[freefempp] 01/03: Recover the branch

Dimitrios Eftaxiopoulos eftaxiop-guest at moszumanska.debian.org
Sun Mar 8 01:19:07 UTC 2015


This is an automated email from the git hooks/post-receive script.

eftaxiop-guest pushed a commit to branch experimental
in repository freefempp.

commit e5ed43cb262bc58ff0df7adbc195a6221f89b17e
Author: Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>
Date:   Sun Mar 8 01:32:47 2015 +0200

    Recover the branch
---
 ._TODO                                             |   Bin 0 -> 171 bytes
 ._ax_lib_hdf5.m4                                   |   Bin 0 -> 507 bytes
 .gitignore                                         |   109 +
 0ldUserReadMe.txt                                  |    34 +
 AUTHORS                                            |     4 +
 BUGS                                               |    88 +
 COPYING                                            |    28 +
 COPYRIGHT                                          |   362 +
 ChangeLog                                          |   646 +
 CheckAll                                           |    21 +
 CheckAllEdp                                        |    69 +
 DOC/._freefem++doc.pdf                             |   Bin 0 -> 177 bytes
 DOC/Makefile.am                                    |    44 +
 FreeFem++-CoCoa                                    |    61 +
 FreeFem++.mcp                                      |   Bin 0 -> 162201 bytes
 HISTORY                                            | 16172 +++++++++++++++++++
 HISTORY_BEFORE_2005                                |   638 +
 INNOVATION                                         |  1214 ++
 INSTALL-MacOSX                                     |    38 +
 Install-MacOS.command.in                           |    50 +
 Makefile.am                                        |   261 +
 NEWS                                               |     0
 README                                             |   439 +
 README_ARPACK                                      |    24 +
 README_MAC                                         |   103 +
 README_WINDOWS                                     |   136 +
 TODO                                               |    35 +
 WHERE_LIBRARY-mkl                                  |     9 +
 WindowsPackage.m4                                  |   155 +
 acmacros.m4                                        |    39 +
 acmpi.m4                                           |   331 +
 acoptim.m4                                         |   255 +
 ax_lib_gsl.m4                                      |   162 +
 ax_lib_hdf5.m4                                     |   309 +
 build/cleancrlf                                    |    54 +
 build/download                                     |    78 +
 build/links2files                                  |    73 +
 build/orgindex                                     |   142 +
 config-wrapper.h                                   |    18 +
 configure.ac                                       |  1984 +++
 copysharedlibs.sh                                  |    24 +
 crimson-freefem++.zip                              |   Bin 0 -> 2054 bytes
 debian/FreeFem++-glx.1                             |    64 +
 debian/FreeFem++-mpi.1                             |    54 +
 debian/FreeFem++-nw.1                              |    54 +
 debian/FreeFem++-x11.1                             |    64 +
 debian/FreeFem++.1                                 |    64 +
 debian/README.Debian                               |    36 +
 debian/changelog                                   |   190 +
 debian/compat                                      |     1 +
 debian/control                                     |   119 +
 debian/copyright                                   |    93 +
 debian/cvmsh2.1                                    |    66 +
 debian/docs                                        |     7 +
 debian/drawbdmesh.1                                |    61 +
 debian/ff-c++.1                                    |    65 +
 debian/ff-get-dep.1                                |    45 +
 debian/ff-mpirun.1                                 |    58 +
 debian/ff-pkg-download.1                           |    35 +
 debian/ffbamg.1                                    |    58 +
 debian/ffglut.1                                    |    58 +
 debian/ffmedit.1                                   |    58 +
 debian/folder/freefem++-doc                        |    10 +
 debian/freefem++-doc.docs                          |     1 +
 debian/freefem++-doc.install                       |     6 +
 debian/freefem++.install                           |     1 +
 debian/freefem++.manpages                          |    14 +
 debian/libfreefem++-dev.install                    |     3 +
 debian/libfreefem++.install                        |     3 +
 debian/patches/configure.patch                     |    25 +
 debian/patches/examples++-load.patch               |    25 +
 debian/patches/examples-bamg.patch                 |     9 +
 debian/patches/series                              |     3 +
 debian/rules                                       |   107 +
 debian/source/format                               |     1 +
 debian/source/options                              |     1 +
 debian/watch                                       |     4 +
 download/AUTHORS                                   |    10 +
 download/Makefile.am                               |   191 +
 download/arpack/ARmake.m4                          |   140 +
 download/arpack/Makefile.am                        |   101 +
 download/arpack/arpack-patch-lapack.tar.gz         |   Bin 0 -> 1156 bytes
 download/arpack/veclib_zdotc.f                     |    36 +
 download/blacs/BLACS.patch                         |    35 +
 .../blacs/BLACS_gridinit_.c-return-values.patch    |    12 +
 download/blacs/Bmake-blacs.inc                     |   236 +
 download/blacs/Makefile                            |    93 +
 download/blas/Makefile.am                          |   188 +
 download/blas/openblas.patches                     |    30 +
 download/blas/opendownload.done                    |     0
 download/common.mak                                |    55 +
 download/f2c/Makefile                              |   112 +
 download/f2c/Makefile-MacOs                        |   229 +
 download/f2c/f2c.h-int                             |   225 +
 download/f2c/fort77.sed                            |   374 +
 download/f2c/tt.f                                  |     3 +
 download/fftw/Makefile.am                          |    43 +
 download/getall                                    |   217 +
 download/gmm/Makefile                              |    61 +
 download/gmm/cxxflags                              |    17 +
 download/headers-sparsesolver.inc                  |   113 +
 download/hips/Makefile                             |   210 +
 download/hips/SRC_SPKIT_makefile                   |    36 +
 download/hips/hips-1.2b-rc4.patch                  |   159 +
 download/hips/makefile-hips.inc                    |   104 +
 download/hypre/Makefile                            |    84 +
 download/hypre/ff-flags.inc                        |    29 +
 download/ipopt/Makefile                            |    85 +
 download/ipopt/Makefile.inc.in                     |    16 +
 download/ipopt/patch-IpBlas                        |   131 +
 download/metis/Makefile                            |    93 +
 download/metis/Makefile-metis.in                   |    24 +
 download/metis/metis-4.0_main_return.patch         |   176 +
 download/metis/patch-metis                         |    11 +
 download/mmg3d/Makefile                            |   113 +
 download/mmg3d/patch-mmg3dv4.diff                  |  3463 ++++
 download/mshmet/Makefile                           |    91 +
 download/mshmet/Makefile-mshmet.inc                |    44 +
 download/mshmet/mshmet.2011.03.06.patch            |    63 +
 download/mshmet/mshmet.2012.04.25_i586.patch       |    11 +
 download/mshmet/mshmetlib-internal.h               |    14 +
 download/mshmet/mshmetlib.c                        |   303 +
 download/mshmet/mshmetlib.h                        |    92 +
 download/mumps-seq/Makefile                        |    89 +
 download/mumps-seq/Makefile-mumps-4.10.0.inc       |   171 +
 download/mumps/MUMPS_4.10.0.patch                  |    31 +
 download/mumps/Makefile                            |    95 +
 download/mumps/Makefile-mumps-4.10.0.inc           |   170 +
 download/nlopt/Make.inc                            |     6 +
 download/nlopt/Makefile                            |    48 +
 download/parmetis/Makefile-parmetis.in             |    25 +
 download/parmetis/makefile                         |    90 +
 download/parmetis/parmetis-3.1.1.patch             |    21 +
 download/parms/Makefile                            |    67 +
 download/parms/makefile-parms.in                   |    58 +
 download/pastix/Makefile                           |   188 +
 download/pastix/all_macros.diff                    |    26 +
 download/pastix/config-pastix-complex.in           |   185 +
 download/pastix/config-pastix-real.in              |   187 +
 download/pastix/pastix_release_2200-blend.patch    |    13 +
 download/pastix/patch-pastix_long_complex.h        |    28 +
 download/scalapack/Makefile                        |    79 +
 download/scalapack/SLmake-scalapack.inc            |    66 +
 download/scotch/Makefile                           |   106 +
 download/scotch/Makefile-scotch.inc                |    32 +
 download/scotch/Makefile.patch                     |    13 +
 download/scotch/scotch_5.1_esmumps.patch           |   217 +
 download/superlu/Makefile                          |   135 +
 download/superlu/make.inc                          |    44 +
 download/superludist/Makefile                      |    77 +
 download/superludist/make-superlu.inc              |    41 +
 download/superludist/superludist_2.3.patch         |    32 +
 .../superludist/superludist_3.0-cast_warning.patch |    25 +
 .../superludist_3.0-operation_undefined.patch      |    24 +
 download/superludist/superludist_3.0-printf.patch  |    10 +
 .../superludist_3.0-return_values.patch            |   158 +
 download/tetgen/Makefile                           |    79 +
 download/tetgen/patches.win64                      |   104 +
 download/tetgen/tetgen1.4.2.patch                  |    41 +
 download/umfpack/Makefile.am                       |   175 +
 download/umfpack/SuiteSparse_config.mk.in          |   396 +
 download/yams/Makefile                             |   108 +
 .../yams/freeyams.2012.02.05-return-values.patch   |    11 +
 download/yams/freeyams.2012.02.05.patch            |   353 +
 download/yams/makefile-yams.inc                    |    46 +
 download/yams/yamslib.c                            |   598 +
 download/yams/yamslib.h                            |   197 +
 download/yams/yamslib_internal.h                   |    41 +
 edp.nedit                                          |    21 +
 examples++-3d/._MeshSurface.idp                    |   Bin 0 -> 171 bytes
 examples++-3d/3d-Leman.edp                         |    51 +
 examples++-3d/ArrayFE-3d.edp                       |     5 +
 examples++-3d/EqPoisson.edp                        |    21 +
 examples++-3d/Lac.edp                              |    20 +
 examples++-3d/Laplace-Adapt-3d.edp                 |    35 +
 examples++-3d/Laplace-Adapt-aniso-3d.edp           |    89 +
 examples++-3d/Laplace3d.edp                        |    63 +
 examples++-3d/LaplaceRT-3d.edp                     |   154 +
 examples++-3d/Makefile.am                          |    46 +
 examples++-3d/MeshSurface.idp                      |   112 +
 examples++-3d/NSI3d-carac.edp                      |   107 +
 examples++-3d/NSI3d.edp                            |   105 +
 examples++-3d/Period-Poisson-cube-ballon.edp       |    64 +
 examples++-3d/Poisson-cube-ballon.edp              |   134 +
 examples++-3d/Poisson.edp                          |    48 +
 examples++-3d/Poisson3d.edp                        |    74 +
 examples++-3d/Stokes.edp                           |    44 +
 examples++-3d/TruncLac.edp                         |    27 +
 examples++-3d/beam-3d.edp                          |    37 +
 examples++-3d/cone.edp                             |    27 +
 examples++-3d/convect-3d.edp                       |    37 +
 examples++-3d/cube-period.edp                      |    78 +
 examples++-3d/cube.idp                             |    39 +
 examples++-3d/cylinder-3d.edp                      |    20 +
 examples++-3d/cylinder.edp                         |    33 +
 examples++-3d/dodecaedre01.mesh                    |  1346 ++
 examples++-3d/fallingspheres.edp                   |    49 +
 examples++-3d/first.edp                            |   128 +
 examples++-3d/intlevelset3d.edp                    |    88 +
 examples++-3d/lac-leman-v4.msh                     |  2177 +++
 examples++-3d/meditddm.edp                         |    50 +
 examples++-3d/p.edp                                |    36 +
 examples++-3d/periodic-3d.edp                      |    43 +
 examples++-3d/pyramide.edp                         |    29 +
 examples++-3d/ref.edp                              |     1 +
 examples++-3d/refinesphere.edp                     |    59 +
 examples++-3d/regtests.edp                         |    50 +
 examples++-3d/regtests.m4                          |    13 +
 examples++-3d/schwarz-nm-3d.edp                    |   176 +
 examples++-3d/sphere2.edp                          |    29 +
 examples++-3d/sphere6.edp                          |    33 +
 examples++-3d/tetgencube.edp                       |    79 +
 examples++-3d/tetgenholeregion.edp                 |    95 +
 examples++-bug/FE0.edp                             |    25 +
 examples++-bug/Makefile.am                         |     3 +
 examples++-bug/SegmentationFault.edp               |    89 +
 examples++-bug/aaa.edp                             |   108 +
 examples++-bug/bug-arg-string.edp                  |    31 +
 examples++-bug/bugborder.edp                       |    40 +
 examples++-bug/bugf.edp                            |    14 +
 examples++-bug/bugifexp.edp                        |     4 +
 examples++-bug/bugv1.18.edp                        |     8 +
 examples++-bug/fe-vect.edp                         |    15 +
 examples++-bug/func.edp                            |    10 +
 examples++-bug/zArithmetic_bug1.edp                |    39 +
 examples++-chapt3/BlackScholes2D.edp               |    29 +
 examples++-chapt3/Makefile.am                      |    35 +
 examples++-chapt3/NSNewton.edp                     |    88 +
 examples++-chapt3/NSprojection-Opt.edp             |   148 +
 examples++-chapt3/NSprojection.edp                 |    87 +
 examples++-chapt3/all.edp                          |    73 +
 examples++-chapt3/condensor.edp                    |    34 +
 examples++-chapt3/convects.edp                     |    52 +
 examples++-chapt3/heatex.edp                       |    24 +
 examples++-chapt3/lame.edp                         |    30 +
 examples++-chapt3/membrane.edp                     |    28 +
 examples++-chapt3/membranerror.edp                 |    29 +
 examples++-chapt3/muwave.edp                       |    34 +
 examples++-chapt3/optimcontrol.edp                 |    48 +
 examples++-chapt3/potential.edp                    |    32 +
 examples++-chapt3/ref.edp                          |     0
 examples++-chapt3/regtests.edp                     |    37 +
 examples++-chapt3/regtests.m4                      |    12 +
 examples++-chapt3/schwarz.edp                      |    26 +
 examples++-chapt3/sound.edp                        |    45 +
 examples++-chapt3/stokes.edp                       |    12 +
 examples++-chapt3/test1.edp                        |    28 +
 examples++-chapt3/testbed.edp                      |    19 +
 examples++-chapt3/thermal.edp                      |    24 +
 examples++-chapt3/thermic.edp                      |    44 +
 examples++-eigen/._BeamEigenValue.edp              |   Bin 0 -> 171 bytes
 examples++-eigen/._free-cyl-axi.edp                |   Bin 0 -> 171 bytes
 examples++-eigen/BeamEigenValue.edp                |    72 +
 examples++-eigen/BeamEigenValueperio.edp           |    72 +
 examples++-eigen/Lap3dEigenValue.edp               |    85 +
 examples++-eigen/LapComplexEigenValue.edp          |    62 +
 examples++-eigen/LapEigenValue.edp                 |    67 +
 examples++-eigen/LapEigenValueFunc.edp             |    70 +
 examples++-eigen/LapnosymEigenValue.edp            |    77 +
 examples++-eigen/Makefile.am                       |    24 +
 examples++-eigen/Stokes-eigen.edp                  |    53 +
 examples++-eigen/VP-Steklov-Poincare.edp           |    22 +
 examples++-eigen/WGM-sphere.edp                    |   111 +
 examples++-eigen/all.edp                           |    49 +
 examples++-eigen/free-cyl-axi.edp                  |    89 +
 examples++-eigen/neuman.edp                        |    30 +
 examples++-eigen/regtests.edp                      |    21 +
 examples++-load/._bilapP3-hct-like.edp             |   Bin 0 -> 171 bytes
 examples++-load/._ffrandom.edp                     |   Bin 0 -> 171 bytes
 examples++-load/._iohd5-beam-2d.edp                |   Bin 0 -> 174 bytes
 examples++-load/._iohd5-beam-3d.edp                |   Bin 0 -> 174 bytes
 examples++-load/._msh3.hpp                         |   Bin 0 -> 171 bytes
 examples++-load/._testFE-PkEdge.edp                |   Bin 0 -> 171 bytes
 examples++-load/APk-AdaptEpsDeltaPk.edp            |    43 +
 examples++-load/APk-ExplicitPkTest.edp             |    22 +
 examples++-load/APk-FreeFemQA.edp                  |    28 +
 examples++-load/APk-MetricPk.edp                   |    31 +
 examples++-load/BEC.cpp                            |    34 +
 examples++-load/BasicMath.h                        |   113 +
 examples++-load/BernadiRaugel.cpp                  |   275 +
 examples++-load/BinaryIO.cpp                       |    89 +
 examples++-load/DxWriter.cpp                       |   351 +
 examples++-load/Element_Mixte.cpp                  |  1111 ++
 examples++-load/Element_P1dc1.cpp                  |   449 +
 examples++-load/Element_P3.cpp                     |   199 +
 examples++-load/Element_P3.hpp                     |    28 +
 examples++-load/Element_P3dc.cpp                   |   207 +
 examples++-load/Element_P3dc.hpp                   |    28 +
 examples++-load/Element_P4.cpp                     |   214 +
 examples++-load/Element_P4.hpp                     |    38 +
 examples++-load/Element_P4dc.cpp                   |   213 +
 examples++-load/Element_P4dc.hpp                   |    38 +
 examples++-load/Element_PkEdge.cpp                 |   183 +
 examples++-load/ExampleMetrics.h                   |   117 +
 examples++-load/FreeFemQA.cpp                      |   188 +
 examples++-load/Geometry.hpp                       |   232 +
 examples++-load/GeometryQA.cpp                     |   654 +
 examples++-load/IPOTest.edp                        |    95 +
 examples++-load/IpOptMinSurf.edp                   |    47 +
 examples++-load/IpoptLap.edp                       |   138 +
 examples++-load/IpoptMinSurfVol.edp                |   254 +
 examples++-load/IpoptVI.edp                        |    31 +
 examples++-load/IpoptVI2.edp                       |    57 +
 examples++-load/LapDG3.edp                         |    56 +
 examples++-load/LapDG4.edp                         |    52 +
 examples++-load/LapLNewSolver.edp                  |    19 +
 examples++-load/LapMUMPS_seq.edp                   |    19 +
 examples++-load/LapNewSolver.edp                   |    16 +
 examples++-load/LapUmfpack64.edp                   |    19 +
 examples++-load/LaplaceP3.edp                      |    15 +
 examples++-load/LaplaceP4.edp                      |    53 +
 examples++-load/LaplaceRT1.edp                     |    42 +
 examples++-load/Leman-mesh.edp                     |    35 +
 examples++-load/MUMPS.cpp                          |   314 +
 examples++-load/MUMPS_seq.cpp                      |   314 +
 examples++-load/Makefile.am                        |   243 +
 examples++-load/MetricKuate.cpp                    |   670 +
 examples++-load/MetricKuate.edp                    |    73 +
 examples++-load/MetricPk.cpp                       |   412 +
 examples++-load/Morley.cpp                         |   297 +
 examples++-load/NSP2BRP0.edp                       |    83 +
 examples++-load/NewSolver.cpp                      |   343 +
 examples++-load/PARDISO.cpp                        |   233 +
 examples++-load/PARDISO.edp                        |    30 +
 examples++-load/README                             |    91 +
 examples++-load/README_SuperLU                     |    33 +
 examples++-load/RZ.h                               |   546 +
 examples++-load/SortedList.h                       |   678 +
 examples++-load/SuperLU.edp                        |    71 +
 examples++-load/SuperLu.cpp                        |   778 +
 examples++-load/TensorK.hpp                        |   581 +
 examples++-load/UMFPACK64.cpp                      |   398 +
 examples++-load/VTK_writer.cpp                     |   340 +
 examples++-load/VTK_writer_3d.cpp                  |   368 +
 examples++-load/VarIneq2.edp                       |   172 +
 examples++-load/addNewType.cpp                     |    81 +
 examples++-load/bfstream.cpp                       |    85 +
 examples++-load/bfstream.edp                       |    24 +
 examples++-load/bilapMorley.edp                    |    36 +
 examples++-load/bilapP3-hct-like.edp               |    44 +
 examples++-load/bmo.cpp                            |   576 +
 examples++-load/bmo.edp                            |    37 +
 examples++-load/bmo.hpp                            |   103 +
 examples++-load/buildlayermesh.edp                 |    57 +
 examples++-load/ch.pts                             |   161 +
 examples++-load/checkglumeshcube.edp               |    84 +
 examples++-load/clapack.h                          |  7262 +++++++++
 examples++-load/cmaes-VarIneq.edp                  |   123 +
 examples++-load/cmaes-oven.edp                     |   166 +
 examples++-load/cmaes.cpp                          |  2939 ++++
 examples++-load/cmaes.h                            |   172 +
 examples++-load/cmaes_interface.h                  |    56 +
 examples++-load/convect_dervieux.edp               |    43 +
 examples++-load/convectchacon-3d.edp               |    36 +
 examples++-load/convectchacon.edp                  |    32 +
 examples++-load/convexehull3d.edp                  |     4 +
 examples++-load/cube.msh                           |   585 +
 examples++-load/dfft.cpp                           |   270 +
 examples++-load/dfft.edp                           |    67 +
 examples++-load/dmatrix.hpp                        |    88 +
 examples++-load/ff-Ipopt.cpp                       |  1747 ++
 examples++-load/ff-NLopt.cpp                       |   878 +
 examples++-load/ff-cmaes.cpp                       |   308 +
 examples++-load/ff-get-dep.awk                     |    36 +
 examples++-load/ff-get-dep.in                      |    38 +
 examples++-load/ff-pkg-download.in                 |    95 +
 examples++-load/ff_gsl_awk.hpp                     |   914 ++
 examples++-load/fflapack.cpp                       |   970 ++
 examples++-load/ffnewuoa.cpp                       |   193 +
 examples++-load/ffnewuoa.edp                       |   105 +
 examples++-load/ffrandom.cpp                       |   104 +
 examples++-load/ffrandom.edp                       |    15 +
 examples++-load/fig.pgm                            |   150 +
 examples++-load/freeyams.cpp                       |   831 +
 examples++-load/funcTemplate.cpp                   |   131 +
 examples++-load/funcTemplate.edp                   |    51 +
 examples++-load/glumesh3D.edp                      |    54 +
 examples++-load/gmsh.cpp                           |   841 +
 examples++-load/gsl.awk                            |   161 +
 examples++-load/gsl.cpp                            |   256 +
 examples++-load/gsl.edp                            |    23 +
 examples++-load/gsl.idp                            |   331 +
 examples++-load/ilut.cpp                           |   152 +
 examples++-load/ilut.edp                           |    44 +
 examples++-load/include.tar.gz                     |   Bin 0 -> 2316 bytes
 examples++-load/iohd5-beam-2d.edp                  |    40 +
 examples++-load/iohd5-beam-3d.edp                  |    42 +
 examples++-load/iohdf5.cpp                         |   734 +
 examples++-load/iovtk.cpp                          |  4036 +++++
 examples++-load/isoline.cpp                        |   837 +
 examples++-load/isoline.edp                        |    64 +
 examples++-load/isolineP1.cpp                      |   895 +
 examples++-load/lame-TD-NSS.edp                    |    87 +
 examples++-load/lap-solvers.edp                    |    29 +
 examples++-load/lapack.cpp                         |   970 ++
 examples++-load/lapack.edp                         |   122 +
 examples++-load/layer.edp                          |     5 +
 examples++-load/lg.pgm                             |     4 +
 examples++-load/lgbmo.cpp                          |   327 +
 examples++-load/load.edp                           |    13 +
 examples++-load/load.link.in                       |   292 +
 examples++-load/mat_dervieux.cpp                   |   159 +
 examples++-load/mat_psi.cpp                        |   271 +
 examples++-load/medit.cpp                          |  2427 +++
 examples++-load/meditddm.edp                       |    50 +
 examples++-load/metis.cpp                          |   133 +
 examples++-load/metis.edp                          |    15 +
 examples++-load/mmg3d-v4.0.cpp                     |   440 +
 examples++-load/msh3.cpp                           |  5875 +++++++
 examples++-load/msh3.hpp                           |   106 +
 examples++-load/mshmet.cpp                         |   757 +
 examples++-load/mshmet.edp                         |     1 +
 examples++-load/myType.edp                         |     6 +
 examples++-load/myfunction.cpp                     |    62 +
 examples++-load/myfunction2.cpp                    |    21 +
 examples++-load/myfunction2.edp                    |     9 +
 examples++-load/newuoa.f                           |  1455 ++
 examples++-load/pcm.cpp                            |   244 +
 examples++-load/pcm.hpp                            |    44 +
 examples++-load/pcm2rnm.cpp                        |   121 +
 examples++-load/pipe.cpp                           |   203 +
 examples++-load/pipe.edp                           |    35 +
 examples++-load/plot-fb-P3.edp                     |    44 +
 examples++-load/plot-fb-P3dc.edp                   |    45 +
 examples++-load/plot-fb-P4.edp                     |    37 +
 examples++-load/plot-fb-P4dc.edp                   |    46 +
 examples++-load/plotfb.edp                         |    34 +
 examples++-load/ppm2rnm.cpp                        |   326 +
 examples++-load/ppm2rnm.edp                        |    12 +
 examples++-load/ppmimg.h                           |    27 +
 examples++-load/provadxw.edp                       |    14 +
 examples++-load/pstream.h                          |  2199 +++
 examples++-load/qf11to25.cpp                       |   864 +
 examples++-load/ref.edp                            |     1 +
 examples++-load/refinesphere.edp                   |    56 +
 examples++-load/regtests.m4                        |    30 +
 examples++-load/schwarz-nm.edp                     |   173 +
 examples++-load/scotch.cpp                         |   152 +
 examples++-load/scotch.edp                         |    45 +
 examples++-load/shell.cpp                          |   144 +
 examples++-load/shell.edp                          |    15 +
 examples++-load/splitedges.cpp                     |   248 +
 examples++-load/splitedges.edp                     |    10 +
 examples++-load/splitmesh3.cpp                     |   115 +
 examples++-load/splitmesh3.edp                     |     4 +
 examples++-load/splitmesh6.cpp                     |   162 +
 examples++-load/splitmesh6.edp                     |    36 +
 examples++-load/symmetrizeCSR.cpp                  |    80 +
 examples++-load/test-ElementMixte.edp              |   225 +
 examples++-load/testFE-P3.edp                      |    61 +
 examples++-load/testFE-P3dc.edp                    |    61 +
 examples++-load/testFE-P4.edp                      |    61 +
 examples++-load/testFE-P4dc.edp                    |    61 +
 examples++-load/testFE-PkEdge.edp                  |    65 +
 examples++-load/testFE.edp                         |    42 +
 examples++-load/testFEMorley.edp                   |    99 +
 examples++-load/tetgen.cpp                         |  2536 +++
 examples++-load/tetgencube.edp                     |    82 +
 examples++-load/tetgenholeregion_rugby.edp         |    88 +
 examples++-load/thresholdings.cpp                  |    91 +
 examples++-load/thresholdings.edp                  |    14 +
 examples++-load/ttestio.edp                        |    43 +
 examples++-mpi/._DDM-NSUzawaCahouetChabart.edp     |   Bin 0 -> 171 bytes
 examples++-mpi/._MUMPS_FreeFem.cpp                 |   Bin 0 -> 171 bytes
 examples++-mpi/._PETSc.hpp                         |   Bin 0 -> 261 bytes
 examples++-mpi/._additional.idp                    |   Bin 0 -> 174 bytes
 examples++-mpi/._complex_SuperLU_DIST_FreeFem.cpp  |   Bin 0 -> 171 bytes
 examples++-mpi/._complex_pastix_FreeFem.cpp        |   Bin 0 -> 167 bytes
 examples++-mpi/._dSuperLU_DIST.cpp                 |   Bin 0 -> 171 bytes
 examples++-mpi/._real_SuperLU_DIST_FreeFem.cpp     |   Bin 0 -> 171 bytes
 examples++-mpi/._removeDOF.cpp                     |   Bin 0 -> 171 bytes
 examples++-mpi/._schwarz.cpp                       |   Bin 0 -> 171 bytes
 examples++-mpi/._schwarz.edp                       |   Bin 0 -> 174 bytes
 examples++-mpi/._stokes-2d.edp                     |   Bin 0 -> 174 bytes
 examples++-mpi/AddLayer2d.idp                      |    62 +
 examples++-mpi/AddLayer3d.idp                      |    62 +
 examples++-mpi/DDM-NSUzawaCahouetChabart.edp       |   120 +
 examples++-mpi/DDM-Schwarz-Lame-2d.edp             |   151 +
 examples++-mpi/DDM-Schwarz-Lame-3d.edp             |   161 +
 examples++-mpi/DDM-Schwarz-Lap-2dd.edp             |   131 +
 examples++-mpi/DDM-Schwarz-Lap-3d.edp              |   136 +
 examples++-mpi/DDM-Schwarz-Stokes-2d.edp           |   168 +
 examples++-mpi/DDM-Schwarz-macro.idp               |   396 +
 examples++-mpi/DDM-funcs-v2.idp                    |   261 +
 examples++-mpi/Heat3d.idp                          |   104 +
 examples++-mpi/Laplace3d-hips.edp                  |   101 +
 examples++-mpi/Laplace3d-hypre.edp                 |   100 +
 examples++-mpi/LaplaceRT-3d-matrix-mumps.edp       |   209 +
 examples++-mpi/LaplaceRT-3d-matrix-pastix.edp      |   199 +
 examples++-mpi/LaplaceRT-3d-matrix-superludist.edp |   207 +
 examples++-mpi/MPICG.cpp                           |   501 +
 examples++-mpi/MPICGLap.edp                        |   182 +
 examples++-mpi/MPIGMRES2D.edp                      |   468 +
 examples++-mpi/MPIGMRES3D.edp                      |   473 +
 examples++-mpi/MPIGMRESmacro.idp                   |   109 +
 examples++-mpi/MPIplot.idp                         |    36 +
 examples++-mpi/MUMPS-dist.edp                      |    40 +
 examples++-mpi/MUMPS-old.edp                       |    44 +
 examples++-mpi/MUMPS.cpp                           |   318 +
 examples++-mpi/MUMPS.edp                           |    60 +
 examples++-mpi/MUMPS_FreeFem.cpp                   |  2605 +++
 examples++-mpi/Makefile.am                         |   112 +
 examples++-mpi/NSI3d-carac-mumps.edp               |   154 +
 examples++-mpi/NSI3d-carac-pastix.edp              |   154 +
 examples++-mpi/NSI3d-carac-superludist.edp         |   154 +
 examples++-mpi/NSI3d-carac.edp                     |     1 +
 examples++-mpi/PETSc.hpp                           |   427 +
 examples++-mpi/Stokes-v1-matrix-mumps.edp          |    81 +
 examples++-mpi/Stokes-v1-matrix-pastix.edp         |    69 +
 examples++-mpi/Stokes-v1-matrix-superludist.edp    |    66 +
 examples++-mpi/Stokes-v2-matrix-mumps.edp          |   104 +
 examples++-mpi/Stokes-v2-matrix-pastix.edp         |   104 +
 examples++-mpi/Stokes-v2-matrix-superludist.edp    |   103 +
 examples++-mpi/Stokes-v3-matrix-mumps.edp          |   122 +
 examples++-mpi/Stokes-v3-matrix-pastix.edp         |   119 +
 examples++-mpi/Stokes-v3-matrix-superludist.edp    |   116 +
 examples++-mpi/VG.edp                              |    72 +
 examples++-mpi/additional.idp                      |   206 +
 examples++-mpi/beam-3d-matrix-pastix.edp           |    68 +
 examples++-mpi/beam-3d-matrix-superludist.edp      |    73 +
 examples++-mpi/cavityNewtow-MUMPS.edp              |   133 +
 examples++-mpi/chaleur3D-hips.edp                  |     9 +
 examples++-mpi/chaleur3D-hypre.edp                 |    94 +
 examples++-mpi/chaleur3D-mumps.edp                 |     8 +
 examples++-mpi/chaleur3D-pastix.edp                |    91 +
 examples++-mpi/chaleur3D-superludist.edp           |     8 +
 examples++-mpi/cmaes-mpi-VarIneq.edp               |   122 +
 examples++-mpi/complex_SuperLU_DIST_FreeFem.cpp    |   843 +
 examples++-mpi/complex_pastix_FreeFem.cpp          |   686 +
 examples++-mpi/dSuperLU_DIST.cpp                   |   740 +
 examples++-mpi/dmatrix.hpp                         |    88 +
 examples++-mpi/essai-com.edp                       |    38 +
 examples++-mpi/essai.edp                           |   159 +
 examples++-mpi/ffmumps_fileparam.txt               |    57 +
 examples++-mpi/ffpastix_iparm_dparm.txt            |   132 +
 examples++-mpi/ffsuperlu_dist_fileparam.txt        |    16 +
 examples++-mpi/ffsuperludistoption-1.hpp           |   507 +
 examples++-mpi/ffsuperludistoption.hpp             |   548 +
 examples++-mpi/generaldefs.h                       |    82 +
 examples++-mpi/getARGV.idp                         |    90 +
 examples++-mpi/hips_FreeFem.cpp                    |   767 +
 examples++-mpi/hypre_FreeFem.cpp                   |  1761 ++
 examples++-mpi/interfacepastix.cpp                 |   551 +
 examples++-mpi/mortar-DN-4-mpi.edp                 |   230 +
 examples++-mpi/mortar-msh.idp                      |    42 +
 examples++-mpi/mpi-cmaes.cpp                       |   392 +
 examples++-mpi/parms_FreeFem.cpp                   |  1069 ++
 examples++-mpi/real_SuperLU_DIST_FreeFem.cpp       |   813 +
 examples++-mpi/real_pastix_FreeFem.cpp             |   719 +
 examples++-mpi/regtests.sh                         |    30 +
 examples++-mpi/removeDOF.cpp                       |   274 +
 examples++-mpi/schwarz-2d.edp                      |    68 +
 examples++-mpi/schwarz-3.edp                       |    93 +
 examples++-mpi/schwarz-b.edp                       |    71 +
 examples++-mpi/schwarz-c.edp                       |    60 +
 examples++-mpi/schwarz.cpp                         |   445 +
 examples++-mpi/schwarz.edp                         |    62 +
 examples++-mpi/stokes-2d.edp                       |    55 +
 examples++-mpi/testsolver_MUMPS.edp                |    89 +
 examples++-mpi/testsolver_SuperLU_DIST.edp         |   160 +
 examples++-mpi/testsolver_dsuperlu_dist.edp        |    62 +
 examples++-mpi/testsolver_pastix.edp               |   198 +
 examples++-mpi/utility.cpp                         |   426 +
 examples++-other/Makefile.am                       |     5 +
 examples++-other/graphics-benchmark.edp            |   127 +
 examples++-other/lap3-cpu.edp                      |    80 +
 examples++-other/speedtest.sh                      |    26 +
 examples++-tutorial/._NSUzawaCahouetChabart.edp    |   Bin 0 -> 171 bytes
 examples++-tutorial/._cavityNewtow.edp             |   Bin 0 -> 171 bytes
 examples++-tutorial/._schwarz-no-overlap.edp       |   Bin 0 -> 171 bytes
 examples++-tutorial/._string.edp                   |   Bin 0 -> 171 bytes
 .../AdaptResidualErrorIndicator.edp                |   113 +
 examples++-tutorial/BEM-C.edp                      |    95 +
 examples++-tutorial/BEM.edp                        |    86 +
 examples++-tutorial/FE.edp                         |    53 +
 examples++-tutorial/FEComplex.edp                  |    51 +
 examples++-tutorial/LapDG2.edp                     |    53 +
 examples++-tutorial/Laplace-RHS-Dirac.edp          |    38 +
 examples++-tutorial/Laplace-lagrange-mult.edp      |    47 +
 examples++-tutorial/Laplace.cpp                    |    59 +
 examples++-tutorial/Laplace.edp                    |    13 +
 examples++-tutorial/LaplaceP1.edp                  |    15 +
 examples++-tutorial/LaplaceP1P2h.edp               |    28 +
 examples++-tutorial/LaplaceP1bis.edp               |    28 +
 examples++-tutorial/LaplaceRT.edp                  |    41 +
 examples++-tutorial/Makefile.am                    |    47 +
 examples++-tutorial/NS-BackwardStep.edp            |   171 +
 examples++-tutorial/NSUzawaCahouetChabart.edp      |   110 +
 examples++-tutorial/Newton.edp                     |    70 +
 examples++-tutorial/Periodic.edp                   |    16 +
 examples++-tutorial/StokesUzawa.edp                |    46 +
 examples++-tutorial/VI-adap.edp                    |   125 +
 examples++-tutorial/VI.edp                         |    82 +
 examples++-tutorial/a_tutorial.edp                 |    38 +
 examples++-tutorial/adapt.edp                      |    25 +
 examples++-tutorial/adaptindicatorP1.edp           |    50 +
 examples++-tutorial/adaptindicatorP2.edp           |    54 +
 examples++-tutorial/aile.msh                       |   337 +
 examples++-tutorial/algo.edp                       |   179 +
 examples++-tutorial/all.edp                        |   253 +
 examples++-tutorial/array.edp                      |   357 +
 examples++-tutorial/beam.edp                       |    38 +
 examples++-tutorial/calculus.edp                   |    56 +
 examples++-tutorial/cavity.edp                     |    61 +
 examples++-tutorial/cavityNewtow.edp               |   126 +
 examples++-tutorial/convect-apt.edp                |    86 +
 examples++-tutorial/convect.edp                    |    29 +
 examples++-tutorial/convect2.edp                   |    35 +
 examples++-tutorial/dumptable.edp                  |     3 +
 examples++-tutorial/ex-vf.edp                      |    27 +
 examples++-tutorial/exception.edp                  |    35 +
 examples++-tutorial/fluidStruct.edp                |   106 +
 examples++-tutorial/fluidStructAdapt.edp           |   170 +
 examples++-tutorial/freeboundary-weak.edp          |   101 +
 examples++-tutorial/freeboundary.edp               |    76 +
 examples++-tutorial/func.edp                       |    63 +
 examples++-tutorial/glumesh.edp                    |    45 +
 examples++-tutorial/gnuplot.edp                    |    31 +
 examples++-tutorial/intlevelset.edp                |    76 +
 examples++-tutorial/io.edp                         |    50 +
 examples++-tutorial/mat_interpol.edp               |    62 +
 examples++-tutorial/medit.edp                      |    32 +
 examples++-tutorial/mesh.edp                       |   340 +
 examples++-tutorial/mortar-DN-4.edp                |   230 +
 examples++-tutorial/mortar-msh.idp                 |    42 +
 examples++-tutorial/movemesh.edp                   |    27 +
 examples++-tutorial/nl-elast-neo-Hookean.edp       |   588 +
 examples++-tutorial/nolinear-elas.edp              |   143 +
 examples++-tutorial/onde.edp                       |    34 +
 examples++-tutorial/periodic4.edp                  |    34 +
 examples++-tutorial/periodic4bis.edp               |    48 +
 examples++-tutorial/plot.edp                       |    46 +
 examples++-tutorial/readmesh.edp                   |    77 +
 examples++-tutorial/ref.edp                        |    37 +
 examples++-tutorial/region.edp                     |    30 +
 examples++-tutorial/regtests.edp                   |   525 +
 examples++-tutorial/regtests.m4                    |    66 +
 examples++-tutorial/saverestore.edp                |    31 +
 examples++-tutorial/schwarz-gc.edp                 |    68 +
 examples++-tutorial/schwarz-no-overlap.edp         |    41 +
 examples++-tutorial/schwarz-overlap.edp            |    34 +
 examples++-tutorial/shur-comp.edp                  |   164 +
 examples++-tutorial/sparse-cmatrix.edp             |   156 +
 examples++-tutorial/sparse-matrix.edp              |   244 +
 examples++-tutorial/sphere.edp                     |    40 +
 examples++-tutorial/string.edp                     |    70 +
 examples++-tutorial/tablefunction.edp              |    21 +
 examples++-tutorial/taboftab.edp                   |    34 +
 examples++-tutorial/thermic-fast.edp               |    45 +
 examples++-tutorial/uniformmesh.edp                |     9 +
 examples++-tutorial/xyf                            |   100 +
 examples++/._NSP1P2.edp                            |   Bin 0 -> 171 bytes
 examples++/D2.edp                                  |    15 +
 examples++/FE-medit.edp                            |    30 +
 examples++/Makefile.am                             |    35 +
 examples++/NSP1P1.edp                              |    66 +
 examples++/NSP1P1b.edp                             |    76 +
 examples++/NSP1P2.edp                              |    77 +
 examples++/Richard.edp                             |   126 +
 examples++/aaRT.edp                                |    59 +
 examples++/aaa-adp.edp                             |    69 +
 examples++/aadaptation.edp                         |    42 +
 examples++/aalapacien.edp                          |    32 +
 examples++/aalaplace-nc.edp                        |    20 +
 examples++/aamove.edp                              |    30 +
 examples++/all.edp                                 |   105 +
 examples++/arrayoFVh.edp                           |    36 +
 examples++/bilap.edp                               |    24 +
 examples++/ccc-adp.edp                             |    48 +
 examples++/demo.edp                                |    51 +
 examples++/demo1.edp                               |    53 +
 examples++/funct.edp                               |    14 +
 examples++/include.edp                             |     2 +
 examples++/lap_mat.edp                             |    34 +
 examples++/lapacienprecon.edp                      |    42 +
 examples++/makeref.edp                             |   248 +
 examples++/parareal.edp                            |   181 +
 examples++/ref.edp                                 |    20 +
 examples++/regtests.edp                            |   308 +
 examples++/regtests.m4                             |    37 +
 examples++/testFE.edp                              |    48 +
 examples++/testadp.edp                             |    52 +
 examples++/teste.edp                               |   147 +
 examples++/wafer-heating-laser-axi.edp             |   128 +
 examples-bamg/NACA012/ad.sh                        |    91 +
 examples-bamg/NACA012/adap.sh                      |    99 +
 examples-bamg/NACA012/adap.sh-g                    |    89 +
 examples-bamg/NACA012/data                         |    25 +
 examples-bamg/NACA012/data-orign                   |    25 +
 examples-bamg/NACA012/naca.awk                     |    47 +
 examples-bamg/NACA012/plot.fv                      |    62 +
 examples-bamg/quadloop/dotest.pl                   |   175 +
 examples-bamg/square/circle_g.mesh                 |    25 +
 examples-bamg/square/doadapt                       |    35 +
 examples-bamg/square/dotest                        |    45 +
 examples-bamg/square/l_g.mesh                      |   488 +
 examples-bamg/square/octogone_g.mesh               |    25 +
 examples-bamg/square/square_g.mesh                 |    17 +
 examples-bamg/square/square_raf_ani_g.mtr          |     6 +
 examples-bamg/square/square_raf_g.mesh             |    23 +
 examples-bamg/square/square_raf_g.mtr              |     2 +
 examples-bamg/test/dotest.pl                       |   168 +
 freefem++.spec                                     |    98 +
 logo.ico                                           |   Bin 0 -> 3126 bytes
 mode-mi-edp.zip                                    |   Bin 0 -> 20227 bytes
 reconfigure                                        |     7 +
 regtests.m4                                        |    53 +
 regtests.sh                                        |    87 +
 src/Algo/BFGS.hpp                                  |   181 +
 src/Algo/BrentLS.hpp                               |   361 +
 src/Algo/CG.hpp                                    |   215 +
 src/Algo/CubicLS.hpp                               |   178 +
 src/Algo/LineSearch.hpp                            |   259 +
 src/Algo/Makefile.am                               |    10 +
 src/Algo/NRJ.hpp                                   |   107 +
 src/Algo/NewtonRaphson.hpp                         |   115 +
 src/Algo/Optima.hpp                                |   116 +
 src/Algo/Param.hpp                                 |   232 +
 src/Algo/RosenBrock.hpp                            |   120 +
 src/Algo/defs.hpp                                  |   118 +
 src/Algo/lgalgo.cpp                                |   302 +
 src/Carbon.r                                       |    18 +
 src/Eigen/arpackff.hpp                             |   439 +
 src/Eigen/eigenvalue.cpp                           |  1053 ++
 src/FreeFem++-CoCoa                                |    50 +
 src/Graphics/._ffglut.cpp                          |   Bin 0 -> 167 bytes
 src/Graphics/._getprog-unix.hpp                    |   Bin 0 -> 171 bytes
 src/Graphics/DefColor.cpp                          |    96 +
 src/Graphics/Makefile.am                           |    11 +
 src/Graphics/Pcrgraph.cpp                          |  1559 ++
 src/Graphics/Xrgraph.cpp                           |  1209 ++
 src/Graphics/ff-win32.cpp                          |    79 +
 src/Graphics/ffglut.cpp                            |  3006 ++++
 src/Graphics/ffglut.hpp                            |   373 +
 src/Graphics/ffthreads.cpp                         |    92 +
 src/Graphics/ffthreads.hpp                         |    65 +
 src/Graphics/getprog-unix.hpp                      |   274 +
 src/Graphics/gggg.cpp                              |    55 +
 src/Graphics/glrgraph.hpp                          |  1637 ++
 src/Graphics/macglrgraf.cpp                        |    29 +
 src/Graphics/macrgraf.cpp                          |  1180 ++
 src/Graphics/mode_open.hpp                         |    10 +
 src/Graphics/rgraph.hpp                            |   250 +
 src/Graphics/sansrgraph.cpp                        |   720 +
 src/Graphics/xglrgraf.cpp                          |    30 +
 src/Makefile.am                                    |    27 +
 src/bamg/Makefile.am                               |    22 +
 src/bamg/bamg.cpp                                  |   835 +
 src/bamg/cvmsh2.cpp                                |   152 +
 src/bamg/global.cpp                                |     3 +
 src/bamglib/._Mesh2.h                              |   Bin 0 -> 171 bytes
 src/bamglib/._MeshWrite.cpp                        |   Bin 0 -> 167 bytes
 src/bamglib/._Metric.cpp                           |   Bin 0 -> 167 bytes
 src/bamglib/._QuadTree.cpp                         |   Bin 0 -> 167 bytes
 src/bamglib/._meshtype.h                           |   Bin 0 -> 171 bytes
 src/bamglib/._write_hdf5.hpp                       |   Bin 0 -> 174 bytes
 src/bamglib/._write_xdmf.cpp                       |   Bin 0 -> 174 bytes
 src/bamglib/._write_xdmf.hpp                       |   Bin 0 -> 174 bytes
 src/bamglib/Makefile.am                            |    11 +
 src/bamglib/Mesh2.cpp                              |  5197 ++++++
 src/bamglib/Mesh2.h                                |  1509 ++
 src/bamglib/MeshDraw.cpp                           |   808 +
 src/bamglib/MeshGeom.cpp                           |  1218 ++
 src/bamglib/MeshQuad.cpp                           |   943 ++
 src/bamglib/MeshRead.cpp                           |  1227 ++
 src/bamglib/MeshWrite.cpp                          |  1021 ++
 src/bamglib/Meshgibbs.cpp                          |  1063 ++
 src/bamglib/Meshio.cpp                             |   373 +
 src/bamglib/Meshio.h                               |   245 +
 src/bamglib/Metric.cpp                             |  1213 ++
 src/bamglib/Metric.h                               |   225 +
 src/bamglib/QuadTree.cpp                           |   542 +
 src/bamglib/QuadTree.h                             |   111 +
 src/bamglib/R2.cpp                                 |    31 +
 src/bamglib/R2.h                                   |   135 +
 src/bamglib/SetOfE4.cpp                            |    84 +
 src/bamglib/SetOfE4.h                              |    64 +
 src/bamglib/meshtype.h                             |    71 +
 src/bamglib/write_hdf5.cpp                         |   506 +
 src/bamglib/write_hdf5.hpp                         |    57 +
 src/bamglib/write_xdmf.cpp                         |   265 +
 src/bamglib/write_xdmf.hpp                         |    41 +
 src/bin-win32/Makefile.am                          |    78 +
 src/bin-win32/launchff++.cpp                       |    59 +
 src/femlib/._CGNL.hpp                              |   Bin 0 -> 171 bytes
 src/femlib/._Drawing.cpp                           |   Bin 0 -> 167 bytes
 src/femlib/._Mesh3dn.cpp                           |   Bin 0 -> 170 bytes
 src/femlib/._QuadratureFormular.hpp                |   Bin 0 -> 171 bytes
 src/femlib/._R1.hpp                                |   Bin 0 -> 171 bytes
 src/femlib/._R2.hpp                                |   Bin 0 -> 171 bytes
 src/femlib/._R3.hpp                                |   Bin 0 -> 171 bytes
 src/femlib/._RNM_op.hpp                            |   Bin 0 -> 171 bytes
 src/femlib/._gmres.hpp                             |   Bin 0 -> 171 bytes
 src/femlib/BamgFreeFem.cpp                         |   967 ++
 src/femlib/BamgFreeFem.hpp                         |    55 +
 src/femlib/CGNL.hpp                                |   114 +
 src/femlib/CheckPtr.cpp                            |   516 +
 src/femlib/ConjuguedGradrientNL.cpp                |   116 +
 src/femlib/DOperator.hpp                           |   560 +
 src/femlib/Drawing.cpp                             |   788 +
 src/femlib/Element_P2h.cpp                         |   134 +
 src/femlib/Element_RT.cpp                          |   831 +
 src/femlib/FESpace-v0.cpp                          |  1723 ++
 src/femlib/FESpace.cpp                             |  2030 +++
 src/femlib/FESpace.hpp                             |   883 +
 src/femlib/FESpacen.cpp                            |   624 +
 src/femlib/FESpacen.hpp                            |   811 +
 src/femlib/FQuadTree.cpp                           |  1125 ++
 src/femlib/FQuadTree.hpp                           |   155 +
 src/femlib/GQuadTree.cpp                           |   854 +
 src/femlib/GQuadTree.hpp                           |   234 +
 src/femlib/GenericMesh.hpp                         |  1578 ++
 src/femlib/HashTable.hpp                           |   159 +
 src/femlib/HeapSort.hpp                            |    56 +
 src/femlib/InvIntFunc.cpp                          |    59 +
 src/femlib/Label.hpp                               |    19 +
 src/femlib/Makefile.am                             |    38 +
 src/femlib/MatriceCreuse.hpp                       |  1039 ++
 src/femlib/MatriceCreuse_tpl.hpp                   |  1947 +++
 src/femlib/Mesh1dn.cpp                             |   125 +
 src/femlib/Mesh1dn.hpp                             |   126 +
 src/femlib/Mesh2dn.cpp                             |   455 +
 src/femlib/Mesh2dn.hpp                             |   147 +
 src/femlib/Mesh3dn.cpp                             |  1414 ++
 src/femlib/Mesh3dn.hpp                             |   188 +
 src/femlib/MeshPoint.hpp                           |   464 +
 src/femlib/P012_1d.cpp                             |   236 +
 src/femlib/P012_2d.cpp                             |   256 +
 src/femlib/P012_3d.cpp                             |   855 +
 src/femlib/PkLagrange.hpp                          |   132 +
 src/femlib/QuadratureFormular.cpp                  |   751 +
 src/femlib/QuadratureFormular.hpp                  |   213 +
 src/femlib/R1.hpp                                  |   117 +
 src/femlib/R2.hpp                                  |   127 +
 src/femlib/R3.hpp                                  |   136 +
 src/femlib/RNM.hpp                                 |  1601 ++
 src/femlib/RNM_op.hpp                              |   175 +
 src/femlib/RNM_opc.hpp                             |   111 +
 src/femlib/RNM_tpl.hpp                             |   344 +
 src/femlib/RefCounter.hpp                          |   117 +
 src/femlib/assertion.hpp                           |    14 +
 src/femlib/fem.cpp                                 |  2083 +++
 src/femlib/fem.hpp                                 |   708 +
 src/femlib/fem3.hpp                                |     1 +
 src/femlib/gibbs.cpp                               |  1253 ++
 src/femlib/glutdraw.cpp                            |   518 +
 src/femlib/gmres.hpp                               |   183 +
 src/femlib/libmesh5.c                              |  1224 ++
 src/femlib/libmesh5.h                              |   178 +
 src/femlib/mortar.cpp                              |   281 +
 src/femlib/mshptg.cpp                              |  2238 +++
 src/femlib/splitsimplex.cpp                        |   471 +
 src/femlib/splitsimplex.hpp                        |     4 +
 src/femlib/ufunction.hpp                           |   104 +
 src/fflib/._AFunction.hpp                          |   Bin 0 -> 167 bytes
 src/fflib/._AFunction2.cpp                         |   Bin 0 -> 170 bytes
 src/fflib/._array_tlp.hpp                          |   Bin 0 -> 171 bytes
 src/fflib/._ffapi.cpp                              |   Bin 0 -> 171 bytes
 src/fflib/._ffapi.hpp                              |   Bin 0 -> 171 bytes
 src/fflib/._lgfem.cpp                              |   Bin 0 -> 170 bytes
 src/fflib/._lgsolver.hpp                           |   Bin 0 -> 171 bytes
 src/fflib/AFunction.cpp                            |  1964 +++
 src/fflib/AFunction.hpp                            |  3256 ++++
 src/fflib/AFunction2.cpp                           |   985 ++
 src/fflib/AFunction_ext.hpp                        |   622 +
 src/fflib/AddNewFE.h                               |   104 +
 src/fflib/AnyType.hpp                              |   202 +
 src/fflib/CodeAlloc.cpp                            |   161 +
 src/fflib/CodeAlloc.hpp                            |    77 +
 src/fflib/InitFunct.cpp                            |    83 +
 src/fflib/InitFunct.hpp                            |    80 +
 src/fflib/Makefile.am                              |    68 +
 src/fflib/Operator.hpp                             |   782 +
 src/fflib/P1IsoValue.cpp                           |   434 +
 src/fflib/P1IsoValue.hpp                           |    49 +
 src/fflib/PlotStream.hpp                           |   257 +
 src/fflib/Serialize.hpp                            |    99 +
 src/fflib/String.hpp                               |   170 +
 src/fflib/UMFPack_Solver.cpp                       |   366 +
 src/fflib/array_complex.cpp                        |    91 +
 src/fflib/array_init.hpp                           |    37 +
 src/fflib/array_long.cpp                           |   169 +
 src/fflib/array_real.cpp                           |    81 +
 src/fflib/array_resize.hpp                         |    32 +
 src/fflib/array_tlp.hpp                            |  1451 ++
 src/fflib/endian.hpp                               |   144 +
 src/fflib/environment.cpp                          |   407 +
 src/fflib/environment.hpp                          |    41 +
 src/fflib/error.hpp                                |   135 +
 src/fflib/ff++.hpp                                 |    47 +
 src/fflib/ffapi.cpp                                |   312 +
 src/fflib/ffapi.hpp                                |   115 +
 src/fflib/ffstack.hpp                              |   384 +
 src/fflib/global.cpp                               |   106 +
 src/fflib/glumesh2D.cpp                            |   431 +
 src/fflib/lex.cpp                                  |   860 +
 src/fflib/lex.hpp                                  |   161 +
 src/fflib/lgfem.cpp                                |  6011 +++++++
 src/fflib/lgfem.hpp                                |   814 +
 src/fflib/lgmat.cpp                                |  3024 ++++
 src/fflib/lgmesh.cpp                               |  1937 +++
 src/fflib/lgmesh.hpp                               |    40 +
 src/fflib/lgmesh3.cpp                              |  1634 ++
 src/fflib/lgmesh3.hpp                              |    40 +
 src/fflib/lgsolver.hpp                             |   612 +
 src/fflib/load.cpp                                 |   168 +
 src/fflib/mt19937ar.cpp                            |   191 +
 src/fflib/problem.cpp                              |  6137 +++++++
 src/fflib/problem.hpp                              |  1347 ++
 src/fflib/showverb.hpp                             |    34 +
 src/fflib/string_def.cpp                           |   172 +
 src/fflib/strversionnumber.hpp                     |    37 +
 src/fflib/strversionnumber.m4                      |    23 +
 src/fflib/throwassert.hpp                          |    54 +
 src/fflib/versionnumber.hpp                        |     1 +
 src/lglib/._lg.ypp                                 |   Bin 0 -> 171 bytes
 src/lglib/Makefile.am                              |    20 +
 src/lglib/lg.ypp                                   |   943 ++
 src/lglib/mymain.cpp                               |    14 +
 src/libMesh/Makefile.am                            |    13 +
 src/libMesh/chrono.c                               |    98 +
 src/libMesh/chrono.h                               |    32 +
 src/libMesh/eigenv.c                               |   620 +
 src/libMesh/eigenv.h                               |    10 +
 src/libMesh/libmesh3.c                             |   937 ++
 src/libMesh/libmesh3.h                             |   168 +
 src/libMesh/libmesh5.c                             |  1260 ++
 src/libMesh/libmesh5.h                             |   174 +
 src/libMesh/memory.c                               |   239 +
 src/libMesh/memory.h                               |    22 +
 src/medit/._keyboard.c                             |   Bin 0 -> 171 bytes
 src/medit/._mouse.c                                |   Bin 0 -> 171 bytes
 src/medit/._sproto.h                               |   Bin 0 -> 171 bytes
 src/medit/Makefile.am                              |    38 +
 src/medit/animat.c                                 |   247 +
 src/medit/bbfile.c                                 |   253 +
 src/medit/camera.c                                 |   139 +
 src/medit/cenrad.c                                 |    81 +
 src/medit/chrono.h                                 |    32 +
 src/medit/clip.c                                   |   345 +
 src/medit/clipvol.c                                |   513 +
 src/medit/critip.c                                 |   312 +
 src/medit/cube.c                                   |   128 +
 src/medit/dlists.c                                 |   658 +
 src/medit/eigenv.h                                 |     2 +
 src/medit/ellipse.c                                |   351 +
 src/medit/extern.h                                 |     6 +
 src/medit/geometry.c                               |   115 +
 src/medit/gisfil.c                                 |   193 +
 src/medit/grafic.h                                 |   225 +
 src/medit/hash.c                                   |   376 +
 src/medit/ilists.c                                 |   524 +
 src/medit/image.c                                  |   333 +
 src/medit/image.h                                  |    29 +
 src/medit/inmsh2.c                                 |   193 +
 src/medit/inout.c                                  |   754 +
 src/medit/inout_morice.c                           |  1478 ++
 src/medit/inout_popenbinaire.c                     |   985 ++
 src/medit/items.c                                  |   478 +
 src/medit/keyboard.c                               |   868 +
 src/medit/listnum.c                                |   148 +
 src/medit/material.c                               |   541 +
 src/medit/medit.c                                  |   439 +
 src/medit/medit.h                                  |    91 +
 src/medit/menus.c                                  |  1181 ++
 src/medit/mesh.c                                   |   477 +
 src/medit/mesh.h                                   |   108 +
 src/medit/mlists.c                                 |  1309 ++
 src/medit/morphing.c                               |    92 +
 src/medit/mouse.c                                  |   438 +
 src/medit/normal.c                                 |   150 +
 src/medit/param.c                                  |    66 +
 src/medit/parsar.c                                 |   162 +
 src/medit/parsop.c                                 |   358 +
 src/medit/particle.c                               |   382 +
 src/medit/path.c                                   |   188 +
 src/medit/persp.c                                  |    83 +
 src/medit/picking.c                                |   943 ++
 src/medit/psfile.c                                 |   204 +
 src/medit/scene.c                                  |   930 ++
 src/medit/scissor.c                                |   113 +
 src/medit/sftcpy.c                                 |   329 +
 src/medit/sproto.h                                 |   300 +
 src/medit/status.c                                 |   182 +
 src/medit/stream.c                                 |  1961 +++
 src/medit/tiles.c                                  |   236 +
 src/medit/transform.c                              |    36 +
 src/medit/util.c                                   |   278 +
 src/medit/vector.c                                 |   780 +
 src/medit/view.c                                   |    91 +
 src/medit/zaldy1.c                                 |    70 +
 src/medit/zaldy2.c                                 |    26 +
 src/mpi/._parallelempi.cpp                         |   Bin 0 -> 170 bytes
 src/mpi/Makefile.am                                |    31 +
 src/mpi/ff-mpirun.in                               |    35 +
 src/mpi/parallelempi-empty.cpp                     |    11 +
 src/mpi/parallelempi.cpp                           |  2636 +++
 src/nw/Makefile.am                                 |    25 +
 src/solver/MUMPS_FreeFem.cpp                       |  2571 +++
 src/solver/README_COMPILE                          |   170 +
 src/solver/complex_SuperLU_DIST_FreeFem.cpp        |   825 +
 src/solver/complex_pastix_FreeFem.cpp              |   705 +
 src/solver/ffsuperludistoption.hpp                 |   544 +
 src/solver/hips_FreeFem.cpp                        |   643 +
 src/solver/hypre_FreeFem.cpp                       |  1758 ++
 src/solver/makefile                                |    43 +
 src/solver/makefile-common.inc                     |    64 +
 src/solver/makefile-sparsesolver.inc               |   317 +
 src/solver/parms_FreeFem.cpp                       |  1043 ++
 src/solver/real_SuperLU_DIST_FreeFem.cpp           |   791 +
 src/solver/real_pastix_FreeFem.cpp                 |   711 +
 src/solver/wrapper_dotblas.c                       |    30 +
 src/solver/wrapper_dotblas.f                       |    42 +
 src/solver/wrapper_dotblas1.c                      |   117 +
 src/solver/wrapper_dotblas1.f                      |    42 +
 test-driver                                        |   139 +
 test-driver-ff                                     |   135 +
 uninstall-ff++                                     |    18 +
 ylwrap                                             |   143 +
 1019 files changed, 289440 insertions(+)

diff --git a/._TODO b/._TODO
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/._TODO differ
diff --git a/._ax_lib_hdf5.m4 b/._ax_lib_hdf5.m4
new file mode 100644
index 0000000..50f16f8
Binary files /dev/null and b/._ax_lib_hdf5.m4 differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fcd7136
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,109 @@
+._
+DOC/freefem++doc.pdf.orig
+DOC/freefem++doc.pdf
+DOC/Makefile.in.orig
+DOC/Makefile.in
+INSTALL
+Makefile.in.orig
+Makefile.in
+aclocal.m4
+compile
+config.h.in.orig
+config.h.in
+config.guess
+config.sub
+configure.orig
+configure
+debian/results.txt
+depcomp
+download/Makefile
+download/Makefile.in
+download/Makefile.in.orig
+download/arpack/Makefile
+download/arpack/Makefile.in
+download/arpack/Makefile.orig
+download/arpack/Makefile.in.orig
+download/bin/ff-get-dep
+download/bin/ff-pkg-download
+download/blas/Makefile
+download/blas/Makefile.in
+download/blas/Makefile.in.orig
+download/fftw/Makefile
+download/gmm/cxxflags.orig
+download/nlopt/config.log
+download/pkg/
+download/umfpack/Makefile
+download/umfpack/Makefile.in
+download/umfpack/Makefile.in.orig
+examples++-3d/Makefile.in.orig
+examples++-3d/Makefile.in
+examples++-3d/all.edp
+examples++-3d/all.edp.orig
+examples++-bug/Makefile.in.orig
+examples++-chapt3/Makefile.in.orig
+examples++-eigen/Makefile.in
+examples++-eigen/Makefile.in.orig
+examples++-eigen/freefem++.pref
+examples++-bug/Makefile.in
+examples++-chapt3/Makefile.in
+examples++-chapt3/freefem++.pref
+examples++-eigen/Makefile.in
+examples++-eigen/modes.txt
+examples++-load/all.edp
+examples++-load/Makefile.in.orig
+examples++-load/Makefile.in
+examples++-load/makeref.edp
+examples++-load/Missing-plugins-so.log
+examples++-load/regtests.edp
+examples++-load/WHERE_LIBRARY
+examples++-load/WHERE_LIBRARY-download-new
+examples++-load/._APk-MetricPk.edp.orig
+examples++-mpi/Makefile.in.orig
+examples++-other/Makefile.in.orig
+examples++-tutorial/Makefile.in.orig
+examples++-tutorial/._array.edp.orig
+examples++-mpi/Makefile.in
+examples++-mpi/Missing-plugins-so.log
+examples++-other/Makefile.in
+examples++-tutorial/Makefile.in
+examples++/Makefile.in
+examples++/Makefile.in.orig
+examples++/freefem++.pref
+install-sh
+missing
+mkinstalldirs
+src/Algo/Makefile.in.orig
+src/Eigen/._eigenvalue.cpp.orig
+src/Graphics/Makefile.in.orig
+src/Makefile.in.orig
+src/bamg/Makefile.in.orig
+src/bamglib/Makefile.in.orig
+src/bin-win32/Makefile.in.orig
+src/femlib/Makefile.in.orig
+src/fflib/Makefile.in
+src/fflib/Makefile.in.orig
+src/fflib/strversionnumber.cpp
+src/fflib/strversionnumber.cpp.orig
+src/fflib/._environment.cpp.orig
+src/lglib/Makefile.in.orig
+src/lglib/lg.tab.cpp.orig
+src/lglib/lg.tab.hpp.orig
+src/libMesh/Makefile.in.orig
+src/medit/Makefile.in.orig
+src/mpi/Makefile.in.orig
+src/nw/Makefile.in.orig
+src/Algo/Makefile.in
+src/Graphics/Makefile.in
+src/Makefile.in
+src/bamg/Makefile.in
+src/bamglib/Makefile.in
+src/bamglib/._Mesh2.cpp.orig
+src/bin-win32/Makefile.in
+src/femlib/Makefile.in
+src/lglib/Makefile.in
+src/lglib/lg.tab.cpp
+src/lglib/lg.tab.hpp
+src/libMesh/Makefile.in
+src/medit/Makefile.in
+src/mpi/Makefile.in
+src/nw/Makefile.in
\ No newline at end of file
diff --git a/0ldUserReadMe.txt b/0ldUserReadMe.txt
new file mode 100644
index 0000000..c8c8995
--- /dev/null
+++ b/0ldUserReadMe.txt
@@ -0,0 +1,34 @@
+///////////////////////////////
+     New 3D features of freefem++ 
+///////////////////////////////
+
+Version 3.0 is the first version capable of 3D computations.  The price to pay is more difficult mesh generations and difficulties to display the results.  More details can be found in the documentation
+
+1. Mesh generation
+==============
+There is an interface with the mesh generator tetgen (http://tetgen.berlios.de/)
+   see: examples++-3d/Poisson3d.edp  ( mesh of a sphere)
+There is a small 3D mesh generator for cylindrical meshes by extrusion of a 2D mesh
+   see example: examples++-3d/Lac.edp  for a mesh of a lac
+                examples++-3d/Stokes.edp for a mesh a cube.
+
+There is a mesh reader from files in format .mesh of medit (http://www.ann.jussieu.fr/~frey/software.html)
+  see example: examples++-3d/dodecaedre01.mesh 
+ 
+
+2. Graphics
+========
+
+2D Graphics
+-------------
+The standard graphic windows now use a client/server architecture based on openGL GLUT, so the commands have changed:
+ - to go to the next graphic type "enter key"
+ - to close the graphic window type escape
+ - to find out about other commands type the ? key
+ 
+Warning:  you must have "ffglut" in your path; this is done for you by the install program on windows system if you do not uncheck the click box.
+
+3D Graphics
+-------------
+Real 3D graphics can be obtained with medit, built in freefem andit can be  launched independently of freefem by the command shell "ffmedit".
+Freefem can also launch medit by the keywork medit.  Two calls to medit will launch two instances of medit. To close these windows use escape.
\ No newline at end of file
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..deb855d
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+Fr�d�ric Hecht <hecht at ann.jussieu.fr>
+Olivier Pironneau <pironneau at ann.jussieu.fr>
+Antoine Le Hyaric <lehyaric at ann.jussieu.fr>
+Albert Ly <ly at ann.jussieu.fr>
\ No newline at end of file
diff --git a/BUGS b/BUGS
new file mode 100644
index 0000000..6f03c12
--- /dev/null
+++ b/BUGS
@@ -0,0 +1,88 @@
+-- bug in  examples++-3d/TruncLac.edp   april 2014 
+assertion under windows system versiuon 3.30 ()
+
+
+-- bug in clean variable (delete) after a break , continue or return.
+example :
+  while(1) 
+{
+    ....
+    if ( ...) break;
+    matrix M= ...
+}  // here we delete the data associated to objet M
+but the variable M  is un set, so some time freefem trap
+when  we free unset pointer.
+
+
+-- bug une fonction with string parameter
+hard to correct  
+  func bool  write(string  fn,real[int] & u)
+    {
+      cout << fn << endl;  //  delete 2 times
+      return true;
+   }
+
+
+Now, problem: (correct in version 1.14)
+   adpation and periodic boundary condition are incompatible.
+   no way to inforce periodic adpated  mesh  today.
+
+-- before version 1.28:
+  bug when 
+  passing a parameter of funct to a  parameter
+  parameter
+  like:
+    func int fi(real a)
+     {
+       int i=a*a/0;
+       return i;
+     }; 
+    func real myfunction(real a,real b)
+    {
+     real z =fi(a)+b/0; // bug loop in E_F0para::operator()(void*) const ()
+     return z;
+    };
+
+
+
+
+-- before version 1.21, bug in interpolation on non connexe 
+   domain, (some pieces of code are lose)
+
+    on(1,u=N.x); the normal is not set  (correct in version 1.20)
+
+
+-- bug in version 1.18 and before
+  The no symetric matrix set form a variationnal form
+  is make with 2 transpositions one on the space and one 
+  at the level of the bilineair form
+  fespace Ph(Th,P1),Vh(Th,P2);
+  varf a(p,v)=int2d(Th)(p*dx(v));
+  matrix A=a(Ph,Vh); // is n m matrix n (resp. m) is the 
+  number of DF of Ph (resp. Vh), so the 
+  construct matrix is Aij= int2d(Th)(v_j*dx(p_i));
+
+ 
+ 
+ 
+bug in version 1.16 and after:
+The mixing of fespace with differents periodic boundary condition is not
+implemented in no-scalar problem. So all the finite element space use for test or unknow functions in a problem, must  have the same  type of periodic boundary condition or no periodic boundary condition. 
+No clean message is give and the result is
+impredictible, Sorry.
+
+
+bug in version 1.15 and before: 
+bug know bug:  example-bug/aaa.edp
+
+Do not make copy mesh and fespace
+
+Mesh Thh;
+{
+Mesh Th=readmesh( ..); // OK
+Th=Thh;  // BUG the mesh is delete twice.
+}
+plot(Thh); // trap because the mesh is delete
+
+the same probleme  occure with fespace
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..de52d63
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,28 @@
+//
+// SUMMARY:  FreeFem++
+// RELEASE: 2
+// USAGE  :  
+// AUTHOR:   F. Hecht, O. Pironneau   
+// ORG    :  Universit� Pierre et Marie Curie, Paris, France
+// E-MAIL :   Hecht at ann.jussieu.fr
+//
+// ORIG-DATE:     November 2001
+/*
+
+  This file is part of Freefem++
+
+    Freefem++ is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    Freefem++  is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with Freefem++; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
\ No newline at end of file
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
index 0000000..6207c52
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,362 @@
+This is The FreeFem++ software.
+
+Programs in it were maintained by
+Frederic hecht <Frederic.Hecht at upmc.fr>  and by
+Olivier Pironneau <Olivier.Pironneau at upmc.fr> and by
+Antoine Le Hyaric <lehyaric at ann.jussieu.fr>
+
+
+All its programs which may be redistributed under the terms of the
+GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999
+ Except files :
+   Comming form COOOL sofware (all files in directory src/Algo,
+    mailto:coool at coool.mines.edu),  no license.
+  and the file mt19937ar.cpp ( mailto:m-mat at math.sci.hiroshima-u.ac.jp )
+  with they own like license.
+
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+

+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+

+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+

+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+

+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+

+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+

+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+

\ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..3ef51df
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,646 @@
+2005-05-03 16:25  hecht
+
+	*   remove pascal in "\p  "  macos version
+
+2005-05-03 15:12  hecht
+
+	*   try to compile with de idm compiler xlc++
+	    work in progress
+	    remove  10^10 an 10.^10  (FH)
+
+2005-05-02 10:57  hecht
+
+	*     do correction for g++-4.0
+	      remove const in Expression type
+
+2005-04-27 14:23  hecht
+
+	*     do correction for g++ version 4.0  (new apple compiler on
+	  Tiger)
+	      small change in RNM and cadna  (FH)
+
+2005-04-22 11:58  lehyaric
+
+	* Debug checks are ok on Debian Testing
+
+2005-04-17 18:44  hecht
+
+	* add page to explain how to bluid weak form with Robin / Neumann
+	  coundary condition
+
+2005-04-16 21:36  hecht
+
+	*  add tool to solve variationnal inequality
+	   add change version to 1.46-1
+
+2005-04-15 22:48  hecht
+
+	*  the 2  new example have probleme with testhighlight.sh
+	   we disable the test in chech (FH)
+
+2005-04-15 22:06  hecht
+
+	* add tools to solve variationnal inequality   let d en array and A
+	  a square matrix (in .edp)    d=A.diag; // get the diagonal  of
+	  the matrix	A.diag = d; //set the diagonal	  set(A,solver=CG);
+	  // important to change precondiconning before solving
+
+2005-04-13 11:58  lehyaric
+
+	* IDE compiles again under MingW (an include file was missing)
+
+2005-04-12 18:37  hecht
+
+	*   add Modification Kohji Ohtsuka in a manual
+	    try too correct problem in eigen value in no symetric cas (??)
+
+2005-04-12 12:07  hecht
+
+	*  add flags to build unionkjack mesh on square
+	   example:  mesh Th=square(nn,mm,[x/ddx,y/ddy] ,flags=1);
+
+2005-04-05 15:08  lehyaric
+
+	* FreeFem+-ide compiles on MacOS X
+
+2005-04-05 14:33  lehyaric
+
+	* First version of FreeFem++-ide without sockets compiles under
+	  Linux
+
+2005-03-30 11:38  hecht
+
+	*   correct name of example  blakschol.edp in BlackSchole.edp
+	    add file in distribution archive (logo2.ico)
+
+2005-03-30 11:05  hecht
+
+	*      add  src/ide/testhighlight.sh in distributed file
+	  (src/ide/Makefile.am) FH
+
+2005-03-30 11:02  lehyaric
+
+	* Not regenerating HISTORY if not in a CVS working area
+
+2005-03-30 10:42  hecht
+
+	* correct some mistake in Makefile.am (in: examples++-load/,
+	  src/ide/)
+
+2005-03-30 09:31  hecht
+
+	*    adding 2 new files for allocation (forgot in previous commit)
+
+2005-03-29 23:13  hecht
+
+	*	Big change in code generation alloc  (work in progress)
+		   to remove all undelete pointer.
+		May be correct trap in arpack++ (alloction problem not
+	  sure,
+		  very strange thing)
+		Put 1-46-0 version number
+		Inforce compile in example-load
+		remark, all test work on my Mac, FH.
+
+2005-03-25 17:59  hecht
+
+	*   correct bug in trunc function:
+	      The bug is  the mesh have hole the we get a mesh with
+	  triangle in the hole:
+	       border a(t=0,2*pi){ x=cos(t); y=sin(t);label=1;}
+	       border b(t=0,2*pi){ x=0.3+0.3*cos(t); y=0.3*sin(t);label=2;}
+	       mesh Thwithhole	 = buildmesh(a(50)+b(-30));
+	       mesh Th2=trunc(Thwithhole,1,split=2,label=2);
+
+2005-03-25 14:54  lehyaric
+
+	* Compiling ok on Linux
+
+2005-03-25 12:37  lehyaric
+
+	* Client and server merged into one unique executable to make sure
+	  that the client can find its server program, even through
+	  symbolic links.
+
+2005-03-17 14:15  lehyaric
+
+	* Included src/lglib/lg.tab.?pp in cleanregen.sh
+
+2005-03-17 14:13  lehyaric
+
+	* Replaced sem_getvalue() with a separate counter on MacOSX.
+
+2005-03-16 22:28  hecht
+
+	*   add tool to get number of mesh triangle  contening a point
+	  (x,y)
+	    or to get the region number
+	    example:
+	     int it00 = Th(0.55,0.6).nuTriangle; // get the number of Th's
+	  triangle contening (0.55,0.6)
+	     int nr00 = Th(0.55,0.6).region;; // get the region number of
+	  Th's triangle contening (0.55,0.6)
+
+2005-03-16 15:37  hecht
+
+	* correct prototype of StrVersionNumber in macrgraf
+
+2005-03-16 15:05  lehyaric
+
+	* Updates to the no-F77 no-C configuration
+
+2005-03-16 14:41  lehyaric
+
+	* Fortran and C compilers are now optional (if they are missing, we
+	  just don't compile the libraries that need them).
+
+2005-03-16 12:08  hecht
+
+	* correct error in prototype of StrVersionNumber and add precision
+	  to show the correct version number
+
+2005-03-13 16:32  hecht
+
+	* correct compilation problem in RNM (resize) with g++3.4 (add
+	  this->)
+
+2005-03-02 11:50  lehyaric
+
+	* Correcting compilation problem on RedHat
+
+2005-03-02 11:29  lehyaric
+
+	* New packaging including FreeFem++-cs features: fast graphics,
+	  grammar highlighting, error-line display
+
+2005-03-02 11:22  lehyaric
+
+	* FreeFem++-cs MinGW bug corrected: does not crash anymore when
+	  reading a file name from the command line
+
+2005-03-01 16:06  lehyaric
+
+	* Removed unnecessary #includes
+
+2005-03-01 15:33  lehyaric
+
+	* Simplified startup code. Hopefully, this will stop the MinGW
+	  segmentation fault bug (at startup when a filename is specified
+	  on the command line), but this is not proven yet.
+
+2005-03-01 14:21  lehyaric
+
+	* Segmentation violation error while loading a file from the
+	  command line in FreeFem++-cs. Debugging in progress.
+
+2005-02-28 18:06  lehyaric
+
+	* Now compiling fine under Cygwin
+
+2005-02-28 11:40  lehyaric
+
+	* Now compiling fine on MinGW
+
+2005-02-28 11:27  lehyaric
+
+	* Removed use of regex.h since it is not available under MinGW.
+
+2005-02-25 16:28  lehyaric
+
+	* Corrected a small compilation error.
+
+2005-02-25 16:14  lehyaric
+
+	* FreeFem++-cs: compile-time or runtime errors are now highlighted
+	  in the editor (the corresponding line number is extracted from
+	  all the server messages thanks to a regex).
+
+2005-02-25 13:10  lehyaric
+
+	* More coherency checks in configure.ac for a correct MPI
+	  installation.
+
+2005-02-25 10:50  lehyaric
+
+	* Added new "resize" reserved word into the highlighting grammar.
+
+2005-02-24 21:27  hecht
+
+	* correct the documentation
+
+2005-02-24 20:44  hecht
+
+	* correct  mistake in return type in complex mean and jump new
+	  function (FH)
+
+2005-02-24 15:33  hecht
+
+	* resize of array and matrices, continuing
+
+2005-02-24 15:32  hecht
+
+	* add resize of int,real and complex array or matrices, exemple:
+	  real [int] tab2=[1,2,3,3.14]; tab2.resize(10); // to set the new
+	  siez of array to 10
+
+2005-02-24 15:08  lehyaric
+
+	* Grammar-driven highlighting works. Regression tests for it are
+	  included in "make check". Include file and macros are not scanned
+	  during highlighting.
+
+2005-02-24 09:44  hecht
+
+	* correct bug  in array of complex FE function like
+	  Vh<complex>[int]  Wh(10); // where Vh is a fespace
+
+2005-02-23 15:51  lehyaric
+
+	* Highlighting test procedure not ready for regression tests yet:
+	  disabled from "make check".
+
+2005-02-23 15:40  lehyaric
+
+	* Renamed some FreeFem++ tokens to avoid collisions with
+	  system-dependant defines.
+
+2005-02-23 15:37  lehyaric
+
+	* Properly compiled lex and yacc source, for machines that do not
+	  have working versions of lex or yacc.
+
+2005-02-23 15:35  lehyaric
+
+	* No CVS keyword in lex and yacc source files to avoid recompiling
+	  them after a "cvs commit" on machines that do not have proper
+	  versions of this software.
+
+2005-02-23 15:22  lehyaric
+
+	* "testhighlight" regression tests now work up to (but not
+	  including) array.edp
+
+2005-02-23 14:50  lehyaric
+
+	* Added highlighting grammar files into CVS, in case the compiling
+	  environment does not include a working version of bison or lex.
+
+2005-02-23 13:44  lehyaric
+
+	* The HISTORY file is now created from CVS logs thanks to "cvs2cl".
+	  Previous HISTORY items are saved as HISTORY_BEFORE_2005.
+
+2005-02-23 12:45  lehyaric
+
+	*     FreeFem++-cs: grammar-driven syntax highlighting works on
+	      (examples++-tutorial/...) Laplace.edp, adapt.edp and
+	      adaptindicatorP1.edp (ALH)
+
+2005-02-23 10:49  hecht
+
+	* add jump and mean of complex function.
+
+2005-02-22 17:37  lehyaric
+
+	* FreeFem++-cs: grammar-driven highlighting procedure works on
+	  (examples++-tutorial/) Laplace.edp and adapt.edp.
+
+2005-02-18 20:13  lehyaric
+
+	* FreeFem++-cs syntax highlighting is now highlights keywords based
+	  on their location in the input buffer, which removes any need for
+	  backtracking in the bison grammar. The grammar is now much
+	  simpler thanks to this.
+
+2005-02-18 18:00  hecht
+
+	* ajoute d'un test d'erreur
+
+2005-02-17 16:54  lehyaric
+
+	* Progressive updates to the highlighting grammar.
+
+2005-02-17 16:02  lehyaric
+
+	* Added new developments
+
+2005-02-17 15:05  lehyaric
+
+	* Compiles on MacOS X.
+
+2005-02-17 15:05  lehyaric
+
+	* Grammar-driven highlighting now includes macros (but it stops
+	  highlighting a macro at the first "/").
+
+2005-02-17 14:27  lehyaric
+
+	* First working version of syntax highlighting through grammar file
+	  in FreeFem++-cs editor.
+
+2005-02-16 18:13  hecht
+
+	* 3D continuing +  truc
+
+2005-02-16 13:44  lehyaric
+
+	* Socket buffering is now limited to avoid random communication
+	  errors.
+
+2005-02-16 12:29  lehyaric
+
+	* Buffered socket writes implemented in FreeFem++-cs
+
+2005-02-15 14:30  lehyaric
+
+	* Corrected comments
+
+2005-02-15 14:19  lehyaric
+
+	* FreeFem++-cs binary TCP flux optimized.
+
+2005-02-14 17:22  lehyaric
+
+	* Socket communication between client and server in FreeFem++-cs
+	  has been translated into binary format for speed.
+
+2005-02-14 11:50  lehyaric
+
+	* Small spelling mistake
+
+2005-02-11 22:20  hecht
+
+	* complet DOC
+
+2005-02-11 18:00  hecht
+
+	*    add 2 new quadrature formular qf7pT and qf9pT with
+	  respectively 15 and 21 points
+	     add  P2b a new finite element  : P2 + bubble
+
+2005-02-11 15:57  lehyaric
+
+	* Now drag'n'drop and copy/paste work concurrently in the
+	  FreeFem++-cs editor window.
+
+2005-02-08 17:26  hecht
+
+	* add 3D stuff in quadtree
+
+2005-02-08 16:52  lehyaric
+
+	* Updated TODO list for FreeFem++-cs
+
+2005-02-08 16:18  lehyaric
+
+	* Dynamic loading is now disabled if dlopen() does not link
+	  properly (bug reported by Haiko Etzel)
+
+2005-02-08 15:18  hecht
+
+	* add  buildmesh example with nbvx=  named parameter
+
+2005-02-08 14:23  lehyaric
+
+	* New Debian package
+
+2005-02-04 16:47  lehyaric
+
+	* Now checks that FLTK is compiled with threads before accepting
+	  it.
+
+2005-02-04 16:24  lehyaric
+
+	* Patchs de configuration propos�s par Thierry Thomas pour FreeBSD
+	  int�gr�s.
+
+2005-02-04 15:30  hecht
+
+	* beginning of	3D version
+
+2005-02-01 17:17  lehyaric
+
+	* Compiles on MacOS X
+
+2005-02-01 16:49  lehyaric
+
+	* New script to remove generated files (in order to prevent CVS
+	  conflicts)
+
+2005-02-01 16:04  lehyaric
+
+	* FreeFem++-cs compiling and running on Windows with fully blocking
+	  sockets
+
+2005-02-01 15:01  lehyaric
+
+	* Cosmetic change
+
+2005-02-01 14:38  lehyaric
+
+	* FreeFem++-cs works with fully-blocking sockets on Linux.
+	  src/fflib/strversionnumber.m4 added to distribution list.
+
+2005-02-01 12:40  lehyaric
+
+	* Still problems with blocking communication. But FreeFem++-cs
+	  compiles
+
+2005-02-01 12:20  lehyaric
+
+	* Reverting FreeFem++-cs to blocking IO because of Microsoft
+	  Windows problems
+
+2005-01-31 15:21  lehyaric
+
+	* New version number in makefiles.
+
+2005-01-31 15:17  lehyaric
+
+	* Default version number now includes package number.  Build date
+	  changes at each build.
+
+2005-01-31 14:07  lehyaric
+
+	* Problem with busy waiting under Windows solved.  Change in
+	  version numbering variables (see configure.ac).
+
+2005-01-29 10:15  hecht
+
+	* end g++3.4 correction on hydre CV:
+	  ----------------------------------------------------------------------
+
+2005-01-29 09:56  hecht
+
+	* correct some compile error with g++ 3.4 CV
+	  ----------------------------------------------------------------------
+
+2005-01-28 14:52  lehyaric
+
+	* Corrected "cannot open '-psn_xxx' document" error on MacOS.
+
+2005-01-28 14:00  lehyaric
+
+	* FreeFem++-cs compiles+runs ok on MacOS X
+
+2005-01-28 13:27  lehyaric
+
+	* Windows packaging for new improved socket implementation
+
+2005-01-28 12:01  lehyaric
+
+	* ecompiling ok on Windows.
+
+2005-01-28 11:28  lehyaric
+
+	* Still trying to resolve discrepancies between Linux and Windows
+	  sockets.
+
+2005-01-27 19:01  hecht
+
+	* correct ; placement in if ...
+
+2005-01-27 18:30  hecht
+
+	* pour mettre les makefile.in ok
+
+2005-01-27 18:14  hecht
+
+	* mac install continuing
+
+2005-01-27 18:07  hecht
+
+	* continuing coorect of macos application installation
+
+2005-01-27 17:16  lehyaric
+
+	* Reorganising socket communication in FreeFem++-cs because of
+	  instabilities on Windows.
+
+2005-01-27 10:59  lehyaric
+
+	* Drag'n'drop works with Mozilla Firefox for Windows.  FreeFem++-cs
+	  documentation updated.
+
+2005-01-26 23:34  hecht
+
+	* add .app.tgz of macos application
+
+2005-01-26 23:31  hecht
+
+	* correct pb dvi pdf in manual.tex
+
+2005-01-26 23:25  hecht
+
+	* correct stuff in dist generation correct trouble in configure.ac
+	  and tar.gz file
+
+2005-01-26 23:22  hecht
+
+	* correct problem dvi and pdf chose make lot of small change in
+	  configure.ac ...
+
+2005-01-26 17:50  hecht
+
+	* coorect macos X application)
+
+2005-01-26 17:35  lehyaric
+
+	* Drag'n'drop works with mozilla-firefox under X11.
+
+2005-01-26 13:58  lehyaric
+
+	* In configure.ac, PACKAGE_VERSION is already used by autoconf, so
+	  we create 'FREEFEM_PACKAGING' instead.
+
+2005-01-26 12:11  lehyaric
+
+	* Drag'n'drop is now working in FreeFem++-cs.
+
+2005-01-26 11:30  lehyaric
+
+	* Drag'n'drop being implemented.
+
+2005-01-24 11:28  hecht
+
+	*   add  named parameter nbtx=..  in buildmesh	function to change
+	  the default
+	     maximal number of vertex in the build mesh.
+
+2005-01-20 20:10  hecht
+
+	*     Correct a segfault if second derivative of test function
+	  exist in
+	      problem definition.  The Change in problem.cpp:
+	      resize : KN<double> buf(Vh.MaximalNbOfDF()*3*Vh.N);
+	      to     : KN<double>
+	  buf(Vh.MaximalNbOfDF()*last_operatortype*Vh.N);
+
+2005-01-20 10:39  hecht
+
+	* correct parameter passing () in macro argument correct linear
+	  combination of sparce matrix.
+
+2005-01-11 13:38  lehyaric
+
+	* FreeFem++-cs compiles with cygwin. It is not tested yet. File
+	  paths may be a problem.
+
+2005-01-10 22:19  hecht
+
+	* change c i C in speedtest.sh to get Cholesky cpu time
+
+2005-01-10 14:03  hecht
+
+	* add forgotten file .pdf
+
+2005-01-10 12:07  hecht
+
+	* window problem continue
+
+2005-01-10 10:41  hecht
+
+	*  correct ????  configure.ac under window
+
+2005-01-07 17:05  hecht
+
+	*  correct expand string in macro
+
+2005-01-07 15:55  hecht
+
+	* add config.h.in
+
+2005-01-07 12:25  lehyaric
+
+	* Cosmetic change
+
+2005-01-07 11:50  hecht
+
+	* correct initialisation in solve in case of un set variable
+
+2005-01-06 21:58  hecht
+
+	*    rewrite the macro generation tool to be more to suppress some
+	  bug
+	     in argument subtition
+	     correct error in line numbering in case of newline in string
+	     cosmetic change in output
+
+2005-01-05 23:10  hecht
+
+	* update HISTORY file
+
+2005-01-05 21:50  hecht
+
+	* correct segmentation violation  error if some FE variable is un
+	  set before solving problem because we use this variable  to
+	  initialise data.
+
+2005-01-04 16:58  hecht
+
+	* continuing	   int1d(Th,3,qfe=qf1pElump)(
+
+2005-01-04 16:45  hecht
+
+	* add qf1pElump   new quadrature formular in int1d() ...
+
diff --git a/CheckAll b/CheckAll
new file mode 100755
index 0000000..cc0d43c
--- /dev/null
+++ b/CheckAll
@@ -0,0 +1,21 @@
+ff=../src/nw/FreeFem++-nw
+ffmpi=""
+if [ -x ./src/bin/FreeFem++-nw.exe ] ; then ff=../src/bin/FreeFem++-nw.exe; fi
+if [ -x ./src/bin-win32/FreeFem++-nw.exe ] ; then ff=../src/bin-win32/FreeFem++-nw.exe; fi
+if [ -x ./src/mpi/ff-mpirun ] ; then ffmpi=../src/mpi/ff-mpirun; fi
+rm CheckAll-out
+for i in examples++*/.; do 
+echo  ----  $i  ---
+cd $i;
+case $i in 
+*mpi/.)  echo " skip $i do test a end " ;;
+*)       ../CheckAllEdp "$ff -nw" *.edp | tee -a ../CheckAll-out ;;
+esac;
+cd ..;
+done
+if [ -n "$ffmpi" ] ; then 
+cd examples++-mpi/
+../CheckAllEdp "$ffmpi -np 4" *.edp | tee -a ../CheckAll-out 
+else
+  echo " **no mpi " | tee -a CheckAll-out 
+fi
\ No newline at end of file
diff --git a/CheckAllEdp b/CheckAllEdp
new file mode 100755
index 0000000..a21f29e
--- /dev/null
+++ b/CheckAllEdp
@@ -0,0 +1,69 @@
+#!/bin/bash
+  red='' # Red.
+  grn='' # Green.
+  lgn='' # Light green.
+  blu='' # Blue.
+  mgn='' # Magenta.
+  std=''     # No color.
+
+NL=0
+NA=0
+NX=0
+NN=0
+NO=0
+NC=0
+NF=0
+
+cmm=$1;shift;
+if [ $# -eq 0 ]; then
+list=*.edp
+elif  [ $# -gt  0 ]; then
+list="$@"
+fi
+for i in $list
+do
+    case $i in
+	all.edp|regtests.edp) 
+	    echo  pass   $i;; 
+	*)
+	    ((NN++))
+	    ( $cmm "$i" )2>&1 1>$i-out;
+	    RES=$?
+	    ((SIG=$RES%128));
+
+	    ## error Compile error : Error load   # 1
+	    ## error Compile error :
+            ## Exec error : exec assert
+	    ## Exec error :
+	    errl=`grep 'error Compile error : Error load' $i-out`
+	    errC=`grep 'error Compile error :' $i-out`
+	    errX=`grep 'Exec error :' $i-out`
+	    errA=`grep 'Exec error : exec assert' $i-out`
+	  #  echo "$RES,$SIG,$errC,$errA."
+	    if [ -n "$errl" ] ; then
+		((NL++))
+		MSG="${mgn} FAIL(load)        ${std}"
+	    elif [ -n "$errC" ] ; then
+		((NC++))
+		MSG="${lgn} FAIL(Compile)     ${std}"
+	    elif [ -n "$errA" ] ; then
+		((NA++))
+		MSG="${blu} FAIL(Assert)      ${std}"
+	    elif [ -n "$errX" ] ; then
+		((NX++))
+		MSG="${mgn} FAIL(Exec)        ${std}"
+	    elif [ $SIG -eq 0 ] ; then
+		((NO++))
+		MSG="${grn} OK  (Exec)        ${std}"
+	    else
+		MSG="${red} FAIL(signal)=$SIG ${std}"
+		((NF++))
+	    fi
+	    echo $MSG  $cmm $i  >>$i-out
+	    echo  $MSG  $cmm $i "( see $i-out )";
+#	    echo  $MSG  $cmm $i "(see $i-out )" >>/tmp/list-ff-$$
+	    ;;
+    esac
+done
+
+echo "Nb Case $NN / ${grn}OK $NO / ${red} FAIL $NF / ${blu} Assert Error $NA/ ${lgn} Compile Error $NC  / ${mgn} load Error $NL / Exec Error $NX${std}"
diff --git a/DOC/._freefem++doc.pdf b/DOC/._freefem++doc.pdf
new file mode 100644
index 0000000..8911007
Binary files /dev/null and b/DOC/._freefem++doc.pdf differ
diff --git a/DOC/Makefile.am b/DOC/Makefile.am
new file mode 100644
index 0000000..20608a5
--- /dev/null
+++ b/DOC/Makefile.am
@@ -0,0 +1,44 @@
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem make multipleauthors start=13/05/04 upmc
+
+dist_pkgdata_DATA=$(DOCPDF)
+documentation: $(DOCPDF) 
+docps:  $(DOCPS) $(DOCPSGZ) 
+docpdf: $(DOCPDF) 
+
+# ALH - 16/10/13 - split GNU make directives into a separate makefile [[file:gnu.mak]] to suppress automake warning
+# messages about non-portability
+
+freefem++doc.pdf:
+	$(MAKE) -f gnu.mak $@ EPSTOPDF="$(EPSTOPDF)"
+freefem++doc.ps:
+	$(MAKE) -f gnu.mak $@ EPSTOPDF="$(EPSTOPDF)"
+freefem++doc.ps.gz:
+	$(MAKE) -f gnu.mak $@ EPSTOPDF="$(EPSTOPDF)"
+clean:
+	$(MAKE) -f gnu.mak $@
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/FreeFem++-CoCoa b/FreeFem++-CoCoa
new file mode 100755
index 0000000..5a657f5
--- /dev/null
+++ b/FreeFem++-CoCoa
@@ -0,0 +1,61 @@
+#!/bin/sh
+#  
+# EXTENSIONS  : ".edp"				# Accepted file extentions
+# OSTYPES     : "****"				# Accepted file types
+# ROLE        : None				# Role (Editor, Viewer, None)
+# SERVICEMENU : FreeFem++     			# Name of Service menu item
+#
+dir=`dirname $0`;
+ff="/usr/local/bin/FreeFem++"
+fa="-glut ffglut  "
+q="'"
+end="exit;"
+begin="cd $PWD;"
+
+# begin the cmd generation ----------
+cmd=""
+# -----------------
+for i in "$@"; do
+
+ d=`dirname "$i"`;
+ f=`basename "$i"`;
+ if [ -f "$i"  ] ; then
+     np=`awk -v npo=$np '$1=="//" && $2=="NBPROC" { if( vv == ""){ print $3;}; vv=1}' "$i"`
+     npa=`awk -v npo=$np '$1=="//" && $2=="PARAM" { if( vv == ""){ for(i=3;i<=NF;++i)print $i;}; vv=1}' "$i"`
+     # echo  --- $np -- $npa  --------
+     if [  "0$np" -gt 0 ]  ; then 
+	 test -x /usr/local/bin/ff-mpirun  && ff="/usr/local/bin/ff-mpirun -np $np"
+     fi
+     if [ -n "$npa"  ] ; then fa="$fa $npa"; fi
+     cmd="$cmd cd $q$d$q; $ff   $q$f$q $fa ;"
+  fi
+done
+# ------------------ 
+if [ -z "$cmd" ]; then
+ cmd="$ff;"
+fi
+# ------------------
+cmd="$cmd"
+# ---- end of cmd generation ----
+echo 'do script "'$cmd'"'
+#
+#
+#  send the command $cmd to the apple terminal via osascript
+#
+# (echo $0;echo $*;echo "--$TERM--";printenv;set)  >/tmp/tutu
+
+if [ -z "$TERM_PROGRAM" ] ; then 
+echo '
+tell application "Terminal"
+	activate
+	try
+	  do script "'$begin$cmd$end'" 
+	end try
+end tell 
+' | osascript 	
+else
+set -e
+eval  $cmd
+fi;
+
+
diff --git a/FreeFem++.mcp b/FreeFem++.mcp
new file mode 100755
index 0000000..4ac511e
Binary files /dev/null and b/FreeFem++.mcp differ
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..7166812
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,16172 @@
+@  changeset:   3168:841250c6ecc4
+|  tag:         tip
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Feb 16 12:51:05 2015 +0100
+|  summary:     correct find petsc
+|
+o  changeset:   3167:cd84708881af
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 13 19:04:29 2015 +0100
+|  summary:     correction  in caes of no compilion of hpddm
+|
+o  changeset:   3166:2ace2a1eda0b
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 13 15:53:04 2015 +0100
+|  summary:     correct typo in configure output
+|
+o  changeset:   3165:45280aa09820
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 13 15:43:25 2015 +0100
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   3164:0d87a638d273
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 13 15:41:24 2015 +0100
+|  summary:     put  change for hpdmm mlk old. Thank P. Jolivet.
+|
+o  changeset:   3163:6510f36c0063
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 13 10:14:01 2015 +0100
+|  summary:     add reinstall-hpddm targed in downlaod/Makefile
+|
+o  changeset:   3162:cd09add72c31
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 18:03:19 2015 +0100
+|  summary:     correct typo in find petsc
+|
+o  changeset:   3161:2d75c3267da7
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 15:41:22 2015 +0100
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   3160:07a30279fade
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 15:11:48 2015 +0100
+|  summary:     add notify of petsc
+|
+o  changeset:   3159:d71a3cc91c39
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 15:04:19 2015 +0100
+|  summary:     update INNOVATION file
+|
+o  changeset:   3158:7ffe24b7a08d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 15:02:49 2015 +0100
+|  summary:     pass to version 3.34-1 for PETSc interface ans schwarz plugins
+|
+o  changeset:   3157:83f4a2ab0c5f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 11:20:52 2015 +0100
+|  summary:     coorect problem on version in PETSc interface and  MKL for schawtz.cpp
+|
+o  changeset:   3156:651407885920
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 10:11:33 2015 +0100
+|  summary:     correct typo after big change in plugin (now all test works)
+|
+o  changeset:   3155:bff13b38aba2
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 12 09:43:26 2015 +0100
+|  summary:     Change all int of plugins due to bug on somme allpe version
+|
+o  changeset:   3154:e8aa9ceccd60
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 21:34:10 2015 +0100
+|  summary:     try of compile schwarz.cpp on all case
+|
+o  changeset:   3153:f693d6250f91
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 17:23:21 2015 +0100
+|  summary:     remove plot in MPI
+|
+o  changeset:   3152:9cbe00fe0e23
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 15:43:46 2015 +0100
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   3151:e6be9d714829
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 15:33:31 2015 +0100
+|  summary:     remove libiomp5 if non openmp
+|
+o  changeset:   3150:fdef3857f8bf
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 14:45:06 2015 +0100
+|  summary:     updet missing file for hpddm
+|
+o  changeset:   3149:7a351cbaa77d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 14:43:09 2015 +0100
+|  summary:     coorect pb of compilation of schwarz.cpp plugins in progress.
+|
+o  changeset:   3148:f85a44d0ab6d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 10:28:55 2015 +0100
+|  summary:     correct ff-get-dep.in ff-get-dep.awk (pb of new line  in awk )
+|
+o  changeset:   3147:bb139ebb5e41
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 10 09:28:35 2015 +0100
+|  summary:     rewrite all automatic search of library in awk ad add no mandatory lib like PETSc
+|
+o  changeset:   3146:d23e38b06cd6
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Feb 09 18:06:20 2015 +0100
+|  summary:     correct missing include seach in ff-get-dep.in for no mandatori libs
+|
+o  changeset:   3145:3516b5ecac75
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 06 18:18:00 2015 +0100
+|  summary:     update download/Makefile.am
+|
+o  changeset:   3144:b6ce652f34d1
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 06 18:10:17 2015 +0100
+|  summary:     add install de hpddm ...
+|
+o  changeset:   3143:54b79f51069b
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 06 14:43:16 2015 +0100
+|  summary:     correct bad LIB_MPI in scotch
+|
+o  changeset:   3142:1faabfce37d3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 06 14:07:59 2015 +0100
+|  summary:     add no mandatoring lib in automatic lib search (WHERE-LIb search)
+|
+o  changeset:   3141:d7420bb1718d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 06 11:50:52 2015 +0100
+|  summary:     do lot of correction for new install version 3.24
+|
+o  changeset:   3140:ad567d1f75ac
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 05 21:40:31 2015 +0100
+|  summary:     correct acmpi for pb sgi mpicc
+|
+o  changeset:   3139:d2144a73ee94
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 05 09:47:20 2015 +0100
+|  summary:     correct problem when find c++11 version in configure
+|
+o  changeset:   3138:d777e1cc38d4
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 16:02:54 2015 +0100
+|  summary:     remove a madatory 3d test
+|
+o  changeset:   3137:ae6b05ca1182
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 15:49:33 2015 +0100
+|  summary:     continue coorect double free
+|
+o  changeset:   3136:d52565e53a04
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 15:01:45 2015 +0100
+|  summary:     correct pb 2 free in bamg
+|
+o  changeset:   3135:e2d7867ffd31
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 14:51:08 2015 +0100
+|  summary:     correct typo
+|
+o  changeset:   3134:e59974780d33
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 14:45:46 2015 +0100
+|  summary:     remove of pb of 2 free un bamg in case of crossing boundary
+|
+o  changeset:   3133:dfe9ee56d630
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 14:12:53 2015 +0100
+|  summary:     change for c++-11 and hdf5 with g++-4.9.1
+|
+o  changeset:   3132:d7e83d234408
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 09:59:26 2015 +0100
+|  summary:     correct jn call for c++11
+|
+o  changeset:   3131:c1663877ad52
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 30 09:57:04 2015 +0100
+|  summary:     coorect pow of c++-11 compiler
+|
+o  changeset:   3130:e1174bba7a16
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 29 10:31:52 2015 +0100
+|  summary:     coorect pb with pclose call
+|
+o  changeset:   3129:1af654663cff
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 29 10:01:11 2015 +0100
+|  summary:     add correct of pb compilation undec g++ 4.8.1 c++-11
+|
+o  changeset:   3128:084f6138edba
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 16 21:10:43 2015 +0100
+|  summary:     add schwarz.edp and add AutoGeneratedFile.tar.gz
+|
+o  changeset:   3127:4edf8d6dd064
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 16 21:05:34 2015 +0100
+|  summary:     cadd schwarz.edp test
+|
+o  changeset:   3126:40891f8e170d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 16 20:39:09 2015 +0100
+|  summary:     correct configure.ac to compile plugin schwarz with PETSc
+|
+o  changeset:   3125:397a0e0b089f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jan 16 17:16:29 2015 +0100
+|  summary:     add petsc in configure (first test)
+|
+o  changeset:   3124:695d108081da
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 16:54:43 2015 +0100
+|  summary:     correct pb compile e new schwarz pluging
+|
+o  changeset:   3123:84eadda9ec1e
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 15:55:21 2015 +0100
+|  summary:     add schwarz interface
+|
+o  changeset:   3122:fb3f97e0b7ad
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 15:25:14 2015 +0100
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   3121:4e9df821cdd8
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 15:24:15 2015 +0100
+|  summary:     add new cpu type on apple
+|
+o  changeset:   3120:18f455b5dd91
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 15:14:33 2015 +0100
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   3119:f2a508d27a6d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 15:12:02 2015 +0100
+|  summary:     add cxx11 chech
+|
+o  changeset:   3118:89604c8d20bb
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 11:04:51 2015 +0100
+|  summary:     correct build/download to follow link in case of curl usage..
+|
+o  changeset:   3117:1356c66b9164
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jan 15 08:22:32 2015 +0100
+|  summary:     correct pb on depot
+|
+o  changeset:   3116:ed9ccb5032ff
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jan 13 22:49:44 2015 +0100
+|  summary:     coorect examples++-load/include dir construction
+|
+o  changeset:   3115:034691a4deff
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jan 13 22:34:43 2015 +0100
+|  summary:     correct reconstrion for examples++-load/include
+|
+o  changeset:   3114:c180b6d013fd
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jan 13 22:01:23 2015 +0100
+|  summary:     add missing file
+|
+o  changeset:   3113:ae32ce3d21c3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jan 13 21:31:46 2015 +0100
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   3112:3201f396e00c
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jan 13 21:30:17 2015 +0100
+|  summary:     correct src/bamg/Makefile.am for hdf5 tools
+|
+o  changeset:   3111:3cdca031639a
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jan 13 21:19:27 2015 +0100
+|  summary:     add missing file
+|
+o  changeset:   3110:cf15bbc40e87
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jan 13 21:08:20 2015 +0100
+|  summary:     add hd5 and xml stuff.
+|
+o  changeset:   3109:be503a9f1ff3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Dec 15 14:52:58 2014 +0100
+|  summary:     put modif un lg.ypp not in lg.tab.cpp
+|
+o  changeset:   3108:1f630ba53655
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Dec 15 14:17:33 2014 +0100
+|  summary:     add missing option in plot
+|
+o  changeset:   3107:77a71b1b2901
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sat Dec 13 21:14:08 2014 +0100
+|  summary:     correct memory leak
+|
+o  changeset:   3106:e18aa16a8edf
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sat Dec 13 14:53:47 2014 +0100
+|  summary:     correct typo for  c++11 >>
+|
+o  changeset:   3105:0094d2a7433d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Dec 12 20:53:16 2014 +0100
+|  summary:     rebuild AutoGeneratedFile.tar.gz and a P. Patch for
+|
+o  changeset:   3104:5d5d0f7cbcfc
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Dec 12 10:40:06 2014 +0100
+|  summary:     correct lot of memory leak in case of
+|
+o  changeset:   3103:e7c44e31bf18
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Dec 11 20:48:28 2014 +0100
+|  summary:     correct memory leack
+|
+o  changeset:   3102:768c07a126f7
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Dec 08 09:37:21 2014 +0100
+|  summary:     add file fore hpddm interface
+|
+o  changeset:   3101:fb9b853f36b3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Nov 28 13:43:55 2014 +0100
+|  summary:     correct ff_finalmize
+|
+o  changeset:   3100:b47f510056e4
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Nov 28 12:06:48 2014 +0100
+|  summary:     add function ff_finalize
+|
+o  changeset:   3099:913a0e471dca
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Nov 26 08:18:43 2014 +0100
+|  summary:     add missing files
+|
+o  changeset:   3098:78b5f9947030
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Nov 26 08:13:09 2014 +0100
+|  summary:     pass to version 3.33
+|
+o  changeset:   3097:492928d72946
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Nov 26 08:10:21 2014 +0100
+|  summary:     begin of PETSc integration
+|
+o  changeset:   3096:e5f2eccb8503
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Nov 14 23:03:05 2014 +0100
+|  summary:     correct bug in periodic B.C ( some time loop)
+|
+o  changeset:   3095:3ed7375fbf91
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Nov 14 09:12:19 2014 +0100
+|  summary:     remove debug call xxxx()
+|
+o  changeset:   3094:82be1c76fe42
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Nov 14 09:11:12 2014 +0100
+|  summary:     correct bug array growing behaves differently on Linux and Mac
+|
+o  changeset:   3093:eecf0e60f9f5
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Nov 12 16:28:08 2014 +0100
+|  summary:     add check on vol tet in readmesh3
+|
+o  changeset:   3092:fa4384bf86b4
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Nov 07 14:30:36 2014 +0100
+|  summary:     correct pb under window  in load.cpp (no dlerror)
+|
+o  changeset:   3091:0a4c31444a80
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Nov 04 10:58:24 2014 +0100
+|  summary:     correct    md5 code of OpenBlas.tar.gz
+|
+o  changeset:   3090:5da39542e29b
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Nov 03 21:46:43 2014 +0100
+|  summary:     Added tag 3.28 for changeset af4fbbef4ecd
+|
+o  changeset:   3089:02abe57a6937
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Nov 03 21:46:28 2014 +0100
+|  summary:     Added tag 3.27 for changeset 4c7506b5ac6c
+|
+o  changeset:   3088:641a8e0bee7c
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Nov 03 21:44:16 2014 +0100
+|  summary:     Added tag 3.29 for changeset d7efc421b561
+|
+o  changeset:   3087:acd6c3b0c193
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Nov 03 21:42:37 2014 +0100
+|  summary:     Added tag 3.32 for changeset d324bac28890
+|
+o  changeset:   3086:edda4017be2b
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Nov 03 21:40:19 2014 +0100
+|  summary:     Added tag 3.31-2 for changeset a7eb0c2116df
+|
+o  changeset:   3085:94b8a1970489
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Nov 03 21:39:58 2014 +0100
+|  summary:     Added tag 3.31-3 for changeset 4e164226411d
+|
+o  changeset:   3084:248ae9751459
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Oct 30 08:43:56 2014 +0100
+|  summary:     thanck to V. Huber  to take care of the verbosity level.
+|
+o  changeset:   3083:4ad6b556e1cb
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Oct 29 19:10:00 2014 +0100
+|  summary:     passversion  to 3.32-1
+|
+o  changeset:   3082:2047e74a7fd2
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Oct 29 19:05:50 2014 +0100
+|  summary:     a compuation of dx,dy in Element_PkEdge
+|
+o  changeset:   3081:39d9338aa60a
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Oct 29 17:10:40 2014 +0100
+|  summary:     coorect plugin
+|
+o  changeset:   3080:ab0bad526b7a
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Oct 22 11:47:55 2014 +0200
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   3079:adf7ec4e0148
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Oct 22 11:47:16 2014 +0200
+|  summary:     add correction of P. Jolivet.
+|
+o  changeset:   3078:d29757759e08
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Oct 20 21:30:08 2014 +0200
+|  summary:     add correct launchff++ add ++d parameter for debuggin
+|
+o  changeset:   3077:df774c8536bf
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Oct 17 10:54:18 2014 +0200
+|  summary:     update INNOVATION
+|
+o  changeset:   3076:9ad9343d75d5
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Oct 17 10:53:01 2014 +0200
+|  summary:     correct big big in memory manageemnt of sparse matrix Matrice_Creuse
+|
+o  changeset:   3075:7e28b3a59725
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Oct 16 22:42:59 2014 +0200
+|  summary:     correct pb of factorisation
+|
+o  changeset:   3074:a216bad8d511
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Oct 16 22:39:31 2014 +0200
+|  summary:     correct type add remove file
+|
+o  changeset:   3073:89d2902eadca
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Oct 16 22:36:24 2014 +0200
+|  summary:     correct typo and remove test ..
+|
+o  changeset:   3072:d4af5fcecb25
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Oct 16 18:30:25 2014 +0200
+|  summary:     add check \ escape on string  "\z" -> z "\\" -> \ "\"" -> "
+|
+o  changeset:   3071:d324bac28890
+|  tag:         3.32
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Oct 16 16:33:01 2014 +0200
+|  summary:     coorect size on arrow  in plot ..
+|
+o  changeset:   3070:50157156eec4
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Oct 01 16:14:50 2014 +0200
+|  summary:     correct PARDISO / omp interface un uv100
+|
+o  changeset:   3069:828f65161d32
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 17:23:35 2014 +0200
+|  summary:     coorect type in parms interface
+|
+o  changeset:   3068:8d8432eea0df
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 17:01:19 2014 +0200
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   3067:0bffd0452ab7
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 16:58:05 2014 +0200
+|  summary:     add MUMPS plugin as MUMPS_seq plug without mpi
+|
+o  changeset:   3066:defe4e954307
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 16:50:45 2014 +0200
+|  summary:     update getall for davis web site change
+|
+o  changeset:   3065:15f28ab62c85
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 16:00:57 2014 +0200
+|  summary:     update getall ofr change SuiteSparse change web site.
+|
+o  changeset:   3064:ec7869984007
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 15:16:41 2014 +0200
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   3063:3086bae92306
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 15:15:30 2014 +0200
+|  summary:     correct environment.cpp and Makefile.am to find and put plugin for mpi
+|
+o  changeset:   3062:1dfbc3cec7ed
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 13:57:17 2014 +0200
+|  summary:     clean return value of /clean_all_installed_ffpp.sh for mac installer
+|
+o  changeset:   3061:5f22bdd00e0e
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 13:51:01 2014 +0200
+|  summary:     add missing chaneg
+|
+o  changeset:   3060:3e57363e9da8
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 13:49:36 2014 +0200
+|  summary:     next step  for mpi plugin
+|
+o  changeset:   3059:8a87f28ed7f5
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Sep 16 11:22:47 2014 +0200
+|  summary:     correct MUMPS plugin  complex version
+|
+o  changeset:   3058:2d9d48374ec8
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Sep 01 14:48:27 2014 +0200
+|  summary:     add vectoral operator line v/a (resp.  a/v-  == v_i/a (resp. a/v_i)
+|
+o  changeset:   3057:e471d8a2ae32
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Aug 26 11:45:47 2014 +0200
+|  summary:     missing file in distribution.
+|
+o  changeset:   3056:d9e53bbab3af
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Aug 25 17:23:15 2014 +0200
+|  summary:     crrect pb in chech un window
+|
+o  changeset:   3055:f302c03c8ae7
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Aug 25 16:36:06 2014 +0200
+|  summary:     coorect a bug in buildlayer in case of 0  edge on border...
+|
+o  changeset:   3054:d23ac6140622
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sat Aug 23 08:08:30 2014 +0200
+|  summary:     pass to ersion 3.31-3
+|
+o  changeset:   3053:4e164226411d
+|  tag:         3.31-3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Aug 12 23:19:52 2014 +0200
+|  summary:     coorect of array size in plot
+|
+o  changeset:   3052:a7eb0c2116df
+|  tag:         3.31-2
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jul 11 21:17:26 2014 +0200
+|  summary:     correct iter in stop function in CG
+|
+o  changeset:   3051:d267356f183c
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Jul 11 14:57:05 2014 +0200
+|  summary:     add script for installation
+|
+o  changeset:   3050:e63d8e10315a
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 22:32:46 2014 +0200
+|  summary:     chech !!
+|
+o  changeset:   3049:3a79062ffe5c
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 22:25:07 2014 +0200
+|  summary:     coorect typo
+|
+o  changeset:   3048:402527913245
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 22:23:35 2014 +0200
+|  summary:     add missing file
+|
+o  changeset:   3047:4b5c501566f6
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 22:00:44 2014 +0200
+|  summary:     update INNOVATION
+|
+o  changeset:   3046:5705d48950bd
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 21:45:46 2014 +0200
+|  summary:     correct pb ConjuguedGradient introduct this afternoon (kprint==0)
+|
+o  changeset:   3045:d3f01b55f65d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 21:23:36 2014 +0200
+|  summary:     correct bug put in DG formulation (rev 3044)
+|
+o  changeset:   3044:010dd06d2876
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 16:59:09 2014 +0200
+|  summary:     remove template initialisation of stopgc ..
+|
+o  changeset:   3043:27a77d0f60c9
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 10:45:24 2014 +0200
+|  summary:     pass to version 3.31-1
+|
+o  changeset:   3042:00d0f665141f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 10 10:41:50 2014 +0200
+|  summary:     add stop function for adapted test ... si doc and iNNVATION file
+|
+o  changeset:   3041:074b99969ce5
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jul 09 16:31:08 2014 +0200
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   3040:5a06d3054622
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jul 09 16:30:03 2014 +0200
+|  summary:     correct problem whitc zdotc  on MacOS
+|
+o  changeset:   3039:ae09f5411c83
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jul 09 09:10:01 2014 +0200
+|  summary:     update INNOVATION
+|
+o  changeset:   3038:3eab3ae21140
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jul 09 08:22:07 2014 +0200
+|  summary:     add function matricx for eigein value
+|
+o  changeset:   3037:794839c2a7cd
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 03 18:57:21 2014 +0200
+|  summary:     end of corecttion of LinearGMRES and AffineGMREs
+|
+o  changeset:   3036:371512bac93d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jul 03 13:00:34 2014 +0200
+|  summary:     correct a big big in LinearGMRES (thank to franco at us.es)
+|
+o  changeset:   3035:b412d75b60bd
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jul 02 10:39:35 2014 +0200
+|  summary:     add missing plugin in MeshSurface.idp
+|
+o  changeset:   3034:0888dfd0dc61
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jul 02 10:31:04 2014 +0200
+|  summary:     correct typo
+|
+o  changeset:   3033:bb189e3f0ea3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jul 02 10:29:53 2014 +0200
+|  summary:     correct misstake  in examples++-3d/MeshSurface.idp
+|
+o  changeset:   3032:1e34d36052ec
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jul 01 19:19:48 2014 +0200
+|  summary:     add '=' for pickinhg on macos on medit..
+|
+o  changeset:   3031:aadbdf882d72
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jul 01 18:30:28 2014 +0200
+|  summary:     correct getall add -h parameter ...
+|
+o  changeset:   3030:dbde96404949
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Jul 01 15:23:05 2014 +0200
+|  summary:     add '=' in medit for picking on mac..
+|
+o  changeset:   3029:ff74fea8d8e7
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Jun 30 10:03:47 2014 +0200
+|  summary:     correct bug in jump in case 1d problem
+|
+o  changeset:   3028:96d648cf5661
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sun Jun 29 22:39:20 2014 +0200
+|  summary:     coorect bug in change in DG matrice construction in case periodic
+|
+o  changeset:   3027:28131940d86b
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Jun 26 11:48:52 2014 +0200
+|  summary:     add new example of C1 approximation witn HCT ...
+|
+o  changeset:   3026:b468fda53b82
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jun 25 18:42:56 2014 +0200
+|  summary:     correct pb with freefem++-nw know no graphic).
+|
+o  changeset:   3025:c9f9ed1fd403
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jun 18 22:01:26 2014 +0200
+|  summary:     correct PARDISO.cpp to compile on Mac.
+|
+o  changeset:   3024:c9ebcf863ae0
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jun 18 21:48:29 2014 +0200
+|  summary:     correct error in gsl.edp
+|
+o  changeset:   3023:fe129f0a04a7
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jun 18 21:19:06 2014 +0200
+|  summary:     correct Makefine.am
+|
+o  changeset:   3022:fe328b42b0bf
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jun 18 21:13:42 2014 +0200
+|  summary:     correct typo (missing ; )
+|
+o  changeset:   3021:796a520a31f6
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jun 18 21:09:55 2014 +0200
+|  summary:     correct INNOVATION.
+|
+o  changeset:   3020:09dd923712b9
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Jun 18 21:07:28 2014 +0200
+|  summary:     add new plugin to make some binary io, will be
+|
+o  changeset:   3019:ff55bb4a608f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri May 16 13:53:06 2014 +0200
+|  summary:     try correct comile pb on UV100
+|
+o  changeset:   3018:9c600978774d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri May 16 13:37:51 2014 +0200
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   3017:2952e5f96558
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri May 16 12:46:05 2014 +0200
+|  summary:     add levelset integral and pass to version 3.30-1  in 3d
+|
+o  changeset:   3016:07b402a63c90
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed May 07 21:21:05 2014 +0200
+|  summary:     correct pb in BEC plugin ( function denpendint of x,y,z point ..
+|
+o  changeset:   3015:1aea517bacce
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed May 07 16:14:10 2014 +0200
+|  summary:     add new plugins for BEC
+|
+o  changeset:   3014:ba2508484995
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Apr 28 14:50:11 2014 +0200
+|  summary:     remove spurioux cout in ffglut (00)
+|
+o  changeset:   3013:bdf2b6da5050
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 10:29:07 2014 +0200
+|  summary:     add binary mode file type
+|
+o  changeset:   3012:525001ac8cfc
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 09:30:04 2014 +0200
+|  summary:     add rev in innovation
+|
+o  changeset:   3011:59412345af2f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 09:28:09 2014 +0200
+|  summary:     remove DEBUG print to find a bug in examples++-tutorial/periodic4.edp
+|
+o  changeset:   3010:0aef24b50bbc
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 01:41:01 2014 +0200
+|  summary:     correct typo
+|
+o  changeset:   3009:127d0bf1147d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 01:35:04 2014 +0200
+|  summary:     add dump
+|
+o  changeset:   3008:dd22333aaf2a
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 01:25:38 2014 +0200
+|  summary:     next
+|
+o  changeset:   3007:f0183dc26132
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 01:13:09 2014 +0200
+|  summary:     correct type in dump
+|
+o  changeset:   3006:178ac8a66957
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 01:11:06 2014 +0200
+|  summary:     add dump
+|
+o  changeset:   3005:2d95c7cc3a39
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Apr 24 01:02:10 2014 +0200
+|  summary:     add bug in Builmesh.
+|
+o  changeset:   3004:f445e1459c72
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Apr 23 17:30:18 2014 +0200
+|  summary:     version of the distribution 3.30
+|
+o  changeset:   3003:ed040aa51a0a
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Apr 23 16:56:47 2014 +0200
+|  summary:     coorect type in doc zero ->  two in def of nTonEdge
+|
+o  changeset:   3002:d3e4511ca0d7
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Apr 23 16:33:00 2014 +0200
+|  summary:     correct DOC version
+|
+o  changeset:   3001:10f137760625
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Apr 23 16:29:23 2014 +0200
+|  summary:     update the doc for multy border ...
+|
+o  changeset:   3000:c9a1eac26e35
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Apr 23 14:34:58 2014 +0200
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   2999:ab3683b70e74
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Apr 23 14:33:22 2014 +0200
+|  summary:     add multy border , past to version 3.30 ..
+|
+o  changeset:   2998:b7cb347b18f3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Apr 22 23:11:38 2014 +0200
+|  summary:     avant un multy border and comment the test .. in mesh.edp
+|
+o  changeset:   2997:03fb3a6a9894
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Apr 22 16:53:26 2014 +0200
+|  summary:     coorect pb of free not alloc pionter in mmg3d4-0
+|
+o  changeset:   2996:6958d44d16e8
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Apr 11 15:15:07 2014 +0200
+|  summary:     remove cout in RT1 2d Finite elemnt
+|
+o  changeset:   2995:57603195ad5d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Apr 09 08:50:57 2014 +0100
+|  summary:     add tools for Quadrature formular.
+|
+o  changeset:   2994:281a9fa7e47e
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 26 09:00:43 2014 +0100
+|  summary:     remove crazy output in lapack.cpp and fflapack.cpp
+|
+o  changeset:   2993:46fd913b30cf
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Mar 24 15:08:45 2014 +0100
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   2992:2036c6a948fd
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 21 18:39:08 2014 +0100
+|  summary:     add tools for integrale with levelset (under ) in 2d ..
+|
+o  changeset:   2991:7ded401a2b84
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 20 15:12:23 2014 +0100
+|  summary:     remve double def of R in P1IsoValue.cpp
+|
+o  changeset:   2990:555bf81333d6
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Mar 17 09:27:01 2014 +0100
+|  summary:     add tool to compute volume under levelset arealevelset , volumelevelset
+|
+o  changeset:   2989:935cf6997964
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Mar 17 09:21:26 2014 +0100
+|  summary:     add tools of mesure doamine def by levelset
+|
+o  changeset:   2988:e898b08ccf2f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 14 17:36:59 2014 +0100
+|  summary:     correct mistake in include  P1IsoValue.hpp
+|
+o  changeset:   2987:a7813b0a1b9b
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 14 17:23:34 2014 +0100
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   2986:69fe85e411a0
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 14 11:19:22 2014 +0100
+|  summary:     try empty matrix in MUMPS => dono works ..
+|
+o  changeset:   2985:03b6d8003a47
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 14 11:09:15 2014 +0100
+|  summary:     put empty matrix in set if need
+|
+o  changeset:   2984:9afbc88823c8
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 14 10:33:44 2014 +0100
+|  summary:     correct mistake in MUMPS.cpp (plugin)
+|
+o  changeset:   2983:2e43d499a8b3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 12 15:45:02 2014 +0100
+|  summary:     update rev innovatiop
+|
+o  changeset:   2982:5433ef595dd2
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 12 15:43:56 2014 +0100
+|  summary:     coorect type and memory mistake in fftime function
+|
+o  changeset:   2981:5cc256ed2a1b
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 12 15:12:16 2014 +0100
+|  summary:     add rev in INNOVATIOn
+|
+o  changeset:   2980:25666438652f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 12 15:10:46 2014 +0100
+|  summary:     add macro generation stuff like Stringification,FILE, LINE si INNIVATION,
+|
+o  changeset:   2979:35727886f469
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 12 08:50:41 2014 +0100
+|  summary:     add int on levelset for sym matrix,
+|
+o  changeset:   2978:057aed9a37d3
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Mar 11 21:16:20 2014 +0100
+|  summary:     rebuild include.tar.gz
+|
+o  changeset:   2977:f68fc8801d7c
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Mar 11 21:06:37 2014 +0100
+|  summary:     add tools to compute int on levelset
+|
+o  changeset:   2976:f6777db44f02
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Mar 11 21:04:37 2014 +0100
+|  summary:     add tool to compute int on levelset
+|
+o  changeset:   2975:2384ccefae8e
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 07 13:40:31 2014 +0100
+|  summary:     add bace cube function .
+|
+o  changeset:   2974:9b8b469c4f18
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Mar 07 11:52:08 2014 +0100
+|  summary:     update INNIVATION
+|
+o  changeset:   2973:d7efc421b561
+|  tag:         3.29
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 06 17:01:11 2014 +0100
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   2972:566f7ef75969
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 06 16:54:04 2014 +0100
+|  summary:     coorect type compilepkg in arpack makefile
+|
+o  changeset:   2971:51d803f66704
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 06 16:07:42 2014 +0100
+|  summary:     coorect problem we getall script
+|
+o  changeset:   2970:be94e3caaa45
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 06 12:11:29 2014 +0100
+|  summary:     coorect install pb in linux for next distribution
+|
+o  changeset:   2969:605daf8c95fd
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 06 11:00:15 2014 +0100
+|  summary:     missing file in dist lgmesh.hpp
+|
+o  changeset:   2968:846a6a5f1192
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 06 09:54:54 2014 +0100
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   2967:d95584630180
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Mar 06 09:53:23 2014 +0100
+|  summary:     correct make dist target in blas ...
+|
+o  changeset:   2966:094e01f7c642
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 19:26:11 2014 +0100
+|  summary:     coorect pb of recomple mmg3d if the patch change
+|
+o  changeset:   2965:a209379da038
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 18:45:23 2014 +0100
+|  summary:     leak mmg3d next step
+|
+o  changeset:   2964:e6f8ef801100
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 18:19:57 2014 +0100
+|  summary:     try memory leal mmg3d v4
+|
+o  changeset:   2963:e342d40ce4dd
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 15:40:39 2014 +0100
+|  summary:     coorect mshmet leak memory problem
+|
+o  changeset:   2962:6d042cb544d6
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 13:29:09 2014 +0100
+|  summary:     correct typo
+|
+o  changeset:   2961:52a5fe2df2b2
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 13:17:57 2014 +0100
+|  summary:     build AutoGeneratedFile.tar.gz
+|
+o  changeset:   2960:66c20b1178c9
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 13:17:25 2014 +0100
+|  summary:     add stuff  of get memory storage info on mac and linux
+|
+o  changeset:   2959:c3e4ab8a0afa
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 11:13:33 2014 +0100
+|  summary:     correct mshmet dependec
+|
+o  changeset:   2958:cab0cb8d1f99
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 11:10:13 2014 +0100
+|  summary:     correct typo error
+|
+o  changeset:   2957:82ad0bd4632f
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Mar 05 11:06:15 2014 +0100
+|  summary:     add tool to find memery leak storageused function ..
+|
+o  changeset:   2956:a39fe4a9f5b6
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Mon Mar 03 23:44:35 2014 +0100
+|  summary:     correct memory leak in mshmet inferface
+|
+o  changeset:   2955:5628f1212fad
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sun Mar 02 21:45:36 2014 +0100
+|  summary:     rebuild  AutoGeneratedFile.tar.gz
+|
+o  changeset:   2954:a778070d5256
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sun Mar 02 21:36:21 2014 +0100
+|  summary:     add uninstall-ff++ script freefem++
+|
+o  changeset:   2953:6f5b01300095
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sun Mar 02 21:16:32 2014 +0100
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   2952:2f5eebee8e67
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Sun Mar 02 21:12:13 2014 +0100
+|  summary:     correct pb in evalution jump of region number
+|
+o  changeset:   2951:f1064e46586e
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Tue Feb 18 14:35:10 2014 +0100
+|  summary:     change error in warning in message error if missing library.
+|
+o  changeset:   2950:cba75b251d6d
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 13 10:55:31 2014 +0100
+|  summary:     correct in 2d integral on levelset of bilinear form
+|
+o  changeset:   2949:8762a49602b5
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Feb 12 18:45:43 2014 +0100
+|  summary:     coorect type in getall
+|
+o  changeset:   2948:10d76bbc862e
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Feb 12 18:39:26 2014 +0100
+|  summary:     make getall with or without thread depending of pearl install
+|
+o  changeset:   2947:934199f05868
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Wed Feb 12 11:26:56 2014 +0100
+|  summary:     rebuild AutoGeneratedFile.tar.gz
+|
+o  changeset:   2946:e0c1f8669ab4
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Fri Feb 07 13:33:03 2014 +0100
+|  summary:     update configure param to compile
+|
+o  changeset:   2945:6f9c41b5a9b1
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 06 22:38:38 2014 +0100
+|  summary:     coorecct readme
+|
+o  changeset:   2944:af4fbbef4ecd
+|  tag:         3.28
+|  parent:      2937:4c7506b5ac6c
+|  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+|  date:        Thu Feb 06 22:30:35 2014 +0100
+|  summary:     correct small bug in
+|
+| o  changeset:   2943:0aa8d880b527
+| |  branch:      alh-dev
+| |  user:        Antoine Le Hyaric
+| |  date:        Thu Feb 06 14:42:15 2014 +0100
+| |  summary:     partial commit on DebianTesting64 (odyssee)
+| |
+| o  changeset:   2942:6ff7e589dcaa
+| |  branch:      alh-dev
+| |  user:        Antoine Le Hyaric
+| |  date:        Wed Feb 05 18:01:38 2014 +0100
+| |  summary:     partial commit on DebianTesting64 (odyssee)
+| |
+| o  changeset:   2941:93032418cfc8
+| |  branch:      alh-dev
+| |  user:        Antoine Le Hyaric
+| |  date:        Tue Feb 04 18:56:55 2014 +0100
+| |  summary:     partial commit on DebianTesting64 (odyssee)
+| |
+| o  changeset:   2940:872c489a2867
+| |  branch:      alh-dev
+| |  user:        Antoine Le Hyaric
+| |  date:        Tue Feb 04 15:53:20 2014 +0100
+| |  summary:     partial commit on DebianTesting64 (odyssee)
+| |
+| o  changeset:   2939:1bc50b3ba773
+| |  branch:      alh-dev
+| |  user:        Antoine Le Hyaric
+| |  date:        Wed Jan 29 18:17:45 2014 +0100
+| |  summary:     >  - New script build/orgindex and file index.org to list all hyperlinks in the FF source in Emacs org-mode format
+| |
+| o  changeset:   2938:e78417933ae1
+| |  branch:      alh-dev
+| |  parent:      2935:72d03e2de866
+| |  user:        Antoine Le Hyaric
+| |  date:        Wed Jan 29 17:25:13 2014 +0100
+| |  summary:     partial commit on DebianTesting64 (odyssee)
+| |
+o |    changeset:   2937:4c7506b5ac6c
+|\ \   tag:         3.27
+| | |  parent:      2936:37691b670f5a
+| | |  parent:      2885:d58dea64f3a0
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Thu Feb 06 14:41:59 2014 +0100
+| | |  summary:     Synchronizing FH and ALH trees
+| | |
+| o |    changeset:   2936:37691b670f5a
+| |\ \   parent:      2934:2cc59dc4712c
+| | | |  parent:      2875:338cb00eff86
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Tue Jan 28 16:26:27 2014 +0100
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+| | | o  changeset:   2935:72d03e2de866
+| | | |  branch:      alh-dev
+| | | |  parent:      2932:6dc37a6b1b61
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Jan 23 12:21:33 2014 +0100
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+| | o |  changeset:   2934:2cc59dc4712c
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Tue Jan 21 16:53:17 2014 +0100
+| | | |  summary:     partial commit on MacOS108 (athena)
+| | | |
+| | o |  changeset:   2933:d0779fbd3270
+| | | |  parent:      2927:05728123cfdd
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Tue Jan 21 16:26:29 2014 +0100
+| | | |  summary:     partial commit on MacOS108 (athena)
+| | | |
+| | | o  changeset:   2932:6dc37a6b1b61
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Jan 09 14:17:02 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | | o  changeset:   2931:3f84037c3f82
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Jan 09 10:45:30 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | | o  changeset:   2930:aef9c00fa974
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Jan 09 10:42:48 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | | o  changeset:   2929:109fbfe6ae46
+| | |/|  branch:      alh-dev
+| | | |  parent:      2928:5ff83fb295b9
+| | | |  parent:      2927:05728123cfdd
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Jan 09 10:37:20 2014 +0100
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+| | | o    changeset:   2928:5ff83fb295b9
+| | | |\   branch:      alh-dev
+| | | | |  parent:      2902:9f9543a57c4a
+| | | | |  parent:      2903:e7454fa79801
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Mon Jan 06 17:18:43 2014 +0100
+| | | | |  summary:     New FFCS version 14.1 using FF 3.26-3
+| | | | |
+| | o | |  changeset:   2927:05728123cfdd
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jan 08 11:49:43 2014 +0100
+| | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | |
+| | o | |  changeset:   2926:6e8b8dee3c7d
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jan 08 11:47:45 2014 +0100
+| | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | |
+| | o | |  changeset:   2925:991bc3308e91
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jan 08 11:42:40 2014 +0100
+| | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | |
+| | o | |  changeset:   2924:731c6e6f7f12
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jan 08 11:30:20 2014 +0100
+| | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | |
+| | o | |  changeset:   2923:b87e6117d8e4
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jan 08 11:28:37 2014 +0100
+| | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | |
+| | o | |    changeset:   2922:d108089c7f41
+| | |\ \ \   parent:      2921:12aa8decef61
+| | | | | |  parent:      2920:b025c2cf1fc0
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 11:09:37 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | | o | |  changeset:   2921:12aa8decef61
+| | | | | |  parent:      2917:e54ad4c7dbb5
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 11:09:36 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | o | | |    changeset:   2920:b025c2cf1fc0
+| | |\ \ \ \   parent:      2918:44aca5b00458
+| | | | | | |  parent:      2919:ad120e12b53c
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Wed Jan 08 11:08:00 2014 +0100
+| | | | | | |  summary:     partial commit on DebianTesting32 (buis)
+| | | | | | |
+| | | o | | |  changeset:   2919:ad120e12b53c
+| | | | | | |  parent:      2908:ecd21a3c9519
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Tue Jan 07 16:41:24 2014 +0100
+| | | | | | |  summary:     Compiling FFCS on Windows 64
+| | | | | | |
+| | o---+ | |  changeset:   2918:44aca5b00458
+| |   | | | |  user:        Antoine Le Hyaric
+| |  / / / /   date:        Wed Jan 08 11:07:57 2014 +0100
+| | | | | |    summary:     partial commit on DebianTesting32 (buis)
+| | | | | |
+| | | o | |  changeset:   2917:e54ad4c7dbb5
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 11:02:32 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | | o | |  changeset:   2916:9a46b1c26db3
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 11:00:32 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | | o | |  changeset:   2915:7561672695dd
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 10:59:10 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | | o | |  changeset:   2914:098107cd6199
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 10:56:56 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | | o | |  changeset:   2913:2e4fcaf138a5
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 10:52:19 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | | o | |  changeset:   2912:6916680747a7
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 10:47:23 2014 +0100
+| | | | | |  summary:     partial commit on Ubuntu1310-64 (ubu64)
+| | | | | |
+| | | o | |  changeset:   2911:866837b2af36
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 10:36:45 2014 +0100
+| | | | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | | | |
+| | | o | |  changeset:   2910:ef54830cf6ca
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jan 08 10:20:13 2014 +0100
+| | | | | |  summary:     Small updates for FFCS release
+| | | | | |
+| | | o | |  changeset:   2909:56d37abf1f91
+| | |/ / /   user:        Antoine Le Hyaric
+| | | | |    date:        Wed Jan 08 10:00:39 2014 +0100
+| | | | |    summary:     Small changing for FFCS compilation on Windows
+| | | | |
+| | o | |  changeset:   2908:ecd21a3c9519
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jan 07 15:05:11 2014 +0100
+| | | | |  summary:     Compiling FFCS on Windows 64
+| | | | |
+| | o | |  changeset:   2907:1ffe24c32b72
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jan 07 12:42:39 2014 +0100
+| | | | |  summary:     Compiling FFCS on Windows 64
+| | | | |
+| | o | |  changeset:   2906:39530b797474
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jan 07 12:34:17 2014 +0100
+| | | | |  summary:     Compiling FFCS on Windows 64
+| | | | |
+| | o | |  changeset:   2905:f800a6ab9788
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jan 07 09:03:23 2014 +0100
+| | | | |  summary:     Making FF compile with FFCS on Win32
+| | | | |
+| | o---+  changeset:   2904:fcdbf0cf5077
+| |   | |  user:        Antoine Le Hyaric
+| |  / /   date:        Mon Jan 06 17:21:07 2014 +0100
+| | | |    summary:     New FFCS version 14.1 using FF 3.26-3
+| | | |
+| | | o  changeset:   2903:e7454fa79801
+| | |/|  parent:      2873:5ea92a62899b
+| | | |  parent:      2902:9f9543a57c4a
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 17:17:08 2014 +0100
+| | | |  summary:     New FFCS version 14.1 using FF 3.26-3
+| | | |
+| | o |  changeset:   2902:9f9543a57c4a
+| | |\|  branch:      alh-dev
+| | | |  parent:      2901:b2c810edffc4
+| | | |  parent:      2873:5ea92a62899b
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 17:00:36 2014 +0100
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+| | o |  changeset:   2901:b2c810edffc4
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 16:59:33 2014 +0100
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+| | o |  changeset:   2900:d174317ebdb4
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 16:52:56 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | o |  changeset:   2899:fd9ac165cadb
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 15:38:04 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | o |  changeset:   2898:37cc9b9aa118
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 15:28:15 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | o |  changeset:   2897:7c15fa116135
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 14:53:49 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | o |  changeset:   2896:138744674c16
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 14:21:11 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | o |  changeset:   2895:a3105d01c462
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 12:35:35 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | o |  changeset:   2894:d5934c1a6b78
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Jan 06 12:11:05 2014 +0100
+| | | |  summary:     partial commit on Windows (telemos)
+| | | |
+| | o |    changeset:   2893:3d92537460f0
+| | |\ \   branch:      alh-dev
+| | | | |  parent:      2892:80c7cc90e5ed
+| | | | |  parent:      2890:741de2d14d63
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Thu Dec 19 16:04:58 2013 +0100
+| | | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | | |
+| | | o |  changeset:   2892:80c7cc90e5ed
+| | | | |  branch:      alh-dev
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Thu Dec 19 12:03:48 2013 +0100
+| | | | |  summary:     Incorporating changes from FH (default branch) into ALH developments (alh-dev branch)
+| | | | |
+| | | o |    changeset:   2891:707584572e06
+| | | |\ \   branch:      alh-dev
+| | | | | |  parent:      2888:9c4bf400b221
+| | | | | |  parent:      2864:b110654707d1
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Dec 19 12:00:24 2013 +0100
+| | | | | |  summary:     Incorporating changes from FH (default branch) into ALH developments (alh-dev branch)
+| | | | | |
+| | o---+ |  changeset:   2890:741de2d14d63
+| | | | | |  branch:      alh-dev
+| | | | | |  parent:      2889:098e8bb04f23
+| | | | | |  parent:      2888:9c4bf400b221
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Dec 18 17:16:03 2013 +0100
+| | | | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | | | |
+| | o | | |  changeset:   2889:098e8bb04f23
+| | | | | |  branch:      alh-dev
+| | | | | |  parent:      2887:54388cb94ac9
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Dec 04 17:53:19 2013 +0100
+| | | | | |  summary:     partial commit on DebianTesting64 (caen)
+| | | | | |
+| | +---o |  changeset:   2888:9c4bf400b221
+| | | |  /   branch:      alh-dev
+| | | | |    user:        Antoine Le Hyaric
+| | | | |    date:        Wed Dec 18 16:18:08 2013 +0100
+| | | | |    summary:     partial commit on DebianTesting64 (odyssee)
+| | | | |
+| | o | |  changeset:   2887:54388cb94ac9
+| | | | |  branch:      alh-dev
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Thu Nov 28 16:29:19 2013 +0100
+| | | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | | |
+| | o | |  changeset:   2886:248f4bd285d0
+| | | | |  branch:      alh-dev
+| | | | |  parent:      2829:4ab97def6ad1
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Nov 27 15:14:05 2013 +0100
+| | | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | | |
+o | | | |  changeset:   2885:d58dea64f3a0
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Feb 05 22:18:08 2014 +0100
+| | | | |  summary:     add AddLayers in 3d
+| | | | |
+o | | | |  changeset:   2884:5d1fa9c3c817
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Feb 05 22:01:56 2014 +0100
+| | | | |  summary:     correct AddLayers
+| | | | |
+o | | | |  changeset:   2883:2cf6464d0761
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Feb 05 09:35:50 2014 +0100
+| | | | |  summary:     at init of full matrix this inverse matrix.
+| | | | |
+o | | | |  changeset:   2882:d0965d6036fc
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Feb 02 20:46:22 2014 +0100
+| | | | |  summary:     rebuild AutoGeneratedFile.tar.gz
+| | | | |
+o | | | |  changeset:   2881:4b6af956b8f8
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Feb 02 20:36:02 2014 +0100
+| | | | |  summary:     correct SplitMesh<R3> function in case of P1b3d display.
+| | | | |
+o | | | |  changeset:   2880:11edbb125bdc
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 29 11:37:27 2014 +0100
+| | | | |  summary:     up AutoGeneratedFile.tar.gz
+| | | | |
+o | | | |  changeset:   2879:961332cb7ed2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 29 11:36:20 2014 +0100
+| | | | |  summary:     correct but in splitsimplex.cpp of P1b 3d case
+| | | | |
+o | | | |  changeset:   2878:87a9a56664ef
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Jan 26 21:41:07 2014 +0100
+| | | | |  summary:     add BuildLayer function i C++
+| | | | |
+o | | | |  changeset:   2877:398ffc82c686
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Jan 24 17:38:34 2014 +0100
+| | | | |  summary:     ajout pour P. jolivet de
+| | | | |
+o | | | |  changeset:   2876:798588c5e951
+|/ / / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |    date:        Thu Jan 16 14:46:52 2014 +0100
+| | | |    summary:     add hypot c function
+| | | |
+o | | |  changeset:   2875:338cb00eff86
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 09 10:45:56 2014 +0100
+| | | |  summary:     add remark in innovation file
+| | | |
+o-----+  changeset:   2874:7b9c53ac2372
+  | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+ / / /   date:        Thu Jan 09 10:44:01 2014 +0100
+| | |    summary:     add missing function in gsl
+| | |
+| | o  changeset:   2873:5ea92a62899b
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Dec 30 22:16:52 2013 +0100
+| | |  summary:     carrect install windows missing files
+| | |
+| | o  changeset:   2872:60ef1773b8b2
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Dec 30 22:01:47 2013 +0100
+| | |  summary:     correct WindowsPackage.m4
+| | |
+| | o  changeset:   2871:27002ba88a46
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Dec 30 17:06:52 2013 +0100
+| | |  summary:     rebuild AutoGeneratedFile.tar.gz
+| | |
+| | o  changeset:   2870:897793e4a7f6
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Dec 30 17:05:54 2013 +0100
+| | |  summary:     correct typo
+| | |
+| | o  changeset:   2869:0b17a2cf1ea6
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Dec 30 17:01:27 2013 +0100
+| | |  summary:     coorect typo
+| | |
+| | o  changeset:   2868:324f120c84cf
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Dec 30 16:56:38 2013 +0100
+| | |  summary:     update gsl interface  with random generator
+| | |
+| | o  changeset:   2867:ccccd77442c2
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Sun Dec 29 23:21:04 2013 +0100
+| | |  summary:     add random gsl generator
+| | |
+| | o  changeset:   2866:5fc3f1298263
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Sat Dec 28 18:20:31 2013 +0100
+| | |  summary:     correct doc and pthread on window version
+| | |
+| | o  changeset:   2865:adf0cca701c2
+| |/   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |    date:        Mon Dec 23 13:41:04 2013 +0100
+| |    summary:     correct mshmesh under window (no phthread lib)
+| |
+| o  changeset:   2864:b110654707d1
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Mon Dec 09 21:34:15 2013 +0100
+| |  summary:     correct pthread with  openblas
+| |
+| o  changeset:   2863:3464dead1c8e
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Mon Dec 09 21:32:58 2013 +0100
+| |  summary:     pass to version 3.26-3
+| |
+| o  changeset:   2862:067eda36460c
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Mon Dec 09 21:08:43 2013 +0100
+| |  summary:     correct link problem of ipopt and blas missing thread libray.
+| |
+| o  changeset:   2861:9818994f3093
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Fri Dec 06 09:43:42 2013 +0100
+| |  summary:     correct lapack interface and simplify the test.
+| |
+| o  changeset:   2860:00a25dfebd01
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Dec 04 10:14:50 2013 +0100
+| |  summary:     add new logo in the doc.
+| |
+| o  changeset:   2859:d1e3f4891a08
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Dec 04 09:56:44 2013 +0100
+| |  summary:     add warning=  flags adaptmesh know if the max numbre of vertiex is reach
+| |
+| o  changeset:   2858:7abc92ebe5ba
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Fri Nov 29 08:49:54 2013 +0100
+| |  summary:     correct examples++-mpi/Laplace3d-hips.edp
+| |
+| o  changeset:   2857:50d15c3910b7
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 28 15:32:42 2013 +0100
+| |  summary:     remove blas and lapack from WHERE-lIBRAY-download
+| |
+| o  changeset:   2856:60a5720c24d4
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 28 13:11:50 2013 +0100
+| |  summary:     correct pb with norm
+| |
+| o  changeset:   2855:b50b5a5a2336
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 28 11:15:05 2013 +0100
+| |  summary:     new version
+| |
+| o  changeset:   2854:2b5ed56c8b59
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 28 10:59:51 2013 +0100
+| |  summary:     correct bug in script ff-get-dep
+| |
+| o  changeset:   2853:a9464311ddea
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Fri Nov 22 11:03:29 2013 +0100
+| |  summary:     correct ff-get-dep.in
+| |
+| o  changeset:   2852:0592cece2ae9
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Fri Nov 22 10:03:12 2013 +0100
+| |  summary:     coorect typo
+| |
+| o  changeset:   2851:58552a27b112
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Fri Nov 22 09:57:01 2013 +0100
+| |  summary:     next correctioon
+| |
+| o  changeset:   2850:f1f45a267a78
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Fri Nov 22 09:54:21 2013 +0100
+| |  summary:     coorect ff-get-dep.in of simple bash shell
+| |
+| o  changeset:   2849:b13a07b5a6b5
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 21 21:31:19 2013 +0100
+| |  summary:     correct gnu.mak to rebuild pdf figure.
+| |
+| o  changeset:   2848:4743da3cb7d6
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 21:52:07 2013 +0100
+| |  summary:     correct typo
+| |
+| o  changeset:   2847:2fdfe47a6f56
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 21:29:22 2013 +0100
+| |  summary:     correct for install
+| |
+| o  changeset:   2846:30a72fb6ca8e
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 20:44:56 2013 +0100
+| |  summary:     correct ff-c++ install
+| |
+| o  changeset:   2845:12a1482c206f
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 20:38:01 2013 +0100
+| |  summary:     correct ff-c++ and install version
+| |
+| o  changeset:   2844:67fa6ca3d5dd
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 18:22:02 2013 +0100
+| |  summary:     add EXTRA_DIST= path openbals
+| |
+| o  changeset:   2843:07cefac0627d
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 16:21:30 2013 +0100
+| |  summary:     update INNOVATIO
+| |
+| o  changeset:   2842:18d0a28bc820
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 16:19:19 2013 +0100
+| |  summary:     reome all relative path in WHERE_LIBRARY-config
+| |
+| o  changeset:   2841:de838ce6aed7
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 15:58:13 2013 +0100
+| |  summary:     cooret PB SuperLU
+| |
+| o  changeset:   2840:89928d1720be
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 20 15:24:11 2013 +0100
+| |  summary:     coorect pb with superlu
+| |
+| o  changeset:   2839:7ed38d0c562b
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 14 07:22:12 2013 +0100
+| |  summary:     correct typo
+| |
+| o  changeset:   2838:49fb2b403572
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 14 07:08:12 2013 +0100
+| |  summary:     correct pb in complex number in MPICG.cpp
+| |
+| o  changeset:   2837:d705f85f99a8
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 14 06:56:09 2013 +0100
+| |  summary:     coorect after test on MacOS 10.9
+| |
+| o  changeset:   2836:12ab7a082206
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Thu Nov 14 00:11:18 2013 +0100
+| |  summary:     coorect Makefile fr dist
+| |
+| o  changeset:   2835:128efccbdbbe
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 13 23:39:13 2013 +0100
+| |  summary:     restored examples++-tutorial/Laplace.cpp
+| |
+| o  changeset:   2834:12fd7a715267
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 13 23:22:25 2013 +0100
+| |  summary:     update AutoGeneratedFile.tar.gz
+| |
+| o  changeset:   2833:3a5004ce04b1
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 13 23:15:38 2013 +0100
+| |  summary:     correct clean Makefile not remove pakage source.
+| |
+| o  changeset:   2832:3f8bd0dc0696
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 13 19:26:39 2013 +0100
+| |  summary:     correct some example ???
+| |
+| o  changeset:   2831:79ffacff401c
+| |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| |  date:        Wed Nov 13 17:41:08 2013 +0100
+| |  summary:     pass to version 3.26
+| |
+| o    changeset:   2830:769140b8b4b5
+| |\   parent:      2822:f0cf8e4172bc
+| | |  parent:      2779:cf1946212db2
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Wed Nov 13 17:39:07 2013 +0100
+| | |  summary:     merge with ALH version, and FH version
+| | |
+o | |  changeset:   2829:4ab97def6ad1
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Thu Nov 07 14:13:31 2013 +0100
+| | |  summary:     >  - Separate download script for all third-party software [[file:download/getall]] (request from FH)
+| | |
+o | |  changeset:   2828:12dd3edd272b
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Thu Oct 31 17:20:51 2013 +0100
+| | |  summary:     >  - Separate download script for all third-party software [[file:download/getall]], request from FH
+| | |
+o | |  changeset:   2827:f9e5c9cdde3c
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Tue Oct 29 09:16:31 2013 +0100
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o | |  changeset:   2826:7a9fc9218ecc
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Wed Oct 23 17:29:44 2013 +0200
+| | |  summary:     >  - Set all hyperlinks to relative paths to make sure that they work from any location
+| | |
+o | |  changeset:   2825:c213ac3c5ddd
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Wed Oct 23 15:30:46 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o---+  changeset:   2824:80b91b59d758
+| | |  branch:      alh-dev
+| | |  parent:      2823:ac72f4fd3cdf
+| | |  parent:      2822:f0cf8e4172bc
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Tue Oct 22 17:47:33 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o | |  changeset:   2823:ac72f4fd3cdf
+| | |  branch:      alh-dev
+| | |  parent:      2821:304b9771c959
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Mon Oct 21 12:14:40 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
++---o  changeset:   2822:f0cf8e4172bc
+| | |  parent:      2814:b788f2283f0a
+| | |  parent:      2821:304b9771c959
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Mon Oct 21 10:54:43 2013 +0200
+| | |  summary:     Keeping ALH and FH trees in sync
+| | |
+o | |  changeset:   2821:304b9771c959
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Mon Oct 21 10:46:00 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o | |  changeset:   2820:f2d70674e0cf
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Thu Oct 17 11:39:56 2013 +0200
+| | |  summary:     >   - split DOC makefiles into Makefile.am and figs.mak to suppress automake warnings about portability
+| | |
+o---+  changeset:   2819:690015709315
+| | |  branch:      alh-dev
+| | |  parent:      2818:fd43eb5d72fd
+| | |  parent:      2814:b788f2283f0a
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Tue Oct 15 15:16:49 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o | |  changeset:   2818:fd43eb5d72fd
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Tue Oct 15 14:57:20 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o | |  changeset:   2817:7231ea317c6b
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Tue Oct 15 09:38:31 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o | |  changeset:   2816:c82bafbc80ed
+| | |  branch:      alh-dev
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Mon Oct 14 15:48:32 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+o | |  changeset:   2815:8ee90b830900
+| | |  branch:      alh-dev
+| | |  parent:      2811:9fe8b47f26fe
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Tue Oct 08 16:50:41 2013 +0200
+| | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | |
+| | o  changeset:   2814:b788f2283f0a
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Mon Oct 14 10:33:16 2013 +0200
+| | |  summary:     changed FFCS Fortran MPI configuration for MPICH2
+| | |
+| | o    changeset:   2813:91392dc99aa0
+| | |\   parent:      2812:e39696d2e66f
+| | | |  parent:      2775:da720285cc20
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Tue Oct 08 10:50:59 2013 +0200
+| | | |  summary:     Keeping ALH and FH trees in sync
+| | | |
++-----o  changeset:   2812:e39696d2e66f
+| | | |  parent:      2782:eb4999ba4ff4
+| | | |  parent:      2811:9fe8b47f26fe
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Tue Oct 08 10:31:31 2013 +0200
+| | | |  summary:     FFCS version number increased to 13.15
+| | | |
+o | | |  changeset:   2811:9fe8b47f26fe
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Oct 02 16:59:53 2013 +0200
+| | | |  summary:     partial commit on MacOS108 (athena)
+| | | |
+o | | |  changeset:   2810:1b93d130a6f3
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Oct 02 16:21:37 2013 +0200
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+o | | |  changeset:   2809:0a1b9e514197
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Sep 30 18:09:43 2013 +0200
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+o | | |  changeset:   2808:92b03c315566
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Sep 25 12:01:34 2013 +0200
+| | | |  summary:     partial commit on Ubuntu1204-64 (ubults64)
+| | | |
+o | | |  changeset:   2807:c15cd2f03b68
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Sep 25 11:11:44 2013 +0200
+| | | |  summary:     >
+| | | |
+o | | |  changeset:   2806:9c3a101331c6
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Mon Sep 23 09:59:26 2013 +0200
+| | | |  summary:     partial commit on DebianTesting64 (odyssee)
+| | | |
+o | | |  changeset:   2805:f364768a91ad
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Sep 19 11:16:44 2013 +0200
+| | | |  summary:     partial commit on DebianTesting64 (iliade)
+| | | |
+o | | |  changeset:   2804:762acbe43ae9
+| | | |  branch:      alh-dev
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Sep 19 11:10:58 2013 +0200
+| | | |  summary:     partial commit on MacOS108 (athena)
+| | | |
+o | | |    changeset:   2803:384865ca600b
+|\ \ \ \   branch:      alh-dev
+| | | | |  parent:      2802:180cf95c3043
+| | | | |  parent:      2801:b4f662e97b98
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Thu Sep 19 11:00:21 2013 +0200
+| | | | |  summary:     partial commit on MacOS108 (athena)
+| | | | |
+| o | | |  changeset:   2802:180cf95c3043
+| | | | |  branch:      alh-dev
+| | | | |  parent:      2800:79c467416c58
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Thu Sep 19 11:00:19 2013 +0200
+| | | | |  summary:     partial commit on MacOS108 (athena)
+| | | | |
+o | | | |  changeset:   2801:b4f662e97b98
+|\| | | |  branch:      alh-dev
+| | | | |  parent:      2794:20715307bd51
+| | | | |  parent:      2800:79c467416c58
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Thu Sep 19 10:59:32 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting64 (iliade)
+| | | | |
+| o | | |    changeset:   2800:79c467416c58
+| |\ \ \ \   branch:      alh-dev
+| | | | | |  parent:      2799:880bc2986524
+| | | | | |  parent:      2793:da28c0b1be77
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Sep 19 10:51:05 2013 +0200
+| | | | | |  summary:     partial commit on MacOS108
+| | | | | |
+| | o | | |  changeset:   2799:880bc2986524
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Jul 25 14:44:53 2013 +0200
+| | | | | |  summary:     Small fixes for MacOS 10.8 compilation
+| | | | | |
+| | o | | |  changeset:   2798:318fde8763e3
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Jul 25 14:31:41 2013 +0200
+| | | | | |  summary:     Small fixes for pastix compilation on MacOS
+| | | | | |
+| | o | | |  changeset:   2797:c3e6d188dd64
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Jul 25 14:22:34 2013 +0200
+| | | | | |  summary:     Small fixes for pastix compilation on MacOS
+| | | | | |
+| | o | | |  changeset:   2796:72f90df8325c
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Jul 25 14:15:58 2013 +0200
+| | | | | |  summary:     Small fixes for pastix compilation on MacOS
+| | | | | |
+| | o | | |  changeset:   2795:b3a31b5e5e66
+| | | | | |  branch:      alh-dev
+| | | | | |  parent:      2732:2a814f7c0f1f
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Jul 25 14:06:15 2013 +0200
+| | | | | |  summary:     Small fixes for MacOS 10.8 compilation
+| | | | | |
+o | | | | |  changeset:   2794:20715307bd51
+|/ / / / /   branch:      alh-dev
+| | | | |    user:        Antoine Le Hyaric
+| | | | |    date:        Thu Sep 19 10:59:30 2013 +0200
+| | | | |    summary:     partial commit on DebianTesting64 (iliade)
+| | | | |
+o | | | |  changeset:   2793:da28c0b1be77
+| | | | |  branch:      alh-dev
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Sep 18 17:10:19 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting64
+| | | | |
+o | | | |  changeset:   2792:7847a84effee
+| | | | |  branch:      alh-dev
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Sep 18 14:38:49 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting64
+| | | | |
+o | | | |  changeset:   2791:99ff5d7f8b98
+| | | | |  branch:      alh-dev
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Sep 18 14:00:35 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting64
+| | | | |
+o | | | |  changeset:   2790:3a3125233c7a
+| | | | |  branch:      alh-dev
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Sep 17 18:24:30 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting64
+| | | | |
+o | | | |    changeset:   2789:b4393a12fe7f
+|\ \ \ \ \   branch:      alh-dev
+| | | | | |  parent:      2788:d9bb255ca068
+| | | | | |  parent:      2781:a0a0a2c0d990
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 17 12:33:26 2013 +0200
+| | | | | |  summary:     partial commit on DebianTesting64
+| | | | | |
+| o | | | |  changeset:   2788:d9bb255ca068
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 17 11:52:02 2013 +0200
+| | | | | |  summary:     partial commit on DebianTesting64
+| | | | | |
+| o | | | |    changeset:   2787:52cfe7abccc8
+| |\ \ \ \ \   branch:      alh-dev
+| | | | | | |  parent:      2784:f3d219682017
+| | | | | | |  parent:      2786:de558ef9e916
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Mon Sep 16 15:50:13 2013 +0200
+| | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | |
+| | o | | | |  changeset:   2786:de558ef9e916
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Mon Sep 16 15:37:42 2013 +0200
+| | | | | | |  summary:     partial commit on Ubuntu1304
+| | | | | | |
+| | o | | | |    changeset:   2785:e60e1b072fb5
+| | |\ \ \ \ \   branch:      alh-dev
+| | | | | | | |  parent:      2783:af7c913fea2f
+| | | | | | | |  parent:      2780:3aec73ae92a6
+| | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | |  date:        Mon Sep 16 14:27:46 2013 +0200
+| | | | | | | |  summary:     Merged FF default branch into alh-dev branch
+| | | | | | | |
+| o | | | | | |  changeset:   2784:f3d219682017
+| | | | | | | |  branch:      alh-dev
+| | | | | | | |  parent:      2763:f103190738d6
+| | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | |  date:        Mon Sep 16 15:50:11 2013 +0200
+| | | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | | |
+| +---o | | | |  changeset:   2783:af7c913fea2f
+| | |  / / / /   branch:      alh-dev
+| | | | | | |    parent:      2763:f103190738d6
+| | | | | | |    user:        Antoine Le Hyaric
+| | | | | | |    date:        Mon Sep 16 12:07:05 2013 +0200
+| | | | | | |    summary:     partial commit on DebianTesting32
+| | | | | | |
++-----------o  changeset:   2782:eb4999ba4ff4
+| | | | | |    user:        Antoine Le Hyaric
+| | | | | |    date:        Tue Sep 17 18:24:22 2013 +0200
+| | | | | |    summary:     Small updates for FFCS
+| | | | | |
+o---+ | | |  changeset:   2781:a0a0a2c0d990
+| | | | | |  parent:      2780:3aec73ae92a6
+| | | | | |  parent:      2769:27971516538c
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 17 11:51:05 2013 +0200
+| | | | | |  summary:     Synchronizing FH and ALH source trees
+| | | | | |
+| | o | | |  changeset:   2780:3aec73ae92a6
+| | | | | |  parent:      2768:9f9d303a3b9d
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Thu Sep 12 12:30:48 2013 +0200
+| | | | | |  summary:     Ignoring .htaccess to go through the web server
+| | | | | |
+| | | | o |  changeset:   2779:cf1946212db2
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Nov 13 14:37:02 2013 +0100
+| | | | | |  summary:     pass to version 2.55-1
+| | | | | |
+| | | | o |  changeset:   2778:58380ba26f11
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Sat Nov 02 10:25:48 2013 +0100
+| | | | | |  summary:     coorect pb in norm and real with new version complex in c++-11
+| | | | | |
+| | | | o |  changeset:   2777:737a1002ab0a
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Oct 31 21:35:57 2013 +0100
+| | | | | |  summary:     coorect mistake in download/ipopt/Makefile for blas
+| | | | | |
+| | | | o |  changeset:   2776:a34eb2d6108b
+| | | | |/   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |    date:        Thu Oct 31 18:41:00 2013 +0100
+| | | | |    summary:     do correct of MacOS 10.9 , new compiler.
+| | | | |
+| | | | o  changeset:   2775:da720285cc20
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Oct 05 08:29:54 2013 +0200
+| | | | |  summary:     correct mistike in the problme of matrix block
+| | | | |
+| | | | o  changeset:   2774:ade6693ffaf4
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Oct 03 18:18:20 2013 +0300
+| | | | |  summary:     correct problem in block matrix with 0 column or 0 row.
+| | | | |
+| | | | o  changeset:   2773:fd3772142d0a
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Sep 26 18:59:58 2013 +0200
+| | | | |  summary:     add missing test
+| | | | |
+| | | | o  changeset:   2772:a8cc2014376f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Sep 26 18:48:45 2013 +0200
+| | | | |  summary:     correct typo and add new autofiles
+| | | | |
+| | | | o  changeset:   2771:a5ad7a4f543a
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Sep 26 18:38:03 2013 +0200
+| | | | |  summary:     correct doc and fftw3  downlaod compilation
+| | | | |
++-------o  changeset:   2770:166bd70dce7c
+| | | |    user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |    date:        Thu Sep 26 17:59:26 2013 +0200
+| | | |    summary:     correct fftw MAkefile.am
+| | | |
+o---+ |  changeset:   2769:27971516538c
+| | | |  parent:      2719:7ae83b320fea
+| | | |  parent:      2768:9f9d303a3b9d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 17 11:42:42 2013 +0200
+| | | |  summary:     update ffc version and ff++ version
+| | | |
+| | o |  changeset:   2768:9f9d303a3b9d
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Sep 11 17:45:42 2013 +0200
+| | | |  summary:     Updates for FFCS compilation on Windows
+| | | |
+| | o |    changeset:   2767:e9ae0c3079fb
+| | |\ \   parent:      2762:98437b4ebf50
+| | | | |  parent:      2766:2fbbc949c081
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Sep 11 17:40:38 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting64
+| | | | |
+| | | o |  changeset:   2766:2fbbc949c081
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Sep 10 15:57:17 2013 +0200
+| | | | |  summary:     Updates for compiling FFCS on Ubuntu
+| | | | |
+| | | o |  changeset:   2765:71a8394c29e5
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Sep 10 15:40:07 2013 +0200
+| | | | |  summary:     Update for compiling FFCS on Ubuntu
+| | | | |
+| | | o |  changeset:   2764:55c008ede4ae
+| | | | |  parent:      2759:05059715e454
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Sep 10 15:08:11 2013 +0200
+| | | | |  summary:     Small corrections for FFCS compilation
+| | | | |
+| o | | |  changeset:   2763:f103190738d6
+| |\| | |  branch:      alh-dev
+| | | | |  parent:      2752:df47e2e6eed5
+| | | | |  parent:      2762:98437b4ebf50
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Sep 11 16:41:06 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting64
+| | | | |
+| | o | |    changeset:   2762:98437b4ebf50
+| | |\ \ \   parent:      2761:16d91a730b0c
+| | | | | |  parent:      2760:6abf65bf289f
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Sep 11 10:42:57 2013 +0200
+| | | | | |  summary:     Updates for FFCS compilation
+| | | | | |
+| | | o | |  changeset:   2761:16d91a730b0c
+| | | | | |  parent:      2750:c63825bee6e0
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Sep 11 10:42:01 2013 +0200
+| | | | | |  summary:     Updates for FFCS compilation
+| | | | | |
+| | o---+ |  changeset:   2760:6abf65bf289f
+| |   | | |  user:        Antoine Le Hyaric
+| |  / / /   date:        Tue Sep 10 14:19:02 2013 +0200
+| | | | |    summary:     Small corrections for FFCS compilation
+| | | | |
+| | | o |    changeset:   2759:05059715e454
+| | | |\ \   parent:      2758:e3af440f1eb5
+| | | | | |  parent:      2757:094eb2bf1ed5
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 10 14:14:04 2013 +0200
+| | | | | |  summary:     partial commit on Windows
+| | | | | |
+| | | | o |  changeset:   2758:e3af440f1eb5
+| | | | | |  parent:      2755:66c84a59ec08
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 10 14:12:50 2013 +0200
+| | | | | |  summary:     Small corrections for cygwin compilation
+| | | | | |
+| | | o | |  changeset:   2757:094eb2bf1ed5
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 10 13:55:23 2013 +0200
+| | | | | |  summary:     Corrections for MacOS 10.6 compilation
+| | | | | |
+| | | o | |  changeset:   2756:f6a45d5192d4
+| | | |/ /   user:        Antoine Le Hyaric
+| | | | |    date:        Tue Sep 10 13:44:49 2013 +0200
+| | | | |    summary:     Corrections for scotch compilation
+| | | | |
+| | | o |    changeset:   2755:66c84a59ec08
+| | | |\ \   parent:      2754:9c42ed65ca44
+| | | | | |  parent:      2717:c64826dc8c81
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 10 11:39:04 2013 +0200
+| | | | | |  summary:     Keeping ALH and FH trees in sync
+| | | | | |
+| | | | o |  changeset:   2754:9c42ed65ca44
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Sep 10 11:16:50 2013 +0200
+| | | | | |  summary:     Corrected pastix compilation for FFCS on MacOS 10.6
+| | | | | |
+| | +---o |  changeset:   2753:da3780f311e8
+| | | |  /   parent:      2750:c63825bee6e0
+| | | | |    user:        Antoine Le Hyaric
+| | | | |    date:        Thu Sep 05 11:39:29 2013 +0200
+| | | | |    summary:     Corrected mumps-seq makefile
+| | | | |
+| o | | |  changeset:   2752:df47e2e6eed5
+| | | | |  branch:      alh-dev
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Sep 11 10:44:26 2013 +0200
+| | | | |  summary:     partial commit on DebianTesting32
+| | | | |
+| o | | |  changeset:   2751:40f8b19d30da
+| |\| | |  branch:      alh-dev
+| | | | |  parent:      2749:d1afac8f61a9
+| | | | |  parent:      2750:c63825bee6e0
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Sep 04 16:48:42 2013 +0200
+| | | | |  summary:     Merged modifs from FH into alh-dev branch
+| | | | |
+| | o | |    changeset:   2750:c63825bee6e0
+| | |\ \ \   parent:      2745:e7875904c41e
+| | | | | |  parent:      2710:4341df7bae13
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Sep 04 16:18:14 2013 +0200
+| | | | | |  summary:     Synchronizing FF and FFCS updates to the Mumps and Umfpack makefiles
+| | | | | |
+| o | | | |  changeset:   2749:d1afac8f61a9
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Sep 04 15:22:24 2013 +0200
+| | | | | |  summary:     partial commit on DebianTesting64
+| | | | | |
+| o | | | |  changeset:   2748:ef562c7d8fb7
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Sep 04 15:16:32 2013 +0200
+| | | | | |  summary:     partial commit on DebianTesting64
+| | | | | |
+| o | | | |  changeset:   2747:698f90a62961
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Sep 04 14:48:43 2013 +0200
+| | | | | |  summary:     partial commit on DebianTesting64
+| | | | | |
+| o---+ | |  changeset:   2746:05a30144950f
+| | | | | |  branch:      alh-dev
+| | | | | |  parent:      2743:2e0fd3c00f4f
+| | | | | |  parent:      2745:e7875904c41e
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Sep 04 14:20:02 2013 +0200
+| | | | | |  summary:     merged default branch back into alh-dev
+| | | | | |
+| | | o | |    changeset:   2745:e7875904c41e
+| | | |\ \ \   parent:      2744:495eae88dc63
+| | | | | | |  parent:      2742:36b98a7a6e7a
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Wed Sep 04 12:22:28 2013 +0200
+| | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | |
+| | | | o | |  changeset:   2744:495eae88dc63
+| | | | | | |  parent:      2708:e50fd5f8a141
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Wed Sep 04 12:19:28 2013 +0200
+| | | | | | |  summary:     Corrections for FFCS compilation
+| | | | | | |
+| o | | | | |  changeset:   2743:2e0fd3c00f4f
+| | | | | | |  branch:      alh-dev
+| | | | | | |  parent:      2741:64de98e105f6
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Thu Aug 01 15:17:00 2013 +0200
+| | | | | | |  summary:     partial commit on DebianTesting32
+| | | | | | |
+| +---o | | |  changeset:   2742:36b98a7a6e7a
+| | | | | | |  parent:      2729:e2707ecfe7b7
+| | | | | | |  parent:      2741:64de98e105f6
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Thu Aug 01 12:34:02 2013 +0200
+| | | | | | |  summary:     Committing all changes for FFCS 13.14 back into FF
+| | | | | | |
+| o | | | | |  changeset:   2741:64de98e105f6
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Wed Jul 31 14:13:59 2013 +0200
+| | | | | | |  summary:     Added configuration option --enable-hypre
+| | | | | | |
+| o | | | | |  changeset:   2740:2bf0f2c8f9db
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Wed Jul 31 11:32:39 2013 +0200
+| | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | |
+| o | | | | |  changeset:   2739:33ed198a1694
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Tue Jul 30 15:26:10 2013 +0200
+| | | | | | |  summary:     Added extra configuration options for metis, parmetis and nlopt
+| | | | | | |
+| o | | | | |  changeset:   2738:a8c44e294d36
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Tue Jul 30 14:30:43 2013 +0200
+| | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | |
+| o | | | | |  changeset:   2737:685af844956b
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Tue Jul 30 14:26:21 2013 +0200
+| | | | | | |  summary:     Parallelized download/mumps-seq compilation
+| | | | | | |
+| o | | | | |  changeset:   2736:1f2cb6cd91e8
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Tue Jul 30 14:04:52 2013 +0200
+| | | | | | |  summary:     Parallelized MUMPS compilation
+| | | | | | |
+| o | | | | |    changeset:   2735:82c740a1f338
+| |\ \ \ \ \ \   branch:      alh-dev
+| | | | | | | |  parent:      2733:e3d8549335c2
+| | | | | | | |  parent:      2734:9e79463c9e48
+| | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | |  date:        Mon Jul 29 18:18:26 2013 +0200
+| | | | | | | |  summary:     partial commit on DebianTesting32
+| | | | | | | |
+| | o---------+  changeset:   2734:9e79463c9e48
+| |   | | | | |  branch:      alh-dev
+| |  / / / / /   parent:      2732:2a814f7c0f1f
+| | | | | | |    user:        Antoine Le Hyaric
+| | | | | | |    date:        Mon Jul 29 18:15:22 2013 +0200
+| | | | | | |    summary:     Fixes for Win32 compilation
+| | | | | | |
+| o---------+  changeset:   2733:e3d8549335c2
+|   | | | | |  branch:      alh-dev
+|  / / / / /   user:        Antoine Le Hyaric
+| | | | | |    date:        Mon Jul 29 15:13:01 2013 +0200
+| | | | | |    summary:     Added configure options --with-[package]-include= and --with-[package]-ldflags=
+| | | | | |
+| | | | | o  changeset:   2732:2a814f7c0f1f
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jul 24 16:08:34 2013 +0200
+| | | | | |  summary:     Fixed DLL compilation on Windows for MUMPS and pARMS
+| | | | | |
+| | | | | o  changeset:   2731:36e1cd88de75
+| | | | | |  branch:      alh-dev
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jul 24 13:41:16 2013 +0200
+| | | | | |  summary:     Compilation fixes for Windows
+| | | | | |
+| | | | | o  changeset:   2730:dca84350a248
+| | | | | |  branch:      alh-dev
+| | | | | |  parent:      2728:577fe9901c85
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Jul 23 16:13:06 2013 +0200
+| | | | | |  summary:     Small fixes for FFCS release version
+| | | | | |
+| | o | | |    changeset:   2729:e2707ecfe7b7
+| | |\ \ \ \   parent:      2724:54b6485a68f0
+| | | | | | |  parent:      2706:4cc59f9e5863
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Thu Jul 11 14:37:27 2013 +0200
+| | | | | | |  summary:     Keeping FH and ALH trees in sync
+| | | | | | |
+| | | | | | o  changeset:   2728:577fe9901c85
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Tue Jul 23 13:17:36 2013 +0200
+| | | | | | |  summary:     partial commit on Windows
+| | | | | | |
+| | | | | | o  changeset:   2727:d36610b57655
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Thu Jul 11 17:22:39 2013 +0200
+| | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | |
+| | | | | | o  changeset:   2726:edcf91fc280c
+| | | | | | |  branch:      alh-dev
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Thu Jul 11 15:09:44 2013 +0200
+| | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | |
+| | | +-----o  changeset:   2725:6e0e54be960e
+| | | | | | |  branch:      alh-dev
+| | | | | | |  parent:      2723:dc28f7873452
+| | | | | | |  parent:      2724:54b6485a68f0
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Wed Jul 10 15:17:16 2013 +0200
+| | | | | | |  summary:     Copied updates from the default branch to the alh-dev branch
+| | | | | | |
+| | | o | | |    changeset:   2724:54b6485a68f0
+| | | |\ \ \ \   parent:      2702:888a6c206637
+| | | | | | | |  parent:      2675:ec7d549934f0
+| | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | |  date:        Wed Jul 10 15:10:10 2013 +0200
+| | | | | | | |  summary:     Technical commit: synchronizing all HG heads from the default branch
+| | | | | | | |
+| | | | | | | o    changeset:   2723:dc28f7873452
+| | | | | | | |\   branch:      alh-dev
+| | | | | | | | |  parent:      2699:8fc2e7e016aa
+| | | | | | | | |  parent:      2722:ed19cfc9dc4a
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Wed Jul 10 15:06:06 2013 +0200
+| | | | | | | | |  summary:     technical commit: synchronizing draft ALH developments
+| | | | | | | | |
+| | | | | | | | o  changeset:   2722:ed19cfc9dc4a
+| | | | | | | | |  branch:      alh-dev
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Mon Jul 01 09:43:47 2013 +0200
+| | | | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | | | |
+| | | | | | | | o  changeset:   2721:8a5543705d99
+| | | | | | | | |  branch:      alh-dev
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Thu Jun 27 12:36:58 2013 +0200
+| | | | | | | | |  summary:     partial commit on DebianTesting64
+| | | | | | | | |
+| | | | | | | | o  changeset:   2720:734e4213f762
+| | | | | | | | |  branch:      alh-dev
+| | | | | | | | |  parent:      2700:4682570a0e2f
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Wed Jun 26 15:41:34 2013 +0200
+| | | | | | | | |  summary:     Created branch alh-dev for draft ALH developments
+| | | | | | | | |
+o | | | | | | | |  changeset:   2719:7ae83b320fea
+| | | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | | | |  date:        Fri Sep 06 15:34:49 2013 +0200
+| | | | | | | | |  summary:     coorect mistake in parmetis install files .
+| | | | | | | | |
+o-----------+ | |  changeset:   2718:35d438d9bcb2
+  | | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+ / / / / / / / /   date:        Fri Sep 06 10:59:36 2013 +0200
+| | | | | | | |    summary:     coorect for compilation with OpenBlas and a Window versio   of sleep.
+| | | | | | | |
+| | | | | o | |  changeset:   2717:c64826dc8c81
+| | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | | |  date:        Thu Sep 05 15:26:31 2013 +0200
+| | | | | | | |  summary:     add cote in -T MPIDIR
+| | | | | | | |
+| | | | | o | |  changeset:   2716:2597949bf544
+| | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | | |  date:        Thu Sep 05 14:57:31 2013 +0200
+| | | | | | | |  summary:     correct wget problme in pastis and superludist Makefile
+| | | | | | | |
+| | | | | o | |  changeset:   2715:306e42af8aca
+| | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | | |  date:        Thu Sep 05 10:58:44 2013 +0200
+| | | | | | | |  summary:     correct typo
+| | | | | | | |
+| | | | | o | |  changeset:   2714:2dca3a0b91a8
+| | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | | |  date:        Thu Sep 05 10:23:15 2013 +0200
+| | | | | | | |  summary:     correct pb of make stop if no arpack..
+| | | | | | | |
+| | | | | o | |  changeset:   2713:8b9576d7d540
+| | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | | |  date:        Thu Sep 05 09:55:51 2013 +0200
+| | | | | | | |  summary:     correct problem on skip mpi example in some case
+| | | | | | | |
+| | | | | o | |  changeset:   2712:524802dba437
+| | | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | | |  date:        Thu Sep 05 06:28:03 2013 +0200
+| | | | | | | |  summary:     rebuild AutoGeneratedFile.tar.gz
+| | | | | | | |
++---------o | |  changeset:   2711:71a6c203d688
+| | | | |  / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |    date:        Thu Sep 05 06:27:19 2013 +0200
+| | | | | | |    summary:     correct problem of stop compilation of load example
+| | | | | | |
+o | | | | | |  changeset:   2710:4341df7bae13
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Wed Sep 04 15:35:34 2013 +0200
+| | | | | | |  summary:     correct pb in mpi test remove graphic
+| | | | | | |
+o-------+ | |  changeset:   2709:45813df0888a
+  | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+ / / / / / /   date:        Wed Sep 04 13:31:56 2013 +0200
+| | | | | |    summary:     add tools to build le list of AutoGeneratedFile.tar.gz
+| | | | | |
+| | | o | |  changeset:   2708:e50fd5f8a141
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Tue Aug 27 14:28:25 2013 +0200
+| | | | | |  summary:     summer correction.
+| | | | | |
++-----o | |  changeset:   2707:17f80351763f
+| | |  / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |    date:        Sat Aug 17 22:39:03 2013 +0200
+| | | | |    summary:     add patch of holiday scotch dolaod with curl; an pb in a*[b,c,d,..]' with complex value
+| | | | |
+o | | | |  changeset:   2706:4cc59f9e5863
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jul 11 12:51:07 2013 +0200
+| | | | |  summary:     add comment for compile
+| | | | |
+o | | | |  changeset:   2705:c435a4165181
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jul 11 11:58:27 2013 +0200
+| | | | |  summary:     correct mmg3d
+| | | | |
+o | | | |  changeset:   2704:3bcad8cbbcbe
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jul 10 22:20:05 2013 +0200
+| | | | |  summary:     correct pb in save make the point is not in tet
+| | | | |
+o---+ | |  changeset:   2703:8a3547f7290a
+| | | | |  parent:      2702:888a6c206637
+|/ / / /   parent:      2675:ec7d549934f0
+| | | |    user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |    date:        Wed Jul 10 15:17:49 2013 +0200
+| | | |    summary:     restore skipcommet example
+| | | |
+| o | |  changeset:   2702:888a6c206637
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jul 10 14:44:03 2013 +0200
+| | | |  summary:     pass to version 3.25  merge ff++ of ALH and FH
+| | | |
+| o---+  changeset:   2701:dd21194cb9f6
+| | | |  parent:      2700:4682570a0e2f
+| | | |  parent:      2674:7bb139d17bea
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Jul 10 10:04:05 2013 +0200
+| | | |  summary:     Keeping FH and ALH trees in sync
+| | | |
+| | | o    changeset:   2700:4682570a0e2f
+| | | |\   parent:      2697:da86b515293e
+| | | | |  parent:      2698:62df716c1320
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jun 26 15:37:52 2013 +0200
+| | | | |  summary:     Transferred all FreeFem++ patches from the FreeFem++-cs source tree to the FreeFem++ source tree
+| | | | |
+| | o---+  changeset:   2699:8fc2e7e016aa
+| |   | |  branch:      alh-dev
+| |  / /   user:        Antoine Le Hyaric
+| | | |    date:        Wed Jun 26 14:52:09 2013 +0200
+| | | |    summary:     Created branch alh-dev for draft ALH developments
+| | | |
+| | | o  changeset:   2698:62df716c1320
+| | | |  parent:      2696:791401576c4d
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Jun 26 12:08:39 2013 +0200
+| | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | |
+| | o |    changeset:   2697:da86b515293e
+| | |\ \   parent:      2688:3eab88cf4024
+| | | | |  parent:      2663:e0d9c72558a1
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jun 25 15:39:07 2013 +0200
+| | | | |  summary:     Keeping FH and ALH trees in sync
+| | | | |
+| | | | o  changeset:   2696:791401576c4d
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jun 26 11:44:47 2013 +0200
+| | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | |
+| | | | o  changeset:   2695:3151480a64b7
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jun 25 15:50:08 2013 +0200
+| | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | |
+| | +---o  changeset:   2694:87b46e1b6393
+| | | | |  parent:      2693:86ea3e4a8851
+| | | | |  parent:      2663:e0d9c72558a1
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jun 25 15:46:25 2013 +0200
+| | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | |
+| | | | o  changeset:   2693:86ea3e4a8851
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jun 25 14:49:33 2013 +0200
+| | | | |  summary:     transferred all patches from the FFCS development tree
+| | | | |
+| | | | o  changeset:   2692:97a9606a653d
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Wed Jun 12 17:50:17 2013 +0200
+| | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | |
+| | | | o  changeset:   2691:419cee6966bc
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jun 11 18:00:21 2013 +0200
+| | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | |
+| | | | o  changeset:   2690:8abb5d66e20f
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jun 11 13:43:22 2013 +0200
+| | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | |
+| | | | o  changeset:   2689:3e931c8973b9
+| | | |/|  parent:      2687:aa013525fb7e
+| | | | |  parent:      2688:3eab88cf4024
+| | | | |  user:        Antoine Le Hyaric
+| | | | |  date:        Tue Jun 11 11:20:43 2013 +0200
+| | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | |
+| | | o |    changeset:   2688:3eab88cf4024
+| | | |\ \   parent:      2686:4fc31e72cdd0
+| | | | | |  parent:      2662:71cafe9dab38
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Tue Jun 11 10:36:23 2013 +0200
+| | | | | |  summary:     Keeping FH and ALH trees in sync
+| | | | | |
+| | | | | o  changeset:   2687:aa013525fb7e
+| | | | |/|  parent:      2681:46dd9851ed4d
+| | | | | |  parent:      2686:4fc31e72cdd0
+| | | | | |  user:        Antoine Le Hyaric
+| | | | | |  date:        Wed Jun 05 16:43:59 2013 +0200
+| | | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | | |
+| | | | o |    changeset:   2686:4fc31e72cdd0
+| | | | |\ \   parent:      2685:767efda6e451
+| | | | | | |  parent:      2308:f01c1ce34eb3
+| | | | | | |  user:        Antoine Le Hyaric
+| | | | | | |  date:        Wed Jun 05 11:19:30 2013 +0200
+| | | | | | |  summary:     Discarded obsolete head f01c1ce34eb3 (but kept that version in the repository)
+| | | | | | |
+| | | | | o |    changeset:   2685:767efda6e451
+| | | | | |\ \   parent:      2684:6b6c8aad96ac
+| | | | | | | |  parent:      2101:31c99c85707b
+| | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | |  date:        Wed Jun 05 11:18:45 2013 +0200
+| | | | | | | |  summary:     Discarded obsolete head 31c99c85707b (but kept that version in the repository)
+| | | | | | | |
+| | | | | | o |    changeset:   2684:6b6c8aad96ac
+| | | | | | |\ \   parent:      2683:cb8d4ecbfa92
+| | | | | | | | |  parent:      2054:f3cbf7394995
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Wed Jun 05 11:18:16 2013 +0200
+| | | | | | | | |  summary:     Discarded obsolete head f3cbf7394995 (but kept that version in the repository)
+| | | | | | | | |
+| | | | | | | o |  changeset:   2683:cb8d4ecbfa92
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Tue Jun 04 14:36:00 2013 +0200
+| | | | | | | | |  summary:     Created Doxygen main page and started to document the C++ classes
+| | | | | | | | |
+| | | | | | | o |  changeset:   2682:fcd1643fef04
+| | | | | | | | |  parent:      2656:77e6f87bfdbf
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Tue Jun 04 14:34:07 2013 +0200
+| | | | | | | | |  summary:     Created Doxygen main page and started to document the C++ classes
+| | | | | | | | |
+| | | | | | | | o  changeset:   2681:46dd9851ed4d
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Wed Jun 05 16:30:09 2013 +0200
+| | | | | | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | | | | | |
+| | | | | | | | o  changeset:   2680:2c62f82b7cf1
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Wed Jun 05 08:55:53 2013 +0200
+| | | | | | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | | | | | |
+| | | | | | | | o  changeset:   2679:7efba1855838
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Tue Jun 04 18:02:11 2013 +0200
+| | | | | | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | | | | | |
+| | | | | | | | o  changeset:   2678:684ae36c47ca
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Tue Jun 04 14:34:01 2013 +0200
+| | | | | | | | |  summary:     commit for fflibexport
+| | | | | | | | |
+| | | | | | | | o  changeset:   2677:be137189177e
+| | | | | | | | |  user:        Antoine Le Hyaric
+| | | | | | | | |  date:        Mon Jun 03 17:29:56 2013 +0200
+| | | | | | | | |  summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | | | | | |
+| | | | | | | | o  changeset:   2676:056116d8b9a9
+| | | | | | | |/   parent:      2656:77e6f87bfdbf
+| | | | | | | |    user:        Antoine Le Hyaric
+| | | | | | | |    date:        Mon Jun 03 16:53:15 2013 +0200
+| | | | | | | |    summary:     Modified by Antoine Le Hyaric on DebianTesting64 (machine odyssee)
+| | | | | | | |
+o | | | | | | |  changeset:   2675:ec7d549934f0
+|/ / / / / / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |    date:        Wed Jul 10 10:23:15 2013 +0200
+| | | | | | |    summary:     add skipcomment in readmesh.edp example
+| | | | | | |
+o | | | | | |  changeset:   2674:7bb139d17bea
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Thu Jul 04 18:04:37 2013 +0200
+| | | | | | |  summary:     put code of index and rindex missing in win32
+| | | | | | |
+o | | | | | |  changeset:   2673:93b7627f23fd
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Tue Jul 02 22:44:56 2013 +0300
+| | | | | | |  summary:     missing xfial Poisson3d.edp
+| | | | | | |
+o | | | | | |  changeset:   2672:ad18e7b807c6
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Tue Jul 02 22:43:32 2013 +0300
+| | | | | | |  summary:     autoreconf
+| | | | | | |
+o | | | | | |  changeset:   2671:67a063a1a524
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Tue Jul 02 22:42:53 2013 +0300
+| | | | | | |  summary:     add  xfail test in not tetgen
+| | | | | | |
+o | | | | | |  changeset:   2670:bc88752878d2
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Tue Jul 02 22:39:08 2013 +0300
+| | | | | | |  summary:     autoreconf
+| | | | | | |
+o | | | | | |  changeset:   2669:e7e5b1846361
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Tue Jul 02 22:38:23 2013 +0300
+| | | | | | |  summary:     update list of xfail example
+| | | | | | |
+o | | | | | |  changeset:   2668:11b43f1fdbfc
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Thu Jun 27 20:40:53 2013 +0200
+| | | | | | |  summary:     correct test-driver-ff to set XFAIL (to can fail no sure fail)
+| | | | | | |
+o | | | | | |  changeset:   2667:2cdabbc53b17
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Thu Jun 27 20:11:08 2013 +0200
+| | | | | | |  summary:     correct typo in XFAIL_TESTS automake variable
+| | | | | | |
+o | | | | | |  changeset:   2666:d11989c6ff07
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Thu Jun 27 19:55:11 2013 +0200
+| | | | | | |  summary:     add in pref missing include dir
+| | | | | | |
+o | | | | | |  changeset:   2665:b4b2ddd8100f
+| | | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | | |  date:        Thu Jun 27 19:37:44 2013 +0200
+| | | | | | |  summary:     add the creation of freefem++.pref file in all directory example
+| | | | | | |
+o | | | | | |  changeset:   2664:4575cdbc939c
+|/ / / / / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |    date:        Thu Jun 27 13:17:13 2013 +0200
+| | | | | |    summary:     coorect missing creation of freefem++.pref   file
+| | | | | |
+o | | | | |  changeset:   2663:e0d9c72558a1
+|/ / / / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |    date:        Tue Jun 11 21:40:05 2013 +0200
+| | | | |    summary:     add parameter in ffglut  program like  -g 1000x500+100+100 -t toto
+| | | | |
+o | | | |  changeset:   2662:71cafe9dab38
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jun 10 20:48:03 2013 +0200
+| | | | |  summary:     correct pb of auto size of 3d plot
+| | | | |
+o | | | |  changeset:   2661:49e7d0ef36a7
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jun 10 14:15:44 2013 +0200
+| | | | |  summary:     add -wait "0.1" of ffglut (=> no manuel wait)
+| | | | |
+o | | | |  changeset:   2660:4c22c41a9f85
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Jun 09 18:21:51 2013 +0200
+| | | | |  summary:     correct typo llevelset.edp ->intlevelset.edp
+| | | | |
+o | | | |  changeset:   2659:6e4d9f511a3c
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Jun 09 17:16:41 2013 +0200
+| | | | |  summary:     put correction of Lorenzo.
+| | | | |
+o | | | |  changeset:   2658:5f7becf9dbd3
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Jun 07 16:11:08 2013 +0200
+| | | | |  summary:     add test of pb ?: operator with div / 0.
+| | | | |
+o-------+  changeset:   2657:9641b54129e2
+  | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+ / / / /   date:        Thu Jun 06 20:57:44 2013 +0200
+| | | |    summary:     change default solver in bilap.edo example
+| | | |
+| | | o  changeset:   2656:77e6f87bfdbf
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Jun 01 10:11:30 2013 +0200
+| | | |  summary:     correct test test "${SKIP:-no}"
+| | | |
+| | | o  changeset:   2655:3b374e87a5a7
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Jun 01 09:52:31 2013 +0200
+| | | |  summary:     correct TESTing of freefem++
+| | | |
+| | | o  changeset:   2654:d9460e4552e0
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri May 31 22:44:45 2013 +0200
+| | | |  summary:     update automake test of freefem++
+| | | |
+| | | o  changeset:   2653:e65c6ce6f363
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed May 29 12:18:37 2013 +0200
+| | | |  summary:     remove \r in patch file
+| | | |
+| | | o  changeset:   2652:379e79e6761b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed May 29 11:48:45 2013 +0200
+| | | |  summary:     add ff-mpirun on windows distrib.
+| | | |
+| | | o  changeset:   2651:a33d824b6777
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed May 29 10:03:44 2013 +0200
+| | | |  summary:     add quote for windows
+| | | |
+| | | o  changeset:   2650:fdbc1f7fc3c6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue May 28 18:59:32 2013 +0200
+| | | |  summary:     correct typo in doc on operator .*+ and ./=
+| | | |
+| | | o  changeset:   2649:9ef12351b744
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 13 21:20:19 2013 +0200
+| | | |  summary:     correct CheckAll
+| | | |
+| | | o  changeset:   2648:e1207c606f45
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 13 21:05:18 2013 +0200
+| | | |  summary:     correct CheckAll
+| | | |
+| | | o  changeset:   2647:1e153d9d7218
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 13 20:55:40 2013 +0200
+| | | |  summary:     correct getline or \r\n files
+| | | |
+| | | o  changeset:   2646:ccdea38daf14
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 06 22:03:44 2013 +0200
+| | | |  summary:     correct configure.ac for umfpack downlad
+| | | |
+| | | o  changeset:   2645:13f113c861c0
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 06 20:42:41 2013 +0200
+| | | |  summary:     correct pb of compile umfpack if no --enable-download  flags
+| | | |
+| | | o  changeset:   2644:d68cb17545dc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 06 20:28:13 2013 +0200
+| | | |  summary:     correct typo in CheckAll to store result
+| | | |
+| | | o  changeset:   2643:f7669c7a10ee
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri May 03 15:10:42 2013 +0200
+| | | |  summary:     remove dir in Makefile.am glx, std, x11
+| | | |
+| | | o  changeset:   2642:134644b820a8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri May 03 12:49:02 2013 +0200
+| | | |  summary:     version 3.23
+| | | |
+| | | o  changeset:   2641:36132ac7c1c1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Apr 27 11:36:36 2013 +0200
+| | | |  summary:     reomve x11, glx, ... off the compilation  prosess
+| | | |
+| | | o  changeset:   2640:4628a7908b73
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 19 15:38:16 2013 +0200
+| | | |  summary:     coorect type in isoline functio,n Area to compute the area of
+| | | |
+| | | o  changeset:   2639:d459cc808f30
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 18 20:45:09 2013 +0200
+| | | |  summary:     change area to Area because area is not a function.
+| | | |
+| | | o  changeset:   2638:f70cee1b6a7b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 18 19:02:42 2013 +0200
+| | | |  summary:     add area of isoline domaine
+| | | |
+| | | o  changeset:   2637:af2fae66daf5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 18 18:43:09 2013 +0200
+| | | |  summary:     coorect bug in close isoline  plugin
+| | | |
+| | | o  changeset:   2636:ef891424f88b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 18 16:47:38 2013 +0200
+| | | |  summary:     add Sylvain dans le auteur de FreeFem++
+| | | |
+| | | o  changeset:   2635:ca6bcf9490a4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 12 10:18:57 2013 +0200
+| | | |  summary:     remove graphics in case of -nw flags for batch test
+| | | |
+| | | o  changeset:   2634:895803f79633
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 12 09:42:12 2013 +0200
+| | | |  summary:     correct typo
+| | | |
+| | | o  changeset:   2633:9f74073f0c38
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 12 09:39:02 2013 +0200
+| | | |  summary:     up ./CheckAll of win32
+| | | |
+| | | o  changeset:   2632:35d4982c7d87
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 11 10:14:24 2013 +0200
+| | | |  summary:     add patch of freebsd on mshmet
+| | | |
+| | | o  changeset:   2631:88e6ad0b5eae
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Apr 09 08:14:58 2013 +0200
+| | | |  summary:     cadd message is case of no compile in configure
+| | | |
+| | | o  changeset:   2630:b7c3c4a72d2d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Apr 08 23:20:18 2013 +0200
+| | | |  summary:     try to put error when mesh is un set .
+| | | |
+| | | o  changeset:   2629:42e29538cbf1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Apr 08 22:05:45 2013 +0200
+| | | |  summary:     do gestion on non mesh (0 pointeur)
+| | | |
+| | | o  changeset:   2628:bc0e94fb0c28
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Apr 08 20:54:46 2013 +0200
+| | | |  summary:     add tools to remove interla faces
+| | | |
+| | | o  changeset:   2627:19af33493619
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Apr 08 18:01:17 2013 +0200
+| | | |  summary:     coormit glumesh in 2d of no mesh  (ok)
+| | | |
+| | | o  changeset:   2626:865b4afb98eb
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Apr 03 21:50:43 2013 +0200
+| | | |  summary:     update ffglut
+| | | |
+| | | o  changeset:   2625:21078f2bcf45
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Apr 03 09:16:57 2013 +0200
+| | | |  summary:     reput esc in ffglut to stop
+| | | |
+| | | o  changeset:   2624:6ee46703380b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Apr 02 11:28:02 2013 +0200
+| | | |  summary:     coorect stop ffglut in case of bug
+| | | |
+| | | o  changeset:   2623:6b417f8e333b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 29 08:59:00 2013 +0100
+| | | |  summary:     coorect the doc for new graphic option
+| | | |
+| | | o  changeset:   2622:d7215ddbcf5a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 28 23:46:05 2013 +0100
+| | | |  summary:     add new graphic event and multy windows
+| | | |
+| | | o  changeset:   2621:8e54a67d70fe
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 28 22:09:35 2013 +0100
+| | | |  summary:     pass to v 3.22
+| | | |
+| | | o  changeset:   2620:7a4a75730418
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 28 21:26:08 2013 +0100
+| | | |  summary:     update plot for multy windows
+| | | |
+| | | o  changeset:   2619:eb24ff98d1d1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Mar 26 23:41:03 2013 +0100
+| | | |  summary:     solve b off int overflow in gibbs renumbering
+| | | |
+| | | o  changeset:   2618:c2fce2359ce2
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Mar 25 16:21:52 2013 +0100
+| | | |  summary:     add type of real , int , complex in doc
+| | | |
+| | | o  changeset:   2617:915914787d79
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 22 23:24:47 2013 +0100
+| | | |  summary:     correct sheel plug for windows
+| | | |
+| | | o  changeset:   2616:2bc25eab7305
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 22 22:25:49 2013 +0100
+| | | |  summary:     cooret shell for windows
+| | | |
+| | | o  changeset:   2615:e4965faa0d98
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 22 21:55:43 2013 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2614:eb0e30cf59c6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 22 21:27:43 2013 +0100
+| | | |  summary:     correct Makefile for cleanning
+| | | |
+| | | o  changeset:   2613:ff917977e3ac
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 22 10:23:58 2013 +0100
+| | | |  summary:     add getenv in shell plugin
+| | | |
+| | | o  changeset:   2612:2411bba1d923
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 16:37:31 2013 +0100
+| | | |  summary:     end for pardiso on hpc1
+| | | |
+| | | o  changeset:   2611:a33781429270
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 16:12:29 2013 +0100
+| | | |  summary:     next PARDISO mkl hpc1
+| | | |
+| | | o  changeset:   2610:e2b27fa668bd
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 15:55:35 2013 +0100
+| | | |  summary:     blas / mlk hpc1 pb ..
+| | | |
+| | | o  changeset:   2609:ddb3de28b4b9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 15:41:14 2013 +0100
+| | | |  summary:     next step   mkl
+| | | |
+| | | o  changeset:   2608:b4a043b50359
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 15:31:14 2013 +0100
+| | | |  summary:     mkl next step ..
+| | | |
+| | | o  changeset:   2607:988959bff8b8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 14:21:30 2013 +0100
+| | | |  summary:     MAJ mlk
+| | | |
+| | | o  changeset:   2606:38b95806d70a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 12:02:32 2013 +0100
+| | | |  summary:     correct mkl  seach in autoconf ...
+| | | |
+| | | o  changeset:   2605:f742f2600c99
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 10:37:50 2013 +0100
+| | | |  summary:     add depend mkl to paridiso
+| | | |
+| | | o  changeset:   2604:8100a6d971e7
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 10:31:34 2013 +0100
+| | | |  summary:     REMOVE Mpi from PARDISO
+| | | |
+| | | o  changeset:   2603:31e73a49d8f3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 21 09:21:12 2013 +0100
+| | | |  summary:     correct 3d trunc . and type in CheckPtr
+| | | |
+| | | o  changeset:   2602:b0783e4cb2d3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Mar 19 09:02:13 2013 +0100
+| | | |  summary:     correct pb in gestion of outside flag in case of brute force search of tet contening a point
+| | | |
+| | | o  changeset:   2601:090c847ad8c8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 15 18:37:05 2013 +0100
+| | | |  summary:     coorect typo
+| | | |
+| | | o  changeset:   2600:3c995bdf4b50
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 15 16:51:31 2013 +0100
+| | | |  summary:     v 3.21-1 autoreconf.
+| | | |
+| | | o  changeset:   2599:71cd2d5a350f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 15 16:50:34 2013 +0100
+| | | |  summary:     passe to versioon 3.21-1
+| | | |
+| | | o  changeset:   2598:3f9a6c79377a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Mar 05 21:03:03 2013 +0100
+| | | |  summary:     correct timer for umfpack
+| | | |
+| | | o  changeset:   2597:206af6393108
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 20 22:02:06 2013 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2596:8a575742fc6f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 20 21:57:57 2013 +0100
+| | | |  summary:     change umpack to no version
+| | | |
+| | | o  changeset:   2595:9af00b7818c1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Feb 14 08:11:01 2013 -0600
+| | | |  summary:     coorect ref value of fluidstruct examples
+| | | |
+| | | o  changeset:   2594:43b25e32651f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 13 23:13:04 2013 -0600
+| | | |  summary:     add n, resize of arry of finite element function ...
+| | | |
+| | | o  changeset:   2593:54f4ad3d3362
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Feb 12 18:14:19 2013 -0600
+| | | |  summary:     correct doc for NSUzawaCahouetChabart.edp
+| | | |
+| | | o  changeset:   2592:aac1b5aec871
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Feb 04 08:19:25 2013 -0600
+| | | |  summary:     up. INNOCATION
+| | | |
+| | | o  changeset:   2591:f14702ce2e6d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Feb 04 08:18:36 2013 -0600
+| | | |  summary:     correct typo
+| | | |
+| | | o  changeset:   2590:7a3472e50c69
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jan 28 14:20:28 2013 +0100
+| | | |  summary:     remove export MACOSX_DEPLOYMENT_TARGET=10.4 on macos (too old stuff)
+| | | |
+| | | o  changeset:   2589:a959a31a2912
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jan 28 09:39:30 2013 +0100
+| | | |  summary:     coorect in  change function the flabel tools.
+| | | |
+| | | o  changeset:   2588:f53ea48bdac4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 24 18:23:48 2013 +0100
+| | | |  summary:     rm bad file
+| | | |
+| | | o  changeset:   2587:b1b23c7916a3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jan 23 16:25:01 2013 +0100
+| | | |  summary:     coorect missing build of quadtree in gmesh 2d case
+| | | |
+| | | o  changeset:   2586:dbd8bda95c9c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jan 21 18:28:55 2013 +0100
+| | | |  summary:     correct ff-mpirun to make local launch in some cas
+| | | |
+| | | o  changeset:   2585:232b71bc7c24
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Jan 20 20:55:49 2013 +0100
+| | | |  summary:     pass to version 3.20-3
+| | | |
+| | | o  changeset:   2584:36c600f16fc4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Jan 18 21:57:09 2013 +0100
+| | | |  summary:     correct the new mmg3d4
+| | | |
+| | | o  changeset:   2583:fc1d1f80a3de
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Jan 15 10:09:22 2013 +0100
+| | | |  summary:     clean scalapack makefile
+| | | |
+| | | o  changeset:   2582:b1d5e28701fc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Jan 15 09:38:04 2013 +0100
+| | | |  summary:     coorect scalapack lib without extern blacs add .oo file in lib
+| | | |
+| | | o  changeset:   2581:f7c9c3f0e753
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 10 11:26:13 2013 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2580:ff72eeaffa02
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 10 10:59:53 2013 +0100
+| | | |  summary:     reomve blacs lib now include in scalapack.
+| | | |
+| | | o  changeset:   2579:8f891641d4e6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 10 10:50:52 2013 +0100
+| | | |  summary:     add blacs in scalapack lib .
+| | | |
+| | | o  changeset:   2578:3e68b323cae8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 10 10:45:12 2013 +0100
+| | | |  summary:     correct type in scalapack
+| | | |
+| | | o  changeset:   2577:2ebfff8d40ea
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 10 10:41:32 2013 +0100
+| | | |  summary:     coorect -FPIC compile falgs in scalapack 2.02
+| | | |
+| | | o  changeset:   2576:1e1b16af7ef3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Jan 08 15:32:18 2013 +0100
+| | | |  summary:     correct DOC freefem++  notepad++ launch freefem++ with lauchff++
+| | | |
+| | | o  changeset:   2575:45ef0341b9de
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Dec 21 17:04:13 2012 +0100
+| | | |  summary:     correct def on WGET in scalapack MAKEFILE
+| | | |
+| | | o  changeset:   2574:43e587d524f2
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Dec 21 10:05:53 2012 +0100
+| | | |  summary:     coorect typo
+| | | |
+| | | o  changeset:   2573:706b1fb04002
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Dec 06 22:50:24 2012 +0100
+| | | |  summary:     update pipe.cpp interface add
+| | | |
+| | | o  changeset:   2572:75958d95b25a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 29 17:50:38 2012 +0100
+| | | |  summary:     move PARDISO to example++-load ( not MPI program)
+| | | |
+| | | o  changeset:   2571:22c5533569ad
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 29 17:38:03 2012 +0100
+| | | |  summary:     remove old version ...
+| | | |
+| | | o  changeset:   2570:a3e882fd71c3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 29 14:45:38 2012 +0100
+| | | |  summary:     PASS PARDISO to complex (not test ..)
+| | | |
+| | | o  changeset:   2569:e916e4a8e005
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 29 11:51:21 2012 +0100
+| | | |  summary:     Coorect SetDefaultSolver in all case (now in main)
+| | | |
+| | | o  changeset:   2568:73fcad054f91
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 29 10:29:35 2012 +0100
+| | | |  summary:     update MUMPS mpi complex version
+| | | |
+| | | o  changeset:   2567:85a427c2f918
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 28 23:20:46 2012 +0100
+| | | |  summary:     put compex in MUMPS in progress
+| | | |
+| | | o  changeset:   2566:1beb3cf38e1d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 28 22:19:39 2012 +0100
+| | | |  summary:     add compile MUMPS and PARDISO
+| | | |
+| | | o  changeset:   2565:ade7d8e2fd80
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 28 22:16:47 2012 +0100
+| | | |  summary:     coorect MUMPS.cpp
+| | | |
+| | | o  changeset:   2564:820d39a3c8cf
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 28 22:11:16 2012 +0100
+| | | |  summary:     correct metis Makefile
+| | | |
+| | | o  changeset:   2563:284eaf041a4b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 28 21:28:36 2012 +0100
+| | | |  summary:     type erreur missing Makefile code for camd
+| | | |
+| | | o  changeset:   2562:b54f279c8c97
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 28 21:22:21 2012 +0100
+| | | |  summary:     add new matrix solver interface (see P. Jolivet)
+| | | |
+| | | o  changeset:   2561:c9eae98ad5dc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Nov 02 22:59:13 2012 +0100
+| | | |  summary:     coorect missing setting nuTriangle
+| | | |
+| | | o  changeset:   2560:2eaedd8688ce
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Nov 02 22:36:18 2012 +0100
+| | | |  summary:     coorect missing of set nuTriangle  some time
+| | | |
+| | | o  changeset:   2559:ee9c67a82a1d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 30 18:25:43 2012 +0100
+| | | |  summary:     correct mistak in mmg3d Makefile
+| | | |
+| | | o  changeset:   2558:e0792728a848
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 26 16:10:48 2012 +0200
+| | | |  summary:     coorect change of intallfaces integral
+| | | |
+| | | o  changeset:   2557:a134cc81aaf2
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 25 10:03:41 2012 +0200
+| | | |  summary:     remove const in cblas interface sdot mistake  in openblas
+| | | |
+| | | o  changeset:   2556:dc973b75b634
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 25 08:04:52 2012 +0200
+| | | |  summary:     coorect PB with OpenBlas  cblas include without const in parameter
+| | | |
+| | | o  changeset:   2555:6fa9b9c59829
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 16 17:31:25 2012 +0200
+| | | |  summary:     add missing compile files
+| | | |
+| | | o  changeset:   2554:43560825cafe
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 10 15:21:51 2012 +0200
+| | | |  summary:     correct pipe.edp example to run under windows.
+| | | |
+| | | o  changeset:   2553:395f577c1a69
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Oct 08 11:53:33 2012 +0900
+| | | |  summary:     add pipe plugin to link with other soft
+| | | |
+| | | o  changeset:   2552:db4af2db147e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Oct 07 14:11:44 2012 +0900
+| | | |  summary:     do small coorection of windows
+| | | |
+| | | o  changeset:   2551:d32ffb11bec9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Oct 07 11:18:26 2012 +0900
+| | | |  summary:     coorect pb to set C io under winder
+| | | |
+| | | o  changeset:   2550:f3986a910f80
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Oct 06 22:34:10 2012 +0900
+| | | |  summary:     type
+| | | |
+| | | o  changeset:   2549:f6229d0989bb
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Oct 06 22:30:02 2012 +0900
+| | | |  summary:     correct mumps compilation
+| | | |
+| | | o  changeset:   2548:a1910dbcf7f9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Oct 06 11:50:54 2012 +0900
+| | | |  summary:     correct pb of segflaut on window atexit when creating the log file
+| | | |
+| | | o  changeset:   2547:1626cbdfe5d6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Oct 06 10:51:50 2012 +0900
+| | | |  summary:     coorect typo
+| | | |
+| | | o  changeset:   2546:7a7fba157b77
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Oct 06 10:50:08 2012 +0900
+| | | |  summary:     add option to remove console output on windows
+| | | |
+| | | o  changeset:   2545:b192e8d7cbd3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Oct 06 10:29:16 2012 +0900
+| | | |  summary:     correct thing of windows porting
+| | | |
+| | | o  changeset:   2544:1b485471f601
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 04 16:13:47 2012 +0200
+| | | |  summary:     coorect pb compile windows
+| | | |
+| | | o  changeset:   2543:b0e5ed55fcb8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 03 18:34:29 2012 +0200
+| | | |  summary:     correct mmg3d with new version
+| | | |
+| | | o  changeset:   2542:a2661dc3cf87
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 03 15:01:12 2012 +0200
+| | | |  summary:     correct pb with drawbdmesh ( not compile now),
+| | | |
+| | | o  changeset:   2541:5540ca108c29
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 03 14:38:28 2012 +0200
+| | | |  summary:     add find root of real poly in  gsl plugin
+| | | |
+| | | o  changeset:   2540:7fcb20950af8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 26 15:31:46 2012 +0200
+| | | |  summary:     remove drawbdmesh on windows
+| | | |
+| | | o  changeset:   2539:3646196ba7b4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 25 13:16:23 2012 +0200
+| | | |  summary:     A left scalar mul with formal arry.
+| | | |
+| | | o  changeset:   2538:004c3ce519db
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Sep 21 14:52:11 2012 +0200
+| | | |  summary:     try a build 3.20 version
+| | | |
+| | | o  changeset:   2537:4ea423174745
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Sep 21 11:37:23 2012 +0200
+| | | |  summary:     add levelset integral in 2d..
+| | | |
+| | | o  changeset:   2536:3df0231f5788
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 19 15:55:46 2012 +0200
+| | | |  summary:     coorect cout
+| | | |
+| | | o  changeset:   2535:1813e516c73c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 19 15:49:51 2012 +0200
+| | | |  summary:     correct isoline.cpp  hard ...
+| | | |
+| | | o  changeset:   2534:d63f9b0d6a90
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 18 21:17:21 2012 +0200
+| | | |  summary:     correct  isoline.cpp bug some time ....
+| | | |
+| | | o  changeset:   2533:9a0f4ba5bc83
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 05 22:33:04 2012 +0200
+| | | |  summary:     do coorect off clang++ compiler
+| | | |
+| | | o  changeset:   2532:7268da0a32dd
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 05 21:59:44 2012 +0200
+| | | |  summary:     correct big problem with clang++ compiler ...
+| | | |
+| | | o  changeset:   2531:bf616e104e58
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 05 21:56:56 2012 +0200
+| | | |  summary:     coorect pb with clang compile, verif strange..
+| | | |
+| | | o  changeset:   2530:10fbabb7ca26
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 05 14:55:29 2012 +0200
+| | | |  summary:     add formal tools Cofact, det 3x3,  : on formal array.
+| | | |
+| | | o  changeset:   2529:4603f7ce0737
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 04 16:41:21 2012 +0200
+| | | |  summary:     clang next step.
+| | | |
+| | | o  changeset:   2528:18d5c72b3f8b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 04 10:32:46 2012 +0200
+| | | |  summary:     do correct for clang compiler
+| | | |
+| | | o  changeset:   2527:061c058bf92d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Sep 03 16:18:48 2012 +0200
+| | | |  summary:     correct for c++11
+| | | |
+| | | o  changeset:   2526:47944725e009
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 28 14:21:56 2012 +0200
+| | | |  summary:     update README macos
+| | | |
+| | | o  changeset:   2525:d54e7f17997b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 28 12:53:41 2012 +0200
+| | | |  summary:     add CheckMPIMacLib.sh and CheckMacLib.sh taget in makefile for mac pkg install
+| | | |
+| | | o  changeset:   2524:8fde78f05ac0
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 27 16:03:36 2012 +0200
+| | | |  summary:     remove print  in sparse solver
+| | | |
+| | | o  changeset:   2523:d6c07fd2ec36
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Aug 26 21:27:19 2012 +0200
+| | | |  summary:     add missing operator ?: of bool
+| | | |
+| | | o  changeset:   2522:e5a90f5a7283
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Aug 16 09:47:15 2012 +0200
+| | | |  summary:     revome print ...
+| | | |
+| | | o  changeset:   2521:91006696c311
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 14 21:17:02 2012 +0200
+| | | |  summary:     correct mistake find by P. Jolivet.
+| | | |
+| | | o  changeset:   2520:ef81308ec4f1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Aug 12 22:07:52 2012 +0200
+| | | |  summary:     cooorect automatic seach in configire (P Jolivet).
+| | | |
+| | | o  changeset:   2519:4422559d360a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 06 23:12:27 2012 +0200
+| | | |  summary:     add comment of my installation
+| | | |
+| | | o  changeset:   2518:27d04b01bb9d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 06 00:14:04 2012 +0200
+| | | |  summary:     correct Superludist with g++ v 4.8
+| | | |
+| | | o  changeset:   2517:08658feae475
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Aug 05 23:37:08 2012 +0200
+| | | |  summary:     forget files
+| | | |
+| | | o  changeset:   2516:c2d91d216c32
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Aug 05 23:31:52 2012 +0200
+| | | |  summary:     coerect Superlu.cpp of g++ v 4.8 add missong this->
+| | | |
+| | | o  changeset:   2515:68577323c46d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Aug 05 15:17:51 2012 +0200
+| | | |  summary:     change mac compiler gcc version 4.8.0
+| | | |
+| | | o  changeset:   2514:ce08661de7d5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jul 12 14:27:34 2012 +0200
+| | | |  summary:     add example
+| | | |
+| | | o  changeset:   2513:efd3db094bcf
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jul 12 14:00:47 2012 +0200
+| | | |  summary:     add imax, imam, correct sctoch interface not //
+| | | |
+| | | o  changeset:   2512:cd465304bca9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 13 20:04:15 2012 +0200
+| | | |  summary:     add compile of shell
+| | | |
+| | | o  changeset:   2511:250772fdd061
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 13 20:00:36 2012 +0200
+| | | |  summary:     add shell/unix interface
+| | | |
+| | | o  changeset:   2510:bfac9dec081e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 13 10:38:55 2012 +0200
+| | | |  summary:     correct PB of cleanning memory of array real[int][int] ...
+| | | |
+| | | o  changeset:   2509:4628b688eeaf
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jun 07 15:12:35 2012 +0200
+| | | |  summary:     add missing include in some computer unistd.h
+| | | |
+| | | o  changeset:   2508:031e9c676174
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jun 07 08:16:38 2012 +0200
+| | | |  summary:     correct mshmet makefile to force the recompilation
+| | | |
+| | | o  changeset:   2507:1839c38ea7dc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jun 07 08:06:55 2012 +0200
+| | | |  summary:     chnge version to 3.19-2
+| | | |
+| | | o  changeset:   2506:80ae2baf5a8d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jun 07 07:50:29 2012 +0200
+| | | |  summary:     correct mshmet problem in case of 2 eigen value in Hessian.
+| | | |
+| | | o  changeset:   2505:95e33e458008
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed May 30 14:13:26 2012 +0200
+| | | |  summary:     correct typo in font size in postcript interface
+| | | |
+| | | o  changeset:   2504:f2cdbadf6faf
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue May 22 21:15:30 2012 +0200
+| | | |  summary:     correct clean part of mshmet makefile + add
+| | | |
+| | | o  changeset:   2503:bee48e40935e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue May 15 11:48:05 2012 +0200
+| | | |  summary:     correct missing const in qf11to25.cpp
+| | | |
+| | | o  changeset:   2502:0232fb9d45b7
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue May 15 11:39:15 2012 +0200
+| | | |  summary:     add build of Quadratur formular in qf11to25.cpp plugins
+| | | |
+| | | o  changeset:   2501:f20a2f3c7bd6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 14 21:04:26 2012 +0200
+| | | |  summary:     set fftw to version 3.3.2
+| | | |
+| | | o  changeset:   2500:f5c0851c058c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed May 09 22:26:21 2012 +0200
+| | | |  summary:     update modif of Ernesto Aranda <Ernesto.Aranda at uclm.es> for new version of mmg3d
+| | | |
+| | | o  changeset:   2499:de4c315dad33
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed May 09 21:11:04 2012 +0200
+| | | |  summary:     pass to version 3.19-1
+| | | |
+| | | o  changeset:   2498:7ecf46eb253d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed May 09 21:06:07 2012 +0200
+| | | |  summary:     add Ernesto Aranda <Ernesto.Aranda at uclm.es>  change ...
+| | | |
+| | | o  changeset:   2497:49f99f157b3c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 07 10:27:41 2012 +0200
+| | | |  summary:     coorect typo = -> != in configure (mkl sgi)
+| | | |
+| | | o  changeset:   2496:f5814395a638
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon May 07 10:14:08 2012 +0200
+| | | |  summary:     remove of use of MKL scalapack and blacs with sgi MPI
+| | | |
+| | | o  changeset:   2495:c3b18fa8f700
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu May 03 19:07:10 2012 +0200
+| | | |  summary:     remove MKLROOT form configure  ( disaper in new mkl configure)
+| | | |
+| | | o  changeset:   2494:d7658c0f681b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu May 03 18:28:44 2012 +0200
+| | | |  summary:     add correct in MUMPS mpi solver
+| | | |
+| | | o  changeset:   2493:c5124bde5bc5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu May 03 11:01:00 2012 +0200
+| | | |  summary:     remove cmake de configure
+| | | |
+| | | o  changeset:   2492:83094b26702f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu May 03 11:00:01 2012 +0200
+| | | |  summary:     add count pour ptr in CheckPtr.cpp
+| | | |
+| | | o  changeset:   2491:463c4c448187
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Apr 24 13:25:56 2012 +0200
+| | | |  summary:     try to count memery pointeur
+| | | |
+| | | o  changeset:   2490:66be2ba0ba65
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Apr 23 23:08:13 2012 +0200
+| | | |  summary:     change version of superlu.
+| | | |
+| | | o  changeset:   2489:d2bee8f1b140
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 17:09:00 2012 +0200
+| | | |  summary:     update mmg3d  swapar.o is also compile without optim.
+| | | |
+| | | o  changeset:   2488:76e28b509475
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 16:51:03 2012 +0200
+| | | |  summary:     correct atexit problem in mmg3 v4 ..
+| | | |
+| | | o  changeset:   2487:cb2752aee207
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 15:40:23 2012 +0200
+| | | |  summary:     correct Interface of Ipopt (ff-Ipopt)
+| | | |
+| | | o  changeset:   2486:04bbadc57f58
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 14:16:51 2012 +0200
+| | | |  summary:     carrect un set varable in mmage3d-v4
+| | | |
+| | | o  changeset:   2485:e83aa5d378f9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 12:03:38 2012 +0200
+| | | |  summary:     coorect ff-Ipopt version
+| | | |
+| | | o  changeset:   2484:90cf49c9fbb5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 11:33:36 2012 +0200
+| | | |  summary:     coorect typo in innovation file
+| | | |
+| | | o  changeset:   2483:baebf141d983
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 09:27:57 2012 +0200
+| | | |  summary:     update INNOVATION file
+| | | |
+| | | o  changeset:   2482:5ede79cd270b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 09:21:18 2012 +0200
+| | | |  summary:     correct typo
+| | | |
+| | | o  changeset:   2481:0c075c537334
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Apr 20 08:48:58 2012 +0200
+| | | |  summary:     add isNaN,IsInf,IsNormal FP fonction and
+| | | |
+| | | o  changeset:   2480:290972213b56
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 19 22:58:51 2012 +0200
+| | | |  summary:     add a true scotch example
+| | | |
+| | | o  changeset:   2479:c0c3c75dd20a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 19 18:46:00 2012 +0200
+| | | |  summary:     add sort of integer array
+| | | |
+| | | o  changeset:   2478:08b71cf34320
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 19 17:17:10 2012 +0200
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2477:551aa5767d7f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 19 17:12:43 2012 +0200
+| | | |  summary:     coorect header of plugin
+| | | |
+| | | o  changeset:   2476:a6258a786803
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 19 16:46:43 2012 +0200
+| | | |  summary:     add scotch interface thanks to P. Jolivet
+| | | |
+| | | o  changeset:   2475:b7f9353707c0
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 19 16:34:39 2012 +0200
+| | | |  summary:     Pour P. Jolivet,
+| | | |
+| | | o  changeset:   2474:e507d135fbf4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 19 16:28:28 2012 +0200
+| | | |  summary:     correct bug in macro with operator .*= and ./=
+| | | |
+| | | o  changeset:   2473:28d82b742e4e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Apr 16 13:54:02 2012 +0200
+| | | |  summary:     comment in stable script examples++-3d/Laplace-Adapt-aniso-3d.edp
+| | | |
+| | | o  changeset:   2472:f7c9fbfee29e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Apr 15 22:27:49 2012 +0200
+| | | |  summary:     correct mmg3d new interface.
+| | | |
+| | | o  changeset:   2471:67ac6a176e89
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Apr 15 10:36:30 2012 +0200
+| | | |  summary:     correct build fo missing file during test in ttestio
+| | | |
+| | | o  changeset:   2470:be230cbc9bb1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Apr 11 22:46:11 2012 +0200
+| | | |  summary:     update doc with  isoline example
+| | | |
+| | | o  changeset:   2469:7b55a13f44bf
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Apr 11 18:15:57 2012 +0200
+| | | |  summary:     correct type in edp files
+| | | |
+| | | o  changeset:   2468:cb455028d3bc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 05 17:59:05 2012 +0200
+| | | |  summary:     correct  pb plot in 3d-lemen;edp example
+| | | |
+| | | o  changeset:   2467:a4495a14cc6f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 05 17:41:19 2012 +0200
+| | | |  summary:     correct Makefile for dist
+| | | |
+| | | o  changeset:   2466:c1c7515b599d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 05 17:38:21 2012 +0200
+| | | |  summary:     remove assert of generate surface mesh ???
+| | | |
+| | | o  changeset:   2465:adf7a32dec37
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 05 17:36:08 2012 +0200
+| | | |  summary:     add new Ipopt example
+| | | |
+| | | o  changeset:   2464:420d59368939
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Apr 05 17:17:53 2012 +0200
+| | | |  summary:     pass to version 3.19 , and add Ipopt documentation
+| | | |
+| | | o  changeset:   2463:684b603bce0f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Apr 03 15:35:04 2012 +0200
+| | | |  summary:     change the return value of inv in lapack , reture info value
+| | | |
+| | | o  changeset:   2462:43d891de7b5c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 30 13:52:21 2012 +0200
+| | | |  summary:     update IPOPT interface
+| | | |
+| | | o  changeset:   2461:ff9197c7215e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 19:02:18 2012 +0100
+| | | |  summary:     forget all.edp (automatical rebuild)
+| | | |
+| | | o  changeset:   2460:5f0193ae54c8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 18:59:23 2012 +0100
+| | | |  summary:     coorect install plugin
+| | | |
+| | | o  changeset:   2459:33407ff589c1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 18:52:47 2012 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2458:da832a4533ec
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 18:51:32 2012 +0100
+| | | |  summary:     romve use file
+| | | |
+| | | o  changeset:   2457:a70d6470d341
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 18:18:18 2012 +0100
+| | | |  summary:     correct typo
+| | | |
+| | | o  changeset:   2456:660e36d76368
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 18:14:56 2012 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2455:d1c7eb0f6226
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 17:48:02 2012 +0100
+| | | |  summary:     coorect FFLAGS in ippot
+| | | |
+| | | o  changeset:   2454:c7e70cac0ced
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 17:45:23 2012 +0100
+| | | |  summary:     correct ipopt fortran flags
+| | | |
+| | | o  changeset:   2453:fa1d39ecf8c5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 17:00:18 2012 +0100
+| | | |  summary:     correct chanhe of ff-IpOpt in ff-Ipopt
+| | | |
+| | | o  changeset:   2452:603891d1341f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 16:58:37 2012 +0100
+| | | |  summary:     correcrt Ipot name
+| | | |
+| | | o  changeset:   2451:abcfed2f161a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 15:24:19 2012 +0100
+| | | |  summary:     remove build file
+| | | |
+| | | o  changeset:   2450:fd47a9cb93e6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 22 14:01:53 2012 +0100
+| | | |  summary:     correct missing CFLAGS compile flige in ipopt
+| | | |
+| | | o  changeset:   2449:9c4f3a731d8f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 15 17:03:46 2012 +0100
+| | | |  summary:     update freeyams versio
+| | | |
+| | | o  changeset:   2448:57268fd78d95
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 15 16:22:26 2012 +0100
+| | | |  summary:     correct ipopt
+| | | |
+| | | o  changeset:   2447:648085c768e2
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Mar 15 15:41:31 2012 +0100
+| | | |  summary:     carrection iptop interface
+| | | |
+| | | o  changeset:   2446:db7e1719d41d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Mar 14 10:03:06 2012 +0100
+| | | |  summary:     coorect typo the WHERE file building
+| | | |
+| | | o  changeset:   2445:9652b407c4d4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Mar 14 09:40:38 2012 +0100
+| | | |  summary:     correct msh3.cpp see INNOVATION
+| | | |
+| | | o  changeset:   2444:0912ecf5b7b6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Mar 13 19:22:46 2012 +0100
+| | | |  summary:     correct type error
+| | | |
+| | | o  changeset:   2443:f73f7abb9628
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Mar 12 20:42:20 2012 +0100
+| | | |  summary:     add Ipopt interface, seems workinging
+| | | |
+| | | o  changeset:   2442:18c51dd3fae0
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 09 22:15:39 2012 +0100
+| | | |  summary:     add nex example
+| | | |
+| | | o  changeset:   2441:d857f8111e76
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 09 22:12:33 2012 +0100
+| | | |  summary:     add IpOpt interface
+| | | |
+| | | o  changeset:   2440:9811138f1bc7
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Mar 09 22:02:20 2012 +0100
+| | | |  summary:     add Ipopt interface
+| | | |
+| | | o  changeset:   2439:939ad2584480
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Mar 07 21:58:28 2012 +0100
+| | | |  summary:     correct pb of name in lapack in arpack configire variable
+| | | |
+| | | o  changeset:   2438:cc334b6ba942
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Mar 07 20:31:44 2012 +0100
+| | | |  summary:     add -mkl flgs in configure in test ..
+| | | |
+| | | o  changeset:   2437:8f1418723ac1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Mar 07 12:53:22 2012 +0100
+| | | |  summary:     add missing operator A(1:3,3:4) on full matrix
+| | | |
+| | | o  changeset:   2436:d8c7a95bab01
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Mar 06 23:13:13 2012 +0100
+| | | |  summary:     add new example
+| | | |
+| | | o  changeset:   2435:e9f77853f86a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Mar 06 22:57:22 2012 +0100
+| | | |  summary:     add subarrey of full matrix.
+| | | |
+| | | o  changeset:   2434:44e45a467771
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Mar 06 22:06:47 2012 +0100
+| | | |  summary:     add new type of array , array of array.
+| | | |
+| | | o  changeset:   2433:ff330cc9ed2a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Feb 24 17:43:14 2012 +0100
+| | | |  summary:     add ipopt download
+| | | |
+| | | o  changeset:   2432:6dd56733d650
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Feb 23 13:07:28 2012 +0100
+| | | |  summary:     add install of libphread-2.dd or win32
+| | | |
+| | | o  changeset:   2431:2fbea8d0c565
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Feb 23 12:07:08 2012 +0100
+| | | |  summary:     add pthread in mpi mumps
+| | | |
+| | | o  changeset:   2430:96c02671ec5c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Feb 23 12:05:52 2012 +0100
+| | | |  summary:     add pthread in WHERE-LIBARY-config for mumps-seq
+| | | |
+| | | o  changeset:   2429:b83672d4b4f9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 22 23:18:22 2012 +0100
+| | | |  summary:     correct typo in libseq path for mumps-seq compile
+| | | |
+| | | o  changeset:   2428:9c218b0575fc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 22 22:16:57 2012 +0100
+| | | |  summary:     add MUMPS seq pluging
+| | | |
+| | | o  changeset:   2427:e714f05e8c68
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Feb 20 10:02:23 2012 +0100
+| | | |  summary:     add tag + correct missing file in windows distributiuon
+| | | |
+| | | o  changeset:   2426:16116189f9fc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Feb 20 10:01:42 2012 +0100
+| | | |  summary:     Added tag 3.18-1 for changeset 7a11ffa1f26e
+| | | |
+| | | o  changeset:   2425:7a11ffa1f26e
+| | | |  tag:         3.18-1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Feb 17 16:14:54 2012 +0100
+| | | |  summary:     correct edp ..
+| | | |
+| | | o  changeset:   2424:ff06d18097d3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Feb 17 15:21:24 2012 +0100
+| | | |  summary:     coorect install windows
+| | | |
+| | | o  changeset:   2423:5dc5d4a44a0f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Feb 17 15:16:38 2012 +0100
+| | | |  summary:     correct missing file in makefiles
+| | | |
+| | | o  changeset:   2422:297b8d9f6034
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 15 22:00:56 2012 +0100
+| | | |  summary:     update doc
+| | | |
+| | | o  changeset:   2421:fc00fdf10fc8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 15 21:32:56 2012 +0100
+| | | |  summary:     continuing update
+| | | |
+| | | o  changeset:   2420:6cf5db8c5b72
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 15 21:29:17 2012 +0100
+| | | |  summary:     add .im, .re of array..compile test
+| | | |
+| | | o  changeset:   2419:56dc83bd98f5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 15 21:01:22 2012 +0100
+| | | |  summary:     add re , operator in complex  sparce matrix
+| | | |
+| | | o  changeset:   2418:04e97610e592
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Feb 14 21:46:23 2012 +0100
+| | | |  summary:     add convert of im and re parl of complex sparse matrix
+| | | |
+| | | o  changeset:   2417:c9503b6ad05c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Feb 14 15:30:45 2012 +0100
+| | | |  summary:     correct norme lp in RNM thank yo a student.
+| | | |
+| | | o  changeset:   2416:17002f8ac1e6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Feb 13 17:12:46 2012 +0100
+| | | |  summary:     add comment in INNOVATION file
+| | | |
+| | | o  changeset:   2415:99a84a69a476
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Feb 13 16:49:40 2012 +0100
+| | | |  summary:     add error  in case of probleme ith periodic
+| | | |
+| | | o  changeset:   2414:7e01a75cf0a2
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 18:02:06 2012 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2413:7e1ce5867819
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 18:01:07 2012 +0100
+| | | |  summary:     add missing files
+| | | |
+| | | o  changeset:   2412:1a9d248b0abe
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 17:57:12 2012 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2411:313f2537e2f6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 17:52:21 2012 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2410:f809aa7e43f9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 17:42:51 2012 +0100
+| | | |  summary:     add missing files
+| | | |
+| | | o  changeset:   2409:124a413008ed
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 16:34:17 2012 +0100
+| | | |  summary:     correct Makefiles
+| | | |
+| | | o  changeset:   2408:cbb20473adea
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 16:33:04 2012 +0100
+| | | |  summary:     remove example without new adaptation schema
+| | | |
+| | | o  changeset:   2407:9c7b8c0c8096
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Feb 08 16:24:20 2012 +0100
+| | | |  summary:     add adpt tool for PK aniso adation in 2d
+| | | |
+| | | o  changeset:   2406:40df8192a994
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Jan 20 15:36:57 2012 +0100
+| | | |  summary:     coorect scriot
+| | | |
+| | | o  changeset:   2405:9f521b6ad9e9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 19 13:37:05 2012 +0100
+| | | |  summary:     correct DOC
+| | | |
+| | | o  changeset:   2404:5c0462ce1574
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jan 19 09:54:05 2012 +0100
+| | | |  summary:     add New example in Chap 3.
+| | | |
+| | | o    changeset:   2403:4bee3958de18
+| | | |\   parent:      2401:64149fc11869
+| | | | |  parent:      2402:6d506087c6af
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 18 21:57:45 2012 +0100
+| | | | |  summary:     merging with 3.18 (error FH)
+| | | | |
+| | | | o  changeset:   2402:6d506087c6af
+| | | | |  parent:      2400:9506aca1ea28
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 18 21:36:47 2012 +0100
+| | | | |  summary:     Added tag v3.18 for changeset 9506aca1ea28
+| | | | |
+| | | o |  changeset:   2401:64149fc11869
+| | | |/   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |    date:        Wed Jan 18 21:34:52 2012 +0100
+| | | |    summary:     correct file to compile with xcode 4.2
+| | | |
+| | | o  changeset:   2400:9506aca1ea28
+| | | |  tag:         v3.18
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jan 16 13:08:11 2012 +0100
+| | | |  summary:     add line ininnovation
+| | | |
+| | | o  changeset:   2399:153d0a5015bb
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jan 16 13:04:13 2012 +0100
+| | | |  summary:     Correct NSprojection example
+| | | |
+| | | o  changeset:   2398:2d9a79b70d5b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jan 16 11:27:49 2012 +0100
+| | | |  summary:     add redownload off mmg34 tar gz
+| | | |
+| | | o  changeset:   2397:1fd0801dc393
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jan 16 11:10:33 2012 +0100
+| | | |  summary:     correct compile of mmg3d v4
+| | | |
+| | | o  changeset:   2396:f03a6f977499
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jan 11 21:35:51 2012 +0100
+| | | |  summary:     add missing file on windows
+| | | |
+| | | o  changeset:   2395:5fcad65c5ece
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jan 11 21:04:00 2012 +0100
+| | | |  summary:     passe to version 3.18
+| | | |
+| | | o  changeset:   2394:a8118bf9d0a5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jan 11 12:11:19 2012 +0100
+| | | |  summary:     update isoline dll.
+| | | |
+| | | o  changeset:   2393:d925ce8d8dd6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Jan 10 21:08:06 2012 +0100
+| | | |  summary:     correct mpigather
+| | | |
+| | | o  changeset:   2392:03d927f3dda3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Jan 10 20:50:00 2012 +0100
+| | | |  summary:     correct parallelempi.cpp mpigather assert
+| | | |
+| | | o  changeset:   2391:8898fcd7acce
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Jan 10 18:40:58 2012 +0100
+| | | |  summary:     change the isolineP1 load file by a isoline file
+| | | |
+| | | o  changeset:   2390:b778cdbf73c1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Dec 15 16:05:51 2011 +0100
+| | | |  summary:     correct pb of offset in readmesh in ffglut
+| | | |
+| | | o  changeset:   2389:cf6f4a7feea8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Dec 15 11:41:53 2011 +0100
+| | | |  summary:     coorect PB de shift  of  1 in  read .msh in 3d
+| | | |
+| | | o  changeset:   2388:8cab02860a3c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 30 15:02:31 2011 +0100
+| | | |  summary:     correct mistake in mpi interface (wrong assert and correct essai.edp)
+| | | |
+| | | o  changeset:   2387:d3f7e78540eb
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 30 14:42:47 2011 +0100
+| | | |  summary:     corret MPI problem
+| | | |
+| | | o  changeset:   2386:1a638fa49fbe
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 17 15:12:11 2011 +0100
+| | | |  summary:     correct BLACS interface ( mkl and debain case)
+| | | |
+| | | o  changeset:   2385:111b11d41665
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 17 13:39:47 2011 +0100
+| | | |  summary:     coorect pb in blacs lib order in WHERE_LIB
+| | | |
+| | | o  changeset:   2384:02fd8c5643f3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 16 22:10:38 2011 +0100
+| | | |  summary:     correct mshmet
+| | | |
+| | | o  changeset:   2383:c7dc28fb1321
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 16 18:30:17 2011 +0100
+| | | |  summary:     correct configure.ac (remove trick on odl mmg3 version (not use at all)
+| | | |
+| | | o  changeset:   2382:f661f9f8e47b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 16 17:56:03 2011 +0100
+| | | |  summary:     remove double symbloe in freeyam with meshlib
+| | | |
+| | | o  changeset:   2381:5732efc58a03
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 16 16:02:42 2011 +0100
+| | | |  summary:     remove compress tools in scotch by default
+| | | |
+| | | o  changeset:   2380:1f7181ed77e3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 16 11:39:39 2011 +0100
+| | | |  summary:     correct mistake in ymas interface
+| | | |
+| | | o  changeset:   2379:f671d72ac333
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 16 11:09:26 2011 +0100
+| | | |  summary:     uodate to last freeymas version
+| | | |
+| | | o  changeset:   2378:b5cf0e99fbc4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Nov 15 17:42:08 2011 +0100
+| | | |  summary:     correct aprmetis and mmg3d  opt version
+| | | |
+| | | o  changeset:   2377:c9f68542a064
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Nov 15 16:19:23 2011 +0100
+| | | |  summary:     add small correct of fratran stuff in ff-c++ et find mpirun in configure
+| | | |
+| | | o  changeset:   2376:e475dc98bc5b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Nov 08 22:30:16 2011 +0100
+| | | |  summary:     add new ffapi.o  in src/bin-win32/Makefile
+| | | |
+| | | o  changeset:   2375:0f35b35f0203
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Nov 08 22:26:08 2011 +0100
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2374:00b37e15d8b8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Nov 08 22:12:36 2011 +0100
+| | | |  summary:     make hack for true random number on window (use of mersen randow)
+| | | |
+| | | o  changeset:   2373:81725e52c648
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Nov 08 21:33:42 2011 +0100
+| | | |  summary:     correct typo error  and pdate the doc.
+| | | |
+| | | o  changeset:   2372:729356646c52
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Nov 08 21:02:28 2011 +0100
+| | | |  summary:     correct the new auto laod interface ...
+| | | |
+| | | o  changeset:   2371:97802e3f5d5e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Nov 06 20:59:48 2011 +0100
+| | | |  summary:     passe to versio 3.17
+| | | |
+| | | o  changeset:   2370:07ee613471d9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sun Nov 06 15:46:21 2011 +0100
+| | | |  summary:     coorect PB off pluging  ( ok may be)
+| | | |
+| | | o  changeset:   2369:3a017668777d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Nov 04 18:45:51 2011 +0100
+| | | |  summary:     correct Typo error in multiple include defence ..
+| | | |
+| | | o  changeset:   2368:72f8424630ee
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Nov 04 16:54:48 2011 +0100
+| | | |  summary:     up innovation
+| | | |
+| | | o  changeset:   2367:e0d1eed7452a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Nov 04 16:28:33 2011 +0100
+| | | |  summary:     update plugin to by compatible with new load schema
+| | | |
+| | | o  changeset:   2366:045f330b4eba
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Nov 02 21:43:35 2011 +0100
+| | | |  summary:     build a work version of mpi on window base of sdk windows hpc
+| | | |
+| | | o  changeset:   2365:896119ddcba9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 26 21:50:31 2011 +0200
+| | | |  summary:     correct missing
+| | | |
+| | | o  changeset:   2364:6162056c2706
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 26 13:27:13 2011 +0200
+| | | |  summary:     pass to v 3.16-1
+| | | |
+| | | o  changeset:   2363:bf3e6531f554
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 26 13:12:33 2011 +0200
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2362:f38424524a39
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 26 13:10:05 2011 +0200
+| | | |  summary:     add patch of Marco Atzeri <marco.atzeri at gmail.com> for cygwin
+| | | |
+| | | o  changeset:   2361:392218d17485
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 21 14:47:43 2011 +0200
+| | | |  summary:     doc is 3.16-1
+| | | |
+| | | o  changeset:   2360:174539a666e8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 21 14:44:44 2011 +0200
+| | | |  summary:     update doc S. Auliac (optim)
+| | | |
+| | | o  changeset:   2359:e2bd8b52269f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 21 14:17:20 2011 +0200
+| | | |  summary:     MAJ  INNOVATION
+| | | |
+| | | o  changeset:   2358:539aa3bc4a1b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 21 14:13:58 2011 +0200
+| | | |  summary:     add mpi_cmaes  lib and examples
+| | | |
+| | | o  changeset:   2357:38c7f4d3ea7b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 20 19:53:57 2011 +0200
+| | | |  summary:     add NLopt interface and cmaes interce (thank to S. Auliac)
+| | | |
+| | | o  changeset:   2356:2edd97964eeb
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 14 14:35:20 2011 +0200
+| | | |  summary:     add truc to remove 2 init
+| | | |
+| | | o  changeset:   2355:408618fc2d14
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 13 23:09:39 2011 +0200
+| | | |  summary:     correct auto load of mumps
+| | | |
+| | | o  changeset:   2354:233a5a7f55c1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 13 23:07:31 2011 +0200
+| | | |  summary:     correct pb of autoinitsfunct
+| | | |
+| | | o  changeset:   2353:09b0580dda3a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 12 15:01:36 2011 +0200
+| | | |  summary:     add tool to automatique load
+| | | |
+| | | o  changeset:   2352:4bf39e36e2aa
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 07 22:10:24 2011 +0200
+| | | |  summary:     coorect pb of alloaction
+| | | |
+| | | o  changeset:   2351:383e5c0deedb
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 07 21:17:54 2011 +0200
+| | | |  summary:     change testio.edp ttestio.edp
+| | | |
+| | | o  changeset:   2350:70f9874ad0e4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 07 17:42:22 2011 +0200
+| | | |  summary:     coorect example
+| | | |
+| | | o  changeset:   2349:b3c7905f858b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 06 17:30:42 2011 +0200
+| | | |  summary:     coorect type in mmg3v4
+| | | |
+| | | o  changeset:   2348:cade5380b91e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 06 17:24:50 2011 +0200
+| | | |  summary:     correct CFALGS
+| | | |
+| | | o  changeset:   2347:70b2d6267d97
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 06 16:55:39 2011 +0200
+| | | |  summary:     correct typo error
+| | | |
+| | | o  changeset:   2346:d48570028111
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 06 13:19:02 2011 +0200
+| | | |  summary:     correct typo error and warning
+| | | |
+| | | o  changeset:   2345:ccd64b80d57f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 06 12:52:17 2011 +0200
+| | | |  summary:     try to bluid v 3.15
+| | | |
+| | | o  changeset:   2344:d47b9dda863c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Oct 06 11:41:48 2011 +0200
+| | | |  summary:     coorect pb in real[int,int] A, B; B=A' , etc..
+| | | |
+| | | o  changeset:   2343:c3dee854061e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 05 18:29:37 2011 +0200
+| | | |  summary:     come back to metis 4.0 for compatibilite reason
+| | | |
+| | | o  changeset:   2342:55e2323587af
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 05 14:44:47 2011 +0200
+| | | |  summary:     correct pastix  patch include  (remove .. in patch file)
+| | | |
+| | | o  changeset:   2341:50b762415bd3
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 05 14:27:57 2011 +0200
+| | | |  summary:     correct  A=A' for array real[int,int] or complex[int,int]
+| | | |
+| | | o  changeset:   2340:70404bc0a76f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Sep 29 21:48:05 2011 +0200
+| | | |  summary:     correct Paul Cazeaux  diff
+| | | |
+| | | o  changeset:   2339:e9d61b12fae9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Sep 29 19:25:21 2011 +0200
+| | | |  summary:     correct install MacOSX
+| | | |
+| | | o  changeset:   2338:6a620fc389e1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Sep 29 13:55:16 2011 +0200
+| | | |  summary:     add freefem++ laucher
+| | | |
+| | | o  changeset:   2337:b6eca8cec8e8
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 28 20:29:53 2011 +0200
+| | | |  summary:     correc configure cmaek typo error
+| | | |
+| | | o  changeset:   2336:f98beda3b2a9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 28 20:26:15 2011 +0200
+| | | |  summary:     try to redo Freefem++.app
+| | | |
+| | | o  changeset:   2335:d03364e04423
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 27 18:23:44 2011 +0200
+| | | |  summary:     correct metis makefile
+| | | |
+| | | o  changeset:   2334:fe046f72fb0a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 27 18:07:55 2011 +0200
+| | | |  summary:     Added tag 3.14-1 for changeset 3d5d2f056b09
+| | | |
+| | | o  changeset:   2333:3d5d2f056b09
+| | | |  tag:         3.14-1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 27 18:07:22 2011 +0200
+| | | |  summary:     pass to versiuon 3.14-1
+| | | |
+| | | o  changeset:   2332:ee6c761a1250
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 27 17:24:22 2011 +0200
+| | | |  summary:     correct emtis interface to v. 5.0.1 (  version 4.0 diseaper).
+| | | |
+| | | o  changeset:   2331:37137749da6e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 27 15:24:10 2011 +0200
+| | | |  summary:     correct metis download  (version 5.0.1)
+| | | |
+| | | o  changeset:   2330:a8aac61cf98b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Sep 22 09:26:49 2011 +0200
+| | | |  summary:     coorect FreeFem++-CoCoa line 26: [: : integer expression expected
+| | | |
+| | | o  changeset:   2329:43229386f981
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Sep 02 09:05:52 2011 +0200
+| | | |  summary:     correct Missing WHERE buils
+| | | |
+| | | o  changeset:   2328:9dc607125215
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Sep 02 08:57:54 2011 +0200
+| | | |  summary:     add missing file
+| | | |
+| | | o  changeset:   2327:6e2de6f927d5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Sep 02 08:53:46 2011 +0200
+| | | |  summary:     update innovation
+| | | |
+| | | o  changeset:   2326:3ea8a0183313
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Sep 01 22:43:12 2011 +0200
+| | | |  summary:     coorect interface with mmg3d verson 4
+| | | |
+| | | o  changeset:   2325:878e5c556d1e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Sep 01 22:40:33 2011 +0200
+| | | |  summary:     coorect inferface with mmg3d version 4
+| | | |
+| | | o  changeset:   2324:6fdc0e5ff2d7
+| | | |  parent:      2321:e34f8a052707
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 29 15:11:31 2011 +0200
+| | | |  summary:     Added tag 3.14-0 for changeset e34f8a052707
+| | | |
+| | | | o  changeset:   2323:a2284c53ea2c
+| | | | |  branch:      alh-autoconf
+| | | | |  parent:      2005:815102f120b1
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Aug 29 11:27:42 2011 +0200
+| | | | |  summary:     close branch incompreansible, plus utiliser
+| | | | |
+| | | | | o  changeset:   2322:234fd78ad3c5
+| | | | | |  branch:      graphical-user-interface-branch
+| | | | | |  parent:      1970:44a4659127b5
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Aug 29 11:26:37 2011 +0200
+| | | | | |  summary:     close branch incompreansible, plus utiliser
+| | | | | |
+| | | o | |  changeset:   2321:e34f8a052707
+| | | | | |  tag:         3.14-0
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Aug 29 10:21:12 2011 +0200
+| | | | | |  summary:     correct bug in 3d P1 interpolation
+| | | | | |
+| | | o | |  changeset:   2320:8901cfb2463f
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 22:00:34 2011 +0200
+| | | | | |  summary:     correct mpi exemple
+| | | | | |
+| | | o | |  changeset:   2319:117a01a44f20
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 21:38:55 2011 +0200
+| | | | | |  summary:     correct allGather check
+| | | | | |
+| | | o | |  changeset:   2318:e100f2b57094
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 21:15:48 2011 +0200
+| | | | | |  summary:     correct pb of allignement in sub array send/recv with MPI
+| | | | | |
+| | | o | |  changeset:   2317:be0d2368a0f4
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 21:08:19 2011 +0200
+| | | | | |  summary:     correct missing return in WSEND
+| | | | | |
+| | | o | |  changeset:   2316:8f502dfff22e
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 15:05:09 2011 +0200
+| | | | | |  summary:     recorrect tetger clan makeifle
+| | | | | |
+| | | o | |  changeset:   2315:cff15f3375e6
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 15:01:16 2011 +0200
+| | | | | |  summary:     do autoreconf
+| | | | | |
+| | | o | |  changeset:   2314:dfe298c27b76
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 14:57:05 2011 +0200
+| | | | | |  summary:     restart of 3.14 version (big mistake yesterday)
+| | | | | |
+| | | o | |  changeset:   2313:fda9929d138d
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 13:53:31 2011 +0200
+| | | | | |  summary:     remobe -march=native (bug on allpe)
+| | | | | |
+| | | o | |  changeset:   2312:3d541b3d75d1
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 11:46:26 2011 +0200
+| | | | | |  summary:     correct optim compile flags
+| | | | | |
+| | | o | |  changeset:   2311:9a74f723f0ac
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 11:33:30 2011 +0200
+| | | | | |  summary:     redo second problem
+| | | | | |
+| | | o | |  changeset:   2310:bf083bb860bc
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Aug 26 11:18:55 2011 +0200
+| | | | | |  summary:     correct debug config flags
+| | | | | |
+| | | o | |  changeset:   2309:11f8b8770f48
+| | | | | |  parent:      2275:76e1708404c5
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Tue May 31 14:03:37 2011 +0200
+| | | | | |  summary:     coorect msssing lib in freeyam pluging
+| | | | | |
+o | | | | |  changeset:   2308:f01c1ce34eb3
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Aug 25 17:54:08 2011 +0200
+| | | | | |  summary:     coorect defaul compile flags
+| | | | | |
+o | | | | |  changeset:   2307:48f6f2dda6f9
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Aug 25 16:04:43 2011 +0200
+| | | | | |  summary:     coorect intrinc second to secnd2 in arpach (missing function).
+| | | | | |
+o | | | | |  changeset:   2306:f1321b98b61b
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Aug 25 11:20:20 2011 +0200
+| | | | | |  summary:     correct clean taget in  Makefile
+| | | | | |
+o | | | | |  changeset:   2305:4b313e53fd00
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Aug 25 09:31:50 2011 +0200
+| | | | | |  summary:     Added tag 3.14 for changeset fbc48e130737
+| | | | | |
+o | | | | |  changeset:   2304:fbc48e130737
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Aug 25 09:30:45 2011 +0200
+| | | | | |  summary:     and add -g in case of --enable-debug
+| | | | | |
+o | | | | |  changeset:   2303:572e5649ecf2
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Aug 03 15:55:49 2011 +0200
+| | | | | |  summary:     correct of lion os.
+| | | | | |
+o | | | | |  changeset:   2302:0183fdbeab37
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Jul 06 11:36:12 2011 +0200
+| | | | | |  summary:     see innovation
+| | | | | |
+o | | | | |  changeset:   2301:5aeeb62cc314
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jul 04 21:37:38 2011 +0200
+| | | | | |  summary:     correct makefile
+| | | | | |
+o | | | | |  changeset:   2300:5c0487b0b207
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 23:12:35 2011 +0200
+| | | | | |  summary:     correct typo
+| | | | | |
+o | | | | |  changeset:   2299:b1bfdb1c8d4c
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 16:48:53 2011 +0200
+| | | | | |  summary:     correct INNOVATION
+| | | | | |
+o | | | | |  changeset:   2298:e8247822dc8f
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 16:21:48 2011 +0200
+| | | | | |  summary:     correct hips solver typo arror in destructor
+| | | | | |
+o | | | | |  changeset:   2297:8d0d89f8408a
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 11:17:09 2011 +0200
+| | | | | |  summary:     pass to version 3.13-3
+| | | | | |
+o | | | | |  changeset:   2296:4088be2bb5b0
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 11:12:40 2011 +0200
+| | | | | |  summary:     add WGET in download/mumps/Makefile-mumps-4.10.0.inc
+| | | | | |
+o | | | | |  changeset:   2295:344cbb3584d8
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 11:05:02 2011 +0200
+| | | | | |  summary:     add missing file
+| | | | | |
+o | | | | |  changeset:   2294:21c29dd8cb63
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 11:00:03 2011 +0200
+| | | | | |  summary:     coorect innovation file
+| | | | | |
+o | | | | |  changeset:   2293:2a0706ac5c1b
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 10:57:28 2011 +0200
+| | | | | |  summary:     coorect hips solver
+| | | | | |
+o | | | | |  changeset:   2292:673e2af79b3b
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 30 09:32:00 2011 +0200
+| | | | | |  summary:     correct HIPS solver
+| | | | | |
+o | | | | |  changeset:   2291:d839c2fd8874
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Jun 29 09:30:24 2011 +0200
+| | | | | |  summary:     upgrade INNOVATION file
+| | | | | |
+o | | | | |  changeset:   2290:2809d03f67ce
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Jun 29 09:21:52 2011 +0200
+| | | | | |  summary:     add interface of New MUMPS version 4.10.0
+| | | | | |
+o | | | | |  changeset:   2289:3ed2fe0ff5bf
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Tue Jun 28 09:18:23 2011 +0200
+| | | | | |  summary:     pass to version 3.13-2
+| | | | | |
+o | | | | |  changeset:   2288:70da8688792b
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 27 23:29:05 2011 +0200
+| | | | | |  summary:     correct gibbs may be algo
+| | | | | |
+o | | | | |  changeset:   2287:97bf00ff569f
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 27 22:54:04 2011 +0200
+| | | | | |  summary:     fing a bug un gibbs algo dur dur
+| | | | | |
+o | | | | |  changeset:   2286:447235cc1f35
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 27 21:17:36 2011 +0200
+| | | | | |  summary:     correct interpolation problem with periodic BC.
+| | | | | |
+o | | | | |  changeset:   2285:fab78e8b1f74
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 27 19:20:06 2011 +0200
+| | | | | |  summary:     correct typo
+| | | | | |
+o | | | | |  changeset:   2284:0f2ff71f4833
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 27 19:14:22 2011 +0200
+| | | | | |  summary:     add mem usage in UMFPACK solver output
+| | | | | |
+o | | | | |  changeset:   2283:540832a7ce66
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 27 10:31:44 2011 +0200
+| | | | | |  summary:     add exemples examples++-tutorial/Laplace-RHS-Dirac.edp
+| | | | | |
+o | | | | |  changeset:   2282:49c1c93356a0
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 09 17:48:18 2011 +0200
+| | | | | |  summary:     correct ambiguity in square func.
+| | | | | |
+o | | | | |  changeset:   2281:a92f428fff7f
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Thu Jun 09 12:26:16 2011 +0200
+| | | | | |  summary:     correct choix of mpimkl
+| | | | | |
+o | | | | |  changeset:   2280:5aa51837cdb7
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Tue Jun 07 20:32:50 2011 +0200
+| | | | | |  summary:     correct install yams
+| | | | | |
+o | | | | |  changeset:   2279:214e7ba93af3
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 06 21:51:56 2011 +0200
+| | | | | |  summary:     correct freeyams
+| | | | | |
+o | | | | |  changeset:   2278:41c904b8660c
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 06 20:42:03 2011 +0200
+| | | | | |  summary:     correct spuriou print
+| | | | | |
+o | | | | |  changeset:   2277:fcaee41a91cb
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Mon Jun 06 19:07:24 2011 +0200
+| | | | | |  summary:     correct freeyams.cpp LD process.
+| | | | | |
+o-----+ | |  changeset:   2276:1a6949ae0965
+  | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+ / / / / /   date:        Mon May 30 15:16:17 2011 +0200
+| | | | |    summary:     add new example
+| | | | |
+| | o | |  changeset:   2275:76e1708404c5
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri May 27 14:40:04 2011 +0200
+| | | | |  summary:     correct typo in int blas type
+| | | | |
+| | o | |  changeset:   2274:beae57ef5319
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri May 27 14:36:03 2011 +0200
+| | | | |  summary:     correct int for blas variable ..
+| | | | |
+| | o | |  changeset:   2273:3f2e931fffc3
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu May 26 15:42:47 2011 +0200
+| | | | |  summary:     correct typo in doc.
+| | | | |
+| | o | |  changeset:   2272:6ba83092a50b
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu May 26 15:15:01 2011 +0200
+| | | | |  summary:     go v 3.13
+| | | | |
+| | o | |  changeset:   2271:27fb12aa07ae
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu May 26 15:13:55 2011 +0200
+| | | | |  summary:     autoreconf
+| | | | |
+| | o | |  changeset:   2270:93499395509f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu May 26 15:11:13 2011 +0200
+| | | | |  summary:     update doc
+| | | | |
+| | o | |  changeset:   2269:55460f8c273e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed May 25 21:07:04 2011 +0200
+| | | | |  summary:     add final comment on Element_miaxte.cpp file
+| | | | |
+| | o | |  changeset:   2268:ab20518693c9
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue May 24 18:21:42 2011 +0200
+| | | | |  summary:     add RT1, RT1Ortho, DBM1, DBM1Ortho Finite element in Element_Mixte.cpp dynamics libs
+| | | | |
+| | o | |  changeset:   2267:b1efdda0703b
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue May 24 17:16:27 2011 +0200
+| | | | |  summary:     add BDM1 and BDM1Ortho Finite element
+| | | | |
+| | o | |  changeset:   2266:b73e6b532325
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri May 20 16:47:08 2011 +0200
+| | | | |  summary:     in progress TD-NND 1 element
+| | | | |
+| | o | |  changeset:   2265:696e7299da62
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri May 20 09:46:32 2011 +0200
+| | | | |  summary:     end of validation for RT1
+| | | | |
+| | o | |  changeset:   2264:0512b6bb56db
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri May 20 09:09:16 2011 +0200
+| | | | |  summary:     correct RT1 and add RT1Ortho F.E.
+| | | | |
+| | o | |  changeset:   2263:b5d879cb17c2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu May 19 15:12:24 2011 +0200
+| | | | |  summary:     correct Elm_TD-NNS.cpp for RT1 F.E.
+| | | | |
+| | o | |  changeset:   2262:13906a499616
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon May 09 08:53:30 2011 +0200
+| | | | |  summary:     correct lapack
+| | | | |
+| | o | |  changeset:   2261:3d579277e4ce
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon May 09 08:02:42 2011 +0200
+| | | | |  summary:     coorect lapack.cpp add full matrice  multiplication
+| | | | |
+| | o | |  changeset:   2260:39fb84c4949b
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri May 06 14:56:04 2011 +0200
+| | | | |  summary:     coorct lapack and New FE element
+| | | | |
+| | o | |  changeset:   2259:a02b7f1a9c02
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu May 05 15:47:08 2011 +0200
+| | | | |  summary:     add New finite in construction
+| | | | |
+| | o | |  changeset:   2258:bcfcf356bb8c
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Apr 28 18:30:09 2011 +0200
+| | | | |  summary:     add splitedges tools  of Mghazli Zoubida <mghazli_zoubida at yahoo.com>
+| | | | |
+| | o | |  changeset:   2257:294a37023d46
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Apr 18 11:57:40 2011 +0200
+| | | | |  summary:     coorect load load under win32
+| | | | |
+| | o | |  changeset:   2256:4d0308f12e72
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Apr 18 09:57:50 2011 +0200
+| | | | |  summary:     correct load link pk of " and ' in var
+| | | | |
+| | o | |  changeset:   2255:da55768a880d
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Apr 15 22:31:24 2011 +0200
+| | | | |  summary:     correct configure.Ac
+| | | | |
+| | o | |  changeset:   2254:83972e23732a
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Apr 15 21:04:34 2011 +0200
+| | | | |  summary:     correct configure.ac for mpi under win32
+| | | | |
+| | o | |  changeset:   2253:2aca6f1b5497
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Apr 15 20:35:45 2011 +0200
+| | | | |  summary:     MPI for win32
+| | | | |
+| | o | |    changeset:   2252:e145e24f6aa0
+| | |\ \ \   parent:      2251:3d2ff16fa1e5
+| | | | | |  parent:      2250:88c8347babf4
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Apr 15 18:28:28 2011 +0200
+| | | | | |  summary:     coorect Makefile
+| | | | | |
+| | | o | |  changeset:   2251:3d2ff16fa1e5
+| | | | | |  parent:      2247:246a6ffbd1f1
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Fri Apr 15 18:13:05 2011 +0200
+| | | | | |  summary:     coorect mpi configure for win32
+| | | | | |
+| | o | | |  changeset:   2250:88c8347babf4
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Apr 13 14:14:51 2011 +0200
+| | | | | |  summary:     updaet Heat3d.idp
+| | | | | |
+| | o | | |  changeset:   2249:3c31e2572e2f
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Apr 13 14:10:00 2011 +0200
+| | | | | |  summary:     correct typ in Heat3d.idp filename
+| | | | | |
+| | o | | |  changeset:   2248:6bcbc93c5bca
+| | |/ / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |    date:        Wed Apr 13 14:07:57 2011 +0200
+| | | | |    summary:     change Heat3D.idp
+| | | | |
+| | o | |  changeset:   2247:246a6ffbd1f1
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Apr 12 22:18:31 2011 +0200
+| | | | |  summary:     coorect Problem in WHERE quote
+| | | | |
+| | o | |  changeset:   2246:bfcbef551c2e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Apr 08 21:47:10 2011 +0200
+| | | | |  summary:     correct Chaleur
+| | | | |
+| | o | |  changeset:   2245:32829734574c
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Apr 08 17:37:22 2011 +0200
+| | | | |  summary:     correct INNOVATION file
+| | | | |
+| | o | |  changeset:   2244:726002c6f090
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Apr 08 17:33:38 2011 +0200
+| | | | |  summary:     remove suprious dump in superlu dist.
+| | | | |
+| | o | |  changeset:   2243:48f3b1e4a098
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Apr 07 12:05:18 2011 +0200
+| | | | |  summary:     correct change for // computing
+| | | | |
+| | o | |  changeset:   2242:a48b9b504aba
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Apr 06 14:50:49 2011 +0200
+| | | | |  summary:     correct configure to build file
+| | | | |
+| | o | |  changeset:   2241:18630017f8c9
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Apr 06 14:49:07 2011 +0200
+| | | | |  summary:     Added tag 3.12-1 for changeset cd142ee7324d
+| | | | |
+| | o | |  changeset:   2240:cd142ee7324d
+| | | | |  tag:         3.12-1
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Apr 05 10:21:23 2011 +0200
+| | | | |  summary:     correct 3d period BC.
+| | | | |
+| | o | |  changeset:   2239:a43c08688b7e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 30 13:14:22 2011 +0200
+| | | | |  summary:     procon gmres remove tgv ????
+| | | | |
+| | o | |  changeset:   2238:fff6c5feb7b6
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 29 21:54:33 2011 +0200
+| | | | |  summary:     gmres precon same
+| | | | |
+| | o | |  changeset:   2237:e04f738a5db2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 29 21:39:31 2011 +0200
+| | | | |  summary:     change precon gmres
+| | | | |
+| | o | |  changeset:   2236:c3258922889e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 29 21:13:11 2011 +0200
+| | | | |  summary:     correct precon gmres
+| | | | |
+| | o | |  changeset:   2235:6e138ea49c63
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Mar 24 16:56:02 2011 +0100
+| | | | |  summary:     correct  PB compiel for hypre with blas.
+| | | | |
+| | o | |  changeset:   2234:bfe9184061ce
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 23 17:30:48 2011 +0100
+| | | | |  summary:     cooret typo
+| | | | |
+| | o | |  changeset:   2233:ed0bb81df53d
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 23 17:24:34 2011 +0100
+| | | | |  summary:     add missing MPI_LIB
+| | | | |
+| | o | |  changeset:   2232:d23847ce53f2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 23 15:14:33 2011 +0100
+| | | | |  summary:     add cast of TypeSparseSlve on int for stokes type of solver .
+| | | | |
+| | o | |  changeset:   2231:f31959eb8d1f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 22 00:59:18 2011 +0100
+| | | | |  summary:     correcd DDM examples; tyop error
+| | | | |
+| | o | |  changeset:   2230:2c44e0a52112
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Mar 21 21:22:49 2011 +0100
+| | | | |  summary:     coorect missing lin in mkl  whith _rf.so ..
+| | | | |
+| | o | |  changeset:   2229:6fc339f2ceff
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 16 14:55:23 2011 +0100
+| | | | |  summary:     coorect ref test in tutorial
+| | | | |
+| | o | |  changeset:   2228:7c7128939c45
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 16 14:21:49 2011 +0100
+| | | | |  summary:     corect configure for mpi
+| | | | |
+| | o | |  changeset:   2227:977b3193fe08
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 16 12:59:13 2011 +0100
+| | | | |  summary:     correct bug in intersection of metric in adaptmesh in case of given metrix
+| | | | |
+| | o | |  changeset:   2226:49d4be4bdab9
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 15 14:55:54 2011 +0100
+| | | | |  summary:     coorect pb on configure of mpi (hard jos)
+| | | | |
+| | o | |  changeset:   2225:b9875e93b847
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 15 14:40:24 2011 +0100
+| | | | |  summary:     add test for m4 and bison command in configure
+| | | | |
+| | o | |  changeset:   2224:7e9e01c6e550
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 15 14:23:06 2011 +0100
+| | | | |  summary:     update mshmet to version 3.0
+| | | | |
+| | o | |  changeset:   2223:417a4450e6f8
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 22:22:41 2011 +0100
+| | | | |  summary:     correct mpi correct of sgi
+| | | | |
+| | o | |  changeset:   2222:85735d18b198
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 21:51:21 2011 +0100
+| | | | |  summary:     compile with sgi MPI
+| | | | |
+| | o | |  changeset:   2221:7d3bf33d6031
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 21:35:02 2011 +0100
+| | | | |  summary:     add check MPI_DOUBLE_COMPLEX in configure
+| | | | |
+| | o | |  changeset:   2220:1d2cb842acb2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 11:56:22 2011 +0100
+| | | | |  summary:     cooret mpi / cpp DOUBLE_COMPLEX
+| | | | |
+| | o | |  changeset:   2219:d0223be2ab7b
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 10:06:50 2011 +0100
+| | | | |  summary:     correct missing cflags in generic blas compilation
+| | | | |
+| | o | |  changeset:   2218:ed71122c4649
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 08:54:14 2011 +0100
+| | | | |  summary:     corrrect loop in makefile when cleanning
+| | | | |
+| | o | |  changeset:   2217:f3f99d1f9f92
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 08:39:35 2011 +0100
+| | | | |  summary:     correct loop in clean target makefiles
+| | | | |
+| | o | |  changeset:   2216:8b03d97bb490
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Mar 09 08:36:34 2011 +0100
+| | | | |  summary:     correct clean in freeyam makefile
+| | | | |
+| | o | |  changeset:   2215:5d1babde36d7
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Mar 08 17:57:47 2011 +0100
+| | | | |  summary:     correct mpi compile flags for sgi computer.
+| | | | |
+| | o | |  changeset:   2214:b04fdc8dbf99
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Feb 09 21:03:19 2011 +0100
+| | | | |  summary:     correct missing in install  examples++-load/fig.pgm	examples++-load/lg.pgm
+| | | | |
+| | o | |  changeset:   2213:0a53c3f15e2e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Feb 09 19:27:59 2011 +0100
+| | | | |  summary:     add missing file in Makefile dist tag.
+| | | | |
+| | o | |  changeset:   2212:bdae2c1318cc
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Feb 09 19:23:36 2011 +0100
+| | | | |  summary:     coorect MPI_DOUBLE_COMPLEX problem in mpi ...
+| | | | |
+| | o | |  changeset:   2211:a16c149daeb4
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Feb 09 18:11:31 2011 +0100
+| | | | |  summary:     correct mpiReduce complex case ..
+| | | | |
+| | o | |  changeset:   2210:94365074e706
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Feb 07 20:58:18 2011 +0100
+| | | | |  summary:     correct some mistake.
+| | | | |
+| | o | |  changeset:   2209:a076fd1237b7
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 25 22:11:03 2011 +0100
+| | | | |  summary:     reomve spuriou dump
+| | | | |
+| | o | |  changeset:   2208:f3ce89f615f8
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 25 21:48:48 2011 +0100
+| | | | |  summary:     add mpiAllReduce(umax,dmaxg,comm,mpiMAX);  where for real umax,dmaxg;
+| | | | |
+| | o | |  changeset:   2207:3a8495a5387a
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 25 11:40:33 2011 +0100
+| | | | |  summary:     add mpiAllReduce on real , long , complex data type
+| | | | |
+| | o | |  changeset:   2206:08fcb4d98a99
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Jan 23 14:34:11 2011 +0100
+| | | | |  summary:     Added tag 3.12-win32 for changeset bea855340647
+| | | | |
+| | o | |  changeset:   2205:bea855340647
+| | | | |  tag:         3.12-win32
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Jan 23 14:33:52 2011 +0100
+| | | | |  summary:     update  INNOVATION
+| | | | |
+| | o | |  changeset:   2204:f6a959c7600c
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Jan 22 21:44:24 2011 +0100
+| | | | |  summary:     correct configure for win32
+| | | | |
+| | o | |  changeset:   2203:e84ba8234183
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 20 13:59:58 2011 +0100
+| | | | |  summary:     correct typo
+| | | | |
+| | o | |  changeset:   2202:09ee2c12edb8
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 20 13:57:40 2011 +0100
+| | | | |  summary:     correct typo
+| | | | |
+| | o | |  changeset:   2201:fb724f3e09a2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 20 13:55:11 2011 +0100
+| | | | |  summary:     correct install idp file in mpi examples
+| | | | |
+| | o | |  changeset:   2200:dd0ca033a004
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 20 13:34:00 2011 +0100
+| | | | |  summary:     add tag for version 3.12
+| | | | |
+| | o | |  changeset:   2199:672e0042f083
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 20 13:29:52 2011 +0100
+| | | | |  summary:     Added tag 3.12 for changeset 270198a4a293
+| | | | |
+| | o | |  changeset:   2198:270198a4a293
+| | | | |  tag:         3.12
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 20 13:23:35 2011 +0100
+| | | | |  summary:     correct HISTORY
+| | | | |
+| | o | |  changeset:   2197:e983b6801336
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 20 08:32:41 2011 +0100
+| | | | |  summary:     coorect type in top Makefile
+| | | | |
+| | o | |  changeset:   2196:673a610cc96e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 23:26:38 2011 +0100
+| | | | |  summary:     correct mpi sover files
+| | | | |
+| | o | |  changeset:   2195:daea22ad31ee
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 19:43:33 2011 +0100
+| | | | |  summary:     correct examples++-mpi/Makefile.am
+| | | | |
+| | o | |  changeset:   2194:b5f8a0106cc0
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 19:30:02 2011 +0100
+| | | | |  summary:     add missing file
+| | | | |
+| | o | |  changeset:   2193:06476f221b1e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 18:19:58 2011 +0100
+| | | | |  summary:     correct medit makefile
+| | | | |
+| | o | |  changeset:   2192:9d6b4e63eb04
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 17:28:44 2011 +0100
+| | | | |  summary:     coorect make for install FreeFem++-CoCoa on MAcOS
+| | | | |
+| | o | |  changeset:   2191:60616abdc65f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 17:15:42 2011 +0100
+| | | | |  summary:     coorect MPI example ...
+| | | | |
+| | o | |  changeset:   2190:daa42faa6092
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 16:55:25 2011 +0100
+| | | | |  summary:     correct MPI example and // solver
+| | | | |
+| | o | |  changeset:   2189:0a5cc096d146
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 16:42:28 2011 +0100
+| | | | |  summary:     correct lot of MPI example
+| | | | |
+| | o | |  changeset:   2188:65e69cb8fa59
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 15:19:20 2011 +0100
+| | | | |  summary:     add missing files
+| | | | |
+| | o | |  changeset:   2187:41b69f3e4ffc
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Jan 19 14:00:15 2011 +0100
+| | | | |  summary:     - correct link proble in hips and hypre under linux
+| | | | |
+| | o | |  changeset:   2186:38874c1f5f5f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 18 23:39:31 2011 +0100
+| | | | |  summary:     add new MPI example DDM-Schwarz method
+| | | | |
+| | o | |  changeset:   2185:b8dc0377392a
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 18 18:59:26 2011 +0100
+| | | | |  summary:     correct mistake in doc
+| | | | |
+| | o | |  changeset:   2184:fb8651ab5956
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 18 18:45:59 2011 +0100
+| | | | |  summary:     see INNOVATION file for all modid
+| | | | |
+| | o | |  changeset:   2183:05d86033bc94
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 18 13:13:23 2011 +0100
+| | | | |  summary:     add README_MAC
+| | | | |
+| | o | |  changeset:   2182:309f9d972d67
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jan 17 23:43:41 2011 +0100
+| | | | |  summary:     correct isolineP1
+| | | | |
+| | o | |  changeset:   2181:f8e9984c708d
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jan 17 23:22:06 2011 +0100
+| | | | |  summary:     ass isolineP1  dynamic lib to build border  form isoline
+| | | | |
+| | o | |  changeset:   2180:7d53be5311f3
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jan 17 08:11:50 2011 +0100
+| | | | |  summary:     coorect spurious endl
+| | | | |
+| | o | |  changeset:   2179:3414092a9ef9
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jan 17 08:07:34 2011 +0100
+| | | | |  summary:     remove spurio endl
+| | | | |
+| | o | |  changeset:   2178:1d166fa13593
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jan 17 08:00:50 2011 +0100
+| | | | |  summary:     remove spurious cout
+| | | | |
+| | o | |  changeset:   2177:e413924e153f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Jan 17 00:04:56 2011 +0100
+| | | | |  summary:     add macro def;
+| | | | |
+| | o | |  changeset:   2176:e218c243ce05
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 13 22:18:17 2011 +0100
+| | | | |  summary:     correct for MINGW load.link
+| | | | |
+| | o | |  changeset:   2175:272b85192249
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 13 21:04:05 2011 +0100
+| | | | |  summary:     correct FLIBS on win32 case
+| | | | |
+| | o | |  changeset:   2174:e3f2a110bb91
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Jan 13 17:19:04 2011 +0100
+| | | | |  summary:     add gsl interface
+| | | | |
+| | o | |  changeset:   2173:a06e9ccb53fd
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Jan 04 17:50:50 2011 +0100
+| | | | |  summary:     add mesure for area of 2d mesh to by compatible this 3d mesh
+| | | | |
+| | o | |  changeset:   2172:6e8a3de60010
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 25 09:23:14 2010 +0100
+| | | | |  summary:     update te doc
+| | | | |
+| | o | |  changeset:   2171:d4cbf3a97506
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 25 08:22:35 2010 +0100
+| | | | |  summary:     see innovation
+| | | | |
+| | o | |  changeset:   2170:f2016b3dac72
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 25 07:26:48 2010 +0100
+| | | | |  summary:     crrect configure.ac to be compatible with new version
+| | | | |
+| | o | |  changeset:   2169:65a4886d5bc8
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 23 11:10:04 2010 +0100
+| | | | |  summary:     Add brute force for seach of poit to be sure
+| | | | |
+| | o | |  changeset:   2168:9ccdb108f833
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Dec 21 12:38:05 2010 +0100
+| | | | |  summary:     add tgv < 0 => no tgv = so we  put 0 on line except 1 on dig term on matrix probleme.
+| | | | |
+| | o | |  changeset:   2167:42f714837f49
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Dec 12 00:15:38 2010 +0100
+| | | | |  summary:     mpi win32 suire ...
+| | | | |
+| | o | |  changeset:   2166:ba43bd5ae9c2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Dec 12 00:11:57 2010 +0100
+| | | | |  summary:     mpi win32  suite
+| | | | |
+| | o | |  changeset:   2165:18e9fd7513ef
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sun Dec 12 00:05:38 2010 +0100
+| | | | |  summary:     mpi coorect on win32
+| | | | |
+| | o | |  changeset:   2164:4a2a7e6595ab
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 11 23:41:02 2010 +0100
+| | | | |  summary:     correct parallele version for win32
+| | | | |
+| | o | |  changeset:   2163:3956acc41dd1
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 11 21:10:00 2010 +0100
+| | | | |  summary:     change mpi ef trouth pointer
+| | | | |
+| | o | |  changeset:   2162:4aacb445efc2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 11 14:27:23 2010 +0100
+| | | | |  summary:     correct pb CNOFLAGS (no opt CFLAGS for medir) under windows
+| | | | |
+| | o | |  changeset:   2161:34a9d49cc35e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 11 14:11:57 2010 +0100
+| | | | |  summary:     next step
+| | | | |
+| | o | |  changeset:   2160:745e4814c1e2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Sat Dec 11 13:49:26 2010 +0100
+| | | | |  summary:     correct pb parallele-empty.cpp
+| | | | |
+| | o | |  changeset:   2159:a9e710fd658e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Dec 10 23:51:33 2010 +0100
+| | | | |  summary:     add src/mpi/parallelempi-empty.cpp
+| | | | |
+| | o | |  changeset:   2158:ff130a08ed27
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Dec 10 10:14:09 2010 +0100
+| | | | |  summary:     change default parameter in examples++-mpi/MPIGMRES3D.edp
+| | | | |
+| | o | |  changeset:   2157:00ba78e75b34
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 09 19:41:01 2010 +0100
+| | | | |  summary:     last modif for v 3.11 (may be)
+| | | | |
+| | o | |  changeset:   2156:522db0c6b622
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 09 18:16:14 2010 +0100
+| | | | |  summary:     updeta doc an exp
+| | | | |
+| | o | |  changeset:   2155:4932c2907ee9
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 09 17:04:13 2010 +0100
+| | | | |  summary:     add macro quting
+| | | | |
+| | o | |  changeset:   2154:df881e2db1cd
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 09 14:34:07 2010 +0100
+| | | | |  summary:     coorect type in getany (all int are long in freefem++)
+| | | | |
+| | o | |  changeset:   2153:5545e58c84ba
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 09 10:59:03 2010 +0100
+| | | | |  summary:     correct tetgen set coorect defauft valeu in nbregion, nbhole, ...
+| | | | |
+| | o | |  changeset:   2152:143e4c285e2e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 09 10:34:14 2010 +0100
+| | | | |  summary:     correct doc and mmg3-d interface
+| | | | |
+| | o | |  changeset:   2151:ffed0beed0f2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Dec 08 23:54:37 2010 +0100
+| | | | |  summary:     correct pb picking ffmedit remove -O flags
+| | | | |
+| | o | |  changeset:   2150:ee5ac6c2b487
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Dec 08 18:10:50 2010 +0100
+| | | | |  summary:     update makefie
+| | | | |
+| | o | |  changeset:   2149:a01cfcb5089f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Dec 08 17:33:38 2010 +0100
+| | | | |  summary:     coorect freeeyam mshmet to a-have more clean option
+| | | | |
+| | o | |  changeset:   2148:8016ff3a5430
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Dec 07 18:02:17 2010 +0100
+| | | | |  summary:     update mmg3d interface
+| | | | |
+| | o | |  changeset:   2147:54b806e85c3e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Dec 07 16:32:06 2010 +0100
+| | | | |  summary:     coorect mshmet ..
+| | | | |
+| | o | |  changeset:   2146:00ebac7181ed
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Dec 07 14:57:59 2010 +0100
+| | | | |  summary:     coorect configure.ac pb this blascoorectr freeyam interface with metric
+| | | | |
+| | o | |  changeset:   2145:444b58f89a98
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Dec 07 13:36:42 2010 +0100
+| | | | |  summary:     coorect freeyams aniso
+| | | | |
+| | o | |  changeset:   2144:de793b3e90c2
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Dec 03 17:44:00 2010 +0100
+| | | | |  summary:     add seach of MKL lib in configure (hard job)
+| | | | |
+| | o | |  changeset:   2143:baa57509c9cd
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Dec 02 23:17:52 2010 +0100
+| | | | |  summary:     see INNOVATION correct MPIGMREs[23]d.edp example
+| | | | |
+| | o | |    changeset:   2142:c01832c2d91e
+| | |\ \ \   parent:      2141:1ca02db51865
+| | | | | |  parent:      2140:bae26bfb0b8c
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Dec 01 16:24:20 2010 +0100
+| | | | | |  summary:     merge ???
+| | | | | |
+| | | o | |  changeset:   2141:1ca02db51865
+| | | | | |  parent:      2139:d87b27635075
+| | | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | | |  date:        Wed Dec 01 15:06:40 2010 +0100
+| | | | | |  summary:     remove file
+| | | | | |
+| | o | | |  changeset:   2140:bae26bfb0b8c
+| | |/ / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |    date:        Wed Dec 01 10:44:59 2010 +0100
+| | | | |    summary:     correct typo
+| | | | |
+| | o | |  changeset:   2139:d87b27635075
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Dec 01 10:38:32 2010 +0100
+| | | | |  summary:     correct the documenation
+| | | | |
+| | o | |  changeset:   2138:9b4cf63d9799
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 30 22:07:42 2010 +0100
+| | | | |  summary:     add file for mlk lib .
+| | | | |
+| | o | |  changeset:   2137:6ebd89576da6
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 30 21:05:05 2010 +0100
+| | | | |  summary:     correct WHERE_LIBRARY-downlaod creation
+| | | | |
+| | o | |  changeset:   2136:9f7e115581d0
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 30 19:17:18 2010 +0100
+| | | | |  summary:     correct mistake in construction of WHERE.gmm file
+| | | | |
+| | o | |  changeset:   2135:d0ec37b43744
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 30 17:50:39 2010 +0100
+| | | | |  summary:     go version 3.10-3
+| | | | |
+| | o | |  changeset:   2134:c00bebf2d35f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 30 15:47:39 2010 +0100
+| | | | |  summary:     do coorect of periodic boundary condition + MUMPS link order
+| | | | |
+| | o | |  changeset:   2133:0ce681a3f66e
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 25 22:06:41 2010 +0100
+| | | | |  summary:     add missing file
+| | | | |
+| | o | |  changeset:   2132:c0a45d4c82a9
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 25 21:50:27 2010 +0100
+| | | | |  summary:     correct spurious print with verbosity !=0
+| | | | |
+| | o | |  changeset:   2131:d0756d2ae8ed
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 25 21:37:14 2010 +0100
+| | | | |  summary:     remove spurio print
+| | | | |
+| | o | |  changeset:   2130:9c81e54436fb
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 25 14:16:34 2010 +0100
+| | | | |  summary:     correct Laplace-Adapt-3d.edp
+| | | | |
+| | o | |  changeset:   2129:d0f9a7e3ce91
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 24 21:20:18 2010 +0100
+| | | | |  summary:     correct Laplace-Adapt-3d.edp
+| | | | |
+| | o | |  changeset:   2128:9628d985d017
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 24 08:55:48 2010 +0100
+| | | | |  summary:     coorect pb compiel on gnome
+| | | | |
+| | o | |  changeset:   2127:934ff69faf4a
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 24 08:39:29 2010 +0100
+| | | | |  summary:     add err comment in case of mesh with isolated vertex
+| | | | |
+| | o | |  changeset:   2126:e05ac461f21d
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 23 13:54:07 2010 +0100
+| | | | |  summary:     update INNOVATION
+| | | | |
+| | o | |  changeset:   2125:5633591673ba
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 23 08:14:13 2010 +0100
+| | | | |  summary:     correct 3d adaptation , try to build a first true example
+| | | | |
+| | o | |  changeset:   2124:76dc4c8a0cbb
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 23 07:17:26 2010 +0100
+| | | | |  summary:     add function to cast formal array into array []  toZarray,toRarray , toCarray
+| | | | |
+| | o | |  changeset:   2123:ecb2452ebe90
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Nov 19 11:37:52 2010 +0100
+| | | | |  summary:     add getARGV tools
+| | | | |
+| | o | |  changeset:   2122:9297b462cd46
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 18 16:31:52 2010 +0100
+| | | | |  summary:     next step for ff-mpirun install (dur dur)
+| | | | |
+| | o | |  changeset:   2121:80914a8bb776
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 18 16:11:24 2010 +0100
+| | | | |  summary:     coorect makefile for ff-mpirun and add srandomdev by read /dev/random + time
+| | | | |
+| | o | |  changeset:   2120:27361d73a03b
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 17 22:04:05 2010 +0100
+| | | | |  summary:     continung tyoo error ff-mpirun
+| | | | |
+| | o | |  changeset:   2119:a4a681882e69
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 17 21:54:25 2010 +0100
+| | | | |  summary:     correct typo of  ff-mpirun  in configure.ac
+| | | | |
+| | o | |  changeset:   2118:967660b728d5
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 17 21:46:20 2010 +0100
+| | | | |  summary:     coorect the previous add ff-run
+| | | | |
+| | o | |  changeset:   2117:43b0bed1bd5b
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 17 21:13:52 2010 +0100
+| | | | |  summary:     coorect INNOVATION
+| | | | |
+| | o | |  changeset:   2116:993567388442
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 17 21:11:58 2010 +0100
+| | | | |  summary:     add ff-mpirun to launch freefem++-mpi simply
+| | | | |
+| | o | |  changeset:   2115:94e4e901b405
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Wed Nov 17 08:03:01 2010 +0100
+| | | | |  summary:     correct mistake
+| | | | |
+| | o | |  changeset:   2114:d684b3efa24f
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 16 22:37:26 2010 +0100
+| | | | |  summary:     correct typo error  in fftw3  in WHERE_LIBRARY-config
+| | | | |
+| | o | |  changeset:   2113:79e95c94d4a5
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 16 20:09:36 2010 +0100
+| | | | |  summary:     correct mistyping in metis.cpp
+| | | | |
+| | o | |  changeset:   2112:09b6d06266af
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 16 19:53:30 2010 +0100
+| | | | |  summary:     romve cout in metis.cpp
+| | | | |
+| | o | |  changeset:   2111:ac951e2d8008
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 16 19:51:00 2010 +0100
+| | | | |  summary:     remove strange dump
+| | | | |
+| | o | |  changeset:   2110:0addf52a6596
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Tue Nov 16 07:34:31 2010 +0100
+| | | | |  summary:     correct MPI version from gmone machine
+| | | | |
+| | o | |  changeset:   2109:18a79ce6b201
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Nov 15 20:36:31 2010 +0100
+| | | | |  summary:     coorect pb of comute of area of mesh some time
+| | | | |
+| | o | |  changeset:   2108:6e7efdc6c4cd
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Mon Nov 15 10:22:02 2010 +0100
+| | | | |  summary:     crrect atof, blas WHERE_LIBRARY
+| | | | |
+| | o | |  changeset:   2107:16dedee619b5
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Fri Nov 05 09:52:22 2010 +0100
+| | | | |  summary:     add nex example
+| | | | |
+| | o | |  changeset:   2106:5e33715c5809
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 04 19:23:41 2010 +0100
+| | | | |  summary:     correct output stream
+| | | | |
+| | o | |  changeset:   2105:ad9c5a3700f3
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 04 18:25:58 2010 +0100
+| | | | |  summary:     reove test in MPIGRES2D
+| | | | |
+| | o | |  changeset:   2104:27f8c8458b71
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 04 18:19:33 2010 +0100
+| | | | |  summary:     add missing file
+| | | | |
+| | o | |  changeset:   2103:3b3bdf3ac0c5
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 04 18:10:55 2010 +0100
+| | | | |  summary:     clean
+| | | | |
+| | o | |  changeset:   2102:b2b101c4208d
+| | | | |  parent:      2099:f9822a5aea7a
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 04 18:01:07 2010 +0100
+| | | | |  summary:     remove pb file
+| | | | |
+o | | | |  changeset:   2101:31c99c85707b
+| | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | | |  date:        Thu Nov 04 17:48:49 2010 +0100
+| | | | |  summary:     add missing idp files
+| | | | |
+o---+ | |  changeset:   2100:79615779ae45
+  | | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+ / / / /   date:        Thu Nov 04 17:48:14 2010 +0100
+| | | |    summary:     add new MPI example
+| | | |
+| o | |  changeset:   2099:f9822a5aea7a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Nov 04 16:50:40 2010 +0100
+| | | |  summary:     add BinaryIO  dynamic lib  in example++-load
+| | | |
+| o | |  changeset:   2098:530dbd02d812
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 27 14:54:30 2010 +0200
+| | | |  summary:     change the default  size of MPI buf to 1Mo
+| | | |
+| o | |  changeset:   2097:74a69bae2f83
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Oct 25 14:10:59 2010 +0200
+| | | |  summary:     correct MPIGMRES examples
+| | | |
+| o | |  changeset:   2096:65da29614162
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 22 21:26:27 2010 +0200
+| | | |  summary:     correct if (1) ; // trap
+| | | |
+| o | |  changeset:   2095:1388d0f67de2
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 22 15:20:08 2010 +0200
+| | | |  summary:     change configure.ac protect MPICMD flags Tanks to P. gostaff
+| | | |
+| o | |  changeset:   2094:d732b07cba51
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 22 15:16:58 2010 +0200
+| | | |  summary:     reomve peace of cade for AutoDiff not use
+| | | |
+| o | |  changeset:   2093:06b5aeacde3c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 22 14:08:30 2010 +0200
+| | | |  summary:     Add MPI CG/GMRES function  for // computing
+| | | |
+| o | |  changeset:   2092:ff22b8c7a500
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 08 15:39:32 2010 +0200
+| | | |  summary:     update INNOVATION
+| | | |
+| o | |  changeset:   2091:2d8b5240b671
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 08 14:12:54 2010 +0200
+| | | |  summary:     correct the bug fing by  O. Pantz  in expression like ;  a(2:)=A^-1*b(1,:)
+| | | |
+| o | |  changeset:   2090:0ab0cc381341
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Oct 06 17:02:11 2010 +0200
+| | | |  summary:     correct make check in 3d examples dir
+| | | |
+| o | |  changeset:   2089:3d4959d4b6e1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 18:34:02 2010 +0200
+| | | |  summary:     add missing file
+| | | |
+| o | |  changeset:   2088:3748aed79d1c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 16:34:40 2010 +0200
+| | | |  summary:     Added tag release_3_10 for changeset f96e7099dbed
+| | | |
+| o | |  changeset:   2087:f96e7099dbed
+| | | |  tag:         release_3_10
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 16:32:09 2010 +0200
+| | | |  summary:     coorect INNOVATION
+| | | |
+| o | |  changeset:   2086:a0a40e1e3132
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 16:02:04 2010 +0200
+| | | |  summary:     add missing install files
+| | | |
+| o | |  changeset:   2085:caf345bbc560
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 15:22:43 2010 +0200
+| | | |  summary:     correct install mpi dymanics libs
+| | | |
+| o | |  changeset:   2084:03ddaceddb3e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 14:50:46 2010 +0200
+| | | |  summary:     add install of dynamic lin in mpi
+| | | |
+| o | |  changeset:   2083:b689c5e0ebb4
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 14:06:32 2010 +0200
+| | | |  summary:     add "-cd" argument to change current directory to edp script directory
+| | | |
+| o | |  changeset:   2082:c0c0d05d486c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 11:30:08 2010 +0200
+| | | |  summary:     coorect missing compile parameter in pARMS libs
+| | | |
+| o | |  changeset:   2081:8626f17af8a6
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 10:49:26 2010 +0200
+| | | |  summary:     correct configure.ac for automatic download of mmg3d lib.
+| | | |
+| o | |  changeset:   2080:672655247fbf
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Oct 05 00:42:30 2010 +0200
+| | | |  summary:     do modif of g++-4.6
+| | | |
+| o | |  changeset:   2079:5b727e03ff94
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 01 16:36:38 2010 +0200
+| | | |  summary:     mistake in parm makefile
+| | | |
+| o | |  changeset:   2078:e0137efef48d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 01 16:10:58 2010 +0200
+| | | |  summary:     version ok for ubuntu 64
+| | | |
+| o | |  changeset:   2077:f43ece160238
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 01 15:47:06 2010 +0200
+| | | |  summary:     correctr for version 2.10xs
+| | | |
+| o | |  changeset:   2076:f0b9786353ec
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 01 15:13:40 2010 +0200
+| | | |  summary:     coorection fort 3.10 version
+| | | |
+| o | |  changeset:   2075:bc78bc18d0b1
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Oct 01 12:46:55 2010 +0200
+| | | |  summary:     try to close version 3.10
+| | | |
+| o | |  changeset:   2074:e2b8cf20c61b
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 29 16:33:21 2010 +0200
+| | | |  summary:     correct IntallWHERE in gmm makefiel
+| | | |
+| o | |  changeset:   2073:10b7a602f98f
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 29 15:38:54 2010 +0200
+| | | |  summary:     correct parms Makefile
+| | | |
+| o | |  changeset:   2072:9440ff46f0ea
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Sep 29 14:19:58 2010 +0200
+| | | |  summary:     Add missing  exemple
+| | | |
+| o | |  changeset:   2071:e843df1be44d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 22:05:42 2010 +0200
+| | | |  summary:     correct -fPIC flags un blacs compilation
+| | | |
+| o | |  changeset:   2070:39392778a85e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 21:24:17 2010 +0200
+| | | |  summary:     update INNOVATION
+| | | |
+| o | |  changeset:   2069:22cc87fe9e3d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 19:14:38 2010 +0200
+| | | |  summary:     corecct MUMPS Makefile (missing CC,FC compile  flags -fPIC )
+| | | |
+| o | |  changeset:   2068:596ef1aa8971
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 15:12:33 2010 +0200
+| | | |  summary:     do autorecconf for add HAVE_SYS_TIME_H
+| | | |
+| o | |  changeset:   2067:ea3d2e60219d
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 15:10:08 2010 +0200
+| | | |  summary:     coorect gmm Makefile for WHERE ...
+| | | |
+| o | |  changeset:   2066:e17ed9466e08
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 14:13:01 2010 +0200
+| | | |  summary:     correct pb on download/bin creation (so time it a file not a dir)
+| | | |
+| o | |  changeset:   2065:a1c8c12f1363
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 12:19:21 2010 +0200
+| | | |  summary:     correct gmm compile and WHERE def.
+| | | |
+| o | |  changeset:   2064:1bed39d421c9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Sep 21 07:55:41 2010 +0200
+| | | |  summary:     correct PB with echo_edp
+| | | |
+| o | |  changeset:   2063:14e807f30896
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Sep 20 22:49:04 2010 +0200
+| | | |  summary:     coorect Makefile of mmglib download ..
+| | | |
+| o | |  changeset:   2062:2005c8d27803
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Sep 20 21:34:12 2010 +0200
+| | | |  summary:     correct mmg3lib  precompile
+| | | |
+| o | |  changeset:   2061:77b950c53405
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Sep 20 20:36:40 2010 +0200
+| | | |  summary:     add new parameter -ne  to remove script output
+| | | |
+| o | |  changeset:   2060:90c7c0e87652
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Sep 09 15:43:29 2010 +0200
+| | | |  summary:     add gmm and corretc load.link.in for windows
+| | | |
+| o | |  changeset:   2059:04ef78a06b11
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 31 13:18:25 2010 +0200
+| | | |  summary:     update README
+| | | |
+| o | |  changeset:   2058:9f3f911348ff
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 31 13:11:27 2010 +0200
+| | | |  summary:     corect innovation
+| | | |
+| o | |  changeset:   2057:87b6d7922730
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 31 13:10:35 2010 +0200
+| | | |  summary:     add missing compila of mshmet dynamc lib
+| | | |
+| o | |  changeset:   2056:5b51781d6c92
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 31 13:02:05 2010 +0200
+| | | |  summary:     upate INNOVATION
+| | | |
+| o | |  changeset:   2055:1235170c0a9e
+| | | |  parent:      2053:0b6fd3c42d32
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Aug 31 12:56:55 2010 +0200
+| | | |  summary:     correct examples++-load/Makefile.am to recreate examples++-load/WHERE_LIBRARY-download
+| | | |
+o | | |  changeset:   2054:f3cbf7394995
+|/ / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |    date:        Tue Aug 31 12:42:00 2010 +0200
+| | |    summary:     coorect typo in asssert mmg3d.cpp
+| | |
+o | |  changeset:   2053:0b6fd3c42d32
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Tue Aug 31 12:30:33 2010 +0200
+| | |  summary:     coorech WHERE of mshlib
+| | |
+o | |  changeset:   2052:b3e9a365ee44
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Tue Aug 31 12:22:40 2010 +0200
+| | |  summary:     add build WHERE
+| | |
+o | |  changeset:   2051:ac3551adc8c2
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Tue Aug 31 11:31:55 2010 +0200
+| | |  summary:     coorect mshmet download compile / makefile
+| | |
+o | |  changeset:   2050:4d081c4fdc8b
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Tue Aug 31 10:00:33 2010 +0200
+| | |  summary:     correct problem of -fPIC compile option in NOOPT  C ompile setup in superludist
+| | |
+o | |  changeset:   2049:b31ed80c5418
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Aug 30 22:52:10 2010 +0200
+| | |  summary:     coorect INNOVATION and auto compile fftw under win32
+| | |
+o | |  changeset:   2048:650bf83f02fc
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Aug 30 22:46:35 2010 +0200
+| | |  summary:     correct problem of creation download/bin  as a file not a dir.
+| | |
+o | |    changeset:   2047:f08673def206
+|\ \ \   parent:      2046:d4c390fea2f5
+| | | |  parent:      2043:3e424de88d66
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 30 17:30:19 2010 +0200
+| | | |  summary:     pass to version 3.9-2
+| | | |
+| o | |  changeset:   2046:d4c390fea2f5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 30 17:27:51 2010 +0200
+| | | |  summary:     correct compile of freeyams and mmg3d under win32
+| | | |
+| o | |  changeset:   2045:008b77f57a47
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 30 16:39:06 2010 +0200
+| | | |  summary:     add missing file
+| | | |
+| o | |  changeset:   2044:226800ecaa6d
+| | | |  parent:      2041:76820d79834a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 30 16:26:41 2010 +0200
+| | | |  summary:     put c++ maning in eigen.h
+| | | |
+o | | |  changeset:   2043:3e424de88d66
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Aug 30 13:56:19 2010 +0200
+| | | |  summary:     correc mmg3d interface (j. Morice) )
+| | | |
+o | | |  changeset:   2042:e6a1f7c85239
+|/ / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |    date:        Mon Aug 30 13:43:47 2010 +0200
+| | |    summary:     coorect mmg3d interface
+| | |
+o | |  changeset:   2041:76820d79834a
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Mon Aug 30 10:31:52 2010 +0200
+| | |  summary:     correct DOC and add dep in ilut.cpp
+| | |
+o | |  changeset:   2040:6e07fc2d42f8
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 27 17:53:53 2010 +0200
+| | |  summary:     update INNOVATION remove warning on pastix
+| | |
+o | |  changeset:   2039:7cf7e1a0a897
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 27 17:51:18 2010 +0200
+| | |  summary:     correct  problem to compile pastix, scotch  undex ubuntu linux.
+| | |
+o | |  changeset:   2038:f6214647e5ab
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 27 16:32:55 2010 +0200
+| | |  summary:     coorect -fPIC option on Fortrn
+| | |
+o | |  changeset:   2037:e79df603fcab
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 27 11:17:59 2010 +0200
+| | |  summary:     coorect fftw Makefie
+| | |
+o | |  changeset:   2036:99c51676b313
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 27 11:00:33 2010 +0200
+| | |  summary:     coorect mpi examples essa.edp an add wiat=1 in all medit call (bug on mac ???)
+| | |
+o | |  changeset:   2035:7b14eaf9f3ed
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 27 09:32:47 2010 +0200
+| | |  summary:     update INNOVATION
+| | |
+o | |  changeset:   2034:0692ff74ab24
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 27 09:28:57 2010 +0200
+| | |  summary:     correct problem of dynamic lib with or without mpi
+| | |
+o | |  changeset:   2033:c91026108711
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Thu Aug 26 20:39:46 2010 +0200
+| | |  summary:     add missing file DOC/plots/multiendmesh.eps
+| | |
+o | |  changeset:   2032:e6b7488922a9
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Thu Aug 26 20:37:52 2010 +0200
+| | |  summary:     add missing file
+| | |
+o | |  changeset:   2031:704b3d3af23d
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Thu Aug 26 18:55:46 2010 +0200
+| | |  summary:     See INNOVATION file for explaination of this change
+| | |
+o | |  changeset:   2030:e773af6b91a7
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Aug 06 11:26:27 2010 +0200
+| | |  summary:     correct configure mpi search when no full path are given (FH).
+| | |
+o | |  changeset:   2029:922d59d4af75
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Sat Jul 10 22:06:05 2010 +0200
+| | |  summary:     correct mistake in download/pastix/Makefile
+| | |
+o | |  changeset:   2028:a2bd2ad4e78a
+| | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |  date:        Fri Jul 09 21:06:22 2010 +0200
+| | |  summary:     update REDME and INNOVATION
+| | |
+o | |    changeset:   2027:14f495eec0bd
+|\ \ \   parent:      2025:6bc312b89041
+| | | |  parent:      2026:3b1e208730b0
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Jul 09 19:16:41 2010 +0200
+| | | |  summary:     coorect MUMPS link liste.
+| | | |
+| o | |  changeset:   2026:3b1e208730b0
+| | | |  parent:      2015:d14d5fe73ed9
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Jul 09 18:57:24 2010 +0200
+| | | |  summary:     do change un MUMPS_FreeFem.cpp
+| | | |
+o | | |  changeset:   2025:6bc312b89041
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Fri Jul 09 18:51:13 2010 +0200
+| | | |  summary:     correct a mistake in set  metric in adapt mesh, thank to J-F Remarcle.
+| | | |
+o | | |  changeset:   2024:e08ce8c8a5d2
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 30 22:39:42 2010 +0200
+| | | |  summary:     correct missing mpi_include flges in superlu-dist makefile
+| | | |
+o | | |  changeset:   2023:121ef5fadbf5
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 30 18:38:41 2010 +0200
+| | | |  summary:     update
+| | | |
+o | | |  changeset:   2022:e38e2dcabc3c
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 30 17:06:08 2010 +0200
+| | | |  summary:     add missing file and correct download/Makefile.am to remove
+| | | |
+o | | |  changeset:   2021:22b443fb5915
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 30 15:19:30 2010 +0200
+| | | |  summary:     correct pastix complex interface
+| | | |
+o | | |  changeset:   2020:b469944f3b63
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Tue Jun 29 13:59:08 2010 +0200
+| | | |  summary:     corret ff-get-dep.in
+| | | |
+o | | |  changeset:   2019:7613e18949b0
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Mon Jun 28 10:49:33 2010 +0200
+| | | |  summary:     remove stupid  assert (matrix sym is CG)
+| | | |
+o | | |  changeset:   2018:6be89be787cc
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Jun 26 22:02:09 2010 +0200
+| | | |  summary:     correct hips and pastix interface
+| | | |
+o | | |  changeset:   2017:e95f7c430680
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Sat Jun 26 21:59:25 2010 +0200
+| | | |  summary:     coorect stupid bug (due to remove static).
+| | | |
+o | | |  changeset:   2016:4b93ae958d23
+|/ / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |    date:        Sat Jun 26 21:46:05 2010 +0200
+| | |    summary:     Correct pastix
+| | |
+o | |    changeset:   2015:d14d5fe73ed9
+|\ \ \   parent:      2010:3bcb7b38c34a
+| | | |  parent:      2014:7a83a063e59e
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jun 17 10:57:12 2010 +0200
+| | | |  summary:     update README_HG
+| | | |
+| o | |  changeset:   2014:7a83a063e59e
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Thu Jun 17 09:00:54 2010 +0200
+| | | |  summary:     Modified by Antoine Le Hyaric on iris.ann.jussieu.fr
+| | | |
+| o | |  changeset:   2013:b72032208ab2
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Jun 16 17:13:41 2010 +0200
+| | | |  summary:     Modified by Antoine Le Hyaric on iris.ann.jussieu.fr
+| | | |
+| o | |  changeset:   2012:85e200ee9012
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Jun 16 15:10:12 2010 +0200
+| | | |  summary:     Modified by Antoine Le Hyaric on iris.ann.jussieu.fr
+| | | |
+| o | |  changeset:   2011:8bf4c30f32bf
+| | | |  parent:      2007:b47cd9ba79ca
+| | | |  user:        Antoine Le Hyaric
+| | | |  date:        Wed Jun 16 10:44:29 2010 +0200
+| | | |  summary:     converting from CVS to Mercurial
+| | | |
+o | | |  changeset:   2010:3bcb7b38c34a
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Thu Jun 17 10:44:16 2010 +0200
+| | | |  summary:     correct download makefile
+| | | |
+o | | |  changeset:   2009:1ba4e27c2764
+| | | |  user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | | |  date:        Wed Jun 16 21:16:16 2010 +0200
+| | | |  summary:     add build .hgrc comment
+| | | |
+o | | |  changeset:   2008:7344a2077883
+|/ / /   user:        Frederic Hecht <frederic.hecht at upmc.fr>
+| | |    date:        Wed Jun 16 18:53:05 2010 +0200
+| | |    summary:     try
+| | |
+o | |  changeset:   2007:b47cd9ba79ca
+| | |  user:        Antoine Le Hyaric
+| | |  date:        Wed Jun 16 10:31:22 2010 +0200
+| | |  summary:     converting from CVS to Mercurial
+| | |
+o | |  changeset:   2006:3bb8e4bb93b7
+| | |  parent:      1962:f5cdd2662eb6
+| | |  user:        convert-repo
+| | |  date:        Wed Jun 16 07:27:03 2010 +0000
+| | |  summary:     update tags
+| | |
+| o |  changeset:   2005:815102f120b1
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Fri Jun 04 15:26:59 2004 +0200
+| | |  summary:     Compilation ok sur Hydre.
+| | |
+| o |  changeset:   2004:6eb70bcaac52
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Fri Jun 04 12:06:26 2004 +0200
+| | |  summary:     Compilation ok sur idared
+| | |
+| o |  changeset:   2003:ff717298a121
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Thu Jun 03 16:02:58 2004 +0200
+| | |  summary:     Les bibliothèques BLAS, ARPACK et UMFPACK sont automatiquement téléchargées
+| | |
+| o |  changeset:   2002:edf4f99d7e54
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed Jun 02 12:39:56 2004 +0200
+| | |  summary:     Configuration des telechargements en cours
+| | |
+| o |  changeset:   2001:06b2ccabec8d
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed Jun 02 12:30:30 2004 +0200
+| | |  summary:     Configuration des telechargements en cours
+| | |
+| o |  changeset:   2000:092b0b13310c
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed Jun 02 11:34:04 2004 +0200
+| | |  summary:     Ajout des libs Blas, Arpack et Umfpack en cours sous Windows
+| | |
+| o |  changeset:   1999:3fd33de0d94b
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue Jun 01 17:11:53 2004 +0200
+| | |  summary:     Premiere installation Windows
+| | |
+| o |  changeset:   1998:0def60c97d19
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Fri May 28 14:13:19 2004 +0200
+| | |  summary:     Le rpertoir src/std contient maintenant non plus une version x11 mais
+| | |
+| o |  changeset:   1997:2eaf38b528a1
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Thu May 27 17:00:47 2004 +0200
+| | |  summary:     Toute première version de FreeFem++ compilable sur Windows avec Cygwin,
+| | |
+| o |  changeset:   1996:931a8adc93ae
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed May 26 11:21:29 2004 +0200
+| | |  summary:     Clarification de quelques commentaires.
+| | |
+| o |  changeset:   1995:6bc565381b22
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 25 16:14:21 2004 +0200
+| | |  summary:     Trois options de configuration manuelle ajoutées:
+| | |
+| o |  changeset:   1994:f40848886dac
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 25 15:05:32 2004 +0200
+| | |  summary:     - Modification de la procédure de test pour exécuter les scripts all.edp
+| | |
+| o |  changeset:   1993:70dc0e4a4a0a
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 25 10:50:09 2004 +0200
+| | |  summary:     Automake ok pour X11 sur MacOS X.
+| | |
+| o |  changeset:   1992:b140ece42b7e
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Mon May 24 19:12:19 2004 +0200
+| | |  summary:     Ajoute l'extension "-g" à la version debug des programmes en vue
+| | |
+| o |  changeset:   1991:eed90ccfb2f9
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Mon May 24 18:19:41 2004 +0200
+| | |  summary:     Automake ok sur Debian/Testing.
+| | |
+| o |  changeset:   1990:75cdc2370b75
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Mon May 24 17:31:34 2004 +0200
+| | |  summary:     Test de la configuration Automake sur macserv2+X11: compilation ok.
+| | |
+| o |  changeset:   1989:746910bc7d39
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Mon May 24 14:57:10 2004 +0200
+| | |  summary:     Début de configuration de FreeFem++ sur Windows/Cygwin.
+| | |
+| o |  changeset:   1988:9e62c7a49ce5
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Mon May 24 11:19:18 2004 +0200
+| | |  summary:     Intégration de la bibliothèque Umfpack dans la configuration et
+| | |
+| o |  changeset:   1987:e413f1a2441f
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed May 19 15:46:55 2004 +0200
+| | |  summary:     Ajoute src/Eigen/eigenvalue.cpp dans la bibliothèque src/fflib/libff.a
+| | |
+| o |  changeset:   1986:7c581dff37a2
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed May 19 15:06:18 2004 +0200
+| | |  summary:     Première version de la procédure de test de non-regression.
+| | |
+| o |  changeset:   1985:dadd01f5b506
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed May 19 13:52:55 2004 +0200
+| | |  summary:     Amélioration de la gestion des numéros de version.
+| | |
+| o |  changeset:   1984:aa87846f7d99
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Wed May 19 11:05:24 2004 +0200
+| | |  summary:     Automake configuré sur macserv2
+| | |
+| o |  changeset:   1983:2f557c31cc18
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 18 18:10:17 2004 +0200
+| | |  summary:     Configuration de la compilation sur MacOSX toujours en cours.
+| | |
+| o |  changeset:   1982:f749df09dd6a
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 18 18:00:00 2004 +0200
+| | |  summary:     Configuration de la procédure de compilation sur MacOSX en cours.
+| | |
+| o |  changeset:   1981:82ad80a2167a
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 18 17:35:36 2004 +0200
+| | |  summary:     Compilation ok sur Debian/Testing et Debian/Unstable
+| | |
+| o |  changeset:   1980:fcd66b328bfb
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 18 17:08:36 2004 +0200
+| | |  summary:     Modification de l'arborescence des répertoires dans src/ afin de placer
+| | |
+| o |  changeset:   1979:775f666ab880
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Tue May 18 12:02:34 2004 +0200
+| | |  summary:     Transformation de la compilation de programmes multiples (-g, -nw, -x11, ...)
+| | |
+| o |  changeset:   1978:f8525919fd4c
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Mon May 17 11:46:26 2004 +0200
+| | |  summary:     Intégration de Arpack et Umfpack en cours sur plusieurs architectures
+| | |
+| o |  changeset:   1977:c78650dfe24a
+| | |  branch:      alh-autoconf
+| | |  user:        hecht
+| | |  date:        Mon May 17 11:23:06 2004 +0200
+| | |  summary:     *** empty log message ***
+| | |
+| o |  changeset:   1976:1e1d2a42cfb1
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Fri May 14 11:48:00 2004 +0200
+| | |  summary:     Test de la présence de mpiCC ajouté (s'il est absent, la version
+| | |
+| o |  changeset:   1975:a25dd9092df7
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Fri May 14 10:08:22 2004 +0200
+| | |  summary:     Extension de la recherche de la bibliothèque BLAS.
+| | |
+| o |  changeset:   1974:74d24eef730c
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Thu May 13 14:54:09 2004 +0200
+| | |  summary:     Quelques nouveaux fichiers installés par la procédure standard Autoreconf -i.
+| | |
+| o |  changeset:   1973:dfa4239b5f28
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Thu May 13 14:45:32 2004 +0200
+| | |  summary:     La procédure Automake + Autoconf a été testée sur Hydre (Debian Testing).
+| | |
+| o |  changeset:   1972:a00adb8d7dee
+| | |  branch:      alh-autoconf
+| | |  user:        lehyaric
+| | |  date:        Thu May 13 14:08:11 2004 +0200
+| | |  summary:     Essai de configuration de autoconf en cours.
+| | |
+| o |  changeset:   1971:44cb3e95ebcc
+| | |  branch:      alh-autoconf
+| | |  parent:      0:6d28b8993874
+| | |  user:        lehyaric
+| | |  date:        Thu May 13 14:00:37 2004 +0200
+| | |  summary:     Intégration de Autoconf et Automake dans la procédure de build en cours.
+| | |
+| | o  changeset:   1970:44a4659127b5
+| | |  branch:      graphical-user-interface-branch
+| | |  tag:         merged_from_gui_branch_to_trunk
+| | |  user:        lehyaric
+| | |  date:        Thu Nov 04 17:26:54 2004 +0100
+| | |  summary:     The zoom facility is operational.
+| | |
+| | o  changeset:   1969:5c2f1f4412eb
+| | |  branch:      graphical-user-interface-branch
+| | |  user:        lehyaric
+| | |  date:        Thu Oct 28 18:18:46 2004 +0200
+| | |  summary:     IDE client currently being debugged. IDE server not connected yet.
+| | |
+| | o  changeset:   1968:0b0a37bf6daa
+| | |  branch:      graphical-user-interface-branch
+| | |  user:        lehyaric
+| | |  date:        Wed Oct 27 16:16:51 2004 +0200
+| | |  summary:     Client/server IDE compiles, but the server process does not run yet.
+| | |
+| | o  changeset:   1967:c8afa28839f5
+| | |  branch:      graphical-user-interface-branch
+| | |  user:        lehyaric
+| | |  date:        Mon Oct 25 17:29:43 2004 +0200
+| | |  summary:     client/server framework done. But the program is still far from compiling.
+| | |
+| | o  changeset:   1966:f97ec9365063
+| | |  branch:      graphical-user-interface-branch
+| | |  user:        lehyaric
+| | |  date:        Thu Oct 21 17:19:57 2004 +0200
+| | |  summary:     Client/server version of FreeFEM++ IDE currently being implemented.
+| | |
+| | o  changeset:   1965:958059001887
+| | |  branch:      graphical-user-interface-branch
+| | |  user:        lehyaric
+| | |  date:        Thu Oct 21 10:39:01 2004 +0200
+| | |  summary:     Reverts object "Global" back to static storage temporarily, while Frederic
+| | |
+| | o  changeset:   1964:82cbca1c015f
+| | |  branch:      graphical-user-interface-branch
+| | |  user:        lehyaric
+| | |  date:        Fri Oct 15 16:57:02 2004 +0200
+| | |  summary:     The IDE is programmed and compiled, but not running yet.
+| | |
+| | o  changeset:   1963:510c87bb28bb
+| |/   branch:      graphical-user-interface-branch
+| |    parent:      0:6d28b8993874
+| |    user:        lehyaric
+| |    date:        Fri Oct 08 12:21:58 2004 +0200
+| |    summary:     First model of an Integrated Development Environment for FreeFem++.
+| |
+o |  changeset:   1962:f5cdd2662eb6
+| |  user:        hecht
+| |  date:        Fri Jun 04 16:26:08 2010 +0200
+| |  summary:     coorect sunstring tools
+| |
+o |  changeset:   1961:85ef460011b5
+| |  user:        hecht
+| |  date:        Fri Jun 04 13:27:24 2010 +0200
+| |  summary:     add missing cast operator from SubString to string
+| |
+o |  changeset:   1960:9d02a34af84e
+| |  user:        morice
+| |  date:        Thu Jun 03 11:54:37 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1959:60960c8ea65f
+| |  user:        morice
+| |  date:        Wed Jun 02 18:28:54 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1958:7c18ab4a9896
+| |  user:        hecht
+| |  date:        Tue May 11 15:27:37 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1957:a54b6ce6a7e3
+| |  user:        hecht
+| |  date:        Mon May 10 23:35:08 2010 +0200
+| |  summary:     continue WHERE configure.ac
+| |
+o |  changeset:   1956:1d450f2bff65
+| |  user:        hecht
+| |  date:        Mon May 10 22:34:17 2010 +0200
+| |  summary:     add where seach
+| |
+o |  changeset:   1955:7b465c06c9d2
+| |  user:        hecht
+| |  date:        Mon May 10 13:41:42 2010 +0200
+| |  summary:     essai find where for downlaod
+| |
+o |  changeset:   1954:395d818be60c
+| |  user:        hecht
+| |  date:        Mon May 10 13:37:11 2010 +0200
+| |  summary:     correct essai
+| |
+o |  changeset:   1953:140dcce8e72d
+| |  user:        hecht
+| |  date:        Mon May 10 13:35:14 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1952:427b025b4dc9
+| |  user:        hecht
+| |  date:        Mon May 10 11:54:05 2010 +0200
+| |  summary:     essai de generation de WHERE-LIB
+| |
+o |  changeset:   1951:6e7c71e22ab1
+| |  user:        hecht
+| |  date:        Sat May 08 20:44:14 2010 +0200
+| |  summary:     change MPI parameter
+| |
+o |  changeset:   1950:b924356b1e5b
+| |  user:        hecht
+| |  date:        Thu May 06 23:20:39 2010 +0200
+| |  summary:     try to find mpi with better way
+| |
+o |  changeset:   1949:908a3c5af9ad
+| |  user:        hecht
+| |  date:        Thu May 06 16:04:20 2010 +0200
+| |  summary:     update OP
+| |
+o |  changeset:   1948:745ef197dbca
+| |  user:        hecht
+| |  date:        Thu May 06 16:04:07 2010 +0200
+| |  summary:     update OP.
+| |
+o |  changeset:   1947:96c42270bc55
+| |  user:        hecht
+| |  date:        Thu May 06 15:03:39 2010 +0200
+| |  summary:     correct  win32 trick
+| |
+o |  changeset:   1946:f7b235f1755a
+| |  user:        hecht
+| |  date:        Thu May 06 14:34:18 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1945:9c1e8dcd9100
+| |  user:        hecht
+| |  date:        Thu May 06 14:33:58 2010 +0200
+| |  summary:     co
+| |
+o |  changeset:   1944:f081711c3135
+| |  user:        hecht
+| |  date:        Fri Apr 30 17:45:19 2010 +0200
+| |  summary:     change to freeyam
+| |
+o |  changeset:   1943:9fadf6558ab1
+| |  user:        hecht
+| |  date:        Fri Apr 30 08:25:05 2010 +0200
+| |  summary:     upat configire.ac
+| |
+o |  changeset:   1942:ffa7bb4d488a
+| |  user:        hecht
+| |  date:        Thu Apr 29 23:14:40 2010 +0200
+| |  summary:     add freeyams interface
+| |
+o |  changeset:   1941:18f1981049b6
+| |  user:        hecht
+| |  date:        Thu Apr 29 23:13:49 2010 +0200
+| |  summary:     update configure.ac for add MPIRUN
+| |
+o |  changeset:   1940:a4a4f315dc9c
+| |  user:        hecht
+| |  date:        Wed Apr 28 13:22:09 2010 +0200
+| |  summary:     a not to bad download directory
+| |
+o |  changeset:   1939:9d8173ab1050
+| |  user:        hecht
+| |  date:        Tue Apr 27 22:06:49 2010 +0200
+| |  summary:     mise a jour
+| |
+o |  changeset:   1938:23e898259fef
+| |  user:        hecht
+| |  date:        Tue Apr 27 14:30:52 2010 +0200
+| |  summary:     correct mistake in download dir
+| |
+o |  changeset:   1937:828fe5ca6699
+| |  user:        hecht
+| |  date:        Fri Apr 23 18:34:16 2010 +0200
+| |  summary:     add new file
+| |
+o |  changeset:   1936:55b9e8dbc3ff
+| |  user:        hecht
+| |  date:        Fri Apr 23 18:32:39 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1935:49eca60e042b
+| |  user:        hecht
+| |  date:        Fri Apr 23 11:24:01 2010 +0200
+| |  summary:     try to build automaticaly all parallele solver (huge work)
+| |
+o |  changeset:   1934:e5293a9cdc8a
+| |  user:        hecht
+| |  date:        Thu Apr 22 11:28:45 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1933:fc1f6516d8f0
+| |  user:        morice
+| |  date:        Thu Apr 15 16:46:45 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1932:d7e0beb48e5e
+| |  user:        morice
+| |  date:        Thu Apr 15 11:22:43 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1931:629f1fe03042
+| |  user:        morice
+| |  date:        Thu Apr 15 10:59:20 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1930:0c7899097de2
+| |  user:        morice
+| |  date:        Mon Apr 12 15:45:36 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1929:a2b19da7465a
+| |  user:        morice
+| |  date:        Mon Apr 12 15:36:54 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1928:86be041b52dd
+| |  user:        morice
+| |  date:        Mon Apr 12 15:19:21 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1927:937c2afd093f
+| |  user:        morice
+| |  date:        Thu Apr 08 16:43:25 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1926:923abf222ca2
+| |  user:        hecht
+| |  date:        Thu Apr 01 21:46:42 2010 +0200
+| |  summary:     pass to version 3.8-2
+| |
+o |  changeset:   1925:aacaad3df8f6
+| |  user:        morice
+| |  date:        Thu Apr 01 14:41:54 2010 +0200
+| |  summary:     orientation for element in movemesh3
+| |
+o |  changeset:   1924:11023f67b884
+| |  user:        hecht
+| |  date:        Thu Apr 01 10:47:43 2010 +0200
+| |  summary:     add sphere6.edp
+| |
+o |  changeset:   1923:83a1575669f0
+| |  user:        hecht
+| |  date:        Wed Mar 31 15:13:12 2010 +0200
+| |  summary:     correct
+| |
+o |  changeset:   1922:04a73c54e6ee
+| |  user:        hecht
+| |  date:        Wed Mar 31 14:55:09 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1921:08a259f0ce22
+| |  user:        morice
+| |  date:        Wed Mar 31 10:54:59 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1920:e36d5fe8cd03
+| |  user:        hecht
+| |  date:        Wed Mar 31 10:50:56 2010 +0200
+| |  summary:     coorect makefile
+| |
+o |  changeset:   1919:55571ba570f9
+| |  user:        hecht
+| |  date:        Wed Mar 31 10:31:56 2010 +0200
+| |  summary:     add  new makefile
+| |
+o |  changeset:   1918:e781b347a370
+| |  user:        hecht
+| |  date:        Tue Mar 30 13:45:47 2010 +0200
+| |  summary:     update parmetis files
+| |
+o |  changeset:   1917:d90c1e2a30f9
+| |  user:        morice
+| |  date:        Mon Mar 29 11:58:30 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1916:c4bcfced6f13
+| |  user:        morice
+| |  date:        Mon Mar 29 11:19:45 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1915:b80817aa7ee7
+| |  user:        morice
+| |  date:        Mon Mar 29 11:07:16 2010 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1914:65fdb04766e3
+| |  user:        morice
+| |  date:        Fri Mar 26 17:38:56 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1913:f4000b122243
+| |  user:        morice
+| |  date:        Fri Mar 26 16:18:32 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1912:a33e7018c5a9
+| |  user:        morice
+| |  date:        Fri Mar 26 15:15:29 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1911:39e22b59029d
+| |  user:        hecht
+| |  date:        Mon Mar 22 17:18:27 2010 +0100
+| |  summary:     correct configure.ac  mpicxx  whta unset before
+| |
+o |  changeset:   1910:2c1683ac514a
+| |  user:        morice
+| |  date:        Mon Mar 22 12:24:25 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1909:8740c5457454
+| |  user:        morice
+| |  date:        Mon Mar 22 12:19:55 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1908:a3f4d18feef7
+| |  user:        morice
+| |  date:        Mon Mar 22 12:13:11 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1907:98cf6430a6d4
+| |  user:        morice
+| |  date:        Mon Mar 22 12:09:59 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1906:379861275764
+| |  user:        morice
+| |  date:        Fri Mar 19 15:37:02 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1905:b763fb4d6610
+| |  user:        morice
+| |  date:        Fri Mar 19 15:27:54 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1904:c86ddaec83d9
+| |  user:        morice
+| |  date:        Fri Mar 19 15:05:39 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1903:cd1703be1487
+| |  user:        morice
+| |  date:        Fri Mar 19 14:55:59 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1902:296133abf0d2
+| |  user:        morice
+| |  date:        Fri Mar 19 14:52:59 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1901:090d8fd21d56
+| |  user:        morice
+| |  date:        Fri Mar 19 14:43:48 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1900:8f61eac2a513
+| |  user:        morice
+| |  date:        Fri Mar 19 14:41:13 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1899:6747aaf6981a
+| |  user:        morice
+| |  date:        Fri Mar 19 14:40:11 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1898:fe5c75d39268
+| |  user:        morice
+| |  date:        Fri Mar 19 14:38:29 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1897:67532e425d3c
+| |  user:        morice
+| |  date:        Fri Mar 19 14:33:01 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1896:53e8bdd5722a
+| |  user:        morice
+| |  date:        Fri Mar 19 14:26:45 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1895:dad309f83d1a
+| |  user:        morice
+| |  date:        Fri Mar 19 14:22:24 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1894:42de76dbd6f2
+| |  user:        morice
+| |  date:        Fri Mar 19 14:18:40 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1893:6f2006878f1f
+| |  user:        morice
+| |  date:        Fri Mar 19 14:16:44 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1892:6aadc8bba606
+| |  user:        morice
+| |  date:        Fri Mar 19 13:41:21 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1891:4dc3e10452dd
+| |  user:        hecht
+| |  date:        Tue Mar 09 11:08:40 2010 +0100
+| |  summary:     correct type ilu.cpp -> ilut.cpp in makefile
+| |
+o |  changeset:   1890:6f245ceae4ce
+| |  user:        hecht
+| |  date:        Sun Mar 07 18:53:45 2010 +0100
+| |  summary:     add missing file
+| |
+o |  changeset:   1889:827ddd73fd36
+| |  user:        hecht
+| |  date:        Sun Mar 07 18:27:41 2010 +0100
+| |  summary:     pass to versio 3.8-1
+| |
+o |  changeset:   1888:216ef2fd580b
+| |  user:        hecht
+| |  date:        Sun Mar 07 18:16:30 2010 +0100
+| |  summary:     correct bug in return  real[int,int]  func
+| |
+o |  changeset:   1887:7f1fa00f6f88
+| |  user:        hecht
+| |  date:        Thu Feb 25 14:52:51 2010 +0100
+| |  summary:     add  flag in freefem++ command -ffg  'ffg command path'   with a traitement of space path.
+| |
+o |  changeset:   1886:eb7357e5511a
+| |  user:        hecht
+| |  date:        Wed Feb 10 16:30:50 2010 +0100
+| |  summary:     corct innovation
+| |
+o |  changeset:   1885:2542e1d811e8
+| |  user:        hecht
+| |  date:        Wed Feb 10 16:21:35 2010 +0100
+| |  summary:     correct  change renum triangle
+| |
+o |  changeset:   1884:2436e52254e4
+| |  user:        hecht
+| |  date:        Wed Feb 10 13:04:32 2010 +0100
+| |  summary:     add renumbering of  vertex in 2d mesh.
+| |
+o |  changeset:   1883:931d93f9ac39
+| |  user:        hecht
+| |  date:        Tue Feb 09 15:53:51 2010 +0100
+| |  summary:     add tellp tellg seekp seekg
+| |
+o |  changeset:   1882:4fc2a406c26d
+| |  user:        hecht
+| |  date:        Tue Feb 09 11:57:23 2010 +0100
+| |  summary:     add seekg and teelg
+| |
+o |  changeset:   1881:3d1237b0e08f
+| |  user:        hecht
+| |  date:        Tue Feb 09 10:00:13 2010 +0100
+| |  summary:     change all.edp build rule
+| |
+o |  changeset:   1880:10c734721deb
+| |  user:        hecht
+| |  date:        Mon Feb 08 19:58:31 2010 +0100
+| |  summary:     correct makefile
+| |
+o |  changeset:   1879:e3df8d40fb1c
+| |  user:        hecht
+| |  date:        Mon Feb 08 19:23:24 2010 +0100
+| |  summary:     add missing file
+| |
+o |  changeset:   1878:8a8a0b9efed9
+| |  user:        hecht
+| |  date:        Mon Feb 08 19:15:35 2010 +0100
+| |  summary:     correct  ' operator in lot of case
+| |
+o |  changeset:   1877:29d816db94eb
+| |  user:        hecht
+| |  date:        Thu Feb 04 20:30:07 2010 +0100
+| |  summary:     update INNOVATION
+| |
+o |  changeset:   1876:4ecd608b125d
+| |  user:        hecht
+| |  date:        Thu Feb 04 20:10:15 2010 +0100
+| |  summary:     unify lapack and fflapack load interface.
+| |
+o |  changeset:   1875:91c414a420a3
+| |  user:        morice
+| |  date:        Thu Feb 04 15:20:38 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1874:7af250db5757
+| |  user:        hecht
+| |  date:        Thu Feb 04 14:48:24 2010 +0100
+| |  summary:     correct lapack seack lib.
+| |
+o |  changeset:   1873:bf8ac5ac2f55
+| |  user:        hecht
+| |  date:        Thu Feb 04 11:15:07 2010 +0100
+| |  summary:     correct problem of include search path
+| |
+o |  changeset:   1872:fb13ee753e57
+| |  user:        hecht
+| |  date:        Wed Feb 03 09:22:35 2010 +0100
+| |  summary:     add 3d schwarz 3d
+| |
+o |  changeset:   1871:a422afbf9671
+| |  user:        hecht
+| |  date:        Tue Feb 02 20:51:19 2010 +0100
+| |  summary:     commeit tipo error
+| |
+o |  changeset:   1870:fc69c1fef879
+| |  user:        hecht
+| |  date:        Tue Feb 02 20:34:51 2010 +0100
+| |  summary:     add volume
+| |
+o |  changeset:   1869:c71bd076f2ec
+| |  user:        hecht
+| |  date:        Mon Feb 01 13:45:14 2010 +0100
+| |  summary:     add tools to get  fort wrapper name
+| |
+o |  changeset:   1868:f66e3f760562
+| |  user:        hecht
+| |  date:        Mon Feb 01 10:50:12 2010 +0100
+| |  summary:     Update co,figure.ac of MPIF77 , ...,  sizeof it, long
+| |
+o |  changeset:   1867:0d16ed2eac32
+| |  user:        hecht
+| |  date:        Sun Jan 31 17:24:57 2010 +0100
+| |  summary:     add MPI fortran and CC  interface
+| |
+o |  changeset:   1866:238d2e7a177d
+| |  user:        hecht
+| |  date:        Thu Jan 28 20:38:21 2010 +0100
+| |  summary:     correct edp to idp dir of  search .idp files
+| |
+o |  changeset:   1865:769324bb4d73
+| |  user:        hecht
+| |  date:        Thu Jan 28 17:44:36 2010 +0100
+| |  summary:     change refface= en label=
+| |
+o |  changeset:   1864:e7899c82f054
+| |  user:        hecht
+| |  date:        Mon Jan 25 09:10:25 2010 +0100
+| |  summary:     correct plot of array of FE  with new version
+| |
+o |  changeset:   1863:f298bac1900c
+| |  user:        hecht
+| |  date:        Mon Jan 25 07:17:34 2010 +0100
+| |  summary:     a littte improvante in ffglut (visu of 3d mesh)
+| |
+o |  changeset:   1862:2b1dc85030ca
+| |  user:        hecht
+| |  date:        Mon Jan 25 06:47:11 2010 +0100
+| |  summary:     ad seekp of ostream file ...
+| |
+o |  changeset:   1861:c1e242006cc8
+| |  user:        hecht
+| |  date:        Mon Jan 25 06:40:08 2010 +0100
+| |  summary:     correct topy in 3d plot
+| |
+o |  changeset:   1860:bf0657d69e94
+| |  user:        hecht
+| |  date:        Mon Jan 25 05:57:40 2010 +0100
+| |  summary:     remove F77_WRAPPER form configure trap on my mac with fort77
+| |
+o |  changeset:   1859:fe7b9cd0f709
+| |  user:        hecht
+| |  date:        Mon Jan 25 05:47:31 2010 +0100
+| |  summary:     pass to version 3.8
+| |
+o |  changeset:   1858:a9c19984fadd
+| |  user:        hecht
+| |  date:        Thu Jan 14 16:18:03 2010 +0100
+| |  summary:     coorect computation of eigen value on complex full matrix
+| |
+o |  changeset:   1857:f51530740c5c
+| |  user:        hecht
+| |  date:        Wed Jan 13 22:41:46 2010 +0100
+| |  summary:     add possibility  to put array in int1d,int2d,int3d,on key word to set
+| |
+o |  changeset:   1856:e6130f5019ba
+| |  user:        hecht
+| |  date:        Wed Jan 13 18:06:46 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1855:52a7add0311b
+| |  user:        hecht
+| |  date:        Wed Jan 13 18:03:59 2010 +0100
+| |  summary:     for mingw freeglut version ....
+| |
+o |  changeset:   1854:b7177e4145d5
+| |  user:        hecht
+| |  date:        Wed Jan 13 17:28:33 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1853:6d8ecc9202f5
+| |  user:        hecht
+| |  date:        Wed Jan 13 17:24:39 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1852:9bed1f5c517e
+| |  user:        hecht
+| |  date:        Wed Jan 13 17:16:01 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1851:5cc23ea21a59
+| |  user:        hecht
+| |  date:        Wed Jan 13 16:06:17 2010 +0100
+| |  summary:     correct typo in configure.ac under win32
+| |
+o |  changeset:   1850:2ba47239afb6
+| |  user:        hecht
+| |  date:        Wed Jan 13 15:14:59 2010 +0100
+| |  summary:     correct to must cou
+| |
+o |  changeset:   1849:421529d5cb67
+| |  user:        hecht
+| |  date:        Wed Jan 13 11:02:08 2010 +0100
+| |  summary:     correction in bamg for 2d ring shaped sub domaines
+| |
+o |  changeset:   1848:795d2400a80a
+| |  user:        hecht
+| |  date:        Tue Jan 12 23:38:00 2010 +0100
+| |  summary:     patch gmsh Christophe Trophime <christophe.trophime at grenoble.cnrs.fr>
+| |
+o |  changeset:   1847:03c7f9f5f133
+| |  user:        hecht
+| |  date:        Tue Jan 12 21:17:48 2010 +0100
+| |  summary:     try to build configure for mingw ...
+| |
+o |  changeset:   1846:48b1cd3c2e4b
+| |  user:        morice
+| |  date:        Tue Jan 12 16:15:59 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1845:f7b3d045a617
+| |  user:        hecht
+| |  date:        Tue Jan 12 13:53:05 2010 +0100
+| |  summary:     add exemple
+| |
+o |  changeset:   1844:c603be120d2d
+| |  user:        atenekeng
+| |  date:        Mon Jan 11 23:19:32 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1843:07d39562f84d
+| |  user:        hecht
+| |  date:        Mon Jan 11 21:02:55 2010 +0100
+| |  summary:     ass Superlu to version 4.0
+| |
+o |  changeset:   1842:9652d9a1931e
+| |  user:        hecht
+| |  date:        Mon Jan 11 17:52:18 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1841:735fdff39099
+| |  user:        hecht
+| |  date:        Sun Jan 10 22:47:14 2010 +0100
+| |  summary:     correct spuriou cout
+| |
+o |  changeset:   1840:6c1591ad5660
+| |  user:        morice
+| |  date:        Tue Jan 05 15:46:48 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1839:3b36b0cdd71f
+| |  user:        morice
+| |  date:        Tue Jan 05 14:10:13 2010 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1838:6453b34c9217
+| |  user:        hecht
+| |  date:        Sun Dec 27 19:17:04 2009 +0100
+| |  summary:     correct fortran link edition in case of incompatible g7è/gfortran and g++
+| |
+o |  changeset:   1837:5110dfd736f3
+| |  user:        hecht
+| |  date:        Sun Dec 27 19:01:36 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1836:6b80ef98c41c
+| |  user:        hecht
+| |  date:        Sun Dec 27 18:55:46 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1835:bc55abed1921
+| |  user:        hecht
+| |  date:        Sun Dec 27 18:51:04 2009 +0100
+| |  summary:     coorect gfrotran / lib pb
+| |
+o |  changeset:   1834:02bcb3362a47
+| |  user:        hecht
+| |  date:        Sun Dec 27 18:43:44 2009 +0100
+| |  summary:     correct configure un case of gfortran with not same version than gcc.
+| |
+o |  changeset:   1833:8ae1bbb6b9e1
+| |  user:        hecht
+| |  date:        Sun Dec 27 18:24:51 2009 +0100
+| |  summary:     correct iovtk.cpp (add tekplot case)
+| |
+o |  changeset:   1832:6e3050d3aacf
+| |  user:        hecht
+| |  date:        Sun Dec 27 12:09:54 2009 +0100
+| |  summary:     add build interpolation interpolation matrix in 3d
+| |
+o |  changeset:   1831:d117aa62e8d2
+| |  user:        hecht
+| |  date:        Fri Dec 18 10:00:30 2009 +0100
+| |  summary:     pass in version 3.7-1 and correct compilation CFLAGS  under  64 architecture.
+| |
+o |  changeset:   1830:749462a2fc20
+| |  user:        hecht
+| |  date:        Fri Dec 11 14:23:48 2009 +0100
+| |  summary:     trunc3d.cpp is now in mesh3.cpp
+| |
+o |  changeset:   1829:925d3a721e3f
+| |  user:        hecht
+| |  date:        Thu Dec 10 21:38:32 2009 +0100
+| |  summary:     add wait
+| |
+o |  changeset:   1828:a2e92cb3e6e3
+| |  user:        hecht
+| |  date:        Thu Dec 10 21:34:40 2009 +0100
+| |  summary:     remove this supite file in cvs
+| |
+o |  changeset:   1827:58d02edf2d0e
+| |  user:        hecht
+| |  date:        Thu Dec 10 21:33:19 2009 +0100
+| |  summary:     add trunc mesh in 3d.
+| |
+o |  changeset:   1826:dc4d33da9a55
+| |  user:        morice
+| |  date:        Thu Dec 10 16:35:06 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1825:6630293ece4e
+| |  user:        morice
+| |  date:        Thu Dec 10 16:25:01 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1824:e421852ce6a5
+| |  user:        morice
+| |  date:        Thu Dec 10 11:17:49 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1823:fff1817b0b36
+| |  user:        hecht
+| |  date:        Thu Dec 10 10:18:37 2009 +0100
+| |  summary:     change lg.y -> lg.ypp
+| |
+o |  changeset:   1822:40b7d100c5d8
+| |  user:        hecht
+| |  date:        Tue Dec 08 11:37:48 2009 +0100
+| |  summary:     suite
+| |
+o |  changeset:   1821:56eb1768a904
+| |  user:        hecht
+| |  date:        Tue Dec 08 11:36:21 2009 +0100
+| |  summary:     add info in INNOVATION
+| |
+o |  changeset:   1820:f7d8b4e0ae1d
+| |  user:        hecht
+| |  date:        Mon Dec 07 22:22:27 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1819:c1c8a95285bb
+| |  user:        hecht
+| |  date:        Mon Dec 07 18:17:16 2009 +0100
+| |  summary:     add example
+| |
+o |  changeset:   1818:fed850c6eb0f
+| |  user:        hecht
+| |  date:        Mon Dec 07 16:23:19 2009 +0100
+| |  summary:     do best plt of 3d meshes
+| |
+o |  changeset:   1817:c057f46814b0
+| |  user:        hecht
+| |  date:        Mon Dec 07 09:01:34 2009 +0100
+| |  summary:     coorect cube.idp and change 3d plot of mesh
+| |
+o |  changeset:   1816:72020a794a9e
+| |  user:        hecht
+| |  date:        Sat Dec 05 18:16:25 2009 +0100
+| |  summary:     remove imtempestive cout.
+| |
+o |  changeset:   1815:47a39d936529
+| |  user:        hecht
+| |  date:        Fri Dec 04 15:53:33 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1814:db02f8bf3214
+| |  user:        hecht
+| |  date:        Fri Dec 04 15:43:18 2009 +0100
+| |  summary:     correct FFLIGS flags of windows
+| |
+o |  changeset:   1813:137e79954fe7
+| |  user:        hecht
+| |  date:        Fri Dec 04 15:36:17 2009 +0100
+| |  summary:     remove copy of  header file form download directory
+| |
+o |  changeset:   1812:b4e4adbe84a3
+| |  user:        hecht
+| |  date:        Fri Dec 04 15:13:50 2009 +0100
+| |  summary:     add missing file
+| |
+o |  changeset:   1811:180008496671
+| |  user:        hecht
+| |  date:        Fri Dec 04 15:11:20 2009 +0100
+| |  summary:     add missing file
+| |
+o |  changeset:   1810:d8f3474d197b
+| |  user:        hecht
+| |  date:        Fri Dec 04 14:59:43 2009 +0100
+| |  summary:     correct   fortran flag in ff-c++ command
+| |
+o |  changeset:   1809:d52e91d99886
+| |  user:        hecht
+| |  date:        Fri Dec 04 14:37:58 2009 +0100
+| |  summary:     add new files for newuao optimiserx
+| |
+o |  changeset:   1808:625009875e58
+| |  user:        hecht
+| |  date:        Fri Dec 04 13:44:30 2009 +0100
+| |  summary:     change in innovation
+| |
+o |  changeset:   1807:10390fccf8b9
+| |  user:        hecht
+| |  date:        Thu Dec 03 10:49:42 2009 +0100
+| |  summary:     correct problem of free mesh to early in case off gluing
+| |
+o |  changeset:   1806:fc93d1454f21
+| |  user:        hecht
+| |  date:        Fri Nov 27 11:17:05 2009 +0100
+| |  summary:     add matrix<int>[int] type in grammar
+| |
+o |  changeset:   1805:bb43bba84bdf
+| |  user:        hecht
+| |  date:        Fri Nov 20 09:38:23 2009 +0100
+| |  summary:     remove warning
+| |
+o |  changeset:   1804:bff4956d8430
+| |  user:        hecht
+| |  date:        Fri Nov 20 09:35:47 2009 +0100
+| |  summary:     remove  some warning
+| |
+o |  changeset:   1803:08437a27c2a6
+| |  user:        hecht
+| |  date:        Thu Nov 19 22:14:40 2009 +0100
+| |  summary:     add example
+| |
+o |  changeset:   1802:24c6e35d1bda
+| |  user:        hecht
+| |  date:        Thu Nov 19 20:41:26 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1801:b22f5fecc9fa
+| |  user:        hecht
+| |  date:        Thu Nov 19 20:38:51 2009 +0100
+| |  summary:     add two examples
+| |
+o |  changeset:   1800:ea3546059a3b
+| |  user:        morice
+| |  date:        Thu Nov 19 16:49:22 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1799:6828802fdc80
+| |  user:        hecht
+| |  date:        Sat Nov 14 22:51:05 2009 +0100
+| |  summary:     in ffglut remove seg to small ???
+| |
+o |  changeset:   1798:416458502277
+| |  user:        hecht
+| |  date:        Fri Nov 13 22:32:37 2009 +0100
+| |  summary:     pass to version 3.7
+| |
+o |  changeset:   1797:5009b00a38ce
+| |  user:        hecht
+| |  date:        Fri Nov 13 12:19:41 2009 +0100
+| |  summary:     correct spouriou print
+| |
+o |  changeset:   1796:b1f05929d2d8
+| |  user:        hecht
+| |  date:        Wed Nov 11 22:46:19 2009 +0100
+| |  summary:     change
+| |
+o |  changeset:   1795:9543c5eca7b7
+| |  user:        hecht
+| |  date:        Wed Nov 11 22:45:29 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1794:a736d190fc78
+| |  user:        hecht
+| |  date:        Tue Nov 10 20:51:54 2009 +0100
+| |  summary:     correct install stuff
+| |
+o |  changeset:   1793:33efbea32b77
+| |  user:        hecht
+| |  date:        Tue Nov 10 20:28:07 2009 +0100
+| |  summary:     build WHERE_LIBRARY-config file for ff-c++ tools
+| |
+o |  changeset:   1792:1564d9e47726
+| |  user:        hecht
+| |  date:        Tue Nov 10 15:36:29 2009 +0100
+| |  summary:     add clapack.h interface
+| |
+o |  changeset:   1791:5df6bba70026
+| |  user:        hecht
+| |  date:        Tue Nov 10 14:33:50 2009 +0100
+| |  summary:     correct vtk files
+| |
+o |  changeset:   1790:9b3614fade98
+| |  user:        hecht
+| |  date:        Mon Nov 09 16:24:48 2009 +0100
+| |  summary:     passe to version  3.6-1
+| |
+o |  changeset:   1789:d4ba4d32c211
+| |  user:        hecht
+| |  date:        Mon Nov 09 15:22:29 2009 +0100
+| |  summary:     add PICHON stuff (for brute force seaching tet )
+| |
+o |  changeset:   1788:9066a9a4c83a
+| |  user:        hecht
+| |  date:        Mon Nov 09 11:59:11 2009 +0100
+| |  summary:     correct problem of missing to 2 functions with g++-4.4
+| |
+o |  changeset:   1787:c8afce8d6282
+| |  user:        hecht
+| |  date:        Mon Nov 09 11:56:46 2009 +0100
+| |  summary:     correct mistake this g+= 4.4 compiler
+| |
+o |  changeset:   1786:c7940961398f
+| |  user:        morice
+| |  date:        Fri Nov 06 11:46:05 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1785:5b9105ef4314
+| |  user:        morice
+| |  date:        Fri Nov 06 11:44:44 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1784:e8f258f9446a
+| |  user:        morice
+| |  date:        Fri Nov 06 11:41:40 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1783:3f117c9abc8d
+| |  user:        morice
+| |  date:        Fri Nov 06 10:50:32 2009 +0100
+| |  summary:     add new tetgen and medit edp file CVS: ----------------------------------------------------------------------
+| |
+o |  changeset:   1782:c6eda2a03844
+| |  user:        hecht
+| |  date:        Thu Nov 05 11:49:07 2009 +0100
+| |  summary:     add missing file.
+| |
+o |  changeset:   1781:0a6031f38b29
+| |  user:        hecht
+| |  date:        Wed Nov 04 12:56:48 2009 +0100
+| |  summary:     change innovation
+| |
+o |  changeset:   1780:8b10917a60ef
+| |  user:        hecht
+| |  date:        Tue Nov 03 21:38:30 2009 +0100
+| |  summary:     add auto stuff
+| |
+o |  changeset:   1779:8938281ebc2e
+| |  user:        hecht
+| |  date:        Tue Nov 03 21:29:32 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1778:2d9b15732841
+| |  user:        hecht
+| |  date:        Tue Nov 03 20:54:39 2009 +0100
+| |  summary:     passe to version 1.4.3 of tetgen.
+| |
+o |  changeset:   1777:d7ff001547be
+| |  user:        hecht
+| |  date:        Tue Oct 27 17:22:13 2009 +0100
+| |  summary:     add eigen value full
+| |
+o |  changeset:   1776:c8de02c7971f
+| |  user:        hecht
+| |  date:        Sun Oct 25 18:18:58 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1775:abb3258333e5
+| |  user:        hecht
+| |  date:        Sun Oct 25 18:03:03 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1774:ad90f689e762
+| |  user:        hecht
+| |  date:        Wed Oct 21 22:19:30 2009 +0200
+| |  summary:     update INNOVATION file
+| |
+o |  changeset:   1773:0fca1c94a0b5
+| |  user:        hecht
+| |  date:        Wed Oct 21 22:16:24 2009 +0200
+| |  summary:     passe to version 3.6
+| |
+o |  changeset:   1772:961bccd81738
+| |  user:        hecht
+| |  date:        Wed Oct 21 22:00:51 2009 +0200
+| |  summary:     coorect .cpp and simlify
+| |
+o |  changeset:   1771:1595300c7f81
+| |  user:        hecht
+| |  date:        Wed Oct 21 20:35:47 2009 +0200
+| |  summary:     New version of funcTemplate.cpp with  function with stack +  1 2 et 3 argument
+| |
+o |  changeset:   1770:12f4eb1a979a
+| |  user:        hecht
+| |  date:        Tue Oct 20 13:32:54 2009 +0200
+| |  summary:     add tools to read .pcm files for optic-flow computation
+| |
+o |  changeset:   1769:d449b7c05ec5
+| |  user:        hecht
+| |  date:        Mon Oct 19 22:46:57 2009 +0200
+| |  summary:     add tools to read pcm opticflow
+| |
+o |  changeset:   1768:41a11cfe6bd1
+| |  user:        hecht
+| |  date:        Thu Oct 15 23:23:01 2009 +0200
+| |  summary:     coorect assert error in gmres without preconditionner.
+| |
+o |  changeset:   1767:037d651d0a6b
+| |  user:        hecht
+| |  date:        Wed Oct 14 23:54:33 2009 +0200
+| |  summary:     You find a very hard bug to correct s ( a small miss tapping)
+| |
+o |  changeset:   1766:3e99aae2de38
+| |  user:        morice
+| |  date:        Wed Oct 14 15:25:40 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1765:5adb0c1b49f2
+| |  user:        morice
+| |  date:        Tue Oct 13 16:48:58 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1764:66936e3bfe84
+| |  user:        hecht
+| |  date:        Tue Oct 13 15:41:03 2009 +0200
+| |  summary:     correct a very old bug in bamg in case of mesh with internal
+| |
+o |  changeset:   1763:0d06bacf7d81
+| |  user:        morice
+| |  date:        Fri Oct 09 22:15:38 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1762:2a7535cf3b0c
+| |  user:        hecht
+| |  date:        Wed Oct 07 13:06:47 2009 +0200
+| |  summary:     correct print error
+| |
+o |  changeset:   1761:e90b49294374
+| |  user:        hecht
+| |  date:        Wed Oct 07 04:54:55 2009 +0200
+| |  summary:     add chech of size of fr-ortran integer, force fortran integer to by 4 bytes with  f2c
+| |
+o |  changeset:   1760:a1266eb439fe
+| |  user:        hecht
+| |  date:        Tue Oct 06 23:01:26 2009 +0200
+| |  summary:     correct  msitake in complex eigenvalue problem.
+| |
+o |  changeset:   1759:8af62e433f06
+| |  user:        hecht
+| |  date:        Mon Sep 28 22:53:48 2009 +0200
+| |  summary:     coorect install problem undex windows and Macos.
+| |
+o |  changeset:   1758:2d14d6567664
+| |  user:        hecht
+| |  date:        Mon Sep 28 21:24:24 2009 +0200
+| |  summary:     add __VC__ under windows (cygwin)
+| |
+o |  changeset:   1757:b34002c2d4ff
+| |  user:        hecht
+| |  date:        Mon Sep 28 18:43:06 2009 +0200
+| |  summary:     correct miss tapping in fflaunch++exe
+| |
+o |  changeset:   1756:4c4dc2c8f823
+| |  user:        hecht
+| |  date:        Mon Sep 28 18:02:18 2009 +0200
+| |  summary:     coorect miss take in launchff++.cpp filename
+| |
+o |  changeset:   1755:79cc99cce5ab
+| |  user:        hecht
+| |  date:        Mon Sep 28 18:01:21 2009 +0200
+| |  summary:     corect misstake in filename
+| |
+o |  changeset:   1754:ff040fb58b23
+| |  user:        morice
+| |  date:        Mon Sep 28 15:46:22 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1753:0b20838e0191
+| |  user:        hecht
+| |  date:        Thu Sep 24 16:51:20 2009 +0200
+| |  summary:     coorect d-Leman.edp      deep is under 0...   (before all tet a < 0)
+| |
+o |  changeset:   1752:f93cbf193dc5
+| |  user:        hecht
+| |  date:        Thu Sep 24 16:32:45 2009 +0200
+| |  summary:     coorect plot of 3d meshes
+| |
+o |  changeset:   1751:9b61149decbb
+| |  user:        hecht
+| |  date:        Thu Sep 24 14:38:15 2009 +0200
+| |  summary:     corect a stop test
+| |
+o |  changeset:   1750:18c376484a0b
+| |  user:        hecht
+| |  date:        Thu Sep 24 14:00:06 2009 +0200
+| |  summary:     correct big bug in case of 3D fepace with constante number of df / node.
+| |
+o |  changeset:   1749:13568ef94d25
+| |  user:        hecht
+| |  date:        Wed Sep 23 23:28:35 2009 +0200
+| |  summary:     continuning array of vect FE func 3d
+| |
+o |  changeset:   1748:9ca65f60265e
+| |  user:        hecht
+| |  date:        Wed Sep 23 21:53:47 2009 +0200
+| |  summary:     correct makefile build WHERE-LIB   -download
+| |
+o |  changeset:   1747:9ad5a70d9da5
+| |  user:        hecht
+| |  date:        Wed Sep 23 21:44:43 2009 +0200
+| |  summary:     add two examples
+| |
+o |  changeset:   1746:636e0dacf420
+| |  user:        hecht
+| |  date:        Wed Sep 23 21:28:34 2009 +0200
+| |  summary:     correct set array of vectorail finite element functions
+| |
+o |  changeset:   1745:fd499d9e6f28
+| |  user:        hecht
+| |  date:        Tue Sep 22 22:59:17 2009 +0200
+| |  summary:     rebuild makefile
+| |
+o |  changeset:   1744:c0f785566dae
+| |  user:        hecht
+| |  date:        Tue Sep 22 18:22:10 2009 +0200
+| |  summary:     add patch filexs
+| |
+o |  changeset:   1743:25480c53626d
+| |  user:        hecht
+| |  date:        Tue Sep 22 11:09:39 2009 +0200
+| |  summary:     corct make fo intall
+| |
+o |  changeset:   1742:5af770aaac29
+| |  user:        hecht
+| |  date:        Tue Sep 22 11:01:06 2009 +0200
+| |  summary:     correct makefile for metis
+| |
+o |  changeset:   1741:e06fc8bfa3e5
+| |  user:        hecht
+| |  date:        Tue Sep 22 10:54:59 2009 +0200
+| |  summary:     remove file from data base
+| |
+o |  changeset:   1740:4142e57dd0e6
+| |  user:        hecht
+| |  date:        Tue Sep 22 10:54:00 2009 +0200
+| |  summary:     coorect install makes
+| |
+o |  changeset:   1739:76b29386160e
+| |  user:        hecht
+| |  date:        Tue Sep 22 10:43:36 2009 +0200
+| |  summary:     continius ff-c++ auto
+| |
+o |  changeset:   1738:0695dbc17cb0
+| |  user:        hecht
+| |  date:        Tue Sep 22 10:25:01 2009 +0200
+| |  summary:     add missing file
+| |
+o |  changeset:   1737:a6f7a118aff7
+| |  user:        hecht
+| |  date:        Tue Sep 22 10:18:56 2009 +0200
+| |  summary:     rebuild makefiles
+| |
+o |  changeset:   1736:879121c3ec58
+| |  user:        hecht
+| |  date:        Tue Sep 22 10:18:19 2009 +0200
+| |  summary:     change ff-c++ off auto dep.  find
+| |
+o |  changeset:   1735:7a7c7c8057db
+| |  user:        hecht
+| |  date:        Mon Sep 21 22:44:01 2009 +0200
+| |  summary:     addfile for ff-pkg-download.in
+| |
+o |  changeset:   1734:15ae6f084ad1
+| |  user:        hecht
+| |  date:        Mon Sep 21 22:43:01 2009 +0200
+| |  summary:     change movemesh3d to movemesh3
+| |
+o |  changeset:   1733:5e49222d0c4d
+| |  user:        hecht
+| |  date:        Mon Sep 21 22:38:53 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1732:878dac9dd908
+| |  user:        morice
+| |  date:        Wed Sep 16 11:54:52 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1731:4f2fa344dc0b
+| |  user:        hecht
+| |  date:        Wed Sep 09 18:17:15 2009 +0200
+| |  summary:     add missing resize of sparse complex matrix
+| |
+o |  changeset:   1730:9d61b8cae5c5
+| |  user:        hecht
+| |  date:        Mon Sep 07 09:50:52 2009 +0200
+| |  summary:     add metis
+| |
+o |  changeset:   1729:90e9c94f2793
+| |  user:        morice
+| |  date:        Fri Sep 04 11:41:30 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1728:c5dbee61cf58
+| |  user:        morice
+| |  date:        Fri Sep 04 11:40:09 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1727:607657f6d2b8
+| |  user:        hecht
+| |  date:        Thu Sep 03 09:51:01 2009 +0200
+| |  summary:     add tools of automatics find libs and include
+| |
+o |  changeset:   1726:1ba4ebcbf0d5
+| |  user:        morice
+| |  date:        Thu Sep 03 08:26:47 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1725:3de000c981b5
+| |  user:        hecht
+| |  date:        Wed Sep 02 21:45:38 2009 +0200
+| |  summary:     add metis link
+| |
+o |  changeset:   1724:260e3f9628d2
+| |  user:        hecht
+| |  date:        Wed Sep 02 09:58:04 2009 +0200
+| |  summary:     add MPI_com in solver prameter
+| |
+o |  changeset:   1723:5399bf49daa4
+| |  user:        morice
+| |  date:        Tue Sep 01 12:41:02 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1722:a04f554f152e
+| |  user:        morice
+| |  date:        Tue Sep 01 12:30:05 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1721:3edc358fb626
+| |  user:        morice
+| |  date:        Tue Sep 01 10:28:55 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1720:f7df348e0c24
+| |  user:        hecht
+| |  date:        Mon Aug 31 10:59:34 2009 +0200
+| |  summary:     CORRECT IN CASE OF mpich
+| |
+o |  changeset:   1719:4a7c39d7edfb
+| |  user:        hecht
+| |  date:        Fri Aug 28 18:11:42 2009 +0200
+| |  summary:     add missing file to coorect trap tst on ubuntu
+| |
+o |  changeset:   1718:2d6aa202da95
+| |  user:        hecht
+| |  date:        Fri Aug 28 17:52:20 2009 +0200
+| |  summary:     coorect README
+| |
+o |  changeset:   1717:a9cc7f75566d
+| |  user:        hecht
+| |  date:        Fri Aug 28 17:27:12 2009 +0200
+| |  summary:     add file to remove trap in check of eigen exampel
+| |
+o |  changeset:   1716:b33bbe62d06f
+| |  user:        hecht
+| |  date:        Fri Aug 28 15:08:18 2009 +0200
+| |  summary:     coorect INNOVATION
+| |
+o |  changeset:   1715:780e891f2505
+| |  user:        hecht
+| |  date:        Thu Aug 27 22:00:32 2009 +0200
+| |  summary:     coorect mistake in parallelempi.cpp
+| |
+o |  changeset:   1714:ee657855b460
+| |  user:        hecht
+| |  date:        Thu Aug 27 21:55:33 2009 +0200
+| |  summary:     commit version 3.5  see innvovation for all change
+| |
+o |  changeset:   1713:d10318b35b4d
+| |  user:        hecht
+| |  date:        Thu Aug 27 16:03:16 2009 +0200
+| |  summary:     passe to versio 3.5  with a real mpi interface.
+| |
+o |  changeset:   1712:f2ac13edc9e2
+| |  user:        hecht
+| |  date:        Wed Aug 26 23:02:52 2009 +0200
+| |  summary:     do a not to bad  mpi version
+| |
+o |  changeset:   1711:9dcb3988b48a
+| |  user:        hecht
+| |  date:        Tue Aug 25 16:06:27 2009 +0200
+| |  summary:     add mpiBarrier + const of mpiGroup and mpiComm (boggus ???)
+| |
+o |  changeset:   1710:728541dd2b77
+| |  user:        hecht
+| |  date:        Tue Aug 25 10:06:23 2009 +0200
+| |  summary:     add   Scatter, Gather, etc in mpi
+| |
+o |  changeset:   1709:a15319a40921
+| |  user:        hecht
+| |  date:        Mon Aug 24 23:40:24 2009 +0200
+| |  summary:     correct mpi version see innovation for detail
+| |
+o |  changeset:   1708:3dc151cd6a93
+| |  user:        hecht
+| |  date:        Sat Aug 08 21:23:53 2009 +0200
+| |  summary:     bmo is boggus and correct mistapping in convect_dervieux
+| |
+o |  changeset:   1707:54225cd7c163
+| |  user:        hecht
+| |  date:        Sat Aug 08 21:12:14 2009 +0200
+| |  summary:     correct convect files
+| |
+o |  changeset:   1706:ea9ea9efff60
+| |  user:        hecht
+| |  date:        Sat Aug 08 20:57:06 2009 +0200
+| |  summary:     change a little, correct a stop test and do a fast version
+| |
+o |  changeset:   1705:5feb310149d3
+| |  user:        hecht
+| |  date:        Sat Aug 08 20:08:41 2009 +0200
+| |  summary:     change INNOVATION
+| |
+o |  changeset:   1704:8bdb3c81f330
+| |  user:        hecht
+| |  date:        Sat Aug 08 19:11:18 2009 +0200
+| |  summary:     build version 3.4-2
+| |
+o |  changeset:   1703:4b463c647ff0
+| |  user:        hecht
+| |  date:        Sat Aug 08 18:25:06 2009 +0200
+| |  summary:     do  new mesh inquire also in 3d
+| |
+o |  changeset:   1702:e91332ff3a6a
+| |  user:        hecht
+| |  date:        Sat Aug 08 10:53:20 2009 +0200
+| |  summary:     correct mesh.edp example for new mesh inquiring
+| |
+o |  changeset:   1701:eeab886b46aa
+| |  user:        hecht
+| |  date:        Fri Aug 07 22:40:17 2009 +0200
+| |  summary:     add tools to inquire boudnary directly in freefem++
+| |
+o |  changeset:   1700:24983130c3d7
+| |  user:        morice
+| |  date:        Sun Aug 02 14:50:37 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1699:2a03691fde42
+| |  user:        morice
+| |  date:        Thu Jul 30 12:55:18 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1698:77cc1c512479
+| |  user:        morice
+| |  date:        Thu Jul 30 07:42:48 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1697:6f77234eaec3
+| |  user:        morice
+| |  date:        Tue Jul 28 14:42:14 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1696:2682e3a39f4d
+| |  user:        morice
+| |  date:        Tue Jul 28 14:40:47 2009 +0200
+| |  summary:     :q
+| |
+o |  changeset:   1695:80772719f92e
+| |  user:        hecht
+| |  date:        Thu Jul 23 12:29:10 2009 +0200
+| |  summary:     add un first example ..
+| |
+o |  changeset:   1694:439fb84bb0eb
+| |  user:        hecht
+| |  date:        Thu Jul 23 12:17:04 2009 +0200
+| |  summary:     rewrite of mpi version ...
+| |
+o |  changeset:   1693:a7a22582cfb4
+| |  user:        hecht
+| |  date:        Wed Jul 22 22:41:32 2009 +0200
+| |  summary:     retore good version
+| |
+o |  changeset:   1692:b15405b6bd05
+| |  user:        hecht
+| |  date:        Wed Jul 22 11:30:29 2009 +0200
+| |  summary:     correct INNOTION
+| |
+o |  changeset:   1691:82f9057773f4
+| |  user:        hecht
+| |  date:        Wed Jul 22 11:28:16 2009 +0200
+| |  summary:     add plot of array of meshes and array of finite element function.
+| |
+o |  changeset:   1690:8acf1467c8c9
+| |  user:        hecht
+| |  date:        Mon Jul 20 22:30:52 2009 +0200
+| |  summary:     go to version 3.4-1
+| |
+o |  changeset:   1689:6fcd68db92d1
+| |  user:        hecht
+| |  date:        Mon Jul 20 18:23:45 2009 +0200
+| |  summary:     cosmetic in ffglut
+| |
+o |  changeset:   1688:d3b315513ffe
+| |  user:        hecht
+| |  date:        Mon Jul 20 18:12:06 2009 +0200
+| |  summary:     update ffglut
+| |
+o |  changeset:   1687:5505e8ebf028
+| |  user:        hecht
+| |  date:        Fri Jul 10 11:02:37 2009 +0200
+| |  summary:     correct load.link.in  or un test
+| |
+o |  changeset:   1686:ae67b591599d
+| |  user:        hecht
+| |  date:        Fri Jul 10 10:53:56 2009 +0200
+| |  summary:     coorect ff-c++ on win3é
+| |
+o |  changeset:   1685:f384c5351ff5
+| |  user:        hecht
+| |  date:        Fri Jul 10 10:19:05 2009 +0200
+| |  summary:     correct ff-c++ of windows case and cygwin
+| |
+o |  changeset:   1684:321b323db9a5
+| |  user:        hecht
+| |  date:        Fri Jul 10 09:36:21 2009 +0200
+| |  summary:     add BEM.epd and launchff.cpp ( a wrapper for windows)
+| |
+o |  changeset:   1683:d2dee6881044
+| |  user:        hecht
+| |  date:        Thu Jul 09 18:31:39 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1682:b4e586ac5a72
+| |  user:        hecht
+| |  date:        Thu Jul 09 17:50:43 2009 +0200
+| |  summary:     add -wait parameter for window launchff++  wrapper
+| |
+o |  changeset:   1681:38744c349358
+| |  user:        hecht
+| |  date:        Thu Jul 09 17:49:50 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1680:c75e3e2fa17e
+| |  user:        morice
+| |  date:        Wed Jul 08 17:58:43 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1679:807c14a16f98
+| |  user:        morice
+| |  date:        Wed Jul 08 17:22:08 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1678:05f5547c5d1d
+| |  user:        morice
+| |  date:        Wed Jul 08 16:55:41 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1677:1e5e278eedaa
+| |  user:        morice
+| |  date:        Wed Jul 08 14:36:26 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1676:8d2f6a01f018
+| |  user:        hecht
+| |  date:        Tue Jul 07 09:07:24 2009 +0200
+| |  summary:     correct mpi version
+| |
+o |  changeset:   1675:df7b6dab61b1
+| |  user:        hecht
+| |  date:        Mon Jul 06 16:33:34 2009 +0200
+| |  summary:     add mpi tools (in test) and correct buyild matrix interplation
+| |
+o |  changeset:   1674:63f2ef1d3223
+| |  user:        morice
+| |  date:        Thu Jul 02 18:11:49 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1673:d0503b06c6db
+| |  user:        hecht
+| |  date:        Tue Jun 30 21:06:38 2009 +0200
+| |  summary:     correct PlotStream io in case of array with check.
+| |
+o |  changeset:   1672:9a2c7fd9711d
+| |  user:        hecht
+| |  date:        Mon Jun 29 18:45:51 2009 +0200
+| |  summary:     change crimon-freefem++.zip in crimson-freefem++.zip
+| |
+o |  changeset:   1671:68133db4e985
+| |  user:        hecht
+| |  date:        Mon Jun 29 16:01:42 2009 +0200
+| |  summary:     p	ss to version 3.4
+| |
+o |  changeset:   1670:eda4376bbd73
+| |  user:        hecht
+| |  date:        Tue Jun 23 18:13:40 2009 +0200
+| |  summary:     change ffglut to bee more safe (version)
+| |
+o |  changeset:   1669:2c7d0aa50098
+| |  user:        hecht
+| |  date:        Thu Jun 18 09:45:06 2009 +0200
+| |  summary:     correct include  hpd -> idp
+| |
+o |  changeset:   1668:1e5e630dddd5
+| |  user:        hecht
+| |  date:        Tue Jun 16 14:42:59 2009 +0200
+| |  summary:     coorect bug on window
+| |
+o |  changeset:   1667:9a28c7cf6052
+| |  user:        morice
+| |  date:        Tue Jun 16 11:57:25 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1666:d17316a654b9
+| |  user:        hecht
+| |  date:        Tue Jun 16 11:08:06 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1665:e2de216ad22c
+| |  user:        hecht
+| |  date:        Tue Jun 16 11:07:49 2009 +0200
+| |  summary:     add examples++-3d/lac-leman-v4.msh  in the distrib
+| |
+o |  changeset:   1664:2e25f004c497
+| |  user:        hecht
+| |  date:        Tue Jun 16 10:36:46 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1663:c047ea6fb673
+| |  user:        hecht
+| |  date:        Tue Jun 16 10:30:42 2009 +0200
+| |  summary:     before the next version
+| |
+o |  changeset:   1662:2932f81e8687
+| |  user:        hecht
+| |  date:        Tue Jun 16 10:25:33 2009 +0200
+| |  summary:     coorect idp  file  in mortar exemple
+| |
+o |  changeset:   1661:822b5c8b04a1
+| |  user:        hecht
+| |  date:        Mon Jun 15 22:36:55 2009 +0200
+| |  summary:     correct bug in makefile
+| |
+o |  changeset:   1660:51a37d2faf4a
+| |  user:        morice
+| |  date:        Mon Jun 15 18:16:49 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1659:bcb8a1242d1b
+| |  user:        hecht
+| |  date:        Fri Jun 12 23:09:42 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1658:83e491da131a
+| |  user:        hecht
+| |  date:        Mon Jun 08 13:42:52 2009 +0200
+| |  summary:     do small correct  in  2 member:
+| |
+o |  changeset:   1657:2caaa85b26e3
+| |  user:        morice
+| |  date:        Mon Jun 08 12:48:34 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1656:19a76fdcdba5
+| |  user:        morice
+| |  date:        Mon Jun 08 12:45:41 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1655:9805b179ac69
+| |  user:        morice
+| |  date:        Mon Jun 08 12:35:10 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1654:b33eb490c839
+| |  user:        morice
+| |  date:        Mon Jun 08 12:03:12 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1653:45466a37654f
+| |  user:        hecht
+| |  date:        Mon Jun 08 11:16:23 2009 +0200
+| |  summary:     add Egde03d and RT03d finite element , correct mistake in
+| |
+o |  changeset:   1652:a3e88f63360c
+| |  user:        morice
+| |  date:        Fri Jun 05 14:27:05 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1651:e0a2e8d5cfd2
+| |  user:        hecht
+| |  date:        Thu Jun 04 12:56:41 2009 +0200
+| |  summary:     to avec good makefiel
+| |
+o |  changeset:   1650:7c00e01ad51b
+| |  user:        hecht
+| |  date:        Thu Jun 04 09:58:56 2009 +0200
+| |  summary:     correct Dxwriter tools
+| |
+o |  changeset:   1649:0ad3748de454
+| |  user:        hecht
+| |  date:        Thu Jun 04 09:37:14 2009 +0200
+| |  summary:     add file
+| |
+o |  changeset:   1648:a1494782af5b
+| |  user:        hecht
+| |  date:        Thu Jun 04 08:35:49 2009 +0200
+| |  summary:     add RT0 in 3D .  5 first test)
+| |
+o |  changeset:   1647:88a17753d10d
+| |  user:        hecht
+| |  date:        Wed Jun 03 23:23:51 2009 +0200
+| |  summary:     try to  put RT03d>  => correct lot of bug in the finite element (vectoriql)
+| |
+o |  changeset:   1646:229d1df51b18
+| |  user:        atenekeng
+| |  date:        Tue Jun 02 23:40:49 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1645:442c0aac83f2
+| |  user:        atenekeng
+| |  date:        Tue Jun 02 23:33:38 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1644:b6bbb2eb44d0
+| |  user:        atenekeng
+| |  date:        Tue Jun 02 23:27:30 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1643:0831c6a1027f
+| |  user:        atenekeng
+| |  date:        Tue Jun 02 23:22:36 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1642:a459d624d2f7
+| |  user:        atenekeng
+| |  date:        Tue Jun 02 23:12:44 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1641:fc0bd0023280
+| |  user:        hecht
+| |  date:        Tue Jun 02 15:40:01 2009 +0200
+| |  summary:     begin of RT0 in 3D.
+| |
+o |  changeset:   1640:00f642dd30c1
+| |  user:        hecht
+| |  date:        Mon Jun 01 18:29:48 2009 +0200
+| |  summary:     add tool to build surfqce mesh.
+| |
+o |  changeset:   1639:43b260ee40b7
+| |  user:        hecht
+| |  date:        Mon Jun 01 18:28:16 2009 +0200
+| |  summary:     V 3.3-1 1 juin 2009
+| |
+o |  changeset:   1638:dbd423d4d000
+| |  user:        hecht
+| |  date:        Fri May 29 13:35:03 2009 +0200
+| |  summary:     reove unused files
+| |
+o |  changeset:   1637:f7079ea8eb23
+| |  user:        hecht
+| |  date:        Fri May 29 13:32:54 2009 +0200
+| |  summary:     add change solver problem on return arry and meshes in function.
+| |
+o |  changeset:   1636:9d7dbf3295c1
+| |  user:        hecht
+| |  date:        Thu May 28 18:33:25 2009 +0200
+| |  summary:     begin of clean real array in function.
+| |
+o |  changeset:   1635:cf621a076ad3
+| |  user:        hecht
+| |  date:        Wed May 27 13:56:54 2009 +0200
+| |  summary:     correct convect 3d..
+| |
+o |  changeset:   1634:a56bc9158f09
+| |  user:        hecht
+| |  date:        Tue May 26 18:05:27 2009 +0200
+| |  summary:     correct -o in find
+| |
+o |  changeset:   1633:81f69e584dfb
+| |  user:        hecht
+| |  date:        Tue May 26 15:52:04 2009 +0200
+| |  summary:     correct msh3.hpp and SuperLU.cpp mesh3 volume is 0 some time
+| |
+o |  changeset:   1632:3c7db6033cce
+| |  user:        hecht
+| |  date:        Tue May 26 15:17:40 2009 +0200
+| |  summary:     add 3d mas lump quadrature furmula (qfV1, qfV2,qfV5 qfV1lump)
+| |
+o |  changeset:   1631:7e03dc459f0e
+| |  user:        hecht
+| |  date:        Mon May 25 11:42:53 2009 +0200
+| |  summary:     version 3.3
+| |
+o |  changeset:   1630:ae1868421420
+| |  user:        atenekeng
+| |  date:        Mon May 18 02:44:56 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1629:69b580f397be
+| |  user:        hecht
+| |  date:        Sun May 17 21:02:40 2009 +0200
+| |  summary:     add -fPIC flags on 64 achitecture
+| |
+o |  changeset:   1628:8ddd25c5ca25
+| |  user:        hecht
+| |  date:        Fri May 15 21:02:32 2009 +0200
+| |  summary:     add 3d eigen value tools
+| |
+o |  changeset:   1627:022e89f77648
+| |  user:        hecht
+| |  date:        Wed May 13 16:11:46 2009 +0200
+| |  summary:     correct   configure.ac and makefile on window for  lapack lib  in
+| |
+o |  changeset:   1626:a97da324c99e
+| |  user:        hecht
+| |  date:        Wed May 13 13:20:28 2009 +0200
+| |  summary:     put coorect for new sparse matrix intercale
+| |
+o |  changeset:   1625:c6cb0b28b7bb
+| |  user:        hecht
+| |  date:        Wed May 13 13:19:09 2009 +0200
+| |  summary:     remove to change in SuperLU.cpp
+| |
+o |  changeset:   1624:0c1099452f82
+| |  user:        hecht
+| |  date:        Wed May 13 13:10:20 2009 +0200
+| |  summary:     put correct
+| |
+o |  changeset:   1623:70718c5b4084
+| |  user:        hecht
+| |  date:        Wed May 13 10:25:44 2009 +0200
+| |  summary:     add oone output
+| |
+o |  changeset:   1622:eb450d4e51f3
+| |  user:        hecht
+| |  date:        Wed May 13 09:46:23 2009 +0200
+| |  summary:     correct the doc (in progress) , coorect the size of text in postscrip driver.
+| |
+o |  changeset:   1621:8d5c2e7a6033
+| |  user:        hecht
+| |  date:        Wed May 13 09:12:05 2009 +0200
+| |  summary:     add fig in doc.
+| |
+o |  changeset:   1620:8f797289de2b
+| |  user:        hecht
+| |  date:        Mon May 11 09:05:58 2009 +0200
+| |  summary:     add   pgm   figure exemple file
+| |
+o |  changeset:   1619:18f8c66246c7
+| |  user:        hecht
+| |  date:        Mon May 11 09:05:29 2009 +0200
+| |  summary:     add tool to read ppm and pgm  image file see  ppm2rnm.edp example
+| |
+o |  changeset:   1618:08c9e444113a
+| |  user:        hecht
+| |  date:        Mon May 11 09:03:08 2009 +0200
+| |  summary:     add  tool to set array like in matlab and scilab
+| |
+o |  changeset:   1617:9a32089d27c6
+| |  user:        hecht
+| |  date:        Thu Apr 30 10:07:55 2009 +0200
+| |  summary:     comment change in dump in RNM.hpp
+| |
+o |  changeset:   1616:af2b47c9eec9
+| |  user:        hecht
+| |  date:        Thu Apr 30 09:52:57 2009 +0200
+| |  summary:     add sort of array and in parallel int array
+| |
+o |  changeset:   1615:d9457f8f8a82
+| |  user:        morice
+| |  date:        Wed Apr 29 18:40:30 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1614:d93e87702112
+| |  user:        morice
+| |  date:        Wed Apr 29 18:37:15 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1613:58344eff0231
+| |  user:        hecht
+| |  date:        Wed Apr 29 09:12:46 2009 +0200
+| |  summary:     add missing file to inv full matrix.
+| |
+o |  changeset:   1612:492aae1c8104
+| |  user:        hecht
+| |  date:        Mon Apr 27 23:30:00 2009 +0200
+| |  summary:     add missing delete
+| |
+o |  changeset:   1611:22b1da7215e8
+| |  user:        hecht
+| |  date:        Mon Apr 27 23:05:26 2009 +0200
+| |  summary:     update iNNOVATIO
+| |
+o |  changeset:   1610:a0cba860253b
+| |  user:        hecht
+| |  date:        Mon Apr 27 23:02:34 2009 +0200
+| |  summary:     update innovation
+| |
+o |  changeset:   1609:4d114f69dcc6
+| |  user:        hecht
+| |  date:        Mon Apr 27 21:56:45 2009 +0200
+| |  summary:     add missing files
+| |
+o |  changeset:   1608:65650e9ec1b0
+| |  user:        hecht
+| |  date:        Mon Apr 27 21:55:44 2009 +0200
+| |  summary:     correct example
+| |
+o |  changeset:   1607:88667b360b31
+| |  user:        hecht
+| |  date:        Mon Apr 27 21:24:59 2009 +0200
+| |  summary:     add perodic FESpace in 3d
+| |
+o |  changeset:   1606:3ef7b85f0698
+| |  user:        morice
+| |  date:        Wed Apr 22 18:06:47 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1605:ee777f6df0eb
+| |  user:        morice
+| |  date:        Wed Apr 22 17:51:29 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1604:2bd5f0930f42
+| |  user:        morice
+| |  date:        Wed Apr 22 11:12:30 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1603:edf35a172e75
+| |  user:        morice
+| |  date:        Tue Apr 21 16:16:10 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1602:95da9106cc83
+| |  user:        morice
+| |  date:        Tue Apr 21 15:33:13 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1601:998fb4969917
+| |  user:        morice
+| |  date:        Tue Apr 21 15:29:16 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1600:87657798c2cb
+| |  user:        morice
+| |  date:        Tue Apr 21 15:09:00 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1599:44156c3a14df
+| |  user:        morice
+| |  date:        Tue Apr 21 13:51:17 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1598:8e33508e3599
+| |  user:        morice
+| |  date:        Tue Apr 21 13:41:11 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1597:664a71a6bf78
+| |  user:        morice
+| |  date:        Mon Apr 20 14:07:04 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1596:b875c74a428e
+| |  user:        morice
+| |  date:        Mon Apr 20 13:17:47 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1595:04341a068ff7
+| |  user:        morice
+| |  date:        Mon Apr 20 13:15:51 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1594:d57fa2584133
+| |  user:        morice
+| |  date:        Mon Apr 20 13:13:39 2009 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1593:1bfe35d03d32
+| |  user:        hecht
+| |  date:        Fri Apr 17 09:29:40 2009 +0200
+| |  summary:     to be sur
+| |
+o |  changeset:   1592:10c357445573
+| |  user:        hecht
+| |  date:        Fri Apr 17 00:50:42 2009 +0200
+| |  summary:     add dump
+| |
+o |  changeset:   1591:915380e22bf9
+| |  user:        hecht
+| |  date:        Fri Apr 17 00:30:10 2009 +0200
+| |  summary:     gros modif dans la gestion des parameters pour le
+| |
+o |  changeset:   1590:465673ac5e9d
+| |  user:        hecht
+| |  date:        Wed Apr 15 19:17:15 2009 +0200
+| |  summary:     correct search of lapack lib
+| |
+o |  changeset:   1589:9e4275fb2706
+| |  user:        hecht
+| |  date:        Wed Apr 15 18:43:46 2009 +0200
+| |  summary:     correct complie of lapack lib  with arpack (buildin in macos)
+| |
+o |  changeset:   1588:f2650d954b5e
+| |  user:        hecht
+| |  date:        Wed Apr 15 18:21:38 2009 +0200
+| |  summary:     do autoreconf
+| |
+o |  changeset:   1587:9ee6ee15818c
+| |  user:        hecht
+| |  date:        Wed Apr 15 18:18:22 2009 +0200
+| |  summary:     coorect --enable-m64   flags compile
+| |
+o |  changeset:   1586:9c12b436f339
+| |  user:        hecht
+| |  date:        Wed Apr 15 18:12:04 2009 +0200
+| |  summary:     correct Makefile-MacOs
+| |
+o |  changeset:   1585:df486d895352
+| |  user:        hecht
+| |  date:        Wed Apr 15 11:15:40 2009 +0200
+| |  summary:     passe to version 3.2
+| |
+o |  changeset:   1584:d0e8b898a63e
+| |  user:        hecht
+| |  date:        Wed Apr 15 11:11:58 2009 +0200
+| |  summary:     do change for 64 bits on macos.
+| |
+o |  changeset:   1583:b43d23573147
+| |  user:        hecht
+| |  date:        Tue Mar 31 13:38:09 2009 +0200
+| |  summary:     add P1b3d
+| |
+o |  changeset:   1582:79f9321ebe42
+| |  user:        morice
+| |  date:        Fri Mar 20 12:18:43 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1581:89bbe7fed648
+| |  user:        morice
+| |  date:        Fri Mar 20 11:25:41 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1580:03b88bc9b368
+| |  user:        morice
+| |  date:        Tue Mar 17 11:16:44 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1579:5b219bb5581f
+| |  user:        morice
+| |  date:        Mon Mar 16 18:16:41 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1578:3bd564aa3f9f
+| |  user:        hecht
+| |  date:        Sat Mar 14 17:27:32 2009 +0100
+| |  summary:     version 3.1-0
+| |
+o |  changeset:   1577:76c7acba2b50
+| |  user:        hecht
+| |  date:        Sat Mar 14 17:12:15 2009 +0100
+| |  summary:     coorect load.link.in  for f77 compile.
+| |
+o |  changeset:   1576:d1c3f8fd5e7a
+| |  user:        morice
+| |  date:        Thu Mar 12 14:32:53 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1575:8b3b4532b68d
+| |  user:        morice
+| |  date:        Thu Mar 12 13:43:36 2009 +0100
+| |  summary:     bug trouver dans Find:
+| |
+o |  changeset:   1574:142b82fe9837
+| |  user:        morice
+| |  date:        Thu Mar 12 13:39:12 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1573:68e386efcdfa
+| |  user:        hecht
+| |  date:        Mon Mar 09 15:00:18 2009 +0100
+| |  summary:     version 3.1  fist step
+| |
+o |  changeset:   1572:41dfdbb8dfa0
+| |  user:        hecht
+| |  date:        Thu Mar 05 11:17:23 2009 +0100
+| |  summary:     correct INNOVATION and remove print
+| |
+o |  changeset:   1571:5e26bd093206
+| |  user:        hecht
+| |  date:        Wed Mar 04 11:45:32 2009 +0100
+| |  summary:     correct int2d in 3d.  (error on    transformation   face  to Tet)
+| |
+o |  changeset:   1570:ae36727a4ce3
+| |  user:        hecht
+| |  date:        Mon Mar 02 14:52:15 2009 +0100
+| |  summary:     make version 3.0-6
+| |
+o |  changeset:   1569:758a2e0f2057
+| |  user:        hecht
+| |  date:        Thu Feb 12 16:19:41 2009 +0100
+| |  summary:     correct bmo and extra dump
+| |
+o |  changeset:   1568:13d77a1f83c3
+| |  user:        hecht
+| |  date:        Thu Feb 12 09:04:47 2009 +0100
+| |  summary:     version 3.0-6
+| |
+o |  changeset:   1567:3537e6e5bd56
+| |  user:        hecht
+| |  date:        Thu Feb 12 08:47:20 2009 +0100
+| |  summary:     add required edges in adaptmesh tools.
+| |
+o |  changeset:   1566:0a7a4da722d6
+| |  user:        hecht
+| |  date:        Wed Feb 11 16:12:09 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1565:06a842864cd3
+| |  user:        hecht
+| |  date:        Wed Feb 11 16:11:22 2009 +0100
+| |  summary:     add code for lock boundary mesh in adapt process.  for JYU ...
+| |
+o |  changeset:   1564:ef831f851c3e
+| |  user:        hecht
+| |  date:        Wed Feb 11 13:36:20 2009 +0100
+| |  summary:     add option -nowait for windows.
+| |
+o |  changeset:   1563:8e8c47f158db
+| |  user:        hecht
+| |  date:        Mon Feb 09 09:41:57 2009 +0100
+| |  summary:     add 3d color ....
+| |
+o |  changeset:   1562:9ef4b48c94e5
+| |  user:        hecht
+| |  date:        Fri Feb 06 11:15:24 2009 +0100
+| |  summary:     correct missing tapping
+| |
+o |  changeset:   1561:b1047bd598d2
+| |  user:        hecht
+| |  date:        Fri Feb 06 10:50:16 2009 +0100
+| |  summary:     add a first plot of 3d data witj plot tools.
+| |
+o |  changeset:   1560:ff43f245e2f3
+| |  user:        hecht
+| |  date:        Thu Feb 05 16:29:09 2009 +0100
+| |  summary:     add new file for tet siplit.
+| |
+o |  changeset:   1559:1498e333f6d9
+| |  user:        morice
+| |  date:        Tue Feb 03 17:45:55 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1558:b70b991cd78c
+| |  user:        morice
+| |  date:        Tue Feb 03 15:09:59 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1557:b6672aa52178
+| |  user:        morice
+| |  date:        Tue Feb 03 15:03:02 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1556:e3dd766cd68b
+| |  user:        hecht
+| |  date:        Tue Jan 27 16:11:43 2009 +0100
+| |  summary:     remove last change (bogus)
+| |
+o |  changeset:   1555:4c5377a65671
+| |  user:        hecht
+| |  date:        Tue Jan 27 16:09:04 2009 +0100
+| |  summary:     correct dy(uh) when uh is P13d. (always 0)
+| |
+o |  changeset:   1554:ca9caabbe3bc
+| |  user:        morice
+| |  date:        Fri Jan 23 16:14:30 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1553:018249cdee99
+| |  user:        morice
+| |  date:        Fri Jan 23 16:13:24 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1552:3db53e497a18
+| |  user:        hecht
+| |  date:        Wed Jan 21 11:04:10 2009 +0100
+| |  summary:     correct bin-win32 install exe
+| |
+o |  changeset:   1551:7a0f31302d16
+| |  user:        hecht
+| |  date:        Wed Jan 21 10:56:45 2009 +0100
+| |  summary:     correct install bin-win32
+| |
+o |  changeset:   1550:91eefe9e3612
+| |  user:        hecht
+| |  date:        Wed Jan 21 10:13:06 2009 +0100
+| |  summary:     remove crazy file
+| |
+o |  changeset:   1549:b6835240f938
+| |  user:        hecht
+| |  date:        Tue Jan 20 20:56:59 2009 +0100
+| |  summary:     correct the install on under  windows / cygwin
+| |
+o |  changeset:   1548:ae5d95f70891
+| |  user:        hecht
+| |  date:        Sun Jan 18 19:25:03 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1547:c5083029fcff
+| |  user:        hecht
+| |  date:        Sun Jan 18 17:21:33 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1546:9dc587c45dff
+| |  user:        hecht
+| |  date:        Fri Jan 16 23:02:59 2009 +0100
+| |  summary:     correct ffglut.cpp
+| |
+o |  changeset:   1545:a0e928ee7675
+| |  user:        morice
+| |  date:        Fri Jan 16 11:38:05 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1544:2ccf8785babb
+| |  user:        morice
+| |  date:        Fri Jan 16 10:54:55 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1543:6d0a2e03c885
+| |  user:        morice
+| |  date:        Fri Jan 16 10:53:39 2009 +0100
+| |  summary:     ajout de savesurfacemesh
+| |
+o |  changeset:   1542:dfed132f264e
+| |  user:        hecht
+| |  date:        Thu Jan 15 12:45:37 2009 +0100
+| |  summary:     pass to version 3.0-5, correct array of 3d finite element function
+| |
+o |  changeset:   1541:bb42989cee29
+| |  user:        hecht
+| |  date:        Mon Jan 12 00:12:58 2009 +0100
+| |  summary:     add dx  witer and test salalo80 at gmail.com
+| |
+o |  changeset:   1540:350a96823dc1
+| |  user:        hecht
+| |  date:        Sat Jan 10 22:26:33 2009 +0100
+| |  summary:     pass to version 3.0-5
+| |
+o |  changeset:   1539:0bac5193dd77
+| |  user:        morice
+| |  date:        Thu Jan 08 10:41:21 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1538:bb5d8553df2c
+| |  user:        hecht
+| |  date:        Wed Jan 07 17:21:59 2009 +0100
+| |  summary:     add new comment file
+| |
+o |  changeset:   1537:e6bc0b8eb690
+| |  user:        morice
+| |  date:        Wed Jan 07 12:00:25 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1536:bbe299dedeb9
+| |  user:        hecht
+| |  date:        Wed Jan 07 09:55:41 2009 +0100
+| |  summary:     correct window message in ffglut
+| |
+o |  changeset:   1535:df5a030a7a05
+| |  user:        hecht
+| |  date:        Wed Jan 07 08:48:03 2009 +0100
+| |  summary:     correct 3d view setting
+| |
+o |  changeset:   1534:172df02611b6
+| |  user:        hecht
+| |  date:        Tue Jan 06 23:22:29 2009 +0100
+| |  summary:     coorect Pvue3
+| |
+o |  changeset:   1533:76f34874cc73
+| |  user:        hecht
+| |  date:        Tue Jan 06 23:15:13 2009 +0100
+| |  summary:     add 3d plot
+| |
+o |  changeset:   1532:0f8e1829074d
+| |  user:        hecht
+| |  date:        Tue Jan 06 20:30:40 2009 +0100
+| |  summary:     correct
+| |
+o |  changeset:   1531:5f9834701ea2
+| |  user:        morice
+| |  date:        Tue Jan 06 14:14:35 2009 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1530:2a6f1aec0d48
+| |  user:        hecht
+| |  date:        Mon Jan 05 18:20:15 2009 +0100
+| |  summary:     correct download/tetgen/Makefile more portable
+| |
+o |  changeset:   1529:52ee5604e8c2
+| |  user:        hecht
+| |  date:        Mon Jan 05 13:26:47 2009 +0100
+| |  summary:     correct int2d in 3d, makefiles fo tetgen and pb with $(DESTDIR)
+| |
+o |  changeset:   1528:7356da4183b8
+| |  user:        hecht
+| |  date:        Mon Jan 05 11:26:43 2009 +0100
+| |  summary:     add test
+| |
+o |  changeset:   1527:2251f3d08b88
+| |  user:        hecht
+| |  date:        Mon Jan 05 11:25:30 2009 +0100
+| |  summary:     correct in2d in 3d  (missing factor 0.5)
+| |
+o |  changeset:   1526:2d4a22506f73
+| |  user:        hecht
+| |  date:        Mon Dec 29 17:34:56 2008 +0100
+| |  summary:     coorect the seach of the include dir
+| |
+o |  changeset:   1525:c67a5f5b9730
+| |  user:        hecht
+| |  date:        Mon Dec 29 17:18:03 2008 +0100
+| |  summary:     remove the clean routine variable after return, to much trouble.
+| |
+o |  changeset:   1524:a52a4003e09e
+| |  user:        hecht
+| |  date:        Sat Dec 27 18:27:41 2008 +0100
+| |  summary:     coorect Laplace3d.edp plot with medit
+| |
+o |  changeset:   1523:f0769f2c0b6a
+| |  user:        hecht
+| |  date:        Sat Dec 27 18:27:18 2008 +0100
+| |  summary:     correct medit.cpp
+| |
+o |  changeset:   1522:5b65b33be28d
+| |  user:        hecht
+| |  date:        Sat Dec 27 17:19:34 2008 +0100
+| |  summary:     update INNOVATION
+| |
+o |  changeset:   1521:0863f21fe19f
+| |  user:        hecht
+| |  date:        Sat Dec 27 17:15:45 2008 +0100
+| |  summary:     do pretty print correction
+| |
+o |  changeset:   1520:9730a238b680
+| |  user:        hecht
+| |  date:        Sat Dec 27 16:48:58 2008 +0100
+| |  summary:     coorect old bug when return of arry
+| |
+o |  changeset:   1519:35ab771c1a8b
+| |  user:        hecht
+| |  date:        Fri Dec 26 22:50:23 2008 +0100
+| |  summary:     correct makefile for dist install (change install-sh script)
+| |
+o |  changeset:   1518:ec10c2fe4fe9
+| |  user:        hecht
+| |  date:        Fri Dec 26 20:31:46 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1517:6896f3fcf127
+| |  user:        hecht
+| |  date:        Fri Dec 26 17:38:24 2008 +0100
+| |  summary:     correct serialeze mesh in 64 mode
+| |
+o |  changeset:   1516:7d5c2a818d42
+| |  user:        hecht
+| |  date:        Fri Dec 26 17:32:10 2008 +0100
+| |  summary:     correct serial in 64 bits mode
+| |
+o |  changeset:   1515:5d564e4fe7c2
+| |  user:        hecht
+| |  date:        Fri Dec 26 17:23:18 2008 +0100
+| |  summary:     try to correct
+| |
+o |  changeset:   1514:2d379f3e299d
+| |  user:        hecht
+| |  date:        Fri Dec 26 17:07:27 2008 +0100
+| |  summary:     correct write string
+| |
+o |  changeset:   1513:ae9e13d7244a
+| |  user:        hecht
+| |  date:        Fri Dec 26 17:06:12 2008 +0100
+| |  summary:     correct write / read string
+| |
+o |  changeset:   1512:86738eb65d94
+| |  user:        hecht
+| |  date:        Fri Dec 26 16:51:33 2008 +0100
+| |  summary:     correct Serialize Mesh  chang long in long long
+| |
+o |  changeset:   1511:09a0e9e181ef
+| |  user:        hecht
+| |  date:        Fri Dec 26 16:23:31 2008 +0100
+| |  summary:     correct build of ff-c++ in src/bin-win32/Makefile.am
+| |
+o |  changeset:   1510:736a461db53e
+| |  user:        hecht
+| |  date:        Fri Dec 26 16:06:40 2008 +0100
+| |  summary:     now load.lik is bliud from Makefile and load.link.in
+| |
+o |  changeset:   1509:28dbac93aec5
+| |  user:        hecht
+| |  date:        Fri Dec 26 16:01:48 2008 +0100
+| |  summary:     correct graphics of curve
+| |
+o |  changeset:   1508:cb901fc6fca0
+| |  user:        hecht
+| |  date:        Thu Dec 18 10:01:05 2008 +0100
+| |  summary:     correct Makefile and graphoc stuff
+| |
+o |  changeset:   1507:0407685463a7
+| |  user:        hecht
+| |  date:        Wed Dec 17 23:52:44 2008 +0100
+| |  summary:     correct ffglut for zooming y -> y-height ????
+| |
+o |  changeset:   1506:503c8ccb098a
+| |  user:        hecht
+| |  date:        Tue Dec 16 23:04:47 2008 +0100
+| |  summary:     coorect makefile for install
+| |
+o |  changeset:   1505:10afda2c8acd
+| |  user:        hecht
+| |  date:        Tue Dec 16 20:26:47 2008 +0100
+| |  summary:     add UMPAck solver
+| |
+o |  changeset:   1504:20c5e5ffc8c4
+| |  user:        hecht
+| |  date:        Tue Dec 16 20:24:46 2008 +0100
+| |  summary:     change the umpack matrice solver
+| |
+o |  changeset:   1503:26bc830cccc5
+| |  user:        hecht
+| |  date:        Tue Dec 16 17:48:59 2008 +0100
+| |  summary:     correct makefiles
+| |
+o |  changeset:   1502:9a693aa2371a
+| |  user:        morice
+| |  date:        Tue Dec 16 12:07:56 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1501:93ed40d6a6e6
+| |  user:        hecht
+| |  date:        Fri Dec 12 15:30:04 2008 +0100
+| |  summary:     change ../statu.... in.statu (for install on macos)
+| |
+o |  changeset:   1500:aca91a335b08
+| |  user:        hecht
+| |  date:        Fri Dec 12 15:18:03 2008 +0100
+| |  summary:     correct configure?ac of ubutu build package
+| |
+o |  changeset:   1499:27e5aef742b2
+| |  user:        hecht
+| |  date:        Fri Dec 12 15:16:22 2008 +0100
+| |  summary:     correct missunderstanding of usage of strchr ( return 0  if the search fail).
+| |
+o |  changeset:   1498:7299590b0a3c
+| |  user:        hecht
+| |  date:        Fri Dec 12 13:42:50 2008 +0100
+| |  summary:     correct the arpach driver , (pas mal.. FH)
+| |
+o |  changeset:   1497:84171470d151
+| |  user:        hecht
+| |  date:        Fri Dec 12 00:30:14 2008 +0100
+| |  summary:     add the mode in eignevalue like in arpack
+| |
+o |  changeset:   1496:7d7daf75c3ac
+| |  user:        hecht
+| |  date:        Wed Dec 10 10:31:24 2008 +0100
+| |  summary:     last chnage before version  3.0-2
+| |
+o |  changeset:   1495:fe9d0abe1c54
+| |  user:        hecht
+| |  date:        Wed Dec 10 10:21:01 2008 +0100
+| |  summary:     coorect for win32
+| |
+o |  changeset:   1494:4d73b3a20b0c
+| |  user:        hecht
+| |  date:        Wed Dec 10 09:47:46 2008 +0100
+| |  summary:     correct conflict with basename (-> baseName)
+| |
+o |  changeset:   1493:0f58bb952ae8
+| |  user:        hecht
+| |  date:        Wed Dec 10 08:45:20 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1492:ca8c350f70e4
+| |  user:        hecht
+| |  date:        Wed Dec 10 08:37:56 2008 +0100
+| |  summary:     add ff++.hpp include file to simplify life.
+| |
+o |  changeset:   1491:5101e82dafe6
+| |  user:        hecht
+| |  date:        Wed Dec 10 00:22:58 2008 +0100
+| |  summary:     correct miss * in pointer
+| |
+o |  changeset:   1490:a673c97e0d53
+| |  user:        hecht
+| |  date:        Tue Dec 09 23:56:09 2008 +0100
+| |  summary:     coorect stuff for loadpath on macos.
+| |
+o |  changeset:   1489:8ec039547530
+| |  user:        hecht
+| |  date:        Tue Dec 09 18:09:20 2008 +0100
+| |  summary:     coorect install on macos
+| |
+o |  changeset:   1488:a7374bf14c69
+| |  user:        hecht
+| |  date:        Tue Dec 09 17:03:50 2008 +0100
+| |  summary:     change == in = miss tapping
+| |
+o |  changeset:   1487:e45dff48bbd8
+| |  user:        hecht
+| |  date:        Tue Dec 09 16:59:37 2008 +0100
+| |  summary:     coorect include dir for install
+| |
+o |  changeset:   1486:3402eeb91b14
+| |  user:        hecht
+| |  date:        Tue Dec 09 16:43:38 2008 +0100
+| |  summary:     stablization of install process
+| |
+o |  changeset:   1485:357c63d481f1
+| |  user:        hecht
+| |  date:        Tue Dec 09 16:24:58 2008 +0100
+| |  summary:     correct on windows to build file in local dir
+| |
+o |  changeset:   1484:1d6688c93330
+| |  user:        morice
+| |  date:        Tue Dec 09 16:06:48 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1483:beb24a04490c
+| |  user:        hecht
+| |  date:        Tue Dec 09 15:05:48 2008 +0100
+| |  summary:     next
+| |
+o |  changeset:   1482:77eb855e58a3
+| |  user:        hecht
+| |  date:        Tue Dec 09 15:03:46 2008 +0100
+| |  summary:     correct binary read on stdin with medit.
+| |
+o |  changeset:   1481:d7db611022fb
+| |  user:        hecht
+| |  date:        Mon Dec 08 22:55:47 2008 +0100
+| |  summary:     coorect makefile remove dependance with ff-c++
+| |
+o |  changeset:   1480:be591602d2fe
+| |  user:        hecht
+| |  date:        Mon Dec 08 22:17:14 2008 +0100
+| |  summary:     corect pb when plot of const function
+| |
+o |  changeset:   1479:51ae281c82c2
+| |  user:        hecht
+| |  date:        Mon Dec 08 22:02:19 2008 +0100
+| |  summary:     corret freefem++ args -fglut trap du to mistake in getprog-unix.hpp
+| |
+o |  changeset:   1478:5adb19ceadd5
+| |  user:        hecht
+| |  date:        Mon Dec 08 16:23:50 2008 +0100
+| |  summary:     correct install dir of freefem++ include, load file.
+| |
+o |  changeset:   1477:7cc876365ccc
+| |  user:        hecht
+| |  date:        Sun Dec 07 23:54:44 2008 +0100
+| |  summary:     pass tversion 3.0-2
+| |
+o |  changeset:   1476:8f0c0241434e
+| |  user:        hecht
+| |  date:        Sun Dec 07 23:52:08 2008 +0100
+| |  summary:     coorect win32 end of prog add a wiat et save the logs
+| |
+o |  changeset:   1475:deeabce583a3
+| |  user:        hecht
+| |  date:        Sun Dec 07 23:04:26 2008 +0100
+| |  summary:     cooret of save window console???
+| |
+o |  changeset:   1474:7a964fb9cc9f
+| |  user:        hecht
+| |  date:        Sun Dec 07 22:51:31 2008 +0100
+| |  summary:     coorect end freefem, try to save consle text
+| |
+o |  changeset:   1473:94e5bfadd2e9
+| |  user:        hecht
+| |  date:        Sat Dec 06 23:24:37 2008 +0100
+| |  summary:     coorect window version add  save console at end job
+| |
+o |  changeset:   1472:b072e947c473
+| |  user:        hecht
+| |  date:        Thu Dec 04 23:31:41 2008 +0100
+| |  summary:     coorect 3d exampel
+| |
+o |  changeset:   1471:cfe19aab6e91
+| |  user:        hecht
+| |  date:        Thu Dec 04 23:07:04 2008 +0100
+| |  summary:     change medit in ffmedit (the freefem++ version of medit)
+| |
+o |  changeset:   1470:e3003c8118ec
+| |  user:        hecht
+| |  date:        Thu Dec 04 22:08:28 2008 +0100
+| |  summary:     correct ..
+| |
+o |  changeset:   1469:94c6f5128de0
+| |  user:        hecht
+| |  date:        Thu Dec 04 21:55:00 2008 +0100
+| |  summary:     add BLASLIB on SuperLu link
+| |
+o |  changeset:   1468:8296e5850e9b
+| |  user:        hecht
+| |  date:        Thu Dec 04 21:28:48 2008 +0100
+| |  summary:     add no compile on pure win32
+| |
+o |  changeset:   1467:2ba1cc1df0ce
+| |  user:        hecht
+| |  date:        Thu Dec 04 18:13:09 2008 +0100
+| |  summary:     coorect Makefile
+| |
+o |  changeset:   1466:beadf0e06de0
+| |  user:        hecht
+| |  date:        Thu Dec 04 18:07:41 2008 +0100
+| |  summary:     correct Makefile
+| |
+o |  changeset:   1465:338221666d53
+| |  user:        hecht
+| |  date:        Thu Dec 04 17:49:24 2008 +0100
+| |  summary:     coorect makefile
+| |
+o |  changeset:   1464:7b0eb03791c7
+| |  user:        hecht
+| |  date:        Thu Dec 04 17:35:58 2008 +0100
+| |  summary:     correct pb unzip
+| |
+o |  changeset:   1463:604e870e1a68
+| |  user:        hecht
+| |  date:        Thu Dec 04 17:31:14 2008 +0100
+| |  summary:     coorect Makefile for window
+| |
+o |  changeset:   1462:e78f4ba9d558
+| |  user:        hecht
+| |  date:        Thu Dec 04 16:19:27 2008 +0100
+| |  summary:     correct Install-MacOS v3
+| |
+o |  changeset:   1461:16b7e168e0af
+| |  user:        hecht
+| |  date:        Thu Dec 04 16:14:18 2008 +0100
+| |  summary:     correct of v3
+| |
+o |  changeset:   1460:719b338b6647
+| |  user:        hecht
+| |  date:        Wed Dec 03 23:39:47 2008 +0100
+| |  summary:     correct makefile for load compilation
+| |
+o |  changeset:   1459:1078ad4956af
+| |  user:        hecht
+| |  date:        Tue Dec 02 11:19:25 2008 +0100
+| |  summary:     correct build medit (compit.date)
+| |
+o |  changeset:   1458:5ff7097a0422
+| |  user:        hecht
+| |  date:        Mon Dec 01 22:14:26 2008 +0100
+| |  summary:     correct ffglut.cpp
+| |
+o |  changeset:   1457:275696a1143d
+| |  user:        hecht
+| |  date:        Sun Nov 30 22:01:37 2008 +0100
+| |  summary:     change SuperLU.cpp -> SuperLu.cpp
+| |
+o |  changeset:   1456:60ee6e9fa734
+| |  user:        hecht
+| |  date:        Sun Nov 30 22:00:31 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1455:4638f02095af
+| |  user:        hecht
+| |  date:        Sun Nov 30 21:43:24 2008 +0100
+| |  summary:     correct bmo.cpp on cygwin
+| |
+o |  changeset:   1454:5680cb4fc599
+| |  user:        hecht
+| |  date:        Sun Nov 30 21:26:42 2008 +0100
+| |  summary:     correct bmo rand generator for win32
+| |
+o |  changeset:   1453:b813c4de5ff9
+| |  user:        hecht
+| |  date:        Sat Nov 29 22:38:28 2008 +0100
+| |  summary:     change rindex -> strrchr under win32
+| |
+o |  changeset:   1452:62b7a73e0883
+| |  user:        hecht
+| |  date:        Sat Nov 29 21:49:18 2008 +0100
+| |  summary:     correct the doc
+| |
+o |  changeset:   1451:3cedfc02647b
+| |  user:        hecht
+| |  date:        Sat Nov 29 21:45:16 2008 +0100
+| |  summary:     Upgrade the doc
+| |
+o |  changeset:   1450:0f2d69e72651
+| |  user:        hecht
+| |  date:        Sat Nov 29 19:20:30 2008 +0100
+| |  summary:     add
+| |
+o |  changeset:   1449:f9d27572c59e
+| |  user:        hecht
+| |  date:        Sat Nov 29 19:14:43 2008 +0100
+| |  summary:     add configure --disable-dependency-tracking  for universal build (macos)
+| |
+o |  changeset:   1448:5972ee9487be
+| |  user:        hecht
+| |  date:        Sat Nov 29 19:02:26 2008 +0100
+| |  summary:     ok a not to bad version
+| |
+o |  changeset:   1447:feed975f6576
+| |  user:        hecht
+| |  date:        Sat Nov 29 18:24:07 2008 +0100
+| |  summary:     correct load facily (test if multy load, and load only one time)
+| |
+o |  changeset:   1446:3880a683b418
+| |  user:        hecht
+| |  date:        Sat Nov 29 18:17:37 2008 +0100
+| |  summary:     correct load example
+| |
+o |  changeset:   1445:c4c1e3ee80a3
+| |  user:        hecht
+| |  date:        Sat Nov 29 17:39:46 2008 +0100
+| |  summary:     change bmo.cpp -> lgbmo.cpp
+| |
+o |  changeset:   1444:ae1862b180e5
+| |  user:        hecht
+| |  date:        Sat Nov 29 17:34:17 2008 +0100
+| |  summary:     add bmo stuff)
+| |
+o |  changeset:   1443:2607ddbf9df2
+| |  user:        hecht
+| |  date:        Sat Nov 29 16:47:49 2008 +0100
+| |  summary:     remove medit lauching when no graphic
+| |
+o |  changeset:   1442:7ff31fce3f84
+| |  user:        hecht
+| |  date:        Sat Nov 29 16:36:48 2008 +0100
+| |  summary:     recorrect
+| |
+o |  changeset:   1441:bb346316ad4a
+| |  user:        hecht
+| |  date:        Sat Nov 29 16:32:00 2008 +0100
+| |  summary:     rebuld regtests.edp
+| |
+o |  changeset:   1440:c10cf4df8949
+| |  user:        hecht
+| |  date:        Sat Nov 29 16:25:31 2008 +0100
+| |  summary:     remove glumesh.edp form regtest
+| |
+o |  changeset:   1439:d0f1c7e9c376
+| |  user:        hecht
+| |  date:        Sat Nov 29 16:05:24 2008 +0100
+| |  summary:     do graphic only on mpirank==0
+| |
+o |  changeset:   1438:eee4429533f7
+| |  user:        hecht
+| |  date:        Sat Nov 29 15:58:42 2008 +0100
+| |  summary:     correct bug in eigenvalue part.
+| |
+o |  changeset:   1437:0a0f8d8930f9
+| |  user:        morice
+| |  date:        Fri Nov 28 12:12:32 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1436:e4c7ffca9ab1
+| |  user:        morice
+| |  date:        Fri Nov 28 12:11:03 2008 +0100
+| |  summary:     Transformation Matrice Morse (stockage ligne) en CCS(compressed column storage)
+| |
+o |  changeset:   1435:45be17df8622
+| |  user:        morice
+| |  date:        Fri Nov 28 11:43:19 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1434:fd52925b5f2a
+| |  user:        hecht
+| |  date:        Fri Nov 28 10:17:32 2008 +0100
+| |  summary:     miss tappin SuperLU.cpp  -> SuperLu.cpp
+| |
+o |  changeset:   1433:acf7ea000d8a
+| |  user:        hecht
+| |  date:        Fri Nov 28 08:09:14 2008 +0100
+| |  summary:     correct 3d exemples
+| |
+o |  changeset:   1432:b0289a360bb3
+| |  user:        hecht
+| |  date:        Wed Nov 26 20:17:04 2008 +0100
+| |  summary:     correct tetgen
+| |
+o |  changeset:   1431:ba4c8e8b1a47
+| |  user:        hecht
+| |  date:        Wed Nov 26 19:51:10 2008 +0100
+| |  summary:     correct missing link pb (tetgen.cpp include msh3.cpp with out int.
+| |
+o |  changeset:   1430:d973280bc7af
+| |  user:        morice
+| |  date:        Wed Nov 26 16:26:31 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1429:5f00f74d83cd
+| |  user:        hecht
+| |  date:        Tue Nov 25 23:03:41 2008 +0100
+| |  summary:     a last touch before the version...
+| |
+o |  changeset:   1428:198f6558aa4d
+| |  user:        hecht
+| |  date:        Tue Nov 25 21:41:51 2008 +0100
+| |  summary:     correct auto compilation of ffw3, superlu, tetgen in cas au enable-download
+| |
+o |  changeset:   1427:f0e86c3e6d85
+| |  user:        hecht
+| |  date:        Tue Nov 25 18:38:00 2008 +0100
+| |  summary:     coorect script for freefem++ app
+| |
+o |  changeset:   1426:9b1df463725b
+| |  user:        hecht
+| |  date:        Tue Nov 25 18:22:54 2008 +0100
+| |  summary:     coorect install macos
+| |
+o |  changeset:   1425:3c52c2253fb7
+| |  user:        hecht
+| |  date:        Tue Nov 25 17:27:14 2008 +0100
+| |  summary:     try to finalise version 3.0-1
+| |
+o |  changeset:   1424:6d9de1c4a05d
+| |  user:        hecht
+| |  date:        Tue Nov 25 17:09:49 2008 +0100
+| |  summary:     next
+| |
+o |  changeset:   1423:42713d97f36f
+| |  user:        hecht
+| |  date:        Tue Nov 25 16:49:48 2008 +0100
+| |  summary:     correct load examples  change popoe.cpp in medit.cpp
+| |
+o |  changeset:   1422:779acd0cfbe2
+| |  user:        hecht
+| |  date:        Tue Nov 25 14:16:39 2008 +0100
+| |  summary:     add missing file
+| |
+o |  changeset:   1421:e70b14304b98
+| |  user:        hecht
+| |  date:        Tue Nov 25 01:05:08 2008 +0100
+| |  summary:     coorect mistake in use of ffglut (remove if FreeFem++-xxx )
+| |
+o |  changeset:   1420:0d19f82c7039
+| |  user:        hecht
+| |  date:        Mon Nov 24 23:18:25 2008 +0100
+| |  summary:     add stuff to save window buff.
+| |
+o |  changeset:   1419:f9ae484334fc
+| |  user:        hecht
+| |  date:        Mon Nov 24 22:46:20 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1418:9650773d46e0
+| |  user:        hecht
+| |  date:        Mon Nov 24 21:31:56 2008 +0100
+| |  summary:     correct layer.edp
+| |
+o |  changeset:   1417:ec0d0e8459b0
+| |  user:        hecht
+| |  date:        Mon Nov 24 20:49:58 2008 +0100
+| |  summary:     coorect glumesh2d load (now in freefem++)
+| |
+o |  changeset:   1416:d4c3c0aa5fd8
+| |  user:        hecht
+| |  date:        Mon Nov 24 20:20:15 2008 +0100
+| |  summary:     update to 3.0_1 testing
+| |
+o |  changeset:   1415:a29e50390efd
+| |  user:        hecht
+| |  date:        Mon Nov 24 20:10:17 2008 +0100
+| |  summary:     past to version 3.0-1
+| |
+o |  changeset:   1414:8ffccb723fd7
+| |  user:        hecht
+| |  date:        Mon Nov 24 17:22:44 2008 +0100
+| |  summary:     correct FreeFem++
+| |
+o |  changeset:   1413:cb84d704cd68
+| |  user:        hecht
+| |  date:        Mon Nov 24 17:08:38 2008 +0100
+| |  summary:     correct of missing io
+| |
+o |  changeset:   1412:ca6fdf19f43a
+| |  user:        hecht
+| |  date:        Mon Nov 24 14:47:12 2008 +0100
+| |  summary:     coorec tmiss tapping
+| |
+o |  changeset:   1411:bf601c202065
+| |  user:        hecht
+| |  date:        Mon Nov 24 14:45:02 2008 +0100
+| |  summary:     add window stuff
+| |
+o |  changeset:   1410:069a9f4b35f8
+| |  user:        hecht
+| |  date:        Mon Nov 24 14:22:26 2008 +0100
+| |  summary:     correct sing flags with PCrgraph.cpp
+| |
+o |  changeset:   1409:2eff1dc91fa8
+| |  user:        hecht
+| |  date:        Mon Nov 24 13:58:45 2008 +0100
+| |  summary:     correct miss tapping
+| |
+o |  changeset:   1408:567bb820c141
+| |  user:        hecht
+| |  date:        Mon Nov 24 13:44:40 2008 +0100
+| |  summary:     add @LIBSNOCONSOLE@ to link freefem++ on windows
+| |
+o |  changeset:   1407:a592c340fa42
+| |  user:        hecht
+| |  date:        Mon Nov 24 10:15:57 2008 +0100
+| |  summary:     yntaxe err.  )) -> ) line 51
+| |
+o |  changeset:   1406:9456f62f1675
+| |  user:        hecht
+| |  date:        Mon Nov 24 10:09:54 2008 +0100
+| |  summary:     do the final (may be ) on no graphics
+| |
+o |  changeset:   1405:d33cd9480a19
+| |  user:        hecht
+| |  date:        Sun Nov 23 23:24:42 2008 +0100
+| |  summary:     remove -mwindows flag
+| |
+o |  changeset:   1404:92d820fc3689
+| |  user:        hecht
+| |  date:        Sun Nov 23 22:56:24 2008 +0100
+| |  summary:     try to have good version of ffglut
+| |
+o |  changeset:   1403:fd3446efd662
+| |  user:        hecht
+| |  date:        Sun Nov 23 22:23:51 2008 +0100
+| |  summary:     correct for win32 api
+| |
+o |  changeset:   1402:cd1e9c3a65f2
+| |  user:        hecht
+| |  date:        Sun Nov 23 16:40:45 2008 +0100
+| |  summary:     crrech ff_glut lib under win32
+| |
+o |  changeset:   1401:eaf758e3a489
+| |  user:        hecht
+| |  date:        Sun Nov 23 16:32:33 2008 +0100
+| |  summary:     change glut libs under win32 (no cygwin)
+| |
+o |  changeset:   1400:854085e2d35f
+| |  user:        hecht
+| |  date:        Sun Nov 23 16:21:00 2008 +0100
+| |  summary:     add new file for win32 comile
+| |
+o |  changeset:   1399:95336c8e2c44
+| |  user:        hecht
+| |  date:        Sun Nov 23 15:36:58 2008 +0100
+| |  summary:     update for ffglu and windows
+| |
+o |  changeset:   1398:f9100b0bb790
+| |  user:        hecht
+| |  date:        Sun Nov 23 14:54:49 2008 +0100
+| |  summary:     correct of win32
+| |
+o |  changeset:   1397:7d704bab6a59
+| |  user:        hecht
+| |  date:        Sun Nov 23 14:53:06 2008 +0100
+| |  summary:     correct PlotStream.hpp for win32
+| |
+o |  changeset:   1396:d4bab58e76b7
+| |  user:        hecht
+| |  date:        Sun Nov 23 10:11:42 2008 +0100
+| |  summary:     reomve exeption
+| |
+o |  changeset:   1395:7746ed4b6e53
+| |  user:        hecht
+| |  date:        Sat Nov 22 20:29:26 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1394:76b21f8a6f07
+| |  user:        hecht
+| |  date:        Sat Nov 22 18:16:09 2008 +0100
+| |  summary:     correct Makefile.am
+| |
+o |  changeset:   1393:28088ce8937e
+| |  user:        hecht
+| |  date:        Sat Nov 22 18:15:41 2008 +0100
+| |  summary:     add threads interface of windows
+| |
+o |  changeset:   1392:302846277f78
+| |  user:        hecht
+| |  date:        Thu Nov 20 14:05:20 2008 +0100
+| |  summary:     correct configure.ac fo ffglut  compie with pthread
+| |
+o |  changeset:   1391:04a9b160e8c4
+| |  user:        hecht
+| |  date:        Thu Nov 20 13:28:38 2008 +0100
+| |  summary:     correct int -> GLint in wiewport array type
+| |
+o |  changeset:   1390:5b0dea51e3ac
+| |  user:        hecht
+| |  date:        Wed Nov 19 14:40:29 2008 +0100
+| |  summary:     crrect build pkg dir
+| |
+o |  changeset:   1389:0e6bc0a93bdd
+| |  user:        hecht
+| |  date:        Wed Nov 19 14:38:27 2008 +0100
+| |  summary:     add super bluid lib
+| |
+o |  changeset:   1388:f4ea619db3e9
+| |  user:        hecht
+| |  date:        Wed Nov 19 11:55:19 2008 +0100
+| |  summary:     correct of the download/tetgen/Makefile makefile.
+| |
+o |  changeset:   1387:3b6ce28f34f8
+| |  user:        hecht
+| |  date:        Tue Nov 18 17:38:31 2008 +0100
+| |  summary:     add missig file
+| |
+o |  changeset:   1386:08adb5c34633
+| |  user:        hecht
+| |  date:        Sun Nov 16 16:40:00 2008 +0100
+| |  summary:     try to put all download in same directory download/pkg
+| |
+o |  changeset:   1385:0f9c81225b28
+| |  user:        hecht
+| |  date:        Sun Nov 16 12:39:46 2008 +0100
+| |  summary:     add package you ubuntu
+| |
+o |  changeset:   1384:2f8474dc4698
+| |  user:        hecht
+| |  date:        Sun Nov 16 11:51:10 2008 +0100
+| |  summary:     correct the sieze of array to store eigen item (add +1)
+| |
+o |  changeset:   1383:b7546bc2390c
+| |  user:        hecht
+| |  date:        Sun Nov 16 11:09:58 2008 +0100
+| |  summary:     remove uninitialiez assert.
+| |
+o |  changeset:   1382:ff78c27246d0
+| |  user:        hecht
+| |  date:        Sun Nov 16 10:48:56 2008 +0100
+| |  summary:     coorect libmesh -> libmesh
+| |
+o |  changeset:   1381:552ace2fcfc7
+| |  user:        hecht
+| |  date:        Sun Nov 16 10:23:09 2008 +0100
+| |  summary:     coorect Makefile.am dependence to bluid compil.date
+| |
+o |  changeset:   1380:0caf8178753d
+| |  user:        hecht
+| |  date:        Sun Nov 16 10:02:05 2008 +0100
+| |  summary:     correct ffmedit Makefile.am missing bluid of ompil.date file
+| |
+o |  changeset:   1379:4e8f7f89556a
+| |  user:        hecht
+| |  date:        Sun Nov 16 09:43:24 2008 +0100
+| |  summary:     correct srv/nw/Makefile.am
+| |
+o |  changeset:   1378:9516426752a3
+| |  user:        hecht
+| |  date:        Sun Nov 16 09:33:36 2008 +0100
+| |  summary:     add missing file
+| |
+o |  changeset:   1377:93b754159849
+| |  user:        hecht
+| |  date:        Sun Nov 16 01:06:32 2008 +0100
+| |  summary:     Huge change in the graphic part.
+| |
+o |  changeset:   1376:9f86824cee2c
+| |  user:        morice
+| |  date:        Thu Nov 13 16:43:39 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1375:1589ecf1c4b7
+| |  user:        morice
+| |  date:        Thu Nov 13 16:40:04 2008 +0100
+| |  summary:     Removed file
+| |
+o |  changeset:   1374:32d14aaa8bc1
+| |  user:        morice
+| |  date:        Wed Nov 05 11:15:23 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1373:0781509f872e
+| |  user:        morice
+| |  date:        Tue Nov 04 17:18:35 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1372:1faebc041661
+| |  user:        morice
+| |  date:        Tue Nov 04 17:16:50 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1371:cf940b88989d
+| |  user:        morice
+| |  date:        Thu Oct 30 11:38:03 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1370:472ebd5510b3
+| |  user:        morice
+| |  date:        Thu Oct 30 11:29:15 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1369:884b6e24b73b
+| |  user:        morice
+| |  date:        Wed Oct 29 16:29:20 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1368:71743a70f477
+| |  user:        morice
+| |  date:        Wed Oct 29 15:10:15 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1367:5f666b631f8b
+| |  user:        morice
+| |  date:        Wed Oct 29 14:12:46 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1366:5ac0c0b60644
+| |  user:        morice
+| |  date:        Wed Oct 29 11:24:56 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1365:d236083ebc43
+| |  user:        morice
+| |  date:        Wed Oct 29 11:21:03 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1364:85909104f0c6
+| |  user:        morice
+| |  date:        Wed Oct 29 11:09:45 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1363:5cb1c4d257fd
+| |  user:        morice
+| |  date:        Mon Oct 27 10:09:44 2008 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1362:cf7b0f1fb9da
+| |  user:        hecht
+| |  date:        Mon Oct 20 22:24:33 2008 +0200
+| |  summary:     add medit to freefem++
+| |
+o |  changeset:   1361:41bd8613d841
+| |  user:        hecht
+| |  date:        Mon Oct 20 16:11:57 2008 +0200
+| |  summary:     add medit in ff++
+| |
+o |  changeset:   1360:6e76013fe786
+| |  user:        hecht
+| |  date:        Sun Oct 19 21:59:21 2008 +0200
+| |  summary:     -- correct none sym eigen arpack call
+| |
+o |  changeset:   1359:97fc195ae7e3
+| |  user:        hecht
+| |  date:        Fri Oct 17 10:44:44 2008 +0200
+| |  summary:     coorect memory misstake in profile matrix.
+| |
+o |  changeset:   1358:182ef0dd29d7
+| |  user:        hecht
+| |  date:        Thu Oct 16 23:10:19 2008 +0200
+| |  summary:     correct memory problem with valgrind.
+| |
+o |  changeset:   1357:fceafcd3c68a
+| |  user:        hecht
+| |  date:        Mon Oct 13 15:58:25 2008 +0200
+| |  summary:     correct  low of precision of geom
+| |
+o |  changeset:   1356:a98d4ac7e0c7
+| |  user:        hecht
+| |  date:        Mon Oct 06 16:59:07 2008 +0200
+| |  summary:     load in correct .edp
+| |
+o |  changeset:   1355:4de09c7ef69d
+| |  user:        hecht
+| |  date:        Mon Oct 06 10:04:30 2008 +0200
+| |  summary:     correct 3d. convert
+| |
+o |  changeset:   1354:6fb475c41e45
+| |  user:        hecht
+| |  date:        Mon Oct 06 09:28:36 2008 +0200
+| |  summary:     correct convect 3D
+| |
+o |  changeset:   1353:a31edb97daea
+| |  user:        hecht
+| |  date:        Mon Oct 06 09:26:17 2008 +0200
+| |  summary:     correct convect in 3D.
+| |
+o |  changeset:   1352:c17f71265f73
+| |  user:        morice
+| |  date:        Thu Sep 25 15:00:32 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1351:e2d0255aa3b7
+| |  user:        morice
+| |  date:        Thu Sep 25 14:55:41 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1350:6bad008adbfd
+| |  user:        morice
+| |  date:        Thu Sep 18 11:31:12 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1349:fcdbf4222941
+| |  user:        morice
+| |  date:        Thu Sep 18 11:24:59 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1348:f577647a6ef8
+| |  user:        hecht
+| |  date:        Wed Sep 17 18:25:19 2008 +0200
+| |  summary:     correct PB on win32 version with P102_1.o (bogus) so remve because not used.
+| |
+o |  changeset:   1347:e94555467e80
+| |  user:        hecht
+| |  date:        Thu Sep 04 13:18:21 2008 +0200
+| |  summary:     add NSI3d-carac.edp
+| |
+o |  changeset:   1346:fd5ed1df556b
+| |  user:        hecht
+| |  date:        Wed Aug 27 17:07:31 2008 +0200
+| |  summary:     a fist beta version with 3d convect
+| |
+o |  changeset:   1345:0e28f1046f82
+| |  user:        hecht
+| |  date:        Wed Aug 27 16:13:16 2008 +0200
+| |  summary:     correct in case of more than 2 proc.
+| |
+o |  changeset:   1344:bc6b22ce6c7d
+| |  user:        hecht
+| |  date:        Wed Aug 27 15:28:02 2008 +0200
+| |  summary:     cleanning mpi output
+| |
+o |  changeset:   1343:14964c74521c
+| |  user:        hecht
+| |  date:        Wed Aug 27 15:18:46 2008 +0200
+| |  summary:     same
+| |
+o |  changeset:   1342:3101fb2fa5a9
+| |  user:        hecht
+| |  date:        Wed Aug 27 15:16:55 2008 +0200
+| |  summary:     improve output of  end mpi
+| |
+o |  changeset:   1341:c9b452184dc3
+| |  user:        hecht
+| |  date:        Wed Aug 27 14:50:58 2008 +0200
+| |  summary:     output clening
+| |
+o |  changeset:   1340:5d9c08ee5b5a
+| |  user:        hecht
+| |  date:        Wed Aug 27 14:30:24 2008 +0200
+| |  summary:     correct MPI dump
+| |
+o |  changeset:   1339:761f96cc8fa4
+| |  user:        hecht
+| |  date:        Mon Aug 25 16:18:28 2008 +0200
+| |  summary:     add new test
+| |
+o |  changeset:   1338:96837b9d8490
+| |  user:        hecht
+| |  date:        Mon Aug 25 16:01:19 2008 +0200
+| |  summary:     add meditsol.edp test (bugus)
+| |
+o |  changeset:   1337:631ca7f3b833
+| |  user:        hecht
+| |  date:        Mon Aug 25 15:23:45 2008 +0200
+| |  summary:     correct popen.cpp
+| |
+o |  changeset:   1336:3fae4ab680d1
+| |  user:        hecht
+| |  date:        Mon Aug 25 15:00:35 2008 +0200
+| |  summary:     add popen.cpp of medit link
+| |
+o |  changeset:   1335:9a3735113e93
+| |  user:        hecht
+| |  date:        Mon Aug 25 10:57:43 2008 +0200
+| |  summary:     add convect 3D
+| |
+o |  changeset:   1334:4fd6a0503885
+| |  user:        hecht
+| |  date:        Wed Jul 23 23:00:00 2008 +0200
+| |  summary:     a beta version of 3d version
+| |
+o |  changeset:   1333:634631a624d7
+| |  user:        hecht
+| |  date:        Wed Jul 23 22:11:51 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1332:dd46501bfe35
+| |  user:        hecht
+| |  date:        Wed Jul 23 22:09:31 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1331:5cadbb291dff
+| |  user:        hecht
+| |  date:        Wed Jul 23 14:51:56 2008 +0200
+| |  summary:     correct CXXFLAGS for load.link
+| |
+o |  changeset:   1330:9acc92fffb15
+| |  user:        hecht
+| |  date:        Wed Jul 23 14:07:36 2008 +0200
+| |  summary:     coorect algo.edp
+| |
+o |  changeset:   1329:4f3864fced7f
+| |  user:        hecht
+| |  date:        Wed Jul 23 14:05:48 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1328:593795622f68
+| |  user:        hecht
+| |  date:        Wed Jul 23 13:47:08 2008 +0200
+| |  summary:     add new 3d exemple
+| |
+o |  changeset:   1327:e396a7e86ddf
+| |  user:        hecht
+| |  date:        Wed Jul 23 13:03:58 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1326:4101a19ce39b
+| |  user:        morice
+| |  date:        Wed Jul 23 12:15:13 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1325:8511165a8c1a
+| |  user:        morice
+| |  date:        Wed Jul 23 12:10:59 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1324:a7fbfb69aff9
+| |  user:        hecht
+| |  date:        Mon Jul 07 22:39:14 2008 +0200
+| |  summary:     add big change in pointer cleanning of mesh.
+| |
+o |  changeset:   1323:c1c144d0c93e
+| |  user:        morice
+| |  date:        Fri Jun 27 10:45:42 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1322:72d5d48de380
+| |  user:        hecht
+| |  date:        Fri Jun 27 10:07:39 2008 +0200
+| |  summary:     remove const char   warning
+| |
+o |  changeset:   1321:0350e3b8531b
+| |  user:        hecht
+| |  date:        Fri Jun 27 10:00:34 2008 +0200
+| |  summary:     remove tetgen part
+| |
+o |  changeset:   1320:ae68e0e4759d
+| |  user:        hecht
+| |  date:        Fri Jun 27 09:51:03 2008 +0200
+| |  summary:     correct FQuadTree construction
+| |
+o |  changeset:   1319:dacab2664d74
+| |  user:        hecht
+| |  date:        Fri Jun 27 09:50:21 2008 +0200
+| |  summary:     add constructeur dans FQuadTree
+| |
+o |  changeset:   1318:47569a10b553
+| |  user:        hecht
+| |  date:        Thu Jun 26 17:46:28 2008 +0200
+| |  summary:     correct RdtoZd  fonction
+| |
+o |  changeset:   1317:b286cadc4463
+| |  user:        morice
+| |  date:        Thu Jun 26 16:12:33 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1316:bd0a4bc55b82
+| |  user:        morice
+| |  date:        Thu Jun 26 14:18:52 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1315:353f0557aeeb
+| |  user:        hecht
+| |  date:        Tue Jun 24 13:36:56 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1314:b48bf88426b8
+| |  user:        hecht
+| |  date:        Tue Jun 24 11:48:58 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1313:db5f17893fd7
+| |  user:        hecht
+| |  date:        Sun Jun 22 20:45:48 2008 +0200
+| |  summary:     remove of cout
+| |
+o |  changeset:   1312:d807bb0388ff
+| |  user:        hecht
+| |  date:        Sat Jun 21 14:18:56 2008 +0200
+| |  summary:     add missing logo
+| |
+o |  changeset:   1311:0f16fe410b58
+| |  user:        hecht
+| |  date:        Sat Jun 21 14:17:09 2008 +0200
+| |  summary:     the alpha version. 3.00
+| |
+o |  changeset:   1310:f6455cf8648e
+| |  user:        hecht
+| |  date:        Sat Jun 21 14:05:00 2008 +0200
+| |  summary:     add missing files
+| |
+o |  changeset:   1309:07e1db73daf0
+| |  user:        morice
+| |  date:        Fri Jun 20 16:58:55 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1308:7b7733d0e797
+| |  user:        hecht
+| |  date:        Thu Jun 19 23:37:37 2008 +0200
+| |  summary:     add missing files
+| |
+o |  changeset:   1307:3302a94264c3
+| |  user:        hecht
+| |  date:        Thu Jun 19 23:22:54 2008 +0200
+| |  summary:     correct  examples++-load/Makefile.am  to add dependence to compile glumesh.cpp
+| |
+o |  changeset:   1306:6edc84e14d53
+| |  user:        hecht
+| |  date:        Thu Jun 19 14:21:08 2008 +0200
+| |  summary:     un version pas mal
+| |
+o |  changeset:   1305:173c659a2f6f
+| |  user:        hecht
+| |  date:        Wed Jun 18 13:55:36 2008 +0200
+| |  summary:     add true random function
+| |
+o |  changeset:   1304:3c554295e169
+| |  user:        hecht
+| |  date:        Wed Jun 18 11:17:57 2008 +0200
+| |  summary:     coorect error  between R2 and R3 stuff.
+| |
+o |  changeset:   1303:8345c9dcffd8
+| |  user:        hecht
+| |  date:        Fri Jun 13 12:01:42 2008 +0200
+| |  summary:     coorect missing patch-lapack in arpack
+| |
+o |  changeset:   1302:a8e47b3a6ead
+| |  user:        hecht
+| |  date:        Thu Jun 12 23:30:25 2008 +0200
+| |  summary:     add missing file
+| |
+o |  changeset:   1301:8419ef4b5ea6
+| |  user:        hecht
+| |  date:        Tue Jun 10 22:19:20 2008 +0200
+| |  summary:     remove arpack++ from freefem++
+| |
+o |  changeset:   1300:5f7e9ae6121c
+| |  user:        hecht
+| |  date:        Tue Jun 10 22:17:25 2008 +0200
+| |  summary:     remove arpack++
+| |
+o |  changeset:   1299:47c0d89ac233
+| |  user:        hecht
+| |  date:        Tue Jun 10 22:15:11 2008 +0200
+| |  summary:     remove arpack++
+| |
+o |  changeset:   1298:e2fed9f3b434
+| |  user:        hecht
+| |  date:        Mon Jun 09 18:36:48 2008 +0200
+| |  summary:     correction g++ 4.2
+| |
+o |  changeset:   1297:cde6b903a078
+| |  user:        hecht
+| |  date:        Mon Jun 09 18:36:08 2008 +0200
+| |  summary:     correction of g++ 4.2
+| |
+o |  changeset:   1296:dba2f88087e1
+| |  user:        morice
+| |  date:        Mon Jun 09 14:32:52 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1295:a38a0a05c591
+| |  user:        morice
+| |  date:        Mon Jun 09 14:15:13 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1294:62223cb51036
+| |  user:        hecht
+| |  date:        Wed May 28 21:44:49 2008 +0200
+| |  summary:     a correct in FEproduct
+| |
+o |  changeset:   1293:5725424057d0
+| |  user:        hecht
+| |  date:        Wed May 28 17:18:14 2008 +0200
+| |  summary:     remove dump
+| |
+o |  changeset:   1292:8b52cc829a1e
+| |  user:        hecht
+| |  date:        Wed May 28 17:16:34 2008 +0200
+| |  summary:     the first 3d version running all test
+| |
+o |  changeset:   1291:6677a3cb311b
+| |  user:        hecht
+| |  date:        Mon May 26 17:12:44 2008 +0200
+| |  summary:     add explicit instenciation E_set_fev3
+| |
+o |  changeset:   1290:384cb8fc29ec
+| |  user:        hecht
+| |  date:        Mon May 26 16:59:08 2008 +0200
+| |  summary:     Stokes is working now.
+| |
+o |  changeset:   1289:44bcfe697314
+| |  user:        hecht
+| |  date:        Mon May 26 09:07:56 2008 +0200
+| |  summary:     add STokes in 3d
+| |
+o |  changeset:   1288:e1870d7093b2
+| |  user:        hecht
+| |  date:        Sat May 24 17:05:38 2008 +0200
+| |  summary:     the first Laplace Operator in 3d work in P13d,P23d finite element.
+| |
+o |  changeset:   1287:0601417c00f0
+| |  user:        hecht
+| |  date:        Thu May 22 16:05:13 2008 +0200
+| |  summary:     correct pb in mesure of tet.
+| |
+o |  changeset:   1286:13797127fc40
+| |  user:        hecht
+| |  date:        Wed May 21 12:41:42 2008 +0200
+| |  summary:     correct GTree  Case methode
+| |
+o |  changeset:   1285:25a3f156a803
+| |  user:        morice
+| |  date:        Wed May 21 11:05:22 2008 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1284:12639b380533
+| |  user:        hecht
+| |  date:        Tue May 20 22:05:36 2008 +0200
+| |  summary:     pb case sensitive in include
+| |
+o |  changeset:   1283:264ad3e9df15
+| |  user:        hecht
+| |  date:        Tue May 20 16:44:49 2008 +0200
+| |  summary:     modif for layer meshes.
+| |
+o |  changeset:   1282:eede6e45ca29
+| |  user:        hecht
+| |  date:        Tue May 20 12:12:16 2008 +0200
+| |  summary:     correct  layer
+| |
+o |  changeset:   1281:9e5802e9e6f2
+| |  user:        hecht
+| |  date:        Tue May 20 11:08:56 2008 +0200
+| |  summary:     add 3 files
+| |
+o |  changeset:   1280:25be52991a76
+| |  user:        hecht
+| |  date:        Fri May 16 10:07:35 2008 +0200
+| |  summary:     add int2d on border off 3d mesh
+| |
+o |  changeset:   1279:271a0c10b941
+| |  user:        hecht
+| |  date:        Fri May 16 00:26:03 2008 +0200
+| |  summary:     add PBord methode to compute genericaly integrale on border element.
+| |
+o |  changeset:   1278:bcf7733f66cf
+| |  user:        hecht
+| |  date:        Thu May 15 23:39:14 2008 +0200
+| |  summary:     correct class  Z3 + Save 3d mesh.
+| |
+o |  changeset:   1277:7f3efc97d905
+| |  user:        hecht
+| |  date:        Thu May 15 23:11:21 2008 +0200
+| |  summary:     remove strversionnumber.cpp (build by the makefiel)
+| |
+o |  changeset:   1276:6846c158476b
+| |  user:        hecht
+| |  date:        Thu May 15 23:03:50 2008 +0200
+| |  summary:     correct win32 mistake double def + PB  GQTree R1
+| |
+o |  changeset:   1275:9b461360cca1
+| |  user:        hecht
+| |  date:        Thu May 15 14:52:25 2008 +0200
+| |  summary:     correct missing assert def in src/femlib/QuadratureFormular.cpp
+| |
+o |  changeset:   1274:59f70178b6a3
+| |  user:        hecht
+| |  date:        Thu May 15 14:13:05 2008 +0200
+| |  summary:     correct
+| |
+o |  changeset:   1273:4e1c1f21abc0
+| |  user:        hecht
+| |  date:        Thu May 15 13:31:00 2008 +0200
+| |  summary:     add missing file
+| |
+o |  changeset:   1272:1e7c8947e560
+| |  user:        hecht
+| |  date:        Thu May 15 13:28:57 2008 +0200
+| |  summary:     correct include dir
+| |
+o |  changeset:   1271:20d19853a704
+| |  user:        hecht
+| |  date:        Thu May 15 12:48:33 2008 +0200
+| |  summary:     add missing file
+| |
+o |  changeset:   1270:6375ea25c494
+| |  user:        hecht
+| |  date:        Thu May 15 12:05:19 2008 +0200
+| |  summary:     a fist 3d version, with PB on boundaru contion.
+| |
+o |  changeset:   1269:93f976abeabc
+| |  user:        hecht
+| |  date:        Thu May 15 00:47:02 2008 +0200
+| |  summary:     3d next step
+| |
+o |  changeset:   1268:60d306545870
+| |  user:        hecht
+| |  date:        Wed May 14 14:48:25 2008 +0200
+| |  summary:     3d continuing
+| |
+o |  changeset:   1267:051a2b0b8339
+| |  user:        hecht
+| |  date:        Wed May 07 16:12:02 2008 +0200
+| |  summary:     a first 3d version ..
+| |
+o |  changeset:   1266:a11672848900
+| |  user:        hecht
+| |  date:        Tue Apr 29 22:19:00 2008 +0200
+| |  summary:     add file
+| |
+o |  changeset:   1265:259dcc851d31
+| |  user:        hecht
+| |  date:        Tue Apr 29 22:01:24 2008 +0200
+| |  summary:     correct examples++-load
+| |
+o |  changeset:   1264:53db1907af65
+| |  user:        hecht
+| |  date:        Tue Apr 29 21:05:36 2008 +0200
+| |  summary:     pass to version 2.25 (last version before 3.0)
+| |
+o |  changeset:   1263:ec6a9046af52
+| |  tag:         release_2_24_4
+| |  user:        hecht
+| |  date:        Wed Apr 23 12:18:12 2008 +0200
+| |  summary:     correct missing code in DG of term in linear form
+| |
+o |  changeset:   1262:e6648830647f
+| |  user:        hecht
+| |  date:        Fri Apr 18 08:26:34 2008 +0200
+| |  summary:     see innovation + correzction in doc
+| |
+o |  changeset:   1261:59b6014ebe00
+| |  user:        hecht
+| |  date:        Fri Apr 11 16:52:51 2008 +0200
+| |  summary:     add formal operator .* and ./ on array []
+| |
+o |  changeset:   1260:ef82bf406677
+| |  user:        hecht
+| |  date:        Fri Apr 11 16:14:11 2008 +0200
+| |  summary:     correct lex.cpp for parameter macro  comma between [].
+| |
+o |  changeset:   1259:94fb8bee70ab
+| |  user:        hecht
+| |  date:        Wed Apr 09 15:46:19 2008 +0200
+| |  summary:     correct eigenvalue, (undo remove  1 line)
+| |
+o |  changeset:   1258:05b9c0c843e5
+| |  user:        hecht
+| |  date:        Wed Apr 09 14:20:41 2008 +0200
+| |  summary:     ad resid= vector in eigen value (see arpack doc)
+| |
+o |  changeset:   1257:d32b839daca5
+| |  user:        hecht
+| |  date:        Wed Apr 09 10:03:09 2008 +0200
+| |  summary:     correct err 21 trp in mshptg (pile trop petit)
+| |
+o |  changeset:   1256:3cdb4d96732c
+| |  user:        hecht
+| |  date:        Wed Apr 09 09:24:39 2008 +0200
+| |  summary:     coorect missing trap in case of errror in msgtpg
+| |
+o |  changeset:   1255:40aba1424fd5
+| |  user:        hecht
+| |  date:        Tue Apr 01 12:05:59 2008 +0200
+| |  summary:     add Bob Gustafson coorect in the doc.
+| |
+o |  changeset:   1254:99c4f39ceb54
+| |  user:        hecht
+| |  date:        Thu Mar 27 14:17:50 2008 +0100
+| |  summary:     correct confire.ac build FLIBS (suite)
+| |
+o |  changeset:   1253:7952d7e59157
+| |  user:        hecht
+| |  date:        Thu Mar 27 12:17:40 2008 +0100
+| |  summary:     misa a jour INNOVATION
+| |
+o |  changeset:   1252:686b9984089a
+| |  user:        hecht
+| |  date:        Thu Mar 27 12:14:26 2008 +0100
+| |  summary:     correct configre.ac to check FLIBS and test the value of FLIBS and X11_LIBS
+| |
+o |  changeset:   1251:7a218e8eb4e4
+| |  user:        hecht
+| |  date:        Fri Feb 22 18:10:51 2008 +0100
+| |  summary:     add missing file
+| |
+o |  changeset:   1250:3f6f96956582
+| |  user:        hecht
+| |  date:        Fri Feb 22 17:49:19 2008 +0100
+| |  summary:     pass to 2.24.1 and  correct buildmesh trap in case of degenerated border.
+| |
+o |  changeset:   1249:466c6cf70d4e
+| |  user:        hecht
+| |  date:        Tue Feb 19 21:00:35 2008 +0100
+| |  summary:     correct periodic condition limite to 1 edge.
+| |
+o |  changeset:   1248:292de6acfd0c
+| |  user:        hecht
+| |  date:        Fri Feb 15 11:16:44 2008 +0100
+| |  summary:     correct include.tar.gz
+| |
+o |  changeset:   1247:f1ac94ae30f0
+| |  user:        hecht
+| |  date:        Thu Feb 14 23:08:44 2008 +0100
+| |  summary:     add missing file R[123].hpp in Makefile.am for dist
+| |
+o |  changeset:   1246:5db85e01658c
+| |  user:        hecht
+| |  date:        Thu Feb 14 14:44:20 2008 +0100
+| |  summary:     rebuild include.tar.gz
+| |
+o |  changeset:   1245:6f7beaf98f55
+| |  user:        hecht
+| |  date:        Thu Feb 14 14:33:59 2008 +0100
+| |  summary:     v 2.24
+| |
+o |  changeset:   1244:71fc0f351404
+| |  user:        hecht
+| |  date:        Thu Feb 07 15:15:32 2008 +0100
+| |  summary:     add script to download medit on windows
+| |
+o |  changeset:   1243:37f9085ca0af
+| |  user:        hecht
+| |  date:        Mon Feb 04 15:07:38 2008 +0100
+| |  summary:     add lazst modification in the doc.
+| |
+o |  changeset:   1242:1d53bd6f9e96
+| |  user:        hecht
+| |  date:        Fri Feb 01 22:09:10 2008 +0100
+| |  summary:     add Th=triangule(xx,yy);
+| |
+o |  changeset:   1241:c1f45746fb19
+| |  user:        hecht
+| |  date:        Tue Jan 29 23:29:12 2008 +0100
+| |  summary:     add info   INNOVATION file
+| |
+o |  changeset:   1240:e1d2110881df
+| |  user:        hecht
+| |  date:        Tue Jan 29 23:20:52 2008 +0100
+| |  summary:     correct rare bug in bamg (missing initialisation variable edges[].adj
+| |
+o |  changeset:   1239:2d981f5a74aa
+| |  user:        hecht
+| |  date:        Thu Jan 24 09:26:32 2008 +0100
+| |  summary:     correct assert fail in case of no UMFPACK in make check
+| |
+o |  changeset:   1238:355795395a28
+| |  user:        hecht
+| |  date:        Wed Jan 23 11:04:16 2008 +0100
+| |  summary:     add mortar (Neuman to Dirichlet )  example in scalar and parallel version
+| |
+o |  changeset:   1237:7132e4a552e2
+| |  user:        hecht
+| |  date:        Tue Jan 22 17:23:05 2008 +0100
+| |  summary:     add vectorial operator ( a ? b : c)  on array where b and c can be scalar
+| |
+o |  changeset:   1236:35c531d0eda6
+| |  user:        hecht
+| |  date:        Wed Jan 16 12:37:04 2008 +0100
+| |  summary:     correct mpi (receive  is now synchrone  and send is asychrone)
+| |
+o |  changeset:   1235:ccbffa0edbc1
+| |  user:        hecht
+| |  date:        Fri Jan 11 10:59:18 2008 +0100
+| |  summary:     nothing
+| |
+o |  changeset:   1234:4a5c97ce6af0
+| |  user:        hecht
+| |  date:        Wed Jan 09 22:33:15 2008 +0100
+| |  summary:     correct README of debian and cnfigure.ac of checking umfpack lib.
+| |
+o |  changeset:   1233:6dc9e9cff6b7
+| |  user:        hecht
+| |  date:        Sat Jan 05 16:50:32 2008 +0100
+| |  summary:     correct Makefile to build universal executable file  on MacOS
+| |
+o |  changeset:   1232:5e33a386cfea
+| |  user:        hecht
+| |  date:        Wed Dec 26 17:30:04 2007 +0100
+| |  summary:     cvs ranlib and ar  in umfpack compilation process of universal file on apple.
+| |
+o |  changeset:   1231:67239ae99bc8
+| |  user:        hecht
+| |  date:        Wed Dec 26 16:44:28 2007 +0100
+| |  summary:     Make big change un configure.ac and makefiel.am to build universal binarie file on apple (ppc and i386)
+| |
+o |  changeset:   1230:42ff4f594013
+| |  user:        hecht
+| |  date:        Thu Dec 20 13:11:42 2007 +0100
+| |  summary:     correct freefem++-doc
+| |
+o |  changeset:   1229:46601bd22684
+| |  user:        hecht
+| |  date:        Tue Dec 18 18:35:55 2007 +0100
+| |  summary:     missing file
+| |
+o |  changeset:   1228:c55ffbf8c297
+| |  user:        hecht
+| |  date:        Tue Dec 18 18:19:04 2007 +0100
+| |  summary:     change ref value  correct elastycity.
+| |
+o |  changeset:   1227:4264a1078ace
+| |  user:        hecht
+| |  date:        Tue Dec 18 18:04:09 2007 +0100
+| |  summary:     just change in UFconfig_mk.m4 for freebsd for comment
+| |
+o |  changeset:   1226:82ca7c0795f4
+| |  user:        hecht
+| |  date:        Tue Dec 18 16:43:55 2007 +0100
+| |  summary:     see innovation correct bug in function with string argument
+| |
+o |  changeset:   1225:30b829eb80a6
+| |  user:        hecht
+| |  date:        Tue Dec 11 21:18:52 2007 +0100
+| |  summary:     type correct Pcrgraph
+| |
+o |  changeset:   1224:f93b6dc20752
+| |  user:        hecht
+| |  date:        Fri Nov 30 13:54:29 2007 +0100
+| |  summary:     correct   error on mpi version
+| |
+o |  changeset:   1223:6b813cebfc7e
+| |  user:        hecht
+| |  date:        Thu Nov 29 12:20:33 2007 +0100
+| |  summary:     suite
+| |
+o |  changeset:   1222:b31f36430d73
+| |  user:        hecht
+| |  date:        Thu Nov 29 12:18:20 2007 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1221:5a4cf32a8ce0
+| |  user:        hecht
+| |  date:        Thu Nov 29 12:15:25 2007 +0100
+| |  summary:     next
+| |
+o |  changeset:   1220:013e64381c12
+| |  user:        hecht
+| |  date:        Thu Nov 29 12:11:42 2007 +0100
+| |  summary:     correct missing preprocessing  variable
+| |
+o |  changeset:   1219:16f1a0466850
+| |  user:        hecht
+| |  date:        Thu Nov 29 07:42:05 2007 +0100
+| |  summary:     correct configure.ac for umfpack (sometime missng a library)
+| |
+o |  changeset:   1218:8c9df5beb3a7
+| |  user:        hecht
+| |  date:        Tue Nov 20 16:49:01 2007 +0100
+| |  summary:     correct missing tapping error in test build drawbdmesh on windows.
+| |
+o |  changeset:   1217:8855b0228166
+| |  user:        hecht
+| |  date:        Tue Nov 20 16:13:38 2007 +0100
+| |  summary:     correct bamg on windows missing drawbdmesh.exe
+| |
+o |  changeset:   1216:d6d35bd4d912
+| |  user:        hecht
+| |  date:        Tue Nov 20 15:38:21 2007 +0100
+| |  summary:     coorect   missing exe extension on bamg program in confure.ac
+| |
+o |  changeset:   1215:5140ecde974b
+| |  user:        hecht
+| |  date:        Mon Nov 19 21:40:06 2007 +0100
+| |  summary:     correct mpi for macos leopard,
+| |
+o |  changeset:   1214:c958ea8751f6
+| |  user:        hecht
+| |  date:        Mon Nov 19 18:13:44 2007 +0100
+| |  summary:     correct MPI configure.ac
+| |
+o |  changeset:   1213:5971ef36e8b0
+| |  user:        hecht
+| |  date:        Mon Nov 19 14:41:30 2007 +0100
+| |  summary:     continuing
+| |
+o |  changeset:   1212:1d04be51cbd3
+| |  user:        hecht
+| |  date:        Mon Nov 19 14:40:00 2007 +0100
+| |  summary:     missing mpiprog
+| |
+o |  changeset:   1211:87b998a26081
+| |  user:        hecht
+| |  date:        Mon Nov 19 14:25:04 2007 +0100
+| |  summary:     correct configure.ac missing FreeFem++ with X11
+| |
+o |  changeset:   1210:8b75110cb5a3
+| |  user:        hecht
+| |  date:        Mon Nov 19 14:17:36 2007 +0100
+| |  summary:     correct configure.ac without x11
+| |
+o |  changeset:   1209:311d084c2046
+| |  user:        hecht
+| |  date:        Sun Nov 18 13:20:22 2007 +0100
+| |  summary:     correct  documentation for new edition
+| |
+o |  changeset:   1208:24706bfcaeff
+| |  user:        hecht
+| |  date:        Tue Nov 13 16:40:14 2007 +0100
+| |  summary:     correct doc,
+| |
+o |  changeset:   1207:3d6e666c6d16
+| |  user:        hecht
+| |  date:        Wed Oct 24 22:17:06 2007 +0200
+| |  summary:     see INNOVATION file
+| |
+o |  changeset:   1206:7165e6427c0e
+| |  user:        hecht
+| |  date:        Mon Oct 22 18:17:22 2007 +0200
+| |  summary:     add format + - , trace and det of array
+| |
+o |  changeset:   1205:4389ca545f46
+| |  user:        hecht
+| |  date:        Tue Oct 02 17:55:05 2007 +0200
+| |  summary:     correct missing parameter SolveGCPrecon and SolveGCDiag
+| |
+o |  changeset:   1204:7c01e8973cec
+| |  user:        hecht
+| |  date:        Tue Oct 02 16:49:37 2007 +0200
+| |  summary:     correct miss-spelling
+| |
+o |  changeset:   1203:78037197ef80
+| |  user:        hecht
+| |  date:        Tue Oct 02 16:07:26 2007 +0200
+| |  summary:     -  add in download automatic generation of f2c and fort77 to get a free  fortran compiler
+| |
+o |  changeset:   1202:45e43ae71094
+| |  user:        hecht
+| |  date:        Sun Sep 30 17:45:11 2007 +0200
+| |  summary:     Add  sparse solver in documentation
+| |
+o |  changeset:   1201:05897868c18c
+| |  user:        hecht
+| |  date:        Thu Sep 20 21:53:50 2007 +0200
+| |  summary:     add SuperSolevr
+| |
+o |  changeset:   1200:9f9f13a8f113
+| |  user:        hecht
+| |  date:        Sun Sep 09 21:17:01 2007 +0200
+| |  summary:     add f2d in case of no fortran
+| |
+o |  changeset:   1199:61b84c52d78d
+| |  user:        hecht
+| |  date:        Fri Sep 07 17:09:59 2007 +0200
+| |  summary:     add f2c download
+| |
+o |  changeset:   1198:04efc3f5f54b
+| |  user:        hecht
+| |  date:        Fri Sep 07 00:13:17 2007 +0200
+| |  summary:     recorrect operator += Virtual matrix operator (introduction in august)
+| |
+o |  changeset:   1197:ff3f4337d5e3
+| |  user:        hecht
+| |  date:        Thu Sep 06 16:23:51 2007 +0200
+| |  summary:     correct SuperLU and UMFPACK driver + add comparaison
+| |
+o |  changeset:   1196:8ae57860389a
+| |  user:        hecht
+| |  date:        Thu Sep 06 16:02:24 2007 +0200
+| |  summary:     add missing files
+| |
+o |  changeset:   1195:647ecb3eea6f
+| |  user:        hecht
+| |  date:        Thu Sep 06 15:58:49 2007 +0200
+| |  summary:     correct 2 def defaulttoGMRES
+| |
+o |  changeset:   1194:18a530f69d84
+| |  user:        hecht
+| |  date:        Thu Sep 06 15:14:13 2007 +0200
+| |  summary:     correct tool to add other sparse (morse) linear solver with dynamic load
+| |
+o |  changeset:   1193:b90d965d48fd
+| |  user:        hecht
+| |  date:        Wed Sep 05 23:27:44 2007 +0200
+| |  summary:     add set sparce solver (morse)
+| |
+o |  changeset:   1192:4ce83180909c
+| |  user:        hecht
+| |  date:        Wed Sep 05 20:15:55 2007 +0200
+| |  summary:     correct complex part of superLU
+| |
+o |  changeset:   1191:041538d4cb5e
+| |  user:        hecht
+| |  date:        Wed Sep 05 18:03:29 2007 +0200
+| |  summary:     Add tools to change Sparce Linear Solver
+| |
+o |  changeset:   1190:6f6d00a9fca5
+| |  user:        hecht
+| |  date:        Tue Aug 28 21:57:58 2007 +0200
+| |  summary:     add N,M in class VirtualMatrix, to correct probleme in RNM class
+| |
+o |  changeset:   1189:a5a12103ca64
+| |  user:        hecht
+| |  date:        Tue Aug 28 17:16:21 2007 +0200
+| |  summary:     add missing oiperator in array:
+| |
+o |  changeset:   1188:92165ee42a24
+| |  user:        hecht
+| |  date:        Fri Aug 24 09:12:38 2007 +0200
+| |  summary:     update doc comtinuing
+| |
+o |  changeset:   1187:da3adb2cfcd8
+| |  user:        hecht
+| |  date:        Fri Aug 24 08:27:32 2007 +0200
+| |  summary:     update the doc.
+| |
+o |  changeset:   1186:c5b4f3e3c65d
+| |  user:        hecht
+| |  date:        Mon Aug 20 21:29:52 2007 +0200
+| |  summary:     add missing file
+| |
+o |  changeset:   1185:866ce6820edc
+| |  user:        hecht
+| |  date:        Mon Aug 20 21:28:18 2007 +0200
+| |  summary:     correct mean and jump operator in interpolation
+| |
+o |  changeset:   1184:ed49097a6267
+| |  user:        hecht
+| |  date:        Mon Aug 20 20:07:51 2007 +0200
+| |  summary:     upgrade INNOVATION
+| |
+o |  changeset:   1183:341e9039538a
+| |  user:        hecht
+| |  date:        Mon Aug 20 18:07:07 2007 +0200
+| |  summary:     correct,  problem of automatic ptr managenemt in plot::operator()
+| |
+o |  changeset:   1182:d10dd6069cd6
+| |  user:        hecht
+| |  date:        Sun Aug 19 22:05:05 2007 +0200
+| |  summary:     pass to version 2.19.
+| |
+o |  changeset:   1181:df0e5e08baf6
+| |  user:        hecht
+| |  date:        Tue Aug 07 22:05:59 2007 +0200
+| |  summary:     correct cin on windows and and type on bogus buildmesh.
+| |
+o |  changeset:   1180:72d9b455a3a7
+| |  user:        hecht
+| |  date:        Thu Jul 19 19:22:48 2007 +0200
+| |  summary:     correct AdaptResidualErrorIndicator and download/Makefile.am to
+| |
+o |  changeset:   1179:a0266c67c331
+| |  user:        hecht
+| |  date:        Thu Jul 19 13:19:01 2007 +0200
+| |  summary:     add missing compile file in example++-load
+| |
+o |  changeset:   1178:82f8d3d94641
+| |  user:        hecht
+| |  date:        Thu Jul 19 11:41:48 2007 +0200
+| |  summary:     see INNOVATION file, past version 2.18
+| |
+o |  changeset:   1177:df947a9d2fbc
+| |  user:        hecht
+| |  date:        Mon Jul 16 14:47:18 2007 +0200
+| |  summary:     add quantile
+| |
+o |  changeset:   1176:eb553aa35dea
+| |  user:        hecht
+| |  date:        Fri Jul 13 17:33:23 2007 +0200
+| |  summary:     add code  to sort  array
+| |
+o |  changeset:   1175:35694b19dc26
+| |  user:        hecht
+| |  date:        Fri Jun 29 22:21:50 2007 +0200
+| |  summary:     xcode projet
+| |
+o |  changeset:   1174:7ad52446d9f9
+| |  user:        hecht
+| |  date:        Thu Jun 28 22:12:20 2007 +0200
+| |  summary:     correct compile error with gcc 3.2.2  lgmat.cpp
+| |
+o |  changeset:   1173:868c291e09df
+| |  user:        hecht
+| |  date:        Thu Jun 21 07:58:39 2007 +0200
+| |  summary:     correct ../fflib/environment.hpp:41:24: warning: no newline at end of file
+| |
+o |  changeset:   1172:542424ec6260
+| |  user:        hecht
+| |  date:        Wed Jun 20 22:42:21 2007 +0200
+| |  summary:     correct bilapMorley.edp add missing term in var. formulation.
+| |
+o |  changeset:   1171:3b9e9a1daea3
+| |  user:        hecht
+| |  date:        Mon Jun 18 22:58:10 2007 +0200
+| |  summary:     set 2.17-2
+| |
+o |  changeset:   1170:0ea82558902f
+| |  user:        hecht
+| |  date:        Mon Jun 18 22:42:38 2007 +0200
+| |  summary:     add mesh example
+| |
+o |  changeset:   1169:17bd8f713142
+| |  user:        hecht
+| |  date:        Mon Jun 18 22:20:25 2007 +0200
+| |  summary:     correct old bug in bamg, in case of bogus boundary (auto crossing)
+| |
+o |  changeset:   1168:33fc210a3294
+| |  user:        hecht
+| |  date:        Fri Jun 15 13:39:12 2007 +0200
+| |  summary:     clean the example
+| |
+o |  changeset:   1167:d1c701a50c9b
+| |  user:        hecht
+| |  date:        Fri Jun 15 11:02:46 2007 +0200
+| |  summary:     correct FreeFem++-Cocoa to add option  -v 0
+| |
+o |  changeset:   1166:730dc114f01f
+| |  user:        hecht
+| |  date:        Fri Jun 15 10:01:07 2007 +0200
+| |  summary:     add missing files
+| |
+o |  changeset:   1165:ed08ef696a78
+| |  user:        hecht
+| |  date:        Fri Jun 15 09:33:06 2007 +0200
+| |  summary:     end of 2.17-1  modif
+| |
+o |  changeset:   1164:2b725188838d
+| |  user:        hecht
+| |  date:        Thu Jun 14 23:03:54 2007 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1163:26214451b1ab
+| |  user:        hecht
+| |  date:        Thu Jun 14 22:35:37 2007 +0200
+| |  summary:     next
+| |
+o |  changeset:   1162:fcc2dbd3a9ce
+| |  user:        hecht
+| |  date:        Thu Jun 14 21:49:13 2007 +0200
+| |  summary:     add -v xx on pc version
+| |
+o |  changeset:   1161:463a69ad8896
+| |  user:        hecht
+| |  date:        Thu Jun 14 11:54:03 2007 +0200
+| |  summary:     suite
+| |
+o |  changeset:   1160:5484bd790c1e
+| |  user:        hecht
+| |  date:        Thu Jun 14 10:27:06 2007 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1159:9e4f6868ccd9
+| |  user:        hecht
+| |  date:        Thu Jun 14 09:51:10 2007 +0200
+| |  summary:     clear output when verbosity = 0
+| |
+o |  changeset:   1158:1584e449a412
+| |  user:        hecht
+| |  date:        Mon Jun 11 15:37:51 2007 +0200
+| |  summary:     correct automatique choose of color in plot of arrow
+| |
+o |  changeset:   1157:45091926fd64
+| |  user:        hecht
+| |  date:        Sat Jun 09 12:15:24 2007 +0200
+| |  summary:     add boundary= ...  flag in plot fonction.
+| |
+o |  changeset:   1156:233789981ccc
+| |  user:        hecht
+| |  date:        Thu Jun 07 12:16:52 2007 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1155:fc6ca727714b
+| |  user:        hecht
+| |  date:        Thu Jun 07 12:15:23 2007 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1154:730ea632f37b
+| |  user:        hecht
+| |  date:        Thu Jun 07 11:52:53 2007 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1153:b2e2ef7ef138
+| |  user:        hecht
+| |  date:        Thu Jun 07 10:53:13 2007 +0200
+| |  summary:     correct mistake in tgamma call
+| |
+o |  changeset:   1152:aee96893dd95
+| |  user:        hecht
+| |  date:        Thu Jun 07 10:37:29 2007 +0200
+| |  summary:     correct missing update
+| |
+o |  changeset:   1151:22b1fb44a1fd
+| |  user:        hecht
+| |  date:        Thu Jun 07 08:17:18 2007 +0200
+| |  summary:     add bessel function   j0, j1, jn, y0, y1, yn -- bessel functions of first and second kind
+| |
+o |  changeset:   1150:c506c2721bc1
+| |  user:        hecht
+| |  date:        Tue Jun 05 18:02:43 2007 +0200
+| |  summary:     same for complex eigen value
+| |
+o |  changeset:   1149:0f0ac1c8239d
+| |  user:        hecht
+| |  date:        Tue Jun 05 17:44:32 2007 +0200
+| |  summary:     add rawvector= in eigenvector
+| |
+o |  changeset:   1148:4bc4aa832c8e
+| |  user:        hecht
+| |  date:        Mon Jun 04 23:03:52 2007 +0200
+| |  summary:     correct qforder= automatic choose in quadature formular in computation of integrale
+| |
+o |  changeset:   1147:f83647e00352
+| |  user:        hecht
+| |  date:        Wed May 16 00:21:37 2007 +0200
+| |  summary:     just add missing files
+| |
+o |  changeset:   1146:d26722df3ff7
+| |  user:        hecht
+| |  date:        Wed May 16 00:09:46 2007 +0200
+| |  summary:     correct  Makefile.am for  examples++-load/include  missing file
+| |
+o |  changeset:   1145:816c2b7c8609
+| |  user:        hecht
+| |  date:        Tue May 15 23:48:22 2007 +0200
+| |  summary:     do autoreconf
+| |
+o |  changeset:   1144:ec60d212a134
+| |  user:        hecht
+| |  date:        Tue May 15 22:01:55 2007 +0200
+| |  summary:     coorect mistake with libcblas
+| |
+o |  changeset:   1143:d110d5bbf588
+| |  user:        hecht
+| |  date:        Thu May 10 12:05:39 2007 +0200
+| |  summary:     correct very old bug in meshptg in case aligne point
+| |
+o |  changeset:   1142:be336c51a337
+| |  user:        hecht
+| |  date:        Thu May 03 10:36:34 2007 +0200
+| |  summary:     correct   Makefile.am dans examples++-load
+| |
+o |  changeset:   1141:c00cb936f998
+| |  user:        hecht
+| |  date:        Wed May 02 17:29:06 2007 +0200
+| |  summary:     - Add read sparce matrix form a file
+| |
+o |  changeset:   1140:f4d3b4252673
+| |  user:        hecht
+| |  date:        Wed Apr 25 09:28:12 2007 +0200
+| |  summary:     coorect splitmesh next step
+| |
+o |  changeset:   1139:650460b31c24
+| |  user:        hecht
+| |  date:        Tue Apr 24 22:20:08 2007 +0200
+| |  summary:     coorect meshsplit function
+| |
+o |  changeset:   1138:d4553b50a958
+| |  user:        hecht
+| |  date:        Tue Apr 24 17:18:50 2007 +0200
+| |  summary:     correct  the variable ff_testideprog="testhighlight${EXEEXT}"
+| |
+o |  changeset:   1137:2a10ec7ebf4a
+| |  user:        hecht
+| |  date:        Mon Apr 23 17:28:50 2007 +0200
+| |  summary:     remove  dump for debbuging in fem.cpp ( mesh() constructor  call splitmesh function)
+| |
+o |  changeset:   1136:db9bb253016b
+| |  user:        hecht
+| |  date:        Sat Apr 21 11:31:01 2007 +0200
+| |  summary:     correct miss speeling and fig ref/label
+| |
+o |  changeset:   1135:ba3a8c4bb929
+| |  user:        hecht
+| |  date:        Fri Apr 20 17:18:59 2007 +0200
+| |  summary:     remove  all compilation in ide dir if --without-fltk  configure flags is set.
+| |
+o |  changeset:   1134:627db69ed2c1
+| |  user:        hecht
+| |  date:        Fri Apr 20 16:01:30 2007 +0200
+| |  summary:     correct error when writing mesh, in case of different region (sub-domain)
+| |
+o |  changeset:   1133:b53c912f5521
+| |  user:        hecht
+| |  date:        Fri Apr 20 14:56:06 2007 +0200
+| |  summary:     do autoreconf
+| |
+o |  changeset:   1132:f7b143c68235
+| |  user:        hecht
+| |  date:        Fri Apr 20 14:54:29 2007 +0200
+| |  summary:     - correct mshptg.cpp  (add swap) , this is used in case of
+| |
+o |  changeset:   1131:8e5261645b5c
+| |  user:        hecht
+| |  date:        Wed Apr 18 12:01:45 2007 +0200
+| |  summary:     correct ligne pof Sun  SS -S vss in fem.cpp
+| |
+o |  changeset:   1130:0b47aaa265ed
+| |  user:        hecht
+| |  date:        Tue Apr 17 22:34:58 2007 +0200
+| |  summary:     same next
+| |
+o |  changeset:   1129:8abeb822514a
+| |  user:        hecht
+| |  date:        Tue Apr 17 22:27:49 2007 +0200
+| |  summary:     same continuing
+| |
+o |  changeset:   1128:b06140d1d045
+| |  user:        hecht
+| |  date:        Tue Apr 17 22:12:49 2007 +0200
+| |  summary:     correct fltk configure process on windows
+| |
+o |  changeset:   1127:bad3e707f5df
+| |  user:        hecht
+| |  date:        Tue Apr 17 21:47:31 2007 +0200
+| |  summary:     coorect mistake on  window akefile+ change fltk dowload install dir
+| |
+o |  changeset:   1126:84e2eb1e36b5
+| |  user:        hecht
+| |  date:        Tue Apr 17 12:52:28 2007 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1125:e25d8911cc1e
+| |  user:        hecht
+| |  date:        Tue Apr 17 12:51:00 2007 +0200
+| |  summary:     add file
+| |
+o |  changeset:   1124:8cf70de5de34
+| |  user:        hecht
+| |  date:        Tue Apr 17 12:08:26 2007 +0200
+| |  summary:     remove umfpack directory  form src
+| |
+o |  changeset:   1123:86e4e6640342
+| |  user:        hecht
+| |  date:        Fri Apr 06 17:42:55 2007 +0200
+| |  summary:     correct regularity, suite.
+| |
+o |  changeset:   1122:27f01e4f3b4e
+| |  user:        hecht
+| |  date:        Fri Apr 06 14:53:20 2007 +0200
+| |  summary:     regularity mistake, suite.
+| |
+o |  changeset:   1121:ad34308e20bc
+| |  user:        hecht
+| |  date:        Fri Apr 06 13:18:37 2007 +0200
+| |  summary:     correct impressin of mesh regularity
+| |
+o |  changeset:   1120:f1de13b4c5b0
+| |  user:        hecht
+| |  date:        Wed Apr 04 21:20:31 2007 +0200
+| |  summary:     go to version 2.15-1, see innovation file
+| |
+o |  changeset:   1119:436c75d9b870
+| |  user:        hecht
+| |  date:        Mon Apr 02 11:45:11 2007 +0200
+| |  summary:     correct examples++-tutorial/sparse-matrix.edp
+| |
+o |  changeset:   1118:3619a30b94c4
+| |  user:        hecht
+| |  date:        Mon Apr 02 11:36:31 2007 +0200
+| |  summary:     correct splitmesh with intenals bourdary
+| |
+o |  changeset:   1117:30af445f8cdb
+| |  user:        hecht
+| |  date:        Sun Mar 25 11:41:56 2007 +0200
+| |  summary:     correct bug in vectorial operation   (a+3.14*b)
+| |
+o |  changeset:   1116:89cb2da6046d
+| |  user:        hecht
+| |  date:        Thu Mar 22 12:01:50 2007 +0100
+| |  summary:     Correct  integration problem in varf of int1d(Th) .. u_Th1 .. v_Th2 ..
+| |
+o |  changeset:   1115:7f0e033977ed
+| |  user:        hecht
+| |  date:        Sun Mar 11 21:22:17 2007 +0100
+| |  summary:     correct licence hearder.
+| |
+o |  changeset:   1114:70758153bd21
+| |  user:        hecht
+| |  date:        Fri Mar 09 23:10:39 2007 +0100
+| |  summary:     correct missing speeling in  configure.ac  mpi++.h -> mpi++.h for mpich.1.2
+| |
+o |  changeset:   1113:fc8765cc14d9
+| |  user:        hecht
+| |  date:        Wed Mar 07 13:51:33 2007 +0100
+| |  summary:     see INNOVATION for detail.
+| |
+o |  changeset:   1112:52b479bdedc2
+| |  user:        hecht
+| |  date:        Wed Feb 14 21:00:18 2007 +0100
+| |  summary:     correct mistake in bluid matrice from  varf with  3 meshes
+| |
+o |  changeset:   1111:724be807f3f5
+| |  user:        hecht
+| |  date:        Sun Feb 04 12:19:57 2007 +0100
+| |  summary:     add scalar term in block matrix as 1x1 sub matrix.
+| |
+o |  changeset:   1110:c84d01a8cf8c
+| |  user:        hecht
+| |  date:        Sat Feb 03 15:17:19 2007 +0100
+| |  summary:     do autoreconf
+| |
+o |  changeset:   1109:1e4907ffb59e
+| |  user:        hecht
+| |  date:        Sat Feb 03 14:25:28 2007 +0100
+| |  summary:     pass to version 2.13  and
+| |
+o |  changeset:   1108:421db81aaa4c
+| |  user:        hecht
+| |  date:        Wed Jan 24 14:01:39 2007 +0100
+| |  summary:     correct  mistake in function
+| |
+o |  changeset:   1107:78da8acfecb9
+| |  user:        hecht
+| |  date:        Mon Jan 15 14:13:11 2007 +0100
+| |  summary:     correct when return a local new pointeur in freefem++ function
+| |
+o |  changeset:   1106:0a1b0afe3ade
+| |  user:        hecht
+| |  date:        Wed Jan 10 13:12:16 2007 +0100
+| |  summary:     add comment
+| |
+o |  changeset:   1105:07b62b54ccf4
+| |  user:        hecht
+| |  date:        Wed Jan 10 11:59:48 2007 +0100
+| |  summary:     pass to 2-12 et correct mistake in no square block matrix
+| |
+o |  changeset:   1104:6c1fa2e746bc
+| |  user:        hecht
+| |  date:        Fri Dec 22 13:33:09 2006 +0100
+| |  summary:     coorect missing spell in configure.ac  (ff_libs => ff_flibs) (fortran libs)
+| |
+o |  changeset:   1103:561eab096a22
+| |  user:        hecht
+| |  date:        Sun Dec 17 09:36:46 2006 +0100
+| |  summary:     change PPC in PP_C in problem.cpp, because PPC macro is defined
+| |
+o |  changeset:   1102:f87ec3ed5e67
+| |  user:        hecht
+| |  date:        Fri Dec 01 21:03:37 2006 +0100
+| |  summary:     coorect LaplaceRT.edp
+| |
+o |  changeset:   1101:e7de74fdbf14
+| |  user:        hecht
+| |  date:        Thu Nov 30 14:48:47 2006 +0100
+| |  summary:     correct dependance in  examples++-load/Makefile.am
+| |
+o |  changeset:   1100:ec4fde559d08
+| |  user:        hecht
+| |  date:        Thu Nov 30 14:45:17 2006 +0100
+| |  summary:     correct build matrices from varf with different mesh in case for mortar mesh.
+| |
+o |  changeset:   1099:77648a46d003
+| |  user:        hecht
+| |  date:        Tue Nov 28 13:53:02 2006 +0100
+| |  summary:     correct bug in interpolation  fespace Wf(Th,[RT0,P0]) function
+| |
+o |  changeset:   1098:7d480ffab837
+| |  user:        hecht
+| |  date:        Fri Nov 10 22:09:21 2006 +0100
+| |  summary:     I correct the problem in arpack (computation of eigen value) under i383 processor.
+| |
+o |  changeset:   1097:593603d24fae
+| |  user:        hecht
+| |  date:        Mon Nov 06 13:55:03 2006 +0100
+| |  summary:     correct -Wall continuing
+| |
+o |  changeset:   1096:07cd72f527a2
+| |  user:        hecht
+| |  date:        Mon Nov 06 09:55:57 2006 +0100
+| |  summary:     correct all -Wall warning,  to try to solve probleme in eigen value computation
+| |
+o |  changeset:   1095:be438995d8e4
+| |  tag:         release_2_10_2_before_Wall
+| |  user:        hecht
+| |  date:        Thu Oct 26 15:36:16 2006 +0200
+| |  summary:     remove debug  dump
+| |
+o |  changeset:   1094:b591f599d49c
+| |  user:        hecht
+| |  date:        Thu Oct 26 14:17:41 2006 +0200
+| |  summary:     correct mistake in configure
+| |
+o |  changeset:   1093:d6b64e445a74
+| |  user:        hecht
+| |  date:        Thu Oct 26 14:09:30 2006 +0200
+| |  summary:     correct error in lapack of arpack  (remove div  by 0)
+| |
+o |  changeset:   1092:3e64d9ef3137
+| |  user:        hecht
+| |  date:        Tue Oct 24 21:22:19 2006 +0200
+| |  summary:     add flags -with-lapack in configure
+| |
+o |  changeset:   1091:3b882c3a5cbc
+| |  user:        hecht
+| |  date:        Fri Oct 20 11:26:41 2006 +0200
+| |  summary:     add HIDDEN PARAMETER to fortran route with character parameters
+| |
+o |  changeset:   1090:15d919e17d54
+| |  user:        hecht
+| |  date:        Thu Oct 19 15:53:21 2006 +0200
+| |  summary:     coorect 70 in 70.
+| |
+o |  changeset:   1089:72ba19f26d06
+| |  user:        hecht
+| |  date:        Thu Oct 19 15:13:18 2006 +0200
+| |  summary:     misa a jour de README_CVS
+| |
+o |  changeset:   1088:7c13736478ae
+| |  user:        hecht
+| |  date:        Wed Oct 18 21:39:17 2006 +0200
+| |  summary:     ATTENTION le serveur CVS a change
+| |
+o |  changeset:   1087:69aece617a96
+| |  user:        hecht
+| |  date:        Wed Oct 18 21:28:11 2006 +0200
+| |  summary:     correct configure.ac for MacOs compile
+| |
+o |  changeset:   1086:c0904d3ddd12
+| |  user:        hecht
+| |  date:        Wed Oct 11 18:23:32 2006 +0200
+| |  summary:     change version 2.10-1
+| |
+o |  changeset:   1085:bfc0a8074e1e
+| |  user:        hecht
+| |  date:        Tue Oct 10 20:48:02 2006 +0200
+| |  summary:     add modif in the doc
+| |
+o |  changeset:   1084:388005cc5029
+| |  user:        hecht
+| |  date:        Tue Oct 10 17:42:15 2006 +0200
+| |  summary:     QF continuing
+| |
+o |  changeset:   1083:7276e657cb50
+| |  user:        hecht
+| |  date:        Tue Oct 10 17:35:27 2006 +0200
+| |  summary:     add QF gauss Legendre  4 and 5 points
+| |
+o |  changeset:   1082:b23f3adc267f
+| |  user:        hecht
+| |  date:        Fri Sep 29 22:30:15 2006 +0200
+| |  summary:     change in all source file the LGPL flags. (FH)
+| |
+o |  changeset:   1081:f945df94b59a
+| |  user:        hecht
+| |  date:        Wed Sep 20 10:23:07 2006 +0200
+| |  summary:     correct tool with crimson editor under Windows
+| |
+o |  changeset:   1080:586e679e834b
+| |  user:        hecht
+| |  date:        Wed Sep 20 10:19:13 2006 +0200
+| |  summary:     coorect comment on crimson editor
+| |
+o |  changeset:   1079:ee0cfa566d11
+| |  user:        hecht
+| |  date:        Tue Sep 19 22:08:51 2006 +0200
+| |  summary:     bluid HISTORY files
+| |
+o |  changeset:   1078:b224a55c4a5c
+| |  user:        hecht
+| |  date:        Tue Sep 19 21:36:43 2006 +0200
+| |  summary:     correct openmpi trouble (async communication)
+| |
+o |  changeset:   1077:11c495eb71a5
+| |  user:        hecht
+| |  date:        Tue Sep 19 17:07:07 2006 +0200
+| |  summary:     update INNIVATION
+| |
+o |  changeset:   1076:a03f49afc8f3
+| |  user:        hecht
+| |  date:        Tue Sep 19 16:24:13 2006 +0200
+| |  summary:     change include.tar.gz file
+| |
+o |  changeset:   1075:0c543fd2904e
+| |  user:        hecht
+| |  date:        Tue Sep 19 16:02:29 2006 +0200
+| |  summary:     add format output routine
+| |
+o |  changeset:   1074:5f55497120c9
+| |  user:        hecht
+| |  date:        Tue Sep 19 11:47:20 2006 +0200
+| |  summary:     correct configure.ac
+| |
+o |  changeset:   1073:e174a3df647c
+| |  user:        hecht
+| |  date:        Mon Sep 18 17:41:24 2006 +0200
+| |  summary:     change under  windows OS  the installed files
+| |
+o |  changeset:   1072:3c866007d12c
+| |  user:        hecht
+| |  date:        Fri Jul 21 18:35:12 2006 +0200
+| |  summary:     passe to version  2.8-2
+| |
+o |  changeset:   1071:11a7f799060e
+| |  user:        hecht
+| |  date:        Fri Jul 21 17:02:18 2006 +0200
+| |  summary:     correct bug with mpi (MPICH-2)
+| |
+o |  changeset:   1070:67582bf9db8d
+| |  user:        hecht
+| |  date:        Fri Jun 30 11:16:30 2006 +0200
+| |  summary:     add print in arpack error
+| |
+o |  changeset:   1069:9d5182230173
+| |  user:        hecht
+| |  date:        Wed Jun 28 18:01:28 2006 +0200
+| |  summary:     add missing file in make dist process
+| |
+o |  changeset:   1068:7ac9ef62d6ea
+| |  user:        hecht
+| |  date:        Wed Jun 28 17:50:29 2006 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   1067:7a7da3aac6d0
+| |  user:        hecht
+| |  date:        Wed Jun 28 17:49:40 2006 +0200
+| |  summary:     add missing file
+| |
+o |  changeset:   1066:e8c85aa01607
+| |  user:        hecht
+| |  date:        Wed Jun 28 17:46:39 2006 +0200
+| |  summary:     add tool to remove cadna in ./configure -without-cadna
+| |
+o |  changeset:   1065:1cdc9b656cbd
+| |  user:        hecht
+| |  date:        Tue Jun 27 23:24:41 2006 +0200
+| |  summary:     do  correction for  openmpi but the
+| |
+o |  changeset:   1064:2a1df2d56b69
+| |  user:        hecht
+| |  date:        Tue Jun 27 23:14:28 2006 +0200
+| |  summary:     version 2.6-1
+| |
+o |  changeset:   1063:83aaaf11d8e4
+| |  user:        hecht
+| |  date:        Fri Jun 16 16:04:45 2006 +0200
+| |  summary:     correct doc netx step.
+| |
+o |  changeset:   1062:c9d7a4cbb447
+| |  user:        hecht
+| |  date:        Fri Jun 16 13:49:56 2006 +0200
+| |  summary:     coorect lame.edp in chap 3 of the doc.
+| |
+o |  changeset:   1061:63490a1bc9e2
+| |  user:        hecht
+| |  date:        Mon Jun 12 21:15:22 2006 +0200
+| |  summary:     add correction from  christophe.trophime at grenoble.cnrs.fr
+| |
+o |  changeset:   1060:56035a847644
+| |  user:        hecht
+| |  date:        Thu Jun 01 09:28:29 2006 +0200
+| |  summary:     add h flag to: Don't write symlinks as symlinks; write the data of the files
+| |
+o |  changeset:   1059:c34152d230f8
+| |  user:        hecht
+| |  date:        Tue May 30 15:37:52 2006 +0200
+| |  summary:     correct OpenGL flag under MacOS configure.ac
+| |
+o |  changeset:   1058:fa234b7279ba
+| |  user:        hecht
+| |  date:        Fri May 26 16:57:12 2006 +0200
+| |  summary:     correct FLIBS in configure.ac
+| |
+o |  changeset:   1057:9f5e47d47b0b
+| |  user:        hecht
+| |  date:        Wed May 24 22:25:02 2006 +0200
+| |  summary:     correct configure.ac
+| |
+o |  changeset:   1056:ee44b7d37064
+| |  user:        hecht
+| |  date:        Fri May 19 19:53:09 2006 +0200
+| |  summary:     cleanning FLIBS configure variable in case of g77
+| |
+o |  changeset:   1055:7d8c1d27e6a5
+| |  user:        hecht
+| |  date:        Thu May 18 16:48:17 2006 +0200
+| |  summary:     correct small error for New macOS install
+| |
+o |  changeset:   1054:d3077251497e
+| |  user:        hecht
+| |  date:        Thu May 18 14:04:09 2006 +0200
+| |  summary:     correct for lam mpi
+| |
+o |  changeset:   1053:a5ae3f5ad14a
+| |  user:        hecht
+| |  date:        Thu May 18 13:59:15 2006 +0200
+| |  summary:     add missing file
+| |
+o |  changeset:   1052:271e5d7d4887
+| |  user:        hecht
+| |  date:        Thu May 18 13:57:25 2006 +0200
+| |  summary:     correct INNOVATION
+| |
+o |  changeset:   1051:689c1b6bc221
+| |  user:        hecht
+| |  date:        Thu May 18 13:51:17 2006 +0200
+| |  summary:     Correct bug in case of vectorial problem with same FE space.
+| |
+o |  changeset:   1050:2d93d1eb482c
+| |  user:        hecht
+| |  date:        Wed May 17 15:35:19 2006 +0200
+| |  summary:     add missing file in distribution
+| |
+o |  changeset:   1049:a35c824f162c
+| |  user:        hecht
+| |  date:        Tue May 16 15:09:18 2006 +0200
+| |  summary:     remove missing speel in configure.ac
+| |
+o |  changeset:   1048:31194b511eee
+| |  user:        hecht
+| |  date:        Tue May 16 15:00:12 2006 +0200
+| |  summary:     try to correct X11 link problem on Linux 64bits architecture
+| |
+o |  changeset:   1047:669f743b8424
+| |  user:        hecht
+| |  date:        Mon May 15 20:01:01 2006 +0200
+| |  summary:     correct pb on 64bits achitecture in file src/fflib/AnyType.hpp
+| |
+o |  changeset:   1046:5c045c7b0278
+| |  user:        hecht
+| |  date:        Fri May 05 22:55:05 2006 +0200
+| |  summary:     do correction geometric data base with RequiredEdge.
+| |
+o |  changeset:   1045:240f50061d02
+| |  user:        hecht
+| |  date:        Wed Apr 26 14:15:13 2006 +0200
+| |  summary:     correct configure.ac :
+| |
+o |  changeset:   1044:68823e1bad2c
+| |  user:        hecht
+| |  date:        Sat Apr 15 18:05:11 2006 +0200
+| |  summary:     correct missing spellibg  line 920
+| |
+o |  changeset:   1043:a57bd667419c
+| |  user:        hecht
+| |  date:        Sat Apr 15 12:00:58 2006 +0200
+| |  summary:     correct probele when compioling with g++ 3.2
+| |
+o |  changeset:   1042:6d6e6646b914
+| |  user:        hecht
+| |  date:        Thu Apr 13 18:36:42 2006 +0200
+| |  summary:     correct the mpi version for macos lam mpi
+| |
+o |  changeset:   1041:4c5e3347dc7a
+| |  user:        hecht
+| |  date:        Thu Apr 13 13:39:58 2006 +0200
+| |  summary:     pass to version 2.7 and correct missing file in mpi Makefile.am
+| |
+o |  changeset:   1040:b08ffa6fe703
+| |  user:        hecht
+| |  date:        Thu Apr 13 10:27:20 2006 +0200
+| |  summary:     coorect misstake in rc/femlib/FESpace.cpp
+| |
+o |  changeset:   1039:2cad75a9fee1
+| |  user:        hecht
+| |  date:        Thu Apr 13 08:37:40 2006 +0200
+| |  summary:     correct trouble  in Boundary condition  when we mixte some
+| |
+o |  changeset:   1038:9c495e402881
+| |  user:        hecht
+| |  date:        Wed Apr 12 14:03:02 2006 +0200
+| |  summary:     remove check suffix .edp to be compatible with drawbdmesh.exe
+| |
+o |  changeset:   1037:e763b1a14153
+| |  user:        hecht
+| |  date:        Wed Apr 12 12:59:38 2006 +0200
+| |  summary:     add line un INNOTAVION
+| |
+o |  changeset:   1036:56eae42c7434
+| |  user:        hecht
+| |  date:        Wed Apr 12 11:31:03 2006 +0200
+| |  summary:     add bamg example an correct problem beetween bamg and freefem graphic
+| |
+o |  changeset:   1035:5a7b04e99f63
+| |  user:        hecht
+| |  date:        Wed Apr 12 07:38:59 2006 +0200
+| |  summary:     correct load.link under windows with new list of .dll files.
+| |
+o |  changeset:   1034:9b67a868ae97
+| |  user:        hecht
+| |  date:        Tue Apr 11 23:26:57 2006 +0200
+| |  summary:     correct load.link script (change list of ff++ dll)
+| |
+o |  changeset:   1033:705dfea6c6f4
+| |  user:        hecht
+| |  date:        Tue Apr 11 22:06:44 2006 +0200
+| |  summary:     Now the all.edp of tutorial run under winder (very hard word). FH
+| |
+o |  changeset:   1032:2baa47074ee1
+| |  user:        hecht
+| |  date:        Tue Apr 11 21:57:50 2006 +0200
+| |  summary:     correct bug under window in Mesh:Find (very rare)
+| |
+o |  changeset:   1031:6c3bf2dfe726
+| |  user:        hecht
+| |  date:        Tue Apr 11 13:52:41 2006 +0200
+| |  summary:     change for window free/delete pair
+| |
+o |  changeset:   1030:3c1196a7980c
+| |  user:        hecht
+| |  date:        Tue Apr 11 10:46:39 2006 +0200
+| |  summary:     the new version of the dll file begin to work on windows (no trap in alloction)
+| |
+o |  changeset:   1029:4e24126f9014
+| |  user:        hecht
+| |  date:        Mon Apr 10 22:53:34 2006 +0200
+| |  summary:     next.
+| |
+o |  changeset:   1028:a15790716999
+| |  user:        hecht
+| |  date:        Mon Apr 10 22:51:52 2006 +0200
+| |  summary:     dur dur Windows, 
+| |
+o |  changeset:   1027:254d30ab0f69
+| |  user:        hecht
+| |  date:        Mon Apr 10 06:59:46 2006 +0200
+| |  summary:     continuing malloc/free for window
+| |
+o |  changeset:   1026:a5c82bb112b0
+| |  user:        hecht
+| |  date:        Sun Apr 09 22:19:13 2006 +0200
+| |  summary:     suite??
+| |
+o |  changeset:   1025:5a8765108bc6
+| |  user:        hecht
+| |  date:        Sun Apr 09 21:50:04 2006 +0200
+| |  summary:     suite, ..
+| |
+o |  changeset:   1024:ef63561dbb98
+| |  user:        hecht
+| |  date:        Sun Apr 09 20:56:27 2006 +0200
+| |  summary:     in progress malloc/free ??
+| |
+o |  changeset:   1023:7c8d3752a8c5
+| |  user:        hecht
+| |  date:        Sun Apr 09 20:38:50 2006 +0200
+| |  summary:     try find pair of malloc /free for windows .dll
+| |
+o |  changeset:   1022:d0b18f8d6670
+| |  user:        hecht
+| |  date:        Sun Apr 09 18:13:49 2006 +0200
+| |  summary:     make change for  windows dll because the pair malloc and free
+| |
+o |  changeset:   1021:d76874c0f85f
+| |  user:        hecht
+| |  date:        Fri Apr 07 08:38:09 2006 +0200
+| |  summary:     correct missing delete pointeur in a=vmass(0,Vh); where vmass in a varf
+| |
+o |  changeset:   1020:02ee34e0fedd
+| |  user:        hecht
+| |  date:        Fri Apr 07 08:35:18 2006 +0200
+| |  summary:     CheckPtr add flag when deleting  after cleanning
+| |
+o |  changeset:   1019:f22016768b22
+| |  user:        hecht
+| |  date:        Thu Apr 06 18:19:09 2006 +0200
+| |  summary:     remove impression
+| |
+o |  changeset:   1018:eea8603b5314
+| |  user:        hecht
+| |  date:        Thu Apr 06 16:59:16 2006 +0200
+| |  summary:     add cfloat include
+| |
+o |  changeset:   1017:c31a741e4f51
+| |  user:        hecht
+| |  date:        Thu Apr 06 16:53:29 2006 +0200
+| |  summary:     add missing include climits in src/femlib/fem.cpp
+| |
+o |  changeset:   1016:c8c3fd920434
+| |  user:        hecht
+| |  date:        Thu Apr 06 16:49:04 2006 +0200
+| |  summary:     correct mistake in interpolation procedure, (in Mesh::Find methode)
+| |
+o |  changeset:   1015:20172ab21d1e
+| |  user:        hecht
+| |  date:        Tue Apr 04 23:31:14 2006 +0200
+| |  summary:     correct bug in freeboundary;edp (trap on  windows some time )
+| |
+o |  changeset:   1014:d2487f969c54
+| |  user:        hecht
+| |  date:        Tue Apr 04 11:25:56 2006 +0200
+| |  summary:     coorect consistance beetween movmesh and checkmovemesh
+| |
+o |  changeset:   1013:a8b6b14521b4
+| |  user:        hecht
+| |  date:        Tue Apr 04 09:11:39 2006 +0200
+| |  summary:     add CR  at end of file src/fflib/ffstack.hpp
+| |
+o |  changeset:   1012:4f0626a95678
+| |  user:        hecht
+| |  date:        Mon Apr 03 22:39:59 2006 +0200
+| |  summary:     correct misspelling
+| |
+o |  changeset:   1011:a4f1420b9b02
+| |  user:        hecht
+| |  date:        Mon Apr 03 22:11:53 2006 +0200
+| |  summary:     pass to 2.5-1
+| |
+o |  changeset:   1010:dd65ef6ffe6a
+| |  user:        hecht
+| |  date:        Mon Apr 03 22:09:30 2006 +0200
+| |  summary:     correct randon error on window
+| |
+o |  changeset:   1009:17557d78d867
+| |  user:        hecht
+| |  date:        Sun Apr 02 21:59:22 2006 +0200
+| |  summary:     add bamg.exe, cvmsh2.exe and drawbdmesh.exe in  Inno setup package
+| |
+o |  changeset:   1008:3c9f1d10e3fa
+| |  user:        hecht
+| |  date:        Sun Apr 02 21:53:41 2006 +0200
+| |  summary:     and bamg and string_def.o files
+| |
+o |  changeset:   1007:41d7de398a7a
+| |  user:        hecht
+| |  date:        Sat Apr 01 17:41:34 2006 +0200
+| |  summary:     add new example  AdaptResidualErrorIndicator in the doc
+| |
+o |  changeset:   1006:33c7dcaed492
+| |  user:        hecht
+| |  date:        Fri Mar 31 23:15:22 2006 +0200
+| |  summary:     add ResidualErrorIndicor example
+| |
+o |  changeset:   1005:c50260b490c6
+| |  user:        hecht
+| |  date:        Fri Mar 31 20:41:41 2006 +0200
+| |  summary:     add 2 files
+| |
+o |  changeset:   1004:0a924b0705c0
+| |  user:        hecht
+| |  date:        Fri Mar 31 18:26:21 2006 +0200
+| |  summary:     add string method and correct bug une string parameter.
+| |
+o |  changeset:   1003:6d7e5f19e5d2
+| |  user:        hecht
+| |  date:        Thu Mar 30 08:50:11 2006 +0200
+| |  summary:     some optimization on new auto free ptr.
+| |
+o |  changeset:   1002:ccabf7cb7fc8
+| |  user:        hecht
+| |  date:        Wed Mar 29 19:29:33 2006 +0200
+| |  summary:     add missing clear language ptr in while and for loops.
+| |
+o |  changeset:   1001:b6f1f5a20727
+| |  user:        hecht
+| |  date:        Wed Mar 29 14:49:33 2006 +0200
+| |  summary:     pass to version 2.5-0
+| |
+o |  changeset:   1000:05c49f7d003b
+| |  user:        hecht
+| |  date:        Wed Mar 29 14:47:52 2006 +0200
+| |  summary:     *  add automatic gestion of free language pointeur to correct
+| |
+o |  changeset:   999:fc85bf0ec864
+| |  tag:         release_2_4_3
+| |  user:        hecht
+| |  date:        Mon Mar 27 23:21:48 2006 +0200
+| |  summary:     add mode for mo text editor on MacOs see the freefem++-doc.pdf for full detail
+| |
+o |  changeset:   998:2fc2e01af985
+| |  user:        hecht
+| |  date:        Mon Mar 27 22:34:13 2006 +0200
+| |  summary:     add freefem++  mode for mi editor on macos http://www.mimikaki.net/en/
+| |
+o |  changeset:   997:a7c4994c838c
+| |  user:        hecht
+| |  date:        Mon Mar 27 21:25:40 2006 +0200
+| |  summary:     * add lot missing vectorial operation with sub array
+| |
+o |  changeset:   996:2a1d5b8a2972
+| |  user:        hecht
+| |  date:        Mon Mar 20 18:10:38 2006 +0100
+| |  summary:     add init of array with a linear form.
+| |
+o |  changeset:   995:8286c03feec4
+| |  user:        hecht
+| |  date:        Fri Mar 17 23:18:34 2006 +0100
+| |  summary:     add missing operator on sub array (type KN_<R>)
+| |
+o |  changeset:   994:4d77a303b202
+| |  user:        hecht
+| |  date:        Fri Mar 17 10:45:16 2006 +0100
+| |  summary:     add new operator on complex array to get real or imag part
+| |
+o |  changeset:   993:a10bc8411406
+| |  user:        hecht
+| |  date:        Fri Mar 17 07:36:20 2006 +0100
+| |  summary:     add   x=exp(y);  when x,y are array  for exp;log,sin,tan , ....
+| |
+o |  changeset:   992:2900e40c201d
+| |  user:        hecht
+| |  date:        Thu Mar 16 11:40:10 2006 +0100
+| |  summary:     add new kind on interplate matrix
+| |
+o |  changeset:   991:45069205c1fe
+| |  user:        hecht
+| |  date:        Mon Mar 13 14:40:55 2006 +0100
+| |  summary:     correct freefem-doc.tex until page 29 example 6.
+| |
+o |  changeset:   990:83997a02688c
+| |  user:        hecht
+| |  date:        Sun Mar 12 12:10:39 2006 +0100
+| |  summary:     do autoreconf
+| |
+o |  changeset:   989:29e852c9228c
+| |  user:        hecht
+| |  date:        Sun Mar 12 10:47:07 2006 +0100
+| |  summary:     change version number
+| |
+o |  changeset:   988:248eeefa3fb8
+| |  user:        hecht
+| |  date:        Sat Mar 11 18:47:41 2006 +0100
+| |  summary:     array of matrix work now.
+| |
+o |  changeset:   987:88eabcc9bac4
+| |  user:        hecht
+| |  date:        Sat Mar 11 09:45:02 2006 +0100
+| |  summary:     correct error in build array of sparce matrix.
+| |
+o |  changeset:   986:28000cfb291d
+| |  user:        hecht
+| |  date:        Fri Mar 10 18:35:23 2006 +0100
+| |  summary:     pl with matrix arry -> remove
+| |
+o |  changeset:   985:c4d7606f1b7c
+| |  user:        hecht
+| |  date:        Fri Mar 10 17:46:28 2006 +0100
+| |  summary:     make big change in the DOC with O. Kavian
+| |
+o |  changeset:   984:0c0790f9714e
+| |  user:        hecht
+| |  date:        Tue Mar 07 20:10:30 2006 +0100
+| |  summary:     tag release_2_4
+| |
+o |  changeset:   983:260fea6042e2
+| |  tag:         release_2_4
+| |  user:        hecht
+| |  date:        Tue Mar 07 20:05:46 2006 +0100
+| |  summary:     pass to  to version 2.4.0
+| |
+o |  changeset:   982:1063ba890e3c
+| |  user:        hecht
+| |  date:        Tue Mar 07 17:49:56 2006 +0100
+| |  summary:     same as previous commit (just on the top dir)
+| |
+o |  changeset:   981:14a915d04752
+| |  user:        hecht
+| |  date:        Tue Mar 07 17:48:47 2006 +0100
+| |  summary:     add new operator outer product, change the doc, ....
+| |
+o |  changeset:   980:796f9d95bf8a
+| |  user:        hecht
+| |  date:        Fri Mar 03 23:29:06 2006 +0100
+| |  summary:     add matric operator like in matlab  mat(I,J) where I,J are
+| |
+o |  changeset:   979:06e185f16d44
+| |  user:        hecht
+| |  date:        Fri Mar 03 13:21:39 2006 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   978:c3cf679cbfe9
+| |  user:        hecht
+| |  date:        Fri Mar 03 13:15:15 2006 +0100
+| |  summary:     add an exemple with 1D lagrange multiplier.
+| |
+o |  changeset:   977:bbe075e51532
+| |  user:        hecht
+| |  date:        Wed Mar 01 23:15:55 2006 +0100
+| |  summary:     add out product of 2 vectors  to build full matrix
+| |
+o |  changeset:   976:049d52a39d27
+| |  user:        lehyaric
+| |  date:        Tue Feb 28 10:18:03 2006 +0100
+| |  summary:     Debian packaging for version 2.3-2
+| |
+o |  changeset:   975:b0579ae35da0
+| |  user:        hecht
+| |  date:        Wed Feb 22 18:12:33 2006 +0100
+| |  summary:     correct exec on PC
+| |
+o |  changeset:   974:1a6c2c83fa7a
+| |  user:        hecht
+| |  date:        Tue Feb 21 15:08:22 2006 +0100
+| |  summary:     tag release_2_3_2
+| |
+o |  changeset:   973:5036f8596f19
+| |  tag:         release_2_3_2
+| |  user:        hecht
+| |  date:        Mon Feb 20 18:15:56 2006 +0100
+| |  summary:     Correct missing sub domain problem when
+| |
+o |  changeset:   972:2d1acc85e77e
+| |  user:        lehyaric
+| |  date:        Fri Feb 10 10:41:17 2006 +0100
+| |  summary:     Improved "make clean", which did not seem to be cleaning correctly anymore.
+| |
+o |  changeset:   971:4a048322f1ac
+| |  user:        hecht
+| |  date:        Thu Feb 09 16:32:06 2006 +0100
+| |  summary:     add configure examples un README files
+| |
+o |  changeset:   970:8853516f2694
+| |  user:        hecht
+| |  date:        Thu Feb 09 15:11:50 2006 +0100
+| |  summary:     correct miss spelling, and error in configure.ac
+| |
+o |  changeset:   969:d3384dd2cf15
+| |  user:        hecht
+| |  date:        Tue Feb 07 21:32:36 2006 +0100
+| |  summary:     reglage in the doc,
+| |
+o |  changeset:   968:5512562ea7e2
+| |  user:        hecht
+| |  date:        Tue Feb 07 20:25:58 2006 +0100
+| |  summary:     add new example
+| |
+o |  changeset:   967:87d1748924cd
+| |  user:        hecht
+| |  date:        Tue Feb 07 20:25:25 2006 +0100
+| |  summary:     Correct missing free   memory in case of  exception in problem.
+| |
+o |  changeset:   966:d72debe05e74
+| |  user:        hecht
+| |  date:        Fri Feb 03 16:18:46 2006 +0100
+| |  summary:     add exception in freefem++ language, the first test is working
+| |
+o |  changeset:   965:646090715f8a
+| |  user:        hecht
+| |  date:        Fri Jan 27 22:47:48 2006 +0100
+| |  summary:     add conf flag in README_WINDOWS
+| |
+o |  changeset:   964:c396c1d7a8ff
+| |  user:        hecht
+| |  date:        Fri Jan 27 22:33:41 2006 +0100
+| |  summary:     correct missing bluid of  lapack in ARPACK if no lapack
+| |
+o |  changeset:   963:09bf146e6970
+| |  user:        hecht
+| |  date:        Fri Jan 27 21:07:55 2006 +0100
+| |  summary:     correct missing include and link order under pure win32 architecture.
+| |
+o |  changeset:   962:8167e2ba058c
+| |  user:        hecht
+| |  date:        Fri Jan 27 18:24:30 2006 +0100
+| |  summary:     correct PB optim on G4
+| |
+o |  changeset:   961:10303c0ceeac
+| |  user:        hecht
+| |  date:        Fri Jan 27 16:43:49 2006 +0100
+| |  summary:     correct PB optim on G5
+| |
+o |  changeset:   960:f0af0d499a0e
+| |  user:        hecht
+| |  date:        Fri Jan 27 15:59:08 2006 +0100
+| |  summary:     correct pb in configure to find wget or curl for download
+| |
+o |  changeset:   959:27b51c168d7d
+| |  user:        hecht
+| |  date:        Fri Jan 27 13:57:18 2006 +0100
+| |  summary:     remove highlight test is no ide
+| |
+o |  changeset:   958:7a51becb5c7c
+| |  user:        hecht
+| |  date:        Fri Jan 27 11:33:28 2006 +0100
+| |  summary:     correct pb in installing apple version (zcat -> gunzip -c)
+| |
+o |  changeset:   957:f8c6b851cd72
+| |  user:        hecht
+| |  date:        Fri Jan 27 10:58:21 2006 +0100
+| |  summary:     take account of mac intel
+| |
+o |  changeset:   956:a3ac2888e73b
+| |  user:        hecht
+| |  date:        Thu Jan 26 10:16:47 2006 +0100
+| |  summary:     add comment in configure.ac
+| |
+o |  changeset:   955:5b4eee4361a3
+| |  user:        hecht
+| |  date:        Mon Jan 23 22:13:34 2006 +0100
+| |  summary:     correct small problem in configure.ac to build freefem on mac intel
+| |
+o |  changeset:   954:2b768b55bef2
+| |  user:        hecht
+| |  date:        Wed Jan 11 22:22:32 2006 +0100
+| |  summary:     correct xcode projet + warning
+| |
+o |  changeset:   953:892542425842
+| |  user:        hecht
+| |  date:        Wed Jan 11 21:13:09 2006 +0100
+| |  summary:     add xcode 2.2 build project for macos (see README_XCODE)
+| |
+o |  changeset:   952:a3feaa34b941
+| |  user:        hecht
+| |  date:        Mon Jan 09 15:42:41 2006 +0100
+| |  summary:     small correct to use xcode of macos and to build bamg shell command
+| |
+o |  changeset:   951:a4bcb6afa861
+| |  user:        lehyaric
+| |  date:        Fri Jan 06 11:28:38 2006 +0100
+| |  summary:     Changed ARPACK library reference for static compiling
+| |
+o |  changeset:   950:f4a233463d32
+| |  user:        lehyaric
+| |  date:        Fri Jan 06 10:51:44 2006 +0100
+| |  summary:     Changed Debian packages documentation format from PS to PDF to reflect
+| |
+o |  changeset:   949:1ae1db6e007a
+| |  user:        hecht
+| |  date:        Fri Jan 06 10:00:32 2006 +0100
+| |  summary:     add building of bamg and cvsmsh2 command
+| |
+o |  changeset:   948:2203e08d58df
+| |  user:        hecht
+| |  date:        Thu Jan 05 15:43:34 2006 +0100
+| |  summary:     merging the source of bamg and the the bamg freefem++ part
+| |
+o |  changeset:   947:a9d0713b4381
+| |  user:        hecht
+| |  date:        Wed Jan 04 11:37:34 2006 +0100
+| |  summary:     add read bamg geometry file with buildmesh function.
+| |
+o |  changeset:   946:51f2fa717070
+| |  user:        hecht
+| |  date:        Wed Jan 04 11:27:06 2006 +0100
+| |  summary:     add build mesh from bamg geometry
+| |
+o |  changeset:   945:71e91a1c79b1
+| |  user:        lehyaric
+| |  date:        Wed Jan 04 10:18:26 2006 +0100
+| |  summary:     New Debian package.
+| |
+o |  changeset:   944:24ff5d45228e
+| |  user:        hecht
+| |  date:        Fri Dec 30 21:13:41 2005 +0100
+| |  summary:     add forget file distribution
+| |
+o |  changeset:   943:23e9c0f0a896
+| |  user:        hecht
+| |  date:        Fri Dec 30 15:37:14 2005 +0100
+| |  summary:     correct pb under Windows change environment to ffenvironment (Global variable)
+| |
+o |  changeset:   942:d3e15f0496c5
+| |  user:        hecht
+| |  date:        Fri Dec 30 12:23:06 2005 +0100
+| |  summary:     pb global.cpp
+| |
+o |  changeset:   941:893de561be72
+| |  user:        hecht
+| |  date:        Fri Dec 30 12:02:47 2005 +0100
+| |  summary:     correct compile error
+| |
+o |  changeset:   940:8e45bd25850f
+| |  user:        hecht
+| |  date:        Fri Dec 30 11:53:15 2005 +0100
+| |  summary:     correct pb uneder Windows with environment, put the def in Global.cpp
+| |
+o |  changeset:   939:fe79bc21aee6
+| |  user:        hecht
+| |  date:        Fri Dec 30 10:57:24 2005 +0100
+| |  summary:     The search directory of  load and include seems ok.
+| |
+o |  changeset:   938:dd01c3dcc4cf
+| |  user:        hecht
+| |  date:        Fri Dec 30 08:34:34 2005 +0100
+| |  summary:     correct environment.cpp under Windows (Pure) and add to bin-win32/Makefile
+| |
+o |  changeset:   937:6eaa175ac89e
+| |  user:        hecht
+| |  date:        Thu Dec 29 17:30:49 2005 +0100
+| |  summary:     add 3 environments varialbe FF_VERBOSITY, FF_INCLUDEPATH, FF_LOADPATH
+| |
+o |  changeset:   936:ab89a4c85ef9
+| |  user:        hecht
+| |  date:        Thu Dec 29 08:00:51 2005 +0100
+| |  summary:     reman NSP1BR.edp in NSP2BRP0.edp
+| |
+o |  changeset:   935:a0a4be528978
+| |  user:        hecht
+| |  date:        Thu Dec 29 07:59:09 2005 +0100
+| |  summary:     correct load.link (return compile compile error).
+| |
+o |  changeset:   934:299e4f9ebabb
+| |  user:        hecht
+| |  date:        Thu Dec 29 07:46:23 2005 +0100
+| |  summary:     add missing files
+| |
+o |  changeset:   933:f07b38bd1772
+| |  user:        hecht
+| |  date:        Wed Dec 28 15:00:04 2005 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   932:ae8b837389cf
+| |  user:        hecht
+| |  date:        Wed Dec 28 14:49:11 2005 +0100
+| |  summary:     I make a huge cleanning in the figure of the DOC
+| |
+o |  changeset:   931:8f09f074b924
+| |  user:        hecht
+| |  date:        Tue Dec 27 22:26:40 2005 +0100
+| |  summary:     correct the example++-load test
+| |
+o |  changeset:   930:6406dda79272
+| |  user:        hecht
+| |  date:        Tue Dec 27 17:32:25 2005 +0100
+| |  summary:     Add two new finite element in examples++-load and change the doc
+| |
+o |  changeset:   929:52e7e6fc6a98
+| |  user:        hecht
+| |  date:        Tue Dec 27 07:54:01 2005 +0100
+| |  summary:     add new Finite Element Bernardi-Raugel for Stokes or Navier-Stokes
+| |
+o |  changeset:   928:4668e8f2bf42
+| |  user:        hecht
+| |  date:        Mon Dec 26 17:28:50 2005 +0100
+| |  summary:     Correct problem in boundary edge (lossing label numbers)  in adapated mesh, savemesh,
+| |
+o |  changeset:   927:b64cea081b9c
+| |  user:        lehyaric
+| |  date:        Tue Dec 13 13:44:58 2005 +0100
+| |  summary:     Added first support for Doxygen documentation. Inline comments still need
+| |
+o |  changeset:   926:16d64c61d6ed
+| |  user:        lehyaric
+| |  date:        Mon Dec 12 16:46:01 2005 +0100
+| |  summary:     Changed --with-suffix configuration in configure.ac to avoid adding
+| |
+o |  changeset:   925:6b38eb0bdbfb
+| |  user:        hecht
+| |  date:        Fri Dec 09 15:09:43 2005 +0100
+| |  summary:     do autoreconf
+| |
+o |  changeset:   924:93ba5ee1504b
+| |  user:        hecht
+| |  date:        Fri Dec 09 15:08:02 2005 +0100
+| |  summary:     correct CCFLAGS in umfpack for test
+| |
+o |  changeset:   923:7b3b757e62c9
+| |  user:        hecht
+| |  date:        Fri Dec 09 11:34:49 2005 +0100
+| |  summary:     add number of parameter in OneOperator class to 10
+| |
+o |  changeset:   922:aebb631a6aa3
+| |  user:        lehyaric
+| |  date:        Fri Dec 09 10:20:36 2005 +0100
+| |  summary:     <cr> symbols still showed in the Cygwin (not Mingw) version. This is now
+| |
+o |  changeset:   921:db9963c894a5
+| |  user:        hecht
+| |  date:        Fri Dec 09 09:36:19 2005 +0100
+| |  summary:     add missing files in DOPC dist
+| |
+o |  changeset:   920:16437453406f
+| |  user:        lehyaric
+| |  date:        Thu Dec 08 16:56:36 2005 +0100
+| |  summary:     New Debian package version 2.1-1.
+| |
+o |  changeset:   919:c838c9300480
+| |  user:        lehyaric
+| |  date:        Thu Dec 08 10:01:47 2005 +0100
+| |  summary:     Removed option --disable-tagging from configure.ac since @TAGGINGDEPEND@
+| |
+o |  changeset:   918:13204148cc8d
+| |  user:        hecht
+| |  date:        Thu Dec 08 07:59:02 2005 +0100
+| |  summary:     correct LIBRARY problem for umfpack Demo
+| |
+o |  changeset:   917:302b77b19c5c
+| |  user:        hecht
+| |  date:        Wed Dec 07 21:40:02 2005 +0100
+| |  summary:     * correct mistake in quadarture formule in integral computation (nota
+| |
+o |  changeset:   916:1280844b35e8
+| |  user:        hecht
+| |  date:        Wed Dec 07 17:43:37 2005 +0100
+| |  summary:     correct problem in umfpack with cblas
+| |
+o |  changeset:   915:e89bd0a8d2d1
+| |  user:        hecht
+| |  date:        Tue Dec 06 22:10:33 2005 +0100
+| |  summary:     correct mistake in cblas on configure.ac
+| |
+o |  changeset:   914:3383a8fb2e59
+| |  user:        hecht
+| |  date:        Tue Dec 06 16:56:31 2005 +0100
+| |  summary:     add new file
+| |
+o |  changeset:   913:34d33d0493a1
+| |  user:        hecht
+| |  date:        Tue Dec 06 16:55:19 2005 +0100
+| |  summary:     Use umfpack 4.4, and correct some mistake in configure.ac
+| |
+o |  changeset:   912:834165e44b24
+| |  user:        lehyaric
+| |  date:        Tue Dec 06 12:18:56 2005 +0100
+| |  summary:     Now compiles with gcc (GCC) 4.0.3 20051201 (prerelease) (Debian 4.0.2-5)
+| |
+o |  changeset:   911:239106833256
+| |  user:        hecht
+| |  date:        Fri Dec 02 11:02:00 2005 +0100
+| |  summary:     Add the generation of an error if you try to set a solver on none square matrix,
+| |
+o |  changeset:   910:589d0d1b27de
+| |  user:        hecht
+| |  date:        Wed Nov 30 13:18:19 2005 +0100
+| |  summary:     /tmp/cvsBIs12d
+| |
+o |  changeset:   909:8ea662ae978c
+| |  user:        lehyaric
+| |  date:        Tue Nov 29 11:45:03 2005 +0100
+| |  summary:     Now dlopen() works even when ARPACK is downloaded
+| |
+o |  changeset:   908:4e7335506261
+| |  user:        hecht
+| |  date:        Mon Nov 28 16:28:25 2005 +0100
+| |  summary:     add optimization of  a*b expression if a ou b is zero.
+| |
+o |  changeset:   907:88031075ba05
+| |  user:        hecht
+| |  date:        Wed Nov 23 22:02:27 2005 +0100
+| |  summary:     add roland correction in the doc.
+| |
+o |  changeset:   906:c8d1e446dddd
+| |  user:        lehyaric
+| |  date:        Wed Nov 23 10:40:26 2005 +0100
+| |  summary:     Added examples++-chapt3/all.edp into cleanregen.sh
+| |
+o |  changeset:   905:3db52fd808f9
+| |  user:        hecht
+| |  date:        Tue Nov 22 16:34:11 2005 +0100
+| |  summary:     correct problem in algo and Newtow exemple (forgot 1/2 and 2) coef
+| |
+o |  changeset:   904:788c50b38101
+| |  user:        lehyaric
+| |  date:        Tue Nov 22 10:10:30 2005 +0100
+| |  summary:     Arbitrary "wget" commands and parameters can be defined through the
+| |
+o |  changeset:   903:ff51ba4da75e
+| |  user:        hecht
+| |  date:        Sat Nov 19 21:53:41 2005 +0100
+| |  summary:     I just try autoreconf on my new mac.
+| |
+o |  changeset:   902:4a6864be0e52
+| |  user:        hecht
+| |  date:        Sat Nov 19 21:46:32 2005 +0100
+| |  summary:     remove the wrong BlackShocle.edp example
+| |
+o |  changeset:   901:aafe6f18031a
+| |  user:        hecht
+| |  date:        Wed Nov 16 11:56:55 2005 +0100
+| |  summary:     correct the following trouble
+| |
+o |  changeset:   900:2998977bc121
+| |  user:        hecht
+| |  date:        Mon Nov 14 22:00:41 2005 +0100
+| |  summary:     correct probleme when resize of full matrix, before the coef of the matrix
+| |
+o |  changeset:   899:79398b5c2b4c
+| |  user:        lehyaric
+| |  date:        Wed Nov 09 15:13:15 2005 +0100
+| |  summary:     New Debian packaging
+| |
+o |  changeset:   898:af9a5fae5106
+| |  user:        lehyaric
+| |  date:        Wed Nov 09 15:11:45 2005 +0100
+| |  summary:     Changed Debian dependency from libfltk1.1c102 to libfltk1.1
+| |
+o |  changeset:   897:a87ee751e538
+| |  user:        hecht
+| |  date:        Tue Nov 08 11:26:28 2005 +0100
+| |  summary:     change  in  grammar lg.y  misplaced  ternary operator
+| |
+o |  changeset:   896:6c6798e0e726
+| |  user:        hecht
+| |  date:        Sun Nov 06 20:36:35 2005 +0100
+| |  summary:     uodate INNOVATION file
+| |
+o |  changeset:   895:e0176cafeeca
+| |  user:        hecht
+| |  date:        Sun Nov 06 20:26:24 2005 +0100
+| |  summary:     change the tolerance value un mshptg form  2^-15 to 2^-30 if the computation in long long
+| |
+o |  changeset:   894:76b1f65a3b90
+| |  user:        hecht
+| |  date:        Wed Nov 02 22:29:12 2005 +0100
+| |  summary:     add files
+| |
+o |  changeset:   893:04dd48fbf3d6
+| |  user:        hecht
+| |  date:        Wed Nov 02 22:06:12 2005 +0100
+| |  summary:     addinf missing files
+| |
+o |  changeset:   892:b32338c130bd
+| |  user:        hecht
+| |  date:        Wed Nov 02 22:04:13 2005 +0100
+| |  summary:     correct small mistake in the doc
+| |
+o |  changeset:   891:af006f72e7b8
+| |  user:        lehyaric
+| |  date:        Wed Nov 02 10:46:14 2005 +0100
+| |  summary:     New Debian packages
+| |
+o |  changeset:   890:a3a685d549f6
+| |  user:        hecht
+| |  date:        Tue Nov 01 17:52:59 2005 +0100
+| |  summary:     correct windows install file and load.link under windows
+| |
+o |  changeset:   889:991fc4be5f2b
+| |  user:        hecht
+| |  date:        Tue Nov 01 17:08:57 2005 +0100
+| |  summary:     correct problem in array operator /=
+| |
+o |  changeset:   888:c32a725f21b6
+| |  user:        hecht
+| |  date:        Tue Nov 01 16:55:32 2005 +0100
+| |  summary:     correct src/bin-win32 Makefile.am
+| |
+o |  changeset:   887:3ef99e3bd6ae
+| |  user:        hecht
+| |  date:        Tue Nov 01 14:14:07 2005 +0100
+| |  summary:     split AFunction3.cpp in 3 files array_{long,real,double}.cpp
+| |
+o |  changeset:   886:92f491c4331f
+| |  user:        hecht
+| |  date:        Mon Oct 31 22:34:02 2005 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   885:d8267da311f1
+| |  user:        hecht
+| |  date:        Mon Oct 31 17:45:53 2005 +0100
+| |  summary:     - Correction de bug UMFPACK resolution complex problem
+| |
+o |  changeset:   884:6c4e84a1a8ac
+| |  user:        hecht
+| |  date:        Sun Oct 30 17:26:35 2005 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   883:0028bacc3e62
+| |  user:        hecht
+| |  date:        Sun Oct 30 17:06:33 2005 +0100
+| |  summary:     correct problem in eigen value computation
+| |
+o |  changeset:   882:706ef465f936
+| |  user:        lehyaric
+| |  date:        Thu Oct 27 19:09:00 2005 +0200
+| |  summary:     Change MPI package name to keep up with Debian Unstable
+| |
+o |  changeset:   881:72a8fd466c6f
+| |  user:        lehyaric
+| |  date:        Thu Oct 27 18:22:43 2005 +0200
+| |  summary:     Places examples++-other last because it contains speed tests which
+| |
+o |  changeset:   880:0dde809ed55f
+| |  user:        lehyaric
+| |  date:        Thu Oct 27 17:51:19 2005 +0200
+| |  summary:     - Improved the way configure finds libXxf86vm.a
+| |
+o |  changeset:   879:c085ef504236
+| |  user:        hecht
+| |  date:        Fri Oct 21 18:18:09 2005 +0200
+| |  summary:     Try to correct problem in win32 version
+| |
+o |  changeset:   878:aa56fd6dc7ba
+| |  user:        hecht
+| |  date:        Fri Oct 21 17:27:42 2005 +0200
+| |  summary:     add .edp file in example++-eigen dir
+| |
+o |  changeset:   877:d45005b94b3d
+| |  user:        lehyaric
+| |  date:        Thu Oct 20 16:22:05 2005 +0200
+| |  summary:     Compiling with the Cygwin DLL is now OK again
+| |
+o |  changeset:   876:6f055a07e3c3
+| |  user:        lehyaric
+| |  date:        Thu Oct 20 15:46:22 2005 +0200
+| |  summary:     configure.ac now dynamically checks for libXxf86vm.a
+| |
+o |  changeset:   875:32d5c81f8e05
+| |  user:        lehyaric
+| |  date:        Thu Oct 20 11:56:16 2005 +0200
+| |  summary:     New manual included in Debian packages
+| |
+o |  changeset:   874:c4f11df6192f
+| |  user:        hecht
+| |  date:        Wed Oct 19 16:05:20 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   873:ba8e3a039026
+| |  user:        hecht
+| |  date:        Wed Oct 19 16:01:24 2005 +0200
+| |  summary:     correct doc file in Mac vercion
+| |
+o |  changeset:   872:97c5169b06d6
+| |  user:        hecht
+| |  date:        Wed Oct 19 15:27:56 2005 +0200
+| |  summary:     add link on Desktop to example
+| |
+o |  changeset:   871:ee0c20283445
+| |  user:        lehyaric
+| |  date:        Wed Oct 19 15:23:03 2005 +0200
+| |  summary:     HISTORY update
+| |
+o |  changeset:   870:87b7436af068
+| |  user:        lehyaric
+| |  date:        Wed Oct 19 15:22:56 2005 +0200
+| |  summary:     Packaging version 2.
+| |
+o |  changeset:   869:3663c2fee3a6
+| |  user:        hecht
+| |  date:        Wed Oct 19 14:31:19 2005 +0200
+| |  summary:     correct misspelling in previous  modif
+| |
+o |  changeset:   868:0bd5255c4bd5
+| |  user:        hecht
+| |  date:        Wed Oct 19 14:20:39 2005 +0200
+| |  summary:     coorect PB LogoUMPC
+| |
+o |  changeset:   867:2e63a3e9ca9e
+| |  user:        hecht
+| |  date:        Wed Oct 19 14:14:17 2005 +0200
+| |  summary:     correct overflow in elem mat when assembling  skyline matrix
+| |
+o |  changeset:   866:adc2ee0d01fe
+| |  user:        hecht
+| |  date:        Tue Oct 18 17:27:16 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   865:5373ad791840
+| |  user:        hecht
+| |  date:        Tue Oct 18 13:41:20 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   864:d801079ba411
+| |  user:        hecht
+| |  date:        Tue Oct 18 13:29:44 2005 +0200
+| |  summary:     add .cpp in load.link command in example++-load/Makefile.am
+| |
+o |  changeset:   863:0bb65f785e1f
+| |  user:        hecht
+| |  date:        Tue Oct 18 13:14:21 2005 +0200
+| |  summary:     correct return type probleme LinearCG
+| |
+o |  changeset:   862:af063a43f41d
+| |  user:        hecht
+| |  date:        Tue Oct 18 11:56:38 2005 +0200
+| |  summary:     correct same problem when passing array as argument.
+| |
+o |  changeset:   861:15a2ea7f7e31
+| |  user:        pironnea
+| |  date:        Mon Oct 17 09:54:27 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   860:c484b5dfde1d
+| |  user:        hecht
+| |  date:        Mon Oct 17 07:26:43 2005 +0200
+| |  summary:     DOC upgrading
+| |
+o |  changeset:   859:c0e097480736
+| |  user:        hecht
+| |  date:        Sun Oct 16 19:48:40 2005 +0200
+| |  summary:     correct small listake in window version
+| |
+o |  changeset:   858:053d6a1895bd
+| |  user:        hecht
+| |  date:        Sat Oct 15 16:28:49 2005 +0200
+| |  summary:     in configure in case off --enable_download don't locat to find an arpack library
+| |
+o |  changeset:   857:46f7d68bc496
+| |  user:        hecht
+| |  date:        Fri Oct 14 11:52:34 2005 +0200
+| |  summary:     doc book continuing
+| |
+o |  changeset:   856:12c305f56de6
+| |  user:        hecht
+| |  date:        Thu Oct 13 16:23:46 2005 +0200
+| |  summary:     change the title page of the doc for publishing
+| |
+o |  changeset:   855:d3e62fa2a587
+| |  user:        pironnea
+| |  date:        Thu Oct 13 11:48:28 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   854:5313bf2fd39a
+| |  user:        pironnea
+| |  date:        Thu Oct 13 11:34:36 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   853:128f45f7d2c2
+| |  user:        hecht
+| |  date:        Wed Oct 12 22:22:47 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   852:221e441ef33a
+| |  user:        hecht
+| |  date:        Wed Oct 12 21:20:57 2005 +0200
+| |  summary:     add forgotten  files
+| |
+o |  changeset:   851:47f4d245d855
+| |  user:        hecht
+| |  date:        Wed Oct 12 21:09:23 2005 +0200
+| |  summary:     update HISTORY
+| |
+o |  changeset:   850:0a5d2156274e
+| |  user:        hecht
+| |  date:        Wed Oct 12 21:08:29 2005 +0200
+| |  summary:     Add makefile to build automaticaly the FreeFem++ version with dll
+| |
+o |  changeset:   849:09368a95147b
+| |  user:        pironnea
+| |  date:        Wed Oct 12 18:20:27 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   848:9b451b2bff88
+| |  user:        hecht
+| |  date:        Wed Oct 12 17:50:50 2005 +0200
+| |  summary:     coorect freefem++doc.tex
+| |
+o |  changeset:   847:60473c6ec0a3
+| |  user:        hecht
+| |  date:        Wed Oct 12 16:09:25 2005 +0200
+| |  summary:     just add mising eps file
+| |
+o |  changeset:   846:7053f50276e4
+| |  user:        hecht
+| |  date:        Wed Oct 12 15:42:06 2005 +0200
+| |  summary:     do correct in the manual, make big change in the dynamic load, see the maunal
+| |
+o |  changeset:   845:3cb796a22b5d
+| |  user:        hecht
+| |  date:        Tue Oct 04 20:31:41 2005 +0200
+| |  summary:     correct small mistake in load.cpp i -> j
+| |
+o |  changeset:   844:2a1740f12cd1
+| |  user:        hecht
+| |  date:        Tue Oct 04 18:17:48 2005 +0200
+| |  summary:     change the version number to build new window version.
+| |
+o |  changeset:   843:1d5169284e4c
+| |  user:        hecht
+| |  date:        Tue Oct 04 17:26:58 2005 +0200
+| |  summary:     correct overflow integer array in elementary martix
+| |
+o |  changeset:   842:cd2ddded3fe8
+| |  user:        hecht
+| |  date:        Tue Oct 04 11:44:01 2005 +0200
+| |  summary:     correct small proble in load.cpp
+| |
+o |  changeset:   841:83c6f67e8571
+| |  user:        hecht
+| |  date:        Tue Sep 27 22:35:41 2005 +0200
+| |  summary:     correct load.cpp to change suffix and prefix
+| |
+o |  changeset:   840:86a63de90bd6
+| |  user:        hecht
+| |  date:        Mon Sep 26 18:03:57 2005 +0200
+| |  summary:     small correction for buildng the Window version
+| |
+o |  changeset:   839:8d1d0e79e8f2
+| |  user:        hecht
+| |  date:        Mon Sep 26 14:42:40 2005 +0200
+| |  summary:     add bin-win32 dir to bluid  win32 executable with .dll files
+| |
+o |  changeset:   838:478cefc531be
+| |  user:        hecht
+| |  date:        Fri Sep 23 17:11:31 2005 +0200
+| |  summary:     version 1.48-1
+| |
+o |  changeset:   837:00683068609c
+| |  user:        lehyaric
+| |  date:        Thu Sep 22 12:01:49 2005 +0200
+| |  summary:     FreeFem++ works on Linux (Debian Testing) thanks to the following
+| |
+o |  changeset:   836:3c745b9c0391
+| |  user:        hecht
+| |  date:        Wed Sep 21 21:04:58 2005 +0200
+| |  summary:     correct bug in  set array of array to array of reverse
+| |
+o |  changeset:   835:d08a7fe8d64b
+| |  user:        lehyaric
+| |  date:        Wed Sep 21 14:52:28 2005 +0200
+| |  summary:     Added new examples++-chapt3 directory to Windows distribution
+| |
+o |  changeset:   834:37968b5d3aa4
+| |  user:        hecht
+| |  date:        Fri Sep 09 15:27:40 2005 +0200
+| |  summary:     change the reconstruction of strversionnumber.cpp
+| |
+o |  changeset:   833:5ed4006dc572
+| |  user:        hecht
+| |  date:        Fri Sep 09 15:19:14 2005 +0200
+| |  summary:     create ref.edp file (empty today)
+| |
+o |  changeset:   832:541c3f59571d
+| |  user:        hecht
+| |  date:        Fri Sep 09 15:17:10 2005 +0200
+| |  summary:     add examples++-chapt3  stuff
+| |
+o |  changeset:   831:d0b4babe44bc
+| |  user:        hecht
+| |  date:        Fri Sep 09 14:30:50 2005 +0200
+| |  summary:     add new include file
+| |
+o |  changeset:   830:ec7cf2a5bb56
+| |  user:        hecht
+| |  date:        Fri Sep 09 13:45:37 2005 +0200
+| |  summary:     correct missing .esp file in Makefile.am
+| |
+o |  changeset:   829:385fa7cb90cf
+| |  user:        hecht
+| |  date:        Fri Sep 09 13:27:16 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   828:17e148260e7d
+| |  user:        hecht
+| |  date:        Fri Sep 09 13:25:55 2005 +0200
+| |  summary:     add threehsv.eps file
+| |
+o |  changeset:   827:561442bc79b4
+| |  user:        hecht
+| |  date:        Wed Aug 31 15:53:14 2005 +0200
+| |  summary:     add new arithmetic if expression   ( (a ? b : c) like in c++
+| |
+o |  changeset:   826:908ddb527637
+| |  user:        hecht
+| |  date:        Tue Aug 30 16:56:27 2005 +0200
+| |  summary:     correct unmissing print in case of  verbosity = 0 .
+| |
+o |  changeset:   825:0a55e1d02298
+| |  user:        hecht
+| |  date:        Tue Aug 30 14:58:44 2005 +0200
+| |  summary:     correct color in window version
+| |
+o |  changeset:   824:f54ced8e4821
+| |  user:        hecht
+| |  date:        Tue Aug 30 13:36:53 2005 +0200
+| |  summary:     Add tool to change the color table of plot:
+| |
+o |  changeset:   823:95d85c693298
+| |  user:        hecht
+| |  date:        Thu Aug 25 14:23:19 2005 +0200
+| |  summary:     add new freefem++ documentation freefem++doc.pdf ( from O. Pironneau)
+| |
+o |  changeset:   822:6ac1c6bfc617
+| |  user:        lehyaric
+| |  date:        Fri Jul 15 14:11:49 2005 +0200
+| |  summary:     Removed "restricted" option from FreeFem++-cs (the Web service does
+| |
+o |  changeset:   821:8508a9315ab1
+| |  user:        lehyaric
+| |  date:        Wed Jul 13 13:40:51 2005 +0200
+| |  summary:     Removed references to undefined class "TheSubFMortars"
+| |
+o |  changeset:   820:546ff9fb4445
+| |  user:        hecht
+| |  date:        Wed Jul 13 12:10:21 2005 +0200
+| |  summary:     OK, we can make dll under window.   first test
+| |
+o |  changeset:   819:4f9e6ba028ac
+| |  user:        hecht
+| |  date:        Tue Jul 12 11:22:20 2005 +0200
+| |  summary:     Big modif to buil .dll under window ( it's hard)
+| |
+o |  changeset:   818:5e1096ec1eb9
+| |  user:        hecht
+| |  date:        Thu Jul 07 09:50:47 2005 +0200
+| |  summary:     find a new bug in cas if we declare new variable after a break, continue or a return
+| |
+o |  changeset:   817:e03e5f78e5fe
+| |  user:        hecht
+| |  date:        Tue Jul 05 16:24:31 2005 +0200
+| |  summary:     correct problem in meshsplit function in case of final mesh with hole and
+| |
+o |  changeset:   816:5fc7ff0dcbe0
+| |  user:        hecht
+| |  date:        Tue Jul 05 13:11:24 2005 +0200
+| |  summary:     change version to 1.47-3
+| |
+o |  changeset:   815:f62d00cabf0e
+| |  user:        lehyaric
+| |  date:        Tue Jul 05 11:48:44 2005 +0200
+| |  summary:     Tuning scripts for Debian amd64 packaging
+| |
+o |  changeset:   814:e74d584065c5
+| |  user:        lehyaric
+| |  date:        Mon Jul 04 17:29:41 2005 +0200
+| |  summary:     Re-enables PDF and PS documentation in Windows packaging after finding the
+| |
+o |  changeset:   813:e9430e4f4bac
+| |  user:        lehyaric
+| |  date:        Mon Jul 04 16:42:49 2005 +0200
+| |  summary:     Removed wrong dynamic linking option bug from configure.ac
+| |
+o |  changeset:   812:edd3b1cd9f6d
+| |  user:        lehyaric
+| |  date:        Mon Jul 04 16:26:14 2005 +0200
+| |  summary:     Added "-fPIC" in compilation options for 64 bit Linux
+| |
+o |  changeset:   811:e5e1da1b1bfe
+| |  user:        hecht
+| |  date:        Mon Jul 04 15:55:23 2005 +0200
+| |  summary:     correct problem in antype castting under window
+| |
+o |  changeset:   810:1cb5cd176bfb
+| |  user:        lehyaric
+| |  date:        Mon Jul 04 14:57:26 2005 +0200
+| |  summary:     Removed documentation from Windows executable package because PDF and PS
+| |
+o |  changeset:   809:b91b4cb1848d
+| |  user:        lehyaric
+| |  date:        Mon Jul 04 13:59:34 2005 +0200
+| |  summary:     Changed Debian package dependency from "arpack++" to "libarpack++2-dev"
+| |
+o |  changeset:   808:152b0171eb45
+| |  user:        lehyaric
+| |  date:        Mon Jul 04 13:30:16 2005 +0200
+| |  summary:     Changing packaging procedure to include new FreeFem++-cs binaries
+| |
+o |  changeset:   807:e18fc97ba94a
+| |  user:        lehyaric
+| |  date:        Mon Jul 04 13:28:59 2005 +0200
+| |  summary:     Changing packaging procedure to include FreeFem++-cs binaries.
+| |
+o |  changeset:   806:6e6d817fee3d
+| |  user:        lehyaric
+| |  date:        Fri Jul 01 17:04:59 2005 +0200
+| |  summary:     Added 64bit debian package (amd64)
+| |
+o |  changeset:   805:bf4bd6f52606
+| |  user:        lehyaric
+| |  date:        Fri Jul 01 15:21:40 2005 +0200
+| |  summary:     Changed makefile to be able to run the Debian packaging procedure.
+| |
+o |  changeset:   804:13a708e99d11
+| |  user:        lehyaric
+| |  date:        Fri Jul 01 14:23:32 2005 +0200
+| |  summary:     Minor modifications in 'clean' goal.
+| |
+o |  changeset:   803:3973b9916156
+| |  user:        lehyaric
+| |  date:        Fri Jul 01 12:08:40 2005 +0200
+| |  summary:     New package (1.47-2) currently being built
+| |
+o |  changeset:   802:93740702390d
+| |  user:        lehyaric
+| |  date:        Fri Jul 01 11:59:51 2005 +0200
+| |  summary:     Building a new package
+| |
+o |  changeset:   801:507bab956933
+| |  user:        hecht
+| |  date:        Fri Jul 01 11:43:15 2005 +0200
+| |  summary:     correct problem with splitmesh with internal boundary
+| |
+o |  changeset:   800:d450da38d40c
+| |  user:        lehyaric
+| |  date:        Fri Jul 01 10:57:28 2005 +0200
+| |  summary:     Test examples++-tutorial/freeboundary-weak also disabled from regression
+| |
+o |  changeset:   799:447f53a0dbac
+| |  user:        lehyaric
+| |  date:        Fri Jul 01 10:34:10 2005 +0200
+| |  summary:     Disabling example examples++-tutorial/freeboundary.edp from regression tests
+| |
+o |  changeset:   798:5b0c1d07bccd
+| |  user:        lehyaric
+| |  date:        Thu Jun 30 12:22:20 2005 +0200
+| |  summary:     Configuration procedure updated with new Cygin/Mingw parameters
+| |
+o |  changeset:   797:93549d7d0176
+| |  user:        lehyaric
+| |  date:        Thu Jun 30 12:08:30 2005 +0200
+| |  summary:     Standard libraries locations have changed under Cygwin/Mingw
+| |
+o |  changeset:   796:8a5fb70aa981
+| |  user:        hecht
+| |  date:        Thu Jun 30 08:10:30 2005 +0200
+| |  summary:     add FE-medit.edp example to show  plot of FE a basis function (FH)
+| |
+o |  changeset:   795:bfa6725fe254
+| |  user:        hecht
+| |  date:        Wed Jun 29 21:40:48 2005 +0200
+| |  summary:     Add a new finite element P0edge to build new error indicator
+| |
+o |  changeset:   794:907fe04bf4f0
+| |  user:        lehyaric
+| |  date:        Wed Jun 29 15:00:05 2005 +0200
+| |  summary:     configure.ac now checks whether flex is compatible with bison. Otherwise
+| |
+o |  changeset:   793:4058e691fedf
+| |  user:        lehyaric
+| |  date:        Wed Jun 29 13:59:35 2005 +0200
+| |  summary:     Added some comments inside lex files about producing bison-compatible lexers
+| |
+o |  changeset:   792:62d20e3691fe
+| |  user:        lehyaric
+| |  date:        Wed Jun 29 11:57:36 2005 +0200
+| |  summary:     Options bison-bridge and bison-locations are not recognized undef cygwin
+| |
+o |  changeset:   791:ca53d6b490fb
+| |  user:        lehyaric
+| |  date:        Wed Jun 29 11:52:45 2005 +0200
+| |  summary:     At the moment, FreeFem++ does not compile under Cygwin because of problems
+| |
+o |  changeset:   790:a78f87e4a2f0
+| |  user:        lehyaric
+| |  date:        Wed Jun 29 10:10:33 2005 +0200
+| |  summary:     Added a new configure option "--disable-tagging" to speed up
+| |
+o |  changeset:   789:f4101f1de341
+| |  user:        hecht
+| |  date:        Tue Jun 28 11:44:33 2005 +0200
+| |  summary:     add instruction to copy sub array in array
+| |
+o |  changeset:   788:a0c72c4364df
+| |  user:        lehyaric
+| |  date:        Tue Jun 28 11:27:01 2005 +0200
+| |  summary:     Color-coding in FreeFem++-cs now colors multi-line comments (/*
+| |
+o |  changeset:   787:d9dae2e4a837
+| |  user:        lehyaric
+| |  date:        Tue Jun 28 11:07:36 2005 +0200
+| |  summary:     FreeFem++-cs no longer crashes under Windows when loading a second EDP program
+| |
+o |  changeset:   786:07e403bc9c4d
+| |  user:        hecht
+| |  date:        Tue Jun 28 10:23:24 2005 +0200
+| |  summary:     correct trouble in block matrix with transpiose sub matrix
+| |
+o |  changeset:   785:77dc6490a932
+| |  user:        hecht
+| |  date:        Mon Jun 27 16:23:51 2005 +0200
+| |  summary:     add tools to build bock matrices like
+| |
+o |  changeset:   784:a8b2df79833e
+| |  user:        hecht
+| |  date:        Thu Jun 23 13:27:55 2005 +0200
+| |  summary:     to add Highlighting Patterns for nedit editor of .edp file., do
+| |
+o |  changeset:   783:8801d1801347
+| |  user:        hecht
+| |  date:        Sun Jun 19 21:09:11 2005 +0200
+| |  summary:     Add way to bluid matrix with varf on different meshes.
+| |
+o |  changeset:   782:96d9ef496911
+| |  user:        hecht
+| |  date:        Fri Jun 10 16:33:43 2005 +0200
+| |  summary:     coorect error  in add
+| |
+o |  changeset:   781:bbebd79e4d3d
+| |  user:        hecht
+| |  date:        Fri Jun 10 16:23:11 2005 +0200
+| |  summary:     correct some spelling error
+| |
+o |  changeset:   780:51598cdf173d
+| |  user:        hecht
+| |  date:        Thu Jun 09 15:48:48 2005 +0200
+| |  summary:     add computation of eigen value for complex matrix
+| |
+o |  changeset:   779:5a11859ad82a
+| |  user:        hecht
+| |  date:        Thu Jun 02 15:56:06 2005 +0200
+| |  summary:     correct une function name in Pcrgraph.cpp
+| |
+o |  changeset:   778:60033de30615
+| |  user:        hecht
+| |  date:        Thu Jun 02 15:02:09 2005 +0200
+| |  summary:     try to build a dll file  continuing.
+| |
+o |  changeset:   777:3a9aa1ef97c4
+| |  user:        hecht
+| |  date:        Thu Jun 02 13:58:02 2005 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   776:ed24b0f0f4df
+| |  user:        hecht
+| |  date:        Thu Jun 02 13:56:57 2005 +0200
+| |  summary:     correct doible name (CodeAlloc.cpp)  in fflib/Makefile.am
+| |
+o |  changeset:   775:615a4b420050
+| |  user:        hecht
+| |  date:        Thu Jun 02 13:54:33 2005 +0200
+| |  summary:     continuing solve problem to make a dll file  of freefem
+| |
+o |  changeset:   774:4cca7ee6dfc1
+| |  user:        hecht
+| |  date:        Wed Jun 01 22:52:42 2005 +0200
+| |  summary:     Do big modification in rgraph.hpp:
+| |
+o |  changeset:   773:200f008bc381
+| |  user:        hecht
+| |  date:        Thu May 12 11:16:59 2005 +0200
+| |  summary:     correct  problem of  CFMessagePort: bootstrap_register()
+| |
+o |  changeset:   772:6f30a07c0403
+| |  user:        hecht
+| |  date:        Wed May 11 15:17:06 2005 +0200
+| |  summary:     cosmetic change in PC version
+| |
+o |  changeset:   771:12b8179f350f
+| |  user:        hecht
+| |  date:        Wed May 11 11:21:00 2005 +0200
+| |  summary:     correct problem in acoptim.m4 (g++-4 and -fast optim flags)
+| |
+o |  changeset:   770:5864a10636d1
+| |  user:        hecht
+| |  date:        Wed May 11 10:09:40 2005 +0200
+| |  summary:     add CXX and CC setting  in fltk  configure parameters
+| |
+o |  changeset:   769:d9d6bd29c106
+| |  user:        hecht
+| |  date:        Tue May 10 21:19:18 2005 +0200
+| |  summary:     add include <errno.hpp> in some ide files  (FH)
+| |
+o |  changeset:   768:de52b6df4ea1
+| |  user:        hecht
+| |  date:        Wed May 04 22:29:42 2005 +0200
+| |  summary:     add  examples++tutorial/xyf file in window distribution
+| |
+o |  changeset:   767:ec5efeca8fb4
+| |  user:        hecht
+| |  date:        Wed May 04 22:04:25 2005 +0200
+| |  summary:     add aile.msh in window distribution
+| |
+o |  changeset:   766:b753e46694a8
+| |  user:        hecht
+| |  date:        Wed May 04 21:59:52 2005 +0200
+| |  summary:     correct  line endding in aile.msh file (make as unix file)
+| |
+o |  changeset:   765:054a01ff942d
+| |  user:        hecht
+| |  date:        Wed May 04 21:13:44 2005 +0200
+| |  summary:     correct DOC/Makefile.am
+| |
+o |  changeset:   764:62ed86008444
+| |  user:        hecht
+| |  date:        Wed May 04 21:01:05 2005 +0200
+| |  summary:     correct the DOC directory and do autoreconf
+| |
+o |  changeset:   763:00dacf8de9d8
+| |  user:        hecht
+| |  date:        Wed May 04 19:56:36 2005 +0200
+| |  summary:     clean the DOC directory to build manual-full and
+| |
+o |  changeset:   762:4d0d7644df80
+| |  user:        hecht
+| |  date:        Wed May 04 14:26:02 2005 +0200
+| |  summary:     rebuil all.edp in examples++-tutorial (to remove ref to bug.edp)
+| |
+o |  changeset:   761:810491481429
+| |  user:        hecht
+| |  date:        Wed May 04 13:09:15 2005 +0200
+| |  summary:     do autoreconf to rebuild Makefile.in files
+| |
+o |  changeset:   760:8aca6e010f53
+| |  user:        hecht
+| |  date:        Wed May 04 13:06:48 2005 +0200
+| |  summary:     add  10^10 and  10.^10 operator (due to error in sphere   .edp)
+| |
+o |  changeset:   759:70c5c7c03926
+| |  user:        hecht
+| |  date:        Tue May 03 16:25:39 2005 +0200
+| |  summary:     remove pascal in "\p  "  macos version
+| |
+o |  changeset:   758:ec2b000b022c
+| |  user:        hecht
+| |  date:        Tue May 03 15:12:06 2005 +0200
+| |  summary:     try to compile with de idm compiler xlc++
+| |
+o |  changeset:   757:379de2f9fa7d
+| |  user:        hecht
+| |  date:        Mon May 02 10:57:59 2005 +0200
+| |  summary:     do correction for g++-4.0
+| |
+o |  changeset:   756:fdaaafdd2726
+| |  user:        hecht
+| |  date:        Wed Apr 27 14:23:44 2005 +0200
+| |  summary:     do correction for g++ version 4.0  (new apple compiler on Tiger)
+| |
+o |  changeset:   755:f90afd98be49
+| |  user:        lehyaric
+| |  date:        Fri Apr 22 11:58:39 2005 +0200
+| |  summary:     Debug checks are ok on Debian Testing
+| |
+o |  changeset:   754:25358d1c2fac
+| |  user:        hecht
+| |  date:        Sun Apr 17 18:44:03 2005 +0200
+| |  summary:     add page to explain how to bluid weak form with Robin / Neumann coundary condition
+| |
+o |  changeset:   753:5dec2ffefbd4
+| |  user:        hecht
+| |  date:        Sat Apr 16 21:36:09 2005 +0200
+| |  summary:     add tool to solve variationnal inequality
+| |
+o |  changeset:   752:95a33493c392
+| |  user:        hecht
+| |  date:        Fri Apr 15 22:06:03 2005 +0200
+| |  summary:     add tools to solve variationnal inequality
+| |
+o |  changeset:   751:b9a7054a3c47
+| |  user:        lehyaric
+| |  date:        Wed Apr 13 11:58:49 2005 +0200
+| |  summary:     IDE compiles again under MingW (an include file was missing)
+| |
+o |  changeset:   750:3cba4b225729
+| |  user:        hecht
+| |  date:        Tue Apr 12 18:37:37 2005 +0200
+| |  summary:     add Modification Kohji Ohtsuka in a manual
+| |
+o |  changeset:   749:1097a5ea6a9b
+| |  user:        hecht
+| |  date:        Tue Apr 12 12:07:29 2005 +0200
+| |  summary:     add flags to build unionkjack mesh on square
+| |
+o |  changeset:   748:80ebe655fe59
+| |  user:        lehyaric
+| |  date:        Tue Apr 05 15:08:18 2005 +0200
+| |  summary:     FreeFem+-ide compiles on MacOS X
+| |
+o |  changeset:   747:dd5a71e36e2b
+| |  user:        lehyaric
+| |  date:        Tue Apr 05 14:33:49 2005 +0200
+| |  summary:     First version of FreeFem++-ide without sockets compiles under Linux
+| |
+o |  changeset:   746:74899325800e
+| |  user:        hecht
+| |  date:        Wed Mar 30 11:38:14 2005 +0200
+| |  summary:     correct name of example  blakschol.edp in BlackSchole.edp
+| |
+o |  changeset:   745:d4ef47df5261
+| |  user:        lehyaric
+| |  date:        Wed Mar 30 11:02:34 2005 +0200
+| |  summary:     Not regenerating HISTORY if not in a CVS working area
+| |
+o |  changeset:   744:8f628e467da3
+| |  user:        hecht
+| |  date:        Wed Mar 30 10:42:49 2005 +0200
+| |  summary:     correct some mistake in Makefile.am (in: examples++-load/, src/ide/)
+| |
+o |  changeset:   743:9ead41b56331
+| |  user:        hecht
+| |  date:        Wed Mar 30 09:31:27 2005 +0200
+| |  summary:     adding 2 new files for allocation (forgot in previous commit)
+| |
+o |  changeset:   742:5bed47d8b18c
+| |  user:        hecht
+| |  date:        Tue Mar 29 23:13:16 2005 +0200
+| |  summary:     Big change in code generation alloc  (work in progress)
+| |
+o |  changeset:   741:24711fe2923e
+| |  user:        hecht
+| |  date:        Fri Mar 25 17:59:22 2005 +0100
+| |  summary:     correct bug in trunc function:
+| |
+o |  changeset:   740:73864219f12e
+| |  user:        lehyaric
+| |  date:        Fri Mar 25 14:54:25 2005 +0100
+| |  summary:     Compiling ok on Linux
+| |
+o |  changeset:   739:a76f21b1ab1e
+| |  user:        lehyaric
+| |  date:        Fri Mar 25 12:37:07 2005 +0100
+| |  summary:     Client and server merged into one unique executable to make sure that the client can find its server program, even through symbolic links.
+| |
+o |  changeset:   738:1bbb4cafbb9b
+| |  user:        lehyaric
+| |  date:        Thu Mar 17 14:15:31 2005 +0100
+| |  summary:     Included src/lglib/lg.tab.?pp in cleanregen.sh
+| |
+o |  changeset:   737:8d7e1b3ebe28
+| |  user:        lehyaric
+| |  date:        Thu Mar 17 14:13:42 2005 +0100
+| |  summary:     Replaced sem_getvalue() with a separate counter on MacOSX.
+| |
+o |  changeset:   736:a92e3f968ecc
+| |  user:        hecht
+| |  date:        Wed Mar 16 22:28:55 2005 +0100
+| |  summary:     add tool to get number of mesh triangle  contening a point (x,y)
+| |
+o |  changeset:   735:31983afb5ba0
+| |  user:        hecht
+| |  date:        Wed Mar 16 15:37:32 2005 +0100
+| |  summary:     correct prototype of StrVersionNumber in macrgraf
+| |
+o |  changeset:   734:f1c10c96352d
+| |  user:        lehyaric
+| |  date:        Wed Mar 16 15:05:14 2005 +0100
+| |  summary:     Updates to the no-F77 no-C configuration
+| |
+o |  changeset:   733:c6b1f76c3c5f
+| |  user:        lehyaric
+| |  date:        Wed Mar 16 14:41:57 2005 +0100
+| |  summary:     Fortran and C compilers are now optional (if they are missing,
+| |
+o |  changeset:   732:e6c08627d1d6
+| |  user:        hecht
+| |  date:        Wed Mar 16 12:08:00 2005 +0100
+| |  summary:     correct error in prototype of StrVersionNumber and
+| |
+o |  changeset:   731:8f0890d47a88
+| |  user:        hecht
+| |  date:        Sun Mar 13 16:32:09 2005 +0100
+| |  summary:     correct compilation problem in RNM (resize) with g++3.4 (add this->)
+| |
+o |  changeset:   730:52c5da835984
+| |  user:        lehyaric
+| |  date:        Wed Mar 02 11:50:19 2005 +0100
+| |  summary:     Correcting compilation problem on RedHat
+| |
+o |  changeset:   729:d2dfa98a26fd
+| |  user:        lehyaric
+| |  date:        Wed Mar 02 11:29:12 2005 +0100
+| |  summary:     New packaging including FreeFem++-cs features: fast graphics, grammar highlighting, error-line display
+| |
+o |  changeset:   728:4125f650c69b
+| |  user:        lehyaric
+| |  date:        Wed Mar 02 11:22:00 2005 +0100
+| |  summary:     FreeFem++-cs MinGW bug corrected: does not crash anymore when reading a file name from the command line
+| |
+o |  changeset:   727:59c2e9b5f8a2
+| |  user:        lehyaric
+| |  date:        Tue Mar 01 16:06:32 2005 +0100
+| |  summary:     Removed unnecessary #includes
+| |
+o |  changeset:   726:b476e6a9aa5a
+| |  user:        lehyaric
+| |  date:        Tue Mar 01 14:21:52 2005 +0100
+| |  summary:     Segmentation violation error while loading a file from the command line in FreeFem++-cs. Debugging in progress.
+| |
+o |  changeset:   725:73070a97038f
+| |  user:        lehyaric
+| |  date:        Mon Feb 28 11:40:10 2005 +0100
+| |  summary:     Now compiling fine on MinGW
+| |
+o |  changeset:   724:9ad116514e1c
+| |  user:        lehyaric
+| |  date:        Fri Feb 25 16:14:13 2005 +0100
+| |  summary:     FreeFem++-cs: compile-time or runtime errors are now highlighted in the
+| |
+o |  changeset:   723:a963794aad0d
+| |  user:        lehyaric
+| |  date:        Fri Feb 25 13:10:25 2005 +0100
+| |  summary:     More coherency checks in configure.ac for a correct MPI installation.
+| |
+o |  changeset:   722:5b390b867211
+| |  user:        lehyaric
+| |  date:        Fri Feb 25 10:50:26 2005 +0100
+| |  summary:     Added new "resize" reserved word into the highlighting grammar.
+| |
+o |  changeset:   721:fb36b11fd57c
+| |  user:        hecht
+| |  date:        Thu Feb 24 21:27:23 2005 +0100
+| |  summary:     correct the documentation
+| |
+o |  changeset:   720:b8fb25f14bbb
+| |  user:        hecht
+| |  date:        Thu Feb 24 20:44:20 2005 +0100
+| |  summary:     correct  mistake in return type in complex mean and jump new function (FH)
+| |
+o |  changeset:   719:347d7fdaf605
+| |  user:        hecht
+| |  date:        Thu Feb 24 15:33:21 2005 +0100
+| |  summary:     resize of array and matrices, continuing
+| |
+o |  changeset:   718:05352247ee60
+| |  user:        hecht
+| |  date:        Thu Feb 24 15:32:36 2005 +0100
+| |  summary:     add resize of int,real and complex array or matrices, exemple:
+| |
+o |  changeset:   717:237af51c2d16
+| |  user:        hecht
+| |  date:        Thu Feb 24 09:44:21 2005 +0100
+| |  summary:     correct bug  in array of complex FE function like
+| |
+o |  changeset:   716:0b0233d67ebb
+| |  user:        lehyaric
+| |  date:        Wed Feb 23 15:51:03 2005 +0100
+| |  summary:     Highlighting test procedure not ready for regression tests yet: disabled
+| |
+o |  changeset:   715:d6cd82cad75c
+| |  user:        lehyaric
+| |  date:        Wed Feb 23 15:22:05 2005 +0100
+| |  summary:     "testhighlight" regression tests now work up to (but not including) array.edp
+| |
+o |  changeset:   714:fb6575626cdc
+| |  user:        lehyaric
+| |  date:        Wed Feb 23 14:50:49 2005 +0100
+| |  summary:     Added highlighting grammar files into CVS, in case the compiling environment
+| |
+o |  changeset:   713:81e3198dfed6
+| |  user:        lehyaric
+| |  date:        Wed Feb 23 13:44:31 2005 +0100
+| |  summary:     The HISTORY file is now created from CVS logs thanks to "cvs2cl".
+| |
+o |  changeset:   712:349dc15fb839
+| |  user:        lehyaric
+| |  date:        Wed Feb 23 12:45:15 2005 +0100
+| |  summary:     FreeFem++-cs: grammar-driven syntax highlighting works on
+| |
+o |  changeset:   711:8871b1b4c0bb
+| |  user:        hecht
+| |  date:        Wed Feb 23 10:49:35 2005 +0100
+| |  summary:     add jump and mean of complex function.
+| |
+o |  changeset:   710:c7e0c39689ca
+| |  user:        lehyaric
+| |  date:        Fri Feb 18 20:13:24 2005 +0100
+| |  summary:     FreeFem++-cs syntax highlighting is now highlights keywords based on their
+| |
+o |  changeset:   709:6b9cc14429a3
+| |  user:        hecht
+| |  date:        Fri Feb 18 18:00:08 2005 +0100
+| |  summary:     ajoute d'un test d'erreur
+| |
+o |  changeset:   708:c442c6ae9737
+| |  user:        lehyaric
+| |  date:        Thu Feb 17 16:02:34 2005 +0100
+| |  summary:     Added new developments
+| |
+o |  changeset:   707:051b3deb6ac4
+| |  user:        lehyaric
+| |  date:        Thu Feb 17 15:05:22 2005 +0100
+| |  summary:     Compiles on MacOS X.
+| |
+o |  changeset:   706:b93878dc57dd
+| |  user:        lehyaric
+| |  date:        Thu Feb 17 14:27:03 2005 +0100
+| |  summary:     First working version of syntax highlighting through grammar file in
+| |
+o |  changeset:   705:ed842e9da7aa
+| |  user:        hecht
+| |  date:        Wed Feb 16 18:13:38 2005 +0100
+| |  summary:     3D continuing +  truc
+| |
+o |  changeset:   704:9b85196f1bca
+| |  user:        lehyaric
+| |  date:        Wed Feb 16 13:44:24 2005 +0100
+| |  summary:     Socket buffering is now limited to avoid random communication errors.
+| |
+o |  changeset:   703:ca5e14fc546c
+| |  user:        lehyaric
+| |  date:        Mon Feb 14 17:22:24 2005 +0100
+| |  summary:     Socket communication between client and server in FreeFem++-cs has been
+| |
+o |  changeset:   702:caeeecdd92b9
+| |  user:        hecht
+| |  date:        Fri Feb 11 22:20:32 2005 +0100
+| |  summary:     complet DOC
+| |
+o |  changeset:   701:10f42008bce2
+| |  user:        hecht
+| |  date:        Fri Feb 11 18:00:16 2005 +0100
+| |  summary:     add 2 new quadrature formular qf7pT and qf9pT with respectively 15 and 21 points
+| |
+o |  changeset:   700:c2f60527abb5
+| |  user:        hecht
+| |  date:        Tue Feb 08 17:26:15 2005 +0100
+| |  summary:     add 3D stuff in quadtree
+| |
+o |  changeset:   699:42115bed3c70
+| |  user:        lehyaric
+| |  date:        Tue Feb 08 16:52:02 2005 +0100
+| |  summary:     Updated TODO list for FreeFem++-cs
+| |
+o |  changeset:   698:1cbe06a20efc
+| |  user:        lehyaric
+| |  date:        Tue Feb 08 16:18:08 2005 +0100
+| |  summary:     Dynamic loading is now disabled if dlopen() does not link properly
+| |
+o |  changeset:   697:b17a41e40e1b
+| |  user:        hecht
+| |  date:        Tue Feb 08 15:18:51 2005 +0100
+| |  summary:     add  buildmesh example with nbvx=  named parameter
+| |
+o |  changeset:   696:662cf549f14b
+| |  user:        lehyaric
+| |  date:        Tue Feb 08 14:23:24 2005 +0100
+| |  summary:     New Debian package
+| |
+o |  changeset:   695:ef360bad2ed9
+| |  user:        lehyaric
+| |  date:        Fri Feb 04 16:47:21 2005 +0100
+| |  summary:     Now checks that FLTK is compiled with threads before accepting it.
+| |
+o |  changeset:   694:3b58d5c49afb
+| |  user:        lehyaric
+| |  date:        Fri Feb 04 16:24:44 2005 +0100
+| |  summary:     Patchs de configuration proposés par Thierry Thomas pour FreeBSD intégrés.
+| |
+o |  changeset:   693:9af00658c499
+| |  user:        hecht
+| |  date:        Fri Feb 04 15:30:49 2005 +0100
+| |  summary:     beginning of  3D version
+| |
+o |  changeset:   692:3dd198f1df06
+| |  user:        lehyaric
+| |  date:        Tue Feb 01 16:49:04 2005 +0100
+| |  summary:     New script to remove generated files (in order to prevent CVS conflicts)
+| |
+o |  changeset:   691:7a29cfe029e6
+| |  user:        lehyaric
+| |  date:        Tue Feb 01 16:04:54 2005 +0100
+| |  summary:     FreeFem++-cs compiling and running on Windows with fully blocking sockets
+| |
+o |  changeset:   690:2fabec51e87c
+| |  user:        lehyaric
+| |  date:        Tue Feb 01 14:38:02 2005 +0100
+| |  summary:     FreeFem++-cs works with fully-blocking sockets on Linux.
+| |
+o |  changeset:   689:f0ac462be8a7
+| |  user:        lehyaric
+| |  date:        Tue Feb 01 12:20:38 2005 +0100
+| |  summary:     Reverting FreeFem++-cs to blocking IO because of Microsoft Windows problems
+| |
+o |  changeset:   688:010fbaa0c385
+| |  user:        lehyaric
+| |  date:        Mon Jan 31 15:21:05 2005 +0100
+| |  summary:     New version number in makefiles.
+| |
+o |  changeset:   687:f06a10e19b98
+| |  user:        lehyaric
+| |  date:        Mon Jan 31 15:17:51 2005 +0100
+| |  summary:     Default version number now includes package number.
+| |
+o |  changeset:   686:c9b8132a2529
+| |  user:        lehyaric
+| |  date:        Mon Jan 31 14:07:13 2005 +0100
+| |  summary:     Problem with busy waiting under Windows solved.
+| |
+o |  changeset:   685:da3d8c2394e2
+| |  user:        hecht
+| |  date:        Sat Jan 29 09:56:58 2005 +0100
+| |  summary:     correct some compile error with g++ 3.4
+| |
+o |  changeset:   684:4082bdc8cf45
+| |  user:        lehyaric
+| |  date:        Fri Jan 28 13:27:49 2005 +0100
+| |  summary:     Windows packaging for new improved socket implementation
+| |
+o |  changeset:   683:b94d16aa1620
+| |  user:        lehyaric
+| |  date:        Fri Jan 28 11:28:07 2005 +0100
+| |  summary:     Still trying to resolve discrepancies between Linux and Windows sockets.
+| |
+o |  changeset:   682:d572b516a5ff
+| |  user:        hecht
+| |  date:        Thu Jan 27 19:01:24 2005 +0100
+| |  summary:     correct ; placement in if ...
+| |
+o |  changeset:   681:e67edeab0092
+| |  user:        hecht
+| |  date:        Thu Jan 27 18:30:17 2005 +0100
+| |  summary:     pour mettre les makefile.in ok
+| |
+o |  changeset:   680:e48d92cee32c
+| |  user:        hecht
+| |  date:        Thu Jan 27 18:15:48 2005 +0100
+| |  summary:     mac install continuing
+| |
+o |  changeset:   679:6a216a159e0c
+| |  user:        hecht
+| |  date:        Thu Jan 27 18:14:20 2005 +0100
+| |  summary:     mac install continuing
+| |
+o |  changeset:   678:915751728e29
+| |  user:        hecht
+| |  date:        Thu Jan 27 18:07:16 2005 +0100
+| |  summary:     continuing coorect of macos application installation
+| |
+o |  changeset:   677:69466588b4f3
+| |  user:        lehyaric
+| |  date:        Thu Jan 27 17:16:54 2005 +0100
+| |  summary:     Reorganising socket communication in FreeFem++-cs because of instabilities
+| |
+o |  changeset:   676:132579c00f77
+| |  user:        lehyaric
+| |  date:        Thu Jan 27 10:59:01 2005 +0100
+| |  summary:     Drag'n'drop works with Mozilla Firefox for Windows.
+| |
+o |  changeset:   675:f7b2a8606369
+| |  user:        hecht
+| |  date:        Wed Jan 26 23:34:28 2005 +0100
+| |  summary:     add .app.tgz of macos application
+| |
+o |  changeset:   674:25c49da9166e
+| |  user:        hecht
+| |  date:        Wed Jan 26 23:31:21 2005 +0100
+| |  summary:     correct pb dvi pdf in manual.tex
+| |
+o |  changeset:   673:d0c77c71561b
+| |  user:        hecht
+| |  date:        Wed Jan 26 23:25:09 2005 +0100
+| |  summary:     correct stuff in dist generation
+| |
+o |  changeset:   672:7df608534c4b
+| |  user:        hecht
+| |  date:        Wed Jan 26 23:22:59 2005 +0100
+| |  summary:     correct problem dvi and pdf chose
+| |
+o |  changeset:   671:29bf3dda976d
+| |  user:        hecht
+| |  date:        Wed Jan 26 17:50:13 2005 +0100
+| |  summary:     coorect macos X application)
+| |
+o |  changeset:   670:0e3142ee3a33
+| |  user:        lehyaric
+| |  date:        Wed Jan 26 13:58:41 2005 +0100
+| |  summary:     In configure.ac, PACKAGE_VERSION is already used by autoconf, so we
+| |
+o |  changeset:   669:9cc276a2e325
+| |  user:        hecht
+| |  date:        Mon Jan 24 11:28:11 2005 +0100
+| |  summary:     add  named parameter nbtx=..  in buildmesh  function to change the default
+| |
+o |  changeset:   668:537fe1f99bce
+| |  user:        hecht
+| |  date:        Thu Jan 20 20:10:32 2005 +0100
+| |  summary:     Correct a segfault if second derivative of test function exist in
+| |
+o |  changeset:   667:28c10d87f954
+| |  user:        hecht
+| |  date:        Thu Jan 20 10:39:37 2005 +0100
+| |  summary:     correct parameter passing () in macro argument
+| |
+o |  changeset:   666:1fe91a34d57d
+| |  user:        hecht
+| |  date:        Mon Jan 10 22:19:58 2005 +0100
+| |  summary:     change c i C in speedtest.sh to get Cholesky cpu time
+| |
+o |  changeset:   665:83ad7c4f24b2
+| |  user:        hecht
+| |  date:        Mon Jan 10 14:03:31 2005 +0100
+| |  summary:     add forgotten file .pdf
+| |
+o |  changeset:   664:7e72fe09da35
+| |  user:        hecht
+| |  date:        Mon Jan 10 12:07:32 2005 +0100
+| |  summary:     window problem continue
+| |
+o |  changeset:   663:b54ebd871dac
+| |  user:        hecht
+| |  date:        Mon Jan 10 10:41:17 2005 +0100
+| |  summary:     correct ????  configure.ac under window
+| |
+o |  changeset:   662:f9abd9543d11
+| |  user:        hecht
+| |  date:        Fri Jan 07 17:05:48 2005 +0100
+| |  summary:     correct expand string in macro
+| |
+o |  changeset:   661:cb5b6ce9fa18
+| |  user:        hecht
+| |  date:        Fri Jan 07 15:55:01 2005 +0100
+| |  summary:     add config.h.in
+| |
+o |  changeset:   660:71ef61f93962
+| |  user:        lehyaric
+| |  date:        Fri Jan 07 12:25:23 2005 +0100
+| |  summary:     Cosmetic change
+| |
+o |  changeset:   659:1454bcfaa242
+| |  user:        hecht
+| |  date:        Fri Jan 07 11:50:08 2005 +0100
+| |  summary:     correct initialisation in solve in case of un set variable
+| |
+o |  changeset:   658:944f60fe0af4
+| |  user:        hecht
+| |  date:        Thu Jan 06 21:58:33 2005 +0100
+| |  summary:     rewrite the macro generation tool to be more to suppress some bug
+| |
+o |  changeset:   657:27abad54b320
+| |  user:        hecht
+| |  date:        Wed Jan 05 23:10:20 2005 +0100
+| |  summary:     update HISTORY file
+| |
+o |  changeset:   656:4de99db8c363
+| |  user:        hecht
+| |  date:        Wed Jan 05 21:50:59 2005 +0100
+| |  summary:     correct segmentation violation  error if
+| |
+o |  changeset:   655:6a65a4351cc6
+| |  user:        hecht
+| |  date:        Tue Jan 04 16:58:02 2005 +0100
+| |  summary:     continuing       int1d(Th,3,qfe=qf1pElump)(
+| |
+o |  changeset:   654:bb8f41ed79bf
+| |  user:        hecht
+| |  date:        Tue Jan 04 16:45:19 2005 +0100
+| |  summary:     add qf1pElump   new quadrature formular in int1d() ...
+| |
+o |  changeset:   653:75e427064019
+| |  user:        hecht
+| |  date:        Wed Dec 29 11:16:11 2004 +0100
+| |  summary:     add concat operator in macro generation #
+| |
+o |  changeset:   652:8dfd9dc97215
+| |  user:        hecht
+| |  date:        Tue Dec 21 18:24:43 2004 +0100
+| |  summary:     add mkff-html.pl file to update the web page.
+| |
+o |  changeset:   651:be477b2a559c
+| |  user:        lehyaric
+| |  date:        Fri Dec 17 17:22:52 2004 +0100
+| |  summary:     Windows package including correction for Mingw -mthreads bug
+| |
+o |  changeset:   650:eb12e1fe86d0
+| |  user:        lehyaric
+| |  date:        Fri Dec 17 15:40:30 2004 +0100
+| |  summary:     Bug solved: Random crashes in Windows GUI
+| |
+o |  changeset:   649:8b2c0dc489c5
+| |  user:        lehyaric
+| |  date:        Fri Dec 17 11:17:27 2004 +0100
+| |  summary:     Change naming conventions in package numbering
+| |
+o |  changeset:   648:2e4307b2394c
+| |  user:        lehyaric
+| |  date:        Thu Dec 16 10:30:07 2004 +0100
+| |  summary:     Added files to "clean-gen" goal
+| |
+o |  changeset:   647:aeba339ce574
+| |  user:        lehyaric
+| |  date:        Thu Dec 16 10:21:45 2004 +0100
+| |  summary:     Added goal "clean-gen" to clean generated files which are included in the
+| |
+o |  changeset:   646:59b4aded663b
+| |  user:        lehyaric
+| |  date:        Wed Dec 15 17:42:56 2004 +0100
+| |  summary:     Postscript output in FreeFem++-cs corrected.
+| |
+o |  changeset:   645:576d59fb636f
+| |  tag:         release_1_44
+| |  user:        hecht
+| |  date:        Sat Dec 11 15:25:14 2004 +0100
+| |  summary:     add one examples and load ide/makefile.in  file
+| |
+o |  changeset:   644:587836032d0c
+| |  user:        hecht
+| |  date:        Tue Dec 07 17:26:16 2004 +0100
+| |  summary:     put manual-full.pdf and remove manual-full.ps.gz in dist files
+| |
+o |  changeset:   643:5915ca34cea8
+| |  user:        hecht
+| |  date:        Tue Dec 07 17:19:47 2004 +0100
+| |  summary:     adding change
+| |
+o |  changeset:   642:272bdb376315
+| |  user:        hecht
+| |  date:        Tue Dec 07 16:47:49 2004 +0100
+| |  summary:     correct missing file in dist target in ide/Makefile.am
+| |
+o |  changeset:   641:943560ba14cb
+| |  user:        hecht
+| |  date:        Tue Dec 07 15:46:54 2004 +0100
+| |  summary:     add pdfsync.sty
+| |
+o |  changeset:   640:574e16fa4580
+| |  user:        hecht
+| |  date:        Tue Dec 07 15:46:54 2004 +0100
+| |  summary:     add pdfsync.sty
+| |
+o |  changeset:   639:40a0aa5074d2
+| |  user:        hecht
+| |  date:        Tue Dec 07 14:40:55 2004 +0100
+| |  summary:     correct bug in LinearGC
+| |
+o |  changeset:   638:ce9d4f35ccbe
+| |  user:        hecht
+| |  date:        Tue Dec 07 14:40:55 2004 +0100
+| |  summary:     correct bug in LinearGC
+| |
+o |  changeset:   637:5e92e098a84c
+| |  user:        hecht
+| |  date:        Tue Dec 07 14:40:55 2004 +0100
+| |  summary:     correct bug in LinearGC
+| |
+o |  changeset:   636:c503ab82d448
+| |  user:        hecht
+| |  date:        Tue Dec 07 14:40:55 2004 +0100
+| |  summary:     correct bug in LinearGC
+| |
+o |  changeset:   635:df1fe243e312
+| |  user:        hecht
+| |  date:        Tue Dec 07 14:40:55 2004 +0100
+| |  summary:     correct bug in LinearGC
+| |
+o |  changeset:   634:5992289e53d9
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   633:bac8aeda8d02
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   632:16ec15ff429e
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   631:5b20a0a70ed3
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   630:6d565e845748
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   629:8c4834a72c8d
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   628:3a567543a457
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   627:1e538d357736
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   626:14c9bd5aa671
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   625:d3e8ab784f54
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   624:078931338411
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   623:6989fe9dcf00
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   622:5850f2541f28
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   621:c1b6502dda0e
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   620:d42824334848
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   619:e3fb8b67aedd
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   618:5231ac489b29
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   617:1ffe14f7e205
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   616:e0e061f7cc0f
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   615:b02e93ab648f
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   614:3826ba342268
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   613:bfe77a690f22
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   612:8a623501ed79
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   611:5eb3d7779ba5
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   610:47890a9320f0
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   609:09fa91db7015
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   608:958a113e64f8
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   607:2550dc877a9e
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   606:0a9e0d2f235a
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   605:5a1f44c2fed5
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   604:fc0a897c0231
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   603:5270118bb4b3
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   602:b8f75296d692
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   601:6405ed03c906
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   600:66d5401897b2
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   599:646706f655fb
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   598:209e45a646c0
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   597:90fd37db4500
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   596:ea886dc74445
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   595:f30855db023a
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   594:01cbb9cc6471
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   593:db32e3dcb9e6
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   592:d2c95b00caa9
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   591:5dd5a8b892c5
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   590:b530f0e60945
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   589:aace165d8a5b
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   588:e7c461ccdd5e
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   587:c43a94efd8d0
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   586:04ca3feeb78f
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   585:0ff5c636ce04
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   584:301f2066aa9e
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   583:5a12dc4f399c
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   582:b7adf373f4fc
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   581:504550d55b8a
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   580:891870d5e48e
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   579:f7ba38e32a59
+| |  user:        lehyaric
+| |  date:        Mon Dec 06 16:17:29 2004 +0100
+| |  summary:     "make dist" does not try and include BLAS source files any more
+| |
+o |  changeset:   578:131067ca69b4
+| |  user:        lehyaric
+| |  date:        Fri Dec 03 15:27:32 2004 +0100
+| |  summary:     Include kernel and libc versions in linux static package name
+| |
+o |  changeset:   577:950a1b1dc850
+| |  user:        lehyaric
+| |  date:        Fri Dec 03 15:27:32 2004 +0100
+| |  summary:     Include kernel and libc versions in linux static package name
+| |
+o |  changeset:   576:dd814ba4d987
+| |  user:        lehyaric
+| |  date:        Fri Dec 03 11:48:53 2004 +0100
+| |  summary:     Wording change
+| |
+o |  changeset:   575:698d11505ca5
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 13:51:32 2004 +0100
+| |  summary:     New package for Windows done
+| |
+o |  changeset:   574:eda5ab893d90
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 13:51:32 2004 +0100
+| |  summary:     New package for Windows done
+| |
+o |  changeset:   573:655782a256ca
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 13:51:32 2004 +0100
+| |  summary:     New package for Windows done
+| |
+o |  changeset:   572:7fe59ebb535e
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 13:26:30 2004 +0100
+| |  summary:     Changed reference value for regression tests
+| |
+o |  changeset:   571:1e0b5bb8a88a
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 13:26:30 2004 +0100
+| |  summary:     Changed reference value for regression tests
+| |
+o |  changeset:   570:28917d41479d
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 13:26:30 2004 +0100
+| |  summary:     Changed reference value for regression tests
+| |
+o |  changeset:   569:f4933536ffc4
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 12:34:13 2004 +0100
+| |  summary:     Regression tests suite was not running. Corrected.
+| |
+o |  changeset:   568:e9f9444f4eec
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 12:34:13 2004 +0100
+| |  summary:     Regression tests suite was not running. Corrected.
+| |
+o |  changeset:   567:5c4ed3b5dd9d
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 12:34:13 2004 +0100
+| |  summary:     Regression tests suite was not running. Corrected.
+| |
+o |  changeset:   566:d8c0ddc9c049
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 12:24:17 2004 +0100
+| |  summary:     FreeFem++-cs works on MacOSX (uses named semaphores)
+| |
+o |  changeset:   565:9ab9aa52b004
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 11:40:45 2004 +0100
+| |  summary:     X11 shared libraries dependencies removed on Mac OS X
+| |
+o |  changeset:   564:a878e8d06b91
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 11:40:45 2004 +0100
+| |  summary:     X11 shared libraries dependencies removed on Mac OS X
+| |
+o |  changeset:   563:fcce285846eb
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 10:12:21 2004 +0100
+| |  summary:     Added FreeFem++-cs to visual regression tests
+| |
+o |  changeset:   562:d740179bde14
+| |  user:        lehyaric
+| |  date:        Thu Dec 02 10:12:21 2004 +0100
+| |  summary:     Added FreeFem++-cs to visual regression tests
+| |
+o |  changeset:   561:26808676972f
+| |  user:        lehyaric
+| |  date:        Wed Dec 01 18:10:45 2004 +0100
+| |  summary:     - Tuned regression tests in examples++-tutorial (convect-apt.edp case)
+| |
+o |  changeset:   560:83c213085ce7
+| |  user:        lehyaric
+| |  date:        Wed Dec 01 18:10:45 2004 +0100
+| |  summary:     - Tuned regression tests in examples++-tutorial (convect-apt.edp case)
+| |
+o |  changeset:   559:053dbd4ba446
+| |  user:        lehyaric
+| |  date:        Wed Dec 01 18:10:45 2004 +0100
+| |  summary:     - Tuned regression tests in examples++-tutorial (convect-apt.edp case)
+| |
+o |  changeset:   558:8139a67a3970
+| |  user:        lehyaric
+| |  date:        Wed Dec 01 18:10:45 2004 +0100
+| |  summary:     - Tuned regression tests in examples++-tutorial (convect-apt.edp case)
+| |
+o |  changeset:   557:9f492b691c47
+| |  user:        lehyaric
+| |  date:        Wed Dec 01 18:10:45 2004 +0100
+| |  summary:     - Tuned regression tests in examples++-tutorial (convect-apt.edp case)
+| |
+o |  changeset:   556:2ab99a6f771a
+| |  user:        hecht
+| |  date:        Tue Nov 30 22:00:45 2004 +0100
+| |  summary:     remove operation g - A*x -b ; => bug in opt version
+| |
+o |  changeset:   555:b9e70adbbe36
+| |  user:        lehyaric
+| |  date:        Tue Nov 30 17:18:15 2004 +0100
+| |  summary:     Application icons now work on Windows
+| |
+o |  changeset:   554:8fc116e186d6
+| |  user:        hecht
+| |  date:        Tue Nov 30 17:08:59 2004 +0100
+| |  summary:     change 1 un 1. du to complex varf (ambiguity)
+| |
+o |  changeset:   553:8838777e7a31
+| |  user:        hecht
+| |  date:        Tue Nov 30 17:00:57 2004 +0100
+| |  summary:     correct small compile error
+| |
+o |  changeset:   552:c187b5186fe1
+| |  user:        lehyaric
+| |  date:        Tue Nov 30 13:43:12 2004 +0100
+| |  summary:     Added X-Windows icon to FreeFem++-cs
+| |
+o |  changeset:   551:b157b8570234
+| |  user:        hecht
+| |  date:        Mon Nov 29 22:23:28 2004 +0100
+| |  summary:     Correction dans matrixinterpole
+| |
+o |  changeset:   550:cb5e794dd229
+| |  user:        hecht
+| |  date:        Mon Nov 29 22:23:28 2004 +0100
+| |  summary:     Correction dans matrixinterpole
+| |
+o |  changeset:   549:f3c219716b61
+| |  user:        hecht
+| |  date:        Mon Nov 29 22:23:28 2004 +0100
+| |  summary:     Correction dans matrixinterpole
+| |
+o |  changeset:   548:38b6ad03bc0a
+| |  user:        hecht
+| |  date:        Mon Nov 29 22:23:28 2004 +0100
+| |  summary:     Correction dans matrixinterpole
+| |
+o |  changeset:   547:aaa46419f2f2
+| |  user:        hecht
+| |  date:        Mon Nov 29 22:23:28 2004 +0100
+| |  summary:     Correction dans matrixinterpole
+| |
+o |  changeset:   546:a1b12d942392
+| |  user:        lehyaric
+| |  date:        Fri Nov 26 16:54:09 2004 +0100
+| |  summary:     New debian package (1.44-8)
+| |
+o |  changeset:   545:5afcd79492c7
+| |  user:        lehyaric
+| |  date:        Fri Nov 26 16:52:47 2004 +0100
+| |  summary:     Remove -mpich version from Debian packages since mpich Debian unstable
+| |
+o |  changeset:   544:decd403ecbfc
+| |  user:        lehyaric
+| |  date:        Fri Nov 26 15:18:49 2004 +0100
+| |  summary:     Windows packaging modified to improve icons management
+| |
+o |  changeset:   543:2bd172a33dc9
+| |  user:        lehyaric
+| |  date:        Fri Nov 26 15:18:49 2004 +0100
+| |  summary:     Windows packaging modified to improve icons management
+| |
+o |  changeset:   542:a204e168b37a
+| |  user:        lehyaric
+| |  date:        Fri Nov 26 11:15:21 2004 +0100
+| |  summary:     Including FreeFem++-cs in the Windows packaging
+| |
+o |  changeset:   541:4392d747f871
+| |  user:        lehyaric
+| |  date:        Thu Nov 25 16:25:05 2004 +0100
+| |  summary:     FreeFem++-cs compiles on Windows _without_ Cygwin
+| |
+o |  changeset:   540:16055790185c
+| |  user:        lehyaric
+| |  date:        Thu Nov 25 10:35:48 2004 +0100
+| |  summary:     Recompiled on Linux (Debian unstable).
+| |
+o |  changeset:   539:c9b0bf01408e
+| |  user:        lehyaric
+| |  date:        Wed Nov 24 14:46:42 2004 +0100
+| |  summary:     FreeFem++-cs currently being compiled without Cygwin (because of license problems)
+| |
+o |  changeset:   538:434fa9c44e79
+| |  user:        lehyaric
+| |  date:        Wed Nov 24 14:46:42 2004 +0100
+| |  summary:     FreeFem++-cs currently being compiled without Cygwin (because of license problems)
+| |
+o |  changeset:   537:052a46e28339
+| |  user:        lehyaric
+| |  date:        Tue Nov 23 16:51:22 2004 +0100
+| |  summary:     We need cygwin1.dll for FreeFem++-cs
+| |
+o |  changeset:   536:e51479949d96
+| |  user:        lehyaric
+| |  date:        Tue Nov 23 16:39:56 2004 +0100
+| |  summary:     FreeFem++-cs works on Windows
+| |
+o |  changeset:   535:c842a897de0b
+| |  user:        lehyaric
+| |  date:        Tue Nov 23 11:06:29 2004 +0100
+| |  summary:     Cosmetic changes
+| |
+o |  changeset:   534:e1be96666c98
+| |  user:        lehyaric
+| |  date:        Mon Nov 22 17:00:15 2004 +0100
+| |  summary:     New binary package for Linux, containing static executables (configure option
+| |
+o |  changeset:   533:c5565ad73ac7
+| |  user:        lehyaric
+| |  date:        Mon Nov 22 17:00:15 2004 +0100
+| |  summary:     New binary package for Linux, containing static executables (configure option
+| |
+o |  changeset:   532:2366c7044750
+| |  user:        lehyaric
+| |  date:        Mon Nov 22 17:00:15 2004 +0100
+| |  summary:     New binary package for Linux, containing static executables (configure option
+| |
+o |  changeset:   531:c4392eca0236
+| |  user:        lehyaric
+| |  date:        Mon Nov 22 15:09:18 2004 +0100
+| |  summary:     New Linux binary package
+| |
+o |  changeset:   530:537a21528272
+| |  user:        lehyaric
+| |  date:        Mon Nov 22 14:11:11 2004 +0100
+| |  summary:     Added new configure option --enable-static to have no shared library
+| |
+o |  changeset:   529:13717f3277b3
+| |  user:        lehyaric
+| |  date:        Mon Nov 22 14:11:11 2004 +0100
+| |  summary:     Added new configure option --enable-static to have no shared library
+| |
+o |  changeset:   528:7960aa03c7c8
+| |  user:        lehyaric
+| |  date:        Mon Nov 22 14:11:11 2004 +0100
+| |  summary:     Added new configure option --enable-static to have no shared library
+| |
+o |  changeset:   527:84887e26fa7d
+| |  user:        lehyaric
+| |  date:        Fri Nov 19 15:41:21 2004 +0100
+| |  summary:     Renamed MPI Debian package from -mpi to -mpich to reflect the fact that
+| |
+o |  changeset:   526:271f7c1e38d5
+| |  user:        lehyaric
+| |  date:        Fri Nov 19 15:41:21 2004 +0100
+| |  summary:     Renamed MPI Debian package from -mpi to -mpich to reflect the fact that
+| |
+o |  changeset:   525:48e68d852cb9
+| |  user:        lehyaric
+| |  date:        Fri Nov 19 12:29:07 2004 +0100
+| |  summary:     Added rules to create a Debian package with mpich
+| |
+o |  changeset:   524:824d648c04a3
+| |  user:        lehyaric
+| |  date:        Fri Nov 19 12:29:07 2004 +0100
+| |  summary:     Added rules to create a Debian package with mpich
+| |
+o |  changeset:   523:a5edb3078853
+| |  user:        lehyaric
+| |  date:        Fri Nov 19 10:57:49 2004 +0100
+| |  summary:     More precise build dependencies for Debian package
+| |
+o |  changeset:   522:59f57df9fae0
+| |  user:        lehyaric
+| |  date:        Thu Nov 18 11:05:11 2004 +0100
+| |  summary:     Added profiling option for configure.ac
+| |
+o |  changeset:   521:316f11a303d2
+| |  user:        lehyaric
+| |  date:        Thu Nov 18 11:03:39 2004 +0100
+| |  summary:     Added possibility to create separate packages for Debian testing and unstable.
+| |
+o |  changeset:   520:f0095131b64f
+| |  user:        lehyaric
+| |  date:        Thu Nov 18 11:03:39 2004 +0100
+| |  summary:     Added possibility to create separate packages for Debian testing and unstable.
+| |
+o |  changeset:   519:718ca74c8d16
+| |  user:        lehyaric
+| |  date:        Thu Nov 18 11:03:39 2004 +0100
+| |  summary:     Added possibility to create separate packages for Debian testing and unstable.
+| |
+o |  changeset:   518:9d89d076190d
+| |  user:        lehyaric
+| |  date:        Wed Nov 17 15:37:02 2004 +0100
+| |  summary:     Default Debian package set to -x11
+| |
+o |  changeset:   517:bdf44e6aba20
+| |  user:        lehyaric
+| |  date:        Wed Nov 17 14:28:50 2004 +0100
+| |  summary:     Updated IDE TODO list
+| |
+o |  changeset:   516:517c1471cf2e
+| |  user:        lehyaric
+| |  date:        Wed Nov 17 12:13:22 2004 +0100
+| |  summary:     Debian package (unstable) for FreeFem++ is ready
+| |
+o |  changeset:   515:eaeb26d2dac2
+| |  user:        lehyaric
+| |  date:        Wed Nov 17 12:13:22 2004 +0100
+| |  summary:     Debian package (unstable) for FreeFem++ is ready
+| |
+o |  changeset:   514:721ef4ae9791
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 17:18:16 2004 +0100
+| |  summary:     Debian packages curently being built. Not fully operational yet.
+| |
+o |  changeset:   513:48d1d0bda2c4
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:39:50 2004 +0100
+| |  summary:     Makes doc up-to-date with IDE.
+| |
+o |  changeset:   512:8ab392a78e7a
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   511:37b96d6a550d
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   510:e9b15663d36a
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   509:210bc8bca680
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   508:580ba532e342
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   507:edb464296e7d
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   506:ada7b140218e
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   505:fafcb50f4e5b
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   504:bcc41dd3fa8d
+| |  user:        lehyaric
+| |  date:        Tue Nov 16 15:21:14 2004 +0100
+| |  summary:     Changed macro LONG_LONG to BAMG_LONG_LONG to avoid any interference with MPI.
+| |
+o |  changeset:   503:afbb5a9e4183
+| |  user:        hecht
+| |  date:        Tue Nov 16 09:25:12 2004 +0100
+| |  summary:     correct problem in integration of complex valued function
+| |
+o |  changeset:   502:2b8521a98d74
+| |  user:        lehyaric
+| |  date:        Mon Nov 15 15:50:42 2004 +0100
+| |  summary:     A paragraph about FreeFem++-cs has been added in the documentation.
+| |
+o |  changeset:   501:12cd26fb848f
+| |  user:        lehyaric
+| |  date:        Mon Nov 15 15:50:42 2004 +0100
+| |  summary:     A paragraph about FreeFem++-cs has been added in the documentation.
+| |
+o |  changeset:   500:892e3010d175
+| |  user:        lehyaric
+| |  date:        Mon Nov 15 15:50:42 2004 +0100
+| |  summary:     A paragraph about FreeFem++-cs has been added in the documentation.
+| |
+o |  changeset:   499:e32593c3ce18
+| |  user:        lehyaric
+| |  date:        Mon Nov 15 13:56:11 2004 +0100
+| |  summary:     FreeFem++-cs compiles on Cedre (Red-Hat Enterprise)
+| |
+o |  changeset:   498:928f4a1766a4
+| |  user:        lehyaric
+| |  date:        Mon Nov 15 10:27:44 2004 +0100
+| |  summary:     Added TODO list for client/server IDE.
+| |
+o |  changeset:   497:ea21be00cbe5
+| |  user:        hecht
+| |  date:        Mon Nov 15 09:56:56 2004 +0100
+| |  summary:     orthographe in manual-full
+| |
+o |  changeset:   496:74b4301aac83
+| |  user:        hecht
+| |  date:        Fri Nov 12 08:31:27 2004 +0100
+| |  summary:     cadna intergration  continuing.
+| |
+o |  changeset:   495:0be17e76a91f
+| |  user:        hecht
+| |  date:        Fri Nov 12 08:31:26 2004 +0100
+| |  summary:     cadna intergration  continuing.
+| |
+o |  changeset:   494:a3d87f2b073c
+| |  user:        hecht
+| |  date:        Fri Nov 12 08:31:26 2004 +0100
+| |  summary:     cadna intergration  continuing.
+| |
+o |  changeset:   493:e43f5465f202
+| |  user:        hecht
+| |  date:        Fri Nov 12 08:31:26 2004 +0100
+| |  summary:     cadna intergration  continuing.
+| |
+o |  changeset:   492:30be56d8661d
+| |  user:        lehyaric
+| |  date:        Thu Nov 11 19:45:49 2004 +0100
+| |  summary:     Progressively debugging the IDE and making it usable.
+| |
+o |  changeset:   491:e2c6e9ede5d9
+| |  user:        lehyaric
+| |  date:        Wed Nov 10 20:12:16 2004 +0100
+| |  summary:     Some corrections for Cygwin configuration of the IDE.
+| |
+o |  changeset:   490:eb18a25a60ea
+| |  user:        lehyaric
+| |  date:        Wed Nov 10 12:38:16 2004 +0100
+| |  summary:     Integrating Windows+Cygwin changes back into Linux.
+| |
+o |  changeset:   489:11ff79651895
+| |  user:        lehyaric
+| |  date:        Wed Nov 10 10:48:49 2004 +0100
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   488:62a7ee053207
+| |  user:        lehyaric
+| |  date:        Tue Nov 09 16:54:04 2004 +0100
+| |  summary:     There was a problem with downloaded BLAS source: it was included in
+| |
+o |  changeset:   487:5d76a60fb602
+| |  user:        hecht
+| |  date:        Tue Nov 09 16:23:12 2004 +0100
+| |  summary:     add interface with cadna
+| |
+o |  changeset:   486:17496d99e45f
+| |  user:        lehyaric
+| |  date:        Tue Nov 09 15:47:10 2004 +0100
+| |  summary:     Windows version of FreeFem++ client/server IDE currently being
+| |
+o |  changeset:   485:6290d8ecd8c1
+| |  user:        lehyaric
+| |  date:        Tue Nov 09 15:47:10 2004 +0100
+| |  summary:     Windows version of FreeFem++ client/server IDE currently being
+| |
+o |  changeset:   484:f926e0479ac8
+| |  user:        lehyaric
+| |  date:        Tue Nov 09 15:47:10 2004 +0100
+| |  summary:     Windows version of FreeFem++ client/server IDE currently being
+| |
+o |  changeset:   483:6d4dfaef560c
+| |  user:        lehyaric
+| |  date:        Mon Nov 08 17:21:45 2004 +0100
+| |  summary:     FreeFem++ compiles on MacOSX. But it has not been tested yet.
+| |
+o |  changeset:   482:a7750c9f311e
+| |  user:        lehyaric
+| |  date:        Mon Nov 08 17:21:45 2004 +0100
+| |  summary:     FreeFem++ compiles on MacOSX. But it has not been tested yet.
+| |
+o |  changeset:   481:fb4eebbf4886
+| |  user:        lehyaric
+| |  date:        Mon Nov 08 15:02:28 2004 +0100
+| |  summary:     First stable version for the Integrated Development Environment
+| |
+o |  changeset:   480:3c1e6d4bc2a2
+| |  user:        lehyaric
+| |  date:        Mon Nov 08 15:02:28 2004 +0100
+| |  summary:     First stable version for the Integrated Development Environment
+| |
+o |  changeset:   479:6a6dfeccf617
+| |  user:        lehyaric
+| |  date:        Mon Nov 08 15:02:28 2004 +0100
+| |  summary:     First stable version for the Integrated Development Environment
+| |
+o |  changeset:   478:fca74d661274
+| |  user:        lehyaric
+| |  date:        Mon Nov 08 15:02:28 2004 +0100
+| |  summary:     First stable version for the Integrated Development Environment
+| |
+o |  changeset:   477:6f5f852316f2
+| |  user:        lehyaric
+| |  date:        Mon Nov 08 15:02:28 2004 +0100
+| |  summary:     First stable version for the Integrated Development Environment
+| |
+o |  changeset:   476:2a9e2f6e8da4
+| |  user:        hecht
+| |  date:        Fri Nov 05 20:58:24 2004 +0100
+| |  summary:     coorect bug in FreeFem++.app the plist file was wrong.x
+| |
+o |  changeset:   475:2130890a279c
+| |  user:        hecht
+| |  date:        Fri Nov 05 20:58:24 2004 +0100
+| |  summary:     coorect bug in FreeFem++.app the plist file was wrong.x
+| |
+o |  changeset:   474:15a22358864b
+| |  user:        hecht
+| |  date:        Fri Nov 05 17:22:45 2004 +0100
+| |  summary:     rm ./FreeFem++.app/Contents/Resources/Contents/Info.plist
+| |
+o |  changeset:   473:78d50e8ca9b3
+| |  user:        hecht
+| |  date:        Fri Nov 05 15:01:51 2004 +0100
+| |  summary:     add install www files
+| |
+o |  changeset:   472:deb301bad9ed
+| |  user:        hecht
+| |  date:        Fri Nov 05 15:01:51 2004 +0100
+| |  summary:     add install www files
+| |
+o |  changeset:   471:d329085d2ad9
+| |  user:        hecht
+| |  date:        Fri Nov 05 15:01:51 2004 +0100
+| |  summary:     add install www files
+| |
+o |  changeset:   470:b469c835a383
+| |  user:        hecht
+| |  date:        Thu Nov 04 11:05:46 2004 +0100
+| |  summary:     small modif  for the look
+| |
+o |  changeset:   469:ab1f51259bd0
+| |  user:        hecht
+| |  date:        Thu Nov 04 10:38:27 2004 +0100
+| |  summary:     corret small problem in LinearCG LinearGMRES
+| |
+o |  changeset:   468:1acbc778abf2
+| |  user:        hecht
+| |  date:        Thu Nov 04 10:38:27 2004 +0100
+| |  summary:     corret small problem in LinearCG LinearGMRES
+| |
+o |  changeset:   467:0ab12962b0fd
+| |  user:        hecht
+| |  date:        Thu Nov 04 10:38:27 2004 +0100
+| |  summary:     corret small problem in LinearCG LinearGMRES
+| |
+o |  changeset:   466:f7e922b5c47b
+| |  user:        hecht
+| |  date:        Thu Nov 04 10:38:27 2004 +0100
+| |  summary:     corret small problem in LinearCG LinearGMRES
+| |
+o |  changeset:   465:7538f84816f9
+| |  user:        hecht
+| |  date:        Thu Nov 04 10:38:27 2004 +0100
+| |  summary:     corret small problem in LinearCG LinearGMRES
+| |
+o |  changeset:   464:c7ebd094ec65
+| |  user:        hecht
+| |  date:        Mon Nov 01 17:05:20 2004 +0100
+| |  summary:     continuing regtest
+| |
+o |  changeset:   463:11e517877eef
+| |  user:        hecht
+| |  date:        Mon Nov 01 17:00:51 2004 +0100
+| |  summary:     correct stability of regtest
+| |
+o |  changeset:   462:dd06f300568d
+| |  user:        hecht
+| |  date:        Mon Nov 01 16:29:42 2004 +0100
+| |  summary:     correct regtest in examples++
+| |
+o |  changeset:   461:1683f7035054
+| |  user:        hecht
+| |  date:        Mon Nov 01 15:22:16 2004 +0100
+| |  summary:     correct sensibility problem in regtest value
+| |
+o |  changeset:   460:390f8dccddda
+| |  user:        hecht
+| |  date:        Mon Nov 01 15:22:16 2004 +0100
+| |  summary:     correct sensibility problem in regtest value
+| |
+o |  changeset:   459:3267ae14952a
+| |  user:        hecht
+| |  date:        Mon Nov 01 14:34:06 2004 +0100
+| |  summary:     beginning  of 1.44 version
+| |
+o |  changeset:   458:2e4939dc785d
+| |  tag:         release_1_43
+| |  user:        hecht
+| |  date:        Sun Oct 31 21:45:57 2004 +0100
+| |  summary:     correct probleme in periodic adapted mesh.
+| |
+o |  changeset:   457:207421f2a7e8
+| |  user:        hecht
+| |  date:        Sun Oct 31 21:45:57 2004 +0100
+| |  summary:     correct probleme in periodic adapted mesh.
+| |
+o |  changeset:   456:200a55791940
+| |  user:        hecht
+| |  date:        Fri Oct 22 22:53:17 2004 +0200
+| |  summary:     correct the sparce-cmatrix.edp problem (bug in copy construct of
+| |
+o |  changeset:   455:7e279b9438e3
+| |  user:        hecht
+| |  date:        Fri Oct 22 22:53:17 2004 +0200
+| |  summary:     correct the sparce-cmatrix.edp problem (bug in copy construct of
+| |
+o |  changeset:   454:d6da0ddeb280
+| |  user:        hecht
+| |  date:        Fri Oct 22 22:13:10 2004 +0200
+| |  summary:     correct plus in copy of real matrix to complex Z
+| |
+o |  changeset:   453:b8318a5e063d
+| |  user:        hecht
+| |  date:        Fri Oct 22 20:55:10 2004 +0200
+| |  summary:     try correct probleme with sparce_cmatrix.edp on hydre
+| |
+o |  changeset:   452:ee654e2bf51f
+| |  user:        hecht
+| |  date:        Fri Oct 22 17:40:01 2004 +0200
+| |  summary:     track a bug in complex matrix
+| |
+o |  changeset:   451:1ec19015b7a7
+| |  user:        hecht
+| |  date:        Fri Oct 22 13:17:13 2004 +0200
+| |  summary:     correct spelling in Makefile.am
+| |
+o |  changeset:   450:81af913867db
+| |  user:        hecht
+| |  date:        Fri Oct 22 13:13:57 2004 +0200
+| |  summary:     correct missing file in dist TARGET
+| |
+o |  changeset:   449:4ebc66387841
+| |  user:        hecht
+| |  date:        Thu Oct 21 23:30:26 2004 +0200
+| |  summary:     correct LD_LIBRARY_PATH in regtests.sh
+| |
+o |  changeset:   448:ae67b79318c9
+| |  user:        hecht
+| |  date:        Thu Oct 21 19:53:59 2004 +0200
+| |  summary:     correct compilation probleme with g++-3.4
+| |
+o |  changeset:   447:210d3e06f92d
+| |  user:        hecht
+| |  date:        Thu Oct 21 11:04:46 2004 +0200
+| |  summary:     olve pb of case in filename if figure dir
+| |
+o |  changeset:   446:b5fa749a5bc9
+| |  user:        hecht
+| |  date:        Thu Oct 21 11:04:46 2004 +0200
+| |  summary:     olve pb of case in filename if figure dir
+| |
+o |  changeset:   445:76207b73fd90
+| |  user:        hecht
+| |  date:        Thu Oct 21 11:04:46 2004 +0200
+| |  summary:     olve pb of case in filename if figure dir
+| |
+o |  changeset:   444:bd6dac9e9094
+| |  user:        hecht
+| |  date:        Thu Oct 21 10:51:25 2004 +0200
+| |  summary:     add info in README_CVS  update -d
+| |
+o |  changeset:   443:3454b8d74eb1
+| |  user:        hecht
+| |  date:        Thu Oct 21 10:47:18 2004 +0200
+| |  summary:     full manual continuing
+| |
+o |  changeset:   442:425302deea0d
+| |  user:        hecht
+| |  date:        Thu Oct 21 10:37:25 2004 +0200
+| |  summary:     change  default manual to manual-full
+| |
+o |  changeset:   441:930731f1e671
+| |  user:        hecht
+| |  date:        Thu Oct 21 09:56:57 2004 +0200
+| |  summary:     add forgetted file
+| |
+o |  changeset:   440:90b421243e49
+| |  user:        hecht
+| |  date:        Thu Oct 21 09:55:46 2004 +0200
+| |  summary:     correct ps generation n tag
+| |
+o |  changeset:   439:054a6408443f
+| |  user:        hecht
+| |  date:        Thu Oct 21 08:26:40 2004 +0200
+| |  summary:     correct problem AssembleVarForm compile with -O3 in hydre
+| |
+o |  changeset:   438:10d97062e606
+| |  user:        lehyaric
+| |  date:        Wed Oct 20 17:26:48 2004 +0200
+| |  summary:     Updates for building debian packages.
+| |
+o |  changeset:   437:6b4d454f052c
+| |  user:        hecht
+| |  date:        Wed Oct 20 13:52:12 2004 +0200
+| |  summary:     correct print in UMFPack driver
+| |
+o |  changeset:   436:5d7b015d6b6a
+| |  user:        hecht
+| |  date:        Wed Oct 20 12:01:16 2004 +0200
+| |  summary:     add inquire of FE space connectivite (see HISTRY file)
+| |
+o |  changeset:   435:77ee9f17989a
+| |  user:        hecht
+| |  date:        Wed Oct 20 12:01:16 2004 +0200
+| |  summary:     add inquire of FE space connectivite (see HISTRY file)
+| |
+o |  changeset:   434:645fa4d8d41e
+| |  user:        hecht
+| |  date:        Wed Oct 20 12:01:16 2004 +0200
+| |  summary:     add inquire of FE space connectivite (see HISTRY file)
+| |
+o |  changeset:   433:fe1cf8c01674
+| |  user:        hecht
+| |  date:        Tue Oct 19 23:31:24 2004 +0200
+| |  summary:     correct bug in UMFPACK driver
+| |
+o |  changeset:   432:db150de11f10
+| |  user:        hecht
+| |  date:        Tue Oct 19 23:31:24 2004 +0200
+| |  summary:     correct bug in UMFPACK driver
+| |
+o |  changeset:   431:086194a0bc97
+| |  user:        hecht
+| |  date:        Tue Oct 19 23:31:24 2004 +0200
+| |  summary:     correct bug in UMFPACK driver
+| |
+o |  changeset:   430:143a3895671e
+| |  user:        hecht
+| |  date:        Tue Oct 19 23:31:24 2004 +0200
+| |  summary:     correct bug in UMFPACK driver
+| |
+o |  changeset:   429:68b5cd5a87d4
+| |  user:        hecht
+| |  date:        Tue Oct 19 23:31:24 2004 +0200
+| |  summary:     correct bug in UMFPACK driver
+| |
+o |  changeset:   428:8e95b761bae5
+| |  user:        hecht
+| |  date:        Wed Oct 13 21:49:56 2004 +0200
+| |  summary:     correct line numbering probleme (lose the first line)
+| |
+o |  changeset:   427:25a98f711d0b
+| |  user:        hecht
+| |  date:        Wed Oct 13 21:49:56 2004 +0200
+| |  summary:     correct line numbering probleme (lose the first line)
+| |
+o |  changeset:   426:144820ccdbd5
+| |  user:        hecht
+| |  date:        Wed Oct 13 18:12:27 2004 +0200
+| |  summary:     remove accent in GC routine
+| |
+o |  changeset:   425:1732ce8c01d8
+| |  user:        hecht
+| |  date:        Wed Oct 13 18:12:27 2004 +0200
+| |  summary:     remove accent in GC routine
+| |
+o |  changeset:   424:1b5098389948
+| |  user:        hecht
+| |  date:        Tue Oct 12 21:38:18 2004 +0200
+| |  summary:     reput previous version (wrong test)
+| |
+o |  changeset:   423:5638a3f80a88
+| |  user:        hecht
+| |  date:        Tue Oct 12 20:59:32 2004 +0200
+| |  summary:     correct probleme in A*x for full matrix
+| |
+o |  changeset:   422:94c1cfab9672
+| |  user:        hecht
+| |  date:        Tue Oct 12 07:28:35 2004 +0200
+| |  summary:     add file src/fflib/lgmat.cpp
+| |
+o |  changeset:   421:e63cf99645a9
+| |  user:        hecht
+| |  date:        Mon Oct 11 21:31:47 2004 +0200
+| |  summary:     complex pde , FE complex function, add complex matrix , first test is
+| |
+o |  changeset:   420:9cab4d0aa69c
+| |  user:        hecht
+| |  date:        Mon Oct 11 21:31:47 2004 +0200
+| |  summary:     complex pde , FE complex function, add complex matrix , first test is
+| |
+o |  changeset:   419:515fd7b96b9f
+| |  user:        hecht
+| |  date:        Mon Oct 11 21:31:47 2004 +0200
+| |  summary:     complex pde , FE complex function, add complex matrix , first test is
+| |
+o |  changeset:   418:79b744606bae
+| |  user:        hecht
+| |  date:        Mon Oct 11 21:31:47 2004 +0200
+| |  summary:     complex pde , FE complex function, add complex matrix , first test is
+| |
+o |  changeset:   417:5bd8386dcd01
+| |  user:        hecht
+| |  date:        Mon Oct 11 21:31:47 2004 +0200
+| |  summary:     complex pde , FE complex function, add complex matrix , first test is
+| |
+o |  changeset:   416:97e71f66af70
+| |  user:        hecht
+| |  date:        Fri Oct 08 18:39:13 2004 +0200
+| |  summary:     complex matrix continuing
+| |
+o |  changeset:   415:f137b9a8fc5c
+| |  user:        hecht
+| |  date:        Fri Oct 08 18:39:13 2004 +0200
+| |  summary:     complex matrix continuing
+| |
+o |  changeset:   414:ebfebb1ac5fc
+| |  user:        hecht
+| |  date:        Fri Oct 08 18:39:13 2004 +0200
+| |  summary:     complex matrix continuing
+| |
+o |  changeset:   413:04eb8a6f2984
+| |  user:        hecht
+| |  date:        Fri Oct 08 18:39:13 2004 +0200
+| |  summary:     complex matrix continuing
+| |
+o |  changeset:   412:a22c9b627343
+| |  user:        hecht
+| |  date:        Wed Oct 06 22:24:56 2004 +0200
+| |  summary:     add a pde complex example
+| |
+o |  changeset:   411:a4b5781ae40c
+| |  user:        hecht
+| |  date:        Wed Oct 06 22:22:05 2004 +0200
+| |  summary:     pde complex , continuing:   first test is now working
+| |
+o |  changeset:   410:bcac253cb61b
+| |  user:        hecht
+| |  date:        Wed Oct 06 22:22:05 2004 +0200
+| |  summary:     pde complex , continuing:   first test is now working
+| |
+o |  changeset:   409:8979601bdc85
+| |  user:        hecht
+| |  date:        Tue Oct 05 21:29:04 2004 +0200
+| |  summary:     complex pde probleme   ( first test) no validation
+| |
+o |  changeset:   408:256c59f10590
+| |  user:        hecht
+| |  date:        Tue Oct 05 21:29:04 2004 +0200
+| |  summary:     complex pde probleme   ( first test) no validation
+| |
+o |  changeset:   407:7d2cf3182e76
+| |  user:        hecht
+| |  date:        Tue Oct 05 21:29:04 2004 +0200
+| |  summary:     complex pde probleme   ( first test) no validation
+| |
+o |  changeset:   406:e95d0ba6b7e3
+| |  user:        hecht
+| |  date:        Tue Oct 05 21:29:04 2004 +0200
+| |  summary:     complex pde probleme   ( first test) no validation
+| |
+o |  changeset:   405:70e5cbe6ea2d
+| |  user:        hecht
+| |  date:        Tue Oct 05 21:29:04 2004 +0200
+| |  summary:     complex pde probleme   ( first test) no validation
+| |
+o |  changeset:   404:44a92d96dedf
+| |  user:        hecht
+| |  date:        Tue Oct 05 21:29:04 2004 +0200
+| |  summary:     complex pde probleme   ( first test) no validation
+| |
+o |  changeset:   403:d6f723e155cb
+| |  user:        hecht
+| |  date:        Tue Oct 05 21:29:04 2004 +0200
+| |  summary:     complex pde probleme   ( first test) no validation
+| |
+o |  changeset:   402:3c4ce746b967
+| |  user:        lehyaric
+| |  date:        Tue Oct 05 15:30:13 2004 +0200
+| |  summary:     Added reduced compilation goal "quick" for development purposes.
+| |
+o |  changeset:   401:b2003bc088ca
+| |  user:        hecht
+| |  date:        Mon Oct 04 10:22:29 2004 +0200
+| |  summary:     add complex edp (continued)
+| |
+o |  changeset:   400:397c36b4b309
+| |  user:        hecht
+| |  date:        Thu Sep 30 14:50:25 2004 +0200
+| |  summary:     add complex FE function
+| |
+o |  changeset:   399:887c12889698
+| |  user:        hecht
+| |  date:        Thu Sep 30 14:50:25 2004 +0200
+| |  summary:     add complex FE function
+| |
+o |  changeset:   398:2f52a8427674
+| |  user:        hecht
+| |  date:        Thu Sep 30 14:50:25 2004 +0200
+| |  summary:     add complex FE function
+| |
+o |  changeset:   397:e83e3edd173f
+| |  user:        hecht
+| |  date:        Thu Sep 30 14:50:25 2004 +0200
+| |  summary:     add complex FE function
+| |
+o |  changeset:   396:a5d848d61a8c
+| |  user:        hecht
+| |  date:        Thu Sep 30 14:50:25 2004 +0200
+| |  summary:     add complex FE function
+| |
+o |  changeset:   395:54aee94d12a5
+| |  user:        hecht
+| |  date:        Thu Sep 30 14:50:25 2004 +0200
+| |  summary:     add complex FE function
+| |
+o |  changeset:   394:82ccf1be8da9
+| |  user:        hecht
+| |  date:        Thu Sep 30 14:50:25 2004 +0200
+| |  summary:     add complex FE function
+| |
+o |  changeset:   393:8057e10dedca
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:41 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   392:6af43ced4bae
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:41 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   391:567799ab94cb
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:41 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   390:abb85c03c031
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:41 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   389:fe223eb326cd
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:40 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   388:4ca7990a291d
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:40 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   387:933bb1d0a477
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:40 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   386:5a2434bfc31b
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:40 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   385:72b317a18586
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:40 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   384:01a48ef68149
+| |  user:        hecht
+| |  date:        Tue Sep 28 10:58:40 2004 +0200
+| |  summary:     add new manual call manual-full
+| |
+o |  changeset:   383:dc00fa274e76
+| |  user:        lehyaric
+| |  date:        Fri Sep 17 17:29:29 2004 +0200
+| |  summary:     More information about CVS commands.
+| |
+o |  changeset:   382:3d5b35158b27
+| |  user:        lehyaric
+| |  date:        Fri Sep 17 16:55:03 2004 +0200
+| |  summary:     Regression tests pass with reduced optimization options on PowerPC G5, fast
+| |
+o |  changeset:   381:fc7c2126f5c4
+| |  user:        lehyaric
+| |  date:        Fri Sep 17 16:13:25 2004 +0200
+| |  summary:     Regression tests pass again on Macintosh PPC (generic mode).
+| |
+o |  changeset:   380:6735dad5752c
+| |  user:        lehyaric
+| |  date:        Fri Sep 17 15:14:21 2004 +0200
+| |  summary:     Make regression tests work again on Macintosh PowerPC (debug mode).
+| |
+o |  changeset:   379:1f9b0349c49d
+| |  user:        lehyaric
+| |  date:        Fri Sep 17 15:14:21 2004 +0200
+| |  summary:     Make regression tests work again on Macintosh PowerPC (debug mode).
+| |
+o |  changeset:   378:ff90d81ab89d
+| |  user:        lehyaric
+| |  date:        Fri Sep 17 15:14:21 2004 +0200
+| |  summary:     Make regression tests work again on Macintosh PowerPC (debug mode).
+| |
+o |  changeset:   377:f7482dd869e3
+| |  user:        lehyaric
+| |  date:        Fri Sep 17 15:14:21 2004 +0200
+| |  summary:     Make regression tests work again on Macintosh PowerPC (debug mode).
+| |
+o |  changeset:   376:bfab63278f19
+| |  user:        lehyaric
+| |  date:        Thu Sep 16 17:24:11 2004 +0200
+| |  summary:     Still trying to find appropriate optimization options for PowerPC G5
+| |
+o |  changeset:   375:0507c2ba4f1e
+| |  user:        lehyaric
+| |  date:        Thu Sep 16 10:43:46 2004 +0200
+| |  summary:     G5 optimization options reverted to G4 because of segmentation fault
+| |
+o |  changeset:   374:cd70efe472da
+| |  user:        hecht
+| |  date:        Wed Sep 15 21:50:30 2004 +0200
+| |  summary:     split AFunction.cpp in 2 files  and remove optim option on ppc G5
+| |
+o |  changeset:   373:5da1312b3ef9
+| |  user:        hecht
+| |  date:        Wed Sep 15 21:50:30 2004 +0200
+| |  summary:     split AFunction.cpp in 2 files  and remove optim option on ppc G5
+| |
+o |  changeset:   372:72e9cd4aa1b8
+| |  user:        hecht
+| |  date:        Wed Sep 15 21:50:30 2004 +0200
+| |  summary:     split AFunction.cpp in 2 files  and remove optim option on ppc G5
+| |
+o |  changeset:   371:1ad31634c74e
+| |  user:        hecht
+| |  date:        Tue Sep 14 14:28:57 2004 +0200
+| |  summary:     correct pb set var CXX  in load.sh call in exampelle++-Makefile.am
+| |
+o |  changeset:   370:8483d008a226
+| |  user:        lehyaric
+| |  date:        Tue Sep 14 13:51:23 2004 +0200
+| |  summary:     Enables load.link work even when $CXX is not defined.
+| |
+o |  changeset:   369:3b19cf768802
+| |  user:        lehyaric
+| |  date:        Tue Sep 14 11:39:15 2004 +0200
+| |  summary:     Corrected bug preventing examples++-tutorial/regtests.m4 from being
+| |
+o |  changeset:   368:fe3f3906e950
+| |  user:        lehyaric
+| |  date:        Tue Sep 14 11:20:40 2004 +0200
+| |  summary:     More updates for FreeBSD compilation
+| |
+o |  changeset:   367:c4a119ca5c9a
+| |  user:        lehyaric
+| |  date:        Mon Sep 13 16:05:19 2004 +0200
+| |  summary:     Modification proposée par Thierry Thomas pour FreeBSD
+| |
+o |  changeset:   366:8493ed2b0f1e
+| |  user:        hecht
+| |  date:        Mon Sep 13 15:33:27 2004 +0200
+| |  summary:     correct plist version
+| |
+o |  changeset:   365:18b4482e75b8
+| |  user:        hecht
+| |  date:        Mon Sep 13 15:33:27 2004 +0200
+| |  summary:     correct plist version
+| |
+o |  changeset:   364:afb03f91b7e1
+| |  user:        hecht
+| |  date:        Mon Sep 13 15:27:09 2004 +0200
+| |  summary:     C++ encapsulte cblas.h in src/femlib/MatriceCreuse_tpl.hpp for freebsd OS
+| |
+o |  changeset:   363:613c6ccc0c5f
+| |  user:        hecht
+| |  date:        Tue Sep 07 17:43:34 2004 +0200
+| |  summary:     corret of window install
+| |
+o |  changeset:   362:8540f099b3ce
+| |  user:        hecht
+| |  date:        Tue Sep 07 16:47:58 2004 +0200
+| |  summary:     add file for MacOS application
+| |
+o |  changeset:   361:7dae94479be9
+| |  user:        lehyaric
+| |  date:        Tue Sep 07 10:37:27 2004 +0200
+| |  summary:     Regression tests in examples++ directory re-implemented using regtests.m4
+| |
+o |  changeset:   360:2d87ce153e15
+| |  user:        lehyaric
+| |  date:        Tue Sep 07 10:37:27 2004 +0200
+| |  summary:     Regression tests in examples++ directory re-implemented using regtests.m4
+| |
+o |  changeset:   359:2784c4a0bd47
+| |  user:        hecht
+| |  date:        Tue Sep 07 09:45:39 2004 +0200
+| |  summary:     correct with-blas=....  tags
+| |
+o |  changeset:   358:cf165daa0d0f
+| |  user:        hecht
+| |  date:        Tue Sep 07 09:36:07 2004 +0200
+| |  summary:     add if previous download of blas reuse it
+| |
+o |  changeset:   357:3eb4c46dcfe9
+| |  user:        hecht
+| |  date:        Tue Sep 07 09:36:07 2004 +0200
+| |  summary:     add if previous download of blas reuse it
+| |
+o |  changeset:   356:76b709dff400
+| |  user:        hecht
+| |  date:        Tue Sep 07 09:36:07 2004 +0200
+| |  summary:     add if previous download of blas reuse it
+| |
+o |  changeset:   355:5e3635850187
+| |  user:        hecht
+| |  date:        Tue Sep 07 09:36:07 2004 +0200
+| |  summary:     add if previous download of blas reuse it
+| |
+o |  changeset:   354:31bc7672aa7c
+| |  user:        hecht
+| |  date:        Tue Sep 07 09:36:07 2004 +0200
+| |  summary:     add if previous download of blas reuse it
+| |
+o |  changeset:   353:bd84364412fe
+| |  user:        hecht
+| |  date:        Mon Sep 06 16:03:02 2004 +0200
+| |  summary:     add missing file regtest.m4 in dist make target in examples++-tutorial
+| |
+o |  changeset:   352:fca5bc988b28
+| |  user:        hecht
+| |  date:        Mon Sep 06 14:00:11 2004 +0200
+| |  summary:     Add  -enable-generic_blas Download generic blas (implie --enable-download)
+| |
+o |  changeset:   351:44f079ca1e54
+| |  user:        hecht
+| |  date:        Fri Sep 03 10:45:06 2004 +0200
+| |  summary:     empty SOURCESS variable in download/blas/Makefile.am  because
+| |
+o |  changeset:   350:1e46b370a8e8
+| |  user:        hecht
+| |  date:        Thu Sep 02 16:04:15 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   349:aa868ed8a653
+| |  user:        hecht
+| |  date:        Thu Sep 02 16:04:15 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   348:ea558c405714
+| |  user:        hecht
+| |  date:        Thu Sep 02 16:04:15 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   347:e93fad9806ee
+| |  user:        hecht
+| |  date:        Thu Sep 02 16:04:15 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   346:699d36073a62
+| |  user:        hecht
+| |  date:        Wed Sep 01 13:51:05 2004 +0200
+| |  summary:     correct string[string] undelete pointer
+| |
+o |  changeset:   345:3630bf06e805
+| |  user:        hecht
+| |  date:        Wed Sep 01 13:51:05 2004 +0200
+| |  summary:     correct string[string] undelete pointer
+| |
+o |  changeset:   344:1f080b312de7
+| |  user:        hecht
+| |  date:        Wed Sep 01 13:51:05 2004 +0200
+| |  summary:     correct string[string] undelete pointer
+| |
+o |  changeset:   343:2207149cc212
+| |  user:        hecht
+| |  date:        Wed Sep 01 09:33:21 2004 +0200
+| |  summary:     expand macro problem , suite (et fin?)
+| |
+o |  changeset:   342:7f3e2e94c5dd
+| |  user:        hecht
+| |  date:        Wed Sep 01 09:33:21 2004 +0200
+| |  summary:     expand macro problem , suite (et fin?)
+| |
+o |  changeset:   341:5155e427a87d
+| |  user:        hecht
+| |  date:        Wed Sep 01 07:41:07 2004 +0200
+| |  summary:     correct pb in macro generation (not finish)
+| |
+o |  changeset:   340:c43b8c2be26a
+| |  user:        hecht
+| |  date:        Tue Aug 31 17:35:35 2004 +0200
+| |  summary:     correct  bug in macro expansion
+| |
+o |  changeset:   339:ffcff5636f12
+| |  user:        hecht
+| |  date:        Mon Aug 30 17:10:10 2004 +0200
+| |  summary:     remove blas call on MacOS 9
+| |
+o |  changeset:   338:531a39f19f63
+| |  user:        hecht
+| |  date:        Mon Aug 30 15:56:07 2004 +0200
+| |  summary:     add blas call  in choleski and LU solver
+| |
+o |  changeset:   337:4fbef75b9c75
+| |  user:        hecht
+| |  date:        Mon Aug 30 15:56:07 2004 +0200
+| |  summary:     add blas call  in choleski and LU solver
+| |
+o |  changeset:   336:411e79c1f3d1
+| |  user:        hecht
+| |  date:        Mon Aug 30 15:56:07 2004 +0200
+| |  summary:     add blas call  in choleski and LU solver
+| |
+o |  changeset:   335:db4ae64b21ff
+| |  user:        hecht
+| |  date:        Mon Aug 30 14:13:24 2004 +0200
+| |  summary:     add blas in choleski
+| |
+o |  changeset:   334:a2136058155e
+| |  user:        hecht
+| |  date:        Mon Aug 30 14:13:24 2004 +0200
+| |  summary:     add blas in choleski
+| |
+o |  changeset:   333:3026860a14e7
+| |  user:        hecht
+| |  date:        Mon Aug 30 14:13:24 2004 +0200
+| |  summary:     add blas in choleski
+| |
+o |  changeset:   332:adae49e68467
+| |  user:        hecht
+| |  date:        Mon Aug 30 14:03:27 2004 +0200
+| |  summary:     correct mpi/Makefile.am for compilation with g++-3.4
+| |
+o |  changeset:   331:d25cf7233e27
+| |  user:        hecht
+| |  date:        Mon Aug 30 13:40:48 2004 +0200
+| |  summary:     correction to by compatible wiath g++-3.4
+| |
+o |  changeset:   330:2053e59afe11
+| |  user:        hecht
+| |  date:        Mon Aug 30 13:40:48 2004 +0200
+| |  summary:     correction to by compatible wiath g++-3.4
+| |
+o |  changeset:   329:de5ee8de0427
+| |  user:        hecht
+| |  date:        Fri Aug 27 17:42:26 2004 +0200
+| |  summary:     correct g++-3.4 compilation probleme
+| |
+o |  changeset:   328:5a1f1387f099
+| |  user:        hecht
+| |  date:        Thu Aug 26 16:51:56 2004 +0200
+| |  summary:     optimize cpu times on choleski and crout
+| |
+o |  changeset:   327:c28bfd60ba97
+| |  user:        hecht
+| |  date:        Thu Aug 26 15:04:49 2004 +0200
+| |  summary:     correct divide by zero in plot
+| |
+o |  changeset:   326:82e0b4315486
+| |  user:        hecht
+| |  date:        Thu Aug 26 15:04:49 2004 +0200
+| |  summary:     correct divide by zero in plot
+| |
+o |  changeset:   325:cf3cb8ac4aff
+| |  user:        hecht
+| |  date:        Thu Aug 26 15:04:49 2004 +0200
+| |  summary:     correct divide by zero in plot
+| |
+o |  changeset:   324:03ff6dc560d5
+| |  user:        hecht
+| |  date:        Thu Aug 26 15:04:49 2004 +0200
+| |  summary:     correct divide by zero in plot
+| |
+o |  changeset:   323:1a52cee5c2df
+| |  user:        hecht
+| |  date:        Thu Aug 26 15:04:49 2004 +0200
+| |  summary:     correct divide by zero in plot
+| |
+o |  changeset:   322:0aa1b06eb0ef
+| |  user:        lehyaric
+| |  date:        Fri Jul 16 14:40:18 2004 +0200
+| |  summary:     Windows package for Version 1.41 complete.
+| |
+o |  changeset:   321:1fe712bb592c
+| |  user:        lehyaric
+| |  date:        Fri Jul 16 14:40:18 2004 +0200
+| |  summary:     Windows package for Version 1.41 complete.
+| |
+o |  changeset:   320:def90fb6ed3d
+| |  user:        lehyaric
+| |  date:        Fri Jul 16 14:40:18 2004 +0200
+| |  summary:     Windows package for Version 1.41 complete.
+| |
+o |  changeset:   319:bf9d235a46b3
+| |  user:        lehyaric
+| |  date:        Fri Jul 16 14:40:18 2004 +0200
+| |  summary:     Windows package for Version 1.41 complete.
+| |
+o |  changeset:   318:85f578ad260e
+| |  user:        lehyaric
+| |  date:        Fri Jul 16 14:40:18 2004 +0200
+| |  summary:     Windows package for Version 1.41 complete.
+| |
+o |  changeset:   317:6628af52db2b
+| |  user:        lehyaric
+| |  date:        Thu Jul 15 10:32:08 2004 +0200
+| |  summary:     Regression tests ok on an Athlon 1.2 GHz.
+| |
+o |  changeset:   316:53712bc8f199
+| |  user:        lehyaric
+| |  date:        Tue Jul 13 14:20:36 2004 +0200
+| |  summary:     Regression tests pass on cygwin.
+| |
+o |  changeset:   315:8ea214d54ae7
+| |  user:        lehyaric
+| |  date:        Tue Jul 13 11:13:06 2004 +0200
+| |  summary:     Small comment change.
+| |
+o |  changeset:   314:64a1e1e70dac
+| |  user:        lehyaric
+| |  date:        Tue Jul 13 11:12:29 2004 +0200
+| |  summary:     Downloaded generic BLAS now work on cedre (redhat, pentium 4).
+| |
+o |  changeset:   313:1faecf8849ea
+| |  user:        lehyaric
+| |  date:        Tue Jul 13 11:12:29 2004 +0200
+| |  summary:     Downloaded generic BLAS now work on cedre (redhat, pentium 4).
+| |
+o |  changeset:   312:d2475c116bac
+| |  user:        lehyaric
+| |  date:        Tue Jul 13 11:01:50 2004 +0200
+| |  summary:     Optimized BLAS replaced with generic BLAS for generic compilation.
+| |
+o |  changeset:   311:9d99b39cf9d4
+| |  user:        lehyaric
+| |  date:        Tue Jul 13 10:29:57 2004 +0200
+| |  summary:     Duplicates xerbla.f when downloading generic blas.
+| |
+o |  changeset:   310:71ed69bf1371
+| |  user:        lehyaric
+| |  date:        Mon Jul 12 17:38:15 2004 +0200
+| |  summary:     Uses generic BLAS for generic compilation, because it is faster to compile
+| |
+o |  changeset:   309:4223a25835b8
+| |  user:        lehyaric
+| |  date:        Mon Jul 12 17:38:15 2004 +0200
+| |  summary:     Uses generic BLAS for generic compilation, because it is faster to compile
+| |
+o |  changeset:   308:b9a134a6f6e2
+| |  user:        lehyaric
+| |  date:        Fri Jul 09 18:10:16 2004 +0200
+| |  summary:     New script to upload Debian packages.
+| |
+o |  changeset:   307:db4e0b9fb8e6
+| |  user:        lehyaric
+| |  date:        Fri Jul 09 18:10:16 2004 +0200
+| |  summary:     New script to upload Debian packages.
+| |
+o |  changeset:   306:fcea44571ff4
+| |  user:        darrasse
+| |  date:        Fri Jul 09 16:52:17 2004 +0200
+| |  summary:     Mise à jour de la liste des auteurs
+| |
+o |  changeset:   305:a518d55630cf
+| |  user:        lehyaric
+| |  date:        Fri Jul 09 10:04:55 2004 +0200
+| |  summary:     Binary ATLAS download disabled for the moment.
+| |
+o |  changeset:   304:e8c7b5754d95
+| |  user:        hecht
+| |  date:        Thu Jul 08 15:31:42 2004 +0200
+| |  summary:     install-www in progress
+| |
+o |  changeset:   303:7af6fdba37a9
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 15:22:13 2004 +0200
+| |  summary:     The precompiled ATLAS library is now correctly downloaded and uncompressed,
+| |
+o |  changeset:   302:193850ffeebf
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 15:22:13 2004 +0200
+| |  summary:     The precompiled ATLAS library is now correctly downloaded and uncompressed,
+| |
+o |  changeset:   301:1a7ea2e9e383
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 15:22:13 2004 +0200
+| |  summary:     The precompiled ATLAS library is now correctly downloaded and uncompressed,
+| |
+o |  changeset:   300:470d4053c3da
+| |  user:        hecht
+| |  date:        Thu Jul 08 15:21:08 2004 +0200
+| |  summary:     correct install-www
+| |
+o |  changeset:   299:7cd6515116e5
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 13:15:48 2004 +0200
+| |  summary:     Reference values for regression tests with and without UMFPACK merged.
+| |
+o |  changeset:   298:fcf594999fd7
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 13:15:48 2004 +0200
+| |  summary:     Reference values for regression tests with and without UMFPACK merged.
+| |
+o |  changeset:   297:3dce3e57c22a
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 13:15:48 2004 +0200
+| |  summary:     Reference values for regression tests with and without UMFPACK merged.
+| |
+o |  changeset:   296:b5573d38d3fd
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 12:02:10 2004 +0200
+| |  summary:     Option to download a precompiled version of ATLAS programmed in, but not
+| |
+o |  changeset:   295:fefc602af266
+| |  user:        lehyaric
+| |  date:        Thu Jul 08 10:44:43 2004 +0200
+| |  summary:     Debian binary packages created, but not tested yet.
+| |
+o |  changeset:   294:2269542083d4
+| |  user:        lehyaric
+| |  date:        Wed Jul 07 17:42:54 2004 +0200
+| |  summary:     Debian packaging in progress.
+| |
+o |  changeset:   293:5fa437bd58d9
+| |  user:        lehyaric
+| |  date:        Wed Jul 07 17:42:54 2004 +0200
+| |  summary:     Debian packaging in progress.
+| |
+o |  changeset:   292:3c887a990870
+| |  user:        hecht
+| |  date:        Wed Jul 07 16:25:04 2004 +0200
+| |  summary:     correction on macosX version
+| |
+o |  changeset:   291:a2af1c655832
+| |  user:        hecht
+| |  date:        Wed Jul 07 16:25:04 2004 +0200
+| |  summary:     correction on macosX version
+| |
+o |  changeset:   290:e6ecf315812d
+| |  user:        hecht
+| |  date:        Wed Jul 07 16:25:04 2004 +0200
+| |  summary:     correction on macosX version
+| |
+o |  changeset:   289:c51cd2b05332
+| |  user:        hecht
+| |  date:        Wed Jul 07 15:56:15 2004 +0200
+| |  summary:     correct pb in freefem++.app on macosX
+| |
+o |  changeset:   288:e142da063d15
+| |  user:        hecht
+| |  date:        Wed Jul 07 15:13:27 2004 +0200
+| |  summary:     correct install-www script
+| |
+o |  changeset:   287:ab379a17cf2e
+| |  user:        hecht
+| |  date:        Wed Jul 07 14:40:01 2004 +0200
+| |  summary:     add native9 make target for Mac9 version
+| |
+o |  changeset:   286:6aaa1a3f395f
+| |  user:        hecht
+| |  date:        Wed Jul 07 14:29:05 2004 +0200
+| |  summary:     correct pb in MACOSX version and instal-www file
+| |
+o |  changeset:   285:28ea7398dafd
+| |  user:        hecht
+| |  date:        Wed Jul 07 14:24:10 2004 +0200
+| |  summary:     correct path of FreeFem++-CoCoa file in install
+| |
+o |  changeset:   284:8609cad81843
+| |  user:        hecht
+| |  date:        Wed Jul 07 14:05:51 2004 +0200
+| |  summary:     Add COPYRIGHT file
+| |
+o |  changeset:   283:1525c53ec559
+| |  user:        hecht
+| |  date:        Wed Jul 07 13:58:17 2004 +0200
+| |  summary:     Add INSTALL-MacOS file
+| |
+o |  changeset:   282:94e900430e00
+| |  user:        lehyaric
+| |  date:        Wed Jul 07 12:51:55 2004 +0200
+| |  summary:     Debian packaging in progress.
+| |
+o |  changeset:   281:f5220090d815
+| |  user:        lehyaric
+| |  date:        Wed Jul 07 12:51:55 2004 +0200
+| |  summary:     Debian packaging in progress.
+| |
+o |  changeset:   280:421a0c5540ec
+| |  user:        hecht
+| |  date:        Wed Jul 07 12:41:05 2004 +0200
+| |  summary:     mal change in epsilon for regtest (on idared)
+| |
+o |  changeset:   279:0f1c9dc9f21f
+| |  user:        hecht
+| |  date:        Wed Jul 07 12:09:31 2004 +0200
+| |  summary:     correct pb in m4 parameter for building  regtests.edp
+| |
+o |  changeset:   278:669fb7802b66
+| |  user:        hecht
+| |  date:        Wed Jul 07 11:32:55 2004 +0200
+| |  summary:     add install-www to set web server
+| |
+o |  changeset:   277:ce3021db6c88
+| |  tag:         release_1_41_before_packaging
+| |  user:        lehyaric
+| |  date:        Mon Jul 05 14:38:47 2004 +0200
+| |  summary:     Remove debugging information
+| |
+o |  changeset:   276:7a4a883326b9
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 16:13:29 2004 +0200
+| |  summary:     Improvements on regression tests on Idared, but still a segmentation fault
+| |
+o |  changeset:   275:82325608c7fa
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 16:04:09 2004 +0200
+| |  summary:     All regression tests ok on Cedre.
+| |
+o |  changeset:   274:9f94970bb44b
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 16:04:09 2004 +0200
+| |  summary:     All regression tests ok on Cedre.
+| |
+o |  changeset:   273:2d7625db8ce9
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 16:04:09 2004 +0200
+| |  summary:     All regression tests ok on Cedre.
+| |
+o |  changeset:   272:7be0ae88c080
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 15:33:45 2004 +0200
+| |  summary:     All regression tests ok on Hydre.
+| |
+o |  changeset:   271:df58e4bd4eda
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 15:33:45 2004 +0200
+| |  summary:     All regression tests ok on Hydre.
+| |
+o |  changeset:   270:0757f6282056
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 15:33:45 2004 +0200
+| |  summary:     All regression tests ok on Hydre.
+| |
+o |  changeset:   269:bd99d82ae56e
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 15:33:45 2004 +0200
+| |  summary:     All regression tests ok on Hydre.
+| |
+o |  changeset:   268:2e6c9c4611a5
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 14:26:01 2004 +0200
+| |  summary:     More updates to make parallel regression tests work.
+| |
+o |  changeset:   267:43dffe189376
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 14:26:01 2004 +0200
+| |  summary:     More updates to make parallel regression tests work.
+| |
+o |  changeset:   266:2934f663b1f6
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 14:26:01 2004 +0200
+| |  summary:     More updates to make parallel regression tests work.
+| |
+o |  changeset:   265:03a2012d998f
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 14:18:33 2004 +0200
+| |  summary:     Correcting some problems with parallel regressions tests.
+| |
+o |  changeset:   264:5659084d9b60
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 14:15:43 2004 +0200
+| |  summary:     Separate set of reference values when UMFPACK is not available.
+| |
+o |  changeset:   263:be8728bf6836
+| |  user:        lehyaric
+| |  date:        Thu Jul 01 13:21:41 2004 +0200
+| |  summary:     More tests on the parallel version (FreeFem++-mpi)
+| |
+o |  changeset:   262:d6eeb2d1500d
+| |  user:        lehyaric
+| |  date:        Wed Jun 30 15:47:51 2004 +0200
+| |  summary:     Regression tests installed in examples++-tutorial, with a separate file
+| |
+o |  changeset:   261:2b2296d0b03d
+| |  user:        lehyaric
+| |  date:        Wed Jun 30 14:29:48 2004 +0200
+| |  summary:     New file configure.param containing configure parameters.
+| |
+o |  changeset:   260:74d8cc71c4ba
+| |  user:        lehyaric
+| |  date:        Wed Jun 30 10:47:20 2004 +0200
+| |  summary:     Describes how to compile FreeFem++ on Windows.
+| |
+o |  changeset:   259:f5b3a2abcf03
+| |  user:        lehyaric
+| |  date:        Wed Jun 30 10:45:28 2004 +0200
+| |  summary:     Because of the way return codes are handled inside shell pipe "|" commands,
+| |
+o |  changeset:   258:dc3cf3b8e5f1
+| |  user:        lehyaric
+| |  date:        Tue Jun 29 18:41:14 2004 +0200
+| |  summary:     More upgrades to make the source tar file compilable on most architectures.
+| |
+o |  changeset:   257:93336381edc4
+| |  user:        lehyaric
+| |  date:        Tue Jun 29 18:41:14 2004 +0200
+| |  summary:     More upgrades to make the source tar file compilable on most architectures.
+| |
+o |  changeset:   256:e511f057ffa7
+| |  user:        lehyaric
+| |  date:        Tue Jun 29 18:41:14 2004 +0200
+| |  summary:     More upgrades to make the source tar file compilable on most architectures.
+| |
+o |  changeset:   255:3be4e4e86327
+| |  user:        lehyaric
+| |  date:        Tue Jun 29 18:41:14 2004 +0200
+| |  summary:     More upgrades to make the source tar file compilable on most architectures.
+| |
+o |  changeset:   254:3a93a6f5e3fb
+| |  user:        lehyaric
+| |  date:        Tue Jun 29 18:41:14 2004 +0200
+| |  summary:     More upgrades to make the source tar file compilable on most architectures.
+| |
+o |  changeset:   253:413fa728d595
+| |  user:        lehyaric
+| |  date:        Tue Jun 29 18:41:14 2004 +0200
+| |  summary:     More upgrades to make the source tar file compilable on most architectures.
+| |
+o |  changeset:   252:95739d9cec9c
+| |  user:        hecht
+| |  date:        Mon Jun 28 22:02:09 2004 +0200
+| |  summary:     correct double echo in macro expansion
+| |
+o |  changeset:   251:c787dfc0af48
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   250:fbad8a94c9fe
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   249:23513d2a05c2
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   248:b46fb2019dd4
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   247:cceac60d1b66
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   246:bbba443f4309
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   245:33d98ebd3407
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   244:7ebb82020029
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   243:cb7d05e66ca1
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   242:ce4ed3033dda
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   241:ccf83b55c405
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   240:c880a524e281
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 19:26:56 2004 +0200
+| |  summary:     .tar.gz packages currently being tested and improved. Testing architectures
+| |
+o |  changeset:   239:491d91e180a6
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   238:1a92d214e4e9
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   237:18d9f46d6956
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   236:6dbd1f92fe78
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   235:9f6dc3d57397
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   234:c4b6d34b9c58
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   233:15448ffdb476
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   232:ad9b66078f50
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   231:244e10acad9f
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   230:a061edaca896
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   229:5f042d9e08c1
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   228:51b52fdc0699
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   227:9cf12e9fcc6a
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   226:b39368025dc3
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 12:36:53 2004 +0200
+| |  summary:     Gathering all regression check in one location (regtests.edp) to let
+| |
+o |  changeset:   225:8be6dcc104ac
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 11:07:54 2004 +0200
+| |  summary:     Cleaning and improving the MacOS version.
+| |
+o |  changeset:   224:e98a86d4e84a
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 11:07:54 2004 +0200
+| |  summary:     Cleaning and improving the MacOS version.
+| |
+o |  changeset:   223:4fe29fbcb591
+| |  user:        lehyaric
+| |  date:        Mon Jun 28 11:07:53 2004 +0200
+| |  summary:     Cleaning and improving the MacOS version.
+| |
+o |  changeset:   222:11ea2dc80fda
+| |  user:        hecht
+| |  date:        Mon Jun 28 09:41:41 2004 +0200
+| |  summary:     small correct
+| |
+o |  changeset:   221:803825852848
+| |  user:        hecht
+| |  date:        Mon Jun 28 09:33:07 2004 +0200
+| |  summary:     FH correct pb in file name
+| |
+o |  changeset:   220:49f933c9d7c5
+| |  user:        hecht
+| |  date:        Mon Jun 28 09:29:04 2004 +0200
+| |  summary:     Correct small thing in DOC and add losed figure
+| |
+o |  changeset:   219:b0b3f7597046
+| |  user:        hecht
+| |  date:        Mon Jun 28 09:29:04 2004 +0200
+| |  summary:     Correct small thing in DOC and add losed figure
+| |
+o |  changeset:   218:260856bae4be
+| |  user:        hecht
+| |  date:        Mon Jun 28 09:29:04 2004 +0200
+| |  summary:     Correct small thing in DOC and add losed figure
+| |
+o |  changeset:   217:d8ebe140a004
+| |  user:        hecht
+| |  date:        Sun Jun 27 17:18:35 2004 +0200
+| |  summary:     FH modif .plist file for MacOS application
+| |
+o |  changeset:   216:274201b08277
+| |  user:        hecht
+| |  date:        Sun Jun 27 17:18:35 2004 +0200
+| |  summary:     FH modif .plist file for MacOS application
+| |
+o |  changeset:   215:b34523490134
+| |  user:        hecht
+| |  date:        Sun Jun 27 17:18:35 2004 +0200
+| |  summary:     FH modif .plist file for MacOS application
+| |
+o |  changeset:   214:1abaf5e80c5b
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 18:39:04 2004 +0200
+| |  summary:     Added a new scheme for checking numerical results in each example
+| |
+o |  changeset:   213:d345132caf0d
+| |  user:        hecht
+| |  date:        Fri Jun 25 18:31:20 2004 +0200
+| |  summary:     FH: add bug example
+| |
+o |  changeset:   212:ed255a0ab2b9
+| |  user:        hecht
+| |  date:        Fri Jun 25 18:30:14 2004 +0200
+| |  summary:     FH:  compile FLAG optimization  on MACOS
+| |
+o |  changeset:   211:952ea771ea45
+| |  user:        hecht
+| |  date:        Fri Jun 25 17:54:02 2004 +0200
+| |  summary:     FH: correct the -fast compilation flag  on MACOS (remove -malign-natural)
+| |
+o |  changeset:   210:ee742b18566c
+| |  user:        hecht
+| |  date:        Fri Jun 25 17:54:02 2004 +0200
+| |  summary:     FH: correct the -fast compilation flag  on MACOS (remove -malign-natural)
+| |
+o |  changeset:   209:566f15d34ead
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 17:30:51 2004 +0200
+| |  summary:     Making "make visualcheck" work.
+| |
+o |  changeset:   208:830668a369ab
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 15:46:10 2004 +0200
+| |  summary:     POSIX system calls times() and sysconf() are not defined in Mingw system
+| |
+o |  changeset:   207:5f265a041999
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 14:18:35 2004 +0200
+| |  summary:     Displays test output as well as recording it during regression tests.
+| |
+o |  changeset:   206:2a8140e574cd
+| |  user:        hecht
+| |  date:        Fri Jun 25 14:13:56 2004 +0200
+| |  summary:     add a forgottent  & in toString  Complex)
+| |
+o |  changeset:   205:1a8af1b6cc4e
+| |  user:        hecht
+| |  date:        Fri Jun 25 14:04:48 2004 +0200
+| |  summary:     change toString to remove problem of optimisation flag -fast on MacOS
+| |
+o |  changeset:   204:cdda0f23627e
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 13:53:20 2004 +0200
+| |  summary:     Avoids the gcc option "-rdynamic" (used for dlopen()) on MacOS.
+| |
+o |  changeset:   203:50b0a79472d0
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 13:42:27 2004 +0200
+| |  summary:     Still more corrections to make regtests.sh work.
+| |
+o |  changeset:   202:7350e7f03cb7
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 12:21:00 2004 +0200
+| |  summary:     Corrected bug where FreeFem++ command was not correctly constructed
+| |
+o |  changeset:   201:1a97c5f8dae3
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   200:bf6116bf6e14
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   199:f9a372018d4d
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   198:173890d6cffd
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   197:1ea692423a96
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   196:eafde84d3182
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   195:36fad8e658ca
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   194:84be95355842
+| |  user:        hecht
+| |  date:        Fri Jun 25 12:17:20 2004 +0200
+| |  summary:     add periodic adaptmesh  stuff
+| |
+o |  changeset:   193:cc913a248488
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 12:12:19 2004 +0200
+| |  summary:     Corrected bug where file examples++-other/speedtest.out was not updated
+| |
+o |  changeset:   192:5eb924283df1
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 11:55:15 2004 +0200
+| |  summary:     Replaced all occurrences of regtests.pl with regtests.sh
+| |
+o |  changeset:   191:5f334f30cf3d
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 11:05:41 2004 +0200
+| |  summary:     Correcting the definition of VersionFreeFemDate and VersionFreeFempp
+| |
+o |  changeset:   190:46b1668643d5
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 10:59:16 2004 +0200
+| |  summary:     More documentation for config-version.h generation.
+| |
+o |  changeset:   189:63d0c3f29db0
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 10:55:37 2004 +0200
+| |  summary:     - Restructuring the regression tests suite to run all non windowed tests
+| |
+o |  changeset:   188:05d5f79cdebc
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 10:55:37 2004 +0200
+| |  summary:     - Restructuring the regression tests suite to run all non windowed tests
+| |
+o |  changeset:   187:dd9823784d74
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 10:55:37 2004 +0200
+| |  summary:     - Restructuring the regression tests suite to run all non windowed tests
+| |
+o |  changeset:   186:28349aab8571
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 10:55:37 2004 +0200
+| |  summary:     - Restructuring the regression tests suite to run all non windowed tests
+| |
+o |  changeset:   185:18a8cf3b1821
+| |  user:        lehyaric
+| |  date:        Fri Jun 25 10:55:37 2004 +0200
+| |  summary:     - Restructuring the regression tests suite to run all non windowed tests
+| |
+o |  changeset:   184:4f7f186b636b
+| |  user:        darrasse
+| |  date:        Thu Jun 24 18:09:06 2004 +0200
+| |  summary:     Ajout du packet freefem++-doc contenant la documentation
+| |
+o |  changeset:   183:e7ca62ae4d11
+| |  user:        darrasse
+| |  date:        Thu Jun 24 18:09:06 2004 +0200
+| |  summary:     Ajout du packet freefem++-doc contenant la documentation
+| |
+o |  changeset:   182:0e82b2a232ce
+| |  user:        darrasse
+| |  date:        Thu Jun 24 18:09:06 2004 +0200
+| |  summary:     Ajout du packet freefem++-doc contenant la documentation
+| |
+o |  changeset:   181:66f445bf7317
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 17:08:22 2004 +0200
+| |  summary:     Some commands (like make speedtest and doc) are more thoroughly documented.
+| |
+o |  changeset:   180:c2c2f1bc0b5d
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 16:49:17 2004 +0200
+| |  summary:     Give a value to LD_LIBRARY_PATH for the examples++-load regression tests.
+| |
+o |  changeset:   179:b4d6436c35bf
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 16:05:39 2004 +0200
+| |  summary:     Regression tests for the parallel version are ok.
+| |
+o |  changeset:   178:089de7eb3548
+| |  user:        darrasse
+| |  date:        Thu Jun 24 14:44:46 2004 +0200
+| |  summary:     Changement de priorité des alternatives. x11 est prioritaire à glx.
+| |
+o |  changeset:   177:6b4f77f9d655
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 13:50:15 2004 +0200
+| |  summary:     examples++-load now works on Cedre (Red Hat), with debug options.
+| |
+o |  changeset:   176:13a795a47cb0
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 13:50:15 2004 +0200
+| |  summary:     examples++-load now works on Cedre (Red Hat), with debug options.
+| |
+o |  changeset:   175:fe0ca2334cad
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 12:27:06 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   174:50971f3da918
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 12:27:06 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   173:e5c1f7c7ce17
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 11:52:52 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   172:1d1b041dabfc
+| |  user:        darrasse
+| |  date:        Thu Jun 24 11:48:27 2004 +0200
+| |  summary:     Ajout de plusieurs this-> pour la compilation avec g++-3.4
+| |
+o |  changeset:   171:04867a5d5213
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 10:44:31 2004 +0200
+| |  summary:     GLX version was not compiled on MacOS X. Corrected.
+| |
+o |  changeset:   170:7e35f0a71ca8
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 09:46:04 2004 +0200
+| |  summary:     examples++-load is being worked on. It still poses problems.
+| |
+o |  changeset:   169:9ac236b0dd89
+| |  user:        lehyaric
+| |  date:        Thu Jun 24 09:46:04 2004 +0200
+| |  summary:     examples++-load is being worked on. It still poses problems.
+| |
+o |  changeset:   168:579a83fef807
+| |  user:        hecht
+| |  date:        Thu Jun 24 08:09:48 2004 +0200
+| |  summary:     modif to bee  compatible with  g++ 3.4
+| |
+o |  changeset:   167:530be6b2021c
+| |  user:        darrasse
+| |  date:        Thu Jun 24 04:12:48 2004 +0200
+| |  summary:     Nouvel ajout de this-> pour la compilation avec g++-3.4
+| |
+o |  changeset:   166:91dcaa97dd82
+| |  user:        darrasse
+| |  date:        Thu Jun 24 03:37:52 2004 +0200
+| |  summary:     Ajout de quelques this-> pour la compilation avec g++ 3.4
+| |
+o |  changeset:   165:f80016364270
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:16:48 2004 +0200
+| |  summary:     Ajout d'une page man générique, obligatoire pour Debian.
+| |
+o |  changeset:   164:8861a5960357
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   163:c6f04faebb32
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   162:2eae0e0f0869
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   161:34d7f2a2a9f1
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   160:a94d47551f62
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   159:704f142ac8a6
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   158:462a19c6fd35
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   157:14490711226c
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   156:ecd8d9f031c5
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   155:39009c82f388
+| |  user:        darrasse
+| |  date:        Thu Jun 24 02:12:43 2004 +0200
+| |  summary:     Insertion du dossier debian contenant les fichiers nécessaires pour la
+| |
+o |  changeset:   154:4c9e9eaee438
+| |  user:        lehyaric
+| |  date:        Wed Jun 23 17:05:33 2004 +0200
+| |  summary:     The regression tests have been checked up to examples++-load not included
+| |
+o |  changeset:   153:cd34c9818fdd
+| |  user:        lehyaric
+| |  date:        Wed Jun 23 15:47:48 2004 +0200
+| |  summary:     Problem with AGL on MasOSX solved: it was not selected for compilation
+| |
+o |  changeset:   152:56ce98e3dd00
+| |  user:        lehyaric
+| |  date:        Wed Jun 23 14:04:06 2004 +0200
+| |  summary:     Regression tests are currently being checked.
+| |
+o |  changeset:   151:0629efd36bdf
+| |  user:        lehyaric
+| |  date:        Wed Jun 23 14:04:06 2004 +0200
+| |  summary:     Regression tests are currently being checked.
+| |
+o |  changeset:   150:d74e4f965d34
+| |  user:        lehyaric
+| |  date:        Wed Jun 23 14:04:06 2004 +0200
+| |  summary:     Regression tests are currently being checked.
+| |
+o |  changeset:   149:ef13ddf7a19d
+| |  user:        lehyaric
+| |  date:        Wed Jun 23 11:36:17 2004 +0200
+| |  summary:     Mise à jour de la configuration de UMFPACK
+| |
+o |  changeset:   148:8c35b9bd5a21
+| |  user:        lehyaric
+| |  date:        Tue Jun 22 18:44:09 2004 +0200
+| |  summary:     Bug preventing the separate compilation of src/fflib/lex.cpp corrected.
+| |
+o |  changeset:   147:b83c3d850f19
+| |  user:        lehyaric
+| |  date:        Tue Jun 22 18:25:26 2004 +0200
+| |  summary:     New 'speedtest' goal to run FreeFem++-nw on examples++-other/lap3-cpu.edp
+| |
+o |  changeset:   146:b4100d9e3db7
+| |  user:        lehyaric
+| |  date:        Tue Jun 22 17:12:59 2004 +0200
+| |  summary:     Optimization ok on PowerPC G5 (Idared)
+| |
+o |  changeset:   145:9f310e0c592f
+| |  user:        lehyaric
+| |  date:        Tue Jun 22 15:38:05 2004 +0200
+| |  summary:     Optimized version ok on cedre (Intel Xeon + gcc + Red Hat Linux)
+| |
+o |  changeset:   144:5835fb842952
+| |  user:        lehyaric
+| |  date:        Tue Jun 22 15:38:05 2004 +0200
+| |  summary:     Optimized version ok on cedre (Intel Xeon + gcc + Red Hat Linux)
+| |
+o |  changeset:   143:3228d62729ed
+| |  user:        lehyaric
+| |  date:        Tue Jun 22 15:38:05 2004 +0200
+| |  summary:     Optimized version ok on cedre (Intel Xeon + gcc + Red Hat Linux)
+| |
+o |  changeset:   142:5a7bc526e492
+| |  user:        darrasse
+| |  date:        Tue Jun 22 15:32:22 2004 +0200
+| |  summary:     correction de la détection de UMFPACK
+| |
+o |  changeset:   141:668587ef4273
+| |  user:        lehyaric
+| |  date:        Tue Jun 22 12:05:59 2004 +0200
+| |  summary:     Correction minime de l'explication de --enable-debug.
+| |
+o |  changeset:   140:76886e6c7a58
+| |  user:        lehyaric
+| |  date:        Mon Jun 21 17:06:16 2004 +0200
+| |  summary:     Optimization ok on Debian/Testing.
+| |
+o |  changeset:   139:06ec58be4aa1
+| |  user:        hecht
+| |  date:        Mon Jun 21 16:56:55 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   138:93b07446f4c5
+| |  user:        hecht
+| |  date:        Mon Jun 21 16:49:06 2004 +0200
+| |  summary:     le fichier fflib/lg.tab.hpp est dans de dir lglib et genere par bison
+| |
+o |  changeset:   137:ba2a49602ec0
+| |  user:        lehyaric
+| |  date:        Mon Jun 21 16:24:54 2004 +0200
+| |  summary:     Parallel version modified to use downloaded UMFPACK if available.
+| |
+o |  changeset:   136:7dd82d676d0d
+| |  user:        lehyaric
+| |  date:        Mon Jun 21 15:53:15 2004 +0200
+| |  summary:     Some corrections for the "generic" optimization mode.
+| |
+o |  changeset:   135:154e95f0efb4
+| |  user:        lehyaric
+| |  date:        Mon Jun 21 15:31:16 2004 +0200
+| |  summary:     Hardware-dependant optimization options currently being selected.
+| |
+o |  changeset:   134:2fc65e06c099
+| |  user:        hecht
+| |  date:        Mon Jun 21 11:08:16 2004 +0200
+| |  summary:     add example of test the optimised version
+| |
+o |  changeset:   133:41b3e409ce8d
+| |  user:        hecht
+| |  date:        Mon Jun 21 11:08:16 2004 +0200
+| |  summary:     add example of test the optimised version
+| |
+o |  changeset:   132:aa3b6d5dea5a
+| |  user:        hecht
+| |  date:        Mon Jun 21 11:08:16 2004 +0200
+| |  summary:     add example of test the optimised version
+| |
+o |  changeset:   131:ee15f9879bb0
+| |  user:        lehyaric
+| |  date:        Sun Jun 20 19:58:38 2004 +0200
+| |  summary:     Optimiztion for Pentium III added.
+| |
+o |  changeset:   130:07ffea2fef49
+| |  user:        lehyaric
+| |  date:        Sun Jun 20 19:30:28 2004 +0200
+| |  summary:     Configuration of compiler optimization flags still being developed.
+| |
+o |  changeset:   129:5e6217c43c12
+| |  user:        lehyaric
+| |  date:        Sun Jun 20 13:26:50 2004 +0200
+| |  summary:     acmacros.m4 and acoptim.m4 will centralize all the necessary treatments
+| |
+o |  changeset:   128:49ecc5ec76f1
+| |  user:        hecht
+| |  date:        Sat Jun 19 14:23:20 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   127:27909cc2efe4
+| |  user:        hecht
+| |  date:        Fri Jun 18 17:50:43 2004 +0200
+| |  summary:     add modif compilation avec gcc 3.4
+| |
+o |  changeset:   126:eb38cdcad258
+| |  user:        lehyaric
+| |  date:        Fri Jun 18 10:31:16 2004 +0200
+| |  summary:     Documentation proofreading ok up to §3.6 included
+| |
+o |  changeset:   125:eebea7c8bada
+| |  user:        lehyaric
+| |  date:        Thu Jun 17 14:34:49 2004 +0200
+| |  summary:     - Documentation proofreading ok up to §3.6 included
+| |
+o |  changeset:   124:de5ab079f924
+| |  user:        lehyaric
+| |  date:        Wed Jun 16 14:47:48 2004 +0200
+| |  summary:     - Removing emacs backup files
+| |
+o |  changeset:   123:f8b658a60f71
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:36:50 2004 +0200
+| |  summary:     add projet codewarrior dans la base CVS en mode Binaire
+| |
+o |  changeset:   122:4365bece55ed
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:35:38 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   121:b1c8e1f1fbfa
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:32:24 2004 +0200
+| |  summary:     correction of string argument in macro processing
+| |
+o |  changeset:   120:e8a577e435c5
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:32:24 2004 +0200
+| |  summary:     correction of string argument in macro processing
+| |
+o |  changeset:   119:2b3e676ae747
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:32:24 2004 +0200
+| |  summary:     correction of string argument in macro processing
+| |
+o |  changeset:   118:3c790a15669c
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:32:24 2004 +0200
+| |  summary:     correction of string argument in macro processing
+| |
+o |  changeset:   117:4223b571b7a2
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:32:24 2004 +0200
+| |  summary:     correction of string argument in macro processing
+| |
+o |  changeset:   116:6d4f0efd7290
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:32:24 2004 +0200
+| |  summary:     correction of string argument in macro processing
+| |
+o |  changeset:   115:8830c3e6a420
+| |  user:        hecht
+| |  date:        Wed Jun 16 14:25:41 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   114:15154662ef97
+| |  user:        lehyaric
+| |  date:        Tue Jun 15 12:08:37 2004 +0200
+| |  summary:     Proofreading ok up to §2.3 included.
+| |
+o |  changeset:   113:f3859d20ff80
+| |  user:        lehyaric
+| |  date:        Thu Jun 10 10:16:17 2004 +0200
+| |  summary:     - Relecture Anglais documentation: chapitre I ok.
+| |
+o |  changeset:   112:5dfaf78878eb
+| |  user:        lehyaric
+| |  date:        Thu Jun 10 10:16:17 2004 +0200
+| |  summary:     - Relecture Anglais documentation: chapitre I ok.
+| |
+o |  changeset:   111:d602db40f9df
+| |  user:        lehyaric
+| |  date:        Thu Jun 10 10:16:17 2004 +0200
+| |  summary:     - Relecture Anglais documentation: chapitre I ok.
+| |
+o |  changeset:   110:85d80f2e6265
+| |  user:        lehyaric
+| |  date:        Wed Jun 09 10:09:10 2004 +0200
+| |  summary:     More help on CVS and automake.
+| |
+o |  changeset:   109:66de63c37bce
+| |  user:        lehyaric
+| |  date:        Tue Jun 08 16:10:19 2004 +0200
+| |  summary:     Relecture anglais doc arrivé au § 1.3
+| |
+o |  changeset:   108:93fa37e6dc7e
+| |  user:        lehyaric
+| |  date:        Mon Jun 07 16:34:17 2004 +0200
+| |  summary:     Première relecture des fichiers README et associés.
+| |
+o |  changeset:   107:828ba65d9130
+| |  user:        lehyaric
+| |  date:        Mon Jun 07 16:34:17 2004 +0200
+| |  summary:     Première relecture des fichiers README et associés.
+| |
+o |  changeset:   106:d76a5467a2c6
+| |  user:        lehyaric
+| |  date:        Mon Jun 07 16:34:17 2004 +0200
+| |  summary:     Première relecture des fichiers README et associés.
+| |
+o |  changeset:   105:b58a786980f6
+| |  user:        lehyaric
+| |  date:        Mon Jun 07 16:34:17 2004 +0200
+| |  summary:     Première relecture des fichiers README et associés.
+| |
+o |  changeset:   104:83b96ae3f863
+| |  user:        lehyaric
+| |  date:        Mon Jun 07 16:34:17 2004 +0200
+| |  summary:     Première relecture des fichiers README et associés.
+| |
+o |  changeset:   103:23de4ddd9d39
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   102:99d43ca61439
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   101:ab16a232f526
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   100:c59fb66f9425
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   99:0bfd80be1c8c
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   98:a12e2d2e0631
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   97:3874c0fba853
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   96:502d1784ed2e
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   95:4dcb9aa0c74e
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   94:37cfd09bf134
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   93:e648a1bfdd58
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   92:dae695622eac
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   91:27cd79875601
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   90:c8bda48c4105
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   89:eb18bcf09a34
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   88:a820a6c27662
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   87:2658627dd95d
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   86:2eb5adcc8f3b
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   85:5c4c5a9817fa
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   84:d7c50a038a79
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   83:e0934bf79429
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   82:60ee4abf02ca
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   81:2bfb83f8a44d
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   80:1b42fd3b13ff
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   79:dfbcaf6116ec
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   78:c990f2f011b2
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   77:2522953f44a9
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   76:d6250e981cf3
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   75:b1d17073cf16
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   74:d524e9ab1f96
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   73:c34a8b43dbb8
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   72:266eeb6a5ad6
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   71:3039d27ef299
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   70:425fc26308ae
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   69:958cf52ec0ae
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   68:7f82309eca0d
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   67:5056a0adbdc9
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   66:db1bcf6b5777
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   65:bb600795df63
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   64:f81592709735
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:25 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   63:2a6417d3e573
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   62:f25428415d3c
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   61:49f2a29fb46e
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   60:c69b6f268006
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   59:9e03261e3434
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   58:1ec7cc14da21
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   57:19c0a9c331c9
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   56:13019879f42e
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   55:c9fab124321e
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   54:a0ae934447f2
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   53:2c37fdc607e9
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   52:fbd4411abda7
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   51:0f97c8037b88
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   50:104bb1f450ad
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   49:23d20c1baebb
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   48:62334abc40ee
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   47:d8836d2bd9f6
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   46:c42f18e39eb4
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   45:5343bcf3d526
+| |  user:        lehyaric
+| |  date:        Fri Jun 04 16:06:24 2004 +0200
+| |  summary:     Les modifications faites dans la branche "alh-autoconf" sont réintégrées
+| |
+o |  changeset:   44:3572cd801d80
+| |  user:        hecht
+| |  date:        Fri Jun 04 15:22:02 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   43:7baa4c3c41ef
+| |  user:        hecht
+| |  date:        Fri Jun 04 15:22:02 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   42:68e784364499
+| |  user:        hecht
+| |  date:        Wed May 26 22:22:36 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   41:db5375fde77a
+| |  user:        hecht
+| |  date:        Wed May 26 22:00:26 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   40:399fdf624955
+| |  user:        hecht
+| |  date:        Wed May 26 21:58:43 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   39:00b51a05f198
+| |  user:        lehyaric
+| |  date:        Wed May 26 11:10:01 2004 +0200
+| |  summary:     manual.tex est réinitialisé à sa version 1.6, car les modifications
+| |
+o |  changeset:   38:4f307cbfc41a
+| |  user:        hecht
+| |  date:        Tue May 25 13:51:07 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   37:9c04976869b2
+| |  user:        ly
+| |  date:        Tue May 25 12:31:17 2004 +0200
+| |  summary:     Chaque exemple a ete reecrit dans un fichier tex separe, et inclus dans le
+| |
+o |  changeset:   36:00d12a962282
+| |  user:        ly
+| |  date:        Tue May 25 12:31:17 2004 +0200
+| |  summary:     Chaque exemple a ete reecrit dans un fichier tex separe, et inclus dans le
+| |
+o |  changeset:   35:e67f5d108cb8
+| |  user:        ly
+| |  date:        Tue May 25 12:31:17 2004 +0200
+| |  summary:     Chaque exemple a ete reecrit dans un fichier tex separe, et inclus dans le
+| |
+o |  changeset:   34:fcaf81e18093
+| |  user:        ly
+| |  date:        Tue May 25 12:31:17 2004 +0200
+| |  summary:     Chaque exemple a ete reecrit dans un fichier tex separe, et inclus dans le
+| |
+o |  changeset:   33:6e952764275e
+| |  user:        ly
+| |  date:        Tue May 25 12:31:17 2004 +0200
+| |  summary:     Chaque exemple a ete reecrit dans un fichier tex separe, et inclus dans le
+| |
+o |  changeset:   32:7d38e62303a8
+| |  user:        lehyaric
+| |  date:        Fri May 14 15:46:33 2004 +0200
+| |  summary:     Début de la relecture de l'anglais de la doc.
+| |
+o |  changeset:   31:25279b0696ab
+| |  user:        lehyaric
+| |  date:        Fri May 14 10:58:43 2004 +0200
+| |  summary:     manual.pdf and manual.ps.gz are automaticalle regenerated, so they should
+| |
+o |  changeset:   30:86ccde355d34
+| |  user:        lehyaric
+| |  date:        Fri May 14 10:43:34 2004 +0200
+| |  summary:     Récupération des Makefiles (depuis l'archive de la version 1.40) qui
+| |
+o |  changeset:   29:63564e1a54d8
+| |  user:        lehyaric
+| |  date:        Thu May 13 14:07:13 2004 +0200
+| |  summary:     Séparation d'une branche spéciale pour les essais de autoconf.
+| |
+o |  changeset:   28:0e192a3be805
+| |  user:        lehyaric
+| |  date:        Thu May 13 14:00:37 2004 +0200
+| |  summary:     Intégration de Autoconf et Automake dans la procédure de build en cours.
+| |
+o |  changeset:   27:33eb5379f1b1
+| |  user:        lehyaric
+| |  date:        Thu May 13 09:54:49 2004 +0200
+| |  summary:     Ajout progressif de tous les fichiers à ignorer.
+| |
+o |  changeset:   26:c5f6979dfddd
+| |  user:        hecht
+| |  date:        Wed May 12 21:32:42 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   25:4bf5a81958af
+| |  user:        lehyaric
+| |  date:        Wed May 12 14:34:39 2004 +0200
+| |  summary:     Fichier regénéré à la compilation
+| |
+o |  changeset:   24:343d50721685
+| |  user:        ly
+| |  date:        Wed May 12 13:21:45 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   23:86eda52226a7
+| |  user:        ly
+| |  date:        Wed May 12 13:21:44 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   22:4aa14c3200dc
+| |  user:        hecht
+| |  date:        Wed May 12 12:10:56 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   21:52c723e3b5d2
+| |  user:        hecht
+| |  date:        Wed May 12 12:10:56 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   20:df833d6233c6
+| |  user:        hecht
+| |  date:        Wed May 12 12:10:56 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   19:a4fb91c7bf52
+| |  user:        hecht
+| |  date:        Wed May 12 12:06:10 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   18:67575fb8c75b
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   17:416a46105dbb
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   16:857518acb793
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   15:ab21c2321e56
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   14:861633b13870
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   13:e92228f45751
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   12:e311b6dcae4a
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   11:7485d6e98966
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   10:c54fd00d722d
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   9:aed0c05275f3
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   8:e322689b6e92
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:31 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   7:ef03e67b3e10
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:30 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   6:d46f9d0308fb
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:30 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   5:cf149a2e8fec
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:30 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   4:f449141657dd
+| |  user:        hecht
+| |  date:        Wed May 12 11:35:30 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   3:f22e3359ec26
+| |  user:        ly
+| |  date:        Tue May 11 17:37:36 2004 +0200
+| |  summary:     *** empty log message ***
+| |
+o |  changeset:   2:fa41e8fddceb
+| |  user:        lehyaric
+| |  date:        Mon Apr 26 12:08:47 2004 +0200
+| |  summary:     Mise à jour de la documentation enregistrée dans CVS à partir de la
+| |
+o |  changeset:   1:1fcb4737d85b
+|/   user:        lehyaric
+|    date:        Mon Apr 26 12:08:46 2004 +0200
+|    summary:     Mise à jour de la documentation enregistrée dans CVS à partir de la
+|
+o  changeset:   0:6d28b8993874
+   tag:         FREEFEM_1_38
+   user:        lehyaric
+   date:        Mon Apr 26 11:58:47 2004 +0200
+   summary:     Initial revision
+
diff --git a/HISTORY_BEFORE_2005 b/HISTORY_BEFORE_2005
new file mode 100644
index 0000000..da01969
--- /dev/null
+++ b/HISTORY_BEFORE_2005
@@ -0,0 +1,638 @@
+beginning:  november 21,  2001:  version 1.08.
+----------------------------------------------
+
+2001/11/22:  correction  of operator == and != 
+2001/11/23 , version: 1.09: correction  (with g++) 
+template<class A>  struct SameType, type of OK must be int and not bool 
+
+2001/11/24   add fonctionality in plot,  bb=[[x1,y1],[x2,y2]] 
+ add  loop if enter  character +,-,=,c,C,r  in graphic window.
+2001/11/28
+ correction bug initialization of QuadTree if less than 4 points in the quadtree
+ files  QuadTree.cpp and FQuadTree.hpp
+ add exec("xxx..."); //to execute on system command. "xxx ... " 
+ add  dumptable(cout); //to show all internal table
+2001/11/29:  
+  Version ans graphique + ajout d'option dans plot (cf. doc)
+  correction ajoute renum() des maillage crees. 
+2001/12/10
+  Correct missing check in plot  
+     ex:  plot(1);  trap before now, genere a compile error
+  Correct in the interpolation is full not conforme FE, 
+  do not prolonged by continuity. change 
+  add after line 479 in file lgfem.cpp
+  if (outside && !KK.tfe->NbDfOnVertex && !KK.tfe->NbDfOnEdge) 
+    return   SetAny<R>(0.0); 
+2001/12/12
+  correction in gibbs (mesh renum) reconstruct the array of
+  triangle for each vertex (PB. of interpolation in non 
+  convexe domain) Big bug.
+
+Make version 1.14
+-----------------
+
+2001/12/14
+  correction in trunc mesh, bug if empty mesh is created,
+  and move  a little the test point in a triangle 
+  is not exactly the barycenter.  
+
+2002/01/14
+  correction in probem.cpp line 1309  bug when we write   qft= ...  , in int2d 
+   if (nargs[0]) return *GetAny<const Fem2D::QuadratureFormular*>((*nargs[1])...
+  becomes:
+   if (nargs[0]) return *GetAny<const Fem2D::QuadratureFormular*>((*nargs[0])...
+2002/01/15
+  in lgfem.cpp remove line 522  reffecran();//bug if not graphique some time
+  in file MeshGeom.cpp line 108 bug if name == 0 ;  add test before the cout like 
+    if(name) cout << " ... " << name << .... 
+  correct the name of the exec file (FreeFee++ -> FreeFem++) in Makefile
+2002/02/03
+  in Mesh2.cpp in preinit() add call to srand(),
+    to get the same  mesh with the same data. 
+  correct 
+  mesh tth=th; 
+  
+Make version 1.15
+-----------------
+
+2002/02/20
+   Add periodic boundary condition see the manual //\index{periodic}
+
+Make version 1.16
+-----------------
+
+  Add Parallele Mpi 
+  correct bug in SegmentationFault.edp missing placing of delete[] operator
+  put declaration in  for
+  wait =xx change the default value of wait
+  ofstream f("foo.txt",append)  open a file in append mode
+   add NoUseOfWait=true;    never wait for run test easly\index{NoUseOfWait}
+
+Make version 1.17 2002/03/20
+----------------------------
+
+  Make default iso value changing with zoom option.
+  Add GMRES solver   dimKrylov= ,  tgv= //\index{GMRES}\index{problem!dimKrylov=}\index{solve!tgv=}\index{problem!tgv=}
+ 
+april 2002
+  Make the current version without CheckPtr, and 
+  correct some bug in string allocation (forgetting +1 in some length)
+  Improving the speed of the software
+  add CPUTime global bool variable to print the CPU time of each instruction.
+  correct some printing without verbosity 
+  adding some checking in array management 
+  Add option in the Makefile (gnumake)
+
+Make version 1.18 the 2002/04/08  
+--------------------------------
+  
+  Big correction in automatic cast see  bugv1.18.edp
+  correction in interpolation of  label see also bugv1.18.edp
+  Big correction in construction of non-symetrix matrix (see BUG)
+
+
+
+Make version 1.19 2002/04/18
+----------------------------
+
+   Correction in Quadtree integer overflow when 
+   interpolate solution of from one big domain to a very small one.
+
+   Correction in embedded function (return problem)
+   Correction in return type of function (right value an note left value)
+   Correction cast bool to int, so lots of bug in expression 
+   like  (region==2)*5 given alway 0, invisibl before 1.18 (because bug in
+   automatics cast)
+
+Make version 1.20 2002/04/25
+----------------------------
+
+  Correction of bug in interpolation on non convexe domain.
+  correction of bug in periodic boundary condition (pb of sens(in french))
+  correction some compilation bug under g++ v3.0 in RNM file
+  correction find common point buildmesh (change threshold value)
+
+Make version 1.21 2002/04/29
+----------------------------
+
+  Add Non linear Conjugued Gradient (CGNL) routine.
+  correct bug in linearGC with non zero right and size.
+
+Make version 1.22 2002/05/02
+----------------------------
+
+ all optimisation tool from //\url{http://coool.mines.edu/}
+ Add BFGS optimisation tools form  cool //\index{BFGS}
+ correct bug in CGNL, correct tgv=, in linear form //\index{CGNL}
+ make algo.edp example 
+
+Make version 1.23 2002/05/13
+----------------------------
+
+  correct bug of the symetric matrix are independ of  x,y,..
+   add line at  285, in file problem.cpp: 
+          MeshPointStack(stack)->set(T(pi),pi,Ku);
+
+  correct bug in sign of int1d in linearform, 
+    so change in exemple fluidstructure, schwarz-no-overlap, LaplaceP1, 
+    aalapacien, lapacienprecon
+  correct some bug in -= operator with  result of *. */ 
+  add some operator:
+    -square(u) = u^2  //\index{square}
+    -intalledges(Th)(...) to compute integrale on all edges of all triangle //\index{intalledges}  
+    for error indicator add global :
+    -lenEdge the len of the current edge //\index{lenEdge}
+    -hTriangle the size of the current triangle //\index{hTriangle}
+    -area the area of the current triangle //\index{area} 
+
+Make version 1.24
+-----------------
+
+  add in BamgFreeFem.cpp after line 211 to set name 
+    Tn->name= new char[strlen("msh2bamg")+1];
+    strcpy(Tn->name,"msh2bamg");
+   add -  of linearform and bilinearform see LaplaceP1bis.edp 
+
+   correct: July 8, 2002
+   Vh u1,u2,v1,v2; 
+   bug in problem(u1,u2,v1,v2,.... ) = 
+   in file: FESSpace.hpp line 193:
+   { throwassert(dim_which_sub_fem[N-1]>=0 && dim_which_sub_fem[N-1]< nb_sub_fem);
+     for(int i=0,n0=0,l=0,i0=0; i<k;  i++,n0+=t.N,i0+=t.NbDoF)
+         for (int j=0;j<t.pij_alpha.N();j++,l++) {
+           pij_alpha[l].i=t.pij_alpha[j].i+i0;
+           pij_alpha[l].p=t.pij_alpha[j].p;
+           pij_alpha[l].j=t.pij_alpha[j].j+n0;
+         }                         
+    } 
+
+    add plot of list of border //\index{plot!border}
+
+    add init array:
+
+    real[int] a=[1,2,3,5.6,7,8,9]; //\index{array!initialisation}
+
+Make version 1.25 
+-----------------
+
+ 13 aout 2002 Major Bug in : FESpace.hpp ligne 199
+
+  All the non scalar problem with same kind
+     of finite element do not work: 
+
+    FESpace.hpp ligne 199
+      for(int i=0,n0=0,l=0,i0=0; i<k;  i++,n0+=t.N,i0+=t.NbDoF)
+        for (int j=0;j<t.pij_alpha.N();j++,l++) {
+          pij_alpha[l].i=t.pij_alpha[j].i+i0;
+          pij_alpha[l].p=t.pij_alpha[j].p;
+          pij_alpha[l].j=t.pij_alpha[j].j+n0;
+          }                         
+    become
+     // Warning the componant is moving first 
+        for (int j=0,l=0;j<t.pij_alpha.N();j++) // for all sub DF
+          for(int i=0,i0=0; i<k; i++,l++) // for componate
+          {
+          pij_alpha[l].i=t.pij_alpha[j].i*k+i;   //  DoF number
+          pij_alpha[l].p=t.pij_alpha[j].p;       //  point of interpolation
+          pij_alpha[l].j=t.pij_alpha[j].j+i*t.N; //  componante of interpolation
+          }                         
+ 
+   two corrections in problem.cpp :
+     2 missing  delete     (example laplacienprecon.edp)
+     2 delete -> delete [] (example testFE.edp) 
+
+ 26 septembre 2002 
+   add New Finite element RTortho (a conforme //\index{RTortho}
+    FE in $H(curl)$ like RT  conforme FE in $H(div)$.
+    see exemple aaRT.epd
+   correct the computation of dx(v) and dy(u) in [u,v] RT finite element
+    function. 
+   compile on hpux 11 with gcc 3.2 see Makefile-hp9000s700
+   correct argument passing in GMRES routine
+
+Make version 1.26 le 26 septembre 2002
+--------------------------------------
+
+ 05 nov. 2002 Correct very small mistake in bamglib  part.
+
+ 19 nov 2002:
+  add:
+   -tanh function //\index{tanh}
+   -qf2pT4P1 a triangular QuadratureFormular  
+	(4P1 the qf2pT QuadratureFormular) //\index{qf2pT4P1}
+   small change une meshadapt to just compute the metrix see exemple
+      convectapt.edp 
+    make interpolation matrix between to FEspace (not wet finish)
+
+ 3/12/2002 
+  make correction to get a not to bad linenumber in error.
+  add add test is used of unset x,y to make a error.
+  add checkmovemesh(Th,[x+u,y+v]) function to return the //\index{checkmovemesh}
+  value of the area of the minimal triangle of the movemesh.
+  see mesh.edp example.
+
+ 23/12/2002:
+  add eigen value solver  //\index{eigenvalue}
+  see eigen README_ARPACK to compile
+  see  examples++-eigen to test.
+
+Make  version 1.28 2/1/2003 
+---------------------
+09/1/2003: 
+ add sub array option in array:  //\index{array!sub}
+  real[int] tab(100);
+  tab(:) = array from 0 to 99=tab.n-1
+  tab(2:10)  sub array from 2 to 10
+  tab(2:10:2)  sub array from 2 to 10 by step 2
+  tab(2:10:2)[0] = 5 ; => modificaton of tab[2] = 5;
+  tab(2:10:2)[1] = 6 ; => modificaton of tab[2+2] = 6;
+  
+  
+16/01/2003
+add macro generation like cpp preprosseur://\index{macro}
+this is usefull to make automatic diff
+exemple: 
+real cc=2;
+macro f(u) (cc*(exp(u)-1)) //
+macro df(f) (cc*(exp(f)))  //
+real u=1;
+cout << (cc*(exp(u)-1)) << endl;
+cout << f(u) << endl;
+cout << df(f(u)) << endl;
+
+see macro.edp  for more detail:
+  
+22/01/2003 
+in file lex.cpp add .c_str() for compilation problem 
+on g++ 2.95   
+  
+15/04/2003
+add new finite element:
+ P1b  P1 + Bubble  //\index{P1b}
+ P1dc P1 discontinious //\index{P1dc}
+ P2dc P2 discontinious //\index{P2dc}
+
+correct bug periodic BC with vectorial FESpace, 
+add the code.
+
+Make version 1.31
+-----------------  
+
+23/04/2003
+  small correction to compile with  g++ 2.95.2 in eigen value tools
+
+26/04/2003
+  add function triangulate(filename) to build the //\index{triangulate}
+  Delaunay Triangulation of a set of points in R^2.
+ to build a function form a set of : x y f(x,y)
+ see exemple mesh.edp  
+
+
+make version 1.32 (29/04/2003)
+-----------------
+
+ -add optimization in automatique interpolation 
+  CPU of all tutoral exemples 172 s( mon my Mac) new version 1.33 (with graphics)
+  CPU of all tutoral exemples 167 s( mon my Mac) new version 1.33 (without graphics)
+  CPU of all tutoral exemples 169 s( mon my Mac) new version 1.32 (without graphics)
+  bofbof.
+  
+ -correct bug in macro generation, a macro existe just in a block {..}.
+
+ //  lex.cpp  
+    if ( ret =='{') { /*cout << " listMacroDef->push_back"<< endl; */
+      listMacroDef->push_back( MapMacroDef() );}
+  else if (ret == '}') {/*cout << " listMacroDef->pop_back"<< endl;  */
+       listMacroDef->pop_back( );}
+
+ -small correction to be compatible with g++ version 3.3
+
+Make version 1.33 01/07/2003
+-----------------------------
+
+ - small correction in parallelempi.cpp add a ; line 159
+
+ - comment line 519 in file AFunction.hpp (pb with g++ 3.3.1)
+	 // operator Expression() const {return f;}
+  (double definition)see line 527
+	  operator  const  E_F0 *  () const {return f;}
+
+ - correct Makefile for mpi version
+ 
+
+21/08/2003:
+ -  Bug in optmization in case on non constant robin boundary condition
+    correct 
+ -  add grey=1  ion plot command to make  grey plot, and //\index{grey=}\index{plot!grey=}
+   correct small mistake ( on mac and X11 , ...)
+ 
+ 
+Make version 1.34 (22/08/2003)
+------------------------------
+
+16/09/2003
+ - bug in local variable stack if the size is larger the 8 ( complex)
+  complex a;real b;
+  a=0;b=1; 
+  // here a is 0+i; 
+  correction is:
+  voila la correction dans AFunction.hpp vers la ligne 1486: 
+  template<class T>
+  inline Type_Expr  NewVariable(aType t,size_t &off) 
+   { 
+     size_t o= align8(off);//  align    
+   //  off += t->un\_ptr\_type->size;
+   // bug    off += t->size;
+    off += t->un_ptr_type->size; // correction 
+    return  Type_Expr(t,new T(o,t));
+   }
+
+02/11/2003
+  -correct probleme of renumbering the traingles of a  mesh 
+   when reading in the bamg software (with readmesh command).
+   This implies error when we restore mesh and non P1 finite element
+   solution, see example saveandrestore.edp. 
+  
+28/11/2003
+  -correction of bug in window version 
+   add the umfpack sparce linear solver (this solver have some problem
+   in some case), so I do'nt put this one in default linearsolver. 
+   remark, I think is due to the way of taking Dirichlet boundary condition
+   Huge value on diagonal (tgv=1e30) and Stokes matrice.//\index{problem!tgv=}\index{solve!tgv=}
+
+  -put this file on the web
+  -put on the web 
+  -the codewarroir projet to build arpack ands umfpack lib.
+  
+Make version 1.36   
+-------------------
+
+ - Change the graphic window in Window xx version
+
+8/12/2003
+ - repare in mpi version  get mesh via mpi
+ - forget build quadtree soo the interpolation bugs
+ - add 4 line in file parallelempi.cpp in mesh serialization (recivied
+   //  add 3 line FH 08/12/2003  forget build quadtree sorry      
+       Fem2D::R2 Pn,Px;
+       a->BoundingBox(Pn,Px);
+       a->quadtree=new FQuadTree(m,Pn,Px,m->nv);
+      
+18/12/2003
+  - add in mpi version://\index{broadcast}
+    broadcast(processor(1),th); //  broadcast  th from proc 1 to all other.
+    see the mpi exemple
+    change the precision to 6 to 12 is savemesh.
+  - add tool to change the default precision on ostream or ofstream 
+    with the C++ syntaxe
+    see saverestore.edp example.
+    cout.precision(12); //\index{precision}
+  - add UMFPACK linear solver ( not well test)   //\index{UMFPACK}
+    http://www.cise.ufl.edu/research/sparse/umfpack
+  - add full matrix with few operator //\index{matrix!full}
+     real [int,int] A(10,10); 
+     A= 2;
+     A(5,5) = 2;
+     cout << A << endl;
+  -add array of mesh //\index{array!mesh}
+
+08/01/2004
+   - merge all mesh example in one file call mesh.edp
+   - add discontinuous Galerkin method (see LapDG2.edp example)
+   - add syntaxe to get mesh information  (see end of mesh.edp exemple)
+   - add meshsplit  function to make conformal recusive locat mesh spliting //\index{meshsplit}
+     (see mesh.edp example)
+   - add dynamic load via dlopen  see load.edp in example++-load  //\index{dynamic load}
+
+Make version 1.37 
+-----------------
+
+15/01/2004
+  - change metrix= in metric= the in adapted mesh metric=[m11,m12,m22]//  \index{meshadapt!metric=}
+    (change the ordre to compatible with the fonction order with IsMetric=1)
+
+02/02/2004
+  - change printing in gmres algorithme
+  - print the size of matrix 
+06/02/2004
+  - change intalledges  in change of discontinuous Galerkin loop also boundary edge//\index{intalledges}
+	 jump(u) is external - internal value of u with normal go to internal to external 
+	 jump(u)  on boundary is -internal value of u //\index{jump}
+	 average(u)  on boundary is internal value of u  //\index{average}
+  - add nTonEdge to get the number of Triangles which see the  current edge//\index{nTonEdge}
+  so see the new LapDG2.edp example for full detail
+07/02/2004
+  - correct bug in real[string] map; // map array  \index{array!string}
+        change in get_element and operator <  of String 
+  - add int array 
+Make Version 1.38
+----------------
+  - remove (void) line 14 of throwassert.hpp file (erreur compile g++3.3.5 )
+  make change in macro expansion of shell (no perfect to day)
+     
+ 16/04/2004 
+  - add matrix tools 
+    bluid interpolation interpolation matric from a FEspace VH  to an other FEspace Vh
+       matrix Ih=matrix B= interplotematrix(VH,Vh); 
+	// where  Vh correspond to  line and Vh to column 
+       the named parameters can be 
+          t= true or false  (to bluid the transpose or not matrix)
+          op=0 ,1 or 2 (to build the interpolation of value, dx,dy )
+          inside=true or false  (to remove or not  all ouside interpolation  quadrature point)
+     build diagonal  sparce  matrix (type is morse)
+     do the matrice product of to sparce matrix (type is morse)
+   add build a sparce matrix from a full matrix so if you have install UMFPACK solver
+     it is possible to solve systeme with full matrix.
+   add set function to change the solver 
+   see exemple  sparce-matrix.edp 
+	   
+  - correct bug flag ouside of mesh 
+    add line in file fem.cpp line 864
+       outside=true; 
+     so some time the P0 interpolatation is no zero
+     add new king of mesh of multiplicator data :
+     mesh emptyTh=emptymesh(Th); // to build a mesh with no internal point 
+     see mesh.edp example
+
+Make Version 1.40
+-----------------
+
+  - add les linear combination of sparce matrice
+  - set a sparce solver to a sparce matrice (to day just UMFPACK)
+  - transforme a full matrix in sparce matrix
+  - add istream f("toto");
+     f.good() or f.EOF to test state the file 
+     remark: the state is set after the read so the previous value is wrong
+
+02/06/2004
+----------
+  -  correction in call macro with string "..." parameter  
+24/06/2004
+----------
+   add tools to bluid periodic adapmesh  see sphere.edp of exemple
+   add HaveUMFPACK global variable see sparse-matrix.edp exemple   
+   Change all the structure of the software 
+   Use ./configure to build all the make file see (README)
+   you can build the Window version with g++ under cygwin 
+   ( http: cygwin.... )
+
+Make Version 1.41 
+-----------------
+
+07/07/2004 
+----------
+an anonymous CVS server is avialable to get FreeFem++ source
+cvs -d :pserver:anonymous at idared.ann.jussieu.fr:/Users/pubcvs/cvs login
+(password = freefem++)
+cvs -d :pserver:anonymous at idared.ann.jussieu.fr:/Users/pubcvs/cvs freefem++ co
+the TAG release_1_41_before_packaging is created
+
+30/08/04
+--------
+ Correct  divide by 0 in plot instruction  when the bounding box is flat.
+ Set default solver to LU because UMFPACK sometime by bad result.
+ Correct all g++-3.4 error
+ Optimize Choleski and Crout solver (divide cpu time by two on pentium)
+ Add stuff for adding new finite element due to the new software achitecture.
+
+31/08/04
+--------
+ Add string[string] array
+ correct bug in  macro expansion 
+     macro parameter will be not expanded 
+  example of bug:
+     macro a(i) i //
+     macro b  a(x)  //  bug here 
+     b = 1 ; // we get "i=1" or we want "x =1"
+
+Make Version 1.42
+-----------------
+
+11/10/04
+--------
+ Add Finite element with complex value, and matrix<complex> 
+ see sparse-cmatrix.edp  and  FEComplex.edp files
+ for a full examples
+
+ Vh<complex> ur; 
+ varf av(u,v)=int(Th)(u*v*(1i+1));
+ Matrix<complex> A = vav(Vh,Vh); 
+ // warning don't mixte Matrix<complex> and Matrix<real> in a expression     
+ 
+19/10/04
+--------
+  correct UMFPACK driver problem, ands set this solver as a default 
+    solver.
+  add finite element connectivite inquire ice FE.epd exemple 
+  fespace Wh(Th,P2);
+   Wh.nt //  given the number of element 
+   Wh.ndof //  given the number of degree of freedom
+   Wh.ndofK //  given the number of degree of freedom on one element 
+   Wh(k,i)  // given the number of i  degree of freedom of element k.
+   //  with $0 <= i <  Wh.ndofK $ and  $0 <= k <  Wh.nt $ 
+
+}
+  build the source and compile version 1.43 
+01/11/04
+--------
+   correct problem on period adapted mesh if orientation are reverse.
+   add cvs tag release_1_43
+   Now  the current version is 1.44 (CVS)
+
+04/11/004
+---------
+   correct problem in LinearGMRES and LinearGC 
+   in LinearCG algorithme for solving A*x = b0+b
+   the matrix function can compute A*x or A*x-b0 ,
+   and the other part b of the right end side can  exist or not.
+   But in LinearGMRES must the function must compute A*x and 
+   b0 can't exist. 
+   see algo.edp  exist for  a full example
+
+06/12/2004
+__________
+  change  function name interplotematrix to interpolate
+  correct  bug introduce in 04/12 change
+  a new graphic FreeFem++-cs: integrated development environment (located in src/ide)
+  see REAME and maunal-full.pdf
+  add new examples++-tutorial
+  mat_interpol.edp  # to test interpolate function
+  shur-comp.edp  # a shur complement domaine decomposition
+
+11/12/2004
+ TAG release_1_44
+ now the current version is 1.45
+
+29/12/2004  
+   add concat operator # in macro generator.
+
+04/01/2005
+   add new quadrature formular on edge (a,b) :qf1pElump  : 1/2(f(a)+f(b))*length(ab)
+
+05/01/2005
+  correction bug  unset FE variable dans le .edp   =>
+  use a null pointeur (in sol) to set the *X  array in  problem.cpp
+   (*X)[K(df)]= (*sol[kfe])[SK(kdf)] ;  
+   make some time make a seg trap error. 
+06/01/2005
+   rewrite the macro generation tool to be more to suppress some bug
+   in argument subtition
+   correct error in line numbering in case of newline in string
+   cosmetic change in output 
+
+20/01/2005
+   count () in macro parameter to handle   couple of () in macro parameter.
+   macro sum(a,b) (a+b); 
+   sum((1),2) // now works and given (1)+2
+   sum(atan2(2,1),2) // now works and given atan2(2,1)+2
+   
+   correct bug in linear combination of sparce matrix:
+   the correction is:
+    change line 1069, in file MatriceCreuse_tpl.hpp
+           mij[make_pair(i,j)] = coef*a[k];
+    to
+           mij[make_pair(i,j)] += coef*a[k];
+    
+    Correct a segfault if second derivative of test function exist in 
+    problem definition.  The Change in problem.cpp:
+    resize : KN<double> buf(Vh.MaximalNbOfDF()*3*Vh.N);
+    to     : KN<double> buf(Vh.MaximalNbOfDF()*last_operatortype*Vh.N);
+
+   
+24/01/2005
+   add  named parameter nbtx=..  in buildmesh  function to change the default 
+   maximal number of vertex in the build mesh.
+
+26/01/2005
+   correct pb with  --disable-pdf in configure.ac
+   correct pdflatex and latex compilation 
+   correct  FreeFem++.app problem when usind in a shell script FreeFem++-CoCoa
+   correct web site and distrib file  freefem++-1.45-2.tar.gz
+
+02/02/2005
+   correct problem with socket in FLTK in freefem++-cs  (not wet finish) ALH
+   add nbvx=  named parameter to change the default maximum number vertices in creted mesh
+   in builmesh (see mesh.edp exemple)  
+   
+10/02/2005
+   add 2 new quadrature formular qf7pT and qf9pT with respectively 15 and 21 points
+   add  P2b a new finite element  : P2 + bubble 
+   make drag and drop on ide version + copy paste 
+
+14/02/2005
+   create a error  when you do   uh = ..  when uh is a  componant of a vectorial fe 
+     element function (for exemple fespace Vh(Th,TR), Vh [uh,vh]; uh = 1 (error here ;)
+     because it's impossible to build   uh and vh independantly.
+
+17/02/2005
+   FreeFem++-cs: Communication speed between client and server has been
+   increased ten-fold (ALH)
+
+   
+23/02/2005
+     add jump and mean of complex function  (FH)
+
+23/02/2005
+    FreeFem++-cs: grammar-driven syntax highlighting works on
+    (examples++-tutorial/...) Laplace.edp, adapt.edp and
+    adaptindicatorP1.edp (ALH)
diff --git a/INNOVATION b/INNOVATION
new file mode 100644
index 0000000..45ede95
--- /dev/null
+++ b/INNOVATION
@@ -0,0 +1,1214 @@
+version 3.34-1 
+ - correct lot of mistake for simple compilation of 
+    hpddm interface ..
+ - add no mandatory lib for petsc 
+      write the WHERE-LIBRARY search lib in awk (more simple ) 
+ version 3.24
+ - configure : 6/02/ 2015
+    correct mpi for  sgi uv computer
+    find gsl lib 
+    add find petsc (in progress) 
+    add missing file in distrubuteion
+ -  correct for compilation with g++-4.9.1 -std=c++11 ( without downlaod)
+ - add hd5 interface  (13/01/2015) 
+    Thank to Mathieu Cloirec CINES - http://www.cines.fr
+   voir example iohd5-beam-2d.edp	    iohd5-beam-3d.edp
+ - add find of libgsl  in configure script 
+ - correct pb of memory leak in case 
+   matrix A = ...; in loop ( this occur in lot of case, tanks to P. Jolivet )
+   correct small memory leak in use of routine due to debugstack. 
+ - correct bug in periodic condition in case common dof with periodic.  
+ - correct big bug in memory gestion of sparse matrix
+ version 3.32 
+ - correct of problem of plugin and mpi,
+    build all dynamics lib with and without mpi, 
+    the mpi version is install  dir lib/mpi 
+ - correct of plugin MUMPS.cpp for complex value. 
+ - add vectorial operator a/v  and v/a where a est scalar and v vector like real[int], ...   
+ version 3.31-3 (rev 3053:4e164226411d 12 Aug 2014) 
+ - correct the problem of size of arrow in 2d plot 
+  version  3.31-2 (rev 3052, 11 july 2014) 
+ - correct stop test function in LinearGC (for zuqi.tang at inria.fr)
+  build tar.gz distribution (rev 3050) 
+  build version MacOs 3.31-1
+ - correct bug put in DG formulation (rev 3044)
+   jump, mean , was wrong from Sun Jun 29 22:39:20 2014 +0200 rev 3028
+  version  3.31-1 (rev 3042, 10 july 2014) 
+ - function to put your stop test in LinearGC and NLGC
+   the prototype is 
+    func  bool stop(int iter,real[int] u,real[int] g)	;
+    	  {    return g.linfty < 1e-5 || iter > 15;}
+    LinearCG(DJ,u,eps=1.e-15,nbiter=20,precon=matId,verbosity=50,stop=stop);
+    
+
+ - add functionnal  interface  to arpack (Eingen Value) 
+
+    func real[int] FA(real[int] & u) { real[int] Au=A^-1*u;return Au;}
+    func real[int] FB(real[int] & u) { real[int] Au=B*u;return Au;}
+    int k=EigenValue(n,FA,FB,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10,maxit=0,ncv=0);
+
+  see examples++-eigen/LapEigenValueFunc.edp for a true example
+
+
+version 3.31  (rev 3037, 1 july 2014)
+ - re-add tan function for complex number  
+ - correct a big mistake in LinearGMRES , the resulat are complity wrong,
+   correct also the algo.edp
+ -  add sqr functon of O. Pironneau
+ - correct update of mercurial depot (rev 3034, 1 july 2014)
+ - correct misstake  in examples++-3d/MeshSurface.idp 
+   about   computation metric in function build surface  Sphere mesh
+   and add a function to build Ellipsoide surface mesh 
+  func mesh3 Ellipsoide (real RX,real RY, real RZ,real h,int L,int orientation)
+ - correct a bug the DG with periodic boundary condition with only one 
+   layer of element.  
+ - add pluging "bfstream" to write and read in binary file (long, double, complex<double> and array)
+   see bfstream.edp for an example. 
+version 3.30-1 may/2014 ( hg rev: 3017)
+ - add levelset integral on 3d case ( on levelset and under level set) 
+ - correct problem with Ipopt / lapack configure ...
+ - add BEC plugin of Bose-Enstein Optimisation
+ - standardisation movemesh3 -> movemesh ( same parameter of 2d version )	
+ - correct jump in basic integrale to be compatible with varf definition
+    jump is not zero on boundary, it is - boundary value ..
+    fespace Ph(Th,P0);u= 1;int1d(Th)( jump(u) ) = - length border . 
+ 
+version 3.30. ( for windows hg  rev : 3013)
+ - add binary ios:mode constant, to open file in binary mode under window
+    to solve pb of seekg under windows  
+ - add multy border april 23 2014 , (hg rev : 3004)
+    syntaxe example:  
+  // i is the index of the the multy index 
+  // the number of sub border is given by teh size if the array to set the number of seg on the border ..
+  // so for multy border the  number of seg of the border , must be  in int[int] array 
+  real[int] RC=[ 0.1, 0.05, 0.05, 0.1],
+            XC= [0.2,0.8,0.2,0.8],
+            YC= [0.2,0.8,0.8,0.2];
+  int[int]  NC=[-10,-11,-12,13]; 
+
+  border bb(t=0,1;i) 
+  {
+  //  cout << " i = " << i << endl; 
+    int ii = (i+1)%4; real t1 = 1-t;
+    x = xx[i]*t1 + xx[ii]*t;
+    y =  yy[i]*t1 + yy[ii]*t;
+    label = 0; ; 
+  }
+  border cc(t=0,2*pi;i) 
+{
+	x = RC[i]*cos(t)+XC[i];
+	y = RC[i]*sin(t)+YC[i];
+	label = i+1; 
+}
+  int[int] nn=[4,4,5,7];
+  plot(bb(nn),cc(NC),wait=1);
+  mesh th= buildmesh(bb(nn)+cc(NC)) ; 
+  plot(th,wait=1); 
+  
+ - add ltime() (rev 2982)  function returns the value of time in seconds 
+       since 0 hours, 0 minutes, 0 seconds, January 1, 1970, (int) 
+ - add new macro tool  like in C  (rev 2980)
+    FILE,LINE,Stringification() to get line number and edp filename,
+    add quote to a parameter after macro generation … 
+    Like in 
+    cout << "in " << FILE << " line " << LINE << "    -- '" 
+         << Stringification( "zzz" aa  () {} +  /* */  bb cc) << "'" << endl;
+  add new int2d on levelset  in 3d  (int test)
+  add basic  func mesh3 Cube(int nx,int ny,int nz) in cube.idp file.
+version 3.29  (hg rev 2973)
+  - add int storagetotal(); and int storageused(); function 
+     to get static of malloc ( memory storage usage)
+   
+  - correct problem of region evalution in jump and mean function 
+version 3.28  ( merge with freefem++-cs tool)
+  - add download/getall perl script to download all related soft
+  - add  int1d on isoline for matrix ...
+  
+version 3.27 
+ - correct bug in display of P1b finite element in 3d 
+   error in SplitMesh<R3>  function  (Thank to O. Pironneau) 
+ - add  AddLayers(Th,suppi[],sizeoverlaps,unssd[]);
+ - add  tool to trunc to get element numbering for Thn to Tho 
+    int[int] In2o(1),Io2n(1); 
+    Tho =  trunc(Tho, x<0, new2old=In2o, old2new=Io2n);
+ - add restrict function for get dof numbering old to new
+    fespace Vnh(Thn,Pk), Voh(Tho,Pk);
+    int[int] n2o=restrict(Vnh,Voh,n2ok);     
+ - correct mistake in gsl interface random number (9/1/14)
+     missing all random  distribution ..
+ - add interface  with gsl random number generation in test .. 
+ - correct pb of compilation under window (mingw32/msys) 
+6/1/14 (ALH)
+ - Creating documentation hyperlinks (in emacs orgtime and in Doxygen format)
+ - New script build/orgindex and file index.org list all hyperlinks in the FF source in Emacs org-mode format
+ - Set all hyperlinks to relative paths to make sure that they work from any location
+ - Separate download script for all third-party software [[file:download/getall]] (request from FH)
+ - created common makefile goals in [[file:download/common.mak]] for all downloaded packages (request from FH)
+   - changed [[file:download/arpack/Makefile.am]] to make use of [[file:download/common.mak]]
+   - done for [[file:download/blas/Makefile.am]] as well
+ - added option --enable-mkl-mlt in [[file:configure.ac::enable_mkl_mlt]] to allow FF to be linked with the
+   multithreaded MKL when an external library requires it (request from Atsushi Suzuki)
+version 3.26-3  09/12/2013 
+   correct problem with openblas need pthread lib 
+01/12/13
+    install dowload lib 
+    update lapack interface in examples.
+    add WHERE_LIBRARY-file in install 
+    change the order of seach lib with   WHERE_LIBRARY-download 
+       WHERE_LIBRARY-config        WHERE_LIBRARY
+    remove all relative in WHERE_LIBRARY-config
+    correct of superlu compile problem
+13/11/203  Pass to version 3.26 ...
+  - correct pb of ambiguity with new complex lib 
+31/10/2013  compilation on MacOS 10.9 with compile of xcode 5.0.1 
+  - correct the pipe.cpp to compile with clang-500.2.79 
+  - remove of warning message genrate by clang++ -std=c++11 (version clang-500.2.79)
+  - correct also compilation problem 
+  - correct error in case of block matrix with block of 0 row or 0 column. 
+21/10/2013 (ALH)
+ - umfpack configuration cleanup (request from Fred)
+ - blas configuration cleanup (request from Cico)
+   - configuration option --enable-generic-blas has no effect anymore, removed
+   - Atlas compilation directives have no effect anymore, removed
+   - Moved OpenBLAS compilation from FFCS source tree to FF source tree
+ - Added configure option --disable-system-fftw to skip any default FFTW library installed on the system
+ - Changed location of lapack WHERE-library setup in [[file:configure.ac::WHERE_lapack]] to insure that it is always
+   defined (request from Fred)
+ - changed FFCS Fortran MPI configuration for MPICH2
+ - split DOC makefiles into Makefile.am and figs.mak to suppress automake warnings about portability
+ - moved build/download script from FFCS to FF before reorganizing FF downloads (request from FH)
+10/9/2013 (ALH)
+ - Corrected pastix compilation for FFCS on MacOS 10.6
+ - Removed dependency from lg.ypp to lg.tab.?pp in [[file:src/lglib/Makefile.am::lg.tab.?pp]] to avoid automatically
+   generated conflicts
+05/09/2013 put version .tar.gz on the web 
+  - correct makefile wget in pastis and superludist  
+  - correct compile of load example :  paradiso, gsl automaticaly 
+ - add AutoGeneratedFile.tar.gz  a file contening all 
+    file build by autoreconf in case of non automake tools (1.13)
+ - add missing file in dist or in mercurial distribution
+ - correct download of scotch un curl 
+ - correct problem in a*[b,c, ... ]' in case of complex value   
+5/9/2013 (ALH)
+ - force Umfpack build to run sequentially (parallel make crashes with "pipe from processes is a directory"?)
+ - pARMS download URL changed to http://www-users.cs.umn.edu/~saad/software/pARMS/pARMS_2.2.php (thanks Fred)
+ - corrected download/mumps parallel compilation (WHERE was not built properly)
+ - Removed all Mercurial-tracked files from .hgignore
+ - added options --with-[package]-include= and --with-[package]-ldflags= to avoid downloading existing packages
+ - Parallelized MUMPS compilation in download/mumps (and mumps-seq)
+ - Applied a patch from Fred for compiling SuiteSparse on Slackware64-14.0
+ - Added configuration option --enable-hypre (disabled by default, contrary to other tools)
+ - Deactivate FFTW download when a local version is found (request from Helmut Jarausch)
+10/7/2013  (version 3.25)
+ - remove of Makefile.in configure for the hg distrubion 
+    use :  autoreconf -i  # too build Makefile.in 
+         before to configure 
+         need automake version 1.13 ... 
+ - merge FFCS (ALH) version and  ff++ version (FH) of freefem++ programs
+ - remove all automake file form the hg data base
+ 
+ - add new parameter to ffglut for demo of freefem++ 
+    ffglut  [-nv|-v|-vv|-vvv] [-wait 0.5] [-g 512x300+10+10] [-t title] [file]
+    all number can be change the wait is in second 0 is default value nowait bewteew plot
+    -g 512x300+10+10 is the geometry of the  graphic window
+    -t the title of the windows 
+26/6/2013 (ALH)
+ - created a build/ subdirectory for build tools
+ - enabled parallel make ("make -j")
+ - created a separate file (acmpi.m4) for complex MPI configuration options
+ - added configuration option --enable-ffcs to make the FF source compatible with FFCS
+ - backported all current FreeFem++ patches for FreeFem++-cs into the FreeFem++
+ - started main doxygen page mainpage.dox
+9/06/2013
+ - correct extract function of mesh Lo Sala <salalo80 at gmail.com>
+ - correct int2d on levelset  see example intlevelset.edp 
+ - correct automake TESTING part (in progress) 
+ - correct typo on the doc with .*= ./=  operator
+ - correct bug in RT0 3d , code in the construction of the DOF.
+   the bug is all dof on border  face of same elemnt have same dof number.
+   thank to Laurent Bernard <laurent.bernard at lgep.supelec.fr> 
+version 3.23
+ - do cleanning in version remove x11, glx, std : freefem++
+   clean compile option for clang and clang++ compiler 
+
+ - add flags to remove internal boundary in 2d,3d in function change 
+     rmInternalEdges=1
+ - correct glumesh in case of no mesh in 2d
+version 3.22
+ - add multi windows graphics ; WindowIndex=0 in plot function
+   add new event in graphic windows 
+     * to set/unset  default graphics stat to previoux plot 
+ - add getenv, setenv , unsetenv function in shell plugins for gestion of environnemnt variable for 
+   openmp. 
+ - correct pb un trunc for 3d mesh with too flat element (sliver) , and cleanning code .
+ - correct bug in gestion off outsite flag is 3d in case of bute force (searchMethod>0) 
+version 3.21-1 
+ - correct bug  a=b' ; of full matrix 
+ - bug in assert on 3d mesh of huge dimension with periodic condition.
+ - correct build Delaunay 3d mesh of set of point. 
+   see examples++-load/convexehull3d.edp
+version 3.21 frev 2013
+ - n, resize in array of finite element function ... 
+     see edp  array.edp file 
+ - correct pb of compilation of Ipopt with clang++ -std=c++11
+ - correct une NSCahouetChabart.epd examples , and correct un doc. 
+    this is a complete rewritting. FH. 12/02/2013.
+ - correct in change function the "flabel=" parameter in 2d and 3d 
+version 3.20-3
+  - add master= in solver of MUMPS interface to set the master mpirank 
+        <0 => distributed matrix. 
+  - correct problem in label generation in freeyams (18/01/2013)
+     all label border was set on 1  before. 
+version 3.20-2
+  - add MUMPS parallel version (in test)
+  - add paradiso seq solver ..
+version 3.20
+ - correct isoline plug in case of sadlle point
+ - change the compilation tools under windows gcc 4/7 + freeglut / ...)
+ - change the compile tools on mac pass to clang++
+ - compile ok of c++11  compiler
+ - add formal tools on array [] or matrix [[],[],]  for elasitic problem. 
+   let A a formal array 
+   if A is matrix 2x2 or 3x3 : trace(A) , det(A) ,    Cofactor(A) ; 
+    A:A  = sum_ij A_ij * A_ij 
+    2*A,   A*2 // muliplication by a scalar 
+
+ -add integration on levelset line (in test) 
+ 
+version 3.19-2
+ - correct pb of C in/output in pluging (in test) 
+ - correct bugs  mshmet pluging in case of double eigen value in eigen
+ - correct typo poblem (string size) when a change the default
+    window size in postscrip in version 3.19-1 to have more 
+    precise postscript plot
+version 3.19-1
+ - add tool to create Quadrature formlar 1d,2d,3d with 
+   plugind: load "qf11to25"
+   real[int,int] tab1(np,2),tab2(np,3),tab3(np,4);
+   QF1 qfe1(norder,tab1);// 1d
+   QF2 qfe1(norder,tab2);// 2D
+   QF3 qfe1(norder,tab3);// 3D
+   where tab(0,i) = weigth , tab(j,i) =  j coord, norder  order of the
+     quadrature 
+   see examples++-load/LaplaceP4.edp for example 
+ - correct download auto compile of
+    mmg3d, mshmet, scotch, ...
+version 3.19 (20 april 2012) 
+ - scotch partionner interface see scotch.edp in examples++-load
+ - add isNaN(x),  isInf(x), IsNormal(x)  function to check floating point
+      of real value x, see ISO C99. 
+ - add function : NaN() and  NaN("") to build NaN real number (double in C) . 
+ - correct error in macro with operator ./=  and .*= 
+ - add Ipopt doc (thanks to Sylvain  Auliac)
+ - add Ipopt interface (thanks to Sylvain  Auliac)
+ - correct 3d trunc bug in case of internal boundary
+      thank to Yoshihiro Tomita <tomita.yoshihiro at gmail.com>. 
+  - add new type of array , array of array
+    see taboftab:edp in  examples++-tuturial
+    real[int] a;  
+    real[int,int][int] m(10);
+    real[int][int] v(10);
+   not well tested.
+version 3.18-2
+ - add plugins with sequentiel  mumps without mpi 
+ - add conversion of re and im part of complex sparse matrix
+   A = C.im; 
+   A = C.re; 
+version 3.18-1
+ - correct Typo error in example 
+ - add generation of error in case of periodic boundary condition 
+   non scalar problem. 
+ - add tools for adaptation of P2 and P3 finite elements with metrics
+   see APk-AdaptEpsDeltaPk.edp APk-FreeFemQA.edp	 APk-MetricPk.edp
+    APk-ExplicitPkTest.edp	       APk-LaplaceDirac.edp
+
+ - New example in in Chapter 3 Navier Stokes Newton NSNewton.edp
+ - add cod to build matrix and vector form varf in 3d in case of
+      different meshes (in test )
+ - correct NSprojection.edp chap3 example (PB in out flow BC.) 
+ - correct compile of mmg3d v4 plugins (small change un distrib archive) 
+v 3.18 (11/01/2012)
+ - rewrite the isoline-P1 plugins (new name isoline.{dll,so,dylib} )
+     see example Leman-mesh.edp and isoline.edp in 
+     examples++-load directory 
+ - correct bug in cas of resize of array with 2 index (full matrix)
+ - correct assert in MPI  in gather and scatter
+ - correct bug in case of return  in loop for or while. 
+ - correct a=int2d(Th,l)(1) in case simple expression  when l is a  array.
+ - build a pkg under macos for distribution .
+v 3.17  (17/11/2011) 
+ - correct PB of pugins: MUMPS, parmetis, metis, mmg34, mshmet 
+ - the new load interface  (for more safe IO)
+ - build mpi for windows with msmpi ( begin) 
+    memory error after end .. 
+ - remove add by default $LIB_MPI in ff-c++ 
+ - change the way add thing in freefem++ in case of  dynamics load 
+   to be  compatible   plugin with freefem++cs  ( solve pb with
+     cin,cout, cerr in  dll may be..).
+   LOADINIT(Init); // where init is a class 
+or do 
+   addingInitFunct FFinit(100,ffinit,"MUMPS_FreeFem"); // where ffinit the init function ...
+v 3.16-1
+ - cmaes interface in scalar and MPI case  (thank to S. Auliac)
+    see doc and examples : cmaes-mpi-VarIneq.edp , cmaes--VarIneq.edp
+ - add NLopt interface (thank to S. Auliac)
+v 3.16 
+  technical stuff: 
+  - correct auto load of mumps
+  - add tool to do automatic load or static load (for testing)
+    see MUMPS_*cpp example 
+v 3.15 
+  - correct all examples++  load and 3d rebuilde the all.edp 
+    and test this examples. 
+  - correct version old bug when full matrix (arry)
+    A=A;' is now correct (set and  initialization )
+    and add  A+=A';    A-=A';
+
+  - reput metis 4.0 form netlib ... (pb of compatibilite with other // soft hips)
+v 3.14-1
+  -   change interface with metis 5.0.1 
+  -   Complete writing of mmg3d interface with version 4 of mmg3d
+      le plugin is "mmg3d-v4.0", the parametre are the same have 
+      command line mmg3d , execpt the file name are not given. 
+  -   remove old bug 3D in interpolation P1 operator 
+      correct bug 29/08/2011 (thanks to rychet at fzu.cz)
+      remove wrong bulid of KHat (memory out of bound)
+
+v 3.14 
+  - correct in configure remove the default -O2 -g autoconf value 
+    and add -g in case of --enable-debug 
+  - a very old error in the on() functionnal
+    the bug is with  a vectorial finite element like RT0, .. 
+     the name of vectorial must     be in lexicographic order 
+     so   u1,u2  is ok but v,u is wrong
+    is correct in version 3.14 the 24/08/2011
+
+  - correct trap in check convect-apt.edp  example
+  - add the existance of patch in configure 
+v 3.13-3 ( 30 june 2011 Seville)
+  - correct the Hips interface (not to bad , in test)
+     load "hips_FreeFem"
+     int[int] iparm(1);real[int] dparm(1);
+     HipsDefaults(iparm,dparm);) // set def option 
+     ( limit to 100 Hips active linear system ).
+  - add interface with MUMPS_4.10.0 version  (with automatic download )
+  - add P1dc3d finite element in pluging  "Element_P1dc1" 
+  - correct bug in gibbs renumbering in 1 case veru sample mesh)
+  - correct bug in interpolation operator with periodic BC
+    mesh Th1=square(2,1), Th2=square(2,2);
+    fespace Vh2(Th2, P1),Ph2(Th&,P1,periodic=[[1,x],[3,x]]);//  une couche
+    matrix Jh=interpolate(Vh2,Ph2,op=0,inside=0);
+    Ph2 w=1.;Vh2 wi; wi[]= Jh*w; // wi must be 1, now this ok. 
+v 3.13-1
+   - correct compilation problem on fedora 13 WITH MPI
+v 3.13 (25 may 2011)   
+   - update the finite element list in  documention 
+   - add (load "Element-Mixte")  NEW FINITE ELEMENT 2D
+         TDNSS1    sym matrix 2x2 conforme in $\{H(div div) / div(div s)) \in H^{-1} \}$
+         RT1 and BDM1  conforme in H(div) Raviert Thomas of Degre 1 and Bezzi, Douglas, Marini 
+         RT1 and BDM1ortho   conforme in H(curl) 2 Nedelec Finite Elemeny
+v 3.12-3 
+   - new finite element in 2d for elasticity in test. TD-NSS0 (see these of Astrid Sabine Sinwel)
+      A New Family of Mixed Finite Elements for Elasticity
+   
+   - add matrice matric multy in lapck interface 
+   - add tool to change the region and label number 
+       change(Th,fregion= integer function to set the region number )
+   - nuTriangle now given the tet number in 3D.  
+   - add mpireduce of matrix to build parallele matrix
+v 3.12-1 april/2011 
+      see remove examples++-mpi/chaleur3D-superludist.edp
+   - correct the precond of gmres algo in A^-1 : (29 mars 2011) to build a correct Navier-Stokes 
+   - add cast TypeOfSolver  on int to parametrize the choise of linear solver.
+   - correct intersection of given metrix in adaptmesh (bug introduc in 07/10 verion 3.9 
+     in case of convect-apt  example  
+v 3.12-1 10 10 fevr 2011 
+    - add VTK write for paraview, examples++-load/VTK_writer.cpp		examples++-load/VTK_writer_3d.cpp (see source for moe details) 
+    - put comment in the documentation about negative tgv 
+    - correct pb blacs mkl  (unde with mumps) 
+    - correct mpiReduce for complex and real data.  
+    - add mpiAllReduce(umax,dmaxg,comm,mpiMAX);  where for real umax,dmaxg;
+    - add tag verson 3.12-win32 
+    - add inferface for mpi in win32 architecture (form 32 version)
+v 3.12    17 jan 2011
+    - correct probleme of comm world on SuperLuDist (complex version)
+    - correct medit Makefile.am in case of no compilation of medit ..
+    - correct a lot of MPI parallel solver example 
+        a bug pastix interface ???
+	MUMPS, superludist, hypre , hips works 
+    - correct link proble in hips and hypre under linux
+    - Add thresholdings.cpp	thresholdings.edp in examples++-load to remove to small coef
+       in a matrix . 
+    - Add lots of DDM Schwarz GMRES precondionned with a coarse grid solver por overlapping : 
+      DDM-Schwarz-Lame-2d.edp		DDM-Schwarz-Lap-2dd.edp		DDM-Schwarz-Stokes-2d.edp	
+      DDM-funcs-v2.idp DDM-Schwarz-Lame-3d.edp  			DDM-Schwarz-Lap-3d.edp			
+      DDM-Schwarz-macro.idp
+      I will add the explanation in the doc in the future; 
+      
+
+    - Add a true exemple to buld mesh form a image (lg.pgm) ,  Leman-mesh.edp 
+    - Add New syntaxe in macro generation
+        NewMacro a(i) 
+        EndMacro 
+       with // comment and macro definition, first trik
+     - Add interface with special function  og gls  http://www.gnu.org/software/gsl/
+        the full list is in the example examples++-loal/gsl.edp  
+     
+v 3.11-1     25 dec 2010
+     - Add coarse preconditioner in MPIGMRES[23]d.edp (to be optimal)
+       now the number of iteration is close to 10.  
+     - Show ff++ line number in case of  assertion  in RNM class. 
+     - add Coarse Preconditionner for  MPIGMRES[23]d.edp (Good)
+     - solve bug For MPIGMRES2D.edp  due to interpolation bug in rare case
+       by Add brute force for seach of point in 2d like in 3d in the seach in find ouside 
+       set global variable :  searchMethod=1;  // more safe seach algo (can be expensive in case of lot of ouside point) 
+      -   add hack of ILU precond, if tgv is < 0 then
+        we remove all the line and put 1 on the diag term ..
+v 3.11 9 dec 2010 
+   - update the documentation of 3d adaption process
+     and / correct  freeyams,mshmet, mmg3d  interface and associaded  example
+   - configure is compatible with MKL lib (on gnome)
+   - add quoting argument in macro argument with { } for mpi  plot .. 
+v 3.10-2
+   - try to compile with MKL libs.
+   - correct MPIGMRES[23]d.edp example 
+     add doc on this example.  
+v 3.10-2
+ - add operator to inverse permuation to set or initial int[int] array
+   I=J^-1; 
+   if J is a permuation of 0:n-1  then we have :   I[j[i]]=i 
+ - correct comment problem of periodic bounary condition in 3D
+    see examples++-3d/periodic-3d.edp
+ - correct configure to scotch compilation on gnone (phtread) 
+v 3.10-1
+  - at convection function form formal array to int,real,complex array
+   (resp.     toZarray, toRarray, toCarray)
+  - correct ffrandom.cpp to read /dev/random to get a true random seed
+    srandomdev 
+  - add ff-mpirun script to simplify the launch of FreeFem++-mpi version
+  - correct MPI for MPI icc on gnome 
+  - correct pb of computation of area, lenbord in mesh type in some case .
+  - correct WHERE_LIBRARY-config  for blas find in configure
+  - correct atof 
+v 3.10 
+  - add true Domain Decomposition example in 2d and 3d. 
+      see    MPIGMRES2D.edp	  MPIGMRES3D.edp in MPI  examples 
+  - add mpi Isend/Irevd for complex struct like matix, meshes 
+     for send/recv Huge objet 
+  - add named parameter verbosity= in add GMRES and GC function 
+     for show algo evolution .
+  - add MPIGC dynamic LIB for // GC and GMRES , add fully // scharwz RAS
+     in MPIGMRES2d.edp 
+  - correct  problem of  a=A^-1*b when a, or b is not consecutive array
+   ie. expression like  M(2,:)  
+  - correct problem of Makefile in download  clean,install,WHERE target
+v 3.10 ( 5 oct 2010)
+  - add install of missing MPI  dynamics lib. 
+  add argument  "-cd"  to FreeFem++ command to change  current directory  to edp script directory 
+  - clean configure.ac 
+  - do correction for g++-4.6 compiler (lambda expressions , and trap ..)
+  - add  MPICG  for Parallel Conjugate Gradient for full split matrix
+     see MPICG
+  - correct Makefiles in download ( add WHERE interface) 
+  - remove wait option in medit because the code is wrong , always waiting  now 
+  - correct bug renumbering  of matrix :  B= A(I,J),
+    the last term N,M was force to zero  =+ -> += (line 1885 of file lgmat.cpp) 
+    where N= I.max, M=J.max 
+v 3.9-3
+  - correct compilation of gmm, mumps on linux
+  - add parameter -ne in FreeFem++ commands  to remove edp script print
+  - correct mistake in --enable-m64 or --enable-m32 (suppress the confugure warning)
+  - correct of ff-c++ script if whith space in path (for windows)
+  - add compilation  of gmm library 
+v 3.9-2
+  - correct compilation of mshmet dynamic library
+  - correct pb of compile of superludist ( add CNOFLAGS no optimze CFLAGS)
+  - correction of lib on win32 for freeyams and mmg3d
+  - correction download/Makefile.am to be sure than bin is a directory.
+  - add fftw of win32 
+
+v 3.9-1
+  - correction  mmg3d interface (J Morice) 
+  - correct of mmg3d and freeyams under wind32 (ld problom)
+v 3.9-1  August 2009   (For FreeFem++ days )
+  - correct configure (find lapack lib change $ll_lapack_libs in $ll_lapack_lib)
+  - correct mistake in mpi 
+    add:  gatherv, allgatherv, scatterv, alltoallv   
+        and complex data type in:  allgather, gather, scatter, alltoall, ..
+    correction bug : gather,  scatter
+    correct essai.edp mpi example 
+  - correct problem of compatibility of dynamic lib  with and without MPI 
+     change ff-cc++ to add all MPI libs if MPI version exist. 
+  - correct default  region number in square build mesh function  now 0 , (2 beetween  v3.8 -- 3.9)  
+  - change in all example  reffacexx= in labelxx= ..., etc to be correct with v 3.8 change.
+  - correct a mistake of type  region= parameter in tetgen all functions.  
+  - correct the mpi configure seach tool
+      miss when no full path are given  ( only change in configure.ac) 
+v 3.9  July 2009.
+  - add lots of automatic  compilation of download soffware,
+   
+	tetgen superlu fftw metis yams mshmet 
+	blacs parmetis scalapack scotch superludist MUMPS pastix hypre hips 
+
+        For the link with mmg3d software put the tar.gz archive in .../dowload/pgk directory.
+    add interface with freeyams, mmg3d, mshmet (3d mesh adatation) software,
+    add automatique compilation of // solver with 
+      flags -auto in ff-c++ commands
+        
+
+v 3.8-2
+  - add cast operator from SubString to String 
+  - correct the SubString tools 
+v 3.8
+  - add in change mesh2 tool to make a renumbering of vertex for periodic 3d mesh. 
+     Th= change(Th,renumv=old2new);
+  - correct ' operator do alway in complex case the conj and trans (Hermissian stuff)
+     in  formal array with [ ]' 
+     in  linear comb of complex matrix  
+        now  A + (-1)*A' is zero  is A is hermisian .
+     in varf term  (a*dx(u)*dy(v) )'  <=>  a' dx(u)*dy(v)
+    now you can  [a*dx(v),dy(v)] ' *[a*dx(u),dy(u)] in complex case.. 
+  - plot of complex field  and 3d vector .. 
+  - upgrade the documentation in 3d mesh example
+  - change configure.ac for mpifc, mpif77,  mpicc, ...  
+  - correct  include seach path 
+  - uniformize named parameter  in change, movemesh, in load "msh" , glumesh, ...
+     add synonyme:  
+        refface=  ->   label=
+	reftet=   ->  region= 
+     in buildlayer:
+	labebup=
+	labebdown=
+	labelmib=
+  - writing  schwarz-nm-3d.edp examples
+     - add array of 3d mesh
+     - add  word  volume to get the volume of the current tet element
+     - correct  metis.cpp in 3d case 
+  - correct in fflapack.cpp (example++-load, computation of eigenvalue of complex matrix)
+         -llapack search in configure.ac 
+        and unify fflapack.cpp lapack.cpp are the same file.
+  - add seekp, tellp  method  on ostream type 
+        seekg, teeg   method on istream type
+        see examples++-tutorial/readmesh.edp examples 
+v 3.7-1 13 jan 2010.. 
+  - EqPoisson.edp (SOlve Poison equation in 3d fish)
+  - add possibility to put array  (int[int] )  to set a set of label/region in
+    in integral (int1d,int2d,int3d)   or  "on" key word 
+    example : int[int] l=[1,2,3]  ,  ...  on(l,u=1);
+  - add tool to compile under mingw/msys under windows 32 (freefem++-nw works, 
+  -  add bug (random trap) in bamg in sub domain computation in case of 
+    internal edge in    same region (fist time in 15 years). 
+  -  add bug in varf interpertation in  complex case (miss some convertion)
+  - add build  interpolation matrix in 3d (see examples++-3d/mat_interpole.edp)
+  - correct CFLAGS (add -fFIP) in superlu , umfpack under 64 architecture. 
+v  3.7   8 december 2009 
+   add 3d beam examples examples++-3d/beam.edp 
+   correct install problem due to metis directory
+   add dynamic load interface with newuoa fortran optimizer without derivative
+      see ffnewuoa.edp example ins examples++-load
+   correct problem of free of mesh in case of  gluing meshes
+     Th= Tha+Thb; // now just the ref counter on Th  is decrease
+                  // and  before  Th is delete 
+   add .im, .real method on complex [int,int] matrix array 
+   add  missing  matrix<complex>[int]  type in grammar.
+
+   correct mistake in genertion of file WHERE_LIBRARY-config
+   add  initialization of	scalar variable at zero 
+   add  warning in case of use of	variable with hide freefem++ name
+   add missing file in download version
+
+v 3.6.1 
+    correct  font problem in documetation
+             lot of mistake in examples++-load 
+    add tool to compile all examples 
+    add PICHON stuff for brute force seach point
+    add umpack long interface to by pass the 32bit limits 
+      see UMFPACK64.cpp and LapUmfpack64.edp in examples++-load.
+    add some interface with lapack (inverse of full matrix, 
+       eigenvalue of full matrix) 
+    correct  ::Draw undef ref.  ubuntu 10. (gcc 4.4)
+    correct typo error  image tools
+    see UMPACK64  (code and example in examples++-load)
+v 3.6 (4 nov 2009)
+    change the version of tetgen to 1.4.3 download
+    correct in ffglut max value of arrow
+    add examples of function with stack parameter in 
+       examples++-load/funcTemplate.cpp load facility
+       and 
+       examples++-load/funcTemplate.edp
+    add tools to read .pcm files for optic-flow computation (pcm2rnm.cpp) 
+  	 see http://www.cs.otago.ac.nz/research/vision/Research/OpticalFlow/pcm.html
+     correct bug in GMRES without preconditionner asset error. 
+     correct a rare and ramdomly bug in the interpolation 2d process when the
+      the element 0 touch the boundary
+     correct on versy old bug in bamg in case of internal boundary edge with
+     two extremity  in true boundary (symptome FillHoleInMesh trap).
+   correct operator  subsript a:b:c  operator (in some case the last value was miss) 
+   correct the  ?: operator in case of constant array  
+  - add -enable-m32 floag to build 32bits freefem++ on 64 architecture computer
+  - correct eigenvalue.cpp in case of complex finite element
+v 3.5-2  (28 sept. 2009)
+  - correct install problem under windows (metis.dll do not compile)
+  - correct MacOS install missing /usr/local/lib/ff++/3.xx-yy link 
+v 3.5-1  (24 sept. 2009) not to bad ...
+
+   - add interface to mestis 
+   - correct  display of 3d mesh (with light doday)
+   - add trap in case of mesh with negative volume 
+   - correct bug  in case  3d finite element with constant number of df / node
+     example fespace Vh(Th2,[P1,P1]); or fespace  Wh(Th3,[P0,P0,P0 ])
+
+   - correct problem with tetgen under windows and ubuntu 
+       (remove optimisation during compilation of the library)
+
+   - correct setting array of vectorial finite element Wh 
+     Wh[int] [u,v](10); // array of 10 value
+     u[1] or v[1] 2 componante function for indice  1.
+     [u[2],v[2]] = [1,2]; //  set the function for indice  2. 
+   - correct in matrix size of  matrix B=A(I,J) to I.n x I.m 
+     where I, J are array of int 
+     
+   - add resize of complex sparse matrix 
+   - Add inferface with metis in examples++-load   (metis.cpp, metis.edp)
+v 3.5 (27 aug. 2009)
+  Complet writing to MPI interface, tested with Open MPI 1.2.3 and mpich 2.1 
+      see chapter 10, page 229, of  the freefem++doc.pdf  and 
+      see example++-mpi/essai.edp.    
+
+  correct 
+      operator  a(:)= 1:4; // before change a copy of a and so do nothing
+      string[string] s; 
+      s[i]; // before trap (two delete) 
+v 3.4-2
+  add boundary mesh inqure in 2d and 3d
+  Th.nbe ; // return the number of boundary element 
+  Th.be(k);   // return the boundary element k $\in \{0,...,Th.nbe-1\}$ 
+  Th.be(k)[l];   // return the vertices l $\in \{0,1\}$ of  boundary elmt k 
+  Th.be(k).Element ;   // return the triangle contening the  boundary elmt k 
+  Th.be(k).whoinElement ;   // return the edge/face number of element contening the  boundary elmt k 
+  Th[k].adj(e) ; // return adjacent element to k by edge/face e, and change 
+  // the value of e to the corresponding edge in the adjacent element
+  Th[k] == Th[k].adj(e) // non adjacent element  
+  Th[k] != Th[k].adj(e) // true adjacent element 
+
+  do small change in msh3.cpp  file 
+ 
+v 3.4-1
+   rewrite of the mpi interface in vue of use group and comunicator
+     now we only use mpi.h and not mpi++.h
+   add plot of array of mesh and array of finite element functions
+   add new command in ffglut graphic interface
+     n,N,i,I  to change the number of isovalue and to set the min,max value to the
+           graphic
+   add left button motion to zoom , and + alt to translate
+V 3.4
+    add in parallel version mpi send, receive and broadcasr of  3d mesh and matrix ( sparse matrix).
+    build a 3d mpi schwarz example (see example++-mpi/schwarz-3.edp)
+    make a wrapper (launchff++.exe)  to launch freefem++ under windows/OS in the edp file directory. 
+    correct in interpolation matrix ( unset variable in case of same mesh 
+      => missing some term in the matrix) 
+
+V 3.3-3 
+  add missing file in distribution examples++-load/DxWriter.cpp
+V 3.3-2  8 june 2009
+  add   2 new finite element:
+   Edge03d : the Nedelec 3d  Edge finite elements.
+   RT03d : the Raviart-Thomas 3d  finite elements
+   correct the size of anytype for 64 bits architecture.
+   install the new .idp file (include of edp file) in
+   directory idp    
+V 3.3-1 1 june 2009
+  to correct the problem of the destruction of parameter in case: 
+      func real[int]   a2(real[int] a) {a[0]=2; return a;}
+   so now the parameter cast to KN_<double> so  the array is not
+   duplicate like in C++, and the value of the parameter is change. 
+   
+  - simplify the internal (C++)  definition of array now of 2 type
+    KN<> * of variable (left expression)
+    and  KN_<> of   right expression 
+  - correct UnRef<A,B> where B ~ A*
+v 3.3  29 may 2009
+  -  correct some problem in return in function :
+   the following function prototype now work without memory fault. 
+
+    func real[int]   a1(int n)  {real[int] a(n);return a;}
+    func real[int]   a2(real[int] &a) { return a;}
+    real[int] G=[7,8,9];		  
+    func real[int]   a3(real[int] &a) { return G;}
+    func mesh carre(int n) { mesh th=square(n,n);  return th;}
+   (lot of change, warning:  now KN<K> is not a freefem++ internal type). 
+  warning : 
+  -  in int3d flag qfV=  a 3d quadrature formula
+        the 3d quadrature formula are
+         qfV1 , qfV1lump, qfV2 , qfV5  (where the number is the ordre of the quadrature)
+  -  correct sign of the normal in 3d (now the normal is exterior)
+      -------------------------------------------------------------
+  -  correct in adapted mesh the flag splitin2=  (no tested)
+  -  correct the convect operator in 3d 
+  -  add EigenValue tool  for 3d case  May 15, 2009. 
+v 3.2
+  - add tools to set array like in matlab/scilab
+    real[int] a(1:2:10),  def  a to 1,3,.. 10.
+    int[int] I(0:n-1) , set array of size n to 0, .., n-1
+    real[int] b(0.1:0.5:9.99) , set   0.1, 0.6, 1.1,..., 9.6  
+    add :   b.n == (9.99-0.1)/0.5 +1
+  - sort(a,p);  // sort a is and array and p in parallel 
+     where is a integer array same size of a.
+        
+  - add interface with MUMPS  parallel solver (in progress) 
+    http://graal.ens-lyon.fr/MUMPS/
+
+  - rename  movemesh2D3Dsurf in movemesh23 and change named 
+     parameter normal= in orientation=
+
+  - add periodic boundary in condition like in 2d
+    example for a cube with label face numbering 
+      1 :  ( x == xmin)        2 :  ( x == xmax) 
+      3 :  ( y == ymin)        4 :  ( y == ymax) 
+      5 :  ( z == zmin)        6 :  ( z == zmax) 
+     fespace Vh(Th,P2,periodic=[[1,y,z],[2,y,z],[3,x,z],[4,x,z],[5,x,y],[6,x,y]]);
+
+  -  automatic: Finite element name conversion  beetween 2d and 3d
+      old : fespace(Th3,P13d);
+      new : fespace(Th3,P1); 
+  - add complete rewrite of the way  to set parameter of the sparse solver
+    for  parallel solver ( no progress)
+  - add --enable-m64 for 64 bit compilation flags 
+  - correct f2c of  take the -m64 flags 
+  -  build the universal f2c library with 4 architecture ppc i386 ppc64 x86_64
+v 3.1-1
+  - add resize of sparse matrix ( only  morse matrix)
+  - add  new 3d finite element P1b3d   (P1 bulle 3d) 
+  - add  new option in int1d function in case for  build matrix with different meshes
+        mortar=1 ( do not remove integration point if the point is outside of the domain)
+    to make no to bad integration on same curve with different meshes. 
+v 3.1
+  -correct compile  order missing libMesh
+  - add lighting in ffglut (key l) for 3d isovalue 
+v 3.0-6
+  - correct int2d in 3d. bug in   Face -> tet mapping  (PBord method) March 5 2009
+        change the postscript  plot dimension to be in A4 paper.  
+        nuTriangle   given the tet  number in 3d case (5 march 2009)
+        area  given the area of the triangle on 3d border integral. 
+  - add tool to required edge in adaptmesh with label of edges. 
+  - correct  dy(uh) (always 0) for P13d finite element  (27 jan 2009)
+      op==op_dy =>  op==op_dy line 97 P012_3D.cpp
+v 3.0-5 (20 jan 2009)
+  - correct array 3D  FE function +  missing function in 3D (not finish) 
+  - correct the install on under windows / cygwin 
+      add src/Graphics/ff-win32.cpp missing file in tar.gz under windows
+      correct ff-c++  under cygwin compile (fist test) 
+  - automatic compilation of BLAS, suppress the automatic compilation of BLAS atlas (to long) 
+  - ffglut improvement 
+        - now save 10 graphic states and use "p" key to show previous graphic
+	- do automatic z rescale on Z direction the  3d plot 
+v 3.0-4 (05 jan 2009)
+  - correct int2d in 3d case: all this integral was multiply by 2. 
+  - add 3d viewing in plot (in test)
+v 3.0-3 (27 dec 2008)
+  - build a not to bad version 
+  - remove so crazy print 
+  - change the ffglut  io with  freefem++  ( to be more universal independant of the architecture an more universal)
+    - correct ffglut in case of plot of array and when the plot is empty.
+      remark ffglut is not compatible with previous version (sorry)
+    the filename create with option w is ffglut_xxxx.ppm (window dump)
+    correct int2d on 3d mesh3d for Neuman Boundary condition
+v 3.0-2 ( 9 dec 2008)
+  - ff-c++ to dynamic load program (add ff++.hpp file  with all include, may be)
+  - correct the Makefiles et load-link, 
+  - correct ffmedit (binary read /win32)
+  - cosmetic change in ffglut + stabilization
+v 3.0-1 (4 dec 2008)
+  - complete change of the graphic (freefem++ is now the old freefem++-nw ) 
+      - add  medit (a visualisator software by  P. Frey)  inside freefem++
+          with a name ffmedit  
+      - suppress the ide version
+          see page: http://www.ann.jussieu.fr/~lehyaric/ffcs
+      - We put a client-server architecture
+        (freefem++,freefem++-nw)  <->  ffglut
+	- freefem++-nw and freefem++ is now the same file 
+	- ffglut is the visualisator in glut library (run on linux, mac, win32)
+    how to use now: 
+        freefem++  file.dp # by default load ffglut (so ffglut must be in the PATH).
+	freefem++  -glut ffglut-path  file.edp  # change ffglut command
+	freefem++  -fglut saveglutfile  file.edp # save data plot
+	ffglut saveglutfile # plot a data file
+	freefem++ -nw file.edp # freefem++ with  graphics 
+	ffmedit  #  used medit in freefem  
+	
+
+  - now glumesh2D dynamics tool is in freefem++   
+        add operator + beetween meshes with glu
+        examples++-tutorial/glumesh.edp
+        
+  - add 3 meshing tools in msh3.{so,dll,dylib}      	
+	operator + between mesh3
+	add freefem++ function:
+	  movemesh2D3Dsurf movemesh3D buildlayers
+        see:
+    	  examples++-load/buildlayermesh.edp
+	  examples++-load/glumesh3D.edp
+	  examples++-load/refinesphere.edp
+	  examples++-load/tetgenholeregion.edp
+
+	    
+  - add interface with tetgen  3d mesher (tetgen.{so,dll,dylib})
+        add freefem++ function: 
+	  tetgconvexhull tetgtransfo tetg tetgreconstruction
+	see:
+      	  examples++-load/buildlayermesh.edp
+	  examples++-load/refinesphere.edp
+	  examples++-load/tetgencube.edp
+	  examples++-load/tetgenholeregion.edp
+
+  - add interface with medit (medit is now in freefem++ this call
+       ffmedit in medit.{so,dll,dylib}
+       add freefem++ function medit savesol (2d , 3d  medit plot)
+
+  - correct ?: operator with array and real. 
+  - correct memory erreur with  valgrind tool (19 oct 2008)
+       In ~ConstructDataFElement() change counter after free
+       nosym eigen call to neupp missing +1 in size of array 
+  - correct gestion of the counter of ConstructDataFElement class (09/2008)
+       in Valladolid spain. 
+  - add 3D FINITE ELEMENT P0,P1,P2 
+     mesh3 Th("toto.mesh")
+     int3d(Th) , int2d(Th)
+     see examples++-3d/first.edp example
+    
+v 2.25
+  - add tool to change lab in mesh see  glumesh.edp examples++-load 
+v 2.24-4
+  - add missing code in case of DG (jump or average) of test function in
+    linear form
+  - add tools to glu meshes (not well test) see glumesh.edp in load examples.
+  - change definition pour interpolation point for P1dc and P2dc  (P-G)*c+G
+    now all interpolation point are fully inside the triangle 
+v 2.24-3
+  - add option resid= in eigenvalue function (see arpack doc)
+  - add  formal operator  ./  .*  between two  [ a , b , c ] array
+v 2.24-2
+  - correct convect explain in documentation. 
+  - correct configure.ac build FLIBS and add check of FLIBS, X11_LIBS value
+  - correct buildmesh trap when degenerate border is create  by error.
+v 2.24-1
+  - correct periodic condition  in case of one edge 
+  - correct doc file
+v 2.24
+  - bug with border and func
+     this kind of code now works
+       func abc=  a(6) + b(4) + c(4)  ;
+       func def = d(4) + e(4) + f(6);
+       func bbb= abc  + def;
+      plot(bbb); mesh Th=buildmesh(bbb);
+     whare : a,c,b,c,d,e,d are  border. 
+
+  - correct bug in periodic Boundary Condition( find by Alexandre Masserey <masserey at ycoorsystems.com>)
+       mistake in abscisse choose.
+       sometime assert fail (loop).
+     add option to the buildmesh that the boundary is fixe (fixeborder=true)
+     see : examples++-tutorial/periodic4bis.edp   
+  -  and  R1.hpp, R2.hpp, R3.hpp files for the 3d version.  
+v 2.23-2
+  - correct trap in adapdmesh (in mortar-DN-4.edp) in very rare case 
+    du to  intialized   adj  of edges on geometry (very old bug) 
+    in case of multi points.
+  with vebosity=10; you get this message: 
+ -- Begin of insertion process 
+ bug  2
+ Bug double points in 
+....
+ Fatal error in the meshgenerator 5
+....
+
+v 2.23-1
+  - correct assert fail in check in case of no UMFPACK
+v 2.23
+  - add new edge finite element (P1 to P5) 
+   in examples++-load/Element_PkEdge.cpp examples++-load/testFE-PkEdge.edp  
+  - preconditionned  mortar example Neuman -> Dirichet in scalar and parallele
+    see examples++-mpi/mortar-DN-4-mpi.edp examples++-tutorial/mortar-DN-4.edp
+  - add vectorial  operator  d=  a ? b : c  where d,a is a array, and b,c can be array or scalar 
+    usefull for boundary condition
+  - correct probleme in mpi recive message
+  - correct load dynamic on MacOs (bug in fortran find library) in configure.ac
+v 2.22-2
+  - small change in configure.ac of find libumfpack on debain systeme
+  - correct checking code in probleme to same the mesh must be unique in problem of solve definition.
+v 2.22-1
+  - make change in Makefile to build universal binary on MacOS
+  - change the README file for compilation on ubuntu Linux.
+v 2.22   (december, 18, 2007)
+  -  correct problem of string argument in function
+  -  correct all elasticity problem (missing sqrt(2) )
+  -  correct save of log file under  Windows XP, ..
+v 2.21   (november, 18, 2007)
+  -  correct documentation for new edition
+  -  correct configure for no X11 and UMFPACK in sparsesuite
+v 2.20-1 (october, 24, 2007)
+  -  correct compilation problem without umfpack
+  -  add  formal operator  for vectorial operator in variationnal form
+        +, -  on  [  ]  array
+        trace operator  matrix like [ [ ... ], .., [... ] ] 
+        take element of an array [ ...][2] 
+v 2.20  (october, 2, 2007)
+  -  add in download automatic generation of f2c and fort77 to get a free  fortran compiler
+	just  go in 
+	(download/f2d;make install)
+  -  add automatic find of libf2c in case of F77=fort77 (driver of f2c) in configure 
+  -  add tools to change the sparse linear solver with load dynamic, see doc and SuperLu example
+     in examles++-load
+v 2.19   (august, 19  2007)
+  - correct buildmesh from geometry file and add nbvx= named parameter
+    to infore the maximal number of verter in a mesh.
+  - add  Th[k].area to get the area of the k-th triangle of Th.
+  - add  Th[k].region to get the region number (label)  of the k-th triangle of Th.
+  - correct string delete in plot of border (mesh.edp)
+  - correct mean and jump in  interpolation operator.
+v 2.18-1 (august, 2007)
+  - correct old bug under Windows: the std input stream  now works (cin) 
+v 2.18  (july, 19, 2007)
+  - add sort of real array or int array, syntaxe: 
+      a.sort, and we have : a[i-1] <= a[i] for i =0 to a.n-1
+  - add  v=a.quantile(p) ;  statisticial function  and commute v such than 
+     #{ i / a[i] < v } = r*a.n   <=>    v = a[r*n]  when the array is sorted.   
+  - correct P4nc, P4 finite element
+v 2.17-2 (19 june 2007)
+  - correct double   $(BLASLIB) in configure.ac (one more)
+  - correct old bug in bamg, in case of bogus boundary (auto
+    crossing)and   add code  to  handle  this error correctly with exception
+    (see "test to catch bogus boundary"  of example++-tutorial/mesh.edp).
+v 2.17-1
+  - add the command line parameter [-v nn] in all freefem++ program to set 
+    the level of verbosity to nn  before all, and if nn == 0 then theoriticaly no more
+    spurious output.
+  - correct  automatique choose of  color in plot of arrow. 
+v 2.17
+  - add bessel function   j0, j1, jn, y0, y1, yn -- bessel
+        functions of first and second kind
+  - add  erf, erfc -- error function operators
+  - add   tgamma, lgamma  -- gamma and log of gamma
+  - add   tool set and get   line,colunm and value of a sparse matrix
+             [I,J,C]=A; // resizing  array I,J,C
+             A=[I,J,C] ;
+            where
+             int[int] I(k),J(k); real[int] C(k);
+  - add   in tools to get eigen vector of None FE problem
+   like:
+     int nev=5;  // number of computed eigen valeu close to sigma
+     real[int] ev(nev); // to store nev eigein value
+     real[int,int] eV(AA.n,nev);   // to store nev eigen vector
+     int k=EigenValue(AA,BB,sym=true,11value=ev,rawvector=eV);
+
+  - correct the quadrature formular automatic choose with the qforder= field
+  by default the order is correct until  order 10 (so exact for P9 polynomals)
+  to add new Quadrature formalur up two  order 26 add  dynamic load qf11to25
+v 2.16-2
+  correct configure.ac for windows ide compile
+  correct meshsplit, trunc  function 
+v 2.16 april 17 2007
+  Change umfpack download version to the last one
+  add string input from file or cin
+  add Compressible Neo-Hookean Materials exemple
+v 2.15-1
+  Correct mistake in cas of splitmesh with internal boundary (assert)
+  Add dump  of the mesh regulary (pesonnal work, FH)
+v 2.15  (27 mars 2007)
+  The blas.tgz file change on http://www.netlib.org/blas/blas.tgz
+  correct the makefile  (remove BLAS dir) 
+v 2.14-3 (24 mars 2007)
+  Correct bug in vectorial operation of type  (b - 3.14*d) (Thanks to F. Dortu)
+v 2.14-2 (22 mars 2007)
+  correct integration problem on none classical mesh (mesh of curve of mortar technique)
+  the mesh::Find methode is boggus of the kind on meshes, i make an optimisation to remove
+  this call in case build matrix with varf int1d(Th)( u*v) , in case of Th, u or v is def.
+  on same meshes.	
+v 2.14-1 (0 mars 2007)
+   correct missing speeling in  configure.ac  mpi++.h -> mpi++.h for mpich.1.2
+   add computing linear form of 2 meshes  (ex. v on mesh Th1, and  compute int2d(Th1)(v) )
+v 2.14  (7 mars 2007)
+   make correction for solaris bluid
+   add P3,P4 and new quadrature formular on triangle up degree 25 
+   with dynamics load. See examples++-load/*P[43]*.edp
+   correct mistake when we build matrix from varf with 3  meshes (FH).
+v 2.13
+   Add formal operator * and ' (to day just transpose) 
+   on vector [ .. ]  and matrix [ [],...,  []]
+   so we can write  
+    macro grad(u) [ dx(u),dy(u)] // EOM
+    int2d(Th)( grad(u)'*grad(v) )   
+    add scalar term in block matrix as 1x1 matrix.
+v 2.12-2
+  correct problem in splitmesh and trunc
+  trunc build always a part of a subdivision mesh
+  splitmesh given more pretty mesh, before if we split 2 adjacent
+  triangle resp in 3 and 4, before we put 2+3 points on the common edge
+  now the put 3 points. 
+v 2.12-1 (jan 15,2007)
+  correct early delete of return pointeur in freefem++ function (trap in string.edp under windows )
+v 2.12   ( jan 10,2007)
+  correct mistake in none square block matrix 
+v 2.11-2 (nov 29,2006)
+  correct integration problem on none classical mesh (mesh of curve of mortar technique)
+  the mesh::Find methode is boggus of the kind on meshes, i make an optimisation to remove 
+  this call in case build matrix with varf int..(Th)( u*v) , in case of Th, u or v is def.
+  on same meshes.  
+v 2.11-1 (nov 28,2006)
+  Correct bug in interpolation, we building fespace Wf(Th,[RT0,P0]); 
+v 2.11 (nov 10,2006)
+ Correction of  the problem in arpack (eigenvalue computation) under i383 processor.
+ After 2 week of hard work, a found the bug.
+ In new version of LAPACK second is a real function
+ and in ARPACK second is a subroutine  (Thank the fortran).  
+ So I change the Makefile to change the name of function second into secnd2. 
+ How to find the bug, in this case the stack of the floatting register (info float under gdb) 
+ are growing. So after any real function can return a NaN (one time) due to stack float register 
+ overflow.  A big Thank to D. Bernardi of the help (Merci au fortran et Merci au i383).
+
+v 2.10 (oct 26,  2006)
+  correct problem with eigen value on window and some linux distrubition (Fedora)
+  add a patch of two functions in lapack  see  arpack/arpack-patch-lapack.tar.gz
+
+v 2.9 (sept 19, 2006 FH) 
+  change Send and Recv in mpi  to Isend and Irecv to make async communication
+  so now freefem++-mpi work with openmpi.
+
+V 2.8-3
+   correct freefem++-cs trap under windows (install the static version)
+   add tools to format ostream  ( file or cout)  
+
+V 2.8-2 
+   (july)
+   use f2c as a fortran compiler on  MacIntel architecture,
+    correct mistake in mpi. 
+   (june 2006)
+   add nint, and correct mistake in ceil function
+   add configure flag to remove cadna --without-cadna
+V2.8
+   Correct mistake in OtherMacOsLib.tgz store file and not link (after 1 june)
+ * Correct bug in vectorial problem with same approximation, some time
+   we do a renumbering of the previous  approximation space (a pointer mistake).
+V2.7-1
+  * change size of data in 64 bits architecture (in file AnyType.hpp)
+V2.7
+  * correct mpi Makefile
+  * correct bug in construction of recursive composite finite element (see HISTORY)
+    remark: the finite elemnt struct, so all dynamic library must be recompile. 
+V2.6-1
+ * add the examples-bamg  directory  in freefem++ and  correct bamg graphic
+V2.6
+ * Huge work (more than a full week) to improve the windows version 
+   change all the .dll construction
+   remove lots of trap. All example run without graphics
+V2.5.1
+ *  change nbve= to nev= in EigenValue function  (to be compatible with the doc)
+ *  newtow to newton    (to correct misspelling)
+ *  change in AnyType to remove da randow bug on windows.
+ *  vim color syntax from Richard MICHEL (vim_highlighting_for_FF++.tar.gz)
+
+V2.5-0 
+  *  add C++ string operator :  int i; string s = "....";
+       i=s.length ; i=s.size; 
+       i=s.find("qsdqs");i=s.rfind("sqs"); i=s.find("qsq",2); 
+       s(3:4)="sdfffsf";  // replace from char 3 to 4 by 
+       // s[3] not alloued to day (char type is not well type in freefem++).
+       getline(cin,s); 
+  *  Correct bug when passing parameter string in function
+  *  add freefem++  mode for mi editor on macos http://www.mimikaki.net/en/
+    store in  mode-mi-edp.zip archive (unzip and put in the Folder  openned with the 
+    mi "Option->Open Mode Folder" menu and set "mi" is the Default application 
+    for all the .edp file). 
+    
+V2.4-2
+  * add lot missing vectorial operation with sub array 
+  * if u is a complex array (i.e. complex[int u] ..;) 
+     then  u.re (resp u.im) are  the real array of the real (resp. imag ) 
+     part of the vector u
+  * in block matrix add utilisation of array to build the block matrix
+    see new Laplace-lagrange-mult.edp file to have an example
+V2.3-3
+ * add outer  product to set matrix or full real or complex 2D array
+    A = 2*a*b'; // where A is a "real[int,int]", b and c a "real[int]".
+    A += 2*a*b'; or  A = 2*a*b';
+   add matrix and array renumbering (see sec. 4.8 of freefem++.doc for all details)
+    
+V2.3-0
+ * add three key word for future use try,catch throw 
+   a exception handling (no memory management.) 
+   try {   code ; }
+   catch (...) { code ; }
+ * use tolpivot= to set the pivottol in LU, crout, cholesky factorization 
+V2.2-1
+ * Add init file to set verbosity, includepath  , loadpath and 
+   add preload (dynamic link file)
+   the file are under unix and MacOs
+	 /etc/freefem++.pref
+         /Users/hecht/.freefem++.pref
+         freefem++.pref
+   under windows
+         freefem++.pref
+   and the syntaxe of the files is
+
+     verbosity= 5
+     loadpath += "/Library/FreeFem++/lib"
+     loadpath += "/Users/hecht/Library/FreeFem++/lib"
+     includepath  += "/Library/FreeFem++/edp"
+     includepath  += "/Users/hecht/Library/FreeFem++/edp"
+     #  comment 
+     load += "funcTemplate" 
+     load += "myfunction" 
+
+ * Add search directory for include, and load  under Unix and Windows
+   Just on the shell sh  set environment variable
+    export FF_VERBOSITY=50 
+    export FF_INCLUDEPATH="dir;;dir2"
+    export FF_LOADPATH="dir;;dir3""
+   remark the separtor of directory  is ";" and not ":" because ":" is use under Windows.
+ * Examples of Add new Finite element with dynamic link/load,  Morley and Bernardi Raugel   
+   see examples++-load 
+V2.1-2
+ * add more example of dynamic load example (thank to F. Dortu)
+ * correct mistake in simple integral computation (not in variationnal 
+   form)  before we alway use a quadrature formula of order 3, 
+   now we can change the quadrature formula and the defaut is of order 5. 
+V2.0-4
+ * change in mshptg the size of the small possible edge from
+   1/32000 to 1/1 000 000 000, this mesher is use in trunc, 
+  splitmesh, and triangulate functions.
+
+V2.0-3
+ * correct operator x =/,  it does  nothing before. (v2.0-3)
+   see end  examples++-tutorial/array.edp for all array operator
+   =  +  -  *  /  .*  ./ += -= /= *=  : .l1 .l2 .linfty .sum .max .min ' 
+   
+ * correct bug when solving complex linear system with UMFPACK
+   before we solve the system when the conjugate matrix
+
+
+Major Change previous version
+-----------------------------
+ * add ternary C expression
+     Symbol       Example      Explanation
+       ?:          a?b:c     ternary operation
+ 
+ * add 
+   sparse matrix computation,
+   block matrix construction 
+   interpolation construction
+   see 
+     examples++-tutorial/sparse-cmatrix.edp  
+     examples++-tutorial/sparse-matrix.edp
+     examples++-tutorial/mat_interpol.edp
+   not so well tested, but could be worse. 
+   
+ * add example to solve vartionnal inequation. VI.edp
+
+ * add  possibility to build matrix where the 3 meshes 
+   the integrale mesh, unkwon FE mesh, test FE function 
+   can be different.  You must use varf to build the matrix 
+   is not a standard porblem.
+  
+ * Improvement of  dynamic loading facility under the 3 systems
+   add a fast fourier transform with dynamic loading
+   see examples++-load/dfft.edp
+
diff --git a/INSTALL-MacOSX b/INSTALL-MacOSX
new file mode 100644
index 0000000..33a676a
--- /dev/null
+++ b/INSTALL-MacOSX
@@ -0,0 +1,38 @@
+
+To install FreeFem++ on your mac you need to run (double click on) the shell script Install-MacOS.command
+(you will need to type your password and you must be "administrator" of your machine).
+
+This script installs FreeFem++, ffglut, ffmedit in /usr/local/bin ,
+as well as some possibly missing libraries  and the FreeFem.app in /Applications. 
+
+This version can be used in 3 modes
+
+	- Like a Mac application with drap and drop, etc; then it opens
+	  a terminal window for the console IO and (when needed) a graphic window
+	  which accepts keyboard commands when in wait mode (listed by typing a "?").
+
+	- In terminal mode: (only when FreeFem++.app has not been moved out of the/ Applications
+	directory). In the terminal window one must type "FreeFem++ <filename>" where <filename>
+	is the name of your xxx.edp file.
+	
+	- With the latest version of the smultron.app (http://tuppis.com/smultron/) text editor
+	directly from inside the editor by typing "cmd+r". Smultron recognizes xx.edp files and 
+	activates a color highlight of the keywords (don't forget a "cmd+s" before the "cmd+r").
+
+ 
+Technical Note:
+-------------
+This will not work on MacOs systems less than 10.3.
+This version uses OpenGL/GLUT graphics.
+
+The installer command puts in /usr/local/bin the following binaries:
+
+ff-c++     tools to compile dynamic libray  with freefem++ 
+FreeFem++  the freefem++ command
+ffglut     the graphic visalisator
+ffmedit    the medit sofware
+
+Some external library are in the archive file OtherMacOsLib.tgz;
+you may need to install these
+	
+READ le READ_MAC to buil freefem++ on your mac. 
\ No newline at end of file
diff --git a/Install-MacOS.command.in b/Install-MacOS.command.in
new file mode 100644
index 0000000..edc45dc
--- /dev/null
+++ b/Install-MacOS.command.in
@@ -0,0 +1,50 @@
+#!/bin/sh
+appl=/Applications
+cd `dirname $0`
+echo "Installtion of Freefem++ " 
+if [ -f OtherMacOsLib.tgz ]; then
+for i in `tar ztf OtherMacOsLib.tgz`; do
+ if [ ! -f "/$i" ]; then
+  echo " the Libary '/$i' don't exist => install (need of admin password)"
+   sudo  tar zxvf OtherMacOsLib.tgz -C / $i
+  else
+  echo " the Libary '/$i'  exist "
+ fi
+done 
+#  verif .... 
+for i in `tar ztf OtherMacOsLib.tgz`; do
+  if [ ! -f "/$i" ]; then
+    echo " the Libary '/$i' don't exist FreeFEM cannot run (call you adminisator sorry)"
+    echo "Sorry"
+    exit 1;
+ fi
+done
+fi
+
+
+echo " copy FreeFem++.app in "$appl" "
+if [ -d FreeFem++.app ] ; then
+  rsync -avHE --delete   FreeFem++.app/  "$appl"/FreeFem++.app
+fi
+
+
+lbin=`cd "$appl"/FreeFem++.app/Contents/bin/; echo *`
+echo "  install $lbin    commands in /usr/local/bin (need of admin password)"
+
+sudo mkdir -p  /usr/local/bin
+sudo mkdir -p  `dirname @ff_prefix_dir@`
+sudo ln -s  "$appl"/FreeFem++.app/Contents/bin/* /usr/local/bin
+sudo rm /usr/local/bin/ff-c++
+sudo sed <"$appl"/FreeFem++.app/Contents/bin/ff-c++ >/usr/local/bin/ff-c++ \
+	-e 's;FFAPPLI_INC;$app/FreeFem++.app/Contents/include;' 
+chmod a+rx /usr/local/bin/ff-c++
+if [ -d "@ff_prefix_dir@" ] ; then
+    echo Warning "@ff_prefix_dir@" is a dirctory keep this.
+else
+    sudo rm -f "@ff_prefix_dir@"
+    sudo ln -s "$appl/FreeFem++.app/Contents" "@ff_prefix_dir@"
+    echo link "@ff_prefix_dir@  ->  $appl/FreeFem++.app/Contents/ "
+fi
+echo "++  FreeFem++ is correctly install in $appl  directory."
+echo " install in /usr/local/bin: $lbin "
+echo " Thanks for  using  FreeFem++ v3 "
\ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..3170a0d
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,261 @@
+# Makefile for FreeFem++, adapted to Automake
+# -------------------------------------------
+
+# Adaptation to Automake: Antoine Le Hyaric - LJLL Paris 6 -
+# lehyaric at ann.jussieu.fr - 13/5/04
+
+# $Id$
+
+SUBDIRS=download src  examples++-tutorial examples++	\
+	examples++-eigen examples++-load examples++-mpi	\
+	examples++-bug examples++-chapt3 examples++-other \
+	examples++-3d DOC 
+
+EXTRA_DIST=test-driver-ff regtests.sh config-wrapper.h  \
+FreeFem++.mcp HISTORY HISTORY_BEFORE_2005  BUGS TODO regtests.m4 \
+INSTALL INSTALL-MacOSX INNOVATION \
+WindowsPackage.m4 README README_ARPACK  README_WINDOWS README_MAC \
+logo.ico copysharedlibs.sh COPYRIGHT edp.nedit  reconfigure \
+mode-mi-edp.zip aclocal.m4  acmacros.m4   acoptim.m4 ax_lib_hdf5.m4  \
+freefem++.spec crimson-freefem++.zip \
+Install-MacOS.command.in \
+examples-bamg/NACA012/naca.awk  examples-bamg/quadloop/dotest.pl \
+examples-bamg/square/*_g.* examples-bamg/square/do* examples-bamg/NACA012/[adp]* \
+examples-bamg/test/dotest*.pl 0ldUserReadMe.txt CheckAllEdp CheckAll  \
+WHERE_LIBRARY-mkl FreeFem++-CoCoa \
+uninstall-ff++ \
+./build/cleancrlf		./build/download		./build/links2files	./build/orgindex
+
+
+FF_MAC_PREFIX=FreeFem++v$(VERSION)$(ADD_PACKAGE_NAME)
+
+FF_EXAMPLES_FILES = COPYRIGHT HISTORY HISTORY_BEFORE_2005 README README_WINDOWS README_MAC BUGS TODO INSTALL INSTALL-MacOSX INNOVATION \
+mode-mi-edp.zip \
+examples++-tutorial/aile.msh examples++-tutorial/xyf \
+examples++-3d/dodecaedre01.mesh  \
+examples++-3d/lac-leman-v4.msh \
+examples++-load/load.link \
+examples++-load/fig.pgm	examples++-load/lg.pgm \
+./examples++-mpi/regtests.sh ./examples++-other/speedtest.sh  \
+./download/fftw/Makefile ./download/fftw/Makefile.am \
+examples++*/*.[ie]dp  CheckAllEdp
+
+
+# Creates a file named "ChangeLog" containing the chronology of all
+# modifications to the source files. Needs "cvs2cl" to be installed.
+
+changelog:
+	cvs2cl
+
+# History before 2005 is stored in the file "HISTORY_BEFORE_2005"
+all-local:: @HISTORY@
+
+# try and avoid running this under fakeroot (otherwise we may face
+# problems trying to connect to CVS as pseudo-root). Debian packaging
+# uses fakeroot.
+history:
+	if test "$$FAKED_MODE" = ""; then\
+		hg log >HISTORY ;\
+		fi
+
+documentation:
+	cd DOC && $(MAKE) $(AM_MAKEFLAGS) documentation
+
+DOC/freefem++doc.pdf:
+	cd $(@D) && $(MAKE) $(AM_MAKEFLAGS) $(@F)
+
+clean-local::
+	-find . \( -name '*~' -or  -name ListOfUnAllocPtr.bin \) |xargs rm 
+	-rm examples*/*.eps 
+
+# "dist" targets
+clean-local::
+	-rm freefem++-*.tar.gz freefem++-*.zip
+	-rm Output/FreeFem++-*.exe
+
+# Reduced compilation
+# -------------------
+
+quick:
+	cd src/libMesh && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/lglib && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/fflib && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/std && $(MAKE) $(AM_MAKEFLAGS)
+
+nw:
+	cd src/libMesh && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/lglib && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/fflib && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/nw && $(MAKE) $(AM_MAKEFLAGS)
+
+bamg:
+	cd src/libMesh && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/lglib && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/fflib && $(MAKE) $(AM_MAKEFLAGS)
+	cd src/bamg && $(MAKE) $(AM_MAKEFLAGS)
+
+ide:
+	cd src/libMesh && $(MAKE) $(AM_MAKEFLAGS)
+	cd download && $(MAKE) $(AM_MAKEFLAGS) 
+	cd src/lglib && $(MAKE) $(AM_MAKEFLAGS) 
+	cd src/fflib && $(MAKE) $(AM_MAKEFLAGS) 
+	cd src/ide && $(MAKE) $(AM_MAKEFLAGS) FreeFem++-cs$(EXEEXT)
+
+# Cleaning generated files which are stored in the CVS repository, to
+# avoid technical CVS conflicts.
+clean-gen:
+	./cleanregen.sh
+
+# Testing
+# -------
+
+# The standard automake goal "make check" is also valid. It just does
+# not run any test that could prevent the user from working on its
+# machine (because of unexpected windows opening right in the middle
+# of the workspace).
+
+visualcheck: all
+	$(MAKE) $(AM_MAKEFLAGS) check VISUALCHECK=yes
+
+speedtest: all
+	cd examples++-other && $(MAKE) $(AM_MAKEFLAGS) check
+
+# Windows package
+# ---------------
+
+# Windows package script (for Inno Setup). We extract version
+# information from the Debian Changelog to get the package release
+# number as well.
+win32:WindowsPackage.iss
+	cd examples++-load;tar zxvf include.tar.gz;mkdir include-tmp;cp -Lr *.h include/* include-tmp
+WindowsPackage.iss: WindowsPackage.m4 configure.ac Makefile.am
+	m4 -DVERSION='$(VERSION)$(ADD_PACKAGE_NAME)' \
+	-DMPIPROG='$(MPIPROG)' WindowsPackage.m4 > WindowsPackage.iss
+
+# Debian package
+# --------------
+
+deb:
+	dpkg-buildpackage -rfakeroot
+	@echo Now run CopyToServer.sh in debian subdirectory
+
+# Build all versions
+# ------------------
+
+
+nativeX: $(FF_MAC_PREFIX)_MacOsX.tgz 
+	echo "done"
+MacOsX: 
+	-rm -rf  OsXxx
+	mkdir -p  OsXxx/Applications/
+	make install DESTDIR="`pwd`/OsXxx"
+	tar zxvf FreeFem++.app.tgz -C OsXxx/Applications/
+	cd OsXxx;tar cvfz  ../$(FF_MAC_PREFIX)_MacOsX.tgz .
+	rm -rf OsXxx
+clean-local::
+	-rm freefem++-$(VERSION).tar.gz
+	-rm -rf FreeFem++v*_MacOS
+
+# Native MacOS packaging
+# ----------------------
+install-exec-local:: 
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(pkgdatadir)/$(VERSION)
+	tar cvf - $(FF_EXAMPLES_FILES)| (cd $(DESTDIR)$(pkgdatadir)/$(VERSION); tar xvf -)
+	$(mkinstalldirs) -m 755 $(DESTDIR)${bindir}
+	-test `uname` = Darwin && $(INSTALL_SCRIPT) FreeFem++-CoCoa  $(DESTDIR)${bindir}
+
+
+ListFiles-natives: .FORCE 
+	echo $(FF_EXAMPLES_FILES) >$@
+	echo ./download/fftw/Makefile ./download/fftw/Makefile.am  >>$@
+	find .  -name '*.[ei]dp' -o -name '*.h*' -o -name '*.cpp' -o -name '*.pgm'  |egrep  '[.]/examples++' >>$@
+	find .   -name '*.h*' -o -name '*.cpp'  |egrep  '[.]/examples++' >>$@
+List-agl-dylib: src/nw/FreeFem++
+	otool -L src/nw/FreeFem++|egrep -v '/System/Library/|/usr/lib/'|awk '/.dylib/ {print $$1}' >$@
+CheckMacLib.sh: src/nw/FreeFem++
+	echo "for i in `otool -L src/nw/FreeFem++|egrep -v '/System/Library/|/usr/lib/'|awk '/.dylib/ {printf($$1.OFS)  }'` ; do test ! -f $$i && exit 1; done; exit 0"  >$@
+	chmod a+x $@
+CheckMPIMacLib.sh: src/mpi/FreeFem++-mpi
+	echo "for i in `otool -L src/mpi/FreeFem++-mpi|egrep -v '/System/Library/|/usr/lib/'|awk '/.dylib/ {printf($$1.OFS)  }'` ; do test ! -f $$i && exit 1; done; exit 0"  >$@
+	chmod a+x $@
+.FORCE:
+
+$(FF_MAC_PREFIX)_Macos:documentation ListFiles-natives
+	-mkdir $@ 
+	cat ListFiles-natives|xargs tar chf - | (cd $@ ; tar xf - )  
+	/Developer/Tools/CpMac "FreeFem++(Carbon)" $@/FreeFem++ 
+	cp   DOC/freefem++-doc.pdf $@
+
+$(FF_MAC_PREFIX)_MacOsX: all documentation  ListFiles-natives List-agl-dylib
+	-mkdir $@ 
+	cp   DOC/freefem++doc.pdf $@
+	cat ListFiles-natives|xargs tar chf - | (cd $@ ; tar xf - )  
+	cd  $@ ; tar zxf ../src/agl/FreeFem++.app.tgz
+	sed <src/agl/Info-plist.am >$@/FreeFem++.app/Contents/Info.plist \
+           -e "s/@VVERSION@/$(VERSION)$(ADD_PACKAGE_NAME)/g" \
+           -e "s/@DATE@/`date`/g"  
+	cp src/nw/FreeFem++ $@/FreeFem++.app/Contents/bin
+	cp src/nw/ffglut $@/FreeFem++.app/Contents/bin
+	cp src/medit/ffmedit $@/FreeFem++.app/Contents/bin
+	cp examples++-load/ff-get-dep  $@/FreeFem++.app/Contents/bin
+	cp examples++-load/ff-pkg-download  $@/FreeFem++.app/Contents/bin
+	sed <examples++-load/ff-c++ > $@/FreeFem++.app/Contents/bin/ff-c++ 	-e 's;FFAPPLI_INC;$@/FreeFem++.app/Contents/include;' 
+	chmod a+x $@/FreeFem++.app/Contents/bin/ff-c++
+	-mkdir $@/FreeFem++.app/Contents/include 
+	-mkdir $@/FreeFem++.app/Contents/idp 
+	cp examples++-load/include/* $@/FreeFem++.app/Contents/include
+	cp examples++-load/*.dylib  $@/FreeFem++.app/Contents/lib
+	cp examples++-*/*.idp  $@/FreeFem++.app/Contents/idp       
+	-if [ -s List-agl-dylib ]; then tar zchvf $@/OtherMacOsLib.tgz `cat List-agl-dylib`; fi; 
+	./config.status  --file=$@/Install-MacOS.command:Install-MacOS.command.in
+	chmod a+rx $@/Install-MacOS.command
+	-mkdir $@/FreeFem++.app/Contents/etc
+	echo loadpath += \"./\"  >$@/FreeFem++.app/Contents/etc/freefem++.pref
+	echo loadpath += \"$(ff_prefix_dir)/lib\"  >>$@/FreeFem++.app/Contents/etc/freefem++.pref
+	echo includepath += \"$(ff_prefix_dir)/edp\"  >>$@/FreeFem++.app/Contents/etc/freefem++.pref
+	echo includepath += \"$(ff_prefix_dir)/idp\"  >>$@/FreeFem++.app/Contents/etc/freefem++.pref
+
+
+$(FF_MAC_PREFIX)_MacOsX.tgz: $(FF_MAC_PREFIX)_MacOsX
+	tar zcvf $(FF_MAC_PREFIX)_MacOsX.tgz  $(FF_MAC_PREFIX)_MacOsX
+
+# Linux binary-only package
+# -------------------------
+
+# Include kernel and libc version in static package name
+PACKAGE_NAME=FreeFem++v$(VERSION)_linux-$(KERNEL_VERSION)_$(LIBC_VERSION)$(OPTIM_TYPE)
+
+linux-package: $(PACKAGE_NAME).tgz
+
+# No direct dependency to "all" to be able to debug the packaging
+# procedure on its own.
+
+$(PACKAGE_NAME):  ListFiles-natives
+	cat ListFiles-natives|xargs tar cfh - | (cd $@ ; tar xf - )  
+	-mkdir $@ 
+	cp src/std/FreeFem++ $@
+	./copysharedlibs.sh src/std/FreeFem++ $@
+	cp src/nw/FreeFem++-nw $@
+	./copysharedlibs.sh src/nw/FreeFem++-nw $@
+	cp src/ide/FreeFem++-cs $@
+	./copysharedlibs.sh src/ide/FreeFem++-cs $@
+	cp src/ide/FreeFem++-server $@
+	./copysharedlibs.sh src/ide/FreeFem++-server $@
+	cp src/ide/FreeFem++-client $@
+	./copysharedlibs.sh src/ide/FreeFem++-client $@
+	-cp src/glx/FreeFem++-glx $@
+	-./copysharedlibs.sh src/glx/FreeFem++-glx $@
+	-cp src/mpi/FreeFem++-mpi $@
+	-./copysharedlibs.sh src/mpi/FreeFem++-mpi $@
+
+
+$(PACKAGE_NAME).tgz: $(PACKAGE_NAME)
+	tar cvzf $@ $<
+
+clean-local::
+	-rm -r $(PACKAGE_NAME) $(PACKAGE_NAME).tgz
+autofiles:AutoGeneratedFile.tar.gz
+
+AutoGeneratedFile.tar.gz:configure List_generate_file Makefile.in Makefile.am  configure.ac
+	tar cvfz $@  `cat List_generate_file`
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644
index 0000000..821b429
--- /dev/null
+++ b/README
@@ -0,0 +1,439 @@
+Compilation of FreeFem++ under unix, MacOs X or mingw  (Windows)
+and bamg (mesh generator)
+----------------------------------------------------------------
+REMARK:    after 4/09/2013, in hg version all 
+construct by autorecong are not on the directly in distrubution.
+
+-- to rebuild    with automake vzersion >= 1.13 autoconf :
+  # autoreconf -i
+    or take the file form the file AutoGeneratedFile.tar.gz 
+  # tar zxvf AutoGeneratedFile.tar.gz 
+
+--  to build a complete  version do
+   # ./configure --enable-download
+-- to test
+   make check
+-- to install
+   sudo make install
+
+
+New:  Test version 3.9  F. Hecht & J. Morice July  2010.
+
+Try to downlaod and compile (add --enable-download flags to configure)
+ lot of related  sofware, (Please read the licence of all with software,
+if you use freefee++ for commercial purpose) 
+
+tetgen superlu fftw metis yams mshmet MUMPS
+blacs parmetis �����scalapack scotch superludist MUMPS pastix hypre hips 
+
+For the link with mmg3d software put the tar.gz archive in .../dowload/pgk directory.
+
+Remark, you can alsy copy all the donwload file in ../dowload/pgk if you have not internet connection.
+
+Brochet-2:download hecht$ ls -1 pkg/*
+MBA-de-FH:download hecht$ ls -1 pkg/*
+pkg/Ipopt-3.10.2.tgz
+pkg/MUMPS_4.10.0.tar.gz
+pkg/ParMetis-3.1.1.tar.gz
+pkg/SuiteSparse-2.4.0.tar.gz
+pkg/arpack96.tar.gz
+pkg/blacstester.tgz
+pkg/fftw-3.2.1.tar.gz
+pkg/freeyams.2012.02.05.tgz
+pkg/gmm-4.1.tar.gz
+pkg/hips-1.2b-rc4.tar.gz
+pkg/metis-4.0.tar.gz
+pkg/mmg3d4.0.tgz
+pkg/mpiblacs-patch03.tgz
+pkg/mpiblacs.tgz
+pkg/mshmet.2011.03.06.tgz
+pkg/nlopt-2.2.4.tar.gz
+pkg/pARMS_2.2.tar.gz
+pkg/pastix_release_2200.tar.bz2
+pkg/patch.tar.gz
+pkg/scalapack-1.8.0.tgz
+pkg/scotch_5.1.6_esmumps.tar.gz
+pkg/superlu_4.0.tar.gz
+pkg/superlu_dist_2.3.tar.gz
+pkg/tetgen1.4.3.tar.gz
+MBA-de-FH:download hecht$ 
+ 
+TO simplify the link and compilation part, 
+
+I have add 3 files
+examples++-load/WHERE_LIBRARY		
+examples++-load/WHERE_LIBRARY-download
+examples++-load/WHERE_LIBRARY-config
+
+On my mac I have install gsl with MacPorts 
+MBA-de-FH:~ hecht$ more work/ff++/examples++-load/WHERE_LIBRARY
+gsl LD -L/opt/local/lib/ -lgsl
+gsl INCLUDE  -I/opt/local/include/
+MBA-de-FH:~ hecht$ 
+
+
+the files 
+examples++-load/WHERE_LIBRARY-config
+examples++-load/WHERE_LIBRARY-download
+are restectively created with ./configure commande ,
+the compilation of all downlaod software.
+and the  examples++-load/Makefile.
+
+
+The use of commande compile with search of include and lib. 
+../exemples++-load/ff-cc++ -auto MUMPS_FreeFem.cpp
+compile a do all the link edition for MUMPS freefem++ interface.
+
+Brochet-2:examples++-mpi hecht$ make MUMPS_FreeFem.dylib
+../examples++-load//ff-c++ -auto  MUMPS_FreeFem.cpp 
+.. 
+
+we just add  the 2 lines  in MUMPS_FreeFem.cpp
+//ff-c++-LIBRARY-dep:  mumps parmetis ptscotch  scalapack blacs blas  mpifc  fc  pthread 
+//ff-c++-cpp-dep: 
+
+
+
+
+*  to today the ide  version is  currently available
+	you can get  from http://www.ann.jussieu.fr/~lehyaric/ffcs/index.htm
+
+
+Old Remark (May be obsolete)
+     *  the graphique is now base of Open/Glut lib.
+     *  IN CASE  of problem under UBUNTU/GLUT  (no graphics window tilte: (march 2009) 
+        they are a know bug with compiz package so  try
+	To disable/enable it graphically, install the compiz-swith package with synatic. Or try this in command line:
+	killall compiz.real && killall compiz && metacity --replace --display :0 & 
+
+F. Hecht.
+-
+
+
+For debian, ubuntu, MacOS, Windows  see the the prerequisite
+
+installed packages before configuration and compilatation.
+
+This file details specific configuration details for FreeFem++. For
+a standard installation, please refer to the file named "INSTALL".
+
+annd see the end of this file to have some 
+configure example:
+
+Full version 3d need automatic download option
+----------------------------------
+For a Full 3d  version , some external piece of software
+can by usefull, the simplest wait is to add "--enable-download"
+to the "./configure" (need of  "wget" or "curl" unix  command). 
+The download archive are store in : 
+download/pkg/SuiteSparse-2.4.0.tar.gz  # umpack 
+download/pkg/arpack96.tar.gz           # arpack
+download/pkg/f2c.tar                   # f2c if no fortran 77
+download/pkg/fftw-3.2.1.tar.gz         # fft
+download/pkg/patch.tar.gz              # arpack
+download/pkg/superlu_3.1.tar.gz        # superlu
+download/pkg/tetgen1.4.2.tar.gz        # tetgen
+download/blas/cblas.tgz                # blas 
+if you have not internet access juste copie this files at the same  place.
+
+
+Debugging and optimization
+--------------------------
+
+Without any option, "./configure" selects the best optimization
+options for the local machine. To produce optimized binaries that can
+be ported to other machines, add the option "--enable-generic".
+
+
+To produce FreeFem++ programs containing debugging symbols and no
+optimization, use "--enable-debug".
+
+If you need to add specific flags to the ones that ./configure
+chooses, just define the corresponding automake variable before
+running configure. For instance, to add flag "-x" to C++ compilations,
+say:
+
+> CXXFLAGS=-x ./configure
+
+Other useful configuration variables include:
+- CFLAGS for C compilation
+- FFLAGS for Fortran compilation
+- LIBS libraries for the linking stage
+- LDFLAGS linking flags
+- LDADD extra options for the linking stage
+- F77  the fortran compile (if not fortran is installed  see section NOFORTRAN)
+- FC   the fortran 90 compiler 
+- CC  the cc compiler
+- CXX the c++ compiler
+
+
+Linear algebra libraries and eigen value problem
+-----------------------------------------------
+By default, "./configure" looks for the X11, BLAS, ARPACK and UMFPACK, OpenGL, GLUT
+libraries on the local system.
+ARPACK is use to compute eigenvalue.
+and UMFPACK is a new fast sparse linear solver.
+
+ If configure cannot find the libraries
+by itself, you can specify the full path to a library file (ending
+with ".a") or the options use by the linker (ex: "-L/usr/local/lib -lblas")
+with the following options:
+
+--with-blas="blas linker options"  
+--with-arpack="arpack linker options"
+--with-amd="amd linker options"
+--with-umfpack="umfpack linker options"
+
+Or, if the configuration flag "--enable-download" is specified, the
+compilation step ("make") will try to download the missing libraries
+(from their official websites) and compile them.
+
+Remark, under linux or window the simplest way to get
+a not to bad version is
+./configure --enable-download 
+
+Here are the different versions of FreeFem++ produced by one
+compilation (some versions may be missing if your system does not
+support them):
+
+* FreeFem++: standard version (using X11 graphics on Linux and MacOS
+  10, Win32 on Windows and  MacOS X) (located in src/std)
+
+* FreeFem++-nw: without graphics (located in src/nw)
+
+* FreeFem++: graphics based on OpenGL (located in src/nw)
+* ffglut: the graphic tools
+
+* FreeFem++-mpi: parallel version, without graphics (located in src/mpi)
+
+The compilation procedure (produced with automake) builds all the
+libraries and executables sequentially. Running "make" in a
+subdirectory does not rebuild dependencies in other directories.
+
+The compilation has been tested under linux and MacOs/Darwin with g++
+version  3.3. 4.0 4.4 It take 30 mn to compile all on
+my PowerBook G4 1Mhz 1024MB.
+
+Rebuilding "configure"
+------------------------
+
+Developers of FreeFem++ can rebuild the configuration system using
+Automake and Autoconf with the command:
+
+> autoreconf
+# to reconfigure with the same parameter 
+> ./reconfigure 
+
+Extra utilities
+---------------
+
+To run an interactive test of FreeFem++:
+> make visualcheck
+
+To run a speed test:
+> make speedtest
+
+To create the documentation in .ps and .pdf format (in the "DOC" directory):
+> make documentation
+
+Examples
+--------
+
+All the Examples are in the two directories examples++ and
+examples++-tutorial. The suffix is .edp ("equations aux derivees
+partielles" in French)
+
+To test all the examples under unix: 
+
+> cd examples++; ../src/std/FreeFem++ all.edp
+> cd examples++-tutorial; ../src/std/FreeFem++ all.edp
+
+To try the  dynamic linking loader example: 
+remark: some adaptation must be done with the suffix probleme (.dll, .so, .dylib )
+and directory  to seach dynamic lib  (shell variable LD_LIBRARY_PATH)
+ 
+
+warning under  Window XP,  first install the cygwin environnent (see http://www.cygwin.com)
+> cd example++-load build a dll file with the following shell script:
+> ./ff-c++  myfunction.cpp  
+
+to execute the examples try  
+  under window xp
+ FreeFem++-nw  load.edp 
+  or otherwise 
+ ../src/nw/FreeFem++-nw load.edp
+
+
+
+-- FreeFem++ v1.38 (date Tue Feb 10 12:04:30 CET 2004)
+ file : load.edp
+ Load: lg_fem  --  no UMFPACK => replace UMFPACK  by LU  
+lg_mesh eigenvalue 
+ load "myfunction" lood: myfunction 
+load: dlopen(./myfunction.so) = 0x84be700
+
+    1 :  mesh Th=square(5,5);
+    2 :  fespace Vh(Th,P1);
+    3 :  Vh uh=myfunction(); // warning  do not forget () 
+    4 :  cout << uh[].min << " " << uh[].max << endl;
+    5 : 
+    6 : 
+    7 :  sizestack + 1024 =1224  ( 200 )
+----------CheckPtr:-----init execution ------ NbUndelPtr  996  Alloc: 79131  NbPtr 1011 
+
+   Nb of edges on Mortars  = 0
+   Nb of edges on Boundary = 20, neb = 20
+ Nb Of Nodes = 36
+ Nb of DF = 36
+0 0.841471
+times: compile 0.01s, execution -2.0837e-19s
+----------CheckPtr:-----end execution -- ------ NbUndelPtr  996  Alloc: 79131  NbPtr 1048 
+Bien: On a fini Normalement
+                CheckPtr:Nb of undelete pointer is 995 last 101
+                CheckPtr:Max Memory used     93.672 kbytes  Memory undelete 78619 
+
+Note 1: if this does not work, please check the manual page of dlopen
+for your system.
+
+
+Note 2. Fast fourier exemple ( FFT )  is in dfft.edp  file
+need of fftw3 
+
+
+Some configure flags use to build the current version
+-----------------------------------------------------
+
+*  Under Debian: ( 2008)
+----------------
+  the installed packages + dependance are:   
+
+  gcc g++ g77
+  libsuitesparse-dev
+  libarpack2-dev
+  libx11-dev libxt-dev libxext-dev
+  patch
+  wget
+  freeglut3-dev
+ - bluid the parallel version
+   openmpi-dev openmpi
+
+ - to rebuild de documentation:  
+  imagemagick 
+  tetex-base   tetex-bin  tetex-extra 
+
+ ./configure 
+  make 
+  make check    (to test de version)
+  make install  (under root)
+   
+*  Under Ubuntu (2008)
+---------------
+  the installed packages + dependance are:   
+   gcc g++  g77
+   wget 
+   m4 bison flex patch
+   libzip-dev
+   libx11-dev libxt-dev libxext-dev 
+    libxpm4 libxpm4-dbg 
+    libsuitesparse-dev libarpack2-devlibarpack2 libarpack2-dev
+    libfltk1.1 libfltk1.1-dbg libfltk1.1-dev
+    libopenmpi1 libopenmpi-dev
+    libopenmpi-dbg libxpm-dev 
+    freeglut3 freeglut3-dev
+    libx11-dev  libxt-dev  libxext-dev 
+    libglut3-dev	
+ - bluid the parallel version
+    openmpi-dev openmpi
+ - to rebuild de documentation:  
+    imagemagick 
+    tetex-base   tetex-bin  tetex-extra 
+ 
+
+ ./configure --enable-download  --with-mpi=mpic++
+#  utility of parameter:
+#  --enable-download :  for fft and tetgen ... 
+#  --with-mpi=mpic++ : for mpi version 
+  make 
+  make check    (to test de version)
+  make install  (under root)
+  
+
+
+* Under Red Hat Enterprise Linux AS release 3:
+----------------------------------------------
+the following rpm:
+blas-3.0-20 gcc-3.2.3-53 tetex-1.0.7-67.9 lapack-3.0-20 ImageMagick-5.5.6-15 wget-1.10.2-0.30E curl-7.10.6-7.rhel3
+are install
+./configure  '--enable-download' '--with-blas=-lblas -llapack'
+
+
+* Under MacOs: (2010)  snow leopard
+-------------
+ 
+ 1) intall Apple's Developer Tools from de Apple DVD
+    Warning the default compile is now 64 bits, 
+ 2) install g95  fortron (to have a fortran  64 bits by default)
+        install macport  from http://www.macports.org/
+        sudo port install g95
+
+     or add flags   -m64  to the fortran command (not tested).
+	cd download/f2c
+	make install-10.6
+ 3)  recompile openmpi with the use of g95  
+
+   './configure'  'FC=/opt/local/bin/g95' 'F77=/opt/local/bin/g95' 
+     make 
+    sudo make install
+
+ 4) TeXLive-teTeX Current Release in http://www.ctan.org/tex-archive/systems/mac/mactex/
+
+
+./configure '-with-suffix=snow-leopard'  '--enable-download' 'build_alias=snow-leopard' 'host_alias=snow-leopard' 'target_alias=snow-leopard' 'F77=/opt/local/bin/g95' '-with-mpi=/usr/local/bin/mpic++' '--enable-m64' 'FLIBS=/opt/local/lib/g95/x86_64-apple-darwin10/4.2.4/libf95.a' 'MPIF77=/usr/local/bin/mpif77' 'MPICC=/usr/local/bin/mpicc' 'MPIFC=/usr/local/bin/mpif90'
+
+* Under MacOC macIntel 
+----------------------
+  1) install Apple's Developer Tools
+  2) install do the NOFORTRAN section. 
+  3) install the TexMac for the documentation:
+ http://ctan.org/get/systems/mac/mactex/MacTeX-20071201.dmg
+
+# to build a full  freefem++  for your Mac:
+first install g95, and recompile openmpi (little tricky)
+
+./configure '-with-suffix=snow-leopard' '-without-fltk' '--enable-download' 'F77=/opt/local/bin/g95' '-with-mpi=/usr/local/bin/mpic++' '--enable-m64' 'FLIBS=/opt/local/lib/g95/x86_64-apple-darwin10/4.2.4/libf95.a' 'MPIF77=/usr/local/bin/mpif77' 'MPICC=/usr/local/bin/mpicc' 'MPIFC=/usr/local/bin/mpif90'
+
+
+./configure -without-fltk' '--enable-download' '-with-mpi=mpic++' 'F77=fort77' '--with-flib=-L/usr/local/lib -lf2c'
+
+or if you have compile the download/f2c   with : (cd download/f2c;make install)
+
+./configure '-with-suffix' 'MacIntel'  '--enable-download' '-with-mpi=mpic++' '-enable-download' 
+
+# to build universal FreeFem++ of 10.4 macOS (ppc , i386):
+( cd  download/f2c; make  -n compile-10.4 install)
+./configure '-with-suffix=Universal' '-without-fltk' '--enable-download' 'F77=/Users/hecht/ff/ff-univ/download/bin/fort77' '--with-flib=/Users/hecht/ff/ff-univ/download/lib/libf2c.a' 'CXX=g++-4.0 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 -mmacosx-version-min=10.4' 'CC=gcc-4.0 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386 -mmacosx-version-min=10.4' 'FFLAGS=-Wc,-isysroot,/Developer/SDKs/MacOSX10.4u.sdk,-arch,ppc,-arch,i386,-mmacosx-version-min=10.4' 'C [...]
+
+
+
+* Under Windows: 
+----------------
+see the end of README_WINDOW  files 
+
+* NOFORTRAN:
+------------
+You have not fortran compiler use f2c and the use the  script fort77
+by the way just do:
+cd  download/f2c
+# to build and install fort77,  linf2c.a in download/bin  download/lib
+make install
+# to install in /usr/local/
+make install-sudo
+
+# to build and universal f2c library on MacOS 10.4 and install in /usr/local/bin  /usr/local/lib
+# and in download/bin  download/lib download/bin  download/include
+#    32/ 64   bits architecture on    intel and ppc
+make -n install-10.4 
+
+for the 64 on intel   version 10.6 (SDK)
+make -n install-10.6
+
diff --git a/README_ARPACK b/README_ARPACK
new file mode 100644
index 0000000..7883aad
--- /dev/null
+++ b/README_ARPACK
@@ -0,0 +1,24 @@
+How to adapt ARPACK for compilation with FreeFem++
+--------------------------------------------------
+the simplest  way is just 
+configure --enable-download 
+--------------------------------------------------
+Or to compile arpack no problem
+
+   Remark, in arpack++ a lot  of incoherance this moderne c++ (g++3 or better)
+so I write the driver by hand (from version 3.) no arpack++ in	    
+include in freefem++ now. 
+
+The last one is in lapack lib second.f in an function not a procedure like in arpack.
+Two weeks work to find this mistake.
+
+
+Frederic Hecht
+-------------
+
+
+
+
+
+
+
diff --git a/README_MAC b/README_MAC
new file mode 100644
index 0000000..6e3f02e
--- /dev/null
+++ b/README_MAC
@@ -0,0 +1,103 @@
+To compile a full version of FreeFem++ under MacOS 
+---------------------------------------------------
+
+Under Mavericks (10.9)  2012 ( xcode 5.0.2 form scratch)
+-------------------------------------------------
+ remark: All line beginning by # are  shell command in terminal. 
+ 
+
+ 1) install xcode 5.0.2 , and the xcode command line tools  
+    xcode 
+    install Auxiliary Tools for Xcode (for PackageMaker)
+ 2) install xcode command line  (xcode 5.0.2  bug ???? ) 
+  # xcode-select --install  
+ 2) install  gcc-4.9 form http://hpc.sourceforge.net
+  # curl -O http://prdownloads.sourceforge.net/hpc/gfortran-4.9-bin.tar.gz?download
+  # sudo tar zxvf gfortran-4.9-bin.tar.gz -C /
+ 3) autoconf and automake now not in xcode
+   I use the macport distribution form http://www.macports.org
+  # sudo port install  autoconfo
+  # sudo port install  automake
+  Or with  brew tool ... 
+ 4) install tex  from  ctan 
+   http://mirrors.ctan.org/systems/mac/mactex/MacTeX.pkg
+ 5) install openmpi form the source 
+ http://www.open-mpi.org/software/ompi/v1.6/downloads/openmpi-1.6.5.tar.bz2
+  #  ./configure 'CC=clang' 'CXX=clang++' 'FC=gfortran' 'F77=gfortran' --enable-ltdl-convenience
+  # make 
+  # sudo make install
+ 6) install gsl 
+  # curl -O http://ftp.gnu.org/gnu/gsl/gsl-1.15.tar.gz
+  # tar zxvf gsl-1.15.tar.gz
+  # cd gsl-1.15.
+  #./configure CC=clang
+  # make
+  # sudo make install 
+ 7) install mecurial from the web http://mercurial.selenic.com
+    
+ 8)  download  
+  # hg clone  http://www.freefem.org/ff++/ff++
+ 9)  compilation of freefem++ 
+  # cd ff++
+  # ./configure '-with-suffix=macos-10.9' '-without-fltk' '--enable-download' '--enable-optim' 'MPIRUN=/usr/local/bin/mpirun' '--enable-m64' '--without-x' 'CC=clang' 'CXXFLAGS=-std=c++11' 'CXX=clang++' 'F77=/usr/local/bin/gfortran' 'FC=/usr/local/bin/gfortran' 'MPICXX=/usr/local/bin/mpic++' 'MPICC=/usr/local/bin/mpicc' 'MPIFC=/usr/local/bin/mpif90' 'MPIF77=/usr/local/bin/mpif90' '--enable-maintainer-mode'
+
+  # make
+  # make
+  # make 
+  # sudo make install 
+
+to bluid the version of 10.8  the version compilation (fev. 2014)
+
+./configure '-with-suffix=macos-10.8' '-without-fltk' '--enable-download' '--enable-optim' 'MPIRUN=/usr/local/bin/mpirun' '--enable-m64' '--without-x' 'CC=clang -isysroot /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk' 'CXXFLAGS=-mmacosx-version-min=10.8' 'CXX=clang++ -std=c++11 -isysroot /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk' 'CFLAGS=-mmacosx-version-min=10.8' 'F77=/usr/loc [...]
+
+------------
+Under Snow Leopard.  Jan 2011
+
+The major problem is take a good f90 to compile new // solver like MUMPS.
+
+Do the follow  instalation process:
+0)  Install the developper tools form the apple DVD's.
+
+1) get macport for http://www.macports.org/  and installation:
+
+  sudo port selfupdate 
+  sudo port install g95
+  sudo port install wget
+
+2) get and install  mercurial form
+   http://mercurial.selenic.com/
+
+3) to  compile  openmpi  with fortran interface  and install
+ do :
+
+wget http://www.open-mpi.org/software/ompi/v1.4/downloads/openmpi-1.4.3.tar.bz2
+
+remark, I have test with version 1.4.1 , but I thing no problem acure  with this new version
+
+ tar zxvf openmpi-1.4.3.tar.bz2
+ cd openmpi-1.4.3
+ ./configure FC=/opt/local/bin/g95 F77=/opt/local/bin/g95 
+ sudo make install 
+ 
+4) get Tex/laTex for the documention build 
+form http://www.tug.org/mactex/
+and install
+
+5) to get download the last freefem++ version , do
+  
+hg clone  http://www.freefem.org/ff++/ff++
+cd ff++ 
+
+./configure '-with-suffix=snow-leopard' '--enable-download' 'F77=/opt/local/bin/g95' '-with-mpi=/usr/local/bin/mpic++' '--enable-m64' 'FLIBS=/opt/local/lib/g95/x86_64-apple-darwin10/4.2.4/libf95.a' 'MPIF77=/usr/local/bin/mpif77' 'MPICC=/usr/local/bin/mpicc' 'MPIFC=/usr/local/bin/mpif90' 'MPI_INC_DIR=/usr/local/include' 'MPICXX=/usr/local/bin/mpic++'
+
+make 
+make install
+
+Good Luck, and  if I miss something sorry,
+ try to add  missing tools with 
+sudo port install missing-tool
+like for exemple:
+
+sudo port install gnuplot
+
+sudo  install_name_tool -change /Users/hecht/ff/ff-MacOS-10.9/download/PETSc/petsc-3.5.2/arch-darwin-c-debug/lib/libparmetis.dylib /usr/local/petsc/lib/libparmetis.dylib libpetsc.3.5.dylib
\ No newline at end of file
diff --git a/README_WINDOWS b/README_WINDOWS
new file mode 100644
index 0000000..35428f1
--- /dev/null
+++ b/README_WINDOWS
@@ -0,0 +1,136 @@
+How to compile FreeFem++ on Microsoft Windows
+---------------------------------------------
+
+WARNING NOW the window is compile under MINGW  (from version 3.11  14/01/2011 FH)
+
+  So the old dll are incompatible with the new version. 
+  -----------------------------------------------------
+
+NEW version with MINGW 32 to have a not to bad FC compiler. 
+----------------------------------------------------------
+
+1) Download and install MINGW32 
+from: 
+http://sunet.dl.sourceforge.net/project/mingw/Automated%20MinGW%20Installer/mingw-get-inst/mingw-get-inst-20101030/mingw-get-inst-20101030.exe
+`
+2) Download un insatll wget for --enable-download in configure
+http://puzzle.dl.sourceforge.net/project/mingw/mingwPORT/Current%20Releases/wget-1.9.1-mingwPORT.tar.bz2
+
+3) the glut of win32 
+
+http://web.cs.wpi.edu/~gogo/courses/mingw/winglut.zip
+
+install in .h file in 
+
+c:\mingw\bin\../lib/gcc/mingw32/4.5.0/../../../../include/GL/glut.h
+c:\mingw\bin\../lib/gcc/mingw32/4.5.0/../../../../include/GL/gl.h
+c:\mingw\bin\../lib/gcc/mingw32/4.5.0/../../../../include/GL/glu.h
+
+add the glut32.dll in you directory in the 2 directories:
+
+$ find /c/MinGW -name glut
+/c/MinGW/bin/glut32.dll
+/c/MinGW/lib/glut32.dll
+ 
+3) the good blas 
+http://www.tacc.utexas.edu/index.php?eID=tx_nawsecuredl&u=0&file=fileadmin/images/GotoBLAS2-1.13_bsd.tar.gz&t=1294842550&hash=638c44fa086136fc2b661b98b52e0ee4
+
+try to compile 
+
+4) MPI for // version 
+use HPC Pack 2008 SDK with Service Pack 2 (SP2) 
+
+5) inno setup to build instraller: 
+http://www.xs4all.nl/~mlaan2/ispack/isetup-5.4.0.exe
+
+6) GSL for gsl interface 
+
+the configure argument are:
+
+
+./configure '--enable-download' 'FC=mingw32-gfortran' 'F77=mingw32-gfortran' 'CC=mingw32-gcc' 'CXX=mingw32-g++' '-with-blas=/home/hecht/blas-x86/libgoto2.dll' 'CXXFLAGS=-I/home/hecht/blas-x86' '--enable-generic' '--with-wget=wget' 'MPIRUN=/c/Program Files/Microsoft HPC Pack 2008 R2/Bin/mpiexec.exe'
+
+$ cat examples++-load/WHERE_LIBRARY
+gsl LD -L'"/c/Program Files (x86)/GSL-1.13"'/lib -lgsl
+gsl INCLUDE -I'/c/Program Files (x86)/GSL-1.13/include'
+
+
+OLD Version with cygwin: (obsolete comment) 
+--------------------------------------------
+
+
+1) Download and install Cygwin from http://www.cygwin.com. Make sure
+that the development tools Automake, Autoconf and GNU C++ , C , g77,
+OPENGL, GLUT  are installed.
+
+2) Download and extract the FreeFem++ source archive from
+http://www.freefem.org
+
+3) Open a Cygwin bash shell and follow the instructions from the
+FreeFem++ INSTALL and README files.
+
+Precompiled BLAS libraries
+--------------------------
+
+Precompiled ATLAS libraries are available at
+http://www.netlib.org/atlas/archives/windows/. There are several
+processor type dependant libraries to choose from. If FreeFem++ is
+configured with the options "--enable-generic" and
+"--enable-download", it will download the most generic version. Or you
+can download a more optimized version and specify it to "./configure"
+with the option "--with-blas=..." (see README).
+
+Creating a Windows package
+--------------------------
+
+To create a Microsoft Windows self-installable package containing
+FreeFem++ executables, examples and documentation, you need to install
+"Inno Setup" (http://www.jrsoftware.org/isinfo.php) on your machine
+first. Then run "make WindowsPackage.iss" and load the file
+"WindowsPackage.iss" into Inno Setup once you have configured and
+compiled FreeFem++ (see INSTALL). Inno Setup places the resulting
+archive in subdirectory "Output".
+
+TROUBLE:
+--------
+
+Infortunatly, all the .exe version without cygwin under  mingw
+do not run under cygwin shell,  they run under under the 
+command window NT  shell if the mingwm10.dll is in the right place:
+.exe directory or in 'C:\WINDOW\system32. 
+
+In version 2.0
+BUG in LAPACK with -O optim flag
+the file ARPACK/LAPACK/dlamch.f 
+symptome: the code loop.
+correct the Makefile.m4 to
+
+inforce the compilation flag
+
+REMARK:
+All the exe and .dll are in 
+src/bin-win32 
+
+To build the install program you must get inno Setup 5 sofware
+http://www.jrsoftware.org/isinfo.php
+and the the cygwin package tex, pdflatex, ImageMagick , ghostscript 
+
+
+make win32
+make documentation
+
+to build the setup file, use  inno setup on file WindowsPackage.iss
+the setup file is in output directory
+
+The configure  flag use to build the version
+-------------------------------------------
+
+for the P4 version, we  compile on pentium-m vaio VGN-S2XP
+with cygwin install  http://www.cygwin.com/
+with the following package
+  gcc,g++,  tetex, wget , f77 , imagemagick 
+
+./configure '--enable-optim' '--enable-download' '--with-suffix=P4'
+
+for the generic i383 we use 
+./configure '--enable-download' '--enable-generic' '--enable-optim' '--with-blas=/home/UNIVERSITE/blas/generic-no-cygwin-blas.dll' 'CPPFLAGS=-I/home/UNIVERSITE/blas/'
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..2fdd35a
--- /dev/null
+++ b/TODO
@@ -0,0 +1,35 @@
+add doc:
+  gsl interface 
+  imax of tableau 
+
+Short time:
+ build a true aniso 3d adaptation example
+  to day bug in interface of mmg3d with metric and in tetgen ...
+
+
+long time: 
+
+Add Finite Volume interface. 
+
+Track: 
+
+add the sup of a function on a mesh
+real uinfty=sup(Th,abs(f));
+real uhinfty=sup(uh); 
+
+
+Newton algorithm.
+
+automatique scheme for time depend problem:
+dt(u) or u_t
+
+implicite:
+problem a(u,v, sheme=Euler , dt = 0.1, tinit = 0, tfinal = 10 , previous=[u1]) = 
+  int2d( u_t*v + dx(u)*dx(v)+dy(u)*dy(v) ) ;
+  
+explicit:
+problem a(u,v, sheme=thetaScheme(0.5) , dt = 0.1 , tinit = 0  , tfinal = 10 , previous=[u1]) = 
+  int2d( u_t*v) + int(dx(u1)*dx(v)+dy(u1)*dy(v)) ;
+
+
+
diff --git a/WHERE_LIBRARY-mkl b/WHERE_LIBRARY-mkl
new file mode 100644
index 0000000..483bbd8
--- /dev/null
+++ b/WHERE_LIBRARY-mkl
@@ -0,0 +1,9 @@
+blas LD '-L at MKLDIR@/lib/@MKL_ARCH@ -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -lguide -lm -lpthread '
+blas INCLUDE '-I at MKLDIR@/include'
+lapack LD '-L at MKLDIR@/lib/@MKL_ARCH@ -llibmkl_lapack'
+lapack INCLUDE '-I at MKLDIR@/include'
+scalapack LD '-L at MKLDIR@/lib/@MKL_ARCH@ -lmkl_scalapack_lp64'
+scalapack INCLUDE '-I at MKLDIR@/include'
+blacs LD '-L at MKLDIR@/lib/@MKL_ARCH@ -lmkl_blacs_lp64'
+blacs INCLUDE '-I at MKLDIR@/include'
+
diff --git a/WindowsPackage.m4 b/WindowsPackage.m4
new file mode 100644
index 0000000..ba6e2e1
--- /dev/null
+++ b/WindowsPackage.m4
@@ -0,0 +1,155 @@
+; Creating a FreeFem++ package for Microsoft Windows with Inno Setup
+; $Id$
+
+; The Inno Setup configuration file WindowsPackage.iss is built from
+; WindowsPackage.m4 with the command "make WindowsPackage.iss".
+
+; No source file here. They are in the source tar ball.
+; suppress -cs version no fltk to day , wait the next version
+;  FH version 3.0-1
+[Setup]
+AppName=FreeFem++-VERSION
+AppVerName=FreeFem++ version VERSION
+DefaultDirName={pf}\FreeFem++
+DefaultGroupName=FreeFem++
+Compression=lzma
+SolidCompression=yes
+ChangesAssociations=yes
+OutputBaseFilename=FreeFem++-VERSION
+ChangesEnvironment=yes
+
+[Files]
+; README 
+Source: "README"; DestDir: "{app}"
+Source: "README_WINDOWS"; DestDir: "{app}"
+Source: "INNOVATION"; DestDir: "{app}"
+Source: "AUTHORS"; DestDir: "{app}"
+Source: "BUGS"; DestDir: "{app}"
+Source: "COPYRIGHT"; DestDir: "{app}"
+Source: "COPYING"; DestDir: "{app}"
+Source: "README"; DestDir: "{app}"
+Source: "crimson-freefem++.zip"; DestDir: "{app}"
+Source: "0ldUserReadMe.txt"; DestDir: "{app}"
+
+; Programs
+Source: "src\bin-win32\FreeFem++.exe"; DestDir: "{app}"
+ifelse(len(MPIPROG),0,; ,)Source: "src\bin-win32\FreeFem++-mpi.exe"; DestDir: "{app}"
+ifelse(len(MPIPROG),0,; ,)Source: "src\mpi\ff-mpirun"; DestDir: "{app}"
+Source: "src\bin-win32\launchff++.exe"; DestDir: "{app}"
+;  to day the dll version do not works so we use the static one (FH)
+;Source: "src\bin-win32\FreeFem++-cs.exe"; DestDir: "{app}"
+;Source: "src\ide\FreeFem++-cs.exe"; DestDir: "{app}"
+Source: "src\nw\ffglut.exe"; DestDir: "{app}"
+Source: "src\medit\ffmedit.exe"; DestDir: "{app}"
+Source: "src\bin-win32\FreeFem++-nw.exe"; DestDir: "{app}"
+Source: "src\bin-win32\bamg.exe"; DestDir: "{app}"
+Source: "src\bin-win32\cvmsh2.exe"; DestDir: "{app}"
+; Source: "src\bin-win32\drawbdmesh.exe"; DestDir: "{app}"
+Source: "src\bin-win32\*.dll"; DestDir: "{app}"
+Source: "examples++-load\ff-c++"; DestDir: "{app}"
+
+; mingwm10.dll is necessary when "-mthreads" is used as a compilation
+; flag.
+
+Source: "C:\MinGW\bin\mingwm10.dll"; DestDir: "{app}"
+; Source: "C:\Cygwin\bin\glut32.dll"; DestDir: "{app}"
+Source: "C:\MinGW\msys\1.0\bin\freeglut.dll"; DestDir: "{app}"
+Source: "C:\MinGW\bin\pthreadGC2.dll"; DestDir: "{app}"
+Source: "C:\MinGW\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}"
+Source: "C:\MinGW\bin\libstdc++-6.dll"; DestDir: "{app}"
+Source: "C:\MinGW\bin\libgfortran-3.dll"; DestDir: "{app}"
+Source: "C:\MinGW\bin\libquadmath-0.dll"; DestDir: "{app}"
+
+
+; Does not include FreeFem++-x11 which would need the Cygwin X-Server
+; Does not include FreeFem++-glx which would need the Cygwin X-Server
+
+; Examples
+Source: "examples++\*.edp"; DestDir: "{app}\examples++"
+Source: "examples++-eigen\*.edp"; DestDir: "{app}\examples++-eigen"
+Source: "examples++-tutorial\*.edp"; DestDir: "{app}\examples++-tutorial"
+Source: "examples++-tutorial\*.idp"; DestDir: "{app}\examples++-tutorial"
+Source: "examples++-tutorial\aile.msh"; DestDir: "{app}\examples++-tutorial"
+Source: "examples++-tutorial\xyf"; DestDir: "{app}\examples++-tutorial"
+Source: "examples++-chapt3\*.edp"; DestDir: "{app}\examples++-chapt3"
+Source: "examples++-other\*.edp"; DestDir: "{app}\examples++-other"
+Source: "examples++-load\*.edp"; DestDir: "{app}\examples++-load"
+Source: "examples++-load\*.idp"; DestDir: "{app}\examples++-load"
+Source: "examples++-load\*.cpp"; DestDir: "{app}\examples++-load"
+Source: "examples++-load\*.pgm"; DestDir: "{app}\examples++-load"
+Source: "examples++-load\*.pts"; DestDir: "{app}\examples++-load"
+Source: "examples++-load\cube.msh"; DestDir: "{app}\examples++-load"
+
+Source: "examples++-load\load.link"; DestDir: "{app}\examples++-load"
+Source: "examples++-load\include-tmp\*"; DestDir: "{app}\examples++-load\include"
+Source: "examples++-3d\*.edp"; DestDir: "{app}\examples++-3d"
+Source: "examples++-3d\dodecaedre01.mesh"; DestDir: "{app}\examples++-3d"
+Source: "examples++-3d\lac-leman-v4.msh"; DestDir: "{app}\examples++-3d"
+Source: "examples++-3d\*.idp"; DestDir: "{app}\examples++-3d"
+ifelse(len(MPIPROG),0,; ,)Source: "examples++-mpi\*.idp"; DestDir: "{app}\examples++-mpi"
+ifelse(len(MPIPROG),0,; ,)Source: "examples++-mpi\ff*.txt"; DestDir: "{app}\examples++-mpi"
+ifelse(len(MPIPROG),0,; ,)Source: "examples++-mpi\*.edp"; DestDir: "{app}\examples++-mpi"
+Source: "0ldUserReadMe.txt"; DestDir: "{app}\examples++-load"
+Source: "0ldUserReadMe.txt"; DestDir: "{app}\examples++-tutorial"
+Source: "0ldUserReadMe.txt"; DestDir: "{app}\examples++-chapt3"
+Source: "0ldUserReadMe.txt"; DestDir: "{app}\examples++"
+Source: "0ldUserReadMe.txt"; DestDir: "{app}\examples++-eigen"
+
+
+
+; Documentation files may need to be copied from another machine if
+; Cygwin refuses to build them.
+
+Source: "DOC\freefem++doc.pdf"; DestDir: "{app}"
+
+; Icons for Windows can be created from a 32x32 image with icotool
+; (Linux Debian unstable), or IrfanView (Windows, not very good
+; results) or paint (Windows, save in .bmp then rename to .ico).
+
+Source: "logo.ico"; DestDir: "{app}"
+
+[Icons]
+
+; Menu
+Name: "{group}\FreeFem++"; Filename: "{app}\launchff++.exe"; IconFilename: "{app}\logo.ico"
+;Name: "{group}\FreeFem++ GUI"; Filename: "{app}\FreeFem++-cs.exe"
+Name: "{group}\PDF manual"; Filename: "{app}\freefem++doc.pdf"
+Name: "{group}\Examples\Tutorial"; Filename: "{app}\examples++-tutorial"
+Name: "{group}\Examples\chapt3"; Filename: "{app}\examples++-chapt3"
+Name: "{group}\Examples\load"; Filename: "{app}\examples++-load"
+Name: "{group}\Examples\Main"; Filename: "{app}\examples++"
+Name: "{group}\Examples\Eigenvalues"; Filename: "{app}\examples++-eigen"
+Name: "{group}\Examples\3d"; Filename: "{app}\examples++-3d"
+ifelse(len(MPIPROG),0,; ,)Name: "{group}\Examples\mpi"; Filename: "{app}\examples++-mpi"
+Name: "{group}\Uninstall FreeFem++ VERSION"; Filename: "{uninstallexe}"
+
+; Desktop
+Name: "{userdesktop}\FreeFem++ VERSION"; Filename: "{app}\FreeFem++.exe"; IconFilename: "{app}\logo.ico"
+;Name: "{userdesktop}\FreeFem++ VERSION GUI"; Filename: "{app}\FreeFem++-cs.exe"
+Name: "{userdesktop}\FreeFem++ VERSION Examples"; Filename: "{group}\Examples"
+
+
+[Registry]
+
+; Link .edp file extension to FreeFem++
+Root: HKCR; Subkey: ".edp"; ValueType: string; ValueName: ""; ValueData: "FreeFemVERSIONScript"; Flags: uninsdeletevalue
+Root: HKCR; Subkey: "FreeFemVERSIONScript"; ValueType: string; ValueName: ""; ValueData: "FreeFem++ Script"; Flags: uninsdeletekey
+Root: HKCR; Subkey: "FreeFemVERSIONScript\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\logo.ico"
+Root: HKCR; Subkey: "FreeFemVERSIONScript\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\launchff++.exe"" ""%1"""
+
+
+[Tasks]
+Name: modifypath; Description: &Add application directory to your system path (if missing you can have trouble with on-the-fly graphic ) ; Flags:  checkedonce
+; unchecked
+
+[Code]
+function ModPathDir(): TArrayOfString;
+var
+			Dir:	TArrayOfString;
+		begin
+			setArrayLength(Dir, 1)
+			Dir[0] := ExpandConstant('{app}');
+			Result := Dir;
+		end;
+ #include "modpath.iss"
+
diff --git a/acmacros.m4 b/acmacros.m4
new file mode 100644
index 0000000..2e24467
--- /dev/null
+++ b/acmacros.m4
@@ -0,0 +1,39 @@
+# Checks whether a compiler accepts a given flag
+# ----------------------------------------------
+
+# $1 = compiler name
+# $2 = flag
+# $3 = make macro containing flags for that compiler
+# $4 =  exec is true ..
+# Note: changes AC_LANG()
+
+AC_DEFUN([CHECK_COMPILE_FLAG],
+	[AC_MSG_CHECKING(whether the $1 compiler accepts $2)
+	check_save_flags="$$3"
+	AC_LANG_PUSH($1)
+	$3="$$3 $2"
+
+	# The program needs to contain something for the test source
+	# file to be created by autoconf.
+
+	# Some options really need to be linked (not only compiled) to
+	# check whether they work.
+
+	AC_LINK_IFELSE([ifelse($1,Fortran 77,
+[       program x
+       end],
+			[AC_LANG_PROGRAM])],
+		check_flag_ok=yes,
+		check_flag_ok=no)
+	AC_MSG_RESULT($check_flag_ok)
+	if test "$check_flag_ok" = no;
+	then
+		$3="$check_save_flags"
+	fi
+	if test -n "$4" ;
+         then 
+	        $4="$check_flag_ok"
+	fi
+
+	AC_LANG_POP($1)
+])
diff --git a/acmpi.m4 b/acmpi.m4
new file mode 100644
index 0000000..d1a466b
--- /dev/null
+++ b/acmpi.m4
@@ -0,0 +1,331 @@
+# Checking wether we can produce a parallel version
+# -------------------------------------------------
+
+dnl m4_include(ax_mpi.m4)
+ff_save_path="$PATH"
+# We need to choose between mpich, openmpi  and lam for the Debian package
+AC_ARG_WITH(mpipath,[  --with-mpipath= the path of mpich under windows (no command  mpic++, ... )])
+AC_ARG_WITH(mpilibs,[  --with-mpilibs= the libs to add to c++,fc, ... (to link with c++ - ex:   -L/usr/local/lib -lmpi_f90  -lmpi_cxx -lmpi -lopen-rte -lopen-pal -lutil) ])
+AC_ARG_WITH(mpilibsc,[  --with-mpilibsc= the libs to add to c  ... (to link with cc (for pastix lib)  ex:   -L/usr/local/lib -lmpi -lopen-rte -lopen-pal -lutil) ])
+AC_ARG_WITH(mpiinc,[  --with-mpiinc= the include directory directive and preprocess directive  (no mpicc++, just use the compiler)) ])
+AC_ARG_WITH(mpi,[  --with-mpi=[yes|no|mpic++|lam|mpich|openmpi|/usr/local/bin/mpic++|... ]	or --without-mpi	Choose MPI implementation (default is mpic++)])
+if test "$with_mpi" != no ; then  
+#if test "$with_mpi" != no ; then
+#AX_MPI(with_mpi=yes, with_mpi=no)
+#fi
+
+# Default is mpic++ 
+ff_mpi_suffix="";
+if test "$with_mpi" = yes -o -z "$with_mpi" 
+then
+   ff_mpicxx=mpic++
+else 
+  case "$with_mpi" in
+ lam|mpich|openmpi)   ff_mpi_suffix=.$with_mpi;ff_mpicxx=mpic++.$with_mpi;;
+ *)  ff_mpicxx="$with_mpi" ;;
+ esac
+fi
+
+dnl AC_MSG_NOTICE([ xxxxxxxxxxxxxxxxxxxx --$with_mpilibs--]);
+if test -n "$with_mpiinc"  -a "$with_mpiinc" != no ; then
+  if test  "$with_mpi" = 'no' ; then with_mpi='yes'; fi
+  ff_MPI_INCLUDE="$with_mpiinc"
+fi
+if test -n "$with_mpilibs" -a "$with_mpilibs" != no ; then
+    ff_MPI_LIB="$with_mpilibs"
+    ff_MPI_LIBC="$with_mpilibs"
+    ff_MPI_LIBFC="$with_mpilibs"
+    MPICXX="$CXX $ff_MPI_INCLUDE"
+    MPIF77="$F77 $ff_MPI_INCLUDE"
+    MPIFC="$FC  $ff_MPI_INCLUDE"
+    MPICC="$CC  $ff_MPI_INCLUDE"
+    AC_MSG_NOTICE([   ---  set  all MPI compile to compiler:   $MPICC , $MPIF77, $MPIFC, $MPICC  ])
+fi
+
+if test -n "$with_mpilibsc" -a "$with_mpilibsc" != no ; then
+ ff_MPI_LIBC="$with_mpilibsc"
+fi
+
+AC_ARG_VAR(MPIRUN,[MPI run command ])
+AC_MSG_CHECKING(for MPIRUN)
+
+if test -z "$MPIRUN" ; then
+    AC_PATH_PROGS(MPIRUN,mpirun mpiexec mpiexec.exe,no)
+    if test "$MPIRUN" = no
+    then
+	ff_mpi=no
+    fi
+fi
+AC_MSG_RESULT($MPIRUN)
+
+AC_MSG_CHECKING(for mpipath )
+	
+if test "$with_mpi" != no -a ! -d  "$with_mpipath" -a "$MPIRUN" != no ; then 
+#   if "$MPIRUN" != no ; tehn 
+    with_mpipath=`AS_DIRNAME(["$MPIRUN"])`
+    with_mpipath=`AS_DIRNAME(["$with_mpipath"])`
+#    echo " ***** with_mpipath $with_mpipath \n"
+
+#    else 
+#    for i in '/c/Program Files (x86)/MPICH2' '/c/Program Files/MPICH2' 'c:\Program Files (x86)\MPICH2' 'c:\Program Files\MPICH2' ; do
+#	test -d "$i" &&  with_mpipath="$i" && break 
+#    done
+#    fi
+fi
+#echo "****  with_mpipath  '$with_mpipath' $MPIRUN *****"
+dnl if test "$with_mpilibs" != "no" ; then
+dnl fi
+case "$MPIRUN" in
+ */sgi/mpt/*) 
+	ff_MPI_INCLUDE_DIR=
+	ff_MPI_LIB_DIR=
+        test -f "$with_mpipath/include/mpif.h" &&  ff_MPI_INCLUDE_DIR="$with_mpipath/include"
+        test -f "$with_mpipath/lib/libmpi.so" &&  ff_MPI_LIB_DIR="$with_mpipath/lib"
+        if test -n "$ff_MPI_INCLUDE_DIR" -a -n "$ff_MPI_LIB_DIR" ; then 
+            ff_MPI_INCLUDE="-I'$ff_MPI_INCLUDE_DIR' "
+            with_mpiinc="$ff_MPI_INCLUDE"
+            ff_MPI_LIBC="-L'$ff_MPI_LIB_DIR' -lmpi"
+            ff_MPI_LIB="-L'$ff_MPI_LIB_DIR' -lmpi++ -lmpi"
+            ff_MPI_LIBFC="-L'$ff_MPI_LIB_DIR'  -lmpi"
+	    ff_mpitype=sgi 
+            test -z "$MPICXX" && MPICXX="$CXX $ff_MPI_INCLUDE"
+            test -z "$MPIF77" && MPIF77="$F77 $ff_MPI_INCLUDE"
+            test -z "$MPIFC"  && MPIFC="$FC  $ff_MPI_INCLUDE"
+            test -z "$MPICC"  && MPICC="$CC  $ff_MPI_INCLUDE"
+#	    echo " *** MPI sgi ..... "
+        fi
+	;;
+esac
+    
+if test  -d "$with_mpipath" -a "$ff_win32" = yes  ; then
+#    sed -e "s?@MPIDIR@?$with_mpipath?" -e "s?@F77@?$F77?" -e "s?@CC@?$CC?" -e "s?@CXX@?$CXX?"   -e "s?@FC@?$FC?"  <mpic++.in >mpic++
+ #   chmod a+rx mpic++ 
+  #  for i in mpicc mpif90 mpifc mpif77 ; do cp mpic++ $i; done 
+#    ff_pwd=`pwd`
+ #   with_mpi="$ff_pwd"/mpic++
+ #   MPICXX="$ff_pwd/mpic++"
+ #   MPIF77="$ff_pwd/mpif77"
+ #   MPIFC="$ff_pwd/mpif90"
+ #   MPICC="$ff_pwd/mpicc" zzzzzzzzzzz   
+    if  with_mpilibs=`which msmpi.dll` 
+    then
+	case "$ff_size_ptr"  in 
+	    4) with_mpipathlib="$with_mpipath/Lib/i386";;
+	    8) with_mpipathlib="$with_mpipath/Lib/amd64";;
+	    *) with_mpipath=no;;
+	esac
+	
+	
+	test -d "$with_mpipath/Inc" &&  ff_MPI_INCLUDE_DIR="$with_mpipath/Inc"
+	test -d "$with_mpipath/Include" &&  ff_MPI_INCLUDE_DIR="$with_mpipath/Include"
+	ff_MPI_INCLUDE="-I'$ff_MPI_INCLUDE_DIR' '-D_MSC_VER' '-D__int64=long long'"
+	with_mpiinc="$ff_MPI_INCLUDE"
+	test -z "$MPIRUN" && MPIRUN="$with_mpipath/bin/mpiexe.exe"
+	ff_MPI_LIBC="$with_mpilibs"
+	ff_MPI_LIB="$with_mpilibs"
+	ff_MPI_LIBFC="$with_mpilibs"
+	test -z "$MPICXX" && MPICXX="$CXX $ff_MPI_INCLUDE"
+	test -z "$MPIF77" && MPIF77="$F77 $ff_MPI_INCLUDE"
+	test -z "$MPIFC"  && MPIFC="$FC  $ff_MPI_INCLUDE"
+	test -z "$MPICC"  && MPICC="$CC  $ff_MPI_INCLUDE"
+    else
+	echo " #### no msmpi.dll  => no mpi under windows .... (FH) " >&AS_MESSAGE_LOG_FD
+	echo " #### no msmpi.dll  => no mpi under windows .... (FH) " >&AS_MESSAGE_FD
+	with_mpipath=no
+	with_mpi=no
+    fi
+else 
+    with_mpipath=no	   
+fi
+
+
+AC_MSG_RESULT($ff_mpi_path)
+
+
+
+
+dnl  correct ff_mpi_path august 2010 -- FH ...  
+
+
+ff_save_cxx="$CXX"
+ff_save_libs="$LIBS"
+
+
+if test "$with_mpi" != no
+then
+	ff_mpi_path=`AS_DIRNAME(["$MPIRUN"])`
+	dnl	echo "ff_mpi_path '$ff_mpi_path' .............."
+	case "$ff_mpi_path" in
+	    .|"") ff_mpi_path="$PATH";ff_defmpicxx="$ff_mpicxx";;
+	    *) ff_mpi_path="$ff_mpi_path";ff_defmpicxx=`expr "//$ff_mpicxx" : '.*/\(.*\)'`;; 
+	    dnl if also  add $PATH they  could be missing some different mpi version... 
+	esac	 
+	AC_ARG_VAR(MPICXX,[MPI C++ compiler command])
+	if test -z "$MPICXX" ; then
+	    AC_PATH_PROGS(MPICXX,$ff_defmpicxx mpic++$ff_mpi_suffix mpicxx$ff_mpi_suffix mpiCC$ff_mpi_suffix mpCC hcp mpxlC mpxlC_r cmpic++,no,$ff_mpi_path)
+	    AC_MSG_CHECKING(for MPICXX)
+	fi
+	ff_mpicxx="eval $MPICXX"
+	CXX=$ff_mpicxx
+	LIBS="$LIBS $ff_MPI_LIB"
+	test -z "$ff_mpi" && ff_mpi=yes
+	AC_LINK_IFELSE(
+	    [AC_LANG_SOURCE([
+#include <mpi.h>
+#include <stdio.h>
+int main(int argc,char **argv){
+  char name[[BUFSIZ]];
+  int length;
+  
+  MPI_Init(&argc, &argv);
+  MPI_Get_processor_name(name, &length);
+  printf("%s: hello world\n", name);
+  MPI_Finalize();
+  return 0;
+}])],ff_mpi=yes,ff_mpi=no)
+	AC_MSG_RESULT($ff_mpi)
+
+	# Also check that mpirun is there. If it isn't, then MPI is
+	# not fully installed.
+
+
+	if test "$ff_mpi" = yes;
+	then
+
+AC_MSG_CHECKING( MPI_DOUBLE_COMPLEX)
+
+	AC_COMPILE_IFELSE(
+[AC_LANG_SOURCE([
+#include <mpi.h>
+MPI_Datatype xxxx=MPI_DOUBLE_COMPLEX;
+])],
+ff_mpi_double_complex=yes,
+ff_mpi_double_complex=no)
+	AC_MSG_RESULT($ff_mpi_double_complex)
+if test "$ff_mpi_double_complex" = yes  ; then
+AC_DEFINE(HAVE_MPI_DOUBLE_COMPLEX,1, mpi_double_complex)
+fi
+
+
+	  echo "MPI CC $ff_mpi" >config_LIB_INFO
+
+		# We do not AC_DEFINE any special flag for parallel
+		# computation here, because it must only be set when the
+ 		# parallel program is compiled (see src/mpi/Makfile.am)
+		ff_mpiprog="FreeFem++-mpi${EXEEXT}"
+   		  AC_SUBST(MPIPROG,"$ff_mpiprog")
+   		  AC_SUBST(MPISCRIPT,"ff-mpirun")
+   		  AC_SUBST(MPIRUN,$MPIRUN)
+                  AC_SUBST(MPICXX,$MPICXX)
+	else
+	        AC_SUBST(MPICXX,$ff_save_cxx)
+	fi
+
+	if test "$ff_mpi" = yes;
+	then
+	  if test "$enable_fortran" != no
+	  then	
+	      
+	      AC_ARG_VAR(MPIF77,[MPI Fortran 77 compiler command])
+	      if test -z "$MPIF77" ; then    
+		  AC_PATH_PROGS(MPIF77, mpif90$ff_mpi_suffix mpif77$ff_mpi_suffix hf77 mpxlf mpf77 mpif90 mpf90 mpxlf90 mpxlf95 mpxlf_r cmpifc cmpif90c, "",$ff_mpi_path)
+	      fi
+	      AC_SUBST(MPIF77)
+	      AC_ARG_VAR(MPIFC,[MPI Fortran 90  compiler command])
+	      if test -z "$MPIFC" ; then
+		  AC_PATH_PROGS(MPIFC, mpif90$ff_mpi_suffix mpxlf95_r mpxlf90_r mpxlf95 mpxlf90 mpf90 cmpif90c, "",$ff_mpi_path)
+	      fi		
+	      AC_SUBST(MPIFC)
+	  fi
+
+	echo " ********************ffmpi= '$ff_mpi' *************   "
+	ff_MPI_INCLUDE="$with_mpiinc"
+	if test -z "$ff_mpitype" ; then 
+            ff_mpishow=`$MPICXX -show` 2>/dev/null
+            ff_mpicshow=`$MPICC -show` 2>/dev/null
+            ff_mpifcshow=`$MPIFC -show` 2>/dev/null
+	    if test "$with_mpilibs" = no -o -z "$with_mpilibs" ; then	 
+		[ff_MPI_INCLUDE=`echo $ff_mpishow|tr ' ' '\n'| grep -E '^-[^WLlOgp]|^-Wp,'|tr '\n' ' '`]
+		ff_MPI_LIB_DIRS=""
+		[ff_MPI_LIB=`echo $ff_mpishow|tr ' ' '\n'| grep -E '^-[Llp]|^-Wl,'|tr '\n' ' '`]
+		[ff_MPI_LIBC=`echo $ff_mpicshow|tr ' ' '\n'| grep -E '^-[Llp]|^-Wl,'|tr '\n' ' '`]
+		[ff_MPI_LIBFC=`echo $ff_mpifcshow|tr ' ' '\n'| grep -E '^-[Llp]|^-Wl,'|grep -v 'commons,use_dylibs' |tr '\n' ' '`]
+		[ff_mpi_idir=`echo $ff_mpishow|tr ' ' '\n'| grep -E '^-I'|sed s/^-I//|tr '\n' ' '`' /usr/include']
+	    fi
+	    [ff_mpi_idir=`echo $ff_MPI_INCLUDE|tr ' ' '\n'| grep -E '^-I'|sed s/^-I//|tr '\n' ' '`' /usr/include']
+	    [ff_mpi_ldir=`echo $ff_MPI_LIB|tr ' ' '\n'| grep -E '^-[Llp]|^-Wl,'|sed -e 's/^-[Llp]//' -e 's/^-Wl,]//'  |tr '\n' ' '`' /usr/lib']
+	    
+	    if  test -z "$ff_MPI_INCLUDE_DIR" ; then  
+		for i in $ff_mpi_idir; do
+		    if test -f "$i/mpi.h" -a -z "$ff_MPI_INCLUDE_DIR"  ;then
+			ff_MPI_INCLUDE_DIR=$i
+		    fi
+		done
+	    fi
+	    for i in $ff_mpi_ldir; do
+		ff_tmp=`ls $i/libmpi.*|head -1`
+		if test  -f "$ff_tmp"  -a -z "$ff_MPI_LIB_DIRS"  ;then
+		    ff_MPI_LIB_DIRS=$i
+		fi
+	    done
+	fi
+	AC_SUBST(MPICXX,$MPICXX)		
+	AC_ARG_VAR(MPICC,[MPI C compiler command in $ff_mpi_path])
+	if test -z "$MPICC" ; then		
+	    AC_PATH_PROGS(MPICC,mpicc$ff_mpi_suffix hcc mpcc mpcc_r mpxlc cmpicc, "",$ff_mpi_path)
+	fi
+	AC_SUBST(MPICC,$MPICC)
+	AC_SUBST(PASTIX_HOSTARCH,$ff_HOSTARCH_pastix)
+
+	if test ! -f "$ff_MPI_INCLUDE_DIR/mpif.h"  ; then
+	    AC_MSG_NOTICE([ MPI without fortran no file "$ff_MPI_INCLUDE_DIR/mpif.h"  ])
+	else
+	    if test -n "$MPIFC" ; then
+	        AC_FF_ADDWHERELIB(mpifc,$ff_MPI_LIBFC,$ff_MPI_INCLUDE)
+	        AC_FF_ADDWHERELIB(mpif77,$ff_MPI_LIBFC,$ff_MPI_INCLUDE)
+dnl		  [echo mpifc LD "'$ff_MPI_LIBFC'"   >>$ff_where_lib_conf ]
+dnl		  [echo mpifc INCLUDE "'$ff_MPI_INCLUDE'" >>$ff_where_lib_conf ]
+dnl		  [echo mpif77 LD "'$ff_MPI_LIBFC'"   >>$ff_where_lib_conf ]
+dnl		  [echo mpif77 INCLUDE "'$ff_MPI_INCLUDE'" >>$ff_where_lib_conf ]
+	    fi
+  	fi
+	if test -n "$MPICXX" ; then 	    
+            AC_FF_ADDWHERELIB(mpi,$ff_MPI_LIB,$ff_MPI_INCLUDE)
+dnl              [echo mpi LD "'$ff_MPI_LIB'"    >>$ff_where_lib_conf ]
+dnl              [echo mpi INCLUDE "'$ff_MPI_INCLUDE'" >>$ff_where_lib_conf ]
+	fi
+	AC_SUBST(MPI_INC_DIR,$ff_MPI_INCLUDE_DIR)      		
+	AC_SUBST(MPI_INCLUDE,$ff_MPI_INCLUDE)
+	AC_SUBST(MPI_LIB_DIRS,$ff_MPI_LIB_DIRS)
+	AC_SUBST(MPI_LIB,$ff_MPI_LIB)
+	AC_SUBST(MPI_LIBC,$ff_MPI_LIBC)
+	AC_SUBST(MPI_LIBFC,$ff_MPI_LIBFC)
+        AC_SUBST(SKIP_TESTS_MPI,"no")
+	fi
+	CXX="$ff_save_cxx"
+	LIBS="$ff_save_libs"
+fi
+fi
+##  clean on MPI variable if not MPI ...
+if test "$ff_mpi" != yes ; then
+          
+	  AC_SUBST(MPIRUN,"")      		
+	  AC_SUBST(MPICC,"")      		
+	  AC_SUBST(MPICXX,"")      		
+	  AC_SUBST(MPIF77,"")      		
+	  AC_SUBST(MPIFC,"")      		
+	  AC_SUBST(MPI_INCLUDE,"")
+	  AC_SUBST(MPI_LIB_DIRS,"")
+	  AC_SUBST(MPI_LIB,"")
+	  AC_SUBST(MPI_LIBC,"")
+	  AC_SUBST(MPI_LIBFC,"")
+          AC_SUBST(SKIP_TESTS_MPI,"yes")
+	  ff_mpi=no
+
+fi
+
+# Local Variables:
+# mode:shell-script
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/acoptim.m4 b/acoptim.m4
new file mode 100644
index 0000000..15b5f63
--- /dev/null
+++ b/acoptim.m4
@@ -0,0 +1,255 @@
+# Choosing debugging and/or optimization flags for compilation
+# ------------------------------------------------------------
+
+AC_ARG_ENABLE(profiling,[  --enable-profiling	Turn on profiling])
+if test "$enable_profiling" = yes
+then
+	CXXFLAGS="$CXXFLAGS -pg"
+	LDFLAGS="$LDFLAGS -pg"
+fi
+
+if test "$enable_m64" = yes -a "$enable_m32" 
+then
+  	    AC_MSG_ERROR([ Choose  32 or 64 architecture not the both ],1);  
+fi
+AC_ARG_ENABLE(m64,[  --enable-m64	Turn on 64 bits architecture])
+if test "$enable_m64" = yes
+then
+	ff_m64=-m64	
+        CHECK_COMPILE_FLAG(C,$ff_m64,CFLAGS)
+        CHECK_COMPILE_FLAG(C,$ff_m64,CNOFLAGS)
+	CHECK_COMPILE_FLAG(C++,$ff_m64,CXXFLAGS)
+	CHECK_COMPILE_FLAG(Fortran 77,$ff_m64,FFLAGS)	
+#  add -fPIC on on 64 architecture 
+        CHECK_COMPILE_FLAG(C,-fPIC,CFLAGS)
+	CHECK_COMPILE_FLAG(C++,-fPIC,CXXFLAGS)
+	CHECK_COMPILE_FLAG(Fortran 77,-fPIC,FFLAGS)	
+
+fi
+AC_ARG_ENABLE(m32,[  --enable-m32	Turn on 32 bits architecture])
+if test "$enable_m32" = yes 
+then
+	ff_m32=-m32	
+        CHECK_COMPILE_FLAG(C,$ff_m32,CFLAGS)
+        CHECK_COMPILE_FLAG(C,$ff_m32,CNOFLAGS)
+	CHECK_COMPILE_FLAG(C++,$ff_m32,CXXFLAGS)
+	CHECK_COMPILE_FLAG(Fortran 77,$ff_m32,FFLAGS)	
+#  add -fPIC on on 64 architecture 
+#        CHECK_COMPILE_FLAG(C,-fPIC,CFLAGS)
+#	CHECK_COMPILE_FLAG(C++,-fPIC,CXXFLAGS)
+#	CHECK_COMPILE_FLAG(Fortran 77,-fPIC,FFLAGS)	
+
+fi
+
+# Debug mode (no optimisation)
+# ----------------------------
+
+AC_MSG_CHECKING(whether to generate debugging information)
+
+AC_ARG_ENABLE(debug,[  --enable-debug	Turn on debug versions of FreeFem++])
+AC_ARG_ENABLE(optim,[  --enable-optim	Turn on compiler optimization])
+
+if test "$enable_debug" = yes;
+then
+
+	AC_MSG_RESULT(yes)
+	CFLAGS="`echo $CFLAGS | sed 's/-O2//g'`"
+	FFLAGS="`echo $FFLAGS | sed 's/-O2//g'`"
+	CXXFLAGS="`echo $CXXFLAGS | sed 's/-O2//g'`"
+        CHECK_COMPILE_FLAG(C,-g,CFLAGS)
+	CHECK_COMPILE_FLAG(C++,-g,CXXFLAGS)
+	CHECK_COMPILE_FLAG(Fortran 77,-g,FFLAGS)	
+
+else
+	AC_MSG_RESULT(no)
+
+	# No debugging information in optimized code
+
+	CFLAGS="$CFLAGS -DNDEBUG"
+	FFLAGS="$FFLAGS -DNDEBUG"
+	CXXFLAGS="$CXXFLAGS -DNDEBUG"
+fi
+
+# Hardware-independant optimization
+# ---------------------------------
+
+if test "$enable_debug" != yes -a "$enable_optim" != no;
+then
+	CHECK_COMPILE_FLAG(C,-O3,CFLAGS)
+	CHECK_COMPILE_FLAG(C++,-O3,CXXFLAGS)
+	CHECK_COMPILE_FLAG(Fortran 77,-O3,FFLAGS)
+fi
+
+AC_ARG_ENABLE(generic,
+[  --enable-generic	Turn off hardware-dependant optimization options])
+
+# FFCS: remove "-mcpu=common" to allow other hardware-dependant values of cpu for PowerPC - thank you Fred (20/02/11)
+
+if test $enable_ffcs = yes
+then
+    # Generic code
+    if test "$enable_debug" != yes \
+	-a "$enable_optim" != no \
+	-a "$enable_generic" = yes
+    then
+	CHECK_COMPILE_FLAG(C,-mcpu=common,CFLAGS)
+	CHECK_COMPILE_FLAG(C++,-mcpu=common,CXXFLAGS)
+	CHECK_COMPILE_FLAG(Fortran 77,-mcpu=common,FFLAGS)
+    fi
+fi
+
+# Hardware-dependant optimization
+# -------------------------------
+
+if test "$enable_debug" != yes \
+    -a "$enable_optim" != no \
+    -a "$enable_generic" != yes
+then
+
+# Autoconf always chooses -O2. -O2 in gcc makes some functions
+# disappear. This is not ideal for debugging. And when we optimize, we
+# do not use -O2 anyway.
+
+CFLAGS="`echo $CFLAGS | sed 's/-O2//g'`"
+FFLAGS="`echo $FFLAGS | sed 's/-O2//g'`"
+CXXFLAGS="`echo $CXXFLAGS | sed 's/-O2//g'`"
+
+    # MacOS X Darwin
+    if test -x /usr/bin/hostinfo
+	then
+        
+
+	# If we are on MacOS X to choise the optimisaztion 
+	AC_MSG_CHECKING(GCC version)
+
+        ff_gcc4=`$CC  --version |awk  ' NR==1 {print $3}'|sed -e 's/\..*$//'` 
+	ff_clang=`$CC  --version |awk  '/clang/  {print $4}'`
+	if test -n "$ff_clang" ; then ff_gcc4="llvm"; fi
+	AC_MSG_RESULT($ff_gcc4)
+
+	# At the moment, we do not know how to produce correct
+	# optimizated code on G5.
+	AC_MSG_CHECKING(PowerPC architecture)
+	ff_machine=`/usr/bin/machine`
+        ff_fast="-O3"
+	if test	-n "$ff_clang" ; then
+          ff_fast='-O3 -fPIC'
+	elif test `uname` = Darwin 
+	    then
+	    # Optimization flags: -fast option do not work because the
+	    # -malign-natural flags create wrong IO code
+            if test  "$ff_gcc4" -eq 4 
+	    then
+               ff_fast='-fast -fPIC'
+            else
+	      ff_fast='-fPIC -O3 -funroll-loops -fstrict-aliasing -fsched-interblock -falign-loops=16 -falign-jumps=16 -falign-functions=16 -falign-jumps-max-skip=15 -falign-loops-max-skip=15 -ffast-math  -mpowerpc-gpopt -force_cpusubtype_ALL -fstrict-aliasing  -mpowerpc64 '
+	    fi
+	fi        
+
+
+        # CPU detection
+
+	case $ff_machine  in
+	  ppc7450) # G4
+		ff_fast="$ff_fast -mtune=G4 -mcpu=G4";;
+          ppc970) # G5 
+	        # remove -fstrict-aliasing on G5 to much optim the
+	        # code cash in GC
+		ff_fast="`echo $ff_fast -mtune=G5 -mcpu=G5| sed 's/-fstrict-aliasing //g'`";;
+          ppc*) # G3 ????
+	       ff_fast="-O3";;
+	  i486)
+	    ff_fast="-O3 $ff_fast";;
+	  x86_64*)
+	  ff_fast="-O3 $ff_fast";;
+	  *)
+	    AC_MSG_ERROR(cannot determine apple cpu type )
+	    ff_fast="-O3";;
+	 esac
+
+
+	AC_MSG_RESULT($ff_fast)
+
+        CHECK_COMPILE_FLAG(C,$ff_fast,CFLAGS)
+	CHECK_COMPILE_FLAG(C++,$ff_fast,CXXFLAGS)
+	CHECK_COMPILE_FLAG(Fortran 77,$ff_fast,FFLAGS)
+
+
+    # Linux
+    elif test -f /proc/cpuinfo
+	then
+
+	# Specific processors
+	proc_type=unknown
+	ff_optim_type=
+	if test `grep 'Pentium III (Coppermine)' /proc/cpuinfo|wc -l` -gt 0
+	    then
+	    proc_type=pentium3
+	    ff_optim_type=-P3
+	elif test `grep 'Intel(R) Pentium(R) III ' /proc/cpuinfo|wc -l` -gt 0
+	    then
+	    proc_type=pentium3
+	    ff_optim_type=-P3
+	elif test `grep 'Intel(R) Pentium(R) 4 ' /proc/cpuinfo|wc -l` -gt 0
+	    then
+	    proc_type=pentium4
+	    ff_optim_type=-P4
+	elif test `grep 'Intel(R) Xeon(TM) CPU' /proc/cpuinfo|wc -l` -gt 0
+	    then
+	    proc_type=pentium4
+	    ff_optim_type=-P4
+	elif test `grep 'AMD Athlon(tm) Processor' /proc/cpuinfo|wc -l` -gt 0
+	    then
+	    proc_type=athlon
+	    ff_optim_type=-Athlon
+	elif test `grep 'AMD Athlon(tm) XP' /proc/cpuinfo|wc -l` -gt 0
+	    then
+	    proc_type=athlon-xp
+	    ff_optim_type=-AthlonXP
+	fi
+
+	if test "$proc_type" != unknown
+	    then
+	    CHECK_COMPILE_FLAG(C,-march=$proc_type,CFLAGS)
+	    CHECK_COMPILE_FLAG(C++,-march=$proc_type,CXXFLAGS)
+	    CHECK_COMPILE_FLAG(Fortran 77,-march=$proc_type,FFLAGS)
+	fi
+
+	# If we did not find a processor type (this happens with
+	# cygwin), try and select separate capabilities instead.
+
+	if test "$proc_type" = unknown
+	    then
+	    if test `grep -e '^flags.*mmx' /proc/cpuinfo|wc -l` -gt 0
+		then
+		CHECK_COMPILE_FLAG(C,-mmmx,CFLAGS)
+		CHECK_COMPILE_FLAG(C++,-mmmx,CXXFLAGS)
+		CHECK_COMPILE_FLAG(Fortran 77,-mmmx,FFLAGS)
+	    fi
+	    if test `grep -e '^flags.*sse ' /proc/cpuinfo|wc -l` -gt 0
+		then
+		CHECK_COMPILE_FLAG(C,-msse,CFLAGS)
+		CHECK_COMPILE_FLAG(C++,-msse,CXXFLAGS)
+		CHECK_COMPILE_FLAG(Fortran 77,-msse,FFLAGS)
+	    fi
+	    if test `grep -e '^flags.*sse2' /proc/cpuinfo|wc -l` -gt 0
+		then
+		CHECK_COMPILE_FLAG(C,-msse2,CFLAGS)
+		CHECK_COMPILE_FLAG(C++,-msse2,CXXFLAGS)
+		CHECK_COMPILE_FLAG(Fortran 77,-msse2,FFLAGS)
+	    fi
+	    if test `grep -e '^flags.*3dnow' /proc/cpuinfo|wc -l` -gt 0
+		then
+		CHECK_COMPILE_FLAG(C,-m3dnow,CFLAGS)
+		CHECK_COMPILE_FLAG(C++,-m3dnow,CXXFLAGS)
+		CHECK_COMPILE_FLAG(Fortran 77,-m3dnow,FFLAGS)
+	    fi
+	fi
+    fi
+fi
+
+# Defines a variable containing the optimization type, to be used in
+# binary archive names. It may be empty if only generic optimization
+# is used.
+
+AC_SUBST(OPTIM_TYPE,$ff_optim_type)
diff --git a/ax_lib_gsl.m4 b/ax_lib_gsl.m4
new file mode 100644
index 0000000..fc7fb44
--- /dev/null
+++ b/ax_lib_gsl.m4
@@ -0,0 +1,162 @@
+# Configure path for the GNU Scientific Library
+# Christopher R. Gabriel <cgabriel at linux.it>, April 2000
+
+
+AC_DEFUN([AX_PATH_GSL],
+[
+AC_ARG_WITH(gsl-prefix,[  --with-gsl-prefix=PFX   Prefix where GSL is installed (optional)],
+            gsl_prefix="$withval", gsl_prefix="")
+AC_ARG_WITH(gsl-exec-prefix,[  --with-gsl-exec-prefix=PFX Exec prefix where GSL is installed (optional)],
+            gsl_exec_prefix="$withval", gsl_exec_prefix="")
+AC_ARG_ENABLE(gsltest, [  --disable-gsltest       Do not try to compile and run a test GSL program],
+		    , enable_gsltest=yes)
+
+  if test "x${GSL_CONFIG+set}" != xset ; then
+     if test "x$gsl_prefix" != x ; then
+         GSL_CONFIG="$gsl_prefix/bin/gsl-config"
+     fi
+     if test "x$gsl_exec_prefix" != x ; then
+        GSL_CONFIG="$gsl_exec_prefix/bin/gsl-config"
+     fi
+  fi
+
+  AC_PATH_PROG(GSL_CONFIG, gsl-config, no)
+  min_gsl_version=ifelse([$1], ,0.2.5,$1)
+  AC_MSG_CHECKING(for GSL - version >= $min_gsl_version)
+  no_gsl=""
+  if test "$GSL_CONFIG" = "no" ; then
+    no_gsl=yes
+  else
+    GSL_CFLAGS=`$GSL_CONFIG --cflags`
+    GSL_LIBS=`$GSL_CONFIG --libs`
+
+    gsl_major_version=`$GSL_CONFIG --version | \
+           sed 's/^\([[0-9]]*\).*/\1/'`
+    if test "x${gsl_major_version}" = "x" ; then
+       gsl_major_version=0
+    fi
+
+    gsl_minor_version=`$GSL_CONFIG --version | \
+           sed 's/^\([[0-9]]*\)\.\{0,1\}\([[0-9]]*\).*/\2/'`
+    if test "x${gsl_minor_version}" = "x" ; then
+       gsl_minor_version=0
+    fi
+
+    gsl_micro_version=`$GSL_CONFIG --version | \
+           sed 's/^\([[0-9]]*\)\.\{0,1\}\([[0-9]]*\)\.\{0,1\}\([[0-9]]*\).*/\3/'`
+    if test "x${gsl_micro_version}" = "x" ; then
+       gsl_micro_version=0
+    fi
+
+    if test "x$enable_gsltest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GSL_CFLAGS"
+      LIBS="$LIBS $GSL_LIBS"
+
+      rm -f conf.gsltest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char* my_strdup (const char *str);
+
+char*
+my_strdup (const char *str)
+{
+  char *new_str;
+  
+  if (str)
+    {
+      new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char));
+      strcpy (new_str, str);
+    }
+  else
+    new_str = NULL;
+  
+  return new_str;
+}
+
+int main (void)
+{
+  int major = 0, minor = 0, micro = 0;
+  int n;
+  char *tmp_version;
+
+  system ("touch conf.gsltest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = my_strdup("$min_gsl_version");
+
+  n = sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) ;
+
+  if (n != 2 && n != 3) {
+     printf("%s, bad version string\n", "$min_gsl_version");
+     exit(1);
+   }
+
+   if (($gsl_major_version > major) ||
+      (($gsl_major_version == major) && ($gsl_minor_version > minor)) ||
+      (($gsl_major_version == major) && ($gsl_minor_version == minor) && ($gsl_micro_version >= micro)))
+     { 
+       exit(0);
+     }   
+   else
+     {
+       exit(1);
+     }
+}
+
+],, no_gsl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gsl" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GSL_CONFIG" = "no" ; then
+       echo "*** The gsl-config script installed by GSL could not be found"
+       echo "*** If GSL was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GSL_CONFIG environment variable to the"
+       echo "*** full path to gsl-config."
+     else
+       if test -f conf.gsltest ; then
+        :
+       else
+          echo "*** Could not run GSL test program, checking why..."
+          CFLAGS="$CFLAGS $GSL_CFLAGS"
+          LIBS="$LIBS $GSL_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GSL or finding the wrong"
+          echo "*** version of GSL. If it is not finding GSL, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GSL was incorrectly installed"
+          echo "*** or that you have moved GSL since it was installed. In the latter case, you"
+          echo "*** may want to edit the gsl-config script: $GSL_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+#     GSL_CFLAGS=""
+#     GSL_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GSL_CFLAGS)
+  AC_SUBST(GSL_LIBS)
+  rm -f conf.gsltest
+])
+
+AU_ALIAS([AM_PATH_GSL], [AX_PATH_GSL])
diff --git a/ax_lib_hdf5.m4 b/ax_lib_hdf5.m4
new file mode 100644
index 0000000..3174385
--- /dev/null
+++ b/ax_lib_hdf5.m4
@@ -0,0 +1,309 @@
+# ===========================================================================
+#        http://www.gnu.org/software/autoconf-archive/ax_lib_hdf5.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_LIB_HDF5([serial/parallel])
+#
+# DESCRIPTION
+#
+#   This macro provides tests of the availability of HDF5 library.
+#
+#   The optional macro argument should be either 'serial' or 'parallel'. The
+#   former only looks for serial HDF5 installations via h5cc. The latter
+#   only looks for parallel HDF5 installations via h5pcc. If the optional
+#   argument is omitted, serial installations will be preferred over
+#   parallel ones.
+#
+#   The macro adds a --with-hdf5 option accepting one of three values:
+#
+#     no   - do not check for the HDF5 library.
+#     yes  - do check for HDF5 library in standard locations.
+#     path - complete path to the HDF5 helper script h5cc or h5pcc.
+#
+#   If HDF5 is successfully found, this macro calls
+#
+#     AC_SUBST(HDF5_VERSION)
+#     AC_SUBST(HDF5_CC)
+#     AC_SUBST(HDF5_CFLAGS)
+#     AC_SUBST(HDF5_CPPFLAGS)
+#     AC_SUBST(HDF5_LDFLAGS)
+#     AC_SUBST(HDF5_LIBS)
+#     AC_SUBST(HDF5_FC)
+#     AC_SUBST(HDF5_FFLAGS)
+#     AC_SUBST(HDF5_FLIBS)
+#     AC_DEFINE(HAVE_HDF5)
+#
+#   and sets with_hdf5="yes".  Additionally, the macro sets
+#   with_hdf5_fortran="yes" if a matching Fortran wrapper script is found.
+#   Note that Autconf's Fortran support is not used to perform this check.
+#   H5CC and H5FC will contain the appropriate serial or parallel HDF5
+#   wrapper script locations.
+#
+#   If HDF5 is disabled or not found, this macros sets with_hdf5="no" and
+#   with_hdf5_fortran="no".
+#
+#   Your configuration script can test $with_hdf to take any further
+#   actions. HDF5_{C,CPP,LD}FLAGS may be used when building with C or C++.
+#   HDF5_F{FLAGS,LIBS} should be used when building Fortran applications.
+#
+#   To use the macro, one would code one of the following in "configure.ac"
+#   before AC_OUTPUT:
+#
+#     1) dnl Check for HDF5 support
+#        AX_LIB_HDF5()
+#
+#     2) dnl Check for serial HDF5 support
+#        AX_LIB_HDF5([serial])
+#
+#     3) dnl Check for parallel HDF5 support
+#        AX_LIB_HDF5([parallel])
+#
+#   One could test $with_hdf5 for the outcome or display it as follows
+#
+#     echo "HDF5 support:  $with_hdf5"
+#
+#   You could also for example, override the default CC in "configure.ac" to
+#   enforce compilation with the compiler that HDF5 uses:
+#
+#     AX_LIB_HDF5([parallel])
+#     if test "$with_hdf5" = "yes"; then
+#             CC="$HDF5_CC"
+#     else
+#             AC_MSG_ERROR([Unable to find HDF5, we need parallel HDF5.])
+#     fi
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Timothy Brown <tbrown at freeshell.org>
+#   Copyright (c) 2010 Rhys Ulerich <rhys.ulerich at gmail.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 11
+
+AC_DEFUN([AX_LIB_HDF5], [
+
+AC_REQUIRE([AC_PROG_SED])
+AC_REQUIRE([AC_PROG_AWK])
+AC_REQUIRE([AC_PROG_GREP])
+
+dnl Check first argument is one of the recognized values.
+dnl Fail eagerly if is incorrect as this simplifies case statements below.
+if   test "m4_normalize(m4_default([$1],[]))" = ""        ; then
+    : # Recognized value
+elif test "m4_normalize(m4_default([$1],[]))" = "serial"  ; then
+    : # Recognized value
+elif test "m4_normalize(m4_default([$1],[]))" = "parallel"; then
+    : # Recognized value
+else
+    AC_MSG_ERROR([
+Unrecognized value for AX[]_LIB_HDF5 within configure.ac.
+If supplied, argument 1 must be either 'serial' or 'parallel'.
+])
+fi
+
+dnl Add a default --with-hdf5 configuration option.
+AC_ARG_WITH([hdf5],
+  AS_HELP_STRING(
+    [--with-hdf5=[yes/no/PATH]],
+    m4_case(m4_normalize([$1]),
+            [serial],   [location of h5cc for serial HDF5 configuration],
+            [parallel], [location of h5pcc for parallel HDF5 configuration],
+            [location of h5cc or h5pcc for HDF5 configuration])
+  ),
+  [if test "$withval" = "no"; then
+     with_hdf5="no"
+   elif test "$withval" = "yes"; then
+     with_hdf5="yes"
+   else
+     with_hdf5="yes"
+     H5CC="$withval"
+   fi],
+   [with_hdf5="yes"]
+)
+
+dnl Set defaults to blank
+HDF5_CC=""
+HDF5_VERSION=""
+HDF5_CFLAGS=""
+HDF5_CPPFLAGS=""
+HDF5_LDFLAGS=""
+HDF5_LIBS=""
+HDF5_FC=""
+HDF5_FFLAGS=""
+HDF5_FLIBS=""
+
+dnl Try and find hdf5 compiler tools and options.
+if test "$with_hdf5" = "yes"; then
+    if test -z "$H5CC"; then
+        dnl Check to see if H5CC is in the path.
+        AC_PATH_PROGS(
+            [H5CC],
+            m4_case(m4_normalize([$1]),
+                [serial],   [h5cc],
+                [parallel], [h5pcc],
+                [h5cc h5pcc]),
+            [])
+    else
+        AC_MSG_CHECKING([Using provided HDF5 C wrapper])
+        AC_MSG_RESULT([$H5CC])
+    fi
+    AC_MSG_CHECKING([for HDF5 libraries])
+    if test ! -f "$H5CC" || test ! -x "$H5CC"; then
+        AC_MSG_RESULT([no])
+        AC_MSG_WARN(m4_case(m4_normalize([$1]),
+            [serial],  [
+Unable to locate serial HDF5 compilation helper script 'h5cc'.
+Please specify --with-hdf5=<LOCATION> as the full path to h5cc.
+HDF5 support is being disabled (equivalent to --with-hdf5=no).
+],            [parallel],[
+Unable to locate parallel HDF5 compilation helper script 'h5pcc'.
+Please specify --with-hdf5=<LOCATION> as the full path to h5pcc.
+HDF5 support is being disabled (equivalent to --with-hdf5=no).
+],            [
+Unable to locate HDF5 compilation helper scripts 'h5cc' or 'h5pcc'.
+Please specify --with-hdf5=<LOCATION> as the full path to h5cc or h5pcc.
+HDF5 support is being disabled (equivalent to --with-hdf5=no).
+]))
+        with_hdf5="no"
+        with_hdf5_fortran="no"
+    else
+        dnl Get the h5cc output
+        HDF5_SHOW=$(eval $H5CC -show)
+
+        dnl Get the actual compiler used
+        HDF5_CC=$(eval $H5CC -show | $AWK '{print $[]1}')
+        if test "$HDF5_CC" = "ccache"; then
+            HDF5_CC=$(eval $H5CC -show | $AWK '{print $[]2}')
+        fi
+
+        dnl h5cc provides both AM_ and non-AM_ options
+        dnl depending on how it was compiled either one of
+        dnl these are empty. Lets roll them both into one.
+
+        dnl Look for "HDF5 Version: X.Y.Z"
+        HDF5_VERSION=$(eval $H5CC -showconfig | $GREP 'HDF5 Version:' \
+            | $AWK '{print $[]3}')
+
+        dnl A ideal situation would be where everything we needed was
+        dnl in the AM_* variables. However most systems are not like this
+        dnl and seem to have the values in the non-AM variables.
+        dnl
+        dnl We try the following to find the flags:
+        dnl (1) Look for "NAME:" tags
+        dnl (2) Look for "H5_NAME:" tags
+        dnl (3) Look for "AM_NAME:" tags
+        dnl
+        HDF5_tmp_flags=$(eval $H5CC -showconfig \
+            | $GREP 'FLAGS\|Extra libraries:' \
+            | $AWK -F: '{printf("%s "), $[]2}' )
+
+        dnl Find the installation directory and append include/
+        HDF5_tmp_inst=$(eval $H5CC -showconfig \
+            | $GREP 'Installation point:' \
+            | $AWK '{print $[]NF}' )
+
+        dnl Add this to the CPPFLAGS
+        HDF5_CPPFLAGS="-I${HDF5_tmp_inst}/include"
+
+        dnl Now sort the flags out based upon their prefixes
+        for arg in $HDF5_SHOW $HDF5_tmp_flags ; do
+          case "$arg" in
+            -I*) echo $HDF5_CPPFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \
+                  || HDF5_CPPFLAGS="$arg $HDF5_CPPFLAGS"
+              ;;
+            -L*) echo $HDF5_LDFLAGS | $GREP -e "$arg" 2>&1 >/dev/null \
+                  || HDF5_LDFLAGS="$arg $HDF5_LDFLAGS"
+              ;;
+            -l*) echo $HDF5_LIBS | $GREP -e "$arg" 2>&1 >/dev/null \
+                  || HDF5_LIBS="$arg $HDF5_LIBS"
+              ;;
+          esac
+        done
+
+        HDF5_LIBS="$HDF5_LIBS -lhdf5"
+        AC_MSG_RESULT([yes (version $[HDF5_VERSION])])
+
+        dnl See if we can compile
+        ax_lib_hdf5_save_CC=$CC
+        ax_lib_hdf5_save_CPPFLAGS=$CPPFLAGS
+        ax_lib_hdf5_save_LIBS=$LIBS
+        ax_lib_hdf5_save_LDFLAGS=$LDFLAGS
+        CC=$HDF5_CC
+        CPPFLAGS=$HDF5_CPPFLAGS
+        LIBS=$HDF5_LIBS
+        LDFLAGS=$HDF5_LDFLAGS
+        AC_CHECK_HEADER([hdf5.h], [ac_cv_hadf5_h=yes], [ac_cv_hadf5_h=no])
+        AC_CHECK_LIB([hdf5], [H5Fcreate], [ac_cv_libhdf5=yes],
+                     [ac_cv_libhdf5=no])
+        if test "$ac_cv_hadf5_h" = "no" && test "$ac_cv_libhdf5" = "no" ; then
+          AC_MSG_WARN([Unable to compile HDF5 test program])
+        fi
+        dnl Look for HDF5's high level library
+        AC_HAVE_LIBRARY([hdf5_hl], [HDF5_LIBS="$HDF5_LIBS -lhdf5_hl"], [], [])
+
+        CC=$ax_lib_hdf5_save_CC
+        CPPFLAGS=$ax_lib_hdf5_save_CPPFLAGS
+        LIBS=$ax_lib_hdf5_save_LIBS
+        LDFLAGS=$ax_lib_hdf5_save_LDFLAGS
+
+        AC_MSG_CHECKING([for matching HDF5 Fortran wrapper])
+        dnl Presume HDF5 Fortran wrapper is just a name variant from H5CC
+        H5FC=$(eval echo -n $H5CC | $SED -n 's/cc$/fc/p')
+        if test -x "$H5FC"; then
+            AC_MSG_RESULT([$H5FC])
+            with_hdf5_fortran="yes"
+            AC_SUBST([H5FC])
+
+            dnl Again, pry any remaining -Idir/-Ldir from compiler wrapper
+            for arg in `$H5FC -show`
+            do
+              case "$arg" in #(
+                -I*) echo $HDF5_FFLAGS | $GREP -e "$arg" >/dev/null \
+                      || HDF5_FFLAGS="$arg $HDF5_FFLAGS"
+                  ;;#(
+                -L*) echo $HDF5_FFLAGS | $GREP -e "$arg" >/dev/null \
+                      || HDF5_FFLAGS="$arg $HDF5_FFLAGS"
+                     dnl HDF5 installs .mod files in with libraries,
+                     dnl but some compilers need to find them with -I
+                     echo $HDF5_FFLAGS | $GREP -e "-I${arg#-L}" >/dev/null \
+                      || HDF5_FFLAGS="-I${arg#-L} $HDF5_FFLAGS"
+                  ;;
+              esac
+            done
+
+            dnl Make Fortran link line by inserting Fortran libraries
+            for arg in $HDF5_LIBS
+            do
+              case "$arg" in #(
+                -lhdf5_hl) HDF5_FLIBS="$HDF5_FLIBS -lhdf5hl_fortran $arg"
+                  ;; #(
+                -lhdf5)    HDF5_FLIBS="$HDF5_FLIBS -lhdf5_fortran $arg"
+                  ;; #(
+                *) HDF5_FLIBS="$HDF5_FLIBS $arg"
+                  ;;
+              esac
+            done
+        else
+            AC_MSG_RESULT([no])
+            with_hdf5_fortran="no"
+        fi
+
+	AC_SUBST([HDF5_VERSION])
+	AC_SUBST([HDF5_CC])
+	AC_SUBST([HDF5_CFLAGS])
+	AC_SUBST([HDF5_CPPFLAGS])
+	AC_SUBST([HDF5_LDFLAGS])
+	AC_SUBST([HDF5_LIBS])
+	AC_SUBST([HDF5_FC])
+	AC_SUBST([HDF5_FFLAGS])
+	AC_SUBST([HDF5_FLIBS])
+	AC_DEFINE([HAVE_HDF5], [1], [Defined if you have HDF5 support])
+    fi
+fi
+])
diff --git a/build/cleancrlf b/build/cleancrlf
new file mode 100755
index 0000000..7a443a0
--- /dev/null
+++ b/build/cleancrlf
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+# ======================================================================
+# Written by Antoine Le Hyaric
+# http://www.ljll.math.upmc.fr/lehyaric
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+#
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem perl start=04/06/2012 upmc written
+
+# clean-up all CR/LF line endings (usually before patching to avoid failures after editing the same source files on
+# different systems)
+
+use strict;
+
+# change files that have been recorded in FF using DOS line endings
+my @files=`find $ARGV[0] -type f`;
+chomp @files;
+foreach my $file(@files){
+  next if $file=~/\.(jpg|eps|mcp|pdf|pgm|o|a|so|png|jpg|gz|tgz)$/;
+  next if $file=~/\.hg\//;
+  my $contents=`cat $file`;
+  my $oldcontents=$contents;
+
+  # changing line-ending conventions. all ffcs patches work from unix-style (ie no CR) files
+
+  $contents=~s/\r$//gm;
+  next if $contents eq $oldcontents;
+  print "cleancrlf: Unix line-ending for $file...\n";
+  open FILE,">$file" or die;
+  print FILE $contents;
+  close FILE;
+}
+
+# Local Variables:
+# mode:cperl
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/build/download b/build/download
new file mode 100755
index 0000000..1409dab
--- /dev/null
+++ b/build/download
@@ -0,0 +1,78 @@
+#!/bin/bash -e
+# ======================================================================
+# Written by Antoine Le Hyaric
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# http://www.ljll.math.upmc.fr/lehyaric
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++  is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+# ======================================================================
+# headeralh freefem shellxe start=21/10/10 upmc
+
+# Download a file by whatever means available
+# -------------------------------------------
+
+# $1=url
+# $2=local name
+# $3=BAD_CERT if the SSL certificate of the web server is wrong
+
+if test -x /usr/bin/wget || test -x /opt/local/bin/wget
+then
+
+    opts=
+    if test "$3" = BAD_CERT
+    then
+	opts=--no-check-certificate
+    fi
+
+    # use no-verbose to avoid mixing several wget outputs together when called concurrently in
+    # [[file:../download/getall]]
+
+    wget "$1" --output-document="$2" --no-verbose $opts
+    ret=$?
+elif test -x /usr/bin/curl
+then
+    curl -L "$1" --output "$2"
+    ret=$?
+
+elif test -x /usr/bin/GET
+then
+    GET "$1" > "$2"
+    ret=$?
+else
+    echo FF download: No way to download files from the web
+    echo FF download: Please install wget or curl or GET
+exit 1
+fi
+if test "$ret" -eq 0 
+then
+  case `file $2` in
+  *zip*) exit 0 ;;
+  *) echo " incorrect file type => remove " $3;
+     rm $3; 
+    exit  1 ;;
+  esac    
+fi
+echo "Error download $3" ;
+exit $ret
+
+# Local Variables:
+# mode:shell-script
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/build/links2files b/build/links2files
new file mode 100755
index 0000000..5457f2e
--- /dev/null
+++ b/build/links2files
@@ -0,0 +1,73 @@
+#!/usr/bin/perl
+# ======================================================================
+# Written by Antoine Le Hyaric
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# http://www.ljll.math.upmc.fr/lehyaric
+# ======================================================================
+# This file is part of Freefem++
+#
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Freefem++  is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+# ======================================================================
+# headeralh freefem perl start=7/10/10 upmc
+
+use strict;
+
+# if a file is a soft link, just convert it into a real file. I know this is dangerous if the file the link points to
+# changes, but I don't have many choices to make the MinGW compilers work (they do not understand Cygwin softlinks).
+
+traverse(<*>);
+
+sub traverse{
+  foreach my $arg(@_){
+
+    # 4/12/10: under cygwin, "find" seems to have random problems (the file system lags behind when doing many file
+    # moves in quick succession?), so just replace it with a local recursive subroutine.
+
+    if(-d $arg){
+      print "links2files: traversing $arg...\n";
+      traverse(<$arg/*>);
+      next;
+    }
+
+    # do not use readlink -f because it does not exist on Mac. Result is in $org
+    my $org;
+    my $nextorg=$arg;
+    do{
+      $org=$nextorg;
+      $nextorg=`readlink $org`;
+    }while($nextorg ne '');
+
+    if(-l $arg){
+      chomp $org;
+      if(-e $org){
+	print "links2files: $arg -> $org\n";
+	unlink $arg;
+	system "cp $org $arg";
+
+	# sometimes on Cygwin the resulting file is of size zero and not readable by anyone? And then if we try again it
+	# works fine!
+	die "$arg is of size 0" unless -s $arg;
+      }
+    }
+  }
+}
+
+# Local Variables:
+# mode:cperl
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/build/orgindex b/build/orgindex
new file mode 100755
index 0000000..c372dd5
--- /dev/null
+++ b/build/orgindex
@@ -0,0 +1,142 @@
+#!/usr/bin/perl
+# Build an index of all Emacs org-mode hyperlinks
+# ======================================================================
+# Written by Antoine Le Hyaric
+# http://www.ljll.math.upmc.fr/lehyaric
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+#
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh brief="Build an index of all Emacs org-mode hyperlinks" default=0 freefem perl start=22/10/2013 upmc written
+
+use strict;
+use warnings;
+use threads;
+use threads::shared;
+use Path::Class; # relative()
+use File::Basename; # dirname()
+use Cwd; # getcwd()
+
+# Scan all files in the FF directory tree
+
+my $pwd=getcwd();
+my %anchors;
+share %anchors;
+my @q;
+share @q;
+my $dir='';
+my @ignore=`cat .hgignore`;
+foreach my $f(`find . -type f`){push @q,$f}
+
+# core count inspired from [[file:../../../alh/perl/System.ph::nbcores]]
+sub nbcores{
+  my $n=1;
+  if(-e "/proc/cpuinfo"){$n=`grep 'processor.*:' /proc/cpuinfo|wc -l`} # linux
+  elsif(-x "/usr/sbin/sysctl"){$n=`sysctl -n hw.ncpu`} # macos
+  elsif(defined $ENV{NUMBER_OF_PROCESSORS}){$n=$ENV{NUMBER_OF_PROCESSORS}} # windows
+  return $n;
+}
+
+# start as many threads as possible
+my @threads;
+for(my $i=0;$i<nbcores();$i++){push @threads,threads->create(\&scanfiles)}
+foreach(@threads){$_->join()}
+
+sub scanfiles{
+  while(defined(my $f=pop @q)){
+
+    # relative path name is required for the index to be operational on any user machine
+    $f=~s/^\.\///;
+    chomp $f;
+    my $frel=file($f)->relative($pwd);
+
+    # files to skip because of .hgignore
+    my $found=0;
+    foreach my $r(@ignore){
+      chomp $r;
+      if($f=~/$r/){
+	$found=1;
+	last;
+      }
+    }
+    next if $found;
+
+    # files to skip for other reasons
+    next if $f=~/\.(bmp|png|jpg|eps|pdf|tar|gz|zip|tgz)$/; # not text
+    next if $f=~/\.hg\//; # not text
+    next if $f=~/examples\+\+-load\/include\//; # duplicated text
+
+    # make sure that we don't leave absolute paths in the hyperlinks because these would not work on other machines
+
+    my $cref=`cat $f`;
+    my $c=$cref;
+    while($cref=~m/\[\[file:([^:\]]+)(.*)\]\]/g){
+
+      # hyperlink potentially containing an absolute path
+      my $labs=$1;
+      if($labs=~/^~\//){
+
+	# set HOME value
+	my $labshome=$labs;
+	$labshome=~s/^~/$ENV{HOME}/;
+
+	# change absolute path to relative in file contents
+	my $lrel=file($labshome)->relative(dirname($f));
+	my $labsqm=quotemeta($labs);
+	$c=~s/\[\[file:$labsqm/\[\[file:$lrel/g;
+      }
+    }
+
+    # update file if some paths were changed
+
+    if($c ne $cref){
+      print "Changed hyperlink paths to relative in $f\n";
+      open FILE,">$f" or die;
+      print FILE $c;
+      close FILE;
+    }
+
+    # find name anchors in file contents
+
+    while($c=~m/<<([^<> ,{}]+)>>/g){$anchors{$1}.=" [[file:${frel}::$1][$frel]]"}
+  }
+}
+
+# print out all existing hyperlink anchors
+
+print "\n";
+open OUT,">index.org" or die;
+print OUT "# -*- mode:org;coding:utf-8 -*-\n";
+print OUT "# Hyperlinks into the FreeFem++ source, built with [[file:build/orgindex]]\n";
+print OUT "# (do not modify this file manually: update the source files and run [[file:build/orgindex]] again)\n";
+print OUT "\n";
+
+foreach(sort {uc($a) cmp uc($b)} keys %anchors){
+  print OUT "$_";
+  my $padding=25;
+  if(length($_)<$padding){print OUT " "x($padding-length($_))}
+  print OUT "$anchors{$_}\n";
+}
+
+close OUT;
+
+# Local Variables:
+# mode:cperl
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/config-wrapper.h b/config-wrapper.h
new file mode 100755
index 0000000..b8b65ee
--- /dev/null
+++ b/config-wrapper.h
@@ -0,0 +1,18 @@
+// Include a platform-specific configuration file
+// ----------------------------------------------
+
+// $Id$
+
+// This wrapper is necessary for platforms where the configure script
+// does not run.
+
+#ifndef CONFIG_WRAPPER_H
+#define CONFIG_WRAPPER_H
+
+#ifdef __MWERKS__
+#include "config-macos9.h"
+#else
+#include <config.h>
+#endif
+
+#endif // CONFIG_WRAPPER_H
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..f807bca
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,1984 @@
+# ------------------------------------------------------------
+
+# Antoine Le Hyaric - LJLL Paris 6 - lehyaric at ann.jussieu.fr - 13/5/04
+# $Id: configure.ac,v 1.338 2010/05/10 21:35:07 hecht Exp $
+
+# Version numbering: x.xx-pp where "pp" is the package version (when
+# the same FreeFem++ version is packaged several times). For
+# coherency, this should have the same value as the top-most package
+# number in debian/changelog.
+
+
+AC_INIT(FreeFem++,3.34-1,hecht at ann.jussieu.fr,freefem++)
+dnl : ${CFLAGS=""}
+dnl : ${CXXFLAGS=""}
+dnl : ${FCFLAGS=""}
+dnl : ${FFLAGS=""}
+
+# progg test  expact under windows 
+ff_TEST_FFPP="../src/nw/FreeFem++"
+
+AC_PREREQ(2.50) dnl for AC_LANG_CASE
+dnl AC_CONFIG_SRCDIR(src/FreeFem++-CoCoa)
+
+# Automake 1.11 is too old for check ...
+
+# ALH - 10/9/13 - FFCS needs to skip this automake version requirement when compiling on older platforms (eg cygwin or
+# last Ubuntu LTS). So we fix a low hardcoded requirement and test for higher versions when not in FFCS.
+
+AM_INIT_AUTOMAKE(1.11 dist-zip)
+
+if test "$enable_ffcs" != yes
+then
+    if test `echo $am__api_version|awk '{if($1>1.13)print "ok";}'` != ok
+    then
+	AC_MSG_ERROR([Automake version needs to be 1.13 or later to enable "make check"])
+    fi
+fi
+
+AC_CONFIG_HEADERS(config.h)
+AC_PROG_MAKE_SET
+dnl AM_COLOR_TESTS=always
+AC_PROG_RANLIB
+
+ff_where_lib_conf=examples++-load/WHERE_LIBRARY-config
+dnl search of associad software
+m4_define([AC_FF_ADDWHERELIB],
+  [	if test -z "$ff_where_lib_conf_$1" ; then
+	    echo "$1 LD $2"  >>$ff_where_lib_conf
+	    test -n "$3" && echo "$1 INCLUDE $3 "  >>$ff_where_lib_conf
+            ff_where_lib_conf_$1=1
+	    AC_MSG_NOTICE([    ++ add $1 : $2 $3 in  $ff_where_lib_conf "])
+	else
+	    AC_MSG_NOTICE([    -- do not add $1 : $2 $3 in  $ff_where_lib_conf "])
+        fi
+]) dnl
+m4_define([AC_FF_WHERELIB],
+    [  	if test -z "$ff_where_lib_conf_$1" ; then
+        AC_MSG_CHECKING(check $1)
+	ff_save_libs=$LIBS
+	LIBS="$LIBS $2 $4"
+	AC_LINK_IFELSE([AC_LANG_PROGRAM([m4_if($3,,,[#include <$3>])],[])], [ff_WHERE=yes],[ff_WHERE=no])
+	if test "$ff_WHERE" = "yes" ; then
+	    echo "$1 LD $2"  >>$ff_where_lib_conf
+	    ff_WHERE_INC=`AS_DIRNAME(["$3"])`
+	    case "$ff_WHERE_INC" in 
+		/*) echo "$1 INCLUDE -I$ff_WHERE_INC"  >>$ff_where_lib_conf ;;
+	    esac
+	fi
+	AC_MSG_RESULT($ff_WHERE)
+
+        ff_where_lib_conf_$1=1
+	LIBS=$ff_save_libs
+	fi
+    ])dnl end m4_define AC_FF_WHERELIB
+
+
+ff_HOSTARCH_pastix=
+echo "#  Build with freefem++ with ./configure " `date`  >$ff_where_lib_conf
+# To allow anonymous CVS version to contain a "./configure" and
+# Makefiles
+
+AM_MAINTAINER_MODE
+
+echo >config_LIB_INFO
+
+# Necessary compilers
+
+AC_PROG_CC
+AC_PROG_CXX
+AC_LANG(C++)
+if test `uname` != Darwin; then
+ ff_ldeg="-Wl,--end-group"
+ ff_ldbg="-Wl,--start-group"
+fi
+
+
+
+
+
+AC_CHECK_PROG(ff_m4,m4,yes,no)
+AC_CHECK_PROG(ff_bison,bison,yes,no)
+dnl AC_CHECK_PROG(ff_cmake,cmake,yes,no)
+AC_CHECK_PROG(ff_patch,patch,yes,no)
+case "$ff_m4 $ff_bison $ff_patch "  in
+*no*)
+    AC_MSG_NOTICE([ to install missing package  under debian or ubuntu, try: sudo apt-get install m4 bison patch cmake ])
+    AC_MSG_ERROR([ Sorry missing  m4,bison,patch command !]);;
+esac
+
+
+if test -z "$CXX"; then
+  AC_MSG_NOTICE( [ fatal error : c++ compiler ! ] );
+  AC_MSG_ERROR([ Sorry no c++ compiler !])
+fi
+
+AC_COMPUTE_INT(ff_size_long,[sizeof(long)])
+AC_COMPUTE_INT(ff_size_int,[sizeof(int)])
+AC_COMPUTE_INT(ff_size_ptr,[sizeof(int*)])
+
+AC_SUBST(SIZEOF_LONG,$ff_size_long)
+AC_SUBST(SIZEOF_INT,$ff_size_int)
+AC_SUBST(SIZEOF_PTR,$ff_size_ptr)
+if test "$ff_size_ptr" -eq 4  ;then
+ AC_SUBST(SIZEOF_PTRINBIT,32)
+elif test  "$ff_size_ptr" -eq 8  ;then
+ AC_SUBST(SIZEOF_PTRINBIT,64)
+else
+  AC_MSG_NOTICE( [ fatal error : sizeof pointer $ff_size_ptr !  or no c++ compiler: $CXX] );
+  AC_MSG_ERROR([ Sorry  sizeof c++ pointer $ff_size_ptr are not  4 or 8 ])
+fi
+
+# FFCS - build the code for FreeFem++-cs
+AC_ARG_ENABLE(ffcs,AC_HELP_STRING([--enable-ffcs],[build FreeFem++ for use by FreeFem++-cs]))
+if test "$enable_ffcs" = yes
+then
+	AC_DEFINE_UNQUOTED(ENABLE_FFCS,$enable_ffcs,[build FreeFem++ for use by FreeFem++-cs])
+else
+	enable_ffcs=no
+fi
+AC_SUBST(ENABLE_FFCS,"$enable_ffcs")
+AM_CONDITIONAL([ENABLE_FFCS],[test $enable_ffcs = yes])
+
+# dur dur car sous MacOsX le fortran n'est pas standard.
+ff_AR="ar"
+ff_ARFLAGS="rv"
+ff_RANLIB="ranlib"
+AC_ARG_ENABLE(fortran,AC_HELP_STRING([--disable-fortran],[No Fortran compiler available ( ARPACK need it)]))
+
+ff_g2c_lib="";
+if test "$enable_fortran" != no
+then
+
+    # ALH-FFCS-2/3/10: add gfortran-mp-4.4 for MacPorts on MacOS 10.6
+    AC_PROG_FC(gfortran  f90  xlf90 g95 gfortran-mp-4.4)
+    AC_PROG_F77(gfortran f90 xlf xlf90 g95 f77 fort77 "$FC" gfortran-mp-4.4)
+
+#	if test -n "$F77"
+#	then
+    ff_flibs=""
+        # modif FH
+    AC_F77_LIBRARY_LDFLAGS
+    dnl	AC_F77_WRAPPERS
+	# correct pb of double def under macos
+    case $F77 in
+	 *fort77)
+	    if test -z "$FLIBS" ; then
+#             FLIBS=`fort77 -v  a.out  2>&1|awk '/a.out/ && /fort77/  { print $(NF-2),$(NF-1)}'`
+#  FH to remove " "
+		FLIBS=`fort77 -v  a.out  2>&1|awk '/a.out/ && /fort77/  { print "echo",$(NF-2),$(NF-1)}'|sh`
+
+		AC_MSG_WARN([  fort77   FLIBS :  $FLIBS ])
+	    fi
+	    ;;
+	*g77)
+	    for i in $FLIBS; do
+		case $i in
+# save last directory of the list
+		    -L*)
+			d=`expr $i : '-L\(.*\)'`;
+			echo " try $d "
+			if test -e "$d/libg2c.so" ; then
+			    ff_flibs="$d/libg2c.so"
+			elif test -e "$d/libg2c.dylib" ; then
+			    ff_flibs="$d/libg2c.dylib"
+			elif test -e "$d/libg2c.a" ; then
+			    ff_flibs="$d/libg2c.a"
+			elif test  -e $d/libg2c.so -o	-e $d/libg2c.a ; then
+			    ff_flibs="$i"
+			fi;;
+		esac
+	    done
+	    if test -e "$ff_flibs"  ;then
+		FLIBS="$ff_flibs"
+	    else
+		FLIBS="$ff_flibs -lg2c"
+	    fi
+	    AC_MSG_WARN([  get dir of -lg2c  FLIBS :  $FLIBS ])
+	    ;;
+# add FH sep 2006 / modif  2009
+        *gfortran)
+            for i in $FLIBS; do
+		case $i in
+		    -L*)
+			d=`expr $i : '-L\(.*\)'`;
+			if test -e "$d/libgfortran.so" ; then
+			    ff_flibs="$d/libgfortran.so"
+			elif test -e "$d/libgfortran.dylib" ; then
+			    ff_flibs="$d/libgfortran.dylib"
+			elif test -e "$d/libgfortran.a" ; then
+			    ff_flibs="$d/libgfortran.a"
+			elif test -e $d/libgfortran.so -o -e $d/libgfortran.a -o -e $d/libgfortran.dylib ; then
+			    ff_flibs="$i"
+			fi;;
+		esac
+            done
+	    if test -e "$ff_flibs"  ;then
+		FLIBS="$ff_flibs"
+	    else
+		FLIBS="$ff_flibs -lgfortran"
+	    fi
+            AC_MSG_WARN([  get dir of -lgfortran  FLIBS :  $FLIBS ])
+            ;;
+    esac
+    AC_ARG_WITH(flib,[  --with-flib= the fortran library ])
+#  correct FH sep 2006 -o -> -a
+    if test "$with_flib" != no -a -n  "$with_flib"
+    then
+	ff_g2c_lib="$with_flib"
+	FLIBS="$with_flib"
+    fi
+# add FH oct 2007 for download f2c
+    if test -z "$F77"  ; then
+	ff_f77=`pwd`/download/bin/fort77
+	ff_flibs=`pwd`/download/lib/libf2c.a
+	if test -x $ff_f77  -a -f $ff_flibs ; then
+	    AC_MSG_WARN([ no fortran, but find download f2c/fort]);
+	    F77=$ff_f77
+	    FLIBS=$ff_flibs
+	else
+	    AC_MSG_NOTICE( [ fatal error : no fortran ] );
+	    AC_MSG_NOTICE( [add --disable-fortran  ] );
+	    AC_MSG_NOTICE( [or try to compile f2c in directory download/f2c  ] );
+	    AC_MSG_NOTICE( [  just do:  make install ] );
+	    AC_MSG_ERROR([ Fatal error No Fortran compiler . ],1);
+	fi
+    fi
+#  check if the FLIBS is correct
+    ff_libs="$LIBS"
+    LIBS="$ff_libs $FLIBS"
+    AC_TRY_LINK_FUNC(exit,ff_err=,ff_err=ok);
+    if test "$ff_err" = "ok" ; then  AC_MSG_ERROR([ Fatal FLIBS: $FLIBS is incorrect. ],1); fi
+    LIBS="$ff_libs"
+    echo "F77 LD $ff_libs" >config_LIB_INFO
+
+    AC_MSG_CHECKING([ Size of fortran 77 integer ])
+
+
+
+##   AC_LANG(fortran);
+    AC_LANG_PUSH([Fortran 77])
+    AC_RUN_IFELSE([AC_LANG_SOURCE([[
+		program test
+		integer  p,i
+		p=1024*1024
+		i= p*p
+		open(7,file="conftest.out")
+		if (i>0) then
+		    write(7,*) 8
+		else
+         write(7,*) 4
+	 endif
+	 close(7)
+	 end
+ ]])] ,ff_f77intsize=`cat conftest.out`,ff_f77intsize=4,ff_f77intsize=4)
+## AC_LANG(C++)
+    AC_LANG_POP([Fortran 77])
+    AC_MSG_RESULT($ff_f77intsize)
+    AC_F77_WRAPPERS
+
+    ff_cfagsf77=""
+    case $ac_cv_f77_mangling in
+#  "lower case, no underscore, no extra underscore")
+#  "lower case, no underscore, extra underscore")
+# ;;
+	"lower case, underscore, no extra underscore") 	ff_cfagsf77="-DAdd_";;
+	"lower case, underscore, extra underscore")       	ff_cfagsf77="-DAdd__ -Df77IsF2C";;
+	"upper case, no underscore, no extra underscore")     ff_cfagsf77="-DUPPER";;
+	"upper case, no underscore, extra underscore")        ff_cfagsf77="-DUPPER -DAdd__";;
+	"upper case, underscore, no extra underscore")      ff_cfagsf77="-DUPPER -DAdd_";;
+	"upper case, underscore, extra underscore")           ff_cfagsf77="-DUPPER -DAdd__";;
+	*) ;;
+    esac
+    AC_SUBST(CFLAGSF77,$ff_cfagsf77)
+    if test $ff_f77intsize -ne  4
+    then
+	AC_MSG_ERROR([ Fatal Error: Your fortran 77  compiler have by not 4 bytes integer ( $ff_f77intsize bytes) ],1);
+    fi
+    test -f /mingw/bin/libpthread-2.dll && ff_pthread_dll=/mingw/bin/libpthread-2.dll ; \
+    AC_FF_ADDWHERELIB(f77,$FLIBS,$ff_cfagsf77 $ff_pthread_dll)
+    AC_FF_ADDWHERELIB(fc,$FLIBS,$ff_cfagsf77 $ff_pthread_dll)
+fi
+
+#  fin test FORTRAN ..........
+# ----------------------------
+
+AC_ARG_ENABLE(c,AC_HELP_STRING([--disable-c],[No C compiler available (C BLAS need it)]))
+if test "$enable_c" != no
+then
+    AC_PROG_CC
+    AM_PROG_CC_C_O
+else
+
+	# We need to define this otherwise ./configure crashes with
+	# the message "configure: error: conditional "am__fastdepCC"
+	# was never defined".
+
+    am__fastdepCC_TRUE=
+    am__fastdepCC_FALSE='#'
+fi
+
+AM_PROG_LEX
+AC_PROG_YACC
+AC_LANG(C++)
+
+
+# Some useful libraries
+
+AC_CHECK_LIB(pthread,pthread_create,ff_pthread="-lpthread",ff_pthread="")
+AC_CHECK_LIB(iomp5,omp_get_wtime,ff_iomp5="-liomp5",ff_iomp5="")
+
+if test -n "$ff_pthread"  ; then
+    AC_FF_ADDWHERELIB(pthread,$ff_pthread,)
+fi
+
+# Necessary absolute pathname for local directory when some libraries
+# are used from several different locations (for instance locally in
+# configure.ac and in a subdir).
+curdir=`pwd`
+
+# Configure options
+# -----------------
+
+echo $ac_configure_args > configure.param
+# by default the suffix of the  .so lib file is .so
+#      it is .dll   under windows
+#      it is .dylib under macos X
+ff_suffix_dylib="so";
+# Checking wether we can produce a MacIntosh-specific version
+# -----------------------------------------------------------
+
+AC_MSG_CHECKING(wether we are on a MacIntosh)
+ff_mac=no
+if test `uname` = Darwin;
+then
+	ff_HOSTARCH_pastix=i686_mac
+	ff_suffix_dylib="dylib"
+	ff_mac=yes
+AC_DEFINE_UNQUOTED(FF_PREFIX_DIR_APPLE,"/Applications/FreeFem++.app/Contents/",FreeFem prefix  dir)
+fi
+AC_MSG_RESULT($ff_mac)
+
+AC_MSG_CHECKING(wether we are on  SunOS)
+ff_sunos=no
+if test `uname -s` = SunOS;
+then
+	ff_sunos=yes
+fi
+AC_MSG_RESULT($ff_sunos)
+
+# Checking wether we can produce a Microsoft Windows-specific version
+# -------------------------------------------------------------------
+
+AC_ARG_ENABLE(cygwindll,
+	[  --enable-cygwindll	Forces the use of the Cygwin DLL (not recommended)])
+
+AC_MSG_CHECKING(wether we are on Microsoft Windows)
+ff_uname=`uname`
+#  flag to build window 32   version   ff_mingw = yes
+ff_mingw=no
+case $ff_uname in
+    CYGWIN*)
+
+    	# FFCS - 17/1/12 - -mno-cygwin is not recognised by the latest version of mingw32
+	if test $enable_ffcs = no
+	then
+	    ff_nocygwin=-mno-cygwin
+	fi
+
+	AC_SUBST(GCCNOCYGWIN,$ff_nocygwin);;
+    MINGW*)
+        enable_cygwindll=no;;
+esac
+case $ff_uname in
+CYGWIN*|MINGW*)
+
+	ff_suffix_dylib="dll";
+        ff_win32=yes;
+
+	# FFCS - 8/3/12 - remove -D_MSC_VER under MinGW64 because it forces system calls to be compiled into any object
+	# (which creates thousands of duplicate definitions for sytem calls like time()).
+
+	if test $enable_ffcs = yes
+	then
+	    AC_SUBST(FFMETIS_CFLAGS,"-D__VC__")
+	else
+	    AC_SUBST(FFMETIS_CFLAGS,"-D__VC__ -D_MSC_VER")
+	fi
+
+	# We need Mingw to avoid Cygwin's extra DLLs
+	if test "$enable_cygwindll" != yes
+	then
+# 	        CHECK_COMPILE_FLAG(C++,-mwindows,CXXFLAGS)
+	        ff_glut_ok=yes
+
+		# FFCS: on Windows, FF crashes when compiling GL/glut.h and the option "--disable-opengl" is not
+		# operational because ff_glut_ok is forced to yes here.
+		if test $enable_ffcs = yes
+		then
+	            ff_glut_ok=no
+		    enable_opengl=no
+		fi
+
+                ff_mingw=yes
+                enable_cygwindll=no;
+		ff_pthread="-mthreads"
+
+		# FFCS does not use the Cygwin MinGW compilers any more
+		if test $enable_ffcs = no
+		then
+		    CXXFLAGS="$CXXFLAGS $ff_nocygwin -I/usr/include/mingw"
+		    FFLAGS="$FFLAGS $ff_nocygwin"
+		    CFLAGS="$CFLAGS $ff_nocygwin -I/usr/include/mingw"
+                    AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a;])],[],
+			[ff_nocygwin="";
+			    AC_MSG_NOTICE([Sorry $ff_nocygwin optio is wrong try whitout , but try with gcc-3.3])
+			    ])
+		    CXXFLAGS="$CXXFLAGS $ff_nocygwin -I/usr/include/mingw"
+		    FFLAGS="$FFLAGS $ff_nocygwin"
+		    CFLAGS="$CFLAGS $ff_nocygwin -I/usr/include/mingw"
+		    CNOFLAGS="$CNOFLAGS $ff_nocygwin -I/usr/include/mingw"
+		fi
+
+		LIBS="$LIBS $ff_nocygwin -mthreads -lws2_32 -lcomdlg32"
+		LIBSNOCONSOLE="-mwindows"
+
+		# FFCS uses a specific compiler, so we specify its libraries explicitely
+		if test $enable_ffcs = no
+		then
+		    test -z "$MPIRUN" &&  MPIRUN=`which mpiexe.exe`
+		    if test "$enable_fortran" != no  -o  "$with_flib" != no ;   then
+			case "$F77" in
+	 		    *gfortran) FLIBS="$ff_nocygwin -lgfortran";;
+	 		    *g77) FLIBS="$ff_nocygwin -lg2c";;
+			    *)   AC_MSG_ERROR([ Sorry no known FLIBS with this $F77  !]) ;;
+			esac
+		    fi
+		fi
+
+                ff_glutname="glut32"
+		#  check abort a existing function just to find in glut32.dll exist in the path
+		#  because glutInit is not the real symbol on win32 dur dur FH !!!!!!!!!
+		AC_CHECK_LIB(glut32,abort,ff_glut="-l$ff_glutname -mthreads -lglu32 -lopengl32",ff_glut="")
+		if test -z "$ff_glut" ; then
+                ff_glutname="freeglut"
+		AC_CHECK_LIB(freeglut,abort,ff_glut="-l$ff_glutname -mthreads -lglu32 -lopengl32",ff_glut_ok=no)
+                fi
+         	# Resources for FreeFem++-cs in Microsoft Windows format
+	        AC_SUBST(FFGLUTNAME,$ff_glutname)
+	        AC_SUBST(WINDRESOBJ,windres.o)
+	        AC_SUBST(LIBSNOCONSOLE,$LIBSNOCONSOLE)
+                AC_SUBST(WIN32DLLTARGET,win32-dll-target)
+		ff_TEST_FFPP="../src/bin-win32/FreeFem++.exe"
+                AC_DEFINE(PURE_WIN32,1,A pure windows applications no cygwin dll)
+		ff_dynload=yes
+	fi
+
+
+	;;
+*)ff_win32=no;;
+esac
+AC_MSG_RESULT($ff_win32)
+
+if test "$ff_win32" = no
+then
+	enable_cygwindll=no
+fi
+
+# FreeFem++-specific version information
+# --------------------------------------
+
+# Version numbering, converted to a floating point value
+ff_numver="`echo $VERSION|sed 's/-\(.*\)/+\1.0*0.000001/'`"
+AC_DEFINE_UNQUOTED(VersionFreeFempp,$ff_numver,FreeFem++ version as a float)
+
+# Since src/fflib/strversionnumber.cpp is recreated at each build, this
+# date is only useful for config-version.h
+
+test "$prefix" = NONE && prefix="$ac_default_prefix"
+ff_prefix_dir="${prefix}/lib/ff++/$VERSION"
+AC_MSG_CHECKING(prefix dir freefem++  )
+AC_MSG_RESULT($ff_prefix_dir)
+
+FF_DATE=`date`
+AC_DEFINE_UNQUOTED(VersionFreeFemDate,"$FF_DATE",FreeFem++ build date)
+AC_DEFINE_UNQUOTED(FF_PREFIX_DIR,"${ff_prefix_dir}",FreeFem prefix  dir)
+AC_SUBST(ff_prefix_dir,$ff_prefix_dir)
+
+# Separate configuration header file for version information, included
+# in config-macos9.h
+
+cat << EOF > config-version.h
+/* FreeFem++ version information for MacOS 9 configuration */
+/* File generated by configure.ac */
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "$PACKAGE_STRING"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+
+/* Version number of package */
+#define VERSION "$VERSION"
+
+/* FreeFem++ build date */
+#define VersionFreeFemDate "$FF_DATE"
+
+/* FreeFem++ version as a float */
+#define VersionFreeFempp ($ff_numver)
+EOF
+
+# Checking wether to produce a debug version
+# ------------------------------------------
+
+# Generic or hardware-dependant optimization
+m4_include(acmacros.m4)
+m4_include(acoptim.m4)
+m4_include(ax_lib_hdf5.m4)
+m4_include(ax_lib_gsl.m4)
+# Checking c++11 for schwarz interface of P. Jolivet ...
+
+CHECK_COMPILE_FLAG(C++,[-std=c++11],CXXFLAGS,ff_cxx11)
+dnl CXXFLAGS="$CXX11FLAGS $CXXFLAGS"
+dnl ff_cxx11="no"
+dnl if test -n "$CXX11FLAGS" ; then ff_cxx11="yes" ; fi
+AC_SUBST(WITH_CXX11,$ff_cxx11)
+#end Checking  c++11
+# ------------------------------
+# compilation flags of FreeFem++
+# ------------------------------
+#  -DDRAWING  bamg active some drawing facility in bamg (inquire mesh)
+#  -DBAMG_LONG_LONG active the use of  long long in bamg
+#  -DDEBUG active the  checking in bamg
+#  -DNCHECKPTR remove check pointer facility
+#  -DCHECK_KN active subscripting of some array
+#  -DWITHCHECK of the dynamic type ckecking of the langague (very slow)
+#  -DEIGENVALUE  to compile the eigen value part
+#  ------------------------------------------------
+
+# FreeFrem++-specific optimizations -fpascal-strings
+
+
+if test "$enable_debug" = yes;
+then
+	CXXFLAGS="$CXXFLAGS  -DBAMG_LONG_LONG -DCHECK_KN"
+	if test "$ff_mac" = yes;
+	then
+		CXXFLAGS="$CXXFLAGS -fno-inline  -fexceptions"
+	fi
+else
+	CXXFLAGS="$CXXFLAGS -DBAMG_LONG_LONG  -DNCHECKPTR"
+	if test "$ff_mac" = yes;
+	then
+		CXXFLAGS="$CXXFLAGS "
+	fi
+fi
+
+#whether or not to add a suffix to the package name
+#--------------------------------------------------
+
+AC_ARG_WITH(suffix,[  --with-suffix=[G3/G4/G4,P4,..] or --without-suffix (default no suffix to package name)])
+
+AC_MSG_CHECKING(suffix to add to package name)
+ff_suffix=
+if test "$with_suffix" = yes -o "$with_suffix" = no -o "$with_suffix" = ""
+then
+  AC_MSG_RESULT(none)
+else
+  ff_suffix="-$with_suffix"
+  AC_MSG_RESULT($ff_suffix)
+fi
+AC_SUBST(ADD_PACKAGE_NAME,$ff_suffix)
+
+
+
+
+# Checking that OpenGL is accessible
+# ----------------------------------
+
+ff_gl_ok=no
+ff_glx_ok=no
+
+ff_libs="$LIBS"
+AC_ARG_WITH(flib,[  --with-flib= the fortran library ])
+AC_ARG_ENABLE([opengl],AS_HELP_STRING([--enable-opengl],
+                                      [Enable/disable support for OpenGL]))
+
+# echo "  .... LIBS = $LIBS .... "
+if test x$enable_opengl != xno; then
+# GL libraries seem to depend on some dlopen capabilities
+if test "$enable_static" != yes -a "$ff_glut_ok" != yes
+then
+	# If we cannot find gl.h, no OpenGL version can be produced
+    AC_CHECK_HEADERS(OpenGL/gl.h,
+        ff_gl_ok=yes
+        ,
+        ff_gl_ok=no
+        )
+
+
+    if test "$ff_gl_ok" = no
+    then
+	AC_CHECK_HEADERS(GL/gl.h,
+	    ff_gl_ok=yes
+	    ,
+	    ff_gl_ok=no
+	    )
+    fi
+    AC_CHECK_HEADERS(GLUT/glut.h,
+        ff_glut_ok=yes,
+        ff_glut_ok=no)
+
+    if test "$ff_glut_ok" = no
+    then
+	AC_CHECK_HEADERS(GL/glut.h,
+	    ff_glut_ok=yes,
+	    ff_glut_ok=no)
+    fi
+
+# GLUT .....
+    if test "$ff_glut_ok" =	yes
+    then
+	for glut in \
+	    "-framework GLUT -framework OpenGL -framework Cocoa" \
+	    "-lglut -lGLU -lGL"
+	do
+	    ff_glut="$glut"
+	    ff_libs1="$LIBS"
+     	    LIBS="$LIBS $ff_glut"
+	    AC_TRY_LINK_FUNC(glutInit,
+		ff_glut_ok=yes
+	        LIBS="$ff_libs1"
+		break,
+		ff_glut_ok=next);
+	    LIBS="$ff_libs1"
+	done
+    fi
+
+
+fi
+fi
+AC_SUBST(LIBSPTHREAD,$ff_pthread)
+
+# ALH - 16/9/13 - at the moment the requirements for medit (glut) are not compatible with FFCS so medit is
+# only compiled with FF.
+
+if test $enable_ffcs = no
+then
+    if test "$ff_glut_ok" = yes
+    then
+	AC_SUBST(LIBSGLUT,$ff_glut)
+	if test -n  "$ff_pthread" ; then
+	    ff_ffglutprog="ffglut${EXEEXT}"
+	    AC_DEFINE_UNQUOTED(PROG_FFGLUT,"$ff_ffglutprog", the ffglut application for the new graphics )
+	fi
+	ff_meditprog="ffmedit${EXEEXT}"
+    fi
+fi
+
+AC_ARG_WITH(suffix,[  --with-suffix=[G3/G4/G4,P4,..] or --without-suffix (default no suffix package name)])
+if test "$with_suffix" = yes
+then
+  with_suffix=""
+elif test "$with_suffix" = no -o -z "$with_suffix"
+then
+  with_suffix=""
+else
+  with_suffix="-$with_suffix"
+fi
+  AC_MSG_CHECKING(add suffix $with_suffix )
+  AC_SUBST(ADD_PACKAGE_NAME,$with_suffix)
+  AC_MSG_RESULT(yes)
+
+
+# Checking wether we can produce a parallel version
+# -------------------------------------------------
+
+if test $enable_ffcs = no
+then
+    # FF case
+    m4_include(acmpi.m4)
+else
+    # FFCS - use the same MPI configuration choices as FFCS
+    ff_mpi=yes
+    AC_SUBST(MPICXX,$MPICXX)
+    AC_SUBST(MPICC,$MPICC)
+    AC_SUBST(MPIF77,$MPIF77)
+    AC_SUBST(MPIFC,$MPIFC)
+    AC_SUBST(MPIPROG,"FreeFem++-mpi${EXEEXT}")
+    AC_SUBST(MPI_INCLUDE,"-I $MPI_INC_DIR")
+    AC_SUBST(MPI_INC_DIR,$MPI_INC_DIR)
+    AC_SUBST(MPI_LIB_DIRS,"")
+    AC_SUBST(MPI_LIB,$MPI_LIB)
+    AC_SUBST(MPI_LIBC,"")
+    AC_SUBST(MPI_LIBFC,"")
+
+    # Extra MPI-dependant configuration options that are set by FF during MPI configuration. FFCS - 25/2/13 - Fred
+    # noticed that if PASTIX_HOSTARCH stays blank, pastix compilation breaks. At least i686_pc_linux and i686_mac are
+    # required by pastix on the corresponding platforms.
+
+    if test"$ff_HOSTARCH_pastix" = ""
+    then
+	ff_HOSTARCH_pastix=i686_pc_linux
+    fi
+    AC_SUBST(PASTIX_HOSTARCH,$ff_HOSTARCH_pastix)
+
+    # these values should not be empty otherwise examples++-load/ff-get-dep will think that they are not defined
+    AC_FF_ADDWHERELIB(mpi,-DDUMMY,-I$MPI_INC_DIR)
+
+    # mpifc and mpif77 libraries should always be specified because FF never calls the Fortran MPI compiler. It always
+    # uses mpicxx in [[file:examples++-load/ff-c++]]. The resulting Fortran libraries (eg Mumps) would compile even
+    # without the proper Fortran libs, but they would not load properly.
+
+    # under Win32, libmpi_f77.a is not the right name and FFCS mingw/mpicxx adds the right libraries by itself
+
+    # With mpich2 Debian wheezy 32 bits, libmpi_f77.a is not available (request from Cico, 14/10/13)
+
+    if test -f /usr/lib/openmpi/lib/libmpi_f77.a
+    then
+        AC_FF_ADDWHERELIB(mpifc,-lmpi_f77,)
+    	AC_FF_ADDWHERELIB(mpif77,-lmpi_f77,)
+    else
+        AC_FF_ADDWHERELIB(mpifc,-DDUMMY,)
+    	AC_FF_ADDWHERELIB(mpif77,-DDUMMY,)
+    fi
+
+    # FFCS - MPI_DOUBLE_COMPLEX kept from original FF configure script
+    AC_MSG_CHECKING( MPI_DOUBLE_COMPLEX)
+    AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE([
+#include <mpi.h>
+		MPI_Datatype xxxx=MPI_DOUBLE_COMPLEX;
+		])],
+    ff_mpi_double_complex=yes,
+    ff_mpi_double_complex=no)
+    AC_MSG_RESULT($ff_mpi_double_complex)
+    if test "$ff_mpi_double_complex" = yes  ; then
+	AC_DEFINE(HAVE_MPI_DOUBLE_COMPLEX,1, mpi_double_complex)
+    fi
+fi
+
+# FFCS needs to change some of the FF makefiles to compile without MPI on MacOS
+AM_CONDITIONAL([FFCS_MPIOK],[test $ff_mpi = yes])
+
+# Looking for useful configuration utilities
+# ------------------------------------------
+
+AC_ARG_ENABLE(download,AC_HELP_STRING([--enable-download],[Download missing libraries (BLAS,ARPACK,UMFPACK,...)]))
+## PETSc
+AC_ARG_WITH(petsc,[  --with-petsc= /usr/local/petsc   --without-petsc  ])
+# /usr/local/petsc/conf/petscvariables 
+ff_petsc_ok=no
+## echo --$with_petsc--
+if test "$with_petsc" != no -a  $ff_mpi = yes; then
+    ff_petsc=""
+    for d in "$with_petsc" /usr /usr/local /opt/usr  /opt/local 
+    do
+	if test -f ; then
+	    ffconfpetsc="$d"		
+        elif test -f "$d/petsc/petscvariables"  ; then 
+  	    ffconfpetsc="$d/petsc/petscvariables"
+	elif test -f  "$d/petsc-conf/petscvariables"   ; then
+  	    ffconfpetsc="$d/petsc-conf/petscvariables" 
+	else
+	    ffconfpetsc=""
+	fi
+	if test -f "$ffconfpetsc" ; then 
+	    if test  "$ff_petsc_ok" = no ; then
+		PETSC_MPIRUN=`awk -F'=' '"MPIEXEC "==$1 {print $2}' $ff_petsc`
+		cmp -s  $PETSC_MPIRUN $MPIRUN
+		if test $?  -eq 0 ; then 
+		    PETSC_WITH_EXTERNAL_LIB=`awk -F'=' '"PETSC_WITH_EXTERNAL_LIB "==$1 {print $2}' $ff_petsc`
+		    PETSC_CC_INCLUDES=`awk -F'=' '"PETSC_CC_INCLUDES "==$1 {print $2}' $ff_petsc`
+		    if test -n "$PETSC_WITH_EXTERNAL_LIB"; then 
+			ff_petsc_ok=yes;
+			AC_FF_ADDWHERELIB(petsc,$PETSC_WITH_EXTERNAL_LIB,$PETSC_CC_INCLUDES)
+		    fi
+		fi
+	    fi
+	fi
+    done
+fi
+
+if test "$ff_petsc_ok" != no ;   then
+    AC_MSG_NOTICE([ with petsc  $ff_petsc])
+else
+    AC_MSG_NOTICE([ without petsc ***** ])
+fi
+
+
+
+#replacing wget with another command
+ff_wget_command="wget --no-check-certificate"
+ff_wget=no
+
+AC_ARG_WITH(wget,
+	[  --with-wget=command	Replace "wget" with another command. Implies --enable-download],
+	   enable_download=yes
+	   ff_wget=yes
+	   ff_wget_command="${withval}")
+
+ff_mkl_libpath=yes
+AC_ARG_WITH(mkl,
+	[  --with-mkl= the  MKL LIBPATH : (ie. /opt/intel/mkl/RR.r.y.xxx/lib/<arch>)],
+	   ff_mkl_libpath="${withval}")
+
+# if enabling downloads find wget or curl to do download
+# ------------------------------------------------------
+
+if test  "$ff_wget" =  no
+then
+	ff_wget=""
+	AC_CHECK_PROG(ff_wget,wget --no-check-certificate,yes,no)
+fi
+if test  "$ff_wget" = no
+then
+        ff_wget_command="curl --fail -O "
+  	ff_curl=""
+	AC_CHECK_PROG(ff_curl,curl -O,yes,no)
+	ff_wget="$ff_curl"
+fi
+
+# for automatique compilation of
+# lib in download
+if test  "$ff_wget" != yes  -a "$enable_download"  = "yes"  ; then
+  enable_download=no
+  AC_MSG_ERROR([   enable-download and no wget or curl. ],1);
+fi
+if test "$enable_download"  = "yes" ; then
+DOWNLOADCOMPILE="compile-pkg install-other"
+else
+DOWNLOADCOMPILE=
+fi
+
+AC_SUBST(WGET,$ff_wget_command)
+AC_SUBST(DOWNLOADCOMPILE,$DOWNLOADCOMPILE)
+
+#  modif FH -----
+#  -- looking for cadna
+#  the round-off error propagation
+# the web site http://www-anp.lip6.fr/cadna/
+#  --------------------
+AC_ARG_WITH(cadna,[  --with-cadna= cadna library --without-cadna  ])
+if test "$with_cadna" != no -o -n  "$with_cadna"
+    then
+    ff_cadna="$with_cadna"
+fi
+ff_cadna_ok=no
+if test "$with_cadna" != no
+    then
+    ff_libs_old="$LIBS"
+    ff_ldflags_old="$LDFLAGS"
+    ff_cadna_dir="${curdir}/download/cadna"
+    LDFLAGS="$LDFLAGS -L$ff_cadna_dir"
+    AC_CHECK_LIB(cadnafree,arit_zero,
+	ff_cadna_ok=yes)
+    AC_CHECK_HEADERS(${ff_cadna_dir}/cadnafree.h,
+	ff_cadna_h=yes, ff_cadna_h=no)
+
+    LIBS="$ff_libs_old"
+    LDFLAGS="$ff_ldflags_old"
+
+    if test "$ff_cadna_ok" = yes  -a "$ff_cadna_h" = yes
+	then
+	AC_DEFINE(HAVE_CADNA,1, freecadna is use to evalute the round-off error propagation )
+	CPPFLAGS="$CPPFLAGS -I$ff_cadna_dir"
+	LIBS=" -L$ff_cadna_dir -lcadnafree $ff_libs_old"
+    else
+	AC_MSG_NOTICE([ without cadna ***** ])
+    fi
+else
+    AC_MSG_NOTICE([ without cadna ***** ])
+fi
+
+# Looking for FFTW
+# ----------------
+
+# ALH - 18/9/13 - deactivates FFTW detection for testing purposes
+
+AC_ARG_ENABLE(system_fftw,AC_HELP_STRING([--disable-system-fftw],[Disable the automatic detection of FFTW]))
+if test "$enable_system_fftw" != no
+then
+
+    # ALH - 4/9/13 - avoid recompiling FFTW if a copy was found on the system (request from Helmut Jarausch, 1/8/13)
+
+    AC_CHECK_LIB(fftw3,fftw_execute,ff_fftw_ok=yes)
+    AC_CHECK_HEADERS(fftw3.h,ff_fftw_h=yes, ff_fftw_h=no)
+fi
+
+if test "$ff_fftw_ok" = yes -a "$ff_fftw_h" = yes
+then
+    AC_FF_ADDWHERELIB(fftw3,-lfftw3,)
+    fftw_download=
+else
+    if test "$enable_download" = yes
+    then
+	ff_DOWNLOAD_FFTW=fftw
+    fi
+fi
+
+# used in [[file:download/fftw/Makefile.am::DOWNLOAD_FFTW]]
+
+AC_SUBST(DOWNLOAD_FFTW,$ff_DOWNLOAD_FFTW)
+
+dnl ---------------------------
+dnl   Looking for the tetgen
+dnl --------------------------
+AC_CHECK_LIB(tet,tetrahedralize,ff_fftet_ok=yes)
+AC_CHECK_HEADERS(tetgen.h,ff_tet_h=yes, ff_tet_h=no)
+if test "$ff_tet_ok" = yes -a "$ff_tet_h" = yes
+then
+    AC_FF_ADDWHERELIB(tetgen,-ltet,)
+    AC_DEFINE(HAVE_TETGEN,1, tetgen is compute tetrahedralize volume of an enclosed surface)
+fi
+
+# Looking for the BLAS
+# --------------------
+
+ff_blas_ok=no
+ff_blas_inc=""
+
+# ALH - 18/9/13 - give the option to deactivate system blas for testing purposes
+AC_ARG_ENABLE(system-blas,AC_HELP_STRING([--disable-system-blas],[Disable the search for a system-wide BLAS library]))
+
+if test "$enable_system_blas" != no
+then
+
+    # User-specified location
+    # add MKL  seach dec 2010  FH ....
+
+    ff_mkl_flags=""
+    if test "$ff_mkl_libpath" != "not" ; then
+	ff_CFLAGS="$CFLAGS"
+	CHECK_COMPILE_FLAG(C,-mkl,CFLAGS)
+	if test  "$ff_CFLAGS" != "$CFLAGS" ; then
+	    ff_ff_mkl_flags="-mkl"
+	fi
+	CFLAGS="$ff_CFLAGS"
+    fi
+
+    AC_MSG_CHECKING(for MKL)
+    ff_mkl_root=""
+    if test "$ff_mkl_libpath" != "not" -a -z "$ff_mkl_flags" ; then
+	
+	if test "$ff_mkl_libpath"  = "yes"  ; then
+	    ff_IFS="$IFS"
+	    IFS=":"
+	    for i in $LD_LIBRARY_PATH:$LIBRARY_PATH ; do
+		case $i in
+		    */mkl/*) ff_mkl_libpath=$i;;
+		esac ;
+	    done;
+	    IFS="$ff_IFS"
+#	else
+#	    ff_mkl_libpath=no
+	fi
+
+	if test "$ff_mkl_libpath" != "no" -a -d "$ff_mkl_libpath" ; then
+	    ff_mkl_root=`expr "//$ff_mkl_libpath" : '//\(.*\)/lib.*'`
+	    ff_mkl_arch=`expr "//$ff_mkl_libpath" : '//.*/lib/\(.*\)'`
+            ff_mkl_lp=_lp64
+            case "$ff_mkl_arch" in
+		*64*)  ff_mkl_lp=_lp64
+	    esac
+            case $F77 in
+		*ifort*) ff_mkl_cc=intel;;
+		*) ff_mkl_cc=gf;;
+            esac
+            # bof bof ....
+	    case "$MPIRUN" in
+		*/sgi/*)         ff_mkl_mpi=_sgimpt;;
+		*/intel/*)         ff_mkl_mpi=_intelmpi;;
+		*)        ff_mkl_mpi=_openmpi;;
+	    esac
+#            echo ................  ff_mkl_root = $ff_mkl_root  .. $ff_mkl_arch
+	    if test ! -d "$ff_mkl_libpath" ; then
+		ff_mkl_libpath="$ff_mkl_root/lib/$ff_mkl_arch"
+	    fi
+	    
+	    if test  -f "$ff_mkl_libpath/libmkl_rt.$ff_suffix_dylib" ; then
+		mkl_blas=rt
+		mkl_lapack=rt
+		ff_mkl_mlt="-L$ff_mkl_libpath -lmkl_rt -lmkl_intel_thread -lmkl_core  $ff_iomp5 $ff_pthread"
+		ff_mkl_blas="-L$ff_mkl_libpath -lmkl_rt -lmkl_sequential -lmkl_core   $ff_iomp5 $ff_pthread"
+		ff_mkl_lapack="$ff_mkl_blas"
+	    elif test -f "$ff_mkl_libpath/libmkl_lapack.$ff_suffix_dylib" ; then
+		ff_mkl_mlt="-L$ff_mkl_libpath -lmkl_${ff_mkl_cc}${ff_mkl_lp} -lmkl_lapack -lmkl_intel${ff_mkl_lp} -lmkl_intel_thread  -lmkl_core -lguide  -lm -lpthread"
+		ff_mkl_blas="-L$ff_mkl_libpath -lmkl_${ff_mkl_cc}${ff_mkl_lp} -lmkl_lapack -lmkl_intel${ff_mkl_lp} -lmkl_sequential -lmkl_core -lguide -lm -lpthread"
+		ff_mkl_lapack="-L$ff_mkl_root/lib/$ff_mkl_arch -lmkl_lapack"
+	    else
+		ff_mkl_mlt="$ff_ldbg  -L$ff_mkl_libpath -lmkl_${ff_mkl_cc}${ff_mkl_lp}  -lmkl_intel${ff_mkl_lp}  -lmkl_intel_thread  -lmkl_core -lmkl_intel_thread $ff_iomp5  $ff_ldeg  -lm $ff_pthread"
+		ff_mkl_blas="$ff_ldbg  -L$ff_mkl_libpath -lmkl_${ff_mkl_cc}${ff_mkl_lp}  -lmkl_intel${ff_mkl_lp} -lmkl_sequential -lmkl_core  -lmkl_sequential $ff_ldeg   -lm $ff_pthread"
+		ff_mkl_lapack="$ff_mkl_blas"
+	    fi
+	    if test -f "-L$ff_mkl_libpathmkl_scalapack${ff_mkl_lp}" ; then 
+            ff_mkl_scalapack="-L$ff_mkl_libpath -lmkl_blacs${ff_mkl_mpi}${ff_mkl_lp} -lmkl_scalapack${ff_mkl_lp} "
+            ff_mkl_blacs="-L$ff_mkl_libpath -lmkl_blacs${ff_mkl_mpi}${ff_mkl_lp} -lmkl_scalapack${ff_mkl_lp}"
+	    fi
+	    ff_blas_ok=yes
+	    ff_lapack_ok=yes
+
+	    # <<enable_mkl_mlt>> ALH - 6/11/13 - request from Atsushi Suzuki - the default MKL library must be able to
+	    # handle threads when FF is connected to AS' solver. So we need an option to configure FF with the
+	    # multithreaded MKL by default.
+
+	    AC_ARG_ENABLE(mkl_mlt,AC_HELP_STRING([--enable-mkl-mlt],[Link with the multithreaded instead of the monothreaded version of the MKL]))
+
+	    if test "$enable_mkl_mlt" = yes
+	    then
+		ff_blas_libs="$ff_mkl_mlt"
+	    else
+		ff_blas_libs="$ff_mkl_blas"
+	    fi
+
+	    ff_blas_inc="-I$ff_mkl_root/include"
+	    dnl  scalapack, and blacs don not work with mlk and sgi
+	    if test "$ff_mkl_mpi" != "_sgimpt" ; then
+		AC_FF_ADDWHERELIB(scalapack,$ff_mkl_scalapack,$ff_blas_inc)
+		AC_FF_ADDWHERELIB(blacs,$ff_mkl_blacs,$ff_blas_inc)
+	    else
+		ff_warm=" (We do not use MKL scalapack and blacs with sgi MPI),  "
+	    fi
+	    AC_FF_ADDWHERELIB(lapack,$ff_mkl_lapack,$ff_blas_inc)
+	    AC_FF_ADDWHERELIB(mkl,$ff_mkl_mlt,$ff_blas_inc)
+            AC_DEFINE(HAVE_MKL,1, the MKL intel lib is present for BLAS and LAPACK  )
+	else
+	    ff_mkl_libpath=no
+
+	# FH - pardiso is there as soon as mkl is
+            enable_pardiso=no
+	fi
+    fi
+
+
+    AC_MSG_RESULT( [ $ff_warm  root: $ff_mkl_root , arch: $ff_mkl_arch , $ff_mkl_lp ...  ])
+
+    AC_ARG_WITH(blas,
+	AC_HELP_STRING([--with-blas=library],[Use a specific version of the Blas]),
+	ff_blas_ok=yes
+	ff_blas_libs="${withval}")
+
+    # Specific BLAS library location for FreeBSD
+    ff_freebsd_blas="-lf2c -lf77blas -latlas -lgslcblas"
+    #  zmach is in lapack
+    # Trying  blas library
+    # echo "LIBS =  $LIBS blas --- $ff_blas_ok"
+    for iblas in \
+	"-framework Accelerate" "$ff_mkl_blas" "-lblas"  "-L/usr/lib/atlas -lblas" \
+	$ff_freebsd_blas
+    do
+	if test "$ff_blas_ok" = no;
+	then
+            AC_MSG_CHECKING(for daxpy_ in $iblas)
+            ff_save_libs="$LIBS"
+            LIBS="$LIBS $iblas"
+            AC_LINK_IFELSE(
+		[AC_LANG_CALL(,daxpy_)],
+		ff_blas_ok=yes
+		ff_blas_libs="$iblas",)
+            LIBS="$ff_save_libs"
+            AC_MSG_RESULT($ff_blas_ok)
+	fi
+    done
+
+    #cblas_zdotu_sub
+    #echo "LIBS = " $LIBS
+    ff_cblas_libs=no
+    if test "$ff_blas_ok" = yes
+    then
+	AC_MSG_CHECKING(for blas_zdotu_sub in $ff_blas_libs)
+	ff_save_libs="$LIBS"
+	LIBS="$LIBS $ff_blas_libs $FLIBS"
+	AC_LINK_IFELSE(
+            [AC_LANG_CALL(,cblas_zdotu_sub)],
+            ff_cblas_libs=yes)
+	AC_MSG_RESULT($ff_cblas_libs)
+	LIBS="$ff_save_libs"
+    fi
+fi
+
+# <<OpenBLAS>> ALH - 18/9/13 - option to compile the OpenBLAS moved from the FFCS tree to FF tree
+
+AC_ARG_ENABLE(openblas,AC_HELP_STRING([--disable-openblas],[Disable the automatic download of OpenBLAS]))
+if  test "$ff_blas_ok" = no && test "$enable_openblas" != no && test "$enable_download" = yes
+then
+    AC_CHECK_PROG(ff_git,git,yes,no)
+    AC_MSG_CHECKING([Activating the OpenBLAS (deactivate with --disable-openblas)])
+    if test $ff_git = no
+    then
+	AC_MSG_RESULT([git not found])
+    else
+	ff_download_blas=openblas
+
+	# it is necessary to split the library path into -L and -l otherwise ff/upstream/examples+++-load/ff-c++ will
+	# place -lgfortran in LIBS, .../libgoto___.lib in OTHER, and call the compiler with $LIBS before $OTHER, which
+	# will fail.
+
+	ff_blas_libs="-L${curdir}/download/blas/OpenBLAS -lopenblas -lgfortran $ff_pthread"
+	ff_blas_inc="-I${curdir}/download/blas/CBLAS/src"
+
+        # skip generic blas compilation and activate OpenBLAS (see [[file:download/blas/Makefile.am::OpenBLAS]])
+	AC_SUBST(DOWNLOADED_BLAS,"")
+	AC_SUBST(COMPILE_OPENBLAS,openblas)
+
+	ff_blas_ok=yes
+	ff_cblas_h=yes
+	ff_cblas_libs=yes
+
+	AC_MSG_RESULT([ok])
+    fi
+fi
+
+# If all else fails, download a generic version
+
+if test "$ff_blas_ok" = no -a "$enable_download" = yes -a "$enable_fortran" != no -a "$enable_c" != no
+then
+    AC_CHECK_PROG(ff_unzip,unzip,yes,no)
+
+    AC_MSG_CHECKING(for BLAS version to download)
+
+    # Do not update $LIBS, but create an extra LIB variable, because this lib does not exist yet, and this could make
+    # the following tests fail.
+
+    # When compiling a generic version, we do not need an optimized version of the BLAS.
+
+    ff_download_blas=generic
+    ff_blas_libs="-L${curdir}/download/blas -lcblas -lf77blas"
+    ff_blas_inc="-I${curdir}/download/blas/CBLAS/src"
+
+    AC_SUBST(DOWNLOADED_BLAS,"libf77blas.a libcblas.a")
+    AC_SUBST(DOWNLOADED_BLAS_BUILT_SOURCES,'BLAS CBLAS $(F77BLAS_SOURCES) $(CBLAS_SOURCES)')
+
+    AC_MSG_RESULT($ff_download_blas)
+    ff_blas_ok=yes
+    ff_cblas_h=yes
+    ff_cblas_libs=yes
+fi
+
+AC_SUBST(BLASLIBS,$ff_blas_libs)
+AC_SUBST(BLASINC,$ff_blas_inc)
+
+#looking for cblas.h  FH
+
+if test "$ff_blas_ok" = yes -a "$ff_cblas_libs" = yes ;
+then
+    AC_CHECK_HEADERS(cblas.h,
+	ff_cblas_h=yes,
+	ff_cblas_h=no)
+    AC_CHECK_HEADERS(Accelerate/cblas.h,
+	ff_cblas_h=yes
+	ff_cblas_h=no)
+    AC_CHECK_HEADERS(atlas/cblas.h,
+	ff_cblas_h=yes
+	ff_cblas_h=no)
+fi
+
+# ALH - 18/9/13 - [[file:download/blas/Makefile.am]] does not update the WHERE mechanism so it always needs to be set up
+# here even in the case of a downloaded blas library.
+
+AC_FF_ADDWHERELIB(blas,$ff_blas_libs,)
+
+# end of BLAS -------------------
+
+# Looking for ARPACK
+# ------------------
+
+# We need the following g77 libraries to connect to the Fortran 77
+# Arpack.
+
+if test "$ff_blas_ok" = yes;
+then
+  ff_g2c_lib="$FLIBS"
+       if test  -n "$ff_g2c_lib"
+       then
+           LIBS="$LIBS $ff_g2c_lib"
+       else
+	  ff_g2c_ok=no
+	  AC_CHECK_LIB(g2c,G77_second_0,
+		LIBS="$LIBS -lg2c"
+		ff_g2c_lib="-lg2c"
+		ff_g2c_ok=yes)
+
+	  if test "$ff_g2c_ok" = no;
+	     then
+	        AC_MSG_CHECKING(for G77_second_0 in /sw/lib/libg2c.a)
+		ff_save_libs="$LIBS"
+		LIBS="$LIBS -L/sw/lib -lg2c"
+		AC_LINK_IFELSE(
+			[AC_LANG_CALL(,G77_second_0)],
+			ff_g2c_lib="-L/sw/lib -lg2c"
+			ff_g2c_ok=yes,
+			LIBS="$ff_save_libs")
+		AC_MSG_RESULT($ff_g2c_ok)
+	  fi
+	fi
+fi
+
+# Copy the result of g2c investigations into a separate variable
+# because BLAS compilation will need it.
+
+AC_SUBST(G2CLIB,$ff_g2c_lib)
+#looking of  lapack if no compile the arpack lapack
+# warning $$ because the make eat one
+ff_lapack_ok=no;
+ff_lapack_lib=
+AC_MSG_CHECKING([for lapack in $LIBS, $ff_blas_libs and -llapack] )
+    if test "$ff_blas_ok" = yes ; then
+        AC_LINK_IFELSE( [AC_LANG_CALL(,dgeqr2_)], ff_lapack_ok=yes)
+	if test "$ff_lapack_ok" = no ; then
+	    ff_save_libs=$LIBS
+	    LIBS="$ff_save_libs $ff_blas_libs"
+            AC_LINK_IFELSE( [AC_LANG_CALL(,dgeqr2_)], ff_lapack_ok=yes)
+	    if test "$ff_lapack_ok" = no ; then
+	    LIBS="$ff_save_libs -llapack $ff_blas_libs"
+            AC_LINK_IFELSE( [AC_LANG_CALL(,dgeqr2_)], [ff_lapack_ok=yes
+	    ff_lapack_lib="-llapack"] )
+	    fi
+	    LIBS="$ff_save_libs"
+	fi
+    fi
+
+AC_MSG_RESULT($ff_lapack_ok)
+if test "$ff_lapack_ok" != no ; then
+AC_SUBST(LAPACKLIBS,$ff_lapack_lib)
+fi
+if test "$ff_lapack_ok" = no; then
+    AC_ARG_WITH(lapack,
+	AC_HELP_STRING([--with-lapack=library],[Use a specific version of Lapack]),
+	ff_lapack_ok=yes
+	ff_lapack_lib="${withval}"
+	LIBS="$ff_lapack_lib $LIBS")
+fi
+
+# Lapack configuration for Arpack
+
+ff_lapackdir='$$(LAPACKdir)'
+if test "$ff_lapack_ok" = yes
+then
+    # no compilation of lapack in arpack
+    ff_lapackdir=
+else
+    ff_lapack_lib="-L${curdir}/download/lib -llapack"
+fi
+
+# Arpack itself
+
+ff_arpack_ok=no
+ff_save_libs="$LIBS"
+ff_arpack_libs=
+if test "$ff_blas_ok" = yes;
+then
+
+	# User-specified location
+	AC_ARG_WITH(arpack,
+		[  --with-arpack=library	Use a specific version of Arpack],
+		ff_arpack_ok=yes
+		ff_arpack_libs="${withval}")
+
+	# Default locations
+	if test "$ff_arpack_ok" = no;
+	then
+		AC_CHECK_LIB(arpack,dsaupd_,
+			ff_arpack_libs="-larpack -llapack"
+			ff_arpack_ok=yes,,
+			-llapack)
+	fi
+
+   # Trying to "locate" Arpack
+   if test "$ff_arpack_ok" = no -a "$enable_download" != yes ;
+   then
+        AC_MSG_CHECKING(for libarpack with locate)
+        ff_lib_arpack=`locate libarpack|grep  'libarpack.*.a$'|head -1`
+	LIBS="$ff_lib_arpack $LIBS"
+        AC_LINK_IFELSE(
+                [AC_LANG_CALL(,dsaupd_)],
+                ff_arpack_ok=yes
+                ff_arpack_libs="$ff_lib_arpack")
+        AC_MSG_RESULT($ff_arpack_ok)
+    fi
+  if test "$ff_arpack_ok" = yes
+  then
+      AC_FF_ADDWHERELIB(arpack,$ff_arpack_libs,)
+      echo  arpack LD "'$ff_arpack_libs'"  >>$ff_where_lib_conf
+  fi
+
+	# If all else fails, download!
+	if test "$ff_arpack_ok" = no -a "$enable_download" = yes \
+	   -a "$enable_fortran" != no
+	then
+                ff_arpack_download=yes
+		AC_MSG_NOTICE(using downloaded Arpack)
+
+		# ALH - 6/11/13 - this install goal is the standard goal for all downloaded packages in
+		# [[file:download/common.mak::install]]
+
+		AC_SUBST(DOWNLOAD_ARPACK,install)
+
+		AC_SUBST(FF_LAPACKdir,$ff_lapackdir)
+		AC_SUBST(ARPACKLIB,${curdir}/download/lib/libarpack.a)
+		AC_SUBST(LAPACK_arpack_LIB,${curdir}/download/lib/liblapack.a)
+
+		# Do not update $LIBS, but create an extra LIB variable, because this lib does not exist yet, and this
+		# could make the following tests fail.
+
+		# ALH - 30/9/13 - do not use the "-L ${curdir}/download/lib" directive because it would allow other
+		# following -l directives (eg -lumfpack) to pick an old locally compiled library instead of the system
+		# ones.
+
+                ff_arpack_libs="${curdir}/download/lib/libarpack.a $ff_lapack_lib"
+		ff_arpack_ok=yes
+	fi
+fi
+if test  "$ff_arpack_ok" != yes
+ then
+	    AC_MSG_NOTICE([-- NO ARPACK --  enable_download : $enable_download , wget: $ff_wget ])
+fi
+
+# Do not insert ARPACK libs in $LIBS yet, because they may not exist
+# yet, and this could make the following tests fail.
+
+LIBS="$ff_save_libs"
+
+if test "$ff_arpack_ok" = yes;
+then
+        AC_SUBST(ARPACKLIBS,$ff_arpack_libs)
+	EIGENOBJ='eigenvalue.$(OBJEXT)'
+	AC_DEFINE(HAVE_LIBARPACK,1,Arpack is used for eigenvalue computation)
+
+	# Determines whether to run the eigenvalue tests
+else
+# all eigen test fails
+	AC_SUBST([SKIP_TESTS_EIGEN],[yes])
+fi
+AC_SUBST([EIGENOBJ])
+
+# ALH - 25/9/13 - <<WHERE_lapack>> always run the WHERE LD statement for lapack because some libraries in
+# examples++-load require it (eg [[file:examples++-load/Element_Mixte.cpp::lapack]]). Request from Fred.
+
+AC_FF_ADDWHERELIB(lapack,$ff_lapack_lib,)
+
+# Looking for UMFPACK
+# -------------------
+
+ff_amd_ok=no
+ff_umfpack_ok=no
+ff_save_libs="$LIBS"
+if test "$ff_blas_ok" = yes;
+then
+
+    # User-specified location
+
+    AC_ARG_WITH(amd,
+	AC_HELP_STRING([--with-amd=library],[Use a specific version of AMD]),
+        ff_amd_ok=yes
+	ff_umfpack_libs="${withval}")
+
+    AC_ARG_WITH(umfpack,
+        AC_HELP_STRING([--with-umfpack=library],[Use a specific version of Umfpack]),
+        ff_umfpack_ok=yes
+        ff_umfpack_libs="${withval} $ff_umfpack_libs")
+
+    # Trying default locations for the headers
+
+    AC_CHECK_HEADERS(umfpack.h umfpack/umfpack.h ufsparse/umfpack.h suitesparse/umfpack.h,
+	ff_umfpack_header=yes
+	ff_umfpack_dir=`dirname $ac_header`)
+
+    # Somes systems like FreeBSD hide umfpack.h in a directory called UMFPACK (all capitals). This breaks the
+    # standard #define produced by autoconf in config.h.in.
+
+    LIBS="$ff_blas_libs $LIBS"
+    if test "$ff_umfpack_header" != yes;
+    then
+	AC_CHECK_HEADER(UMFPACK/umfpack.h,
+	    ff_umfpack_header=yes
+	    ff_umfpack_dir=UMFPACK
+	    AC_DEFINE(HAVE_BIG_UMFPACK_UMFPACK_H,1,If umfpack.h is located in UMFPACK subdir))
+    fi
+
+    if test "$ff_amd_ok" = no;
+    then
+	AC_CHECK_LIB(amd,amd_info,
+	    ff_umfpack_libs="$ff_umfpack_libs -lamd"
+	    ff_amd_ok=yes)
+    fi
+
+    if test "$ff_umfpack_ok" = no -a "$ff_amd_ok" = yes;
+    then
+
+        # ALH - 30/9/13 - other libraries required by Umfpack
+
+	AC_CHECK_LIB(cholmod,cholmod_add,ff_umfpack_libs="$ff_umfpack_libs -lcholmod")
+	AC_CHECK_LIB(colamd,colamd_set_defaults,ff_umfpack_libs="$ff_umfpack_libs -lcolamd")
+
+	AC_CHECK_LIB(umfpack,umf_i_malloc,
+	    ff_umfpack_libs="-lumfpack $ff_umfpack_libs"
+	    ff_umfpack_ok=yes,,$ff_umfpack_libs)
+    fi
+
+    if test "$ff_umfpack_header" != yes -o "$ff_umfpack_ok" != yes; then
+        ff_umfpack_ok=no
+	AC_MSG_WARN([Sorry, we could not find the UMFPACK lib or the UMFPACK headers])
+    fi
+
+    if test "$ff_umfpack_ok" = yes -a "$ff_amd_ok" = yes; then
+	AC_DEFINE(HAVE_LIBUMFPACK,1,Umfpack is used for sparse matrices computations)
+    fi
+fi
+
+LIBS="$ff_save_libs"
+
+# If all else fails, download!
+
+if test "$ff_umfpack_ok" = no -a "$enable_download" = yes
+then
+    AC_MSG_NOTICE(using downloaded UMFPACK)
+    AC_SUBST(DOWNLOAD_UMFPACK,"umfpack")
+    ff_umfpack_download=yes
+
+    # Do not update $LIBS, but create an extra LIB variable, because this lib does not exist yet, and this could make
+    # the following tests fail.
+
+    ff_umfpack_libs="-L${curdir}/download/lib -lumfpack -lcholmod -lcolamd -lamd -lsuitesparseconfig"
+    AC_DEFINE(HAVE_LIBUMFPACK,1,UMFPACK)
+    if test "$ff_win32" = yes; then
+  	AC_SUBST(FF_UMFPACK_CONFIG,-DCBLAS)
+    fi
+    ff_umfpack_ok=yes
+fi
+
+# ALH - 17/9/13 - moved UMFPACK configuration settings in wherelib to _after_ configuring the download version because
+# [[file:download/umfpack/Makefile.am]] does not set the WHERE mechanism. Also removed -I/usr/include/$ff_umfpack_dir
+# from include options for FFCS because it breaks the MingW64 compilation process.
+
+if test "$ff_umfpack_ok" = yes
+then
+    if test $enable_ffcs = no
+    then
+	AC_FF_ADDWHERELIB(amd,$ff_umfpack_libs,-I/usr/include/$ff_umfpack_dir)
+	AC_FF_ADDWHERELIB(umfpack,$ff_umfpack_libs,-I/usr/include/$ff_umfpack_dir)
+    else
+	AC_FF_ADDWHERELIB(amd,$ff_umfpack_libs,)
+	AC_FF_ADDWHERELIB(umfpack,$ff_umfpack_libs,)
+    fi
+else
+    AC_MSG_NOTICE([ -- NO UMFPACK (ff_wget = $ff_wget)])
+fi
+
+AC_SUBST(UMFPACKLIBS,$ff_umfpack_libs)
+
+# If times() and sysconf() are not here, UMFPACK should know
+
+if test "$ff_umfpack_ok" = yes
+then
+    AC_CHECK_FUNCS(times sysconf,
+	ff_umfpack_posix_ok=yes,
+	ff_umfpack_posix_ok=no)
+
+    if test "$ff_umfpack_posix_ok" = no
+    then
+	AC_SUBST(FF_UMFPACK_CONFIG,"-DCBLAS -DNPOSIX")
+    fi
+fi
+
+# Checking for some functions that may not appear everywhere
+# ----------------------------------------------------------
+AC_CHECK_HEADERS([unistd.h])
+# asinh acosh atanh are not in Mingw yet gettimeofday
+ff_malloc_h=""
+AC_HEADER_TIME
+AC_CHECK_HEADERS(malloc.h,ff_malloc_h=1)
+AC_SUBST(FF_MALLOC_H,$ff_malloc_h)
+
+AC_CHECK_FUNCS(asinh acosh atanh getenv jn erfc tgamma gettimeofday mallinfo mstats)
+AC_CHECK_FUNCS(srandomdev)
+
+
+AC_CHECK_FUNCS(second_,ff_second="",ff_second=second.o)
+AC_SUBST(FF_SECOND,"$ff_second")
+
+# Enable static linking (no shared libraries)
+# -------------------------------------------
+AC_CHECK_PROG(ff_libtool,libtool,yes,no)
+if test  "$ff_mac" = "yes"  -a "$ff_libtool" = yes ; then
+  ff_AR="libtool"
+  ff_ARFLAGS="-static -o"
+  ff_RANLIB="echo"
+fi
+
+AC_ARG_ENABLE(static,
+	[  --enable-static	Build binaries with no shared library dependencies])
+if test "$enable_static" = yes
+then
+	AC_CHECK_PROG(ff_libtool,libtool,yes,no)
+	if test "$ff_libtool" = yes
+	then
+		LDFLAGS="$LDFLAGS -all-static"
+		AC_SUBST(STATICTOOL,libtool)
+	else
+		AC_MSG_ERROR(libtool not found)
+	fi
+fi
+#  for compiation of  arpack  use libtool to bluid universal library on MacOs.
+AC_SUBST(AR,$ff_AR)
+AC_SUBST(ARFLAGS,$ff_ARFLAGS)
+AC_SUBST(RANLIN,$ff_RANLIB)
+
+
+# Dynamic loading of compiled functions
+# -------------------------------------
+
+# Not if we don't want shared libraries (non FH  modif FH juin 2005)
+ff_dynload=no
+if test "$enable_static" != yes
+then
+
+	# Availability of dlopen(). Use AC_COMPILE rather than
+	# AC_CHECK_HEADERS because the latter has problems seeing it (in
+	# Cygwin) when it does not compile (in Mingw).
+
+	AC_MSG_CHECKING(for dlfcn.h)
+	AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <dlfcn.h>]])],
+		ff_dynload=yes,
+		ff_dynload=no)
+	AC_MSG_RESULT($ff_dynload)
+fi
+
+# FFCS - -lm missing for ffmedit link stage on Debian Testing
+AC_CHECK_LIB(m,sin)
+
+# Checks that we also have the corresponding library
+if test "$ff_dynload" = yes
+then
+	AC_CHECK_LIB(dl,dlinfo)
+
+	# Checks that everythings works ok
+	AC_MSG_CHECKING(whether dlopen links ok)
+	AC_LINK_IFELSE(
+[AC_LANG_SOURCE([[#include <dlfcn.h>
+int main(int argc,char **argv){
+  dlopen("",RTLD_LAZY);
+  return 0;
+}]])],
+	ff_dynload=yes,
+	ff_dynload=no)
+	AC_MSG_RESULT($ff_dynload)
+fi
+
+#  the -rdynamic don't exist on macos and sunOS
+if test "$ff_dynload" = yes
+then
+	AC_DEFINE(HAVE_DLFCN_H,1,Dynamic loading - not mandatory)
+	# Activate dynamic loading tests (see examples++-load/Makefile.am)
+	AC_SUBST(LOAD_TESTS,../regtests.sh)
+	AC_SUBST(LOAD_COMPILE,load_compile)
+
+	# gcc on MacOS does not produce an error with "-rdynamic" but
+	# still complains about it.
+	if test "$ff_mac" = "no" -a "$ff_win32"  = "no" -a "$ff_sunos"  = "no" ;
+	then
+		CHECK_COMPILE_FLAG(C++,-rdynamic,LDFLAGS)
+dnl		CHECK_COMPILE_FLAG(C,-rdynamic,CNOFLAGS)
+dnl		CHECK_COMPILE_FLAG(C,-rdynamic,CFLAGS)
+	fi
+	CHECK_COMPILE_FLAG(C++,-fPIC,CXXFLAGS)
+	CHECK_COMPILE_FLAG(C,-fPIC,CFLAGS)
+	CHECK_COMPILE_FLAG(C,-fPIC,CNOFLAGS)
+	if test "$enable_fortran" != no
+	 then
+	 CHECK_COMPILE_FLAG(Fortran,-fPIC,FFLAGS)
+	 CHECK_COMPILE_FLAG(Fortran,-fPIC,FNOFLAGS)
+	 CHECK_COMPILE_FLAG(Fortran,-fPIC,FCFLAGS)
+	 CHECK_COMPILE_FLAG(Fortran,-fPIC,FCNOFLAGS)
+dnl	 CHECK_COMPILE_FLAG(Fortran,-rdynamic,FNOFLAGS)
+dnl	 CHECK_COMPILE_FLAG(Fortran,-rdynamic,FFLAGS)
+
+	fi
+fi
+AC_SUBST(DYLIB_SUFFIX,$ff_suffix_dylib)
+
+# Checking wether we can generate some documentation
+# --------------------------------------------------
+
+AC_CHECK_PROG(ff_latex,latex,yes,no)
+AC_CHECK_PROG(ff_makeindex,makeindex,yes,no)
+AC_CHECK_PROG(ff_dvips,dvips,yes,no)
+# to translate the figure
+AC_CHECK_PROG(ff_pdf2ps,pdf2ps,yes,no)
+AC_CHECK_PROGS(EPSTOPDF,[epstopdf pstopdf],[false])
+AC_CHECK_PROG(ff_convert,convert,yes,no)
+if test "$ff_latex" = yes -a "$ff_makeindex" = yes -a "$ff_dvips" = yes -a $ff_pdf2ps = yes -a $ff_convert = yes;
+then
+	AC_SUBST(DOCPS,"freefem++doc.ps")
+
+	AC_CHECK_PROG(ff_gzip,gzip,yes,no)
+	if test "$ff_gzip" = yes;
+	then
+		AC_SUBST(DOCPSGZ,"freefem++doc.ps.gz")
+	fi
+fi
+
+# PDF documentation building sometimes poses problems because of
+# pdfsync.sty. So we need to be able to disable it.
+enable_pdf=yes
+AC_ARG_ENABLE(pdf,[  --disable-pdf	Disable PDF documentation building])
+if test "$enable_pdf" != no
+then
+   AC_CHECK_PROG(ff_pdflatex,pdflatex,yes,no)
+   if test "$ff_pdflatex" = yes -a $EPSTOPDF != false -a $ff_convert = yes;
+   then
+	AC_SUBST(DOCPDF,"freefem++doc.pdf")
+   fi
+fi
+
+# HISTORY logging through CVS, but only if we are in a CVS working area
+if test -d CVS
+then
+	AC_CHECK_PROG(ff_history,cvs2cl,yes,no)
+	if test "$ff_history" = yes
+	then
+	   AC_SUBST(HISTORY,history)
+	fi
+fi
+
+# Choosing compilation options for the standard version (in src/std)
+# ------------------------------------------------------------------
+
+# The "standard" configured version can use win32 (mingw)
+
+if test "$ff_mingw" = yes
+then
+
+    # FFCS does not use FreeFem++-std, and Pcrgraph.cpp does not compile under mingwin64
+    if test $enable_ffcs = no
+    then
+	ff_stdprog="FreeFem++-std${EXEEXT}"
+	ff_std_graph_obj=Pcrgraph.$OBJEXT
+    fi
+
+    # ALH - FFCS - 30/11/8 - I need to get the output from FF for FFCS regression tests
+    if test $enable_ffcs = yes
+    then
+	ff_std_ldflags="-mconsole -mwindows"
+    else
+	ff_std_ldflags=-mwindows
+    fi
+
+	ff_std_libs=
+fi
+AC_SUBST(STD_GRAPH_OBJ,$ff_std_graph_obj)
+AC_SUBST(STD_LDFLAGS,$ff_std_ldflags)
+
+AC_SUBST(STD_LIBS,$ff_std_libs)
+
+# Allow some downloaded tools not to be compiled
+# ----------------------------------------------
+
+# ALH - this is required by FFCS that needs to deactivate some tools that do not work on all platforms. Some FF users
+# may also find interesting to specify a local version of a tool instead of downloading it.
+
+# m4 macro parameters: $1 = tool name, $2 = dynamic library name, $3 = download directory name if different from $1
+
+m4_define([TOOL_PARAMETERS],
+    [AC_ARG_WITH($1_include,AC_HELP_STRING([--with-$1-include=],[Include directives for $1 instead of automatic download]))
+    AC_ARG_WITH($1_ldflags,AC_HELP_STRING([--with-$1-ldflags=],[Link-time directives for $1 instead of automatic download]))
+
+    if test "$with_$1_include" != "" || test "$with_$1_ldflags" != ""
+    then
+
+	# some directives have been specified, use them instead of downloading
+
+	AC_FF_ADDWHERELIB($1,$with_$1_ldflags,$with_$1_include)
+        AC_SUBST([TOOL_COMPILE_$1],"")
+	enable_$1_download=no
+    fi
+])
+
+m4_define([TOOL_DISABLE],
+    [AC_ARG_ENABLE($1,AC_HELP_STRING([--disable-$1],[Do not use $1]))
+    if test "$enable_$1" = "no"
+    then
+        AC_SUBST([TOOL_COMPILE_$1],"")
+        AC_SUBST([TOOL_DYLIB_$1],"")
+    else
+        AC_SUBST([TOOL_COMPILE_$1],ifelse($3,,$1,$3))
+        AC_SUBST([TOOL_DYLIB_$1],$2)
+	enable_$1_download=yes
+    fi
+
+    # Also allow to disable the download of one tool if it is already locally installed
+
+    TOOL_PARAMETERS($1,$2,$3)
+])
+##  try to see pakage is hon computer  if the FH ZZZZ 
+## FH to find gsl ... 
+AX_PATH_GSL(1.15, ff_with_gsl=yes, ff_with_gsl=no)
+if test "$ff_with_gsl" = "yes"; then  
+  AC_FF_ADDWHERELIB(gsl,$GSL_LIBS,$GSL_CFLAGS)
+fi
+
+##
+
+
+m4_map([AC_FF_WHERELIB],[
+	[[mumps],[-ldmumps -lzmumps  -lmumps_common  -lpord],[dmumps_c.h],[]],
+	[[mumps_ptscotch],[-lpord_ptscotch -lmumps_common_ptscotch -ldmumps_ptscotch -lzmumps_ptscotch -lpord_ptscotch],[dmumps_c.h]],
+	[[mumps_scotch],[-lpord_scotch -lmumps_common_scotch -ldmumps_scotch -lzmumps_scotch -lpord_scotch],[dmumps_c.h]],
+	[[hypre],[-lHYPRE]],
+	[[fftw3],[-lfftw3],[/usr/include/fftw3.h],[]],
+	[[superlu_dist],[-lsuperlu-dist],[/usr/include/superlu-dist/superlu_defs.h],[]],
+	[[superlu],[-lsuperlu],[/usr/include/superlu/superlu_enum_consts.h],[]],
+	[[Superlu4],[-lsuperlu4],[/usr/include/superlu4/superlu_enum_consts.h],[]],
+        [[blacs],[ -lblacsCinit$ff_with_mpi	-lblacsF77init$ff_with_mpi	-lblacs$ff_with_mpi],[]],
+        [[scalapack],[-lscalapack$ff_with_mpi],[]],
+        [[scotch],[-lscotch -lscotcherr],[scotch.h]],
+        [[ptscotch],[-lptscotch -lptscotcherr],[ptscotch.h]],
+	[[metis],[-lscotch -lmetis],[/usr/include/metis/metis.h],[]],
+	[[metis],[-lscotch -lmetis],[metis.h],[]],
+	[[parmetis],[-lptscotch -lparmetis],[],[]],
+	[[freeyams],[-lfreeyams],[freeyamslib.h],[]],
+	[[mmg3d],[-lmmg3d],[libmmg3d.h],[]],
+	[[mshmet],[-lmshmet],[],[]],
+dnl	[[gsl],[-lgsl -lgslcblas -lm],[gsl/gsl_sf.h],[]],
+	[[parms],[-lparms -litsol -llapack -lblas -lm],[],[]],
+	[[tetgen],[-ltet],[tetgen.h],[]],
+    ]
+    )
+## before try 
+
+TOOL_DISABLE(fflapack,fflapack.$DYLIB_SUFFIX)
+TOOL_DISABLE(hips,hips_FreeFem.$DYLIB_SUFFIX)
+TOOL_DISABLE(ipopt,ff-Ipopt.$DYLIB_SUFFIX)
+TOOL_DISABLE(lapack,lapack.$DYLIB_SUFFIX)
+TOOL_DISABLE(metis,metis.$DYLIB_SUFFIX)
+TOOL_DISABLE(mmg3d,mmg3d-v4.0.$DYLIB_SUFFIX)
+TOOL_DISABLE(mshmet,mshmet.$DYLIB_SUFFIX)
+TOOL_DISABLE(mumps,"MUMPS_FreeFem.$DYLIB_SUFFIX MUMPS.$DYLIB_SUFFIX")
+TOOL_DISABLE(mumps_seq,"MUMPS_seq.$DYLIB_SUFFIX MUMPS.$DYLIB_SUFFIX",mumps-seq)
+TOOL_DISABLE(nlopt,ff-NLopt.$DYLIB_SUFFIX)
+TOOL_DISABLE(parmetis)
+TOOL_DISABLE(parms,parms_FreeFem.$DYLIB_SUFFIX)
+TOOL_DISABLE(pastix,"interfacepastix.$DYLIB_SUFFIX complex_pastix_FreeFem.$DYLIB_SUFFIX real_pastix_FreeFem.$DYLIB_SUFFIX")
+TOOL_DISABLE(pipe,pipe.$DYLIB_SUFFIX)
+TOOL_DISABLE(scotch,scotch.$DYLIB_SUFFIX)
+TOOL_DISABLE(superlu,SuperLu.$DYLIB_SUFFIX)
+TOOL_DISABLE(superludist,"complex_SuperLU_DIST_FreeFem.$DYLIB_SUFFIX real_SuperLU_DIST_FreeFem.$DYLIB_SUFFIX dSuperLU_DIST.$DYLIB_SUFFIX")
+TOOL_DISABLE(umfpack,UMFPACK64.$DYLIB_SUFFIX)
+TOOL_DISABLE(yams,freeyams.$DYLIB_SUFFIX)
+TOOL_DISABLE(pipe,pipe.$DYLIB_SUFFIX)
+
+# FFCS - MUMPS_seq has a different Win32 compiler setup from FFCS, so we need to add some extra parameters
+
+if test "$OS" = Windows_NT
+then
+    CFLAGS="$CFLAGS -DWITHOUT_PTHREAD -DAdd_"
+
+    # we also need to satisfy ff-c++ that the pthread are not a blocking point
+    if test -n "$ff_pthread"  ; then
+       AC_FF_ADDWHERELIB(pthread,"",)
+    fi
+fi
+
+# ALH - pARMS needs "-fno-range-check" on Windows, but this options fails on MacOS 10.8.  Add no-range-check for Windows
+# for hexadecimal parameter constants like:
+#
+# [[file:c:/cygwin/home/alh/ffcs/rel/mingw/mpif.h::PARAMETER MPI_SHORT_INT z 8c000003]]
+#
+# Such constants are rejected without [[file:download/parms/makefile-parms.in::NO_RANGE_CHECK]]
+
+if test "$OS" = Windows_NT
+then
+    AC_SUBST(NO_RANGE_CHECK,-fno-range-check)
+fi
+
+# ALH - 4/9/13 - request from Helmut Jarausch - allow to change Scotch include path
+if test "$with_scotch_include" = "" 
+then
+    with_scotch_include=$ac_pwd/download/include/scotch
+fi
+AC_SUBST(SCOTCH_INCLUDE,$with_scotch_include)
+
+# Find out kernel and libc versions
+# ---------------------------------
+
+if test "$ff_win32" != yes -a "$ff_mac" != yes
+then
+	AC_MSG_CHECKING(kernel version)
+	ff_kernel_version=`cat /proc/version|perl -e '<STDIN>=~/(\d+\.\d+\.\d+)/;print $1;'`
+	AC_MSG_RESULT($ff_kernel_version)
+	AC_SUBST(KERNEL_VERSION,$ff_kernel_version)
+
+	AC_MSG_CHECKING(libc version)
+	ff_libc_version=`ldd /bin/sh | awk '/libc/{print $3}' | xargs readlink | sed -e 's/\.so$//'`
+	AC_MSG_RESULT($ff_libc_version)
+	AC_SUBST(LIBC_VERSION,$ff_libc_version)
+fi
+#  def variable pour les makefiles
+
+# creating all makefiles
+# ----------------------
+
+ff_bamgprog="bamg${EXEEXT} cvmsh2${EXEEXT}"
+
+AC_SUBST(CNOFLAGS,$CNOFLAGS) dnl for superludist CFLAGS without optim  ...
+AC_SUBST(FNOFLAGS,$FNOFLAGS) dnl for blacs CFLAGS without optim  ...
+
+# The final list of executable programs
+
+AC_SUBST(MEDITPROG,$ff_meditprog)
+AC_SUBST(FFGLUTPROG,$ff_ffglutprog)
+AC_SUBST(BAMGPROG,$ff_bamgprog)
+AC_SUBST(STDPROG,$ff_stdprog)
+ff_progs="FreeFem++-nw $ff_bamgprog  $ff_mpiprog $ff_meditprog $ff_ffglutprog"
+
+AC_SUBST(TEST_FFPP,$ff_TEST_FFPP)
+AC_SUBST(TEST_FFPPMPI,"../src/mpi/ff-mpirun")
+
+ff_with_mpi=-openmpi;
+
+ff_blacs="-lblacsCinit$ff_with_mpi     -lblacsF77init$ff_with_mpi      -lblacs$ff_with_mpi"
+ff_scalapack=-lscalapack
+
+# change MKL interface ...
+test -n "$ff_mkl_blacs" && ff_blacs="$ff_mkl_blacs"
+test -n "$ff_mkl_scalapack" && ff_scalapack="$ff_mkl_scalapack"
+test -n "$ff_mkl_root" && ff_winc="$ff_mkl_root/include/mkl_blas.h"
+
+# FFCS - 27/10/11 - Some extra conditionals for things that do not work on certain systems (eg MPI libraries under
+# Windows)
+
+##  search of HDF5 ....
+AX_LIB_HDF5()
+if test "$with_hdf5" = "yes"; then  
+  AC_FF_ADDWHERELIB(hdf5,$HDF5_LDFLAGS  $HDF5_LIBS,$HDF5_CPPFLAGS)
+  LIBS="$LIBS $HDF5_LDFLAGS  $HDF5_LIBS"
+else
+  enable_iohdf5=no  
+fi
+TOOL_DISABLE(iohdf5,iohdf5.$DYLIB_SUFFIX)
+
+
+AM_CONDITIONAL([FFCS_WINDOWS],[test "$OS" = Windows_NT])
+
+#  remove gsl if not find ... FH
+# correction FH .. 18/12/2013. 
+# ALH - 7/1/14 - not able to compile gsl or pardiso with FFCS on Windows
+if test "$enable_ffcs" != yes
+then
+    if test  "$ff_where_lib_conf_gsl" == 1  -a  "$enable_gsl"!="no" ; then enable_gsl=yes; fi;
+    if test  "$ff_where_lib_conf_mkl" == 1  -a  "$enable_mkl"!=no ; then enable_pardiso=yes; fi;
+fi
+TOOL_DISABLE(gsl,"gsl.$DYLIB_SUFFIX")
+TOOL_DISABLE(NewSolver,"NewSolver.$DYLIB_SUFFIX")
+TOOL_DISABLE(pardiso,"PARDISO.$DYLIB_SUFFIX")
+
+# echo "debug cxxx11: $ff_cxx11 mpi: $ff_mpi petsc: $ff_petsc_ok "
+
+test "$ff_cxx11" != yes -o  "$ff_mpi" != yes &&  enable_schwarz=no
+
+TOOL_DISABLE(schwarz,"schwarz.$DYLIB_SUFFIX removeDOF.$DYLIB_SUFFIX utility.$DYLIB_SUFFIX")
+
+
+# All makefiles
+AC_OUTPUT(Makefile
+    download/Makefile
+    download/blas/Makefile
+    download/arpack/Makefile
+    download/umfpack/Makefile
+    download/fftw/Makefile
+    src/Makefile
+    src/bamglib/Makefile
+    src/Graphics/Makefile
+    src/femlib/Makefile
+    src/Algo/Makefile
+    src/lglib/Makefile
+    src/fflib/Makefile
+    src/nw/Makefile
+    src/mpi/Makefile
+    src/bamg/Makefile
+    src/libMesh/Makefile
+    src/medit/Makefile
+    src/bin-win32/Makefile
+    examples++/Makefile
+    examples++-eigen/Makefile
+    examples++-tutorial/Makefile
+    examples++-mpi/Makefile
+    examples++-load/Makefile
+    examples++-chapt3/Makefile
+    examples++-bug/Makefile
+    examples++-other/Makefile
+    examples++-3d/Makefile
+    DOC/Makefile)
+AC_MSG_NOTICE([  freefem++ used  download : $enable_download ])
+AC_MSG_NOTICE([	 	 --  Dynamic load facility: $ff_dynload ])
+AC_MSG_NOTICE([		 --  ARPACK (eigen value): $ff_arpack_ok ])
+AC_MSG_NOTICE([		 --  UMFPACK (sparse solver) $ff_umfpack_ok ])
+AC_MSG_NOTICE([		 --  BLAS $ff_blas_ok ])
+AC_MSG_NOTICE([		 --  with MPI             $ff_mpi])
+AC_MSG_NOTICE([          --  with PETSC $ff_petsc_ok ]);
+AC_MSG_NOTICE([          --  with schwarz (HPDDM) $enable_schwarz (need MPI & c++11 :  $ff_cxx11 ) ]);
+
+
+AC_MSG_NOTICE([    progs: $ff_progs ])
+if test  "$ff_umfpack_download" = yes  ;then
+    AC_MSG_NOTICE([      use of download UMFPACK see  download/umfpack/SuiteSparse/UMFPACK/README.txt for the License])
+fi
+if test "$ff_arpack_download" = yes  ; then
+    AC_MSG_NOTICE([      use of download ARPACK see  download/arpack/ARPACK/README  no License ])
+fi
+
+if test "$enable_download" = yes  ;then
+    AC_MSG_NOTICE([      use of download fftw   see  download/fftw/fftw-3.2/COPYRIGHT ])
+    AC_MSG_NOTICE([      use of download tetgen  see download/tetgen/tetgen1.4.3/LICENSE ])
+    AC_MSG_NOTICE([      use of download freeyams  see download/yams/freeyams.2011.02.22 (suface mesh adaptation)  ])
+    AC_MSG_NOTICE([      use of download mmg3d (v4)   see download/mmg3d/mmg3d4/LICENCE.txt  ])
+    AC_MSG_NOTICE([      use of download metis])
+
+    # ALH - some tools may be activated but not downloaded if a local version is specified (see
+    # [[TOOL_PARAMETERS]])
+
+    if test "$enable_superlu_download" = yes
+    then
+	AC_MSG_NOTICE([      use of download superlu])
+    fi
+
+    if test -n "$MPICC" ; then
+   	AC_MSG_NOTICE([      try to download: blacs parmetis  scalapack scotch superludist pastix hypre hips library])
+    fi
+
+    if test "$ff_download_blas" = "generic"  ; then
+        AC_MSG_NOTICE([      use of download generic blas and cblas freefem may be slow  ])
+        AC_MSG_NOTICE([      you can try to use the  Kazushige Goto s BLAS at http://www.cs.utexas.edu/users/flame/goto/  ])
+        AC_MSG_NOTICE([          or at  http://www.tacc.utexas.edu/~kgoto/ for the best BLAS .])
+        AC_MSG_NOTICE([      or try to download/compile the altas blas .])
+    fi
+
+    # ALH - 30/10/13 - (request from FH) all downloads are now part of a separate script ([[file:download/getall]])
+    # which needs to be run before make for the user to specify whether he is ok with each of the package licences.
+
+    AC_MSG_NOTICE([      Please run "download/getall" to download all necessary packages before running make])
+fi
+
+# FFCS does not use glut, so remove this message because it could make the user think that something is broken
+
+if test $enable_ffcs = no
+then
+    if test "$ff_glut_ok" != yes  ; then
+	AC_MSG_NOTICE([     *********************************************** ])
+	AC_MSG_NOTICE([     WARNING: you do not have the new grachics tools ])
+	AC_MSG_NOTICE([         because the configure do not find OpenGL, GLUT or pthread  developer stuff ])
+	AC_MSG_NOTICE([         read the README to find missing package  ])
+	AC_MSG_NOTICE([         F. Hecht  ])
+	AC_MSG_NOTICE([ to install missing package  under debian or ubuntu, try: sudo apt-get install freeglut3-dev ])
+	AC_MSG_NOTICE([     *********************************************** ])
+    fi
+fi
+
+# Local Variables:
+# mode:shell-script
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/copysharedlibs.sh b/copysharedlibs.sh
new file mode 100755
index 0000000..04893af
--- /dev/null
+++ b/copysharedlibs.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+# Find out which shared libs an executable needs and copy them
+# Antoine Le Hyaric - LJLL Paris 6 - lehyaric at ann.jussieu.fr - 22/11/04
+# $Id$
+
+# $1=executable to analyze
+if test ! -x $1
+then
+    echo $1 is not an executable
+    exit 1
+fi
+
+# $2= where to copy shared libs
+if test ! -d $2
+then
+    echo $2 is not a directory
+fi
+
+# List all shared libs
+libs=`ldd $1|awk '{print $3}'`
+if test "$libs" != "dynamic" -a "$libs" != ""
+then
+    cp $libs $2
+fi
diff --git a/crimson-freefem++.zip b/crimson-freefem++.zip
new file mode 100644
index 0000000..4f82ed0
Binary files /dev/null and b/crimson-freefem++.zip differ
diff --git a/debian/FreeFem++-glx.1 b/debian/FreeFem++-glx.1
new file mode 100644
index 0000000..7f471af
--- /dev/null
+++ b/debian/FreeFem++-glx.1
@@ -0,0 +1,64 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FREEFEM++-glx 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+FreeFem++-glx \- executes FreeFem++ scripts
+.SH SYNOPSIS
+.B FreeFem++-glx
+.RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B FreeFem++-glx
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBFreeFem++-glx\fP is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). It can launch OpenGL graphics windows.
+.SH OPTIONS
+A summary of options is included below.
+.br
+.\".B \-h, \-\-help
+.B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.br
+.B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.br
+.B \-glut  command  :  the command name of glut (default is ffglut)
+.br
+.B \-nowait  :  do not wait after launching a window
+.br
+.B \-wait  :  wait after launching a window
+.br
+.B \-nw  :  no ffglut (=> no graphics windows)
+.br
+.B \-ne  :  no edp script output
+.br
+.B \-cd  :  change dir to script dir
+.BR 
+.TP
+.SH SEE ALSO
+.BR FreeFem++ (1),
+.BR FreeFem++-nw (1),
+.BR FreeFem++-x11 (1),
+.BR FreeFem++-mpi
+.br
+.SH AUTHOR
+FreeFem++-glx was written by Frédéric Hecht<hecht at ann.jussieu.fr>, Olivier Pironneau<pironneau at ann.jussieu.fr>, Antoine Le Hyaric<lehyaric at ann.jussieu.fr> and Albert Ly<ly at ann.jussieu.fr>.
+.PP
+This manual page was made by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/FreeFem++-mpi.1 b/debian/FreeFem++-mpi.1
new file mode 100644
index 0000000..34ed329
--- /dev/null
+++ b/debian/FreeFem++-mpi.1
@@ -0,0 +1,54 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FREEFEM++-mpi 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+FreeFem++-mpi \- executes FreeFem++ scripts
+.SH SYNOPSIS
+.B FreeFem++-mpi
+.RI "[ -v  verbosity ] [ -nw ] [ -cd ] script.edp"
+.br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B FreeFem++-mpi
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBFreeFem++-mpi\fP is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). It is used for running FreeFem++ scripts in parallel (see the FreeFem++ documentation on how to do this). It can give only postscript plot output. i.e. no graphics windows are opened.
+.SH OPTIONS
+A summary of options is included below.
+.br
+.\".B \-h, \-\-help
+.B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.br
+.B \-ne  :  no edp script output
+.br
+.B \-cd  :  change dir to script dir
+.BR 
+.TP
+.SH SEE ALSO
+.BR FreeFem++ (1),
+.BR FreeFem++-nw (1),
+.BR FreeFem++-x11 (1),
+.BR FreeFem++-glx
+.br
+.SH AUTHOR
+FreeFem++-mpi was written by Frédéric Hecht<hecht at ann.jussieu.fr>, Olivier Pironneau<pironneau at ann.jussieu.fr>, Antoine Le Hyaric<lehyaric at ann.jussieu.fr> and Albert Ly<ly at ann.jussieu.fr>.
+.PP
+This manual page was made by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/FreeFem++-nw.1 b/debian/FreeFem++-nw.1
new file mode 100644
index 0000000..4e33209
--- /dev/null
+++ b/debian/FreeFem++-nw.1
@@ -0,0 +1,54 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FREEFEM++-nw 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+FreeFem++-nw \- executes FreeFem++ scripts
+.SH SYNOPSIS
+.B FreeFem++-nw
+.RI "[ -v verbosity ] [ -ne ] [ -cd ] script.edp"
+.br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B FreeFem++-nw
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBFreeFem++-nw\fP is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). It can give only postscript plot output (batch version, no graphics windows via ffglut).
+.SH OPTIONS
+A summary of options is included below.
+.br
+.\".B \-h, \-\-help
+.B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.br
+.B \-ne  :  no edp script output
+.br
+.B \-cd  :  change dir to script dir
+.BR 
+.TP
+.SH SEE ALSO
+.BR FreeFem++ (1),
+.BR FreeFem++-x11 (1),
+.BR FreeFem++-glx (1),
+.BR FreeFem++-mpi
+.br
+.SH AUTHOR
+FreeFem++-nw was written by Frédéric Hecht<hecht at ann.jussieu.fr>, Olivier Pironneau<pironneau at ann.jussieu.fr>, Antoine Le Hyaric<lehyaric at ann.jussieu.fr> and Albert Ly<ly at ann.jussieu.fr>.
+.PP
+This manual page was made by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/FreeFem++-x11.1 b/debian/FreeFem++-x11.1
new file mode 100644
index 0000000..d7e7669
--- /dev/null
+++ b/debian/FreeFem++-x11.1
@@ -0,0 +1,64 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FREEFEM++-x11 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+FreeFem++-x11 \- executes FreeFem++ scripts
+.SH SYNOPSIS
+.B FreeFem++-x11
+.RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B FreeFem++-x11
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBFreeFem++-x11\fP is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). It can launch, X11 graphics windows.
+.SH OPTIONS
+A summary of options is included below.
+.br
+.\".B \-h, \-\-help
+.B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.br
+.B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.br
+.B \-glut  command  :  the command name of glut (default is ffglut)
+.br
+.B \-nowait  :  do not wait after launching a window
+.br
+.B \-wait  :  wait after launching a window
+.br
+.B \-nw  :  no ffglut (=> no graphics windows)
+.br
+.B \-ne  :  no edp script output
+.br
+.B \-cd  :  change dir to script dir
+.BR 
+.TP
+.SH SEE ALSO
+.BR FreeFem++ (1),
+.BR FreeFem++-nw (1),
+.BR FreeFem++-glx (1),
+.BR FreeFem++-mpi
+.br
+.SH AUTHOR
+FreeFem++-x11 was written by Frédéric Hecht<hecht at ann.jussieu.fr>, Olivier Pironneau<pironneau at ann.jussieu.fr>, Antoine Le Hyaric<lehyaric at ann.jussieu.fr> and Albert Ly<ly at ann.jussieu.fr>.
+.PP
+This manual page was made by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/FreeFem++.1 b/debian/FreeFem++.1
new file mode 100644
index 0000000..76ae8be
--- /dev/null
+++ b/debian/FreeFem++.1
@@ -0,0 +1,64 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FREEFEM++ 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+FreeFem++ \- executes FreeFem++ scripts
+.SH SYNOPSIS
+.B FreeFem++
+.RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B FreeFem++
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBFreeFem++\fP is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM).
+.SH OPTIONS
+A summary of options is included below.
+.br
+.\".B \-h, \-\-help
+.B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.br
+.B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.br
+.B \-glut  command  :  the command name of glut (default is ffglut)
+.br
+.B \-nowait  :  do not wait after launching a window
+.br
+.B \-wait  :  wait after launching a window
+.br
+.B \-nw  :  no ffglut (=> no graphics windows)
+.br
+.B \-ne  :  no edp script output
+.br
+.B \-cd  :  change dir to script dir
+.BR 
+.TP
+.SH SEE ALSO
+.BR FreeFem++-x11 (1),
+.BR FreeFem++-nw (1),
+.BR FreeFem++-glx (1),
+.BR FreeFem++-mpi
+.br
+.SH AUTHOR
+FreeFem++ was written by Frédéric Hecht<hecht at ann.jussieu.fr>, Olivier Pironneau<pironneau at ann.jussieu.fr>, Antoine Le Hyaric<lehyaric at ann.jussieu.fr> and Albert Ly<ly at ann.jussieu.fr>.
+.PP
+This manual page was created by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/README.Debian b/debian/README.Debian
new file mode 100644
index 0000000..cd83ce0
--- /dev/null
+++ b/debian/README.Debian
@@ -0,0 +1,36 @@
+A repack script, namely debian/repack.sh, should be used in order to
+
+i) Remove the apple-mac files, beginning with ., form the upstream source tree.
+ii) Convert the upstream source version numbering from freefem++-a.b-c.tar.gz to
+    freefem++-a.b.c.tar.gz for Debian packaging.
+
+In the debian/repack.sh script one should just set
+
+VERSION=a.b-c
+VERSION1=a.b.c
+
+or
+
+VERSION=a.b
+VERSION1=a.b
+
+if -c is absent in the upstream version, and then should execute the script 
+from within the /debian directory. 
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otent.gr>  Fri, 30 Dec 2011 21:44:00 +0200
+
+
+Note that the executable file /usr/bin/bamg has been renamed /user/bin/ffbamg
+to avoid double occurence of the former, in both freefem++ and rheolef 
+packages.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otent.gr>  Mon, 20 Jun 2011 22:49:00 +0200
+
+
+Please note that gcc 4.5.3 instead of gcc 4.6 is forced because of the bug:
+http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49264
+We will update the dependency once gcc 4.6.1 is released and uploaded to
+unstable.
+
+ -- Sylvestre Ledru <sylvestre at debian.org>  Tue, 07 Jun 2011 17:50:04 +0200
+
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..0da2a5c
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,190 @@
+freefem++ (3.34.1-1) UNRELEASED; urgency=medium
+
+  * Imported Upstream version 3.34.1
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Sun, 22 Feb 2015 11:50:14 +0200
+
+freefem++ (3.32.1-1) experimental; urgency=medium
+
+  * Edit d/watch file to fix broken downloaded upstream tarball
+  * Imported Upstream version 3.32.1
+  * Update standards version
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Tue, 30 Dec 2014 16:21:29 +0200
+
+freefem++ (3.31-2-1) unstable; urgency=low
+
+  * Imported Upstream version 3.31-2
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Mon, 21 Jul 2014 14:15:13 +0300
+
+freefem++ (3.30-1) unstable; urgency=medium
+
+  * Imported Upstream version 3.30
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Fri, 25 Apr 2014 13:47:29 +0300
+
+freefem++ (3.27-1) unstable; urgency=medium
+
+  * Imported Upstream version 3.27
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Mon, 03 Mar 2014 13:31:46 +0200
+
+freefem++ (3.26-2-3) unstable; urgency=low
+
+  * Change package urgency from medium to low
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Thu, 26 Dec 2013 19:30:00 +0200
+
+freefem++ (3.26-2-2) unstable; urgency=medium
+
+  [ Dimitrios Eftaxiopoulos ]
+  * Enable build with metis
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Thu, 26 Dec 2013 16:13:46 +0200
+
+freefem++ (3.26-2-1) unstable; urgency=low
+
+  * Imported Upstream version 3.26-2 (Closes: #706714)
+  * Disable make check execution in d/rules (Closes: #730739)
+  * Correct architecture names for hurd and kfreebsd (Closes: #730738)
+  * Make libmesh.a install only in libfreefem++ binary
+  * Fix duplication of executables (Closes: #701161)
+  * Update standards version
+  * Set installation dir of WHERE* scripts to /usr/include/freefem++
+  * Add rdfind and symlinks to build deps in d/control
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Thu, 19 Dec 2013 22:38:49 +0200
+
+freefem++ (3.25-1) unstable; urgency=low
+
+  [ Dimitrios Eftaxiopoulos ]
+  * Imported Upstream version 3.25 (Closes: #701161 #706714)
+  * Change installation directory of header-like *.idp files
+    from /usr/lib/freefem++ to /usr/include/freefem++, in order
+    to fix a lintian warning
+  * Update patch to examples++-load/Makefile.am in order to enable
+    functioning of load *.so and include *.idp commands in *.edp
+    scripts
+  * Delete patches to src/Graphics/sansgraph.cpp and
+    src/Graphics/xglrgraph.cpp because they are not needed any more
+  * Fix lintian warning about missing LDFLAGS
+  * Override dh_auto_test in debian/rules, such that in case it is 
+    used, it completes executing all *.edp example files, regardless
+    of aborting on some of them
+  * Add libmetis-dev to build-deps in d/control
+  * Remove libparmetis-dev from build deps
+  * Add --parallel option to dh $@ in debian/rules
+  * Add hardening compilation flags to mpic++
+  * Allow testing of compiling and running the example files after build
+
+  [ Christophe Trophime ]
+  * update C. Trophime email
+  * add support for nlopt, ipopt - simplify debian/rules
+  * upload CT changes to 3.20
+  * add patch for configure
+  * add patch for examples++-mpi
+  * fix bamg install
+  * add corrected scripts to build plugins
+  * add patch for properly build examples++-load
+  * add lintian overrides for libfreefem++
+  * add some missing files
+  * update patches
+  * update rules
+  * reorder BuildDepends - comment out unsupported libs
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Thu, 12 Sep 2013 00:02:58 +0300
+
+freefem++ (3.20-1) experimental; urgency=low
+
+  * New upstream release.
+  * Add libnlopt-dev and coinor-libipopt-dev to build-deps.
+  * Update patch examples++-load-Makefile.patch.
+  * Remove patch examples-load-WHERE-LIBRARY.patch.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Thu, 18 Oct 2012 14:14:12 +0300
+
+freefem++ (3.19.1-1) unstable; urgency=low
+
+  * New upstream release.
+  * Make debian/compat=9.
+  * Make debhelper (>= 9~) in Build-Depends in debian/control.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Sun, 03 Jun 2012 22:16:18 +0300
+
+freefem++ (3.19-1) unstable; urgency=low
+
+  * New upstream release.
+  * Add libmumps-seq-dev to build-deps.
+  * Update standards version to 3.9.3.
+  * Fix FTBFS due to new g++-4.7 (Closes: #672612).
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Sun, 12 May 2012 03:59:00 +0200
+
+freefem++ (3.18.1-1) unstable; urgency=low
+
+  * New upstream release.
+  * Create new patch for documentation build.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Fri, 17 Feb 2012 21:29:00 +0200
+
+freefem++ (3.18-1) unstable; urgency=low
+
+  * New upstream release.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Sat, 4 Feb 2012 21:10:00 +0200
+
+freefem++ (3.17-2) unstable; urgency=low
+
+  * Fix build failure on hurd-i386 architecture.
+  * Rename kfreebsd.patch to examples++-load-load-link-in.patch and ammend it.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Thu, 29 Dec 2011 16:31:00 +0200
+
+freefem++ (3.17-1) unstable; urgency=low
+
+  * New upstream release.
+  * Add build-deps for libgmm++-dev.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Sun, 27 Nov 2011 14:17:00 +0200
+
+freefem++ (3.14-1) unstable; urgency=low
+
+  * Add build-deps for mumps_ptscotch, mumps_scotch and hypre.
+  * Change build-dep libfltk1.1-dev to libfltk1.3-dev | libfltk-dev in debian/
+    control file.
+  * New upstream release.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Wed, 14 Sep 2011 19:11:00 +0300
+
+freefem++ (3.13.3-1) unstable; urgency=low
+
+  * Add patch for the location of file freefem++.pref.
+  * New upstream release.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Tue, 9 Aug 2011 15:31:00 +0300
+
+freefem++ (3.13.2-1) unreleased; urgency=low
+
+  * Revert to gcc-4.6 for building.
+  * New upstream release.
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Sun, 3 Jul 2011 21:51:00 +0300
+
+freefem++ (3.13-2) unstable; urgency=low
+
+  * Change build-dep from openmpi-bin to mpi-default-dev to effect build on 
+    more arches.
+  * Apply patch kfreebsd.patch to fix build failure on kfreebsd arches.
+  * Rename /usr/bin/bamg to /usr/bin/ffbamg to fix double occurence of the 
+    former, in both rheolef and freefem++ packages (Closes: #630864).
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Mon, 20 Jun 2011 23:00:00 +0200
+
+freefem++ (3.13-1) unstable; urgency=low
+
+  * Initial release (Closes: #500755).
+  * Built with gcc-4.5 (see bug report 49264 submitted to the gcc bugzilla 
+    upstream).
+
+ -- Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>  Mon, 13 Jun 2011 11:10:00 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..dfcb8f4
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,119 @@
+Source: freefem++
+Section: science
+Priority: optional
+Maintainer: Debian Science Maintainers <debian-science-maintainers at lists.alioth.debian.org>
+Uploaders: Christophe Trophime <christophe.trophime at lncmi.cnrs.fr>, 
+ Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>
+Build-Depends: debhelper (>= 9~), dh-autoreconf, libsuperlu-dev,
+ quilt, gawk, gfortran, rdfind, symlinks,
+ flex, bison, libxt-dev, libxext-dev, libxxf86vm-dev, 
+ libxpm-dev, libmumps-scotch-dev, libmumps-ptscotch-dev,
+ libfltk1.3-dev | libfltk-dev, freeglut3-dev, ghostscript, imagemagick,
+ texlive, texlive-extra-utils, texlive-latex-extra, texlive-font-utils, 
+ libfftw3-dev, libgsl0-dev,
+ libhypre-dev, 
+ libarpack2-dev, libsuitesparse-dev,
+ libmumps-dev, libblacs-mpi-dev, libscalapack-mpi-dev,
+ libscotch-dev, libptscotch-dev,
+ libmetis-dev,
+ libmumps-seq-dev, 
+ libnlopt-dev, 
+ coinor-libipopt-dev,
+ libgmm++-dev
+# libtet1.4-dev,
+# libmmg3dlib4.0-4.0-dev, freeyams, mshmet, mshint,
+# libparms2-dev, libitsol-dev,
+# libhips-dev, libpastix-dev,
+# libsuperlu-dist-dev
+Standards-Version: 3.9.6
+Homepage: http://www.freefem.org/ff++/
+Vcs-Git: git://anonscm.debian.org/debian-science/packages/freefempp.git
+Vcs-Browser: http://anonscm.debian.org/gitweb/?p=debian-science/packages/freefempp.git
+
+Package: freefem++
+Architecture: any
+Section: math
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Provides the binaries of the FreeFem++ FE suite
+ FreeFem++ is an implementation of a language dedicated to the finite
+ element method. It enables you to solve Partial Differential
+ Equations (PDE) easily.
+ .
+ Problems involving PDE from several branches of physics such as
+ fluid-structure interactions require interpolations of data on
+ several meshes and their manipulation within one program. FreeFem++
+ includes a fast quadtree-based interpolation algorithm and a language
+ for the manipulation of these data on multiple meshes. It contains
+ also a powerful mesh generation and adaption tool integrated
+ seamlessly in FreeFem++ called bamg.
+ .
+ FreeFem++ is written in C++ and the FreeFem++ language is a C++ idiom
+ allowing for a smooth learning curve.
+ .
+ This package contains the executables of FreeFem++.
+
+Package: libfreefem++
+Architecture: any
+Section: libs
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Provides the shared libraries of the FreeFem++ FE suite
+ FreeFem++ is an implementation of a language dedicated to the finite
+ element method. It enables you to solve Partial Differential
+ Equations (PDE) easily.
+ .
+ Problems involving PDE from several branches of physics such as
+ fluid-structure interactions require interpolations of data on
+ several meshes and their manipulation within one program. FreeFem++
+ includes a fast quadtree-based interpolation algorithm and a language
+ for the manipulation of these data on multiple meshes. It contains
+ also a powerful mesh generation and adaption tool integrated
+ seamlessly in FreeFem++ called bamg.
+ .
+ FreeFem++ is written in C++ and the FreeFem++ language is a C++ idiom
+ allowing for a smooth learning curve.
+ .
+ This package contains the shared libraries of FreeFem++.
+
+Package: libfreefem++-dev
+Architecture: any
+Section: libdevel
+Depends: libfreefem++, ${shlibs:Depends}, ${misc:Depends}
+Description: Provides the development files of the FreeFem++ FE suite
+ FreeFem++ is an implementation of a language dedicated to the finite
+ element method. It enables you to solve Partial Differential
+ Equations (PDE) easily.
+ .
+ Problems involving PDE from several branches of physics such as
+ fluid-structure interactions require interpolations of data on
+ several meshes and their manipulation within one program. FreeFem++
+ includes a fast quadtree-based interpolation algorithm and a language
+ for the manipulation of these data on multiple meshes. It contains
+ also a powerful mesh generation and adaption tool integrated
+ seamlessly in FreeFem++ called bamg.
+ .
+ FreeFem++ is written in C++ and the FreeFem++ language is a C++ idiom
+ allowing for a smooth learning curve.
+ .
+ This package contains the development files of FreeFem++.
+
+Package: freefem++-doc
+Architecture: all
+Section: doc
+Depends: ${misc:Depends}
+Description: Provides the documentation of the FreeFem++ FE suite
+ FreeFem++ is an implementation of a language dedicated to the finite
+ element method. It enables you to solve Partial Differential
+ Equations (PDE) easily.
+ .
+ Problems involving PDE from several branches of physics such as
+ fluid-structure interactions require interpolations of data on
+ several meshes and their manipulation within one program. FreeFem++
+ includes a fast quadtree-based interpolation algorithm and a language
+ for the manipulation of these data on multiple meshes. It contains
+ also a powerful mesh generation and adaption tool integrated
+ seamlessly in FreeFem++ called bamg.
+ .
+ FreeFem++ is written in C++ and the FreeFem++ language is a C++ idiom
+ allowing for a smooth learning curve. 
+ .
+ This package contains the documentation files of FreeFem++. 
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..138c22b
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,93 @@
+Files: *
+
+Copyright:
+
+    (C) 2010 Frederic Hecht, Olivier Pironneau, Antoine Le Hyaric    
+
+License:
+
+     All programs may be redistributed under the terms of the
+     GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999.
+     See /usr/share/common-licenses/LGPL-2.1
+
+Excepted are the following files which have their own licences:
+
+
+Files: src/lglib/lg.tab.cpp
+       src/lglib/lg.tab.hpp
+
+Copyright: 
+
+    (C) 2006, Free Software Foundation
+
+Licence:
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+    See /usr/share/common-licenses/GPL-2
+
+
+Files: src/Algo
+
+Copyright: 
+
+    (C) 2003, Lydia Deng, Wences Gouveia
+
+Licence:
+
+    The COOOL library is a free software. You can do anything you want
+    with it including make a fortune.  However, neither the authors,
+    the Center for Wave Phenomena, nor anyone else you can think of
+    makes any guarantees about anything in this package or any aspect
+    of its functionality.
+
+    Since you've got the source code you can also modify the
+    library to suit your own purposes. We would appreciate it 
+    if the headers that identify the authors are kept in the 
+    source code.
+
+
+Files: src/fflib/mt19937ar.cpp 
+
+Copyright:
+    
+    (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+    All rights reserved.
+
+Licence: 
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions
+    are met:
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+    3. Neither the name of the University nor the names of its contributors
+       may be used to endorse or promote products derived from this software
+       without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+    SUCH DAMAGE.
+
+
+The Debian packaging is:
+
+    Copyright (C) 2010 Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>
+                  2009-2010 Cristophe Trophime <christophe.trophime at grenoble.cnrs.fr>
+                  2006-2010 Christophe Prud'homme <prudhomm at debian.org> 
+
+    and is licensed under the GPL version 3. See /usr/share/common-licenses/GPL-3.
+
diff --git a/debian/cvmsh2.1 b/debian/cvmsh2.1
new file mode 100644
index 0000000..7d7cde9
--- /dev/null
+++ b/debian/cvmsh2.1
@@ -0,0 +1,66 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH CVMSH2 1 "January 3, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+cvmsh2 \- a 2D mesh converter
+.SH SYNOPSIS
+.B cvmsh2
+.RI "Inmeshfile  OutBdmeshfile  [-g OutGeomfile ] [ -thetamax theta ] [ -v level ]"
+.br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B cvmsh2
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBcvmsh2\fP is a converter of 2d meshes. It accepts .am_fmt, .amdba, .am, .nopo, .msh, .ftq + bd mesh types as input and converts them to .am_fmt, .amdba, .am, .nopo, .msh, .ftq + bd output types. It is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM).
+.SH OPTIONS
+A summary of options is included below.
+.br
+.\".B \-h, \-\-help
+.B \-thetamax  theta : theta is the angular limit for smooth curve in degrees
+.br 
+.B \-v  level :  level is the level of verbosity in the range [0..99] 0 => no message, 99 too many
+.\" .br
+.\" .B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.\" .br
+.\" .B \-glut  command  :  the command name of glut (default is ffglut)
+.\" .br
+.\" .B \-nowait  :  do not wait after launching a window
+.\" .br
+.\" .B \-wait  :  wait after launching a window
+.\" .br
+.\" .B \-nw  :  no ffglut (=> no graphics windows)
+.\" .br
+.\" .B \-ne  :  no edp script output
+.\" .br
+.\" .B \-cd  :  change dir to script dir
+.\" .BR 
+.\" .TP
+.\" .SH SEE ALSO
+.\" .BR FreeFem++-x11 (1),
+.\" .BR FreeFem++-nw (1),
+.\" .BR FreeFem++-glx (1),
+.\" .BR FreeFem++-mpi
+.br
+.SH AUTHOR
+FreeFem++ was written by Frédéric Hecht<hecht at ann.jussieu.fr>.
+.PP
+This manual page was created by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..a0a7f2c
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,7 @@
+0ldUserReadMe.txt
+BUGS
+NEWS
+README
+README_ARPACK
+README_WINDOWS
+TODO
diff --git a/debian/drawbdmesh.1 b/debian/drawbdmesh.1
new file mode 100644
index 0000000..f4bbfa0
--- /dev/null
+++ b/debian/drawbdmesh.1
@@ -0,0 +1,61 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH DRAWBDMESH 1 "January 3, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+drawbdmesh \- a two - dimensional mesh viewer
+.SH SYNOPSIS
+.B bamg
+.\" .RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.\" .br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B drawbdmesh
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBdrawbdmesh\fP is a command for viewing a 2D mesh. It is associated with bamg, the mesh generator and iterpolator. drawbdmesh is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM).
+.\" .SH OPTIONS
+.\" A summary of options is included below.
+.\" .br
+.\" .\".B \-h, \-\-help
+.\" .B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.\" .br
+.\" .B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.\" .br
+.\" .B \-glut  command  :  the command name of glut (default is ffglut)
+.\" .br
+.\" .B \-nowait  :  do not wait after launching a window
+.\" .br
+.\" .B \-wait  :  wait after launching a window
+.\" .br
+.\" .B \-nw  :  no ffglut (=> no graphics windows)
+.\" .br
+.\" .B \-ne  :  no edp script output
+.\" .br
+.\" .B \-cd  :  change dir to script dir
+.BR 
+.TP
+.SH SEE ALSO
+.BR bamg (1)
+.br
+.SH AUTHOR
+drawbdmesh was written by Frédéric Hecht<hecht at ann.jussieu.fr>.
+.PP
+This manual page was created by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/ff-c++.1 b/debian/ff-c++.1
new file mode 100644
index 0000000..567a796
--- /dev/null
+++ b/debian/ff-c++.1
@@ -0,0 +1,65 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FF-C++ 1 "March 29, 2004"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+ff-c++ \- tool for automatic compilation with FreeFem++ library
+.SH SYNOPSIS
+.B ff-c++
+[\fIOPTIONS\fR] \fIFILE\fR \fI'LDFLAGS'\fR \fI'CPPFLAGS'\fR 
+The following extensions cpp,cp,cxx,c,f,F may be dropped in \fIFILE\fR.
+.SH DESCRIPTION
+.PP
+Compile FILE with freefem+ library with additionnal
+LDFLAGS and CPPFLAGS options
+.PP
+Mandatory arguments to long options are mandatory for short options too.
+.TP
+\fB\-auto\fR build automatically the dependence
+.TP
+\fB\-n\fR  do nothing just print
+.TP
+\fB\-g\fR  compile with \-g option
+.TP
+\fB\-c\fR compile only
+.TP
+\fB\-mpi\fR  with  mpi
+.TP
+\fB\-O*\fR  compile with \-O* option
+.TP
+\fB\-cygwin\fR compile for cygwin/win32 OS (Window XP, ...)
+.TP
+\fB\-win32\fR  compile for win32 OS (Window XP, ...) default under cygwin
+.TP
+\fB\-l\fR \fIfiles\fR  add files to the ld process (link)
+.TP
+\fB\-I\fR \fIdir\fR  add dir in include seach dir for compilation
+.TP
+\fB\-b\fR \fIdir\fR  to change the default install  dir 
+.TP
+\fB\-dll\fR \fIfile\fR  add  dll and this file copy in the install dir
+.TP
+\fB\-o\fR \fIoutputfile\fR without suffix
+.PP
+This manual page was written for the Debian distribution
+because the original program does not have a manual page.
+Instead, it has detailed documentation in the manual; see below.
+.SH SEE ALSO
+The extensive manual of FreeFem++ is written in LaTeX and it is available in
+Postscript format in /usr/share/doc/freefem++/ on your hard disc.
+.SH AUTHOR
+This manual page was written by Christophe Trophime <christophe.trophime at grenoble.cnrs.fr>,
+for the Debian project (but may be used by others).
\ No newline at end of file
diff --git a/debian/ff-get-dep.1 b/debian/ff-get-dep.1
new file mode 100644
index 0000000..b4ada3c
--- /dev/null
+++ b/debian/ff-get-dep.1
@@ -0,0 +1,45 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FREEFEM++ 1 "March 29, 2004"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+ff-get-dep \- tool to retreive dependence for compilation with FreeFem++ library
+.SH SYNOPSIS
+.B ff-get-dep
+[\fIOPTIONS\fR] \fIFILE\fR
+.SH DESCRIPTION
+.PP
+Reteive dependence needed to compile FILE with freefem+ library
+.PP
+Mandatory arguments to long options are mandatory for short options too.
+.TP
+\fB\-l*\fR
+.TP
+\fB\-dlib\fR
+.TP
+\fB\-dcpp\fR
+.TP
+\fB\-ff\fR
+.PP
+This manual page was written for the Debian distribution
+because the original program does not have a manual page.
+Instead, it has detailed documentation in the manual; see below.
+.SH SEE ALSO
+The extensive manual of FreeFem++ is written in LaTeX and it is available in
+Postscript format in /usr/share/doc/freefem++/ on your hard disc.
+.SH AUTHOR
+This manual page was written by Christophe Trophime <christophe.trophime at grenoble.cnrs.fr>,
+for the Debian project (but may be used by others).
\ No newline at end of file
diff --git a/debian/ff-mpirun.1 b/debian/ff-mpirun.1
new file mode 100644
index 0000000..ad53f78
--- /dev/null
+++ b/debian/ff-mpirun.1
@@ -0,0 +1,58 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FF-MPIRUN 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+ff-mpirun \- a tool for running jobs in parallel within FreeFem++
+.SH SYNOPSIS
+.B ff-mpirun
+.\" .RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.\" .br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B ff-mpirun
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBff-mpirun\fP is a script that facilitates the process of running jobs in parallel within FreeFem++. It is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). 
+.\" .SH OPTIONS
+.\" A summary of options is included below.
+.\" .br
+.\" .\".B \-h, \-\-help
+.\" .B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.\" .br
+.\" .B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.\" .br
+.\" .B \-glut  command  :  the command name of glut (default is ffglut)
+.\" .br
+.\" .B \-nowait  :  do not wait after launching a window
+.\" .br
+.\" .B \-wait  :  wait after launching a window
+.\" .br
+.\" .B \-nw  :  no ffglut (=> no graphics windows)
+.\" .br
+.\" .B \-ne  :  no edp script output
+.\" .br
+.\" .B \-cd  :  change dir to script dir
+.\" .BR 
+.\" .TP
+.SH AUTHOR
+ff-mpitun was written by Frédéric Hecht<hecht at ann.jussieu.fr>.
+.PP
+This manual page was created by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/ff-pkg-download.1 b/debian/ff-pkg-download.1
new file mode 100644
index 0000000..b14a356
--- /dev/null
+++ b/debian/ff-pkg-download.1
@@ -0,0 +1,35 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FF-PKG-DOWNLOAD 1 "March 29, 2004"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+ff-pkg-download \- tool to download package for building FreeFem++ loadable modules
+.SH SYNOPSIS
+.B ff-pkg-download
+[\fIOPTIONS\fR] \fIPACKAGE\fR
+.SH DESCRIPTION
+.PP
+Download \fIPACKAGE\fR to compile loadable module with freefem+ library
+.PP
+This manual page was written for the Debian distribution
+because the original program does not have a manual page.
+Instead, it has detailed documentation in the manual; see below.
+.SH SEE ALSO
+The extensive manual of FreeFem++ is written in LaTeX and it is available in
+Postscript format in /usr/share/doc/freefem++/ on your hard disc.
+.SH AUTHOR
+This manual page was written by Christophe Trophime <christophe.trophime at grenoble.cnrs.fr>,
+for the Debian project (but may be used by others).
\ No newline at end of file
diff --git a/debian/ffbamg.1 b/debian/ffbamg.1
new file mode 100644
index 0000000..1e14670
--- /dev/null
+++ b/debian/ffbamg.1
@@ -0,0 +1,58 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH BAMG 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+bamg \- a two - dimensional anisotropic mesh generator and interpolator
+.SH SYNOPSIS
+.B bamg
+.\" .RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.\" .br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B bamg
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBbamg\fP generates two - dimensional anisotropic meshes and interpolates finite element functions on them. A detailed documentation for bamg can be found at http://www.ann.jussieu.fr/hecht/ftp/bamg/bamg.pdf. It is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). 
+.\" .SH OPTIONS
+.\" A summary of options is included below.
+.\" .br
+.\" .\".B \-h, \-\-help
+.\" .B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.\" .br
+.\" .B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.\" .br
+.\" .B \-glut  command  :  the command name of glut (default is ffglut)
+.\" .br
+.\" .B \-nowait  :  do not wait after launching a window
+.\" .br
+.\" .B \-wait  :  wait after launching a window
+.\" .br
+.\" .B \-nw  :  no ffglut (=> no graphics windows)
+.\" .br
+.\" .B \-ne  :  no edp script output
+.\" .br
+.\" .B \-cd  :  change dir to script dir
+.\" .BR 
+.\" .TP
+.SH AUTHOR
+Bamg was written by Frédéric Hecht<hecht at ann.jussieu.fr>.
+.PP
+This manual page was created by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/ffglut.1 b/debian/ffglut.1
new file mode 100644
index 0000000..cb89edc
--- /dev/null
+++ b/debian/ffglut.1
@@ -0,0 +1,58 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FFGLUT 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+ffglut \- a visualisation tool, based on the GLUT library, used for viewing meshes and results within FreeFem++
+.SH SYNOPSIS
+.B ffglut
+.\" .RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.\" .br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B ffglut
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBffglut\fP command generates visualisation windows, with the help of the GLUT library, for viewing meshes and results within FreeFem++. It is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). 
+.\" .SH OPTIONS
+.\" A summary of options is included below.
+.\" .br
+.\" .\".B \-h, \-\-help
+.\" .B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.\" .br
+.\" .B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.\" .br
+.\" .B \-glut  command  :  the command name of glut (default is ffglut)
+.\" .br
+.\" .B \-nowait  :  do not wait after launching a window
+.\" .br
+.\" .B \-wait  :  wait after launching a window
+.\" .br
+.\" .B \-nw  :  no ffglut (=> no graphics windows)
+.\" .br
+.\" .B \-ne  :  no edp script output
+.\" .br
+.\" .B \-cd  :  change dir to script dir
+.\" .BR 
+.\" .TP
+.SH AUTHOR
+ffglut was written by Frédéric Hecht<hecht at ann.jussieu.fr>.
+.PP
+This manual page was created by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/ffmedit.1 b/debian/ffmedit.1
new file mode 100644
index 0000000..7ecfc21
--- /dev/null
+++ b/debian/ffmedit.1
@@ -0,0 +1,58 @@
+.\"                                      Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH FF-MEDIT 1 "January 2, 2011"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh        disable hyphenation
+.\" .hy        enable hyphenation
+.\" .ad l      left justify
+.\" .ad b      justify to both left and right margins
+.\" .nf        disable filling
+.\" .fi        enable filling
+.\" .br        insert line break
+.\" .sp <n>    insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+ff-medit \- a tool that runs Medit adapted to FreeFem++
+.SH SYNOPSIS
+.B ff-medit
+.\" .RI "[ -v  verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw ] [ -f ] script.edp"
+.\" .br
+.SH DESCRIPTION
+This manual page documents briefly the scope of the 
+.B ff-medit
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBff-medit\fP command runs Medit for viewing meshes and results related to FreeFem++. Medit is a 3d mesh visualisation tool. A detailed documentation for Medit can be found at http://www.ann.jussieu.fr/~frey/publications/RT-0253.pdf.ff-medit is part of the FreeFem++ suite which is used for the solution of Partial Differential Equations (PDE's) via the Finite Element Method (FEM). 
+.\" .SH OPTIONS
+.\" A summary of options is included below.
+.\" .br
+.\" .\".B \-h, \-\-help
+.\" .B \-v  verbosity : 0 -- 1000000 levels of FreeFem++ output
+.\" .br
+.\" .B \-fglut  filepath  :  the file name for saving all the plots (replot with ffglut command)
+.\" .br
+.\" .B \-glut  command  :  the command name of glut (default is ffglut)
+.\" .br
+.\" .B \-nowait  :  do not wait after launching a window
+.\" .br
+.\" .B \-wait  :  wait after launching a window
+.\" .br
+.\" .B \-nw  :  no ffglut (=> no graphics windows)
+.\" .br
+.\" .B \-ne  :  no edp script output
+.\" .br
+.\" .B \-cd  :  change dir to script dir
+.\" .BR 
+.\" .TP
+.SH AUTHOR
+Bamg was written by Pascal Frey<frey at ann.jussieu.fr>.
+.PP
+This manual page was created by Dimitrios Eftaxiopoulos <eftaxi12 at otenet.gr>,
+for the Debian project (and may be used by others).
\ No newline at end of file
diff --git a/debian/folder/freefem++-doc b/debian/folder/freefem++-doc
new file mode 100644
index 0000000..d6c60ae
--- /dev/null
+++ b/debian/folder/freefem++-doc
@@ -0,0 +1,10 @@
+Document: freefem++-doc
+Title: Debian FreeFem++ Manual
+Author: Frederic Hecht
+Abstract: This manual describes the usage
+ of the FreeFem++ suite for the solution of PDE's via the 
+ Finite Element method.
+Section: Science/Mathematics
+
+Format: PDF
+Files: /usr/share/doc/freefem++-doc/freefem++doc.pdf.gz
\ No newline at end of file
diff --git a/debian/freefem++-doc.docs b/debian/freefem++-doc.docs
new file mode 100644
index 0000000..d4f4542
--- /dev/null
+++ b/debian/freefem++-doc.docs
@@ -0,0 +1 @@
+#DOCS#
diff --git a/debian/freefem++-doc.install b/debian/freefem++-doc.install
new file mode 100644
index 0000000..46bdcab
--- /dev/null
+++ b/debian/freefem++-doc.install
@@ -0,0 +1,6 @@
+debian/tmp/usr/share/freefem++/freefem++doc.pdf usr/share/doc/freefem++-doc/
+debian/tmp/usr/share/freefem++/3.*/examples* usr/share/doc/freefem++/examples/
+examples-bamg usr/share/doc/freefem++/examples/
+examples++-load/*.cpp usr/share/doc/freefem++/plugins/
+examples++-load/*.hpp usr/share/doc/freefem++/plugins/
+debian/folder/freefem++-doc /usr/share/doc-base/
diff --git a/debian/freefem++.install b/debian/freefem++.install
new file mode 100644
index 0000000..dba26b5
--- /dev/null
+++ b/debian/freefem++.install
@@ -0,0 +1 @@
+debian/tmp/usr/bin/*
\ No newline at end of file
diff --git a/debian/freefem++.manpages b/debian/freefem++.manpages
new file mode 100644
index 0000000..871437d
--- /dev/null
+++ b/debian/freefem++.manpages
@@ -0,0 +1,14 @@
+debian/ffbamg.1
+debian/cvmsh2.1
+debian/drawbdmesh.1
+debian/ff-c++.1
+debian/ff-get-dep.1
+debian/ff-pkg-download.1
+debian/ff-mpirun.1
+debian/ffmedit.1
+debian/ffglut.1
+debian/FreeFem++.1
+debian/FreeFem++-glx.1
+debian/FreeFem++-mpi.1
+debian/FreeFem++-nw.1
+debian/FreeFem++-x11.1
\ No newline at end of file
diff --git a/debian/libfreefem++-dev.install b/debian/libfreefem++-dev.install
new file mode 100644
index 0000000..b02eae9
--- /dev/null
+++ b/debian/libfreefem++-dev.install
@@ -0,0 +1,3 @@
+debian/tmp/usr/lib/ff++/3.*/include/* usr/include/freefem++/
+debian/tmp/usr/lib/ff++/3.*/lib/*WHERE* usr/include/freefem++/
+debian/tmp/usr/lib/ff++/3.*/idp/* usr/include/freefem++/idp/
\ No newline at end of file
diff --git a/debian/libfreefem++.install b/debian/libfreefem++.install
new file mode 100644
index 0000000..6d56d69
--- /dev/null
+++ b/debian/libfreefem++.install
@@ -0,0 +1,3 @@
+debian/tmp/usr/lib/ff++/3.*/lib/*.so* usr/lib/freefem++/
+debian/tmp/usr/lib/ff++/3.*/etc/freefem++.pref etc/
+
diff --git a/debian/patches/configure.patch b/debian/patches/configure.patch
new file mode 100644
index 0000000..8affc91
--- /dev/null
+++ b/debian/patches/configure.patch
@@ -0,0 +1,25 @@
+Change the path name for finding the superlu libraries
+--- a/configure.ac
++++ b/configure.ac
+@@ -1653,8 +1653,8 @@
+ 	[[hypre],[-lHYPRE]],
+ 	[[fftw3],[-lfftw3],[/usr/include/fftw3.h],[]],
+ 	[[superlu_dist],[-lsuperlu-dist],[/usr/include/superlu-dist/superlu_defs.h],[]],
+-	[[superlu],[-lsuperlu],[/usr/include/superlu/superlu_enum_consts.h],[]],
+-	[[Superlu4],[-lsuperlu4],[/usr/include/superlu4/superlu_enum_consts.h],[]],
++	[[superlu],[-lsuperlu4],[/usr/include/superlu/superlu_enum_consts.h],[]],
++	[[superlu],[-lsuperlu4],[/usr/include/superlu/slu_ddefs.h],[]],
+         [[blacs],[ -lblacsCinit$ff_with_mpi	-lblacsF77init$ff_with_mpi	-lblacs$ff_with_mpi],[]],
+         [[scalapack],[-lscalapack$ff_with_mpi],[]],
+         [[scotch],[-lscotch -lscotcherr],[scotch.h]],
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -6,7 +6,7 @@
+ 
+ # $Id$
+ 
+-SUBDIRS=download src  examples++-tutorial examples++	\
++SUBDIRS=src  examples++-tutorial examples++	\
+ 	examples++-eigen examples++-load examples++-mpi	\
+ 	examples++-bug examples++-chapt3 examples++-other \
+ 	examples++-3d DOC 
diff --git a/debian/patches/examples++-load.patch b/debian/patches/examples++-load.patch
new file mode 100644
index 0000000..25f339c
--- /dev/null
+++ b/debian/patches/examples++-load.patch
@@ -0,0 +1,25 @@
+Ensure build on Hurd and kfreebsd arches and find header and library paths  
+--- a/examples++-load/Makefile.am
++++ b/examples++-load/Makefile.am
+@@ -212,8 +212,8 @@
+ 	  sed <$$i >$(DESTDIR)$(ff_prefix_dir)/lib/$$i 's#$(abs_top_builddir)/download#$(ff_prefix_dir)#' ;\
+ 	 done
+ 	echo loadpath += \"./\"  >$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
+-	echo loadpath += \"$(ff_prefix_dir)/lib\"  >>$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
+-	echo includepath += \"$(ff_prefix_dir)/idp\"  >>$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
++	echo loadpath += \"$(prefix)/lib/freefem++\"  >>$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
++	echo includepath += \"$(prefix)/include/freefem++/idp\"  >>$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
+ 	$(INSTALL_SCRIPT) ff-c++  $(DESTDIR)${bindir}
+ 	$(INSTALL_SCRIPT) ff-pkg-download  $(DESTDIR)${bindir}
+ 	$(INSTALL_SCRIPT) ff-get-dep   $(DESTDIR)${bindir}
+--- a/examples++-load/load.link.in
++++ b/examples++-load/load.link.in
+@@ -225,7 +225,7 @@
+         LIBS="'$b/libff.dll' $LIBS $DLL"
+ #        SUF=dll
+ 	;;
+-    FreeBSD|NetBSD)
++    FreeBSD|NetBSD|GNU|GNU/kFreeBSD)
+ 	SHARED="-shared" 
+ 	FLAGS='-fPIC';;
+ 	# 64 bit Linux needs -fPIC (ALH)
diff --git a/debian/patches/examples-bamg.patch b/debian/patches/examples-bamg.patch
new file mode 100644
index 0000000..7173499
--- /dev/null
+++ b/debian/patches/examples-bamg.patch
@@ -0,0 +1,9 @@
+Set proper path for perl executable
+--- a/examples-bamg/test/dotest.pl
++++ b/examples-bamg/test/dotest.pl
+@@ -1,4 +1,4 @@
+-#!/usr/local/bin/perl
++#!/usr/bin/perl
+ # -----  clean ---
+ unlink <*.mesh>;
+ unlink <*.am_fmt>;
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..7a03102
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,3 @@
+examples++-load.patch
+examples-bamg.patch
+configure.patch
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..68f3959
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,107 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+export DH_VERBOSE=1
+export DH_OPTIONS=-v
+
+# export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic
+# export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
+
+LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)
+
+
+%:
+	dh $@ --with autoreconf --parallel
+
+export OMPI_MCA_plm_rsh_agent=/bin/false                #workaround to start MPI-applications in chroot
+# 
+# # to avoid lintian warnings
+# CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS)
+# CFLAGS:=$(shell dpkg-buildflags --get CFLAGS)
+# CXXFLAGS:=$(shell dpkg-buildflags --get CXXFLAGS)
+# LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)
+# 
+ override_dh_auto_clean:
+	dh_auto_clean
+	rm -f config.log
+	rm -f config-version.h config_LIB_INFO configure.param
+	rm -f download/fftw/cxxflags
+	rm -f download/hips/config.log download/ipopt/config.log
+	rm -f download/metis/config.log download/metis/Makefile.in
+	rm -f download/mumps/config.log download/mumps-seq/config.log
+	rm -f download/parmetis/config.log
+	rm -f download/parms/config.log download/parms/Makefile.in
+	rm -f download/pastix/config-complex.in download/pastix/config.log
+	rm -f download/scalapack/config.log
+	rm -f download/scotch/config.log
+	rm -f download/superludist/config.log
+	rm -f download/tetgen/cxxflags
+	cd src && rm -f medit/compil.date mpi/config.log mpi/ff-mpirun \
+			lglib/lg.output
+	cd DOC && rm -f cpfigs/*.pdf addfe.aux freefem++doc.aux \
+			freefem++doc.idx freefem++doc.ilg freefem++doc.ind \
+			freefem++doc.log freefem++doc.out \
+			freefem++doc.pdfsync freefem++doc.toc
+	cd examples++-load && rm -f *.ps *.txt *.mesh glu2D.mesh.gmsh \
+					pippo.data pippo.dx triQA.msh \
+					freefem++.pref config.log \
+					WHERE_LIBRARY-config ipopt.out
+	cd examples++-tutorial && rm -f A.matrix *.ps *.txt g.mesh toto.Th \
+					*.gmsh toto.am_fmt toto.dbg lestables \
+					freefem++.pref Th*.msh emptymesh-2.msh \
+					th.msh toto.msh
+	rm -f examples++/toto.txt
+	cd examples++-3d && rm -f A.txt B.txt Th.mesh Th3.mesh dd.bb dd.meshb \
+					freefem++.pref
+	cd examples++-chapt3 && rm -f J.txt Th.mesh Th.msh graph.txt *.ps
+	cd examples++-mpi && rm -f beam-deformed-mumps.mesh *.ps \
+				   freefem++.pref *.so *.o
+
+# #
+# # To rebuild
+# 	find . -name \*.o | xargs --no-run-if-empty rm
+# 	find . -name \*.so | xargs --no-run-if-empty rm
+#
+ 
+override_dh_autoreconf_clean:
+	dh_autoreconf_clean
+	dh_quilt_unpatch
+
+override_dh_autoreconf:
+	dh_quilt_patch
+	dh_autoreconf --as-needed
+
+override_dh_auto_configure:
+	dh_auto_configure -- CC="gcc $(LDFLAGS)" CXX="g++ $(LDFLAGS)" \
+			MPICXX="mpic++ $(LDFLAGS)"
+# 	   CPPFLAGS=$(CPPFLAGS) \
+# 	   CFLAGS="$(CFLAGS) -lm" \
+# 	   CXXFLAGS="$(CXXFLAGS)" \
+# 	   CXX=mpic++
+# 	cp -f examples++-load/WHERE_LIBRARY-config debian
+# 	dh_auto_build
+ 
+override_dh_auto_install:
+	dh_auto_install
+	mv debian/tmp/usr/bin/bamg debian/tmp/usr/bin/ffbamg
+	rdfind -outputname debian/results.txt -makesymlinks true debian/tmp/usr/bin/
+	symlinks -r -s -c debian/tmp/usr/bin/
+
+# #
+# # Install modified script to create plugins	
+# 	cp examples++-load/WHERE_LIBRARY-config examples++-load/WHERE_LIBRARY
+# 	cp -f debian/ff-c++ debian/tmp/usr/bin
+# 	cp -f debian/ff-get-dep debian/tmp/usr/bin
+# #
+# # Fix lintian warnings
+# 	chmod ugo-x debian/tmp/usr/lib/ff++/3.*/idp/*.idp
+# 
+ 
+ override_dh_auto_test:
+#	$(MAKE) $(AM_MAKEFLAGS) -i check
\ No newline at end of file
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/options b/debian/source/options
new file mode 100644
index 0000000..8aa68ab
--- /dev/null
+++ b/debian/source/options
@@ -0,0 +1 @@
+ extend-diff-ignore = "(^|/)(examples\+\+-load/all\.edp|examples\+\+-3d/all\.edp|DOC/freefem\+\+doc\.pdf|download/gmm/cxxflags|src/fflib/strversionnumber\.cpp|download/nlopt/config\.log|examples\+\+-eigen/freefem\+\+\.pref|examples\+\+-load/Missing-plugins-so\.log|examples\+\+-load/WHERE_LIBRARY-download-new|examples\+\+/freefem\+\+\.pref|configure\.ac|examples\+\+-chapt3/freefem\+\+\.pref|examples\+\+-mpi/Missing-plugins-so\.log|download/pkg/MUMPS_4\.10\.0\.tar\.gz|download/fftw/Makefil [...]
\ No newline at end of file
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..0a0a28b
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,4 @@
+# Compulsory line, this is a version 3 file
+version=3
+opts="uversionmangle=s/-/./g" \
+  http://www.freefem.org/ff++/ftp/ freefem\+\+-(.+)\.tar\.gz
diff --git a/download/AUTHORS b/download/AUTHORS
new file mode 100644
index 0000000..015eaa9
--- /dev/null
+++ b/download/AUTHORS
@@ -0,0 +1,10 @@
+Library mmg3d, 
+Authors: 
+  -- Dobrzynski C�cile <cecile.dobrzynski at math.u-bordeaux1.fr>
+  -- Frey Pascal <frey at ann.jussieu.fr>
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+The licence will be CeCILL-C (see http://www.cecill.info/ for more detail.) 
+
diff --git a/download/Makefile.am b/download/Makefile.am
new file mode 100755
index 0000000..1e89643
--- /dev/null
+++ b/download/Makefile.am
@@ -0,0 +1,191 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+# $Id: Makefile.am,v 1.16 2010/05/06 21:20:38 hecht Exp $
+
+SUBDIRS=blas arpack umfpack  
+EXTRA_DIST= \
+./nlopt/Make.inc ./nlopt/Makefile \
+./blacs/BLACS.patch \
+./blacs/BLACS_gridinit_.c-return-values.patch \
+./blacs/Bmake-blacs.inc \
+./blacs/Makefile \
+./f2c/Makefile \
+./f2c/Makefile-MacOs \
+./f2c/f2c.h-int \
+./f2c/fort77.sed \
+./f2c/tt.f \
+./fftw/Makefile.am \
+./fftw/Makefile.in \
+./gmm/Makefile \
+./gmm/cxxflags \
+./headers-sparsesolver.inc \
+./hips/Makefile \
+./hips/SRC_SPKIT_makefile \
+./hips/hips-1.2b-rc4.patch \
+./hips/makefile-hips.inc \
+./hypre/Makefile \
+./hypre/ff-flags.inc \
+./metis/Makefile \
+./metis/Makefile-metis.in \
+./metis/patch-metis \
+./metis/metis-4.0_main_return.patch \
+./mmg3d/Makefile \
+./mmg3d/patch-mmg3dv4.diff \
+./mshmet/Makefile \
+./mshmet/Makefile-mshmet.inc \
+./mshmet/mshmet.2011.03.06.patch \
+./mshmet/mshmet.2012.04.25_i586.patch \
+./mshmet/mshmetlib-internal.h \
+./mshmet/mshmetlib.c \
+./mshmet/mshmetlib.h \
+./mumps/Makefile \
+./mumps-seq/Makefile-mumps-4.10.0.inc \
+./mumps-seq/Makefile \
+./mumps/Makefile-mumps-4.10.0.inc \
+./mumps/MUMPS_4.10.0.patch \
+./parmetis/Makefile-parmetis.in \
+./parmetis/makefile \
+./parmetis/parmetis-3.1.1.patch \
+./parms/Makefile \
+./parms/makefile-parms.in \
+./pastix/Makefile \
+./pastix/config-pastix-complex.in \
+./pastix/config-pastix-real.in \
+./pastix/pastix_release_2200-blend.patch \
+./pastix/patch-pastix_long_complex.h \
+./pastix//all_macros.diff \
+./scalapack/Makefile \
+./scalapack/SLmake-scalapack.inc \
+./scotch/Makefile \
+./scotch/Makefile-scotch.inc \
+./scotch/Makefile.patch \
+./scotch/scotch_5.1_esmumps.patch \
+./superlu/Makefile \
+./superlu/make.inc \
+./superludist/Makefile \
+./superludist/make-superlu.inc \
+./superludist/superludist_2.3.patch \
+./superludist/superludist_3.0-printf.patch \
+./superludist/superludist_3.0-cast_warning.patch \
+./superludist/superludist_3.0-return_values.patch \
+./superludist/superludist_3.0-operation_undefined.patch \
+./tetgen/Makefile \
+./tetgen/tetgen1.4.2.patch \
+./tetgen/patches.win64 \
+./yams/Makefile \
+./yams/freeyams.2012.02.05.patch \
+./yams/freeyams.2012.02.05-return-values.patch \
+./yams/makefile-yams.inc \
+./yams/yamslib.c \
+./yams/yamslib.h \
+./yams/yamslib_internal.h \
+ipopt/Makefile	\
+ipopt/Makefile.inc.in \
+ipopt/patch-IpBlas  \
+getall 
+
+# FFCS: See [[file:../../../configure.ac::tools_problems_all_platforms]] for reasons why some tools may be deactivated
+
+# <<no_more_blacs>> blacs is included in scalapack 2.0.2
+
+MPI_SOFT=@TOOL_COMPILE_parmetis@ scalapack @TOOL_COMPILE_superludist@	\
+	@TOOL_COMPILE_mumps@ @TOOL_COMPILE_pastix@			\
+	@TOOL_COMPILE_hips@ @TOOL_COMPILE_parms@
+
+LIST_SOFT=tetgen @TOOL_COMPILE_superlu@ fftw @TOOL_COMPILE_metis@	\
+	@TOOL_COMPILE_scotch@ @TOOL_COMPILE_mshmet@			\
+	@TOOL_COMPILE_yams@ @TOOL_COMPILE_mmg3d@ gmm			\
+	@TOOL_COMPILE_nlopt@ @TOOL_COMPILE_mumps_seq@			\
+	@TOOL_COMPILE_ipopt@ 
+
+all-recursive: bin lib include pkg
+
+lib: 
+	mkdir lib
+bin: 
+	mkdir bin
+include:
+	mkdir  include
+pkg:
+	mkdir pkg
+
+# ALH - /download/yams and /download/mshmet need /src/libMesh/libmesh.a but /src is compiled after /download, so we
+# need to compile it now
+
+lib/libMesh.a:lib include
+	cd ../src/libMesh && $(MAKE) $(AM_MAKEFLAGS)
+	test -f ../src/libMesh/libMesh.a
+	mkdir -p include/libMesh
+	cp ../src/libMesh/*h  include/libMesh
+	echo libMesh  LD -L at DIR@/lib -lMesh  > lib/WHERE.libMesh
+	echo libMesh INCLUDE -I at DIR@/include/libMesh >> lib/WHERE.libMesh
+	cp ../src/libMesh/libMesh.a lib/libMesh.a
+
+all-local:bin lib include lib/libMesh.a  pkg  $(DOWNLOADCOMPILE)  install-other
+
+install-other: tag-install-other
+
+tag-install-other:
+	test -n "$(TOOL_COMPILE_schwarz)" && $(MAKE) install-hpddm
+	touch tag-install-other
+
+WHERE-OTHER: lib/WHERE.hpddm
+WHERE-LD: tag-compile-pkg  WHERE-OTHER
+	touch ../examples++-load/WHERE_LIBRARY-config ../examples++-load/WHERE_LIBRARY		
+	grep LD ../examples++-load/WHERE_LIBRARY ../examples++-load/WHERE_LIBRARY-config >WHERE-LD
+install-hpddm:
+	 test -n "$(TOOL_COMPILE_schwarz)" && ./getall hpddm -a  && $(MAKE) include/hpddm-master  lib/WHERE.hpddm
+reinstall-hpddm:
+	-rm ../pkg/hpddm.zip 
+	-rm -rf include/hpddm-master
+	test -n "$(TOOL_COMPILE_schwarz)" && $(MAKE) install-hpddm
+include/hpddm-master:
+	-if test -f ../pkg/hpddm.zip ; then cd include; unzip ../pkg/hpddm.zip ; fi
+
+lib/WHERE.hpddm: 
+	if test -d include/hpddm-master ; then \
+	echo hpddm LD -L at DIR@/lib > $@ ;\
+	echo hpddm  INCLUDE -I at DIR@/include/hpddm-master/src >> $@ ;\
+	fi
+
+# FFCS: need to stop at the first error to make sure that all libraries are correctly compiled
+compile-dir: 
+	@echo "\n\n ****** $(COMPILEDIR) ****** \n\n";
+	@if [ 0 -eq `egrep ':$(COMPILEDIR)' WHERE-LD | wc -l` ] ;then \
+	  cd $(COMPILEDIR) && $(MAKE) $(DIRTARGET) ; \
+	else \
+	 echo $(COMPILEDIR) is in WHERE- files ;\
+	fi 
+compile-pkg: tag-compile-pkg WHERE-LD
+
+# FFCS: need to stop at the first error to make sure that all libraries are correctly compiled
+tag-compile-pkg: bin lib include pkg FORCE
+	@if [ -n "$(WGET)" ] ; then \
+	for d in $(LIST_SOFT) ; do $(MAKE) compile-dir COMPILEDIR=$$d || exit 1;done ;\
+	if [ -n "$(MPICC)" ] ; then \
+	for d in $(MPI_SOFT) ; do 	$(MAKE) compile-dir COMPILEDIR=$$d || exit 1; done;\
+	fi;fi
+	touch tag-compile-pkg
+FORCE:
+
+re-install: 
+	$(MAKE) compile-pkg DIRTARGET=install
+WHERE:
+	$(MAKE) compile-pkg DIRTARGET=WHERE 
+install-exec-local:	
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/lib
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/bin
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/include
+	cp -rp lib $(DESTDIR)$(ff_prefix_dir)
+	cp -rp include  $(DESTDIR)$(ff_prefix_dir)
+	cp -rp bin  $(DESTDIR)$(ff_prefix_dir)
+
+clean-local:
+	-rm -rf	 tag-* include lib bin 
+	-mkdir   include lib bin 	
+	-rm */FAIT */FAIRE 
+# 	FFCS - make sure that all directories are cleaned. Thisis especially important under Windows because there is no
+# 	compilation dependencies control there (see
+# 	[[file:c:/cygwin/home/alh/ffcs/dist/configure.ac::dependency_tracking]])
+	for d in $(LIST_SOFT) $(MPI_SOFT) ; do $(MAKE) clean -C $$d ; done
diff --git a/download/arpack/ARmake.m4 b/download/arpack/ARmake.m4
new file mode 100644
index 0000000..c8ce22f
--- /dev/null
+++ b/download/arpack/ARmake.m4
@@ -0,0 +1,140 @@
+# ARPACK ARmake.inc modified for FreeFem++
+# $Id$
+
+###########################################################################
+#
+#  Program:         ARPACK
+#
+#  Module:          ARmake.inc
+#
+#  Purpose:         Top-level Definitions
+#
+#  Creation date:   February 22, 1996
+#
+#  Modified:
+#
+#  Send bug reports, comments or suggestions to arpack at caam.rice.edu
+#
+############################################################################
+#
+# %---------------------------------%
+# |  SECTION 1: PATHS AND LIBRARIES |
+# %---------------------------------%
+#
+#
+# %--------------------------------------%
+# | You should change the definition of  |
+# | home if ARPACK is built some place   | 
+# | other than your home directory.      |
+# %--------------------------------------%
+#
+home = FF_HOME
+#
+#  %--------------------------------------%
+#  | The platform identifier to suffix to |
+#  | the end of library names             |
+#  %--------------------------------------%
+#
+PLAT = ff++
+#
+#  %------------------------------------------------------%
+#  | The directories to find the various pieces of ARPACK |
+#  %------------------------------------------------------%
+#
+BLASdir      = $(home)/BLAS
+LAPACKdir    = $(home)/LAPACK
+UTILdir      = $(home)/UTIL
+SRCdir       = $(home)/SRC
+#
+#DIRS        = $(BLASdir) $(LAPACKdir) $(UTILdir) $(SRCdir)
+#
+# %-------------------------------------------------------------------%
+# | Comment out the previous line and uncomment the following         |
+# | if you already have the BLAS and LAPACK installed on your system. |
+# | NOTE: ARPACK assumes the use of LAPACK version 2 codes.           |
+# %-------------------------------------------------------------------%
+#
+DIRS         = FF_LAPACKdir  $(UTILdir) $(SRCdir)
+#
+# %---------------------------------------------------%
+# | The name of the libraries to be created/linked to |
+# %---------------------------------------------------%
+#
+ARPACKLIB  = FF_ARPACKLIB
+LAPACKLIB  = FF_LAPACKLIB
+BLASLIB = FF_BLASLIB 
+#
+ALIBS =  $(ARPACKLIB) $(LAPACKLIB) $(BLASLIB) 
+#
+# 
+# %---------------------------------------------------------%
+# |                  SECTION 2: COMPILERS                   |
+# |                                                         |
+# | The following macros specify compilers, linker/loaders, |
+# | the archiver, and their options.  You need to make sure |
+# | these are correct for your system.                      |
+# %---------------------------------------------------------%
+#
+#
+# %------------------------------%
+# | Make our own suffixes' list. |
+# %------------------------------%
+#
+.SUFFIXES:
+.SUFFIXES:	.f	.o
+#
+# %------------------%
+# | Default command. |
+# %------------------%
+#
+.DEFAULT:
+	@$(ECHO) "Unknown target $@, try:  make help"
+#
+# %-------------------------------------------%
+# |  Command to build .o files from .f files. |
+# %-------------------------------------------%
+#
+.f.o:
+	@$(ECHO) Making $@ from $<
+	@$(FC) -c $(FFLAGS) $<
+#
+# %-----------------------------------------%
+# | Various compilation programs and flags. |
+# | You need to make sure these are correct |
+# | for your system.                        |
+# %-----------------------------------------%
+#
+FC      = FF_FC
+FFLAGS	= FF_FFLAGS
+LDFLAGS = FF_LDFLAGS
+SECOND_O = FF_SECOND
+CD      = cd
+
+ECHO    = echo
+
+LN      = ln
+LNFLAGS = -s
+
+MAKE    = make
+
+RM      = rm
+RMFLAGS = -f
+
+SHELL   = /bin/sh
+#
+#  %----------------------------------------------------------------%
+#  | The archiver and the flag(s) to use when building an archive   |
+#  | (library).  Also the ranlib routine.  If your system has no    |
+#  | ranlib, set RANLIB = touch.                                    |
+#  %----------------------------------------------------------------%
+#
+AR = FF_AR 
+ARFLAGS = FF_ARFLAGS
+RANLIB   = FF_RANLIB
+#
+# %----------------------------------%
+# | This is the general help target. |
+# %----------------------------------%
+#
+help:
+	@$(ECHO) "usage: make ?"
diff --git a/download/arpack/Makefile.am b/download/arpack/Makefile.am
new file mode 100644
index 0000000..2d043e4
--- /dev/null
+++ b/download/arpack/Makefile.am
@@ -0,0 +1,101 @@
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem make multipleauthors start=04/06/04 upmc brief="Makefile for downloaded ARPACK"
+
+all-local:$(DOWNLOAD_ARPACK)
+EXTRA_DIST=ARmake.m4 arpack-patch-lapack.tar.gz  veclib_zdotc.f
+
+PKGCOMMON_PACKTITLE=ARPACK
+include ../common.mak
+
+# nothing specific to do for [[file:../common.mak::reinstall]]
+
+reinstall::install
+
+# Downloading and compiling ARPACK
+# --------------------------------
+
+# set in configure 
+#ARPACKLIB=ARPACK/libarpack_ff++.a
+DIRPKG=../pkg
+ARPACK96_TAR_GZ=$(DIRPKG)/arpack96.tar.gz
+PATCH_TAR_GZ=$(DIRPKG)/patch.tar.gz
+
+PKGCOMMON_PACKAGES=$(ARPACK96_TAR_GZ) $(PATCH_TAR_GZ)
+
+# FFCS: need to add $(RANLIB) under mingw64 to avoid "archive has no index" error
+
+compilepkg::$(ARPACKLIB)
+$(ARPACKLIB): ARPACK/fait
+	case '$(BLASLIBS)' in *vecLib*|*Accelerate*) $(F77) -c $(FFLAGS) veclib_zdotc.f -o ARPACK/SRC/veclib_zdotc.o ;; esac; 
+	mkdir -p ../include ../lib
+	if [ -n '@FF_LAPACKdir@' ] ; then \
+	$(F77) -c `echo $(FFLAGS)\ |sed -e s/-O.\*\ // ` ARPACK/LAPACK/dlamch.f -o ARPACK/LAPACK/dlamch.o; \
+	fi; \
+	cd ARPACK && make lib 
+	if test -n '@FF_LAPACKdir@' ; then \
+	$(AR) $(ARFLAGS) $(LAPACK_arpack_LIB)  ARPACK/SRC/*.o  ARPACK/UTIL/*.o ARPACK/LAPACK/*.o ;\
+	$(RANLIB) $(LAPACK_arpack_LIB) ;\
+	else \
+	$(AR) $(ARFLAGS) $(ARPACKLIB)  ARPACK/SRC/*.o  ARPACK/UTIL/*.o ;\
+	fi
+
+ARPACK/fait: $(ARPACK96_TAR_GZ) $(PATCH_TAR_GZ) ARmake.m4 Makefile
+	-rm -rf ARPACK
+	gunzip -c $(ARPACK96_TAR_GZ) | tar xf -
+	gunzip -c $(PATCH_TAR_GZ) | tar xf -
+	gunzip -c arpack-patch-lapack.tar.gz | tar xf -
+	case '$(BLASLIBS)' in *vecLib*|*Accelerate*) \
+         for i in  ARPACK/LAPACK/zlatrs.f ARPACK/LAPACK/ztrsyl.f ARPACK/SRC/zgetv0.f ARPACK/SRC/znaitr.f ARPACK/SRC/znaup2.f ARPACK/SRC/zneupd.f;\
+	   do  mv  $$i $$i.cpy; sed -e 's/ZDOTC/ZZDOTC/' -e 's/zdotc/zzdotc/' <$$i.cpy >$$i;rm $$i.cpy; \
+	    done;; \
+	 esac 
+
+	for i in ARPACK/SRC/*.f ; do \
+	    mv  $$i $$i.cpy; sed -e 's/, second/, secnd2/' -e 's/call *second/call secnd2/' <$$i.cpy >$$i;rm $$i.cpy; done 
+	for i in  ARPACK/UTIL/second.f;  do  \
+	   mv  $$i $$i.cpy; cat $$i.cpy| sed 's/ SECOND *(/ secnd2(/'|grep -v EXTERNAL  >$$i;rm $$i.cpy; done 
+	m4  -DFF_BLASLIB="$(BLASLIB)" \
+	    -DFF_ARPACKLIB="$(ARPACKLIB)" \
+            -DFF_LAPACK_arpack_LIB="$(LAPACK_arpack_LIB)" \
+	    -DFF_FC="@F77@" \
+            -DFF_FFLAGS="@FFLAGS@" \
+	    -DFF_LAPACKdir='@FF_LAPACKdir@' \
+            -DFF_LDFLAGS="@LDFLAGS@" \
+            -DFF_HOME=`pwd`/ARPACK \
+	    -DFF_SECOND="@FF_SECOND@" \
+	    -DFF_AR="@AR@" \
+	    -DFF_ARFLAGS="@ARFLAGS@" \
+	    -DFF_RANLIB="@RANLIB@" \
+	    ARmake.m4 >ARPACK/ARmake.inc
+	touch ARPACK/fait
+
+$(ARPACK96_TAR_GZ) $(PATCH_TAR_GZ):
+	../getall -o ARPACK -a
+
+clean-local::
+	-rm -r ARPACK ../lib/libarpack.a
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/arpack/arpack-patch-lapack.tar.gz b/download/arpack/arpack-patch-lapack.tar.gz
new file mode 100644
index 0000000..5a9ce23
Binary files /dev/null and b/download/arpack/arpack-patch-lapack.tar.gz differ
diff --git a/download/arpack/veclib_zdotc.f b/download/arpack/veclib_zdotc.f
new file mode 100644
index 0000000..eb6662b
--- /dev/null
+++ b/download/arpack/veclib_zdotc.f
@@ -0,0 +1,36 @@
+      double complex function zzdotc(n,zx,incx,zy,incy)
+c
+c     forms the dot product of a vector.
+c     jack dongarra, 3/11/78.
+c     modified 12/3/93, array(1) declarations changed to array(*)
+c
+      double complex zx(*),zy(*),ztemp
+      integer i,incx,incy,ix,iy,n
+      ztemp = (0.0d0,0.0d0)
+      zzdotc = (0.0d0,0.0d0)
+      if(n.le.0)return
+      if(incx.eq.1.and.incy.eq.1)go to 20
+c
+c        code for unequal increments or equal increments
+c          not equal to 1
+c
+      ix = 1
+      iy = 1
+      if(incx.lt.0)ix = (-n+1)*incx + 1
+      if(incy.lt.0)iy = (-n+1)*incy + 1
+      do 10 i = 1,n
+        ztemp = ztemp + dconjg(zx(ix))*zy(iy)
+        ix = ix + incx
+        iy = iy + incy
+   10 continue
+      zzdotc = ztemp
+      return
+c
+c        code for both increments equal to 1
+c
+   20 do 30 i = 1,n
+        ztemp = ztemp + dconjg(zx(i))*zy(i)
+   30 continue
+      zzdotc = ztemp
+      return
+      end
diff --git a/download/blacs/BLACS.patch b/download/blacs/BLACS.patch
new file mode 100644
index 0000000..7749dfd
--- /dev/null
+++ b/download/blacs/BLACS.patch
@@ -0,0 +1,35 @@
+diff -ur BLACS/SRC/MPI/Makefile BLACS-okk/Makefile
+--- BLACS/SRC/MPI/Makefile	2010-02-16 13:29:39.000000000 +0100
++++ BLACS-okk/Makefile	2010-02-16 13:24:56.000000000 +0100
+@@ -86,7 +86,8 @@
+ 	rm -f $(BLACSFINIT) $(BLACSCINIT)
+ 	make $(BLACSFINIT)
+ 	make $(BLACSCINIT)
+-	$(ARCH) $(ARCHFLAGS) $(BLACSLIB) $(Fintobj) $(Cintobj)
++	cp INTERNAL/*.o .
++	$(ARCH) $(ARCHFLAGS) $(BLACSLIB) $(internal) $(Fintobj) $(Cintobj)
+ 	$(RANLIB) $(BLACSLIB)
+ 
+ $(BLACSFINIT) :
+@@ -110,7 +111,7 @@
+ 	( cd INTERNAL ; $(MAKE) -f ../Makefile I_int "dlvl=$(BTOPdir)" )
+ 
+ I_int : Bdef.h Bconfig.h $(internal)
+-	$(ARCH) $(ARCHFLAGS) $(BLACSLIB) $(internal)
++	#$(ARCH) $(ARCHFLAGS) $(BLACSLIB) $(internal)
+ 
+ Bdef.h : ../Bdef.h
+ 	rm -f Bdef.h
+@@ -196,9 +196,10 @@
+ bi_f77_mpi_testall.o : mpif.h bi_f77_mpi_testall.f
+ 	$(F77) -c $(F77FLAGS) $*.f
+ 
+-mpif.h : $(MPIINCdir)/mpif.h
++# FFCS: watch out for spaces and links under Windows. Also, make dependencies cannot contain spaces.
++mpif.h :
+ 	rm -f mpif.h
+-	ln -s $(MPIINCdir)/mpif.h mpif.h
++	cp $(MPIINCdir)/mpif.h mpif.h
+ 
+ #  ------------------------------------------------------------------------
+ #  We move C .o files to .C so that we can use the portable suffix rule for
diff --git a/download/blacs/BLACS_gridinit_.c-return-values.patch b/download/blacs/BLACS_gridinit_.c-return-values.patch
new file mode 100644
index 0000000..9bdd788
--- /dev/null
+++ b/download/blacs/BLACS_gridinit_.c-return-values.patch
@@ -0,0 +1,12 @@
+--- ./BLACS/SRC/MPI/blacs_gridinit_.c.orig	2013-01-27 12:42:38.712531484 +0000
++++ ./BLACS/SRC/MPI/blacs_gridinit_.c	2013-01-27 12:49:32.411131896 +0000
+@@ -35,4 +35,9 @@
+    blacs_gridmap_(ConTxt, tmpgrid, nprow, nprow, npcol);
+ #endif
+    free(tmpgrid);
++#if (INTFACE == C_CALL)
++   return 0;
++#else
++   return NULL;
++#endif
+ }
diff --git a/download/blacs/Bmake-blacs.inc b/download/blacs/Bmake-blacs.inc
new file mode 100644
index 0000000..8ee0c5c
--- /dev/null
+++ b/download/blacs/Bmake-blacs.inc
@@ -0,0 +1,236 @@
+abs_top_builddir=@abs_top_builddir@
+include $(abs_top_builddir)/download/headers-sparsesolver.inc
+#=============================================================================
+#====================== SECTION 0: FREEFEM++  ================================
+#=============================================================================
+#  The following macros specify the executable to download BLACS
+#=============================================================================
+WGET = @WGET@ 
+
+#=============================================================================
+#====================== SECTION 1: PATHS AND LIBRARIES =======================
+#=============================================================================
+#  The following macros specify the name and location of libraries required by
+#  the BLACS and its tester.
+#=============================================================================
+ 
+#  --------------------------------------
+
+#  Make sure we've got a consistent shell
+#  --------------------------------------
+   SHELL = /bin/sh
+
+#  -----------------------------
+#  The top level BLACS directory
+#  -----------------------------
+  BTOPdir = $(abs_top_builddir)/download/blacs/BLACS
+
+#  ---------------------------------------------------------------------------
+#  The communication library your BLACS have been written for.
+#  Known choices (and the machines they run on) are:
+#
+#     COMMLIB   MACHINE
+#     .......   ..............................................................
+#     CMMD      Thinking Machine's CM-5
+#     MPI       Wide variety of systems
+#     MPL       IBM's SP series (SP1 and SP2)
+#     NX        Intel's supercomputer series (iPSC2, iPSC/860, DELTA, PARAGON)
+#     PVM       Most unix machines; See PVM User's Guide for details
+#  ---------------------------------------------------------------------------
+   COMMLIB = MPI
+
+#  -------------------------------------------------------------
+#  The platform identifier to suffix to the end of library names
+#  -------------------------------------------------------------
+   PLAT = FREEFEM
+
+#  ----------------------------------------------------------
+#  Name and location of the BLACS library.  See section 2 for 
+#  details on BLACS debug level (BLACSDBGLVL).
+#  ----------------------------------------------------------
+   BLACSdir    = $(BTOPdir)/LIB
+   BLACSDBGLVL = 0
+   BLACSFINIT  = $(BLACSdir)/libblacsF77init_$(COMMLIB)-$(PLAT)-$(BLACSDBGLVL).a
+   BLACSCINIT  = $(BLACSdir)/libblacsCinit_$(COMMLIB)-$(PLAT)-$(BLACSDBGLVL).a
+   BLACSLIB    = $(BLACSdir)/libblacs_$(COMMLIB)-$(PLAT)-$(BLACSDBGLVL).a
+
+#  -------------------------------------
+#  Name and location of the MPI library.
+#  -------------------------------------
+   MPIdir = $(FFMPIDIR) 
+   MPIdev =  
+   MPIplat = 
+
+   # FFCS: Windows path to MPICH2 contains spaces, but FF configure --with-mpipath option should not contain quotes
+   # because FF configure adds quotes when defining MPI_LIB
+
+   MPILIBdir = '@MPI_LIB_DIRS@'
+   MPIINCdir = '@MPI_INC_DIR@'
+   MPILIB = @MPI_LIB@
+
+#  -------------------------------------
+#  All libraries required by the tester.
+#  -------------------------------------
+   BTLIBS = $(BLACSFINIT) $(BLACSLIB) $(BLACSFINIT) $(MPILIB) 
+
+#  ----------------------------------------------------------------
+#  The directory to put the installation help routines' executables
+#  ----------------------------------------------------------------
+   INSTdir = $(BTOPdir)/INSTALL/EXE
+
+#  ------------------------------------------------
+#  The name and location of the tester's executable
+#  ------------------------------------------------
+   TESTdir = $(BTOPdir)/TESTING/EXE
+   FTESTexe = $(TESTdir)/xFbtest_$(COMMLIB)-$(PLAT)-$(BLACSDBGLVL)
+   CTESTexe = $(TESTdir)/xCbtest_$(COMMLIB)-$(PLAT)-$(BLACSDBGLVL)
+#=============================================================================
+#=============================== End SECTION 1 ===============================
+#=============================================================================
+ 
+
+#=============================================================================
+#========================= SECTION 2: BLACS INTERNALS ========================
+#=============================================================================
+#  The following macro definitions set preprocessor values for the BLACS.
+#  The file Bconfig.h sets these values if they are not set by the makefile.
+#  User's compiling only the tester can skip this entire section.
+#  NOTE: The MPI defaults have been set for MPICH.
+#=============================================================================
+
+#  -----------------------------------------------------------------------
+#  The directory to find the required communication library include files, 
+#  if they are required by your system.
+#  -----------------------------------------------------------------------
+   SYSINC = -I$(MPIINCdir)
+
+#  ---------------------------------------------------------------------------
+#  The Fortran 77 to C interface to be used.  If you are unsure of the correct
+#  setting for your platform, compile and run BLACS/INSTALL/xintface.
+#  Choices are: Add_, NoChange, UpCase, or f77IsF2C.
+#  ---------------------------------------------------------------------------
+   INTFACE = @CFLAGSF77@ 
+
+#  ------------------------------------------------------------------------
+#  Allows the user to vary the topologies that the BLACS default topologies
+#  (TOP = ' ') correspond to.  If you wish to use a particular topology
+#  (as opposed to letting the BLACS make the choice), uncomment the
+#  following macros, and replace the character in single quotes with the
+#  topology of your choice.
+#  ------------------------------------------------------------------------
+#  DEFBSTOP   = -DDefBSTop="'1'"
+#  DEFCOMBTOP = -DDefCombTop="'1'"
+  DEFBSTOP   = $(FFDEFBSTOP) 
+  DEFCOMBTOP = $(FFDEFCOMBTOP)
+
+#  -------------------------------------------------------------------
+#  If your MPI_Send is locally-blocking, substitute the following line
+#  for the empty macro definition below.
+#  SENDIS = -DSndIsLocBlk
+#  -------------------------------------------------------------------
+  SENDIS = $(FFSENDIS)
+
+#  --------------------------------------------------------------------
+#  If your MPI handles packing of non-contiguous messages by copying to
+#  another buffer or sending extra bytes, better performance may be
+#  obtained by replacing the empty macro definition below with the
+#  macro definition on the following line.
+#  BUFF = -DNoMpiBuff
+#  --------------------------------------------------------------------
+  BUFF = $(FFBUFF)
+
+#  -----------------------------------------------------------------------
+#  If you know something about your system, you may make it easier for the
+#  BLACS to translate between C and fortran communicators.  If the empty
+#  macro defininition is left alone, this translation will cause the C
+#  BLACS to globally block for MPI_COMM_WORLD on calls to BLACS_GRIDINIT
+#  and BLACS_GRIDMAP.  If you choose one of the options for translating
+#  the context, neither the C or fortran calls will globally block.
+#  If you are using MPICH, or a derivitive system, you can replace the 
+#  empty macro definition below with the following (note that if you let
+#  MPICH do the translation between C and fortran, you must also indicate
+#  here if your system has pointers that are longer than integers.  If so,
+#  define -DPOINTER_64_BITS=1.)  For help on setting TRANSCOMM, you can
+#  run BLACS/INSTALL/xtc_CsameF77 and BLACS/INSTALL/xtc_UseMpich as
+#  explained in BLACS/INSTALL/README.
+#   TRANSCOMM = -DUseMpich
+#
+#  If you know that your MPI uses the same handles for fortran and C
+#  communicators, you can replace the empty macro definition below with
+#  the macro definition on the following line.
+#  TRANSCOMM = -DCSameF77
+#  -----------------------------------------------------------------------
+  TRANSCOMM =  $(FFTRANSCOMM)
+
+#  --------------------------------------------------------------------------
+#  You may choose to have the BLACS internally call either the C or Fortran77
+#  interface to MPI by varying the following macro.  If TRANSCOMM is left
+#  empty, the C interface BLACS_GRIDMAP/BLACS_GRIDINIT will globally-block if
+#  you choose to use the fortran internals, and the fortran interface will
+#  block if you choose to use the C internals.  It is recommended that the 
+#  user leave this macro definition blank, unless there is a strong reason
+#  to prefer one MPI interface over the other.
+#  WHATMPI = -DUseF77Mpi
+#  WHATMPI = -DUseCMpi
+#  --------------------------------------------------------------------------
+  WHATMPI = $(FFWHATMPI)
+
+#  ---------------------------------------------------------------------------
+#  Some early versions of MPICH and its derivatives cannot handle user defined
+#  zero byte data types.  If your system has this problem (compile and run
+#  BLACS/INSTALL/xsyserrors to check if unsure), replace the empty macro
+#  definition below with the macro definition on the following line.
+#  SYSERRORS = -DZeroByteTypeBug
+#  ---------------------------------------------------------------------------
+  SYSERRORS = $(FFSYSERRORS)
+
+#  ------------------------------------------------------------------
+#  These macros set the debug level for the BLACS.  The fastest
+#  code is produced by BlacsDebugLvl 0.  Higher levels provide
+#  more debug information at the cost of performance.  Present levels
+#  of debug are:
+#  0 : No debug information
+#  1 : Mainly parameter checking.
+#  ------------------------------------------------------------------
+   DEBUGLVL = -DBlacsDebugLvl=$(BLACSDBGLVL)
+
+#  -------------------------------------------------------------------------
+#  All BLACS definitions needed for compile (DEFS1 contains definitions used
+#  by all BLACS versions).
+#  -------------------------------------------------------------------------
+   DEFS1 = -DSYSINC $(SYSINC) $(INTFACE) $(DEFBSTOP) $(DEFCOMBTOP) $(DEBUGLVL)
+   BLACSDEFS = $(DEFS1) $(SENDIS) $(BUFF) $(TRANSCOMM) $(WHATMPI) $(SYSERRORS)
+#=============================================================================
+#=============================== End SECTION 2 ===============================
+#=============================================================================
+ 
+
+#=============================================================================
+#=========================== SECTION 3: COMPILERS ============================
+#=============================================================================
+#  The following macros specify compilers, linker/loaders, the archiver,
+#  and their options.  Some of the fortran files need to be compiled with no
+#  optimization.  This is the F77NO_OPTFLAG.  The usage of the remaining
+#  macros should be obvious from the names.
+#=============================================================================
+   F77            = @MPIF77@ #--prefix /Users/morice/librairie/openmpi-gcc-gfortran-4.4/
+   F77NO_OPTFLAGS =  @FNOFLAGS@
+   F77FLAGS       = @FFLAGS@
+   F77LOADER      = $(F77)
+   F77LOADFLAGS   = @FFLAGS@ @LDFLAGS@ 
+   CC             = @MPICC@ #--prefix /Users/morice/librairie/openmpi-gcc-gfortran-4.4/ 
+   CCFLAGS        = @CFLAGS@ #-fnested-functions
+   CCLOADER       = $(CC)
+   CCLOADFLAGS    = @LDFLAGS@ 
+
+#  --------------------------------------------------------------------------
+#  The archiver and the flag(s) to use when building an archive (library).
+#  Also the ranlib routine.  If your system has no ranlib, set RANLIB = echo.
+#  --------------------------------------------------------------------------
+  ARCH      =  @AR@  #ar
+  ARCHFLAGS =  @ARFLAGS@   #rs
+  RANLIB    =  @RANLIB@
+
+#=============================================================================
+#=============================== End SECTION 3 ===============================
+#=============================================================================
diff --git a/download/blacs/Makefile b/download/blacs/Makefile
new file mode 100644
index 0000000..cd46685
--- /dev/null
+++ b/download/blacs/Makefile
@@ -0,0 +1,93 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+# $Id$
+include Bmake.inc
+
+all-local: blacs 
+
+# Downloading and compiling BLACS
+# ------------------------------
+# http://www.netlib.org/blacs/
+# Hips information
+DIRPKG=../pkg
+SRCDIR=BLACS
+PACKAGE1=$(DIRPKG)/mpiblacs.tgz
+PACKAGE2=$(DIRPKG)/mpiblacs-patch03.tgz
+PACKAGE3=$(DIRPKG)/blacstester.tgz
+SERVER=http://www.netlib.org/blacs/
+INSTALL=../..
+
+SYSERRORS = 
+
+blacs:FAIRE
+
+
+FAIRE:$(SRCDIR)/FAIT
+	$(MAKE) WHERE
+	touch FAIRE
+
+Bmake.inc: ../../config.status	Makefile Bmake-blacs.inc
+	../../config.status  --file="Bmake.inc1:Bmake-blacs.inc"
+	sed s/-DAdd__/-Df77IsF2C/ <Bmake.inc1 >Bmake.inc
+	rm Bmake.inc1
+
+# FFCS: make sure that this makefile fails if the BLACS do not compile. But run links2files when the compilation fails because of
+# a symbolic link (under Windows). Repeat it only by hand to avoid infinite loops!
+$(SRCDIR)/FAIT: $(SRCDIR)
+#	cd $(SRCDIR)/INSTALL/;$(MAKE) xintface xsyserrors xcmpi_sane xfmpi_sane xtc_CsameF77 xtc_UseMpich
+	-cd $(SRCDIR) && $(MAKE) mpi
+	../../../../build/links2files
+	-cd $(SRCDIR) && $(MAKE) mpi
+	../../../../build/links2files
+	cd $(SRCDIR) && $(MAKE) mpi
+	touch $(SRCDIR)/FAIT
+
+WHERE: 
+	-if [ -f $(SRCDIR)/FAIT ] ; then \
+	make install;  \
+	echo blacs LD -L at DIR@/lib/blacs -lblacs_MPI-FREEFEM-0 	-lblacsF77init_MPI-FREEFEM-0	-lblacsCinit_MPI-FREEFEM-0  -lblacs_MPI-FREEFEM-0  >$(SRCDIR)/$(INSTALL)/lib/WHERE.blacs ;\
+	fi
+
+install: $(SRCDIR)/FAIT
+	mkdir -p $(SRCDIR)/$(INSTALL)/lib/blacs
+	cp $(SRCDIR)/LIB/*.a $(SRCDIR)/$(INSTALL)/lib/blacs/
+
+# FFCS: some files in the untarred archives are symbolic links that need to be converted for MinGW compilers
+$(SRCDIR): $(PACKAGE1) $(PACKAGE2) $(PACKAGE3)
+	gunzip -c $(PACKAGE1) | tar xvf -
+	gunzip -c $(PACKAGE2) | tar xvf -
+	gunzip -c $(PACKAGE3) | tar xvf -
+	patch -p0 < BLACS_gridinit_.c-return-values.patch
+	cd $(SRCDIR)/SRC/MPI; patch -p1 < ../../../BLACS.patch
+	cp Bmake.inc $(SRCDIR)
+	mv $(SRCDIR)/SRC/MPI/Makefile $(SRCDIR)/SRC/MPI/Makefile.tmp
+	sed -e 's;\.C;\.oo;g'  -e 's@: $$(MPIINCdir)/mpif.h@:@' \
+	< $(SRCDIR)/SRC/MPI/Makefile.tmp \
+	> $(SRCDIR)/SRC/MPI/Makefile
+	../../../../build/links2files
+	touch $(SRCDIR)
+
+$(PACKAGE1):
+	-mkdir $(DIRPKG)
+	cd $(DIRPKG);$(WGET)  $(SERVER)/`basename $(PACKAGE1)`
+
+$(PACKAGE2):
+	-mkdir $(DIRPKG)
+	cd $(DIRPKG);$(WGET) $(SERVER)/`basename $(PACKAGE2)`
+
+$(PACKAGE3):
+	-mkdir $(DIRPKG)
+	cd $(DIRPKG);$(WGET) $(SERVER)/`basename $(PACKAGE3)`
+
+# FFCS: only run make clean if cd to SRCDIR worked, otherwise this is an infinite loop.
+clean-local:
+	-cd $(SRCDIR)/SRC/MPI &&  $(MAKE) clean -C $(SRCDIR)/SRC/MPI
+	-rm Bmake.inc FAIRE
+	-rm $(SRCDIR)/$(INSTALL)/lib/blacs/*.a
+	-rm -rf $(SRCDIR)
+
+clean: clean-local
+
+
+.PHONY:$(SRCDIR)/$(INSTALL)  compile install
\ No newline at end of file
diff --git a/download/blas/Makefile.am b/download/blas/Makefile.am
new file mode 100644
index 0000000..dff37b9
--- /dev/null
+++ b/download/blas/Makefile.am
@@ -0,0 +1,188 @@
+# Downloading and compiling extra BLAS libraries
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh brief="Downloading and compiling extra BLAS libraries" default=0 freefem make multipleauthors start=04/06/04 upmc
+
+DIRPKG=../pkg
+BLAS_TGZ=$(DIRPKG)/blas.tgz
+CBLAS_TGZ=$(DIRPKG)/cblas.tgz
+
+PKGCOMMON_PACKTITLE=BLAS
+PKGCOMMON_PACKAGES=$(BLAS_TGZ) $(CBLAS_TGZ) ../pkg/OpenBLAS.tar.gz
+include ../common.mak
+
+EXTRA_DIST= \
+openblas.patches 
+
+# Downloading and compiling the Generic Blas
+# ------------------------------------------
+
+noinst_LIBRARIES=@DOWNLOADED_BLAS@
+##compile::$(noinst_LIBRARIES)
+EXTRA_LIBRARIES=libf77blas.a libcblas.a
+pkgcompile::@DOWNLOADED_BLAS@
+
+# List of files to compile (do not list them in *_SOURCES to prevent them from being included in distributions).
+
+F77BLAS_SOURCES=BLAS/caxpy.f BLAS/crotg.f BLAS/dcopy.f BLAS/dsymv.f BLAS/lsame.f BLAS/sspmv.f BLAS/zaxpy.f BLAS/zhpr2.f	\
+BLAS/ccopy.f BLAS/cscal.f BLAS/ddot.f BLAS/dsyr2.f BLAS/sasum.f BLAS/sspr2.f BLAS/zcopy.f BLAS/zhpr.f BLAS/cdotc.f	\
+BLAS/csrot.f BLAS/dgbmv.f BLAS/dsyr2k.f BLAS/saxpy.f BLAS/sspr.f BLAS/zdotc.f BLAS/zrotg.f BLAS/cdotu.f BLAS/csscal.f	\
+BLAS/dgemm.f BLAS/dsyr.f BLAS/scasum.f BLAS/sswap.f BLAS/zdotu.f BLAS/zscal.f BLAS/cgbmv.f BLAS/cswap.f BLAS/dgemv.f	\
+BLAS/dsyrk.f BLAS/scnrm2.f BLAS/ssymm.f BLAS/zdrot.f BLAS/zswap.f BLAS/cgemm.f BLAS/csymm.f BLAS/dger.f BLAS/dtbmv.f	\
+BLAS/scopy.f BLAS/ssymv.f BLAS/zdscal.f BLAS/zsymm.f BLAS/cgemv.f BLAS/csyr2k.f BLAS/dnrm2.f BLAS/dtbsv.f BLAS/sdot.f	\
+BLAS/ssyr2.f BLAS/zgbmv.f BLAS/zsyr2k.f BLAS/cgerc.f BLAS/csyrk.f BLAS/drot.f BLAS/dtpmv.f BLAS/sdsdot.f BLAS/ssyr2k.f	\
+BLAS/zgemm.f BLAS/zsyrk.f BLAS/cgeru.f BLAS/ctbmv.f BLAS/drotg.f BLAS/dtpsv.f BLAS/sgbmv.f BLAS/ssyr.f BLAS/zgemv.f	\
+BLAS/ztbmv.f BLAS/chbmv.f BLAS/ctbsv.f BLAS/drotm.f BLAS/dtrmm.f BLAS/sgemm.f BLAS/ssyrk.f BLAS/zgerc.f BLAS/ztbsv.f	\
+BLAS/chemm.f BLAS/ctpmv.f BLAS/drotmg.f BLAS/dtrmv.f BLAS/sgemv.f BLAS/stbmv.f BLAS/zgeru.f BLAS/ztpmv.f BLAS/chemv.f	\
+BLAS/ctpsv.f BLAS/dsbmv.f BLAS/dtrsm.f BLAS/sger.f BLAS/stbsv.f BLAS/zhbmv.f BLAS/ztpsv.f BLAS/cher2.f BLAS/ctrmm.f	\
+BLAS/dscal.f BLAS/dtrsv.f BLAS/snrm2.f BLAS/stpmv.f BLAS/zhemm.f BLAS/ztrmm.f BLAS/cher2k.f BLAS/ctrmv.f BLAS/dsdot.f	\
+BLAS/dzasum.f BLAS/srot.f BLAS/stpsv.f BLAS/zhemv.f BLAS/ztrmv.f BLAS/cher.f BLAS/ctrsm.f BLAS/dspmv.f BLAS/dznrm2.f	\
+BLAS/srotg.f BLAS/strmm.f BLAS/zher2.f BLAS/ztrsm.f BLAS/cherk.f BLAS/ctrsv.f BLAS/dspr2.f BLAS/icamax.f BLAS/srotm.f	\
+BLAS/strmv.f BLAS/zher2k.f BLAS/ztrsv.f BLAS/chpmv.f BLAS/dasum.f BLAS/dspr.f BLAS/idamax.f BLAS/srotmg.f BLAS/strsm.f	\
+BLAS/zher.f BLAS/chpr2.f BLAS/daxpy.f BLAS/dswap.f BLAS/isamax.f BLAS/ssbmv.f BLAS/strsv.f BLAS/zherk.f BLAS/chpr.f	\
+BLAS/dcabs1.f BLAS/dsymm.f BLAS/izamax.f BLAS/sscal.f blas_xerbla.f BLAS/zhpmv.f
+
+CBLAS_SOURCES=CBLAS/src/cblas_caxpy.c CBLAS/src/cblas_drot.c CBLAS/src/cblas_sgemm.c CBLAS/src/cblas_zher2.c		\
+CBLAS/src/cblas_ccopy.c CBLAS/src/cblas_drotg.c CBLAS/src/cblas_sgemv.c CBLAS/src/cblas_zher2k.c			\
+CBLAS/src/cblas_cdotc_sub.c CBLAS/src/cblas_drotm.c CBLAS/src/cblas_sger.c CBLAS/src/cblas_zher.c			\
+CBLAS/src/cblas_cdotu_sub.c CBLAS/src/cblas_drotmg.c CBLAS/src/cblas_snrm2.c CBLAS/src/cblas_zherk.c			\
+CBLAS/src/cblas_cgbmv.c CBLAS/src/cblas_dsbmv.c CBLAS/src/cblas_srot.c CBLAS/src/cblas_zhpmv.c CBLAS/src/cblas_cgemm.c	\
+CBLAS/src/cblas_dscal.c CBLAS/src/cblas_srotg.c CBLAS/src/cblas_zhpr2.c CBLAS/src/cblas_cgemv.c CBLAS/src/cblas_dsdot.c	\
+CBLAS/src/cblas_srotm.c CBLAS/src/cblas_zhpr.c CBLAS/src/cblas_cgerc.c CBLAS/src/cblas_dspmv.c CBLAS/src/cblas_srotmg.c	\
+CBLAS/src/cblas_zscal.c CBLAS/src/cblas_cgeru.c CBLAS/src/cblas_dspr2.c CBLAS/src/cblas_ssbmv.c CBLAS/src/cblas_zswap.c	\
+CBLAS/src/cblas_chbmv.c CBLAS/src/cblas_dspr.c CBLAS/src/cblas_sscal.c CBLAS/src/cblas_zsymm.c CBLAS/src/cblas_chemm.c	\
+CBLAS/src/cblas_dswap.c CBLAS/src/cblas_sspmv.c CBLAS/src/cblas_zsyr2k.c CBLAS/src/cblas_chemv.c			\
+CBLAS/src/cblas_dsymm.c CBLAS/src/cblas_sspr2.c CBLAS/src/cblas_zsyrk.c CBLAS/src/cblas_cher2.c CBLAS/src/cblas_dsymv.c	\
+CBLAS/src/cblas_sspr.c CBLAS/src/cblas_ztbmv.c CBLAS/src/cblas_cher2k.c CBLAS/src/cblas_dsyr2.c CBLAS/src/cblas_sswap.c	\
+CBLAS/src/cblas_ztbsv.c CBLAS/src/cblas_cher.c CBLAS/src/cblas_dsyr2k.c CBLAS/src/cblas_ssymm.c CBLAS/src/cblas_ztpmv.c	\
+CBLAS/src/cblas_cherk.c CBLAS/src/cblas_dsyr.c CBLAS/src/cblas_ssymv.c CBLAS/src/cblas_ztpsv.c CBLAS/src/cblas_chpmv.c	\
+CBLAS/src/cblas_dsyrk.c CBLAS/src/cblas_ssyr2.c CBLAS/src/cblas_ztrmm.c CBLAS/src/cblas_chpr2.c CBLAS/src/cblas_dtbmv.c	\
+CBLAS/src/cblas_ssyr2k.c CBLAS/src/cblas_ztrmv.c CBLAS/src/cblas_chpr.c CBLAS/src/cblas_dtbsv.c CBLAS/src/cblas_ssyr.c	\
+CBLAS/src/cblas_ztrsm.c CBLAS/src/cblas_cscal.c CBLAS/src/cblas_dtpmv.c CBLAS/src/cblas_ssyrk.c CBLAS/src/cblas_ztrsv.c	\
+CBLAS/src/cblas_csscal.c CBLAS/src/cblas_dtpsv.c CBLAS/src/cblas_stbmv.c CBLAS/src/cdotcsub.f CBLAS/src/cblas_cswap.c	\
+CBLAS/src/cblas_dtrmm.c CBLAS/src/cblas_stbsv.c CBLAS/src/cdotusub.f CBLAS/src/cblas_csymm.c CBLAS/src/cblas_dtrmv.c	\
+CBLAS/src/cblas_stpmv.c CBLAS/src/dasumsub.f CBLAS/src/cblas_csyr2k.c CBLAS/src/cblas_dtrsm.c CBLAS/src/cblas_stpsv.c	\
+CBLAS/src/ddotsub.f CBLAS/src/cblas_csyrk.c CBLAS/src/cblas_dtrsv.c CBLAS/src/cblas_strmm.c CBLAS/src/dnrm2sub.f	\
+CBLAS/src/cblas_ctbmv.c CBLAS/src/cblas_dzasum.c CBLAS/src/cblas_strmv.c CBLAS/src/dsdotsub.f CBLAS/src/cblas_ctbsv.c	\
+CBLAS/src/cblas_dznrm2.c CBLAS/src/cblas_strsm.c CBLAS/src/dzasumsub.f CBLAS/src/cblas_ctpmv.c CBLAS/src/cblas_f77.h	\
+CBLAS/src/cblas_strsv.c CBLAS/src/dznrm2sub.f CBLAS/src/cblas_ctpsv.c CBLAS/src/cblas_globals.c				\
+CBLAS/src/cblas_xerbla.c CBLAS/src/icamaxsub.f CBLAS/src/cblas_ctrmm.c CBLAS/src/cblas.h CBLAS/src/cblas_zaxpy.c	\
+CBLAS/src/idamaxsub.f CBLAS/src/cblas_ctrmv.c CBLAS/src/cblas_icamax.c CBLAS/src/cblas_zcopy.c CBLAS/src/isamaxsub.f	\
+CBLAS/src/cblas_ctrsm.c CBLAS/src/cblas_idamax.c CBLAS/src/cblas_zdotc_sub.c CBLAS/src/izamaxsub.f			\
+CBLAS/src/cblas_ctrsv.c CBLAS/src/cblas_isamax.c CBLAS/src/cblas_zdotu_sub.c CBLAS/src/Makefile CBLAS/src/cblas_dasum.c	\
+CBLAS/src/cblas_izamax.c CBLAS/src/cblas_zdscal.c CBLAS/src/sasumsub.f CBLAS/src/cblas_daxpy.c CBLAS/src/cblas_sasum.c	\
+CBLAS/src/cblas_zgbmv.c CBLAS/src/scasumsub.f CBLAS/src/cblas_dcopy.c CBLAS/src/cblas_saxpy.c CBLAS/src/cblas_zgemm.c	\
+CBLAS/src/scnrm2sub.f CBLAS/src/cblas_ddot.c CBLAS/src/cblas_scasum.c CBLAS/src/cblas_zgemv.c CBLAS/src/sdotsub.f	\
+CBLAS/src/cblas_dgbmv.c CBLAS/src/cblas_scnrm2.c CBLAS/src/cblas_zgerc.c CBLAS/src/sdsdotsub.f CBLAS/src/cblas_dgemm.c	\
+CBLAS/src/cblas_scopy.c CBLAS/src/cblas_zgeru.c CBLAS/src/snrm2sub.f CBLAS/src/cblas_dgemv.c CBLAS/src/cblas_sdot.c	\
+CBLAS/src/cblas_zhbmv.c CBLAS/src/xerbla.c CBLAS/src/cblas_dger.c CBLAS/src/cblas_sdsdot.c CBLAS/src/cblas_zhemm.c	\
+CBLAS/src/zdotcsub.f CBLAS/src/cblas_dnrm2.c CBLAS/src/cblas_sgbmv.c CBLAS/src/cblas_zhemv.c CBLAS/src/zdotusub.f
+
+nodist_libf77blas_a_SOURCES=$(F77BLAS_SOURCES)
+nodist_libcblas_a_SOURCES=$(CBLAS_SOURCES)
+BUILT_SOURCES=@DOWNLOADED_BLAS_BUILT_SOURCES@
+
+# -ICBLAS/include to find cblas.h
+libcblas_a_CFLAGS=-DADD_ -ICBLAS/include
+
+# "xerbla" exists in both BLAS and CBLAS. So we need to rename it to obtain two different object files.
+
+BLAS:BLAS/fait
+
+BLAS/fait:$(BLAS_TGZ)
+	mkdir -p ../include ../lib
+	-if tar xvzf $(BLAS_TGZ) BLAS/xerbla.f 2>&1 1>/dev/null ; then \
+	tar xvzf $(BLAS_TGZ) ; \
+	else \
+	mkdir -p BLAS;cd BLAS && tar xvzf ../$(BLAS_TGZ);\
+	fi
+	cp BLAS/xerbla.f blas_xerbla.f
+	touch BLAS/fait
+$(F77BLAS_SOURCES): BLAS
+
+CBLAS:CBLAS/fait
+
+CBLAS/fait: $(CBLAS_TGZ)
+	tar xvzf $(CBLAS_TGZ)
+	cp CBLAS/include/*.h  CBLAS/src
+	touch CBLAS/fait
+$(CBLAS_SOURCES): CBLAS/fait
+
+clean-local::
+	-rm -r BLAS CBLAS blas_xerbla.f
+
+# <<OpenBLAS>> ALH - 18/9/13 - Downloading and building the OpenBLAS
+# ------------------------------------------------------------------
+
+# to activate this, see [[file:../../configure.ac::OpenBLAS]]
+
+all-local::@COMPILE_OPENBLAS@
+pkgcompile::@COMPILE_OPENBLAS@
+generic:
+openblas:links.done
+
+# links2files is required for the MinGW compiler to understand where to find the library contents under Cygwin
+if FFCS_WINDOWS
+links.done:openblas.done
+	cd OpenBLAS && ../../../build/links2files
+	touch $@
+else
+links.done:openblas.done
+	touch $@
+endif
+
+openblas.done:openpatches.done
+#
+# DYNAMIC_ARCH=1 allows the Openblas to run fast on all the processor architectures that the FFCS users may have
+#
+
+	test  -d ../lib ||  mkdir  ../lib 
+	cd OpenBLAS && make BINARY=@SIZEOF_PTRINBIT@ CC=${CC} FC=${FC} DYNAMIC_ARCH=1 libs netlib
+	touch $@
+
+# The OpenBLAS directory is updated during the compilation, so the patching step should not depend on the directory
+# date
+
+openpatches.done:opendownload.done
+	tar xvzf ../pkg/OpenBLAS.tar.gz
+#
+# ALH - 7/1/14 - The tar directory has changed names
+#
+	mv xianyi-OpenBLAS-* OpenBLAS
+	patch -u -p1 < openblas.patches
+	touch $@
+
+download::opendownload.done
+opendownload.done:
+	../getall -o OpenBLAS -a
+	touch $@
+
+# ALH - 6/11/13 - Since OpenBLAS is quite long to compile and it does not change very often, it's only cleaned as part
+# of the specific target 'veryclean'.
+
+veryclean::
+	-rm -r *.done OpenBLAS xianyi-OpenBLAS-*
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/blas/openblas.patches b/download/blas/openblas.patches
new file mode 100644
index 0000000..3bb9db8
--- /dev/null
+++ b/download/blas/openblas.patches
@@ -0,0 +1,30 @@
+# -*- mode:diff;coding:raw-text; -*-
+diff -r -u ref/OpenBLAS/c_check OpenBLAS/c_check
+--- ref/OpenBLAS/c_check	2010-01-28 20:26:25.000000000 +0100
++++ OpenBLAS/c_check	2012-06-05 15:17:47.877934400 +0200
+@@ -22,15 +22,16 @@
+ 
+ $cross_suffix = "";
+ 
+-if ($ARGV[0] =~ /(.*)(-[.\d]+)/) {
+-    if ($1 =~ /(.*-)(.*)/) {
+-	$cross_suffix = $1;
+-    }
+-} else {
+-    if ($ARGV[0] =~ /(.*-)(.*)/) {
+-	$cross_suffix = $1;
+-    }
+-}
++# FFCS - this test is broken when using full paths with dashes for compilers
++#if ($ARGV[0] =~ /(.*)(-[.\d]+)/) {
++#    if ($1 =~ /(.*-)(.*)/) {
++#	$cross_suffix = $1;
++#    }
++#} else {
++#    if ($ARGV[0] =~ /(.*-)(.*)/) {
++#	$cross_suffix = $1;
++#    }
++#}
+ 
+ $compiler = "";
+ $compiler = PGI       if ($data =~ /COMPILER_PGI/);
diff --git a/download/blas/opendownload.done b/download/blas/opendownload.done
new file mode 100644
index 0000000..e69de29
diff --git a/download/common.mak b/download/common.mak
new file mode 100644
index 0000000..c2225f7
--- /dev/null
+++ b/download/common.mak
@@ -0,0 +1,55 @@
+# Common make rules for all downloaded packages (request from FH)
+# ======================================================================
+# Written by Antoine Le Hyaric
+# http://www.ljll.math.upmc.fr/lehyaric
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh brief="Common make rules for all downloaded packages (request from FH)" default=0 freefem make start=06/11/2013 upmc written
+
+# Common goals for all packages:
+# download compile install reinstall clean veryclean
+
+# <<download>>
+
+# PKGCOMMON_PACKTITLE correspond to package names in [[file:getall]]
+download::
+	../getall -o $(PKGCOMMON_PACKTITLE)
+$(PKGCOMMON_PACKAGES):download
+
+compilepkg::download
+
+# <<install>>
+
+install::compilepkg
+
+# <<reinstall>>
+
+reinstall::compilepkg
+
+clean-local::
+
+veryclean::clean
+	-rm $(PKGCOMMON_PACKAGES)
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/f2c/Makefile b/download/f2c/Makefile
new file mode 100644
index 0000000..9378e81
--- /dev/null
+++ b/download/f2c/Makefile
@@ -0,0 +1,112 @@
+
+DIRPKG=../pkg
+LISTINST=  ../bin/f2c ../bin/fort77 ../include/f2c.h ../lib/libf2c.a
+DIRINSTALL=/usr/local
+F2C_TAR=$(DIRPKG)/f2c.tar
+all:compile
+
+$(F2C_TAR):
+	mkdir -p $(DIRPKG)
+	$(WGET) # wget --passive-ftp ftp://netlib.bell-labs.com/netlib/f2c.tar
+	curl http://netlib.sandia.gov/cgi-bin/netlib/netlibfiles.tar?filename=netlib/f2c -o "$(DIRPKG)/f2c.tar"
+f2c:$(F2C_TAR) f2c.h-int
+	tar xvf $(F2C_TAR)
+	gunzip -rf f2c/*
+	gunzip -rf f2c/*/*
+	cd f2c;unzip -d libf2c  libf2c.zip
+	for i in `find . -name f2c.h`; do cp f2c.h-int $$i; done
+
+f2c/libf2c/makefile: Makefile
+	egrep -v 'ld -r|mv [$$]' <f2c/libf2c/makefile.u >f2c/libf2c/makefile
+
+compile:f2c f2c/libf2c/makefile
+	cd f2c/src; make -f makefile.u f2c
+	cd f2c/libf2c; make 
+
+compile-10.4:f2c Makefile-MacOs
+	cd f2c/src; make -f makefile.u f2c
+	cd f2c/libf2c; make -f ../../Makefile-MacOs OS=10.4 
+compile-10.5:f2c Makefile-MacOs
+	cd f2c/src; make -f makefile.u f2c 
+	cd f2c/libf2c; make -f ../../Makefile-MacOs OS=10.5
+compile-10.6:f2c Makefile-MacOs
+	cd f2c/src; make -f makefile.u f2c 
+	cd f2c/libf2c; make -f ../../Makefile-MacOs OS=10.6
+
+
+install:  ../lib ../include ../bin ../bin/fort77 ../bin/mpifort77
+	-mkdir ../bin
+	cp f2c/src/f2c ../bin/.
+	cp f2c/src/f2c.h ../include
+	cp f2c/libf2c/libf2c.a ../lib
+	../bin/fort77 tt.f
+	rm a.out
+
+install-10.4: compile-10.4
+	sudo make install-sudo
+	make install
+install-10.5: compile-10.5
+	sudo make install-sudo
+	make install
+install-10.6: compile-10.6
+	sudo make install-sudo
+	make install
+install-sudo: $(DIRINSTALL)/bin/fort77 $(DIRINSTALL)/bin/mpifort77
+	mkdir -p $(DIRINSTALL)/bin $(DIRINSTALL)/include $(DIRINSTALL)/lib
+	cp f2c/src/f2c $(DIRINSTALL)/bin; 
+	cp f2c/src/f2c.h $(DIRINSTALL)/include; 
+	cp f2c/libf2c/libf2c.a $(DIRINSTALL)/lib 	 
+	$(DIRINSTALL)/bin/fort77 tt.f	
+	rm a.out
+
+
+
+../bin/fort77: fort77.sed Makefile
+	dd="`pwd`/.." ; \
+	sed -e "s;@CC@;$(CC);"g \
+	-e "s;@INC@;-I$$dd/include;g" \
+         -e "s;@LLIBDIR@;-L$$dd/lib;g" \
+         -e "s;@f2c@;$$dd/bin/f2c;g"  < fort77.sed >../bin/fort77
+	chmod a+x ../bin/fort77
+../bin/mpifort77: fort77.sed Makefile
+	dd="`pwd`/.." ; \
+	sed -e "s;@CC@;mpicc;"g \
+	-e "s;@INC@;-I$$dd/include;g" \
+         -e "s;@LLIBDIR@;-L$$dd/lib;g" \
+         -e "s;@f2c@;$$dd/bin/f2c;g"  < fort77.sed >../bin/fort77
+	chmod a+x ../bin/fort77
+
+$(DIRINSTALL)/bin/fort77: fort77.sed Makefile
+	dd="$(DIRINSTALL)/" ; \
+	sed -e "s;@CC@;$(CC);"g \
+	-e "s;@INC@;-I$$dd/include;g" \
+         -e "s;@LLIBDIR@;-L$$dd/lib;g" \
+         -e "s;@f2c@;$$dd/bin/f2c;g"  < fort77.sed >$(DIRINSTALL)/bin/fort77
+	chmod a+x $(DIRINSTALL)/bin/fort77
+$(DIRINSTALL)/bin/mpifort77: fort77.sed Makefile
+	dd="$(DIRINSTALL)/" ; \
+	sed -e "s;@CC@;mpicc;"g \
+	-e "s;@INC@;-I$$dd/include;g" \
+         -e "s;@LLIBDIR@;-L$$dd/lib;g" \
+         -e "s;@f2c@;$$dd/bin/f2c;g"  < fort77.sed >$(DIRINSTALL)/bin/fort77
+	chmod a+x $(DIRINSTALL)/bin/fort77
+
+
+../bin:	
+	mkdir ../bin
+../lib:	
+	mkdir ../lib
+../include:	
+	mkdir ../include
+clean-local:
+	-rm -rf  f2c *~  a.out
+clean:clean-local
+
+veryclean: clean 
+	-rm $(LISTINST) $(F2C_TAR)
+
+
+
+
+
+
diff --git a/download/f2c/Makefile-MacOs b/download/f2c/Makefile-MacOs
new file mode 100644
index 0000000..4a9a342
--- /dev/null
+++ b/download/f2c/Makefile-MacOs
@@ -0,0 +1,229 @@
+# Unix makefile: see README.
+# For C++, first "make hadd".
+# If your compiler does not recognize ANSI C, add
+#	-DKR_headers
+# to the CFLAGS = line below.
+# On Sun and other BSD systems that do not provide an ANSI sprintf, add
+#	-DUSE_STRLEN
+# to the CFLAGS = line below.
+# On Linux systems, add
+#	-DNON_UNIX_STDIO
+# to the CFLAGS = line below.  For libf2c.so under Linux, also add
+#	-fPIC
+# to the CFLAGS = line below.
+
+.SUFFIXES: .c .o
+CC = cc
+SHELL = /bin/sh
+
+ifeq (10.4,$(OS))
+CC=gcc-4.0
+LIST_ARCH=-arch ppc -arch i386 -arch ppc64  -arch x86_64
+SDK=/Developer/SDKs/MacOSX10.4u.sdk
+endif
+ifeq (10.5,$(OS))  
+LIST_ARCH=-arch ppc -arch i386 -arch x86_64  -arch ppc64
+SDK=/Developer/SDKs/MacOSX10.5.sdk
+endif
+ifeq (10.6,$(OS))  
+LIST_ARCH= -arch i386 -arch x86_64  
+SDK=/Developer/SDKs/MacOSX10.6.sdk
+endif
+
+CFLAGS = -O -isysroot $(SDK) $(LIST_ARCH) -mmacosx-version-min=$(OS) -DNO_My_ctype
+LDFLAGS=-Wl,-syslibroot,$(SDK) $(LIST_ARCH)
+AR=libtool  -static  -o
+LIBDIR=/usr/local/lib
+# compile, then strip unnecessary symbols
+.c.o:
+	$(CC) -c -DSkip_f2c_Undefs $(CFLAGS) $*.c
+## Under Solaris (and other systems that do not understand ld -x),
+## omit -x in the ld line above.
+## If your system does not have the ld command, comment out
+## or remove both the ld and mv lines above.
+
+MISC =	f77vers.o i77vers.o main.o s_rnge.o abort_.o exit_.o getarg_.o iargc_.o\
+	getenv_.o signal_.o s_stop.o s_paus.o system_.o cabs.o\
+	derf_.o derfc_.o erf_.o erfc_.o sig_die.o uninit.o
+POW =	pow_ci.o pow_dd.o pow_di.o pow_hh.o pow_ii.o pow_ri.o pow_zi.o pow_zz.o
+CX =	c_abs.o c_cos.o c_div.o c_exp.o c_log.o c_sin.o c_sqrt.o
+DCX =	z_abs.o z_cos.o z_div.o z_exp.o z_log.o z_sin.o z_sqrt.o
+REAL =	r_abs.o r_acos.o r_asin.o r_atan.o r_atn2.o r_cnjg.o r_cos.o\
+	r_cosh.o r_dim.o r_exp.o r_imag.o r_int.o\
+	r_lg10.o r_log.o r_mod.o r_nint.o r_sign.o\
+	r_sin.o r_sinh.o r_sqrt.o r_tan.o r_tanh.o
+DBL =	d_abs.o d_acos.o d_asin.o d_atan.o d_atn2.o\
+	d_cnjg.o d_cos.o d_cosh.o d_dim.o d_exp.o\
+	d_imag.o d_int.o d_lg10.o d_log.o d_mod.o\
+	d_nint.o d_prod.o d_sign.o d_sin.o d_sinh.o\
+	d_sqrt.o d_tan.o d_tanh.o
+INT =	i_abs.o i_dim.o i_dnnt.o i_indx.o i_len.o i_mod.o i_nint.o i_sign.o\
+	lbitbits.o lbitshft.o
+HALF =	h_abs.o h_dim.o h_dnnt.o h_indx.o h_len.o h_mod.o h_nint.o h_sign.o
+CMP =	l_ge.o l_gt.o l_le.o l_lt.o hl_ge.o hl_gt.o hl_le.o hl_lt.o
+EFL =	ef1asc_.o ef1cmc_.o
+CHAR =	f77_aloc.o s_cat.o s_cmp.o s_copy.o
+I77 =	backspac.o close.o dfe.o dolio.o due.o endfile.o err.o\
+	fmt.o fmtlib.o ftell_.o iio.o ilnw.o inquire.o lread.o lwrite.o\
+	open.o rdfmt.o rewind.o rsfe.o rsli.o rsne.o sfe.o sue.o\
+	typesize.o uio.o util.o wref.o wrtfmt.o wsfe.o wsle.o wsne.o xwsne.o
+QINT =	pow_qq.o qbitbits.o qbitshft.o ftell64_.o
+TIME =	dtime_.o etime_.o
+
+# If you get an error compiling dtime_.c or etime_.c, try adding
+# -DUSE_CLOCK to the CFLAGS assignment above; if that does not work,
+# omit $(TIME) from OFILES = assignment below.
+
+# To get signed zeros in write statements on IEEE-arithmetic systems,
+# add -DSIGNED_ZEROS to the CFLAGS assignment below and add signbit.o
+# to the end of the OFILES = assignment below.
+
+# For INTEGER*8 support (which requires system-dependent adjustments to
+# f2c.h), add $(QINT) to the OFILES = assignment below...
+
+OFILES = $(MISC) $(POW) $(CX) $(DCX) $(REAL) $(DBL) $(INT) \
+	$(HALF) $(CMP) $(EFL) $(CHAR) $(I77) $(TIME)
+
+all: f2c.h signal1.h sysdep1.h libf2c.a
+
+libf2c.a: $(OFILES)
+	libtool  -static  -o libf2c.a $(OFILES)
+
+## Shared-library variant: the following rule works on Linux
+## systems.  Details are system-dependent.  Under Linux, -fPIC
+## must appear in the CFLAGS assignment when making libf2c.so.
+## Under Solaris, use -Kpic in CFLAGS and use "ld -G" instead
+## of "cc -shared".
+
+libf2c.so: $(OFILES)
+	libtool  -dynamic  -o libf2c.dylib  $(OFILES)	
+#	cc -shared -o libf2c.so $(OFILES)
+
+### If your system lacks ranlib, you don't need it; see README.
+
+f77vers.o: f77vers.c
+	$(CC) -c f77vers.c
+
+i77vers.o: i77vers.c
+	$(CC) -c i77vers.c
+
+# To get an "f2c.h" for use with "f2c -C++", first "make hadd"
+hadd: f2c.h0 f2ch.add
+	cat f2c.h0 f2ch.add >f2c.h
+
+# For use with "f2c" and "f2c -A":
+f2c.h: f2c.h0
+	cp f2c.h0 f2c.h
+
+# You may need to adjust signal1.h and sysdep1.h suitably for your system...
+signal1.h: signal1.h0
+	cp signal1.h0 signal1.h
+
+sysdep1.h: sysdep1.h0
+	cp sysdep1.h0 sysdep1.h
+
+# If your system lacks onexit() and you are not using an
+# ANSI C compiler, then you should uncomment the following
+# two lines (for compiling main.o):
+#main.o: main.c
+#	$(CC) -c -DNO_ONEXIT -DSkip_f2c_Undefs main.c
+# On at least some Sun systems, it is more appropriate to
+# uncomment the following two lines:
+#main.o: main.c
+#	$(CC) -c -Donexit=on_exit -DSkip_f2c_Undefs main.c
+
+install: libf2c.a
+	cp -p libf2c.a $(LIBDIR)
+	#-ranlib $(LIBDIR)/libf2c.a
+
+clean:
+	rm -f libf2c.a *.o arith.h signal1.h sysdep1.h
+
+backspac.o:	fio.h
+close.o:	fio.h
+dfe.o:		fio.h
+dfe.o:		fmt.h
+due.o:		fio.h
+endfile.o:	fio.h rawio.h
+err.o:		fio.h rawio.h
+fmt.o:		fio.h
+fmt.o:		fmt.h
+iio.o:		fio.h
+iio.o:		fmt.h
+ilnw.o:		fio.h
+ilnw.o:		lio.h
+inquire.o:	fio.h
+lread.o:	fio.h
+lread.o:	fmt.h
+lread.o:	lio.h
+lread.o:	fp.h
+lwrite.o:	fio.h
+lwrite.o:	fmt.h
+lwrite.o:	lio.h
+open.o:		fio.h rawio.h
+rdfmt.o:	fio.h
+rdfmt.o:	fmt.h
+rdfmt.o:	fp.h
+rewind.o:	fio.h
+rsfe.o:		fio.h
+rsfe.o:		fmt.h
+rsli.o:		fio.h
+rsli.o:		lio.h
+rsne.o:		fio.h
+rsne.o:		lio.h
+sfe.o:		fio.h
+signbit.o:	arith.h
+sue.o:		fio.h
+uio.o:		fio.h
+uninit.o:	arith.h
+util.o:		fio.h
+wref.o:		fio.h
+wref.o:		fmt.h
+wref.o:		fp.h
+wrtfmt.o:	fio.h
+wrtfmt.o:	fmt.h
+wsfe.o:		fio.h
+wsfe.o:		fmt.h
+wsle.o:		fio.h
+wsle.o:		fmt.h
+wsle.o:		lio.h
+wsne.o:		fio.h
+wsne.o:		lio.h
+xwsne.o:	fio.h
+xwsne.o:	lio.h
+xwsne.o:	fmt.h
+
+arith.h: arithchk.c
+	$(CC) $(CFLAGS) -DNO_FPINIT arithchk.c -lm ||\
+	 $(CC) -DNO_LONG_LONG $(CFLAGS) -DNO_FPINIT arithchk.c -lm
+	./a.out >arith.h
+	rm -f a.out arithchk.o
+
+check:
+	xsum Notice README abort_.c arithchk.c backspac.c c_abs.c c_cos.c \
+	c_div.c c_exp.c c_log.c c_sin.c c_sqrt.c cabs.c close.c comptry.bat \
+	d_abs.c d_acos.c d_asin.c d_atan.c d_atn2.c d_cnjg.c d_cos.c d_cosh.c \
+	d_dim.c d_exp.c d_imag.c d_int.c d_lg10.c d_log.c d_mod.c \
+	d_nint.c d_prod.c d_sign.c d_sin.c d_sinh.c d_sqrt.c d_tan.c \
+	d_tanh.c derf_.c derfc_.c dfe.c dolio.c dtime_.c due.c ef1asc_.c \
+	ef1cmc_.c endfile.c erf_.c erfc_.c err.c etime_.c exit_.c f2c.h0 \
+	f2ch.add f77_aloc.c f77vers.c fio.h fmt.c fmt.h fmtlib.c \
+	fp.h ftell_.c ftell64_.c \
+	getarg_.c getenv_.c h_abs.c h_dim.c h_dnnt.c h_indx.c h_len.c \
+	h_mod.c h_nint.c h_sign.c hl_ge.c hl_gt.c hl_le.c hl_lt.c \
+	i77vers.c i_abs.c i_dim.c i_dnnt.c i_indx.c i_len.c i_mod.c \
+	i_nint.c i_sign.c iargc_.c iio.c ilnw.c inquire.c l_ge.c l_gt.c \
+	l_le.c l_lt.c lbitbits.c lbitshft.c libf2c.lbc libf2c.sy lio.h \
+	lread.c lwrite.c main.c makefile.sy makefile.u makefile.vc \
+	makefile.wat math.hvc mkfile.plan9 open.c pow_ci.c pow_dd.c \
+	pow_di.c pow_hh.c pow_ii.c pow_qq.c pow_ri.c pow_zi.c pow_zz.c \
+	qbitbits.c qbitshft.c r_abs.c r_acos.c r_asin.c r_atan.c r_atn2.c \
+	r_cnjg.c r_cos.c r_cosh.c r_dim.c r_exp.c r_imag.c r_int.c r_lg10.c \
+	r_log.c r_mod.c r_nint.c r_sign.c r_sin.c r_sinh.c r_sqrt.c \
+	r_tan.c r_tanh.c rawio.h rdfmt.c rewind.c rsfe.c rsli.c rsne.c \
+	s_cat.c s_cmp.c s_copy.c s_paus.c s_rnge.c s_stop.c scomptry.bat sfe.c \
+	sig_die.c signal1.h0 signal_.c signbit.c sue.c sysdep1.h0 system_.c \
+	typesize.c \
+	uio.c uninit.c util.c wref.c wrtfmt.c wsfe.c wsle.c wsne.c xwsne.c \
+	z_abs.c z_cos.c z_div.c z_exp.c z_log.c z_sin.c z_sqrt.c >xsum1.out
+	cmp xsum0.out xsum1.out && mv xsum1.out xsum.out || diff xsum[01].out
diff --git a/download/f2c/f2c.h-int b/download/f2c/f2c.h-int
new file mode 100644
index 0000000..e9bc11b
--- /dev/null
+++ b/download/f2c/f2c.h-int
@@ -0,0 +1,225 @@
+/* f2c.h  --  Standard Fortran to C header file */
+
+/**  barf  [ba:rf]  2.  "He suggested using FORTRAN, and everybody barfed."
+
+	- From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */
+
+#ifndef F2C_INCLUDE
+#define F2C_INCLUDE
+
+/* set integer to int not to long */
+typedef  int integer;
+typedef unsigned int uinteger;
+typedef  int logical;
+
+typedef char *address;
+typedef short int shortint;
+typedef float real;
+typedef double doublereal;
+typedef struct { real r, i; } complex;
+typedef struct { doublereal r, i; } doublecomplex;
+typedef short int shortlogical;
+typedef char logical1;
+typedef char integer1;
+#ifdef INTEGER_STAR_8	/* Adjust for integer*8. */
+typedef long long longint;		/* system-dependent */
+typedef unsigned long long ulongint;	/* system-dependent */
+#define qbit_clear(a,b)	((a) & ~((ulongint)1 << (b)))
+#define qbit_set(a,b)	((a) |  ((ulongint)1 << (b)))
+#endif
+
+#define TRUE_ (1)
+#define FALSE_ (0)
+
+/* Extern is for use with -E */
+#ifndef Extern
+#define Extern extern
+#endif
+
+/* I/O stuff */
+
+#ifdef f2c_i2
+/* for -i2 */
+typedef short flag;
+typedef short ftnlen;
+typedef short ftnint;
+#else
+typedef long int flag;
+typedef long int ftnlen;
+typedef long int ftnint;
+#endif
+
+/*external read, write*/
+typedef struct
+{	flag cierr;
+	ftnint ciunit;
+	flag ciend;
+	char *cifmt;
+	ftnint cirec;
+} cilist;
+
+/*internal read, write*/
+typedef struct
+{	flag icierr;
+	char *iciunit;
+	flag iciend;
+	char *icifmt;
+	ftnint icirlen;
+	ftnint icirnum;
+} icilist;
+
+/*open*/
+typedef struct
+{	flag oerr;
+	ftnint ounit;
+	char *ofnm;
+	ftnlen ofnmlen;
+	char *osta;
+	char *oacc;
+	char *ofm;
+	ftnint orl;
+	char *oblnk;
+} olist;
+
+/*close*/
+typedef struct
+{	flag cerr;
+	ftnint cunit;
+	char *csta;
+} cllist;
+
+/*rewind, backspace, endfile*/
+typedef struct
+{	flag aerr;
+	ftnint aunit;
+} alist;
+
+/* inquire */
+typedef struct
+{	flag inerr;
+	ftnint inunit;
+	char *infile;
+	ftnlen infilen;
+	ftnint	*inex;	/*parameters in standard's order*/
+	ftnint	*inopen;
+	ftnint	*innum;
+	ftnint	*innamed;
+	char	*inname;
+	ftnlen	innamlen;
+	char	*inacc;
+	ftnlen	inacclen;
+	char	*inseq;
+	ftnlen	inseqlen;
+	char 	*indir;
+	ftnlen	indirlen;
+	char	*infmt;
+	ftnlen	infmtlen;
+	char	*inform;
+	ftnint	informlen;
+	char	*inunf;
+	ftnlen	inunflen;
+	ftnint	*inrecl;
+	ftnint	*innrec;
+	char	*inblank;
+	ftnlen	inblanklen;
+} inlist;
+
+#define VOID void
+
+union Multitype {	/* for multiple entry points */
+	integer1 g;
+	shortint h;
+	integer i;
+	/* longint j; */
+	real r;
+	doublereal d;
+	complex c;
+	doublecomplex z;
+	};
+
+typedef union Multitype Multitype;
+
+/*typedef long int Long;*/	/* No longer used; formerly in Namelist */
+
+struct Vardesc {	/* for Namelist */
+	char *name;
+	char *addr;
+	ftnlen *dims;
+	int  type;
+	};
+typedef struct Vardesc Vardesc;
+
+struct Namelist {
+	char *name;
+	Vardesc **vars;
+	int nvars;
+	};
+typedef struct Namelist Namelist;
+
+#define abs(x) ((x) >= 0 ? (x) : -(x))
+#define dabs(x) (doublereal)abs(x)
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+#define dmin(a,b) (doublereal)min(a,b)
+#define dmax(a,b) (doublereal)max(a,b)
+#define bit_test(a,b)	((a) >> (b) & 1)
+#define bit_clear(a,b)	((a) & ~((uinteger)1 << (b)))
+#define bit_set(a,b)	((a) |  ((uinteger)1 << (b)))
+
+/* procedure parameter types for -A and -C++ */
+
+#define F2C_proc_par_types 1
+#ifdef __cplusplus
+typedef int /* Unknown procedure type */ (*U_fp)(...);
+typedef shortint (*J_fp)(...);
+typedef integer (*I_fp)(...);
+typedef real (*R_fp)(...);
+typedef doublereal (*D_fp)(...), (*E_fp)(...);
+typedef /* Complex */ VOID (*C_fp)(...);
+typedef /* Double Complex */ VOID (*Z_fp)(...);
+typedef logical (*L_fp)(...);
+typedef shortlogical (*K_fp)(...);
+typedef /* Character */ VOID (*H_fp)(...);
+typedef /* Subroutine */ int (*S_fp)(...);
+#else
+typedef int /* Unknown procedure type */ (*U_fp)();
+typedef shortint (*J_fp)();
+typedef integer (*I_fp)();
+typedef real (*R_fp)();
+typedef doublereal (*D_fp)(), (*E_fp)();
+typedef /* Complex */ VOID (*C_fp)();
+typedef /* Double Complex */ VOID (*Z_fp)();
+typedef logical (*L_fp)();
+typedef shortlogical (*K_fp)();
+typedef /* Character */ VOID (*H_fp)();
+typedef /* Subroutine */ int (*S_fp)();
+#endif
+/* E_fp is for real functions when -R is not specified */
+typedef VOID C_f;	/* complex function */
+typedef VOID H_f;	/* character function */
+typedef VOID Z_f;	/* double complex function */
+typedef doublereal E_f;	/* real function with -R not specified */
+
+/* undef any lower-case symbols that your C compiler predefines, e.g.: */
+
+#ifndef Skip_f2c_Undefs
+#undef cray
+#undef gcos
+#undef mc68010
+#undef mc68020
+#undef mips
+#undef pdp11
+#undef sgi
+#undef sparc
+#undef sun
+#undef sun2
+#undef sun3
+#undef sun4
+#undef u370
+#undef u3b
+#undef u3b2
+#undef u3b5
+#undef unix
+#undef vax
+#endif
+#endif
diff --git a/download/f2c/fort77.sed b/download/f2c/fort77.sed
new file mode 100644
index 0000000..8e803eb
--- /dev/null
+++ b/download/f2c/fort77.sed
@@ -0,0 +1,374 @@
+#! /usr/bin/perl -w
+# fort77 (compiler driver) script for f2c
+# For use with gcc under Linux
+# This code is in the public domain; use at your own risk.
+# Parse options
+
+$version = "1.14a";
+$nnflag = '-Nn802';
+$tmpdir = $ENV{'TMPDIR'} || '/tmp';
+$cpp = 0;
+$fast_math = 1;
+$debug = 0;
+$debugcmd = "";
+push(@includes, "@INC@");
+# Loop over all options; pull all options from @ARGV and put all
+# arguments into @argv.	 This is needed because, apparently, UNIX
+# compilers acceppt options anywhere on the command line.
+
+while ($_ = $ARGV[0]) {
+    shift;
+
+    if (!/^-/) {
+	if (/\.P$/) {
+	    push(@pfiles, $_);
+	}
+	else {
+	    push(@argv, $_);
+	}
+	next;
+    }
+    # First, the f2c options.
+
+    if (/^-[CUuaEhRrz]$/ || /^-I[24]$/ || /^-onetrip$/ || /^-![clPR]$/ ||
+	/^-ext$/ || /^-!bs$/ || /^-W[1-9][0-9]*$/ || /^-w8$/ || /^-w66$/ ||
+	/^-r8$/ || /^-N[^n][0-9]+$/) {
+	push (@fopts, $_);
+    }
+    elsif (/^-Nn[0-9]+$/) {
+	$nnflag = $_;
+    }
+
+# Prototype flags for f2c
+
+    elsif (/^-Ps?/) {
+	$extract_prototypes ++;
+	push (@fopts, $_);
+    }
+
+# Does somebody want to run the preprocessor?
+
+    elsif (/^-cpp$/) {
+	$cpp++;
+    }
+
+# These are common to both f2c and gcc
+    elsif (/^-w$/) {
+	push(@fopts, $_);
+	push(@copts, $_);
+    }
+
+# This is for the linker, too...
+    elsif (/^-g$/) {
+	push(@fopts, $_);
+	push(@copts, $_);
+	push(@lopts, $_);
+	$debug ++;
+    }
+
+# Special options for the different subprocesses: f for f2c step,
+# p for (separate) preprocessing, c for C compiler, l for linker.
+# a is also passed to the C compiler.
+
+    elsif (/^-Wf,/) {
+	push(@fopts, &parsewx($_));
+    }
+    elsif (/-Wp,/) {
+	push(@cppopts, &parsewx($_));
+    }
+    elsif (/-W[ca],/) {
+	push(@copts, &parsewx($_));
+    }
+    elsif (/-Wl,/) {
+	push(@lopts,&parsewx($_));
+    }
+
+# gcc only options
+
+# too many -f and -W options to list them all...
+
+# First, let's see wether somebody wants to adhere to the C standard
+# in Fortran.
+
+    elsif (/^-fnofast-math$/) {
+	$fast_math = 0;
+    }
+    elsif (/^-m64$/) {
+	push(@copts, $_); 
+	push(@lopts, $_);
+    }
+    elsif (/^-m32$/) {
+	push(@copts, $_); 
+	push(@lopts, $_);
+    }
+
+# The '-f' option to f2c...
+
+    elsif (/^-f$/) {
+	push(@fopts, $_);
+    }
+    elsif (/^-[fWUAm]/ || /^-[Ex]$/ || /^-pipe$/ ) {
+	push(@copts, $_);
+    }
+
+# Includes and outputs...
+
+    elsif (/^-I$/) {
+	(@ARGV > 0) || die "$0: Missing argument to \"$_\"\n";
+	push(@includes, "-I".shift);
+    }
+    elsif (/^-I./) {
+	push(@includes, $_);
+    }
+    elsif (/^-o$/) {
+	(@ARGV > 0) || die "$0: Missing argument to \"$_\"\n";
+	$output = shift;
+    }
+    elsif (/^-o(.*)/) {
+	$output = $1;
+    }
+
+# Optimization
+    elsif (/^-O/) {
+	push(@copts, $_);
+	push(@lopts, $_);
+	$optimize ++;
+    }
+
+# Options for both C compiler and linker
+
+    elsif (/^-[Og]/ || /^-p$/ || /^-pg$/) {
+	push(@copts, $_);
+	push(@lopts, $_);
+    }
+    elsif (/^-[bV]$/ ) {
+	(@ARGV > 0) || die "$0 : Missing argument to \"$_\"\n";
+	$arg = shift;
+	push(@copts, $_, $arg);
+	push(@lopts, $_, $arg);
+    }
+    elsif (/^-[bV]./ ) {
+	push(@copts, $_);
+	push(@lopts, $_);
+    }
+
+# Linker only options
+
+    elsif (/^-[lL]$/) {
+	push(@lopts, $_);
+	(@ARGV > 0) || die "$0: Missing argument to \"$_\"\n";
+	$_ = shift;
+	push(@lopts, $_);
+    }
+    elsif (/^-[lL]./ || /^-nostartfiles$/ || /^-static$/ || /^-shared$/ ||
+	   /^-symbolic$/) {
+	push(@lopts, $_);
+    }
+    elsif (/^-[cS]$/) {
+	$compile_only = $_;
+    }
+    elsif (/^-D/) {
+	push(@cppopts, $_);
+    }
+#   Are we verbose?
+
+    elsif (/^-v$/) {
+	$verbose ++;
+    }
+
+# Does somebody want to keep the C files around?
+
+    elsif (/^-k$/) {
+	$keep_c ++;
+    }
+
+    else {
+	die "$0: Illegal option: $_\n";
+    }
+
+}
+
+push(@fopts,$nnflag);
+push(@copts,'-ffast-math') if $optimize && $fast_math;
+push(@cppopts, at includes);
+push(@fopts, at includes,"-I.");
+push(@fopts, @pfiles);
+
+if ($verbose) {
+    print STDERR "$0: fort77 Version $version\n";
+    if ($verbose > 1) {
+	push(@copts,"-v");
+	push(@lopts,"-v");
+	push(@cppopts,"-v");
+    }
+}
+
+
+ at ARGV = @argv;
+
+if ($compile_only && $output && (@ARGV>1)) {
+    warn "$0: Warning: $compile_only and -o with mutiple files, ignoring -o\n";
+    $output = "";
+}
+
+die "$0: No input files specified\n" unless @ARGV;
+
+while ($_ = $ARGV[0]) {
+    shift;
+    $ffile = "";
+    $cfile = "";
+    $lfile = "";
+    $basefile = "";
+
+    if (/\.[fF]$/) {
+	$ffile = $_;
+	$basefile = $ffile;
+    }
+    elsif (/\.[cCisSm]$/ || /\.cc$/ || /\.cxx$/) {
+	$cfile = $_;
+	$basefile = $_;
+    }
+    else {
+	push(@lfiles, $_);
+    }
+    if ($ffile) {
+	&check_file_read($ffile);
+	if ($keep_c) {
+	    $cfile = ($ffile =~ /([^\/]*\.).$/)[0] . "c";
+	}
+	else {
+	    $seq ++;
+	    $cfile = "$tmpdir/fort77-$$-$seq.c";
+	}
+	if ($debug) {
+	    $debugcmd = ' | /usr/bin/perl -p -e \'s/^(#line.*)""/$1"'
+		. $ffile . '"/\' '
+	}
+	if ($cpp || ($ffile =~ /\.F$/)) {
+#         Backslashes at the end of comment lines confuse cpp...
+	    $pipe =  "| /lib/cpp -traditional " . 
+		join(' ', at cppopts) . " | @f2c@ " .
+		    join(' ', at fopts) . $debugcmd . " > $cfile";
+	    print STDERR "$0: Running \"$pipe\"" if $verbose;
+	    open(F2C,$pipe);
+
+	    open (FFILE, "$ffile") || die ("$0: Cannot open $ffile: $_\n");
+	    while (<FFILE>) {
+		s/([cC*].*)\\$/$1/;
+		print F2C $_;
+	    }
+	    close(FFILE);
+	    close(F2C);
+	    $retcode = $? / 256;
+
+	}
+	else {
+	    $retcode = &mysystem("@f2c@ ".
+				 join (" ", at fopts). " < ". $ffile .
+				 $debugcmd . " > $cfile")/256;
+	}
+	if ($retcode && !$keep_c) {
+	    print STDERR "$0: unlinking $cfile\n" if $verbose;
+	    unlink $cfile;
+	    die "$0: aborting compilation\n";
+	}
+
+# Separate the prototypes out from the C files.
+
+	if ($extract_prototypes) {
+	    $pfile = ($basefile =~ /([^\/]*\.).$/)[0] . "P";
+            open(CFILE, "$cfile") || die ("$0: Cannot open $cfile\n");
+# *wdh*	    while (($line = <CFILE>) &&
+	    while (defined($line = <CFILE>) &&
+		   ($line !~ '#ifdef P_R_O_T_O_T_Y_P_E_S\n')) {
+		print $line;
+	    }
+	    if ($_) {
+        	open(PFILE, ">$pfile") || die ("$0: Cannot open $pfile\n");
+# *wdh*		while (($line = <CFILE>) && ($line !~ '#endif')) {
+		while (defined($line = <CFILE>) && ($line !~ '#endif')) {
+		    print PFILE $line;
+		}
+		close(PFILE);
+	    }
+	    close(CFILE);
+	}
+    }
+
+# C compilation step.
+
+    if ($cfile) {
+# *wdh*	@command = ("cc", at cppopts, at copts);
+	@command = ("@CC@", at cppopts, at copts);
+	if ($compile_only && $output) {
+	    push(@command,'-o',$output,$compile_only);
+	}
+	elsif ((!$compile_only) || ($compile_only eq '-c')) {
+	    $lfile = ($basefile =~ /([^\/]*\.).$/)[0] . "o";
+	    push(@command, '-c', '-o', $lfile);
+	}
+	elsif ($compile_only eq '-S') {
+	    $sfile = ($basefile =~ /([^\/]*\.).$/)[0] . "s";
+	    push(@command, '-S', '-o', $sfile);
+	}
+
+	push(@command,$cfile);
+	$retcode = &mysystem(@command)/256;
+
+	if ($retcode) {
+	    die "$0: aborting compilation\n";
+	}
+	if ($ffile && !$keep_c) {
+	    print STDERR "$0: unlinking $cfile\n" if $verbose;
+	    unlink $cfile;
+	}
+	if ($lfile) {
+	    push (@gener_lfiles, $lfile); push(@lfiles, $lfile);
+	    $lfile = "";
+	}
+    }
+    push (@lfiles, $lfile) if $lfile;
+}
+
+
+exit if $compile_only;
+
+push (@output, "-o", $output) if $output;
+
+$retcode = &mysystem("@CC@", @output, @lfiles, @lopts, "@LLIBDIR@","-lf2c", "-lm" );
+if (@gener_lfiles) {
+    print STDERR "$0: unlinking ",join(',', at gener_lfiles),"\n" if $verbose;
+    unlink (@gener_lfiles);
+}
+exit $retcode;
+
+# Basically a system call, except that we want to be verbose if
+# necessary.
+
+sub mysystem
+{
+    local (@args) = @_;
+    if (@args == 1) {
+	print STDERR "$0: Running \"$args[0]\"\n" if $verbose;
+	system($args[0]);
+    }
+    else {
+	print STDERR "$0: Running \"",join(' ', at args),"\"\n" if $verbose;
+	system(@args);
+    }
+}
+
+sub parsewx
+{
+    local ($str) = @_;
+    local(@tmp) = split(/,/,$str);
+    shift(@tmp);
+    return @tmp;
+}
+
+sub check_file_read
+{
+    local ($name) = @_;
+    open (TESTFILE,"$name") || die "Cannot open $name: $!\n";
+    close(TESTFILE);
+}
diff --git a/download/f2c/tt.f b/download/f2c/tt.f
new file mode 100644
index 0000000..4833029
--- /dev/null
+++ b/download/f2c/tt.f
@@ -0,0 +1,3 @@
+      program tt
+      print *,"dgfgdfg"
+      end
diff --git a/download/fftw/Makefile.am b/download/fftw/Makefile.am
new file mode 100644
index 0000000..e53650a
--- /dev/null
+++ b/download/fftw/Makefile.am
@@ -0,0 +1,43 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+all-local: $(DOWNLOAD_FFTW)
+
+# Downloading and compiling FFTW
+# ------------------------------
+
+# FFTW information
+FFTW_VERSION=3.3.2
+SRCDIR=fftw-$(FFTW_VERSION)
+PACKAGE=fftw-$(FFTW_VERSION).tar.gz
+SERVER=http://www.fftw.org
+THIS=fftw3
+
+fftw: $(SRCDIR)/FAIT WHERE
+	$(MAKE) WHERE
+
+$(SRCDIR)/FAIT:$(SRCDIR)/FAIT-1
+	cd $(SRCDIR) && ./configure --disable-dependency-tracking  --disable-fortran  --prefix=`pwd`/../..  CXX="$(CXX)" CC="$(CC)"  CFLAGS="$(CFLAGS)" CPP='gcc -E' CXXFLAGS="$(CXXFLAGS)"
+	cd $(SRCDIR) && make
+	cd $(SRCDIR) && make install
+	touch $(SRCDIR)/FAIT
+
+$(SRCDIR)/FAIT-1:../pkg/$(PACKAGE)
+	tar xvzf ../pkg/$(PACKAGE)
+	touch $(SRCDIR)/FAIT-1
+
+../pkg/$(PACKAGE):
+	-mkdir ../pkg
+	cd ../pkg;@WGET@ -N $(SERVER)/$(PACKAGE)
+
+WHERE:$(SRCDIR)/FAIT
+	-if [ $(SRCDIR)/FAIT ] ; then \
+	echo $(THIS)  LD -L at DIR@/lib -l$(THIS)  >../lib/WHERE.$(THIS) ;\
+	echo $(THIS) INCLUDE -I at DIR@/include   >> ../lib/WHERE.$(THIS) ;\
+	fi
+
+
+clean-local:
+	-rm -rf fftw-* 
+	-rm ../include/fftw3.f ../include/fftw3.f03 ../include/fftw3.h ../include/fftw3l.f03 ../include/fftw3q.f03	\
+		../lib/libfftw3.a ../lib/libfftw3.la
diff --git a/download/getall b/download/getall
new file mode 100755
index 0000000..d10a47e
--- /dev/null
+++ b/download/getall
@@ -0,0 +1,217 @@
+#!/usr/bin/perl
+# Download third-party packages independently of FF configuration (request from FH)
+# ======================================================================
+# Written by Antoine Le Hyaric
+# http://www.ljll.math.upmc.fr/lehyaric
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+#
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh brief="Download third-party packages independently of FF configuration (request from FH)" default=0 freefem perl start=21/10/2013 upmc written
+
+use strict;
+use Getopt::Std;
+use Digest::MD5 qw(md5_hex); # [[http://perldoc.perl.org/Digest/MD5.html]]
+
+# This download script needs to be able to work on platforms that do not have threads (eg Mingw).
+
+my $can_use_threads=eval 'use threads;use threads::shared;1';
+
+my %opts;
+getopts('afho:',\%opts);
+
+if($opts{h}){
+  print <<EOF;
+getall [options]: Download third-party packages independently of the FreeFem++ configuration procedure
+
+Available options:
+
+-a = accept all licences without further user interaction
+-f = force downloads even if packages are already present locally
+-h = this help
+-o name,name,... = only download packages with the given names
+
+EOF
+  exit 0;
+}
+
+# Accumulate errors and print them all at the end of the script
+
+my $errors='';
+if($can_use_threads){share(\$errors)}
+
+# list required packages
+my $only=0;
+my %packs;
+if(defined $opts{o}){
+  $only=1;
+  foreach(split(/,/,$opts{o})){$packs{$_}=1}
+}
+
+# can be run from the parent directory
+
+if(-x "download/getall"){chdir "download"}
+
+# can be run from any of the child directories
+
+if(-x "../getall"){chdir ".."}
+
+system "mkdir -p pkg";
+my @downloads;
+
+download('ARPACK','http://www.caam.rice.edu/software/ARPACK/SRC/arpack96.tar.gz',
+	 'http://www.caam.rice.edu/software/ARPACK','arpack96.tar.gz','fffaa970198b285676f4156cebc8626e');
+download('ARPACK','http://www.caam.rice.edu/software/ARPACK/SRC/patch.tar.gz',
+	 'http://www.caam.rice.edu/software/ARPACK','patch.tar.gz','14830d758f195f272b8594a493501fa2');
+
+download('BLAS','http://www.netlib.org/blas/blas.tgz','http://www.netlib.org/blas','blas.tgz',
+	 '5e99e975f7a1e3ea6abcad7c6e7e42e6');
+download('BLAS','http://www.netlib.org/blas/blast-forum/cblas.tgz','http://www.netlib.org/blas','cblas.tgz',
+	 '1e8830f622d2112239a4a8a83b84209a');
+
+download('OpenBLAS','http://github.com/xianyi/OpenBLAS/tarball/v0.2.12','http://www.openblas.net/','OpenBLAS.tar.gz',
+	 'dfc868e0c134855639f036d2723bf4be',
+	 'BAD_CERT');
+
+download('FFTW','http://www.fftw.org/fftw-3.3.2.tar.gz','http://www.fftw.org','fftw-3.3.2.tar.gz',
+	 '6977ee770ed68c85698c7168ffa6e178');
+
+download('freeYams','http://www.ann.jussieu.fr/~frey/ftp/archives/freeyams.2012.02.05.tgz',
+	 'http://www.ann.jussieu.fr/~frey/software.html','freeyams.2012.02.05.tgz','b7c82a256a3e59beeb2b578de93a4e0b');
+
+download('Gmm++','http://download.gna.org/getfem/stable/gmm-4.2.tar.gz',
+	 'http://download.gna.org/getfem/html/homepage/download.html','gmm-4.2.tar.gz','35fe900f7459c49f4b4337dc691c8cdf');
+
+download('Hips','http://hips.gforge.inria.fr/release/hips-1.2b-rc4.tar.gz',
+	 'http://hips.gforge.inria.fr/','hips-1.2b-rc4.tar.gz','78720bf9bbbce5e174bdbdbaa1e5d7b4');
+
+download('Ipopt','http://www.coin-or.org/download/source/Ipopt/Ipopt-3.10.2.tgz',
+	 'https://projects.coin-or.org/Ipopt','Ipopt-3.10.2.tgz','e647a49a80a03f2682db583e00aa520b');
+
+download('METIS','http://www.netlib.org/linalg/metis-4.0.tar.gz','http://www.netlib.org/linalg/','metis-4.0.tar.gz',
+	 '0aa546419ff7ef50bd86ce1ec7f727c7');
+
+download('ParMETIS','http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/OLD/ParMetis-3.1.1.tar.gz',
+	 'http://glaros.dtc.umn.edu/gkhome/views/metis','ParMetis-3.1.1.tar.gz','57318dbaddff2c3d1ef820cff0bf87b0');
+
+download('MMG3D','http://www.math.u-bordeaux1.fr/~dobrzyns/logiciels/download/mmg3d4.0.tgz',
+	 'http://www.math.u-bordeaux1.fr/~dobrzyns/logiciels/mmg3d.php','mmg3d4.0.tgz','bfc2b0373bc208e0512415d1aa2e76a1');
+
+download('mshmet','http://www.ann.jussieu.fr/~frey/ftp/archives/mshmet.2012.04.25.tgz',
+	 'http://www.ann.jussieu.fr/~frey/software.html','mshmet.2012.04.25.tgz','427f397e0602efc56aa897d38a8e9bfa');
+
+download('MUMPS','http://graal.ens-lyon.fr/MUMPS/MUMPS_4.10.0.tar.gz',
+	 'http://graal.ens-lyon.fr/MUMPS/','MUMPS_4.10.0.tar.gz','959e9981b606cd574f713b8422ef0d9f');
+
+download('NLopt','http://ab-initio.mit.edu/nlopt/nlopt-2.2.4.tar.gz',
+	 'http://ab-initio.mit.edu/wiki/index.php/NLopt','nlopt-2.2.4.tar.gz','9c60c6380a10c6d2a06895f0e8756d4f');
+
+download('pARMS','http://www-users.cs.umn.edu/~saad/software/pARMS/pARMS_2.2.php',
+	 'http://www-users.cs.umn.edu/~saad/software/pARMS','pARMS_2.2.tar.gz','be0b4a539d78b9b2b7faf32ff83de822');
+
+# ALH - 6/1/14 - web certificate for gforge.inria.fr is rejected
+
+download('PaStiX','https://gforge.inria.fr/frs/download.php/21873/pastix_release_2200.tar.bz2',
+	 'https://gforge.inria.fr/projects/pastix/','pastix_release_2200.tar.bz2','c82b1808084f183dc8dfd07b1deef694',
+	 'BAD_CERT');
+
+download('ScaLAPACK','http://www.netlib.org/scalapack/scalapack-2.0.2.tgz',
+	 'http://www.netlib.org/scalapack/','scalapack-2.0.2.tgz','2f75e600a2ba155ed9ce974a1c4b536f');
+
+# ALH - 6/1/14 - web certificate for gforge.inria.fr is rejected
+
+download('Scotch','https://gforge.inria.fr/frs/download.php/23391/scotch_5.1.6_esmumps.tar.gz',
+	 'https://gforge.inria.fr/projects/scotch/','scotch_5.1.6_esmumps.tar.gz','961d0ab22914fc6455a62699cf7b5a47',
+	 'BAD_CERT');
+
+download('SuiteSparse','http://www.cise.ufl.edu/research/sparse/SuiteSparse/SuiteSparse-4.3.1.tar.gz',
+	 'http://www.cise.ufl.edu/research/sparse/SuiteSparse/','SuiteSparse-4.3.1.tar.gz',
+	 'f8f26a3b1c7f82444c0db0b375215287');
+
+download('SuperLU','http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_4.3.tar.gz',
+	 'http://crd-legacy.lbl.gov/~xiaoye/SuperLU/','superlu_4.3.tar.gz','b72c6309f25e9660133007b82621ba7c');
+download('SuperLU_DIST','http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_dist_3.0.tar.gz',
+	 'http://crd-legacy.lbl.gov/~xiaoye/SuperLU/','superlu_dist_3.0.tar.gz','1d77f10a265f5751d4e4b59317d778f8');
+
+download('TetGen','http://wias-berlin.de/software/tetgen/files/tetgen1.4.3.tar.gz',
+	 'http://wias-berlin.de/software/tetgen/','tetgen1.4.3.tar.gz','d6a4bcdde2ac804f7ec66c29dcb63c18');
+
+download('PETSc','http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/petsc-lite-3.5.2.tar.gz',
+	 'http://ftp.mcs.anl.gov/pub/petsc/release-snapshots','petsc-lite-3.5.2.tar.gz','d707336a98d7cb31d843804d020edc94');
+download('hpddm','https://github.com/hpddm/hpddm/archive/master.zip',
+	 'https://github.com/hpddm','hpddm.zip','none');
+
+# run all downloads concurrently
+
+if($can_use_threads){
+  my @threads;
+  foreach(@downloads){push @threads,threads->create(\&downloadone,$_)}
+  foreach(@threads){$_->join()}
+}
+else{
+  foreach(@downloads){downloadone($_)}
+}
+
+if($errors ne ''){
+  print "\n$errors";
+  exit 1;
+}
+
+sub download{
+  my($title,$url,$lic,$pkg,$md5,$opts)=@_;
+
+  # skip packages that have not been requested explicitely
+  return if($only && !defined $packs{$title});
+
+  # skip packages that are already present
+  if(-f "pkg/$pkg" && !$opts{f}){
+    print "$title $pkg done\n";
+    return;
+  }
+
+  # we do not store the answers to these questions. To repeat the same downloads without manual input, options "-a" and
+  # "-o names" are provided.
+
+  if(!$opts{a}){
+    print "$title: please check the licence at $lic. Do you want to download $url? (yN)\n";
+    my $ans=uc <STDIN>;
+    chomp $ans;
+    return if $ans ne 'Y';
+  }
+
+  # uses [[file:../build/download]]
+  push @downloads,"$url,pkg/$pkg,$md5,$opts";
+}
+
+sub downloadone{
+  my($url,$pkg,$md5,$opts)=split(/,/,$_[0]);
+  my $cmd="../build/download $url $pkg $opts";
+  print "$cmd\n";
+  system $cmd;
+  if($?){$errors.="ERROR: $cmd FAILED\n"}
+
+  # check if resulting package contents are valid
+  my $md5check=md5_hex(`cat $pkg`);
+  if( ( $md5 ne "none") && ($md5check ne $md5)){$errors.="ERROR: INVALID MD5 for $pkg\n"}
+}
+
+# Local Variables:
+# mode:cperl
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/gmm/Makefile b/download/gmm/Makefile
new file mode 100644
index 0000000..e0328ce
--- /dev/null
+++ b/download/gmm/Makefile
@@ -0,0 +1,61 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include cxxflags
+
+# Downloading and compiling FFTW
+# ------------------------------
+PKG=gmm
+# $(PKG) information
+SRCDIR=$(PKG)-$(PKG_VERSION)
+PACKAGE=$(PKG)-$(PKG_VERSION).tar.gz
+SERVER=http://download.gna.org/getfem/stable
+PKGDIR=../pkg
+PKG_VERSION=4.2
+INSTALL=../..
+
+
+$(PKG):FAIT 
+
+FAITwin32-dll-target:
+	echo "On Pure Win32 (to hard to compile) "
+
+FAIT: 
+	$(MAKE) install  
+	touch FAIT
+	$(MAKE) WHERE  	
+
+FAIRE: $(SRCDIR) 
+	cd $(SRCDIR) && ./configure --disable-dependency-tracking   --prefix=`pwd`/$(INSTALL) CXX="$(CXX)" CC="$(CC)"  CFLAGS="$(CFLAGS)" CPP='gcc -E' CXXFLAGS="$(CXXFLAGS)"
+	cd $(SRCDIR) && make
+	touch FAIRE
+install: FAIRE 
+	cd $(SRCDIR) && make install
+
+
+$(SRCDIR): $(PKGDIR)/$(PACKAGE)
+	gunzip -c   $^ | tar xvf - 
+
+$(PKGDIR)/$(PACKAGE):
+	../getall -o Gmm++ -a
+
+clean: clean-local
+
+clean-local:
+	-rm -rf $(PKG)-* FAIT FAIRE $(SRCDIR) 
+	-rm ../lib/WHERE.gmm
+
+cxxflags: ../Makefile
+	grep 'CXX *=' ../Makefile >cxxflags
+	grep 'CC *=' ../Makefile >>cxxflags
+	grep 'CXXFLAGS *=' ../Makefile >>cxxflags
+	grep 'CFLAGS *=' ../Makefile >>cxxflags
+	grep 'WGET *=' ../Makefile >>cxxflags
+	grep 'WIN32DLLTARGET *=' ../Makefile >>cxxflags
+
+WHERE: 
+	- at if [ -f FAIT ] ; then \
+	echo build ../lib/WHERE.gmm ;\
+	echo gmm INCLUDE -I at DIR@/include  > ../lib/WHERE.gmm ;\
+	echo gmm LD -L at DIR@/lib   >> ../lib/WHERE.gmm ;\
+	fi
diff --git a/download/gmm/cxxflags b/download/gmm/cxxflags
new file mode 100644
index 0000000..7265555
--- /dev/null
+++ b/download/gmm/cxxflags
@@ -0,0 +1,17 @@
+CXX = clang++ -std=c++11 -isysroot /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
+MPICXX = 
+ac_ct_CXX = 
+CC = clang -isysroot /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
+H5CC = /usr/local/bin/h5cc
+HDF5_CC = clang
+MPICC = 
+YACC = bison -y
+ac_ct_CC = clang -isysroot /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
+CXXFLAGS = -m64 -fPIC -g -std=c++11  -DBAMG_LONG_LONG -DCHECK_KN -fno-inline  -fexceptions -fPIC
+CFLAGS = -g  -m64 -fPIC -g -fPIC
+FCFLAGS = -g -fPIC
+FFMETIS_CFLAGS = 
+GSL_CFLAGS = -I/usr/local/include
+HDF5_CFLAGS = 
+WGET = wget --no-check-certificate
+WIN32DLLTARGET = 
diff --git a/download/headers-sparsesolver.inc b/download/headers-sparsesolver.inc
new file mode 100644
index 0000000..5e02506
--- /dev/null
+++ b/download/headers-sparsesolver.inc
@@ -0,0 +1,113 @@
+# BLAS
+#FFBLASINCLUDE = -I/Users/morice/librairie/PATCHVECLIB/
+#FFBLASDIRLIBS = 
+#FFBLASLIB     = -L/Users/morice/librairie/PATCHVECLIB/ -lwrapperdotblas -framework veclib
+#FFBLASLIB2    = -lblas
+
+
+# LAPACK
+#FFLAPACKDIRLIBS = 
+#FFLAPACKLIB     = -framework veclib
+#FFLAPACKLIB2    = -llapack
+
+# MPI
+#FFMPIDIR      = /Users/morice/librairie/openmpi-gcc-gfortran-4.4/
+#FFMPIINCLUDE  = -I/Users/morice/librairie/openmpi-gcc-gfortran-4.4/include/
+#FFMPILIB      = -L/Users/morice/librairie/openmpi-gcc-gfortran-4.4/lib/ -lmpi -lmpi_cxx -lopen-pal -lopen-rte -lotf -lvt
+#FFMPIDIRLIBS  = /Users/morice/librairie/openmpi-gcc-gfortran-4.4/lib/
+#FFMPILIB2     = mpi mpi_cxx open-pal open-rte otf vt
+
+# INT
+
+#pastix
+FFVERSIONINT = _long
+FFCTYPESINT  = -DFORCE_LONG -DLONG
+
+#scotch
+FFINTSCOTCH  = -DLONG
+
+#hips :: -DINTSIZE32, -DINTSIZE64 ou default
+FFINTHIPS    = 
+
+# particularite
+#
+FFLIBOTHERSMUMPS = -framework Carbon -framework AppKit 
+
+#blasdef :: 
+FFBLASDEF =  -DUSE_VENDOR_BLAS
+
+#### parameter for blacs ####
+
+#  ------------------------------------------------------------------------
+#  Allows the user to vary the topologies that the BLACS default topologies
+#  (TOP = ' ') correspond to.  If you wish to use a particular topology
+#  (as opposed to letting the BLACS make the choice), uncomment the
+#  following macros, and replace the character in single quotes with the
+#  topology of your choice.
+#  ------------------------------------------------------------------------
+#  DEFBSTOP   = -DDefBSTop="'1'"
+#  DEFCOMBTOP = -DDefCombTop="'1'"
+
+FFDEFBSTOP   = 
+FFDEFCOMBTOP =
+
+#  -------------------------------------------------------------------
+#  If your MPI_Send is locally-blocking, substitute the following line
+#  for the empty macro definition below.
+#  SENDIS = -DSndIsLocBlk
+#  -------------------------------------------------------------------
+FFSENDIS =
+
+#  --------------------------------------------------------------------
+#  If your MPI handles packing of non-contiguous messages by copying to
+#  another buffer or sending extra bytes, better performance may be
+#  obtained by replacing the empty macro definition below with the
+#  macro definition on the following line.
+#  BUFF = -DNoMpiBuff
+#  --------------------------------------------------------------------
+FFBUFF = 
+
+#  -----------------------------------------------------------------------
+#  If you know something about your system, you may make it easier for the
+#  BLACS to translate between C and fortran communicators.  If the empty
+#  macro defininition is left alone, this translation will cause the C
+#  BLACS to globally block for MPI_COMM_WORLD on calls to BLACS_GRIDINIT
+#  and BLACS_GRIDMAP.  If you choose one of the options for translating
+#  the context, neither the C or fortran calls will globally block.
+#  If you are using MPICH, or a derivitive system, you can replace the 
+#  empty macro definition below with the following (note that if you let
+#  MPICH do the translation between C and fortran, you must also indicate
+#  here if your system has pointers that are longer than integers.  If so,
+#  define -DPOINTER_64_BITS=1.)  For help on setting TRANSCOMM, you can
+#  run BLACS/INSTALL/xtc_CsameF77 and BLACS/INSTALL/xtc_UseMpich as
+#  explained in BLACS/INSTALL/README.
+#   TRANSCOMM = -DUseMpich
+#
+#  If you know that your MPI uses the same handles for fortran and C
+#  communicators, you can replace the empty macro definition below with
+#  the macro definition on the following line.
+#  TRANSCOMM = -DCSameF77
+#  -----------------------------------------------------------------------
+FFTRANSCOMM =  -DUseMpi2
+
+#  --------------------------------------------------------------------------
+#  You may choose to have the BLACS internally call either the C or Fortran77
+#  interface to MPI by varying the following macro.  If TRANSCOMM is left
+#  empty, the C interface BLACS_GRIDMAP/BLACS_GRIDINIT will globally-block if
+#  you choose to use the fortran internals, and the fortran interface will
+#  block if you choose to use the C internals.  It is recommended that the 
+#  user leave this macro definition blank, unless there is a strong reason
+#  to prefer one MPI interface over the other.
+#  WHATMPI = -DUseF77Mpi
+#  WHATMPI = -DUseCMpi
+#  --------------------------------------------------------------------------
+FFWHATMPI = 
+
+#  ---------------------------------------------------------------------------
+#  Some early versions of MPICH and its derivatives cannot handle user defined
+#  zero byte data types.  If your system has this problem (compile and run
+#  BLACS/INSTALL/xsyserrors to check if unsure), replace the empty macro
+#  definition below with the macro definition on the following line.
+#  SYSERRORS = -DZeroByteTypeBug
+#  ---------------------------------------------------------------------------
+FFSYSERRORS = 
\ No newline at end of file
diff --git a/download/hips/Makefile b/download/hips/Makefile
new file mode 100644
index 0000000..d3edfc1
--- /dev/null
+++ b/download/hips/Makefile
@@ -0,0 +1,210 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+# $Id: Makefile,v 1.2 2010/03/31 08:50:56 hecht Exp $
+include makefile.inc
+
+all-local: hips
+
+# Downloading and compiling HIPS
+# ------------------------------
+# http://hips.gforge.inria.fr/release/hips-1.2b-rc4.tar.gz
+# Hips information
+
+DIRPKG=../pkg
+SRCDIR=hips-$(hips_VERSION)
+PACKAGE=$(DIRPKG)/hips-$(hips_VERSION).tar.gz
+SERVER=http://hips.gforge.inria.fr/release/
+INSTALL=../..
+hips_VERSION=1.2b-rc4
+
+# rappel ::  SRC= $(wildcard *.c) ==> permet de chopper tout les points *.c d'un repertoire
+# OBJ =  $(SRC:.c=.o)
+# ==> implique *.o dans les repertoire pour recuperer
+
+SRCPhidalCommon = $(SRCDIR)/SRC/PHIDAL/COMMON
+ObjPhidalCommon = $(SRCPhidalCommon)/*.o
+
+SRCPhidalOrdering = $(SRCDIR)/SRC/PHIDAL/ORDERING
+ObjPhidalOrdering = $(SRCPhidalOrdering)/*.o 
+
+SRCPhidalSequential = $(SRCDIR)/SRC/PHIDAL/SEQUENTIAL
+ObjPhidalSequential  = $(SRCPhidalSequential)/*.o 
+
+SRCDBMATRIX = $(SRCDIR)/SRC/BLOCK/DBMATRIX/
+ObjBlockDBMATRIX   = $(SRCDIR)/SRC/BLOCK/DBMATRIX/amalgamate.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix2PhidalMatrix.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_Build.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_Copy.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_FACTO2.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_FACTO.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_FACTOu.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_func.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_GEMM.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_GEMM_N.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_GEMMu.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_MatVec2.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_MatVec.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_MLILUPrec.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_MLIutil.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_PrecSolve.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_SEQ.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_Setup.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_SetupHID.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_solve2.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_solve.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_TRSM.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_LL.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_RL.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_RL_DROP.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_func.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_pic.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_SchurProd.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/db_struct.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/dumpDBMatrix.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_SymbolMatrix.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/PHIDAL_SymbolMatrix.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/print.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/SF_Direct.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/size.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_MLICCPrec.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix2PhidalMatrix_drop.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd_PH_DB.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_SetupHID.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_MLICCPrec.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMATRIX_MLILUPrec.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_LL.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_LLu.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_FACTO.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix_FACTO2u.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_RL.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_RLu.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_RL_DROP.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBPrec_FACTO_TRSM_GEMM_RL_DROPu.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd_DB_PH.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd_PH_DB.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd_DB.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd_DB_DB.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_PCG_DB_PH.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_PCG_PH_DB.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_PCG_DB.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/HIPS_PCG_DB_DB.o \
+	$(SRCDIR)/SRC/BLOCK/DBMATRIX/DBMatrix2PhidalMatrix_drop.o
+
+
+
+SRCBlockSOLVMATRIX = $(SRCDIR)/SRC/BLOCK/SOLVMATRIX
+ObjBlockSOLVMATRIX = $(SRCBlockSOLVMATRIX)/*.o
+
+SRCBlockSOLVMATRIX2 = $(SRCDIR)/SRC/BLOCK/SOLVMATRIX2
+ObjBlockSOLVMATRIX2 = $(SRCBlockSOLVMATRIX2)/*.o
+
+#/SRC/IO;
+ObjIO = $(SRCDIR)/SRC/IO/*.o
+
+#/SRC/PHIDAL/PARALLEL
+SRCPhidalParallel = $(SRCDIR)/SRC/PHIDAL/PARALLEL
+ObjPhidalParallel  = $(SRCPhidalParallel)/*.o 
+
+#SRC/BLOCK/PARALLEL
+ObjBlockParallel = $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrMatrix_func.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrMatrix_Build.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrMatrix_Setup.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrMatrix_Copy.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDISTRMATRIX_SEQ.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDISTRMATRIX_MLICCPrec.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDISTRMATRIX_MLILUPrec.o $(SRCDIR)/SRC/BLOCK/PARALLEL/db_parallel_struct.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBcomm.o $(SRCDIR)/SRC/BLOCK/PARA [...]
+	$(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrPrec_FACTO_TRSM_GEMM_LL.o \
+	$(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrPrec_FACTO_TRSM_GEMM_RL.o \
+	$(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrPrec_FACTO_TRSM_GEMM_RL_DROP.o \
+	$(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrPrec_FACTO_TRSM_GEMM_LLu.o \
+	$(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrPrec_FACTO_TRSM_GEMM_RLu.o \
+	$(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrPrec_FACTO_TRSM_GEMM_RL_DROPu.o \
+	$(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrPrec_func2.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDistrMatrix_solve_sub.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBcomm2.o $(SRCDIR)/SRC/BLOCK/PARALLEL/DBDISTRMATRIX_MatVec2.o
+
+
+#SRC/HIPS_WRAPPER
+ObjHIPS_WRAPPER= $(SRCDIR)/SRC/HIPS_WRAPPER/*.o
+
+#SRC/BLAS
+ObjBLAS= $(SRCDIR)/SRC/BLAS/zsymv.o $(SRCDIR)/SRC/BLAS/csymv.o
+
+#SRC/SPKIT pas besoin
+ObjSPKIT= $(SRCDIR)/SRC/SPKIT/skitfc.o $(SRCDIR)/SRC/SPKIT/skitf.o
+
+
+# definition of obj for librairies
+OBJLIBHIPSSEQUENTIAL = $(ObjPhidalCommon) $(ObjPhidalOrdering) $(ObjPhidalSequential) $(ObjBlockDBMATRIX) $(ObjBlockSOLVMATRIX) $(ObjBlockSOLVMATRIX2) $(ObjHIPS_WRAPPER) $(ObjBLAS)
+OBJLIBHIPS = $(ObjPhidalCommon) $(ObjPhidalOrdering) $(ObjPhidalSequential) $(ObjBlockDBMATRIX) $(ObjBlockSOLVMATRIX) $(ObjBlockSOLVMATRIX2) $(ObjPhidalParallel) $(ObjBlockParallel) $(ObjHIPS_WRAPPER) $(ObjBLAS)
+
+OBJLIBIO = $(ObjIO)
+
+ifndef FC
+OBJLIBSPKIT = 
+else
+OBJLIBSPKIT = $(ObjSPKIT)
+endif
+
+hips: FAIRE  
+
+# FFCS: more dependencies for parallel builds
+FAIT:$(SRCDIR)/tag-ff++
+	$(MAKE) ..  WHERE
+	touch FAIT
+
+FAIRE: FAIT 
+
+makefile.inc: ../Makefile   ../../config.status makefile-hips.inc Makefile     
+	../../config.status  --file="makefile.inc:makefile-hips.inc"
+
+
+install:..
+
+..: $(SRCDIR)/tag-ff++
+	cp makefile.inc $(SRCDIR)
+	cd $(SRCDIR); $(MAKE)
+	-rm $(SRCDIR)/LIB/*.a
+	$(AR) $(ARFLAGS) $(SRCDIR)/LIB/libhips.a $(OBJLIBHIPS)
+	$(RANLIB) $(SRCDIR)/LIB/libhips.a
+	$(AR) $(ARFLAGS) $(SRCDIR)/LIB/libhipssequential.a $(OBJLIBHIPSSEQUENTIAL)
+	$(RANLIB) $(SRCDIR)/LIB/libhipssequential.a
+	$(AR) $(ARFLAGS) $(SRCDIR)/LIB/libio.a $(OBJLIBIO) 
+	$(RANLIB) $(SRCDIR)/LIB/libio.a
+	if [ -n "$(OBJLIBSPKIT)" ] ; then \
+	$(AR) $(ARFLAGS) $(SRCDIR)/LIB/libspkit.a $(OBJLIBSPKIT) ;\
+	$(RANLIB) $(SRCDIR)/LIB/libspkit.a;\
+	fi
+	mkdir -p ../include/hips
+	cp $(SRCDIR)/LIB/*.h ../include/hips/
+	mkdir -p ../lib/hips
+	cp $(SRCDIR)/LIB/*.a ../lib/hips
+WHERE:
+	echo hips LD -L at DIR@/lib/hips -lio -lhips  >../lib/WHERE.hips
+	echo hips INCLUDE -I at DIR@/include/hips>> ../lib/WHERE.hips
+	echo hipssequential LD -L at DIR@/lib/hips -lio -lhipssequential  >>../lib/WHERE.hips
+	echo hipssequential INCLUDE -I at DIR@/include/hips  >> ../lib/WHERE.hips
+
+
+$(SRCDIR)/tag-ff++: $(PACKAGE)
+	tar xvzf $(PACKAGE)
+	cd $(SRCDIR); patch -p1 <../hips-1.2b-rc4.patch
+#	cd $(SRCDIR)/SRC/INCLUDE/; patch -p1 < ../../../hips-1.2b-rc4-1.patch;
+#	cd $(SRCDIR)/SRC/IO/; patch -p1 < ../../../hips-1.2b-rc4-2.patch;
+#	cd $(SRCDIR); for d in SRC/INCLUDE SRC/IO SRC/SPKIT TESTS/PARALLEL; do \
+#	  cp $$d/makefile $$d/makefile.orig; \
+#	  sed 's/\$$(CC).*-E/$$(CPP) $$(CFLAGS) $$(CC_OPT)/' >$$d/makefile <$$d/makefile.orig;\
+#	done
+#	cp  SRC_SPKIT_makefile $(SRCDIR)/SRC/SPKIT/makefile
+	touch $(SRCDIR)/tag-ff++
+
+$(PACKAGE):
+	../getall -o Hips -a
+
+# FFCS: avoid loops when SRCDIR does not exist
+clean-local:
+	-cd $(SRCDIR) && $(MAKE) clean  -C $(SRCDIR)
+	rm makefile.inc
+	-rm ../WHERE/hips
+	-rm ../lib/hips/*
+	-rm -rf ../lib/hips/
+	-rm ../include/hips/*
+	-rm -rf ../include/hips/
+	-rm -rf $(SRCDIR)
+	-rm FAIT
+
+clean: clean-local
+
+.PHONY:..
\ No newline at end of file
diff --git a/download/hips/SRC_SPKIT_makefile b/download/hips/SRC_SPKIT_makefile
new file mode 100755
index 0000000..1c63bf6
--- /dev/null
+++ b/download/hips/SRC_SPKIT_makefile
@@ -0,0 +1,36 @@
+HIPS_DIR = ../..
+include $(HIPS_DIR)/makefile.co
+
+ifneq ($(FC),true)
+	TMP   = skitfc.f90 skitf.f90
+	OBJ   = $(TMP:.f90=.o)
+else
+	OBJ   = 
+	AR    = echo do nothing : ar 
+endif
+
+default: $(OBJ)
+	$(AR) $(ARFLAGS) $(LIBSPKIT) $(OBJ)
+
+%.o: %.f90
+	$(FC) $(FC_OPT) $< -c -o $@
+
+skitfc.f90: template-skitfc.F90
+	$(CPP) $(CFLAGS) $(CC_OPT) $< > $@
+
+skitf.f90: template-skitf.F90
+	$(CPP) $(CFLAGS) $(CC_OPT) $< > $@
+
+clean:
+	rm -f $(TMP) *.o *.ex* *core ./extras/core* out* \#*  *~
+
+
+
+
+
+
+
+
+
+
+
diff --git a/download/hips/hips-1.2b-rc4.patch b/download/hips/hips-1.2b-rc4.patch
new file mode 100644
index 0000000..a3afb77
--- /dev/null
+++ b/download/hips/hips-1.2b-rc4.patch
@@ -0,0 +1,159 @@
+diff -ur hips-1.2b-rc4/SRC/INCLUDE/hips.h hips-1.2b-rc4-okk/SRC/INCLUDE/hips.h
+--- hips-1.2b-rc4/SRC/INCLUDE/hips.h	2009-06-21 23:12:59.000000000 +0200
++++ hips-1.2b-rc4-okk/SRC/INCLUDE/hips.h	2010-06-17 10:42:14.000000000 +0200
+@@ -122,6 +122,7 @@
+ #ifndef HIPS_H
+ #define HIPS_H
+ #include <stdio.h>
++#include <ctype.h>
+ #include "type.h"
+ 
+ #ifdef INTL
+diff -ur hips-1.2b-rc4/SRC/INCLUDE/makefile hips-1.2b-rc4-okk/SRC/INCLUDE/makefile
+--- hips-1.2b-rc4/SRC/INCLUDE/makefile	2009-03-09 13:34:49.000000000 +0100
++++ hips-1.2b-rc4-okk/SRC/INCLUDE/makefile	2010-06-17 10:42:14.000000000 +0200
+@@ -7,7 +7,7 @@
+ 	$(CP) -f hips.inc $(HIPS_DIR)/LIB/
+ 
+ hips.inc:  hips_interface.F90
+-	$(CC) $(CC_OPT) -E hips_interface.F90 > hips.inc
++	$(CPP) $(CFLAGS) $(CC_OPT) hips_interface.F90 > hips.inc
+ 
+ .h:
+ 	$(CP) -f $< $(HIPS_DIR)/LIB/
+Only in hips-1.2b-rc4-okk/SRC/INCLUDE: makefile.orig
+diff -ur hips-1.2b-rc4/SRC/INCLUDE/queue.h hips-1.2b-rc4-okk/SRC/INCLUDE/queue.h
+--- hips-1.2b-rc4/SRC/INCLUDE/queue.h	2009-06-21 23:12:57.000000000 +0200
++++ hips-1.2b-rc4-okk/SRC/INCLUDE/queue.h	2010-06-25 08:21:50.000000000 +0200
+@@ -98,7 +98,7 @@
+ } Heap;
+ 
+ 
+-#define static
++/*#define static*/
+ 
+ int     Heap_Init       (Heap *, dim_t size);
+ void    Heap_Exit       (Heap *);
+diff -ur hips-1.2b-rc4/SRC/IO/io_hb.c hips-1.2b-rc4-okk/SRC/IO/io_hb.c
+--- hips-1.2b-rc4/SRC/IO/io_hb.c	2009-05-11 15:59:33.000000000 +0200
++++ hips-1.2b-rc4-okk/SRC/IO/io_hb.c	2010-06-17 10:42:14.000000000 +0200
+@@ -222,7 +222,11 @@
+ #include<stdlib.h>
+ #include<string.h>
+ #include<math.h>
++#ifdef __APPLE__
++#include <malloc/malloc.h>
++#else
+ #include<malloc.h>
++#endif
+ #include <assert.h>
+ 
+ /** macros FSCANF and FGETS **/
+diff -ur hips-1.2b-rc4/SRC/IO/io_hb.h hips-1.2b-rc4-okk/SRC/IO/io_hb.h
+--- hips-1.2b-rc4/SRC/IO/io_hb.h	2009-02-23 23:59:03.000000000 +0100
++++ hips-1.2b-rc4-okk/SRC/IO/io_hb.h	2010-06-17 10:42:14.000000000 +0200
+@@ -5,7 +5,11 @@
+ 
+ #include<stdio.h>
+ #include<stdlib.h>
++#ifdef __APPLE__
++#include<malloc/malloc.h>
++#else
+ #include<malloc.h>
++#endif
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+diff -ur hips-1.2b-rc4/SRC/IO/io_mm.c hips-1.2b-rc4-okk/SRC/IO/io_mm.c
+--- hips-1.2b-rc4/SRC/IO/io_mm.c	2009-05-11 15:59:33.000000000 +0200
++++ hips-1.2b-rc4-okk/SRC/IO/io_mm.c	2010-06-17 10:42:14.000000000 +0200
+@@ -11,7 +11,11 @@
+ 
+ #include <stdio.h>
+ #include <string.h>
++#ifdef __APPLE__
++#include <malloc/malloc.h>
++#else
+ #include <malloc.h>
++#endif
+ #include <ctype.h>
+ 
+ 
+diff -ur hips-1.2b-rc4/SRC/IO/makefile hips-1.2b-rc4-okk/SRC/IO/makefile
+--- hips-1.2b-rc4/SRC/IO/makefile	2009-03-19 18:13:16.000000000 +0100
++++ hips-1.2b-rc4-okk/SRC/IO/makefile	2010-06-17 10:42:14.000000000 +0200
+@@ -17,7 +17,7 @@
+ 	$(AR) $(ARFLAGS) $(LIBIOMM) $(OBJ) 
+ 
+ uread.f90: template-uread.F90
+-	$(CC) $(CFLAGS) $(CC_OPT) -E $< > $@
++	$(CPP) $(CFLAGS) $(CC_OPT) $< > $@
+ 
+ %.o: %.c
+ 	$(CC) $(CC_OPT) $< -c -o $@
+Only in hips-1.2b-rc4-okk/SRC/IO: makefile.orig
+diff -ur hips-1.2b-rc4/SRC/SPKIT/makefile hips-1.2b-rc4-okk/SRC/SPKIT/makefile
+--- hips-1.2b-rc4/SRC/SPKIT/makefile	2009-03-19 18:13:16.000000000 +0100
++++ hips-1.2b-rc4-okk/SRC/SPKIT/makefile	2010-06-17 10:42:14.000000000 +0200
+@@ -6,6 +6,7 @@
+ 	OBJ   = $(TMP:.f90=.o)
+ else
+ 	OBJ   = 
++	AR    = echo do nothing : ar 
+ endif
+ 
+ default: $(OBJ)
+@@ -15,10 +16,10 @@
+ 	$(FC) $(FC_OPT) $< -c -o $@
+ 
+ skitfc.f90: template-skitfc.F90
+-	$(CC) $(CFLAGS) $(CC_OPT) -E $< > $@
++	$(CPP) $(CFLAGS) $(CC_OPT) $< > $@
+ 
+ skitf.f90: template-skitf.F90
+-	$(CC) $(CFLAGS) $(CC_OPT) -E $< > $@
++	$(CPP) $(CFLAGS) $(CC_OPT) $< > $@
+ 
+ clean:
+ 	rm -f $(TMP) *.o *.ex* *core ./extras/core* out* \#*  *~
+Only in hips-1.2b-rc4-okk/SRC/SPKIT: makefile.orig
+diff -ur hips-1.2b-rc4/TESTS/PARALLEL/makefile hips-1.2b-rc4-okk/TESTS/PARALLEL/makefile
+--- hips-1.2b-rc4/TESTS/PARALLEL/makefile	2009-04-30 10:24:48.000000000 +0200
++++ hips-1.2b-rc4-okk/TESTS/PARALLEL/makefile	2010-06-17 10:42:14.000000000 +0200
+@@ -41,17 +41,17 @@
+ 	$(MPICC) $(MPICC_OPT) $< -c -o $@
+ 
+ testHIPS1-Fortran.f90 : ../../SRC/INCLUDE/hips.inc templateHIPS1-Fortran.F90
+-	$(CC) $(CFLAGS) $(CC_OPT) -E  templateHIPS1-Fortran.F90 > testHIPS1-Fortran.f90
++	$(CPP) $(CFLAGS) $(CC_OPT)  templateHIPS1-Fortran.F90 > testHIPS1-Fortran.f90
+ 
+ testHIPS2-Fortran.f90 : ../../SRC/INCLUDE/hips.inc templateHIPS2-Fortran.F90
+-	$(CC) $(CFLAGS) $(CC_OPT) -E  templateHIPS2-Fortran.F90 > testHIPS2-Fortran.f90
++	$(CPP) $(CFLAGS) $(CC_OPT)  templateHIPS2-Fortran.F90 > testHIPS2-Fortran.f90
+ 
+ 
+ testHIPS3-Fortran.f90 : ../../SRC/INCLUDE/hips.inc templateHIPS3-Fortran.F90
+-	$(CC) $(CFLAGS) $(CC_OPT) -E  templateHIPS3-Fortran.F90 > testHIPS3-Fortran.f90
++	$(CPP) $(CFLAGS) $(CC_OPT)  templateHIPS3-Fortran.F90 > testHIPS3-Fortran.f90
+ 
+ testHIPS-Laplace1-Fortran.f90 : ../../SRC/INCLUDE/hips.inc templateHIPS-Laplace1-Fortran.F90
+-	$(CC) $(CFLAGS) $(CC_OPT) -E  templateHIPS-Laplace1-Fortran.F90 > testHIPS-Laplace1-Fortran.f90
++	$(CPP) $(CFLAGS) $(CC_OPT)  templateHIPS-Laplace1-Fortran.F90 > testHIPS-Laplace1-Fortran.f90
+ 
+ testHIPS1-Fortran.o: testHIPS1-Fortran.f90 $(LIBHIPS)
+ 	$(MPIFC) $(MPIFC_OPT) $< -c -o $@
+Only in hips-1.2b-rc4-okk/TESTS/PARALLEL: makefile.orig
+Only in hips-1.2b-rc4-okk: makefile.inc
+Only in hips-1.2b-rc4-okk: tag-ff++
+diff -ur  hips-1.2b-rc4/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd.c~ hips-1.2b-rc4/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd.c
+--- hips-1.2b-rc4/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd.c~	2009-06-21 23:13:12.000000000 +0200
++++ hips-1.2b-rc4/SRC/BLOCK/DBMATRIX/HIPS_Fgmresd.c	2012-09-04 10:08:08.000000000 +0200
+@@ -80,7 +80,7 @@
+        assert(incx == incy);
+ 
+        for(i=0; i<n; i++) {
+-         dot += conj(x[i]) * y[i];
++         dot += CONJ(x[i]) * y[i];
+        }
+ 
+        return dot;
diff --git a/download/hips/makefile-hips.inc b/download/hips/makefile-hips.inc
new file mode 100755
index 0000000..f79c607
--- /dev/null
+++ b/download/hips/makefile-hips.inc
@@ -0,0 +1,104 @@
+abs_top_builddir=@abs_top_builddir@
+DOWNLOADFF=$(abs_top_builddir)/download/
+include $(DOWNLOADFF)/headers-sparsesolver.inc
+### ADD for freefem++
+###
+###  HIPS specific compilation flags
+###
+
+##   Arithmetic
+##    - default is -DTYPE_REAL in double precision (-DPREC_DOUBLE)
+##    - use -DTYPE_COMPLEX to build Complex version of HIPS
+##    - use -DPREC_SIMPLE to compute in single precision
+
+#COEFTYPE     = 
+
+COEFTYPE    = -DTYPE_REAL
+#COEFTYPE    = -DTYPE_COMPLEX
+
+#COEFTYPE    = -DTYPE_REAL    -DPREC_SIMPLE
+#COEFTYPE    = -DTYPE_COMPLEX -DPREC_SIMPLE
+
+
+##   Partitionner
+##    - default partitioner is METIS
+##    - use -DSCOTCH_PART to use SCOTCH
+
+PARTITIONER  = 
+#PARTITIONER = -DSCOTCH_PART
+
+##   Integer size
+##    - default int type is    : INTS = INTL = int (C type length)
+##    - use -DINTSIZE32 To set : INTS = INTEGER(4) and INTL = INTEGER(4)
+##    - use -DINTSIZE64 to set : INTS = INTEGER(4) and INTL = INTEGER(8)
+
+INTSIZE      =
+#INTSIZE     = -DINTSIZE64
+#INTSIZE     = -DINTSIZE32
+
+
+###
+###  Compiler
+###
+
+ARCH       = -DLINUX
+RANLIB     = @RANLIB@ 
+CC	   = @CC@       # C compiler 
+
+# FFCS - add MPI_INCLUDE because FF cannot use the defaut openmpi scripts on MacOS (see
+# [[file:../../../../configure.ac::mpicc_on_macos]])
+
+MPICC      = @MPICC@ @MPI_INCLUDE@
+
+CPP	   = cpp
+FC         = 
+MPIFC      = @MPIFC@
+LD	   = $(CC)     # Linker
+MPILD      = $(MPICC)
+
+CFLAGS	   =  @CFLAGS@         # Additional C compiler flags
+FFLAGS	   =  @FCFLAGS@        # Additional Fortran compiler flags
+LFLAGS     =  @LDFLAGS@         # Additional linker flags
+
+
+
+
+COPTFLAGS  =  #-fno-inline      # Optimization flags
+FOPTFLAGS  =  #-fno-inline      # 
+
+###
+###  Library
+###
+
+IBLAS      =  $(FFBLASINCLUDE)   # BLAS include path
+LBLAS      =  $(FFBLASLIB)  @LIBSPTHREAD@ # BLAS linker flags
+
+IMPI       =  $(FFMPIINCLUDE)      # Additional MPI include path
+LMPI       =  $(FFMPILIB)  -lsupc++ @FLIBS@  # Additional MPI linker flags
+
+##   METIS_DIR : path to METIS
+METIS_DIR  =  $(DOWNLOADFF)#
+IMETIS     = -I$(METIS_DIR)include/metis/
+LMETIS     = -L$(METIS_DIR)lib/ -lmetis
+
+##   SCOTCH_DIR : path to SCOTCH
+SCOTCH_DIR = $(DOWNLOADFF)
+ISCOTCH    = -I$(SCOTCH_DIR)include/scotch
+LSCOTCH    = -L$(SCOTCH_DIR)lib/ -lscotch -lscotcherr
+
+###
+###  Misc
+###
+
+MAKE	   = make
+AR	   = @AR@       #//ar
+ARFLAGS	   = @ARFLAGS@ #//-crs  
+LN	   = ln
+CP	   = cp
+
+###
+
+##   Uncomment that to run in DEBUG mode
+#DEBUG     = -g -DDEBUG_M
+
+WGET    = @WGET@
\ No newline at end of file
diff --git a/download/hypre/Makefile b/download/hypre/Makefile
new file mode 100644
index 0000000..4e2b20e
--- /dev/null
+++ b/download/hypre/Makefile
@@ -0,0 +1,84 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+# $Id$
+include ../headers-sparsesolver.inc
+include ff-flags
+
+
+# Downloading and compiling hypre
+# ------------------------------
+
+DIRPKG=../pkg
+SRCDIR=hypre-$(HYPRE_VERSION)
+PACKAGE=$(DIRPKG)/hypre-$(HYPRE_VERSION).tar.gz
+SERVER=https://computation.llnl.gov/casc/hypre/download
+PKGDIR=../pkg
+HYPRE_VERSION=2.4.0b
+INSTALL=../..
+SRCDIR2=hypre\-$(HYPRE_VERSION)
+
+hypre: FAIT$(WIN32DLLTARGET)
+
+FAITwin32-dll-target:
+	echo "On Pure Win32 (to hard to compile) "
+
+FAIT:	
+	$(MAKE) FAIRE WHERE
+	touch FAIT
+
+
+
+#====== 
+#
+#
+# Remark :: To test hypre examples we need to set parameter
+#  --with-blas-lib-dirs= --with-blas-libs= 
+#  --with-lapack-lib-dirs --with-lapack-lib
+#======
+
+FAIRE: $(SRCDIR)/FAIT
+
+$(SRCDIR)/FAIT:$(SRCDIR)
+	cd $(SRCDIR)/src && ./configure  CXX="$(CXX)" CC="$(CC)" CFLAGS="$(CFLAGS)" CPP="$(CC) -E" CXXFLAGS="$(CXXFLAGS)" F77="$(F77)" FFLAGS="$(FFLAGS)" FLIBS="$(FLIBS)" LDFLAGS="$(LDFLAGS)" --with-MPI-include="$(FFMPIDIR)" --with-MPI-lib-dirs="$(FFMPIDIRLIBS)" --with-MPI-libs="$(FFMPILIB2)" --prefix="${abs_top_builddir}/download"  --includedir="${abs_top_builddir}/download"/include/hypre  --libdir="${abs_top_builddir}/download"/lib/hypre  --with-lapack-libs="$(LAPACKLIBS)" --with-blas-libs="$ [...]
+# --with-lapack --with-blas  #// to add lapack to test
+	# the following line is to avoid compilation of local blas and local lapack of hypre
+	# begin patch
+#	cd $(SRCDIR)/src/config/; mv Makefile.config Makefile-tmp.config; 
+#	sed -e 's;${abs_top_builddir}/download/hypre/${SRCDIR}/src/lapack; ;'\
+#	<$(SRCDIR)/src/config/Makefile-tmp.config\
+#	>$(SRCDIR)/src/config/Makefile.config
+#	cd $(SRCDIR)/src/config/; mv Makefile.config Makefile-tmp.config; 
+#	sed -e 's;${abs_top_builddir}/download/hypre/${SRCDIR}/src/blas; ;'\
+#	<$(SRCDIR)/src/config/Makefile-tmp.config\
+#	>$(SRCDIR)/src/config/Makefile.config
+#	# end patch
+	cd $(SRCDIR)/src && $(MAKE)
+	cd $(SRCDIR)/src && $(MAKE) install
+	touch $(SRCDIR)/FAIT
+install: 
+	cd $(SRCDIR)/src && $(MAKE) install
+WHERE:
+	if [ -f $(SRCDIR)/FAIT ] ; then  \
+	echo hypre LD -L at DIR@/lib/hypre  -lHYPRE  >$(SRCDIR)/$(INSTALL)/lib/WHERE.hypre ;\
+	echo hypre INCLUDE -I at DIR@/include/hypre  >> $(SRCDIR)/$(INSTALL)/lib/WHERE.hypre ;\
+	fi
+
+
+$(SRCDIR): $(PACKAGE) 
+	tar xvzf $(PACKAGE)
+	touch $(SRCDIR)
+
+$(PACKAGE):
+	-mkdir $(DIRPKG)
+	cd $(PKGDIR); $(WGET)   $(SERVER)/`basename $(PACKAGE)`
+
+clean: clean-local
+
+clean-local:
+	-rm -rf $(SRCDIR) FAIT 
+	-rm ff-flags FAIT
+
+ff-flags: ../Makefile ff-flags.inc 
+	../../config.status  --file="ff-flags:ff-flags.inc"
+
diff --git a/download/hypre/ff-flags.inc b/download/hypre/ff-flags.inc
new file mode 100644
index 0000000..4f41d90
--- /dev/null
+++ b/download/hypre/ff-flags.inc
@@ -0,0 +1,29 @@
+abs_top_builddir = @abs_top_builddir@
+CXX = @CXX@
+MPICXX = @MPICXX@
+ac_ct_CXX = @ac_ct_CXX@
+CC = @CC@
+MPICC = @MPICC@
+YACC = @YACC@
+ac_ct_CC = @ac_ct_CC@
+FLIBS = @FLIBS@
+CXXFLAGS = @CXXFLAGS@
+CFLAGS = @CFLAGS@
+FCFLAGS = @FCFLAGS@
+FFMETIS_CFLAGS = @FFMETIS_CFLAGS@
+X_CFLAGS = @X_CFLAGS@
+CFLAGSF77 = @CFLAGSF77@
+F77 = @F77@
+MPIF77 = @MPIF77@
+ac_ct_F77 = @ac_ct_F77@
+FFLAGS = @FFLAGS@
+LDFLAGS = @LDFLAGS@
+STD_LDFLAGS = @STD_LDFLAGS@
+FLIBS = @FLIBS@
+WGET = @WGET@
+WIN32DLLTARGET = @WIN32DLLTARGET@
+FFMPIDIRLIBS = @MPI_LIB_DIRS@
+FFMPIDIR = @MPI_INC_DIR@
+FFMPILIB2 = @MPI_LIB@
+BLASLIBS = @BLASLIBS@
+LAPACKLIBS = @LAPACKLIBS@
diff --git a/download/ipopt/Makefile b/download/ipopt/Makefile
new file mode 100755
index 0000000..caee366
--- /dev/null
+++ b/download/ipopt/Makefile
@@ -0,0 +1,85 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include Makefile.inc
+
+all-local: Ipopt
+
+# Downloading and compiling mumps
+# ------------------------------
+
+DIR=$(DOWNLOADFF)/ipopt
+DIRPKG=../pkg
+SRCDIR=Ipopt-$(VERSION)
+PACKAGE=$(DIRPKG)/Ipopt-$(VERSION).tgz
+INSTALL=../..
+VERSION=3.10.2
+# 3.10.2
+URL=http://www.coin-or.org/download/source/Ipopt
+FHSL=#$(DIRPKG)/ddeps.f $(DIRPKG)/ma27ad.f  $(DIRPKG)/mc19d.f 
+LIBMUMPS=-L$(DOWNLOADFF)/lib  -ldmumpsFREEFEM-SEQ -lzmumpsFREEFEM-SEQ -lmumps_commonFREEFEM-SEQ -lpordFREEFEM-SEQ -lmpiseqFREEFEM-SEQ
+INCMUMPS=$(DOWNLOADFF)/include/libseq 
+#/Ipopt-3.10.2.tgz
+Ipopt: $(SRCDIR)/FAIRE
+#  --enable-static  --disable-shared  
+
+# ALH - 6/1/14 - We need to specify FLIBS explicitely because Ipopt
+# fails to guess FLIBS correctly on Windows+Cygwin+Mingw64, see [[file:Makefile.inc.in::FLIBS]]
+
+$(SRCDIR)/FAIT: $(SRCDIR)/tag-tar
+#	FFCS - disable dependency tracking like in FFCS itself for MinGW compilation (problem with backslashes, see
+#	[[file:../../../../configure.ac::enable_dependency_tracking]])
+	cd $(SRCDIR) ; \
+	 ./configure --disable-dependency-tracking \
+		   --disable-shared --enable-static \
+                  --with-mumps='$(LIBMUMPS)' \
+	          --without-hsl \
+	          --with-mumps-incdir='$(INCMUMPS)' \
+	  CXX='$(CXX)' CXXFLAGS='$(CXXFLAGS) -I$(INCMUMPS)' \
+	  CC='$(CC)' CFLAGS='$(CFLAGS) -I$(INCMUMPS)' \
+	  F77='$(FC)' FFLAGS='$(FCFLAGS)' \
+	  FLIBS='$(FLIBS)' \
+	  CXXCPP='$(CXXCPP)'  CPP='$(CXXCPP)' \
+	 --with-blas='$(LIBBLAS)' --with-lapack='$(LIBLAPACK)' --prefix='$(DOWNLOADFF)'
+	touch $(SRCDIR)/FAIT	
+
+# FFCS - avoid remaking install every time
+install.done: $(SRCDIR)/FAIT
+	$(MAKE)  -C  $(SRCDIR) install	
+	touch $@
+clean-local::
+	-rm *.done
+
+# FFCS - install and WHERE need to be sequential
+WHERE.done: install.done
+	echo Ipopt LD -L at DIR@/lib   -lipopt   >$(SRCDIR)/$(INSTALL)/lib/WHERE.Ipopt;
+	echo Ipopt INCLUDE -I at DIR@/include/coin  >> $(SRCDIR)/$(INSTALL)/lib/WHERE.Ipopt ;
+	touch $@
+
+Makefile.inc:
+	../../config.status  --file="Makefile.inc:Makefile.inc.in"
+
+# FFCS - install and WHERE need to be sequential
+$(SRCDIR)/FAIRE: install.done WHERE.done
+	touch $@
+
+
+$(SRCDIR)/$(INSTALL): $(SRCDIR)/tag-tar
+
+$(SRCDIR)/tag-tar:$(PACKAGE) $(FHSL) 
+	tar xvzf $(PACKAGE)
+	patch -p0 <patch-IpBlas
+	touch $(SRCDIR)/tag-tar
+
+$(PACKAGE):
+	../getall -o Ipopt -a
+
+clean-local::
+	rm -rf  $(SRCDIR)  *~ Makefile.inc
+
+clean: clean-local
+	-rm -rf ../include/coin
+	-rm ../lib/libipopt* ../lib/liblcoinhsl* 
+	-rm $(PACKAGE)
+
+.PHONY:$(SRCDIR)/$(INSTALL)
diff --git a/download/ipopt/Makefile.inc.in b/download/ipopt/Makefile.inc.in
new file mode 100644
index 0000000..4ebcd3e
--- /dev/null
+++ b/download/ipopt/Makefile.inc.in
@@ -0,0 +1,16 @@
+abs_top_builddir=@abs_top_builddir@
+DOWNLOADFF= $(abs_top_builddir)/download
+CC      = @CC@
+CXX      = @CXX@
+CXXFLAGS      = @CXXFLAGS@
+CFLAGS      = @CFLAGS@
+FC      = @FC@ 
+FCFLAGS      = @FCFLAGS@ 
+LIBBLAS =  @BLASLIBS@ 
+LIBLAPACK =@LAPACKLIBS@
+WGET=@WGET@
+CXXCPP=@CXXCPP@
+
+# <<FLIBS>> ALH - 6/1/14 - Ipopt fails to guess FLIBS correctly on Windows+Cygwin+Mingw64
+
+FLIBS=@FLIBS@
diff --git a/download/ipopt/patch-IpBlas b/download/ipopt/patch-IpBlas
new file mode 100644
index 0000000..54ab918
--- /dev/null
+++ b/download/ipopt/patch-IpBlas
@@ -0,0 +1,131 @@
+--- Ipopt-3.10.2/Ipopt/src/LinAlg/IpBlas.cpp	2010-12-21 22:34:47.000000000 +0100
++++ Ipopt-3.10.2-okk/Ipopt/src/LinAlg/IpBlas.cpp	2012-03-15 15:30:11.000000000 +0100
+@@ -8,7 +8,7 @@
+ 
+ #include "IpoptConfig.h"
+ #include "IpBlas.hpp"
+-
++#include <cassert> 
+ // Prototypes for the BLAS routines
+ extern "C"
+ {
+@@ -57,6 +57,7 @@
+                              int transa_len, int diag_len);
+ }
+ 
++
+ namespace Ipopt
+ {
+ #ifndef HAVE_CBLAS
+@@ -65,8 +66,13 @@
+                     Index incY)
+   {
+     ipfint n=size, INCX=incX, INCY=incY;
+-
+-    return F77_FUNC(ddot,DDOT)(&n, x, &INCX, y, &INCY);
++    
++    Number s=0;
++    if( incX && incY ) s=   F77_FUNC(ddot,DDOT)(&n, x, &INCX, y, &INCY) ; 
++    else 
++      for (int i=0,ix=0,iy=0;  i<n;  ++i, ix += incX, iy += incY )
++	s += x[ix]*y[iy]; 
++     return s ;
+   }
+ 
+   /* Interface to FORTRAN routine DNRM2. */
+@@ -81,7 +87,7 @@
+   Number IpBlasDasum(Index size, const Number *x, Index incX)
+   {
+     ipfint n=size, INCX=incX;
+-
++    assert(incX);  // FH 
+     return F77_FUNC(dasum,DASUM)(&n, x, &INCX);
+   }
+ 
+@@ -89,7 +95,7 @@
+   Index IpBlasIdamax(Index size, const Number *x, Index incX)
+   {
+     ipfint n=size, INCX=incX;
+-
++    assert(incX);  // FH 
+     return (Index) F77_FUNC(idamax,IDAMAX)(&n, x, &INCX);
+   }
+ 
+@@ -97,8 +103,17 @@
+   void IpBlasDcopy(Index size, const Number *x, Index incX, Number *y, Index incY)
+   {
+     ipfint N=size, INCX=incX, INCY=incY;
+-
+-    F77_FUNC(dcopy,DCOPY)(&N, x, &INCX, y, &INCY);
++    if(incX)
++      F77_FUNC(dcopy,DCOPY)(&N, x, &INCX, y, &INCY);
++    else  // modif FH
++      if(incY==1)
++	{
++	  Number *ey = y + size;
++	  while (y <ey) *y++=*x;
++	}
++      else 
++	 for(Index i=0,ii=0; i<size;++i, ii+=incY)
++	  y[ii]=*x;
+   }
+ 
+   /* Interface to FORTRAN routine DAXPY. */
+@@ -106,15 +121,25 @@
+                    Index incY)
+   {
+     ipfint N=size, INCX=incX, INCY=incY;
+-
+-    F77_FUNC(daxpy,DAXPY)(&N, &alpha, x, &INCX, y, &INCY);
++    if(incX) 
++      F77_FUNC(daxpy,DAXPY)(&N, &alpha, x, &INCX, y, &INCY);
++    else  // modif FH                                 
++      if(incY==1)
++        {
++          Number *ey = y + size;
++          while (y <ey) 
++	    *y++ += *x * alpha;
++        }
++      else
++	for(Index i=0,ii=0; i<size;++i, ii+=incY)
++          y[ii] += *x * alpha;      
+   }
+ 
+   /* Interface to FORTRAN routine DSCAL. */
+   void IpBlasDscal(Index size, Number alpha, Number *x, Index incX)
+   {
+     ipfint N=size, INCX=incX;
+-
++    assert(incX);  // FH 
+     F77_FUNC(dscal,DSCAL)(&N, &alpha, x, &INCX);
+   }
+ 
+@@ -123,7 +148,7 @@
+                    Index incX, Number beta, Number* y, Index incY)
+   {
+     ipfint M=nCols, N=nRows, LDA=ldA, INCX=incX, INCY=incY;
+-
++    assert(incX && incY);  // FH
+     char TRANS;
+     if (trans) {
+       TRANS = 'T';
+@@ -141,7 +166,7 @@
+                    Index incY)
+   {
+     ipfint N=n, LDA=ldA, INCX=incX, INCY=incY;
+-
++    assert(incX && incY);  // FH
+     char UPLO='L';
+ 
+     F77_FUNC(dsymv,DSYMV)(&UPLO, &N, &alpha, A, &LDA, x,
+--- Ipopt-3.10.2/Ipopt/src/Algorithm/IpIpoptAlg.cpp	2011-06-11 11:23:59.000000000 -0500
++++ Ipopt-3.10.2-okk/Ipopt/src/Algorithm/IpIpoptAlg.cpp	2013-02-12 14:07:39.000000000 -0600
+@@ -262,7 +262,7 @@
+     }
+ 
+     if (!isResto) {
+-      Jnlst().Printf(J_ITERSUMMARY, J_MAIN, "This is Ipopt version "IPOPT_VERSION", running with linear solver %s.\n\n", linear_solver_.c_str());
++      Jnlst().Printf(J_ITERSUMMARY, J_MAIN, "This is Ipopt version " IPOPT_VERSION ", running with linear solver %s.\n\n", linear_solver_.c_str());
+     }
+ 
+     SolverReturn retval = UNASSIGNED;
diff --git a/download/metis/Makefile b/download/metis/Makefile
new file mode 100644
index 0000000..edae386
--- /dev/null
+++ b/download/metis/Makefile
@@ -0,0 +1,93 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include Makefile.in
+
+all-local: metis
+
+# Downloading and compiling Tetgen
+# ------------------------------
+# http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-4.0.tar.gz
+# Metis information
+DIRPKG=../pkg
+SRCDIR=metis-$(metis_VERSION)
+PACKAGE=$(DIRPKG)/metis-$(metis_VERSION).tar.gz
+SERVER=http://www.netlib.org/linalg/
+#//http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD
+INSTALL=../..
+
+# FFCS - 14/11/11 - version 4.0.3 is not available from netlib anymore
+metis_VERSION=4.0
+
+metis: FAIRE
+
+
+$(SRCDIR)/FAIT:
+	$(MAKE) install
+	touch $(SRCDIR)/FAIT
+
+install:$(SRCDIR)/tag-compile
+#	cd $(SRCDIR)/Programs ;$(MAKE) 
+	-mkdir -p ../include/metis
+	cp $(SRCDIR)/Lib/*.h ../include/metis
+
+
+FAIRE: $(SRCDIR)/FAIT 
+	$(MAKE) WHERE
+	touch FAIRE
+
+Makefile.in: ../../config.status Makefile-metis.in
+	../../config.status  --file="Makefile.in:Makefile-metis.in"
+
+$(SRCDIR)/tag-compile: $(SRCDIR)/tags
+	cp Makefile.in $(SRCDIR)
+	-mkdir -p ../lib/metis
+	cd $(SRCDIR)/Lib;make
+	-cd $(SRCDIR)/Programs;make 
+	touch $(SRCDIR)/tag-compile
+
+
+
+WHERE: 
+	-if [ -f $(SRCDIR)/FAIT ] ; then \
+	echo metis LD -L at DIR@/lib/metis -lmetis  >$(SRCDIR)/$(INSTALL)/lib/WHERE.metis ;\
+	echo metis INCLUDE -I at DIR@/include/metis>> $(SRCDIR)/$(INSTALL)/lib/WHERE.metis ;\
+	fi
+
+
+
+
+# FFCS: patch is necessary for metis 4.0, but not for 4.0.3
+$(SRCDIR)/tags: $(PACKAGE)
+	tar xvzf $(PACKAGE)
+	patch -p0  <patch-metis
+	patch -p0  <metis-4.0_main_return.patch
+	mv  $(SRCDIR)/Programs/Makefile $(SRCDIR)/Programs/Makefile-orig
+	sed -e 's;BINDIR = ..;BINDIR = ../$(INSTALL)/bin;' \
+            -e 's;../libmetis.a;../$(INSTALL)/lib/metis/libmetis.a;' \
+            -e 's;-L[.][.];-L../$(INSTALL)/lib/metis;' \
+          <$(SRCDIR)/Programs/Makefile-orig \
+          >$(SRCDIR)/Programs/Makefile
+	mv $(SRCDIR)/Lib/Makefile $(SRCDIR)/Lib/Makefile-orig
+	sed   -e 's;../libmetis.a;../$(INSTALL)/lib/metis/libmetis.a;' \
+          <$(SRCDIR)/Lib/Makefile-orig \
+          >$(SRCDIR)/Lib/Makefile
+	touch $(SRCDIR)/tags
+
+$(PACKAGE):
+	../getall -o METIS -a
+
+clean-local:
+	-cd $(SRCDIR) && $(MAKE) realclean  -C $(SRCDIR)
+	-rm -rf metis-4.0 config.log
+	-rm -rf ../lib/metis ../lib/WHERE.metis
+	-rm -rf ../include/metis
+	-rm -rf $(SRCDIR)
+	-rm FAIRE FAIT 
+
+# FFCS - 23/5/12 - $(SRCDIR)/$(INSTALL) is meaningless if $(SRCDIR) does not exist
+clean: clean-local
+	-rm ../lib/metis/libmetis.a
+	-rm ../lib/include/metis.h
+	-rm -rf $(SRCDIR)
+	-rm FAIRE FAIT 
diff --git a/download/metis/Makefile-metis.in b/download/metis/Makefile-metis.in
new file mode 100644
index 0000000..2e8c3fa
--- /dev/null
+++ b/download/metis/Makefile-metis.in
@@ -0,0 +1,24 @@
+# Which compiler to use
+CC = @CC@
+
+# What optimization level to use
+OPTFLAGS = @CFLAGS@ 
+
+# What options to be used by the compiler
+COPTIONS = @FFMETIS_CFLAGS@
+
+# What options to be used by the loader
+LDOPTIONS = @LDFLAGS@
+
+# What archiving to use
+AR =  @AR@ @ARFLAGS@
+
+# What to use for indexing the archive
+RANLIB = @RANLIB@
+#RANLIB = ar -ts
+#RANLIB = 
+WGET = @WGET@
+
+
+EXEEXT = @EXEEXT@
+VERNUM = @EXEEXT@
\ No newline at end of file
diff --git a/download/metis/metis-4.0_main_return.patch b/download/metis/metis-4.0_main_return.patch
new file mode 100644
index 0000000..1143972
--- /dev/null
+++ b/download/metis/metis-4.0_main_return.patch
@@ -0,0 +1,176 @@
+--- metis-4.0/Programs/kmetis.c.orig	2013-01-26 21:01:39.898052768 +0000
++++ metis-4.0/Programs/kmetis.c	2013-01-26 21:01:52.186053491 +0000
+@@ -19,7 +19,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, nparts, options[10];
+   idxtype *part;
+@@ -100,6 +100,8 @@
+ 
+ 
+   GKfree(&graph.xadj, &graph.adjncy, &graph.vwgt, &graph.adjwgt, &part, LTERM);
++
++  return 0;
+ }  
+ 
+ 
+--- metis-4.0/Programs/pmetis.c.orig	2013-01-26 22:42:46.375724925 +0000
++++ metis-4.0/Programs/pmetis.c	2013-01-26 22:43:33.744727711 +0000
+@@ -19,7 +19,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, nparts, options[10];
+   idxtype *part;
+@@ -100,6 +100,8 @@
+ 
+ 
+   GKfree(&graph.xadj, &graph.adjncy, &graph.vwgt, &graph.adjwgt, &part, LTERM);
++  
++  return 0;
+ }  
+ 
+ 
+--- ./metis-4.0/Programs/graphchk.c.orig	2013-01-26 23:00:11.167253583 +0000
++++ ./metis-4.0/Programs/graphchk.c	2013-01-26 23:00:38.003255160 +0000
+@@ -19,7 +19,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   GraphType graph;
+   char filename[256];
+@@ -53,6 +53,8 @@
+ 
+ 
+   GKfree(&graph.xadj, &graph.adjncy, &graph.vwgt, &graph.adjwgt, LTERM);
++  
++  return 0;
+ }  
+ 
+ 
+--- ./metis-4.0/Programs/mesh2dual.c.orig	2013-01-26 23:02:14.677260844 +0000
++++ ./metis-4.0/Programs/mesh2dual.c	2013-01-26 23:02:45.081262631 +0000
+@@ -20,7 +20,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, j, ne, nn, etype, numflag=0;
+   idxtype *elmnts, *xadj, *adjncy;
+@@ -67,6 +67,7 @@
+ 
+   GKfree(&elmnts, &xadj, &adjncy, LTERM);
+ 
++  return 0;
+ }
+ 
+ 
+--- ./metis-4.0/Programs/mesh2nodal.c.orig	2013-01-26 23:03:35.671265601 +0000
++++ ./metis-4.0/Programs/mesh2nodal.c	2013-01-26 23:03:59.234266985 +0000
+@@ -20,7 +20,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, j, ne, nn, etype, numflag=0;
+   idxtype *elmnts, *xadj, *adjncy;
+@@ -67,6 +67,7 @@
+ 
+   GKfree(&elmnts, &xadj, &adjncy, LTERM);
+ 
++  return 0;
+ }
+ 
+ 
+--- ./metis-4.0/Programs/oemetis.c.orig	2013-01-26 23:04:51.689270079 +0000
++++ ./metis-4.0/Programs/oemetis.c	2013-01-26 23:05:15.686271479 +0000
+@@ -19,7 +19,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, options[10];
+   idxtype *perm, *iperm;
+@@ -90,6 +90,8 @@
+ 
+ 
+   GKfree(&graph.xadj, &graph.adjncy, &perm, &iperm, LTERM);
++  
++  return 0;
+ }  
+ 
+ 
+--- ./metis-4.0/Programs/onmetis.c.orig	2013-01-26 23:06:04.908274368 +0000
++++ ./metis-4.0/Programs/onmetis.c	2013-01-26 23:06:26.011275618 +0000
+@@ -19,7 +19,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, options[10];
+   idxtype *perm, *iperm;
+@@ -90,6 +90,8 @@
+ 
+ 
+   GKfree(&graph.xadj, &graph.adjncy, &perm, &iperm, LTERM);
++
++  return 0;
+ }  
+ 
+ 
+--- ./metis-4.0/Programs/partdmesh.c.orig	2013-01-26 23:07:09.315278152 +0000
++++ ./metis-4.0/Programs/partdmesh.c	2013-01-26 23:07:33.761279588 +0000
+@@ -20,7 +20,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, j, ne, nn, etype, numflag=0, nparts, edgecut;
+   idxtype *elmnts, *epart, *npart;
+@@ -88,6 +88,7 @@
+ 
+   GKfree(&elmnts, &epart, &npart, LTERM);
+ 
++  return 0;
+ }
+ 
+ 
+--- ./metis-4.0/Programs/partnmesh.c.orig	2013-01-26 23:09:04.858284939 +0000
++++ ./metis-4.0/Programs/partnmesh.c	2013-01-26 23:09:45.701287342 +0000
+@@ -20,7 +20,7 @@
+ /*************************************************************************
+ * Let the game begin
+ **************************************************************************/
+-main(int argc, char *argv[])
++int main(int argc, char *argv[])
+ {
+   int i, j, ne, nn, etype, numflag=0, nparts, edgecut;
+   idxtype *elmnts, *epart, *npart;
+@@ -88,6 +88,7 @@
+ 
+   GKfree(&elmnts, &epart, &npart, LTERM);
+ 
++  return 0;
+ }
+ 
+ 
diff --git a/download/metis/patch-metis b/download/metis/patch-metis
new file mode 100644
index 0000000..397d4f6
--- /dev/null
+++ b/download/metis/patch-metis
@@ -0,0 +1,11 @@
+--- metis-4.0/Lib/rename.h	2009-09-22 18:28:35.000000000 +0200
++++ metis-4.0/Lib/rename.h-ok	2009-09-22 18:28:47.000000000 +0200
+@@ -410,7 +410,7 @@
+ #define RandomPermute			__RandomPermute
+ #define ispow2				__ispow2
+ #define InitRandom			__InitRandom
+-#define log2				__log2
++#define log2				metis_log2
+ 
+ 
+ 
diff --git a/download/mmg3d/Makefile b/download/mmg3d/Makefile
new file mode 100644
index 0000000..20ae563
--- /dev/null
+++ b/download/mmg3d/Makefile
@@ -0,0 +1,113 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+all-local: mmg3d
+
+include ff-flags
+
+# Downloading and compiling mmg3d
+# -------------------------------
+# 
+DIRPKG= ../pkg
+SRCDIR= ./mmg3d4
+PACKAGE=$(DIRPKG)/mmg3d4.0.tgz
+INSTALL=..
+mmg3d_VERSION=
+# mmg3d pas sur internet
+LIBMMG3D=$(INSTALL)/lib/libmmg3d-v4.a
+OPT=4
+# size of the PKG file ( this file change See Cecile.) FFCS - 19/2/13 - the test for the file size (`stat -f "%z" file`)
+# is not portable from MacOS, so just leave it out in FFCS (SIZEPKG is still useful to force a remake when the package
+# changes)
+SIZEPKG=158547
+
+OBJS= analar.o	chkmsh.o	hash.o		memory.o	optcte.o	outqua.o	simu44.o	swap44.o	zaldy.o \
+analarcutting.o	chrono.o	heap.o		mmg3d1.o	optlap.o	pattern.o	simu56.o	swap56.o \
+baryct.o	colpoi.o	inout.o		mmg3d4.o	optlen.o	quality.o	simu68.o	swap68.o \
+boulep.o	coquil.o	length.o	mmg3d9.o	optlentet.o	queue.o		simu710.o	swap710.o \
+bucket.o	cutelt.o	librnbg.o	movevertex.o	optra4.o	ratio.o		solmap.o	swapar.o \
+		delaunay.o	locate.o	optbdry.o	opttet.o	scalem.o	spledg.o	swaptet.o \
+cenrad.o	eigenv.o	matrix.o	optcoq.o	opttyp.o	simu23.o	swap23.o	typelt.o 
+
+OBJSNOP =  cendel.o swapar.o
+
+# FFCS - simplify Makefile structure
+mmg3d:WHERE.done
+
+mmg3d4/FAIT-4.done:tag-tar-$(SIZEPKG)
+	echo "#define COMPIL " '"' `date` '"' > ./mmg3d4/build/sources/compil.date
+	cd mmg3d4/build/sources/; $(MAKE) CC='$(CC)' CFLAGS='$(CNOFLAGS) -g'   $(OBJSNOP) 
+	cd mmg3d4/build/sources/; $(MAKE) CC='$(CC)' CFLAGS='$(CFLAGS) -g'   $(OBJS) 
+	cd mmg3d4/build/sources/mmg3dmain; $(CC) -c $(CFLAGS)   mmg3d.c -I..
+	$(AR) $(ARFLAGS) $(LIBMMG3D) mmg3d4/build/sources/*.o mmg3d4/build/sources/mmg3dmain/mmg3d.o
+#
+#	FFCS - ranlib required on Windows 7 64 bits
+#
+	$(RANLIB) $(LIBMMG3D)
+	-$(CC) $(CNOFLAGS) mmg3d4/build/sources/mmg3dmain/mmg3d.o   mmg3d4/build/sources/*.o -o ../bin/mmg3d $(STD_LIBS)
+	touch mmg3d4/FAIT-4.done
+
+# FFCS - simplify Makefile structure
+install-4.done:mmg3d4/FAIT-4.done 
+	-mkdir ../include/mmg3d-v4/		
+	cp mmg3d4/build/sources/*.h ../include/mmg3d-v4/
+	touch $@
+clean::
+	-rm install-4.done
+
+mmg3d-4:$(PACKAGE)
+
+install:install-4.done WHERE.done
+
+# FFCS - keep simplest makefile structure for automatic recompilations
+WHERE.done: install-4.done
+	echo mmg3d-v4  LD -L at DIR@/lib -lmmg3d-v4  >../lib/WHERE.mmg3d ;
+	echo mmg3d-v4 INCLUDE -I at DIR@/include/mmg3d-v4>> ../lib/WHERE.mmg3d ;
+	echo build WHERE ./lib/WHERE.mmg3d ;
+	touch $@
+clean::
+	-rm WHERE.done
+
+FAIRE: mmg3d4/FAIT-4.done install-4.done
+
+# FFCS - keep it simple
+tag-tar-$(SIZEPKG): $(PACKAGE) patch-mmg3dv4.diff
+	-rm -rf  mmg3d4
+	tar xvzf $(PACKAGE)
+	touch mmg3d4/build/sources/dataff.h 	
+#
+#	ALH - clean-up all CR/LF to make patching more successful
+#
+	../../build/cleancrlf mmg3d4
+#
+	cd mmg3d4;patch -p1 <../patch-mmg3dv4.diff
+	cat </dev/null >mmg3d4/build/sources/mmg3dConfig.h
+	touch tag-tar-$(SIZEPKG)
+#	cp makefile-mmg3d.inc $(SRCDIR)/makefile
+
+$(PACKAGE):
+	../getall -o MMG3D -a
+
+clean::
+	-rm ff-flags
+#
+#	FFCS - make sure that all directories are cleaned. Thisis especially important under Windows because there is no
+#	compilation dependencies control there (see
+#	[[file:c:/cygwin/home/alh/ffcs/dist/configure.ac::dependency_tracking]])
+#
+	-rm -r mmg3d4
+	-rm FAIT* mmg* flags-* tag-tar*
+	-rm $(PACKAGE)
+
+ff-flags: ../Makefile Makefile
+	grep 'abs_top_builddir *=' ../Makefile > ff-flags
+	grep 'CC *=' ../Makefile >> ff-flags
+	grep 'CFLAGS *=' ../Makefile >> ff-flags
+	grep 'LDFLAGS *=' ../Makefile >> ff-flags
+	grep 'AR *=' ../Makefile >> ff-flags
+	grep 'ARFLAGS *=' ../Makefile >> ff-flags
+	grep 'RANLIB *=' ../Makefile >> ff-flags
+	grep 'WGET *=' ../Makefile >> ff-flags
+	grep 'STD_LIBS *=' ../Makefile >> ff-flags
+	grep 'CNOFLAGS *=' ../Makefile >> ff-flags
+.PHONY:$(SRCDIR)/$(INSTALL)
\ No newline at end of file
diff --git a/download/mmg3d/patch-mmg3dv4.diff b/download/mmg3d/patch-mmg3dv4.diff
new file mode 100644
index 0000000..803e2ce
--- /dev/null
+++ b/download/mmg3d/patch-mmg3dv4.diff
@@ -0,0 +1,3463 @@
+>diff -r -u mmg3d4/build/sources/analarcutting.c mmg3d4-new/build/sources/analarcutting.c
+--- mmg3d4/build/sources/analarcutting.c	2012-12-19 16:05:32.000000000 +0100
++++ mmg3d4-new/build/sources/analarcutting.c	2013-01-18 16:33:45.000000000 +0100
+@@ -307,7 +307,7 @@
+     printf("6 cut : %8d\n",n6);
+     printf("---------------------------\n"); */
+   if ( !na )  return(na);
+-#warning check memory allocation
++  // #warning check memory allocation
+ 
+   //printf("%d cut init --- nb tet %d\n",na,mesh->ne);
+   return(na);
+diff -r -u mmg3d4/build/sources/cutelt.c mmg3d4-new/build/sources/cutelt.c
+--- mmg3d4/build/sources/cutelt.c	2012-12-19 16:05:32.000000000 +0100
++++ mmg3d4-new/build/sources/cutelt.c	2013-01-18 16:35:41.000000000 +0100
+@@ -305,8 +305,7 @@
+ //      }
+ //      return(1);
+ // }
+-int ddebug=0;
+-
++extern int ddebug; 
+ int MMG_decouphex(pMesh mesh, pHedge hed,int k,int* p,int ref) {
+   pTetra  pt;
+   int     i,nu1,nu2;
+diff -r -u mmg3d4/build/sources/dataff.h mmg3d4-new/build/sources/dataff.h
+--- mmg3d4/build/sources/dataff.h	2013-01-18 21:52:48.000000000 +0100
++++ mmg3d4-new/build/sources/dataff.h	2013-01-18 18:50:04.000000000 +0100
+@@ -0,0 +1,60 @@
++/*
++ *  dataff.h
++ *  
++ *
++ *  Created by Fr\E9d\E9ric Hecht on 19/06/11.
++ *  Copyright 2011 UPMC. All rights reserved.
++ *
++ 
++ */
++
++enum ff_data_type {
++    ff_id_vertex =0,
++    ff_id_seg =1,
++    ff_id_tria=2,
++    ff_id_tet =3,
++
++    ff_id_prism =5,
++    ff_id_hex =6,
++    ff_id_quad =7,
++    ff_id_corner=8
++} ;
++
++
++typedef struct  DataFF 
++{
++  const char  * meshname;
++  const char  * movename;
++  const char  * solname;
++  int imprim;
++  int memory;
++  int   np; //  nb of vertices  in/out 
++  int   typesol; //  1 iso , 6 : m11; m12,m13,m22,m23,m33
++  void * mesh;
++  double * sol; /* metric :size typesol*np  */
++  double * mov; /* displac. size :3*np  */ 
++  void (*set_mesh)(void *dataff,int *data,int ldata);
++  void (*end_mesh)(void *dataff);
++  void (*set_v)(void *dataff,int i,double *xyz,int lab);
++  void (*set_elmt)(void *dataff,int ff_id,int i,int *k,int lab);
++  void (*get_mesh)(void *dataff,int *data,int ldata);
++  void (*get_v3)(void *dataff,int i,double *xyz,int *lab);
++  void (*get_elmt)(void *dataff,int ff_id,int i,int *k,int *lab);
++} DataFF;
++
++#ifdef __cplusplus
++extern "C" {
++#endif  
++    int mainmmg3d(int argc,char *argv[],DataFF *dataff); 
++
++#ifdef __cplusplus
++}
++#endif 
++/*
++ m11 = met[0] 
++ m12 = met[1] 
++ m13 = met[2] 
++ m22 = met[3]
++ m23 = met[4] 
++ m33 = met[5]  
++*/
+diff -r -u mmg3d4/build/sources/delaunay.c mmg3d4-new/build/sources/delaunay.c
+--- mmg3d4/build/sources/delaunay.c	2012-12-19 16:05:32.000000000 +0100
++++ mmg3d4-new/build/sources/delaunay.c	2013-01-18 16:32:41.000000000 +0100
+@@ -728,7 +728,7 @@
+   if ( ppt->tag & M_UNUSED )  return(0);
+ 
+   tref = mesh->tetra[list->tetra[1]/6].ref;
+-#warning remove this test
++  // #warning remove this test
+   for (k=1; k<=lon; k++)
+     if(tref!=mesh->tetra[list->tetra[k]/6].ref)
+       printf("pbs coquil %d %d tet %d\n",tref,mesh->tetra[list->tetra[k]/6].ref,list->tetra[k]/6);
+diff -r -u mmg3d4/build/sources/libmmg3d.h mmg3d4-new/build/sources/libmmg3d.h
+--- mmg3d4/build/sources/libmmg3d.h	2012-12-19 16:05:36.000000000 +0100
++++ mmg3d4-new/build/sources/libmmg3d.h	2013-01-18 16:32:41.000000000 +0100
+@@ -118,12 +118,12 @@
+ typedef MMG_Sol * MMG_pSol;
+ 
+ /* inout */
+-int  MMG_loadMesh(MMG_pMesh ,char *);
+-int  MMG_loadSol(MMG_pSol ,char *,int );
+-int  MMG_loadVect(MMG_pMesh ,char *,int );
+-int  MMG_saveMesh(MMG_pMesh ,char *);
+-int  MMG_saveSol(MMG_pMesh ,MMG_pSol ,char *);
+-int  MMG_saveVect(MMG_pMesh ,char *);
++int  MMG_loadMesh(MMG_pMesh ,char *,void *);
++int  MMG_loadSol(MMG_pSol ,char *,int ,void *);
++int  MMG_loadVect(MMG_pMesh ,char *,int ,void *);
++int  MMG_saveMesh(MMG_pMesh ,char *,void *);
++int  MMG_saveSol(MMG_pMesh ,MMG_pSol ,char *,void *);
++int  MMG_saveVect(MMG_pMesh ,char *,void *);
+ 
+ #ifdef  __cplusplus
+ namespace mmg3d{
+diff -r -u mmg3d4/build/sources/mesh.h mmg3d4-new/build/sources/mesh.h
+--- mmg3d4/build/sources/mesh.h	2012-12-19 16:05:36.000000000 +0100
++++ mmg3d4-new/build/sources/mesh.h	2013-01-18 16:32:41.000000000 +0100
+@@ -405,17 +405,17 @@
+ 
+ /* function pointers */
+ typedef int (*MMG_Swap)(pMesh ,pSol ,pList );
+-MMG_Swap MMG_swpptr;
+-double (*MMG_length)(double *,double *,double *,double *);
+-double (*MMG_caltet)(pMesh ,pSol ,int );
+-double (*MMG_calte1)(pMesh ,pSol ,int );
+-int    (*MMG_caltet2)(pMesh ,pSol ,int ,int ,double ,double *);
+-int    (*MMG_cavity)(pMesh ,pSol ,int ,int ,pList ,int );
+-int    (*MMG_buckin)(pMesh ,pSol ,pBucket ,int );
+-int    (*MMG_optlen)(pMesh ,pSol ,double ,int );
+-int    (*MMG_interp)(double *,double *,double *,double );
+-int    (*MMG_optlentet)(pMesh ,pSol ,pQueue ,double ,int ,int );
+-int    (*MMG_movevertex)(pMesh ,pSol ,int ,int );
++extern MMG_Swap MMG_swpptr;
++extern double (*MMG_length)(double *,double *,double *,double *);
++extern double (*MMG_caltet)(pMesh ,pSol ,int );
++extern double (*MMG_calte1)(pMesh ,pSol ,int );
++extern int    (*MMG_caltet2)(pMesh ,pSol ,int ,int ,double ,double *);
++extern int    (*MMG_cavity)(pMesh ,pSol ,int ,int ,pList ,int );
++extern int    (*MMG_buckin)(pMesh ,pSol ,pBucket ,int );
++extern int    (*MMG_optlen)(pMesh ,pSol ,double ,int );
++extern int    (*MMG_interp)(double *,double *,double *,double );
++extern int    (*MMG_optlentet)(pMesh ,pSol ,pQueue ,double ,int ,int );
++extern int    (*MMG_movevertex)(pMesh ,pSol ,int ,int );
+ 
+ 
+ #endif
+diff -r -u mmg3d4/build/sources/mmg3d4.c mmg3d4-new/build/sources/mmg3d4.c
+--- mmg3d4/build/sources/mmg3d4.c	2012-12-19 16:05:33.000000000 +0100
++++ mmg3d4-new/build/sources/mmg3d4.c	2013-01-18 18:28:05.000000000 +0100
+@@ -3,32 +3,32 @@
+ Co-auteurs : Cecile Dobrzynski et Pascal Frey.
+ Propriétaires :IPB - UPMC -INRIA.
+ 
+-Copyright © 2004-2005-2006-2007-2008-2009-2010-2011,
++Copyright © 2004-2005-2006-2007-2008-2009-2010-2011, 
+ diffusé sous les termes et conditions de la licence publique générale de GNU
+-Version 3 ou toute version ultérieure.
++Version 3 ou toute version ultérieure.  
+ 
+ Ce fichier est une partie de MMG3D.
+ MMG3D est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier
+ suivant les termes de la licence publique générale de GNU
+ Version 3 ou toute version ultérieure.
+-MMG3D est distribué dans l'espoir qu'il sera utile, mais SANS
+-AUCUNE GARANTIE ; sans même garantie de valeur marchande.
++MMG3D est distribué dans l'espoir qu'il sera utile, mais SANS 
++AUCUNE GARANTIE ; sans même garantie de valeur marchande.  
+ Voir la licence publique générale de GNU pour plus de détails.
+-MMG3D est diffusé en espérant qu’il sera utile,
+-mais SANS AUCUNE GARANTIE, ni explicite ni implicite,
+-y compris les garanties de commercialisation ou
+-d’adaptation dans un but spécifique.
++MMG3D est diffusé en espérant qu’il sera utile, 
++mais SANS AUCUNE GARANTIE, ni explicite ni implicite, 
++y compris les garanties de commercialisation ou 
++d’adaptation dans un but spécifique. 
+ Reportez-vous à la licence publique générale de GNU pour plus de détails.
+-Vous devez avoir reçu une copie de la licence publique générale de GNU
+-en même temps que ce document.
++Vous devez avoir reçu une copie de la licence publique générale de GNU 
++en même temps que ce document. 
+ Si ce n’est pas le cas, aller voir <http://www.gnu.org/licenses/>.
+ /****************************************************************************
+ Initial software: MMG3D Version 4.0
+ Co-authors: Cecile Dobrzynski et Pascal Frey.
+ Owners: IPB - UPMC -INRIA.
+ 
+-Copyright © 2004-2005-2006-2007-2008-2009-2010-2011,
+-spread under the terms and conditions of the license GNU General Public License
++Copyright © 2004-2005-2006-2007-2008-2009-2010-2011, 
++spread under the terms and conditions of the license GNU General Public License 
+ as published Version 3, or (at your option) any later version.
+ 
+ This file is part of MMG3D
+@@ -41,26 +41,26 @@
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+-along with MMG3D. If not, see <http://www.gnu.org/licenses/>.
++along with MMG3D. If not, see <http://www.gnu.org/licenses/>.  
+ ****************************************************************************/
+ #include "mesh.h"
+ 
+-int MMG_npuiss,MMG_nvol,MMG_npres;
+-int MMG_nlen,MMG_ncal,MMG_ntopo,MMG_nex;
+-int MMG_npuisstot,MMG_nvoltot,MMG_nprestot;
+-int MMG_npdtot;
+-int MMG_nplen,MMG_npref,MMG_bouffe;
++extern int MMG_npuiss,MMG_nvol,MMG_npres;
++extern int MMG_nlen,MMG_ncal,MMG_ntopo,MMG_nex;
++extern int MMG_npuisstot,MMG_nvoltot,MMG_nprestot;
++extern int MMG_npdtot;
++extern int MMG_nplen,MMG_npref,MMG_bouffe;
+ 
+ int ddebug;
+ 
+ int MMG_mmg3d4(pMesh mesh,pSol sol,int *alert) {
+   Hedge    hash;
+-  pBucket        bucket;
++  pBucket	 bucket; 
+   double   declic;
+-  int              base,na,nd,ns,nna,nnd,nns,dd,it,nf,maxtou;
+-  double   lmoy,LLLONG;
+-  int k;
+-  pTetra pt;
++  int		   base,na,nd,ns,nna,nnd,nns,dd,it,nf,maxtou; 
++  double   lmoy,LLLONG;                      
++	int k;
++	pTetra pt;
+   if ( abs(mesh->info.imprim) > 3 )
+     fprintf(stdout,"  ** SIZE OPTIMIZATION\n");
+   if ( mesh->info.imprim < 0 ) {
+@@ -73,82 +73,82 @@
+   maxtou = 10;
+   nna = nns = nnd = 0;
+   it  = 0;
+-  declic = 3. / ALPHAD;
++  declic = 3. / ALPHAD;  
+   lmoy = 10.;
+   LLLONG = 1.5;
+-
++  
+   nna = 10;
+-  do {
+-    na  = nd  = ns  = 0;
++  do { 
++    na  = nd  = ns  = 0; 
+     if(0) ddebug = 1;
+     else ddebug = 0;
+-
++    
+     if(it && !(it%2) ) {
+       bucket = MMG_newBucket(mesh,M_MAX(mesh->info.bucksiz,BUCKSIZ));
+       if ( !bucket )  return(0);
+-      //MMG_saveMesh(mesh,"avtana.mesh");
+-      MMG_analar(mesh,sol,bucket,&na,&nd,&nf,alert);
+-      //MMG_saveMesh(mesh,"apresana.mesh");
+-      if ( abs(mesh->info.imprim) > 5 )
+-	fprintf(stdout,"     %7d INSERTED  %7d REMOVED   %7d FILTERED\n",na,nd,nf);
+-
+-      M_free(bucket->head);
+-      M_free(bucket->link);
+-      M_free(bucket);
+-
++			//MMG_saveMesh(mesh,"avtana.mesh",0);
++      MMG_analar(mesh,sol,bucket,&na,&nd,&nf,alert);      
++			//MMG_saveMesh(mesh,"apresana.mesh",0);
++      if ( abs(mesh->info.imprim) > 5 ) 
++        fprintf(stdout,"     %7d INSERTED  %7d REMOVED   %7d FILTERED\n",na,nd,nf);  
++
++	    M_free(bucket->head);
++	    M_free(bucket->link);
++	    M_free(bucket);
++        
+     } else {
+-      ++mesh->flag;
++        ++mesh->flag;
+     }
+-    //printf("IT %d $$$$$$$$$$$ LLLONG  %9.3f\n",it,LLLONG);
+-    nna = nns = nnd = 0;
+-
++    //printf("IT %d $$$$$$$$$$$ LLLONG  %9.3f\n",it,LLLONG); 
++    nna = nns = nnd = 0; 
++      
+     /*splitting*/
+     if ( !mesh->info.noinsert && (!*alert)  ) {
+       /* store points on edges */
+       if ( !MMG_zaldy4(&hash,mesh->np) ) {
+-	if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM.\n");
+-	*alert = 2;
+-	break;
++        if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM.\n"); 
++        *alert = 2;
++        break;
+       }
+-      nna = MMG_analarcutting(mesh,sol,&hash,alert,&lmoy,LLLONG);
++      nna = MMG_analarcutting(mesh,sol,&hash,alert,&lmoy,LLLONG); 
+       if ( abs(mesh->info.imprim) > 5 ) { printf("lmoy %9.5f\n",lmoy); }
+       /*puts("--------------------------------------");
+-	puts("--------------------------------------");
+-	puts("--------------------------------------");
+-      */
++      puts("--------------------------------------");
++      puts("--------------------------------------");
++      */                             
+       if ( *alert ) {
+-	fprintf(stdout," \n\n ** UNABLE TO CUT (analarcutting)\n");
+-	fprintf(stdout," ** RETRY WITH -m > %6d \n\n",mesh->info.memory);
+-	MMG_saveMesh(mesh,"crash.mesh");
+-	MMG_saveSol(mesh,sol,"crash.sol");
+-	exit(0);
++        fprintf(stdout," \n\n ** UNABLE TO CUT (analarcutting)\n");
++        fprintf(stdout," ** RETRY WITH -m > %6d \n\n",mesh->info.memory);
++        MMG_saveMesh(mesh,"crash.mesh",0);
++        MMG_saveSol(mesh,sol,"crash.sol",0); 
++        exit(0);
+       }
+-      M_free(hash.item);
++      M_free(hash.item);        
+     }
+-    else if ( *alert )  nna = 0;
+-    /* adjacencies */
++    else if ( *alert )  nna = 0;  
++    /* adjacencies */ 
+     if ( nna /*|| it == (maxtou-1)*/ ) {
+       mesh->nt = 0;
+       if ( !MMG_hashTetra(mesh) )  return(0);
+       if ( !MMG_markBdry(mesh) )   return(0);
+     }
+-    // printf("chkmsh\n");
+-    // MMG_unscaleMesh(mesh,sol);
+-    //     MMG_saveMesh(mesh,"chk.mesh");
++    // printf("chkmsh\n");   
++		// MMG_unscaleMesh(mesh,sol);
++		//     MMG_saveMesh(mesh,"chk.mesh",0);
+     //MMG_chkmsh(mesh,1,-1);
+-    //if(it==1)exit(0);
+-    /* delaunization */
+-    if ( !mesh->info.noswap && (nna || na) ) {
++		//if(it==1)exit(0);		
++     /* delaunization */
++    if ( !mesh->info.noswap && (nna || na) ) {  
+       nns   =  MMG_cendel(mesh,sol,declic,base);
+     }
+ 
+     /* deletion */
+     /*if ( 0 && nna ) {
+       nnd   = MMG_colvert(mesh,sol,base);
+-      } */
++    } */
+     if ( nna+nnd+nns && abs(mesh->info.imprim) > 3 )
+       fprintf(stdout,"     %7d INSERTED  %7d REMOVED   %7d FLIPPED\n",nna+na,nnd+nd,nns);
+-
++    
+   }
+   while ( na+nd+nns+nna+nnd > 0 && ++it < maxtou && lmoy > 1.3);
+ 
+@@ -161,80 +161,80 @@
+     MMG_prilen(mesh,sol);
+   }
+ 
+-  //return(1);
+-  //MMG_saveMesh(mesh,"aprescut.mesh");
+-  fprintf(stdout,"    ---\n");
+-
++	//return(1);
++	//MMG_saveMesh(mesh,"aprescut.mesh",0);
++	fprintf(stdout,"    ---\n");
++  
+   /*analyze standard*/
+-  base   = mesh->flag;
+-  *alert = 0;
++    base   = mesh->flag;
++    *alert = 0;
+ 
+-  nna = 0;
+-  nnd = 0;
+-  nf  = 0;
+-  it  = 0;
+-  maxtou = 100;
+-  MMG_npdtot=0;
+-  MMG_npuisstot=0;
+-  MMG_nprestot=0;
+-  MMG_nvoltot=0;
+-
+-  /* 2. field points */
+-  if ( mesh->info.imprim < -4 ) {
+-    MMG_prilen(mesh,sol);
+-    fprintf(stdout,"  -- FIELD POINTS\n");
+-  }
+-
+-  /* create filter */
+-  bucket = MMG_newBucket(mesh,M_MAX(mesh->info.bucksiz,BUCKSIZ));
+-  if ( !bucket )  return(0);
+-
+-  do {
+-    MMG_analar(mesh,sol,bucket,&na,&nd,&nf,alert);
+-    nna += na;
+-    nnd += nd;
+-    if ( *alert ) {
+-      if ( nd < 1000 )  break;
+-      else  *alert = 0;
+-    }
+-    if ( it > 5 ) {
+-      dd = abs(nd-na);
+-      if ( dd < 5 || dd < 0.05*nd )   break;
+-      else if ( it > 12 && nd >= na )  break;
+-    }
+-    if ( na+nd && abs(mesh->info.imprim) > 3 )
+-      fprintf(stdout,"     %7d INSERTED  %7d REMOVED   %7d FILTERED\n",na,nd,nf);
+-    // MMG_saveMesh(mesh,"chk.mesh");
+-    // //if(it==1) exit(0);
+-  }
+-  while ( na+nd > 0 && ++it < maxtou );
+-
+-  if ( nna+nnd && abs(mesh->info.imprim) < 3 ) {
+-    fprintf(stdout,"     %7d INSERTED  %7d REMOVED  %7d FILTERED\n",na,nd,nf);
+-  }
+-
+-  if(MMG_npdtot>0) {
+-    fprintf(stdout,"    REJECTED : %5d\n",MMG_npdtot);
+-    fprintf(stdout,"          VOL      : %6.2f %%    %5d \n",
+-	    100*(MMG_nvoltot/(float)
+-		 MMG_npdtot),MMG_nvoltot);
+-    fprintf(stdout,"          PUISS    : %6.2f %%    %5d \n",
+-	    100*(MMG_npuisstot/(float) MMG_npdtot),MMG_npuisstot);
+-    fprintf(stdout,"         PROCHE    : %6.2f %%    %5d \n",
+-	    100*(MMG_nprestot/(float) MMG_npuisstot),MMG_nprestot);
++    nna = 0;
++    nnd = 0;
++    nf  = 0;
++    it  = 0;
++    maxtou = 100;
+     MMG_npdtot=0;
+     MMG_npuisstot=0;
++    MMG_nprestot=0;
+     MMG_nvoltot=0;
+-  }
+-  if ( mesh->info.imprim < 0 ) {
+-    MMG_outqua(mesh,sol);
+-    MMG_prilen(mesh,sol);
+-  }
+ 
+-  M_free(bucket->head);
+-  M_free(bucket->link);
+-  M_free(bucket);
++    /* 2. field points */
++    if ( mesh->info.imprim < -4 ) {
++      MMG_prilen(mesh,sol);
++      fprintf(stdout,"  -- FIELD POINTS\n");
++    }
++
++    /* create filter */
++    bucket = MMG_newBucket(mesh,M_MAX(mesh->info.bucksiz,BUCKSIZ));
++    if ( !bucket )  return(0);
++
++    do {
++      MMG_analar(mesh,sol,bucket,&na,&nd,&nf,alert);    
++      nna += na;
++      nnd += nd;
++      if ( *alert ) {
++        if ( nd < 1000 )  break;
++        else  *alert = 0;
++      }
++      if ( it > 5 ) {
++        dd = abs(nd-na);
++        if ( dd < 5 || dd < 0.05*nd )   break;
++        else if ( it > 12 && nd >= na )  break;
++      }
++      if ( na+nd && abs(mesh->info.imprim) > 3 )
++        fprintf(stdout,"     %7d INSERTED  %7d REMOVED   %7d FILTERED\n",na,nd,nf);    
++			// MMG_saveMesh(mesh,"chk.mesh",0);
++			// //if(it==1) exit(0);
++    }
++    while ( na+nd > 0 && ++it < maxtou );
++
++    if ( nna+nnd && abs(mesh->info.imprim) < 3 ) {
++      fprintf(stdout,"     %7d INSERTED  %7d REMOVED  %7d FILTERED\n",na,nd,nf);
++    }
++
++  if(MMG_npdtot>0) { 
++  fprintf(stdout,"    REJECTED : %5d\n",MMG_npdtot);
++  fprintf(stdout,"          VOL      : %6.2f %%    %5d \n",
++  	100*(MMG_nvoltot/(float)
++  MMG_npdtot),MMG_nvoltot); 
++  fprintf(stdout,"          PUISS    : %6.2f %%    %5d \n",
++  	100*(MMG_npuisstot/(float) MMG_npdtot),MMG_npuisstot);
++  fprintf(stdout,"         PROCHE    : %6.2f %%    %5d \n",
++  	100*(MMG_nprestot/(float) MMG_npuisstot),MMG_nprestot);	
++  MMG_npdtot=0;
++  MMG_npuisstot=0;
++  MMG_nvoltot=0;  
++  } 
++    if ( mesh->info.imprim < 0 ) {
++      MMG_outqua(mesh,sol);
++      MMG_prilen(mesh,sol);
++    }
+ 
++    M_free(bucket->head);
++    M_free(bucket->link);
++    M_free(bucket);
++  
+ 
+   return(1);
+ }
+diff -r -u mmg3d4/build/sources/mmg3dConfig.h mmg3d4-new/build/sources/mmg3dConfig.h
+--- mmg3d4/build/sources/mmg3dConfig.h	2012-12-19 16:05:36.000000000 +0100
++++ mmg3d4-new/build/sources/mmg3dConfig.h	2013-01-18 16:32:41.000000000 +0100
+@@ -2,4 +2,4 @@
+ #define Tutorial_VERSION_MAJOR 
+ #define Tutorial_VERSION_MINOR 
+ 
+-#define USE_SCOTCH
++/* #undef USE_SCOTCH */
+diff -r -u mmg3d4/build/sources/mmg3dlib/mmg3dlib.c mmg3d4-new/build/sources/mmg3dlib/mmg3dlib.c
+--- mmg3d4/build/sources/mmg3dlib/mmg3dlib.c	2012-12-19 16:06:03.000000000 +0100
++++ mmg3d4-new/build/sources/mmg3dlib/mmg3dlib.c	2013-01-18 16:32:41.000000000 +0100
+@@ -385,7 +385,7 @@
+   if ( !MMG_hashTetra(mesh) )    return(1);
+   if ( !MMG_markBdry(mesh) )     return(1);
+   if (abs(mesh->info.option)==10) {
+-    MMG_saveMesh(mesh,"tetra.mesh");
++    MMG_saveMesh(mesh,"tetra.mesh",0);
+     return(0);
+   }           
+   if ( !sol->np) {
+@@ -431,7 +431,7 @@
+     if ( abs(info->option) == 9 ) {  
+       if(!MMG_mmg3d9(mesh,sol,&alert)) {
+         if ( !MMG_unscaleMesh(mesh,sol) )  return(1);
+-        MMG_saveMesh(mesh,"errormoving.mesh");
++        MMG_saveMesh(mesh,"errormoving.mesh",0);
+ 	      //MMG_saveSol(mesh,sol,mesh->outf);
+ 	      return(1);
+       }
+diff -r -u mmg3d4/build/sources/optlen.c mmg3d4-new/build/sources/optlen.c
+--- mmg3d4/build/sources/optlen.c	2012-12-19 16:05:33.000000000 +0100
++++ mmg3d4-new/build/sources/optlen.c	2013-01-18 16:32:41.000000000 +0100
+@@ -48,7 +48,7 @@
+ #define  HQCOEF    0.9 
+ #define  HCRIT     0.98
+ 
+-double MMG_rao(pMesh mesh,int k,int inm);
++double MMG_rao(pMesh mesh,int k,FILE* );
+ int MMG_optlen_ani(pMesh mesh,pSol sol,double declic,int base) {
+   pTetra    pt,pt1;
+   pPoint    ppa,ppb;
+diff -r -u mmg3d4/build/sources/pattern.c mmg3d4-new/build/sources/pattern.c
+--- mmg3d4/build/sources/pattern.c	2012-12-19 16:05:33.000000000 +0100
++++ mmg3d4-new/build/sources/pattern.c	2013-01-18 18:41:02.000000000 +0100
+@@ -47,7 +47,7 @@
+ 
+ 
+ unsigned char MMG_arfa[3][4] = { {2,0,1,3}, {1,2,0,3}, {0,1,2,3} };
+-extern int MMG_permar[10][4];
++extern int MMG_permar[12][4];
+ extern int MMG_pointar[64][2];
+ extern int ddebug;
+ //insert ip on ia-ib
+diff -r -u mmg3d4/build/sources/quality.c mmg3d4-new/build/sources/quality.c
+--- mmg3d4/build/sources/quality.c	2012-12-19 16:05:33.000000000 +0100
++++ mmg3d4-new/build/sources/quality.c	2013-01-18 16:32:41.000000000 +0100
+@@ -46,7 +46,7 @@
+ #include "mesh.h"  
+ 
+ 
+-double MMG_rao(pMesh mesh,int k,int inm);
++double MMG_rao(pMesh mesh,int k,FILE* inm) ;
+ double MMG_caltetrao(pMesh mesh,pSol sol,int iel) {
+ 	return(MMG_rao(mesh,iel,0));
+ }
+diff -r -u mmg3d4/build/sources/ratio.c mmg3d4-new/build/sources/ratio.c
+--- mmg3d4/build/sources/ratio.c	2012-12-19 16:05:33.000000000 +0100
++++ mmg3d4-new/build/sources/ratio.c	2013-01-18 16:32:41.000000000 +0100
+@@ -365,7 +365,7 @@
+   fprintf(stdout,"           ELEMENT   %d (%d)   %d %d %d %d\n",
+ 	  iel,ielreal,pt->v[0],pt->v[1],pt->v[2],pt->v[3]);
+ 
+-  if ( abs(mesh->info.imprim) < 5 )  return;
++  if ( abs(mesh->info.imprim) < 5 )  return (1) ;
+ 
+   fprintf(stdout,"\n     HISTOGRAMM\n");
+   for (k=1; k<9; k++) {
+diff -r -u mmg3d4/build/sources/sproto.h mmg3d4-new/build/sources/sproto.h
+--- mmg3d4/build/sources/sproto.h	2012-12-19 16:05:36.000000000 +0100
++++ mmg3d4-new/build/sources/sproto.h	2013-01-18 16:32:41.000000000 +0100
+@@ -67,13 +67,13 @@
+ int  MMG_inEdge(pHedge ,int *,int *,int *);
+ int  MMG_markBdry(pMesh );
+ 
+-/* inout */
+-int  MMG_loadMesh(pMesh ,char *);
+-int  MMG_loadSol(pSol ,char *,int );
+-int  MMG_loadVect(pMesh ,char *,int );
+-int  MMG_saveMesh(pMesh ,char *);
+-int  MMG_saveSol(pMesh ,pSol ,char *);
+-int  MMG_saveVect(pMesh ,char *);
++/* inout add param  F.H. june 2011 (dataff) */
++int  MMG_loadMesh(pMesh ,char *,void *);
++int  MMG_loadSol(pSol ,char *,int ,void *);
++int  MMG_loadVect(pMesh ,char *,int ,void *);
++int  MMG_saveMesh(pMesh ,char *,void *);
++int  MMG_saveSol(pMesh ,pSol ,char *,void *);
++int  MMG_saveVect(pMesh ,char *,void *);
+ 
+ int  MMG_loctet(pMesh ,int ,int ,double *,double *);
+ int  MMG_computeMetric(pMesh ,pSol ,int ,double * );
+diff -r -u mmg3d4/build/sources/swapar.c mmg3d4-new/build/sources/swapar.c
+--- mmg3d4/build/sources/swapar.c	2012-12-19 16:05:33.000000000 +0100
++++ mmg3d4-new/build/sources/swapar.c	2013-01-18 18:43:38.000000000 +0100
+@@ -1,106 +1,107 @@
+-/****************************************************************************
+-Logiciel initial: MMG3D Version 4.0
+-Co-auteurs : Cecile Dobrzynski et Pascal Frey.
+-Propriétaires :IPB - UPMC -INRIA.
+-
+-Copyright © 2004-2005-2006-2007-2008-2009-2010-2011,
+-diffusé sous les termes et conditions de la licence publique générale de GNU
+-Version 3 ou toute version ultérieure.
+-
+-Ce fichier est une partie de MMG3D.
+-MMG3D est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier
+-suivant les termes de la licence publique générale de GNU
+-Version 3 ou toute version ultérieure.
+-MMG3D est distribué dans l'espoir qu'il sera utile, mais SANS
+-AUCUNE GARANTIE ; sans même garantie de valeur marchande.
+-Voir la licence publique générale de GNU pour plus de détails.
+-MMG3D est diffusé en espérant qu’il sera utile,
+-mais SANS AUCUNE GARANTIE, ni explicite ni implicite,
+-y compris les garanties de commercialisation ou
+-d’adaptation dans un but spécifique.
+-Reportez-vous à la licence publique générale de GNU pour plus de détails.
+-Vous devez avoir reçu une copie de la licence publique générale de GNU
+-en même temps que ce document.
+-Si ce n’est pas le cas, aller voir <http://www.gnu.org/licenses/>.
+-/****************************************************************************
+-Initial software: MMG3D Version 4.0
+-Co-authors: Cecile Dobrzynski et Pascal Frey.
+-Owners: IPB - UPMC -INRIA.
+-
+-Copyright © 2004-2005-2006-2007-2008-2009-2010-2011,
+-spread under the terms and conditions of the license GNU General Public License
+-as published Version 3, or (at your option) any later version.
+-
+-This file is part of MMG3D
+-MMG3D is free software; you can redistribute it and/or modify
+-it under the terms of the GNU General Public License as published by
+-the Free Software Foundation; either version 3 of the License, or
+-(at your option) any later version.
+-MMG3D is distributed in the hope that it will be useful,
+-but WITHOUT ANY WARRANTY; without even the implied warranty of
+-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-GNU General Public License for more details.
+-You should have received a copy of the GNU General Public License
+-along with MMG3D. If not, see <http://www.gnu.org/licenses/>.
+-****************************************************************************/
+-#include "mesh.h"
+-
+-int MMG_swapar(pMesh mesh,pSol sol,pQueue q,List *list,int lon,double crit,double declic) {
+-  pTetra   pt;
+-  int      i,l,jel,ncas,ddebug,iadr;
+-
+-  MMG_swpptr = 0;
+-  ncas   = 0;
+-  if ( !MMG_getnElt(mesh,10) )  return(-1);
+-  if(0 && list->tetra[1]/6==2352) ddebug=1;
+-  else ddebug=0;
+-
+-  switch(lon) {
+-  case 3:
+-    ncas = MMG_simu32(mesh,sol,list,crit);
+-    break;
+-  case 4:
+-    ncas = MMG_simu44(mesh,sol,list,crit);
+-    break;
+-  case 5:
+-    ncas = MMG_simu56(mesh,sol,list,crit);
+-    break;
+-  case 6:
+-    ncas = MMG_simu68(mesh,sol,list,crit);
+-    break;
+-  case 7:
+-    ncas = MMG_simu710(mesh,sol,list,crit);
+-    break;
+-  default:
+-    return(0);
+-  }
+-  if(ddebug) printf("on fait swap %d\n",ncas);
+-  if ( ncas && MMG_swpptr ) {
+-    if(ddebug) MMG_saveMesh(mesh,"avt.mesh");
+-    for (l=1; l<=lon; l++) {
+-      jel = list->tetra[l]/6;
+-      pt  = &mesh->tetra[jel];
+-      if(ddebug) {
+-	printf("tet %d : %d %d %d %d -- %d %d %d %d %d %d\n",jel,pt->v[0],pt->v[1],pt->v[2],pt->v[3],
+-	       pt->bdryinfo[0],pt->bdryinfo[1],pt->bdryinfo[2],pt->bdryinfo[3],pt->bdryinfo[4],pt->bdryinfo[5]);
+-
+-      }
+-      MMG_kiudel(q,jel);
+-    }
+-    lon = MMG_swpptr(mesh,sol,list);
+-    assert(lon);
+-    if(!lon) return(0);
+-
+-    for (l=1; l<=lon; l++) {
+-      jel = list->tetra[l];
+-      pt  = &mesh->tetra[jel];
+-      if ( pt->qual >= declic )  MMG_kiuput(q,jel);
+-      for (i=0; i<4; i++)  mesh->point[pt->v[i]].flag = mesh->flag;
+-
+-    }
+-    if(ddebug) {MMG_saveMesh(mesh,"sw.mesh");    exit(0);}
+-    return(1);
+-  }
+-
+-  return(0);
+-}
++/****************************************************************************
++Logiciel initial: MMG3D Version 4.0
++Co-auteurs : Cecile Dobrzynski et Pascal Frey.
++Propriétaires :IPB - UPMC -INRIA.
++
++Copyright © 2004-2005-2006-2007-2008-2009-2010-2011, 
++diffusé sous les termes et conditions de la licence publique générale de GNU
++Version 3 ou toute version ultérieure.  
++
++Ce fichier est une partie de MMG3D.
++MMG3D est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier
++suivant les termes de la licence publique générale de GNU
++Version 3 ou toute version ultérieure.
++MMG3D est distribué dans l'espoir qu'il sera utile, mais SANS 
++AUCUNE GARANTIE ; sans même garantie de valeur marchande.  
++Voir la licence publique générale de GNU pour plus de détails.
++MMG3D est diffusé en espérant qu’il sera utile, 
++mais SANS AUCUNE GARANTIE, ni explicite ni implicite, 
++y compris les garanties de commercialisation ou 
++d’adaptation dans un but spécifique. 
++Reportez-vous à la licence publique générale de GNU pour plus de détails.
++Vous devez avoir reçu une copie de la licence publique générale de GNU 
++en même temps que ce document. 
++Si ce n’est pas le cas, aller voir <http://www.gnu.org/licenses/>.
++/****************************************************************************
++Initial software: MMG3D Version 4.0
++Co-authors: Cecile Dobrzynski et Pascal Frey.
++Owners: IPB - UPMC -INRIA.
++
++Copyright © 2004-2005-2006-2007-2008-2009-2010-2011, 
++spread under the terms and conditions of the license GNU General Public License 
++as published Version 3, or (at your option) any later version.
++
++This file is part of MMG3D
++MMG3D is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 3 of the License, or
++(at your option) any later version.
++MMG3D is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++GNU General Public License for more details.
++You should have received a copy of the GNU General Public License
++along with MMG3D. If not, see <http://www.gnu.org/licenses/>.  
++****************************************************************************/
++#include "mesh.h"
++
++int MMG_swapar(pMesh mesh,pSol sol,pQueue q,List *list,int lon,double crit,double declic) {
++  pTetra   pt;
++  int      i,l,jel,ncas,ddebug,iadr;
++
++  MMG_swpptr = 0;
++  ncas   = 0;
++  if ( !MMG_getnElt(mesh,10) )  return(-1);
++	if(0 && list->tetra[1]/6==2352) ddebug=1;
++	else ddebug=0;
++	
++  switch(lon) {
++  case 3:
++	  ncas = MMG_simu32(mesh,sol,list,crit);
++    break;
++  case 4:
++	  ncas = MMG_simu44(mesh,sol,list,crit); 
++    break;
++  case 5:
++	ncas = MMG_simu56(mesh,sol,list,crit);
++    break;
++  case 6:
++	ncas = MMG_simu68(mesh,sol,list,crit); 
++    break;
++  case 7:
++	ncas = MMG_simu710(mesh,sol,list,crit);   
++    break;  
++  default:
++    return(0);
++  }
++	if(ddebug) printf("on fait swap %d\n",ncas);
++  if ( ncas && MMG_swpptr ) {
++		if(ddebug) MMG_saveMesh(mesh,"avt.mesh",0);
++    for (l=1; l<=lon; l++) {
++      jel = list->tetra[l]/6;
++      pt  = &mesh->tetra[jel]; 
++			if(ddebug) {
++				printf("tet %d : %d %d %d %d -- %d %d %d %d %d %d\n",jel,pt->v[0],pt->v[1],pt->v[2],pt->v[3],
++					pt->bdryinfo[0],pt->bdryinfo[1],pt->bdryinfo[2],pt->bdryinfo[3],pt->bdryinfo[4],pt->bdryinfo[5]);  
++				
++			} 
++			MMG_kiudel(q,jel);
++    }
++    lon = MMG_swpptr(mesh,sol,list);
++    assert(lon);
++    if(!lon) return(0); 
++    
++    for (l=1; l<=lon; l++) {
++      jel = list->tetra[l];
++      pt  = &mesh->tetra[jel]; 
++      if ( pt->qual >= declic )  MMG_kiuput(q,jel);
++      for (i=0; i<4; i++)  mesh->point[pt->v[i]].flag = mesh->flag;		 
++
++   }
++    if(ddebug) {MMG_saveMesh(mesh,"sw.mesh",0);    exit(0);}
++    return(1);
++  }
++
++  return(0);
++}
++
+diff -u  mmg3d4/build/sources/inout.c mmg3d4-ok/build/sources/inout.c
+--- mmg3d4/build/sources/inout.c	2012-12-19 16:05:32.000000000 +0100
++++ mmg3d4-ok/build/sources/inout.c	2013-07-11 11:43:47.000000000 +0200
+@@ -44,6 +44,7 @@
+ along with MMG3D. If not, see <http://www.gnu.org/licenses/>.
+ ****************************************************************************/
+ #include "mesh.h"
++#include "dataff.h"
+ 
+ 
+ extern short           MMG_imprim;
+@@ -100,35 +101,467 @@
+   return(out);
+ }
+ 
++
++int MMG_loadMeshff(pMesh mesh,char *filename,DataFF *dataff) {  
++   
++    
++    Hedge    				 hed,hed2;
++    pPoint       	   ppt;
++    pTetra           pt;
++    pTria            pt1;
++    int i,j,k; 
++    int nhex=0, npris=0, netmp=0,nq=0, pp[10] , ned=0, ncor=0;
++    int p0,p1,p2,p3,p4,p5,p6,ref ;
++    int data[10],ldata=10;
++    dataff->get_mesh(dataff,data,10);
++    mesh->np = data[ff_id_vertex];
++    ned = data[ff_id_seg];
++    mesh->nt = data[ff_id_tria];
++    mesh->ne = data[ff_id_tet];
++    netmp=mesh->ne;
++    nhex=data[ff_id_hex];
++    npris=data[ff_id_prism]; 
++    nq=data[ff_id_quad];
++    ncor= data[ff_id_corner];
++
++    if( nhex || npris) {
++	printf("mmg3d ff interface , hex or prism NOT SUPPORTED  to day (sorry  FH) \n");
++	goto L0; 
++    }
++    
++    mesh->ncor = 0; 
++    mesh->ver =1;
++    if ( abs(mesh->info.option)==10 ) {
++	fprintf(stdout,"  -- READING %8d HEXA %8d PRISMS\n",nhex,npris);  
++	if(!mesh->ne) netmp = 0;  
++	mesh->ne += 6*nhex + 3*npris; 
++    }
++    
++    if ( abs(mesh->info.imprim) > 5 )
++	fprintf(stdout,"  -- READING DATA for ff interface ");
++    
++    if ( !mesh->np || !mesh->ne ) {
++	fprintf(stdout,"  ** MISSING DATA yy\n");
++	goto L0; ;
++    }
++    if ( !MMG_zaldy(mesh) )  goto L0; 
++    
++    /* read mesh vertices */
++    mesh->npfixe = mesh->np;
++    
++    for (k=1; k<=mesh->np; k++) {
++	ppt = &mesh->point[k];
++	dataff->get_v3(dataff,k,ppt->c,&ppt->ref);
++	ppt->tag  = M_UNUSED;    
++    }
++    
++    /* read mesh triangles */
++    mesh->ntfixe = mesh->nt;
++
++    for (k=1; k<=mesh->nt; k++) {
++	pt1 = &mesh->tria[k]; 
++	dataff->get_elmt(dataff,ff_id_tria,k,pt1->v,&pt1->ref);
++	 
++	}  
++    
++
++
++    /* read mesh quads (option 10)*/ 
++    if(abs(mesh->info.option)==10) { 
++	fprintf(stdout,"     QUADS READING %d\n",nq);
++	mesh->ntfixe += 4*nq;
++        for (k=1; k<=nq; k++) {
++	    dataff->get_elmt(dataff, ff_id_quad ,k,pp,&ref);
++	
++	    pt1 = &mesh->tria[++mesh->nt]; 
++	    pt1->v[0] = pp[0];
++	    pt1->v[1] = pp[1];
++	    pt1->v[2] = pp[2];
++	    pt1->ref  = ref;
++	    pt1 = &mesh->tria[++mesh->nt]; 
++	    pt1->v[0] = pp[0];
++	    pt1->v[1] = pp[2];
++	    pt1->v[2] = pp[3];
++	    pt1->ref  = ref;
++	    pt1 = &mesh->tria[++mesh->nt]; 
++	    pt1->v[0] = pp[0];
++	    pt1->v[1] = pp[1];
++	    pt1->v[2] = pp[3];
++	    pt1->ref  = ref;
++	    pt1 = &mesh->tria[++mesh->nt]; 
++	    pt1->v[0] = pp[1];
++	    pt1->v[1] = pp[2];
++	    pt1->v[2] = pp[3];
++	    pt1->ref  = ref;
++	    
++	}
++    }
++    
++    /*read and store edges*/
++    if (ned) {         
++	if ( !MMG_zaldy4(&hed,ned) ) {
++	    if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : EDGES IGNORED\n"); 
++	    ned = 0;
++	}   
++	mesh->ned = ned;
++	
++	for (k=1; k<=ned; k++) { 
++	   dataff->get_elmt(dataff, ff_id_seg ,k,pp,&ref);
++	   
++	    if(MMG_edgePut(&hed,pp[0],pp[1],2)>1) {
++		fprintf(stdout,"  ## WARNING DOUBLE EDGE : %d %d\n",pp[0],pp[1]);
++	    }
++	}
++    }
++    
++    /* read mesh tetrahedra */
++    mesh->nefixe = mesh->ne;
++ 
++  
++    for (k=1; k<=netmp; k++) { 
++	pt = &mesh->tetra[k];
++	dataff->get_elmt(dataff,ff_id_tet,k,pt->v,&ref);
++	pt->ref  = ref;//0;//ref ;  
++	for(i=0 ; i<4 ; i++)
++	    pt->bdryref[i] = -1;  
++	
++	if (ned) { int nu1,nu2;
++	    for(i=0 ; i<6 ; i++) {                         
++		nu1 = pt->v[MMG_iare[i][0]];
++		nu2 = pt->v[MMG_iare[i][1]];
++		pt->bdryinfo[i] = MMG_edgePoint(&hed,nu1,nu2);
++	    }  			
++	    
++	} else {
++	    for(i=0 ; i<6 ; i++)
++		pt->bdryinfo[i] = 0;  			
++	}
++    }
++    if (ned) M_free(hed.item); 
++    
++    /*read corners*/ 
++    if (ncor) {
++	
++	mesh->ncor = ncor;
++	for (k=1; k<=ncor; k++) { 
++	    dataff->get_elmt(dataff,ff_id_corner,k,&ref,0);
++
++	    ppt = &mesh->point[ref];
++	    ppt->geom = M_CORNER; 
++	} 
++    }
++#ifdef XXXXXXXXXXXXXXX
++    if ( abs(mesh->info.option)==10 ) { 
++	if(bin) {
++	    printf("NOT SUPPORTED\n");
++	    exit(0);
++	} 
++	if ( !MMG_zaldy4(&hed2,3*npris+6*nhex) ) {
++	    if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : PRISM IGNORED\n"); 
++	    npris = 0;
++	    nhex  = 0;
++	}   
++	
++	/*read hexa and transform to tetra*/
++	rewind(inm);
++	fseek(inm,posnhex,SEEK_SET);
++	for (k=1; k<=nhex; k++) {   
++	    fscanf(inm,"%d %d %d %d %d %d %d %d %d",&p0,&p1,&p2,&p3,&p4,&p5,&p6,&p7,&ref); 
++	    //fscanf(inm,"%d %d %d %d %d %d %d %d %d",&p0,&p4,&p2,&p1,&p3,&p5,&p6,&p7,&ref); 
++	    //printf("hex %d : %d %d %d %d %d %d %d %d\n",k,p0,p1,p2,p3,p4,p5,p6,p7);   
++	    MMG_cuthex(mesh,&hed2,netmp+(k-1)*6,p0,p1,p2,p3,p4,p5,p6,p7,ref);
++	}  
++	
++	/*read prism and transform to tetra
++	 ---> compatibility pbs ==> hash edge and switch case*/  
++	rewind(inm);
++	fseek(inm,posnpris,SEEK_SET); 
++	nimp = 0; 
++	ne = netmp+6*nhex;
++	for (k=1; k<=npris; k++) {
++	    fscanf(inm,"%d %d %d %d %d %d %d",&p0,&p1,&p2,&p3,&p4,&p5,&ref); 
++	    if(!MMG_cutprism(mesh,&hed2,ne,p0,p1,p2,p3,p4,p5,ref))
++	      {
++		if(mesh->info.imprim < 0 ) fprintf(stdout,"DECOMPOSITION PRISM INVALID \n\n"); 
++		mesh->ne += 5;
++		ne += 8;
++		nimp++; 
++		continue;
++	      }
++	    ne += 3;
++	}
++	if(abs(mesh->info.imprim) > 3 )fprintf(stdout,"     %d INVALID DECOMPOSITION\n\n",nimp);
++    }
++#endif    
++    if ( abs(mesh->info.imprim) > 3 ) {
++	fprintf(stdout,"     NUMBER OF GIVEN VERTICES   %8d\n",mesh->npfixe);
++	if ( mesh->ntfixe )
++	    fprintf(stdout,"     NUMBER OF GIVEN TRIANGLES  %8d\n",mesh->ntfixe);
++	fprintf(stdout,"     NUMBER OF GIVEN TETRAHEDRA %8d\n",mesh->nefixe);
++	if ( ncor )
++	    fprintf(stdout,"     NUMBER OF GIVEN CORNERS    %8d\n",ncor);
++	if ( ned )
++	    fprintf(stdout,"     NUMBER OF GIVEN EDGES      %8d\n",ned);
++    }
++    //    MMG_saveMesh(mesh,"XXXXX.mesh",0);
++   dataff->mesh=0; // used 
++    return 1; 
++L0: 
++    dataff->mesh=0;// used 
++    return 1; 
++}
++
++int MMG_loadSolff(pSol sol,char *filename,int npmax,DataFF *dataff) { 
++   
++     double     tmp , *dsol ;       
++    int         binch,bdim,iswp;
++    int         k,i,isol,type,bin,dim,btyp,bpos;
++    long        posnp;
++    char        *ptr,data[128],chaine[128];
++    if( ! dataff->sol){
++	fprintf(stdout,"  ** MISSING DATA metrix ff \n");
++	return(1);
++    }
++    dsol = dataff->sol;
++    dataff->sol=0;// used 
++    
++
++    btyp = (dataff->typesol== 6)  ?  3: dataff->typesol ;
++    sol->np= dataff->np;
++    
++    if ( !sol->np ) {
++	fprintf(stdout,"  ** MISSING DATA zz\n");
++	return(1);
++    }
++    
++    if ( btyp!= 1 && btyp!=3 ) {
++      fprintf(stdout,"  ** DATA IGNORED (ff) btyp=%d\n",btyp);
++	sol->np = 0;
++	return(1);
++    }
++    
++    sol->offset = (btyp==1) ? 1 : 6;
++    
++    if ( abs(MMG_imprim) > 5 )
++	fprintf(stdout,"  -- READING DATA FILE(ff) %s\n",data);
++    
++    if ( !sol->np ) {
++	fprintf(stdout,"  ** MISSING DATA  no metrix  \n");
++	return(0);
++    }
++    sol->npfixe = sol->np;
++    sol->npmax  = npmax;
++    if ( !MMG_zaldy3(sol) )  return(0);
++    
++    /* read mesh solutions */
++    sol->npfixe = sol->np;
++ 
++    for (k=1; k<=sol->np; k++) {
++	isol = (k-1) * sol->offset + 1;
++	    for (i=0; i<sol->offset; i++) 		     
++		    sol->met[isol + i] = *dsol++;
++
++    }
++    
++    if ( abs(MMG_imprim) > 3 )
++	fprintf(stdout,"     NUMBER OF GIVEN DATA       %8d\n",sol->npfixe);
++    
++ 
++    return(1);  
++
++}
++/* load solution (metric) */
++int MMG_loadVectff(pMesh mesh,char *filename,int npmax,DataFF *dataff) {
++  
++      
++    pDispl       pd;
++    int         binch,bdim,iswp;
++    int         k,i,type,bin,dim,btyp,bpos,iadr;
++    long        posnp;
++    char        *ptr,data[128],chaine[128];
++    double *fsol = dataff->mov;
++    dataff->mov=0;// used 
++    
++    pd = mesh->disp;
++    pd->np =mesh->np ;
++ 
++       if ( !pd->np || !fsol  ) {
++	 fprintf(stdout,"  ** MISSING DATA dep ff %d %p\n",pd->np, fsol);
++	return(0);
++    }
++   
++    
++    if ( abs(mesh->info.imprim) > 5 )
++	fprintf(stdout,"  -- COPY DATA form ff interface  %s\n",data);
++    
++    /* read mesh solutions */
++    for (k=1; k<=pd->np; k++) {
++	iadr = (k - 1) * 3 + 1;
++	
++	    for (i=0; i<3; i++) {
++		    pd->mv[iadr + i] =  *fsol++;
++		}
++	    } 
++           
++    
++    
++    if ( abs(mesh->info.imprim) > 3 )
++	fprintf(stdout,"     NUMBER OF GIVEN DATA       %8d\n",pd->np);
++       return(1);
++  
++    
++}
++int MMG_saveMeshff(pMesh mesh,char *filename,DataFF *dataff) {  
++    
++    pPoint       	   ppt;
++    pTetra           pt;
++    pTria            pt1;
++    int j,k,np,nc,k0;
++    int data[10],ldata=10;
++    int kn[10];
++    np = 0; 
++    nc = 0;
++    // compress vertex ... fist case ... 
++    for (k=1; k<=mesh->np; k++) {
++      ppt = &mesh->point[k];
++      if ( ppt->tag & M_UNUSED )  continue;  
++      ppt->tmp = ++np;  
++      /*      if ( ppt->geom & M_CORNER )  cor[nc++] = ppt->tmp; */
++    }
++   
++    /*   seacrch vertex not in tet ???? */
++    {
++        int kk=0,npp=np;
++       for (k=1; k<=mesh->np; k++)
++       {
++            ppt = &mesh->point[k];
++           if ((ppt->tag & M_UNUSED )) ppt->tmp =-2;
++           else ppt->tmp =-1;
++
++       }
++       for ( k=1; k<=mesh->ne; k++)
++	{
++            pt = &mesh->tetra[k];
++            if ( !pt->v[0] )  continue;
++            k0++;
++            for(j=0;j<4;++j)
++              mesh->point[pt->v[j]].tmp=0;
++	}
++        np=0;
++        for (k=1; k<=mesh->np; k++)
++	{
++            ppt = &mesh->point[k];
++            
++            if ( ppt->tmp ==0) 
++               ppt->tmp = ++np; 
++            else
++            {
++                
++            if (ppt->tmp==-1)
++	    {
++                kk++;
++                ppt->tag  |= M_UNUSED;
++	    }
++                ppt->tmp=0;
++            }
++	}
++        if(kk) printf(" mmg3d: Strange nb of point %d not in tet is not zero (correct by FH)!\n" , kk);
++      
++    }
++    
++    mesh->nt=0;
++    if(! MMG_markBdry(mesh)) 
++      mesh->nt=0;
++    data[ff_id_vertex]=np ;
++    //data[ff_id_seg]=ned ;
++    data[ff_id_tria]=mesh->nt ;
++    int ne=0;
++    for ( k=1; k<=mesh->ne; k++) 
++      {
++	pt = &mesh->tetra[k];
++	if ( !pt->v[0] )  continue;  
++	ne++; 
++      }
++    
++    data[ff_id_tet]=ne  ;
++    printf(" mmg3d:  nbp = %d, nb tet %d\n",np,ne);
++    //data[ff_id_hex]=nhex;
++    //data[ff_id_prism]=npris; 
++    //data[ff_id_quad]=nq;
++    // data[ff_id_corner]=ncor;
++    
++    dataff->set_mesh(dataff,data,10);
++    
++    
++    for ( k=1; k<=mesh->np; k++) 
++      {
++	ppt = &mesh->point[k];
++	if ( ! ppt->tmp   )  continue;
++	dataff->set_v(dataff, ppt->tmp,ppt->c,ppt->ref);	    
++      }
++    
++    
++    for (k=1; k<=mesh->nt; k++) 
++      {
++	pt1 = &mesh->tria[k];
++	for(j=0;j<3;++j)
++	  kn[j] = mesh->point[pt1->v[j]].tmp;
++	dataff->set_elmt(dataff,ff_id_tria,k,kn,pt1->ref);
++	
++      }  
++    k0=0;
++    for ( k=1; k<=mesh->ne; k++) 
++      {
++	
++	pt = &mesh->tetra[k];
++	if ( !pt->v[0] )  continue;  
++	k0++;
++	for(j=0;j<4;++j)
++	  kn[j] = mesh->point[pt->v[j]].tmp;
++	dataff->set_elmt(dataff,ff_id_tet,k0,kn,pt->ref);
++	
++    }  
++    dataff->end_mesh(dataff);
++    return 1; 
++}
++int MMG_saveSolff (pMesh mesh,pSol sol,char *filename,DataFF *dataff) {
++  return 1; 
++}
++/*save the node speed : coornew-coorold/dt*/
++int MMG_saveVectff(pMesh mesh,char *filename,DataFF *dataff) {
++   return 1; 
++}
+ /* read mesh data */
+-int MMG_loadMesh(pMesh mesh,char *filename) {
++int MMG_loadMesh(pMesh mesh,char *filename,void *dataff) {  
+   FILE*            inm;
+   Hedge            hed,hed2;
+   pPoint           ppt;
+   pTetra           pt;
+   pHexa            ph,listhexa;
+   pTria            pt1;
+-  int              k,dim,ref,bin,bpos,i,tmp;
+-  int              *adjahex;
++  int              k,dim,ref,bin,bpos,i,tmp;  
++  int              *adjahex; 
+   long             posnp,posnt,posne,posnhex,posnpris,posncor,posned,posnq;
+   char            *ptr,data[128],chaine[128];
+   int              nhex,npris,netmp,ncor,ned,nq;
+-  int              p0,p1,p2,p3,p4,p5,p6,p7;
+-  int              binch,bdim,iswp,nu1,nu2,nimp,ne,nbado;
+-  float            fc;
+-  double           volhex,volref;
++  int              p0,p1,p2,p3,p4,p5,p6,p7;  
++  int              binch,bdim,iswp,nu1,nu2,nimp,ne,nbado;       
++  float            fc; 
++  double           volhex,volref;  
+   int              iadr,reorient;
+-
++  if(dataff)
++    return MMG_loadMeshff( mesh,filename,(DataFF*) dataff);
++  
+ 
+   posnp = posnt = posne = posnhex = posnpris = 0;
+   netmp = ncor = ned = 0;
+   bin = 0;
+   iswp = 0;
+-  mesh->np = mesh->nt = mesh->ne = mesh->ncor = 0;
++  mesh->np = mesh->nt = mesh->ne = mesh->ncor = 0; 
+   npris = nhex = nq = 0;
+-
++  
+   strcpy(data,filename);
+-  ptr = strstr(data,".mesh");
++  ptr = strstr(data,".mesh");  
+   if ( !ptr ) {
+     strcat(data,".meshb");
+     if( !(inm = fopen(data,"rb")) ) {
+@@ -136,8 +569,8 @@
+       *ptr = '\0';
+       strcat(data,".mesh");
+       if( !(inm = fopen(data,"r")) ) {
+-	fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
+-	return(0);
++        fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
++        return(0);
+       }
+     } else {
+       bin = 1;
+@@ -147,194 +580,194 @@
+     ptr = strstr(data,".meshb");
+     if( !ptr ) {
+       if( !(inm = fopen(data,"r")) ) {
+-	fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
+-	return(0);
+-      }
++        fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
++        return(0);
++      }      
+     } else {
+       bin = 1;
+       if( !(inm = fopen(data,"rb")) ) {
+-	fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
+-	return(0);
++        fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
++        return(0);
+       }
+-
+-    }
++      
++    }  
+   }
+ 
+   fprintf(stdout,"  %%%% %s OPENED\n",data);
+   if (!bin) {
+-    strcpy(chaine,"D");
+-    while(fscanf(inm,"%s",&chaine[0])!=EOF && strncmp(chaine,"End",strlen("End")) ) {
++    strcpy(chaine,"D");     
++    while(fscanf(inm,"%s",&chaine[0])!=EOF && strncmp(chaine,"End",strlen("End")) ) { 
+       if(!strncmp(chaine,"MeshVersionFormatted",strlen("MeshVersionFormatted"))) {
+-	fscanf(inm,"%d",&mesh->ver);
+-	continue;
++          fscanf(inm,"%d",&mesh->ver);
++          continue;
+       } else if(!strncmp(chaine,"Dimension",strlen("Dimension"))) {
+-	fscanf(inm,"%d",&dim);
+-	if(dim!=3) {
+-	  fprintf(stdout,"BAD DIMENSION : %d\n",dim);
+-	  return(0);
+-	}
+-	continue;
++          fscanf(inm,"%d",&dim);
++          if(dim!=3) {
++            fprintf(stdout,"BAD DIMENSION : %d\n",dim);
++            return(0);
++          }
++          continue;
+       } else if(!strncmp(chaine,"Vertices",strlen("Vertices"))) {
+-	fscanf(inm,"%d",&mesh->np);
+-	posnp = ftell(inm);
+-	continue;
++        fscanf(inm,"%d",&mesh->np); 
++        posnp = ftell(inm);
++        continue;
+       } else if(!strncmp(chaine,"Triangles",strlen("Triangles"))) {
+-	fscanf(inm,"%d",&mesh->nt);
+-	posnt = ftell(inm);
+-	continue;
++        fscanf(inm,"%d",&mesh->nt); 
++        posnt = ftell(inm);
++        continue;
+       } else if(!strncmp(chaine,"Tetrahedra",strlen("Tetrahedra"))) {
+-	fscanf(inm,"%d",&mesh->ne);
+-	netmp = mesh->ne;
+-	posne = ftell(inm);
+-	continue;
+-      } else if(!strncmp(chaine,"Hexahedra",strlen("Hexahedra"))) {
+-	assert(abs(mesh->info.option)==10);
+-	fscanf(inm,"%d",&nhex);
+-	//nhex=0;
+-	posnhex = ftell(inm);
+-	continue;
+-      } else if(!strncmp(chaine,"Pentahedra",strlen("Pentahedra"))) {
+-	assert(abs(mesh->info.option)==10);
+-	fscanf(inm,"%d",&npris);
+-	//npris=0;
+-	posnpris = ftell(inm);
+-	continue;
+-      } else if(!strncmp(chaine,"Corners",strlen("Corners"))) {
+-	fscanf(inm,"%d",&ncor);
+-	posncor = ftell(inm);
+-	continue;
+-      } else if(!strncmp(chaine,"Edges",strlen("Edges"))) {
+-	fscanf(inm,"%d",&ned);
+-	posned = ftell(inm);
+-	continue;
+-      } else if(abs(mesh->info.option)==10 && !strncmp(chaine,"Quadrilaterals",strlen("Quadrilaterals"))) {
+-	fscanf(inm,"%d",&nq);
+-	posnq = ftell(inm);
+-	continue;
+-      }
+-    }
++        fscanf(inm,"%d",&mesh->ne); 
++        netmp = mesh->ne;
++        posne = ftell(inm);
++        continue;
++      } else if(!strncmp(chaine,"Hexahedra",strlen("Hexahedra"))) { 
++        assert(abs(mesh->info.option)==10);  
++        fscanf(inm,"%d",&nhex); 
++				//nhex=0;
++        posnhex = ftell(inm);
++        continue;
++      } else if(!strncmp(chaine,"Pentahedra",strlen("Pentahedra"))) { 
++        assert(abs(mesh->info.option)==10); 
++        fscanf(inm,"%d",&npris);
++				//npris=0;
++        posnpris = ftell(inm);
++        continue;
++      } else if(!strncmp(chaine,"Corners",strlen("Corners"))) { 
++        fscanf(inm,"%d",&ncor); 
++        posncor = ftell(inm);
++        continue;
++      } else if(!strncmp(chaine,"Edges",strlen("Edges"))) { 
++	      fscanf(inm,"%d",&ned); 
++	      posned = ftell(inm);
++	      continue;
++	    } else if(abs(mesh->info.option)==10 && !strncmp(chaine,"Quadrilaterals",strlen("Quadrilaterals"))) {
++		    fscanf(inm,"%d",&nq); 
++		    posnq = ftell(inm);
++		    continue;
++		  }
++    }  
+   } else {
+     bdim = 0;
+     fread(&mesh->ver,sw,1,inm);
+-    iswp=0;
+-    if(mesh->ver==16777216)
+-      iswp=1;
++    iswp=0;   
++    if(mesh->ver==16777216) 
++      iswp=1;    
+     else if(mesh->ver!=1) {
+       fprintf(stdout,"BAD FILE ENCODING\n");
+-    }
+-    fread(&mesh->ver,sw,1,inm);
+-    if(iswp) mesh->ver = MMG_swapbin(mesh->ver);
+-    while(fread(&binch,sw,1,inm)!=0 && binch!=54 ) {
+-      if(iswp) binch=MMG_swapbin(binch);
+-      if(binch==54) break;
++    } 
++    fread(&mesh->ver,sw,1,inm); 
++    if(iswp) mesh->ver = MMG_swapbin(mesh->ver); 
++    while(fread(&binch,sw,1,inm)!=0 && binch!=54 ) {  
++      if(iswp) binch=MMG_swapbin(binch);      
++      if(binch==54) break;  
+       if(!bdim && binch==3) {  //Dimension
+-	fread(&bdim,sw,1,inm);  //NulPos=>20
+-	if(iswp) bdim=MMG_swapbin(bdim);
+-	fread(&bdim,sw,1,inm);
+-	if(iswp) bdim=MMG_swapbin(bdim);
+-	if(bdim!=3) {
+-	  fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
+-	  exit(0);
+-	  return(1);
+-	}
+-	continue;
++        fread(&bdim,sw,1,inm);  //NulPos=>20
++        if(iswp) bdim=MMG_swapbin(bdim);
++        fread(&bdim,sw,1,inm);  
++        if(iswp) bdim=MMG_swapbin(bdim);
++        if(bdim!=3) {
++          fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
++          exit(0);
++          return(1);
++        }
++        continue;
+       } else if(!mesh->np && binch==4) {  //Vertices
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	fread(&mesh->np,sw,1,inm);
+-	if(iswp) mesh->np=MMG_swapbin(mesh->np);
+-	posnp = ftell(inm);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-	continue;
++        fread(&bpos,sw,1,inm); //NulPos 
++        if(iswp) bpos=MMG_swapbin(bpos);
++        fread(&mesh->np,sw,1,inm); 
++        if(iswp) mesh->np=MMG_swapbin(mesh->np);
++        posnp = ftell(inm);     
++        rewind(inm);
++        fseek(inm,bpos,SEEK_SET);        
++        continue;
+       }  else if(!mesh->nt && binch==6) {//Triangles
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	fread(&mesh->nt,sw,1,inm);
+-	if(iswp) mesh->nt=MMG_swapbin(mesh->nt);
+-	posnt = ftell(inm);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-	continue;
+-      } else if(!mesh->ne && binch==8) {
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	fread(&mesh->ne,sw,1,inm);
+-	if(iswp) mesh->ne=MMG_swapbin(mesh->ne);
+-	netmp = mesh->ne;
+-	posne = ftell(inm);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-	continue;
+-      } else if(!nhex && binch==10) {
+-	assert(abs(mesh->info.option)==10);
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	fread(&nhex,sw,1,inm);
+-	if(iswp) nhex=MMG_swapbin(nhex);
+-	posnhex = ftell(inm);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-	continue;
+-      } else if(!npris && binch==9) {
+-	assert(abs(mesh->info.option)==10);
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	fread(&npris,sw,1,inm);
+-	if(iswp) npris=MMG_swapbin(npris);
+-	posnpris = ftell(inm);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-	continue;
+-      } else if(!ncor && binch==13) {
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	fread(&ncor,sw,1,inm);
+-	if(iswp) ncor=MMG_swapbin(ncor);
+-	posncor = ftell(inm);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-	continue;
+-      } else if(!ned && binch==5) { //Edges
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	fread(&ned,sw,1,inm);
+-	if(iswp) ned=MMG_swapbin(ned);
+-	posned = ftell(inm);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-	continue;
+-      } else {
+-	//printf("on traite ? %d\n",binch);
+-	fread(&bpos,sw,1,inm); //NulPos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	//printf("on avance... Nulpos %d\n",bpos);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-      }
+-    }
+-
++        fread(&bpos,sw,1,inm); //NulPos 
++        if(iswp) bpos=MMG_swapbin(bpos);
++        fread(&mesh->nt,sw,1,inm); 
++        if(iswp) mesh->nt=MMG_swapbin(mesh->nt);
++        posnt = ftell(inm); 
++        rewind(inm);
++        fseek(inm,bpos,SEEK_SET);        
++        continue;
++       } else if(!mesh->ne && binch==8) {  
++         fread(&bpos,sw,1,inm); //NulPos 
++         if(iswp) bpos=MMG_swapbin(bpos);
++         fread(&mesh->ne,sw,1,inm); 
++         if(iswp) mesh->ne=MMG_swapbin(mesh->ne);
++         netmp = mesh->ne;
++         posne = ftell(inm);
++         rewind(inm);
++         fseek(inm,bpos,SEEK_SET);        
++         continue;
++       } else if(!nhex && binch==10) { 
++         assert(abs(mesh->info.option)==10);
++         fread(&bpos,sw,1,inm); //NulPos 
++         if(iswp) bpos=MMG_swapbin(bpos);
++         fread(&nhex,sw,1,inm); 
++         if(iswp) nhex=MMG_swapbin(nhex);
++         posnhex = ftell(inm);
++         rewind(inm);
++         fseek(inm,bpos,SEEK_SET);        
++         continue;
++       } else if(!npris && binch==9) { 
++         assert(abs(mesh->info.option)==10);
++         fread(&bpos,sw,1,inm); //NulPos 
++         if(iswp) bpos=MMG_swapbin(bpos);
++         fread(&npris,sw,1,inm); 
++         if(iswp) npris=MMG_swapbin(npris);
++         posnpris = ftell(inm);
++         rewind(inm);
++         fseek(inm,bpos,SEEK_SET);        
++         continue;
++       } else if(!ncor && binch==13) { 
++         fread(&bpos,sw,1,inm); //NulPos 
++         if(iswp) bpos=MMG_swapbin(bpos);
++         fread(&ncor,sw,1,inm);          
++         if(iswp) ncor=MMG_swapbin(ncor);
++         posncor = ftell(inm);
++         rewind(inm);
++         fseek(inm,bpos,SEEK_SET);        
++         continue;
++        } else if(!ned && binch==5) { //Edges
++	       fread(&bpos,sw,1,inm); //NulPos 
++	       if(iswp) bpos=MMG_swapbin(bpos);
++	       fread(&ned,sw,1,inm); 
++	       if(iswp) ned=MMG_swapbin(ned);
++	       posned = ftell(inm);
++	       rewind(inm);
++	       fseek(inm,bpos,SEEK_SET);        
++	       continue;
++	      } else {
++         //printf("on traite ? %d\n",binch);
++         fread(&bpos,sw,1,inm); //NulPos 
++         if(iswp) bpos=MMG_swapbin(bpos);
++         //printf("on avance... Nulpos %d\n",bpos);         
++         rewind(inm);
++         fseek(inm,bpos,SEEK_SET);        
++       }     
++    }            
++    
+   }
+ 
+   if ( abs(mesh->info.option)==10 ) {
+-    fprintf(stdout,"  -- READING %8d HEXA %8d PRISMS\n",nhex,npris);
+-    if(!mesh->ne) netmp = 0;
+-    mesh->ne += 6*nhex + 3*npris;
++    fprintf(stdout,"  -- READING %8d HEXA %8d PRISMS\n",nhex,npris);  
++    if(!mesh->ne) netmp = 0;  
++    mesh->ne += 6*nhex + 3*npris; 
+   }
+ 
+   if ( abs(mesh->info.imprim) > 5 )
+     fprintf(stdout,"  -- READING DATA FILE %s\n",data);
+ 
+   if ( !mesh->np || !mesh->ne ) {
+-    fprintf(stdout,"  ** MISSING DATA\n");
++    fprintf(stdout,"  ** MISSING DAT qqA\n");
+     return(0);
+   }
+-  if(abs(mesh->info.option)==10) { //allocation
++	if(abs(mesh->info.option)==10) { //allocation
+     listhexa  = (pHexa)M_calloc(nhex+1,sizeof(Hexa),"allochexa");
+-    assert(listhexa);
+-    adjahex = (int*)M_calloc(6*nhex+7,sizeof(int),"allocadjhexa");
+-    assert(adjahex);
+-  }
++	  assert(listhexa);     
++	  adjahex = (int*)M_calloc(6*nhex+7,sizeof(int),"allocadjhexa");
++	  assert(adjahex);                             
++  }  
+   if ( !MMG_zaldy(mesh) )  return(0);
+   /* read mesh vertices */
+   mesh->npfixe = mesh->np;
+@@ -342,35 +775,35 @@
+   fseek(inm,posnp,SEEK_SET);
+   for (k=1; k<=mesh->np; k++) {
+     ppt = &mesh->point[k];
+-    if (mesh->ver < 2) { /*float*/
++    if (mesh->ver < 2) { /*float*/ 
+       if (!bin) {
+-	for (i=0 ; i<3 ; i++) {
+-	  fscanf(inm,"%f",&fc);
+-	  ppt->c[i] = (double) fc;
+-	}
+-	fscanf(inm,"%d",&ppt->ref);
++        for (i=0 ; i<3 ; i++) {
++          fscanf(inm,"%f",&fc);
++          ppt->c[i] = (double) fc;
++        } 
++        fscanf(inm,"%d",&ppt->ref);
+       } else {
+-	for (i=0 ; i<3 ; i++) {
+-	  fread(&fc,sw,1,inm);
+-	  if(iswp) fc=MMG_swapf(fc);
+-	  ppt->c[i] = (double) fc;
+-	}
+-	fread(&ppt->ref,sw,1,inm);
+-	if(iswp) ppt->ref=MMG_swapbin(ppt->ref);
++        for (i=0 ; i<3 ; i++) {
++          fread(&fc,sw,1,inm); 
++          if(iswp) fc=MMG_swapf(fc);    
++          ppt->c[i] = (double) fc;
++        }     
++        fread(&ppt->ref,sw,1,inm);         
++        if(iswp) ppt->ref=MMG_swapbin(ppt->ref);    
+       }
+     } else {
+-      if (!bin)
+-	fscanf(inm,"%lf %lf %lf %d",&ppt->c[0],&ppt->c[1],&ppt->c[2],&ppt->ref);
++      if (!bin) 
++        fscanf(inm,"%lf %lf %lf %d",&ppt->c[0],&ppt->c[1],&ppt->c[2],&ppt->ref); 
+       else {
+-	for (i=0 ; i<3 ; i++) {
+-	  fread(&ppt->c[i],sd,1,inm);
+-	  if(iswp) ppt->c[i]=MMG_swapd(ppt->c[i]);
+-	}
+-	fread(&ppt->ref,sw,1,inm);
+-	if(iswp) ppt->ref=MMG_swapbin(ppt->ref);
+-      }
+-    }
+-    ppt->tag  = M_UNUSED;
++        for (i=0 ; i<3 ; i++) { 
++          fread(&ppt->c[i],sd,1,inm);
++          if(iswp) ppt->c[i]=MMG_swapd(ppt->c[i]); 
++        }   
++        fread(&ppt->ref,sw,1,inm);         
++        if(iswp) ppt->ref=MMG_swapbin(ppt->ref);    
++      }  
++    }             
++    ppt->tag  = M_UNUSED;    
+   }
+ 
+   /* read mesh triangles */
+@@ -378,227 +811,226 @@
+   rewind(inm);
+   fseek(inm,posnt,SEEK_SET);
+   for (k=1; k<=mesh->nt; k++) {
+-    pt1 = &mesh->tria[k];
++    pt1 = &mesh->tria[k]; 
+     if (!bin)
+       fscanf(inm,"%d %d %d %d",&pt1->v[0],&pt1->v[1],&pt1->v[2],&pt1->ref);
+     else {
+-      for (i=0 ; i<3 ; i++) {
+-	fread(&pt1->v[i],sw,1,inm);
+-	if(iswp) pt1->v[i]=MMG_swapbin(pt1->v[i]);
+-      }
+-      fread(&pt1->ref,sw,1,inm);
+-      if(iswp) pt1->ref=MMG_swapbin(pt1->ref);
+-    }
+-  }
+-  /* read mesh quads (option 10)*/
+-  if(abs(mesh->info.option)==10) {
+-    fprintf(stdout,"     QUADS READING %d\n",nq);
++      for (i=0 ; i<3 ; i++) { 
++        fread(&pt1->v[i],sw,1,inm); 
++        if(iswp) pt1->v[i]=MMG_swapbin(pt1->v[i]);    
++      }
++      fread(&pt1->ref,sw,1,inm); 
++      if(iswp) pt1->ref=MMG_swapbin(pt1->ref);           
++    }  
++  }
++  /* read mesh quads (option 10)*/ 
++	if(abs(mesh->info.option)==10) { 
++		fprintf(stdout,"     QUADS READING %d\n",nq);
+     mesh->ntfixe += 4*nq;
+ 
+     rewind(inm);
+     fseek(inm,posnq,SEEK_SET);
+     for (k=1; k<=nq; k++) {
+       if (!bin)
+-	fscanf(inm,"%d %d %d %d %d",&p0,&p1,&p2,&p3,&ref);
++        fscanf(inm,"%d %d %d %d %d",&p0,&p1,&p2,&p3,&ref);
+       else {
+-	fread(&p0,sw,1,inm);
+-	if(iswp) p0=MMG_swapbin(p0);
+-	fread(&p1,sw,1,inm);
+-	if(iswp) p1=MMG_swapbin(p1);
+-	fread(&p2,sw,1,inm);
+-	if(iswp) p2=MMG_swapbin(p2);
+-	fread(&p3,sw,1,inm);
+-	if(iswp) p3=MMG_swapbin(p3);
+-	fread(&pt1->ref,sw,1,inm);
+-	if(iswp) ref=MMG_swapbin(ref);
+-      }
++        fread(&p0,sw,1,inm); 
++        if(iswp) p0=MMG_swapbin(p0);    
++        fread(&p1,sw,1,inm); 
++        if(iswp) p1=MMG_swapbin(p1);    
++        fread(&p2,sw,1,inm); 
++        if(iswp) p2=MMG_swapbin(p2);    
++        fread(&p3,sw,1,inm); 
++        if(iswp) p3=MMG_swapbin(p3);    
++	      fread(&pt1->ref,sw,1,inm); 
++	      if(iswp) ref=MMG_swapbin(ref);           
++      } 
+       /*creation of 4 triangles per quads because we don't know how hexa will be cut*/
+-      pt1 = &mesh->tria[++mesh->nt];
+-      pt1->v[0] = p0;
+-      pt1->v[1] = p1;
+-      pt1->v[2] = p2;
+-      pt1->ref  = ref;
+-      pt1 = &mesh->tria[++mesh->nt];
+-      pt1->v[0] = p0;
+-      pt1->v[1] = p2;
+-      pt1->v[2] = p3;
+-      pt1->ref  = ref;
+-      pt1 = &mesh->tria[++mesh->nt];
+-      pt1->v[0] = p0;
+-      pt1->v[1] = p1;
+-      pt1->v[2] = p3;
+-      pt1->ref  = ref;
+-      pt1 = &mesh->tria[++mesh->nt];
+-      pt1->v[0] = p1;
+-      pt1->v[1] = p2;
+-      pt1->v[2] = p3;
+-      pt1->ref  = ref;
+-
+-    }
+-  }
+-  /*read and store edges*/
+-  if (ned) {
+-    if ( !MMG_zaldy4(&hed,ned) ) {
+-      if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : EDGES IGNORED\n");
+-      ned = 0;
+-    }
+-    mesh->ned = ned;
++      pt1 = &mesh->tria[++mesh->nt]; 
++			pt1->v[0] = p0;
++			pt1->v[1] = p1;
++			pt1->v[2] = p2;
++			pt1->ref  = ref;
++      pt1 = &mesh->tria[++mesh->nt]; 
++			pt1->v[0] = p0;
++			pt1->v[1] = p2;
++			pt1->v[2] = p3;
++			pt1->ref  = ref;
++      pt1 = &mesh->tria[++mesh->nt]; 
++			pt1->v[0] = p0;
++			pt1->v[1] = p1;
++			pt1->v[2] = p3;
++			pt1->ref  = ref;
++      pt1 = &mesh->tria[++mesh->nt]; 
++			pt1->v[0] = p1;
++			pt1->v[1] = p2;
++			pt1->v[2] = p3;
++			pt1->ref  = ref;
++ 
++    }
++  }
++	/*read and store edges*/
++  if (ned) {         
++	  if ( !MMG_zaldy4(&hed,ned) ) {
++      if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : EDGES IGNORED\n"); 
++			ned = 0;
++    }   
++		mesh->ned = ned;
+     rewind(inm);
+-    fseek(inm,posned,SEEK_SET);
+-    for (k=1; k<=ned; k++) {
++    fseek(inm,posned,SEEK_SET); 
++    for (k=1; k<=ned; k++) { 
+       if (!bin)
+-	fscanf(inm,"%d %d %d",&nu1,&nu2,&ref);
++        fscanf(inm,"%d %d %d",&nu1,&nu2,&ref);
+       else {
+-	fread(&nu1,sw,1,inm);
+-	if(iswp) nu1=MMG_swapbin(nu1);
+-	fread(&nu2,sw,1,inm);
+-	if(iswp) nu2=MMG_swapbin(nu2);
+-	fread(&ref,sw,1,inm);
+-	if(iswp) ref=MMG_swapbin(ref);
+-      }
+-      if(MMG_edgePut(&hed,nu1,nu2,2)>1) {
+-	fprintf(stdout,"  ## WARNING DOUBLE EDGE : %d %d\n",nu1,nu2);
+-      }
+-      mesh->point[nu1].geom = M_RIDGE_GEO;
+-      mesh->point[nu2].geom = M_RIDGE_GEO;
++        fread(&nu1,sw,1,inm); 
++        if(iswp) nu1=MMG_swapbin(nu1);    
++        fread(&nu2,sw,1,inm); 
++        if(iswp) nu2=MMG_swapbin(nu2);    
++        fread(&ref,sw,1,inm); 
++        if(iswp) ref=MMG_swapbin(ref);    
++      }  
++			if(MMG_edgePut(&hed,nu1,nu2,2)>1) {
++				fprintf(stdout,"  ## WARNING DOUBLE EDGE : %d %d\n",nu1,nu2);
++			} 
++			mesh->point[nu1].geom = M_RIDGE_GEO;  
++			mesh->point[nu2].geom = M_RIDGE_GEO;  
+     }
+   }
+ 
+   /* read mesh tetrahedra */
+   mesh->nefixe = mesh->ne;
+   rewind(inm);
+-  fseek(inm,posne,SEEK_SET);
+-  reorient = 0;
+-  for (k=1; k<=netmp; k++) {
++  fseek(inm,posne,SEEK_SET); 
++	reorient = 0;
++  for (k=1; k<=netmp; k++) { 
+     pt = &mesh->tetra[k];
+-    if (!bin)
+-      fscanf(inm,"%d %d %d %d %d",&pt->v[0],&pt->v[1],&pt->v[2],&pt->v[3],&ref);
+-    else {
+-
+-      for (i=0 ; i<4 ; i++) {
+-	fread(&pt->v[i],sw,1,inm);
+-	if(iswp) pt->v[i]=MMG_swapbin(pt->v[i]);
+-      }
+-      fread(&ref,sw,1,inm);
+-      if(iswp) ref=MMG_swapbin(ref);
+-    }
++    if (!bin) 
++      fscanf(inm,"%d %d %d %d %d",&pt->v[0],&pt->v[1],&pt->v[2],&pt->v[3],&ref); 
++    else {                                                                        
++	
++      for (i=0 ; i<4 ; i++) { 
++        fread(&pt->v[i],sw,1,inm); 
++        if(iswp) pt->v[i]=MMG_swapbin(pt->v[i]);    
++      }
++      fread(&ref,sw,1,inm);         
++      if(iswp) ref=MMG_swapbin(ref);           
++    }  
+     pt->ref  = ref;//0;//ref ;
+ 
+     /*check orientation*/
+-    volref = MMG_voltet(mesh,k);
+-    if(volref < 0) {
+-      reorient++;
+-      tmp = pt->v[2];
+-      pt->v[2] = pt->v[3];
+-      pt->v[3] = tmp;
+-    }
+-
++		volref = MMG_voltet(mesh,k);
++		if(volref < 0) {
++		 if(!reorient) {
++		   fprintf(stdout,"\n     $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ \n");
++		   fprintf(stdout,"         BAD ORIENTATION : vol < 0 -- Some tetra will be reoriented\n");     
++		   fprintf(stdout,"     $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ \n\n");
++		   reorient = 1;        
++		 }
++		 tmp = pt->v[2];
++     pt->v[2] = pt->v[3];
++     pt->v[3] = tmp;
++		}
++	  
+     for(i=0 ; i<4 ; i++)
+-      pt->bdryref[i] = -1;
+-
+-    if (ned) {
+-      for(i=0 ; i<6 ; i++) {
+-	nu1 = pt->v[MMG_iare[i][0]];
+-	nu2 = pt->v[MMG_iare[i][1]];
+-	pt->bdryinfo[i] = MMG_edgePoint(&hed,nu1,nu2);
+-      }
+-
+-    } else {
+-      for(i=0 ; i<6 ; i++)
+-	pt->bdryinfo[i] = 0;
+-    }
++      pt->bdryref[i] = -1;  
++    
++		if (ned) {
++	    for(i=0 ; i<6 ; i++) {                         
++				nu1 = pt->v[MMG_iare[i][0]];
++				nu2 = pt->v[MMG_iare[i][1]];
++	      pt->bdryinfo[i] = MMG_edgePoint(&hed,nu1,nu2);
++			}  			
++			
++		} else {
++	    for(i=0 ; i<6 ; i++)
++	      pt->bdryinfo[i] = 0;  			
++		}
+   }
+-  if(reorient) {
+-    fprintf(stdout,"\n     $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ \n");
+-    fprintf(stdout,"         BAD ORIENTATION : vol < 0 -- %8d tetra reoriented\n",reorient);
+-    fprintf(stdout,"     $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ \n\n");
+-    reorient = 1;
+-  }
+-   if (ned) M_free(hed.item);
++  if (ned) M_free(hed.item); 
+ 
+-  /*read corners*/
++  /*read corners*/ 
+   if (ncor) {
+     rewind(inm);
+-    fseek(inm,posncor,SEEK_SET);
++    fseek(inm,posncor,SEEK_SET); 
+     mesh->ncor = ncor;
+-    for (k=1; k<=ncor; k++) {
++    for (k=1; k<=ncor; k++) { 
+       if (!bin)
+-	fscanf(inm,"%d",&ref);
++        fscanf(inm,"%d",&ref);
+       else {
+-	fread(&ref,sw,1,inm);
+-	if(iswp) ref=MMG_swapbin(ref);
+-      }
++        fread(&ref,sw,1,inm); 
++        if(iswp) ref=MMG_swapbin(ref);    
++      }  
+       ppt = &mesh->point[ref];
+-      ppt->geom = M_CORNER;
+-    }
++      ppt->geom = M_CORNER; 
++    } 
+   }
+-
+-
+-  if ( abs(mesh->info.option)==10 ) {
++   
++	
++  if ( abs(mesh->info.option)==10 ) { 
+     if(bin) {
+       printf("NOT SUPPORTED\n");
+       exit(0);
+-    }
+-    if ( !MMG_zaldy4(&hed2,3*npris+6*nhex) ) {
+-      if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : PRISM IGNORED\n");
+-      npris = 0;
+-      nhex  = 0;
+-    }
++    } 
++	  if ( !MMG_zaldy4(&hed2,3*npris+6*nhex) ) {
++      if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : PRISM IGNORED\n"); 
++			npris = 0;
++			nhex  = 0;
++    }   
+ 
+     /*read hexa and transform to tetra*/
+     rewind(inm);
+-    fseek(inm,posnhex,SEEK_SET);
+-    nbado = 0;
++    fseek(inm,posnhex,SEEK_SET);   
++		nbado = 0;
+     for (k=1; k<=nhex; k++) {
+-      ph = &listhexa[k];
+-      fscanf(inm,"%d %d %d %d %d %d %d %d %d",&ph->v[0],&ph->v[1],&ph->v[2],&ph->v[3],&ph->v[4],&ph->v[5],&ph->v[6],&ph->v[7],&ph->ref);
+-      //fscanf(inm,"%d %d %d %d %d %d %d %d %d",&p0,&p4,&p2,&p1,&p3,&p5,&p6,&p7,&ref);
+-      //printf("hex %d : %d %d %d %d %d %d %d %d\n",k,p0,p1,p2,p3,p4,p5,p6,p7);
++			ph = &listhexa[k];   
++      fscanf(inm,"%d %d %d %d %d %d %d %d %d",&ph->v[0],&ph->v[1],&ph->v[2],&ph->v[3],&ph->v[4],&ph->v[5],&ph->v[6],&ph->v[7],&ph->ref); 
++      //fscanf(inm,"%d %d %d %d %d %d %d %d %d",&p0,&p4,&p2,&p1,&p3,&p5,&p6,&p7,&ref); 
++      //printf("hex %d : %d %d %d %d %d %d %d %d\n",k,p0,p1,p2,p3,p4,p5,p6,p7); 
+       //check orientability of the hexahedra : vol of tet p0 p1 p3 p4
+-      volhex = MMG_quickvol(mesh->point[ph->v[0]].c,mesh->point[ph->v[1]].c,mesh->point[ph->v[2]].c,mesh->point[ph->v[3]].c);
+-      if(k==1) {
+-	volref = volhex;
+-	//printf("vol %e\n",volref);
+-      }
+-      else {
+-	if(volref*volhex < 0) {
+-	  fprintf(stdout,"BAD ORIENTATION OF HEXAHEDRON %d : %d %d %d %d %d %d %d %d\n",k,p0,p1,p2,p3,p4,p5,p6,p7);
+-	  nbado++;
+-	  tmp = ph->v[3];
+-	  ph->v[3] = ph->v[1];
+-	  ph->v[1] = tmp;
+-	  tmp = ph->v[5];
+-	  ph->v[5] = ph->v[7];
+-	  ph->v[7] = tmp;
+-	}
+-      }
+-      // MMG_cuthex(mesh,&hed2,netmp+(k-1)*6,ph->v[0],ph->v[1],ph->v[2],ph->v[3],ph->v[4],ph->v[5],ph->v[6],ph->v[7],ph->ref);
+-    }
+-    fprintf(stdout,"%8d HEXA REORIENTED\n",nbado);
++			volhex = MMG_quickvol(mesh->point[ph->v[0]].c,mesh->point[ph->v[1]].c,mesh->point[ph->v[2]].c,mesh->point[ph->v[3]].c);
++			if(k==1) {
++				volref = volhex; 
++				//printf("vol %e\n",volref);
++			}
++			else {
++				if(volref*volhex < 0) {
++					fprintf(stdout,"BAD ORIENTATION OF HEXAHEDRON %d : %d %d %d %d %d %d %d %d\n",k,p0,p1,p2,p3,p4,p5,p6,p7);
++					nbado++;
++					tmp = ph->v[3];
++					ph->v[3] = ph->v[1];
++					ph->v[1] = tmp;
++					tmp = ph->v[5];
++					ph->v[5] = ph->v[7];
++					ph->v[7] = tmp;
++				}
++			} 
++			// MMG_cuthex(mesh,&hed2,netmp+(k-1)*6,ph->v[0],ph->v[1],ph->v[2],ph->v[3],ph->v[4],ph->v[5],ph->v[6],ph->v[7],ph->ref);
++    }  
++		fprintf(stdout,"%8d HEXA REORIENTED\n",nbado);
+ 
+-    if(!MMG_hashHexa(listhexa,adjahex,nhex)) return(0);
+-    MMG_cuthex(mesh,&hed2,listhexa,adjahex,nhex,netmp);
++		if(!MMG_hashHexa(listhexa,adjahex,nhex)) return(0);  
++	  MMG_cuthex(mesh,&hed2,listhexa,adjahex,nhex,netmp); 
+     /*read prism and transform to tetra
+-      ---> compatibility pbs ==> hash edge and switch case*/
++		---> compatibility pbs ==> hash edge and switch case*/  
+     rewind(inm);
+-    fseek(inm,posnpris,SEEK_SET);
+-    nimp = 0;
+-    ne = netmp+6*nhex;
++    fseek(inm,posnpris,SEEK_SET); 
++		nimp = 0; 
++		ne = netmp+6*nhex;
+     for (k=1; k<=npris; k++) {
+-      fscanf(inm,"%d %d %d %d %d %d %d",&p0,&p1,&p2,&p3,&p4,&p5,&ref);
+-      if(!MMG_cutprism(mesh,&hed2,ne,p0,p1,p2,p3,p4,p5,ref))
+-	{
+-	  if(mesh->info.imprim < 0 ) fprintf(stdout,"DECOMPOSITION PRISM INVALID \n\n");
+-	  mesh->ne += 5;
+-	  ne += 8;
+-	  nimp++;
+-	  continue;
+-	}
+-      ne += 3;
++      fscanf(inm,"%d %d %d %d %d %d %d",&p0,&p1,&p2,&p3,&p4,&p5,&ref); 
++			if(!MMG_cutprism(mesh,&hed2,ne,p0,p1,p2,p3,p4,p5,ref))
++			{
++				if(mesh->info.imprim < 0 ) fprintf(stdout,"DECOMPOSITION PRISM INVALID \n\n"); 
++				mesh->ne += 5;
++				ne += 8;
++				nimp++; 
++				continue;
++			}
++			ne += 3;
+     }
+-    if(abs(mesh->info.imprim) > 3 )fprintf(stdout,"     %d INVALID DECOMPOSITION\n\n",nimp);
++		if(abs(mesh->info.imprim) > 3 )fprintf(stdout,"     %d INVALID DECOMPOSITION\n\n",nimp);
+   }
+-
++  
+   if ( abs(mesh->info.imprim) > 3 && abs(mesh->info.option)!=10 ) {
+     fprintf(stdout,"     NUMBER OF GIVEN VERTICES   %8d\n",mesh->npfixe);
+     if ( mesh->ntfixe )
+@@ -609,24 +1041,26 @@
+     if ( ned )
+       fprintf(stdout,"     NUMBER OF GIVEN EDGES      %8d\n",ned);
+   }
+-  fclose(inm);
+-  return(1);
++ fclose(inm);
++ return(1);
+ }
+ 
+ 
+ /* load solution (metric) */
+-int MMG_loadSol(pSol sol,char *filename,int npmax) {
+-  FILE       *inm;
++int MMG_loadSol(pSol sol,char *filename,int npmax,void *dataff) { 
++  FILE       *inm;   
+   float       fsol;
+-  double      tmp;
++  double      tmp;       
+   int         binch,bdim,iswp;
+   int         k,i,isol,type,bin,dim,btyp,bpos;
+   long        posnp;
+   char        *ptr,data[128],chaine[128];
+-
+-  posnp = 0;
++    if(dataff) 
++	return MMG_loadSolff( sol,filename,npmax,(DataFF*) dataff);
++  
++  posnp = 0; 
+   bin   = 0;
+-  iswp  = 0;
++  iswp  = 0; 
+ 
+   strcpy(data,filename);
+   ptr = strstr(data,".mesh");
+@@ -645,94 +1079,94 @@
+   }
+   fprintf(stdout,"  %%%% %s OPENED\n",data);
+ 
+-
+-  if(!bin) {
++   
++  if(!bin) {   
+     strcpy(chaine,"DDD");
+-    while(fscanf(inm,"%s",&chaine[0])!=EOF && strncmp(chaine,"End",strlen("End")) ) {
++    while(fscanf(inm,"%s",&chaine[0])!=EOF && strncmp(chaine,"End",strlen("End")) ) { 
+       if(!strncmp(chaine,"Dimension",strlen("Dimension"))) {
+-	fscanf(inm,"%d",&dim);
+-	if(dim!=3) {
+-	  fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
+-	  return(1);
+-	}
+-	continue;
++          fscanf(inm,"%d",&dim);
++          if(dim!=3) {
++            fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim); 
++            return(1);
++          }
++          continue;
+       } else if(!strncmp(chaine,"SolAtVertices",strlen("SolAtVertices"))) {
+-	fscanf(inm,"%d",&sol->np);
+-	fscanf(inm,"%d",&type);
+-	if(type!=1) {
+-	  fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
+-	  return(1);
+-	}
+-	fscanf(inm,"%d",&btyp);
+-	posnp = ftell(inm);
+-	break;
+-      }
+-    }
+-  } else {
+-    fread(&binch,sw,1,inm);
+-    iswp=0;
+-    if(binch==16777216) iswp=1;
++        fscanf(inm,"%d",&sol->np); 
++        fscanf(inm,"%d",&type); 
++        if(type!=1) {
++          fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
++          return(1);
++        }
++        fscanf(inm,"%d",&btyp);
++        posnp = ftell(inm);
++        break;
++      } 
++    }            
++  } else {     
++    fread(&binch,sw,1,inm); 
++    iswp=0;   
++    if(binch==16777216) iswp=1;    
+     else if(binch!=1) {
+       fprintf(stdout,"BAD FILE ENCODING\n");
+-    }
+-    fread(&sol->ver,sw,1,inm);
+-    if(iswp) sol->ver = MMG_swapbin(sol->ver);
++    } 
++    fread(&sol->ver,sw,1,inm); 
++    if(iswp) sol->ver = MMG_swapbin(sol->ver); 
+     while(fread(&binch,sw,1,inm)!=EOF && binch!=54 ) {
+-      if(iswp) binch=MMG_swapbin(binch);
+-      if(binch==54) break;
++      if(iswp) binch=MMG_swapbin(binch);      
++      if(binch==54) break;  
+       if(binch==3) {  //Dimension
+-	fread(&bdim,sw,1,inm);  //NulPos=>20
+-	if(iswp) bdim=MMG_swapbin(bdim);
+-	fread(&bdim,sw,1,inm);
+-	if(iswp) bdim=MMG_swapbin(bdim);
+-	if(bdim!=3) {
+-	  fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
+-	  exit(0);
+-	  return(1);
+-	}
+-	continue;
++        fread(&bdim,sw,1,inm);  //NulPos=>20
++        if(iswp) bdim=MMG_swapbin(bdim);
++        fread(&bdim,sw,1,inm);
++        if(iswp) bdim=MMG_swapbin(bdim);
++        if(bdim!=3) {
++          fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
++          exit(0);
++          return(1);
++        }
++        continue;
+       } else if(binch==62) {  //SolAtVertices
+-	fread(&binch,sw,1,inm); //NulPos
+-	if(iswp) binch=MMG_swapbin(binch);
+-	fread(&sol->np,sw,1,inm);
+-	if(iswp) sol->np=MMG_swapbin(sol->np);
+-	fread(&binch,sw,1,inm); //nb sol
+-	if(iswp) binch=MMG_swapbin(binch);
+-	if(binch!=1) {
+-	  fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
+-	  return(1);
+-	}
+-	fread(&btyp,sw,1,inm); //typsol
+-	if(iswp) btyp=MMG_swapbin(btyp);
+-	posnp = ftell(inm);
+-	break;
++        fread(&binch,sw,1,inm); //NulPos
++        if(iswp) binch=MMG_swapbin(binch);
++        fread(&sol->np,sw,1,inm); 
++        if(iswp) sol->np=MMG_swapbin(sol->np);
++        fread(&binch,sw,1,inm); //nb sol
++        if(iswp) binch=MMG_swapbin(binch);
++        if(binch!=1) {
++          fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
++          return(1);
++        }
++        fread(&btyp,sw,1,inm); //typsol
++        if(iswp) btyp=MMG_swapbin(btyp);
++        posnp = ftell(inm);
++        break;
+       } else {
+-	fread(&bpos,sw,1,inm); //Pos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-      }
+-    }
+-
+-  }
++        fread(&bpos,sw,1,inm); //Pos 
++        if(iswp) bpos=MMG_swapbin(bpos);
++        rewind(inm);
++        fseek(inm,bpos,SEEK_SET);        
++      } 
++    }            
++    
++  }       
+   if ( !sol->np ) {
+-    fprintf(stdout,"  ** MISSING DATA\n");
++    fprintf(stdout,"  ** MISSING DATA ss\n");
+     return(1);
+   }
+ 
+   if ( btyp!= 1 && btyp!=3 ) {
+-    fprintf(stdout,"  ** DATA IGNORED\n");
++    fprintf(stdout,"  ** DATA IGNORED %d\n",btyp);
+     sol->np = 0;
+     return(1);
+   }
+-
++  
+   sol->offset = (btyp==1) ? 1 : 6;
+ 
+   if ( abs(MMG_imprim) > 5 )
+     fprintf(stdout,"  -- READING DATA FILE %s\n",data);
+ 
+   if ( !sol->np ) {
+-    fprintf(stdout,"  ** MISSING DATA\n");
++    fprintf(stdout,"  ** MISSING DATA xx\n");
+     return(0);
+   }
+   sol->npfixe = sol->np;
+@@ -742,31 +1176,31 @@
+   /* read mesh solutions */
+   sol->npfixe = sol->np;
+   rewind(inm);
+-  fseek(inm,posnp,SEEK_SET);
++  fseek(inm,posnp,SEEK_SET);  
+   for (k=1; k<=sol->np; k++) {
+     isol = (k-1) * sol->offset + 1;
+-    if (sol->ver == 1) {
++    if (sol->ver == 1) { 
+       for (i=0; i<sol->offset; i++) {
+-	if(!bin){
+-	  fscanf(inm,"%f",&fsol);
+-	  sol->met[isol + i] = (double) fsol;
+-	} else {
+-	  fread(&fsol,sw,1,inm);
+-	  if(iswp) fsol=MMG_swapf(fsol);
+-	  sol->met[isol + i] = (double) fsol;
+-	}
+-      }
++        if(!bin){
++          fscanf(inm,"%f",&fsol);    
++          sol->met[isol + i] = (double) fsol;
++        } else {
++          fread(&fsol,sw,1,inm);             
++          if(iswp) fsol=MMG_swapf(fsol);
++          sol->met[isol + i] = (double) fsol;
++        }
++      } 
+     } else {
+       for (i=0; i<sol->offset; i++) {
+-	if(!bin){
+-	  fscanf(inm,"%lf",&sol->met[isol + i]);
++        if(!bin){
++          fscanf(inm,"%lf",&sol->met[isol + i]); 
+ 
+-	} else {
+-	  fread(&sol->met[isol + i],sd,1,inm);
+-	  if(iswp) sol->met[isol + i]=MMG_swapd(sol->met[isol + i]);
+-	}
+-      }
+-    }
++        } else {
++          fread(&sol->met[isol + i],sd,1,inm);       
++          if(iswp) sol->met[isol + i]=MMG_swapd(sol->met[isol + i]);
++        } 
++      } 
++    }             
+     /* MMG_swap data */
+     if ( sol->offset == 6 ) {
+       tmp                = sol->met[isol + 2];
+@@ -778,13 +1212,13 @@
+   if ( abs(MMG_imprim) > 3 )
+     fprintf(stdout,"     NUMBER OF GIVEN DATA       %8d\n",sol->npfixe);
+ 
+-  fclose(inm);
+-  return(1);
++  fclose(inm);   
++  return(1);  
+ }
+ 
+ 
+-int MMG_loadVect(pMesh mesh,char *filename,int npmax) {
+-  FILE       *inm;
++int MMG_loadVect(pMesh mesh,char *filename,int npmax,void *dataff) {
++  FILE       *inm;   
+   pDispl       pd;
+   float       fsol;
+   int         binch,bdim,iswp;
+@@ -792,10 +1226,13 @@
+   long        posnp;
+   char        *ptr,data[128],chaine[128];
+ 
+-  pd = mesh->disp;
++  if(dataff) 
++      return MMG_loadVectff( mesh, filename,npmax,(DataFF*) dataff);
+ 
+-  posnp = 0;
+-  bin   = 0;
++  pd = mesh->disp;
++  
++  posnp = 0; 
++  bin   = 0; 
+   iswp  = 0;
+ 
+   strcpy(data,filename);
+@@ -815,76 +1252,76 @@
+   }
+   fprintf(stdout,"  %%%% %s OPENED\n",data);
+ 
+-
+-  if(!bin) {
++   
++  if(!bin) {   
+     strcpy(chaine,"DDD");
+-    while(fscanf(inm,"%s",&chaine[0])!=EOF && strncmp(chaine,"End",strlen("End")) ) {
++    while(fscanf(inm,"%s",&chaine[0])!=EOF && strncmp(chaine,"End",strlen("End")) ) { 
+       if(!strncmp(chaine,"Dimension",strlen("Dimension"))) {
+-	fscanf(inm,"%d",&dim);
+-	if(dim!=3) {
+-	  fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
+-	  return(1);
+-	}
+-	continue;
++          fscanf(inm,"%d",&dim);
++          if(dim!=3) {
++            fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim); 
++            return(1);
++          }
++          continue;
+       } else if(!strncmp(chaine,"SolAtVertices",strlen("SolAtVertices"))) {
+-	fscanf(inm,"%d",&pd->np);
+-	fscanf(inm,"%d",&type);
+-	if(type!=1) {
+-	  fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
+-	  return(1);
+-	}
+-	fscanf(inm,"%d",&btyp);
+-	posnp = ftell(inm);
+-	break;
+-      }
+-    }
+-  } else {
+-    fread(&pd->ver,sw,1,inm);
+-    iswp=0;
+-    if(pd->ver==16777216) iswp=1;
++        fscanf(inm,"%d",&pd->np); 
++        fscanf(inm,"%d",&type); 
++        if(type!=1) {
++          fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
++          return(1);
++        }
++        fscanf(inm,"%d",&btyp);
++        posnp = ftell(inm);
++        break;
++      } 
++    }            
++  } else {     
++    fread(&pd->ver,sw,1,inm); 
++    iswp=0;   
++    if(pd->ver==16777216) iswp=1;    
+     else if(pd->ver!=1) {
+       fprintf(stdout,"BAD FILE ENCODING\n");
+-    }
+-    fread(&pd->ver,sw,1,inm);
+-    if(iswp) pd->ver = MMG_swapbin(pd->ver);
++    } 
++    fread(&pd->ver,sw,1,inm); 
++    if(iswp) pd->ver = MMG_swapbin(pd->ver); 
+     while(fread(&binch,sw,1,inm)!=EOF && binch!=54 ) {
+-      if(iswp) binch=MMG_swapbin(binch);
+-      if(binch==54) break;
++      if(iswp) binch=MMG_swapbin(binch);      
++      if(binch==54) break;  
+       if(binch==3) {  //Dimension
+-	fread(&bdim,sw,1,inm);  //Pos=>20
+-	if(iswp) bdim=MMG_swapbin(bdim);
+-	fread(&bdim,sw,1,inm);
+-	if(iswp) bdim=MMG_swapbin(bdim);
+-	if(bdim!=3) {
+-	  fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
+-	  exit(0);
+-	  return(1);
+-	}
+-	continue;
++        fread(&bdim,sw,1,inm);  //Pos=>20
++        if(iswp) bdim=MMG_swapbin(bdim);      
++        fread(&bdim,sw,1,inm);
++        if(iswp) bdim=MMG_swapbin(bdim);      
++        if(bdim!=3) {
++          fprintf(stdout,"BAD SOL DIMENSION : %d\n",dim);
++          exit(0);
++          return(1);
++        }
++        continue;
+       } else if(binch==62) {  //SolAtVertices
+-	fread(&binch,sw,1,inm); //Pos
+-	if(iswp) binch=MMG_swapbin(binch);
+-	fread(&pd->np,sw,1,inm);
+-	if(iswp) pd->np=MMG_swapbin(pd->np);
+-	fread(&binch,sw,1,inm); //nb sol
+-	if(iswp) binch=MMG_swapbin(binch);
+-	if(binch!=1) {
+-	  fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
+-	  return(1);
+-	}
+-	fread(&btyp,sw,1,inm); //typsol
+-	if(iswp) btyp=MMG_swapbin(btyp);
+-	posnp = ftell(inm);
+-	break;
++        fread(&binch,sw,1,inm); //Pos
++        if(iswp) binch=MMG_swapbin(binch);      
++        fread(&pd->np,sw,1,inm); 
++        if(iswp) pd->np=MMG_swapbin(pd->np);      
++        fread(&binch,sw,1,inm); //nb sol
++        if(iswp) binch=MMG_swapbin(binch);      
++        if(binch!=1) {
++          fprintf(stdout,"SEVERAL SOLUTION => IGNORED : %d\n",type);
++          return(1);
++        }
++        fread(&btyp,sw,1,inm); //typsol
++        if(iswp) btyp=MMG_swapbin(btyp);      
++        posnp = ftell(inm);
++        break;
+       } else {
+-	fread(&bpos,sw,1,inm); //Pos
+-	if(iswp) bpos=MMG_swapbin(bpos);
+-	rewind(inm);
+-	fseek(inm,bpos,SEEK_SET);
+-      }
+-    }
+-
+-  }
++        fread(&bpos,sw,1,inm); //Pos 
++        if(iswp) bpos=MMG_swapbin(bpos);      
++        rewind(inm);
++        fseek(inm,bpos,SEEK_SET);        
++      } 
++    }            
++    
++  }       
+   if ( !pd->np ) {
+     fprintf(stdout,"  ** MISSING DATA\n");
+     return(0);
+@@ -895,7 +1332,7 @@
+   }
+ 
+   if ( btyp != 2 ) {
+-    fprintf(stdout,"  ** DATA IGNORED\n");
++    fprintf(stdout,"  ** DATA IGNORED %d !=2\n",btyp);
+     return(0);
+   }
+ 
+@@ -907,47 +1344,50 @@
+   fseek(inm,posnp,SEEK_SET);
+   for (k=1; k<=pd->np; k++) {
+     iadr = (k - 1) * 3 + 1;
+-    if (pd->ver < 2) {
++    if (pd->ver < 2) { 
+       for (i=0; i<3; i++) {
+-	if(!bin){
+-	  fscanf(inm,"%f",&fsol);
+-	  pd->mv[iadr + i] = (double) fsol;
+-	} else {
+-	  fread(&fsol,sw,1,inm);
+-	  if(iswp) fsol=MMG_swapf(fsol);
+-	  pd->mv[iadr + i] = (double) fsol;
+-	}
+-      }
++        if(!bin){
++          fscanf(inm,"%f",&fsol); 
++          pd->mv[iadr + i] = (double) fsol;
++        } else {
++          fread(&fsol,sw,1,inm);             
++          if(iswp) fsol=MMG_swapf(fsol);      
++          pd->mv[iadr + i] = (double) fsol;
++        }
++      } 
+     } else {
+       for (i=0; i<3; i++) {
+-	if(!bin){
+-	  fscanf(inm,"%lf",&pd->mv[iadr + i]);
+-	} else {
+-	  fread(&pd->mv[iadr + i],sd,1,inm);
+-	  if(iswp) pd->mv[iadr + i]=MMG_swapd(pd->mv[iadr + i]);
+-	}
+-      }
+-    }
++        if(!bin){
++          fscanf(inm,"%lf",&pd->mv[iadr + i]); 
++        } else {
++          fread(&pd->mv[iadr + i],sd,1,inm);
++          if(iswp) pd->mv[iadr + i]=MMG_swapd(pd->mv[iadr + i]);      
++        } 
++      } 
++    }             
+   }
+ 
+   if ( abs(mesh->info.imprim) > 3 )
+     fprintf(stdout,"     NUMBER OF GIVEN DATA       %8d\n",pd->np);
+ 
+-  fclose(inm);
++  fclose(inm); 
+   return(1);
+ }
+ 
+ 
+ /* save mesh to disk */
+-int MMG_saveMesh(pMesh mesh,char *filename) {
+-  FILE*        inm;
+-  Hedge                          hed;
++int MMG_saveMesh(pMesh mesh,char *filename,void *dataff) {  
++  FILE*        inm; 
++	Hedge				 hed;
+   pPoint       ppt;
+   pTria        pt1;
+   pTetra       pt;
+   int          i,k,np,ne,nc,ned,*cor,*ed,ref,bin,bpos;
+-  char        *ptr,data[128],chaine[128];
++  char        *ptr,data[128],chaine[128]; 
+   int          binch,nu1,nu2;
++  if(dataff) 
++      return MMG_saveMeshff( mesh, filename,(DataFF*)  dataff);
++
+   mesh->ver = 2; //double precision
+   bin = 0;
+   strcpy(data,filename);
+@@ -959,28 +1399,28 @@
+       *ptr = '\0';
+       strcat(data,".mesh");
+       if( !(inm = fopen(data,"w")) ) {
+-	fprintf(stderr,"  ** UNABLE TO OPEN %s.\n",data);
+-	return(0);
++        fprintf(stderr,"  ** UNABLE TO OPEN %s.\n",data);
++        return(0);
+       }
+     } else {
+-      bin = 1;
++      bin = 1;   
+     }
+   }
+-  else {
++  else { 
+     ptr = strstr(data,".meshb");
+     if( ptr ) bin = 1;
+     if( !(inm = fopen(data,"w")) ) {
+       fprintf(stderr,"  ** UNABLE TO OPEN %s.\n",data);
+       return(0);
+-    }
++    } 
+   }
+   fprintf(stdout,"  %%%% %s OPENED\n",data);
+ 
+   /*entete fichier*/
+   if(!bin) {
+-    strcpy(&chaine[0],"MeshVersionFormatted 2\n");
++    strcpy(&chaine[0],"MeshVersionFormatted 2\n"); 
+     fprintf(inm,"%s",chaine);
+-    strcpy(&chaine[0],"\n\nDimension 3\n");
++    strcpy(&chaine[0],"\n\nDimension 3\n"); 
+     fprintf(inm,"%s ",chaine);
+   } else {
+     binch = 1; //MeshVersionFormatted
+@@ -993,33 +1433,38 @@
+     fwrite(&bpos,sw,1,inm);
+     binch = 3;
+     fwrite(&binch,sw,1,inm);
+-
++    
+   }
+ 
+   /* compact vertices */
+-  if(mesh->ncor) {
++  if(mesh->ncor) {   
+     cor = (int*) M_calloc(mesh->ncor,sizeof(int),"MMG_savemesh");
+-    assert(cor);
++    assert(cor);   
+   }
+-  if(mesh->ned) {
+-    if ( !MMG_zaldy4(&hed,mesh->ned) ) {
+-      if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : EXPORT EDGES IGNORED\n");
+-      mesh->ned = 0;
+-    }
++  if(mesh->ned) {   
++	  if ( !MMG_zaldy4(&hed,mesh->ned) ) {
++      if ( mesh->info.ddebug )  fprintf(stdout,"  ## MEMORY ALLOCATION PROBLEM : EXPORT EDGES IGNORED\n"); 
++			mesh->ned = 0;
++    }   
+     ed = (int*)M_calloc(2*mesh->ned,sizeof(int),"MMG_savemesh");
+-    assert(ed);
++    assert(ed);   
+   }
+-  np = 0;
++  np = 0; 
+   nc = 0;
+   for (k=1; k<=mesh->np; k++) {
+     ppt = &mesh->point[k];
+-    if ( ppt->tag & M_UNUSED )  continue;
+-    ppt->tmp = ++np;
++    if ( ppt->tag & M_UNUSED )  continue;  
++		ppt->tmp = ++np;  
+     if ( ppt->geom & M_CORNER )  cor[nc++] = ppt->tmp;
++  } 
++  //assert(mesh->ncor==nc);
++  if(mesh->ncor!=nc) {
++    fprintf(stdout,"WARNING: some corners have been added or deleted\n");
++    mesh->ncor = nc;
+   }
+-  assert(mesh->ncor==nc);
++
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nVertices\n");
++    strcpy(&chaine[0],"\n\nVertices\n"); 
+     fprintf(inm,"%s",chaine);
+     fprintf(inm,"%d\n",np);
+   } else {
+@@ -1027,27 +1472,27 @@
+     fwrite(&binch,sw,1,inm);
+     bpos += 12+(1+3*mesh->ver)*4*np; //NullPos
+     fwrite(&bpos,sw,1,inm);
+-    fwrite(&np,sw,1,inm);
++    fwrite(&np,sw,1,inm);    
+   }
+   for(k=1; k<=mesh->np; k++) {
+     ppt = &mesh->point[k];
+-    if ( ppt->tag & M_UNUSED )  continue;
+-    //if(ppt->tmp==52453) printf("point %d --> %d\n",ppt->tmp,k);
++    if ( ppt->tag & M_UNUSED )  continue;  
++		//if(ppt->tmp==52453) printf("point %d --> %d\n",ppt->tmp,k);
+     if(!bin) {
+       fprintf(inm,"%.15lg %.15lg %.15lg %d\n",ppt->c[0],ppt->c[1],ppt->c[2],ppt->ref);
+     } else {
+-      fwrite((unsigned char*)&ppt->c[0],sd,1,inm);
+-      fwrite((unsigned char*)&ppt->c[1],sd,1,inm);
+-      fwrite((unsigned char*)&ppt->c[2],sd,1,inm);
+-      fwrite((unsigned char*)&ppt->ref,sw,1,inm);
++      fwrite((unsigned char*)&ppt->c[0],sd,1,inm);    
++      fwrite((unsigned char*)&ppt->c[1],sd,1,inm);    
++      fwrite((unsigned char*)&ppt->c[2],sd,1,inm);    
++      fwrite((unsigned char*)&ppt->ref,sw,1,inm);    
+     }
+   }
+ 
+-  /* rebuild triangles tabular and write triangles */
++  /* rebuild triangles tabular and write triangles */ 
+   mesh->nt = 0;
+   if(MMG_markBdry(mesh)) {
+     if(!bin) {
+-      strcpy(&chaine[0],"\n\nTriangles\n");
++      strcpy(&chaine[0],"\n\nTriangles\n"); 
+       fprintf(inm,"%s",chaine);
+       fprintf(inm,"%d \n",mesh->nt);
+     } else {
+@@ -1055,49 +1500,48 @@
+       fwrite(&binch,sw,1,inm);
+       bpos += 12+16*mesh->nt; //Pos
+       fwrite(&bpos,sw,1,inm);
+-      fwrite(&mesh->nt,sw,1,inm);
++      fwrite(&mesh->nt,sw,1,inm);    
+     }
+     for (k=1; k<=mesh->nt; k++) {
+       pt1  = &mesh->tria[k];
+-      ref  = pt1->ref;
++  	    ref  = pt1->ref;    
+       if(!bin) {
+-	//if(ref==0) printf("tr %d bad ref!!\n",k);
+-	fprintf(inm,"%d %d %d %d\n",mesh->point[pt1->v[0]].tmp,mesh->point[pt1->v[1]].tmp
+-		,mesh->point[pt1->v[2]].tmp,ref);
++        fprintf(inm,"%d %d %d %d\n",mesh->point[pt1->v[0]].tmp,mesh->point[pt1->v[1]].tmp
++    							  ,mesh->point[pt1->v[2]].tmp,ref);
+       } else {
+-	fwrite(&mesh->point[pt1->v[0]].tmp,sw,1,inm);
+-	fwrite(&mesh->point[pt1->v[1]].tmp,sw,1,inm);
+-	fwrite(&mesh->point[pt1->v[2]].tmp,sw,1,inm);
+-	fwrite(&ref,sw,1,inm);
++        fwrite(&mesh->point[pt1->v[0]].tmp,sw,1,inm);    
++        fwrite(&mesh->point[pt1->v[1]].tmp,sw,1,inm);    
++        fwrite(&mesh->point[pt1->v[2]].tmp,sw,1,inm);    
++        fwrite(&ref,sw,1,inm);    
+       }
+     }
+-  }
+-
++  }   
++ 
+   /* write tetrahedra */
+-  ne = 0;
+-  ned = 0;
+-  //printf("avt %d\n",mesh->ned);
++  ne = 0; 
++	ned = 0;  
++	//printf("avt %d\n",mesh->ned);
+   for (k=1; k<=mesh->ne; k++) {
+     pt = &mesh->tetra[k];
+-    if ( !pt->v[0] )  continue;
+-    if(mesh->ned) {
+-      for (i=0 ; i<6 ; i++) {
+-	if (pt->bdryinfo[i]) {
+-	  nu1 = pt->v[MMG_iare[i][0]];
+-	  nu2 = pt->v[MMG_iare[i][1]];
+-	  if (MMG_edgePut(&hed,nu1,nu2,2)<=1) {
+-	    ed[2*ned] = (mesh->point[nu1]).tmp;
+-	    ed[2*ned + 1] = (mesh->point[nu2]).tmp;
+-	    ned++;
+-	  }
+-	}
+-      }
+-    }
+-    ne++;
++    if ( !pt->v[0] )  continue;  
++		if(mesh->ned) {
++		  for (i=0 ; i<6 ; i++) {
++		  	if (pt->bdryinfo[i]) {
++		  		nu1 = pt->v[MMG_iare[i][0]];
++		  		nu2 = pt->v[MMG_iare[i][1]];
++		  		if (MMG_edgePut(&hed,nu1,nu2,2)<=1) {
++		  			ed[2*ned] = (mesh->point[nu1]).tmp;
++		  			ed[2*ned + 1] = (mesh->point[nu2]).tmp;
++		  			ned++;
++		  		} 
++		  	}
++		  } 
++		}
++	  ne++;  
+   }
+-  //printf("ned %d\n",ned);
++	//printf("ned %d\n",ned);
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nTetrahedra\n");
++    strcpy(&chaine[0],"\n\nTetrahedra\n"); 
+     fprintf(inm,"%s",chaine);
+     fprintf(inm,"%d\n",ne);
+   } else {
+@@ -1105,29 +1549,29 @@
+     fwrite(&binch,sw,1,inm);
+     bpos += 12 + 20*ne;//Pos
+     fwrite(&bpos,sw,1,inm);
+-    fwrite((unsigned char*)&ne,sw,1,inm);
+-  }
+-  ne=0;
++    fwrite((unsigned char*)&ne,sw,1,inm);    
++  } 
++	ne=0;
+   for (k=1; k<=mesh->ne; k++) {
+     pt = &mesh->tetra[k];
+-    if ( !pt->v[0] )  continue;
+-    ne++;
+-    ref = pt->ref;
++    if ( !pt->v[0] )  continue;  
++		ne++; 
++    ref = pt->ref;    
+     if(!bin) {
+       fprintf(inm,"%d %d %d %d %d\n",mesh->point[pt->v[0]].tmp,mesh->point[pt->v[1]].tmp
+-	      ,mesh->point[pt->v[2]].tmp,mesh->point[pt->v[3]].tmp,ref);
++  							   ,mesh->point[pt->v[2]].tmp,mesh->point[pt->v[3]].tmp,ref);
+     } else {
+-      fwrite(&mesh->point[pt->v[0]].tmp,sw,1,inm);
+-      fwrite(&mesh->point[pt->v[1]].tmp,sw,1,inm);
+-      fwrite(&mesh->point[pt->v[2]].tmp,sw,1,inm);
+-      fwrite(&mesh->point[pt->v[3]].tmp,sw,1,inm);
+-      fwrite(&ref,sw,1,inm);
++      fwrite(&mesh->point[pt->v[0]].tmp,sw,1,inm);    
++      fwrite(&mesh->point[pt->v[1]].tmp,sw,1,inm);    
++      fwrite(&mesh->point[pt->v[2]].tmp,sw,1,inm);    
++      fwrite(&mesh->point[pt->v[3]].tmp,sw,1,inm);    
++      fwrite(&ref,sw,1,inm);    
+     }
+-  }
+-
++  }  
++     
+   if(mesh->ned) {
+     if(!bin) {
+-      strcpy(&chaine[0],"\n\nEdges\n");
++      strcpy(&chaine[0],"\n\nEdges\n"); 
+       fprintf(inm,"%s",chaine);
+       fprintf(inm,"%d\n",ned);
+     } else {
+@@ -1135,50 +1579,50 @@
+       fwrite(&binch,sw,1,inm);
+       bpos += 12 + 3*4*ned;//Pos
+       fwrite(&bpos,sw,1,inm);
+-      fwrite((unsigned char*)&ned,sw,1,inm);
+-    }
+-    for (k=0; k<ned; k++) {
+-      ref = 0;
+-      if(!bin) {
+-	fprintf(inm,"%d %d %d \n",ed[2*k],ed[2*k+1],ref);
+-      } else {
+-	fwrite(&ed[2*k],sw,1,inm);
+-	fwrite(&ed[2*k+1],sw,1,inm);
+-	fwrite(&ref,sw,1,inm);
+-      }
+-    }
+-    M_free(hed.item);
+-    M_free(ed);
++      fwrite((unsigned char*)&ned,sw,1,inm);    
++    } 
++  	  for (k=0; k<ned; k++) {
++   	    ref = 0;    
++  	    if(!bin) {
++  	      fprintf(inm,"%d %d %d \n",ed[2*k],ed[2*k+1],ref);
++  	    } else {
++  	      fwrite(&ed[2*k],sw,1,inm);    
++  	      fwrite(&ed[2*k+1],sw,1,inm);    
++  	      fwrite(&ref,sw,1,inm);    
++  	    }
++  	  }
++  	  M_free(hed.item);
++			M_free(ed);
+   }
+-
++  
+   /* write corners */
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nCorners\n");
++    strcpy(&chaine[0],"\n\nCorners\n"); 
+     fprintf(inm,"%s",chaine);
+     fprintf(inm,"%d\n",mesh->ncor);
+   } else {
+     binch = 13; //Corners
+     fwrite(&binch,sw,1,inm);
+-    bpos += 12 + 4*mesh->ncor;//Pos
++    bpos += 12 + 4*mesh->ncor;//Pos  
+     fwrite(&bpos,sw,1,inm);
+-    fwrite((unsigned char*)&mesh->ncor,sw,1,inm);
++    fwrite((unsigned char*)&mesh->ncor,sw,1,inm);    
+   }
+   for (k=0; k<mesh->ncor; k++) {
+     if(!bin) {
+       fprintf(inm,"%d \n",cor[k]);
+     } else {
+-      fwrite(&cor[k],sw,1,inm);
++      fwrite(&cor[k],sw,1,inm);    
+     }
+-  }
++  }  
+   /*fin fichier*/
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nEnd\n");
++    strcpy(&chaine[0],"\n\nEnd\n"); 
+     fprintf(inm,"%s",chaine);
+   } else {
+     binch = 54; //End
+     fwrite(&binch,sw,1,inm);
+   }
+-  fclose(inm);
++  fclose(inm); 
+   if(mesh->ncor) M_free(cor);
+   if ( mesh->info.imprim ) {
+     fprintf(stdout,"     NUMBER OF GIVEN VERTICES   %8d\n",mesh->npfixe);
+@@ -1193,20 +1637,22 @@
+     if ( mesh->ned )
+       fprintf(stdout,"     TOTAL NUMBER OF EDGES      %8d\n",ned);
+   }
+-  //if(ned!=mesh->ned) exit(0);
++	//if(ned!=mesh->ned) exit(0);
+   return(1);
+ 
+ }
+ 
+ 
+-int MMG_saveSol(pMesh mesh,pSol sol,char *filename) {
++int MMG_saveSol(pMesh mesh,pSol sol,char *filename,void *dataff) {
+   FILE*        inm;
+   pPoint       ppt;
+   float        fsol;
+   double       tmp;
+   int          i,k,nbl,isol,bin,bpos,typ;
+-  char        *ptr,data[128],chaine[128];
++  char        *ptr,data[128],chaine[128]; 
+   int          binch;
++  if(dataff) 
++      return MMG_saveSolff( mesh, sol, filename,(DataFF*) dataff);
+ 
+   if ( !sol->np )  return(1);
+   bin = 1;
+@@ -1219,24 +1665,24 @@
+       *ptr = '\0';
+       bin  = 0;
+     } else {
+-      ptr = strstr(data,".solb");
+-      if ( ptr ) {
+-	*ptr = '\0';
+-	bin  = 1;
++	    ptr = strstr(data,".solb");
++	    if ( ptr ) {
++	      *ptr = '\0';
++	      bin  = 1;	
+       } else {
+-	ptr = strstr(data,".sol");
+-	if ( ptr ) {
+-	  *ptr = '\0';
+-	  bin  = 0;
+-	}
+-      }
+-    }
++			  ptr = strstr(data,".sol");
++			  if ( ptr ) {
++			    *ptr = '\0';
++			    bin  = 0;	
++			  }
++			}
++    } 
+   }
+-  if ( bin )
++  if ( bin ) 
+     strcat(data,".solb");
+   else
+     strcat(data,".sol");
+-
++  
+   sol->ver = 2;
+   if( bin && !(inm = fopen(data,"wb")) ) {
+     fprintf(stderr,"  ** UNABLE TO OPEN %s.\n",data);
+@@ -1251,9 +1697,9 @@
+ 
+   /*entete fichier*/
+   if(!bin) {
+-    strcpy(&chaine[0],"MeshVersionFormatted 2\n");
++    strcpy(&chaine[0],"MeshVersionFormatted 2\n"); 
+     fprintf(inm,"%s",chaine);
+-    strcpy(&chaine[0],"\n\nDimension 3\n");
++    strcpy(&chaine[0],"\n\nDimension 3\n"); 
+     fprintf(inm,"%s ",chaine);
+   } else {
+     binch = 1; //MeshVersionFormatted
+@@ -1266,19 +1712,19 @@
+     fwrite(&bpos,sw,1,inm);
+     binch = 3;
+     fwrite(&binch,sw,1,inm);
+-
++    
+   }
+ 
+ 
+   switch(sol->offset) {
+   case 1:
+-    typ = 1;
+-    break;
++	 typ = 1;
++   break;
+   case 6:
+-    typ = 3;
++	  typ = 3;
+     break;
+   default:
+-    fprintf(stdout,"  ** DATA IGNORED\n");
++    fprintf(stdout,"  ** DATA IGNORED not 1 ou 6 == %d\n",sol->offset);
+     return(0);
+   }
+ 
+@@ -1287,11 +1733,11 @@
+   for (k=1; k<=mesh->np; k++) {
+     ppt = &mesh->point[k];
+     if ( ppt->tag & M_UNUSED )  continue;
+-    nbl++;
++	nbl++;
+   }
+-
++  
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nSolAtVertices\n");
++    strcpy(&chaine[0],"\n\nSolAtVertices\n"); 
+     fprintf(inm,"%s",chaine);
+     fprintf(inm,"%d\n",nbl);
+     fprintf(inm,"%d %d\n",1,typ);
+@@ -1300,7 +1746,7 @@
+     fwrite(&binch,sw,1,inm);
+     bpos += 20+(sol->offset*sol->ver)*4*nbl; //Pos
+     fwrite(&bpos,sw,1,inm);
+-    fwrite(&nbl,sw,1,inm);
++    fwrite(&nbl,sw,1,inm);    
+     binch = 1; //nb sol
+     fwrite(&binch,sw,1,inm);
+     binch = typ; //typ sol
+@@ -1317,34 +1763,34 @@
+       sol->met[isol + 3] = tmp;
+     }
+     if (sol->ver < 2) {
+-      if(!bin) {
+-	for (i=0; i<sol->offset; i++) {
+-	  fsol = (float) sol->met[isol + i];
+-	  fprintf(inm,"%f ",fsol);
+-	}
+-	fprintf(inm,"\n");
++      if(!bin) { 
++        for (i=0; i<sol->offset; i++) {
++          fsol = (float) sol->met[isol + i];
++          fprintf(inm,"%f ",fsol);
++        } 
++        fprintf(inm,"\n");  
+       } else {
+-	for (i=0; i<sol->offset; i++) {
+-	  fsol = (float) sol->met[isol + i];
+-	  fwrite(&fsol,sw,1,inm);
+-	}
++        for (i=0; i<sol->offset; i++) { 
++          fsol = (float) sol->met[isol + i];
++          fwrite(&fsol,sw,1,inm);
++        }    
+       }
+     } else {
+-      if(!bin) {
+-	for (i=0; i<sol->offset; i++)
+-	  fprintf(inm,"%.15lg ",sol->met[isol + i]);
+-	fprintf(inm,"\n");
++      if(!bin) { 
++        for (i=0; i<sol->offset; i++)
++          fprintf(inm,"%.15lg ",sol->met[isol + i]); 
++        fprintf(inm,"\n");  
+       } else {
+-	for (i=0; i<sol->offset; i++)
+-	  fwrite(&sol->met[isol + i],sd,1,inm);
++        for (i=0; i<sol->offset; i++)
++          fwrite(&sol->met[isol + i],sd,1,inm);    
+       }
+-
++      
+     }
+   }
+-
++  
+   /*fin fichier*/
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nEnd\n");
++    strcpy(&chaine[0],"\n\nEnd\n"); 
+     fprintf(inm,"%s",chaine);
+   } else {
+     binch = 54; //End
+@@ -1355,14 +1801,16 @@
+ }
+ 
+ /*save the node speed : coornew-coorold/dt*/
+-int MMG_saveVect(pMesh mesh,char *filename) {
+-  FILE*        inm;
++int MMG_saveVect(pMesh mesh,char *filename,void *dataff) {
++  FILE*        inm;  
+   pDispl        pd;
+   pPoint       ppt;
+   double       dsol,dd;
+   int          i,k,nbl,bin,bpos,typ;
+-  char        *ptr,data[128],chaine[128];
++  char        *ptr,data[128],chaine[128]; 
+   unsigned char binch;
++  if(dataff) 
++      return MMG_saveVectff( mesh, filename,(DataFF*) dataff);
+ 
+   pd      = mesh->disp;
+   pd->ver = 2;
+@@ -1378,7 +1826,7 @@
+       bin  = 0;
+     }
+   }
+-  if ( bin )
++  if ( bin ) 
+     strcat(data,".o.solb");
+   else
+     strcat(data,".o.sol");
+@@ -1395,9 +1843,9 @@
+ 
+   /*entete fichier*/
+   if(!bin) {
+-    strcpy(&chaine[0],"MeshVersionFormatted 2\n");
++    strcpy(&chaine[0],"MeshVersionFormatted 2\n"); 
+     fprintf(inm,"%s",chaine);
+-    strcpy(&chaine[0],"\n\nDimension 3\n");
++    strcpy(&chaine[0],"\n\nDimension 3\n"); 
+     fprintf(inm,"%s ",chaine);
+   } else {
+     binch = 1; //MeshVersionFormatted
+@@ -1410,20 +1858,20 @@
+     fwrite(&bpos,sw,1,inm);
+     binch = 3;
+     fwrite(&binch,sw,1,inm);
+-
++    
+   }
+-  typ = 2;
++	typ = 2;
+ 
+   /* write data */
+   nbl = 0;
+   for (k=1; k<=mesh->np; k++) {
+     ppt = &mesh->point[k];
+     if ( ppt->tag & M_UNUSED )  continue;
+-    nbl++;
++	nbl++;
+   }
+-
++  
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nSolAtVertices\n");
++    strcpy(&chaine[0],"\n\nSolAtVertices\n"); 
+     fprintf(inm,"%s",chaine);
+     fprintf(inm,"%d\n",nbl);
+     fprintf(inm,"%d %d\n",1,typ);
+@@ -1432,34 +1880,34 @@
+     fwrite(&binch,sw,1,inm);
+     bpos += 20+(3*pd->ver)*4*nbl; //Pos
+     fwrite(&bpos,sw,1,inm);
+-    fwrite(&nbl,sw,1,inm);
++    fwrite(&nbl,sw,1,inm);    
+     binch = 1; //nb sol
+     fwrite(&binch,sw,1,inm);
+     binch = typ; //typ sol
+     fwrite(&binch,sw,1,inm);
+-  }
+-
+-
+-  dd = mesh->info.delta / (double)PRECI;
++  } 
++  
++  
++  dd = mesh->info.delta / (double)PRECI;  
+   fprintf(stdout,"        DT %e\n",mesh->info.dt);
+   for (k=1; k<=mesh->np; k++) {
+     ppt = &mesh->point[k];
+-    if ( ppt->tag & M_UNUSED )  continue;
++    if ( ppt->tag & M_UNUSED )  continue; 
+     for (i=0 ; i<3 ; i++) {
+-      dsol = (ppt->c[i] - mesh->disp->cold[3*(k-1) + 1 + i]* dd - mesh->info.min[i])/mesh->info.dt;
+-      if(!bin) {
+-	fprintf(inm,"%.15lg ",dsol);
++      dsol = (ppt->c[i] - mesh->disp->cold[3*(k-1) + 1 + i]* dd - mesh->info.min[i])/mesh->info.dt; 
++      if(!bin) { 
++        fprintf(inm,"%.15lg ",dsol); 
+       } else {
+-	fwrite(&dsol,sd,1,inm);
++        fwrite(&dsol,sd,1,inm);    
+       }
+     }
+-    if (!bin) fprintf(inm,"\n");
++    if (!bin) fprintf(inm,"\n");  
+   }
+-
+-
++  
++  
+   /*fin fichier*/
+   if(!bin) {
+-    strcpy(&chaine[0],"\n\nEnd\n");
++    strcpy(&chaine[0],"\n\nEnd\n"); 
+     fprintf(inm,"%s",chaine);
+   } else {
+     binch = 54; //End
+--- mmg3d4/build/sources/mmg3d9.c	2012-12-19 16:05:33.000000000 +0100
++++ mmg3d4-nnew/build/sources/mmg3d9.c	2014-03-05 18:37:03.000000000 +0100
+@@ -382,7 +382,7 @@
+     fprintf(stdout,"  ** MOVING MESH\n");
+ 
+   /*alloc et init metold*/
+-  sol->metold = (double*)M_calloc(sol->npmax+1,sol->offset*sizeof(double),"MMG_mmg3d9");
++  if(!sol->metold) sol->metold = (double*)M_calloc(sol->npmax+1,sol->offset*sizeof(double),"MMG_mmg3d9");
+   assert(sol->metold);
+   mesh->disp->cold = (double*)M_calloc(3*(mesh->npmax + 1),sizeof(double),"MMG_mmg3d9");
+   assert(mesh->disp->cold);
+
+--- mmg3d4/build/sources/mmg3dmain/mmg3d.c	2012-12-19 16:05:53.000000000 +0100
++++ mmg3d4-new/build/sources/mmg3dmain/mmg3d.c	2014-04-22 16:37:41.000000000 +0200
+@@ -46,7 +46,7 @@
+ #include "compil.date"
+ #include "mesh.h"
+ #include "eigenv.h"
+-
++#include "dataff.h"
+ TIM_mytime         MMG_ctim[TIMEMAX];
+ short	             MMG_imprim;
+ 
+@@ -310,7 +310,8 @@
+     strcpy(sol->name,mesh->name);
+   }
+   if ( mesh->outf == NULL ) {
+-    mesh->outf = (char *)calloc(128,sizeof(char));
++    static char stbub [256]; 
++    mesh->outf =  stbub; /*(char *)calloc(128,sizeof(char)); */ 
+     assert(mesh->outf);
+     strcpy(mesh->outf,mesh->name);
+     ptr = strstr(mesh->outf,".mesh");
+@@ -397,6 +398,7 @@
+ 	    100.*ttot/ttim[0],call[0],ttot/(float)call[0]);
+   }
+   fprintf(stdout,"\n   ELAPSED TIME  %.2f SEC.  (%.2f)\n",ttim[0],ttot);
++  fflush(stdout);
+ }
+ 
+ 
+@@ -433,8 +435,7 @@
+   return(1);
+ }
+ 
+-
+-int main(int argc,char *argv[]) {
++int mainmmg3d(int argc,char *argv[],DataFF *dataff) { 
+   pMesh      	mesh;
+   pSol       	sol;
+   Info     	*info;
+@@ -442,7 +443,7 @@
+   int k,iadr,i,jj,kk,ii;
+   double	lambda[3],v[3][3],*mold,*m,declic,maxLES,calLES;
+   fprintf(stdout,"  -- MMG3d, Release %s (%s) \n",M_VER,M_REL);
+-  fprintf(stdout,"     Copyright (c) LJLL/IMB, 2010\n");
++  fprintf(stdout,"     Copyright (c) LJLL/IMB, 2014\n");
+   fprintf(stdout,"    %s\n",COMPIL);
+ 
+   signal(SIGABRT,excfun);
+@@ -451,7 +452,7 @@
+   signal(SIGSEGV,excfun);
+   signal(SIGTERM,excfun);
+   signal(SIGINT,excfun);
+-  atexit(endcod);
++  if(dataff==0) atexit(endcod);
+ 
+   TIM_tminit(MMG_ctim,TIMEMAX);
+   TIM_chrono(ON,&MMG_ctim[0]);
+@@ -479,15 +480,27 @@
+   info->dt       = 1.;
+   info->bdry     = 0;
+   info->optles   = 0;
+-
++   /* modif F. Hecht ..*/
++   if(dataff)
++     {
++       mesh->name=dataff->meshname;
++       mesh->move=dataff->movename;
++       sol->name=dataff->solname;
++       /*      printf(" #### %p %p %p --- \n",mesh->name,mesh->move,sol->name); */
++       info->imprim=dataff->imprim;
++       info->memory=dataff->memory;
++     }
++   /* end modf */ 
+   if ( !parsar(argc,argv,mesh,sol) )  return(1);
+   MMG_imprim = info->imprim;
+   
+   /* load data */
+   if ( MMG_imprim )   fprintf(stdout,"\n  -- INPUT DATA\n");
+   TIM_chrono(ON,&MMG_ctim[1]);
+-  if ( !MMG_loadMesh(mesh,mesh->name) )  return(1); 
+-  if ( !MMG_loadSol(sol,sol->name,mesh->npmax) )  return(1);
++  /* modif FH. for interface with ff++ add dataff param     */
++  if ( !MMG_loadMesh(mesh,mesh->name,dataff) )  return(1); 
++  if ( !MMG_loadSol(sol,sol->name,mesh->npmax,dataff ) )  return(1);
++
+   if ( sol->np && sol->np != mesh->np ) {
+     fprintf(stdout,"  ## WARNING: WRONG SOLUTION NUMBER. IGNORED\n");
+     sol->np = 0;
+@@ -495,7 +508,7 @@
+ 
+   if ( !parsop(mesh) )  return(1);
+ 
+-  if ( abs(info->option) == 9 && !MMG_loadVect(mesh,mesh->move,mesh->np) )  return(0);
++  if ( abs(info->option) == 9 && !MMG_loadVect(mesh,mesh->move,mesh->np,dataff) )  return(0);
+ 
+   if ( !MMG_setfunc(sol->offset) ) return(1);
+   if ( !MMG_scaleMesh(mesh,sol) )  return(1);   
+@@ -527,7 +540,7 @@
+   if ( !MMG_hashTetra(mesh) )    return(1);
+   if ( !MMG_markBdry(mesh) )     return(1);
+   if (abs(mesh->info.option)==10) {
+-    MMG_saveMesh(mesh,"tetra.mesh");
++    MMG_saveMesh(mesh,"tetra.mesh",dataff);
+     return(0);
+   }           
+ 
+@@ -571,8 +584,8 @@
+     if ( abs(info->option) == 9 ) {
+       if(!MMG_mmg3d9(mesh,sol,&alert)) {
+         if ( !MMG_unscaleMesh(mesh,sol) )  return(1);
+-        MMG_saveMesh(mesh,mesh->outf);
+-	MMG_saveSol(mesh,sol,mesh->outf);
++        MMG_saveMesh(mesh,mesh->outf,dataff);
++	MMG_saveSol(mesh,sol,mesh->outf,dataff);
+ 	return(1);
+       }
+       /*puts("appel 1");
+@@ -678,18 +691,18 @@
+     fprintf(stdout,"\n  ## WARNING: INCOMPLETE MESH  %d , %d\n",
+             mesh->np,mesh->ne);
+ 
+-  if ( MMG_imprim )  fprintf(stdout,"\n  -- WRITING DATA FILE %s\n",mesh->outf);
++  if ( MMG_imprim && !dataff)  fprintf(stdout,"\n  -- WRITING DATA FILE %s\n",mesh->outf);
+   TIM_chrono(ON,&MMG_ctim[1]);
+   if ( !MMG_unscaleMesh(mesh,sol) )  return(1);
+-  MMG_saveMesh(mesh,mesh->outf);
++  MMG_saveMesh(mesh,mesh->outf,dataff);
+   if ( info->option == 9 ) {
+-    MMG_saveSol(mesh,sol,mesh->outf);
+-    MMG_saveVect(mesh,mesh->move);    
++    MMG_saveSol(mesh,sol,mesh->outf,dataff);
++    MMG_saveVect(mesh,mesh->move,dataff);    
+   }
+   else
+-    MMG_saveSol(mesh,sol,mesh->outf);
++    MMG_saveSol(mesh,sol,mesh->outf,dataff);   
+   TIM_chrono(OFF,&MMG_ctim[1]);
+-  if ( MMG_imprim )  fprintf(stdout,"  -- WRITING COMPLETED\n");
++  if ( MMG_imprim && !dataff)  fprintf(stdout,"  -- WRITING COMPLETED\n");
+ 
+   /* free mem */
+   M_free(mesh->point);
+@@ -697,14 +710,42 @@
+   M_free(mesh->tetra);
+   /*la desallocation de ce pointeur plante dans certains cas...*/
+   M_free(mesh->adja);
++  /* free FH thank to Iztok Bajc */
++  /*    if( mesh->outf ) free( mesh->outf ); */
++    if(sol->metold  ) M_free(sol->metold );
++    if(mesh->disp->cold ) M_free(mesh->disp->cold);
++   /* ---- */
+   M_free(mesh->disp->alpha);
+   M_free(mesh->disp->mv);
+   M_free(mesh->disp);
+ 
+-  if ( sol->npfixe )  M_free(sol->met);
++  if ( sol->met )  M_free(sol->met);
+   M_free(sol);
+ 
+   if ( MMG_imprim < -4 || info->ddebug )  M_memDump();
+   M_free(mesh);
++  if(MMG_imprim && dataff ) endcod();
++  if( M_memLeak() > 1000)
++    {
++        M_memDump();
++    }
+   return(0);
+ }
++
++int main(int argc,char *argv[])  {
++    return  mainmmg3d( argc,argv,0);
++}
++/*
++ def 
++ */
++ MMG_Swap MMG_swpptr;
++ double (*MMG_length)(double *,double *,double *,double *);
++ double (*MMG_caltet)(pMesh ,pSol ,int );
++ double (*MMG_calte1)(pMesh ,pSol ,int );
++ int    (*MMG_caltet2)(pMesh ,pSol ,int ,int ,double ,double *);
++ int    (*MMG_cavity)(pMesh ,pSol ,int ,int ,pList ,int );
++ int    (*MMG_buckin)(pMesh ,pSol ,pBucket ,int );
++ int    (*MMG_optlen)(pMesh ,pSol ,double ,int );
++ int    (*MMG_interp)(double *,double *,double *,double );
++ int    (*MMG_optlentet)(pMesh ,pSol ,pQueue ,double ,int ,int );
++ int    (*MMG_movevertex)(pMesh ,pSol ,int ,int );
diff --git a/download/mshmet/Makefile b/download/mshmet/Makefile
new file mode 100755
index 0000000..f9a3128
--- /dev/null
+++ b/download/mshmet/Makefile
@@ -0,0 +1,91 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+all-local: mshmet
+
+include ff-flags
+
+# Downloading and compiling mshmet
+# -------------------------------
+# 
+DIRPKG= ../pkg
+SRCDIR= ./mshmet$(mshmet_VERSION)
+#-$(mshmet_VERSION)
+PACKAGE=$(DIRPKG)/mshmet$(mshmet_VERSION).tgz
+SERVER=http://www.ann.jussieu.fr/~frey/ftp/archives/
+INSTALL=../..
+mshmet_VERSION=.2012.04.25
+FAIRE=$(SRCDIR)/FAIRE
+
+# ---------------------- 
+#     mshmetlib
+
+MSHMET_DIR = $(abs_top_builddir)/download/mshmet/mshmet$(mshmet_VERSION)
+MSHMET_SRCDIRNOLIB = $(MSHMET_DIR)/sources
+MSHMET_SRCDIR = $(MSHMET_DIR)/sourceslib
+MSHMET_OBJDIR = $(MSHMET_DIR)/objects
+
+mshmet: $(FAIRE) 
+
+$(FAIRE):$(SRCDIR)/FAIT
+	$(MAKE) WHERE $(SRCDIR)/$(INSTALL)  
+	touch $(FAIRE)
+
+$(SRCDIR)/FAIT:$(SRCDIR)/tag-tar
+	cd $(MSHMET_DIR); $(MAKE)
+	touch $(SRCDIR)/FAIT
+
+# FFCS - libMesh is also required by yams, so we move all the rules to [[file:../../../Makefile.am]]
+install:$(SRCDIR)/FAIT
+	cp $(MSHMET_SRCDIR)/mshmetlib.h  $(SRCDIR)/$(INSTALL)/include/mshmetlib.h
+	cp $(MSHMET_OBJDIR)/libmshmet.a  $(SRCDIR)/$(INSTALL)/lib/libmshmet.a
+
+# FFCS - simplify makefile structure for automatic rebuilds
+WHERE:install
+	echo mshmet  LD -L at DIR@/lib -lmshmet  >$(SRCDIR)/$(INSTALL)/lib/WHERE.mshmet
+	echo mshmet INCLUDE -I at DIR@/include>> $(SRCDIR)/$(INSTALL)/lib/WHERE.mshmet
+
+
+$(SRCDIR)/tag-tar: $(PACKAGE) mshmetlib-internal.h mshmetlib.c mshmetlib.h 
+	-mkdir mshmet$(mshmet_VERSION)
+	cd mshmet$(mshmet_VERSION); tar xvzf ../$(PACKAGE)
+	-mkdir $(MSHMET_SRCDIR)
+	cp $(MSHMET_SRCDIRNOLIB)/*.c $(MSHMET_SRCDIRNOLIB)/*.h $(MSHMET_SRCDIR)
+	cp $(MSHMET_SRCDIRNOLIB)/compil.date $(MSHMET_SRCDIR)
+	cp mshmetlib-internal.h mshmetlib.c mshmetlib.h $(MSHMET_SRCDIR)/
+	cp ../../src/libMesh/chrono.h $(MSHMET_SRCDIR)
+	rm $(MSHMET_SRCDIR)/mshmet.c
+	rm $(MSHMET_SRCDIR)/chrono.c
+	cp ../../src/libMesh/eigenv.c $(MSHMET_SRCDIR)
+	cp Makefile-mshmet.inc $(MSHMET_DIR)/makefile
+	cd $(MSHMET_SRCDIR); patch -p2 < ../../mshmet.2011.03.06.patch
+#
+#	Patch for i586 developed by John Hunt (14/2/13)
+#
+	cd $(MSHMET_SRCDIR); patch -p2 < ../../mshmet.2012.04.25_i586.patch
+	touch $(SRCDIR)/tag-tar
+
+$(PACKAGE):
+	../getall -o mshmet -a
+
+clean:
+	-rm ff-flags
+#	FFCS - make sure that all directories are cleaned. Thisis especially important under Windows because there is no
+#	compilation dependencies control there (see
+#	[[file:c:/cygwin/home/alh/ffcs/dist/configure.ac::dependency_tracking]])
+	-rm -rf mshmet.????.??.??
+	-rm FAIT $(FAIRE) 
+
+ff-flags: ../Makefile 
+	grep 'abs_top_builddir *=' ../Makefile >> ff-flags
+	grep 'CC *=' ../Makefile >> ff-flags
+	grep 'CFLAGS *=' ../Makefile >> ff-flags
+	grep 'LDFLAGS *=' ../Makefile >> ff-flags
+	grep 'AR *=' ../Makefile >> ff-flags
+	grep 'ARFLAGS *=' ../Makefile >> ff-flags
+	grep 'RANLIB *=' ../Makefile >> ff-flags
+	grep 'WGET *=' ../Makefile >> ff-flags
+	grep 'mshmet_VERSION *=' ./Makefile >> ff-flags
+
+
+.PHONY: $(SRCDIR)/$(INSTALL)
diff --git a/download/mshmet/Makefile-mshmet.inc b/download/mshmet/Makefile-mshmet.inc
new file mode 100644
index 0000000..8a31f9c
--- /dev/null
+++ b/download/mshmet/Makefile-mshmet.inc
@@ -0,0 +1,44 @@
+include ../ff-flags
+
+MSHMETDIR =  $(abs_top_builddir)/download/mshmet/mshmet$(mshmet_VERSION)
+# working dirs
+EXEDIR = #$(MSHMETDIR)/executable
+SRCDIR = $(MSHMETDIR)/sourceslib
+OBJDIR = $(MSHMETDIR)/objects/$(ARCHI)
+ARCDIR = $(MSHMETDIR)/archives
+DIRDIR = $(EXEDIR) $(OBJDIR) $(ARCDIR)
+VPATH  = $(SRCDIR)
+INCDIR = -I$(MSHMETDIR)/sourceslib/ -I$(abs_top_builddir)/src/libMesh/
+LDLDIR = -L$(abs_top_builddir)/src/libMesh/ -lMesh
+
+# objects list
+src    = $(wildcard $(SRCDIR)/*.c)
+header = $(wildcard $(SRCDIR)/*.h)
+objs   = $(patsubst $(SRCDIR)%,$(OBJDIR)%,$(src:.c=.o))
+prog   = mshmet
+lib    = $(OBJDIR)/libmshmet.a
+
+#.SILENT:
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+	$(CC) $(OPT64) $(INCDIR) $(CFLAGS) -DSERIAL -c $< -o $@
+
+$(EXEDIR)/$(prog):$(DIRDIR) $(objs)
+	echo "#define COMPIL " '"' `date` '"' > $(SRCDIR)/compil.date
+	#$(CC) -c $(CFLAGS) $(INCDIR) $(SRCDIR)/mshmet.c -o $(OBJDIR)/mshmet.o
+	#$(CC) $(LDFLAGS) $(OPT64) $(LDLDIR) $(objs) -o $@ -lm
+	$(AR) $(ARFLAGS) $(lib) $(objs)
+	$(RANLIB) $(lib)
+
+$(objs):$(header)
+
+$(DIRDIR):
+	@[ -d $@ ] || mkdir $@
+
+clean:
+	-rm $(objs) $(EXEDIR)/$(prog)
+
+tar:$(DIRDIR)
+	tar czf $(ARCDIR)/$(prog).`date +"%Y.%m.%d"`.tgz sources makefile
+
+target: $(EXEDIR)/$(prog)
diff --git a/download/mshmet/mshmet.2011.03.06.patch b/download/mshmet/mshmet.2011.03.06.patch
new file mode 100644
index 0000000..bd940f3
--- /dev/null
+++ b/download/mshmet/mshmet.2011.03.06.patch
@@ -0,0 +1,63 @@
+--- mshmet.2011.03.06/sources/mshmet.h	2011-02-11 19:41:49.000000000 +0100
++++ mshmet.2011.03.06/sourceslib/mshmet.h	2011-11-16 22:04:20.000000000 +0100
+@@ -33,7 +33,7 @@
+ #define MS_MAX(a,b)   ( ((a) < (b)) ? (b) : (a) )
+ #define MS_MIN(a,b)   ( ((a) < (b)) ? (a) : (b) )
+ 
+-char idir[5];
++extern char idir[5];
+ 
+ typedef struct {
+   double         c[3];
+@@ -135,17 +135,17 @@
+ pHash hashEdge_3d(pMesh mesh);
+ pHash hashEdge_2d(pMesh mesh);
+ 
+-int   (*boulep)(pMesh ,int ,int ,int *);
+-int   (*hashel)(pMesh );
+-int   (*gradLS)(pMesh ,pSol ,int ,int );
+-int   (*hessLS)(pMesh ,pSol ,int ,int );
+-int   (*avgval)(pMesh ,pSol ,int );
+-int   (*clsval)(pMesh ,pSol ,int );
+-int   (*nrmhes)(pMesh ,pSol ,int );
+-int   (*redsim)(double *,double *,double *);
+-int   (*defmet)(pMesh ,pSol ,int );
+-double (*getSol)(pSol ,int ,int );
+-int   (*metrLS)(pMesh mesh,pSol );
+-int   (*lissag)(pMesh ,pSol , int ,int );
++extern int   (*boulep)(pMesh ,int ,int ,int *);
++extern int   (*hashel)(pMesh );
++extern int   (*gradLS)(pMesh ,pSol ,int ,int );
++extern int   (*hessLS)(pMesh ,pSol ,int ,int );
++extern int   (*avgval)(pMesh ,pSol ,int );
++extern int   (*clsval)(pMesh ,pSol ,int );
++extern int   (*nrmhes)(pMesh ,pSol ,int );
++extern int   (*redsim)(double *,double *,double *);
++extern int   (*defmet)(pMesh ,pSol ,int );
++extern double (*getSol)(pSol ,int ,int );
++extern int   (*metrLS)(pMesh mesh,pSol );
++extern int   (*lissag)(pMesh ,pSol , int ,int );
+ 
+ #endif
+--- mshmet.2012.04.25/sources/lplib3.c	2013-04-10 11:53:17.000000000 +0200
++++ mshmet.2012.04.25/sourceslib/lplib3.c	2013-04-10 11:54:49.000000000 +0200
+@@ -30,7 +30,10 @@
+ #include <assert.h>
+ #include <errno.h>
+ #include "lplib3.h"
+-
++#ifdef __FreeBSD__
++#include <sys/types.h>
++#include <pmc.h>
++#endif
+ 
+ /*----------------------------------------------------------*/
+ /* Defines													*/
+@@ -1250,6 +1253,7 @@
+ 		 * NPROC environment variable (BSD/OS, CrayOS)
+ 		 * sysctl hw.ncpu or kern.smp.cpus
+ 		 */
++	        int ncpu; 
+ 		if (pmc_init() == 0 && (ncpu = pmc_ncpu()) != -1)
+ 			maxthreads = ncpu;
+ 		else
diff --git a/download/mshmet/mshmet.2012.04.25_i586.patch b/download/mshmet/mshmet.2012.04.25_i586.patch
new file mode 100644
index 0000000..3d82255
--- /dev/null
+++ b/download/mshmet/mshmet.2012.04.25_i586.patch
@@ -0,0 +1,11 @@
+--- mshmet.2012.04.25/sourceslib/libmesh5.c.orig	2013-02-12 17:47:00.093678985 +0000
++++ mshmet.2012.04.25/sourceslib/libmesh5.c	2013-02-12 17:48:27.083684096 +0000
+@@ -1381,7 +1381,7 @@
+ 	int IntVal;
+ 	long pos;
+ 
+-	if(msh->ver >= 3)
++	if ( (msh->ver >= 3) && (sizeof(long) == 8) )
+ 		ScaDblWrd(msh, (unsigned char*)&pos);
+ 	else
+ 	{
diff --git a/download/mshmet/mshmetlib-internal.h b/download/mshmet/mshmetlib-internal.h
new file mode 100644
index 0000000..51e7787
--- /dev/null
+++ b/download/mshmet/mshmetlib-internal.h
@@ -0,0 +1,14 @@
+typedef MSHMET_Point Point;
+typedef MSHMET_Tetra Tetra;
+typedef MSHMET_Tria Tria;
+typedef MSHMET_Mesh Mesh;
+typedef MSHMET_Sol Sol;
+typedef MSHMET_Deriv Deriv;
+
+typedef MSHMET_pPoint pPoint; 
+typedef MSHMET_pTetra pTetra; 
+typedef MSHMET_pDeriv pDeriv;
+typedef MSHMET_pTria pTria;   
+typedef MSHMET_Info Info;     
+typedef MSHMET_pMesh pMesh;   
+typedef MSHMET_pSol pSol;
diff --git a/download/mshmet/mshmetlib.c b/download/mshmet/mshmetlib.c
new file mode 100644
index 0000000..b78ad8c
--- /dev/null
+++ b/download/mshmet/mshmetlib.c
@@ -0,0 +1,303 @@
+/* mshmetlib.c
+
+ mshmetlib(int option, ...) to use mshmet via a library
+ * compute metric based on hessian
+
+ * j.morice LJLL 2010
+ * Copyright (c) LJLL, 2010.
+*/
+
+#include "mshmet.h"
+#include "compil.date"
+extern long verbosity;
+char     idir[5]     = {0,1,2,0,1};
+mytime   mshmet_ctim[TIMEMAX];
+int   (*boulep)(pMesh ,int ,int ,int *);
+int   (*hashel)(pMesh );
+int   (*gradLS)(pMesh ,pSol ,int ,int );
+int   (*hessLS)(pMesh ,pSol ,int ,int );
+int   (*avgval)(pMesh ,pSol ,int );
+int   (*clsval)(pMesh ,pSol ,int );
+int   (*nrmhes)(pMesh ,pSol ,int );
+int   (*redsim)(double *,double *,double *);
+int   (*defmet)(pMesh ,pSol ,int );
+double (*getSol)(pSol ,int ,int );
+int   (*metrLS)(pMesh mesh,pSol );
+int   (*lissag)(pMesh ,pSol , int ,int );
+
+
+static void mshmet_excfun(int sigid) {
+  fprintf(stdout,"\n Unexpected error:");  fflush(stdout);
+  switch(sigid) {
+    case SIGABRT:
+      fprintf(stdout,"  Abnormal stop\n");  exit(1);
+    case SIGFPE:
+      fprintf(stdout,"  Floating-point exception\n"); exit(1);
+    case SIGILL:
+      fprintf(stdout,"  Illegal instruction\n"); exit(1);
+    case SIGSEGV:
+      fprintf(stdout,"  Segmentation fault\n");  exit(1);
+    case SIGTERM:
+    case SIGINT:
+      //fprintf(stdout,"  Program killed\n");  exit(1);
+      fprintf(stdout," Abnormal end\n");  exit(1);
+  }
+  exit(1);
+}
+
+/*
+static void usage(char *prog) {
+  fprintf(stdout,"\n usage: %s filein[.mesh] [solin[.sol]] [fileout.sol] -eps x -hmin y -hmax z -v -iso -norm\n",prog);
+  
+  fprintf(stdout,"\n** Generic options :\n");
+  fprintf(stdout,"-d      Turn on debug mode\n");
+  fprintf(stdout,"-h      Print this message\n");
+  fprintf(stdout,"-ls     Build levelset metric\n");
+  fprintf(stdout,"-v [n]  Tune level of verbosity\n");
+  fprintf(stdout,"-m file Use metric file\n");
+
+  fprintf(stdout,"\n** Specific options : \n");
+  fprintf(stdout,"  -eps :  tolerance\n");
+  fprintf(stdout,"  -hmin:  min size\n");
+  fprintf(stdout,"  -hmax:  max size\n");
+  fprintf(stdout,"  -iso :  isotropic\n");
+  fprintf(stdout,"  -w   :  relative width for LS (0<w<1)\n");
+  fprintf(stdout,"  -n[i]:  normalization (level i), default=0\n");
+  fprintf(stdout,"  -s n :  consider solution n (only)\n");
+
+  fprintf(stdout,"\n** DEFAULT.hmet file allows to store parameter values\n");
+  fprintf(stdout,"eps   x\n");
+  fprintf(stdout,"hmin  y\n");
+  fprintf(stdout,"hmax  z\n");
+  fprintf(stdout,"iso\n");
+  exit(1);
+}
+*/
+
+/*
+int parsop(pMesh mesh,pSol sol) {
+  char    *ptr,data[256],key[256];
+  float    dummy;
+  int      i,ret;
+  FILE    *in;
+
+  strcpy(data,sol->name);
+  ptr = strstr(data,".sol");
+  if ( ptr )  *ptr = '\0';
+  strcat(data,".mhes");
+
+  in = fopen(data,"r");
+  if ( !in ) {
+    strcpy(data,"DEFAULT.hmet");
+    in = fopen(data,"r");
+    if ( !in )  {
+      if ( mesh->info.imprim < 0 )
+        fprintf(stdout,"  %%%% DEFAULT VALUES (%g %g %g)\n",
+                mesh->info.eps,mesh->info.hmin,mesh->info.hmax);
+      return(1);
+    }
+  }
+  fprintf(stdout,"  %%%% %s FOUND\n",data);
+
+  while ( !feof(in) ) {
+    ret = fscanf(in,"%s",key);
+    if ( !ret || feof(in) )  break;
+    for (i=0; i<strlen(key); i++) key[i] = tolower(key[i]);
+
+    if ( !strcmp(key,"hmin") ) {
+      fscanf(in,"%f",&dummy);
+      mesh->info.hmin = dummy;
+    }
+    else if ( !strcmp(key,"hmax") ) {
+      fscanf(in,"%f",&dummy);
+      mesh->info.hmax = dummy;
+    }
+    else if ( !strcmp(key,"eps") ) {
+      fscanf(in,"%f",&dummy);
+      mesh->info.eps = dummy;
+    }
+    else if ( !strcmp(key,"iso") ) {
+      mesh->info.iso = 1;
+    }
+    else if ( !strcmp(key,"norm") ) {
+      fscanf(in,"%d",&mesh->info.nnu);
+    }
+    else if ( key[0] == '#' ) {
+      fgets(key,255,in);
+    }
+    else fprintf(stderr,"  unrecognized keyword : %s\n",key);
+  }
+
+  fclose(in);
+  return(1);
+}
+*/
+
+static void mshmet_stats(pMesh mesh,pSol sol) {
+  fprintf(stdout,"     NUMBER OF GIVEN VERTICES   %8d\n",mesh->np);
+  if ( mesh->nt )
+    fprintf(stdout,"     NUMBER OF GIVEN TRIANGLES  %8d\n",mesh->nt);
+  if ( mesh->ne )
+    fprintf(stdout,"     NUMBER OF GIVEN TETRAHEDRA %8d\n",mesh->ne);
+  fprintf(stdout,"     NUMBER OF GIVEN DATA       %8d\n",sol->np);
+}
+
+
+static void mshmet_endcod() {
+  double   ttot,ttim[TIMEMAX];
+  int      k,call[TIMEMAX];
+
+  chrono(OFF,&mshmet_ctim[0]);
+  for (k=0; k<TIMEMAX; k++) {
+    call[k] = mshmet_ctim[k].call;
+    ttim[k] = mshmet_ctim[k].call ? gttime(mshmet_ctim[k]) : 0.0;
+  }
+  ttot    = ttim[1]+ttim[2]+ttim[3]+ttim[4];
+  ttim[0] = MS_MAX(ttim[0],ttot);
+
+  if ( ttot > 0.01 ) {
+    fprintf(stdout,"\n  -- CPU REQUIREMENTS\n");
+    fprintf(stdout,"  in/out    %8.2f %%    %3d. calls,   %7.2f sec/call\n",
+        100.*ttim[1]/ttim[0],call[1],ttim[1]/(float)call[1]);
+    fprintf(stdout,"  analysis  %8.2f %%    %3d. calls,   %7.2f sec/call\n",
+        100.*ttim[2]/ttim[0],call[2],ttim[2]/(float)call[2]);
+    fprintf(stdout,"  metric    %8.2f %%    %3d. calls,   %7.2f sec/call\n",
+        100.*ttim[3]/ttim[0],call[3],ttim[3]/(float)call[3]);
+    fprintf(stdout,"  total     %8.2f %%    %3d. calls,   %7.2f sec/call\n",
+        100.*ttot/ttim[0],call[0],ttot/(float)call[0]);
+  }
+  fprintf(stdout,"\n   ELAPSED TIME  %.2f SEC.  (%.2f)\n",ttim[0],ttot);
+}
+
+
+/* set function pointers */
+/* set function pointers */
+void MSHMET_setfunc(pMesh mesh) {
+  if ( mesh->dim == 2 ) {
+    boulep = boulep_2d;
+    hashel = hashel_2d;
+    gradLS = gradLS_2d;
+    hessLS = hessLS_2d;
+    getSol = getSol_2d;
+    avgval = avgval_2d;
+    clsval = clsval_2d;
+    nrmhes = nrmhes_2d;
+    defmet = defmet_2d;
+    redsim = redsim_2d;
+    metrLS = metrLS_2d;
+    lissag = lissag_2d;
+  }
+  else {
+    if ( mesh->ne > 0 ) { /* 3d */
+      boulep = boulep_3d;
+      hashel = hashel_3d;
+      gradLS = gradLS_3d;
+      hessLS = hessLS_3d;
+      getSol = getSol_3d;
+      avgval = avgval_3d;
+      clsval = clsval_3d;
+      nrmhes = nrmhes_3d;
+      defmet = defmet_3d;
+      redsim = redsim_3d;
+      metrLS = metrLS_3d;
+			lissag = lissag_3d;
+    }
+    else { /* surface mesh */
+      boulep = boulep_2d;
+      hashel = hashel_2d;
+      lissag = lissag_2d;
+      avgval = avgval_3d;
+      clsval = clsval_3d;
+      nrmhes = nrmhes_3d;
+      getSol = getSol_3d;
+      redsim = redsim_3d;
+      gradLS = gradLS_s;
+      hessLS = hessLS_s;
+      defmet = defmet_s;
+
+      metrLS = metrLS_3d;
+    }
+  }
+}
+
+
+
+int MSHMET_mshmet(int intopt[7], double fopt[4], pMesh mesh, pSol sol){
+  Info *info;
+  fprintf(stdout,"  -- MSHMET, Release %s (%s) \n",MS_VER,MS_REL);
+  fprintf(stdout,"     %s\n",MS_CPY);
+  fprintf(stdout,"    %s\n",COMPIL);
+
+  /* trap exceptions */
+  signal(SIGABRT,mshmet_excfun);
+  signal(SIGFPE,mshmet_excfun);
+  signal(SIGILL,mshmet_excfun);
+  signal(SIGSEGV,mshmet_excfun);
+  signal(SIGTERM,mshmet_excfun);
+  signal(SIGINT,mshmet_excfun);
+  //atexit(mshmet_endcod);
+
+  tminit(mshmet_ctim,TIMEMAX);
+  chrono(ON,&mshmet_ctim[0]);
+  chrono(ON,&mshmet_ctim[1]);
+  /* default */
+  info = &mesh->info;
+  info->hmin   = (float) fopt[0]; // 0.01;
+  info->hmax   = (float) fopt[1]; // 1.0;
+  info->eps    = (float) fopt[2]; // 0.01;
+  info->width  = (float) fopt[3]; // 0.05;
+
+  info->nnu    = intopt[0]; //  0;
+  info->iso    = intopt[1]; //  0;
+  info->ls     = intopt[2]; //  0;
+  info->ddebug = intopt[3]; //  0;
+  info->imprim = intopt[4]; // 10;
+  info->nlis   = intopt[5]; //  0;
+  
+  info->bin    =   1;          // pas besoin c'est pour le fichier
+  info->nsol   =  -1; //-1;    // pas besoin ==> on peut prendre plusieurs solutions en meme temps ???
+  info->metric =  intopt[6];        // 0; // metric given besoin ???
+ 
+  MSHMET_setfunc(mesh);
+  chrono(OFF,&mshmet_ctim[1]);
+  if ( mesh->info.imprim )  mshmet_stats(mesh,sol);
+  fprintf(stdout,"  -- DATA READING COMPLETED.     %.2f sec.\n",gttime(mshmet_ctim[1]));
+
+  fprintf(stdout,"\n  %s\n   MODULE MSHMET-LJLL : %s (%s)\n  %s\n",
+          MS_STR,MS_VER,MS_REL,MS_STR);
+
+  /* analysis */
+  chrono(ON,&mshmet_ctim[2]);
+  if ( mesh->info.imprim )   fprintf(stdout,"\n  -- PHASE 1 : ANALYSIS\n");
+  if ( abs(mesh->info.imprim) > 4 ) {
+    fprintf(stdout,"  ** SETTING ADJACENCIES\n");
+    fflush(stdout);
+  }
+  if ( !scaleMesh(mesh,sol) )  return(1);
+  if ( !hashel(mesh) )         exit(1);
+  chrono(OFF,&mshmet_ctim[2]);
+  if ( mesh->info.imprim )
+    fprintf(stdout,"  -- PHASE 1 COMPLETED.     %.2f sec.\n",gttime(mshmet_ctim[2]));
+
+  /* metric */
+  chrono(ON,&mshmet_ctim[3]);
+  if ( mesh->info.imprim )  fprintf(stdout,"\n  -- PHASE 2 : METRIC\n");
+  if ( !mshme1(mesh,sol) )  exit(1);
+  
+  chrono(OFF,&mshmet_ctim[3]);
+  if ( mesh->info.imprim )
+    fprintf(stdout,"  -- PHASE 2 COMPLETED.     %.2f sec.\n",gttime(mshmet_ctim[3]));
+  
+  fprintf(stdout,"\n  %s\n   END OF MODULE MSHMET \n  %s\n",MS_STR,MS_STR);
+  /*
+  sol->outn="zzzz";
+  if ( !saveMet(sol,&mesh->info,sol->outn) )  exit(1);
+  */
+  if ( mesh->info.imprim )
+    mshmet_endcod();
+
+  fprintf(stdout,"\n  %s\n   END OF MODULE MSHMET \n  %s\n",MS_STR,MS_STR);
+  if ( mesh->info.imprim < -4 || mesh->info.ddebug )  M_memDump();
+
+  return(0);
+}
diff --git a/download/mshmet/mshmetlib.h b/download/mshmet/mshmetlib.h
new file mode 100644
index 0000000..f0f38b6
--- /dev/null
+++ b/download/mshmet/mshmetlib.h
@@ -0,0 +1,92 @@
+typedef struct {
+  /*
+  double         aire,rins;
+  double         c[3];
+  int            s,nv,mark;
+  unsigned char  b,h;
+  */
+  double         c[3];
+  int            s,nv,mark;
+  unsigned char  b,h;
+} MSHMET_Point;
+typedef MSHMET_Point * MSHMET_pPoint;
+
+typedef struct {
+  int     v[3];
+  int     mark;
+  /*
+  double  aire;
+  int     v[3];
+  int     mark;*/
+} MSHMET_Tria;
+typedef MSHMET_Tria * MSHMET_pTria;
+
+typedef struct {
+  int     v[4];
+  int     mark;
+} MSHMET_Tetra;
+typedef MSHMET_Tetra * MSHMET_pTetra;
+
+typedef struct {
+  double   delta;
+  double   min[3],max[3];
+  float    eps,hmin,hmax,width,ani,hgrad,map;
+  int      nnu,nsol,nlis;
+  char     imprim,ddebug,iso,bin,metric,ls;
+
+  /* double   delta;
+  double   min[3],max[3];
+  float    eps,hmin,hmax,width;
+  int      nnu,nsol,nlis;
+  char     imprim,ddebug,iso,bin,metric,ls; */
+} MSHMET_Info;
+
+typedef struct {
+  /*
+  int      np,nt,ne,ver,dim;
+  int     *adja,mark;
+  char    *name,*mname;
+
+  MSHMET_pPoint   point;
+  MSHMET_pTria    tria;
+  MSHMET_pTetra   tetra;
+  MSHMET_Info info;
+  */
+
+  int      np,nt,ne,ver,dim;
+  int     *adja,mark;
+  char    *name,*mname;
+
+  MSHMET_pPoint   point;
+  MSHMET_pTria    tria;
+  MSHMET_pTetra   tetra;
+  MSHMET_Info     info;
+} MSHMET_Mesh;
+
+typedef MSHMET_Mesh * MSHMET_pMesh;
+
+typedef struct {
+  int         np,ver,dim,type,size,typtab[GmfMaxTyp];
+  double     *sol,*met,*hes,*grd,*nn,umin,umax;
+  char       *name,*outn,*mapname;
+  /*  version 2.0 
+  int         np,ver,dim,type,size,typtab[GmfMaxTyp];
+  double     *sol,*met,umin,umax;
+  char       *name,*outn; */
+} MSHMET_Sol;
+typedef MSHMET_Sol * MSHMET_pSol;
+
+typedef struct {
+  double         grd[3];
+  double         hes[6];
+} MSHMET_Deriv;
+typedef MSHMET_Deriv * MSHMET_pDeriv;
+
+#ifdef  __cplusplus
+namespace mshmet{
+extern "C" {
+#endif
+  int MSHMET_mshmet(int intopt[7], double fopt[4], MSHMET_pMesh mesh, MSHMET_pSol sol);
+#ifdef  __cplusplus
+}}
+#endif
diff --git a/download/mumps-seq/Makefile b/download/mumps-seq/Makefile
new file mode 100644
index 0000000..7af418f
--- /dev/null
+++ b/download/mumps-seq/Makefile
@@ -0,0 +1,89 @@
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# http://www.ljll.math.upmc.fr/lehyaric
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem make multipleauthors start=19/03/10 upmc
+
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include Makefile.inc
+
+all-local: mumps
+mumps:../lib/WHERE.mumpsseq
+
+# Downloading and compiling mumps
+# -------------------------------
+
+DIRPKG=../pkg
+SRCDIR=MUMPS_$(VERSION)
+PACKAGE1=$(DIRPKG)/MUMPS_$(VERSION).tar.gz
+INSTALL=../..
+VERSION=4.10.0
+
+# FFCS - install and WHERE need to be done sequentially, even in parallel builds
+
+../lib/WHERE.mumpsseq: install.done
+	echo mumps-seq LD -L at DIR@/lib -ldmumpsFREEFEM-SEQ -lzmumpsFREEFEM-SEQ -lmumps_commonFREEFEM-SEQ	\
+		-lpordFREEFEM-SEQ $(LIBSPTHREAD)  > ../lib/WHERE.mumpsseq
+	echo mumps-seq INCLUDE -I at DIR@/include/libseq >> ../lib/WHERE.mumpsseq
+	echo libseq LD -L at DIR@/lib  -lmpiseqFREEFEM-SEQ >>../lib/WHERE.mumpsseq
+	echo libseq INCLUDE -I at DIR@/include/libseq >> ../lib/WHERE.mumpsseq
+
+install.done: $(SRCDIR)/FAIT
+	-mkdir -p ../include/libseq
+	cp $(SRCDIR)/include/*.h ../include/libseq
+	cp $(SRCDIR)/libseq/*.h  ../include/libseq
+	-mkdir -p ../lib
+	cp $(SRCDIR)/lib/*.a ../lib/
+	cp $(SRCDIR)/libseq/libmpiseqFREEFEM-SEQ.a ../lib/
+	touch $@
+
+$(SRCDIR)/FAIT:Makefile.inc
+	cp Makefile.inc $(SRCDIR)
+#
+#	FFCS - 22/5/12 - Mumps has difficulties compiling d & z in parallel
+#
+	cd $(SRCDIR) && $(MAKE) d
+	cd $(SRCDIR) && $(MAKE) z
+	touch $@
+
+Makefile.inc: ../../config.status Makefile Makefile-mumps-$(VERSION).inc $(SRCDIR)/tag-tar
+	../../config.status  --file="Makefile.inc:Makefile-mumps-$(VERSION).inc"
+
+$(SRCDIR)/tag-tar:$(PACKAGE1)
+	tar xvzf $(PACKAGE1)
+	touch $@
+
+$(PACKAGE1):
+	../getall -o MUMPS -a
+
+clean:
+	-rm Makefile.inc FAIRE* *~ 
+	-rm -rf ../include/*mumps*
+	-rm -rf ../lib/lib*mumps* ../lib/libpord*.a ../lib/libmpiseq*.a ../lib/WHERE.mumpsseq
+	-rm -rf $(SRCDIR)
+	-rm *.done config.log
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/mumps-seq/Makefile-mumps-4.10.0.inc b/download/mumps-seq/Makefile-mumps-4.10.0.inc
new file mode 100644
index 0000000..cd73aaf
--- /dev/null
+++ b/download/mumps-seq/Makefile-mumps-4.10.0.inc
@@ -0,0 +1,171 @@
+
+abs_top_builddir=@abs_top_builddir@
+DOWNLOADFF= $(abs_top_builddir)/download
+
+#
+#  This file is part of MUMPS 4.10.0, built on Tue May 10 12:56:32 UTC 2011
+#
+################################################################################
+#
+#   Makefile.inc.generic
+#
+#   This defines some parameters dependent on your platform; you should
+#   look for the approriate file in the directory ./Make.inc/ and copy it
+#   into a file called Makefile.inc. For example, from the MUMPS root
+#   directory, use 
+#   "cp Make.inc/Makefile.inc.generic ./Makefile.inc"
+#   (see the main README file for details)
+#
+#   If you do not find any suitable Makefile in Makefile.inc, use this file:
+#   "cp Make.inc/Makefile.inc.generic ./Makefile.inc" and modify it according
+#   to the comments given below. If you manage to build MUMPS on a new platform,
+#   and think that this could be useful to others, you may want to send us
+#   the corresponding Makefile.inc file.
+#
+################################################################################
+
+
+########################################################################
+#Begin orderings
+#
+# NOTE that PORD is distributed within MUMPS by default. If you would like to
+# use other orderings, you need to obtain the corresponding package and modify
+# the variables below accordingly.
+# For example, to have Metis available within MUMPS:
+#          1/ download Metis and compile it
+#          2/ uncomment (suppress # in first column) lines
+#             starting with LMETISDIR,  LMETIS
+#          3/ add -Dmetis in line ORDERINGSF
+#             ORDERINGSF  = -Dpord -Dmetis
+#          4/ Compile and install MUMPS
+#             make clean; make   (to clean up previous installation)
+#
+#          Metis/ParMetis and SCOTCH/PT-SCOTCH (ver 5.1 and later) orderings are now available for MUMPS.
+#
+
+SCOTCHDIR  = $(DOWNLOADFF)/
+ISCOTCH    = #-I$(SCOTCHDIR)/include/scotch
+# You have to choose one among the following two lines depending on
+# the type of analysis you want to perform. If you want to perform only
+# sequential analysis choose the first (remember to add -Dscotch in the ORDERINGSF
+# variable below); for both parallel and sequential analysis choose the second 
+# line (remember to add -Dptscotch in the ORDERINGSF variable below)
+
+#LSCOTCH    = -L$(SCOTCHDIR)/lib/scotch/ -lesmumps -lscotch -lscotcherr
+LSCOTCH    = #-L$(SCOTCHDIR)/lib -lptesmumps -lptscotch -lptscotcherr
+
+
+LPORDDIR = $(topdir)/PORD/lib/
+IPORD    = -I$(topdir)/PORD/include/
+LPORD    = -L$(LPORDDIR) -lpord
+
+LMETISDIR = $(DOWNLOADFF)
+#IMETIS    = # Metis doesn't need include files (Fortran interface avail.)
+
+# You have to choose one among the following two lines depending on
+# the type of analysis you want to perform. If you want to perform only
+# sequential analysis choose the first (remember to add -Dmetis in the ORDERINGSF
+# variable below); for both parallel and sequential analysis choose the second 
+# line (remember to add -Dparmetis in the ORDERINGSF variable below)
+
+LMETIS    = # -L$(LMETISDIR)/lib -lparmetis -lmetis
+
+# The following variables will be used in the compilation process.
+# Please note that -Dptscotch and -Dparmetis imply -Dscotch and -Dmetis respectively.
+#ORDERINGSF = -Dscotch -Dmetis -Dpord -Dptscotch -Dparmetis
+ORDERINGSF  = -Dpord
+ORDERINGSC  = $(ORDERINGSF)
+
+LORDERINGS = $(LMETIS) $(LPORD) $(LSCOTCH)
+IORDERINGSF = $(ISCOTCH)
+IORDERINGSC = $(IMETIS) $(IPORD) $(ISCOTCH)
+
+#End orderings
+########################################################################
+# DEFINE HERE SOME COMMON COMMANDS, THE COMPILER NAMES, ETC...
+
+# PLAT : use it to add a default suffix to the generated libraries
+PLAT    = FREEFEM-SEQ
+# Library extension, + C and Fortran "-o" option
+# may be different under Windows
+LIBEXT  = .a
+OUTC    = -o 
+OUTF    = -o 
+# RM : remove files
+RM      = /bin/rm -f
+# CC : C compiler
+CC      = @CC@
+# FC : Fortran 90 compiler
+FC      = @FC@ 
+# FL : Fortran linker
+FL      = @FC@ 
+# AR : Archive object in a library
+#      keep a space at the end if options have to be separated from lib name
+AR      =   @AR@ @ARFLAGS@ 
+# RANLIB : generate index of an archive file
+#   (optionnal use "RANLIB = echo" in case of problem)
+RANLIB  = @RANLIB@
+#RANLIB  = echo
+
+# SCALAP should define the SCALAPACK and  BLACS libraries.
+#SCALAPDIR = $(DOWNLOADFF)/lib/scalapack/
+#SCALAP    = $(FFBLASLIB) -L$(SCALAPDIR) -lscalapack -L$(DOWNLOADFF)/lib/blacs/ -lblacs_MPI-$(PLAT)-0 -lblacsF77init_MPI-$(PLAT)-0 -lblacsCinit_MPI-$(PLAT)-0
+
+# INCLUDE DIRECTORY FOR MPI
+#INCPAR  = $(FFMPIINCLUDE)
+
+# LIBRARIES USED BY THE PARALLEL VERSION OF MUMPS: $(SCALAP) and MPI
+LIBPAR  = #$(SCALAP) $(FFMPILIB)
+
+# The parallel version is not concerned by the next two lines.
+# They are related to the sequential library provided by MUMPS,
+# to use instead of ScaLAPACK and MPI.l
+INCSEQ  = -I$(DOWNLOADFF)/mumps-seq/MUMPS_4.10.0/libseq
+LIBSEQ  = -L$(DOWNLOADFF)//mumps-seq/MUMPS_4.10.0/libseq  -lmpiseq$(PLAT)
+
+# DEFINE HERE YOUR BLAS LIBRARY
+
+LIBBLAS =  @BLASLIBS@
+
+# DEFINE YOUR PTHREAD LIBRARY
+LIBOTHERS = @LIBSPTHREAD@ @FLIBS@ $(FFLIBOTHERSMUMPS) 
+LIBSPTHREAD = @LIBSPTHREAD@
+
+# FORTRAN/C COMPATIBILITY:
+#  Use:
+#    -DAdd_ if your Fortran compiler adds an underscore at the end
+#              of symbols,
+#     -DAdd__ if your Fortran compiler adds 2 underscores,
+#
+#     -DUPPER if your Fortran compiler uses uppercase symbols
+#
+#     leave empty if your Fortran compiler does not change the symbols.
+#
+
+
+CDEFS = @CFLAGSF77@
+
+#COMPILER OPTIONS
+OPTF    = -O @FFLAGS@ 
+OPTC    = -O -I. @CFLAGS@  
+OPTL    = -O @FFLAGS@ 
+
+
+# CHOOSE BETWEEN USING THE SEQUENTIAL OR THE PARALLEL VERSION.
+
+#Sequential:
+INCS = $(INCSEQ)
+LIBS = $(LIBSEQ)
+LIBSEQNEEDED = libseqneeded
+
+#Parallel:
+#INCS = $(INCPAR)
+#LIBS = $(LIBPAR)
+#LIBSEQNEEDED = libseqneeded
+
+WGET = @WGET@
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/mumps/MUMPS_4.10.0.patch b/download/mumps/MUMPS_4.10.0.patch
new file mode 100644
index 0000000..3daa254
--- /dev/null
+++ b/download/mumps/MUMPS_4.10.0.patch
@@ -0,0 +1,31 @@
+Only in MUMPS_4.10.0-new/: Makefile.inc
+Only in MUMPS_4.10.0-new//src: fmpi.h
+diff -ur MUMPS_4.10.0/src/mumps_orderings.h MUMPS_4.10.0-new//src/mumps_orderings.h
+--- MUMPS_4.10.0/src/mumps_orderings.h	2011-05-10 12:56:41 +0000
++++ MUMPS_4.10.0-new//src/mumps_orderings.h	2012-10-06 13:15:22 +0000
+@@ -68,6 +68,14 @@
+                  int *nv, int *ncmpa, int *totw );
+ #endif /*PORD*/
+ #if defined(scotch) || defined(ptscotch)
++#if defined(ptscotch)
++#define SCOTCH_PTSCOTCH
++#include "mpi.h"
++#include <stdio.h>
++#include "ptscotch.h"
++#else
++#include "scotch.h"
++#endif
+ int esmumps( const int n, const int iwlen, int * const pe, const int pfree,
+              int * const len, int * const iw, int * const nv, int * const elen,
+              int * const last);
+@@ -86,9 +94,6 @@
+               int * const        ncmpa );
+ #endif /*scotch or ptscotch*/
+ #if defined(ptscotch)
+-#include "mpi.h"
+-#include <stdio.h>
+-#include "ptscotch.h"
+ int mumps_dgraphinit( SCOTCH_Dgraph *, MPI_Fint *, MPI_Fint *);
+ #define MUMPS_DGRAPHINIT \
+   F_SYMBOL(dgraphinit,DGRAPHINIT)
+Only in MUMPS_4.10.0-new/: tag-tar
diff --git a/download/mumps/Makefile b/download/mumps/Makefile
new file mode 100644
index 0000000..4f9ec04
--- /dev/null
+++ b/download/mumps/Makefile
@@ -0,0 +1,95 @@
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# http://www.ljll.math.upmc.fr/lehyaric
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem make multipleauthors start=19/03/10 upmc
+
+include Makefile.inc
+
+all-local: mumps
+
+# Downloading and compiling mumps
+# -------------------------------
+
+DIRPKG=../pkg
+SRCDIR=MUMPS_$(VERSION)
+PACKAGE1=$(DIRPKG)/MUMPS_$(VERSION).tar.gz
+VERSION=4.10.0
+
+mumps:../lib/WHERE.mumps
+
+$(SRCDIR)/FAIT: $(SRCDIR)/tag-tar
+	cp Makefile.inc $(SRCDIR)
+#
+# ALH - 'd' and 'z' versions need to be made sequentially
+#
+	cd $(SRCDIR);make d
+	cd $(SRCDIR);make z
+	touch $@
+
+# ALH - WHERE was not built properly during a full compile from a clean source. This goal has been rewritten to solve
+# this issue.
+
+../lib/WHERE.mumps:install.done
+	echo mumps LD -L at DIR@/lib   -ldmumpsFREEFEM -lzmumpsFREEFEM  -lmumps_commonFREEFEM -lpordFREEFEM -lpthread  > $@
+	echo mumps INCLUDE -I at DIR@/include  >> $@
+
+install.done:$(SRCDIR)/FAIT
+	-mkdir -p ../include/libseq
+	cp $(SRCDIR)/include/*.h ../include/
+	cp $(SRCDIR)/libseq/*.h  ../include/libseq
+	-mkdir -p ../lib
+	cp $(SRCDIR)/lib/*.a ../lib/
+	cp $(SRCDIR)/libseq/libmpiseqFREEFEM.a ../lib/
+	touch $@
+
+FAIRE-$(VERSION):WHERE
+	touch FAIRE-$(VERSION)
+
+# ALH - "make d" and "make z" need to be done sequentially
+$(SRCDIR)/FAIT:$(SRCDIR)/tag-tar Makefile.inc
+	cp Makefile.inc $(SRCDIR)
+	cd $(SRCDIR) && $(MAKE) d
+	cd $(SRCDIR) && $(MAKE) z
+	touch $@
+
+Makefile.inc:../../config.status Makefile Makefile-mumps-$(VERSION).inc
+	../../config.status --file="Makefile.inc:Makefile-mumps-$(VERSION).inc"
+
+$(SRCDIR)/tag-tar:$(PACKAGE1)
+	tar xvzf $(PACKAGE1)
+	patch -d MUMPS_$(VERSION) -p 1 < MUMPS_$(VERSION).patch
+	touch $(SRCDIR)/tag-tar
+
+clean:clean-local
+clean-local:
+	-cd $(SRCDIR) &&  $(MAKE) clean -C $(SRCDIR) 
+	-rm Makefile.inc FAIRE* ../lib/WHERE.mumps
+	-rm -rf ../include/*mumps*
+	-rm -rf ../lib/lib*mumps* ../lib/libpord*.a ../lib/libmpiseq*.a
+	-rm -rf $(SRCDIR)
+#	-rm $(PACKAGE1)
+	-rm config.log *.done
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/mumps/Makefile-mumps-4.10.0.inc b/download/mumps/Makefile-mumps-4.10.0.inc
new file mode 100644
index 0000000..4cb240d
--- /dev/null
+++ b/download/mumps/Makefile-mumps-4.10.0.inc
@@ -0,0 +1,170 @@
+
+abs_top_builddir=@abs_top_builddir@
+DOWNLOADFF= $(abs_top_builddir)/download
+
+#
+#  This file is part of MUMPS 4.10.0, built on Tue May 10 12:56:32 UTC 2011
+#
+################################################################################
+#
+#   Makefile.inc.generic
+#
+#   This defines some parameters dependent on your platform; you should
+#   look for the approriate file in the directory ./Make.inc/ and copy it
+#   into a file called Makefile.inc. For example, from the MUMPS root
+#   directory, use 
+#   "cp Make.inc/Makefile.inc.generic ./Makefile.inc"
+#   (see the main README file for details)
+#
+#   If you do not find any suitable Makefile in Makefile.inc, use this file:
+#   "cp Make.inc/Makefile.inc.generic ./Makefile.inc" and modify it according
+#   to the comments given below. If you manage to build MUMPS on a new platform,
+#   and think that this could be useful to others, you may want to send us
+#   the corresponding Makefile.inc file.
+#
+################################################################################
+
+
+########################################################################
+#Begin orderings
+#
+# NOTE that PORD is distributed within MUMPS by default. If you would like to
+# use other orderings, you need to obtain the corresponding package and modify
+# the variables below accordingly.
+# For example, to have Metis available within MUMPS:
+#          1/ download Metis and compile it
+#          2/ uncomment (suppress # in first column) lines
+#             starting with LMETISDIR,  LMETIS
+#          3/ add -Dmetis in line ORDERINGSF
+#             ORDERINGSF  = -Dpord -Dmetis
+#          4/ Compile and install MUMPS
+#             make clean; make   (to clean up previous installation)
+#
+#          Metis/ParMetis and SCOTCH/PT-SCOTCH (ver 5.1 and later) orderings are now available for MUMPS.
+#
+
+SCOTCHDIR  = $(DOWNLOADFF)/
+ISCOTCH    = -I$(SCOTCHDIR)/include/scotch
+# You have to choose one among the following two lines depending on
+# the type of analysis you want to perform. If you want to perform only
+# sequential analysis choose the first (remember to add -Dscotch in the ORDERINGSF
+# variable below); for both parallel and sequential analysis choose the second 
+# line (remember to add -Dptscotch in the ORDERINGSF variable below)
+
+#LSCOTCH    = -L$(SCOTCHDIR)/lib/scotch/ -lesmumps -lscotch -lscotcherr
+LSCOTCH    = -L$(SCOTCHDIR)/lib -lptesmumps -lptscotch -lptscotcherr
+
+
+LPORDDIR = $(topdir)/PORD/lib/
+IPORD    = -I$(topdir)/PORD/include/
+LPORD    = -L$(LPORDDIR) -lpord
+
+LMETISDIR = $(DOWNLOADFF)
+#IMETIS    = # Metis doesn't need include files (Fortran interface avail.)
+
+# You have to choose one among the following two lines depending on
+# the type of analysis you want to perform. If you want to perform only
+# sequential analysis choose the first (remember to add -Dmetis in the ORDERINGSF
+# variable below); for both parallel and sequential analysis choose the second 
+# line (remember to add -Dparmetis in the ORDERINGSF variable below)
+
+LMETIS    = -L$(LMETISDIR)/lib -lparmetis -lmetis
+
+# The following variables will be used in the compilation process.
+# Please note that -Dptscotch and -Dparmetis imply -Dscotch and -Dmetis respectively.
+ORDERINGSF = -Dscotch -Dmetis -Dpord -Dptscotch -Dparmetis
+#ORDERINGSF  = -Dpord
+ORDERINGSC  = $(ORDERINGSF)
+
+LORDERINGS = $(LMETIS) $(LPORD) $(LSCOTCH)
+IORDERINGSF = $(ISCOTCH)
+IORDERINGSC = $(IMETIS) $(IPORD) $(ISCOTCH)
+
+#End orderings
+########################################################################
+# DEFINE HERE SOME COMMON COMMANDS, THE COMPILER NAMES, ETC...
+
+# PLAT : use it to add a default suffix to the generated libraries
+PLAT    = FREEFEM
+# Library extension, + C and Fortran "-o" option
+# may be different under Windows
+LIBEXT  = .a
+OUTC    = -o 
+OUTF    = -o 
+# RM : remove files
+RM      = /bin/rm -f
+# CC : C compiler
+CC      = @CC@
+# FC : Fortran 90 compiler
+FC      = @FC@ 
+# FL : Fortran linker
+FL      = @FC@ 
+# AR : Archive object in a library
+#      keep a space at the end if options have to be separated from lib name
+AR      =   @AR@ @ARFLAGS@ 
+# RANLIB : generate index of an archive file
+#   (optionnal use "RANLIB = echo" in case of problem)
+RANLIB  = @RANLIB@
+#RANLIB  = echo
+
+# SCALAP should define the SCALAPACK and  BLACS libraries.
+SCALAPDIR = $(DOWNLOADFF)/lib/scalapack/
+SCALAP    = $(FFBLASLIB) -L$(SCALAPDIR) -lscalapack -L$(DOWNLOADFF)/lib/blacs/ -lblacs_MPI-$(PLAT)-0 -lblacsF77init_MPI-$(PLAT)-0 -lblacsCinit_MPI-$(PLAT)-0
+
+# INCLUDE DIRECTORY FOR MPI
+INCPAR  = $(FFMPIINCLUDE)
+
+# LIBRARIES USED BY THE PARALLEL VERSION OF MUMPS: $(SCALAP) and MPI
+LIBPAR  = $(SCALAP) $(FFMPILIB)
+
+# The parallel version is not concerned by the next two lines.
+# They are related to the sequential library provided by MUMPS,
+# to use instead of ScaLAPACK and MPI.
+INCSEQ  = -I$(topdir)/libseq
+LIBSEQ  = -L$(topdir)/libseq -lmpiseq
+
+# DEFINE HERE YOUR BLAS LIBRARY
+
+LIBBLAS =  @BLASLIBS@
+
+# DEFINE YOUR PTHREAD LIBRARY
+LIBOTHERS = @LIBSPTHREAD@ @FLIBS@ $(FFLIBOTHERSMUMPS) 
+
+# FORTRAN/C COMPATIBILITY:
+#  Use:
+#    -DAdd_ if your Fortran compiler adds an underscore at the end
+#              of symbols,
+#     -DAdd__ if your Fortran compiler adds 2 underscores,
+#
+#     -DUPPER if your Fortran compiler uses uppercase symbols
+#
+#     leave empty if your Fortran compiler does not change the symbols.
+#
+
+
+CDEFS = @CFLAGSF77@
+
+#COMPILER OPTIONS
+
+# FFCS - 23/4/13 - -fno-range-check required on MinGW to compile with
+# Microsoft MPI. mpif.h contains INTEGER MPI_FLOAT_INT / PARAMETER
+# (MPI_FLOAT_INT=z'8c000000') which requires this.
+
+OPTF    = -O @FFLAGS@ @MPI_INCLUDE@ -fno-range-check
+OPTC    = -O -I. @CFLAGS@  @MPI_INCLUDE@
+OPTL    = -O @FFLAGS@ @MPI_LIBFC@ 
+
+
+# CHOOSE BETWEEN USING THE SEQUENTIAL OR THE PARALLEL VERSION.
+
+#Sequential:
+#INCS = $(INCSEQ)
+#LIBS = $(LIBSEQ)
+#LIBSEQNEEDED = libseqneeded
+
+#Parallel:
+INCS = $(INCPAR)
+LIBS = $(LIBPAR)
+LIBSEQNEEDED = libseqneeded
+
+WGET = @WGET@
\ No newline at end of file
diff --git a/download/nlopt/Make.inc b/download/nlopt/Make.inc
new file mode 100644
index 0000000..c577bf5
--- /dev/null
+++ b/download/nlopt/Make.inc
@@ -0,0 +1,6 @@
+FFDOWNLOAD=@abs_builddir@/download
+CC=@CC@
+CXX=@CXX@
+WGET=@WGET@
+CXXFLAGS=@CXXFLAGS@
+CFLAGS=@CFLAGS@
\ No newline at end of file
diff --git a/download/nlopt/Makefile b/download/nlopt/Makefile
new file mode 100644
index 0000000..465f331
--- /dev/null
+++ b/download/nlopt/Makefile
@@ -0,0 +1,48 @@
+URL="http://ab-initio.mit.edu/nlopt/nlopt-2.2.4.tar.gz"
+SRCDIR=nlopt-2.2.4
+TARGZ=../pkg/$(SRCDIR).tar.gz
+-include Make.defs
+
+all: FAIRE
+
+FAIRE: ../pkg $(SRCDIR)/FAIT 
+
+$(SRCDIR)/FAIT: $(TARGZ)
+	tar zxvf $(TARGZ)
+#
+#	FFCS - 30/11/11 - "--disable-dependency-tracking": dependencies pose problem on mixed Cygwin/MinGW setups
+#	because of slashes and backslashes
+#
+# 	FFCS - 22/10/12 - Fred - "--without-octave": patch for one machine that has octave installed on it: building of
+#	nlopt fails because it wants to install the octave components.  Not a bad idea in general but probably not when
+#	building ffcs.
+#
+	cd $(SRCDIR) && ./configure --disable-dependency-tracking --with-cxx --prefix="$(FFDOWNLOAD)" CXX="$(CXX)"	\
+	CXXFLAGS="$(CXXFLAGS)" CC="$(CC)" CFLAGS="$(CFLAGS)" CP="$(CXXCPP)" "--without-threadlocal" "--without-octave"
+#
+#	FFCS - 30/11/11 - we need to know when the building process breaks
+#
+	cd $(SRCDIR) && $(MAKE) install
+	touch $(SRCDIR)/FAIT
+	$(MAKE) WHERE
+../pkg:
+	mkdir $@
+
+$(TARGZ):
+	../getall -o NLopt -a
+
+clean-local:
+	rm -rf $(SRCDIR) Make.defs 
+	rm -f ../lib/libnlopt_cxx*  ../lib/WHERE.nlopt 
+	rm -f ../include/nlopt*
+
+clean:clean-local
+
+WHERE: 
+	-if [ -f $(SRCDIR)/FAIT ] ; then \
+	echo nlopt LD -L at DIR@/lib -lnlopt_cxx  >../lib/WHERE.nlopt ;\
+	echo nlopt INCLUDE -I at DIR@/include >> ../lib/WHERE.nlopt ;\
+	fi
+
+Make.defs: ../../config.status	Makefile Make.inc
+	../../config.status  --file="Make.defs:Make.inc"
diff --git a/download/parmetis/Makefile-parmetis.in b/download/parmetis/Makefile-parmetis.in
new file mode 100644
index 0000000..673fba7
--- /dev/null
+++ b/download/parmetis/Makefile-parmetis.in
@@ -0,0 +1,25 @@
+
+# Which compiler to use
+CC = @MPICC@
+LD=  @MPICC@
+# What optimization level to use
+OPTFLAGS = @CFLAGS@ 
+
+# What options to be used by the compiler
+# FFCS - add path to mpi.h (required for MacOS 10.8 + MacPorts OpenMPI)
+COPTIONS =  -DHAVE_CONFIG_H -I. -I../../../.. -I @MPI_INC_DIR@ @FFMETIS_CFLAGS@ #-D_MSC_VER
+
+# What options to be used by the loader
+LDOPTIONS = @LDFLAGS@ 
+XTRALIBS= @MPI_LIBC@
+
+# What archiving to use
+AR =  @AR@ @ARFLAGS@
+
+# What to use for indexing the archive
+RANLIB = @RANLIB@
+#RANLIB = ar -ts
+#RANLIB = 
+WGET = @WGET@
+
+
diff --git a/download/parmetis/makefile b/download/parmetis/makefile
new file mode 100755
index 0000000..da56206
--- /dev/null
+++ b/download/parmetis/makefile
@@ -0,0 +1,90 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include Makefile.in
+
+all-local: parmetis
+
+# Downloading and compiling Tetgen
+# ------------------------------
+# http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/parmetis-4.0.tar.gz
+# Parmetis information
+DIRPKG=../pkg
+SRCDIR=ParMetis-$(parmetis_VERSION)
+PACKAGE=$(DIRPKG)/ParMetis-$(parmetis_VERSION).tar.gz
+SERVER=http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/OLD
+
+INSTALL=../..
+parmetis_VERSION=3.1.1
+
+parmetis: WHERE.done
+
+compile.done:$(SRCDIR)/tags Makefile.in
+	-mkdir -p "../lib/parmetis"
+	-mkdir -p "../include/parmetis"
+	cp Makefile.in $(SRCDIR)
+# 	FFCS - we need to know when errors occur
+	cd $(SRCDIR)/METISLib && $(MAKE) 
+	cd $(SRCDIR)/ParMETISLib && $(MAKE) 
+	touch $@
+
+# FFCS - simpler makefile
+install.done:compile.done
+#	cp $(SRCDIR)/libparmetis.a $(SRCDIR)/$(INSTALL)/lib
+#	cp $(SRCDIR)/libmetis.a $(SRCDIR)/$(INSTALL)/lib
+	cp $(SRCDIR)/parmetis.h ../include/parmetis
+	cp $(SRCDIR)/METISLib/*.h ../include/parmetis
+	sed  's;../parmetis.h;parmetis.h;' <$(SRCDIR)/METISLib/metis.h >../include/parmetis/metis.h
+#
+#	FFCS - 23/5/12 - cannot keep name libmetis.a because it is identical to the library created by
+#	[[file:../metis/Makefile]] and library path mechanisms at link time pick one for the other on MinGW.
+	mv $(SRCDIR)/$(INSTALL)/lib/parmetis/libmetis.a $(SRCDIR)/$(INSTALL)/lib/parmetis/libmetispar.a
+#
+	-cd $(SRCDIR)/Programs && make 
+	touch $@
+
+# FFCS - simpler makefile
+WHERE.done:install.done
+	echo parmetis LD -L at DIR@/lib/parmetis -lparmetis -lmetispar  >$(SRCDIR)/$(INSTALL)/lib/WHERE.parmetis ;
+	echo parmetis INCLUDE -I at DIR@/include/parmetis   >> $(SRCDIR)/$(INSTALL)/lib/WHERE.parmetis ;
+	touch $@
+
+Makefile.in: ../../config.status Makefile-parmetis.in
+	../../config.status  --file="Makefile.in:Makefile-parmetis.in"
+
+
+
+$(SRCDIR)/tags: $(PACKAGE)
+	tar xvzf $(PACKAGE)
+	patch -p0  <parmetis-3.1.1.patch
+	mv  $(SRCDIR)/Programs/Makefile $(SRCDIR)/Programs/Makefile-orig
+	sed -e 's;BINDIR = .*$$;BINDIR = ../$(INSTALL)/bin;' \
+            -e 's;../libparmetis.a;../$(INSTALL)/lib/parmetis/libparmetis.a;' \
+            -e 's;../libmetis.a;../$(INSTALL)/lib/parmetis/libmetis.a;' \
+            -e 's;-L[.][.];-L../$(INSTALL)/lib/parmetis;' \
+          <$(SRCDIR)/Programs/Makefile-orig \
+          >$(SRCDIR)/Programs/Makefile
+	mv $(SRCDIR)/ParMETISLib/Makefile $(SRCDIR)/ParMETISLib/Makefile-orig
+	sed   -e 's;../libparmetis.a;../$(INSTALL)/lib/parmetis/libparmetis.a;' \
+	      -e 's;../libmetis.a;../$(INSTALL)/lib/parmetis/libmetis.a;' \
+          <$(SRCDIR)/ParMETISLib/Makefile-orig \
+          >$(SRCDIR)/ParMETISLib/Makefile
+	mv $(SRCDIR)/METISLib/Makefile $(SRCDIR)/METISLib/Makefile-orig
+	sed   -e 's;../libparmetis.a;../$(INSTALL)/lib/parmetis/libparmetis.a;' \
+	      -e 's;../libmetis.a;../$(INSTALL)/lib/parmetis/libmetis.a;' \
+          <$(SRCDIR)/METISLib/Makefile-orig \
+          >$(SRCDIR)/METISLib/Makefile
+	touch $(SRCDIR)/tags
+
+$(PACKAGE):
+	../getall -o ParMETIS -a
+
+# FFCS - 23/5/12 - corrected bug in removing .a from ../lib
+clean:
+	-cd $(SRCDIR) && $(MAKE) realclean  -C  $(SRCDIR)
+	-rm Makefile.in $(SRCDIR)/tags
+	-rm -rf ../lib/parmetis
+	-rm -rf ../include/parmetis
+	-rm -rf ../include/metis
+	-rm -rf $(SRCDIR)
+	-rm *.done
diff --git a/download/parmetis/parmetis-3.1.1.patch b/download/parmetis/parmetis-3.1.1.patch
new file mode 100644
index 0000000..6fbd5c5
--- /dev/null
+++ b/download/parmetis/parmetis-3.1.1.patch
@@ -0,0 +1,21 @@
+--- ParMetis-3.1.1/ParMETISLib/stdheaders.h	2008-09-16 23:39:19.000000000 +0200
++++ ParMetis-3.1.1/ParMETISLib/stdheaders.h-ok	2010-03-30 11:51:17.000000000 +0200
+@@ -11,10 +11,16 @@
+  * $Id$
+  */
+ 
+-
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#ifdef HAVE_MALLOC_H
++#include <malloc.h>
++#endif
++#else
++#include <malloc.h>
++#endif
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include <malloc.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <math.h>
diff --git a/download/parms/Makefile b/download/parms/Makefile
new file mode 100644
index 0000000..4efa7f0
--- /dev/null
+++ b/download/parms/Makefile
@@ -0,0 +1,67 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include Makefile.in
+
+all-local: parms
+
+# Downloading and compiling parms
+# -------------------------------
+# http://www-users.cs.umn.edu/~saad/software/pARMS/pARMS_2.2.php
+# Parms information
+DIRPKG=../pkg
+SRCDIR=pARMS_$(parms_VERSION)
+PACKAGE=$(DIRPKG)/pARMS_$(parms_VERSION).tar.gz
+SERVER=http://www-users.cs.umn.edu/~saad/software/pARMS/pARMS_2.2.php
+INSTALL=../..
+parms_VERSION=2.2
+
+parms: FAIRE
+
+# FFCS: more dependencies for parallel builds
+$(SRCDIR)/FAIT:$(SRCDIR)
+	$(MAKE) $(SRCDIR)/$(INSTALL)  WHERE
+	touch $(SRCDIR)/FAIT
+install:$(SRCDIR)/$(INSTALL)
+
+FAIRE: $(SRCDIR)/FAIT
+
+Makefile.in: ../../config.status	Makefile makefile-parms.in
+	../../config.status  --file="Makefile.in:makefile-parms.in"
+	case `uname` in *CYGWIN*)  cp Makefile.in Makefile.inn; sed "s/COPTIONS =/COPTIONS = -D__VC__/" <Makefile.inn > Makefile.in; rm Makefile.inn ;; esac 
+
+$(SRCDIR)/$(INSTALL): $(SRCDIR)
+	cp Makefile.in $(SRCDIR)/makefile.in
+	cd $(SRCDIR); $(MAKE) ./LIB/libparms$(DBG).a
+	mkdir -p ../include/parms
+	cp $(SRCDIR)/INCLUDE/*.h ../include/parms/
+	cp $(SRCDIR)/LIB/*.a ../lib/
+
+$(SRCDIR): $(PACKAGE)
+	tar xvzf $(PACKAGE)
+	touch $(SRCDIR)
+
+$(PACKAGE):
+	../getall -o pARMS -a
+
+clean:
+	-make cleanall -C $(SRCDIR)/src
+	-rm Makefile.in ../lib/WHERE.parms
+	-rm ../lib/libparms.*
+	-rm -rf ../include/parms
+	-rm -rf $(SRCDIR)
+#
+#	FFCS - make sure that all directories are cleaned. This is especially important under Windows because there is no
+#	compilation dependencies control there (see
+#	[[file:c:/cygwin/home/alh/ffcs/dist/configure.ac::dependency_tracking]])
+#
+	-rm -rf pARMS_*
+	-rm config.log
+#	-rm $(PACKAGE)
+
+WHERE:
+	echo parms LD -L at DIR@/lib -lparms$(DBG)  >../lib/WHERE.parms
+	echo parms INCLUDE -I at DIR@/include/parms >> ../lib/WHERE.parms
+
+.PHONY:$(SRCDIR)/$(INSTALL)
+
diff --git a/download/parms/makefile-parms.in b/download/parms/makefile-parms.in
new file mode 100644
index 0000000..3f99887
--- /dev/null
+++ b/download/parms/makefile-parms.in
@@ -0,0 +1,58 @@
+abs_top_builddir = @abs_top_builddir@
+WGET=@WGET@
+
+# FFCS - let "make clean" work even if include file is not found
+-include $(abs_top_builddir)/download/headers-sparsesolver.inc
+
+# path for this directory 
+PARMS_ROOT	= $(abs_top_builddir)/download/parms/pARMS_2.2
+
+# name used for architecture 
+ARCH	=	LINUX   
+DARCH 	=	-D$(ARCH)
+
+# variable to declare optimization level
+# use '-g' to create libparms for debugging purposes
+DBG     =      -O3
+
+# to make pARMS name compatible with other linear algebra software
+# such as PETSc, assign DCHNAME as: DCHNAME = -DPETSC
+DCHNAME = 
+
+# archive command
+AR	= @AR@ #ar
+ARFLAGS	= @ARFLAGS@ #cr
+#====================================================================
+
+#====================================================================
+# Options for a generic LINUX configuration 
+#################################
+ CC	=	@MPICC@
+
+ # FFCS - "-I MPI_INC_DIR" required on MacOS 10.8 MacPorts+OpenMPI
+ CFLAGS	= $(DBG) $(DARCH) $(DCHNAME)  @CFLAGS@ -I @MPI_INC_DIR@
+
+ INCLUDE_METIS =     #-I
+ METIS_HOME  =       #-L/Users/morice/work/ParMetis-3.1.1/ -lparmetis -lmetis 
+
+# fortran compiler / linker 
+ FC	=	@MPIFC@
+
+# ALH - add no-range-check for Windows (hexadecimal parameter constants like
+# [[file:c:/cygwin/home/alh/ffcs/rel/mingw/mpif.h::PARAMETER MPI_SHORT_INT z 8c000003]]
+# are rejected without this. See [[file:../../configure.ac::NO_RANGE_CHECK]]
+
+ FFLAGS	= $(DBG)  $(DARCH)  @FFLAGS@ @NO_RANGE_CHECK@
+
+# the directory of MPI library. for example -L/usr/local/mpich/lib
+ LFLAGS_MPI 	= $(FFMPIINCLUDE) 
+# the mpi library
+ LIBS_MPI	= $(FFMPILIB)
+# the directory of BLAS
+ LFLAGS_BLAS	= $(FFBLASINCLUDE)
+# the BLAS library
+ LIBS_BLAS	= $(FFBLASLIB) @LIBSPTHREAD@  
+#LINKER
+ LINKER	=	$(FC)
+#LINK OPTION
+ LINK_OPT	=   #-nofor_main pour ifort compiler
diff --git a/download/pastix/Makefile b/download/pastix/Makefile
new file mode 100644
index 0000000..5ac87c3
--- /dev/null
+++ b/download/pastix/Makefile
@@ -0,0 +1,188 @@
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# http://www.ljll.math.upmc.fr/lehyaric
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem make multipleauthors start=19/03/10 upmc
+
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include config.in
+
+all-local: pastix
+
+# Downloading and compiling pastix
+# ------------------------------
+DIRPKG   = ../pkg
+SRCDIR   = pastix_release_$(VERSION)
+PACKAGE1 = $(DIRPKG)/pastix_release_$(VERSION).tar.bz2
+SERVER   = https://gforge.inria.fr/frs/download.php/21873/
+INSTALL  = ../..
+VERSION  = 2200
+
+VERSIONTYPE=$(VERSIONINT)$(VERSIONPRC)$(VERSIONFLT)
+VERSIONTYPECOMPLEX=$(VERSIONINT)_complex
+VERSIONNAME=$(VERSIONBIT)$(VERSIONMPI)$(VERSIONSMP)$(VERSIONBUB)$(VERSIONTYPE)$(VERSIONORD)_$(HOSTARCH)
+PASTIX_DIR = $(abs_top_builddir)/download/pastix/$(SRCDIR)/install
+
+ifneq (,$(findstring libtool,$(ARPROG)))
+	OBJLIBTOOL = $(SRCDIR)/src/sopalin/obj/$(HOSTARCH)/*.o $(SRCDIR)/src/blend/obj/$(HOSTARCH)/*.o $(SRCDIR)/src/fax/obj/$(HOSTARCH)/*.o $(SRCDIR)/src/kass/obj/$(HOSTARCH)/*.o $(SRCDIR)/src/order/obj/$(HOSTARCH)/*.o $(SRCDIR)/src/symbol/obj/$(HOSTARCH)/*.o $(SRCDIR)/src/common/obj/$(HOSTARCH)/*.o
+else
+	OBJLIBTOOL = 
+endif
+
+pastix: FAIRE
+
+
+# FFCS - parallel make rules
+WHERE: install
+	echo double_pastix LD -L at DIR@/lib/pastix/double   -lpastix   >$(SRCDIR)/$(INSTALL)/lib/WHERE.pastix ;
+	echo double_pastix INCLUDE -I at DIR@/include/pastix/double >> $(SRCDIR)/$(INSTALL)/lib/WHERE.pastix ;
+	echo complex_pastix LD -L at DIR@/lib/pastix/complex   -lpastix   >>$(SRCDIR)/$(INSTALL)/lib/WHERE.pastix ;
+	echo complex_pastix INCLUDE -I at DIR@/include/pastix/complex >> $(SRCDIR)/$(INSTALL)/lib/WHERE.pastix ;
+
+FAIRE:$(SRCDIR)/FAIT 
+	$(MAKE) WHERE
+	touch FAIRE
+
+config.in: ../Makefile ../../config.status	Makefile
+	../../config.status  --file="config.in:config-pastix-real.in"
+	../../config.status  --file="config-complex.in:config-pastix-complex.in"
+
+install:$(SRCDIR)/FAIT
+
+$(SRCDIR)/FAIT: $(SRCDIR) 
+	cp config.in $(SRCDIR)/src/
+#
+#	FFCS - 16/1/13 - this crashes in parallel
+#
+	cd $(SRCDIR)/src; $(MAKE) -j1 expor
+	#ifndef (,$(OBJLIBTOOL)) # redefinition of "cd $(SRCDIR)/src; $(MAKE) install" for libtool
+	rm -f $(SRCDIR)/install/pastix*.h $(SRCDIR)/install/pastix*.in $(SRCDIR)/install/murge*.inc
+	$(abs_top_builddir)/download/pastix/$(SRCDIR)/src/utils/bin/${HOSTARCH}/genheader $(PASTIX_DIR)/pastix$(VERSIONTYPE).h $(PASTIX_DIR)/pastix_fortran$(VERSIONTYPE).h \
+	$(PASTIX_DIR)/murge$(VERSIONTYPE).inc $(SRCDIR)/src/murge/include/murge.h $(SRCDIR)/src/murge/scripts/genfort.pl
+	cat $(SRCDIR)/src/../bin/$(HOSTARCH)/pastix.h         >> $(PASTIX_DIR)/pastix$(VERSIONTYPE).h
+	cat $(SRCDIR)/src/common/src/api.h                    >> $(PASTIX_DIR)/pastix$(VERSIONTYPE).h
+	cat $(SRCDIR)/src/../bin/$(HOSTARCH)/pastix_fortran.inc >> $(PASTIX_DIR)/murge$(VERSIONTYPE).inc
+	ln -sf $(PASTIX_DIR)/pastix$(VERSIONTYPE).h         	$(PASTIX_DIR)/pastix.h
+	ln -sf $(PASTIX_DIR)/pastix_fortran$(VERSIONTYPE).h 	$(PASTIX_DIR)/pastix_fortran.h
+	ln -sf $(PASTIX_DIR)/murge$(VERSIONTYPE).inc	 	$(PASTIX_DIR)/murge.inc
+	cp  $(SRCDIR)/src/sopalin/src/csc_utils.h                     $(PASTIX_DIR)/csc_utils$(VERSIONTYPE).h
+	ln -fs $(PASTIX_DIR)/csc_utils$(VERSIONTYPE).h $(PASTIX_DIR)/csc_utils.h
+	cp  $(SRCDIR)/src/sopalin/src/cscd_utils.h                    $(PASTIX_DIR)/cscd_utils${VERSIONTYPE}.h
+	ln -fs $(PASTIX_DIR)/cscd_utils$(VERSIONTYPE).h $(PASTIX_DIR)/cscd_utils.h
+	cp  $(SRCDIR)/src/common/src/nompi.h                          $(PASTIX_DIR)/pastix_nompi.h
+	cp  $(SRCDIR)/src/murge/include/murge.h 			 $(PASTIX_DIR)/murge.h
+	$(ARPROG) $(ARFLAGS) $(SRCDIR)/install/libpastix$(VERSIONNAME).a $(OBJLIBTOOL)
+	ranlib $(SRCDIR)/install/libpastix$(VERSIONNAME).a
+	ln -sf $(PASTIX_DIR)/libpastix$(VERSIONNAME).a $(PASTIX_DIR)/libpastix.a
+	cp $(PASTIX_DIR)/../bin/$(HOSTARCH)/libpastix_murge.a $(PASTIX_DIR)/libpastix_murge$(VERSIONNAME).a
+	ln -sf $(PASTIX_DIR)/libpastix_murge$(VERSIONNAME).a $(PASTIX_DIR)/libpastix_murge.a
+	#else
+	#cd $(SRCDIR)/src; $(MAKE) install
+	#endif 
+	mkdir -p $(SRCDIR)/$(INSTALL)/include/pastix/double
+	cp $(SRCDIR)/install/*.h $(SRCDIR)/$(INSTALL)/include/pastix/double/
+	mkdir -p $(SRCDIR)/$(INSTALL)/lib/pastix/double
+	cp $(SRCDIR)/install/*.a $(SRCDIR)/$(INSTALL)/lib/pastix/double/
+	cd $(SRCDIR)/src/ &&  $(MAKE) clean 
+#
+# complex version
+#
+	cp config-complex.in $(SRCDIR)/src/config.in	
+#
+#	FFCS - 16/1/13 - this crashes in parallel
+#
+	cd $(SRCDIR)/src/;$(MAKE) -j1 expor
+#ifdef ($(OBJLIBTOOL))
+	rm -f $(SRCDIR)/install/pastix*.h $(SRCDIR)/install/pastix*.in $(SRCDIR)/install/murge*.inc
+	$(abs_top_builddir)/download/pastix/$(SRCDIR)/src/utils/bin/${HOSTARCH}/genheader $(PASTIX_DIR)/pastix$(VERSIONTYPECOMPLEX).h $(PASTIX_DIR)/pastix_fortran$(VERSIONTYPECOMPLEX).h \
+	$(PASTIX_DIR)/murge$(VERSIONTYPECOMPLEX).inc $(SRDIR)/src/murge/include/murge.h $(SRDIR)/src/murge/scripts/genfort.pl
+	cat $(SRCDIR)/src/../bin/$(HOSTARCH)/pastix.h         >> $(PASTIX_DIR)/pastix$(VERSIONTYPECOMPLEX).h
+	cat $(SRCDIR)/src/common/src/api.h                    >> $(PASTIX_DIR)/pastix$(VERSIONTYPECOMPLEX).h
+	cat $(SRCDIR)/src/../bin/$(HOSTARCH)/pastix_fortran.inc >> $(PASTIX_DIR)/murge$(VERSIONTYPECOMPLEX).inc
+	ln -sf $(PASTIX_DIR)/pastix$(VERSIONTYPECOMPLEX).h         	$(PASTIX_DIR)/pastix.h
+	ln -sf $(PASTIX_DIR)/pastix_fortran$(VERSIONTYPECOMPLEX).h 	$(PASTIX_DIR)/pastix_fortran.h
+	ln -sf $(PASTIX_DIR)/murge$(VERSIONTYPECOMPLEX).inc	 	$(PASTIX_DIR)/murge.inc
+	cp  $(SRCDIR)/src/sopalin/src/csc_utils.h                     $(PASTIX_DIR)/csc_utils$(VERSIONTYPECOMPLEX).h
+	ln -fs $(PASTIX_DIR)/csc_utils$(VERSIONTYPECOMPLEX).h $(PASTIX_DIR)/csc_utils.h
+	cp  $(SRCDIR)/src/sopalin/src/cscd_utils.h                    $(PASTIX_DIR)/cscd_utils${VERSIONTYPECOMPLEX}.h
+	ln -fs $(PASTIX_DIR)/cscd_utils$(VERSIONTYPECOMPLEX).h $(PASTIX_DIR)/cscd_utils.h
+	cp  $(SRCDIR)/src/common/src/nompi.h                          $(PASTIX_DIR)/pastix_nompi.h
+	cp  $(SRCDIR)/src/murge/include/murge.h 			 $(PASTIX_DIR)/murge.h
+	$(ARPROG) $(ARFLAGS) $(SRCDIR)/install/libpastix$(VERSIONNAME).a $(OBJLIBTOOL)
+	ranlib $(SRCDIR)/install/libpastix$(VERSIONNAME).a
+	ln -sf $(PASTIX_DIR)/libpastix$(VERSIONNAME).a $(PASTIX_DIR)/libpastix.a
+	cp $(PASTIX_DIR)/../bin/$(HOSTARCH)/libpastix_murge.a $(PASTIX_DIR)/libpastix_murge$(VERSIONNAME).a
+	ln -sf $(PASTIX_DIR)/libpastix_murge$(VERSIONNAME).a $(PASTIX_DIR)/libpastix_murge.a
+#else
+	#cd $(SRCDIR)/src/ && $(MAKE) install -C $(SRCDIR)/src
+#endif
+	mkdir -p $(SRCDIR)/$(INSTALL)/include/pastix/complex
+	cp $(SRCDIR)/install/*.h $(SRCDIR)/$(INSTALL)/include/pastix/complex/
+	mkdir -p $(SRCDIR)/$(INSTALL)/lib/pastix/complex
+	cp $(SRCDIR)/install/*.a $(SRCDIR)/$(INSTALL)/lib/pastix/complex/
+	(cd $(SRCDIR)/$(INSTALL)/include/pastix/complex/; patch pastix_long_complex.h)   <patch-pastix_long_complex.h
+	(cd $(SRCDIR)/$(INSTALL)/include/pastix/complex/; patch pastix.h) <patch-pastix_long_complex.h
+	touch $(SRCDIR)/FAIT
+
+
+
+$(SRCDIR): $(PACKAGE1)
+	tar xvfj $(PACKAGE1)
+#
+# 31/7/13 - ALH - patch from Fred to avoid picking up a locally installed version of Umfpack when FF compiles its own on
+# Slackware64-14.0. For more information see FFCS comments from Fred on
+# [[http://www.ljll.math.upmc.fr//~lehyaric/ffcs/news/20130528-1139.php]] (dated 30/7/13)
+#
+	patch -p0 < all_macros.diff
+#
+	cd $(SRCDIR)/src/blend/src/; patch -p2 < ../../../../pastix_release_2200-blend.patch
+	touch $(SRCDIR)
+
+$(PACKAGE1):
+	../getall -o PaStiX -a
+
+# FFCS: avoid loops when SRCDIR does not exist
+clean-local:
+	-cd $(SRCDIR)/src &&  $(MAKE) clean 
+
+clean: clean-local
+	-rm config.in FAIRE 
+	-rm $(SRCDIR)/FAIT
+	-rm -rf $(SRCDIR)/$(INSTALL)/include/pastix/double
+	-rm -rf $(SRCDIR)/$(INSTALL)/lib/pastix/double
+	-rm -rf $(SRCDIR)/$(INSTALL)/include/pastix/complex
+	-rm -rf $(SRCDIR)/$(INSTALL)/lib/pastix/complex
+	-rm -rf $(SRCDIR)
+#
+# FFCS - also force reconfiguration
+#
+	-rm config.in config-complex.in config.log
+	-rm config.log
+#	-rm $(PACKAGE1)
+
+.PHONY:$(SRCDIR)/$(INSTALL)
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/pastix/all_macros.diff b/download/pastix/all_macros.diff
new file mode 100644
index 0000000..ede8482
--- /dev/null
+++ b/download/pastix/all_macros.diff
@@ -0,0 +1,26 @@
+
+--- pastix_release_2200/src/all_macros 2009-02-19 07:33:00.000000000 -0600
++++ pastix_release_2200/src/all_macros.new 2013-03-24 10:34:37.026406767 -0500
+@@ -11,7 +11,7 @@
+ OBJ		= $(OBJEXT)
+ 
+ AR		= $(ARPROG)
+-CCINC           = -I. -I$(DSTDIR) -I$(INSDIR)
++CCINC           = -I$(DSTDIR) -I$(INSDIR)
+ CAT		= cat
+ CP		= cp
+ MKDIR		= mkdir
+@@ -21,10 +21,10 @@
+ TOUCH		= touch
+ TAIL		= tail
+ HEAD		= head
+-VERSION         = `../../myversion.sh`
++VERSION         = ../../myversion.sh
+ 
+ COMMONPASTIX_H	= 	$(INSDIR)/common_pastix.h	\
+ 			$(INSDIR)/api.h			\
+ 			$(INSDIR)/debug.h		\
+ 			$(INSDIR)/errors.h		\
+-			$(INSDIR)/redefine_functions.h
+\ No newline at end of file
++			$(INSDIR)/redefine_functions.h
diff --git a/download/pastix/config-pastix-complex.in b/download/pastix/config-pastix-complex.in
new file mode 100644
index 0000000..f2c1a8f
--- /dev/null
+++ b/download/pastix/config-pastix-complex.in
@@ -0,0 +1,185 @@
+abs_top_builddir=@abs_top_builddir@
+include $(abs_top_builddir)/download/headers-sparsesolver.inc
+HOSTARCH    = @PASTIX_HOSTARCH@#i686_mac
+VERSIONBIT  = _ at SIZEOF_PTRINBIT@bit
+EXEEXT      =
+OBJEXT      = .o
+LIBEXT      = .a
+CCPROG      = @CC@ -Wall -DX_ARCH$(HOSTARCH)
+CFPROG      = @F77@ 
+CF90PROG    = @F77@ -ffree-form
+MCFPROG     = @MPIFC@ 
+CF90CCPOPT  = -ffree-form -x f95-cpp-input #avant
+# Compilation options for optimization (make expor)
+CCFOPT      = -O3 @CFLAGS@
+# Compilation options for debug (make | make debug)
+CCFDEB      = -g3
+
+LKFOPT      =
+MKPROG      = make 
+
+# FFCS - add MPI_INCLUDE because FF cannot use the defaut openmpi scripts on MacOS (see
+# [[file:../../../../configure.ac::mpicc_on_macos]])
+
+MPCCPROG    = @MPICC@ -Wall -DX_ARCH$(HOSTARCH) @MPI_INCLUDE@
+ARFLAGS     = @ARFLAGS@  # ruv
+ARPROG      = @AR@       # ar
+EXTRALIB    = @FLIBS@ -lm -lsupc++
+
+VERSIONMPI  = _mpi
+VERSIONSMP  = _smp
+VERSIONBUB  = _nobubble
+VERSIONINT  = _int
+VERSIONPRC  = _simple
+VERSIONFLT  = _real
+VERSIONORD  = _scotch
+
+###################################################################
+#                          INTEGER TYPE                           #
+###################################################################
+# uncomment the following lines for integer type support (Only 1)
+
+VERSIONINT  = $(FFVERSIONINT)#_long
+CCTYPES     = $(FFCTYPESINT)#-DFORCE_LONG -DLONG
+#---------------------------
+#VERSIONINT  = _int32
+#CCTYPES     = -DFORCE_INT32 -DINTSIZE32
+#---------------------------
+#VERSIONINT  = _int64
+#CCTYPES     = -DFORCE_INT64 -DINTSSIZE64
+
+###################################################################
+#                           FLOAT TYPE                            #
+###################################################################
+
+# uncomment the following lines for double precision support
+#VERSIONPRC  = _double
+CCTYPES    := $(CCTYPES) -DFORCE_DOUBLE -DPREC_DOUBLE
+
+# uncomment the following lines for float=complex support
+VERSIONFLT  = _complex
+CCTYPES    := $(CCTYPES) -DFORCE_COMPLEX -DTYPE_COMPLEX -DPREC_DOUBLE
+
+
+###################################################################
+#                          Mpi/THREADS                            #
+###################################################################
+
+# uncomment the following lines for sequential (NOMPI) version
+#VERSIONMPI  = _nompi
+#CCTYPES    := $(CCTYPES) -DFORCE_NOMPI
+#MPCCPROG    = $(CCPROG)
+#MCFPROG     = $(CFPROG)
+
+# uncomment the following lines for non-threaded (NOSMP) version
+#VERSIONSMP  = _nosmp
+#CCTYPES    := $(CCTYPES) -DFORCE_NOSMP
+
+# Uncomment the following line to enable a progression thread
+#CCPASTIX   := $(CCPASTIX) -DTHREAD_COMM
+
+# Uncomment the following line if your MPI doesn't support MPI_THREAD_MULTIPLE level
+#CCPASTIX   := $(CCPASTIX) -DPASTIX_FUNNELED
+
+# Uncomment the following line if your MPI doesn't support MPI_Datatype correctly
+#CCPASTIX   := $(CCPASTIX) -DNO_MPI_TYPE
+
+###################################################################
+#                          Options                                #
+###################################################################
+
+# Uncomment the following lines for NUMA-aware allocation (recommended)
+CCPASTIX   := $(CCPASTIX) -DNUMA_ALLOC
+
+# Show memory usage statistics
+#CCPASTIX   := $(CCPASTIX) -DMEMORY_USAGE
+
+# Show memory usage statistics in solver
+#CCPASTIX   := $(CCPASTIX) -DSTATS_SOPALIN
+
+# Uncomment following line for dynamic thread scheduling support
+#CCPASTIX   := $(CCPASTIX) -DPASTIX_BUBBLE 
+
+# Uncomment the following lines for Out-of-core
+#CCPASTIX   := $(CCPASTIX) -DOOC
+
+###################################################################
+#                      GRAPH PARTITIONING                         #
+###################################################################
+CCPASTIX   := $(CCPASTIX) $(FFMPIINCLUDE)
+EXTRALIB   := $(EXTRALIB) $(FFMPILIB)
+
+# uncomment the following lines for using metis ordering 
+#VERSIONORD  = _metis
+#METIS_HOME  = $(abs_top_builddir)/download/
+#CCPASTIX   := $(CCPASTIX) -DMETIS  -I$(METIS_HOME)/include/metis/
+#EXTRALIB   := $(EXTRALIB) -L$(METIS_HOME)/lib/ -lmetis 
+
+# Scotch always needed to compile
+SCOTCH_HOME =
+
+# ALH - 4/9/13 - see [[file:../../configure.ac::SCOTCH_INCLUDE]]
+SCOTCH_INC  =  @SCOTCH_INCLUDE@
+
+SCOTCH_LIB  = $(abs_top_builddir)/download/lib/
+# uncomment on of this blocks					     
+#scotch								     
+CCPASTIX   := $(CCPASTIX) -I$(SCOTCH_INC)
+EXTRALIB   := $(EXTRALIB) -L$(SCOTCH_LIB) -lscotch -lscotcherrexit
+#ptscotch							     
+#CCPASTIX   := $(CCPASTIX) -I$(SCOTCH_INC) -DDISTRIBUTED
+#EXTRALIB   := $(EXTRALIB) -L$(SCOTCH_LIB) -lptscotch -lscotcherrexit
+
+###################################################################
+#                             MARCEL                              #
+###################################################################
+
+# Uncomment following lines for marcel thread support
+#VERSIONSMP := $(VERSIONSMP)_marcel
+#CCPASTIX   := $(CCPASTIX) `pm2-config --cflags` -I${PM2_ROOT}/marcel/include/pthread
+#EXTRALIB   := $(EXTRALIB) `pm2-config --libs`
+# ---- Thread Posix ------
+EXTRALIB   := $(EXTRALIB) @LIBSPTHREAD@ 
+# Uncomment following line for bubblesched framework support (need marcel support)
+#VERSIONBUB  = _bubble
+#CCPASTIX   := $(CCPASTIX) -DPASTIX_USE_BUBBLE 
+
+###################################################################
+#                              BLAS                               #
+###################################################################
+
+# Choose Blas library (Only 1)
+# Do not forget to set BLAS_HOME if it is not in your environnement
+BLAS_HOME= $(FFBLASINCLUDE )
+#----  Blas    ----
+BLASLIB = $(FFBLASLIB)  #@BLASLIBS@
+#---- Gotoblas ----
+#BLASLIB =  -L$(BLAS_HOME) -lgoto
+#----  MKL     ----
+# Uncomment the correct line
+#BLASLIB =  -L$(BLAS_HOME) -lmkl_intel_lp64 -lmkl_sequential -lmkl_core
+#BLASLIB =  -L$(BLAS_HOME) -lmkl_intel -lmkl_sequential -lmkl_core
+#----  Acml    ----
+#BLASLIB =  -L$(BLAS_HOME) -lacml
+
+
+###################################################################
+#                          DO NOT TOUCH                           #
+###################################################################
+
+FOPT      := $(CCFOPT)
+FDEB      := $(CCFDEB)
+CCHEAD    := $(CCPROG) $(CCTYPES) $(CCFOPT)
+CCFOPT    := $(CCFOPT) $(CCTYPES) $(CCPASTIX)
+CFDEB     := $(CCFDEB) $(CCTYPES) $(CCPASTIX)
+
+###################################################################
+#                        MURGE COMPATIBILITY                      #
+###################################################################
+
+MAKE     = $(MKPROG)
+CC       = $(MPCCPROG)
+CFLAGS   = $(CCTYPES) $(CCFOPT) 
+FC       = $(MCFPROG) 
+FFLAGS   = $(CCFOPT)
+LDFLAGS  = $(EXTRALIB) $(BLASLIB)
\ No newline at end of file
diff --git a/download/pastix/config-pastix-real.in b/download/pastix/config-pastix-real.in
new file mode 100644
index 0000000..5a8b330
--- /dev/null
+++ b/download/pastix/config-pastix-real.in
@@ -0,0 +1,187 @@
+abs_top_builddir=@abs_top_builddir@
+include $(abs_top_builddir)/download/headers-sparsesolver.inc
+HOSTARCH    = @PASTIX_HOSTARCH@
+VERSIONBIT  = _ at SIZEOF_PTRINBIT@bit
+EXEEXT      =
+OBJEXT      = .o
+LIBEXT      = .a
+WGET        = @WGET@
+CCPROG      = @CC@ -Wall -DX_ARCH$(HOSTARCH)
+CFPROG      = @F77@ 
+CF90PROG    = @FC@ 
+MCFPROG     = @MPIFC@ 
+CF90CCPOPT  = -ffree-form -x f95-cpp-input #avant
+# Compilation options for optimization (make expor)
+CCFOPT      = -O3 @CFLAGS@
+# Compilation options for debug (make | make debug)
+CCFDEB      = -g3
+
+LKFOPT      =
+MKPROG      = make 
+
+# FFCS - add MPI_INCLUDE because FF cannot use the defaut openmpi scripts on MacOS (see
+# [[file:../../../../configure.ac::mpicc_on_macos]])
+
+MPCCPROG    = @MPICC@ -Wall -DX_ARCH$(HOSTARCH) @MPI_INCLUDE@
+
+ARFLAGS     = @ARFLAGS@  # ruv
+ARPROG      = @AR@       # ar
+EXTRALIB    = @FLIBS@ -lm -lsupc++
+
+VERSIONMPI  = _mpi
+VERSIONSMP  = _smp
+VERSIONBUB  = _nobubble
+VERSIONINT  = _int
+VERSIONPRC  = _simple
+VERSIONFLT  = _real
+VERSIONORD  = _scotch
+
+###################################################################
+#                          INTEGER TYPE                           #
+###################################################################
+# uncomment the following lines for integer type support (Only 1)
+
+VERSIONINT  = $(FFVERSIONINT)#_long
+CCTYPES     = $(FFCTYPESINT)#-DFORCE_LONG -DLONG
+#---------------------------
+#VERSIONINT  = _int32
+#CCTYPES     = -DFORCE_INT32 -DINTSIZE32
+#---------------------------
+#VERSIONINT  = _int64
+#CCTYPES     = -DFORCE_INT64 -DINTSSIZE64
+
+###################################################################
+#                           FLOAT TYPE                            #
+###################################################################
+
+# uncomment the following lines for double precision support
+VERSIONPRC  = _double
+CCTYPES    := $(CCTYPES) -DFORCE_DOUBLE -DPREC_DOUBLE
+
+# uncomment the following lines for float=complex support
+#VERSIONFLT  = _complex
+#CCTYPES    := $(CCTYPES) -DFORCE_COMPLEX -DTYPE_COMPLEX -DPREC_DOUBLE
+
+
+###################################################################
+#                          Mpi/THREADS                            #
+###################################################################
+
+# uncomment the following lines for sequential (NOMPI) version
+#VERSIONMPI  = _nompi
+#CCTYPES    := $(CCTYPES) -DFORCE_NOMPI
+#MPCCPROG    = $(CCPROG)
+#MCFPROG     = $(CFPROG)
+
+# uncomment the following lines for non-threaded (NOSMP) version
+#VERSIONSMP  = _nosmp
+#CCTYPES    := $(CCTYPES) -DFORCE_NOSMP
+
+# Uncomment the following line to enable a progression thread
+#CCPASTIX   := $(CCPASTIX) -DTHREAD_COMM
+
+# Uncomment the following line if your MPI doesn't support MPI_THREAD_MULTIPLE level
+#CCPASTIX   := $(CCPASTIX) -DPASTIX_FUNNELED
+
+# Uncomment the following line if your MPI doesn't support MPI_Datatype correctly
+#CCPASTIX   := $(CCPASTIX) -DNO_MPI_TYPE
+
+###################################################################
+#                          Options                                #
+###################################################################
+
+# Uncomment the following lines for NUMA-aware allocation (recommended)
+CCPASTIX   := $(CCPASTIX) -DNUMA_ALLOC
+
+# Show memory usage statistics
+#CCPASTIX   := $(CCPASTIX) -DMEMORY_USAGE
+
+# Show memory usage statistics in solver
+#CCPASTIX   := $(CCPASTIX) -DSTATS_SOPALIN
+
+# Uncomment following line for dynamic thread scheduling support
+#CCPASTIX   := $(CCPASTIX) -DPASTIX_BUBBLE 
+
+# Uncomment the following lines for Out-of-core
+#CCPASTIX   := $(CCPASTIX) -DOOC
+
+###################################################################
+#                      GRAPH PARTITIONING                         #
+###################################################################
+CCPASTIX   := $(CCPASTIX) $(FFMPIINCLUDE)
+EXTRALIB   := $(EXTRALIB) $(FFMPILIB)
+
+# uncomment the following lines for using metis ordering 
+#VERSIONORD  = _metis
+#METIS_HOME  = $(abs_top_builddir)/download/
+#CCPASTIX   := $(CCPASTIX) -DMETIS  -I$(METIS_HOME)/include/metis/
+#EXTRALIB   := $(EXTRALIB) -L$(METIS_HOME)/lib/ -lmetis 
+
+# Scotch always needed to compile
+SCOTCH_HOME =
+
+# ALH - 4/9/13 - see [[file:../../configure.ac::SCOTCH_INCLUDE]]
+SCOTCH_INC  = @SCOTCH_INCLUDE@
+
+SCOTCH_LIB  = $(abs_top_builddir)/download/lib/
+# uncomment on of this blocks					     
+#scotch								     
+CCPASTIX   := $(CCPASTIX) -I$(SCOTCH_INC)
+EXTRALIB   := $(EXTRALIB) -L$(SCOTCH_LIB) -lscotch -lscotcherrexit
+#ptscotch							     
+#CCPASTIX   := $(CCPASTIX) -I$(SCOTCH_INC) -DDISTRIBUTED
+#EXTRALIB   := $(EXTRALIB) -L$(SCOTCH_LIB) -lptscotch -lscotcherrexit
+
+###################################################################
+#                             MARCEL                              #
+###################################################################
+
+# Uncomment following lines for marcel thread support
+#VERSIONSMP := $(VERSIONSMP)_marcel
+#CCPASTIX   := $(CCPASTIX) `pm2-config --cflags` -I${PM2_ROOT}/marcel/include/pthread
+#EXTRALIB   := $(EXTRALIB) `pm2-config --libs`
+# ---- Thread Posix ------
+EXTRALIB   := $(EXTRALIB) @LIBSPTHREAD@ 
+# Uncomment following line for bubblesched framework support (need marcel support)
+#VERSIONBUB  = _bubble
+#CCPASTIX   := $(CCPASTIX) -DPASTIX_USE_BUBBLE 
+
+###################################################################
+#                              BLAS                               #
+###################################################################
+
+# Choose Blas library (Only 1)
+# Do not forget to set BLAS_HOME if it is not in your environnement
+BLAS_HOME= $(FFBLASINCLUDE )
+#----  Blas    ----
+BLASLIB = $(FFBLASLIB)  #@BLASLIBS@
+#---- Gotoblas ----
+#BLASLIB =  -L$(BLAS_HOME) -lgoto
+#----  MKL     ----
+# Uncomment the correct line
+#BLASLIB =  -L$(BLAS_HOME) -lmkl_intel_lp64 -lmkl_sequential -lmkl_core
+#BLASLIB =  -L$(BLAS_HOME) -lmkl_intel -lmkl_sequential -lmkl_core
+#----  Acml    ----
+#BLASLIB =  -L$(BLAS_HOME) -lacml
+
+
+###################################################################
+#                          DO NOT TOUCH                           #
+###################################################################
+
+FOPT      := $(CCFOPT)
+FDEB      := $(CCFDEB)
+CCHEAD    := $(CCPROG) $(CCTYPES) $(CCFOPT)
+CCFOPT    := $(CCFOPT) $(CCTYPES) $(CCPASTIX)
+CFDEB     := $(CCFDEB) $(CCTYPES) $(CCPASTIX)
+
+###################################################################
+#                        MURGE COMPATIBILITY                      #
+###################################################################
+
+MAKE     = $(MKPROG)
+CC       = $(MPCCPROG)
+CFLAGS   = $(CCTYPES) $(CCFOPT) 
+FC       = $(MCFPROG) 
+FFLAGS   = $(CCFOPT)
+LDFLAGS  = $(EXTRALIB) $(BLASLIB)
\ No newline at end of file
diff --git a/download/pastix/pastix_release_2200-blend.patch b/download/pastix/pastix_release_2200-blend.patch
new file mode 100644
index 0000000..637ed1c
--- /dev/null
+++ b/download/pastix/pastix_release_2200-blend.patch
@@ -0,0 +1,13 @@
+diff -ur pastix_release_2200/src/blend/src/make_gen pastix_release_2200-okk/blend/make_gen
+--- pastix_release_2200/src/blend/src/make_gen	2009-02-19 14:33:00.000000000 +0100
++++ pastix_release_2200-okk/blend/make_gen	2010-02-12 11:03:07.000000000 +0100
+@@ -90,8 +90,7 @@
+ ##
+ 
+ 
+-$(DSTDIR)/libblend3d$(LIB):		$(HEADERS) 			\
+-					$(OJTDIR)/task$(OBJ)   		\
++$(DSTDIR)/libblend3d$(LIB):		$(OJTDIR)/task$(OBJ)   		\
+ 					$(OJTDIR)/fanboth2$(OBJ)   	\
+ 					$(OJTDIR)/splitfunc$(OBJ)   	\
+ 					$(OJTDIR)/symbol_cost$(OBJ)   	\
diff --git a/download/pastix/patch-pastix_long_complex.h b/download/pastix/patch-pastix_long_complex.h
new file mode 100644
index 0000000..be637ef
--- /dev/null
+++ b/download/pastix/patch-pastix_long_complex.h
@@ -0,0 +1,28 @@
+--- pastix_release_2200/../../include/pastix/complex/pastix_long_complex.h	2011-10-05 14:28:24.000000000 +0200
++++ /tmp/pastix_long_complex.h	2011-10-05 14:39:17.000000000 +0200
+@@ -1,9 +1,16 @@
+-#include <complex.h>
++#ifdef __cplusplus
++#include <complex>
++#define pastix_float_t   std::complex<double> 
++extern "C" {
++  MPI_Datatype GetMpiType() ;
++#else
++ #include <complex.h>
++#define pastix_float_t   double complex
++#endif
+ 
+ #define pastix_int_t     long
+ #define pastix_uint_t    unsigned long
+ #define MPI_PASTIX_INT   MPI_LONG
+-#define pastix_float_t   double complex
+ #define MPI_PASTIX_FLOAT GetMpiType()
+ #define INT              pastix_int_t
+ #define UINT             pastix_uint_t
+@@ -744,3 +751,6 @@
+ #define MTX_ISRHS(a) (a)[0]!='\0'
+ 
+ /* **************************************** */
++#ifdef __cplusplus
++}
++#endif
diff --git a/download/scalapack/Makefile b/download/scalapack/Makefile
new file mode 100644
index 0000000..3616be1
--- /dev/null
+++ b/download/scalapack/Makefile
@@ -0,0 +1,79 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include SLmake.inc
+
+all-local: scalapack
+
+# FFCS: parallel compilation crashes on Win32 (same archive updated from 2 different parallel makes)
+MAKEFLAGS=-j 1
+
+# Downloading and compiling scalapack
+# ------------------------------
+# http://www.netlib.org/scalapack/
+# Hips information
+DIRPKG=../pkg
+SRCDIR=scalapack-2.0.2
+PACKAGE1=$(DIRPKG)/scalapack-2.0.2.tgz
+SERVER=http://www.netlib.org/scalapack/
+INSTALL=../..
+
+# FFCS: shorten argument length to avoid "sh: ../ar: Argument list too long" under Cygwin
+DIR1 = TOOLS/LAPACK/*.o
+DIR2 = TOOLS/*.o
+DIR3 = PBLAS/SRC/PBBLAS/*.o
+DIR4 = PBLAS/SRC/PTZBLAS/*.o
+DIR5 = PBLAS/SRC/PTOOLS/*.o
+DIR6 = PBLAS/SRC/*.o
+DIR7 = REDIST/SRC/*.o
+DIR8 = SRC/*.o
+DIR9 = BLACS/SRC/*.o BLACS/SRC/*.oo
+
+scalapack: FAIRE
+
+# FFCS: shorten argument length to avoid "sh: ../ar: Argument list too long" under Cygwin
+$(SRCDIR)/FAIT-202:$(SRCDIR)/tag-tar
+	cp SLmake.inc $(SRCDIR)
+	cd $(SRCDIR);$(MAKE) lib
+	rm $(SRCDIR)/libscalapack.a
+	cd $(SRCDIR) && $(ARCH) $(ARCHFLAGS) libscalapack.a $(DIR1) $(DIR2) $(DIR3) $(DIR4) $(DIR5) $(DIR6) $(DIR7) $(DIR8) $(DIR9)
+	$(RANLIB) $(SRCDIR)/libscalapack.a
+	touch $(SRCDIR)/FAIT-202
+install:
+	mkdir -p ../include
+	cp $(SRCDIR)/SRC/*.h ../include
+	mkdir -p ../lib
+	cp $(SRCDIR)/libscalapack.a ../lib
+
+WHERE:
+	if [ -f $(SRCDIR)/FAIT-202 ] ; then \
+	make install;  \
+	echo scalapack LD -L at DIR@/lib  -lscalapack   >../lib/WHERE.scalapack ;\
+	echo scalapack INCLUDE -I at DIR@/include  >> ../lib/WHERE.scalapack ;\
+	fi
+
+FAIRE: $(SRCDIR)/FAIT-202
+	$(MAKE) WHERE
+	touch FAIRE 
+
+SLmake.inc: ../../config.status	Makefile SLmake-scalapack.inc
+	../../config.status  --file="SLmake.inc:SLmake-scalapack.inc"
+
+$(SRCDIR)/tag-tar: $(PACKAGE1)
+	gunzip -c $(PACKAGE1) | tar xvf -
+	touch $(SRCDIR)/tag-tar
+
+$(PACKAGE1):
+	../getall -o ScaLAPACK -a
+
+clean:
+#	FFCS - need to clean completely even in case of error
+	-rm SLmake.inc FAIRE FAIT
+#	FFCS - make sure that all directories are cleaned. Thisis especially important under Windows because there is no
+#	compilation dependencies control there (see
+#	[[file:c:/cygwin/home/alh/ffcs/dist/configure.ac::dependency_tracking]])
+	-rm -rf scalapack-*
+	-rm config.log
+#	-rm $(PACKAGE1)
+
+.PHONY:$(SRCDIR)/$(INSTALL)
\ No newline at end of file
diff --git a/download/scalapack/SLmake-scalapack.inc b/download/scalapack/SLmake-scalapack.inc
new file mode 100644
index 0000000..6eb5dc7
--- /dev/null
+++ b/download/scalapack/SLmake-scalapack.inc
@@ -0,0 +1,66 @@
+############################################################################
+#
+#  Program:         ScaLAPACK
+#
+#  Module:          SLmake.inc
+#
+#  Purpose:         Top-level Definitions
+#
+#  Creation date:   February 15, 2000
+#
+#  Modified:        October 13, 2011
+#
+#  Send bug reports, comments or suggestions to scalapack at cs.utk.edu
+#
+############################################################################
+#
+#  C preprocessor definitions:  set CDEFS to one of the following:
+#
+#     -DNoChange (fortran subprogram names are lower case without any suffix)
+#     -DUpCase   (fortran subprogram names are upper case without any suffix)
+#     -DAdd_     (fortran subprogram names are lower case with "_" appended)
+
+CDEFS         = @CFLAGSF77@ -DNO_IEEE $(USEMPI)
+
+#
+#  The fortran and C compilers, loaders, and their flags
+#
+
+FC            = @MPIF77@ 
+CC            = @MPICC@ 
+NOOPT         = -O0 @CNOFLAGS@
+
+# FFCS - some return statements without value cause trouble on MacOS
+# FFCS - add path to mpi.h (required for MacOS 10.8 + MacPorts OpenMPI)
+# FFCS - added @CNOFLAGS@ according to upstream changes
+CCFLAGS       = -O3 -Wreturn-type @CFLAGS@ -I @MPI_INC_DIR@ @CNOFLAGS@
+FCFLAGS       = -O3 @CNOFLAGS@
+FCLOADER      = $(FC)
+CCLOADER      = $(CC)
+FCLOADFLAGS   = $(FCFLAGS)
+CCLOADFLAGS   = $(CCFLAGS)
+
+#
+#  The archiver and the flag(s) to use when building archive (library)
+#  Also the ranlib routine.  If your system has no ranlib, set RANLIB = echo
+#
+
+ARCH          = @AR@
+ARCHFLAGS     = @ARFLAGS@
+RANLIB        = @RANLIB@
+
+#
+#  The name of the ScaLAPACK library to be created
+#
+
+SCALAPACKLIB  = libscalapack.a
+
+#
+#  BLAS, LAPACK (and possibly other) libraries needed for linking test programs
+#
+
+BLASLIB       = $(FFBLASLIB)
+LAPACKLIB     = $(FFLAPACKLIB)
+LIBS          = $(LAPACKLIB) $(BLASLIB)
+
+WGET = @WGET@
\ No newline at end of file
diff --git a/download/scotch/Makefile b/download/scotch/Makefile
new file mode 100644
index 0000000..5e8e887
--- /dev/null
+++ b/download/scotch/Makefile
@@ -0,0 +1,106 @@
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# http://www.ljll.math.upmc.fr/lehyaric
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem make multipleauthors start=19/03/10 upmc
+
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+include Makefile.inc
+
+all-local: scotch
+
+# Downloading and compiling scotch
+# -------------------------------
+# http://gforge.inria.fr/frs/download.php/23391/scotch_5.1.7_esmumps.tar.gz
+# Scotch information
+DIRPKG=../pkg
+SRCDIR=scotch_$(scotch_VERSION)
+PACKAGE=$(DIRPKG)/scotch_$(scotch_VERSION_LOCAL).tar.gz
+SERVER=https://gforge.inria.fr/frs/download.php/23391
+INSTALL=../..
+scotch_VERSION=5.1_esmumps
+scotch_VERSION_LOCAL=5.1.6_esmumps
+#  trick to no in MPI on NOT .. 
+TESTMPI= test -n '$(CCP)'
+scotch: FAIRE
+
+$(SRCDIR)/AFAIRE:
+	$(MAKE) install 
+
+FAIRE: $(SRCDIR)/FAIT
+	$(MAKE)  WHERE
+	touch FAIRE
+Makefile.inc: ../../config.status Makefile-scotch.inc Makefile
+	../../config.status  --file="Makefile.inc:Makefile-scotch.inc"
+	case `uname` in *CYGWIN*)  cp Makefile.inc Makefile.inn; sed "s/COPTIONS =/COPTIONS = -D__VC__/" <Makefile.inn > Makefile.inc; rm Makefile.inn ;; esac 
+	case `uname` in *CYGWIN*|*MINGW*)  cp Makefile.inc Makefile.inn; sed -e "s/-DCOMMON_TIMING_OLD//" -e "s/-DCOMMON_RANDOM_FIXED_SEED/-DCOMMON_RANDOM_RAND  -DCOMMON_RANDOM_FIXED_SEED -D'pipe(pfds)=_pipe(pfds,1024,0x8000)'/" <Makefile.inn > Makefile.inc; rm Makefile.inn ;; esac 
+
+# FFCS - 16/1/13 - what was "$(CCP)" used for?
+$(SRCDIR)/FAIT: $(SRCDIR) Makefile.inc
+	cp Makefile.inc $(SRCDIR)/src
+	cd $(SRCDIR)/src && $(MAKE) scotch
+#
+#	FFCS - 16/1/13 - this crashes when run in parallel
+#       FH: compile pt only if mpi is here 
+	if $(TESTMPI) ; then  cd $(SRCDIR)/src && $(MAKE) -j1 ptscotch ; fi
+	touch $(SRCDIR)/FAIT
+
+install:$(SRCDIR)/FAIT
+	mkdir -p $(SRCDIR)/$(INSTALL)/include/scotch
+	cp $(SRCDIR)/include/*.h $(SRCDIR)/$(INSTALL)/include/scotch/
+	cp $(SRCDIR)/lib/*.a $(SRCDIR)/$(INSTALL)/lib/
+
+# ALH - 16/1/13 - simplifying make rules
+WHERE:$(SRCDIR)/FAIT
+	$(MAKE) install
+	-rm $(SRCDIR)/$(INSTALL)/lib/WHERE.scotch
+	-$(TESTMPI) &&echo ptscotch LD -L at DIR@/lib -lptesmumps -lptscotch -lptscotcherr >>$(SRCDIR)/$(INSTALL)/lib/WHERE.scotch
+	-$(TESTMPI) &&echo ptscotch INCLUDE -I at DIR@/include/scotch >> $(SRCDIR)/$(INSTALL)/lib/WHERE.scotch
+	echo scotch LD -L at DIR@/lib -lscotch -lscotcherr >>$(SRCDIR)/$(INSTALL)/lib/WHERE.scotch
+	echo scotch INCLUDE -I at DIR@/include/scotch >> $(SRCDIR)/$(INSTALL)/lib/WHERE.scotch
+
+$(SRCDIR): $(PACKAGE)
+	tar xvzf $(PACKAGE)
+	cd $(SRCDIR)/src/libscotch/; patch -p1 < ../../../scotch_5.1_esmumps.patch
+	cd $(SRCDIR)/src/esmumps/; patch -p1 < ../../../Makefile.patch
+	touch $(SRCDIR)
+
+$(PACKAGE):
+	../getall -o Scotch -a
+
+# FFCS - 28/3/13 - more cleaning
+clean-local:
+	-cd $(SRCDIR)/src && $(MAKE)  realclean  -C $(SRCDIR)/src
+	-rm config.log
+# FH 	-rm $(PACKAGE) 
+
+clean: clean-local
+	-rm Makefile.inc
+	-rm -rf $(SRCDIR)
+	-rm FAIRE 
+.PHONY:$(SRCDIR)/$(INSTALL)
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/scotch/Makefile-scotch.inc b/download/scotch/Makefile-scotch.inc
new file mode 100644
index 0000000..5ea9b52
--- /dev/null
+++ b/download/scotch/Makefile-scotch.inc
@@ -0,0 +1,32 @@
+# ALH - avoid blocking when Makefile.inc is not built yet
+-include @abs_top_builddir@/download/headers-sparsesolver.inc
+
+EXE	=
+LIB	= .a
+OBJ	= .o
+DIRMPI  = @FFMPIDIR@
+MAKE	= make
+AR	= @AR@
+ARFLAGS	= @ARFLAGS@
+CAT	= cat
+CCS     = @CC@ 
+CCP	= @MPICC@ 
+CCD     = @CC@ -I'@MPI_INC_DIR@'
+
+# FFCS - 16/4/13 - some plain C files seem to need access to mpi.h too
+
+# FFCS - 23/4/13 - remove thread and fork dependency on Windows with
+# -DCOMMON_STUB_FORK without -DCOMMON_PTHREAD
+# [[file:scotch_5.1_esmumps/INSTALL.TXT::COMMON_STUB_FORK]]
+
+CFLAGS	= @CFLAGS@ -I'@MPI_INC_DIR@' $(FFINTSCOTCH) -Drestrict=__restrict -DCOMMON_STUB_FORK  -DCOMMON_RANDOM_FIXED_SEED -DCOMMON_TIMING_OLD -DSCOTCH_RENAME -DSCOTCH_DETERMINISTIC
+
+LDFLAGS	= @LDFLAGS@ -lm @MPI_LIBC@  @LIBSPTHREAD@  #-L/usr/local/lib/gcc/
+CP	= cp
+LEX	= @LEX@
+LN	= ln
+MKDIR	= mkdir
+MV	= mv
+RANLIB	= @RANLIB@
+YACC	= @YACC@
+WGET    = @WGET@
diff --git a/download/scotch/Makefile.patch b/download/scotch/Makefile.patch
new file mode 100644
index 0000000..588e67f
--- /dev/null
+++ b/download/scotch/Makefile.patch
@@ -0,0 +1,13 @@
+diff -ur scotch_5.1_esmumps/src/esmumps/Makefile scotch-okk/Makefile 
+--- scotch_5.1_esmumps/src/esmumps/Makefile	2009-04-27 11:22:08.000000000 +0200
++++ scotch-okk/Makefile	2012-05-09 10:00:46.765713788 +0200
+@@ -44,7 +44,7 @@
+ 				$(CC) $(CFLAGS) -I$(includedir) -c $(<) -o $(@)
+ 
+ %$(EXE)	:	%.c
+-		 		$(CC) $(CFLAGS) -I$(includedir) $(<) -o $(@) -L$(libdir) $(LDFLAGS) -L. -l$(ESMUMPSLIB) -l$(SCOTCHLIB) -l$(SCOTCHLIB)errexit
++		 		$(CC) $(CFLAGS) -I$(includedir) $(<) -o $(@) -L$(libdir) -L. -l$(ESMUMPSLIB) -l$(SCOTCHLIB) -l$(SCOTCHLIB)errexit $(LDFLAGS) 
+ 
+ ##
+ ##  Project rules.
+
diff --git a/download/scotch/scotch_5.1_esmumps.patch b/download/scotch/scotch_5.1_esmumps.patch
new file mode 100644
index 0000000..ac7782b
--- /dev/null
+++ b/download/scotch/scotch_5.1_esmumps.patch
@@ -0,0 +1,217 @@
+diff -ur scotch_5.1_esmumps/src/libscotch/Makefile scotch_5.1_esmumps-okk/Makefile
+--- scotch_5.1_esmumps/src/libscotch/Makefile	2009-06-06 16:05:52.000000000 +0200
++++ scotch_5.1_esmumps-okk/Makefile	2010-02-11 18:14:35.000000000 +0100
+@@ -64,10 +64,9 @@
+ 					scotch.h									\
+ 					scotchf.h									\
+ 					libptscotch$(LIB)								\
+-					libscotch$(LIB)									\
+ 					libptscotcherr$(LIB)								\
+ 					libptscotcherrexit$(LIB)
+-
++					## libscotch$(LIB)	
+ install				:
+ 					-$(CP) scotch.h scotchf.h $(includedir)
+ 					-$(CP) libscotch$(LIB) libscotcherr*$(LIB) $(libdir)
+@@ -2274,7 +2273,162 @@
+ 					vdgraph_separate_sq$(OBJ)		\
+ 					vdgraph_separate_st$(OBJ)		\
+ 					vdgraph_separate_zr$(OBJ)		\
+-					vdgraph_store$(OBJ)
++					vdgraph_store$(OBJ) arch$(OBJ) 		\
++					arch_build$(OBJ)			\
++					arch_cmplt$(OBJ)			\
++					arch_cmpltw$(OBJ)			\
++					arch_deco$(OBJ)				\
++					arch_hcub$(OBJ)				\
++					arch_mesh$(OBJ)				\
++					arch_tleaf$(OBJ)			\
++					arch_torus$(OBJ)			\
++					arch_vcmplt$(OBJ)			\
++					arch_vhcub$(OBJ)			\
++					bgraph$(OBJ)				\
++					bgraph_bipart_bd$(OBJ)			\
++					bgraph_bipart_df$(OBJ)			\
++					bgraph_bipart_ex$(OBJ)			\
++					bgraph_bipart_fm$(OBJ)			\
++					bgraph_bipart_gg$(OBJ)			\
++					bgraph_bipart_gp$(OBJ)			\
++					bgraph_bipart_ml$(OBJ)			\
++					bgraph_bipart_st$(OBJ)			\
++					bgraph_bipart_zr$(OBJ)			\
++					bgraph_check$(OBJ)			\
++					bgraph_store$(OBJ)			\
++					common$(OBJ)				\
++					common_file$(OBJ)			\
++					common_file_compress$(OBJ)		\
++					common_file_uncompress$(OBJ)		\
++					common_integer$(OBJ)			\
++					common_memory$(OBJ)			\
++					common_stub$(OBJ)			\
++					gain$(OBJ)				\
++					geom$(OBJ)				\
++					graph$(OBJ)				\
++					graph_base$(OBJ)			\
++					graph_check$(OBJ)			\
++					graph_coarsen$(OBJ)			\
++					graph_induce$(OBJ)			\
++					graph_io$(OBJ)				\
++					graph_io_chac$(OBJ)			\
++					graph_io_habo$(OBJ)			\
++					graph_io_mmkt$(OBJ)			\
++					graph_io_scot$(OBJ)			\
++					graph_list$(OBJ)			\
++					hall_order_hd$(OBJ)			\
++					hall_order_hf$(OBJ)			\
++					hall_order_hx$(OBJ)			\
++					hgraph$(OBJ)				\
++					hgraph_check$(OBJ)			\
++					hgraph_induce$(OBJ)			\
++					hgraph_order_bl$(OBJ)			\
++					hgraph_order_cp$(OBJ)			\
++					hgraph_order_gp$(OBJ)			\
++					hgraph_order_hd$(OBJ)			\
++					hgraph_order_hf$(OBJ)			\
++					hgraph_order_hx$(OBJ)			\
++					hgraph_order_nd$(OBJ)			\
++					hgraph_order_si$(OBJ)			\
++					hgraph_order_st$(OBJ)			\
++					hmesh$(OBJ)				\
++					hmesh_check$(OBJ)			\
++					hmesh_hgraph$(OBJ)			\
++					hmesh_induce$(OBJ)			\
++					hmesh_mesh$(OBJ)			\
++					hmesh_order_bl$(OBJ)			\
++					hmesh_order_cp$(OBJ)			\
++					hmesh_order_gr$(OBJ)			\
++					hmesh_order_gp$(OBJ)			\
++					hmesh_order_hd$(OBJ)			\
++					hmesh_order_hf$(OBJ)			\
++					hmesh_order_hx$(OBJ)			\
++					hmesh_order_nd$(OBJ)			\
++					hmesh_order_si$(OBJ)			\
++					hmesh_order_st$(OBJ)			\
++					kgraph$(OBJ)				\
++					kgraph_map_rb$(OBJ)			\
++					kgraph_map_rb_map$(OBJ)			\
++					kgraph_map_rb_part$(OBJ)		\
++					kgraph_map_st$(OBJ)			\
++					library_arch$(OBJ)			\
++					library_arch_f$(OBJ)			\
++					library_arch_build$(OBJ)		\
++					library_arch_build_f$(OBJ)		\
++					library_geom$(OBJ)			\
++					library_geom_f$(OBJ)			\
++					library_graph$(OBJ)			\
++					library_graph_f$(OBJ)			\
++					library_graph_base$(OBJ)		\
++					library_graph_base_f$(OBJ)		\
++					library_graph_check$(OBJ)		\
++					library_graph_check_f$(OBJ)		\
++					library_graph_io_chac$(OBJ)		\
++					library_graph_io_chac_f$(OBJ)		\
++					library_graph_io_habo$(OBJ)		\
++					library_graph_io_habo_f$(OBJ)		\
++					library_graph_io_mmkt$(OBJ)		\
++					library_graph_io_mmkt_f$(OBJ)		\
++					library_graph_io_scot$(OBJ)		\
++					library_graph_io_scot_f$(OBJ)		\
++					library_graph_map$(OBJ)			\
++					library_graph_map_f$(OBJ)		\
++					library_graph_map_view$(OBJ)		\
++					library_graph_map_view_f$(OBJ)		\
++					library_graph_order$(OBJ)		\
++					library_graph_order_f$(OBJ)		\
++					library_mesh$(OBJ)			\
++					library_mesh_f$(OBJ)			\
++					library_mesh_graph$(OBJ)		\
++					library_mesh_graph_f$(OBJ)		\
++					library_mesh_io_habo$(OBJ)		\
++					library_mesh_io_habo_f$(OBJ)		\
++					library_mesh_io_scot$(OBJ)		\
++					library_mesh_io_scot_f$(OBJ)		\
++					library_mesh_order$(OBJ)		\
++					library_mesh_order_f$(OBJ)		\
++					library_parser$(OBJ)			\
++					library_parser_f$(OBJ)			\
++					library_random$(OBJ)			\
++					library_random_f$(OBJ)			\
++					mapping$(OBJ)				\
++					mapping_io$(OBJ)			\
++					mesh$(OBJ)				\
++					mesh_check$(OBJ)			\
++					mesh_coarsen$(OBJ)			\
++					mesh_graph$(OBJ)			\
++					mesh_induce_sepa$(OBJ)			\
++					mesh_io$(OBJ)				\
++					mesh_io_habo$(OBJ)			\
++					mesh_io_scot$(OBJ)			\
++					order$(OBJ)				\
++					order_check$(OBJ)			\
++					order_io$(OBJ)				\
++					parser$(OBJ)				\
++					parser_ll$(OBJ)				\
++					parser_yy$(OBJ)				\
++					vgraph$(OBJ)				\
++					vgraph_check$(OBJ)			\
++					vgraph_separate_bd$(OBJ)		\
++					vgraph_separate_es$(OBJ)		\
++					vgraph_separate_fm$(OBJ)		\
++					vgraph_separate_gg$(OBJ)		\
++					vgraph_separate_gp$(OBJ)		\
++					vgraph_separate_ml$(OBJ)		\
++					vgraph_separate_st$(OBJ)		\
++					vgraph_separate_th$(OBJ)		\
++					vgraph_separate_vw$(OBJ)		\
++					vgraph_separate_zr$(OBJ)		\
++					vgraph_store$(OBJ)			\
++					vmesh$(OBJ)				\
++					vmesh_check$(OBJ)			\
++					vmesh_separate_fm$(OBJ)			\
++					vmesh_separate_gg$(OBJ)			\
++					vmesh_separate_gr$(OBJ)			\
++					vmesh_separate_ml$(OBJ)			\
++					vmesh_separate_zr$(OBJ)			\
++					vmesh_separate_st$(OBJ)			\
++					vmesh_store$(OBJ)
+ 					$(AR) $(ARFLAGS) $(@) $(?)
+ 					-$(RANLIB) $(@)
+ 
+--- scotch_5.1_esmumps/src/libscotch/common.c	2008-05-22 13:44:41 +0000
++++ scotch_5.1_esmumps-okk/common.c	2012-05-08 14:47:19 +0000
+@@ -54,10 +54,25 @@
+ */
+ 
+ #define COMMON
+-
+ #include <time.h>
+ #include "common.h"
+ 
++#if defined(_WIN32)
++#include  <sys/timeb.h>
++double
++clockGet (void)
++{
++  time_t	ltime;
++  struct    _timeb	tstruct;
++
++  time (&ltime);
++  _ftime(&tstruct);
++ double val = (double) ltime + (double) tstruct.millitm*(0.001);
++ return val;
++}
++
++#else
++
+ /*******************/
+ /*                 */
+ /* Timing routine. */
+@@ -86,7 +101,7 @@
+ #endif /* COMMON_TIMING_OLD */
+ #endif /* MPI_INT */
+ }
+-
++#endif /*  _WIN32 */
+ /***************************/
+ /*                         */
+ /* Usage printing routine. */
diff --git a/download/superlu/Makefile b/download/superlu/Makefile
new file mode 100755
index 0000000..31ed365
--- /dev/null
+++ b/download/superlu/Makefile
@@ -0,0 +1,135 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+all-local: superlu
+
+# Downloading and compiling Tetgen
+# ------------------------------
+
+# SUPERLU information
+#http://crd.lbl.gov/~xiaoye/SuperLU/superlu_4.0.tar.gz
+DIRPKG=../pkg
+SRCDIR=SuperLU_4.3
+PACKAGE=superlu_4.3.tar.gz
+PACKAGE_PATH=$(DIRPKG)/$(PACKAGE)
+SERVER=http://crd-legacy.lbl.gov/~xiaoye/SuperLU/
+# http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_4.3.tar.gz
+INSTALL=../..
+SUPERLU_VERSION=4.3
+SUPERLULIB=../$(INSTALL)/lib/libsuperlu_$(SUPERLU_VERSION).a
+include  ff-FLAGS
+
+### LAPACK 
+LAAUX 	= lsame.o xerbla.o
+SLASRC 	= slacon.o 
+DLASRC	= dlacon.o
+CLASRC	= clacon.o scsum1.o icmax1.o
+ZLASRC	= zlacon.o dzsum1.o izmax1.o
+SCLAUX 	= slamch.o
+DZLAUX 	= dlamch.o
+
+### SuperLU 
+ALLAUX 	= superlu_timer.o util.o memory.o get_perm_c.o mmd.o \
+	  sp_coletree.o sp_preorder.o sp_ienv.o relax_snode.o \
+	  heap_relax_snode.o colamd.o
+
+SLUSRC = \
+	sgssv.o sgssvx.o \
+	ssp_blas2.o ssp_blas3.o sgscon.o  \
+	slangs.o sgsequ.o slaqgs.o spivotgrowth.o \
+	sgsrfs.o sgstrf.o sgstrs.o scopy_to_ucol.o \
+	ssnode_dfs.o ssnode_bmod.o \
+	spanel_dfs.o spanel_bmod.o sreadhb.o \
+	scolumn_dfs.o scolumn_bmod.o spivotL.o spruneL.o \
+	smemory.o sutil.o smyblas2.o
+
+DLUSRC = \
+	dgssv.o dgssvx.o \
+	dsp_blas2.o dsp_blas3.o dgscon.o \
+	dlangs.o dgsequ.o dlaqgs.o dpivotgrowth.o  \
+	dgsrfs.o dgstrf.o dgstrs.o dcopy_to_ucol.o \
+	dsnode_dfs.o dsnode_bmod.o \
+	dpanel_dfs.o dpanel_bmod.o dreadhb.o \
+	dcolumn_dfs.o dcolumn_bmod.o dpivotL.o dpruneL.o \
+	dmemory.o dutil.o dmyblas2.o ## dgstrsL.o dgstrsU.o
+
+CLUSRC = \
+	scomplex.o cgssv.o cgssvx.o csp_blas2.o csp_blas3.o cgscon.o \
+	clangs.o cgsequ.o claqgs.o cpivotgrowth.o  \
+	cgsrfs.o cgstrf.o cgstrs.o ccopy_to_ucol.o \
+	csnode_dfs.o csnode_bmod.o \
+	cpanel_dfs.o cpanel_bmod.o creadhb.o \
+	ccolumn_dfs.o ccolumn_bmod.o cpivotL.o cpruneL.o \
+	cmemory.o cutil.o cmyblas2.o
+
+ZLUSRC = \
+	dcomplex.o zgssv.o zgssvx.o zsp_blas2.o zsp_blas3.o zgscon.o \
+	zlangs.o zgsequ.o zlaqgs.o zpivotgrowth.o  \
+	zgsrfs.o zgstrf.o zgstrs.o zcopy_to_ucol.o \
+	zsnode_dfs.o zsnode_bmod.o \
+	zpanel_dfs.o zpanel_bmod.o zreadhb.o \
+	zcolumn_dfs.o zcolumn_bmod.o zpivotL.o zpruneL.o \
+	zmemory.o zutil.o zmyblas2.o
+
+
+OBJ_SUPERLU = $(ALLAUX) $(LAAUX) \
+ $(SLUSRC)  $(SLASRC) $(SCLAUX) \
+ $(DLUSRC)  $(DLASRC) $(DZLAUX) \
+ $(CLUSRC)  $(CLASRC) \
+ $(ZLUSRC)  $(ZLASRC) 
+
+superlu: FAIT
+
+# FFCS - 18/6/12 - depend on SRCDIR to remake all when package version changes
+FAIT:$(SRCDIR)	
+	$(MAKE)  install WHERE
+	touch FAIT
+
+
+FAIRE:$(SRCDIR)
+	cd $(SRCDIR)/SRC; $(MAKE) -f ../../ff-FLAGS  $(OBJ_SUPERLU)
+	touch FAIRE
+
+# FFCS - FAIRE and WHERE need to be done sequentially, even in a parallel build (corrected by Cico, 1/3/12)
+install: FAIRE
+	$(MAKE) WHERE
+	cd $(SRCDIR)/SRC; $(AR) $(ARFLAGS) $(SUPERLULIB)  $(OBJ_SUPERLU)
+	cd $(SRCDIR)/SRC; $(RANLIB) $(SUPERLULIB) 
+	cp $(SRCDIR)/SRC/s*h  $(SRCDIR)/$(INSTALL)/include
+WHERE:
+	echo superlu LD -L at DIR@/lib -lsuperlu_$(SUPERLU_VERSION)  >$(SRCDIR)/$(INSTALL)/lib/WHERE.superlu
+	echo superlu INCLUDE -I at DIR@/include >> $(SRCDIR)/$(INSTALL)/lib/WHERE.superlu
+
+
+
+
+$(SRCDIR)/$(INSTALL): 
+	mkdir $(SRCDIR)/$(INSTALL)
+
+
+$(SRCDIR): $(PACKAGE_PATH)
+	tar xvzf $(PACKAGE_PATH)
+	touch $(SRCDIR)
+
+$(PACKAGE_PATH):
+	../getall -o SuperLU -a
+
+# FFCS - make sure that all directories are cleaned. Thisis especially important under Windows because there is no
+# compilation dependencies control there (see [[file:c:/cygwin/home/alh/ffcs/dist/configure.ac::dependency_tracking]])
+
+clean:
+	-rm -rf SuperLU_* ff-FLAGS
+	-rm -rf FAIT FAIRE
+
+
+# ALH - FFCS - 18/5/9 - FHecht says he forgot to add -fPIC for 64 bit platforms, so I add it myself here.
+ff-FLAGS: ../Makefile  Makefile 
+	grep '^CXX *=' ../Makefile >>$@
+	grep '^CC *=' ../Makefile >>$@
+	grep '^CFLAGS *=' ../Makefile|sed 's/$$/ -fPIC/' >>$@
+	grep '^BLAS[A-Z ]*='  ../Makefile|grep =  >>$@
+	grep '^AR *='  ../Makefile|grep =  >>$@
+	grep '^ARFLAGS *='  ../Makefile|grep =  >>$@
+	grep '^RANLIB *='    ../Makefile|grep =  >>$@
+	grep '^WGET *='    ../Makefile|grep =  >>$@
+
diff --git a/download/superlu/make.inc b/download/superlu/make.inc
new file mode 100644
index 0000000..39a27bd
--- /dev/null
+++ b/download/superlu/make.inc
@@ -0,0 +1,44 @@
+############################################################################
+#
+#  Program:         SuperLU
+#
+#  Module:          make.inc
+#
+#  Purpose:         Top-level Definitions
+#
+#  Creation date:   October 2, 1995
+#
+#  Modified:	    February 4, 1997  Version 1.0
+#		    November 15, 1997 Version 1.1
+#		    September 1, 1999 Version 2.0
+#
+############################################################################
+#
+#
+#  The name of the libraries to be created/linked to
+#
+TMGLIB       = $(INSTALL)/../lib/libtmglib.a
+SUPERLULIB   = $(INSTALL)/../lib/libsuperlu_3.1.a
+BLASLIB      =  $(BLASLIBS)
+
+#
+#  The archiver and the flag(s) to use when building archive (library)
+#  If your system has no ranlib, set RANLIB = echo.
+#
+ARCH         = $(AR)
+ARCHFLAGS    = $(ARFLAGS)
+
+
+FORTRAN	     = f77
+FFLAGS       = -O
+LOADER       = $(CC)
+LOADOPTS     = 
+
+#
+#  C preprocessor defs for compilation (-DNoChange, -DAdd_, or -DUpCase)
+#
+CDEFS        = -DAdd_
+#
+# The directory in which Matlab is installed
+#
+MATLAB	     = /usr/sww/pkg/matlab
diff --git a/download/superludist/Makefile b/download/superludist/Makefile
new file mode 100644
index 0000000..8a97c30
--- /dev/null
+++ b/download/superludist/Makefile
@@ -0,0 +1,77 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+all-local: superludist
+
+# Downloading and compiling SuperLU DIST
+# ------------------------------
+
+# SUPERLU information
+#http://crd.lbl.gov/~xiaoye/SuperLU/superlu_3.1.tar.gz
+#http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_dist_3.0.tar.gz
+DIRPKG=../pkg
+SRCDIR=SuperLU_DIST_3.0
+PACKAGE=superlu_dist_3.0.tar.gz
+PACKAGE_PATH=$(DIRPKG)/$(PACKAGE)
+SERVER=http://crd-legacy.lbl.gov/~xiaoye/SuperLU/
+INSTALL=../..
+SUPERLU_DIST_VERSION=3.0
+DISTSUPERLULIB=../$(INSTALL)/lib/libsuperlu_dist_3.0.a
+## WGET=wget
+
+include make.inc
+
+superludist: FAIT
+
+# FFCS: more dependencies for parallel builds
+FAIT:$(SRCDIR)
+	$(MAKE) FAIRE install WHERE
+	touch FAIT
+
+
+FAIRE: $(SRCDIR)/SRC/$(DSUPERLULIB)  
+	touch FAIRE
+
+make.inc: ../../config.status  Makefile
+	grep 'abs_top_builddir *=' ../Makefile >> dirflags
+	cat dirflags make-superlu.inc > make-superlu-tmp.inc
+	rm dirflags
+	../../config.status  --file="make.inc:make-superlu-tmp.inc"
+	case 'uname' in *CYGWIN_) cp make.inc Makefile.inn; sed "s/COPTIONS =/COPTIONS = -D__VC__/" <Makefile.inn > Makefile.in; rm Makefile.inn ;; esac
+	rm make-superlu-tmp.inc
+
+# FFCS: we need an error if make breaks
+$(SRCDIR)/SRC/$(DSUPERLULIB): $(SRCDIR)
+	cp make.inc $(SRCDIR)/make.inc
+	cd $(SRCDIR)/SRC && $(MAKE)
+# FFCS: we need more dependencies for parallel builds
+install:$(SRCDIR)/SRC/$(DSUPERLULIB)
+	mkdir -p $(SRCDIR)/$(INSTALL)/include/superludist
+	cp $(SRCDIR)/SRC/*.h  $(SRCDIR)/$(INSTALL)/include/superludist
+WHERE:
+	echo superlu_dist LD -L at DIR@/lib -lsuperlu_dist_3.0  >$(SRCDIR)/$(INSTALL)/lib/WHERE.superlu_dist
+	echo superlu_dist INCLUDE -I at DIR@/include/superludist  >> $(SRCDIR)/$(INSTALL)/lib/WHERE.superlu_dist
+
+
+$(SRCDIR): $(PACKAGE_PATH)
+	tar xvzf $(PACKAGE_PATH)
+	cd $(SRCDIR)/SRC/; patch -p1 < ../../superludist_2.3.patch
+	cd $(SRCDIR)/SRC/; patch -p3 < ../../superludist_3.0-printf.patch
+	cd $(SRCDIR)/SRC/; patch -p2 < ../../superludist_3.0-cast_warning.patch
+	cd $(SRCDIR)/SRC/; patch -p2 < ../../superludist_3.0-return_values.patch
+	cd $(SRCDIR)/SRC/; patch -p2 < ../../superludist_3.0-operation_undefined.patch
+	touch $(SRCDIR)
+
+$(PACKAGE_PATH):
+	../getall -o SuperLU_DIST -a
+
+# FFCS - make sure that all directories are cleaned. Thisis especially important under Windows because there is no
+# compilation dependencies control there (see [[file:c:/cygwin/home/alh/ffcs/dist/configure.ac::dependency_tracking]])
+
+clean:
+	-rm -rf SuperLU_DIST*
+	-rm  ../include/superludist/*.h
+	-rm -r ../include/superludist/
+	-rm -r ../lib/libsuperlu_dist*.a
+	-rm -r make.inc
+	-rm -rf FAIT FAIRE
diff --git a/download/superludist/make-superlu.inc b/download/superludist/make-superlu.inc
new file mode 100644
index 0000000..3152216
--- /dev/null
+++ b/download/superludist/make-superlu.inc
@@ -0,0 +1,41 @@
+# FFCS - let "make clean" work even if include file is not found
+-include $(abs_top_builddir)/download/headers-sparsesolver.inc
+#############################################
+#  FLAGS :: FREEFEM TO COMPILE SUPERLU_DIST
+#
+DSUPERLULIB     = $(abs_top_builddir)/download/lib/libsuperlu_dist_3.0.a
+
+BLASDEF	     	= $(FFBLASDEF)
+BLASLIB      	= @BLASLIBS@
+
+#
+#  The archiver and the flag(s) to use when building archive (library)
+#  If your system has no ranlib, set RANLIB = echo.
+#
+ARCH         	= @AR@
+ARCHFLAGS    	= @ARFLAGS@
+RANLIB       	= @RANLIB@
+
+############################################################################
+# C compiler setup
+CC           	= @MPICC@
+# CFLAGS should be set to be the C flags that include optimization
+# FFCS - problem with some return statements on MacOS
+# FFCS - -I MPI_INC_DIR required on MacOS 10.8 MacPorts+OpenMPI
+CFLAGS          = -Wreturn-type @CFLAGS@ -I @MPI_INC_DIR@
+# NOOPTS should be set to be the C flags that turn off any optimization
+NOOPTS		=  @CNOFLAGS@ 
+############################################################################
+# FORTRAN compiler setup
+FORTRAN         = @F77@
+FFLAGS 		= @FFLAGS@
+############################################################################
+LOADER	 = @CXX@
+LOADOPTS = 
+############################################################################
+#  C preprocessor defs for compilation (-DNoChange, -DAdd_, or -DUpCase)
+#
+#  Need follow the convention of how C calls a Fortran routine.
+#
+CDEFS        = @CFLAGSF77@
+WGET =@WGET@ 
\ No newline at end of file
diff --git a/download/superludist/superludist_2.3.patch b/download/superludist/superludist_2.3.patch
new file mode 100644
index 0000000..ece2dc8
--- /dev/null
+++ b/download/superludist/superludist_2.3.patch
@@ -0,0 +1,32 @@
+diff -ur SuperLU_DIST_2.3/SRC/Makefile SuperLU_DIST_2.3-okk/Makefile
+--- SuperLU_DIST_2.3/SRC/Makefile	2008-09-13 17:13:18.000000000 +0200
++++ SuperLU_DIST_2.3-okk/Makefile	2010-02-16 08:24:45.000000000 +0100
+@@ -51,6 +51,8 @@
+ ZSLUSRC	= dcomplex.o zlangs.o zgsequ.o zlaqgs.o zutil.o \
+ 	  zmemory.o zmyblas2.o dmemory.o zsp_blas2.o zsp_blas3.o
+ 
++#ZSLUSRCdemory= dmemory.o
++
+ #
+ # Routines for double precision parallel SuperLU
+ # DPLUSRC = dldperm.o ddistribute.o pdgstrf.o pdgstrs_Bglobal.o 
+@@ -69,7 +71,7 @@
+ 	  pzgsequ.o pzlaqgs.o pzgsrfs.o pzgsmv.o pzgstrs_lsum.o \
+ 	  pzsymbfact_distdata.o
+ 
+-all:  double complex16
++all:  doublecomplex16
+ 
+ double: $(DSLUSRC) $(DPLUSRC) $(ALLAUX) $(LAAUX)
+ 	$(ARCH) $(ARCHFLAGS) $(DSUPERLULIB) \
+@@ -81,6 +83,10 @@
+ 		$(ZSLUSRC) $(ZPLUSRC) $(ALLAUX) $(LAAUX)
+ 	$(RANLIB) $(DSUPERLULIB)
+ 
++doublecomplex16: $(DSLUSRC) $(DPLUSRC) $(ZSLUSRC) $(ZPLUSRC) $(ALLAUX) $(LAAUX)
++	$(ARCH) $(ARCHFLAGS) $(DSUPERLULIB) \
++		$(DSLUSRC) $(DPLUSRC) $(ZSLUSRC) $(ZPLUSRC) $(ALLAUX) $(LAAUX)
++	$(RANLIB) $(DSUPERLULIB)
+ 
+ ##################################
+ # Do not optimize these routines #
diff --git a/download/superludist/superludist_3.0-cast_warning.patch b/download/superludist/superludist_3.0-cast_warning.patch
new file mode 100644
index 0000000..389ddb6
--- /dev/null
+++ b/download/superludist/superludist_3.0-cast_warning.patch
@@ -0,0 +1,25 @@
+diff -ur SuperLU_DIST_3.0.orig/SRC/pdgstrf.c SuperLU_DIST_3.0/SRC/pdgstrf.c
+--- SuperLU_DIST_3.0.orig/SRC/pdgstrf.c	2011-10-11 20:45:40.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/pdgstrf.c	2013-02-13 12:51:45.691434748 +0000
+@@ -2597,7 +2597,7 @@
+ 		    MPI_Isend(ublk_ptr, u_diag_cnt, MPI_DOUBLE, pr,
+ 			      tag, comm, U_diag_blk_send_req + pr);
+ 		}
+-	    U_diag_blk_send_req[krow] = 1; /* flag outstanding Isend */
++	    U_diag_blk_send_req[krow] = (MPI_Request) 1; /* flag outstanding Isend */
+ 	}
+ 
+     } else  { /* non-diagonal process */
+Only in SuperLU_DIST_3.0/SRC: pdgstrf.o
+diff -ur SuperLU_DIST_3.0.orig/SRC/pzgstrf.c SuperLU_DIST_3.0/SRC/pzgstrf.c
+--- SuperLU_DIST_3.0.orig/SRC/pzgstrf.c	2011-10-11 20:45:40.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/pzgstrf.c	2013-02-13 12:54:00.212442635 +0000
+@@ -2543,7 +2543,7 @@
+ 		    MPI_Isend(ublk_ptr, u_diag_cnt, SuperLU_MPI_DOUBLE_COMPLEX, pr,
+ 			      tag, comm, U_diag_blk_send_req + pr);
+ 		}
+-	    U_diag_blk_send_req[krow] = 1; /* flag outstanding Isend */
++	    U_diag_blk_send_req[krow] = (MPI_Request) 1; /* flag outstanding Isend */
+ 	}
+ 
+     } else  { /* non-diagonal process */
diff --git a/download/superludist/superludist_3.0-operation_undefined.patch b/download/superludist/superludist_3.0-operation_undefined.patch
new file mode 100644
index 0000000..3cbff19
--- /dev/null
+++ b/download/superludist/superludist_3.0-operation_undefined.patch
@@ -0,0 +1,24 @@
+--- SuperLU_DIST_3.0/SRC/util.c.orig	2013-02-20 10:23:45.674505816 +0000
++++ SuperLU_DIST_3.0/SRC/util.c	2013-02-20 10:24:09.001507187 +0000
+@@ -662,8 +662,8 @@
+ 
+     do {
+ 	++(*num_diag_procs);
+-	i = (++i) % nprow;
+-	j = (++j) % npcol;
++	i = (i + 1) % nprow;
++	j = (j + 1) % npcol;
+ 	pkk = PNUM( i, j, grid );
+     } while ( pkk != 0 ); /* Until wrap back to process 0 */
+     if ( !(*diag_procs = intMalloc_dist(*num_diag_procs)) )
+@@ -673,8 +673,8 @@
+     for (i = j = k = 0; k < *num_diag_procs; ++k) {
+ 	pkk = PNUM( i, j, grid );
+ 	(*diag_procs)[k] = pkk;
+-	i = (++i) % nprow;
+-	j = (++j) % npcol;
++	i = (i + 1) % nprow;
++	j = (j + 1) % npcol;
+     }
+     for (k = 0; k < nsupers; ++k) {
+ 	knsupc = SuperSize( k );
diff --git a/download/superludist/superludist_3.0-printf.patch b/download/superludist/superludist_3.0-printf.patch
new file mode 100644
index 0000000..0de05df
--- /dev/null
+++ b/download/superludist/superludist_3.0-printf.patch
@@ -0,0 +1,10 @@
+--- ./SuperLU_DIST_3.0/SRC/xerbla.c.orig	2013-02-13 12:21:04.893027330 +0000
++++ ./SuperLU_DIST_3.0/SRC/xerbla.c	2013-02-13 12:21:22.677028381 +0000
+@@ -9,6 +9,7 @@
+ </pre> 
+ */
+ #include "Cnames.h"
++#include <stdio.h>
+ 
+ /* Subroutine */ 
+ /*! \brief
diff --git a/download/superludist/superludist_3.0-return_values.patch b/download/superludist/superludist_3.0-return_values.patch
new file mode 100644
index 0000000..a915882
--- /dev/null
+++ b/download/superludist/superludist_3.0-return_values.patch
@@ -0,0 +1,158 @@
+Only in SuperLU_DIST_3.0/SRC: 1
+diff -ur SuperLU_DIST_3.0.orig/SRC/dutil.c SuperLU_DIST_3.0/SRC/dutil.c
+--- SuperLU_DIST_3.0.orig/SRC/dutil.c	2011-09-06 00:16:34.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/dutil.c	2013-02-13 17:40:36.696123287 +0000
+@@ -185,6 +185,8 @@
+     if ( (dp = (double *) Astore->nzval) != NULL )
+         PrintDouble5("nzval", nnz_loc, dp);
+     printf("==== end CompRowLoc matrix\n");
++
++    return 0;
+ }
+ 
+ int file_dPrint_CompRowLoc_Matrix_dist(FILE *fp, SuperMatrix *A)
+@@ -205,6 +207,8 @@
+     if ( (dp = (double *) Astore->nzval) != NULL )
+         file_PrintDouble5(fp, "nzval", nnz_loc, dp);
+     fprintf(fp, "==== end CompRowLoc matrix\n");
++
++    return 0;
+ }
+ 
+ void
+@@ -355,6 +359,8 @@
+ 	fprintf(fp, "%14e", x[i]);
+     }
+     fprintf(fp, "\n");
++
++    return 0;
+ }
+ 
+ /*! \brief Print the blocks in the factored matrix L.
+@@ -461,6 +467,8 @@
+   file_PrintInt10(fp, "ptr_ind_torecv", procs+1, gsmv_comm->ptr_ind_torecv);
+   file_PrintInt10(fp, "SendCounts", procs, gsmv_comm->SendCounts);
+   file_PrintInt10(fp, "RecvCounts", procs, gsmv_comm->RecvCounts);
++
++  return 0;
+ }
+ 
+ 
+Binary files SuperLU_DIST_3.0.orig/SRC/dutil.o and SuperLU_DIST_3.0/SRC/dutil.o differ
+diff -ur SuperLU_DIST_3.0.orig/SRC/pddistribute.c SuperLU_DIST_3.0/SRC/pddistribute.c
+--- SuperLU_DIST_3.0.orig/SRC/pddistribute.c	2011-09-06 00:16:34.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/pddistribute.c	2013-02-13 17:44:50.198138179 +0000
+@@ -304,6 +304,8 @@
+     CHECK_MALLOC(iam, "Exit dReDistribute_A()");
+ #endif
+  
++    return 0;
++
+ } /* dReDistribute_A */
+ 
+ float
+Binary files SuperLU_DIST_3.0.orig/SRC/pddistribute.o and SuperLU_DIST_3.0/SRC/pddistribute.o differ
+diff -ur SuperLU_DIST_3.0.orig/SRC/psymbfact.c SuperLU_DIST_3.0/SRC/psymbfact.c
+--- SuperLU_DIST_3.0.orig/SRC/psymbfact.c	2011-09-06 00:16:34.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/psymbfact.c	2013-02-13 17:47:47.931004764 +0000
+@@ -2267,6 +2267,8 @@
+   
+   for (i = fstVtx_toUpd; i < nvtcs_toUpd; i++)
+     marker[i] = 0;
++
++    return 0;
+ }
+ 
+ static int_t
+@@ -4005,6 +4007,8 @@
+   if (newelts_U) SUPERLU_FREE (newelts_U);
+   if (PS->szDnsSep < mem_dnsCS)
+     PS->szDnsSep = mem_dnsCS;
++
++  return 0;
+ }
+ 
+ /*! \brief
+@@ -4534,6 +4538,8 @@
+   if (request_snd != NULL) SUPERLU_FREE (request_snd);
+   if (request_rcv != NULL) SUPERLU_FREE (request_rcv);
+   if (status != NULL) SUPERLU_FREE (status);
++
++  return 0;
+ }
+ 
+ static void
+Binary files SuperLU_DIST_3.0.orig/SRC/psymbfact.o and SuperLU_DIST_3.0/SRC/psymbfact.o differ
+diff -ur SuperLU_DIST_3.0.orig/SRC/pzdistribute.c SuperLU_DIST_3.0/SRC/pzdistribute.c
+--- SuperLU_DIST_3.0.orig/SRC/pzdistribute.c	2011-09-06 00:16:34.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/pzdistribute.c	2013-02-13 17:53:06.269023492 +0000
+@@ -303,6 +303,7 @@
+     CHECK_MALLOC(iam, "Exit zReDistribute_A()");
+ #endif
+  
++    return 0;
+ } /* zReDistribute_A */
+ 
+ float
+Binary files SuperLU_DIST_3.0.orig/SRC/pzdistribute.o and SuperLU_DIST_3.0/SRC/pzdistribute.o differ
+diff -ur SuperLU_DIST_3.0.orig/SRC/util.c SuperLU_DIST_3.0/SRC/util.c
+--- SuperLU_DIST_3.0.orig/SRC/util.c	2011-10-11 21:14:16.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/util.c	2013-02-13 17:54:31.042028470 +0000
+@@ -490,6 +490,7 @@
+     gstrs_comm->ptr_to_ibuf = ptr_to_ibuf;
+     gstrs_comm->ptr_to_dbuf = ptr_to_ibuf + procs;
+ 
++    return 0;
+ } /* PXGSTRS_INIT */
+ 
+ 
+@@ -763,6 +764,8 @@
+ 	fprintf(fp, "%6d", x[i]);
+     }
+     fprintf(fp, "\n");
++
++    return 0;
+ }
+ 
+ int_t
+Binary files SuperLU_DIST_3.0.orig/SRC/util.o and SuperLU_DIST_3.0/SRC/util.o differ
+diff -ur SuperLU_DIST_3.0.orig/SRC/zutil.c SuperLU_DIST_3.0/SRC/zutil.c
+--- SuperLU_DIST_3.0.orig/SRC/zutil.c	2011-09-06 00:16:34.000000000 +0000
++++ SuperLU_DIST_3.0/SRC/zutil.c	2013-02-13 17:56:24.618035143 +0000
+@@ -184,6 +184,8 @@
+     if ( (dp = (doublecomplex *) Astore->nzval) != NULL )
+         PrintDoublecomplex("nzval", nnz_loc, dp);
+     printf("==== end CompRowLoc matrix\n");
++
++    return 0;
+ }
+ 
+ int file_zPrint_CompRowLoc_Matrix_dist(FILE *fp, SuperMatrix *A)
+@@ -204,6 +206,8 @@
+     if ( (dp = (doublecomplex *) Astore->nzval) != NULL )
+         file_PrintDoublecomplex(fp, "nzval", nnz_loc, dp);
+     fprintf(fp, "==== end CompRowLoc matrix\n");
++
++    return 0;
+ }
+ 
+ void
+@@ -351,6 +355,8 @@
+     fprintf(fp, "%10s:\tReal\tImag\n", name);
+     for (i = 0; i < len; ++i)
+ 	fprintf(fp, "\t%d\t%.4f\t%.4f\n", i, x[i].r, x[i].i);
++
++    return 0;
+ }
+ 
+ /*! \brief Print the blocks in the factored matrix L.
+@@ -457,6 +463,8 @@
+   file_PrintInt10(fp, "ptr_ind_torecv", procs+1, gsmv_comm->ptr_ind_torecv);
+   file_PrintInt10(fp, "SendCounts", procs, gsmv_comm->SendCounts);
+   file_PrintInt10(fp, "RecvCounts", procs, gsmv_comm->RecvCounts);
++
++  return 0;
+ }
+ 
+ 
+Binary files SuperLU_DIST_3.0.orig/SRC/zutil.o and SuperLU_DIST_3.0/SRC/zutil.o differ
diff --git a/download/tetgen/Makefile b/download/tetgen/Makefile
new file mode 100755
index 0000000..b6f376e
--- /dev/null
+++ b/download/tetgen/Makefile
@@ -0,0 +1,79 @@
+# and compiling extra libraries
+# -----------------------------------------
+
+include cxxflags
+all-local: tetgen
+
+# Downloading and compiling Tetgen
+# ------------------------------
+
+# Tetgen information
+DIRPKG=../pkg
+tetgen_VERSION=1.4.3
+SRCDIR=tetgen$(tetgen_VERSION)
+PACKAGE=$(DIRPKG)/tetgen$(tetgen_VERSION).tar.gz
+
+# FFCS - 6/11/12 - curl is not able to follow redirections from http://tetgen.org/files
+SERVER=http://wias-berlin.de/software/tetgen/files
+
+INSTALL=../..
+
+tetgen: FAIRE 
+
+
+FAIRE:install.done $(SRCDIR)/FAIT cxxflags WHERE.done
+	touch FAIRE
+
+
+# ALH - FFCS - 18/12/8 - need '-fPIC' on Linux64 because the .a will be used in a .so (by examples++-load/tetgen.cpp).
+
+# FFCS - 30/11/10 - need ranlib on Win64. The PATH is setup so that mingw/ranlib is called
+
+$(SRCDIR)/FAIT: $(SRCDIR)/tags  cxxflags 
+	cd $(SRCDIR);$(CXX) $(CXXFLAGS) -fPIC -DSELF_CHECK  -DNDEBUG -DTETLIBRARY -c tetgen.cxx
+	cd $(SRCDIR);$(CXX) $(CXXFLAGS) -fPIC -DSELF_CHECK  -DNDEBUG -DTETLIBRARY -c predicates.cxx
+	touch $(SRCDIR)/FAIT
+WHERE.done: $(SRCDIR)/FAIT
+	echo tetgen LD -L at DIR@/lib -ltet  >$(SRCDIR)/$(INSTALL)/lib/WHERE.tetgen
+	echo tetgen  INCLUDE -I at DIR@/include >> $(SRCDIR)/$(INSTALL)/lib/WHERE.tetgen
+	touch $@
+clean-local::
+	-rm WHERE.done
+
+# FFCS - avoid remaking install every time
+install.done:$(SRCDIR)/FAIT
+	cd $(SRCDIR);$(AR) $(ARFLAGS)  $(INSTALL)/lib/libtet.a tetgen.o predicates.o
+	ranlib $(SRCDIR)/$(INSTALL)/lib/libtet.a
+	cp $(SRCDIR)/tetgen.h $(SRCDIR)/$(INSTALL)/include 
+	touch $@
+clean-local::
+	-rm install.done
+
+
+$(SRCDIR)/tags: $(PACKAGE)
+	tar xvzf $(PACKAGE)
+#       FFCS: needs to patch tetgen because mingw64 has 4-byte longs
+	cd tetgen1.4.3 && patch -u -p1 < ../patches.win64
+	touch $(SRCDIR)/tags
+#	cd tetgen1.4.2;patch -p1 <../tetgen1.4.2.patch 
+
+$(PACKAGE):
+	../getall -o TetGen -a
+
+clean-local::
+	-rm -rf tetgen1.4.?  FAIT FAIRE 
+clean:
+	-rm $(SRCDIR)/$(INSTALL)/lib/libtet.a
+	-rm $(SRCDIR)/$(INSTALL)/include/tetgen.h
+	-rm FAIT
+	-rm -rf tetgen1.4.?
+cxxflags: ../Makefile  Makefile
+	grep 'CXX *=' ../Makefile >cxxflags
+	grep 'CC *=' ../Makefile >>cxxflags
+#	FFCS - 10/5/12 - bug under Windows if -O3 is specified tetgen never returns. It could also be the case under
+#	Ubuntu. All optimisation options are removed for safety.
+	grep 'CXXFLAGS *=' ../Makefile | sed 's/ -O[0-9]* / /g'  >>cxxflags
+	grep 'WGET *=' ../Makefile >>cxxflags
+	grep 'AR *=' ../Makefile >>cxxflags
+	grep 'ARFLAGS *=' ../Makefile >>cxxflags
+.PHONY:$(SRCDIR)/$(INSTALL)
\ No newline at end of file
diff --git a/download/tetgen/patches.win64 b/download/tetgen/patches.win64
new file mode 100644
index 0000000..55630d8
--- /dev/null
+++ b/download/tetgen/patches.win64
@@ -0,0 +1,104 @@
+# -*- mode:diff;coding:raw-text; -*-
+diff -u -p1 /home/alh/tmp/tetgen1.4.3/tetgen.cxx tetgen1.4.3/tetgen.cxx
+--- /home/alh/tmp/tetgen1.4.3/tetgen.cxx	2009-12-13 22:21:08.000000000 +0100
++++ tetgen1.4.3/tetgen.cxx	2010-11-24 15:47:44.253943800 +0100
+@@ -4844,3 +4844,3 @@ void tetgenmesh::dummyinit(int tetwords,
+ {
+-  unsigned long alignptr;
++  unsigned FFCSLONG alignptr;
+ 
+@@ -4850,3 +4850,3 @@ void tetgenmesh::dummyinit(int tetwords,
+   // Align 'dummytet' on a 'tetrahedrons->alignbytes'-byte boundary.
+-  alignptr = (unsigned long) dummytetbase;
++  alignptr = (unsigned FFCSLONG) dummytetbase;
+   dummytet = (tetrahedron *)
+@@ -4875,3 +4875,3 @@ void tetgenmesh::dummyinit(int tetwords,
+     // Align 'dummysh' on a 'subfaces->alignbytes'-byte boundary.
+-    alignptr = (unsigned long) dummyshbase;
++    alignptr = (unsigned FFCSLONG) dummyshbase;
+     dummysh = (shellface *)
+@@ -15082,3 +15082,3 @@ void tetgenmesh::btree_insert(point inse
+   point *ptary;
+-  long arylen; // The array lenhgth is saved in ptary[0].
++  FFCSLONG arylen; // The array lenhgth is saved in ptary[0].
+ 
+@@ -15087,3 +15087,3 @@ void tetgenmesh::btree_insert(point inse
+   // Get the current array length.
+-  arylen = (long) ptary[0];
++  arylen = (FFCSLONG) ptary[0];
+   // Insert the point into the node.
+@@ -15106,3 +15106,3 @@ void tetgenmesh::btree_search(point inse
+   int ptsamples, ptidx;
+-  long arylen;
++  FFCSLONG arylen;
+   int i;
+@@ -15112,3 +15112,3 @@ void tetgenmesh::btree_search(point inse
+   // Get the current array length.
+-  arylen = (long) ptary[0];
++  arylen = (FFCSLONG) ptary[0];
+ 
+@@ -15165,3 +15165,3 @@ void tetgenmesh::ordervertices(point* ve
+   point *ptary;
+-  long arylen;
++  FFCSLONG arylen;
+   int index, i, j;
+@@ -15186,3 +15186,3 @@ void tetgenmesh::ordervertices(point* ve
+     ptary = *jpptary;
+-    arylen = (long) ptary[0];
++    arylen = (FFCSLONG) ptary[0];
+     for (j = 2; j <= arylen; j++) { // Skip the first point.
+@@ -21031,3 +21031,3 @@ bool tetgenmesh::delaunizecavity(arraypo
+             printf("    Queue a subface x%lx (%d, %d, %d).\n", 
+-              (unsigned long) checksh.sh, pointmark(sorg(checksh)),
++              (unsigned FFCSLONG) checksh.sh, pointmark(sorg(checksh)),
+               pointmark(sdest(checksh)), pointmark(sapex(checksh)));
+@@ -21081,3 +21081,3 @@ bool tetgenmesh::delaunizecavity(arraypo
+                 printf("    Queue a subface x%lx (%d, %d, %d).\n", 
+-                  (unsigned long) checksh.sh, pointmark(sorg(checksh)),
++                  (unsigned FFCSLONG) checksh.sh, pointmark(sorg(checksh)),
+                   pointmark(sdest(checksh)), pointmark(sapex(checksh)));
+@@ -23474,3 +23474,3 @@ bool tetgenmesh::carvecavity(list* newte
+               printf("    Intet x%lx %d (%d, %d, %d, %d) is iversed.\n", 
+-                (unsigned long) intet.tet, intet.loc, pointmark(pa),
++                (unsigned FFCSLONG) intet.tet, intet.loc, pointmark(pa),
+                 pointmark(pb), pointmark(pc), pointmark(oppo(intet)));
+@@ -23544,3 +23544,3 @@ bool tetgenmesh::carvecavity(list* newte
+             pointmark(org(neightet)), pointmark(dest(neightet)),
+-            pointmark(apex(neightet)), (unsigned long) auxsh.sh);
++            pointmark(apex(neightet)), (unsigned FFCSLONG) auxsh.sh);
+           printf("  p:draw_tet(%d, %d, %d, %d) -- in\n",
+@@ -33711,5 +33711,5 @@ int tetgenmesh::checksegments()
+             printf("    Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n", 
+-              (unsigned long) tetloop.tet, pointmark(org(tetloop)),
++              (unsigned FFCSLONG) tetloop.tet, pointmark(org(tetloop)),
+               pointmark(dest(tetloop)), pointmark(apex(tetloop)),
+-              pointmark(oppo(tetloop)), (unsigned long) sseg.sh,
++              pointmark(oppo(tetloop)), (unsigned FFCSLONG) sseg.sh,
+               pointmark(pa), pointmark(pb));
+@@ -33725,3 +33725,3 @@ int tetgenmesh::checksegments()
+                 printf("    Tet: x%lx (%d, %d, %d, %d) - ", 
+-                  (unsigned long) tetloop.tet, pointmark(org(tetloop)),
++                  (unsigned FFCSLONG) tetloop.tet, pointmark(org(tetloop)),
+                   pointmark(dest(tetloop)), pointmark(apex(tetloop)),
+@@ -33729,3 +33729,3 @@ int tetgenmesh::checksegments()
+                 if (checkseg.sh != NULL) {
+-                  printf("Seg x%lx (%d, %d).\n", (unsigned long) checkseg.sh,
++                  printf("Seg x%lx (%d, %d).\n", (unsigned FFCSLONG) checkseg.sh,
+                   pointmark(sorg(checkseg)), pointmark(sdest(checkseg))); 
+diff -u -p1 /home/alh/tmp/tetgen1.4.3/tetgen.h tetgen1.4.3/tetgen.h
+--- /home/alh/tmp/tetgen1.4.3/tetgen.h	2009-12-13 22:20:33.000000000 +0100
++++ tetgen1.4.3/tetgen.h	2010-11-24 15:43:52.687137100 +0100
+@@ -3318,5 +3318,12 @@ inline bool tetgenmesh::isfacehasedge(fa
+ 
++// FFCS: mingw64 compiler refuses to convert 8-byte pointers to 4-byte longs
++#ifdef WIN64
++#define FFCSLONG long long
++#else
++#define FFCSLONG long
++#endif
++
+ inline bool tetgenmesh::issymexist(triface* t) {
+   tetrahedron *ptr = (tetrahedron *) 
+-    ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
++    ((unsigned FFCSLONG)(t->tet[t->loc]) & ~(unsigned FFCSLONG)7l);
+   return ptr != dummytet;
diff --git a/download/tetgen/tetgen1.4.2.patch b/download/tetgen/tetgen1.4.2.patch
new file mode 100644
index 0000000..a2dcf15
--- /dev/null
+++ b/download/tetgen/tetgen1.4.2.patch
@@ -0,0 +1,41 @@
+diff -ur tetgen1.4.2/tetgen.cxx tetgen1.4.2-okk/tetgen.cxx
+--- tetgen1.4.2/tetgen.cxx	2007-04-16 16:45:11.000000000 +0200
++++ tetgen1.4.2-okk/tetgen.cxx	2009-05-25 10:37:19.000000000 +0200
+@@ -3506,7 +3506,7 @@
+ //                                                                           //
+ ///////////////////////////////////////////////////////////////////////////////
+ 
+-void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
++void tetgenmesh::set_compfunc(const char* str, int* itbytes, compfunc* pcomp)
+ {
+   // First figure out whether it is a pointer or not.
+   if (str[strlen(str) - 1] == '*') {
+@@ -25978,6 +25978,7 @@
+   }
+   delete [] oldtetlist;
+   delete [] newtetlist;
++  delete [] newpt; // Add by J. Morice for FreeFem++ (missing delete) Nov 2008
+   // Clear work lists.
+   newsegshlist->clear();
+   spinshlist->clear();
+diff -ur tetgen1.4.2/tetgen.h tetgen1.4.2-okk/tetgen.h
+--- tetgen1.4.2/tetgen.h	2007-04-16 16:45:13.000000000 +0200
++++ tetgen1.4.2-okk/tetgen.h	2009-05-25 10:37:41.000000000 +0200
+@@ -980,7 +980,7 @@
+ 
+     // The function used to determine the size of primitive data types and
+     //   set the corresponding predefined linear order functions for them.
+-    static void set_compfunc(char* str, int* itembytes, compfunc* pcomp);
++    static void set_compfunc(const char* str, int* itembytes, compfunc* pcomp);
+ 
+ ///////////////////////////////////////////////////////////////////////////////
+ //                                                                           //
+@@ -1021,7 +1021,7 @@
+         list(int itbytes, compfunc pcomp, int mitems = 256, int exsize = 128) {
+           listinit(itbytes, pcomp, mitems, exsize);
+         }
+-        list(char* str, int mitems = 256, int exsize = 128) {
++        list(const char* str, int mitems = 256, int exsize = 128) {
+           set_compfunc(str, &itembytes, &comp);
+           listinit(itembytes, comp, mitems, exsize);
+         }
diff --git a/download/umfpack/Makefile.am b/download/umfpack/Makefile.am
new file mode 100644
index 0000000..fa459a7
--- /dev/null
+++ b/download/umfpack/Makefile.am
@@ -0,0 +1,175 @@
+# Downloading and compiling extra libraries for Umfpack
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh brief="Downloading and compiling extra libraries for Umfpack" default=0 freefem make multipleauthors start=04/06/04 upmc
+
+# see [[file:../../configure.ac::DOWNLOAD_UMFPACK]]
+all-local: $(DOWNLOAD_UMFPACK)
+EXTRA_DIST= SuiteSparse_config.mk.in 
+
+# Downloading and compiling UMFPACK
+# ---------------------------------
+
+DIRPKG=../pkg
+SUITESPARSE_TGZ=$(DIRPKG)/SuiteSparse-4.3.1.tar.gz
+
+UMFPACKLIB=../lib/libumfpack.a 
+AMDLIB=../lib/libamd.a
+CAMDLIB=../lib/libcamd.a
+CHOLMODLIB=../lib/libcholmod.a
+COLAMDLIB=../lib/libcolamd.a
+SUITESPARSECONFIGLIB=../lib/libsuitesparseconfig.a
+
+# ALH - 4/9/13 - parallel make crashes ("pipe from processes is a directory"?). make sure that everything is run
+# sequentially
+
+umfpack:
+	$(MAKE) MAKEFLAGS= $(AMDLIB)
+	$(MAKE) MAKEFLAGS= $(UMFPACKLIB)
+	$(MAKE) MAKEFLAGS= $(SUITESPARSECONFIGLIB)
+#
+# ALH - 19/9/13 - cholmod part built sequentially
+#
+	$(MAKE) MAKEFLAGS= $(CAMDLIB)
+	$(MAKE) MAKEFLAGS= $(COLAMDLIB)
+	$(MAKE) MAKEFLAGS= $(AMDLIB)
+	$(MAKE) MAKEFLAGS= $(CHOLMODLIB)
+	$(MAKE) MAKEFLAGS= $(SUITESPARSECONFIGLIB) 
+
+# FFCS: SuiteSparse/*/Source are not able to compile in parallel from scratch ("pipe from processes is a
+# directory"?). But specifying "make -j 1" is not enough (another error pops up). Use "$(MAKE) MAKEFLAGS=" instead
+# (using "make MAKEFLAGS=" still produces an error on Cygwin).
+
+$(SUITESPARSECONFIGLIB): SuiteSparse/FF 
+	cd SuiteSparse/SuiteSparse_config && $(MAKE) MAKEFLAGS=
+	mkdir -p ../include ../lib
+	cp -f SuiteSparse/SuiteSparse_config/SuiteSparse_config.h  ../include
+	cp  SuiteSparse/SuiteSparse_config/libsuitesparseconfig.a ../lib/libsuitesparseconfig.a
+	$(RANLIB) ../lib/libsuitesparseconfig.a
+
+$(UMFPACKLIB): SuiteSparse/FF 
+	cd SuiteSparse/UMFPACK/Lib && $(MAKE) MAKEFLAGS=
+	mkdir -p ../include ../lib
+	cp -f  SuiteSparse/UMFPACK/Include/*.h ../include
+	cp -f SuiteSparse/SuiteSparse_config/SuiteSparse_config.h  ../include
+	cp  SuiteSparse/UMFPACK/Lib/libumfpack.a ../lib/libumfpack.a
+	$(RANLIB) ../lib/libumfpack.a
+
+$(AMDLIB): SuiteSparse/FF 
+	cd SuiteSparse/AMD/Lib && $(MAKE) MAKEFLAGS=
+	mkdir -p ../include ../lib
+	cp -f  SuiteSparse/AMD/Include/*.h ../include
+	cp  SuiteSparse/AMD/Lib/libamd.a ../lib/libamd.a
+	$(RANLIB) ../lib/libamd.a
+
+$(CAMDLIB): SuiteSparse/FF 
+	cd SuiteSparse/CAMD/Lib && $(MAKE) MAKEFLAGS=
+	mkdir -p ../include ../lib
+	cp -f  SuiteSparse/CAMD/Include/*.h ../include
+	cp  SuiteSparse/CAMD/Lib/libcamd.a ../lib/libcamd.a
+	$(RANLIB) ../lib/libcamd.a
+
+$(CHOLMODLIB): SuiteSparse/FF 
+	cd SuiteSparse/CHOLMOD/Lib && $(MAKE) MAKEFLAGS=
+	mkdir -p ../include ../lib
+	cp -f  SuiteSparse/CHOLMOD/Include/*.h ../include
+	cp  SuiteSparse/CHOLMOD/Lib/libcholmod.a ../lib/libcholmod.a
+	$(RANLIB) ../lib/libcholmod.a
+
+$(COLAMDLIB): SuiteSparse/FF 
+	cd SuiteSparse/COLAMD/Lib && $(MAKE) MAKEFLAGS=
+	mkdir -p ../include ../lib
+	cp -f  SuiteSparse/COLAMD/Include/*.h ../include
+	cp  SuiteSparse/COLAMD/Lib/libcolamd.a ../lib/libcolamd.a
+	$(RANLIB) ../lib/libcolamd.a
+
+UMFPACKv4.4:
+	tar xzf UMFPACKv4.4.tar.gz
+
+# The 'lib' goal is replaced with 'libb' to avoid problems with the existing 'Lib' subdirectory on case-insensitive file
+# systems the lib depend of the Makefile to force the reconstruction if the parameter change
+
+UMFPACKv4.4/AMD/Makefile2 UMFPACKv4.4/UMFPACK/Makefile2: UMFPACKv4.4  
+	sed 's/lib:/libb:/' < UMFPACKv4.4/UMFPACK/`basename $@ 2`  >$@
+
+SuiteSparse/DATE:$(SUITESPARSE_TGZ)
+	tar zxvf $(SUITESPARSE_TGZ)
+	touch SuiteSparse/DATE
+
+SuiteSparse/FF:SuiteSparse/DATE  SuiteSparse/SuiteSparse_config/SuiteSparse_config.mk
+	touch SuiteSparse/FF
+
+SuiteSparse/SuiteSparse_config/SuiteSparse_config.mk:SuiteSparse/DATE Makefile SuiteSparse_config.mk.in
+	../../config.status  --file="SuiteSparse_config.mk:SuiteSparse_config.mk.in"
+	-if  diff SuiteSparse_config.mk SuiteSparse/SuiteSparse_config/SuiteSparse_config.mk  2>&1 >/dev/null; then \
+	    echo " same flags => no recompilation !  " ; \
+	else \
+	   echo "  recompile umfpack (some flags change) => clean umfpack colmod amd " ;\
+	   mkdir -p SuiteSparse/SuiteSparse_config ;\
+	   cp SuiteSparse_config.mk SuiteSparse/SuiteSparse_config/SuiteSparse_config.mk ; \
+	   (cd SuiteSparse/UMFPACK && make clean); \
+	   (cd SuiteSparse/CHOLMOD && make clean); \
+	   (cd SuiteSparse/COLAMD && make clean); \
+	   (cd SuiteSparse/CAMD && make clean); \
+	   (cd SuiteSparse/CAMD && make clean); \
+	   (cd SuiteSparse/AMD && make clean); \
+	   find . -name '*.exe'|xargs rm;  \
+	fi; 
+	touch SuiteSparse/SuiteSparse_config/SuiteSparse_config.mk
+
+UMFPACK_Make.m4: Makefile UMFPACKv4.4
+	m4   -DFF_CC="$(CC)" \
+             -DFF_CFLAGS="@CPPFLAGS@ @CFLAGS@ @BLASINC@" \
+             -DFF_LIB="@BLASLIB@ @LIBS@" \
+	     -DFF_CONFIG="@FF_UMFPACK_CONFIG@" \
+              UMFPACK_Make.m4 >Make.include
+	-if  diff Make.include UMFPACKv4.4/UMFPACK/Make/Make.include 2>&1 >/dev/null; then \
+	    echo " same flags => no recompilation !  " ; \
+	else \
+	   echo "  recompile umfpack (some flags change) => clean umfpack" ;\
+	   cp Make.include  UMFPACKv4.4/UMFPACK/Make/Make.include; \
+	   cd UMFPACKv4.4/UMFPACK && make clean; \
+	   find . -name '*.exe'|xargs rm; \
+	fi; 
+UMFPACKv4.4.tar.gz:
+	@WGET@ -N http://www.cise.ufl.edu/research/sparse/umfpack/v4.4/UMFPACKv4.4.tar.gz
+$(SUITESPARSE_TGZ):
+	../getall -o SuiteSparse -a
+
+clean-local:
+	-rm $(AMDLIB) $(CAMDLIB) $(CHOLMODLIB) $(COLAMDLIB) $(SUITESPARSECONFIGLIB)
+	-rm ../include/amd*.h 
+	-rm ../include/umfpack*.h 
+	-rm ../include/colmod*.h 
+	-rm ../include/camd*.h 
+	-rm ../include/amd*.h
+	-rm ../include/SuiteSparse_config.h 
+	-rm -rf UMFPACKv4.?.tar.gz UMFPACKv4.?
+	-rm SuiteSparse*gz 
+	-rm -rf SuiteSparse
+	-rm ../pkg/SuiteSparse-*
+	-rm SuiteSparse_config.mk
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/download/umfpack/SuiteSparse_config.mk.in b/download/umfpack/SuiteSparse_config.mk.in
new file mode 100644
index 0000000..11e8dbd
--- /dev/null
+++ b/download/umfpack/SuiteSparse_config.mk.in
@@ -0,0 +1,396 @@
+#===============================================================================
+# SuiteSparse_config.mk:  common configuration file for the SuiteSparse
+#===============================================================================
+
+# This file contains all configuration settings for all packages authored or
+# co-authored by Tim Davis:
+#
+# Package Version       Description
+# ------- -------       -----------
+# AMD	  1.2 or later  approximate minimum degree ordering
+# COLAMD  2.4 or later  column approximate minimum degree ordering
+# CCOLAMD 1.0 or later  constrained column approximate minimum degree ordering
+# CAMD    any		constrained approximate minimum degree ordering
+# UMFPACK 4.5 or later	sparse LU factorization, with the BLAS
+# CHOLMOD any		sparse Cholesky factorization, update/downdate
+# KLU	  0.8 or later  sparse LU factorization, BLAS-free
+# BTF	  0.8 or later  permutation to block triangular form
+# LDL	  1.2 or later	concise sparse LDL'
+# CXSparse any		extended version of CSparse (int/long, real/complex)
+# SuiteSparseQR	any	sparse QR factorization
+# RBio    2.0 or later  read/write sparse matrices in Rutherford-Boeing format
+#
+# By design, this file is NOT included in the CSparse makefile.
+# That package is fully stand-alone.  CSparse is primarily for teaching;
+# production code should use CXSparse.
+#
+# The SuiteSparse_config directory and the above packages should all appear in
+# a single directory, in order for the Makefile's within each package to find
+# this file.
+#
+# To enable an option of the form "# OPTION = ...", edit this file and
+# delete the "#" in the first column of the option you wish to use.
+#
+# The use of METIS 4.0.1 is optional.  To exclude METIS, you must compile with
+# CHOLMOD_CONFIG set to -DNPARTITION.  See below for details.  However, if you
+# do not have a metis-4.0 directory inside the SuiteSparse directory, the
+# */Makefile's that optionally rely on METIS will automatically detect this
+# and compile without METIS.
+
+#------------------------------------------------------------------------------
+# Generic configuration
+#------------------------------------------------------------------------------
+
+# Using standard definitions from the make environment, typically:
+#
+#   CC              cc      C compiler
+#   CXX             g++     C++ compiler
+#   CFLAGS          [ ]     flags for C and C++ compiler
+#   CPPFLAGS        [ ]     flags for C and C++ compiler
+#   TARGET_ARCH     [ ]     target architecture
+#   FFLAGS          [ ]     flags for Fortran compiler
+#   RM              rm -f   delete a file
+#   AR              ar      create a static *.a library archive
+#   ARFLAGS         rv      flags for ar
+#   MAKE            make    make itself (sometimes called gmake)
+#
+# You can redefine them here, but by default they are used from the
+# default make environment.
+
+# C and C++ compiler flags.  The first three are standard for *.c and *.cpp
+# Add -DNTIMER if you do use any timing routines (otherwise -lrt is required).
+# CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC -DNTIMER
+  CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O3 -fexceptions -fPIC -DNTIMER
+
+# ranlib, and ar, for generating libraries.  If you don't need ranlib,
+# just change it to RANLAB = echo
+AR = @AR@ 
+RANLIB = @RANLIB@
+ARFLAGS =@ARFLAGS@
+
+ARCHIVE = $(AR) $(ARFLAGS)
+
+# copy and delete a file
+CP = cp -f
+MV = mv -f
+
+# Fortran compiler (not required for 'make' or 'make library')
+F77 = gfortran
+F77FLAGS = $(FFLAGS) -O
+F77LIB =
+
+# C and Fortran libraries.  Remove -lrt if you don't have it.
+  LIB = -lm 
+# Using the following requires CF = ... -DNTIMER on POSIX C systems.
+# LIB = -lm
+
+# For "make install"
+INSTALL_LIB = @abs_srcdir@/../lib
+INSTALL_INCLUDE = @abs_srcdir@/../include
+
+# Which version of MAKE you are using (default is "make")
+# MAKE = make
+# MAKE = gmake
+
+#------------------------------------------------------------------------------
+# BLAS and LAPACK configuration:
+#------------------------------------------------------------------------------
+
+# UMFPACK and CHOLMOD both require the BLAS.  CHOLMOD also requires LAPACK.
+# See Kazushige Goto's BLAS at http://www.cs.utexas.edu/users/flame/goto/ or
+# http://www.tacc.utexas.edu/~kgoto/ for the best BLAS to use with CHOLMOD.
+# LAPACK is at http://www.netlib.org/lapack/ .  You can use the standard
+# Fortran LAPACK along with Goto's BLAS to obtain very good performance.
+# CHOLMOD gets a peak numeric factorization rate of 3.6 Gflops on a 3.2 GHz
+# Pentium 4 (512K cache, 4GB main memory) with the Goto BLAS, and 6 Gflops
+# on a 2.5Ghz dual-core AMD Opteron.
+
+# These settings will probably not work, since there is no fixed convention for
+# naming the BLAS and LAPACK library (*.a or *.so) files.
+
+# This is probably slow ... it might connect to the Standard Reference BLAS:
+BLAS = @BLASLIBS@
+LAPACK = @LAPACKLIBS@
+
+# NOTE: this next option for the "Goto BLAS" has nothing to do with a "goto"
+# statement.  Rather, the Goto BLAS is written by Dr. Kazushige Goto.
+# Using the Goto BLAS:
+# BLAS = -lgoto -lgfortran -lgfortranbegin
+# BLAS = -lgoto2 -lgfortran -lgfortranbegin -lpthread
+
+# Using non-optimized versions:
+# BLAS = -lblas_plain -lgfortran -lgfortranbegin
+# LAPACK = -llapack_plain
+
+# BLAS = -lblas_plain -lgfortran -lgfortranbegin
+# LAPACK = -llapack
+
+# The BLAS might not contain xerbla, an error-handling routine for LAPACK and
+# the BLAS.  Also, the standard xerbla requires the Fortran I/O library, and
+# stops the application program if an error occurs.  A C version of xerbla
+# distributed with this software (SuiteSparse_config/xerbla/libcerbla.a)
+# includes a Fortran-callable xerbla routine that prints nothing and does not
+# stop the application program.  This is optional.
+
+# XERBLA = ../../SuiteSparse_config/xerbla/libcerbla.a 
+
+# If you wish to use the XERBLA in LAPACK and/or the BLAS instead,
+# use this option:
+XERBLA = 
+
+# If you wish to use the Fortran SuiteSparse_config/xerbla/xerbla.f instead,
+# use this:
+
+# XERBLA = ../../SuiteSparse_config/xerbla/libxerbla.a 
+
+#------------------------------------------------------------------------------
+# GPU configuration for CHOLMOD, using the CUDA BLAS
+#------------------------------------------------------------------------------
+
+# no cuda
+GPU_BLAS_PATH =
+GPU_CONFIG =
+
+# with cuda BLAS acceleration for CHOLMOD
+# GPU_BLAS_PATH=/usr/local/cuda
+# GPU_CONFIG=-DGPU_BLAS -I$(GPU_BLAS_PATH)/include
+
+#------------------------------------------------------------------------------
+# METIS, optionally used by CHOLMOD
+#------------------------------------------------------------------------------
+
+# If you do not have METIS, or do not wish to use it in CHOLMOD, you must
+# compile CHOLMOD with the -DNPARTITION flag.
+
+# The path is relative to where it is used, in CHOLMOD/Lib, CHOLMOD/MATLAB, etc.
+# You may wish to use an absolute path.  METIS is optional.  Compile
+# CHOLMOD with -DNPARTITION if you do not wish to use METIS.
+METIS_PATH = ../../metis-4.0
+METIS = ../../metis-4.0/libmetis.a
+
+#------------------------------------------------------------------------------
+# UMFPACK configuration:
+#------------------------------------------------------------------------------
+
+# Configuration flags for UMFPACK.  See UMFPACK/Source/umf_config.h for details.
+#
+# -DNBLAS	do not use the BLAS.  UMFPACK will be very slow.
+# -D'LONGBLAS=long' or -DLONGBLAS='long long' defines the integers used by
+#  		LAPACK and the BLAS (defaults to 'int')
+# -DNSUNPERF	do not use the Sun Perf. Library (default is use it on Solaris)
+# -DNRECIPROCAL	do not multiply by the reciprocal
+# -DNO_DIVIDE_BY_ZERO	do not divide by zero
+# -DNCHOLMOD    do not use CHOLMOD as a ordering method.  If -DNCHOLMOD is
+#               included in UMFPACK_CONFIG, then UMFPACK  does not rely on
+#               CHOLMOD, CAMD, CCOLAMD, COLAMD, and METIS.
+
+UMFPACK_CONFIG =
+
+# uncomment this line to compile UMFPACK without CHOLMOD:
+# UMFPACK_CONFIG = -DNCHOLMOD
+
+#------------------------------------------------------------------------------
+# CHOLMOD configuration
+#------------------------------------------------------------------------------
+
+# CHOLMOD Library Modules, which appear in libcholmod.a:
+# Core		requires: none
+# Check		requires: Core
+# Cholesky	requires: Core, AMD, COLAMD.  optional: Partition, Supernodal
+# MatrixOps	requires: Core
+# Modify	requires: Core
+# Partition	requires: Core, CCOLAMD, METIS.  optional: Cholesky
+# Supernodal	requires: Core, BLAS, LAPACK
+#
+# CHOLMOD test/demo Modules (all are GNU GPL, do not appear in libcholmod.a):
+# Tcov		requires: Core, Check, Cholesky, MatrixOps, Modify, Supernodal
+#		optional: Partition
+# Valgrind	same as Tcov
+# Demo		requires: Core, Check, Cholesky, MatrixOps, Supernodal
+#		optional: Partition
+#
+# Configuration flags:
+# -DNCHECK	    do not include the Check module.	   License GNU LGPL
+# -DNCHOLESKY	    do not include the Cholesky module.	   License GNU LGPL
+# -DNPARTITION	    do not include the Partition module.   License GNU LGPL
+#		    also do not include METIS.
+# -DNGPL	    do not include any GNU GPL Modules in the CHOLMOD library:
+# -DNMATRIXOPS	    do not include the MatrixOps module.   License GNU GPL
+# -DNMODIFY	    do not include the Modify module.      License GNU GPL
+# -DNSUPERNODAL     do not include the Supernodal module.  License GNU GPL
+#
+# -DNPRINT	    do not print anything.
+# -D'LONGBLAS=long' or -DLONGBLAS='long long' defines the integers used by
+#  		    	LAPACK and the BLAS (defaults to 'int')
+# -DNSUNPERF	    for Solaris only.  If defined, do not use the Sun
+#			Performance Library
+
+CHOLMOD_CONFIG = -DNPARTITION -DNGPL $(GPU_CONFIG)
+
+# uncomment this line to compile CHOLMOD without METIS:
+# CHOLMOD_CONFIG = -DNPARTITION
+
+#------------------------------------------------------------------------------
+# SuiteSparseQR configuration:
+#------------------------------------------------------------------------------
+
+# The SuiteSparseQR library can be compiled with the following options:
+#
+# -DNPARTITION      do not include the CHOLMOD partition module
+# -DNEXPERT         do not include the functions in SuiteSparseQR_expert.cpp
+# -DHAVE_TBB        enable the use of Intel's Threading Building Blocks (TBB)
+
+# default, without timing, without TBB:
+SPQR_CONFIG =
+# with TBB:
+# SPQR_CONFIG = -DHAVE_TBB
+
+# This is needed for IBM AIX: (but not for and C codes, just C++)
+# SPQR_CONFIG = -DBLAS_NO_UNDERSCORE
+
+# with TBB, you must select this:
+# TBB = -ltbb
+# without TBB:
+TBB =
+
+#------------------------------------------------------------------------------
+# Linux
+#------------------------------------------------------------------------------
+
+# Using default compilers:
+CC = @CC@
+CFLAGS = @CFLAGS@
+# CF = $(CFLAGS) -O3 -fexceptions
+
+# alternatives:
+# CF = $(CFLAGS) -g -fexceptions \
+   	-Wall -W -Wshadow -Wmissing-prototypes -Wstrict-prototypes \
+    	-Wredundant-decls -Wnested-externs -Wdisabled-optimization -ansi \
+        -funit-at-a-time
+# CF = $(CFLAGS) -O3 -fexceptions \
+   	-Wall -W -Werror -Wshadow -Wmissing-prototypes -Wstrict-prototypes \
+    	-Wredundant-decls -Wnested-externs -Wdisabled-optimization -ansi
+# CF = $(CFLAGS) -O3 -fexceptions -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
+# CF = $(CFLAGS) -O3
+# CF = $(CFLAGS) -O3 -g -fexceptions
+# CF = $(CFLAGS) -g -fexceptions \
+   	-Wall -W -Wshadow \
+    	-Wredundant-decls -Wdisabled-optimization -ansi
+
+# consider:
+# -fforce-addr -fmove-all-movables -freduce-all-givs -ftsp-ordering
+# -frename-registers -ffast-math -funroll-loops
+
+# Using the Goto BLAS:
+# BLAS = -lgoto -lfrtbegin -lg2c $(XERBLA) -lpthread
+
+# Using Intel's icc and ifort compilers:
+#   (does not work for mexFunctions unless you add a mexopts.sh file)
+# F77 = ifort
+# CC = icc
+# CF = $(CFLAGS) -O3 -xN -vec_report=0
+# CF = $(CFLAGS) -g
+
+# 64bit:
+# F77FLAGS = -O -m64
+# CF = $(CFLAGS) -O3 -fexceptions -m64
+# BLAS = -lgoto64 -lfrtbegin -lg2c -lpthread $(XERBLA)
+# LAPACK = -llapack64
+
+# SUSE Linux 10.1, AMD Opteron, with GOTO Blas
+# F77 = gfortran
+# BLAS = -lgoto_opteron64 -lgfortran
+
+# SUSE Linux 10.1, Intel Pentium, with GOTO Blas
+# F77 = gfortran
+# BLAS = -lgoto -lgfortran
+
+#------------------------------------------------------------------------------
+# Mac
+#------------------------------------------------------------------------------
+
+# As recommended by macports, http://suitesparse.darwinports.com/
+# I've tested them myself on Mac OSX 10.6.1 and 10.6.8 (Snow Leopard),
+# on my MacBook Air, and they work fine.
+
+# F77 = gfortran
+# CF = $(CFLAGS) -O3 -fno-common -fexceptions -DNTIMER
+# BLAS = -framework Accelerate
+# LAPACK = -framework Accelerate
+# LIB = -lm
+
+#------------------------------------------------------------------------------
+# Solaris
+#------------------------------------------------------------------------------
+
+# 32-bit
+# CF = $(CFLAGS) -KPIC -dalign -xc99=%none -Xc -xlibmieee -xO5 -xlibmil -m32
+
+# 64-bit
+# CF = $(CFLAGS) -fast -KPIC -xc99=%none -xlibmieee -xlibmil -m64 -Xc
+
+# FFLAGS = -fast -KPIC -dalign -xlibmil -m64
+
+# The Sun Performance Library includes both LAPACK and the BLAS:
+# BLAS = -xlic_lib=sunperf
+# LAPACK =
+
+
+#------------------------------------------------------------------------------
+# Compaq Alpha
+#------------------------------------------------------------------------------
+
+# 64-bit mode only
+# CF = $(CFLAGS) -O2 -std1
+# BLAS = -ldxml
+# LAPACK =
+
+#------------------------------------------------------------------------------
+# IBM RS 6000
+#------------------------------------------------------------------------------
+
+# BLAS = -lessl
+# LAPACK =
+
+# 32-bit mode:
+# CF = $(CFLAGS) -O4 -qipa -qmaxmem=16384 -qproto
+# F77FLAGS = -O4 -qipa -qmaxmem=16384
+
+# 64-bit mode:
+# CF = $(CFLAGS) -O4 -qipa -qmaxmem=16384 -q64 -qproto
+# F77FLAGS = -O4 -qipa -qmaxmem=16384 -q64
+
+#------------------------------------------------------------------------------
+# SGI IRIX
+#------------------------------------------------------------------------------
+
+# BLAS = -lscsl
+# LAPACK =
+
+# 32-bit mode
+# CF = $(CFLAGS) -O
+
+# 64-bit mode (32 bit int's and 64-bit long's):
+# CF = $(CFLAGS) -64
+# F77FLAGS = -64
+
+# SGI doesn't have ranlib
+# RANLIB = echo
+
+#------------------------------------------------------------------------------
+# AMD Opteron (64 bit)
+#------------------------------------------------------------------------------
+
+# BLAS = -lgoto_opteron64 -lg2c
+# LAPACK = -llapack_opteron64
+
+# SUSE Linux 10.1, AMD Opteron
+# F77 = gfortran
+# BLAS = -lgoto_opteron64 -lgfortran
+# LAPACK = -llapack_opteron64
+
+#------------------------------------------------------------------------------
+# remove object files and profile output
+#------------------------------------------------------------------------------
+
+CLEAN = *.o *.obj *.ln *.bb *.bbg *.da *.tcov *.gcov gmon.out *.bak *.d *.gcda *.gcno
diff --git a/download/yams/Makefile b/download/yams/Makefile
new file mode 100644
index 0000000..28b2654
--- /dev/null
+++ b/download/yams/Makefile
@@ -0,0 +1,108 @@
+# Downloading and compiling extra libraries
+# -----------------------------------------
+
+# $Id$
+all-local: yams
+
+include ff-flags
+
+# Downloading and compiling yams
+# -------------------------------
+# 
+DIRPKG= ../pkg
+SRCDIR= ./freeyams$(yams_VERSION)
+#-$(yams_VERSION)
+PACKAGE=$(DIRPKG)/freeyams$(yams_VERSION).tgz
+SERVER=http://www.ann.jussieu.fr/~frey/ftp/archives/
+INSTALL=../..
+yams_VERSION=.2012.02.05
+
+# ---------------------- 
+#     yamslib
+
+YAMS_DIR = $(abs_top_builddir)/download/yams/$(SRCDIR)
+YAMS_SRCDIRNOLIB = $(YAMS_DIR)/sources
+YAMS_SRCDIR = $(YAMS_DIR)/sourceslib
+YAMS_OBJDIR = $(YAMS_DIR)/objects
+
+yams: FAIRE  
+
+
+
+# FFCS - make sure that PATCH is done sequentially otherwise its error messages are drowned into other meaningless
+# parallel compilation messages
+
+FAIRE: $(SRCDIR)/PATCH yamslib_internal.h yamslib.c yamslib.h  ../Makefile
+	$(MAKE)  install  WHERE
+	touch FAIRE
+
+$(SRCDIR)/FAIT: $(SRCDIR)/PATCH  yamslib_internal.h yamslib.c yamslib.h 
+	cp yamslib_internal.h yamslib.c yamslib.h $(YAMS_SRCDIR)/
+	cp makefile-yams.inc $(YAMS_DIR)/makefile
+	cd $(YAMS_DIR); make
+	touch $(SRCDIR)/FAIT
+install: $(SRCDIR)/FAIT
+	sed  s/defines.h/freeyams_defines.h/ <$(YAMS_SRCDIR)/yamslib.h  >../include/freeyamslib.h
+	cp $(YAMS_SRCDIR)/defines.h  ../include/freeyams_defines.h
+	-mkdir ../lib	
+	cp $(YAMS_OBJDIR)/libyams.a  ../lib/libfreeyams.a
+
+# FFCS - WHERE is made to depend on FAIT otherwise it may be built in parallel and not be activated because FAIT is not
+# there yet
+
+WHERE: $(SRCDIR)/FAIT
+	echo freeyams  LD -L at DIR@/lib -lfreeyams  >$(SRCDIR)/$(INSTALL)/lib/WHERE.freeyams ;
+	echo freeyams INCLUDE -I at DIR@/include>> $(SRCDIR)/$(INSTALL)/lib/WHERE.freeyams ;
+
+$(SRCDIR)/PATCH: $(PACKAGE) 
+	-mkdir -p $(SRCDIR)
+	cd $(SRCDIR); tar xvzf ../$(PACKAGE)
+	-mkdir $(YAMS_SRCDIR)
+	cp $(YAMS_SRCDIRNOLIB)/*.c $(YAMS_SRCDIRNOLIB)/*.h $(YAMS_SRCDIR)
+	rm $(YAMS_SRCDIR)/memory.c 
+	cp $(YAMS_SRCDIRNOLIB)/compil.date $(YAMS_SRCDIR)
+	cd $(YAMS_SRCDIR) && \
+	  patch -p2 < ../../freeyams$(yams_VERSION).patch && \
+	  patch -p2 < ../../freeyams$(yams_VERSION)-return-values.patch
+	mv  $(YAMS_SRCDIR)/yams.c $(YAMS_SRCDIR)/..
+	touch $(SRCDIR)/PATCH
+
+$(PACKAGE):
+	../getall -o freeYams -a
+
+# FFCS: only run make clean if cd to SRCDIR worked, otherwise this is infinite loop.
+
+clean-local: 
+	-rm FAIRE FAIT  $(SRCDIR)/FAIT
+	-cd $(YAMS_DIR) &&  $(MAKE) -C $(YAMS_DIR)  clean
+	-rm $(YAMS_OBJDIR)/libyams.a
+
+# FFCS -simplifying all paths
+
+ clean: clean-local
+	-rm ff-flags
+	-rm $(SRCDIR)/$(INSTALL)/lib/libfreeyams.a
+	-rm $(SRCDIR)/$(INSTALL)/include/*freeyams*.h
+	-rm $(SRCDIR)/$(INSTALL)/lib/WHERE.freeyams
+	-rm ../lib/libfreeyams.a
+	-rm ../include/*freeyams*.h
+	-rm ../lib/WHERE.freeyams
+	-rm -rf $(YAMS_DIR)
+	-rm -rf $(SRCDIR)
+	-rm $(PACKAGE)
+	-rm FAIT FAIRE
+
+ff-flags: ../Makefile Makefile
+	grep 'abs_top_builddir *=' ../Makefile > ff-flags
+	grep 'CC *=' ../Makefile >> ff-flags
+	grep 'CFLAGS *=' ../Makefile >> ff-flags
+	grep 'LDFLAGS *=' ../Makefile >> ff-flags
+	grep 'AR *=' ../Makefile >> ff-flags
+	grep 'ARFLAGS *=' ../Makefile >> ff-flags
+	grep 'RANLIB *=' ../Makefile >> ff-flags
+	grep 'yams_VERSION *=' ./Makefile >> ff-flags
+	grep 'WGET *=' ../Makefile >> ff-flags
+	grep 'LIBS *=' ../Makefile >> ff-flags
+
+
+.PHONY: $(SRCDIR)/$(INSTALL)
diff --git a/download/yams/freeyams.2012.02.05-return-values.patch b/download/yams/freeyams.2012.02.05-return-values.patch
new file mode 100644
index 0000000..df83599
--- /dev/null
+++ b/download/yams/freeyams.2012.02.05-return-values.patch
@@ -0,0 +1,11 @@
+--- freeyams.2012.02.05/sourceslib/debug.c.orig	2013-01-27 14:24:38.489115910 +0000
++++ freeyams.2012.02.05/sourceslib/debug.c	2013-01-27 14:25:24.156118592 +0000
+@@ -178,7 +178,7 @@
+       }
+     }
+   }
+-  
++  return 0;  
+ }
+ 
+ 
diff --git a/download/yams/freeyams.2012.02.05.patch b/download/yams/freeyams.2012.02.05.patch
new file mode 100644
index 0000000..f9e5949
--- /dev/null
+++ b/download/yams/freeyams.2012.02.05.patch
@@ -0,0 +1,353 @@
+diff -ru freeyams.2011.09.23/sourceslib/blinde.c freeyams.2011.09.23-orig/sourceslib/blinde.c
+--- freeyams.2011.09.23/sourceslib/blinde.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/blinde.c	2011-11-16 09:59:50.000000000 +0100
+@@ -36,7 +36,7 @@
+   ida =                          id[0]*10 + id[1];
+   /*printf("date = %d %d %d\n",iy,im,ida); */
+   if ( YMD(iy,im,ida) > YMD(MAX_YEAR,MAX_MONTH,MAX_DAY) ) {
+-    fprintf(stdout,"  -- YAMS (LJLL), Version %s (%s)\n",VERSION,RELEASE);
++    fprintf(stdout,"  -- YAMS (LJLL), Version %s (%s)\n",YAMS_VERSION,RELEASE);
+     fprintf(stdout,"     Copyright (C) LJLL, 1999-2006.\n\n");
+     fprintf(stdout," ## Expiration date reached. Sorry.\n");
+     fprintf(stdout,"    Please contact the author.\n");
+diff -ru freeyams.2011.09.23/sourceslib/defines.h freeyams.2011.09.23-orig/sourceslib/defines.h
+--- freeyams.2011.09.23/sourceslib/defines.h	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/defines.h	2011-11-16 09:59:50.000000000 +0100
+@@ -18,7 +18,7 @@
+ /* current version */
+ #define DEFAULT_FILE    "DEFAULT.yams"
+ #define RELEASE         "oct, 2006"
+-#define VERSION         "2.4 b"
++#define YAMS_VERSION    "2.4 b"
+ #define COPYRIGHT       "Copyright (C) LJLL, 1999-2006"
+ 
+ #define REL    1
+diff -ru freeyams.2011.09.23/sourceslib/extern.h freeyams.2011.09.23-orig/sourceslib/extern.h
+--- freeyams.2011.09.23/sourceslib/extern.h	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/extern.h	2011-11-16 09:59:50.000000000 +0100
+@@ -4,6 +4,7 @@
+ 
+ 
+ #ifndef __YAMS
++#ifndef __YAMSLIB
+   extern Error      yerr;
+   extern Info       info;
+   extern Options    opts;
+@@ -14,7 +15,7 @@
+   extern short     imprim;
+   extern ubyte     ddebug;
+ #endif
+-
++#endif
+ 
+ #ifdef __cplusplus
+ }
+diff -ru freeyams.2011.09.23/sourceslib/inout.c freeyams.2011.09.23-orig/sourceslib/inout.c
+--- freeyams.2011.09.23/sourceslib/inout.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/inout.c	2011-11-16 09:59:50.000000000 +0100
+@@ -581,7 +581,7 @@
+     ppt->tag |= M_UNUSED;
+     ppt->flag = ppt->color = 0;
+   }
+-
++  printf("sm->connex %d\n",sm->connex);
+   if ( sm->connex > 0 ) {
+     for (k=1; k<=sm->ne; k++) {
+       pt1 = &sm->tria[k];
+@@ -679,8 +679,8 @@
+         natv++;
+         if ( ppt->tag & M_CORNER )  tatv++;
+       }
+-      if ( !gs->new )  gs->new = ++nn;
+-      if ( !gt->new )  gt->new = ++nt;
++      if ( !gs->newnum )  gs->newnum = ++nn;
++      if ( !gt->newnum )  gt->newnum = ++nt;
+       if ( !pt1->edg[i] && pt1->tag[i] == M_NOTAG )  continue;
+       else if ( pt1->adj[i] && (k > pt1->adj[i]) )   continue;
+       nedge++;
+@@ -864,12 +864,12 @@
+   nn = nbl = 0;
+   for (k=1; k<=sm->nvmax; k++) {
+     gs = &sm->geom[k];
+-    if ( gs->new > 0 ) {
++    if ( gs->newnum > 0 ) {
+       iadr = nbl * 3;
+       tabf[iadr+0] = gs->vn[0];
+       tabf[iadr+1] = gs->vn[1];
+       tabf[iadr+2] = gs->vn[2];
+-      gs->new = ++nn;
++      gs->newnum = ++nn;
+       ++nbl;
+       if ( nbl == NMAX ) {
+         LM_write_field(&ms, LM_Normals, nbl, tabf);
+@@ -890,7 +890,7 @@
+         iadr = nbl * 2;
+         gs = &sm->geom[pt1->vn[i]];
+         tabi[iadr+0] = ppt->tmp;
+-        tabi[iadr+1] = gs->new;
++        tabi[iadr+1] = gs->newnum;
+         ppt->flag = 1;
+         ++nbl;
+         if ( nbl == NMAX ) {
+@@ -916,7 +916,7 @@
+         iadr = nbl * 3;
+         tabi[iadr+0] = nn;
+         tabi[iadr+1] = i+1;
+-        tabi[iadr+2] = gs->new;
++        tabi[iadr+2] = gs->newnum;
+         ++nbl;
+         if ( nbl == NMAX ) {
+           LM_write_field(&ms, LM_NormalAtTriangleVertices, nbl, tabi);
+@@ -931,12 +931,12 @@
+   nt = nbl = 0;
+   for (k=1; k<=sm->ntmax; k++) {
+     gt = &sm->tgte[k];
+-    if ( gt->new > 0 ) {
++    if ( gt->newnum > 0 ) {
+       iadr = nbl * 3;
+       tabf[iadr+0] = gt->t[0];
+       tabf[iadr+1] = gt->t[1];
+       tabf[iadr+2] = gt->t[2];
+-      gt->new  = ++nt;
++      gt->newnum  = ++nt;
+       ++nbl;
+       if ( nbl == NMAX ) {
+         LM_write_field(&ms, LM_Tangents, nbl, tabf);
+@@ -956,7 +956,7 @@
+       iadr = nbl * 2;
+       gt = &sm->tgte[ppt->tge];
+       tabi[iadr+0]  = ppt->tmp;
+-      tabi[iadr+1]  = gt->new;
++      tabi[iadr+1]  = gt->newnum;
+       ppt->flag = 1;
+       ++nbl;
+       if ( nbl == NMAX ) {
+@@ -1105,8 +1105,8 @@
+         natv++;
+         if ( ppt->tag & M_CORNER )  tatv++;
+       }
+-      if ( !gs->new )  gs->new = ++nn;
+-      if ( !gt->new )  gt->new = ++nq;
++      if ( !gs->newnum )  gs->newnum = ++nn;
++      if ( !gt->newnum )  gt->newnum = ++nq;
+       if ( !pq1->edg[i] && pq1->tag[i] == M_NOTAG )  continue;
+       else if ( pq1->adj[i] && (k > pq1->adj[i]) )   continue;
+       nedge++;
+@@ -1263,12 +1263,12 @@
+   nn = nbl = 0;
+   for (k=1; k<=sm->nvmax; k++) {
+     gs = &sm->geom[k];
+-    if ( gs->new > 0 ) {
++    if ( gs->newnum > 0 ) {
+       iadr = nbl * 3;
+       tabf[iadr+0] = gs->vn[0];
+       tabf[iadr+1] = gs->vn[1];
+       tabf[iadr+2] = gs->vn[2];
+-      gs->new = ++nn;
++      gs->newnum = ++nn;
+       ++nbl;
+       if ( nbl == NMAX ) {
+         LM_write_field(&ms, LM_Normals, nbl, tabf);
+@@ -1289,7 +1289,7 @@
+         iadr = nbl * 2;
+         gs = &sm->geom[pq1->vn[i]];
+         tabi[iadr+0] = ppt->tmp;
+-        tabi[iadr+1] = gs->new;
++        tabi[iadr+1] = gs->newnum;
+         ppt->flag = 1;
+         ++nbl;
+         if ( nbl == NMAX ) {
+@@ -1315,7 +1315,7 @@
+     iadr = nbl * 3;
+     tabi[iadr+0] = nn;
+     tabi[iadr+1] = i+1;
+-    tabi[iadr+2] = gs->new;
++    tabi[iadr+2] = gs->newnum;
+     ++nbl;
+         if ( nbl == NMAX ) {
+           LM_write_field(&ms, LM_NormalAtQuadrilateralVertices, nbl, tabi);
+@@ -1330,12 +1330,12 @@
+   nq = nbl = 0;
+   for (k=1; k<=sm->ntmax; k++) {
+     gt = &sm->tgte[k];
+-    if ( gt->new > 0 ) {
++    if ( gt->newnum > 0 ) {
+       iadr = nbl * 3;
+       tabf[iadr+0] = gt->t[0];
+       tabf[iadr+1] = gt->t[1];
+       tabf[iadr+2] = gt->t[2];
+-      gt->new  = ++nq;
++      gt->newnum  = ++nq;
+       ++nbl;
+       if ( nbl == NMAX ) {
+         LM_write_field(&ms, LM_Tangents, nbl, tabf);
+@@ -1355,7 +1355,7 @@
+       iadr = nbl * 2;
+       gt = &sm->tgte[ppt->tge];
+       tabi[iadr+0]  = ppt->tmp;
+-      tabi[iadr+1]  = gt->new;
++      tabi[iadr+1]  = gt->newnum;
+       ppt->flag = 1;
+       ++nbl;
+       if ( nbl == NMAX ) {
+@@ -1524,8 +1524,8 @@
+   /* adjust sizes */
+   if ( opts.hmin < 0.0 )
+     opts.hmin = max(opts.hmin,hmin);
+-    if ( opts.hmax < 0.0 )
+-      opts.hmax = max(opts.hmax,hmax);
++  if ( opts.hmax < 0.0 )
++    opts.hmax = max(opts.hmax,hmax);
+ 
+   E_pop();
+   return(1);
+Only in freeyams.2011.09.23-orig/sourceslib: inout.c.orig
+diff -ru freeyams.2011.09.23/sourceslib/parsop.c freeyams.2011.09.23-orig/sourceslib/parsop.c
+--- freeyams.2011.09.23/sourceslib/parsop.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/parsop.c	2011-11-16 09:59:50.000000000 +0100
+@@ -16,7 +16,7 @@
+   }
+ 
+   /* create standard parameter file */
+-  fprintf(out,"#  Generated by YAMS %s\n",VERSION);
++  fprintf(out,"#  Generated by YAMS %s\n",YAMS_VERSION);
+   fprintf(out,"#  Uncomment next if absolute unit desired\n");
+   fprintf(out,"#Absolute\n");
+ 
+Only in freeyams.2011.09.23-orig/sourceslib: parsop.c.orig
+diff -ru freeyams.2011.09.23/sourceslib/primsg.c freeyams.2011.09.23-orig/sourceslib/primsg.c
+--- freeyams.2011.09.23/sourceslib/primsg.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/primsg.c	2011-11-16 09:59:50.000000000 +0100
+@@ -18,10 +18,10 @@
+     case 0000:
+       if ( opts.ctrl & ISO )
+         fprintf(stdout,"\n  %s\n   MODULE YAMS-LJLL : %s\n  %s\n",
+-	        STR,VERSION,STR);
++	        STR,YAMS_VERSION,STR);
+       else
+         fprintf(stdout,"\n  %s\n   MODULE YAMS-LJLL (ANISO) : %s\n  %s\n",
+-	        STR,VERSION,STR);
++	        STR,YAMS_VERSION,STR);
+       return;
+     case 0001: 
+       fprintf(stdout,"\n  %s\n   END OF MODULE YAMS\n  %s\n\n",STR,STR);
+diff -ru freeyams.2011.09.23/sourceslib/surf.h freeyams.2011.09.23-orig/sourceslib/surf.h
+--- freeyams.2011.09.23/sourceslib/surf.h	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/surf.h	2011-11-16 09:59:50.000000000 +0100
+@@ -64,13 +64,13 @@
+ typedef struct geomsupp {
+   float    vn[3];           /* array of vertex normals  */
+   float    gap;             /* local gap value          */
+-  int      new;             /* pointer to new number    */
++  int      newnum;             /* pointer to new number    */
+ } GeomSupp;
+ typedef GeomSupp  * pGeomSupp;
+ 
+ typedef struct geomtge {
+   float    t[3];
+-  int      new;
++  int      newnum;
+ } Geomtge;
+ typedef Geomtge   * pGeomtge;
+ 
+diff -ru freeyams.2011.09.23/sourceslib/yams.c freeyams.2011.09.23-orig/sourceslib/yams.c
+--- freeyams.2011.09.23/sourceslib/yams.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/yams.c	2011-11-16 09:59:50.000000000 +0100
+@@ -24,6 +24,7 @@
+ ubyte     ddebug;
+ ubyte     ecp;
+ 
++long verbosity; 
+ 
+ static void excfun(int sigid) {
+   fprintf(stdout,"\n Unexpected error:");  fflush(stdout);
+Only in freeyams.2011.09.23-orig/sourceslib: yams.c.orig
+diff -ru freeyams.2011.09.23/sourceslib/yams.h freeyams.2011.09.23-orig/sourceslib/yams.h
+--- freeyams.2011.09.23/sourceslib/yams.h	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/yams.h	2011-11-16 09:59:50.000000000 +0100
+@@ -6,12 +6,17 @@
+ #include <string.h>
+ 
+ #include "chrono.h"
+-#include "edge.h"
+-#include "error.h"
+-#include "hash.h"
+-#include "stack.h"
+-#include "info.h"
+ #include "memory.h"
+-#include "option.h"
+-#include "surf.h"
++
++//#include "edge.h"
++//#include "error.h"
++//#include "hash.h"
++//#include "stack.h"
++//#include "info.h"
++//#include "memory.h"
++//#include "option.h"
++//#include "surf.h"
++
++#include "yamslib.h"
++#include "yamslib_internal.h"
+ #include "global.h"
+diff -ru freeyams.2011.09.23/sourceslib/yams0.c freeyams.2011.09.23-orig/sourceslib/yams0.c
+--- freeyams.2011.09.23/sourceslib/yams0.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/yams0.c	2011-11-16 09:59:50.000000000 +0100
+@@ -24,7 +24,7 @@
+   if ( imprim ) {
+     if ( ecp )
+       fprintf(stdout,"  ## Version:  Ecole Centrale de Paris ##\n\n");
+-    fprintf(stdout,"  -- YAMS (LJLL) Version %s (%s)\n",VERSION,RELEASE);
++    fprintf(stdout,"  -- YAMS (LJLL) Version %s (%s)\n",YAMS_VERSION,RELEASE);
+     fprintf(stdout,"     %s.\n",COPYRIGHT);
+     fprintf(stdout,"     compiled: %s.\n\n",COMPIL);
+   }
+diff -ru freeyams.2011.09.23/sourceslib/zaldy1.c freeyams.2011.09.23-orig/sourceslib/zaldy1.c
+--- freeyams.2011.09.23/sourceslib/zaldy1.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/zaldy1.c	2011-11-16 09:59:50.000000000 +0100
+@@ -45,13 +45,20 @@
+     }
+   }
+   else {
++    int bytes = sizeof(Point) \
++              + sizeof(Metric) \
++              + 2   * sizeof(Triangle) \
++              + 1.5 * sizeof(GeomSupp) \
++              + 0.2 * sizeof(Geomtge) \
++              + 3.7 * sizeof(Hashtable);
++    /*
+     int bytes = sizeof(struct spoint) \
+               + sizeof(struct metric) \
+               + 2   * sizeof(struct striangle) \
+               + 1.5 * sizeof(struct geomsupp) \
+               + 0.2 * sizeof(struct geomtge) \
+               + 3.7 * sizeof(struct shashtab);
+-
++    */
+     sm->npmax = (int)((double)memory / bytes * million);
+     sm->npmax = max(sm->npmax,npmax);
+     sm->nemax = max(2 * sm->npmax,nemax);
+diff -ru freeyams.2011.09.23/sourceslib/zaldy3.c freeyams.2011.09.23-orig/sourceslib/zaldy3.c
+--- freeyams.2011.09.23/sourceslib/zaldy3.c	2011-11-16 11:06:08.000000000 +0100
++++ freeyams.2011.09.23-orig/sourceslib/zaldy3.c	2011-11-16 09:59:50.000000000 +0100
+@@ -34,7 +34,7 @@
+     for (j=sm->nvmax; j<nvsize; j++) {
+       sm->geom[j].vn[0] = sm->geom[j].vn[1] = sm->geom[j].vn[2] = 0.;
+       sm->geom[j].gap   = 1.;
+-      sm->geom[j].new   = 0;
++      sm->geom[j].newnum   = 0;
+     }
+     sm->nvmax = nvsize;
+     yerr.inderr[0] = sm->nvmax;
+diff -u freeyams.2012.02.05/sourceslib/outqua_a.c  freeyams.2011.09.23-orig/sourceslib/outqua_a.c
+--- freeyams.2012.02.05/sourceslib/outqua_a.c	2009-05-13 21:00:03.000000000 +0200
++++ freeyams.2011.09.23-orig/sourceslib/outqua_a.c	2012-09-04 08:51:04.000000000 +0200
+@@ -219,7 +219,7 @@
+   pt = &mesh->tria[iel];
+   fprintf(stdout,"     WORST ELEMENT   %d (%d)   %d %d %d\n",iel,ielr,pt->v[0],pt->v[1],pt->v[2]);
+ 
+-  if ( abs(imprim) < 5 )  return;
++  if ( abs(imprim) < 5 )  return (1) ;
+  
+   fprintf(stdout,"\n     HISTOGRAMM\n");
+   imax = min(9,(int)(10.*rapmax));
diff --git a/download/yams/makefile-yams.inc b/download/yams/makefile-yams.inc
new file mode 100644
index 0000000..f6e4fc4
--- /dev/null
+++ b/download/yams/makefile-yams.inc
@@ -0,0 +1,46 @@
+include ../ff-flags
+
+# working dirs
+
+YAMS2DIR =$(abs_top_builddir)/download/yams/freeyams$(yams_VERSION)
+EXEDIR = $(abs_top_builddir)/download/bin
+SRCDIR = $(YAMS2DIR)/sourceslib
+OBJDIR = $(YAMS2DIR)/objects
+ARCDIR = $(YAMS2DIR)/archives
+DIRDIR = $(EXEDIR) $(OBJDIR) $(ARCDIR)
+INCDIR = -I$(YAMS2DIR)/sourcesnew -I$(abs_top_builddir)/src/libMesh/
+LDLDIR = -L$(abs_top_builddir)/src/libMesh/ -lMesh 
+VPATH  = $(SRCDIR)
+
+# objects list
+src    = $(wildcard $(SRCDIR)/*.c)
+header = $(wildcard $(SRCDIR)/*.h)
+objs   = $(patsubst $(SRCDIR)%,$(OBJDIR)%,$(src:.c=.o))
+prog   = yams2
+lib    = $(OBJDIR)/libyams.a
+
+#.SILENT:
+
+$(OBJDIR)/%.o: $(SRCDIR)/%.c
+	$(CC) $(OPT64)  $(INCDIR) $(CFLAGS) -c $< -o $@
+
+$(EXEDIR)/$(prog):$(DIRDIR) $(objs) 
+	echo "#define COMPIL " '"' `date` '"' > $(SRCDIR)/compil.date
+	$(CC) -c $(CFLAGS) $(INCDIR) $(SRCDIR)/yams0.c -o $(OBJDIR)/yams0.o -I../../../src/libMesh/ 
+	$(CC) -c $(CFLAGS) $(INCDIR) $(SRCDIR)/../yams.c -I$(SRCDIR)  -o $(OBJDIR)/yams.o -I../../../src/libMesh/ 
+	$(AR) $(ARFLAGS) $(lib) $(objs)
+	$(CC)  $(LDFLAGS) $(OPT64) $(LDLDIR) $(OBJDIR)/yams.o -o $@ $(lib) -lm -L../../../src/libMesh/ -lMesh $(LIBS)
+	$(RANLIB) $(lib)
+
+$(objs):$(header)
+
+$(DIRDIR):
+	@[ -d $@ ] || mkdir $@
+
+clean:
+	-rm $(objs) $(EXEDIR)/$(prog)
+
+tar:$(DIRDIR)
+	tar czf $(ARCDIR)/$(prog).`date +"%Y.%m.%d"`.tgz sources makefile
+
+target: $(EXEDIR)/$(prog)
\ No newline at end of file
diff --git a/download/yams/yamslib.c b/download/yams/yamslib.c
new file mode 100644
index 0000000..7a285b7
--- /dev/null
+++ b/download/yams/yamslib.c
@@ -0,0 +1,598 @@
+#define  __YAMSLIB
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+
+#include "yams.h"
+#include "defines.h"
+#include "sproto.h"
+
+extern long verbosity;
+/* globals (see globals.h) */
+Error       yerr;
+Info        info;
+Options     opts;
+pHashtable  hash;
+mytime      ctim[TIMEMAX];
+
+long      nhmax,hnext,hsize;
+int       out,idir[5] = {0,1,2,0,1},idirq[7] = {0,1,2,3,0,1,2};
+short     imprim;
+ubyte     ddebug;
+ubyte     ecp;
+
+
+static void yams_excfun(int sigid) {
+  switch(sigid){
+  case SIGFPE:
+    fprintf(stderr,"  ## FP EXCEPTION. STOP\n");
+    break;
+  case SIGILL:
+    fprintf(stderr,"  ## ILLEGAL INSTRUCTION. STOP\n");
+    break;
+  case SIGSEGV:
+    fprintf(stderr,"  ## SEGMENTATION FAULT. STOP\n");
+    break;
+  case SIGABRT:
+  case SIGTERM:
+  case SIGINT:
+    fprintf(stderr,"  ## ABNORMAL END. STOP\n");
+    break;
+  }
+  out = 0;
+  exit(1);
+}
+
+static void yams_endcod() {
+  chrono(OFF,&ctim[0]);
+  chrono(OFF,&ctim[1]);
+  E_dump();
+  if ( out <= 0 ) {
+    prierr(WAR,8002);
+    fprintf(stdout,"\n   ELAPSED TIME  %.2f SEC.\n",gttime(ctim[0]));
+  }
+}
+
+static void yams_inival(){
+  /* initialize data */
+  E_put("inival");
+  info.dmin  = (double)FLT_MAX; 
+  info.dmax  = (double)FLT_MIN;
+  info.xmin  = info.ymin = info.zmin = (double)FLT_MAX;
+  info.xmax  = info.ymax = info.zmax = (double)-FLT_MAX/2.;
+  info.nedg  = info.nrid = info.ndang = 0;
+  info.ncoi  = info.nreq = info.nvus  = 0;
+  info.cc    = info.flip = 0;
+  info.nulp  = info.nulf = info.nuln = 0;
+  info.qpire = 0;
+  info.manifold = TRUE;
+
+  /* set default values for options */
+  opts.hmin   = -2.0;    
+  opts.hmax   = -2.0;
+  opts.shock  =   1.3;       /* default mesh gradation     */
+  opts.eps    =   0.01;      /* geometric approximation    */
+  opts.iso    =   0.0;
+  opts.declic =   1.0 / BETAC;
+  opts.lambda =   -1.0;
+  opts.mu     =   -1.0;
+  opts.ridge  =   cos(RIDG*M_PI/180.);
+  opts.geom   =   cos(GEOM*M_PI/180.);
+  opts.walton =   COS45DEG;  /* Walton limitation          */
+  opts.bande  =   -2;       /* default = 1 unit           */
+  opts.degrad =   QUALCOE;   /* quality degradation        */
+  opts.ctrl   =   REL | ISO;
+  opts.iter   =   -1;
+  opts.check  = 1;
+  opts.alpha  = sqrt(opts.eps*(2.0-opts.eps));
+  opts.gap    = 1 - opts.eps;
+  
+  opts.minnp  =   -1;
+  opts.alpha  =   sqrt(opts.eps*(2.0-opts.eps));
+  opts.gap    =   1.0 - opts.eps;
+
+  E_pop();
+}
+
+void yams_printval() {
+   if(verbosity<1) return;
+      
+  /* set default values for options */
+  printf("-- freeyams options value    \n");
+  printf("       - hmin %f\n",opts.hmin);
+  printf("       - hmax %f\n",opts.hmax);
+  printf("       - kmin %f\n",opts.kmin);
+  printf("       - kmax %f\n",opts.kmax);
+  printf("       - eps %f\n",opts.eps);
+  printf("       - iso %f\n",opts.iso);
+  printf("       - alpha %f\n", opts.alpha );
+  printf("       - gap %f\n", opts.gap );
+  printf("       - degrad %f\n", opts.degrad);
+  printf("       - ridge %f\n", opts.ridge);
+  printf("       - geom %f\n", opts.geom);
+  printf("       - shock %f\n",opts.shock);
+  printf("       - bande %f\n", opts.bande );
+  printf("       - walton %f\n", opts.walton);
+  printf("       - declic %f\n", opts.declic);
+  printf("       - lambda %f\n",opts.lambda);
+  printf("       - mu %f\n",opts.mu);
+   
+  printf("       - ctrl %d\n", opts.ctrl );
+  printf("       - iter %d\n", opts.iter );
+  printf("       - choix %d\n", opts.choix );
+  printf("       - minnp %d\n", opts.minnp );
+  
+  printf("       - check %X\n", (unsigned char) opts.check);
+  printf("       - ptmult %X\n",  (unsigned char) opts.ptmult);
+  printf("       - noreff %X\n",  (unsigned char) opts.noreff);
+  printf("       - ffem %X\n",  (unsigned char) opts.ffem );
+ 
+}
+
+
+int yams_main(pSurfMesh sm, int intopt[23], double fopt[14], int infondang, int infocc ) {
+  hash=NULL;
+  float       declic;
+  float       ridge=RIDG;
+  int         option,absopt,ret,memory,corr;
+  int         choix;
+  short       phase;
+  int k;
+  /* trap exceptions */
+  signal(SIGABRT,yams_excfun);
+  signal(SIGFPE,yams_excfun);
+  signal(SIGILL,yams_excfun);
+  signal(SIGSEGV,yams_excfun);
+  signal(SIGTERM,yams_excfun);
+  signal(SIGINT,yams_excfun);
+  //atexit(yams_endcod);
+
+  /* init time and calls */
+  tminit(ctim,TIMEMAX);
+  chrono(ON,&ctim[0]);
+
+  
+
+  /* assign default values */
+  yerr.lerror = FALSE;
+  yerr.coderr = 0;
+  phase  = 0;
+  ret    = TRUE;
+  out    = -1;
+  memory = -1;
+  imprim = -99;
+  option = -99;
+  choix  = option;
+  ddebug = FALSE;
+  declic = 0.009;
+  ecp    = 0;
+  
+  // assigne option and surfacemesh
+  
+  /* setting defaults */
+  sm->infile  = NULL;
+  sm->outfile = NULL;
+  sm->type    = M_SMOOTH | M_QUERY | M_DETECT | M_BINARY | M_OUTPUT;
+  yams_inival();
+
+  for (k=1; k<=sm->npfixe; k++) {
+    pPoint ppt = &sm->point[k];
+    /* find extrema coordinates */
+    if ( ppt->c[0] < info.xmin ) info.xmin = ppt->c[0];
+    if ( ppt->c[0] > info.xmax ) info.xmax = ppt->c[0];
+    if ( ppt->c[1] < info.ymin ) info.ymin = ppt->c[1];
+    if ( ppt->c[1] > info.ymax ) info.ymax = ppt->c[1];
+    if ( ppt->c[2] < info.zmin ) info.zmin = ppt->c[2];
+    if ( ppt->c[2] > info.zmax ) info.zmax = ppt->c[2];
+  }
+
+  // info nuln et nulp
+  info.nuln = 0; 
+  for (k=1; k<=sm->nvfixe; k++) {
+    pGeomSupp g0 = &sm->geom[ k ];    
+    double dd = g0->vn[0]*g0->vn[0] + g0->vn[1]*g0->vn[1] + g0->vn[2]*g0->vn[2];
+    if ( dd < 0.0 ) 
+      info.nuln++;
+  }
+  info.nulp = 0;
+
+  /* mark used vertices */
+  for (k=1; k<=sm->nefixe; k++) {
+    pTriangle pt1 = &sm->tria[k];
+    int i;
+    if ( pt1->v[0] )
+      for (i=0; i<3; i++) {
+        pPoint ppt = &sm->point[pt1->v[i]];
+        ppt->tag &= ~M_UNUSED;
+      }
+  }
+
+  /* count unused vertices */
+  for (k=1; k<=sm->npfixe; k++) {
+    pPoint ppt;
+    ppt = &sm->point[k];
+    if ( ppt->tag & M_UNUSED )  info.nulp++;
+  }
+
+
+  /* get decimation parameters */
+  opts.noreff = 0;
+  opts.ffem   = 1;
+  opts.ptmult = 0;
+
+  /*
+    intopt : 0  !! anisotropie
+             1  !! ecp 
+             2  !! extended out put file
+	     3  !! FE correction 
+	     4  !! Formatted (ascii) output file
+	     5  !! save metric file
+	     6  !! msh2
+	     7  !! Split multiple connected points
+	     8  !! memory
+	     9  !! connected component
+	    10  !! vrml 
+	    11  !! imprim
+	    12  !! nm : Create point on straight edge (no mapping)
+	    13  !! nc : No validity check during smoothing (opt. 9)
+	    14  !! np : Specify number of points desired
+	    15  !! nit : Nb Iter
+	    16  !! nq  : Output quads
+	    17  !! nr  : No ridge detection
+	    18  !! ns  : No point smoothing
+	    19  !! no  : No output file
+	    20  !! ref : Ignore face references
+	    // rajouter lors de l'ouverture du fichiers yams
+	    21  !! absolute : opts.ctrl &= ~REL;
+	    22  !! set optim option
+
+    fopt   : 0  !! iso 
+             1  !! eps 
+	     2  // pas de valeur
+	     3  !! opts.lambda
+	     4  !! opts.mu
+	     5  // pas de valeur
+	     6  !! hgrad  :: opts.shock
+	     7  !! hmin   :: opts.hmin
+	     8  !! hmax   :: opts.hmax
+	     // rajouter lors de l'ouverture du fichiers yams
+	     9  !! tolerance :: opts.bande
+	     10 !! degrad :: opts.degrad
+	     11 !! declic :: opts.declic 
+	     12 !! walton :: opts.walton = cos(dummy/180.0*M_PI);
+	     13 !! ridge  :: opts.ridge
+   */
+  if( intopt[0] == 1)
+    opts.ctrl ^= ISO;
+  opts.iso = fopt[0];  
+  if( intopt[1] == 1 ) { ecp = 1;   sm->type &= ~M_BINARY; }
+  opts.eps = fopt[1];
+  if( intopt[2] == 1 )  sm->type |= M_EXTEND;
+  if( intopt[3] == 1 )  opts.ffem = 0;
+  if( intopt[4] == 1 )  sm->type &= ~M_BINARY;
+  if( intopt[5] == 1 )  sm->type |= M_METRIC;
+  if( intopt[6] == 1 ){
+    sm->type |=  M_MSH2;
+    sm->type &= ~M_BINARY;
+    sm->type &= ~M_EXTEND; 
+  }
+  if( intopt[7] == 1 ){
+    opts.ptmult = 1;
+  }
+  memory = intopt[8]; 
+  sm->connex = intopt[9]; // a initialiser � -1 par d�fault
+  if( intopt[10] == 1 ){
+    sm->type |=  M_VRML;
+    sm->type &= ~M_BINARY;
+    sm->type &= ~M_EXTEND;
+  }
+  imprim = intopt[11]; 
+  // parsar -n
+  if( intopt[12] == 1 ) sm->type &= ~M_QUERY;
+  if( intopt[13] == 1 ) opts.check = 0;
+  opts.minnp = intopt[14];
+  opts.iter = intopt[15];
+  if(verbosity>9) 
+  printf(" type = %d  %d \n", sm->type,intopt[17]);
+  if( intopt[16] == 1 ) sm->type |= M_QUADS;
+  if( intopt[17] == 1 ) sm->type &= ~M_DETECT;
+  if( intopt[18] == 1 ) sm->type &= ~M_SMOOTH;
+  //if( intopt[19] == 1 ) sm->type &= ~M_OUTPUT;
+    if(verbosity>9) 
+  printf(" type = %d  %d \n", sm->type,intopt[17]);
+  sm->type &= ~M_OUTPUT;
+  // parsar -r 
+  if( intopt[20] == 1 ) opts.noreff = 1;
+  // parsar -l
+  opts.lambda  =  fopt[3];
+  opts.mu      =  fopt[4];
+  // parsar -O
+  option = intopt[22];
+  choix  = intopt[22];
+  // parsar -h
+  opts.shock = fopt[6];
+  opts.hmin = fopt[7];
+  opts.hmax = fopt[8];
+
+  // fin parsar
+  opts.choix = option;
+
+  // yams0
+  
+  /* check option */
+  if ( (option) > 0 )
+    sm->type |= M_ENRICH;
+  else
+    memory = -1;
+  /*
+  if ( (abs(*choix) > 4) && !(sm->type & M_QUADS) )
+    sm->type &= ~M_SMOOTH;
+  */
+  if ( !(opts.ctrl & ISO) && (abs(option) != 1) && (abs(option) != 6) )
+    opts.ctrl ^= ISO;
+
+  if ( imprim )   fprintf(stdout,"  -- INPUT DATA\n");
+  chrono(ON,&ctim[5]);
+  
+  opts.bande =  fopt[9];
+  opts.degrad = fopt[10];
+  if( intopt[21] == 1) opts.ctrl &= ~REL;
+
+  // parsop check
+  /* check parameters consistency */
+
+  ridge = fopt[13];
+  if ( (ridge < 0.0) || !(sm->type & M_DETECT) )
+    opts.ridge = -1.0;
+  else
+    opts.ridge  = cos(ridge*M_PI / 180.0);
+ 
+
+
+  opts.degrad = min(opts.degrad,1.0);
+  opts.degrad = max(opts.degrad,0.001);
+
+  /* bound values */
+  opts.alpha = sqrt(opts.eps * (2.-opts.eps));
+  opts.gap   = 1.0 - opts.eps;
+  if ( opts.walton < COS45DEG )  opts.walton = COS45DEG;
+
+  // end assignement mesh and options
+  //int bb = loadSol(sm,sm->infile);
+  //sm->nmfixe = bb ? sm->npfixe : 0;
+  absopt = abs(option);
+
+  chrono(OFF,&ctim[5]);
+  if ( imprim ) {
+    fprintf(stdout,"     NUMBER OF GIVEN VERTICES    %8d\n",sm->npfixe);
+    fprintf(stdout,"     NUMBER OF GIVEN TRIANGLES   %8d\n",sm->nefixe);
+    fprintf(stdout,"  -- DATA READING COMPLETED.     %.2f sec.\n",
+            gttime(ctim[5]));
+    if ( imprim < -4 )  priopt(choix);
+  }
+
+
+  if ( imprim ) yams_printval();
+
+
+  /* set adjacencies  */
+  chrono(ON,&ctim[1]);
+  chrono(ON,&ctim[2]);
+  ret = tabvo2(sm,declic);
+  chrono(OFF,&ctim[2]);
+  if ( !ret ) {
+    prierr(ERR,yerr.coderr);
+    exit(1);
+  }
+
+  /* print surface quality */
+  if ( imprim ) {
+    if ( opts.ctrl & ISO ) 
+      priqua(sm);
+    else if ( sm->metric )
+      priqua_a(sm);
+    primsg(0000);
+    if ( abs(imprim) > 1 ) {
+      yerr.inderr[0] = sm->npmax;
+      yerr.inderr[1] = sm->nemax;
+      primsg(0002);
+    }
+  }
+
+  /* pre-processing stage */
+  yerr.inderr[0] = ++phase;
+  out = 0;
+  if ( abs(imprim) > 1 )  primsg(1000);
+  chrono(ON,&ctim[2]);
+  corr = sm->type & M_DETECT ? 1 : 0;
+  if ( !setvoi(sm,corr) )   exit(1);
+  if ( !ptmult(sm) )   exit(1);
+  if ( absopt < 6 ) { 
+    declic = 0.038;
+		declic = opts.ctrl & ISO ? 1e-6 : 1.e-8;
+    if ( !sident(sm,corr) )    exit(1);
+    if ( !delnul(sm,declic) )  exit(1);
+    if ( !optedg(sm) )         exit(1);
+  }
+  if ( sm->type & M_DETECT && !sident(sm,1) )  exit(1);
+
+  /* smoothing */
+  if ( absopt == 9 ) {
+    if ( !noshrk(sm,opts.check) )  exit(1);
+	  //if ( !hilbert(sm) )  exit(1);
+    //if ( !denois(sm) )  exit(1);
+  }
+  else {
+    if ( opts.iter < 0 )  opts.iter = 5;
+    if ( absopt < 5 ) {
+      if ( !norpoi(sm,0,corr) )  exit(1);
+      if ( !tgepoi(sm,0,corr) )  exit(1);
+    }
+  }
+  chrono(OFF,&ctim[2]);
+
+  yerr.inderr[0] = phase;
+  yerr.cooerr[0] = gttime(ctim[2]);
+  if ( abs(imprim) > 1 ) {
+    primsg(1001);
+    if ( imprim < -4 ) {
+      bilan(sm);
+      prigap(sm);
+    }
+  }
+  if(verbosity>9) {
+      
+  printf("absopt= %d\n", absopt);
+  printf("imprim= %d\n", imprim);
+  printf("sm->np %d\n", sm->np);
+  printf("sm->dim %d\n", sm->dim);
+  }
+  /* surface remeshing */
+  yerr.inderr[0] = ++phase;
+  if ( absopt && absopt <= 6 ) {
+    if ( abs(imprim) > 1 )  primsg(1000);
+    chrono(ON,&ctim[4]);
+
+    /* geometry enrichment */
+    if ( option > 0 ) {
+      chrono(ON,&ctim[6]);
+      if ( option == 4 )
+        ret = yams4(sm);
+      else if ( option == 6 )
+        ret = yams6(sm);
+       else
+        ret = yams3(sm);
+      chrono(OFF,&ctim[6]);
+      if ( !ret )  exit(1);
+    }
+
+    /* surface simplification */
+    if ( absopt == 1 )
+      ret = yams1(sm);
+    else if ( absopt == 2 ) {
+      if ( opts.minnp < 0 )
+        ret = yams2(sm);
+      else
+        ret = yams22(sm);
+    }
+    else if ( absopt == 5 && sm->type & M_METRIC ) 
+      ret = calmet(sm);
+    chrono(OFF,&ctim[4]);
+    if ( !ret )  exit(1);
+
+    yerr.inderr[0] = phase;
+    yerr.cooerr[0] = gttime(ctim[4]);
+    if ( abs(imprim) > 1 ) {
+      primsg(1001);
+      if ( imprim < -4 ) {
+        if ( opts.ctrl & ISO )
+          priqua(sm);
+        else
+          priqua_a(sm);
+        prilen(sm);
+      }
+    }
+  }
+
+  /* mesh optimization */
+  yerr.inderr[0] = ++phase;
+  if ( absopt < 4 && absopt != 2 && yerr.coderr != 4000 ) {
+    if ( abs(imprim) > 1 )  primsg(1000);
+
+    chrono(ON,&ctim[3]);
+    if ( sm->type & M_SMOOTH && yerr.coderr != 4000 ) {
+      ret = optra4(sm,option);
+      if ( !ret )  exit(1);
+    }
+    if ( absopt < 2 && opts.ffem && !optfem(sm) )  exit(1);
+    chrono(OFF,&ctim[3]);
+    yerr.inderr[0] = phase;
+    yerr.cooerr[0] = gttime(ctim[3]);
+    if ( abs(imprim) > 1 ) primsg(1001);
+  }
+
+  /* convert to quads (09-2003) */
+  if ( sm->type & M_QUADS ) {
+    yerr.inderr[0] = ++phase;
+    if ( abs(imprim) > 1 )  primsg(1000);
+    chrono(ON,&ctim[4]);
+
+    if ( !yamsq(sm) )  exit(1);
+ 
+    yerr.inderr[0] = phase;
+    yerr.cooerr[0] = gttime(ctim[4]);    
+    if ( abs(imprim) > 1 )  primsg(1001);
+  }
+  chrono(OFF,&ctim[1]);
+
+  /* evaluation histograms */
+  if ( abs(imprim) > 1 && absopt < 10 ) {
+    if ( sm->type & M_QUADS )
+      outqua_q(sm);
+    else {
+      if ( absopt == 1 )  prilen(sm);
+      if ( opts.ctrl & ISO )
+        outqua(sm);
+      else {
+	outqua_a(sm);
+        outqua1_a(sm);
+      }
+      if ( sm->connex && info.cc > 1 )  rchsub(sm);
+    }
+  }
+  if ( abs(imprim) > 1 )  primsg(0001);
+
+  /* write resulting mesh */ // pertinence freefem++ ??? J. Morice
+  if ( sm->type & M_OUTPUT ) {
+    
+    chrono(ON,&ctim[5]);
+    out = yams8(sm,sm->outfile,absopt);
+    chrono(OFF,&ctim[5]);
+  }
+  else {
+    if ( imprim )  priout(sm);
+    out=1;
+  }
+
+  if ( imprim ) yams_printval();
+
+  /* print CPU requirements */
+  chrono(OFF,&ctim[0]);
+  if ( imprim ) {
+    if ( imprim < 0 ) primem(sm->npmax);
+    pritim(sm,option);
+  }
+
+  if ( imprim ) yams_endcod();
+  
+  M_free(hash);
+  hash=NULL;
+  /* check for mem leaks */
+  if ( imprim < 0 && M_memLeak() )  M_memDump();
+
+#ifdef DISTRIB
+  /* free token */
+  if ( !IsKeyCodeProtected(keycode) )
+    free_token(&token);
+#endif
+  
+  infondang = info.ndang;
+  infocc = info.cc;
+  
+  return(0);
+}
+// add FH 03/14 ...
+void yams_free(pSurfMesh sm)
+{
+  /* release allocated memory */
+  M_free(sm->point);
+  M_free(sm->tria);
+  M_free(sm->geom);
+  M_free(sm->tgte);
+  if ( sm->metric ) M_free(sm->metric);
+  if ( sm->edge )   M_free(sm->edge);
+  M_free(sm);
+}
diff --git a/download/yams/yamslib.h b/download/yams/yamslib.h
new file mode 100644
index 0000000..0e3f7b9
--- /dev/null
+++ b/download/yams/yamslib.h
@@ -0,0 +1,197 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Edge: Structure used to store specified mesh edges */
+typedef struct yams_sedge {
+  int     p1,p2;
+  int     ref;
+  int     tag;
+} yams_Edge;
+typedef yams_Edge * yams_pEdge;
+
+#ifndef  ERR
+#define  ERR   1
+#define  WAR   2
+#define  MSG   3
+#endif
+
+typedef struct yams_error {
+  double cooerr[6];
+  int    inderr[6];
+  int    lerror;
+  int    coderr;
+} yams_Error;
+
+#include "defines.h"
+
+/* HashTable: hash table structure for mesh edges */
+typedef struct yams_shashtab {
+  int    min;           /* min(a,b)         */
+  int    nxt;           /* next edge        */
+  int    elt;
+  int    ind;
+} yams_Hashtable;
+typedef yams_Hashtable * yams_pHashtable;
+
+typedef struct yams_sstack {
+  int    *t;
+  int     in,out,cur;
+} yams_Stack;
+typedef yams_Stack * yams_pStack;
+
+typedef struct yams_sinfo {
+  double   xmin,ymin,zmin,xmax,ymax,zmax;  /* bounding box  */
+  double   delta;
+  double   dmin,dmax;                      /* edge lengths  */
+  float    qworst;
+  int      meshtype,cc,flip;
+  long     nulp,nulf,nuln;                 /* not used      */
+  int      qpire;
+  int      nedg,nrid,ncoi,nreq,nvus;
+  int      nafixe,nvrequis,ndang;
+  int      manifold;
+} yams_Info;
+
+typedef struct yams_soptions {
+  float    hmin,hmax;      /* desired sizes    */
+  float    kmin,kmax;      /* curvature min,max*/
+  float    eps,iso;        /* max. tolerance, isovalue   */
+  float    alpha,gap;      /* max values allow.*/
+  float    degrad;         /* max degrad. qual */
+  float    ridge;          /* cosine ridge ang */
+  float    geom;
+  float    shock;          /* mesh gradation   */
+  float    bande;          /* bandwidth        */
+  float    walton;         /* angle limitation */
+  float    declic;
+  float    lambda,mu;      /* for smoothing    */
+  int      ctrl;           /* absolute values  */
+  int      minnp;
+  short    iter,choix;
+  unsigned char ptmult,noreff,ffem,check;
+} yams_Options;
+
+#ifndef ubyte
+typedef unsigned char  ubyte;
+#endif
+
+/* Point: Structure that defines a vertex in a mesh. */
+typedef struct yams_spoint {
+  float   c[3];            /* coordinates           */
+  float   size;            /* calculated size       */
+  int     tge;             /* tangent at ridge      */
+  short   color;
+  int     ref;
+  int     tmp;
+  ubyte   tag;             /* vertex type           */
+  ubyte   geom;
+  ubyte   flag;
+} yams_Point;
+typedef yams_Point     * yams_pPoint;
+
+/* Triangle: Structure that defines a triangle in a mesh. */
+typedef struct yams_striangle {
+  float   n[3];             /* face normal                */
+  float   dish;             /* distance to surface        */
+  float   qual;             /* triangle quality           */
+
+  int     v[3];             /* array of vertex indices    */
+  int     adj[3];           /* array of adjacent trias    */
+  int     vn[3];            /* array of vertex normals    */
+  int     edg[3];
+  int     nxt;
+  int     ref;
+  short   cc;
+
+  ubyte   voy[3];           /* array of voyeur vertices  */
+  ubyte   flag1;
+  ubyte   tag[3];           /* array of edge classes     */
+  ubyte   flag2;
+} yams_Triangle;
+typedef yams_Triangle  * yams_pTriangle;
+
+typedef struct yams_squad {
+  float    qual;
+  float    n[3];
+  int      v[4];
+  int      adj[4];
+  int      ref,edg[4],vn[4];
+  short    cc;
+  ubyte    flag1,flag2;
+  ubyte    voy[4];
+  ubyte    tag[4];
+} yams_Quad;
+typedef yams_Quad * yams_pQuad;
+
+typedef struct {
+  int   v[4];
+  int   ref;
+} yams_Tetra;
+typedef yams_Tetra * yams_pTetra;
+
+typedef struct yams_geomsupp {
+  float    vn[3];           /* array of vertex normals  */
+  float    gap;             /* local gap value          */
+  int      newnum;             /* pointer to new number    */
+} yams_GeomSupp;
+typedef yams_GeomSupp  * yams_pGeomSupp;
+
+typedef struct yams_geomtge {
+  float    t[3];
+  int      newnum;
+} yams_Geomtge;
+typedef yams_Geomtge   * yams_pGeomtge;
+
+typedef struct yams_metric {
+  float k1,k2;
+  float m[6];                /* anisotropic metric */
+} yams_Metric;
+typedef yams_Metric   * yams_pMetric;
+
+
+/* SurfMesh: Structure that defines a mesh. */
+typedef struct yams_smesh {
+  int       dim;                /* mesh dimension (2,3)     */
+  int       type;
+  int       connex;             /* # connected component    */
+  int       np,npfixe,npmax;    /* number of vertices       */
+  int       ne,nefixe,nemax;    /* number of triangles      */
+  int       nq,ntet;            /* quads, ntets             */
+  int       nv,nvfixe,nvmax;    /* number of vertex normals */
+  int       nafixe,nmfixe;
+  int       nt,ntfixe,ntmax;    /* vertex tgtes             */
+  int       mark;               /* coloring...              */
+  int       ipil;
+
+  char     *infile;
+  char     *outfile;
+
+  yams_pPoint    point;          /* array of vertices         */
+  yams_pTriangle tria;           /* array of triangles        */
+  yams_pTetra    tetra;
+  yams_pQuad     quad;
+  yams_pGeomSupp geom;           /* pointer to geometric info */
+  yams_pGeomtge  tgte;           /* pointer to tge at ridge   */
+  yams_pMetric   metric;         /* local metric at vertex    */
+
+  yams_pEdge     edge;
+} yams_SurfMesh;
+typedef yams_SurfMesh  * yams_pSurfMesh;
+
+#ifdef __cplusplus
+namespace yams{
+#endif
+  int yams_main(yams_pSurfMesh sm, int intopt[23], double fopt[14], int infondang, int infocc );
+  int zaldy1(int nemax,int npmax,int nvmax,int memory,yams_pSurfMesh sm,int choix);
+  int   zaldy2(int npmax);
+  int   zaldy3(yams_pSurfMesh ,int code);
+  void yams_free(yams_pSurfMesh sm); // Add FH 03/14 
+
+#ifdef __cplusplus
+}
+#endif
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/download/yams/yamslib_internal.h b/download/yams/yamslib_internal.h
new file mode 100644
index 0000000..ae3b955
--- /dev/null
+++ b/download/yams/yamslib_internal.h
@@ -0,0 +1,41 @@
+/*
+typedef struct yams_sedge sedge;
+typedef struct yams_error error;
+typedef struct yams_shashtable shashtable;
+typedef struct yams_sstack sstack;
+typedef struct yams_sinfo sinfo;
+typedef struct yams_soptions soptions;
+typedef struct yams_spoint spoint;
+typedef struct yams_striangle striangle;
+typedef struct yams_squad squad;
+typedef struct yams_geomtge geomtge;
+typedef struct yams_geomsupp geomsupp;
+typedef struct yams_metric metric;
+typedef struct yams_smesh smesh;
+*/
+typedef yams_Edge Edge;
+typedef yams_Error Error;
+typedef yams_Hashtable Hashtable;
+typedef yams_Stack Stack;
+typedef yams_Info Info;
+typedef yams_Options Options;
+typedef yams_Point Point;
+typedef yams_Triangle Triangle;
+typedef yams_Quad Quad;
+typedef yams_Tetra Tetra;
+typedef yams_Geomtge Geomtge;
+typedef yams_GeomSupp GeomSupp;
+typedef yams_Metric Metric;
+typedef yams_SurfMesh SurfMesh;
+
+typedef yams_pEdge pEdge;
+typedef yams_pHashtable pHashtable;
+typedef yams_pStack pStack;
+typedef yams_pPoint pPoint;
+typedef yams_pTriangle pTriangle;
+typedef yams_pQuad pQuad;
+typedef yams_pTetra pTetra;
+typedef yams_pGeomtge pGeomtge;
+typedef yams_pGeomSupp pGeomSupp;
+typedef yams_pMetric pMetric;
+typedef yams_pSurfMesh pSurfMesh;
diff --git a/edp.nedit b/edp.nedit
new file mode 100644
index 0000000..7817f07
--- /dev/null
+++ b/edp.nedit
@@ -0,0 +1,21 @@
+nedit.highlightPatterns: edp:1:0{\n\
+		comment:"/\\*":"\\*/"::Comment::\n\
+		cplus comment:"//":"$"::Comment::\n\
+		string:"L?""":"""":"\\n":String::\n\
+		preprocessor line:"macro":"//"::Preprocessor::\n\
+		string escape chars:"\\\\(.|\\n)":::String1:string:\n\
+		preprocessor esc chars:"\\\\(.|\\n)":::Preprocessor1:preprocessor line:\n\
+		preprocessor comment:"/\\*":"\\*/"::Comment:preprocessor line:\n\
+		preproc cplus comment:"//":"$"::Comment:preprocessor line:\n\
+		preprocessor numeric constant:"<((0(x|X)[0-9a-fA-F]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?>":::Numeric Const:preprocessor line:D\n\
+		numeric constant:"<((0(x|X)[0-9a-fA-F]*)|(([0-9]+\\.?[0-9]*)|(\\.[0-9]+))((e|E)(\\+|-)?[0-9]+)?)(L|l|UL|ul|u|U|F|f)?>":::Numeric Const::D\n\
+		storage keyword:"<(func|real|int|double|mesh|fespace|varf|matrix|problem|solve|ifstream|ofstream|bool)>":::Storage Type::D\n\
+		keyword:"<(Cmatrix|R3|border|break|complex|continue|element|else|end|fespace|for|if|ifstream|include|load|mesh|problem|real|return|solve|string|varf|vertex|while)>":::Keyword::D\n\
+		functionff:"<(BFGS|EigenValue|LinearCG|LinearGMRES|NLCG|Newtow|abs|acos|acosh|adaptmesh|arg|asin|asinh|assert|atan|atan2|atanh|average|buildmesh|buildmeshborder|checkmovemesh|clock|conj|convect|cos|cosh|dumptable|dx|dxx|dxy|dy|dyx|dyy|emptymesh|exec|exit|exp|imag|int1d|int2d|intalledges|interplotematrix|interpolate|jump|log|log10|max|mean|min|movemesh|norm|on|otherside|plot|polar|pow|readmesh|savemesh|set|sin|sinh|splitmesh|sqrt|square|tan|tanh|triangulate|trunc)>":::Identifier1::D\n\
+		constantff:"<(CG|CPUTime|Cholesky|Crout|GMRES|HaveUMFPACK|LU|N|NoUseOfWait|P|P0|P0edge|P1|P1b|P1dc|P1nc|P2|P2b|P2dc|P2h|P2b|RT0|RT0Ortho|RTmodif|UMFPACK|append|area|cin|cout|endl|false|hTriangle|inside|label|lenEdge|nTonEdge|nuEdge|nuTriangle|pi|qf1pE|qf1pElump|qf1pT|qf1pTlump|qf2pE|qf2pT|qf2pT4P1|qf3pE|qf5pT|qf7pT|qf9pT|region|true|verbosity|version|wait|x|y|z)>":::Identifier::D\n\
+		braces:"[{}]":::Keyword::D\n\
+	}
+nedit.languageModes: 	edp:.edp::::::".,/\\`'!|@#%^&*()-=+{}[]"":;<>?~"
+nedit.styles:        Numeric Const:darkGreen:Plain\n\
+        Preprocessor:RoyalBlue4:Plain\n\
+        Preprocessor1:blue:Plain\n\
diff --git a/examples++-3d/._MeshSurface.idp b/examples++-3d/._MeshSurface.idp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-3d/._MeshSurface.idp differ
diff --git a/examples++-3d/3d-Leman.edp b/examples++-3d/3d-Leman.edp
new file mode 100644
index 0000000..b9a7363
--- /dev/null
+++ b/examples++-3d/3d-Leman.edp
@@ -0,0 +1,51 @@
+load "msh3"
+load "medit"
+int nn=10;
+// a pententiel flow on a lac .. 
+//  a first freefem++ 3d example 
+// ------  not to bad ......
+verbosity=3;
+mesh Th2("lac-leman-v4.msh");
+fespace Vh2(Th2,P1);
+Vh2 deep;
+{  Vh2 v; 
+	macro Grad(u) [dx(u),dy(u)] //
+	solve P(deep,v)= int2d(Th2)(Grad(deep)'*Grad(v))+int2d(Th2)(v)
+	+on(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,deep=-1);
+	deep = deep*5/abs(deep[].min);
+	plot(deep,wait=1);
+}
+Vh2 ux,uz,p2;
+int[int] rup=[0,200],  rdown=[0,100],rmid(17*2);
+for(int i=0;i<rmid.n;++i)
+  rmid[i]=1+i/2;
+cout << rmid << endl;
+real maxdeep = deep[].min;
+mesh3 Th=buildlayers(Th2,nn,
+  coef= deep/maxdeep,
+  zbound=[deep,0],
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+if(!NoUseOfWait)medit("Leman",Th);
+fespace Vh(Th,P13d);
+Vh p,q;
+//  (-deep[].min)*c = 0.5 Km
+//  c = 
+real cc=(0.5/-deep[].min);
+cout << cc << " cc = " << endl;
+cc=1; //  otherwise bug in boundaing condition ... 
+macro Grad(u) [dx(u),dy(u),cc*dz(u)] //
+
+real ain=int2d(Th,1)(1.);
+real aout=int2d(Th,2)(1.);
+cout << " area " << ain << " " << aout << endl;
+real din=1./ain;
+real dout=-1./aout;
+solve P(p,q)= int3d(Th)(Grad(p)'*Grad(q)+1e-5*p*q)-int2d(Th,1)(q*din)+int2d(Th,2)(q*dout);
+
+plot(p,wait=1,nbiso=30,value=1);
+if(!NoUseOfWait) medit("potentiel",Th,p,wait=1);
+
+real vregtest = p[].max ;
+cout << " p max " << vregtest << endl; 
\ No newline at end of file
diff --git a/examples++-3d/ArrayFE-3d.edp b/examples++-3d/ArrayFE-3d.edp
new file mode 100644
index 0000000..e69098c
--- /dev/null
+++ b/examples++-3d/ArrayFE-3d.edp
@@ -0,0 +1,5 @@
+mesh3 Th("dodecaedre01.mesh");
+fespace Vh(Th,P23d);
+Vh[int] u(10);
+u[1]=x;
+cout << " u[1].l2 =" << u[1][].l2 << endl;
\ No newline at end of file
diff --git a/examples++-3d/EqPoisson.edp b/examples++-3d/EqPoisson.edp
new file mode 100644
index 0000000..29bda42
--- /dev/null
+++ b/examples++-3d/EqPoisson.edp
@@ -0,0 +1,21 @@
+load "msh3" load "medit"
+func f=2*((0.1+(((x/3))*(x-1)*(x-1)/1+x/100))^(1/3.)-(0.1)^(1/3.));
+real yf=f(1.2,0); 
+border up(t=1.2,0.){ x=t;y=f;label=0;}
+border axe2(t=0.2,1.15) { x=t;y=0;label=0;}
+border hole(t=pi,0) { x= 0.15 + 0.05*cos(t);y= 0.05*sin(t); label=1;}
+border axe1(t=0,0.1) { x=t;y=0;label=0;}
+border queue(t=0,1) { x= 1.15 + 0.05*t; y = yf*t; label =0;}
+int np= 100;
+func bord= up(np)+axe1(np/10)+hole(np/10)+axe2(8*np/10)+ queue(np/10);
+plot( bord); 
+mesh Th2=buildmesh(bord);
+plot(Th2,wait=1);
+int[int] l23=[0,0,1,1]; 
+mesh3 Th=buildlayers(Th2,coef= max(.15,y/max(f,0.05)), 50 ,zbound=[0,2*pi]
+   ,transfo=[x,y*cos(z),y*sin(z)],facemerge=1,labelmid=l23);
+macro Grad(u) [dx(u),dy(u),dz(u)] //
+fespace Vh(Th,P1);  Vh u,v;
+solve Poisson(u,v) = int3d(Th)( Grad(u)'*Grad(v) ) - int3d(Th)( v) + on(1,u=1);
+plot(u,wait=1,nbiso=20,value=1);
+medit("u",Th,u,wait=1);
diff --git a/examples++-3d/Lac.edp b/examples++-3d/Lac.edp
new file mode 100644
index 0000000..aa9e046
--- /dev/null
+++ b/examples++-3d/Lac.edp
@@ -0,0 +1,20 @@
+load "msh3"
+load "medit"
+int nn=10;
+border cc(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
+mesh Th2= buildmesh(cc(100));
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+func zmin= 2-sqrt(4-(x*x+y*y));
+func zmax= 2-sqrt(3.);
+
+mesh3 Th=buildlayers(Th2,nn,
+  coef=  (zmax-zmin)/zmax ,
+  zbound=[zmin,zmax],
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+medit("Lac",Th,wait=1);
+// FFCS: testing 3d plots
+plot(Th,cmm="Lac");
diff --git a/examples++-3d/Laplace-Adapt-3d.edp b/examples++-3d/Laplace-Adapt-3d.edp
new file mode 100644
index 0000000..f9a33e2
--- /dev/null
+++ b/examples++-3d/Laplace-Adapt-3d.edp
@@ -0,0 +1,35 @@
+load "msh3" load "tetgen" load "mshmet" load "medit"
+//build initial mesh
+int nn  = 6;
+int[int] l1111=[1,1,1,1],l01=[0,1],l11=[1,1];//   label numbering 
+mesh3 Th3=buildlayers(square(nn,nn,region=0,label=l1111),
+      nn,  zbound=[0,1],  labelmid=l11,   labelup = l01,  labeldown = l01);
+Th3 = trunc(Th3,(x<0.5) | (y < 0.5) | (z < 0.5) ,label=1);// remove the $]0.5,1[^3 cube$
+//end of build initial mesh
+fespace Vh(Th3,P1);
+Vh u,v,usol;
+
+macro Grad(u) [dx(u),dy(u),dz(u)] // EOM
+
+problem Poisson(u,v,solver=CG) = int3d(Th3)( Grad(u)'*Grad(v) )  // ') for emacs 
+  -int3d(Th3)( 1*v ) + on(1,u=0);
+
+real errm=1e-2;// level of error 
+
+for(int ii=0; ii<5; ii++)
+{
+  Poisson;
+  cout <<" u min, max = " <<  u[].min << " "<< u[].max << endl;
+  Vh h ;
+  h[]=mshmet(Th3,u,normalization=1,aniso=0,nbregul=1,hmin=1e-3,hmax=0.3,err=errm);//loptions=MSHloptions,doptions=MSHdoptions);
+  cout <<" h min, max = " <<  h[].min << " "<< h[].max << " " << h[].n << " " << Th3.nv << endl;
+  // FFCS: add 3D view parameters
+  plot(u,wait=1,fill=0,boundary=0,CutPlane=0,ShowMeshes=1,LabelColors=0);
+  errm*= 0.8;// change the level of error
+  cout << " Th3" << Th3.nv < " " << Th3.nt << endl;
+  Th3=tetgreconstruction(Th3,switch="raAQ",sizeofvolume=h*h*h/6.);
+  medit("U-adap-iso-"+ii,Th3,u,wait=1);
+}
+
+
+
diff --git a/examples++-3d/Laplace-Adapt-aniso-3d.edp b/examples++-3d/Laplace-Adapt-aniso-3d.edp
new file mode 100644
index 0000000..88bd881
--- /dev/null
+++ b/examples++-3d/Laplace-Adapt-aniso-3d.edp
@@ -0,0 +1,89 @@
+// in test wrong skip 
+if(0) 
+
+{
+load "msh3"
+load "tetgen"
+load "mshmet"
+load "mmg3d-v4.0"
+load "freeyams"
+load "medit"
+searchMethod=1; // more safe seach algo ..
+macro det2(a,b,c,d) (a*d-c*b) //
+macro det3s(m11,m21,m31,m22,m32,m33)
+( m11*det2(m22,m32,m32,m33)
+ -m21*det2(m21,m31,m31,m33) 
+ +m31*det2(m11,m21,m21,m22) ) // 
+int nn  = 6;
+
+int[int] l1111=[1,1,1,1],l01=[0,1],l11=[1,1];//   label numbering 
+
+mesh3 Th3=buildlayers(square(nn,nn,region=0,label=l1111),
+      nn,  zbound=[0,1],  labelmid=l11,   labelup = l01,  labeldown = l01);
+// remove the $]0.5,1[^3 cube$
+Th3 = trunc(Th3,(x<0.5) | (y < 0.5) | (z < 0.5) ,label=1);
+
+fespace Vh(Th3,P1);
+fespace Mh(Th3,[P1,P1,P1,P1,P1,P1]);
+Vh u,v,usol,h3;
+Mh [m11,m21,m22,m31,m32,m33];
+macro Grad(u) [dx(u),dy(u),dz(u)] // EOM
+
+problem Poisson(u,v,solver=CG) = int3d(Th3)( Grad(u)'*Grad(v) )  // ') for emacs 
+  -int3d(Th3)( 1*v ) + on(1,u=0);
+
+int nbregu=1;
+int[int]  MSHloptions=[1,0,0,0,verbosity,nbregu,0];// mesh aniso ..
+real[int] MSHdoptions=[1e-3,0.2,0.01,0];
+real lerr=0.01;
+verbosity=4;
+for(int ii=0; ii<2; ii++) //  BUG trap  in interation 3 
+{
+  Poisson;
+  plot(u,wait=1);
+  h3=0;
+  [m11,m21,m22,m31,m32,m33]=[0,0,0,0,0,0];
+  cout <<" u min, max = " <<  u[].min << " "<< u[].max << endl;
+  real cc=(u[].max-u[].min);// rescale coefficiant 
+ 
+ // real[in t] met=mshmet(Th3,u,loptions=MSHloptions,doptions=MSHdoptions);
+  real[int] met=mshmet(Th3,u,hmin=1e-3,hmax=0.2,err=lerr,aniso=1);
+ // cot << met.n << " " << met2.n << endl;
+ m11[]=met;
+ // savemesh(Th3,"Th3.mesh");
+ // savesol("Th3.sol",Th3, [m11,m21,m22,m31,m32,m33]);
+  medit("met",Th3,[m11,m21,m22,m31,m32,m33]);
+  cout << " met size "<< met.n << " " << m11[].n << endl;
+  
+  verbosity=1;
+    mesh3 Thb=freeyams(Th3,metric=m11[],hmin=0.0001,hmax=0.3,gradation=2.,verbosity=-10);
+    h3=det3s(m11,m21,m31,m22,m32,m33);
+    real[int] rltetg = [0.1,0.1,.1,1,lerr*5];
+  Th3=tetg(Thb,switch="aAQpYY",regionlist=rltetg);
+  [m11,m21,m22,m31,m32,m33]=[m11,m21,m22,m31,m32,m33];
+   h3 = 1/sqrt(det3s(m11,m21,m31,m22,m32,m33));
+  cout <<" h3 min, max = " <<  h3[].min << " "<< h3[].max << endl;
+  Th3=tetgreconstruction(Th3,switch="raAQYY",sizeofvolume=h3/6.);
+  [m11,m21,m22,m31,m32,m33]=[m11,m21,m22,m31,m32,m33];
+  medit("met3",Th3,[m11,m21,m22,m31,m32,m33]);
+  int[int] mopt=[1,0,64,0,0,-10];
+   fespace Ph(Th3,P0);
+   Ph vol= volume;
+  medit("Vol",Th3,vol,order=0);
+
+  Th3=mmg3d(Th3,metric=m11[]); 
+  [m11,m21,m22,m31,m32,m33]=[m11,m21,m22,m31,m32,m33];
+  Th3=mmg3d(Th3,metric=m11[]); 
+  medit("Th3-"+ii,Th3,wait=1);
+
+ 
+  
+  lerr *= 0.6;// change the level of error
+  cout << " Th3" << Th3.nv < " " << Th3.nt << endl;
+  
+  medit("U-adap-iso-"+ii,Th3,u,wait=1);
+}
+cout <<"end Laplace  Adapt aniso 3d. edp " <<endl;
+
+
+}
\ No newline at end of file
diff --git a/examples++-3d/Laplace3d.edp b/examples++-3d/Laplace3d.edp
new file mode 100644
index 0000000..a043de7
--- /dev/null
+++ b/examples++-3d/Laplace3d.edp
@@ -0,0 +1,63 @@
+/*
+   Warning in before version 3.2-1 the nomarl are interal normal
+   after the signe is correct and now the noral was exterior normal. 
+ */
+verbosity=2;
+load "msh3"
+int nn=20;
+mesh Th2=square(nn,nn,region=0);
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+
+fespace Vh(Th,P2);
+
+func ue =   2*x*x + 3*y*y + 4*z*z + 5*x*y+6*x*z+1;
+func uex=   4*x+  5*y+6*z;
+func uey=   6*y + 5*x;
+func uez=   8*z +6*x;
+func f= -18. ;
+Vh uhe = ue; //
+
+cout << " uhe min:  " << uhe[].min << " max:" << uhe[].max << endl;
+
+Vh u,v;
+
+macro Grad3(u) [dx(u),dy(u),dz(u)]  // EOM
+
+
+  problem Lap3d(u,v,solver=CG)  =
+  int3d(Th)(Grad3(v)' *Grad3(u)) //') for emacs 
+  + int2d(Th,2)(u*v)  
+  - int3d(Th)(f*v) 
+  - int2d(Th,2) ( ue*v + (uex*N.x +uey*N.y +uez*N.z)*v )
+  + on(1,u=ue);
+Lap3d;
+cout << " u min::   " << u[]. min << "  max: " << u[].max << endl;
+real err= int3d(Th)( square(u-ue) );
+real aa1= int3d(Th,qfV=qfV1)(u) ;
+real aa2= int3d(Th,qfV=qfV1lump)(u) ;
+
+cout << " aa1 = " << aa1 << endl;
+cout << " aa2 = " << aa2 << endl;
+cout << int3d(Th)(1.) << " = " << Th.mesure << endl;
+cout << int3d(Th,qfV=qfV1)(1.) << " = " << Th.mesure << endl;
+cout << int3d(Th,qfV=qfV1lump)(1.) << " = " << Th.mesure << endl;
+Vh d= ue-u;
+cout <<  " err = " << err <<  " diff l^\intfy = " << d[].linfty << endl;
+real  aire2=int2d(Th,2)(1.); // bug correct in version 3.0-4 
+cout << " aire2 = " << aire2 << endl;
+func uuu= 2.+x;
+cout << uuu(1,1,1) << endl;
+assert( abs(aire2-1.) < 1e-6);
+plot(u,wait=1);
+
+assert( err < 1e-6);
+
diff --git a/examples++-3d/LaplaceRT-3d.edp b/examples++-3d/LaplaceRT-3d.edp
new file mode 100644
index 0000000..f797925
--- /dev/null
+++ b/examples++-3d/LaplaceRT-3d.edp
@@ -0,0 +1,154 @@
+/*
+   $ - \Delta p = f $   on $\Omega$, 
+   $ dp / dn = (g1d,g2d). n  $ on $\Gamma_{1}$ 
+   $ p = gd  $ on $\Gamma_{2}$    
+   with de Mixte finite element formulation 
+
+   Find $p\in L^2(\Omega) $  and $u\in H(div) $ such than 
+   $$  u - Grad p = 0    $$
+   $$ - div u =  f $$
+   $$  u. n = (g1d,g2d). n   \mbox{ on } \Gamma_{2}$$
+   $$ p = gd  \mbox{ on }\Gamma_{1}$$
+   the variationnel form is: 
+                                                                                                                   
+ $\forall v\in H(div)$;  $v.n = 0$ on $\Gamma_{2} $:  
+
+  $ \int_\Omega  u v + p div v -\int_{\Gamma_{1}} gd* v.n  = 0 $ 
+ $\forall q\in L^2$:   $  +\int_\Omega q div u = -\int_Omega f q  $
+and $ u.n = (g1n,g2n).n$ on $\Gamma_2$
+
+*/
+include "cube.idp"
+    int[int]  Nxyz=[10,10,10];
+    real [int,int]  Bxyz=[[0,1],[0,1],[0,1]];
+    int [int,int]  Lxyz=[[1,1],[1,1],[2,1]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+fespace Vh(Th,P1);
+fespace Rh(Th,RT03d);
+fespace Nh(Th,Edge03d);//  Nedelec Finite element. 
+fespace Ph(Th,P0);
+
+func gd = 1.;
+
+func g1n = 2.;
+func g2n = 3.; 
+func g3n = 4.; 
+
+func f = 1.;
+
+Rh [u1,u2,u3],[v1,v2,v3];
+Nh [e1,e2,e3];
+[u1,u2,u3]=[1+100*x,2+100*y,3+100*z];
+
+// a + b ^ x = 
+/*
+  b1    x     a1 + b2*z - b3*y 
+  b2 ^  y  =  a2 - b1*z + b3*x
+  b3    z     a3 + b1*y - b2*x
+*/
+real b1=30,b2=10,b3=20;
+func ex1=100+b2*z-b3*y;
+
+func ex1x=0.;
+func ex1y=-b3+0;
+func ex1z=b2+0;
+
+func ex2=200.- b1*z + b3*x ;
+func ex2x= b3 +0;
+func ex2y= 0. ;
+func ex2z= -b1 +0;
+func ex3=300.+b1*y - b2*x ;
+func ex3x= -b2 +0;
+func ex3y= b1 +0;
+func ex3z= 0. ;
+[e1,e2,e3]=[ex1,ex2,ex3]; 
+
+int k=Th(.1,.2,.3).nuTriangle ;
+cout << " u = " << u1(.1,.2,.3)  << " " << u2(.1,.2,.3) << " " << u3(.1,.2,.3) << endl;
+cout << " dx u = " << dx(u1)(.1,.2,.3)  << " " << dy(u2)(.1,.2,.3) << " " << dz(u3)(.1,.2,.3) << endl;
+
+cout << " e  = " << e1(.1,.2,.3)  << " " << e2(.1,.2,.3) << " " << e3(.1,.2,.3) << endl;
+cout << " ex = " << ex1(.1,.2,.3)  << " " << ex2(.1,.2,.3) << " " << ex3(.1,.2,.3) << endl;
+
+
+cout << " dx,dy,dz   e1x= " << ex1x(.1,.2,.3)  << " " << ex1y(.1,.2,.3) << " " << ex1z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2x= " << ex2x(.1,.2,.3)  << " " << ex2y(.1,.2,.3) << " " << ex2z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3x= " << ex3x(.1,.2,.3)  << " " << ex3y(.1,.2,.3) << " " << ex3z(.1,.2,.3) << endl;
+
+cout << " dx,dy,dz   e1 = " << dx(e1)(.1,.2,.3)  << " " << dy(e1)(.1,.2,.3) << " " << dz(e1)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2 = " << dx(e2)(.1,.2,.3)  << " " << dy(e2)(.1,.2,.3) << " " << dz(e2)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3 = " << dx(e3)(.1,.2,.3)  << " " << dy(e3)(.1,.2,.3) << " " << dz(e3)(.1,.2,.3) << endl;
+
+
+cout << " k = " << k << endl;
+cout << Rh(k,0) << " " <<Rh(k,1) << " " <<Rh(k,2) << " " <<Rh(k,3) << endl;
+cout << " df = " << u1[][Rh(k,0)] <<  " " << u1[][Rh(k,1)]  <<" " << u1[][Rh(k,2)]  << " " << u1[][Rh(k,2)] << endl;
+// cout << u1[] << endl;
+
+Vh P,Q;
+Ph p,q; 
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //
+macro Grad(u) [dx(u),dy(u),dz(u)]  //
+  problem laplace(P,Q,solver=CG) = 
+  int3d(Th) ( Grad(P)'*Grad(Q)) //') for emacs
+  - int3d(Th)(f*Q) 
+  + on(1,P=gd) 
+  - int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q);
+
+fespace RPh(Th,[RT03d,P0]);
+varf von1([u1,u2,u3,p],[v1,v2,v3,q])  = 
+   int3d(Th)( p*q*1e-15+ u1*v1 + u2*v2 + u3*v3 + p*div(v1,v2,v3) + div(u1,u2,u3)*q )
+ - int3d(Th) ( f*q)
+ + int2d(Th,1)( gd*(v1*N.x +v2*N.y + v3*N.z) )  //  int on gamma 
+ + on(2,u1=g1n,u2=g2n,u3=g3n);
+
+RPh [vv1,vv2,vv3,qq];
+// some verification Boundary Condition
+// and interpolation ...
+real[int]  ron=von1(0,RPh);
+vv3[]=von1(0,RPh);
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << endl;
+[vv1,vv2,vv3,qq]=[g1n,g2n,g3n,100];
+[v1,v2,v3]=[g1n,g2n,g3n];
+
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << " " << qq(.1,.2,.001) << endl;
+cout << " v : = " << v1(.1,.2,.001)  << " " << v2(.1,.2,.001) << " " << v3(.1,.2,.001)  << endl;
+
+// end of verification of Boundary Condition ... 
+
+problem laplaceMixte([u1,u2,u3,p],[v1,v2,v3,q],solver=GMRES,eps=1.0e-10,tgv=1e30,dimKrylov=400) =
+   int3d(Th)( p*q*1e-15+ u1*v1 + u2*v2 + u3*v3 + p*div(v1,v2,v3) + div(u1,u2,u3)*q )
+ + int3d(Th) ( f*q)
+ - int2d(Th,1)( gd*(v1*N.x +v2*N.y + v3*N.z) )  //  int on gamma 
+ + on(2,u1=g1n,u2=g2n,u3=g3n);
+
+laplace;
+
+// FFCS: add 3D view parameters
+real[int] CameraPositionValue = [0.0165449,3.23891,-0.991528];
+real[int] CameraFocalPointValue = [0.5,0.5,0.5];
+real[int] CameraViewUpValue = [0.671735,0.442219,0.594318];
+real[int] CutPlaneOriginValue = [0.5,0.5,1.01];
+real[int] CutPlaneNormalValue = [0.689523,0.722423,0.0516115];
+plot(P,fill=0,boundary=0,ShowMeshes=1,CutPlane=1,
+	CameraPosition=CameraPositionValue,
+	CameraFocalPoint=CameraFocalPointValue,
+	CameraViewUp=CameraViewUpValue,
+	CutPlaneOrigin=CutPlaneOriginValue,
+	CutPlaneNormal = CutPlaneNormalValue);
+
+laplaceMixte;
+
+real errL2=sqrt(int3d(Th)(square(P-p))) ;
+cout << " int 2 x,yz "<<int2d(Th,2)(x) << " " << int2d(Th,2)(y) << " " << int2d(Th,2)(z) << endl;
+cout << " int 2 gn "<<int2d(Th,2)(g1n) << " " << int2d(Th,2)(g2n) << " " << int2d(Th,2)(g3n) << endl;
+cout << " int 2 U  "<<int2d(Th,2)(u1) << " " << int2d(Th,2)(u2) << " " << int2d(Th,2)(u3) << endl;
+cout << " int 2 V  "<<int2d(Th,2)(vv1) << " " << int2d(Th,2)(vv2) << " " << int2d(Th,2)(vv3) << endl;
+cout << " int 2 DP "<<int2d(Th,2)(dx(P)) << " " << int2d(Th,2)(dy(P)) << " " << int2d(Th,2)(dz(P)) << endl;
+  
+cout << "  diff: u Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (u1*N.x +u2*N.y + u3*N.z) ) ) ) <<endl;
+cout << "  diff: P Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (dx(P)*N.x +dy(P)*N.y + dz(P)*N.z) ) ) ) <<endl;
+cout << " diff err L2 :" << errL2 << endl;
+cout << "    P     L2 :" <<sqrt(int3d(Th)(square(P))) << endl;
+cout << "    p     L2 :" <<sqrt(int3d(Th)(square(p))) << endl;
+assert(errL2<0.05);
\ No newline at end of file
diff --git a/examples++-3d/Makefile.am b/examples++-3d/Makefile.am
new file mode 100644
index 0000000..fcd4579
--- /dev/null
+++ b/examples++-3d/Makefile.am
@@ -0,0 +1,46 @@
+# $Id$
+
+all-local: all.edp regtests.edp  freefem++.pref
+
+TESTS=3d-Leman.edp ArrayFE-3d.edp EqPoisson.edp Lac.edp Laplace-Adapt-3d.edp Laplace-Adapt-aniso-3d.edp Laplace3d.edp LaplaceRT-3d.edp NSI3d-carac.edp NSI3d.edp Period-Poisson-cube-ballon.edp Poisson-cube-ballon.edp Poisson.edp Poisson3d.edp Stokes.edp TruncLac.edp  beam-3d.edp cone.edp convect-3d.edp cube-period.edp cylinder-3d.edp cylinder.edp fallingspheres.edp first.edp meditddm.edp p.edp periodic-3d.edp pyramide.edp  refinesphere.edp  schwarz-nm-3d.edp sphere2.edp sphere6.edp tetgen [...]
+XFAIL_TESTS=Laplace-Adapt-aniso-3d.edp fallingspheres.edp Laplace-Adapt-3d.edp Period-Poisson-cube-ballon.edp Poisson-cube-ballon.edp cylinder.edp refinesphere.edp tetgencube.edp tetgenholeregion.edp Poisson3d.edp  schwarz-nm-3d.edp 
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPP) FLAGS_FFPP=-nw
+
+LIST_IDP=MeshSurface.idp cube.idp
+
+EXTRA_DIST=*.edp  all.edp regtests.edp regtests.m4 ref.edp dodecaedre01.mesh \
+  lac-leman-v4.msh $(LIST_IDP)
+
+
+
+all.edp:  Makefile
+	(echo "NoGraphicWindow=true;NoUseOfWait=true;int verbosityy=verbosity;int MEM1234=storageused();"; \
+	for i in *`ls *.edp|grep -v -E '^(all|regtests|makeref|ref)\.edp$$'` ; do  \
+		echo ' cout << "--------- file : '$$i' --------------------------------------------------------" << endl;' ;\
+		echo "verbosity=verbosityy;searchMethod=0;" ; \
+		echo \{ include \"$$i\"\;\}\; ;\
+		echo ' cout << " mem leak = " <<storageused() - MEM1234 << endl << "------------------------------------------------------------------------------ " << endl;' ;\
+	done) > $@
+
+# To create a new set of reference values in "ref.edp"
+Ref: makeref.edp freefem++.pref
+	export  FF_LOADPATH=../examples++-load/.;../src/nw/FreeFem++-nw makeref.edp
+
+makeref.edp: regtests.m4 ../regtests.m4
+	m4 regtests.m4 > makeref.edp
+
+freefem++.pref:
+	echo loadpath = \"../examples++-load/\" >freefem++.pref
+	echo loadpath += \"./\" >>freefem++.pref
+3d-Leman.edp:freefem++.pref
+install-exec-local:: 
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/idp
+	$(INSTALL)  -m 555  $(LIST_IDP)  $(DESTDIR)$(ff_prefix_dir)/idp
+
+
+
+# To check the scripts against their reference values
+regtests.edp: regtests.m4 ../regtests.m4
+	m4 -DASSERT regtests.m4 > regtests.edp
+FORCE:
diff --git a/examples++-3d/MeshSurface.idp b/examples++-3d/MeshSurface.idp
new file mode 100644
index 0000000..abe1b39
--- /dev/null
+++ b/examples++-3d/MeshSurface.idp
@@ -0,0 +1,112 @@
+load "msh3"
+load "medit"
+load "freeyams"
+// 2 basic functions to build surface mesh 
+/*  Usage:
+  mesh3   SurfaceHex(N,B,L,orient);
+  --   build the surface mesh of a 3d box 
+  where: for example:
+    int[int]  N=[nx,ny,nz]; //  the number of seg in the 3 direction
+    real [int,int]  B=[[xmin,xmax],[ymin,ymax],[zmin,zmax]]; // bounding bax  
+    int [int,int]  L=[[1,2],[3,4],[5,6]]; // the label of the 6 face left,right, front, back, down, right
+    orient the global orientation of the surface 1 extern (-1 intern)
+
+
+  func mesh3 Sphere(real R,real h,int L,int orient);
+  -- build a surface mesh of a sphere with 1 mapping (spheriale coordinate) 
+     where R is  the raduis, 
+     h is the mesh size  of  the shpere
+     L is the label the the sphere
+     orient the global orientation of the surface 1 extern (-1 intern
+
+*/
+func mesh3 SurfaceHex(int[int] & N,real[int,int] &B ,int[int,int] & L,int orientation)
+{
+    real x0=B(0,0),x1=B(0,1);
+    real y0=B(1,0),y1=B(1,1);
+    real z0=B(2,0),z1=B(2,1);
+    
+    int nx=N[0],ny=N[1],nz=N[2];
+    
+    mesh Thx = square(ny,nz,[y0+(y1-y0)*x,z0+(z1-z0)*y]);
+    mesh Thy = square(nx,nz,[x0+(x1-x0)*x,z0+(z1-z0)*y]);
+    mesh Thz = square(nx,ny,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+    
+    int[int] refx=[0,L(0,0)],refX=[0,L(0,1)];   //  Xmin, Ymax faces labels renumbering 
+    int[int] refy=[0,L(1,0)],refY=[0,L(1,1)];   //  Ymin, Ymax faces labesl renumbering 
+    int[int] refz=[0,L(2,0)],refZ=[0,L(2,1)];   //  Zmin, Zmax faces labels renumbering 
+    
+    mesh3 Thx0 = movemesh23(Thx,transfo=[x0,x,y],orientation=-orientation,label=refx);
+    mesh3 Thx1 = movemesh23(Thx,transfo=[x1,x,y],orientation=+orientation,label=refX);
+    mesh3 Thy0 = movemesh23(Thy,transfo=[x,y0,y],orientation=+orientation,label=refy);
+    mesh3 Thy1 = movemesh23(Thy,transfo=[x,y1,y],orientation=-orientation,label=refY);
+    mesh3 Thz0 = movemesh23(Thz,transfo=[x,y,z0],orientation=-orientation,label=refz);
+    mesh3 Thz1 = movemesh23(Thz,transfo=[x,y,z1],orientation=+orientation,label=refZ);
+    mesh3 Th= Thx0+Thx1+Thy0+Thy1+Thz0+Thz1;
+    return Th;
+}
+func mesh3 Ellipsoide (real RX,real RY, real RZ,real h,int L,int orientation)
+{
+  mesh  Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},frac{-pi}{2}[\times]0,2\pi[ $
+  //  a parametrization of a sphere 
+  func f1 =RX*cos(x)*cos(y);
+  func f2 =RY*cos(x)*sin(y);
+  func f3 =RZ*sin(x);
+  //    partiel derivative 
+  func f1x= -RX*sin(x)*cos(y);   
+  func f1y= -RX*cos(x)*sin(y);
+  func f2x= -RY*sin(x)*sin(y);
+  func f2y= +RY*cos(x)*cos(y);
+  func f3x=-RZ*cos(x);
+  func f3y=0;
+  // the metric on the sphere  $  M = DF^t DF $
+  func m11=f1x^2+f2x^2+f3x^2;
+  func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+  func m22=f1y^2+f2y^2+f3y^2;
+  
+  func perio=[[4,y],[2,y],[1,x],[3,x]];  // to store the periodic condition 
+  
+  real hh=h;// hh  mesh size on unite sphere
+  real vv= 1/square(hh);
+  Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+  Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+  Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+  Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+  int[int] ref=[0,L];  
+  
+  mesh3  ThS= movemesh23(Th,transfo=[f1,f2,f3],orientation=orientation,refface=ref);
+  ThS=freeyams(ThS,hmin=h,hmax=h,gradation=2.,verbosity=-10,mem=100,option=0);
+  return ThS;
+}
+ 
+ 
+func mesh3 Sphere(real R,real h,int L,int orientation)
+{
+
+  return Ellipsoide(R,R,R,h,L,orientation);
+}
+/*  test: 
+ load "tetgen" 
+  {   
+    real hs = 0.1;  // mesh size on sphere 
+    int[int]  N=[20,20,20];
+    real [int,int]  B=[[-1,1],[-1,1],[-1,1]];
+    int [int,int]  L=[[1,2],[3,4],[5,6]];
+    
+    ////////////////////////////////
+    mesh3 ThH = SurfaceHex(N,B,L,1);
+    mesh3 ThS =Sphere(0.5,hs,7,1); // "gluing" surface meshs to tolat boundary meshes
+    cout << " xxxx" << ThH.nv << " " << ThS.nv << endl;
+    
+    mesh3 ThHS=ThH+ThS;
+    savemesh(ThHS,"Hex-Sphere.mesh");
+    exec("ffmedit Hex-Sphere.mesh;rm Hex-Sphere.mesh");
+    
+    real voltet=(hs^3)/6.;
+    cout << " voltet = " << voltet << endl;
+    real[int] domaine = [0,0,0,1,voltet,0,0,0.7,2,voltet];
+  
+    mesh3 Th = tetg(ThHS,switch="pqaAAYYQ",nbofregions=2,regionlist=domaine);    
+    medit("Cube-With-Ball",Th);
+  }
+*/
\ No newline at end of file
diff --git a/examples++-3d/NSI3d-carac.edp b/examples++-3d/NSI3d-carac.edp
new file mode 100644
index 0000000..6e113cc
--- /dev/null
+++ b/examples++-3d/NSI3d-carac.edp
@@ -0,0 +1,107 @@
+load "msh3"
+real nu=0.01,dt=0.3;
+real alpha=1./dt,alpha2=sqrt(alpha);
+
+int nn=5;
+
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  // region=r1, 
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+fespace VVh(Th,[P23d,P23d,P23d,P13d]);
+fespace Vh(Th,P23d);
+fespace Ph(Th,P13d);
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+  
+  varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3)
+             - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+ +  on(2,u1=1.,u2=0,u3= 0)
+ + on(1,u1=0,u2=0,u3=0)
+ ;
+
+cout << "b  mat " << endl;
+
+matrix A=vStokes(VVh,VVh);
+cout << "e  mat " << endl;
+set(A,solver=UMFPACK);
+cout << "e fac  mat " << endl;
+real[int] b= vStokes(0,VVh);
+
+VVh [u1,u2,u3,p];
+VVh [X1,X2,X3,Xp];
+VVh [x1,x2,x3,xp]=[x,y,z,0];
+
+
+
+u1[]= A^-1 * b;
+
+ux= u1(x,0.5,y);
+uz= u3(x,0.5,y);
+p2= p(x,0.5,y);
+plot([ux,uz],p2,cmm=" cut y = 0.5",wait=1);
+macro XX1() (x-u1*dt)//
+macro XX2() (y-u2*dt)//
+macro XX3() (z-u3*dt)//
+
+  varf vNS([uu1,uu2,uu3,p],[v1,v2,v3,q]) = 
+  int3d(Th)( alpha*(uu1*v1+uu2*v2+uu3*v3) + nu*(Grad(uu1)'*Grad(v1) +  Grad(uu2)'*Grad(v2) +  Grad(uu3)'*Grad(v3))
+  - div(uu1,uu2,uu3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,uu1=1,uu2=0,uu3=0)
+  + on(1,uu1=0,uu2=0,uu3=0)
+ 
+    +  int3d(Th,optimize=1,qforder=4)(   alpha*(  convect([u1,u2,u3],-dt,u1)*v1  +   convect([u1,u2,u3],-dt,u2)*v2  +   convect([u1,u2,u3],-dt,u3)*v3 )  ) ;
+  //   +  int3d(Th,optimize=1)(   alpha*(  u1(X1,X2,X3)*v1  +  u2(X1,X2,X3)*v2  +  u3(X1,X2,X3)*v3 )  ) ;
+//  +  int3d(Th,optimize=1)(   alpha*(  u1(XX1,XX2,XX3)*v1  +  u2(XX1,XX2,XX3)*v2  +  u3(XX1,XX2,XX3)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1(x,y,z)*v1  +  u2(x,y,z)*v2  +  u3(x,y,z)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1*v1  +  u2*v2  +  u3*v3 )  ) ;
+
+cout << " build  A" << endl;
+A = vNS(VVh,VVh);
+cout << " fac A" << endl;
+set(A,solver=UMFPACK);
+real t=0;
+for(int i=0;i<10;++i)
+  {
+    t += dt;
+    cout << " iteration " << i << " t = " << t << endl;
+    X1[]=x1[]+u1[]*(-dt);
+    //    verbosity=1000;
+    b=vNS(0,VVh);
+    verbosity=2;
+    u1[]= A^-1 * b;
+    ux= u1(x,0.5,y);
+    uz= u3(x,0.5,y);
+    p2= p(x,0.5,y);
+    plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=0);
+    if(i%5==6)
+    {
+      exec("mkdir dd");
+      string prefu="dd/u-"+(100+i);
+      string prefp="dd/p-"+(100+i);
+      savemesh(Th,prefu+".mesh");
+      savemesh(Th,prefp+".mesh");
+     
+      ofstream file(prefu+".bb"); 
+      ofstream filep(prefp+".bb"); 
+      Ph up1=u1,up2=u2,up3=u3,pp=p;
+      file << "3 1 3 "<< up1[].n << " 2 \n";
+      filep << "3 1 1 "<< pp[].n << " 2 \n";
+      for (int j=0;j<up1[].n ; j++)  
+	{
+	  file << up1[][j] <<" " <<up2[][j] <<" "<< up3[][j] <<"\n";
+	  filep << pp[][j] <<  endl; 
+	}  
+    }
+  }
+plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=1);
diff --git a/examples++-3d/NSI3d.edp b/examples++-3d/NSI3d.edp
new file mode 100644
index 0000000..f5a5c7b
--- /dev/null
+++ b/examples++-3d/NSI3d.edp
@@ -0,0 +1,105 @@
+load "msh3"
+real nu=0.01,dt=0.3;
+real alpha=1./dt,alpha2=sqrt(alpha);
+
+int nn=5;
+
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  // region=r1, 
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+fespace VVh(Th,[P23d,P23d,P23d,P13d]);
+fespace Vh(Th,P23d);
+fespace Ph(Th,P13d);
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+  
+  varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3)
+             - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+ +  on(2,u1=1.,u2=0,u3= 0)
+ + on(1,u1=0,u2=0,u3=0)
+ ;
+
+cout << "b  mat " << endl;
+
+matrix A=vStokes(VVh,VVh);
+cout << "e  mat " << endl;
+set(A,solver=UMFPACK);
+cout << "e fac  mat " << endl;
+real[int] b= vStokes(0,VVh);
+
+VVh [u1,u2,u3,p];
+VVh [X1,X2,X3,Xp];
+VVh [x1,x2,x3,xp]=[x,y,z,0];
+
+
+
+u1[]= A^-1 * b;
+
+ux= u1(x,0.5,y);
+uz= u3(x,0.5,y);
+p2= p(x,0.5,y);
+plot([ux,uz],p2,cmm=" cut y = 0.5",wait=1);
+macro XX1() (x-u1*dt)//
+macro XX2() (y-u2*dt)//
+macro XX3() (z-u3*dt)//
+
+  varf vNS([uu1,uu2,uu3,p],[v1,v2,v3,q]) = 
+  int3d(Th)( alpha*(uu1*v1+uu2*v2+uu3*v3) + nu*(Grad(uu1)'*Grad(v1) +  Grad(uu2)'*Grad(v2) +  Grad(uu3)'*Grad(v3))
+  - div(uu1,uu2,uu3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,uu1=1,uu2=0,uu3=0)
+  + on(1,uu1=0,uu2=0,uu3=0)
+   +  int3d(Th,optimize=1)(   alpha*(  u1(X1,X2,X3)*v1  +  u2(X1,X2,X3)*v2  +  u3(X1,X2,X3)*v3 )  ) ;
+//  +  int3d(Th,optimize=1)(   alpha*(  u1(XX1,XX2,XX3)*v1  +  u2(XX1,XX2,XX3)*v2  +  u3(XX1,XX2,XX3)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1(x,y,z)*v1  +  u2(x,y,z)*v2  +  u3(x,y,z)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1*v1  +  u2*v2  +  u3*v3 )  ) ;
+
+cout << " build  A" << endl;
+A = vNS(VVh,VVh);
+cout << " fac A" << endl;
+set(A,solver=UMFPACK);
+real t=0;
+for(int i=0;i<10;++i)
+  {
+    t += dt;
+    cout << " iteration " << i << " t = " << t << endl;
+    X1[]=x1[]+u1[]*(-dt);
+    //    verbosity=200;
+    b=vNS(0,VVh);
+    verbosity=2;
+    u1[]= A^-1 * b;
+    ux= u1(x,0.5,y);
+    uz= u3(x,0.5,y);
+    p2= p(x,0.5,y);
+    plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=0);
+    if(0)
+    {
+      exec("mkdir dd");
+      string prefu="dd/u-"+(100+i);
+      string prefp="dd/p-"+(100+i);
+      savemesh(Th,prefu+".mesh");
+      savemesh(Th,prefp+".mesh");
+     
+      ofstream file(prefu+".bb"); 
+      ofstream filep(prefp+".bb"); 
+      Ph up1=u1,up2=u2,up3=u3,pp=p;
+      file << "3 1 3 "<< up1[].n << " 2 \n";
+      filep << "3 1 1 "<< pp[].n << " 2 \n";
+      for (int j=0;j<up1[].n ; j++)  
+	{
+	  file << up1[][j] <<" " <<up2[][j] <<" "<< up3[][j] <<"\n";
+	  filep << pp[][j] <<  endl; 
+	}  
+    }
+  }
+plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=1);
diff --git a/examples++-3d/Period-Poisson-cube-ballon.edp b/examples++-3d/Period-Poisson-cube-ballon.edp
new file mode 100755
index 0000000..dc9dd11
--- /dev/null
+++ b/examples++-3d/Period-Poisson-cube-ballon.edp
@@ -0,0 +1,64 @@
+verbosity=1;
+load "msh3"
+load "tetgen"
+load "medit"
+include "MeshSurface.idp"
+
+mesh3 Th;
+try {
+  Th=readmesh3("Th-hex-sph.mesh");
+ }
+catch(...)
+  { 
+    real hs = 0.2;  // mesh size on sphere 
+    int[int]  NN=[11,9,10];
+    real [int,int]  BB=[[-1.1,1.1],[-.9,.9],[-1,1]];
+    int [int,int]  LL=[[1,2],[3,4],[5,6]];
+    
+    ////////////////////////////////
+    mesh3 ThHS = SurfaceHex(NN,BB,LL,1)+Sphere(0.5,hs,7,1); // "gluing" surface meshs to tolat boundary meshes
+    real voltet=(hs^3)/6.;
+    cout << " voltet = " << voltet << endl;
+    real[int] domaine = [0,0,0,1,voltet,0,0,0.7,2,voltet];
+    
+    mesh3 Th = tetg(ThHS,switch="pqaAYY",nbofregions=2,regionlist=domaine);    
+    // Tetrahelize the interior of the cube with tetgen
+    medit("tetg",Th,wait=1);
+    savemesh(Th,"Th-hex-sph.mesh");
+    // FFCS: testing 3d plots
+    plot(Th);
+ }
+
+
+
+fespace Ph(Th,P0);
+verbosity=50;
+fespace Vh(Th,P1,periodic=[[3,x,z],[4,x,z],[1,y,z],[2,y,z],[5,x,y],[6,x,y]]);// back and front
+verbosity=1;
+Ph reg=region;
+
+cout << "  centre = " << reg(0,0,0) << endl;
+cout << " exterieur = " << reg(0,0,0.7) << endl;
+
+macro Grad(u) [dx(u),dy(u),dz(u)] // EOM
+
+Vh uh,vh;
+real x0=0.3,y0=0.4,z0=06;
+func f= sin(x*2*pi+x0)*sin(y*2*pi+y0)*sin(z*2*pi+z0);
+real gn = 1.;
+real cf= 1;
+problem P(uh,vh,solver=sparsesolver)=
+     int3d(Th,1)( Grad(uh)'*Grad(vh)*100) 
+  +  int3d(Th,2)( Grad(uh)'*Grad(vh)*2) 
+  + int3d(Th) (vh*f)
+//  + on(-1,uh=-1) + on(1,uh=1) 
+//  + int2d(Th,2,-2)(vh*gn)
+//  + int2d(Th,3,-3)(cf*vh*uh)
+  ; 
+  
+  P;
+
+plot(uh,wait=1, nbiso=6);
+medit("   uh ",Th, uh,wait=1); 
+
+
diff --git a/examples++-3d/Poisson-cube-ballon.edp b/examples++-3d/Poisson-cube-ballon.edp
new file mode 100644
index 0000000..293a207
--- /dev/null
+++ b/examples++-3d/Poisson-cube-ballon.edp
@@ -0,0 +1,134 @@
+verbosity=1;
+load "msh3"
+load "tetgen"
+load "medit"
+
+ 
+// 
+mesh3 ThHex;
+real volumetet;  // use in tetg.
+{
+	//  first  build the 6 faces of the hex.
+real x0=-1,x1=1;
+real y0=-1.1,y1=1.1;
+real z0=-1.2,z1=1.2;
+
+int nx=19,ny=20,nz=21;
+//  a  volume  of  on tet. 
+volumetet= (x1-x0)*(y1-y0)*(z1-z0)/ (nx*ny*ny) /6.;
+
+mesh Thx = square(ny,nz,[y0+(y1-y0)*x,z0+(z1-z0)*y]);
+mesh Thy = square(nx,nz,[x0+(x1-x0)*x,z0+(z1-z0)*y]);
+mesh Thz = square(nx,ny,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+int[int] refz=[0,5];  //  bas
+int[int] refZ=[0,6];   //  haut
+int[int] refy=[0,3];  //  devant
+int[int] refY=[0,4];   // derriere
+int[int] refx=[0,1];  // gauche
+int[int] refX=[0,2];   // droite 
+
+
+mesh3 Thx0 = movemesh23(Thx,transfo=[x0,x,y],orientation=-1,label=refx);
+mesh3 Thx1 = movemesh23(Thx,transfo=[x1,x,y],orientation=1,label=refX);
+mesh3 Thy0 = movemesh23(Thy,transfo=[x,y0,y],orientation=+1,label=refy);
+mesh3 Thy1 = movemesh23(Thy,transfo=[x,y1,y],orientation=-1,label=refY);
+mesh3 Thz0 = movemesh23(Thz,transfo=[x,y,z0],orientation=-1,label=refz);
+mesh3 Thz1 = movemesh23(Thz,transfo=[x,y,z1],orientation=+1,label=refZ);
+
+//medit("  --- ", Thx0,Thx1,Thy0,Thy1,Thz0,Thz1);
+ ThHex = Thx0+Thx1+Thy0+Thy1+Thz0+Thz1;
+ 
+}
+mesh3 Thsph; // 
+
+{
+mesh  Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},frac{-pi}{2}[\times]0,2\pi[ $
+//  a paratrization of a sphere 
+func f1 =cos(x)*cos(y);
+func f2 =cos(x)*sin(y);
+func f3 = sin(x);
+//  de  partiel derivatrive of the parametrization DF
+func f1x=sin(x)*cos(y);   
+func f1y=-cos(x)*sin(y);
+func f2x=-sin(x)*sin(y);
+func f2y=cos(x)*cos(y);
+func f3x=cos(x);
+func f3y=0;
+// $  M = DF^t DF $
+func m11=f1x^2+f2x^2+f3x^2;
+func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+func m22=f1y^2+f2y^2+f3y^2;
+
+func perio=[[4,y],[2,y],[1,x],[3,x]];  // to store the periodic condition 
+
+// the intial mesh
+savemesh(Th,"sphere",[f1,f2,f3]);
+
+real R=0.5,hh=0.1/R;// hh  taille du maille sur la shere unite. 
+real vv= 1/square(hh);
+verbosity=2;
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,inquire=1,periodic=perio);
+plot(Th,wait=1);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+
+Thsph = movemesh23(Th,transfo=[f1*R,f2*R,f3*R],orientation=-1);
+}
+
+
+////////////////////////////////
+mesh3 ThS = ThHex+Thsph; // "gluing" surface meshs to tolat boundary meshes
+medit("Bounday mesh",ThS,wait=1);
+
+// build a mesh of a axis parallel box with TetGen
+
+real[int] domaine = [0,0,0,1,volumetet,0,0,0.7,2,volumetet];
+mesh3 Th = tetg(ThS,switch="pqaAAYYQ",nbofregions=2,regionlist=domaine);    
+// Tetrahelize the interior of the cube with tetgen
+medit("tetg",Th,wait=1);
+savemesh(Th,"Th-hex-sph.mesh");
+
+fespace Ph(Th,P03d);
+fespace Vh(Th,P13d);
+Ph reg=region;
+
+cout << "  centre = " << reg(0,0,0) << endl;
+cout << " exterieur = " << reg(0,0,0.7) << endl;
+
+macro Grad(u) [dx(u),dy(u),dz(u)] // EOM
+
+Vh uh,vh;
+real f=1.;
+real gn = 1.;
+real cf= 1;
+problem P(uh,vh)=
+   int3d(Th,1)( Grad(uh)'*Grad(vh)*100) 
+  +  int3d(Th,2)( Grad(uh)'*Grad(vh)*2) 
+  + int3d(Th) (vh*f)
+  + on(-1,uh=-1) + on(1,uh=1) 
+  + int2d(Th,2,-2)(vh*gn)
+  + int2d(Th,3,-3)(cf*vh*uh)
+  ; 
+  
+  P;
+
+// FFCS: with 3D view parameters
+real[int] CameraPositionValue = [3.50634,-2.51489,2.60313];
+real[int] CameraFocalPointValue = [0.0604689,-0.304636,-0.256484];
+real[int] CameraViewUpValue = [0.7198,0.502367,-0.479078];
+real[int] CutPlaneOriginValue = [-0.5,-0.55,0.0335184];
+real[int] CutPlaneNormalValue = [0,0,1];
+plot(uh,wait=1, nbiso=6,
+	BorderAsMesh = 1,
+	CameraPosition=CameraPositionValue,
+	CameraFocalPoint=CameraFocalPointValue,
+	CameraViewUp=CameraViewUpValue,
+	CutPlaneOrigin=CutPlaneOriginValue,
+	CutPlaneNormal = CutPlaneNormalValue);
+medit("   uh ",Th, uh,wait=1); 
+
+
diff --git a/examples++-3d/Poisson.edp b/examples++-3d/Poisson.edp
new file mode 100644
index 0000000..42ae9ed
--- /dev/null
+++ b/examples++-3d/Poisson.edp
@@ -0,0 +1,48 @@
+verbosity=2;
+
+mesh3 Th("dodecaedre01");
+fespace Vh(Th,P23d);
+func ue =   2*x*x + 3*y*y + 4*z*z + 5*x*y+6*x*z+1;
+func uex=   4*x+  5*y+6*z;
+func uey=   6*y + 5*x;
+func uez=   8*z +6*x;
+func f= -18. ;
+Vh uhe = ue; // bug ..
+cout << " uhe min:  " << uhe[]. min << " max:" << uhe[].max << endl;
+
+border cc(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
+mesh Th2=buildmesh(cc(50));
+fespace Vh2(Th2,P2);
+
+
+Vh u,v;
+
+macro Grad3(u) [dx(u),dy(u),dz(u)]  // EOM
+
+problem Lap3d(u,v,solver=CG)=int3d(Th)(Grad3(v)' *Grad3(u)) - int3d(Th)(f*v) 
++ on(0,1,u=ue);
+Lap3d;
+cout << " u min::   " << u[]. min << "  max: " << u[].max << endl;
+real err= int3d(Th)( square(u-ue) );
+cout << int3d(Th)(1.) << " = " << Th.mesure << endl;
+plot(u,wait=1);
+Vh d= ue-u;
+cout <<  " err = " << err <<  " diff l^\intfy = " << d[].linfty << endl;
+Vh2 u2=u,u2e=ue;
+plot(u2,wait=1);
+plot(u2,u2e,wait=1);
+
+// test new plot ... 
+plot(Th,wait=1);
+plot(u,wait=1);
+
+/*
+	{
+ ofstream file("dd.bb"); 
+	file << "3 1 1 "<< u[].n << " 2 \n";
+	int j;
+	for (j=0;j<u[].n ; j++)  
+	  file << d[][j] << endl; 
+    }
+*/  
+assert(err < 1e-9);
diff --git a/examples++-3d/Poisson3d.edp b/examples++-3d/Poisson3d.edp
new file mode 100644
index 0000000..b9124cb
--- /dev/null
+++ b/examples++-3d/Poisson3d.edp
@@ -0,0 +1,74 @@
+// build de mesh of a Sphere
+// -------------------------- 
+load "tetgen"
+load "medit"
+
+mesh Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},frac{-pi}{2}[\times]0,2\pi[ $
+//  a parametrization of a sphere 
+func f1 =cos(x)*cos(y);
+func f2 =cos(x)*sin(y);
+func f3 = sin(x);
+//  de  partiel derivative of the parametrization DF
+func f1x=sin(x)*cos(y);   
+func f1y=-cos(x)*sin(y);
+func f2x=-sin(x)*sin(y);
+func f2y=cos(x)*cos(y);
+func f3x=cos(x);
+func f3y=0;
+// $  M = DF^t DF $
+func m11=f1x^2+f2x^2+f3x^2;
+func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+func m22=f1y^2+f2y^2+f3y^2;
+
+func perio=[[4,y],[2,y],[1,x],[3,x]];  
+real hh=0.1;
+real vv= 1/square(hh);
+verbosity=2;
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+
+verbosity=2;
+real[int] domaine =[0.,0.,0.,1,0.01];
+mesh3 Th3=tetgtransfo(Th,transfo=[f1,f2,f3],nbofregions=1,regionlist=domaine);
+//savemesh(Th3,"sphere.meshb");
+medit("sphere",Th3);
+
+// FFCS - check 3D plots
+plot(Th3,cmm="sphere");
+
+fespace Vh(Th3,P23d);
+func ue =   2*x*x + 3*y*y + 4*z*z+ 5*x*y+6*x*z+1;
+func f= -18. ;
+Vh uhe = ue; // bug ..
+cout << " uhe min:  " << uhe[].min << " max:" << uhe[].max << endl;
+cout << uhe(0.,0.,0.) << endl;
+
+
+//savesol("f3.sol",Th3,ue,ue,[f,ue,f],order=1);
+//int bb=meditmeshsol("sol",Th3,solution=1,scalar=uhe);
+
+
+border cc(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
+mesh Th2=buildmesh(cc(50));
+fespace Vh2(Th2,P2);
+
+Vh u,v;
+
+macro Grad3(u) [dx(u),dy(u),dz(u)]  // EOM
+
+problem Lap3d(u,v,solver=CG)=int3d(Th3)(Grad3(v)' *Grad3(u)) - int3d(Th3)(f*v) + on(0,1,u=ue);
+Lap3d;
+cout << " u min::   " << u[]. min << "  max: " << u[].max << endl;
+real err= int3d(Th3)( square(u-ue) );
+cout << int3d(Th3)(1.) << " = " << Th3.mesure << endl;
+Vh d= ue-u;
+cout <<  " err = " << err <<  " diff l^\intfy = " << d[].linfty << endl;
+Vh2 u2=u,u2e=ue;
+plot(u2,wait=1);
+plot(u2,u2e,wait=1);
+
+// FFCS - check 3D plots
+plot(u);
+
+assert(err < 1e-9);
diff --git a/examples++-3d/Stokes.edp b/examples++-3d/Stokes.edp
new file mode 100644
index 0000000..a591721
--- /dev/null
+++ b/examples++-3d/Stokes.edp
@@ -0,0 +1,44 @@
+load "msh3" load "medit"
+int nn=3;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+medit("c10x10x10",Th,wait=1);
+
+// FFCS: testing 3d plots
+plot(Th);
+
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace Vh(Th,P23d);
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+VVh [u1,u2,u3,p];
+VVh [v1,v2,v3,q];
+func fup = (1-x)*(x)*y*(1-y)*16;
+solve vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3) //)';
+		       - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,u1=fup,u2=0,u3=0) + on(1,u1=0,u2=0,u3=0) ;
+plot(p,wait=1, nbiso=5); // a 3d plot of iso  pressure. 
+plot([u1,u2,u3] ,wait=1, nbiso=5); // a 3d plot of iso  pressure. 
+//  to see the 10 cup plan in 2d 
+for(int i=1;i<10;i++)
+  {
+    real yy=i/10.;
+    ux= u1(x,yy,y);
+    uz= u3(x,yy,y);
+    p2= p(x,yy,y);
+    plot([ux,uz],p2,cmm=" cut y = "+yy,wait= 1);
+  }
+
+// FFCS: testing 3d plots
+plot(u1);
+plot(u2);
+plot(u3);
+plot(p);
diff --git a/examples++-3d/TruncLac.edp b/examples++-3d/TruncLac.edp
new file mode 100644
index 0000000..a61118f
--- /dev/null
+++ b/examples++-3d/TruncLac.edp
@@ -0,0 +1,27 @@
+load "msh3"
+load "medit"
+int nn=10;
+
+border cc(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
+mesh Th2= buildmesh(cc(100));
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+func zmin= 2-sqrt(4-(x*x+y*y));
+func zmax= 2-sqrt(3.);
+
+mesh3 Th=buildlayers(Th2,nn,
+  coef=  (zmax-zmin)/zmax,
+  zbound=[zmin,zmax],
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+
+func u=x^2+y^2;
+
+mesh3 Th3=trunc(Th,(u-0.5)>1.e-10,split=1,label=135);
+medit("Lac",wait=1,Th);
+plot(Th); // FFCS: testing 3d plots
+medit("LacTruncated",Th3,wait=1);
+plot(Th3); // FFCS: testing 3d plots
diff --git a/examples++-3d/beam-3d.edp b/examples++-3d/beam-3d.edp
new file mode 100644
index 0000000..4798826
--- /dev/null
+++ b/examples++-3d/beam-3d.edp
@@ -0,0 +1,37 @@
+load "medit"
+include "cube.idp"
+int[int]  Nxyz=[20,5,5];
+real [int,int]  Bxyz=[[0.,5.],[0.,1.],[0.,1.]];
+int [int,int]  Lxyz=[[1,2],[2,2],[2,2]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+
+real E = 21.5e4;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+
+fespace Vh(Th,[P1,P1,P1]);
+Vh [u1,u2,u3], [v1,v2,v3];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2,u3)  [dx(u1),dy(u2),dz(u3),(dz(u2)+dy(u3))/sqrt2,(dz(u1)+dx(u3))/sqrt2,(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u1,u2,u3) ( dx(u1)+dy(u2)+dz(u3) ) // EOM
+  
+solve Lame([u1,u2,u3],[v1,v2,v3])=
+  int3d(Th)(  
+	    lambda*div(u1,u2,u3)*div(v1,v2,v3)	
+	    +2.*mu*( epsilon(u1,u2,u3)'*epsilon(v1,v2,v3) ) //')
+	      )
+  - int3d(Th) (gravity*v3)
+  + on(1,u1=0,u2=0,u3=0)
+  ;
+real dmax= u1[].max;
+cout << " max deplacement = " << dmax << endl;
+real coef= 0.1/dmax;
+int[int] ref2=[1,0,2,0];
+mesh3 Thm=movemesh3(Th,transfo=[x+u1*coef,y+u2*coef,z+u3*coef],label=ref2);
+Thm=change(Thm,label=ref2);
+plot(Th,Thm, wait=1,cmm="coef  amplification = "+coef );
+
diff --git a/examples++-3d/cone.edp b/examples++-3d/cone.edp
new file mode 100644
index 0000000..f43dbad
--- /dev/null
+++ b/examples++-3d/cone.edp
@@ -0,0 +1,27 @@
+//  example to build a mesh a cone 
+load "msh3"
+load "medit"
+// cone using buildlayers with a triangle 
+real RR=1,HH=1; 
+border Taxe(t=0,HH){x=t;y=0;label=0;};
+border Hypo(t=1,0){x=HH*t;y=RR*t;label=1;};
+border Vert(t=0,RR){x=HH;y=t;label=2;};
+
+int nn=10;
+real h= 1./nn;
+mesh Th2=buildmesh(  Taxe(HH*nn)+ Hypo(sqrt(HH*HH+RR*RR)*nn) + Vert(RR*nn) ) ;
+plot(Th2,wait=1);
+//medit("circle",ThT);
+
+int MaxLayersT=(int(2*pi*RR/h)/4)*4;
+func zminT = 0;
+func zmaxT = 2*pi;
+func fx= y*cos(z);// / max( abs(cos(z) ), abs(sin(z)));
+func fy= y*sin(z);// / max( abs(cos(z) ), abs(sin(z)));
+func fz= x;
+int[int] r1T=[0,0], r2T=[0,0,2,2];
+int[int] r4T=[0,2]; 
+mesh3 Th3T=buildlayers(Th2,coef= max(.01,y/max(x,0.4) ), MaxLayersT,zbound=[zminT,zmaxT],transfo=[fx,fy,fz],facemerge=1, region=r1T, labelmid=r2T);
+medit("cone",Th3T,wait=1);
+// FFCS: testing 3d plots
+plot(Th3T,cmm="cone");
diff --git a/examples++-3d/convect-3d.edp b/examples++-3d/convect-3d.edp
new file mode 100644
index 0000000..0963088
--- /dev/null
+++ b/examples++-3d/convect-3d.edp
@@ -0,0 +1,37 @@
+load "msh3"
+
+int nn=8;
+
+mesh Th2=square(nn,nn,[x*2.-1.,y*2.-1.]);
+fespace Vh2(Th2,P1);
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=-1,zmax=1.;
+
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  // region=r1, 
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+func  real hill(real r2){return exp(-10.*(r2));};
+
+fespace Vh(Th,P13d);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+Vh v,vo;
+Vh2 v2;
+real x0=0.3,y0=0.3,z0=0;
+vo=hill(square(x-x0)+square(y-y0)+square(z-z0));
+real t=0;
+v2=vo(x,y,0);
+plot(v2,cmm=" cut y = 0.5, time ="+t,wait=1);
+real dt=0.1;
+func u1=1.;
+func u2=2.;
+func u3=3.;
+v=convect([u1,u2,u3],-dt,vo);
+v2=v(x,y,0);
+t += dt;
+plot(v2,cmm=" cut y = 0.5, time ="+t,wait=1);
diff --git a/examples++-3d/cube-period.edp b/examples++-3d/cube-period.edp
new file mode 100644
index 0000000..d58371d
--- /dev/null
+++ b/examples++-3d/cube-period.edp
@@ -0,0 +1,78 @@
+load "msh3"
+int nn=10;;
+mesh Th2=square(nn,nn,region=0);
+fespace Vh2(Th2,P2);
+// // label  face  numbering 
+//      1 :  ( x == xmin)        2 :  ( x == xmax) 
+//      3 :  ( y == ymin)        4 :  ( y == ymax) 
+//      5 :  ( z == zmin)        6 :  ( z == zmax) 
+// ---
+int[int] rup=[0,5],  rdown=[0,6], rmid=[4,1,2,2, 1,3 ,3,4];
+real zmin=0,zmax=1;
+
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  // region=r1, 
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+cout << "Th :  nv = " << Th.nv << " nt =" << Th.nt << endl;
+savemesh(Th,"Th.mesh");
+verbosity=10;
+
+//  the Finite element space with full periodic condition in 3 axes
+fespace Vh(Th,P2,periodic=[[1,y,z],[2,y,z],[3,x,z],[4,x,z],[5,x,y],[6,x,y]]);
+verbosity=2;
+
+// a  code to build some verification ....
+fespace Vhh(Th,P2);
+
+int[int] num(Vhh.ndof);
+num=-1;
+int er=0;
+for(int k=0;k<Th.nt;++k)
+  {
+    int err=0;
+    for(int i=0;i<4;i++) 
+      {
+	if(num[Vhh(k,i)]== -1)
+	  num[Vhh(k,i)] = Vh(k,i);
+	else if(num[Vhh(k,i)] != Vh(k,i))
+	  {
+	    ++err;
+	    cout << " bug " << k <<  " : " << num[Vh(k,i)]  << " !=  " << Vhh(k,i) << endl; 
+	  }
+      }
+    if(err)
+      {
+	for(int i=0;i<4;i++) cout << Vh(k,i) << " ";     cout << endl;
+	for(int i=0;i<4;i++) cout << Vhh(k,i) << " ";    cout << endl << endl;;
+      }
+    er+=err;
+  }
+
+// ++++++
+int  n1 = nn+nn+1; //   P2 =>  
+int  n2 = n1-1; //
+int  nnn=n2*n2*n2;
+int nnn1=n1*n1*n1;
+cout << " ndf pare= " << Vh.ndof << " " << nnn << endl;
+cout << " ndf  = " << Vhh.ndof << " " << nnn1 << endl;
+assert(er==0 && nnn == Vh.ndof && nnn1 == Vhh.ndof); // some verification ...
+  Vh u,v,uu;
+  real x0=2*pi/3,y0=2*pi/4,z0=2*pi*2/3;
+  func ue= sin(2*pi*x+x0)*sin(2*pi*y+y0)*sin(2*pi*z+z0);
+  real cc= -3*(2*pi)^2 ;
+  func f = -cc*ue;
+  uu=ue;
+macro Grad(u) [dx(u),dy(u),dz(u)] //;
+  solve P(u,v,solver=CG)= int3d(Th)(Grad(u)'*Grad(v)) - int3d(Th)(f*v); //') ;
+cout << "Err L2 = " << sqrt(int3d(Th)( square(u-uu)) ) << endl;
+
+// FFCS: add 3D view
+
+///Vh2 u0=u(x,y,0);
+///Vh2 u1=u(x,y,1);
+///plot(u0,u1,wait=1);
+
+plot(u,nbiso=10);
diff --git a/examples++-3d/cube.idp b/examples++-3d/cube.idp
new file mode 100644
index 0000000..ecca66b
--- /dev/null
+++ b/examples++-3d/cube.idp
@@ -0,0 +1,39 @@
+load "msh3"
+load "medit"
+// ! basic functions to build regular mesh of a cube
+/*
+  mesh3   Cube(NN,BB,L);
+    --   build the surface mesh of a 3d box 
+    where: for exqmple:
+  int[int]  NN=[nx,ny,nz]; //  the number of seg in the 3 direction
+  real [int,int]  BB=[[xmin,xmax],[ymin,ymax],[zmin,zmax]]; // bounding bax  
+  int [int,int]  L=[[1,2],[3,4],[5,6]]; // the label of the 6 face left,right, front, back, down, right
+*/
+func mesh3 Cube(int[int] & NN,real[int,int] &BB ,int[int,int] & L)
+{    
+  //  first  build the 6 faces of the hex.
+  real x0=BB(0,0),x1=BB(0,1);
+  real y0=BB(1,0),y1=BB(1,1);
+  real z0=BB(2,0),z1=BB(2,1);
+  
+  int nx=NN[0],ny=NN[1],nz=NN[2];
+  mesh Thx = square(nx,ny,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+  
+  int[int] rup=[0,L(2,1)],  rdown=[0,L(2,0)], 
+    rmid=[1,L(1,0),  2,L(0,1),  3, L(1,1),  4, L(0,0) ];
+  mesh3 Th=buildlayers(Thx,nz,   zbound=[z0,z1], 
+		       labelmid=rmid,   labelup = rup,
+		       labeldown = rdown);
+  
+  return Th;
+}
+func mesh3 Cube(int Nx,int Ny,int Nz)
+{
+  int[int] NN=[Nx,Ny,Nz];
+  real [int,int]  BB=[[0,1],[0,1],[0,1]];	
+  int[int,int] LL=[[1,2],[3,4],[5,6]]; 
+  return Cube(NN,BB,LL);
+} 
+ 
+
+  
diff --git a/examples++-3d/cylinder-3d.edp b/examples++-3d/cylinder-3d.edp
new file mode 100644
index 0000000..39c78d0
--- /dev/null
+++ b/examples++-3d/cylinder-3d.edp
@@ -0,0 +1,20 @@
+load "msh3"// buildlayer
+load "medit"// buildlayer
+
+border C(t=0,2*pi) { x = cos(t); y=sin(t); label=1;}
+mesh Baseh = buildmesh(C(20));
+plot(Baseh,wait=1);
+
+int[int] rup=[0,1],  rdown=[0,2], rmid=[1,3];
+func zmin= 1;
+func zmax= 10;
+int nlayer=100;
+mesh3 Th=buildlayers(Baseh,nlayer,
+  coef= 1.,
+  zbound=[zmin,zmax],
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+medit("Cyl",Th,wait=1);
+// FFCS: testing 3d plots
+plot(Th,cmm="Cyl");
diff --git a/examples++-3d/cylinder.edp b/examples++-3d/cylinder.edp
new file mode 100644
index 0000000..b1dac8e
--- /dev/null
+++ b/examples++-3d/cylinder.edp
@@ -0,0 +1,33 @@
+load "msh3"
+load "tetgen"
+load "medit"
+// Maillage d'un cylindre d'axe 0x
+// 
+int nx=10; // nombre de points le long de l'axe
+int nth=50; // nombre de points sur la circonference
+real xmin=1.,xmax=3.;
+// Maillage de cercles pour les deux faces
+border cc(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
+mesh Thcercle = buildmesh(cc(nth));
+
+// Maillage de carre qui va etre applique au bord du cylindre ave movemesh23
+mesh Thcarre=square(nx,nth,[xmin+x*(xmax-xmin),2*pi*y]);
+//plot(Thcarre);
+
+// parametrisation d'un cylindre d'axe Ox
+func f1 = x;
+func f2 = cos(y);
+func f3 = sin(y);
+mesh3 Thsurf1=movemesh23(Thcarre,transfo=[f1,f2,f3],orientation=-1);
+mesh3 Thsurf2=movemesh23(Thcercle,transfo=[xmin,x,y],orientation=-1);
+mesh3 Thsurf3=movemesh23(Thcercle,transfo=[xmax,x,y],orientation=1);
+mesh3 Thsurf=Thsurf1+Thsurf2+Thsurf3;
+real voltet= ( ( (2*pi)/50 )^3 )/6.;
+cout << "  voltet = " << voltet << endl;
+real[int] domaine = [1.5,0.,0.,1,voltet];
+mesh3 Th=tetg(Thsurf,switch="pqaaAAYYQ",nbofregions=1,regionlist=domaine);
+
+savemesh(Th,"cyl.mesh");
+medit("cyl",Th,wait=1);
+// FFCS: testing 3d plots
+plot(Th,cmm="cyl");
diff --git a/examples++-3d/dodecaedre01.mesh b/examples++-3d/dodecaedre01.mesh
new file mode 100644
index 0000000..6628830
--- /dev/null
+++ b/examples++-3d/dodecaedre01.mesh
@@ -0,0 +1,1346 @@
+MeshVersionFormatted 1
+# Mesh generated by nb2mesh (INRIA)
+
+
+Dimension
+3 
+
+# Set of mesh vertices
+
+Vertices
+216 
+0.491123 0.356822 0.794654 0 
+-0.187592 0.57735 0.794654 0 
+-0.607062 9.31409e-17 0.794654 0 
+-0.187592 -0.57735 0.794654 0 
+0.491123 -0.356822 0.794654 0 
+0.187592 0.57735 -0.794654 0 
+-0.491123 0.356822 -0.794654 0 
+-0.491123 -0.356822 -0.794654 0 
+0.187592 -0.57735 -0.794654 0 
+0.607062 -4.65705e-17 -0.794654 0 
+0.794654 0.57735 0.187592 0 
+0.303531 0.934172 -0.187592 0 
+-0.303531 0.934172 0.187592 0 
+-0.794654 0.57735 -0.187592 0 
+-0.982247 1.39711e-16 0.187592 0 
+-0.794654 -0.57735 -0.187592 0 
+-0.303531 -0.934172 0.187592 0 
+0.303531 -0.934172 -0.187592 0 
+0.794654 -0.57735 0.187592 0 
+0.982247 -4.65705e-17 -0.187592 0 
+-2.79423e-17 0 1 0 
+-2.79423e-17 2.79423e-17 -1 0 
+0.276393 0.850651 0.447214 0 
+-0.723607 0.525731 0.447214 0 
+-0.723607 -0.525731 0.447214 0 
+0.276393 -0.850651 0.447214 0 
+0.894427 -5.58846e-17 0.447214 0 
+-0.276393 0.850651 -0.447214 0 
+-0.894427 6.98557e-17 -0.447214 0 
+-0.276393 -0.850651 -0.447214 0 
+0.723607 -0.525731 -0.447214 0 
+0.723607 0.525731 -0.447214 0 
+0.25923 -0.188342 0.947274 0 
+0.525731 -5.94228e-17 0.850651 0 
+0.25923 0.188342 0.947274 0 
+0.0990171 0.304743 -0.947274 0 
+0.425325 0.309017 -0.850651 0 
+0.320426 -9.83253e-18 -0.947274 0 
+0.0468717 0.753743 0.655496 0 
+0.16246 0.5 0.850651 0 
+0.405119 0.637341 0.655496 0 
+-0.702368 0.277497 0.655496 0 
+-0.425325 0.309017 0.850651 0 
+-0.480959 0.58224 0.655496 0 
+-0.480959 -0.58224 0.655496 0 
+-0.425325 -0.309017 0.850651 0 
+-0.702368 -0.277497 0.655496 0 
+0.405119 -0.637341 0.655496 0 
+0.16246 -0.5 0.850651 0 
+0.0468717 -0.753743 0.655496 0 
+0.731336 0.188342 0.655496 0 
+0.731336 -0.188342 0.655496 0 
+-0.0468717 0.753743 -0.655496 0 
+-0.16246 0.5 -0.850651 0 
+-0.405119 0.637341 -0.655496 0 
+-0.731336 0.188342 -0.655496 0 
+-0.525731 8.91342e-17 -0.850651 0 
+-0.731336 -0.188342 -0.655496 0 
+-0.405119 -0.637341 -0.655496 0 
+-0.16246 -0.5 -0.850651 0 
+-0.0468717 -0.753743 -0.655496 0 
+0.480959 -0.58224 -0.655496 0 
+0.425325 -0.309017 -0.850651 0 
+0.702368 -0.277497 -0.655496 0 
+0.702368 0.277497 -0.655496 0 
+0.480959 0.58224 -0.655496 0 
+-0.0990171 0.304743 0.947274 0 
+-0.320426 4.91626e-17 0.947274 0 
+-0.0990171 -0.304743 0.947274 0 
+0.0990171 -0.304743 -0.947274 0 
+-0.25923 -0.188342 -0.947274 0 
+-0.25923 0.188342 -0.947274 0 
+0.688191 0.5 0.525731 0 
+0.565332 0.753743 0.33507 0 
+0.587785 0.809017 -1.48557e-17 0 
+0.306102 0.942084 0.137036 0 
+8.91342e-17 1 0 0 
+-0.0143242 0.942084 0.33507 0 
+-0.262866 0.809017 0.525731 0 
+-0.542155 0.770582 0.33507 0 
+-0.587785 0.809017 0 0 
+-0.801385 0.58224 0.137036 0 
+-0.951057 0.309017 0 0 
+-0.900402 0.277497 0.33507 0 
+-0.850651 1.2463e-16 0.525731 0 
+-0.900402 -0.277497 0.33507 0 
+-0.951057 -0.309017 1.48557e-17 0 
+-0.801385 -0.58224 0.137036 0 
+-0.587785 -0.809017 1.48557e-17 0 
+-0.542155 -0.770582 0.33507 0 
+-0.262866 -0.809017 0.525731 0 
+-0.0143242 -0.942084 0.33507 0 
+-1.78268e-16 -1 0 0 
+0.306102 -0.942084 0.137036 0 
+0.587785 -0.809017 0 0 
+0.565332 -0.753743 0.33507 0 
+0.688191 -0.5 0.525731 0 
+0.891549 -0.304743 0.33507 0 
+0.951057 -0.309017 0 0 
+0.990566 -5.40789e-17 0.137036 0 
+0.951057 0.309017 -1.48557e-17 0 
+0.891549 0.304743 0.33507 0 
+-0.688191 0.5 -0.525731 0 
+-0.565332 0.753743 -0.33507 0 
+-0.306102 0.942084 -0.137036 0 
+0.0143242 0.942084 -0.33507 0 
+0.262866 0.809017 -0.525731 0 
+-0.688191 -0.5 -0.525731 0 
+-0.891549 -0.304743 -0.33507 0 
+-0.990566 1.10616e-16 -0.137036 0 
+-0.891549 0.304743 -0.33507 0 
+0.262866 -0.809017 -0.525731 0 
+0.0143242 -0.942084 -0.33507 0 
+-0.306102 -0.942084 -0.137036 0 
+-0.565332 -0.753743 -0.33507 0 
+0.850651 -4.98521e-17 -0.525731 0 
+0.900402 -0.277497 -0.33507 0 
+0.801385 -0.58224 -0.137036 0 
+0.542155 -0.770582 -0.33507 0 
+0.542155 0.770582 -0.33507 0 
+0.801385 0.58224 -0.137036 0 
+0.900402 0.277497 -0.33507 0 
+-0.641066 0.180621 -0.121104 0 
+-0.289149 0.338185 0.123889 0 
+-0.53285 0.493571 -0.1668 0 
+-0.657109 0.289176 0.105955 0 
+-0.660539 0.140781 -0.339313 0 
+0.236469 0.702297 -0.119761 0 
+0.293479 0.664326 0.253992 0 
+0.177505 0.363349 -0.0220877 0 
+-0.13669 0.666735 0.148585 0 
+-0.077289 0.624594 -0.105375 0 
+0.490099 0.439095 -0.389076 0 
+0.572485 0.513847 0.00158281 0 
+-0.0147537 -0.301166 0.00573164 0 
+0.027261 -0.609388 -0.0368522 0 
+-0.210932 -0.44583 0.274374 0 
+-0.187906 -0.469788 -0.121119 0 
+-0.264179 0.00110005 -0.0686397 0 
+0.139429 -0.176865 0.141747 0 
+0.137993 0.0397672 -0.0474711 0 
+0.0549939 -0.277568 0.38053 0 
+-0.31332 -0.205816 0.246979 0 
+-0.470354 -0.172651 -0.0444443 0 
+-0.512056 -0.451171 0.0222751 0 
+-0.63543 -0.27962 0.191868 0 
+-0.485376 -0.459615 0.361165 0 
+-0.377691 -0.632462 -0.145148 0 
+0.195227 0.497143 0.558163 0 
+0.471638 0.295428 0.498678 0 
+-0.0767607 0.422523 0.42746 0 
+-0.0133728 0.314914 0.699076 0 
+0.210462 0.199609 0.658993 0 
+0.29383 0.428373 0.283453 0 
+-0.751395 -0.148984 -0.116319 0 
+-0.440269 -0.0800457 -0.444693 0 
+0.168272 0.0650597 -0.364626 0 
+0.129559 -0.219634 -0.638505 0 
+0.463777 -0.0623083 -0.361699 0 
+0.343182 -0.330995 -0.364227 0 
+0.493658 -0.143422 -0.586334 0 
+0.411319 0.125283 -0.636386 0 
+0.264237 -0.384147 -0.612663 0 
+0.501592 0.206461 -0.358475 0 
+0.0132368 0.307451 -0.300997 0 
+-0.0152879 0.569786 -0.430361 0 
+0.768744 -0.0853962 0.0302352 0 
+0.703096 -0.0195892 -0.265073 0 
+0.66767 -0.0937254 0.365578 0 
+0.624914 0.135741 0.228425 0 
+0.43053 -0.191743 0.280203 0 
+0.628446 -0.397168 0.176134 0 
+-0.294394 -0.562508 -0.388368 0 
+0.541027 -0.233274 -0.0637026 0 
+0.24393 0.432938 -0.480573 0 
+-0.0108428 0.352749 -0.652537 0 
+-0.345747 0.285932 -0.306576 0 
+-0.462044 0.0270721 0.201178 0 
+-0.74082 0.00772943 0.147783 0 
+-0.0988376 -0.0884954 -0.304341 0 
+-0.536653 -0.327598 -0.375823 0 
+-0.254917 -0.700613 0.152166 0 
+0.0579332 0.0669963 0.312854 0 
+-0.313188 0.627651 -0.209244 0 
+-0.413966 0.58379 0.136803 0 
+0.491904 -0.0087985 0.549865 0 
+0.0023627 -0.55211 0.524977 0 
+0.289635 -0.414128 0.643574 0 
+0.178419 -0.180643 0.644293 0 
+-0.609006 0.0150692 0.405833 0 
+-0.510316 0.242031 0.42591 0 
+0.317525 0.133964 0.182226 0 
+0.48528 0.243879 -0.00862047 0 
+0.614023 0.390478 0.226698 0 
+0.274736 -0.399844 -0.0376275 0 
+-0.125503 0.319529 -0.117781 0 
+0.0874565 -0.359885 -0.278676 0 
+0.690974 0.253499 -0.13669 0 
+0.313572 -0.578924 0.300802 0 
+-0.371471 0.262212 -0.608757 0 
+-0.0594493 0.658146 0.400466 0 
+-0.182072 -0.407708 0.600325 0 
+-0.30708 -0.124887 0.675407 0 
+-0.260489 0.127059 0.594044 0 
+0.0510777 -0.6298 -0.374388 0 
+-0.072537 -0.384745 -0.477982 0 
+0.389971 -0.550182 -0.266139 0 
+0.598158 -0.329966 -0.383532 0 
+0.0625799 -0.651979 0.186025 0 
+0.431474 -0.619128 -0.00192976 0 
+-0.0958472 -0.00188602 0.654796 0 
+-0.171146 -0.117364 -0.711793 0 
+-0.268558 -0.406826 -0.616475 0 
+-0.326231 0.520121 0.384798 0 
+-0.105999 0.124624 -0.618196 0 
+0.152665 0.0433483 -0.681703 0 
+
+# Set of Triangles
+
+Triangles
+240 
+33 34 35 0 
+36 37 38 0 
+39 40 41 0 
+42 43 44 0 
+45 46 47 0 
+48 49 50 0 
+51 34 52 0 
+53 54 55 0 
+56 57 58 0 
+59 60 61 0 
+62 63 64 0 
+65 37 66 0 
+35 40 67 0 
+67 43 68 0 
+68 46 69 0 
+69 49 33 0 
+38 63 70 0 
+70 60 71 0 
+71 57 72 0 
+72 54 36 0 
+41 73 74 0 
+74 75 76 0 
+76 77 78 0 
+78 79 39 0 
+44 79 80 0 
+80 81 82 0 
+82 83 84 0 
+84 85 42 0 
+47 85 86 0 
+86 87 88 0 
+88 89 90 0 
+90 91 45 0 
+50 91 92 0 
+92 93 94 0 
+94 95 96 0 
+96 97 48 0 
+52 97 98 0 
+98 99 100 0 
+100 101 102 0 
+102 73 51 0 
+55 103 104 0 
+104 81 105 0 
+105 77 106 0 
+106 107 53 0 
+58 108 109 0 
+109 87 110 0 
+110 83 111 0 
+111 103 56 0 
+61 112 113 0 
+113 93 114 0 
+114 89 115 0 
+115 108 59 0 
+64 116 117 0 
+117 99 118 0 
+118 95 119 0 
+119 112 62 0 
+66 107 120 0 
+120 75 121 0 
+121 101 122 0 
+122 116 65 0 
+21 33 35 0 
+5 34 33 0 
+1 35 34 0 
+22 36 38 0 
+6 37 36 0 
+10 38 37 0 
+23 39 41 0 
+2 40 39 0 
+1 41 40 0 
+24 42 44 0 
+3 43 42 0 
+2 44 43 0 
+25 45 47 0 
+4 46 45 0 
+3 47 46 0 
+26 48 50 0 
+5 49 48 0 
+4 50 49 0 
+27 51 52 0 
+1 34 51 0 
+5 52 34 0 
+28 53 55 0 
+6 54 53 0 
+7 55 54 0 
+29 56 58 0 
+7 57 56 0 
+8 58 57 0 
+30 59 61 0 
+8 60 59 0 
+9 61 60 0 
+31 62 64 0 
+9 63 62 0 
+10 64 63 0 
+32 65 66 0 
+10 37 65 0 
+6 66 37 0 
+21 35 67 0 
+1 40 35 0 
+2 67 40 0 
+21 67 68 0 
+2 43 67 0 
+3 68 43 0 
+21 68 69 0 
+3 46 68 0 
+4 69 46 0 
+21 69 33 0 
+4 49 69 0 
+5 33 49 0 
+22 38 70 0 
+10 63 38 0 
+9 70 63 0 
+22 70 71 0 
+9 60 70 0 
+8 71 60 0 
+22 71 72 0 
+8 57 71 0 
+7 72 57 0 
+22 72 36 0 
+7 54 72 0 
+6 36 54 0 
+23 41 74 0 
+1 73 41 0 
+11 74 73 0 
+23 74 76 0 
+11 75 74 0 
+12 76 75 0 
+23 76 78 0 
+12 77 76 0 
+13 78 77 0 
+23 78 39 0 
+13 79 78 0 
+2 39 79 0 
+24 44 80 0 
+2 79 44 0 
+13 80 79 0 
+24 80 82 0 
+13 81 80 0 
+14 82 81 0 
+24 82 84 0 
+14 83 82 0 
+15 84 83 0 
+24 84 42 0 
+15 85 84 0 
+3 42 85 0 
+25 47 86 0 
+3 85 47 0 
+15 86 85 0 
+25 86 88 0 
+15 87 86 0 
+16 88 87 0 
+25 88 90 0 
+16 89 88 0 
+17 90 89 0 
+25 90 45 0 
+17 91 90 0 
+4 45 91 0 
+26 50 92 0 
+4 91 50 0 
+17 92 91 0 
+26 92 94 0 
+17 93 92 0 
+18 94 93 0 
+26 94 96 0 
+18 95 94 0 
+19 96 95 0 
+26 96 48 0 
+19 97 96 0 
+5 48 97 0 
+27 52 98 0 
+5 97 52 0 
+19 98 97 0 
+27 98 100 0 
+19 99 98 0 
+20 100 99 0 
+27 100 102 0 
+20 101 100 0 
+11 102 101 0 
+27 102 51 0 
+11 73 102 0 
+1 51 73 0 
+28 55 104 0 
+7 103 55 0 
+14 104 103 0 
+28 104 105 0 
+14 81 104 0 
+13 105 81 0 
+28 105 106 0 
+13 77 105 0 
+12 106 77 0 
+28 106 53 0 
+12 107 106 0 
+6 53 107 0 
+29 58 109 0 
+8 108 58 0 
+16 109 108 0 
+29 109 110 0 
+16 87 109 0 
+15 110 87 0 
+29 110 111 0 
+15 83 110 0 
+14 111 83 0 
+29 111 56 0 
+14 103 111 0 
+7 56 103 0 
+30 61 113 0 
+9 112 61 0 
+18 113 112 0 
+30 113 114 0 
+18 93 113 0 
+17 114 93 0 
+30 114 115 0 
+17 89 114 0 
+16 115 89 0 
+30 115 59 0 
+16 108 115 0 
+8 59 108 0 
+31 64 117 0 
+10 116 64 0 
+20 117 116 0 
+31 117 118 0 
+20 99 117 0 
+19 118 99 0 
+31 118 119 0 
+19 95 118 0 
+18 119 95 0 
+31 119 62 0 
+18 112 119 0 
+9 62 112 0 
+32 66 120 0 
+6 107 66 0 
+12 120 107 0 
+32 120 121 0 
+12 75 120 0 
+11 121 75 0 
+32 121 122 0 
+11 101 121 0 
+20 122 101 0 
+32 122 65 0 
+20 116 122 0 
+10 65 116 0 
+
+# Set of tetrahedra
+
+Tetrahedra
+867 
+123 124 125 126 0 
+127 83 111 110 0 
+14 83 111 127 0 
+123 125 14 126 0 
+128 76 129 75 0 
+128 130 131 132 0 
+128 133 107 120 0 
+128 134 120 75 0 
+135 136 137 138 0 
+135 139 140 141 0 
+135 142 140 143 0 
+135 139 144 143 0 
+145 146 87 88 0 
+145 147 88 90 0 
+145 148 89 16 0 
+149 150 41 1 0 
+149 151 152 39 0 
+149 153 151 154 0 
+123 127 155 110 0 
+103 125 14 127 0 
+109 156 127 155 0 
+109 127 110 155 0 
+157 158 159 160 0 
+127 109 29 58 0 
+127 56 156 58 0 
+161 116 162 159 0 
+161 38 162 10 0 
+161 160 158 163 0 
+161 62 163 63 0 
+130 141 157 164 0 
+130 141 165 157 0 
+128 166 106 107 0 
+128 131 130 129 0 
+128 132 77 106 0 
+167 117 168 20 0 
+167 169 170 171 0 
+167 172 169 171 0 
+173 61 30 59 0 
+167 98 169 172 0 
+167 168 117 174 0 
+167 100 169 98 0 
+128 132 131 77 0 
+65 164 133 162 0 
+162 164 133 175 0 
+128 133 175 107 0 
+128 165 132 166 0 
+175 166 107 6 0 
+175 176 6 37 0 
+143 135 138 144 0 
+123 177 139 156 0 
+144 139 178 143 0 
+144 179 155 146 0 
+144 180 181 156 0 
+145 146 144 155 0 
+145 147 90 182 0 
+143 139 178 183 0 
+139 141 183 140 0 
+135 140 139 143 0 
+145 146 147 143 0 
+138 180 181 144 0 
+166 55 28 53 0 
+123 179 110 155 0 
+83 123 127 14 0 
+184 166 177 55 0 
+184 81 125 185 0 
+184 125 124 185 0 
+126 82 84 24 0 
+184 125 55 177 0 
+169 170 27 100 0 
+169 51 186 52 0 
+169 51 170 186 0 
+142 187 188 189 0 
+179 190 191 84 0 
+179 85 190 84 0 
+179 126 83 84 0 
+179 146 86 87 0 
+179 86 190 85 0 
+179 146 87 155 0 
+179 190 178 191 0 
+192 183 186 150 0 
+192 141 174 140 0 
+130 192 183 141 0 
+130 192 154 183 0 
+192 183 150 154 0 
+193 170 194 154 0 
+170 192 154 193 0 
+130 192 141 193 0 
+141 140 195 174 0 
+130 141 196 165 0 
+141 196 165 180 0 
+165 157 175 130 0 
+192 174 141 193 0 
+141 164 193 159 0 
+183 141 124 130 0 
+192 183 140 171 0 
+128 130 165 175 0 
+135 139 141 180 0 
+135 197 138 180 0 
+139 141 180 196 0 
+157 197 160 141 0 
+141 159 193 174 0 
+158 9 60 70 0 
+198 194 193 170 0 
+167 198 20 168 0 
+198 194 134 193 0 
+198 133 134 121 0 
+198 32 133 121 0 
+198 168 193 164 0 
+198 168 122 20 0 
+184 132 105 131 0 
+128 129 77 131 0 
+128 132 106 166 0 
+132 106 166 28 0 
+185 184 131 124 0 
+124 132 130 196 0 
+171 199 172 97 0 
+184 104 125 81 0 
+125 126 124 185 0 
+123 177 125 124 0 
+125 82 126 185 0 
+127 103 177 200 0 
+125 55 177 103 0 
+184 55 125 104 0 
+123 127 125 177 0 
+123 126 14 83 0 
+123 144 178 179 0 
+123 139 124 178 0 
+127 125 177 103 0 
+136 93 18 94 0 
+192 174 193 170 0 
+130 183 154 151 0 
+123 144 139 178 0 
+141 124 130 196 0 
+139 124 196 177 0 
+135 141 195 197 0 
+145 181 148 16 0 
+146 147 25 88 0 
+144 146 143 178 0 
+168 20 117 116 0 
+145 87 155 16 0 
+161 163 158 63 0 
+145 182 138 137 0 
+144 135 138 180 0 
+129 201 23 78 0 
+129 134 75 74 0 
+194 154 74 134 0 
+153 35 21 33 0 
+128 77 129 76 0 
+128 130 134 129 0 
+128 129 134 75 0 
+128 130 132 165 0 
+130 129 154 134 0 
+145 182 90 89 0 
+147 91 137 202 0 
+147 182 91 90 0 
+143 202 147 137 0 
+143 147 203 190 0 
+130 133 134 193 0 
+198 164 32 122 0 
+65 66 37 133 0 
+133 164 65 32 0 
+133 134 121 120 0 
+203 202 69 46 0 
+203 190 47 3 0 
+3 204 68 203 0 
+205 112 18 113 0 
+197 157 160 158 0 
+205 163 206 197 0 
+182 17 114 93 0 
+197 160 195 207 0 
+197 136 207 195 0 
+197 158 206 180 0 
+197 138 205 136 0 
+197 206 138 180 0 
+208 168 117 116 0 
+208 168 159 174 0 
+208 174 118 117 0 
+160 62 161 208 0 
+208 207 174 160 0 
+163 160 62 161 0 
+208 62 207 160 0 
+145 138 182 148 0 
+182 114 148 136 0 
+145 147 182 137 0 
+89 182 114 148 0 
+136 93 209 182 0 
+145 181 138 148 0 
+147 182 137 91 0 
+182 137 187 209 0 
+182 137 91 187 0 
+91 182 187 92 0 
+210 209 195 136 0 
+210 174 207 195 0 
+210 207 118 119 0 
+210 18 136 207 0 
+210 207 119 18 0 
+134 74 194 11 0 
+130 154 129 131 0 
+128 130 175 133 0 
+130 133 193 164 0 
+129 131 78 77 0 
+129 154 74 41 0 
+167 198 170 101 0 
+198 133 32 164 0 
+167 174 117 99 0 
+161 159 208 116 0 
+208 168 116 159 0 
+168 116 164 122 0 
+199 172 97 96 0 
+141 180 165 157 0 
+135 143 137 142 0 
+183 153 151 211 0 
+183 204 211 151 0 
+124 183 204 178 0 
+60 206 212 213 0 
+206 181 138 180 0 
+163 160 197 205 0 
+141 197 160 195 0 
+206 213 61 173 0 
+168 193 164 159 0 
+198 168 164 122 0 
+167 168 174 193 0 
+164 116 159 162 0 
+129 41 74 23 0 
+141 164 159 157 0 
+204 214 151 124 0 
+143 203 211 204 0 
+204 43 152 151 0 
+204 67 211 152 0 
+204 152 43 67 0 
+203 204 68 211 0 
+3 191 43 204 0 
+204 151 152 211 0 
+149 151 39 201 0 
+151 152 39 2 0 
+214 201 2 151 0 
+211 189 21 69 0 
+130 183 151 124 0 
+151 124 214 131 0 
+149 150 1 153 0 
+149 151 201 154 0 
+130 124 151 131 0 
+175 162 164 157 0 
+130 141 164 193 0 
+199 48 96 97 0 
+165 180 215 157 0 
+165 176 215 177 0 
+206 205 138 173 0 
+128 166 175 165 0 
+132 184 166 165 0 
+130 134 154 193 0 
+213 8 108 181 0 
+145 146 155 87 0 
+206 173 181 213 0 
+181 148 115 173 0 
+181 156 58 109 0 
+181 8 108 58 0 
+145 144 181 155 0 
+181 115 148 16 0 
+181 155 109 16 0 
+181 155 156 109 0 
+200 215 177 156 0 
+169 186 171 97 0 
+156 212 215 180 0 
+170 51 27 102 0 
+144 181 155 156 0 
+127 156 200 177 0 
+162 10 38 37 0 
+156 155 123 127 0 
+145 137 143 147 0 
+146 25 147 47 0 
+123 144 179 155 0 
+179 146 190 86 0 
+179 126 84 191 0 
+204 190 191 178 0 
+42 190 84 191 0 
+190 191 42 3 0 
+145 144 138 181 0 
+145 143 137 138 0 
+182 136 148 138 0 
+146 147 143 190 0 
+145 182 89 148 0 
+47 203 46 147 0 
+147 202 45 91 0 
+192 183 171 186 0 
+183 211 142 189 0 
+198 101 134 194 0 
+164 157 162 159 0 
+133 66 37 175 0 
+175 176 37 216 0 
+198 134 101 121 0 
+167 170 193 174 0 
+171 174 172 195 0 
+171 188 142 199 0 
+183 171 189 142 0 
+146 47 190 86 0 
+206 156 181 180 0 
+182 137 209 136 0 
+139 141 124 183 0 
+148 205 138 136 0 
+148 205 30 173 0 
+181 173 115 108 0 
+148 115 173 30 0 
+215 22 216 212 0 
+165 177 215 180 0 
+215 200 177 176 0 
+215 157 180 216 0 
+158 216 212 180 0 
+213 8 60 59 0 
+213 59 173 108 0 
+197 206 205 138 0 
+213 212 71 8 0 
+213 212 60 71 0 
+213 173 59 61 0 
+183 154 153 150 0 
+177 196 165 184 0 
+131 124 132 130 0 
+170 194 102 101 0 
+170 51 150 186 0 
+170 102 150 51 0 
+167 171 174 172 0 
+167 171 170 174 0 
+168 193 159 174 0 
+169 170 171 186 0 
+167 101 170 100 0 
+210 199 172 195 0 
+210 174 195 172 0 
+139 141 196 124 0 
+134 194 101 11 0 
+123 83 179 126 0 
+146 47 147 190 0 
+145 144 143 138 0 
+123 156 127 177 0 
+144 179 146 178 0 
+209 136 94 93 0 
+93 209 182 92 0 
+210 209 199 195 0 
+140 209 199 142 0 
+187 26 92 209 0 
+50 187 26 92 0 
+123 126 179 178 0 
+210 118 19 95 0 
+126 191 24 84 0 
+179 126 191 178 0 
+203 204 190 3 0 
+147 203 46 202 0 
+143 203 204 190 0 
+139 143 140 183 0 
+211 142 189 202 0 
+146 143 178 190 0 
+203 211 69 202 0 
+178 183 204 143 0 
+149 154 41 150 0 
+149 23 201 39 0 
+152 153 40 35 0 
+204 124 191 214 0 
+149 153 154 150 0 
+151 201 2 39 0 
+169 97 171 172 0 
+2 214 151 43 0 
+143 142 183 211 0 
+181 16 108 115 0 
+182 187 92 209 0 
+215 177 156 180 0 
+143 190 204 178 0 
+148 136 114 205 0 
+135 140 142 209 0 
+145 144 146 143 0 
+123 126 178 124 0 
+128 134 133 120 0 
+140 171 195 174 0 
+130 154 192 193 0 
+140 171 183 142 0 
+197 157 158 180 0 
+165 166 176 177 0 
+128 175 166 107 0 
+192 186 171 170 0 
+130 196 132 165 0 
+159 160 174 141 0 
+151 154 131 201 0 
+204 124 178 191 0 
+143 147 202 203 0 
+184 185 105 81 0 
+126 185 24 191 0 
+149 23 129 201 0 
+165 184 166 177 0 
+169 52 27 51 0 
+161 116 208 64 0 
+62 112 207 160 0 
+141 157 197 180 0 
+158 160 197 163 0 
+199 48 188 187 0 
+210 96 199 94 0 
+210 209 136 94 0 
+135 209 136 195 0 
+184 196 124 177 0 
+131 79 201 78 0 
+13 214 80 185 0 
+129 131 201 78 0 
+184 132 124 196 0 
+131 185 13 105 0 
+184 185 131 105 0 
+43 214 151 204 0 
+183 189 171 186 0 
+42 3 191 43 0 
+149 41 129 23 0 
+79 214 201 2 0 
+149 152 40 39 0 
+211 68 21 67 0 
+161 63 64 62 0 
+136 114 205 113 0 
+143 211 183 204 0 
+179 190 146 178 0 
+135 136 197 195 0 
+171 199 195 172 0 
+210 172 199 96 0 
+210 209 94 199 0 
+172 97 19 98 0 
+208 160 174 159 0 
+140 209 195 199 0 
+158 159 160 161 0 
+160 141 159 157 0 
+160 174 141 195 0 
+161 64 208 62 0 
+210 174 172 118 0 
+154 170 194 150 0 
+134 75 121 120 0 
+135 137 209 142 0 
+167 193 198 168 0 
+199 142 187 188 0 
+143 142 211 202 0 
+202 187 189 49 0 
+130 175 133 164 0 
+134 193 194 154 0 
+132 105 131 77 0 
+166 176 53 6 0 
+184 132 166 28 0 
+184 166 55 28 0 
+149 201 129 154 0 
+125 14 126 82 0 
+184 131 124 132 0 
+200 7 54 72 0 
+139 156 177 180 0 
+8 156 181 213 0 
+156 212 8 57 0 
+202 147 45 46 0 
+185 131 13 214 0 
+123 124 139 177 0 
+139 196 180 177 0 
+112 163 160 62 0 
+167 172 99 98 0 
+207 174 118 208 0 
+70 158 9 63 0 
+158 9 63 163 0 
+161 38 216 162 0 
+157 216 159 158 0 
+161 208 159 160 0 
+180 139 144 135 0 
+210 207 174 118 0 
+206 158 9 60 0 
+184 196 165 132 0 
+216 159 158 161 0 
+215 157 216 176 0 
+123 110 179 83 0 
+181 138 148 173 0 
+206 212 156 180 0 
+182 136 93 114 0 
+153 34 35 33 0 
+208 168 174 117 0 
+183 211 189 153 0 
+182 138 137 136 0 
+145 155 181 16 0 
+171 5 189 188 0 
+150 73 1 51 0 
+199 187 26 48 0 
+188 189 33 5 0 
+188 189 49 33 0 
+186 171 5 189 0 
+189 171 188 142 0 
+188 187 49 189 0 
+192 170 150 186 0 
+185 214 80 24 0 
+165 157 215 176 0 
+185 214 24 191 0 
+211 69 202 189 0 
+124 214 185 191 0 
+204 190 3 191 0 
+186 52 97 169 0 
+28 132 105 184 0 
+127 125 14 123 0 
+208 118 207 31 0 
+169 172 98 97 0 
+198 170 101 194 0 
+164 162 65 116 0 
+10 161 116 162 0 
+79 214 80 13 0 
+140 171 199 195 0 
+174 172 118 99 0 
+210 172 96 19 0 
+126 24 185 82 0 
+203 69 211 68 0 
+151 152 211 153 0 
+161 158 216 38 0 
+158 212 22 70 0 
+158 212 70 60 0 
+126 124 185 191 0 
+176 37 216 36 0 
+215 200 176 72 0 
+166 53 176 55 0 
+153 189 33 21 0 
+176 72 200 54 0 
+216 162 38 37 0 
+202 187 49 4 0 
+175 162 157 216 0 
+175 176 166 6 0 
+160 112 207 205 0 
+167 170 198 193 0 
+156 56 200 57 0 
+206 180 158 212 0 
+158 38 22 216 0 
+216 158 212 22 0 
+211 152 67 21 0 
+140 171 142 199 0 
+135 180 141 197 0 
+150 186 1 153 0 
+215 36 176 216 0 
+206 9 205 61 0 
+174 160 207 195 0 
+186 153 189 34 0 
+175 133 66 107 0 
+198 134 133 193 0 
+157 162 159 216 0 
+147 203 190 47 0 
+199 97 188 48 0 
+211 153 21 189 0 
+154 74 134 129 0 
+124 214 131 185 0 
+133 32 120 121 0 
+135 209 137 136 0 
+70 158 38 22 0 
+123 144 156 139 0 
+144 156 155 123 0 
+215 72 176 36 0 
+57 200 215 72 0 
+156 200 215 57 0 
+15 110 179 87 0 
+209 94 199 26 0 
+179 15 83 110 0 
+179 84 15 85 0 
+14 127 111 103 0 
+128 12 107 106 0 
+216 212 180 215 0 
+133 107 120 66 0 
+128 12 75 120 0 
+194 11 73 102 0 
+208 116 117 64 0 
+162 10 37 65 0 
+161 63 10 64 0 
+206 60 9 61 0 
+212 71 8 57 0 
+213 108 8 59 0 
+200 54 7 55 0 
+200 57 7 72 0 
+200 103 7 56 0 
+202 69 4 49 0 
+203 3 46 68 0 
+190 3 85 47 0 
+152 39 2 40 0 
+214 43 2 44 0 
+176 6 54 53 0 
+179 85 15 86 0 
+177 55 176 200 0 
+189 33 5 34 0 
+134 11 101 121 0 
+164 116 65 122 0 
+170 101 102 100 0 
+143 211 203 202 0 
+135 137 143 138 0 
+68 204 67 211 0 
+126 82 14 83 0 
+194 11 74 73 0 
+166 53 28 106 0 
+126 124 191 178 0 
+154 150 73 41 0 
+213 8 71 60 0 
+175 6 107 66 0 
+179 15 87 86 0 
+200 7 103 55 0 
+206 138 181 173 0 
+127 200 56 103 0 
+127 111 56 29 0 
+167 99 20 100 0 
+208 31 117 118 0 
+175 133 162 37 0 
+187 4 91 50 0 
+185 82 24 80 0 
+167 20 99 117 0 
+182 17 91 90 0 
+184 81 105 104 0 
+202 4 46 45 0 
+29 109 127 110 0 
+177 55 200 103 0 
+192 141 140 183 0 
+183 204 151 124 0 
+176 54 55 53 0 
+203 46 3 47 0 
+211 68 69 21 0 
+137 209 142 187 0 
+46 147 45 47 0 
+202 46 4 69 0 
+176 36 6 37 0 
+216 37 38 36 0 
+183 139 178 124 0 
+198 121 122 32 0 
+215 57 212 156 0 
+164 122 65 32 0 
+198 133 164 193 0 
+148 30 114 115 0 
+136 113 93 114 0 
+126 83 84 82 0 
+125 103 104 55 0 
+184 124 125 177 0 
+58 156 127 109 0 
+58 156 181 8 0 
+162 10 65 116 0 
+210 19 96 95 0 
+137 202 91 187 0 
+210 95 96 94 0 
+147 47 25 45 0 
+190 86 47 85 0 
+145 16 88 87 0 
+201 39 78 79 0 
+129 77 78 76 0 
+125 14 82 81 0 
+175 37 6 66 0 
+204 68 67 43 0 
+204 43 214 191 0 
+186 34 5 52 0 
+197 160 207 205 0 
+153 33 189 34 0 
+37 133 162 65 0 
+133 66 32 65 0 
+162 159 216 161 0 
+161 158 38 63 0 
+157 175 130 164 0 
+150 192 154 170 0 
+167 98 99 100 0 
+183 186 153 189 0 
+175 176 165 166 0 
+212 70 71 22 0 
+158 60 206 212 0 
+186 189 5 34 0 
+5 52 97 186 0 
+208 31 62 64 0 
+186 153 34 1 0 
+129 76 78 23 0 
+191 24 84 42 0 
+150 102 194 73 0 
+210 119 118 95 0 
+167 170 169 100 0 
+148 114 89 115 0 
+153 35 34 1 0 
+127 58 29 56 0 
+181 109 58 108 0 
+156 57 58 56 0 
+168 122 20 116 0 
+149 41 39 40 0 
+31 208 62 207 0 
+156 57 8 58 0 
+128 12 120 107 0 
+140 143 142 183 0 
+184 104 28 55 0 
+128 12 106 77 0 
+169 98 100 27 0 
+187 48 50 26 0 
+187 91 92 50 0 
+187 50 48 49 0 
+167 174 99 172 0 
+188 5 33 49 0 
+169 27 170 51 0 
+215 216 22 36 0 
+125 14 81 104 0 
+146 86 88 25 0 
+72 57 212 215 0 
+147 90 25 88 0 
+43 3 204 68 0 
+147 90 91 45 0 
+215 212 72 22 0 
+167 198 101 20 0 
+157 180 216 158 0 
+188 5 48 97 0 
+214 80 24 44 0 
+191 24 42 44 0 
+154 74 41 73 0 
+208 64 117 31 0 
+149 1 41 40 0 
+150 41 1 73 0 
+131 13 78 77 0 
+131 201 79 214 0 
+175 216 37 162 0 
+175 216 157 176 0 
+132 77 106 105 0 
+176 54 36 72 0 
+207 18 112 119 0 
+174 99 118 117 0 
+152 67 35 40 0 
+131 78 13 79 0 
+167 100 20 101 0 
+216 22 36 38 0 
+168 159 164 116 0 
+134 75 11 121 0 
+133 66 120 32 0 
+151 131 214 201 0 
+171 199 97 188 0 
+214 131 13 79 0 
+206 213 181 156 0 
+163 9 63 62 0 
+166 106 107 53 0 
+198 121 101 122 0 
+207 62 31 119 0 
+156 212 213 8 0 
+181 108 213 173 0 
+206 213 60 61 0 
+173 30 115 59 0 
+209 26 199 187 0 
+206 163 205 9 0 
+173 108 59 115 0 
+156 139 144 180 0 
+17 89 182 114 0 
+125 185 81 82 0 
+205 30 61 113 0 
+127 111 29 110 0 
+134 11 75 74 0 
+155 87 110 109 0 
+179 15 84 83 0 
+143 202 137 142 0 
+200 7 57 56 0 
+146 88 86 87 0 
+145 88 16 89 0 
+181 108 16 109 0 
+170 27 100 102 0 
+128 75 12 76 0 
+185 80 81 82 0 
+184 104 105 28 0 
+214 80 44 79 0 
+202 91 187 4 0 
+206 213 156 212 0 
+169 27 52 98 0 
+146 86 25 47 0 
+171 188 97 5 0 
+169 97 98 52 0 
+215 36 22 72 0 
+183 186 150 153 0 
+210 136 195 207 0 
+110 179 87 155 0 
+172 99 19 118 0 
+209 93 94 92 0 
+205 113 61 112 0 
+142 202 187 189 0 
+210 94 18 95 0 
+192 170 171 174 0 
+207 62 119 112 0 
+128 130 133 134 0 
+209 199 142 187 0 
+188 49 187 48 0 
+202 49 189 69 0 
+148 138 205 173 0 
+197 207 136 205 0 
+135 141 140 195 0 
+145 89 90 88 0 
+137 187 142 202 0 
+190 85 3 42 0 
+136 113 205 18 0 
+210 94 136 18 0 
+183 154 151 153 0 
+205 163 160 112 0 
+192 140 174 171 0 
+135 197 136 138 0 
+209 26 92 94 0 
+155 16 87 109 0 
+170 150 102 194 0 
+106 28 132 105 0 
+85 42 190 84 0 
+131 105 13 77 0 
+172 19 99 98 0 
+161 10 63 38 0 
+202 4 45 91 0 
+182 92 17 93 0 
+214 2 79 44 0 
+210 172 19 118 0 
+163 112 9 62 0 
+149 152 151 153 0 
+198 20 122 101 0 
+172 19 97 96 0 
+210 95 18 119 0 
+205 173 61 30 0 
+201 78 39 23 0 
+148 30 205 114 0 
+163 112 205 9 0 
+186 51 1 34 0 
+205 207 18 112 0 
+136 205 207 18 0 
+166 6 53 107 0 
+199 96 48 26 0 
+199 94 96 26 0 
+212 22 71 72 0 
+127 103 56 111 0 
+206 205 173 61 0 
+135 195 140 209 0 
+97 186 171 5 0 
+206 163 9 158 0 
+197 163 206 158 0 
+175 157 165 176 0 
+149 40 153 1 0 
+150 186 51 1 0 
+189 69 49 33 0 
+149 40 152 153 0 
+128 76 12 77 0 
+154 73 194 74 0 
+130 131 151 154 0 
+176 6 36 54 0 
+153 1 40 35 0 
+154 150 194 73 0 
+152 2 67 40 0 
+152 67 21 35 0 
+201 79 2 39 0 
+212 70 60 71 0 
+213 60 61 59 0 
+149 154 129 41 0 
+205 61 9 112 0 
+205 114 30 113 0 
+182 91 17 92 0 
+148 89 16 115 0 
+125 14 104 103 0 
+166 176 177 55 0 
+158 63 70 38 0 
+127 200 156 56 0 
+161 64 10 116 0 
+187 49 4 50 0 
+149 39 41 23 0 
+189 21 69 33 0 
+212 57 72 71 0 
+136 18 93 113 0 
+176 200 55 54 0 
+151 43 152 2 0 
+196 165 180 177 0 
+150 73 51 102 0 
+129 154 201 131 0 
+145 147 146 88 0 
+182 17 90 89 0 
+214 44 191 43 0 
+207 31 118 119 0 
+129 74 75 76 0 
+191 44 42 43 0 
+203 46 69 68 0 
+152 2 43 67 0 
+152 153 35 21 0 
+129 76 23 74 0 
+110 123 127 83 0 
+186 52 51 34 0 
+211 152 21 153 0 
+188 48 5 49 0 
+185 13 81 80 0 
+214 191 44 24 0 
+194 11 102 101 0 
+185 13 105 81 0 
+147 45 25 90 0 
+
+End
diff --git a/examples++-3d/fallingspheres.edp b/examples++-3d/fallingspheres.edp
new file mode 100644
index 0000000..9beb48d
--- /dev/null
+++ b/examples++-3d/fallingspheres.edp
@@ -0,0 +1,49 @@
+// test of mmg3d for move objets in a mesh ...
+load "msh3" 
+load "tetgen" 
+load "medit" 
+load "mmg3d-v4.0"                                                               
+include "MeshSurface.idp"
+
+// build mesh of a box (311)  wit 2 holes  (300,310)
+
+real hs = 0.8; 
+int[int]  N=[4/hs,8/hs,11.5/hs];
+real [int,int]  B=[[-2,2],[-2,6],[-10,1.5]];
+int [int,int]  L=[[311,311],[311,311],[311,311]];
+mesh3 ThH = SurfaceHex(N,B,L,1);
+mesh3 ThSg =Sphere(1,hs,300,-1); // "gluing" surface meshs to tolat boundary meshes
+mesh3 ThSd =Sphere(1,hs,310,-1); 
+
+ThSd=movemesh(ThSd,[x,4+y,z]);
+
+mesh3 ThHS=ThH+ThSg+ThSd;
+medit("ThHS", ThHS);
+
+real voltet=(hs^3)/6.;
+cout << " voltet = " << voltet << endl;
+real[int] domaine = [0,0,-4,1,voltet];
+real [int] holes=[0,0,0,0,4,0];
+mesh3 Th = tetg(ThHS,switch="pqaAAYYQ",regionlist=domaine,holelist=holes);    
+medit("Box-With-two-Ball",Th);
+// End build mesh 
+
+// int[int] opt=[9,0,64,0,0,3];   // options  of mmg3d see freeem++ doc 
+
+real[int] vit=[0,0,-0.3];
+func zero = 0.;
+func dep  = vit[2];
+
+fespace Vh(Th,P1); 
+macro Grad(u) [dx(u),dy(u),dz(u)] //
+
+Vh uh,vh; //  to compute the displacemnt field 
+problem Lap(uh,vh,solver=CG) = int3d(Th)(Grad(uh)'*Grad(vh))  //') for emacs
+				  + on(310,300,uh=dep) +on(311,uh=0.); 
+
+for(int it=0; it<29; it++){ 
+  cout<<"  ITERATION       "<<it<<endl;
+  Lap;
+  plot(Th,uh);
+  Th=mmg3d(Th,opt="-O 9",displacement=[zero,zero,uh]); 
+ }
diff --git a/examples++-3d/first.edp b/examples++-3d/first.edp
new file mode 100644
index 0000000..15f0e3a
--- /dev/null
+++ b/examples++-3d/first.edp
@@ -0,0 +1,128 @@
+verbosity=2;
+mesh3 Th("dodecaedre01");
+border cc(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
+mesh Th2=buildmesh(cc(50));
+fespace Vh2(Th2,P2);
+int nbtets=Th.nt;
+cout << " Th mes " << Th.mesure << " border mes " << Th.bordermesure << endl;
+cout << " nb of Tets = " << nbtets << endl;
+if(1) {
+  nbtets=2;
+  for (int i=0;i<nbtets;i++)
+    for (int j=0; j <4; j++)
+      cout << i << " " << j << " Th[i][j] = "
+	   << Th[i][j] << "  x = "<< Th[i][j].x  << " , y= "<< Th[i][j].y 
+	   << ",  label=" << Th[i][j].label << endl;
+	    
+//   Th(i)   return   the vextex i of Th
+//   Th[k]   return   the tet k of Th.
+
+  // get vertices information : 
+  int nbvertices=Th.nv;
+  //nbvertices=2;
+  cout << " nb of vertices = " << nbvertices << endl;
+  for (int i=0;i<nbvertices;i++)
+	cout << "Th(" <<i  << ") : "   // << endl;	
+	     << Th(i).x << " " << Th(i).y  << " " << Th(i).z << " " << Th(i).label // version 2.19 
+	  << endl;
+ // version >3.4-1
+  // --------- new stuff -----------------
+  int k=0,l=1,e=1;
+  Th.nbe ; // return the number of boundary element \hfilll
+  Th.be(k);   // return the boundary element k $\in \{0,...,Th.nbe-1\}$ \hfilll
+  Th.be(k)[l];   // return the vertices l $\in \{0,1\}$ of  boundary element k \hfilll
+  Th.be(k).Element ;   // return the tet contening the  boundary element k \hfilll
+  Th.be(k).whoinElement ;   // return the egde number of triangle contening the  boundary element k \hfilll
+  Th[k].adj(e) ; // return adjacent tet to k by face e, and change the value of e to \hfilll
+  // the corresponding face in the adjacent tet
+  Th[k] == Th[k].adj(e) ;// non adjacent tet return the same 
+  Th[k] != Th[k].adj(e) ;// true adjacent tet 
+  
+  cout << " print mesh connectivity " << endl;
+  int nbelement = Th.nt; 
+  for (int k=0;k<nbelement;++k)
+    cout << k << " :  " << int(Th[k][0]) << " " << int(Th[k][1]) << " " <<  int(Th[k][2]) 
+         << " " <<  int(Th[k][3])
+	 << " , label  " << Th[k].label << endl; 
+  //  
+  
+  for (int k=0;k<nbelement;++k)
+    for (int e=0,ee;e<4;++e) 
+      //  remark FH hack:  set ee to e, and ee is change by method adj, 
+      //  in () to make difference with  named parameters. 
+      {
+	    cout << k <<  " " << e << " <=>  " << int(Th[k].adj((ee=e))) << " " << ee  
+	     << "  adj: " << ( Th[k].adj((ee=e)) != Th[k]) << endl;  
+      }
+      // note :     if k == int(Th[k].adj(ee=e)) not adjacent element 
+
+
+  int nbboundaryelement = Th.nbe; 
+  Th.be;
+    for (int k=0;k<nbboundaryelement;++k)
+      cout << k << " : " <<  Th.be(k)[0] << " " << Th.be(k)[1] << " , label " << Th.be(k).label 
+	   <<  " tet  " << int(Th.be(k).Element) << " " << Th.be(k).whoinElement <<  endl; 
+    
+	  
+savemesh(Th,"dd.meshb");
+ }
+fespace Vh(Th,P23d);
+Vh xx=x;
+if(xx[].n == Th.nv)
+  for(int i=0;i<Th.nv;++i)
+    assert(abs(Th(i).x-xx[][i])<1e-6);
+
+func ue =   2*x*x + 3*y*y + 4*z*z + 5*x*y+6*x*z+1;
+func f= -18. ;
+Vh u=f,b,d,uhe=ue,bc;
+cout << " Vh.ndof =  " <<  Vh.ndof << endl;
+cout << "  Vh.ndofK " << Vh.ndofK << endl;
+cout << Th[5].region << endl;
+// cout << Th(0,0,0).region << endl;  a faire ...
+cout << Th[5][3] << endl;  // ok.. 
+
+
+for(int i=0;i<Vh.ndofK;++i )
+  cout << Vh(11,i) << " ";
+ cout << endl;
+
+cout << ue(0.1,0.2,0.3)<< "  == " << f(0.1,0.2,0.3) << endl; ;
+macro Grad3(u) [dx(u),dy(u),dz(u)]  // EOM
+
+varf vbc(u,v) =  on(0,u=1);
+varf vlap(u,v) = int3d(Th)(Grad3(v)' *Grad3(u)) + int3d(Th)(f*v) + on(0,u=ue);
+varf vBord(u,v,solver=CG) = int2d(Th)(u*v) ;
+verbosity=10; 
+matrix A=vlap(Vh,Vh);
+matrix B=vBord(Vh,Vh);
+verbosity=1; 
+b[]=vlap(0,Vh);
+//bc[]=vbc(0,Vh);
+//cout << bc[] <<endl;
+{
+ofstream fa("A.txt");
+ofstream fb("B.txt");
+fa << A ;
+fb << b[] ;
+}
+
+
+cout << b[]. min << " " << b[].max << endl;
+u[]=A^-1*b[];
+cout << u[]. min << " " << u[].max << endl;
+real err= int3d(Th)( square(u-ue) );
+d= ue-u;
+cout <<  " err = " << err <<  " " << d[].linfty << endl;
+cout << " u (0,0,0) "<< u(0.,0.,0.) << endl;
+cout << " dx(u) (0,0,0) "<< dx(u)(0.,0.,0.) << endl;
+cout << " dy u (0,0,0) "<< dy(u)(0.,0.,0.) << endl;
+cout << " dz u (0,0,0) "<< dz(u)(0.,0.,0.) << endl;
+Vh2 u2=u(x,y,0.);
+plot(u2,wait=1);
+plot(u2,wait=1);
+	{ ofstream file("dd.bb"); 
+	file << "3 1 1 "<< u[].n << " 2 \n";
+	int j;
+	for (j=0;j<u[].n ; j++)  
+	  file << d[][j] << endl; 
+    }  
diff --git a/examples++-3d/intlevelset3d.edp b/examples++-3d/intlevelset3d.edp
new file mode 100644
index 0000000..fb39700
--- /dev/null
+++ b/examples++-3d/intlevelset3d.edp
@@ -0,0 +1,88 @@
+load "medit"
+include "cube.idp"
+real surfS1 = 4*pi;
+real volS1 =surfS1/3.; 
+int nn= 16; 
+int[int]  Nxyz=[nn,nn,nn];
+real [int,int]  Bxyz=[[-2.,2.],[-2.,2.],[-2.,2.]];
+int [int,int]  Lxyz=[[1,1],[1,1],[1,1]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+
+int err=0;
+real eps = 0.5;
+func r = sqrt(x*x +y*y+z*z);
+
+real lc ;
+verbosity=3;
+lc = int2d(Th,levelset=r-1.)(1.) ; 
+cout << " area of the level set = " <<  lc  << " =  surfS1 " << surfS1 ;
+cout << ", Ok = " << (abs(lc-surfS1) < eps) << endl; 
+if( abs(lc-surfS1) > eps) err++;
+fespace Vh(Th,P1);
+// test linear and bilinear ... 
+varf vl(u,v) = int2d(Th,levelset=r-1.)(v) + int2d(Th,levelset=r-1.)(u*v);
+real[int] vv=vl(0,Vh);
+
+cout << " area of the level set (varf linear ) = " <<  (lc=vv.sum)  << "=  surfS1 " << surfS1 ;
+cout  << ", Ok = " << (abs(lc-surfS1) < eps) << endl;
+if( abs(lc-surfS1) > eps) err++; 
+real[int]  one(Vh.ndof); 
+one=1.;
+matrix VV=vl(Vh,Vh); //  matrix with levelset
+vv = VV*one;
+cout << " area of the level set (varf bilinear same) = " <<  (lc=vv.sum)  << "=  surfS1 " << surfS1;
+cout << ", Ok = " << (abs(lc-surfS1) < eps) << endl;; 
+if( abs(lc-surfS1) > eps) err++;
+
+//  just for test a idea approximation of int of negative part of levelset 
+//   to we just change the mesure of the element not the quadrature point 
+{ // test new stuff for level set  ... 
+    macro grad(u) [dx(u),dy(u),dz(u)] //
+    Vh u,v;
+    solve Pxx(u,v) = int3d(Th) ( grad(u)'*grad(v)*1e-8 ) + int3d(Th, levelset= 1-r) ( grad(u)'*grad(v) ) + on(1,u=0) + int3d(Th, levelset= 1-r) ( 1*v);
+    plot(u,wait=1);   
+    varf vxx(u,v) =  int3d(Th, levelset= 1-r) ( u*v ) + int3d(Th, levelset= 1-r) ( 1*v);
+  matrix XX=vxx(Vh,Vh);
+  real[int] xx=vxx(0,Vh);
+  real vol1= int3d(Th, levelset= 1-r)(1.);
+  cout << "   vol1 = " << vol1 << "  ~= " << Th.mesure - volS1 << endl;
+  err += (abs(vol1-(Th.mesure - volS1)) > eps); 
+  cout << " xx.sum = " << xx.sum << " == " << vol1 <<endl;
+  err += (abs(vol1-xx.sum) > 1e-8); 
+  
+  real[int] yy(Vh.ndof); yy=1;
+  xx= XX*yy;
+  cout << " XX.sum = " << xx.sum << " == " << vol1 << endl;
+  err += (abs(vol1-xx.sum) > 1e-8); 
+
+}
+
+
+
+if(0)
+{// test on diff mesh3  not wet implemented (FH  frev 2014)
+mesh3 Th1=Cube(Nxyz,Bxyz,Lxyz);
+mesh3 Th2=Cube(Nxyz,Bxyz,Lxyz);
+fespace Vh1(Th1,P1);
+fespace Vh2(Th2,P1);
+
+varf vl(u,v) = int2d(Th,levelset=r-1.)(v) + int2d(Th,levelset=r-1.)(u*v);
+real[int] vv=vl(0,Vh2);
+
+cout << " area of the level set (varf linear diff    ) = " <<  (lc=vv.sum)  << "=  surfS1 " << surfS1 ;
+cout  << ", Ok = " << (abs(lc-surfS1) < eps) << endl;
+if( abs(lc-surfS1) > eps) err++; 
+real[int]  one(Vh1.ndof); 
+one=1.;
+// sorry not implemented to day ... FH 
+//verbosity=10000;
+matrix VV=vl(Vh1,Vh2); // no build of matrix with levelset 
+vv = VV*one;
+cout << " area of the level set (varf bilinear diff ) = " <<  (lc=vv.sum)  << "=  surfS1 " << surfS1;
+cout << ", Ok = " << (abs(lc-surfS1) < eps) << endl;; 
+if( abs(lc-surfS1) > eps) err++;
+
+}
+cout << " Nb err " << err << endl;
+assert(err==0);
+
diff --git a/examples++-3d/lac-leman-v4.msh b/examples++-3d/lac-leman-v4.msh
new file mode 100644
index 0000000..6299167
--- /dev/null
+++ b/examples++-3d/lac-leman-v4.msh
@@ -0,0 +1,2177 @@
+ 726 1287 163
+  -3.166550E+01  -1.909791E+01       0
+  -3.215124E+01  -1.923959E+01       0
+  -3.203180E+01  -1.829373E+01       0
+  -3.117977E+01  -1.895624E+01       0
+  -3.018414E+01  -1.794688E+01       0
+  -3.069403E+01  -1.881457E+01       0
+   1.215291E+00   1.556453E+01       0
+   2.186786E+00   1.566365E+01       0
+  -3.148183E+01  -1.744692E+01       0
+  -3.105384E+01  -1.654076E+01       0
+  -2.978685E+01  -1.701745E+01       0
+  -1.094411E+01  -1.575159E+00       0
+  -1.160714E+01  -2.331522E+00       0
+  -3.078949E+01  -1.556367E+01       0
+  -3.054660E+01  -1.457925E+01       0
+  -7.100961E+00   1.313629E+01       0
+  -6.390251E+00   1.385259E+01       0
+  -3.031209E+01  -1.359284E+01       0
+  -3.009034E+01  -1.261755E+01       0
+  -1.005347E+01  -1.094012E+00       0
+  -2.987597E+01  -1.162686E+01       0
+  -2.713174E+01  -1.274498E+01       0
+  -2.775871E+01  -1.353930E+01       0
+  -2.665462E+01  -1.185643E+01       0
+  -8.278338E+00  -1.385359E-01       0
+  -9.197585E+00  -5.679001E-01       0
+  -1.525801E+01  -1.362001E+00       0
+  -1.580458E+01  -5.465184E-01       0
+  -2.943467E+01  -9.648941E+00       0
+  -2.913899E+01  -8.688972E+00       0
+  -1.378167E+01   9.672063E+00       0
+  -1.277474E+01   9.593495E+00       0
+  -2.323562E+01  -5.673601E+00       0
+  -2.370660E+01  -6.564808E+00       0
+   2.534466E+00   3.497695E+00       0
+   1.555411E+00   3.238794E+00       0
+  -2.287303E+01  -4.729162E+00       0
+  -2.637113E+01  -4.574604E+00       0
+  -2.586459E+01  -3.698489E+00       0
+  -1.463674E+00   3.149763E+00       0
+  -2.452829E+00   3.357648E+00       0
+  -2.158959E+01  -3.187480E+00       0
+  -2.224570E+01  -3.947422E+00       0
+  -2.116288E+01  -2.278077E+00       0
+  -2.421287E+01  -1.227155E+00       0
+  -2.382784E+01  -2.991088E-01       0
+  -2.052041E+01  -1.494388E+00       0
+  -7.334484E+00   2.156796E-01       0
+  -1.870830E+01  -7.793139E-01       0
+  -1.969113E+01  -9.672824E-01       0
+   5.550725E-01   3.123134E+00       0
+  -1.579689E+01   9.644691E+00       0
+  -1.478875E+01   9.718360E+00       0
+  -1.235292E+01  -3.003412E+00       0
+  -1.333895E+01  -3.219058E+00       0
+  -1.432420E+01  -3.115663E+00       0
+  -1.493019E+01  -2.320072E+00       0
+  -1.176516E+01   9.608171E+00       0
+  -2.187210E+01   1.973794E+00       0
+  -2.130224E+01   2.795284E+00       0
+  -4.323426E+00   2.737290E+00       0
+  -5.105968E+00   2.101837E+00       0
+  -5.706318E+00   1.287857E+00       0
+  -6.384078E+00   5.466660E-01       0
+  -1.077779E+01   9.773576E+00       0
+  -9.889764E+00   1.025630E+01       0
+  -1.715033E+01   8.406992E+00       0
+  -1.673046E+01   9.291586E+00       0
+  -1.848089E+01   6.888416E+00       0
+  -1.783916E+01   7.665083E+00       0
+  -3.441680E+00   3.229260E+00       0
+  -1.910265E+01   6.092138E+00       0
+  -4.568117E-01   3.095842E+00       0
+  -2.051267E+01   4.654040E+00       0
+  -1.982331E+01   5.386102E+00       0
+  -9.150299E+00   1.092717E+01       0
+  -2.091799E+01   3.728785E+00       0
+  -8.528802E+00   1.171462E+01       0
+  -7.765534E+00   1.237486E+01       0
+  -1.777619E+01  -3.828625E-01       0
+  -2.329540E+01   5.595584E-01       0
+  -2.265328E+01   1.334904E+00       0
+  -2.492831E+01  -1.913491E+00       0
+   1.253833E+01   4.168055E+00       0
+   1.152691E+01   4.186773E+00       0
+  -2.689610E+01  -5.436592E+00       0
+   6.076778E+00   1.456733E+01       0
+   7.058537E+00   1.433012E+01       0
+  -2.426872E+01  -7.405269E+00       0
+  -2.478772E+01  -8.272439E+00       0
+   1.848097E+01   3.136912E+00       0
+   1.751351E+01   3.426128E+00       0
+  -2.758584E+01  -6.172731E+00       0
+  -2.528557E+01  -9.152231E+00       0
+  -2.827818E+01  -6.908854E+00       0
+  -2.885708E+01  -7.720651E+00       0
+  -2.577252E+01  -1.003804E+01       0
+   2.128405E+01   1.997150E+00       0
+   2.034461E+01   2.360448E+00       0
+  -2.623671E+01  -1.093559E+01       0
+   2.410142E+01   2.424263E+00       0
+   2.330206E+01   1.961290E+00       0
+  -2.966143E+01  -1.063902E+01       0
+   2.689433E+01   2.912265E+00       0
+   2.588888E+01   2.995886E+00       0
+   2.790088E+01   2.887291E+00       0
+   2.886948E+01   3.165034E+00       0
+   2.462570E+01   7.732876E+00       0
+   2.554193E+01   7.306142E+00       0
+   2.882900E+01   3.731727E+00       0
+  -2.835500E+01  -1.435314E+01       0
+  -2.876985E+01  -1.527492E+01       0
+  -2.931816E+01  -1.612340E+01       0
+   2.792473E+01   5.449827E+00       0
+   2.874804E+01   4.865112E+00       0
+   8.495348E+00   4.153106E+00       0
+   7.484971E+00   4.137935E+00       0
+   9.505647E+00   4.187049E+00       0
+   1.051416E+01   4.196359E+00       0
+  -3.763476E+00   1.533774E+01       0
+  -2.768691E+00   1.548427E+01       0
+  -2.536491E+01  -2.818201E+00       0
+   1.354819E+01   4.134679E+00       0
+   2.359139E-01   1.532255E+01       0
+   1.455724E+01   4.074767E+00       0
+   1.555854E+01   3.945781E+00       0
+   3.160734E+00   1.538736E+01       0
+   4.128721E+00   1.510135E+01       0
+   5.096318E+00   1.481513E+01       0
+   1.654174E+01   3.708476E+00       0
+   8.032566E+00   1.407691E+01       0
+   1.230851E+01   1.175562E+01       0
+   1.329316E+01   1.152123E+01       0
+   1.133838E+01   1.203148E+01       0
+   2.229403E+01   1.994729E+00       0
+   1.425407E+01   1.130239E+01       0
+   1.525645E+01   1.107616E+01       0
+   1.822242E+01   1.041108E+01       0
+   1.921317E+01   1.018843E+01       0
+   1.723136E+01   1.063330E+01       0
+   2.487469E+01   2.990299E+00       0
+   2.019984E+01   9.965649E+00       0
+   2.636406E+01   6.728216E+00       0
+   2.711385E+01   6.055352E+00       0
+   2.119527E+01   9.738233E+00       0
+   2.209106E+01   9.358974E+00       0
+   2.285851E+01   8.706068E+00       0
+   2.878852E+01   4.298419E+00       0
+   2.372138E+01   8.176893E+00       0
+  -7.651449E-01   1.529451E+01       0
+   5.466136E+00   4.237731E+00       0
+   4.471369E+00   4.087326E+00       0
+  -1.677838E+01  -2.979206E-01       0
+   6.475961E+00   4.201879E+00       0
+   3.498722E+00   3.804208E+00       0
+  -5.554882E+00   1.441290E+01       0
+  -4.634468E+00   1.482889E+01       0
+  -1.759632E+00   1.546301E+01       0
+   8.986220E+00   1.373394E+01       0
+   1.040569E+01   1.241719E+01       0
+   1.943196E+01   2.797553E+00       0
+   1.624104E+01   1.085523E+01       0
+   9.863718E+00   1.325168E+01       0
+  -3.121184E+01  -1.842737E+01       0
+  -3.000638E+01  -1.527752E+01       0
+  -2.929600E+01  -1.481640E+01       0
+  -2.936440E+01  -1.362340E+01       0
+  -2.990323E+01  -1.438283E+01       0
+  -2.924288E+01  -1.243990E+01       0
+  -2.847777E+01  -1.306647E+01       0
+  -2.771592E+01  -1.231345E+01       0
+  -2.895692E+01  -1.150949E+01       0
+  -2.827373E+01  -1.060043E+01       0
+  -2.851239E+01  -1.218514E+01       0
+  -2.886369E+01  -9.778903E+00       0
+  -2.788220E+01  -9.277356E+00       0
+  -2.716205E+01  -8.133773E+00       0
+  -2.818554E+01  -8.289001E+00       0
+  -2.633560E+01  -7.335575E+00       0
+  -2.731436E+01  -7.094331E+00       0
+  -2.567969E+01  -6.710022E+00       0
+  -2.502929E+01  -6.076153E+00       0
+  -2.662220E+01  -6.475689E+00       0
+  -2.597766E+01  -5.918071E+00       0
+  -2.367240E+01  -5.366385E+00       0
+  -2.563564E+01  -5.090832E+00       0
+  -2.494562E+01  -4.456474E+00       0
+  -2.340803E+01  -3.682770E+00       0
+  -2.338819E+01  -2.657475E+00       0
+  -2.420242E+01  -3.000322E+00       0
+  -2.337769E+01  -1.556240E+00       0
+  -2.183700E+01  -1.945817E+00       0
+  -2.282804E+01  -6.192588E-01       0
+  -2.088115E+01  -5.617803E-01       0
+  -2.248661E+01  -1.447411E+00       0
+  -1.982804E+01   7.977405E-01       0
+  -2.198448E+01   2.418496E-01       0
+  -1.898556E+01   1.939247E+00       0
+  -1.765475E+01   2.818694E+00       0
+  -2.075964E+01   7.800584E-01       0
+  -1.996147E+01   1.722273E+00       0
+  -1.344948E+01  -2.475736E+00       0
+  -1.433123E+01  -1.946418E+00       0
+  -1.357503E+01  -1.573305E+00       0
+  -1.992997E+01   3.427644E+00       0
+  -2.044665E+01   2.752736E+00       0
+  -1.300541E+01  -7.177390E-01       0
+  -1.165369E+01   2.151622E+00       0
+  -1.494528E+01   1.549490E+00       0
+  -1.886369E+01   4.951241E+00       0
+  -9.243702E+00   1.307150E+00       0
+  -1.788130E+01   5.795156E+00       0
+  -1.054456E+01   8.778412E-01       0
+  -8.339744E+00   1.715143E+00       0
+  -1.635401E+01   7.852803E+00       0
+  -1.421556E+01   4.339554E+00       0
+  -6.693213E+00   1.193807E+00       0
+  -1.661310E+01   1.449843E+00       0
+  -1.320252E+01   7.823285E+00       0
+  -1.229745E+01   8.997171E+00       0
+  -9.783607E+00   7.442037E+00       0
+  -1.437575E+01  -8.491228E-01       0
+  -1.609578E+01   8.649311E+00       0
+  -9.340321E+00   2.899835E-01       0
+  -7.034109E+00   1.879403E+00       0
+  -1.717805E+01   7.092472E+00       0
+  -1.444355E+01   6.477408E+00       0
+  -5.839757E+00   4.208635E+00       0
+  -7.530865E+00   9.471583E+00       0
+  -1.140219E+01   8.784687E+00       0
+  -1.043594E+01  -4.652853E-01       0
+  -3.301540E+00   9.176939E+00       0
+  -1.014742E+01   3.617145E+00       0
+  -1.270115E+01  -1.915452E+00       0
+  -1.313930E+00   5.365961E+00       0
+  -9.117811E+00   9.202049E+00       0
+  -1.217047E+01  -1.329325E+00       0
+  -7.395129E-01   3.852957E+00       0
+   8.254946E-01   3.834041E+00       0
+  -7.766968E+00   6.821113E+00       0
+  -2.101117E+01   1.852645E+00       0
+   1.397465E+00   4.404514E+00       0
+  -9.048252E+00   1.007204E+01       0
+  -2.165080E+01   1.237485E+00       0
+  -1.835532E+01   1.194155E+00       0
+  -7.451369E+00   1.142082E+01       0
+  -1.917741E+01   2.347887E-01       0
+  -1.138854E+00   6.190456E+00       0
+  -5.013125E+00   1.281868E+01       0
+  -1.894919E+01   3.733540E+00       0
+   2.095248E+00   1.249177E+01       0
+  -6.231526E+00   1.129741E+01       0
+  -2.006876E+01   5.818640E-02       0
+   5.047816E+00   6.805877E+00       0
+   5.879543E+00   1.206272E+01       0
+  -4.851861E+00   1.416334E+01       0
+   7.014873E+00   5.172953E+00       0
+   7.815209E+00   9.787917E+00       0
+  -3.100457E+00   1.467229E+01       0
+  -2.253873E+01  -2.336626E+00       0
+  -2.188892E+01  -9.564023E-01       0
+   9.274157E+00   6.294451E+00       0
+  -9.967689E-01   1.353931E+01       0
+   1.118306E+01   4.689899E+00       0
+  -5.359475E-01   9.159404E+00       0
+  -2.463277E+01  -3.710953E+00       0
+   1.056735E+01   9.964777E+00       0
+   8.686217E-01   1.450966E+01       0
+  -2.425641E+01  -2.194102E+00       0
+   1.156405E+01   6.120647E+00       0
+   1.218559E+01   8.958346E+00       0
+   3.733061E+00   1.436235E+01       0
+   4.933521E+00   1.343812E+01       0
+  -2.451348E+01  -5.355476E+00       0
+   1.402294E+01   8.122092E+00       0
+   4.037852E+00   1.056270E+01       0
+   6.334763E+00   1.364970E+01       0
+  -2.400245E+01  -4.551454E+00       0
+   1.532390E+01   4.951333E+00       0
+   7.618529E+00   1.237351E+01       0
+   7.399642E+00   1.334148E+01       0
+   1.579032E+01   7.733267E+00       0
+   8.538839E+00   1.302224E+01       0
+  -2.479495E+01  -6.841012E+00       0
+   9.471624E+00   1.054154E+01       0
+  -2.527888E+01  -7.483146E+00       0
+   1.720744E+01   4.518148E+00       0
+   9.292955E+00   8.819443E+00       0
+   1.913038E+01   8.379011E+00       0
+   1.188657E+01   9.933715E+00       0
+  -2.797248E+01  -7.625294E+00       0
+  -2.589937E+01  -8.270890E+00       0
+   2.024648E+01   6.743147E+00       0
+   1.247188E+01   1.080869E+01       0
+   2.199446E+01   3.882118E+00       0
+   1.331978E+01   9.666670E+00       0
+  -2.650187E+01  -9.182469E+00       0
+   2.188410E+01   2.509049E+00       0
+   1.447152E+01   1.044576E+01       0
+  -2.699361E+01  -1.021692E+01       0
+   2.320956E+01   2.802630E+00       0
+   1.665934E+01   9.793162E+00       0
+  -2.816000E+01  -1.157092E+01       0
+   1.728219E+01   7.208235E+00       0
+   2.327436E+01   6.485070E+00       0
+   2.036458E+01   9.119381E+00       0
+   2.496909E+01   5.340247E+00       0
+   2.633267E+01   4.493852E+00       0
+   2.083903E+01   8.492726E+00       0
+   2.716244E+01   4.346165E+00       0
+   2.217880E+01   7.636322E+00       0
+   2.156526E+01   5.576129E+00       0
+   2.780109E+01   3.706917E+00       0
+   2.421910E+01   7.037437E+00       0
+   2.522149E+01   6.271831E+00       0
+   2.605199E+01   5.512569E+00       0
+   2.709294E+01   5.077645E+00       0
+   2.784645E+01   4.610206E+00       0
+  -1.730764E+01   1.888267E+00       0
+  -8.307140E+00   9.693098E+00       0
+   5.266988E-01   4.640987E+00       0
+  -3.017351E+01  -1.608848E+01       0
+  -9.424459E+00   6.063944E+00       0
+  -8.215404E+00   8.699068E+00       0
+  -1.428582E+00   4.433988E+00       0
+  -2.734268E+01  -1.124439E+01       0
+  -8.533350E+00   7.664116E+00       0
+  -9.820754E+00   9.615464E+00       0
+   3.153429E-02   3.895118E+00       0
+  -1.001311E+01   2.597929E+00       0
+  -1.131558E+01   6.269415E+00       0
+  -6.166729E+00   8.709197E+00       0
+  -2.283862E+00   1.460755E+01       0
+  -1.141351E+01  -6.283564E-02       0
+  -1.237680E+01   8.305096E+00       0
+  -8.207586E+00   1.060168E+01       0
+  -7.628687E+00   5.644219E+00       0
+  -1.489212E+01   7.146043E+00       0
+  -2.262402E+01  -3.169566E+00       0
+  -1.339538E+01   5.319712E+00       0
+  -1.562364E+01   5.331395E+00       0
+  -5.354467E+00   3.143166E+00       0
+  -1.826791E+01   1.845833E-01       0
+  -1.391789E+01   7.274438E-02       0
+  -1.010704E+01   8.735805E+00       0
+  -1.727349E+01   6.738238E-01       0
+  -6.992121E+00   2.787263E+00       0
+  -1.584344E+01   7.021773E-01       0
+  -1.162136E+01   7.814593E+00       0
+  -1.329287E+01   8.796059E+00       0
+  -1.101684E+01   3.998227E+00       0
+  -1.242000E+01   7.740888E-01       0
+  -1.946014E+01   2.722014E+00       0
+  -1.654937E+01   2.052673E+00       0
+  -7.548728E+00   1.312854E+00       0
+  -1.852652E+01   2.801148E+00       0
+  -1.298991E+01   4.445458E+00       0
+  -1.371023E+01   2.876219E+00       0
+  -1.512404E+01   8.878620E+00       0
+  -5.984841E+00   2.707420E+00       0
+  -8.345048E+00   7.891806E-01       0
+  -1.141723E+01  -1.048491E+00       0
+  -1.982490E+01   4.305416E+00       0
+  -1.370301E+01   8.461397E-01       0
+  -9.166841E+00   2.226975E+00       0
+  -1.785871E+01   4.456614E+00       0
+  -1.569496E+01   3.730842E+00       0
+  -1.653732E+01   2.878306E+00       0
+  -1.647858E+01   5.954288E+00       0
+  -1.424349E+01   9.064389E+00       0
+  -1.544465E+01   7.944569E+00       0
+  -4.667924E+00   3.781661E+00       0
+  -2.172906E+00   5.295905E+00       0
+  -8.237153E+00   2.783632E+00       0
+  -3.993061E+00   4.403707E+00       0
+  -5.083891E+00   5.682918E+00       0
+   4.815287E+00   4.992277E+00       0
+  -5.972520E-01   5.631164E+00       0
+  -1.378789E+00   1.074045E+01       0
+   1.797174E+00   6.043171E+00       0
+   6.588798E+00   7.333266E+00       0
+  -4.639821E+00   1.357759E+01       0
+   7.987409E+00   4.963959E+00       0
+  -3.187643E+00   1.110392E+01       0
+   9.912238E+00   4.911248E+00       0
+   6.000129E-01   1.364126E+01       0
+   1.074631E+01   5.258474E+00       0
+  -1.305143E-01   7.402446E+00       0
+   9.864770E+00   5.629647E+00       0
+   2.500779E+00   1.355139E+01       0
+   1.181429E+01   5.035060E+00       0
+   1.318093E+01   6.308234E+00       0
+   5.696220E+00   1.303185E+01       0
+   5.306624E+00   8.354813E+00       0
+   8.490392E+00   1.110040E+01       0
+   1.626953E+01   4.734584E+00       0
+   1.037582E+01   1.075363E+01       0
+   9.649385E+00   7.169945E+00       0
+   1.884729E+01   4.775526E+00       0
+   1.262490E+01   1.021054E+01       0
+   2.089439E+01   2.904278E+00       0
+   1.276249E+01   9.686857E+00       0
+   2.052635E+01   4.377554E+00       0
+   1.504002E+01   8.623217E+00       0
+   1.419348E+01   8.962527E+00       0
+   1.526627E+01   1.031833E+01       0
+   1.714698E+01   8.997569E+00       0
+   1.804740E+01   5.536333E+00       0
+   2.312459E+01   5.637471E+00       0
+   2.663836E+01   3.696977E+00       0
+   1.996083E+01   8.446339E+00       0
+   2.311712E+01   7.480205E+00       0
+   2.339956E+01   4.953946E+00       0
+   2.840494E+01   4.236361E+00       0
+  -1.926723E+01   1.182322E+00       0
+  -4.558202E+00   1.039281E+01       0
+   3.118998E+00   4.931886E+00       0
+  -4.699728E+00   8.123150E+00       0
+  -5.402032E+00   1.364046E+01       0
+  -6.078351E+00   1.297998E+01       0
+  -1.804203E+01   3.510814E+00       0
+   2.570830E+00   1.503388E+01       0
+   1.947304E+00   1.461096E+01       0
+  -6.600758E+00   9.487618E+00       0
+  -5.844904E+00   1.221482E+01       0
+   1.115317E+00   9.146266E+00       0
+   5.459474E+00   1.394358E+01       0
+   6.294744E+00   5.721626E+00       0
+   6.026059E+00   1.078125E+01       0
+  -2.128583E+01  -1.453350E+00       0
+   8.069807E+00   7.795198E+00       0
+  -3.858081E+00   1.308160E+01       0
+   1.431263E+01   5.153244E+00       0
+  -3.381613E-02   1.197318E+01       0
+  -1.518548E+00   8.679000E+00       0
+   1.129140E+01   1.096577E+01       0
+   1.023680E+01   1.150206E+01       0
+  -2.126217E-01   1.425938E+01       0
+   1.277657E+01   4.900574E+00       0
+   1.066850E+01   8.301679E+00       0
+   1.018967E+01   8.956943E+00       0
+   3.818242E+00   1.215634E+01       0
+   4.596577E+00   1.420283E+01       0
+   3.386640E+00   1.358550E+01       0
+   1.388070E+01   9.661904E+00       0
+   1.243301E+01   7.080290E+00       0
+   4.755257E+00   1.251389E+01       0
+   1.243324E+00   1.146610E+01       0
+   7.798063E+00   1.158490E+01       0
+   1.404835E+01   6.215189E+00       0
+   6.647298E+00   1.269014E+01       0
+   1.741870E+01   9.824943E+00       0
+   1.471074E+01   7.239707E+00       0
+   8.538776E+00   1.195648E+01       0
+   9.464186E+00   1.227509E+01       0
+   8.761903E+00   9.565447E+00       0
+   2.014434E+01   3.371801E+00       0
+   1.699353E+01   5.391604E+00       0
+   9.675554E+00   9.589483E+00       0
+   7.423374E+00   8.458163E+00       0
+   1.960041E+01   9.226595E+00       0
+   2.172651E+01   8.603454E+00       0
+   1.887967E+01   7.455474E+00       0
+   2.405633E+01   3.408241E+00       0
+   1.338652E+01   1.039175E+01       0
+   1.326361E+01   8.906288E+00       0
+   2.157721E+01   2.981502E+00       0
+   2.234432E+01   3.020876E+00       0
+   1.798267E+01   8.155973E+00       0
+   1.646401E+01   6.977754E+00       0
+   2.426653E+01   4.537177E+00       0
+   2.034132E+01   7.585793E+00       0
+   2.563722E+01   3.765440E+00       0
+   2.162684E+01   6.674124E+00       0
+   2.251502E+01   6.857054E+00       0
+   1.990491E+01   5.163642E+00       0
+   1.670490E-01   5.521661E+00       0
+  -8.491089E+00   3.805574E+00       0
+  -7.614537E+00   7.867860E+00       0
+  -1.054027E+01   5.509817E+00       0
+  -6.712455E+00   6.157905E+00       0
+  -2.936250E+00   1.378357E+01       0
+  -1.292578E+01   6.950738E+00       0
+  -9.619388E+00   5.065220E+00       0
+  -2.225233E+00   4.214659E+00       0
+  -1.451383E+01   5.593474E+00       0
+  -1.594809E+01   7.050173E+00       0
+  -7.552948E+00   4.752556E+00       0
+  -9.407825E+00   4.193975E+00       0
+  -1.272966E+01   2.278862E+00       0
+  -1.365315E+01   3.848761E+00       0
+  -1.466124E+01   3.514388E+00       0
+  -1.204541E+01  -6.022265E-01       0
+  -1.455275E+01   8.265932E-01       0
+  -9.980192E+00   1.812241E+00       0
+  -1.723518E+01   3.642089E+00       0
+  -1.548754E+01   2.900626E+00       0
+  -1.599900E+01   4.472961E+00       0
+  -1.531443E+01   6.260712E+00       0
+  -3.115543E+00   7.236352E+00       0
+  -1.850463E+00   6.863078E+00       0
+  -4.946562E+00   4.812548E+00       0
+   3.958973E+00   4.622055E+00       0
+  -2.242582E+00   9.337676E+00       0
+  -3.194717E-01   6.386773E+00       0
+   5.430869E+00   5.850246E+00       0
+  -4.310034E+00   1.216782E+01       0
+  -5.125384E+00   1.177942E+01       0
+   1.481505E+00   1.358307E+01       0
+   3.120752E+00   1.275494E+01       0
+   5.753197E+00   7.627069E+00       0
+   8.410719E+00   1.031406E+01       0
+   1.862781E+01   3.899569E+00       0
+   2.068917E+01   6.073924E+00       0
+   1.681604E+01   7.993021E+00       0
+  -3.662079E+00   1.030962E+01       0
+  -6.466955E+00   7.481663E+00       0
+  -6.749973E+00   1.223725E+01       0
+  -7.125417E+00   1.034944E+01       0
+   4.390077E-01   8.588430E+00       0
+   5.933557E+00   5.024064E+00       0
+   5.040550E+00   9.946437E+00       0
+   7.149365E+00   6.802736E+00       0
+   1.339022E+01   5.427835E+00       0
+  -3.914737E-01   1.019713E+01       0
+  -1.179955E+00   7.676650E+00       0
+   1.252964E+01   5.804914E+00       0
+   9.757729E+00   8.075479E+00       0
+   5.222661E+00   1.154408E+01       0
+   4.423483E+00   1.150481E+01       0
+  -6.226422E-01   1.122479E+01       0
+   7.453743E+00   1.074870E+01       0
+   6.899464E+00   1.172498E+01       0
+   1.502520E+01   6.041071E+00       0
+   9.262934E+00   1.145945E+01       0
+   7.262644E+00   7.575065E+00       0
+   2.125010E+01   7.661196E+00       0
+   1.803292E+01   6.877621E+00       0
+   2.483971E+01   3.850682E+00       0
+   1.611897E+01   5.890981E+00       0
+   2.082086E+01   6.952099E+00       0
+   2.534143E+01   4.586595E+00       0
+  -1.815768E+01   2.129091E+00       0
+  -4.866889E-01   4.756173E+00       0
+  -8.785364E+00   6.796538E+00       0
+  -1.042277E+01   6.469175E+00       0
+  -9.148799E+00   8.341845E+00       0
+  -1.076396E+01   1.970111E+00       0
+  -1.080069E+01   7.976623E+00       0
+  -1.360758E+01   6.258308E+00       0
+  -5.169603E+00   8.976542E+00       0
+  -1.339782E+00   1.450073E+01       0
+  -1.133799E+01   1.459638E+00       0
+  -7.793731E+00   1.001834E+01       0
+  -5.812672E+00   5.364061E+00       0
+  -1.174336E+01   3.558701E+00       0
+  -1.196676E+01   6.984927E+00       0
+  -1.683202E+01   4.456081E+00       0
+  -1.414254E+01   4.869295E+00       0
+  -6.250943E+00   3.344617E+00       0
+  -1.228217E+01   9.382246E-02       0
+  -7.639007E+00   2.085485E+00       0
+  -6.258805E+00   1.999955E+00       0
+  -1.489779E+01   3.943626E-02       0
+  -1.249235E+01   5.103519E+00       0
+  -1.106316E+01   2.968699E+00       0
+  -1.304189E+01   3.802950E-01       0
+  -1.476373E+01   2.417656E+00       0
+  -1.106855E+01   4.728895E+00       0
+  -1.390527E+01   1.714087E+00       0
+  -1.268319E+01   3.486841E+00       0
+  -1.430689E+01   8.090865E+00       0
+  -1.299766E+01   1.253939E+00       0
+  -1.497850E+01   4.546100E+00       0
+  -1.706362E+01   5.150483E+00       0
+  -1.580002E+01   1.988626E+00       0
+  -3.068415E+00   4.183971E+00       0
+  -6.978561E+00   3.975643E+00       0
+  -9.248398E+00   3.209535E+00       0
+  -3.006789E+00   5.613379E+00       0
+  -5.513377E+00   8.109619E+00       0
+   3.418926E+00   5.955381E+00       0
+   1.108797E+00   5.377330E+00       0
+   9.260797E-01   1.005312E+01       0
+  -1.932026E+00   1.373759E+01       0
+   2.344984E+00   4.157891E+00       0
+   3.579048E+00   8.291715E+00       0
+   7.980413E+00   6.084739E+00       0
+   6.867526E+00   9.864573E+00       0
+  -3.967819E+00   1.419509E+01       0
+   7.827264E+00   7.093616E+00       0
+  -1.659381E+00   1.298501E+01       0
+   9.008488E+00   5.176768E+00       0
+  -8.797335E-01   1.190239E+01       0
+   2.595358E+00   6.675119E+00       0
+  -5.788429E-01   8.289032E+00       0
+   1.043224E+01   6.451417E+00       0
+   1.316177E+01   7.867461E+00       0
+   6.580496E+00   8.082344E+00       0
+   2.987151E+00   9.020868E+00       0
+   1.130263E+01   7.043543E+00       0
+   9.237357E+00   7.626641E+00       0
+   1.924493E+01   3.485569E+00       0
+   1.907150E+01   5.663176E+00       0
+   2.138220E+01   4.601830E+00       0
+   2.109448E+01   3.695145E+00       0
+   1.568837E+01   9.661083E+00       0
+   1.477009E+01   9.605354E+00       0
+   1.866558E+01   9.275496E+00       0
+   1.620007E+01   8.804713E+00       0
+   1.889543E+01   6.452778E+00       0
+   2.242520E+01   4.937951E+00       0
+   2.406038E+01   5.752785E+00       0
+   1.959064E+01   7.774495E+00       0
+  -4.193748E+00   1.122172E+01       0
+  -6.040142E+00   1.023647E+01       0
+  -4.325434E+00   5.364698E+00       0
+  -4.359556E+00   9.583805E+00       0
+   2.864529E+00   1.442297E+01       0
+   1.048805E+00   7.538166E+00       0
+   2.277425E+00   1.143451E+01       0
+   6.939276E+00   6.104240E+00       0
+   8.632536E+00   8.794377E+00       0
+  -2.217598E+00   1.147734E+01       0
+   1.563633E+01   6.766881E+00       0
+   8.652391E-01   1.273766E+01       0
+  -1.131360E-01   1.312919E+01       0
+  -1.442105E+00   9.741200E+00       0
+  -3.747465E+00   8.166677E+00       0
+   1.116712E+01   9.017083E+00       0
+   3.844376E+00   1.291963E+01       0
+   1.360479E+01   7.146692E+00       0
+   1.153616E+01   8.010012E+00       0
+   4.201534E+00   1.351563E+01       0
+   2.121509E+00   1.052785E+01       0
+   8.022627E+00   9.030186E+00       0
+   1.955809E+01   4.192982E+00       0
+   1.715532E+01   6.317246E+00       0
+   7.332302E+00   9.246770E+00       0
+   2.309830E+01   3.935399E+00       0
+   1.251983E+01   8.141813E+00       0
+   2.242179E+01   6.017437E+00       0
+   2.079255E+01   5.165096E+00       0
+  -1.388829E+01   7.129119E+00       0
+  -6.754112E+00   5.019540E+00       0
+  -1.197515E+01   2.867420E+00       0
+  -1.830064E+00   6.010908E+00       0
+  -2.521528E+00   6.200644E+00       0
+  -2.445144E+00   8.637652E+00       0
+   4.409970E+00   6.010367E+00       0
+   4.121977E+00   9.714654E+00       0
+   4.931439E+00   1.086212E+01       0
+  -8.618600E-01   1.262130E+01       0
+  -8.437593E+00   6.067855E+00       0
+  -1.168549E+01   7.792602E-01       0
+  -1.196011E+01   4.367081E+00       0
+  -7.875105E+00   4.208050E+00       0
+  -3.749737E+00   6.622524E+00       0
+   2.611875E+00   5.750171E+00       0
+   2.112947E-01   1.098496E+01       0
+   4.549100E+00   8.881750E+00       0
+  -1.562422E+00   1.216153E+01       0
+   2.521956E+00   8.356598E+00       0
+   1.522484E+00   8.445978E+00       0
+   1.055401E+01   7.494033E+00       0
+   8.691459E+00   7.161016E+00       0
+   1.974138E+01   6.184314E+00       0
+   1.789676E+01   9.340577E+00       0
+  -5.822306E+00   9.464157E+00       0
+   2.058334E+00   5.115649E+00       0
+  -3.199729E+00   6.308627E+00       0
+  -2.328291E+00   1.245009E+01       0
+  -4.171474E+00   7.280333E+00       0
+   6.526331E+00   8.958561E+00       0
+   7.616661E-01   6.437349E+00       0
+  -7.107853E+00   8.617753E+00       0
+  -1.163734E+01   5.327806E+00       0
+  -5.165995E+00   7.280186E+00       0
+  -3.315754E+00   1.204583E+01       0
+  -1.248439E+01   6.012252E+00       0
+  -1.242037E+01   7.564266E+00       0
+  -1.031170E+01   4.510288E+00       0
+  -8.560791E+00   4.966075E+00       0
+  -2.800570E+00   4.876022E+00       0
+  -7.717563E+00   3.519564E+00       0
+  -1.213670E+01   1.439200E+00       0
+  -1.367528E+01   4.562429E+00       0
+  -1.647212E+01   3.819662E+00       0
+  -2.953749E+00   8.198591E+00       0
+  -9.301894E-01   6.908404E+00       0
+  -2.164057E+00   7.877357E+00       0
+  -3.465902E+00   5.046021E+00       0
+  -2.479467E+00   1.026916E+01       0
+   6.161962E+00   6.599316E+00       0
+   1.804322E+01   4.445736E+00       0
+  -5.623386E+00   6.395730E+00       0
+   6.620863E-01   9.350614E+00       0
+  -4.239379E+00   8.789026E+00       0
+  -1.099198E+01   7.139972E+00       0
+  -1.639714E+01   5.078985E+00       0
+   3.815512E+00   6.995086E+00       0
+   2.145963E-01   9.444242E+00       0
+   2.065755E+00   9.346411E+00       0
+  -2.959049E+00   1.289438E+01       0
+   2.898199E+00   7.593224E+00       0
+   4.687935E+00   7.835927E+00       0
+   5.956073E+00   8.421729E+00       0
+   3.057576E+00   1.095864E+01       0
+  -5.211243E+00   1.079744E+01       0
+   1.648219E+00   6.848308E+00       0
+   3.663407E+00   1.141480E+01       0
+   8.189206E+00   8.446726E+00       0
+  -1.336393E+00   1.149511E+01       0
+   3.142048E+00   9.889532E+00       0
+   8.846836E+00   8.105335E+00       0
+  -2.373969E+00   1.316814E+01       0
+   2.989124E+00   1.188151E+01       0
+   6.004668E+00   9.720885E+00       0
+   5.564489E+00   9.051740E+00       0
+   3.941591E+00   5.306448E+00       0
+   3.679634E+00   9.175671E+00       0
+   1.960561E+01   7.052681E+00       0
+  -5.193083E+00   9.906298E+00       0
+  -3.704925E+00   5.886393E+00       0
+  -4.530690E+00   6.351655E+00       0
+   2.045850E+00   7.570599E+00       0
+      2      1      3       0
+    245    346    319       0
+    200    244    197       0
+    244     59     82       0
+      4    164      1       0
+     66    243     76       0
+      6      5    164       0
+    243    236    320       0
+    164      3      1       0
+     36    242    239       0
+      5      9    164       0
+    321    242    583       0
+     10      9      5       0
+    165     14    322       0
+     11     10      5       0
+    244    241     59       0
+    241    206     60       0
+     15     14    165       0
+    113    165    322       0
+    489    579    478       0
+    240    481    517       0
+    111    167    166       0
+    113    166    165       0
+    155    417    586       0
+    586     36     35       0
+     19     18    167       0
+    166    167    168       0
+    485     40    325       0
+    239    321    329       0
+     21     19    169       0
+     23     22    171       0
+     22     24    171       0
+    231    334    362       0
+    303    171    326       0
+    237    234     13       0
+    240    479    327       0
+    236    243    328       0
+    300     97    297       0
+    169    170    174       0
+     36    239     51       0
+     51    239    329       0
+     12    362     13       0
+    172    173    103       0
+    234    202     54       0
+     30     29    175       0
+    365    374    579       0
+    297     94    292       0
+    682    233    489       0
+    177    178    176       0
+    240    337    481       0
+    292     90    286       0
+    259    590    482       0
+    177    180    291       0
+     20    231     12       0
+    286     89    284       0
+    231    213    334       0
+    179    183    180       0
+    219    572    644       0
+    284     34    182       0
+     34     33    185       0
+    181    184    183       0
+    230     58    220       0
+     76    243    336       0
+     76    336     78       0
+    182    186    184       0
+    323    480    484       0
+     33     37    185       0
+    325    373    485       0
+     39     38    186       0
+    371    487    338       0
+    278     37    188       0
+     43     42    339       0
+    266     39    187       0
+    227    499    486       0
+     67    226    215       0
+     42     44    192       0
+    189    191    269       0
+    499    338    487       0
+     61     71    372       0
+    563    217     63       0
+    190    269    122       0
+     46     45    191       0
+     44     47    430       0
+    261    430    194       0
+     25    224     26       0
+    224    213    231       0
+     67    223     68       0
+     50     49    247       0
+    192    261    195       0
+    223     52     68       0
+     27    222     28       0
+    247     49    343       0
+    197     81    193       0
+    222    207    344       0
+    328     65    345       0
+    245    343    346       0
+    194    200    197       0
+    228    555    645       0
+     32    220     58       0
+    218    346    348       0
+    230    335    349       0
+    234     54     13       0
+     31     53    370       0
+     55    202     56       0
+    233    579    489       0
+    208    566    646       0
+    196    201    200       0
+    198    356    353       0
+    543    245    319       0
+     55     54    202       0
+    218    348    576       0
+     57     56    203       0
+     48    217    355       0
+    222    203    204       0
+    360    563     62       0
+    198    543    356       0
+    216    492    491       0
+    216    574    492       0
+     70    226     67       0
+    223    215    371       0
+    222    204    207       0
+     62    342    360       0
+     60     59    241       0
+    355    214    361       0
+    204    202    234       0
+    334    655    561       0
+    205    250    363       0
+    209    348    494       0
+    330    566    548       0
+    564    222    344       0
+    421    199    496       0
+    368    354    576       0
+    212     69     72       0
+    361     48    355       0
+    226     69    212       0
+    231     26    224       0
+    217     48     64       0
+    365    495    211       0
+    367    574    498       0
+    341    486    499       0
+     74    363     75       0
+     64     63    217       0
+    210     72     75       0
+    346    153    348       0
+    350     31    370       0
+     32     31    350       0
+    215    223     67       0
+    361    224     25       0
+     65     58    230       0
+     27    203    222       0
+    215    487    371       0
+    211    213    224       0
+    223    359     52       0
+     77    206    205       0
+    562    355    225       0
+    353    201    198       0
+     70     69    226       0
+     60    206     77       0
+    487    226    369       0
+    205    363     77       0
+    342     61    372       0
+    373    235    647       0
+    345    236    328       0
+     20     26    231       0
+    204    203    202       0
+    325     40    238       0
+    214    562    374       0
+     57    203     27       0
+    207    204    234       0
+    500    658    671       0
+    320    336    243       0
+     56    202    203       0
+    207    234    237       0
+     40     73    238       0
+    415    201    196       0
+    329    238     73       0
+    228    372    502       0
+    201    206    241       0
+    253    200    194       0
+    152    151    377       0
+     66    328    243       0
+    200    241    244       0
+    343     80    346       0
+    152    377    503       0
+    518     79    246       0
+    210    212     72       0
+     49     80    343       0
+    235    325    544       0
+    232    629    689       0
+    205    353    250       0
+    195    261    193       0
+    388    690    505       0
+    246    336    519       0
+    197     82     81       0
+     50    247    253       0
+    428    521    257       0
+    425    518    252       0
+    200    201    241       0
+    189    260    191       0
+    254    701    650       0
+    249    508    507       0
+    195    193    191       0
+     50    194     47       0
+    117    116    383       0
+    256    382    590       0
+    197    244     82       0
+    191    193     46       0
+    257    117    383       0
+    157    590    120       0
+    193     81     46       0
+    249    425    508       0
+    189    339    260       0
+    197    193    261       0
+    118    119    385       0
+    251    390    509       0
+     42    192    260       0
+    269     45     83       0
+    387    597    389       0
+    248    378    505       0
+    189    190    188       0
+    190    122    266       0
+    262    593    389       0
+    251    621    717       0
+     43    339    188       0
+    268    423      7       0
+    190    189    269       0
+     43    188     37       0
+    264     85    391       0
+    150    552    438       0
+    188    190    266       0
+    182    274    186       0
+    527    391    439       0
+    443    128    272       0
+    187     39    186       0
+    255    451    393       0
+    185    278    274       0
+    186     38     86       0
+    125    126    279       0
+    254    506    694       0
+     34    185    274       0
+    281     88    277       0
+    187    274    278       0
+    182    184    181       0
+    126    130    396       0
+    258    456    512       0
+    184     86    183       0
+    277    451    281       0
+    181    183    179       0
+    183     93    180       0
+    279    126    396       0
+    163    159    283       0
+     89     34    284       0
+    267    290    436       0
+    184    186     86       0
+     90     89    286       0
+     92     91    513       0
+    262    389    597       0
+    183     86     93       0
+    179    180    177       0
+    695     92    513       0
+    290    271    402       0
+    180     95    291       0
+     94     90    292       0
+    457     99    401       0
+    400    290    402       0
+    180     93     95       0
+    176    178     30       0
+    312    474    514       0
+    275    453    404       0
+    178     96     30       0
+     97     94    297       0
+     98    135    298       0
+    445    466    405       0
+    178    291     96       0
+    173    176    175       0
+    467     98    298       0
+    299    445    608       0
+    176     30    175       0
+    100     97    300       0
+    102    101    301       0
+    282    470    515       0
+    175     29    103       0
+    302    407    452       0
+    169    174    172       0
+    174    171    303       0
+    174    303    172       0
+    287    695    408       0
+    173    175    103       0
+    412    147    311       0
+    169    172     21       0
+    145    142    306       0
+    172    103     21       0
+    305    475    642       0
+    105    104    410       0
+    306    309    145       0
+    170    171    174       0
+    306    461    411       0
+    300    326    100       0
+    111    170    167       0
+    104    106    313       0
+    305    314    412       0
+    170    169    167       0
+    640    468    301       0
+     23    171    170       0
+    169     19    167       0
+    106    107    313       0
+    109    108    314       0
+    165    168     15       0
+    168    167     18       0
+    107    110    313       0
+    307    316    315       0
+     23    170    111       0
+    308    317    316       0
+    168     18     15       0
+    310    318    317       0
+    111    166    112       0
+    166    168    165       0
+    112    166    113       0
+    318    414    115       0
+    322     14     10       0
+    313    110    414       0
+      6    164      4       0
+    115    114    318       0
+    164      9      3       0
+    196    247    415       0
+    246     79     78       0
+    232    504    693       0
+    415    245    198       0
+    253    247    196       0
+    377    506    650       0
+    332    676    517       0
+    249    382    419       0
+     16     79    518       0
+    250    356    421       0
+    363    250    210       0
+      8      7    423       0
+    422      8    423       0
+    252    246    519       0
+    420     16    518       0
+    253    196    200       0
+     50    253    194       0
+    257    154    117       0
+    596    435    526       0
+    273    393    427       0
+    129    443    427       0
+    256    157    156       0
+     17    419    156       0
+    118    593    116       0
+    377    151    521       0
+    283    455    163       0
+    276    708    714       0
+    259    333    121       0
+    120    259    121       0
+    260    192    195       0
+    191    260    195       0
+    261    192    430       0
+    197    261    194       0
+    264    119     85       0
+    523    694    622       0
+    333    552    158       0
+    382    249    432       0
+    391     85     84       0
+    392    527    524       0
+    379    628    525       0
+    501    248    690       0
+    266    122     39       0
+    278    266    187       0
+    397    267    436       0
+    455    283    454       0
+    268      7    124       0
+    263    627    438       0
+    269    191     45       0
+    122    269     83       0
+    392    446    527       0
+    288    623    715       0
+    294    400    465       0
+    288    528    441       0
+    272    128    127       0
+    276    522    652       0
+    273    427    443       0
+    390    251    510       0
+    274    187    186       0
+     34    274    182       0
+    299    465    445       0
+    270    527    446       0
+    711    717    708       0
+    594    434    653       0
+    277     88     87       0
+    429    522    718       0
+    278    185     37       0
+    266    278    188       0
+    287    130     92       0
+    392    524    450       0
+    281    283    131       0
+    255    429    533       0
+    281    280    283       0
+     88    281    131       0
+    140    302    452       0
+    450    433    534       0
+    283    159    131       0
+    395    285    535       0
+    284    182    181       0
+    286    284    181       0
+    454    395    535       0
+    288    441    459       0
+    286    181    179       0
+    292    286    179       0
+    401    606    457       0
+    540    396    458       0
+    456    288    459       0
+    381    523    536       0
+    289    411    461       0
+    138    452    668       0
+    436    294    132       0
+    630    290    267       0
+    291     95     96       0
+    177    291    178       0
+    292    179    177       0
+    297    292    177       0
+    309    472    537       0
+    304    638    538       0
+    294    133    132       0
+    134    436    132       0
+    301    468    135       0
+    464    141    539       0
+    400    402    465       0
+    275    405    466       0
+    297    177    176       0
+    173    300    176       0
+    301    135    102       0
+    401     98    467       0
+    299    137    136       0
+    133    465    136       0
+    300    297    176       0
+    303    326    173       0
+    464    101    141       0
+    298    135    468       0
+    302    140    162       0
+    137    406    162       0
+    326    171     24       0
+    172    303    173       0
+    304    538    469       0
+    279    396    540       0
+    307    613    471       0
+    149    412    314       0
+    461    142    139       0
+    293    514    541       0
+    308    316    542       0
+    109    315    143       0
+    316    144    143       0
+    471    539    542       0
+    311    462    537       0
+    145    309    462       0
+    317    114    144       0
+    473    410    308       0
+    462    147    146       0
+    472    293    541       0
+    474    312    642       0
+    399    637    476       0
+    414    110    148       0
+    410    313    310       0
+    314    108    149       0
+    409    613    305       0
+    315    109    314       0
+    305    613    314       0
+    316    143    315       0
+    542    316    307       0
+    317    144    316       0
+    310    317    308       0
+    318    114    317       0
+    313    318    310       0
+    319    218    354       0
+    198    245    543       0
+    320    236    324       0
+    424    519    229       0
+    321    477    544       0
+    242    321    239       0
+    322     10     11       0
+    113    322     11       0
+    323    484    683       0
+    331    480    546       0
+    324    229    320       0
+    221    327    547       0
+    325    238    544       0
+    373    325    235       0
+    326     24    100       0
+    173    326    300       0
+    547    324    236       0
+    323    545    221       0
+    328     66     65       0
+    230    345     65       0
+    329    321    544       0
+     51    329     73       0
+    566    233    351       0
+    213    495    548       0
+    349    557    699       0
+    227    486    550       0
+    332    581    551       0
+    324    479    676       0
+    333    585    552       0
+    121    333    158       0
+    352    561    655       0
+    237    362    493       0
+    335    230    220       0
+    350    335    220       0
+    336    320    554       0
+     78    336    246       0
+    481    337    645       0
+    545    654    240       0
+    338    227    644       0
+    350    370    572       0
+    339     42    260       0
+    188    339    189       0
+    351    569    656       0
+    349    681    557       0
+    496    368    688       0
+    340    486    559       0
+    360    342    560       0
+     61    342     62       0
+    346     80    153       0
+    247    343    245       0
+    352    573    567       0
+    494    344    364       0
+    549    230    349       0
+    547    345    221       0
+    348    153     28       0
+    319    346    218       0
+    347    374    562       0
+     63     62    563       0
+    348     28    564       0
+    576    348    209       0
+    483    681    219       0
+    546    221    699       0
+    350    219    335       0
+     32    350    220       0
+    357    571    656       0
+    330    233    566       0
+    561    352    567       0
+    213    553    655       0
+    353    205    206       0
+    201    353    206       0
+    492    497    568       0
+    319    354    368       0
+    355    217    225       0
+    211    361    214       0
+    356    199    421       0
+    353    356    250       0
+    565    357    656       0
+    559    687    340       0
+    358    568    570       0
+    556    656    571       0
+    370    359    572       0
+     52    359     53       0
+    560    342    228       0
+    225    563    347       0
+    361    211    224       0
+     48    361     25       0
+    362    237     13       0
+    231    362     12       0
+    363    210     75       0
+     77    363     74       0
+    561    567    207       0
+    490    570    573       0
+    365    211    214       0
+    374    365    214       0
+    366    212    210       0
+    250    366    210       0
+    367    492    574       0
+    369    212    575       0
+    368    199    319       0
+    209    568    576       0
+    369    226    212       0
+    366    558    575       0
+    370     53    359       0
+    371    572    359       0
+    371    338    572       0
+    223    371    359       0
+    485    577     41       0
+    342    372    228       0
+    485    373    684       0
+    248    647    235       0
+    488    683    657       0
+    330    365    579       0
+    375    502    372       0
+     71    375    372       0
+    500    629    673       0
+    332    517    581       0
+    257    521    154       0
+    380    583    670       0
+    380    675    583       0
+    235    378    248       0
+    448    434    660       0
+    333    482    585       0
+    417    659    670       0
+    394    707    719       0
+    588    666    591       0
+    532    429    589       0
+    382    432    590       0
+    419    382    256       0
+    385    593    118       0
+    431    536    591       0
+    693    516    232       0
+    263    585    592       0
+    387    119    264       0
+    383    116    593       0
+    386    268    438       0
+    592    672    662       0
+    387    385    119       0
+    391    387    264       0
+    587    600    663       0
+    265    435    596       0
+    389    385    387       0
+    270    601    597       0
+    422    619    127       0
+    268    509    423       0
+    433    524    123       0
+    387    391    270       0
+    433    123    125       0
+    466    271    641       0
+    427    277     87       0
+    447    393    273       0
+    707    511    599       0
+    426    520    664       0
+    455    535    437       0
+    533    429    532       0
+    396    130    287       0
+    458    396    287       0
+    437    134    160       0
+    267    397    285       0
+    440    528    665       0
+    431    591    666       0
+    457    403    637       0
+    476    514    667       0
+    465    296    445       0
+    290    400    294       0
+    401     99     98       0
+    312    514    643       0
+    402    271    466       0
+    465    402    296       0
+    603    637    513       0
+    467    295    606       0
+    610    282    515       0
+    406    299    608       0
+    405    275    404       0
+    607    406    608       0
+    406    607    162       0
+    299    406    137       0
+    452    407    668       0
+    404    282    610       0
+    463    538    611       0
+    470    540    638       0
+    413    409    612       0
+    315    314    613       0
+    410    104    313       0
+    308    410    310       0
+    472    411    614       0
+    306    411    309       0
+    412    149    147       0
+    474    475    311       0
+    413    471    613       0
+    642    612    409       0
+    414    148    115       0
+    313    414    318       0
+    415    247    245       0
+    201    415    198       0
+    416    516    615       0
+    424    332    669       0
+    586    417    670       0
+    152    503    155       0
+    580    648    671       0
+    516    416    618       0
+    419    256    156       0
+     16    420     17       0
+    420    249    419       0
+     17    420    419       0
+    496    199    368       0
+    250    421    366       0
+    422    423    619       0
+      8    422    127       0
+    509    268    386       0
+    619    423    390       0
+    424    229    676       0
+    551    669    332       0
+    709    252    616       0
+    420    425    249       0
+    664    520    620       0
+    251    448    621       0
+    427    393    277       0
+    129    427     87       0
+    428    257    622       0
+    694    506    428       0
+    395    532    512       0
+    529    429    255       0
+    430    192     44       0
+    194    430     47       0
+    602    666    398       0
+    456    258    636       0
+    592    585    716       0
+    590    432    482       0
+    433    125    279       0
+    470    282    625       0
+    434    448    626       0
+    263    592    653       0
+    504    435    628       0
+    418    678    673       0
+    436    290    294       0
+    437    436    134       0
+    437    285    397       0
+    436    437    397       0
+    438    268    124       0
+    150    438    124       0
+    439    391     84       0
+    123    439     84       0
+    601    665    597       0
+    267    441    630       0
+    630    440    633       0
+    285    459    267       0
+    444    631    634       0
+    621    708    717       0
+    443    129    128       0
+    634    443    272       0
+    444    510    631       0
+    619    444    272       0
+    445    296    466       0
+    404    607    608       0
+    598    446    632       0
+    440    665    633       0
+    447    255    393       0
+    272    444    634       0
+    621    448    635       0
+    626    448    251       0
+    449    395    454       0
+    451    533    280       0
+    534    433    279       0
+    598    632    275       0
+    451    280    281       0
+    393    451    277       0
+    609    668    469       0
+    140    452    138       0
+    453    282    404       0
+    632    453    275       0
+    454    283    280       0
+    449    454    280       0
+    455    437    160       0
+    163    455    160       0
+    512    285    395       0
+    460    712    636       0
+    603    457    637       0
+     99    457    161       0
+    458    287    408       0
+    304    470    638       0
+    459    441    267       0
+    456    459    285       0
+    623    712    715       0
+    589    429    718       0
+    461    306    142       0
+    138    609    139       0
+    462    311    147       0
+    145    462    146       0
+    614    722    472       0
+    469    463    289       0
+    464    471    640       0
+    101    464    301       0
+    465    299    136       0
+    294    465    133       0
+    466    296    402       0
+    633    446    641       0
+    467    298    468       0
+    605    606    295       0
+    640    301    464       0
+    467    468    295       0
+    469    289    609       0
+    515    469    407       0
+    470    304    515       0
+    453    625    282       0
+    471    413    640       0
+    141    473    539       0
+    472    309    411       0
+    289    614    411       0
+    473    141    105       0
+    410    473    105       0
+    474    541    514       0
+    409    305    642       0
+    475    305    412       0
+    311    475    412       0
+    514    476    643       0
+    722    611    667       0
+    505    477    675       0
+    544    477    378       0
+    578    685    347       0
+    654    323    683       0
+    479    517    676       0
+    327    479    324       0
+    546    323    221       0
+    565    656    677       0
+    645    337    488       0
+    418    581    678       0
+    384    624    679       0
+    259    482    333       0
+    557    483    680       0
+    335    219    681       0
+    489    484    682       0
+    337    654    683       0
+    577    485    684       0
+     40    485     41       0
+    559    486    574       0
+    550    486    340       0
+    487    215    226       0
+    341    499    369       0
+    488    337    683       0
+    374    347    685       0
+    489    478    683       0
+    480    682    484       0
+    490    358    570       0
+    553    208    686       0
+    208    646    490       0
+    559    216    687       0
+    492    367    497       0
+    491    492    358       0
+    493    207    237       0
+    334    493    362       0
+    494    348    564       0
+    570    494    364       0
+    495    213    211       0
+    330    495    365       0
+    498    688    367       0
+    421    496    366       0
+    497    576    568       0
+    368    497    367       0
+    575    700    369       0
+    368    367    688       0
+    499    227    338       0
+    369    499    487       0
+    629    500    689       0
+    725    617    724       0
+    526    501    690       0
+    689    500    691       0
+    617    375    692       0
+    555    502    376       0
+    720    377    650       0
+    155    503    417       0
+    628    435    265       0
+    384    516    693       0
+    505    378    477       0
+    583    675    477       0
+    506    377    521       0
+    381    511    694       0
+    672    679    624       0
+    249    507    432       0
+    508    425    252       0
+    615    508    709       0
+    509    390    423       0
+    627    626    386       0
+    510    442    631       0
+    390    510    444       0
+    511    381    599       0
+    706    511    394       0
+    512    456    285       0
+    449    532    395       0
+    603     91    161       0
+    287     92    695       0
+    514    293    667       0
+    403    643    476       0
+    515    304    469       0
+    610    515    407       0
+    516    384    615       0
+    723    618    416       0
+    517    479    240       0
+    376    725    696       0
+    518    246    252       0
+    420    518    425       0
+    519    336    554       0
+    616    519    424       0
+    520    388    620       0
+    584    525    702       0
+    521    151    154       0
+    506    521    428       0
+    707    674    719       0
+    652    522    429       0
+    588    257    383       0
+    460    536    431       0
+    524    439    123       0
+    450    524    433       0
+    697    702    520       0
+    434    531    660       0
+    596    388    520       0
+    691    526    435       0
+    527    270    391       0
+    524    527    439       0
+    528    398    665       0
+    441    528    440       0
+    529    255    447       0
+    442    530    447       0
+    530    276    652       0
+    447    530    529       0
+    531    379    525       0
+    584    660    525       0
+    532    258    512       0
+    533    532    449       0
+    533    449    280       0
+    255    533    451       0
+    534    279    540       0
+    450    534    453       0
+    535    285    437       0
+    454    535    455       0
+    536    523    591       0
+    599    536    460       0
+    537    474    311       0
+    309    537    462       0
+    604    408    399       0
+    469    538    463       0
+    542    473    308       0
+    464    539    471       0
+    638    458    408       0
+    625    540    470       0
+    541    474    537       0
+    472    541    537       0
+    542    307    471       0
+    473    542    539       0
+    543    319    199       0
+    356    543    199       0
+    544    378    235       0
+    329    544    238       0
+    545    240    327       0
+    221    545    327       0
+    546    480    323       0
+    549    699    221       0
+    547    327    324       0
+    345    547    236       0
+    548    495    330       0
+    490    686    208       0
+    549    221    345       0
+    230    549    345       0
+    550    340    680       0
+    219    644    483       0
+    618    551    698       0
+    709    616    723       0
+    552    263    438       0
+    158    552    150       0
+    553    213    548       0
+    208    553    548       0
+    554    320    229       0
+    519    554    229       0
+    555    228    502       0
+    696    555    376       0
+    571    357    491       0
+    566    556    646       0
+    565    680    340       0
+    549    349    699       0
+    575    558    700       0
+    496    558    366       0
+    574    486    341       0
+    491    687    216       0
+    578    228    645       0
+    360    560    347       0
+    561    207    493       0
+    334    561    493       0
+    562    214    355       0
+    347    562    225       0
+    563    360    347       0
+    217    563    225       0
+    564     28    222       0
+    494    564    344       0
+    680    677    331       0
+    357    565    340       0
+    566    351    556       0
+    548    566    208       0
+    567    364    344       0
+    207    567    344       0
+    570    209    494       0
+    492    568    358       0
+    569    351    682       0
+    331    677    480       0
+    570    568    209       0
+    573    570    364       0
+    571    491    358       0
+    490    571    358       0
+    572    338    644       0
+    350    572    219       0
+    573    364    567       0
+    686    573    352       0
+    574    216    559       0
+    498    574    341       0
+    575    212    366       0
+    498    700    558       0
+    576    497    368       0
+    218    576    354       0
+    577    375     71       0
+     41    577     71       0
+    578    347    560       0
+    228    578    560       0
+    579    374    478       0
+    330    579    233       0
+    684    692    577       0
+    647    648    373       0
+    696    517    481       0
+    551    581    418       0
+    720    417    503       0
+    587    663    705       0
+    583    477    321       0
+    586    670    242       0
+    697    584    702       0
+    600    714    703       0
+    672    592    716       0
+    552    585    263       0
+    586    242     36       0
+    155    586     35       0
+    595    701    705       0
+    394    661    706       0
+    588    523    622       0
+    593    588    383       0
+    599    674    707       0
+    532    589    258       0
+    590    259    120       0
+    256    590    157       0
+    591    523    588       0
+    262    666    588       0
+    704    716    482       0
+    713    594    662       0
+    593    385    389       0
+    588    593    262       0
+    594    531    434       0
+    627    653    434       0
+    595    380    659       0
+    650    701    582       0
+    596    526    388       0
+    265    596    520       0
+    597    398    262       0
+    270    597    387       0
+    632    446    392       0
+    466    598    275       0
+    599    381    536       0
+    639    674    460       0
+    661    587    706       0
+    621    635    708       0
+    601    270    446       0
+    598    641    446       0
+    602    398    528       0
+    288    715    528       0
+    603    513     91       0
+    457    603    161       0
+    604    611    408       0
+    476    604    399       0
+    605    403    606       0
+    640    612    295       0
+    606    403    457       0
+    467    606    401       0
+    607    404    610       0
+    162    607    302       0
+    608    445    405       0
+    404    608    405       0
+    609    289    461       0
+    139    609    461       0
+    610    407    302       0
+    607    610    302       0
+    611    538    408       0
+    667    611    604       0
+    612    312    605       0
+    295    612    605       0
+    613    409    413       0
+    315    613    307       0
+    614    289    463       0
+    722    614    463       0
+    615    384    679       0
+    508    615    507       0
+    616    669    723       0
+    519    616    252       0
+    617    376    502       0
+    375    617    502       0
+    629    698    418       0
+    516    618    232       0
+    619    390    444       0
+    127    619    272       0
+    675    388    505       0
+    595    705    726       0
+    635    448    584       0
+    530    442    711       0
+    622    257    588       0
+    381    694    523       0
+    623    636    712       0
+    456    623    288       0
+    624    384    693       0
+    531    594    713       0
+    625    453    534       0
+    540    625    534       0
+    626    251    509       0
+    386    626    509       0
+    627    434    626       0
+    438    627    386       0
+    628    265    525       0
+    693    628    379       0
+    649    689    691       0
+    618    698    232       0
+    630    441    440       0
+    290    630    271       0
+    631    442    447       0
+    273    634    447       0
+    632    392    450       0
+    453    632    450       0
+    633    601    446       0
+    630    633    271       0
+    634    631    447       0
+    443    634    273       0
+    703    584    426       0
+    651    276    714       0
+    636    623    456       0
+    589    639    258       0
+    637    403    476       0
+    513    637    399       0
+    638    540    458       0
+    538    638    408       0
+    639    460    636       0
+    258    639    636       0
+    640    413    612       0
+    468    640    295       0
+    641    598    466       0
+    633    641    271       0
+    642    475    474       0
+    612    642    312       0
+    643    403    605       0
+    312    643    605       0
+    644    227    550       0
+    483    644    550       0
+    645    555    481       0
+    578    645    488       0
+    646    556    571       0
+    490    646    571       0
+    647    248    501       0
+    500    648    501       0
+    648    580    373       0
+    501    648    647       0
+    649    435    504       0
+    232    649    504       0
+    650    582    720       0
+    254    650    506       0
+    651    714    721       0
+    276    651    522       0
+    652    429    529       0
+    530    652    529       0
+    653    627    263       0
+    662    653    592       0
+    654    337    240       0
+    323    654    545       0
+    655    334    213       0
+    686    655    553       0
+    656    556    351       0
+    677    656    569       0
+    685    478    374       0
+    488    657    578       0
+    725    673    678       0
+    692    580    724       0
+    659    417    582       0
+    595    659    582       0
+    660    531    525       0
+    448    660    584       0
+    661    522    651       0
+    721    661    651       0
+    713    624    379       0
+    653    662    594       0
+    663    600    703       0
+    726    705    663       0
+    726    620    710       0
+    703    664    663       0
+    665    398    597       0
+    633    665    601       0
+    666    262    398       0
+    715    666    602       0
+    667    293    722       0
+    476    667    604       0
+    668    407    469       0
+    138    668    609       0
+    669    551    723       0
+    424    669    616       0
+    670    659    380       0
+    242    670    583       0
+    671    648    500       0
+    617    692    724       0
+    679    432    507       0
+    662    672    624       0
+    673    658    500       0
+    418    673    629       0
+    674    599    460       0
+    589    674    639       0
+    675    380    710       0
+    388    675    620       0
+    676    332    424       0
+    324    676    229       0
+    677    569    480       0
+    557    680    331       0
+    678    581    517       0
+    658    673    725       0
+    679    672    704       0
+    615    679    507       0
+    680    483    550       0
+    677    680    565       0
+    681    483    557       0
+    335    681    349       0
+    682    480    569       0
+    233    682    351       0
+    683    484    489       0
+    657    683    478       0
+    684    373    580       0
+    692    684    580       0
+    685    578    657       0
+    478    685    657       0
+    686    490    573       0
+    655    686    352       0
+    687    491    357       0
+    340    687    357       0
+    688    498    558       0
+    496    688    558       0
+    691    500    501       0
+    232    689    649       0
+    690    248    505       0
+    526    690    388       0
+    691    501    526       0
+    649    691    435       0
+    692    375    577       0
+    671    724    580       0
+    693    504    628       0
+    624    693    379       0
+    694    511    254       0
+    622    694    428       0
+    695    513    399       0
+    408    695    399       0
+    696    678    517       0
+    555    696    481       0
+    697    520    426       0
+    584    697    426       0
+    698    551    418       0
+    232    698    629       0
+    699    557    331       0
+    546    699    331       0
+    700    498    341       0
+    369    700    341       0
+    701    595    582       0
+    706    701    254       0
+    702    525    265       0
+    520    702    265       0
+    703    635    584       0
+    664    703    426       0
+    704    482    432       0
+    679    704    432       0
+    705    701    587       0
+    664    620    726       0
+    706    587    701       0
+    511    706    254       0
+    719    674    718       0
+    511    707    394       0
+    714    635    703       0
+    530    711    276       0
+    709    416    615       0
+    252    709    508       0
+    710    620    675       0
+    595    710    380       0
+    717    442    510       0
+    276    711    708       0
+    712    460    431       0
+    666    715    431       0
+    713    662    624       0
+    531    713    379       0
+    714    708    635       0
+    721    714    600       0
+    715    712    431       0
+    528    715    602       0
+    716    585    482       0
+    672    716    704       0
+    717    711    442       0
+    251    717    510       0
+    719    522    661       0
+    589    718    674       0
+    719    718    522       0
+    394    719    661       0
+    720    582    417       0
+    377    720    503       0
+    721    600    587       0
+    661    721    587       0
+    722    293    472       0
+    611    722    463       0
+    723    551    618       0
+    709    723    416       0
+    724    671    658       0
+    725    724    658       0
+    725    678    696       0
+    617    725    376       0
+    726    710    595       0
+    664    726    663       0
+      1      2       2
+      2      3      15
+      4      1       2
+      5      6      10
+      7      8      12
+      9     10      15
+     11      5      10
+     12     13      10
+     14     15      15
+     16     17      13
+     18     19      15
+     20     12      10
+     19     21      15
+     22     23      10
+     24     22      10
+     25     26      10
+     27     28      10
+     29     30      15
+     31     32       6
+     33     34      10
+     35     36      11
+     37     33      10
+     38     39      15
+     40     41      11
+     42     43      10
+     44     42      10
+     45     46       7
+     47     44      10
+     48     25      10
+     49     50      10
+     36     51      11
+     52     53      14
+     13     54      10
+     55     56      10
+     54     55      10
+     56     57      10
+     32     58      13
+     59     60      14
+     61     62       4
+     63     64      10
+     65     66      13
+     67     68      14
+     68     52      14
+     58     65      13
+     69     70      14
+     62     63      10
+     70     67      14
+     71     61       4
+     72     69      14
+     73     40      11
+     64     48      10
+     74     75      14
+     75     72      14
+     53     31       6
+     66     76      13
+     60     77      14
+     26     20      10
+     57     27      10
+     78     79      13
+     79     16      13
+     80     49      10
+     81     82      14
+     50     47      10
+     46     81      14
+     83     45       7
+     84     85      11
+     43     37      10
+     86     38      15
+     87     88      12
+     34     89      10
+     89     90      10
+     91     92      11
+     93     86      15
+     90     94      10
+     95     93      15
+     30     96      15
+     94     97      10
+     98     99      11
+     97    100      10
+    101    102      11
+    103     29      15
+     21    103      15
+    104    105       1
+    106    104      12
+    107    106      12
+    108    109      12
+    110    107      12
+     23    111      10
+     15     18      15
+    111    112      10
+    112    113      10
+     10     14      15
+      6      4       2
+    114    115      12
+      3      9      15
+     82     59      14
+    116    117      11
+    118    116      11
+     85    119      11
+    120    121      13
+     39    122      15
+    123     84      11
+    124      7       5
+    122     83      15
+    125    123      11
+    126    125      11
+    127    128      12
+    128    129      12
+     92    130      11
+     88    131      12
+     96     95      15
+    132    133      12
+    134    132      12
+    102    135      11
+    136    137      12
+    133    136      12
+    135     98      11
+    138    139      12
+    140    138      12
+    105    141       1
+    139    142      12
+    143    144      12
+    145    146      12
+    144    114      12
+    146    147      12
+    148    110      12
+    149    108      12
+      8    127      12
+    113     11      10
+    150    124       5
+    151    152      11
+    100     24      10
+     76     78      13
+     41     71       4
+    153     80      10
+     51     73      11
+     28    153      10
+     77     74      14
+    154    151      11
+    152    155      11
+    117    154      11
+     17    156      13
+    157    120      13
+    156    157      13
+    121    158      13
+    131    159      12
+    160    134      12
+     99    161      11
+    142    145      12
+    147    149      12
+    115    148      12
+    119    118      11
+    158    150      13
+    155     35      11
+    129     87      12
+    162    140      12
+    163    160      12
+    159    163      12
+    141    101       1
+    109    143      12
+    130    126      11
+    161     91      11
+    137    162      12
diff --git a/examples++-3d/meditddm.edp b/examples++-3d/meditddm.edp
new file mode 100644
index 0000000..c65c4e5
--- /dev/null
+++ b/examples++-3d/meditddm.edp
@@ -0,0 +1,50 @@
+// meditddm.edp
+load "medit"
+
+/********************************************
+ Initial Problem:
+Resolution of the following EDP:
+$- \Delta u = f$ on   $\Omega =\{ (x,y) |  1 \leq sqrt(x^2+y^2) \geq 2}$
+$- \Delta u = f1$ on  $\Omega_{1} =\{ (x,y) |  0.5 \leq sqrt(x^2+y^2) \geq 1.}$
+$u = 1$ on $\Gamma$  +  Null Neumman condition on $\Gamma_{1}$ and on $\Gamma_{2}$	
+We find the solution $u$ in solving two EDP defined on domain $\Omega$ and $\Omega_{1}$
+This solution is vizualize with ffmedit 
+*********************************************/
+verbosity=3;
+
+border Gamma(t=0,2*pi){x=cos(t); y=sin(t); label=1;};
+border Gamma1(t=0,2*pi){x=2*cos(t); y=2*sin(t); label=2;};
+border Gamma2(t=0,2*pi){x=0.5*cos(t); y=0.5*sin(t); label=3;};
+
+// construction of mesh of domain $\Omega$
+mesh Th=buildmesh(Gamma1(40)+Gamma(-40)); 
+
+fespace Vh(Th,P2);
+func f=sqrt(x*x+y*y);
+Vh us,v;
+macro Grad2(us) [dx(us),dy(us)]  // EOM
+
+problem Lap2dOmega(us,v,init=false)=int2d(Th)(Grad2(v)' *Grad2(us)) - int2d(Th)(f*v)+on(Gamma,us=1) ;
+//  Resolution of EDP defined on the domain $\Omega$
+// $- \Delta u = f$ on $\Omega$ 
+//      $u = 1$  on $\Gamma
+//   + Null Neumann condition on $\Gamma_{1}$
+Lap2dOmega;
+
+// construction of mesh of domain $\Omega1 =\{ (x,y) |  0.5 \leq sqrt(x^2+y^2) \geq 1.}$
+mesh Th1=buildmesh(Gamma(40)+Gamma2(-40));
+
+fespace Vh1(Th1,P2);
+func f1=10*sqrt(x*x+y*y);
+Vh1 u1,v1;
+macro Grad21(u1) [dx(u1),dy(u1)]  // EOM
+
+problem Lap2dOmega1(u1,v1,init=false)=int2d(Th1)(Grad21(v1)' *Grad21(u1)) - int2d(Th1)(f1*v1)+on(Gamma,u1=1) ;
+//   Resolution of EDP defined on the domain $\Omega_{1}$
+// $- \Delta u = f1$ on $\Omega_{1}$ 
+//      $u = 1$ on $\Gamma$
+//   + Null Neumann condition on $\Gamma_{2}$
+Lap2dOmega1; 
+
+// vizualisation of solution of the initial problem
+medit("solution",Th,us,Th1,u1,order=1,meditff="ffmedit",save="testsavemedit.solb",wait=1);	
diff --git a/examples++-3d/p.edp b/examples++-3d/p.edp
new file mode 100644
index 0000000..009a122
--- /dev/null
+++ b/examples++-3d/p.edp
@@ -0,0 +1,36 @@
+verbosity=2;
+
+mesh3 Th("dodecaedre01");
+fespace Vh(Th,P23d);
+func ue =   2*x*x + 3*y*y + 4*z*z + 5*x*y+6*x*z+1;
+func f= -18. ;
+//Vh uhe = ue; // bug ..
+//cout << " uhe min:  " << uhe[]. min << " max:" << uhe[].max << endl;
+/*
+border cc(t=0,2*pi){x=cos(t);y=sin(t);label=1;}
+mesh Th2=buildmesh(cc(50));
+fespace Vh2(Th2,P2);
+
+
+Vh u,v;
+
+//uhe = ue;
+macro Grad3(u) [dx(u),dy(u),dz(u)]  // EOM
+
+problem Lap3d(u,v,solver=CG)=int3d(Th)(Grad3(v)' *Grad3(u)) - int3d(Th)(f*v) + - int3d(Th)(f*v) + on(0,1,u=ue);
+Lap3d;
+cout << " u min::   " << u[]. min << "  max: " << u[].max << endl;
+real err= int3d(Th)( square(u-ue) );
+cout << int3d(Th)(1.) << " = " << Th.mesure << endl;
+Vh d= ue-u;
+cout <<  " err = " << err <<  " diff l^\intfy = " << d[].linfty << endl;
+Vh2 u2=u;
+plot(u2,wait=1);
+plot(u2,wait=1);
+	{ ofstream file("dd.bb"); 
+	file << "3 1 1 "<< u[].n << " 2 \n";
+	int j;
+	for (j=0;j<u[].n ; j++)  
+	  file << d[][j] << endl; 
+    }  
+*/
diff --git a/examples++-3d/periodic-3d.edp b/examples++-3d/periodic-3d.edp
new file mode 100644
index 0000000..b4ff6de
--- /dev/null
+++ b/examples++-3d/periodic-3d.edp
@@ -0,0 +1,43 @@
+load "msh3"
+load "medit"
+searchMethod=1; // more safe seach algo .. (FH for PICHON ??) 
+verbosity=1;
+real a=1, d=0.5, h=0.5;
+border b1(t=0.5,-0.5) {x=a*t; y=-a/2; label=1;};
+border b2(t=0.5,-0.5) {x=a/2; y=a*t; label=2;};
+border b3(t=0.5,-0.5) {x=a*t; y=a/2; label=3;};
+border b4(t=0.5,-0.5) {x=-a/2; y=a*t; label=4;};
+border i1(t=0,2*pi) {x=d/2*cos(t); y=-d/2*sin(t); label=7;};
+int nnb=7, nni=10; 
+mesh Th=buildmesh(b1(-nnb)+b3(nnb)+b2(-nnb)+b4(nnb)+i1(nni));//, fixeborder=true);
+//Th=adaptmesh(Th,0.1,IsMetric=1,periodic=[[1,x],[3,x],[2,y],[4,y]]);
+int nz=3;
+{ // for cleanning  memory..
+int[int] old2new(0:Th.nv-1);
+fespace Vh2(Th,P1);
+Vh2 sorder=x+y; 
+sort(sorder[],old2new);
+int[int]  new2old=old2new^-1;   // inverse the permuation 
+//for(int i=0;i< Th.nv;++i) // so by hand. 
+//  new2old[old2new[i]]=i;
+Th= change(Th,renumv=new2old);
+sorder[]=0:Th.nv-1;
+}
+{
+  fespace Vh2(Th,P1);
+  Vh2 nu;
+  nu[]=0:Th.nv-1;
+  plot(nu,cmm="nu=",wait=1);
+}
+int[int] rup=[0,5], rlow=[0,6], rmid=[1,1,2,2,3,3,4,4,7,7], rtet=[0,41];
+func zmin=0;
+func zmax=h;
+mesh3 Th3=buildlayers(Th, nz, zbound=[zmin,zmax],
+reftet=rtet,reffacemid=rmid, reffaceup=rup, reffacelow=rlow);
+for(int i=1;i<=6;++i)
+  cout << " int " << i << " :  " << int2d(Th3,i)(1.) << " " << int2d(Th3,i)(1./area) << endl;
+savemesh(Th3,"Th3.mesh");
+plot(Th3,wait=1);
+medit("Th3",Th3);
+
+fespace Vh(Th3,P2, periodic=[[1,x,z],[3,x,z],[2,y,z],[4,y,z],[5,x,y],[6,x,y]]);
\ No newline at end of file
diff --git a/examples++-3d/pyramide.edp b/examples++-3d/pyramide.edp
new file mode 100644
index 0000000..c463ba8
--- /dev/null
+++ b/examples++-3d/pyramide.edp
@@ -0,0 +1,29 @@
+//  example to build a mesh a cone 
+load "msh3"
+load "medit"
+// cone using buildlayers with a triangle 
+real LX=1,LY=1,LXY=sqrt(LX*LX+LY*LY),HH=1; 
+border Hypo(t=1,0){x=LX*t;y=LY*(1-t);label=1;};
+border Vert(t=LY,0){x=0;y=t;label=0;};
+border Hori(t=0,LX){x=t;y=0;label=0;};
+
+int nn=10;
+real h= 1./nn;
+plot(Vert(LY*nn)+ Hypo(LXY*nn) + Hori(LX*nn),wait=1);
+mesh Th2=buildmesh( Vert(LY*nn)+ Hypo(LXY*nn) + Hori(LX*nn) ) ;
+ Th2 = Th2 + movemesh(Th2,[x,-y])+ movemesh(Th2,[-x,-y])+  movemesh(Th2,[-x,y]);
+plot(Th2,wait=1);
+func fpyramide= (1-abs(x)/LX-abs(y)/LY)*HH;
+fespace Vh2(Th2,P1);
+Vh2 fp2=fpyramide;
+plot(fp2,wait=1,dim=3);
+
+
+int[int] r1T=[0,0], r2up=[0,1],r2down=[0,1];
+int[int] r4T=[0,2]; 
+mesh3 Th3=buildlayers(Th2,coef= max(fpyramide/HH,0.01), nn,zbound=[0,fpyramide],
+ region=r1T, labelup=r2up, labeldown=r2down);
+
+medit("Pyramide",Th3,wait=1);
+// FFCS: testing 3d plots
+plot(Th3);
diff --git a/examples++-3d/ref.edp b/examples++-3d/ref.edp
new file mode 100644
index 0000000..f2701f4
--- /dev/null
+++ b/examples++-3d/ref.edp
@@ -0,0 +1 @@
+real REF3dXLeman=196.33;
diff --git a/examples++-3d/refinesphere.edp b/examples++-3d/refinesphere.edp
new file mode 100644
index 0000000..063bf0a
--- /dev/null
+++ b/examples++-3d/refinesphere.edp
@@ -0,0 +1,59 @@
+// file adaptsphere.edp
+load "msh3"
+load "tetgen"
+load "medit"
+
+mesh Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},frac{-pi}{2}[\times]0,2\pi[ $
+//  a parametrization of a sphere 
+func f1 =cos(x)*cos(y);
+func f2 =cos(x)*sin(y);
+func f3 = sin(x);
+//  partiel derivative of the parametrization DF
+func f1x=sin(x)*cos(y);   
+func f1y=-cos(x)*sin(y);
+func f2x=-sin(x)*sin(y);
+func f2y=cos(x)*cos(y);
+func f3x=cos(x);
+func f3y=0;
+// $  M = DF^t DF $
+func m11=f1x^2+f2x^2+f3x^2;
+func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+func m22=f1y^2+f2y^2+f3y^2;
+
+func perio=[[4,y],[2,y],[1,x],[3,x]];  
+real hh=0.1;
+real vv= 1/square(hh);
+verbosity=2;
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+
+verbosity=2;
+
+// construction of the surface of spheres
+real Rmin  = 1.;
+func f1min = Rmin*f1;
+func f2min = Rmin*f2;
+func f3min = Rmin*f3;
+
+mesh3 Th3=movemesh23(Th,transfo=[f1min,f2min,f3min]);
+
+real[int] domain = [0.,0.,0.,145,0.01];
+mesh3 Th3sph=tetg(Th3,switch="paAAQYY",nbofregions=1,regionlist=domain);
+
+int[int] newlabel = [145,18];
+real[int] domainrefine = [0.,0.,0.,145,0.0001];
+mesh3 Th3sphrefine=tetgreconstruction(Th3sph,switch="raAQ",region=newlabel,nbofregions=1,regionlist=domainrefine,sizeofvolume=0.0001);
+
+int[int] newlabel2 = [145,53];
+func fsize = 0.01/(( 1 + 5*sqrt( (x-0.5)^2+(y-0.5)^2+(z-0.5)^2) )^3);
+mesh3 Th3sphrefine2=tetgreconstruction(Th3sph,switch="raAQ",region=newlabel2,sizeofvolume=fsize);
+
+ medit("sphere",Th3sph,wait=1);
+ medit("sphererefinedomain",wait=1,Th3sphrefine);
+  medit("sphererefinelocal",wait=1,Th3sphrefine2);
+
+// FFCS: testing 3d plots
+plot(Th3sph);
+plot(Th3sphrefine);
+plot(Th3sphrefine2);
diff --git a/examples++-3d/regtests.edp b/examples++-3d/regtests.edp
new file mode 100644
index 0000000..d0b9176
--- /dev/null
+++ b/examples++-3d/regtests.edp
@@ -0,0 +1,50 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+// Regression tests
+// ----------------
+
+// The tests are checked against reference values by "make check" in
+// each examples subdirectory
+
+// "ref.edp" contains all reference values and may be rebuilt with
+// "make Ref"
+
+// $Id$
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+NoUseOfWait=true;
+int verbosityy=verbosity;
+
+
+
+
+include "ref.edp";
+
+
+
+
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+cout << "--------- file : 3d-Leman.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "3d-Leman.edp";
+	real TEST3dXLeman=vregtest;
+		cout<<"3d-Leman reference value = "<<REF3dXLeman
+				<<" test value ="<<TEST3dXLeman<<endl;
+			assert(TEST3dXLeman<REF3dXLeman*(1+0.1));
+				assert(TEST3dXLeman>REF3dXLeman*(1-0.1));
+};
+
+
+
diff --git a/examples++-3d/regtests.m4 b/examples++-3d/regtests.m4
new file mode 100644
index 0000000..99fe46a
--- /dev/null
+++ b/examples++-3d/regtests.m4
@@ -0,0 +1,13 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+include(../regtests.m4)
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+ONETEST(3d-Leman,vregtest,0.1)
+
+
diff --git a/examples++-3d/schwarz-nm-3d.edp b/examples++-3d/schwarz-nm-3d.edp
new file mode 100644
index 0000000..086eac4
--- /dev/null
+++ b/examples++-3d/schwarz-nm-3d.edp
@@ -0,0 +1,176 @@
+bool withmetis=1;
+bool RAS=0;
+int sizeoverlaps=2; // size off overlap 
+int nnx=2,nny=2,nnz=2;
+
+func bool AddLayers(mesh3 & Th,real[int] &ssd,int n,real[int] &unssd)
+{
+  //  build a continuous function  uussd (P1) :
+  //  ssd in the caracteristics function on the input sub domain.
+  //  such that : 
+  //   unssd = 1 when   ssd =1;
+  //   add n layer of element (size of the overlap)
+  //   and unssd = 0 ouside of this layer ...
+  // ---------------------------------
+  fespace Vh(Th,P1);
+  fespace Ph(Th,P0);
+  Ph s;
+  assert(ssd.n==Ph.ndof);
+  assert(unssd.n==Vh.ndof);
+  unssd=0;
+  s[]= ssd;
+  //  plot(s,wait=1,fill=1);
+  Vh u;
+  varf vM(u,v)=int3d(Th,qforder=1)(u*v/volume);
+  matrix M=vM(Ph,Vh);
+  
+  for(int i=0;i<n;++i)
+    {
+      u[]= M*s[];
+      // plot(u,wait=1);
+      u = u>.1; 
+      // plot(u,wait=1);
+      unssd+= u[];
+      s[]= M'*u[];//';
+      s = s >0.1;
+    }
+  unssd /= (n);
+  u[]=unssd;
+  ssd=s[];      
+  return true;
+}
+
+int withplot=3;
+include "cube.idp" 
+ int[int]  NN=[25,25,25]; //  the number of step in each  direction                                                                                                                    
+ real [int,int]  BB=[[0,1],[0,1],[0,1]]; // bounding box                                                                                                             
+ int [int,int]  L=[[1,1],[1,1],[1,1]]; // the label of the 6 face left,right,
+//  front, back, down, right
+mesh3 Th=Cube(NN,BB,L);
+int npart= nnx*nny*nnz;
+fespace Ph(Th,P0);
+fespace Vh(Th,P1);
+
+Ph  part;
+Vh  sun=0,unssd=0;
+Ph xx=x,yy=y,zz=z,nupp;
+//part = int(xx*nnx)*nny + int(yy*nny);
+part = int(xx*nnx)*nny*nnz + int(yy*nny)*nnz + int(zz*nnz);
+//plot(part,wait=1);
+if(withmetis)
+  {
+    load "metis";
+    int[int] nupart(Th.nt);
+    metisdual(nupart,Th,npart); 
+    for(int i=0;i<nupart.n;++i)
+      part[][i]=nupart[i];
+  }
+if(withplot>1)
+plot(part,fill=1,cmm="dual",wait=1);
+mesh3[int] aTh(npart);
+mesh3 Thi=Th;
+fespace Vhi(Thi,P1);
+Vhi[int] au(npart),pun(npart);
+matrix[int] Rih(npart);
+matrix[int] Dih(npart);
+matrix[int] aA(npart);
+Vhi[int] auntgv(npart);
+Vhi[int] rhsi(npart);
+
+for(int i=0;i<npart;++i)
+  {
+    Ph suppi= abs(part-i)<0.1;
+    AddLayers(Th,suppi[],sizeoverlaps,unssd[]);
+    Thi=aTh[i]=trunc(Th,suppi>0,label=10,split=1);
+    Rih[i]=interpolate(Vhi,Vh,inside=1); //  Vh -> Vhi
+    if(RAS)
+      {
+        suppi= abs(part-i)<0.1;
+        varf vSuppi(u,v)=int3d(Th,qforder=1)(suppi*v/volume);
+        unssd[]= vSuppi(0,Vh);
+        unssd = unssd>0.;
+        if(withplot>19)
+          plot(unssd,wait=1);
+      }
+    pun[i][]=Rih[i]*unssd[];
+    sun[] += Rih[i]'*pun[i][];//';
+    if(withplot>9)
+      plot(part,aTh[i],fill=1,wait=1);
+  }
+real[int] viso=[0,0.1,0.2,0.3];  
+plot(sun,wait=1,dim=3,fill=1,viso=viso);
+for(int i=0;i<npart;++i)
+  {
+    Thi=aTh[i];
+    pun[i]= pun[i]/sun;
+    if(withplot>8)
+      plot(pun[i],wait=1);    
+  }
+
+//  verif partition of unite 
+
+macro Grad(u) [dx(u),dy(u),dz(u)]//EOM 
+  sun=0;
+
+for(int i=0;i<npart;++i)
+  {
+    cout << " build part :" << i << "/" << npart << endl;
+    Thi=aTh[i];
+    varf va(u,v) = 
+      int3d(Thi)(Grad(u)'*Grad(v))//')
+      +on(1,u=1) + int3d(Thi)(v)
+      +on(10,u=0) ; 
+    
+    cout << i << " -----------Vhi.ndof " << Vhi.ndof << endl;
+    aA[i]=va(Vhi,Vhi);
+      cout << i << " -----------Vhi.ndof " << Vhi.ndof << endl;
+  
+    set(aA[i],solver=UMFPACK);
+    rhsi[i][]= va(0,Vhi);
+    Dih[i]=pun[i][];
+    real[int]  un(Vhi.ndof);
+    un=1.;
+    real[int] ui=Dih[i]*un; 
+    sun[] += Rih[i]'*ui;;//';
+    varf vaun(u,v) = on(10,u=1);
+    auntgv[i][]=vaun(0,Vhi); // store array of tgv on Gamma intern.
+  }
+if(withplot>5)
+  plot(sun,fill=1,wait=1);
+cout << sun[].max << " " << sun[].min<< endl;
+// verification of the partition of the unite.
+assert( 1.-1e-9 <= sun[].min  && 1.+1e-9 >= sun[].max);  
+
+int nitermax=1000;
+{
+  Vh un=0;
+  for(int iter=0;iter<nitermax;++iter)
+    {
+      real err=0;
+      Vh un1=0;
+      for(int i=0;i<npart;++i)
+        {
+          Thi=aTh[i];
+          real[int] ui=Rih[i]*un[];//';
+          //{   Vhi uuu; uuu[]=ui;      plot(uuu,wait=1);}
+          real[int] bi = ui .* auntgv[i][];
+          bi = auntgv[i][] ? bi :  rhsi[i][];  
+          ui=au[i][];
+          ui= aA[i] ^-1 * bi;
+          //{   Vhi uuu; uuu[]=ui;      plot(uuu,wait=1);}
+          bi = ui-au[i][];
+          err += bi'*bi;//';
+          au[i][]= ui;
+          bi = Dih[i]*ui;
+          un1[] += Rih[i]'*bi;//';
+        }
+      err= sqrt(err);
+      cout << iter << " Err = " << err << endl;
+      if(err<1e-3) break;
+      //    plot(un1,wait=1);
+      un[]=un1[];
+      if(withplot>2)
+        plot(au,dim=3,wait=0,cmm=" iter  "+iter,fill=1 );
+    }
+  plot(un,wait=1,dim=3,fill=1);
+}
diff --git a/examples++-3d/sphere2.edp b/examples++-3d/sphere2.edp
new file mode 100644
index 0000000..a075441
--- /dev/null
+++ b/examples++-3d/sphere2.edp
@@ -0,0 +1,29 @@
+load "msh3"
+load "medit"
+border BC(t=0,2*pi){ x=cos(t);y=sin(t);label=1;}
+mesh TC= buildmesh(BC(100));
+func r
+ = (1e-5+abs(1-square(x)-square(y)))^0.5;
+real cc=100;
+//TC=adaptmesh(TC,[cc*x/r,0,cc*y/r],IsMetric=1);
+plot(TC,wait=1);
+mesh3 Thup=movemesh23(TC,transfo=[x,y,sqrt(abs(1-square(x)-square(y)))]);
+mesh3 Thdown=movemesh23(TC,transfo=[x,y,-sqrt(abs(1-square(x)-square(y)))]);
+verbosity=10;
+mesh3 Th= Thup+Thdown;
+
+
+if(1)
+  {
+    medit("Thup",Thup,wait=1);
+    medit("Thdown",Thdown,wait=1);
+    medit("Th",Th,wait=1);
+ 
+   // FFCS: removing medit calls for regression tests will empty the
+   // curly brackets
+   1;
+  }
+// FFCS: testing 3d plots
+plot(Thup);
+plot(Thdown);
+plot(Th);
diff --git a/examples++-3d/sphere6.edp b/examples++-3d/sphere6.edp
new file mode 100644
index 0000000..41d4a06
--- /dev/null
+++ b/examples++-3d/sphere6.edp
@@ -0,0 +1,33 @@
+load "msh3"
+load "medit" 
+real sqrt2=sqrt(2.);
+real onesqrt2=sqrt2/2.;
+
+mesh TS= square(10,10);
+TS=adaptmesh(TS,sqrt(1+x*x+y*y),err=0.003,periodic=[[4,y],[1,x],[2,y],[3,x]]);
+TS=adaptmesh(TS,sqrt(1+x*x+y*y),err=0.003,periodic=[[4,y],[1,x],[2,y],[3,x]]);
+TS=TS+movemesh(TS,[-x,y])+movemesh(TS,[x,-y])+movemesh(TS,[-x,-y]);//  build symetrique mesh
+plot(TS,wait=1); 
+int orientation=1;
+func f = 1;
+int[int]  ref=[0,1]; 
+mesh3 Thx0 = movemesh23(TS,transfo=[-f,x,y],orientation=-orientation,label=ref);
+mesh3 Thx1 = movemesh23(TS,transfo=[+f,x,y],orientation=+orientation,label=ref);
+mesh3 Thy0 = movemesh23(TS,transfo=[x,-f,y],orientation=+orientation,label=ref);
+mesh3 Thy1 = movemesh23(TS,transfo=[x,+f,y],orientation=-orientation,label=ref);
+mesh3 Thz0 = movemesh23(TS,transfo=[x,y,-f],orientation=-orientation,label=ref);
+mesh3 Thz1 = movemesh23(TS,transfo=[x,y,+f],orientation=+orientation,label=ref);
+mesh3 Tcube= Thx0+Thx1+Thy0+Thy1+Thz0+Thz1;
+//savemesh(Tcube,"T.mesh");
+//exec("ffmedit T.mesh");
+medit("Tcube",Tcube);
+plot(Tcube,wait=1);
+func R = sqrt(x*x+y*y+z*z);
+mesh3 Th = movemesh3(Tcube,transfo=[x/R,y/R,z/R]);
+plot(Th,wait=1);
+//savemesh(Th,"T.mesh");
+//exec("ffmedit T.mesh");
+medit("Th",Th);
+
+// FFCS: testing 3d plots
+plot(Th);
diff --git a/examples++-3d/tetgencube.edp b/examples++-3d/tetgencube.edp
new file mode 100644
index 0000000..64109f5
--- /dev/null
+++ b/examples++-3d/tetgencube.edp
@@ -0,0 +1,79 @@
+// file tetgencube.edp
+load "msh3"
+load "tetgen"
+load "medit"
+
+real x0,x1,y0,y1;
+x0=1.; x1=2.; y0=0.; y1=2*pi;
+mesh Thsq1 = square(5,35,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+func ZZ1min = 0;
+func ZZ1max = 1.5;
+func XX1 = x;
+func YY1 = y;
+
+int[int] ref31h = [0,12];
+int[int] ref31b = [0,11];
+
+mesh3 Th31h = movemesh23(Thsq1,transfo=[XX1,YY1,ZZ1max],label=ref31h,orientation=1);
+mesh3 Th31b = movemesh23(Thsq1,transfo=[XX1,YY1,ZZ1min],label=ref31b,orientation=-1);   
+
+
+/////////////////////////////////
+x0=1.; x1=2.; y0=0.; y1=1.5;
+mesh Thsq2 = square(5,8,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+func ZZ2 = y;
+func XX2 = x;
+func YY2min = 0.;
+func YY2max = 2*pi;
+
+int[int] ref32h = [0,13];
+int[int] ref32b = [0,14];
+
+mesh3 Th32h = movemesh23(Thsq2,transfo=[XX2,YY2max,ZZ2],label=ref32h,orientation=-1);  
+mesh3 Th32b = movemesh23(Thsq2,transfo=[XX2,YY2min,ZZ2],label=ref32b,orientation=1);
+
+/////////////////////////////////
+x0=0.; x1=2*pi; y0=0.; y1=1.5;
+mesh Thsq3 = square(35,8,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+func XX3min = 1.;
+func XX3max = 2.;
+
+func YY3 = x;
+func ZZ3 = y;
+
+int[int] ref33h = [0,15];
+int[int] ref33b = [0,16];
+
+mesh3 Th33h = movemesh23(Thsq3,transfo=[XX3max,YY3,ZZ3],label=ref33h,orientation=1);  
+mesh3 Th33b = movemesh23(Thsq3,transfo=[XX3min,YY3,ZZ3],label=ref33b,orientation=-1); 
+
+////////////////////////////////
+mesh3 Th33 = Th31h+Th31b+Th32h+Th32b+Th33h+Th33b; // "gluing" surface meshs to obtain the surface of cube
+//medit("glumesh",Th33);
+savemesh(Th33,"Th33.mesh");
+
+// build a mesh of a axis parallel box with TetGen
+//real[int] domaine = [1.5,pi,0.75,145,0.001];
+//mesh3 Thfinal = tetg(Th33,switch="pqaAAYYQ",nbofregions=1,regionlist=domaine);    // Tetrahelize the interior of the cube with tetgen
+//medit("tetg",Thfinal);
+//savemesh(Thfinal,"Thfinal.mesh");
+
+
+// build a mesh of a half cylindrical shell of interior radius 1. and exterior radius 2 and heigh 1.5
+func mv2x = x*cos(y);
+func mv2y = x*sin(y);
+func mv2z = z;
+//mesh3 Thmv2 = movemesh3(Thfinal, transfo=[mv2x,mv2y,mv2z]);
+//savemesh(Thmv2,"halfcylindricalshell.mesh");
+//verbosity=2;
+mesh3 Thmv2surf = movemesh(Th33,[mv2x,mv2y,mv2z], facemerge=0);
+medit("maillagesurf",Thmv2surf,wait=1);
+//savemesh(Thmv2surf,"maillagesurfacecylindre.mesh");
+//medit("maillageplein",Thmv2);
+
+// FFCS: testing 3d plots
+plot(Thmv2surf);
+
+
diff --git a/examples++-3d/tetgenholeregion.edp b/examples++-3d/tetgenholeregion.edp
new file mode 100755
index 0000000..e9798d8
--- /dev/null
+++ b/examples++-3d/tetgenholeregion.edp
@@ -0,0 +1,95 @@
+// file tetgenholeregion.edp
+load "msh3"
+load "tetgen"
+load "medit"
+//verbosity=2;
+
+// Test 1
+
+mesh Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},\frac{-pi}{2}[\times]0,2\pi[ $
+//  a parametrization of a sphere 
+func f1 =cos(x)*cos(y);
+func f2 =cos(x)*sin(y);
+func f3 = sin(x);
+//  partiel derivative of the parametrization DF
+func f1x=sin(x)*cos(y);   
+func f1y=-cos(x)*sin(y);
+func f2x=-sin(x)*sin(y);
+func f2y=cos(x)*cos(y);
+func f3x=cos(x);
+func f3y=0;
+// $  M = DF^t DF $
+func m11=f1x^2+f2x^2+f3x^2;
+func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+func m22=f1y^2+f2y^2+f3y^2;
+
+func perio=[[4,y],[2,y],[1,x],[3,x]];  
+real hh=0.1;
+real vv= 1/square(hh);
+verbosity=2;
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+//plot(Th,wait=1);
+medit("squaremesh",Th,wait=1);
+plot(Th); // FFCS: testing 3d plots
+verbosity=2;
+
+// construction of the surface of spheres
+real Rmin  = 1.;
+func f1min = Rmin*f1;
+func f2min = Rmin*f2;
+func f3min = Rmin*f3;
+
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+mesh3 Th3sph=movemesh23(Th,transfo=[f1min,f2min,f3min],orientation=-1);
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+savemesh(Th3sph,"sphereR1.mesh");
+medit("sphereR1",wait=1,Th3sph);
+plot(Th3sph); // FFCS: testing 3d plots
+real Rmax  = 2.;
+func f1max = Rmax*f1;
+func f2max = Rmax*f2;
+func f3max = Rmax*f3;
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+mesh3 Th3sph2=movemesh23(Th,transfo=[f1max,f2max,f3max],orientation=1);
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+savemesh(Th3sph2,"sphereR2.mesh");
+cout << "addition" << endl;
+mesh3 Th3=Th3sph+Th3sph2;
+savemesh(Th3,"sphereAdd.mesh");
+medit("sphereSurfaceAdd",wait=1,Th3);
+plot(Th3); // FFCS: testing 3d plots
+
+
+real[int] domain2 = [1.5,0.,0.,145,0.001,0.5,0.,0.,18,0.01];
+cout << "==============================" << endl;
+cout << " tetgen call without hole " << endl;
+cout << "==============================" << endl;
+mesh3 Th3fin=tetg(Th3,switch="paAAYYCCV",nbofregions=2,regionlist=domain2);
+cout << "=============================" << endl;
+cout << "finish: tetgen call without hole" << endl;
+cout << "=============================" << endl;
+savemesh(Th3fin,"spherewithtworegion.mesh"); 
+medit("spherewithtworegion",wait=1,Th3fin);
+plot(Th3fin); // FFCS: testing 3d plots
+
+real[int] hole = [0.,0.,0.];
+real[int] domain = [1.5,0.,0.,53,0.001];
+cout << "=============================" << endl;
+cout << "  tetgen call with hole   " << endl;
+cout << "=============================" << endl;
+mesh3 Th3finhole=tetg(Th3,switch="paAAYCCV",nbofholes=1,holelist=hole,nbofregions=1,regionlist=domain);
+cout << "=============================" << endl;
+cout << "finish: tetgen call with hole   " << endl;
+cout << "=============================" << endl;
+savemesh(Th3finhole,"spherewithahole.mesh"); 
+medit("spherewithahole",wait=1,Th3finhole);
+plot(Th3finhole); // FFCS: testing 3d plots
+
+
+
+
diff --git a/examples++-bug/FE0.edp b/examples++-bug/FE0.edp
new file mode 100644
index 0000000..c43f6af
--- /dev/null
+++ b/examples++-bug/FE0.edp
@@ -0,0 +1,25 @@
+{//  example with no mesh .. 
+mesh Th,Th1; //  no mesh
+
+fespace Vh(Th,P2); 
+Vh u,v; // ok 
+varf a(u,v) = int2d(Th1)(u*v) + int2d(Th)(v) +on(1,u=1);
+matrix A=a(Vh,Vh); 
+real[int] b=a(0,Vh);
+problem PPP(u,v) = int2d(Th)(u*v) + int2d(Th)(v) +on(1,u=1); 
+Th=square(1,1);
+u=x;
+}
+
+{
+load "msh3"
+mesh3 Th; //  no mesh
+fespace Vh(Th,P2); 
+Vh u,v; // ok 
+varf a(u,v) = int2d(Th)(u*v) + int2d(Th)(v) +on(1,u=1);
+matrix A=a(Vh,Vh); 
+real[int] b=a(0,Vh);
+problem PPP(u,v) = int2d(Th)(u*v) + int2d(Th)(v) +on(1,u=1); 
+Th=buildlayers(square(2,2),3);
+u=x;
+}
diff --git a/examples++-bug/Makefile.am b/examples++-bug/Makefile.am
new file mode 100644
index 0000000..05eb3d3
--- /dev/null
+++ b/examples++-bug/Makefile.am
@@ -0,0 +1,3 @@
+# $Id$
+
+EXTRA_DIST=*.edp
diff --git a/examples++-bug/SegmentationFault.edp b/examples++-bug/SegmentationFault.edp
new file mode 100755
index 0000000..dcebc62
--- /dev/null
+++ b/examples++-bug/SegmentationFault.edp
@@ -0,0 +1,89 @@
+
+////////////////////////////////////
+// Optimisation d'une 'grue'         //
+// � volume constant              //
+// avec un maillage sous-jacent   //
+// qu'on adpate a x^2 et y ^2 mais avec une
+// erreur constante //
+// plante de temps a autre (depend de niter !!!)
+////////////////////////////////////
+// Nom du fichier de sauvegarde
+string sauve="grue";
+
+// nombre d'it�rations
+int niter=1;
+
+//nombre de sauvegardes du maillage (<niter)
+int nsave=20;
+
+//coefficient d'exag�ration de la d�formation
+real exa=1;
+
+//pas
+real pas=0.01;
+
+//pr�cision du calcul
+real errcalc=0.001;//
+
+//finesse du maillage de structure
+real errground=0.01;
+
+//initialisation du compteur des sauvergardes
+int nsaved=0;
+
+//compliance
+real compliance;
+
+//fonction d�finissant la zone � optimiser (=1 sur la fronti�re optimisable, =0 sinon)
+func cutx =(y>1)*(x<4);
+func cuty =(y>1)*(x<4);
+
+//d�finition des bords de la forme
+//label =
+// 1:Condition de Dirichlet
+// 2:Condition Libre
+// 3:Condition de Neuman non nulles
+
+border a1(t=8,9) {x=5; y=t;label=3;}; // logement de la charge
+border b(t=5,0)  {x=t; y=9;label=2;}; // haut de la grue
+border c1(t=1.5,5) {x=t; y=8;label=2;}; //bras de la grue
+border d2(t=9,0) {x=-0.5+0.5/9*t; y=t;label=2;}; //cote gauche de la grue
+border d1(t=0,8) {x=0.5+t/8; y=t;label=2;} //cote droit de la grue
+border e(t=-0.5,0.5) {x=t; y=0;label=1;}; //base de la grue
+
+// forces appliqu�es 
+func g1=0; 
+func g2=-1;
+
+// coefficients de Young et de Lam�
+real lambda=12;
+real mu=6;
+
+
+// coefficients de Lam� du mat�riau
+cout <<"lambda,mu ="<<lambda<<","<<mu <<endl; 
+
+// construction du maillage de structure de la forme
+mesh Shground= buildmesh(e(5)+d1(20)+c1(10)+a1(5)+b(25)+d2(20));
+mesh Sh=Shground;
+
+fespace Vh(Sh,[P1,P1]);
+Vh [uu,vv],[w,s];
+
+// Calcul du d�placement de la structure
+problem elasticite([uu,vv],[w,s],solver=CG,eps=1.0e-6) =
+    int2d(Sh)(
+               2*mu*(dx(uu)*dx(w)+dy(vv)*dy(s)+((dx(vv)+dy(uu))*(dx(s)+dy(w)))/2)
+              +lambda*(dx(uu)+dy(vv))*(dx(w)+dy(s))
+	)
+    + int1d(Sh,3) (g1*w+g2*s)	
+    +on(1,uu=0,vv=0)
+;
+
+elasticite;
+
+cout << "adaptation"<<endl;
+Sh = adaptmesh  (Sh,[uu,vv],err=errcalc);
+plot(Sh,wait=1);
+
+elasticite;//Segmentation Fault !!!
diff --git a/examples++-bug/aaa.edp b/examples++-bug/aaa.edp
new file mode 100644
index 0000000..f4e81c1
--- /dev/null
+++ b/examples++-bug/aaa.edp
@@ -0,0 +1,108 @@
+// remark: the sign of p is correct 
+bool classique=0;
+
+real s0=clock();
+mesh Th=square(10,10);
+fespace Vh2(Th,P2);
+fespace Vh(Th,P1);
+fespace Wh(Th,[P2,P2,P1]);
+Vh2 u2,v2,up1,up2;
+Vh2 u1,v1; 
+Vh  u1x=0,u1y,u2x,u2y, vv;
+
+real reylnods=1000;
+//cout << " Enter the reynolds number :"; cin >> reylnods;
+assert(reylnods>1 && reylnods < 100000); 
+up1=0;
+up2=0; 
+func g=(x)*(1-x)*4; 
+Vh p=0,q;
+real alpha=0;
+real  nu=1;
+int i=0,iter=0;
+real dt=0;
+
+real sig = 2*classique-1;
+
+varf vNS([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2)
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +        dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001)
+            - p*dx(v1) - p*dy(v2)
+            - dx(u1)*q - dy(u2)*q
+           )
+  + int2d(Th) ( sig*(-alpha*convect([up1,up2],-dt,up1)*v1 -alpha*convect([up1,up2],-dt,up2)*v2 ) )
+  + on(3,u1=g,u2=0)
+  + on(1,2,4,u1=0,u2=0) ;
+
+
+solve NS ([u1,u2,p],[v1,v2,q],solver=UMFPACK,init=i,save="toto") =   vNS; 
+
+     cout << "-- n " << p[].n << " stokes " << endl;
+     cout << "-- u1 : " << u1[].min << " " << u1[].max << endl;
+     cout << "-- u2 : " << u2[].min << " " << u2[].max << endl;
+     cout << "-- p  : " << p[].min << " " << p[].max << endl;
+//plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="StokesP2P1.eps",value=1,wait=1);
+dt = 0.1;
+int nbiter = 2;
+real coefdt = 0.25^(1./nbiter);
+real coefcut = 0.25^(1./nbiter) , cut=0.01;
+real tol=0.5,coeftol = 0.25^(1./nbiter);
+nu=1./reylnods;   
+Wh [uu1,uu2,pp];
+Wh [vv1,vv2,qq];
+Wh [f1,f2,fp];
+for (iter=1;iter<=nbiter;iter++)
+{
+  cout << " dt = " << dt << " ------------------------ sig ="<< sig  << endl;
+  alpha=1/dt;
+  for (i=0;i<=1;i++)
+    {
+      up1=u1;
+      up2=u2;     
+      matrix A=vNS(Wh,Wh,solver=UMFPACK);
+      //     set(A,solver=UMFPACK); // set a solver 	
+      verbosity=3;
+      if(classique) {
+	//NS;
+	solve NS1 ([uu1,uu2,pp],[vv1,vv2,qq],solver=UMFPACK,init=i,save="toto") =   vNS; 	
+      }
+      else {
+	f1[] = vNS(0,Wh);
+	{
+	  ofstream tt("tt.matrix");
+	  tt << A << endl;
+	}
+	{
+	  ofstream tt("tt.b");
+	  tt << f1[]  << endl;
+	}
+	uu1[]  = A^-1*f1[];
+      }
+      verbosity=1;
+      u1=uu1;
+      u2=uu2;
+      p = pp;
+      
+      cout << "-- n " << p[].n << endl;
+      cout << "-- u1 : " << u1[].min << " " << u1[].max << endl;
+      cout << "-- u2 : " << u2[].min << " " << u2[].max << endl;
+      cout << "-- p  : " << p[].min << " " << p[].max << endl;
+      
+      if ( !(i % 10)) 
+	plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="plotNS_"+iter+"_"+i+".eps");  
+      cout << "CPU " << clock()-s0 << "s " << endl;     
+    } 
+  
+  if (iter>= nbiter) break;
+ 
+  Th=adaptmesh(Th,[dx(u1),dy(u1),dx(u1),dy(u2)],
+              abserror=0,cutoff=cut,err=tol, inquire=0,ratio=1.5,hmin=1./1000);
+  plot(Th,ps="ThNS.eps");
+  dt = dt*coefdt;
+  tol = tol *coeftol;
+  cut = cut *coefcut;
+}
+cout << "CPU " << clock()-s0 << "s " << endl;     
diff --git a/examples++-bug/bug-arg-string.edp b/examples++-bug/bug-arg-string.edp
new file mode 100644
index 0000000..9f4dbfa
--- /dev/null
+++ b/examples++-bug/bug-arg-string.edp
@@ -0,0 +1,31 @@
+//  bug string macro parameter   version < 1.41
+// bug in string parameter version before <2.5
+// -----------------
+ macro tyty(uu) uu//  
+cout << tyty("toto") << endl;
+
+// other bug   un func parameter  no correct 
+
+  func string   write(string  fn,real[int] & u)
+    {
+      cout <<"write :   " <<  fn << " u = "<<  u << endl;  //  delete 2 times before version 2.5 
+      return fn; 
+    }
+
+  func string   write1(string  fn,real[int] & u)
+    {
+      cout << "write 1 " << fn << " u = " << u << endl;   
+      string toto=fn; ;
+      return toto+"dfsdf"; 
+    }
+
+ real[int] u(3);
+ u=1;
+
+string tt=tyty("toto1"+1+" -- 77");
+
+string t1="0123456789";// write(tt,u);
+
+string t2=  write1(t1,u)+write1(tt,u);
+
+cout << " t2 = " << t2 << endl;
\ No newline at end of file
diff --git a/examples++-bug/bugborder.edp b/examples++-bug/bugborder.edp
new file mode 100644
index 0000000..25a32a9
--- /dev/null
+++ b/examples++-bug/bugborder.edp
@@ -0,0 +1,40 @@
+
+verbosity=0;
+real x0=0.0, x1=1.5;
+real y0=0.0, y1=2.0;
+real xx0=0.5, xx1=1.;
+real yy0=0.5, yy1=1.;
+int acc,ref, i;
+real sH;
+ref=10;
+
+border a( t= x0,x1){ x= t ; y= y0; label=1; };
+border b( t= y0,y1){ x= x0; y= t ; label=2; };
+border c( t= x0,x1){ x= t ; y= y1; label=3; };
+border d( t= y0,y1){ x= x1; y= t ; label=4; };
+border aa( t= xx0,xx1){ x= t ; y= yy0; label=1; };
+border bb( t= yy0,yy1){ x= xx0; y= t ; label=2; };
+border cc( t= xx0,xx1){ x= t ; y= yy1; label=3; };
+border dd( t= yy0,yy1){ x= xx1; y= t ; label=4; };
+
+//cout << "enter accuracy = ";
+//cin >> acc;
+acc=0;
+// Creation des maillages grossier et fin
+
+//mesh TH=square(ref,ref,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+mesh TH = buildmesh( a(10) + b(-10) + c(-10) + d(+10)
+                    +aa(-10) + bb(+10) + cc(+10) + dd(-10) );
+plot(TH,wait=1);
+end;
+
+{ //    hole 
+real pi=4.0*atan(1);
+border a(t=0,2*pi){ x=cos(t); y=sin(t);label=1;};
+border b(t=0,2*pi){ x=0.3+0.3*cos(t); y=0.3*sin(t);label=2;};
+mesh Thwithouthole= buildmesh(a(50)+b(+30));
+mesh Thwithhole   = buildmesh(a(50)+b(-30));
+plot(Thwithouthole,wait=1,ps="Thwithouthole.eps");
+plot(Thwithhole,wait=1,ps="Thwithhole.eps");
+}
\ No newline at end of file
diff --git a/examples++-bug/bugf.edp b/examples++-bug/bugf.edp
new file mode 100644
index 0000000..faaa3b2
--- /dev/null
+++ b/examples++-bug/bugf.edp
@@ -0,0 +1,14 @@
+ // routine
+// bug before  version 1.27 pb passage d'argument
+func int myfunction(real  a1)
+{
+   int i=a1*a1/1;
+   return i;
+}; 
+func real myfunction(real a,real b)
+{
+   real z =myfunction(a)+b;
+   return z;
+};
+// appele 
+cout << myfunction(1.0,3.) << " " << myfunction(1,3)  << endl;
diff --git a/examples++-bug/bugifexp.edp b/examples++-bug/bugifexp.edp
new file mode 100644
index 0000000..5f6ad6c
--- /dev/null
+++ b/examples++-bug/bugifexp.edp
@@ -0,0 +1,4 @@
+mesh Th=square(10,10);
+fespace Vh(Th,P1);
+// bug due  to optimisation process .. HARD ....  FH 
+Vh u = y ? 1./y : x;
\ No newline at end of file
diff --git a/examples++-bug/bugv1.18.edp b/examples++-bug/bugv1.18.edp
new file mode 100644
index 0000000..dd4bb57
--- /dev/null
+++ b/examples++-bug/bugv1.18.edp
@@ -0,0 +1,8 @@
+// bug correct in version 1.19
+cout << ( 10. < 2 ) << endl;
+cout << ( 10. < 2. ) << endl;
+mesh Th=square(5,5);
+fespace Xh(Th,P2);
+Xh v;
+v=label;
+plot(v,value=1,wait=1);
diff --git a/examples++-bug/fe-vect.edp b/examples++-bug/fe-vect.edp
new file mode 100644
index 0000000..f61c2de
--- /dev/null
+++ b/examples++-bug/fe-vect.edp
@@ -0,0 +1,15 @@
+mesh Th = square(10,10); 
+fespace Wh(Th,[P2,P2]);	// R2->R2
+Wh [F1,F2]; //def de l'inconnu et des fonct tests
+
+F1 = 1;
+// il y a un bug ici car dans un element fini vectoriel
+// il est impossible defini juste une composante
+//  il faut faire:
+
+cout << F1(0.5, 0.6) << endl;
+cout << F2(0.5, 0.6) << endl;
+cout << F1(0.5, 0.6);
+[F1,F2]=[1,2]; 
+cout << " -- F1 " <<  F1(0.5, 0.6) << endl;
+cout << " -- F2 " << F2(0.5, 0.6) << endl;
\ No newline at end of file
diff --git a/examples++-bug/func.edp b/examples++-bug/func.edp
new file mode 100644
index 0000000..c837448
--- /dev/null
+++ b/examples++-bug/func.edp
@@ -0,0 +1,10 @@
+//  bug --
+mesh Th=square(1,1);
+fespace Vh(Th,P1);
+Vh u;
+func real  ff( Vh & u) { return u;} 
+func real xx(real x){ return x;}
+func real yy(func real(real xx)) { return xx(1);}
+ 
+func f=1;
+f=2; 
\ No newline at end of file
diff --git a/examples++-bug/zArithmetic_bug1.edp b/examples++-bug/zArithmetic_bug1.edp
new file mode 100644
index 0000000..724ecc2
--- /dev/null
+++ b/examples++-bug/zArithmetic_bug1.edp
@@ -0,0 +1,39 @@
+// +=====================================================================+
+// | Un bug en arithmetique complexe.                                    |
+// +---------------------------------------------------------------------+
+// | 01/09/02 : Les tableaux de complexes ne sont pas dispos             |
+// | 11/09/03, V1.34                                                     |
+// |   variable du contexte sont ecrasees c'est le cas de j              |
+// |                                                                     |
+// +=====================================================================+
+
+
+   complex z1, z2, j    ;
+   real    ReZ, ImZ ;
+
+   j = 0 + 1i ;
+   cout << "j = " << j <<" attendu : i" << endl ;
+
+   cout << "trace 1 de j = " << j  << endl ;
+   ReZ = 4.5 ; ImZ = 6.7 ; 
+   cout << "ReZ = " << ReZ << " attendu : 4.5 " << endl ;
+   cout << "ImZ = " << ImZ << " attendu : 6.7 " << endl ;
+   cout << "trace 2 de j = " << j  << endl ;
+   cout << "Voila, j est ecrase par 0 + (ReZ) i !" << endl ;
+   
+   cout << endl ;
+   cout << "Le meme Pb pour les reels ? " << endl ;
+
+   
+   real r1, r2, jR   ;
+
+   jR = 2 ;
+   cout << "jR = " << jR <<" attendu : 2" << endl ;
+
+   cout << "trace 1 de jR = " << jR  << endl ;
+   ReZ = 4.5 ; ImZ = 6.7 ; 
+   cout << "ReZ = " << ReZ << " attendu : 4.5 " << endl ;
+   cout << "ImZ = " << ImZ << " attendu : 6.7 " << endl ;
+   cout << "trace 2 de jR = " << jR  << endl ;
+   cout << "NON jR n'est pas ecrase" << endl ;
+   cout << endl ;
diff --git a/examples++-chapt3/BlackScholes2D.edp b/examples++-chapt3/BlackScholes2D.edp
new file mode 100755
index 0000000..4399c65
--- /dev/null
+++ b/examples++-chapt3/BlackScholes2D.edp
@@ -0,0 +1,29 @@
+// file BlackScholes2D.edp
+int m=30,L=80,LL=80, j=100;
+real sigmax=0.3, sigmay=0.3, rho=0.3, r=0.05, K=40, dt=0.01;
+mesh th=square(m,m,[L*x,LL*y]);
+fespace Vh(th,P1);
+
+Vh u=max(K-max(x,y),0.);
+Vh xveloc, yveloc, v,uold;
+
+for (int n=0; n*dt <= 1.0; n++)
+{
+  if(j>20)  { th = adaptmesh(th,u,verbosity=1,abserror=1,nbjacoby=2,
+              err=0.001, nbvx=5000, omega=1.8, ratio=1.8, nbsmooth=3,
+              splitpbedge=1, maxsubdiv=5,rescaling=1) ;
+     j=0;
+     xveloc = -x*r+x*sigmax^2+x*rho*sigmax*sigmay/2;
+     yveloc = -y*r+y*sigmay^2+y*rho*sigmax*sigmay/2;
+     u=u;
+    };
+  uold=u;
+  solve eq1(u,v,init=j,solver=LU) = int2d(th)(  u*v*(r+1/dt)
+    + dx(u)*dx(v)*(x*sigmax)^2/2 + dy(u)*dy(v)*(y*sigmay)^2/2
+    + dy(u)*dx(v)*rho*sigmax*sigmay*x*y/2 + dx(u)*dy(v)*rho*sigmax*sigmay*x*y/2)
+    + int2d(th)( -v*convect([xveloc,yveloc],dt,uold)/dt)+ on(2,3,u=0);
+
+  j=j+1;
+};
+plot(u,wait=1,value=1);
+plot(th,wait=1);
diff --git a/examples++-chapt3/Makefile.am b/examples++-chapt3/Makefile.am
new file mode 100644
index 0000000..ca1be28
--- /dev/null
+++ b/examples++-chapt3/Makefile.am
@@ -0,0 +1,35 @@
+# $Id$
+
+all-local: all.edp regtests.edp freefem++.pref
+TESTS=BlackScholes2D.edp NSNewton.edp NSprojection.edp condensor.edp convects.edp heatex.edp lame.edp membrane.edp membranerror.edp muwave.edp optimcontrol.edp potential.edp schwarz.edp sound.edp stokes.edp test1.edp testbed.edp thermal.edp thermic.edp
+# if .. no arpack ... 
+XFAIL_TESTS=sound.edp
+
+EXTRA_DIST=*.edp  all.edp regtests.edp regtests.m4 ref.edp
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPP) FLAGS_FFPP=-nw
+
+all.edp:
+	(echo "NoUseOfWait=true;int verbosityy=verbosity;"; \
+	for i in *`ls *.edp|grep -v -E '^(all|regtests|makeref|ref)\.edp$$'` ; do  \
+		echo ' cout << "--------- file : '$$i' --------------------------------------------------------" << endl;' ;\
+		echo "verbosity=verbosityy;" ; \
+		echo \{ include \"$$i\"\;\}\; ;\
+		echo ' cout << "------------------------------------------------------------------------------ " << endl;' ;\
+	done) > $@
+
+# To create a new set of reference values in "ref.edp"
+Ref: makeref.edp
+	../src/nw/FreeFem++-nw makeref.edp
+
+makeref.edp: regtests.m4 ../regtests.m4
+	m4 regtests.m4 > makeref.edp
+
+# To check the scripts against their reference values
+regtests.edp: regtests.m4 ../regtests.m4
+	m4 -DASSERT regtests.m4 > regtests.edp
+freefem++.pref:
+	echo loadpath = \"../examples++-load/\" >freefem++.pref
+	echo loadpath += \"./\" >>freefem++.pref
+
+FORCE:
\ No newline at end of file
diff --git a/examples++-chapt3/NSNewton.edp b/examples++-chapt3/NSNewton.edp
new file mode 100644
index 0000000..d4c7772
--- /dev/null
+++ b/examples++-chapt3/NSNewton.edp
@@ -0,0 +1,88 @@
+// Author: F. Hecht  
+// jan 2012 Stationnary imcompressible Navier Stokes Equation with Newton method.
+//  a round a 3d Cylinder 
+// build the  Mesh
+real R = 5,L=15;
+border cc(t=0,2*pi){ x=cos(t)/2;y=sin(t)/2;label=1;}
+border ce(t=pi/2,3*pi/2) { x=cos(t)*R;y=sin(t)*R;label=1;}
+border beb(tt=0,1) { real t=tt^1.2; x= t*L; y= -R; label = 1;}
+border beu(tt=1,0) { real t=tt^1.2; x= t*L; y= R; label = 1;}
+border beo(t=-R,R) {  x= L; y= t; label = 0;}
+border bei(t=-R/4,R/4) {  x= L/2; y= t; label = 0;}
+mesh Th=buildmesh(cc(-50)+ce(30)+beb(20)+beu(20)+beo(10)+bei(10));
+plot(Th);
+
+// bounding box for the plot 
+func bb=[[-1,-2],[4,2]];
+
+//  operator 
+macro Grad(u1,u2) [ dx(u1),dy(u1), dx(u2),dy(u2)]// 
+macro UgradV(u1,u2,v1,v2) [ [u1,u2]'*[dx(v1),dy(v1)] , [u1,u2]'*[dx(v2),dy(v2)] ]// 
+macro div(u1,u2)  (dx(u1)+dy(u2))//
+
+//  FE Space 
+fespace Xh(Th,P2);fespace Mh(Th,P1);
+Xh u1,u2,v1,v2,du1,du2,u1p,u2p;
+Mh p,q,dp,pp;
+
+// intial guess with B.C. 
+u1 = ( x^2+y^2) > 2;
+u2=0;
+
+//  Physical parameter 
+real nu= 1./50, nufinal=1/200. ,cnu=0.5; 
+
+// stop test for Newton 
+real eps=1e-6;
+
+verbosity=0;
+while(1)  //  Loop on vicosity 
+{   int n;
+	real err=0;	
+	for( n=0;n< 15;n++) // Newton Loop 
+	{
+	   solve Oseen([du1,du2,dp],[v1,v2,q]) =
+		   int2d(Th) (  nu*(Grad(du1,du2)'*Grad(v1,v2) )
+		              + UgradV(du1,du2, u1, u2)'*[v1,v2]
+		              + UgradV( u1, u2,du1,du2)'*[v1,v2]
+		              - div(du1,du2)*q - div(v1,v2)*dp 
+		              - 1e-8*dp*q // stabilization term 
+		             )
+		- int2d(Th) (  nu*(Grad(u1,u2)'*Grad(v1,v2) )
+		              + UgradV(u1,u2, u1, u2)'*[v1,v2]
+		              - div(u1,u2)*q - div(v1,v2)*p 
+		              - 1e-8*p*q 
+		             )
+	    + on(1,du1=0,du2=0)
+	    ;
+	    u1[] -= du1[];
+	    u2[] -= du2[];
+	    p[]  -= dp[];
+	    real Lu1=u1[].linfty,  Lu2 = u2[].linfty , Lp = p[].linfty;
+	    err= du1[].linfty/Lu1 + du2[].linfty/Lu2 + dp[].linfty/Lp;
+	    
+	    cout << n << " err = " << err << " " << eps << " rey  =" << 1./nu << endl;
+	    if(err < eps) break; // converge 
+	    if( n>3 && err > 10.) break; //  Blowup ????           
+	}
+ if(err < eps)  // if converge  decrease nu (more difficulte)
+ {
+   plot([u1,u2],p,wait=1,cmm=" rey = " + 1./nu , coef=0.3,bb=bb);
+   if( nu == nufinal) break; 
+   if( n < 4) cnu=cnu^1.5; // fast converge => change faster 
+   nu = max(nufinal, nu* cnu); // new vicosity 
+   u1p=u1;  u2p=u2;  pp=p; //  save correct solution ...
+ }
+ else {  // if blowup,  increase nu (more simple)
+   assert(cnu< 0.95); // final blowup ...  
+   nu = nu/cnu; //  get previous value of viscosity 
+   cnu= cnu^(1./1.5); // no conv. => change lower 
+   nu = nu* cnu;  // new vicosity
+   cout << " restart nu = " << nu << " Rey= "<< 1./nu << "  (cnu = " << cnu << " ) \n";
+   // restore correct solution ..
+   u1=u1p;
+   u2=u2p;
+   p=pp; 
+ }   
+}
+
diff --git a/examples++-chapt3/NSprojection-Opt.edp b/examples++-chapt3/NSprojection-Opt.edp
new file mode 100755
index 0000000..d9de1bb
--- /dev/null
+++ b/examples++-chapt3/NSprojection-Opt.edp
@@ -0,0 +1,148 @@
+// file NSprojection.edp
+// Version july 2014, 
+// FH. Change B.C on u on outpout , more simple .. 
+// ............
+verbosity=0;
+border a0(t=1,0){ x=-2;      y=t;      label=1;}// inlet ..
+border a1(t=-2,0){ x=t;    y=0;        label=2;}
+border a2(t=0,-0.5){ x=0;      y=t;       label=2;}
+border a3(t=0,1){ x=18*t^1.2;  y=-0.5;       label=2;}
+border a4(t=-0.5,1){ x=18;     y=t;   label=3;}// outlet 
+border a5(t=1,0){ x=-2+20*t; y=1;        label=4;}
+int n=1;
+mesh Th= buildmesh(a0(3*n)+a1(20*n)+a2(10*n)+a3(150*n)+a4(5*n)+a5(100*n));
+
+plot(Th);
+fespace Vh(Th,P1);
+fespace Wh(Th,[P1,P1]);
+real nu = 0.0025, dt = 0.2; // Reynolds=200
+
+Vh w,u = 0, v =0, p = 0, q=0;
+Vh uold,vold,pold; 
+ // def of Matrix dtMx and dtMy
+ matrix M1,Mdx,Mdy,AAu,AAv,AAp;
+ real[int] rhsu(Vh.ndof), rhsv(Vh.ndof), rhsp(Vh.ndof);
+ real[int] rhsu0(Vh.ndof), rhsv0(Vh.ndof), rhsp0(Vh.ndof);
+macro  BuildMat()
+ { /* for memory managenemt */
+   w=w;
+   u=u;
+   v=v;
+   p=p;
+   q=q; 
+   uold=0;
+   vold=0;
+   pold=0;
+   
+   varf vM(unused,v) = int2d(Th)(v) ;
+   varf vdx(u,v) = int2d(Th)(v*dx(u)) ;
+   varf vdy(u,v) = int2d(Th)(v*dy(u)) ;
+   varf pb4u(u,w)
+        =int2d(Th)(u*w/dt +nu*(dx(u)*dx(w)+dy(u)*dy(w)))
+          + on(1,u = 4*y*(1-y)) + on(2,4,u = 0) 
+        ;
+   varf pb4v(v,w)
+        = int2d(Th)(v*w/dt +nu*(dx(v)*dx(w)+dy(v)*dy(w)))
+        +on(1,2,3,4,v = 0);
+   varf pb4p(q,w) = int2d(Th)(dx(q)*dx(w)+dy(q)*dy(w))
+     + on(3,q=0);
+   AAu = pb4u(Vh,Vh,solver=sparsesolver);
+   AAv = pb4v(Vh,Vh,solver=sparsesolver);
+   AAp = pb4p(Vh,Vh,solver=sparsesolver);
+  
+   rhsu.resize(Vh.ndof);
+   rhsv.resize(Vh.ndof);
+   rhsp.resize(Vh.ndof);
+   rhsu0.resize(Vh.ndof);
+   rhsv0.resize(Vh.ndof);
+   rhsp0.resize(Vh.ndof);
+  
+   
+   rhsu0 = pb4u(0,Vh);
+   rhsv0 = pb4v(0,Vh);
+   rhsp0 = pb4p(0,Vh);
+   real[int] Mlump = vM(0,Vh); 
+   real[int] one(Vh.ndof); one = 1;  
+   real[int] aM1 =  one ./ Mlump; 
+   M1 = aM1;
+   Mdx = vdx(Vh,Vh);
+   Mdy = vdy(Vh,Vh);
+ }
+ // 
+ 
+BuildMat
+
+real err=1, outflux=1;
+for(int n=0;n<300;n++)
+ {	
+  varf  cpb4u(u,w) = int2d(Th)((convect([uold,vold],-dt,uold)/dt)*w); 
+  varf  cpb4v(u,w) = int2d(Th)((convect([uold,vold],-dt,vold)/dt)*w); 
+  uold[] = u[];
+  vold[] = v[];
+  pold[]=p[];
+  p[]=-p[]; 
+  rhsu = rhsu0;
+  rhsv = rhsv0; 
+  rhsp = 0;
+  rhsu += Mdx*p[];
+  rhsv += Mdy*p[];
+  rhsu += cpb4u(0,Vh);
+  rhsv += cpb4v(0,Vh);
+  u[]= AAu^-1*rhsu;
+  v[]= AAv^-1*rhsv;
+  rhsp += Mdx*u[];
+  rhsp += Mdy*v[];
+  rhsp /= dt;
+  rhsp += rhsp0;
+  q[]= AAp^-1*rhsp;
+  p[] = pold[] -q[];  
+  
+  rhsu = Mdx*q[];
+  rhsv = Mdy*q[];
+  rhsu *= dt; 
+  rhsv *= dt; 
+  u[] += rhsu;
+  v[] += rhsv;
+  plot(u);
+  
+  
+/*  
+  solve pb4u(u,w,init=n,solver=CG,eps=epsu)
+        =int2d(Th)(u*w/dt +nu*(dx(u)*dx(w)+dy(u)*dy(w)))
+        -int2d(Th)((convect([uold,vold],-dt,uold)/dt-dx(p))*w)
+        + on(1,u = 4*y*(1-y)) + on(2,4,u = 0) 
+        ;
+  plot(u);
+
+  solve pb4v(v,w,init=n,solver=CG,eps=epsv)
+        = int2d(Th)(v*w/dt +nu*(dx(v)*dx(w)+dy(v)*dy(w)))
+        -int2d(Th)((convect([uold,vold],-dt,vold)/dt-dy(p))*w)
+        +on(1,2,3,4,v = 0);
+
+ solve pb4p(q,w,solver=CG,init=n,eps=epsp) = int2d(Th)(dx(q)*dx(w)+dy(q)*dy(w))
+    - int2d(Th)((dx(u)+ dy(v))*w/dt)+ on(3,q=0);
+
+ // to have absolute epsilon in CG algorithm. 
+  epsv = -abs(epsv);
+  epsu = -abs(epsu);
+  epsp = -abs(epsp);
+
+  p = pold-q;
+  u[] += dtM1x*q[];
+  v[] += dtM1y*q[];
+ */
+  
+  if(n%50==49){
+    Th = adaptmesh(Th,[u,v],q,err=0.04,nbvx=100000);
+    plot(Th, wait=true);
+    BuildMat // rebuild mat.   
+ }
+ 
+  err = sqrt(int2d(Th)(square(u-uold)+square(v-vold))/Th.area) ;
+  outflux = int1d(Th)( [u,v]'*[N.x,N.y]) ;
+  cout << " iter " << n << " Err L2 = " << err << " "<< " flux sortant = "<< outflux << endl; 
+  if(err < 1e-3) break;
+}
+assert(abs(outflux)< 2e-3); // verifaction ... 
+plot(p,wait=1,ps="NSprojP.eps");
+plot(u,wait=1,ps="NSprojU.eps");
diff --git a/examples++-chapt3/NSprojection.edp b/examples++-chapt3/NSprojection.edp
new file mode 100755
index 0000000..1256af8
--- /dev/null
+++ b/examples++-chapt3/NSprojection.edp
@@ -0,0 +1,87 @@
+// file NSprojection.edp
+// Version july 2014, 
+// FH. Change B.C on u on outpout , more simple .. 
+// ............
+verbosity=0;
+border a0(t=1,0){ x=-2;      y=t;      label=1;}// inlet ..
+border a1(t=-2,0){ x=t;    y=0;        label=2;}
+border a2(t=0,-0.5){ x=0;      y=t;       label=2;}
+border a3(t=0,1){ x=18*t^1.2;  y=-0.5;       label=2;}
+border a4(t=-0.5,1){ x=18;     y=t;   label=3;}// outlet 
+border a5(t=1,0){ x=-2+20*t; y=1;        label=4;}
+int n=1;
+mesh Th= buildmesh(a0(3*n)+a1(20*n)+a2(10*n)+a3(150*n)+a4(5*n)+a5(100*n));
+
+plot(Th);
+fespace Vh(Th,P1);
+
+real nu = 0.0025, dt = 0.2; // Reynolds=200
+
+Vh w,u = 0, v =0, p = 0, q=0;
+
+ real epsv = 1e-6, epsu = 1e-6, epsp = 1e-6;// Eps CG ..
+ // def of Matrix dtMx and dtMy
+ matrix dtM1x,dtM1y;
+ 
+macro  BuildMat()
+ { /* for memory managenemt */
+   varf vM(unused,v) = int2d(Th)(v) ;
+   varf vdx(u,v) = int2d(Th)(v*dx(u)*dt) ;
+   varf vdy(u,v) = int2d(Th)(v*dy(u)*dt) ;
+
+   real[int] Mlump = vM(0,Vh); 
+   real[int] one(Vh.ndof); one = 1;  
+   real[int] M1 =  one ./ Mlump; 
+   matrix dM1 = M1;
+   matrix Mdx = vdx(Vh,Vh);
+   matrix Mdy = vdy(Vh,Vh);
+   dtM1x = dM1*Mdx;
+   dtM1y = dM1*Mdy; 
+ }// 
+ 
+BuildMat
+
+real err=1, outflux=1;
+for(int n=0;n<300;n++)
+ {	
+  Vh uold = u,  vold = v, pold=p;
+  
+  solve pb4u(u,w,init=n,solver=CG,eps=epsu)
+        =int2d(Th)(u*w/dt +nu*(dx(u)*dx(w)+dy(u)*dy(w)))
+        -int2d(Th)((convect([uold,vold],-dt,uold)/dt-dx(p))*w)
+        + on(1,u = 4*y*(1-y)) + on(2,4,u = 0) 
+        ;
+  plot(u);
+
+  solve pb4v(v,w,init=n,solver=CG,eps=epsv)
+        = int2d(Th)(v*w/dt +nu*(dx(v)*dx(w)+dy(v)*dy(w)))
+        -int2d(Th)((convect([uold,vold],-dt,vold)/dt-dy(p))*w)
+        +on(1,2,3,4,v = 0);
+
+ solve pb4p(q,w,solver=CG,init=n,eps=epsp) = int2d(Th)(dx(q)*dx(w)+dy(q)*dy(w))
+    - int2d(Th)((dx(u)+ dy(v))*w/dt)+ on(3,q=0);
+
+ // to have absolute epsilon in CG algorithm. 
+  epsv = -abs(epsv);
+  epsu = -abs(epsu);
+  epsp = -abs(epsp);
+
+  p = pold-q;
+  u[] += dtM1x*q[];
+  v[] += dtM1y*q[];
+ 
+  
+  if(n%50==49){
+    Th = adaptmesh(Th,[u,v],q,err=0.04,nbvx=100000);
+    plot(Th, wait=true);
+    BuildMat // rebuild mat.   
+ }
+ 
+  err = sqrt(int2d(Th)(square(u-uold)+square(v-vold))/Th.area) ;
+  outflux = int1d(Th)( [u,v]'*[N.x,N.y]) ;
+  cout << " iter " << n << " Err L2 = " << err << " "<< " flux sortant = "<< outflux << endl; 
+  if(err < 1e-3) break;
+}
+assert(abs(outflux)< 2e-3); // verifaction ... 
+plot(p,wait=1,ps="NSprojP.eps");
+plot(u,wait=1,ps="NSprojU.eps");
diff --git a/examples++-chapt3/all.edp b/examples++-chapt3/all.edp
new file mode 100644
index 0000000..9228ebd
--- /dev/null
+++ b/examples++-chapt3/all.edp
@@ -0,0 +1,73 @@
+NoUseOfWait=true;int verbosityy=verbosity;
+ cout << "--------- file : BlackScholes2D.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "BlackScholes2D.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : NSprojection.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "NSprojection.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : condensor.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "condensor.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : convects.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "convects.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : heatex.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "heatex.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : lame.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "lame.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : membrane.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "membrane.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : membranerror.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "membranerror.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : muwave.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "muwave.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : optimcontrol.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "optimcontrol.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : potential.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "potential.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : schwarz.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "schwarz.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : sound.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "sound.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : stokes.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "stokes.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : test1.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "test1.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : testbed.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "testbed.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : thermal.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "thermal.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : thermic.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "thermic.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
diff --git a/examples++-chapt3/condensor.edp b/examples++-chapt3/condensor.edp
new file mode 100755
index 0000000..12c316a
--- /dev/null
+++ b/examples++-chapt3/condensor.edp
@@ -0,0 +1,34 @@
+// file condensor.edp
+
+int C1=99, C2=98; // could be anything
+border C0(t=0,2*pi){x=5*cos(t); y=5*sin(t);}
+
+border C11(t=0,1){ x=1+t;  y=3;      label=C1;}
+border C12(t=0,1){ x=2;    y=3-6*t;  label=C1;}
+border C13(t=0,1){ x=2-t;  y=-3;     label=C1;}
+border C14(t=0,1){ x=1;    y=-3+6*t; label=C1;}
+
+border C21(t=0,1){ x=-2+t; y=3;      label=C2;}
+border C22(t=0,1){ x=-1;   y=3-6*t;  label=C2;}
+border C23(t=0,1){ x=-1-t; y=-3;     label=C2;}
+border C24(t=1,0){ x=-2;   y=-3+6*t; label=C2;}
+
+mesh Th=buildmesh(   C0(50)
+                    +C11(5)+C12(20)+C13(5)+C14(20)
+                    +C21(5)+C22(20)+C23(5)+C24(-20));
+plot(Th,wait=1);
+
+fespace Vh(Th,P1); Vh u,v;
+
+solve a(u,v)= int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))
+                +on(C0,u=0)+on(C1,u=1)+on(C2,u=-1);
+plot(u,value=true, ps="condersor.eps");
+
+// savemesh(Th,"condensor.msh");
+/*
+mesh Sh=readmesh("condensor.msh");
+fespace Vsh(Sh,P1); Vsh us,vs;
+solve b(us,vs)= int2d(Sh)(dx(us)*dx(vs)+dy(us)*dy(vs))
+                +on(1,us=0)+on(99,us=1)+on(98,us=-1);
+plot(us,value=true);
+*/
diff --git a/examples++-chapt3/convects.edp b/examples++-chapt3/convects.edp
new file mode 100755
index 0000000..2533582
--- /dev/null
+++ b/examples++-chapt3/convects.edp
@@ -0,0 +1,52 @@
+// file convects.edp
+// Characteristics Galerkin
+border C(t=0, 2*pi) { x=cos(t);  y=sin(t); };
+mesh Th = buildmesh(C(100));
+fespace Uh(Th,P1);
+Uh cold, c = exp(-10*((x-0.3)^2 +(y-0.3)^2));
+
+real dt = 0.17,t=0;
+Uh u1 = y, u2 = -x;
+for (int m=0; m<2*pi/dt ; m++) {
+    t += dt;     cold=c;
+    c=convect([u1,u2],-dt,cold);
+    plot(c,cmm=" t="+t + ", min=" + c[].min + ", max=" +  c[].max);
+}
+// Now with Discontinuous Galerkin
+fespace Vh(Th,P1dc);
+
+Vh w, ccold, v1 = y, v2 = -x, cc = exp(-10*((x-0.3)^2 +(y-0.3)^2));
+real u, al=0.5;  dt = 0.05;
+
+macro n()(N.x*v1+N.y*v2) //
+
+problem  Adual(cc,w) = int2d(Th)((cc/dt+(v1*dx(cc)+v2*dy(cc)))*w)
+  + intalledges(Th)((1-nTonEdge)*w*(al*abs(n)-n/2)*jump(cc))
+//  - int1d(Th,C)((n(u)<0)*abs(n(u))*cc*w)  // unused because cc=0 on d(Omega)^-
+  - int2d(Th)(ccold*w/dt);
+
+for ( t=0; t< 2*pi ; t+=dt)
+{
+ ccold=cc; Adual;
+ plot(cc,fill=1,cmm="t="+t + ", min=" + cc[].min + ", max=" +  cc[].max);
+};
+real [int] viso=[-0.1,0,0.5,0.1,0.5,0.2,0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.65,0.7,0.75,0.8,0.9,1];
+plot(c,wait=1,fill=1,value=1,ps="convectCG.eps",viso=viso);
+plot(cc,wait=1,fill=1,value=1,ps="convectDG.eps",viso=viso);
+
+// the same DG very much faster
+varf aadual(cc,w) = int2d(Th)((cc/dt+(v1*dx(cc)+v2*dy(cc)))*w)
+        + intalledges(Th)((1-nTonEdge)*w*(al*abs(n)-n/2)*jump(cc));
+varf bbdual(ccold,w) =  - int2d(Th)(ccold*w/dt);
+matrix  AA= aadual(Vh,Vh);
+matrix BB = bbdual(Vh,Vh);
+set (AA,init=t,solver=UMFPACK);
+Vh rhs=0;
+for ( t=0; t< 2*pi ; t+=dt)
+{
+  ccold=cc;
+  rhs[] = BB* ccold[];
+  cc[] = AA^-1*rhs[];
+  plot(cc,fill=0,cmm="t="+t + ", min=" + cc[].min + ", max=" +  cc[].max);
+};
+plot(cc,wait=1,fill=1,value=1,ps="convectDG.eps",viso=viso);
diff --git a/examples++-chapt3/heatex.edp b/examples++-chapt3/heatex.edp
new file mode 100755
index 0000000..c6dde77
--- /dev/null
+++ b/examples++-chapt3/heatex.edp
@@ -0,0 +1,24 @@
+// file heatex.edp
+int C1=99, C2=98; // could be anything
+border C0(t=0,2*pi){x=5*cos(t); y=5*sin(t);}
+
+border C11(t=0,1){ x=1+t;  y=3;      label=C1;}
+border C12(t=0,1){ x=2;    y=3-6*t;  label=C1;}
+border C13(t=0,1){ x=2-t;  y=-3;     label=C1;}
+border C14(t=0,1){ x=1;    y=-3+6*t; label=C1;}
+
+border C21(t=0,1){ x=-2+t; y=3;      label=C2;}
+border C22(t=0,1){ x=-1;   y=3-6*t;  label=C2;}
+border C23(t=0,1){ x=-1-t; y=-3;     label=C2;}
+border C24(t=0,1){ x=-2;   y=-3+6*t; label=C2;}
+
+mesh Th=buildmesh(    C0(50)
+                    + C11(5)+C12(20)+C13(5)+C14(20)
+                    + C21(-5)+C22(-20)+C23(-5)+C24(-20));
+plot(Th,wait=1,ps="heatexTh.ps");
+
+fespace Vh(Th,P1); Vh u,v;
+Vh kappa=1+4*(x<-1)*(x>-2)*(y<3)*(y>-3);
+solve a(u,v)= int2d(Th)(kappa*(dx(u)*dx(v)+dy(u)*dy(v)))
+                +on(C0,u=20)+on(C1,u=100);
+plot(u,value=true,wait=1,fill=true);
diff --git a/examples++-chapt3/lame.edp b/examples++-chapt3/lame.edp
new file mode 100755
index 0000000..b53c7b4
--- /dev/null
+++ b/examples++-chapt3/lame.edp
@@ -0,0 +1,30 @@
+// file lame.edd
+mesh Th=square(10,10,[20*x,2*y-1]);
+fespace Vh(Th,P2);
+Vh u,v,uu,vv;
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2)  [dx(u1),dy(u2),(dy(u1)+dx(u2))/sqrt2] // EOM
+// remark the $1/\sqrt2$ in term (dy(u1)+dx(u2)) is because 
+// we want: 
+//  epsilon(u1,u2)'* epsilon(v1,v2) == $ \varepsilon(\bm{u}): varepsilon(\bm{v})$
+macro div(u,v) ( dx(u)+dy(v) ) // EOM
+
+
+real E = 21e5, nu = 0.28, mu= E/(2*(1+nu)); 
+real lambda = E*nu/((1+nu)*(1-2*nu)), f = -1; //  
+
+solve lame([u,v],[uu,vv])= int2d(Th)(  
+        lambda*div(u,v)*div(uu,vv)
+        +2.*mu*( epsilon(u,v)'*epsilon(uu,vv) ) )	
+        - int2d(Th)(f*vv) 
+        + on(4,u=0,v=0);
+real coef=100;
+plot([u,v],wait=1,ps="lamevect.eps",coef=coef);
+
+mesh th1 = movemesh(Th, [x+u*coef, y+v*coef]);
+ plot(th1,wait=1,ps="lamedeform.eps");
+real dxmin  = u[].min; 
+real dymin  = v[].min; 
+
+cout << " - dep.  max   x = "<< dxmin<< " y=" << dymin << endl; 
+cout << "   dep.  (20,0)  = " << u(20,0) << " " << v(20,0) << endl; 
diff --git a/examples++-chapt3/membrane.edp b/examples++-chapt3/membrane.edp
new file mode 100755
index 0000000..16a8f7e
--- /dev/null
+++ b/examples++-chapt3/membrane.edp
@@ -0,0 +1,28 @@
+// file membrane.edp
+real theta=4.*pi/3.;
+real a=2.,b=1.; // the length of the semimajor axis and  semiminor axis
+func z=x;
+
+border Gamma1(t=0,theta)    { x = a * cos(t); y = b*sin(t); }
+border Gamma2(t=theta,2*pi) { x = a * cos(t); y = b*sin(t); }
+mesh Th=buildmesh(Gamma1(100)+Gamma2(50));   // construction of mesh
+
+fespace Vh(Th,P2); // P2 conforming triangular FEM
+Vh phi,w, f=1;
+
+solve Laplace(phi,w)=int2d(Th)(dx(phi)*dx(w) + dy(phi)*dy(w))
+                - int2d(Th)(f*w) + on(Gamma1,phi=z);  // resolution of laplace equation
+plot(phi,wait=true, ps="membrane.eps"); //Plot Th and v
+plot(Th,wait=true, ps="membraneTh.eps"); //Plot Th and v
+
+// to build a gnuplot data file
+{ ofstream ff("graph.txt");
+   for (int i=0;i<Th.nt;i++)
+   { for (int j=0; j <3; j++)
+       ff<<Th[i][j].x  << "    "<< Th[i][j].y<< "  "<<phi[][Vh(i,j)]<<endl;
+    ff<<Th[i][0].x  << "    "<< Th[i][0].y<< "  "<<phi[][Vh(i,0)]<<endl
+      <<endl<<endl;
+   }
+}
+
+savemesh(Th,"Th.msh");
diff --git a/examples++-chapt3/membranerror.edp b/examples++-chapt3/membranerror.edp
new file mode 100755
index 0000000..2bafec4
--- /dev/null
+++ b/examples++-chapt3/membranerror.edp
@@ -0,0 +1,29 @@
+// file membranerror.edp
+verbosity=0;
+
+real theta=4.*pi/3.;
+real a=1.,b=1.; // the length of the semimajor axis and  semiminor axis
+border Gamma1(t=0,theta)    { x = a * cos(t); y = b*sin(t); }
+border Gamma2(t=theta,2*pi) { x = a * cos(t); y = b*sin(t); }
+
+
+func f=-4*(cos(x^2+y^2-1) -(x^2+y^2)*sin(x^2+y^2-1));
+func phiexact=sin(x^2+y^2-1);
+
+real[int] L2error(2);
+for(int n=0;n<2;n++)
+{
+  mesh Th=buildmesh(Gamma1(40*(n+1))+Gamma2(20*(n+1)));
+  fespace Vh(Th,P2); 
+   Vh phi,w;
+  
+  solve laplace(phi,w)=int2d(Th)(dx(phi)*dx(w) + dy(phi)*dy(w))
+    - int2d(Th)(f*w) - int1d(Th,Gamma2)(2*w)+ on(Gamma1,phi=0);
+  plot(Th,phi,wait=true,ps="membrane.eps"); //Plot Th and phi
+  
+  L2error[n]= sqrt(int2d(Th)((phi-phiexact)^2));
+}  
+for(int n=0;n<2;n++)
+  cout << " L2error " << n << " = "<<  L2error[n] <<endl;
+  
+cout <<" convergence rate = "<< log(L2error[0]/L2error[1])/log(2.)  <<endl;
diff --git a/examples++-chapt3/muwave.edp b/examples++-chapt3/muwave.edp
new file mode 100755
index 0000000..6e604ad
--- /dev/null
+++ b/examples++-chapt3/muwave.edp
@@ -0,0 +1,34 @@
+// file muwave.edp
+real a=20, b=20, c=15, d=8, e=2, l=12, f=2, g=2;
+border a0(t=0,1) {x=a*t; y=0;label=1;}
+border a1(t=1,2) {x=a; y= b*(t-1);label=1;}
+border a2(t=2,3) { x=a*(3-t);y=b;label=1;}
+border a3(t=3,4){x=0;y=b-(b-c)*(t-3);label=1;}
+border a4(t=4,5){x=0;y=c-(c-d)*(t-4);label=2;}
+border a5(t=5,6){ x=0; y= d*(6-t);label=1;}
+
+border b0(t=0,1) {x=a-f+e*(t-1);y=g; label=3;}
+border b1(t=1,4) {x=a-f; y=g+l*(t-1)/3; label=3;}
+border b2(t=4,5) {x=a-f-e*(t-4); y=l+g; label=3;}
+border b3(t=5,8) {x=a-e-f; y= l+g-l*(t-5)/3; label=3;}
+int n=2;
+mesh Th = buildmesh(a0(10*n)+a1(10*n)+a2(10*n)+a3(10*n)
+        +a4(10*n)+a5(10*n)+b0(5*n)+b1(10*n)+b2(5*n)+b3(10*n));
+plot(Th,wait=1);
+fespace Vh(Th,P1);
+real meat =  Th(a-f-e/2,g+l/2).region, air= Th(0.01,0.01).region;
+Vh R=(region-air)/(meat-air);
+
+Vh<complex> v,w;
+solve muwave(v,w) = int2d(Th)(v*w*(1+R)
+                -(dx(v)*dx(w)+dy(v)*dy(w))*(1-0.5i))
+   + on(1,v=0) + on(2, v=sin(pi*(y-c)/(c-d)));
+Vh vr=real(v), vi=imag(v);
+plot(vr,wait=1,ps="rmuonde.ps", fill=true);
+plot(vi,wait=1,ps="imuonde.ps", fill=true);
+
+fespace Uh(Th,P1); Uh u,uu, ff=1e5*(vr^2 + vi^2)*R;
+
+solve temperature(u,uu)= int2d(Th)(dx(u)* dx(uu)+ dy(u)* dy(uu))
+     - int2d(Th)(ff*uu) + on(1,2,u=0);
+plot(u,wait=1,ps="tempmuonde.ps", fill=true);
diff --git a/examples++-chapt3/optimcontrol.edp b/examples++-chapt3/optimcontrol.edp
new file mode 100644
index 0000000..e7609d5
--- /dev/null
+++ b/examples++-chapt3/optimcontrol.edp
@@ -0,0 +1,48 @@
+// file optimcontrol.edp
+border aa(t=0, 2*pi) {    x = 5*cos(t);    y = 5*sin(t);  };
+border bb(t=0, 2*pi) {    x = cos(t);    y = sin(t);  };
+border cc(t=0, 2*pi) {    x = -3+cos(t);    y = sin(t);  };
+border dd(t=0, 2*pi) {    x = cos(t);    y = -3+sin(t);  };
+mesh th = buildmesh(aa(70)+bb(35)+cc(35)+dd(35));
+fespace Vh(th,P1);
+Vh Ib=((x^2+y^2)<1.0001),
+   Ic=(((x+3)^2+ y^2)<1.0001),
+   Id=((x^2+(y+3)^2)<1.0001),
+   Ie=(((x-1)^2+ y^2)<=4),
+   ud,u,uh,du;
+real[int] z(3);
+problem A(u,uh) =int2d(th)((1+z[0]*Ib+z[1]*Ic+z[2]*Id)*(dx(u)*dx(uh)
+                    +dy(u)*dy(uh))) + on(aa,u=x^3-y^3);
+z[0]=2; z[1]=3; z[2]=4;
+A; ud=u;
+ofstream f("J.txt");
+func real J(real[int] & Z)
+{
+    for (int i=0;i<z.n;i++)z[i]=Z[i];
+    A; real s= int2d(th)(Ie*(u-ud)^2);
+    f<<s<<"   "; return s;
+}
+
+real[int] dz(3), dJdz(3);
+
+problem B(du,uh)
+  =int2d(th)((1+z[0]*Ib+z[1]*Ic+z[2]*Id)*(dx(du)*dx(uh)+dy(du)*dy(uh)))
+  +int2d(th)((dz[0]*Ib+dz[1]*Ic+dz[2]*Id)*(dx(u)*dx(uh)+dy(u)*dy(uh)))
+  +on(aa,du=0);
+
+func real[int] DJ(real[int] &Z)
+    {
+      for(int i=0;i<z.n;i++)
+        { for(int j=0;j<dz.n;j++) dz[j]=0;
+          dz[i]=1; B;
+          dJdz[i]= 2*int2d(th)(Ie*(u-ud)*du);
+      }
+     return dJdz;
+ }
+
+ real[int] Z(3);
+ for(int j=0;j<z.n;j++) Z[j]=1;
+ BFGS(J,DJ,Z,eps=1.e-6,nbiter=15,nbiterline=20);
+ cout << "BFGS: J(z) = " << J(Z) <<  endl;
+ for(int j=0;j<z.n;j++) cout<<z[j]<<endl;
+ plot(ud,value=1,ps="u.eps");
\ No newline at end of file
diff --git a/examples++-chapt3/potential.edp b/examples++-chapt3/potential.edp
new file mode 100755
index 0000000..3ff5077
--- /dev/null
+++ b/examples++-chapt3/potential.edp
@@ -0,0 +1,32 @@
+// file potential.edp
+
+real S=99;
+border C(t=0,2*pi) {  x=3*cos(t);  y=3*sin(t);}
+border Splus(t=0,1){  x = t; y = 0.17735*sqrt(t)-0.075597*t
+        - 0.212836*(t^2)+0.17363*(t^3)-0.06254*(t^4); label=S;}
+border Sminus(t=1,0){  x =t; y= -(0.17735*sqrt(t)-0.075597*t
+        -0.212836*(t^2)+0.17363*(t^3)-0.06254*(t^4)); label=S;}
+mesh Th= buildmesh(C(50)+Splus(70)+Sminus(70));
+fespace Vh(Th,P2); Vh psi,w;
+
+solve potential(psi,w)=int2d(Th)(dx(psi)*dx(w)+dy(psi)*dy(w))+
+  on(C,psi = y)+ on(S,psi=0);
+
+plot(psi,wait=1);
+border D(t=0,2){x=1+t;y=0;}
+mesh Sh = buildmesh(C(25)+Splus(-90)+Sminus(-90)+D(200));
+fespace Wh(Sh,P1); Wh v,vv;
+int steel=Sh(0.5,0).region, air=Sh(-1,0).region;
+fespace W0(Sh,P0);
+W0 k=0.01*(region==air)+0.1*(region==steel);
+W0 u1=dy(psi)*(region==air), u2=-dx(psi)*(region==air);
+Wh vold = 120*(region==steel);
+real dt=0.05, nbT=50;
+int i;
+problem thermic(v,vv,init=i,solver=LU)= int2d(Sh)(v*vv/dt + k*(dx(v) * dx(vv) + dy(v) * dy(vv))
+                + 10*(u1*dx(v)+u2*dy(v))*vv)- int2d(Sh)(vold*vv/dt);
+for(i=0;i<nbT;i++){
+    v=vold; thermic;
+ plot(v);
+}
+plot(v,wait=1);
diff --git a/examples++-chapt3/ref.edp b/examples++-chapt3/ref.edp
new file mode 100644
index 0000000..e69de29
diff --git a/examples++-chapt3/regtests.edp b/examples++-chapt3/regtests.edp
new file mode 100644
index 0000000..89ce0ed
--- /dev/null
+++ b/examples++-chapt3/regtests.edp
@@ -0,0 +1,37 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+// Regression tests
+// ----------------
+
+// The tests are checked against reference values by "make check" in
+// each examples subdirectory
+
+// "ref.edp" contains all reference values and may be rebuilt with
+// "make Ref"
+
+// $Id$
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+NoUseOfWait=true;
+int verbosityy=verbosity;
+
+
+
+
+include "ref.edp";
+
+
+
+
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+
diff --git a/examples++-chapt3/regtests.m4 b/examples++-chapt3/regtests.m4
new file mode 100644
index 0000000..8c24d45
--- /dev/null
+++ b/examples++-chapt3/regtests.m4
@@ -0,0 +1,12 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+include(../regtests.m4)
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+
diff --git a/examples++-chapt3/schwarz.edp b/examples++-chapt3/schwarz.edp
new file mode 100755
index 0000000..6463609
--- /dev/null
+++ b/examples++-chapt3/schwarz.edp
@@ -0,0 +1,26 @@
+//  Tutorial file schwarz.edp: Schwarz Algorithm
+border a(t=0,1){x=t;y=0;} // This is a rectangle
+border a1(t=1,2){x=t;y=0;}
+border b(t=0,1){x=2;y=t;}
+border c(t=2,0){x=t ;y=1;}
+border d(t=1,0){x = 0; y = t;} // next is a circle
+border e(t=0, pi/2){ x= cos(t); y = sin(t);}
+border e1(t=pi/2, 2*pi){ x= cos(t); y = sin(t);}
+real n=4;
+
+//Omega1
+mesh th = buildmesh( a(5*n) + a1(5*n) + b(5*n) + c(10*n) + d(5*n));
+fespace Vh(th,P1); Vh v,u=0;
+
+//Omega2
+mesh TH = buildmesh ( e(5*n) + e1(25*n) );
+fespace VH(TH,P1); VH V,U = 0;
+
+for( int i=0; i< 4; i++) {
+    plot(U,u, wait=1);
+    solve AA(U,V)= int2d(TH)(dx(U)* dx(V)+ dy(U)* dy(V))
+                 - int2d(TH)(V) + on(e,U=u)+ on(e1,U=0);
+    solve aa(u,v)= int2d(th)(dx(u)*dx(v)+ dy(u)* dy(v))
+                - int2d(th)(v) + on(a,d,u=U) + on(a1,b,c,u=0);
+}
+plot(U,u, wait=1);
diff --git a/examples++-chapt3/sound.edp b/examples++-chapt3/sound.edp
new file mode 100755
index 0000000..5d9022e
--- /dev/null
+++ b/examples++-chapt3/sound.edp
@@ -0,0 +1,45 @@
+real kc2=1; // try this value 19.4256;
+func g=y*(1-y);
+
+border a0(t=0,1) { x= 5; y= 1+2*t ;}
+border a1(t=0,1) { x=5-2*t; y= 3 ;}
+border a2(t=0,1) { x= 3-2*t; y=3-2*t ;}
+border a3(t=0,1) { x= 1-t; y= 1 ;}
+border a4(t=0,1) { x= 0; y= 1-t ;}
+border a5(t=0,1) { x= t; y= 0  ;}
+border a6(t=0,1) { x= 1+4*t; y= t ;}
+
+mesh Th=buildmesh( a0(20) + a1(20) + a2(20)
+        + a3(20) + a4(20) + a5(20) + a6(20));
+fespace Vh(Th,P1);  Vh u,v;
+
+solve sound(u,v)=int2d(Th)(u*v * kc2 - dx(u)*dx(v) - dy(u)*dy(v))
+                 - int1d(Th,a4)(g*v);
+plot(u, wait=1, ps="sound0.eps");
+
+Vh u1,u2;
+
+
+real sigma = 20;  // value of the shift
+
+// OP = A - sigma B ;  //  the shifted matrix
+varf  op(u1,u2)= int2d(Th)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) - sigma* u1*u2 )
+ ;//                   +  on(1,2,3,4,u1=0) ;  // Boundary condition
+
+varf b([u1],[u2]) = int2d(Th)(  u1*u2 ) ; // no  Boundary condition
+
+matrix OP= op(Vh,Vh,solver=Crout,factorize=1);  // crout solver because the matrix in not positive
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20);
+
+
+int nev=2;  // number of computed eigen value close to sigma
+
+real[int] ev(nev); // to store the  nev eigenvalue
+Vh[int] eV(nev);   // to store the nev eigenvector \index{EigenValue}
+
+
+int k=EigenValue(OP,B,sym=true,sigma=sigma,value=ev,vector=eV,
+                   tol=1e-10,maxit=0,ncv=0);
+cout<<ev(0)<<" 2 eigen values "<<ev(1)<<endl;
+v=eV[0];
+plot(v,wait=1,ps="eigen.eps");
diff --git a/examples++-chapt3/stokes.edp b/examples++-chapt3/stokes.edp
new file mode 100755
index 0000000..9acaa75
--- /dev/null
+++ b/examples++-chapt3/stokes.edp
@@ -0,0 +1,12 @@
+//file Stokes.edp
+int n=3;
+mesh Th=square(10*n,10*n);
+fespace Uh(Th,P1b); Uh u,v,uu,vv;
+fespace Ph(Th,P1);  Ph p,pp;
+
+solve stokes([u,v,p],[uu,vv,pp]) =
+    int2d(Th)(dx(u)*dx(uu)+dy(u)*dy(uu) + dx(v)*dx(vv)+ dy(v)*dy(vv)
+            + dx(p)*uu + dy(p)*vv + pp*(dx(u)+dy(v))
+            -1e-10*p*pp)            
+            + on(1,2,4,u=0,v=0) + on(3,u=1,v=0);
+plot([u,v],p,wait=1);
diff --git a/examples++-chapt3/test1.edp b/examples++-chapt3/test1.edp
new file mode 100755
index 0000000..511de23
--- /dev/null
+++ b/examples++-chapt3/test1.edp
@@ -0,0 +1,28 @@
+//Tutorial file test1.pde
+// YOUR FIRST PROGRAM
+
+border C(t=0,2*pi){x=cos(t); y=sin(t);}                    // the boundary
+mesh Th = buildmesh (C(50));                // of the domain and its mesh
+fespace Vh(Th,P1);      // Finite Element of degree 2 defined here for Vh
+ Vh u,v;            // defines u and v as piecewise-P2 continuous functions
+ func f= x*y;                       // definition of an algebraic function
+ real cpu = clock();
+ solve Poisson(u,v,solver=LU) =               // defines and solves the PDE
+    int2d(Th)( dx(u)*dx(v) + dy(u)*dy(v))               //  bilinear part
+    - int2d(Th)( f*v)                                   // right hand side
+    + on(C,u=0)  ;                          // Dirichlet boundary condition
+
+  plot(u,wait=1);
+ cout << " CPU time = " << clock()-cpu << endl;
+
+// ENDS HERE
+
+// FOR THE PRO: The same done with total control over the algebra
+varf a(u,v) = int2d(Th)( dx(u)*dx(v) + dy(u)*dy(v))+ on(C,u=0) ;
+matrix A=a(Vh,Vh);  // stiffness matrix, see (\ref{eqn:Stiffness0})
+varf b(u,v) = int2d(Th)( u*v ) ;
+matrix B=b(Vh,Vh);
+Vh F=f;
+v[] = B*F[];
+u[]=A^-1*v[];
+plot(u,wait=1);
diff --git a/examples++-chapt3/testbed.edp b/examples++-chapt3/testbed.edp
new file mode 100755
index 0000000..7ccf588
--- /dev/null
+++ b/examples++-chapt3/testbed.edp
@@ -0,0 +1,19 @@
+cout << " "<< endl;
+/*  Ne compile pas FH ?? 
+for (idt = 1; idt < 50; idt++)
+ {
+   temps += dt;
+   cout << " --------- temps " << temps << " \n ";
+   b1[] =  vfconv1(0,Xh);
+   b2[] =  vfconv2(0,Xh);
+   cout << "  min b1 b2  " << b1[].min << " " << b2[].min << endl;
+   cout << "  max b1 b2  " << b1[].max << " " << b2[].max << endl;
+   // call Conjugate Gradient with preconditioner '
+   //  warning eps < 0 => absolue stop test \index{precon=}
+   LinearCG(divup,p[],eps=-1.e-6,nbiter=50,precon=CahouetChabart);
+   divup(p[]);   //  computed the velocity
+
+   plot([u1,u2],p,wait=!(idt%10),value= 1,coef=0.1);
+ }
+ 
+*/
\ No newline at end of file
diff --git a/examples++-chapt3/thermal.edp b/examples++-chapt3/thermal.edp
new file mode 100755
index 0000000..1453983
--- /dev/null
+++ b/examples++-chapt3/thermal.edp
@@ -0,0 +1,24 @@
+// file heatex.edp
+int C1=99, C2=98; // could be anything
+border C0(t=0,2*pi){x=5*cos(t); y=5*sin(t);}
+
+border C11(t=0,1){ x=1+t;  y=3;      label=C1;}
+border C12(t=0,1){ x=2;    y=3-6*t;  label=C1;}
+border C13(t=0,1){ x=2-t;  y=-3;     label=C1;}
+border C14(t=0,1){ x=1;    y=-3+6*t; label=C1;}
+
+border C21(t=0,1){ x=-2+t; y=3;      label=C2;}
+border C22(t=0,1){ x=-1;   y=3-6*t;  label=C2;}
+border C23(t=0,1){ x=-1-t; y=-3;     label=C2;}
+border C24(t=0,1){ x=-2;   y=-3+6*t; label=C2;}
+
+mesh Th=buildmesh(    C0(50)
+                    + C11(5)+C12(20)+C13(5)+C14(20)
+                    + C21(-5)+C22(-20)+C23(-5)+C24(-20));
+plot(Th,wait=1);
+
+fespace Vh(Th,P1); Vh u,v;
+Vh kappa=1+4*(x<-1)*(x>-2)*(y<3)*(y>-3);
+solve a(u,v)= int2d(Th)(kappa*(dx(u)*dx(v)+dy(u)*dy(v)))
+                +on(C0,u=20)+on(C1,u=100);
+plot(u,value=true,wait=1,fill=true);
diff --git a/examples++-chapt3/thermic.edp b/examples++-chapt3/thermic.edp
new file mode 100755
index 0000000..7e46694
--- /dev/null
+++ b/examples++-chapt3/thermic.edp
@@ -0,0 +1,44 @@
+// file thermal.edp
+
+func u0 =10+90*x/6;
+func k = 1.8*(y<0.5)+0.2;
+real ue = 25, alpha=0.25, T=5, dt=0.1 ;
+
+mesh Th=square(30,5,[6*x,y]);
+fespace Vh(Th,P1);
+/*
+Vh u=u0,v,uold;
+// for the flat plate
+problem thermic(u,v)= int2d(Th)(u*v/dt + k*(dx(u) * dx(v) + dy(u) * dy(v)))
+                + int1d(Th,1,3)(alpha*u*v)
+                - int1d(Th,1,3)(alpha*ue*v)
+                - int2d(Th)(uold*v/dt) + on(2,4,u=u0);
+// for the rod
+problem thermaxi(u,v)=int2d(Th)((u*v/dt + dx(u)*dx(v) + dy(u)*dy(v))*x)
+                + int1d(Th,3)(alpha*x*u*v) - int1d(Th,3)(alpha*x*ue*v)
+                - int2d(Th)(uold*v*x/dt) + on(2,4,u=u0);
+ofstream ff("thermic.dat");
+for(real t=0;t<T;t+=dt){
+    uold=u;
+    // thermaxi; thermic; // choose one of the two
+    ff<<t<<" "<<u(3,0.5)<<endl;
+    plot(u);
+}
+for(int i=0;i<20;i++) cout<<dy(u)(6.0*i/20.0,0.9)<<endl;
+plot(u,fill=true,wait=true,ps="thermic.eps");
+*/
+real rad=1e-8, uek=ue+273;
+Vh vold,w,v=u0-ue,b;
+problem thermradia(v,w)
+    = int2d(Th)(v*w/dt + k*(dx(v) * dx(w) + dy(v) * dy(w)))
+                + int1d(Th,1,3)(b*v*w)
+                - int2d(Th)(vold*w/dt) + on(2,4,v=u0-ue);
+
+for(real t=0;t<T;t+=dt){
+    vold=v;
+    for(int m=0;m<5;m++){
+       b= alpha + rad * (v + 2*uek) * ((v+uek)^2 + uek^2);
+       thermradia;
+    }
+}
+vold=v+ue; plot(vold);
diff --git a/examples++-eigen/._BeamEigenValue.edp b/examples++-eigen/._BeamEigenValue.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-eigen/._BeamEigenValue.edp differ
diff --git a/examples++-eigen/._free-cyl-axi.edp b/examples++-eigen/._free-cyl-axi.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-eigen/._free-cyl-axi.edp differ
diff --git a/examples++-eigen/BeamEigenValue.edp b/examples++-eigen/BeamEigenValue.edp
new file mode 100644
index 0000000..a495edf
--- /dev/null
+++ b/examples++-eigen/BeamEigenValue.edp
@@ -0,0 +1,72 @@
+//  Computation of the eigen value and eigen vector of the 
+// Dirichlet problem  on square $]0,\pi[^2$
+// ----------------------------------------
+// we use the inverse shift mode 
+// the shift is given with sigma real
+// -------------------------------------
+//  find $\lamda$ such that:
+// $$  \int_{\omega}  \nabla u_ \nabla v = \lamba \int_{\omega} u \nabla v  $$
+verbosity=1;
+int bottombeam = 2;
+border aaa(t=2,0)  { x=0; y=t ;label=1;};        //  left beam
+border bbb(t=0,10) { x=t; y=0 ;label=bottombeam;};        //  bottom of beam
+border ccc(t=0,2)  { x=10; y=t ;label=1;};       //  rigth beam
+border ddd(t=0,10) { x=10-t; y=2; label=3;};     //  top beam 
+real E = 21.5;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+mesh Th = buildmesh( bbb(20)+ccc(5)+ddd(20)+aaa(5));
+fespace Vh(Th,[P1,P1]);
+Vh [uu,vv], [w,s];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+// deformation of a beam under its own weight 
+
+real shift = 0;  // value of the shift 
+
+varf a([uu,vv],[w,s])=
+	int2d(Th)(  
+		2*mu*(dx(uu)*dx(w)+dy(vv)*dy(s)+ ((dx(vv)+dy(uu))*(dx(s)+dy(w)))/2 )
+               + lambda*(dx(uu)+dy(vv))*(dx(w)+dy(s))
+        - shift* (uu*w + vv*s)      
+             )
+  + on(1,uu=0,vv=0)
+  ;
+
+varf b([uu,vv],[w,s])=
+	int2d(Th)(uu*w + vv*s)      ;
+
+
+
+matrix A= a(Vh,Vh,solver=UMFPACK); 
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+
+// important remark:
+// the boundary condition is make with exact penalisation:
+//     we put 1e30=tgv  on the diagonal term of the lock degre of freedom.
+//  So take dirichlet boundary condition just on $a$ variationnal form
+// and not on  $b$ variationnanl form.
+// because we solve
+//  $$ w=A^-1*B*v $$
+
+int nev=20;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+Vh[int] [eV,eW](nev);   // to store nev eigen vector
+
+
+int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10,maxit=0,ncv=0);
+//   tol= the tolerace
+//   maxit= the maximal iteration see arpack doc.
+//   ncv   see arpack doc.
+//  the return value is number of converged eigen value.
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+
+for (int i=0;i<k;i++)
+{
+  [uu,vv]=[eV[i],eW[i]];
+  plot([uu,vv],cmm="Eigen  Vector "+i+" valeur =" + ev[i]  ,wait=1,value=1,ps="eigen"+i+".eps");
+}
+
diff --git a/examples++-eigen/BeamEigenValueperio.edp b/examples++-eigen/BeamEigenValueperio.edp
new file mode 100644
index 0000000..92f4dde
--- /dev/null
+++ b/examples++-eigen/BeamEigenValueperio.edp
@@ -0,0 +1,72 @@
+//  Computation of the eigen value and eigen vector of the 
+// Dirichlet problem  on square $]0,\pi[^2$
+// ----------------------------------------
+// we use the inverse shift mode 
+// the shift is given with sigma real
+// -------------------------------------
+//  find $\lamda$ such that:
+// $$  \int_{\omega}  \nabla u_ \nabla v = \lamba \int_{\omega} u \nabla v  $$
+verbosity=1;
+int bottombeam = 2;
+border aaa(t=2,0)  { x=0; y=t ;label=1;};        //  left beam
+border bbb(t=0,10) { x=t; y=0 ;label=bottombeam;};        //  bottom of beam
+border ccc(t=0,2)  { x=10; y=t ;label=4;};       //  rigth beam
+border ddd(t=0,10) { x=10-t; y=2; label=3;};     //  top beam 
+real E = 21.5;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+mesh Th = buildmesh( bbb(20)+ccc(5)+ddd(20)+aaa(5));
+fespace Vh(Th,[P1,P1],periodic=[ [bottombeam,x],[3,x],[1,y],[4,y] ]);
+Vh [uu,vv], [w,s];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+// deformation of a beam under its own weight 
+
+real shift = 1;  // value of the shift 
+
+varf a([uu,vv],[w,s])=
+	int2d(Th)(  
+		2*mu*(dx(uu)*dx(w)+dy(vv)*dy(s)+ ((dx(vv)+dy(uu))*(dx(s)+dy(w)))/2 )
+               + lambda*(dx(uu)+dy(vv))*(dx(w)+dy(s))
+        - shift* (uu*w + vv*s)      
+             )
+//  + on(1,uu=0,vv=0)
+  ;
+
+varf b([uu,vv],[w,s])=
+	int2d(Th)(uu*w + vv*s)      ;
+
+
+
+matrix A= a(Vh,Vh,solver=Crout,factorize=1); 
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+
+// important remark:
+// the boundary condition is make with exact penalisation:
+//     we put 1e30=tgv  on the diagonal term of the lock degre of freedom.
+//  So take dirichlet boundary condition just on $a$ variationnal form
+// and not on  $b$ variationnanl form.
+// because we solve
+//  $$ w=A^-1*B*v $$
+
+int nev=20;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+Vh[int] [eV,eW](nev);   // to store nev eigen vector
+
+
+int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10,maxit=0,ncv=0);
+//   tol= the tolerace
+//   maxit= the maximal iteration see arpack doc.
+//   ncv   see arpack doc.
+//  the return value is number of converged eigen value.
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+
+for (int i=0;i<k;i++)
+{
+  [uu,vv]=[eV[i],eW[i]];
+  plot([uu,vv],cmm="Eigen  Vector "+i+" valeur =" + ev[i]  ,wait=1,value=1,ps="eigen"+i+".eps");
+}
+
diff --git a/examples++-eigen/Lap3dEigenValue.edp b/examples++-eigen/Lap3dEigenValue.edp
new file mode 100644
index 0000000..efa3b40
--- /dev/null
+++ b/examples++-eigen/Lap3dEigenValue.edp
@@ -0,0 +1,85 @@
+//  Computation of the eigen value and eigen vector of the 
+// Dirichlet problem  on cube  $]0,\pi[^3$
+// ----------------------------------------
+// we use the inverse shift mode 
+// the shift is given with sigma real
+// -------------------------------------
+//  find $\lamda$ such that:
+// $$  \int_{\omega}  \nabla u_ \nabla v = \lamba \int_{\omega} u \nabla v  $$
+
+load "msh3"	
+int nn=15;
+mesh Th2=square(nn,nn,[pi*x,pi*y]);
+fespace Vh2(Th2,P1);
+int[int] rup=[0,1],  rdown=[0,1], rmid=[4,1,2,1, 1,1 ,3,1];
+real zmin=0,zmax=pi;
+
+mesh3 Th=buildlayers(Th2,nn,
+		     zbound=[zmin,zmax],
+		     // region=r1, 
+		     labelmid=rmid, 
+		     reffaceup = rup,
+		     reffacelow = rdown);
+cout << "Th :  nv = " << Th.nv << " nt =" << Th.nt << endl;
+
+fespace Vh(Th,P1);
+Vh u1,u2;
+
+
+real sigma = 00;  // value of the shift 
+macro Grad(u) [dx(u),dy(u),dz(u)] // EOM
+  varf  a(u1,u2)= int3d(Th)(  Grad(u1)'*Grad(u2)  - sigma* u1*u2 ) //') 
+  +  on(1,u1=0.) ;  // Boundary condition
+                   
+varf b([u1],[u2]) = int3d(Th)(  u1*u2 ) ; // no  Boundary condition
+
+matrix A= a(Vh,Vh,solver=UMFPACK); 
+cout << " fin A .. " << endl;
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+
+// important remark:
+// the boundary condition is make with exact penalisation:
+//     we put 1e30=tgv  on the diagonal term of the lock degre of freedom.
+//  So take dirichlet boundary condition just on $a$ variationnal form
+// and not on  $b$ variationnanl form.
+// because we solve
+//  $$ w=A^-1*B*v $$
+
+int nev=10;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+Vh[int] eV(nev);   // to store nev eigen vector
+
+
+int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10,maxit=0,ncv=0);
+//   tol= the tolerace
+//   maxit= the maximal iteration see arpack doc.
+//   ncv   see arpack doc.
+//  the return value is number of converged eigen value.
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+
+int nerr=0;
+real[int]  eev(6*6*6);
+eev=1e100;
+for(int i=1,k=0;i<6;++i)
+  for(int j=1;j<6;++j)
+    for(int l=1;l<6;++l)
+      eev[k++]=i*i+j*j+l*l;
+eev.sort;
+cout << eev << endl;
+for (int i=0;i<k;i++)
+  {
+    u1=eV[i];
+    real gg = int3d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1) + dz(u1)*dz(u1) );
+    real mm= int3d(Th)(u1*u1) ;
+    real err = int3d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1) + dz(u1)*dz(u1) - (ev[i])*u1*u1) ;
+    if(abs(err) > 1e-6) nerr++;
+    if(abs(ev[i]-eev[i]) > eev[i]*1e-1) nerr++;
+    cout << " ---- " <<  i<< " " << ev[i] << " == " << eev[i] << " err= " << err << " --- "<<endl;
+    plot(eV[i],cmm="Eigen 3d  Vector "+i+" valeur =" + ev[i]+ " == " + eev[i]    ,wait=1,value=1,ps="eigen"+i+".eps");
+  }
+
+// FFCS: avoid this assert because the list of eigenvalues is not
+// always sorted in the same way
+//assert(nerr==0);
diff --git a/examples++-eigen/LapComplexEigenValue.edp b/examples++-eigen/LapComplexEigenValue.edp
new file mode 100644
index 0000000..6b3a233
--- /dev/null
+++ b/examples++-eigen/LapComplexEigenValue.edp
@@ -0,0 +1,62 @@
+//  laplace with matrix  
+verbosity=1;
+mesh Th=square(20,20,[pi*x,pi*y]);
+fespace Vh(Th,P2);
+Vh<complex> u1,u2;
+Vh ur,ui;
+int n=u1.n;
+complex[int] Bu1(n),Bu2(n);
+complex[int] Au1(n),Au2(n);
+
+complex  sigma = 0; //1.000+1i;                     
+complex nu=1+1i;
+
+varf  op(u1,u2)= int2d(Th)(  nu*(dx(u1)*dx(u2) + dy(u1)*dy(u2))  - sigma*u1*u2  )
+                    +  on(1,2,3,4,u1=0)
+;
+varf  a(u1,u2)= int2d(Th)(  nu*(dx(u1)*dx(u2) + dy(u1)*dy(u2))   )
+                    +  on(1,2,3,4,u1=0)
+;
+                   
+varf b([u1],[u2]) = int2d(Th)(  u1*u2 ) ;//+  on(1,2,3,4,u1=0);
+
+
+matrix<complex> OP= op(Vh,Vh,solver=UMFPACK); 
+matrix<complex> A= a(Vh,Vh,solver=GMRES); 
+matrix<complex> B= b(Vh,Vh,solver=GMRES,eps=1e-20); 
+int nev=10;
+
+complex[int] ev(nev); // to store 10 eigen value 
+Vh<complex>[int] eV(nev);   // to store 10 eigen vector  
+
+int k=EigenValue(OP,B,sigma=sigma,value=ev,vector=eV,
+	         tol=1e-10,maxit=90000,ncv=100);
+
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+for (int kk=0;kk<k;kk++)
+{ 
+  int i=kk;	
+  u1=eV[i];	
+  complex v= ev[i];
+  Bu1=B*u1[];
+  Au1=A*u1[];
+    //  The Rayleigh quotient lambda = x'Ax/x'Bx 
+    //  given the eigen value 
+  complex xAx = u1[]'*Au1 ;
+  complex xBx = u1[]'*Bu1 ;
+  //  A u = l * B u
+  Bu1 =   v*Bu1;
+  u1[] = Au1 -Bu1; 
+  if(norm(u1[].sum)>1e-5)
+        cout << "BUG :::   zero ==  " <<u1[].sum << endl;
+  cout << " ---- " <<  i<< " " <<  v << endl;
+  ur=real(eV[i]);
+  ui=imag(eV[i]);
+//  plot(ur,cmm="Eigen  Vector (real)  "+i+" valeur =" + v  ,wait=1,value=1);
+//  plot(ui,cmm="Eigen  Vector (imag)  "+i+" valeur =" + v  ,wait=1,value=1);
+
+    // FFCS: add 3d view
+    plot(eV[i],dim=3,fill=1);
+}
+
diff --git a/examples++-eigen/LapEigenValue.edp b/examples++-eigen/LapEigenValue.edp
new file mode 100644
index 0000000..1a42ee9
--- /dev/null
+++ b/examples++-eigen/LapEigenValue.edp
@@ -0,0 +1,67 @@
+//  Computation of the eigen value and eigen vector of the 
+// Dirichlet problem  on square $]0,\pi[^2$
+// ----------------------------------------
+// we use the inverse shift mode 
+// the shift is given with sigma real
+// -------------------------------------
+//  find $\lamda$ such that:
+// $$  \int_{\omega}  \nabla u_ \nabla v = \lamba \int_{\omega} u \nabla v  $$
+verbosity=1;
+mesh Th=square(20,20,[pi*y,pi*x]);
+fespace Vh(Th,P2);
+Vh u1,u2;
+
+
+real sigma = 00;  // value of the shift 
+
+varf  a(u1,u2)= int2d(Th)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) - sigma* u1*u2 )
+                    +  on(1,2,3,4,u1=0) ;  // Boundary condition
+                   
+varf b([u1],[u2]) = int2d(Th)(  u1*u2 ) ; // no  Boundary condition
+
+matrix A= a(Vh,Vh,solver=sparsesolver); 
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+
+// important remark:
+// the boundary condition is make with exact penalisation:
+//     we put 1e30=tgv  on the diagonal term of the lock degre of freedom.
+//  So take dirichlet boundary condition just on $a$ variationnal form
+// and not on  $b$ variationnanl form.
+// because we solve
+//  $$ w=A^-1*B*v $$
+
+int nev=20;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+Vh[int] eV(nev);   // to store nev eigen vector
+
+
+int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10,maxit=0,ncv=0);
+//   tol= the tolerace
+//   maxit= the maximal iteration see arpack doc.
+//   ncv   see arpack doc.
+//  the return value is number of converged eigen value.
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+int nerr=0;
+real[int]  eev(36);
+eev=1e100;
+for(int i=1,k=0;i<6;++i)
+for(int j=1;j<6;++j)
+  eev[k++]=i*i+j*j;
+eev.sort;
+cout << eev << endl;
+for (int i=0;i<k;i++)
+{
+  u1=eV[i];
+  real gg = int2d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1));
+  real mm= int2d(Th)(u1*u1) ;
+  real err = int2d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1) - (ev[i])*u1*u1) ;
+  if(abs(err) > 1e-6) nerr++;
+  if(abs(ev[i]-eev[i]) > 1e-1) nerr++;
+  cout << " ---- " <<  i<< " " << ev[i] << " == " << eev[i] << " err= " << err << " --- "<<endl;
+
+  // FFCS: add 3D view capabilities
+  plot(eV[i],cmm="Eigen  Vector "+i+" valeur =" + ev[i]  ,wait=1,value=1,ps="eigen"+i+".eps",dim=3,fill=1,CutPlane=0,ShowAxes=0);
+}
+assert(nerr==0);
diff --git a/examples++-eigen/LapEigenValueFunc.edp b/examples++-eigen/LapEigenValueFunc.edp
new file mode 100644
index 0000000..da2d476
--- /dev/null
+++ b/examples++-eigen/LapEigenValueFunc.edp
@@ -0,0 +1,70 @@
+//  Computation of the eigen value and eigen vector of the 
+// Dirichlet problem  on square $]0,\pi[^2$
+// Functionnal interface 
+// ----------------------------------------
+// we use the inverse shift mode 
+// the shift is given with sigma real
+// -------------------------------------
+//  find $\lamda$ such that:
+// $$  \int_{\omega}  \nabla u_ \nabla v = \lamba \int_{\omega} u \nabla v  $$
+verbosity=1;
+mesh Th=square(20,20,[pi*y,pi*x]);
+fespace Vh(Th,P2);
+Vh u1,u2;
+int n=Vh.ndof; 
+
+real sigma = 00;  // value of the shift 
+
+varf  a(u1,u2)= int2d(Th)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) - sigma* u1*u2 )
+                    +  on(1,2,3,4,u1=0) ;  // Boundary condition
+                   
+varf b([u1],[u2]) = int2d(Th)(  u1*u2 ) ; // no  Boundary condition
+
+matrix A= a(Vh,Vh,solver=sparsesolver); 
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+
+func real[int] FA(real[int] & u) { real[int] Au=A^-1*u;return Au;}
+func real[int] FB(real[int] & u) { real[int] Au=B*u;return Au;}
+// important remark:
+// the boundary condition is make with exact penalisation:
+//     we put 1e30=tgv  on the diagonal term of the lock degre of freedom.
+//  So take dirichlet boundary condition just on $a$ variationnal form
+// and not on  $b$ variationnanl form.
+// because we solve
+//  $$ w=A^-1*B*v $$
+
+int nev=20;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+Vh[int] eV(nev);   // to store nev eigen vector
+
+
+int k=EigenValue(n,FA,FB,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10,maxit=0,ncv=0);
+//   tol= the tolerace
+//   maxit= the maximal iteration see arpack doc.
+//   ncv   see arpack doc.
+//  the return value is number of converged eigen value.
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+int nerr=0;
+real[int]  eev(36);
+eev=1e100;
+for(int i=1,k=0;i<6;++i)
+for(int j=1;j<6;++j)
+  eev[k++]=i*i+j*j;
+eev.sort;
+cout << eev << endl;
+for (int i=0;i<k;i++)
+{
+  u1=eV[i];
+  real gg = int2d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1));
+  real mm= int2d(Th)(u1*u1) ;
+  real err = int2d(Th)(dx(u1)*dx(u1) + dy(u1)*dy(u1) - (ev[i])*u1*u1) ;
+  if(abs(err) > 1e-6) nerr++;
+  if(abs(ev[i]-eev[i]) > 1e-1) nerr++;
+  cout << " ---- " <<  i<< " " << ev[i] << " == " << eev[i] << " err= " << err << " --- "<<endl;
+
+  // FFCS: add 3D view capabilities
+  plot(eV[i],cmm="Eigen  Vector "+i+" valeur =" + ev[i]  ,wait=1,value=1,ps="eigen"+i+".eps",dim=3,fill=1,CutPlane=0,ShowAxes=0);
+}
+assert(nerr==0);
diff --git a/examples++-eigen/LapnosymEigenValue.edp b/examples++-eigen/LapnosymEigenValue.edp
new file mode 100644
index 0000000..7f94072
--- /dev/null
+++ b/examples++-eigen/LapnosymEigenValue.edp
@@ -0,0 +1,77 @@
+//  laplace with matrix  
+verbosity=1;
+mesh Th=square(20,20,[2*pi*x,2*pi*y]);
+fespace Vh(Th,P2);
+Vh u1,u2;
+int n=u1.n;
+real[int] Bu1(n),Bu2(n);
+real[int] Au1(n),Au2(n);
+
+real sigma = 0;                     
+real nu=0.1;
+
+varf  op(u1,u2)= int2d(Th)(  nu*(dx(u1)*dx(u2) + dy(u1)*dy(u2)) + (dx(u1)+dy(u1))*u2 - sigma* u1*u2 )
+                    +  on(1,2,3,4,u1=0)
+;
+varf  a(u1,u2)= int2d(Th)(  nu*(dx(u1)*dx(u2) + dy(u1)*dy(u2)) + (dx(u1)+dy(u1))*u2 )
+                    +  on(1,2,3,4,u1=0)
+;
+                   
+varf b([u1],[u2]) = int2d(Th)(  u1*u2 ) ;//+  on(1,2,3,4,u1=0);
+
+
+matrix OP= op(Vh,Vh,solver=UMFPACK,factorize=0); 
+matrix A= a(Vh,Vh,solver=GMRES); 
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+int nev=10;
+
+real[int] ev(nev); // to store 10 eigein value real part
+real[int] evi(nev); // to store 10 eigein value imag part
+Vh[int] eV(nev);   // to store 10 eigen vector  
+/*
+ For real nonsymmetric problems, complex eigenvectors are
+ given as two consecutive vectors, so if Eigenvalue $k$ and $k+1$ 
+ are complex conjugate eigenvalues, 
+the vector eV[K] will contain the real part and 
+the vector eV[K] the imaginary part of the corresponding 
+complex conjugate eigenvectors. 
+*/
+
+
+int k=EigenValue(OP,B,sym=false,sigma=sigma,value=ev,vector=eV,
+	         tol=1e-10,maxit=0,ncv=0,ivalue=evi);
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+for (int kk=0;kk<k;kk++)
+{ 
+  int i=kk;
+  u1=eV[i];
+  u2=0;
+  real er=ev[i],ei=evi[i];
+  complex v= er+ei*1i;
+  if(ei) { // complex case
+    int j=++kk;
+    if (j>=k) break; 
+    u2 = eV[j];
+  }
+  cout << " ||u1|| " << u1[].linfty << " || u2|| = " << u2[].linfty << endl;
+  Bu1=B*u1[];
+  Bu2=B*u2[];
+  Au1=A*u1[];
+  Au2=A*u2[];
+    //  The Rayleigh quotient lambda = x'Ax/x'Bx 
+    //  given the eigen value 
+  real xBx = u1[]'*Bu1 + u2[]'*Bu2;
+  complex xAx = u1[]'*Au1 + u2[]'*Au2 + 1i*(u1[]'*Au2 - u2[]'*Au1);
+  complex eigenvalue = xAx/xBx;
+  cout << " ---- " <<  i<< " " <<  v <<" eigenvalue= " << eigenvalue << endl;
+
+  // FFCS: add 3D view
+  plot(eV[i],cmm="Eigen  Vector "+i+" valeur =" + er + " , " + ei  ,wait=1,value=1,dim=3,fill=1);
+}
+
+// FFCS: order of eigenvalues may change, and biggest eigenvalue
+// (95.xxx) may not be picked up at all.
+
+real regtest=0;
+for(int i=1;i<nev;i++)if(ev[i]<95 && regtest<ev[i])regtest=ev[i];
diff --git a/examples++-eigen/Makefile.am b/examples++-eigen/Makefile.am
new file mode 100644
index 0000000..7935374
--- /dev/null
+++ b/examples++-eigen/Makefile.am
@@ -0,0 +1,24 @@
+# $Id$
+# F. hecht july 2014  add  LapEigenValueFunc.edp example 
+all-local: all.edp freefem++.pref
+
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPP) FLAGS_FFPP=-nw SKIP=$(SKIP_TESTS_EIGEN)
+
+TESTS=BeamEigenValue.edp BeamEigenValueperio.edp Lap3dEigenValue.edp  LapEigenValue.edp LapnosymEigenValue.edp Stokes-eigen.edp VP-Steklov-Poincare.edp neuman.edp  WGM-sphere.edp free-cyl-axi.edp LapEigenValueFunc.edp
+#  LapComplexEigenValue.edp  (buggus) 
+EXTRA_DIST=*.edp all.edp
+
+all.edp:
+	(echo "NoUseOfWait=true;int verbosityy=verbosity;"; \
+	for i in *`ls *.edp|grep -v -E '^(all|regtests|makeref|ref)\.edp$$'` ; do  \
+		echo ' cout << "--------- file : '$$i' --------------------------------------------------------" << endl;' ;\
+		echo "verbosity=verbosityy;" ; \
+		echo \{ include \"$$i\"\;\}\; ;\
+		echo ' cout << "------------------------------------------------------------------------------ " << endl;' ;\
+	done) > $@
+
+freefem++.pref:
+	echo loadpath = \"../examples++-load/\" >freefem++.pref
+	echo loadpath += \"./\" >>freefem++.pref
+
diff --git a/examples++-eigen/Stokes-eigen.edp b/examples++-eigen/Stokes-eigen.edp
new file mode 100644
index 0000000..b478225
--- /dev/null
+++ b/examples++-eigen/Stokes-eigen.edp
@@ -0,0 +1,53 @@
+// remark: the sign of p is correct 
+real s0=clock();
+mesh Th=square(20,20);
+fespace Xh(Th,P2);
+fespace Mh(Th,P1);
+fespace XhxXhxMh(Th,[P2,P2,P1]);
+
+Xh u1,u2;
+Mh p;
+
+real alpha=0;
+real  nu=1;
+int i=0,iter=0;
+
+varf vfStokes ([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +        dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            - p*dx(v1) - p*dy(v2)
+            - dx(u1)*q - dy(u2)*q
+           )
+  + on(1,2,3,4,u1=0,u2=0) 
+;
+varf b([u1,u2,p],[v1,v2,q]) = int2d(Th)(  u1*v1+u2*v2+p*q*0.) ; // no  Boundary condition
+
+matrix A= vfStokes(XhxXhxMh,XhxXhxMh,solver=UMFPACK,factorize=0); 
+matrix B= b(XhxXhxMh,XhxXhxMh,solver=CG,eps=1e-20); 
+
+real sigma=0;
+int nev=20;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+XhxXhxMh[int] [eu1,eu2,ep](nev);   // to store nev eigen vector
+
+int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eu1,tol=1e-10,maxit=0,ncv=0);
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+
+for (int i=0;i<k;i++)
+{
+  cout << " valeur propre : " << i << "  : " << ev[i] << endl;
+  u1=eu1[i];
+  u2=eu2[i];
+  p=ep[i];
+
+  // FFCS: changed to 3D view
+  plot([u1,u2],p,cmm="Eigen  Vector "+i+" valeur =" + ev[i]  ,value=1,ArrowSize=-1.6,dim=3,fill=1);
+}
+
+cout << "CPU " << clock()-s0 << "s " << endl;     
+assert(abs(ev[0]-52.3471) < 0.1); 
diff --git a/examples++-eigen/VP-Steklov-Poincare.edp b/examples++-eigen/VP-Steklov-Poincare.edp
new file mode 100644
index 0000000..fa54044
--- /dev/null
+++ b/examples++-eigen/VP-Steklov-Poincare.edp
@@ -0,0 +1,22 @@
+//  Eigen Valeur of Stelov Poincare Problem of Laplacian Operator
+// in FreeFem++ 
+int[int] l4=[1,1,1,1];
+mesh Th=square(50,50,[x,y],label=l4);
+fespace Vh(Th,P1);
+
+
+macro Grad(u) [dx(u),dy(u)]//
+real sigma = 1;// 
+varf vA(u,v)=int1d(Th)(-sigma*u*v)+int2d(Th)(Grad(v)'*Grad(u)) ; //'
+varf vM(u,v)= int1d(Th)(u*v);
+matrix A = vA(Vh,Vh,solver=sparsesolver);
+matrix B = vM(Vh,Vh);
+int nev = 20;
+real[int] ev(nev);
+Vh[int] eV(nev);
+int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eV);
+k=min(k,nev); //  some time the number of converged eigen value is  greater then nev..
+cout << ev <<endl;
+for(int i=0;i<k;++i)
+ 	plot(eV[i],cmm=" vp " + ev[i],wait=1,dim=3,fill=1);
+ 
\ No newline at end of file
diff --git a/examples++-eigen/WGM-sphere.edp b/examples++-eigen/WGM-sphere.edp
new file mode 100644
index 0000000..53044cc
--- /dev/null
+++ b/examples++-eigen/WGM-sphere.edp
@@ -0,0 +1,111 @@
+//Script for FreeFem++cs  http://www.ann.jussieu.fr/~lehyaric/ffcs/index.htm
+//to compute WG eigen vector (magnetic field) and value (wave vector)
+// of axially symmetrical dielectric resonators
+// See Chaper 9 the example Whispering gallery modes of teh DOC. 
+
+
+//Developed by I. S. Grudinin at JPL/Caltech
+//Copyright 2012 California Institute of Technology. Government sponsorship acknowledged.
+//If this script was helpful in a project that resulted in a publication, please cite our paper:
+//``Finite element modeling of coupled optical microdisk resonators for displacement sensing,''
+//I. S. Grudinin and Nan Yu (2012)
+//    J. Opt. Soc. Am. B
+
+//based on "Traceable 2-D finite-element simulation of the whispering-gallery modes of axisymmetric electromagnetic resonators"
+//by M. Oxborrow
+//IEEE TRANSACTIONS ON MICROWAVE THEORY AND TECHNIQUES  Volume: 55   Issue: 6   Pages: 1209-1218
+
+real radius=36; //approximate radius of the cavity
+real yb=-10,yt=-yb; //window yb=bottom and yt=top coordinates
+real xl=radius-5,xr=radius+3; //window xl=left and xr=right coordinates
+real angle=asin((yt)/radius); //angle of the sphere segment to model in radians
+int Nm=60;  	//number of mesh vertices per border 
+real ne=1.46; //n_e-extraordinary refractive index (root of permittivity parallel to z-axis, epara)
+real no=1.46; //n_o-ordinary refractive index (root of permittivity orthogonal to z-axis, eorto)
+real nm=1;     //refractive index of surrounding medium (air)
+
+int nev=4; // number of eigen values to find
+
+int M=213;	//azimuthal mode order ~ 2Pi*n*R/lambda
+real alpha=1; 	//penalty term
+
+//describing the mesh:
+border W1l(t=0,1) { x=xl+(radius*cos(angle)-xl)*(1-t); y=yt; label=1;}  // window upper border left
+border W1r(t=0,1) { x=xr-(xr-radius*cos(angle))*(t); y=yt; label=1;}  	// window upper border right
+border W2(t=0,1) { x=xr; y=yb+(yt-yb)*t; label=1;}  			// window right border
+border W3l(t=0,1) { x=xl+(radius*cos(angle)-xl)*(t); y=yb; label=1;}  	// window lower border left
+border W3r(t=0,1) { x=xr-(xr-radius*cos(angle))*(1-t); y=yb; label=1;}  // window lower border right
+border W4(t=0,1) { x=xl; y=yt-(yt-yb)*t; label=1;} 			// window left border
+border S(t=0,1) { x=radius*cos((t-0.5)*2*angle); y=radius*sin((t-0.5)*2*angle); label=2;}  //sphere segment
+mesh Th = buildmesh(W1r(Nm/4)+W1l(Nm/4)+W4(Nm)+W3l(Nm/4)+W3r(Nm/4)+W2(Nm)+S(Nm));
+plot (Th, WindowIndex = 0);
+
+
+//setting subdomain parameters, i.e. refractive indices of resonator and surrounding air box
+fespace Ph(Th, P0);  
+Ph reg=region; // function that returns region number of a point XY
+int ncav=reg(xl+1, 0);  // cavity
+int nair=reg(xr-1, 0);		//air
+Ph eorto=no^2*(region==ncav)+nm^2*(region==nair);  //subdomains for epsilon values inside and outside the resonators
+Ph epara=ne^2*(region==ncav)+nm^2*(region==nair);  //subdomains for epsilon values inside and outside the resonators
+
+//supplementary variables to store eigenvectors, defined on mesh Th with P2 elements - Largange quadratic.
+fespace Supp(Th, P2);
+Supp eHsqr;
+
+//3d vector FE space 
+fespace Vh(Th,[P2,P2,P2]);
+Vh [Hr, Hphi, Hz], [vHr, vHphi, vHz]; //magnetic field components on Vh space and test functions vH
+
+real sigma =(M/(ne*radius))^2+2; // value of the shift (k^2), where the modes will be found
+
+//boundary condition macros
+macro EWall(Hr,Hphi, Hz) (dy(Hr)-dx(Hz)+Hr*N.x+Hz*N.y-epara*(Hz*M-dy(Hphi)*x)*N.y+eorto*(Hphi-Hr*M+dx(Hphi)*x)*N.x) // eom
+macro MWall(Hr,Hphi, Hz) (Hphi+Hz*N.x-Hr*N.y+epara*(Hz*M-dy(Hphi)*x)*N.x+eorto*(Hphi-Hr*M+dx(Hphi)*x)*N.y ) // eom
+//b matrix (see freefem++ manual, section 9 - eigenvalue problems)
+varf b([Hr, Hphi, Hz], [vHr, vHphi, vHz]) = int2d(Th)( x*(Hr*vHr+Hphi*vHphi+Hz*vHz) );
+// OP = A - sigma B ; // the shifted matrix
+varf op([Hr, Hphi, Hz], [vHr, vHphi, vHz])=
+int2d(Th)(
+(
+	(eorto*(vHphi*Hphi-M*(vHphi*Hr+Hphi*vHr)+M^2*vHr*Hr)+epara*M^2*vHz*Hz)/x   //A/r
+	+eorto*(dx(vHphi)*(Hphi-M*Hr)+dx(Hphi)*(vHphi-M*vHr))-epara*M*(vHz*dy(Hphi)+Hz*dy(vHphi)) //B
+	+x*(eorto*dx(vHphi)*dx(Hphi)+epara*((dx(vHz)-dy(vHr))*(dx(Hz)-dy(Hr))+dy(vHphi)*dy(Hphi))) //C
+)/(eorto*epara)
++alpha*(
+	(vHr*Hr-M*(vHphi*Hr+Hphi*vHr)+M^2*vHphi*Hphi)/x  //D/r
+	+(dx(vHr)+dy(vHz))*(Hr-M*Hphi)+(vHr-M*vHphi)*(dx(Hr)+dy(Hz)) //E
+	+x*(dx(vHr)+dy(vHz))*(dx(Hr)+dy(Hz))  //F
+)  
+-sigma*x*(vHr*Hr+vHphi*Hphi+vHz*Hz)
+)
+//electric wall boundary condition on the boundary of computation domain
++int1d(Th,1)(EWall(Hr,Hphi,Hz)*EWall(vHr, vHphi, vHz));
+
+//setting sparce matrices and assigning the solver UMFPACK to solve eigenvalue problem
+matrix B=b(Vh,Vh,solver=UMFPACK);
+matrix OP= op(Vh,Vh,solver=UMFPACK);
+
+real[int] ev(nev); // to store the nev eigenvalue
+Vh[int] [eHr,eHphi,eHz](nev); // to store the nev eigenvector
+//calling ARPACK on sparce matrices with the assigned solver UMFPACK:
+int k=EigenValue(OP,B,sym=true,sigma=sigma,value=ev,vector=eHr,tol=1e-10,maxit=0,ncv=0);
+
+k=min(k,nev); //  sometimes the number of converged eigen values 
+              // can be greater than nev;
+
+
+//file to output mode values
+ofstream f("modes.txt");
+//setting number of digits in the file output
+int nold=f.precision(11);
+
+
+for (int i=0;i<k;i++)
+{
+ real lambda=2*pi/sqrt(ev[i]);
+ eHsqr=(sqrt(eHr[i]^2+eHphi[i]^2+eHz[i]^2)); // intensity from magnetic field components
+ plot(eHsqr,WindowIndex=i, value=1, nbiso=20,LabelColors=1, aspectratio=1, cmm="Mode "+i+", lambda="+lambda+", F="+(299792.458/lambda));
+ f << "Mode "<<i<<", ka=" << sqrt(ev[i])*radius << endl;
+
+};
diff --git a/examples++-eigen/all.edp b/examples++-eigen/all.edp
new file mode 100644
index 0000000..2b9db97
--- /dev/null
+++ b/examples++-eigen/all.edp
@@ -0,0 +1,49 @@
+NoUseOfWait=true;int verbosityy=verbosity;
+ cout << "--------- file : BeamEigenValue.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "BeamEigenValue.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : BeamEigenValueperio.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "BeamEigenValueperio.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Lap3dEigenValue.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Lap3dEigenValue.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LapComplexEigenValue.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LapComplexEigenValue.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LapEigenValue.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LapEigenValue.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LapEigenValueFunc.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LapEigenValueFunc.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LapnosymEigenValue.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LapnosymEigenValue.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Stokes-eigen.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Stokes-eigen.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : VP-Steklov-Poincare.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "VP-Steklov-Poincare.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : WGM-sphere.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "WGM-sphere.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : free-cyl-axi.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "free-cyl-axi.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : neuman.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "neuman.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
diff --git a/examples++-eigen/free-cyl-axi.edp b/examples++-eigen/free-cyl-axi.edp
new file mode 100644
index 0000000..363e6fc
--- /dev/null
+++ b/examples++-eigen/free-cyl-axi.edp
@@ -0,0 +1,89 @@
+//  Computation of the eigen value and eigen vector of the 
+// 
+// ----------------------------------------
+// we use the inverse shift mode 
+// the shift is given with sigma real
+// -------------------------------------
+// Linear elastisitic problem in axisym. model. 
+// thank to http://www.me.mtu.edu/~mavable/MEEM4405/Axi.pdf
+//  for the model.
+//  the benchmark  case is
+// thank form comsol and ansys 
+// the comsol sol testcaes:  Eigenfrequency Analysis of a Free Cylinder
+// The model is taken from NAFEMS Free Vibration Benchmarks
+// 1. F. Abassian, D.J. Dawswell, and N.C. Knowles, Free Vibration Benchmarks, 
+// Volume 3, NAFEMS, Glasgow, 1987
+//  the comsol data: 
+// http://www.comsol.com/model/download/40173/free_cylinder.pdf 
+// F. Hecht may 2014 ??
+// warning: Axi / 0x   
+//  r == y,  
+real[int] freqref=[0,243.53,377.41,394.11,397.72,405.28];   
+verbosity=0;
+real ccc= 1; // coef scale of matrix 
+real E =  2.e11*ccc ;// 72e9;
+real nu = 0.3;
+real rho = 8000*ccc;//2700;//
+real freq0 = 100; 
+real mu = E/(2.*(1.+nu));
+real lambda = E*nu/((1.+nu)*(1.-2.*nu));
+real R1 = 1.8, R2 = R1+ 0.4, L = 10;
+int nn = 40, nz = 40;
+border cc1(t=0,2*pi){ x = R1*cos(t); y=R1*sin(t); }
+border cc2(t=0,2*pi){ x = R2*cos(t); y=R2*sin(t); }
+int NN = 10; 
+mesh Th=square(L*NN,(R2-R1)*NN,[x*L, (1-y)*R1+y*R2]); 
+plot(Th, wait=1); 
+
+
+real shift = 1; // make a shift because 0 mode ... 
+real C11=  2*mu  + lambda  ; 
+real C12 =  lambda ;
+real C44=  2*mu;
+func Amat = [  [C11, C12, C12, 0.  ],
+               [C12, C11, C12,  0. ],
+               [C12, C12, C11,  0. ],
+               [0. , 0. , 0.,   C44]
+             ];
+
+fespace Vh(Th,[P2,P2]);
+Vh [u1,u2], [v1,v2];
+func dr=dy; 
+func r=y; 
+
+macro Strainaxi(ux,ur)  [dx(ux),dr(ur),ur/r, dr(ux)+dx(ur) ] // EOM
+  
+varf vLame([u1,u2],[v1,v2])=
+  int2d(Th)(  (Strainaxi(v1,v2)'*(Amat*Strainaxi(u1,u2))  
+  - ([u1,u2]'*[v1,v2]*rho*shift) )*y )
+  ;
+varf vMass([u1,u2],[v1,v2])=
+  int2d(Th)( ( [v1,v2]'*[u1,u2]*rho )*y );
+ 
+matrix A= vLame(Vh,Vh,solver=sparsesolver); 
+matrix B= vMass(Vh,Vh,solver=CG,eps=1e-20); 
+
+int nev=6;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+Vh[int] [eu1,eu2](nev);   // to store nev eigen vector
+
+
+int k=EigenValue(A,B,sigma=shift,sym=true,value=ev,vector=eu1,tol=1e-20);
+
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+int nerr=0;
+for (int i=0;i<k;i++)
+{
+    real e = ev[i] ;
+    real freq = sqrt(abs(e))/(pi*2) ;
+    if( abs(freq-freqref[i]) > 0.3) nerr++;
+  cout << i << " ev " <<  e << " freq = " << freq  << "Hz, err=" << abs(freq-freqref[i]) <<endl;   
+  real coef= 0.5/eu1[i][].linfty;
+  mesh Thm=movemesh(Th,[x+eu1[i]*coef,y+eu2[i]*coef]);
+  //plot(Th,Thm, wait=1,cmm=i+"/"+k+"coef  amplification = "+coef );
+ // medit("Thm-"+ev[i],Thm,wait=1);
+ plot(Thm,Th,wait=1,cmm=i+"/"+k+"coef  amplification = "+coef +" freq " + freq + "Hz"  , fill=1);
+}
+assert(nerr==0);
\ No newline at end of file
diff --git a/examples++-eigen/neuman.edp b/examples++-eigen/neuman.edp
new file mode 100644
index 0000000..cf36a72
--- /dev/null
+++ b/examples++-eigen/neuman.edp
@@ -0,0 +1,30 @@
+border ccc(t=0,2*pi){x=cos(t);y=sin(t);}
+mesh Th=buildmesh(ccc(10));
+//mesh Th=readmesh("Th.msh");
+fespace Vh(Th,P2);
+Vh u1,u2;
+real sigma = 1e-5;
+
+varf  a(u1,u2)= int2d(Th)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) - sigma* u1*u2 );
+
+                   
+varf b([u1],[u2]) = int2d(Th)(  u1*u2 ) ; // no  Boundary condition
+
+matrix A= a(Vh,Vh,solver=Crout,factorize=1); 
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+
+int nev=20;  // number of computed eigen valeu close to sigma
+
+real[int] ev(nev); // to store nev eigein value
+Vh[int] eV(nev);   // to store nev eigen vector
+
+int k=EigenValue(A,B,sym=true,sigma=sigma,value=ev,vector=eV,tol=1e-10,maxit=0,ncv=0);
+k=min(k,nev); //  some time the number of converged eigen value 
+              // can be greater than nev;
+
+for(int i=0;i<k;i++){
+  cout << " Valeur propre " << i << " = " << ev[i] << endl;
+
+  // FFCS: add 3D view
+  plot(eV[i],dim=3,fill=1);
+}
diff --git a/examples++-eigen/regtests.edp b/examples++-eigen/regtests.edp
new file mode 100644
index 0000000..5abbc50
--- /dev/null
+++ b/examples++-eigen/regtests.edp
@@ -0,0 +1,21 @@
+NoUseOfWait=true;int verbosityy=verbosity;
+ cout << "--------- file : BeamEigenValue.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "BeamEigenValue.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : BeamEigenValueperio.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "BeamEigenValueperio.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LapEigenValue.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LapEigenValue.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Stokes-eigen.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Stokes-eigen.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : neuman.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "neuman.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
diff --git a/examples++-load/._bilapP3-hct-like.edp b/examples++-load/._bilapP3-hct-like.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-load/._bilapP3-hct-like.edp differ
diff --git a/examples++-load/._ffrandom.edp b/examples++-load/._ffrandom.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-load/._ffrandom.edp differ
diff --git a/examples++-load/._iohd5-beam-2d.edp b/examples++-load/._iohd5-beam-2d.edp
new file mode 100644
index 0000000..361d6a9
Binary files /dev/null and b/examples++-load/._iohd5-beam-2d.edp differ
diff --git a/examples++-load/._iohd5-beam-3d.edp b/examples++-load/._iohd5-beam-3d.edp
new file mode 100644
index 0000000..361d6a9
Binary files /dev/null and b/examples++-load/._iohd5-beam-3d.edp differ
diff --git a/examples++-load/._msh3.hpp b/examples++-load/._msh3.hpp
new file mode 100755
index 0000000..14f037e
Binary files /dev/null and b/examples++-load/._msh3.hpp differ
diff --git a/examples++-load/._testFE-PkEdge.edp b/examples++-load/._testFE-PkEdge.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-load/._testFE-PkEdge.edp differ
diff --git a/examples++-load/APk-AdaptEpsDeltaPk.edp b/examples++-load/APk-AdaptEpsDeltaPk.edp
new file mode 100755
index 0000000..c7afabc
--- /dev/null
+++ b/examples++-load/APk-AdaptEpsDeltaPk.edp
@@ -0,0 +1,43 @@
+load "MetricPk"
+load "Element_P3";	
+load "Element_P4";
+
+int nIter=4;
+mesh Th=square(20,20,[x,y]);
+//fespace Vh(Th,P1); int kDeg=1;  //degr� des FE utilis�s
+//fespace Vh(Th,P2); int kDeg=2;  //degr� des FE utilis�s
+fespace Vh(Th,P3); int kDeg=3;  //degr� des FE utilis�s
+int rdeg=1;	 //on approche le gradient ou des d�riv�es d'ordre sup�rieur
+
+real ratio = 2.;//number of triangles is multiplied by ratio at each step
+real rmax = 1; 	//max triangle size desired.
+
+Vh u,v;
+fespace Metric(Th,[P1,P1,P1]);
+Metric [m11,m12,m22];
+////pour de l'adaptation isotrope
+//problem EpsDelta(u,v) = 
+//		int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))+
+//		on(1,u=1)+on(2,3,4, u=0);
+//avec une forte anisotropie, et des singularit�s aux coins.
+real eps=0.01;
+problem EpsDelta(u,v) = 
+		int2d(Th)(eps*dx(u)*dx(v)+eps*dy(u)*dy(v)+(dx(u)+dy(u))*v)+
+		on(1,u=atan(10*x*(1-x)))+on(2,3,4, u=0);
+
+//real massRef = 1000*Th.nt;	
+real massRef = Th.nt/2;
+EpsDelta;
+plot(u, wait=1);
+for(int i=0; i<nIter; i++){
+	plot(Th, wait=1); //on affiche avant de tout changer
+	plot(u, wait=1);
+	[m11,m12,m22]=[0,0,0];	//absolument crucial...
+	m11[]=MetricPk(Th,u,kDeg=kDeg,rDeg=rdeg, mass=massRef);
+	Th = adaptmesh(Th,m11,m12,m22,IsMetric=true);
+	cout << "expected number of triangles : " << massRef/20 << "; obtained " << Th.nt << "\n";
+	EpsDelta;
+	massRef=ratio*massRef;
+}
+
+plot(Th, wait=1, ps="triangulationEpsDelta.ps");
\ No newline at end of file
diff --git a/examples++-load/APk-ExplicitPkTest.edp b/examples++-load/APk-ExplicitPkTest.edp
new file mode 100755
index 0000000..5ca2d90
--- /dev/null
+++ b/examples++-load/APk-ExplicitPkTest.edp
@@ -0,0 +1,22 @@
+load "MetricPk"
+
+int kDeg=4;
+int nIter=5;
+mesh Th=square(20,20,[2*x-1,2*y-1]);
+real c=5;
+func f = x^2*y + y^3 + tanh(c*(-2*x + sin(5*y)));
+real ratio = 1.3;
+//real massRef=40*Th.nt; //40 : constante pour passer de la masse au nb de triangles (?).
+real massRef=Th.nt/2; //The number of triangles is approx twice the mass
+
+fespace Metric(Th,[P1,P1,P1]);
+Metric [m11,m12,m22];
+for(int i=0; i<nIter; i++){
+	plot(Th,wait=true);
+	[m11,m12,m22]=[0,0,0];
+	m11[]=MetricPk(Th,f,kDeg=kDeg,rDeg=1,mass=massRef,MetricType=1,TriangulationType=1);
+	Th = adaptmesh(Th,m11,m12,m22,IsMetric=true);
+	massRef=massRef*ratio;
+}
+plot(Th,wait=true,ps="lastMesh.ps");
+
diff --git a/examples++-load/APk-FreeFemQA.edp b/examples++-load/APk-FreeFemQA.edp
new file mode 100755
index 0000000..2fa2901
--- /dev/null
+++ b/examples++-load/APk-FreeFemQA.edp
@@ -0,0 +1,28 @@
+load "FreeFemQA"
+
+mesh Th=square(1,1,[x,y]);
+
+func scal = 1/(x+0.2)^2;
+
+//func scal = 5;
+
+func mxx=100*scal;
+func mxy=0;
+func myy=scal;
+
+Th=adaptmesh(Th,4*scal,0,4*scal,IsMetric=true);
+Th=MeshGenQA(Th,mxx,mxy,myy,exportToMathematica=true,exportMetricToMathematica=true,finalRefine=false);
+plot(Th,wait=true,ps="IsoFFMesh.ps");
+
+//Th=readmesh("triQA.msh");
+plot(Th,ps="QAMesh.ps");
+
+
+//mesh Th=readmesh("/Users/jean-mariemirebeau/Library/Developer/Xcode/DerivedData/DelaunayFlip-deaxqdiomhuvirblsdlxiubujmam/Build/Products/Debug/Th.msh");
+//plot(Th);
+
+//Le sens Geometry->FF a l'air de marcher.
+//Maintenant, il faut le sens inverse.
+
+//mesh Th=square(1,1,[x,y]);
+//savemesh(Th,"ThFF.msh");
\ No newline at end of file
diff --git a/examples++-load/APk-MetricPk.edp b/examples++-load/APk-MetricPk.edp
new file mode 100755
index 0000000..a8597cd
--- /dev/null
+++ b/examples++-load/APk-MetricPk.edp
@@ -0,0 +1,31 @@
+load "MetricPk"
+
+mesh Th=square(3,3,[x,y]);
+fespace Metric(Th,[P1,P1,P1]);
+Metric [m11,m12,m22];
+
+//fespace Deriv(Th,[P1,P1,P1]);
+//Deriv [D1,D2,D3]; 
+//m11[]=MetricPk(Th,(x^2+100*y^2)/2,kDeg=1,rDeg=1,Derivatives=D1[]);
+
+
+fespace Deriv(Th,[P1,P1,P1,P1]);
+Deriv [D1,D2,D3,D4]; 
+//m11[]=MetricPk(Th,(x^3+2*3*x^2*y+3*3*x*y^2+4*y^3)/6,kDeg=2,rDeg=1,Derivatives=D1[]);
+m11[]=MetricPk(Th,(x^3/100+y^3)/6,kDeg=2,rDeg=1,Derivatives=D1[]);
+
+//fespace Deriv(Th,[P1,P1,P1,P1,P1]);
+//Deriv [D1,D2,D3,D4,D5]; 
+//m11[]=MetricPk(Th,(x^4+2*4*x^3*y+3*6*x^2*y^2+4*4*x*y^3+5*y^4)/24,kDeg=3,rDeg=1,Derivatives=D1[]);
+//m11[]=MetricPk(Th,(x^3+2*3*x^2*y+3*3*x*y^2+4*y^3)/6,kDeg=3,rDeg=1,Derivatives=D1[]);
+
+//fespace Deriv(Th,[P1,P1,P1,P1,P1,P1]);
+//Deriv [D1,D2,D3,D4,D5,D6]; 
+//m11[]=MetricPk(Th,(x^5+2*5*x^4*y+3*10*x^3*y^2+4*10*x^2*y^3+5*5*x*y^4+6*y^5)/120,kDeg=4,rDeg=1,Derivatives=D1[]);
+//m11[]=MetricPk(Th,(x^4+2*4*x^3*y+3*6*x^2*y^2+4*4*x*y^3+5*y^4)/24,kDeg=4,rDeg=1,Derivatives=D1[]);
+
+
+//plot(m11,m12,m22,dim=3,wait=1);
+cout << m11[] << endl;
+cout << D1[] << endl;
+
diff --git a/examples++-load/BEC.cpp b/examples++-load/BEC.cpp
new file mode 100644
index 0000000..93532fd
--- /dev/null
+++ b/examples++-load/BEC.cpp
@@ -0,0 +1,34 @@
+// Example C++ function "myfunction", dynamically loaded into "load.edp"
+// ---------------------------------------------------------------------
+// $Id$
+#include <ff++.hpp>
+using namespace Fem2D;
+double BECtrap(Stack stack,KN<double> * const &  pd)
+{
+  MeshPoint &mp= *MeshPointStack(stack); // the struct to get x,y, normal , value 
+  double *d = *pd;
+  double x= mp.P.x; // get the current x value
+  double y= mp.P.y; // get the current y value
+  double z= mp.P.y; // get the current y value
+  double x2=x*x, y2=y*y,z2=z*z, r2 = x2+y2, r4 = r2*r2;
+  long  n = pd->N(); 
+
+  // cout << "x = " << x << " y=" << y << " " << sin(x)*cos(y) <<  endl;
+  double ret ;
+  if( n ==4)
+    ret = x2*d[0] + y2*d[1] + z2*d[2] + r4*d[3] ; 
+  else  if(n==6)
+    {
+      double s = sin(d[5]*z);
+      ret = x2*d[0] + y2*d[1] + z2*d[2] + r4*d[3] + d[4]*s*s; 
+    }
+  else ffassert(0); // 
+  return ret; 
+}
+
+
+void init(){
+  Global.Add("BECtrap","(",new OneOperator1s_<double,KN<double> * ,E_F0mps >(BECtrap));
+}
+
+LOADFUNC(init);
diff --git a/examples++-load/BasicMath.h b/examples++-load/BasicMath.h
new file mode 100755
index 0000000..083ba8b
--- /dev/null
+++ b/examples++-load/BasicMath.h
@@ -0,0 +1,113 @@
+//
+//  BasicMath.h
+//  FastMarchingBundle
+//
+//  Created by Jean-Marie Mirebeau on 11/07/11.
+//  Copyright 2011 UPMC. All rights reserved.
+//
+#ifndef BASIC_MATH
+#define BASIC_MATH
+#include <fstream>
+#include <sstream>
+#include "assert.h"
+using namespace std;
+
+/****** A few common functions which are absent in C++ *******/
+
+template<class ring> inline ring square(ring u){return u*u;}
+template<class ring> inline ring cube(ring u){return u*u*u;}
+inline double sqrt3(double r){return r>=0 ? pow(r,1/3.) : -pow(-r,1/3.);}
+template<class ordered_zero> inline int sign(ordered_zero a) {return a>0 ? 1 : (a==ordered_zero(0) ? 0 : -1);}
+
+inline int mod (int a, int N) {const double u = a%N; return u>=0 ? u : u+N;} //math modulo. Beware : % is wrong for negative numbers
+inline int smallmod(int a, int N) {const int NHalf = N/2; return -NHalf+mod(a+NHalf,N);}//math symmetrized modulo, in [-N/2,N/2] or so.
+//inline int round0(double a){return a>0 ? ceil(a-0.5) : floor(a+0.5);} //rounding towards the closest integer to 0. 
+
+/****** Some debug macros *****/
+//try_debug helps to locate errors in combination with external libraries
+#if DEBUG
+#define assert_msg(condition, message) if (! (condition)) { std::cerr << message << " : "; assert(condition); assert(false); } else {}
+#define try_debug_msg(instructions, message) try{ instructions ;} catch(...) {assert_msg(false, message);}
+#define try_debug(instructions) try{ instructions ;} catch(...) {assert(false);}
+#else
+#define assert_msg(condition, message) assert(condition)
+#define try_debug_msg(instructions, message) { instructions ;}
+#define try_debug(instructions) { instructions ;}
+#endif
+
+/***** Display of mathematical structures in diverse formats *******/
+//typical usage : some_ostream << some_Format_Math << data1 << data2 <<data3 << endl;
+
+enum Format_Math {Standard, Mathematica}; //more formats to come if required 
+
+class ostream_math { //This class only contains a reference to an ostream, and a math format type
+public:
+    Format_Math format;
+    ostream & os;
+    ostream_math(ostream & OS, Format_Math Format) : os(OS), format(Format){}
+};
+
+inline ostream_math operator << (ostream & f, Format_Math Format){return ostream_math(f,Format);}
+extern ostream_math coutMath; 
+// ostream_math coutMath= cout << Mathematica;
+//default bahavior : ostream
+inline ostream_math operator << (ostream_math f, ostream & (*func)(ostream &)){ func(f.os); return f;}
+template<class E> inline ostream_math operator << (ostream_math f, const E & n){ f.os << n; return f;}
+
+//Display of doubles : 1.5e+34 -> 1.5*10^+34
+inline ostream_math operator << (ostream_math f, double x){
+    if(f.format==Mathematica) {
+        ostringstream oss; oss << x; const char * px = oss.str().c_str();
+        if(px[0]=='N') f<<"Indeterminate"; 
+        else if(px[0]=='i') f<<"Infinity"; 
+        else if(px[0]=='-' && px[1]=='i') f<<"-Infinity"; 
+        else {
+            for(int i=0; i<20 && px[i]>0; i++) 
+                if(px[i]=='e') {
+                    char Buffer[20]; for(int j=0; j<i; j++) Buffer[j]=px[j]; Buffer[i]=0;
+                    f << Buffer << "*10^" << px+i+1; return f;}
+            f << px;
+        } //if px[0]
+    } else f.os << x;
+    return f;
+}
+
+template <class ForwardIterator> void print_array(ostream_math f, ForwardIterator first, ForwardIterator last, bool one_per_line=false) {
+    string sep = one_per_line ? ",\n" : ",";
+    f<<"{";
+    if(first!=last) f<<*first++; 
+    while(first!=last) f << sep << *first++;
+    f<<"}";
+}
+
+/*
+//Display of arrays
+template<class E> void print_array(ostream & f, const E * tab, int N, bool one_per_line=false){
+    if(one_per_line) for(int i=0; i<N; i++) f << tab[i] << endl;
+    else for(int i=0; i<N; i++) f << tab[i] << " ";
+}
+
+template<class E> void print_array(ostream_math f, const E * tab, int N, bool one_per_line=false){
+    if(f.format==Mathematica) {
+        if(N==0) {f << "{}"; return;}
+        f << "{"; 
+        for(int i=0; i<N; i++) {f << tab[i]; if(i<N-1) f << ",";}
+        f << "}";}
+    else {print_array(f.os, tab, N, one_per_line); return;}
+}
+
+//Sampling function values. Not the best way to do it, but how to avoid it without copy-pasting everything above ?
+template<class E> void print_array(ostream_math f, E (*func)(int), int N, bool one_per_line=false){
+    E * tab = new E [N]; for(int i=0; i<N; i++) tab[i]=func(i);
+    print_array(f, tab, N, one_per_line);
+    delete tab;
+}
+
+template<class E> inline void print_array(ostream & f, E (*func)(int), int N, bool one_per_line=false){
+    print_array(f << Standard, func, N, one_per_line);}
+ */
+
+//conversion to string
+template <class E> std::string to_string(const E & e){ostringstream oss; oss << e; return oss.str();}
+
+#endif
diff --git a/examples++-load/BernadiRaugel.cpp b/examples++-load/BernadiRaugel.cpp
new file mode 100644
index 0000000..61ccb43
--- /dev/null
+++ b/examples++-load/BernadiRaugel.cpp
@@ -0,0 +1,275 @@
+// The  P2BR finite element : the Bernadi Raugel Finite Element
+// F. Hecht, decembre 2005
+// -------------
+// See Bernardi, C., Raugel, G.: Analysis of some finite elements for the Stokes problem. Math. Comp. 44, 71-79 (1985).
+//  It is  a 2d coupled FE 
+// the Polynomial space is $ P1^2$ + 3 normals bubbles edges function $(P_2)$
+// the degre of freedom is 6 values at of the 2 componantes at the  3 vertices
+// and the 3 flux on the 3 edges  
+//   So 9 degrees of freedom and  N= 2. 
+
+// -----------------------  related files: 
+//  to check  and validate  :  testFE.edp 
+//  to get a real example   :  NSP2BRP0.edp
+// ------------------------------------------------------------
+
+// -----------------------
+
+#include <ff++.hpp>
+#include "AddNewFE.h"
+
+namespace  Fem2D {
+  
+  class TypeOfFE_P2BRLagrange : public  TypeOfFE { public:  
+    static int Data[];
+    // double Pi_h_coef[];
+    
+    TypeOfFE_P2BRLagrange(): TypeOfFE(6+3+0,
+				      2,
+				      Data,
+				      4,
+				      1,
+				      6+3*(2+2), // nb coef to build interpolation
+				      9, // np point to build interpolation
+				      0)
+    {  
+      const double gauss1=(1.-sqrt(1./3.))/2;
+      const double gauss2=1.-gauss1;
+      // faux 
+      const R2 Pt[] = { R2(0,0),R2(1,0),R2(0,1)}; 
+      // for the 3 vertices 6 coef 
+      int kk=0;
+      for (int p=0;p<3;p++)
+	{ 
+	  P_Pi_h[p]=Pt[p];
+	  pij_alpha[kk]= IPJ(kk,p,0);
+	  ++kk;
+	  pij_alpha[kk]= IPJ(kk,p,1); 
+	  ++kk;
+	}
+      // for 
+      int p=3;
+      for (int e=0;e<3;++e)
+	{ // point d'integration sur l'arete e 
+	  R2 A=Pt[VerticesOfTriangularEdge[e][0]];
+	  R2 B=Pt[VerticesOfTriangularEdge[e][1]];
+	  P_Pi_h[p]= A*gauss1+B*gauss2;
+	  //	  cout <<"\n" <<  p << " --  " << P_Pi_h[p] << " ::  " << A << " " << B << endl;
+	  pij_alpha[kk++]= IPJ(6+e,p,0); // coef = 0.5* l_e *ne_x * sge	  
+	  pij_alpha[kk++]= IPJ(6+e,p,1); // coef = 0.5* l_e *ne_y * sge	  	  
+	  p++;
+	  P_Pi_h[p]= A*gauss2+B*gauss1;
+	  // cout << p << " ++ " << P_Pi_h[p] << endl;
+	  pij_alpha[kk++]= IPJ(6+e,p,0); // coef = 0.5* l_e *ne_x * sge	  	  
+	  pij_alpha[kk++]= IPJ(6+e,p,1); // coef = 0.5* l_e *ne_y * sge	  	  
+	  p++;
+	}
+      assert(P_Pi_h.N()==p);
+      assert(pij_alpha.N()==kk);
+
+     }
+    void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+    void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const;
+  } ;
+  //                     on what     nu df on node node of df    
+ int TypeOfFE_P2BRLagrange::Data[]={
+   0,0, 1,1, 2,2,  3,4,5,
+   0,1, 0,1, 0,1,  0,0,0,
+   0,0, 1,1, 2,2,  3,4,5,
+   0,0, 0,0, 0,0,  0,0,0,
+   0,1, 2,3, 4,5,  6,7,8, 
+   0,0, 
+   0,0,
+   0,9 
+};
+
+void TypeOfFE_P2BRLagrange::Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+  {
+    const Triangle & T(K.T);
+    int k=0;
+    // coef pour les 3 sommets  fois le 2 composantes 
+    for (int i=0;i<6;i++)
+      v[k++]=1; 
+    //   integration sur les aretes 
+    for (int i=0;i<3;i++)
+      {
+	
+        R2 N(T.Edge(i).perp());
+	N  *= T.EdgeOrientation(i)*0.5 ;
+        v[k++]= N.x; 
+        v[k++]= N.y;
+        v[k++]= N.x;
+        v[k++]= N.y;
+      }
+  }
+  
+  void TypeOfFE_P2BRLagrange::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+  {
+    R2 A(K[0]), B(K[1]),C(K[2]);
+    R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+    R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+    //  $int_e_1 l0*l0 = |e_1| /3 $ et  $int_e_1 l0*l1 = |e_1| /6 $
+    //  pour avoir  flux = 1   
+    //  
+    R2 E[3]={ K.Edge(0),K.Edge(1),K.Edge(2)};
+    double l2E[3]={  (E[0],E[0]),  (E[1],E[1]),  (E[2],E[2]) };  
+    double lE[3]={  sqrt(l2E[0]), sqrt(l2E[1]), sqrt(l2E[2]) };
+    double sgE[3]={ K.EdgeOrientation(0), K.EdgeOrientation(1), K.EdgeOrientation(2)}; 
+    R2 cN[3]= { 
+      E[0].perp() *(6.*sgE[0]/l2E[0]), 
+      E[1].perp() *(6.*sgE[1]/l2E[1]),
+      E[2].perp() *(6.*sgE[2]/l2E[2]) 
+    };
+
+    val=0; 
+    
+    throwassert( val.N()>=9);
+    throwassert(val.M()==2);
+    
+    
+    val=0; 
+
+
+  if (whatd[op_id])
+    {
+      RN_ f0(val('.',0,op_id)); 
+      RN_ f1(val('.',1,op_id)); 
+      
+      f1[1]=f0[0] = l0;
+      f1[3]=f0[2] = l1;
+      f1[5]=f0[4] = l2;
+      
+      f0[6] = cN[0].x*l1*l2; // oppose au sommet 0
+      f0[7] = cN[1].x*l0*l2; // oppose au sommet 1
+      f0[8] = cN[2].x*l1*l0; // oppose au sommet 3
+      
+      f1[6] = cN[0].y*l1*l2; // oppose au sommet 0
+      f1[7] = cN[1].y*l0*l2; // oppose au sommet 1
+      f1[8] = cN[2].y*l1*l0; // oppose au sommet 3
+      
+    }
+  
+  if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+    {
+      R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+      if (whatd[op_dx])
+	{
+	  RN_ f0x(val('.',0,op_dx)); 
+	  RN_ f1x(val('.',1,op_dx)); 
+	  
+	  f1x[1]=f0x[0] = Dl0.x;
+	  f1x[3]=f0x[2] = Dl1.x;
+	  f1x[5]=f0x[4] = Dl2.x;
+	  
+	  
+	  f0x[6] = cN[0].x*(Dl1.x*l2 + Dl2.x*l1) ;
+	  f0x[7] = cN[1].x*(Dl2.x*l0 + Dl0.x*l2) ;
+	  f0x[8] = cN[2].x*(Dl0.x*l1 + Dl1.x*l0) ;
+	  
+	  f1x[6] = cN[0].y*(Dl1.x*l2 + Dl2.x*l1) ;
+	  f1x[7] = cN[1].y*(Dl2.x*l0 + Dl0.x*l2) ;
+	  f1x[8] = cN[2].y*(Dl0.x*l1 + Dl1.x*l0) ;
+	  
+	}
+      
+      if (whatd[op_dy])
+	{  
+	  RN_ f0y(val('.',0,op_dy)); 
+	  RN_ f1y(val('.',1,op_dy)); 
+	  
+	  f1y[1]=f0y[0] = Dl0.y;
+	  f1y[3]=f0y[2] = Dl1.y;
+	  f1y[5]=f0y[4] = Dl2.y;
+	  
+	  f0y[6] = cN[0].x*(Dl1.y*l2 + Dl2.y*l1) ;
+	  f0y[7] = cN[1].x*(Dl2.y*l0 + Dl0.y*l2) ;
+	  f0y[8] = cN[2].x*(Dl0.y*l1 + Dl1.y*l0) ;
+	  
+	  f1y[6] = cN[0].y*(Dl1.y*l2 + Dl2.y*l1) ;
+	  f1y[7] = cN[1].y*(Dl2.y*l0 + Dl0.y*l2) ;
+	  f1y[8] = cN[2].y*(Dl0.y*l1 + Dl1.y*l0) ;
+	}
+      
+      if (whatd[op_dxx])
+	{  
+	  
+	  
+	  RN_ f0xx(val('.',0,op_dxx)); 
+	  RN_ f1xx(val('.',1,op_dxx)); 
+	  
+	  
+	  f0xx[6] =  2*cN[0].x*Dl1.x*Dl2.x;
+	  f0xx[7] =  2*cN[1].x*Dl0.x*Dl2.x;
+	  f0xx[8] =  2*cN[2].x*Dl0.x*Dl1.x;
+	  f1xx[6] =  2*cN[0].y*Dl1.x*Dl2.x;
+	  f1xx[7] =  2*cN[1].y*Dl0.x*Dl2.x;
+	  f1xx[8] =  2*cN[2].y*Dl0.x*Dl1.x;
+	}
+      
+      if (whatd[op_dyy])
+	{  
+	  RN_ f0yy(val('.',0,op_dyy)); 
+	  RN_ f1yy(val('.',1,op_dyy)); 
+	  
+	  f0yy[6] =  2*cN[0].x*Dl1.y*Dl2.y;
+	  f0yy[7] =  2*cN[1].x*Dl0.y*Dl2.y;
+	  f0yy[8] =  2*cN[2].x*Dl0.y*Dl1.y;
+	  f1yy[6] =  2*cN[0].y*Dl1.y*Dl2.y;
+	  f1yy[7] =  2*cN[1].y*Dl0.y*Dl2.y;
+	  f1yy[8] =  2*cN[2].y*Dl0.y*Dl1.y;
+	}
+      if (whatd[op_dxy])
+	{  
+	  assert(val.K()>op_dxy);
+	  RN_ f0xy(val('.',0,op_dxy)); 
+	  RN_ f1xy(val('.',1,op_dxy)); 
+	  
+	  
+	  f0xy[6] =  cN[0].x*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+	  f0xy[7] =  cN[1].x*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+	  f0xy[8] =  cN[2].x*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+	  f1xy[6] =  cN[0].y*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+	  f1xy[7] =  cN[1].y*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+	  f1xy[8] =  cN[2].y*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+	}
+      
+    }
+  //  now remove the flux part on 6 first DL 
+  //  w_i = w_i - a_i w_{k_i} - b_i w_{l_i} ;
+  {
+    int    k[6]={ 6+1 , 6+1,  6+2 , 6+2, 6+0, 6+0 };
+    int    l[6]={ 6+2 , 6+2,  6+0 , 6+0, 6+1, 6+1 };
+
+    R2 eN[3]= { 
+      E[0].perp() *(0.5*sgE[0]),
+      E[1].perp() *(0.5*sgE[1]),
+      E[2].perp() *(0.5*sgE[2])
+    };
+
+    double a[6]={ eN[1].x , eN[1].y,   eN[2].x , eN[2].y, eN[0].x , eN[0].y};
+    double b[6]={ eN[2].x , eN[2].y,   eN[0].x , eN[0].y, eN[1].x , eN[1].y};
+    int nop=0;
+
+    int vop[last_operatortype];
+    for (int j=0;j<last_operatortype;j++)
+      if (whatd[j])
+	vop[nop++] = j;
+
+    for(int i=0;i<6;++i)
+      for(int jj=0;jj<nop;++jj)
+      {
+        int j=vop[jj];
+	val(i,0,j) -= a[i]*val(k[i],0,j)  +    b[i]*val(l[i],0,j)  ;
+	val(i,1,j) -= a[i]*val(k[i],1,j)  +    b[i]*val(l[i],1,j)  ;
+      }
+  }
+  
+}
+//  ----   cooking to add the finite elemet to freefem table --------  
+// a static variable to def the finite element 
+  static TypeOfFE_P2BRLagrange P2LagrangeP2BR;
+  //  now adding   FE in FreeFEm++  table
+  static AddNewFE P2BR("P2BR",&P2LagrangeP2BR); 
+// --- end cooking   
+} // end FEM2d namespace 
+  
diff --git a/examples++-load/BinaryIO.cpp b/examples++-load/BinaryIO.cpp
new file mode 100644
index 0000000..95a0941
--- /dev/null
+++ b/examples++-load/BinaryIO.cpp
@@ -0,0 +1,89 @@
+
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpace.hpp" 
+#include "MeshPoint.hpp"
+#include "AFunction_ext.hpp" // Extension of "AFunction.hpp" to deal with more than 3 parameters function
+using namespace Fem2D;
+
+ 
+double SaveVec(KN<double> *const & f, string *const & nome)   
+{
+  std::ofstream outfile (nome->data(),ios_base::binary);
+  // To access value at node i of vector N, do as follow: *(N[0]+i)
+  // Explanation (C++ for dummies as I am ;-):
+  //   N         is an alias to the KN object.
+  //   N[0]      is a pointer to the first element of the vector.
+  //   N[0]+i    is a pointer to the ith element of the vector.
+  //   *(N[0]+i) is the value of the ith element of the vector.
+ 
+  long int nn = f->N(); // get number of nodes
+  long int dim=nn;
+  outfile.write ((char*) &dim, sizeof(long int));//write the dimension of the vector
+  double ftemp ;
+  for(long int i=0; i<nn; i++) {
+    
+    ftemp = *(f[0]+i) ;
+    outfile.write ((char*) &ftemp, sizeof(double));
+  }
+  outfile.close();
+  return 0.0;  // dummy return value.
+}
+
+ 
+double LoadVec(KN<double> *const & ww, string *const & nome)   
+{
+  std::ifstream infile (nome->data(),ios_base::binary);
+  long int dim;
+  infile.read((char *) &dim, sizeof(long int));
+  double dtemp;
+  for(long int i=0; i<dim; i++)
+   {
+   infile.read((char *) &dtemp, sizeof(double));
+    *(ww[0]+i)=dtemp ;
+    }
+  return 0.0;  // dummy return value.
+}
+
+ 
+double LoadFlag(long int *const & ww, string *const & nome)   
+{
+  std::ifstream infile (nome->data(),ios_base::binary);
+  long int flag;
+  infile.read((char *) &flag, sizeof(long int));
+  *ww=flag;
+  return 0.0;  // dummy return value.
+}
+
+double flag(long int *const & FLAG,string *const &nome)   
+{
+  std::ofstream outfile (nome->data(),ios_base::binary);
+long int Flag;
+ Flag= *FLAG;   
+ outfile.write ((char*) &Flag, sizeof(long int));
+outfile.close();
+ return 0.0;
+}
+
+
+
+//   add the function name to the freefem++ table 
+/*  class Init { public:
+  Init();
+};	
+$1 */
+static void Load_Init(){	
+		
+  Global.Add("LoadVec","(",new OneOperator2_<double,  KN<double>*, string* >(LoadVec)); 
+Global.Add("LoadFlag","(",new OneOperator2_<double,long int*, string* >(LoadFlag));
+  Global.Add("SaveVec","(",new OneOperator2_<double,KN<double>*, string* >(SaveVec));
+ Global.Add("flag","(",new OneOperator2_<double,long int*,string* >(flag));  
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/DxWriter.cpp b/examples++-load/DxWriter.cpp
new file mode 100644
index 0000000..05393e0
--- /dev/null
+++ b/examples++-load/DxWriter.cpp
@@ -0,0 +1,351 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : 
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Sala Lorenzo
+// E-MAIL   : salalo80 at gmail.com
+//
+
+#include "mode_open.hpp"
+#include <iostream>
+#include <cfloat>
+#include <cmath>
+#include <iterator>
+using namespace std;
+#include "ff++.hpp"
+using namespace Fem2D;
+
+
+/*!The class DxWriter permits to save in opendx format a "field" 
+(in the dx-language a "field" means the values of a function f(x,y,z) on a grid),
+a time series (an ordered collection of "fields", so we have field0=f(x,y,z,t0), field1=f(x,y,z,t1)
+and so on).
+DxWriter creates two files: one with extension .data where it puts the position of the grid, the connessions, 
+the values; and one with extension.dx where it puts the time series.
+Now you can save only scalar fields. 
+An example <code>
+load "DxWriter"
+mesh Th=square(5,5);
+DxWriter ff("pippo");
+Dxaddmesh(ff, Th);
+Dxaddtimeseries(ff, "Vx",Th);
+fespace Vh(Th, P1);
+Vh vx=x*y;
+Dxaddsol2ts(ff,"Vx",1.0, vx);
+vx=0.5*x*y^2+0.2;
+Dxaddsol2ts(ff,"Vx",2.0, vx);
+cout<<"Ciao";
+</code>
+*/
+
+class DxWriter {
+	struct tsinfo{
+		int imesh;//!<index of the mesh
+		std::string name;
+		std::vector<double> vecistant;
+	};
+private:
+std::vector<Fem2D::Mesh*> _vecmesh;
+std::vector<tsinfo> _vecofts;
+std::string _nameoffile;
+/*! This string contains the name of data file with \\ where there's a \ in the path*/
+std::string _nameofdatafile;
+//!files containing the data and the timeseries
+std::ofstream _ofdata, _ofts;
+
+/*!This function is called frequently, so if the main program crashes the files are good
+and you need only write "end" at the end of data file: echo end>>nameoffile.data and then the files are good
+*/
+void save_header(){
+		std::string s=_nameoffile;
+		s.append(".dx");
+		_ofts.open(s.c_str(), std::ios_base::out);
+		for(int i=0;i<_vecofts.size();++i){
+				_ofts<<"object \""<<_vecofts[i].name<<"\" class series"<<std::endl;  
+				for(int j=0;j<_vecofts[i].vecistant.size();++j){
+					_ofts<<"member "<<j<<" value file \""<<_nameofdatafile<<"\",\""<<_vecofts[i].name<<"_"<<j<<"\" position "<<_vecofts[i].vecistant[j]<<std::endl;
+				}
+				_ofts<<std::endl;
+		}
+		_ofts<<"end"<<std::endl;
+		_ofts.close();
+	}
+	
+
+public:
+  DxWriter() { std::cout << "Constructor of DxWriter" << endl;  }
+  void openfiles(const std::string& s){
+		_nameoffile=s;
+		std::string tmp=s+".data";
+		std::cout<<tmp<<" ";
+		_ofdata.open(tmp.c_str(), std::ios_base::out);
+		_nameofdatafile="";
+		for(int i=0;i<tmp.length();++i){
+			if(tmp.at(i)=='\\')
+				_nameofdatafile.append(1,'\\');
+			_nameofdatafile.append(1,tmp.at(i));
+		}
+  }
+	
+  void addmesh(Fem2D::Mesh* mesh){
+		Fem2D::Mesh& Th(*mesh);
+		_vecmesh.push_back(mesh);
+		_ofdata.flags(std::ios_base::scientific);
+		_ofdata.precision(15);
+		_ofdata<<"object \"pos_"<<_vecmesh.size()-1 <<"\" class array type float rank 1 shape 2 items "<<Th.nv<<" data follows"<<std::endl;
+		for(int k=0;k<Th.nv;++k){//Scorre tutti i vertici
+			_ofdata << Th(k).x<<" "<<Th(k).y<<endl;
+		}
+		_ofdata<<std::endl;
+		_ofdata.flags(std::ios_base::fixed);
+		_ofdata<<"object \"conn_"<<_vecmesh.size()-1<<"\" class array type int rank 1 shape 3 items "<<Th.nt<<" data follows "<<endl;
+		for (int i=0;i<Th.nt;i++){
+			for (int j=0; j <3; j++)
+				_ofdata << Th(i,j) << " ";
+			_ofdata<< endl;
+		}
+		_ofdata<<"attribute \"element type\" string \"triangles\" "<<std::endl;
+		_ofdata<<"attribute \"ref\" string \"positions\" "<<std::endl<<std::endl;
+  }
+  /*!Add a new time series, defined on the mesh*/
+	void addtimeseries(const string& nameofts, Fem2D::Mesh* mesh){
+		tsinfo ts;ts.name=nameofts;
+		std::vector<Fem2D::Mesh*>::const_iterator first=_vecmesh.begin(), last=_vecmesh.end();
+		if(std::find(first, last, mesh)==last){
+			addmesh(mesh);
+			ts.imesh=_vecmesh.size()-1;
+		}else{
+			ts.imesh=std::distance(first, std::find(first, last, mesh));
+		}
+		_vecofts.push_back(ts);
+	}
+  
+	/*!Add an instant to a time series name*/
+	void addistant2ts(const string& nameofts, const double t, const KN<double>&val){
+		int jj=-1;
+		for(int i=0;i<_vecofts.size();++i){
+			if(_vecofts[i].name==nameofts)jj=i;
+		}
+		_vecofts[jj].vecistant.push_back(t);
+		_ofdata.flags(std::ios_base::scientific);
+		_ofdata.precision(15);
+		_ofdata<<"object \""<<nameofts<<"_data_"<<_vecofts[jj].vecistant.size()-1<<"\" class array type float rank 0 items "<<
+			val.size()<<" data follows"<<std::endl;
+		for(int i=0;i<val.size();++i)
+			_ofdata<<val[i]<<std::endl;
+		_ofdata<<"attribute \"dep\" string \"positions\""<<std::endl<<std::endl;
+		_ofdata<<"object \""<<nameofts<<"_"<<_vecofts[jj].vecistant.size()-1<<"\" class field"<<std::endl;
+		_ofdata<<"component \"positions\" value \"pos_"<<_vecofts[jj].imesh<<"\""<<std::endl;
+		_ofdata<<"component \"connections\" value \"conn_"<<_vecofts[jj].imesh<<"\""<<std::endl;
+		_ofdata<<"component \"data\" value \""<<nameofts<<"_data_"<<_vecofts[jj].vecistant.size()-1<<"\""<<std::endl<<std::endl;
+		_ofdata.flush();
+		save_header();
+	}
+	
+	/*!Add a field*/
+	void addfield(const string& nameoffield, Fem2D::Mesh* mesh, const KN<double>&val){
+		std::vector<Fem2D::Mesh*>::const_iterator first=_vecmesh.begin(), last=_vecmesh.end();
+		int im;
+		if(std::find(first, last, mesh)==last){
+			addmesh(mesh);
+			im=_vecmesh.size()-1;
+		}else{
+			im=std::distance(first, std::find(first, last, mesh));
+		}
+		_ofdata.flags(std::ios_base::scientific);
+		_ofdata.precision(15);
+		_ofdata<<"object \""<<nameoffield<<"_data\" class array type float rank 0 items "<<
+			val.size()<<" data follows"<<std::endl;
+		for(int i=0;i<val.size();++i)
+			_ofdata<<val[i]<<std::endl;
+		_ofdata<<"attribute \"dep\" string \"positions\""<<std::endl<<std::endl;
+		_ofdata<<"object \""<<nameoffield<<"\" class field"<<std::endl;
+		_ofdata<<"component \"positions\" value \"pos_"<<im<<"\""<<std::endl;
+		_ofdata<<"component \"connections\" value \"conn_"<<im<<"\""<<std::endl;
+		_ofdata<<"component \"data\" value \""<<nameoffield<<"_data\""<<std::endl<<std::endl;
+		_ofdata.flush();
+	}
+	
+	/*!Get the mesh associated with the series nameofts*/
+	Fem2D::Mesh* getmeshts(const string& nameofts){
+		for(int i=0;i<_vecofts.size();++i){
+			if(_vecofts[i].name==nameofts)return _vecmesh[_vecofts[i].imesh];
+		}
+		return NULL;
+	}
+ 
+  void init(){
+		new(this)DxWriter(); 
+  }
+	
+  void destroy() {
+		if(_ofdata.is_open()){
+			_ofdata<<std::endl<<"end"<<std::endl;
+			_ofdata.close(); 		
+		}
+  } 
+};
+
+
+class Dxwritesol_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+	Expression edx;
+  Expression ename;//!<name of time series or field
+	Expression et;//!<time
+  long what; // 1 scalar, 2 vector, 3 symtensor
+  long nbfloat; // 1 scalar, n vector (3D), n symtensor(3D)
+  Expression evct;
+
+public:
+  Dxwritesol_Op(const basicAC_F0 &  args) :  what(0), nbfloat(0)
+  {
+		evct=0;
+    int nbofsol;
+    int ddim=2;
+    int stsize=3;
+		//There's no named parameter
+    args.SetNameParam();
+		if(args.size()!=4){
+			CompileError("Dxwritesol accepts only 4 parameters");
+		}
+		if (BCastTo<DxWriter *>(args[0])) edx = CastTo<DxWriter *>(args[0]);
+		if (BCastTo<string *>(args[1])) ename = CastTo<string *>(args[1]);
+    if (BCastTo<double>(args[2]))    et = CastTo<double>(args[2]);
+    
+    if ( args[3].left()==atype<double>() ){
+			what=1;
+			nbfloat=1;
+			evct=to<double>( args[3] );
+		}
+		else if ( args[3].left()==atype<double *>() )
+		{
+			what=1;
+			nbfloat=1;
+			evct=to<double>( args[3] );
+		}
+    else if ( BCastTo<pfer>(args[3]) )
+		{
+			what=1;
+			nbfloat=1;
+			evct=to<double>( args[3] );
+		}
+    else if ( args[3].left()==atype<E_Array>() )
+		{
+			CompileError("Until now only scalar solution");
+			
+			/*const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+			//cout << "taille" << a0->size() << endl;
+			//if (a0->size() != ddim || a0->size() != stsize) 
+			//  CompileError("savesol in 2D: vector solution is 2 composant, symmetric solution is 3 composant");
+			if( a0->size() == ddim){
+				// vector solution
+				what=2;
+				nbfloat=a0->size();
+				for(int j=0; j<l[i].nbfloat; j++){
+					//evct[j] = to<double>( (*a0)[j]);
+				}
+			}
+			else if( a0->size() == stsize){
+				// symmetric tensor solution
+				what=3;
+				nbfloat=a0->size();
+				for(int j=0; j<l[i].nbfloat; j++){
+					//evct[j] = to<double>( (*a0)[j]);
+				}
+			}*/
+		}
+    else {
+			CompileError("savesol in 2D: Sorry no way to save this kind of data");
+    }
+      
+  }
+  static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<DxWriter *>(), atype<string *>(), atype<double>(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new Dxwritesol_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+};
+
+
+AnyType Dxwritesol_Op::operator()(Stack stack)  const 
+{ 
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+	DxWriter &dx=*(GetAny<DxWriter *>((*edx)(stack)));
+  string &name=*(GetAny<string *>((*ename)(stack)));
+	double t=GetAny<double>((*et)(stack));
+	Mesh &Th=*(dx.getmeshts(name));
+
+  int nt = Th.nt;
+  int nv = Th.nv;
+
+  int nbsol=nv;
+  long longdefault;
+
+  KN<double> valsol(nbsol);
+  valsol=0.;
+  KN<int> takemesh(nbsol);
+	takemesh=0;
+  MeshPoint *mp3(MeshPointStack(stack));
+  for (int it=0;it<nt;it++){
+    for(int iv=0;iv<3;iv++){
+			int i=Th(it,iv);
+			mp3->setP(&Th,it,iv);					
+			valsol[i] = valsol[i] + GetAny< double >((*evct)(stack));			
+			++takemesh[i];
+		}
+	}
+	for(int i=0; i<nbsol; i++){
+		valsol[i] /= takemesh[i]; 
+	}
+	
+	//Writes valsol on the file file
+	dx.addistant2ts(name, t, valsol);	
+	
+  return longdefault;
+}
+
+// le vrai constructeur est la
+DxWriter* init_DxWriter(DxWriter * const &a, string * const & s)
+{
+  std::cout << "start init_DxWriter" << std::endl;
+  a->init();
+  a->openfiles(*s);
+  std::cout << "end init_DxWriter" << std::endl;
+  return a;
+} 
+
+void* call_addmesh( DxWriter * const & mt, Fem2D::Mesh* const & pTh)
+{ 
+  mt->addmesh(pTh);
+  return NULL;
+}
+
+void* call_addtimeseries( DxWriter * const & mt,string * const & name, Fem2D::Mesh* const & pTh)
+{ 
+  mt->addtimeseries(*name, pTh);
+  return NULL;
+}
+
+
+//   Add the function name to the freefem++ table 
+/*  class Init { public:
+  Init();
+};
+$1 */
+static void Load_Init(){
+
+  Dcl_Type<DxWriter*>(InitP<DxWriter>,Destroy<DxWriter>); // declare deux nouveau type pour freefem++  un pointeur et 
+  
+  zzzfff->Add("DxWriter",atype<DxWriter*>()); // ajoute le type myType a freefem++ 
+  // constructeur  d'un type myType  dans freefem 
+  TheOperators->Add("<-", new OneOperator2_<DxWriter*, DxWriter* ,string*>(&init_DxWriter));
+  
+  Global.Add("Dxaddmesh","(",new OneOperator2_<void *, DxWriter*, Fem2D::Mesh*>(call_addmesh)); 
+	Global.Add("Dxaddtimeseries","(",new OneOperator3_<void *, DxWriter*, std::string*, Fem2D::Mesh*>(call_addtimeseries)); 
+	
+	Global.Add("Dxaddsol2ts","(",new OneOperatorCode< Dxwritesol_Op> );
+  
+  //atype< myType * >()->Add("(","",new OneOperator3_<myType_uv,myType *,double,double  >(set_myType_uv));
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/Element_Mixte.cpp b/examples++-load/Element_Mixte.cpp
new file mode 100644
index 0000000..e40f41e
--- /dev/null
+++ b/examples++-load/Element_Mixte.cpp
@@ -0,0 +1,1111 @@
+//  add some mixte finite element  
+// RT1 et BDM1  conforme in H(div) space,  ie u.n  continuous (n = is the normal) 
+// RT1Ortho , BDM1 are conforme in H(curl) space ie u.t  continuous  (t = is the tangent) 
+//  RT1 , RT1Ortho  ( Neledec type I order 1)
+//  BDM1 (Brezzi, Douglas, Marini) ,  , BDM1Ortho  ( Neledec type I� order 1)
+// the 
+//   TDNNS1   finite element for symetrix 2x2 matrix conforme in H(div div)
+//    : Snn are continious 
+// See Thesis of Astrid Sabine Sinwel, A New Family of Mixed Finite Elements for Elasticity, 2009
+//  http://www.numa.uni-linz.ac.at/Teaching/PhD/Finished/sinwel-diss.pdf 
+//       JOHANNES KEPLER UNIVERSITA,T LINZ
+//  Thesis of Sabine Zaglmayr, High Order Finite Element Methods for Electromagnetic Field Computation, 2006
+//     JOHANNES KEPLER UNIVERSITA,T LINZ
+// http://www.numerik.math.tugraz.at/~zaglmayr/pub/szthesis.pdf
+// 
+// F. Hecht  May 2011
+// ------------------------------------------------------------
+//   test 
+/*
+
+--  edp script associed: 
+ LaplaceRT1.edp
+ lame-TD-NSS.edp
+ test-ElementMixte.edp
+ 
+ */
+
+//ff-c++-LIBRARY-dep:   lapack
+//ff-c++-LIBRARY-dep:   blas
+
+#include "ff++.hpp"
+#include "AddNewFE.h"
+
+#ifdef __LP64__
+typedef int intblas;
+typedef int integer;
+#else
+typedef long intblas;
+typedef long integer;
+#endif
+
+
+typedef integer  logical;
+typedef float   LAPACK_real;
+typedef double   doublereal;
+typedef logical  (* L_fp)();
+typedef integer      ftnlen;
+
+typedef complex<float> LAPACK_complex;
+typedef complex<double> doublecomplex;
+typedef void VOID; 
+#define complex LAPACK_complex 
+#define real LAPACK_real 
+
+#include "clapack.h"
+#undef real
+#undef complex 
+// #include "problem.hpp"
+namespace  Fem2D {
+    
+    // ------ P2 TD_NNS  
+    class TypeOfFE_TD_NNS0 : public  TypeOfFE { public:  
+	static int Data[];
+	// double Pi_h_coef[];
+	
+	TypeOfFE_TD_NNS0(): TypeOfFE(3,
+				     3,
+				     Data,
+				     1,
+				     1,
+				     9, // nb coef to build interpolation
+				     3, // np point to build interpolation
+				     0)
+	{  
+	    
+	    
+	    const R c3=1./3.;
+	    const R2 Pt[] = {R2(0.5,0.5), R2(0,0.5),R2(0.5,0)}; 
+	    // for the 3 vertices 6 coef 
+	    // P_Pi_h[0]=Pt[0];
+	    int kk=0;   
+	    
+	    for (int e=0;e<3;++e)
+	      { // point d'integration sur l'arete e 
+		  P_Pi_h[e]= Pt[e];
+		  pij_alpha[kk++]= IPJ(e,e,0);   
+		  pij_alpha[kk++]= IPJ(e,e,1); 	  
+		  pij_alpha[kk++]= IPJ(e,e,2);   
+		  
+	      }
+	    assert(P_Pi_h.N()==3);
+	    assert(pij_alpha.N()==kk);
+	    
+	}
+	void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+	void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const;
+    } ;
+    //                     on what     nu df on node node of df    
+    int TypeOfFE_TD_NNS0::Data[]={
+	3,4,5,  //  support on what 
+	0,0,0,  // df on node 
+	0,1,2,  // th node of df 
+	0,0,0,  //  df previou FE
+	0,1,2,  //  which df on prev 
+	0,0,0,
+	0,0,0, 
+	3,3,3 
+    };
+    
+    void TypeOfFE_TD_NNS0::Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+    {
+      const Triangle & T(K.T);
+      int k=0;
+      //   integration sur les aretes 
+      for (int i=0;i<3;i++)
+	{
+	  
+	  R2 N(T.Edge(i).perp());
+	  v[k++]= N.x*N.x; 
+	  v[k++]= 2*N.y*N.x;
+	  v[k++]= N.y*N.y;
+	}
+      assert(k==9); 
+    }
+    
+    void TypeOfFE_TD_NNS0::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+    {
+      typedef double R;
+      //R2 A(K[0]), B(K[1]),C(K[2]);
+      R l0=1-P.x-P.y,l1=P.x,l2=P.y;
+      const R c3= 1./3.;
+      R ll3[3]={l0-c3,l1-c3,l2-c3};
+      R ll[3]={l0,l1,l2};
+      R2 Dl[3]=  {K.H(0), K.H(1), K.H(2) };
+      /* if T_i=Edge(i) ,N=T.perp :
+       N_i' T_j T_k' N_i =0  if i=j or i=k
+       N_i' T_j = det(T_i,T_j) = aire(K) 
+       */
+      R cK= 2* K.area; 
+      R2 Rl[3]= { K.Edge(0)/cK,   K.Edge(1)/ cK,   K.Edge(2)/ cK};   //  
+      /* bulle:
+       $ B_i = ((Rot L_i+1 ) (Rot L_(i+2)' ))^s  L_i$
+       s => symetrise ..
+       */
+      R S[3][3],S1[3][3];
+      for(int i=0;i<3;++i)
+	{
+	  int i1=(i+1)%3;
+	  int i2=(i+2)%3;
+	  S[0][i]= -Rl[i1].x*Rl[i2].x;
+	  S[1][i]= -(Rl[i1].x*Rl[i2].y+Rl[i1].y*Rl[i2].x)*0.5;
+	  S[2][i]= -Rl[i1].y*Rl[i2].y;
+	  
+	}
+      val=0; 
+      KN<bool> wd(KN_<const bool>(whatd,last_operatortype));
+      
+      if (wd[op_id])
+	{
+	  for(int c=0;c<3;++c)
+	      for(int i=0;i<3;++i){
+		  val(i,c,op_id)    = S[c][i]; //  (c3-ll[i])/c3 
+	      }
+	}
+      
+      /*
+       // s[.] [i] = 
+       { //     //  compute the inv of S with lapack 
+       for(int j=0;j<3;++j)
+       for(int i=0;i<3;++i)
+       S1[i][j]=S[i][j];
+       
+       intblas N=3,LWORK = 9;
+       double WORK[9] ;
+       intblas INFO,IPIV[4];
+       
+       dgetrf_(&N,&N,&(S1[0][0]),&N,IPIV,&INFO);
+       ffassert(INFO==0);
+       dgetri_(&N,&(S1[0][0]),&N,IPIV,WORK,&LWORK,&INFO);
+       ffassert(INFO==0);
+       
+       }
+       R B[3][3], BB[3][3];
+       R cc = 3./K.area; 
+       for(int j=0;j<3;++j)
+       for(int i=0;i<3;++i)
+       B[i][j]= S[i][j]*ll[j];
+       
+       for(int i=0;i<3;++i)
+       for(int k=0;k<3;++k)
+       {  BB[i][k]=0.;	      
+       for(int j=0;j<3;++j)
+       BB[i][k] += cc*S[i][j]*ll[j]*S1[j][k];
+       }
+       if(verbosity>1000)
+       {
+       
+       cout << endl;
+       cout <<  Rl[0] << " "<< Rl[1]  << ",  " <<Rl[2] << endl;	
+       for(int i=0;i<3;++i)
+       cout << " *****    " << BB[i][0] << " " << BB[i][1] << " " << BB[i][2] << "\t l " << ll[i] << endl;
+       }
+       
+       // the basic function are
+       //  the space S_i * ( a_i+b_1lambda_i) 
+       //  the base :
+       //  tree egde function: 
+       //   coefe*  S_i*( lambda_i - 1/3)   :  zero a barycenter 
+       //   coefk*BB_i ,withh     B_i =   (S_i * lambda_i),   BB = B * S1 , ok because lambda_i = 1/3 a bary
+       //  so BB_ij = coefk/3  delta_ij  at G the barycenter.
+       // 
+       KN<bool> wd(KN_<const bool>(whatd,last_operatortype));
+       val=0; 
+       
+       throwassert( val.N()>=6);
+       throwassert(val.M()==3);
+       
+       
+       val=0; 
+       
+       
+       if (wd[op_id])
+       {
+       for(int c=0;c<3;++c)
+       for(int i=0;i<3;++i){
+       val(i,c,op_id)    = S[c][i]*(c3-ll[i])/c3; //  (c3-ll[i])/c3 
+       val(i+3,c,op_id)  = BB[c][i];	      
+       }
+       }
+       if (wd[op_dx])
+       {
+       for(int i=0;i<3;++i)
+       for(int k=0;k<3;++k)
+       {  BB[i][k]=0.;	      
+       for(int j=0;j<3;++j)
+       BB[i][k] += cc*S[i][j]*Dl[j].x*S1[j][k];
+       }
+       
+       for(int c=0;c<3;++c)
+       for(int i=0;i<3;++i)
+       {
+       val(i  ,c,op_dx)    = -S[c][i]*Dl[i].x/c3;
+       val(i+3,c,op_dx)  = BB[c][i];	      
+       
+       }
+       
+       
+       }
+       
+       if (wd[op_dy])
+       {  
+       
+       for(int i=0;i<3;++i)
+       for(int k=0;k<3;++k)
+       {  BB[i][k]=0.	;      
+       for(int j=0;j<3;++j)
+       BB[i][k] += cc*S[i][j]*Dl[j].y*S1[j][k];
+       }
+       
+       for(int c=0;c<3;++c)
+       for(int i=0;i<3;++i)
+       {
+       val(i  ,c,op_dy)    = -S[c][i]*Dl[i].y/c3;
+       val(i+3,c,op_dy)  = BB[c][i];	      
+       
+       }
+       
+       
+       }	  
+       
+       
+       */
+      
+    }
+    
+    
+    // ------ P2 TD_NNS  
+    class TypeOfFE_TD_NNS1 : public  TypeOfFE { public:  
+	static int Data[];
+	// double Pi_h_coef[];
+	const QuadratureFormular1d & QFE;
+	const  GQuadratureFormular<R2> & QFK;
+	
+	TypeOfFE_TD_NNS1(): TypeOfFE(3*2+3,
+				     3,
+				     Data,
+				     2,
+				     1,
+				     3+6*3*QF_GaussLegendre2.n, // nb coef to build interpolation
+				     QuadratureFormular_T_1.n+3*QF_GaussLegendre2.n, // np point to build interpolation
+				     0),
+	QFE(QF_GaussLegendre2), QFK(QuadratureFormular_T_1)	
+	{  
+	    
+	    
+	    int kk=0,kp=0;
+	    for(int p=0;p<QFK.n;++p)
+	      {
+		P_Pi_h[kp++]=QFK[p];
+	        for (int c=0;c<3;c++)
+		    pij_alpha[kk++]= IPJ(3*2+c,p,c);
+	      }
+	    
+	    for (int e=0;e<3;++e) 
+	      {
+		for(int p=0;p<QFE.n;++p)
+		  {
+		    R2 A(TriangleHat[VerticesOfTriangularEdge[e][0]]);
+		    R2 B(TriangleHat[VerticesOfTriangularEdge[e][1]]);
+		    P_Pi_h[kp++]= B*(QFE[p].x)+ A*(1.-QFE[p].x);// X=0 => A  X=1 => B;       
+		    
+		  }
+	      }
+	    
+	    
+	    for (int e=0;e<3;++e)
+		for(int p=0;p<QFE.n;++p)	
+		  { 
+		      int pp=QFK.n+ e*QFE.n+p;
+		      pij_alpha[kk++]= IPJ(2*e+0,pp,0);  
+		      pij_alpha[kk++]= IPJ(2*e+1,pp,0);  
+		      pij_alpha[kk++]= IPJ(2*e+0,pp,1);  
+		      pij_alpha[kk++]= IPJ(2*e+1,pp,1);  
+		      pij_alpha[kk++]= IPJ(2*e+0,pp,2);  
+		      pij_alpha[kk++]= IPJ(2*e+1,pp,2);  
+		      
+		      
+		  }
+	    ffassert(P_Pi_h.N()==kp);
+	    ffassert(pij_alpha.N()==kk);
+	    
+	}
+	void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+	void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const;
+    } ;
+    //                     on what     nu df on node node of df    
+    int TypeOfFE_TD_NNS1::Data[]={
+	3,3, 4,4, 5,5, 6,6,6,//  support on what 
+	0,1, 0,1, 0,1, 0,1,2, // df on node 
+	0,0, 1,1, 2,2, 3,3,3,  // th node of df 
+	0,0, 0,0, 0,0, 0,0,0, //  df previou FE
+	0,1, 2,3, 4,5, 6,7,8, //  which df on prev 
+	0,0,0,
+	0,0,0, 
+	9,9,9 
+    };
+    
+    void TypeOfFE_TD_NNS1::Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+    {
+      
+      const Triangle & T(K.T);
+      int k=0;
+      // coef pour les 3 sommets  fois le 2 composantes 
+      // for (int i=0;i<3;i++)
+      for (int p=0;p<QFK.n;++p) 	
+	{ // wrong ... 
+	    // 3 -1 -1    
+	    // -1 3 -1    / 4  
+	    // -1 -1 3 
+	    /*R l[3]; QFK[p].toBary(l);
+	     R c0 = QFK[p].a * T.area/4*(3*l[0]-l[1]-l[2]);
+	     R c1 = QFK[p].a * T.area/4*(l[0]+3*l[1]-l[2]);
+	     R c2 = QFK[p].a * T.area/4*(l[0]-l[1]+3*l[2]);*/
+	    R cc=QFK[p].a * T.area;
+	    v[k++]=cc; // * T.area; 
+	    v[k++]=cc;// * T.area; 
+	    v[k++]=cc;// * T.area; 
+	}
+      //   integration sur les aretes 
+      for (int i=0;i<3;i++)
+	{
+	  R s = T.EdgeOrientation(i) ;
+	  for (int p=0;p<QFE.n;++p) 
+	    {
+	      R l0 = QFE[p].x, l1 = 1-QFE[p].x;
+	      R p0= (2*l0-l1)*2;// poly othogonaux to \lambda_1
+	      R p1= (2*l1-l0)*2;// poly othogonaux to \lambda_0
+	      R cc1 = p0*QFE[p].a; // 
+	      R cc0 = p1*QFE[p].a; //
+	      if(s<0) Exchange(cc1,cc0); // exch lambda0,lambda1
+	      
+	      
+	      R2 N(T.Edge(i).perp());
+	      v[k++]= cc0*N.x*N.x;
+	      v[k++]= cc1*N.x*N.x;    
+	      v[k++]= cc0*2*N.y*N.x;
+	      v[k++]= cc1*2*N.y*N.x;    
+	      v[k++]= cc0*N.y*N.y;
+	      v[k++]= cc1*N.y*N.y;
+	    }
+	}
+      ffassert(pij_alpha.N()==k);    
+    } 
+    void TypeOfFE_TD_NNS1::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+    {
+      typedef double R;
+      R l0=1-P.x-P.y,l1=P.x,l2=P.y;
+      const R c3= 1./3.;
+      R ll3[3]={l0-c3,l1-c3,l2-c3};
+      R ll[3]={l0,l1,l2};
+      R2 Dl[3]=  {K.H(0), K.H(1), K.H(2) };
+      /* if T_i=Edge(i) ,N=T.perp :
+       N_i' T_j T_k' N_i =0  if i=j or i=k
+       N_i' T_j = det(T_i,T_j) = aire(K) 
+       */
+      R cK= 2* K.area; 
+      R2 Rl[3]= { K.Edge(0)/cK,   K.Edge(1)/ cK,   K.Edge(2)/ cK};   //  
+      /* bulle:
+       $ B_i = ((Rot L_i+1 ) (Rot L_(i+2)' ))^s  L_i$
+       s => symetrise ..
+       */
+      R S[3][3],S1[3][3];
+      int ei0[3]={1,2,0};
+      int ei1[3]={ 2,0,1};
+      
+      for(int i=0;i<3;++i)
+	{
+	  if(K.EdgeOrientation(i) < 0) Exchange(ei0[i],ei1[i]);
+	  int i1=(i+1)%3;
+	  int i2=(i+2)%3;
+	  S[0][i]= -Rl[i1].x*Rl[i2].x;
+	  S[1][i]= -(Rl[i1].x*Rl[i2].y+Rl[i1].y*Rl[i2].x)*0.5;
+	  S[2][i]= -Rl[i1].y*Rl[i2].y;
+	  
+	}
+      // s[.] [i] = 
+      { //     //  compute the inv of S with lapack 
+	  for(int j=0;j<3;++j)
+	      for(int i=0;i<3;++i)
+		  S1[i][j]=S[i][j];
+	  
+	  intblas N=3,LWORK = 9;
+	  double WORK[9] ;
+	  intblas  INFO,IPIV[4];
+	  
+	  dgetrf_(&N,&N,&(S1[0][0]),&N,IPIV,&INFO);
+	  ffassert(INFO==0);
+	  dgetri_(&N,&(S1[0][0]),&N,IPIV,WORK,&LWORK,&INFO);
+	  ffassert(INFO==0);
+	  
+      }
+      R B[3][3], BB[3][3];
+      R cc = 3./K.area; 
+      for(int j=0;j<3;++j)
+	  for(int i=0;i<3;++i)
+	      B[i][j]= S[i][j]*ll[j];
+      
+      for(int i=0;i<3;++i)
+	  for(int k=0;k<3;++k)
+	    {  BB[i][k]=0.;	      
+		for(int j=0;j<3;++j)
+		    BB[i][k] += cc*S[i][j]*ll[j]*S1[j][k];
+	    }
+      if(verbosity>1000)
+	{
+	  
+	  cout << endl;
+	  cout <<  Rl[0] << " "<< Rl[1]  << ",  " <<Rl[2] << endl;	
+	  for(int i=0;i<3;++i)
+	      cout << " *****    " << BB[i][0] << " " << BB[i][1] << " " << BB[i][2] << "\t l " << ll[i] << endl;
+	}
+      
+      // the basic function are
+      //  the space S_i * ( a_i+b_1lambda_i) 
+      //  the base :
+      //  tree egde function: 
+      //   coefe*  S_i*( lambda_i - 1/3)   :  zero a barycenter 
+      //   coefk*BB_i ,withh     B_i =   (S_i * lambda_i),   BB = B * S1 , ok because lambda_i = 1/3 a bary
+      //  so BB_ij = coefk/3  delta_ij  at G the barycenter.
+      // 
+      KN<bool> wd(KN_<const bool>(whatd,last_operatortype));
+      val=0; 
+      
+      throwassert( val.N()>=6);
+      throwassert(val.M()==3);
+      
+      
+      val=0; 
+      
+      
+      if (wd[op_id])
+	{
+	  for(int c=0;c<3;++c)
+	      for(int i=0;i<3;++i){
+		  
+		  val(2*i,c,op_id)      = S[c][i]*(ll[ei0[i]]-ll[i]);  
+		  val(2*i+1,c,op_id)    = S[c][i]*(ll[ei1[i]]-ll[i]);  
+		  val(i+6,c,op_id)  = BB[c][i];	      
+	      }
+	}
+      if (wd[op_dx])
+	{
+	  for(int i=0;i<3;++i)
+	      for(int k=0;k<3;++k)
+		{  BB[i][k]=0.;	      
+		    for(int j=0;j<3;++j)
+			BB[i][k] += cc*S[i][j]*Dl[j].x*S1[j][k];
+		}
+	  
+	  for(int c=0;c<3;++c)
+	      for(int i=0;i<3;++i)
+		{
+		  val(2*i,c,op_dx)      = S[c][i]*(Dl[ei0[i]].x-Dl[i].x); 
+		  val(2*i+1,c,op_dx)    = S[c][i]*(Dl[ei1[i]].x-Dl[i].x); 
+		  val(i+6,c,op_dx)  = BB[c][i];	      
+		  
+		}
+	  
+	  
+	}
+      
+      if (wd[op_dy])
+	{  
+	    
+	    for(int i=0;i<3;++i)
+		for(int k=0;k<3;++k)
+		  {  BB[i][k]=0.	;      
+		      for(int j=0;j<3;++j)
+			  BB[i][k] += cc*S[i][j]*Dl[j].y*S1[j][k];
+		  }
+	    
+	    for(int c=0;c<3;++c)
+		for(int i=0;i<3;++i)
+		  {
+		    val(2*i,c,op_dy)      = S[c][i]*(Dl[ei0[i]].y-Dl[i].y); 
+		    val(2*i+1,c,op_dy)    = S[c][i]*(Dl[ei1[i]].y-Dl[i].y); 
+		    val(i+6,c,op_dy)  = BB[c][i];	      
+		    
+		  }
+	    
+	    
+	}	  
+      
+      
+      
+      
+    }
+    
+    
+    struct  InitTypeOfRTk_2d
+  {
+    
+    int k;//  order poly on edge
+    int ndfi;// nb of internal dof 
+    int npe; // nb point on edge
+    int ndf; // nb dof
+    
+    KN<R> X;  //  point on edge
+    //    KN<R> Pi_h_coef; // 1
+    KN<int> Data; // data of TypeOfFE
+    const QuadratureFormular1d QFE;
+    const  GQuadratureFormular<R2> & QFK;
+    InitTypeOfRTk_2d(int KK) 
+    :k(KK),ndfi((k+1)*(k)), npe(k+1),ndf(3*npe+ndfi),Data( 5*ndf+6),
+    QFE(-1+2*npe,npe,GaussLegendre(npe),true), QFK(QuadratureFormular_T_5)
+    {
+      int j=0;
+      int ndfe=ndf-ndfi; // 
+      int o[6];
+      o[0]=0;
+      for(int i=1;i<6;++i)
+	  o[i]=o[i-1]+ndf;
+      for(int df=0;df<ndf;++df)
+	{
+	  if( df < ndfe)
+	    {
+	      int e= df/npe;
+	      int n= df%npe;
+	      Data[o[0]+df]=3+e;
+	      Data[o[1]+df]=n;
+	      Data[o[2]+df]=e;
+	      Data[o[3]+df]=0;
+	      Data[o[4]+df]=df;
+	    }
+	  else {
+	      int n= df-ndfe;
+	      Data[o[0]+df]=6;
+	      Data[o[1]+df]=n;
+	      Data[o[2]+df]=3;
+	      Data[o[3]+df]=0;
+	      Data[o[4]+df]=df;	      
+	  }
+	  
+	}
+      Data[o[5]+0] =0;
+      Data[o[5]+1] =0 ;
+      Data[o[5]+2] =0;
+      Data[o[5]+3] =0;
+      Data[o[5]+4] =ndf ;
+      Data[o[5]+5] =ndf;// end_dfcomp 
+      
+    }
+  };
+    
+    class TypeOfFE_RT1_2d :public InitTypeOfRTk_2d, public  TypeOfFE { 
+    public:  
+	static double Pi_h_coef[];
+	bool Ortho;
+	
+	TypeOfFE_RT1_2d(bool ortho)
+	:  InitTypeOfRTk_2d(1),
+	TypeOfFE(ndf,2,Data,2,1,
+		 2*2*3*QFE.n+QFK.n*2,// nb coef mat interpole
+		 3*QFE.n+QFK.n, // nb P interpolation 
+		 0),
+	Ortho(ortho)
+	{  
+	    //      cout << " Pk = " << k << endl;
+	    int kkk=0,i=0;
+	    for (int e=0;e<3;++e) 
+		for (int p=0;p<QFE.n;++p) 
+		  {
+		    R2 A(TriangleHat[VerticesOfTriangularEdge[e][0]]);
+		    R2 B(TriangleHat[VerticesOfTriangularEdge[e][1]]);
+		    
+		    pij_alpha[kkk++]= IPJ(2*e,i,0);
+		    pij_alpha[kkk++]= IPJ(2*e,i,1);
+		    pij_alpha[kkk++]= IPJ(2*e+1,i,0);
+		    pij_alpha[kkk++]= IPJ(2*e+1,i,1);
+		    
+		    
+		    P_Pi_h[i++]= B*(QFE[p].x)+ A*(1.-QFE[p].x);// X=0 => A  X=1 => B;       
+		  }
+	    int i6=6,i7=7;
+	    if(Ortho) Exchange(i6,i7); // x,y -> -y, x 
+	    for (int p=0;p<QFK.n;++p) 
+	      {
+		pij_alpha[kkk++]= IPJ(i6,i,0);
+		pij_alpha[kkk++]= IPJ(i7,i,1);
+		P_Pi_h[i++]= QFK[p]; 
+	      }
+	    //cout << kkk << " kkk == " << this->pij_alpha.N() << endl;
+	    //cout << i << "  ii == " << this->P_Pi_h.N() << endl;
+	    ffassert(kkk==this->pij_alpha.N());
+	    ffassert(i==this->P_Pi_h.N() );
+	}
+	
+	void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const 
+	{ // compute the coef of interpolation ...
+	    const Triangle & T(K.T);
+	    int k=0;
+	    for (int i=0;i<3;i++)
+	      {  
+		  R2 E(Ortho? T.Edge(i) : -T.Edge(i).perp());
+		  
+		  R s = T.EdgeOrientation(i) ;
+		  for (int p=0;p<QFE.n;++p) 
+		    {
+		      R l0 = QFE[p].x, l1 = 1-QFE[p].x;
+		      R p0= (2*l0-l1)*2;// poly othogonaux to \lambda_1
+		      R p1= (2*l1-l0)*2;// poly othogonaux to \lambda_0
+		      R cc1 = s*p0*QFE[p].a; // 
+		      R cc0 = s*p1*QFE[p].a; //
+		      if(s<0) Exchange(cc1,cc0); // exch lambda0,lambda1
+		      v[k++]= cc0*E.x;
+		      v[k++]= cc0*E.y; 
+		      v[k++]= cc1*E.x;
+		      v[k++]= cc1*E.y; 
+		    }
+	      }
+	    R sy= Ortho ? -1 : 1; 
+	    
+	    for (int p=0;p<QFK.n;++p) 	
+	      {
+		v[k++]=sy*QFK[p].a * T.area; 
+		v[k++]=QFK[p].a * T.area; 
+	      }
+	    // cout << " k= " << k << " == " << this->pij_alpha.N() << endl;
+	    assert(k==this->pij_alpha.N());
+	}
+	void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+    } ;
+    // ENDOFCLASS TypeOfFE_PkEdge    
+    
+    void TypeOfFE_RT1_2d::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & Phat,RNMK_ & val) const
+    {
+      R2 X=K(Phat);
+      R2 Q[]={ R2(K[0]), R2(K[1]),R2(K[2])};
+      R2 A[]={ R2(Q[1],Q[2]), R2(Q[2],Q[0]), R2(Q[0],Q[1])}; 
+      R2 B[]={ R2(A[1],A[2]), R2(A[2],A[0]), R2(A[0],A[1])}; 
+      R l0=1-Phat.x-Phat.y,l1=Phat.x,l2=Phat.y; 
+      R L[3]={l0,l1,l2};
+      
+      static long  count=10;
+      /*      
+      if( count < 0)
+	{
+	  cout << "TypeOfFE_RT1_2d "<< " " << A[0]+A[1]+A[2] << " " <<  B[0]+B[1]+B[2] << endl;
+	  cout << det(Q[0],Q[1],Q[2]) << " X = " << X << " Phat ="  << Phat << endl;
+	  cout<< "Q="  << Q[0]<< "," << Q[1] << " , " << Q[2] <<endl; 
+	  cout<< "A="  << A[0]<< "," << A[1] << " , " << A[2] << endl; 
+	  cout<< "B="  << B[0]<< "," << B[1] << " , " << B[2] <<endl; 
+	}
+      
+       THE 2 DOF k=0,1  are: on edge e   f -> \int_e f \lambda_{e+k} . n_e 
+       THE 2 internal dof are : f -> \int_K f e_i  where e_i is the canonical basis of R^2 
+       
+       
+       so the basis function are 
+       
+       let call \phi_i the basic fonction of RT0 (without orientation) so the normal is exterior.
+       \phi_i (X) = ( X- Q_i ) / (2 |K|) =  \lambda_{i+1} Curl( \lambda_{i+2}) - \lambda_{i+2} Curl( \lambda_{i+1})
+       
+       edge function j=0,1
+       i1= i+j+1, i2= i+2-j  remark : {i,i1,i2} <=> {i,i+1,i+2}  
+       \phi_i ( \lambda_{i1} - 4/3 \lambda_i) + 1/3 \phi_{i1}\lambda_{i1}
+       
+       internal function are 
+       \sum   bx_i \phi_{i}\lambda_{i}
+       \sum   by_i \phi_{i}\lambda_{i}
+       \sum bx_i = 1/c0
+       \sum by_i = 1/c0 
+       we have 
+       \phi_{i} = A_{i+2}  \lambda_{i+1} - A_{i+1}  \lambda_{i+2}
+       with
+       A_i = Th.edge(i)/ ( 2 |K])    
+       B_i = A_{i+2} - A_{i+1}  
+       det( B_i ) = 9 *2 area 
+       to be homogene
+       cc0= |K]  sqrt(area)*sqrt(18)
+       ccK= 9 *2 area *c0; 
+       bx_0 = det(R2(cc0,0),B1,B2)/ ( cck)  
+       
+       
+       so all basic d function are the sum of 3 function 
+       
+       sum_{k=0}^2  c_k  phi_{p_k} lambda_{l_k} 
+       
+       */
+      
+      
+      assert( val.N()>=ndf);
+      assert(val.M()==2);
+      int ee=0;
+      
+      val=0; 
+      
+      R2 phi[3] = { X-Q[0], X-Q[1], X-Q[2] };// phi * area *2 
+      
+      int pI[8][3];// store p_k 
+      int lI[8][3];// store l_k 
+      R   cI[8][3];// store c_k 
+      
+      int df=0;
+      R CKK = 2* K.area; 
+      for(int e=0;e<3;++e)
+	{
+	  int i=e;
+	  int ii[2]={(e+1)%3,(e+2)%3};
+	  int i2=(e+2)%3;
+	  R s = K.EdgeOrientation(e)/CKK;
+	  if(s<0) Exchange(ii[0],ii[1]); // 
+	  for(int k=0;k<2;++k,df++)
+	    {
+	      pI[df][0]= i;
+	      lI[df][0]= ii[k];
+	      cI[df][0]= s;
+	      
+	      pI[df][1]= i;
+	      lI[df][1]= i;
+	      cI[df][1]= -s*4./3.;
+	      
+	      pI[df][2]= ii[k];
+	      lI[df][2]= ii[k];
+	      cI[df][2]= s/3.;
+	      
+	      
+	    }
+	}
+      /*     
+       if(count<0)
+       {
+       // verif. 
+       R2 PP[] ={ R2(0.5,0),R2(0.5,0.5),R2(0,0.5)};
+       int err=0;
+       for(int df = 0;df < 6;++df)
+       {  
+       cout << " df = " << df << " : \t";
+       for(int k=0;k<3;++k)
+       cout  <<"+ " << cI[df][k] << " *l" << lI[df][k]  << " *phi" << pI[df][k] << "  \t  ";
+       cout << endl;    
+       
+       R2 fd;
+       for(int p=0;p<3;++p)
+       {
+       R L[3]; PP[p].toBary(L);
+       R2 X=K(PP[p]);
+       cout << X << " ,\t " << L[0] << " " << L[1] << " " <<L[2] ;
+       R2 phi[3] = { X-Q[0], X-Q[1], X-Q[2] };// phi * area *2 
+       
+       R2 ff = (cI[df][0] * L[lI[df][0]]) * phi[pI[df][0]]
+       + (cI[df][1] * L[lI[df][1]]) * phi[pI[df][1]]
+       + (cI[df][2] * L[lI[df][2]]) * phi[pI[df][2]]
+       ;
+       fd += ff;
+       cout << " :::: " << 3*ff 
+       << " :  " <<  3*(cI[df][0] * L[lI[df][0]]) * phi[pI[df][0]]
+       << " ; " <<  3*(cI[df][1] * L[lI[df][1]]) * phi[pI[df][1]]
+       << " ; " <<  3*(cI[df][2] * L[lI[df][2]]) * phi[pI[df][2]]
+       << " :  " <<  3*(cI[df][0] * L[lI[df][0]])  <<"(" <<  phi[pI[df][0]] <<")"
+       << " ; " <<  3*(cI[df][1] * L[lI[df][1]]) <<"(" << phi[pI[df][1]]<<")"
+       << " ; " <<  3*(cI[df][2] * L[lI[df][2]]) <<"(" << phi[pI[df][2]]<<")"		    
+       <<endl;
+       
+       }
+       if( fd.norme() > 1e-5) err++;
+       cout << " Verif " << df << " [ " << 3*fd << " ] " << fd.norme()  <<endl;		
+       }
+       ffassert(err==0);
+       
+       }
+       */
+      R cK = 18.* K.area;
+      R c0 = sqrt(cK);
+      R cb = 12/c0;
+      R ccK = K.area*cK/c0; 
+      for(int k=0;k<2;++k,df++)
+	{
+	  
+	  R2 PB(0,0);
+	  PB[k]=cb;
+	  // if( count <5) cout << " PB = " << PB << " df = " << df << " " << cK << " ==" << det(B[0] ,B[1],B[2]) <<endl;
+	  R b0 = det(PB   ,B[1],B[2])/ ccK;
+	  R b1 = det(B[0],PB   ,B[2])/ ccK;
+	  R b2 = det(B[0],B[1],PB   )/ ccK;
+	  
+	  // if( count <5) cout << " S= "<< b0*B[0]+b1*B[1]+b2*B[2] << " s= " << (b0+b1+b2) << " b=" << b0 << " " << b1 << " " << b2 <<  endl;
+	  pI[df][0]= 0;
+	  lI[df][0]= 0;
+	  cI[df][0]= b0;
+	  
+	  pI[df][1]= 1;
+	  lI[df][1]= 1;
+	  cI[df][1]= b1;
+	  
+	  pI[df][2]= 2;
+	  lI[df][2]= 2;
+	  cI[df][2]= b2;
+	  
+	}
+      /*
+       if( count< 5)
+       {
+       cout << Phat << " " << X << endl; 
+       for( int e=0;e<3;++e)
+       {  int e1= (e+1)%3, e2=(e+2)%3 ;
+       cout << " phi e " << phi[e] << " == " << L[e1]*A[e2] -  L[e2]*A[e1] << endl;		
+       }
+       for(int df=0;df< 8;++df)
+       {
+       cout << " df = " << df << " : \t";
+       for(int k=0;k<3;++k)
+       cout  <<"+ " << cI[df][k] << " *l" << lI[df][k]  << " *phi" << pI[df][k] << "  \t  ";
+       cout << endl;    
+       }
+       
+       }
+       */      
+      int ortho0=0,ortho1=1; R s1ortho=1;
+      if(Ortho) { ortho0=1; ortho1=0; s1ortho=-1;}
+      
+      if (whatd[op_id])
+	{
+          
+          for(int df=0;df< 8;++df)
+	    {
+	      R2 fd(0.,0.) ;
+	      for(int k=0;k<3;++k) {
+		  fd += (cI[df][k] * L[lI[df][k]]) * phi[pI[df][k]] ;
+	      }
+	      
+	      val(df,ortho0,op_id)= fd.x;
+	      val(df,ortho1,op_id)= s1ortho*fd.y;
+	    }
+	}
+      
+      
+      if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+	{
+          R2 DL[3]={K.H(0),K.H(1),K.H(2)};
+	  R2 Dphix(1,0);
+	  R2 Dphiy(0,1);
+	  
+	  if (whatd[op_dx])
+	    {
+	      
+	      for(int df=0;df< 8;++df)
+		{
+		  R2 fd(0.,0.);
+		  for(int k=0;k<3;++k)
+		      fd += cI[df][k] * (DL[lI[df][k]].x * phi[pI[df][k]] + L[lI[df][k]]* Dphix);
+		  val(df,ortho0,op_dx)= fd.x;
+		  val(df,ortho1,op_dx)= s1ortho*fd.y;	      
+		}
+	      
+	    }
+	  if (whatd[op_dy])
+	    {
+	      
+	      for(int df=0;df< 8;++df)
+		{
+		  R2 fd(0.,0.);
+		  for(int k=0;k<3;++k)
+		      fd += cI[df][k] * (DL[lI[df][k]].y * phi[pI[df][k]] + L[lI[df][k]]* Dphiy);
+		  val(df,ortho0,op_dy)= fd.x;
+		  val(df,ortho1,op_dy)= s1ortho*fd.y;	      
+		}
+	      
+	    }
+	  if(whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+	    {
+	      cout << " to do FH RT1 dxx, dyy dxy " << endl; 
+	      ffassert(0); 
+	    }
+	  
+	}
+      count++;
+    }
+    
+    
+    class TypeOfFE_BDM1_2d : public  TypeOfFE { 
+    public:  
+	static int Data[];
+	static double Pi_h_coef[];
+	bool Ortho;
+	const QuadratureFormular1d & QFE;
+	TypeOfFE_BDM1_2d(bool ortho)
+	: 
+	TypeOfFE(6,2,Data,1,1,
+		 2*2*3*2,// nb coef mat interpole
+		 3*2, // nb P interpolation 
+		 0),
+	QFE(QF_GaussLegendre2),
+	Ortho(ortho)
+	{  
+	    //      cout << " Pk = " << k << endl;
+	    int kkk=0,i=0;
+	    for (int e=0;e<3;++e) 
+		for (int p=0;p<QFE.n;++p) 
+		  {
+		    R2 A(TriangleHat[VerticesOfTriangularEdge[e][0]]);
+		    R2 B(TriangleHat[VerticesOfTriangularEdge[e][1]]);
+		    
+		    pij_alpha[kkk++]= IPJ(2*e,i,0);
+		    pij_alpha[kkk++]= IPJ(2*e,i,1);
+		    pij_alpha[kkk++]= IPJ(2*e+1,i,0);
+		    pij_alpha[kkk++]= IPJ(2*e+1,i,1);
+		    
+		    
+		    P_Pi_h[i++]= B*(QFE[p].x)+ A*(1.-QFE[p].x);// X=0 => A  X=1 => B;       
+		  }
+	    //cout << kkk << " kkk == " << this->pij_alpha.N() << endl;
+	    //cout << i << "  ii == " << this->P_Pi_h.N() << endl;
+	    ffassert(kkk==this->pij_alpha.N());
+	    ffassert(i==this->P_Pi_h.N() );
+	}
+	
+	void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const 
+	{ // compute the coef of interpolation ...
+	    const Triangle & T(K.T);
+	    int k=0;
+	    for (int i=0;i<3;i++)
+	      {  
+		  R2 E(Ortho? T.Edge(i) : -T.Edge(i).perp());
+		  
+		  R s = T.EdgeOrientation(i) ;
+		  for (int p=0;p<QFE.n;++p) 
+		    {
+		      R l0 = QFE[p].x, l1 = 1-QFE[p].x;
+		      R p0= s; // poly othogonaux to \lambda_1
+		      R p1= -3*(l0-l1);// poly othogonaux to \lambda_0
+		      R cc0 = p0*QFE[p].a; // 
+		      R cc1 = p1*QFE[p].a; //
+		      //if(s<0) Exchange(cc1,cc0); // exch lambda0,lambda1
+		      v[k++]= cc0*E.x;
+		      v[k++]= cc0*E.y; 
+		      v[k++]= cc1*E.x;
+		      v[k++]= cc1*E.y; 
+		    }
+	      }
+	    // cout << " k= " << k << " == " << this->pij_alpha.N() << endl;
+	    assert(k==this->pij_alpha.N());
+	}
+	void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+    } ;
+    // ENDOFCLASS TypeOfFE_PkEdge
+    
+  int  TypeOfFE_BDM1_2d::Data[]={
+	3,3, 4,4, 5,5,  //  support on what 
+	0,1, 0,1, 0,1,  // df on node 
+	0,0, 1,1, 2,2,  // th node of df 
+	0,0,0, 0,0,0, //  df previou FE
+	0,1,2,3,4,5,  //  which df on prev 
+	0,0,
+	0,0,
+	6,6 
+    };
+    
+    
+    void TypeOfFE_BDM1_2d::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & Phat,RNMK_ & val) const
+    {
+      R2 X=K(Phat);
+      R2 Q[]={ R2(K[0]), R2(K[1]),R2(K[2])};
+      R l0=1-Phat.x-Phat.y,l1=Phat.x,l2=Phat.y; 
+      R L[3]={l0,l1,l2};
+      R2 Dl[3]={K.H(0),K.H(1),K.H(2)};
+      
+      static int count=10;
+      
+      
+      
+      assert( val.N()>=6);
+      assert(val.M()==2);
+      int ee=0;
+      
+      val=0; 
+      R cK = 2* K.area;
+      
+      int ortho0=0,ortho1=1; R s1ortho=1;
+      if(Ortho) { ortho0=1; ortho1=0; s1ortho=-1;}
+      
+      if (whatd[op_id])
+	{
+          
+          for(int df=0,e =0;e< 3;++e)
+	    {
+	      int e1=(e+1)%3, e2=(e+2)%3;
+	      R s = K.EdgeOrientation(e) ;
+	      R2 f1= (X-Q[e]) * s / cK ;
+	      R2 f2= -(Dl[e1]*L[e2]+Dl[e2]*L[e1]).perp() ;
+	      
+	      
+	      val(df,ortho0,op_id)= f1.x;
+	      val(df++,ortho1,op_id)= s1ortho*f1.y;
+	      
+	      val(df,ortho0,op_id)= f2.x;
+	      val(df++,ortho1,op_id)= s1ortho*f2.y;
+	    }
+	}
+      
+      
+      if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+	{
+ 	  R2 Dphix(1,0);
+	  R2 Dphiy(0,1);
+	  
+	  if (whatd[op_dx])
+	    {
+	      
+	      for(int df=0,e =0;e< 3;++e)
+		{
+		  int e1=(e+1)%3, e2=(e+2)%3;
+		  R s = K.EdgeOrientation(e) ;
+		  R2 f1=  R2( s / cK,0.) ;
+		  R2 f2= -(Dl[e1]*Dl[e2].x+Dl[e2]*Dl[e1].x).perp() ;
+		  
+		  
+		  val(df,ortho0,op_dx)= f1.x;
+		  val(df++,ortho1,op_dx)= s1ortho*f1.y;
+		  
+		  val(df,ortho0,op_dx)= f2.x;
+		  val(df++,ortho1,op_dx)= s1ortho*f2.y;
+		}
+	      
+	    }
+	  if (whatd[op_dy])
+	    {
+	      
+	      for(int df=0,e =0;e< 3;++e)
+		{
+		  int e1=(e+1)%3, e2=(e+2)%3;
+		  R s = K.EdgeOrientation(e) ;
+		  R2 f1=  R2(0.,  s / cK) ;
+		  R2 f2= -(Dl[e1]*Dl[e2].y+Dl[e2]*Dl[e1].y).perp() ;
+		  
+		  
+		  val(df,ortho0,op_dy)= f1.x;
+		  val(df++,ortho1,op_dy)= s1ortho*f1.y;
+		  
+		  val(df,ortho0,op_dy)= f2.x;
+		  val(df++,ortho1,op_dy)= s1ortho*f2.y;
+		}
+	      
+	    }
+	  
+	}
+      count++;
+    }
+    
+    
+    
+    
+    
+    // a static variable to add the finite element to freefem++
+    static TypeOfFE_RT1_2d Elm_TypeOfFE_RT1_2d(false);// RT1    
+    static TypeOfFE_RT1_2d Elm_TypeOfFE_RT1_2dOrtho(true);// RT1ortho  
+    static TypeOfFE_BDM1_2d Elm_TypeOfFE_BDM1_2d(false);// BDM1    
+    static TypeOfFE_BDM1_2d Elm_TypeOfFE_BDM1_2dOrtho(true);// BDM1ortho  
+    static TypeOfFE_TD_NNS0 Elm_TD_NNS;
+    static TypeOfFE_TD_NNS1 Elm_TD_NNS1;
+    static AddNewFE FE__TD_NNS("TDNNS0",&Elm_TD_NNS); 
+    static AddNewFE FE__TD_NNS1("TDNNS1",&Elm_TD_NNS1);     
+    static AddNewFE Elm__TypeOfFE_RT1_2d("RT1",&Elm_TypeOfFE_RT1_2d); 
+    static AddNewFE Elm__TypeOfFE_RT1_2dOrtho("RT1Ortho",&Elm_TypeOfFE_RT1_2dOrtho); 
+    static AddNewFE Elm__TypeOfFE_BDM1_2d("BDM1",&Elm_TypeOfFE_BDM1_2d); 
+    static AddNewFE Elm__TypeOfFE_BDM1_2dOrtho("BDM1Ortho",&Elm_TypeOfFE_BDM1_2dOrtho); 
+    
+} // FEM2d namespace 
+// --- fin -- 
+
+
diff --git a/examples++-load/Element_P1dc1.cpp b/examples++-load/Element_P1dc1.cpp
new file mode 100644
index 0000000..a3cbdf6
--- /dev/null
+++ b/examples++-load/Element_P1dc1.cpp
@@ -0,0 +1,449 @@
+#include "ff++.hpp"
+#include "AddNewFE.h"
+
+// Attention probleme de numerotation des inconnues
+// -------------------------------------------------
+// dans freefem, il y a un noeud par objets  sommet, arete, element.
+// et donc la numerotation des dl dans l'element depend 
+// de l'orientation des aretes
+// 
+/// ---------------------------------------------------------------
+namespace  Fem2D {
+
+    
+    // -------------------
+    // ttdc1_ finite element fully discontinue. 
+    // -------------------
+    class TypeOfFE_P1ttdc1_ : public  TypeOfFE { public:  
+	static int Data[];
+	static double Pi_h_coef[];
+	static const R2 G;
+	static const R cshrink;
+	static const R cshrink1;
+	//  (1 -1/3)*
+	
+	static R2 Shrink(const R2& P){ return (P-G)*cshrink+G;}
+	static R2 Shrink1(const R2& P){ return (P-G)*cshrink1+G;}
+	
+	TypeOfFE_P1ttdc1_(): TypeOfFE(0,0,3,1,Data,1,1,3,3,Pi_h_coef)
+	{ const R2 Pt[] = { Shrink(R2(0,0)), Shrink(R2(1,0)), Shrink(R2(0,1)) }; 
+	    for (int i=0;i<NbDoF;i++) {
+		pij_alpha[i]= IPJ(i,i,0);
+		P_Pi_h[i]=Pt[i];
+		// cout << Pt[i] << " " ;
+	    }
+	    //	cout <<" cshrink: " << cshrink << " cshrink1 : "<< cshrink1 <<endl;
+	}
+	
+	void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+	
+	
+	virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
+	
+    } ;
+    const R2 TypeOfFE_P1ttdc1_::G(1./3.,1./3.);   
+    const R TypeOfFE_P1ttdc1_::cshrink=1;   
+    const R TypeOfFE_P1ttdc1_::cshrink1=1./TypeOfFE_P1ttdc1_::cshrink;   
+    
+    class TypeOfFE_P2ttdc1_ : public  TypeOfFE { public:  
+	static int Data[];
+	static double Pi_h_coef[];
+	static const R2 G;
+	static const R cshrink;
+	static const R cshrink1;
+	
+	static R2 Shrink(const R2& P){ return (P-G)*cshrink+G;}
+	static R2 Shrink1(const R2& P){ return (P-G)*cshrink1+G;}
+	
+	TypeOfFE_P2ttdc1_(): TypeOfFE(0,0,6,1,Data,3,1,6,6,Pi_h_coef)
+	{ const R2 Pt[] = { Shrink(R2(0,0)), Shrink(R2(1,0)), Shrink(R2(0,1)),
+	    Shrink(R2(0.5,0.5)),Shrink(R2(0,0.5)),Shrink(R2(0.5,0)) };
+	    for (int i=0;i<NbDoF;i++) {
+		pij_alpha[i]= IPJ(i,i,0);
+		P_Pi_h[i]=Pt[i]; }
+	}
+	
+	
+	void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+	
+	
+    } ;
+    //                          on what   nu df on node  node of df    
+    int TypeOfFE_P1ttdc1_::Data[]={6,6,6,       0,1,2,       0,0,0,       0,0,0,         0,1,2,       0, 0,3};
+    int TypeOfFE_P2ttdc1_::Data[]={6,6,6,6,6,6, 0,1,2,3,4,5, 0,0,0,0,0,0,  0,0,0,0,0,0,  0,1,2,3,4,5, 0, 0,6};
+    double TypeOfFE_P1ttdc1_::Pi_h_coef[]={1.,1.,1.};
+    double TypeOfFE_P2ttdc1_::Pi_h_coef[]={1.,1.,1.,1.,1.,1.};
+    
+    const R2 TypeOfFE_P2ttdc1_::G(1./3.,1./3.);   
+    const R TypeOfFE_P2ttdc1_::cshrink=1;   
+    const R TypeOfFE_P2ttdc1_::cshrink1=1./TypeOfFE_P2ttdc1_::cshrink;   
+    
+    
+    R TypeOfFE_P1ttdc1_::operator()(const FElement & K,const  R2 & P1Hat,const KN_<R> & u,int componante,int op) const 
+    { 
+	
+	R2 PHat=Shrink1(P1Hat);  
+	R u0(u(K(0))), u1(u(K(1))), u2(u(K(2)));
+	R r=0;
+	if (op==0)
+	  {
+	    R l0=1-PHat.x-PHat.y,l1=PHat.x,l2=PHat.y; 
+	    r = u0*l0+u1*l1+l2*u2;
+	  }
+	else
+	  { 
+	      const Triangle & T=K.T;
+	      R2 D0 = T.H(0)*cshrink1 , D1 = T.H(1)*cshrink1  , D2 = T.H(2)*cshrink1 ;
+	      if (op==1)
+		  r =  D0.x*u0 + D1.x*u1 + D2.x*u2 ;
+	      else 
+		  r =  D0.y*u0 + D1.y*u1 + D2.y*u2 ;
+	  }
+	//  cout << r << "\t";
+	return r;
+    }
+    
+    void TypeOfFE_P1ttdc1_::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P1,RNMK_ & val) const
+    {
+      R2 P=Shrink1(P1);  
+      
+      //  const Triangle & K(FE.T);
+      R2 A(K[0]), B(K[1]),C(K[2]);
+      R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+      
+      if (val.N() <3) 
+	  throwassert(val.N() >=3);
+      throwassert(val.M()==1 );
+      //  throwassert(val.K()==3 );
+      
+      val=0; 
+      RN_ f0(val('.',0,op_id)); 
+      
+      if (whatd[op_id]) 
+	{
+	  f0[0] = l0;
+	  f0[1] = l1;
+	  f0[2] = l2;}
+      if (whatd[op_dx] || whatd[op_dy])
+	{
+	  R2 Dl0(K.H(0)*cshrink1), Dl1(K.H(1)*cshrink1), Dl2(K.H(2)*cshrink1);
+	  
+	  if (whatd[op_dx]) 
+	    {
+	      RN_ f0x(val('.',0,op_dx)); 
+	      f0x[0] = Dl0.x;
+	      f0x[1] = Dl1.x;
+	      f0x[2] = Dl2.x;
+	    }
+	  
+	  if (whatd[op_dy]) {
+	      RN_ f0y(val('.',0,op_dy)); 
+	      f0y[0] = Dl0.y;
+	      f0y[1] = Dl1.y;
+	      f0y[2] = Dl2.y;
+	  }
+	}
+    }
+    
+    
+    
+    void TypeOfFE_P2ttdc1_::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P1,RNMK_ & val) const
+    {
+      R2 P=Shrink1(P1);  
+      
+      //  const Triangle & K(FE.T);
+      R2 A(K[0]), B(K[1]),C(K[2]);
+      R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+      R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+      
+      //  throwassert(FE.N == 1);  
+      throwassert( val.N()>=6);
+      throwassert(val.M()==1);
+      //  throwassert(val.K()==3 );
+      
+      val=0; 
+      // --     
+      if (whatd[op_id])
+	{
+	  RN_ f0(val('.',0,op_id)); 
+	  f0[0] = l0*(2*l0-1);
+	  f0[1] = l1*(2*l1-1);
+	  f0[2] = l2*(2*l2-1);
+	  f0[3] = 4*l1*l2; // oppose au sommet 0
+	  f0[4] = 4*l0*l2; // oppose au sommet 1
+	  f0[5] = 4*l1*l0; // oppose au sommet 3
+	}
+      if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+	{
+	  R2 Dl0(K.H(0)*cshrink1), Dl1(K.H(1)*cshrink1), Dl2(K.H(2)*cshrink1);
+	  if (whatd[op_dx])
+	    {
+	      RN_ f0x(val('.',0,op_dx)); 
+	      f0x[0] = Dl0.x*l4_0;
+	      f0x[1] = Dl1.x*l4_1;
+	      f0x[2] = Dl2.x*l4_2;
+	      f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
+	      f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
+	      f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
+	    }
+	  
+	  if (whatd[op_dy])
+	    {  
+		RN_ f0y(val('.',0,op_dy)); 
+		f0y[0] = Dl0.y*l4_0;
+		f0y[1] = Dl1.y*l4_1;
+		f0y[2] = Dl2.y*l4_2;
+		f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
+		f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
+		f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
+	    }
+	  
+	  if (whatd[op_dxx])
+	    {  
+		RN_ fxx(val('.',0,op_dxx)); 
+		
+		fxx[0] = 4*Dl0.x*Dl0.x;
+		fxx[1] = 4*Dl1.x*Dl1.x;
+		fxx[2] = 4*Dl2.x*Dl2.x;
+		fxx[3] =  8*Dl1.x*Dl2.x;
+		fxx[4] =  8*Dl0.x*Dl2.x;
+		fxx[5] =  8*Dl0.x*Dl1.x;
+	    }
+	  
+	  if (whatd[op_dyy])
+	    {  
+		RN_ fyy(val('.',0,op_dyy)); 
+		fyy[0] = 4*Dl0.y*Dl0.y;
+		fyy[1] = 4*Dl1.y*Dl1.y;
+		fyy[2] = 4*Dl2.y*Dl2.y;
+		fyy[3] =  8*Dl1.y*Dl2.y;
+		fyy[4] =  8*Dl0.y*Dl2.y;
+		fyy[5] =  8*Dl0.y*Dl1.y;
+	    }
+	  if (whatd[op_dxy])
+	    {  
+		assert(val.K()>op_dxy);
+		RN_ fxy(val('.',0,op_dxy)); 
+		
+		fxy[0] = 4*Dl0.x*Dl0.y;
+		fxy[1] = 4*Dl1.x*Dl1.y;
+		fxy[2] = 4*Dl2.x*Dl2.y;
+		fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+		fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+		fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+	    }
+	  
+	}
+      
+    }
+    
+    
+    //
+    // end ttdc1_
+    // ------------------
+    
+   
+    static void SetPtPkDC(R3 *Pt,int kk,int nn,R cc=1 )
+    {  // P0 P1 et P2 , P1b 
+	const int d=3	;
+	int n=0;
+	double dK= kk;
+	double cc1= 1-cc;// 
+	const R3 G=R3::diag(1./(d+1)); // barycenter
+        for(int i=0;i<= kk; ++i)
+	  for(int j=0;j<= kk-i; ++j)
+	    for(int k=0;k<= kk-i-j; ++k)
+		{  int l = kk -i-j-k;
+		    ffassert(l>=0 && l <= kk);
+		    Pt[n++] = R3(k/dK,j/dK,i/dK)*cc + G*cc1 ; 
+		}
+	ffassert(n==nn);
+	if(verbosity>9)
+	    cout << " Pkdc = " << KN_<R3>(Pt,nn)<<"\n";
+	
+    }
+    
+    
+class TypeOfFE_LagrangeDC3d: public  GTypeOfFE<Mesh3>
+  {
+    //typedef typename  MMesh Mesh;
+  public:
+    typedef   Mesh3 Mesh;
+    typedef   Mesh::Element Element;
+    typedef   Element::Rd Rd;
+    typedef   Element::RdHat RdHat;
+    static const int d=Rd::d;
+     const R cshrink;
+     const R cshrink1;
+        static const Rd G;
+    //  (1 -1/3)*
+    
+     Rd Shrink(const Rd& P) const { return (P-G)*cshrink+G;}
+     Rd Shrink1(const Rd& P) const { return (P-G)*cshrink1+G;}
+    
+    const int k;
+
+    struct A4 {
+	int dfon[4];
+	
+	A4(int k) {
+	    //  (k+3)(k+2)(k+1) / 6   // d== 3
+	    
+	    int ndf = (d== 3) ? ((k+3)*(k+2)*(k+1) / 6) : 
+	    ((d== 2) ? ((k+2)*(k+1) / 2) : k+1 );  
+	   
+	    dfon[0]=dfon[1]=dfon[2]=dfon[3]=0;
+	    dfon[d]=ndf;
+	     
+	    if(verbosity>9)      
+		cout << "A4 "<<   k<< " "   <<dfon[0]<< dfon[1]<<dfon[2]<<dfon[3]<<endl;
+	}
+	operator const  int  * () const {return dfon;}
+    };
+    
+    RdHat *Pt;
+    TypeOfFE_LagrangeDC3d(int kk,R cc):
+    //              dfon ,N,nsub(graphique) ,  const mat interpolation , discontinuous 
+    GTypeOfFE<Mesh>(A4(kk),1,Max(kk,1),true,true),cshrink(cc),cshrink1(1./cc),k(kk)
+    {
+      int n=this->NbDoF;
+      if(verbosity>9)    
+	  cout << "\n +++ Pdc"<<k<<" : ndof : "<< n <<endl;
+      SetPtPkDC (this->PtInterpolation,k,this->NbDoF,cc);
+      if(verbosity>9)    cout << this->PtInterpolation<< endl;
+      {
+	  for (int i=0;i<n;i++) 
+	    {
+	      this->pInterpolation[i]=i;
+	      this->cInterpolation[i]=0;
+	      this->dofInterpolation[i]=i;
+	      this->coefInterpolation[i]=1.;
+	    }  
+	}
+       
+      /*
+         inv de a M1  + b Id  =   a1 M1  + b1 Id  ( M1 : mat /  m_ij =1 ) 
+         M*M = (d+1) M =>
+         b1 =  1/b
+         a1 = -b / ((d+1)a+1) 
+       */
+    }
+    ~TypeOfFE_LagrangeDC3d(){ } //cout << "TypeOfFE_LagrangeDC3d"<< this->NbDoF<<endl;}
+    
+    void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, RNMK_ & val) const;
+    virtual R operator()(const FElement & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const ;
+
+  private:
+    TypeOfFE_LagrangeDC3d( const TypeOfFE_LagrangeDC3d &) ;
+    void operator=( const TypeOfFE_LagrangeDC3d &) ;
+  };
+    
+void TypeOfFE_LagrangeDC3d::FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P1, RNMK_ & val) const
+    {
+      //  const Triangle & K(FE.T);
+       R3 P=this->Shrink1(P1); 
+      R l[]={1.-P.sum(),P.x,P.y,P.z}; 
+      
+      assert(val.N() >=Element::nv);
+      assert(val.M()==1 );
+      
+      val=0; 
+      RN_ f0(val('.',0,op_id)); 
+      
+      if (whatd & Fop_D0) 
+	{
+	  f0[0] = l[0];
+	  f0[1] = l[1];
+	  f0[2] = l[2];
+	  f0[3] = l[3];
+	}
+      if (whatd & Fop_D1)
+	{
+	  R3 Dl[4];
+	  K.Gradlambda(Dl);
+	  for(int i=0;i<4;++i)
+	     Dl[i] *= cshrink1;
+	  //for(int i=0;i<4;++i)
+	  //      cout << Dl[i] << endl;
+	  if (whatd & Fop_dx) 
+	    {
+	      RN_ f0x(val('.',0,op_dx)); 
+	      f0x[0] = Dl[0].x;
+	      f0x[1] = Dl[1].x;
+	      f0x[2] = Dl[2].x;
+	      f0x[3] = Dl[3].x;
+	      
+	    }
+	  
+	  if (whatd & Fop_dy) {
+	      RN_ f0y(val('.',0,op_dy)); 
+	      f0y[0] = Dl[0].y;
+	      f0y[1] = Dl[1].y;
+	      f0y[2] = Dl[2].y;
+	      f0y[3] = Dl[3].y;
+	  }
+	  
+	  if (whatd & Fop_dz) {
+	      RN_ f0z(val('.',0,op_dz)); 
+	      f0z[0] = Dl[0].z;
+	      f0z[1] = Dl[1].z;
+	      f0z[2] = Dl[2].z;
+	      f0z[3] = Dl[3].z;
+	  }
+	}
+      //  cout << val << endl;
+    }
+    
+R TypeOfFE_LagrangeDC3d::operator()(const FElement & K,const  R3 & PHat1,const KN_<R> & u,int componante,int op) const 
+    { 
+	R3 PHat=Shrink1(PHat1); 
+	R r=0;
+	if(k==1)
+	  {
+	    
+	   R u0(u(K(0))), u1(u(K(1))), u2(u(K(2))),u3(u(K(3)));
+	
+	if (op==0)
+	  {
+	    R l[4]; 
+	    PHat.toBary(l);
+	    r = u0*l[0]+u1*l[1]+l[2]*u2+l[3]*u3;
+	  }
+	else if(op==op_dx || op==op_dy || op==op_dz) 
+	  { 
+	      const Element & T=K.T;
+	      R3 D[4];
+	      T.Gradlambda(D);
+	      for(int i=0;i<4;++i)
+		  D[i] *= cshrink1;
+	      if (op==op_dx)
+		  r =  D[0].x*u0 + D[1].x*u1 + D[2].x*u2+ D[3].x*u3 ;
+	      else if (op==op_dy) 
+		  r =  D[0].y*u0 + D[1].y*u1 + D[2].y*u2+ D[3].y*u3 ;
+	      else 
+		  r =  D[0].z*u0 + D[1].z*u1 + D[2].z*u2+ D[3].z*u3 ;
+	  }
+	  }
+	else
+	    ffassert(0); // to do ..
+	return r;
+    }   
+    
+    const R3 TypeOfFE_LagrangeDC3d::G(1./4.,1./4.,1./4.);   
+    
+
+// link with FreeFem++ 
+static TypeOfFE_P1ttdc1_ P1dc1LagrangeP1dc1;
+static TypeOfFE_P2ttdc1_ P2dc1LagrangeP2dc1;
+static TypeOfFE_LagrangeDC3d TypeOfFE_LagrangeDC3dtt(1,0.999);
+        
+// a static variable to add the finite element to freefem++
+static AddNewFE  P1dcLagrange("P1dc1",&P1dc1LagrangeP1dc1); 
+static AddNewFE  P2dcLagrange("P2dc1",&P2dc1LagrangeP2dc1); 
+static AddNewFE3  P1dttLagrange3d("P1dc3d",&TypeOfFE_LagrangeDC3dtt,"P1dc"); 
+
+} // FEM2d namespace 
+
+
+// --- fin -- 
+
diff --git a/examples++-load/Element_P3.cpp b/examples++-load/Element_P3.cpp
new file mode 100644
index 0000000..1ca8b00
--- /dev/null
+++ b/examples++-load/Element_P3.cpp
@@ -0,0 +1,199 @@
+#include "ff++.hpp"
+#include "AddNewFE.h"
+// Attention probleme de numerotation des inconnues
+// -------------------------------------------------
+// dans freefem, il y a un noeud par objets  sommet, arete, element.
+// et donc la numerotation des dl dans l'element depend 
+// de l'orientation des aretes
+// 
+/// ---------------------------------------------------------------
+namespace  Fem2D {
+
+ // ------ P3  Hierarchical (just remove P1 node of the P2 finite element)  --------
+ class TypeOfFE_P3Lagrange : public  TypeOfFE { public:  
+   static const int k=3; 
+   static const int ndf = (k+2)*(k+1)/2;
+   static int Data[];
+   static double Pi_h_coef[];
+   static const int nn[10][3] ;
+   static const int aa[10][3] ;
+   static const int ff[10];
+   static const int il[10];
+   static const int jl[10];
+   static const int kl[10];
+    
+   
+   TypeOfFE_P3Lagrange(): TypeOfFE(3+2*3+1,1,Data,4,1,16,10,0)
+   {  
+     static const  R2 Pt[10] = { 
+     R2( 0/3. , 0/3. ) , 
+     R2( 3/3. , 0/3. ) , 
+     R2( 0/3. , 3/3. ) , 
+     R2( 2/3. , 1/3. ) ,  
+     R2( 1/3. , 2/3. ) , 
+     R2( 0/3. , 2/3. ) , 
+     R2( 0/3. , 1/3. ) , 
+     R2( 1/3. , 0/3. ) , 
+     R2( 2/3. , 0/3. ) , 
+     R2( 1/3. , 1/3. ) } ;
+     //   3,4,5,6,7,8
+     int other[10]= { -1, -1,-1,4,3,6,5,8,7,-1 }; 
+     
+     int kk=0;
+     for (int i=0;i<NbDoF;i++) 
+       {
+	 pij_alpha[kk++]= IPJ(i,i,0);
+	 if(other[i]>=0)
+	   pij_alpha[kk++]= IPJ(i,other[i],0);
+	 P_Pi_h[i]=Pt[i]; 
+       }
+      assert(P_Pi_h.N()==NbDoF);
+      assert(pij_alpha.N()==kk);
+   }
+  
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+   {
+     for (int i=0;i<16;++i)
+       v[i]=1;
+     int e0=K.EdgeOrientation(0);
+     int e1=K.EdgeOrientation(1);
+     int e2=K.EdgeOrientation(2);
+     int ooo[6]={e0,e0,e1,e1,e2,e2};
+     int iii[6]; 
+     int jjj[6];
+     for(int i=0;i<6;++i)
+       { 
+	 iii[i]= 3+2*i; // si  orient = 1
+         jjj[i]= 4+2*i; // si orient = -1
+       }
+     for(int i=0;i<6;++i)
+       if(ooo[i]==1) v[jjj[i]]=0;
+       else v[iii[i]]=0;
+          
+   }
+ } ;
+  //                     on what     nu df on node node of df    
+  int TypeOfFE_P3Lagrange::Data[]={
+    0,1,2,3,3,4,4,5,5,6,     // the support number  of the node of the df 
+    0,0,0,0,1,0,1,0,1,0,     // the number of the df on  the node  
+    0,1,2,3,3,4,4,5,5,6,    // the node of the df 
+    0,0,0,0,0,0,0,0,0,0,     //  the df come from which FE (generaly 0)
+    0,1,2,3,4,5,6,7,8,9,    //  which are de df on sub FE
+    0,                      // for each compontant $j=0,N-1$ it give the sub FE associated 
+    0,10 
+  };
+  double TypeOfFE_P3Lagrange::Pi_h_coef[]={1.,1.,1.,1.,1.,1.,1.,1.,1.,1.};
+  
+  void TypeOfFE_P3Lagrange::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+  {
+ 
+    R2 A(K[0]), B(K[1]),C(K[2]);
+    R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+    R L[3]={l0*k,l1*k,l2*k};
+    throwassert( val.N()>=10);
+    throwassert(val.M()==1);
+    // Attention il faut renumeroter les fonction de bases
+    //   car dans freefem++, il y a un node par sommet, arete or element
+    //   et la numerotation naturelle  mais 2 noud pas arete
+    //   donc p est la perumation
+    //   echange de numerotation si les arete sont dans le mauvais sens 
+    int p[10];
+    for(int i=0;i<10;++i)
+      p[i]=i;
+
+    if(K.EdgeOrientation(0) <0) Exchange(p[3],p[4]);// 3,4
+    if(K.EdgeOrientation(1) <0) Exchange(p[5],p[6]);// 5,6 
+    if(K.EdgeOrientation(2) <0) Exchange(p[7],p[8]);// 7,8
+    //cout << KN_<int>(p,10) <<endl;
+    val=0; 
+    /*
+    //  les fonction de base du Pk Lagrange sont 
+    //  
+    //
+    */
+// -- 
+    
+    
+    if (whatd[op_id])
+      {
+	RN_ f0(val('.',0,op_id)); 
+	for (int df=0;df<ndf;df++)
+	  {
+	    int pdf=p[df];
+	    R f=1./ff[df];
+	    
+	    for( int i=0;i<k;++i)
+	      {
+		f *= L[nn[df][i]]-aa[df][i];
+		//cout <<  L[nn[df][i]]-aa[df][i]<< " ";
+	      }
+	    f0[pdf] = f;
+	    //cout << pdf<< " " << df << " f " <<f <<endl;
+	  }
+	//cout <<" L " << L[0] << " " << L[1] << " " << L[2] << endl;
+	//cout << ndf << " nbf = "<< f0 <<endl;
+      }
+    
+    
+    if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+      {
+	R2 D[]={K.H(0)*k, K.H(1)*k,K.H(2)*k };
+	if (whatd[op_dx] || whatd[op_dy] )
+	  {
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];
+		R fx=0.,fy=0.,f=1./ff[df];
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dx]) val(pdf,0,op_dx)=fx;
+		if(whatd[op_dy]) val(pdf,0,op_dy)=fy;		
+	      } 
+	  }
+	
+	if (whatd[op_dyy] ||whatd[op_dxy]|| whatd[op_dxx] )
+	  {  
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];		
+		R fx=0.,fy=0.,f=1./ff[df];
+		R fxx=0.,fyy=0.,fxy=0.;
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fxx=fxx*Ln+2.*fx*D[n].x;
+		    fyy=fyy*Ln+2.*fy*D[n].y;
+		    fxy=fxy*Ln+fx*D[n].y+fy*D[n].x;
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dxx]) val(pdf,0,op_dxx)=fxx;
+		if(whatd[op_dyy]) val(pdf,0,op_dyy)=fyy;
+		if(whatd[op_dxy]) val(pdf,0,op_dxy)=fxy;
+	      }
+	  }
+	
+      }
+  }
+#include "Element_P3.hpp"
+  
+
+
+// link with FreeFem++ 
+static TypeOfFE_P3Lagrange P3LagrangeP3;
+// a static variable to add the finite element to freefem++
+static AddNewFE  P3Lagrange("P3",&P3LagrangeP3); 
+} // FEM2d namespace 
+
+
+// --- fin -- 
+
diff --git a/examples++-load/Element_P3.hpp b/examples++-load/Element_P3.hpp
new file mode 100644
index 0000000..aa6dfc6
--- /dev/null
+++ b/examples++-load/Element_P3.hpp
@@ -0,0 +1,28 @@
+ const int TypeOfFE_P3Lagrange::nn[10][3] =  { 
+		 { 0 ,0 ,0 } ,
+		 { 1 ,1 ,1 } ,
+		 { 2 ,2 ,2 } ,
+		 { 1 ,1 ,2 } ,
+		 { 1 ,2 ,2 } ,
+		 { 0 ,2 ,2 } ,
+		 { 0 ,0 ,2 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,1 ,1 } ,
+		 { 0 ,1 ,2 } }
+;
+ const int TypeOfFE_P3Lagrange::aa[10][3] =  { 
+		 { 0 ,1 ,2 } ,
+		 { 0 ,1 ,2 } ,
+		 { 0 ,1 ,2 } ,
+		 { 0 ,1 ,0 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,1 ,0 } ,
+		 { 0 ,1 ,0 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,0 ,0 } }
+;
+ const int TypeOfFE_P3Lagrange::ff[10] =  { 6 ,6 ,6 ,2 ,2 ,2 ,2 ,2 ,2 ,1 };
+ const int TypeOfFE_P3Lagrange::il[10] =  { 3 ,0 ,0 ,0 ,0 ,1 ,2 ,2 ,1 ,1 };
+ const int TypeOfFE_P3Lagrange::jl[10] =  { 0 ,3 ,0 ,2 ,1 ,0 ,0 ,1 ,2 ,1 };
+ const int TypeOfFE_P3Lagrange::kl[10] =  { 0 ,0 ,3 ,1 ,2 ,2 ,1 ,0 ,0 ,1 };
diff --git a/examples++-load/Element_P3dc.cpp b/examples++-load/Element_P3dc.cpp
new file mode 100644
index 0000000..3b67c22
--- /dev/null
+++ b/examples++-load/Element_P3dc.cpp
@@ -0,0 +1,207 @@
+#include "ff++.hpp"
+#include "AddNewFE.h"
+
+// Attention probleme de numerotation des inconnues
+// -------------------------------------------------
+// dans freefem, il y a un noeud par objets  sommet, arete, element.
+// et donc la numerotation des dl dans l'element depend 
+// de l'orientation des aretes
+// 
+/// ---------------------------------------------------------------
+namespace  Fem2D {
+
+ // ------ P3dc  
+ class TypeOfFE_P3dcLagrange : public  TypeOfFE { public:  
+   static const int k=3; 
+   static const int ndf = (k+2)*(k+1)/2;
+   static int Data[];
+   static double Pi_h_coef[];
+   static const int nn[10][3] ;
+   static const int aa[10][3] ;
+   static const int ff[10];
+   static const int il[10];
+   static const int jl[10];
+   static const int kl[10];
+    
+   static const R2 G;
+   static const R cshrink;
+   static const R cshrink1;
+   //  (1 -1/3)*
+    
+   static R2 Shrink(const R2& P){ return (P-G)*cshrink+G;}
+   static R2 Shrink1(const R2& P){ return (P-G)*cshrink1+G;}
+   
+   TypeOfFE_P3dcLagrange(): TypeOfFE(3+2*3+1,1,Data,4,1,10,10,Pi_h_coef)
+   {  
+     static const  R2 Pt[10] = { 
+       R2( 0/3. , 0/3. ) , 
+       R2( 3/3. , 0/3. ) , 
+       R2( 0/3. , 3/3. ) , 
+       R2( 2/3. , 1/3. ) ,  
+       R2( 1/3. , 2/3. ) , 
+       R2( 0/3. , 2/3. ) , 
+       R2( 0/3. , 1/3. ) , 
+       R2( 1/3. , 0/3. ) , 
+       R2( 2/3. , 0/3. ) , 
+       R2( 1/3. , 1/3. ) } ;
+     //   3,4,5,6,7,8
+     for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Shrink(Pt[i]); }
+
+   }
+
+  
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   /*   void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+   {
+     for (int i=0;i<10;++i)
+       v[i]=1;
+     int e0=K.EdgeOrientation(0);
+     int e1=K.EdgeOrientation(1);
+     int e2=K.EdgeOrientation(2);
+     int ooo[6]={e0,e0,e1,e1,e2,e2};
+     int iii[6]; 
+     int jjj[6];
+     for(int i=0;i<6;++i)
+       { 
+	 iii[i]= 3+2*i; // si  orient = 1
+         jjj[i]= 4+2*i; // si orient = -1
+       }
+     for(int i=0;i<6;++i)
+       if(ooo[i]==1) v[jjj[i]]=0;
+       else v[iii[i]]=0;
+          
+       }*/
+ } ;
+
+
+  const R2 TypeOfFE_P3dcLagrange::G(1./3.,1./3.);   
+  const R TypeOfFE_P3dcLagrange::cshrink=1-1e-2;   
+  const R TypeOfFE_P3dcLagrange::cshrink1=1./TypeOfFE_P3dcLagrange::cshrink;   
+
+  //                     on what     nu df on node node of df    
+  int TypeOfFE_P3dcLagrange::Data[]={
+    6,6,6, 6,6, 6,6, 6,6, 6,    // the support number  of the node of the df  
+    0,1,2,3,4,5,6,7,8,9,     // the number of the df on  the node  
+    0,0,0,0,0,0,0,0,0,0,     //  the node of the df 
+    0,0,0,0,0,0,0,0,0,0,     //  the df come from which FE (generaly 0)
+    0,1,2,3,4,5,6,7,8,9,    //  which are de df on sub FE
+    0,                      // for each compontant $j=0,N-1$ it give the sub FE associated 
+    0, 10 };
+  double TypeOfFE_P3dcLagrange::Pi_h_coef[]={1.,1.,1.,1.,1.,1.,1.,1.,1.,1.};
+  
+  void TypeOfFE_P3dcLagrange::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P1,RNMK_ & val) const
+  {
+    R2 P=Shrink1(P1);
+    R2 A(K[0]), B(K[1]),C(K[2]);
+    R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+    R L[3]={l0*k,l1*k,l2*k};
+    throwassert( val.N()>=10);
+    throwassert(val.M()==1);
+    // Attention il faut renumeroter les fonction de bases
+    //   car dans freefem++, il y a un node par sommet, arete or element
+    //   et la numerotation naturelle  mais 2 noud pas arete
+    //   donc p est la perumation
+    //   echange de numerotation si les arete sont dans le mauvais sens 
+    int p[10];
+    for(int i=0;i<10;++i)
+      p[i]=i;
+    /*
+    if(K.EdgeOrientation(0) <0) Exchange(p[3],p[4]);// 3,4
+    if(K.EdgeOrientation(1) <0) Exchange(p[5],p[6]);// 5,6 
+    if(K.EdgeOrientation(2) <0) Exchange(p[7],p[8]);// 7,8
+    */
+    //cout << KN_<int>(p,10) <<endl;
+    val=0; 
+    /*
+    //  les fonction de base du Pk Lagrange sont 
+    //  
+    //
+    */
+// -- 
+    
+    
+    if (whatd[op_id])
+      {
+	RN_ f0(val('.',0,op_id)); 
+	for (int df=0;df<ndf;df++)
+	  {
+	    int pdf=p[df];
+	    R f=1./ff[df];
+	    
+	    for( int i=0;i<k;++i)
+	      {
+		f *= L[nn[df][i]]-aa[df][i];
+		//cout <<  L[nn[df][i]]-aa[df][i]<< " ";
+	      }
+	    f0[pdf] = f;
+	    //cout << pdf<< " " << df << " f " <<f <<endl;
+	  }
+	//cout <<" L " << L[0] << " " << L[1] << " " << L[2] << endl;
+	//cout << ndf << " nbf = "<< f0 <<endl;
+      }
+    
+    
+    if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+      {
+	R ks=k*cshrink1;
+	R2 D[]={K.H(0)*ks, K.H(1)*ks,K.H(2)*ks };
+	if (whatd[op_dx] || whatd[op_dy] )
+	  {
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];
+		R fx=0.,fy=0.,f=1./ff[df];
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dx]) val(pdf,0,op_dx)=fx;
+		if(whatd[op_dy]) val(pdf,0,op_dy)=fy;		
+	      } 
+	  }
+	
+	if (whatd[op_dyy] ||whatd[op_dxy]|| whatd[op_dxx] )
+	  {  
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];		
+		R fx=0.,fy=0.,f=1./ff[df];
+		R fxx=0.,fyy=0.,fxy=0.;
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fxx=fxx*Ln+2.*fx*D[n].x;
+		    fyy=fyy*Ln+2.*fy*D[n].y;
+		    fxy=fxy*Ln+fx*D[n].y+fy*D[n].x;
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dxx]) val(pdf,0,op_dxx)=fxx;
+		if(whatd[op_dyy]) val(pdf,0,op_dyy)=fyy;
+		if(whatd[op_dxy]) val(pdf,0,op_dxy)=fxy;
+	      }
+	  }
+	
+      }
+  }
+#include "Element_P3dc.hpp"
+  
+
+
+// link with FreeFem++ 
+static TypeOfFE_P3dcLagrange P3dcLagrangeP3dc;
+// a static variable to add the finite element to freefem++
+static AddNewFE  P3dcLagrange("P3dc",&P3dcLagrangeP3dc); 
+} // FEM2d namespace 
+
+
+// --- fin -- 
+
diff --git a/examples++-load/Element_P3dc.hpp b/examples++-load/Element_P3dc.hpp
new file mode 100644
index 0000000..21600a5
--- /dev/null
+++ b/examples++-load/Element_P3dc.hpp
@@ -0,0 +1,28 @@
+ const int TypeOfFE_P3dcLagrange::nn[10][3] =  { 
+		 { 0 ,0 ,0 } ,
+		 { 1 ,1 ,1 } ,
+		 { 2 ,2 ,2 } ,
+		 { 1 ,1 ,2 } ,
+		 { 1 ,2 ,2 } ,
+		 { 0 ,2 ,2 } ,
+		 { 0 ,0 ,2 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,1 ,1 } ,
+		 { 0 ,1 ,2 } }
+;
+ const int TypeOfFE_P3dcLagrange::aa[10][3] =  { 
+		 { 0 ,1 ,2 } ,
+		 { 0 ,1 ,2 } ,
+		 { 0 ,1 ,2 } ,
+		 { 0 ,1 ,0 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,1 ,0 } ,
+		 { 0 ,1 ,0 } ,
+		 { 0 ,0 ,1 } ,
+		 { 0 ,0 ,0 } }
+;
+ const int TypeOfFE_P3dcLagrange::ff[10] =  { 6 ,6 ,6 ,2 ,2 ,2 ,2 ,2 ,2 ,1 };
+ const int TypeOfFE_P3dcLagrange::il[10] =  { 3 ,0 ,0 ,0 ,0 ,1 ,2 ,2 ,1 ,1 };
+ const int TypeOfFE_P3dcLagrange::jl[10] =  { 0 ,3 ,0 ,2 ,1 ,0 ,0 ,1 ,2 ,1 };
+ const int TypeOfFE_P3dcLagrange::kl[10] =  { 0 ,0 ,3 ,1 ,2 ,2 ,1 ,0 ,0 ,1 };
diff --git a/examples++-load/Element_P4.cpp b/examples++-load/Element_P4.cpp
new file mode 100644
index 0000000..1a5ab41
--- /dev/null
+++ b/examples++-load/Element_P4.cpp
@@ -0,0 +1,214 @@
+#include "ff++.hpp"
+#include "AddNewFE.h"
+// Attention probleme de numerotation des inconnues
+// -------------------------------------------------
+// dans freefem, il y a un noeud par objets  sommet, arete, element.
+// et donc la numerotation des dl dans l'element depend 
+// de l'orientation des aretes
+// 
+/// ---------------------------------------------------------------
+namespace  Fem2D {
+
+ // ------ P4  Hierarchical (just remove P1 node of the P2 finite element)  --------
+ class TypeOfFE_P4Lagrange : public  TypeOfFE { public:  
+   static const int k=4; 
+   static const int ndf = (k+2)*(k+1)/2;
+   static int Data[];
+   static double Pi_h_coef[];
+   static const int nn[15][4] ;
+   static const int aa[15][4] ;
+   static const int ff[15];
+   static const int il[15];
+   static const int jl[15];
+   static const int kl[15];
+    
+   
+   TypeOfFE_P4Lagrange(): TypeOfFE(3+3*3+3,1,Data,4,1,15+6,15,0)
+   {  
+     static const  R2 Pt[15] =  {
+       R2( 0/4. , 0/4. ) , 
+       R2( 4/4. , 0/4. ) , 
+       R2( 0/4. , 4/4. ) , 
+       R2( 3/4. , 1/4. ) , 
+       R2( 2/4. , 2/4. ) , 
+       R2( 1/4. , 3/4. ) , 
+       R2( 0/4. , 3/4. ) , 
+       R2( 0/4. , 2/4. ) , 
+       R2( 0/4. , 1/4. ) , 
+       R2( 1/4. , 0/4. ) , 
+       R2( 2/4. , 0/4. ) , 
+       R2( 3/4. , 0/4. ) , 
+       R2( 1/4. , 2/4. ) , 
+       R2( 2/4. , 1/4. ) , 
+       R2( 1/4. , 1/4. ) } 
+     ;
+     
+                       //    3,4,5, 6,7,8, 9,10,11, 
+     int other[15]= { 0,1,2, 5,4,3, 8,7,6, 11,10,9,12,13,14}; 
+     
+     int kk=0;
+     for (int i=0;i<NbDoF;i++) 
+       {
+	 pij_alpha[kk++]= IPJ(i,i,0);
+	 if(other[i]!=i)
+	   pij_alpha[kk++]= IPJ(i,other[i],0);
+	 P_Pi_h[i]=Pt[i]; 
+       }
+
+      assert(P_Pi_h.N()==NbDoF);
+      assert(pij_alpha.N()==kk);
+   }
+  
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+   {
+     for (int i=0;i<15+6;++i)
+       v[i]=1;
+     int e0=K.EdgeOrientation(0);
+     int e1=K.EdgeOrientation(1);
+     int e2=K.EdgeOrientation(2);
+     int ooo[6]={e0,e0,e1,e1,e2,e2};
+     /*   3,4
+	  5,
+	  6,7
+	  8,9,
+	  10,
+	  11,12,
+	  13,14,
+	  15
+	  16,17
+     */     
+     int iii[6]={3,6,8,11,13,16}; 
+     int jjj[6];
+     for(int i=0;i<6;++i)
+       { 
+         jjj[i]= iii[i]+1; // si orient = -1
+       }
+     for(int i=0;i<6;++i)
+       if(ooo[i]==1) v[jjj[i]]=0;
+       else v[iii[i]]=0;
+          
+   }
+ } ;
+  //                     on what     nu df on node node of df    
+  int TypeOfFE_P4Lagrange::Data[]={
+    0,1,2,3,3,3,4,4,4,5,5,5,6,6,6,     // the support number  of the node of the df 
+    0,0,0,0,1,2,0,1,2,0,1,2,0,1,2,     // the number of the df on  the node  
+    0,1,2,3,3,3,4,4,4,5,5,5,6,6,6,    // the node of the df 
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,     //  the df come from which FE (generaly 0)
+    0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,    //  which are de df on sub FE
+    0,                      // for each compontant $j=0,N-1$ it give the sub FE associated 
+    0,15 };
+  
+  void TypeOfFE_P4Lagrange::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+  {
+ 
+    R2 A(K[0]), B(K[1]),C(K[2]);
+    R l0=1.-P.x-P.y,l1=P.x,l2=P.y; 
+    R L[3]={l0*k,l1*k,l2*k};
+    throwassert( val.N()>=10);
+    throwassert(val.M()==1);
+    // Attention il faut renumeroter les fonction de bases
+    //   car dans freefem++, il y a un node par sommet, arete or element
+    //   et la numerotation naturelle  mais 2 noud pas arete
+    //   donc p est la perumation
+    //   echange de numerotation si les arete sont dans le mauvais sens 
+    int p[15];
+    for(int i=0;i<15;++i)
+      p[i]=i;
+    
+    if(K.EdgeOrientation(0) <0) Exchange(p[3],p[5]);// 3,4
+    if(K.EdgeOrientation(1) <0) Exchange(p[6],p[8]);// 5,6 
+    if(K.EdgeOrientation(2) <0) Exchange(p[9],p[11]);// 7,8
+    //cout << KN_<int>(p,10) <<endl;
+    val=0; 
+    /*
+    //  les fonction de base du Pk Lagrange sont 
+    //  
+    //
+    */
+// -- 
+    
+    
+    if (whatd[op_id])
+      {
+	RN_ f0(val('.',0,op_id)); 
+	for (int df=0;df<ndf;df++)
+	  {
+	    int pdf=p[df];
+	    R f=1./ff[df];
+	    
+	    for( int i=0;i<k;++i)
+	      {
+		f *= L[nn[df][i]]-aa[df][i];
+		//cout <<  L[nn[df][i]]-aa[df][i]<< " ";
+	      }
+	    f0[pdf] = f;
+	    //cout << pdf<< " " << df << " f " <<f <<endl;
+	  }
+	//cout <<" L " << L[0] << " " << L[1] << " " << L[2] << endl;
+	//cout << ndf << " nbf = "<< f0 <<endl;
+      }
+    
+    
+    if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+      {
+	R2 D[]={K.H(0)*k, K.H(1)*k,K.H(2)*k };
+	if (whatd[op_dx] || whatd[op_dy] )
+	  {
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];
+		R fx=0.,fy=0.,f=1./ff[df];
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dx]) val(pdf,0,op_dx)=fx;
+		if(whatd[op_dy]) val(pdf,0,op_dy)=fy;		
+	      } 
+	  }
+	
+	if (whatd[op_dyy] ||whatd[op_dxy]|| whatd[op_dxx] )
+	  {  
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];		
+		R fx=0.,fy=0.,f=1./ff[df];
+		R fxx=0.,fyy=0.,fxy=0.;
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fxx=fxx*Ln+2.*fx*D[n].x;
+		    fyy=fyy*Ln+2.*fy*D[n].y;
+		    fxy=fxy*Ln+fx*D[n].y+fy*D[n].x;
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dxx]) val(pdf,0,op_dxx)=fxx;
+		if(whatd[op_dyy]) val(pdf,0,op_dyy)=fyy;
+		if(whatd[op_dxy]) val(pdf,0,op_dxy)=fxy;
+	      }
+	  }
+	
+      }
+  }
+#include "Element_P4.hpp"
+  
+
+
+// link with FreeFem++ 
+static TypeOfFE_P4Lagrange P4LagrangeP4;
+// a static variable to add the finite element to freefem++
+static AddNewFE  P4Lagrange("P4",&P4LagrangeP4); 
+} // FEM2d namespace 
+
+
+// --- fin -- 
+
diff --git a/examples++-load/Element_P4.hpp b/examples++-load/Element_P4.hpp
new file mode 100644
index 0000000..7d8fe9a
--- /dev/null
+++ b/examples++-load/Element_P4.hpp
@@ -0,0 +1,38 @@
+const int TypeOfFE_P4Lagrange::nn[15][4] =  { 
+                 { 0 ,0 ,0 ,0 } ,
+                 { 1 ,1 ,1 ,1 } ,
+                 { 2 ,2 ,2 ,2 } ,
+                 { 1 ,1 ,1 ,2 } ,
+                 { 1 ,1 ,2 ,2 } ,
+                 { 1 ,2 ,2 ,2 } ,
+                 { 0 ,2 ,2 ,2 } ,
+                 { 0 ,0 ,2 ,2 } ,
+                 { 0 ,0 ,0 ,2 } ,
+                 { 0 ,0 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,1 } ,
+                 { 0 ,1 ,1 ,1 } ,
+                 { 0 ,1 ,2 ,2 } ,
+                 { 0 ,1 ,1 ,2 } ,
+                 { 0 ,0 ,1 ,2 } }
+;
+const int TypeOfFE_P4Lagrange::aa[15][4] =  { 
+                 { 0 ,1 ,2 ,3 } ,
+                 { 0 ,1 ,2 ,3 } ,
+                 { 0 ,1 ,2 ,3 } ,
+                 { 0 ,1 ,2 ,0 } ,
+                 { 0 ,1 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,2 } ,
+                 { 0 ,0 ,1 ,2 } ,
+                 { 0 ,1 ,0 ,1 } ,
+                 { 0 ,1 ,2 ,0 } ,
+                 { 0 ,1 ,2 ,0 } ,
+                 { 0 ,1 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,2 } ,
+                 { 0 ,0 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,0 } ,
+                 { 0 ,1 ,0 ,0 } }
+;
+const int TypeOfFE_P4Lagrange::ff[15] =  { 24 ,24 ,24 ,6 ,4 ,6 ,6 ,4 ,6 ,6 ,4 ,6 ,2 ,2 ,2 };
+const int TypeOfFE_P4Lagrange::il[15] =  { 4 ,0 ,0 ,0 ,0 ,0 ,1 ,2 ,3 ,3 ,2 ,1 ,1 ,1 ,2 };
+const int TypeOfFE_P4Lagrange::jl[15] =  { 0 ,4 ,0 ,3 ,2 ,1 ,0 ,0 ,0 ,1 ,2 ,3 ,1 ,2 ,1 };
+const int TypeOfFE_P4Lagrange::kl[15] =  { 0 ,0 ,4 ,1 ,2 ,3 ,3 ,2 ,1 ,0 ,0 ,0 ,2 ,1 ,1 };
diff --git a/examples++-load/Element_P4dc.cpp b/examples++-load/Element_P4dc.cpp
new file mode 100644
index 0000000..cbda9f3
--- /dev/null
+++ b/examples++-load/Element_P4dc.cpp
@@ -0,0 +1,213 @@
+#include "ff++.hpp"
+#include "AddNewFE.h"
+
+
+// Attention probleme de numerotation des inconnues
+// -------------------------------------------------
+// dans freefem, il y a un noeud par objets  sommet, arete, element.
+// et donc la numerotation des dl dans l'element depend 
+// de l'orientation des aretes
+// 
+/// ---------------------------------------------------------------
+namespace  Fem2D {
+
+ // ------ P4dc  Hierarchical (just remove P1 node of the P2 finite element)  --------
+ class TypeOfFE_P4dcLagrange : public  TypeOfFE { public:  
+   static const int k=4; 
+   static const int ndf = (k+2)*(k+1)/2;
+   static int Data[];
+   static double Pi_h_coef[];
+   static const int nn[15][4] ;
+   static const int aa[15][4] ;
+   static const int ff[15];
+   static const int il[15];
+   static const int jl[15];
+   static const int kl[15];
+    
+   static const R2 G;
+   static const R cshrink;
+   static const R cshrink1;
+   //  (1 -1/3)*
+    
+   static R2 Shrink(const R2& P){ return (P-G)*cshrink+G;}
+   static R2 Shrink1(const R2& P){ return (P-G)*cshrink1+G;}
+   
+   TypeOfFE_P4dcLagrange(): TypeOfFE(3+3*3+3,1,Data,4,1,15,15,Pi_h_coef)
+   {  
+     static const  R2 Pt[15] =  {
+       R2( 0/4. , 0/4. ) , 
+       R2( 4/4. , 0/4. ) , 
+       R2( 0/4. , 4/4. ) , 
+       R2( 3/4. , 1/4. ) , 
+       R2( 2/4. , 2/4. ) , 
+       R2( 1/4. , 3/4. ) , 
+       R2( 0/4. , 3/4. ) , 
+       R2( 0/4. , 2/4. ) , 
+       R2( 0/4. , 1/4. ) , 
+       R2( 1/4. , 0/4. ) , 
+       R2( 2/4. , 0/4. ) , 
+       R2( 3/4. , 0/4. ) , 
+       R2( 1/4. , 2/4. ) , 
+       R2( 2/4. , 1/4. ) , 
+       R2( 1/4. , 1/4. ) } 
+     ;
+     
+       for (int i=0;i<NbDoF;i++) {
+	   pij_alpha[i]= IPJ(i,i,0);
+	   P_Pi_h[i]=Shrink(Pt[i]); }
+       //    3,4,5, 6,7,8, 9,10,11, 
+   }
+  
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ /*  void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+   {
+     for (int i=0;i<15+6;++i)
+       v[i]=1;
+     int e0=K.EdgeOrientation(0);
+     int e1=K.EdgeOrientation(1);
+     int e2=K.EdgeOrientation(2);
+     int ooo[6]={e0,e0,e1,e1,e2,e2};
+    int iii[6]={3,6,8,11,13,16}; 
+     int jjj[6];
+     for(int i=0;i<6;++i)
+       { 
+         jjj[i]= iii[i]+1; // si orient = -1
+       }
+     for(int i=0;i<6;++i)
+       if(ooo[i]==1) v[jjj[i]]=0;
+       else v[iii[i]]=0;
+          
+   }
+   */
+ } ;
+
+  const R2 TypeOfFE_P4dcLagrange::G(1./3.,1./3.);   
+  const R TypeOfFE_P4dcLagrange::cshrink=1-1e-2;   
+  const R TypeOfFE_P4dcLagrange::cshrink1=1./TypeOfFE_P4dcLagrange::cshrink;   
+
+  //                     on what     nu df on node node of df    
+  int TypeOfFE_P4dcLagrange::Data[]={
+    6,6,6,6,6, 6,6,6,6,6 ,6,6,6,6,6,    //  the support number  of the node of the df 
+    0,1,2,3,4, 5,6,7,8,9 ,10,11,12,13,14,  // the number of the df on  the node  
+    0,0,0,0,0, 0,0,0,0,0 ,0,0,0,0,0,    // the node of the df 
+    0,0,0,0,0, 0,0,0,0,0 ,0,0,0,0,0,     //  the df come from which FE (generaly 0)
+    0,1,2,3,4, 5,6,7,8,9 ,10,11,12,13,14,    //  which are de df on sub FE
+    0,                      // for each compontant $j=0,N-1$ it give the sub FE associated 
+    
+    0, 15};
+  double TypeOfFE_P4dcLagrange::Pi_h_coef[]={ 1.,1.,1.,1.,1. ,1.,1.,1.,1.,1. ,1.,1.,1.,1.,1.};
+ 
+  void TypeOfFE_P4dcLagrange::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P1,RNMK_ & val) const
+  {
+    R2 P=Shrink1(P1);
+    R2 A(K[0]), B(K[1]),C(K[2]);
+    R l0=1.-P.x-P.y,l1=P.x,l2=P.y; 
+    R L[3]={l0*k,l1*k,l2*k};
+    throwassert( val.N()>=14);
+    throwassert(val.M()==1);
+    // Attention il faut renumeroter les fonction de bases
+    //   car dans freefem++, il y a un node par sommet, arete or element
+    //   et la numerotation naturelle  mais 2 noud pas arete
+    //   donc p est la perumation
+    //   echange de numerotation si les arete sont dans le mauvais sens 
+    int p[15];
+    for(int i=0;i<15;++i)
+      p[i]=i;
+    
+  //  if(K.EdgeOrientation(0) <0) Exchange(p[3],p[5]);// 3,4
+  // if(K.EdgeOrientation(1) <0) Exchange(p[6],p[8]);// 5,6 
+  //  if(K.EdgeOrientation(2) <0) Exchange(p[9],p[11]);// 7,8
+    //cout << KN_<int>(p,10) <<endl;
+    val=0; 
+    /*
+    //  les fonction de base du Pk Lagrange sont 
+    //  
+    //
+    */
+// -- 
+    
+    
+    if (whatd[op_id])
+      {
+	RN_ f0(val('.',0,op_id)); 
+	for (int df=0;df<ndf;df++)
+	  {
+	    int pdf=p[df];
+	    R f=1./ff[df];
+	    
+	    for( int i=0;i<k;++i)
+	      {
+		f *= L[nn[df][i]]-aa[df][i];
+		//cout <<  L[nn[df][i]]-aa[df][i]<< " ";
+	      }
+	    f0[pdf] = f;
+	    //cout << pdf<< " " << df << " f " <<f <<endl;
+	  }
+	//cout <<" L " << L[0] << " " << L[1] << " " << L[2] << endl;
+	//cout << ndf << " nbf = "<< f0 <<endl;
+      }
+    
+    
+    if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+      {
+	R ks=k*cshrink1;
+	R2 D[]={K.H(0)*ks, K.H(1)*ks,K.H(2)*ks };
+	if (whatd[op_dx] || whatd[op_dy] )
+	  {
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];
+		R fx=0.,fy=0.,f=1./ff[df];
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dx]) val(pdf,0,op_dx)=fx;
+		if(whatd[op_dy]) val(pdf,0,op_dy)=fy;		
+	      } 
+	  }
+	
+	if (whatd[op_dyy] ||whatd[op_dxy]|| whatd[op_dxx] )
+	  {  
+	    for (int df=0;df<ndf;df++)
+	      {
+		int pdf=p[df];		
+		R fx=0.,fy=0.,f=1./ff[df];
+		R fxx=0.,fyy=0.,fxy=0.;
+		for( int i=0;i<k;++i) 
+		  {
+		    int n= nn[df][i];
+		    R Ln=L[n]-aa[df][i];
+		    fxx=fxx*Ln+2.*fx*D[n].x;
+		    fyy=fyy*Ln+2.*fy*D[n].y;
+		    fxy=fxy*Ln+fx*D[n].y+fy*D[n].x;
+		    fx= fx*Ln+f*D[n].x;
+		    fy= fy*Ln+f*D[n].y;
+		    f = f*Ln;
+		  } 
+		if(whatd[op_dxx]) val(pdf,0,op_dxx)=fxx;
+		if(whatd[op_dyy]) val(pdf,0,op_dyy)=fyy;
+		if(whatd[op_dxy]) val(pdf,0,op_dxy)=fxy;
+	      }
+	  }
+	
+      }
+  }
+
+#include "Element_P4dc.hpp"
+  
+
+
+// link with FreeFem++ 
+static TypeOfFE_P4dcLagrange P4dcLagrangeP4dc;
+// a static variable to add the finite element to freefem++
+static AddNewFE  P4dcLagrange("P4dc",&P4dcLagrangeP4dc); 
+} // FEM2d namespace 
+
+
+// --- fin -- 
+
diff --git a/examples++-load/Element_P4dc.hpp b/examples++-load/Element_P4dc.hpp
new file mode 100644
index 0000000..6613058
--- /dev/null
+++ b/examples++-load/Element_P4dc.hpp
@@ -0,0 +1,38 @@
+const int TypeOfFE_P4dcLagrange::nn[15][4] =  { 
+                 { 0 ,0 ,0 ,0 } ,
+                 { 1 ,1 ,1 ,1 } ,
+                 { 2 ,2 ,2 ,2 } ,
+                 { 1 ,1 ,1 ,2 } ,
+                 { 1 ,1 ,2 ,2 } ,
+                 { 1 ,2 ,2 ,2 } ,
+                 { 0 ,2 ,2 ,2 } ,
+                 { 0 ,0 ,2 ,2 } ,
+                 { 0 ,0 ,0 ,2 } ,
+                 { 0 ,0 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,1 } ,
+                 { 0 ,1 ,1 ,1 } ,
+                 { 0 ,1 ,2 ,2 } ,
+                 { 0 ,1 ,1 ,2 } ,
+                 { 0 ,0 ,1 ,2 } }
+;
+const int TypeOfFE_P4dcLagrange::aa[15][4] =  { 
+                 { 0 ,1 ,2 ,3 } ,
+                 { 0 ,1 ,2 ,3 } ,
+                 { 0 ,1 ,2 ,3 } ,
+                 { 0 ,1 ,2 ,0 } ,
+                 { 0 ,1 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,2 } ,
+                 { 0 ,0 ,1 ,2 } ,
+                 { 0 ,1 ,0 ,1 } ,
+                 { 0 ,1 ,2 ,0 } ,
+                 { 0 ,1 ,2 ,0 } ,
+                 { 0 ,1 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,2 } ,
+                 { 0 ,0 ,0 ,1 } ,
+                 { 0 ,0 ,1 ,0 } ,
+                 { 0 ,1 ,0 ,0 } }
+;
+const int TypeOfFE_P4dcLagrange::ff[15] =  { 24 ,24 ,24 ,6 ,4 ,6 ,6 ,4 ,6 ,6 ,4 ,6 ,2 ,2 ,2 };
+const int TypeOfFE_P4dcLagrange::il[15] =  { 4 ,0 ,0 ,0 ,0 ,0 ,1 ,2 ,3 ,3 ,2 ,1 ,1 ,1 ,2 };
+const int TypeOfFE_P4dcLagrange::jl[15] =  { 0 ,4 ,0 ,3 ,2 ,1 ,0 ,0 ,0 ,1 ,2 ,3 ,1 ,2 ,1 };
+const int TypeOfFE_P4dcLagrange::kl[15] =  { 0 ,0 ,4 ,1 ,2 ,3 ,3 ,2 ,1 ,0 ,0 ,0 ,2 ,1 ,1 };
diff --git a/examples++-load/Element_PkEdge.cpp b/examples++-load/Element_PkEdge.cpp
new file mode 100644
index 0000000..0d4370a
--- /dev/null
+++ b/examples++-load/Element_PkEdge.cpp
@@ -0,0 +1,183 @@
+#include "ff++.hpp"
+#include "AddNewFE.h"
+
+// Attention probleme de numerotation des inconnues
+// -------------------------------------------------
+// dans freefem, il y a un noeud par objets  sommet, arete, element.
+// et donc la numerotation des dl dans l'element depend 
+// de l'orientation des aretes
+// 
+/// ---------------------------------------------------------------
+namespace  Fem2D {
+  struct  InitTypeOfFE_PkEdge
+  {
+    int k;//  order poly on edge
+    int npe; // nb point on edge
+    int ndf; // nb dof
+    KN<R> X;  //  point on edge
+    //    KN<R> Pi_h_coef; // 1
+    KN<int> Data; // data of TypeOfFE
+    InitTypeOfFE_PkEdge(int KK) 
+      :k(KK),npe(k+1),ndf(3*npe),X(npe),Data( 5*ndf+3)
+    {
+      //Pi_h_coef=1.;
+      const QuadratureFormular1d QF(-1+2*npe,npe,GaussLegendre(npe),true);
+      for (int i=0;i<npe;++i)
+	X[i]=QF[i].x;
+      HeapSort((R *) X,npe);
+      int j=0;
+      int o[6];
+      o[0]=0;
+      for(int i=1;i<6;++i)
+	o[i]=o[i-1]+ndf;
+      for(int df=0;df<ndf;++df)
+	{
+	  int e= df/npe;
+	  int n= df%npe;
+          Data[o[0]+df]=3+e;
+          Data[o[1]+df]=n;
+          Data[o[2]+df]=e;
+          Data[o[3]+df]=0;
+          Data[o[4]+df]=df;
+	}
+      Data[o[5]] =0;
+      Data[o[5]+1] =0 ;
+      Data[o[5]+2] =ndf;// end_dfcomp 
+
+    }
+  };
+
+  class TypeOfFE_PkEdge :public InitTypeOfFE_PkEdge, public  TypeOfFE { 
+  public:  
+    static double Pi_h_coef[];
+    
+    
+    TypeOfFE_PkEdge(int KK)
+      :  InitTypeOfFE_PkEdge(KK),
+	 TypeOfFE(ndf,1,Data,-k,1,ndf*2,ndf,0)
+    {  
+      //      cout << " Pk = " << k << endl;
+      int kkk=0;
+      for (int i=0;i<NbDoF;i++) 
+	{
+	  int e= i/npe;
+	  int j= i%npe;
+	  int ii= e*npe+npe-j-1;
+	  R2 A(TriangleHat[VerticesOfTriangularEdge[e][0]]);
+	  R2 B(TriangleHat[VerticesOfTriangularEdge[e][1]]);	 
+	  pij_alpha[kkk++]= IPJ(i,i,0);
+	  pij_alpha[kkk++]= IPJ(i,ii,0);
+	  P_Pi_h[i]= A*(1.-X[j])+ B*(X[j]);// X=0 => A  X=1 => B;       
+	  //  cout << P_Pi_h[i]<< endl;;
+	}
+
+    }
+
+   void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+   {
+     int kkk=0;
+     for (int e=0;e<3;++e)
+       {
+	 int i0=0;
+	 if( K.EdgeOrientation(e)<0.)
+	   i0=1-i0;
+	 int i1=1-i0;
+	 for(int p=0;p<npe;++p)
+	   {
+	     v[kkk+i0]=0;
+	     v[kkk+i1]=1;
+	     kkk+=2;
+	   }
+       }  
+     //cout << " v :" << v << endl;
+   }
+    
+    void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+    } ;
+  // ENDOFCLASS TypeOfFE_PkEdge    
+    
+    void TypeOfFE_PkEdge::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+    {
+      
+      R2 A(K[0]), B(K[1]),C(K[2]);
+      R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+      R L[3]={l0,l1,l2};
+      assert( val.N()>=ndf);
+      assert(val.M()==1);
+      int ee=0;
+      if (L[0] <= min(L[1],L[2]) ) ee=0; // arete  
+      else if  (L[1] <= min(L[0],L[2]) ) ee=1;
+      else ee=2;
+      int e3=ee*npe;
+      double s=1.-L[ee];
+      R xe = L[VerticesOfTriangularEdge[ee][0]]/s;//  go from 0 to 1 on edge
+      R dxe = -1;
+      if(K.EdgeOrientation(ee) <0.) 
+          xe = 1-xe, dxe=-1;
+      //cout << P << " ee = " << ee << " xe " << xe << " " << L[ee]<< " s=" <<s  << " orient: " << K.EdgeOrientation(ee) <<endl;
+      assert(s);
+      val=0; 
+      if (whatd[op_id])
+	{
+	  RN_ f0(val('.',0,op_id)); 
+	  for (int l=0;l<npe;l++)
+	    {
+	      int dof= e3+l;
+	      R f=1.;
+	      for (int i=0;i<npe;++i)
+		if(i != l) 
+		  f *= (xe-X[i])/(X[l]-X[i]);
+	      f0[dof] = f;
+	    }
+	  //cout << " f0 = " << f0 << " X= "<< X << endl;
+	}
+
+      
+      if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+	{
+            R2 E =K.Edge(ee);
+            R lE2=(E,E);
+            dxe /=lE2;
+            //cout << " xe = "<< xe << " " << dxe << " " << lE2 << endl;
+            for (int l=0;l<npe;l++)
+            {
+                int dof= e3+l;
+                R f=1. ,df = 0., ddf = 0.;
+                for (int i=0;i<npe;++i)
+                    if(i != l)
+                    {   R xx=(xe-X[i])/(X[l]-X[i]);
+                        R dxx= dxe/(X[l]-X[i]);
+                        ddf = ddf* xx + 2*df*dxx;
+                        df = df* xx + f*dxx;
+                        f *= xx;
+                    }
+               // cout << "   dof: " << dof << " " << f << " " << df << " " << 1./lE2/(X[1]- X[0]) << " " << E << endl;
+                if( whatd[op_id])val(dof,0,op_id)= f;
+                if( whatd[op_dx]) val(dof,0,op_dx)= df*E.x;
+                if( whatd[op_dy]) val(dof,0,op_dy)= df*E.y;
+                if( whatd[op_dxx]) val(dof,0,op_dxx)= ddf*E.x*E.x;
+                if( whatd[op_dyy]) val(dof,0,op_dyy)= ddf*E.y*E.y;
+                if( whatd[op_dxy]) val(dof,0,op_dxy)= ddf*E.x*E.y;
+               
+            }
+    	}
+    }
+
+  
+  // link with FreeFem++ 
+  static TypeOfFE_PkEdge PkEdgeP1(1);
+  static TypeOfFE_PkEdge PkEdgeP2(2);
+  static TypeOfFE_PkEdge PkEdgeP3(3);
+  static TypeOfFE_PkEdge PkEdgeP4(4);
+  static TypeOfFE_PkEdge PkEdgeP5(5);
+  // a static variable to add the finite element to freefem++
+  static AddNewFE  P1Edge("P1edge",&PkEdgeP1); 
+  static AddNewFE  P2Edge("P2edge",&PkEdgeP2); 
+  static AddNewFE  P3Edge("P3edge",&PkEdgeP3); 
+  static AddNewFE  P4Edge("P4edge",&PkEdgeP4); 
+  static AddNewFE  P5Edge("P5edge",&PkEdgeP5); 
+} // FEM2d namespace 
+
+
+// --- fin -- 
+
diff --git a/examples++-load/ExampleMetrics.h b/examples++-load/ExampleMetrics.h
new file mode 100755
index 0000000..4f3c0d4
--- /dev/null
+++ b/examples++-load/ExampleMetrics.h
@@ -0,0 +1,117 @@
+//
+//  ExampleMetrics.h
+//  MeshGen
+//
+//  Created by Jean-Marie Mirebeau on 08/06/11.
+//  Copyright 2011 UPMC. All rights reserved.
+//
+#ifndef EXAMPLE_METRICS_H
+#define EXAMPLE_METRICS_H
+
+#include "math.h"
+#include "RZ.h"
+
+// ********** functions ***********
+
+/*
+ Some riemannian metrics on the unit square or cube, for the purpose of testing algorithms. 
+ */
+
+template <int whichMetric> const sym2 ExampleMetric(const R2 & P);
+template <int whichMetric> const sym3 ExampleMetric3D(const R3 & P);
+
+/********************** 2D *****************/
+
+template<>
+const sym2 ExampleMetric<0>(const R2 & P){return sym2(1,0,1);}    //identity
+
+template<>
+const sym2 ExampleMetric<1>(const R2 & P){    //A piecewise constant anisotropic metric
+    const double scal = fabs(P.x-1/2.)<1/6. ? 4 : 1;
+    return sym2(scal,-scal,4*scal);
+}
+
+template<>
+const sym2 ExampleMetric<2>(const R2 & P){    //circle, regularity Graded.
+    const double delta = 0.03; //paramètre
+    
+    const R2 Q = P - R2(0.5,0.5);
+    const double r= Q.norm(); 
+    const double h = max(fabs(r-1/2.),delta);
+    
+    return sym2(1/(h*h), 1/h, Q);
+}
+
+template<>
+const sym2 ExampleMetric<3>(const R2 & P){    //circle, regularity QuasiAcute.
+    const double delta = 0.4; //paramètre
+    
+    const R2 Q = P - R2(0.5,0.5);
+    const double r = Q.norm(); 
+    const double h = max(fabs(r-1/2.),delta);
+    const double k = max(fabs(r-1/2.),delta*delta);
+    
+    return sym2(1/(k*k), 1/(h*h), Q);
+}
+
+template<>
+const sym2 ExampleMetric<4>(const R2 & P){return sym2(10,0,1);}    //diagonal
+
+template<>
+const sym2 ExampleMetric<5>(const R2 & P){    //High anisotropy along the spiral r=k(theta+2 mu Pi), mu in {0,1,2}.
+    const double pi = 4*atan(1);
+    const double width = 0.006;
+    const double k= 0.4/(6*pi);
+    const double mu = 100.;
+    
+    const R2 Q = P-R2(0.5,0.5);
+    const double r = Q.norm();
+    double theta = Q.x==-r ? pi : 2*atan(Q.y/(r+Q.x)); //theta = theta >= 0 ? theta : theta+pi;
+    
+    if(fabs(r-k*theta) <= width){theta = theta;}
+    else if (fabs(r-k*(theta+2*pi)) <= width) {theta = theta+2*pi;}
+    else if (fabs(r-k*(theta+4*pi)) <= width) {theta = theta+4*pi;}
+    else if (fabs(r-k*(theta+6*pi)) <= width && theta <=0) {theta = theta+6*pi;}
+    else return sym2(1,0,1); //{metric[0]=1; metric[1]=0; metric[2]=1; break;}
+    
+    double c= cos(theta)-theta*sin(theta), s=sin(theta)+theta*cos(theta); //tangente à la spirale
+    double cOld=c; c=-s; s=cOld;
+    
+    return sym2(1,1/(mu*mu),R2(c,s));
+}
+
+template<>
+const sym2 ExampleMetric<6>(const R2 & P){    //high but constant anisotropy
+    const double mu=30., t = 0.3; R2 Q(cos(t),sin(t));
+    return sym2(1,1/(mu*mu), Q);
+}
+
+template<> const sym2 ExampleMetric<7>(const R2 & P){const double s=0.1+(P-R2(0.1,0.2)).norm(); return sym2()/square(s);}
+template<> const sym2 ExampleMetric<8>(const R2 & P){const double s=0.1+(P-R2(0.1,0.2)).norm(); return sym2(100,1,R2(1/2.,sqrt(3.)/2))/square(s);}
+template<> const sym2 ExampleMetric<9>(const R2 & P){const double s=0.1+fabs(P.x); return sym2(100,0,1)/square(s);}
+
+//template<int whichMetric> sym2 coExampleMetric(const R2 & P){return ExampleMetric<whichMetric>(P).comatrix();}
+
+/************************ 3D *************************/
+
+template<>
+const sym3 ExampleMetric3D<0>(const R3 & P){return sym3(1,1,1,0,0,0);}
+
+template<>
+const sym3 ExampleMetric3D<1>(const R3 & P){return sym3(1,10,100,0,0,0);}
+
+template<>
+const sym3 ExampleMetric3D<2>(const R3 & P){return sym3(1,10,R3(0.1,-0.2,0.4));}
+
+template<>
+const sym3 ExampleMetric3D<3>(const R3 & P){ // tire bouchon...
+    const double r0 = 0.33; const double theta0 = 4*M_PI;
+    const double delta0 = 0.06; const double mu = 1/8.;
+    
+    const R3 Q(P.x-0.5, P.y-0.5, P.z-0.5);
+    const double r = sqrt(Q.x*Q.x+Q.y*Q.y);
+    if(fabs(r-r0) > delta0) return sym3();
+    if(square(Q.x-r*cos(theta0*Q.z))+ square(Q.y-r*sin(theta0*Q.z)) > square(r*delta0)) return sym3();
+    return sym3(mu*mu, 1, R3( -r0*theta0*sin(theta0*Q.z), r0*theta0*cos(theta0*Q.z), 1)); 
+}
+#endif
\ No newline at end of file
diff --git a/examples++-load/FreeFemQA.cpp b/examples++-load/FreeFemQA.cpp
new file mode 100644
index 0000000..417bd0e
--- /dev/null
+++ b/examples++-load/FreeFemQA.cpp
@@ -0,0 +1,188 @@
+//
+//  FreeFamQA.cpp
+//  
+//
+//  Created by Jean-Marie Mirebeau on 09/10/11.
+//  Copyright 2011 UPMC. All rights reserved.
+//
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+//compilation : ff-c++ FreeFemQA.cpp -I/usr/local/boost_1_47_0
+//ff-c++-cpp-dep: GeometryQA.cpp 
+#include  <iostream>
+#include  <cfloat>
+#include  <cmath>
+using namespace std;
+#include "ff++.hpp" 
+using namespace Fem2D;
+
+//#include <boost/operators.hpp>
+namespace mir {
+#define _FLAGGED_BOUNDARY_
+#include "Geometry.hpp"
+}
+ 
+//the main class
+//details of FreeFem meshes (connectivity, etc) in file GenericMesh.hpp
+
+class MeshGenQA :  public E_F0mps 
+{
+public:
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =7;
+    
+    Expression nargs[n_name_param];// store named args
+    
+    typedef Mesh *  Result;
+    Expression expTh;
+    Expression expM11;
+    Expression expM12;
+    Expression expM22;
+    
+    MeshGenQA(const basicAC_F0 & args)
+    {
+        args.SetNameParam(n_name_param,name_param,nargs);// named args
+        expTh= to<pmesh>(args[0]);  // a the expression to get the mesh
+        expM11= to<double>(args[1]);  
+        expM12= to<double>(args[2]);  
+        expM22= to<double>(args[3]);  
+    }
+    double arg(int i,Stack stack,double a) const { return nargs[i] ? GetAny<double>( (*nargs[i])(stack) ): a;}
+    long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    bool arg(int i,Stack stack,bool a) const{ return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+    KN<double> * arg(int i,Stack stack,KN<double> * a) const{ return nargs[i] ? GetAny<KN<double> *>( (*nargs[i])(stack) ): a;}
+    
+    
+    ~MeshGenQA(){}
+    
+    static ArrayOfaType  typeargs()
+    { return  ArrayOfaType(
+                           atype<pmesh>(),
+                           atype<double>(),
+                           atype<double>(),
+                           atype<double>()
+                           );;
+    }
+    static  E_F0 * f(const basicAC_F0 & args){ return new MeshGenQA(args);}
+    AnyType operator()(Stack s) const ;// la vraie fonction qui fait faire le boulot     
+};
+
+basicAC_F0::name_and_type MeshGenQA::name_param[MeshGenQA::n_name_param] = {
+    //{ "flag",               &typeid(long)},
+    { "noIsoRef",               &typeid(bool)},
+    { "finalRefine",            &typeid(bool)},
+    { "exportIntermediateData", &typeid(bool)},
+    { "Lip",                    &typeid(double)},
+    { "exportToMathematica",    &typeid(bool)},
+    { "exportMetricToMathematica",&typeid(bool)},
+    { "noRef",                  &typeid(bool)}
+};
+
+AnyType MeshGenQA:: operator()(Stack stack) const 
+{   
+    //const long  flag = arg(0,stack,0L);
+    const bool noIsoRef = arg(0,stack,false);
+    const bool finalRefine = arg(1,stack,false);
+    const bool exportIntermediateData = arg(2,stack,false);
+
+    
+    unsigned int flag = 0;
+    if(noIsoRef)                flag |= mir::Triangulation::hRQA_noIsoRef;
+    if(finalRefine)             flag |= mir::Triangulation::hRQA_finalRefine;
+    if(exportIntermediateData)  flag |= mir::Triangulation::hRQA_exportIntermediateData;
+    
+    const double Lip = arg(3,stack,5.);
+    const bool exportToMathematica = arg(4, stack, false);
+    const bool exportMetricToMathematica = arg(5, stack, false);
+    const bool noRef = arg(6, stack, false);
+    
+    Mesh * pTh = GetAny<pmesh>((*expTh)(stack));
+    ffassert(pTh);
+    const Mesh & Th= *pTh;
+        
+    class FFMetric2 : public mir::Metric2 {
+        const MeshGenQA &MGQA_;
+        Stack stack_;
+    public:
+        FFMetric2(const MeshGenQA &MGQA, Stack stack, double Lip):MGQA_(MGQA),stack_(stack){lip=Lip;}
+        const mir::sym2 operator()(const mir::R2 &P) const {
+            MeshPointStack(stack_)->set(P.x,P.y); //needs to be done three times ?
+            MeshPointStack(stack_)->set(P.x,P.y);
+            MeshPointStack(stack_)->set(P.x,P.y);
+            return mir::sym2(GetAny<double>((*MGQA_.expM11)(stack_)), 
+                             GetAny<double>((*MGQA_.expM12)(stack_)),
+                             GetAny<double>((*MGQA_.expM22)(stack_))
+                             );
+        }
+    };
+    
+    FFMetric2 ffMetric(*this,stack,Lip);
+    const mir::Metric2 &metric = ffMetric;
+        
+    mir::Triangulation triQA(Th,metric);
+    if(!triQA.check()) {cout << "MeshGenQA : Error while importing mesh !\n"; return false;}
+       
+    if(exportToMathematica) triQA.export_to_Mathematica("ThFF.txt");
+    if(exportMetricToMathematica) triQA.export_to_Mathematica_Metric("ThFF_Metric.txt");
+    
+    if(!noRef) triQA.hRefineQA(1, flag);
+    
+    triQA.export_to_FreeFem("triQA.msh");
+    
+    if(exportToMathematica) triQA.export_to_Mathematica("TriQA.txt");
+    if(exportMetricToMathematica) triQA.export_to_Mathematica_Metric("TriQA_Metric.txt");
+    
+    /*
+    if(exportToMathematica) {
+        vector<double> gains;
+        gains.resize(triQA.ne_oriented());
+        for(int i=0; i<triQA.ne_oriented(); ++i)
+            gains[i]=triQA.getEdges()[i].flipGain();
+        ofstream data_out; data_out.open("gains.txt"); 
+        mir::print_array(data_out << mir::Mathematica, gains.begin(), gains.end());
+        data_out.close();
+    }*/
+
+  //  generation de la class Mesh a partir des 3 tableaux : v,t,b
+  {
+    Mesh * m = triQA.export_to_Mesh(); // new Mesh(nbv+nbt,nbt*3,neb,v,t,b);
+    R2 Pn,Px;
+    m->BoundingBox(Pn,Px);
+    m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+    m->decrement();
+    return m;
+  }
+
+};
+
+/*  class Init { public:
+    Init();
+};
+
+$1 */
+
+// Init init;
+static void Load_Init()
+{
+    cout << "\n  -- lood: init MeshGenQA\n";
+    Global.Add("MeshGenQA","(", new OneOperatorCode<MeshGenQA >( ));
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/Geometry.hpp b/examples++-load/Geometry.hpp
new file mode 100644
index 0000000..b254a57
--- /dev/null
+++ b/examples++-load/Geometry.hpp
@@ -0,0 +1,232 @@
+ //
+//  Geometry.h
+//  DelaunayFlip
+//
+//  Created by Jean-Marie Mirebeau on 15/07/11.
+//  Copyright 2011 UPMC. All rights reserved.
+//
+#ifndef GEOMETRY
+#define GEOMETRY
+
+#include <iostream>
+#include "RZ.h"
+#include "SortedList.h"
+
+using namespace std;
+
+/**************** Vertex ******************/
+class Vertex : public R2 { //heritage is perhaps not totally justified here, but...
+    sym2 m;
+    int gen;
+    //friend int main(int argc, const char * argv[]); //for Debug purposes
+public: 
+    Vertex():R2(),m(){};
+    Vertex(R2 u, int Gen, sym2 metric=sym2()) : R2(u), gen(Gen), m(metric) {}
+    Vertex(R2 u, int Gen, const Metric2 &metric) : R2(u), gen(Gen), m(metric(u)) {}
+    
+    const sym2 & getm() const {return m;}
+    int getGen() const {return gen;}
+    sym3 homogeneousDistance() const {const R2 a(*this); const R2 ma=m*a; const double ama=a.scal(ma); return sym3(m.xx, m.yy, ama, m.xy, -ma.y, -ma.x);}
+    double dist2(const R2 &P) const {return m.norm2(*this-P);}
+};
+
+/*inline ostream& operator<<(ostream &f, const Vertex &u){f<<R2(u)<<u.getGen(); return f;}
+inline ostream_math operator<<(ostream_math f, const Vertex &u){
+    if(f.format==Mathematica) f<<"{"<<R2(u)<<","<<u.getGen()<<"}"; else f.os<<u; return f;}
+*/
+inline ostream& operator<<(ostream &f, const Vertex &u){return f<<R2(u);}
+inline ostream_math operator<<(ostream_math f, const Vertex &u){return f<<"{"<<R2(u)<<","<<u.getGen()<<","<<u.getm()<<"}";}
+
+
+/****************** Edge ****************/
+class Edge { //edges are oriented. t is on the left.
+//    bool refinable;
+    Vertex const *u; Vertex const *v; // Note : routines tend to leave v constant when possible (i.e. except construct and flip)
+    Edge *next, *sister; //next edge on triangle and reversed edge
+    Edge * prev() const {return next->next;}
+    bool cut(Vertex const *start, Vertex const *end, Edge *oldSister, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, 
+             const Metric2 &metric, vector<Edge*> & aligned);
+    //friend int main(int argc, const char * argv[]); //for Debug purposes
+#ifdef _FLAGGED_BOUNDARY_
+    int onBoundary_;
+#endif
+    
+public:
+    Edge():u(NULL),v(NULL),next(NULL),sister(NULL){};
+    
+#ifdef _FLAGGED_BOUNDARY_
+    Edge(Vertex const *U, Vertex const *V, Edge *S, Edge *N, int OnBoundary_=0):u(U),v(V),sister(S),next(N),onBoundary_(OnBoundary_){};
+    int onBoundary() const {return onBoundary_;} //{if(sister!=NULL) return 0; if(onBoundary_>0) return onBoundary_; return 10;}
+#else
+    Edge(Vertex const *U, Vertex const *V, Edge *S, Edge *N):u(U),v(V),next(N),sister(S){};
+    bool onBoundary() const {return sister==NULL;}
+#endif
+    
+    inline bool flipable() const;
+    inline double flipGain() const ; //gain brought by a flip in terms of square cosine
+
+    inline bool flip();
+    inline bool flip(Edge * affected[4]);
+    inline bool flip_resolve();
+    Vertex const * getu() const {return u;} Vertex const * getv() const {return v;}
+    R2 vec() const {return *v-*u;} //R2(v->x - u->x, v->y - u->y)
+//    R2 midPoint(){return R2((v->x + u->x)/2, (v->y + u->y)/2);}
+//    R2 bary() const {if(sister==NULL) return (*u+*v)/2; return (*u +*v +*next->v +*sister->next->v)/4;}
+    
+    bool isRepresentative() const {return (sister==NULL) || (u->x < v->x) || (u->x == v->x && u->y < v->y);}
+    Edge * representative(){return isRepresentative() ? this : sister;}
+    bool isRepresentative3() const {R2 v=vec(); return v<next->vec() && v<prev()->vec();}
+    bool isRepresentative3(Vertex const *triangle[3]) const {triangle[0]=u; triangle[1]=v; triangle[2]=next->v; return isRepresentative3();}
+    
+    enum refinement_priority {selected_edge_first, newest_vertex_first, euclidean_longest_edge_first};
+    Edge * which_first(refinement_priority priority);
+    //refine splits the edge and returns a pointer to the other half of the splitted edge //bool newestVertexFirst=true
+    Edge * refine(Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, const Metric2 &metric, refinement_priority priority);
+    //splits associated triangle if larger than size h/sqrt(smallEigenVal) (metric taken at the worst point on the triangle). Non recursive.
+    bool hRefine3(double h, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, const Metric2 &metric, refinement_priority priority);
+    //splits the edge if its length in the metric (taken at the worst point on the edge) is larger than h.
+    Edge * hRefine2(double h, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, const Metric2 &metric, safe_vector<Edge*> *recursive=NULL, bool exaggerate=false);
+    bool check() const;
+    
+    Edge * getNext() const {return next;}
+    Edge * getSister() const {return sister;}
+    
+    bool cut(Vertex const *start, Vertex const *end, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, 
+             const Metric2 &metric, vector<Edge*> & aligned);
+    Vertex *intersect(Vertex const *start, Vertex const *end, Tab<Vertex> &VertexAllocator, const Metric2 &metric);
+};
+inline ostream& operator<<(ostream &f, const Edge &e){f<<R2(*(e.getu()))<<" "<<R2(*(e.getv())); return f;}
+inline ostream_math operator<<(ostream_math f, const Edge &e){
+    if(f.format==Mathematica) f<<"{"<<R2(*(e.getu()))<<","<<R2(*(e.getv()))<<"}"; else f.os<<e; return f;}
+
+inline bool Edge::check() const {
+    if(u==NULL || v==NULL) cout << "Edge::check : Invalid extremities"; 
+    else if(u==v) cout << "Edge::check : identical extremities"; 
+    else if(next==NULL || next->next==NULL) cout<<"Edge::check : Missing edge connections"; 
+    else if(next->next->next!=this) cout<<"Edge::check : not a triangle"; 
+    else if(next->u!=v) cout<<"Edge::check : invalid next edge (next->u!=v)";
+    else if(sister!=NULL && sister->u!=v) cout<<"Edge::check : invalid sister edge";
+//    else if(sister!=NULL && refinable && !sister->refinable) cout<<"Edge::check : flag refinable inconsistent with sister edge"<<endl;
+    else if(isRepresentative3() && det(vec(),next->vec())<0) cout<<"Edge::check : trigonometric order not respected";
+#ifdef _FLAGGED_BOUNDARY_
+    else if(sister==NULL && onBoundary_==0) cout << "Edge::check : Interior edge without sister !" << endl;
+#endif
+    else return true;
+    coutMath << " " << *this << *next << *next->next << endl;
+    return false;
+}
+
+inline bool Edge::flipable() const {
+    return !onBoundary() && det(sister->prev()->vec(),next->vec())>0 && det(prev()->vec(),sister->next->vec())>0; 
+}
+
+inline double Edge::flipGain() const { //edge is assumed to be flipable, hence angles are <pi. Result positive <=> flip increases minimum angle.
+    if(!flipable()) return 0;
+    Vertex const *s=next->v; Vertex const *t=sister->next->v;
+    const R2 uv=*v-*u, st=*t-*s, vs=*s-*v, su=*u-*s, ut=*t-*u, tv=*v-*t;
+    const sym2 &mu=u->getm(), &mv=v->getm(), ms=s->getm(), mt=t->getm(); 
+    return 
+    min(min(min(-ms.cos(st,vs), ms.cos(st,su)), min(mt.cos(st,ut), -mt.cos(st,tv))),min(-mu.cos(su,ut),-mv.cos(tv,vs)))-
+    min(min(min(-mu.cos(uv,su), mu.cos(uv,ut)), min(mv.cos(uv,tv), -mv.cos(uv,vs))),min(-ms.cos(vs,su),-mt.cos(ut,tv)));
+//    max(max(mu.cos2(uv,su), mu.cos2(uv,ut)), max(mv.cos2(uv,tv), mv.cos2(uv,vs))) -
+//    max(max(ms.cos2(st,vs), ms.cos2(st,su)), max(mt.cos2(st,ut), mt.cos2(st,tv)));
+} 
+
+inline bool Edge::flip(){
+    if(sister==NULL) return false; //triangle inversion is unchecked
+    
+    Edge *e=this, *f=sister;
+    Edge *ep=prev(), *fp=sister->prev();
+    Vertex const *u=ep->u; Vertex const *v=fp->u;
+    
+    e->u=u; e->v=v;
+    f->u=v; f->v=u;
+    
+    e->next->next=e; f->next->next=f;
+    ep->next=f->next; fp->next=e->next;
+    e->next=fp; f->next=ep;    
+    return true;
+}
+
+inline bool Edge::flip(Edge * affected[4]){ //representatives of affected edges
+    if(flip()){
+        affected[0]=next->          representative();
+        affected[1]=prev()->        representative();
+        affected[2]=sister->next->  representative();
+        affected[3]=sister->prev()->representative();
+        return true;
+    } 
+    return false;
+}
+
+inline bool Edge::flip_resolve(){
+    if(flipGain()<=0) return false;
+    Edge * affected[4]; flip(affected); for(int i=0; i<4; i++) affected[i]->flip_resolve();
+    return true;
+}
+
+/****************************************************/
+
+class Triangulation {
+    Tab<Vertex> vertices;
+    Tab<Edge>   edges;
+    friend int main(int argc, const char * argv[]); //for Debug purposes
+public:
+    const Metric2 &metric;
+    
+    const Tab<Vertex>   & getVertices() {return vertices;}
+    const Tab<Edge>     & getEdges()    {return edges;}
+    
+    int nv() const {return vertices.card();}
+    int ne_oriented() const {return edges.card();}
+    int nt() const {return ne_oriented()/3;}
+    
+    Triangulation(int N, const Metric2 &Metric); //basic NxN square triangulation
+    //Triangulation(const Tab<Vertex> &Vertices, const Tab<Edge> &Edges, sym2 (*Metric)(const R2&)=NULL, double Lip=5): vertices(Vertices), edges(Edges), metric(Metric), lip(Lip) {if(!check()) cout << "Invalid triangulation !" << endl; movie_init();} //pointer mismatch
+#ifdef FF___HPP_
+    Triangulation(const Fem2D::Mesh &Th, const Metric2 &Metric);
+#endif
+    
+    void Delaunay_ordered(const vector<bool> &toExclude);    
+    void Delaunay_ordered(){vector<bool> toExclude; toExclude.resize(ne_oriented()); Delaunay_ordered(toExclude);}
+    void Delaunay_unordered(){for(int i=0; i<ne_oriented(); ++i) edges[i].flip_resolve();}
+    
+    int Connectivity(Tab<Z2> & connectivity) const {
+        int counter=0;
+        for(int i=0; i<ne_oriented(); ++i) if(edges[i].isRepresentative()) 
+            connectivity[counter++]=Z2(vertices.index(edges[i].getu()), vertices.index(edges[i].getv()));
+        return nt(); //number of triangles
+    }
+    
+    //Refines triangles isotropically, based on the small eigenvalue of the metric.
+    void hRefine(double h=1, Edge::refinement_priority priority=Edge::euclidean_longest_edge_first)
+        {if(h<=0) return; for(int i=0; i<ne_oriented(); ++i) if(edges[i].hRefine3(h,edges,vertices,metric,priority)) movie_frame();}
+    void hRefineQA(double h=1, unsigned int flag=0, Edge::refinement_priority priority=Edge::euclidean_longest_edge_first);
+    enum hRefineQA_opt {hRQA_finalRefine=1, hRQA_exportIntermediateData=2, hRQA_noIsoRef=4};
+    
+    //Affects only the position, not the metric
+    void moveMesh(R2 (*vec)(const R2 &), double amplification=1){for(int i=0; i<nv(); i++) vertices[i]+=vec(vertices[i])*amplification;}
+    
+    bool check() const {
+        bool passed=true;
+        for(int i=0; i<edges.card(); i++) passed = passed && edges[i].check();
+        return passed;
+    }
+    
+    void export_to_FreeFem(const char *filename) const;
+    Fem2D::Mesh *  export_to_Mesh() const;
+    void export_to_Mathematica(const char *filename) const {ofstream data_out; data_out.open(filename); data_out << Mathematica << edges; data_out.close();}
+    void export_to_Mathematica_Metric(const char *filename) const {ofstream data_out; data_out.open(filename); data_out << Mathematica << vertices; data_out.close();}
+    void export_to(Format_Math format, const char *filename) const {if(format==Mathematica) export_to_Mathematica(filename); else export_to_FreeFem(filename);}
+    
+    //movie functionality
+    string movie_name;
+    Format_Math movie_format;
+    mutable int movie_frame_number;
+    void movie_frame() const {if(movie_name.size()==0) return; export_to(movie_format, movie_frame_name().c_str());}
+private:
+    void movie_init(){movie_name=""; movie_frame_number=0; movie_format=Mathematica;}
+    string movie_frame_name() const;    
+};
+
+#endif
diff --git a/examples++-load/GeometryQA.cpp b/examples++-load/GeometryQA.cpp
new file mode 100644
index 0000000..79450ce
--- /dev/null
+++ b/examples++-load/GeometryQA.cpp
@@ -0,0 +1,654 @@
+//
+//  GeometryQA.cpp
+//  
+//
+//  Created by Jean-Marie Mirebeau on 09/10/11.
+//  -------------------------------------------
+//  Copyright 2011 UPMC. All rights reserved.
+//  Modif by F. Hecht 02/2012 for FreeFem++
+//  --------------------------------------
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include  <iostream>
+#include  <cfloat>
+#include  <cmath>
+using namespace std;
+#include "ff++.hpp" 
+using namespace Fem2D;
+
+//#include <boost/operators.hpp>
+namespace mir {
+
+
+
+#define _FLAGGED_BOUNDARY_
+#include "Geometry.hpp"
+
+ostream_math coutMath= cout << Mathematica;
+
+template<> const string R2::name = "R2";
+template<> const string Z2::name = "Z2";
+template<> const R2 R2::NABiDim = R2(DBL_MAX,DBL_MAX); //NAN could be a better alternative, but equality tests become problematic, 
+template<> const Z2 Z2::NABiDim = Z2(INT_MAX,INT_MAX); //and NAN does not exists for integers. 
+template<> const string R3::name = "R3";
+template<> const string Z3::name = "Z3";
+
+#include "ExampleMetrics.h" 
+
+Edge * Edge::refine(Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, const Metric2 &metric, refinement_priority priority){
+    Edge * const wf=which_first(priority); if(wf!=this) wf->refine(EdgeAllocator, VertexAllocator, metric, priority);
+    if(sister!=NULL) {
+        Edge * const swf=sister->which_first(priority); if(swf!=sister) swf->refine(EdgeAllocator, VertexAllocator, metric, priority);
+    }
+    Vertex const *w=next->v; Vertex *t=VertexAllocator.next();
+    const int newGen = 1+max(max(u->getGen(),v->getGen()),max(next->v->getGen(),sister==NULL ? -1 : sister->next->v->getGen()));
+    *t=Vertex((*u+*v)/2,newGen,metric);    
+    Edge *const wt=EdgeAllocator.next(), *const tw=EdgeAllocator.next(), *const ut=EdgeAllocator.next();
+    *wt=Edge(w,t,tw,this); 
+    *tw=Edge(t,w,wt,prev());
+    
+#ifdef _FLAGGED_BOUNDARY_
+    *ut=Edge(u,t,NULL,tw,onBoundary());
+#else
+    *ut=Edge(u,t,NULL,tw);
+#endif
+    
+    u=t;
+    prev()->next=ut; 
+    next->next=wt;
+    
+    if(sister==NULL) return ut;
+    
+    Vertex const *x=sister->next->v;
+    Edge *xt=EdgeAllocator.next(), *tx=EdgeAllocator.next(), *vt=EdgeAllocator.next();
+    *xt=Edge(x,t,tx,sister);
+    *tx=Edge(t,x,xt,sister->prev());
+    
+#ifdef _FLAGGED_BOUNDARY_
+    *vt=Edge(v,t,this,tx,onBoundary());
+#else
+    *vt=Edge(v,t,this,tx);
+#endif
+    
+    sister->u=t;
+    sister->prev()->next=vt;
+    sister->next->next=xt;
+    
+    ut->sister=sister;
+    sister->sister=ut;
+    sister=vt;
+    
+    return ut;
+}
+
+bool Edge::hRefine3(double h, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, const Metric2 &metric, refinement_priority priority){
+    Edge * const wf = which_first(priority);
+    if(this!=wf) return wf->hRefine3(h,EdgeAllocator, VertexAllocator, metric, priority); 
+    const double maxLen=max(max(vec().norm(), next->vec().norm()),prev()->vec().norm());
+    R2 const *w=next->v;
+    double minSize=sqrt(metric(*w).invNorm());
+    
+    if(metric.lip==0){
+        if(h*minSize<maxLen) {refine(EdgeAllocator, VertexAllocator, metric, priority); return true;}
+        return false;
+    }
+    //If the metric is not constant, it is sampled until resolution allows to make a sensible choice. Smallest eigenvalue used only.
+    for(int pow=1; h*(minSize-metric.lip*maxLen/(2*pow))<maxLen/2; pow*=2){  // !!! condition should be checked
+        for(int i=0; i<=pow; i++)
+            for(int j=0; i+j<=pow; j++){
+                if(i%2==0 && j%2==0) continue;
+                minSize=min(minSize, sqrt(metric((*u*i+*v*j+*w*(pow-i-j))/pow).invNorm()));
+                if(h*minSize<maxLen) {refine(EdgeAllocator, VertexAllocator, metric, priority); return true;}
+            }
+    }
+    return false;
+}
+
+Edge * Edge::hRefine2(double h, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, const Metric2 &metric, safe_vector<Edge*> *recursive, bool exaggerate){
+    //in the case recursive=!NULL of a recursive split, the safe_vector recursive contains all newly created edges which are oriented like *this. 
+    const R2 Vec = vec();
+    sym2 m= metric(*u); if(exaggerate) m=m.exaggerate();
+    double minSize=1/m.norm(Vec);
+    
+    if(metric.lip==0){
+        if(h*minSize<1) {
+            Edge *const e=refine(EdgeAllocator, VertexAllocator, metric, selected_edge_first);
+            if(recursive){
+                hRefine2   (h, EdgeAllocator, VertexAllocator, metric, recursive, exaggerate);
+                e->hRefine2(h, EdgeAllocator, VertexAllocator, metric, recursive, exaggerate);
+                recursive->push_back(e); 
+            }
+            return e;
+        }
+        return NULL;
+    }
+    //If the metric is not constant, it is sampled until resolution allows to make a sensible choice (based on lip constant). Smallest eigenvalue used only.
+    //assert(lip>0);
+    for(int pow=1;  h*(minSize-metric.lip/(2*pow))<0.5; pow*=2){    // !!! condition should be checked
+        for(int i=0; i<=pow; i++){
+            if(i%2==0) continue;
+            m= metric((*u*i+*v*(pow-i))/pow); if(exaggerate) m=m.exaggerate();
+            minSize=min(minSize, 1/m.norm(Vec));
+            if(h*minSize<1) {
+                Edge *const e=refine(EdgeAllocator, VertexAllocator, metric, selected_edge_first);
+                if(recursive){
+                    hRefine2   (h, EdgeAllocator, VertexAllocator, metric, recursive, exaggerate);
+                    e->hRefine2(h, EdgeAllocator, VertexAllocator, metric, recursive, exaggerate);
+                    recursive->push_back(e); 
+                }
+                return e;
+            }
+        }
+    }
+    return NULL;
+}
+
+Edge * Edge::which_first(refinement_priority priority){
+    if(priority==selected_edge_first) return this;
+    else if(priority==newest_vertex_first){
+        const int ugen=u->getGen(), vgen=v->getGen(), wgen=next->v->getGen();
+        return ugen>vgen ? (ugen>wgen ? next : this) : (vgen>wgen ? prev() : this);
+    } else { //euclidean_longest_edge_first
+        const double this_len=vec().norm(), next_len=next->vec().norm(), prev_len=prev()->vec().norm();
+        return next_len>prev_len ? (next_len>this_len ? next : this) : (prev_len>this_len ? prev() : this);
+    }
+}
+
+bool Edge::cut(Vertex const *start, Vertex const *end, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, 
+               const Metric2 &metric, vector<Edge*> & aligned){
+    //aligned collects created edges which are aligned with the cut
+    if(start==v) return next->cut(start, end, EdgeAllocator, VertexAllocator, metric, aligned);  //looking for the starting edge, in the wrong direction
+    if(start==u){ //looking for the starting edge, in the good direction
+        if(end==v) return false;
+        const R2 se= *end-*start;
+        
+        Edge *currentEdge=this; double currentDet; double prevDet=-det(vec(),se);
+        do {
+            currentDet=-prevDet;
+            prevDet=det(currentEdge->prev()->vec(),se);
+            if(currentDet>0 && prevDet>0) return currentEdge->cut(start,end, NULL, EdgeAllocator, VertexAllocator, metric, aligned);
+            currentEdge=currentEdge->prev()->sister; if(currentEdge==this) return false;
+        } while(currentEdge!=NULL);
+        
+        currentEdge=this; currentDet=det(vec(),se);
+        while (currentEdge->sister!=NULL) {
+            currentEdge=currentEdge->sister->next; if(currentEdge==this) return false;
+            prevDet=-currentDet;
+            currentDet=det(currentEdge->vec(),se);
+            if(currentDet>0 && prevDet>0) return currentEdge->cut(start,end, NULL, EdgeAllocator, VertexAllocator, metric, aligned);
+        }
+    }
+    //cout << "hello" << endl;
+    return false; // not supposed to happen
+}
+
+bool Edge::cut(Vertex const *start, Vertex const *end, Edge *oldSister, Tab<Edge> &EdgeAllocator, Tab<Vertex> &VertexAllocator, 
+               const Metric2& metric, vector<Edge*> & aligned){
+    Vertex *t=next->intersect(start, end, VertexAllocator, metric);
+    
+    if(oldSister==NULL){
+        //Vertex *s=next->intersect(start, end, VertexAllocator, metric);
+        if(t==NULL) return false;
+        Edge *const tw=next; Edge *const wu=tw->next;
+        Edge *const vt=EdgeAllocator.next();
+        Edge *const ut=EdgeAllocator.next(), *const tu=EdgeAllocator.next(); 
+        tw->u=t; wu->next=ut;
+        *ut=Edge(u,t,tu,next); aligned.push_back(ut);
+        *tu=Edge(t,u,ut,this);
+        *vt=Edge(v,t,next->sister,tu);
+        
+        
+        vt->sister->sister=vt;
+        next=vt;
+        return vt->sister->cut(start, end, tw, EdgeAllocator, VertexAllocator, metric, aligned);
+    }
+    Vertex const *const w=next->v;
+    Vertex const *const s=sister->v;
+    if(t!=NULL){
+        Edge *const tw=next; Edge *const wu=next->next;
+        Edge *const ws=EdgeAllocator.next(); Edge *const sw=EdgeAllocator.next(); 
+        Edge *const st=EdgeAllocator.next(); Edge *const ts=EdgeAllocator.next();
+        Edge *const us=EdgeAllocator.next(); Edge *const vt=EdgeAllocator.next();
+        
+        tw->u=t; tw->next=ws; 
+        wu->next=us; 
+        *ws=Edge(w,s,sw,st);
+        *sw=Edge(s,w,ws,wu);
+        *st=Edge(s,t,ts,tw); aligned.push_back(st);
+        *ts=Edge(t,s,st,this);
+        *us=Edge(u,s,oldSister,sw); oldSister->sister=us;
+        *vt=Edge(v,t,tw->sister,ts);
+        
+        vt->sister->sister=vt;
+        next=vt; u=s;
+        
+        return vt->sister->cut(start, end, tw, EdgeAllocator, VertexAllocator, metric, aligned);
+    }
+    t=next->next->intersect(start, end, VertexAllocator, metric);
+    if(t!=NULL){
+        Edge *const vw=next; Edge *const tu=next->next;
+        Edge *const sw=EdgeAllocator.next(); Edge *const ws=EdgeAllocator.next();
+        Edge *const ts=EdgeAllocator.next(); Edge *const st=EdgeAllocator.next();
+        Edge *const us=EdgeAllocator.next(); Edge *const wt=EdgeAllocator.next();
+        
+        vw->next=ws; 
+        tu->u=t; tu->next=us;
+        *sw=Edge(s,w,ws,wt);
+        *ws=Edge(w,s,sw,this);
+        *ts=Edge(t,s,st,sw);
+        *st=Edge(s,t,ts,tu); aligned.push_back(st);
+        *us=Edge(u,s,oldSister,st); oldSister->sister=us;
+        *wt=Edge(w,t,tu->sister,ts);
+        
+        wt->sister->sister=wt; u=s;
+        
+        return wt->sister->cut(start, end, tu, EdgeAllocator, VertexAllocator, metric, aligned);
+    }
+    if(w==end){// last bisected edge
+        Edge *const vw=next; Edge *const wu=next->next;
+        Edge *const us=EdgeAllocator.next();
+        Edge *const sw=EdgeAllocator.next(); Edge *ws=EdgeAllocator.next();
+        
+        vw->next=ws; 
+        wu->next=us;
+        *us=Edge(u,s,oldSister,sw); oldSister->sister=us;
+        *sw=Edge(s,w,ws,wu); aligned.push_back(sw);
+        *ws=Edge(w,s,sw,this);
+        
+        u=s;
+        
+        return true;
+    }
+    return false;
+}
+
+Vertex * Edge::intersect(Vertex const *start, Vertex const *end, Tab<Vertex> &VertexAllocator, const Metric2 &metric){
+    if(start==end || start==u || start ==v || end ==u || end ==v || u==v) return NULL;
+    const R2 es=*start-*end, uv=vec();
+    const R2 diff=(*end+*start)-(*v+*u);
+    if(det(uv,es)==0) return NULL;
+    const R2 coef=diff.lin_solve(uv, es);
+    if(coef.x <=-1 || coef.x>=1 || coef.y<=-1 || coef.y>=1 || coef==R2::NABiDim) return NULL;
+    *VertexAllocator.next()=Vertex(*u*(1-coef.x)/2+*v*(1+coef.x)/2, 1+max(u->getGen(),v->getGen()), metric);
+    return &VertexAllocator[VertexAllocator.max_accessed_pos];
+}
+
+
+ostream_math operator << (ostream_math f, Edge *e){if(e!=NULL) return f << *e; return f; } //<<"{{},{}}";
+
+Triangulation::Triangulation(int N, const Metric2 &Metric): metric(Metric){
+    for(int i=0; i<=N; i++)
+        for(int j=0; j<=N; j++)
+            vertices[i+(N+1)*j]=Vertex(R2(i/double(N), j/double(N)), abs(N-i-j), metric);
+    
+    for(int i=0; i<N; i++)
+        for(int j=0; j<N; j++){
+            const int index=i+N*j;
+#ifdef _FLAGGED_BOUNDARY_
+            edges[6*index+0]=Edge(&vertices[i  +(N+1)*j],     &vertices[i+1+(N+1)*j]    , j>0?   &edges[6*(index-N)+3] : NULL, &edges[6*index+1], 
+                                  j  ==0 ? 1 : 0);
+            edges[6*index+1]=Edge(&vertices[i+1+(N+1)*j],     &vertices[i  +(N+1)*(j+1)],        &edges[6*index    +4],        &edges[6*index+2]);
+            edges[6*index+2]=Edge(&vertices[i  +(N+1)*(j+1)], &vertices[i  +(N+1)*j]    , i>0?   &edges[6*(index-1)+5] : NULL, &edges[6*index+0], 
+                                  i  ==0 ? 4 : 0);
+            edges[6*index+3]=Edge(&vertices[i+1+(N+1)*(j+1)], &vertices[i  +(N+1)*(j+1)], j+1<N? &edges[6*(index+N)]   : NULL, &edges[6*index+4], 
+                                  j+1==N ? 3 : 0);
+            edges[6*index+4]=Edge(&vertices[i  +(N+1)*(j+1)], &vertices[i+1+(N+1)*j]    ,        &edges[6*index    +1],        &edges[6*index+5]);
+            edges[6*index+5]=Edge(&vertices[i+1+(N+1)*j],     &vertices[i+1+(N+1)*(j+1)], i+1<N? &edges[6*(index+1)+2] : NULL, &edges[6*index+3],
+                                  i+1==N ? 2 : 0);
+#else
+            edges[6*index+0]=Edge(&vertices[i  +(N+1)*j],     &vertices[i+1+(N+1)*j]    , j>0?   &edges[6*(index-N)+3] : NULL, &edges[6*index+1]);
+            edges[6*index+1]=Edge(&vertices[i+1+(N+1)*j],     &vertices[i  +(N+1)*(j+1)],        &edges[6*index    +4],        &edges[6*index+2]);
+            edges[6*index+2]=Edge(&vertices[i  +(N+1)*(j+1)], &vertices[i  +(N+1)*j]    , i>0?   &edges[6*(index-1)+5] : NULL, &edges[6*index+0]);
+            edges[6*index+3]=Edge(&vertices[i+1+(N+1)*(j+1)], &vertices[i  +(N+1)*(j+1)], j+1<N? &edges[6*(index+N)]   : NULL, &edges[6*index+4]);
+            edges[6*index+4]=Edge(&vertices[i  +(N+1)*(j+1)], &vertices[i+1+(N+1)*j]    ,        &edges[6*index    +1],        &edges[6*index+5]);
+            edges[6*index+5]=Edge(&vertices[i+1+(N+1)*j],     &vertices[i+1+(N+1)*(j+1)], i+1<N? &edges[6*(index+1)+2] : NULL, &edges[6*index+3]);            
+#endif
+        }
+    movie_init();
+}
+
+void Triangulation::Delaunay_ordered(const vector<bool> &toExclude){
+    vector<double> gains; gains.resize(ne_oriented());
+    SortedList<RZ> toFlip;
+    
+    for(int i=0; i<ne_oriented(); i++){//first sort and first computation of the angles
+        if(!edges[i].isRepresentative()) continue;
+        const double gain= toExclude[i] ? 0 : edges[i].flipGain();
+        gains[i]=gain; 
+        if(gain>0) toFlip.insert(RZ(gain,i));
+    }
+    
+    while(toFlip.Card()>0){
+        const RZ current=toFlip.pop();
+        Edge * affected[4];
+        if(!edges[current.number].flip(affected)) continue;
+        movie_frame();
+        
+        for(int i=0; i<4; i++){
+            const int index = edges.index(affected[i]);
+            if(gains[index]>0) toFlip.remove(RZ(gains[index],index));
+            const double gain= toExclude[index] ? 0 : edges[index].flipGain();
+            gains[index]=gain;
+            if(gain>0) toFlip.insert(RZ(gain,index));
+        }
+    }
+}
+
+void Triangulation::hRefineQA(double h, unsigned int flag, Edge::refinement_priority priority){
+    if(h<=0) return;
+    if(!(flag & hRQA_noIsoRef)) hRefine(h, priority);
+    
+    const bool exportIntermediateData = flag & hRQA_exportIntermediateData;
+    const bool finalRefine = flag & hRQA_finalRefine;
+    
+    //const double ratio=0.5; //over_refinement of the extremal half edges. Replaced with an exageration of the metric.
+    
+    if(exportIntermediateData){
+        vertices.export_content("vertices_iso.txt");
+        Tab<Z2> connectivity; Connectivity(connectivity);
+        connectivity.export_content("connectivity_iso.txt");
+    }
+    
+    //collecting the extremal edges associated to each vertex.
+    const int nv_iso=nv(); const int ne_iso=ne_oriented();
+    cout << "Triangulation::hRefineQA : Intermediate isotropic triangulation contains " << nt() << " triangles" << endl;
+    
+    double *minDet= new double [nv_iso](); //set to zero
+    double *maxDet= new double [nv_iso]();
+    Edge **minEdge= new Edge *[nv_iso]();
+    Edge **maxEdge= new Edge *[nv_iso]();
+    R2   *eigenVec= new R2[nv_iso];
+    for(int i=0; i<nv_iso; i++) eigenVec[i]=vertices[i].getm().eigensys();
+    
+    for(int i=0; i<ne_iso; i++){
+        Edge *e=&edges[i]; if(!e->isRepresentative()) continue;
+        R2 vec=e->vec(); vec/=vec.norm();
+        
+        for(int j=0; j<=1; j++){
+            const int index = vertices.index(j==0 ? e->getu() : e->getv());
+            const double currentDet = det(vec,eigenVec[index])*(1-2*j);
+            if      (currentDet<minDet[index]) {minDet[index]=currentDet; minEdge[index]=e;}
+            else if (currentDet>maxDet[index]) {maxDet[index]=currentDet; maxEdge[index]=e;}
+        }
+    }
+    
+    delete minDet; delete maxDet; delete eigenVec;
+    
+    //refining these edges
+    Tab<Edge> halfEdges;
+    Tab<int> endVertex;
+    safe_vector<Edge*> toExcludePtr; //these edges should be excluded from the flipping process
+
+    for(int i=0; i<ne_iso; i++){
+        Edge *e=&edges[i]; 
+        if(!e->isRepresentative()) continue;
+        
+        const int indexu = vertices.index(e->getu()), indexv = vertices.index(e->getv());
+        bool extru= (e==minEdge[indexu]) || (e==maxEdge[indexu]);
+        bool extrv= (e==minEdge[indexv]) || (e==maxEdge[indexv]);
+        
+        if(!extru && !extrv) continue;
+        Edge *const f=e->hRefine2(h, edges, vertices, metric, NULL); //non recursive split. 
+        
+        if(f==NULL) continue;
+        const int indexw=vertices.max_accessed_pos; //index of the mid point between u and v that was just created
+        
+        if(exportIntermediateData){
+            if(extru) *halfEdges.next()=*f;
+            if(extrv) *halfEdges.next()=*e;
+        }
+        
+        if(finalRefine){
+            if(extru && !extrv) endVertex[indexw]=indexv+1; // "+1" required to distinguish from values initialized to zero 
+            if(extrv && !extru) endVertex[indexw]=indexu+1; 
+        }   
+        if(extru) {//recursive split, exaggerate //*ratio
+            f->hRefine2(h, edges, vertices, metric, &toExcludePtr, true);
+            toExcludePtr.push_back(f); 
+        } 
+        if(extrv) {
+            e->hRefine2(h, edges, vertices, metric, &toExcludePtr, true);
+            toExcludePtr.push_back(e); 
+        }
+        //Note : in the theoretical algorithm, the edge is split in 3, and the midpart is refined if extru || extrv        
+        movie_frame();
+    }
+    
+    delete minEdge; delete maxEdge; 
+    if(exportIntermediateData) {halfEdges.export_content("halfEdges.txt"); edges.export_content("edgesBeforeDelaunay.txt");}
+    cout << "Triangulation::hRefineQA : Intermediate anisotropic triangulation contains " << nt() << " triangles."<< endl;
+    
+    vector<bool> toExclude; toExclude.resize(ne_oriented());
+    for(vector<Edge*>::const_iterator e=toExcludePtr.begin(); e!=toExcludePtr.end(); ++e)
+        if(!(*e)->onBoundary()) {toExclude[edges.index(*e)]=true; toExclude[edges.index((*e)->getSister())]=true;} //boundary edges are fixed anyway
+    
+    toExcludePtr.clear();
+    /*
+    for(int i=0; i<toExcludePtr.size(); ++i){
+        const Edge *const e=toExcludePtr[i];
+        toExclude[edges.index(e)]=true;
+        if(!e->onBoundary()) toExclude[edges.index(e->getSister())]=true;
+    }*/
+
+    if(movie_name.size()>0) cout << "Beginning main flip. Movie frame : " << movie_frame_number; 
+    Delaunay_ordered(toExclude);
+    if(movie_name.size()>0) cout << "; Finishing : " << movie_frame_number << endl; 
+    
+    if(finalRefine) {
+        for(int i=0; i<ne_oriented(); ++i) {
+            Edge *e=&edges[i]; 
+            const int indexw=vertices.index(e->getu());
+            if(endVertex[indexw]>0){
+                e->cut(e->getu(), &vertices[endVertex[indexw]-1], edges, vertices, metric, toExcludePtr);
+                endVertex[indexw]=0;
+                movie_frame();
+            }
+        }
+        cout << "Triangulation::hRefineQA : Triangulation contains " << nt() << " triangles after optional refinement (which eliminates the remaining large angles.)"<< endl;
+    }
+    //return;
+    //now taking care of the boundary
+    for(int i=0; i<ne_oriented(); ++i) if(edges[i].onBoundary()) if(edges[i].hRefine2(h, edges, vertices, metric, &toExcludePtr, true)) movie_frame();     
+
+    toExclude.resize(ne_oriented());
+    for(vector<Edge*>::const_iterator e=toExcludePtr.begin(); e!=toExcludePtr.end(); ++e)
+        if(!(*e)->onBoundary()) {toExclude[edges.index(*e)]=true; toExclude[edges.index((*e)->getSister())]=true;} //boundary edges are fixed anyway    
+
+    Delaunay_ordered(toExclude);
+    cout << "Triangulation::hRefineQA : Final triangulation contains " << nt() << " triangles after refinement of the boundary."<< endl;
+}
+
+Fem2D::Mesh *  Triangulation::export_to_Mesh() const 
+{
+  typedef  Fem2D::Triangle FFT;
+  typedef  Fem2D::Vertex FFV;
+  using  Fem2D::R2;
+  typedef  Fem2D::BoundaryEdge FFBE;
+  using  Fem2D::Mesh;
+  using namespace Fem2D; 
+ // using  Fem2D::R;
+
+    vector<bool>onBoundary; onBoundary.resize(nv());
+    int boundaryEdges=0;
+    for(int i=0; i<ne_oriented(); i++) {
+      const Edge & e =edges[i];
+        if(!e.onBoundary() || !e.isRepresentative()) continue;
+        onBoundary[vertices.index(e.getu())]=true; 
+        onBoundary[vertices.index(e.getv())]=true; 
+        boundaryEdges++;
+    }
+    
+    int nbv=nv(); // nombre de sommet 
+    int nbt=nt(); // nombre de triangles
+    int neb=boundaryEdges; // nombre d'aretes fontiere
+    // allocation des nouveaux items du maillage  
+    FFV * v= new FFV[nbv+nbt];
+    FFT *t= new FFT[nbt*3];
+    FFBE *b= new FFBE[neb];
+  // generation des nouveaus sommets 
+  FFV *vv=v;
+
+  for (int i=0;i<nbv;i++)
+   {
+
+     vv->x=vertices[i].x;
+     vv->y=vertices[i].y;
+     vv->lab = onBoundary[i] ;
+     vv++;      
+   }
+  //  generation des triangles 
+  FFT *tt= t; 
+  int nberr=0;
+   
+  Vertex const *triangle[3];
+  for(int i=0; i<ne_oriented(); i++) 
+    if(edges[i].isRepresentative3(triangle)) 
+      {
+	int i0= vertices.index(triangle[0]);
+	int i1= vertices.index(triangle[1]);
+	int i2= vertices.index(triangle[2]);
+	(*tt++).set(v,i0,i1,i2,0);
+      }
+  /* 
+  for (int i=0;i<nbt;i++)
+    {
+      int i0=Th(i,0), i1=Th(i,1),i2=Th(i,2);
+      int ii = nbv + i; // numero du 
+      // les 3 triangles par triangles origines 
+      (*tt++).set(v,ii,i1,i2,Th[i].lab);
+      (*tt++).set(v,i0,ii,i2,Th[i].lab);
+      (*tt++).set(v,i0,i1,ii,Th[i].lab);
+    }  
+  */
+  // les arete frontieres qui n'ont pas change
+  FFBE * bb=b;
+    //edges
+  for(int i=0; i<ne_oriented(); i++) 
+    {
+      const Edge & e=edges[i];
+      if(!e.onBoundary() || !e.isRepresentative()) continue;
+    //        data_out << 1+vertices.index(e.getu()) 
+      // << " " << 1+vertices.index(e.getv()) << " " << e.onBoundary() << endl;
+      int i1= vertices.index(e.getu());
+      int i2= vertices.index(e.getv());
+      int lab = e.onBoundary() ;
+      (*bb++).set(v,i1,i2,lab); 
+    } 
+  /*
+  for (int i=0;i<neb;i++)
+    {        
+      int i1=Th(Th.bedges[i][0]);
+      int i2=Th(Th.bedges[i][1]);
+      int lab=Th.bedges[i].lab;     
+      (*bb++).set(v,i1,i2,lab);   
+    }
+  */
+  Mesh * m = new Mesh(nbv,nbt,neb,v,t,b);
+
+  return m;
+}
+
+void Triangulation::export_to_FreeFem(const char *filename) const {
+    ofstream data_out; data_out.open(filename);
+        
+    vector<bool>onBoundary; onBoundary.resize(nv());
+    int boundaryEdges=0;
+    for(int i=0; i<ne_oriented(); i++) {
+        const Edge & e =edges[i];
+        if(!e.onBoundary() || !e.isRepresentative()) continue;
+        onBoundary[vertices.index(e.getu())]=true; 
+        onBoundary[vertices.index(e.getv())]=true; 
+        boundaryEdges++;
+    }
+    
+    data_out << nv() << " " << nt() << " " << boundaryEdges <<endl;
+    
+    //vertices
+    for(int i=0; i<nv(); i++) 
+      data_out << vertices[i] << " " << onBoundary[i] << endl;
+    
+    //triangles
+    Vertex const *triangle[3];
+    for(int i=0; i<ne_oriented(); i++) if(edges[i].isRepresentative3(triangle)) 
+        data_out << 1+vertices.index(triangle[0]) << " " << 1+vertices.index(triangle[1]) << " " << 1+vertices.index(triangle[2]) << " " << 0 << endl;
+    
+    cout << "Exporting edges" << endl;
+    
+    //edges
+    for(int i=0; i<ne_oriented(); i++) {
+        const Edge & e=edges[i];
+        if(!e.onBoundary() || !e.isRepresentative()) continue;
+#ifdef _FLAGGED_BOUNDARY_
+        data_out << 1+vertices.index(e.getu()) << " " << 1+vertices.index(e.getv()) << " " << e.onBoundary() << endl;
+#else
+        data_out << 1+vertices.index(e.getu()) << " " << 1+vertices.index(e.getv()) << " " << 1 << endl;
+#endif
+    } 
+        
+    data_out.close();
+}
+
+string Triangulation::movie_frame_name() const {
+    ostringstream oss; 
+    oss << movie_name << "_";
+    if(movie_frame_number<10)   oss << 0;
+    if(movie_frame_number<100)  oss << 0;
+    if(movie_frame_number<1000) oss << 0;
+    oss << movie_frame_number++ << ".txt";
+    return oss.str();
+}
+
+#ifdef FF___HPP_
+Triangulation::Triangulation(const Fem2D::Mesh &Th, const Metric2 &Metric):metric(Metric){
+    for(int i=0; i<Th.nv; ++i){
+        const Fem2D::R2 Point=Th(i);
+        vertices[i]=Vertex(R2(Point.x,Point.y),0,metric);
+    }
+    
+    cout << "Hello ???" << endl;
+    
+    //I collect boundary edge labels, since I do not understand how Th.BorderElementAdj(ui,vi) works.
+    std::map<pair<int,int>,int> BorderElementLabels;
+    
+    for(int i=0; i<Th.nbBrdElmts(); ++i){
+        const int ui = Th(Th.be(i)[0]), vi = Th(Th.be(i)[1]); const int label = Th.be(i).lab;
+        BorderElementLabels[pair<int,int>(ui,vi)] = label;
+        BorderElementLabels[pair<int,int>(vi,ui)] = label;        
+    }
+    
+    for(int i=0; i<Th.nt; ++i)
+        for(int j=0; j<3; ++j) {
+            int ip; int jp=j; ip=Th.ElementAdj(i,jp);
+#ifdef _FLAGGED_BOUNDARY_
+            Edge * const sister = (i==ip) ? NULL : &edges[3*ip+jp];
+            const int ui=Th(i,(j+1)%3), vi=Th(i,(j+2)%3);
+            const std::map<pair<int,int>,int>::iterator it=BorderElementLabels.find(pair<int,int>(ui,vi));
+            const int label = (it==BorderElementLabels.end()) ? 0 : it->second;            
+            edges[3*i+j]=Edge(&vertices[ui], &vertices[vi], sister, &edges[3*i+(j+1)%3], label);
+#else
+            edges[3*i+j]=Edge(&vertices[Th(i,(j+1)%3)], &vertices[Th(i,(j+2)%3)], i==ip ? NULL : &edges[3*ip+jp], &edges[3*i+(j+1)%3]);
+#endif
+        }
+}
+#endif
+
+
+} // end namespace std 
diff --git a/examples++-load/IPOTest.edp b/examples++-load/IPOTest.edp
new file mode 100644
index 0000000..63847c1
--- /dev/null
+++ b/examples++-load/IPOTest.edp
@@ -0,0 +1,95 @@
+/*
+ *     min   x1*x4*(x1 + x2 + x3)  +  x3
+            (= x1^2.x4 + x1.x2.x4 + x1.x3.x4 + x3)
+ *     s.t.  x1*x2*x3*x4                   >=  25
+ *           x1**2 + x2**2 + x3**2 + x4**2  =  40
+ *           1 <=  x1,x2,x3,x4  <= 5
+ *
+ *     Starting point:
+ *        x = (1, 5, 5, 1)
+ *
+ *     Optimal solution:
+ *        x = (1.00000000, 4.74299963, 3.82114998, 1.37940829)
+ */
+ 
+ load "ff-Ipopt"
+ 
+ real[int] xlb=[1.,1.,1.,1.],xub=[5.,5.,5.,5.],glb=[25.,40.],gub=[1.e19,40.];
+ 
+ func real J(real[int] &X)
+ {
+ 	return X[0]*X[3]*(X[0] + X[1] + X[2]) + X[2];
+ }
+ 
+ func real[int] dJ(real[int] &X)
+ {
+ 	real[int] grad(X.n);
+ 	grad[0] = 2.*X[0]*X[3] + X[1]*X[3] + X[2]*X[3];
+ 	grad[1] = X[0]*X[3];
+ 	grad[2] = X[0]*X[3] + 1.;
+ 	grad[3] = X[0]*X[0] + X[0]*X[1] + X[0]*X[2];
+ 	return grad;
+ }
+ 
+matrix H; 
+
+	int[int] hi=[0,1,1,2,2,2,3,3,3,3],hj=[0,0,1,0,1,2,0,1,2,3];
+	real[int] hc(hi.n);
+	hc=0.;
+
+func matrix HJ(real[int] &X,real jfactor,real[int] &lambda)
+{
+	H = [hi,hj,hc];
+	H(0,0) = jfactor * 2*X[3];
+	H(1,0) = jfactor * X[3];
+	H(2,0) = jfactor * X[3];
+	H(3,0) = jfactor * (2*X[0] + X[1] + X[2]);
+	H(3,1) = jfactor * X[0];
+	H(3,2) = jfactor * X[0];
+	H(1,0) += lambda[0] * (X[2]*X[3]);
+	H(2,0) += lambda[0] * (X[1]*X[3]);
+	H(2,1) += lambda[0] * (X[0]*X[3]);
+	H(3,0) += lambda[0] * (X[1]*X[2]);
+	H(3,1) += lambda[0] * (X[0]*X[2]);
+	H(3,2) += lambda[0] * (X[0]*X[1]);
+	H(0,0) += lambda[1] * 2.;
+	H(1,1) += lambda[1] * 2.;
+	H(2,2) += lambda[1] * 2.;
+	H(3,3) += lambda[1] * 2.;
+	//cout << H << endl;
+	return H;
+}
+ 
+ func real[int] G(real[int] &X)
+ {
+ 	real[int] g(2);
+ 	g[0] = X[0]*X[1]*X[2]*X[3];
+ 	g[1] = square(X.l2);
+ 	return g;
+ }
+ 
+ matrix GG;
+ int[int] II=[0, 0, 0, 0, 1, 1, 1, 1], JJ=[0, 1, 2, 3, 0, 1, 2, 3];
+ real[int] CC=[0.,0.,0.,0.,0.,0.,0.,0.];
+ 
+ GG = [II,JJ,CC];
+ 
+ func matrix jacG(real[int] &X)
+ {
+    GG(0,0) = X[1]*X[2]*X[3];
+    GG(0,1) = X[0]*X[2]*X[3];
+    GG(0,2) = X[0]*X[1]*X[3];
+    GG(0,3) = X[0]*X[1]*X[2];
+    GG(1,0) = 2.*X[0];
+    GG(1,1) = 2.*X[1];
+    GG(1,2) = 2.*X[2];
+    GG(1,3) = 2.*X[3];
+ 	return GG;
+ }
+ 
+ real[int] start=[1, 5, 5, 1];
+ real[int] optimsol=[1.00000000, 4.74299963, 3.82114998, 1.37940829];
+IPOPT(J,dJ,HJ,G,jacG,start,ub=xub, lb=xlb,clb=glb,cub=gub);
+optimsol -= start;
+cout << "Dist : " << optimsol.l2 << endl;
+ 
\ No newline at end of file
diff --git a/examples++-load/IpOptMinSurf.edp b/examples++-load/IpOptMinSurf.edp
new file mode 100644
index 0000000..6a49bd7
--- /dev/null
+++ b/examples++-load/IpOptMinSurf.edp
@@ -0,0 +1,47 @@
+load "ff-Ipopt"
+int bfgs=1,constraint =1; // aglo .. 
+real x0=1.5,y0=0.5; 
+mesh Th=square(10,10,[x+1,y]);
+fespace Vh(Th,P2);
+func g = cos(pi*x)*cos(pi*y);; //acosh(sqrt(x*x+y*y));//cos(pi*x)*cos(pi*y);
+Vh ue= g;
+macro grad(u) [dx(u),dy(u)]//EOM
+func real J(real[int]& X)
+{
+    Vh u; u[]=X;
+    return int2d(Th)(sqrt(1+grad(u)'*grad(u))) ;
+}
+
+func real[int]  DJ(real[int]& X)
+{
+    Vh u; u[]=X;
+   
+    varf vg(uu,v) = int2d(Th)((grad(u)'*grad(v)) / sqrt(1+grad(u)'*grad(u))) ;
+   real[int] G= vg(0,Vh); 
+    return G;}
+matrix H;//global vairable for Hessien matrix Overwise  => seg fault in Ipopt     
+func matrix  HJ(real[int]& X)
+{
+    Vh u; u[]=X;   
+    varf vH(v,w) = int2d(Th)( (grad(w)'*grad(v)) / sqrt(1+grad(u)'*grad(u)) 
+     - (grad(w)'*grad(u))*(grad(v)'*grad(u)) *(1+grad(u)'*grad(u))^-1.5 ) ;
+    H = vH(Vh,Vh); 
+    return H;}  
+       
+    
+varf OnGamma(u,v) = on(1,2,3,4,u=1); 
+Vh OnG;
+OnG[]=OnGamma(0,Vh,tgv=1); // 1 on Gamma 
+Vh lb = OnG!=0 ? g : -1e19 ; // 
+Vh ub = OnG!=0 ? g :  1e19 ; //  
+Vh u = OnG!=0  ? g : 0 ; //  initial guest ..
+Vh clb = 3-square(10*(square(x-x0)+square(y-y0))); //  constraint .. 
+if(constraint) lb = max(lb,clb); 
+int ret;
+if(bfgs) 
+  ret = IPOPT(J,DJ,u[],lb=lb[],ub=ub[],bfgs=1); 
+else 
+  ret = IPOPT(J,DJ,HJ,u[],lb=lb[],ub=ub[]); 
+
+cout << " min = "  << J(u[]) << "  ~ " << J(ue[]) << " ret = " << ret << endl; 
+plot(u, wait=1);
diff --git a/examples++-load/IpoptLap.edp b/examples++-load/IpoptLap.edp
new file mode 100644
index 0000000..ecd08d0
--- /dev/null
+++ b/examples++-load/IpoptLap.edp
@@ -0,0 +1,138 @@
+load "ff-Ipopt";
+
+int NN=10;
+
+mesh Th = square(NN,NN);
+
+fespace Vh(Th,P1);
+func f=1;
+func g=0;
+
+varf Poiss(u,v) = int2d(Th)(0.5*dx(u)*dx(v) + 0.5*dy(u)*dy(v)) - int2d(Th)(v*f);
+varf dPoiss(u,v) = int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v)) ;
+matrix A = Poiss(Vh,Vh);
+matrix dA = dPoiss(Vh,Vh);
+real[int] b = Poiss(0,Vh);
+
+varf Bord(u,v) = int1d(Th,1,2,3,4)(0.5*u*v) - int1d(Th,1,2,3,4)(v*g);
+varf dBord(u,v) = int1d(Th,1,2,3,4)(u*v);
+real intg2 = int1d(Th,1,2,3,4)(0.5*g*g);
+
+
+matrix M = dBord(Vh,Vh);
+real[int] bc= Bord(0,Vh);
+
+
+
+//cout << M << endl;
+//matrix M = Bord(Vh,Vh);
+
+int iter=0;
+
+func real J(real[int] &X)
+{
+	Vh u;
+	u[]=X;
+	real[int] Au = A*X;
+	Au += b;
+	real res = X '* Au;
+	plot(u,dim=3,fill=1,cmm="res = "+res+" - iter="+(iter++));
+	return res;
+}
+
+int nj=0;
+func real[int] dJ(real[int] &X)
+{
+	real[int] Au = dA*X;
+	//Au *= 2.;
+	Au += b;
+	return Au;
+}
+
+int nh=0;
+
+matrix MH;
+func matrix HJ(real[int] &X,real objfact,real[int] &lm) 
+{
+	int[int] ia(0),ja(0),ic(0),jc(0);
+	real[int] ca(0),cc(0);
+	[ia,ja,ca] = dA;
+	[ic,jc,cc] = M;
+	ca *= (objfact ? objfact : 0.0001);
+	cc *= (lm[0] ? lm[0] : 0.0001);
+	matrix odA = [ia,ja,ca];
+	matrix lmM = [ic,jc,cc];
+	MH = odA + lmM;
+	return MH;
+}
+//func matrix HJ(real[int] &X) {return dA;}
+//out << dA << end;
+int nc=0;
+func real[int] C(real[int] &X)
+{
+	real[int] res=M*X;
+	res *= 0.5;
+	res += bc;
+	real result = X '* res;
+	result += intg2;
+	real[int] rrr = [result];
+	return rrr;
+}
+
+int ndc=0;
+matrix MdC;
+for(int i=0;i<Vh.ndof;++i)
+{
+	Vh xx=0.;
+	xx[][i] = 1.;
+	real[int] Mxx = M*xx[];
+	real[int,int] MMxx(1,Mxx.n);
+	MMxx(0,:) = Mxx;
+	matrix MMMxx = MMxx;
+	matrix temp = MMMxx;
+	if(i==0) MdC = MMMxx;
+	else MMMxx = MdC + temp;
+	MdC = MMMxx;
+}
+cout << MdC << endl;
+int[int] imdc(0),jmdc(0);
+real[int] cmdc(0);
+[imdc,jmdc,cmdc] = MdC;
+func matrix dC(real[int] &X)
+{
+	real[int] res = M*X;
+	res += bc;
+	real[int,int] mdc(1,X.n);
+	mdc(0,:) = res;
+	for(int i=0;i<res.n;++i) if(res[i]) MdC(0,i) = res[i];
+	
+	return MdC;
+}
+//cout << borders << endl;
+real[int] Clb(1),Cub(1);
+Clb=0.;
+Cub=0.;
+Vh start=0.;//x*(x-1)*y*(1-y);
+
+real[int] xub(Vh.ndof),xlb(Vh.ndof);
+xub=1.e19;
+xlb=-1.e19;
+//xub = xub .* inside;
+//xlb = xlb .* inside;
+//cout << "J=" << J(start[]) << endl << " dJ=" << dJ(start[]) << endl << " HJ=" << HJ(start[]) << endl << " C=" << C(start[]) << endl << " dC=" << dC(start[]) << endl;
+//cout << "dC = " << dC(start[]) << endl;
+
+//IPOPT(J,dJ,HJ,start[],ConstFunc=C,ConstGrad=dC,clb=Clb,cub=Cub);
+/*
+real[int] lll=[0.];
+cout << HJ(start[],1.,lll) << endl;
+lll[0] = 1.;
+cout << HJ(start[],0.,lll) << endl;*/
+
+
+IPOPT(J,dJ,HJ,C,dC,start[],ub=xub, lb=xlb,cub=Cub,clb=Clb);
+
+Vh uff,v;
+solve LaplaceFF(uff,v) = int2d(Th)(dx(uff)*dx(v) + dy(uff)*dy(v)) - int2d(Th)(v*f) + on(1,2,3,4,uff=0);
+real nl2 = sqrt(int2d(Th)(square(uff-start))), ninf = sqrt(int2d(Th)(square(dx(uff)-dx(start)) + square(dy(uff)-dy(start))));
+cout << "||ipopt - ff||_2 = " << nl2 << "   ||grad||_2 = "  << ninf << endl;
diff --git a/examples++-load/IpoptMinSurfVol.edp b/examples++-load/IpoptMinSurfVol.edp
new file mode 100644
index 0000000..dfa5bc3
--- /dev/null
+++ b/examples++-load/IpoptMinSurfVol.edp
@@ -0,0 +1,254 @@
+// this exemple is buggus in some case ...
+// strange ...  FH.  , S Auliac  (will be correct in test ???)
+// remove the test  (no loop)  
+int nadapt=0;//  3 is teh previous value..
+load "msh3";
+load "medit";
+load "ff-Ipopt";
+
+real alpha=0.9;
+int np=30;
+mesh Th = square(2*np,np,[2*pi*x,pi*y]);
+
+// FFCS regression reference value
+real regtest;
+
+fespace Vh(Th,P1,periodic=[[2,y],[4,y]/*,[1,x],[3,x]*/]);
+
+/*
+ * Initial shape definition
+ * outside of the mesh adaptation loop to initialize with the previous optimial shape found on further iterations
+ */
+
+Vh startshape=5;//+0.5*(cos(10*x)*sin(10*y)*sin(y));
+
+//uz,lz,lm : dual variables storage for the warmstart
+Vh uz=1.,lz=1.;
+real[int] lm=[1];
+
+
+
+for(int kkk=0;kkk<nadapt;++kkk) //Mesh adaptation loop
+{
+
+int iter=0;
+func sin2 = square(sin(y));
+
+/*
+ * A function which transform Th in 3d mesh (r=rho)
+ * a point (theta,phi) of Th becomes ( r(theta,phi)*cos(theta)*sin(phi) , r(theta,phi)*sin(theta)*sin(phi) , r(theta,phi)*cos(phi) )
+ * then displays the resulting mesh with medit.
+ * (often crashs if some values of rho are negative or if freefem is compiled with debug)
+ */
+func int Plot3D(real[int] &rho,string cmm,bool ffplot)
+{
+	Vh rhoo;
+	rhoo[]=rho;
+	//mesh sTh = square(np,np/2,[2*pi*x,pi*y]);
+	//fespace sVh(sTh,P1);
+	//Vh rhoplot=rhoo;
+	try
+	{
+		mesh3 Sphere = movemesh23(Th,transfo=[rhoo(x,y)*cos(x)*sin(y),rhoo(x,y)*sin(x)*sin(y),rhoo(x,y)*cos(y)]);
+		if(ffplot) plot(Sphere);
+		else medit(cmm ,Sphere,wait=0);
+	}
+	catch(...)
+	{
+		cout << "cant plot" << endl;
+	}
+	return 1;
+}
+
+
+/*
+ * Surface computation
+ * Maybe is it possible to use movemesh23 to have the surface function less complicated
+ * However, it would not simplify the gradient and the hessian
+ */
+func real Area(real[int] &X)
+{
+	Vh rho;
+	rho[] = X;
+	Vh rho2 = square(rho);
+	Vh rho4 = square(rho2);
+	real res = int2d(Th)(sqrt( rho4*sin2 + rho2*square(dx(rho)) + rho2*sin2*square(dy(rho)) ) );
+	++iter;
+	if(1) plot(rho,value=1,fill=1,cmm="rho(theta,phi) on [0,2pi]x[0,pi] - S="+res,dim=3);
+	else Plot3D(rho[],"shape_evolution",1);
+	return res;
+}
+func real[int] GradArea(real[int] &X)
+{
+	Vh rho,rho2;
+	rho[] = X;
+	rho2[] = square(X);
+	Vh sqrtPsi,alpha;
+	{
+		Vh  dxrho2 = dx(rho)*dx(rho), dyrho2 = dy(rho)*dy(rho);
+		sqrtPsi = sqrt( rho2*rho2*sin2 + rho2*dxrho2 + rho2*dyrho2*sin2 );
+		alpha = 2.*rho2*rho*sin2 + rho*dxrho2 + rho*dyrho2*sin2;
+	}
+	varf dArea(u,v) = int2d(Th)(1./sqrtPsi * (alpha*v + rho2*dx(rho)*dx(v) + rho2*dy(rho)*sin2*dy(v)) );
+	real[int] grad = dArea(0,Vh);
+	return grad;
+}
+matrix hessianA;
+func matrix HessianArea(real[int] &X)
+{
+	Vh rho,rho2;
+	rho[] = X;
+	rho2 = square(rho);
+	Vh sqrtPsi,sqrtPsi3,C00,C01,C02,C11,C12,C22,A;
+	{
+		Vh C0,C1,C2;
+		Vh  dxrho2 = dx(rho)*dx(rho), dyrho2 = dy(rho)*dy(rho);
+		sqrtPsi = sqrt( rho2*rho2*sin2 + rho2*dxrho2 + rho2*dyrho2*sin2 );
+		sqrtPsi3 = ( rho2*rho2*sin2 + rho2*dxrho2 + rho2*dyrho2*sin2 )*sqrtPsi;
+		C0 = 2*rho2*rho*sin2 + rho*dxrho2 + rho*dyrho2*sin2;
+		C1 = rho2*dx(rho);
+		C2 = rho2*sin2*dy(rho);
+		C00 = square(C0);
+		C01 = C0*C1;
+		C02 = C0*C2;
+		C11 = square(C1);
+		C12 = C1*C2;
+		C22 = square(C2);
+		A = 6.*rho2*sin2 + dxrho2 + dyrho2*sin2;
+	}
+	varf d2Area(w,v) =
+		int2d(Th)(1./sqrtPsi * (A*w*v + 2*rho*dx(rho)*dx(w)*v + 2*rho*dx(rho)*w*dx(v) + 2*rho*dy(rho)*sin2*dy(w)*v + 2*rho*dy(rho)*sin2*w*dy(v)
+								+ rho2*dx(w)*dx(v) + rho2*sin2*dy(w)*dy(v)) 
+		+        1./sqrtPsi3 * (C00*w*v + C01*dx(w)*v + C01*w*dx(v) + C02*dy(w)*v + C02*w*dy(v) + C11*dx(w)*dx(v)
+								   + C12*dx(w)*dy(v) + C12*dy(w)*dx(v) + C22*dy(w)*dy(v)) );
+	hessianA = d2Area(Vh,Vh);
+	return hessianA;
+}
+
+
+/*
+ * Volume computation
+ */
+func real Volume(real[int] &X)
+{
+	Vh rho;
+	rho[]=X;
+	Vh rho3=rho*rho*rho;
+	real res = 1./3.*int2d(Th)(rho3*sin(y));
+	return res;
+}
+func real[int] GradVolume(real[int] &X)
+{
+	Vh rho;
+	rho[]=X;
+	varf dVolume(u,v) = int2d(Th)(rho*rho*sin(y)*v);
+	real[int] grad = dVolume(0,Vh);
+	return grad;
+}
+matrix hessianV;
+func matrix HessianVolume(real[int] &X)
+{
+	Vh rho;
+	rho[]=X;
+	varf d2Volume(w,v) = int2d(Th)(2*rho*sin(y)*v*w);
+	hessianV = d2Volume(Vh,Vh);
+	return hessianV;
+}
+
+
+
+/*
+ * If we want to use the volume as a constraint function
+ * we must wrap it in some freefem functions returning the appropriate type 
+ * The lagrangian hessian also have to be wrapped since the Volume is not linear with 
+ * respect to rho, it will constribbute to the hessian.
+ */
+func real[int] ipVolume(real[int] &X) {real[int] vol = [Volume(X)]; return vol;}
+matrix mdV;
+func matrix ipGradVolume(real[int] &X) {real[int,int] dvol(1,Vh.ndof); dvol(0,:)=GradVolume(X); mdV=dvol; return mdV;}
+matrix HLagrangian;
+func matrix ipHessianLag(real[int] &X,real objfact,real[int] &lambda)
+{
+	HLagrangian = objfact*HessianArea(X) + lambda[0]*HessianVolume(X);
+	return HLagrangian;
+}
+/*building struct for GradVolume */
+int[int] gvi(Vh.ndof),gvj=0:Vh.ndof-1;
+gvi=0;
+
+
+/*
+ * The starting value
+ */
+Vh rc=startshape ;
+
+
+/*
+ * Bounds definition
+ */
+Vh ub=1.e19;
+//Vh lb=1.,ub=3.;
+
+
+/*
+ * make it funnier by puptting some objects inside the shape , where rho has to be greater than a given value
+ */
+Vh lb=0;
+int shapeswitch=1;
+real sigma=2*pi/40.,treshold=0.1;
+func real Gaussian(real X,real Y,real theta,real phi)
+{
+	real deltax2 = square((X-theta)*sin(Y)) , deltay2 = square(Y-phi);
+	return exp(-0.5 * (deltax2 + deltay2) / (sigma*sigma));
+}
+real e=0.1,r0=0.25,rr=2-r0;
+real E=1./(e*e),RR=1./(rr*rr);
+func disc1 = sqrt(1./(RR+(E-RR)*cos(y)*cos(y)))*(1+0.1*cos(7*x));
+func disc2 = sqrt(1./(RR+(E-RR)*cos(x)*cos(x)*sin2))  ;
+if(1) //doesn't work well...
+{
+	lb=r0;
+	/*{
+		func f = rr*Gaussian(x,y,0,0);
+		func g = rr*Gaussian(x,y,0,pi);
+		lb = max(max(lb,f),g);
+	}*/
+	for(int q=0;q<5;++q)
+	{
+		func f = rr*Gaussian(x,y,2*q*pi/5.,pi/3.);
+		func g = rr*Gaussian(x,y,2*q*pi/5.+pi/5.,2.*pi/3.);
+		lb = max(max(lb,f),g);
+	}
+	lb = max(lb,rr*Gaussian(x,y,2*pi,pi/3));
+}
+lb =  max(lb,max(disc1, disc2));
+real Vobj = Volume(lb[]);
+real Vnvc = 4./3.*pi*pow(lb[].linfty,3);
+
+if(1) Plot3D(lb[],"object_inside",0);
+real[int] clb=0.,cub=[(1-alpha)*Vobj + alpha*Vnvc];
+
+
+/*
+ * Call to IPOPT
+ */
+int res=IPOPT(Area,GradArea,ipHessianLag,ipVolume,ipGradVolume,rc[],ub=ub[],lb=lb[],clb=clb,cub=cub,checkindex=1,maxiter=kkk<nadapt-1 ? 40:150,warmstart=kkk,lm=lm,uz=uz[],lz=lz[],tol=0.00001,structjacc=[gvi,gvj]);
+cout << " IPOPT: res =" << res << endl ;
+/*
+ * Display the final mesh
+ */
+Plot3D(rc[],"Shape_at_"+kkk,0);
+Plot3D(GradArea(rc[]),"ShapeGradient",0);
+if(kkk<nadapt-1)
+{
+	Th = adaptmesh(Th,rc*cos(x)*sin(y),rc*sin(x)*sin(y),rc*cos(y)/*,hmax=pi/np*/,nbvx=50000,periodic=[[2,y],[4,y]/*,[1,x],[3,x]*/]);
+	plot(Th,wait=1);
+	startshape = rc;
+	uz=uz;//dual variables interpolation
+	lz=lz;
+}
+
+// FFCS regression reference value
+regtest=rc[]'*rc[];
+}
+
diff --git a/examples++-load/IpoptVI.edp b/examples++-load/IpoptVI.edp
new file mode 100644
index 0000000..ca23233
--- /dev/null
+++ b/examples++-load/IpoptVI.edp
@@ -0,0 +1,31 @@
+//  Solver - Delta u = f , u < g et u = 0 on Gamma 
+load "ff-Ipopt";
+int nn=20;
+mesh Th=square(nn,nn);
+fespace Vh(Th,P2);
+
+func f = 1.; //rhs function
+real r=0.03,s=0.1; //some parameters for g
+func g = r - r/2*exp(-0.5*(square(x-0.5)+square(y-0.5))/square(s));
+
+
+macro Grad(u) [dx(u),dy(u)]//
+varf vP(u,v) = int2d(Th)(Grad(u)'*Grad(v)) - int2d(Th)(f*v);
+
+matrix A = vP(Vh,Vh,solver=CG);
+real[int] b = vP(0,Vh);
+
+// Warning the boundary condition are given with lb and ub on border
+// equal value ... 
+Vh u=0;
+Vh lb=-1.e19;
+varf vGamma(u,v) = on(1,2,3,4,u=1);
+real[int] onGamma=vGamma(0,Vh);
+Vh ub=g;
+ub[] = onGamma ? 0. : ub[];
+lb[] = onGamma ? 0. : lb[];
+
+IPOPT([A,b],u[],lb=lb[],ub=ub[]);
+
+plot(u,wait=1);
+
diff --git a/examples++-load/IpoptVI2.edp b/examples++-load/IpoptVI2.edp
new file mode 100644
index 0000000..9e64d6c
--- /dev/null
+++ b/examples++-load/IpoptVI2.edp
@@ -0,0 +1,57 @@
+load "ff-Ipopt";
+int nn=10;
+mesh Th=square(nn,nn);
+fespace Vh(Th,[P1,P1] );
+fespace Wh(Th,[P1] );
+int iter=0;
+
+func f1 =  10;//right hand sides
+func f2 = -15;
+func g1 = -0.1;//Boundary conditions functions
+func g2 =  0.1;
+
+Vh [uz,uz2]=[1,1],[lz,lz2]=[1,1];
+Wh lm=1.;
+Vh [u1,u2]=[0,0];//starting point
+
+
+while(++iter)
+{
+macro Grad(u) [dx(u),dy(u)]//gradient macro
+varf vP([u1,u2],[v1,v2]) = int2d(Th)(Grad(u1)'*Grad(v1)+ Grad(u2)'*Grad(v2)) 
+- int2d(Th)(f1*v1+f2*v2);
+
+matrix A = vP(Vh,Vh);//Fitness function matrix...
+real[int] b = vP(0,Vh);//and linear form
+
+int[int] II1=[0],II2=[1];//Constraints matrix
+matrix C1 =  interpolate (Wh,Vh, U2Vc=II1);
+matrix C2 =  interpolate (Wh,Vh, U2Vc=II2);
+matrix CC = -1*C1 + C2; // u2 - u1 >0
+Wh cl=0;//constraints lower bounds (no upper bounds)
+
+//Boundary conditions
+varf vGamma([u1,u2],[v1,v2]) = on(1,2,3,4,u1=1,u2=1);
+real[int] onGamma=vGamma(0,Vh);
+Vh [ub1,ub2]=[g1,g2];
+Vh [lb1,lb2]=[g1,g2];
+ub1[] = onGamma ? ub1[] : 1e19  ; //Unbounded in interior
+lb1[] = onGamma ? lb1[] : -1e19  ;
+
+
+Vh [uzi,uzi2]=[uz,uz2],[lzi,lzi2]=[lz,lz2];
+Wh lmi=lm;
+Vh [ui1,ui2]=[u1,u2];
+
+IPOPT([b,A],CC,ui1[],lb=lb1[],clb=cl[],ub=ub1[],warmstart=iter>1,uz=uzi[],lz=lzi[],lm=lmi[]);
+
+//cout << "ADAPTMESH ITERATION " << iter << endl << "UZ = " << uzi[] << endl << "LZ = " << lzi[] << endl << "LM = " << lmi[] << endl;
+
+plot(ui1,ui2,wait=1,nbiso=60,dim=3);
+if(iter > 1) break;
+Th= adaptmesh(Th,[ui1,ui2],err=0.004,nbvx=100000);
+[uz,uz2]=[uzi,uzi2];
+[lz,lz2]=[lzi,lzi2];
+[u1,u2]=[ui1,ui2];
+lm=lmi;
+}
diff --git a/examples++-load/LapDG3.edp b/examples++-load/LapDG3.edp
new file mode 100644
index 0000000..5643bbf
--- /dev/null
+++ b/examples++-load/LapDG3.edp
@@ -0,0 +1,56 @@
+load "Element_P3dc"
+load "Element_P3"
+
+
+//    Discontinous Galerlin Method
+//   based on paper from 
+// Riviere, Beatrice; Wheeler, Mary F.; Girault, Vivette
+// title: 
+// A priori error estimates for finite element 
+// methods based on discontinuous approximation spaces
+//  for elliptic problems.
+//  SIAM J. Numer. Anal. 39 (2001), no. 3, 902--931 (electronic).
+//  ---------------------------------
+//  Formulation given by Vivette Girault
+//  ------ 
+// Author: F. Hecht , december 2003
+// -------------------------------
+//   nonsymetric bilinear form
+//   ------------------------
+//  solve $ -\Delta u = f$ on $\Omega$ and $u= g$ on $\Gamma$
+macro dn(u) (N.x*dx(u)+N.y*dy(u) ) //  def the normal derivative 
+
+mesh Th = square(3,3); // unite square 
+fespace Vh(Th,P3dc);     // Discontinous P2 finite element
+fespace Xh(Th,P3);
+//  if param = 0 => Vh must be P2 otherwise we need some penalisation  
+real pena=1000; // a paramater to add penalisation 
+varf Ans(u,v)= 
+   int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v)  ) // Ok P4 
+ + intalledges(Th,qforder=7)(//  loop on all  edge of all triangle 
+       // the edge are see nTonEdge times so we / nTonEdge
+       // remark: nTonEdge =1 on border edge and =2 on internal 
+       // we are in a triange th normal is the exterior normal
+       // def: jump = external - internal value; on border exter value =0
+       //      average = (external + internal value)/2, on border just internal value
+            ( jump(v)*average(dn(u)) -  jump(u)*average(dn(v)) 
+          + pena*jump(u)*jump(v) ) / nTonEdge 
+)
+;
+func f=1;
+func g=0;
+Vh u,v;
+Xh uu,vv;
+problem A(u,v,solver=UMFPACK) = Ans 
+- int2d(Th)(f*v) 
+- int1d(Th)(g*dn(v)  + pena*g*v) 
+;
+problem A1(uu,vv,solver=CG) 
+= 
+ int2d(Th)(dx(uu)*dx(vv)+dy(uu)*dy(vv)) - int2d(Th)(f*vv) + on(1,2,3,4,uu=g);
+ 
+ A; // solve  DG
+ A1; // solve continuous
+
+plot(u,uu,cmm="P3 Discontinue Galerkin",wait=1,value=1);
+plot(u,cmm="Discontinue Galerkin",wait=1,value=1,fill=1);
diff --git a/examples++-load/LapDG4.edp b/examples++-load/LapDG4.edp
new file mode 100644
index 0000000..df804f2
--- /dev/null
+++ b/examples++-load/LapDG4.edp
@@ -0,0 +1,52 @@
+//    Discontinous Galerlin Method
+//   based on paper from 
+// Riviere, Beatrice; Wheeler, Mary F.; Girault, Vivette
+// title: 
+// A priori error estimates for finite element 
+// methods based on discontinuous approximation spaces
+//  for elliptic problems.
+//  SIAM J. Numer. Anal. 39 (2001), no. 3, 902--931 (electronic).
+//  ---------------------------------
+//  Formulation given by Vivette Girault
+//  ------ 
+// Author: F. Hecht , december 2003
+// -------------------------------
+//   nonsymetric bilinear form
+//   ------------------------
+//  solve $ -\Delta u = f$ on $\Omega$ and $u= g$ on $\Gamma$
+macro dn(u) (N.x*dx(u)+N.y*dy(u) ) //  def the normal derivative 
+
+mesh Th = square(10,10); // unite square 
+fespace Vh(Th,P2dc);     // Discontinous P2 finite element
+fespace Xh(Th,P2);
+//  if param = 0 => Vh must be P2 otherwise we need some penalisation  
+real pena=0; // a paramater to add penalisation 
+varf Ans(u,v)= 
+   int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v)  )
+ + intalledges(Th)(//  loop on all  edge of all triangle 
+       // the edge are see nTonEdge times so we / nTonEdge
+       // remark: nTonEdge =1 on border edge and =2 on internal 
+       // we are in a triange th normal is the exterior normal
+       // def: jump = external - internal value; on border exter value =0
+       //      average = (external + internal value)/2, on border just internal value
+            ( jump(v)*average(dn(u)) -  jump(u)*average(dn(v)) 
+          + pena*jump(u)*jump(v) ) / nTonEdge 
+)
+;
+func f=1;
+func g=0;
+Vh u,v;
+Xh uu,vv;
+problem A(u,v,solver=UMFPACK) = Ans 
+- int2d(Th)(f*v) 
+- int1d(Th)(g*dn(v)  + pena*g*v) 
+;
+problem A1(uu,vv,solver=CG) 
+= 
+ int2d(Th)(dx(uu)*dx(vv)+dy(uu)*dy(vv)) - int2d(Th)(f*vv) + on(1,2,3,4,uu=g);
+ 
+ A; // solve  DG
+ A1; // solve continuous
+
+plot(u,uu,cmm="Discontinue Galerkin",wait=1,value=1);
+plot(u,cmm="Discontinue Galerkin",wait=1,value=1,fill=1);
diff --git a/examples++-load/LapLNewSolver.edp b/examples++-load/LapLNewSolver.edp
new file mode 100644
index 0000000..687ec46
--- /dev/null
+++ b/examples++-load/LapLNewSolver.edp
@@ -0,0 +1,19 @@
+load "Element_P3"
+load "NewSolver"
+
+defaulttoUMFPACK();
+verbosity=3;
+ mesh Th=square(10,10);
+ fespace Vh(Th,P3);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh) =                    //  Definion of  the problem 
+    int2d(Th,qft=qf7pT)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th,qft=qf7pT)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+verbosity=5;
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP3.eps",value=true);
diff --git a/examples++-load/LapMUMPS_seq.edp b/examples++-load/LapMUMPS_seq.edp
new file mode 100644
index 0000000..a8f0b70
--- /dev/null
+++ b/examples++-load/LapMUMPS_seq.edp
@@ -0,0 +1,19 @@
+load "Element_P3"
+load "MUMPS_seq"
+
+defaulttoMUMPSseq();
+verbosity=3;
+ mesh Th=square(10,10);
+ fespace Vh(Th,P3);     // P1 FE space
+ Vh<complex>  uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh,solver=sparsesolverSym) =                    //  Definion of  the problem 
+    int2d(Th,qft=qf7pT)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th,qft=qf7pT)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+verbosity=3;
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP3.eps",value=true);
diff --git a/examples++-load/LapNewSolver.edp b/examples++-load/LapNewSolver.edp
new file mode 100644
index 0000000..f1801ad
--- /dev/null
+++ b/examples++-load/LapNewSolver.edp
@@ -0,0 +1,16 @@
+load "Element_P3"
+load "NewSolver"
+verbosity=3;
+ mesh Th=square(10,10);
+ fespace Vh(Th,P3);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh) =                    //  Definion of  the problem 
+    int2d(Th,qft=qf7pT)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th,qft=qf7pT)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP3.eps",value=true);
diff --git a/examples++-load/LapUmfpack64.edp b/examples++-load/LapUmfpack64.edp
new file mode 100644
index 0000000..0b7a502
--- /dev/null
+++ b/examples++-load/LapUmfpack64.edp
@@ -0,0 +1,19 @@
+load "Element_P3"
+load "UMFPACK64"
+
+defaulttoUMFPACK64();
+verbosity=3;
+ mesh Th=square(10,10);
+ fespace Vh(Th,P3);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh) =                    //  Definion of  the problem 
+    int2d(Th,qft=qf7pT)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th,qft=qf7pT)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+verbosity=5;
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP3.eps",value=true);
diff --git a/examples++-load/LaplaceP3.edp b/examples++-load/LaplaceP3.edp
new file mode 100644
index 0000000..045173e
--- /dev/null
+++ b/examples++-load/LaplaceP3.edp
@@ -0,0 +1,15 @@
+load "Element_P3"
+
+ mesh Th=square(10,10);
+ fespace Vh(Th,P3);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh) =                    //  Definion of  the problem 
+    int2d(Th,qft=qf7pT)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th,qft=qf7pT)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP3.eps",value=true);
diff --git a/examples++-load/LaplaceP4.edp b/examples++-load/LaplaceP4.edp
new file mode 100644
index 0000000..37cd77f
--- /dev/null
+++ b/examples++-load/LaplaceP4.edp
@@ -0,0 +1,53 @@
+load "Element_P4"
+load "Element_P3"
+load "qf11to25"
+
+  
+mesh Th=square(10,10);
+verbosity=4;
+
+for (int i=1;i<=26;i++)
+{
+  cout <<" int1d order= "<< i ;
+  int1d(Th,qforder=i)(1.);
+}
+
+for (int i=1;i<=26;i++)
+{
+ cout <<" int2d order= "<< i ;	
+  int2d(Th,qforder=i)(1.);
+}
+
+verbosity=1;
+
+ fespace Vh(Th,P4);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh) =                    //  Definion of  the problem 
+    int2d(Th,qft=qf11pT)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th,qft=qf25pT)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP4.eps",value=true);
+
+  real[int,int] qq1=[ [0.5,0],
+                      [0.5,1]];
+  real[int,int] qq2=[[1./3,0,0],[1./3.,1,0],[1./3.,0,1]];
+  real[int,int] qq3=[[1./4,0,0,0],[1./4.,1,0,0],[1./4.,0,1,0],[1./4.,0,0,1]];
+  
+  QF1 qf1(1,qq1);
+  QF2 qf2(1,qq2);
+  QF3 qf3(1,qq3);
+  real I1 = int1d(Th,qfe=qf1)(x^2) ;
+  real I1l = int1d(Th,qfe=qf1pElump)(x^2) ;
+
+  real I2 = int2d(Th,qft=qf2)(x^2) ;
+  real I2l = int2d(Th,qft=qf1pTlump)(x^2) ;
+
+  cout << I1 << " == " << I1l << endl; 
+  cout << I2 << " == " << I2l << endl; 
+  assert( abs(I1-I1l) < 1e-10);
+  assert( abs(I2-I2l) < 1e-10);
diff --git a/examples++-load/LaplaceRT1.edp b/examples++-load/LaplaceRT1.edp
new file mode 100644
index 0000000..6f069a2
--- /dev/null
+++ b/examples++-load/LaplaceRT1.edp
@@ -0,0 +1,42 @@
+load "Element_Mixte"
+/*
+   Solving the following Poisson problem 
+   Find $p$, such that;
+   $ - \Delta p = f $   on $\Omega$, 
+   $ dp / dn = (g1d,g2d). n  $ on $\Gamma_{123}$ 
+   $ p = gd  $ on $\Gamma_{1}$ 
+  with de Mixte finite element formulation 
+   Find $p\in L^2(\Omega)   and $u\in H(div) $ such than  
+    u - Grad p = 0
+    - div u =  f
+   $  u. n = (g1d,g2d). n  $ on $\Gamma_{123}$
+   $ p = gd  $ on $\Gamma_{1}$
+
+   the variationnel form is:
+ $\forall v\in H(div)$;  $v.n = 0$ on $\Gamma_{4}\} $:    $ \int_\Omega  u v + p div v -\int_{\Gamma_{123}} gd* v.n  = 0 $
+
+ $\forall q\in L^2$:   $  -\int_\Omega q div u = \int_Omega f q  $ 
+and $ u.n = (g1n,g2n).n$ on $\Gamma_4$ 
+
+*/
+mesh Th=square(10,10);
+fespace Vh(Th,RT1);
+fespace Ph(Th,P1dc);
+
+func gd = 1.;
+func g1n = 1.;
+func g2n = 1.; 
+func f = 1.;
+
+Vh [u1,u2],[v1,v2];
+Ph p,q; 
+
+problem laplaceMixte([u1,u2,p],[v1,v2,q],solver=UMFPACK,eps=1.0e-10,tgv=1e30,dimKrylov=150) =
+   int2d(Th)( p*q*0e-10+ u1*v1 + u2*v2 + p*(dx(v1)+dy(v2)) + (dx(u1)+dy(u2))*q )
+ + int2d(Th) ( f*q)
+ - int1d(Th,1,2,3)( gd*(v1*N.x +v2*N.y))   //  int on gamma 
+ + on(4,u1=g1n,u2=g2n);
+
+ laplaceMixte;
+ plot([u1,u2],coef=0.1,wait=1,ps="lapRTuv.eps",value=true); 
+ plot(p,fill=1,wait=1,ps="laRTp.eps",value=true);  
diff --git a/examples++-load/Leman-mesh.edp b/examples++-load/Leman-mesh.edp
new file mode 100644
index 0000000..77c7347
--- /dev/null
+++ b/examples++-load/Leman-mesh.edp
@@ -0,0 +1,35 @@
+load "ppm2rnm" load "isoline"
+string leman="lg.pgm";
+real AreaLac =  580.03; // $Km^2$
+real hsize= 5; 
+real[int,int] Curves(3,1);
+int[int] be(1);
+int nc;// nb of curve 
+{  
+  real[int,int] ff1(leman); // read  image and set to an rect. array 
+  int nx = ff1.n, ny=ff1.m; // grey value beetween 0 to 1 (dark)
+  // build a Cartesian mesh such that the origne is qt the right place.
+  mesh Th=square(nx-1,ny-1,[(nx-1)*(x),(ny-1)*(1-y)]);   
+   // warning  the numbering is of the vertices (x,y) is 
+   // given by $  i = x/nx + nx* y/ny $
+  fespace Vh(Th,P1);
+  Vh f1; f1[]=ff1; //  transforme array in finite element function.
+  plot(f1,wait=1); 
+  nc=isoline(Th,f1,iso=0.25,close=1,Curves,beginend=be,smoothing=.1,ratio=0.5); 
+  verbosity=1; 
+}
+// the longuest isoline 
+int ic0=be(0), ic1=be(1)-1;		
+plot([Curves(0,ic0:ic1),Curves(1,ic0:ic1)], wait=1);
+int NC= Curves(2,ic1)/hsize;
+real xl = Curves(0,ic0:ic1).max-5;
+real yl = Curves(1,ic0:ic1).min+5;
+border G(t=0,1) {  P=Curve(Curves,ic0,ic1,t);  label= 1 + (x>xl)*2 + (y<yl);} 		
+
+plot(G(-NC),wait=1); 
+mesh Th=buildmesh(G(-NC));
+plot(Th,wait=1);
+real scale = sqrt(AreaLac/Th.area);
+Th=movemesh(Th,[x*scale,y*scale]); // resize the  mesh to have the correct scale 
+cout << " Th.area = " << Th.area << " Km^2 " << " == " << AreaLac <<  "   Km^2 " << endl ;
+plot(Th,wait=1,ps="leman.eps");
diff --git a/examples++-load/MUMPS.cpp b/examples++-load/MUMPS.cpp
new file mode 100644
index 0000000..230f565
--- /dev/null
+++ b/examples++-load/MUMPS.cpp
@@ -0,0 +1,314 @@
+// SUMMARY  :   add interface with partionning library scotch 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : F. Hecht
+// E-MAIL   : F. Hecht <hecht at ljll.math.upmc.fr>
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:  mumps-seq blas  libseq  fc  pthread
+//ff-c++-cpp-dep: 
+//
+// F. Hecht  december 2011
+// ----------------------------
+//  file to add MUMPS sequentiel interface for sparce linear solver with dynamic load.
+
+#include  <iostream>
+using namespace std;
+
+
+#include "ff++.hpp"
+
+#include "mpi.h"
+#include "dmumps_c.h"
+#include "zmumps_c.h"
+
+const int  JOB_INIT = -1;
+const int  JOB_END =-2;
+const int JOB_ANA_FAC = 4;
+const int JOB_SOLVE = 3;
+const int USE_COMM_WORLD = -987654; 
+
+template<typename RR> struct MUMPS_STRUC_TRAIT {typedef void MUMPS;  typedef void R; };
+template<> struct MUMPS_STRUC_TRAIT<double>  {typedef DMUMPS_STRUC_C MUMPS; typedef double R;};
+template<> struct MUMPS_STRUC_TRAIT<Complex>  {typedef ZMUMPS_STRUC_C MUMPS; typedef ZMUMPS_COMPLEX R;};
+void mumps_c(DMUMPS_STRUC_C *id) { dmumps_c(id);}  
+void mumps_c(ZMUMPS_STRUC_C *id) { zmumps_c(id);}  
+
+
+template<typename  R>
+class SolveMUMPS_seq :   public MatriceMorse<R>::VirtualSolver 
+{
+public:
+  // typedef double R;
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  typedef typename  MUMPS_STRUC_TRAIT<R>::R MR; 
+  mutable typename MUMPS_STRUC_TRAIT<R>::MUMPS id; 
+
+  int & ICNTL(int i) const  { return id.icntl[i-1];}
+  R & CNTL(int i) const  { return id.cntl[i-1];}
+  int & INFO(int i) const { return id.info[i-1];}
+  R & RINFO(int i) const { return id.rinfo[i-1];}
+  int & INFOG(int i) const { return id.infog[i-1];}
+  R & RINFOG(int i) const { return id.rinfog[i-1];}
+  void SetVerb(int i=verbosity) const {
+    if( verbosity < 5) 
+      { 
+	ICNTL(1)=6;
+	ICNTL(3)=0;
+	ICNTL(4)=0;
+      }
+    else 
+      {
+	ICNTL(1)=6;
+	ICNTL(2)=0;
+	ICNTL(3)=6;
+	ICNTL(4)=0;
+	if(verbosity < 10) ICNTL(4)=1;
+	else if(verbosity < 15) ICNTL(4)=1;
+	else if(verbosity < 20) ICNTL(4)=2;
+	else if(verbosity < 25) ICNTL(4)=3;
+	else ICNTL(4)=4;
+      }
+    //cout << ICNTL(1) << " " << ICNTL(2) << " "<< ICNTL(3) << " "<< ICNTL(4) << endl; 
+  }
+  void Check(const char * msg="mumps-seq") const 
+  {
+    if( INFO(1) !=0) 
+      {
+	cout << " Erreur Mumps number " << INFO(1) << endl;
+	cout << " Fatal Erreur  " << msg << endl;
+	Clean();
+	id.job=JOB_END;
+	mumps_c(&id); /* Terminate instance */
+	int ierr = MPI_Finalize();
+	ErrorExec(msg,INFO(1) ); 
+      }
+  }
+  SolveMUMPS_seq(const MatriceMorse<R> &A,int strategy,double ttgv, double epsilon=1e-6,
+	       double pivot=-1.,double pivot_sym=-1.  ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv)
+  { 
+    int myid=0;
+    int ierr=0;
+    int argc=0;
+    char ** argv = 0;;
+    ierr = MPI_Init(&argc, &argv);
+    ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid);
+
+    id.job=JOB_INIT;
+    id.par=1;
+    id.sym=A.sym() ;
+    id.comm_fortran=USE_COMM_WORLD;
+    mumps_c(&id);
+    SetVerb();
+
+    ICNTL(5)=0; // input matrix type 
+    ICNTL(7)=7; // NUMBERING ...
+
+    ICNTL(9)=1; // 1: A x = b, !1 : tA x = b 
+    ICNTL(18) = 0; 
+    id.nrhs=0; // 
+    int  n = A.n;
+    int nz = A.nbcoef;
+    ffassert( A.n == A.m) ;
+
+    int * irn = new int[nz];
+    int * jcn = new int[nz];
+    R  * a= new  R [nz];
+    for(int i = 0;i<n;++i)
+      for(int k = A.lg[i]; k<A.lg[i+1];++k)
+      {
+	irn[k]=i+1;
+	jcn[k]=A.cl[k]+1;
+	a[k]= A.a[k];
+      }
+   
+    id.n = n; 
+    id.nz =nz; 
+    id.irn=irn; 
+    id.jcn=jcn;
+    id.a = (MR *) (void  *)a; 
+    id.rhs = 0;
+
+
+
+    id.job=JOB_ANA_FAC; // performs the analysis. and performs the factorization. 
+    mumps_c(&id);
+    Check("MUMPS-seq analayse and Factorize");
+    if(verbosity>3)
+      cout << "  -- MUMPS LU   n=  " << n << ", peak Mem: " << INFOG(22) << " Mb" << " sym: " << id.sym <<  endl;
+
+  }
+  void Solver(const MatriceMorse<R> &A,KN_<R> &x,const KN_<R> &b) const  {
+     ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    ffassert(A.ChecknbLine( id.n) && id.n == x.N() && A.ChecknbColumn(id.n) );
+    //  convert   array in long ...
+    if(verbosity>2)
+      cout << " -- MUMPS solve,  peak Mem : "<< INFOG(22) << " Mb,   n = " 
+	   << id.n << " sym =" << id.sym <<  endl; 
+    id.nrhs = 1;
+    x = b;
+    id.rhs= (MR *) (void  *) (R*) x;
+    SetVerb();
+    id.job=JOB_SOLVE; // performs the analysis. and performs the factorization. 
+    mumps_c(&id);
+    Check("MUMPS-seq Solve");
+    
+    if(verbosity>3)
+      cout << "   b min max " << b.min() << " " <<b.max() << endl;
+    if(verbosity>1) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+  }
+  void Clean() const 
+  {
+    if(verbosity>10)
+      cout << "~SolveMUMPS_seq:" << this << endl;
+    delete [] id.irn;
+    delete [] id.jcn;
+    delete [] id.a;
+    SetVerb();
+  }
+
+  ~SolveMUMPS_seq() 
+  { 
+    Clean();
+    id.job=JOB_END;
+    mumps_c(&id); /* Terminate instance */
+    int ierr = MPI_Finalize();  
+  }
+
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+/*
+template<>
+class SolveMUMPS_seq<Complex> :   public MatriceMorse<Complex>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  double tgv;
+
+
+
+  
+public:
+  SolveMUMPS_seq(const MatriceMorse<Complex> &A,int strategy,double ttgv, double epsilon=1e-6,
+     double pivot=-1.,double pivot_sym=-1.
+) : 
+    eps(epsilon),epsr(0),tgv(ttgv),
+    ar(0),ai(0),
+
+   { 
+    int status;
+    throwassert( !A.sym());
+
+  }
+  void Solver(const MatriceMorse<Complex> &A,KN_<Complex> &x,const KN_<Complex> &b) const  {
+        ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    if(verbosity>1)
+    {
+      cout << "  -- MUMPS _solve,  peak Mem : " <<  -1 << "Mbytes " << endl;
+      cout << "   b min max " << b.min() << " " <<b.max() << endl;
+      cout << "   x min max " << x.min() << " " <<x.max() << endl;
+    }
+  }
+
+  ~SolveMUMPS_seq() { 
+    if(verbosity>5)
+    cout << "~SolveMUMPS_seq " << endl;
+  }
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+     
+
+}; 
+*/
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildSolverIMUMPSseq(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+  if(verbosity>3)
+    cout << " BuildSolverMUMPSseq<double>" << endl;
+    return new SolveMUMPS_seq<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+inline MatriceMorse<Complex>::VirtualSolver *
+BuildSolverIMUMPSseq(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  if(verbosity>3)
+    cout << " BuildSolverMUMPSseq<Complex>" << endl;
+    return new SolveMUMPS_seq<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+DefSparseSolverSym<double>::SparseMatSolver SparseMatSolverSym_R ; ;
+DefSparseSolverSym<Complex>::SparseMatSolver SparseMatSolverSym_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetMUMPS_seq()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to MUMPSseq" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverIMUMPSseq;
+    DefSparseSolver<Complex>::solver =BuildSolverIMUMPSseq;    
+    DefSparseSolverSym<double>::solver  =BuildSolverIMUMPSseq;
+    DefSparseSolverSym<Complex>::solver =BuildSolverIMUMPSseq;    
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return  true;
+}
+
+
+void init22()
+{    
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  SparseMatSolverSym_R= DefSparseSolverSym<double>::solver;
+  SparseMatSolverSym_C= DefSparseSolverSym<Complex>::solver;
+
+  if(verbosity>1)
+    cout << "\n Add: MUMPS_seq:  defaultsolver defaultsolverMUMPS_seq" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver; 
+  DefSparseSolver<double>::solver =BuildSolverIMUMPSseq;
+  DefSparseSolver<Complex>::solver =BuildSolverIMUMPSseq;
+
+  if(! Global.Find("defaulttoMUMPSseq").NotNull() )
+    Global.Add("defaulttoMUMPSseq","(",new OneOperator0<bool>(SetMUMPS_seq));  
+}
+
+
+LOADFUNC(init22);
diff --git a/examples++-load/MUMPS_seq.cpp b/examples++-load/MUMPS_seq.cpp
new file mode 100644
index 0000000..230f565
--- /dev/null
+++ b/examples++-load/MUMPS_seq.cpp
@@ -0,0 +1,314 @@
+// SUMMARY  :   add interface with partionning library scotch 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : F. Hecht
+// E-MAIL   : F. Hecht <hecht at ljll.math.upmc.fr>
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:  mumps-seq blas  libseq  fc  pthread
+//ff-c++-cpp-dep: 
+//
+// F. Hecht  december 2011
+// ----------------------------
+//  file to add MUMPS sequentiel interface for sparce linear solver with dynamic load.
+
+#include  <iostream>
+using namespace std;
+
+
+#include "ff++.hpp"
+
+#include "mpi.h"
+#include "dmumps_c.h"
+#include "zmumps_c.h"
+
+const int  JOB_INIT = -1;
+const int  JOB_END =-2;
+const int JOB_ANA_FAC = 4;
+const int JOB_SOLVE = 3;
+const int USE_COMM_WORLD = -987654; 
+
+template<typename RR> struct MUMPS_STRUC_TRAIT {typedef void MUMPS;  typedef void R; };
+template<> struct MUMPS_STRUC_TRAIT<double>  {typedef DMUMPS_STRUC_C MUMPS; typedef double R;};
+template<> struct MUMPS_STRUC_TRAIT<Complex>  {typedef ZMUMPS_STRUC_C MUMPS; typedef ZMUMPS_COMPLEX R;};
+void mumps_c(DMUMPS_STRUC_C *id) { dmumps_c(id);}  
+void mumps_c(ZMUMPS_STRUC_C *id) { zmumps_c(id);}  
+
+
+template<typename  R>
+class SolveMUMPS_seq :   public MatriceMorse<R>::VirtualSolver 
+{
+public:
+  // typedef double R;
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  typedef typename  MUMPS_STRUC_TRAIT<R>::R MR; 
+  mutable typename MUMPS_STRUC_TRAIT<R>::MUMPS id; 
+
+  int & ICNTL(int i) const  { return id.icntl[i-1];}
+  R & CNTL(int i) const  { return id.cntl[i-1];}
+  int & INFO(int i) const { return id.info[i-1];}
+  R & RINFO(int i) const { return id.rinfo[i-1];}
+  int & INFOG(int i) const { return id.infog[i-1];}
+  R & RINFOG(int i) const { return id.rinfog[i-1];}
+  void SetVerb(int i=verbosity) const {
+    if( verbosity < 5) 
+      { 
+	ICNTL(1)=6;
+	ICNTL(3)=0;
+	ICNTL(4)=0;
+      }
+    else 
+      {
+	ICNTL(1)=6;
+	ICNTL(2)=0;
+	ICNTL(3)=6;
+	ICNTL(4)=0;
+	if(verbosity < 10) ICNTL(4)=1;
+	else if(verbosity < 15) ICNTL(4)=1;
+	else if(verbosity < 20) ICNTL(4)=2;
+	else if(verbosity < 25) ICNTL(4)=3;
+	else ICNTL(4)=4;
+      }
+    //cout << ICNTL(1) << " " << ICNTL(2) << " "<< ICNTL(3) << " "<< ICNTL(4) << endl; 
+  }
+  void Check(const char * msg="mumps-seq") const 
+  {
+    if( INFO(1) !=0) 
+      {
+	cout << " Erreur Mumps number " << INFO(1) << endl;
+	cout << " Fatal Erreur  " << msg << endl;
+	Clean();
+	id.job=JOB_END;
+	mumps_c(&id); /* Terminate instance */
+	int ierr = MPI_Finalize();
+	ErrorExec(msg,INFO(1) ); 
+      }
+  }
+  SolveMUMPS_seq(const MatriceMorse<R> &A,int strategy,double ttgv, double epsilon=1e-6,
+	       double pivot=-1.,double pivot_sym=-1.  ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv)
+  { 
+    int myid=0;
+    int ierr=0;
+    int argc=0;
+    char ** argv = 0;;
+    ierr = MPI_Init(&argc, &argv);
+    ierr = MPI_Comm_rank(MPI_COMM_WORLD, &myid);
+
+    id.job=JOB_INIT;
+    id.par=1;
+    id.sym=A.sym() ;
+    id.comm_fortran=USE_COMM_WORLD;
+    mumps_c(&id);
+    SetVerb();
+
+    ICNTL(5)=0; // input matrix type 
+    ICNTL(7)=7; // NUMBERING ...
+
+    ICNTL(9)=1; // 1: A x = b, !1 : tA x = b 
+    ICNTL(18) = 0; 
+    id.nrhs=0; // 
+    int  n = A.n;
+    int nz = A.nbcoef;
+    ffassert( A.n == A.m) ;
+
+    int * irn = new int[nz];
+    int * jcn = new int[nz];
+    R  * a= new  R [nz];
+    for(int i = 0;i<n;++i)
+      for(int k = A.lg[i]; k<A.lg[i+1];++k)
+      {
+	irn[k]=i+1;
+	jcn[k]=A.cl[k]+1;
+	a[k]= A.a[k];
+      }
+   
+    id.n = n; 
+    id.nz =nz; 
+    id.irn=irn; 
+    id.jcn=jcn;
+    id.a = (MR *) (void  *)a; 
+    id.rhs = 0;
+
+
+
+    id.job=JOB_ANA_FAC; // performs the analysis. and performs the factorization. 
+    mumps_c(&id);
+    Check("MUMPS-seq analayse and Factorize");
+    if(verbosity>3)
+      cout << "  -- MUMPS LU   n=  " << n << ", peak Mem: " << INFOG(22) << " Mb" << " sym: " << id.sym <<  endl;
+
+  }
+  void Solver(const MatriceMorse<R> &A,KN_<R> &x,const KN_<R> &b) const  {
+     ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    ffassert(A.ChecknbLine( id.n) && id.n == x.N() && A.ChecknbColumn(id.n) );
+    //  convert   array in long ...
+    if(verbosity>2)
+      cout << " -- MUMPS solve,  peak Mem : "<< INFOG(22) << " Mb,   n = " 
+	   << id.n << " sym =" << id.sym <<  endl; 
+    id.nrhs = 1;
+    x = b;
+    id.rhs= (MR *) (void  *) (R*) x;
+    SetVerb();
+    id.job=JOB_SOLVE; // performs the analysis. and performs the factorization. 
+    mumps_c(&id);
+    Check("MUMPS-seq Solve");
+    
+    if(verbosity>3)
+      cout << "   b min max " << b.min() << " " <<b.max() << endl;
+    if(verbosity>1) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+  }
+  void Clean() const 
+  {
+    if(verbosity>10)
+      cout << "~SolveMUMPS_seq:" << this << endl;
+    delete [] id.irn;
+    delete [] id.jcn;
+    delete [] id.a;
+    SetVerb();
+  }
+
+  ~SolveMUMPS_seq() 
+  { 
+    Clean();
+    id.job=JOB_END;
+    mumps_c(&id); /* Terminate instance */
+    int ierr = MPI_Finalize();  
+  }
+
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+/*
+template<>
+class SolveMUMPS_seq<Complex> :   public MatriceMorse<Complex>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  double tgv;
+
+
+
+  
+public:
+  SolveMUMPS_seq(const MatriceMorse<Complex> &A,int strategy,double ttgv, double epsilon=1e-6,
+     double pivot=-1.,double pivot_sym=-1.
+) : 
+    eps(epsilon),epsr(0),tgv(ttgv),
+    ar(0),ai(0),
+
+   { 
+    int status;
+    throwassert( !A.sym());
+
+  }
+  void Solver(const MatriceMorse<Complex> &A,KN_<Complex> &x,const KN_<Complex> &b) const  {
+        ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    if(verbosity>1)
+    {
+      cout << "  -- MUMPS _solve,  peak Mem : " <<  -1 << "Mbytes " << endl;
+      cout << "   b min max " << b.min() << " " <<b.max() << endl;
+      cout << "   x min max " << x.min() << " " <<x.max() << endl;
+    }
+  }
+
+  ~SolveMUMPS_seq() { 
+    if(verbosity>5)
+    cout << "~SolveMUMPS_seq " << endl;
+  }
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+     
+
+}; 
+*/
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildSolverIMUMPSseq(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+  if(verbosity>3)
+    cout << " BuildSolverMUMPSseq<double>" << endl;
+    return new SolveMUMPS_seq<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+inline MatriceMorse<Complex>::VirtualSolver *
+BuildSolverIMUMPSseq(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  if(verbosity>3)
+    cout << " BuildSolverMUMPSseq<Complex>" << endl;
+    return new SolveMUMPS_seq<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+DefSparseSolverSym<double>::SparseMatSolver SparseMatSolverSym_R ; ;
+DefSparseSolverSym<Complex>::SparseMatSolver SparseMatSolverSym_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetMUMPS_seq()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to MUMPSseq" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverIMUMPSseq;
+    DefSparseSolver<Complex>::solver =BuildSolverIMUMPSseq;    
+    DefSparseSolverSym<double>::solver  =BuildSolverIMUMPSseq;
+    DefSparseSolverSym<Complex>::solver =BuildSolverIMUMPSseq;    
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return  true;
+}
+
+
+void init22()
+{    
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  SparseMatSolverSym_R= DefSparseSolverSym<double>::solver;
+  SparseMatSolverSym_C= DefSparseSolverSym<Complex>::solver;
+
+  if(verbosity>1)
+    cout << "\n Add: MUMPS_seq:  defaultsolver defaultsolverMUMPS_seq" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver; 
+  DefSparseSolver<double>::solver =BuildSolverIMUMPSseq;
+  DefSparseSolver<Complex>::solver =BuildSolverIMUMPSseq;
+
+  if(! Global.Find("defaulttoMUMPSseq").NotNull() )
+    Global.Add("defaulttoMUMPSseq","(",new OneOperator0<bool>(SetMUMPS_seq));  
+}
+
+
+LOADFUNC(init22);
diff --git a/examples++-load/Makefile.am b/examples++-load/Makefile.am
new file mode 100644
index 0000000..94fbb9b
--- /dev/null
+++ b/examples++-load/Makefile.am
@@ -0,0 +1,243 @@
+all-local: @LOAD_COMPILE@
+TESTS=APk-AdaptEpsDeltaPk.edp APk-ExplicitPkTest.edp APk-FreeFemQA.edp APk-MetricPk.edp IPOTest.edp IpOptMinSurf.edp IpoptLap.edp IpoptMinSurfVol.edp IpoptVI.edp IpoptVI2.edp LapDG3.edp LapDG4.edp LapLNewSolver.edp LapMUMPS_seq.edp LapNewSolver.edp LapUmfpack64.edp LaplaceP3.edp LaplaceP4.edp LaplaceRT1.edp Leman-mesh.edp MetricKuate.edp NSP2BRP0.edp PARDISO.edp SuperLU.edp VarIneq2.edp  bilapMorley.edp bmo.edp buildlayermesh.edp checkglumeshcube.edp cmaes-VarIneq.edp cmaes-oven.edp conv [...]
+# all test can fail must but clean ????  FH... 
+XFAIL_TESTS=$(TESTS)
+
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPP) FLAGS_FFPP=-nw
+
+EXTRA_DIST= $(TESTS) all.edp makeref.edp regtests.edp \
+ff-get-dep.in ff-get-dep.awk ff-pkg-download.in load.link.in  include.tar.gz \
+ BernadiRaugel.cpp Morley.cpp dfft.cpp  \
+ funcTemplate.cpp mat_dervieux.cpp mat_psi.cpp myfunction.cpp \
+ mat_dervieux.cpp  funcTemplate.cpp \
+ regtests.m4     addNewType.cpp \
+  qf11to25.cpp  Element_P3.cpp  Element_P3.hpp  Element_P4.cpp  Element_P4.hpp \
+  Element_P3dc.cpp  Element_P3dc.hpp Element_P4dc.cpp  Element_P4dc.hpp \
+  Element_PkEdge.cpp \
+  SuperLu.cpp  \
+  NewSolver.cpp \
+  splitmesh3.cpp    splitmesh6.cpp   \
+  README_SuperLU \
+  tetgen.cpp\
+  msh3.cpp msh3.hpp\
+  ffrandom.cpp   \
+  medit.cpp  \
+  bmo.cpp lgbmo.cpp bmo.hpp \
+ fflapack.cpp	lapack.cpp	clapack.h  \
+ fig.pgm lg.pgm ppm2rnm.cpp ppmimg.h   \
+ DxWriter.cpp  metis.cpp pcm.cpp pcm.hpp pcm2rnm.cpp \
+ UMFPACK64.cpp iovtk.cpp gmsh.cpp MetricKuate.cpp  \
+ ffnewuoa.cpp		newuoa.f Element_P1dc1.cpp ilut.cpp  \
+ freeyams.cpp mmg3d-v4.0.cpp  mshmet.cpp \
+ BinaryIO.cpp	gsl.cpp   gsl.awk ff_gsl_awk.hpp gsl.idp isolineP1.cpp isoline.cpp lg.pgm  \
+ thresholdings.cpp	 \
+ VTK_writer_3d.cpp VTK_writer.cpp splitedges.cpp  \
+ Element_Mixte.cpp    \
+ myfunction2.cpp   \
+ cmaes.cpp \
+ cmaes.h cmaes_interface.h ff-cmaes.cpp \
+ ff-NLopt.cpp \
+ MetricPk.cpp GeometryQA.cpp  FreeFemQA.cpp BasicMath.h  TensorK.hpp  Geometry.hpp  \
+ RZ.h SortedList.h ExampleMetrics.h  \
+ cube.msh  \
+ MUMPS_seq.cpp \
+ MUMPS.cpp \
+ ff-Ipopt.cpp \
+ scotch.cpp    shell.cpp \
+ pipe.cpp pstream.h  \
+ symmetrizeCSR.cpp \
+ dmatrix.hpp PARDISO.cpp             \
+ ch.pts   BEC.cpp bfstream.cpp iohdf5.cpp \
+ iohd5-beam-2d.edp	iohd5-beam-3d.edp
+
+LIST_COMPILE=myfunction.$(DYLIB_SUFFIX)  BernadiRaugel.$(DYLIB_SUFFIX) \
+         Morley.$(DYLIB_SUFFIX) funcTemplate.$(DYLIB_SUFFIX) addNewType.$(DYLIB_SUFFIX) \
+         qf11to25.$(DYLIB_SUFFIX)  Element_P3.$(DYLIB_SUFFIX)    Element_P4.$(DYLIB_SUFFIX)  \
+	 Element_P3dc.$(DYLIB_SUFFIX)    Element_P4dc.$(DYLIB_SUFFIX) 	\
+	 Element_PkEdge.$(DYLIB_SUFFIX)  msh3.$(DYLIB_SUFFIX) \
+	splitmesh3.$(DYLIB_SUFFIX)  splitmesh6.$(DYLIB_SUFFIX) \
+	ffrandom.$(DYLIB_SUFFIX)  \
+	medit.$(DYLIB_SUFFIX)  \
+	mat_dervieux.$(DYLIB_SUFFIX) lgbmo.$(DYLIB_SUFFIX) mat_psi.$(DYLIB_SUFFIX)\
+	ppm2rnm.$(DYLIB_SUFFIX) DxWriter.$(DYLIB_SUFFIX) \
+	pcm2rnm.$(DYLIB_SUFFIX) $(DYLIB_OTHER_COMPILE)  \
+	iovtk.$(DYLIB_SUFFIX) 	 gmsh.$(DYLIB_SUFFIX) MetricKuate.$(DYLIB_SUFFIX) \
+	Element_P1dc1.$(DYLIB_SUFFIX) BinaryIO.$(DYLIB_SUFFIX) \
+        isolineP1.$(DYLIB_SUFFIX) isoline.$(DYLIB_SUFFIX)  thresholdings.$(DYLIB_SUFFIX) \
+        VTK_writer_3d.$(DYLIB_SUFFIX)  VTK_writer.$(DYLIB_SUFFIX) \
+	splitedges.$(DYLIB_SUFFIX) Element_Mixte.$(DYLIB_SUFFIX) \
+	myfunction2.$(DYLIB_SUFFIX) \
+	MetricPk.$(DYLIB_SUFFIX) FreeFemQA.$(DYLIB_SUFFIX) shell.$(DYLIB_SUFFIX) \
+	@TOOL_DYLIB_pipe@ symmetrizeCSR.$(DYLIB_SUFFIX)  BEC.$(DYLIB_SUFFIX) \
+	bfstream.$(DYLIB_SUFFIX) @TOOL_DYLIB_iohdf5@
+
+# FFCS - some libraries are skipped because the corresponding tool is deactivated.
+
+LIST_COMPILE_PKG=tetgen.$(DYLIB_SUFFIX) @TOOL_DYLIB_superlu@ dfft.$(DYLIB_SUFFIX) @TOOL_DYLIB_metis@		\
+	@TOOL_DYLIB_umfpack@ NewSolver.$(DYLIB_SUFFIX) @TOOL_DYLIB_lapack@ @TOOL_DYLIB_fflapack@		\
+	ffnewuoa.$(DYLIB_SUFFIX) ilut.$(DYLIB_SUFFIX) @TOOL_DYLIB_yams@ @TOOL_DYLIB_mmg3d@ @TOOL_DYLIB_mshmet@	\
+	@TOOL_DYLIB_gsl@ @TOOL_DYLIB_mumps_seq@ @TOOL_DYLIB_ipopt@ @TOOL_DYLIB_nlopt@ ff-cmaes.$(DYLIB_SUFFIX)	\
+	@TOOL_DYLIB_scotch@ @TOOL_DYLIB_pardiso@
+
+bin_PROGRAMS=
+
+# FFCS parallel make: some targets need to be built first, sequentially
+
+load_compile: ff-c++ WHERE_LIBRARY-download include.done freefem++.pref
+#
+# max_load
+	- at rm "Missing-plugins-$(DYLIB_SUFFIX).log" 2>/dev/null || true
+	$(MAKE) $(AM_MAKEFLAGS) $(LIST_COMPILE) $(LIST_COMPILE_PKG)
+	@if test -f Missing-plugins-$(DYLIB_SUFFIX).log ; then cat Missing-plugins-$(DYLIB_SUFFIX).log; fi; exit 0 
+	@echo Warning missing plugin: `for i in $(LIST_COMPILE) $(LIST_COMPILE_PKG); do if test ! -s $i ; then j=1; echo "$i," ;fi; done`
+	echo " finish build list $(DYLIB_SUFFIX)"
+
+.cpp.$(DYLIB_SUFFIX): ff-c++
+	 ./ff-c++ -auto $< 
+
+# FFCS - 26/10/11 - Unpacking include.tar.gz is very often buggy under Cygwin (softlinks are randomly replaced with
+# empty files without any access right). So just replace the whole thing with a plain copy.
+
+allheaders=../src/fflib/AddNewFE.h ../src/fflib/AFunction_ext.hpp ../src/fflib/AFunction.hpp ../src/fflib/AnyType.hpp	\
+	../src/fflib/array_init.hpp ../src/fflib/array_resize.hpp ../src/fflib/array_tlp.hpp				\
+	../src/femlib/assertion.hpp ../src/femlib/BamgFreeFem.hpp ../src/Algo/BFGS.hpp ../src/Algo/BrentLS.hpp		\
+	../src/Algo/CG.hpp ../src/femlib/CGNL.hpp ../src/fflib/CodeAlloc.hpp ../config.h ../config-wrapper.h		\
+	../src/Algo/CubicLS.hpp ../src/Algo/defs.hpp ../src/femlib/DOperator.hpp ../src/libMesh/eigenv.h		\
+	../src/fflib/endian.hpp ../src/fflib/environment.hpp ../src/fflib/error.hpp ../src/femlib/fem3.hpp		\
+	../src/femlib/fem.hpp ../src/femlib/FESpace.hpp ../src/femlib/FESpacen.hpp ../src/fflib/ff++.hpp		\
+	../src/fflib/ffstack.hpp ../src/femlib/FQuadTree.hpp ../src/femlib/GenericMesh.hpp				\
+	../src/Graphics/getprog-unix.hpp ../src/Graphics/glrgraph.hpp ../src/femlib/gmres.hpp				\
+	../src/femlib/GQuadTree.hpp ../src/femlib/HashTable.hpp ../src/femlib/HeapSort.hpp ../src/fflib/InitFunct.hpp	\
+	../src/fflib/ffapi.hpp ../src/femlib/Label.hpp ../src/fflib/lex.hpp ../src/fflib/lgfem.hpp			\
+	../src/fflib/lgmesh3.hpp ../src/fflib/lgsolver.hpp ../src/lglib/lg.tab.hpp ../src/femlib/libmesh5.h		\
+	../src/Algo/LineSearch.hpp ../src/femlib/MatriceCreuse.hpp ../src/femlib/MatriceCreuse_tpl.hpp			\
+	../src/femlib/Mesh1dn.hpp ../src/femlib/Mesh2dn.hpp ../src/bamglib/Mesh2.h ../src/femlib/Mesh3dn.hpp		\
+	../src/bamglib/Meshio.h ../src/femlib/MeshPoint.hpp ../src/bamglib/meshtype.h ../src/bamglib/Metric.h		\
+	../src/Graphics/mode_open.hpp ../src/Algo/NewtonRaphson.hpp ../src/Algo/NRJ.hpp ../src/fflib/Operator.hpp	\
+	../src/Algo/Optima.hpp ../src/Algo/Param.hpp ../src/femlib/PkLagrange.hpp ../src/fflib/PlotStream.hpp		\
+	../src/fflib/problem.hpp ../src/femlib/QuadratureFormular.hpp ../src/bamglib/QuadTree.h ../src/femlib/R1.hpp	\
+	../src/bamglib/R2.h ../src/femlib/R2.hpp ../src/femlib/R3.hpp ../src/femlib/RefCounter.hpp			\
+	../src/Graphics/rgraph.hpp ../src/femlib/RNM.hpp ../src/femlib/RNM_opc.hpp ../src/femlib/RNM_op.hpp		\
+	../src/femlib/RNM_tpl.hpp ../src/Algo/RosenBrock.hpp ../src/fflib/Serialize.hpp ../src/bamglib/SetOfE4.h	\
+	../src/fflib/showverb.hpp ../src/femlib/splitsimplex.hpp ../src/fflib/String.hpp				\
+	../src/fflib/strversionnumber.hpp ../src/fflib/throwassert.hpp ../src/femlib/ufunction.hpp			\
+	../src/fflib/versionnumber.hpp ../src/bamglib/write_hdf5.hpp	../src/bamglib/write_xdmf.hpp                   \
+	../src/fflib/P1IsoValue.hpp
+
+if ENABLE_FFCS
+
+include.done: $(allheaders)
+	-rm -rf include
+	mkdir -p include
+	cp $^ include
+	touch $@
+
+else
+include.done: $(allheaders)
+	-rm -rf include
+	mkdir -p  include
+	for i in $(allheaders); do  ln -s ../$$i include/. ; done 
+	touch $@
+endif
+
+clean-local::
+	-rm -r include
+	-rm include.done
+
+Ref: makeref.edp
+	../src/nw/FreeFem++-nw makeref.edp
+
+makeref.edp: regtests.m4 ../regtests.m4
+	m4 regtests.m4 > makeref.edp
+
+all-local: all.edp regtests.edp load_compile
+
+# FFCS - 27/2/13 - remove dependency on Makefile to avoid recompiling everything everytime something is changed in the
+# configuration step
+
+all.edp:
+	@(echo "NoGraphicWindow=true;NoUseOfWait=true;int verbosityy=verbosity;"; \
+	for i in *`ls *.edp|grep -v -E '^(all|regtests|makeref|ref)\.edp$$'` ; do  \
+		echo ' cout << "--------- file : '$$i' --------------------------------------------------------" << endl;' ;\
+		echo "verbosity=verbosityy;" ; \
+		echo \{ include \"$$i\"\;\}\; ;\
+		echo ' cout << "------------------------------------------------------------------------------ " << endl;' ;\
+	done) > $@
+
+# To check the scripts against their reference values
+regtests.edp: regtests.m4 ../regtests.m4
+	m4 -DASSERT regtests.m4 > regtests.edp
+
+# FFCS - 27/2/13 - remove dependency on Makefile to avoid recompiling everything everytime something is changed in the
+# configuration step
+
+$(LIST_COMPILE):ff-c++ include.done
+
+clean-local::
+	-rm *.o *.$(DYLIB_SUFFIX) load.link WHERE_LIBRARY-download ff-get-dep ff-c++ ff-pkg-download \
+	  $(LIST_COMPILE) $(LIST_COMPILE_PKG)  regtests.edp makeref.edp
+	-rm -rf include include.done
+ff-c++:load.link.in load.link WHERE_LIBRARY-download ff-get-dep ../config.status
+	../config.status  --file=ff-c++:load.link.in
+	chmod a+x ff-c++
+load.link:load.link.in ../config.status
+	../config.status  --file=load.link:load.link.in
+	chmod a+x load.link
+ff-pkg-download:ff-pkg-download.in ../config.status
+	../config.status  --file=$@:$@.in
+	chmod a+x $@
+	cp $@ ../download/bin
+ff-get-dep:ff-get-dep.in ../config.status
+	../config.status  --file=$@:$@.in
+	chmod a+x $@
+	-if [ -d ../download/bin ] ;then cp $@ ../download/bin; fi
+WHERE_LIBRARY-download:ff-pkg-download FORCE  WHERE_LIBRARY-config WHERE_LIBRARY
+	@./ff-pkg-download >$@-new
+	@diff $@-new $@  || (cp $@-new $@ ;touch WHERE_LIBRARY)
+WHERE_LIBRARY:
+	touch $@
+FORCE: ;
+freefem++.pref:
+	echo loadpath = \"./\" >freefem++.pref
+install-exec-local:: load_compile WHERE_LIBRARY
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/lib
+	test -n "$(MPIPROG)" && $(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/lib/mpi
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/include
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/etc
+	$(INSTALL_DATA)  clapack.h ppmimg.h  bmo.hpp msh3.hpp pcm.hpp  include/*   $(DESTDIR)$(ff_prefix_dir)/include
+	$(INSTALL)  -m 555 $(LIST_COMPILE) $(DESTDIR)$(ff_prefix_dir)/lib
+	$(INSTALL)  -m 555 ff-get-dep.awk  WHERE_LIBRARY-config WHERE_LIBRARY  $(DESTDIR)$(ff_prefix_dir)/lib
+	for i in  WHERE_LIBRARY-config WHERE_LIBRARY WHERE_LIBRARY-download; do \
+	  sed <$$i >$(DESTDIR)$(ff_prefix_dir)/lib/$$i 's#$(abs_top_builddir)/download#$(ff_prefix_dir)#' ;\
+	 done
+	echo loadpath += \"./\"  >$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
+	echo loadpath += \"$(ff_prefix_dir)/lib\"  >>$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
+	echo includepath += \"$(ff_prefix_dir)/idp\"  >>$(DESTDIR)$(ff_prefix_dir)/etc/freefem++.pref
+	$(INSTALL_SCRIPT) ff-c++  $(DESTDIR)${bindir}
+	$(INSTALL_SCRIPT) ff-pkg-download  $(DESTDIR)${bindir}
+	$(INSTALL_SCRIPT) ff-get-dep   $(DESTDIR)${bindir}
+##	$(DESTDIR)${bindir}/ff-pkg-download $(DESTDIR) >$(DESTDIR)$(ff_prefix_dir)/lib/WHERE_LIBRARY-download
+	-for i in $(LIST_COMPILE_PKG); do \
+	 if [ -f $$i ] ; then 	$(INSTALL)  -m 555 $$i $(DESTDIR)$(ff_prefix_dir)/lib; fi; done
+	- if [ -n "$(MPIPROG)" ] ; then \
+		for i in $(LIST_COMPILE_PKG) $(LIST_COMPILE); do \
+		 if [ -f ../examples++-mpi/$$i ] ; then \
+	    	    $(INSTALL)  -m 555 ../examples++-mpi/$$i $(DESTDIR)$(ff_prefix_dir)/lib/mpi; \
+	        else echo missing install mpi version ???  ../examples++-mpi/$$i ;\
+	         fi;  \
+	        done ; \
+	fi
+
+clean-local::
+	-rm *.fg *.eps *~ *.ps  *.mesh *.mesh.gmsh ListOfAllocPtr-8.bin ffglut*.ppm Th.o.meshb	Th3.d.meshb	dep.sol.meshbgh \
+ipopt.out	mmg.out xxxx ThFF.txt		TriQA.txt		cavidadTT.txt		mass.txt		xy.txt \
+ThFF_Metric.txt		TriQA_Metric.txt	datanc.txt		u100m8.txt \
+TTh.sol		Th.o.sol	Th3.sol		dep.o.sol	dep.sol		gradient.sol	hessien.sol pippo.data pippo.dx testsavemedit.solb med.gp bidule.vtk	disque.vtk g-iso 
+
+
+# FFCS: add tags for files that are not specified to automake by a SOURCE directive (this tags file is automatically
+# taken into account by automake when it sees it).
+
+TAGS:
+	etags *.?pp
diff --git a/examples++-load/MetricKuate.cpp b/examples++-load/MetricKuate.cpp
new file mode 100644
index 0000000..49f0ffc
--- /dev/null
+++ b/examples++-load/MetricKuate.cpp
@@ -0,0 +1,670 @@
+//  Implementation of P1-P0 FVM-FEM
+// ---------------------------------------------------------------------
+// $Id$
+// compile and link with ./load.link  mat\_dervieux.cpp 
+#include  <iostream>
+#include  <cfloat>
+#include  <cmath>
+using namespace std;
+/*
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "RNM.hpp"
+// remove problem of include 
+#undef  HAVE_LIBUMFPACK
+#undef HAVE_CADNA
+#include "MatriceCreuse_tpl.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "problem.hpp"
+//#include "ellipsemax.hpp"
+*/
+#include "ff++.hpp" 
+
+using namespace std;
+
+
+R Min (const R a,const R b);
+R Max (const R a,const R b);
+inline void Exchange (R a,R b) {R c=a;a=b;b=c;};
+//const R precision = 1e-10;
+
+int  LireTaille( const char * NomDuFichier,int &nbnoeuds);
+int  Lire( const char * NomDuFichier,int n ,R2 noeuds[] );
+template<typename T>
+bool from_string( const string & Str, T & Dest )
+{
+  // cr�er un flux � partir de la chaine donn�e
+  istringstream iss( Str );
+  // tenter la conversion vers Dest
+  iss >> Dest;
+  return !Dest;
+};
+
+
+void metrique(int nbpoints, R2 * Point,R &A, R &B,R &C,R epsilon)
+{
+
+
+  C=0.;
+   
+  R  epsilon0=1e-5,precision=1e-15,delta=1e-10;
+  R inf =1e50;
+ 
+  R Rmin=inf,Rmax=0.;
+  
+  int indiceX0=0;
+  
+ 
+  R2 *PPoint = new R2 [nbpoints];
+  
+  for(int i=0;i<nbpoints;i++)
+    {
+     
+      Rmax=Max(Rmax,Point[i].norme());
+      
+      //---d�placement des points situ�es sur les axes--------------
+      if(abs(Point[i].x)<=precision)
+	{
+	  if(Point[i].y<0)
+	    {
+	      Point[i].x=-delta;
+	      Point[i].y=-sqrt(pow(Point[i].y,2)-pow(Point[i].x,2));
+	    }
+	  if(Point[i].y>0)
+	    {
+	      Point[i].x=delta;
+	      Point[i].y=sqrt(pow(Point[i].y,2)-pow(Point[i].x,2));
+	    }
+	}
+      
+      if(abs(Point[i].y)<=precision)
+	{
+	  if(Point[i].x<0)
+	    {
+	      Point[i].y=-delta;
+	      Point[i].x=-sqrt(pow(Point[i].x,2)-pow(Point[i].y,2));
+	    }
+	  if(Point[i].x>0)
+	    {
+	      Point[i].y=delta;
+	      Point[i].x=sqrt(pow(Point[i].x,2)-pow(Point[i].y,2));
+	    }
+	}
+      //-----------------------------------------------------------
+      assert(abs(Point[i].x*Point[i].y)>=pow(precision,2));
+
+      if(Rmin>Point[i].norme())
+	{
+	  indiceX0=i;
+	  Rmin=Point[i].norme();
+	}
+    
+      //cout<<Point[i]<<endl;	
+    }
+  
+  
+  
+  //-------permutation des indices de la liste des points : 
+  //ranger la liste en commen�ant par le point X0-------
+  for(int k=0;k<nbpoints-indiceX0;k++)
+    {
+      PPoint[k]=Point[k+indiceX0];
+    }
+  
+  for(int k=nbpoints-indiceX0;k<nbpoints;k++)
+    {
+      PPoint[k]=Point[k-nbpoints+indiceX0];
+    }
+  
+  
+  for(int i=0;i<nbpoints;i++) Point[i]=PPoint[i];	
+ 
+  
+  
+  
+  
+  //----------------------------------------------------------------
+  
+ 
+  int test=-1;
+  
+  
+  
+ 
+  
+  R X0;
+  R Y0;
+  
+
+  R bmin= 0.,bmax=inf,b1,b2,aik=0.,bik=0.,cik=0.;
+ R Xk=0.,Yk=0.,Ck=0.,Ak =0.,Bk=0.,Xi=0.,Yi=0.,ri,detXY=0.,Ri,R0,r0;
+
+ 
+ X0=Point[0].x;
+ Y0=Point[0].y;
+ r0=Point[0].norme();
+ assert(r0 == Rmin);
+
+ //cout<<" Rmin = "<<Rmin<<" Rmax =  "<<Rmax<<endl;
+ 
+
+ R EPS=0.;// pour recuperer la valeur de epsilon0 optimale
+  R epsilonmax=r0*(1.-r0/Rmax)/20.;
+ 
+  R  Tabepsilon[20];
+
+  int neps =4;
+ //--------- discertisation de epsilon0----------------------------------
+ if(epsilonmax>1e-2)
+   {
+     neps=10;
+
+     Tabepsilon[0]=1e-5;
+     Tabepsilon[1]=1e-4;
+     Tabepsilon[2]=1e-3;
+     for(int i=3;i<neps;i++)
+       {
+	 Tabepsilon[i]=(i-3)*(epsilonmax-1e-2)/(neps-4.) +1e-2;
+  
+       }
+     
+   }
+
+
+ else
+   {
+    
+     Tabepsilon[0]=1e-5;
+     Tabepsilon[1]=1e-4;
+     Tabepsilon[2]=1e-3;
+     Tabepsilon[3]=1e-2;
+   }
+ //------------------------------------------------------------------------
+
+ int condition = -1;
+
+ if(r0<=epsilon0)epsilon0=r0*epsilon0;
+ B=A=1./((r0-epsilon0)*(r0-epsilon0));
+  R epsilon0min=epsilon0;
+
+   if(abs(Rmin-Rmax)>1e-5)
+    {
+     //cout<<" Rmax - Rmin  "<<Rmax-Rmin<<endl;
+     for(int ee=0;ee<neps-1;ee++) //boucle sur epsilon0---------------
+       {
+	 epsilon0= Tabepsilon[ee];
+	 if(r0<=epsilon0)epsilon0=r0*epsilon0;
+	 assert(r0>epsilon0);
+	 R0=r0/(r0-epsilon0);
+	 
+	 for(int i=1;i<nbpoints;i++)	 //boucle sur chaque noeud
+	   {
+	     
+	     Xi=Point[i].x;
+	     Yi=Point[i].y;
+	     ri=Point[i].norme();
+	     if(ri<=epsilon)epsilon=ri*epsilon;
+	     assert(ri>epsilon);
+	     Ri = ri/(ri-epsilon);
+	     detXY=Xi*Y0-Yi*X0;
+	     
+	     
+	     
+	     
+	     
+	     
+	     //------deplacement des points align�s avec l'origine et X0-----------
+	     if(abs(detXY)<=precision)
+	       {
+		 
+		 Xi += delta;
+		 
+		 if(Yi<0)Yi= -sqrt(pow(ri,2)- pow(Xi,2));
+		 else Yi=sqrt(pow(ri,2)- pow(Xi,2));
+		 Point[i].x=Xi;
+		 Point[i].y=Yi;
+		 ri=Point[i].norme();
+		 if(ri<=epsilon)epsilon=ri*epsilon;
+		 assert(ri>epsilon);
+		 Ri = ri/(ri-epsilon);
+		 
+	       }
+	     
+	     detXY=Xi*Y0-Yi*X0;
+	     
+	     assert(abs(detXY)>=precision);   
+	     
+	     
+	     //-----------------------------------------------------------------
+	     
+	     //-----racines du polynome en b � minimiser----------------------------
+	    
+	     R bb1=(1./pow(detXY,2))*(pow(X0*Ri,2)+pow(Xi*R0,2)-2.*abs(Xi*X0)*sqrt(pow(R0*Ri,2)-pow(detXY/(Rmax*(r0-epsilon0)),2)));
+	    
+	     R bb2=(1./pow(detXY,2))*(pow(X0*Ri,2)+pow(Xi*R0,2)+2.*abs(Xi*X0)*sqrt(pow(R0*Ri,2)-pow(detXY/(Rmax*(r0-epsilon0)),2))); 
+	   
+	    
+	     //--fin----racines du polynome en b � minimiser--------------------
+	     
+	     
+	     bmax=Min(bb2,pow(Rmax/pow((r0),2),2));
+	     
+	     
+	     bmin=Max(1./(Rmax*Rmax),bb1);//minoration de b
+	       R Cte = Max(1e-9,(bmax-bmin)*1e-9);
+	       bmin=bmin*(1.+Cte);
+	       bmax=bmax*(1.-Cte);
+	     
+	   
+	     //bornes de b-----------------------------------------------------------
+	     
+	     //cas:  majoration de c --------------------------------------------
+	     R Li=X0*Xi*(pow(Rmax/pow(r0-epsilon0min,2),2)-1./pow(Rmax,2))+(pow(Ri*X0,2)-pow(R0*Xi,2))/detXY;
+	     R LiXY=Xi*Y0+Yi*X0;
+	     
+	     if(abs(LiXY)>=precision)
+	       {
+		 condition=1;
+		 
+		 if(Xi*X0>0)
+		   {
+		     if(LiXY>0) bmin=Max(bmin,-Li/LiXY);
+		     else bmax=Min(bmax,-Li/LiXY);
+		   }
+		 else
+		   {
+		     
+		     if(LiXY<0) bmin=Max(bmin,-Li/LiXY);
+		     else bmax=Min(bmax,-Li/LiXY); 
+		   }
+		 
+	       }
+	     
+	     else
+	       {
+		 if(Li<0) condition =0;
+		 else condition =1;
+	       }
+	     
+	     
+	     
+	     //cas  minoration de c --------------------------------------------
+	     Li=X0*Xi*(-pow(Rmax/pow(r0-epsilon0min,2),2)+1./pow(Rmax,2))+(pow(Ri*X0,2)-pow(R0*Xi,2))/detXY;
+	     LiXY=Xi*Y0+Yi*X0;
+	     
+	     if(abs(LiXY)>=precision)
+	       {
+		 condition=1;
+		 
+		 if(Xi*X0>0)
+		   {
+		     if(LiXY<0) bmin=Max(bmin,-Li/LiXY);
+		     else bmax=Min(bmax,-Li/LiXY);
+		   }
+		 else
+		   {
+		     
+		     if(LiXY>0) bmin=Max(bmin,-Li/LiXY);
+		     else bmax=Min(bmax,-Li/LiXY); 
+		   }
+		 
+	       }
+	     
+	     else
+	       {
+		 if(Li>0) condition =0;
+		 else condition =1;
+	       }
+	     
+	     if (condition==1)
+	       {
+		 
+		 
+		 //--cas : minoration de a-----------------------------------------------
+		 
+		 R Gi=((Xi*Yi*R0*R0-X0*Y0*Ri*Ri)/detXY +Xi*X0/(Rmax*Rmax))/(Yi*Y0);
+		 
+		 if(Xi*X0>0)
+		   {
+		     if(Yi*Y0>0) bmin=Max(bmin,Gi);
+		     else bmax=Min(bmax,Gi);
+		   }
+		 else
+		   {
+		     if(Yi*Y0<0) bmin=Max(bmin,Gi);
+		     else bmax=Min(bmax,Gi);
+		   }
+		 
+		 //cas :majoration de a------------------------------------------------
+		 
+		 
+		 R Hi=(Xi*X0*Rmax*Rmax/pow((r0-epsilon0min),4)+(Xi*Yi*R0*R0-X0*Y0*Ri*Ri)/detXY)/(Yi*Y0);
+		 if(Xi*X0>0)
+		   {
+		     if(Yi*Y0>0) bmax=Min(bmax,Hi);
+		     else bmin=Max(bmin,Hi);
+		   }
+		 else
+		   {
+		     if(Yi*Y0<0) bmax=Min(bmax,Hi);
+		     else bmin=Max(bmin,Hi);
+		     
+		   }
+		 
+		 
+		 
+		 
+		 
+		 //------fin bornes de b------------------------------------------------
+		 b2=bmax;
+		 b1=bmin;
+		 
+		 for(int k=1;k<nbpoints ;k++)//on balaye les contraintes
+		   {
+		   
+		     Xk=Point[k].x;
+		     Yk=Point[k].y;
+		     Bk=(Yk*Yk*Xi*X0 +Xk*(Xk*Yi*Y0-Yk*(Yi*X0+Xi*Y0)))/(Xi*X0);
+		     Ck=(X0*Xi*detXY-Xk*(Xi*R0*R0*(Yk*Xi-Yi*Xk) +X0*Ri*Ri*(-Yk*X0+Y0*Xk)))/(Xi*X0*detXY);
+		     
+		     assert(abs(Xi*X0*Y0*Yi*Xk*Yk)>=pow(precision,5));
+		     if(abs(Bk)>precision)//non nul
+		       {
+			 if(Bk<=0) bmax=Min(bmax,Ck/Bk);
+			 
+			 else  bmin=Max(bmin,Ck/Bk);
+			 
+			 if((bmax<b1)||(bmin>b2)||(bmin>bmax))
+			   {
+			     //cout<<" i = "<<i<<"  k = "<<k<<endl;	
+			     test=0;
+			     break;  
+			   }
+			 
+			 else  test=1;		       
+			 
+		       }
+		     else
+		       {
+			 
+			 if (Ck>precision) 
+			   { 
+			     test=0;
+			     break;  	
+			   }
+			 else //Ck<=0
+			   {
+			     test=-1;// 1 peut etre
+			     
+			   }
+		       }
+		     
+		     
+		   }
+		 if(test==1)
+		   { 
+		   
+		     R a0=-pow((detXY/(Xi*X0)),2);
+		     R a1=2.*(pow(Ri/Xi,2)+pow(R0/X0,2));
+		     if(((a0*bmax+a1)*bmax) <((a0*bmin+a1)*bmin)) bik=bmax;
+		     else bik=bmin;
+		     aik=(Ri*Ri*Y0*X0 -R0*R0*Yi*Xi+bik*Yi*Y0*detXY)/(detXY*Xi*X0);
+		     //(Ri*Ri*Y0/Xi - R0*R0*Yi/X0)/detXY+bik*Yi*Y0/(Xi*X0);
+		     cik=( -Ri*Ri*X0*X0 + R0*R0*Xi*Xi-bik*(Yi*X0+Y0*Xi)*detXY)/(detXY*Xi*X0);
+		    
+		     
+		     
+		   
+		     assert((4.*aik*bik-cik*cik)>=0.);// aire positive	 
+		     assert(abs((4.*aik*bik-cik*cik)-pow(2./(Rmax*(r0-epsilon0)),2))>0);// aire positive
+		     if((4.*aik*bik-cik*cik)<=(4.*A*B-C*C)) 
+		       {
+			 A=aik;
+			 B=bik;
+			 C=cik;
+			 EPS=epsilon0;
+		       }
+		     
+		     
+		     
+		   }
+		 
+		 
+		 
+		 //-----------------------------------------------------------------  
+		 
+	       }  
+	     
+	     
+	   }
+       }
+     
+     }
+ else
+   {
+     A=B=1./(Rmin*Rmin);
+     C=0.;
+     }
+ delete [] PPoint;  
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int  LireTaille( const char * NomDuFichier,int & nbnoeuds)
+{ //Lire le maillage  sur le fichier de nom NomDuFichier
+  
+  //Ouverture du fichier  a partir de son nom
+  ifstream f( NomDuFichier );
+  //char  buffer[BUFSIZ];
+  string buffer;
+  
+  nbnoeuds =0;
+  if( !f )
+    { cerr << "Erreur a l'ouverture du fichier " << NomDuFichier << endl;
+      return 1; }
+  
+  while ( getline( f,buffer,'\n' ) )
+    {
+      if((buffer[0]!='#')&&(buffer!="")){ nbnoeuds +=1;
+	// cout<<buffer<<endl;
+      }
+    }
+  
+  
+  return 0;
+}
+
+
+int  Lire( const char * NomDuFichier,int n ,R2 noeuds[] ){
+  
+  ifstream f( NomDuFichier );
+  
+  string buffer;
+  int i=0 ;
+  
+  
+  while(i<n)
+    {   
+      f >> buffer;			
+      if(buffer[0]=='#')
+	{  getline( f,buffer );}
+      else{
+	
+	
+	
+	// Lecture X Y Z de chacun des noeuds
+	
+	from_string( buffer,noeuds[i++].x ); 
+	f>>noeuds[i-1].y>>buffer;
+	
+      }
+      
+      
+      
+    }
+  
+  
+  
+  return 0;
+}
+
+
+
+
+
+R Min (const R a,const R b){return a < b ? a : b;}
+R Max (const R a,const R b){return a > b ? a : b;}
+
+
+
+
+
+
+
+//  metrixkuate(Th,np,o,err,[m11,m12,m22]);
+class MetricKuate :  public E_F0mps 
+{
+public:
+  typedef bool  Result;
+  Expression expTh;
+  Expression expnp;
+  Expression exphmin;
+  Expression exphmax;
+  Expression experr;
+  Expression m11,m12,m22;
+  Expression px,py;
+  
+  MetricKuate(const basicAC_F0 & args)
+  {
+
+    args.SetNameParam();
+    expTh= to<pmesh>(args[0]);  // a the expression to get the mesh
+    expnp= to<long>(args[1]);  // a the expression to get the mesh
+    exphmin= to<double>(args[2]);  // a the expression to get the mesh
+    exphmax= to<double>(args[3]);  // a the expression to get the mesh
+    experr= to<double>(args[4]);  // a the expression to get the mesh
+    //  a array expression [ a, b]
+    const E_Array * ma= dynamic_cast<const E_Array*>((Expression) args[5]);
+    const E_Array * mp= dynamic_cast<const E_Array*>((Expression) args[6]);
+    if (ma->size() != 3) CompileError("syntax: MetricKuate(Th,np,o,err,[m11,m12,m22],[xx,yy])");
+    if (mp->size() != 2) CompileError("syntax: MetricKuate(Th,np,o,err,[m11,m12,m22],[xx,yy])");
+    int err =0;
+    m11= CastTo<KN<double> * >((*ma)[0]); // fist exp of the array (must be a  double)
+    m12= CastTo<KN<double> * >((*ma)[1]); // second exp of the array (must be a  double)
+    m22= CastTo<KN<double> * >((*ma)[2]); // second exp of the array (must be a  double)
+    px= CastTo<double * >((*mp)[0]); // fist exp of the array (must be a  double)
+    py= CastTo<double * >((*mp)[1]); // second exp of the array (must be a  double)
+  }
+
+  ~MetricKuate()
+  {
+  }
+
+  static ArrayOfaType  typeargs()
+  { return  ArrayOfaType(
+			 atype<pmesh>(),
+			 atype<long>(),
+			 atype<double>(),
+			 atype<double>(),
+			 atype<double>(),
+			 atype<E_Array>(),
+			 atype<E_Array>());
+  }
+  static  E_F0 * f(const basicAC_F0 & args){ return new MetricKuate(args);}
+  AnyType operator()(Stack s) const ;
+
+};
+
+// the evaluation routine
+AnyType MetricKuate::operator()(Stack stack) const
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh = GetAny<pmesh>((*expTh)(stack));
+  long np=  GetAny<long>((*expnp)(stack));
+  double hmin=  GetAny<double>((*exphmin)(stack));
+  double hmax=  GetAny<double>((*exphmax)(stack));
+  KN<double> *pm11,*pm12,*pm22;
+  double *pxx,*pyy;
+  pm11=  GetAny<KN<double>*>((*m11)(stack));
+  pm22=  GetAny<KN<double>*>((*m22)(stack));
+  pm12=  GetAny<KN<double>*>((*m12)(stack));
+  pxx =  GetAny<double*>((*px)(stack));
+  pyy =  GetAny<double*>((*py)(stack));
+  ffassert(pTh);
+  KN<R2> Pt(np);
+  Mesh & Th (*pTh);
+  cout << " MetricKuate " << np << " hmin = "<< hmin << " hmax = " << hmax  << " nv = " << Th.nv <<  endl;
+  R hmx2=1./(hmax*hmax);
+  R hmn2=1./(hmin*hmin);
+
+  ffassert(pm11->N()==Th.nv);
+  ffassert(pm12->N()==Th.nv);
+  ffassert(pm22->N()==Th.nv);
+  {
+    for (int iv=0;iv<Th.nv;iv++)
+      {
+	R2 P=Th(iv);
+	MeshPointStack(stack)->set(P.x,P.y);
+	double m11=1,m12=0,m22=1;
+	for(int i=0;i<np;i++)
+	  {
+	    double t=(M_PI*2.*i+0.5)/np;
+	    *pxx=cos(t);
+	    *pyy=sin(t);
+	    double ee =  fabs(GetAny<double>((*experr)(stack)));
+	    *pxx*=M_E;
+	    *pyy*=M_E;
+	    double eee =  fabs(GetAny<double>((*experr)(stack)));
+	    ee = max(ee,1e-30);
+	    eee = max(eee,1e-30);
+	    //  e^p  = eee/ee  
+	    double p = Min(Max(log(eee)-log(ee),0.1),10);
+	    // c^p ee = 1
+	    // c = (1/ee)^1/p
+	    double  c=pow(1./ee,1./p);
+	    c = min(max(c,hmin),hmax);
+	    Pt[i].x = *pxx*c/M_E;
+	    Pt[i].y = *pyy*c/M_E;	   
+	    if(iv==0) {
+	      cout << Pt[i] << "  ++++ " << i <<" " << t <<  " " << p << " c = " << R2(*pxx*c/M_E,*pyy*c/M_E) << "e=  " << ee << " " << eee << " " << c << endl;
+	      }
+	     
+	  }
+	double epsilon=1e-5;
+	metrique(np,Pt,m11,m22,m12,epsilon);
+	if(iv==0)  cout << "  ---- 11,12,22 : " << m11 << " "<< m12/2.  << " "<< m22 << endl; 
+	(*pm11)[iv]=m11;
+	(*pm12)[iv]=m12/2.;;
+	(*pm22)[iv]=m22;
+
+      }
+  }
+  *mp = mps;
+  return true;
+}
+
+
+/*  class Init { public:
+  Init();
+};
+$1 */
+static void Load_Init()
+{
+  cout << "\n  -- lood: init MetricKuate\n";
+  Global.Add("MetricKuate","(", new OneOperatorCode<MetricKuate >( ));
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/MetricKuate.edp b/examples++-load/MetricKuate.edp
new file mode 100644
index 0000000..be77f41
--- /dev/null
+++ b/examples++-load/MetricKuate.edp
@@ -0,0 +1,73 @@
+load "MetricKuate"
+mesh Th=square(5,5,[(x-0.5)*2,(y-0.5)*2]);
+real x0,y0;//  pour definir l'err  forme n lineare en x0,y0 
+real coef =1;
+fespace Vh(Th,P1);
+fespace Wh(Th,P2);
+fespace Ph(Th,P0);
+real c=10;
+
+func f = tanh(c * (sin( (5 * y)) -  (2 * x))) +  (y * x * x) +   pow( y,  3);;
+
+func fxxx = 0.16e2 * pow(0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1), 0.2e1) * pow(c, 0.3e1) - 0.32e2 * pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1) * (0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1)) * pow(c, 0.3e1);
+func fxxy = -0.40e2 * pow(0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1), 0.2e1) * pow(c, 0.3e1) * cos( (5 * y)) + 0.80e2 * pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1) * (0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1)) * pow(c, 0.3e1) * cos( (5 * y)) + 0.2e1;
+func fxyy = 0.100e3 * pow(0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1), 0.2e1) * pow(c, 0.3e1) * pow(cos( (5 * y)), 0.2e1) - 0.200e3 * pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1) * (0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1)) * pow(c, 0.3e1) * pow(cos( (5 * y)), 0.2e1) - 0.100e3 * tanh(c * (sin( (5 * y)) -  (2 * x))) * (0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1)) * c * c * sin( (5 * y));
+
+func fyyy = -0.250e3 * pow(0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1), 0.2e1) * pow(c, 0.3e1) * pow(cos( (5 * y)), 0.3e1) + 0.500e3 * pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1) * (0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1)) * pow(c, 0.3e1) * pow(cos( (5 * y)), 0.3e1) + 0.750e3 * tanh(c * (sin( (5 * y)) -  (2 * x))) * (0.1e1 - pow(tanh(c * (sin( (5 * y)) -  (2 * x))), 0.2e1)) * c * c * cos( (5 * y)) * sin( (5 * y)) - 0.125e3 * (0.1e1 - pow(tanh(c * (sin(  [...]
+
+/*
+real p=20;
+real p3=p-3, p321=p*(p-1)*(p-2);
+func f= x^p + y^p;
+func fxxx = p321*x;
+func fyyy = p321*y;
+func fxxy=0.;
+func fxyy=0.;
+*/
+func err=(fxxx*x0*x0*x0+3*fxxy*x0*x0*y0+3*fxyy*x0*y0*y0+fyyy*y0*y0*y0 )*coef;
+
+for(int i=1;i<4;i++)
+  {
+    Vh m11,m12,m22;    
+    coef = 1;
+    Wh f2=f;
+    MetricKuate(Th,200,0.0001,3,err,[m11[],m12[],m22[]],[x0,y0]);
+   // plot(m11,m22,wait=1,cmm="mmmm");
+    real cc=10;
+    Th=adaptmesh(Th,cc*m11,cc*m12,cc*m22,IsMetric=1,inquire=1,hmin=0.00001,nbvx=1000000);
+    cout << m11[].max << " " << m12[].max << " " << m22[].max << endl;
+    plot(Th,wait=1,ps="Th.eps");
+    plot(f2,wait=1);
+    Ph eh = (abs(f2-f));
+    Ph leh= log10(eh);
+    real[int] viso=[-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1];
+    plot(leh,fill=1,wait=1,viso=viso,value=1,ps="leh.eps");
+    cout << i << " .... " << eh[].min << " "<< eh[].max << " "<< eh[].sum/eh[].n << " " 
+         << int2d(Th)(eh)/Th.area << " " << Th.nt << " " << Th.nv << endl;
+  }
+   Th=square(5,5,[(x-0.5)*2,(y-0.5)*2]);
+
+// FFCS - regression tests
+real regtest;
+
+ real cerr= 0.005*(0.000961606/0.000582183)^0.66; 
+  for(int i=1;i<4;i++)
+  {
+    Vh m11,m12,m22;    
+    coef = 1;
+    Wh f2=f;
+   
+    real cc=10;
+    Th=adaptmesh(Th,f,err=cerr,inquire=1,hmin=0.00001,nbvx=1000000);
+    cout << m11[].max << " " << m12[].max << " " << m22[].max << endl;
+    plot(Th,wait=1,ps="Th2.eps");
+    plot(f2,wait=1);
+    Ph eh = (abs(f2-f));
+    Ph leh= log10(eh);
+    real[int] viso=[-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1];
+    plot(leh,fill=1,wait=1,viso=viso,value=1,ps="leh2.eps");
+    cout << i << " .... " << eh[].min << " "<< eh[].max << " "<< eh[].sum/eh[].n << " " 
+         << int2d(Th)(eh)/Th.area << " " << Th.nt << " " << Th.nv << endl;
+    regtest=eh[]'*eh[];//'
+  }
+
diff --git a/examples++-load/MetricPk.cpp b/examples++-load/MetricPk.cpp
new file mode 100644
index 0000000..e48719f
--- /dev/null
+++ b/examples++-load/MetricPk.cpp
@@ -0,0 +1,412 @@
+//  // ---------------------------------------------------------------------
+// $Id$
+// compile and link with ff-c++ metric_Pk.cpp 
+#include  <iostream>
+#include  <cfloat>
+#include  <cmath>
+using namespace std;
+#include "ff++.hpp" 
+using namespace Fem2D;
+
+
+#include <vector>
+//typedef std::vector<R>::iterator Rptr;
+//typedef std::vector<R>::const_iterator const_Rptr;
+//template <class A> inline A * to_ptr(std::vector<A>::iterator it){return &*it;}
+//template <class A> inline const A * to_ptr(std::vector<A>::const_iterator it){return &*it;}
+
+
+#include "TensorK.hpp"
+//the main class
+
+class MetricPk :  public E_F0mps 
+{
+public:
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param=10;
+    
+    Expression nargs[n_name_param];// stocker les argunments nommes
+
+  typedef KN_<double>  Result;
+  Expression expTh;
+  Expression expu;
+    
+  MetricPk(const basicAC_F0 & args)
+  {
+    args.SetNameParam(n_name_param,name_param,nargs);// les arguments nommes
+    expTh= to<pmesh>(args[0]);  // a the expression to get the mesh
+    expu= to<double>(args[1]);  // a the expression to get the mesh
+    /*
+    exphmin= to<double>(args[2]);  // a the expression to get the mesh
+    exphmax= to<double>(args[3]);  // a the expression to get the mesh
+    experr= to<double>(args[4]);  // a the expression to get the mesh
+    //  a array expression [ a, b]
+    const E_Array * ma= dynamic_cast<const E_Array*>((Expression) args[5]);
+    const E_Array * mp= dynamic_cast<const E_Array*>((Expression) args[6]);
+    if (ma->size() != 3) CompileError("syntax: MetricKuate(Th,np,o,err,[m11,m12,m22],[xx,yy])");
+    if (mp->size() != 2) CompileError("syntax: MetricKuate(Th,np,o,err,[m11,m12,m22],[xx,yy])");
+    int err =0;
+    m11= CastTo<KN<double> * >((*ma)[0]); // fist exp of the array (must be a  double)
+    m12= CastTo<KN<double> * >((*ma)[1]); // second exp of the array (must be a  double)
+    m22= CastTo<KN<double> * >((*ma)[2]); // second exp of the array (must be a  double)
+    px= CastTo<double * >((*mp)[0]); // fist exp of the array (must be a  double)
+    py= CastTo<double * >((*mp)[1]); // second exp of the array (must be a  double)
+     */
+  }
+    double arg(int i,Stack stack,double a) const { return nargs[i] ? GetAny<double>( (*nargs[i])(stack) ): a;}
+    long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    bool arg(int i,Stack stack,bool a) const{ return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+    KN<double> * arg(int i,Stack stack,KN<double> * a) const{ return nargs[i] ? GetAny<KN<double> *>( (*nargs[i])(stack) ): a;}
+ 
+    
+  ~MetricPk(){}
+
+  static ArrayOfaType  typeargs()
+  { return  ArrayOfaType(
+			 atype<pmesh>(),
+			 atype<double>());;
+  }
+  static  E_F0 * f(const basicAC_F0 & args){ return new MetricPk(args);}
+  AnyType operator()(Stack s) const ;// la vraie fonction qui fait faire le boulot 
+
+};
+
+basicAC_F0::name_and_type MetricPk::name_param[MetricPk::n_name_param] = {
+    { "kDeg",               &typeid(long)},  
+    { "rDeg",               &typeid(long)},  
+    { "iterJacobiDeriv",    &typeid(long)},
+    { "iterJacobiMetric",   &typeid(long)},
+    { "Derivatives",        &typeid(KN<double>*)},
+    { "rmax",               &typeid(double)},
+    { "mass",               &typeid(double)},
+    { "TriangulationType",  &typeid(long)},
+    { "MetricType",         &typeid(long)},
+    { "pExp",               &typeid(double)}
+  };
+
+AnyType MetricPk:: operator()(Stack stack) const 
+{
+    /************* r�cup�ration des arguments ****************/
+    
+    const long k_deg=  arg(0,stack,2L);   // Finite element of degree k_deg will be used for approximation.
+    const long m_deg=k_deg+1;             // Derivatives of degree m_deg = k_deg+1 will be estimated.
+    const long m_dim=m_deg+1;             // The description of these derivatives requires m_dim = m_deg+1 coefficients.
+    const long nDOFt=((k_deg+1)*(k_deg+2))/2;   // Number of Lagrange points on each triangle.
+    
+    const long r_deg=  arg(1,stack,1L);   // The function is approximated in the W^r,p Sobolev semi-norm.
+    const double p_exp = arg(9,stack,2.);
+    
+    const long iterJacobiDeriv  = arg(2,stack,3L); // The derivatives are slightly smoothed before use.
+    const long iterJacobiMetric = arg(3,stack,3L); // The riemannian metric is slightly smoothed before being returned.
+    
+    const double rmax=arg(5,stack,1.);      //Not used yet. (Lower bound for the metric)
+    const double mass=arg(6,stack,1000.);   // Mass of the metric returned, i.e. mass = int sqrt(det M). 
+    // In practice, bamg produces a mesh with nt=2*mass elements.
+    
+    const TensorK::triangulation_type ttype = TensorK::triangulation_type(arg(7,stack,long(0))); // Type of triangulation on which approx will be done.
+    const TensorK::which_matrix wmat = TensorK::which_matrix(arg(8,stack,long(1))); // Type of metric. Do not change.
+
+    
+    TensorK tk(m_deg, r_deg, ttype, wmat, p_exp);
+    
+    cout << "Approximation of " << r_deg << "th derivatives using finite elements of degree " << k_deg << ", in the L^" << p_exp << " norm.\n"; 
+    cout << "Triangulation type : " << ttype << "; Graded=0, Quasi_Acute(refined)=1, Quasi_Acute_Unrefined=2, Quasi_Acute_Proved(refined)=3" << endl;
+    //cout << "Metric type : " << wmat << "M0_alone=0, M1_alone=1, M0_M1_weighted_sum=2" << endl;
+
+    Mesh * pTh = GetAny<pmesh>((*expTh)(stack));
+    ffassert(pTh);
+    const Mesh & Th= *pTh; 
+
+    /************ initialisations ***************/
+    
+    //the metric
+    const int nv = Th.nv;
+    KN<double> * pMetric=new KN<double>(nv*3);
+    KN<double> & metric= * pMetric;
+    metric=0.; 
+    
+    if(!tk.is_valid){
+        cout << "Error : Unsupported parameters for MetricPk!\n";
+        Add2StackOfPtr2Free(stack,pMetric);
+        return SetAny<KN<double> > (metric); //identically zero metric is returned in case of error
+    }
+    
+    //Lagrange points.
+    const R2 QLagrange[5][15]={
+        {R2(1./3.,1./3.)},  //k_deg=0, barycenter.
+        {R2(0,0),R2(1,0),R2(0,1)},
+        {R2(0,0),R2(1,0),R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0)},
+        {R2(0,0),R2(1,0),R2(0,1),R2(2./3.,1./3.),R2(1./3.,2./3.),R2(0,2./3.),R2(0,1./3.),R2(1./3.,0),R2(2./3.,0),R2(1/3.,1/3.)},
+        {R2(0,0),R2(1,0),R2(0,1),R2(3./4.,1./4.),R2(1./2.,1./2.),R2(1./4.,3./4.),R2(0.,3./4.),R2(0.,1./2.),R2(0.,1./4.),R2(1./4.,0),R2(1./2.,0),R2(3./4.,0),
+            R2(1./4.,1./2.),R2(1./2.,1./4.),R2(1./4.,1./4.)}
+    };
+    
+    std::vector<R> aires; aires.resize(nv);         //area of the "cell" surrounding a point
+    std::vector<R> Deriv; Deriv.resize(m_dim*nv);   //estimate of the derivatives at a point
+    std::vector<R> DOFt; DOFt.resize(nDOFt);        //degrees of freedom on a triangle
+    
+    //le bord
+    //Th.ElementAdj(k,ie); renvoie k', �crase ie par ie';
+    // is frontiere k' <0 ou k'==k
+    //Seg
+    //BoundaryElement (+r�cent)
+    //Th.nbe ou Th.neb
+    //Th.be(i)  Th.be(i)[0] ou Th.be(i)[1]
+    std::vector<int> nextv; nextv.resize(nv); fill(nextv.begin(), nextv.end(), -1);
+    for(int i=0; i<Th.nt; ++i) for(int ie=0; ie<3; ++ie) {
+        int iee=ie;
+        const int j = Th.ElementAdj(i,iee);
+        if(j==i || j <0)    nextv[Th(i,(ie+1)%3)]=Th(i,(ie+2)%3); //nextv[Th(i,(ie+1)%3)]=Th(i,(ie+2)%3);
+    }
+    
+//    cout << "next point on boundary\n"; for(int i=0; i<nv; ++i) cout << " " << nextv[i]; cout << "\n";
+    
+//  for(int i=0; i<Th.neb; ++i) nextv[Th.be(i)[0]]=Th.be(i)[1]; //ne convient pas : les num�ros sont oubli�s, seuls les points sont conserv�s.
+    
+    /********* estimation des d�riv�es ***********/
+    for(int i=0; i<Th.nt; ++i){
+        const Triangle &K=Th[i];           
+        const R2 sommets[3]={K(R2(0,0)),K(R2(1,0)),K(R2(0,1))};
+        const R aire=det(sommets[0],sommets[1],sommets[2])/2;
+        const R2 invHauteur[3]={perp(sommets[1]-sommets[2])/(2*aire),perp(sommets[2]-sommets[0])/(2*aire),perp(sommets[0]-sommets[1])/(2*aire)};
+        
+        for(int dof=0; dof<nDOFt; ++dof){   //Degrees of freedom on the triangle
+            const R2 Point=K(QLagrange[k_deg][dof]);
+            MeshPointStack(stack)->set(Point.x,Point.y);
+            DOFt[dof]= GetAny<double>((*expu)(stack));
+        }
+        
+        double f[m_deg]; //contains the derivatives of order
+        switch(m_deg){
+            case 2:{    //accolades n�cessaires pour d�clarer des variables dans un case
+                double f[2]; tk.getDerivatives(DOFt,invHauteur,f); //f={fx,fy}
+                
+                for(int j=0; j<3; ++j){
+                    const int s= Th(i,j); //le sommet j du triangle i
+                    Deriv[m_dim*s+0]+= aire* f[0]*invHauteur[j].x; //contribution � l'estimation des d�riv�es secondes.
+                    Deriv[m_dim*s+1]+= aire*(f[0]*invHauteur[j].y/2.+f[1]*invHauteur[j].x/2.);
+                    Deriv[m_dim*s+2]+= aire* f[1]*invHauteur[j].y;
+                    aires[s]+=aire;
+                }
+                break;
+            }
+            case 3:{
+                double f[3]; tk.getDerivatives(DOFt,invHauteur,f); //f={fxx,fxy,fyy}
+                
+                for(int j=0; j<3; ++j){
+                    const int s= Th(i,j);
+                    Deriv[m_dim*s+0]+= aire*f[0]*invHauteur[j].x; //contribution � l'estimation des d�riv�es troisi�mes.
+                    Deriv[m_dim*s+1]+= aire*(f[0]*invHauteur[j].y/3.+f[1]*invHauteur[j].x*2./3.);
+                    Deriv[m_dim*s+2]+= aire*(f[2]*invHauteur[j].x/3.+f[1]*invHauteur[j].y*2./3.);
+                    Deriv[m_dim*s+3]+= aire*f[2]*invHauteur[j].y;
+                    aires[s]+=aire;
+                }
+                break;
+            }
+            case 4:{
+                double f[4]; tk.getDerivatives(DOFt,invHauteur,f); //f={fxxx,fxxy,fxyy,fyyy}
+                
+                for(int j=0; j<3; ++j){
+                    const int s= Th(i,j);
+                    Deriv[m_dim*s+0]+= f[0]*invHauteur[j].x*aire; //contribution � l'estimation des d�riv�es quatri�mes.
+                    Deriv[m_dim*s+1]+= (f[0]*invHauteur[j].y/4.   +f[1]*invHauteur[j].x*3./4.)*aire;
+                    Deriv[m_dim*s+2]+= (f[1]*invHauteur[j].y/2.   +f[2]*invHauteur[j].x/2.)*aire;
+                    Deriv[m_dim*s+3]+= (f[2]*invHauteur[j].y*3./4.+f[3]*invHauteur[j].x/4.)*aire;
+                    Deriv[m_dim*s+4]+= f[3]*invHauteur[j].y*aire;
+                    aires[s]+=aire;
+                }
+                break;
+            }
+            case 5:{
+                double f[5]; tk.getDerivatives(DOFt,invHauteur,f); //f={fxxxx,fxxxy,fxxyy,fxyyy,fyyyy}
+                
+                for(int j=0; j<3; ++j){
+                    const int s= Th(i,j);
+                    Deriv[m_dim*s+0]+= f[0]*invHauteur[j].x*aire; //contribution � l'estimation des d�riv�es quatri�mes.
+                    Deriv[m_dim*s+1]+= (f[0]*invHauteur[j].y/5.+f[1]*invHauteur[j].x*4./5.)*aire;
+                    Deriv[m_dim*s+2]+= (f[1]*invHauteur[j].y*2./5.+f[2]*invHauteur[j].x*3./5.)*aire;
+                    Deriv[m_dim*s+3]+= (f[2]*invHauteur[j].y*3./5.+f[3]*invHauteur[j].x*2./5.)*aire;
+                    Deriv[m_dim*s+4]+= (f[3]*invHauteur[j].y*4./5.+f[4]*invHauteur[j].x/5.)*aire;
+                    Deriv[m_dim*s+5]+= f[4]*invHauteur[j].y*aire;
+                    aires[s]+=aire;
+                }
+            } //case m_deg==5
+        } //switch m_deg
+    } //for i triangle
+    
+    for(int i=0; i<nv; ++i)    for(int j=0; j<m_dim; ++j)  Deriv[m_dim*i+j]*=3/aires[i]; 
+    
+    //Estimating derivatives on the boundary by averaging neighboring estimates in the interior.
+    //First the graph distance to the interior is estimated, using Dijkstra's algorithm.
+    {
+        multimap<int,int> connectivity; // this is probably already computed by FreeFem. Where ?
+        vector<pair<int,int> > dist; //(distance,number)
+        set<int> computed;
+        
+        for(int i=0; i<Th.nt; ++i){ //Obtaining the connectivity
+            const int u=Th(i,0), v=Th(i,1), w=Th(i,2);
+            if(nextv[u]==-1 && nextv[v]==-1 && nextv[w]==-1) continue; // attention is restricted to the boundary.
+            connectivity.insert(pair<int,int>(u,v)); connectivity.insert(pair<int,int>(v,u));
+            connectivity.insert(pair<int,int>(v,w)); connectivity.insert(pair<int,int>(w,v));
+            connectivity.insert(pair<int,int>(w,u)); connectivity.insert(pair<int,int>(u,w));
+            if(nextv[u]==-1 && computed.insert(u).second==true) dist.push_back(pair<int,int>(u,0)); 
+            if(nextv[v]==-1 && computed.insert(v).second==true) dist.push_back(pair<int,int>(v,0)); 
+            if(nextv[w]==-1 && computed.insert(w).second==true) dist.push_back(pair<int,int>(w,0)); 
+        }
+        
+        for(int i=0; i<dist.size(); ++i){ //Dijkstra's algorithm.
+            const int u=dist[i].first; const int du=dist[i].second;
+            computed.insert(u);
+            const pair<multimap<int,int>::iterator, multimap<int,int>::iterator> ret = connectivity.equal_range(u);
+            for(multimap<int,int>::iterator it=ret.first; it!=ret.second; ++it){
+                const int v=it->second;
+                if(computed.insert(v).second) dist.push_back(pair<int,int>(v,du+1));
+            }
+        }
+        
+        map<int,int> dist_sorted; dist_sorted.insert(dist.begin(), dist.end());
+        
+        for(int i=0; i<dist.size(); ++i){
+            const int u=dist[i].first; const int du=dist[i].second;
+            if(du==0) continue;
+            const pair<multimap<int,int>::iterator, multimap<int,int>::iterator> neighbors = connectivity.equal_range(u);
+            int closer_neighbors=0;
+            for(multimap<int,int>::iterator it=neighbors.first; it!=neighbors.second; ++it){
+                const int v=it->second;
+                const int dv=dist_sorted.find(v)->second;
+                if(du!=dv+1) continue;
+                closer_neighbors++;
+                for(int k=0; k<m_dim; ++k) Deriv[m_dim*u+k]+=Deriv[m_dim*v+k];
+            }
+            for(int k=0; k<m_dim; ++k) Deriv[m_dim*u+k]/=closer_neighbors;
+        }
+    }
+    
+    // Averaging derivatives
+    std::vector<int> cardNeighbors; cardNeighbors.resize(nv); 
+    for(int i=0; i<Th.nt; ++i) for(int j=0; j<3; ++j) cardNeighbors[Th(i,j)]+=3;
+    
+    {
+        std::vector<R> DerivNew; DerivNew.resize(m_dim*nv);
+        
+        for(int r=0; r<iterJacobiDeriv; ++r){
+            
+            fill(DerivNew.begin(), DerivNew.end(), 0);
+            
+            for(int i=0; i<Th.nt; ++i){
+                const int u=Th(i,0); const int v=Th(i,1); const int w=Th(i,2);
+                for(int k=0; k<m_dim; ++k){
+                    const R sum = Deriv[m_dim*u+k]+Deriv[m_dim*v+k]+Deriv[m_dim*w+k];
+                    DerivNew[m_dim*u+k]+=sum; DerivNew[m_dim*v+k]+=sum; DerivNew[m_dim*w+k]+=sum;
+                }//for k
+            }//for i triangles
+            
+            for(int i=0; i<nv; ++i) for(int k=0; k<m_dim; ++k) Deriv[m_dim*i+k]= DerivNew[m_dim*i+k]/cardNeighbors[i]; 
+        }
+    }
+
+    //Exporting the derivatives, if required
+    KN<double> * pDerivRes=  arg(4,stack,(KN<double> *)0);
+    if(pDerivRes){
+        ffassert( pDerivRes->N()== m_dim*nv); 
+        KN<double> &DerivRes = *pDerivRes;
+        for(int i=0; i<m_dim*nv; ++i)
+            DerivRes[i]=Deriv[i]; 
+    }
+    
+    /**************** Computing the "L^infinity homogeneous" metric ************/
+    
+    std::vector<R> ih_metric; ih_metric.resize(3*nv);
+    for(int i=0; i<nv; ++i)  tk.getM(&Deriv[m_dim*i],&ih_metric[3*i]);
+    
+    //Jacobi iterations
+    //the power -1/2 of the metrics, which is homogenous to a distance, is averaged.
+//    cout << "!!!!!!!!!! HELLO !!!!!!!!!!!\n";
+//    for(int i=0; i<nv; ++i) if(ih_metric[3*i]==0 && ih_metric[3*i+1]==0 && ih_metric[3*i+2]==0) {
+//        cout << Th(i).x << "," << Th(i).y << endl;
+//        for(int j=0; j<m_dim; ++j) cout << Deriv[m_dim*i+j] << ",";
+//        cout << "jacobi deriv : " << iterJacobiDeriv << endl;
+//    }
+    
+    // Averaging the metric
+    {
+        for(int i=0; i<nv; ++i) TensorK::PowSym(&ih_metric[3*i],-0.5); 
+        
+        std::vector<double> ih_metricNew; ih_metricNew.resize(3*nv);
+        for(int r=0; r<iterJacobiMetric; ++r){
+            
+            fill(ih_metricNew.begin(),ih_metricNew.end(),0);
+            
+            for(int i=0; i<Th.nt; ++i){
+                const int u=Th(i,0); const int v=Th(i,1); const int w=Th(i,2);
+                for(int k=0; k<3; ++k){
+                    const R sum = ih_metric[3*u+k]+ih_metric[3*v+k]+ih_metric[3*w+k]; 
+                    ih_metricNew[3*u+k]+=sum; ih_metricNew[3*v+k]+=sum; ih_metricNew[3*w+k]+=sum;
+                }//for k
+            }//for i triangles
+            for(int i=0; i<nv; ++i) for(int k=0; k<3; ++k) ih_metric[3*i+k]=ih_metricNew[3*i+k]/cardNeighbors[i];
+        }
+        
+        for(int i=0; i<nv; ++i) TensorK::PowSym(&ih_metric[3*i],-2);
+    }
+
+    /**************** Multiplicator to obtain prescribed mass and to balance errors ****************/ 
+    // Note : future versions could include hmin and hmax parameters.
+    {
+        const long d_dim = 2; // Space Dimension : 2
+        
+        //M : Metric for the L^p norm, M_0 metric for the L^infty norm
+        const R alpha = -1./((m_deg-r_deg)*p_exp+d_dim); // M = (det M_0)^alpha M_0
+        const R beta = (m_deg-r_deg)*p_exp/( ((m_deg-r_deg)*p_exp+d_dim)*2.);  // integrate sqrt(det M) = integrate (det M_0)^beta; beta = (alpha*d_dim+1)/2.
+        //const R tau = 2./(m_deg-r_deg+1);
+        
+        
+        for(int i=0; i<nv; ++i) aires[i]/=3;
+        R totalArea = 0; for(int i=0; i<nv; ++i) totalArea += aires[i];
+        //cout << "totalArea : " << totalArea << "\n";
+        
+        R totalMass = 0; for(int i=0; i<nv; ++i) totalMass += aires[i]*pow(TensorK::det(&ih_metric[3*i]), beta); //Eigen[i][0]*Eigen[i][1]
+        const R gamma = pow(mass/totalMass,1./(beta*d_dim)); // gamma satisfies integrate (det (gamma M_0) )^beta = mass
+        for(int i=0; i<nv; ++i) {
+            const R lambda = gamma*pow(square(gamma)*TensorK::det(&ih_metric[3*i]), alpha); //Eigen[i][0]*Eigen[i][1]
+            for(int j=0; j<3; ++j) metric[3*i+j]=lambda*ih_metric[3*i+j]; 
+        }
+        
+        R obtainedMass = 0; for(int i=0; i<nv; ++i) obtainedMass += aires[i]*sqrt(TensorK::det(metric+3*i));
+        cout << "Desired Mass : " << mass << "; obtained mass " << obtainedMass << endl;
+    }
+    
+    Add2StackOfPtr2Free(stack,pMetric);
+    return SetAny<KN<double> > (metric);
+    
+    /* //example by F.Hecht
+    for( int k=0;k<Th.nt; ++k)
+    {
+        const Triangle &K=Th[k];
+        for (int i=0;i<6;++i)
+        {
+            R2 Pi=K(Q2[i]);
+            MeshPointStack(stack)->set(Pi.x,Pi.y);
+            R uP= GetAny<double>((*expu)(stack));
+            cout << Pi << " " << uP << endl;
+            if(i<3) 
+            { int s= Th(k,i); // le sommet i du triangle k.
+                metric[3*s+0] =uP;
+                metric[3*s+1] =uP+1; 
+                metric[3*s+2] =uP+3;                    
+            }
+                
+        }
+    }
+     */   
+}
+/*  class Init { public:
+  Init();
+};
+Init init;*/
+static void Load_Init()
+{
+  cout << "\n  -- lood: init MetricPk\n";
+  Global.Add("MetricPk","(", new OneOperatorCode<MetricPk >( ));
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/Morley.cpp b/examples++-load/Morley.cpp
new file mode 100644
index 0000000..b8c79de
--- /dev/null
+++ b/examples++-load/Morley.cpp
@@ -0,0 +1,297 @@
+//  MORLEY FINITE ELEMENT 
+// F. Hecht  december 2005
+// ----------------------------
+//  the Polynomial space is $P�2$, an the degree of freedom are
+// the 3 values a the 3 vertices and the three 
+// normal derivative at the middle at the tree the edges
+// remark; 
+//   to compute the interpolante, we need
+//   the value , plus the value of the normal derivative
+//   so I use the following hack, I say the is a tree dim vectorial 
+//   finite element with give  the value, x derivative ,and the y derivative
+//  Ref: chapter VII section 50  fig 50.2  of 
+//   Ciarlet,   HandBook of Numerical Analysis, Volume II Finite elemet methodes (parts 1),
+//             NORTH-HOLLAND 
+// -----------------------  related files: 
+//  to check  and validate  : testFEMorlay.edp 
+//  to get a real example   :  bilapMorley.edp
+// ------------------------------------------------------------
+
+#include "ff++.hpp"
+#include "AddNewFE.h"
+
+// #include "problem.hpp"
+namespace  Fem2D {
+  
+  // ------ P2 Morley  
+  class TypeOfFE_P2Morley : public  TypeOfFE { public:  
+    static int Data[];
+    // double Pi_h_coef[];
+    
+    TypeOfFE_P2Morley(): TypeOfFE(3+3+0,
+				  3,// hack   u, u_x, u_y for interpolation
+				      Data,
+				      2,
+				      1,
+				      3+6, // nb coef to build interpolation
+				      6, // np point to build interpolation
+				      0)
+    {  
+      const double gauss1=(1.-sqrt(1./3.))/2;
+      const double gauss2=1.-gauss1;
+
+      const R2 Pt[] = { R2(0,0),R2(1,0),R2(0,1),R2(0.5,0.5), R2(0,0.5),R2(0.5,0)}; 
+      // for the 3 vertices 6 coef 
+      int kk=0;
+      for (int p=0;p<3;p++)
+	{ 
+	  P_Pi_h[p]=Pt[p];
+	  pij_alpha[kk]= IPJ(kk,p,0);
+	  kk++;
+	}
+      // for 
+      int p=3;
+      for (int e=0;e<3;++e)
+	{ // point d'integration sur l'arete e 
+	  P_Pi_h[p]= Pt[p];
+	  //	  cout <<"\n" <<  p << " --  " << P_Pi_h[p] << " ::  " << A << " " << B << endl;
+	  pij_alpha[kk++]= IPJ(3+e,p,1); // coef = 0.5* l_e *ne_x * sge	  
+	  pij_alpha[kk++]= IPJ(3+e,p,2); // coef = 0.5* l_e *ne_y * sge	  	  
+	  p++;
+	}
+      assert(P_Pi_h.N()==p);
+      assert(pij_alpha.N()==kk);
+
+     }
+    void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+    void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const;
+  } ;
+  //                     on what     nu df on node node of df    
+ int TypeOfFE_P2Morley::Data[]={
+   0,1,2,  3,4,5,
+   0,0,0,  0,0,0,
+   0,1,2,  3,4,5,
+   0,0,0,  0,0,0,
+   0,1,2,  3,4,5,
+   0,0,0,
+   0,0,0, 
+   6,6,6 
+};
+
+void TypeOfFE_P2Morley::Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+  {
+    const Triangle & T(K.T);
+    int k=0;
+    // coef pour les 3 sommets  fois le 2 composantes 
+    for (int i=0;i<3;i++)
+      v[k++]=1; 
+    //   integration sur les aretes 
+    for (int i=0;i<3;i++)
+      {
+	
+        R2 N(T.Edge(i).perp());
+	N  *= T.EdgeOrientation(i);
+        v[k++]= N.x; 
+        v[k++]= N.y;
+      }
+  }
+  
+  void TypeOfFE_P2Morley::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+  {
+    typedef double R;
+    R2 A(K[0]), B(K[1]),C(K[2]);
+    R l0=1-P.x-P.y,l1=P.x,l2=P.y;
+
+
+    R2 Dl[3]=  {K.H(0), K.H(1), K.H(2) };
+
+
+    R2 E[3]={ K.Edge(0),K.Edge(1),K.Edge(2)};
+    //    double l2E[3]={  (E[0],E[0]),  (E[1],E[1]),  (E[2],E[2]) };  
+    // double lE[3]={  sqrt(l2E[0]), sqrt(l2E[1]), sqrt(l2E[2]) };
+    double sgE[3]={ K.EdgeOrientation(0), K.EdgeOrientation(1), K.EdgeOrientation(2)}; 
+    // $ w_{3+i} = ccc[i] * ( li-2*li*li) $  
+    //   donc  $  D(w_i) =  ccc[i]  (1-2*li) Dl[i] $ 
+    //  we must have $$ int_{e_i} dn(w_{3+j) ) =  \delta_{ij} $ 
+    // $int_e_i dn(w_{3+i} )  = ccc[i] (Dl[i],Ne[i]) = 1 $
+    //  $ ccc[i] = 1/  (Dl[i],Ne[i]) $ 
+    R2 Ne[3]= { 
+      E[0].perp() *sgE[0], 
+      E[1].perp() *sgE[1],
+      E[2].perp() *sgE[2] 
+    };
+    
+    double ccc[] = { 1./(Dl[0],Ne[0]), 1./(Dl[1],Ne[1]), 1./(Dl[2],Ne[2]) };
+
+
+    R l3=(l0-l0*l0)*ccc[0];
+    R l4=(l1-l1*l1)*ccc[1];
+    R l5=(l2-l2*l2)*ccc[2];
+
+    R dl3=(1-2*l0)*ccc[0];
+    R dl4=(1-2*l1)*ccc[1];
+    R dl5=(1-2*l2)*ccc[2];
+    
+  //  cout << l0 << " " << l1 << " " << l2 << " " << l3 << " " << l4 << " " << l5 ;
+    KN<bool> wd(KN_<const bool>(whatd,last_operatortype));
+    KN<int>  wd_op(last_operatortype),wd_j(last_operatortype);
+    wd_j=0;
+    wd_op=-1;
+    if (whatd[op_id]) {wd[op_dx ]=wd[op_dy ]=true; wd_op[op_dx ]=wd_op[op_dy ]=op_id; wd_j[op_dx ]=1;wd_j[op_dy ]=2;}
+    if (whatd[op_dx]) {wd[op_dxx]=wd[op_dxy]=true; wd_op[op_dxx]=wd_op[op_dxy]=op_dx; wd_j[op_dxx]=1;wd_j[op_dxy]=2;}
+    if (whatd[op_dy]) {wd[op_dyy]=wd[op_dxy]=true; wd_op[op_dxy]=wd_op[op_dyy]=op_dy; wd_j[op_dxy]=1;wd_j[op_dyy]=2;}
+    // on previligie les originaux 
+    for (int i=0; i< last_operatortype ; ++i)
+      if (whatd[i]) 
+	{ wd_op[i]=i;  wd_j[i]=0;}
+    val=0; 
+    
+    throwassert( val.N()>=6);
+    throwassert(val.M()==3);
+    
+    
+    val=0; 
+  
+
+  if (wd[op_id])
+    {
+     
+      RN_ f(val('.',0,op_id)); 
+      
+      f[0] = l0;
+      f[1] = l1;
+      f[2] = l2;
+      //  remark  \int_O \Delta u = \int_G \dn(u) 
+      //  \Delta l1^2 = Div ( 2 l1 \nalba l1) = 2 (\nalba l1,\nalba l1)
+      f[3] = l3 ; // (1-2 lO) \nabla l0
+      f[4] = l4 ;
+      f[5] = l5 ;
+      
+    }
+  
+  if (wd[op_dx])
+    {
+      RN_ fx(val('.',wd_j[op_dx],wd_op[op_dx])); 
+      
+      fx[0] = Dl[0].x;
+      fx[1] = Dl[1].x;
+      fx[2] = Dl[2].x;
+      
+      fx[3] = dl3*Dl[0].x; 
+      fx[4] = dl4*Dl[1].x; 
+      fx[5] = dl5*Dl[2].x;
+      
+    }
+      
+  if (wd[op_dy])
+    {  
+      //      RN_ fy(val('.',0,op_dy)); 
+      RN_ fy(val('.',wd_j[op_dy],wd_op[op_dy]));       
+      fy[0] = Dl[0].y;
+      fy[1] = Dl[1].y;
+      fy[2] = Dl[2].y;
+      
+      fy[3] = dl3*Dl[0].y; 
+      fy[4] = dl4*Dl[1].y; 
+      fy[5] = dl5*Dl[2].y;
+      
+    }
+  
+  
+  if (wd[op_dxx])
+    {  
+      //      RN_ fxx(val('.',0,op_dxx)); 
+      RN_ fxx(val('.',wd_j[op_dxx],wd_op[op_dxx]));             
+      fxx[3] = Dl[0].x*Dl[0].x*ccc[0]*-2.;
+      fxx[4] = Dl[1].x*Dl[1].x*ccc[1]*-2.;
+      fxx[5] = Dl[2].x*Dl[2].x*ccc[2]*-2.;
+      
+    }
+  
+  if (wd[op_dyy])
+    {  
+      
+      //RN_ fyy(val('.',0,op_dyy)); 
+      RN_ fyy(val('.',wd_j[op_dyy],wd_op[op_dyy]));       
+      
+      fyy[3] = Dl[0].y*Dl[0].y*ccc[0]*-2.;
+      fyy[4] = Dl[1].y*Dl[1].y*ccc[1]*-2.;
+      fyy[5] = Dl[2].y*Dl[2].y*ccc[2]*-2.;
+      
+      
+    }
+  
+  if (wd[op_dxy])
+    {  
+      assert(val.K()>wd_op[op_dxy]);
+      
+      // RN_ fxy(val('.',0,op_dxy));
+      RN_ fxy(val('.',wd_j[op_dxy],wd_op[op_dxy]));             
+      fxy[3] = Dl[0].x*Dl[0].y*ccc[0]*-2.;
+      fxy[4] = Dl[1].x*Dl[1].y*ccc[1]*-2.;
+      fxy[5] = Dl[2].x*Dl[2].y*ccc[2]*-2.;
+      
+    }
+  
+  
+  {
+    int vop[last_operatortype], nop=0;
+    for (int j=0;j<last_operatortype;j++)
+      if (wd[j])
+	vop[nop++] = j;
+    
+    //  mise a zero des flux of int_e_j dn(w_i) pour i,j = 0,..,2 
+    
+    for(int i=0;i<3;++i)
+      for(int e=0;e<3;++e)
+	{
+	  // 0= int_e  w_i = dn(li) - a = a = (Dn[i],N) 
+	  double a= (Dl[i],Ne[e]);
+	  // but   = 0 
+	  for(int opp=0;opp<nop;++opp)
+	    {
+	      int op=vop[opp];
+	      int k = wd_op[op];
+	      int j = wd_j[op];
+	      val(i,j,k) -= a*val(e+3,j,k);
+	    }
+	  
+	};
+    //  copie of the derivative for the hack. 
+   // cout << " copie " << endl;
+    if (whatd[op_id])
+      { 
+	if(wd_op[op_dx]!= op_id)
+	  val('.',1,op_id)=val('.',wd_j[op_dx],wd_op[op_dx]);
+	if(wd_op[op_dy]!= op_id)
+	  val('.',2,op_id)=val('.',wd_j[op_dy],wd_op[op_dy]);
+      }
+
+    if (whatd[op_dx])
+      { 
+	if(wd_op[op_dxx]!= op_dx)
+	  val('.',1,op_dx)=val('.',wd_j[op_dxx],wd_op[op_dxx]);
+	if(wd_op[op_dxy]!= op_dx)
+	  val('.',2,op_dx)=val('.',wd_j[op_dxy],wd_op[op_dxy]);
+      }
+    if (whatd[op_dy])
+      { 
+	if(wd_op[op_dxy]!= op_dy)
+	  val('.',1,op_dy)=val('.',wd_j[op_dxy],wd_op[op_dxy]);
+	if(wd_op[op_dyy]!= op_dy)
+	  val('.',2,op_dy)=val('.',wd_j[op_dyy],wd_op[op_dyy]);
+      }
+   
+
+  }
+  
+  }
+
+
+// a static variable to add the finite element to freefem++
+static TypeOfFE_P2Morley P2LagrangeP2Morley;
+static AddNewFE  P2Morley("P2Morley",&P2LagrangeP2Morley); 
+} // FEM2d namespace 
+  // --- fin -- 
+
+  
diff --git a/examples++-load/NSP2BRP0.edp b/examples++-load/NSP2BRP0.edp
new file mode 100644
index 0000000..0ba08c7
--- /dev/null
+++ b/examples++-load/NSP2BRP0.edp
@@ -0,0 +1,83 @@
+load "BernadiRaugel"
+// remark: the sign of p is correct 
+real s0=clock();
+mesh Th=square(10,10);
+fespace Vh2(Th,P2BR);
+fespace Vh(Th,P0);
+Vh2 [u1,u2],[up1,up2];
+Vh2 [v1,v2]; 
+
+
+real reylnods=400;
+//cout << " Enter the reynolds number :"; cin >> reylnods;
+assert(reylnods>1 && reylnods < 100000); 
+[up1,up2]=[0.,0.];
+
+func g=(x)*(1-x)*4; 
+Vh p=0,q;
+real alpha=0;
+real  nu=1;
+int i=0,iter=0;
+real dt=0;
+solve NS ([u1,u2,p],[v1,v2,q],init=i) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +        dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            - p*dx(v1) - p*dy(v2)
+            - dx(u1)*q - dy(u2)*q
+           )
+  + int2d(Th) ( -alpha*convect([up1,up2],-dt,up1)*v1 -alpha*convect([up1,up2],-dt,up2)*v2 )
+  + on(3,u1=g,u2=0) 
+  + on(1,2,4,u1=0,u2=0) ;
+plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="StokesP2P1.eps",value=1,wait=1);
+{
+  real[int] xx(21),yy(21),pp(21);
+  for (int i=0;i<21;i++)
+   {
+     yy[i]=i/20.;
+     xx[i]=u1(0.5,i/20.);
+     pp[i]=p(i/20.,0.999);
+    }
+      cout << " " << yy << endl;
+     plot([xx,yy],wait=1,cmm="u1 x=0.5 cup");
+     plot([yy,pp],wait=1,cmm="pressure y=0.999 cup");
+}
+
+dt = 0.1;
+int nbiter = 3;
+real coefdt  = 0.25^(1./nbiter);
+real coefcut = 0.25^(1./nbiter) , cut=0.01;
+real tol=0.3,coeftol = 0.25^(1./nbiter);
+nu=1./reylnods;   
+
+for (iter=1;iter<=nbiter;iter++)
+{
+  cout << " dt = " << dt << " ------------------------ " << endl;
+  alpha=1/dt;
+  for (i=0;i<=10;i++)
+   {
+     up1[]=u1[]; // copie vectoriel 
+
+     NS;
+     if ( !(i % 10)) 
+     plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="plotNS_"+iter+"_"+i+".eps");  
+     cout << "CPU " << clock()-s0 << "s " << endl;     
+   } 
+ 
+  if (iter>= nbiter) break;
+ 
+  Th=adaptmesh(Th,[u1,u2],iso=0,
+              abserror=0,cutoff=cut,err=tol, inquire=0,ratio=1.5,hmin=1./1000);
+  plot(Th,ps="ThNS.eps");
+  dt = dt*coefdt;
+  tol = tol *coeftol;
+  cut = cut *coefcut;
+  [u1,u2]=[u1,u2];// reinterpolation 
+  [up1,up2]=[u1,u2];// reinterpolation 
+	
+  p=p;	
+//  plot(coef=0.2,cmm=" [u1,u2] et p --------- ",p,[u1,u2],wait=1);  	
+   }
+cout << "CPU " << clock()-s0 << "s " << endl;     
diff --git a/examples++-load/NewSolver.cpp b/examples++-load/NewSolver.cpp
new file mode 100644
index 0000000..2351ecd
--- /dev/null
+++ b/examples++-load/NewSolver.cpp
@@ -0,0 +1,343 @@
+//  file to add UMFPACK solver with dynamic load.
+//ff-c++-LIBRARY-dep: umfpack amd blas 
+//ff-c++-cpp-dep: 
+
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+
+#include "MatriceCreuse_tpl.hpp"
+
+ 
+#ifdef HAVE_LIBUMFPACK
+extern "C" {
+#ifdef HAVE_UMFPACK_H
+#include <umfpack.h>
+#else
+#ifdef HAVE_UMFPACK_UMFPACK_H
+#include <umfpack/umfpack.h>
+#else
+#ifdef HAVE_BIG_UMFPACK_UMFPACK_H
+#include <UMFPACK/umfpack.h>
+#else
+#ifdef HAVE_UFSPARSE_UMFPACK_H
+#include <ufsparse/umfpack.h>
+#else
+#ifdef HAVE_SUITESPARSE_UMFPACK_H
+#include <suitesparse/umfpack.h>
+#else
+
+  // Defaults to a local version of the UMFPACK headers
+#include "../../download/include/umfpack.h"
+
+#endif // HAVE_SUITESPARSE_UMFPACK_H
+#endif // HAVE_UFSPARSE_UMFPACK_H
+#endif // HAVE_BIG_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_H
+}
+#endif
+template<class R>
+class SolveUMFPACK :   public MatriceMorse<R>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  void *Symbolic, *Numeric ;
+  int umfpackstrategy;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+public:
+  SolveUMFPACK(const MatriceMorse<R> &A,int strategy,double ttgv, double epsilon=1e-6,
+	       double pivot=-1.,double pivot_sym=-1.  ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),
+    Symbolic(0),Numeric(0)  ,
+    umfpackstrategy(strategy),
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+    
+    int status;
+    throwassert( !A.sym() && Numeric == 0 && Symbolic==0 );
+    int n=A.n;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    
+    for(int i=0;i<UMFPACK_CONTROL;i++) Control[i]=0;
+    for(int i=0;i<UMFPACK_INFO;i++) Info[i]=0;
+    
+    umfpack_di_defaults (Control) ;
+    Control[UMFPACK_PRL]=1;
+   // Control[UMFPACK_PIVOT_TOLERANCE]=1E-10;
+    
+    if(verbosity>4) Control[UMFPACK_PRL]=2;
+    if(tol_pivot_sym>0) Control[UMFPACK_SYM_PIVOT_TOLERANCE]=pivot_sym;
+    if(tol_pivot>0) Control[UMFPACK_PIVOT_TOLERANCE]=pivot;
+    if(umfpackstrategy>=0)   Control[UMFPACK_STRATEGY]=umfpackstrategy;
+    if(verbosity>3) { 
+      cout << "  UMFPACK real  Solver Control :" ;
+      cout << "\n\t SYM_PIVOT_TOLERANCE "<< Control[UMFPACK_SYM_PIVOT_TOLERANCE];
+      cout << "\n\t PIVOT_TOLERANCE     "<< Control[UMFPACK_PIVOT_TOLERANCE];
+      cout << "\n\t PRL                 "<< Control[UMFPACK_PRL];
+      cout << "\n";      
+    }
+    
+    status = umfpack_di_symbolic (n, n, A.lg, A.cl, A.a, &Symbolic,Control,Info) ;
+    if (status !=  0)
+    {
+      (void) umfpack_di_report_matrix (n, n, A.lg, A.cl, A.a, 1, Control) ;
+
+	umfpack_di_report_info (Control, Info) ;
+	umfpack_di_report_status (Control, status) ;
+	cerr << "umfpack_di_symbolic failed" << endl;
+	ExecError("umfpack_di_symbolic failed");
+	//ffassert(0);
+    }
+
+    status = umfpack_di_numeric (A.lg, A.cl, A.a, Symbolic, &Numeric,Control,Info) ;
+    if (status !=  0)
+    {
+	umfpack_di_report_info (Control, Info) ;
+	umfpack_di_report_status (Control, status) ;
+	cerr << "umfpack_di_numeric failed" << endl;
+	ExecError("umfpack_di_numeric failed");
+	ffassert(0);
+    }
+
+    if (Symbolic) umfpack_di_free_symbolic (&Symbolic),Symbolic=0; 
+    if(verbosity>3)
+    cout << "  -- umfpack_di_build LU " << n <<  endl;
+    if(verbosity>5)     (void)  umfpack_di_report_info(Control,Info);
+
+  }
+  void Solver(const MatriceMorse<R> &A,KN_<R> &x,const KN_<R> &b) const  {
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    for(int i=0;i<UMFPACK_CONTROL;i++) Control[i]=0;
+    for(int i=0;i<UMFPACK_INFO;i++) Info[i]=0;
+    int n= b.N(); 
+     ffassert(A.ChecknbLine( n) && n == x.N() && A.ChecknbColumn(n) );
+    
+     umfpack_di_defaults (Control) ;
+     // change UMFPACK_At to UMFPACK_Aat in complex 
+     int status = umfpack_di_solve (UMFPACK_Aat, A.lg, A.cl, A.a,KN_2Ptr<R> (x), KN_2Ptr<R>(b), Numeric,Control,Info) ;
+    if (status != 0)
+    {
+	umfpack_di_report_info (Control, Info) ;
+	umfpack_di_report_status (Control, status) ;
+	cerr << "umfpack_di_solve failed" << endl;
+	ExecError("umfpack_di_solve failed");
+	
+	ffassert(0);
+    }
+     if(verbosity>2)
+    cout << " -- umfpack_di_solve " << endl;
+    if(verbosity>3)
+    cout << "   b min max " << b.min() << " " <<b.max() << endl;
+    if(verbosity>3)     (void)  umfpack_di_report_info(Control,Info);
+     if(verbosity>1) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+  }
+
+  ~SolveUMFPACK() { 
+   if(verbosity>3)
+    cout << "~SolveUMFPACK S:" << Symbolic << " N:" << Numeric <<endl;
+    if (Symbolic)   umfpack_di_free_symbolic  (&Symbolic),Symbolic=0; 
+    if (Numeric)    umfpack_di_free_numeric (&Numeric),Numeric=0;
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+template<>
+class SolveUMFPACK<Complex> :   public MatriceMorse<Complex>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  int umfpackstrategy;
+  double tgv;
+  void *Symbolic, *Numeric ;
+  double *ar,*ai;
+
+
+    double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+
+public:
+  SolveUMFPACK(const MatriceMorse<Complex> &A,int strategy,double ttgv, double epsilon=1e-6,
+     double pivot=-1.,double pivot_sym=-1.
+) : 
+    eps(epsilon),epsr(0),umfpackstrategy(strategy),tgv(ttgv),
+    Symbolic(0),Numeric(0),
+    ar(0),ai(0),
+    tol_pivot_sym(pivot_sym), 
+    tol_pivot(pivot)
+   { 
+    int status;
+    throwassert( !A.sym());
+    int n=A.n;
+    //  copy the coef of the matrice ---
+     ar= new double[A.nbcoef];
+     ai= new double[A.nbcoef];
+     ffassert(ar && ai);
+     C2RR(A.nbcoef,A.a,ar,ai);
+        
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    umfpack_zi_defaults (Control) ;
+    Control[UMFPACK_PRL]=1;
+    if(verbosity>4) Control[UMFPACK_PRL]=2;
+   //    Control[UMFPACK_SYM_PIVOT_TOLERANCE]=1E-10;
+  //  Control[UMFPACK_PIVOT_TOLERANCE]=1E-10;
+    if(tol_pivot_sym>0) Control[UMFPACK_SYM_PIVOT_TOLERANCE]=pivot_sym;
+    if(tol_pivot>0) Control[UMFPACK_PIVOT_TOLERANCE]=pivot;
+    if(umfpackstrategy>=0) Control[UMFPACK_STRATEGY]=umfpackstrategy;
+    if(verbosity>3) { 
+      cout << "  UMFPACK complex Solver Control :" ;
+      cout << "\n\t SYM_PIVOT_TOLERANCE "<< Control[UMFPACK_SYM_PIVOT_TOLERANCE];
+      cout << "\n\t PIVOT_TOLERANCE     "<< Control[UMFPACK_PIVOT_TOLERANCE];
+      cout << "\n\t PRL                 "<< Control[UMFPACK_PRL];
+      cout << "\n";      
+    }
+    status = umfpack_zi_symbolic (n, n, A.lg, A.cl, ar,ai, &Symbolic,Control,Info) ;
+    if (status < 0)
+    {
+      (void) umfpack_zi_report_matrix (n, n, A.lg, A.cl, ar,ai, 1, Control) ;
+
+	umfpack_zi_report_info (Control, Info) ;
+	umfpack_zi_report_status (Control, status) ;
+	cerr << "umfpack_zi_symbolic failed" << endl;
+	ExecError("umfpack_zi_symbolic failed");
+	ffassert(0);
+	exit(2);
+    }
+
+    status = umfpack_zi_numeric (A.lg, A.cl, ar,ai, Symbolic, &Numeric,Control,Info) ;
+    if (status < 0)
+    {
+	umfpack_zi_report_info (Control, Info) ;
+	umfpack_zi_report_status (Control, status) ;
+	cerr << "umfpack_zi_numeric failed" << endl;
+	ExecError("umfpack_zi_numeric failed");
+	ffassert(0);
+	exit(2);
+    }
+
+    if (Symbolic) umfpack_zi_free_symbolic (&Symbolic),Symbolic=0; 
+    if(verbosity>3)
+    cout << "umfpack_zi_build LU " << n <<  endl;
+    if(verbosity>5)     (void)  umfpack_zi_report_info(Control,Info);
+
+  }
+  void Solver(const MatriceMorse<Complex> &A,KN_<Complex> &x,const KN_<Complex> &b) const  {
+        ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+     umfpack_zi_defaults (Control) ;
+     int n = b.N();
+     ffassert(A.ChecknbLine( n) && n == x.N() && A.ChecknbColumn(n) );
+     KN<double> xr(n),xi(n),br(n),bi(n);
+     C2RR(n,b,br,bi);
+     // change UMFPACK_At to UMFPACK_Aat in complex  oct 2005 
+    int status = umfpack_zi_solve (UMFPACK_Aat, A.lg, A.cl, ar,ai, xr, xi, br,bi, Numeric,Control,Info) ;
+    if (status < 0)
+    {
+	umfpack_zi_report_info (Control, Info) ;
+	umfpack_zi_report_status (Control, status) ;
+	cerr << "umfpack_zi_solve failed" << endl;
+	ExecError("umfpack_zi_numeric failed");
+	ffassert(0);
+	exit(2);
+    }
+    RR2C(n,xr,xi,x);
+    if(verbosity>1)
+    {
+     cout << "  -- umfpack_zi_solve " << endl;
+     if(verbosity>3)     (void)  umfpack_zi_report_info(Control,Info);
+    
+      cout << "   b min max " << b.min() << " " <<b.max() << endl;
+      cout << "   x min max " << x.min() << " " <<x.max() << endl;
+    }
+  }
+
+  ~SolveUMFPACK() { 
+    if(verbosity>5)
+    cout << "~SolveUMFPACK " << endl;
+    if (Symbolic)   umfpack_zi_free_symbolic  (&Symbolic),Symbolic=0; 
+    if (Numeric)    umfpack_zi_free_numeric (&Numeric),Numeric=0;
+    delete [] ar;
+    delete [] ai;   
+  }
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+     
+
+}; 
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildSolverIUMFPack(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+  if( verbosity>9)
+    cout << " BuildSolverUMFPack<double>" << endl;
+    return new SolveUMFPACK<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+inline MatriceMorse<Complex>::VirtualSolver *
+BuildSolverIUMFPack(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  if( verbosity>9)
+    cout << " BuildSolverUMFPack<Complex>" << endl;
+    return new SolveUMFPACK<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+
+
+bool SetUMFPACK()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to IUMFPack" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverIUMFPack;
+    DefSparseSolver<Complex>::solver =BuildSolverIUMFPack;    
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return  true;
+}
+
+/*  class Init { public:
+    Init();
+};
+$1 */
+static void Load_Init(){    
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  if(verbosity>1)
+    cout << "\n Add: UMFPACK:  defaultsolver defaultsolverUMFPACK" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  
+  DefSparseSolver<double>::solver =BuildSolverIUMFPack;
+  DefSparseSolver<Complex>::solver =BuildSolverIUMFPack;
+
+  if(! Global.Find("defaulttoUMFPACK").NotNull() )
+    Global.Add("defaulttoUMFPACK","(",new OneOperator0<bool>(SetUMFPACK));  
+}
+
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/PARDISO.cpp b/examples++-load/PARDISO.cpp
new file mode 100644
index 0000000..2434bc3
--- /dev/null
+++ b/examples++-load/PARDISO.cpp
@@ -0,0 +1,233 @@
+// SUMMARY  :   PARDISO interface
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : P. Jolivet 
+// E-MAIL   : Pierre Jolivet <pierre.jolivet at ljll.math.upmc.fr>
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+//ff-c++-LIBRARY-dep:  mkl
+//#include <mpi.h>
+#include <mkl_pardiso.h>
+#include <mkl_spblas.h>
+#include <mkl_types.h>
+#if 0
+#include <omp.h>
+#else
+
+extern "C" {
+extern int    omp_get_max_threads  (void);
+extern int     omp_get_num_threads  (void);
+extern void    omp_set_num_threads (int);
+}
+#endif
+#include "rgraph.hpp"
+#include "AFunction.hpp"
+
+#include "MatriceCreuse.hpp"
+#include "dmatrix.hpp"
+
+template<typename RR> struct  PARDISO_STRUC_TRAIT {  typedef void R;static  const int unSYM=0;static const int SYM=0;};
+template<> struct PARDISO_STRUC_TRAIT<double>  { typedef double R;static const int unSYM=11;static const int SYM=2;};
+template<> struct PARDISO_STRUC_TRAIT<Complex>  { typedef Complex R;static const int unSYM=13;static const int SYM=-4;};
+
+void mkl_csrcsc (MKL_INT * job, MKL_INT * n, Complex *Acsr, MKL_INT * AJ0, MKL_INT * AI0, Complex *Acsc, MKL_INT * AJ1, MKL_INT * AI1, MKL_INT * info)
+{ mkl_zcsrcsc (job,n,reinterpret_cast<MKL_Complex16*>(Acsr),AJ0,AI0,reinterpret_cast<MKL_Complex16*>(Acsc),AJ1,AI1,info);}
+
+void mkl_csrcsc (MKL_INT * job, MKL_INT * n, double *Acsr, MKL_INT * AJ0, MKL_INT * AI0, double *Acsc, MKL_INT * AJ1, MKL_INT * AI1, MKL_INT * info)
+{ mkl_dcsrcsc (job,n,Acsr,AJ0,AI0,Acsc,AJ1,AI1,info);}
+
+
+template<class R>
+class SolverPardiso : public MatriceMorse<R>::VirtualSolver {
+    private:
+        mutable void* _pt[64];
+        mutable MKL_INT _mtype;
+        mutable MKL_INT _iparm[64];
+        mutable MatriceMorse<R>* ptA;
+        MKL_INT* _I;
+        MKL_INT* _J;
+    
+    public:
+    typedef typename  PARDISO_STRUC_TRAIT<R>::R MR;
+
+        SolverPardiso(const MatriceMorse<R> &A, KN<long> &param_int, KN<double> &param_double) {
+            ptA = (MatriceMorse<R>*)(&A);
+            MKL_INT phase, error, msglvl;
+            MR ddum;
+            R* _C;
+            if(A.symetrique)
+                _mtype =  PARDISO_STRUC_TRAIT<R>::SYM;
+            else {
+                if(param_int)
+                    _mtype = param_int[0];
+                else
+                    _mtype = PARDISO_STRUC_TRAIT<R>::unSYM;
+            }
+            for (unsigned short i = 0; i < 64; ++i) {
+                _iparm[i] = 0;
+                _pt[i] = NULL;
+            }
+            _iparm[0] = 1;      /* No solver default */
+            _iparm[1] = 3;      /* Fill-in reordering from METIS */
+            _iparm[2] = 1;
+            _iparm[3] = 0;      /* No iterative-direct algorithm */
+            _iparm[4] = 0;      /* No user fill-in reducing permutation */
+            _iparm[5] = 0;      /* Write solution into rhs */
+            _iparm[6] = 0;      /* Not in use */
+            _iparm[7] = 0;      /* Max numbers of iterative refinement steps */
+            _iparm[8] = 0;      /* Not in use */
+            _iparm[9] = 13;     /* Perturb the pivot elements with 1E-13 */
+            _iparm[10] = 1;     /* Use nonsymmetric permutation and scaling MPS */
+            _iparm[11] = 0;     /* Not in use */
+            _iparm[12] = 0;     /* Maximum weighted matching algorithm is switched-off (default for symmetric). Try _iparm[12] = 1 in case of inappropriate accuracy */
+            _iparm[13] = 0;     /* Output: Number of perturbed pivots */
+            _iparm[14] = 0;     /* Not in use */
+            _iparm[15] = 0;     /* Not in use */
+            _iparm[16] = 0;     /* Not in use */
+            _iparm[17] = -1;    /* Output: Number of nonzeros in the factor LU */
+            _iparm[18] = -1;    /* Output: Mflops for LU factorization */
+            _iparm[19] = 0;     /* Output: Numbers of CG Iterations */
+            _iparm[34] = 1;
+            msglvl = 0;         /* Print statistical information in file */
+            if(verbosity > 1)
+                msglvl = 1;
+            error = 0;          /* Initialize error flag */
+            phase = 12;
+            MKL_INT one = 1;
+            MKL_INT n = A.n;
+            if(_mtype != 2) {
+                _I = A.lg;
+                _J = A.cl;
+                _C = A.a;
+            }
+            else {
+                if(A.symetrique) {
+                    int job[6] = { 0, 0, 0, 0, 0, 1 };
+                    _I = new MKL_INT[n + 1];
+                    _J = new MKL_INT[A.nbcoef];
+                    _C = new R[A.nbcoef];
+                    mkl_csrcsc(job, &n, reinterpret_cast<MR*>( A.a), A.cl, A.lg, reinterpret_cast<MR*>(_C), _J, _I, &error);
+                }
+                else {
+                    _I = new MKL_INT[n + 1];
+                    _J = new MKL_INT[n + (A.nbcoef - n) / 2];
+                    _C = new R[n + (A.nbcoef - n) / 2];
+                    trimCSR<true, 'C',R>(n, _I, A.lg, _J, A.cl, _C, A.a);
+                }
+            }
+            PARDISO(_pt, &one, &one, &_mtype, &phase,
+                    &n, reinterpret_cast<MR*>(_C), _I, _J, &one, &one, _iparm, &msglvl, &ddum, &ddum, &error);
+            if(_C != A.a)
+                delete [] _C;
+        };
+
+        void Solver(const MatriceMorse<R> &A, KN_<R> &x, const KN_<R> &b) const  {
+            MKL_INT one    = 1;
+            MKL_INT msglvl = 0;
+            if(verbosity > 1)
+                msglvl = 1;
+            MKL_INT error  = 0;
+            MKL_INT phase = 33;
+            MR ddum;
+            MKL_INT n = A.n;
+            PARDISO(_pt, &one, &one, &_mtype, &phase, &n, &ddum, _I, _J, &one, &one, _iparm, &msglvl, reinterpret_cast<MR*>((R*)b), reinterpret_cast<MR*>((R*)x), &error);
+        };
+
+        ~SolverPardiso() {
+            MKL_INT phase = -1;
+            MKL_INT one = 1;
+            MKL_INT msglvl = 0;
+            MKL_INT error;
+            MR ddum;
+            MKL_INT idum;
+            MKL_INT n = ptA->n;
+            PARDISO(_pt, &one, &one, &_mtype, &phase, &n, &ddum, &idum, &idum, &one, &one, _iparm, &msglvl, &ddum, &ddum, &error);
+            if(_mtype == 2) {
+                if(_I)
+                    delete [] _I;
+                if(_J)
+                    delete [] _J;
+            }
+        };
+};
+
+template<class R>
+typename MatriceMorse<R>::VirtualSolver* buildSolver(DCL_ARG_SPARSE_SOLVER(R, A)) {
+    return new SolverPardiso<R>(*A, ds.lparams, ds.dparams);
+}
+extern  TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue;
+bool SetPARDISO()
+{
+    if(verbosity>1)
+        cout << " SetDefault sparse solver to MUMPS" << endl;
+    DefSparseSolver<double>::solver  = buildSolver<double>;
+    DefSparseSolver<Complex>::solver = buildSolver<Complex>;
+    DefSparseSolverSym<double>::solver  = buildSolver<double>;
+    DefSparseSolverSym<Complex>::solver = buildSolver<Complex>;
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return 0;
+}
+/*  class Init {
+    public:
+        Init();
+};
+
+
+
+$1 */
+
+
+
+
+static long ffompgetnumthreads(){return omp_get_num_threads();}
+static long ffompgetmaxthreads(){return omp_get_max_threads();}
+
+static long ffompsetnumthreads(long n){omp_set_num_threads(n); return n;}
+
+static void Load_Init() {
+  //}static void initPARDISO()
+  //{
+    
+    if(verbosity>1)
+        cout << "\n Add: PARDISO:  defaultsolver defaultsolverPARDISO" << endl;
+    TypeSolveMat::defaultvalue = TypeSolveMat::SparseSolver;
+    DefSparseSolver<double>::solver = buildSolver<double>;
+    DefSparseSolver<Complex>::solver = buildSolver<Complex>;
+
+    DefSparseSolver<double>::solver  = buildSolver;
+    DefSparseSolver<Complex>::solver = buildSolver;
+    DefSparseSolverSym<double>::solver  = buildSolver;
+    DefSparseSolverSym<Complex>::solver = buildSolver;
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+     if(! Global.Find("defaulttoPARDISO").NotNull() )
+        Global.Add("defaulttoPARDISO","(",new OneOperator0<bool>(SetPARDISO));
+    if(! Global.Find("ompsetnumthreads").NotNull() )
+    Global.Add("ompsetnumthreads","(",new OneOperator1<long,long>(ffompsetnumthreads));
+    if(! Global.Find("ompgetnumthreads").NotNull() )
+    Global.Add("ompgetnumthreads","(",new OneOperator0<long>(ffompgetnumthreads));
+    if(! Global.Find("ompgetmaxthreads").NotNull() )
+        Global.Add("ompgetmaxthreads","(",new OneOperator0<long>(ffompgetmaxthreads));
+
+}
+
+
+//LOADFUNC(initPARDISO);
+LOADFUNC(Load_Init)
diff --git a/examples++-load/PARDISO.edp b/examples++-load/PARDISO.edp
new file mode 100755
index 0000000..be450b8
--- /dev/null
+++ b/examples++-load/PARDISO.edp
@@ -0,0 +1,30 @@
+load "PARDISO" 
+load "symmetrizeCSR"
+load "shell"
+//if(ompgetnumthreads() < 2 & getenv("OMP_NUM_THREAD") =="" ) 
+//  ompsetnumthreads(10);// set number of thread for PARDISO ..  
+//cout << " OMP NUM THREAD = " << ompgetnumthreads()  << " " << ompgetmaxthreads() << endl;; 
+int[int] l = [1, 1, 2, 2];
+mesh Th = square(150, 150, label = l);
+fespace Vh(Th, P2);
+Vh u, v;
+varf lap(u,v) = int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v)) + int2d(Th)(v) + on(1, u = 1);
+real[int] b = lap(0, Vh);
+matrix A = lap(Vh, Vh);
+matrix B = A; //lap(Vh, Vh,solver=CG);;
+symmetrizeCSR(B);
+verbosity = 2;
+// If you want, you can pass an array of integer (int[int] t)
+// for specifying the type of the matrix you want to factorize
+//
+// You really should not though, as FreeFem++ will automatically
+// set the solver to either LU or LDL^T
+// lparams = t
+set(A, solver = sparsesolver);
+set(B, solver = sparsesolver);
+verbosity = 0;
+Vh x;
+x[] = A^-1 * b;
+plot(Th, x, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver unsymmetric", value = 1);
+x[] = B^-1 * b;
+plot(Th, x, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver symmetric", value = 1);
diff --git a/examples++-load/README b/examples++-load/README
new file mode 100644
index 0000000..1d0961b
--- /dev/null
+++ b/examples++-load/README
@@ -0,0 +1,91 @@
+
+  new tools to simplify to find the freefem++ external library
+  now in each file.cpp you  have the dependence .cp and file library
+  by adding this kind of line in the cpp file:
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:   xxx 
+//ff-c++-cpp-dep:   yyy.cpp
+
+the command 
+./ff-pkg-download  
+build the liste of compile package in download directory
+this is store in WHERE_LIBRARY-download
+
+and you can add by hand in 
+WHERE_LIBRARY 
+like:  
+lapack  LD  -framework vecLib
+include '-I/System/Library/Frameworks/vecLib.framework/Versions/A/Headers/'
+blas  LD  -framework vecLib
+
+To compile automaticaly:
+just do depending of you achitecture
+make tutu.so
+make tutu.dll    
+make tutu.dylib    
+
+  
+  new function add with loading facility 
+-----------------------------------------
+MetricKuate.cpp:  		MetricKuate
+NewLSolver.cpp:      		defaultsolver
+NewLSolver.cpp:  		defaulttoLUMFPACK
+NewSolver.cpp:    		defaultsolver
+NewSolver.cpp:  		defaulttoUMFPACK
+SuperLU-mt.cpp:    		defaultsolver
+SuperLU-mt.cpp:  		defaulttoSuperLU
+SuperLU.cpp:    		defaultsolver
+SuperLU.cpp:  		defaulttoSuperLU
+buildlayer.cpp:  		buildlayers
+dfft.cpp:  		dfft
+dfft.cpp:  		dfft
+dfft.cpp:  		dfft
+ff-mt19937ar.cpp:  		genrandint32
+ff-mt19937ar.cpp:  		genrandint331
+ff-mt19937ar.cpp:  		genrandreal1
+ff-mt19937ar.cpp:  		genrandreal2
+ff-mt19937ar.cpp:  		genrandreal3
+ff-mt19937ar.cpp:  		genrandres53
+ff-mt19937ar.cpp:  		gendrandint
+ffrandom.cpp:  		srandomdev
+ffrandom.cpp:  		srandom
+ffrandom.cpp:  		random
+funcTemplate.cpp:  		CppModTemplate3
+funcTemplate.cpp:  		CppModTemplate4
+funcTemplate.cpp:  		CppModTemplate5
+funcTemplate.cpp:  		CppModTemplate6
+funcTemplate.cpp:  		CppModTemplate7
+funcTemplate.cpp:  		CppModTemplate8
+hess2d.cpp:  		hessienDF
+hess2d.cpp:  		hessienMC
+mat_dervieux.cpp:  		MatUpWind0
+mat_psi.cpp:     		MatUpWind0
+myfunction.cpp:  		myfunction
+passeVh.cpp:  		myfunction
+medit.cpp:  		medit
+medit.cpp:  		savesol
+medit.cpp:  		medit
+medit.cpp:  		savesol
+
+qf11to25.cpp:	    		qf11pT
+qf11to25.cpp:	    		qf13pT
+qf11to25.cpp:	    		qf14pT
+qf11to25.cpp:	    		qf16pT
+qf11to25.cpp:	    		qf18pT
+qf11to25.cpp:	    		qf20pT
+qf11to25.cpp:	    		qf21pT
+qf11to25.cpp:	    		qf23pT
+qf11to25.cpp:	    		qf25pT
+qf11to25.cpp:	    		qf11pE
+qf11to25.cpp:	    		qf12pE
+qf11to25.cpp:	    		qf13pE
+qft6.cpp:	    		qf2pTT
+qft6.cpp:	    		qf4pTT
+splitmesh3.cpp:  		splitmesh3
+splitmesh6.cpp:  		splitmesh6
+tetgen.cpp:  		tetgconvexhull
+tetgen.cpp:  		tetgconvexhull
+tetgen.cpp:  		tetgtransfo
+tetgen.cpp:  		tetg
+tetgen.cpp:  		tetgreconstruction
+ppm2rnm:  read pgm  ilage file
\ No newline at end of file
diff --git a/examples++-load/README_SuperLU b/examples++-load/README_SuperLU
new file mode 100644
index 0000000..1c320ab
--- /dev/null
+++ b/examples++-load/README_SuperLU
@@ -0,0 +1,33 @@
+To compile superlu.cpp 
+
+to build ../download/lib/libsuperlu_3.1.a
+#  Just do : 
+cd ../download/superlu/
+make
+cd -
+make  SuperLu.$suffix_dynamic_lib
+
+where $suffix_dynamic_lib is "so" "dll" "dylib" depending of you
+achitechure  ( linux, windows, MacOSX)
+
+
+
+1) download the SuperLu 3.0 package form
+
+curl   http://crd.lbl.gov/~xiaoye/SuperLU/superlu_3.0.tar.gz  -o superlu_3.0.tar.gz
+tar xvfz superlu_3.0.tar.gz
+go SuperLU_3.0 directory
+edite make.inc
+make 
+
+
+to compile  the freefem++ load file  of SuperLu with freefem do:
+some find like : 
+./ff-c++ SuperLU.cpp  -I$HOME/work/LinearSolver/SuperLU_3.1/include -L$HOME/work/LinearSolver/SuperLU_3.0/ -lsuperlu_3.0
+To test 
+FreeFem++ SuperLu.edp
+
+Gook Luck. F. Hecht
+
+
+
diff --git a/examples++-load/RZ.h b/examples++-load/RZ.h
new file mode 100755
index 0000000..1334647
--- /dev/null
+++ b/examples++-load/RZ.h
@@ -0,0 +1,546 @@
+//
+//  RZ.h
+//  MeshGenQA
+//
+//  Created by Jean-Marie Mirebeau on 18/06/11.
+//  Copyright 2011 UPMC. All rights reserved.
+//
+#ifndef RZ_H
+#define RZ_H
+
+#include <iostream>
+#include <vector>
+#include "math.h"
+#include "float.h"
+#include "BasicMath.h"
+using namespace std;
+
+/* 
+ Strongly inspired by R2.hpp from F. Hecht
+ 
+ The class RZ contains a double and an integer. Elements of this class are ordered lexicographically.
+ 
+ The template classes Bidim and TriDim describe points with coordinates in a ring (usually integer or real).
+ The classes sym2 and sym3 describe symmetric matrices with real entries.
+ 
+ Lattice basis reduction is implemented under the following names :
+ bool sym2::reduced_basis(Z2 Basis[2]) const;
+ bool sym3::reduced_basis(Z3 Basis[3]) const;
+ 
+ */
+
+class RZ; 
+
+template<class ring> class BiDim;
+typedef BiDim<double> R2;
+typedef BiDim<int>    Z2;
+
+template<class ring> class TriDim;
+typedef TriDim<double> R3;
+typedef TriDim<int>    Z3;
+
+R2 ZdtoRd(const Z2 & P);
+R3 ZdtoRd(const Z3 & P);
+
+class sym2; 
+class sym3;
+
+class Metric2; class FctMetric2;
+class Metric3; class FctMetric3;
+
+//print conventions at the end of the file
+template<class ring> inline ostream& operator << (ostream& f, const BiDim<ring>  & P);
+template<class ring> inline ostream& operator << (ostream& f, const TriDim<ring> & P);
+inline ostream& operator <<(ostream& f, const sym2 & S);
+inline ostream& operator <<(ostream& f, const sym3 & S);
+
+/**************** operators *************/
+//boost implementation is presumably better, but you need to install boost first.
+#ifdef USE_BOOST_OPERATORS
+#include <boost/operators.hpp> 
+using boost::totally_ordered;
+using boost::equality_comparable;
+template <class V, class K> class vector_space : boost::additive<V>, boost::multiplicative<V,K> {};
+
+#else
+// Operators for a vector space V on a field K. (or a module on a ring, but be careful with divisions.)
+// K elements are passed by value, since we assume that it is a machine type (e.g. double, int)
+template <class V, class K> class vector_space {
+public:
+    friend V operator + (V u, const V &v) {return u+=v;}
+    friend V operator - (V u, const V &v) {return u-=v;}
+    friend V operator * (V u, K k)  {return u*=k;}
+    friend V operator * (K k, V u)  {return u*=k;}
+    friend V operator / (V u, K k)  {return u/=k;}
+};
+
+template <class A> class totally_ordered {
+    friend bool operator > (const A &a, const A &b){return b<a;} 
+    friend bool operator <= (const A &a, const A &b){return !(b<a);}
+    friend bool operator >= (const A &a, const A &b){return !(a<b);} 
+    friend bool operator != (const A &a, const A &b){return !(a==b);} 
+};
+
+template <class A> class equality_comparable {
+    friend bool operator != (const A &a, const A &b){return !(a==b);} 
+};
+
+#endif
+
+/**************** classe RZ (distance, number - index) *************/
+
+class RZ :
+totally_ordered<RZ>
+{ //could have used std::pair but too late
+public:
+    double distance;
+    int number;
+    
+    RZ(): distance(-DBL_MAX), number(INT_MIN){}
+    RZ(double dist, int num): distance(dist), number(num){}
+    RZ(const RZ & L): distance(L.distance), number(L.number) {}
+    
+    RZ & operator=(const RZ & L)  {distance = L.distance; number = L.number; return *this;}
+    bool operator == (const RZ & L) const {return distance == L.distance && number == L.number;} 
+    bool operator <  (const RZ & L) const {return distance < L.distance || (distance == L.distance && number < L.number);}
+    
+    RZ MIN(){return RZ(-DBL_MAX,INT_MIN);}
+    RZ MAX(){return RZ(DBL_MAX, INT_MAX);}
+};
+inline ostream& operator <<(ostream& f, const RZ & P ){f << " " << P.distance << " " << P.number; return f;}
+inline ostream_math operator <<(ostream_math f, const RZ & P ){f << "{" << P.distance << "," << P.number << "}"; return f;}
+
+/***************** classes 2d ****************/
+
+template<class ring> class BiDim : vector_space<BiDim<ring>,ring>, totally_ordered<BiDim<ring> >
+{
+public:
+    ring x,y;
+    BiDim():x(0),y(0){};
+    BiDim(ring X, ring Y):x(X), y(Y){};
+    
+    BiDim &  operator*=(ring c) {x*=c; y*=c; return *this;}
+    BiDim &  operator/=(ring c) {const ring d=1/c; assert_msg(c!=ring(0) && d!=ring(0), name << " error : division by " << c); x*=d; y*=d; return *this;}
+    BiDim &  operator+=(const BiDim & P)  {x += P.x;y += P.y;return *this;}
+	BiDim &  operator-=(const BiDim & P)  {x -= P.x;y -= P.y;return *this;}
+    
+    bool operator ==(const BiDim & P) const {return x==P.x && y==P.y;}
+    bool operator < (const BiDim & P) const {return x<P.x || (x==P.x && y<P.y);}
+    
+    const BiDim   operator-() const {return BiDim(-x,-y);}
+    
+    const BiDim lin_sum(const BiDim & P, const BiDim & Q) const {return BiDim(x*P.x+y*Q.x, x*P.y+y*Q.y);};   //produit [P,Q] *this
+    const TriDim<ring> lin_sum(const TriDim<ring> & P, const TriDim<ring> & Q) const {return TriDim<ring>(x*P.x+y*Q.x,x*P.y+y*Q.y,x*P.z+y*Q.z);}
+    const BiDim lin_solve(const BiDim & P, const BiDim & Q) const; //coefficients de *this dans la base (P,Q) : [P,Q]^{-1} *this.
+    
+    ring prod() const {return x*y;}
+    ring min()  const {return x<y ? x : y;}
+    
+    ring   norm2() const {return x*x+y*y;}
+    double norm()  const {return sqrt(norm2());}
+    double norm1() const {return fabs(x)+fabs(y);} 
+    ring scal(const BiDim & Q) const {return x*Q.x+y*Q.y;}
+    
+    bool isPositive() const {return x>=ring(0) && y>=ring(0);}
+//    bool isStrictlyPositive() const {return x>ring(0) && y>ring(0);}
+    bool isZero() const     {return x==ring(0) && y==ring(0);}
+    
+    ring   operator [](int i) const {assert_msg(0<=i && i<=1, name << "::[] error : out of bounds"); if(i==0) return x; else return y;}
+    ring & operator [](int i)       {assert_msg(0<=i && i<=1, name << "::[] error : out of bounds"); if(i==0) return x; else return y;}
+    
+    static const int dim=2;
+    static const string name;
+    static const BiDim NABiDim;
+    
+    BiDim & sort() {if(x>y){const ring t=x; x=y; y=t;} return *this;}
+};
+
+
+
+template<class ring> ring det(const BiDim<ring> & P, const BiDim<ring> & Q) {return P.x*Q.y-P.y*Q.x;}
+
+inline R2 ZdtoRd(const Z2 & P) {return R2(P.x,P.y);}
+
+template<class ring> const BiDim<ring> BiDim<ring>::lin_solve(const BiDim<ring> & P, const BiDim<ring> & Q) const {//coefficients de *this dans la base (P,Q) : [P,Q]^{-1} *this.
+    ring Det = P.x*Q.y-P.y*Q.x;
+    if(Det==0) {cout << name << "::lin_solve error : vectors are collinear " << P << "; " << Q << endl; return NABiDim;}
+    ring invDet=1/Det;
+    if(invDet==0) {cout << name << "::lin_solve error : determinant is not invertible " << Det << "; " << P << "; " << Q << endl; return NABiDim;}
+    return BiDim((x*Q.y-y*Q.x)*invDet,(-x*P.y+y*P.x)*invDet);
+};
+
+
+// matrices symétriques
+class sym2 : vector_space<sym2, double>
+{
+public:
+    double xx, xy, yy;
+    sym2():xx(1),xy(0),yy(1){}
+    sym2(double XX, double XY, double YY):xx(XX), xy(XY), yy(YY){}
+    sym2(double lambda, double mu, const R2 & P);
+    sym2(const sym2 & S):xx(S.xx),xy(S.xy),yy(S.yy){}
+    explicit sym2(double s):xx(s),xy(0),yy(s){};
+    
+    template<class ring> double norm2(const BiDim<ring> & P) const {return xx*(P.x*P.x)+2*xy*(P.x*P.y)+yy*(P.y*P.y);}
+    template<class ring> double norm (const BiDim<ring> & P) const {return sqrt(norm2(P));}
+    template<class ring> double scal (const BiDim<ring> & P, const BiDim<ring> & Q) const 
+    {return xx*(P.x*Q.x)+xy*(P.x*Q.y+P.y*Q.x)+yy*(P.y*Q.y);}
+    template<class ring> double cos2 (const BiDim<ring> & P, const BiDim<ring> & Q) const {return square(scal(P,Q))/(norm2(P)*norm2(Q));}
+    template<class ring> double cos (const BiDim<ring> & P, const BiDim<ring> & Q) const {return scal(P,Q)/(norm(P)*norm(Q));}
+    
+    double det() const {return xx*yy-xy*xy;}
+    double trace() const {return xx+yy;}
+    
+    bool isDiagonal() const {return xy==0;}
+    bool isPositiveDefinite() const {return det()>0 && trace()>0;}
+    void eigen(double E[2]) const { //petite puis grande vap
+        double hDiff = sqrt( square(xx-yy)/4 + square(xy));
+        double hSum = (xx+yy)/2;
+        E[0] = hSum-hDiff;  E[1] = hSum+hDiff;
+    }
+    R2 eigensys(double E[2]) const; 
+    R2 eigensys() const {double E[2]; return eigensys(E);}
+    double norm() const {double E[2]; eigen(E); return max(-E[0],E[1]);}
+    double invNorm() const {return inverse().norm();}
+    
+    //sym2 &  operator+=(double mu)  {xx += mu;yy += mu;return *this;}
+	
+    sym2 & operator+=(sym2 S){xx+=S.xx; xy+=S.xy; yy+=S.yy; return *this;} 
+    sym2 & operator-=(sym2 S){xx-=S.xx; xy-=S.xy; yy-=S.yy; return *this;} 
+    sym2 & operator*=(double lambda)  {xx*=lambda; xy*=lambda; yy*=lambda; return *this;}
+	sym2 & operator/=(double lambda)  {assert_msg(lambda!=0, "sym2 error : division by 0"); return operator*=(1/lambda);}
+    
+    R2 solve(const R2 & P) const;
+    sym2 comatrix() const {return sym2(yy,-xy,xx);}
+    sym2 inverse () const;
+    sym2 sqrtSym() const;
+    sym2 conjugate(const R2 & P, const R2 & Q) const {return sym2(norm2(P), scal(P,Q), norm2(Q));}
+    sym2 exaggerate() const;
+    sym2 tame() const;
+    
+    void reduced_basis(Z2 Basis[2]) const;    
+    R2 operator * (const R2 & P) const {return R2(xx*P.x+xy*P.y, xy*P.x+yy*P.y);}
+};
+
+inline sym2::sym2(double lambda, double mu, const R2 & P){
+    const double normP=P.norm(); //sqrt(P.x*P.x+P.y*P.y); //norme euclidienne...
+    if(normP==0.) {xx=yy=sqrt(fabs(lambda*mu)); xy=0; return;};
+    R2 Q = P/normP;
+    const double nu = lambda-mu;
+    xx=nu*Q.x*Q.x+mu;
+    xy=nu*Q.x*Q.y;
+    yy=nu*Q.y*Q.y+mu;
+}
+
+inline R2 sym2::eigensys(double E[2]) const { //petite puis grande vap. vecteur propre associé à la petite valeur propre
+    eigen(E);
+    const double div = E[0]*E[0] - E[1]*E[1];
+    if(div == 0.) return R2(0,0); //matrice isotrope : on renvoit 0;
+        double c = (E[0]*xx - E[1]*yy)/div;
+        c= c>=0 ? sqrt(c) : 0; //normalement toujours positif
+        double s = (E[0]*yy-E[1]*xx)/div;
+        s= s>=0 ? sqrt(s) : 0;
+        s= (E[0]-E[1])*xy>0 ? s : -s;
+        return R2(c,s);
+        }
+
+inline R2 sym2::solve(const R2 & P) const {
+    const double Det = det();
+    assert_msg(Det!=0, "sym2::solve error : determinant is zero. " << *this);
+    return R2(yy*P.x-xy*P.y, -xy*P.x+xx*P.y)/Det;
+}
+
+inline sym2 sym2::inverse () const {
+    double Det=det(); assert_msg(Det!=0, "sym2::inverse error : determinant is zero. " << *this);
+    return sym2(yy/Det, -xy/Det, xx/Det);}
+
+inline sym2 sym2::sqrtSym() const {
+    double E[2]; eigen(E);
+    sym2 Sq(*this);
+    assert_msg(E[0]>=0 && E[1]>0, "sym2::sqrtSym error : non positive definite matrix. " << *this); 
+    double a = 1/(sqrt(E[0])+sqrt(E[1]));
+	double b = a*sqrt(E[0]*E[1]);
+    Sq*=a; Sq+=sym2(b); return Sq;
+}
+
+inline sym2 sym2::exaggerate() const {//returns a symmetric matrix with the same eigenvectors, but a slightly increased (up to 4x) largest eigenvalue 
+    double E[2]; eigen(E);
+    sym2 Ex(*this);
+    assert(E[0]>=0 && E[1]>0);
+    if(E[0]==E[1]) return Ex;
+    const double diff=E[1]-E[0], E1n = E[1]*square(2/(1+E[0]/E[1]));
+    const double a=E[0]*(E[1]-E1n)/diff, b=(E1n-E[0])/diff;
+    return sym2(a)+b*Ex;
+}
+
+inline sym2 sym2::tame() const {//returns a symmetric matrix with the same eigenvectors, but with the largest eigenvalue divided by 4 or equal to the smallest
+    double E[2]; eigen(E);
+    sym2 Tm(*this);
+    assert(E[0]>=0 && E[1]>0);
+    if(E[0]==E[1]) return Tm;
+    const double diff=E[1]-E[0], E1n = max(E[1]/square(2/(1+E[0]/E[1])),E[0]);
+    const double a=E[0]*(E[1]-E1n)/diff, b=(E1n-E[0])/diff;
+    return sym2(a)+b*Tm;
+}
+
+inline void sym2::reduced_basis(Z2 Basis[2]) const {
+    Z2 &b0=Basis[0], &b1=Basis[1];
+    b0=Z2(1,0); b1=Z2(0,1);
+    double n0=norm2(b0), n1=norm2(b1); // Squared norms
+    
+    if(n1<n0){swap(b0,b1);swap(n0,n1);}  //Sorting the canonical basis by norm
+    if(isDiagonal()) return;
+    
+    while(true){
+        b1 -= round(scal(b0, b1)/n0)*b0;
+        n1=norm2(b1);
+        if(n0<=n1) break;
+        swap(b0,b1); swap(n0,n1);
+    }
+}
+
+/***************** classes 3d ****************/
+
+template<class ring> class TriDim : vector_space<TriDim<ring>,ring>, totally_ordered<TriDim<ring> >
+{
+public:
+    ring x,y,z;
+    TriDim():x(),y(),z(){};
+    TriDim(ring X, ring Y, ring Z):x(X),y(Y),z(Z){};
+    explicit TriDim(int i):x(),y(),z(){assert_msg(0<=i && i<=2, "TriDim::Tridim(int i) error : out of bounds "<<i); if(i==0) x=1; else if(i==1) y=1; else z=1;} 
+    
+    TriDim & operator+=(const TriDim & P)  {x += P.x;y += P.y;z += P.z;return *this;}
+	TriDim & operator-=(const TriDim & P)  {x -= P.x;y -= P.y;z -= P.z;return *this;}
+    TriDim & operator*=(ring c) {x*=c; y*=c; z*=c; return *this;}
+    TriDim & operator/=(ring c) {ring d=1/c; assert_msg(c!=ring(0) && d!=ring(0), name << " error : division by " << c); return operator*=(d);}
+    TriDim   operator-() const {return TriDim(-x,-y,-z);}
+    bool     operator ==(const Z3 & P) const {return x==P.x && y==P.y && z==P.z;}
+    TriDim   operator^(const TriDim & P) const {return TriDim(y*P.z-z*P.y, z*P.x-x*P.z, x*P.y-y*P.x);}
+    
+    bool operator<(const TriDim & P) const {return x<P.x || (x==P.x && (y<P.y || (y==P.y && z<P.z)));} 
+    
+    TriDim lin_sum  (const TriDim & P, const TriDim & Q, const TriDim & R) const //[P,Q,R]*this
+    {return TriDim(x*P.x+y*Q.x+z*R.x, x*P.y+y*Q.y+z*R.y, x*P.z+y*Q.z+z*R.z);} 
+    TriDim lin_solve(const TriDim & P, const TriDim & Q, const TriDim & R) const; //[P,Q,R]^{-1}*this
+    
+    int prod() const {return x*y*z;}
+    ring min()  const {return x<y ? (x<z ? x : z) : (y<z ? y : z);}
+    ring max()  const {return x>y ? (x>z ? x : z) : (y>z ? y : z);}
+    
+    ring   operator[](int i) const {assert_msg(0<=i && i<3,name << "::[] error : out of bounds"); 
+        if(i==0) return x; else if(i==1) return y; else return z;}
+    ring & operator[](int i)       {assert_msg(0<=i && i<3,name << "::[] error : out of bounds"); 
+        if(i==0) return x; else if(i==1) return y; else return z;}
+    
+    bool isZero()     const {return x==ring(0) && y==ring(0) && z==ring(0);}
+    bool isPositive() const {return x>=ring(0) && y>=ring(0) && z>=ring(0);}
+    
+    ring norm2()   const {return x*x+y*y+z*z;}
+    double norm()  const {return sqrt(norm2());}
+    double norm1() const {return fabs(x)+fabs(y)+fabs(z);}
+    
+    ring scal(const TriDim & Q) const {return x*Q.x+y*Q.y+z*Q.z;}
+    
+    static const int dim=3;
+    static const string name;
+};
+
+
+inline R3 ZdtoRd(const Z3 & P){return R3(P.x,P.y,P.z);}
+
+template<class ring> inline double determinant(TriDim<ring> &P, TriDim<ring> &Q, TriDim<ring> &R){
+    return P.x*Q.y*R.z+P.y*Q.z*R.x+P.z*Q.x*R.y-P.z*Q.y*R.x-P.y*Q.x*R.z-P.x*Q.z*R.y;
+}
+
+template<class ring> 
+TriDim<ring> TriDim<ring>::lin_solve(const TriDim<ring> & P, const TriDim<ring> & Q, const TriDim<ring> & R) const {
+    const ring Det = P.x*Q.y*R.z+P.y*Q.z*R.x+P.z*Q.x*R.y-P.z*Q.y*R.x-P.y*Q.x*R.z-P.x*Q.z*R.y;
+    assert_msg(Det!=0,name << "::lin_solve error : matrix is not invertible" << P << "; " << Q << "; " << "; " << R);
+    const ring invDet = 1/Det;
+    assert_msg(invDet!=0, name << "::lin_solve error : determinant is not invertible" << Det << "; " << P << "; " << Q << "; " << "; " << R);
+    return R3((Q.y*R.z-Q.z*R.y)*x+(Q.z*R.x-Q.x*R.z)*y+(Q.x*R.y-Q.y*R.x)*z,
+              (R.y*P.z-R.z*P.y)*x+(R.z*P.x-R.x*P.z)*y+(R.x*P.y-R.y*P.x)*z,
+              (P.y*Q.z-P.z*Q.y)*x+(P.z*Q.x-P.x*Q.z)*y+(P.x*Q.y-P.y*Q.x)*z
+              )*invDet;
+}
+
+// matrices symétriques
+class sym3 : vector_space<sym3,double>, equality_comparable<sym3>
+{
+public:
+    double xx, yy, zz, xy, yz, zx;
+    sym3():xx(1),yy(1),zz(1),xy(0),yz(0),zx(0) {}
+    explicit sym3(double lambda):xx(lambda),yy(lambda),zz(lambda),xy(0),yz(0),zx(0) {}
+    sym3(double XX, double YY, double ZZ, double XY, double YZ, double ZX):xx(XX), yy(YY), zz(ZZ), xy(XY), yz(YZ), zx(ZX){}
+    sym3(double lambda, double mu, const R3 & P){
+        const R3 Q = P/P.norm();
+        const double nu = lambda-mu;
+        xx=nu*Q.x*Q.x+mu; yy=nu*Q.y*Q.y+mu; zz=nu*Q.z*Q.z+mu;
+        xy=nu*Q.x*Q.y;
+        yz=nu*Q.y*Q.z;
+        zx=nu*Q.z*Q.x;
+    }
+    
+    template<class ring> double norm2(const TriDim<ring> & P) const 
+    {return xx*(P.x*P.x)+yy*(P.y*P.y)+zz*(P.z*P.z)+2*xy*(P.x*P.y)+2*yz*(P.y*P.z)+2*zx*(P.z*P.x);}
+    template<class ring> double norm(const TriDim<ring> & P) const {return sqrt(norm2(P));}
+    template<class ring> double scal(const TriDim<ring> & P, const TriDim<ring> & Q) const {
+        return xx*(P.x*Q.x)+yy*(P.y*Q.y)+zz*(P.z*Q.z)+
+        xy*(P.x*Q.y+P.y*Q.x)+yz*(P.y*Q.z+P.z*Q.y)+zx*(P.z*Q.x+P.x*Q.z);
+    }
+    
+    double det()         const {return xx*yy*zz+2*xy*yz*zx-xx*yz*yz-yy*zx*zx-zz*xy*xy;}
+    double trace()       const {return xx+yy+zz;}
+    double invariant()   const {return xx*xx+yy*yy+zz*zz-xy*xy-yz*yz-zx*zx;}
+    
+    bool isDiagonal()           const {return xy==0 && yz==0 && zx==0;}
+    bool isPositiveDefinite()   const {return det()>0 && trace()>0 && invariant()>0;}
+    
+    void reduced_basis(Z3 Basis[3]) const;
+    bool operator == (const sym3 &S) const {return xx==S.xx && yy==S.yy && zz==S.zz && xy==S.xy && yz==S.yz && zx==S.zx;}
+    sym3 & operator+=(double mu)  {xx += mu;yy += mu;zz+=mu;return *this;}
+	sym3 & operator*=(double lambda)  {xx*=lambda; yy*=lambda; zz*=lambda; xy*=lambda; yz*=lambda; zx*=lambda;return *this;}
+	sym3 & operator/=(double lambda)  {assert_msg(lambda!=0, "sym3 error : division by 0"); return operator*=(1/lambda);}
+    sym3 & operator+=(const sym3 &m)  {xx+=m.xx;yy+=m.yy;zz+=m.zz;xy+=m.xy;yz+=m.yz;zx+=m.zx;return *this;}
+    sym3 & operator-=(const sym3 &m)  {xx-=m.xx;yy-=m.yy;zz-=m.zz;xy-=m.xy;yz-=m.yz;zx-=m.zx;return *this;}
+        
+    const R3 operator*(const R3 & P) const {return R3(xx*P.x+xy*P.y+zx*P.z, xy*P.x+yy*P.y+yz*P.z, zx*P.x+yz*P.y+zz*P.z);}
+    const sym3 comatrix() const;
+    const R3 KernelRep() const; //matrix needs to be rank 2, otherwise a null vector is returned.
+    const sym3 inverse() const;
+    template<class ring> sym3 conjugate(const TriDim<ring> & u, const TriDim<ring> & v, const TriDim<ring> & w) const 
+    {return sym3(norm2(u), norm2(v), norm2(w), scal(u,v), scal(v,w), scal(w,u));}
+};
+
+inline const sym3 sym3::comatrix() const {return sym3(yy*zz-square(yz), xx*zz-square(zx), xx*yy-square(xy), yz*zx-xy*zz, zx*xy-xx*yz, xy*yz-yy*zx);}
+
+inline const sym3 sym3::inverse() const {
+    const double Det=det(); assert_msg(Det!=0,"sym3::inverse error : Matrix is not invertible " << *this ); 
+    return comatrix()/Det;
+}
+
+inline void sym3::reduced_basis(Z3 Basis[3]) const { 
+    assert_msg(isPositiveDefinite(), "sym3::reduced_basis error : matrix is not positive definite.");
+        
+    Z3 &b0=Basis[0], &b1=Basis[1], &b2=Basis[2];
+    b0=Z3(1,0,0); b1=Z3(0,1,0); b2=Z3(0,0,1);
+    double n0=norm2(b0), n1=norm2(b1), n2=norm2(b2); // Squared norms
+        
+    if(n2<n1){swap(b1,b2);swap(n1,n2);} //Sorting the canonical basis by norm
+    if(n1<n0){swap(b0,b1);swap(n0,n1);}
+    if(n2<n1){swap(b1,b2);swap(n1,n2);}
+    if(isDiagonal()) return;
+    
+    while(true){
+        while(true){
+            b1 -= round(scal(b0, b1)/n0)*b0;
+            n1=norm2(b1);
+            if(n0<=n1) break;
+            swap(b0,b1); swap(n0,n1);
+        }
+        const sym2 Gram(n0,scal(b0,b1), n1);
+        R2 P = Gram.solve(R2(scal(b0,b2),scal(b1,b2)));
+        const Z2 Q(round(P.x), round(P.y));
+        P-=ZdtoRd(Q);
+        b2 -= Q.lin_sum(b0, b1);
+        n2=norm2(b2);
+        const Z3 b20 = b2-sign(P.x)*b0; const double n20 = norm2(b20);
+        const Z3 b21 = b2-sign(P.y)*b1; const double n21 = norm2(b21);
+        const double n2p=min(n2,min(n20,n21));
+        if(n20==n2p) b2=b20;
+        if(n21==n2p) b2=b21;
+        n2=n2p;
+        if(n1<=n2) break;
+        swap(b1,b2); swap(n1,n2);
+        if(n0<=n1) continue;
+        swap(b0,b1); swap(n0,n1);
+    }
+}
+
+inline const R3 sym3::KernelRep() const {
+    const sym3 co=comatrix();
+    const double norms2[3]= {square(co.xx)+square(co.xy)+square(co.zx),square(co.xy)+square(co.yy)+square(co.yz),square(co.zx)+square(co.yz)+square(co.zz)};
+    return norms2[1]>norms2[2] ? (norms2[0]>norms2[1] ? R3(co.xx,co.xy,co.zx) : R3(co.xy,co.yy,co.yz) ) : (norms2[0]>norms2[2] ? R3(co.xx,co.xy,co.zx) : R3(co.zx,co.yz,co.zz) );
+}
+/************************** affichage de variables et tableaux **********************/
+
+
+
+template<class ring> inline ostream& operator <<(ostream& f, const BiDim<ring> & P ){f << P.x << " " << P.y; return f;}
+template<class ring> inline ostream_math operator <<(ostream_math f, const BiDim<ring> & P ){
+    if(f.format==Mathematica) f<< "{" << P.x << "," << P.y << "}"; else f.os << P;
+    return f;}
+
+template<class ring> inline ostream& operator <<(ostream& f, const TriDim<ring> & P ){f << P.x << " " << P.y << " " << P.z; return f;}
+template<class ring> inline ostream_math operator <<(ostream_math f, const TriDim<ring> & P ){
+    if(f.format==Mathematica) f<< "{" << P.x << "," << P.y << "," << P.z <<"}"; else f.os << P;
+    return f;}
+
+
+inline ostream& operator <<(ostream& f, const sym2 & S ){f << "xx : " << S.xx << "; xy : " << S.xy << "; yy : " << S.yy; return f;}
+inline ostream_math operator <<(ostream_math f, const sym2 & S ){
+    if(f.format==Mathematica) f << "{{" << S.xx << "," << S.xy << "},{" << S.xy << "," << S.yy << "}}"; else f.os << S;
+    return f;}
+
+
+inline ostream& operator <<(ostream& f, const sym3 & S){
+    f <<   "xx : " << S.xx << "; yy : " << S.yy << "; zz : " << S.zz; 
+    f << "; xy : " << S.xy << "; yz : " << S.yz << "; zx : " << S.zx; 
+    return f;}
+inline ostream_math operator <<(ostream_math f, const sym3 & S){
+    if(f.format==Mathematica) f << "{{" << S.xx << "," << S.xy << "," << S.zx << "},{" << S.xy << "," << S.yy << "," << S.yz << "},{" << S.zx << "," << S.yz << "," << S.zz << "}}"; else f.os << S;
+    return f;}
+
+
+//affichage de tableaux
+template <class ForwardIterator, class Zd> void print_array(ostream_math f, ForwardIterator first, ForwardIterator last, Zd N, bool one_per_line=false) {
+    int prod[N.dim]; prod[0]=N[0]; for(int k=1; k<N.dim; ++k) prod[k]=N[k]*prod[k-1];
+    for(int k=0; k<N.dim; ++k) f<<"{";
+    if(first!=last) f<<*first++; 
+    int i=1;
+    for(; first!=last; ++first, ++i){
+        for(int k=0; k<N.dim; ++k) if(i%(prod[k])==0) f<<"}";
+        f<<","; if(one_per_line) f<<"\n";
+        for(int k=0; k<N.dim; ++k) if(i%(prod[k])==0) f<<"{";
+        f << *first;
+    }
+    for(int k=0; k<N.dim; ++k) f<<"}";
+    assert(i==prod[N.dim-1]); //size and format must match
+}
+
+// *********************** Metric classes **********************
+
+// 2d
+class Metric2 {
+public:
+    double lip;
+    Metric2():lip(0){}; // ?? value -1 is reserved to identify the euclidean metric ?? Useful ??
+    virtual const sym2 operator()(const R2 &P) const {return sym2(1,0,1);}
+    virtual ~Metric2(){}
+};
+
+class FctMetric2 : public Metric2 {
+public:
+    const sym2 (*metric_)(const R2 &);
+    FctMetric2(const sym2 (*metric)(const R2 &), double Lip=5):metric_(metric){lip=Lip;}
+    const sym2 operator()(const R2 &P) const {return metric_(P);}
+};
+
+// 3d
+class Metric3 {
+public:
+    double lip;
+    Metric3():lip(0){}; 
+    virtual const sym3 operator()(const R3 &P) const {return sym3(1,1,1,0,0,0);}
+    virtual ~Metric3(){}
+};
+
+class FctMetric3 : public Metric2 {
+public:
+    const sym3 (*metric_)(const R3 &);
+    FctMetric3(const sym3 (*metric)(const R3 &), double Lip=5):metric_(metric){lip=Lip;}
+    const sym3 operator()(const R3 &P) const {return metric_(P);}
+};
+
+
+#endif
diff --git a/examples++-load/SortedList.h b/examples++-load/SortedList.h
new file mode 100755
index 0000000..f251f40
--- /dev/null
+++ b/examples++-load/SortedList.h
@@ -0,0 +1,678 @@
+//
+//  SortedList.h
+//  FastMarchingBundle
+//
+//  Created by Jean-Marie Mirebeau on 22/06/11.
+//  Copyright 2011 UPMC. All rights reserved.
+//
+#ifndef SORTED_LIST_H
+#define SORTED_LIST_H
+
+#include <iostream>
+#include <fstream>
+#include <set>
+#include <vector>
+//#include <stack>
+#include "float.h"
+#include "BasicMath.h"
+using namespace std;
+
+/* 
+ 
+ The template class Tab implements arrays of arbitrary length, which does not need to be fixed in advance.
+ 
+ The template class SortedList implements sorted lists of arbitrary length, which does not need to be fixed in advance either.
+ Common usages, such as insersion and deletion, access to minimal and maximal element, have the complexity log(n).
+
+ The template class RBTree implements Balanced Trees using the Red/Black labels approach. It should not be used directly, but only through SortedList.
+ */
+ 
+template <class TabElement> class Tab;
+template <class TreeLabel>  class SortedList;
+template <class TreeLabel>  class RBTree;
+
+/****************************** Arrays of arbitrary length : Tab *******************************************/
+
+template <class TabElement> 
+class Tab {
+public:
+    Tab():cardMax(startCard), growIndex(0), max_accessed_pos(-1){
+        elements[growIndex++].resize(startCard);
+    };
+    Tab(const Tab<TabElement> & tab):max_accessed_pos(tab.max_accessed_pos) {
+        cout << "Tab constructor Warning : copying Tab of cardinality " << tab.cardMax << "; max accessed pos : " << tab.max_accessed_pos << endl;
+        elements[growIndex++].resize(startCard);
+        for(int i=0; i<tab.cardMax; i++) Element(i)=tab[i];
+    }
+    //~Tab(){for(int i=0; i<growIndex; i++) delete elements[i];}
+    
+    TabElement & operator[](int pos){ //TabElement & Element(int pos)
+        assert_msg(pos>=0,"Tab::Element Error : Negative index " << pos);
+        if(pos >= cardMax){
+            const bool hasGrown = grow(); //contents of an assertion are not executed if NDEBUG
+            assert_msg(hasGrown,"Tab::Element Error : Maximum array size excessed. "<< pos);
+            return operator[](pos);}
+        max_accessed_pos = max(pos, max_accessed_pos);
+        if(pos<startCard) return elements[0][pos];
+        int i, pow; 
+        //for(i=1, pow=startCard; pos>=2*pow; i++, pow*=2){}; 
+        for(i=growIndex-1, pow=cardMax/2; pos<pow; i--, pow/=2){}; 
+        //log(cardMax) complexity in worst case. Unit in average thanks to reversed loop
+        return elements[i][pos-pow];
+    };
+    const TabElement & operator[](int pos) const {
+        assert_msg(pos>=0, "Tab::Element Error : Negative index " << pos);
+        assert_msg(pos<=max_accessed_pos,"Tab::Element const Error : max_accessed_pos exceeded. "<< pos);
+        if(pos<startCard) return elements[0][pos];
+        int i, pow; 
+        //for(i=1, pow=startCard; pos>=2*pow; i++, pow*=2){}; //
+        for(i=growIndex-1, pow=cardMax/2; pos<pow; i--, pow/=2){}; 
+        return elements[i][pos-pow];
+    };
+    void export_content(const char * filename, Format_Math format=Mathematica, bool one_per_line=false) const {
+        ofstream data_out; data_out.open(filename); print_array(data_out << format, *this, one_per_line); data_out.close();}
+    
+    void sort();
+    int max_accessed_pos;
+    int card() const {return max_accessed_pos+1;}
+    
+    TabElement *next(){return &operator[](max_accessed_pos+1);}
+    
+    int index(TabElement const *ptr) const {
+        const int j0= int(ptr-&elements[0][0]);
+        if(0 <= j0 && j0 <startCard) return j0;
+        int i, pow;
+        for(i=growIndex-1, pow=cardMax/2; i>=1; i--, pow/=2) {
+            const int j = int(ptr-&elements[i][0]); 
+            if(0<=j && j<pow) return pow+j;
+        }
+        cout<<"Tab::index error : element does not belong to tab"<<endl;
+        return -1;
+    }
+    
+private:
+    int cardMax;
+    int growIndex;
+    const static int startCard = 4;
+    const static int growMax   = 30;
+    
+    vector<TabElement> elements[growMax];
+//    TabElement * elements[growMax]; 
+//    TabElement NegElement;
+    
+    bool grow(){
+        if(growIndex==growMax) return false;
+        elements[growIndex++].resize(cardMax);
+        cardMax*=2;
+        return true;
+    }
+    TabElement & Element(int pos) {return operator[](pos);}
+    const TabElement & Element(int pos) const {return operator[](pos);}
+};
+
+template <class TabElement>
+void Tab<TabElement>::sort(){
+    if(max_accessed_pos >50){ //tri n ln(n).
+        SortedList<TabElement> list;
+        for(int i=0; i<=max_accessed_pos; ++i) list.insert(Element(i));
+        for(int i=0; i<=max_accessed_pos; ++i) Element(i)=list.pop();
+        return;
+    }
+    TabElement swap;
+    for (int i=0; i<max_accessed_pos; ++i) {
+        if(operator[](i+1)<operator[](i)){
+            swap=Element(i+1);
+            Element(i+1)=Element(i);
+            int j;
+            for(j=i-1; j>=0 && Element(j)>swap; --j) Element(j+1)=Element(j);
+            Element(j+1)=swap;
+        }
+    }
+}
+
+template<class E> void print_array(ostream & f, const Tab<E> & tab, bool one_per_line=false){
+    const int N=tab.max_accessed_pos+1; 
+    if(one_per_line) for(int i=0; i<N; i++) f << tab[i] << endl;
+    else for(int i=0; i<N; i++) f << tab[i] << " ";
+}
+
+template<class E> void print_array(ostream_math f, const Tab<E> & tab, bool one_per_line=false){
+    if(f.format==Mathematica) {
+        const int N=tab.max_accessed_pos+1; 
+        if(N<=0) {f << "{}"; return;}
+        f << "{"; 
+        for(int i=0; i<N; i++) {f << tab[i]; if(i<N-1) f << ",";}
+        f << "}";}
+    else {print_array(f.os, tab, one_per_line); return;}
+}
+
+template<class TabElement> ostream&     operator <<(ostream& f,     const Tab<TabElement> & tab ){print_array(f,tab); return f;}
+template<class TabElement> ostream_math operator <<(ostream_math f, const Tab<TabElement> & tab ){print_array(f,tab); return f;}
+
+// ********************** Reservoir *********************
+//Reservoir of copies of a given object.  References are consistent over time.
+template<class E> class Reservoir {
+    Tab<E> reserve;
+    mutable vector<E*> unused;
+public:
+    int card() const {return int(reserve.card()-unused.size());}
+    E* next(){if(unused.empty()) return reserve.next(); E* e=unused.back(); unused.pop_back(); return e;} //bizarre that pop is void 
+    bool free(E* e){if(reserve.index(e)<0) return false; unused.push_back(e); return true;}
+    void enumerate(vector<E*> &elems);
+    void enumerate(vector<const E*> &elems) const;
+};
+
+
+template<class E> void Reservoir<E>::enumerate(vector<E*> &elems){
+    sort(unused.begin(), unused.end());
+    int u=0; //vector<E*>::const_iterator u does not work for some reason
+    for(int i=0; i<reserve.card(); ++i){
+        E *const e=&reserve[i];
+        if(e==unused[u]) ++u;
+        else elems.push_back(e);
+    }
+}
+
+template<class E> void Reservoir<E>::enumerate(vector<const E*> &elems) const {
+    sort(unused.begin(), unused.end());
+    int u=0; //vector<E*>::const_iterator u does not work for some reason
+    for(int i=0; i<reserve.card(); ++i){
+        const E *const e=&reserve[i];
+        if(u<unused.size() && e==unused[u]) ++u;
+        else elems.push_back(e);
+    }
+}
+/************************ Safe Vector (at debug time) *********************/
+//same as standard library's vector, but with additional checks at DEBUG time. Should be zero overhead at non debug time
+
+template<class E> class safe_vector : public vector<E> {
+public:
+          E & operator[](size_t n)       {assert(0<=n && n<this->size()); return this->vector<E>::operator[](n);}
+    const E & operator[](size_t n) const {assert(0<=n && n<this->size()); return this->vector<E>::operator[](n);}
+          E & front()                    {assert(0<this->size()); return this->vector<E>::front();}
+    const E & front()              const {assert(0<this->size()); return this->vector<E>::front();}
+          E & back()                     {assert(0<this->size()); return this->vector<E>::back();}
+    const E & back()               const {assert(0<this->size()); return this->vector<E>::back();}
+};
+
+/************************ Sorted List *********************/
+
+//new implementation : a simple interface with std::set
+template <class E> 
+class SortedList {
+    set<E> s;
+public:
+    int Card(){return int(s.size());}
+    bool contains(E e){return s.count(e);}
+    E min(){return *s.begin();} //empty cases ?
+    E max(){return *--s.end();}
+    bool insert(E e){return s.insert(e).second;}
+    bool remove(E e){return s.erase(e);}
+    E pop(){E e=min(); remove(e); return e;}
+    void print(ostream &f){
+        Tab<E> tab; enumerate(tab); f << tab;}
+    //int enumerate(Tab<E> &tab){set<E>::const_iterator it; int i; for(it=s.begin(), i=0; it!=s.end(); ++it, ++i){tab[i]=*it;} return i;}
+    //int enumerate(Tab<E> &tab){for(int i=0; i<Card(); ++i){tab[i]=s[i];} return Card();}
+    int enumerate(Tab<E> &tab);
+    void clear(){s.clear();}
+};
+
+template<>
+inline int SortedList<RZ>::enumerate(Tab<RZ> &tab){
+    set<RZ>::const_iterator it; int i; 
+    for(it=s.begin(), i=0; it!=s.end(); ++it, ++i){tab[i]=*it;} 
+    return i;
+}
+
+
+//old implementation based on personal construction of red black trees. Works fine, but the standard library might be safer and/or faster (?)
+/*
+template <class TreeLabel> 
+class SortedList {
+public:
+    const int & Card;
+    
+    SortedList() : newNode(0), deleteNode(0), card(0), Card(card), cardMax(startCard), growIndex(1){
+        nodes[0]    = new RBTree<TreeLabel>    [2*cardMax];
+        pNodes      = new RBTree<TreeLabel> *  [2*cardMax];
+        for(int i=0; i<2*cardMax; i++) {pNodes[i] = nodes[0]+i;}
+    }
+    SortedList(const SortedList & list){
+        cout << "Sorted list constructor warning : copying list of cardinal " << list.Card << endl;
+        Tab<TreeLabel> tab; list.enumerate(tab); for(int i=0; i<list.Card; i++) insert(tab[i]);
+    }
+    ~SortedList(){
+        for(int i=0; i<growIndex; i++) delete nodes[i];
+        delete pNodes;
+    }
+    bool contains(TreeLabel m){return root.contains(m);}
+    TreeLabel min(){return root.min();}
+    TreeLabel max(){return root.max();}
+    bool insert(TreeLabel m){
+        if(root.insert(m, pNodes[newNode], pNodes[newNode+1])){
+            card++; newNode = (newNode+2)%(2*cardMax); 
+            if(card==cardMax) grow();
+            return true;}
+        return false;
+    }
+    bool remove(TreeLabel m){
+        if(root.remove(m, pNodes[deleteNode], pNodes[deleteNode+1])){card--; deleteNode = (deleteNode+2)%(2*cardMax); return true;}
+        return false;
+    }
+    TreeLabel pop();
+    void print(ostream& f) const {f << "{ "; root.printInOrder(f); f << "}";}
+    void printTree(ostream& f) const {f << root;}
+    int enumerate(Tab<TreeLabel> & tab){int counter=0; root.enumerate(tab, counter); return counter;}
+    void clear(){while(Card>0) pop();}
+private:
+    const static int startCard = 64;
+    const static int growMax   = 25;
+    int growIndex;
+    
+    RBTree<TreeLabel> root;
+    RBTree<TreeLabel> * nodes[growMax]; 
+    RBTree<TreeLabel> * * pNodes;
+    int newNode;
+    int deleteNode;
+    
+    int card;   //attention : le nombre de noeuds est le double du cardinal
+    int cardMax;
+    
+    bool grow(){
+        //lorsque grow est appelé, on doit avoir card==cardMax, et donc newNode == deleteNode
+        if(growIndex == growMax) return false;
+        nodes[growIndex] = new RBTree<TreeLabel> [2*cardMax]; //création des nouveaux noeuds. même nombre que tous ceux créés jusque alors
+        cardMax*=2;
+        delete pNodes;
+        pNodes = new RBTree<TreeLabel> * [2*cardMax]; //création des nouveaux pointeurs, autant que de noeuds au total
+        for(int i=0; i<cardMax; i++) pNodes[i] = nodes[growIndex]+i;
+        newNode = 0;    deleteNode = cardMax;   growIndex++;
+        return true;
+    }
+};
+
+
+template<class TreeLabel>
+TreeLabel SortedList<TreeLabel>::pop(){
+    TreeLabel ans;
+    if(card<=0) return root.ELEMENT_MAX;
+    ans = root.pop(pNodes[deleteNode], pNodes[deleteNode+1]);
+    card--; deleteNode = (deleteNode+2)%(2*cardMax);        
+    return ans;
+}
+
+template<class TreeLabel> ostream& operator <<(ostream& f, const SortedList<TreeLabel> & list){
+    list.print(f); return f;}
+template<class TreeLabel> ostream_math operator <<(ostream_math f, const SortedList<TreeLabel> & list){
+    if(f.format==Mathematica) {Tab<TreeLabel> tab; list.enumerate(tab); f<<tab;} else f.os << list;
+    return f;}
+
+// ********************** RBTree *********************
+
+// Note : si le besoin s'en fait sentir, il est envisageable de diviser par 2 l'occupation mémoire, 
+// en faisant porter un noeud non trivial aux feuilles.
+
+enum RBL {Red, Black, Leaf};
+enum AP {Absorbed, Propagated};
+enum APb {Absorbed_true, Absorbed_false, Propagated_true};
+
+inline bool APb2bool(APb a){return a!=Absorbed_false;}
+inline AP APb2AP(APb a){return a==Propagated_true ? Propagated : Absorbed;}
+inline APb AP_b2APb(AP a, bool b){return a==Propagated ? Propagated_true : (b==true ? Absorbed_true : Absorbed_false);}
+
+template <class TreeLabel> class RBTree {
+public:    
+    RBTree () :color(Leaf),n(),left(NULL),right(NULL){}
+    bool contains (TreeLabel m);
+    bool checkColor();
+    TreeLabel min();
+    TreeLabel max();
+    int black_height();
+    bool check();
+    bool insert(TreeLabel m,    RBTree<TreeLabel> * leftTree,       RBTree<TreeLabel> * rightTree);
+    bool remove(TreeLabel m,    RBTree<TreeLabel> * & leftTree,     RBTree<TreeLabel> * & rightTree);
+    TreeLabel pop(              RBTree<TreeLabel> * & leftTree,     RBTree<TreeLabel> * & rightTree); //renvoie le plus petit élément, et le supprime
+    void print(ostream& f) const;
+    void printInOrder(ostream& f) const;
+    bool isEmpty(){return color==Leaf;}
+    void enumerate(Tab<TreeLabel> & tab, int & counter);
+    void reset();
+private:
+    friend class SortedList<TreeLabel>;
+    RBL color;
+    TreeLabel n;
+    RBTree * left;
+    RBTree * right;
+    
+    void conflict();
+    bool rec_insert(TreeLabel m, RBTree<TreeLabel> * leftTree, RBTree<TreeLabel> * rightTree);
+    APb rec_remove(TreeLabel m, RBTree<TreeLabel> * & leftTree, RBTree<TreeLabel> * & rightTree);
+    AP unbalanced_right();    
+    AP unbalanced_left();
+    
+    static const TreeLabel ELEMENT_MIN;
+    static const TreeLabel ELEMENT_MAX;
+};
+
+template<class TreeLabel>
+inline ostream& operator <<(ostream& f, const RBTree<TreeLabel> & tree ){
+    tree.print(f);
+    return f;
+}
+
+template <class TreeLabel>
+void RBTree<TreeLabel>::print(std::ostream& f) const {
+    if(color==Leaf) {f << "Leaf"; return;}
+    f << n << " "; 
+    if(color==Red) {f << "Red";} else f << "Black"; 
+    f << "( " << *left << ", " << *right << ")";
+}
+
+template <class TreeLabel>
+void RBTree<TreeLabel>::printInOrder(std::ostream& f) const {
+    if(color==Leaf) return;
+    left->printInOrder(f);
+    if(!left->isEmpty()) f << ", ";
+    f << n;
+    if(!right->isEmpty()) f << ", ";
+    right->printInOrder(f);
+}
+
+template <class TreeLabel>
+bool RBTree<TreeLabel>::contains (TreeLabel m){return n==m || (color != Leaf && (m<n ? left->contains(m) : right->contains(m)) ); }
+
+template <class TreeLabel>
+bool RBTree<TreeLabel>::checkColor(){
+    return color==Leaf || (left->checkColor() && right->checkColor() && (color != Red || (left->color != Red && right->color != Red)));
+}
+
+template <class TreeLabel>
+TreeLabel RBTree<TreeLabel>::min()  {return color==Leaf ? ELEMENT_MAX : (left->color==Leaf ? n : left->min() );}
+
+template <class TreeLabel>
+TreeLabel RBTree<TreeLabel>::max()  {return color==Leaf ? ELEMENT_MIN : (right->color==Leaf ? n : right->max() );}
+
+template <class TreeLabel>
+int RBTree<TreeLabel>::black_height(){
+    if(color==Leaf) return 0;
+    int lh = left->black_height(); 
+    int rh = right->black_height(); 
+    return lh==rh ? (color == Black) + lh : INT_MIN; 
+} 
+// par construction, la hauteur noire à gauche et à droite doivent être égales. En cas de différence, la valeur reçue est négative.
+
+template <class TreeLabel>
+bool RBTree<TreeLabel>::check(){return checkColor() && black_height() >= 0;}
+
+
+template <class TreeLabel>
+void RBTree<TreeLabel>::conflict(){
+    if(color!=Black) return;
+    
+    if(left->color==Red && left->left->color==Red){
+        RBTree * OldLeft = left;
+        RBTree * OldLeftLeft = left->left;
+        RBTree * t1 = OldLeftLeft->left;
+        RBTree * t2 = OldLeftLeft->right;
+        RBTree * t3 = OldLeft->right;
+        RBTree * t4 = right;
+        
+        const TreeLabel n1 = OldLeftLeft->n;
+        const TreeLabel n2 = OldLeft->n;
+        const TreeLabel n3 = n;
+        
+        color = Red;
+        left  = OldLeftLeft;    left->color = Black; 
+        right = OldLeft;        right->color = Black;
+        
+        left->left = t1;      left->right = t2;
+        right->left = t3;     right->right = t4;
+        
+        left->n   = n1;
+        n         = n2;
+        right->n  = n3;
+        return;
+    }
+    if(left->color == Red && left->right->color == Red){
+        //RBTree * OldLeft = left;
+        RBTree * OldLeftRight = left->right;
+        //RBTree * t1 = OldLeft->left;
+        RBTree * t2 = OldLeftRight->left;
+        RBTree * t3 = OldLeftRight->right;
+        RBTree * t4 = right;
+        
+        //const TreeLabel n1 = OldLeft->n;
+        const TreeLabel n2 = OldLeftRight->n;
+        const TreeLabel n3 = n;
+        
+        color = Red;
+        //left = OldLeft;       //inchangé 
+        left->color = Black;
+        right = OldLeftRight;
+        right->color = Black;
+        
+        //left->left = t1;    //inchangé
+        left->right  = t2;
+        right->left  = t3;
+        right->right = t4;
+        
+        //left->n   = n1;
+        n           = n2;
+        right->n  = n3;
+        return;
+    }
+    if(right->color == Red && right->right->color == Red){
+        RBTree * OldRight = right;
+        RBTree * OldRightRight = right->right;
+        RBTree * t1 = left;
+        RBTree * t2 = OldRight->left;
+        RBTree * t3 = OldRightRight->left;
+        RBTree * t4 = OldRightRight->right;
+        
+        const TreeLabel n1 = n;
+        const TreeLabel n2 = OldRight->n;
+        const TreeLabel n3 = OldRightRight->n;
+        
+        color = Red;
+        left    = OldRight;         left->color = Black;
+        right   = OldRightRight;    right->color = Black;
+        
+        left->left = t1;      left->right = t2;
+        right->left = t3;     right->right = t4;
+        
+        left->n   = n1;
+        n           = n2;
+        right->n  = n3;
+        return;
+    }
+    if(right->color == Red && right->left->color == Red){
+        //RBTree * OldRight = right;
+        RBTree * OldRightLeft = right->left;
+        RBTree * t1 = left;
+        RBTree * t2 = OldRightLeft->left;
+        RBTree * t3 = OldRightLeft->right;
+        //RBTree * t4 = OldRight->right;
+        
+        const TreeLabel n1 = n;
+        const TreeLabel n2 = OldRightLeft->n;
+        //            const TreeLabel n3 = OldRight->n;
+        
+        color = Red;
+        left = OldRightLeft;
+        left->color = Black;
+        //right = OldRight;      //inchangé
+        right->color = Black;
+        
+        left->left = t1;      left->right = t2;
+        right->left = t3;     //right->right = t4; //inchangé
+        
+        left->n   = n1;
+        n         = n2;
+        //right->n  = n3;
+        return;
+    }
+}
+
+template <class TreeLabel>
+bool RBTree<TreeLabel>::rec_insert(TreeLabel m, RBTree<TreeLabel> * leftTree, RBTree<TreeLabel> * rightTree){
+    if(color==Leaf){color=Red; n=m; left = leftTree; right = rightTree; return true;}
+    if(n==m) return false;
+    const bool ans = m < n ? left->rec_insert(m, leftTree, rightTree) : right->rec_insert(m, leftTree, rightTree);
+    conflict();
+    return ans;
+}
+
+template <class TreeLabel>
+bool RBTree<TreeLabel>::insert(TreeLabel m, RBTree<TreeLabel> * leftTree, RBTree<TreeLabel> * rightTree){
+    const bool ans = rec_insert(m, leftTree, rightTree);
+    color = Black;
+    return ans;
+}
+
+template <class TreeLabel>
+AP RBTree<TreeLabel>::unbalanced_right(){ //branche de droite plus légère que celle de gauche (suite à une délétion)
+    if(color == Red && left->color == Black){
+        color = Black;
+        left->color = Red;
+        conflict();
+        return Absorbed;
+    }
+    if(color == Black && left->color == Red){
+        RBTree * OldLeft = left;
+        RBTree * t1 = left->left;
+        RBTree * t2 = left->right;
+        RBTree * t3 = right;
+        const TreeLabel n1 = left->n;
+        const TreeLabel n2 = n;
+        
+        left = t1;
+        right = OldLeft;
+        right->left = t2;
+        right->right = t3;
+        
+        right->color = Black;
+        t2->color = Red;  //par construction t2->color == Black initialement
+        
+        n = n1; right->n = n2;
+        right->conflict();
+        return Absorbed;
+        
+    }
+    if(color == Black && left->color == Black){
+        left->color = Red;
+        conflict();
+        return Propagated; //l'arbre a été allégé, le déséquilibre est propagé
+    }
+    return Absorbed; // on n'est pas censé en arriver là
+}
+
+template <class TreeLabel>
+AP RBTree<TreeLabel>::unbalanced_left(){ //branche de gauche plus légère que celle de droite (suite à une délétion)
+    if(color == Red && right->color == Black){
+        color = Black;
+        right->color=Red;
+        conflict();
+        return Absorbed;
+    }
+    if(color == Black && right->color == Red){
+        RBTree * OldRight = right;
+        RBTree * t1 = left;
+        RBTree * t2 = right->left;
+        RBTree * t3 = right->right;
+        const TreeLabel n1 = n;
+        const TreeLabel n2 = right->n;
+        
+        left = OldRight;
+        left->left = t1;
+        left->right = t2;
+        right = t3;
+        
+        left->color = Black;
+        t2->color = Red;  //par construction t2->color == Black initialement
+        
+        left->n = n1; n = n2; 
+        left->conflict();
+        return Absorbed;
+        
+    }
+    if(color == Black && right->color == Black){
+        right->color = Red;
+        conflict();
+        return Propagated; //l'arbre a été allégé, le déséquilibre est propagé
+    }
+    return Absorbed; // on n'est pas censé en arriver là
+}
+
+template <class TreeLabel>
+APb RBTree<TreeLabel>::rec_remove(TreeLabel m, RBTree<TreeLabel> * & leftTree, RBTree<TreeLabel> * & rightTree){
+    if(color == Leaf) return Absorbed_false; //rien ne se passe
+    if(m<n){ 
+        const APb ans = left->rec_remove(m, leftTree, rightTree); 
+        conflict();
+        if(ans != Propagated_true) return ans;
+        return AP_b2APb(unbalanced_left(), APb2bool(ans));
+    }
+    if(m>n){ 
+        const APb ans = right->rec_remove(m, leftTree, rightTree); 
+        conflict();
+        if(ans != Propagated_true) return ans;
+        return AP_b2APb(unbalanced_right(), APb2bool(ans));
+    }
+    //cas m==n
+    if(left->color != Leaf){
+        const TreeLabel maxLeft = left->max();
+        n = maxLeft;
+        const APb ans = left->rec_remove(maxLeft, leftTree, rightTree);
+        conflict();
+        if(ans != Propagated_true) return ans;
+        return AP_b2APb(unbalanced_left(), APb2bool(ans));        
+    }
+    if(right->color!=Leaf){
+        const TreeLabel minRight = right->min();
+        n = minRight;
+        const APb ans = right->rec_remove(minRight, leftTree, rightTree);
+        conflict();
+        if(ans != Propagated_true) return ans;
+        return AP_b2APb(unbalanced_right(), APb2bool(ans));
+    }
+    RBL OldColor = color;
+    leftTree = left;
+    rightTree = right;
+    reset();
+    if(OldColor == Black) return Propagated_true;
+    return Absorbed_true;
+}
+
+template<class TreeLabel> void RBTree<TreeLabel>::reset() {color = Leaf; n=ELEMENT_MIN; left = NULL; right = NULL;}
+
+template <class TreeLabel>
+bool RBTree<TreeLabel>::remove(TreeLabel m, RBTree<TreeLabel> * & leftTree, RBTree<TreeLabel> * & rightTree){
+    const APb ans = rec_remove(m, leftTree, rightTree);
+    if(color == Red) color = Black;
+    return APb2bool(ans);
+}
+
+template <class TreeLabel>
+TreeLabel RBTree<TreeLabel>::pop(RBTree<TreeLabel> * & leftTree, RBTree<TreeLabel> * & rightTree){
+    const TreeLabel m=min();
+    remove(m, leftTree, rightTree);
+    return m;
+}
+
+template <class TreeLabel>
+void RBTree<TreeLabel>::enumerate(Tab<TreeLabel> & tab, int & counter){
+    if(color==Leaf) return;
+    left->enumerate(tab, counter);
+    tab[counter++] = n; //RZ(n.distance, n.number);
+    right->enumerate(tab,counter);
+}
+
+template<>                const double    RBTree<double>   ::ELEMENT_MIN = DBL_MIN;
+template<>                const int       RBTree<int>      ::ELEMENT_MIN = INT_MIN;
+template<class TreeLabel> const TreeLabel RBTree<TreeLabel>::ELEMENT_MIN = TreeLabel().MIN();
+template<>                const double    RBTree<double>   ::ELEMENT_MAX = DBL_MAX;
+template<>                const int       RBTree<int>      ::ELEMENT_MAX = INT_MAX;
+template<class TreeLabel> const TreeLabel RBTree<TreeLabel>::ELEMENT_MAX = TreeLabel().MAX();
+ */
+ 
+#endif
diff --git a/examples++-load/SuperLU.edp b/examples++-load/SuperLU.edp
new file mode 100644
index 0000000..9f4cee0
--- /dev/null
+++ b/examples++-load/SuperLU.edp
@@ -0,0 +1,71 @@
+load "SuperLu"
+
+verbosity=0;
+
+{
+
+cout << "laplace solving with SuperLu" << endl;
+
+mesh Th=square(10,10);
+fespace Vh(Th,P1);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+
+problem laplace(uh,vh,solver=sparsesolver,tgv=1e5) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th)( f*vh )                        	     //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  bou  ndary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+ 
+  plot(uh,ps="Laplace.eps",value=true); 
+}
+
+// FFCS: need to declare it globally to print out its value for regression tests
+complex[int] lastx(4);
+
+for(int i=0;i<3;++i)
+{
+  if(i==0)  cout << "resolution SuperLU" <<endl; 
+  if(i==1)  cout << "resolution GMRES" <<endl;
+  if(i==2)  cout << "resolution UMFPACK" <<endl; 
+  {
+    matrix A = 
+      [[ 0,  1,  0, 10],
+       [ 0,  0,  2,  0],
+       [ 0,  0,  0,  3],
+       [ 4,  0,  0,  0]];
+    real[int] xx = [ 4,1,2,3], x(4), b(4); // xb(4),bbb(4);
+    b=A*xx;
+    cout << "b="  << b  << endl;
+    cout << "xx=" << xx << endl;
+    set(A,solver=sparsesolver,sparams="DiagPivotThresh=0.05,ColPerm=MMD_AT_PLUS_A,Equil=NO"); 
+    x = A^-1*b;	
+    cout << "x=" << endl; cout << x << endl;	
+  }
+  
+  {
+    matrix<complex> A = 
+      [[  0, 1i,  0, 10],
+       [  0,  0, 2i,  0],
+       [  0,  0,  0, 3i],
+       [ 4i,  0,  0,  0]];
+    complex[int] xx = [ 4i,1i,2i,3i], x(4), b(4);
+    b = A*xx;
+    cout << "b="  << b << endl;
+    cout << "xx=" << xx << endl;
+    set(A,solver=sparsesolver);
+    x = A^-1*b;
+    cout << "x=" << endl; cout << x << endl;
+    lastx=x;
+  }
+  if(i==0)defaulttoGMRES();
+  if(i==1)defaultsolver();
+}
+cout << " fin.. \n";
+
+
+
+
diff --git a/examples++-load/SuperLu.cpp b/examples++-load/SuperLu.cpp
new file mode 100644
index 0000000..ad407b0
--- /dev/null
+++ b/examples++-load/SuperLu.cpp
@@ -0,0 +1,778 @@
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:   superlu blas 
+//ff-c++-cpp-dep: 
+//  for Super4.0 library   
+#include "ff++.hpp"
+#include "slu_ddefs.h"
+#include "superlu_enum_consts.h"
+#define GlobalLU_t GlobalLU_txxxx
+#define countnz countnzxxxx
+#define fixupL fixupLxxxx
+#define print_lu_col print_lu_colxxxx
+#define check_tempv check_tempvxxxx
+#define PrintPerf PrintPerfxxxx
+#define ilu_countnz  ilu_countnzxxxx
+#include "slu_zdefs.h"
+
+#undef GlobalLU_t
+#undef countnz
+#undef fixupL
+#undef print_lu_col
+#undef check_tempv
+#undef PrintPerf
+#undef ilu_countnz
+
+
+template <class R> struct SuperLUDriver
+{
+    
+};
+
+template <> struct SuperLUDriver<double>
+{
+    /* Driver routines */
+    static  Dtype_t R_SLU_T() { return SLU_D;} 
+    static void
+    gssv(superlu_options_t * p1, SuperMatrix * p2, int * p3, int * p4, SuperMatrix * p5,
+	  SuperMatrix * p6, SuperMatrix * p7 , SuperLUStat_t * p8, int * p9)
+    { dgssv( p1,p2,p3,p4,p5,p6,p7,p8,p9); }
+    
+    
+    static void
+	gssvx(superlu_options_t * p1, SuperMatrix * p2, int * p3, int * p4, int * p5,
+	       char * p6, double * p7, double * p8, SuperMatrix * p9, SuperMatrix * p10,
+	       void * p11, int p12, SuperMatrix * p13, SuperMatrix * p14,
+	       double * p15, double * p16, double * p17, double * p18,
+	       mem_usage_t * p19, SuperLUStat_t * p20, int * p21)
+    { dgssvx( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,  p11,p12,p13,p14,p15,p16,p17,p18,p19,p20, p21); }
+    
+    
+    
+    /* Supernodal LU factor related */
+    static void
+	Create_CompCol_Matrix(SuperMatrix * p1, int p2 , int p3, int p4, double * p5,
+			       int * p6, int * p7, Stype_t p8, Dtype_t p9 , Mtype_t p10)
+    {
+	    dCreate_CompCol_Matrix( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
+    }
+    
+    
+    static void
+	Create_CompRow_Matrix(SuperMatrix * p1, int p2, int p3, int p4, double * p5,
+			       int * p6, int * p7, Stype_t p8, Dtype_t p9, Mtype_t p10)
+    {
+	dCreate_CompRow_Matrix( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
+    }
+    
+    
+    static void
+	Create_Dense_Matrix(SuperMatrix * p1, int p2, int p3, double * p4, int p5,
+			     Stype_t p6, Dtype_t p7, Mtype_t p8)
+    {
+	dCreate_Dense_Matrix( p1,p2,p3,p4,p5,p6,p7,p8);
+    }
+    
+    
+    static void
+	Create_SuperNode_Matrix(SuperMatrix * p1, int p2, int p3, int p4, double * p5, 
+				 int * p6, int * p7, int * p8, int * p9, int * p10,
+				 Stype_t p11, Dtype_t p12, Mtype_t p13)
+    {
+	    dCreate_SuperNode_Matrix( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,  p11,p12,p13);
+    }
+    
+    static void 
+    CompRow_to_CompCol(int p1, int p2, int p3, 
+		       double *p4, int *p5, int *p6,
+		       double **p7, int **p8, int **p9)
+  {
+    dCompRow_to_CompCol( p1, p2, p3, p4, p5, p6, p7, p8, p9);
+  }
+
+    
+};
+
+
+
+template <> struct SuperLUDriver<Complex>
+{
+    /* Driver routines */
+  static  Dtype_t R_SLU_T() { return SLU_Z;} 
+  static doublecomplex *dc(Complex *p)  { return (doublecomplex *) (void *) p;}
+  static doublecomplex **dc(Complex **p)  { return (doublecomplex **) (void *) p;}
+  
+    static void
+    gssv(superlu_options_t * p1, SuperMatrix * p2, int * p3, int * p4, SuperMatrix * p5,
+	 SuperMatrix * p6, SuperMatrix * p7 , SuperLUStat_t * p8, int * p9)
+    { zgssv( p1,p2,p3,p4,p5,p6,p7,p8,p9); }
+    
+    
+    static void
+    gssvx(superlu_options_t * p1, SuperMatrix * p2, int * p3, int * p4, int * p5,
+	  char * p6, double * p7, double * p8, SuperMatrix * p9, SuperMatrix * p10,
+	  void * p11, int p12, SuperMatrix * p13, SuperMatrix * p14,
+	  double * p15, double * p16, double * p17, double * p18,
+	  mem_usage_t * p19, SuperLUStat_t * p20, int * p21)
+    { zgssvx( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,  p11,p12,p13,p14,p15,p16,p17,p18,p19,p20, p21); }
+    
+    
+    
+    /* Supernodal LU factor related */
+    static void
+    Create_CompCol_Matrix(SuperMatrix * p1, int p2 , int p3, int p4, Complex * p5,
+			  int * p6, int * p7, Stype_t p8, Dtype_t p9 , Mtype_t p10)
+    {
+	zCreate_CompCol_Matrix( p1,p2,p3,p4,dc(p5),p6,p7,p8,p9,p10);
+    }
+    
+    
+    static void
+    Create_CompRow_Matrix(SuperMatrix * p1, int p2, int p3, int p4, Complex * p5,
+			  int * p6, int * p7, Stype_t p8, Dtype_t p9, Mtype_t p10)
+    {
+	zCreate_CompRow_Matrix( p1,p2,p3,p4,dc(p5),p6,p7,p8,p9,p10);
+    }
+    
+    
+    static void
+    Create_Dense_Matrix(SuperMatrix * p1, int p2, int p3, Complex * p4, int p5,
+			Stype_t p6, Dtype_t p7, Mtype_t p8)
+    {
+	zCreate_Dense_Matrix( p1,p2,p3,dc(p4),p5,p6,p7,p8);
+    }
+    
+    
+    static void
+    Create_SuperNode_Matrix(SuperMatrix * p1, int p2, int p3, int p4, Complex * p5, 
+			    int * p6, int * p7, int * p8, int * p9, int * p10,
+			    Stype_t p11, Dtype_t p12, Mtype_t p13)
+    {
+	zCreate_SuperNode_Matrix( p1,p2,p3,p4,dc(p5),p6,p7,p8,p9,p10,  p11,p12,p13);
+    }
+    
+  static void 
+  CompRow_to_CompCol(int p1, int p2, int p3, Complex *p4, int *p5, 
+		     int *p6, Complex **p7, int **p8, int **p9)
+  {
+    zCompRow_to_CompCol( p1, p2, p3, dc(p4), p5, p6, dc(p7), p8, p9);
+  }
+    
+};
+
+// read options for superlu in freefem++
+/*
+#ifdef __cpluscplus
+int s_(char *ff, ...)
+{
+  int i = 0;
+  while( *(++i+&str) != 0 )
+    if( strcmp(str, (char*)*(&str+i)) == 0)
+      return i;
+  return 0;
+}
+
+#else
+*/
+int s_(char* str, const char* cmp[])
+{
+  int i = 0;
+  while( cmp[i] != 0){
+    if( strcmp(str, cmp[i]) == 0){
+      //cout << *str << " return" << i << endl;
+      return i+1 ;
+    }
+    i++;
+  }
+  //cout << *str << " return 0" << endl;
+  return 0;
+}
+//#endif
+/*
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[5] = {NATURAL, MMD_ATA, MMD_AT_PLUS_A, COLAMD, MY_PERMC};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const  IterRefine_t enumIterRefine_t[4] = {NOREFINE, SINGLE, DOUBLE, EXTRA};  
+  
+  static const char*  compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  
+  static const char* comp[] = {"Fact", "Equil","ColPerm",
+  "DiagPivotThresh","Trans","IterRefine",
+  "SymmetricMode","PivotGrowth","ConditionNumber",
+  "PrintStat",0};
+*/
+
+void read_options_freefem(string string_option, superlu_options_t *options){
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[5] = {NATURAL, MMD_ATA, MMD_AT_PLUS_A, COLAMD, MY_PERMC};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const  IterRefine_t enumIterRefine_t[4] = {NOREFINE, SLU_SINGLE, SLU_DOUBLE, SLU_EXTRA};  
+
+  static const char*  compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  
+  static const char* comp[] = {"Fact", "Equil","ColPerm",
+			       "DiagPivotThresh","Trans","IterRefine",
+			       "SymmetricMode","PivotGrowth","ConditionNumber",
+			       "PrintStat",0};
+
+
+   /* Set the default values for options argument:
+	options.Fact = DOFACT;
+	options.Equil = YES;
+	options.ColPerm = COLAMD;
+	options.DiagPivotThresh = 1.0;
+	options.Trans = NOTRANS;
+	options.IterRefine = NOREFINE;
+	options.SymmetricMode = NO;
+	options.PivotGrowth = NO;
+	options.ConditionNumber = NO;
+	options.PrintStat = YES;
+    */
+  //cout << "string_option" <<  *string_option << endl;
+    KN<char> kdata(string_option.size()+1);
+    
+    char * data=kdata;
+  strcpy( data, string_option.c_str()); 
+  cout << "data=" << data << endl;
+  char * tictac;
+  tictac = strtok(data," =,\t\n");
+  cout << "tictac=" << data << endl;
+// #ifdef __cplusplus
+//   while(tictac != NULL){
+//     int id_option = s_(tictac, "Fact", "Equil","ColPerm",
+// 				"DiagPivotThresh","Trans","IterRefine",
+// 				"SymmetricMode","PivotGrowth","ConditionNumber",
+// 				"PrintStat",0);
+//     tictac = strtok(NULL," ,\t\n");
+//     int val_options;
+//     switch (id_option)
+//       { 
+//       case 1 : // Fact
+// 	val_options= s_(tictac, "DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+// 	  exit(1);
+// 	}
+// 	options->Fact= enumfact_t[val_options-1];
+// 	break;
+//       case 2:  // Equil
+// 	val_options= s_(tictac, "NO", "YES", 0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+// 	  exit(1);
+// 	}
+// 	options->Equil= enumyes_no_t[val_options-1];
+// 	break;
+//       case 3:  // ColPerm
+// 	val_options= s_(tictac,"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+// 	  exit(1);
+// 	}
+// 	options->ColPerm= enumcolperm_t[val_options-1];
+//       case 4:  // DiagPivotThresh
+// 	options->DiagPivotThresh= strtod(tictac,&tictac);
+// 	break;
+//       case 5:  // Trans
+// 	val_options= s_(tictac, "NOTRANS", "TRANS", "CONJ",0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+// 	  exit(1);
+// 	}
+// 	options->Trans= enumtrans_t[val_options-1];
+// 	break;
+//       case 6:  // IterRefine
+// 	val_options= s_(tictac, "NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","IterRefine");
+// 	  exit(1);
+// 	}
+// 	options->IterRefine= enumIterRefine_t[val_options-1];
+// 	break;
+//       case 7:  // SymmetricMode
+// 	val_options= s_(tictac, "NO","YES",0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+// 	  exit(1);
+// 	}
+// 	options->SymmetricMode= enumyes_no_t[val_options-1];
+// 	break;
+//       case 8:  // PivotGrowth
+// 	val_options= s_(tictac, "NO","YES",0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+// 	  exit(1);
+// 	}
+// 	options->PivotGrowth= enumyes_no_t[val_options-1];
+// 	break;
+//       case 9:  // ConditionNumber
+// 	val_options= s_(tictac, "NO","YES",0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+// 	  exit(1);
+// 	}
+// 	options->ConditionNumber = enumyes_no_t[val_options-1];
+// 	break;
+//       case 10: // PrintStat
+// 	val_options= s_(tictac, "NO","YES",0);
+// 	if( val_options == 0){
+// 	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+// 	  exit(1);
+// 	}
+// 	options->PrintStat = enumyes_no_t[val_options-1];
+// 	break;
+//       case 0: // Equivalent of case default
+// 	printf("A false parameter for  SuperLU is given %s \n",tictac);
+// 	exit(1);
+//       }  
+//     tictac = strtok(NULL," ,\t\n");
+//   }
+// #else
+  while(tictac != NULL){
+    //char* comp[] = {"Fact", "Equil","ColPerm",
+    //"DiagPivotThresh","Trans","IterRefine",
+    //"SymmetricMode","PivotGrowth","ConditionNumber",
+    //"PrintStat",0 };
+    int id_option = s_(tictac, comp);
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 1 : // Fact
+	//char* comp1[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+	val_options= s_(tictac,compfact_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+	  exit(1);
+	}
+	options->Fact = enumfact_t[val_options-1];
+	break;
+      case 2:  // Equil
+	//char* comp2[] = {"NO", "YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+	  exit(1);
+	}
+	options->Equil = enumyes_no_t[val_options-1];
+	break;
+      case 3:  // ColPerm
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compcolperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ColPerm = enumcolperm_t[val_options-1];
+	break;
+      case 4:  // DiagPivotThresh
+	options->DiagPivotThresh= strtod(tictac,&tictac);
+	break;
+      case 5:  // Trans
+	//char* comp5[] = {"NOTRANS", "TRANS", "CONJ", 0};
+	val_options= s_(tictac, comptrans_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+	  exit(1);
+	}
+	options->Trans = enumtrans_t[val_options-1];
+	break;
+      case 6:  // IterRefine
+	//char* comp6[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA", 0};
+	val_options= s_(tictac, compIterRefine_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","IterRefine");
+	  exit(1);
+	}
+	options->IterRefine = enumIterRefine_t[val_options-1];
+	break;
+      case 7:  // SymmetricMode
+	//char* comp7[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+	  exit(1);
+	}
+	options->SymmetricMode= enumyes_no_t[val_options-1]; 
+	break;
+      case 8:  // PivotGrowth
+	//char* comp8[] = {"NO","YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+	  exit(1);
+	}
+	options->PivotGrowth = enumyes_no_t[val_options-1];
+	break;
+      case 9:  // ConditionNumber
+	//char* comp9[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+	  exit(1);
+	}
+	options->ConditionNumber = enumyes_no_t[val_options-1];
+	break;
+      case 10: // PrintStat
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+	options->PrintStat = enumyes_no_t[val_options-1];
+	break;
+      case 0: // Equivalent of case default
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+  //#endif
+}
+
+  
+
+
+
+
+template<class R>
+class SolveSuperLU :   public MatriceMorse<R>::VirtualSolver, public SuperLUDriver<R>   {
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  
+  
+  mutable char           equed[1];
+  yes_no_t       equil;
+  mutable SuperMatrix    A, L, U;
+  NCformat       *Astore;
+  NCformat       *Ustore;
+  SCformat       *Lstore;
+  R              *a;
+  int            *asub, *xa;
+  KN<int>             perm_c; /* column permutation vector */
+  KN<int>             perm_r; /* row permutations from partial pivoting */
+  string string_option;
+  //string *file_option;
+  //string *file_perm_r;
+  //string *file_perm_c;
+  
+  KN<int>            etree;
+  R         *rhsb, *rhsx, *xact;
+  double         *RR, *CC;
+  int m, n, nnz;
+  
+  R         *arow;
+  int       *asubrow, *xarow;
+  
+   
+   mutable superlu_options_t options;
+   mutable mem_usage_t    mem_usage;
+   
+public:
+  SolveSuperLU(const MatriceMorse<R> &AA,int strategy,double ttgv, double epsilon,
+	       double pivot,double pivot_sym, string & param_char, KN<long> pperm_r, 
+	       KN<long> pperm_c ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),
+    etree(0),string_option(param_char),perm_r(pperm_r), perm_c(pperm_c),
+    RR(0), CC(0), 
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+     SuperMatrix    B, X;
+     SuperLUStat_t stat;
+     void           *work=0;
+     int            info, lwork=0, nrhs=1;
+     int            i;
+     double         ferr[1];
+     double         berr[1];
+     double          rpg, rcond;
+    
+     R *bb;
+     R *xx;
+
+     A.Store=0;
+     B.Store=0;
+     X.Store=0;
+     L.Store=0;
+     U.Store=0;
+	
+    int status;
+
+    n=AA.n;
+    m=AA.m;
+    nnz=AA.nbcoef;
+
+    arow=AA.a;
+    asubrow=AA.cl;
+    xarow=AA.lg;
+
+    /* FreeFem++ use Morse Format */ 
+    // FFCS - "this->" required by g++ 4.7
+    this->CompRow_to_CompCol(m, n, nnz, arow, asubrow, xarow, 
+		       &a, &asub, &xa);
+
+    /* Defaults */
+    lwork = 0;
+    nrhs  = 0;
+    
+    /* Set the default values for options argument:
+	options.Fact = DOFACT;
+	options.Equil = YES;
+	options.ColPerm = COLAMD;
+	options.DiagPivotThresh = 1.0;
+	options.Trans = NOTRANS;
+	options.IterRefine = NOREFINE;
+	options.SymmetricMode = NO;
+	options.PivotGrowth = NO;
+	options.ConditionNumber = NO;
+	options.PrintStat = YES;
+    */
+    set_default_options(&options);
+    
+    printf(".. default options:\n");
+    printf("\tFact\t %8d\n", options.Fact);
+    printf("\tEquil\t %8d\n", options.Equil);
+    printf("\tColPerm\t %8d\n", options.ColPerm);
+    printf("\tDiagPivotThresh %8.4f\n", options.DiagPivotThresh);
+    printf("\tTrans\t %8d\n", options.Trans);
+    printf("\tIterRefine\t%4d\n", options.IterRefine);
+    printf("\tSymmetricMode\t%4d\n", options.SymmetricMode);
+    printf("\tPivotGrowth\t%4d\n", options.PivotGrowth);
+    printf("\tConditionNumber\t%4d\n", options.ConditionNumber);
+    printf("..\n");
+    
+    if(!string_option.empty()) read_options_freefem(string_option,&options);
+    
+    printf(".. options:\n");
+    printf("\tFact\t %8d\n", options.Fact);
+    printf("\tEquil\t %8d\n", options.Equil);
+    printf("\tColPerm\t %8d\n", options.ColPerm);
+    printf("\tDiagPivotThresh %8.4f\n", options.DiagPivotThresh);
+    printf("\tTrans\t %8d\n", options.Trans);
+    printf("\tIterRefine\t%4d\n", options.IterRefine);
+    printf("\tSymmetricMode\t%4d\n", options.SymmetricMode);
+    printf("\tPivotGrowth\t%4d\n", options.PivotGrowth);
+    printf("\tConditionNumber\t%4d\n", options.ConditionNumber);
+    printf("..\n");
+
+    Dtype_t R_SLU = SuperLUDriver<R>::R_SLU_T(); 
+
+    // FFCS - "this->" required by g++ 4.7
+    this->Create_CompCol_Matrix(&A, m, n, nnz, a, asub, xa, SLU_NC, R_SLU, SLU_GE);
+  
+    this->Create_Dense_Matrix(&B, m, 0, (R*) 0, m, SLU_DN, R_SLU, SLU_GE);
+    this->Create_Dense_Matrix(&X, m, 0, (R*) 0, m, SLU_DN, R_SLU, SLU_GE);
+      
+
+      if ( etree.size() ==0 )   etree.resize(n);   
+      if ( perm_r.size() ==0 )   perm_r.resize(n);   
+      if ( perm_c.size() ==0 )   perm_c.resize(n);   
+     
+    if ( !(RR = new double[n]) )
+        ABORT("SUPERLU_MALLOC fails for R[].");
+    for(int ii=0; ii<n; ii++){
+      RR[ii]=1.;
+    }
+    if ( !(CC = new double[m]) )
+        ABORT("SUPERLU_MALLOC fails for C[].");
+    for(int ii=0; ii<n; ii++){
+      CC[ii]=1.;
+    }    
+    ferr[0]=0;
+    berr[0]=0;
+    /* Initialize the statistics variables. */
+    StatInit(&stat);
+    
+    /* ONLY PERFORM THE LU DECOMPOSITION */
+    B.ncol = 0;  /* Indicate not to solve the system */
+    SuperLUDriver<R>::gssvx(&options, &A, perm_c, perm_r, etree, equed, RR, CC,
+           &L, &U, work, lwork, &B, &X, &rpg, &rcond, ferr, berr,
+           &mem_usage, &stat, &info);
+
+   
+
+    if(verbosity>2)
+    printf("LU factorization: dgssvx() returns info %d\n", info);
+    if(verbosity>3)
+    {
+    if ( info == 0 || info == n+1 ) {
+	
+	if ( options.PivotGrowth ) printf("Recip. pivot growth = %e\n", rpg);
+	if ( options.ConditionNumber )
+	    printf("Recip. condition number = %e\n", rcond);
+        Lstore = (SCformat *) L.Store;
+        Ustore = (NCformat *) U.Store;
+	printf("No of nonzeros in factor L = %d\n", Lstore->nnz);
+    	printf("No of nonzeros in factor U = %d\n", Ustore->nnz);
+    	printf("No of nonzeros in L+U = %d\n", Lstore->nnz + Ustore->nnz - n);
+	printf("L\\U MB %.3f\ttotal MB needed %.3f\texpansions %d\n",
+	       mem_usage.for_lu/1e6, mem_usage.total_needed/1e6,
+	       stat.expansions
+	       );
+	fflush(stdout);
+	
+    } else if ( info > 0 && lwork == -1 ) {
+        printf("** Estimated memory: %d bytes\n", info - n);
+    }
+    }
+    if ( verbosity>5 ) StatPrint(&stat);
+    StatFree(&stat);
+    if( B.Store)  Destroy_SuperMatrix_Store(&B);
+    if( X.Store)  Destroy_SuperMatrix_Store(&X);
+    options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+
+
+  }
+  void Solver(const MatriceMorse<R> &AA,KN_<R> &x,const KN_<R> &b) const  {
+    SuperMatrix    B, X;
+    SuperLUStat_t stat;
+    void           *work=0;
+    int            info=0, lwork=0, nrhs=1;
+    int            i;
+    double       ferr[1], berr[1];
+    double         rpg, rcond;
+    double       *xx;
+
+    B.Store=0;
+    X.Store=0;
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    Dtype_t R_SLU = SuperLUDriver<R>::R_SLU_T(); 
+
+      { 
+	  KN_2Ptr<R> xx(x),bb(b);
+	  // cout << " xx #### " << xx.c.N() << " "<< xx.ca.N() <<  " " << xx.ca.step << endl;
+	  //cout << " bb #### " << bb.c.N() << " "<< bb.ca.N() << " " << bb.ca.step <<endl;
+	  // FFCS - "this->" required by g++ 4.7
+	  this->Create_Dense_Matrix(&B, m, 1, bb, m, SLU_DN, R_SLU, SLU_GE);
+	  this->Create_Dense_Matrix(&X, m, 1, xx, m, SLU_DN, R_SLU, SLU_GE);
+	  
+	  B.ncol = nrhs;  /* Set the number of right-hand side */
+	  
+	  /* Initialize the statistics variables. */
+	  StatInit(&stat);
+	  
+	  
+	  SuperLUDriver<R>::gssvx(&options, &A, perm_c, perm_r, etree, equed, RR, CC,
+				  &L, &U, work, lwork, &B, &X, &rpg, &rcond, ferr, berr,
+				  &mem_usage, &stat, &info);
+	  
+	  
+	  
+	  if(verbosity>2)
+	      printf("Triangular solve: dgssvx() returns info %d\n", info);
+	  
+      }
+  
+   
+
+    if(verbosity>3)
+    {
+    if ( info == 0 || info == n+1 ) {
+	
+        /* This is how you could access the solution matrix. */
+        R *sol = (R*) ((DNformat*) X.Store)->nzval; 
+	
+	
+	if ( options.IterRefine ) {
+            printf("Iterative Refinement:\n");
+	    printf("%8s%8s%16s%16s\n", "rhs", "Steps", "FERR", "BERR");
+	    printf("%8d%8d%16e%16e\n", i+1, stat.RefineSteps, ferr[0], berr[0]);
+	}
+	fflush(stdout);
+    } else if ( info > 0 && lwork == -1 ) {
+        printf("** Estimated memory: %d bytes\n", info - n);
+    }
+    }
+    
+
+    //cout << "   x min max " << x.min() << " " <<x.max() << endl;
+    //cout << "=========================================" << endl;
+    if( B.Store)  Destroy_SuperMatrix_Store(&B);
+    if( X.Store)  Destroy_SuperMatrix_Store(&X);
+  }
+
+  ~SolveSuperLU() { 
+   if(verbosity>3)
+       cout << "~SolveSuperLU S:" << endl;
+   //   if (etree)    delete[] etree; 
+   //   if (perm_r)   delete[] perm_r; 
+   //   if (perm_c)   delete[] perm_c; 
+      if (RR)   delete[] RR; 
+      if (CC)   delete[] CC; 
+      if( A.Store)  Destroy_SuperMatrix_Store(&A);
+      if( L.Store)  Destroy_SuperNode_Matrix(&L);
+      if( U.Store)  Destroy_CompCol_Matrix(&U);
+      
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverSuperLU(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverSuperLU<double>" << endl;
+    return new SolveSuperLU<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym,ds.sparams,ds.perm_r,ds.perm_c);
+}
+
+MatriceMorse<Complex>::VirtualSolver *
+BuildSolverSuperLU(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  if(verbosity>9)
+    cout << " BuildSolverSuperLU<Complex>" << endl;
+  return new SolveSuperLU<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym,ds.sparams,ds.perm_r,ds.perm_c);
+}
+
+
+/*  class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetSuperLU()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to SuperLU" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverSuperLU;
+    DefSparseSolver<Complex>::solver =BuildSolverSuperLU;    
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return  true;
+}
+
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: SuperLU,  defaultsolverSuperLU" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverSuperLU;
+  DefSparseSolver<Complex>::solver =BuildSolverSuperLU;
+  Global.Add("defaulttoSuperLU","(",new OneOperator0<bool>(SetSuperLU));
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/TensorK.hpp b/examples++-load/TensorK.hpp
new file mode 100755
index 0000000..490b82a
--- /dev/null
+++ b/examples++-load/TensorK.hpp
@@ -0,0 +1,581 @@
+//
+//  TensorK.h
+//  
+//
+//  Created by Jean-Marie Mirebeau on 12/10/11.
+//  Copyright 2011 UPMC. All rights reserved.
+//
+// This file contains two main routines : 
+// - one for the construction of a metric
+// - one for the computing the derivatives of a polynomial sampled at lagrange points on a triangle
+
+#ifndef _TensorK_h
+#define _TensorK_h
+
+#include <vector>
+#include <cmath>
+#include <algorithm>
+#include "assert.h"
+using std::vector;
+
+// ***************** Quelques fonctions ************
+
+//quelques fonctions
+
+
+inline double square(double u){return u*u;};
+inline double   max(double a, double b)                                 {return a>b ? a             : b;}
+inline double   max(double a, double b, double c)                       {return a>c ? max(a,b)      : max(b,c);}
+inline double   max(double a, double b, double c, double d)             {return a>d ? max(a,b,c)    : max(b,c,d);}
+inline double   max(double a, double b, double c, double d, double e)   {return a>e ? max(a,b,c,d)  : max(b,c,d,e);}
+
+// ***************** Prototypes ********************
+
+
+class TensorK {
+    vector<double> factorials;
+    std::vector<double> exponents;
+    double factorial(int n) const {assert(0<=n<=factorials.size()); return factorials[n];}
+    double binomial(int n, int k) const {assert(0<=n && n<=factorials.size() && 0<=k && k<=n); return factorials[n]/(factorials[k]*factorials[n-k]);}
+    const int t_deg; //degree of the polynomials involved
+public:
+    const int m_deg;
+    const int r_deg;
+    enum triangulation_type {Graded=0, Quasi_Acute=1, Quasi_Acute_Unrefined=2, Quasi_Acute_Proved=3};
+    const triangulation_type ttype;
+    const double p_exp;
+    enum which_matrix {M0_alone=0, M1_alone=1, M0_M1_weighted_sum=2};
+    const which_matrix wmat;
+    
+    static const int d_dim=2;
+    const double gamma_exp;
+    const double homog_exp;
+    const bool is_valid;
+    
+    TensorK(int m_deg_, int r_deg_, triangulation_type ttype_, which_matrix wmat, double p_exp_);
+    
+    void getM(const double *D, double M[3]) const; //L^Infinity metric        // size required : D[m_deg+1], m_deg+1 == m_dim
+    void equilibrate(const double M[3], double Me[3]) const; //Me = (det M)^(-1/((m-r)p+d)) M = (det M)^gamma_exp M.
+private:
+    
+    void getMc(const double *D, double Mc[3]) const;                          //size required : D[t_deg+1] 
+    void getM0(const double E[2], double c, double s, double M0[3]) const;    //input : eigenvalues and eigenvector of Mc
+    void getM1(const double *D, double c, double s, double M1[3]) const;      //size required : D[t_deg+1] 
+    void getMs(const double *D, double Ms[3]) const;                          //size required : D[t_deg+1] 
+    
+    void rotate(const double *D, double *Dr, double c, double s) const;       //size required : D[t_deg+1] 
+    void getSquare(const double *D, double *Ds) const; //get |d^r pi|^2. D[m_deg+1], Ds[t_deg+1]
+    
+public: //derivative estimation
+    void getDerivatives(const std::vector<double> & DOFt, const R2 invHauteur[3], double *f) const;
+private:
+    template<int m> void Derivatives(const std::vector<double> & DOFt, const R2 invHauteur[3], double f[m]) const;
+    
+public: //symmetric matrix utilities
+    static void EigenSym(const double S[3], double E[2]);
+    static void EigenSysSym(const double S[3], double Eigen[2], double &c, double &s);
+    static void MakeEigenSym(double S[3], double vap[2], double c, double s);    
+    static void AffSym(double S[3], double a, double b);    
+    static void MaxSym(double S[3], double lambda);    
+    static double det(const double S[3]){return S[0]*S[2]-S[1]*S[1];}
+    static void PowSym(double S[3], double p);
+    
+private: //debugging
+    friend int main(int argc, const char * argv[]);
+};
+ 
+
+// **************** Constructor ********************
+
+TensorK::TensorK(int m_deg_, int r_deg_, triangulation_type ttype_=Graded, which_matrix wmat_=M1_alone, double p_exp_=2):
+m_deg(m_deg_), r_deg(r_deg_),  ttype(ttype_), wmat(wmat_), p_exp(p_exp_),
+t_deg((ttype_==Quasi_Acute_Proved) ? 2*(m_deg_-r_deg_) :m_deg_),
+gamma_exp(-1./((m_deg_-r_deg_)*p_exp_+d_dim)),
+homog_exp(1./((m_deg_-r_deg_)*(ttype_==Quasi_Acute_Proved ? 2. : 1.)) ),
+is_valid(m_deg_>=2 && m_deg_<=5 && r_deg_>=0 && r_deg_<=m_deg_-1 && ttype_>=0 && ttype_ <=3 && wmat_>=0 && wmat_ <=2 && p_exp_ >=0) 
+{
+    factorials.resize(t_deg+1);
+    factorials[0]=1; for(int i=1; i<=t_deg; ++i) factorials[i]=i*factorials[i-1];
+    exponents.resize(t_deg+1);
+    for(int k=1; k<=t_deg; ++k)
+        switch (ttype) {
+            case Graded:
+                exponents[k] = 1./k;
+                break;
+                
+            case Quasi_Acute:
+                exponents[k] = 1./std::min(k,m_deg-r_deg);
+                break;
+                
+            case Quasi_Acute_Unrefined:
+                exponents[k] = (k<=m_deg-r_deg) ? 1./k : 1./(k-1./p_exp);
+                break;
+                
+            case Quasi_Acute_Proved:
+                exponents[k] = 1./k;
+                break;
+        }
+}
+
+/*
+void Mc(const double * D, int m_deg, double Mc[3]);
+void M0(const double * D, int m_deg, double M0[3], const double Mc[3]){NULL;};
+void M0(const double * D, int m_deg, double M0[3]){double getMc[3]; Mc(D,m_deg,getMc); M0(D,m_deg,getMc);}
+void M1(const double * D, int m_deg, double M1[3], const double Mc[3]){NULL;};
+void M1(const double * D, int m_deg, double M1[3]){double getMc[3]; Mc(D,m_deg,getMc); M1(D,m_deg,getMc);}
+void Ms(const double * D, int m_deg, double Ms[3]);
+*/
+ 
+//void Derivatives(const double DOFt[3],  const R2 invHauteur[3], double &fx,      double &fy);
+//void Derivatives(const double DOFt[6],  const R2 invHauteur[3], double &fxx,     double &fxy,    double &fyy);
+//void Derivatives(const double DOFt[10], const R2 invHauteur[3], double &fxxx,    double &fxxy,   double &fxyy,   double &fyyy);
+//void Derivatives(const double DOFt[15], const R2 invHauteur[3], double &fxxxx,   double &fxxxy,  double &fxxyy,  double &fxyyy, double &fyyyy);
+
+// ********************* Matrices **********************
+
+void TensorK::getMc(const double * D, double Mc[3]) const {
+    Mc[0]=0; Mc[1]=0; Mc[2]=0;
+    for(int i=0; i<t_deg; ++i){
+        Mc[0]+=binomial(t_deg-1,i)*D[i]*D[i];
+        Mc[1]+=binomial(t_deg-1,i)*D[i]*D[i+1];
+        Mc[2]+=binomial(t_deg-1,i)*D[i+1]*D[i+1];
+    }
+}
+
+void TensorK::getM0(const double E[2], double c, double s, double M0[3]) const {    //size required : D[t_deg+1] 
+    double EPow[2]={pow(2*E[0],homog_exp), pow(2*E[1],homog_exp)};
+    MakeEigenSym(M0,EPow,c,s);
+}
+
+void TensorK::getM1(const double *D, double c, double s, double M1[3]) const {
+    double DChg[t_deg+1]; rotate(D,DChg,c,-s);
+    double DChgMax=0; for(int r=0; r<=t_deg; ++r) {DChg[r]=fabs(DChg[r]); DChgMax=max(DChgMax,DChg[r]);}
+    if(DChgMax==0) {M1[0]=0; M1[1]=0; M1[2]=0; return;}
+    
+    double vap[2]={0,0}; //The eigenvalues of the matrix returned. 
+    for(int r=0; r< t_deg; ++r) vap[0]=max(vap[0], pow(DChg[r]/DChgMax, exponents[t_deg-r]) );
+    for(int r=1; r<=t_deg; ++r) vap[1]=max(vap[1], pow(DChg[r]/DChgMax, exponents[r])       );
+    
+    const double scal  = pow(DChgMax, homog_exp);
+    const double scal2 = pow(2.,m_deg*homog_exp);    
+    for(int i=0; i<2; ++i) {vap[i]*=scal; vap[i]=vap[i]*vap[i]; vap[i]*=scal2;}
+    
+    MakeEigenSym(M1,vap,c,s);
+}
+
+void TensorK::getMs(const double *D, double Ms[3]) const {
+    double Mc[3]; double E[2]; double c,s;
+    getMc(D,Mc); EigenSysSym(Mc,E,c,s);
+    switch (wmat) {
+        case M0_M1_weighted_sum:{
+            double M1[3]; getM1(D,c,s,M1);
+            double M0[3]; getM0(E,c,s,M0);
+            const double r = max(2-E[1]/E[0],0);
+            for(int i=0; i<3; ++i) Ms[i] = r*M0[i]+(1-r)*M1[i];
+            return;}
+            
+        case M1_alone:
+            getM1(D,c,s,Ms);
+            return;
+            
+        case M0_alone:
+            getM0(E,c,s,Ms);
+            return;
+            
+        default:
+            std::cout << "TensorK::getMs error ! Unsupplied case." << std::endl;
+            break;
+    }
+}
+
+void TensorK::getM(const double *D, double *M) const {
+    if(ttype==Quasi_Acute_Proved){
+        double Ds[t_deg+1]; getSquare(D, Ds);
+        getMs(Ds,M);
+    } else {
+        getMs(D,M); 
+//        const double scal = pow(M[0]+M[2], r_deg/double(m_deg-r_deg)); 
+//        M[0]*=scal; M[1]*=scal; M[2]*=scal;
+    }    
+}
+
+void TensorK::getSquare(const double *D, double *Ds) const {
+    assert(ttype==Quasi_Acute_Proved);
+    //    if(!quasi_acute) {
+    //        for(int i=0; i<=m_deg; ++i) Ds[i]=D[i]; 
+    //        return;
+    //    }   
+    
+    const int diff_deg = m_deg-r_deg; assert(2*diff_deg == t_deg);
+    for(int i=0; i<=t_deg; ++i) Ds[i]=0;
+    for(int r=0; r<=r_deg; ++r){
+        const double * const Dr= D+r;
+        for(int p=0; p<=diff_deg; ++p)
+            for(int q=0; q<=diff_deg; ++q){
+                Ds[p+q]+=binomial(diff_deg,p)*binomial(diff_deg,q)/binomial(t_deg, p+q)*Dr[p]*Dr[q];
+            }
+    }
+}
+
+void TensorK::rotate(const double *D, double *Dr, double c, double s) const {
+    for(int i=0; i<=t_deg; ++i) Dr[i]=0;
+    
+    double cpow[t_deg+1]; cpow[0]=1; for(int i=1; i<=t_deg; ++i) cpow[i]=c*cpow[i-1];
+    double spow[t_deg+1]; spow[0]=1; for(int i=1; i<=t_deg; ++i) spow[i]=s*spow[i-1];
+    double parity[t_deg+1]; parity[0]=1; for(int i=1; i<=t_deg; ++i) parity[i]=-parity[i-1];
+    
+    for(int i=0; i<=t_deg; ++i){
+        const int j=t_deg-i;
+        for(int p=0; p<=i; ++p){
+            const int q=i-p;
+            for(int u=0; u<=j; ++u){
+                const int v=j-u;
+                Dr[p+u]+=D[i]*binomial(t_deg,i)*binomial(i,p)*binomial(j,u)/binomial(t_deg,p+u)*cpow[p+v]*spow[q+u]*parity[q];
+            }
+        }
+    }
+}
+
+void TensorK::equilibrate(const double M[3], double Me[3]) const {
+    const double scal = pow(det(M),gamma_exp);
+    for(int i=0; i<3; ++i) Me[i] = scal*M[i];
+}; //Me = (det M)^(-1/((m-r)p+d)) M
+
+//    void getM0(const double *D, double M0[3]){
+//        double Mc[3]; double E[2]; double c,s;
+//        getMc(D,Mc); EigenSysSym(Mc,E,c,s);
+//        getM0(E,c,s,M0);
+//    }
+//    void getM1(const double *D, double M1[3]){
+//        double Mc[3]; double E[2]; double c,s;
+//        getMc(D,Mc); EigenSysSym(Mc,E,c,s);
+//        getM1(D,c,s,M1);
+//    }
+
+// ******************** Matrix Utilities ********************
+
+void TensorK::EigenSym(const double S[3], double E[2]){
+    double hDiff = sqrt( square(S[0]-S[2])/4 + square(S[1]));
+    double hSum = (S[0]+S[2])/2;
+    E[0] = hSum-hDiff;
+    E[1] = hSum+hDiff;
+    return;
+}
+
+void TensorK::EigenSysSym(const double S[3], double Eigen[2], double &c, double &s){
+    EigenSym(S,Eigen);//calcul des valeurs propres de la matrice Mc, dans l'ordre croissant
+    const double div = Eigen[0]*Eigen[0] - Eigen[1]*Eigen[1]; 
+    if(div == 0.){ c=1; s=0;} //si les vap sont égales (la matrice est positive)
+    else{
+        c = (Eigen[0]*S[0] - Eigen[1]*S[2])/div;
+        c= c>=0 ? sqrt(c) : 0; //normalement toujours positif
+        s = (Eigen[0]*S[2]-Eigen[1]*S[0])/div;
+        s= s>=0 ? sqrt(s) : 0; //idem
+        s= (Eigen[0]-Eigen[1])*S[1]>0 ? s : -s;
+    }
+}
+
+void TensorK::MakeEigenSym(double S[3], double vap[2], double c, double s){
+    S[0] = vap[0]*c*c+vap[1]*s*s;
+    S[1] = (vap[0]-vap[1])*c*s;
+    S[2] = vap[0]*s*s+vap[1]*c*c;
+}
+
+void TensorK::AffSym(double S[3], double a, double b){
+    S[0] = a*S[0]+b;
+    S[1] = a*S[1];
+    S[2] = a*S[2]+b;
+}
+
+void TensorK::MaxSym(double S[3], double lambda){
+    double E[2];
+    EigenSym(S,E);
+    if(lambda <= E[0]) return;
+    if(E[1]	  <= lambda) {S[0] = lambda; S[1]=0; S[2] = lambda; return;};
+    AffSym(S, (E[1]-lambda)/(E[1]-E[0]), E[1] * (lambda - E[0])/(E[1] - E[0]));
+}
+
+void TensorK::PowSym(double S[3], double p){
+    double E[2]; //old eigenvalues
+    EigenSym(S,E);
+    
+    double Ep[2]; //new eigenvalues
+    if(p==-2) {Ep[0]=1/(E[0]*E[0]); Ep[1]=1/(E[1]*E[1]);}
+    else if (p==-0.5) {Ep[0]=1/sqrt(E[0]); Ep[1]=1/sqrt(E[1]);}
+    else {Ep[0]=pow(E[0],p); Ep[1]=pow(E[1],p);}
+    
+    const double diff=E[1]-E[0];
+    if(diff==0) {S[0]=Ep[0]; S[1]=0; S[2]=Ep[0]; return;} //scalar case
+    AffSym(S,(Ep[1]-Ep[0])/diff, (Ep[0]*E[1]-Ep[1]*E[0])/diff);
+}
+
+// ********************* Derivatives estimation ********************
+
+template<> void TensorK::Derivatives<2>(const std::vector<double> & DOFt, const R2 invHauteur[3], double f[2]) const {
+    f[0] = 
+    -DOFt[0]*invHauteur[0].x
+    -DOFt[1]*invHauteur[1].x
+    -DOFt[2]*invHauteur[2].x;
+    
+    f[1]=
+    -DOFt[0]*invHauteur[0].y
+    -DOFt[1]*invHauteur[1].y
+    -DOFt[2]*invHauteur[2].y;
+}
+
+template<> void TensorK::Derivatives<3>(const std::vector<double> & DOFt, const R2 invHauteur[3], double f[3]) const {
+    f[0] = 
+    4*DOFt[0]*invHauteur[0].x*invHauteur[0].x+
+    4*DOFt[1]*invHauteur[1].x*invHauteur[1].x+
+    4*DOFt[2]*invHauteur[2].x*invHauteur[2].x+
+    8*DOFt[3]*invHauteur[1].x*invHauteur[2].x+
+    8*DOFt[4]*invHauteur[2].x*invHauteur[0].x+
+    8*DOFt[5]*invHauteur[0].x*invHauteur[1].x; //dérivée seconde en x de la fonction P2 sur le triangle d'intérêt.
+    
+    f[1] = 
+    4*DOFt[0]*invHauteur[0].x*invHauteur[0].y+
+    4*DOFt[1]*invHauteur[1].x*invHauteur[1].y+
+    4*DOFt[2]*invHauteur[2].x*invHauteur[2].y+
+    4*DOFt[3]*(invHauteur[1].x*invHauteur[2].y+invHauteur[1].y*invHauteur[2].x)+
+    4*DOFt[4]*(invHauteur[2].x*invHauteur[0].y+invHauteur[2].y*invHauteur[0].x)+
+    4*DOFt[5]*(invHauteur[0].x*invHauteur[1].y+invHauteur[0].y*invHauteur[1].x);
+    
+    f[2] = 
+    4*DOFt[0]*invHauteur[0].y*invHauteur[0].y+
+    4*DOFt[1]*invHauteur[1].y*invHauteur[1].y+
+    4*DOFt[2]*invHauteur[2].y*invHauteur[2].y+
+    8*DOFt[3]*invHauteur[1].y*invHauteur[2].y+
+    8*DOFt[4]*invHauteur[2].y*invHauteur[0].y+
+    8*DOFt[5]*invHauteur[0].y*invHauteur[1].y;
+}
+
+template<> void TensorK::Derivatives<4>(const std::vector<double> & DOFt, const R2 invHauteur[3], double f[4]) const {
+    f[0] =-6.*(
+               (9./2.)  *DOFt[0]    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x+
+               (9./2.)  *DOFt[1]    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x+
+               (9./2.)  *DOFt[2]    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x+
+               (27./2.) *DOFt[3]    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[2].x+
+               (27./2.) *DOFt[4]    *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].x+
+               (27./2.) *DOFt[5]    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[0].x+
+               (27./2.) *DOFt[6]    *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].x+
+               (27./2.) *DOFt[7]    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[1].x+
+               (27./2.) *DOFt[8]    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].x+
+               27.      *DOFt[9]    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[2].x
+               ); 
+    
+    f[1] =-6.*(
+               (9./2.)  *DOFt[0]    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].y+
+               (9./2.)  *DOFt[1]    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].y+
+               (9./2.)  *DOFt[2]    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].y+
+               (27./2.) *DOFt[3]    *(invHauteur[1].x    *invHauteur[1].x    *invHauteur[2].y*(1./3.)+
+                                      invHauteur[1].y    *invHauteur[1].x    *invHauteur[2].x*(2./3.))+
+               (27./2.) *DOFt[4]    *(invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].y*(2./3.)+
+                                      invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].x*(1./3.))+
+               (27./2.) *DOFt[5]    *(invHauteur[2].x    *invHauteur[2].x    *invHauteur[0].y*(1./3.)+
+                                      invHauteur[2].y    *invHauteur[2].x    *invHauteur[0].x*(2./3.))+
+               (27./2.) *DOFt[6]    *(invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].y*(2./3.)+
+                                      invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].x*(1./3.))+
+               (27./2.) *DOFt[7]    *(invHauteur[0].x    *invHauteur[0].x    *invHauteur[1].y*(1./3.)+
+                                      invHauteur[0].y    *invHauteur[0].x    *invHauteur[1].x*(2./3.))+
+               (27./2.) *DOFt[8]    *(invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].y*(2./3.)+
+                                      invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].x*(1./3.))+
+               27.      *DOFt[9]    *(invHauteur[0].x    *invHauteur[1].x    *invHauteur[2].y/3.+
+                                      invHauteur[0].x    *invHauteur[1].y    *invHauteur[2].x/3.+
+                                      invHauteur[0].y    *invHauteur[1].x    *invHauteur[2].x/3.)
+               ); 
+    f[2] =-6.*(
+               (9./2.)  *DOFt[0]    *invHauteur[0].x    *invHauteur[0].y    *invHauteur[0].y+
+               (9./2.)  *DOFt[1]    *invHauteur[1].x    *invHauteur[1].y    *invHauteur[1].y+
+               (9./2.)  *DOFt[2]    *invHauteur[2].x    *invHauteur[2].y    *invHauteur[2].y+
+               (27./2.) *DOFt[3]    *(invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].x*(1./3.)+
+                                      invHauteur[1].x    *invHauteur[1].y    *invHauteur[2].y*(2./3.))+
+               (27./2.) *DOFt[4]    *(invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].x*(2./3.)+
+                                      invHauteur[1].x    *invHauteur[2].y    *invHauteur[2].y*(1./3.))+
+               (27./2.) *DOFt[5]    *(invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].x*(1./3.)+
+                                      invHauteur[2].x    *invHauteur[2].y    *invHauteur[0].y*(2./3.))+
+               (27./2.) *DOFt[6]    *(invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].x*(2./3.)+
+                                      invHauteur[2].x    *invHauteur[0].y    *invHauteur[0].y*(1./3.))+
+               (27./2.) *DOFt[7]    *(invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].x*(1./3.)+
+                                      invHauteur[0].x    *invHauteur[0].y    *invHauteur[1].y*(2./3.))+
+               (27./2.) *DOFt[8]    *(invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].x*(2./3.)+
+                                      invHauteur[0].x    *invHauteur[1].y    *invHauteur[1].y*(1./3.))+
+               27.      *DOFt[9]    *(invHauteur[0].y    *invHauteur[1].y    *invHauteur[2].x/3.+
+                                      invHauteur[0].y    *invHauteur[1].x    *invHauteur[2].y/3.+
+                                      invHauteur[0].x    *invHauteur[1].y    *invHauteur[2].y/3.)
+               ); 
+    
+    f[3] =-6.*(
+               (9./2.)  *DOFt[0]    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y+
+               (9./2.)  *DOFt[1]    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y+
+               (9./2.)  *DOFt[2]    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y+
+               (27./2.) *DOFt[3]    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].y+
+               (27./2.) *DOFt[4]    *invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].y+
+               (27./2.) *DOFt[5]    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].y+
+               (27./2.) *DOFt[6]    *invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].y+
+               (27./2.) *DOFt[7]    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].y+
+               (27./2.) *DOFt[8]    *invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].y+
+               27.      *DOFt[9]    *invHauteur[0].y    *invHauteur[1].y    *invHauteur[2].y
+               ); 
+}
+
+template<> void TensorK::Derivatives<5>(const std::vector<double> & DOFt, const R2 invHauteur[3], double f[5]) const {
+    f[0] =
+    (32./3.)    *DOFt[0]   *24 *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x+
+    (32./3.)    *DOFt[1]   *24 *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x+
+    (32./3.)    *DOFt[2]   *24 *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x+
+    (128./3.)   *DOFt[3]   *24 *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[2].x+
+    64          *DOFt[4]   *24 *invHauteur[1].x    *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].x+
+    (128./3.)   *DOFt[5]   *24 *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x+
+    (128./3.)   *DOFt[6]   *24 *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[0].x+
+    64          *DOFt[7]   *24 *invHauteur[2].x    *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].x+
+    (128./3.)   *DOFt[8]   *24 *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x+
+    (128./3.)   *DOFt[9]   *24 *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[1].x+
+    64          *DOFt[10]  *24 *invHauteur[0].x    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].x+
+    (128./3.)   *DOFt[11]  *24 *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x+
+    128.        *DOFt[12]  *24 *invHauteur[0].x    *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].x+
+    128.        *DOFt[13]  *24 *invHauteur[2].x    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].x+
+    128.        *DOFt[14]  *24 *invHauteur[1].x    *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].x;
+    
+    f[1] =
+    (32./3.)    *DOFt[0]   *24 *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].y+
+    (32./3.)    *DOFt[1]   *24 *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].y+
+    (32./3.)    *DOFt[2]   *24 *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].y+
+    
+    (128./3.)   *DOFt[3]   *(6 *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[2].y+
+                             18*invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].y    *invHauteur[2].x)+
+    64          *DOFt[4]   *(12*invHauteur[1].x    *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].y+
+                             12*invHauteur[1].x    *invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].x)+
+    (128./3.)   *DOFt[5]   *(18*invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].y+
+                             6 *invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x)+
+    
+    (128./3.)   *DOFt[6]   *(6 *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[0].y+
+                             18*invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].y    *invHauteur[0].x)+
+    64          *DOFt[7]   *(12*invHauteur[2].x    *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].y+
+                             12*invHauteur[2].x    *invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].x)+
+    (128./3.)   *DOFt[8]   *(18*invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].y+
+                             6 *invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x)+
+    
+    (128./3.)   *DOFt[9]   *(6 *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[1].y+
+                             18*invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].y    *invHauteur[1].x)+
+    64          *DOFt[10]  *(12*invHauteur[0].x    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].y+
+                             12*invHauteur[0].x    *invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].x)+
+    (128./3.)   *DOFt[11]  *(18*invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].y+
+                             6 *invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].x)+
+    
+    128.        *DOFt[12]  *(12*invHauteur[0].x    *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].y+
+                             6 *invHauteur[0].x    *invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].x+
+                             6 *invHauteur[0].y    *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].x)+
+    128.        *DOFt[13]  *(12*invHauteur[2].x    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].y+
+                             6 *invHauteur[2].x    *invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].x+
+                             6 *invHauteur[2].y    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].x)+
+    128.        *DOFt[14]  *(12*invHauteur[1].x    *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].y+
+                             6 *invHauteur[1].x    *invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].x+
+                             6 *invHauteur[1].y    *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].x);
+    
+    f[2] = 
+    (32./3.)    *DOFt[0]   *24 *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].y    *invHauteur[0].y+
+    (32./3.)    *DOFt[1]   *24 *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].y    *invHauteur[1].y+
+    (32./3.)    *DOFt[2]   *24 *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].y    *invHauteur[2].y+
+    
+    (128./3.)   *DOFt[3]   *(12*invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].y    *invHauteur[2].y+
+                             12*invHauteur[1].x    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].x)+
+    64          *DOFt[4]   *(4 *invHauteur[1].x    *invHauteur[1].x    *invHauteur[2].y    *invHauteur[2].y+
+                             16*invHauteur[1].x    *invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].y+
+                             4 *invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].x)+
+    (128./3.)   *DOFt[5]   *(12*invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].y    *invHauteur[2].y+
+                             12*invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].y)+
+    
+    (128./3.)   *DOFt[6]   *(12*invHauteur[2].x    *invHauteur[2].x    *invHauteur[2].y    *invHauteur[0].y+
+                             12*invHauteur[2].x    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].x)+
+    64          *DOFt[7]   *(4 *invHauteur[2].x    *invHauteur[2].x    *invHauteur[0].y    *invHauteur[0].y+
+                             16*invHauteur[2].x    *invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].y+
+                             4 *invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].x)+
+    (128./3.)   *DOFt[8]   *(12*invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].y    *invHauteur[0].y+
+                             12*invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].y)+
+    
+    (128./3.)   *DOFt[9]   *(12*invHauteur[0].x    *invHauteur[0].x    *invHauteur[0].y    *invHauteur[1].y+
+                             12*invHauteur[0].x    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].x)+
+    64          *DOFt[10]  *(4 *invHauteur[0].x    *invHauteur[0].x    *invHauteur[1].y    *invHauteur[1].y+
+                             16*invHauteur[0].x    *invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].y+
+                             4 *invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].x)+
+    (128./3.)   *DOFt[11]  *(12*invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].y    *invHauteur[1].y+
+                             12*invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].x    *invHauteur[1].y)+
+    
+    128.        *DOFt[12]  *(4 *invHauteur[0].x    *invHauteur[1].x    *invHauteur[2].y    *invHauteur[2].y+
+                             4 *invHauteur[0].y    *invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].x+
+                             8 *invHauteur[0].x    *invHauteur[1].y    *invHauteur[2].x    *invHauteur[2].y+
+                             8 *invHauteur[0].y    *invHauteur[1].x    *invHauteur[2].x    *invHauteur[2].y)+
+    128.        *DOFt[13]  *(4 *invHauteur[2].x    *invHauteur[0].x    *invHauteur[1].y    *invHauteur[1].y+
+                             4 *invHauteur[2].y    *invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].x+
+                             8 *invHauteur[2].x    *invHauteur[0].y    *invHauteur[1].x    *invHauteur[1].y+
+                             8 *invHauteur[2].y    *invHauteur[0].x    *invHauteur[1].x    *invHauteur[1].y)+
+    128.        *DOFt[14]  *(4 *invHauteur[1].x    *invHauteur[2].x    *invHauteur[0].y    *invHauteur[0].y+
+                             4 *invHauteur[1].y    *invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].x+
+                             8 *invHauteur[1].x    *invHauteur[2].y    *invHauteur[0].x    *invHauteur[0].y+
+                             8 *invHauteur[1].y    *invHauteur[2].x    *invHauteur[0].x    *invHauteur[0].y);
+    
+    f[3] =
+    (32./3.)    *DOFt[0]   *24 *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].x+
+    (32./3.)    *DOFt[1]   *24 *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].x+
+    (32./3.)    *DOFt[2]   *24 *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].x+
+    
+    (128./3.)   *DOFt[3]   *(6 *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].x+
+                             18*invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].x    *invHauteur[2].y)+
+    64          *DOFt[4]   *(12*invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].x+
+                             12*invHauteur[1].y    *invHauteur[1].x    *invHauteur[2].y    *invHauteur[2].y)+
+    (128./3.)   *DOFt[5]   *(18*invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].x+
+                             6 *invHauteur[1].x    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y)+
+    
+    (128./3.)   *DOFt[6]   *(6 *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].x+
+                             18*invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].x    *invHauteur[0].y)+
+    64          *DOFt[7]   *(12*invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].x+
+                             12*invHauteur[2].y    *invHauteur[2].x    *invHauteur[0].y    *invHauteur[0].y)+
+    (128./3.)   *DOFt[8]   *(18*invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].x+
+                             6 *invHauteur[2].x    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y)+
+    
+    (128./3.)   *DOFt[9]   *(6 *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].x+
+                             18*invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].x    *invHauteur[1].y)+
+    64          *DOFt[10]  *(12*invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].x+
+                             12*invHauteur[0].y    *invHauteur[0].x    *invHauteur[1].y    *invHauteur[1].y)+
+    (128./3.)   *DOFt[11]  *(18*invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].x+
+                             6 *invHauteur[0].x    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y)+
+    
+    128.        *DOFt[12]  *(12*invHauteur[0].y    *invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].x+
+                             6 *invHauteur[0].y    *invHauteur[1].x    *invHauteur[2].y    *invHauteur[2].y+
+                             6 *invHauteur[0].x    *invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].y)+
+    128.        *DOFt[13]  *(12*invHauteur[2].y    *invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].x+
+                             6 *invHauteur[2].y    *invHauteur[0].x    *invHauteur[1].y    *invHauteur[1].y+
+                             6 *invHauteur[2].x    *invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].y)+
+    128.        *DOFt[14]  *(12*invHauteur[1].y    *invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].x+                                                                    
+                             6 *invHauteur[1].y    *invHauteur[2].x    *invHauteur[0].y    *invHauteur[0].y+
+                             6 *invHauteur[1].x    *invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].y);
+    f[4] =
+    (32./3.)    *DOFt[0]   *24 *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y+
+    (32./3.)    *DOFt[1]   *24 *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y+
+    (32./3.)    *DOFt[2]   *24 *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y+
+    (128./3.)   *DOFt[3]   *24 *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].y+
+    64          *DOFt[4]   *24 *invHauteur[1].y    *invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].y+
+    (128./3.)   *DOFt[5]   *24 *invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y+
+    (128./3.)   *DOFt[6]   *24 *invHauteur[2].y    *invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].y+
+    64          *DOFt[7]   *24 *invHauteur[2].y    *invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].y+
+    (128./3.)   *DOFt[8]   *24 *invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y+
+    (128./3.)   *DOFt[9]   *24 *invHauteur[0].y    *invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].y+
+    64          *DOFt[10]  *24 *invHauteur[0].y    *invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].y+
+    (128./3.)   *DOFt[11]  *24 *invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].y    *invHauteur[1].y+
+    128.        *DOFt[12]  *24 *invHauteur[0].y    *invHauteur[1].y    *invHauteur[2].y    *invHauteur[2].y+
+    128.        *DOFt[13]  *24 *invHauteur[2].y    *invHauteur[0].y    *invHauteur[1].y    *invHauteur[1].y+
+    128.        *DOFt[14]  *24 *invHauteur[1].y    *invHauteur[2].y    *invHauteur[0].y    *invHauteur[0].y;
+}
+    
+void TensorK::getDerivatives(const std::vector<double> & DOFt, const R2 invHauteur[3], double *f) const {
+    assert(DOFt.size()==((m_deg+1)*m_deg)/2);
+//    [((m+1)*(m+2))/2]
+    switch(m_deg){
+        case 2: return Derivatives<2>(DOFt, invHauteur, f);
+        case 3: return Derivatives<3>(DOFt, invHauteur, f);
+        case 4: return Derivatives<4>(DOFt, invHauteur, f);
+        case 5: return Derivatives<5>(DOFt, invHauteur, f);
+    }
+}
+
+#endif
diff --git a/examples++-load/UMFPACK64.cpp b/examples++-load/UMFPACK64.cpp
new file mode 100644
index 0000000..2ef20ac
--- /dev/null
+++ b/examples++-load/UMFPACK64.cpp
@@ -0,0 +1,398 @@
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:  umfpack amd blas 
+//ff-c++-cpp-dep: 
+//  
+//  file to add UMFPACK solver with dynamic load.
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+
+#include "MatriceCreuse_tpl.hpp"
+
+#include <wchar.h>
+ 
+#ifdef HAVE_LIBUMFPACK
+extern "C" {
+#ifdef HAVE_UMFPACK_H
+#include <umfpack.h>
+#else
+#ifdef HAVE_UMFPACK_UMFPACK_H
+#include <umfpack/umfpack.h>
+#else
+#ifdef HAVE_BIG_UMFPACK_UMFPACK_H
+#include <UMFPACK/umfpack.h>
+#else
+#ifdef HAVE_UFSPARSE_UMFPACK_H
+#include <ufsparse/umfpack.h>
+#else
+#ifdef HAVE_SUITESPARSE_UMFPACK_H
+#include <suitesparse/umfpack.h>
+#else
+
+  // Defaults to a local version of the UMFPACK headers
+#include "../../download/include/umfpack.h"
+
+#endif // HAVE_SUITESPARSE_UMFPACK_H
+#endif // HAVE_UFSPARSE_UMFPACK_H
+#endif // HAVE_BIG_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_H
+}
+#endif
+template<class R>
+class SolveUMFPACK64 :   public MatriceMorse<R>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  void *Symbolic, *Numeric ;
+  int umfpackstrategy;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+public:
+  SolveUMFPACK64(const MatriceMorse<R> &A,int strategy,double ttgv, double epsilon=1e-6,
+	       double pivot=-1.,double pivot_sym=-1.  ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),
+    Symbolic(0),Numeric(0)  ,
+    umfpackstrategy(strategy),
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+    
+    int status;
+    throwassert( !A.sym() && Numeric == 0 && Symbolic==0 );
+    int n=A.n;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    
+    for(int i=0;i<UMFPACK_CONTROL;i++) Control[i]=0;
+    for(int i=0;i<UMFPACK_INFO;i++) Info[i]=0;
+    
+    umfpack_dl_defaults (Control) ;
+    Control[UMFPACK_PRL]=1;
+   // Control[UMFPACK_PIVOT_TOLERANCE]=1E-10;
+    
+    if(verbosity>4) Control[UMFPACK_PRL]=2;
+    if(tol_pivot_sym>0) Control[UMFPACK_SYM_PIVOT_TOLERANCE]=pivot_sym;
+    if(tol_pivot>0) Control[UMFPACK_PIVOT_TOLERANCE]=pivot;
+    if(umfpackstrategy>=0)   Control[UMFPACK_STRATEGY]=umfpackstrategy;
+    if(verbosity>3) { 
+      cout << "  UMFPACK (long) real  Solver Control :" ;
+      cout << "\n\t SYM_PIVOT_TOLERANCE "<< Control[UMFPACK_SYM_PIVOT_TOLERANCE];
+      cout << "\n\t PIVOT_TOLERANCE     "<< Control[UMFPACK_PIVOT_TOLERANCE];
+      cout << "\n\t PRL                 "<< Control[UMFPACK_PRL];
+      cout << "\n";      
+    }
+    //  convert   array in long ...
+    // FFCS: Win64 long pb
+#ifdef WIN64
+    KN<long long> Alg(n+1),Acl(A.nbcoef);
+#else
+    KN<long> Alg(n+1),Acl(A.nbcoef);
+#endif
+    for(int i=0;i<=n;++i)
+      Alg[i]=A.lg[i];
+
+    for(int i=0;i<A.nbcoef;++i)
+      Acl[i]=A.cl[i];
+
+    status = umfpack_dl_symbolic (n, n, Alg, Acl, A.a, &Symbolic,Control,Info) ;
+    if (status !=  0)
+    {
+      (void) umfpack_dl_report_matrix (n, n, Alg, Acl, A.a, 1, Control) ;
+
+	umfpack_dl_report_info (Control, Info) ;
+	umfpack_dl_report_status (Control, status) ;
+	cerr << "umfpack_dl_symbolic failed" << endl;
+	ExecError("umfpack_dl_symbolic failed");
+	//ffassert(0);
+    }
+
+    status = umfpack_dl_numeric (Alg, Acl, A.a, Symbolic, &Numeric,Control,Info) ;
+    if (status !=  0)
+    {
+	umfpack_dl_report_info (Control, Info) ;
+	umfpack_dl_report_status (Control, status) ;
+	cerr << "umfpack_dl_numeric failed" << endl;
+	ExecError("umfpack_dl_numeric failed");
+	ffassert(0);
+    }
+
+    if (Symbolic) umfpack_dl_free_symbolic (&Symbolic),Symbolic=0; 
+    if(verbosity>3)
+    cout << "  -- umfpack_dl_build LU " << n <<  endl;
+    if(verbosity>5)     (void)  umfpack_dl_report_info(Control,Info);
+
+  }
+  void Solver(const MatriceMorse<R> &A,KN_<R> &x,const KN_<R> &b) const  {
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    for(int i=0;i<UMFPACK_CONTROL;i++) Control[i]=0;
+    for(int i=0;i<UMFPACK_INFO;i++) Info[i]=0;
+    int n= b.N(); 
+     ffassert(A.ChecknbLine( n) && n == x.N() && A.ChecknbColumn(n) );
+    
+     umfpack_dl_defaults (Control) ;
+    //  convert   array in long ...
+     // FFCS: Win64 long pb
+#ifdef WIN64
+    KN<long long> Alg(n+1),Acl(A.nbcoef);
+#else
+    KN<long> Alg(n+1),Acl(A.nbcoef);
+#endif
+    for(int i=0;i<=n;++i)
+      Alg[i]=A.lg[i];
+
+    for(int i=0;i<A.nbcoef;++i)
+      Acl[i]=A.cl[i];
+
+     // change UMFPACK_At to UMFPACK_Aat in complex 
+    int status = umfpack_dl_solve (UMFPACK_Aat, Alg, Acl, A.a,KN_2Ptr<R>(x), KN_2Ptr<R>(b), Numeric,Control,Info) ;
+    if (status != 0)
+    {
+	umfpack_dl_report_info (Control, Info) ;
+	umfpack_dl_report_status (Control, status) ;
+	cerr << "umfpack_dl_solve failed" << endl;
+	ExecError("umfpack_dl_solve failed");
+	
+	ffassert(0);
+    }
+     if(verbosity>2)
+    cout << " -- umfpack_dl_solve,  peak Mem : " <<  long(Info[UMFPACK_PEAK_MEMORY])/(1024*1024)*Info[UMFPACK_SIZE_OF_UNIT] << "Mbytes " << endl;
+    if(verbosity>3)
+    cout << "   b min max " << b.min() << " " <<b.max() << endl;
+    if(verbosity>3)     (void)  umfpack_dl_report_info(Control,Info);
+     if(verbosity>1) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+  }
+
+  ~SolveUMFPACK64() { 
+   if(verbosity>3)
+    cout << "~SolveUMFPACK 64:" << Symbolic << " N:" << Numeric <<endl;
+    if (Symbolic)   umfpack_dl_free_symbolic  (&Symbolic),Symbolic=0; 
+    if (Numeric)    umfpack_dl_free_numeric (&Numeric),Numeric=0;
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+template<>
+class SolveUMFPACK64<Complex> :   public MatriceMorse<Complex>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  int umfpackstrategy;
+  double tgv;
+  void *Symbolic, *Numeric ;
+  double *ar,*ai;
+
+
+    double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+
+public:
+  SolveUMFPACK64(const MatriceMorse<Complex> &A,int strategy,double ttgv, double epsilon=1e-6,
+     double pivot=-1.,double pivot_sym=-1.
+) : 
+    eps(epsilon),epsr(0),umfpackstrategy(strategy),tgv(ttgv),
+    Symbolic(0),Numeric(0),
+    ar(0),ai(0),
+    tol_pivot_sym(pivot_sym), 
+    tol_pivot(pivot)
+   { 
+    int status;
+    throwassert( !A.sym());
+    int n=A.n;
+    //  copy the coef of the matrice ---
+     ar= new double[A.nbcoef];
+     ai= new double[A.nbcoef];
+     ffassert(ar && ai);
+     C2RR(A.nbcoef,A.a,ar,ai);
+        
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    umfpack_zl_defaults (Control) ;
+    Control[UMFPACK_PRL]=1;
+    if(verbosity>4) Control[UMFPACK_PRL]=2;
+   //    Control[UMFPACK_SYM_PIVOT_TOLERANCE]=1E-10;
+  //  Control[UMFPACK_PIVOT_TOLERANCE]=1E-10;
+    if(tol_pivot_sym>0) Control[UMFPACK_SYM_PIVOT_TOLERANCE]=pivot_sym;
+    if(tol_pivot>0) Control[UMFPACK_PIVOT_TOLERANCE]=pivot;
+    if(umfpackstrategy>=0) Control[UMFPACK_STRATEGY]=umfpackstrategy;
+    if(verbosity>3) { 
+      cout << "  UMFPACK(64) complex Solver Control :" ;
+      cout << "\n\t SYM_PIVOT_TOLERANCE "<< Control[UMFPACK_SYM_PIVOT_TOLERANCE];
+      cout << "\n\t PIVOT_TOLERANCE     "<< Control[UMFPACK_PIVOT_TOLERANCE];
+      cout << "\n\t PRL                 "<< Control[UMFPACK_PRL];
+      cout << "\n";      
+    }
+
+    //  convert   array in long ...
+
+    // FFCS: need a longlong on Win64 because longs are 32 bits
+#ifdef WIN64
+    KN<long long> Alg(n+1),Acl(A.nbcoef);
+#else
+    KN<long> Alg(n+1),Acl(A.nbcoef);
+#endif
+    for(int i=0;i<=n;++i)
+      Alg[i]=A.lg[i];
+
+    for(int i=0;i<A.nbcoef;++i)
+      Acl[i]=A.cl[i];
+
+
+    status = umfpack_zl_symbolic (n, n, Alg, Acl, ar,ai, &Symbolic,Control,Info) ;
+    if (status < 0)
+    {
+      (void) umfpack_zl_report_matrix (n, n, Alg, Acl, ar,ai, 1, Control) ;
+
+	umfpack_zl_report_info (Control, Info) ;
+	umfpack_zl_report_status (Control, status) ;
+	cerr << "umfpack_zl_symbolic failed" << endl;
+	ExecError("umfpack_zl_symbolic failed");
+	ffassert(0);
+	exit(2);
+    }
+
+    status = umfpack_zl_numeric (Alg, Acl, ar,ai, Symbolic, &Numeric,Control,Info) ;
+    if (status < 0)
+    {
+	umfpack_zl_report_info (Control, Info) ;
+	umfpack_zl_report_status (Control, status) ;
+	cerr << "umfpack_zl_numeric failed" << endl;
+	ExecError("umfpack_zl_numeric failed");
+	ffassert(0);
+	exit(2);
+    }
+
+    if (Symbolic) umfpack_zl_free_symbolic (&Symbolic),Symbolic=0; 
+    if(verbosity>3)
+    cout << "umfpack_zl_build LU " << n <<  endl;
+    if(verbosity>5)     (void)  umfpack_zl_report_info(Control,Info);
+
+  }
+  void Solver(const MatriceMorse<Complex> &A,KN_<Complex> &x,const KN_<Complex> &b) const  {
+        ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+     umfpack_zl_defaults (Control) ;
+     int n = b.N();
+     ffassert(A.ChecknbLine( n) && n == x.N() && A.ChecknbColumn(n) );
+     KN<double> xr(n),xi(n),br(n),bi(n);
+     C2RR(n,b,br,bi);
+     // change UMFPACK_At to UMFPACK_Aat in complex  oct 2005
+
+    //  convert   array in long ...
+     // FFCS: Win64 long pb
+#ifdef WIN64
+    KN<long long> Alg(n+1),Acl(A.nbcoef);
+#else
+    KN<long> Alg(n+1),Acl(A.nbcoef);
+#endif
+
+    for(int i=0;i<=n;++i)
+      Alg[i]=A.lg[i];
+
+    for(int i=0;i<A.nbcoef;++i)
+      Acl[i]=A.cl[i];
+
+ 
+    int status = umfpack_zl_solve (UMFPACK_Aat, Alg, Acl, ar,ai, xr, xi, br,bi, Numeric,Control,Info) ;
+    if (status < 0)
+    {
+	umfpack_zl_report_info (Control, Info) ;
+	umfpack_zl_report_status (Control, status) ;
+	cerr << "umfpack_zl_solve failed" << endl;
+	ExecError("umfpack_zl_numeric failed");
+	ffassert(0);
+	exit(2);
+    }
+    RR2C(n,xr,xi,x);
+    if(verbosity>1)
+    {
+      cout << "  -- umfpack_zl_solve,  peak Mem : " <<  long(Info[UMFPACK_PEAK_MEMORY])/(1024*1024)*Info[UMFPACK_SIZE_OF_UNIT] << "Mbytes " << endl;
+   
+     if(verbosity>3)     (void)  umfpack_zl_report_info(Control,Info);
+    
+      cout << "   b min max " << b.min() << " " <<b.max() << endl;
+      cout << "   x min max " << x.min() << " " <<x.max() << endl;
+    }
+  }
+
+  ~SolveUMFPACK64() { 
+    if(verbosity>5)
+    cout << "~SolveUMFPACK64 " << endl;
+    if (Symbolic)   umfpack_zl_free_symbolic  (&Symbolic),Symbolic=0; 
+    if (Numeric)    umfpack_zl_free_numeric (&Numeric),Numeric=0;
+    delete [] ar;
+    delete [] ai;   
+  }
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+     
+
+}; 
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildSolverIUMFPack64(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+  if( verbosity>9)
+    cout << " BuildSolverUMFPack64<double>" << endl;
+    return new SolveUMFPACK64<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+inline MatriceMorse<Complex>::VirtualSolver *
+BuildSolverIUMFPack64(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  if( verbosity>9)
+    cout << " BuildSolverUMFPack64<Complex>" << endl;
+    return new SolveUMFPACK64<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetUMFPACK64()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to IUMFPack64" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverIUMFPack64;
+    DefSparseSolver<Complex>::solver =BuildSolverIUMFPack64;    
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return  true;
+}
+
+
+void init22()
+{    
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  if(verbosity>1)
+    cout << "\n Add: UMFPACK64:  defaultsolver defaultsolverUMFPACK64" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver; 
+  DefSparseSolver<double>::solver =BuildSolverIUMFPack64;
+  DefSparseSolver<Complex>::solver =BuildSolverIUMFPack64;
+
+  if(! Global.Find("defaulttoUMFPACK64").NotNull() )
+    Global.Add("defaulttoUMFPACK64","(",new OneOperator0<bool>(SetUMFPACK64));  
+}
+
+
+LOADFUNC(init22);
diff --git a/examples++-load/VTK_writer.cpp b/examples++-load/VTK_writer.cpp
new file mode 100644
index 0000000..d6e3718
--- /dev/null
+++ b/examples++-load/VTK_writer.cpp
@@ -0,0 +1,340 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : 
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Cedric Ody (not an expert in c++)
+// E-MAIL   : cedric.listes at gmail.com
+// from the work of  Sala Lorenzo (Dxwriter)
+
+#include "mode_open.hpp"
+#include <iostream>
+#include <cfloat>
+#include <cmath>
+#include <iterator>
+using namespace std;
+#include "ff++.hpp"
+using namespace Fem2D;
+
+class VtkWriter 
+{
+ struct tsinfo
+ {
+  int imesh;//!<index of the mesh
+  std::string name;
+  std::vector<double> vecistant;
+ };
+ 
+private:
+ std::vector<Fem2D::Mesh*> _vecmesh;
+ //std::vector<tsinfo> _vecofts;
+ std::string _nameoffile;
+
+ /*! This string contains the name of data file with \\ where there's a \ in the path*/
+ std::string _nameofdatafile;
+
+ //!files containing the data and the timeseries
+ std::ofstream _ofdata;
+
+public:
+ VtkWriter() { std::cout << "Constructor of VtkWriter" << endl;  }
+ void openfiles(const std::string& s)
+  {
+   _nameoffile=s;
+   std::string tmp=s+".vtu";
+   std::cout<<tmp<<" ";
+   _ofdata.open(tmp.c_str(), std::ios_base::out);
+   _nameofdatafile="";
+   for(int i=0;i<tmp.length();++i)
+    {
+     if(tmp.at(i)=='\\')
+      _nameofdatafile.append(1,'\\');
+     _nameofdatafile.append(1,tmp.at(i));
+    }
+  }
+
+ void addmesh(Fem2D::Mesh* mesh)
+  {
+   Fem2D::Mesh& Th(*mesh);
+   _vecmesh.push_back(mesh);
+   _ofdata.flags(std::ios_base::scientific);
+   _ofdata.precision(15);
+
+   _ofdata << "<?xml version=\"1.0\"?>" << std::endl;
+   _ofdata << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" ;
+   _ofdata << std::endl;
+   _ofdata << "<UnstructuredGrid>" ; _ofdata << std::endl;
+   _ofdata << "<Piece NumberOfPoints=\"" << Th.nv << "\" NumberOfCells=\"" << Th.nt << "\">"; 
+   _ofdata << std::endl;
+   _ofdata << "<Points>" << std::endl;
+   _ofdata << "<DataArray type=\"Float32\" Name=\"Position\" NumberOfComponents=\"3\" format=\"ascii\">"; 
+   _ofdata << std::endl;
+   for(int k=0;k<Th.nv;++k) _ofdata << Th(k).x<<" "<<Th(k).y<< " " << 0.0 << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "</Points>" << std::endl;
+   _ofdata << "<Cells>" << std::endl;
+   _ofdata << "<DataArray type=\"Int32\" Name=\"connectivity\" NumberOfComponents=\"1\" format=\"ascii\">"; 
+   _ofdata << std::endl;
+   for(int i=0;i<Th.nt;++i)
+    for (int j=0; j <3; j++) _ofdata << Th(i,j) << " " ;
+   _ofdata << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "<DataArray type=\"Int32\" Name=\"offsets\" NumberOfComponents=\"1\" format=\"ascii\">"; 
+   _ofdata << std::endl;	
+   for(int i=0;i<Th.nt;++i)  _ofdata << 3+3*(i) << " ";
+   _ofdata << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "<DataArray type=\"UInt8\" Name=\"types\" NumberOfComponents=\"1\" format=\"ascii\">" ; 
+   _ofdata<< std::endl;	
+   for(int i=0;i<Th.nt;++i)  _ofdata << 5 << " ";
+   _ofdata << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "</Cells>" << std::endl; 
+   _ofdata << "<PointData >" << endl; 
+  }
+ 
+ double checkprecision(double val)
+  {
+   double tmp;
+   if ( val >= 0. ) tmp=max(0.,val);
+   if ( val <  0. ) tmp=min(0.,val);
+   return tmp;
+  }
+
+ /*!Add a field*/
+ void addscalar(const string& nameoffield, Fem2D::Mesh* mesh, const KN<double>&val)
+  {
+   _ofdata.flags(std::ios_base::scientific);
+   _ofdata.precision(15);
+
+   _ofdata << "<DataArray type=\"Float32\" Name=\"";
+   _ofdata << nameoffield<<"\" NumberOfComponents=\"1\" format=\"ascii\">";
+   _ofdata << std::endl;
+   for(int i=0;i<val.size();++i) _ofdata<<checkprecision(val[i])<<std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   
+   _ofdata.flush();
+  }
+ 
+  /*!Add a field*/
+ void addvector(const string& nameoffield, Fem2D::Mesh* mesh, const KN<double>&val, const KN<double>&val2)
+  {
+   _ofdata.flags(std::ios_base::scientific);
+   _ofdata.precision(15);
+
+   _ofdata << "<DataArray type=\"Float32\" Name=\"";
+   _ofdata << nameoffield<<"\" NumberOfComponents=\"3\" format=\"ascii\">";
+   _ofdata << std::endl;
+   for(int i=0;i<val.size();++i) _ofdata<<checkprecision(val[i])<< " " << checkprecision(val2[i]) << " " << 0.0 << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata.flush();
+  }
+
+ /*!Get the mesh associated with the series nameofts*/
+ Fem2D::Mesh* getmeshts(const string& nameofts)
+  {
+   return _vecmesh[0];
+  }
+ 
+ void init()
+  {
+   new(this)VtkWriter(); 
+  }
+ 
+ void destroy() 
+  {
+   if(_ofdata.is_open())
+    {
+     _ofdata << "</PointData>" << endl;	
+     _ofdata << "<CellData>" << endl; 	
+     _ofdata << "</CellData>" << endl; 
+     _ofdata << "</Piece>" << endl;
+     _ofdata << "</UnstructuredGrid>" << endl;
+     _ofdata << "</VTKFile>" << endl;
+     _ofdata.close(); 		
+    }
+  } 
+}; //End of class
+
+class Vtkwritesol_Op : public E_F0mps 
+{
+public:
+ typedef long  Result;
+ Expression edx;
+ Expression ename;//!<name of time series or field
+ Expression et;//!<time
+ long what; // 1 scalar, 2 vector, 3 symtensor
+ long nbfloat; // 1 scalar, n vector (3D), n symtensor(3D)
+ Expression evct,evct2;
+ 
+public:
+ Vtkwritesol_Op(const basicAC_F0 &  args) :  what(0), nbfloat(0)
+  {
+   evct=0;
+   evct2=0;
+   int nbofsol;
+   int ddim=2;
+   //There's no named parameter
+   args.SetNameParam();
+   if(args.size()!=3)
+    {
+     CompileError("Vtkwritesol accepts only 4 parameters");
+    }
+   if (BCastTo<VtkWriter *>(args[0])) edx = CastTo<VtkWriter *>(args[0]);
+   if (BCastTo<string *>(args[1])) ename = CastTo<string *>(args[1]);
+   
+   if ( args[2].left()==atype<double>() )
+    {
+     what=1;
+     nbfloat=1;
+     evct=to<double>( args[2] );
+    }
+   else if ( args[2].left()==atype<double *>() )
+    {
+     what=1;
+     nbfloat=1;
+     evct=to<double>( args[2] );
+    }
+   else if ( BCastTo<pfer>(args[2]) )
+    {
+     what=1;
+     nbfloat=1;
+     evct=to<double>( args[2] );
+    }
+   else if ( args[2].left()==atype<E_Array>() )
+    {
+     std::cout << "Until now only scalar solution" << std::endl;
+     
+     int i=2;
+     const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+         
+     if( a0->size() == ddim){
+      // vector solution
+      what=2;
+      nbfloat=a0->size();
+      evct = to<double>( (*a0)[0]);
+      evct2 = to<double>( (*a0)[1]);
+      
+     }
+      cout << "Passed Until now only scalar solution" << std::endl;
+    }
+   else 
+    {
+     CompileError("savesol in 2D: Sorry no way to save this kind of data");
+    }
+   
+  }
+ // all type
+ static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<VtkWriter *>(), atype<string *>(), true); }
+ static  E_F0 * f(const basicAC_F0 & args) { return new Vtkwritesol_Op(args);} 
+ AnyType operator()(Stack stack)  const ;
+}; // end of class
+
+
+AnyType Vtkwritesol_Op::operator()(Stack stack)  const 
+{ 
+ MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+ VtkWriter &dx=*(GetAny<VtkWriter *>((*edx)(stack)));
+ string &name=*(GetAny<string *>((*ename)(stack)));
+ //double t=GetAny<double>((*et)(stack));
+ Mesh &Th=*(dx.getmeshts(name));
+ 
+ int nt = Th.nt;
+ int nv = Th.nv;
+ 
+ int nbsol=nv;
+ long longdefault;
+ 
+ KN<double> valsol(nbsol);
+ valsol=0.;
+ KN<int> takemesh(nbsol);
+ takemesh=0;
+ MeshPoint *mp3(MeshPointStack(stack));
+ for (int it=0;it<nt;it++)
+  {
+  for(int iv=0;iv<3;iv++)
+   {
+    int i=Th(it,iv);
+    mp3->setP(&Th,it,iv);					
+    valsol[i] = valsol[i] + GetAny< double >((*evct)(stack));			
+    ++takemesh[i];
+   }
+  }
+ for(int i=0; i<nbsol; i++)
+  {
+   valsol[i] /= takemesh[i]; 
+  }
+ 
+ //Writes valsol on the file file
+ if (what==1) dx.addscalar(name,&Th,valsol);
+
+ if (what == 2)
+  {
+   KN<double> valsol2(nbsol);
+   valsol2=0.;
+   KN<int> takemesh(nbsol);
+   takemesh=0;
+   MeshPoint *mp3(MeshPointStack(stack));
+   for (int it=0;it<nt;it++)
+    {
+     for(int iv=0;iv<3;iv++)
+      {
+       int i=Th(it,iv);
+       mp3->setP(&Th,it,iv);					
+       valsol2[i] = valsol2[i] + GetAny< double >((*evct2)(stack));			
+       ++takemesh[i];
+      }
+    }
+   for(int i=0; i<nbsol; i++)
+    {
+     valsol2[i] /= takemesh[i]; 
+    }
+   
+   //Writes valsol on the file file
+   dx.addvector(name,&Th,valsol,valsol2);
+   
+  }
+
+ return longdefault;
+
+}
+
+
+
+// le vrai constructeur est la
+VtkWriter* init_VtkWriter(VtkWriter * const &a, string * const & s)
+{
+ std::cout << "start init_VtkWriter" << std::endl;
+ a->init();
+ a->openfiles(*s);
+ std::cout << "end init_VtkWriter" << std::endl;
+ return a;
+} 
+
+void* call_addmesh( VtkWriter * const & mt, Fem2D::Mesh* const & pTh) {
+  mt->addmesh(pTh);
+  return NULL;
+}
+ 
+//   Add the function name to the freefem++ table 
+/*  class Init 
+{ 
+public:
+ Init();
+};
+
+$1 */
+static void Load_Init()
+{
+ 
+ Dcl_Type<VtkWriter*>(InitP<VtkWriter>,Destroy<VtkWriter>); 
+// declare deux nouveau type pour freefem++  un pointeur et 
+
+ zzzfff->Add("VtkWriter",atype<VtkWriter*>()); // ajoute le type myType a freefem++ 
+ // constructeur  d'un type myType  dans freefem 
+ TheOperators->Add("<-", new OneOperator2_<VtkWriter*, VtkWriter* ,string*>(&init_VtkWriter));
+ Global.Add("Vtkaddmesh","(",new OneOperator2_<void *, VtkWriter*, Fem2D::Mesh*>(call_addmesh)); 
+ Global.Add("Vtkaddscalar","(",new OneOperatorCode< Vtkwritesol_Op> );
+ 
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/VTK_writer_3d.cpp b/examples++-load/VTK_writer_3d.cpp
new file mode 100644
index 0000000..3d60a7b
--- /dev/null
+++ b/examples++-load/VTK_writer_3d.cpp
@@ -0,0 +1,368 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : 
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Cedric Ody (not an expert in c++)
+// E-MAIL   : cedric.listes at gmail.com
+// from the work of  Sala Lorenzo (Dxwriter)
+
+#include "mode_open.hpp"
+#include <iostream>
+#include <cfloat>
+#include <cmath>
+#include <iterator>
+using namespace std;
+#include "ff++.hpp"
+//using namespace Fem2D;
+#include <set>
+#include <vector>
+//#include "msh3.hpp"
+
+class VtkWriter 
+{
+ struct tsinfo
+ {
+  int imesh;//!<index of the mesh
+  std::string name;
+  std::vector<double> vecistant;
+ };
+ 
+private:
+ std::vector<Mesh3*> _vecmesh;
+ //std::vector<tsinfo> _vecofts;
+ std::string _nameoffile;
+
+ /*! This string contains the name of data file with \\ where there's a \ in the path*/
+ std::string _nameofdatafile;
+
+ //!files containing the data and the timeseries
+ std::ofstream _ofdata;
+
+public:
+ VtkWriter() { std::cout << "Constructor of VtkWriter" << endl;  }
+ void openfiles(const std::string& s)
+  {
+   _nameoffile=s;
+   std::string tmp=s+".vtu";
+   std::cout<<tmp<<" ";
+   _ofdata.open(tmp.c_str(), std::ios_base::out);
+   _nameofdatafile="";
+   for(int i=0;i<tmp.length();++i)
+    {
+     if(tmp.at(i)=='\\')
+      _nameofdatafile.append(1,'\\');
+     _nameofdatafile.append(1,tmp.at(i));
+    }
+  }
+
+ void addmesh(Mesh3* mesh)
+  {
+   Mesh3& Th(*mesh);
+   _vecmesh.push_back(mesh);
+   _ofdata.flags(std::ios_base::scientific);
+   _ofdata.precision(15);
+
+   _ofdata << "<?xml version=\"1.0\"?>" << std::endl;
+   _ofdata << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << std::endl;
+   _ofdata << "<UnstructuredGrid>" << std::endl;
+   _ofdata << "<Piece NumberOfPoints=\"" << Th.nv << "\" NumberOfCells=\"" << Th.nt << "\">" << std::endl;
+   _ofdata << "<Points>" << std::endl;
+   _ofdata << "<DataArray type=\"Float32\" Name=\"Position\" NumberOfComponents=\"3\" format=\"ascii\">" << std::endl;
+   for(int k=0;k<Th.nv;++k) _ofdata << Th(k).x<<" "<<Th(k).y<< " "<<Th(k).z<<std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "</Points>" << std::endl;
+   _ofdata << "<Cells>" << std::endl;
+   _ofdata << "<DataArray type=\"Int32\" Name=\"connectivity\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;
+   for(int i=0;i<Th.nt;++i)
+    for (int j=0; j <4; j++) _ofdata << Th(i,j) << " " ;
+   _ofdata << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "<DataArray type=\"Int32\" Name=\"offsets\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;	
+   for(int i=0;i<Th.nt;++i)  _ofdata << 4+4*(i) << " ";
+   _ofdata << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "<DataArray type=\"UInt8\" Name=\"types\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;	
+   for(int i=0;i<Th.nt;++i)  _ofdata << 10 << " ";
+   _ofdata << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata << "</Cells>" << std::endl; 
+   _ofdata << "<PointData >" << endl; 
+  }
+ 
+ /*!Add a field*/
+ void addscalar(const string& nameoffield, Mesh3* mesh, const KN<double>&val)
+  {
+   _ofdata.flags(std::ios_base::scientific);
+   _ofdata.precision(15);
+
+   _ofdata << "<DataArray type=\"Float32\" Name=\""<<nameoffield<<"\" NumberOfComponents=\"1\" format=\"ascii\">" << std::endl;
+   for(int i=0;i<val.size();++i) _ofdata<<checkprecision(val[i])<<std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   
+   _ofdata.flush();
+  }
+ 
+ double checkprecision(double val)
+  {
+   double tmp;
+   if ( val >= 0. ) tmp=max(0.,val);
+   if ( val <  0. ) tmp=min(0.,val);
+   return tmp;
+  }
+
+  /*!Add a field*/
+ void addvector(const string& nameoffield, Mesh3* mesh, const KN<double>&val,
+                const KN<double>&val2,const KN<double>&val3 )
+  {
+   _ofdata.flags(std::ios_base::scientific);
+   _ofdata.precision(15);
+
+   _ofdata << "<DataArray type=\"Float32\" Name=\""<<nameoffield<<"\" NumberOfComponents=\"3\" format=\"ascii\">" << std::endl;
+   for(int i=0;i<val.size();++i) _ofdata<<checkprecision(val[i])<< " " << checkprecision(val2[i]) << " " << checkprecision(val3[i]) << std::endl;
+   _ofdata << "</DataArray>" << std::endl;
+   _ofdata.flush();
+  }
+
+
+ /*!Get the mesh associated with the series nameofts*/
+ Mesh3* getmeshts(const string& nameofts)
+  {
+   return _vecmesh[0];
+  }
+ 
+ void init()
+  {
+   new(this)VtkWriter(); 
+  }
+ 
+ void destroy() 
+  {
+   if(_ofdata.is_open())
+    {
+     _ofdata << "</PointData>" << endl;	
+     _ofdata << "<CellData>" << endl; 	
+     _ofdata << "</CellData>" << endl; 
+     _ofdata << "</Piece>" << endl;
+     _ofdata << "</UnstructuredGrid>" << endl;
+     _ofdata << "</VTKFile>" << endl;
+     _ofdata.close(); 		
+    }
+  } 
+}; //End of class
+
+class Vtkwritesol_Op : public E_F0mps 
+{
+public:
+ typedef long  Result;
+ Expression edx;
+ Expression ename;//!<name of time series or field
+ Expression et;//!<time
+ long what; // 1 scalar, 2 vector, 3 symtensor
+ long nbfloat; // 1 scalar, n vector (3D), n symtensor(3D)
+ Expression evct,evct2,evct3;
+ 
+public:
+ Vtkwritesol_Op(const basicAC_F0 &  args) :  what(0), nbfloat(0)
+  {
+   evct=0;
+   evct2=0;
+   evct3=0;
+   int nbofsol;
+   int ddim=3;
+   //There's no named parameter
+   args.SetNameParam();
+   if(args.size()!=3)
+    {
+     CompileError("Vtkwritesol accepts only 4 parameters");
+    }
+   if (BCastTo<VtkWriter *>(args[0])) edx = CastTo<VtkWriter *>(args[0]);
+   if (BCastTo<string *>(args[1])) ename = CastTo<string *>(args[1]);
+   
+   if ( args[2].left()==atype<double>() )
+    {
+     what=1;
+     nbfloat=1;
+     evct=to<double>( args[2] );
+    }
+   else if ( args[2].left()==atype<double *>() )
+    {
+     what=1;
+     nbfloat=1;
+     evct=to<double>( args[2] );
+    }
+   else if ( BCastTo<pfer>(args[2]) )
+    {
+     what=1;
+     nbfloat=1;
+     evct=to<double>( args[2] );
+    }
+   else if ( args[2].left()==atype<E_Array>() )
+    {
+     std::cout << "Until now only scalar solution" << std::endl;
+     
+     int i=2;
+     const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+       
+
+      if( a0->size() == 1){
+      // scalar solution
+      what=1;
+      nbfloat=a0->size();
+      evct = to<double>( (*a0)[0]);
+      
+     }
+  
+     if( a0->size() == ddim){
+      // vector solution
+      what=2;
+      nbfloat=a0->size();
+      evct = to<double>( (*a0)[0]);
+      evct2 = to<double>( (*a0)[1]);
+      evct3 = to<double>( (*a0)[2]);
+      
+     }
+      cout << "Passed Until now only scalar solution" << std::endl;
+    }
+   else 
+    {
+     CompileError("savesol in 2D: Sorry no way to save this kind of data");
+    }
+   
+  }
+ static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<VtkWriter *>(), atype<string *>(), true); }// all type
+ static  E_F0 * f(const basicAC_F0 & args) { return new Vtkwritesol_Op(args);} 
+ AnyType operator()(Stack stack)  const ;
+}; // end of class
+
+
+AnyType Vtkwritesol_Op::operator()(Stack stack)  const 
+{ 
+ MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+ VtkWriter &dx=*(GetAny<VtkWriter *>((*edx)(stack)));
+ string &name=*(GetAny<string *>((*ename)(stack)));
+ //double t=GetAny<double>((*et)(stack));
+ Mesh3 &Th=*(dx.getmeshts(name));
+ 
+ int nt = Th.nt;
+ int nv = Th.nv;
+ 
+ int nbsol=nv;
+ long longdefault;
+ 
+ KN<double> valsol(nbsol);
+ valsol=0.;
+ KN<int> takemesh(nbsol);
+ takemesh=0;
+ MeshPoint *mp3(MeshPointStack(stack));
+ for (int it=0;it<nt;it++)
+  {
+  for(int iv=0;iv<4;iv++)
+   {
+    int i=Th(it,iv);
+    mp3->setP(&Th,it,iv);					
+    valsol[i] = valsol[i] + GetAny< double >((*evct)(stack));			
+    ++takemesh[i];
+   }
+  }
+ for(int i=0; i<nbsol; i++)
+  {
+   valsol[i] /= takemesh[i]; 
+  }
+ 
+ //Writes valsol on the file file
+ if (what==1) 
+   dx.addscalar(name,&Th,valsol);
+
+ if (what == 2)
+  {
+   KN<double> valsol2(nbsol);
+   valsol2=0.;
+   KN<int> takemesh(nbsol);
+   takemesh=0;
+   MeshPoint *mp3(MeshPointStack(stack));
+   for (int it=0;it<nt;it++)
+    {
+     for(int iv=0;iv<4;iv++)
+      {
+       int i=Th(it,iv);
+       mp3->setP(&Th,it,iv);					
+       valsol2[i] = valsol2[i] + GetAny< double >((*evct2)(stack));			
+       ++takemesh[i];
+      }
+    }
+   for(int i=0; i<nbsol; i++)
+    {
+     valsol2[i] /= takemesh[i]; 
+    }
+   
+   {
+    KN<double> valsol3(nbsol);
+    valsol3=0.;
+    KN<int> takemesh(nbsol);
+    takemesh=0;
+    MeshPoint *mp3(MeshPointStack(stack));
+    for (int it=0;it<nt;it++)
+     {
+      for(int iv=0;iv<4;iv++)
+       {
+        int i=Th(it,iv);
+        mp3->setP(&Th,it,iv);					
+        valsol3[i] = valsol3[i] + GetAny< double >((*evct3)(stack));			
+        ++takemesh[i];
+       }
+     }
+    for(int i=0; i<nbsol; i++)
+     {
+      valsol3[i] /= takemesh[i]; 
+     }
+
+   //Writes valsol on the file file
+   dx.addvector(name,&Th,valsol,valsol2,valsol3);
+
+      }
+   
+  }
+
+ return longdefault;
+
+}
+
+
+
+// le vrai constructeur est la
+VtkWriter* init_VtkWriter(VtkWriter * const &a, string * const & s)
+{
+ std::cout << "start init_VtkWriter" << std::endl;
+ a->init();
+ a->openfiles(*s);
+ std::cout << "end init_VtkWriter" << std::endl;
+ return a;
+} 
+
+void* call_addmesh( VtkWriter * const & mt, Mesh3* const & pTh) {
+  mt->addmesh(pTh);
+  return NULL;
+}
+ 
+//   Add the function name to the freefem++ table 
+/*  class Init 
+{ 
+public:
+ Init();
+};
+
+$1 */
+static void Load_Init()
+{
+ 
+ Dcl_Type<VtkWriter*>(InitP<VtkWriter>,Destroy<VtkWriter>); // declare deux nouveau type pour freefem++  un pointeur et 
+ 
+ zzzfff->Add("VtkWriter",atype<VtkWriter*>()); // ajoute le type myType a freefem++ 
+ // constructeur  d'un type myType  dans freefem 
+ TheOperators->Add("<-", new OneOperator2_<VtkWriter*, VtkWriter* ,string*>(&init_VtkWriter));
+ Global.Add("Vtkaddmesh","(",new OneOperator2_<void *, VtkWriter*, Mesh3*>(call_addmesh)); 
+ Global.Add("Vtkaddscalar","(",new OneOperatorCode< Vtkwritesol_Op> );
+ 
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/VarIneq2.edp b/examples++-load/VarIneq2.edp
new file mode 100644
index 0000000..b1344cd
--- /dev/null
+++ b/examples++-load/VarIneq2.edp
@@ -0,0 +1,172 @@
+load "ff-NLopt"
+
+//A brief script to demonstrate how to use the freefemm interfaced nlopt routines
+//The problem consist in solving a simple variational inequality using one of the
+//optimization algorithm of nlopt. We restart the algorithlm a few times agter
+//performing some mesh adaptation to get a more precise output.
+int kas = 3; //    choose of the algo ...
+
+int NN = 10;
+mesh Th = square(NN,NN);
+func f1=1.;
+func f2=-1.;
+func g1=0.;
+func g2=0.1;
+int iter=0;
+int nadapt=2;
+real starttol=1e-6,bctol=6.e-12;
+fespace Vh(Th,P1);
+Vh oldu1,oldu2;
+
+
+for(int al=0;al<nadapt;++al)
+{
+	
+varf BVF(v,w) = int2d(Th)(0.5*dx(v)*dx(w) + 0.5*dy(v)*dy(w));
+varf LVF1(v,w) = int2d(Th)(f1*w);
+varf LVF2(v,w) = int2d(Th)(f2*w);
+matrix A =  BVF(Vh,Vh);
+real[int] b1 = LVF1(0,Vh) , b2 = LVF2(0,Vh); 
+
+varf Vbord(v,w) = on(1,2,3,4,v=1);
+Vh In,Bord;
+Bord[] = Vbord(0,Vh,tgv=1);
+In[] = Bord[] ? 0:1;
+Vh gh1=Bord*g1,gh2=Bord*g2;
+
+func real J(real[int] &X)
+{
+	Vh u1,u2;
+	u1[] = X(0:Vh.ndof-1);
+	u2[] = X(Vh.ndof:2*Vh.ndof-1);
+	iter++;
+	real[int] Au1 = A*u1[], Au2 = A*u2[];
+	Au1 -= b1;
+	Au2 -= b2;
+	real val = u1[]'*Au1 + u2[]'*Au2;
+	if(iter %10==9) 
+	plot(u1,u2,nbiso=30,fill=1,dim=3,cmm="adapt level " + al + " - iteration " + iter + " - J = " + val,value=1);
+	return val;
+}
+
+varf dBFV(v,w) = int2d(Th)(dx(v)*dx(w)+dy(v)*dy(w));
+matrix dA = dBFV(Vh,Vh);
+func real[int] dJ(real[int] &X)
+{
+	Vh u1,u2;
+	u1[] = X(0:Vh.ndof-1);
+	u2[] = X(Vh.ndof:2*Vh.ndof-1);
+	
+	real[int] grad1 = dA*u1[], grad2 = dA*u2[];
+	grad1 -= b1;
+	grad2 -= b2;
+	real[int] Grad(X.n);
+	Grad(0:Vh.ndof-1) = grad1;
+	Grad(Vh.ndof:2*Vh.ndof-1) = grad2; 
+	return Grad;
+}
+
+
+func real[int] IneqC(real[int] &X)
+{
+	real[int] constraints(Vh.ndof);
+	for(int i=0;i<Vh.ndof;++i) constraints[i] = X[i] - X[i+Vh.ndof];
+	return constraints;
+}
+func real[int,int] dIneqC(real[int] &X)
+{
+	real[int,int] dconst(Vh.ndof,2*Vh.ndof);//so sparse... shame!
+	dconst=0;
+	for(int i=0;i<Vh.ndof;++i)
+	{
+		dconst(i,i) = 1.;
+		dconst(i,i+Vh.ndof) = -1.;
+	}
+	return dconst;
+}
+
+real[int] BordIndex(Th.nbe); //Indexes of border d.f.
+{
+	int k=0;
+	for(int i=0;i<Bord.n;++i) if(Bord[][i]) {BordIndex[k]=i; ++k;}
+}
+func real[int] BC(real[int] &X)
+{
+	real[int] bc(2*Th.nbe);
+	for(int i=0;i<Th.nbe;++i)
+	{
+		int I = BordIndex[i];
+		bc[i] = X[I] - gh1[][I];
+		bc[i+Th.nbe] = X[I+Th.nv] - gh2[][I];
+	}
+	return bc;
+}
+func real[int,int] dBC(real[int] &X)
+{
+	real[int,int] dbc(2*Th.nbe,2*Th.nv);//yet sparser...:(
+	dbc=0.;
+	for(int i=0;i<Th.nbe;++i)
+	{
+		int I=BordIndex[i];
+		dbc(i,I) = 1.;
+		dbc(i+Th.nbe,I+Th.nv) = 1.;
+	}
+	return dbc;
+}
+
+
+real[int] start(2*Vh.ndof),up(2*Vh.ndof),lo(2*Vh.ndof);
+
+if(al==0)
+{
+	start(0:Vh.ndof-1) = 0.;
+	start(Vh.ndof:2*Vh.ndof-1) = 0.01;//comment this two lines and uncomment what follows to use ub and lb
+	/*Vh g1i=g1,g2i=g2;
+	start(0:Vh.ndof-1) = g1i[];
+	start(Vh.ndof:2*Vh.ndof-1) = g2i[]; */
+}
+else 
+{
+	start(0:Vh.ndof-1) = oldu1[];
+	start(Vh.ndof:2*Vh.ndof-1) = oldu2[]; 
+}
+up=1000000;
+lo=-1000000;
+for(int i=0;i<Vh.ndof;++i)
+{
+	if(Bord[][i])
+	{
+		up[i] = gh1[][i] + bctol;
+		lo[i] = gh1[][i] - bctol;
+		up[i+Vh.ndof] = gh2[][i] + bctol;
+		lo[i+Vh.ndof] = gh2[][i] - bctol;
+	}
+}
+
+//Uncomment this to use ub and lb
+/*
+real[int] diff1 = start - lo , diff2 = up - start;
+for(int i=0;i<diff1.n;++i) 
+{
+	if(diff1[i]<0) start[i]=lo[i];
+	if(diff2[i]<0) start[i]=up[i]; 
+}*/
+
+real mini=1e100;
+if(kas==1)
+   mini = nloptAUGLAG(J,start,grad=dJ,lb=lo,ub=up,IConst=IneqC,gradIConst=dIneqC,subOpt="LBFGS",stopMaxFEval=10000,stopAbsFTol=starttol);
+else if(kas==2) 
+ mini = nloptMMA(J,start,grad=dJ,lb=lo,ub=up,stopMaxFEval=10000,stopAbsFTol=starttol);
+else if(kas==3) 
+ mini = nloptAUGLAG(J,start,grad=dJ,IConst=IneqC,gradIConst=dIneqC,EConst=BC,gradEConst=dBC,subOpt="LBFGS",stopMaxFEval=200,stopRelXTol=1e-2);
+else if(kas==4) 
+ mini = nloptSLSQP(J,start,grad=dJ,IConst=IneqC,gradIConst=dIneqC,EConst=BC,gradEConst=dBC,stopMaxFEval=10000,stopAbsFTol=starttol);
+Vh best1,best2;
+best1[] = start(0:Vh.ndof-1);
+best2[] = start(Vh.ndof:2*Vh.ndof-1);
+
+Th = adaptmesh(Th,best1,best2);
+
+oldu1=best1;
+oldu2=best2;
+}
diff --git a/examples++-load/addNewType.cpp b/examples++-load/addNewType.cpp
new file mode 100644
index 0000000..7626df2
--- /dev/null
+++ b/examples++-load/addNewType.cpp
@@ -0,0 +1,81 @@
+
+// Example C++ function "CppModTemplate" dynamically loaded into "load.edp"
+// ------------------------------------------------------------------------
+#include "ff++.hpp" 
+using namespace Fem2D;
+
+// see src/femlib/RNM.hpp
+
+class myType { public:
+  string * nom;
+  myType(char * nn) { cout << " nn = " << nn << endl;  }
+  double x(double u,double v) const { return u+v;}
+  void init() { cout << " init myTpe \n" ;  nom =0;} // init des pointeur
+  void destroy() { cout << " destroy de la variable associe \n";  delete  nom;nom=0; } 
+};
+
+class myType_uv { public:
+  myType * mt;
+  double u,v;
+  myType_uv(myType * mmt,double uu,double vv): mt(mmt),u(uu),v(vv) {}
+};
+
+// le vrai constructeur est la
+myType * init_MyType(myType * const &a, string * const & s)
+{
+  a->nom = new string(* s);
+  cout << " build MyType " << *a->nom << endl;
+  return NULL; // return value never used for now (13.1)
+} 
+
+
+myType_uv set_myType_uv( myType * const & mt,const double & u,const double & v)
+{  return myType_uv(mt,u,v);}
+
+double get_myType_uv_x(const myType_uv & muv)
+{
+  return muv.mt->x(muv.u,muv.v);
+}
+
+R3 * get_myType_uv_N(const myType_uv & muv)
+{
+  static R3 r;
+  r=R3(muv.mt->x(muv.u,muv.v),0.,0.);
+  return &r;
+}
+//   Add the function name to the freefem++ table 
+/*  class Init { public:
+  Init();
+};
+$1 */
+static void Load_Init(){
+
+  Dcl_Type<myType*>(InitP<myType >,Destroy<myType>); // declare deux nouveau type pour freefem++  un pointeur et 
+  Dcl_Type<myType_uv>();
+  //  Dcl_Type<R3>();
+  //  cast d'un ** en * 
+  //  atype<myType**>()->AddCast( new E_F1_funcT<myType*,myType **>(UnRef<myType*>)); 
+
+  zzzfff->Add("myType",atype<myType*>()); // ajoute le type myType a freefem++ 
+  // constructeur  d'un type myType  dans freefem 
+  TheOperators->Add("<-", 
+		    new OneOperator2_<myType *,myType* ,string*>(&init_MyType)); 
+  // dans ff++
+  //    myType ff("qsdlqdjlqsjdlkq");
+  // ajoute la fonction  myType* (u,v) cree le type myType_uv
+  //   ff(0.1,0.6).x
+  //   deux etapes
+  //    1)  ff(u,v) -> myType_uv
+  //  ajoute la methode x sur myType_uv   ff(u,v).x 
+  // ajoute des fonction sur myType_uv
+  // 1)
+
+  atype< myType * >()->Add("(","",new OneOperator3_<myType_uv,myType *,double,double  >(set_myType_uv));  
+
+   Add<myType_uv>("x",".",new OneOperator1_<double,myType_uv>(get_myType_uv_x) );
+   Add<myType_uv>("N",".",new OneOperator1_<R3*,myType_uv>(get_myType_uv_N) );
+}
+
+
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/bfstream.cpp b/examples++-load/bfstream.cpp
new file mode 100644
index 0000000..039d40c
--- /dev/null
+++ b/examples++-load/bfstream.cpp
@@ -0,0 +1,85 @@
+// to compile ff-c++ bstream.cpp
+//  warning do not compile under windows...
+#include "ff++.hpp"
+#include <cstdio>
+#include <unistd.h>
+
+template<class T>
+class Stream_b { public:
+    Stream_b(T * ff) :f(ff) {}
+    Stream_b(T ** ff) :f(*ff) {ffassert(f); }
+    Stream_b(const Stream_b &io): f(io.f) {}
+    
+    T * f;
+};
+
+template<class T>
+ Stream_b<T>  pto_stream_b(T **f){ return Stream_b<T>(f);}
+template<class T>
+Stream_b<T>  to_stream_b(T *f){ return Stream_b<T>(f);}
+
+template<class T>
+istream * Read(Stream_b<istream> const &   io, T * const & data ) {
+    io.f->read(reinterpret_cast<char *>(data),sizeof(*data));
+    return io.f; }
+
+template<class T>
+istream * Read(Stream_b<istream> const &   io, KN<T> * const & data ) {
+     long n;
+    io.f->read(reinterpret_cast<char *>(&n),sizeof(long));
+    cout << " read  n =" << n << " " << n*sizeof(sizeof(T)) << " "  <<  endl;
+    if( n != data->N()) data->resize(n);
+    T*  p = *data;
+    io.f->read(reinterpret_cast<char *>(p),n*sizeof(T));
+    return io.f; }
+template<class T>
+ostream * Write(Stream_b<ostream> const &   io, KN<T> * const & data ) {
+    T*  p = *data;
+    long n=data->N();
+    cout << " write n =" << n << " " << n*sizeof(T) << " " << p <<  endl;
+    io.f->write(reinterpret_cast<const char *>(&n),sizeof(long));
+    io.f->write(reinterpret_cast<const char *>(p),n*sizeof(T));
+    return io.f; }
+
+template<class T>
+ostream * Write(Stream_b<ostream> const &   io, T * const & data ) {
+    io.f->write(reinterpret_cast<const char *>(data),sizeof(*data));
+    return io.f; }
+template<class T>
+ostream * Write(Stream_b<ostream> const &   io, T  const & data ) {
+    io.f->write(reinterpret_cast<const char *>(&data),sizeof(data));
+    return io.f; }
+template <class K>
+void initK()
+{
+    typedef Stream_b<ostream> OB;
+    typedef Stream_b<istream> IB;
+    Add<IB>("(","",new OneOperator2_<istream *,IB,K *>(Read));
+    Add<OB>("(","",new OneOperator2_<ostream *,OB,K *>(Write));
+    Add<OB>("(","",new OneOperator2_<ostream *,OB,K >(Write));
+    Add<IB>("(","",new OneOperator2_<istream *,IB,KN<K> *>(Read));
+    Add<OB>("(","",new OneOperator2_<ostream *,OB,KN<K> * >(Write));
+    
+}
+void inittt()
+{
+    typedef Stream_b<ostream> OB;
+    typedef Stream_b<istream> IB;
+    Dcl_Type< OB>  ();
+    Dcl_Type< IB> ();
+    
+    Add<istream**>("read",".",new OneOperator1<IB,istream**>(pto_stream_b<istream>));
+    Add<ostream**>("write",".",new OneOperator1<OB,ostream**>(pto_stream_b<ostream>));
+    initK<long>();
+    initK<double>();
+    initK<complex<double> >();
+    
+/*
+     Add<IB>("(","",new OneOperator2_<istream *,IB,double *>(Read));
+    Add<OB>("(","",new OneOperator2_<ostream *,OB,double *>(Write));
+    Add<OB>("(","",new OneOperator2_<ostream *,OB,double >(Write));
+ */
+    
+}
+
+LOADFUNC(inittt);
diff --git a/examples++-load/bfstream.edp b/examples++-load/bfstream.edp
new file mode 100644
index 0000000..e3ce3cc
--- /dev/null
+++ b/examples++-load/bfstream.edp
@@ -0,0 +1,24 @@
+load "bfstream"
+real[int] b(10),bb(1);
+for(int i=0; i< b.n; ++i)
+  b[i] = i+pi;
+cout << " " << b << endl; 
+{
+ofstream f("toto.dt");
+f.write(134);
+f.write(1.346888);
+f.write(b);
+}
+b=0;
+
+{
+real r;
+int i;
+ifstream f("toto.dt");
+f.read(i);
+f.read(r);
+f.read(bb);
+cout << i << " " << r << endl; 
+cout << bb << endl; 
+//cout << b << endl; 
+}
\ No newline at end of file
diff --git a/examples++-load/bilapMorley.edp b/examples++-load/bilapMorley.edp
new file mode 100644
index 0000000..3d44502
--- /dev/null
+++ b/examples++-load/bilapMorley.edp
@@ -0,0 +1,36 @@
+load "Morley"
+
+int n=100,nn=n+10;
+real[int] xx(nn),yy(nn);
+
+mesh Th=square(40,40);  // mesh definition of $\Omega$
+fespace Wh(Th,P2);
+fespace Vh(Th,P2Morley);      // finite element space
+// correct june 21 2007 (Thank to  Hui Zhang hzhang at mailst.xjtu.edu.cn who find the error)
+macro bilaplacien(u,v) ( dxx(u)*dxx(v)+dyy(u)*dyy(v)+2.*dxy(u)*dxy(v)) // fin macro 
+real f=1;
+Vh [u,ux,uy],[v,vx,vy];
+
+solve bilap([u,ux,uy],[v,vx,vy]) =
+    int2d(Th)(  bilaplacien(u,v) )
+   - int2d(Th)(f*v)
+   + on(1,2,3,4,u=0,ux=0,uy=0) 
+; 
+   
+plot(u,cmm="u", wait=1,fill=1);
+plot(ux,wait=1,cmm="u_x");
+plot(uy,wait=1,cmm="u_y");
+Wh uu=u;
+real umax = uu[].max; 
+int err =  (abs(umax-0.0012782) > 1e-4); 
+cout << " uu max " << umax << " ~ 0.0012782,  err = " << err << endl; 
+
+
+
+for (int i=0;i<=n;i++)
+ {
+   xx[i]=real(i)/n;
+   yy[i]=u(0.5,real(i)/n); // value of uh at point (0.5, i/10.) 
+ }
+ plot([xx(0:n),yy(0:n)],wait=1);
+ assert(err==0); 
\ No newline at end of file
diff --git a/examples++-load/bilapP3-hct-like.edp b/examples++-load/bilapP3-hct-like.edp
new file mode 100644
index 0000000..27e6ce5
--- /dev/null
+++ b/examples++-load/bilapP3-hct-like.edp
@@ -0,0 +1,44 @@
+// a trick to build C1 finite element with P3 lagrangre finite element
+// like HSIEH-CLOUCH-TOCHER finite element 
+// the idee is insure the the jump (dn(u)) on all edges 
+// by penalisatison ... 
+// not to bad ... 
+// F. Hecht juin 2014 ..
+
+load "Element_P3" // for P3
+load "splitmesh3" // to splite each triangle in 3 traingle
+
+int n=100,nn=n+10;
+real[int] xx(nn),yy(nn);
+
+mesh Th=square(20,20);  // mesh definition of $\Omega$
+//Th=splitmesh3(Th);
+fespace Vh(Th,P3);      // finite element space
+
+macro bilaplacien(u,v) ( dxx(u)*dxx(v)+dyy(u)*dyy(v)+2.*dxy(u)*dxy(v)) // fin macro 
+real f=1;
+Vh [u],[v];
+real pena = 1e6;
+macro dn(u) (dx(u)*N.x+dy(u)*N.y)//
+solve bilap([u],[v]) =
+    int2d(Th)(  bilaplacien(u,v) ) 
+  + intalledges(Th) ( jump(dn(u))*jump(dn(v))*pena) 
+   - int2d(Th)(f*v)
+   
+   + on(1,2,3,4,u=0) 
+; 
+   
+plot(u,cmm="u", wait=1,fill=1);
+real umax = u[].max; 
+int err =  (abs(umax-0.0012782) > 1e-4); 
+cout << " uu max " << umax << " ~  0.0012782  , err = " << err 
+     << " " << abs(umax-0.0012782) <<endl; 
+
+
+for (int i=0;i<=n;i++)
+ {
+   xx[i]=real(i)/n;
+   yy[i]=u(0.5,real(i)/n); // value of uh at point (0.5, i/10.) 
+ }
+ plot([xx(0:n),yy(0:n)],wait=1);
+ assert(err==0); 
\ No newline at end of file
diff --git a/examples++-load/bmo.cpp b/examples++-load/bmo.cpp
new file mode 100644
index 0000000..5074f0c
--- /dev/null
+++ b/examples++-load/bmo.cpp
@@ -0,0 +1,576 @@
+//ff-c++-LIBRARY-dep:   
+//ff-c++-cpp-dep: 
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+#include <cassert>
+#include <cmath>
+using namespace std; 
+#include "RNM.hpp"    
+#include "bmo.hpp"    
+
+int irand_(int  i)
+{
+#ifdef WIN32
+  srand(i);
+  return rand();
+#else
+  srandom(i);
+  return random();
+#endif
+}
+
+static /* Subroutine */ double  xrandme(integer ii)
+{
+
+#ifdef  WIN32
+    static double xrd2, xrd3, xrd4, xrd5, xrd6;
+    /* System generated locals */
+    int i__1, i__2, i__3, i__4;
+    double d__1;
+
+    double xilim = 2147483648.;
+    xrd2 = (d__1 = irand_(ii) / xilim, abs(d__1));
+    i__1 = irand_(ii);
+    xrd3 = (d__1 = irand_(i__1) / xilim, abs(d__1));
+    i__2 = irand_(ii);
+    i__1 = irand_(i__2);
+    xrd4 = (d__1 = irand_(i__1) / xilim, abs(d__1));
+    i__3 = irand_(ii);
+    i__2 = irand_(i__3);
+    i__1 = irand_(i__2);
+    xrd5 = (d__1 = irand_(i__1) / xilim, abs(d__1));
+    i__4 = irand_(ii);
+    i__3 = irand_(i__4);
+    i__2 = irand_(i__3);
+    i__1 = irand_(i__2);
+    xrd6 = (d__1 = irand_(i__1) / xilim, abs(d__1));
+    double xx=(xrd2 + xrd3 + xrd4 + xrd5 + xrd6) / 5.;
+#else
+    //  srandom(ii);
+  long r=random();
+  r=random();
+  const unsigned long rmax= (1UL<<31)-1;
+  double xx=  (double) r/ (double) rmax;
+#endif
+  //    cout << " \t\t\trand = " << xx << " " << ii << endl;
+  return  xx;
+} 
+
+
+static istream & Eat2LN(istream & f)
+{
+  int c;
+  while( (c=f.get()) !='\n') {cout << char(c);assert(f.good());}
+  cout << endl;
+  return f;
+}
+
+double BijanMO::main(Vect & xx,Vect & xxmin, Vect &xxmax)
+{  
+  /* Local variables */
+  double costsave;
+  integer irestart;
+  double f,  costsave0, f0;
+  Vect v(ndim), v0(ndim), x1(ndim), hgc(ndim),fpx(ndim),
+    fpx0(ndim),temp(ndim), xmin(ndim), xmax(ndim), xsave(ndim), vinit(ndim),xsave0(ndim);
+  double rho;
+  double rho0; 
+  double rho00;
+  integer iter1;
+  double  gnorm;
+  integer iterbvp, itersom;
+  double irestart2;
+  ncstr = 0;
+  nbeval = 0;
+  nbevalp = 0;
+  // init ..
+  ffassert(ndim==xx.N());
+  ffassert(ndim==xxmin.N());
+  ffassert(ndim==xxmax.N());
+  vinit=xx;
+  xmin=xxmin;
+  xmax=xxmax;
+  
+  finit=func(vinit);
+  if(debug)
+  cout  << " ndim = "<< ndim <<  endl;
+  
+  f = finit;
+  f0 = finit;
+  xopt1=xoptg=vinit;
+  if (finit < epsij) {
+    cstropt=cstr;     
+    fseulopt = fseul;
+    goto L9101;
+  }
+  epsij *= finit;
+  if(debug)
+  cout << " F = "<< finit << endl;
+  if(ncstr>0)
+    { 
+      if(debug)
+	{
+	  cout << " CSTR = " ;
+	  for(int i=0;i<ncstr;++i) 
+	    cout <<cstr[i] << " ";
+	  cout << endl;
+	}
+    }
+  if(debug)
+    cout  << finit << " "<< 1. << " "<< xoptg[0] << " "<<  xoptg[1] << " /J/  " << endl;
+  /* cccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+  
+  /* x        open(2,file='hist.J',status='unknown') */
+  /* x        open(3,file='hist.JC',status='unknown') */
+  
+  /* x        write(3,999) fseul,(cstr(ii),ii=1,ncstr) */
+  /* x        write(2,*) finit,1.,xoptg(1),xoptg(2) */
+  /* x        close(2) */
+   
+  itersom = 0;
+  costsaveming = finit;
+  irestart2=1;
+  //  cout << " ------ " <<  nbrestart << " " << nbext1 << "  " << nbbvp << endl;
+  for (irestart = 1; irestart <= nbrestart; ++irestart) 
+    {
+      xsave=vinit; 
+      irestart2 *= 2;
+      rho00 = rho000 / irestart2;
+      
+      double iter2=1;
+      for (iter1 = 1; iter1 <= nbext1; ++iter1) 
+	{
+	  costsavemin = finit;
+  	  v= xsave;
+	  iter2 *= 2;
+	  rho0 = rho00 / iter2;
+	  double iterbvp2=1;
+	  for (iterbvp = 1; iterbvp <= nbbvp; ++iterbvp) 
+	    {
+	      iterbvp2*=2;
+	      ++itersom;	     
+	      x1 = v;	
+	      rho = rho0 / iterbvp2;
+	      if(debug> 4)
+		cout << "MM " << irestart << " " << iter1 << " " << iterbvp << " " << rho 
+		     << " ------------------------------ \n";
+	      gradopt(  x1, fpx, temp, rho, f, gnorm,fpx0, hgc);
+	      
+	      if (costsaveming < epsij) 
+	        break;      
+	      if (iterbvp >= 2) 
+		tir(  v,  fpx);
+	      else 
+		rand(v);
+		
+	      v0=v;
+	      f0 = f;
+	    }
+	  if(debug)
+	    {
+	      cout.precision(15); 
+	      cout << " F = " << costsavemin << " FM = " << costsaveming << endl;
+	    }
+	  if (costsaveming < epsij) 
+	    goto L9101;
+	  
+	  
+	  costsave = f;
+	    
+	  if (iter1 >= 2) 
+		tir(  v, fpx);
+	  else 
+		rand(v);
+	    
+	  
+	  costsave0 = costsave;
+	  xsave0 = xsave;
+	  
+	}
+    }
+  
+
+  
+ L9101:
+  
+  result( xoptg, vinit);
+  cout << "-------------------------------------------\n";
+  cout.precision(15);
+  cout << " FM = " <<costsaveming << " nb eval J : " << nbeval<< " nbevalp : " <<  nbevalp <<  endl;
+  if(ncstr>0)
+    {   
+      cout << "-------------------------------------------\n";
+      cout << "F seul = " << fseulopt << endl;
+      cout << "-------------------------------------------\n";
+      cout << " CSTR = " ;
+      for(int i=0;i<ncstr;++i) 
+	cout <<cstropt[i] << " ";
+      cout << endl;
+      cout << "-------------------------------------------\n";
+      if( ndim<20)
+	{
+	  cout << " x = " ;
+	  for(int i=0;i<ndim;++i) 
+	    cout <<xoptg[i] << " ";
+	  
+	}
+      cout << "-------------------------------------------\n";
+      
+    }
+  xx= xoptg;
+  return fseulopt;
+}
+
+
+void BijanMO::tir(Vect &v, Vect &fpx)
+{
+      double fp=funcapp( v, fpx);
+      for(int i=0;i<ndim;++i)
+	{
+	  double vi=v[i],x0=xmin[i],x1=xmax[i], fpxi=-fpx[i];	  
+	  fpxi=min(fpxi,( x1-vi)*0.95);
+	  fpxi=max(fpxi,( x0-vi)*0.95);   
+	  vi = max(min(vi+fpxi ,x1),x0);
+	  v[i]=vi;
+          fpx[i]=fpxi;	  
+	}     
+}
+void BijanMO::rand(Vect &v)
+    {
+      if(diagrand)
+	{
+	  double xrdran= xrandme(nbeval+nbevalp); 
+	  for(int ii=0;ii<ndim;++ii)
+	    {
+	      v(ii)=xmin(ii)+xrdran*(xmax(ii)-xmin(ii));
+	      v(ii)=max(min(v(ii),xmax(ii)),xmin(ii));
+	    }
+	}
+      else 
+	for(int ii=0;ii<ndim;++ii)
+	  {
+	    double xrdran= xrandme(nbeval+nbevalp); 
+	    v(ii)=xmin(ii)+xrdran*(xmax(ii)-xmin(ii));
+	    v(ii)=max(min(v(ii),xmax(ii)),xmin(ii));
+	  }
+      
+    }
+ 
+ 
+
+ int BijanMO::gradopt(Vect & x1, Vect & fpx, 
+		      Vect & temp, double &rho, double  &f,
+		      double &gnorm, 
+		      Vect & fpx0, Vect & hgc)
+ {   
+   
+   /* Local variables */
+    integer ii;
+    integer igc, igr;
+    double xmod, xmod0, gamgc;
+    double xmodd, xnorm, gnorm0=0.;
+ 
+   /* Function Body */
+    f = func(x1);
+   
+   igc = typealgo;// 1 =>   CG  , other : descent 
+   hgc = 0.;
+   for (igr = 1; igr <= nbgrad; ++igr)
+     {
+       
+       xnorm =0.;
+       fpx0=fpx;
+       xnorm=fpx.norm();
+       nbeval = -nbeval;
+       funcp( x1, fpx,f);
+       nbeval = -nbeval;
+       
+       gamgc = 0.;
+       
+       if (igc == 1 && igr >= 2 && xnorm > 1e-10) 
+	 for (ii = 0; ii < ndim; ++ii) 
+	   gamgc += (fpx[ii] - fpx0[ii]) * fpx[ii] / xnorm;
+       for (ii = 0; ii < ndim; ++ii) 
+	 hgc(ii)=fpx(ii)+gamgc*hgc(ii);
+       if(debug> 5)
+       cout <<"\t\t\t"<<  rho << " "<< hgc(0) << " " << hgc(1) << "\n" ;
+       f=ropt_dicho(x1, temp, rho, hgc,f);
+
+       xmod =0.;
+       xmodd =0.;
+       for (ii = 0; ii < ndim; ++ii) 
+	 {
+	   double x0=x1(ii);
+	   x1(ii)=x1(ii)-rho*hgc(ii);
+	   x1(ii)=min(x1(ii),xmax(ii));
+	   x1(ii)=max(x1(ii),xmin(ii));
+	   xmod=xmod+abs(x1(ii)-x0);
+	   xmodd=xmodd+abs(x1(ii));
+	 }
+       if (igr == 1) 
+	 xmod0 = xmod;
+       
+       
+       f = func(x1); 
+       
+       gnorm = fpx.l2();
+       if (igr == 1)  gnorm0 = gnorm;
+       if (gnorm0 < 1e-6) 
+	 return 0;   
+       gnorm /= gnorm0;
+      if(histpath) 
+      {
+	  ofstream fhist(histpath->c_str(),ios::app);
+	  fhist.precision(16);
+	  fhist << f << " " << gnorm*gnorm0<< " ";
+	  int n1 = min(ndim,10);
+	  for(int i=0;i<n1;++i)
+		fhist << x1[i] << " ";
+      }
+      if(histcpath) 
+	   {
+	       ofstream fhist(histcpath->c_str(),ios::app);
+	       fhist.precision(16);
+	       fhist << fseul << endl;
+	       for(int i=0;i<ncstr;++i)
+		   fhist << cstr[i] << (i%4 ? '\n' : '\t') << '\t' ;
+	   }
+	 
+       if(debug>2)
+       cout << "\t\t\t "<< f << " " << gnorm*gnorm0<< " "<< x1[0]<< " "<< x1[1] << " /J/ "<<endl;
+       /* x        open(2,file='hist.J',access='append') */
+       /* x        write(2,*) f,gnorm*gnorm0,x1(1),x1(2) */
+       /* x        close(2) */
+       /* x        write(3,999) fseul,(cstr(ii),ii=1,ncstr) */
+       
+       if (f < costsaveming)
+	 {
+	   costsaveming = f;
+	   gnormsave = gnorm;
+	   cstropt=cstr;
+	   fseulopt =  fseul;
+	   xoptg=x1;
+	 }
+       
+       if (f < costsavemin) 
+	 {
+	   costsavemin = f;
+	   xopt1=x1;
+	 }
+       
+       if (f < epsij) 
+	 break;
+       if (gnorm < 1e-6 || gnorm * gnorm0 < 1e-6) 
+	 break;
+       
+       
+       /*      if(gnorm.lt.1.e-2.or.gnorm*gnorm0.lt.1.e-6.or.xmod/xmodd.lt.epsloc */
+       /*     1  .or.xmod/xmod0.lt.epsloc) goto 888 */
+     } 
+    if(debug> 3) //      
+   cout << "\t\t\t opt: rho = " << rho << " F = " << f << endl;
+   return 0;
+ } 
+ 
+ 
+double  BijanMO::ropt_dicho(Vect x, Vect temp, double &ro, Vect g, double ccout)
+{
+  integer j, l;
+  double s, fm, sd, sn, pr;
+ static  double fmin[3]={0,0,0};
+  integer numi;
+  double romin[3];
+  integer numimax;
+  
+   
+    
+   /* Function Body */
+   numi = 0;
+   numimax = 5;
+ L240:
+   romin[0] = ro *.5;
+   romin[1] = ro;
+   romin[2] = ro *2.;
+   l = 0;
+ L300:
+   fmin[l]=fun( x, temp, g, romin[l]);
+   ++l;
+   ++numi;
+   if (l==1 & fmin[0] > ccout) 
+     {   
+       ro *= .5;
+       /* ******  test d'arret */
+       if (abs(ro) <1e-5 || numi > numimax)  goto L500;
+       goto L240;
+     }   
+ L360:
+   if(l<2) goto L300;
+   if (fmin[0] < fmin[1])  goto L380;
+ L370:
+   if(l<3) goto L300;
+   if (fmin[1] <=  fmin[2] )  goto L450;
+   else  goto L420;
+   
+ L380:
+   l=3;
+   romin[2] = romin[1];
+   fmin[2] = fmin[1];
+   romin[1] = romin[0];
+   fmin[1] = fmin[0];
+   romin[0] *= .5;
+   ++numi;
+   fmin[0]= fun( x,  temp, g, romin[0]);
+   goto L360;
+ L420:
+   romin[0] = romin[1];
+   fmin[0] = fmin[1];
+   romin[1] = romin[2];
+   fmin[1] = fmin[2];
+   romin[2] *= 2.;
+   ++numi;
+   fmin[2]=fun( x, temp, g, romin[2]);
+   goto L370;
+ L450:
+    ro = romin[1];
+    if (abs( fmin[1] - fmin[2])* 2 / (fmin[1] + fmin[2]) < 1e-4 || numi > numimax)
+      goto L500;
+    
+    /* ****** calcul de ro interpole */
+    sn = 0.;
+    sd = 0.;
+    for (int i = 0; i < 3; ++i)
+      {
+	s = 0.;
+	pr = 1.;
+	for (j = 0; j <3; ++j) 
+	  {
+	    if (i != j) 
+	      {
+		s += romin[j];
+		pr *= romin[i] - romin[j];
+	      }
+	    
+	    
+	  }
+	sn += fmin[i] * s / pr;
+	sd += fmin[i] / pr;
+      }
+
+    ro = sn / sd / 2.;
+    if(debug> 5)
+    cout << "\t\t\t\tro int  = " << ro << " " << l << endl;
+ L500:
+    fm=fun(x, temp, g, ro);
+    ccout = fm;
+    if (fm > fmin[1]) 
+      {
+	ro = romin[1];
+	ccout = fmin[1];
+      }
+    if(debug> 4)
+    cout << "\t\t\t\tdicho : " << ro << " " << ccout << " " << l << endl;
+    return ccout;
+} /* ropt_dicho__ */
+
+
+double  BijanMO::fun(Vect & x,  Vect& temp, Vect& g, double ro)
+{ 
+  for(int ii=0;ii<ndim;++ii)
+   {
+     temp[ii]=x[ii]-ro*g[ii];
+     temp[ii]=max(min(temp[ii],xmax[ii]),xmin[ii]);
+   } 
+  if(debug> 5)
+  cout << "                ro = " << ro << endl;
+  return func(temp);
+}
+
+void  BijanMO::funcp(Vect &x, Vect &fpx,double f)
+{
+
+    /* Local variables */
+     double fp, x00;
+     /* Function Body */
+     nbevalp=nbevalp+1;
+     double *ok=DJ( x, fpx);     
+     if(!ok)
+       {
+	 for(int ii=0;ii<ndim;++ii)
+	   {
+	     x00 = x[ii];
+	     double epsifd=max(min(abs(x00)*epsfd,100*epsfd),epsfd/100.);
+	     if (x00 + epsifd <= xmax[ii]) 
+	       {
+		 x[ii] = x00 + epsifd;
+		 fp = func(x);
+	       } 
+	     else
+	       {
+		 x[ii] = x00 - epsifd;
+		 fp = func(x);
+		 epsifd = -epsifd;
+	       }
+	     fpx[ii] = (fp - f) / epsifd;
+	     x[ii] = x00;
+	   }
+       }	
+     
+}
+
+
+ double  BijanMO::funcapp(Vect & x, Vect &fpx)
+{
+ /* Local variables */
+  integer kk;
+  double diffucarte;
+  integer nbevalsave;
+  double diffucarte0;
+  integer kkk;
+  double xcoef,fapp;
+  
+  /* Function Body */
+    nbevalsave = min(nbeval,nbsol);
+
+    diffucarte0 = 100.;
+    diffucarte = diffucarte0;
+    double itest2=1.;
+    
+    for(int itest=0;itest<=5;++itest)
+      {
+	itest2*=2;
+        fapp = 0.;
+	fpx=0.;
+	xcoef = 0.;
+	for (kk = 0; kk <nbevalsave; ++kk) 
+	  {
+	    double d = 0.;
+	    for (kkk = 0; kkk < ndim; ++kkk)
+	      {
+		double dd = (x[kkk] - xfeval(kk,kkk)) / ( xmax[kkk] - xmin[kkk]);
+		d += dd*dd;
+	      }
+	    double vloc = exp(-d * diffucarte);
+	    fapp += feval[kk] * vloc;
+	    for (kkk = 0; kkk < ndim; ++kkk) 
+	      {
+		double  xcc = (x[kkk] - xfeval(kk,kkk)) / ( xmax[kkk] - xmin[kkk]);
+		fpx[kkk] -= diffucarte * 2 * xcc * vloc;
+	      }
+	    xcoef += vloc;
+	  }
+	if (xcoef > 1e-6)
+	  {
+	    fapp /= xcoef;
+	    fpx/= xcoef;
+	    break;
+	  }
+	else 
+	  diffucarte = diffucarte0 / itest2 ;
+      }
+    if(debug> 3)
+    cout << "                fapp = " << fapp << " " << nbeval <<  x[0] << " " << x[1]  << endl;
+    return fapp;
+}
+	
+
diff --git a/examples++-load/bmo.edp b/examples++-load/bmo.edp
new file mode 100644
index 0000000..cf9d95b
--- /dev/null
+++ b/examples++-load/bmo.edp
@@ -0,0 +1,37 @@
+load "./lgbmo"
+int n=2;
+real[int] X(n),DX(n);
+real[int] X0(n);
+for(int i=0;i<n;++i) X0[i]=0.5;
+
+func real J(real[int] & x)
+{
+  real s=n;
+  x -= X0;
+  for (int i=0;i<x.n;i++)
+    s +=(x[i]*x[i]-cos(18.*x[i]));
+  //cout << " J " << s << "       .... " << x[0] << " " << x[1] << endl;
+  return s;
+}
+
+func real[int] DJ(real[int] &x)
+{
+  x -= X0; 
+  for (int i=0;i<x.n;i++)
+    x[i]=2*x[i]+18*sin(18*x[i]);
+  //cout << " dJ "  << "       .... " << x[0] << " " << x[1] << endl;
+  return x;  // return of global variable ok 
+};
+
+for(int i=0;i<n;++i)
+  X[i]=abs(sin((i+1)/(n*2.)));
+verbosity=9;
+
+//  buggus.. 
+ 
+real  mm=0;// bmo(J,DJ,X,min=-10,max=10);
+cout << " min = " << mm << endl;
+
+cout << " x = " << X << endl;
+cout << " X0 = " << X0 << endl;
+
diff --git a/examples++-load/bmo.hpp b/examples++-load/bmo.hpp
new file mode 100644
index 0000000..22e4d51
--- /dev/null
+++ b/examples++-load/bmo.hpp
@@ -0,0 +1,103 @@
+typedef int integer;
+class BijanMO  
+  {
+  public: 
+    typedef double R;
+    typedef KN<R> Vect;
+    typedef KNM<R> Mat;
+    int debug; //  niveau de print 
+    bool diagrand;
+    int ndim;
+    int n100;
+    int nbsol;
+    Vect cstr, cstropt;
+    double finit,fseul, fseulopt;
+    integer ncstr;
+    double costsaveming, gnormsave, costsavemin;
+    integer nbeval, nbevalp;
+    Vect  feval,xoptg,xopt1;
+    Mat xfeval;
+    KN<double> xmin,xmax;
+    // data file 
+    int nbrestart,nbext1,nbbvp,nbgrad,ifd;
+    double epsfd,rho000,epsloc,epsij;
+      int typealgo; //   1 CG 
+      string * histpath;// 0 => no file
+      string * histcpath;// 0 => no file
+      BijanMO(int nndim,
+	    int wnbrestart=1,
+	    int wnbext1=1,
+	    int wnbbvp=5,
+	    int wnbgrad=5,
+	    double wepsfd=1e-5,
+	    double wrho000=100,
+	    double wepsloc=1e-4,
+	    double wepsij=1e-6,
+	    int nn100=100)
+      : debug(1),
+	diagrand(1), //  choix of diag rand vector or not. 
+	ndim(nndim),
+	n100(nn100),
+	nbsol(1000),
+	cstr(n100),cstropt(n100),
+	feval(nbsol),
+	xoptg(ndim),xopt1(ndim),xfeval(nbsol,ndim),
+	xmin(ndim),xmax(ndim),
+	nbrestart(wnbrestart),nbext1(wnbext1),
+	nbbvp(wnbbvp),nbgrad(wnbgrad),//ifd(wifd),
+	epsfd(wepsfd),rho000(wrho000),epsloc(wepsloc),epsij(wepsij),
+      typealgo(1),
+      histpath(0),
+      histcpath(0)
+    {
+      cout << nbrestart << " == " << wnbrestart << endl;
+      
+      /*   1 1 1 10 rho =1 epsloc=1e4 (unused), epsglo=1, */
+      /*      open(1,file='DATA_BMO.txt',status='unknown') */
+      /*      read(1,*) nbrestart */
+      /*      read(1,*) nbext1 */
+      /*      read(1,*) nbbvp */
+      /*      read(1,*) nbgrad */
+      /*      read(1,*) ifd,epsfd */
+      /*      read(1,*) rho000,epsloc */
+      /*      read(1,*) epsij */
+      /*      read(1,*) ndim */
+      /*      close(1) */  
+      /*<       call init(ndim,vinit,xmin,xmax)>*/
+
+
+}
+    
+
+    double main(Vect & vinit,Vect & xxmim,Vect & xxmax);
+    double  funcapp(Vect & x, Vect &fpx);
+    void    funcp(Vect &x, Vect &fpx,double f);
+    double  fun(Vect & x,  Vect& temp, Vect& g, double ro);
+    double  ropt_dicho(Vect x, Vect temp, double & ro, Vect g, double ccout);
+    int     gradopt(Vect & x1, Vect & fpx, 
+		      Vect & temp, double &rho, double  &f,
+		      double &gnorm,  
+		      Vect & fpx0, Vect & hgc);
+    void     tir( Vect &v, Vect &fpx);
+    void     rand( Vect &v);
+      
+    double func(Vect & x) 
+    {
+      double f=J(x);
+      if(nbeval>=0) 
+	{
+	  int ieval=nbeval++%nbsol;
+	  xfeval(ieval,':')=x;
+	  feval(ieval)=f;
+	}
+      return f;
+    }
+
+    virtual ~BijanMO(){}
+    // les 4 functions utilisateur 
+   // virtual void init(Vect & xinit) = 0;    
+    virtual double J( Vect & x)=0;
+    virtual R * DJ(Vect & x, Vect &fpx){return 0;} // do not existe 
+    virtual void result(Vect & xoptg,Vect &vinit){} 
+ 
+};
diff --git a/examples++-load/buildlayermesh.edp b/examples++-load/buildlayermesh.edp
new file mode 100644
index 0000000..1740676
--- /dev/null
+++ b/examples++-load/buildlayermesh.edp
@@ -0,0 +1,57 @@
+// file buildlayermesh.edp
+load "msh3"
+load "tetgen"
+// Test 1
+
+int C1=99, C2=98; // could be anything
+
+border C01(t=0,pi){ x=t;  y=0;      label=1;}
+border C02(t=0,2*pi){ x=pi; y=t;  label=1;}
+border C03(t=0,pi){ x=pi-t;  y=2*pi;    label=1;}
+border C04(t=0,2*pi){ x=0;    y=2*pi-t; label=1;}
+
+
+border C11(t=0,0.7){ x=0.5+t;  y=2.5;      label=C1;}
+border C12(t=0,2){ x=1.2;    y=2.5+t;  label=C1;}
+border C13(t=0,0.7){ x=1.2-t;  y=4.5;     label=C1;}
+border C14(t=0,2){ x=0.5;    y=4.5-t; label=C1;}
+
+
+border C21(t=0,0.7){ x= 2.3+t;     y=2.5;  label=C2;}
+border C22(t=0,2){        x=3;   y=2.5+t;  label=C2;}
+border C23(t=0,0.7){   x=3-t;     y=4.5;  label=C2;}
+border C24(t=0,2){       x=2.3;   y=4.5-t; label=C2;}
+
+mesh Th=buildmesh(    C01(10)+C02(10)+ C03(10)+C04(10)
+                    + C11(5)+C12(5)+C13(5)+C14(5) 
+                    + C21(-5)+C22(-5)+C23(-5)+C24(-5));
+
+mesh Ths=buildmesh(    C01(10)+C02(10)+ C03(10)+C04(10)
+                    + C11(5)+C12(5)+C13(5)+C14(5) );
+                    
+// construction of a box with one hole and two regions
+func zmin=0.;
+func zmax=1.;
+int MaxLayer=10;
+
+int[int] r1=[0,41];
+int[int] r2=[98,98,99,99,1,56];
+int[int] r3=[4,12];    //  The triangles of upper surface generated by the triangle in the 2D region of mesh Th of label 4 as label 12.
+int[int] r4=[4,45];    //  The triangles of lower surface generated by the triangle in the 2D region of mesh Th of label 4 as label 45.
+ 
+mesh3 Th3=buildlayers(Th, MaxLayer, zbound=[zmin,zmax], region=r1, labelmid=r2, reffaceup = r3, reffacelow = r4 );
+savemesh(Th3,"box2region1hole.mesh");
+
+
+// Construction of a sphere with tetgen 
+func XX1 = cos(y)*sin(x);
+func YY1 = sin(y)*sin(x);
+func ZZ1 = cos(x);
+
+real [int] domain = [0.,0.,0.,0,0.001];
+string test="paACQ";
+cout << endl;
+cout << "test=" << test << endl;
+mesh3 Th3sph=tetgtransfo(Ths,transfo=[XX1,YY1,ZZ1],switch=test,nbofregions=1,regionlist=domain);
+savemesh(Th3sph,"sphere2region.mesh");
+
diff --git a/examples++-load/ch.pts b/examples++-load/ch.pts
new file mode 100644
index 0000000..ae1d494
--- /dev/null
+++ b/examples++-load/ch.pts
@@ -0,0 +1,161 @@
+160
+95.91494000000001 70.24874 19.99927
+95.45166999999999 78.0317 19.99927
+88.64861000000001 72.35452 19.99927
+95.91494000000001 70.24874 .0
+88.64861000000001 72.35452 .0
+95.45166999999999 78.0317 .0
+101.609 73.69660000000001 19.99927
+101.609 73.69660000000001 .0
+102.3193 64.70634 19.99927
+110.7396 73.23895 19.99927
+102.3193 64.70634 .0
+110.7396 73.23895 .0
+111.6493 63.57484 19.99927
+111.6493 63.57484 .0
+103.681 83.57972 19.99927
+103.681 83.57972 .0
+114.881 84.66911 19.99927
+114.881 84.66911 .0
+88.66826 43.20776 14.99875
+100.9997 42.99999 14.99875
+100.9997 42.99999 19.99927
+88.66826 43.20776 19.99927
+96.14236 53.88265 19.99927
+88.66826 43.20776 7.999145
+100.9997 42.99999 7.999145
+88.66826 43.20776 .0
+100.9997 42.99999 .0
+96.14236 53.88265 .0
+84.49039000000001 53.74788000000001 19.99927
+84.49039000000001 53.74788000000001 .0
+88.10390999999999 82.75706 19.99927
+88.10390999999999 82.75706 .0
+79.39442 77.52911 19.99927
+79.39442 77.52911 .0
+82.32566 87.46838 19.99927
+82.32566 87.46838 .0
+88.00002000000001 94.99863999999999 19.99927
+88.00002000000001 94.99863999999999 .0
+81.42439 94.15633 19.99927
+74.65782 88.72342999999999 19.99927
+81.42439 94.15633 .0
+74.65782 88.72342999999999 .0
+77.99899000000001 99.99916000000001 19.99927
+77.99899000000001 99.99916000000001 .0
+81.28679999999999 64.85234 19.99927
+81.28679999999999 64.85234 .0
+71.0415 68.59220000000001 19.99927
+71.0415 68.59220000000001 .0
+69.66011 78.88523999999999 19.99927
+59.64223 74.05317999999999 19.99927
+59.64223 74.05317999999999 .0
+69.66011 78.88523999999999 .0
+63.99978 61.49994 14.99875
+63.99978 52.56022 14.99875
+63.99978 52.56022 19.99927
+63.99978 61.49994 19.99927
+72.19266 55.38196 19.99927
+63.99978 61.49994 7.999145
+63.99978 52.56022 7.999145
+63.99978 61.49994 .0
+63.99978 52.56022 .0
+72.19266 55.38196 .0
+120.2493 94.99863999999999 14.99875
+109.4986 94.99863999999999 14.99875
+109.4986 94.99863999999999 19.99927
+120.2493 94.99863999999999 19.99927
+120.2493 94.99863999999999 7.999145
+109.4986 94.99863999999999 7.999145
+120.2493 94.99863999999999 .0
+109.4986 94.99863999999999 .0
+124.7388 84.97795 19.99927
+124.7388 84.97795 .0
+131.0 74.19918 14.99875
+131.0 84.59892 14.99875
+131.0 84.59892 19.99927
+131.0 74.19918 19.99927
+131.0 74.19918 7.999145
+131.0 84.59892 7.999145
+131.0 74.19918 .0
+131.0 84.59892 .0
+120.3813 76.59695999999999 19.99927
+120.3813 76.59695999999999 .0
+68.25064999999999 97.50031 14.99875
+58.49949000000001 94.99863999999999 14.99875
+58.49949000000001 94.99863999999999 19.99927
+68.25064999999999 97.50031 19.99927
+63.59267 86.34530999999999 19.99927
+68.25064999999999 97.50031 7.999145
+58.49949000000001 94.99863999999999 7.999145
+68.25064999999999 97.50031 .0
+58.49949000000001 94.99863999999999 .0
+63.59267 86.34530999999999 .0
+94.80028000000001 86.72153 19.99927
+94.80028000000001 86.72153 .0
+120.6199 66.43869 19.99927
+116.0012 57.99874 19.99927
+120.6199 66.43869 .0
+116.0012 57.99874 .0
+91.54334 63.0891 19.99927
+91.54334 63.0891 .0
+108.4991 55.99123000000001 19.99927
+108.4991 55.99123000000001 .0
+76.33401999999999 43.41272 19.99927
+76.33401999999999 43.41272 .0
+63.99978 43.62049 14.99875
+63.99978 43.62049 19.99927
+63.99978 43.62049 7.999145
+63.99978 43.62049 .0
+76.33401999999999 43.41272 14.99875
+76.33401999999999 43.41272 7.999145
+98.75071999999999 94.99863999999999 14.99875
+88.00002000000001 94.99863999999999 14.99875
+98.75071999999999 94.99863999999999 19.99927
+98.75071999999999 94.99863999999999 7.999145
+88.00002000000001 94.99863999999999 7.999145
+98.75071999999999 94.99863999999999 .0
+131.0 94.99863999999999 14.99875
+131.0 94.99863999999999 19.99927
+131.0 94.99863999999999 7.999145
+131.0 94.99863999999999 .0
+84.11697 99.73524000000001 14.99875
+77.99899000000001 99.99916000000001 14.99875
+84.11697 99.73524000000001 19.99927
+84.11697 99.73524000000001 7.999145
+77.99899000000001 99.99916000000001 7.999145
+84.11697 99.73524000000001 .0
+59.64223 74.05317999999999 14.99875
+59.64223 74.05317999999999 7.999145
+50.87939 84.04298000000001 19.99927
+50.87939 84.04298000000001 .0
+131.0 42.99999 14.99875
+131.0 53.39972 14.99875
+131.0 53.39972 19.99927
+131.0 42.99999 19.99927
+123.5006 55.99123000000001 19.99927
+123.5006 55.99123000000001 14.99875
+131.0 42.99999 7.999145
+131.0 53.39972 7.999145
+123.5006 55.99123000000001 7.999145
+131.0 42.99999 .0
+131.0 53.39972 .0
+123.5006 55.99123000000001 .0
+131.0 63.79945 19.99927
+131.0 63.79945 .0
+131.0 63.79945 14.99875
+131.0 63.79945 7.999145
+116.0012 57.99874 14.99875
+116.0012 57.99874 7.999145
+48.75115 92.49979 14.99875
+48.75115 92.49979 19.99927
+48.75115 92.49979 7.999145
+48.75115 92.49979 .0
+50.87939 84.04298000000001 14.99875
+50.87939 84.04298000000001 7.999145
+39.0 90.00093 14.99875
+39.0 90.00093 19.99927
+39.0 90.00093 7.999145
+39.0 90.00093 .0
+108.4991 55.99123000000001 14.99875
+108.4991 55.99123000000001 7.999145
diff --git a/examples++-load/checkglumeshcube.edp b/examples++-load/checkglumeshcube.edp
new file mode 100644
index 0000000..0a0399d
--- /dev/null
+++ b/examples++-load/checkglumeshcube.edp
@@ -0,0 +1,84 @@
+// file tetgencube.edp
+// this is  a BUGGUS  file work in progress F. Hecht .... Oct 2011
+load "msh3"
+load "tetgen"
+load "medit"
+
+real x0,x1,y0,y1;
+x0=1.; x1=2.; y0=0.; y1=2*pi;
+mesh Thsq1 = square(5,35,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+func ZZ1min = 0;
+func ZZ1max = 1.5;
+func XX1 = x;
+func YY1 = y;
+
+int[int] ref31h = [0,12];
+int[int] ref31b = [0,11];
+
+mesh3 Th31h = movemesh23(Thsq1,transfo=[XX1,YY1,ZZ1max],label=ref31h,orientation=1);
+mesh3 Th31b = movemesh23(Thsq1,transfo=[XX1,YY1,ZZ1min],label=ref31b,orientation=-1);   
+
+//medit("haut",Th31h);
+//medit("bas",Th31b);
+
+/////////////////////////////////
+x0=1.; x1=2.; y0=0.; y1=1.5;
+mesh Thsq2 = square(5,8,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+func ZZ2 = y;
+func XX2 = x;
+func YY2min = 0.;
+func YY2max = 2*pi;
+
+int[int] ref32h = [0,13];
+int[int] ref32b = [0,14];
+
+mesh3 Th32h = movemesh23(Thsq2,transfo=[XX2,YY2max,ZZ2],label=ref32h,orientation=-1);  
+mesh3 Th32b = movemesh23(Thsq2,transfo=[XX2,YY2min,ZZ2],label=ref32b,orientation=1);
+
+/////////////////////////////////
+x0=0.; x1=2*pi; y0=0.; y1=1.5;
+mesh Thsq3 = square(35,8,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+func XX3min = 1.;
+func XX3max = 2.;
+
+func YY3 = x;
+func ZZ3 = y;
+
+int[int] ref33h = [0,15];
+int[int] ref33b = [0,16];
+cout << "tyty\n";
+verbosity = 4; 
+mesh3 Th33h = movemesh23(Thsq3,transfo=[XX3max,YY3,ZZ3],label=ref33h,orientation=1);  
+cout << "tyty\n";
+mesh3 Th33b = movemesh23(Thsq3,transfo=[XX3min,YY3,ZZ3],label=ref33b,orientation=-1); 
+
+////////////////////////////////
+mesh3 Th33 = Th31h+Th31b+Th32h+Th32b+Th33h+Th33b; // "gluing" surface meshs to obtain the surface of cube
+cout << "premier check" << endl;
+checkbemesh(Th33,manifolds=[ [[11,1],[12,1],[13,1],[14,1],[15,1],[16,1]] ]);
+
+
+func mv2x = x;
+func mv2y = y;
+func mv2z = -1.5+z;
+cout << "movemesh ::new mesh" <<endl;
+mesh3 Th33mv = movemesh(Th33, [mv2x,mv2y,mv2z]);
+int[int] r1=[12,11,11,21,13,23,14,24,15,25,16,26];
+cout << "change ::new mesh" <<endl;
+//medit("Th33mv",Th33mv);
+if(0) {
+Th33mv=change(Th33mv,label=r1);  // bug change if non tet in mesh .... HERE ...
+cout << "add ::new mesh" <<endl;
+mesh3 Thall = Th33+Th33mv;  // The vertex of faces of labels 11 of Th33 and Th33mv must be same. The faces of label 11 of Thall correspond to the faces of the first in the sum : Th33.
+
+medit("Thall",Thall);
+// check manifold of the two gluing mesh
+cout << "check gluing 1" << endl; 
+checkbemesh(Thall,manifolds=[ [[11,1],[12,1],[13,1],[14,1],[15,1],[16,1]] ]);
+cout << "check gluing 2" << endl; 
+checkbemesh(Thall,manifolds=[ [[11,-1],[21,1],[23,1],[24,1],[25,1],[26,1]] ]);   
+cout << "check exterior" << endl;
+checkbemesh(Thall,manifolds=[ [[12,1],[13,1],[14,1],[15,1],[16,1],[21,1],[23,1],[24,1],[25,1],[26,1]] ]); // check the exterior manifold 
+}
\ No newline at end of file
diff --git a/examples++-load/clapack.h b/examples++-load/clapack.h
new file mode 100644
index 0000000..4b28d3c
--- /dev/null
+++ b/examples++-load/clapack.h
@@ -0,0 +1,7262 @@
+/* header file for clapack 3.2.1 */
+
+#ifndef __CLAPACK_H
+#define __CLAPACK_H
+
+#ifdef __cplusplus 	
+extern "C" {	
+#endif		
+
+/* Subroutine */ int caxpy_(integer *n, complex *ca, complex *cx, integer *
+	incx, complex *cy, integer *incy);
+
+/* Subroutine */ int ccopy_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy);
+
+/* Complex */ VOID cdotc_(complex * ret_val, integer *n, complex *cx, integer 
+	*incx, complex *cy, integer *incy);
+
+/* Complex */ VOID cdotu_(complex * ret_val, integer *n, complex *cx, integer 
+	*incx, complex *cy, integer *incy);
+
+/* Subroutine */ int cgbmv_(char *trans, integer *m, integer *n, integer *kl, 
+	integer *ku, complex *alpha, complex *a, integer *lda, complex *x, 
+	integer *incx, complex *beta, complex *y, integer *incy);
+
+/* Subroutine */ int cgemm_(char *transa, char *transb, integer *m, integer *
+	n, integer *k, complex *alpha, complex *a, integer *lda, complex *b, 
+	integer *ldb, complex *beta, complex *c__, integer *ldc);
+
+/* Subroutine */ int cgemv_(char *trans, integer *m, integer *n, complex *
+	alpha, complex *a, integer *lda, complex *x, integer *incx, complex *
+	beta, complex *y, integer *incy);
+
+/* Subroutine */ int cgerc_(integer *m, integer *n, complex *alpha, complex *
+	x, integer *incx, complex *y, integer *incy, complex *a, integer *lda);
+
+/* Subroutine */ int cgeru_(integer *m, integer *n, complex *alpha, complex *
+	x, integer *incx, complex *y, integer *incy, complex *a, integer *lda);
+
+/* Subroutine */ int chbmv_(char *uplo, integer *n, integer *k, complex *
+	alpha, complex *a, integer *lda, complex *x, integer *incx, complex *
+	beta, complex *y, integer *incy);
+
+/* Subroutine */ int chemm_(char *side, char *uplo, integer *m, integer *n, 
+	complex *alpha, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *beta, complex *c__, integer *ldc);
+
+/* Subroutine */ int chemv_(char *uplo, integer *n, complex *alpha, complex *
+	a, integer *lda, complex *x, integer *incx, complex *beta, complex *y, 
+	 integer *incy);
+
+/* Subroutine */ int cher_(char *uplo, integer *n, real *alpha, complex *x, 
+	integer *incx, complex *a, integer *lda);
+
+/* Subroutine */ int cher2_(char *uplo, integer *n, complex *alpha, complex *
+	x, integer *incx, complex *y, integer *incy, complex *a, integer *lda);
+
+/* Subroutine */ int cher2k_(char *uplo, char *trans, integer *n, integer *k, 
+	complex *alpha, complex *a, integer *lda, complex *b, integer *ldb, 
+	real *beta, complex *c__, integer *ldc);
+
+/* Subroutine */ int cherk_(char *uplo, char *trans, integer *n, integer *k, 
+	real *alpha, complex *a, integer *lda, real *beta, complex *c__, 
+	integer *ldc);
+
+/* Subroutine */ int chpmv_(char *uplo, integer *n, complex *alpha, complex *
+	ap, complex *x, integer *incx, complex *beta, complex *y, integer *
+	incy);
+
+/* Subroutine */ int chpr_(char *uplo, integer *n, real *alpha, complex *x, 
+	integer *incx, complex *ap);
+
+/* Subroutine */ int chpr2_(char *uplo, integer *n, complex *alpha, complex *
+	x, integer *incx, complex *y, integer *incy, complex *ap);
+
+/* Subroutine */ int crotg_(complex *ca, complex *cb, real *c__, complex *s);
+
+/* Subroutine */ int cscal_(integer *n, complex *ca, complex *cx, integer *
+	incx);
+
+/* Subroutine */ int csrot_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy, real *c__, real *s);
+
+/* Subroutine */ int csscal_(integer *n, real *sa, complex *cx, integer *incx);
+
+/* Subroutine */ int cswap_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy);
+
+/* Subroutine */ int csymm_(char *side, char *uplo, integer *m, integer *n, 
+	complex *alpha, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *beta, complex *c__, integer *ldc);
+
+/* Subroutine */ int csyr2k_(char *uplo, char *trans, integer *n, integer *k, 
+	complex *alpha, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *beta, complex *c__, integer *ldc);
+
+/* Subroutine */ int csyrk_(char *uplo, char *trans, integer *n, integer *k, 
+	complex *alpha, complex *a, integer *lda, complex *beta, complex *c__, 
+	 integer *ldc);
+
+/* Subroutine */ int ctbmv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, complex *a, integer *lda, complex *x, integer *incx);
+
+/* Subroutine */ int ctbsv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, complex *a, integer *lda, complex *x, integer *incx);
+
+/* Subroutine */ int ctpmv_(char *uplo, char *trans, char *diag, integer *n, 
+	complex *ap, complex *x, integer *incx);
+
+/* Subroutine */ int ctpsv_(char *uplo, char *trans, char *diag, integer *n, 
+	complex *ap, complex *x, integer *incx);
+
+/* Subroutine */ int ctrmm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, complex *alpha, complex *a, integer *lda, 
+	complex *b, integer *ldb);
+
+/* Subroutine */ int ctrmv_(char *uplo, char *trans, char *diag, integer *n, 
+	complex *a, integer *lda, complex *x, integer *incx);
+
+/* Subroutine */ int ctrsm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, complex *alpha, complex *a, integer *lda, 
+	complex *b, integer *ldb);
+
+/* Subroutine */ int ctrsv_(char *uplo, char *trans, char *diag, integer *n, 
+	complex *a, integer *lda, complex *x, integer *incx);
+
+doublereal dasum_(integer *n, doublereal *dx, integer *incx);
+
+/* Subroutine */ int daxpy_(integer *n, doublereal *da, doublereal *dx, 
+	integer *incx, doublereal *dy, integer *incy);
+
+doublereal dcabs1_(doublecomplex *z__);
+
+/* Subroutine */ int dcopy_(integer *n, doublereal *dx, integer *incx, 
+	doublereal *dy, integer *incy);
+
+doublereal ddot_(integer *n, doublereal *dx, integer *incx, doublereal *dy, 
+	integer *incy);
+
+/* Subroutine */ int dgbmv_(char *trans, integer *m, integer *n, integer *kl, 
+	integer *ku, doublereal *alpha, doublereal *a, integer *lda, 
+	doublereal *x, integer *incx, doublereal *beta, doublereal *y, 
+	integer *incy);
+
+/* Subroutine */ int dgemm_(char *transa, char *transb, integer *m, integer *
+	n, integer *k, doublereal *alpha, doublereal *a, integer *lda, 
+	doublereal *b, integer *ldb, doublereal *beta, doublereal *c__, 
+	integer *ldc);
+
+/* Subroutine */ int dgemv_(char *trans, integer *m, integer *n, doublereal *
+	alpha, doublereal *a, integer *lda, doublereal *x, integer *incx, 
+	doublereal *beta, doublereal *y, integer *incy);
+
+/* Subroutine */ int dger_(integer *m, integer *n, doublereal *alpha, 
+	doublereal *x, integer *incx, doublereal *y, integer *incy, 
+	doublereal *a, integer *lda);
+
+doublereal dnrm2_(integer *n, doublereal *x, integer *incx);
+
+/* Subroutine */ int drot_(integer *n, doublereal *dx, integer *incx, 
+	doublereal *dy, integer *incy, doublereal *c__, doublereal *s);
+
+/* Subroutine */ int drotg_(doublereal *da, doublereal *db, doublereal *c__, 
+	doublereal *s);
+
+/* Subroutine */ int drotm_(integer *n, doublereal *dx, integer *incx, 
+	doublereal *dy, integer *incy, doublereal *dparam);
+
+/* Subroutine */ int drotmg_(doublereal *dd1, doublereal *dd2, doublereal *
+	dx1, doublereal *dy1, doublereal *dparam);
+
+/* Subroutine */ int dsbmv_(char *uplo, integer *n, integer *k, doublereal *
+	alpha, doublereal *a, integer *lda, doublereal *x, integer *incx, 
+	doublereal *beta, doublereal *y, integer *incy);
+
+/* Subroutine */ int dscal_(integer *n, doublereal *da, doublereal *dx, 
+	integer *incx);
+
+doublereal dsdot_(integer *n, real *sx, integer *incx, real *sy, integer *
+	incy);
+
+/* Subroutine */ int dspmv_(char *uplo, integer *n, doublereal *alpha, 
+	doublereal *ap, doublereal *x, integer *incx, doublereal *beta, 
+	doublereal *y, integer *incy);
+
+/* Subroutine */ int dspr_(char *uplo, integer *n, doublereal *alpha, 
+	doublereal *x, integer *incx, doublereal *ap);
+
+/* Subroutine */ int dspr2_(char *uplo, integer *n, doublereal *alpha, 
+	doublereal *x, integer *incx, doublereal *y, integer *incy, 
+	doublereal *ap);
+
+/* Subroutine */ int dswap_(integer *n, doublereal *dx, integer *incx, 
+	doublereal *dy, integer *incy);
+
+/* Subroutine */ int dsymm_(char *side, char *uplo, integer *m, integer *n, 
+	doublereal *alpha, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *beta, doublereal *c__, integer *ldc);
+
+/* Subroutine */ int dsymv_(char *uplo, integer *n, doublereal *alpha, 
+	doublereal *a, integer *lda, doublereal *x, integer *incx, doublereal 
+	*beta, doublereal *y, integer *incy);
+
+/* Subroutine */ int dsyr_(char *uplo, integer *n, doublereal *alpha, 
+	doublereal *x, integer *incx, doublereal *a, integer *lda);
+
+/* Subroutine */ int dsyr2_(char *uplo, integer *n, doublereal *alpha, 
+	doublereal *x, integer *incx, doublereal *y, integer *incy, 
+	doublereal *a, integer *lda);
+
+/* Subroutine */ int dsyr2k_(char *uplo, char *trans, integer *n, integer *k, 
+	doublereal *alpha, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *beta, doublereal *c__, integer *ldc);
+
+/* Subroutine */ int dsyrk_(char *uplo, char *trans, integer *n, integer *k, 
+	doublereal *alpha, doublereal *a, integer *lda, doublereal *beta, 
+	doublereal *c__, integer *ldc);
+
+/* Subroutine */ int dtbmv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *x, integer *incx);
+
+/* Subroutine */ int dtbsv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *x, integer *incx);
+
+/* Subroutine */ int dtpmv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublereal *ap, doublereal *x, integer *incx);
+
+/* Subroutine */ int dtpsv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublereal *ap, doublereal *x, integer *incx);
+
+/* Subroutine */ int dtrmm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, doublereal *alpha, doublereal *a, integer *
+	lda, doublereal *b, integer *ldb);
+
+/* Subroutine */ int dtrmv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublereal *a, integer *lda, doublereal *x, integer *incx);
+
+/* Subroutine */ int dtrsm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, doublereal *alpha, doublereal *a, integer *
+	lda, doublereal *b, integer *ldb);
+
+/* Subroutine */ int dtrsv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublereal *a, integer *lda, doublereal *x, integer *incx);
+
+doublereal dzasum_(integer *n, doublecomplex *zx, integer *incx);
+
+doublereal dznrm2_(integer *n, doublecomplex *x, integer *incx);
+
+integer icamax_(integer *n, complex *cx, integer *incx);
+
+integer idamax_(integer *n, doublereal *dx, integer *incx);
+
+integer isamax_(integer *n, real *sx, integer *incx);
+
+integer izamax_(integer *n, doublecomplex *zx, integer *incx);
+
+logical lsame_(char *ca, char *cb);
+
+doublereal sasum_(integer *n, real *sx, integer *incx);
+
+/* Subroutine */ int saxpy_(integer *n, real *sa, real *sx, integer *incx, 
+	real *sy, integer *incy);
+
+doublereal scabs1_(complex *z__);
+
+doublereal scasum_(integer *n, complex *cx, integer *incx);
+
+doublereal scnrm2_(integer *n, complex *x, integer *incx);
+
+/* Subroutine */ int scopy_(integer *n, real *sx, integer *incx, real *sy, 
+	integer *incy);
+
+doublereal sdot_(integer *n, real *sx, integer *incx, real *sy, integer *incy);
+
+doublereal sdsdot_(integer *n, real *sb, real *sx, integer *incx, real *sy, 
+	integer *incy);
+
+/* Subroutine */ int sgbmv_(char *trans, integer *m, integer *n, integer *kl, 
+	integer *ku, real *alpha, real *a, integer *lda, real *x, integer *
+	incx, real *beta, real *y, integer *incy);
+
+/* Subroutine */ int sgemm_(char *transa, char *transb, integer *m, integer *
+	n, integer *k, real *alpha, real *a, integer *lda, real *b, integer *
+	ldb, real *beta, real *c__, integer *ldc);
+
+/* Subroutine */ int sgemv_(char *trans, integer *m, integer *n, real *alpha, 
+	real *a, integer *lda, real *x, integer *incx, real *beta, real *y, 
+	integer *incy);
+
+/* Subroutine */ int sger_(integer *m, integer *n, real *alpha, real *x, 
+	integer *incx, real *y, integer *incy, real *a, integer *lda);
+
+doublereal snrm2_(integer *n, real *x, integer *incx);
+
+/* Subroutine */ int srot_(integer *n, real *sx, integer *incx, real *sy, 
+	integer *incy, real *c__, real *s);
+
+/* Subroutine */ int srotg_(real *sa, real *sb, real *c__, real *s);
+
+/* Subroutine */ int srotm_(integer *n, real *sx, integer *incx, real *sy, 
+	integer *incy, real *sparam);
+
+/* Subroutine */ int srotmg_(real *sd1, real *sd2, real *sx1, real *sy1, real 
+	*sparam);
+
+/* Subroutine */ int ssbmv_(char *uplo, integer *n, integer *k, real *alpha, 
+	real *a, integer *lda, real *x, integer *incx, real *beta, real *y, 
+	integer *incy);
+
+/* Subroutine */ int sscal_(integer *n, real *sa, real *sx, integer *incx);
+
+/* Subroutine */ int sspmv_(char *uplo, integer *n, real *alpha, real *ap, 
+	real *x, integer *incx, real *beta, real *y, integer *incy);
+
+/* Subroutine */ int sspr_(char *uplo, integer *n, real *alpha, real *x, 
+	integer *incx, real *ap);
+
+/* Subroutine */ int sspr2_(char *uplo, integer *n, real *alpha, real *x, 
+	integer *incx, real *y, integer *incy, real *ap);
+
+/* Subroutine */ int sswap_(integer *n, real *sx, integer *incx, real *sy, 
+	integer *incy);
+
+/* Subroutine */ int ssymm_(char *side, char *uplo, integer *m, integer *n, 
+	real *alpha, real *a, integer *lda, real *b, integer *ldb, real *beta, 
+	 real *c__, integer *ldc);
+
+/* Subroutine */ int ssymv_(char *uplo, integer *n, real *alpha, real *a, 
+	integer *lda, real *x, integer *incx, real *beta, real *y, integer *
+	incy);
+
+/* Subroutine */ int ssyr_(char *uplo, integer *n, real *alpha, real *x, 
+	integer *incx, real *a, integer *lda);
+
+/* Subroutine */ int ssyr2_(char *uplo, integer *n, real *alpha, real *x, 
+	integer *incx, real *y, integer *incy, real *a, integer *lda);
+
+/* Subroutine */ int ssyr2k_(char *uplo, char *trans, integer *n, integer *k, 
+	real *alpha, real *a, integer *lda, real *b, integer *ldb, real *beta, 
+	 real *c__, integer *ldc);
+
+/* Subroutine */ int ssyrk_(char *uplo, char *trans, integer *n, integer *k, 
+	real *alpha, real *a, integer *lda, real *beta, real *c__, integer *
+	ldc);
+
+/* Subroutine */ int stbmv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, real *a, integer *lda, real *x, integer *incx);
+
+/* Subroutine */ int stbsv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, real *a, integer *lda, real *x, integer *incx);
+
+/* Subroutine */ int stpmv_(char *uplo, char *trans, char *diag, integer *n, 
+	real *ap, real *x, integer *incx);
+
+/* Subroutine */ int stpsv_(char *uplo, char *trans, char *diag, integer *n, 
+	real *ap, real *x, integer *incx);
+
+/* Subroutine */ int strmm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, real *alpha, real *a, integer *lda, real *b, 
+	integer *ldb);
+
+/* Subroutine */ int strmv_(char *uplo, char *trans, char *diag, integer *n, 
+	real *a, integer *lda, real *x, integer *incx);
+
+/* Subroutine */ int strsm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, real *alpha, real *a, integer *lda, real *b, 
+	integer *ldb);
+
+/* Subroutine */ int strsv_(char *uplo, char *trans, char *diag, integer *n, 
+	real *a, integer *lda, real *x, integer *incx);
+
+/* Subroutine */ int xerbla_(char *srname, integer *info);
+
+/* Subroutine */ int xerbla_array__(char *srname_array__, integer *
+	srname_len__, integer *info, ftnlen srname_array_len);
+
+/* Subroutine */ int zaxpy_(integer *n, doublecomplex *za, doublecomplex *zx, 
+	integer *incx, doublecomplex *zy, integer *incy);
+
+/* Subroutine */ int zcopy_(integer *n, doublecomplex *zx, integer *incx, 
+	doublecomplex *zy, integer *incy);
+
+/* Double Complex */ VOID zdotc_(doublecomplex * ret_val, integer *n, 
+	doublecomplex *zx, integer *incx, doublecomplex *zy, integer *incy);
+
+/* Double Complex */ VOID zdotu_(doublecomplex * ret_val, integer *n, 
+	doublecomplex *zx, integer *incx, doublecomplex *zy, integer *incy);
+
+/* Subroutine */ int zdrot_(integer *n, doublecomplex *cx, integer *incx, 
+	doublecomplex *cy, integer *incy, doublereal *c__, doublereal *s);
+
+/* Subroutine */ int zdscal_(integer *n, doublereal *da, doublecomplex *zx, 
+	integer *incx);
+
+/* Subroutine */ int zgbmv_(char *trans, integer *m, integer *n, integer *kl, 
+	integer *ku, doublecomplex *alpha, doublecomplex *a, integer *lda, 
+	doublecomplex *x, integer *incx, doublecomplex *beta, doublecomplex *
+	y, integer *incy);
+
+/* Subroutine */ int zgemm_(char *transa, char *transb, integer *m, integer *
+	n, integer *k, doublecomplex *alpha, doublecomplex *a, integer *lda, 
+	doublecomplex *b, integer *ldb, doublecomplex *beta, doublecomplex *
+	c__, integer *ldc);
+
+/* Subroutine */ int zgemv_(char *trans, integer *m, integer *n, 
+	doublecomplex *alpha, doublecomplex *a, integer *lda, doublecomplex *
+	x, integer *incx, doublecomplex *beta, doublecomplex *y, integer *
+	incy);
+
+/* Subroutine */ int zgerc_(integer *m, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *y, integer *incy, 
+	doublecomplex *a, integer *lda);
+
+/* Subroutine */ int zgeru_(integer *m, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *y, integer *incy, 
+	doublecomplex *a, integer *lda);
+
+/* Subroutine */ int zhbmv_(char *uplo, integer *n, integer *k, doublecomplex 
+	*alpha, doublecomplex *a, integer *lda, doublecomplex *x, integer *
+	incx, doublecomplex *beta, doublecomplex *y, integer *incy);
+
+/* Subroutine */ int zhemm_(char *side, char *uplo, integer *m, integer *n, 
+	doublecomplex *alpha, doublecomplex *a, integer *lda, doublecomplex *
+	b, integer *ldb, doublecomplex *beta, doublecomplex *c__, integer *
+	ldc);
+
+/* Subroutine */ int zhemv_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *a, integer *lda, doublecomplex *x, integer *incx, 
+	doublecomplex *beta, doublecomplex *y, integer *incy);
+
+/* Subroutine */ int zher_(char *uplo, integer *n, doublereal *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *a, integer *lda);
+
+/* Subroutine */ int zher2_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *y, integer *incy, 
+	doublecomplex *a, integer *lda);
+
+/* Subroutine */ int zher2k_(char *uplo, char *trans, integer *n, integer *k, 
+	doublecomplex *alpha, doublecomplex *a, integer *lda, doublecomplex *
+	b, integer *ldb, doublereal *beta, doublecomplex *c__, integer *ldc);
+
+/* Subroutine */ int zherk_(char *uplo, char *trans, integer *n, integer *k, 
+	doublereal *alpha, doublecomplex *a, integer *lda, doublereal *beta, 
+	doublecomplex *c__, integer *ldc);
+
+/* Subroutine */ int zhpmv_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *ap, doublecomplex *x, integer *incx, doublecomplex *
+	beta, doublecomplex *y, integer *incy);
+
+/* Subroutine */ int zhpr_(char *uplo, integer *n, doublereal *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *ap);
+
+/* Subroutine */ int zhpr2_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *y, integer *incy, 
+	doublecomplex *ap);
+
+/* Subroutine */ int zrotg_(doublecomplex *ca, doublecomplex *cb, doublereal *
+	c__, doublecomplex *s);
+
+/* Subroutine */ int zscal_(integer *n, doublecomplex *za, doublecomplex *zx, 
+	integer *incx);
+
+/* Subroutine */ int zswap_(integer *n, doublecomplex *zx, integer *incx, 
+	doublecomplex *zy, integer *incy);
+
+/* Subroutine */ int zsymm_(char *side, char *uplo, integer *m, integer *n, 
+	doublecomplex *alpha, doublecomplex *a, integer *lda, doublecomplex *
+	b, integer *ldb, doublecomplex *beta, doublecomplex *c__, integer *
+	ldc);
+
+/* Subroutine */ int zsyr2k_(char *uplo, char *trans, integer *n, integer *k, 
+	doublecomplex *alpha, doublecomplex *a, integer *lda, doublecomplex *
+	b, integer *ldb, doublecomplex *beta, doublecomplex *c__, integer *
+	ldc);
+
+/* Subroutine */ int zsyrk_(char *uplo, char *trans, integer *n, integer *k, 
+	doublecomplex *alpha, doublecomplex *a, integer *lda, doublecomplex *
+	beta, doublecomplex *c__, integer *ldc);
+
+/* Subroutine */ int ztbmv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *x, integer 
+	*incx);
+
+/* Subroutine */ int ztbsv_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *x, integer 
+	*incx);
+
+/* Subroutine */ int ztpmv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublecomplex *ap, doublecomplex *x, integer *incx);
+
+/* Subroutine */ int ztpsv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublecomplex *ap, doublecomplex *x, integer *incx);
+
+/* Subroutine */ int ztrmm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, doublecomplex *alpha, doublecomplex *a, 
+	integer *lda, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int ztrmv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *x, integer *incx);
+
+/* Subroutine */ int ztrsm_(char *side, char *uplo, char *transa, char *diag, 
+	integer *m, integer *n, doublecomplex *alpha, doublecomplex *a, 
+	integer *lda, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int ztrsv_(char *uplo, char *trans, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *x, integer *incx);
+
+/* Subroutine */ int cbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, real *d__, real *e, complex *vt, integer *ldvt, 
+	complex *u, integer *ldu, complex *c__, integer *ldc, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cgbbrd_(char *vect, integer *m, integer *n, integer *ncc, 
+	 integer *kl, integer *ku, complex *ab, integer *ldab, real *d__, 
+	real *e, complex *q, integer *ldq, complex *pt, integer *ldpt, 
+	complex *c__, integer *ldc, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgbcon_(char *norm, integer *n, integer *kl, integer *ku, 
+	 complex *ab, integer *ldab, integer *ipiv, real *anorm, real *rcond, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgbequ_(integer *m, integer *n, integer *kl, integer *ku, 
+	 complex *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real 
+	*colcnd, real *amax, integer *info);
+
+/* Subroutine */ int cgbequb_(integer *m, integer *n, integer *kl, integer *
+	ku, complex *ab, integer *ldab, real *r__, real *c__, real *rowcnd, 
+	real *colcnd, real *amax, integer *info);
+
+/* Subroutine */ int cgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, complex *ab, integer *ldab, complex *afb, integer *
+	ldafb, integer *ipiv, complex *b, integer *ldb, complex *x, integer *
+	ldx, real *ferr, real *berr, complex *work, real *rwork, integer *
+	info);
+
+/* Subroutine */ int cgbrfsx_(char *trans, char *equed, integer *n, integer *
+	kl, integer *ku, integer *nrhs, complex *ab, integer *ldab, complex *
+	afb, integer *ldafb, integer *ipiv, real *r__, real *c__, complex *b, 
+	integer *ldb, complex *x, integer *ldx, real *rcond, real *berr, 
+	integer *n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, 
+	integer *nparams, real *params, complex *work, real *rwork, integer *
+	info);
+
+/* Subroutine */ int cgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, complex *ab, integer *ldab, integer *ipiv, complex *b, integer *
+	ldb, integer *info);
+
+/* Subroutine */ int cgbsvx_(char *fact, char *trans, integer *n, integer *kl, 
+	 integer *ku, integer *nrhs, complex *ab, integer *ldab, complex *afb, 
+	 integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__, 
+	complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, real 
+	*ferr, real *berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgbsvxx_(char *fact, char *trans, integer *n, integer *
+	kl, integer *ku, integer *nrhs, complex *ab, integer *ldab, complex *
+	afb, integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__, 
+	 complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, 
+	real *rpvgrw, real *berr, integer *n_err_bnds__, real *
+	err_bnds_norm__, real *err_bnds_comp__, integer *nparams, real *
+	params, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgbtf2_(integer *m, integer *n, integer *kl, integer *ku, 
+	 complex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int cgbtrf_(integer *m, integer *n, integer *kl, integer *ku, 
+	 complex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int cgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, complex *ab, integer *ldab, integer *ipiv, complex 
+	*b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *scale, integer *m, complex *v, integer *ldv, 
+	integer *info);
+
+/* Subroutine */ int cgebal_(char *job, integer *n, complex *a, integer *lda, 
+	integer *ilo, integer *ihi, real *scale, integer *info);
+
+/* Subroutine */ int cgebd2_(integer *m, integer *n, complex *a, integer *lda, 
+	 real *d__, real *e, complex *tauq, complex *taup, complex *work, 
+	integer *info);
+
+/* Subroutine */ int cgebrd_(integer *m, integer *n, complex *a, integer *lda, 
+	 real *d__, real *e, complex *tauq, complex *taup, complex *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int cgecon_(char *norm, integer *n, complex *a, integer *lda, 
+	 real *anorm, real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgeequ_(integer *m, integer *n, complex *a, integer *lda, 
+	 real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, 
+	integer *info);
+
+/* Subroutine */ int cgeequb_(integer *m, integer *n, complex *a, integer *
+	lda, real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, 
+	integer *info);
+
+/* Subroutine */ int cgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	complex *a, integer *lda, integer *sdim, complex *w, complex *vs, 
+	integer *ldvs, complex *work, integer *lwork, real *rwork, logical *
+	bwork, integer *info);
+
+/* Subroutine */ int cgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, complex *a, integer *lda, integer *sdim, complex *
+	w, complex *vs, integer *ldvs, real *rconde, real *rcondv, complex *
+	work, integer *lwork, real *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int cgeev_(char *jobvl, char *jobvr, integer *n, complex *a, 
+	integer *lda, complex *w, complex *vl, integer *ldvl, complex *vr, 
+	integer *ldvr, complex *work, integer *lwork, real *rwork, integer *
+	info);
+
+/* Subroutine */ int cgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, complex *a, integer *lda, complex *w, complex *vl, 
+	integer *ldvl, complex *vr, integer *ldvr, integer *ilo, integer *ihi, 
+	 real *scale, real *abnrm, real *rconde, real *rcondv, complex *work, 
+	integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cgegs_(char *jobvsl, char *jobvsr, integer *n, complex *
+	a, integer *lda, complex *b, integer *ldb, complex *alpha, complex *
+	beta, complex *vsl, integer *ldvsl, complex *vsr, integer *ldvsr, 
+	complex *work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cgegv_(char *jobvl, char *jobvr, integer *n, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *alpha, complex *beta, 
+	 complex *vl, integer *ldvl, complex *vr, integer *ldvr, complex *
+	work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cgehd2_(integer *n, integer *ilo, integer *ihi, complex *
+	a, integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgehrd_(integer *n, integer *ilo, integer *ihi, complex *
+	a, integer *lda, complex *tau, complex *work, integer *lwork, integer 
+	*info);
+
+/* Subroutine */ int cgelq2_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgelqf_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *b, integer *ldb, complex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgelsd_(integer *m, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, real *s, real *rcond, 
+	integer *rank, complex *work, integer *lwork, real *rwork, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int cgelss_(integer *m, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, real *s, real *rcond, 
+	integer *rank, complex *work, integer *lwork, real *rwork, integer *
+	info);
+
+/* Subroutine */ int cgelsx_(integer *m, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *jpvt, real *rcond, 
+	 integer *rank, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgelsy_(integer *m, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *jpvt, real *rcond, 
+	 integer *rank, complex *work, integer *lwork, real *rwork, integer *
+	info);
+
+/* Subroutine */ int cgeql2_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgeqlf_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgeqp3_(integer *m, integer *n, complex *a, integer *lda, 
+	 integer *jpvt, complex *tau, complex *work, integer *lwork, real *
+	rwork, integer *info);
+
+/* Subroutine */ int cgeqpf_(integer *m, integer *n, complex *a, integer *lda, 
+	 integer *jpvt, complex *tau, complex *work, real *rwork, integer *
+	info);
+
+/* Subroutine */ int cgeqr2_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgeqrf_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgerfs_(char *trans, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+	b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgerfsx_(char *trans, char *equed, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, real *r__, real *c__, complex *b, integer *ldb, complex *x, 
+	integer *ldx, real *rcond, real *berr, integer *n_err_bnds__, real *
+	err_bnds_norm__, real *err_bnds_comp__, integer *nparams, real *
+	params, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgerq2_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgerqf_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgesc2_(integer *n, complex *a, integer *lda, complex *
+	rhs, integer *ipiv, integer *jpiv, real *scale);
+
+/* Subroutine */ int cgesdd_(char *jobz, integer *m, integer *n, complex *a, 
+	integer *lda, real *s, complex *u, integer *ldu, complex *vt, integer 
+	*ldvt, complex *work, integer *lwork, real *rwork, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int cgesv_(integer *n, integer *nrhs, complex *a, integer *
+	lda, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgesvd_(char *jobu, char *jobvt, integer *m, integer *n, 
+	complex *a, integer *lda, real *s, complex *u, integer *ldu, complex *
+	vt, integer *ldvt, complex *work, integer *lwork, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, char *equed, real *r__, real *c__, complex *b, integer *ldb, 
+	complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgesvxx_(char *fact, char *trans, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, char *equed, real *r__, real *c__, complex *b, integer *ldb, 
+	complex *x, integer *ldx, real *rcond, real *rpvgrw, real *berr, 
+	integer *n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, 
+	integer *nparams, real *params, complex *work, real *rwork, integer *
+	info);
+
+/* Subroutine */ int cgetc2_(integer *n, complex *a, integer *lda, integer *
+	ipiv, integer *jpiv, integer *info);
+
+/* Subroutine */ int cgetf2_(integer *m, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, integer *info);
+
+/* Subroutine */ int cgetrf_(integer *m, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, integer *info);
+
+/* Subroutine */ int cgetri_(integer *n, complex *a, integer *lda, integer *
+	ipiv, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgetrs_(char *trans, integer *n, integer *nrhs, complex *
+	a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int cggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *lscale, real *rscale, integer *m, complex *v, 
+	integer *ldv, integer *info);
+
+/* Subroutine */ int cggbal_(char *job, integer *n, complex *a, integer *lda, 
+	complex *b, integer *ldb, integer *ilo, integer *ihi, real *lscale, 
+	real *rscale, real *work, integer *info);
+
+/* Subroutine */ int cgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, integer *n, complex *a, integer *lda, complex *b, integer *
+	ldb, integer *sdim, complex *alpha, complex *beta, complex *vsl, 
+	integer *ldvsl, complex *vsr, integer *ldvsr, complex *work, integer *
+	lwork, real *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int cggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, char *sense, integer *n, complex *a, integer *lda, complex *b, 
+	 integer *ldb, integer *sdim, complex *alpha, complex *beta, complex *
+	vsl, integer *ldvsl, complex *vsr, integer *ldvsr, real *rconde, real 
+	*rcondv, complex *work, integer *lwork, real *rwork, integer *iwork, 
+	integer *liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int cggev_(char *jobvl, char *jobvr, integer *n, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *alpha, complex *beta, 
+	 complex *vl, integer *ldvl, complex *vr, integer *ldvr, complex *
+	work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	 complex *alpha, complex *beta, complex *vl, integer *ldvl, complex *
+	vr, integer *ldvr, integer *ilo, integer *ihi, real *lscale, real *
+	rscale, real *abnrm, real *bbnrm, real *rconde, real *rcondv, complex 
+	*work, integer *lwork, real *rwork, integer *iwork, logical *bwork, 
+	integer *info);
+
+/* Subroutine */ int cggglm_(integer *n, integer *m, integer *p, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *d__, complex *x, 
+	complex *y, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, complex *a, integer *lda, complex *b, integer *ldb, 
+	 complex *q, integer *ldq, complex *z__, integer *ldz, integer *info);
+
+/* Subroutine */ int cgglse_(integer *m, integer *n, integer *p, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *c__, complex *d__, 
+	complex *x, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cggqrf_(integer *n, integer *m, integer *p, complex *a, 
+	integer *lda, complex *taua, complex *b, integer *ldb, complex *taub, 
+	complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cggrqf_(integer *m, integer *p, integer *n, complex *a, 
+	integer *lda, complex *taua, complex *b, integer *ldb, complex *taub, 
+	complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, complex *a, integer *
+	lda, complex *b, integer *ldb, real *alpha, real *beta, complex *u, 
+	integer *ldu, complex *v, integer *ldv, complex *q, integer *ldq, 
+	complex *work, real *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int cggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, complex *a, integer *lda, complex *b, integer 
+	*ldb, real *tola, real *tolb, integer *k, integer *l, complex *u, 
+	integer *ldu, complex *v, integer *ldv, complex *q, integer *ldq, 
+	integer *iwork, real *rwork, complex *tau, complex *work, integer *
+	info);
+
+/* Subroutine */ int cgtcon_(char *norm, integer *n, complex *dl, complex *
+	d__, complex *du, complex *du2, integer *ipiv, real *anorm, real *
+	rcond, complex *work, integer *info);
+
+/* Subroutine */ int cgtrfs_(char *trans, integer *n, integer *nrhs, complex *
+	dl, complex *d__, complex *du, complex *dlf, complex *df, complex *
+	duf, complex *du2, integer *ipiv, complex *b, integer *ldb, complex *
+	x, integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cgtsv_(integer *n, integer *nrhs, complex *dl, complex *
+	d__, complex *du, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, complex *dl, complex *d__, complex *du, complex *dlf, complex *
+	df, complex *duf, complex *du2, integer *ipiv, complex *b, integer *
+	ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgttrf_(integer *n, complex *dl, complex *d__, complex *
+	du, complex *du2, integer *ipiv, integer *info);
+
+/* Subroutine */ int cgttrs_(char *trans, integer *n, integer *nrhs, complex *
+	dl, complex *d__, complex *du, complex *du2, integer *ipiv, complex *
+	b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgtts2_(integer *itrans, integer *n, integer *nrhs, 
+	complex *dl, complex *d__, complex *du, complex *du2, integer *ipiv, 
+	complex *b, integer *ldb);
+
+/* Subroutine */ int chbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	complex *ab, integer *ldab, real *w, complex *z__, integer *ldz, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	complex *ab, integer *ldab, real *w, complex *z__, integer *ldz, 
+	complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int chbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, complex *ab, integer *ldab, complex *q, integer *ldq, 
+	real *vl, real *vu, integer *il, integer *iu, real *abstol, integer *
+	m, real *w, complex *z__, integer *ldz, complex *work, real *rwork, 
+	integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int chbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, complex *ab, integer *ldab, complex *bb, integer *ldbb, 
+	complex *x, integer *ldx, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, complex *ab, integer *ldab, complex *bb, integer *ldbb, 
+	real *w, complex *z__, integer *ldz, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int chbgvd_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, complex *ab, integer *ldab, complex *bb, integer *ldbb, 
+	real *w, complex *z__, integer *ldz, complex *work, integer *lwork, 
+	real *rwork, integer *lrwork, integer *iwork, integer *liwork, 
+	integer *info);
+
+/* Subroutine */ int chbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, complex *ab, integer *ldab, complex *bb, 
+	integer *ldbb, complex *q, integer *ldq, real *vl, real *vu, integer *
+	il, integer *iu, real *abstol, integer *m, real *w, complex *z__, 
+	integer *ldz, complex *work, real *rwork, integer *iwork, integer *
+	ifail, integer *info);
+
+/* Subroutine */ int chbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	complex *ab, integer *ldab, real *d__, real *e, complex *q, integer *
+	ldq, complex *work, integer *info);
+
+/* Subroutine */ int checon_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, real *anorm, real *rcond, complex *work, integer *
+	info);
+
+/* Subroutine */ int cheequb_(char *uplo, integer *n, complex *a, integer *
+	lda, real *s, real *scond, real *amax, complex *work, integer *info);
+
+/* Subroutine */ int cheev_(char *jobz, char *uplo, integer *n, complex *a, 
+	integer *lda, real *w, complex *work, integer *lwork, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cheevd_(char *jobz, char *uplo, integer *n, complex *a, 
+	integer *lda, real *w, complex *work, integer *lwork, real *rwork, 
+	integer *lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int cheevr_(char *jobz, char *range, char *uplo, integer *n, 
+	complex *a, integer *lda, real *vl, real *vu, integer *il, integer *
+	iu, real *abstol, integer *m, real *w, complex *z__, integer *ldz, 
+	integer *isuppz, complex *work, integer *lwork, real *rwork, integer *
+	lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int cheevx_(char *jobz, char *range, char *uplo, integer *n, 
+	complex *a, integer *lda, real *vl, real *vu, integer *il, integer *
+	iu, real *abstol, integer *m, real *w, complex *z__, integer *ldz, 
+	complex *work, integer *lwork, real *rwork, integer *iwork, integer *
+	ifail, integer *info);
+
+/* Subroutine */ int chegs2_(integer *itype, char *uplo, integer *n, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chegst_(integer *itype, char *uplo, integer *n, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chegv_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, real *w, 
+	complex *work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int chegvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, real *w, 
+	complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int chegvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	real *vl, real *vu, integer *il, integer *iu, real *abstol, integer *
+	m, real *w, complex *z__, integer *ldz, complex *work, integer *lwork, 
+	 real *rwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int cherfs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+	b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cherfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, real *s, complex *b, integer *ldb, complex *x, integer *ldx, 
+	real *rcond, real *berr, integer *n_err_bnds__, real *err_bnds_norm__, 
+	 real *err_bnds_comp__, integer *nparams, real *params, complex *work, 
+	 real *rwork, integer *info);
+
+/* Subroutine */ int chesv_(char *uplo, integer *n, integer *nrhs, complex *a, 
+	 integer *lda, integer *ipiv, complex *b, integer *ldb, complex *work, 
+	 integer *lwork, integer *info);
+
+/* Subroutine */ int chesvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, 
+	 real *ferr, real *berr, complex *work, integer *lwork, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int chesvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, char *equed, real *s, complex *b, integer *ldb, complex *x, 
+	integer *ldx, real *rcond, real *rpvgrw, real *berr, integer *
+	n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, integer *
+	nparams, real *params, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chetd2_(char *uplo, integer *n, complex *a, integer *lda, 
+	 real *d__, real *e, complex *tau, integer *info);
+
+/* Subroutine */ int chetf2_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, integer *info);
+
+/* Subroutine */ int chetrd_(char *uplo, integer *n, complex *a, integer *lda, 
+	 real *d__, real *e, complex *tau, complex *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int chetrf_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int chetri_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, complex *work, integer *info);
+
+/* Subroutine */ int chetrs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int chfrk_(char *transr, char *uplo, char *trans, integer *n, 
+	 integer *k, real *alpha, complex *a, integer *lda, real *beta, 
+	complex *c__);
+
+/* Subroutine */ int chgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, complex *h__, integer *ldh, complex *t, 
+	integer *ldt, complex *alpha, complex *beta, complex *q, integer *ldq, 
+	 complex *z__, integer *ldz, complex *work, integer *lwork, real *
+	rwork, integer *info);
+
+/* Character */ VOID chla_transtype__(char *ret_val, ftnlen ret_val_len, 
+	integer *trans);
+
+/* Subroutine */ int chpcon_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, real *anorm, real *rcond, complex *work, integer *info);
+
+/* Subroutine */ int chpev_(char *jobz, char *uplo, integer *n, complex *ap, 
+	real *w, complex *z__, integer *ldz, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int chpevd_(char *jobz, char *uplo, integer *n, complex *ap, 
+	real *w, complex *z__, integer *ldz, complex *work, integer *lwork, 
+	real *rwork, integer *lrwork, integer *iwork, integer *liwork, 
+	integer *info);
+
+/* Subroutine */ int chpevx_(char *jobz, char *range, char *uplo, integer *n, 
+	complex *ap, real *vl, real *vu, integer *il, integer *iu, real *
+	abstol, integer *m, real *w, complex *z__, integer *ldz, complex *
+	work, real *rwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int chpgst_(integer *itype, char *uplo, integer *n, complex *
+	ap, complex *bp, integer *info);
+
+/* Subroutine */ int chpgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *ap, complex *bp, real *w, complex *z__, integer *ldz, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chpgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *ap, complex *bp, real *w, complex *z__, integer *ldz, 
+	complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int chpgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, complex *ap, complex *bp, real *vl, real *vu, 
+	integer *il, integer *iu, real *abstol, integer *m, real *w, complex *
+	z__, integer *ldz, complex *work, real *rwork, integer *iwork, 
+	integer *ifail, integer *info);
+
+/* Subroutine */ int chprfs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *afp, integer *ipiv, complex *b, integer *ldb, complex *x, 
+	 integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int chpsv_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chpsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer *
+	ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chptrd_(char *uplo, integer *n, complex *ap, real *d__, 
+	real *e, complex *tau, integer *info);
+
+/* Subroutine */ int chptrf_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, integer *info);
+
+/* Subroutine */ int chptri_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, complex *work, integer *info);
+
+/* Subroutine */ int chptrs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, complex *h__, integer *ldh, complex *w, complex *
+	vl, integer *ldvl, complex *vr, integer *ldvr, integer *mm, integer *
+	m, complex *work, real *rwork, integer *ifaill, integer *ifailr, 
+	integer *info);
+
+/* Subroutine */ int chseqr_(char *job, char *compz, integer *n, integer *ilo, 
+	 integer *ihi, complex *h__, integer *ldh, complex *w, complex *z__, 
+	integer *ldz, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cla_gbamv__(integer *trans, integer *m, integer *n, 
+	integer *kl, integer *ku, real *alpha, complex *ab, integer *ldab, 
+	complex *x, integer *incx, real *beta, real *y, integer *incy);
+
+doublereal cla_gbrcond_c__(char *trans, integer *n, integer *kl, integer *ku, 
+	complex *ab, integer *ldab, complex *afb, integer *ldafb, integer *
+	ipiv, real *c__, logical *capply, integer *info, complex *work, real *
+	rwork, ftnlen trans_len);
+
+doublereal cla_gbrcond_x__(char *trans, integer *n, integer *kl, integer *ku, 
+	complex *ab, integer *ldab, complex *afb, integer *ldafb, integer *
+	ipiv, complex *x, integer *info, complex *work, real *rwork, ftnlen 
+	trans_len);
+
+/* Subroutine */ int cla_gbrfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *kl, integer *ku, integer *nrhs, 
+	complex *ab, integer *ldab, complex *afb, integer *ldafb, integer *
+	ipiv, logical *colequ, real *c__, complex *b, integer *ldb, complex *
+	y, integer *ldy, real *berr_out__, integer *n_norms__, real *errs_n__,
+	 real *errs_c__, complex *res, real *ayb, complex *dy, complex *
+	y_tail__, real *rcond, integer *ithresh, real *rthresh, real *dz_ub__,
+	 logical *ignore_cwise__, integer *info);
+
+doublereal cla_gbrpvgrw__(integer *n, integer *kl, integer *ku, integer *
+	ncols, complex *ab, integer *ldab, complex *afb, integer *ldafb);
+
+/* Subroutine */ int cla_geamv__(integer *trans, integer *m, integer *n, real 
+	*alpha, complex *a, integer *lda, complex *x, integer *incx, real *
+	beta, real *y, integer *incy);
+
+doublereal cla_gercond_c__(char *trans, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, integer *ipiv, real *c__, logical *capply,
+	 integer *info, complex *work, real *rwork, ftnlen trans_len);
+
+doublereal cla_gercond_x__(char *trans, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, integer *ipiv, complex *x, integer *info, 
+	complex *work, real *rwork, ftnlen trans_len);
+
+/* Subroutine */ int cla_gerfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *nrhs, complex *a, integer *lda, 
+	complex *af, integer *ldaf, integer *ipiv, logical *colequ, real *c__,
+	 complex *b, integer *ldb, complex *y, integer *ldy, real *berr_out__,
+	 integer *n_norms__, real *errs_n__, real *errs_c__, complex *res, 
+	real *ayb, complex *dy, complex *y_tail__, real *rcond, integer *
+	ithresh, real *rthresh, real *dz_ub__, logical *ignore_cwise__, 
+	integer *info);
+
+/* Subroutine */ int cla_heamv__(integer *uplo, integer *n, real *alpha, 
+	complex *a, integer *lda, complex *x, integer *incx, real *beta, real 
+	*y, integer *incy);
+
+doublereal cla_hercond_c__(char *uplo, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, integer *ipiv, real *c__, logical *capply,
+	 integer *info, complex *work, real *rwork, ftnlen uplo_len);
+
+doublereal cla_hercond_x__(char *uplo, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, integer *ipiv, complex *x, integer *info, 
+	complex *work, real *rwork, ftnlen uplo_len);
+
+/* Subroutine */ int cla_herfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, complex *a, integer *lda, complex *af, 
+	integer *ldaf, integer *ipiv, logical *colequ, real *c__, complex *b, 
+	integer *ldb, complex *y, integer *ldy, real *berr_out__, integer *
+	n_norms__, real *errs_n__, real *errs_c__, complex *res, real *ayb, 
+	complex *dy, complex *y_tail__, real *rcond, integer *ithresh, real *
+	rthresh, real *dz_ub__, logical *ignore_cwise__, integer *info, 
+	ftnlen uplo_len);
+
+doublereal cla_herpvgrw__(char *uplo, integer *n, integer *info, complex *a, 
+	integer *lda, complex *af, integer *ldaf, integer *ipiv, real *work, 
+	ftnlen uplo_len);
+
+/* Subroutine */ int cla_lin_berr__(integer *n, integer *nz, integer *nrhs, 
+	complex *res, real *ayb, real *berr);
+
+doublereal cla_porcond_c__(char *uplo, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, real *c__, logical *capply, integer *info,
+	 complex *work, real *rwork, ftnlen uplo_len);
+
+doublereal cla_porcond_x__(char *uplo, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, complex *x, integer *info, complex *work, 
+	real *rwork, ftnlen uplo_len);
+
+/* Subroutine */ int cla_porfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, complex *a, integer *lda, complex *af, 
+	integer *ldaf, logical *colequ, real *c__, complex *b, integer *ldb, 
+	complex *y, integer *ldy, real *berr_out__, integer *n_norms__, real *
+	errs_n__, real *errs_c__, complex *res, real *ayb, complex *dy, 
+	complex *y_tail__, real *rcond, integer *ithresh, real *rthresh, real 
+	*dz_ub__, logical *ignore_cwise__, integer *info, ftnlen uplo_len);
+
+doublereal cla_porpvgrw__(char *uplo, integer *ncols, complex *a, integer *
+	lda, complex *af, integer *ldaf, real *work, ftnlen uplo_len);
+
+doublereal cla_rpvgrw__(integer *n, integer *ncols, complex *a, integer *lda, 
+	complex *af, integer *ldaf);
+
+/* Subroutine */ int cla_syamv__(integer *uplo, integer *n, real *alpha, 
+	complex *a, integer *lda, complex *x, integer *incx, real *beta, real 
+	*y, integer *incy);
+
+doublereal cla_syrcond_c__(char *uplo, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, integer *ipiv, real *c__, logical *capply,
+	 integer *info, complex *work, real *rwork, ftnlen uplo_len);
+
+doublereal cla_syrcond_x__(char *uplo, integer *n, complex *a, integer *lda, 
+	complex *af, integer *ldaf, integer *ipiv, complex *x, integer *info, 
+	complex *work, real *rwork, ftnlen uplo_len);
+
+/* Subroutine */ int cla_syrfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, complex *a, integer *lda, complex *af, 
+	integer *ldaf, integer *ipiv, logical *colequ, real *c__, complex *b, 
+	integer *ldb, complex *y, integer *ldy, real *berr_out__, integer *
+	n_norms__, real *errs_n__, real *errs_c__, complex *res, real *ayb, 
+	complex *dy, complex *y_tail__, real *rcond, integer *ithresh, real *
+	rthresh, real *dz_ub__, logical *ignore_cwise__, integer *info, 
+	ftnlen uplo_len);
+
+doublereal cla_syrpvgrw__(char *uplo, integer *n, integer *info, complex *a, 
+	integer *lda, complex *af, integer *ldaf, integer *ipiv, real *work, 
+	ftnlen uplo_len);
+
+/* Subroutine */ int cla_wwaddw__(integer *n, complex *x, complex *y, complex 
+	*w);
+
+/* Subroutine */ int clabrd_(integer *m, integer *n, integer *nb, complex *a, 
+	integer *lda, real *d__, real *e, complex *tauq, complex *taup, 
+	complex *x, integer *ldx, complex *y, integer *ldy);
+
+/* Subroutine */ int clacgv_(integer *n, complex *x, integer *incx);
+
+/* Subroutine */ int clacn2_(integer *n, complex *v, complex *x, real *est, 
+	integer *kase, integer *isave);
+
+/* Subroutine */ int clacon_(integer *n, complex *v, complex *x, real *est, 
+	integer *kase);
+
+/* Subroutine */ int clacp2_(char *uplo, integer *m, integer *n, real *a, 
+	integer *lda, complex *b, integer *ldb);
+
+/* Subroutine */ int clacpy_(char *uplo, integer *m, integer *n, complex *a, 
+	integer *lda, complex *b, integer *ldb);
+
+/* Subroutine */ int clacrm_(integer *m, integer *n, complex *a, integer *lda, 
+	 real *b, integer *ldb, complex *c__, integer *ldc, real *rwork);
+
+/* Subroutine */ int clacrt_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy, complex *c__, complex *s);
+
+/* Complex */ VOID cladiv_(complex * ret_val, complex *x, complex *y);
+
+/* Subroutine */ int claed0_(integer *qsiz, integer *n, real *d__, real *e, 
+	complex *q, integer *ldq, complex *qstore, integer *ldqs, real *rwork, 
+	 integer *iwork, integer *info);
+
+/* Subroutine */ int claed7_(integer *n, integer *cutpnt, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, real *d__, complex *
+	q, integer *ldq, real *rho, integer *indxq, real *qstore, integer *
+	qptr, integer *prmptr, integer *perm, integer *givptr, integer *
+	givcol, real *givnum, complex *work, real *rwork, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int claed8_(integer *k, integer *n, integer *qsiz, complex *
+	q, integer *ldq, real *d__, real *rho, integer *cutpnt, real *z__, 
+	real *dlamda, complex *q2, integer *ldq2, real *w, integer *indxp, 
+	integer *indx, integer *indxq, integer *perm, integer *givptr, 
+	integer *givcol, real *givnum, integer *info);
+
+/* Subroutine */ int claein_(logical *rightv, logical *noinit, integer *n, 
+	complex *h__, integer *ldh, complex *w, complex *v, complex *b, 
+	integer *ldb, real *rwork, real *eps3, real *smlnum, integer *info);
+
+/* Subroutine */ int claesy_(complex *a, complex *b, complex *c__, complex *
+	rt1, complex *rt2, complex *evscal, complex *cs1, complex *sn1);
+
+/* Subroutine */ int claev2_(complex *a, complex *b, complex *c__, real *rt1, 
+	real *rt2, real *cs1, complex *sn1);
+
+/* Subroutine */ int clag2z_(integer *m, integer *n, complex *sa, integer *
+	ldsa, doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int clags2_(logical *upper, real *a1, complex *a2, real *a3, 
+	real *b1, complex *b2, real *b3, real *csu, complex *snu, real *csv, 
+	complex *snv, real *csq, complex *snq);
+
+/* Subroutine */ int clagtm_(char *trans, integer *n, integer *nrhs, real *
+	alpha, complex *dl, complex *d__, complex *du, complex *x, integer *
+	ldx, real *beta, complex *b, integer *ldb);
+
+/* Subroutine */ int clahef_(char *uplo, integer *n, integer *nb, integer *kb, 
+	 complex *a, integer *lda, integer *ipiv, complex *w, integer *ldw, 
+	integer *info);
+
+/* Subroutine */ int clahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, complex *h__, integer *ldh, complex *w, 
+	integer *iloz, integer *ihiz, complex *z__, integer *ldz, integer *
+	info);
+
+/* Subroutine */ int clahr2_(integer *n, integer *k, integer *nb, complex *a, 
+	integer *lda, complex *tau, complex *t, integer *ldt, complex *y, 
+	integer *ldy);
+
+/* Subroutine */ int clahrd_(integer *n, integer *k, integer *nb, complex *a, 
+	integer *lda, complex *tau, complex *t, integer *ldt, complex *y, 
+	integer *ldy);
+
+/* Subroutine */ int claic1_(integer *job, integer *j, complex *x, real *sest, 
+	 complex *w, complex *gamma, real *sestpr, complex *s, complex *c__);
+
+/* Subroutine */ int clals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, complex *b, integer *ldb, complex *bx, 
+	integer *ldbx, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+	difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+	rwork, integer *info);
+
+/* Subroutine */ int clalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, complex *b, integer *ldb, complex *bx, integer *ldbx, 
+	real *u, integer *ldu, real *vt, integer *k, real *difl, real *difr, 
+	real *z__, real *poles, integer *givptr, integer *givcol, integer *
+	ldgcol, integer *perm, real *givnum, real *c__, real *s, real *rwork, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int clalsd_(char *uplo, integer *smlsiz, integer *n, integer 
+	*nrhs, real *d__, real *e, complex *b, integer *ldb, real *rcond, 
+	integer *rank, complex *work, real *rwork, integer *iwork, integer *
+	info);
+
+doublereal clangb_(char *norm, integer *n, integer *kl, integer *ku, complex *
+	ab, integer *ldab, real *work);
+
+doublereal clange_(char *norm, integer *m, integer *n, complex *a, integer *
+	lda, real *work);
+
+doublereal clangt_(char *norm, integer *n, complex *dl, complex *d__, complex 
+	*du);
+
+doublereal clanhb_(char *norm, char *uplo, integer *n, integer *k, complex *
+	ab, integer *ldab, real *work);
+
+doublereal clanhe_(char *norm, char *uplo, integer *n, complex *a, integer *
+	lda, real *work);
+
+doublereal clanhf_(char *norm, char *transr, char *uplo, integer *n, complex *
+	a, real *work);
+
+doublereal clanhp_(char *norm, char *uplo, integer *n, complex *ap, real *
+	work);
+
+doublereal clanhs_(char *norm, integer *n, complex *a, integer *lda, real *
+	work);
+
+doublereal clanht_(char *norm, integer *n, real *d__, complex *e);
+
+doublereal clansb_(char *norm, char *uplo, integer *n, integer *k, complex *
+	ab, integer *ldab, real *work);
+
+doublereal clansp_(char *norm, char *uplo, integer *n, complex *ap, real *
+	work);
+
+doublereal clansy_(char *norm, char *uplo, integer *n, complex *a, integer *
+	lda, real *work);
+
+doublereal clantb_(char *norm, char *uplo, char *diag, integer *n, integer *k, 
+	 complex *ab, integer *ldab, real *work);
+
+doublereal clantp_(char *norm, char *uplo, char *diag, integer *n, complex *
+	ap, real *work);
+
+doublereal clantr_(char *norm, char *uplo, char *diag, integer *m, integer *n, 
+	 complex *a, integer *lda, real *work);
+
+/* Subroutine */ int clapll_(integer *n, complex *x, integer *incx, complex *
+	y, integer *incy, real *ssmin);
+
+/* Subroutine */ int clapmt_(logical *forwrd, integer *m, integer *n, complex 
+	*x, integer *ldx, integer *k);
+
+/* Subroutine */ int claqgb_(integer *m, integer *n, integer *kl, integer *ku, 
+	 complex *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real 
+	*colcnd, real *amax, char *equed);
+
+/* Subroutine */ int claqge_(integer *m, integer *n, complex *a, integer *lda, 
+	 real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, char *
+	equed);
+
+/* Subroutine */ int claqhb_(char *uplo, integer *n, integer *kd, complex *ab, 
+	 integer *ldab, real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqhe_(char *uplo, integer *n, complex *a, integer *lda, 
+	 real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqhp_(char *uplo, integer *n, complex *ap, real *s, 
+	real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqp2_(integer *m, integer *n, integer *offset, complex 
+	*a, integer *lda, integer *jpvt, complex *tau, real *vn1, real *vn2, 
+	complex *work);
+
+/* Subroutine */ int claqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, complex *a, integer *lda, integer *jpvt, complex *
+	tau, real *vn1, real *vn2, complex *auxv, complex *f, integer *ldf);
+
+/* Subroutine */ int claqr0_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, complex *h__, integer *ldh, complex *w, 
+	integer *iloz, integer *ihiz, complex *z__, integer *ldz, complex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int claqr1_(integer *n, complex *h__, integer *ldh, complex *
+	s1, complex *s2, complex *v);
+
+/* Subroutine */ int claqr2_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, complex *h__, integer *ldh, 
+	 integer *iloz, integer *ihiz, complex *z__, integer *ldz, integer *
+	ns, integer *nd, complex *sh, complex *v, integer *ldv, integer *nh, 
+	complex *t, integer *ldt, integer *nv, complex *wv, integer *ldwv, 
+	complex *work, integer *lwork);
+
+/* Subroutine */ int claqr3_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, complex *h__, integer *ldh, 
+	 integer *iloz, integer *ihiz, complex *z__, integer *ldz, integer *
+	ns, integer *nd, complex *sh, complex *v, integer *ldv, integer *nh, 
+	complex *t, integer *ldt, integer *nv, complex *wv, integer *ldwv, 
+	complex *work, integer *lwork);
+
+/* Subroutine */ int claqr4_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, complex *h__, integer *ldh, complex *w, 
+	integer *iloz, integer *ihiz, complex *z__, integer *ldz, complex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int claqr5_(logical *wantt, logical *wantz, integer *kacc22, 
+	integer *n, integer *ktop, integer *kbot, integer *nshfts, complex *s, 
+	 complex *h__, integer *ldh, integer *iloz, integer *ihiz, complex *
+	z__, integer *ldz, complex *v, integer *ldv, complex *u, integer *ldu, 
+	 integer *nv, complex *wv, integer *ldwv, integer *nh, complex *wh, 
+	integer *ldwh);
+
+/* Subroutine */ int claqsb_(char *uplo, integer *n, integer *kd, complex *ab, 
+	 integer *ldab, real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqsp_(char *uplo, integer *n, complex *ap, real *s, 
+	real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqsy_(char *uplo, integer *n, complex *a, integer *lda, 
+	 real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int clar1v_(integer *n, integer *b1, integer *bn, real *
+	lambda, real *d__, real *l, real *ld, real *lld, real *pivmin, real *
+	gaptol, complex *z__, logical *wantnc, integer *negcnt, real *ztz, 
+	real *mingma, integer *r__, integer *isuppz, real *nrminv, real *
+	resid, real *rqcorr, real *work);
+
+/* Subroutine */ int clar2v_(integer *n, complex *x, complex *y, complex *z__, 
+	 integer *incx, real *c__, complex *s, integer *incc);
+
+/* Subroutine */ int clarcm_(integer *m, integer *n, real *a, integer *lda, 
+	complex *b, integer *ldb, complex *c__, integer *ldc, real *rwork);
+
+/* Subroutine */ int clarf_(char *side, integer *m, integer *n, complex *v, 
+	integer *incv, complex *tau, complex *c__, integer *ldc, complex *
+	work);
+
+/* Subroutine */ int clarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, complex *v, integer *ldv, 
+	complex *t, integer *ldt, complex *c__, integer *ldc, complex *work, 
+	integer *ldwork);
+
+/* Subroutine */ int clarfg_(integer *n, complex *alpha, complex *x, integer *
+	incx, complex *tau);
+
+/* Subroutine */ int clarfp_(integer *n, complex *alpha, complex *x, integer *
+	incx, complex *tau);
+
+/* Subroutine */ int clarft_(char *direct, char *storev, integer *n, integer *
+	k, complex *v, integer *ldv, complex *tau, complex *t, integer *ldt);
+
+/* Subroutine */ int clarfx_(char *side, integer *m, integer *n, complex *v, 
+	complex *tau, complex *c__, integer *ldc, complex *work);
+
+/* Subroutine */ int clargv_(integer *n, complex *x, integer *incx, complex *
+	y, integer *incy, real *c__, integer *incc);
+
+/* Subroutine */ int clarnv_(integer *idist, integer *iseed, integer *n, 
+	complex *x);
+
+/* Subroutine */ int clarrv_(integer *n, real *vl, real *vu, real *d__, real *
+	l, real *pivmin, integer *isplit, integer *m, integer *dol, integer *
+	dou, real *minrgp, real *rtol1, real *rtol2, real *w, real *werr, 
+	real *wgap, integer *iblock, integer *indexw, real *gers, complex *
+	z__, integer *ldz, integer *isuppz, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int clarscl2_(integer *m, integer *n, real *d__, complex *x, 
+	integer *ldx);
+
+/* Subroutine */ int clartg_(complex *f, complex *g, real *cs, complex *sn, 
+	complex *r__);
+
+/* Subroutine */ int clartv_(integer *n, complex *x, integer *incx, complex *
+	y, integer *incy, real *c__, complex *s, integer *incc);
+
+/* Subroutine */ int clarz_(char *side, integer *m, integer *n, integer *l, 
+	complex *v, integer *incv, complex *tau, complex *c__, integer *ldc, 
+	complex *work);
+
+/* Subroutine */ int clarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, complex *v, 
+	integer *ldv, complex *t, integer *ldt, complex *c__, integer *ldc, 
+	complex *work, integer *ldwork);
+
+/* Subroutine */ int clarzt_(char *direct, char *storev, integer *n, integer *
+	k, complex *v, integer *ldv, complex *tau, complex *t, integer *ldt);
+
+/* Subroutine */ int clascl_(char *type__, integer *kl, integer *ku, real *
+	cfrom, real *cto, integer *m, integer *n, complex *a, integer *lda, 
+	integer *info);
+
+/* Subroutine */ int clascl2_(integer *m, integer *n, real *d__, complex *x, 
+	integer *ldx);
+
+/* Subroutine */ int claset_(char *uplo, integer *m, integer *n, complex *
+	alpha, complex *beta, complex *a, integer *lda);
+
+/* Subroutine */ int clasr_(char *side, char *pivot, char *direct, integer *m, 
+	 integer *n, real *c__, real *s, complex *a, integer *lda);
+
+/* Subroutine */ int classq_(integer *n, complex *x, integer *incx, real *
+	scale, real *sumsq);
+
+/* Subroutine */ int claswp_(integer *n, complex *a, integer *lda, integer *
+	k1, integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int clasyf_(char *uplo, integer *n, integer *nb, integer *kb, 
+	 complex *a, integer *lda, integer *ipiv, complex *w, integer *ldw, 
+	integer *info);
+
+/* Subroutine */ int clatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, complex *ab, integer *ldab, complex *
+	x, real *scale, real *cnorm, integer *info);
+
+/* Subroutine */ int clatdf_(integer *ijob, integer *n, complex *z__, integer 
+	*ldz, complex *rhs, real *rdsum, real *rdscal, integer *ipiv, integer 
+	*jpiv);
+
+/* Subroutine */ int clatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, complex *ap, complex *x, real *scale, real *cnorm, 
+	 integer *info);
+
+/* Subroutine */ int clatrd_(char *uplo, integer *n, integer *nb, complex *a, 
+	integer *lda, real *e, complex *tau, complex *w, integer *ldw);
+
+/* Subroutine */ int clatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, complex *a, integer *lda, complex *x, real *scale, 
+	 real *cnorm, integer *info);
+
+/* Subroutine */ int clatrz_(integer *m, integer *n, integer *l, complex *a, 
+	integer *lda, complex *tau, complex *work);
+
+/* Subroutine */ int clatzm_(char *side, integer *m, integer *n, complex *v, 
+	integer *incv, complex *tau, complex *c1, complex *c2, integer *ldc, 
+	complex *work);
+
+/* Subroutine */ int clauu2_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *info);
+
+/* Subroutine */ int clauum_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *info);
+
+/* Subroutine */ int cpbcon_(char *uplo, integer *n, integer *kd, complex *ab, 
+	 integer *ldab, real *anorm, real *rcond, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cpbequ_(char *uplo, integer *n, integer *kd, complex *ab, 
+	 integer *ldab, real *s, real *scond, real *amax, integer *info);
+
+/* Subroutine */ int cpbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, complex *ab, integer *ldab, complex *afb, integer *ldafb, 
+	complex *b, integer *ldb, complex *x, integer *ldx, real *ferr, real *
+	berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cpbstf_(char *uplo, integer *n, integer *kd, complex *ab, 
+	 integer *ldab, integer *info);
+
+/* Subroutine */ int cpbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, complex *ab, integer *ldab, complex *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int cpbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, complex *ab, integer *ldab, complex *afb, integer *
+	ldafb, char *equed, real *s, complex *b, integer *ldb, complex *x, 
+	integer *ldx, real *rcond, real *ferr, real *berr, complex *work, 
+	real *rwork, integer *info);
+
+/* Subroutine */ int cpbtf2_(char *uplo, integer *n, integer *kd, complex *ab, 
+	 integer *ldab, integer *info);
+
+/* Subroutine */ int cpbtrf_(char *uplo, integer *n, integer *kd, complex *ab, 
+	 integer *ldab, integer *info);
+
+/* Subroutine */ int cpbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, complex *ab, integer *ldab, complex *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int cpftrf_(char *transr, char *uplo, integer *n, complex *a, 
+	 integer *info);
+
+/* Subroutine */ int cpftri_(char *transr, char *uplo, integer *n, complex *a, 
+	 integer *info);
+
+/* Subroutine */ int cpftrs_(char *transr, char *uplo, integer *n, integer *
+	nrhs, complex *a, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cpocon_(char *uplo, integer *n, complex *a, integer *lda, 
+	 real *anorm, real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cpoequ_(integer *n, complex *a, integer *lda, real *s, 
+	real *scond, real *amax, integer *info);
+
+/* Subroutine */ int cpoequb_(integer *n, complex *a, integer *lda, real *s, 
+	real *scond, real *amax, integer *info);
+
+/* Subroutine */ int cporfs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, complex *b, integer *ldb, 
+	 complex *x, integer *ldx, real *ferr, real *berr, complex *work, 
+	real *rwork, integer *info);
+
+/* Subroutine */ int cporfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, real *s, 
+	complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, real 
+	*berr, integer *n_err_bnds__, real *err_bnds_norm__, real *
+	err_bnds_comp__, integer *nparams, real *params, complex *work, real *
+	rwork, integer *info);
+
+/* Subroutine */ int cposv_(char *uplo, integer *n, integer *nrhs, complex *a, 
+	 integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, char *
+	equed, real *s, complex *b, integer *ldb, complex *x, integer *ldx, 
+	real *rcond, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cposvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, char *
+	equed, real *s, complex *b, integer *ldb, complex *x, integer *ldx, 
+	real *rcond, real *rpvgrw, real *berr, integer *n_err_bnds__, real *
+	err_bnds_norm__, real *err_bnds_comp__, integer *nparams, real *
+	params, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cpotf2_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *info);
+
+/* Subroutine */ int cpotrf_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *info);
+
+/* Subroutine */ int cpotri_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *info);
+
+/* Subroutine */ int cpotrs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cppcon_(char *uplo, integer *n, complex *ap, real *anorm, 
+	 real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cppequ_(char *uplo, integer *n, complex *ap, real *s, 
+	real *scond, real *amax, integer *info);
+
+/* Subroutine */ int cpprfs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *afp, complex *b, integer *ldb, complex *x, integer *ldx, 
+	real *ferr, real *berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cppsv_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *ap, complex *afp, char *equed, real *s, complex *b, 
+	integer *ldb, complex *x, integer *ldx, real *rcond, real *ferr, real 
+	*berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cpptrf_(char *uplo, integer *n, complex *ap, integer *
+	info);
+
+/* Subroutine */ int cpptri_(char *uplo, integer *n, complex *ap, integer *
+	info);
+
+/* Subroutine */ int cpptrs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cpstf2_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *piv, integer *rank, real *tol, real *work, integer *info);
+
+/* Subroutine */ int cpstrf_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *piv, integer *rank, real *tol, real *work, integer *info);
+
+/* Subroutine */ int cptcon_(integer *n, real *d__, complex *e, real *anorm, 
+	real *rcond, real *rwork, integer *info);
+
+/* Subroutine */ int cpteqr_(char *compz, integer *n, real *d__, real *e, 
+	complex *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int cptrfs_(char *uplo, integer *n, integer *nrhs, real *d__, 
+	 complex *e, real *df, complex *ef, complex *b, integer *ldb, complex 
+	*x, integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cptsv_(integer *n, integer *nrhs, real *d__, complex *e, 
+	complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cptsvx_(char *fact, integer *n, integer *nrhs, real *d__, 
+	 complex *e, real *df, complex *ef, complex *b, integer *ldb, complex 
+	*x, integer *ldx, real *rcond, real *ferr, real *berr, complex *work, 
+	real *rwork, integer *info);
+
+/* Subroutine */ int cpttrf_(integer *n, real *d__, complex *e, integer *info);
+
+/* Subroutine */ int cpttrs_(char *uplo, integer *n, integer *nrhs, real *d__, 
+	 complex *e, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cptts2_(integer *iuplo, integer *n, integer *nrhs, real *
+	d__, complex *e, complex *b, integer *ldb);
+
+/* Subroutine */ int crot_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy, real *c__, complex *s);
+
+/* Subroutine */ int cspcon_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, real *anorm, real *rcond, complex *work, integer *info);
+
+/* Subroutine */ int cspmv_(char *uplo, integer *n, complex *alpha, complex *
+	ap, complex *x, integer *incx, complex *beta, complex *y, integer *
+	incy);
+
+/* Subroutine */ int cspr_(char *uplo, integer *n, complex *alpha, complex *x, 
+	 integer *incx, complex *ap);
+
+/* Subroutine */ int csprfs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *afp, integer *ipiv, complex *b, integer *ldb, complex *x, 
+	 integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int cspsv_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer *
+	ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int csptrf_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, integer *info);
+
+/* Subroutine */ int csptri_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, complex *work, integer *info);
+
+/* Subroutine */ int csptrs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int csrscl_(integer *n, real *sa, complex *sx, integer *incx);
+
+/* Subroutine */ int cstedc_(char *compz, integer *n, real *d__, real *e, 
+	complex *z__, integer *ldz, complex *work, integer *lwork, real *
+	rwork, integer *lrwork, integer *iwork, integer *liwork, integer *
+	info);
+
+/* Subroutine */ int cstegr_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, complex *z__, integer *ldz, integer *isuppz, 
+	real *work, integer *lwork, integer *iwork, integer *liwork, integer *
+	info);
+
+/* Subroutine */ int cstein_(integer *n, real *d__, real *e, integer *m, real 
+	*w, integer *iblock, integer *isplit, complex *z__, integer *ldz, 
+	real *work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int cstemr_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, integer *m, 
+	real *w, complex *z__, integer *ldz, integer *nzc, integer *isuppz, 
+	logical *tryrac, real *work, integer *lwork, integer *iwork, integer *
+	liwork, integer *info);
+
+/* Subroutine */ int csteqr_(char *compz, integer *n, real *d__, real *e, 
+	complex *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int csycon_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, real *anorm, real *rcond, complex *work, integer *
+	info);
+
+/* Subroutine */ int csyequb_(char *uplo, integer *n, complex *a, integer *
+	lda, real *s, real *scond, real *amax, complex *work, integer *info);
+
+/* Subroutine */ int csymv_(char *uplo, integer *n, complex *alpha, complex *
+	a, integer *lda, complex *x, integer *incx, complex *beta, complex *y, 
+	 integer *incy);
+
+/* Subroutine */ int csyr_(char *uplo, integer *n, complex *alpha, complex *x, 
+	 integer *incx, complex *a, integer *lda);
+
+/* Subroutine */ int csyrfs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+	b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int csyrfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, real *s, complex *b, integer *ldb, complex *x, integer *ldx, 
+	real *rcond, real *berr, integer *n_err_bnds__, real *err_bnds_norm__, 
+	 real *err_bnds_comp__, integer *nparams, real *params, complex *work, 
+	 real *rwork, integer *info);
+
+/* Subroutine */ int csysv_(char *uplo, integer *n, integer *nrhs, complex *a, 
+	 integer *lda, integer *ipiv, complex *b, integer *ldb, complex *work, 
+	 integer *lwork, integer *info);
+
+/* Subroutine */ int csysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, 
+	 real *ferr, real *berr, complex *work, integer *lwork, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int csysvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, char *equed, real *s, complex *b, integer *ldb, complex *x, 
+	integer *ldx, real *rcond, real *rpvgrw, real *berr, integer *
+	n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, integer *
+	nparams, real *params, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int csytf2_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, integer *info);
+
+/* Subroutine */ int csytrf_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int csytri_(char *uplo, integer *n, complex *a, integer *lda, 
+	 integer *ipiv, complex *work, integer *info);
+
+/* Subroutine */ int csytrs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int ctbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, complex *ab, integer *ldab, real *rcond, complex *work, 
+	real *rwork, integer *info);
+
+/* Subroutine */ int ctbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, complex *ab, integer *ldab, complex *b, 
+	integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int ctbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, complex *ab, integer *ldab, complex *b, 
+	integer *ldb, integer *info);
+
+/* Subroutine */ int ctfsm_(char *transr, char *side, char *uplo, char *trans, 
+	 char *diag, integer *m, integer *n, complex *alpha, complex *a, 
+	complex *b, integer *ldb);
+
+/* Subroutine */ int ctftri_(char *transr, char *uplo, char *diag, integer *n, 
+	 complex *a, integer *info);
+
+/* Subroutine */ int ctfttp_(char *transr, char *uplo, integer *n, complex *
+	arf, complex *ap, integer *info);
+
+/* Subroutine */ int ctfttr_(char *transr, char *uplo, integer *n, complex *
+	arf, complex *a, integer *lda, integer *info);
+
+/* Subroutine */ int ctgevc_(char *side, char *howmny, logical *select, 
+	integer *n, complex *s, integer *lds, complex *p, integer *ldp, 
+	complex *vl, integer *ldvl, complex *vr, integer *ldvr, integer *mm, 
+	integer *m, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int ctgex2_(logical *wantq, logical *wantz, integer *n, 
+	complex *a, integer *lda, complex *b, integer *ldb, complex *q, 
+	integer *ldq, complex *z__, integer *ldz, integer *j1, integer *info);
+
+/* Subroutine */ int ctgexc_(logical *wantq, logical *wantz, integer *n, 
+	complex *a, integer *lda, complex *b, integer *ldb, complex *q, 
+	integer *ldq, complex *z__, integer *ldz, integer *ifst, integer *
+	ilst, integer *info);
+
+/* Subroutine */ int ctgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, complex *a, integer *lda, complex *b, 
+	integer *ldb, complex *alpha, complex *beta, complex *q, integer *ldq, 
+	 complex *z__, integer *ldz, integer *m, real *pl, real *pr, real *
+	dif, complex *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+
+/* Subroutine */ int ctgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, complex *a, integer *
+	lda, complex *b, integer *ldb, real *tola, real *tolb, real *alpha, 
+	real *beta, complex *u, integer *ldu, complex *v, integer *ldv, 
+	complex *q, integer *ldq, complex *work, integer *ncycle, integer *
+	info);
+
+/* Subroutine */ int ctgsna_(char *job, char *howmny, logical *select, 
+	integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *vl, integer *ldvl, complex *vr, integer *ldvr, real *s, real 
+	*dif, integer *mm, integer *m, complex *work, integer *lwork, integer 
+	*iwork, integer *info);
+
+/* Subroutine */ int ctgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, complex *c__, 
+	integer *ldc, complex *d__, integer *ldd, complex *e, integer *lde, 
+	complex *f, integer *ldf, real *scale, real *rdsum, real *rdscal, 
+	integer *info);
+
+/* Subroutine */ int ctgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, complex *c__, 
+	integer *ldc, complex *d__, integer *ldd, complex *e, integer *lde, 
+	complex *f, integer *ldf, real *scale, real *dif, complex *work, 
+	integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int ctpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	complex *ap, real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int ctprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *ap, complex *b, integer *ldb, complex *x, 
+	integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int ctptri_(char *uplo, char *diag, integer *n, complex *ap, 
+	integer *info);
+
+/* Subroutine */ int ctptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *ap, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ctpttf_(char *transr, char *uplo, integer *n, complex *
+	ap, complex *arf, integer *info);
+
+/* Subroutine */ int ctpttr_(char *uplo, integer *n, complex *ap, complex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int ctrcon_(char *norm, char *uplo, char *diag, integer *n, 
+	complex *a, integer *lda, real *rcond, complex *work, real *rwork, 
+	integer *info);
+
+/* Subroutine */ int ctrevc_(char *side, char *howmny, logical *select, 
+	integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl, 
+	complex *vr, integer *ldvr, integer *mm, integer *m, complex *work, 
+	real *rwork, integer *info);
+
+/* Subroutine */ int ctrexc_(char *compq, integer *n, complex *t, integer *
+	ldt, complex *q, integer *ldq, integer *ifst, integer *ilst, integer *
+	info);
+
+/* Subroutine */ int ctrrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *x, integer *ldx, real *ferr, real *berr, complex *work, real 
+	*rwork, integer *info);
+
+/* Subroutine */ int ctrsen_(char *job, char *compq, logical *select, integer 
+	*n, complex *t, integer *ldt, complex *q, integer *ldq, complex *w, 
+	integer *m, real *s, real *sep, complex *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int ctrsna_(char *job, char *howmny, logical *select, 
+	integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl, 
+	complex *vr, integer *ldvr, real *s, real *sep, integer *mm, integer *
+	m, complex *work, integer *ldwork, real *rwork, integer *info);
+
+/* Subroutine */ int ctrsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *c__, integer *ldc, real *scale, integer *info);
+
+/* Subroutine */ int ctrti2_(char *uplo, char *diag, integer *n, complex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int ctrtri_(char *uplo, char *diag, integer *n, complex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int ctrtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *a, integer *lda, complex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int ctrttf_(char *transr, char *uplo, integer *n, complex *a, 
+	 integer *lda, complex *arf, integer *info);
+
+/* Subroutine */ int ctrttp_(char *uplo, integer *n, complex *a, integer *lda, 
+	 complex *ap, integer *info);
+
+/* Subroutine */ int ctzrqf_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, integer *info);
+
+/* Subroutine */ int ctzrzf_(integer *m, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cung2l_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cung2r_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cungbr_(char *vect, integer *m, integer *n, integer *k, 
+	complex *a, integer *lda, complex *tau, complex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int cunghr_(integer *n, integer *ilo, integer *ihi, complex *
+	a, integer *lda, complex *tau, complex *work, integer *lwork, integer 
+	*info);
+
+/* Subroutine */ int cungl2_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cunglq_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int cungql_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int cungqr_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int cungr2_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cungrq_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int cungtr_(char *uplo, integer *n, complex *a, integer *lda, 
+	 complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int cunmhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int cunml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int cunmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cupgtr_(char *uplo, integer *n, complex *ap, complex *
+	tau, complex *q, integer *ldq, complex *work, integer *info);
+
+/* Subroutine */ int cupmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, complex *ap, complex *tau, complex *c__, integer *ldc, 
+	complex *work, integer *info);
+
+/* Subroutine */ int dbdsdc_(char *uplo, char *compq, integer *n, doublereal *
+	d__, doublereal *e, doublereal *u, integer *ldu, doublereal *vt, 
+	integer *ldvt, doublereal *q, integer *iq, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, doublereal *d__, doublereal *e, doublereal *vt, 
+	integer *ldvt, doublereal *u, integer *ldu, doublereal *c__, integer *
+	ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int ddisna_(char *job, integer *m, integer *n, doublereal *
+	d__, doublereal *sep, integer *info);
+
+/* Subroutine */ int dgbbrd_(char *vect, integer *m, integer *n, integer *ncc, 
+	 integer *kl, integer *ku, doublereal *ab, integer *ldab, doublereal *
+	d__, doublereal *e, doublereal *q, integer *ldq, doublereal *pt, 
+	integer *ldpt, doublereal *c__, integer *ldc, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dgbcon_(char *norm, integer *n, integer *kl, integer *ku, 
+	 doublereal *ab, integer *ldab, integer *ipiv, doublereal *anorm, 
+	doublereal *rcond, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgbequ_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublereal *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, integer *
+	info);
+
+/* Subroutine */ int dgbequb_(integer *m, integer *n, integer *kl, integer *
+	ku, doublereal *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, integer *
+	info);
+
+/* Subroutine */ int dgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublereal *ab, integer *ldab, doublereal *afb, 
+	integer *ldafb, integer *ipiv, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgbrfsx_(char *trans, char *equed, integer *n, integer *
+	kl, integer *ku, integer *nrhs, doublereal *ab, integer *ldab, 
+	doublereal *afb, integer *ldafb, integer *ipiv, doublereal *r__, 
+	doublereal *c__, doublereal *b, integer *ldb, doublereal *x, integer *
+	ldx, doublereal *rcond, doublereal *berr, integer *n_err_bnds__, 
+	doublereal *err_bnds_norm__, doublereal *err_bnds_comp__, integer *
+	nparams, doublereal *params, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, doublereal *ab, integer *ldab, integer *ipiv, doublereal *b, 
+	integer *ldb, integer *info);
+
+/* Subroutine */ int dgbsvx_(char *fact, char *trans, integer *n, integer *kl, 
+	 integer *ku, integer *nrhs, doublereal *ab, integer *ldab, 
+	doublereal *afb, integer *ldafb, integer *ipiv, char *equed, 
+	doublereal *r__, doublereal *c__, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgbsvxx_(char *fact, char *trans, integer *n, integer *
+	kl, integer *ku, integer *nrhs, doublereal *ab, integer *ldab, 
+	doublereal *afb, integer *ldafb, integer *ipiv, char *equed, 
+	doublereal *r__, doublereal *c__, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *rcond, doublereal *rpvgrw, 
+	doublereal *berr, integer *n_err_bnds__, doublereal *err_bnds_norm__, 
+	doublereal *err_bnds_comp__, integer *nparams, doublereal *params, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgbtf2_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublereal *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgbtrf_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublereal *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublereal *ab, integer *ldab, integer *ipiv, 
+	doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *scale, integer *m, doublereal *v, integer *
+	ldv, integer *info);
+
+/* Subroutine */ int dgebal_(char *job, integer *n, doublereal *a, integer *
+	lda, integer *ilo, integer *ihi, doublereal *scale, integer *info);
+
+/* Subroutine */ int dgebd2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tauq, doublereal *
+	taup, doublereal *work, integer *info);
+
+/* Subroutine */ int dgebrd_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tauq, doublereal *
+	taup, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgecon_(char *norm, integer *n, doublereal *a, integer *
+	lda, doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dgeequ_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, doublereal 
+	*colcnd, doublereal *amax, integer *info);
+
+/* Subroutine */ int dgeequb_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, doublereal 
+	*colcnd, doublereal *amax, integer *info);
+
+/* Subroutine */ int dgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	doublereal *a, integer *lda, integer *sdim, doublereal *wr, 
+	doublereal *wi, doublereal *vs, integer *ldvs, doublereal *work, 
+	integer *lwork, logical *bwork, integer *info);
+
+/* Subroutine */ int dgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, doublereal *a, integer *lda, integer *sdim, 
+	doublereal *wr, doublereal *wi, doublereal *vs, integer *ldvs, 
+	doublereal *rconde, doublereal *rcondv, doublereal *work, integer *
+	lwork, integer *iwork, integer *liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int dgeev_(char *jobvl, char *jobvr, integer *n, doublereal *
+	a, integer *lda, doublereal *wr, doublereal *wi, doublereal *vl, 
+	integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int dgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublereal *a, integer *lda, doublereal *wr, 
+	doublereal *wi, doublereal *vl, integer *ldvl, doublereal *vr, 
+	integer *ldvr, integer *ilo, integer *ihi, doublereal *scale, 
+	doublereal *abnrm, doublereal *rconde, doublereal *rcondv, doublereal 
+	*work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int dgegs_(char *jobvsl, char *jobvsr, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	alphar, doublereal *alphai, doublereal *beta, doublereal *vsl, 
+	integer *ldvsl, doublereal *vsr, integer *ldvsr, doublereal *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int dgegv_(char *jobvl, char *jobvr, integer *n, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, 
+	doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl, 
+	doublereal *vr, integer *ldvr, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dgehd2_(integer *n, integer *ilo, integer *ihi, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dgehrd_(integer *n, integer *ilo, integer *ihi, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int dgejsv_(char *joba, char *jobu, char *jobv, char *jobr, 
+	char *jobt, char *jobp, integer *m, integer *n, doublereal *a, 
+	integer *lda, doublereal *sva, doublereal *u, integer *ldu, 
+	doublereal *v, integer *ldv, doublereal *work, integer *lwork, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int dgelq2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgelqf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgelsd_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork, 
+	 integer *iwork, integer *info);
+
+/* Subroutine */ int dgelss_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int dgelsx_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	jpvt, doublereal *rcond, integer *rank, doublereal *work, integer *
+	info);
+
+/* Subroutine */ int dgelsy_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	jpvt, doublereal *rcond, integer *rank, doublereal *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int dgeql2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgeqlf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgeqp3_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *jpvt, doublereal *tau, doublereal *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int dgeqpf_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *jpvt, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgeqr2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgeqrf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgerfs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *af, integer *ldaf, integer *
+	ipiv, doublereal *b, integer *ldb, doublereal *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dgerfsx_(char *trans, char *equed, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, doublereal *r__, doublereal *c__, doublereal *b, 
+	integer *ldb, doublereal *x, integer *ldx, doublereal *rcond, 
+	doublereal *berr, integer *n_err_bnds__, doublereal *err_bnds_norm__, 
+	doublereal *err_bnds_comp__, integer *nparams, doublereal *params, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgerq2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgerqf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgesc2_(integer *n, doublereal *a, integer *lda, 
+	doublereal *rhs, integer *ipiv, integer *jpiv, doublereal *scale);
+
+/* Subroutine */ int dgesdd_(char *jobz, integer *m, integer *n, doublereal *
+	a, integer *lda, doublereal *s, doublereal *u, integer *ldu, 
+	doublereal *vt, integer *ldvt, doublereal *work, integer *lwork, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int dgesv_(integer *n, integer *nrhs, doublereal *a, integer 
+	*lda, integer *ipiv, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dgesvd_(char *jobu, char *jobvt, integer *m, integer *n, 
+	doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *
+	ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dgesvj_(char *joba, char *jobu, char *jobv, integer *m, 
+	integer *n, doublereal *a, integer *lda, doublereal *sva, integer *mv, 
+	 doublereal *v, integer *ldv, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, char *equed, doublereal *r__, doublereal *c__, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dgesvxx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, char *equed, doublereal *r__, doublereal *c__, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *rpvgrw, doublereal *berr, integer *n_err_bnds__, 
+	doublereal *err_bnds_norm__, doublereal *err_bnds_comp__, integer *
+	nparams, doublereal *params, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dgetc2_(integer *n, doublereal *a, integer *lda, integer 
+	*ipiv, integer *jpiv, integer *info);
+
+/* Subroutine */ int dgetf2_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgetrf_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgetri_(integer *n, doublereal *a, integer *lda, integer 
+	*ipiv, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgetrs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
+	ldb, integer *info);
+
+/* Subroutine */ int dggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *lscale, doublereal *rscale, integer *m, 
+	doublereal *v, integer *ldv, integer *info);
+
+/* Subroutine */ int dggbal_(char *job, integer *n, doublereal *a, integer *
+	lda, doublereal *b, integer *ldb, integer *ilo, integer *ihi, 
+	doublereal *lscale, doublereal *rscale, doublereal *work, integer *
+	info);
+
+/* Subroutine */ int dgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, integer *n, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, integer *sdim, doublereal *alphar, doublereal *alphai, 
+	doublereal *beta, doublereal *vsl, integer *ldvsl, doublereal *vsr, 
+	integer *ldvsr, doublereal *work, integer *lwork, logical *bwork, 
+	integer *info);
+
+/* Subroutine */ int dggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, char *sense, integer *n, doublereal *a, integer *lda, 
+	doublereal *b, integer *ldb, integer *sdim, doublereal *alphar, 
+	doublereal *alphai, doublereal *beta, doublereal *vsl, integer *ldvsl, 
+	 doublereal *vsr, integer *ldvsr, doublereal *rconde, doublereal *
+	rcondv, doublereal *work, integer *lwork, integer *iwork, integer *
+	liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int dggev_(char *jobvl, char *jobvr, integer *n, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, 
+	doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl, 
+	doublereal *vr, integer *ldvr, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, 
+	integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale, 
+	doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal *
+	rcondv, doublereal *work, integer *lwork, integer *iwork, logical *
+	bwork, integer *info);
+
+/* Subroutine */ int dggglm_(integer *n, integer *m, integer *p, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *d__, 
+	doublereal *x, doublereal *y, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *q, integer *ldq, doublereal *z__, integer *
+	ldz, integer *info);
+
+/* Subroutine */ int dgglse_(integer *m, integer *n, integer *p, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *c__, 
+	doublereal *d__, doublereal *x, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dggqrf_(integer *n, integer *m, integer *p, doublereal *
+	a, integer *lda, doublereal *taua, doublereal *b, integer *ldb, 
+	doublereal *taub, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dggrqf_(integer *m, integer *p, integer *n, doublereal *
+	a, integer *lda, doublereal *taua, doublereal *b, integer *ldb, 
+	doublereal *taub, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, doublereal *a, 
+	integer *lda, doublereal *b, integer *ldb, doublereal *alpha, 
+	doublereal *beta, doublereal *u, integer *ldu, doublereal *v, integer 
+	*ldv, doublereal *q, integer *ldq, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *tola, doublereal *tolb, integer *k, integer 
+	*l, doublereal *u, integer *ldu, doublereal *v, integer *ldv, 
+	doublereal *q, integer *ldq, integer *iwork, doublereal *tau, 
+	doublereal *work, integer *info);
+
+/* Subroutine */ int dgsvj0_(char *jobv, integer *m, integer *n, doublereal *
+	a, integer *lda, doublereal *d__, doublereal *sva, integer *mv, 
+	doublereal *v, integer *ldv, doublereal *eps, doublereal *sfmin, 
+	doublereal *tol, integer *nsweep, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dgsvj1_(char *jobv, integer *m, integer *n, integer *n1, 
+	doublereal *a, integer *lda, doublereal *d__, doublereal *sva, 
+	integer *mv, doublereal *v, integer *ldv, doublereal *eps, doublereal 
+	*sfmin, doublereal *tol, integer *nsweep, doublereal *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int dgtcon_(char *norm, integer *n, doublereal *dl, 
+	doublereal *d__, doublereal *du, doublereal *du2, integer *ipiv, 
+	doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dgtrfs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *dl, doublereal *d__, doublereal *du, doublereal *dlf, 
+	doublereal *df, doublereal *duf, doublereal *du2, integer *ipiv, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int dgtsv_(integer *n, integer *nrhs, doublereal *dl, 
+	doublereal *d__, doublereal *du, doublereal *b, integer *ldb, integer 
+	*info);
+
+/* Subroutine */ int dgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublereal *dl, doublereal *d__, doublereal *du, doublereal *
+	dlf, doublereal *df, doublereal *duf, doublereal *du2, integer *ipiv, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dgttrf_(integer *n, doublereal *dl, doublereal *d__, 
+	doublereal *du, doublereal *du2, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgttrs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *dl, doublereal *d__, doublereal *du, doublereal *du2, 
+	integer *ipiv, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dgtts2_(integer *itrans, integer *n, integer *nrhs, 
+	doublereal *dl, doublereal *d__, doublereal *du, doublereal *du2, 
+	integer *ipiv, doublereal *b, integer *ldb);
+
+/* Subroutine */ int dhgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, doublereal *h__, integer *ldh, doublereal 
+	*t, integer *ldt, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *q, integer *ldq, doublereal *z__, integer *ldz, 
+	doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dhsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, doublereal *h__, integer *ldh, doublereal *wr, 
+	doublereal *wi, doublereal *vl, integer *ldvl, doublereal *vr, 
+	integer *ldvr, integer *mm, integer *m, doublereal *work, integer *
+	ifaill, integer *ifailr, integer *info);
+
+/* Subroutine */ int dhseqr_(char *job, char *compz, integer *n, integer *ilo, 
+	 integer *ihi, doublereal *h__, integer *ldh, doublereal *wr, 
+	doublereal *wi, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *info);
+
+logical disnan_(doublereal *din);
+
+/* Subroutine */ int dla_gbamv__(integer *trans, integer *m, integer *n, 
+	integer *kl, integer *ku, doublereal *alpha, doublereal *ab, integer *
+	ldab, doublereal *x, integer *incx, doublereal *beta, doublereal *y, 
+	integer *incy);
+
+doublereal dla_gbrcond__(char *trans, integer *n, integer *kl, integer *ku, 
+	doublereal *ab, integer *ldab, doublereal *afb, integer *ldafb, 
+	integer *ipiv, integer *cmode, doublereal *c__, integer *info, 
+	doublereal *work, integer *iwork, ftnlen trans_len);
+
+/* Subroutine */ int dla_gbrfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *kl, integer *ku, integer *nrhs, 
+	doublereal *ab, integer *ldab, doublereal *afb, integer *ldafb, 
+	integer *ipiv, logical *colequ, doublereal *c__, doublereal *b, 
+	integer *ldb, doublereal *y, integer *ldy, doublereal *berr_out__, 
+	integer *n_norms__, doublereal *errs_n__, doublereal *errs_c__, 
+	doublereal *res, doublereal *ayb, doublereal *dy, doublereal *
+	y_tail__, doublereal *rcond, integer *ithresh, doublereal *rthresh, 
+	doublereal *dz_ub__, logical *ignore_cwise__, integer *info);
+
+doublereal dla_gbrpvgrw__(integer *n, integer *kl, integer *ku, integer *
+	ncols, doublereal *ab, integer *ldab, doublereal *afb, integer *ldafb);
+
+/* Subroutine */ int dla_geamv__(integer *trans, integer *m, integer *n, 
+	doublereal *alpha, doublereal *a, integer *lda, doublereal *x, 
+	integer *incx, doublereal *beta, doublereal *y, integer *incy);
+
+doublereal dla_gercond__(char *trans, integer *n, doublereal *a, integer *lda,
+	 doublereal *af, integer *ldaf, integer *ipiv, integer *cmode, 
+	doublereal *c__, integer *info, doublereal *work, integer *iwork, 
+	ftnlen trans_len);
+
+/* Subroutine */ int dla_gerfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *nrhs, doublereal *a, integer *lda, 
+	doublereal *af, integer *ldaf, integer *ipiv, logical *colequ, 
+	doublereal *c__, doublereal *b, integer *ldb, doublereal *y, integer *
+	ldy, doublereal *berr_out__, integer *n_norms__, doublereal *errs_n__,
+	 doublereal *errs_c__, doublereal *res, doublereal *ayb, doublereal *
+	dy, doublereal *y_tail__, doublereal *rcond, integer *ithresh, 
+	doublereal *rthresh, doublereal *dz_ub__, logical *ignore_cwise__, 
+	integer *info);
+
+/* Subroutine */ int dla_lin_berr__(integer *n, integer *nz, integer *nrhs, 
+	doublereal *res, doublereal *ayb, doublereal *berr);
+
+doublereal dla_porcond__(char *uplo, integer *n, doublereal *a, integer *lda, 
+	doublereal *af, integer *ldaf, integer *cmode, doublereal *c__, 
+	integer *info, doublereal *work, integer *iwork, ftnlen uplo_len);
+
+/* Subroutine */ int dla_porfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, doublereal *a, integer *lda, doublereal *
+	af, integer *ldaf, logical *colequ, doublereal *c__, doublereal *b, 
+	integer *ldb, doublereal *y, integer *ldy, doublereal *berr_out__, 
+	integer *n_norms__, doublereal *errs_n__, doublereal *errs_c__, 
+	doublereal *res, doublereal *ayb, doublereal *dy, doublereal *
+	y_tail__, doublereal *rcond, integer *ithresh, doublereal *rthresh, 
+	doublereal *dz_ub__, logical *ignore_cwise__, integer *info, ftnlen 
+	uplo_len);
+
+doublereal dla_porpvgrw__(char *uplo, integer *ncols, doublereal *a, integer *
+	lda, doublereal *af, integer *ldaf, doublereal *work, ftnlen uplo_len);
+
+doublereal dla_rpvgrw__(integer *n, integer *ncols, doublereal *a, integer *
+	lda, doublereal *af, integer *ldaf);
+
+/* Subroutine */ int dla_syamv__(integer *uplo, integer *n, doublereal *alpha,
+	 doublereal *a, integer *lda, doublereal *x, integer *incx, 
+	doublereal *beta, doublereal *y, integer *incy);
+
+doublereal dla_syrcond__(char *uplo, integer *n, doublereal *a, integer *lda, 
+	doublereal *af, integer *ldaf, integer *ipiv, integer *cmode, 
+	doublereal *c__, integer *info, doublereal *work, integer *iwork, 
+	ftnlen uplo_len);
+
+/* Subroutine */ int dla_syrfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, doublereal *a, integer *lda, doublereal *
+	af, integer *ldaf, integer *ipiv, logical *colequ, doublereal *c__, 
+	doublereal *b, integer *ldb, doublereal *y, integer *ldy, doublereal *
+	berr_out__, integer *n_norms__, doublereal *errs_n__, doublereal *
+	errs_c__, doublereal *res, doublereal *ayb, doublereal *dy, 
+	doublereal *y_tail__, doublereal *rcond, integer *ithresh, doublereal 
+	*rthresh, doublereal *dz_ub__, logical *ignore_cwise__, integer *info,
+	 ftnlen uplo_len);
+
+doublereal dla_syrpvgrw__(char *uplo, integer *n, integer *info, doublereal *
+	a, integer *lda, doublereal *af, integer *ldaf, integer *ipiv, 
+	doublereal *work, ftnlen uplo_len);
+
+/* Subroutine */ int dla_wwaddw__(integer *n, doublereal *x, doublereal *y, 
+	doublereal *w);
+
+/* Subroutine */ int dlabad_(doublereal *small, doublereal *large);
+
+/* Subroutine */ int dlabrd_(integer *m, integer *n, integer *nb, doublereal *
+	a, integer *lda, doublereal *d__, doublereal *e, doublereal *tauq, 
+	doublereal *taup, doublereal *x, integer *ldx, doublereal *y, integer 
+	*ldy);
+
+/* Subroutine */ int dlacn2_(integer *n, doublereal *v, doublereal *x, 
+	integer *isgn, doublereal *est, integer *kase, integer *isave);
+
+/* Subroutine */ int dlacon_(integer *n, doublereal *v, doublereal *x, 
+	integer *isgn, doublereal *est, integer *kase);
+
+/* Subroutine */ int dlacpy_(char *uplo, integer *m, integer *n, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb);
+
+/* Subroutine */ int dladiv_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *d__, doublereal *p, doublereal *q);
+
+/* Subroutine */ int dlae2_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *rt1, doublereal *rt2);
+
+/* Subroutine */ int dlaebz_(integer *ijob, integer *nitmax, integer *n, 
+	integer *mmax, integer *minp, integer *nbmin, doublereal *abstol, 
+	doublereal *reltol, doublereal *pivmin, doublereal *d__, doublereal *
+	e, doublereal *e2, integer *nval, doublereal *ab, doublereal *c__, 
+	integer *mout, integer *nab, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dlaed0_(integer *icompq, integer *qsiz, integer *n, 
+	doublereal *d__, doublereal *e, doublereal *q, integer *ldq, 
+	doublereal *qstore, integer *ldqs, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dlaed1_(integer *n, doublereal *d__, doublereal *q, 
+	integer *ldq, integer *indxq, doublereal *rho, integer *cutpnt, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlaed2_(integer *k, integer *n, integer *n1, doublereal *
+	d__, doublereal *q, integer *ldq, integer *indxq, doublereal *rho, 
+	doublereal *z__, doublereal *dlamda, doublereal *w, doublereal *q2, 
+	integer *indx, integer *indxc, integer *indxp, integer *coltyp, 
+	integer *info);
+
+/* Subroutine */ int dlaed3_(integer *k, integer *n, integer *n1, doublereal *
+	d__, doublereal *q, integer *ldq, doublereal *rho, doublereal *dlamda, 
+	 doublereal *q2, integer *indx, integer *ctot, doublereal *w, 
+	doublereal *s, integer *info);
+
+/* Subroutine */ int dlaed4_(integer *n, integer *i__, doublereal *d__, 
+	doublereal *z__, doublereal *delta, doublereal *rho, doublereal *dlam, 
+	 integer *info);
+
+/* Subroutine */ int dlaed5_(integer *i__, doublereal *d__, doublereal *z__, 
+	doublereal *delta, doublereal *rho, doublereal *dlam);
+
+/* Subroutine */ int dlaed6_(integer *kniter, logical *orgati, doublereal *
+	rho, doublereal *d__, doublereal *z__, doublereal *finit, doublereal *
+	tau, integer *info);
+
+/* Subroutine */ int dlaed7_(integer *icompq, integer *n, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, doublereal *d__, 
+	doublereal *q, integer *ldq, integer *indxq, doublereal *rho, integer 
+	*cutpnt, doublereal *qstore, integer *qptr, integer *prmptr, integer *
+	perm, integer *givptr, integer *givcol, doublereal *givnum, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlaed8_(integer *icompq, integer *k, integer *n, integer 
+	*qsiz, doublereal *d__, doublereal *q, integer *ldq, integer *indxq, 
+	doublereal *rho, integer *cutpnt, doublereal *z__, doublereal *dlamda, 
+	 doublereal *q2, integer *ldq2, doublereal *w, integer *perm, integer 
+	*givptr, integer *givcol, doublereal *givnum, integer *indxp, integer 
+	*indx, integer *info);
+
+/* Subroutine */ int dlaed9_(integer *k, integer *kstart, integer *kstop, 
+	integer *n, doublereal *d__, doublereal *q, integer *ldq, doublereal *
+	rho, doublereal *dlamda, doublereal *w, doublereal *s, integer *lds, 
+	integer *info);
+
+/* Subroutine */ int dlaeda_(integer *n, integer *tlvls, integer *curlvl, 
+	integer *curpbm, integer *prmptr, integer *perm, integer *givptr, 
+	integer *givcol, doublereal *givnum, doublereal *q, integer *qptr, 
+	doublereal *z__, doublereal *ztemp, integer *info);
+
+/* Subroutine */ int dlaein_(logical *rightv, logical *noinit, integer *n, 
+	doublereal *h__, integer *ldh, doublereal *wr, doublereal *wi, 
+	doublereal *vr, doublereal *vi, doublereal *b, integer *ldb, 
+	doublereal *work, doublereal *eps3, doublereal *smlnum, doublereal *
+	bignum, integer *info);
+
+/* Subroutine */ int dlaev2_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *rt1, doublereal *rt2, doublereal *cs1, doublereal *sn1);
+
+/* Subroutine */ int dlaexc_(logical *wantq, integer *n, doublereal *t, 
+	integer *ldt, doublereal *q, integer *ldq, integer *j1, integer *n1, 
+	integer *n2, doublereal *work, integer *info);
+
+/* Subroutine */ int dlag2_(doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *safmin, doublereal *scale1, doublereal *
+	scale2, doublereal *wr1, doublereal *wr2, doublereal *wi);
+
+/* Subroutine */ int dlag2s_(integer *m, integer *n, doublereal *a, integer *
+	lda, real *sa, integer *ldsa, integer *info);
+
+/* Subroutine */ int dlags2_(logical *upper, doublereal *a1, doublereal *a2, 
+	doublereal *a3, doublereal *b1, doublereal *b2, doublereal *b3, 
+	doublereal *csu, doublereal *snu, doublereal *csv, doublereal *snv, 
+	doublereal *csq, doublereal *snq);
+
+/* Subroutine */ int dlagtf_(integer *n, doublereal *a, doublereal *lambda, 
+	doublereal *b, doublereal *c__, doublereal *tol, doublereal *d__, 
+	integer *in, integer *info);
+
+/* Subroutine */ int dlagtm_(char *trans, integer *n, integer *nrhs, 
+	doublereal *alpha, doublereal *dl, doublereal *d__, doublereal *du, 
+	doublereal *x, integer *ldx, doublereal *beta, doublereal *b, integer 
+	*ldb);
+
+/* Subroutine */ int dlagts_(integer *job, integer *n, doublereal *a, 
+	doublereal *b, doublereal *c__, doublereal *d__, integer *in, 
+	doublereal *y, doublereal *tol, integer *info);
+
+/* Subroutine */ int dlagv2_(doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *csl, doublereal *snl, doublereal *csr, doublereal *
+	snr);
+
+/* Subroutine */ int dlahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublereal *h__, integer *ldh, doublereal 
+	*wr, doublereal *wi, integer *iloz, integer *ihiz, doublereal *z__, 
+	integer *ldz, integer *info);
+
+/* Subroutine */ int dlahr2_(integer *n, integer *k, integer *nb, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *t, integer *ldt, 
+	doublereal *y, integer *ldy);
+
+/* Subroutine */ int dlahrd_(integer *n, integer *k, integer *nb, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *t, integer *ldt, 
+	doublereal *y, integer *ldy);
+
+/* Subroutine */ int dlaic1_(integer *job, integer *j, doublereal *x, 
+	doublereal *sest, doublereal *w, doublereal *gamma, doublereal *
+	sestpr, doublereal *s, doublereal *c__);
+
+logical dlaisnan_(doublereal *din1, doublereal *din2);
+
+/* Subroutine */ int dlaln2_(logical *ltrans, integer *na, integer *nw, 
+	doublereal *smin, doublereal *ca, doublereal *a, integer *lda, 
+	doublereal *d1, doublereal *d2, doublereal *b, integer *ldb, 
+	doublereal *wr, doublereal *wi, doublereal *x, integer *ldx, 
+	doublereal *scale, doublereal *xnorm, integer *info);
+
+/* Subroutine */ int dlals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, doublereal *b, integer *ldb, doublereal 
+	*bx, integer *ldbx, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, doublereal *givnum, integer *ldgnum, doublereal *
+	poles, doublereal *difl, doublereal *difr, doublereal *z__, integer *
+	k, doublereal *c__, doublereal *s, doublereal *work, integer *info);
+
+/* Subroutine */ int dlalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, doublereal *b, integer *ldb, doublereal *bx, integer *
+	ldbx, doublereal *u, integer *ldu, doublereal *vt, integer *k, 
+	doublereal *difl, doublereal *difr, doublereal *z__, doublereal *
+	poles, integer *givptr, integer *givcol, integer *ldgcol, integer *
+	perm, doublereal *givnum, doublereal *c__, doublereal *s, doublereal *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlalsd_(char *uplo, integer *smlsiz, integer *n, integer 
+	*nrhs, doublereal *d__, doublereal *e, doublereal *b, integer *ldb, 
+	doublereal *rcond, integer *rank, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dlamrg_(integer *n1, integer *n2, doublereal *a, integer 
+	*dtrd1, integer *dtrd2, integer *index);
+
+integer dlaneg_(integer *n, doublereal *d__, doublereal *lld, doublereal *
+	sigma, doublereal *pivmin, integer *r__);
+
+doublereal dlangb_(char *norm, integer *n, integer *kl, integer *ku, 
+	doublereal *ab, integer *ldab, doublereal *work);
+
+doublereal dlange_(char *norm, integer *m, integer *n, doublereal *a, integer 
+	*lda, doublereal *work);
+
+doublereal dlangt_(char *norm, integer *n, doublereal *dl, doublereal *d__, 
+	doublereal *du);
+
+doublereal dlanhs_(char *norm, integer *n, doublereal *a, integer *lda, 
+	doublereal *work);
+
+doublereal dlansb_(char *norm, char *uplo, integer *n, integer *k, doublereal 
+	*ab, integer *ldab, doublereal *work);
+
+doublereal dlansf_(char *norm, char *transr, char *uplo, integer *n, 
+	doublereal *a, doublereal *work);
+
+doublereal dlansp_(char *norm, char *uplo, integer *n, doublereal *ap, 
+	doublereal *work);
+
+doublereal dlanst_(char *norm, integer *n, doublereal *d__, doublereal *e);
+
+doublereal dlansy_(char *norm, char *uplo, integer *n, doublereal *a, integer 
+	*lda, doublereal *work);
+
+doublereal dlantb_(char *norm, char *uplo, char *diag, integer *n, integer *k, 
+	 doublereal *ab, integer *ldab, doublereal *work);
+
+doublereal dlantp_(char *norm, char *uplo, char *diag, integer *n, doublereal 
+	*ap, doublereal *work);
+
+doublereal dlantr_(char *norm, char *uplo, char *diag, integer *m, integer *n, 
+	 doublereal *a, integer *lda, doublereal *work);
+
+/* Subroutine */ int dlanv2_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *d__, doublereal *rt1r, doublereal *rt1i, doublereal *rt2r, 
+	 doublereal *rt2i, doublereal *cs, doublereal *sn);
+
+/* Subroutine */ int dlapll_(integer *n, doublereal *x, integer *incx, 
+	doublereal *y, integer *incy, doublereal *ssmin);
+
+/* Subroutine */ int dlapmt_(logical *forwrd, integer *m, integer *n, 
+	doublereal *x, integer *ldx, integer *k);
+
+doublereal dlapy2_(doublereal *x, doublereal *y);
+
+doublereal dlapy3_(doublereal *x, doublereal *y, doublereal *z__);
+
+/* Subroutine */ int dlaqgb_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublereal *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqge_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, doublereal 
+	*colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqp2_(integer *m, integer *n, integer *offset, 
+	doublereal *a, integer *lda, integer *jpvt, doublereal *tau, 
+	doublereal *vn1, doublereal *vn2, doublereal *work);
+
+/* Subroutine */ int dlaqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, doublereal *a, integer *lda, integer *jpvt, 
+	doublereal *tau, doublereal *vn1, doublereal *vn2, doublereal *auxv, 
+	doublereal *f, integer *ldf);
+
+/* Subroutine */ int dlaqr0_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublereal *h__, integer *ldh, doublereal 
+	*wr, doublereal *wi, integer *iloz, integer *ihiz, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dlaqr1_(integer *n, doublereal *h__, integer *ldh, 
+	doublereal *sr1, doublereal *si1, doublereal *sr2, doublereal *si2, 
+	doublereal *v);
+
+/* Subroutine */ int dlaqr2_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, doublereal *h__, integer *
+	ldh, integer *iloz, integer *ihiz, doublereal *z__, integer *ldz, 
+	integer *ns, integer *nd, doublereal *sr, doublereal *si, doublereal *
+	v, integer *ldv, integer *nh, doublereal *t, integer *ldt, integer *
+	nv, doublereal *wv, integer *ldwv, doublereal *work, integer *lwork);
+
+/* Subroutine */ int dlaqr3_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, doublereal *h__, integer *
+	ldh, integer *iloz, integer *ihiz, doublereal *z__, integer *ldz, 
+	integer *ns, integer *nd, doublereal *sr, doublereal *si, doublereal *
+	v, integer *ldv, integer *nh, doublereal *t, integer *ldt, integer *
+	nv, doublereal *wv, integer *ldwv, doublereal *work, integer *lwork);
+
+/* Subroutine */ int dlaqr4_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublereal *h__, integer *ldh, doublereal 
+	*wr, doublereal *wi, integer *iloz, integer *ihiz, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dlaqr5_(logical *wantt, logical *wantz, integer *kacc22, 
+	integer *n, integer *ktop, integer *kbot, integer *nshfts, doublereal 
+	*sr, doublereal *si, doublereal *h__, integer *ldh, integer *iloz, 
+	integer *ihiz, doublereal *z__, integer *ldz, doublereal *v, integer *
+	ldv, doublereal *u, integer *ldu, integer *nv, doublereal *wv, 
+	integer *ldwv, integer *nh, doublereal *wh, integer *ldwh);
+
+/* Subroutine */ int dlaqsb_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, doublereal *s, doublereal *scond, doublereal *amax, 
+	 char *equed);
+
+/* Subroutine */ int dlaqsp_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqsy_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqtr_(logical *ltran, logical *lreal, integer *n, 
+	doublereal *t, integer *ldt, doublereal *b, doublereal *w, doublereal 
+	*scale, doublereal *x, doublereal *work, integer *info);
+
+/* Subroutine */ int dlar1v_(integer *n, integer *b1, integer *bn, doublereal 
+	*lambda, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
+	lld, doublereal *pivmin, doublereal *gaptol, doublereal *z__, logical 
+	*wantnc, integer *negcnt, doublereal *ztz, doublereal *mingma, 
+	integer *r__, integer *isuppz, doublereal *nrminv, doublereal *resid, 
+	doublereal *rqcorr, doublereal *work);
+
+/* Subroutine */ int dlar2v_(integer *n, doublereal *x, doublereal *y, 
+	doublereal *z__, integer *incx, doublereal *c__, doublereal *s, 
+	integer *incc);
+
+/* Subroutine */ int dlarf_(char *side, integer *m, integer *n, doublereal *v, 
+	 integer *incv, doublereal *tau, doublereal *c__, integer *ldc, 
+	doublereal *work);
+
+/* Subroutine */ int dlarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, doublereal *v, integer *
+	ldv, doublereal *t, integer *ldt, doublereal *c__, integer *ldc, 
+	doublereal *work, integer *ldwork);
+
+/* Subroutine */ int dlarfg_(integer *n, doublereal *alpha, doublereal *x, 
+	integer *incx, doublereal *tau);
+
+/* Subroutine */ int dlarfp_(integer *n, doublereal *alpha, doublereal *x, 
+	integer *incx, doublereal *tau);
+
+/* Subroutine */ int dlarft_(char *direct, char *storev, integer *n, integer *
+	k, doublereal *v, integer *ldv, doublereal *tau, doublereal *t, 
+	integer *ldt);
+
+/* Subroutine */ int dlarfx_(char *side, integer *m, integer *n, doublereal *
+	v, doublereal *tau, doublereal *c__, integer *ldc, doublereal *work);
+
+/* Subroutine */ int dlargv_(integer *n, doublereal *x, integer *incx, 
+	doublereal *y, integer *incy, doublereal *c__, integer *incc);
+
+/* Subroutine */ int dlarnv_(integer *idist, integer *iseed, integer *n, 
+	doublereal *x);
+
+/* Subroutine */ int dlarra_(integer *n, doublereal *d__, doublereal *e, 
+	doublereal *e2, doublereal *spltol, doublereal *tnrm, integer *nsplit, 
+	 integer *isplit, integer *info);
+
+/* Subroutine */ int dlarrb_(integer *n, doublereal *d__, doublereal *lld, 
+	integer *ifirst, integer *ilast, doublereal *rtol1, doublereal *rtol2, 
+	 integer *offset, doublereal *w, doublereal *wgap, doublereal *werr, 
+	doublereal *work, integer *iwork, doublereal *pivmin, doublereal *
+	spdiam, integer *twist, integer *info);
+
+/* Subroutine */ int dlarrc_(char *jobt, integer *n, doublereal *vl, 
+	doublereal *vu, doublereal *d__, doublereal *e, doublereal *pivmin, 
+	integer *eigcnt, integer *lcnt, integer *rcnt, integer *info);
+
+/* Subroutine */ int dlarrd_(char *range, char *order, integer *n, doublereal 
+	*vl, doublereal *vu, integer *il, integer *iu, doublereal *gers, 
+	doublereal *reltol, doublereal *d__, doublereal *e, doublereal *e2, 
+	doublereal *pivmin, integer *nsplit, integer *isplit, integer *m, 
+	doublereal *w, doublereal *werr, doublereal *wl, doublereal *wu, 
+	integer *iblock, integer *indexw, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dlarre_(char *range, integer *n, doublereal *vl, 
+	doublereal *vu, integer *il, integer *iu, doublereal *d__, doublereal 
+	*e, doublereal *e2, doublereal *rtol1, doublereal *rtol2, doublereal *
+	spltol, integer *nsplit, integer *isplit, integer *m, doublereal *w, 
+	doublereal *werr, doublereal *wgap, integer *iblock, integer *indexw, 
+	doublereal *gers, doublereal *pivmin, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dlarrf_(integer *n, doublereal *d__, doublereal *l, 
+	doublereal *ld, integer *clstrt, integer *clend, doublereal *w, 
+	doublereal *wgap, doublereal *werr, doublereal *spdiam, doublereal *
+	clgapl, doublereal *clgapr, doublereal *pivmin, doublereal *sigma, 
+	doublereal *dplus, doublereal *lplus, doublereal *work, integer *info);
+
+/* Subroutine */ int dlarrj_(integer *n, doublereal *d__, doublereal *e2, 
+	integer *ifirst, integer *ilast, doublereal *rtol, integer *offset, 
+	doublereal *w, doublereal *werr, doublereal *work, integer *iwork, 
+	doublereal *pivmin, doublereal *spdiam, integer *info);
+
+/* Subroutine */ int dlarrk_(integer *n, integer *iw, doublereal *gl, 
+	doublereal *gu, doublereal *d__, doublereal *e2, doublereal *pivmin, 
+	doublereal *reltol, doublereal *w, doublereal *werr, integer *info);
+
+/* Subroutine */ int dlarrr_(integer *n, doublereal *d__, doublereal *e, 
+	integer *info);
+
+/* Subroutine */ int dlarrv_(integer *n, doublereal *vl, doublereal *vu, 
+	doublereal *d__, doublereal *l, doublereal *pivmin, integer *isplit, 
+	integer *m, integer *dol, integer *dou, doublereal *minrgp, 
+	doublereal *rtol1, doublereal *rtol2, doublereal *w, doublereal *werr, 
+	 doublereal *wgap, integer *iblock, integer *indexw, doublereal *gers, 
+	 doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int dlarscl2_(integer *m, integer *n, doublereal *d__, 
+	doublereal *x, integer *ldx);
+
+/* Subroutine */ int dlartg_(doublereal *f, doublereal *g, doublereal *cs, 
+	doublereal *sn, doublereal *r__);
+
+/* Subroutine */ int dlartv_(integer *n, doublereal *x, integer *incx, 
+	doublereal *y, integer *incy, doublereal *c__, doublereal *s, integer 
+	*incc);
+
+/* Subroutine */ int dlaruv_(integer *iseed, integer *n, doublereal *x);
+
+/* Subroutine */ int dlarz_(char *side, integer *m, integer *n, integer *l, 
+	doublereal *v, integer *incv, doublereal *tau, doublereal *c__, 
+	integer *ldc, doublereal *work);
+
+/* Subroutine */ int dlarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, doublereal *v, 
+	 integer *ldv, doublereal *t, integer *ldt, doublereal *c__, integer *
+	ldc, doublereal *work, integer *ldwork);
+
+/* Subroutine */ int dlarzt_(char *direct, char *storev, integer *n, integer *
+	k, doublereal *v, integer *ldv, doublereal *tau, doublereal *t, 
+	integer *ldt);
+
+/* Subroutine */ int dlas2_(doublereal *f, doublereal *g, doublereal *h__, 
+	doublereal *ssmin, doublereal *ssmax);
+
+/* Subroutine */ int dlascl_(char *type__, integer *kl, integer *ku, 
+	doublereal *cfrom, doublereal *cto, integer *m, integer *n, 
+	doublereal *a, integer *lda, integer *info);
+
+/* Subroutine */ int dlascl2_(integer *m, integer *n, doublereal *d__, 
+	doublereal *x, integer *ldx);
+
+/* Subroutine */ int dlasd0_(integer *n, integer *sqre, doublereal *d__, 
+	doublereal *e, doublereal *u, integer *ldu, doublereal *vt, integer *
+	ldvt, integer *smlsiz, integer *iwork, doublereal *work, integer *
+	info);
+
+/* Subroutine */ int dlasd1_(integer *nl, integer *nr, integer *sqre, 
+	doublereal *d__, doublereal *alpha, doublereal *beta, doublereal *u, 
+	integer *ldu, doublereal *vt, integer *ldvt, integer *idxq, integer *
+	iwork, doublereal *work, integer *info);
+
+/* Subroutine */ int dlasd2_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, doublereal *d__, doublereal *z__, doublereal *alpha, doublereal *
+	beta, doublereal *u, integer *ldu, doublereal *vt, integer *ldvt, 
+	doublereal *dsigma, doublereal *u2, integer *ldu2, doublereal *vt2, 
+	integer *ldvt2, integer *idxp, integer *idx, integer *idxc, integer *
+	idxq, integer *coltyp, integer *info);
+
+/* Subroutine */ int dlasd3_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, doublereal *d__, doublereal *q, integer *ldq, doublereal *dsigma, 
+	doublereal *u, integer *ldu, doublereal *u2, integer *ldu2, 
+	doublereal *vt, integer *ldvt, doublereal *vt2, integer *ldvt2, 
+	integer *idxc, integer *ctot, doublereal *z__, integer *info);
+
+/* Subroutine */ int dlasd4_(integer *n, integer *i__, doublereal *d__, 
+	doublereal *z__, doublereal *delta, doublereal *rho, doublereal *
+	sigma, doublereal *work, integer *info);
+
+/* Subroutine */ int dlasd5_(integer *i__, doublereal *d__, doublereal *z__, 
+	doublereal *delta, doublereal *rho, doublereal *dsigma, doublereal *
+	work);
+
+/* Subroutine */ int dlasd6_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, doublereal *d__, doublereal *vf, doublereal *vl, 
+	doublereal *alpha, doublereal *beta, integer *idxq, integer *perm, 
+	integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum, 
+	 integer *ldgnum, doublereal *poles, doublereal *difl, doublereal *
+	difr, doublereal *z__, integer *k, doublereal *c__, doublereal *s, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlasd7_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *k, doublereal *d__, doublereal *z__, 
+	doublereal *zw, doublereal *vf, doublereal *vfw, doublereal *vl, 
+	doublereal *vlw, doublereal *alpha, doublereal *beta, doublereal *
+	dsigma, integer *idx, integer *idxp, integer *idxq, integer *perm, 
+	integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum, 
+	 integer *ldgnum, doublereal *c__, doublereal *s, integer *info);
+
+/* Subroutine */ int dlasd8_(integer *icompq, integer *k, doublereal *d__, 
+	doublereal *z__, doublereal *vf, doublereal *vl, doublereal *difl, 
+	doublereal *difr, integer *lddifr, doublereal *dsigma, doublereal *
+	work, integer *info);
+
+/* Subroutine */ int dlasda_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *sqre, doublereal *d__, doublereal *e, doublereal *u, integer 
+	*ldu, doublereal *vt, integer *k, doublereal *difl, doublereal *difr, 
+	doublereal *z__, doublereal *poles, integer *givptr, integer *givcol, 
+	integer *ldgcol, integer *perm, doublereal *givnum, doublereal *c__, 
+	doublereal *s, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlasdq_(char *uplo, integer *sqre, integer *n, integer *
+	ncvt, integer *nru, integer *ncc, doublereal *d__, doublereal *e, 
+	doublereal *vt, integer *ldvt, doublereal *u, integer *ldu, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dlasdt_(integer *n, integer *lvl, integer *nd, integer *
+	inode, integer *ndiml, integer *ndimr, integer *msub);
+
+/* Subroutine */ int dlaset_(char *uplo, integer *m, integer *n, doublereal *
+	alpha, doublereal *beta, doublereal *a, integer *lda);
+
+/* Subroutine */ int dlasq1_(integer *n, doublereal *d__, doublereal *e, 
+	doublereal *work, integer *info);
+
+/* Subroutine */ int dlasq2_(integer *n, doublereal *z__, integer *info);
+
+/* Subroutine */ int dlasq3_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, doublereal *dmin__, doublereal *sigma, doublereal *desig, 
+	 doublereal *qmax, integer *nfail, integer *iter, integer *ndiv, 
+	logical *ieee, integer *ttype, doublereal *dmin1, doublereal *dmin2, 
+	doublereal *dn, doublereal *dn1, doublereal *dn2, doublereal *g, 
+	doublereal *tau);
+
+/* Subroutine */ int dlasq4_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, integer *n0in, doublereal *dmin__, doublereal *dmin1, 
+	doublereal *dmin2, doublereal *dn, doublereal *dn1, doublereal *dn2, 
+	doublereal *tau, integer *ttype, doublereal *g);
+
+/* Subroutine */ int dlasq5_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, doublereal *tau, doublereal *dmin__, doublereal *dmin1, 
+	doublereal *dmin2, doublereal *dn, doublereal *dnm1, doublereal *dnm2, 
+	 logical *ieee);
+
+/* Subroutine */ int dlasq6_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, doublereal *dmin__, doublereal *dmin1, doublereal *dmin2, 
+	 doublereal *dn, doublereal *dnm1, doublereal *dnm2);
+
+/* Subroutine */ int dlasr_(char *side, char *pivot, char *direct, integer *m, 
+	 integer *n, doublereal *c__, doublereal *s, doublereal *a, integer *
+	lda);
+
+/* Subroutine */ int dlasrt_(char *id, integer *n, doublereal *d__, integer *
+	info);
+
+/* Subroutine */ int dlassq_(integer *n, doublereal *x, integer *incx, 
+	doublereal *scale, doublereal *sumsq);
+
+/* Subroutine */ int dlasv2_(doublereal *f, doublereal *g, doublereal *h__, 
+	doublereal *ssmin, doublereal *ssmax, doublereal *snr, doublereal *
+	csr, doublereal *snl, doublereal *csl);
+
+/* Subroutine */ int dlaswp_(integer *n, doublereal *a, integer *lda, integer 
+	*k1, integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int dlasy2_(logical *ltranl, logical *ltranr, integer *isgn, 
+	integer *n1, integer *n2, doublereal *tl, integer *ldtl, doublereal *
+	tr, integer *ldtr, doublereal *b, integer *ldb, doublereal *scale, 
+	doublereal *x, integer *ldx, doublereal *xnorm, integer *info);
+
+/* Subroutine */ int dlasyf_(char *uplo, integer *n, integer *nb, integer *kb, 
+	 doublereal *a, integer *lda, integer *ipiv, doublereal *w, integer *
+	ldw, integer *info);
+
+/* Subroutine */ int dlat2s_(char *uplo, integer *n, doublereal *a, integer *
+	lda, real *sa, integer *ldsa, integer *info);
+
+/* Subroutine */ int dlatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, doublereal *ab, integer *ldab, 
+	doublereal *x, doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int dlatdf_(integer *ijob, integer *n, doublereal *z__, 
+	integer *ldz, doublereal *rhs, doublereal *rdsum, doublereal *rdscal, 
+	integer *ipiv, integer *jpiv);
+
+/* Subroutine */ int dlatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublereal *ap, doublereal *x, doublereal *scale, 
+	doublereal *cnorm, integer *info);
+
+/* Subroutine */ int dlatrd_(char *uplo, integer *n, integer *nb, doublereal *
+	a, integer *lda, doublereal *e, doublereal *tau, doublereal *w, 
+	integer *ldw);
+
+/* Subroutine */ int dlatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublereal *a, integer *lda, doublereal *x, 
+	doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int dlatrz_(integer *m, integer *n, integer *l, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work);
+
+/* Subroutine */ int dlatzm_(char *side, integer *m, integer *n, doublereal *
+	v, integer *incv, doublereal *tau, doublereal *c1, doublereal *c2, 
+	integer *ldc, doublereal *work);
+
+/* Subroutine */ int dlauu2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+
+/* Subroutine */ int dlauum_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+
+/* Subroutine */ int dopgtr_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *tau, doublereal *q, integer *ldq, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dopmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublereal *ap, doublereal *tau, doublereal *c__, integer 
+	*ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dorg2l_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorg2r_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorgbr_(char *vect, integer *m, integer *n, integer *k, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int dorghr_(integer *n, integer *ilo, integer *ihi, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int dorgl2_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorglq_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dorgql_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dorgqr_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dorgr2_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorgrq_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dorgtr_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dorm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dorm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, doublereal *a, integer *lda, doublereal *tau, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dormhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, doublereal *a, integer *lda, doublereal *
+	tau, doublereal *c__, integer *ldc, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dorml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublereal *a, integer *lda, doublereal *tau, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublereal *a, integer *lda, doublereal *tau, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dormtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dpbcon_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, doublereal *anorm, doublereal *rcond, doublereal *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int dpbequ_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, doublereal *s, doublereal *scond, doublereal *amax, 
+	 integer *info);
+
+/* Subroutine */ int dpbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublereal *ab, integer *ldab, doublereal *afb, integer *ldafb, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int dpbstf_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, integer *info);
+
+/* Subroutine */ int dpbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublereal *ab, integer *ldab, doublereal *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int dpbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, doublereal *ab, integer *ldab, doublereal *afb, 
+	integer *ldafb, char *equed, doublereal *s, doublereal *b, integer *
+	ldb, doublereal *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	 doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dpbtf2_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, integer *info);
+
+/* Subroutine */ int dpbtrf_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, integer *info);
+
+/* Subroutine */ int dpbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublereal *ab, integer *ldab, doublereal *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int dpftrf_(char *transr, char *uplo, integer *n, doublereal 
+	*a, integer *info);
+
+/* Subroutine */ int dpftri_(char *transr, char *uplo, integer *n, doublereal 
+	*a, integer *info);
+
+/* Subroutine */ int dpftrs_(char *transr, char *uplo, integer *n, integer *
+	nrhs, doublereal *a, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dpocon_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dpoequ_(integer *n, doublereal *a, integer *lda, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int dpoequb_(integer *n, doublereal *a, integer *lda, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int dporfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int dporfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	doublereal *s, doublereal *b, integer *ldb, doublereal *x, integer *
+	ldx, doublereal *rcond, doublereal *berr, integer *n_err_bnds__, 
+	doublereal *err_bnds_norm__, doublereal *err_bnds_comp__, integer *
+	nparams, doublereal *params, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dposv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*a, integer *lda, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	char *equed, doublereal *s, doublereal *b, integer *ldb, doublereal *
+	x, integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *
+	berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dposvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	char *equed, doublereal *s, doublereal *b, integer *ldb, doublereal *
+	x, integer *ldx, doublereal *rcond, doublereal *rpvgrw, doublereal *
+	berr, integer *n_err_bnds__, doublereal *err_bnds_norm__, doublereal *
+	err_bnds_comp__, integer *nparams, doublereal *params, doublereal *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int dpotf2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+
+/* Subroutine */ int dpotrf_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+
+/* Subroutine */ int dpotri_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+
+/* Subroutine */ int dpotrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int dppcon_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dppequ_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int dpprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, doublereal *afp, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dppsv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*ap, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *ap, doublereal *afp, char *equed, doublereal *s, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dpptrf_(char *uplo, integer *n, doublereal *ap, integer *
+	info);
+
+/* Subroutine */ int dpptri_(char *uplo, integer *n, doublereal *ap, integer *
+	info);
+
+/* Subroutine */ int dpptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dpstf2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *piv, integer *rank, doublereal *tol, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dpstrf_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *piv, integer *rank, doublereal *tol, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dptcon_(integer *n, doublereal *d__, doublereal *e, 
+	doublereal *anorm, doublereal *rcond, doublereal *work, integer *info);
+
+/* Subroutine */ int dpteqr_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dptrfs_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *df, doublereal *ef, doublereal *b, integer 
+	*ldb, doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	 doublereal *work, integer *info);
+
+/* Subroutine */ int dptsv_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dptsvx_(char *fact, integer *n, integer *nrhs, 
+	doublereal *d__, doublereal *e, doublereal *df, doublereal *ef, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	info);
+
+/* Subroutine */ int dpttrf_(integer *n, doublereal *d__, doublereal *e, 
+	integer *info);
+
+/* Subroutine */ int dpttrs_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dptts2_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *b, integer *ldb);
+
+/* Subroutine */ int drscl_(integer *n, doublereal *sa, doublereal *sx, 
+	integer *incx);
+
+/* Subroutine */ int dsbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublereal *ab, integer *ldab, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *info);
+
+/* Subroutine */ int dsbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublereal *ab, integer *ldab, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int dsbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, doublereal *ab, integer *ldab, doublereal *q, integer *
+	ldq, doublereal *vl, doublereal *vu, integer *il, integer *iu, 
+	doublereal *abstol, integer *m, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *iwork, integer *ifail, 
+	integer *info);
+
+/* Subroutine */ int dsbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+	ldbb, doublereal *x, integer *ldx, doublereal *work, integer *info);
+
+/* Subroutine */ int dsbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+	ldbb, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dsbgvd_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+	ldbb, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dsbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, doublereal *ab, integer *ldab, doublereal *
+	bb, integer *ldbb, doublereal *q, integer *ldq, doublereal *vl, 
+	doublereal *vu, integer *il, integer *iu, doublereal *abstol, integer 
+	*m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int dsbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	doublereal *ab, integer *ldab, doublereal *d__, doublereal *e, 
+	doublereal *q, integer *ldq, doublereal *work, integer *info);
+
+/* Subroutine */ int dsfrk_(char *transr, char *uplo, char *trans, integer *n, 
+	 integer *k, doublereal *alpha, doublereal *a, integer *lda, 
+	doublereal *beta, doublereal *c__);
+
+/* Subroutine */ int dsgesv_(integer *n, integer *nrhs, doublereal *a, 
+	integer *lda, integer *ipiv, doublereal *b, integer *ldb, doublereal *
+	x, integer *ldx, doublereal *work, real *swork, integer *iter, 
+	integer *info);
+
+/* Subroutine */ int dspcon_(char *uplo, integer *n, doublereal *ap, integer *
+	ipiv, doublereal *anorm, doublereal *rcond, doublereal *work, integer 
+	*iwork, integer *info);
+
+/* Subroutine */ int dspev_(char *jobz, char *uplo, integer *n, doublereal *
+	ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dspevd_(char *jobz, char *uplo, integer *n, doublereal *
+	ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dspevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublereal *ap, doublereal *vl, doublereal *vu, integer *il, integer *
+	iu, doublereal *abstol, integer *m, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *iwork, integer *ifail, 
+	integer *info);
+
+/* Subroutine */ int dspgst_(integer *itype, char *uplo, integer *n, 
+	doublereal *ap, doublereal *bp, integer *info);
+
+/* Subroutine */ int dspgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *ap, doublereal *bp, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *info);
+
+/* Subroutine */ int dspgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *ap, doublereal *bp, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int dspgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublereal *ap, doublereal *bp, doublereal *vl, 
+	doublereal *vu, integer *il, integer *iu, doublereal *abstol, integer 
+	*m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int dsposv_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	x, integer *ldx, doublereal *work, real *swork, integer *iter, 
+	integer *info);
+
+/* Subroutine */ int dsprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, doublereal *afp, integer *ipiv, doublereal *b, 
+	integer *ldb, doublereal *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dspsv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*ap, integer *ipiv, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *ap, doublereal *afp, integer *ipiv, doublereal *b, 
+	integer *ldb, doublereal *x, integer *ldx, doublereal *rcond, 
+	doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dsptrd_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *d__, doublereal *e, doublereal *tau, integer *info);
+
+/* Subroutine */ int dsptrf_(char *uplo, integer *n, doublereal *ap, integer *
+	ipiv, integer *info);
+
+/* Subroutine */ int dsptri_(char *uplo, integer *n, doublereal *ap, integer *
+	ipiv, doublereal *work, integer *info);
+
+/* Subroutine */ int dsptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, integer *ipiv, doublereal *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int dstebz_(char *range, char *order, integer *n, doublereal 
+	*vl, doublereal *vu, integer *il, integer *iu, doublereal *abstol, 
+	doublereal *d__, doublereal *e, integer *m, integer *nsplit, 
+	doublereal *w, integer *iblock, integer *isplit, doublereal *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int dstedc_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstegr_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstein_(integer *n, doublereal *d__, doublereal *e, 
+	integer *m, doublereal *w, integer *iblock, integer *isplit, 
+	doublereal *z__, integer *ldz, doublereal *work, integer *iwork, 
+	integer *ifail, integer *info);
+
+/* Subroutine */ int dstemr_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, integer *m, doublereal *w, doublereal *z__, integer *ldz, 
+	 integer *nzc, integer *isuppz, logical *tryrac, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dsteqr_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dsterf_(integer *n, doublereal *d__, doublereal *e, 
+	integer *info);
+
+/* Subroutine */ int dstev_(char *jobz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int dstevd_(char *jobz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstevr_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstevx_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, doublereal *work, integer *iwork, 
+	integer *ifail, integer *info);
+
+/* Subroutine */ int dsycon_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, doublereal *anorm, doublereal *rcond, doublereal *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int dsyequb_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *s, doublereal *scond, doublereal *amax, doublereal *
+	work, integer *info);
+
+/* Subroutine */ int dsyev_(char *jobz, char *uplo, integer *n, doublereal *a, 
+	 integer *lda, doublereal *w, doublereal *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int dsyevd_(char *jobz, char *uplo, integer *n, doublereal *
+	a, integer *lda, doublereal *w, doublereal *work, integer *lwork, 
+	integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dsyevr_(char *jobz, char *range, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *vl, doublereal *vu, integer *
+	il, integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dsyevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *vl, doublereal *vu, integer *
+	il, integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, doublereal *work, integer *lwork, 
+	integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int dsygs2_(integer *itype, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int dsygst_(integer *itype, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int dsygv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *w, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsygvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *w, doublereal *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int dsygvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublereal *a, integer *lda, doublereal *b, integer 
+	*ldb, doublereal *vl, doublereal *vu, integer *il, integer *iu, 
+	doublereal *abstol, integer *m, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *iwork, 
+	integer *ifail, integer *info);
+
+/* Subroutine */ int dsyrfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *af, integer *ldaf, integer *
+	ipiv, doublereal *b, integer *ldb, doublereal *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dsyrfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, doublereal *s, doublereal *b, integer *ldb, doublereal 
+	*x, integer *ldx, doublereal *rcond, doublereal *berr, integer *
+	n_err_bnds__, doublereal *err_bnds_norm__, doublereal *
+	err_bnds_comp__, integer *nparams, doublereal *params, doublereal *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int dsysv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*a, integer *lda, integer *ipiv, doublereal *b, integer *ldb, 
+	doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, doublereal *b, integer *ldb, doublereal *x, integer *
+	ldx, doublereal *rcond, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int dsysvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, char *equed, doublereal *s, doublereal *b, integer *
+	ldb, doublereal *x, integer *ldx, doublereal *rcond, doublereal *
+	rpvgrw, doublereal *berr, integer *n_err_bnds__, doublereal *
+	err_bnds_norm__, doublereal *err_bnds_comp__, integer *nparams, 
+	doublereal *params, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dsytd2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tau, integer *info);
+
+/* Subroutine */ int dsytf2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int dsytrd_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tau, doublereal *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsytrf_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsytri_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, doublereal *work, integer *info);
+
+/* Subroutine */ int dsytrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
+	ldb, integer *info);
+
+/* Subroutine */ int dtbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, doublereal *ab, integer *ldab, doublereal *rcond, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublereal *ab, integer *ldab, doublereal 
+	*b, integer *ldb, doublereal *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublereal *ab, integer *ldab, doublereal 
+	*b, integer *ldb, integer *info);
+
+/* Subroutine */ int dtfsm_(char *transr, char *side, char *uplo, char *trans, 
+	 char *diag, integer *m, integer *n, doublereal *alpha, doublereal *a, 
+	 doublereal *b, integer *ldb);
+
+/* Subroutine */ int dtftri_(char *transr, char *uplo, char *diag, integer *n, 
+	 doublereal *a, integer *info);
+
+/* Subroutine */ int dtfttp_(char *transr, char *uplo, integer *n, doublereal 
+	*arf, doublereal *ap, integer *info);
+
+/* Subroutine */ int dtfttr_(char *transr, char *uplo, integer *n, doublereal 
+	*arf, doublereal *a, integer *lda, integer *info);
+
+/* Subroutine */ int dtgevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublereal *s, integer *lds, doublereal *p, integer *ldp, 
+	doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, integer 
+	*mm, integer *m, doublereal *work, integer *info);
+
+/* Subroutine */ int dtgex2_(logical *wantq, logical *wantz, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	q, integer *ldq, doublereal *z__, integer *ldz, integer *j1, integer *
+	n1, integer *n2, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dtgexc_(logical *wantq, logical *wantz, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	q, integer *ldq, doublereal *z__, integer *ldz, integer *ifst, 
+	integer *ilst, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dtgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, doublereal *a, integer *lda, doublereal *
+	b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *q, integer *ldq, doublereal *z__, integer *ldz, 
+	integer *m, doublereal *pl, doublereal *pr, doublereal *dif, 
+	doublereal *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+
+/* Subroutine */ int dtgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, doublereal *a, 
+	integer *lda, doublereal *b, integer *ldb, doublereal *tola, 
+	doublereal *tolb, doublereal *alpha, doublereal *beta, doublereal *u, 
+	integer *ldu, doublereal *v, integer *ldv, doublereal *q, integer *
+	ldq, doublereal *work, integer *ncycle, integer *info);
+
+/* Subroutine */ int dtgsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, 
+	doublereal *s, doublereal *dif, integer *mm, integer *m, doublereal *
+	work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int dtgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *c__, integer *ldc, doublereal *d__, integer *ldd, 
+	doublereal *e, integer *lde, doublereal *f, integer *ldf, doublereal *
+	scale, doublereal *rdsum, doublereal *rdscal, integer *iwork, integer 
+	*pq, integer *info);
+
+/* Subroutine */ int dtgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *c__, integer *ldc, doublereal *d__, integer *ldd, 
+	doublereal *e, integer *lde, doublereal *f, integer *ldf, doublereal *
+	scale, doublereal *dif, doublereal *work, integer *lwork, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dtpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublereal *ap, doublereal *rcond, doublereal *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int dtprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *ap, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtptri_(char *uplo, char *diag, integer *n, doublereal *
+	ap, integer *info);
+
+/* Subroutine */ int dtptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *ap, doublereal *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int dtpttf_(char *transr, char *uplo, integer *n, doublereal 
+	*ap, doublereal *arf, integer *info);
+
+/* Subroutine */ int dtpttr_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *a, integer *lda, integer *info);
+
+/* Subroutine */ int dtrcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublereal *a, integer *lda, doublereal *rcond, doublereal *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int dtrevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublereal *t, integer *ldt, doublereal *vl, integer *
+	ldvl, doublereal *vr, integer *ldvr, integer *mm, integer *m, 
+	doublereal *work, integer *info);
+
+/* Subroutine */ int dtrexc_(char *compq, integer *n, doublereal *t, integer *
+	ldt, doublereal *q, integer *ldq, integer *ifst, integer *ilst, 
+	doublereal *work, integer *info);
+
+/* Subroutine */ int dtrrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *a, integer *lda, doublereal *b, integer *
+	ldb, doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtrsen_(char *job, char *compq, logical *select, integer 
+	*n, doublereal *t, integer *ldt, doublereal *q, integer *ldq, 
+	doublereal *wr, doublereal *wi, integer *m, doublereal *s, doublereal 
+	*sep, doublereal *work, integer *lwork, integer *iwork, integer *
+	liwork, integer *info);
+
+/* Subroutine */ int dtrsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublereal *t, integer *ldt, doublereal *vl, integer *
+	ldvl, doublereal *vr, integer *ldvr, doublereal *s, doublereal *sep, 
+	integer *mm, integer *m, doublereal *work, integer *ldwork, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int dtrsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, doublereal *a, integer *lda, doublereal *b, integer *
+	ldb, doublereal *c__, integer *ldc, doublereal *scale, integer *info);
+
+/* Subroutine */ int dtrti2_(char *uplo, char *diag, integer *n, doublereal *
+	a, integer *lda, integer *info);
+
+/* Subroutine */ int dtrtri_(char *uplo, char *diag, integer *n, doublereal *
+	a, integer *lda, integer *info);
+
+/* Subroutine */ int dtrtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *a, integer *lda, doublereal *b, integer *
+	ldb, integer *info);
+
+/* Subroutine */ int dtrttf_(char *transr, char *uplo, integer *n, doublereal 
+	*a, integer *lda, doublereal *arf, integer *info);
+
+/* Subroutine */ int dtrttp_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *ap, integer *info);
+
+/* Subroutine */ int dtzrqf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, integer *info);
+
+/* Subroutine */ int dtzrzf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+doublereal dzsum1_(integer *n, doublecomplex *cx, integer *incx);
+
+integer icmax1_(integer *n, complex *cx, integer *incx);
+
+integer ieeeck_(integer *ispec, real *zero, real *one);
+
+integer ilaclc_(integer *m, integer *n, complex *a, integer *lda);
+
+integer ilaclr_(integer *m, integer *n, complex *a, integer *lda);
+
+integer iladiag_(char *diag);
+
+integer iladlc_(integer *m, integer *n, doublereal *a, integer *lda);
+
+integer iladlr_(integer *m, integer *n, doublereal *a, integer *lda);
+
+integer ilaenv_(integer *ispec, char *name__, char *opts, integer *n1, 
+	integer *n2, integer *n3, integer *n4);
+
+integer ilaprec_(char *prec);
+
+integer ilaslc_(integer *m, integer *n, real *a, integer *lda);
+
+integer ilaslr_(integer *m, integer *n, real *a, integer *lda);
+
+integer ilatrans_(char *trans);
+
+integer ilauplo_(char *uplo);
+
+/* Subroutine */ int ilaver_(integer *vers_major__, integer *vers_minor__, 
+	integer *vers_patch__);
+
+integer ilazlc_(integer *m, integer *n, doublecomplex *a, integer *lda);
+
+integer ilazlr_(integer *m, integer *n, doublecomplex *a, integer *lda);
+
+integer iparmq_(integer *ispec, char *name__, char *opts, integer *n, integer 
+	*ilo, integer *ihi, integer *lwork);
+
+integer izmax1_(integer *n, doublecomplex *cx, integer *incx);
+
+logical lsamen_(integer *n, char *ca, char *cb);
+
+integer smaxloc_(real *a, integer *dimm);
+
+/* Subroutine */ int sbdsdc_(char *uplo, char *compq, integer *n, real *d__, 
+	real *e, real *u, integer *ldu, real *vt, integer *ldvt, real *q, 
+	integer *iq, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, real *d__, real *e, real *vt, integer *ldvt, real *
+	u, integer *ldu, real *c__, integer *ldc, real *work, integer *info);
+
+doublereal scsum1_(integer *n, complex *cx, integer *incx);
+
+/* Subroutine */ int sdisna_(char *job, integer *m, integer *n, real *d__, 
+	real *sep, integer *info);
+
+/* Subroutine */ int sgbbrd_(char *vect, integer *m, integer *n, integer *ncc, 
+	 integer *kl, integer *ku, real *ab, integer *ldab, real *d__, real *
+	e, real *q, integer *ldq, real *pt, integer *ldpt, real *c__, integer 
+	*ldc, real *work, integer *info);
+
+/* Subroutine */ int sgbcon_(char *norm, integer *n, integer *kl, integer *ku, 
+	 real *ab, integer *ldab, integer *ipiv, real *anorm, real *rcond, 
+	real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgbequ_(integer *m, integer *n, integer *kl, integer *ku, 
+	 real *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real *
+	colcnd, real *amax, integer *info);
+
+/* Subroutine */ int sgbequb_(integer *m, integer *n, integer *kl, integer *
+	ku, real *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real 
+	*colcnd, real *amax, integer *info);
+
+/* Subroutine */ int sgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, real *ab, integer *ldab, real *afb, integer *ldafb, 
+	 integer *ipiv, real *b, integer *ldb, real *x, integer *ldx, real *
+	ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgbrfsx_(char *trans, char *equed, integer *n, integer *
+	kl, integer *ku, integer *nrhs, real *ab, integer *ldab, real *afb, 
+	integer *ldafb, integer *ipiv, real *r__, real *c__, real *b, integer 
+	*ldb, real *x, integer *ldx, real *rcond, real *berr, integer *
+	n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, integer *
+	nparams, real *params, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, real *ab, integer *ldab, integer *ipiv, real *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int sgbsvx_(char *fact, char *trans, integer *n, integer *kl, 
+	 integer *ku, integer *nrhs, real *ab, integer *ldab, real *afb, 
+	integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__, 
+	real *b, integer *ldb, real *x, integer *ldx, real *rcond, real *ferr, 
+	 real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgbsvxx_(char *fact, char *trans, integer *n, integer *
+	kl, integer *ku, integer *nrhs, real *ab, integer *ldab, real *afb, 
+	integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__, 
+	real *b, integer *ldb, real *x, integer *ldx, real *rcond, real *
+	rpvgrw, real *berr, integer *n_err_bnds__, real *err_bnds_norm__, 
+	real *err_bnds_comp__, integer *nparams, real *params, real *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int sgbtf2_(integer *m, integer *n, integer *kl, integer *ku, 
+	 real *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int sgbtrf_(integer *m, integer *n, integer *kl, integer *ku, 
+	 real *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int sgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, real *ab, integer *ldab, integer *ipiv, real *b, 
+	integer *ldb, integer *info);
+
+/* Subroutine */ int sgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *scale, integer *m, real *v, integer *ldv, integer 
+	*info);
+
+/* Subroutine */ int sgebal_(char *job, integer *n, real *a, integer *lda, 
+	integer *ilo, integer *ihi, real *scale, integer *info);
+
+/* Subroutine */ int sgebd2_(integer *m, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tauq, real *taup, real *work, integer *info);
+
+/* Subroutine */ int sgebrd_(integer *m, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tauq, real *taup, real *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int sgecon_(char *norm, integer *n, real *a, integer *lda, 
+	real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgeequ_(integer *m, integer *n, real *a, integer *lda, 
+	real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, integer 
+	*info);
+
+/* Subroutine */ int sgeequb_(integer *m, integer *n, real *a, integer *lda, 
+	real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, integer 
+	*info);
+
+/* Subroutine */ int sgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	real *a, integer *lda, integer *sdim, real *wr, real *wi, real *vs, 
+	integer *ldvs, real *work, integer *lwork, logical *bwork, integer *
+	info);
+
+/* Subroutine */ int sgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, real *a, integer *lda, integer *sdim, real *wr, 
+	real *wi, real *vs, integer *ldvs, real *rconde, real *rcondv, real *
+	work, integer *lwork, integer *iwork, integer *liwork, logical *bwork, 
+	 integer *info);
+
+/* Subroutine */ int sgeev_(char *jobvl, char *jobvr, integer *n, real *a, 
+	integer *lda, real *wr, real *wi, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, real *a, integer *lda, real *wr, real *wi, real *
+	vl, integer *ldvl, real *vr, integer *ldvr, integer *ilo, integer *
+	ihi, real *scale, real *abnrm, real *rconde, real *rcondv, real *work, 
+	 integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int sgegs_(char *jobvsl, char *jobvsr, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real 
+	*beta, real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgegv_(char *jobvl, char *jobvr, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real 
+	*beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int sgehd2_(integer *n, integer *ilo, integer *ihi, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgehrd_(integer *n, integer *ilo, integer *ihi, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgejsv_(char *joba, char *jobu, char *jobv, char *jobr, 
+	char *jobt, char *jobp, integer *m, integer *n, real *a, integer *lda, 
+	 real *sva, real *u, integer *ldu, real *v, integer *ldv, real *work, 
+	integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int sgelq2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgelqf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, real *a, integer *lda, real *b, integer *ldb, real *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int sgelsd_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, real *s, real *rcond, integer *
+	rank, real *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int sgelss_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, real *s, real *rcond, integer *
+	rank, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgelsx_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *jpvt, real *rcond, 
+	integer *rank, real *work, integer *info);
+
+/* Subroutine */ int sgelsy_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *jpvt, real *rcond, 
+	integer *rank, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeql2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgeqlf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeqp3_(integer *m, integer *n, real *a, integer *lda, 
+	integer *jpvt, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeqpf_(integer *m, integer *n, real *a, integer *lda, 
+	integer *jpvt, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgeqr2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgeqrf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgerfs_(char *trans, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *af, integer *ldaf, integer *ipiv, real *b, 
+	integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgerfsx_(char *trans, char *equed, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	real *r__, real *c__, real *b, integer *ldb, real *x, integer *ldx, 
+	real *rcond, real *berr, integer *n_err_bnds__, real *err_bnds_norm__, 
+	 real *err_bnds_comp__, integer *nparams, real *params, real *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int sgerq2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgerqf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgesc2_(integer *n, real *a, integer *lda, real *rhs, 
+	integer *ipiv, integer *jpiv, real *scale);
+
+/* Subroutine */ int sgesdd_(char *jobz, integer *m, integer *n, real *a, 
+	integer *lda, real *s, real *u, integer *ldu, real *vt, integer *ldvt, 
+	 real *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int sgesv_(integer *n, integer *nrhs, real *a, integer *lda, 
+	integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sgesvd_(char *jobu, char *jobvt, integer *m, integer *n, 
+	real *a, integer *lda, real *s, real *u, integer *ldu, real *vt, 
+	integer *ldvt, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgesvj_(char *joba, char *jobu, char *jobv, integer *m, 
+	integer *n, real *a, integer *lda, real *sva, integer *mv, real *v, 
+	integer *ldv, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	char *equed, real *r__, real *c__, real *b, integer *ldb, real *x, 
+	integer *ldx, real *rcond, real *ferr, real *berr, real *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int sgesvxx_(char *fact, char *trans, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	char *equed, real *r__, real *c__, real *b, integer *ldb, real *x, 
+	integer *ldx, real *rcond, real *rpvgrw, real *berr, integer *
+	n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, integer *
+	nparams, real *params, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgetc2_(integer *n, real *a, integer *lda, integer *ipiv, 
+	 integer *jpiv, integer *info);
+
+/* Subroutine */ int sgetf2_(integer *m, integer *n, real *a, integer *lda, 
+	integer *ipiv, integer *info);
+
+/* Subroutine */ int sgetrf_(integer *m, integer *n, real *a, integer *lda, 
+	integer *ipiv, integer *info);
+
+/* Subroutine */ int sgetri_(integer *n, real *a, integer *lda, integer *ipiv, 
+	 real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgetrs_(char *trans, integer *n, integer *nrhs, real *a, 
+	integer *lda, integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *lscale, real *rscale, integer *m, real *v, 
+	integer *ldv, integer *info);
+
+/* Subroutine */ int sggbal_(char *job, integer *n, real *a, integer *lda, 
+	real *b, integer *ldb, integer *ilo, integer *ihi, real *lscale, real 
+	*rscale, real *work, integer *info);
+
+/* Subroutine */ int sgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, integer *n, real *a, integer *lda, real *b, integer *ldb, 
+	integer *sdim, real *alphar, real *alphai, real *beta, real *vsl, 
+	integer *ldvsl, real *vsr, integer *ldvsr, real *work, integer *lwork, 
+	 logical *bwork, integer *info);
+
+/* Subroutine */ int sggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, char *sense, integer *n, real *a, integer *lda, real *b, 
+	integer *ldb, integer *sdim, real *alphar, real *alphai, real *beta, 
+	real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *rconde, 
+	real *rcondv, real *work, integer *lwork, integer *iwork, integer *
+	liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int sggev_(char *jobvl, char *jobvr, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real 
+	*beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int sggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, real *a, integer *lda, real *b, integer *ldb, real 
+	*alphar, real *alphai, real *beta, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, integer *ilo, integer *ihi, real *lscale, real *rscale, 
+	 real *abnrm, real *bbnrm, real *rconde, real *rcondv, real *work, 
+	integer *lwork, integer *iwork, logical *bwork, integer *info);
+
+/* Subroutine */ int sggglm_(integer *n, integer *m, integer *p, real *a, 
+	integer *lda, real *b, integer *ldb, real *d__, real *x, real *y, 
+	real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, real *a, integer *lda, real *b, integer *ldb, real 
+	*q, integer *ldq, real *z__, integer *ldz, integer *info);
+
+/* Subroutine */ int sgglse_(integer *m, integer *n, integer *p, real *a, 
+	integer *lda, real *b, integer *ldb, real *c__, real *d__, real *x, 
+	real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sggqrf_(integer *n, integer *m, integer *p, real *a, 
+	integer *lda, real *taua, real *b, integer *ldb, real *taub, real *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int sggrqf_(integer *m, integer *p, integer *n, real *a, 
+	integer *lda, real *taua, real *b, integer *ldb, real *taub, real *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int sggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, real *a, integer *lda, 
+	 real *b, integer *ldb, real *alpha, real *beta, real *u, integer *
+	ldu, real *v, integer *ldv, real *q, integer *ldq, real *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int sggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, real *a, integer *lda, real *b, integer *ldb, 
+	real *tola, real *tolb, integer *k, integer *l, real *u, integer *ldu, 
+	 real *v, integer *ldv, real *q, integer *ldq, integer *iwork, real *
+	tau, real *work, integer *info);
+
+/* Subroutine */ int sgsvj0_(char *jobv, integer *m, integer *n, real *a, 
+	integer *lda, real *d__, real *sva, integer *mv, real *v, integer *
+	ldv, real *eps, real *sfmin, real *tol, integer *nsweep, real *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int sgsvj1_(char *jobv, integer *m, integer *n, integer *n1, 
+	real *a, integer *lda, real *d__, real *sva, integer *mv, real *v, 
+	integer *ldv, real *eps, real *sfmin, real *tol, integer *nsweep, 
+	real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgtcon_(char *norm, integer *n, real *dl, real *d__, 
+	real *du, real *du2, integer *ipiv, real *anorm, real *rcond, real *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgtrfs_(char *trans, integer *n, integer *nrhs, real *dl, 
+	 real *d__, real *du, real *dlf, real *df, real *duf, real *du2, 
+	integer *ipiv, real *b, integer *ldb, real *x, integer *ldx, real *
+	ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgtsv_(integer *n, integer *nrhs, real *dl, real *d__, 
+	real *du, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, real *dl, real *d__, real *du, real *dlf, real *df, real *duf, 
+	real *du2, integer *ipiv, real *b, integer *ldb, real *x, integer *
+	ldx, real *rcond, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int sgttrf_(integer *n, real *dl, real *d__, real *du, real *
+	du2, integer *ipiv, integer *info);
+
+/* Subroutine */ int sgttrs_(char *trans, integer *n, integer *nrhs, real *dl, 
+	 real *d__, real *du, real *du2, integer *ipiv, real *b, integer *ldb, 
+	 integer *info);
+
+/* Subroutine */ int sgtts2_(integer *itrans, integer *n, integer *nrhs, real 
+	*dl, real *d__, real *du, real *du2, integer *ipiv, real *b, integer *
+	ldb);
+
+/* Subroutine */ int shgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, real *h__, integer *ldh, real *t, integer 
+	*ldt, real *alphar, real *alphai, real *beta, real *q, integer *ldq, 
+	real *z__, integer *ldz, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int shsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, real *h__, integer *ldh, real *wr, real *wi, real 
+	*vl, integer *ldvl, real *vr, integer *ldvr, integer *mm, integer *m, 
+	real *work, integer *ifaill, integer *ifailr, integer *info);
+
+/* Subroutine */ int shseqr_(char *job, char *compz, integer *n, integer *ilo, 
+	 integer *ihi, real *h__, integer *ldh, real *wr, real *wi, real *z__, 
+	 integer *ldz, real *work, integer *lwork, integer *info);
+
+logical sisnan_(real *sin__);
+
+/* Subroutine */ int sla_gbamv__(integer *trans, integer *m, integer *n, 
+	integer *kl, integer *ku, real *alpha, real *ab, integer *ldab, real *
+	x, integer *incx, real *beta, real *y, integer *incy);
+
+doublereal sla_gbrcond__(char *trans, integer *n, integer *kl, integer *ku, 
+	real *ab, integer *ldab, real *afb, integer *ldafb, integer *ipiv, 
+	integer *cmode, real *c__, integer *info, real *work, integer *iwork, 
+	ftnlen trans_len);
+
+/* Subroutine */ int sla_gbrfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *kl, integer *ku, integer *nrhs, 
+	real *ab, integer *ldab, real *afb, integer *ldafb, integer *ipiv, 
+	logical *colequ, real *c__, real *b, integer *ldb, real *y, integer *
+	ldy, real *berr_out__, integer *n_norms__, real *errs_n__, real *
+	errs_c__, real *res, real *ayb, real *dy, real *y_tail__, real *rcond,
+	 integer *ithresh, real *rthresh, real *dz_ub__, logical *
+	ignore_cwise__, integer *info);
+
+doublereal sla_gbrpvgrw__(integer *n, integer *kl, integer *ku, integer *
+	ncols, real *ab, integer *ldab, real *afb, integer *ldafb);
+
+/* Subroutine */ int sla_geamv__(integer *trans, integer *m, integer *n, real 
+	*alpha, real *a, integer *lda, real *x, integer *incx, real *beta, 
+	real *y, integer *incy);
+
+doublereal sla_gercond__(char *trans, integer *n, real *a, integer *lda, real 
+	*af, integer *ldaf, integer *ipiv, integer *cmode, real *c__, integer 
+	*info, real *work, integer *iwork, ftnlen trans_len);
+
+/* Subroutine */ int sla_gerfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *nrhs, real *a, integer *lda, real *
+	af, integer *ldaf, integer *ipiv, logical *colequ, real *c__, real *b,
+	 integer *ldb, real *y, integer *ldy, real *berr_out__, integer *
+	n_norms__, real *errs_n__, real *errs_c__, real *res, real *ayb, real 
+	*dy, real *y_tail__, real *rcond, integer *ithresh, real *rthresh, 
+	real *dz_ub__, logical *ignore_cwise__, integer *info);
+
+/* Subroutine */ int sla_lin_berr__(integer *n, integer *nz, integer *nrhs, 
+	real *res, real *ayb, real *berr);
+
+doublereal sla_porcond__(char *uplo, integer *n, real *a, integer *lda, real *
+	af, integer *ldaf, integer *cmode, real *c__, integer *info, real *
+	work, integer *iwork, ftnlen uplo_len);
+
+/* Subroutine */ int sla_porfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, real *a, integer *lda, real *af, integer *
+	ldaf, logical *colequ, real *c__, real *b, integer *ldb, real *y, 
+	integer *ldy, real *berr_out__, integer *n_norms__, real *errs_n__, 
+	real *errs_c__, real *res, real *ayb, real *dy, real *y_tail__, real *
+	rcond, integer *ithresh, real *rthresh, real *dz_ub__, logical *
+	ignore_cwise__, integer *info, ftnlen uplo_len);
+
+doublereal sla_porpvgrw__(char *uplo, integer *ncols, real *a, integer *lda, 
+	real *af, integer *ldaf, real *work, ftnlen uplo_len);
+
+doublereal sla_rpvgrw__(integer *n, integer *ncols, real *a, integer *lda, 
+	real *af, integer *ldaf);
+
+/* Subroutine */ int sla_syamv__(integer *uplo, integer *n, real *alpha, real 
+	*a, integer *lda, real *x, integer *incx, real *beta, real *y, 
+	integer *incy);
+
+doublereal sla_syrcond__(char *uplo, integer *n, real *a, integer *lda, real *
+	af, integer *ldaf, integer *ipiv, integer *cmode, real *c__, integer *
+	info, real *work, integer *iwork, ftnlen uplo_len);
+
+/* Subroutine */ int sla_syrfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, real *a, integer *lda, real *af, integer *
+	ldaf, integer *ipiv, logical *colequ, real *c__, real *b, integer *
+	ldb, real *y, integer *ldy, real *berr_out__, integer *n_norms__, 
+	real *errs_n__, real *errs_c__, real *res, real *ayb, real *dy, real *
+	y_tail__, real *rcond, integer *ithresh, real *rthresh, real *dz_ub__,
+	 logical *ignore_cwise__, integer *info, ftnlen uplo_len);
+
+doublereal sla_syrpvgrw__(char *uplo, integer *n, integer *info, real *a, 
+	integer *lda, real *af, integer *ldaf, integer *ipiv, real *work, 
+	ftnlen uplo_len);
+
+/* Subroutine */ int sla_wwaddw__(integer *n, real *x, real *y, real *w);
+
+/* Subroutine */ int slabad_(real *small, real *large);
+
+/* Subroutine */ int slabrd_(integer *m, integer *n, integer *nb, real *a, 
+	integer *lda, real *d__, real *e, real *tauq, real *taup, real *x, 
+	integer *ldx, real *y, integer *ldy);
+
+/* Subroutine */ int slacn2_(integer *n, real *v, real *x, integer *isgn, 
+	real *est, integer *kase, integer *isave);
+
+/* Subroutine */ int slacon_(integer *n, real *v, real *x, integer *isgn, 
+	real *est, integer *kase);
+
+/* Subroutine */ int slacpy_(char *uplo, integer *m, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb);
+
+/* Subroutine */ int sladiv_(real *a, real *b, real *c__, real *d__, real *p, 
+	real *q);
+
+/* Subroutine */ int slae2_(real *a, real *b, real *c__, real *rt1, real *rt2);
+
+/* Subroutine */ int slaebz_(integer *ijob, integer *nitmax, integer *n, 
+	integer *mmax, integer *minp, integer *nbmin, real *abstol, real *
+	reltol, real *pivmin, real *d__, real *e, real *e2, integer *nval, 
+	real *ab, real *c__, integer *mout, integer *nab, real *work, integer 
+	*iwork, integer *info);
+
+/* Subroutine */ int slaed0_(integer *icompq, integer *qsiz, integer *n, real 
+	*d__, real *e, real *q, integer *ldq, real *qstore, integer *ldqs, 
+	real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slaed1_(integer *n, real *d__, real *q, integer *ldq, 
+	integer *indxq, real *rho, integer *cutpnt, real *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int slaed2_(integer *k, integer *n, integer *n1, real *d__, 
+	real *q, integer *ldq, integer *indxq, real *rho, real *z__, real *
+	dlamda, real *w, real *q2, integer *indx, integer *indxc, integer *
+	indxp, integer *coltyp, integer *info);
+
+/* Subroutine */ int slaed3_(integer *k, integer *n, integer *n1, real *d__, 
+	real *q, integer *ldq, real *rho, real *dlamda, real *q2, integer *
+	indx, integer *ctot, real *w, real *s, integer *info);
+
+/* Subroutine */ int slaed4_(integer *n, integer *i__, real *d__, real *z__, 
+	real *delta, real *rho, real *dlam, integer *info);
+
+/* Subroutine */ int slaed5_(integer *i__, real *d__, real *z__, real *delta, 
+	real *rho, real *dlam);
+
+/* Subroutine */ int slaed6_(integer *kniter, logical *orgati, real *rho, 
+	real *d__, real *z__, real *finit, real *tau, integer *info);
+
+/* Subroutine */ int slaed7_(integer *icompq, integer *n, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, real *d__, real *q, 
+	integer *ldq, integer *indxq, real *rho, integer *cutpnt, real *
+	qstore, integer *qptr, integer *prmptr, integer *perm, integer *
+	givptr, integer *givcol, real *givnum, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int slaed8_(integer *icompq, integer *k, integer *n, integer 
+	*qsiz, real *d__, real *q, integer *ldq, integer *indxq, real *rho, 
+	integer *cutpnt, real *z__, real *dlamda, real *q2, integer *ldq2, 
+	real *w, integer *perm, integer *givptr, integer *givcol, real *
+	givnum, integer *indxp, integer *indx, integer *info);
+
+/* Subroutine */ int slaed9_(integer *k, integer *kstart, integer *kstop, 
+	integer *n, real *d__, real *q, integer *ldq, real *rho, real *dlamda, 
+	 real *w, real *s, integer *lds, integer *info);
+
+/* Subroutine */ int slaeda_(integer *n, integer *tlvls, integer *curlvl, 
+	integer *curpbm, integer *prmptr, integer *perm, integer *givptr, 
+	integer *givcol, real *givnum, real *q, integer *qptr, real *z__, 
+	real *ztemp, integer *info);
+
+/* Subroutine */ int slaein_(logical *rightv, logical *noinit, integer *n, 
+	real *h__, integer *ldh, real *wr, real *wi, real *vr, real *vi, real 
+	*b, integer *ldb, real *work, real *eps3, real *smlnum, real *bignum, 
+	integer *info);
+
+/* Subroutine */ int slaev2_(real *a, real *b, real *c__, real *rt1, real *
+	rt2, real *cs1, real *sn1);
+
+/* Subroutine */ int slaexc_(logical *wantq, integer *n, real *t, integer *
+	ldt, real *q, integer *ldq, integer *j1, integer *n1, integer *n2, 
+	real *work, integer *info);
+
+/* Subroutine */ int slag2_(real *a, integer *lda, real *b, integer *ldb, 
+	real *safmin, real *scale1, real *scale2, real *wr1, real *wr2, real *
+	wi);
+
+/* Subroutine */ int slag2d_(integer *m, integer *n, real *sa, integer *ldsa, 
+	doublereal *a, integer *lda, integer *info);
+
+/* Subroutine */ int slags2_(logical *upper, real *a1, real *a2, real *a3, 
+	real *b1, real *b2, real *b3, real *csu, real *snu, real *csv, real *
+	snv, real *csq, real *snq);
+
+/* Subroutine */ int slagtf_(integer *n, real *a, real *lambda, real *b, real 
+	*c__, real *tol, real *d__, integer *in, integer *info);
+
+/* Subroutine */ int slagtm_(char *trans, integer *n, integer *nrhs, real *
+	alpha, real *dl, real *d__, real *du, real *x, integer *ldx, real *
+	beta, real *b, integer *ldb);
+
+/* Subroutine */ int slagts_(integer *job, integer *n, real *a, real *b, real 
+	*c__, real *d__, integer *in, real *y, real *tol, integer *info);
+
+/* Subroutine */ int slagv2_(real *a, integer *lda, real *b, integer *ldb, 
+	real *alphar, real *alphai, real *beta, real *csl, real *snl, real *
+	csr, real *snr);
+
+/* Subroutine */ int slahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, real *h__, integer *ldh, real *wr, real *
+	wi, integer *iloz, integer *ihiz, real *z__, integer *ldz, integer *
+	info);
+
+/* Subroutine */ int slahr2_(integer *n, integer *k, integer *nb, real *a, 
+	integer *lda, real *tau, real *t, integer *ldt, real *y, integer *ldy);
+
+/* Subroutine */ int slahrd_(integer *n, integer *k, integer *nb, real *a, 
+	integer *lda, real *tau, real *t, integer *ldt, real *y, integer *ldy);
+
+/* Subroutine */ int slaic1_(integer *job, integer *j, real *x, real *sest, 
+	real *w, real *gamma, real *sestpr, real *s, real *c__);
+
+logical slaisnan_(real *sin1, real *sin2);
+
+/* Subroutine */ int slaln2_(logical *ltrans, integer *na, integer *nw, real *
+	smin, real *ca, real *a, integer *lda, real *d1, real *d2, real *b, 
+	integer *ldb, real *wr, real *wi, real *x, integer *ldx, real *scale, 
+	real *xnorm, integer *info);
+
+/* Subroutine */ int slals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, real *b, integer *ldb, real *bx, 
+	integer *ldbx, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+	difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+	work, integer *info);
+
+/* Subroutine */ int slalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, real *b, integer *ldb, real *bx, integer *ldbx, real *
+	u, integer *ldu, real *vt, integer *k, real *difl, real *difr, real *
+	z__, real *poles, integer *givptr, integer *givcol, integer *ldgcol, 
+	integer *perm, real *givnum, real *c__, real *s, real *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int slalsd_(char *uplo, integer *smlsiz, integer *n, integer 
+	*nrhs, real *d__, real *e, real *b, integer *ldb, real *rcond, 
+	integer *rank, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slamrg_(integer *n1, integer *n2, real *a, integer *
+	strd1, integer *strd2, integer *index);
+
+integer slaneg_(integer *n, real *d__, real *lld, real *sigma, real *pivmin, 
+	integer *r__);
+
+doublereal slangb_(char *norm, integer *n, integer *kl, integer *ku, real *ab, 
+	 integer *ldab, real *work);
+
+doublereal slange_(char *norm, integer *m, integer *n, real *a, integer *lda, 
+	real *work);
+
+doublereal slangt_(char *norm, integer *n, real *dl, real *d__, real *du);
+
+doublereal slanhs_(char *norm, integer *n, real *a, integer *lda, real *work);
+
+doublereal slansb_(char *norm, char *uplo, integer *n, integer *k, real *ab, 
+	integer *ldab, real *work);
+
+doublereal slansf_(char *norm, char *transr, char *uplo, integer *n, real *a, 
+	real *work);
+
+doublereal slansp_(char *norm, char *uplo, integer *n, real *ap, real *work);
+
+doublereal slanst_(char *norm, integer *n, real *d__, real *e);
+
+doublereal slansy_(char *norm, char *uplo, integer *n, real *a, integer *lda, 
+	real *work);
+
+doublereal slantb_(char *norm, char *uplo, char *diag, integer *n, integer *k, 
+	 real *ab, integer *ldab, real *work);
+
+doublereal slantp_(char *norm, char *uplo, char *diag, integer *n, real *ap, 
+	real *work);
+
+doublereal slantr_(char *norm, char *uplo, char *diag, integer *m, integer *n, 
+	 real *a, integer *lda, real *work);
+
+/* Subroutine */ int slanv2_(real *a, real *b, real *c__, real *d__, real *
+	rt1r, real *rt1i, real *rt2r, real *rt2i, real *cs, real *sn);
+
+/* Subroutine */ int slapll_(integer *n, real *x, integer *incx, real *y, 
+	integer *incy, real *ssmin);
+
+/* Subroutine */ int slapmt_(logical *forwrd, integer *m, integer *n, real *x, 
+	 integer *ldx, integer *k);
+
+doublereal slapy2_(real *x, real *y);
+
+doublereal slapy3_(real *x, real *y, real *z__);
+
+/* Subroutine */ int slaqgb_(integer *m, integer *n, integer *kl, integer *ku, 
+	 real *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real *
+	colcnd, real *amax, char *equed);
+
+/* Subroutine */ int slaqge_(integer *m, integer *n, real *a, integer *lda, 
+	real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, char *
+	equed);
+
+/* Subroutine */ int slaqp2_(integer *m, integer *n, integer *offset, real *a, 
+	 integer *lda, integer *jpvt, real *tau, real *vn1, real *vn2, real *
+	work);
+
+/* Subroutine */ int slaqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, real *a, integer *lda, integer *jpvt, real *tau, 
+	real *vn1, real *vn2, real *auxv, real *f, integer *ldf);
+
+/* Subroutine */ int slaqr0_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, real *h__, integer *ldh, real *wr, real *
+	wi, integer *iloz, integer *ihiz, real *z__, integer *ldz, real *work, 
+	 integer *lwork, integer *info);
+
+/* Subroutine */ int slaqr1_(integer *n, real *h__, integer *ldh, real *sr1, 
+	real *si1, real *sr2, real *si2, real *v);
+
+/* Subroutine */ int slaqr2_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, real *h__, integer *ldh, 
+	integer *iloz, integer *ihiz, real *z__, integer *ldz, integer *ns, 
+	integer *nd, real *sr, real *si, real *v, integer *ldv, integer *nh, 
+	real *t, integer *ldt, integer *nv, real *wv, integer *ldwv, real *
+	work, integer *lwork);
+
+/* Subroutine */ int slaqr3_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, real *h__, integer *ldh, 
+	integer *iloz, integer *ihiz, real *z__, integer *ldz, integer *ns, 
+	integer *nd, real *sr, real *si, real *v, integer *ldv, integer *nh, 
+	real *t, integer *ldt, integer *nv, real *wv, integer *ldwv, real *
+	work, integer *lwork);
+
+/* Subroutine */ int slaqr4_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, real *h__, integer *ldh, real *wr, real *
+	wi, integer *iloz, integer *ihiz, real *z__, integer *ldz, real *work, 
+	 integer *lwork, integer *info);
+
+/* Subroutine */ int slaqr5_(logical *wantt, logical *wantz, integer *kacc22, 
+	integer *n, integer *ktop, integer *kbot, integer *nshfts, real *sr, 
+	real *si, real *h__, integer *ldh, integer *iloz, integer *ihiz, real 
+	*z__, integer *ldz, real *v, integer *ldv, real *u, integer *ldu, 
+	integer *nv, real *wv, integer *ldwv, integer *nh, real *wh, integer *
+	ldwh);
+
+/* Subroutine */ int slaqsb_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int slaqsp_(char *uplo, integer *n, real *ap, real *s, real *
+	scond, real *amax, char *equed);
+
+/* Subroutine */ int slaqsy_(char *uplo, integer *n, real *a, integer *lda, 
+	real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int slaqtr_(logical *ltran, logical *lreal, integer *n, real 
+	*t, integer *ldt, real *b, real *w, real *scale, real *x, real *work, 
+	integer *info);
+
+/* Subroutine */ int slar1v_(integer *n, integer *b1, integer *bn, real *
+	lambda, real *d__, real *l, real *ld, real *lld, real *pivmin, real *
+	gaptol, real *z__, logical *wantnc, integer *negcnt, real *ztz, real *
+	mingma, integer *r__, integer *isuppz, real *nrminv, real *resid, 
+	real *rqcorr, real *work);
+
+/* Subroutine */ int slar2v_(integer *n, real *x, real *y, real *z__, integer 
+	*incx, real *c__, real *s, integer *incc);
+
+/* Subroutine */ int slarf_(char *side, integer *m, integer *n, real *v, 
+	integer *incv, real *tau, real *c__, integer *ldc, real *work);
+
+/* Subroutine */ int slarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, real *v, integer *ldv, 
+	real *t, integer *ldt, real *c__, integer *ldc, real *work, integer *
+	ldwork);
+
+/* Subroutine */ int slarfg_(integer *n, real *alpha, real *x, integer *incx, 
+	real *tau);
+
+/* Subroutine */ int slarfp_(integer *n, real *alpha, real *x, integer *incx, 
+	real *tau);
+
+/* Subroutine */ int slarft_(char *direct, char *storev, integer *n, integer *
+	k, real *v, integer *ldv, real *tau, real *t, integer *ldt);
+
+/* Subroutine */ int slarfx_(char *side, integer *m, integer *n, real *v, 
+	real *tau, real *c__, integer *ldc, real *work);
+
+/* Subroutine */ int slargv_(integer *n, real *x, integer *incx, real *y, 
+	integer *incy, real *c__, integer *incc);
+
+/* Subroutine */ int slarnv_(integer *idist, integer *iseed, integer *n, real 
+	*x);
+
+/* Subroutine */ int slarra_(integer *n, real *d__, real *e, real *e2, real *
+	spltol, real *tnrm, integer *nsplit, integer *isplit, integer *info);
+
+/* Subroutine */ int slarrb_(integer *n, real *d__, real *lld, integer *
+	ifirst, integer *ilast, real *rtol1, real *rtol2, integer *offset, 
+	real *w, real *wgap, real *werr, real *work, integer *iwork, real *
+	pivmin, real *spdiam, integer *twist, integer *info);
+
+/* Subroutine */ int slarrc_(char *jobt, integer *n, real *vl, real *vu, real 
+	*d__, real *e, real *pivmin, integer *eigcnt, integer *lcnt, integer *
+	rcnt, integer *info);
+
+/* Subroutine */ int slarrd_(char *range, char *order, integer *n, real *vl, 
+	real *vu, integer *il, integer *iu, real *gers, real *reltol, real *
+	d__, real *e, real *e2, real *pivmin, integer *nsplit, integer *
+	isplit, integer *m, real *w, real *werr, real *wl, real *wu, integer *
+	iblock, integer *indexw, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slarre_(char *range, integer *n, real *vl, real *vu, 
+	integer *il, integer *iu, real *d__, real *e, real *e2, real *rtol1, 
+	real *rtol2, real *spltol, integer *nsplit, integer *isplit, integer *
+	m, real *w, real *werr, real *wgap, integer *iblock, integer *indexw, 
+	real *gers, real *pivmin, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slarrf_(integer *n, real *d__, real *l, real *ld, 
+	integer *clstrt, integer *clend, real *w, real *wgap, real *werr, 
+	real *spdiam, real *clgapl, real *clgapr, real *pivmin, real *sigma, 
+	real *dplus, real *lplus, real *work, integer *info);
+
+/* Subroutine */ int slarrj_(integer *n, real *d__, real *e2, integer *ifirst, 
+	 integer *ilast, real *rtol, integer *offset, real *w, real *werr, 
+	real *work, integer *iwork, real *pivmin, real *spdiam, integer *info);
+
+/* Subroutine */ int slarrk_(integer *n, integer *iw, real *gl, real *gu, 
+	real *d__, real *e2, real *pivmin, real *reltol, real *w, real *werr, 
+	integer *info);
+
+/* Subroutine */ int slarrr_(integer *n, real *d__, real *e, integer *info);
+
+/* Subroutine */ int slarrv_(integer *n, real *vl, real *vu, real *d__, real *
+	l, real *pivmin, integer *isplit, integer *m, integer *dol, integer *
+	dou, real *minrgp, real *rtol1, real *rtol2, real *w, real *werr, 
+	real *wgap, integer *iblock, integer *indexw, real *gers, real *z__, 
+	integer *ldz, integer *isuppz, real *work, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int slarscl2_(integer *m, integer *n, real *d__, real *x, 
+	integer *ldx);
+
+/* Subroutine */ int slartg_(real *f, real *g, real *cs, real *sn, real *r__);
+
+/* Subroutine */ int slartv_(integer *n, real *x, integer *incx, real *y, 
+	integer *incy, real *c__, real *s, integer *incc);
+
+/* Subroutine */ int slaruv_(integer *iseed, integer *n, real *x);
+
+/* Subroutine */ int slarz_(char *side, integer *m, integer *n, integer *l, 
+	real *v, integer *incv, real *tau, real *c__, integer *ldc, real *
+	work);
+
+/* Subroutine */ int slarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, real *v, 
+	integer *ldv, real *t, integer *ldt, real *c__, integer *ldc, real *
+	work, integer *ldwork);
+
+/* Subroutine */ int slarzt_(char *direct, char *storev, integer *n, integer *
+	k, real *v, integer *ldv, real *tau, real *t, integer *ldt);
+
+/* Subroutine */ int slas2_(real *f, real *g, real *h__, real *ssmin, real *
+	ssmax);
+
+/* Subroutine */ int slascl_(char *type__, integer *kl, integer *ku, real *
+	cfrom, real *cto, integer *m, integer *n, real *a, integer *lda, 
+	integer *info);
+
+/* Subroutine */ int slascl2_(integer *m, integer *n, real *d__, real *x, 
+	integer *ldx);
+
+/* Subroutine */ int slasd0_(integer *n, integer *sqre, real *d__, real *e, 
+	real *u, integer *ldu, real *vt, integer *ldvt, integer *smlsiz, 
+	integer *iwork, real *work, integer *info);
+
+/* Subroutine */ int slasd1_(integer *nl, integer *nr, integer *sqre, real *
+	d__, real *alpha, real *beta, real *u, integer *ldu, real *vt, 
+	integer *ldvt, integer *idxq, integer *iwork, real *work, integer *
+	info);
+
+/* Subroutine */ int slasd2_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, real *d__, real *z__, real *alpha, real *beta, real *u, integer *
+	ldu, real *vt, integer *ldvt, real *dsigma, real *u2, integer *ldu2, 
+	real *vt2, integer *ldvt2, integer *idxp, integer *idx, integer *idxc, 
+	 integer *idxq, integer *coltyp, integer *info);
+
+/* Subroutine */ int slasd3_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, real *d__, real *q, integer *ldq, real *dsigma, real *u, integer *
+	ldu, real *u2, integer *ldu2, real *vt, integer *ldvt, real *vt2, 
+	integer *ldvt2, integer *idxc, integer *ctot, real *z__, integer *
+	info);
+
+/* Subroutine */ int slasd4_(integer *n, integer *i__, real *d__, real *z__, 
+	real *delta, real *rho, real *sigma, real *work, integer *info);
+
+/* Subroutine */ int slasd5_(integer *i__, real *d__, real *z__, real *delta, 
+	real *rho, real *dsigma, real *work);
+
+/* Subroutine */ int slasd6_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, real *d__, real *vf, real *vl, real *alpha, real *beta, 
+	 integer *idxq, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+	difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int slasd7_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *k, real *d__, real *z__, real *zw, real *vf, 
+	real *vfw, real *vl, real *vlw, real *alpha, real *beta, real *dsigma, 
+	 integer *idx, integer *idxp, integer *idxq, integer *perm, integer *
+	givptr, integer *givcol, integer *ldgcol, real *givnum, integer *
+	ldgnum, real *c__, real *s, integer *info);
+
+/* Subroutine */ int slasd8_(integer *icompq, integer *k, real *d__, real *
+	z__, real *vf, real *vl, real *difl, real *difr, integer *lddifr, 
+	real *dsigma, real *work, integer *info);
+
+/* Subroutine */ int slasda_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *sqre, real *d__, real *e, real *u, integer *ldu, real *vt, 
+	integer *k, real *difl, real *difr, real *z__, real *poles, integer *
+	givptr, integer *givcol, integer *ldgcol, integer *perm, real *givnum, 
+	 real *c__, real *s, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slasdq_(char *uplo, integer *sqre, integer *n, integer *
+	ncvt, integer *nru, integer *ncc, real *d__, real *e, real *vt, 
+	integer *ldvt, real *u, integer *ldu, real *c__, integer *ldc, real *
+	work, integer *info);
+
+/* Subroutine */ int slasdt_(integer *n, integer *lvl, integer *nd, integer *
+	inode, integer *ndiml, integer *ndimr, integer *msub);
+
+/* Subroutine */ int slaset_(char *uplo, integer *m, integer *n, real *alpha, 
+	real *beta, real *a, integer *lda);
+
+/* Subroutine */ int slasq1_(integer *n, real *d__, real *e, real *work, 
+	integer *info);
+
+/* Subroutine */ int slasq2_(integer *n, real *z__, integer *info);
+
+/* Subroutine */ int slasq3_(integer *i0, integer *n0, real *z__, integer *pp, 
+	 real *dmin__, real *sigma, real *desig, real *qmax, integer *nfail, 
+	integer *iter, integer *ndiv, logical *ieee, integer *ttype, real *
+	dmin1, real *dmin2, real *dn, real *dn1, real *dn2, real *g, real *
+	tau);
+
+/* Subroutine */ int slasq4_(integer *i0, integer *n0, real *z__, integer *pp, 
+	 integer *n0in, real *dmin__, real *dmin1, real *dmin2, real *dn, 
+	real *dn1, real *dn2, real *tau, integer *ttype, real *g);
+
+/* Subroutine */ int slasq5_(integer *i0, integer *n0, real *z__, integer *pp, 
+	 real *tau, real *dmin__, real *dmin1, real *dmin2, real *dn, real *
+	dnm1, real *dnm2, logical *ieee);
+
+/* Subroutine */ int slasq6_(integer *i0, integer *n0, real *z__, integer *pp, 
+	 real *dmin__, real *dmin1, real *dmin2, real *dn, real *dnm1, real *
+	dnm2);
+
+/* Subroutine */ int slasr_(char *side, char *pivot, char *direct, integer *m, 
+	 integer *n, real *c__, real *s, real *a, integer *lda);
+
+/* Subroutine */ int slasrt_(char *id, integer *n, real *d__, integer *info);
+
+/* Subroutine */ int slassq_(integer *n, real *x, integer *incx, real *scale, 
+	real *sumsq);
+
+/* Subroutine */ int slasv2_(real *f, real *g, real *h__, real *ssmin, real *
+	ssmax, real *snr, real *csr, real *snl, real *csl);
+
+/* Subroutine */ int slaswp_(integer *n, real *a, integer *lda, integer *k1, 
+	integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int slasy2_(logical *ltranl, logical *ltranr, integer *isgn, 
+	integer *n1, integer *n2, real *tl, integer *ldtl, real *tr, integer *
+	ldtr, real *b, integer *ldb, real *scale, real *x, integer *ldx, real 
+	*xnorm, integer *info);
+
+/* Subroutine */ int slasyf_(char *uplo, integer *n, integer *nb, integer *kb, 
+	 real *a, integer *lda, integer *ipiv, real *w, integer *ldw, integer 
+	*info);
+
+/* Subroutine */ int slatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, real *ab, integer *ldab, real *x, 
+	real *scale, real *cnorm, integer *info);
+
+/* Subroutine */ int slatdf_(integer *ijob, integer *n, real *z__, integer *
+	ldz, real *rhs, real *rdsum, real *rdscal, integer *ipiv, integer *
+	jpiv);
+
+/* Subroutine */ int slatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, real *ap, real *x, real *scale, real *cnorm, 
+	integer *info);
+
+/* Subroutine */ int slatrd_(char *uplo, integer *n, integer *nb, real *a, 
+	integer *lda, real *e, real *tau, real *w, integer *ldw);
+
+/* Subroutine */ int slatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, real *a, integer *lda, real *x, real *scale, real 
+	*cnorm, integer *info);
+
+/* Subroutine */ int slatrz_(integer *m, integer *n, integer *l, real *a, 
+	integer *lda, real *tau, real *work);
+
+/* Subroutine */ int slatzm_(char *side, integer *m, integer *n, real *v, 
+	integer *incv, real *tau, real *c1, real *c2, integer *ldc, real *
+	work);
+
+/* Subroutine */ int slauu2_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+
+/* Subroutine */ int slauum_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+
+/* Subroutine */ int sopgtr_(char *uplo, integer *n, real *ap, real *tau, 
+	real *q, integer *ldq, real *work, integer *info);
+
+/* Subroutine */ int sopmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, real *ap, real *tau, real *c__, integer *ldc, real *work, 
+	integer *info);
+
+/* Subroutine */ int sorg2l_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorg2r_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorgbr_(char *vect, integer *m, integer *n, integer *k, 
+	real *a, integer *lda, real *tau, real *work, integer *lwork, integer 
+	*info);
+
+/* Subroutine */ int sorghr_(integer *n, integer *ilo, integer *ihi, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgl2_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorglq_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgql_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgqr_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgr2_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorgrq_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgtr_(char *uplo, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *info);
+
+/* Subroutine */ int sorm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *info);
+
+/* Subroutine */ int sormbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, real *a, integer *lda, real *tau, real *c__, 
+	integer *ldc, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, real *a, integer *lda, real *tau, real *
+	c__, integer *ldc, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *info);
+
+/* Subroutine */ int sormlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *info);
+
+/* Subroutine */ int sormr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, real *a, integer *lda, real *tau, real *c__, 
+	integer *ldc, real *work, integer *info);
+
+/* Subroutine */ int sormrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, real *a, integer *lda, real *tau, real *c__, 
+	integer *ldc, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, real *a, integer *lda, real *tau, real *c__, integer *ldc, 
+	 real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int spbcon_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, real *anorm, real *rcond, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int spbequ_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, real *s, real *scond, real *amax, integer *info);
+
+/* Subroutine */ int spbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, real *ab, integer *ldab, real *afb, integer *ldafb, real *b, 
+	integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int spbstf_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, integer *info);
+
+/* Subroutine */ int spbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, real *ab, integer *ldab, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int spbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, real *ab, integer *ldab, real *afb, integer *ldafb, 
+	char *equed, real *s, real *b, integer *ldb, real *x, integer *ldx, 
+	real *rcond, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int spbtf2_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, integer *info);
+
+/* Subroutine */ int spbtrf_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, integer *info);
+
+/* Subroutine */ int spbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, real *ab, integer *ldab, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int spftrf_(char *transr, char *uplo, integer *n, real *a, 
+	integer *info);
+
+/* Subroutine */ int spftri_(char *transr, char *uplo, integer *n, real *a, 
+	integer *info);
+
+/* Subroutine */ int spftrs_(char *transr, char *uplo, integer *n, integer *
+	nrhs, real *a, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int spocon_(char *uplo, integer *n, real *a, integer *lda, 
+	real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int spoequ_(integer *n, real *a, integer *lda, real *s, real 
+	*scond, real *amax, integer *info);
+
+/* Subroutine */ int spoequb_(integer *n, real *a, integer *lda, real *s, 
+	real *scond, real *amax, integer *info);
+
+/* Subroutine */ int sporfs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *af, integer *ldaf, real *b, integer *ldb, real *x, 
+	 integer *ldx, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int sporfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, real *s, real *
+	b, integer *ldb, real *x, integer *ldx, real *rcond, real *berr, 
+	integer *n_err_bnds__, real *err_bnds_norm__, real *err_bnds_comp__, 
+	integer *nparams, real *params, real *work, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int sposv_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, char *equed, 
+	real *s, real *b, integer *ldb, real *x, integer *ldx, real *rcond, 
+	real *ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sposvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, char *equed, 
+	real *s, real *b, integer *ldb, real *x, integer *ldx, real *rcond, 
+	real *rpvgrw, real *berr, integer *n_err_bnds__, real *
+	err_bnds_norm__, real *err_bnds_comp__, integer *nparams, real *
+	params, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int spotf2_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+
+/* Subroutine */ int spotrf_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+
+/* Subroutine */ int spotri_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+
+/* Subroutine */ int spotrs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sppcon_(char *uplo, integer *n, real *ap, real *anorm, 
+	real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sppequ_(char *uplo, integer *n, real *ap, real *s, real *
+	scond, real *amax, integer *info);
+
+/* Subroutine */ int spprfs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *afp, real *b, integer *ldb, real *x, integer *ldx, real *ferr, 
+	real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sppsv_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *ap, real *afp, char *equed, real *s, real *b, integer *
+	ldb, real *x, integer *ldx, real *rcond, real *ferr, real *berr, real 
+	*work, integer *iwork, integer *info);
+
+/* Subroutine */ int spptrf_(char *uplo, integer *n, real *ap, integer *info);
+
+/* Subroutine */ int spptri_(char *uplo, integer *n, real *ap, integer *info);
+
+/* Subroutine */ int spptrs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int spstf2_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *piv, integer *rank, real *tol, real *work, integer *info);
+
+/* Subroutine */ int spstrf_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *piv, integer *rank, real *tol, real *work, integer *info);
+
+/* Subroutine */ int sptcon_(integer *n, real *d__, real *e, real *anorm, 
+	real *rcond, real *work, integer *info);
+
+/* Subroutine */ int spteqr_(char *compz, integer *n, real *d__, real *e, 
+	real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int sptrfs_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *df, real *ef, real *b, integer *ldb, real *x, integer *ldx, 
+	real *ferr, real *berr, real *work, integer *info);
+
+/* Subroutine */ int sptsv_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sptsvx_(char *fact, integer *n, integer *nrhs, real *d__, 
+	 real *e, real *df, real *ef, real *b, integer *ldb, real *x, integer 
+	*ldx, real *rcond, real *ferr, real *berr, real *work, integer *info);
+
+/* Subroutine */ int spttrf_(integer *n, real *d__, real *e, integer *info);
+
+/* Subroutine */ int spttrs_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sptts2_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *b, integer *ldb);
+
+/* Subroutine */ int srscl_(integer *n, real *sa, real *sx, integer *incx);
+
+/* Subroutine */ int ssbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	real *ab, integer *ldab, real *w, real *z__, integer *ldz, real *work, 
+	 integer *info);
+
+/* Subroutine */ int ssbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	real *ab, integer *ldab, real *w, real *z__, integer *ldz, real *work, 
+	 integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int ssbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, real *ab, integer *ldab, real *q, integer *ldq, real *vl, 
+	 real *vu, integer *il, integer *iu, real *abstol, integer *m, real *
+	w, real *z__, integer *ldz, real *work, integer *iwork, integer *
+	ifail, integer *info);
+
+/* Subroutine */ int ssbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+	x, integer *ldx, real *work, integer *info);
+
+/* Subroutine */ int ssbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+	w, real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int ssbgvd_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+	w, real *z__, integer *ldz, real *work, integer *lwork, integer *
+	iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int ssbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, real *ab, integer *ldab, real *bb, integer *
+	ldbb, real *q, integer *ldq, real *vl, real *vu, integer *il, integer 
+	*iu, real *abstol, integer *m, real *w, real *z__, integer *ldz, real 
+	*work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	real *ab, integer *ldab, real *d__, real *e, real *q, integer *ldq, 
+	real *work, integer *info);
+
+/* Subroutine */ int ssfrk_(char *transr, char *uplo, char *trans, integer *n, 
+	 integer *k, real *alpha, real *a, integer *lda, real *beta, real *
+	c__);
+
+/* Subroutine */ int sspcon_(char *uplo, integer *n, real *ap, integer *ipiv, 
+	real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sspev_(char *jobz, char *uplo, integer *n, real *ap, 
+	real *w, real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int sspevd_(char *jobz, char *uplo, integer *n, real *ap, 
+	real *w, real *z__, integer *ldz, real *work, integer *lwork, integer 
+	*iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sspevx_(char *jobz, char *range, char *uplo, integer *n, 
+	real *ap, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, real *work, integer *
+	iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int sspgst_(integer *itype, char *uplo, integer *n, real *ap, 
+	 real *bp, integer *info);
+
+/* Subroutine */ int sspgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *ap, real *bp, real *w, real *z__, integer *ldz, real *work, 
+	integer *info);
+
+/* Subroutine */ int sspgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *ap, real *bp, real *w, real *z__, integer *ldz, real *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sspgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, real *ap, real *bp, real *vl, real *vu, integer *il, 
+	 integer *iu, real *abstol, integer *m, real *w, real *z__, integer *
+	ldz, real *work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssprfs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *afp, integer *ipiv, real *b, integer *ldb, real *x, integer *
+	ldx, real *ferr, real *berr, real *work, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int sspsv_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *ap, real *afp, integer *ipiv, real *b, integer *ldb, real 
+	*x, integer *ldx, real *rcond, real *ferr, real *berr, real *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int ssptrd_(char *uplo, integer *n, real *ap, real *d__, 
+	real *e, real *tau, integer *info);
+
+/* Subroutine */ int ssptrf_(char *uplo, integer *n, real *ap, integer *ipiv, 
+	integer *info);
+
+/* Subroutine */ int ssptri_(char *uplo, integer *n, real *ap, integer *ipiv, 
+	real *work, integer *info);
+
+/* Subroutine */ int ssptrs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sstebz_(char *range, char *order, integer *n, real *vl, 
+	real *vu, integer *il, integer *iu, real *abstol, real *d__, real *e, 
+	integer *m, integer *nsplit, real *w, integer *iblock, integer *
+	isplit, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sstedc_(char *compz, integer *n, real *d__, real *e, 
+	real *z__, integer *ldz, real *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int sstegr_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, integer *isuppz, real *
+	work, integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sstein_(integer *n, real *d__, real *e, integer *m, real 
+	*w, integer *iblock, integer *isplit, real *z__, integer *ldz, real *
+	work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int sstemr_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, integer *m, 
+	real *w, real *z__, integer *ldz, integer *nzc, integer *isuppz, 
+	logical *tryrac, real *work, integer *lwork, integer *iwork, integer *
+	liwork, integer *info);
+
+/* Subroutine */ int ssteqr_(char *compz, integer *n, real *d__, real *e, 
+	real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int ssterf_(integer *n, real *d__, real *e, integer *info);
+
+/* Subroutine */ int sstev_(char *jobz, integer *n, real *d__, real *e, real *
+	z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int sstevd_(char *jobz, integer *n, real *d__, real *e, real 
+	*z__, integer *ldz, real *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int sstevr_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, integer *isuppz, real *
+	work, integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sstevx_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, real *work, integer *
+	iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssycon_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, real *anorm, real *rcond, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int ssyequb_(char *uplo, integer *n, real *a, integer *lda, 
+	real *s, real *scond, real *amax, real *work, integer *info);
+
+/* Subroutine */ int ssyev_(char *jobz, char *uplo, integer *n, real *a, 
+	integer *lda, real *w, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int ssyevd_(char *jobz, char *uplo, integer *n, real *a, 
+	integer *lda, real *w, real *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int ssyevr_(char *jobz, char *range, char *uplo, integer *n, 
+	real *a, integer *lda, real *vl, real *vu, integer *il, integer *iu, 
+	real *abstol, integer *m, real *w, real *z__, integer *ldz, integer *
+	isuppz, real *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+
+/* Subroutine */ int ssyevx_(char *jobz, char *range, char *uplo, integer *n, 
+	real *a, integer *lda, real *vl, real *vu, integer *il, integer *iu, 
+	real *abstol, integer *m, real *w, real *z__, integer *ldz, real *
+	work, integer *lwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssygs2_(integer *itype, char *uplo, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ssygst_(integer *itype, char *uplo, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ssygv_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *w, real *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int ssygvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *w, real *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int ssygvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, real *a, integer *lda, real *b, integer *ldb, real *
+	vl, real *vu, integer *il, integer *iu, real *abstol, integer *m, 
+	real *w, real *z__, integer *ldz, real *work, integer *lwork, integer 
+	*iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssyrfs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *af, integer *ldaf, integer *ipiv, real *b, 
+	integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+	work, integer *iwork, integer *info);
+
+/* Subroutine */ int ssyrfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	real *s, real *b, integer *ldb, real *x, integer *ldx, real *rcond, 
+	real *berr, integer *n_err_bnds__, real *err_bnds_norm__, real *
+	err_bnds_comp__, integer *nparams, real *params, real *work, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int ssysv_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, integer *ipiv, real *b, integer *ldb, real *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int ssysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	real *b, integer *ldb, real *x, integer *ldx, real *rcond, real *ferr, 
+	 real *berr, real *work, integer *lwork, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int ssysvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	char *equed, real *s, real *b, integer *ldb, real *x, integer *ldx, 
+	real *rcond, real *rpvgrw, real *berr, integer *n_err_bnds__, real *
+	err_bnds_norm__, real *err_bnds_comp__, integer *nparams, real *
+	params, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int ssytd2_(char *uplo, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tau, integer *info);
+
+/* Subroutine */ int ssytf2_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, integer *info);
+
+/* Subroutine */ int ssytrd_(char *uplo, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tau, real *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int ssytrf_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int ssytri_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, real *work, integer *info);
+
+/* Subroutine */ int ssytrs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int stbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, real *ab, integer *ldab, real *rcond, real *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int stbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, real *ab, integer *ldab, real *b, integer 
+	*ldb, real *x, integer *ldx, real *ferr, real *berr, real *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int stbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, real *ab, integer *ldab, real *b, integer 
+	*ldb, integer *info);
+
+/* Subroutine */ int stfsm_(char *transr, char *side, char *uplo, char *trans, 
+	 char *diag, integer *m, integer *n, real *alpha, real *a, real *b, 
+	integer *ldb);
+
+/* Subroutine */ int stftri_(char *transr, char *uplo, char *diag, integer *n, 
+	 real *a, integer *info);
+
+/* Subroutine */ int stfttp_(char *transr, char *uplo, integer *n, real *arf, 
+	real *ap, integer *info);
+
+/* Subroutine */ int stfttr_(char *transr, char *uplo, integer *n, real *arf, 
+	real *a, integer *lda, integer *info);
+
+/* Subroutine */ int stgevc_(char *side, char *howmny, logical *select, 
+	integer *n, real *s, integer *lds, real *p, integer *ldp, real *vl, 
+	integer *ldvl, real *vr, integer *ldvr, integer *mm, integer *m, real 
+	*work, integer *info);
+
+/* Subroutine */ int stgex2_(logical *wantq, logical *wantz, integer *n, real 
+	*a, integer *lda, real *b, integer *ldb, real *q, integer *ldq, real *
+	z__, integer *ldz, integer *j1, integer *n1, integer *n2, real *work, 
+	integer *lwork, integer *info);
+
+/* Subroutine */ int stgexc_(logical *wantq, logical *wantz, integer *n, real 
+	*a, integer *lda, real *b, integer *ldb, real *q, integer *ldq, real *
+	z__, integer *ldz, integer *ifst, integer *ilst, real *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int stgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, real *a, integer *lda, real *b, integer *
+	ldb, real *alphar, real *alphai, real *beta, real *q, integer *ldq, 
+	real *z__, integer *ldz, integer *m, real *pl, real *pr, real *dif, 
+	real *work, integer *lwork, integer *iwork, integer *liwork, integer *
+	info);
+
+/* Subroutine */ int stgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, real *a, integer *lda, 
+	 real *b, integer *ldb, real *tola, real *tolb, real *alpha, real *
+	beta, real *u, integer *ldu, real *v, integer *ldv, real *q, integer *
+	ldq, real *work, integer *ncycle, integer *info);
+
+/* Subroutine */ int stgsna_(char *job, char *howmny, logical *select, 
+	integer *n, real *a, integer *lda, real *b, integer *ldb, real *vl, 
+	integer *ldvl, real *vr, integer *ldvr, real *s, real *dif, integer *
+	mm, integer *m, real *work, integer *lwork, integer *iwork, integer *
+	info);
+
+/* Subroutine */ int stgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *c__, integer *
+	ldc, real *d__, integer *ldd, real *e, integer *lde, real *f, integer 
+	*ldf, real *scale, real *rdsum, real *rdscal, integer *iwork, integer 
+	*pq, integer *info);
+
+/* Subroutine */ int stgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *c__, integer *
+	ldc, real *d__, integer *ldd, real *e, integer *lde, real *f, integer 
+	*ldf, real *scale, real *dif, real *work, integer *lwork, integer *
+	iwork, integer *info);
+
+/* Subroutine */ int stpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	real *ap, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int stprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *ap, real *b, integer *ldb, real *x, integer *ldx, 
+	 real *ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int stptri_(char *uplo, char *diag, integer *n, real *ap, 
+	integer *info);
+
+/* Subroutine */ int stptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *ap, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int stpttf_(char *transr, char *uplo, integer *n, real *ap, 
+	real *arf, integer *info);
+
+/* Subroutine */ int stpttr_(char *uplo, integer *n, real *ap, real *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int strcon_(char *norm, char *uplo, char *diag, integer *n, 
+	real *a, integer *lda, real *rcond, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int strevc_(char *side, char *howmny, logical *select, 
+	integer *n, real *t, integer *ldt, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, integer *mm, integer *m, real *work, integer *info);
+
+/* Subroutine */ int strexc_(char *compq, integer *n, real *t, integer *ldt, 
+	real *q, integer *ldq, integer *ifst, integer *ilst, real *work, 
+	integer *info);
+
+/* Subroutine */ int strrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *a, integer *lda, real *b, integer *ldb, real *x, 
+	integer *ldx, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+
+/* Subroutine */ int strsen_(char *job, char *compq, logical *select, integer 
+	*n, real *t, integer *ldt, real *q, integer *ldq, real *wr, real *wi, 
+	integer *m, real *s, real *sep, real *work, integer *lwork, integer *
+	iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int strsna_(char *job, char *howmny, logical *select, 
+	integer *n, real *t, integer *ldt, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, real *s, real *sep, integer *mm, integer *m, real *
+	work, integer *ldwork, integer *iwork, integer *info);
+
+/* Subroutine */ int strsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, real *a, integer *lda, real *b, integer *ldb, real *
+	c__, integer *ldc, real *scale, integer *info);
+
+/* Subroutine */ int strti2_(char *uplo, char *diag, integer *n, real *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int strtri_(char *uplo, char *diag, integer *n, real *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int strtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *a, integer *lda, real *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int strttf_(char *transr, char *uplo, integer *n, real *a, 
+	integer *lda, real *arf, integer *info);
+
+/* Subroutine */ int strttp_(char *uplo, integer *n, real *a, integer *lda, 
+	real *ap, integer *info);
+
+/* Subroutine */ int stzrqf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, integer *info);
+
+/* Subroutine */ int stzrzf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int xerbla_(char *srname, integer *info);
+
+/* Subroutine */ int xerbla_array__(char *srname_array__, integer *
+	srname_len__, integer *info, ftnlen srname_array_len);
+
+/* Subroutine */ int zbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, doublereal *d__, doublereal *e, doublecomplex *vt, 
+	integer *ldvt, doublecomplex *u, integer *ldu, doublecomplex *c__, 
+	integer *ldc, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zcgesv_(integer *n, integer *nrhs, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublecomplex *work, complex *swork, 
+	doublereal *rwork, integer *iter, integer *info);
+
+/* Subroutine */ int zcposv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublecomplex *work, complex *swork, 
+	doublereal *rwork, integer *iter, integer *info);
+
+/* Subroutine */ int zdrscl_(integer *n, doublereal *sa, doublecomplex *sx, 
+	integer *incx);
+
+/* Subroutine */ int zgbbrd_(char *vect, integer *m, integer *n, integer *ncc, 
+	 integer *kl, integer *ku, doublecomplex *ab, integer *ldab, 
+	doublereal *d__, doublereal *e, doublecomplex *q, integer *ldq, 
+	doublecomplex *pt, integer *ldpt, doublecomplex *c__, integer *ldc, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgbcon_(char *norm, integer *n, integer *kl, integer *ku, 
+	 doublecomplex *ab, integer *ldab, integer *ipiv, doublereal *anorm, 
+	doublereal *rcond, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zgbequ_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublecomplex *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, integer *
+	info);
+
+/* Subroutine */ int zgbequb_(integer *m, integer *n, integer *kl, integer *
+	ku, doublecomplex *ab, integer *ldab, doublereal *r__, doublereal *
+	c__, doublereal *rowcnd, doublereal *colcnd, doublereal *amax, 
+	integer *info);
+
+/* Subroutine */ int zgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublecomplex *ab, integer *ldab, doublecomplex *
+	afb, integer *ldafb, integer *ipiv, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgbrfsx_(char *trans, char *equed, integer *n, integer *
+	kl, integer *ku, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *afb, integer *ldafb, integer *ipiv, doublereal *r__, 
+	doublereal *c__, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	integer *ldx, doublereal *rcond, doublereal *berr, integer *
+	n_err_bnds__, doublereal *err_bnds_norm__, doublereal *
+	err_bnds_comp__, integer *nparams, doublereal *params, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, doublecomplex *ab, integer *ldab, integer *ipiv, doublecomplex *
+	b, integer *ldb, integer *info);
+
+/* Subroutine */ int zgbsvx_(char *fact, char *trans, integer *n, integer *kl, 
+	 integer *ku, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *afb, integer *ldafb, integer *ipiv, char *equed, 
+	doublereal *r__, doublereal *c__, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zgbsvxx_(char *fact, char *trans, integer *n, integer *
+	kl, integer *ku, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *afb, integer *ldafb, integer *ipiv, char *equed, 
+	doublereal *r__, doublereal *c__, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *rpvgrw, 
+	 doublereal *berr, integer *n_err_bnds__, doublereal *err_bnds_norm__, 
+	 doublereal *err_bnds_comp__, integer *nparams, doublereal *params, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgbtf2_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublecomplex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgbtrf_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublecomplex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublecomplex *ab, integer *ldab, integer *ipiv, 
+	doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *scale, integer *m, doublecomplex *v, 
+	integer *ldv, integer *info);
+
+/* Subroutine */ int zgebal_(char *job, integer *n, doublecomplex *a, integer 
+	*lda, integer *ilo, integer *ihi, doublereal *scale, integer *info);
+
+/* Subroutine */ int zgebd2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *d__, doublereal *e, doublecomplex *tauq, 
+	doublecomplex *taup, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgebrd_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *d__, doublereal *e, doublecomplex *tauq, 
+	doublecomplex *taup, doublecomplex *work, integer *lwork, integer *
+	info);
+
+/* Subroutine */ int zgecon_(char *norm, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeequ_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, 
+	doublereal *colcnd, doublereal *amax, integer *info);
+
+/* Subroutine */ int zgeequb_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, 
+	doublereal *colcnd, doublereal *amax, integer *info);
+
+/* Subroutine */ int zgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	doublecomplex *a, integer *lda, integer *sdim, doublecomplex *w, 
+	doublecomplex *vs, integer *ldvs, doublecomplex *work, integer *lwork, 
+	 doublereal *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, doublecomplex *a, integer *lda, integer *sdim, 
+	doublecomplex *w, doublecomplex *vs, integer *ldvs, doublereal *
+	rconde, doublereal *rcondv, doublecomplex *work, integer *lwork, 
+	doublereal *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zgeev_(char *jobvl, char *jobvr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *w, doublecomplex *vl, 
+	integer *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublecomplex *a, integer *lda, doublecomplex *w, 
+	doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr, 
+	integer *ilo, integer *ihi, doublereal *scale, doublereal *abnrm, 
+	doublereal *rconde, doublereal *rcondv, doublecomplex *work, integer *
+	lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgegs_(char *jobvsl, char *jobvsr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, 
+	integer *ldvsl, doublecomplex *vsr, integer *ldvsr, doublecomplex *
+	work, integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgegv_(char *jobvl, char *jobvr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, integer 
+	*ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, integer 
+	*lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgehd2_(integer *n, integer *ilo, integer *ihi, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zgehrd_(integer *n, integer *ilo, integer *ihi, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgelq2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgelqf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgelsd_(integer *m, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublereal *s, doublereal *rcond, integer *rank, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zgelss_(integer *m, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublereal *s, doublereal *rcond, integer *rank, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgelsx_(integer *m, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *jpvt, doublereal *rcond, integer *rank, doublecomplex *work, 
+	doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgelsy_(integer *m, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *jpvt, doublereal *rcond, integer *rank, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeql2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgeqlf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zgeqp3_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *jpvt, doublecomplex *tau, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeqpf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *jpvt, doublecomplex *tau, doublecomplex *work, 
+	doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeqr2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgeqrf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zgerfs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work, 
+	 doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgerfsx_(char *trans, char *equed, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, doublereal *r__, doublereal *c__, doublecomplex *
+	b, integer *ldb, doublecomplex *x, integer *ldx, doublereal *rcond, 
+	doublereal *berr, integer *n_err_bnds__, doublereal *err_bnds_norm__, 
+	doublereal *err_bnds_comp__, integer *nparams, doublereal *params, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgerq2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgerqf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zgesc2_(integer *n, doublecomplex *a, integer *lda, 
+	doublecomplex *rhs, integer *ipiv, integer *jpiv, doublereal *scale);
+
+/* Subroutine */ int zgesdd_(char *jobz, integer *m, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u, 
+	integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zgesv_(integer *n, integer *nrhs, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *b, integer *ldb, integer *
+	info);
+
+/* Subroutine */ int zgesvd_(char *jobu, char *jobvt, integer *m, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u, 
+	integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, char *equed, doublereal *r__, doublereal *c__, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgesvxx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, char *equed, doublereal *r__, doublereal *c__, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *rpvgrw, doublereal *berr, integer *
+	n_err_bnds__, doublereal *err_bnds_norm__, doublereal *
+	err_bnds_comp__, integer *nparams, doublereal *params, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgetc2_(integer *n, doublecomplex *a, integer *lda, 
+	integer *ipiv, integer *jpiv, integer *info);
+
+/* Subroutine */ int zgetf2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgetrf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgetri_(integer *n, doublecomplex *a, integer *lda, 
+	integer *ipiv, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgetrs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, integer *info);
+
+/* Subroutine */ int zggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *lscale, doublereal *rscale, integer *m, 
+	doublecomplex *v, integer *ldv, integer *info);
+
+/* Subroutine */ int zggbal_(char *job, integer *n, doublecomplex *a, integer 
+	*lda, doublecomplex *b, integer *ldb, integer *ilo, integer *ihi, 
+	doublereal *lscale, doublereal *rscale, doublereal *work, integer *
+	info);
+
+/* Subroutine */ int zgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, integer *sdim, doublecomplex *alpha, doublecomplex *
+	beta, doublecomplex *vsl, integer *ldvsl, doublecomplex *vsr, integer 
+	*ldvsr, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	logical *bwork, integer *info);
+
+/* Subroutine */ int zggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, char *sense, integer *n, doublecomplex *a, integer *lda, 
+	doublecomplex *b, integer *ldb, integer *sdim, doublecomplex *alpha, 
+	doublecomplex *beta, doublecomplex *vsl, integer *ldvsl, 
+	doublecomplex *vsr, integer *ldvsr, doublereal *rconde, doublereal *
+	rcondv, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	integer *iwork, integer *liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zggev_(char *jobvl, char *jobvr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, integer 
+	*ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, integer 
+	*lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *alpha, doublecomplex *beta, 
+	doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr, 
+	integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale, 
+	doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal *
+	rcondv, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	integer *iwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zggglm_(integer *n, integer *m, integer *p, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *d__, doublecomplex *x, doublecomplex *y, doublecomplex 
+	*work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *q, integer *ldq, doublecomplex *z__, 
+	integer *ldz, integer *info);
+
+/* Subroutine */ int zgglse_(integer *m, integer *n, integer *p, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *c__, doublecomplex *d__, doublecomplex *x, 
+	doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zggqrf_(integer *n, integer *m, integer *p, 
+	doublecomplex *a, integer *lda, doublecomplex *taua, doublecomplex *b, 
+	 integer *ldb, doublecomplex *taub, doublecomplex *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int zggrqf_(integer *m, integer *p, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *taua, doublecomplex *b, 
+	 integer *ldb, doublecomplex *taub, doublecomplex *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int zggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, doublecomplex *a, 
+	integer *lda, doublecomplex *b, integer *ldb, doublereal *alpha, 
+	doublereal *beta, doublecomplex *u, integer *ldu, doublecomplex *v, 
+	integer *ldv, doublecomplex *q, integer *ldq, doublecomplex *work, 
+	doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, doublecomplex *a, integer *lda, doublecomplex 
+	*b, integer *ldb, doublereal *tola, doublereal *tolb, integer *k, 
+	integer *l, doublecomplex *u, integer *ldu, doublecomplex *v, integer 
+	*ldv, doublecomplex *q, integer *ldq, integer *iwork, doublereal *
+	rwork, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgtcon_(char *norm, integer *n, doublecomplex *dl, 
+	doublecomplex *d__, doublecomplex *du, doublecomplex *du2, integer *
+	ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *work, 
+	integer *info);
+
+/* Subroutine */ int zgtrfs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *dlf, doublecomplex *df, doublecomplex *duf, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgtsv_(integer *n, integer *nrhs, doublecomplex *dl, 
+	doublecomplex *d__, doublecomplex *du, doublecomplex *b, integer *ldb, 
+	 integer *info);
+
+/* Subroutine */ int zgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *dlf, doublecomplex *df, doublecomplex *duf, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zgttrf_(integer *n, doublecomplex *dl, doublecomplex *
+	d__, doublecomplex *du, doublecomplex *du2, integer *ipiv, integer *
+	info);
+
+/* Subroutine */ int zgttrs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zgtts2_(integer *itrans, integer *n, integer *nrhs, 
+	doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zhbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *w, doublecomplex *z__, 
+	integer *ldz, doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *w, doublecomplex *z__, 
+	integer *ldz, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	integer *lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zhbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, doublecomplex *ab, integer *ldab, doublecomplex *q, 
+	integer *ldq, doublereal *vl, doublereal *vu, integer *il, integer *
+	iu, doublereal *abstol, integer *m, doublereal *w, doublecomplex *z__, 
+	 integer *ldz, doublecomplex *work, doublereal *rwork, integer *iwork, 
+	 integer *ifail, integer *info);
+
+/* Subroutine */ int zhbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublecomplex *ab, integer *ldab, doublecomplex *bb, 
+	integer *ldbb, doublecomplex *x, integer *ldx, doublecomplex *work, 
+	doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublecomplex *ab, integer *ldab, doublecomplex *bb, 
+	integer *ldbb, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhbgvd_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublecomplex *ab, integer *ldab, doublecomplex *bb, 
+	integer *ldbb, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, integer *lwork, doublereal *rwork, integer *
+	lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zhbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, doublecomplex *ab, integer *ldab, 
+	doublecomplex *bb, integer *ldbb, doublecomplex *q, integer *ldq, 
+	doublereal *vl, doublereal *vu, integer *il, integer *iu, doublereal *
+	abstol, integer *m, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, doublereal *rwork, integer *iwork, integer *
+	ifail, integer *info);
+
+/* Subroutine */ int zhbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *d__, doublereal *e, 
+	doublecomplex *q, integer *ldq, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zhecon_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublereal *anorm, doublereal *rcond, 
+	doublecomplex *work, integer *info);
+
+/* Subroutine */ int zheequb_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *s, doublereal *scond, doublereal *amax, 
+	doublecomplex *work, integer *info);
+
+/* Subroutine */ int zheev_(char *jobz, char *uplo, integer *n, doublecomplex 
+	*a, integer *lda, doublereal *w, doublecomplex *work, integer *lwork, 
+	doublereal *rwork, integer *info);
+
+/* Subroutine */ int zheevd_(char *jobz, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *w, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *lrwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int zheevr_(char *jobz, char *range, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *vl, doublereal *vu, 
+	integer *il, integer *iu, doublereal *abstol, integer *m, doublereal *
+	w, doublecomplex *z__, integer *ldz, integer *isuppz, doublecomplex *
+	work, integer *lwork, doublereal *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zheevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *vl, doublereal *vu, 
+	integer *il, integer *iu, doublereal *abstol, integer *m, doublereal *
+	w, doublecomplex *z__, integer *ldz, doublecomplex *work, integer *
+	lwork, doublereal *rwork, integer *iwork, integer *ifail, integer *
+	info);
+
+/* Subroutine */ int zhegs2_(integer *itype, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zhegst_(integer *itype, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zhegv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublereal *w, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	 integer *info);
+
+/* Subroutine */ int zhegvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublereal *w, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	 integer *lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zhegvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublereal *vl, doublereal *vu, integer *il, integer *
+	iu, doublereal *abstol, integer *m, doublereal *w, doublecomplex *z__, 
+	 integer *ldz, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	 integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int zherfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work, 
+	 doublereal *rwork, integer *info);
+
+/* Subroutine */ int zherfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, doublereal *s, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *berr, 
+	integer *n_err_bnds__, doublereal *err_bnds_norm__, doublereal *
+	err_bnds_comp__, integer *nparams, doublereal *params, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhesv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zhesvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	 integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhesvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, char *equed, doublereal *s, doublecomplex *b, 
+	integer *ldb, doublecomplex *x, integer *ldx, doublereal *rcond, 
+	doublereal *rpvgrw, doublereal *berr, integer *n_err_bnds__, 
+	doublereal *err_bnds_norm__, doublereal *err_bnds_comp__, integer *
+	nparams, doublereal *params, doublecomplex *work, doublereal *rwork, 
+	integer *info);
+
+/* Subroutine */ int zhetd2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *d__, doublereal *e, doublecomplex *tau, 
+	integer *info);
+
+/* Subroutine */ int zhetf2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zhetrd_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *d__, doublereal *e, doublecomplex *tau, 
+	doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zhetrf_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int zhetri_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zhetrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, integer *info);
+
+/* Subroutine */ int zhfrk_(char *transr, char *uplo, char *trans, integer *n, 
+	 integer *k, doublereal *alpha, doublecomplex *a, integer *lda, 
+	doublereal *beta, doublecomplex *c__);
+
+/* Subroutine */ int zhgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *h__, integer *ldh, 
+	doublecomplex *t, integer *ldt, doublecomplex *alpha, doublecomplex *
+	beta, doublecomplex *q, integer *ldq, doublecomplex *z__, integer *
+	ldz, doublecomplex *work, integer *lwork, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zhpcon_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zhpev_(char *jobz, char *uplo, integer *n, doublecomplex 
+	*ap, doublereal *w, doublecomplex *z__, integer *ldz, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhpevd_(char *jobz, char *uplo, integer *n, 
+	doublecomplex *ap, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, integer *lwork, doublereal *rwork, integer *
+	lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zhpevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublecomplex *ap, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublecomplex *z__, integer *ldz, doublecomplex *work, doublereal *
+	rwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int zhpgst_(integer *itype, char *uplo, integer *n, 
+	doublecomplex *ap, doublecomplex *bp, integer *info);
+
+/* Subroutine */ int zhpgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *ap, doublecomplex *bp, doublereal *w, doublecomplex 
+	*z__, integer *ldz, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zhpgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *ap, doublecomplex *bp, doublereal *w, doublecomplex 
+	*z__, integer *ldz, doublecomplex *work, integer *lwork, doublereal *
+	rwork, integer *lrwork, integer *iwork, integer *liwork, integer *
+	info);
+
+/* Subroutine */ int zhpgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublecomplex *ap, doublecomplex *bp, doublereal *
+	vl, doublereal *vu, integer *il, integer *iu, doublereal *abstol, 
+	integer *m, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, doublereal *rwork, integer *iwork, integer *
+	ifail, integer *info);
+
+/* Subroutine */ int zhprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *afp, integer *ipiv, doublecomplex *
+	b, integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zhpsv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zhpsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *ap, doublecomplex *afp, integer *ipiv, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhptrd_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *d__, doublereal *e, doublecomplex *tau, integer *info);
+
+/* Subroutine */ int zhptrf_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, integer *info);
+
+/* Subroutine */ int zhptri_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zhptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zhsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, doublecomplex *h__, integer *ldh, doublecomplex *
+	w, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr, 
+	 integer *mm, integer *m, doublecomplex *work, doublereal *rwork, 
+	integer *ifaill, integer *ifailr, integer *info);
+
+/* Subroutine */ int zhseqr_(char *job, char *compz, integer *n, integer *ilo, 
+	 integer *ihi, doublecomplex *h__, integer *ldh, doublecomplex *w, 
+	doublecomplex *z__, integer *ldz, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zla_gbamv__(integer *trans, integer *m, integer *n, 
+	integer *kl, integer *ku, doublereal *alpha, doublecomplex *ab, 
+	integer *ldab, doublecomplex *x, integer *incx, doublereal *beta, 
+	doublereal *y, integer *incy);
+
+doublereal zla_gbrcond_c__(char *trans, integer *n, integer *kl, integer *ku, 
+	doublecomplex *ab, integer *ldab, doublecomplex *afb, integer *ldafb, 
+	integer *ipiv, doublereal *c__, logical *capply, integer *info, 
+	doublecomplex *work, doublereal *rwork, ftnlen trans_len);
+
+doublereal zla_gbrcond_x__(char *trans, integer *n, integer *kl, integer *ku, 
+	doublecomplex *ab, integer *ldab, doublecomplex *afb, integer *ldafb, 
+	integer *ipiv, doublecomplex *x, integer *info, doublecomplex *work, 
+	doublereal *rwork, ftnlen trans_len);
+
+/* Subroutine */ int zla_gbrfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *kl, integer *ku, integer *nrhs, 
+	doublecomplex *ab, integer *ldab, doublecomplex *afb, integer *ldafb, 
+	integer *ipiv, logical *colequ, doublereal *c__, doublecomplex *b, 
+	integer *ldb, doublecomplex *y, integer *ldy, doublereal *berr_out__, 
+	integer *n_norms__, doublereal *errs_n__, doublereal *errs_c__, 
+	doublecomplex *res, doublereal *ayb, doublecomplex *dy, doublecomplex 
+	*y_tail__, doublereal *rcond, integer *ithresh, doublereal *rthresh, 
+	doublereal *dz_ub__, logical *ignore_cwise__, integer *info);
+
+doublereal zla_gbrpvgrw__(integer *n, integer *kl, integer *ku, integer *
+	ncols, doublecomplex *ab, integer *ldab, doublecomplex *afb, integer *
+	ldafb);
+
+/* Subroutine */ int zla_geamv__(integer *trans, integer *m, integer *n, 
+	doublereal *alpha, doublecomplex *a, integer *lda, doublecomplex *x, 
+	integer *incx, doublereal *beta, doublereal *y, integer *incy);
+
+doublereal zla_gercond_c__(char *trans, integer *n, doublecomplex *a, integer 
+	*lda, doublecomplex *af, integer *ldaf, integer *ipiv, doublereal *
+	c__, logical *capply, integer *info, doublecomplex *work, doublereal *
+	rwork, ftnlen trans_len);
+
+doublereal zla_gercond_x__(char *trans, integer *n, doublecomplex *a, integer 
+	*lda, doublecomplex *af, integer *ldaf, integer *ipiv, doublecomplex *
+	x, integer *info, doublecomplex *work, doublereal *rwork, ftnlen 
+	trans_len);
+
+/* Subroutine */ int zla_gerfsx_extended__(integer *prec_type__, integer *
+	trans_type__, integer *n, integer *nrhs, doublecomplex *a, integer *
+	lda, doublecomplex *af, integer *ldaf, integer *ipiv, logical *colequ,
+	 doublereal *c__, doublecomplex *b, integer *ldb, doublecomplex *y, 
+	integer *ldy, doublereal *berr_out__, integer *n_norms__, doublereal *
+	errs_n__, doublereal *errs_c__, doublecomplex *res, doublereal *ayb, 
+	doublecomplex *dy, doublecomplex *y_tail__, doublereal *rcond, 
+	integer *ithresh, doublereal *rthresh, doublereal *dz_ub__, logical *
+	ignore_cwise__, integer *info);
+
+/* Subroutine */ int zla_heamv__(integer *uplo, integer *n, doublereal *alpha,
+	 doublecomplex *a, integer *lda, doublecomplex *x, integer *incx, 
+	doublereal *beta, doublereal *y, integer *incy);
+
+doublereal zla_hercond_c__(char *uplo, integer *n, doublecomplex *a, integer *
+	lda, doublecomplex *af, integer *ldaf, integer *ipiv, doublereal *c__,
+	 logical *capply, integer *info, doublecomplex *work, doublereal *
+	rwork, ftnlen uplo_len);
+
+doublereal zla_hercond_x__(char *uplo, integer *n, doublecomplex *a, integer *
+	lda, doublecomplex *af, integer *ldaf, integer *ipiv, doublecomplex *
+	x, integer *info, doublecomplex *work, doublereal *rwork, ftnlen 
+	uplo_len);
+
+/* Subroutine */ int zla_herfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, doublecomplex *a, integer *lda, 
+	doublecomplex *af, integer *ldaf, integer *ipiv, logical *colequ, 
+	doublereal *c__, doublecomplex *b, integer *ldb, doublecomplex *y, 
+	integer *ldy, doublereal *berr_out__, integer *n_norms__, doublereal *
+	errs_n__, doublereal *errs_c__, doublecomplex *res, doublereal *ayb, 
+	doublecomplex *dy, doublecomplex *y_tail__, doublereal *rcond, 
+	integer *ithresh, doublereal *rthresh, doublereal *dz_ub__, logical *
+	ignore_cwise__, integer *info, ftnlen uplo_len);
+
+doublereal zla_herpvgrw__(char *uplo, integer *n, integer *info, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublereal *work, ftnlen uplo_len);
+
+/* Subroutine */ int zla_lin_berr__(integer *n, integer *nz, integer *nrhs, 
+	doublecomplex *res, doublereal *ayb, doublereal *berr);
+
+doublereal zla_porcond_c__(char *uplo, integer *n, doublecomplex *a, integer *
+	lda, doublecomplex *af, integer *ldaf, doublereal *c__, logical *
+	capply, integer *info, doublecomplex *work, doublereal *rwork, ftnlen 
+	uplo_len);
+
+doublereal zla_porcond_x__(char *uplo, integer *n, doublecomplex *a, integer *
+	lda, doublecomplex *af, integer *ldaf, doublecomplex *x, integer *
+	info, doublecomplex *work, doublereal *rwork, ftnlen uplo_len);
+
+/* Subroutine */ int zla_porfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, doublecomplex *a, integer *lda, 
+	doublecomplex *af, integer *ldaf, logical *colequ, doublereal *c__, 
+	doublecomplex *b, integer *ldb, doublecomplex *y, integer *ldy, 
+	doublereal *berr_out__, integer *n_norms__, doublereal *errs_n__, 
+	doublereal *errs_c__, doublecomplex *res, doublereal *ayb, 
+	doublecomplex *dy, doublecomplex *y_tail__, doublereal *rcond, 
+	integer *ithresh, doublereal *rthresh, doublereal *dz_ub__, logical *
+	ignore_cwise__, integer *info, ftnlen uplo_len);
+
+doublereal zla_porpvgrw__(char *uplo, integer *ncols, doublecomplex *a, 
+	integer *lda, doublecomplex *af, integer *ldaf, doublereal *work, 
+	ftnlen uplo_len);
+
+doublereal zla_rpvgrw__(integer *n, integer *ncols, doublecomplex *a, integer 
+	*lda, doublecomplex *af, integer *ldaf);
+
+/* Subroutine */ int zla_syamv__(integer *uplo, integer *n, doublereal *alpha,
+	 doublecomplex *a, integer *lda, doublecomplex *x, integer *incx, 
+	doublereal *beta, doublereal *y, integer *incy);
+
+doublereal zla_syrcond_c__(char *uplo, integer *n, doublecomplex *a, integer *
+	lda, doublecomplex *af, integer *ldaf, integer *ipiv, doublereal *c__,
+	 logical *capply, integer *info, doublecomplex *work, doublereal *
+	rwork, ftnlen uplo_len);
+
+doublereal zla_syrcond_x__(char *uplo, integer *n, doublecomplex *a, integer *
+	lda, doublecomplex *af, integer *ldaf, integer *ipiv, doublecomplex *
+	x, integer *info, doublecomplex *work, doublereal *rwork, ftnlen 
+	uplo_len);
+
+/* Subroutine */ int zla_syrfsx_extended__(integer *prec_type__, char *uplo, 
+	integer *n, integer *nrhs, doublecomplex *a, integer *lda, 
+	doublecomplex *af, integer *ldaf, integer *ipiv, logical *colequ, 
+	doublereal *c__, doublecomplex *b, integer *ldb, doublecomplex *y, 
+	integer *ldy, doublereal *berr_out__, integer *n_norms__, doublereal *
+	errs_n__, doublereal *errs_c__, doublecomplex *res, doublereal *ayb, 
+	doublecomplex *dy, doublecomplex *y_tail__, doublereal *rcond, 
+	integer *ithresh, doublereal *rthresh, doublereal *dz_ub__, logical *
+	ignore_cwise__, integer *info, ftnlen uplo_len);
+
+doublereal zla_syrpvgrw__(char *uplo, integer *n, integer *info, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublereal *work, ftnlen uplo_len);
+
+/* Subroutine */ int zla_wwaddw__(integer *n, doublecomplex *x, doublecomplex 
+	*y, doublecomplex *w);
+
+/* Subroutine */ int zlabrd_(integer *m, integer *n, integer *nb, 
+	doublecomplex *a, integer *lda, doublereal *d__, doublereal *e, 
+	doublecomplex *tauq, doublecomplex *taup, doublecomplex *x, integer *
+	ldx, doublecomplex *y, integer *ldy);
+
+/* Subroutine */ int zlacgv_(integer *n, doublecomplex *x, integer *incx);
+
+/* Subroutine */ int zlacn2_(integer *n, doublecomplex *v, doublecomplex *x, 
+	doublereal *est, integer *kase, integer *isave);
+
+/* Subroutine */ int zlacon_(integer *n, doublecomplex *v, doublecomplex *x, 
+	doublereal *est, integer *kase);
+
+/* Subroutine */ int zlacp2_(char *uplo, integer *m, integer *n, doublereal *
+	a, integer *lda, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zlacpy_(char *uplo, integer *m, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zlacrm_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *b, integer *ldb, doublecomplex *c__, 
+	integer *ldc, doublereal *rwork);
+
+/* Subroutine */ int zlacrt_(integer *n, doublecomplex *cx, integer *incx, 
+	doublecomplex *cy, integer *incy, doublecomplex *c__, doublecomplex *
+	s);
+
+/* Double Complex */ VOID zladiv_(doublecomplex * ret_val, doublecomplex *x, 
+	doublecomplex *y);
+
+/* Subroutine */ int zlaed0_(integer *qsiz, integer *n, doublereal *d__, 
+	doublereal *e, doublecomplex *q, integer *ldq, doublecomplex *qstore, 
+	integer *ldqs, doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zlaed7_(integer *n, integer *cutpnt, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, doublereal *d__, 
+	doublecomplex *q, integer *ldq, doublereal *rho, integer *indxq, 
+	doublereal *qstore, integer *qptr, integer *prmptr, integer *perm, 
+	integer *givptr, integer *givcol, doublereal *givnum, doublecomplex *
+	work, doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zlaed8_(integer *k, integer *n, integer *qsiz, 
+	doublecomplex *q, integer *ldq, doublereal *d__, doublereal *rho, 
+	integer *cutpnt, doublereal *z__, doublereal *dlamda, doublecomplex *
+	q2, integer *ldq2, doublereal *w, integer *indxp, integer *indx, 
+	integer *indxq, integer *perm, integer *givptr, integer *givcol, 
+	doublereal *givnum, integer *info);
+
+/* Subroutine */ int zlaein_(logical *rightv, logical *noinit, integer *n, 
+	doublecomplex *h__, integer *ldh, doublecomplex *w, doublecomplex *v, 
+	doublecomplex *b, integer *ldb, doublereal *rwork, doublereal *eps3, 
+	doublereal *smlnum, integer *info);
+
+/* Subroutine */ int zlaesy_(doublecomplex *a, doublecomplex *b, 
+	doublecomplex *c__, doublecomplex *rt1, doublecomplex *rt2, 
+	doublecomplex *evscal, doublecomplex *cs1, doublecomplex *sn1);
+
+/* Subroutine */ int zlaev2_(doublecomplex *a, doublecomplex *b, 
+	doublecomplex *c__, doublereal *rt1, doublereal *rt2, doublereal *cs1, 
+	 doublecomplex *sn1);
+
+/* Subroutine */ int zlag2c_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, complex *sa, integer *ldsa, integer *info);
+
+/* Subroutine */ int zlags2_(logical *upper, doublereal *a1, doublecomplex *
+	a2, doublereal *a3, doublereal *b1, doublecomplex *b2, doublereal *b3, 
+	 doublereal *csu, doublecomplex *snu, doublereal *csv, doublecomplex *
+	snv, doublereal *csq, doublecomplex *snq);
+
+/* Subroutine */ int zlagtm_(char *trans, integer *n, integer *nrhs, 
+	doublereal *alpha, doublecomplex *dl, doublecomplex *d__, 
+	doublecomplex *du, doublecomplex *x, integer *ldx, doublereal *beta, 
+	doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zlahef_(char *uplo, integer *n, integer *nb, integer *kb, 
+	 doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *w, 
+	integer *ldw, integer *info);
+
+/* Subroutine */ int zlahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *h__, integer *ldh, 
+	doublecomplex *w, integer *iloz, integer *ihiz, doublecomplex *z__, 
+	integer *ldz, integer *info);
+
+/* Subroutine */ int zlahr2_(integer *n, integer *k, integer *nb, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *t, 
+	integer *ldt, doublecomplex *y, integer *ldy);
+
+/* Subroutine */ int zlahrd_(integer *n, integer *k, integer *nb, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *t, 
+	integer *ldt, doublecomplex *y, integer *ldy);
+
+/* Subroutine */ int zlaic1_(integer *job, integer *j, doublecomplex *x, 
+	doublereal *sest, doublecomplex *w, doublecomplex *gamma, doublereal *
+	sestpr, doublecomplex *s, doublecomplex *c__);
+
+/* Subroutine */ int zlals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, doublecomplex *b, integer *ldb, 
+	doublecomplex *bx, integer *ldbx, integer *perm, integer *givptr, 
+	integer *givcol, integer *ldgcol, doublereal *givnum, integer *ldgnum, 
+	 doublereal *poles, doublereal *difl, doublereal *difr, doublereal *
+	z__, integer *k, doublereal *c__, doublereal *s, doublereal *rwork, 
+	integer *info);
+
+/* Subroutine */ int zlalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, doublecomplex *b, integer *ldb, doublecomplex *bx, 
+	integer *ldbx, doublereal *u, integer *ldu, doublereal *vt, integer *
+	k, doublereal *difl, doublereal *difr, doublereal *z__, doublereal *
+	poles, integer *givptr, integer *givcol, integer *ldgcol, integer *
+	perm, doublereal *givnum, doublereal *c__, doublereal *s, doublereal *
+	rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zlalsd_(char *uplo, integer *smlsiz, integer *n, integer 
+	*nrhs, doublereal *d__, doublereal *e, doublecomplex *b, integer *ldb, 
+	 doublereal *rcond, integer *rank, doublecomplex *work, doublereal *
+	rwork, integer *iwork, integer *info);
+
+doublereal zlangb_(char *norm, integer *n, integer *kl, integer *ku, 
+	doublecomplex *ab, integer *ldab, doublereal *work);
+
+doublereal zlange_(char *norm, integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *work);
+
+doublereal zlangt_(char *norm, integer *n, doublecomplex *dl, doublecomplex *
+	d__, doublecomplex *du);
+
+doublereal zlanhb_(char *norm, char *uplo, integer *n, integer *k, 
+	doublecomplex *ab, integer *ldab, doublereal *work);
+
+doublereal zlanhe_(char *norm, char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *work);
+
+doublereal zlanhf_(char *norm, char *transr, char *uplo, integer *n, 
+	doublecomplex *a, doublereal *work);
+
+doublereal zlanhp_(char *norm, char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *work);
+
+doublereal zlanhs_(char *norm, integer *n, doublecomplex *a, integer *lda, 
+	doublereal *work);
+
+doublereal zlanht_(char *norm, integer *n, doublereal *d__, doublecomplex *e);
+
+doublereal zlansb_(char *norm, char *uplo, integer *n, integer *k, 
+	doublecomplex *ab, integer *ldab, doublereal *work);
+
+doublereal zlansp_(char *norm, char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *work);
+
+doublereal zlansy_(char *norm, char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *work);
+
+doublereal zlantb_(char *norm, char *uplo, char *diag, integer *n, integer *k, 
+	 doublecomplex *ab, integer *ldab, doublereal *work);
+
+doublereal zlantp_(char *norm, char *uplo, char *diag, integer *n, 
+	doublecomplex *ap, doublereal *work);
+
+doublereal zlantr_(char *norm, char *uplo, char *diag, integer *m, integer *n, 
+	 doublecomplex *a, integer *lda, doublereal *work);
+
+/* Subroutine */ int zlapll_(integer *n, doublecomplex *x, integer *incx, 
+	doublecomplex *y, integer *incy, doublereal *ssmin);
+
+/* Subroutine */ int zlapmt_(logical *forwrd, integer *m, integer *n, 
+	doublecomplex *x, integer *ldx, integer *k);
+
+/* Subroutine */ int zlaqgb_(integer *m, integer *n, integer *kl, integer *ku, 
+	 doublecomplex *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqge_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, 
+	doublereal *colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqhb_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond, 
+	doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqhe_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *s, doublereal *scond, doublereal *amax, 
+	char *equed);
+
+/* Subroutine */ int zlaqhp_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqp2_(integer *m, integer *n, integer *offset, 
+	doublecomplex *a, integer *lda, integer *jpvt, doublecomplex *tau, 
+	doublereal *vn1, doublereal *vn2, doublecomplex *work);
+
+/* Subroutine */ int zlaqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, doublecomplex *a, integer *lda, integer *jpvt, 
+	doublecomplex *tau, doublereal *vn1, doublereal *vn2, doublecomplex *
+	auxv, doublecomplex *f, integer *ldf);
+
+/* Subroutine */ int zlaqr0_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *h__, integer *ldh, 
+	doublecomplex *w, integer *iloz, integer *ihiz, doublecomplex *z__, 
+	integer *ldz, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zlaqr1_(integer *n, doublecomplex *h__, integer *ldh, 
+	doublecomplex *s1, doublecomplex *s2, doublecomplex *v);
+
+/* Subroutine */ int zlaqr2_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, doublecomplex *h__, 
+	integer *ldh, integer *iloz, integer *ihiz, doublecomplex *z__, 
+	integer *ldz, integer *ns, integer *nd, doublecomplex *sh, 
+	doublecomplex *v, integer *ldv, integer *nh, doublecomplex *t, 
+	integer *ldt, integer *nv, doublecomplex *wv, integer *ldwv, 
+	doublecomplex *work, integer *lwork);
+
+/* Subroutine */ int zlaqr3_(logical *wantt, logical *wantz, integer *n, 
+	integer *ktop, integer *kbot, integer *nw, doublecomplex *h__, 
+	integer *ldh, integer *iloz, integer *ihiz, doublecomplex *z__, 
+	integer *ldz, integer *ns, integer *nd, doublecomplex *sh, 
+	doublecomplex *v, integer *ldv, integer *nh, doublecomplex *t, 
+	integer *ldt, integer *nv, doublecomplex *wv, integer *ldwv, 
+	doublecomplex *work, integer *lwork);
+
+/* Subroutine */ int zlaqr4_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *h__, integer *ldh, 
+	doublecomplex *w, integer *iloz, integer *ihiz, doublecomplex *z__, 
+	integer *ldz, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zlaqr5_(logical *wantt, logical *wantz, integer *kacc22, 
+	integer *n, integer *ktop, integer *kbot, integer *nshfts, 
+	doublecomplex *s, doublecomplex *h__, integer *ldh, integer *iloz, 
+	integer *ihiz, doublecomplex *z__, integer *ldz, doublecomplex *v, 
+	integer *ldv, doublecomplex *u, integer *ldu, integer *nv, 
+	doublecomplex *wv, integer *ldwv, integer *nh, doublecomplex *wh, 
+	integer *ldwh);
+
+/* Subroutine */ int zlaqsb_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond, 
+	doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqsp_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqsy_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *s, doublereal *scond, doublereal *amax, 
+	char *equed);
+
+/* Subroutine */ int zlar1v_(integer *n, integer *b1, integer *bn, doublereal 
+	*lambda, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
+	lld, doublereal *pivmin, doublereal *gaptol, doublecomplex *z__, 
+	logical *wantnc, integer *negcnt, doublereal *ztz, doublereal *mingma, 
+	 integer *r__, integer *isuppz, doublereal *nrminv, doublereal *resid, 
+	 doublereal *rqcorr, doublereal *work);
+
+/* Subroutine */ int zlar2v_(integer *n, doublecomplex *x, doublecomplex *y, 
+	doublecomplex *z__, integer *incx, doublereal *c__, doublecomplex *s, 
+	integer *incc);
+
+/* Subroutine */ int zlarcm_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublecomplex *b, integer *ldb, doublecomplex *c__, integer *ldc, 
+	 doublereal *rwork);
+
+/* Subroutine */ int zlarf_(char *side, integer *m, integer *n, doublecomplex 
+	*v, integer *incv, doublecomplex *tau, doublecomplex *c__, integer *
+	ldc, doublecomplex *work);
+
+/* Subroutine */ int zlarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, doublecomplex *v, integer 
+	*ldv, doublecomplex *t, integer *ldt, doublecomplex *c__, integer *
+	ldc, doublecomplex *work, integer *ldwork);
+
+/* Subroutine */ int zlarfg_(integer *n, doublecomplex *alpha, doublecomplex *
+	x, integer *incx, doublecomplex *tau);
+
+/* Subroutine */ int zlarfp_(integer *n, doublecomplex *alpha, doublecomplex *
+	x, integer *incx, doublecomplex *tau);
+
+/* Subroutine */ int zlarft_(char *direct, char *storev, integer *n, integer *
+	k, doublecomplex *v, integer *ldv, doublecomplex *tau, doublecomplex *
+	t, integer *ldt);
+
+/* Subroutine */ int zlarfx_(char *side, integer *m, integer *n, 
+	doublecomplex *v, doublecomplex *tau, doublecomplex *c__, integer *
+	ldc, doublecomplex *work);
+
+/* Subroutine */ int zlargv_(integer *n, doublecomplex *x, integer *incx, 
+	doublecomplex *y, integer *incy, doublereal *c__, integer *incc);
+
+/* Subroutine */ int zlarnv_(integer *idist, integer *iseed, integer *n, 
+	doublecomplex *x);
+
+/* Subroutine */ int zlarrv_(integer *n, doublereal *vl, doublereal *vu, 
+	doublereal *d__, doublereal *l, doublereal *pivmin, integer *isplit, 
+	integer *m, integer *dol, integer *dou, doublereal *minrgp, 
+	doublereal *rtol1, doublereal *rtol2, doublereal *w, doublereal *werr, 
+	 doublereal *wgap, integer *iblock, integer *indexw, doublereal *gers, 
+	 doublecomplex *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *iwork, integer *info);
+
+/* Subroutine */ int zlarscl2_(integer *m, integer *n, doublereal *d__, 
+	doublecomplex *x, integer *ldx);
+
+/* Subroutine */ int zlartg_(doublecomplex *f, doublecomplex *g, doublereal *
+	cs, doublecomplex *sn, doublecomplex *r__);
+
+/* Subroutine */ int zlartv_(integer *n, doublecomplex *x, integer *incx, 
+	doublecomplex *y, integer *incy, doublereal *c__, doublecomplex *s, 
+	integer *incc);
+
+/* Subroutine */ int zlarz_(char *side, integer *m, integer *n, integer *l, 
+	doublecomplex *v, integer *incv, doublecomplex *tau, doublecomplex *
+	c__, integer *ldc, doublecomplex *work);
+
+/* Subroutine */ int zlarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, doublecomplex 
+	*v, integer *ldv, doublecomplex *t, integer *ldt, doublecomplex *c__, 
+	integer *ldc, doublecomplex *work, integer *ldwork);
+
+/* Subroutine */ int zlarzt_(char *direct, char *storev, integer *n, integer *
+	k, doublecomplex *v, integer *ldv, doublecomplex *tau, doublecomplex *
+	t, integer *ldt);
+
+/* Subroutine */ int zlascl_(char *type__, integer *kl, integer *ku, 
+	doublereal *cfrom, doublereal *cto, integer *m, integer *n, 
+	doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int zlascl2_(integer *m, integer *n, doublereal *d__, 
+	doublecomplex *x, integer *ldx);
+
+/* Subroutine */ int zlaset_(char *uplo, integer *m, integer *n, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *a, integer *
+	lda);
+
+/* Subroutine */ int zlasr_(char *side, char *pivot, char *direct, integer *m, 
+	 integer *n, doublereal *c__, doublereal *s, doublecomplex *a, 
+	integer *lda);
+
+/* Subroutine */ int zlassq_(integer *n, doublecomplex *x, integer *incx, 
+	doublereal *scale, doublereal *sumsq);
+
+/* Subroutine */ int zlaswp_(integer *n, doublecomplex *a, integer *lda, 
+	integer *k1, integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int zlasyf_(char *uplo, integer *n, integer *nb, integer *kb, 
+	 doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *w, 
+	integer *ldw, integer *info);
+
+/* Subroutine */ int zlat2c_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, complex *sa, integer *ldsa, integer *info);
+
+/* Subroutine */ int zlatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, doublecomplex *ab, integer *ldab, 
+	doublecomplex *x, doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int zlatdf_(integer *ijob, integer *n, doublecomplex *z__, 
+	integer *ldz, doublecomplex *rhs, doublereal *rdsum, doublereal *
+	rdscal, integer *ipiv, integer *jpiv);
+
+/* Subroutine */ int zlatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublecomplex *ap, doublecomplex *x, doublereal *
+	scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int zlatrd_(char *uplo, integer *n, integer *nb, 
+	doublecomplex *a, integer *lda, doublereal *e, doublecomplex *tau, 
+	doublecomplex *w, integer *ldw);
+
+/* Subroutine */ int zlatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublecomplex *a, integer *lda, doublecomplex *x, 
+	doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int zlatrz_(integer *m, integer *n, integer *l, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work);
+
+/* Subroutine */ int zlatzm_(char *side, integer *m, integer *n, 
+	doublecomplex *v, integer *incv, doublecomplex *tau, doublecomplex *
+	c1, doublecomplex *c2, integer *ldc, doublecomplex *work);
+
+/* Subroutine */ int zlauu2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int zlauum_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int zpbcon_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *anorm, doublereal *
+	rcond, doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpbequ_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond, 
+	doublereal *amax, integer *info);
+
+/* Subroutine */ int zpbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublecomplex *ab, integer *ldab, doublecomplex *afb, integer *
+	ldafb, doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	 doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+
+/* Subroutine */ int zpbstf_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, integer *info);
+
+/* Subroutine */ int zpbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublecomplex *ab, integer *ldab, doublecomplex *b, integer *
+	ldb, integer *info);
+
+/* Subroutine */ int zpbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, doublecomplex *ab, integer *ldab, doublecomplex *afb, 
+	integer *ldafb, char *equed, doublereal *s, doublecomplex *b, integer 
+	*ldb, doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *
+	ferr, doublereal *berr, doublecomplex *work, doublereal *rwork, 
+	integer *info);
+
+/* Subroutine */ int zpbtf2_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, integer *info);
+
+/* Subroutine */ int zpbtrf_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, integer *info);
+
+/* Subroutine */ int zpbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublecomplex *ab, integer *ldab, doublecomplex *b, integer *
+	ldb, integer *info);
+
+/* Subroutine */ int zpftrf_(char *transr, char *uplo, integer *n, 
+	doublecomplex *a, integer *info);
+
+/* Subroutine */ int zpftri_(char *transr, char *uplo, integer *n, 
+	doublecomplex *a, integer *info);
+
+/* Subroutine */ int zpftrs_(char *transr, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zpocon_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpoequ_(integer *n, doublecomplex *a, integer *lda, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int zpoequb_(integer *n, doublecomplex *a, integer *lda, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int zporfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+
+/* Subroutine */ int zporfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, doublereal *s, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	 integer *ldx, doublereal *rcond, doublereal *berr, integer *
+	n_err_bnds__, doublereal *err_bnds_norm__, doublereal *
+	err_bnds_comp__, integer *nparams, doublereal *params, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zposv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, char *equed, doublereal *s, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zposvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, char *equed, doublereal *s, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *rpvgrw, 
+	 doublereal *berr, integer *n_err_bnds__, doublereal *err_bnds_norm__, 
+	 doublereal *err_bnds_comp__, integer *nparams, doublereal *params, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpotf2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int zpotrf_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int zpotri_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+
+/* Subroutine */ int zpotrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zppcon_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *anorm, doublereal *rcond, doublecomplex *work, doublereal 
+	*rwork, integer *info);
+
+/* Subroutine */ int zppequ_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int zpprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *afp, doublecomplex *b, integer *ldb, 
+	 doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zppsv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *ap, doublecomplex *afp, char *equed, doublereal *
+	s, doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpptrf_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *info);
+
+/* Subroutine */ int zpptri_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *info);
+
+/* Subroutine */ int zpptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zpstf2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *piv, integer *rank, doublereal *tol, 
+	doublereal *work, integer *info);
+
+/* Subroutine */ int zpstrf_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *piv, integer *rank, doublereal *tol, 
+	doublereal *work, integer *info);
+
+/* Subroutine */ int zptcon_(integer *n, doublereal *d__, doublecomplex *e, 
+	doublereal *anorm, doublereal *rcond, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zpteqr_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublecomplex *z__, integer *ldz, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int zptrfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublereal *df, doublecomplex *ef, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+
+/* Subroutine */ int zptsv_(integer *n, integer *nrhs, doublereal *d__, 
+	doublecomplex *e, doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zptsvx_(char *fact, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublereal *df, doublecomplex *ef, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpttrf_(integer *n, doublereal *d__, doublecomplex *e, 
+	integer *info);
+
+/* Subroutine */ int zpttrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zptts2_(integer *iuplo, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zrot_(integer *n, doublecomplex *cx, integer *incx, 
+	doublecomplex *cy, integer *incy, doublereal *c__, doublecomplex *s);
+
+/* Subroutine */ int zspcon_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zspmv_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *ap, doublecomplex *x, integer *incx, doublecomplex *
+	beta, doublecomplex *y, integer *incy);
+
+/* Subroutine */ int zspr_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *ap);
+
+/* Subroutine */ int zsprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *afp, integer *ipiv, doublecomplex *
+	b, integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int zspsv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *ap, doublecomplex *afp, integer *ipiv, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zsptrf_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, integer *info);
+
+/* Subroutine */ int zsptri_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zsptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int zstedc_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublecomplex *z__, integer *ldz, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *lrwork, integer *iwork, 
+	integer *liwork, integer *info);
+
+/* Subroutine */ int zstegr_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublecomplex *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zstein_(integer *n, doublereal *d__, doublereal *e, 
+	integer *m, doublereal *w, integer *iblock, integer *isplit, 
+	doublecomplex *z__, integer *ldz, doublereal *work, integer *iwork, 
+	integer *ifail, integer *info);
+
+/* Subroutine */ int zstemr_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, integer *m, doublereal *w, doublecomplex *z__, integer *
+	ldz, integer *nzc, integer *isuppz, logical *tryrac, doublereal *work, 
+	 integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zsteqr_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublecomplex *z__, integer *ldz, doublereal *work, 
+	integer *info);
+
+/* Subroutine */ int zsycon_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublereal *anorm, doublereal *rcond, 
+	doublecomplex *work, integer *info);
+
+/* Subroutine */ int zsyequb_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *s, doublereal *scond, doublereal *amax, 
+	doublecomplex *work, integer *info);
+
+/* Subroutine */ int zsymv_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *a, integer *lda, doublecomplex *x, integer *incx, 
+	doublecomplex *beta, doublecomplex *y, integer *incy);
+
+/* Subroutine */ int zsyr_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *a, integer *lda);
+
+/* Subroutine */ int zsyrfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work, 
+	 doublereal *rwork, integer *info);
+
+/* Subroutine */ int zsyrfsx_(char *uplo, char *equed, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, doublereal *s, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *berr, 
+	integer *n_err_bnds__, doublereal *err_bnds_norm__, doublereal *
+	err_bnds_comp__, integer *nparams, doublereal *params, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zsysv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zsysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	 integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zsysvxx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, char *equed, doublereal *s, doublecomplex *b, 
+	integer *ldb, doublecomplex *x, integer *ldx, doublereal *rcond, 
+	doublereal *rpvgrw, doublereal *berr, integer *n_err_bnds__, 
+	doublereal *err_bnds_norm__, doublereal *err_bnds_comp__, integer *
+	nparams, doublereal *params, doublecomplex *work, doublereal *rwork, 
+	integer *info);
+
+/* Subroutine */ int zsytf2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zsytrf_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *lwork, 
+	integer *info);
+
+/* Subroutine */ int zsytri_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zsytrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, integer *info);
+
+/* Subroutine */ int ztbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, doublecomplex *ab, integer *ldab, doublereal *rcond, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+
+/* Subroutine */ int ztbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ztfsm_(char *transr, char *side, char *uplo, char *trans, 
+	 char *diag, integer *m, integer *n, doublecomplex *alpha, 
+	doublecomplex *a, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int ztftri_(char *transr, char *uplo, char *diag, integer *n, 
+	 doublecomplex *a, integer *info);
+
+/* Subroutine */ int ztfttp_(char *transr, char *uplo, integer *n, 
+	doublecomplex *arf, doublecomplex *ap, integer *info);
+
+/* Subroutine */ int ztfttr_(char *transr, char *uplo, integer *n, 
+	doublecomplex *arf, doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int ztgevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublecomplex *s, integer *lds, doublecomplex *p, integer 
+	*ldp, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *
+	ldvr, integer *mm, integer *m, doublecomplex *work, doublereal *rwork, 
+	 integer *info);
+
+/* Subroutine */ int ztgex2_(logical *wantq, logical *wantz, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *q, integer *ldq, doublecomplex *z__, integer *ldz, 
+	integer *j1, integer *info);
+
+/* Subroutine */ int ztgexc_(logical *wantq, logical *wantz, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *q, integer *ldq, doublecomplex *z__, integer *ldz, 
+	integer *ifst, integer *ilst, integer *info);
+
+/* Subroutine */ int ztgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, doublecomplex *a, integer *lda, 
+	doublecomplex *b, integer *ldb, doublecomplex *alpha, doublecomplex *
+	beta, doublecomplex *q, integer *ldq, doublecomplex *z__, integer *
+	ldz, integer *m, doublereal *pl, doublereal *pr, doublereal *dif, 
+	doublecomplex *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+
+/* Subroutine */ int ztgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, doublecomplex *a, 
+	integer *lda, doublecomplex *b, integer *ldb, doublereal *tola, 
+	doublereal *tolb, doublereal *alpha, doublereal *beta, doublecomplex *
+	u, integer *ldu, doublecomplex *v, integer *ldv, doublecomplex *q, 
+	integer *ldq, doublecomplex *work, integer *ncycle, integer *info);
+
+/* Subroutine */ int ztgsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublecomplex *a, integer *lda, doublecomplex *b, integer 
+	*ldb, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *
+	ldvr, doublereal *s, doublereal *dif, integer *mm, integer *m, 
+	doublecomplex *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int ztgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *c__, integer *ldc, doublecomplex *d__, integer *ldd, 
+	doublecomplex *e, integer *lde, doublecomplex *f, integer *ldf, 
+	doublereal *scale, doublereal *rdsum, doublereal *rdscal, integer *
+	info);
+
+/* Subroutine */ int ztgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *c__, integer *ldc, doublecomplex *d__, integer *ldd, 
+	doublecomplex *e, integer *lde, doublecomplex *f, integer *ldf, 
+	doublereal *scale, doublereal *dif, doublecomplex *work, integer *
+	lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int ztpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublecomplex *ap, doublereal *rcond, doublecomplex *work, doublereal 
+	*rwork, integer *info);
+
+/* Subroutine */ int ztprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *ap, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztptri_(char *uplo, char *diag, integer *n, 
+	doublecomplex *ap, integer *info);
+
+/* Subroutine */ int ztptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *ap, doublecomplex *b, integer *ldb, 
+	integer *info);
+
+/* Subroutine */ int ztpttf_(char *transr, char *uplo, integer *n, 
+	doublecomplex *ap, doublecomplex *arf, integer *info);
+
+/* Subroutine */ int ztpttr_(char *uplo, integer *n, doublecomplex *ap, 
+	doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int ztrcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *rcond, doublecomplex *
+	work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztrevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublecomplex *t, integer *ldt, doublecomplex *vl, 
+	integer *ldvl, doublecomplex *vr, integer *ldvr, integer *mm, integer 
+	*m, doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztrexc_(char *compq, integer *n, doublecomplex *t, 
+	integer *ldt, doublecomplex *q, integer *ldq, integer *ifst, integer *
+	ilst, integer *info);
+
+/* Subroutine */ int ztrrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+
+/* Subroutine */ int ztrsen_(char *job, char *compq, logical *select, integer 
+	*n, doublecomplex *t, integer *ldt, doublecomplex *q, integer *ldq, 
+	doublecomplex *w, integer *m, doublereal *s, doublereal *sep, 
+	doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int ztrsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublecomplex *t, integer *ldt, doublecomplex *vl, 
+	integer *ldvl, doublecomplex *vr, integer *ldvr, doublereal *s, 
+	doublereal *sep, integer *mm, integer *m, doublecomplex *work, 
+	integer *ldwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztrsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *c__, integer *ldc, doublereal *scale, 
+	integer *info);
+
+/* Subroutine */ int ztrti2_(char *uplo, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int ztrtri_(char *uplo, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int ztrtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, integer *info);
+
+/* Subroutine */ int ztrttf_(char *transr, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *arf, integer *info);
+
+/* Subroutine */ int ztrttp_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *ap, integer *info);
+
+/* Subroutine */ int ztzrqf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, integer *info);
+
+/* Subroutine */ int ztzrzf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zung2l_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zung2r_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zungbr_(char *vect, integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zunghr_(integer *n, integer *ilo, integer *ihi, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungl2_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zunglq_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungql_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungqr_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungr2_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zungrq_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungtr_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zunm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunmbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, doublecomplex *a, integer *lda, doublecomplex 
+	*tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int zunmhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *a, integer *lda, 
+	doublecomplex *tau, doublecomplex *c__, integer *ldc, doublecomplex *
+	work, integer *lwork, integer *info);
+
+/* Subroutine */ int zunml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunmlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zunmql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zunmqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zunmr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunmr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublecomplex *a, integer *lda, doublecomplex 
+	*tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+	info);
+
+/* Subroutine */ int zunmrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zunmrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublecomplex *a, integer *lda, doublecomplex 
+	*tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+	lwork, integer *info);
+
+/* Subroutine */ int zunmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork, 
+	 integer *info);
+
+/* Subroutine */ int zupgtr_(char *uplo, integer *n, doublecomplex *ap, 
+	doublecomplex *tau, doublecomplex *q, integer *ldq, doublecomplex *
+	work, integer *info);
+
+/* Subroutine */ int zupmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublecomplex *ap, doublecomplex *tau, doublecomplex *c__, 
+	 integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int dlamc1_(integer *beta, integer *t, logical *rnd, logical 
+	*ieee1);
+
+doublereal dsecnd_();
+
+/* Subroutine */ int ilaver_(integer *vers_major__, integer *vers_minor__, 
+	integer *vers_patch__);
+
+logical lsame_(char *ca, char *cb);
+
+doublereal second_();
+
+doublereal slamch_(char *cmach);
+
+/* Subroutine */ int slamc1_(integer *beta, integer *t, logical *rnd, logical 
+	*ieee1);
+
+/* Subroutine */ int slamc2_(integer *beta, integer *t, logical *rnd, real *
+		    eps, integer *emin, real *rmin, integer *emax, real *rmax);
+
+doublereal slamc3_(real *a, real *b);
+
+/* Subroutine */ int slamc4_(integer *emin, real *start, integer *base);
+
+/* Subroutine */ int slamc5_(integer *beta, integer *p, integer *emin,
+		    logical *ieee, integer *emax, real *rmax);
+
+
+doublereal dlamch_(char *cmach);
+
+/* Subroutine */ int dlamc1_(integer *beta, integer *t, logical *rnd, logical
+		    *ieee1);
+
+/* Subroutine */ int dlamc2_(integer *beta, integer *t, logical *rnd,
+		    doublereal *eps, integer *emin, doublereal *rmin, integer *emax,
+			    doublereal *rmax);
+
+doublereal dlamc3_(doublereal *a, doublereal *b);
+
+/* Subroutine */ int dlamc4_(integer *emin, doublereal *start, integer *base);
+
+/* Subroutine */ int dlamc5_(integer *beta, integer *p, integer *emin,
+		    logical *ieee, integer *emax, doublereal *rmax);
+
+integer ilaenv_(integer *ispec, char *name__, char *opts, integer *n1, 
+	integer *n2, integer *n3, integer *n4);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __CLAPACK_H */
diff --git a/examples++-load/cmaes-VarIneq.edp b/examples++-load/cmaes-VarIneq.edp
new file mode 100644
index 0000000..b94d749
--- /dev/null
+++ b/examples++-load/cmaes-VarIneq.edp
@@ -0,0 +1,123 @@
+load "ff-cmaes"
+
+
+int NN = 7;
+mesh Th = square(NN,NN);
+func f1=1.;
+func f2=-1.;
+func g1=0.;
+func g2=0.1;
+int iter=0;
+int nadapt=1;
+real starttol=1e-10,bctol=6.e-12;
+fespace Vh(Th,P1);
+Vh ou1,ou2;
+real pena=1000;
+
+
+for(int al=0;al<nadapt;++al)
+{
+	
+varf BVF(v,w) = int2d(Th)(0.5*dx(v)*dx(w) + 0.5*dy(v)*dy(w));
+varf LVF1(v,w) = int2d(Th)(f1*w);
+varf LVF2(v,w) = int2d(Th)(f2*w);
+matrix A =  BVF(Vh,Vh);
+real[int] b1 = LVF1(0,Vh) , b2 = LVF2(0,Vh); 
+
+varf Vbord(v,w) = on(1,2,3,4,v=1);
+//real[int] bord = Vbord(0,Vh);
+//real[int] in = bord ? 0 : 1;
+Vh In,Bord;
+Bord[] = Vbord(0,Vh,tgv=1);
+In[] = Bord[] ? 0:1;
+Vh gh1=Bord*g1,gh2=Bord*g2;
+
+
+
+//Function which create a vector of the search space type from
+//two finite element functions
+func int FEFToSSP(real[int] &fef1,real[int] &fef2,real[int] &ssp)
+{
+	int kX=0;
+	for(int i=0;i<Vh.ndof;++i)
+	{
+		if(In[][i])
+		{
+			ssp[kX] = fef1[i];
+			ssp[kX+In[].sum] = fef2[i];
+			++kX;
+		}
+	}
+	return 1;
+}
+//Function spliting a vector from the search space and fills
+//two finite element functions with it
+func int SSPToFEF(real[int] &fef1,real[int] &fef2,real[int] &ssp)
+{
+	int kX=0;
+	for(int i=0;i<Vh.ndof;++i)
+	{
+		if(In[][i])
+		{
+			fef1[i] = ssp[kX];
+			fef2[i] = ssp[kX+In[].sum];
+			++kX;
+		}
+		else
+		{
+			fef1[i] = gh1[][i];
+			fef2[i] = gh2[][i];
+		}
+	}
+	return 1;
+}
+
+
+func real IneqC(real[int] &X)
+{
+	real[int] constraints(In[].sum);
+	for(int i=0;i<In[].sum;++i)
+	{
+		constraints[i] = X[i] - X[i+In[].sum];
+		constraints[i] = constraints[i] <= 0 ? 0. : constraints[i];
+	}
+	return constraints.l2;
+}
+
+
+func real J(real[int] &X)
+{
+	Vh u1,u2;
+	SSPToFEF(u1[],u2[],X);
+	iter++;
+	real[int] Au1 = A*u1[], Au2 = A*u2[];
+	Au1 -= b1;
+	Au2 -= b2;
+	real val = u1[]'*Au1 + u2[]'*Au2;
+	val +=  pena * IneqC(X);
+	if(iter%200==199) 
+	plot(u1,u2,nbiso=30,fill=1,dim=3,cmm="adapt level " + al + " - iteration " + iter + " - J = " + val,value=1);
+	return val ;
+}
+
+
+
+real[int] start(2*In[].sum);
+
+if(al==0)
+{
+	start(0:In[].sum-1) = 0.;
+	start(In[].sum:2*In[].sum-1) = 0.1;
+}
+else FEFToSSP(ou1[],ou2[],start);
+
+
+real mini = cmaes(J,start,stopMaxFunEval=10000*(al+1),stopTolX=1.e-3/(10*(al+1)),initialStdDev=(0.025/(pow(100.,al))));
+Vh best1,best2;
+SSPToFEF(best1[],best2[],start);
+
+Th = adaptmesh(Th,best1,best2);
+ou1 = best1;
+ou2 = best2;
+
+}
diff --git a/examples++-load/cmaes-oven.edp b/examples++-load/cmaes-oven.edp
new file mode 100644
index 0000000..36005aa
--- /dev/null
+++ b/examples++-load/cmaes-oven.edp
@@ -0,0 +1,166 @@
+load "ff-cmaes"
+
+int NP=10;			//Control the mesh quality
+func ud=100; 		//Desired temperature in the target zone
+real L=2,l=1.5,R=0.075;//L:oven length, l:oven height, R: resistors radius
+real eps=1e-2,hugeval=1.e30;		//a small value governing collisions and a huge one for something else
+int nbres=6;		//number of resistors (should not be changed) 
+int NPres=NP*(2*pi*R);
+real[int] pr(nbres+2), K(nbres+2); 
+int regi=nbres, rege=nbres+1, lext=1;
+K=1;	K[regi]=10;
+
+macro Grad(u) [dx(u),dy(u)]//EOM
+macro Resistor(i,cx,cy,lab)
+border Res#i(t=0.,2*pi) {x=cx+R*cos(t); y=cy+R*sin(t); label=lab;}//EOM
+real pena = 100;
+func target = 100.;
+
+real[int] Xmin(3*nbres),Xmax(3*nbres);
+for(int i=0;i<nbres;++i)
+{
+	Xmin[3*i] = -hugeval;
+	Xmax[3*i] = hugeval;
+	Xmin[3*i+1] = (i%3)*(L/3) +  R+eps/2;
+	Xmax[3*i+1] = (i%3 + 1)*(L/3) - (R+eps/2);
+	Xmin[3*i+2] = R+eps + (i>2 ? 2*l/3 : 0);
+	Xmax[3*i+2] = (i>2 ? l : l/3) - (R+eps);
+}
+cout << "Xmin: " << Xmin << endl << "Xmax: " << Xmax << endl;
+
+int iter=0;
+func real J(real[int] &X)
+{
+	verbosity=0;
+	real[int] XX=X,diff=X;
+	for(int i=0;i<X.n;++i)
+	{
+		XX[i] = X[i]>Xmin[i] ? X[i] : Xmin[i];
+		XX[i] = XX[i]<Xmax[i] ? XX[i] : Xmax[i];
+	}
+	diff -= XX;
+	real corr = diff.l2;
+	//cout << X << endl << XX << endl << "==>" << corr << endl;
+	
+	border b1(t=0,1){x=L*t; y=0; label=0;}
+	border b2(t=0,1){x=L;   y=l*t; label=0;}
+	border b3(t=0,1){x=L*(1-t); y=l; label=0;}
+	border b4(t=0,1){x=0;   y=l*(1-t); label=0;}
+	Resistor(1,XX[1] ,XX[2] ,1);
+	Resistor(2,XX[4] ,XX[5] ,1);
+	Resistor(3,XX[7] ,XX[8] ,1);
+	Resistor(4,XX[10],XX[11],1);
+	Resistor(5,XX[13],XX[14],1);
+	Resistor(6,XX[16],XX[17],1);
+	border bi1(t=0,2){x=(0.5+t)*L/3; y=l/3; label=1;}
+	border bi2(t=0,1){x=5*L/6; y=(1+t)*l/3; label=1;}
+	border bi3(t=0,2){x=(2.5-t)*L/3; y=2*l/3; label=1;}
+	border bi4(t=0,1){x=L/6; y=(2-t)*l/3; label=1;}
+	mesh Th = buildmesh(
+		 bi1(2*NP*L/3)+bi2(NP*l/3)+bi3(2*NP*L/3)+bi4(NP*l/3)
+		+ Res1(NPres)+Res2(NPres)+Res3(NPres)+Res4(NPres)+Res5(NPres)+Res6(NPres)
+		+ b1(NP*L)+b2(NP*l)+b3(NP*L)+b4(NP*l));
+	//plot(Th,wait=1);
+	
+	fespace Vh(Th,P1);
+	Vh u,v,reg=region;
+	real[int] K(reg[].max+1),pr(reg[].max+1);
+	K=1;
+	K[Th(L/2,l/2).region] = 10;
+	pr=0;
+	for(int i=0;i<nbres;++i) pr(Th(XX[3*i+1],XX[3*i+2]).region) = XX[3*i];
+	//plot(reg,value=1,fill=1,wait=1);
+	
+	solve Chaleur(u,v) = int2d(Th)( (dx(u)*dx(v) + dy(u)*dy(v)) * K[region]) + int1d(Th,0)(u*v) - int2d(Th)(pr[region]*v) ;
+	if(iter %200 == 199)
+	plot(u,fill=1,nbiso=50,wait=0,dim=2);
+	real meanu = int2d(Th,Th(L/2,l/2).region)(u)/int2d(Th,Th(L/2,l/2).region)(1.);
+	real res = int2d(Th,Th(L/2,l/2).region)(square(u-target));
+	cout << "J: iter " << iter++ << "  -  mean=" << meanu << "  -  corr=" << corr << "  -  res=" << res << " ==> " << res+pena*corr << endl;
+	cout << "pos : ";
+	for(int j=0;j<X.n;++j) cout << " " << X[j];
+	cout << endl;
+	return res + pena*corr;
+}
+
+real[int] grad(3*nbres);
+bool plotgrad=1;
+func real[int] dJ(real[int] &X)
+{
+	verbosity=0;
+	real[int] XX=X,diff=X;
+	for(int i=0;i<X.n;++i)
+	{
+		XX[i] = X[i]>Xmin[i] ? X[i] : Xmin[i];
+		XX[i] = XX[i]<Xmax[i] ? XX[i] : Xmax[i];
+	}
+	diff -= XX;
+	real corr = diff.l2;
+	//cout << X << endl << XX << endl << "==>" << corr << endl;
+	
+	border b1(t=0,1){x=L*t; y=0; label=7;}
+	border b2(t=0,1){x=L;   y=l*t; label=7;}
+	border b3(t=0,1){x=L*(1-t); y=l; label=7;}
+	border b4(t=0,1){x=0;   y=l*(1-t); label=7;}
+	Resistor(1,XX[1] ,XX[2] ,0);
+	Resistor(2,XX[4] ,XX[5] ,1);
+	Resistor(3,XX[7] ,XX[8] ,2);
+	Resistor(4,XX[10],XX[11],3);
+	Resistor(5,XX[13],XX[14],4);
+	Resistor(6,XX[16],XX[17],5);
+	border bi1(t=0,2){x=(0.5+t)*L/3; y=l/3; label=6;}
+	border bi2(t=0,1){x=5*L/6; y=(1+t)*l/3; label=6;}
+	border bi3(t=0,2){x=(2.5-t)*L/3; y=2*l/3; label=6;}
+	border bi4(t=0,1){x=L/6; y=(2-t)*l/3; label=6;}
+	mesh Th = buildmesh(
+		 bi1(2*NP*L/3)+bi2(NP*l/3)+bi3(2*NP*L/3)+bi4(NP*l/3)
+		+ Res1(NPres)+Res2(NPres)+Res3(NPres)+Res4(NPres)+Res5(NPres)+Res6(NPres)
+		+ b1(NP*L)+b2(NP*l)+b3(NP*L)+b4(NP*l));
+	//plot(Th,wait=1);
+	
+	fespace Vh(Th,P1);
+	Vh reg=region;
+	real[int] K(reg[].max+1),pr(reg[].max+1);
+	K=1;
+	K[Th(L/2,l/2).region] = 10;
+	pr=0;
+	for(int i=0;i<nbres;++i) pr(Th(XX[3*i+1],XX[3*i+2]).region) = XX[3*i];
+	//plot(reg,value=1,fill=1,wait=1);
+	Vh u,v;
+	solve Chaleur(u,v) = int2d(Th)( (dx(u)*dx(v) + dy(u)*dy(v)) * K[region]) + int1d(Th,7)(u*v) - int2d(Th)(pr[region]*v) ;
+	int regt = Th(L/2,l/2).region;
+	for(int i=0;i<nbres;++i)
+	{
+		Vh up,ux,uy;
+		int thereg = Th(XX[3*i+1],XX[3*i+2]).region;
+		//cout << "pr:" << pr[thereg] << endl;
+		solve dpchaleur(up,v) = int2d(Th)( (dx(up)*dx(v) + dy(up)*dy(v)) * K[region]) + int1d(Th,7)(up*v) - int2d(Th,thereg)(v);
+		grad[3*i] = int2d(Th,regt)(2*up*(u-target)) + 2*pena*diff[3*i];
+		solve dxchaleur(ux,v) = int2d(Th)( (dx(ux)*dx(v) + dy(ux)*dy(v)) * K[region]) + int1d(Th,7)(ux*v) - int1d(Th,i)(pr[thereg]*v*N.x);
+		grad[3*i+1] = int2d(Th,regt)(2*ux*(u-target)) + 2*pena*diff[3*i+1];
+		solve dychaleur(uy,v) = int2d(Th)( (dx(uy)*dx(v) + dy(uy)*dy(v)) * K[region]) + int1d(Th,7)(uy*v) - int1d(Th,i)(pr[thereg]*v*N.y);
+		grad[3*i+2] = int2d(Th,regt)(2*uy*(u-target)) + 2*pena*diff[3*i+2];
+		if(plotgrad)
+		{
+			plot(up,nbiso=50,wait=0,cmm="Derivative w.r.t. pr["+i+"]");
+			plot(ux,nbiso=50,wait=0,cmm="Derivative w.r.t. x["+i+"]");
+			plot(uy,nbiso=50,wait=0,cmm="Derivative w.r.t. y["+i+"]");
+		}
+	}
+	cout << "dJ : " << grad << endl;
+	return grad;
+}
+
+
+real pst=5000;
+real isdxy=3*L/24.;
+real[int] isd  =[1000,isdxy,isdxy,1000,isdxy,isdxy,1000,isdxy,isdxy,1000,isdxy,5*l/6,1000,isdxy,isdxy,1000,isdxy,isdxy];
+real[int] start=[pst,L/6,l/6,pst,L/2,l/6,pst,5*L/6,l/6,pst,L/6,5*l/6,pst,L/2,5*l/6,pst,5*L/6,5*l/6];
+
+//dJ(start);
+cout << cmaes(J,start,initialStdDevs=isd,stopTolFun=1e-1,stopMaxIter=200,stopMaxFunEval=1000);
+//BFGS(J,dJ,start,nbiterline=10,nbiter=3000,eps=1.e-8);
+iter = 1000;
+
+// FFCS - regression test reference value
+real regtest=J(start);
diff --git a/examples++-load/cmaes.cpp b/examples++-load/cmaes.cpp
new file mode 100644
index 0000000..6c09267
--- /dev/null
+++ b/examples++-load/cmaes.cpp
@@ -0,0 +1,2939 @@
+/* --------------------------------------------------------- */
+/* --- File: cmaes.c  -------- Author: Nikolaus Hansen   --- */
+/* --------------------------------------------------------- */
+/*   
+     CMA-ES for non-linear function minimization. 
+
+     Copyright 1996, 2003, 2007 Nikolaus Hansen 
+     e-mail: hansen .AT. bionik.tu-berlin.de
+             hansen .AT. lri.fr
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License, version 2,
+    as published by the Free Software Foundation.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+/* --- Changes : --- 
+  03/03/21: argument const double *rgFunVal of
+            cmaes_ReestimateDistribution() was treated incorrectly.
+  03/03/29: restart via cmaes_resume_distribution() implemented.  
+  03/03/30: Always max std dev / largest axis is printed first. 
+  03/08/30: Damping is adjusted for large mueff. 
+  03/10/30: Damping is adjusted for large mueff always. 
+  04/04/22: Cumulation time and damping for step size adjusted. 
+            No iniphase but conditional update of pc. 
+  05/03/15: in ccov-setting mucov replaced by mueff. 
+  05/10/05: revise comment on resampling in example.c
+  05/10/13: output of "coorstddev" changed from sigma * C[i][i] 
+            to correct sigma * sqrt(C[i][i]).  
+  05/11/09: Numerical problems are not anymore handled by increasing 
+            sigma, but lead to satisfy a stopping criterion in 
+            cmaes_Test(). 
+  05/11/09: Update of eigensystem and test for numerical problems 
+            moved right before sampling. 
+  06/02/24: Non-ansi array definitions replaced (thanks to Marc 
+            Toussaint). 
+  06/02/25: Overflow in time measurement for runs longer than 
+            2100 seconds. This could lead to stalling the 
+            covariance matrix update for long periods. 
+            Time measurement completely rewritten. 
+  06/02/26: Included population size lambda as parameter to 
+            cmaes_init (thanks to MT). 
+  06/02/26: Allow no initial reading/writing of parameters via
+            "non" and "writeonly" keywords for input parameter 
+            filename in cmaes_init. 
+  06/02/27: Optimized code regarding time spent in updating the 
+            covariance matrix in function Adapt_C2(). 
+  07/08/03: clean up and implementation of an exhaustive test 
+            of the eigendecomposition (via #ifdef for now) 
+  07/08/04: writing of output improved 
+  07/08/xx: termination criteria revised and more added, 
+            damp replaced by damps=damp*cs, documentation improved.
+            Interface significantly changed, evaluateSample function
+            and therefore the function pointer argument removed. 
+            Renaming of functions in accordance with Java code. 
+            Clean up of parameter names, mainly in accordance with
+            Matlab conventions. Most termination criteria can be
+            changed online now. Many more small changes, but not in 
+            the core procedure. 
+  07/10/29: ReSampleSingle() got a better interface. ReSampleSingle()
+            is now ReSampleSingle_old only for backward
+            compatibility. Also fixed incorrect documentation. The new
+            function SampleSingleInto() has an interface similar to
+            the old ReSampleSingle(), but is not really necessary.
+  07/11/20: bug: stopMaxIter did not translate into the correct default
+            value but into -1 as default. This lead to a too large 
+            damps and the termination test became true from the first
+            iteration. (Thanks to Michael Calonder)
+  07/11/20: new default stopTolFunHist = 1e-13;  (instead of zero)
+  08/09/26: initial diagonal covariance matrix in code, but not
+            yet in interface
+  08/09/27: diagonalCovarianceMatrix option in initials.par provided
+  08/10/17: uncertainty handling implemented in example3.c. 
+            PerturbSolutionInto() provides the optional small 
+            perturbations before reevaluation.
+  10/10/16: TestForTermination changed such that diagonalCovarianceMatrix 
+            option now yields linear time behavior 
+
+  Wish List
+
+    o as writing time is measure for all files at once, the display
+      cannot be independently written to a file via signals.par, while
+      this would be desirable. 
+
+    o clean up sorting of eigenvalues and vectors which is done repeatedly.
+
+    o either use cmaes_Get() in cmaes_WriteToFilePtr(): revise the
+      cmaes_write that all keywords available with get and getptr are
+      recognized. Also revise the keywords, keeping backward
+      compatibility. (not only) for this it would be useful to find a
+      way how cmaes_Get() signals an unrecognized keyword. For GetPtr
+      it can return NULL.
+
+    o or break cmaes_Get() into single getter functions, being a nicer 
+      interface, and compile instead of runtime error, and faster. For
+      file signals.par it does not help. 
+
+    o writing data depending on timing in a smarter way, e.g. using 10% 
+      of all time. First find out whether clock() is useful for measuring
+      disc writing time and then timings_t class can be utilized. 
+      For very large dimension the default of 1 seconds waiting might 
+      be too small. 
+
+    o allow modification of best solution depending on delivered f(xmean)
+
+    o re-write input and output procedures 
+*/
+
+#include <math.h>   /* sqrt() */
+#include <stddef.h> /* size_t */
+#include <stdlib.h> /* NULL, free */
+#include <string.h> /* strlen() */
+#include <stdio.h>  /* sprintf(), NULL? */
+#include "cmaes_interface.h" /* <time.h> via cmaes.h */
+
+/* --------------------------------------------------------- */
+/* ------------------- Declarations ------------------------ */
+/* --------------------------------------------------------- */
+
+/* ------------------- External Visibly -------------------- */
+
+/* see cmaes_interface.h for those, not listed here */
+
+long   random_init(random_t *, long unsigned seed /* 0==clock */);
+void   random_exit(random_t *);
+double random_Gauss(random_t *); /* (0,1)-normally distributed */
+double random_Uniform(random_t *);
+long   random_Start(random_t *, long unsigned seed /* 0==1 */);
+
+void   timings_init(timings_t *timing);
+void   timings_start(timings_t *timing); /* fields totaltime and tictoctime */
+double timings_update(timings_t *timing);
+void   timings_tic(timings_t *timing);
+double timings_toc(timings_t *timing);
+
+void readpara_init (readpara_t *, int dim, int seed,  const double * xstart, 
+                    const double * sigma, int lambda, const char * filename);
+void readpara_exit(readpara_t *);
+void readpara_ReadFromFile(readpara_t *, const char *szFileName);
+void readpara_SupplementDefaults(readpara_t *);
+void readpara_SetWeights(readpara_t *, const char * mode);
+void readpara_WriteToFile(readpara_t *, const char *filenamedest, 
+                          const char *parafilesource);
+
+double const * cmaes_SetMean(cmaes_t *, const double *xmean);
+double * cmaes_PerturbSolutionInto(cmaes_t *t, double *xout, 
+                                   double const *xin, double eps);
+void cmaes_WriteToFile(cmaes_t *, const char *key, const char *name);
+void cmaes_WriteToFileAW(cmaes_t *t, const char *key, const char *name, 
+                         const char * append);
+void cmaes_WriteToFilePtr(cmaes_t *, const char *key, FILE *fp);
+void cmaes_ReadFromFilePtr(cmaes_t *, FILE *fp); 
+void cmaes_FATAL(char const *s1, char const *s2, 
+                 char const *s3, char const *s4);
+
+
+/* ------------------- Locally visibly ----------------------- */
+
+static char * getTimeStr(void); 
+static void TestMinStdDevs( cmaes_t *);
+/* static void WriteMaxErrorInfo( cmaes_t *); */
+
+static void Eigen( int N,  double **C, double *diag, double **Q, 
+                   double *rgtmp);
+static int  Check_Eigen( int N,  double **C, double *diag, double **Q);
+static void QLalgo2 (int n, double *d, double *e, double **V); 
+static void Householder2(int n, double **V, double *d, double *e); 
+static void Adapt_C2(cmaes_t *t, int hsig);
+
+static void FATAL(char const *sz1, char const *s2, 
+                  char const *s3, char const *s4);
+static void ERRORMESSAGE(char const *sz1, char const *s2, 
+                         char const *s3, char const *s4);
+static void   Sorted_index( const double *rgFunVal, int *index, int n);
+static int    SignOfDiff( const void *d1, const void * d2);
+static double douSquare(double);
+static double rgdouMax( const double *rgd, int len);
+static double rgdouMin( const double *rgd, int len);
+static double douMax( double d1, double d2);
+static double douMin( double d1, double d2);
+static int    intMin( int i, int j);
+static int    MaxIdx( const double *rgd, int len);
+static int    MinIdx( const double *rgd, int len);
+static double myhypot(double a, double b);
+static double * new_double( int n);
+static void * new_void( int n, size_t size); 
+
+/* --------------------------------------------------------- */
+/* ---------------- Functions: cmaes_t --------------------- */
+/* --------------------------------------------------------- */
+
+static char *
+getTimeStr(void) {
+  time_t tm = time(0);
+  static char s[33];
+
+  /* get time */
+  strncpy(s, ctime(&tm), 24); /* TODO: hopefully we read something useful */
+  s[24] = '\0'; /* cut the \n */
+  return s;
+}
+
+char * 
+cmaes_SayHello(cmaes_t *t)
+{
+  /* write initial message */
+  sprintf(t->sOutString, 
+          "(%d,%d)-CMA-ES(mu_eff=%.1f), Ver=\"%s\", dimension=%d, diagonalIterations=%ld, randomSeed=%d (%s)", 
+          t->sp.mu, t->sp.lambda, t->sp.mueff, t->version, t->sp.N, (long)t->sp.diagonalCov,
+          t->sp.seed, getTimeStr());
+
+  return t->sOutString; 
+}
+
+double * 
+cmaes_init(cmaes_t *t, /* "this" */
+                int dimension, 
+                double *inxstart,
+                double *inrgstddev, /* initial stds */
+                long int inseed,
+                int lambda, 
+                const char *input_parameter_filename) 
+{
+  int i, j, N;
+  double dtest, trace;
+
+  t->version = "3.11.00.beta";
+
+  readpara_init (&t->sp, dimension, inseed, inxstart, inrgstddev, 
+                   lambda, input_parameter_filename);
+  t->sp.seed = random_init( &t->rand, (long unsigned int) t->sp.seed);
+
+  N = t->sp.N; /* for convenience */
+  
+  /* initialization  */
+  for (i = 0, trace = 0.; i < N; ++i)
+    trace += t->sp.rgInitialStds[i]*t->sp.rgInitialStds[i];
+  t->sigma = sqrt(trace/N); /* t->sp.mueff/(0.2*t->sp.mueff+sqrt(N)) * sqrt(trace/N); */
+
+  t->chiN = sqrt((double) N) * (1. - 1./(4.*N) + 1./(21.*N*N));
+  t->flgEigensysIsUptodate = 1;
+  t->flgCheckEigen = 0; 
+  t->genOfEigensysUpdate = 0;
+  timings_init(&t->eigenTimings);
+  t->flgIniphase = 0; /* do not use iniphase, hsig does the job now */
+  t->flgresumedone = 0;
+  t->flgStop = 0;
+
+  for (dtest = 1.; dtest && dtest < 1.1 * dtest; dtest *= 2.) 
+    if (dtest == dtest + 1.)
+      break;
+  t->dMaxSignifKond = dtest / 1000.; /* not sure whether this is really save, 100 does not work well enough */
+
+  t->gen = 0;
+  t->countevals = 0;
+  t->state = 0;
+  t->dLastMinEWgroesserNull = 1.0;
+  t->printtime = t->writetime = t->firstwritetime = t->firstprinttime = 0; 
+
+  t->rgpc = new_double(N);
+  t->rgps = new_double(N);
+  t->rgdTmp = new_double(N+1);
+  t->rgBDz = new_double(N);
+  t->rgxmean = new_double(N+2); t->rgxmean[0] = N; ++t->rgxmean;
+  t->rgxold = new_double(N+2); t->rgxold[0] = N; ++t->rgxold; 
+  t->rgxbestever = new_double(N+3); t->rgxbestever[0] = N; ++t->rgxbestever; 
+  t->rgout = new_double(N+2); t->rgout[0] = N; ++t->rgout;
+  t->rgD = new_double(N);
+  t->C = (double**)new_void(N, sizeof(double*));
+  t->B = (double**)new_void(N, sizeof(double*));
+  t->publicFitness = new_double(t->sp.lambda); 
+  t->rgFuncValue = new_double(t->sp.lambda+1); 
+  t->rgFuncValue[0]=t->sp.lambda; ++t->rgFuncValue;
+  t->arFuncValueHist = new_double(10+(int)ceil(3.*10.*N/t->sp.lambda)+1);
+  t->arFuncValueHist[0] = (double)(10+(int)ceil(3.*10.*N/t->sp.lambda));
+  t->arFuncValueHist++; 
+
+  for (i = 0; i < N; ++i) {
+      t->C[i] = new_double(i+1);
+      t->B[i] = new_double(N);
+    }
+  t->index = (int *) new_void(t->sp.lambda, sizeof(int));
+  for (i = 0; i < t->sp.lambda; ++i) 
+    t->index[i] = i; /* should not be necessary */
+  t->rgrgx = (double **)new_void(t->sp.lambda, sizeof(double*));
+  for (i = 0; i < t->sp.lambda; ++i) {
+    t->rgrgx[i] = new_double(N+2);
+    t->rgrgx[i][0] = N; 
+    t->rgrgx[i]++;
+  }
+
+  /* Initialize newed space  */
+
+  for (i = 0; i < N; ++i)
+    for (j = 0; j < i; ++j)
+       t->C[i][j] = t->B[i][j] = t->B[j][i] = 0.;
+        
+  for (i = 0; i < N; ++i)
+    {
+      t->B[i][i] = 1.;
+      t->C[i][i] = t->rgD[i] = t->sp.rgInitialStds[i] * sqrt(N / trace);
+      t->C[i][i] *= t->C[i][i];
+      t->rgpc[i] = t->rgps[i] = 0.;
+    }
+
+  t->minEW = rgdouMin(t->rgD, N); t->minEW = t->minEW * t->minEW;
+  t->maxEW = rgdouMax(t->rgD, N); t->maxEW = t->maxEW * t->maxEW; 
+
+  t->maxdiagC=t->C[0][0]; for(i=1;i<N;++i) if(t->maxdiagC<t->C[i][i]) t->maxdiagC=t->C[i][i];
+  t->mindiagC=t->C[0][0]; for(i=1;i<N;++i) if(t->mindiagC>t->C[i][i]) t->mindiagC=t->C[i][i];
+
+  /* set xmean */
+  for (i = 0; i < N; ++i)
+    t->rgxmean[i] = t->rgxold[i] = t->sp.xstart[i]; 
+  /* use in case xstart as typicalX */
+  if (t->sp.typicalXcase) 
+    for (i = 0; i < N; ++i)
+      t->rgxmean[i] += t->sigma * t->rgD[i] * random_Gauss(&t->rand);
+
+  if (strcmp(t->sp.resumefile, "_no_")  != 0)
+    cmaes_resume_distribution(t, t->sp.resumefile);
+
+  return (t->publicFitness); 
+
+} /* cmaes_init() */
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+
+void 
+cmaes_resume_distribution(cmaes_t *t, char *filename)
+{
+  int i, j, res, n; 
+  double d; 
+  FILE *fp = fopen( filename, "r"); 
+  if(fp == 0) {
+    ERRORMESSAGE("cmaes_resume_distribution(): could not open '", 
+                 filename, "'",0);
+    return;
+  }
+  /* count number of "resume" entries */
+  i = 0; res = 0;
+  while (1) {
+    if ((res = fscanf(fp, " resume %lg", &d)) == EOF)
+      break;
+    else if (res==0) 
+      fscanf(fp, " %*s");
+    else if(res > 0)
+      i += 1;
+  }
+
+  /* go to last "resume" entry */
+  n = i; i = 0; res = 0; rewind(fp);
+  while (i<n) {
+    if ((res = fscanf(fp, " resume %lg", &d)) == EOF)
+      FATAL("cmaes_resume_distribution(): Unexpected error, bug",0,0,0); 
+    else if (res==0) 
+      fscanf(fp, " %*s");
+    else if(res > 0)
+      ++i;
+  }
+  if (d != t->sp.N)
+    FATAL("cmaes_resume_distribution(): Dimension numbers do not match",0,0,0); 
+  
+  /* find next "xmean" entry */  
+  while (1) {
+    if ((res = fscanf(fp, " xmean %lg", &d)) == EOF)
+      FATAL("cmaes_resume_distribution(): 'xmean' not found",0,0,0); 
+    else if (res==0) 
+      fscanf(fp, " %*s");
+    else if(res > 0)
+      break;
+  }
+  
+  /* read xmean */
+  t->rgxmean[0] = d; res = 1; 
+  for(i = 1; i < t->sp.N; ++i)
+    res += fscanf(fp, " %lg", &t->rgxmean[i]);
+  if (res != t->sp.N)
+    FATAL("cmaes_resume_distribution(): xmean: dimensions differ",0,0,0); 
+
+  /* find next "path for sigma" entry */  
+  while (1) {
+    if ((res = fscanf(fp, " path for sigma %lg", &d)) == EOF)
+      FATAL("cmaes_resume_distribution(): 'path for sigma' not found",0,0,0); 
+    else if (res==0) 
+      fscanf(fp, " %*s");
+    else if(res > 0)
+      break;
+  }
+  
+  /* read ps */
+  t->rgps[0] = d; res = 1;
+  for(i = 1; i < t->sp.N; ++i)
+    res += fscanf(fp, " %lg", &t->rgps[i]);
+  if (res != t->sp.N)
+    FATAL("cmaes_resume_distribution(): ps: dimensions differ",0,0,0); 
+  
+  /* find next "path for C" entry */  
+  while (1) {
+    if ((res = fscanf(fp, " path for C %lg", &d)) == EOF)
+      FATAL("cmaes_resume_distribution(): 'path for C' not found",0,0,0); 
+    else if (res==0) 
+      fscanf(fp, " %*s");
+    else if(res > 0)
+      break;
+  }
+  /* read pc */
+  t->rgpc[0] = d; res = 1;
+  for(i = 1; i < t->sp.N; ++i)
+    res += fscanf(fp, " %lg", &t->rgpc[i]);
+  if (res != t->sp.N)
+    FATAL("cmaes_resume_distribution(): pc: dimensions differ",0,0,0); 
+
+  /* find next "sigma" entry */  
+  while (1) {
+    if ((res = fscanf(fp, " sigma %lg", &d)) == EOF)
+      FATAL("cmaes_resume_distribution(): 'sigma' not found",0,0,0); 
+    else if (res==0) 
+      fscanf(fp, " %*s");
+    else if(res > 0)
+      break;
+  }
+  t->sigma = d;
+
+  /* find next entry "covariance matrix" */
+  while (1) {
+    if ((res = fscanf(fp, " covariance matrix %lg", &d)) == EOF)
+      FATAL("cmaes_resume_distribution(): 'covariance matrix' not found",0,0,0); 
+    else if (res==0) 
+      fscanf(fp, " %*s");
+    else if(res > 0)
+      break;
+  }
+  /* read C */
+  t->C[0][0] = d; res = 1;
+  for (i = 1; i < t->sp.N; ++i)
+    for (j = 0; j <= i; ++j)
+      res += fscanf(fp, " %lg", &t->C[i][j]);
+  if (res != (t->sp.N*t->sp.N+t->sp.N)/2)
+    FATAL("cmaes_resume_distribution(): C: dimensions differ",0,0,0); 
+   
+  t->flgIniphase = 0;
+  t->flgEigensysIsUptodate = 0;
+  t->flgresumedone = 1;
+  cmaes_UpdateEigensystem(t, 1);
+  
+} /* cmaes_resume_distribution() */
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+
+void 
+cmaes_exit(cmaes_t *t)
+{
+  int i, N = t->sp.N;
+  t->state = -1; /* not really useful at the moment */
+  free( t->rgpc);
+  free( t->rgps);
+  free( t->rgdTmp);
+  free( t->rgBDz);
+  free( --t->rgxmean);
+  free( --t->rgxold); 
+  free( --t->rgxbestever); 
+  free( --t->rgout); 
+  free( t->rgD);
+  for (i = 0; i < N; ++i) {
+    free( t->C[i]);
+    free( t->B[i]);
+  }
+  for (i = 0; i < t->sp.lambda; ++i) 
+    free( --t->rgrgx[i]);
+  free( t->rgrgx); 
+  free( t->C);
+  free( t->B);
+  free( t->index);
+  free( t->publicFitness);
+  free( --t->rgFuncValue);
+  free( --t->arFuncValueHist);
+  random_exit (&t->rand);
+  readpara_exit (&t->sp); 
+} /* cmaes_exit() */
+
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+double const * 
+cmaes_SetMean(cmaes_t *t, const double *xmean)
+/*
+ * Distribution mean could be changed before SamplePopulation().
+ * This might lead to unexpected behaviour if done repeatedly. 
+ */
+{
+  int i, N=t->sp.N;
+
+  if (t->state >= 1 && t->state < 3)
+    FATAL("cmaes_SetMean: mean cannot be set inbetween the calls of ",
+          "SamplePopulation and UpdateDistribution",0,0);
+
+  if (xmean != 0 && xmean != t->rgxmean)
+    for(i = 0; i < N; ++i)
+      t->rgxmean[i] = xmean[i];
+  else 
+    xmean = t->rgxmean; 
+
+  return xmean; 
+}
+ 
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+double * const * 
+cmaes_SamplePopulation(cmaes_t *t)
+{
+  int iNk, i, j, N=t->sp.N;
+  int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); 
+  double sum;
+  double const *xmean = t->rgxmean; 
+
+  /* cmaes_SetMean(t, xmean); * xmean could be changed at this point */
+
+  /* calculate eigensystem  */
+  if (!t->flgEigensysIsUptodate) {
+    if (!flgdiag)
+      cmaes_UpdateEigensystem(t, 0);
+    else {
+        for (i = 0; i < N; ++i)
+          t->rgD[i] = sqrt(t->C[i][i]);
+        t->minEW = douSquare(rgdouMin(t->rgD, N)); 
+        t->maxEW = douSquare(rgdouMax(t->rgD, N));
+        t->flgEigensysIsUptodate = 1;
+        timings_start(&t->eigenTimings);
+      }
+  }
+
+  /* treat minimal standard deviations and numeric problems */
+  TestMinStdDevs(t); 
+
+  for (iNk = 0; iNk < t->sp.lambda; ++iNk)
+    { /* generate scaled random vector (D * z)    */
+      for (i = 0; i < N; ++i)
+        if (flgdiag)
+          t->rgrgx[iNk][i] = xmean[i] + t->sigma * t->rgD[i] * random_Gauss(&t->rand);
+        else
+          t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand);
+      if (!flgdiag)
+        /* add mutation (sigma * B * (D*z)) */
+        for (i = 0; i < N; ++i) {
+          for (j = 0, sum = 0.; j < N; ++j)
+            sum += t->B[i][j] * t->rgdTmp[j];
+          t->rgrgx[iNk][i] = xmean[i] + t->sigma * sum;
+        }
+    }
+  if(t->state == 3 || t->gen == 0)
+    ++t->gen;
+  t->state = 1; 
+
+  return(t->rgrgx);
+} /* SamplePopulation() */
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+double const * 
+cmaes_ReSampleSingle_old( cmaes_t *t, double *rgx)
+{
+  int i, j, N=t->sp.N;
+  double sum; 
+
+  if (rgx == 0)
+    FATAL("cmaes_ReSampleSingle(): Missing input double *x",0,0,0);
+
+  for (i = 0; i < N; ++i)
+    t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand);
+  /* add mutation (sigma * B * (D*z)) */
+  for (i = 0; i < N; ++i) {
+    for (j = 0, sum = 0.; j < N; ++j)
+      sum += t->B[i][j] * t->rgdTmp[j];
+    rgx[i] = t->rgxmean[i] + t->sigma * sum;
+  }
+  return rgx;
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+double * const * 
+cmaes_ReSampleSingle( cmaes_t *t, int iindex)
+{
+  int i, j, N=t->sp.N;
+  double *rgx; 
+  double sum; 
+  static char s[99];
+
+  if (iindex < 0 || iindex >= t->sp.lambda) {
+    sprintf(s, "index==%d must be between 0 and %d", iindex, t->sp.lambda);
+    FATAL("cmaes_ReSampleSingle(): Population member ",s,0,0);
+  }
+  rgx = t->rgrgx[iindex];
+
+  for (i = 0; i < N; ++i)
+    t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand);
+  /* add mutation (sigma * B * (D*z)) */
+  for (i = 0; i < N; ++i) {
+    for (j = 0, sum = 0.; j < N; ++j)
+      sum += t->B[i][j] * t->rgdTmp[j];
+    rgx[i] = t->rgxmean[i] + t->sigma * sum;
+  }
+  return(t->rgrgx);
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+double * 
+cmaes_SampleSingleInto( cmaes_t *t, double *rgx)
+{
+  int i, j, N=t->sp.N;
+  double sum; 
+
+  if (rgx == 0)
+    rgx = new_double(N);
+
+  for (i = 0; i < N; ++i)
+    t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand);
+  /* add mutation (sigma * B * (D*z)) */
+  for (i = 0; i < N; ++i) {
+    for (j = 0, sum = 0.; j < N; ++j)
+      sum += t->B[i][j] * t->rgdTmp[j];
+    rgx[i] = t->rgxmean[i] + t->sigma * sum;
+  }
+  return rgx;
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+double * 
+cmaes_PerturbSolutionInto( cmaes_t *t, double *rgx, double const *xmean, double eps)
+{
+  int i, j, N=t->sp.N;
+  double sum; 
+
+  if (rgx == 0)
+    rgx = new_double(N);
+  if (xmean == 0)
+    FATAL("cmaes_PerturbSolutionInto(): xmean was not given",0,0,0);
+
+  for (i = 0; i < N; ++i)
+    t->rgdTmp[i] = t->rgD[i] * random_Gauss(&t->rand);
+  /* add mutation (sigma * B * (D*z)) */
+  for (i = 0; i < N; ++i) {
+    for (j = 0, sum = 0.; j < N; ++j)
+      sum += t->B[i][j] * t->rgdTmp[j];
+    rgx[i] = xmean[i] + eps * t->sigma * sum;
+  }
+  return rgx;
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+double *
+cmaes_UpdateDistribution( cmaes_t *t, const double *rgFunVal)
+{
+  int i, j, iNk, hsig, N=t->sp.N;
+  int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); 
+  double sum; 
+  double psxps; 
+  
+  if(t->state == 3)
+    FATAL("cmaes_UpdateDistribution(): You need to call \n",
+          "SamplePopulation() before update can take place.",0,0);
+  if(rgFunVal == 0) 
+    FATAL("cmaes_UpdateDistribution(): ", 
+          "Fitness function value array input is missing.",0,0);
+
+  if(t->state == 1)  /* function values are delivered here */
+    t->countevals += t->sp.lambda;
+  else
+    ERRORMESSAGE("cmaes_UpdateDistribution(): unexpected state",0,0,0);
+
+  /* assign function values */
+  for (i=0; i < t->sp.lambda; ++i) 
+    t->rgrgx[i][N] = t->rgFuncValue[i] = rgFunVal[i];
+  
+
+  /* Generate index */
+  Sorted_index(rgFunVal, t->index, t->sp.lambda);
+  
+  /* Test if function values are identical, escape flat fitness */
+  if (t->rgFuncValue[t->index[0]] == 
+      t->rgFuncValue[t->index[(int)t->sp.lambda/2]]) {
+    t->sigma *= exp(0.2+t->sp.cs/t->sp.damps);
+    ERRORMESSAGE("Warning: sigma increased due to equal function values\n",
+                 "   Reconsider the formulation of the objective function",0,0);
+  }
+  
+  /* update function value history */
+  for(i = (int)*(t->arFuncValueHist-1)-1; i > 0; --i) /* for(i = t->arFuncValueHist[-1]-1; i > 0; --i) */
+    t->arFuncValueHist[i] = t->arFuncValueHist[i-1];
+  t->arFuncValueHist[0] = rgFunVal[t->index[0]];
+
+  /* update xbestever */
+  if (t->rgxbestever[N] > t->rgrgx[t->index[0]][N] || t->gen == 1)
+    for (i = 0; i <= N; ++i) {
+      t->rgxbestever[i] = t->rgrgx[t->index[0]][i];
+      t->rgxbestever[N+1] = t->countevals;
+    }
+
+  /* calculate xmean and rgBDz~N(0,C) */
+  for (i = 0; i < N; ++i) {
+    t->rgxold[i] = t->rgxmean[i]; 
+    t->rgxmean[i] = 0.;
+    for (iNk = 0; iNk < t->sp.mu; ++iNk) 
+      t->rgxmean[i] += t->sp.weights[iNk] * t->rgrgx[t->index[iNk]][i];
+    t->rgBDz[i] = sqrt(t->sp.mueff)*(t->rgxmean[i] - t->rgxold[i])/t->sigma; 
+  }
+
+  /* calculate z := D^(-1) * B^(-1) * rgBDz into rgdTmp */
+  for (i = 0; i < N; ++i) {
+    if (!flgdiag)
+      for (j = 0, sum = 0.; j < N; ++j)
+        sum += t->B[j][i] * t->rgBDz[j];
+    else
+      sum = t->rgBDz[i];
+    t->rgdTmp[i] = sum / t->rgD[i];
+  }
+  
+  /* TODO?: check length of t->rgdTmp and set an upper limit, e.g. 6 stds */
+  /* in case of manipulation of arx, 
+     this can prevent an increase of sigma by several orders of magnitude
+     within one step; a five-fold increase in one step can still happen. 
+  */ 
+  /*
+    for (j = 0, sum = 0.; j < N; ++j)
+      sum += t->rgdTmp[j] * t->rgdTmp[j];
+    if (sqrt(sum) > chiN + 6. * sqrt(0.5)) {
+      rgdTmp length should be set to upper bound and hsig should become zero 
+    }
+  */
+
+  /* cumulation for sigma (ps) using B*z */
+  for (i = 0; i < N; ++i) {
+    if (!flgdiag)
+      for (j = 0, sum = 0.; j < N; ++j)
+        sum += t->B[i][j] * t->rgdTmp[j];
+    else
+      sum = t->rgdTmp[i];
+    t->rgps[i] = (1. - t->sp.cs) * t->rgps[i] + 
+      sqrt(t->sp.cs * (2. - t->sp.cs)) * sum;
+  }
+  
+  /* calculate norm(ps)^2 */
+  for (i = 0, psxps = 0.; i < N; ++i)
+    psxps += t->rgps[i] * t->rgps[i];
+
+  /* cumulation for covariance matrix (pc) using B*D*z~N(0,C) */
+  hsig = sqrt(psxps) / sqrt(1. - pow(1.-t->sp.cs, 2*t->gen)) / t->chiN
+    < 1.4 + 2./(N+1);
+  for (i = 0; i < N; ++i) {
+    t->rgpc[i] = (1. - t->sp.ccumcov) * t->rgpc[i] + 
+      hsig * sqrt(t->sp.ccumcov * (2. - t->sp.ccumcov)) * t->rgBDz[i];
+  }
+  
+  /* stop initial phase */
+  if (t->flgIniphase && 
+      t->gen > douMin(1/t->sp.cs, 1+N/t->sp.mucov)) 
+    {
+      if (psxps / t->sp.damps / (1.-pow((1. - t->sp.cs), t->gen)) 
+          < N * 1.05) 
+        t->flgIniphase = 0;
+    }
+  
+#if 0
+  /* remove momentum in ps, if ps is large and fitness is getting worse */
+  /* This is obsolete due to hsig and harmful in a dynamic environment */
+  if(psxps/N > 1.5 + 10.*sqrt(2./N) 
+     && t->arFuncValueHist[0] > t->arFuncValueHist[1]
+     && t->arFuncValueHist[0] > t->arFuncValueHist[2]) {
+    double tfac = sqrt((1 + douMax(0, log(psxps/N))) * N / psxps);
+    for (i=0; i<N; ++i) 
+      t->rgps[i] *= tfac;
+    psxps *= tfac*tfac; 
+  }
+#endif
+  
+  /* update of C  */
+
+  Adapt_C2(t, hsig);
+  
+  /* Adapt_C(t); not used anymore */
+
+#if 0
+  if (t->sp.ccov != 0. && t->flgIniphase == 0) {
+    int k; 
+
+    t->flgEigensysIsUptodate = 0;
+
+    /* update covariance matrix */
+    for (i = 0; i < N; ++i)
+      for (j = 0; j <=i; ++j) {
+        t->C[i][j] = (1 - t->sp.ccov) * t->C[i][j] 
+          + t->sp.ccov * (1./t->sp.mucov) 
+            * (t->rgpc[i] * t->rgpc[j] 
+               + (1-hsig)*t->sp.ccumcov*(2.-t->sp.ccumcov) * t->C[i][j]);
+        for (k = 0; k < t->sp.mu; ++k) /* additional rank mu update */
+          t->C[i][j] += t->sp.ccov * (1-1./t->sp.mucov) * t->sp.weights[k]  
+            * (t->rgrgx[t->index[k]][i] - t->rgxold[i]) 
+            * (t->rgrgx[t->index[k]][j] - t->rgxold[j])
+            / t->sigma / t->sigma; 
+      }
+  }
+#endif
+
+
+  /* update of sigma */
+  t->sigma *= exp(((sqrt(psxps)/t->chiN)-1.)*t->sp.cs/t->sp.damps);
+
+  t->state = 3;
+
+  return (t->rgxmean);
+
+} /* cmaes_UpdateDistribution() */
+
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+static void
+Adapt_C2(cmaes_t *t, int hsig)
+{
+  int i, j, k, N=t->sp.N;
+  int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); 
+
+  if (t->sp.ccov != 0. && t->flgIniphase == 0) {
+
+    /* definitions for speeding up inner-most loop */
+    double ccov1 = douMin(t->sp.ccov * (1./t->sp.mucov) * (flgdiag ? (N+1.5) / 3. : 1.), 1.);
+    double ccovmu = douMin(t->sp.ccov * (1-1./t->sp.mucov)* (flgdiag ? (N+1.5) / 3. : 1.), 1.-ccov1); 
+    double sigmasquare = t->sigma * t->sigma; 
+
+    t->flgEigensysIsUptodate = 0;
+
+    /* update covariance matrix */
+    for (i = 0; i < N; ++i)
+      for (j = flgdiag ? i : 0; j <= i; ++j) {
+        t->C[i][j] = (1 - ccov1 - ccovmu) * t->C[i][j] 
+          + ccov1
+            * (t->rgpc[i] * t->rgpc[j] 
+               + (1-hsig)*t->sp.ccumcov*(2.-t->sp.ccumcov) * t->C[i][j]);
+        for (k = 0; k < t->sp.mu; ++k) { /* additional rank mu update */
+          t->C[i][j] += ccovmu * t->sp.weights[k]  
+            * (t->rgrgx[t->index[k]][i] - t->rgxold[i]) 
+            * (t->rgrgx[t->index[k]][j] - t->rgxold[j])
+            / sigmasquare;
+        }
+      }
+    /* update maximal and minimal diagonal value */
+    t->maxdiagC = t->mindiagC = t->C[0][0];
+    for (i = 1; i < N; ++i) {
+      if (t->maxdiagC < t->C[i][i])
+        t->maxdiagC = t->C[i][i];
+      else if (t->mindiagC > t->C[i][i])
+        t->mindiagC = t->C[i][i];
+    }
+  } /* if ccov... */
+}
+
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+static void 
+TestMinStdDevs(cmaes_t *t)
+  /* increases sigma */
+{
+  int i, N = t->sp.N; 
+  if (t->sp.rgDiffMinChange == 0)
+    return;
+
+  for (i = 0; i < N; ++i)
+    while (t->sigma * sqrt(t->C[i][i]) < t->sp.rgDiffMinChange[i]) 
+      t->sigma *= exp(0.05+t->sp.cs/t->sp.damps);
+
+} /* cmaes_TestMinStdDevs() */
+
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void cmaes_WriteToFile(cmaes_t *t, const char *key, const char *name)
+{ 
+  cmaes_WriteToFileAW(t, key, name, "a"); /* default is append */
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void cmaes_WriteToFileAW(cmaes_t *t, const char *key, const char *name, 
+                         const char *appendwrite)
+{ 
+  const char *s = "tmpcmaes.dat"; 
+  FILE *fp;
+  
+  if (name == 0)
+    name = s; 
+
+  fp = fopen( name, appendwrite); 
+
+  if(fp == 0) {
+    ERRORMESSAGE("cmaes_WriteToFile(): could not open '", name, 
+                 "' with flag ", appendwrite);
+    return;
+  }
+
+  if (appendwrite[0] == 'w') {
+    /* write a header line, very rudimentary */
+    fprintf(fp, "%% # %s (randomSeed=%d, %s)\n", key, t->sp.seed, getTimeStr());
+  } else 
+    if (t->gen > 0 || strncmp(name, "outcmaesfit", 11) != 0)
+      cmaes_WriteToFilePtr(t, key, fp); /* do not write fitness for gen==0 */
+
+  fclose(fp);
+
+} /* WriteToFile */
+
+/* --------------------------------------------------------- */
+void cmaes_WriteToFilePtr(cmaes_t *t, const char *key, FILE *fp)
+
+/* this hack reads key words from input key for data to be written to
+ * a file, see file signals.par as input file. The length of the keys
+ * is mostly fixed, see key += number in the code! If the key phrase
+ * does not match the expectation the output might be strange.  for
+ * cmaes_t *t == 0 it solely prints key as a header line. Input key
+ * must be zero terminated.
+ */
+{ 
+  int i, k, N=(t ? t->sp.N : 0); 
+  char const *keyend, *keystart; 
+  const char *s = "few";
+  if (key == 0)
+    key = s; 
+  keystart = key; /* for debugging purpose */ 
+  keyend = key + strlen(key);
+
+  while (key < keyend)
+    {
+      if (strncmp(key, "axisratio", 9) == 0)
+        {
+          fprintf(fp, "%.2e", sqrt(t->maxEW/t->minEW));
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "idxminSD", 8) == 0)
+        {
+          int mini=0; for(i=N-1;i>0;--i) if(t->mindiagC==t->C[i][i]) mini=i; 
+          fprintf(fp, "%d", mini+1);
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "idxmaxSD", 8) == 0)
+        {
+          int maxi=0; for(i=N-1;i>0;--i) if(t->maxdiagC==t->C[i][i]) maxi=i; 
+          fprintf(fp, "%d", maxi+1);
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      /* new coordinate system == all eigenvectors */
+      if (strncmp(key, "B", 1) == 0) 
+        {
+          /* int j, index[N]; */
+          int j, *iindex=(int*)(new_void(N,sizeof(int))); /* MT */
+          Sorted_index(t->rgD, iindex, N); /* should not be necessary, see end of QLalgo2 */
+          /* One eigenvector per row, sorted: largest eigenvalue first */
+          for (i = 0; i < N; ++i)
+            for (j = 0; j < N; ++j)
+              fprintf(fp, "%g%c", t->B[j][iindex[N-1-i]], (j==N-1)?'\n':'\t');
+          ++key; 
+          free(iindex); /* MT */
+        }
+      /* covariance matrix */
+      if (strncmp(key, "C", 1) == 0) 
+        {
+          int j;
+          for (i = 0; i < N; ++i)
+            for (j = 0; j <= i; ++j)
+              fprintf(fp, "%g%c", t->C[i][j], (j==i)?'\n':'\t');
+          ++key; 
+        }
+      /* (processor) time (used) since begin of execution */ 
+      if (strncmp(key, "clock", 4) == 0)
+        {
+          timings_update(&t->eigenTimings);
+          fprintf(fp, "%.1f %.1f",  t->eigenTimings.totaltotaltime, 
+                  t->eigenTimings.tictoctime);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      /* ratio between largest and smallest standard deviation */
+      if (strncmp(key, "stddevratio", 11) == 0) /* std dev in coordinate axes */
+        {
+          fprintf(fp, "%g", sqrt(t->maxdiagC/t->mindiagC));
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      /* standard deviations in coordinate directions (sigma*sqrt(C[i,i])) */
+      if (strncmp(key, "coorstddev", 10) == 0 
+          || strncmp(key, "stddev", 6) == 0) /* std dev in coordinate axes */
+        {
+          for (i = 0; i < N; ++i)
+            fprintf(fp, "%s%g", (i==0) ? "":"\t", t->sigma*sqrt(t->C[i][i]));
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      /* diagonal of D == roots of eigenvalues, sorted */
+      if (strncmp(key, "diag(D)", 7) == 0)
+        {
+          for (i = 0; i < N; ++i)
+            t->rgdTmp[i] = t->rgD[i];
+          qsort(t->rgdTmp, (unsigned) N, sizeof(double), &SignOfDiff); /* superfluous */
+          for (i = 0; i < N; ++i)
+            fprintf(fp, "%s%g", (i==0) ? "":"\t", t->rgdTmp[i]);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "dim", 3) == 0)
+        {
+          fprintf(fp, "%d", N);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "eval", 4) == 0)
+        {
+          fprintf(fp, "%.0f", t->countevals);
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "few(diag(D))", 12) == 0)/* between four and six axes */
+        { 
+          int add = (int)(0.5 + (N + 1.) / 5.); 
+          for (i = 0; i < N; ++i)
+            t->rgdTmp[i] = t->rgD[i];
+          qsort(t->rgdTmp, (unsigned) N, sizeof(double), &SignOfDiff);
+          for (i = 0; i < N-1; i+=add)        /* print always largest */
+            fprintf(fp, "%s%g", (i==0) ? "":"\t", t->rgdTmp[N-1-i]);
+          fprintf(fp, "\t%g\n", t->rgdTmp[0]);        /* and smallest */
+          break; /* number of printed values is not determined */
+        }
+      if (strncmp(key, "fewinfo", 7) == 0) { 
+        fprintf(fp," Iter Fevals  Function Value          Sigma   ");
+        fprintf(fp, "MaxCoorDev MinCoorDev AxisRatio   MinDii      Time in eig\n");
+        while (*key != '+' && *key != '\0' && key < keyend)
+          ++key;
+      }
+      if (strncmp(key, "few", 3) == 0) { 
+        fprintf(fp, " %4.0f ", t->gen); 
+        fprintf(fp, " %5.0f ", t->countevals); 
+        fprintf(fp, "%.15e", t->rgFuncValue[t->index[0]]);
+        fprintf(fp, "  %.2e  %.2e %.2e", t->sigma, t->sigma*sqrt(t->maxdiagC), 
+                t->sigma*sqrt(t->mindiagC));
+        fprintf(fp, "  %.2e  %.2e", sqrt(t->maxEW/t->minEW), sqrt(t->minEW));
+        while (*key != '+' && *key != '\0' && key < keyend)
+          ++key;
+        fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+      }
+      if (strncmp(key, "funval", 6) == 0 || strncmp(key, "fitness", 6) == 0)
+        {
+          fprintf(fp, "%.15e", t->rgFuncValue[t->index[0]]);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "fbestever", 9) == 0)
+        {
+          fprintf(fp, "%.15e", t->rgxbestever[N]); /* f-value */
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "fmedian", 7) == 0)
+        {
+          fprintf(fp, "%.15e", t->rgFuncValue[t->index[(int)(t->sp.lambda/2)]]);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "fworst", 6) == 0)
+        {
+          fprintf(fp, "%.15e", t->rgFuncValue[t->index[t->sp.lambda-1]]);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "arfunval", 8) == 0 || strncmp(key, "arfitness", 8) == 0)
+        {
+          for (i = 0; i < N; ++i)
+            fprintf(fp, "%s%.10e", (i==0) ? "" : "\t", 
+                    t->rgFuncValue[t->index[i]]);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "gen", 3) == 0)
+        {
+          fprintf(fp, "%.0f", t->gen);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "iter", 4) == 0)
+        {
+          fprintf(fp, "%.0f", t->gen);
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "sigma", 5) == 0)
+        {
+          fprintf(fp, "%.4e", t->sigma);
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "minSD", 5) == 0) /* minimal standard deviation */
+        {
+          fprintf(fp, "%.4e", sqrt(t->mindiagC));
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "maxSD", 5) == 0)
+        {
+          fprintf(fp, "%.4e", sqrt(t->maxdiagC));
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "mindii", 6) == 0)
+        {
+          fprintf(fp, "%.4e", sqrt(t->minEW));
+          while (*key != '+' && *key != '\0' && key < keyend)
+           ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "0", 1) == 0)
+        {
+          fprintf(fp, "0");
+          ++key; 
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "lambda", 6) == 0)
+        {
+          fprintf(fp, "%d", t->sp.lambda);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "N", 1) == 0)
+        {
+          fprintf(fp, "%d", N);
+          ++key; 
+          fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+        }
+      if (strncmp(key, "resume", 6) == 0)
+        {
+          fprintf(fp, "\n# resume %d\n", N);
+          fprintf(fp, "xmean\n");
+          cmaes_WriteToFilePtr(t, "xmean", fp);
+          fprintf(fp, "path for sigma\n");
+          for(i=0; i<N; ++i)
+            fprintf(fp, "%g%s", t->rgps[i], (i==N-1) ? "\n":"\t");
+          fprintf(fp, "path for C\n");
+          for(i=0; i<N; ++i)
+            fprintf(fp, "%g%s", t->rgpc[i], (i==N-1) ? "\n":"\t");
+          fprintf(fp, "sigma %g\n", t->sigma);
+          /* note than B and D might not be up-to-date */
+          fprintf(fp, "covariance matrix\n"); 
+          cmaes_WriteToFilePtr(t, "C", fp);
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+        }
+      if (strncmp(key, "xbest", 5) == 0) { /* best x in recent generation */
+        for(i=0; i<N; ++i)
+          fprintf(fp, "%s%g", (i==0) ? "":"\t", t->rgrgx[t->index[0]][i]);
+        while (*key != '+' && *key != '\0' && key < keyend)
+          ++key;
+        fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+      }
+      if (strncmp(key, "xmean", 5) == 0) {
+        for(i=0; i<N; ++i)
+          fprintf(fp, "%s%g", (i==0) ? "":"\t", t->rgxmean[i]);
+        while (*key != '+' && *key != '\0' && key < keyend)
+          ++key;
+        fprintf(fp, "%c", (*key=='+') ? '\t':'\n');
+      }
+      if (strncmp(key, "all", 3) == 0)
+        {
+          time_t ti = time(0);
+          fprintf(fp, "\n# --------- %s\n", asctime(localtime(&ti)));
+          fprintf(fp, " N %d\n", N);
+          fprintf(fp, " seed %d\n", t->sp.seed);
+          fprintf(fp, "function evaluations %.0f\n", t->countevals);
+          fprintf(fp, "elapsed (CPU) time [s] %.2f\n", t->eigenTimings.totaltotaltime);
+          fprintf(fp, "function value f(x)=%g\n", t->rgrgx[t->index[0]][N]);
+          fprintf(fp, "maximal standard deviation %g\n", t->sigma*sqrt(t->maxdiagC));
+          fprintf(fp, "minimal standard deviation %g\n", t->sigma*sqrt(t->mindiagC));
+          fprintf(fp, "sigma %g\n", t->sigma);
+          fprintf(fp, "axisratio %g\n", rgdouMax(t->rgD, N)/rgdouMin(t->rgD, N));
+          fprintf(fp, "xbestever found after %.0f evaluations, function value %g\n", 
+                  t->rgxbestever[N+1], t->rgxbestever[N]);
+          for(i=0; i<N; ++i)
+            fprintf(fp, " %12g%c", t->rgxbestever[i], 
+                    (i%5==4||i==N-1)?'\n':' ');
+          fprintf(fp, "xbest (of last generation, function value %g)\n", 
+                  t->rgrgx[t->index[0]][N]); 
+          for(i=0; i<N; ++i)
+            fprintf(fp, " %12g%c", t->rgrgx[t->index[0]][i], 
+                    (i%5==4||i==N-1)?'\n':' ');
+          fprintf(fp, "xmean \n");
+          for(i=0; i<N; ++i)
+            fprintf(fp, " %12g%c", t->rgxmean[i], 
+                    (i%5==4||i==N-1)?'\n':' ');
+          fprintf(fp, "Standard deviation of coordinate axes (sigma*sqrt(diag(C)))\n");
+          for(i=0; i<N; ++i)
+            fprintf(fp, " %12g%c", t->sigma*sqrt(t->C[i][i]), 
+                    (i%5==4||i==N-1)?'\n':' ');
+          fprintf(fp, "Main axis lengths of mutation ellipsoid (sigma*diag(D))\n");
+          for (i = 0; i < N; ++i)
+            t->rgdTmp[i] = t->rgD[i];
+          qsort(t->rgdTmp, (unsigned) N, sizeof(double), &SignOfDiff);
+          for(i=0; i<N; ++i)
+            fprintf(fp, " %12g%c", t->sigma*t->rgdTmp[N-1-i], 
+                    (i%5==4||i==N-1)?'\n':' ');
+          fprintf(fp, "Longest axis (b_i where d_ii=max(diag(D))\n");
+          k = MaxIdx(t->rgD, N);
+          for(i=0; i<N; ++i)
+            fprintf(fp, " %12g%c", t->B[i][k], (i%5==4||i==N-1)?'\n':' ');
+          fprintf(fp, "Shortest axis (b_i where d_ii=max(diag(D))\n");
+          k = MinIdx(t->rgD, N);
+          for(i=0; i<N; ++i)
+            fprintf(fp, " %12g%c", t->B[i][k], (i%5==4||i==N-1)?'\n':' ');
+          while (*key != '+' && *key != '\0' && key < keyend)
+            ++key;
+        } /* "all" */
+
+#if 0 /* could become generic part */
+      s0 = key;
+      d = cmaes_Get(t, key); /* TODO find way to detect whether key was found */
+      if (key == s0) /* this does not work, is always true */
+        {
+          /* write out stuff, problem: only generic format is available */
+          /* move in key until "+" or end */
+        }
+#endif 
+
+      if (*key == '\0') 
+        break; 
+      else if (*key != '+') { /* last key was not recognized */
+        ERRORMESSAGE("cmaes_t:WriteToFilePtr(): unrecognized key '", key, "'", 0); 
+        while (*key != '+' && *key != '\0' && key < keyend)
+          ++key;
+      }
+      while (*key == '+') 
+        ++key; 
+    } /* while key < keyend */ 
+
+  if (key > keyend)
+    FATAL("cmaes_t:WriteToFilePtr(): BUG regarding key sequence",0,0,0);
+
+} /* WriteToFilePtr */
+
+/* --------------------------------------------------------- */
+double  
+cmaes_Get( cmaes_t *t, char const *s)
+{
+  int N=t->sp.N;
+
+  if (strncmp(s, "axisratio", 5) == 0) { /* between lengths of longest and shortest principal axis of the distribution ellipsoid */
+    return (rgdouMax(t->rgD, N)/rgdouMin(t->rgD, N));
+  }
+  else if (strncmp(s, "eval", 4) == 0) { /* number of function evaluations */
+    return (t->countevals);
+  }
+  else if (strncmp(s, "fctvalue", 6) == 0
+           || strncmp(s, "funcvalue", 6) == 0
+           || strncmp(s, "funvalue", 6) == 0
+           || strncmp(s, "fitness", 3) == 0) { /* recent best function value */
+    return(t->rgFuncValue[t->index[0]]);
+  }
+  else if (strncmp(s, "fbestever", 7) == 0) { /* ever best function value */
+    return(t->rgxbestever[N]);
+  }
+  else if (strncmp(s, "generation", 3) == 0
+           || strncmp(s, "iteration", 4) == 0) { 
+    return(t->gen);
+  }
+  else if (strncmp(s, "maxeval", 4) == 0
+           || strncmp(s, "MaxFunEvals", 8) == 0
+           || strncmp(s, "stopMaxFunEvals", 12) == 0) { /* maximal number of function evaluations */
+    return(t->sp.stopMaxFunEvals);
+  }
+  else if (strncmp(s, "maxgen", 4) == 0
+           || strncmp(s, "MaxIter", 7) == 0
+           || strncmp(s, "stopMaxIter", 11) == 0) { /* maximal number of generations */
+    return(ceil(t->sp.stopMaxIter));
+  }
+  else if (strncmp(s, "maxaxislength", 5) == 0) { /* sigma * max(diag(D)) */
+    return(t->sigma * sqrt(t->maxEW));
+  }
+  else if (strncmp(s, "minaxislength", 5) == 0) { /* sigma * min(diag(D)) */
+    return(t->sigma * sqrt(t->minEW));
+  }
+  else if (strncmp(s, "maxstddev", 4) == 0) { /* sigma * sqrt(max(diag(C))) */
+    return(t->sigma * sqrt(t->maxdiagC));
+  }
+  else if (strncmp(s, "minstddev", 4) == 0) { /* sigma * sqrt(min(diag(C))) */
+    return(t->sigma * sqrt(t->mindiagC));
+  }
+  else if (strncmp(s, "N", 1) == 0 || strcmp(s, "n") == 0 || 
+           strncmp(s, "dimension", 3) == 0) {
+    return (N);
+  }
+  else if (strncmp(s, "lambda", 3) == 0
+           || strncmp(s, "samplesize", 8) == 0
+           || strncmp(s, "popsize", 7) == 0) { /* sample size, offspring population size */
+    return(t->sp.lambda);
+  }
+  else if (strncmp(s, "sigma", 3) == 0) {
+    return(t->sigma);
+  }
+  FATAL( "cmaes_Get(cmaes_t, char const * s): No match found for s='", s, "'",0);
+  return(0);
+} /* cmaes_Get() */
+
+/* --------------------------------------------------------- */
+double * 
+cmaes_GetInto( cmaes_t *t, char const *s, double *res)
+{
+  int i, N = t->sp.N;
+  double const * res0 = cmaes_GetPtr(t, s);
+  if (res == 0)
+    res = new_double(N);
+  for (i = 0; i < N; ++i)
+    res[i] = res0[i];
+  return res; 
+}
+
+/* --------------------------------------------------------- */
+double * 
+cmaes_GetNew( cmaes_t *t, char const *s)
+{
+  return (cmaes_GetInto(t, s, 0));
+}
+
+/* --------------------------------------------------------- */
+const double * 
+cmaes_GetPtr( cmaes_t *t, char const *s)
+{
+  int i, N=t->sp.N;
+
+  /* diagonal of covariance matrix */
+  if (strncmp(s, "diag(C)", 7) == 0) { 
+    for (i = 0; i < N; ++i)
+      t->rgout[i] = t->C[i][i]; 
+    return(t->rgout);
+  }
+  /* diagonal of axis lengths matrix */
+  else if (strncmp(s, "diag(D)", 7) == 0) { 
+    return(t->rgD);
+  }
+  /* vector of standard deviations sigma*sqrt(diag(C)) */
+  else if (strncmp(s, "stddev", 3) == 0) { 
+    for (i = 0; i < N; ++i)
+      t->rgout[i] = t->sigma * sqrt(t->C[i][i]); 
+    return(t->rgout);
+  }
+  /* bestever solution seen so far */
+  else if (strncmp(s, "xbestever", 7) == 0)
+    return(t->rgxbestever);
+  /* recent best solution of the recent population */
+  else if (strncmp(s, "xbest", 5) == 0)
+    return(t->rgrgx[t->index[0]]);
+  /* mean of the recent distribution */
+  else if (strncmp(s, "xmean", 1) == 0)
+    return(t->rgxmean);
+  
+  return(0);
+}
+
+/* --------------------------------------------------------- */
+/* tests stopping criteria 
+ *   returns a string of satisfied stopping criterion for each line
+ *   otherwise 0 
+*/
+const char *
+cmaes_TestForTermination( cmaes_t *t)
+{
+  double range, fac;
+  int iAchse, iKoo;
+  int flgdiag = ((t->sp.diagonalCov == 1) || (t->sp.diagonalCov >= t->gen)); 
+  static char sTestOutString[3024];
+  char * cp = sTestOutString;
+  int i, cTemp, N=t->sp.N; 
+  cp[0] = '\0';
+
+      /* function value reached */
+      if ((t->gen > 1 || t->state > 1) && t->sp.stStopFitness.flg && 
+          t->rgFuncValue[t->index[0]] <= t->sp.stStopFitness.val) 
+        cp += sprintf(cp, "Fitness: function value %7.2e <= stopFitness (%7.2e)\n", 
+                      t->rgFuncValue[t->index[0]], t->sp.stStopFitness.val);
+      
+      /* TolFun */
+      range = douMax(rgdouMax(t->arFuncValueHist, (int)douMin(t->gen,*(t->arFuncValueHist-1))), 
+                     rgdouMax(t->rgFuncValue, t->sp.lambda)) -
+        douMin(rgdouMin(t->arFuncValueHist, (int)douMin(t->gen, *(t->arFuncValueHist-1))), 
+               rgdouMin(t->rgFuncValue, t->sp.lambda));
+      
+      if (t->gen > 0 && range <= t->sp.stopTolFun) {
+        cp += sprintf(cp, 
+                      "TolFun: function value differences %7.2e < stopTolFun=%7.2e\n", 
+                      range, t->sp.stopTolFun);
+      }
+
+      /* TolFunHist */
+      if (t->gen > *(t->arFuncValueHist-1)) {
+        range = rgdouMax(t->arFuncValueHist, (int)*(t->arFuncValueHist-1)) 
+          - rgdouMin(t->arFuncValueHist, (int)*(t->arFuncValueHist-1));
+        if (range <= t->sp.stopTolFunHist)
+          cp += sprintf(cp, 
+                        "TolFunHist: history of function value changes %7.2e stopTolFunHist=%7.2e", 
+                        range, t->sp.stopTolFunHist);
+      }
+      
+      /* TolX */
+      for(i=0, cTemp=0; i<N; ++i) {
+        cTemp += (t->sigma * sqrt(t->C[i][i]) < t->sp.stopTolX) ? 1 : 0;
+        cTemp += (t->sigma * t->rgpc[i] < t->sp.stopTolX) ? 1 : 0;
+      }
+      if (cTemp == 2*N) {
+        cp += sprintf(cp, 
+                      "TolX: object variable changes below %7.2e \n", 
+                      t->sp.stopTolX);
+      }
+
+      /* TolUpX */
+      for(i=0; i<N; ++i) {
+        if (t->sigma * sqrt(t->C[i][i]) > t->sp.stopTolUpXFactor * t->sp.rgInitialStds[i])
+          break;
+      }
+      if (i < N) {
+        cp += sprintf(cp, 
+                      "TolUpX: standard deviation increased by more than %7.2e, larger initial standard deviation recommended \n", 
+                      t->sp.stopTolUpXFactor);
+      }
+
+      /* Condition of C greater than dMaxSignifKond */
+      if (t->maxEW >= t->minEW * t->dMaxSignifKond) {
+        cp += sprintf(cp, 
+                      "ConditionNumber: maximal condition number %7.2e reached. maxEW=%7.2e,minEW=%7.2e,maxdiagC=%7.2e,mindiagC=%7.2e\n", 
+                      t->dMaxSignifKond, t->maxEW, t->minEW, t->maxdiagC, t->mindiagC);
+      } /* if */
+      
+      /* Principal axis i has no effect on xmean, ie. 
+         x == x + 0.1 * sigma * rgD[i] * B[i] */
+      if (!flgdiag) {
+        for (iAchse = 0; iAchse < N; ++iAchse)
+          {
+            fac = 0.1 * t->sigma * t->rgD[iAchse];
+            for (iKoo = 0; iKoo < N; ++iKoo){ 
+              if (t->rgxmean[iKoo] != t->rgxmean[iKoo] + fac * t->B[iKoo][iAchse])
+                break;
+            }
+            if (iKoo == N)        
+              {
+                /* t->sigma *= exp(0.2+t->sp.cs/t->sp.damps); */
+                cp += sprintf(cp, 
+                              "NoEffectAxis: standard deviation 0.1*%7.2e in principal axis %d without effect\n", 
+                              fac/0.1, iAchse);
+                break;
+              } /* if (iKoo == N) */
+          } /* for iAchse             */
+      } /* if flgdiag */
+      /* Component of xmean is not changed anymore */
+      for (iKoo = 0; iKoo < N; ++iKoo)
+        {
+          if (t->rgxmean[iKoo] == t->rgxmean[iKoo] + 
+              0.2*t->sigma*sqrt(t->C[iKoo][iKoo]))
+            {
+              /* t->C[iKoo][iKoo] *= (1 + t->sp.ccov); */
+              /* flg = 1; */
+              cp += sprintf(cp, 
+                            "NoEffectCoordinate: standard deviation 0.2*%7.2e in coordinate %d without effect\n", 
+                            t->sigma*sqrt(t->C[iKoo][iKoo]), iKoo); 
+              break;
+            }
+          
+        } /* for iKoo */
+      /* if (flg) t->sigma *= exp(0.05+t->sp.cs/t->sp.damps); */
+
+      if(t->countevals >= t->sp.stopMaxFunEvals) 
+        cp += sprintf(cp, "MaxFunEvals: conducted function evaluations %.0f >= %g\n", 
+                      t->countevals, t->sp.stopMaxFunEvals);
+      if(t->gen >= t->sp.stopMaxIter) 
+        cp += sprintf(cp, "MaxIter: number of iterations %.0f >= %g\n", 
+                      t->gen, t->sp.stopMaxIter); 
+      if(t->flgStop)
+        cp += sprintf(cp, "Manual: stop signal read\n");
+
+#if 0
+  else if (0) {
+    for(i=0, cTemp=0; i<N; ++i) {
+      cTemp += (sigma * sqrt(C[i][i]) < stopdx) ? 1 : 0;
+      cTemp += (sigma * rgpc[i] < stopdx) ? 1 : 0;
+    }
+    if (cTemp == 2*N)
+      flgStop = 1;
+  }
+#endif
+
+  if (cp - sTestOutString>320)
+    ERRORMESSAGE("Bug in cmaes_t:Test(): sTestOutString too short",0,0,0);
+
+  if (cp != sTestOutString) {
+    return sTestOutString;
+  }
+
+  return(0);
+  
+} /* cmaes_Test() */
+
+/* --------------------------------------------------------- */
+void cmaes_ReadSignals(cmaes_t *t, char const *filename)
+{
+  const char *s = "signals.par"; 
+  FILE *fp;
+  if (filename == 0)
+    filename = s;
+  fp = fopen( filename, "r"); 
+  if(fp == 0) {
+    return;
+  }
+  cmaes_ReadFromFilePtr( t, fp);
+  fclose(fp);
+}
+/* --------------------------------------------------------- */
+void cmaes_ReadFromFilePtr( cmaes_t *t, FILE *fp)
+/* reading commands e.g. from signals.par file 
+*/
+{
+  const char *keys[15];
+  char s[199], sin1[99], sin2[129], sin3[99], sin4[99];
+  int ikey, ckeys, nb; 
+  double d; 
+  static int flglockprint = 0;
+  static int flglockwrite = 0;
+  static long countiterlastwritten; 
+  static long maxdiffitertowrite; /* to prevent long gaps at the beginning */
+  int flgprinted = 0;
+  int flgwritten = 0; 
+  double deltaprinttime = time(0)-t->printtime; /* using clock instead might not be a good */
+  double deltawritetime = time(0)-t->writetime; /* idea as disc time is not CPU time? */
+  double deltaprinttimefirst = t->firstprinttime ? time(0)-t->firstprinttime : 0; /* time is in seconds!? */
+  double deltawritetimefirst = t->firstwritetime ? time(0)-t->firstwritetime : 0; 
+  if (countiterlastwritten > t->gen) { /* probably restarted */
+    maxdiffitertowrite = 0;
+    countiterlastwritten = 0;
+  }
+
+  keys[0] = " stop%98s %98s";        /* s=="now" or eg "MaxIter+" %lg"-number */
+                                     /* works with and without space */
+  keys[1] = " print %98s %98s";       /* s==keyword for WriteFile */
+  keys[2] = " write %98s %128s %98s"; /* s1==keyword, s2==filename */
+  keys[3] = " check%98s %98s";
+  keys[4] = " maxTimeFractionForEigendecompostion %98s";
+  ckeys = 5; 
+  strcpy(sin2, "tmpcmaes.dat");
+
+  if (cmaes_TestForTermination(t)) 
+    {
+      deltaprinttime = time(0); /* forces printing */
+      deltawritetime = time(0);
+    }
+  while(fgets(s, sizeof(s), fp) != 0)
+    { 
+      if (s[0] == '#' || s[0] == '%') /* skip comments  */
+        continue; 
+      sin1[0] = sin2[0] = sin3[0] = sin4[0] = '\0';
+      for (ikey=0; ikey < ckeys; ++ikey)
+        {
+          if((nb=sscanf(s, keys[ikey], sin1, sin2, sin3, sin4)) >= 1) 
+            {
+              switch(ikey) {
+              case 0 : /* "stop", reads "stop now" or eg. stopMaxIter */
+                if (strncmp(sin1, "now", 3) == 0) 
+                  t->flgStop = 1; 
+                else if (strncmp(sin1, "MaxFunEvals", 11) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) 
+                    t->sp.stopMaxFunEvals = d; 
+                }
+                else if (strncmp(sin1, "MaxIter", 4) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) 
+                    t->sp.stopMaxIter = d; 
+                }
+                else if (strncmp(sin1, "Fitness", 7) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) 
+                    {
+                      t->sp.stStopFitness.flg = 1; 
+                      t->sp.stStopFitness.val = d; 
+                    }
+                }
+                else if (strncmp(sin1, "TolFunHist", 10) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) 
+                    t->sp.stopTolFunHist = d; 
+                }
+                else if (strncmp(sin1, "TolFun", 6) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) 
+                    t->sp.stopTolFun = d; 
+                }
+                else if (strncmp(sin1, "TolX", 4) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) 
+                    t->sp.stopTolX = d; 
+                }
+                else if (strncmp(sin1, "TolUpXFactor", 4) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) 
+                    t->sp.stopTolUpXFactor = d; 
+                }
+                break;
+              case 1 : /* "print" */
+                d = 1; /* default */
+                if (sscanf(sin2, "%lg", &d) < 1 && deltaprinttimefirst < 1)
+                  d = 0; /* default at first time */
+                if (deltaprinttime >= d && !flglockprint) {
+                  cmaes_WriteToFilePtr(t, sin1, stdout);
+                  flgprinted = 1;
+                }
+                if(d < 0) 
+                  flglockprint += 2;
+                break; 
+              case 2 : /* "write" */
+                /* write header, before first generation */
+                if (t->countevals < t->sp.lambda && t->flgresumedone == 0) 
+                  cmaes_WriteToFileAW(t, sin1, sin2, "w"); /* overwrite */
+                d = 0.9; /* default is one with smooth increment of gaps */
+                if (sscanf(sin3, "%lg", &d) < 1 && deltawritetimefirst < 2)
+                  d = 0; /* default is zero for the first second */
+                if(d < 0) 
+                  flglockwrite += 2;
+                if (!flglockwrite) {
+                  if (deltawritetime >= d) {
+                    cmaes_WriteToFile(t, sin1, sin2);
+                    flgwritten = 1; 
+                  } else if (d < 1 
+                             && t->gen-countiterlastwritten > maxdiffitertowrite) {
+                    cmaes_WriteToFile(t, sin1, sin2);
+                    flgwritten = 1; 
+                  }
+                }
+                break; 
+              case 3 : /* check, checkeigen 1 or check eigen 1 */
+                if (strncmp(sin1, "eigen", 5) == 0) {
+                  if (sscanf(sin2, " %lg", &d) == 1) {
+                    if (d > 0)
+                      t->flgCheckEigen = 1;
+                    else
+                      t->flgCheckEigen = 0;
+                  }
+                  else
+                    t->flgCheckEigen = 0;
+                }
+                break;
+              case 4 : /* maxTimeFractionForEigendecompostion */
+                if (sscanf(sin1, " %lg", &d) == 1) 
+                  t->sp.updateCmode.maxtime = d;
+                break; 
+              default :
+                break; 
+              }
+              break; /* for ikey */
+            } /* if line contains keyword */
+        } /* for each keyword */
+    } /* while not EOF of signals.par */
+  if (t->writetime == 0) 
+    t->firstwritetime = time(0); 
+  if (t->printtime == 0)
+    t->firstprinttime = time(0); 
+
+  if (flgprinted)
+    t->printtime = time(0);
+  if (flgwritten) {
+    t->writetime = time(0);
+    if (t->gen-countiterlastwritten > maxdiffitertowrite)
+      ++maxdiffitertowrite; /* smooth prolongation of writing gaps/intervals */
+    countiterlastwritten = (long int) t->gen;
+  }
+  --flglockprint;
+  --flglockwrite;
+  flglockprint = (flglockprint > 0) ? 1 : 0;
+  flglockwrite = (flglockwrite > 0) ? 1 : 0;
+} /*  cmaes_ReadFromFilePtr */ 
+
+/* ========================================================= */
+static int
+Check_Eigen( int N,  double **C, double *diag, double **Q) 
+/* 
+   exhaustive test of the output of the eigendecomposition
+   needs O(n^3) operations 
+
+   writes to error file 
+   returns number of detected inaccuracies 
+*/
+{
+    /* compute Q diag Q^T and Q Q^T to check */
+  int i, j, k, res = 0;
+  double cc, dd; 
+  static char s[324];
+
+  for (i=0; i < N; ++i)
+    for (j=0; j < N; ++j) {
+      for (cc=0.,dd=0., k=0; k < N; ++k) {
+        cc += diag[k] * Q[i][k] * Q[j][k];
+        dd += Q[i][k] * Q[j][k];
+      }
+      /* check here, is the normalization the right one? */
+      if (fabs(cc - C[i>j?i:j][i>j?j:i])/sqrt(C[i][i]*C[j][j]) > 1e-10 
+          && fabs(cc - C[i>j?i:j][i>j?j:i]) > 3e-14) {
+        sprintf(s, "%d %d: %.17e %.17e, %e", 
+                i, j, cc, C[i>j?i:j][i>j?j:i], cc-C[i>j?i:j][i>j?j:i]);
+        ERRORMESSAGE("cmaes_t:Eigen(): imprecise result detected ", 
+                     s, 0, 0);
+        ++res; 
+      }
+      if (fabs(dd - (i==j)) > 1e-10) {
+        sprintf(s, "%d %d %.17e ", i, j, dd);
+        ERRORMESSAGE("cmaes_t:Eigen(): imprecise result detected (Q not orthog.)", 
+                     s, 0, 0);
+        ++res;
+      }
+    }
+  return res; 
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void 
+cmaes_UpdateEigensystem(cmaes_t *t, int flgforce)
+{
+  int i, N = t->sp.N;
+
+  timings_update(&t->eigenTimings);
+
+  if(flgforce == 0) {
+    if (t->flgEigensysIsUptodate == 1)
+      return; 
+
+    /* return on modulo generation number */ 
+    if (t->sp.updateCmode.flgalways == 0 /* not implemented, always ==0 */
+        && t->gen < t->genOfEigensysUpdate + t->sp.updateCmode.modulo
+        )
+      return;
+
+    /* return on time percentage */
+    if (t->sp.updateCmode.maxtime < 1.00 
+        && t->eigenTimings.tictoctime > t->sp.updateCmode.maxtime * t->eigenTimings.totaltime
+        && t->eigenTimings.tictoctime > 0.0002)
+      return; 
+  }
+  timings_tic(&t->eigenTimings);
+
+  Eigen( N, t->C, t->rgD, t->B, t->rgdTmp);
+      
+  timings_toc(&t->eigenTimings);
+
+  /* find largest and smallest eigenvalue, they are supposed to be sorted anyway */
+  t->minEW = rgdouMin(t->rgD, N);
+  t->maxEW = rgdouMax(t->rgD, N);
+
+  if (t->flgCheckEigen)
+    /* needs O(n^3)! writes, in case, error message in error file */ 
+    i = Check_Eigen( N, t->C, t->rgD, t->B);
+  
+#if 0 
+  /* Limit Condition of C to dMaxSignifKond+1 */
+  if (t->maxEW > t->minEW * t->dMaxSignifKond) {
+    ERRORMESSAGE("Warning: Condition number of covariance matrix at upper limit.",
+                 " Consider a rescaling or redesign of the objective function. " ,"","");
+    printf("\nWarning: Condition number of covariance matrix at upper limit\n");
+    tmp = t->maxEW/t->dMaxSignifKond - t->minEW;
+    tmp = t->maxEW/t->dMaxSignifKond;
+    t->minEW += tmp;
+    for (i=0;i<N;++i) {
+      t->C[i][i] += tmp;
+      t->rgD[i] += tmp;
+    }
+  } /* if */
+  t->dLastMinEWgroesserNull = minEW;
+#endif   
+  
+  for (i = 0; i < N; ++i)
+    t->rgD[i] = sqrt(t->rgD[i]);
+  
+  t->flgEigensysIsUptodate = 1;
+  t->genOfEigensysUpdate = t->gen; 
+  
+  return;
+      
+} /* cmaes_UpdateEigensystem() */
+
+
+/* ========================================================= */
+static void 
+Eigen( int N,  double **C, double *diag, double **Q, double *rgtmp)
+/* 
+   Calculating eigenvalues and vectors. 
+   Input: 
+     N: dimension.
+     C: symmetric (1:N)xN-matrix, solely used to copy data to Q
+     niter: number of maximal iterations for QL-Algorithm. 
+     rgtmp: N+1-dimensional vector for temporal use. 
+   Output: 
+     diag: N eigenvalues. 
+     Q: Columns are normalized eigenvectors.
+ */
+{
+  int i, j;
+
+  if (rgtmp == 0) /* was OK in former versions */
+    FATAL("cmaes_t:Eigen(): input parameter double *rgtmp must be non-0", 0,0,0);
+
+  /* copy C to Q */
+  if (C != Q) {
+    for (i=0; i < N; ++i)
+      for (j = 0; j <= i; ++j)
+        Q[i][j] = Q[j][i] = C[i][j];
+  }
+
+#if 0
+    Householder( N, Q, diag, rgtmp);
+    QLalgo( N, diag, Q, 30*N, rgtmp+1);
+#else
+    Householder2( N, Q, diag, rgtmp);
+    QLalgo2( N, diag, rgtmp, Q);
+#endif
+
+}  
+
+
+/* ========================================================= */
+static void 
+QLalgo2 (int n, double *d, double *e, double **V) {
+  /*
+    -> n     : Dimension. 
+    -> d     : Diagonale of tridiagonal matrix. 
+    -> e[1..n-1] : off-diagonal, output from Householder
+    -> V     : matrix output von Householder
+    <- d     : eigenvalues
+    <- e     : garbage?
+    <- V     : basis of eigenvectors, according to d
+
+    Symmetric tridiagonal QL algorithm, iterative 
+    Computes the eigensystem from a tridiagonal matrix in roughtly 3N^3 operations
+    
+    code adapted from Java JAMA package, function tql2. 
+  */
+
+  int i, k, l, m;
+  double f = 0.0;
+  double tst1 = 0.0;
+  double eps = 2.22e-16; /* Math.pow(2.0,-52.0);  == 2.22e-16 */
+  
+      /* shift input e */
+      for (i = 1; i < n; i++) {
+         e[i-1] = e[i];
+      }
+      e[n-1] = 0.0; /* never changed again */
+   
+      for (l = 0; l < n; l++) { 
+
+        /* Find small subdiagonal element */
+   
+         if (tst1 < fabs(d[l]) + fabs(e[l]))
+           tst1 = fabs(d[l]) + fabs(e[l]);
+         m = l;
+         while (m < n) {
+           if (fabs(e[m]) <= eps*tst1) {
+             /* if (fabs(e[m]) + fabs(d[m]+d[m+1]) == fabs(d[m]+d[m+1])) { */
+               break;
+            }
+            m++;
+         }
+   
+         /* If m == l, d[l] is an eigenvalue, */
+         /* otherwise, iterate. */
+   
+         if (m > l) {  /* TODO: check the case m == n, should be rejected here!? */
+            int iter = 0;
+            do { /* while (fabs(e[l]) > eps*tst1); */
+               double dl1, h;
+               double g = d[l];
+               double p = (d[l+1] - g) / (2.0 * e[l]); 
+               double r = myhypot(p, 1.); 
+
+               iter = iter + 1;  /* Could check iteration count here */
+   
+               /* Compute implicit shift */
+   
+               if (p < 0) {
+                  r = -r;
+               }
+               d[l] = e[l] / (p + r);
+               d[l+1] = e[l] * (p + r);
+               dl1 = d[l+1];
+               h = g - d[l];
+               for (i = l+2; i < n; i++) {
+                  d[i] -= h;
+               }
+               f = f + h;
+   
+               /* Implicit QL transformation. */
+   
+               p = d[m];
+             {
+               double c = 1.0;
+               double c2 = c;
+               double c3 = c;
+               double el1 = e[l+1];
+               double s = 0.0;
+               double s2 = 0.0;
+               for (i = m-1; i >= l; i--) {
+                  c3 = c2;
+                  c2 = c;
+                  s2 = s;
+                  g = c * e[i];
+                  h = c * p;
+                  r = myhypot(p, e[i]);
+                  e[i+1] = s * r;
+                  s = e[i] / r;
+                  c = p / r;
+                  p = c * d[i] - s * g;
+                  d[i+1] = h + s * (c * g + s * d[i]);
+   
+                  /* Accumulate transformation. */
+   
+                  for (k = 0; k < n; k++) {
+                     h = V[k][i+1];
+                     V[k][i+1] = s * V[k][i] + c * h;
+                     V[k][i] = c * V[k][i] - s * h;
+                  }
+               }
+               p = -s * s2 * c3 * el1 * e[l] / dl1;
+               e[l] = s * p;
+               d[l] = c * p;
+             }
+   
+               /* Check for convergence. */
+   
+            } while (fabs(e[l]) > eps*tst1);
+         }
+         d[l] = d[l] + f;
+         e[l] = 0.0;
+      }
+     
+      /* Sort eigenvalues and corresponding vectors. */
+#if 1
+      /* TODO: really needed here? So far not, but practical and only O(n^2) */
+      {
+      int j; 
+      double p;
+      for (i = 0; i < n-1; i++) {
+         k = i;
+         p = d[i];
+         for (j = i+1; j < n; j++) {
+            if (d[j] < p) {
+               k = j;
+               p = d[j];
+            }
+         }
+         if (k != i) {
+            d[k] = d[i];
+            d[i] = p;
+            for (j = 0; j < n; j++) {
+               p = V[j][i];
+               V[j][i] = V[j][k];
+               V[j][k] = p;
+            }
+         }
+      }
+      }
+#endif 
+} /* QLalgo2 */ 
+
+
+/* ========================================================= */
+static void 
+Householder2(int n, double **V, double *d, double *e) {
+  /* 
+     Householder transformation of a symmetric matrix V into tridiagonal form. 
+   -> n             : dimension
+   -> V             : symmetric nxn-matrix
+   <- V             : orthogonal transformation matrix:
+                      tridiag matrix == V * V_in * V^t
+   <- d             : diagonal
+   <- e[0..n-1]     : off diagonal (elements 1..n-1) 
+
+   code slightly adapted from the Java JAMA package, function private tred2()  
+
+  */
+
+  int i,j,k; 
+
+      for (j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+      }
+
+      /* Householder reduction to tridiagonal form */
+   
+      for (i = n-1; i > 0; i--) {
+   
+        /* Scale to avoid under/overflow */
+   
+         double scale = 0.0;
+         double h = 0.0;
+         for (k = 0; k < i; k++) {
+            scale = scale + fabs(d[k]);
+         }
+         if (scale == 0.0) {
+            e[i] = d[i-1];
+            for (j = 0; j < i; j++) {
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+               V[j][i] = 0.0;
+            }
+         } else {
+   
+           /* Generate Householder vector */
+
+            double f, g, hh;
+   
+            for (k = 0; k < i; k++) {
+               d[k] /= scale;
+               h += d[k] * d[k];
+            }
+            f = d[i-1];
+            g = sqrt(h);
+            if (f > 0) {
+               g = -g;
+            }
+            e[i] = scale * g;
+            h = h - f * g;
+            d[i-1] = f - g;
+            for (j = 0; j < i; j++) {
+               e[j] = 0.0;
+            }
+   
+            /* Apply similarity transformation to remaining columns */
+   
+            for (j = 0; j < i; j++) {
+               f = d[j];
+               V[j][i] = f;
+               g = e[j] + V[j][j] * f;
+               for (k = j+1; k <= i-1; k++) {
+                  g += V[k][j] * d[k];
+                  e[k] += V[k][j] * f;
+               }
+               e[j] = g;
+            }
+            f = 0.0;
+            for (j = 0; j < i; j++) {
+               e[j] /= h;
+               f += e[j] * d[j];
+            }
+            hh = f / (h + h);
+            for (j = 0; j < i; j++) {
+               e[j] -= hh * d[j];
+            }
+            for (j = 0; j < i; j++) {
+               f = d[j];
+               g = e[j];
+               for (k = j; k <= i-1; k++) {
+                  V[k][j] -= (f * e[k] + g * d[k]);
+               }
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+            }
+         }
+         d[i] = h;
+      }
+   
+      /* Accumulate transformations */
+   
+      for (i = 0; i < n-1; i++) {
+         double h; 
+         V[n-1][i] = V[i][i];
+         V[i][i] = 1.0;
+         h = d[i+1];
+         if (h != 0.0) {
+            for (k = 0; k <= i; k++) {
+               d[k] = V[k][i+1] / h;
+            }
+            for (j = 0; j <= i; j++) {
+               double g = 0.0;
+               for (k = 0; k <= i; k++) {
+                  g += V[k][i+1] * V[k][j];
+               }
+               for (k = 0; k <= i; k++) {
+                  V[k][j] -= g * d[k];
+               }
+            }
+         }
+         for (k = 0; k <= i; k++) {
+            V[k][i+1] = 0.0;
+         }
+      }
+      for (j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+         V[n-1][j] = 0.0;
+      }
+      V[n-1][n-1] = 1.0;
+      e[0] = 0.0;
+
+} /* Housholder() */
+
+
+#if 0
+/* ========================================================= */
+static void
+WriteMaxErrorInfo(cmaes_t *t)
+{
+  int i,j, N=t->sp.N; 
+  char *s = (char *)new_void(200+30*(N+2), sizeof(char)); s[0] = '\0';
+  
+  sprintf( s+strlen(s),"\nKomplett-Info\n");
+  sprintf( s+strlen(s)," Gen       %20.12g\n", t->gen);
+  sprintf( s+strlen(s)," Dimension %d\n", N);
+  sprintf( s+strlen(s)," sigma     %e\n", t->sigma);
+  sprintf( s+strlen(s)," lastminEW %e\n", 
+           t->dLastMinEWgroesserNull);
+  sprintf( s+strlen(s)," maxKond   %e\n\n", t->dMaxSignifKond);
+  sprintf( s+strlen(s),"     x-Vektor          rgD     Basis...\n");
+  ERRORMESSAGE( s,0,0,0);
+  s[0] = '\0';
+  for (i = 0; i < N; ++i)
+    {
+      sprintf( s+strlen(s), " %20.12e", t->rgxmean[i]);
+      sprintf( s+strlen(s), " %10.4e", t->rgD[i]);
+      for (j = 0; j < N; ++j)
+        sprintf( s+strlen(s), " %10.2e", t->B[i][j]);
+      ERRORMESSAGE( s,0,0,0);
+      s[0] = '\0';
+    }
+  ERRORMESSAGE( "\n",0,0,0);
+  free( s);
+} /* WriteMaxErrorInfo() */
+#endif
+
+/* --------------------------------------------------------- */
+/* --------------- Functions: timings_t -------------------- */
+/* --------------------------------------------------------- */
+/* timings_t measures overall time and times between calls
+ * of tic and toc. For small time spans (up to 1000 seconds)
+ * CPU time via clock() is used. For large time spans the
+ * fall-back to elapsed time from time() is used.
+ * timings_update() must be called often enough to prevent
+ * the fallback. */
+/* --------------------------------------------------------- */
+void 
+timings_init(timings_t *t) {
+  t->totaltotaltime = 0; 
+  timings_start(t);
+}
+void 
+timings_start(timings_t *t) {
+  t->totaltime = 0;
+  t->tictoctime = 0;
+  t->lasttictoctime = 0;
+  t->istic = 0;
+  t->lastclock = clock();
+  t->lasttime = time(0);
+  t->lastdiff = 0;
+  t->tictoczwischensumme = 0;
+  t->isstarted = 1;
+}
+
+double 
+timings_update(timings_t *t) {
+/* returns time between last call of timings_*() and now, 
+ *    should better return totaltime or tictoctime? 
+ */
+  double diffc, difft;
+  clock_t lc = t->lastclock; /* measure CPU in 1e-6s */
+  time_t lt = t->lasttime;   /* measure time in s */
+
+  if (t->isstarted != 1)
+    FATAL("timings_started() must be called before using timings... functions",0,0,0);
+
+  t->lastclock = clock(); /* measures at most 2147 seconds, where 1s = 1e6 CLOCKS_PER_SEC */
+  t->lasttime = time(0);
+
+  diffc = (double)(t->lastclock - lc) / CLOCKS_PER_SEC; /* is presumably in [-21??, 21??] */
+  difft = difftime(t->lasttime, lt);                    /* is presumably an integer */
+
+  t->lastdiff = difft; /* on the "save" side */
+
+  /* use diffc clock measurement if appropriate */
+  if (diffc > 0 && difft < 1000)
+    t->lastdiff = diffc;
+
+  if (t->lastdiff < 0)
+    FATAL("BUG in time measurement", 0, 0, 0);
+
+  t->totaltime += t->lastdiff;
+  t->totaltotaltime += t->lastdiff;
+  if (t->istic) {
+    t->tictoczwischensumme += t->lastdiff;
+    t->tictoctime += t->lastdiff;
+  }
+
+  return t->lastdiff; 
+}
+
+void
+timings_tic(timings_t *t) {
+  if (t->istic) { /* message not necessary ? */
+    ERRORMESSAGE("Warning: timings_tic called twice without toc",0,0,0);
+    return; 
+  }
+  timings_update(t); 
+  t->istic = 1; 
+}
+
+double
+timings_toc(timings_t *t) {
+  if (!t->istic) {
+    ERRORMESSAGE("Warning: timings_toc called without tic",0,0,0);
+    return -1; 
+  }
+  timings_update(t);
+  t->lasttictoctime = t->tictoczwischensumme;
+  t->tictoczwischensumme = 0;
+  t->istic = 0;
+  return t->lasttictoctime;
+}
+
+/* --------------------------------------------------------- */
+/* ---------------- Functions: random_t -------------------- */
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+/* X_1 exakt :          0.79788456)  */
+/* chi_eins simuliert : 0.798xx   (seed -3) */
+/*                    +-0.001 */
+/* --------------------------------------------------------- */
+/* 
+   Gauss() liefert normalverteilte Zufallszahlen
+   bei vorgegebenem seed.
+*/
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+
+long 
+random_init( random_t *t, long unsigned inseed)
+{
+  clock_t cloc = clock();
+
+  t->flgstored = 0;
+  t->rgrand = (long *) new_void(32, sizeof(long));
+  if (inseed < 1) {
+    while ((long) (cloc - clock()) == 0)
+      ; /* TODO: remove this for time critical applications? */
+    inseed = (long unsigned)abs(100*time(0)+clock());
+  }
+  return random_Start(t, inseed);
+}
+
+void
+random_exit(random_t *t)
+{
+  free( t->rgrand);
+}
+
+/* --------------------------------------------------------- */
+long random_Start( random_t *t, long unsigned inseed)
+{
+  long tmp;
+  int i;
+
+  t->flgstored = 0;
+  t->startseed = inseed;
+  if (inseed < 1)
+    inseed = 1; 
+  t->aktseed = inseed;
+  for (i = 39; i >= 0; --i)
+  {
+    tmp = t->aktseed/127773;
+    t->aktseed = 16807 * (t->aktseed - tmp * 127773)
+      - 2836 * tmp;
+    if (t->aktseed < 0) t->aktseed += 2147483647;
+    if (i < 32)
+      t->rgrand[i] = t->aktseed;
+  }
+  t->aktrand = t->rgrand[0];
+  return inseed;
+}
+
+/* --------------------------------------------------------- */
+double random_Gauss(random_t *t)
+{
+  double x1, x2, rquad, fac;
+
+  if (t->flgstored)
+  {    
+    t->flgstored = 0;
+    return t->hold;
+  }
+  do 
+  {
+    x1 = 2.0 * random_Uniform(t) - 1.0;
+    x2 = 2.0 * random_Uniform(t) - 1.0;
+    rquad = x1*x1 + x2*x2;
+  } while(rquad >= 1 || rquad <= 0);
+  fac = sqrt(-2.0*log(rquad)/rquad);
+  t->flgstored = 1;
+  t->hold = fac * x1;
+  return fac * x2;
+}
+
+/* --------------------------------------------------------- */
+double random_Uniform( random_t *t)
+{
+  long tmp;
+
+  tmp = t->aktseed/127773;
+  t->aktseed = 16807 * (t->aktseed - tmp * 127773)
+    - 2836 * tmp;
+  if (t->aktseed < 0) 
+    t->aktseed += 2147483647;
+  tmp = t->aktrand / 67108865;
+  t->aktrand = t->rgrand[tmp];
+  t->rgrand[tmp] = t->aktseed;
+  return (double)(t->aktrand)/(2.147483647e9);
+}
+
+static char *
+szCat(const char *sz1, const char*sz2, 
+      const char *sz3, const char *sz4);
+
+/* --------------------------------------------------------- */
+/* -------------- Functions: readpara_t -------------------- */
+/* --------------------------------------------------------- */
+void
+readpara_init (readpara_t *t,
+               int dim, 
+               int inseed, 
+               const double * inxstart, 
+               const double * inrgsigma,
+               int lambda, 
+               const char * filename)
+{
+  int i, N;
+  t->rgsformat = static_cast<const char **>(new_void(55, sizeof(char *)));
+  t->rgpadr = static_cast<void**>(new_void(55, sizeof(void *))); 
+  t->rgskeyar = static_cast<const char**>(new_void(11, sizeof(char *)));
+  t->rgp2adr = static_cast<double***>(new_void(11, sizeof(double **)));
+  t->weigkey = static_cast<char *>(new_void(7, sizeof(char))); 
+
+  /* All scalars:  */
+  i = 0;
+  t->rgsformat[i] = " N %d";        t->rgpadr[i++] = (void *) &t->N; 
+  t->rgsformat[i] = " seed %d";    t->rgpadr[i++] = (void *) &t->seed;
+  t->rgsformat[i] = " stopMaxFunEvals %lg"; t->rgpadr[i++] = (void *) &t->stopMaxFunEvals;
+  t->rgsformat[i] = " stopMaxIter %lg"; t->rgpadr[i++] = (void *) &t->stopMaxIter;
+  t->rgsformat[i] = " stopFitness %lg"; t->rgpadr[i++]=(void *) &t->stStopFitness.val;
+  t->rgsformat[i] = " stopTolFun %lg"; t->rgpadr[i++]=(void *) &t->stopTolFun;
+  t->rgsformat[i] = " stopTolFunHist %lg"; t->rgpadr[i++]=(void *) &t->stopTolFunHist;
+  t->rgsformat[i] = " stopTolX %lg"; t->rgpadr[i++]=(void *) &t->stopTolX;
+  t->rgsformat[i] = " stopTolUpXFactor %lg"; t->rgpadr[i++]=(void *) &t->stopTolUpXFactor;
+  t->rgsformat[i] = " lambda %d";      t->rgpadr[i++] = (void *) &t->lambda;
+  t->rgsformat[i] = " mu %d";          t->rgpadr[i++] = (void *) &t->mu;
+  t->rgsformat[i] = " weights %5s";    t->rgpadr[i++] = (void *) t->weigkey;
+  t->rgsformat[i] = " fac*cs %lg";t->rgpadr[i++] = (void *) &t->cs;
+  t->rgsformat[i] = " fac*damps %lg";   t->rgpadr[i++] = (void *) &t->damps;
+  t->rgsformat[i] = " ccumcov %lg";    t->rgpadr[i++] = (void *) &t->ccumcov;
+  t->rgsformat[i] = " mucov %lg";     t->rgpadr[i++] = (void *) &t->mucov;
+  t->rgsformat[i] = " fac*ccov %lg";  t->rgpadr[i++]=(void *) &t->ccov;
+  t->rgsformat[i] = " diagonalCovarianceMatrix %lg"; t->rgpadr[i++]=(void *) &t->diagonalCov;
+  t->rgsformat[i] = " updatecov %lg"; t->rgpadr[i++]=(void *) &t->updateCmode.modulo;
+  t->rgsformat[i] = " maxTimeFractionForEigendecompostion %lg"; t->rgpadr[i++]=(void *) &t->updateCmode.maxtime;
+  t->rgsformat[i] = " resume %59s";    t->rgpadr[i++] = (void *) t->resumefile;
+  t->rgsformat[i] = " fac*maxFunEvals %lg";   t->rgpadr[i++] = (void *) &t->facmaxeval;
+  t->rgsformat[i] = " fac*updatecov %lg"; t->rgpadr[i++]=(void *) &t->facupdateCmode;
+  t->n1para = i; 
+  t->n1outpara = i-2; /* disregard last parameters in WriteToFile() */
+
+  /* arrays */
+  i = 0;
+  t->rgskeyar[i]  = " typicalX %d";   t->rgp2adr[i++] = &t->typicalX;
+  t->rgskeyar[i]  = " initialX %d";   t->rgp2adr[i++] = &t->xstart;
+  t->rgskeyar[i]  = " initialStandardDeviations %d"; t->rgp2adr[i++] = &t->rgInitialStds;
+  t->rgskeyar[i]  = " diffMinChange %d"; t->rgp2adr[i++] = &t->rgDiffMinChange;
+  t->n2para = i;  
+
+  t->N = dim;
+  t->seed = (unsigned) inseed; 
+  t->xstart = 0; 
+  t->typicalX = 0;
+  t->typicalXcase = 0;
+  t->rgInitialStds = 0; 
+  t->rgDiffMinChange = 0; 
+  t->stopMaxFunEvals = -1;
+  t->stopMaxIter = -1;
+  t->facmaxeval = 1; 
+  t->stStopFitness.flg = -1;
+  t->stopTolFun = 1e-12; 
+  t->stopTolFunHist = 1e-13; 
+  t->stopTolX = 0; /* 1e-11*insigma would also be reasonable */ 
+  t->stopTolUpXFactor = 1e3; 
+
+  t->lambda = lambda;
+  t->mu = -1;
+  t->mucov = -1;
+  t->weights = 0;
+  strcpy(t->weigkey, "log");
+
+  t->cs = -1;
+  t->ccumcov = -1;
+  t->damps = -1;
+  t->ccov = -1;
+
+  t->diagonalCov = 0; /* default is 0, but this might change in future, see below */
+
+  t->updateCmode.modulo = -1;  
+  t->updateCmode.maxtime = -1;
+  t->updateCmode.flgalways = 0;
+  t->facupdateCmode = 1;
+  strcpy(t->resumefile, "_no_");
+
+  if (strcmp(filename, "non") != 0 && strcmp(filename, "writeonly") != 0)
+    readpara_ReadFromFile(t, filename);
+
+  if (t->N <= 0)
+    t->N = dim;
+
+  N = t->N; 
+  if (N == 0)
+    FATAL("readpara_readpara_t(): problem dimension N undefined.\n",
+          "  (no default value available).",0,0); 
+  if (t->xstart == 0 && inxstart == 0 && t->typicalX == 0) {
+    ERRORMESSAGE("Warning: initialX undefined. typicalX = 0.5...0.5 used.","","","");
+    printf("\nWarning: initialX undefined. typicalX = 0.5...0.5 used.\n");
+  }
+  if (t->rgInitialStds == 0 && inrgsigma == 0) {
+    /* FATAL("initialStandardDeviations undefined","","",""); */
+    ERRORMESSAGE("Warning: initialStandardDeviations undefined. 0.3...0.3 used.","","","");
+    printf("\nWarning: initialStandardDeviations. 0.3...0.3 used.\n");
+  }
+
+  if (t->xstart == 0) {
+    t->xstart = new_double(N);
+
+    /* put inxstart into xstart */
+    if (inxstart != 0) { 
+      for (i=0; i<N; ++i)
+        t->xstart[i] = inxstart[i];
+    }
+    /* otherwise use typicalX or default */
+    else {
+      t->typicalXcase = 1;
+      for (i=0; i<N; ++i)
+        t->xstart[i] = (t->typicalX == 0) ? 0.5 : t->typicalX[i]; 
+    }
+  } /* xstart == 0 */
+  
+  if (t->rgInitialStds == 0) {
+    t->rgInitialStds = new_double(N);
+    for (i=0; i<N; ++i)
+      t->rgInitialStds[i] = (inrgsigma == 0) ? 0.3 : inrgsigma[i];
+  }
+
+  readpara_SupplementDefaults(t);
+  if (strcmp(filename, "non") != 0)
+    readpara_WriteToFile(t, "actparcmaes.par", filename);
+} /* readpara_init */
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void readpara_exit(readpara_t *t)
+{
+  if (t->xstart != 0) /* not really necessary */
+    free( t->xstart);
+  if (t->typicalX != 0)
+    free( t->typicalX);
+  if (t->rgInitialStds != 0)
+    free( t->rgInitialStds);
+  if (t->rgDiffMinChange != 0)
+    free( t->rgDiffMinChange);
+  if (t->weights != 0)
+    free( t->weights);
+
+  free(t->rgsformat);
+  free(t->rgpadr);
+  free(t->rgskeyar);
+  free(t->rgp2adr);
+  free(t->weigkey);
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void 
+readpara_ReadFromFile(readpara_t *t, const char * filename)
+{
+  char s[1000];
+	const char *ss = "initials.par";
+  int ipara, i;
+  int size;
+  FILE *fp;
+  if (filename == 0)
+    filename = ss;
+  fp = fopen( filename, "r"); 
+  if(fp == 0) {
+    ERRORMESSAGE("cmaes_ReadFromFile(): could not open '", filename, "'",0);
+    return;
+  }
+  for (ipara=0; ipara < t->n1para; ++ipara)
+    {
+      rewind(fp);
+      while(fgets(s, sizeof(s), fp) != 0)
+        { /* skip comments  */
+          if (s[0] == '#' || s[0] == '%')
+            continue;
+          if(sscanf(s, t->rgsformat[ipara], t->rgpadr[ipara]) == 1) {
+            if (strncmp(t->rgsformat[ipara], " stopFitness ", 13) == 0)
+              t->stStopFitness.flg = 1;
+            break;
+          }
+        }
+    } /* for */
+  if (t->N <= 0)
+    FATAL("readpara_ReadFromFile(): No valid dimension N",0,0,0); 
+  for (ipara=0; ipara < t->n2para; ++ipara)
+    {
+      rewind(fp);
+      while(fgets(s, sizeof(s), fp) != 0) /* read one line */
+        { /* skip comments  */
+          if (s[0] == '#' || s[0] == '%')
+            continue;
+          if(sscanf(s, t->rgskeyar[ipara], &size) == 1) { /* size==number of values to be read */
+            if (size > 0) {
+              *t->rgp2adr[ipara] = new_double(t->N);
+              for (i=0;i<size&&i<t->N;++i) /* start reading next line */
+                if (fscanf(fp, " %lf", &(*t->rgp2adr[ipara])[i]) != 1)
+                  break;
+              if (i<size && i < t->N) {
+                ERRORMESSAGE("readpara_ReadFromFile ", filename, ": ",0); 
+                FATAL( "'", t->rgskeyar[ipara], 
+                       "' not enough values found.\n", 
+                       "   Remove all comments between numbers.");
+              }
+              for (; i < t->N; ++i) /* recycle */
+                (*t->rgp2adr[ipara])[i] = (*t->rgp2adr[ipara])[i%size];
+            }
+          }
+        }  
+    } /* for */
+  fclose(fp);
+  return;
+} /* readpara_ReadFromFile() */
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void
+readpara_WriteToFile(readpara_t *t, const char *filenamedest, 
+                     const char *filenamesource)
+{
+  int ipara, i; 
+  size_t len;
+  time_t ti = time(0);
+  FILE *fp = fopen( filenamedest, "a"); 
+  if(fp == 0) {
+    ERRORMESSAGE("cmaes_WriteToFile(): could not open '", 
+                 filenamedest, "'",0);
+    return;
+  }
+  fprintf(fp, "\n# Read from %s at %s\n", filenamesource, 
+          asctime(localtime(&ti))); /* == ctime() */
+  for (ipara=0; ipara < 1; ++ipara) {
+    fprintf(fp, t->rgsformat[ipara], *(int *)t->rgpadr[ipara]);
+    fprintf(fp, "\n");
+  }
+  for (ipara=0; ipara < t->n2para; ++ipara) {
+    if(*t->rgp2adr[ipara] == 0)
+      continue;
+    fprintf(fp, t->rgskeyar[ipara], t->N);
+    fprintf(fp, "\n");
+    for (i=0; i<t->N; ++i)
+      fprintf(fp, "%7.3g%c", (*t->rgp2adr[ipara])[i], (i%5==4)?'\n':' ');
+    fprintf(fp, "\n");
+  }
+  for (ipara=1; ipara < t->n1outpara; ++ipara) {
+    if (strncmp(t->rgsformat[ipara], " stopFitness ", 13) == 0)
+      if(t->stStopFitness.flg == 0) {
+        fprintf(fp, " stopFitness\n");
+        continue;
+      }
+    len = strlen(t->rgsformat[ipara]);
+    if (t->rgsformat[ipara][len-1] == 'd') /* read integer */
+      fprintf(fp, t->rgsformat[ipara], *(int *)t->rgpadr[ipara]);
+    else if (t->rgsformat[ipara][len-1] == 's') /* read string */
+      fprintf(fp, t->rgsformat[ipara], (char *)t->rgpadr[ipara]);
+    else { 
+      if (strncmp(" fac*", t->rgsformat[ipara], 5) == 0) {
+        fprintf(fp, " ");
+        fprintf(fp, t->rgsformat[ipara]+5, *(double *)t->rgpadr[ipara]);
+      } else
+        fprintf(fp, t->rgsformat[ipara], *(double *)t->rgpadr[ipara]);
+    }
+    fprintf(fp, "\n");
+  } /* for */
+  fprintf(fp, "\n");
+  fclose(fp); 
+} /* readpara_WriteToFile() */
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void 
+readpara_SupplementDefaults(readpara_t *t)
+{
+  double t1, t2;
+  int N = t->N; 
+  clock_t cloc = clock();
+  
+  if (t->seed < 1) {
+    while ((int) (cloc - clock()) == 0)
+      ; /* TODO: remove this for time critical applications!? */
+    t->seed = (unsigned int)abs(100*time(0)+clock());
+  }
+
+  if (t->stStopFitness.flg == -1)
+    t->stStopFitness.flg = 0;
+
+  if (t->lambda < 2)
+    t->lambda = 4+(int)(3*log((double)N));
+  if (t->mu == -1) {
+    t->mu = t->lambda/2; 
+    readpara_SetWeights(t, t->weigkey);
+  }
+  if (t->weights == 0)
+    readpara_SetWeights(t, t->weigkey);
+
+  if (t->cs > 0) /* factor was read */
+    t->cs *= (t->mueff + 2.) / (N + t->mueff + 3.);
+  if (t->cs <= 0 || t->cs >= 1)
+    t->cs = (t->mueff + 2.) / (N + t->mueff + 3.);
+
+  if (t->ccumcov <= 0 || t->ccumcov > 1)
+    t->ccumcov = 4. / (N + 4);
+  
+  if (t->mucov < 1) {
+    t->mucov = t->mueff;
+  }
+  t1 = 2. / ((N+1.4142)*(N+1.4142));
+  t2 = (2.*t->mueff-1.) / ((N+2.)*(N+2.)+t->mueff);
+  t2 = (t2 > 1) ? 1 : t2;
+  t2 = (1./t->mucov) * t1 + (1.-1./t->mucov) * t2;
+  if (t->ccov >= 0) /* ccov holds the read factor */
+    t->ccov *= t2;
+  if (t->ccov < 0 || t->ccov > 1) /* set default in case */
+    t->ccov = t2;
+
+  if (t->diagonalCov == -1)
+    t->diagonalCov = 2 + 100. * N / sqrt((double)t->lambda); 
+
+  if (t->stopMaxFunEvals == -1)  /* may depend on ccov in near future */
+    t->stopMaxFunEvals = t->facmaxeval*900*(N+3)*(N+3); 
+  else
+    t->stopMaxFunEvals *= t->facmaxeval;
+
+  if (t->stopMaxIter == -1)
+    t->stopMaxIter = ceil((double)(t->stopMaxFunEvals / t->lambda)); 
+
+  if (t->damps < 0) 
+    t->damps = 1; /* otherwise a factor was read */
+  t->damps = t->damps 
+    * (1 + 2*douMax(0., sqrt((t->mueff-1.)/(N+1.)) - 1))     /* basic factor */
+    * douMax(0.3, 1. -                                       /* modify for short runs */
+                  (double)N / (1e-6+douMin(t->stopMaxIter, t->stopMaxFunEvals/t->lambda))) 
+    + t->cs;                                                 /* minor increment */
+
+  if (t->updateCmode.modulo < 0)
+    t->updateCmode.modulo = 1./t->ccov/(double)(N)/10.;
+  t->updateCmode.modulo *= t->facupdateCmode;
+  if (t->updateCmode.maxtime < 0)
+    t->updateCmode.maxtime = 0.20; /* maximal 20% of CPU-time */
+
+} /* readpara_SupplementDefaults() */
+
+   
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+void 
+readpara_SetWeights(readpara_t *t, const char * mode)
+{
+  double s1, s2;
+  int i;
+
+  if(t->weights != 0)
+    free( t->weights); 
+  t->weights = new_double(t->mu);
+  if (strcmp(mode, "lin") == 0)
+    for (i=0; i<t->mu; ++i) 
+      t->weights[i] = t->mu - i;
+  else if (strncmp(mode, "equal", 3) == 0)
+    for (i=0; i<t->mu; ++i) 
+      t->weights[i] = 1;
+  else if (strcmp(mode, "log") == 0) 
+    for (i=0; i<t->mu; ++i) 
+      t->weights[i] = log(t->mu+1.)-log(i+1.); 
+  else
+    for (i=0; i<t->mu; ++i) 
+      t->weights[i] = log(t->mu+1.)-log(i+1.); 
+
+  /* normalize weights vector and set mueff */
+  for (i=0, s1=0, s2=0; i<t->mu; ++i) {
+    s1 += t->weights[i];
+    s2 += t->weights[i]*t->weights[i];
+  }
+  t->mueff = s1*s1/s2;
+  for (i=0; i<t->mu; ++i) 
+    t->weights[i] /= s1;
+
+  if(t->mu < 1 || t->mu > t->lambda || 
+     (t->mu==t->lambda && t->weights[0]==t->weights[t->mu-1]))
+    FATAL("readpara_SetWeights(): invalid setting of mu or lambda",0,0,0);
+
+} /* readpara_SetWeights() */
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+static double 
+douSquare(double d)
+{
+  return d*d;
+}
+static int 
+intMin( int i, int j)
+{
+  return i < j ? i : j;
+}
+static double
+douMax( double i, double j)
+{
+  return i > j ? i : j;
+}
+static double
+douMin( double i, double j)
+{
+  return i < j ? i : j;
+}
+static double
+rgdouMax( const double *rgd, int len)
+{
+  int i;
+  double max = rgd[0];
+  for (i = 1; i < len; ++i)
+    max = (max < rgd[i]) ? rgd[i] : max;
+  return max;
+}
+
+static double
+rgdouMin( const double *rgd, int len)
+{
+  int i;
+  double min = rgd[0];
+  for (i = 1; i < len; ++i)
+    min = (min > rgd[i]) ? rgd[i] : min;
+  return min;
+}
+
+static int    
+MaxIdx( const double *rgd, int len)
+{
+  int i, res;
+  for(i=1, res=0; i<len; ++i)
+    if(rgd[i] > rgd[res])
+      res = i;
+  return res;
+}
+static int    
+MinIdx( const double *rgd, int len)
+{
+  int i, res;
+  for(i=1, res=0; i<len; ++i)
+    if(rgd[i] < rgd[res])
+      res = i;
+  return res;
+}
+
+static double 
+myhypot(double a, double b) 
+/* sqrt(a^2 + b^2) numerically stable. */
+{
+  double r = 0;
+  if (fabs(a) > fabs(b)) {
+    r = b/a;
+    r = fabs(a)*sqrt(1+r*r);
+  } else if (b != 0) {
+    r = a/b;
+    r = fabs(b)*sqrt(1+r*r);
+  }
+  return r;
+}
+
+static int SignOfDiff(const void *d1, const void * d2) 
+{ 
+  return *((double *) d1) > *((double *) d2) ? 1 : -1; 
+} 
+
+#if 1
+/* dirty index sort */
+static void Sorted_index(const double *rgFunVal, int *iindex, int n)
+{
+  int i, j;
+  for (i=1, iindex[0]=0; i<n; ++i) {
+    for (j=i; j>0; --j) {
+      if (rgFunVal[iindex[j-1]] < rgFunVal[i])
+        break;
+      iindex[j] = iindex[j-1]; /* shift up */
+    }
+    iindex[j] = i; /* insert i */
+  }
+}
+#endif 
+
+static void * new_void(int n, size_t size)
+{
+  static char s[70];
+  void *p = calloc((unsigned) n, size);
+  if (p == 0) {
+    sprintf(s, "new_void(): calloc(%ld,%ld) failed",(long)n,(long)size);
+    FATAL(s,0,0,0);
+  }
+  return p;
+}
+
+double * 
+cmaes_NewDouble(int n) 
+{
+  return new_double(n);
+}
+
+static double * new_double(int n)
+{
+  static char s[170];
+  double *p = (double *) calloc((unsigned) n, sizeof(double));
+  if (p == 0) {
+    sprintf(s, "new_double(): calloc(%ld,%ld) failed",
+            (long)n,(long)sizeof(double));
+    FATAL(s,0,0,0);
+  }
+  return p;
+}
+
+/* --------------------------------------------------------- */
+/* --------------------------------------------------------- */
+
+/* ========================================================= */
+void 
+cmaes_FATAL(char const *s1, char const *s2, char const *s3, 
+            char const *s4)
+{
+  time_t t = time(0);
+  ERRORMESSAGE( s1, s2, s3, s4);
+  ERRORMESSAGE("*** Exiting cmaes_t ***",0,0,0);
+  printf("\n -- %s %s\n", asctime(localtime(&t)), 
+           s2 ? szCat(s1, s2, s3, s4) : s1);
+  printf(" *** CMA-ES ABORTED, see errcmaes.err *** \n");
+  fflush(stdout);
+  exit(1);
+}
+
+/* ========================================================= */
+static void 
+FATAL(char const *s1, char const *s2, char const *s3, 
+      char const *s4)
+{
+  cmaes_FATAL(s1, s2, s3, s4);
+}
+
+/* ========================================================= */
+void ERRORMESSAGE( char const *s1, char const *s2, 
+                   char const *s3, char const *s4)
+{
+#if 1
+  /*  static char szBuf[700];  desirable but needs additional input argument 
+      sprintf(szBuf, "%f:%f", gen, gen*lambda);
+  */
+  time_t t = time(0);
+  FILE *fp = fopen( "errcmaes.err", "a");
+  if (!fp)
+    {
+      printf("\nFATAL ERROR: %s\n", s2 ? szCat(s1, s2, s3, s4) : s1);
+      printf("cmaes_t could not open file 'errcmaes.err'.");
+      printf("\n *** CMA-ES ABORTED *** ");
+      fflush(stdout);
+      exit(1);
+    }
+  fprintf( fp, "\n -- %s %s\n", asctime(localtime(&t)), 
+           s2 ? szCat(s1, s2, s3, s4) : s1);
+  fclose (fp);
+#endif
+}
+
+/* ========================================================= */
+char *szCat(const char *sz1, const char*sz2, 
+            const char *sz3, const char *sz4)
+{
+  static char szBuf[700];
+
+  if (!sz1)
+    FATAL("szCat() : Invalid Arguments",0,0,0);
+
+  strncpy ((char *)szBuf, sz1, (unsigned)intMin( (int)strlen(sz1), 698));
+  szBuf[intMin( (int)strlen(sz1), 698)] = '\0';
+  if (sz2)
+    strncat ((char *)szBuf, sz2, 
+             (unsigned)intMin((int)strlen(sz2)+1, 698 - (int)strlen((char const *)szBuf)));
+  if (sz3)
+    strncat((char *)szBuf, sz3, 
+            (unsigned)intMin((int)strlen(sz3)+1, 698 - (int)strlen((char const *)szBuf)));
+  if (sz4)
+    strncat((char *)szBuf, sz4, 
+            (unsigned)intMin((int)strlen(sz4)+1, 698 - (int)strlen((char const *)szBuf)));
+  return (char *) szBuf;
+}
+
+
diff --git a/examples++-load/cmaes.h b/examples++-load/cmaes.h
new file mode 100644
index 0000000..7df21f4
--- /dev/null
+++ b/examples++-load/cmaes.h
@@ -0,0 +1,172 @@
+/* --------------------------------------------------------- */
+/* --- File: cmaes.h ----------- Author: Nikolaus Hansen --- */
+/* ---------------------- last modified: IX 2010         --- */
+/* --------------------------------- by: Nikolaus Hansen --- */
+/* --------------------------------------------------------- */
+/*   
+     CMA-ES for non-linear function minimization. 
+
+     Copyright (C) 1996, 2003-2010  Nikolaus Hansen. 
+     e-mail: nikolaus.hansen (you know what) inria.fr
+      
+     License: see file cmaes.c
+   
+*/
+#ifndef NH_cmaes_h /* only include ones */ 
+#define NH_cmaes_h 
+
+#include <time.h>
+
+typedef struct 
+/* random_t 
+ * sets up a pseudo random number generator instance 
+ */
+{
+  /* Variables for Uniform() */
+  long int startseed;
+  long int aktseed;
+  long int aktrand;
+  long int *rgrand;
+  
+  /* Variables for Gauss() */
+  short flgstored;
+  double hold;
+} random_t;
+
+typedef struct 
+/* timings_t 
+ * time measurement, used to time eigendecomposition 
+ */
+{
+  /* for outside use */
+  double totaltime; /* zeroed by calling re-calling timings_start */
+  double totaltotaltime;
+  double tictoctime; 
+  double lasttictoctime;
+  
+  /* local fields */
+  clock_t lastclock;
+  time_t lasttime;
+  clock_t ticclock;
+  time_t tictime;
+  short istic;
+  short isstarted; 
+
+  double lastdiff;
+  double tictoczwischensumme;
+} timings_t;
+
+typedef struct 
+/* readpara_t
+ * collects all parameters, in particular those that are read from 
+ * a file before to start. This should split in future? 
+ */
+{
+  /* input parameter */
+  int N; /* problem dimension, must stay constant */
+  unsigned int seed; 
+  double * xstart; 
+  double * typicalX; 
+  int typicalXcase;
+  double * rgInitialStds;
+  double * rgDiffMinChange; 
+
+  /* termination parameters */
+  double stopMaxFunEvals; 
+  double facmaxeval;
+  double stopMaxIter; 
+  struct { int flg; double val; } stStopFitness; 
+  double stopTolFun;
+  double stopTolFunHist;
+  double stopTolX;
+  double stopTolUpXFactor;
+
+  /* internal evolution strategy parameters */
+  int lambda;          /* -> mu, <- N */
+  int mu;              /* -> weights, (lambda) */
+  double mucov, mueff; /* <- weights */
+  double *weights;     /* <- mu, -> mueff, mucov, ccov */
+  double damps;        /* <- cs, maxeval, lambda */
+  double cs;           /* -> damps, <- N */
+  double ccumcov;      /* <- N */
+  double ccov;         /* <- mucov, <- N */
+  double diagonalCov;  /* number of initial iterations */
+  struct { int flgalways; double modulo; double maxtime; } updateCmode;
+  double facupdateCmode;
+
+  /* supplementary variables */
+
+  char *weigkey; 
+  char resumefile[99];
+  const char **rgsformat;
+  void **rgpadr;
+  const char **rgskeyar;
+  double ***rgp2adr;
+  int n1para, n1outpara;
+  int n2para;
+} readpara_t;
+
+typedef struct 
+/* cmaes_t 
+ * CMA-ES "object" 
+ */
+{
+  const char *version;
+  readpara_t sp;
+  random_t rand; /* random number generator */
+
+  double sigma;  /* step size */
+
+  double *rgxmean;  /* mean x vector, "parent" */
+  double *rgxbestever; 
+  double **rgrgx;   /* range of x-vectors, lambda offspring */
+  int *index;       /* sorting index of sample pop. */
+  double *arFuncValueHist;
+
+  short flgIniphase; /* not really in use anymore */
+  short flgStop; 
+
+  double chiN; 
+  double **C;  /* lower triangular matrix: i>=j for C[i][j] */
+  double **B;  /* matrix with normalize eigenvectors in columns */
+  double *rgD; /* axis lengths */
+
+  double *rgpc;
+  double *rgps;
+  double *rgxold; 
+  double *rgout; 
+  double *rgBDz;   /* for B*D*z */
+  double *rgdTmp;  /* temporary (random) vector used in different places */
+  double *rgFuncValue; 
+  double *publicFitness; /* returned by cmaes_init() */
+
+  double gen; /* Generation number */
+  double countevals;
+  double state; /* 1 == sampled, 2 == not in use anymore, 3 == updated */
+
+  double maxdiagC; /* repeatedly used for output */
+  double mindiagC;
+  double maxEW;
+  double minEW;
+
+  char sOutString[330]; /* 4x80 */
+
+  short flgEigensysIsUptodate;
+  short flgCheckEigen; /* control via signals.par */
+  double genOfEigensysUpdate; 
+  timings_t eigenTimings;
+ 
+  double dMaxSignifKond; 				     
+  double dLastMinEWgroesserNull;
+
+  short flgresumedone; 
+
+  time_t printtime; 
+  time_t writetime; /* ideally should keep track for each output file */
+  time_t firstwritetime;
+  time_t firstprinttime; 
+
+} cmaes_t; 
+
+
+#endif 
diff --git a/examples++-load/cmaes_interface.h b/examples++-load/cmaes_interface.h
new file mode 100644
index 0000000..0c4afc9
--- /dev/null
+++ b/examples++-load/cmaes_interface.h
@@ -0,0 +1,56 @@
+/* --------------------------------------------------------- */
+/* --- File: cmaes_interface.h - Author: Nikolaus Hansen --- */
+/* ---------------------- last modified:  IV 2007        --- */
+/* --------------------------------- by: Nikolaus Hansen --- */
+/* --------------------------------------------------------- */
+/*   
+     CMA-ES for non-linear function minimization. 
+
+     Copyright (C) 1996, 2003, 2007 Nikolaus Hansen. 
+     e-mail: hansen AT bionik.tu-berlin.de
+             hansen AT lri.fr
+
+     License: see file cmaes.c
+*/
+#include "cmaes.h"
+
+/* --------------------------------------------------------- */
+/* ------------------ Interface ---------------------------- */
+/* --------------------------------------------------------- */
+
+/* --- initialization, constructors, destructors --- */
+double * cmaes_init(cmaes_t *, int dimension , double *xstart, 
+		double *stddev, long seed, int lambda, 
+		const char *input_parameter_filename);
+void cmaes_resume_distribution(cmaes_t *evo_ptr, char *filename);
+void cmaes_exit(cmaes_t *);
+
+/* --- core functions --- */
+double * const * cmaes_SamplePopulation(cmaes_t *);
+double *         cmaes_UpdateDistribution(cmaes_t *, 
+					  const double *rgFitnessValues);
+const char *     cmaes_TestForTermination(cmaes_t *);
+
+/* --- additional functions --- */
+double * const * cmaes_ReSampleSingle( cmaes_t *t, int index);
+double const *   cmaes_ReSampleSingle_old(cmaes_t *, double *rgx); 
+double *         cmaes_SampleSingleInto( cmaes_t *t, double *rgx);
+void             cmaes_UpdateEigensystem(cmaes_t *, int flgforce);
+
+/* --- getter functions --- */
+double         cmaes_Get(cmaes_t *, char const *keyword);
+const double * cmaes_GetPtr(cmaes_t *, char const *keyword); /* e.g. "xbestever" */
+double *       cmaes_GetNew( cmaes_t *t, char const *keyword); 
+double *       cmaes_GetInto( cmaes_t *t, char const *keyword, double *mem); 
+
+/* --- online control and output --- */
+void           cmaes_ReadSignals(cmaes_t *, char const *filename);
+void           cmaes_WriteToFile(cmaes_t *, const char *szKeyWord,
+                                 const char *output_filename); 
+char *         cmaes_SayHello(cmaes_t *);
+/* --- misc --- */
+double *       cmaes_NewDouble(int n);  
+void           cmaes_FATAL(char const *s1, char const *s2, char const *s3, 
+			   char const *s4);
+
+
diff --git a/examples++-load/convect_dervieux.edp b/examples++-load/convect_dervieux.edp
new file mode 100644
index 0000000..0ea801c
--- /dev/null
+++ b/examples++-load/convect_dervieux.edp
@@ -0,0 +1,43 @@
+bool fast=true;
+load "mat_dervieux";  // external module in C++ must be loaded
+border a(t=0, 2*pi){ x = cos(t); y = sin(t);  }
+mesh th = buildmesh(a(100));
+fespace Vh(th,P1);
+
+Vh vh,vold,u1 = y, u2 = -x;
+Vh v = exp(-10*((x-0.3)^2 +(y-0.3)^2)), vWall=0, rhs =0;
+
+real dt = 0.025;
+// qf1pTlump means mass lumping is used
+problem  FVM(v,vh) = int2d(th,qft=qf1pTlump)(v*vh/dt)
+                  - int2d(th,qft=qf1pTlump)(vold*vh/dt)
+      + int1d(th,a)(((u1*N.x+u2*N.y)<0)*(u1*N.x+u2*N.y)*vWall*vh)
++ rhs[] ;
+
+
+matrix A;
+MatUpWind1(A,th,vold,[u1,u2]);
+if(fast)
+  {
+    varf  vFVM(v,vh) = int2d(th,qft=qf1pTlump)(v*vh/dt)
+      - int1d(th,a)(((u1*N.x+u2*N.y)<0)*(u1*N.x+u2*N.y)*vWall*vh)      ;
+    real[int] rhs0=vFVM(0,Vh);
+    matrix M=vFVM(Vh,Vh,solver=CG);
+    A=-A+M;
+
+    for ( real t=0; t< pi ; t+=dt)
+      {
+	vold=v;
+        rhs[]=rhs0;
+	rhs[] += A * vold[] ;
+	v[]= M^-1*rhs[];
+	plot(v,wait=0);
+      }
+  }
+else
+for ( real t=0; t< pi ; t+=dt){
+  vold=v;
+  rhs[] = A * vold[] ;
+  FVM;
+  plot(v,wait=0);
+};
diff --git a/examples++-load/convectchacon-3d.edp b/examples++-load/convectchacon-3d.edp
new file mode 100644
index 0000000..008e884
--- /dev/null
+++ b/examples++-load/convectchacon-3d.edp
@@ -0,0 +1,36 @@
+load "msh3"
+load "mat_psi"
+border a(t=0, 2*pi)     {    x = cos(t);    y = sin(t);  };
+mesh th2 = buildmesh(a(70));
+mesh3 th=  buildlayers(th2,5,zbound=[0,1]);
+fespace Vh(th,P1);
+
+Vh vh,vo,u1 = y, u2 = -x, v = exp(-10*((x-0.3)^2 +(y-0.3)^2)), u3=0, rhs =0;
+Vh wh=0,Bwh;
+real dt = 0.001,t=0, tmax=3.14;
+int kk=0;
+varf aa(v,vh) = int3d(th)(v*vh/dt) ;
+matrix  AA= aa(Vh,Vh,solver=UMFPACK);
+
+problem  A(v,vh) = int3d(th)(v*vh/dt)   - int3d(th)(vo*vh/dt) + rhs[];
+
+real[int] viso=[-0.1,0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,10,100,1000];
+verbosity = 4;
+if(1)
+ cout << "\n\n\n  MatUpWind0 3d not yet implemented FH. (To DO) \n\n\n" << endl; 
+else
+for ( t=0; t< tmax ; t+=dt)
+{
+  vo=v;
+  matrix B;
+  MatUpWind0(B,th,vo,[u1,u2,u3]);
+//  cout << B << endl;
+  rhs[] = AA* vo[];
+  rhs[] += B* vo[] ;
+  v[] = AA^-1*rhs[];
+ // wh[][50]=1;
+  //Bwh[] = B*wh[];
+ // plot(wh,Bwh,wait=1);
+  plot(v,fill=1,cmm="convection: t="+t + ", min=" + v[].min + ", max=" +  v[].max,viso=viso,wait=0);
+};
+plot(v,wait=1,value=1,fill=1);
diff --git a/examples++-load/convectchacon.edp b/examples++-load/convectchacon.edp
new file mode 100644
index 0000000..65b3f8c
--- /dev/null
+++ b/examples++-load/convectchacon.edp
@@ -0,0 +1,32 @@
+load "mat_psi"
+border a(t=0, 2*pi)     {    x = cos(t);    y = sin(t);  };
+mesh th = buildmesh(a(70));
+fespace Vh(th,P1);
+
+Vh vh,vo,u1 = y, u2 = -x, v = exp(-10*((x-0.3)^2 +(y-0.3)^2)), rhs =0;
+Vh wh=0,Bwh;
+real dt = 0.001,t=0, tmax=pi/4;
+int kk=0;
+varf aa(v,vh) = int2d(th)(v*vh/dt) ;
+matrix  AA= aa(Vh,Vh,solver=CG);
+
+problem  A(v,vh) = int2d(th)(v*vh/dt)   - int2d(th)(vo*vh/dt) + rhs[];
+
+real[int] viso=[-0.1,0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1,10,100,1000];
+verbosity = 4;
+for ( t=0; t< tmax ; t+=dt)
+{
+  vo[]=v[];
+  matrix B;
+  MatUpWind0(B,th,vo,[u1,u2]);
+//  cout << B << endl;
+  rhs[] = B* vo[] ;
+  rhs[] = -rhs[] ;
+  rhs[] += AA* vo[];
+  v[] = AA^-1*rhs[];
+ // wh[][50]=1;
+  //Bwh[] = B*wh[];
+ // plot(wh,Bwh,wait=1);
+  plot(v,fill=1,dim=3,cmm="convection: t="+t + ", min=" + v[].min + ", max=" +  v[].max,viso=viso,wait=0);
+};
+plot(v,dim=3,wait=1,value=1,fill=1);
diff --git a/examples++-load/convexehull3d.edp b/examples++-load/convexehull3d.edp
new file mode 100644
index 0000000..bd4ffb6
--- /dev/null
+++ b/examples++-load/convexehull3d.edp
@@ -0,0 +1,4 @@
+load "tetgen" 
+
+mesh3 Th=tetgconvexhull("ch.pts",region=1,label=3);//,reftet=1, refface=1);
+plot(Th);
diff --git a/examples++-load/cube.msh b/examples++-load/cube.msh
new file mode 100644
index 0000000..cd8c2c7
--- /dev/null
+++ b/examples++-load/cube.msh
@@ -0,0 +1,585 @@
+$MeshFormat
+2 0 8
+$EndMeshFormat
+$Nodes
+93
+1 0 0 0
+2 1 0 0
+3 1 1 0
+4 0 1 0
+5 1 1 1
+6 1 0 1
+7 0 0 1
+8 0 1 1
+9 0.3333333333326071 1 0
+10 0.6666666666658988 1 0
+11 1 0.6666666666673606 0
+12 1 0.3333333333344899 0
+13 0.6666666666673606 0 0
+14 0.3333333333344899 0 0
+15 0 0.3333333333326071 0
+16 0 0.6666666666658988 0
+17 1 0.6666666666673606 1
+18 1 0.3333333333344899 1
+19 0.6666666666673606 0 1
+20 0.3333333333344899 0 1
+21 0 0.3333333333326071 1
+22 0 0.6666666666658988 1
+23 0.3333333333326071 1 1
+24 0.6666666666658988 1 1
+25 1 1 0.3333333333326071
+26 1 1 0.6666666666658988
+27 1 0 0.3333333333326071
+28 1 0 0.6666666666658988
+29 0 0 0.3333333333326071
+30 0 0 0.6666666666658988
+31 0 1 0.3333333333326071
+32 0 1 0.6666666666658988
+33 0.6033987166763249 0.3101885670465382 0
+34 0.769851917280195 0.6582487583463627 0
+35 0.3956160891556272 0.684861250769156 0
+36 0.2293953234680604 0.3255914299923437 0
+37 0.8175163458359214 0.160880475095257 0
+38 0.1822373556220586 0.8378819793587637 0
+39 1 0.287795406903777 0.5162592383367501
+40 1 0.677749446674222 0.738440154311957
+41 1 0.5497854121514134 0.323956695317194
+42 1 0.2394619452145299 0.250885368529923
+43 1 0.8121736384318632 0.4458127032587921
+44 1 0.8057251434501275 0.2206205463817186
+45 1 0.2597756373824978 0.7842732118629211
+46 0.2696653904235826 0 0.507567042174021
+47 0.5089518016469133 0 0.7191309942205057
+48 0.525787937742471 0 0.4230502036065255
+49 0.2335074533456678 0 0.7829029531710534
+50 0.3755409516430834 0 0.2043738922542082
+51 0.7835677343427908 0 0.5236968663041317
+52 0.7918372405314129 0 0.7818989054381073
+53 0.7252605483992843 0 0.2474090492495787
+54 0 0.3189361886297027 0.471090130118638
+55 0 0.3345786853318198 0.754826829805717
+56 0 0.6844037619596788 0.6088816240370495
+57 0 0.6368173167452134 0.2516230284835886
+58 0 0.8377676071563944 0.818887072675737
+59 0 0.825870995852778 0.1462390904540489
+60 0 0.2578173677415044 0.2112092983869667
+61 0.4659615515276305 1 0.341076738349146
+62 0.3561903612622483 1 0.7764212397445254
+63 0.7139534585284268 1 0.6680916643257201
+64 0.2048376520554457 1 0.4577750407509648
+65 0.8077636127869927 1 0.334861400445562
+66 0.2079004435473459 1 0.2273791342858121
+67 0.6033987166763249 0.3101885670465382 1
+68 0.769851917280195 0.6582487583463627 1
+69 0.3956160891556272 0.684861250769156 1
+70 0.2293953234680604 0.3255914299923437 1
+71 0.8175163458359214 0.160880475095257 1
+72 0.1822373556220586 0.8378819793587637 1
+73 0.5181254719613425 0.512820448991764 0.5222218545365421
+74 0.3161690575272439 0.3126655926137832 0.3311497441358422
+75 0.6360818500851182 0.7210360273959794 0.295034021342571
+76 0.3094461830608684 0.7044061796974738 0.3498323752432158
+77 0.3209010156600531 0.3026010954511582 0.6834725753627503
+78 0.7447276689998517 0.456432312236522 0.7473314440265498
+79 0.6879655308338695 0.3191317587205752 0.3177242488758017
+80 0.3112472585627467 0.6934967487277688 0.6896867215854406
+81 0.6070665682496384 0.7278138857821207 0.7524393983227856
+82 0.7794358175012712 0.6486911468986005 0.5348728099974022
+83 0.2253693732805382 0.5144212358631581 0.1856217218953246
+84 0.5064007851930725 0.4934742660593801 0.1909006305043531
+85 0.2116040567831997 0.4985313910731254 0.5138492930908205
+86 0.6138237354943221 0.2436572730156315 0.5921353831639898
+87 0.1896271624975805 0.1335106123291861 0.1362237629249333
+88 0.4772199555576193 0.4900582817265309 0.818091543605002
+89 0.16317799408501 0.5287352311465979 0.8393348531998897
+90 0.5007595428173509 0.7973624929334675 0.514992099280024
+91 0.41357779735851 0.2266192142511251 0.1261314227295705
+92 0.09287798162604473 0.7907426563470528 0.4129188738729443
+93 0.7952502473596437 0.4322708451082602 0.1157419828834438
+$EndNodes
+$Elements
+483
+1 15 3 0 1 0 1
+2 15 3 0 2 0 2
+3 15 3 0 3 0 3
+4 15 3 0 4 0 4
+5 15 3 0 5 0 5
+6 15 3 0 6 0 6
+7 15 3 0 10 0 7
+8 15 3 0 14 0 8
+9 1 3 0 1 0 4 9
+10 1 3 0 1 0 9 10
+11 1 3 0 1 0 10 3
+12 1 3 0 2 0 3 11
+13 1 3 0 2 0 11 12
+14 1 3 0 2 0 12 2
+15 1 3 0 3 0 2 13
+16 1 3 0 3 0 13 14
+17 1 3 0 3 0 14 1
+18 1 3 0 4 0 1 15
+19 1 3 0 4 0 15 16
+20 1 3 0 4 0 16 4
+21 1 3 0 8 0 5 17
+22 1 3 0 8 0 17 18
+23 1 3 0 8 0 18 6
+24 1 3 0 9 0 6 19
+25 1 3 0 9 0 19 20
+26 1 3 0 9 0 20 7
+27 1 3 0 10 0 7 21
+28 1 3 0 10 0 21 22
+29 1 3 0 10 0 22 8
+30 1 3 0 11 0 8 23
+31 1 3 0 11 0 23 24
+32 1 3 0 11 0 24 5
+33 1 3 0 13 0 3 25
+34 1 3 0 13 0 25 26
+35 1 3 0 13 0 26 5
+36 1 3 0 14 0 2 27
+37 1 3 0 14 0 27 28
+38 1 3 0 14 0 28 6
+39 1 3 0 18 0 1 29
+40 1 3 0 18 0 29 30
+41 1 3 0 18 0 30 7
+42 1 3 0 22 0 4 31
+43 1 3 0 22 0 31 32
+44 1 3 0 22 0 32 8
+45 2 3 0 6 0 34 10 3
+46 2 3 0 6 0 35 9 10
+47 2 3 0 6 0 10 34 35
+48 2 3 0 6 0 12 2 37
+49 2 3 0 6 0 34 11 12
+50 2 3 0 6 0 12 33 34
+51 2 3 0 6 0 37 33 12
+52 2 3 0 6 0 9 38 4
+53 2 3 0 6 0 38 16 4
+54 2 3 0 6 0 34 3 11
+55 2 3 0 6 0 37 2 13
+56 2 3 0 6 0 1 15 36
+57 2 3 0 6 0 36 14 1
+58 2 3 0 6 0 33 13 14
+59 2 3 0 6 0 13 33 37
+60 2 3 0 6 0 15 16 36
+61 2 3 0 6 0 9 35 38
+62 2 3 0 6 0 16 38 35
+63 2 3 0 6 0 33 35 34
+64 2 3 0 6 0 33 36 35
+65 2 3 0 6 0 35 36 16
+66 2 3 0 6 0 14 36 33
+67 2 3 0 15 0 2 42 12
+68 2 3 0 15 0 11 12 41
+69 2 3 0 15 0 12 42 41
+70 2 3 0 15 0 18 45 6
+71 2 3 0 15 0 45 28 6
+72 2 3 0 15 0 11 44 3
+73 2 3 0 15 0 3 44 25
+74 2 3 0 15 0 42 2 27
+75 2 3 0 15 0 40 17 5
+76 2 3 0 15 0 40 5 26
+77 2 3 0 15 0 11 41 44
+78 2 3 0 15 0 18 40 45
+79 2 3 0 15 0 17 40 18
+80 2 3 0 15 0 41 39 40
+81 2 3 0 15 0 41 40 43
+82 2 3 0 15 0 45 40 39
+83 2 3 0 15 0 40 26 43
+84 2 3 0 15 0 41 43 44
+85 2 3 0 15 0 41 42 39
+86 2 3 0 15 0 43 25 44
+87 2 3 0 15 0 28 45 39
+88 2 3 0 15 0 42 27 39
+89 2 3 0 15 0 27 28 39
+90 2 3 0 15 0 43 26 25
+91 2 3 0 19 0 6 52 19
+92 2 3 0 19 0 6 28 52
+93 2 3 0 19 0 2 13 53
+94 2 3 0 19 0 2 53 27
+95 2 3 0 19 0 1 50 14
+96 2 3 0 19 0 1 29 50
+97 2 3 0 19 0 49 7 20
+98 2 3 0 19 0 49 30 7
+99 2 3 0 19 0 13 14 50
+100 2 3 0 19 0 13 50 53
+101 2 3 0 19 0 48 47 51
+102 2 3 0 19 0 48 51 53
+103 2 3 0 19 0 50 46 48
+104 2 3 0 19 0 48 46 47
+105 2 3 0 19 0 50 48 53
+106 2 3 0 19 0 46 49 47
+107 2 3 0 19 0 30 49 46
+108 2 3 0 19 0 47 49 20
+109 2 3 0 19 0 51 47 52
+110 2 3 0 19 0 53 51 27
+111 2 3 0 19 0 51 28 27
+112 2 3 0 19 0 52 28 51
+113 2 3 0 19 0 29 46 50
+114 2 3 0 19 0 46 29 30
+115 2 3 0 19 0 19 47 20
+116 2 3 0 19 0 52 47 19
+117 2 3 0 23 0 4 59 16
+118 2 3 0 23 0 4 31 59
+119 2 3 0 23 0 1 15 60
+120 2 3 0 23 0 60 29 1
+121 2 3 0 23 0 7 55 21
+122 2 3 0 23 0 7 30 55
+123 2 3 0 23 0 8 22 58
+124 2 3 0 23 0 58 32 8
+125 2 3 0 23 0 57 60 15
+126 2 3 0 23 0 57 15 16
+127 2 3 0 23 0 56 55 54
+128 2 3 0 23 0 30 54 55
+129 2 3 0 23 0 56 22 55
+130 2 3 0 23 0 22 21 55
+131 2 3 0 23 0 56 58 22
+132 2 3 0 23 0 32 58 56
+133 2 3 0 23 0 60 57 54
+134 2 3 0 23 0 29 60 54
+135 2 3 0 23 0 56 54 57
+136 2 3 0 23 0 56 57 31
+137 2 3 0 23 0 16 59 57
+138 2 3 0 23 0 59 31 57
+139 2 3 0 23 0 30 29 54
+140 2 3 0 23 0 31 32 56
+141 2 3 0 27 0 3 65 10
+142 2 3 0 27 0 9 10 61
+143 2 3 0 27 0 10 65 61
+144 2 3 0 27 0 66 4 9
+145 2 3 0 27 0 66 31 4
+146 2 3 0 27 0 65 3 25
+147 2 3 0 27 0 5 24 63
+148 2 3 0 27 0 26 5 63
+149 2 3 0 27 0 8 62 23
+150 2 3 0 27 0 8 32 62
+151 2 3 0 27 0 9 61 66
+152 2 3 0 27 0 63 62 61
+153 2 3 0 27 0 62 64 61
+154 2 3 0 27 0 62 24 23
+155 2 3 0 27 0 24 62 63
+156 2 3 0 27 0 32 64 62
+157 2 3 0 27 0 61 65 63
+158 2 3 0 27 0 61 64 66
+159 2 3 0 27 0 63 65 26
+160 2 3 0 27 0 25 26 65
+161 2 3 0 27 0 66 64 31
+162 2 3 0 27 0 31 64 32
+163 2 3 0 28 0 18 6 71
+164 2 3 0 28 0 19 71 6
+165 2 3 0 28 0 5 17 68
+166 2 3 0 28 0 68 24 5
+167 2 3 0 28 0 20 7 70
+168 2 3 0 28 0 70 7 21
+169 2 3 0 28 0 72 22 8
+170 2 3 0 28 0 23 72 8
+171 2 3 0 28 0 68 18 67
+172 2 3 0 28 0 18 68 17
+173 2 3 0 28 0 67 18 71
+174 2 3 0 28 0 67 69 68
+175 2 3 0 28 0 24 68 69
+176 2 3 0 28 0 69 22 72
+177 2 3 0 28 0 23 69 72
+178 2 3 0 28 0 67 71 19
+179 2 3 0 28 0 70 67 20
+180 2 3 0 28 0 67 70 69
+181 2 3 0 28 0 22 70 21
+182 2 3 0 28 0 69 70 22
+183 2 3 0 28 0 67 19 20
+184 2 3 0 28 0 23 24 69
+185 4 3 0 1 0 70 67 20 77
+186 4 3 0 1 0 35 9 66 76
+187 4 3 0 1 0 70 22 69 89
+188 4 3 0 1 0 71 45 52 78
+189 4 3 0 1 0 21 49 55 70
+190 4 3 0 1 0 9 61 66 76
+191 4 3 0 1 0 40 68 63 81
+192 4 3 0 1 0 62 32 64 80
+193 4 3 0 1 0 50 1 29 87
+194 4 3 0 1 0 62 58 32 80
+195 4 3 0 1 0 8 62 58 32
+196 4 3 0 1 0 71 78 52 86
+197 4 3 0 1 0 80 32 64 92
+198 4 3 0 1 0 10 44 65 75
+199 4 3 0 1 0 67 47 20 77
+200 4 3 0 1 0 35 66 9 38
+201 4 3 0 1 0 55 56 22 89
+202 4 3 0 1 0 9 35 61 76
+203 4 3 0 1 0 68 18 67 78
+204 4 3 0 1 0 78 39 79 82
+205 4 3 0 1 0 62 8 58 72
+206 4 3 0 1 0 82 65 75 90
+207 4 3 0 1 0 67 71 52 86
+208 4 3 0 1 0 63 65 43 82
+209 4 3 0 1 0 38 35 66 76
+210 4 3 0 1 0 63 5 68 40
+211 4 3 0 1 0 18 68 17 78
+212 4 3 0 1 0 76 57 59 83
+213 4 3 0 1 0 78 71 67 86
+214 4 3 0 1 0 78 45 52 86
+215 4 3 0 1 0 38 76 59 83
+216 4 3 0 1 0 65 44 43 75
+217 4 3 0 1 0 18 40 45 78
+218 4 3 0 1 0 67 70 69 88
+219 4 3 0 1 0 40 18 17 78
+220 4 3 0 1 0 52 67 19 71
+221 4 3 0 1 0 33 35 36 84
+222 4 3 0 1 0 80 56 32 92
+223 4 3 0 1 0 23 72 8 62
+224 4 3 0 1 0 65 82 63 90
+225 4 3 0 1 0 49 70 20 77
+226 4 3 0 1 0 45 51 52 86
+227 4 3 0 1 0 60 74 29 87
+228 4 3 0 1 0 34 35 33 84
+229 4 3 0 1 0 65 75 43 82
+230 4 3 0 1 0 45 40 39 78
+231 4 3 0 1 0 44 10 34 75
+232 4 3 0 1 0 61 35 75 76
+233 4 3 0 1 0 57 38 59 83
+234 4 3 0 1 0 40 39 78 82
+235 4 3 0 1 0 13 33 14 91
+236 4 3 0 1 0 1 14 36 87
+237 4 3 0 1 0 12 33 37 93
+238 4 3 0 1 0 49 55 70 77
+239 4 3 0 1 0 68 67 69 88
+240 4 3 0 1 0 62 61 63 90
+241 4 3 0 1 0 41 44 34 75
+242 4 3 0 1 0 60 15 57 83
+243 4 3 0 1 0 58 56 32 80
+244 4 3 0 1 0 60 57 54 83
+245 4 3 0 1 0 16 15 36 83
+246 4 3 0 1 0 78 82 79 86
+247 4 3 0 1 0 38 66 59 76
+248 4 3 0 1 0 62 72 58 80
+249 4 3 0 1 0 67 52 19 47
+250 4 3 0 1 0 67 19 20 47
+251 4 3 0 1 0 57 15 16 83
+252 4 3 0 1 0 45 52 51 28
+253 4 3 0 1 0 5 68 40 17
+254 4 3 0 1 0 39 78 79 86
+255 4 3 0 1 0 40 41 39 82
+256 4 3 0 1 0 16 59 57 38
+257 4 3 0 1 0 54 55 30 77
+258 4 3 0 1 0 49 70 21 7
+259 4 3 0 1 0 61 35 9 10
+260 4 3 0 1 0 41 75 79 82
+261 4 3 0 1 0 38 57 16 83
+262 4 3 0 1 0 47 49 20 77
+263 4 3 0 1 0 61 62 64 90
+264 4 3 0 1 0 51 45 39 86
+265 4 3 0 1 0 46 54 30 77
+266 4 3 0 1 0 46 74 77 86
+267 4 3 0 1 0 49 7 21 55
+268 4 3 0 1 0 13 50 53 91
+269 4 3 0 1 0 44 41 43 75
+270 4 3 0 1 0 18 71 67 78
+271 4 3 0 1 0 63 68 24 81
+272 4 3 0 1 0 55 49 30 77
+273 4 3 0 1 0 75 41 79 93
+274 4 3 0 1 0 47 67 52 86
+275 4 3 0 1 0 69 62 23 24
+276 4 3 0 1 0 50 46 74 87
+277 4 3 0 1 0 70 67 77 88
+278 4 3 0 1 0 60 54 29 74
+279 4 3 0 1 0 71 18 45 78
+280 4 3 0 1 0 34 41 75 93
+281 4 3 0 1 0 39 41 79 82
+282 4 3 0 1 0 82 78 73 86
+283 4 3 0 1 0 74 46 29 87
+284 4 3 0 1 0 35 10 61 75
+285 4 3 0 1 0 67 47 77 86
+286 4 3 0 1 0 46 48 74 86
+287 4 3 0 1 0 46 74 54 77
+288 4 3 0 1 0 62 80 64 90
+289 4 3 0 1 0 28 39 51 45
+290 4 3 0 1 0 75 41 43 82
+291 4 3 0 1 0 57 54 83 85
+292 4 3 0 1 0 82 73 79 86
+293 4 3 0 1 0 33 13 53 91
+294 4 3 0 1 0 22 70 21 89
+295 4 3 0 1 0 54 57 56 85
+296 4 3 0 1 0 49 46 30 77
+297 4 3 0 1 0 5 63 68 24
+298 4 3 0 1 0 50 13 14 91
+299 4 3 0 1 0 48 74 79 91
+300 4 3 0 1 0 67 86 77 88
+301 4 3 0 1 0 63 40 26 5
+302 4 3 0 1 0 50 48 53 91
+303 4 3 0 1 0 10 35 34 75
+304 4 3 0 1 0 76 66 59 92
+305 4 3 0 1 0 39 45 78 86
+306 4 3 0 1 0 35 38 16 83
+307 4 3 0 1 0 40 26 43 82
+308 4 3 0 1 0 76 80 64 92
+309 4 3 0 1 0 41 40 43 82
+310 4 3 0 1 0 25 65 43 26
+311 4 3 0 1 0 51 42 53 79
+312 4 3 0 1 0 38 35 76 83
+313 4 3 0 1 0 57 76 59 92
+314 4 3 0 1 0 13 33 53 37
+315 4 3 0 1 0 11 41 44 34
+316 4 3 0 1 0 54 46 29 74
+317 4 3 0 1 0 55 22 21 89
+318 4 3 0 1 0 65 3 25 44
+319 4 3 0 1 0 74 60 54 83
+320 4 3 0 1 0 34 11 3 44
+321 4 3 0 1 0 42 53 27 51
+322 4 3 0 1 0 35 83 36 84
+323 4 3 0 1 0 40 81 63 82
+324 4 3 0 1 0 68 40 17 78
+325 4 3 0 1 0 69 62 24 81
+326 4 3 0 1 0 42 51 39 79
+327 4 3 0 1 0 12 11 34 93
+328 4 3 0 1 0 48 50 74 91
+329 4 3 0 1 0 48 79 53 91
+330 4 3 0 1 0 74 48 79 86
+331 4 3 0 1 0 26 63 43 82
+332 4 3 0 1 0 79 33 53 91
+333 4 3 0 1 0 44 3 10 65
+334 4 3 0 1 0 35 34 75 84
+335 4 3 0 1 0 61 65 63 90
+336 4 3 0 1 0 74 60 36 87
+337 4 3 0 1 0 75 73 79 82
+338 4 3 0 1 0 80 76 64 90
+339 4 3 0 1 0 33 84 36 91
+340 4 3 0 1 0 72 58 80 89
+341 4 3 0 1 0 61 10 65 75
+342 4 3 0 1 0 2 53 27 37
+343 4 3 0 1 0 42 27 37 2
+344 4 3 0 1 0 33 53 37 79
+345 4 3 0 1 0 72 62 69 80
+346 4 3 0 1 0 43 63 26 65
+347 4 3 0 1 0 76 74 83 84
+348 4 3 0 1 0 80 62 69 81
+349 4 3 0 1 0 23 69 72 62
+350 4 3 0 1 0 65 61 75 90
+351 4 3 0 1 0 60 74 36 83
+352 4 3 0 1 0 34 10 44 3
+353 4 3 0 1 0 70 49 20 7
+354 4 3 0 1 0 46 50 29 87
+355 4 3 0 1 0 42 53 37 27
+356 4 3 0 1 0 73 74 76 84
+357 4 3 0 1 0 68 78 67 88
+358 4 3 0 1 0 68 40 78 81
+359 4 3 0 1 0 7 55 49 30
+360 4 3 0 1 0 53 42 37 79
+361 4 3 0 1 0 40 63 26 82
+362 4 3 0 1 0 54 74 83 85
+363 4 3 0 1 0 51 42 39 27
+364 4 3 0 1 0 11 41 34 93
+365 4 3 0 1 0 35 75 76 84
+366 4 3 0 1 0 46 48 50 74
+367 4 3 0 1 0 33 34 84 93
+368 4 3 0 1 0 51 39 79 86
+369 4 3 0 1 0 74 54 77 85
+370 4 3 0 1 0 68 69 24 81
+371 4 3 0 1 0 84 75 79 93
+372 4 3 0 1 0 85 57 56 92
+373 4 3 0 1 0 74 73 76 85
+374 4 3 0 1 0 22 72 69 89
+375 4 3 0 1 0 11 12 41 93
+376 4 3 0 1 0 74 73 77 86
+377 4 3 0 1 0 76 57 83 85
+378 4 3 0 1 0 78 86 67 88
+379 4 3 0 1 0 88 70 69 89
+380 4 3 0 1 0 15 1 36 87
+381 4 3 0 1 0 74 76 83 85
+382 4 3 0 1 0 73 74 79 86
+383 4 3 0 1 0 81 62 63 90
+384 4 3 0 1 0 81 68 69 88
+385 4 3 0 1 0 47 46 77 86
+386 4 3 0 1 0 73 75 79 84
+387 4 3 0 1 0 56 58 22 89
+388 4 3 0 1 0 54 46 30 29
+389 4 3 0 1 0 57 85 76 92
+390 4 3 0 1 0 40 78 81 82
+391 4 3 0 1 0 55 54 56 85
+392 4 3 0 1 0 79 42 37 93
+393 4 3 0 1 0 84 34 75 93
+394 4 3 0 1 0 2 53 37 13
+395 4 3 0 1 0 52 6 45 71
+396 4 3 0 1 0 55 85 56 89
+397 4 3 0 1 0 15 60 36 83
+398 4 3 0 1 0 6 52 45 28
+399 4 3 0 1 0 58 72 22 89
+400 4 3 0 1 0 62 63 24 81
+401 4 3 0 1 0 62 81 80 90
+402 4 3 0 1 0 48 46 47 86
+403 4 3 0 1 0 84 83 36 91
+404 4 3 0 1 0 85 80 77 88
+405 4 3 0 1 0 78 68 81 88
+406 4 3 0 1 0 41 42 39 79
+407 4 3 0 1 0 74 73 79 84
+408 4 3 0 1 0 80 58 56 89
+409 4 3 0 1 0 72 80 69 89
+410 4 3 0 1 0 75 73 76 84
+411 4 3 0 1 0 48 51 53 79
+412 4 3 0 1 0 55 70 77 89
+413 4 3 0 1 0 32 31 64 92
+414 4 3 0 1 0 73 85 77 88
+415 4 3 0 1 0 85 80 76 92
+416 4 3 0 1 0 35 76 83 84
+417 4 3 0 1 0 73 80 85 88
+418 4 3 0 1 0 48 51 79 86
+419 4 3 0 1 0 54 55 77 85
+420 4 3 0 1 0 38 66 9 4
+421 4 3 0 1 0 74 84 79 91
+422 4 3 0 1 0 88 80 77 89
+423 4 3 0 1 0 80 85 77 89
+424 4 3 0 1 0 41 42 79 93
+425 4 3 0 1 0 18 6 71 45
+426 4 3 0 1 0 85 55 77 89
+427 4 3 0 1 0 70 88 77 89
+428 4 3 0 1 0 73 74 77 85
+429 4 3 0 1 0 33 79 37 93
+430 4 3 0 1 0 43 25 44 65
+431 4 3 0 1 0 39 51 27 28
+432 4 3 0 1 0 87 14 36 91
+433 4 3 0 1 0 74 50 87 91
+434 4 3 0 1 0 66 61 64 76
+435 4 3 0 1 0 82 81 63 90
+436 4 3 0 1 0 46 49 47 77
+437 4 3 0 1 0 2 42 12 37
+438 4 3 0 1 0 66 76 64 92
+439 4 3 0 1 0 80 85 56 92
+440 4 3 0 1 0 41 12 42 93
+441 4 3 0 1 0 38 4 16 59
+442 4 3 0 1 0 4 59 66 31
+443 4 3 0 1 0 76 61 64 90
+444 4 3 0 1 0 73 80 76 85
+445 4 3 0 1 0 84 74 83 91
+446 4 3 0 1 0 6 52 19 71
+447 4 3 0 1 0 73 75 76 90
+448 4 3 0 1 0 74 87 36 91
+449 4 3 0 1 0 83 74 36 91
+450 4 3 0 1 0 80 73 76 90
+451 4 3 0 1 0 75 61 76 90
+452 4 3 0 1 0 81 78 73 82
+453 4 3 0 1 0 86 73 77 88
+454 4 3 0 1 0 59 4 66 38
+455 4 3 0 1 0 66 31 59 92
+456 4 3 0 1 0 42 12 37 93
+457 4 3 0 1 0 85 80 56 89
+458 4 3 0 1 0 86 78 73 88
+459 4 3 0 1 0 84 33 79 91
+460 4 3 0 1 0 78 81 73 88
+461 4 3 0 1 0 51 47 52 86
+462 4 3 0 1 0 70 55 21 89
+463 4 3 0 1 0 80 88 69 89
+464 4 3 0 1 0 80 81 69 88
+465 4 3 0 1 0 81 80 73 88
+466 4 3 0 1 0 60 15 36 87
+467 4 3 0 1 0 82 75 73 90
+468 4 3 0 1 0 1 15 60 87
+469 4 3 0 1 0 72 8 58 22
+470 4 3 0 1 0 81 82 73 90
+471 4 3 0 1 0 80 81 73 90
+472 4 3 0 1 0 1 60 29 87
+473 4 3 0 1 0 51 48 47 86
+474 4 3 0 1 0 33 84 79 93
+475 4 3 0 1 0 87 50 14 91
+476 4 3 0 1 0 31 66 64 92
+477 4 3 0 1 0 1 50 14 87
+478 4 3 0 1 0 56 31 32 92
+479 4 3 0 1 0 56 57 31 92
+480 4 3 0 1 0 12 34 33 93
+481 4 3 0 1 0 35 16 36 83
+482 4 3 0 1 0 14 33 36 91
+483 4 3 0 1 0 31 57 59 92
+$EndElements
diff --git a/examples++-load/dfft.cpp b/examples++-load/dfft.cpp
new file mode 100644
index 0000000..d15fbb6
--- /dev/null
+++ b/examples++-load/dfft.cpp
@@ -0,0 +1,270 @@
+// Example C++ function "myfunction", dynamically loaded into "ff-c++ dfft.cpp "
+// ---------------------------------------------------------------------
+// $Id$
+
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:   fftw3 
+//ff-c++-cpp-dep: 
+//  
+#include "ff++.hpp"
+#include "AFunction_ext.hpp"
+#include <fftw3.h>
+
+
+template<class Complex>
+class DFFT_1d2dor3d
+{  
+public: 
+  Complex * x;
+  int n, m,k;
+  int sign;   
+  DFFT_1d2dor3d(KN<Complex> * xx,long signn,long nn=1,long kk=1) : x(*xx),n(nn),m(xx->N()/(nn*kk)),k(kk),sign(signn) {
+    cout << xx << " " << signn << " " << nn << " " << xx->N() << " n: " << n << " m:" << m << " k:  " << k <<endl;
+    ffassert(n>0 && (n*m*k ==xx->N()));
+    
+  } 
+
+
+  DFFT_1d2dor3d(KNM<Complex> * xx,long signn) : x(*xx),n(xx->M()),m(xx->N()),sign(signn) {
+  }
+  
+};
+
+DFFT_1d2dor3d<Complex>  dfft(KN<Complex> * const  & x,const long &sign)
+{
+  return DFFT_1d2dor3d<Complex>(x,sign);
+}
+
+DFFT_1d2dor3d<Complex>  dfft(KN<Complex> *const  &x,const long &nn,const long &sign)
+{
+  return DFFT_1d2dor3d<Complex>(x,sign,nn);
+}
+DFFT_1d2dor3d<Complex>  dfft(KN<Complex> *const  &x,const long &nn,const long &kk,const long &sign)
+{
+  return DFFT_1d2dor3d<Complex>(x,sign,nn,kk);
+}
+
+DFFT_1d2dor3d<Complex> dfft(KNM<Complex> * const &  x,const long &sign)
+{
+  return DFFT_1d2dor3d<Complex>(x,sign);
+}
+bool ff_execute(fftw_plan *p)
+{
+ if(*p)  fftw_execute(*p);
+    return 0; 
+}
+
+bool ff_delete(fftw_plan *p)
+{
+   if(*p)  fftw_destroy_plan(*p);
+    *p =0; 
+    return 0;
+}
+
+KN<Complex> * dfft_eq(  KN<Complex> * const   &x,const DFFT_1d2dor3d<Complex>  & d)
+{
+  ffassert(x->N()==d.n*d.m*d.k );
+  Complex *px =  *x;
+  fftw_plan p;
+  //cout << " dfft " << px << " = " << d.x << " n = " << d.n << " " << d.m << " sign = " << d.sign << endl; 
+  if ( d.k ==1)
+  {
+   if ( d.n > 1)
+    p = fftw_plan_dft_2d(d.n,d.m,reinterpret_cast<fftw_complex*>(d.x),reinterpret_cast<fftw_complex*> (px),d.sign,FFTW_ESTIMATE);
+   else
+    p = fftw_plan_dft_1d(d.m ,reinterpret_cast<fftw_complex*>(d.x),reinterpret_cast<fftw_complex*> (px),d.sign,FFTW_ESTIMATE);
+  }
+   else 
+   {
+       if ( d.n > 1)
+           p = fftw_plan_dft_3d(d.n,d.m,d.k,reinterpret_cast<fftw_complex*>(d.x),reinterpret_cast<fftw_complex*> (px),d.sign,FFTW_ESTIMATE);
+       else
+           p = fftw_plan_dft_2d(d.m,d.k,reinterpret_cast<fftw_complex*>(d.x),reinterpret_cast<fftw_complex*> (px),d.sign,FFTW_ESTIMATE);
+       
+   }
+ // cout << " ---" ;
+  fftw_execute(p);
+ // cout << " ---" ;
+  fftw_destroy_plan(p);
+ // cout << " ---" ;
+  return  x;
+}
+
+
+KN<double> * dfft_eq(  KN<double> * const   &x,const DFFT_1d2dor3d<double>  & d)
+{
+  ffassert(0); 
+  return  x;
+}
+
+/*  class Init { public:
+  Init();
+  };*/
+// bofbof .. 
+struct  fftw_plan_s {};
+// ...
+
+template<> inline AnyType DeletePtr<fftw_plan*>(Stack,const AnyType &x) {
+    fftw_plan  * a=PGetAny<fftw_plan>(x);
+    if(*a) fftw_destroy_plan(*a);
+    *a =0; 
+    return  Nothing;
+};
+
+fftw_plan* plan__eq( fftw_plan* a, fftw_plan b)
+{
+    if(*a) fftw_destroy_plan(*a);
+    *a=b;
+    return a; 
+}
+fftw_plan* plan_set( fftw_plan* a, fftw_plan b)
+{
+  //    if(*a) fftw_destroy_plan(*a);
+    *a=b;
+    return a; 
+}
+
+fftw_plan plan_dfft(KN<Complex> * const  & x,KN<Complex> * const  & y,const long &sign)
+{
+  return  fftw_plan_dft_1d(x->N() ,reinterpret_cast<fftw_complex*>(&x[0]),reinterpret_cast<fftw_complex*> (&y[0]),sign,FFTW_ESTIMATE);
+}
+fftw_plan plan_dfft(KNM<Complex> * const  & x,KNM<Complex> * const  & y,const long &sign)
+{
+    long m=x->N(), n=x->M();
+    fftw_plan_dft_2d(n,m,reinterpret_cast<fftw_complex*>(&x[0]),reinterpret_cast<fftw_complex*> (&y[0]),sign,FFTW_ESTIMATE);
+    return 0;
+}
+
+fftw_plan plan_dfft(KN<Complex> * const  & x,KN<Complex> * const  & y,const long &n,const long &sign)
+{
+    long  nn=n, mm=y->N()/nn; ffassert( mm*nn == y->N() && x->N() == y->N()  );
+    return fftw_plan_dft_2d(nn,mm,reinterpret_cast<fftw_complex*>(&x[0]),reinterpret_cast<fftw_complex*> (&y[0]),sign,FFTW_ESTIMATE);
+    
+}
+
+fftw_plan plan_dfft(KN<Complex> * const  & x,KN<Complex> * const  & y,const long &n,const long &k,const long &sign)
+{
+    int nn=n, mm= y->N()/(k*n), kk= k;
+    ffassert(y->N() == nn*mm*kk) ;
+    if( nn >1)
+      return fftw_plan_dft_3d(nn,mm,kk, reinterpret_cast<fftw_complex*>(&x[0]),reinterpret_cast<fftw_complex*> (&y[0]),sign,FFTW_ESTIMATE);
+    else 
+      return fftw_plan_dft_2d(nn,mm,reinterpret_cast<fftw_complex*>(&x[0]),reinterpret_cast<fftw_complex*> (&y[0]),sign,FFTW_ESTIMATE);
+}
+
+
+
+class Mapkk :  public E_F0mps
+{
+    
+public:
+    typedef Complex R;
+    typedef  KN_<R>  Result;
+    ;
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =0;
+    Expression nargs[n_name_param];
+    Expression expv, expm,exp;
+    
+    Mapkk(const basicAC_F0 & args)
+    : expv(0), expm(0),exp(0)
+    {
+        args.SetNameParam(n_name_param,name_param,nargs);
+        expv= to<KN<R>*>(args[0]);  // a the expression to get the mesh
+        expm= to<long>(args[1]);
+        exp= to<R>(args[2]);// a the expression to get the mesh
+     
+    }
+    
+    ~Mapkk()
+    {
+    }
+    
+    static ArrayOfaType  typeargs()
+    { return  ArrayOfaType(
+                           atype<KN<R> *>(),
+			   atype<long >(),
+                           atype<R >()
+			   );
+    }
+    static  E_F0 * f(const basicAC_F0 & args){ return new Mapkk(args);}
+    AnyType operator()(Stack s) const ;
+    
+};
+
+basicAC_F0::name_and_type Mapkk::name_param[]={};
+
+AnyType Mapkk::operator()(Stack s) const
+{
+    MeshPoint *mp(MeshPointStack(s)) , mps=*mp;
+    KN<R> * pv=GetAny<KN<R> *>((*expv)(s));
+    KN<R> v(*pv);
+ 
+    long nn = v.N();
+    long m = GetAny<long>((*expm)(s));
+    cout << " expm " << expm << " m = " << m << endl; 
+    long n = nn/m;
+    double ki = 1./n ;
+    double kj = 1./m ;
+    double ki0=0., kj0=0;
+    cout <<  n << " " << m << " " << nn << " == " << n*m << endl;
+    ffassert( m* n  == nn );
+    long n2= (n+1)/2, m2=(m+1)/2;
+    for(long k=0,i=0;i < n; ++i)
+         for(long j=0;j < m; ++j,++k)
+         {//
+             int ii=i, jj=j;
+             if( ii > n2) ii=i-n;
+             if( jj > m2) jj=j-n;            
+             R2 P(i*ki+ki0 ,j*kj+kj0);
+             mp->set(P.x,P.y);
+             v[k] = GetAny< R>((*exp)(s));
+         }
+    *mp = mps;
+    return 0L;
+}
+
+
+static void Load_Init(){
+  typedef DFFT_1d2dor3d<Complex>  DFFT_C;
+  typedef DFFT_1d2dor3d<double>  DFFT_R;
+
+  cout << " lood: init dfft " << endl;
+  Dcl_Type<DFFT_C >();
+  Dcl_Type<DFFT_R >();
+    
+  // cout << typeid(fftw_plan).name()  << endl;
+  Dcl_Type<fftw_plan*>(::InitializePtr<fftw_plan*>,::DeletePtr<fftw_plan*>);
+  Dcl_Type<fftw_plan>();
+  zzzfff->Add("fftwplan",atype<fftw_plan * >());
+    
+  TheOperators->Add("=", new OneOperator2<fftw_plan *,fftw_plan *,fftw_plan>(plan__eq));
+  TheOperators->Add("<-", new OneOperator2<fftw_plan *,fftw_plan *,fftw_plan>(plan_set));
+    
+  Global.Add("plandfft","(", new OneOperator3_<fftw_plan,KN<Complex>*,KN<Complex>*,long >(plan_dfft ));
+  Global.Add("plandfft","(", new OneOperator4_<fftw_plan,KN<Complex>*,KN<Complex>*,long,long >(plan_dfft ));
+  Global.Add("plandfft","(", new OneOperator5_<fftw_plan,KN<Complex>*,KN<Complex>*,long,long,long >(plan_dfft ));
+  Global.Add("plandfft","(", new OneOperator3_<fftw_plan,KNM<Complex>*,KNM<Complex>*,long >(plan_dfft ));
+    
+
+  Global.Add("execute","(", new OneOperator1<bool,fftw_plan*>(ff_execute));
+  Global.Add("delete","(", new OneOperator1<bool,fftw_plan*>(ff_delete));
+    
+    
+  Global.Add("dfft","(", new OneOperator2_<DFFT_C,KN<Complex>*,long >(dfft ));
+  Global.Add("dfft","(", new OneOperator3_<DFFT_C,KN<Complex>*,long,long >(dfft ));
+  Global.Add("dfft","(", new OneOperator4_<DFFT_C,KN<Complex>*,long,long, long >(dfft ));
+  Global.Add("dfft","(", new OneOperator2_<DFFT_C,KNM<Complex>*,long >(dfft ));
+  Global.Add("map","(", new OneOperatorCode<Mapkk>( ));
+  TheOperators->Add("=", new OneOperator2_<KN<Complex>*,KN<Complex>*,DFFT_C>(dfft_eq));
+  /*
+  Global.Add("dfft","(", new OneOperator2_<DFFT_R,KN<double>*,long >(dfft ));
+  Global.Add("dfft","(", new OneOperator3_<DFFT_R,KN<double>*,long,long >(dfft ));
+  Global.Add("dfft","(", new OneOperator4_<DFFT_R,KN<double>*,long,long, long >(dfft ));
+  Global.Add("dfft","(", new OneOperator2_<DFFT_R,KNM<double>*,long >(dfft ));
+  TheOperators->Add("=", new OneOperator2_<KN<double>*,KN<double>*,DFFT_R>(dfft_eq));
+  */
+  // TheOperators->Add("=", new OneOperator2_<KNM<Complex>*,KNM<Complex>*,DFFT_1d2dor3d>(dfft_eq));
+
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/dfft.edp b/examples++-load/dfft.edp
new file mode 100644
index 0000000..85dfd2e
--- /dev/null
+++ b/examples++-load/dfft.edp
@@ -0,0 +1,67 @@
+// Example of dynamic function load
+// --------------------------------
+// $Id$
+//   Discret Fast Fourier Transform 
+// -------------------------------
+ load "dfft"
+ 
+int nx=32,ny=16,N=nx*ny;
+// warning the fourier space is not exactly the unite square due to periodic condition
+mesh Th=square(nx-1,ny-1,[(nx-1)*x/nx,(ny-1)*y/ny]);
+// warring  the numbering is of the vertices (x,y) is 
+// given by $  i = x/nx + nx* y/ny $
+
+fespace Vh(Th,P1); 
+
+func f1 = cos(2*x*2*pi)*cos(3*y*2*pi);
+Vh<complex> u=f1,v;
+Vh w=f1;
+
+
+Vh  ur,ui;
+//  in dfft the matrix n,m is in row-major order ann array n,m is 
+// store j + m* i ( the transpose of the square numbering ) 
+ v[]=dfft(u[],ny,-1);
+ u[]=dfft(v[],ny,+1);
+ cout << " ||u||_\infty " << u[].linfty << endl;
+ u[] *= 1./N; // remark: operator /= bug  before version 2.0-3 (FH)
+ cout << " ||u||_\infty " << u[].linfty <<  endl;
+  ur=real(u); 
+  plot(w,wait=1,value=1,cmm="w");
+  plot(ur,wait=1,value=1,cmm="u");
+ v = w-u;
+cout << " diff = "<< v[].max << " " <<  v[].min << endl;
+assert( norm(v[].max) < 1e-10 &&  norm(v[].min) < 1e-10) ;
+ // -------  a more hard example ----\hfilll
+ // Lapacien en FFT \hfilll
+ // $ -\Delta u = f $ with biperiodic condition \hfilll
+func f = cos(3*2*pi*x)*cos(2*2*pi*y); // 
+func ue =  +(1./(square(2*pi)*13.))*cos(3*2*pi*x)*cos(2*2*pi*y);  // the exact solution 
+Vh<complex> ff = f;
+Vh<complex> fhat;
+fhat[] = dfft(ff[],ny,-1);
+
+Vh<complex> wij;
+// warning in fact we take mode between -nx/2, nx/2 and -ny/2,ny/2
+//  thank to the operator ?: \label{?:} 
+wij = square(2.*pi)*(square(( x<0.5?x*nx:(x-1)*nx)) + square((y<0.5?y*ny:(y-1)*ny)));
+wij[][0] = 1e-5; // to remove div / 0
+fhat[] = fhat[]./ wij[];  // 
+u[]=dfft(fhat[],ny,1);
+u[] /= complex(N);
+ur = real(u); // the solution
+w = real(ue); // the exact solution 
+plot(w,ur,value=1 ,cmm=" ue   ", wait=1); 
+w[] -= ur[]; // array sub
+real err= abs(w[].max)+abs(w[].min) ;
+cout << " err = " << err << endl;
+assert( err  < 1e-6);
+
+// version 3.22 ... 
+
+fftwplan p1=plandfft(u[],v[],ny,-1);
+fftwplan p2=plandfft(u[],v[],ny,1);
+real ccc = square(2.*pi);
+cout << " ny = " << ny << endl; 
+map(wij[],ny,ccc*(x*x+y*y)); 
+wij[][0] = 1e-5;
diff --git a/examples++-load/dmatrix.hpp b/examples++-load/dmatrix.hpp
new file mode 100755
index 0000000..85cafea
--- /dev/null
+++ b/examples++-load/dmatrix.hpp
@@ -0,0 +1,88 @@
+// SUMMARY  :   matrix manipulation
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : P. Jolivet 
+// E-MAIL   : Pierre Jolivet <pierre.jolivet at ljll.math.upmc.fr>
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+#include <vector>
+//#include <mpi.h>
+#include <iostream>
+#include <numeric>
+
+struct step {
+    public:
+        step(int x, int y) : x(x), y(y) { }
+        int operator()() { return x += y; }
+
+    private:
+        int x, y;
+};
+
+template<unsigned char M, unsigned char S>
+static void CSR2COO(unsigned int n, int* compressedI, int* uncompressedI) {
+    if(S == 'U') {
+        for(int i = n - 1; i > -1; --i) {
+            if(M == 'F')
+                std::fill(uncompressedI + compressedI[i] - 1, uncompressedI + compressedI[i + 1] - 1, i + 1);
+            else
+                std::fill(uncompressedI + compressedI[i], uncompressedI + compressedI[i + 1], i + 1);
+        }
+    }
+    else if(S == 'L') {
+        for(int i = 1; i < n; ++i) {
+            if(M == 'F')
+                std::fill(uncompressedI + compressedI[i] - i - 1, uncompressedI + compressedI[i + 1] - i - 1, i + 1);
+            else
+                std::fill(uncompressedI + compressedI[i] - i, uncompressedI + compressedI[i + 1] - i - 1, i + 1);
+        }
+    }
+};
+
+template<bool WithDiagonal, unsigned char N,typename Scalar>
+static unsigned int trimCSR(unsigned int n, int* trimmedI, int* untrimmedI, int* trimmedJ, int* untrimmedJ, Scalar* trimmedC, Scalar* untrimmedC) {
+    unsigned int upper = 0;
+    for(unsigned int i = 0; i < n - WithDiagonal; ++i) {
+        trimmedI[i] = upper + (N == 'F');
+        int* jIndex = lower_bound(untrimmedJ + untrimmedI[i], untrimmedJ + untrimmedI[i + 1], i + !WithDiagonal);
+        unsigned int j = untrimmedI[i] + jIndex - (untrimmedJ + untrimmedI[i]);
+        if(N == 'F') {
+            for(unsigned int k = j; k < untrimmedI[i + 1]; ++k)
+                trimmedJ[upper + k - j] = untrimmedJ[k] + 1;
+
+        } else
+            std::copy(untrimmedJ + j, untrimmedJ + untrimmedI[i + 1], trimmedJ + upper);
+        std::copy(untrimmedC + j, untrimmedC + untrimmedI[i + 1], trimmedC + upper);
+        upper += untrimmedI[i + 1] - j;
+    }
+    if(WithDiagonal) {
+        trimmedI[n - 1] = upper + (N == 'F');
+        trimmedI[n] = trimmedI[n - 1] + 1;
+        trimmedJ[upper] = n - (N == 'C');
+        trimmedC[upper] = untrimmedC[untrimmedI[n] - 1];
+        return trimmedI[n];
+    }
+    else {
+        trimmedI[n] = trimmedI[n - 1];
+        return trimmedI[n + 1];
+    }
+};
diff --git a/examples++-load/ff-Ipopt.cpp b/examples++-load/ff-Ipopt.cpp
new file mode 100644
index 0000000..a8955ab
--- /dev/null
+++ b/examples++-load/ff-Ipopt.cpp
@@ -0,0 +1,1747 @@
+/*
+ *  ff-NLopt.cpp
+ *
+ *
+ *  Created by Sylvain Auliac on 17/01/12.
+ *
+ */
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//ff-c++-LIBRARY-dep:  Ipopt mumps-seq blas  libseq  fc
+
+//using namespace std;
+#include "IpTNLP.hpp"
+#include "IpIpoptApplication.hpp"
+#include "ff++.hpp"
+
+
+
+extern Block *currentblock;
+
+typedef double R;
+typedef KN_<R> Rn_;
+typedef KN<R> Rn;
+typedef KNM_<R> Rnm_;
+typedef KNM<R> Rnm;
+
+
+
+
+
+/*****************************************************************************************************************************
+ *	Some misc. function usefull later...
+ *****************************************************************************************************************************/
+
+//A variadic function to add an undefinite number of elements to a set of short int
+//This is used to define the set of named parameter which are not used when some assumptions
+//upon the optimization poblem functions are met
+void AddElements(std::set<unsigned short> &_set,int amount,int first,...)
+{
+    int elem=0;
+    va_list vl;
+    va_start(vl,first);
+    _set.insert(first);
+    for (int i=1;i<amount;i++)
+    {
+        elem=va_arg(vl,int);
+        _set.insert(elem);
+        
+    }
+    va_end(vl);
+    
+}
+
+//A raw pointer cleaner
+template<class T> inline void clean(T *p) {if(p) {delete p; p=0;} }
+
+//Pair compare (certainly already implemented in the STL with KeyLess...)
+inline bool operator<=(const std::pair<int,int> &l,const std::pair<int,int> &r) {return (l.first < r.first) || (l.first==r.first && l.second <= r.second);}
+
+//Some logical operators (exclussive or and its negation)
+inline bool XOR(bool a,bool b) {return (!a && b) || (a && !b);}
+inline bool NXOR(bool a,bool b) {return !XOR(a,b);}
+
+//A debug tool
+#ifdef DEBUG
+inline void SONDE() {static int i=1; cout << "SONDE " << i << endl; ++i;}
+#else
+inline void SONDE() {}
+#endif
+
+
+
+
+
+/*****************************************************************************************************************************
+ *	FreeFem function callers
+ *  ffcalfunc : template abstract mother class with a pointer to the freefem stack and the J virtual method which computes
+ *              the function
+ *****************************************************************************************************************************/
+template<class K> class ffcalfunc
+{
+public:
+    Stack stack;
+    ffcalfunc(const ffcalfunc &f) : stack(f.stack) {}
+    ffcalfunc(Stack _stack) : stack(_stack) {}
+    virtual K J(Rn_) const = 0;
+    virtual  ~ffcalfunc() {}
+};
+
+
+/*****************************************************************************************************************************
+ *	GeneralFunc : Most general case (specialized for sparse matrix returning functions, because IPOPT need the hessian func
+ *                to take some additional parameters).
+ *    @theparame: ff expression of the parameter of the ff function, computing J(x) need the associated KN to be set to the
+ *                values of x
+ *    @JJ       : ff expression of the function
+ *****************************************************************************************************************************/
+template<class K> class GeneralFunc : public ffcalfunc<K>
+{
+public:
+    Expression JJ,theparame;
+    GeneralFunc(const GeneralFunc &f) : ffcalfunc<K>(f),JJ(f.JJ),theparame(f.theparame) {}
+    GeneralFunc(Stack s,Expression JJJ,Expression epar) : ffcalfunc<K>(s),JJ(JJJ), theparame(epar) {}
+    K J(Rn_  x) const
+    {
+        KN<double> *p=GetAny<KN<double> *>( (*theparame)(this->stack) );
+        *p=x;
+        K ret= GetAny<K>( (*JJ)(this->stack) );
+        //cout << "call to ffcalfunc.J with " << *p << " and ret=" << ret << endl;
+        WhereStackOfPtr2Free(this->stack)->clean();
+        return  ret;
+    }
+};
+
+/*****************************************************************************************************************************
+ *	P2ScalarFunc: encapsulate a function which is the sum of a bilinear and a linear form (no constant part since it will be
+ *                used as fitness function). It also handles the case of pure quadratic or linear forms.
+ *    @vf       : If true J will compute 0.5xMx - bx (x is the solution of Mx = b in the unconstrained optimization process)
+ *                if false xMx + bx is returned
+ *    @M        : FF expression of the matrix of the bilinear form (null pointer for linear form case)
+ *    @b        : FF expression of the vector representation of the linear part (null for pure quadratic case)
+ *****************************************************************************************************************************/
+class P2ScalarFunc : public ffcalfunc<R>
+{
+public:
+    const bool vf;
+    Expression M,b; //Matrix of the quadratic part, vector of the linear part
+    P2ScalarFunc(const P2ScalarFunc &f) : ffcalfunc<R>(f),M(f.M),b(f.b),vf(f.vf) {}
+    P2ScalarFunc(Stack s,Expression _M,Expression _b,bool _vf=false) : ffcalfunc<R>(s),M(_M),b(_b),vf(_vf) {}
+    R J(Rn_ x) const
+    {
+        Rn tmp(x.N(),0.);
+        if(M)
+        {
+            Matrice_Creuse<R> * a = GetAny<Matrice_Creuse<R> *>( (*M)(stack) );
+            MatriceMorse<R> *A = dynamic_cast<MatriceMorse<R> *>(&(*a->A));
+            assert(A);
+            tmp  = (*A)*x;
+            if(vf) tmp/=2.;
+        }
+        if(b)
+        {
+            Rn *B = GetAny<Rn*>( (*b)(stack) );
+            tmp += *B;
+            //if(vf) tmp -= (*B); else tmp += (*B);
+        }
+        R res=0.;
+        for(int i=0;i<x.N();++i) res += x[i]*tmp[i];
+        return res;
+    }
+};
+
+/*****************************************************************************************************************************
+ *	P1VectorFunc: encapsulate a function which is the sum of a linear part and a constant, mostly used for affine/linear
+ *                constraints, or for P2 fitness function gradient
+ *    @vf       : Set to true if this is expected the gradient of a P2 scalar function associated to Ax=b linear system
+ *                J will then return Ax - b. Otherwize Ax+b is returned.
+ *    @M        : FF expression of the matrix of the linear part
+ *    @b        : FF expression of the vector representation of the constant part
+ *****************************************************************************************************************************/
+class P1VectorFunc : public ffcalfunc<Rn>
+{
+public:
+    const bool vf;
+    Expression M,b;
+    P1VectorFunc(const P1VectorFunc &f) : ffcalfunc<Rn>(f),M(f.M),b(f.b),vf(f.vf) {}
+    P1VectorFunc(Stack s,Expression _M,Expression _b,bool _vf=false) : ffcalfunc<Rn>(s),M(_M),b(_b),vf(_vf) {}
+    Rn J(Rn_ x) const
+    {
+        Rn tmp(0);
+        if(M)
+        {
+            Matrice_Creuse<R> * a = GetAny<Matrice_Creuse<R> *>( (*M)(stack) );
+            MatriceMorse<R> *A = dynamic_cast<MatriceMorse<R> *>(&(*a->A));
+            assert(A);
+            if(tmp.N() != A->n) {tmp.resize(A->n); tmp=0.;}
+            tmp  = (*A)*x;
+        }
+        if(b)
+        {
+            Rn* B = GetAny<Rn *>( (*b)(stack) );
+            if(tmp.N() != B->N()) {tmp.resize(B->N()); tmp=0.;}
+            tmp += *B;
+            //if(vf) tmp -= (*B); else tmp += (*B);
+        }
+        return tmp;
+    }
+};
+
+
+
+/*****************************************************************************************************************************
+ *	ffcalfunc<Matrice_Creuse>R>*>: specialization for sparse matrix returning function. When it encapsulates the hessian
+ *                function of the lagragian, non-linear constraints will need the additional obj_factor and lagrange multiplier
+ *                parameters. The one parameter version of J is called if there is no non-linear constraints or if the objects
+ *                represents the jacobian of the constraints.
+ *****************************************************************************************************************************/
+template<> class ffcalfunc<Matrice_Creuse<R> *>
+{
+public:
+    typedef Matrice_Creuse<R> *K;
+    Stack stack;
+    ffcalfunc(const ffcalfunc &f) : stack(f.stack) {}
+    ffcalfunc(Stack s) : stack(s) {}
+    virtual K J(Rn_) const = 0;
+    virtual K J(Rn_,double,Rn_) const = 0;
+    virtual bool NLCHPEnabled() const = 0; //Non Linear Constraints Hessian Prototype
+    virtual ~ffcalfunc(){}
+    
+};
+
+/*****************************************************************************************************************************
+ *	GeneralSparseMatFunc: general case of sparse matrix returning function. Members datas added are ff expression of the
+ *                scalar objective factor and vectorial lagrange multipliers.
+ *****************************************************************************************************************************/
+class GeneralSparseMatFunc : public ffcalfunc<Matrice_Creuse<R> *>
+{
+private:
+    typedef ffcalfunc<Matrice_Creuse<R> *> FFF;
+public:
+    Expression JJ,param,paramlm,paramof;
+    GeneralSparseMatFunc(const GeneralSparseMatFunc &f) : FFF(f),JJ(f.JJ),param(f.param),paramlm(f.paramlm),paramof(f.paramof) {};
+    GeneralSparseMatFunc(Stack s,Expression JJJ,Expression epar,Expression eparof=0,Expression eparlm=0)
+    : FFF(s),JJ(JJJ),param(epar),paramlm(eparlm),paramof(eparof)
+    {ffassert(NXOR(paramlm,paramof));}
+    bool NLCHPEnabled() const {return paramlm && paramof;}
+    K J(Rn_  x) const
+    {
+        KN<double> *p=GetAny<KN<double> *>( (*param)(stack) );
+        *p=x;
+        K ret= GetAny<K>( (*JJ)(stack));
+        //cout << "call to ffcalfunc.J with " << *p << " and ret=" << ret << endl;
+        WhereStackOfPtr2Free(stack)->clean();
+        return  ret;
+    }
+    K J(Rn_  x,double of,Rn_ lm) const
+    {
+        if(paramlm && paramof)
+        {
+            KN<double> *p=GetAny<KN<double> *>( (*param)(stack) );
+            double *pof=GetAny<double *>( (*paramof)(stack) );
+            KN<double > *plm=GetAny<KN<double> *>( (*paramlm)(stack) );
+            *p=x;
+            *pof=of;
+            int m= lm.N(), mm=plm->N();
+            if( (m != mm) && mm) {cout << " ff-ipopt H : big bug int size ???"<< m << " != " << mm <<  endl; abort();};
+            *plm=lm;
+            K ret= GetAny<K>( (*JJ)(stack));
+            //cout << "call to ffcalfunc.J with " << *p << " and ret=" << ret << endl;
+            WhereStackOfPtr2Free(stack)->clean();
+            return  ret;
+        }
+        else return J(x);
+    }
+};
+
+/*****************************************************************************************************************************
+ *	ConstantSparseMatFunc: Encapsulate a constant matrix returning function. Just contains the ff expression of the matrix
+ *                (and stack inherited from mother class), this matrix is returned regardless of x.
+ *****************************************************************************************************************************/
+class ConstantSparseMatFunc : public ffcalfunc<Matrice_Creuse<R> *>
+{
+private:
+    typedef ffcalfunc<Matrice_Creuse<R> *> FFF;
+public:
+    Expression M; //Expression of the matrix
+    ConstantSparseMatFunc(const ConstantSparseMatFunc &f) : FFF(f),M(f.M) {}
+    ConstantSparseMatFunc(Stack s,Expression _M) : FFF(s),M(_M) {}
+    bool NLCHPEnabled() const {return false;}
+    K J(Rn_) const
+    {
+        K ret = M ? GetAny<K>( (*M)(stack) ) : 0;
+        WhereStackOfPtr2Free(stack)->clean();
+        return ret;
+    }
+    K J(Rn_ x,double,Rn_) const {return J(x);}
+};
+
+
+
+typedef ffcalfunc<double> ScalarFunc;
+typedef ffcalfunc<Rn> VectorFunc;
+typedef ffcalfunc<Rnm> FullMatrixFunc;
+typedef ffcalfunc<Matrice_Creuse<R>* > SparseMatFunc;
+
+
+
+
+
+/*****************************************************************************************************************************
+ *	SparseMatStructure: a class for sparse matrix structure management (mostly merging). The most interesting methods in this
+ *                class are :
+ *    AddMatrix : merge the structure of the given matrix to the structure of current object
+ *    AddArrays : merge structure in arrays form to the current object
+ *    ToKn      : allocate the raws and cols pointers and fill them with the std::set<Z2> form of the structure
+ *                structure is then emptied if this method is passed a true value
+ * ==> update 28/03/2012, autostruct proved useless since the structure merging can be done with operator +
+ *     (I did not no whether nullify coefficients where removed from the result but it actually doesn't so the structure of
+ *      the lagrangian hessian can be guessed exactly by evaluating on a point yeilding the biggest fitness function
+ *      hessian along with a dual vector filled with 1).
+ *****************************************************************************************************************************/
+class SparseMatStructure
+{
+public:
+    typedef std::pair<int,int> Z2;
+    typedef std::set<Z2> Structure;
+    typedef std::pair<KN<int>,KN<int> > Zn2;
+    typedef Structure::const_iterator const_iterator;
+    typedef Structure::iterator iterator;
+    
+    SparseMatStructure(bool _sym=0) : structure(),sym(_sym),n(0),m(0),raws(0),cols(0) {}
+    SparseMatStructure(Matrice_Creuse<R> const * const M,bool _sym=0) : structure(),sym(_sym),n(M->N()),m(M->M()),raws(0),cols(0) {this->AddMatrix(M);}
+    template<class INT> SparseMatStructure(const KN<INT> &I,const KN<INT> &J,bool _sym=0) : structure(),sym(_sym),n(I.max()),m(J.max()),raws(0),cols(0) {this->AddArrays(I,J);}
+    ~SparseMatStructure() {if(raws) delete raws; if(cols) delete cols;}
+    
+    const_iterator begin() const {return structure.begin();}
+    iterator begin() {return structure.begin();}
+    const_iterator end() const {return structure.end();}
+    iterator end() {return structure.end();}
+    //Structure& operator()() {return structure;}
+    //const Structure& operator()() const {return structure;}
+    bool empty() const {return structure.empty() && !raws && !cols;}
+    int N() const {return n;}
+    int M() const {return m;}
+    
+    SparseMatStructure& clear() {structure.clear(); if(raws) delete raws; if(cols) delete cols; sym=false; n=0; m=0; return *this;}
+    int size() const {return structure.size() ? structure.size() : (raws ? raws->N() : 0);}
+    SparseMatStructure& AddMatrix(Matrice_Creuse<R> const * const);
+    template<class INT> SparseMatStructure& AddArrays(const KN<INT> &,const KN<INT> &);
+    SparseMatStructure& ToKn(bool emptystruct=false);
+    
+    
+    KN<int> & Raws() {return *raws;}
+    KN<int> const & Raws() const {return *raws;}
+    KN<int> & Cols() {return *cols;}
+    KN<int> const & Cols() const {return *cols;}
+    
+private:
+    int n,m;
+    Structure structure;
+    bool sym;
+    //Zn2 *array_structure;
+    KN<int> *raws,*cols;
+};
+
+SparseMatStructure& SparseMatStructure::ToKn(bool emptystruct)
+{
+    if(raws) delete raws;
+    if(cols) delete cols;
+    raws = new KN<int>(structure.size());
+    cols = new KN<int>(structure.size());
+    int k=0;
+    for(const_iterator i=begin();i!=end();++i) {(*raws)[k]=i->first; (*cols)[k]=i->second; ++k;}
+    if(emptystruct) structure.clear();
+    return *this;
+}
+
+SparseMatStructure& SparseMatStructure::AddMatrix(Matrice_Creuse<R> const * const _M)
+{
+    n = n > _M->N() ? n : _M->N();
+    m = m > _M->M() ? m : _M->M();
+    MatriceMorse<R> const * const M = dynamic_cast<MatriceMorse<R> const * const> (&(*_M->A));
+    if( !M ) {
+        cerr << " Err= "<< " Matrix is not morse or CSR "<< &(*_M->A) << endl;
+        ffassert(M);
+    }
+     {
+    if(!sym || (sym && M->symetrique))
+    {
+        for(int i=0;i < M->N;++i)
+        {
+            for(int k=M->lg[i]; k < M->lg[i+1]; ++k) structure.insert(Z2(i,M->cl[k]));
+        }
+    }
+    else // sym && !M->symetrique
+    {
+        for(int i=0;i<M->N;++i)
+        {
+            for(int k=M->lg[i]; k < M->lg[i+1]; ++k) if(i >= M->cl[k]) structure.insert(Z2(i,M->cl[k]));
+        }
+    }
+    }
+    return *this;
+}
+template<class INT> SparseMatStructure& SparseMatStructure::AddArrays(const KN<INT> &I,const KN<INT> &J)
+{
+    ffassert(I.N()==J.N());
+    n = n > I.max()+1 ? n : I.max()+1;
+    m = m > J.max()+1 ? m : J.max()+1;
+    if(!sym) for(int k=0;k<I.N();++k) structure.insert(Z2(I[k],J[k]));
+    else for(int k=0;k<I.N();++k) if(I[k]>=J[k]) structure.insert(Z2(I[k],J[k]));
+    return *this;
+}
+
+
+
+
+
+/*****************************************************************************************************************************
+ *	ffNLP : Derived from the TNLP non-linear problem wrapper class of Ipopt. Virtual methods are defined as explain in
+ *          the IPOPT documentation. Some of them are tricky because the sparse matrix format in freefem is CRS, whereas
+ *          IPOPT use COO storage.
+ *          It is even more tricky because most of time, FreeFem will remove null coefficient from the structure, leading to
+ *          non constant indexing of the coefficient through the algorithm in case of very non linear functions. As IPOPT need
+ *          a constant structure, a FindIndex method involving a dichotomic search has been implemented to prevent the errors
+ *          related to that.
+ *****************************************************************************************************************************/
+using namespace Ipopt;
+
+class ffNLP : public TNLP
+{
+public:
+    ffNLP() : xstart(0) {}
+    ffNLP(Rn &,const Rn &,const Rn &,const Rn &,const Rn &,ScalarFunc*, VectorFunc*, SparseMatFunc*, VectorFunc*, SparseMatFunc*);
+    ffNLP(Rn &,const Rn &,const Rn &,const Rn &,const Rn &,ScalarFunc*, VectorFunc*, SparseMatFunc*, VectorFunc*, SparseMatFunc*, int ,int ,int);
+    virtual ~ffNLP();
+    
+    bool get_nlp_info(Index&, Index&, Index&, Index&, IndexStyleEnum&); //the IPOPT methods
+    bool get_bounds_info(Index, Number*, Number*, Index, Number*, Number*);
+    bool get_starting_point(Index, bool, Number*,bool , Number* , Number*,Index , bool ,Number* );
+    bool eval_f(Index, const Number*, bool, Number&);
+    bool eval_grad_f(Index, const Number*, bool, Number*);
+    bool eval_g(Index, const Number*, bool, Index, Number*);
+    bool eval_jac_g(Index, const Number*, bool,Index, Index, Index*, Index *,Number*);
+    bool eval_h(Index, const Number*, bool ,Number , Index , const Number*,bool, Index, Index*,Index*, Number*);
+    void finalize_solution(SolverReturn, Index, const Number*, const Number*, const Number*, Index, const Number*, const Number*, Number,
+                           const IpoptData* ip_data,
+                           IpoptCalculatedQuantities* ip_cq);
+    
+    template<class INT> ffNLP& SetHessianStructure(const KN<INT> &,const KN<INT> &,bool reset=0);
+    template<class INT> ffNLP& SetJacobianStructure(const KN<INT> &,const KN<INT> &,bool reset=0);
+    enum Level {do_nothing,user_defined, one_evaluation, basis_analysis};
+    ffNLP& BuildMatrixStructures(Level,Level,int);
+    ffNLP& EnableCheckStruct() {checkstruct=true; return *this;}
+    ffNLP& DisableCheckStruct() {checkstruct=false; return *this;}
+    
+    Rn lambda_start,x_start,uz_start,lz_start;
+    double sigma_start;
+    
+    double final_value;
+private:
+    //algorithm datas
+    Rn *xstart,xl,xu,gl,gu;
+    ScalarFunc *fitness; //Pointers to functions wrappers
+    VectorFunc *dfitness,*constraints;
+    SparseMatFunc *hessian,*dconstraints;
+    int mm,nnz_jac,nnz_h; //duplicated datas? did not seems to be reachable in the base class
+    //bool sym;
+    bool checkstruct;
+    SparseMatStructure HesStruct,JacStruct;
+    
+    //some static functions...
+    template<class A,class B> static void KnToPtr(const KN<A> &a,B *b) {for(int i=0;i<a.N();++i) b[i]=a[i];} //Fill a pointer with a KN
+    template<class A,class B> static void KnFromPtr(KN<A> &a,B const *b) {for(int i=0;i<a.N();++i) a[i]=b[i];}//Fill a KN with a pointer <-- to avoid the use of const_cast
+    static int FindIndex(const KN<int> &irow,const KN<int> & jrow,int i,int j,int kmin,int kmax);
+};
+
+
+ffNLP::ffNLP(Rn &x,const Rn &_xl,const Rn &_xu,const Rn &_gl,const Rn &_gu,ScalarFunc * _fitness,VectorFunc * _dfitness,SparseMatFunc * _hessian,
+             VectorFunc * _constraints,SparseMatFunc * _dconstraints) :
+xstart(&x), xl(_xl), xu(_xu), gl(_gl), gu(_gu),final_value(299792458.),//sym(0),unsymind(),
+fitness(_fitness), dfitness(_dfitness), constraints(_constraints),uz_start(),lz_start(),
+hessian(_hessian), dconstraints(_dconstraints),mm(-1),nnz_jac(-1),nnz_h(-1),
+HesStruct(true),JacStruct(false),sigma_start(1.),lambda_start(),x_start(x),checkstruct(1) {}
+
+
+ffNLP::ffNLP(Rn &x,const Rn &_xl,const Rn &_xu,const Rn &_gl,const Rn &_gu,ScalarFunc * _fitness,VectorFunc * _dfitness,SparseMatFunc * _hessian,
+             VectorFunc * _constraints,SparseMatFunc * _dconstraints, int _mm,int _nnz_jac,int _nnz_h) :
+xstart(&x), xl(_xl), xu(_xu), gl(_gl), gu(_gu),hessian(_hessian),final_value(299792458.),//sym(0),unsymind(),
+fitness(_fitness),dfitness(_dfitness),constraints(_constraints),dconstraints(_dconstraints),uz_start(),lz_start(),
+mm(_mm),nnz_jac(_nnz_jac),nnz_h(_nnz_h),HesStruct(true),JacStruct(false),sigma_start(1.),lambda_start(),x_start(x),checkstruct(1) {}
+
+ffNLP::~ffNLP()
+{
+    /*
+     clean(fitness);
+     clean(dfitness);
+     clean(constraints);
+     clean(hessian);
+     clean(dconstraints);
+     */
+}
+
+template<class INT> ffNLP& ffNLP::SetHessianStructure(const KN<INT> &I,const KN<INT> &J,bool reset)
+{
+    if(reset) HesStruct.clear();
+    HesStruct.AddArrays(I,J);
+    return *this;
+}
+template<class INT> ffNLP& ffNLP::SetJacobianStructure(const KN<INT> &I,const KN<INT> &J,bool reset)
+{
+    if(reset) JacStruct.clear();
+    JacStruct.AddArrays(I,J);
+    return *this;
+}
+ffNLP& ffNLP::BuildMatrixStructures(Level hlvl, Level jlvl,int _mm)
+{
+    if(jlvl!=do_nothing && dconstraints)
+    {
+        if(jlvl==user_defined) ffassert(JacStruct.size());
+        else if((jlvl==one_evaluation || jlvl==basis_analysis) && dconstraints) JacStruct.AddMatrix(dconstraints->J(x_start));
+    }
+    if(hlvl!=do_nothing && hessian)
+    {
+        if(hlvl==user_defined) ffassert(HesStruct.size());
+        else if(hlvl==one_evaluation || !hessian->NLCHPEnabled() )
+        {
+            Rn lms=lambda_start;
+            lms=1.;
+            HesStruct.AddMatrix(hessian->J(x_start,sigma_start,lms));
+        }
+        else if(hlvl==basis_analysis)
+        {
+            {
+                Rn lambda(_mm,0.);
+                HesStruct.AddMatrix(hessian->J(x_start,1.,lambda));
+            }
+            for(int i=0;i<_mm;++i)
+            {
+                Rn lambda(_mm,0.);
+                lambda[i] = 1.;
+                HesStruct.AddMatrix(hessian->J(x_start,0.,lambda));
+                lambda[i] = 0.;
+            }
+        }
+    }
+    JacStruct.ToKn();
+    HesStruct.ToKn();
+    return *this;
+}
+int ffNLP::FindIndex(const KN<int> &irow,const KN<int> &jcol,int i,int j,int kmin,int kmax)
+{
+    //cout << "Trying to find (" << i << ',' << j << ") in :" << irow << jcol << " - kmin=" << kmin << " and kmax=" << kmax << endl;
+    typedef std::pair<int,int> Z2;
+    Z2 ij(i,j),ijmin(irow[kmin],jcol[kmin]),ijmax(irow[kmax],jcol[kmax]);
+    if(abs(kmin-kmax)<=1)
+    {
+        if(ij==ijmin) return kmin;
+        else if(ij==ijmax) return kmax;
+        else return -1;
+    }
+    else
+    {
+        int knew = (kmin + kmax) / 2;
+        Z2 ijnew(irow[knew],jcol[knew]);
+        if(ij <= ijnew) return FindIndex(irow,jcol,i,j,kmin,knew);
+        else return FindIndex(irow,jcol,i,j,knew,kmax);
+    }
+}
+
+
+bool ffNLP::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,Index& nnz_h_lag, IndexStyleEnum& index_style)
+{
+    bool ret=true;
+    n = xstart ? xstart->N() : (ret=0);
+    //set(m,mm,constraints,xstart,ret);
+    //set(nnz_jac_g,nnz_jac,dconstraints,xstart,ret);
+    //set(nnz_h_lag,nnz_h,hessian,xstart,ret);
+    //if(JacStruct.empty() && constraints) BuildMatrixStructures(do_nothing,one_evaluation);
+    //if(HesStruct.empty()) BuildMatrixStructures(one_evaluation,do_nothing);
+    mm = m = constraints ? JacStruct.N() : 0;
+    nnz_jac = nnz_jac_g = constraints ? JacStruct.size() : 0;
+    nnz_h = nnz_h_lag = HesStruct.size();
+    index_style = TNLP::C_STYLE;
+    return ret;
+}
+
+bool ffNLP::get_bounds_info(Index n, Number* x_l, Number* x_u, Index m, Number* g_l, Number* g_u)
+{
+    //cout << "n=" << n << " m=" << m << " mm=" << mm << " g_l.N()=" << gl.N() << " g_u.N()=" << gu.N() << endl;
+    //assert(gl.N()==mm);
+    //assert(gu.N()==mm);
+    KnToPtr(xl,x_l);
+    KnToPtr(xu,x_u);
+    if(mm) KnToPtr(gl,g_l);
+    if(mm) KnToPtr(gu,g_u);
+    /* DEBUG
+     cout << "constraints lower bound = (";
+     for(int i=0;i<m;++i) cout << g_l[i] <<  (i<m-1 ? ',':')');
+     cout << endl << "constraints upper bound = (";
+     for(int i=0;i<m;++i) cout << g_u[i] <<  (i<m-1 ? ',':')');
+     cout << endl;*/
+    return true;
+}
+bool ffNLP::get_starting_point(Index n, bool init_x, Number* x,bool init_z, Number* z_L, Number* z_U,Index m, bool init_lambda,Number* lambda)
+{
+    assert(init_x == true);
+    assert(xstart->N() == n);
+    KnToPtr(*xstart,x);
+    if(init_z)
+    {
+        if(uz_start.N() != n)
+        {
+            if(xu.min() < 1.e19)
+            {
+                cout << "ff-IPOPT warm start : upper simple bounds start multipliers array doesn't have the expected size (" << uz_start.N() << "!=" << n << ")." << endl;
+                cout << "                   ";
+                if(uz_start.N()==0) cout << "maybe because no upper bounds multiplier has been given. " << endl;
+                cout << " Initializing them to 1..." << endl;
+            }
+            uz_start.resize(n);
+            uz_start=1.;
+        }
+        if(lz_start.N() != n)
+        {
+            if(xl.max() > -1e19)
+            {
+                cout << "ff-IPOPT warm start : lower simple bounds start multipliers array doesn't have the expected size (" << lz_start.N() << "!=" << n << ")." << endl;
+                cout << "                   ";
+                if(lz_start.N()==0) cout << "maybe because no lower bounds multiplier has been given. " << endl;
+                cout << " Initializing them to 1..." << endl;
+            }
+            lz_start.resize(n);
+            lz_start=1.;
+        }
+        KnToPtr(uz_start, z_U);
+        KnToPtr(lz_start, z_L);
+    }
+    if(init_lambda)
+    {
+        if(lambda_start.N() != m)
+        {
+            cout << "ff-IPOPT warm start : constraints start multipliers array doesn't have the expected size (" << lambda_start.N() << "!=" << m << ")." << endl;
+            cout << "                   ";
+            if(lambda_start.N()==0) cout << "maybe because no constraints multiplier has been given. " << endl;
+            cout << " Initializing them to 1..." << endl;
+            lambda_start.resize(m);
+            lambda_start=1.;
+        }
+        KnToPtr(lambda_start, lambda);
+    }
+    return true;
+}
+bool ffNLP::eval_f(Index n, const Number* x, bool new_x, Number& obj_value)
+{
+    assert(n == xstart->N());
+    Rn X(n);
+    KnFromPtr(X,x);
+    obj_value = fitness->J(X);
+    return true;
+}
+bool ffNLP::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
+{
+    assert(n == xstart->N());
+    Rn X(n);
+    KnFromPtr(X,x);
+    Rn _grad_f=dfitness->J(X);
+    KnToPtr(_grad_f,grad_f);
+    return true;
+}
+bool ffNLP::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g)
+{
+    Rn X(n);
+    KnFromPtr(X,x);
+    if(constraints)
+    {
+        Rn _g=constraints->J(X);
+        KnToPtr(_g,g);
+    }
+    return true;
+}
+bool ffNLP::eval_jac_g(Index n, const Number* x, bool new_x,Index m, Index nele_jac, Index* iRow, Index *jCol,Number* values)
+{
+    assert(n==xstart->N());
+    Rn X(n);
+    if(x) KnFromPtr(X,x); else X=*xstart;
+    
+    if(values==0)
+    {
+        int k=0;
+        for(SparseMatStructure::const_iterator i=JacStruct.begin(); i != JacStruct.end(); ++i)
+        {
+            iRow[k] = i->first;
+            jCol[k] = i->second;
+            ++k;
+        }
+    }
+    else if(dconstraints)
+    {
+        Matrice_Creuse<R>* M = dconstraints->J(X);
+        MatriceMorse<R> *MM = dynamic_cast<MatriceMorse<R>* >(&(*M->A));  //ugly!
+        for(int i=0;i<MM->N;++i)
+        {
+            for(int k=MM->lg[i]; k < MM->lg[i+1]; ++k)
+            {
+                if(checkstruct)
+                {
+                    int kipopt = FindIndex(JacStruct.Raws(),JacStruct.Cols(),i,MM->cl[k],0,nele_jac-1);
+                    if(kipopt>=0) values[kipopt] = MM->a[k];
+                }
+                else values[k] = MM->a[k];
+            }
+        }
+    }
+    return true;
+}
+
+
+bool ffNLP::eval_h(Index n, const Number* x, bool new_x,Number obj_factor, Index m, const Number* lambda,bool new_lambda, Index nele_hess, Index* iRow,Index* jCol, Number* values)
+{
+    Rn X(n),L(m);
+    if(x) KnFromPtr(X,x); else X=*xstart;
+    if(lambda) KnFromPtr(L,lambda); else L=0.;
+    
+    bool NLCHPE = hessian->NLCHPEnabled();
+    Number _obj_factor = NLCHPE ? 1. : obj_factor;
+    if(values==0)
+    {
+        int k=0;
+        for(SparseMatStructure::const_iterator i=HesStruct.begin(); i != HesStruct.end(); ++i)
+        {
+            iRow[k] = i->first;
+            jCol[k] = i->second;
+            ++k;
+        }
+    }
+    else
+    {
+        Matrice_Creuse<R>* M=0;
+        if(NLCHPE) M=hessian->J(X,obj_factor,L); else M=hessian->J(X);
+        MatriceMorse<R> *MM = dynamic_cast<MatriceMorse<R>* >(&(*M->A));//ugly!
+        if(MM)
+        {
+            if(checkstruct)
+            {
+                for(int i=0;i<MM->N;++i)
+                {
+                    for(int k=MM->lg[i]; k < MM->lg[i+1]; ++k)
+                    {
+                        int kipopt = FindIndex(HesStruct.Raws(),HesStruct.Cols(),i,MM->cl[k],0,nele_hess-1);
+                        if(kipopt>=0) values[kipopt] = _obj_factor * (MM->a[k]);
+                        //else values[k] = (hessian->paramof &&hessian->paramlm ? 1. : obj_factor) * (MM->a[k]);
+                    }
+                }
+            }
+            else if(! MM->symetrique)
+            {
+                for(int i=0,kipopt=0;i<MM->N;++i)
+                {
+                    for(int k=MM->lg[i]; k < MM->lg[i+1]; ++k)
+                    {
+                        if(i >= MM->cl[k])
+                        {
+                            values[kipopt] = _obj_factor * (MM->a[k]);
+                            ++kipopt;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                for(int i=0;i<MM->N;++i)
+                {
+                    for(int k=MM->lg[i]; k < MM->lg[i+1]; ++k) values[k] = _obj_factor * (MM->a[k]);
+                }
+            }
+        }
+    }
+    return true;
+}
+
+
+void ffNLP::finalize_solution(SolverReturn status,
+                              Index n, const Number* x, const Number* z_L, const Number* z_U,
+                              Index m, const Number* g, const Number* lambda,
+                              Number obj_value,const IpoptData* ip_data,
+                              IpoptCalculatedQuantities* ip_cq)
+{
+    KnFromPtr(*xstart,x);
+    KnFromPtr(lambda_start,lambda);
+    KnFromPtr(lz_start, z_L);
+    KnFromPtr(uz_start, z_U);
+    final_value = obj_value;
+}
+
+
+
+/*****************************************************************************************************************************
+ *	Assumptions : these are tags used as template parameters for case specific function wrapping or warning message in the
+ *                interface. Some case can be added here (but some class has to be specialized for the new cases)
+ *  AssumptionF : undeff              --> undefined case (not used)
+ *                no_assumption_f     --> most general case when the fitness function and all its derivative are coded in the
+ *                                        freefem script with the func keyword (type Polymorphic in c++). These functions
+ *                                        are then wrapped in GeneralFunc objects.
+ *                P2_f                --> no longer used (it was used for fitness and its gradient defined as func in freefem
+ *                                        script, while the hessian is a constant matrix directly given to the interface, but
+ *                                        it leads to ambiguities).
+ *                unavailable_hessian --> fitness function and its gradients coded with func in the ff script, wrapped into
+ *                                        GeneralFunc objects, without second order derivative function. Enables the BFGS
+ *                                        option of IPOPT.
+ *                mv_P2_f             --> fitness function is a P2 function which will be defined by a [matrix,vector] array.
+ *                                        The functions are passed to the ffNLP object as P2ScalarFunc, P1VectorFunc and
+ *                                        ConstantSparseMatFunc respectively for the fitness function, its gradient and its
+ *                                        hessian (with all vf=1).
+ *                quadratic_f         --> f is a pure quadratic fonction, defined by a single matrix. Same type as mv_P2_f
+ *                                        for function wrappers with a vf=0 tag.
+ *                linear_f            --> f is a linear form, defined by a single vector. Same type as mv_P2_f
+ *                                        for function wrappers with a vf=0 tag.
+ *  AssumptionG : undeff              --> undefined case (not used)
+ *                no_assumption_f     --> most general case when the constraint functions and all its derivative are coded in
+ *                                        the freefem script with the func keyword (type Polymorphic in c++). These functions
+ *                                        are then wrapped in GeneralFunc objects.
+ *                P1_g                --> no longer used (it was used for constraints defined as func in freefem script
+ *                                        , while the jacobian is a constant matrix directly given to the interface, but
+ *                                        it leads to ambiguities).
+ *                mv_P1_g             --> Constraints function is a P1 function which will be defined by a [matrix,vector]
+ *                                        array. The functions are passed to the ffNLP object as P1VectorFunc and
+ *                                        ConstantSparseMatFunc respectively for the constraints and its jacobian (with
+ *                                        all vf=0).
+ *                linear_g            --> Constraints are linear, defined by a single matrix. Same type as mv_P1_g
+ *                                        for function wrappers with a vf=0 tag.
+ *  Case : templatized with a pair of AssumptionF and AssumptionG, is used to build different constructor for the interface
+ *         class in order to overload the freefem function which will call IPOPT
+ *****************************************************************************************************************************/
+
+
+enum AssumptionF {undeff,no_assumption_f, P2_f, unavailable_hessian, mv_P2_f, quadratic_f, linear_f};
+enum AssumptionG {undefg,without_constraints, no_assumption_g, P1_g, mv_P1_g, linear_g};
+
+template<AssumptionF AF,AssumptionG AG> struct Case
+{
+    Case() {}
+    static const AssumptionF af=AF;
+    static const AssumptionG ag=AG;
+};
+
+
+/*****************************************************************************************************************************
+ *	CheckMatrixVectorPair : Small function taking an E_Array and check whether the type of the 2 objects contained in the
+ *  array are matrix and vector. Returns false if types are not matrix/vector.
+ *  order is modified to know whether the matrix is in first position or not.
+ *****************************************************************************************************************************/
+bool CheckMatrixVectorPair(const E_Array *mv,bool &order)
+{
+    const aType t1 = (*mv)[0].left(), t2 = (*mv)[1].left();
+    if(NXOR(t1 == atype<Matrice_Creuse<R>*>() , t2 == atype<Matrice_Creuse<R>*>())) return false;
+    else if(NXOR(t1 == atype<Rn*>(),t2 == atype<Rn*>())) return false;
+    else
+    {
+        order = (t1 == atype<Matrice_Creuse<R>*>());
+        return true;
+    }
+}
+
+
+/*****************************************************************************************************************************
+ *	The following class offers a polymorphic way to build the function wrappers to pass to the ffNLP object
+ *  Each element of the assumption enum define a "FunctionDatas" class in which the constructor and the operator() makes
+ *  case specific task.
+ *  If some new value in the Assumption enums are to be added, the FitnessFunctionDatas and/or ConstraintFunctionDatas with
+ *  the new value as template parameter has to be specialized.
+ *  What should the method do is (exemple at the end of the file with already coded cases):
+ *  Constructor : define the Expression members using the arguments passed to the IPOPT function in the script
+ *  operator()  : allocate with appropriate dynamic type the ScalarFunc, VectorFunc, SparseMatFunc pointers, and display some
+ *                case dependant errors or warnings (note that there is no ScalarFunc ptr to allocate for constraints)
+ *****************************************************************************************************************************/
+class GenericFitnessFunctionDatas
+{
+public:
+    static GenericFitnessFunctionDatas* New(AssumptionF,const basicAC_F0 &,Expression const *,const C_F0&,const C_F0&,const C_F0&);
+    bool CompletelyNonLinearConstraints;
+    Expression JJ,GradJ,Hessian;
+    GenericFitnessFunctionDatas() : CompletelyNonLinearConstraints(true),JJ(0),GradJ(0),Hessian(0) {}
+    virtual const AssumptionF A() const {return undeff;}
+    virtual void operator()(Stack,const C_F0&,const C_F0&,const C_F0&,Expression const *,ScalarFunc *&,VectorFunc *&,SparseMatFunc *&,bool) const = 0; //Build the functions
+    virtual ~GenericFitnessFunctionDatas() {}
+};
+template<AssumptionF AF> class FitnessFunctionDatas : public GenericFitnessFunctionDatas  //not really a template, since most of the methods of all cases have to be specialized
+{
+public:
+    FitnessFunctionDatas(const basicAC_F0 &,Expression const *,const C_F0 &,const C_F0 &,const C_F0 &);
+    const AssumptionF A() const {return AF;}
+    void operator()(Stack,const C_F0&,const C_F0&,const C_F0&,Expression const *,ScalarFunc *&,VectorFunc *&,SparseMatFunc *&,bool) const;
+    
+};
+
+class GenericConstraintFunctionDatas
+{
+public:
+    static GenericConstraintFunctionDatas* New(AssumptionG,const basicAC_F0 &,Expression const *,const C_F0 &);
+    Expression Constraints,GradConstraints;
+    GenericConstraintFunctionDatas() : Constraints(0),GradConstraints(0) {}
+    virtual const AssumptionG A() const {return undefg;}
+    virtual const bool WC() const =0;//with constraints
+    virtual void operator()(Stack,const C_F0 &,Expression const *,VectorFunc *&,SparseMatFunc *&,bool) const = 0;//build the functions`
+    virtual  ~GenericConstraintFunctionDatas() {}
+    
+};
+template<AssumptionG AG> class ConstraintFunctionDatas : public GenericConstraintFunctionDatas
+{
+public:
+    ConstraintFunctionDatas(const basicAC_F0 &,Expression const *,const C_F0 &);
+    const AssumptionG A() const {return AG;}
+    const bool WC() const {return AG!=without_constraints;}
+    void operator()(Stack,const C_F0&,Expression const *,VectorFunc *&,SparseMatFunc *&,bool) const ;
+};
+
+
+
+
+/*****************************************************************************************************************************
+ *	OptimIpopt & OptimIpopt::E_Ipopt - The interface class
+ *  Do the link beetween freefem and Ipopt
+ *****************************************************************************************************************************/
+class OptimIpopt : public OneOperator
+{
+public:
+    const AssumptionF AF;
+    const AssumptionG AG;
+    class E_Ipopt : public E_F0mps
+    {
+    private:
+        bool spurious_cases;
+    public:
+        const AssumptionF AF;
+        const AssumptionG AG;
+        const bool WC;
+        std::set<unsigned short> unused_name_param; //In some case, some parameter are usless, this is the list of their index in nargs
+        void InitUNP(); //Initialize unusued_name_param at freefem compile time
+        static basicAC_F0::name_and_type name_param[];
+        static const int n_name_param=29;
+        Expression nargs[n_name_param];
+        Expression X;
+        mutable Rn lm;
+        C_F0 L_m;
+        C_F0 inittheparam,theparam,closetheparam;
+        C_F0 initobjfact,objfact;
+        GenericFitnessFunctionDatas * fitness_datas;
+        GenericConstraintFunctionDatas * constraints_datas;
+        bool arg(int i,Stack stack,bool a) const {return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+        long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+        R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+        Rn_ arg(int i,Stack stack,Rn_ a) const {return nargs[i] ? GetAny<Rn_>((*nargs[i])(stack)) : a;}
+        template<typename T> T Arg(int i,Stack s) const {return GetAny<T>( (*nargs[i])(s));}
+        
+        E_Ipopt(const basicAC_F0 & args,AssumptionF af,AssumptionG ag)
+        : lm(),L_m(CPValue(lm)),AF(af),AG(ag),WC(ag!=without_constraints),unused_name_param(),
+        spurious_cases(false),fitness_datas(0),constraints_datas(0)
+        {
+            InitUNP();
+            int nbj= args.size()-1;
+            Block::open(currentblock); // make a new block to
+            X = to<Rn*>(args[nbj]);
+            C_F0 X_n(args[nbj],"n");
+            //  the expression to init the theparam of all
+            inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+            initobjfact = currentblock->NewVar<LocalVariable>("objective factor",atype<double *>());
+            //C_F0 initlm = currentblock->NewVar<LocalVariable>("lagrange multiplier",atype<KN<R> *>(),L_m);
+            theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+            objfact = currentblock->Find("objective factor");
+            args.SetNameParam(n_name_param,name_param,nargs);
+            fitness_datas = GenericFitnessFunctionDatas::New(AF,args,nargs,theparam,objfact,L_m); //Creates links to the freefem objects
+            constraints_datas = GenericConstraintFunctionDatas::New(AG,args,nargs,theparam);      //defining the functions
+            spurious_cases = AG==no_assumption_g && (AF==P2_f || AF==mv_P2_f || AF==quadratic_f || AF==linear_f);
+            closetheparam=currentblock->close(currentblock);   // the cleanning block expression
+        }
+        ~E_Ipopt()
+        {
+            if(fitness_datas) delete fitness_datas;
+            if(constraints_datas) delete constraints_datas;
+        }
+        
+        
+        virtual AnyType operator()(Stack stack)  const
+        {
+            double cost = nan("");
+            WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005
+            Rn &x = *GetAny<Rn *>((*X)(stack));
+            {
+                Expression test(theparam); //in some case the KN object associated to the param is never initialized, leading to failed assertion in KN::destroy
+                Rn *tt = GetAny<Rn *>((*test)(stack)); //this lines prevent this to happen
+                *tt = x;
+            }
+            long n=x.N();
+            bool warned=false;
+            cout << endl;
+            if(spurious_cases)
+            {
+                cout << "ff-IPOPT Spurious case detected : the hessian is defined as a constant matrix but constraints are given in function form." << endl;
+                cout << "If they are not affine, the optimization is likely to fail. In this case, try one of the following suggestions:" << endl;
+                cout << "  - if constraints have computable hessians, use function form for the fitness function and all its derivatives" << endl;
+                cout << "    and check the documentation to know how to express the whole lagrangian hessian." << endl;
+                cout << "  - if constraints hessians are difficult to obtain, force the BFGS mode using named parameter "<< name_param[12].name<< '.' << endl;
+                cout << "Do not worry about this message if you know all your constraints has a constant null hessian." << endl << endl;
+            }
+            if(nargs[7]) cout << "ff-IPOPT : the named parameter autostruct is no longer used in this version of the interface." << endl;
+            //Detection of mixed case dependant warnings or error
+            for(int i=0;i<n_name_param;++i)
+                if(nargs[i] && unused_name_param.find(i)!=unused_name_param.end())
+                {
+                    cout << "ff-IPOPT Warning: named parameter " << name_param[i].name << " is useless for the problem you have set." << endl;
+                    warned = true;
+                }
+            if(nargs[4] && nargs[5] && nargs[7])
+            {
+                cout << "ff-IPOPT Warning: both " << name_param[4].name << " and " << name_param[5].name << " has been defined, so " << name_param[7].name;
+                cout << " will be ignored." << endl;
+            }
+            if(warned)
+            {
+                if(!WC && AF==unavailable_hessian && nargs[8])
+                {
+                    cout << "  ==> " << name_param[8].name << " is useless because there should not be any function returning matrix in your problem," << endl;
+                    cout << "      (2 functions can only be J and dJ). You may as well have forgotten one function (IPOPT will certainly crash if so)." << endl;
+                }
+                if(AF!=no_assumption_f && AF!=unavailable_hessian && AG!=no_assumption_g && nargs[5])
+                {
+                    cout << "  ==> your lagrangian hessian is a constant matrix, so there is no need to specify its structure with " << name_param[5].name << endl;
+                    cout << "      since it is contained in the matrix object." << endl;
+                }
+                if(AF!=no_assumption_f && AF!=unavailable_hessian && AG!=no_assumption_g && nargs[7])
+                {
+                    cout << "  ==> " << name_param[7].name << " will be ignored since all matrices are constants and constraints do not" << endl;
+                    cout << "      contribute to the hessian, matrix structure determination is trivial." << endl;
+                }
+                if(AF==unavailable_hessian && AG!=no_assumption_g && (nargs[7] || nargs[8]))
+                {
+                    cout << "  ==> " << name_param[7].name << " or " << name_param[8].name << " will be ignored since the only matrix you have passed is constant. " << endl;
+                    cout << "      Or maybe did you forget to pass a function (IPOPT will certainly crash if so)." << endl;
+                }
+                if(AF!=no_assumption_f && AF!=unavailable_hessian && AG!=no_assumption_g && nargs[8])
+                {
+                    cout << "  ==> no need to use " << name_param[8].name << " since all matrices are constant, structures won't change through the algorithm," << endl;
+                    cout << "      it is automatically set to the default disabling value." << endl;
+                }
+            }
+            
+            long iprint = verbosity;
+            
+            ScalarFunc *ffJ=0;
+            VectorFunc *ffdJ=0,*ffC=0;
+            SparseMatFunc *ffH=0,*ffdC=0;
+            
+            (*fitness_datas)(stack,theparam,objfact,L_m,nargs,ffJ,ffdJ,ffH,warned);//Fill the functions
+            (*constraints_datas)(stack,theparam,nargs,ffC,ffdC,warned);
+            
+            Rn xl(n),xu(n),gl(nargs[2] ? Arg<Rn_>(2,stack).N() : 0),gu(nargs[3] ? Arg<Rn_>(3,stack).N() : 0);
+            int mmm=0;
+            if(WC && (gl.N()+gu.N())==0)
+            {
+                cout << "IPOPT Warning : constrained problem without constraints bounds." << endl;
+                mmm = ffC->J(x).N();
+            }
+            else mmm=gl.N()>gu.N() ? gl.N() : gu.N();
+            Rn_ *lag_mul=0,*l_z=0,*u_z=0;//Rn(mmm,1.);
+            //int niter=arg(6,stack,100L);
+            int autostructmode = ffNLP::one_evaluation;
+            bool checkindex = (AF!=no_assumption_f && AG!=no_assumption_g) ? false : arg(8,stack,true), cberror=false;
+            
+            if(nargs[0]) xl=Arg<Rn_>(0,stack); else xl=-1.e19;
+            if(nargs[1]) xu=Arg<Rn_>(1,stack); else xu=1.e19;
+            if(nargs[2]) gl=Arg<Rn_>(2,stack); else {gl.resize(mmm); gl=-1.e19;}
+            if(nargs[3]) gu=Arg<Rn_>(3,stack); else {gu.resize(mmm); gu=1.e19;}
+            const E_Array * ejacstruct = (WC && AF==no_assumption_f && AG==no_assumption_g && nargs[4]) ? dynamic_cast<const E_Array *> (nargs[4]) : 0,
+            * ehesstruct = (AF==no_assumption_f && nargs[5]) ? dynamic_cast<const E_Array *> (nargs[5]) : 0;
+            
+            if(nargs[6] && WC) lag_mul = new Rn_(GetAny<Rn_>((*nargs[6])(stack)));
+            if(nargs[21]) l_z = new Rn_(GetAny<Rn_>((*nargs[21])(stack)));
+            if(nargs[20]) u_z = new Rn_(GetAny<Rn_>((*nargs[20])(stack)));
+            
+            
+            SmartPtr<TNLP> optim = new ffNLP(x,xl,xu,gl,gu,ffJ,ffdJ,ffH,ffC,ffdC);
+            ffNLP * _optim = dynamic_cast<ffNLP *> (&(*optim));
+            assert(_optim);
+            if(WC && nargs[6]) _optim->lambda_start = *lag_mul;
+            else if(WC)
+            {
+                _optim->lambda_start.resize(mmm);
+                _optim->lambda_start = 1.;
+            }
+            _optim->sigma_start = 1.;
+            if(nargs[21] && nargs[0]) _optim->lz_start = *l_z;
+            else if(nargs[0]) {_optim->lz_start.resize(xl.N()); _optim->lz_start = 1.;}
+            if(nargs[20] && nargs[1]) _optim->uz_start = *u_z;
+            else if(nargs[1]) {_optim->uz_start.resize(xu.N()); _optim->uz_start = 1.;}
+            
+            if(ejacstruct)
+            {
+                if(ejacstruct->nbitem()!=2) ExecError("\nSorry, we were expecting an array with two componants in structjac=[iraw,jcol]");
+                if((*ejacstruct)[0].left() != atype<KN<long> *>()) CompileError("Sorry, array componants in structjac=[iraw,jcol] must be integer arrays");
+                if((*ejacstruct)[1].left() != atype<KN<long> *>()) CompileError("Sorry, array componants in structjac=[iraw,jcol] must be integer arrays");
+                Expression raws = (*ejacstruct)[0], cols = (*ejacstruct)[1];
+                _optim->SetJacobianStructure(*GetAny<KN<long>*>((*raws)(stack)),*GetAny<KN<long>*>((*cols)(stack)),true);
+            }
+            if(ehesstruct)
+            {
+                if(ehesstruct->nbitem()!=2) ExecError("\nSorry, we were expecting an array with two componants in structhess=[iraw,jcol]");
+                if((*ehesstruct)[0].left() != atype<KN<long> *>()) CompileError("Sorry, array componants in structhess=[iraw,jcol] must be integer arrays");
+                if((*ehesstruct)[1].left() != atype<KN<long> *>()) CompileError("Sorry, array componants in structhess=[iraw,jcol] must be integer arrays");
+                Expression raws = (*ehesstruct)[0], cols = (*ehesstruct)[1];
+                _optim->SetHessianStructure(*GetAny<KN<long>*>((*raws)(stack)),*GetAny<KN<long>*>((*cols)(stack)),true);
+            }
+            ffNLP::Level lh=ehesstruct ? ffNLP::user_defined : ffNLP::Level(autostructmode),lj=ejacstruct ? ffNLP::user_defined : ffNLP::Level(autostructmode);
+            if(AF==unavailable_hessian) lh=ffNLP::do_nothing;
+            _optim->BuildMatrixStructures(lh,lj,mmm);
+            if(checkindex) _optim->EnableCheckStruct();
+            
+            SmartPtr<IpoptApplication> app = new IpoptApplication();
+            
+            //app->Options()->SetNumericValue("tol", 1e-10);
+            if(nargs[9]) app->Options()->SetNumericValue("tol",GetAny<double>((*nargs[9])(stack)));
+            if(nargs[10]) app->Options()->SetIntegerValue("max_iter",GetAny<long>((*nargs[10])(stack)));
+            if(nargs[11]) app->Options()->SetNumericValue("max_cpu_time",GetAny<double>((*nargs[11])(stack)));
+            bool bfgs = nargs[12] ? GetAny<bool>((*nargs[12])(stack)) : false;
+            //app->Options()->SetStringValue("hessian_approximation","limited-memory");
+            if(AF==unavailable_hessian || bfgs)
+            {
+                if(AF==unavailable_hessian && !bfgs) cout << "IPOPT Note : No hessian given ==> LBFGS hessian approximation enabled" << endl;
+                app->Options()->SetStringValue("hessian_approximation","limited-memory");
+            }
+            if(nargs[13])
+            {
+                string derivative_test = *GetAny<string*>((*nargs[13])(stack)) ;
+                app->Options()->SetStringValue("derivative_test",derivative_test.c_str());
+            }
+            if(nargs[14])
+            {
+                string options_file = *GetAny<string*>((*nargs[14])(stack));
+                app->Options()->SetStringValue("option_file_name",options_file.c_str());
+            }
+            if(nargs[15]) app->Options()->SetIntegerValue("print_level",GetAny<long>((*nargs[15])(stack)));
+            if(AG==without_constraints || AG==mv_P1_g || AG==linear_g)
+            {
+                app->Options()->SetStringValue("jac_c_constant","yes");
+                app->Options()->SetStringValue("jac_d_constant","yes");
+            }
+            if(AF==mv_P2_f || AF==quadratic_f || AF==linear_f) app->Options()->SetStringValue("hessian_constant","yes");
+            if(nargs[16]) app->Options()->SetNumericValue("derivative_test_perturbation",GetAny<double>((*nargs[16])(stack)));
+            if(nargs[17]) app->Options()->SetNumericValue("derivative_test_tol",GetAny<double>((*nargs[16])(stack)));
+            if(nargs[18]) app->Options()->SetStringValue("fixed_variable_treatment",GetAny<string*>((*nargs[18])(stack))->c_str());
+            if(nargs[19])
+            {
+                app->Options()->SetStringValue("warm_start_init_point","yes");
+                if(WC && !nargs[6])
+                {
+                    cout << "ff-IPOPT Warning : warm start for constrained problem without initial constraints dual variables (" << name_param[6].name << " parameter)." << endl;
+                    cout << "                   ==> Starting with " << name_param[6].name << "=(1,1,...,1)." << endl;
+                }
+                if(nargs[0] && !nargs[21])
+                {
+                    cout << "ff-IPOPT Warning : warm start with simple lower bounds without initial lower bounds dual variables (" << name_param[21].name << " parameter)." << endl;
+                    cout << "                   ==> Starting with " << name_param[21].name << "=(1,1,...,1)." << endl;
+                }
+                if(nargs[1] && !nargs[20])
+                {
+                    cout << "ff-IPOPT Warning : warm start with simple upper bounds without initial upper bounds dual variables (" << name_param[20].name << " parameter)." << endl;
+                    cout << "                   ==> Starting with " << name_param[20].name << "=(1,1,...,1)." << endl;
+                }
+                if(l_z) _optim->lz_start = *l_z;
+                if(u_z) _optim->uz_start = *u_z;
+                if(lag_mul) _optim->lambda_start = *lag_mul;
+            }
+            
+            if(nargs[22]) app->Options()->SetNumericValue("mu_init",GetAny<double>((*nargs[22])(stack)));
+            else app->Options()->SetStringValue("mu_strategy", "adaptive");
+            if(nargs[23]) app->Options()->SetNumericValue("mumps_pivtol",GetAny<double>((*nargs[23])(stack)));
+            if(nargs[24]) app->Options()->SetNumericValue("bound_relax_factor",GetAny<double>((*nargs[24])(stack)));
+            if(nargs[25]) app->Options()->SetStringValue("mu_strategy",GetAny<string*>((*nargs[25])(stack))->c_str());
+            if(nargs[27]) app->Options()->SetNumericValue("mu_min",GetAny<double>((*nargs[27])(stack)));
+            if(nargs[28]) if(!GetAny<bool>((*nargs[28])(stack))) app->Options()->SetStringValue("accept_every_trial_step","yes");
+            //if(nargs[26]) app->Options()->SetNumericValue("obj_scaling_factor",GetAny<double>((*nargs[26])(stack)));
+            if(verbosity>1) app->Options()->SetStringValue("print_user_options","yes");
+            app->Options()->SetStringValue("output_file", "ipopt.out");
+            if(AF!=no_assumption_f && AF!=unavailable_hessian && AG!=no_assumption_g) app->Options()->SetStringValue("mehrotra_algorithm", "yes");
+            
+            ApplicationReturnStatus status;
+            app->Initialize();
+            
+            // Ask Ipopt to solve the problem
+            status = app->OptimizeTNLP(optim);
+            
+            if(lag_mul) *lag_mul = _optim->lambda_start;
+            if(l_z) *l_z = _optim->lz_start;
+            if(u_z) *u_z = _optim->uz_start;
+            cost = _optim->final_value;
+            
+            if(nargs[26])
+            {
+                double *pfv = GetAny<double*>((*nargs[26])(stack));
+                *pfv = cost;
+            }
+            if(verbosity)
+            {
+                if(status == Solve_Succeeded) printf("\n\n*** Ipopt succeeded \n");
+                else if(static_cast<int>(status)<0) printf("\n\n*** Ipopt failure!\n");
+                else printf("\n\n*** Ipopt mixed results.\n");
+            }
+            
+            
+            clean(lag_mul);
+            clean(l_z);
+            clean(u_z);
+            clean(ffJ);
+            clean(ffdJ);
+            clean(ffH);
+            clean(ffC);
+            clean(ffdC);
+            if(lm) lm.destroy(); // clean memory of LM
+            closetheparam.eval(stack); // clean memory
+            WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005
+            return SetAny<long>(static_cast<long>(static_cast<int>(status))); //SetAny<long>(0);  Modif FH  july 2005
+        }
+        
+        operator aType () const { return atype<long>();}
+        
+    };
+    
+    E_F0 * code(const basicAC_F0 & args) const {return new E_Ipopt(args,AF,AG);}
+    
+    //Constructors - they define the different prototype of the overloaded IPOPT function reachable in freefem scripts
+    
+    OptimIpopt(Case<no_assumption_f,no_assumption_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<KN<R> *>()),
+    AF(no_assumption_f),AG(no_assumption_g) {}
+    OptimIpopt(Case<no_assumption_f,without_constraints>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<KN<R> *>()),
+    AF(no_assumption_f),AG(without_constraints) {}
+    OptimIpopt(Case<no_assumption_f,P1_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R> *>(),atype<KN<R> *>()),
+    AF(no_assumption_f),AG(P1_g) {}
+    OptimIpopt(Case<no_assumption_f,mv_P1_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<E_Array>(),atype<KN<R> *>()),
+    AF(no_assumption_f),AG(mv_P1_g) {}
+    OptimIpopt(Case<no_assumption_f,linear_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R> *>()),
+    AF(no_assumption_f),AG(linear_g) {}
+    
+    
+    OptimIpopt(Case<P2_f,P1_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R> *>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R> *>(),atype<KN<R> *>()),
+    AF(P2_f),AG(P1_g) {}
+    OptimIpopt(Case<P2_f,without_constraints>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R> *>(),atype<KN<R> *>()),
+    AF(P2_f),AG(without_constraints) {}
+    OptimIpopt(Case<P2_f,no_assumption_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R> *>(),atype<Polymorphic*>(),atype<Polymorphic *>(),atype<KN<R> *>()),
+    AF(P2_f),AG(no_assumption_g) {}
+    OptimIpopt(Case<P2_f,mv_P1_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<E_Array>(),atype<KN<R> *>()),
+    AF(P2_f),AG(mv_P1_g) {}
+    OptimIpopt(Case<P2_f,linear_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R> *>()),
+    AF(P2_f),AG(linear_g) {}
+    
+    OptimIpopt(Case<unavailable_hessian,no_assumption_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<KN<R> *>()),
+    AF(unavailable_hessian),AG(no_assumption_g) {}
+    OptimIpopt(Case<unavailable_hessian,without_constraints>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<KN<R> *>()),AF(unavailable_hessian),AG(without_constraints) {}
+    OptimIpopt(Case<unavailable_hessian,P1_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R> *>()),
+    AF(unavailable_hessian),AG(P1_g) {}
+    OptimIpopt(Case<unavailable_hessian,mv_P1_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<E_Array>(),atype<KN<R>*>()),
+    AF(unavailable_hessian),AG(mv_P1_g) {}
+    OptimIpopt(Case<unavailable_hessian,linear_g>) :
+    OneOperator(atype<long>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(unavailable_hessian),AG(linear_g) {}
+    
+    OptimIpopt(Case<mv_P2_f,no_assumption_g>) :
+    OneOperator(atype<long>(),atype<E_Array>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<KN<R>*>()),
+    AF(mv_P2_f),AG(no_assumption_g) {}
+    OptimIpopt(Case<mv_P2_f,without_constraints>) :
+    OneOperator(atype<long>(),atype<E_Array>(),atype<KN<R>*>()),
+    AF(mv_P2_f),AG(without_constraints) {}
+    OptimIpopt(Case<mv_P2_f,P1_g>) :
+    OneOperator(atype<long>(),atype<E_Array>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(mv_P2_f),AG(P1_g) {}
+    OptimIpopt(Case<mv_P2_f,mv_P1_g>) :
+    OneOperator(atype<long>(),atype<E_Array>(),atype<E_Array>(),atype<KN<R>*>()),
+    AF(mv_P2_f),AG(mv_P1_g) {}
+    OptimIpopt(Case<mv_P2_f,linear_g>) :
+    OneOperator(atype<long>(),atype<E_Array>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(mv_P2_f),AG(linear_g) {}
+    
+    OptimIpopt(Case<quadratic_f,no_assumption_g>) :
+    OneOperator(atype<long>(),atype<Matrice_Creuse<R>*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<KN<R>*>()),
+    AF(quadratic_f),AG(no_assumption_g) {}
+    OptimIpopt(Case<quadratic_f,without_constraints>) :
+    OneOperator(atype<long>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(quadratic_f),AG(without_constraints) {}
+    OptimIpopt(Case<quadratic_f,P1_g>) :
+    OneOperator(atype<long>(),atype<Matrice_Creuse<R>*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(quadratic_f),AG(P1_g) {}
+    OptimIpopt(Case<quadratic_f,mv_P1_g>) :
+    OneOperator(atype<long>(),atype<Matrice_Creuse<R>*>(),atype<E_Array>(),atype<KN<R>*>()),
+    AF(quadratic_f),AG(mv_P1_g) {}
+    OptimIpopt(Case<quadratic_f,linear_g>) :
+    OneOperator(atype<long>(),atype<Matrice_Creuse<R>*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(quadratic_f),AG(linear_g) {}
+    
+    
+    OptimIpopt(Case<linear_f,no_assumption_g>) :
+    OneOperator(atype<long>(),atype<KN<R>*>(),atype<Polymorphic*>(),atype<Polymorphic*>(),atype<KN<R>*>()),
+    AF(linear_f),AG(no_assumption_g) {}
+    OptimIpopt(Case<linear_f,without_constraints>) :
+    OneOperator(atype<long>(),atype<KN<R>*>(),atype<KN<R>*>()),
+    AF(linear_f),AG(without_constraints) {}
+    OptimIpopt(Case<linear_f,P1_g>) :
+    OneOperator(atype<long>(),atype<KN<R>*>(),atype<Polymorphic*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(linear_f),AG(P1_g) {}
+    OptimIpopt(Case<linear_f,mv_P1_g>) :
+    OneOperator(atype<long>(),atype<KN<R>*>(),atype<E_Array>(),atype<KN<R>*>()),
+    AF(linear_f),AG(mv_P1_g) {}
+    OptimIpopt(Case<linear_f,linear_g>) :
+    OneOperator(atype<long>(),atype<KN<R>*>(),atype<Matrice_Creuse<R>*>(),atype<KN<R>*>()),
+    AF(linear_f),AG(linear_g) {}
+    
+};
+
+
+
+/*
+ enum AssumptionF {no_assumption_f, P2_f, unavailable_hessian, mv_P2_f, quadratic_f,linear_f};
+ enum AssumptionG {without_constraints, no_assumption_g, P1_g, mv_P1_g, linear_g};
+ */
+
+//Case dependant initialization of unused_name_param
+//exemple : AF==no_assumption_f && AG==without_constraints ==> no constraint related named parameter should be used (index 2,3,4,6 - first integer is how many are not used)
+void OptimIpopt::E_Ipopt::InitUNP()
+{
+    if(AF==no_assumption_f && AG==no_assumption_g) {} //no unused named parameter
+    if(AF==no_assumption_f && AG==without_constraints)			AddElements(unused_name_param,4,2,3,4,6);
+    if(AF==no_assumption_f && AG==P1_g)											AddElements(unused_name_param,1,4);
+    if(AF==no_assumption_f && AG==mv_P1_g)									AddElements(unused_name_param,1,4);
+    if(AF==no_assumption_f && AG==linear_g)									AddElements(unused_name_param,1,4);
+    if(AF==P2_f	&& AG==P1_g)																AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==P2_f && AG==without_constraints)									AddElements(unused_name_param,8,2,3,4,5,6,7,8,12);
+    if(AF==P2_f && AG==no_assumption_g)											AddElements(unused_name_param,1,5);
+    if(AF==P2_f && AG==mv_P1_g)															AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==P2_f && AG==linear_g)														AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==unavailable_hessian && AG==no_assumption_g)			AddElements(unused_name_param,1,5);
+    if(AF==unavailable_hessian && AG==without_constraints)	AddElements(unused_name_param,7,2,3,4,5,6,7,8);
+    if(AF==unavailable_hessian && AG==P1_g)									AddElements(unused_name_param,4,4,5,7,8);
+    if(AF==unavailable_hessian && AG==mv_P1_g)							AddElements(unused_name_param,4,4,5,7,8);
+    if(AF==unavailable_hessian && AG==linear_g)							AddElements(unused_name_param,4,4,5,7,8);
+    if(AF==mv_P2_f && AG==without_constraints)							AddElements(unused_name_param,8,2,3,4,5,6,7,8,12);
+    if(AF==mv_P2_f && AG==no_assumption_g)									AddElements(unused_name_param,1,5);
+    if(AF==mv_P2_f && AG==P1_g)															AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==mv_P2_f && AG==mv_P1_g)													AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==mv_P2_f && AG==linear_g)													AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==quadratic_f && AG==without_constraints)					AddElements(unused_name_param,8,2,3,4,5,6,7,8,12);
+    if(AF==quadratic_f && AG==no_assumption_g)							AddElements(unused_name_param,1,5);
+    if(AF==quadratic_f && AG==P1_g)													AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==quadratic_f && AG==mv_P1_g)											AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==quadratic_f && AG==linear_g)											AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==linear_f && AG==without_constraints)							AddElements(unused_name_param,8,2,3,4,5,6,7,8,12);
+    if(AF==linear_f && AG==no_assumption_g)									AddElements(unused_name_param,1,5);
+    if(AF==linear_f && AG==P1_g)														AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==linear_f && AG==mv_P1_g)													AddElements(unused_name_param,5,4,5,7,8,12);
+    if(AF==linear_f && AG==linear_g)												AddElements(unused_name_param,5,4,5,7,8,12);
+}
+
+
+
+basicAC_F0::name_and_type  OptimIpopt::E_Ipopt::name_param[]=
+{
+    //DONT CHANGE THE ORDER!!!! If some parameters need to be added, add them after the last one
+    //otherwize warning message of this interface will be a mess
+    {"lb",				&typeid(KN_<double>) },									//0  -  lower bound on optimization parameter X
+    {"ub",				&typeid(KN_<double>) },									//1  -  upper bound on optimization parameter X
+    {"clb",				&typeid(KN_<double>) },									//2  -  constraints lower bounds
+    {"cub",				&typeid(KN_<double>) },									//3  -  constraints upper bounds
+    {"structjacc",&typeid(E_Array)},											//4  -  constraints jacobian structure
+    {"structhess",&typeid(E_Array)},											//5  -  lagrangian hessian structure
+    {"lm",				&typeid(KN_<double>)},									//6  -  lagrange multiplier (for autostruct or to get their value at the end of the algorithm)
+    {"autostruct",&typeid(long)},													//7  -  automatic structure determination
+    {"checkindex",&typeid(bool)},													//8  -  whether to use the FindIndex function or not
+    {"tol",				&typeid(double)},												//9  -  stopping criteria tol
+    {"maxiter",		&typeid(long)},													//10 -  stopping criteria : maximum number of iterations
+    {"maxcputime",&typeid(double)},												//11 -  stopping criteria : maximum CPU time
+    {"bfgs",      &typeid(bool)},													//12 -  force the bfgs hessian approximation
+    {"derivativetest", &typeid(string*)},									//13 -  call the derivative checker
+    {"optfile",		&typeid(string*)},											//14 -  set the ipopt option file name (default is ipopt.opt)
+    {"printlevel",&typeid(long)},													//15 -  controls IPOPT print level output
+    {"dth",				&typeid(double)},												//16 -  perturbation for finite difference derivative test
+    {"dttol",			&typeid(double)},												//17 -  relative tolerence for the derivative test error detection
+    {"fixedvar",	&typeid(string*)},											//18 -  remove the equality simple bounds from problem
+    {"warmstart", &typeid(bool)},													//19 -  do we initialize multipliers with given values
+    {"uz",				&typeid(KN_<double>) },									//20 -  simple upper bounds dual variable
+    {"lz",				&typeid(KN_<double>) },									//21 -  simple lower bounds dual variable
+    {"muinit",		&typeid(double) },											//22 -  barrier parameter initialization
+    {"pivtol",		&typeid(double) },											//23 -  pivot tolerance for the linear solver
+    {"brf",				&typeid(double) },											//24 -  bounds relax factor
+    {"mustrategy",&typeid(string*) },											//25 -  strategy for barrier parameter update
+    {"objvalue",  &typeid(double*) },											//26 -  to get the last objective function value
+    {"mumin",			&typeid(double) },											//27 -  minimal value for the barrier parameter
+    {"linesearch",&typeid(bool) }                         //28 -  use the line search or not (if no, the usual Newton step is kept)
+    //{"osf",				&typeid(double) }												//26 -  objective function scalling factor
+};
+
+
+
+/*  class Init { public:
+    Init();
+};
+
+static Init init;
+*/
+static void Load_Init()
+{
+    Global.Add("IPOPT","(",new OptimIpopt(Case<no_assumption_f,no_assumption_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<no_assumption_f,without_constraints>()));
+    //Global.Add("IPOPT","(",new OptimIpopt(Case<no_assumption_f,P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<no_assumption_f,mv_P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<no_assumption_f,linear_g>()));
+    /*Global.Add("IPOPT","(",new OptimIpopt(Case<P2_f,P1_g>()));
+     Global.Add("IPOPT","(",new OptimIpopt(Case<P2_f,without_constraints>()));
+     Global.Add("IPOPT","(",new OptimIpopt(Case<P2_f,no_assumption_g>()));
+     Global.Add("IPOPT","(",new OptimIpopt(Case<P2_f,mv_P1_g>()));
+     Global.Add("IPOPT","(",new OptimIpopt(Case<P2_f,linear_g>()));*/
+    Global.Add("IPOPT","(",new OptimIpopt(Case<unavailable_hessian,no_assumption_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<unavailable_hessian,without_constraints>()));
+    //Global.Add("IPOPT","(",new OptimIpopt(Case<unavailable_hessian,P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<unavailable_hessian,mv_P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<unavailable_hessian,linear_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<mv_P2_f,no_assumption_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<mv_P2_f,without_constraints>()));
+    //Global.Add("IPOPT","(",new OptimIpopt(Case<mv_P2_f,P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<mv_P2_f,mv_P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<mv_P2_f,linear_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<quadratic_f,no_assumption_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<quadratic_f,without_constraints>()));
+    //Global.Add("IPOPT","(",new OptimIpopt(Case<quadratic_f,P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<quadratic_f,mv_P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<quadratic_f,linear_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<linear_f,no_assumption_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<linear_f,without_constraints>()));
+    //Global.Add("IPOPT","(",new OptimIpopt(Case<linear_f,P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<linear_f,mv_P1_g>()));
+    Global.Add("IPOPT","(",new OptimIpopt(Case<linear_f,linear_g>()));
+}
+
+
+
+
+/*****************************************************************************************************************************
+ *	Specialization of functions builders' constructor and operator()
+ *****************************************************************************************************************************/
+
+
+template<> FitnessFunctionDatas<no_assumption_f>::FitnessFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m)
+: GenericFitnessFunctionDatas()
+{
+    const Polymorphic * opJ  = dynamic_cast<const Polymorphic *>(args[0].LeftValue()),
+    * opdJ = dynamic_cast<const Polymorphic *>(args[1].LeftValue()),
+    * opH  = dynamic_cast<const Polymorphic *>(args[2].LeftValue());
+    ArrayOfaType hprototype2(atype<KN<R> *>(),atype<double>(),atype<KN<R>*>()),hprototype1(atype<KN<R> *>());
+    JJ =	to<R>(C_F0(opJ,"(",theparam));
+    GradJ = to<Rn_>(C_F0(opdJ,"(",theparam));
+    if(opH->Find("(",hprototype2))
+    {
+        CompletelyNonLinearConstraints = true;
+        Hessian = to<Matrice_Creuse<R>* >(C_F0(opH,"(",theparam,objfact,L_m));
+    }
+    else if(opH->Find("(",hprototype1))
+    {
+        CompletelyNonLinearConstraints = false; //When constraints are affine, lagrange multipliers are not used in the hessian, obj_factor is also hidden to the user
+        Hessian = to<Matrice_Creuse<R>* >(C_F0(opH,"(",theparam));
+    }
+    else CompileError("Error, wrong hessian function prototype. Must be either (real[int] &) or (real[int] &,real,real[int] &)");
+}
+template<> void FitnessFunctionDatas<no_assumption_f>::operator()
+(Stack stack,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m,Expression const *nargs,ScalarFunc *&ffJ,VectorFunc *&ffdJ,SparseMatFunc *&ffH,bool warned) const
+{
+    ffJ = new GeneralFunc<R>(stack,JJ,theparam);
+    ffdJ = new GeneralFunc<Rn>(stack,GradJ,theparam);
+    if(CompletelyNonLinearConstraints) ffH = new GeneralSparseMatFunc(stack,Hessian,theparam,objfact,L_m);
+    else ffH = new GeneralSparseMatFunc(stack,Hessian,theparam);
+}
+
+
+template<> FitnessFunctionDatas<P2_f>::FitnessFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m)
+: GenericFitnessFunctionDatas()
+{
+    CompletelyNonLinearConstraints = false;
+    const Polymorphic * opJ  = dynamic_cast<const Polymorphic *>(args[0].LeftValue()),* opdJ = dynamic_cast<const Polymorphic *>(args[1].LeftValue());
+    JJ =	to<R>(C_F0(opJ,"(",theparam));
+    GradJ = to<Rn_>(C_F0(opdJ,"(",theparam));
+    Hessian = to<Matrice_Creuse<R> *>(args[2]);
+}
+template<> void FitnessFunctionDatas<P2_f>::operator()
+(Stack stack,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m,Expression const *nargs,ScalarFunc *&ffJ,VectorFunc *&ffdJ,SparseMatFunc *&ffH,bool warned) const
+{
+    if(warned && nargs[5])
+    {
+        cout << "  ==> your lagrangian hessian is a constant matrix, so there is no need to specify its structure with ";
+        cout << OptimIpopt::E_Ipopt::name_param[5].name << endl;
+        cout << "      since it is contained in the matrix object." << endl;
+    }
+    ffJ = new GeneralFunc<R>(stack,JJ,theparam);
+    ffdJ = new GeneralFunc<Rn>(stack,GradJ,theparam);
+    ffH = new ConstantSparseMatFunc(stack,Hessian);
+}
+
+
+template<> FitnessFunctionDatas<unavailable_hessian>::FitnessFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m)
+: GenericFitnessFunctionDatas()
+{
+    CompletelyNonLinearConstraints = false;
+    const Polymorphic * opJ = dynamic_cast<const Polymorphic *> (args[0].LeftValue()),* opdJ = dynamic_cast<const Polymorphic *>(args[1].LeftValue());
+    JJ =	to<R>(C_F0(opJ,"(",theparam));
+    GradJ = to<Rn_>(C_F0(opdJ,"(",theparam));
+}
+template<> void FitnessFunctionDatas<unavailable_hessian>::operator()
+(Stack stack,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m,Expression const *nargs,ScalarFunc *&ffJ,VectorFunc *&ffdJ,SparseMatFunc *&ffH,bool warned) const
+{
+    if(warned && nargs[5])
+    {
+        cout << "  ==> no hessian has been given, the LBFGS mode has been enabled, thus making ";
+        cout << OptimIpopt::E_Ipopt::name_param[5].name << " useless. You may also" << endl << "      have forgoten a function (IPOPT will certainly crash if so)." << endl;
+    }
+    ffJ = new GeneralFunc<R>(stack,JJ,theparam);
+    ffdJ = new GeneralFunc<Rn>(stack,GradJ,theparam);
+    ffH = 0;
+}
+
+
+template<> FitnessFunctionDatas<mv_P2_f>::FitnessFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m)
+: GenericFitnessFunctionDatas()
+{
+    const E_Array *M_b = dynamic_cast<const E_Array *>(args[0].LeftValue());
+    if(M_b->nbitem() != 2) CompileError("\nSorry, we were expecting an array with two componants, either [M,b] or [b,M] for the affine constraints expression." );
+    bool order = true;
+    if(CheckMatrixVectorPair(M_b,order))
+    {
+        Hessian = to<Matrice_Creuse<R> *>((*M_b)[order ? 0:1]);
+        GradJ = to<Rn*>((*M_b)[order ? 1:0]); //This is gradJ evaluated on x=0
+    }
+}
+template<> void FitnessFunctionDatas<mv_P2_f>::operator()
+(Stack stack,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m,Expression const *nargs,ScalarFunc *&ffJ,VectorFunc *&ffdJ,SparseMatFunc *&ffH,bool warned) const
+{
+    if(warned && nargs[5])
+    {
+        cout << "  ==> your lagrangian hessian is a constant matrix, so there is no need to specify its structure with ";
+        cout << OptimIpopt::E_Ipopt::name_param[5].name << endl;
+        cout << "      since it is contained in the matrix object." << endl;
+    }
+    ffJ = new P2ScalarFunc(stack,Hessian,GradJ,true);
+    ffdJ = new P1VectorFunc(stack,Hessian,GradJ,true);
+    ffH = new ConstantSparseMatFunc(stack,Hessian);
+}
+
+
+template<> FitnessFunctionDatas<quadratic_f>::FitnessFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m)
+: GenericFitnessFunctionDatas() {Hessian = to<Matrice_Creuse<R> *>(args[0]);}
+template<> void FitnessFunctionDatas<quadratic_f>::operator()
+(Stack stack,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m,Expression const *nargs,ScalarFunc *&ffJ,VectorFunc *&ffdJ,SparseMatFunc *&ffH,bool warned) const
+{
+    if(warned && nargs[5])
+    {
+        cout << "  ==> your lagrangian hessian is a constant matrix, so there is no need to specify its structure with ";
+        cout << OptimIpopt::E_Ipopt::name_param[5].name << endl;
+        cout << "      since it is contained in the matrix object." << endl;
+    }
+    ffJ = new P2ScalarFunc(stack,Hessian,0,true);
+    ffdJ = new P1VectorFunc(stack,Hessian,0,true);
+    ffH = new ConstantSparseMatFunc(stack,Hessian);
+}
+
+
+template<> FitnessFunctionDatas<linear_f>::FitnessFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m)
+: GenericFitnessFunctionDatas() {GradJ = to<Rn *>(args[0]);}
+template<> void FitnessFunctionDatas<linear_f>::operator()
+(Stack stack,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &L_m,Expression const *nargs,ScalarFunc *&ffJ,VectorFunc *&ffdJ,SparseMatFunc *&ffH,bool warned) const
+{
+    if(warned && nargs[5])
+    {
+        cout << "  ==> your lagrangian hessian is a null matrix, so there is no need to specify its structure with ";
+        cout << OptimIpopt::E_Ipopt::name_param[5].name << endl;
+        cout << "      since it is empty." << endl;
+    }
+    ffJ = new P2ScalarFunc(stack,0,GradJ);
+    ffdJ = new P1VectorFunc(stack,0,GradJ);
+    ffH = 0;
+}
+
+
+
+
+template<> ConstraintFunctionDatas<without_constraints>::ConstraintFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam)
+: GenericConstraintFunctionDatas() {}
+template<> void ConstraintFunctionDatas<without_constraints>::operator()(Stack stack,const C_F0 &theparam,Expression const *nargs,VectorFunc *&ffC,SparseMatFunc *&ffdC,bool warned) const
+{
+    if(warned)
+    {
+        if(nargs[2] || nargs[3]) cout << "  ==> Some constraints bounds have been defined while no constraints function has been passed." << endl;
+        if(nargs[4]) cout << "  ==> A structure has been provided for the constraints jacobian but there is no constraint function." << endl;
+        if(nargs[6]) cout << "  ==> Unconstrained problem make the use of " << OptimIpopt::E_Ipopt::name_param[6].name << " pointless (see the documentation for more details)." << endl;
+    }
+    ffC = 0;
+    ffdC = 0;
+}
+
+template<> ConstraintFunctionDatas<no_assumption_g>::ConstraintFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam)
+: GenericConstraintFunctionDatas()
+{
+    int nbj = args.size()-1;
+    const Polymorphic * opG = dynamic_cast<const Polymorphic *> (args[nbj-2].LeftValue()),
+    * opjG= dynamic_cast<const Polymorphic *> (args[nbj-1].LeftValue());
+    Constraints = to<Rn_>(C_F0(opG,"(",theparam));
+    GradConstraints = to<Matrice_Creuse<R>*>(C_F0(opjG,"(",theparam));
+}
+template<> void ConstraintFunctionDatas<no_assumption_g>::operator()(Stack stack,const C_F0 &theparam,Expression const *nargs,VectorFunc *&ffC,SparseMatFunc *&ffdC,bool) const 
+{
+    ffC = new GeneralFunc<Rn>(stack,Constraints,theparam);
+    ffdC = new GeneralSparseMatFunc(stack,GradConstraints,theparam);
+}
+
+template<> ConstraintFunctionDatas<P1_g>::ConstraintFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam)
+: GenericConstraintFunctionDatas() 
+{
+    int nbj = args.size()-1;
+    const Polymorphic * opG = dynamic_cast<const Polymorphic *> (args[nbj-2].LeftValue());
+    Constraints = to<Rn_>(C_F0(opG,"(",theparam));
+    GradConstraints = to<Matrice_Creuse<R> *>(args[nbj-1]);
+}
+template<> void ConstraintFunctionDatas<P1_g>::operator()(Stack stack,const C_F0 &theparam,Expression const *nargs,VectorFunc *&ffC,SparseMatFunc *&ffdC,bool warned) const 
+{
+    if(warned && nargs[4])
+    {
+        cout << "  ==> your constraints jacobian is a constant matrix, there is no need to specify its structure with " << OptimIpopt::E_Ipopt::name_param[4].name << endl;
+        cout << "      since it is contained in the matrix object." << endl;
+    }
+    ffC = new GeneralFunc<Rn>(stack,Constraints,theparam);
+    ffdC = new ConstantSparseMatFunc(stack,GradConstraints);
+}
+
+template<> ConstraintFunctionDatas<mv_P1_g>::ConstraintFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam)
+: GenericConstraintFunctionDatas() 
+{
+    int nbj = args.size()-1;
+    const E_Array *M_b = dynamic_cast<const E_Array *>(args[nbj-1].LeftValue());
+    if(M_b->nbitem() != 2) CompileError("\nSorry, we were expecting an array with two componants, either [M,b] or [b,M] for the affine constraints expression." );
+    bool order=true;
+    if(CheckMatrixVectorPair(M_b,order))
+    {
+        GradConstraints = to<Matrice_Creuse<R> *>((*M_b)[order ? 0:1]);
+        Constraints = to<Rn*>((*M_b)[order ? 1:0]); //Constraint on x=0
+    }
+    else CompileError("\nWrong types in the constraints [matrix,vector] pair, expecting a sparse matrix and real[int].");
+}
+template<> void ConstraintFunctionDatas<mv_P1_g>::operator()(Stack stack,const C_F0 &theparam,Expression const *nargs,VectorFunc *&ffC,SparseMatFunc *&ffdC,bool warned) const 
+{
+    if(warned && nargs[4])
+    {
+        cout << "  ==> your constraints jacobian is a constant matrix, there is no need to specify its structure with " << OptimIpopt::E_Ipopt::name_param[4].name << endl;
+        cout << "      since it is contained in the matrix object." << endl;
+    }
+    ffC = new P1VectorFunc(stack,GradConstraints,Constraints);
+    ffdC = new ConstantSparseMatFunc(stack,GradConstraints);
+}
+
+template<> ConstraintFunctionDatas<linear_g>::ConstraintFunctionDatas(const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam)
+: GenericConstraintFunctionDatas() 
+{
+    int nbj = args.size()-1;
+    GradConstraints = to<Matrice_Creuse<R> *>(args[nbj-1]);
+}
+template<> void ConstraintFunctionDatas<linear_g>::operator()(Stack stack,const C_F0 &theparam,Expression const *nargs,VectorFunc *&ffC,SparseMatFunc *&ffdC,bool warned) const 
+{
+    if(warned && nargs[4])
+    {
+        cout << "  ==> your constraints jacobian is a constant matrix, there is no need to specify its structure with " << OptimIpopt::E_Ipopt::name_param[4].name << endl;
+        cout << "      since it is contained in the matrix object." << endl;
+    }
+    ffC = new P1VectorFunc(stack,GradConstraints,0);
+    ffdC = new ConstantSparseMatFunc(stack,GradConstraints);
+}
+
+
+GenericFitnessFunctionDatas* GenericFitnessFunctionDatas::New(AssumptionF AF,const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam,const C_F0 &objfact,const C_F0 &lm)
+{
+    switch (AF) 
+    {
+        case no_assumption_f:
+            return new FitnessFunctionDatas<no_assumption_f>(args,nargs,theparam,objfact,lm);
+            break;
+        case P2_f:
+            return new FitnessFunctionDatas<P2_f>(args,nargs,theparam,objfact,lm);
+            break;
+        case unavailable_hessian:
+            return new FitnessFunctionDatas<unavailable_hessian>(args,nargs,theparam,objfact,lm);
+            break;
+        case mv_P2_f:
+            return new FitnessFunctionDatas<mv_P2_f>(args,nargs,theparam,objfact,lm);
+            break;
+        case quadratic_f:
+            return new FitnessFunctionDatas<quadratic_f>(args,nargs,theparam,objfact,lm);
+            break;
+        case linear_f:
+            return new FitnessFunctionDatas<linear_f>(args,nargs,theparam,objfact,lm);
+            break;
+        default:
+            return 0; 
+            break;
+    }
+}
+
+GenericConstraintFunctionDatas* GenericConstraintFunctionDatas::New(AssumptionG AG,const basicAC_F0 &args,Expression const *nargs,const C_F0 &theparam)
+{
+    switch (AG)
+    {
+        case no_assumption_g:
+            return new ConstraintFunctionDatas<no_assumption_g>(args,nargs,theparam);
+            break;
+        case without_constraints:
+            return new ConstraintFunctionDatas<without_constraints>(args,nargs,theparam);
+            break;
+        case P1_g:
+            return new ConstraintFunctionDatas<P1_g>(args,nargs,theparam);
+            break;
+        case mv_P1_g:
+            return new ConstraintFunctionDatas<mv_P1_g>(args,nargs,theparam);
+            break;
+        case linear_g:
+            return new ConstraintFunctionDatas<linear_g>(args,nargs,theparam);
+            break;
+        default:
+            return 0;
+            break;
+    }
+}
+
+/*
+ enum AssumptionF {undeff,no_assumption_f, P2_f, unavailable_hessian, mv_P2_f, quadratic_f, linear_f};
+ enum AssumptionG {undefg,without_constraints, no_assumption_g, P1_g, mv_P1_g, linear_g};
+ */
+LOADFUNC(Load_Init)
+
diff --git a/examples++-load/ff-NLopt.cpp b/examples++-load/ff-NLopt.cpp
new file mode 100644
index 0000000..0994528
--- /dev/null
+++ b/examples++-load/ff-NLopt.cpp
@@ -0,0 +1,878 @@
+/*
+ *  ff-NLopt.cpp
+ *  
+ *
+ *  Created by Sylvain Auliac on 25/05/11.
+ *
+ */
+
+//ff-c++-LIBRARY-dep:   nlopt
+//ff-c++-cpp-dep: 
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Sylvain Auliac
+// E-MAIL   : auliac at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include  <iostream>
+#include <stack>
+#include <vector>
+using namespace std;
+#include "ff++.hpp"
+
+#include <nlopt.hpp>
+
+
+extern Block *currentblock;
+
+typedef double R;
+typedef double (*NLoptFuncType)(unsigned,const double *,double *,void*);
+
+template<nlopt::algorithm ALGO> struct Info								{static const bool DF=true,SA=false; static const char *name;};//DF=Derivative Free , SA=need a Sub Algorithm
+template<> struct Info<nlopt::LD_LBFGS_NOCEDAL>						{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_LBFGS>										{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_VAR1>										{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_VAR2>										{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_TNEWTON>									{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_TNEWTON_RESTART>					{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_TNEWTON_PRECOND>					{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_TNEWTON_PRECOND_RESTART>	{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_MMA>											{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::LD_AUGLAG>									{static const bool DF=false,SA=true; static const char *name;};
+template<> struct Info<nlopt::LD_AUGLAG_EQ>								{static const bool DF=false,SA=true; static const char *name;};
+template<> struct Info<nlopt::LD_SLSQP>										{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::GD_STOGO>										{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::GD_STOGO_RAND>							{static const bool DF=false,SA=false; static const char *name;};
+template<> struct Info<nlopt::GD_MLSL>										{static const bool DF=false,SA=true; static const char *name;};
+template<> struct Info<nlopt::GD_MLSL_LDS>								{static const bool DF=false,SA=true; static const char *name;};
+template<> struct Info<nlopt::GN_MLSL>										{static const bool DF=true,SA=true; static const char *name;};
+template<> struct Info<nlopt::GN_MLSL_LDS>								{static const bool DF=true,SA=true; static const char *name;};
+template<> struct Info<nlopt::LN_AUGLAG>									{static const bool DF=true,SA=true; static const char *name;};
+template<> struct Info<nlopt::LN_AUGLAG_EQ>								{static const bool DF=true,SA=true; static const char *name;};
+template<> struct Info<nlopt::G_MLSL>											{static const bool DF=true,SA=true; static const char *name;};
+template<> struct Info<nlopt::G_MLSL_LDS>									{static const bool DF=true,SA=true; static const char *name;};
+template<> struct Info<nlopt::AUGLAG>											{static const bool DF=true,SA=true; static const char *name;};
+template<> struct Info<nlopt::AUGLAG_EQ>									{static const bool DF=true,SA=true; static const char *name;};
+
+
+
+template<nlopt::algorithm ALGO> const char *Info<ALGO>::name					= "ALGORITHM";
+template<> const char *Info<nlopt::GN_DIRECT>::name										= "Dividing Rectangles";
+template<> const char *Info<nlopt::GN_DIRECT_L>::name									= "Locally Biased Dividing Rectangles";
+template<> const char *Info<nlopt::GN_DIRECT_L_RAND>::name						=	"Randomized Locally Biased Dividing Rectangles";
+template<> const char *Info<nlopt::GN_DIRECT_NOSCAL>::name						= "Dividing Rectangles (no scaling)";
+template<> const char *Info<nlopt::GN_DIRECT_L_NOSCAL>::name					= "Locally Biased Dividing Rectangles (no scaling)";
+template<> const char *Info<nlopt::GN_DIRECT_L_RAND_NOSCAL>::name			= "Randomized Locally Biased Dividing Rectangles (no scaling)";
+template<> const char *Info<nlopt::GN_ORIG_DIRECT>::name							= "Original Glabonsky's Dividing Rectangles";
+template<> const char *Info<nlopt::GN_ORIG_DIRECT_L>::name						= "Original Glabonsky's Locally Biased Dividing Rectangles";
+					 const char *Info<nlopt::GD_STOGO>::name										=	"StoGO";
+					 const char *Info<nlopt::GD_STOGO_RAND>::name								= "Randomized StoGO";
+					 const char *Info<nlopt::LD_LBFGS_NOCEDAL>::name						= "Nocedal's Low-Storage BFGS";
+					 const char *Info<nlopt::LD_LBFGS>::name										= "Low-Storage BFGS";
+template<> const char *Info<nlopt::LN_PRAXIS>::name										= "Principal Axis";
+					 const char *Info<nlopt::LD_VAR1>::name											= "Rank-1 Shifted Limited Memory Variable Metric";
+					 const char *Info<nlopt::LD_VAR2>::name											=	"Rank-2 Shifted Limited Memory Variable Metric";
+					 const char *Info<nlopt::LD_TNEWTON>::name									=	"Truncated Newton";
+					 const char *Info<nlopt::LD_TNEWTON_RESTART>::name					=	"Steepest Descent Restarting Truncated Newton";
+					 const char *Info<nlopt::LD_TNEWTON_PRECOND>::name					=	"BFGS Preconditionned Truncated Newton";
+					 const char *Info<nlopt::LD_TNEWTON_PRECOND_RESTART>::name	=	"BFGS Precondionned Truncated Newton with Steepest Descent Resrtarting";
+template<> const char *Info<nlopt::GN_CRS2_LM>::name									= "Controlled Random Search with Local Mutation";
+					 const char *Info<nlopt::GN_MLSL>::name											= "Multi-Level Single-Linkage (derivative free)";
+					 const char *Info<nlopt::GD_MLSL>::name											=	"Multi-Level Single-Linkage (with gradient-based local search)";
+					 const char *Info<nlopt::GN_MLSL_LDS>::name									= "Low Discrepancy Sequence Multi-Level Single-Linkage (derivative free)";
+					 const char *Info<nlopt::GD_MLSL_LDS>::name									=	"Low Discrepancy Sequence Multi-Level Single-Linkage (with gradient-based local search)";
+					 const char *Info<nlopt::LD_MMA>::name											= "Method of Moving Asymptotes";
+template<> const char *Info<nlopt::LN_COBYLA>::name										= "Constrained Optimization by Linear Approximations";
+template<> const char *Info<nlopt::LN_NEWUOA>::name										= "NEWUOA";
+template<> const char *Info<nlopt::LN_NEWUOA_BOUND>::name							= "NEWUOA for bounded optimization";
+template<> const char *Info<nlopt::LN_NELDERMEAD>::name								= "Nelder-Mead Simplex";
+template<> const char *Info<nlopt::LN_SBPLX>::name										= "Subplex";
+					 const char *Info<nlopt::LN_AUGLAG>::name										= "Inequality/Equality Constraints Augmented Lagrangian (derivative free)";
+					 const char *Info<nlopt::LD_AUGLAG>::name										= "Inequality/Equality Constraints Augmented Lagrangian (with gradient-based subsidiary search)";
+					 const char *Info<nlopt::LN_AUGLAG_EQ>::name								= "Equality Constraints Augmented Lagrangian (derivative free)";
+					 const char *Info<nlopt::LD_AUGLAG_EQ>::name								= "Equality Constraints Augmented Lagrangian (with gradient-based subsidiary search)";
+template<> const char *Info<nlopt::LN_BOBYQA>::name										= "BOBYQA";
+template<> const char *Info<nlopt::GN_ISRES>::name										= "Improved Stochastic Ranking Evolution Strategy";
+					 const char *Info<nlopt::LD_SLSQP>::name										= "Sequential Least-Squares Quadratic Programming";
+					 const char *Info<nlopt::G_MLSL>::name											= "Multi-Level Single-Linkage";
+					 const char *Info<nlopt::G_MLSL_LDS>::name									= "Low Discrepancy Multi-level Single-Linkage";
+					 const char *Info<nlopt::AUGLAG>::name											= "Inequality/Equality Constraints Augmented Lagrangian";
+					 const char *Info<nlopt::AUGLAG_EQ>::name										= "Equality Constraints Augmented Lagrangian";
+
+					 
+
+inline void Sonde(int i) {cout << "sonde " << i << endl;}
+
+
+typedef KN_<R> Rn_;
+typedef KN<R> Rn;
+typedef KNM_<R> Rnm_;
+typedef KNM<R> Rnm;
+
+/*template<class T> inline std::vector<T> KnToStdVect(const KN<T> &V)
+{
+	std::vector<T> v(V.n);
+	for(int i=0;i<v.size();++i) v[i] = V[i];
+	return v;
+}*/
+
+template<class T> inline std::vector<T> KnToStdVect(const KN_<T> &V)
+{
+	std::vector<T> v(V.n);
+	for(int i=0;i<v.size();++i) v[i] = V[i];
+	return v;
+}
+
+
+
+template<class K> class ffcalfunc  //   to call the freefem function .. J, constraints, and derivatives
+{ 
+	public:
+		Stack stack;
+		Expression JJ,theparame;
+    
+		ffcalfunc(const ffcalfunc &f) : stack(f.stack),JJ(f.JJ),theparame(f.theparame) {}
+		ffcalfunc(Stack s,Expression JJJ,Expression epar) : stack(s),JJ(JJJ), theparame(epar) {}
+		K J(Rn_  x) const 
+		{
+			KN<double> *p=GetAny<KN<double> *>( (*theparame)(stack) );
+			*p=x;
+			K ret= GetAny<K>( (*JJ)(stack));
+			//cout << "call to ffcalfunc.J with " << *p << " and ret=" << ret << endl;
+			WhereStackOfPtr2Free(stack)->clean();
+			return  ret; 
+		}
+};
+
+
+typedef ffcalfunc<double> * ScalarFunc;
+typedef ffcalfunc<Rn> * VectorFunc;
+typedef ffcalfunc<Rnm> * MatrixFunc;
+
+
+class GenericOptimizer
+{
+	public:
+		/*GenericOptimizer(nlopt::algorithm ALGO) : opt(ALGO,0),x(0),econsttol(0),iconsttol(0),econstrained(false),iconstrained(false),fit(0),d_fit(0),equaconst(0),
+																							d_equaconst(0),ineqconst(0),d_ineqconst(0),subopt(0)
+		{}*/
+		GenericOptimizer(nlopt::algorithm ALGO,int dim=0) : opt(ALGO,dim),x(0),econsttol(0),iconsttol(0),econstrained(false),iconstrained(false),fit(0),d_fit(0),equaconst(0),
+																							d_equaconst(0),ineqconst(0),d_ineqconst(0),subopt(0)
+		{}
+		GenericOptimizer(nlopt::algorithm ALGO,const ffcalfunc<R> &_ff,Rn &xstart) : opt(ALGO,xstart.n),x(&xstart),econsttol(0),iconsttol(0),econstrained(false),iconstrained(false),
+																							fit(new ffcalfunc<R>(_ff)),d_fit(0),equaconst(0),d_equaconst(0),ineqconst(0),d_ineqconst(0),subopt(0)
+		{
+			opt.set_min_objective(NLoptFunc, static_cast<void*>(this));
+		}
+		virtual ~GenericOptimizer()
+		{
+			Clean(fit);
+			Clean(d_fit);
+			Clean(equaconst);
+			Clean(d_equaconst);
+			Clean(ineqconst);
+			Clean(d_ineqconst);
+			Clean(subopt);
+		}
+	
+	
+			
+		double operator() () 
+		{
+			double minf; 
+			vector<double> vv(x->n);
+			for(int i=0;i<vv.size();++i) vv[i] = (*x)[i];
+			opt.optimize(vv,minf);
+			for(int i=0;i<vv.size();++i) (*x)[i] = vv[i];
+			return minf;
+		}
+		
+		virtual bool DF() const {return true;}
+		virtual bool SA() const {return false;}
+		virtual const char * Name() const {return "Generic Algorithm";}
+		virtual nlopt::algorithm Tag() const = 0;
+		
+		GenericOptimizer& SetEqualityConstraintsTolerance(const Rn_ &val) {econsttol=val; return *this;}
+		GenericOptimizer& SetInequalityConstraintsTolerance(const Rn_ &val) {iconsttol=val; return *this;}
+		GenericOptimizer& SetSCXRelativeTolerance(const double val) {opt.set_xtol_rel(val); return *this;} //SC = stopping criteria
+		GenericOptimizer& SetSCXAbsoluteTolerance(const Rn_ &val) {opt.set_xtol_abs(KnToStdVect(val)); return *this;}
+		GenericOptimizer& SetLowerBounds(const Rn_ &lb) {opt.set_lower_bounds(KnToStdVect(lb)); return *this;}
+		GenericOptimizer& SetUpperBounds(const Rn_ &ub) {opt.set_upper_bounds(KnToStdVect(ub)); return *this;}
+		GenericOptimizer& SetSCStopFunctionValue(const double val) {opt.set_stopval(val); return *this;}
+		GenericOptimizer& SetSCRelativeFunctionTolerance(const double val) {opt.set_ftol_rel(val); return *this;}
+		GenericOptimizer& SetSCAbsoluteFunctionTolerance(const double val) {opt.set_ftol_abs(val); return *this;}
+		GenericOptimizer& SetSCMaxFunctionEvaluations(const long val) {opt.set_maxeval(val); return *this;}
+		GenericOptimizer& SetSCEllapsedTime(const double val) {opt.set_maxtime(val); return *this;}
+		GenericOptimizer& SetPopulationSize(const int val) {opt.set_population(static_cast<unsigned>(val)); return *this;}
+		virtual GenericOptimizer& SetVectorStorage(const int val) {opt.set_vector_storage(static_cast<unsigned>(val)); return *this;}
+		
+		GenericOptimizer& SetObjectiveFunctionGradient(const ffcalfunc<Rn> &g) {Clean(d_fit) = new ffcalfunc<Rn>(g); return *this;}
+		GenericOptimizer& SetEqualityConstraintFunction(const ffcalfunc<Rn> &f) {Clean(equaconst) = new ffcalfunc<Rn>(f); return *this;}
+		GenericOptimizer& SetEqualityConstraintGradient(const ffcalfunc<Rnm> &g) {Clean(d_equaconst) = new ffcalfunc<Rnm>(g); return *this;}
+		GenericOptimizer& SetInequalityConstraintFunction(const ffcalfunc<Rn> &f) {Clean(ineqconst) = new ffcalfunc<Rn>(f); return *this;}
+		GenericOptimizer& SetInequalityConstraintGradient(const ffcalfunc<Rnm> &g) {Clean(d_ineqconst) = new ffcalfunc<Rnm>(g); return *this;}
+		
+		
+		
+		GenericOptimizer& SetEqualityConstraints()
+		{
+			if(econstrained) opt.remove_equality_constraints();
+			Rn etestv = equaconst->J(*x);
+			if(econsttol.n==0) {econsttol.resize(etestv.n); econsttol = 1.e-12;}
+			else assert(econsttol.n == etestv.n);
+			opt.add_equality_mconstraint(NLoptECDF,static_cast<void*>(this),KnToStdVect(econsttol));
+			econstrained = true;
+			return *this;
+		}
+		GenericOptimizer& SetInequalityConstraints()
+		{
+			if(iconstrained) opt.remove_inequality_constraints();
+			Rn itestv = ineqconst->J(*x);
+			//cout << "itestv = " << itestv << "(x=" << *x << ")" <<  endl;
+			if(iconsttol.n==0) {iconsttol.resize(itestv.n); iconsttol = 1.e-12;}
+			else assert(iconsttol.n == itestv.n);
+			opt.add_inequality_mconstraint(NLoptICDF,static_cast<void*>(this),KnToStdVect(iconsttol));
+			iconstrained = true;
+			return *this;
+		}
+		
+		static double NLoptFunc(const std::vector<double> &xx,std::vector<double> &grad, void *data)
+		{
+			GenericOptimizer * pthis = static_cast<GenericOptimizer *>(data);
+			int n = xx.size();
+			Rn X(n);
+			for(int i=0;i<n;++i) X[i] = xx[i];
+			//cout << "grad: " << grad << "d_fit.top():" << d_fit.top() << endl;
+			if(grad.size() && pthis->d_fit)
+			{
+				Rn dJ=pthis->d_fit->J(X);
+				for(int i=0;i<n;++i) grad[i] = dJ[i];
+			} 
+			//cout << "call to NLoptFunc with x=" << X << endl;
+			return pthis->fit->J(X);
+		}
+		static void NLoptECDF(unsigned m,double *result,unsigned n,const double *xx,double *grad,void *data)
+		{
+			GenericOptimizer * pthis = static_cast<GenericOptimizer *>(data);
+			if(pthis->equaconst)
+			{
+				Rn X(n);
+				for(int k=0;k<n;++k) X[k] = xx[k];
+				Rn Y=pthis->equaconst->J(X);
+				assert(Y.n==m);
+				for(int i=0;i<m;++i) result[i] = Y[i];
+				if(grad)
+				{
+					assert(pthis->d_equaconst);
+					Rnm dconst=pthis->d_equaconst->J(X);
+					assert(dconst.N()==m && dconst.M()==n);
+					for(int i=0;i<m;++i)
+						for(int j=0;j<n;++j) grad[i*n + j] = dconst(i,j);
+				}
+			}
+			else 
+			{
+				for(int i=0;i<m;++i)
+				{
+					result[i] = 0;
+					if(grad) for(int j=0;j<n;++j) grad[i*n+j]=0;
+				}
+			}
+		}
+		static void NLoptICDF(unsigned m,double *result,unsigned n,const double *xx,double *grad,void *data)
+		{
+			GenericOptimizer * pthis = static_cast<GenericOptimizer *>(data);
+			if(pthis->ineqconst)
+			{
+				Rn X(n);
+				for(int k=0;k<n;++k) X[k] = xx[k];
+				Rn Y=pthis->ineqconst->J(X);
+				assert(Y.N()==m);
+				for(int i=0;i<m;++i) result[i] = Y[i];
+				if(grad)
+				{
+					assert(pthis->d_ineqconst);
+					Rnm dconst=pthis->d_ineqconst->J(X);
+					assert(dconst.N()==m && dconst.M()==n);
+					for(int i=0;i<m;++i)
+						for(int j=0;j<n;++j) grad[i*n + j] = dconst(i,j);
+				}
+			}
+			else 
+			{
+				for(int i=0;i<m;++i)
+				{
+					result[i] = 0;
+					if(grad) for(int j=0;j<n;++j) grad[i*n+j]=0;
+				}
+			}
+		}
+			
+	
+	
+	
+		nlopt::opt opt,*subopt;
+		Rn *x,econsttol,iconsttol;
+		bool iconstrained,econstrained;
+		ScalarFunc fit;
+		VectorFunc d_fit,equaconst,ineqconst;
+		MatrixFunc d_equaconst,d_ineqconst;
+	private:
+		GenericOptimizer();
+		template<class T> static T*& Clean(T*& p) 
+		{
+			if(p) delete p;
+			p=0;
+			return p;
+		}
+};
+
+
+
+
+
+template<nlopt::algorithm ALGO> class Optimizer : public GenericOptimizer
+{
+	public:
+		
+		Optimizer(int dim=0) : GenericOptimizer(ALGO,dim) {}
+		Optimizer(const ffcalfunc<R> &_ff,Rn &xstart) : GenericOptimizer(ALGO,_ff,xstart) {}
+		~Optimizer() {}
+		
+		
+		bool DF() const {return Info<ALGO>::DF;}
+		bool SA() const {return Info<ALGO>::SA;}
+		nlopt::algorithm Tag() const {return ALGO;}
+		const char * Name() const {return Info<ALGO>::name;}
+		
+	private:
+};
+
+
+
+template<bool a> struct MyCheck {MyCheck() {} };
+template<> struct MyCheck<false>
+{
+	private:
+		MyCheck() {}
+};
+
+template<nlopt::algorithm ALGO> class SAOptimizer : public GenericOptimizer
+{
+	public:
+
+		SAOptimizer(int dim=0) : GenericOptimizer(ALGO,dim),subopt(0) {MyCheck<Info<ALGO>::SA>();}
+		SAOptimizer(const ffcalfunc<R> &_ff,Rn &xstart) : GenericOptimizer(ALGO,_ff,xstart),subopt(0) {MyCheck<Info<ALGO>::SA>();}
+		~SAOptimizer() {if(subopt) delete subopt; subopt=0;}
+		
+		GenericOptimizer *subopt;
+		
+		bool DF() const {return Info<ALGO>::DF && (subopt ? subopt->DF() : false);}
+		bool SA() const {return true;}
+		nlopt::algorithm Tag() const {return ALGO;}
+		const char * Name() const {return Info<ALGO>::name;}
+		
+		GenericOptimizer& SetSubOptimizer(const string & name=string(),bool save= 1);
+		GenericOptimizer& SetSASCXRelativeTolerance(const double val) {if(subopt) subopt->opt.set_xtol_rel(val); return *this;} //SC = stopping criteria
+		GenericOptimizer& SetSASCXAbsoluteTolerance(const Rn_ &val) {if(subopt) subopt->opt.set_xtol_abs(KnToStdVect(val)); return *this;}
+		GenericOptimizer& SetSASCStopFunctionValue(const double val) {if(subopt) subopt->opt.set_stopval(val); return *this;}
+		GenericOptimizer& SetSASCRelativeFunctionTolerance(const double val) {if(subopt) subopt->opt.set_ftol_rel(val); return *this;}
+		GenericOptimizer& SetSASCAbsoluteFunctionTolerance(const double val) {if(subopt) subopt->opt.set_ftol_abs(val); return *this;}
+		GenericOptimizer& SetSASCMaxFunctionEvaluations(const long val) {if(subopt) subopt->opt.set_maxeval(val); return *this;}
+		GenericOptimizer& SetSASCEllapsedTime(const double val) {if(subopt) subopt->opt.set_maxtime(val); return *this;}
+		GenericOptimizer& SetSAPopulationSize(const int val) {if(subopt) subopt->opt.set_population(static_cast<unsigned>(val));return *this;}
+		GenericOptimizer& SetVectorStorage(const int val) {if(subopt) subopt->opt.set_vector_storage(static_cast<unsigned>(val)); return *this;}
+		
+};
+template<nlopt::algorithm ALGO> GenericOptimizer& SAOptimizer<ALGO>::SetSubOptimizer(const string &name,bool save)
+{
+	if(!subopt)
+	{
+		if(name=="DIRECT") subopt = new Optimizer<nlopt::GN_DIRECT>(x->n);
+		else if(name=="DIRECTL") subopt = new Optimizer<nlopt::GN_DIRECT_L>(x->n);
+		else if(name=="DIRECTLRand") subopt = new Optimizer<nlopt::GN_DIRECT_L_RAND>(x->n);
+		else if(name=="DIRECTNoScal") subopt = new Optimizer<nlopt::GN_DIRECT_NOSCAL>(x->n);
+		else if(name=="DIRECTLNoScal") subopt = new Optimizer<nlopt::GN_DIRECT_L_NOSCAL>(x->n);
+		else if(name=="DIRECTLRandNoScal") subopt = new Optimizer<nlopt::GN_DIRECT_L_RAND_NOSCAL>(x->n);
+		else if(name=="OrigDIRECT") subopt = new Optimizer<nlopt::GN_ORIG_DIRECT>(x->n);
+		else if(name=="OrigDIRECTL") subopt = new Optimizer<nlopt::GN_ORIG_DIRECT_L>(x->n);
+		else if(name=="StoGO") subopt = new Optimizer<nlopt::GD_STOGO>(x->n);
+		else if(name=="StoGORand") subopt = new Optimizer<nlopt::GD_STOGO_RAND>(x->n);
+		else if(name=="LBFGS") subopt = new Optimizer<nlopt::LD_LBFGS>(x->n);
+		else if(name=="PRAXIS") subopt = new Optimizer<nlopt::LN_PRAXIS>(x->n);
+		else if(name=="Var1") subopt = new Optimizer<nlopt::LD_VAR1>(x->n);
+		else if(name=="Var2") subopt = new Optimizer<nlopt::LD_VAR2>(x->n);
+		else if(name=="TNewton") subopt = new Optimizer<nlopt::LD_TNEWTON>(x->n);
+		else if(name=="TNewtonRestart") subopt = new Optimizer<nlopt::LD_TNEWTON_RESTART>(x->n);
+		else if(name=="TNewtonPrecond") subopt = new Optimizer<nlopt::LD_TNEWTON_PRECOND>(x->n);
+		else if(name=="TNewtonPrecondRestart") subopt = new Optimizer<nlopt::LD_TNEWTON_PRECOND_RESTART>(x->n);
+		else if(name=="CRS2") subopt = new Optimizer<nlopt::GN_CRS2_LM>(x->n);
+		else if(name=="MMA") subopt = new Optimizer<nlopt::LD_MMA>(x->n);
+		else if(name=="COBYLA") subopt = new Optimizer<nlopt::LN_COBYLA>(x->n);
+		else if(name=="NEWUOA") subopt = new Optimizer<nlopt::LN_NEWUOA>(x->n);
+		else if(name=="NEWUOABound") subopt = new Optimizer<nlopt::LN_NEWUOA_BOUND>(x->n);
+		else if(name=="NelderMead") subopt = new Optimizer<nlopt::LN_NELDERMEAD>(x->n);
+		else if(name=="Sbplx") subopt = new Optimizer<nlopt::LN_SBPLX>(x->n);
+		else if(name=="BOBYQA") subopt = new Optimizer<nlopt::LN_BOBYQA>(x->n);
+		else if(name=="ISRES") subopt = new Optimizer<nlopt::GN_ISRES>(x->n);
+		else if(name=="SLSQP") subopt = new Optimizer<nlopt::LD_SLSQP>(x->n);
+		else cout << "Warning: unknown or unauthorized optimizer name passed as sub algorithm to " << Info<ALGO>::name << endl;
+	}
+	if(subopt && save) opt.set_local_optimizer(subopt->opt);
+	return *this;
+}
+
+
+
+
+
+template<nlopt::algorithm ALGO,bool SA=Info<ALGO>::SA> class OptimNLopt : public OneOperator 
+{
+	public:
+		const int cas;
+
+		class E_NLopt : public E_F0mps 
+		{ 
+			public:
+				const int cas;
+				static basicAC_F0::name_and_type name_param[] ;
+				static const int n_name_param =18;
+				Expression nargs[n_name_param];
+				Expression X;
+				C_F0 inittheparam,theparam,closetheparam; 
+				Expression JJ;
+				Expression GradJ,EIConst,EGradIConst,EEConst,EGradEConst;
+				long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+				R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+				Rn_ arg(int i,Stack stack,Rn_ a) const {return nargs[i] ? GetAny<Rn_>((*nargs[2])(stack)) : a;}
+				template<typename T> T Arg(int i,Stack s) const {return GetAny<T>( (*nargs[i])(s));}
+      
+				E_NLopt(const basicAC_F0 & args,int cc) : cas(cc)
+				{
+					int nbj= args.size()-1;
+					Block::open(currentblock); // make a new block to 
+					X = to<Rn*>(args[nbj]);
+					C_F0 X_n(args[nbj],"n");
+					//  the expression to init the theparam of all 
+					inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+					theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+					args.SetNameParam(n_name_param,name_param,nargs);
+					const  Polymorphic * opJ=0;
+					if (nbj>0)
+					{
+						opJ=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+						assert(opJ);
+					}      
+					JJ= to<R>(C_F0(opJ,"(",theparam));
+					const Polymorphic * gradient = nargs[0] ? dynamic_cast<const Polymorphic *>(nargs[0]) : 0,
+														* iconst = nargs[1] ? dynamic_cast<const Polymorphic *>(nargs[1]) : 0,
+														* gradiconst = nargs[2] ? dynamic_cast<const Polymorphic *>(nargs[2]) : 0,
+														* econst = nargs[3] ? dynamic_cast<const Polymorphic *>(nargs[3]) : 0,
+														* gradeconst = nargs[4] ? dynamic_cast<const Polymorphic *>(nargs[4]) : 0;
+					if(gradient) GradJ = to<Rn_>(C_F0(gradient,"(",theparam));
+					if(iconst) EIConst = to<Rn_>(C_F0(iconst,"(",theparam));
+					if(gradiconst) EGradIConst = to<Rnm_>(C_F0(gradiconst,"(",theparam));
+					if(econst) EEConst = to<Rn_>(C_F0(econst,"(",theparam));
+					if(gradeconst) EGradEConst = to<Rnm_>(C_F0(gradeconst,"(",theparam));
+					closetheparam=currentblock->close(currentblock);   // the cleanning block expression 
+				}
+    
+				virtual AnyType operator()(Stack stack)  const
+				{
+					double cost = 1e100;
+					WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005 
+					Rn &x = *GetAny<Rn *>((*X)(stack));	
+					long n=x.N();	
+					
+					const bool  gradient = nargs[0] ? dynamic_cast<const Polymorphic *>(nargs[0]) : 0,
+											iconst = nargs[1] ? dynamic_cast<const Polymorphic *>(nargs[1]) : 0,
+											gradiconst = nargs[2] ? dynamic_cast<const Polymorphic *>(nargs[2]) : 0,
+											econst = nargs[3] ? dynamic_cast<const Polymorphic *>(nargs[3]) : 0,
+											gradeconst = nargs[4] ? dynamic_cast<const Polymorphic *>(nargs[4]) : 0;
+					
+					long iprint = verbosity;	
+					ffcalfunc<double> ffJ(stack,JJ,theparam);
+					
+					Optimizer<ALGO> optim(ffJ,x);
+					if(nargs[5])  optim.SetLowerBounds(Arg<Rn_>(5,stack));
+					if(nargs[6])  optim.SetUpperBounds(Arg<Rn_>(6,stack));
+					if(nargs[7])  optim.SetSCStopFunctionValue(Arg<R>(7,stack));
+					if(nargs[8])  optim.SetEqualityConstraintsTolerance(Arg<Rn_>(8,stack));
+					if(nargs[9])  optim.SetSCXRelativeTolerance(Arg<R>(9,stack));
+					if(nargs[10]) optim.SetSCXAbsoluteTolerance(Arg<Rn_>(10,stack));
+					if(nargs[11]) optim.SetSCRelativeFunctionTolerance(Arg<R>(11,stack));
+					if(nargs[12]) optim.SetSCAbsoluteFunctionTolerance(Arg<R>(12,stack));
+					if(nargs[13]) optim.SetSCMaxFunctionEvaluations(Arg<long>(13,stack));
+					if(nargs[14]) optim.SetSCEllapsedTime(Arg<R>(14,stack));
+					if(nargs[15]) optim.SetInequalityConstraintsTolerance(Arg<Rn_>(15,stack));
+					if(nargs[16]) optim.SetPopulationSize(static_cast<int>(Arg<long>(16,stack)));
+					if(nargs[17])
+					{
+						optim.SetVectorStorage(static_cast<int> (Arg<long>(17,stack)));
+						if(optim.DF()) cout << "Warning: in " << optim.Name() << " algorithm - using nGradStored is pointless (no gradient to store in a derivative free context)." << endl;
+						else if(ALGO==nlopt::LD_SLSQP || ALGO==nlopt::LD_MMA) cout << "Warning: nGradStored can't be used with " << optim.Name() << ", parameter will be ignored." << endl;
+					}
+					
+					if(econst) optim.SetEqualityConstraintFunction(ffcalfunc<Rn>(stack,EEConst,theparam));
+					if(iconst) optim.SetInequalityConstraintFunction(ffcalfunc<Rn>(stack,EIConst,theparam));
+					
+					if(optim.DF())
+					{
+						if(gradient) cout << "Warning: in " << optim.Name() << " algorithm - derivative free algorithm will ignore the objective function gradient." << endl;
+						if(gradiconst)
+						{
+							cout << "Warning: in " << optim.Name() << " algorithm - derivative free algorithm will ignore the inequality constraints gradient." << endl;
+							if(!iconst) cout << "Also note that this gradient has been provided for an inexisting set of inequality constraints!" << endl;
+						}
+						if(gradeconst)
+						{
+							cout << "Warning: in " << optim.Name() << " algorithm - derivative free algorithm will ignore the equality constraints gradient." << endl;
+							if(!econst) cout << "Also note that this gradient has been provided for an inexisting set of equality constraints!" << endl;
+						}
+					}
+					else
+					{
+						if(gradient) optim.SetObjectiveFunctionGradient(ffcalfunc<Rn>(stack,GradJ,theparam));
+						else cout << "Warning: in " << optim.Name() << " algorithm - no objective function gradient has been provided (choose a derivative free algorithm if it is not available)." << endl;
+						
+						if(econst)
+						{
+							if(gradeconst) optim.SetEqualityConstraintGradient(ffcalfunc<Rnm>(stack,EGradEConst,theparam));
+							else cout << "Warning: in " << optim.Name() << " algorithm - no equality constraints gradients has been provided." << endl;
+						}
+						else if(gradeconst) cout << "Warning: in " << optim.Name() << " algorithm - gradients have been provided for an inexisting set of equality constraints." << endl;
+						
+						if(iconst)
+						{
+							if(gradiconst) optim.SetInequalityConstraintGradient(ffcalfunc<Rnm>(stack,EGradIConst,theparam));
+							else cout << "Warning: in " << optim.Name() << " algorithm - no inequality constraints gradients has been provided." << endl;
+						}
+						else if(gradiconst)cout << "Warning: in " << optim.Name() << " algorithm - gradients have been provided for an inexisting set of inequality constraints." << endl;
+					}
+					
+					if(econst) optim.SetEqualityConstraints();
+					if(iconst) optim.SetInequalityConstraints();
+					
+					if(verbosity>1) cout << Info<ALGO>::name << " starting..." << endl; 
+					try {cost = optim();}
+					catch(nlopt::roundoff_limited) {cout << " nlopt roundoff limited" << endl;}
+					catch(nlopt::forced_stop) { cout << " nlopt forced stop" << endl;}
+					catch(std::runtime_error) {cout << "runtime error" << endl;}
+					catch(std::invalid_argument) {cout << "invalid argument" << endl;}
+					catch(std::bad_alloc) {cout << "bad alloc" << endl;}
+					
+					//x = KN_<double>(optim.xbestever(),optim.dimension());
+					//cout << "Number of fitness evalution(s) : " << optim.eval() << endl;
+					
+					closetheparam.eval(stack); // clean memory 
+					WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+					return cost; //SetAny<long>(0);  Modif FH  july 2005       
+				}
+				    
+				operator aType () const { return atype<double>();}         
+		};
+  
+		E_F0 * code(const basicAC_F0 & args) const {return new E_NLopt(args,cas);}
+  
+		OptimNLopt(int c) :   OneOperator(atype<double>(),atype<Polymorphic*>(),atype<KN<R> *>()),cas(c){}
+};
+
+
+template<nlopt::algorithm ALGO,bool SA> basicAC_F0::name_and_type  OptimNLopt<ALGO,SA>::E_NLopt::name_param[]= 
+{
+	{"grad",						&typeid(Polymorphic*) },
+	{"IConst",					&typeid(Polymorphic*) },
+	{"gradIConst",			&typeid(Polymorphic*) },
+	{"EConst",					&typeid(Polymorphic*) },
+	{"gradEConst",			&typeid(Polymorphic*) },
+	{"lb",							&typeid(KN_<double>) },
+	{"ub",							&typeid(KN_<double>) },
+	{"stopFuncValue",   &typeid(double) },
+	{"tolEConst",				&typeid(KN_<double>) },
+	{"stopRelXTol",			&typeid(double) },
+	{"stopAbsXTol",     &typeid(KN_<double>) },
+	{"stopRelFTol",			&typeid(double) },
+	{"stopAbsFTol",			&typeid(double) },
+	{"stopMaxFEval",		&typeid(long) },
+	{"stopTime",				&typeid(double) },
+	{"tolIConst",				&typeid(KN_<double>) },
+	{"popSize",					&typeid(long) },
+	{"nGradStored",			&typeid(long) }
+};
+
+
+
+
+template<nlopt::algorithm ALGO> class OptimNLopt<ALGO,true> : public OneOperator 
+{
+	public:
+		const int cas;
+
+		class E_NLopt : public E_F0mps 
+		{ 
+			public:
+				const int cas;
+				static basicAC_F0::name_and_type name_param[] ;
+				static const int n_name_param =27;
+				Expression nargs[n_name_param];
+				Expression X;
+				C_F0 inittheparam,theparam,closetheparam; 
+				Expression JJ;
+				Expression GradJ,EIConst,EGradIConst,EEConst,EGradEConst;
+				long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+				R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+				Rn_ arg(int i,Stack stack,Rn_ a) const {return nargs[i] ? GetAny<Rn_>((*nargs[2])(stack)) : a;}
+				template<typename T> T Arg(int i,Stack s) const {return GetAny<T>( (*nargs[i])(s));}
+      
+				E_NLopt(const basicAC_F0 & args,int cc) : cas(cc)
+				{
+					int nbj= args.size()-1;
+					Block::open(currentblock); // make a new block to 
+					X = to<Rn*>(args[nbj]);
+					C_F0 X_n(args[nbj],"n");
+					//  the expression to init the theparam of all 
+					inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+					theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+					args.SetNameParam(n_name_param,name_param,nargs);
+					const  Polymorphic * opJ=0;
+					if (nbj>0)
+					{
+						opJ=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+						assert(opJ);
+					}      
+					JJ= to<R>(C_F0(opJ,"(",theparam));
+					const Polymorphic * gradient = nargs[0] ? dynamic_cast<const Polymorphic *>(nargs[0]) : 0,
+														* iconst = nargs[1] ? dynamic_cast<const Polymorphic *>(nargs[1]) : 0,
+														* gradiconst = nargs[2] ? dynamic_cast<const Polymorphic *>(nargs[2]) : 0,
+														* econst = nargs[3] ? dynamic_cast<const Polymorphic *>(nargs[3]) : 0,
+														* gradeconst = nargs[4] ? dynamic_cast<const Polymorphic *>(nargs[4]) : 0;
+					if(gradient) GradJ = to<Rn_>(C_F0(gradient,"(",theparam));
+					if(iconst) EIConst = to<Rn_>(C_F0(iconst,"(",theparam));
+					if(gradiconst) EGradIConst = to<Rnm_>(C_F0(gradiconst,"(",theparam));
+					if(econst) EEConst = to<Rn_>(C_F0(econst,"(",theparam));
+					if(gradeconst) EGradEConst = to<Rnm_>(C_F0(gradeconst,"(",theparam));
+					closetheparam=currentblock->close(currentblock);   // the cleanning block expression 
+				}
+    
+				virtual AnyType operator()(Stack stack)  const
+				{
+					double cost = 1e100;
+					WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005 
+					Rn &x = *GetAny<Rn *>((*X)(stack));	
+					long n=x.N();	
+					
+					const bool  gradient = nargs[0] ? dynamic_cast<const Polymorphic *>(nargs[0]) : 0,
+											iconst = nargs[1] ? dynamic_cast<const Polymorphic *>(nargs[1]) : 0,
+											gradiconst = nargs[2] ? dynamic_cast<const Polymorphic *>(nargs[2]) : 0,
+											econst = nargs[3] ? dynamic_cast<const Polymorphic *>(nargs[3]) : 0,
+											gradeconst = nargs[4] ? dynamic_cast<const Polymorphic *>(nargs[4]) : 0;
+											
+					
+					long iprint = verbosity;	
+					ffcalfunc<double> ffJ(stack,JJ,theparam);
+					
+					SAOptimizer<ALGO> optim(ffJ,x);
+					if(nargs[5])  optim.SetLowerBounds(Arg<Rn_>(5,stack));
+					if(nargs[6])  optim.SetUpperBounds(Arg<Rn_>(6,stack));
+					if(nargs[7])  optim.SetSCStopFunctionValue(Arg<R>(7,stack));
+					if(nargs[8])  optim.SetEqualityConstraintsTolerance(Arg<Rn_>(8,stack));
+					if(nargs[9])  optim.SetSCXRelativeTolerance(Arg<R>(9,stack));
+					if(nargs[10]) optim.SetSCXAbsoluteTolerance(Arg<Rn_>(10,stack));
+					if(nargs[11]) optim.SetSCRelativeFunctionTolerance(Arg<R>(11,stack));
+					if(nargs[12]) optim.SetSCAbsoluteFunctionTolerance(Arg<R>(12,stack));
+					if(nargs[13]) optim.SetSCMaxFunctionEvaluations(Arg<long>(13,stack));
+					if(nargs[14]) optim.SetSCEllapsedTime(Arg<R>(14,stack));
+					if(nargs[15]) optim.SetInequalityConstraintsTolerance(Arg<Rn_>(15,stack));
+					if(nargs[16]) optim.SetPopulationSize(static_cast<int>(Arg<long>(16,stack)));
+					if(nargs[17]) optim.SetSubOptimizer(*Arg<string*>(17,stack),0);
+					else cout << "Warning: in " << optim.Name() << " algorithm - you have to specify a local optimizer, aboarting optimization (use the subOpt named parameter)." << endl;
+					if(nargs[18])  optim.SetSASCStopFunctionValue(Arg<R>(18,stack));
+					if(nargs[19])  optim.SetSASCXRelativeTolerance(Arg<R>(19,stack));
+					if(nargs[20]) optim.SetSASCXAbsoluteTolerance(Arg<Rn_>(20,stack));
+					if(nargs[21]) optim.SetSASCRelativeFunctionTolerance(Arg<R>(21,stack));
+					if(nargs[22]) optim.SetSASCAbsoluteFunctionTolerance(Arg<R>(22,stack));
+					if(nargs[23]) optim.SetSASCMaxFunctionEvaluations(Arg<long>(23,stack));
+					if(nargs[24]) optim.SetSASCEllapsedTime(Arg<R>(24,stack));
+					if(nargs[25]) optim.SetSAPopulationSize(static_cast<int>(Arg<long>(25,stack)));
+					if(nargs[26]) 
+					{
+						optim.SetVectorStorage(static_cast<int> (Arg<long>(26,stack)));
+						if(optim.DF()) cout << "Warning: in " << optim.subopt->Name() << " algorithm - using nGradStored is pointless (no gradient to store in a derivative free context)." << endl;
+						else if(optim.subopt->Tag()==nlopt::LD_SLSQP || optim.subopt->Tag()==nlopt::LD_MMA) 
+							cout << "Warning: nGradStored can't be used with " << optim.Name() << ", parameter will be ignored." << endl;
+					}
+					optim.SetSubOptimizer();
+
+					
+					if(econst) optim.SetEqualityConstraintFunction(ffcalfunc<Rn>(stack,EEConst,theparam));
+					if(iconst) optim.SetInequalityConstraintFunction(ffcalfunc<Rn>(stack,EIConst,theparam));
+					
+					if(optim.subopt)
+					{
+						if(optim.subopt->DF())
+						{
+							if(gradient) cout << "Warning: in " << optim.Name() << " algorithm - derivative free sub-algorithm will ignore the objective function gradient." << endl;
+							if(gradiconst)
+							{
+								cout << "Warning: in " << optim.Name() << " algorithm - derivative free sub-algorithm will ignore the inequality constraints gradient." << endl;
+								if(!iconst) cout << "Also note that this gradient has been provided for an inexisting set of inequality constraints!" << endl;
+							}
+							if(gradeconst)
+							{
+								cout << "Warning: in " << optim.Name() << " algorithm - derivative free sub-algorithm will ignore the equality constraints gradient." << endl;
+								if(!econst) cout << "Also note that this gradient has been provided for an inexisting set of equality constraints!" << endl;
+							}
+						}
+						else
+						{
+							if(gradient) optim.SetObjectiveFunctionGradient(ffcalfunc<Rn>(stack,GradJ,theparam));
+							else cout << "Warning: in " << optim.Name() << " algorithm - no objective function gradient has been provided (choose a derivative free local search if it is not available)." << endl;
+						
+							if(econst)
+							{
+								if(gradeconst) optim.SetEqualityConstraintGradient(ffcalfunc<Rnm>(stack,EGradEConst,theparam));
+								else cout << "Warning: in " << optim.Name() << " algorithm - no equality constraints gradients has been provided." << endl;
+							}
+							else if(gradeconst) cout << "Warning: in " << optim.Name() << " algorithm - gradients have been provided for an inexisting set of equality constraints." << endl;
+						
+							if(iconst)
+							{
+								if(gradiconst) optim.SetInequalityConstraintGradient(ffcalfunc<Rnm>(stack,EGradIConst,theparam));
+								else cout << "Warning: in " << optim.Name() << " algorithm - no inequality constraints gradients has been provided." << endl;
+							}
+							else if(gradiconst)cout << "Warning: in " << optim.Name() << " algorithm - gradients have been provided for an inexisting set of inequality constraints." << endl;
+						}
+					
+						if(econst) optim.SetEqualityConstraints();
+						if(iconst) optim.SetInequalityConstraints();
+					
+						if(verbosity>1) cout << Info<ALGO>::name << " starting..." << endl; 
+						try {cost = optim();}
+						catch(nlopt::roundoff_limited) {cout << " nlopt roundoff limited" << endl;}
+						catch(nlopt::forced_stop) { cout << " nlopt forced stop" << endl;}
+						catch(std::runtime_error) {cout << "runtime error" << endl;}
+						catch(std::invalid_argument) {cout << "invalid argument" << endl;}
+						catch(std::bad_alloc) {cout << "bad alloc" << endl;}
+					}
+					//x = KN_<double>(optim.xbestever(),optim.dimension());
+					//cout << "Number of fitness evalution(s) : " << optim.eval() << endl;
+					
+					closetheparam.eval(stack); // clean memory 
+					WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+					return cost; //SetAny<long>(0);  Modif FH  july 2005       
+				}
+				    
+				operator aType () const { return atype<double>();}         
+		};
+  
+		E_F0 * code(const basicAC_F0 & args) const {return new E_NLopt(args,cas);}
+  
+		OptimNLopt(int c) :   OneOperator(atype<double>(),atype<Polymorphic*>(),atype<KN<R> *>()),cas(c){}
+};
+
+
+template<nlopt::algorithm ALGO> basicAC_F0::name_and_type  OptimNLopt<ALGO,true>::E_NLopt::name_param[]= 
+{
+	{"grad",						&typeid(Polymorphic*) },
+	{"IConst",					&typeid(Polymorphic*) },
+	{"gradIConst",			&typeid(Polymorphic*) },
+	{"EConst",					&typeid(Polymorphic*) },
+	{"gradEConst",			&typeid(Polymorphic*) },
+	{"lb",							&typeid(KN_<double>) },
+	{"ub",							&typeid(KN_<double>) },
+	{"stopFuncValue",   &typeid(double) },
+	{"tolEConst",				&typeid(KN_<double>) },
+	{"stopRelXTol",			&typeid(double) },
+	{"stopAbsXTol",     &typeid(KN_<double>) },
+	{"stopRelFTol",			&typeid(double) },
+	{"stopAbsFTol",			&typeid(double) },
+	{"stopMaxFEval",		&typeid(long) },
+	{"stopTime",				&typeid(double) },
+	{"tolIConst",				&typeid(KN_<double>) },
+	{"popSize",					&typeid(long) }, //16
+	{"subOpt",					&typeid(string*) },
+	{"SOStopFuncValue", &typeid(double) },
+	{"SOStopRelXTol",		&typeid(double) },
+	{"SOStopAbsXTol",   &typeid(KN_<double>) },
+	{"SOStopRelFTol",		&typeid(double) },
+	{"SOStopAbsFTol",		&typeid(double) },
+	{"SOStopMaxFEval",	&typeid(long) },
+	{"SOStopTime",			&typeid(double) },
+	{"SOPopSize",				&typeid(long) },
+	{"nGradStored",			&typeid(long) }
+};
+
+
+
+
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init()  
+{
+  Global.Add("nloptDIRECT",								"(",new OptimNLopt<nlopt::GN_DIRECT>(1)); 
+  Global.Add("nloptDIRECTL",							"(",new OptimNLopt<nlopt::GN_DIRECT_L>(1));
+  Global.Add("nloptDIRECTLRand",					"(",new OptimNLopt<nlopt::GN_DIRECT_L_RAND>(1)); 
+  Global.Add("nloptDIRECTNoScal",					"(",new OptimNLopt<nlopt::GN_DIRECT_NOSCAL>(1)); 
+  Global.Add("nloptDIRECTLNoScal",				"(",new OptimNLopt<nlopt::GN_DIRECT_L_NOSCAL>(1)); 
+  Global.Add("nloptDIRECTLRandNoScal",		"(",new OptimNLopt<nlopt::GN_DIRECT_L_RAND_NOSCAL>(1)); 
+  Global.Add("nloptOrigDIRECT",						"(",new OptimNLopt<nlopt::GN_ORIG_DIRECT>(1)); 
+  Global.Add("nloptOrigDIRECTL",					"(",new OptimNLopt<nlopt::GN_ORIG_DIRECT_L>(1));
+  Global.Add("nloptStoGO",								"(",new OptimNLopt<nlopt::GD_STOGO>(1));
+  Global.Add("nloptStoGORand",						"(",new OptimNLopt<nlopt::GD_STOGO_RAND>(1));
+  //Global.Add("nloptLBFGSNocedal",					"(",new OptimNLopt<nlopt::LD_LBFGS_NOCEDAL>(1)); //Invalid argument
+  Global.Add("nloptLBFGS",								"(",new OptimNLopt<nlopt::LD_LBFGS>(1)); 
+  Global.Add("nloptPRAXIS",								"(",new OptimNLopt<nlopt::LN_PRAXIS>(1));
+  Global.Add("nloptVar1",									"(",new OptimNLopt<nlopt::LD_VAR1>(1));  
+  Global.Add("nloptVar2",									"(",new OptimNLopt<nlopt::LD_VAR2>(1));  
+  Global.Add("nloptTNewton",							"(",new OptimNLopt<nlopt::LD_TNEWTON>(1));
+  Global.Add("nloptTNewtonRestart",				"(",new OptimNLopt<nlopt::LD_TNEWTON_RESTART>(1));
+  Global.Add("nloptTNewtonPrecond",				"(",new OptimNLopt<nlopt::LD_TNEWTON_PRECOND>(1));
+  Global.Add("nloptTNewtonPrecondRestart","(",new OptimNLopt<nlopt::LD_TNEWTON_PRECOND_RESTART>(1));  
+  Global.Add("nloptCRS2",									"(",new OptimNLopt<nlopt::GN_CRS2_LM>(1));
+  Global.Add("nloptMMA",									"(",new OptimNLopt<nlopt::LD_MMA>(1));  
+  Global.Add("nloptCOBYLA",								"(",new OptimNLopt<nlopt::LN_COBYLA>(1));  
+  Global.Add("nloptNEWUOA",								"(",new OptimNLopt<nlopt::LN_NEWUOA>(1));  
+  Global.Add("nloptNEWUOABound",					"(",new OptimNLopt<nlopt::LN_NEWUOA_BOUND>(1)); 
+  Global.Add("nloptNelderMead",						"(",new OptimNLopt<nlopt::LN_NELDERMEAD>(1));
+	Global.Add("nloptSbplx",								"(",new OptimNLopt<nlopt::LN_SBPLX>(1));
+	Global.Add("nloptBOBYQA",								"(",new OptimNLopt<nlopt::LN_BOBYQA>(1));
+	Global.Add("nloptISRES",								"(",new OptimNLopt<nlopt::GN_ISRES>(1));
+	Global.Add("nloptSLSQP",								"(",new OptimNLopt<nlopt::LD_SLSQP>(1));
+	Global.Add("nloptMLSL",									"(",new OptimNLopt<nlopt::G_MLSL>(1));
+	Global.Add("nloptMLSLLDS",							"(",new OptimNLopt<nlopt::G_MLSL_LDS>(1));
+	Global.Add("nloptAUGLAG",								"(",new OptimNLopt<nlopt::AUGLAG>(1));
+	Global.Add("nloptAUGLAGEQ",							"(",new OptimNLopt<nlopt::AUGLAG_EQ>(1));
+}
+
+
+
+
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/ff-cmaes.cpp b/examples++-load/ff-cmaes.cpp
new file mode 100644
index 0000000..0700f03
--- /dev/null
+++ b/examples++-load/ff-cmaes.cpp
@@ -0,0 +1,308 @@
+
+//ff-c++-cpp-dep: cmaes.cpp
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Sylvain Auliac
+// E-MAIL   : auliac at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+/* 
+	This is a freefem interface of the Hansen's CMA-ES C optimizer.
+	The class CMAES is a quick C++ interface for the contents of the C files
+	then follow the real FreeFem++ stuff.
+*/
+
+
+#include  <iostream>
+using namespace std;
+#include "ff++.hpp"
+
+#include "cmaes_interface.h"
+
+
+class CMAES //Abstract class, because the fitness function prototype may differ from users to users
+{
+	public:
+		//typedef double (*FFT)(double const *); //Fitness Function Type
+		CMAES() : pop(0),fitvals(0),evo() {}
+		CMAES(int d,double *xstart,double *stddev,long seed,int lambda,const char *ipf="initials.par") : pop(0),fitvals(0),evo()
+		{
+			fitvals = init(d,xstart,stddev,seed,lambda,ipf);
+			cout << SayHello() << endl;
+		}
+		virtual ~CMAES() {exit();}
+		
+		void resume_distribution(char *filename) {return cmaes_resume_distribution(&evo, filename);}
+		double * const * & SamplePopulation() {return pop = cmaes_SamplePopulation(&evo);}
+		double * UpdateDistribution() {return cmaes_UpdateDistribution(&evo,fitvals);}
+		const char * TestForTermination() const {return cmaes_TestForTermination(&evo);}
+		double * const * & ReSampleSingle(int index) {return pop = cmaes_ReSampleSingle(&evo,index);}
+		double const * ReSampleSingle_old(double *rgx) {return cmaes_ReSampleSingle_old(&evo,rgx);}
+		void UpdateEigensystem(int flgforce) {return cmaes_UpdateEigensystem(&evo, flgforce);}
+		virtual void PopEval() =0;
+		//{for(int i=0;i<popsize();++i) fitvals[i] = ff(pop[i]);} //the thing to parralelize
+		
+		double axisratio() const {return cmaes_Get(&evo,"axisratio");}	//between lengths of longest and shortest principal axis of the distribution ellipsoid 
+		int eval() const {return floor(cmaes_Get(&evo,"eval"));}				//number of function evaluations
+		double fitness() const {return cmaes_Get(&evo,"fitness");}			//recent best function evaluation
+		double fbestever() const {return cmaes_Get(&evo,"fbestever");}  //ever best function value
+		int generation() const {return floor(cmaes_Get(&evo,"generation"));}
+		int maxeval() const {return floor(cmaes_Get(&evo,"maxeval"));}	//maximal number of function evaluations
+		int maxgen() const {return floor(cmaes_Get(&evo,"maxgen"));}		//maximal number of generations
+		double maxaxislength() const {return cmaes_Get(&evo,"maxaxislength");}
+		double minaxislength() const {return cmaes_Get(&evo,"minaxislength");}
+		double maxstddev() const {return cmaes_Get(&evo,"maxstddev");}
+		double minstddev() const {return cmaes_Get(&evo,"minstddev");}
+		int dimension() const {return floor(cmaes_Get(&evo,"dimension"));}
+		int popsize() const {return floor(cmaes_Get(&evo,"lambda"));}
+		double sigma() const {return cmaes_Get(&evo,"sigma");}
+		double * diagC() const {return const_cast<double*>(cmaes_GetPtr(&evo,"diag(C)"));}
+		double * diagD() const {return const_cast<double*>(cmaes_GetPtr(&evo,"diag(D)"));}
+		double * stddev() const {return const_cast<double*>(cmaes_GetPtr(&evo,"stddev"));}
+		double * xbestever() const {return const_cast<double*>(cmaes_GetPtr(&evo,"xbestever"));}
+		double * xbest() const {return const_cast<double*>(cmaes_GetPtr(&evo,"xbest"));}
+		double * xmean() const {return const_cast<double*>(cmaes_GetPtr(&evo,"xmean"));}
+		
+		void ReadSignals(char const * filename) const {cmaes_ReadSignals(&evo,filename);}
+		char * SayHello() const {return cmaes_SayHello(&evo);}
+		void WriteToFile(char const * keyword,char const * output_filename) const {cmaes_WriteToFile(&evo,keyword,output_filename);}
+		
+		virtual double * operator() () 
+		{
+			//ReadSignals("signals.par");
+			while(!TestForTermination())
+			{
+				SamplePopulation();
+				PopEval();
+				UpdateDistribution();
+				//ReadSignals("signals.par");
+			}
+			cout << "Stop : " << TestForTermination() << endl;
+			return xmean();
+		}
+		cmaes_t& optimizer() {return evo;}
+	protected:
+		double * const * pop;
+		double * fitvals;
+	private:
+		void exit() {cmaes_exit(&evo);}
+		double*& init(int dimension,double *xstart,double *stddev,long seed,int lambda,const char *input_parameter_filename)
+			{return fitvals = cmaes_init(&evo,dimension,xstart,stddev,seed,lambda,input_parameter_filename);}
+		mutable cmaes_t evo;
+};
+
+
+
+
+/*
+	Now comes the FreeFem ++ part :
+*/
+
+extern Block *currentblock;
+
+typedef double R;
+
+class OptimCMA_ES : public OneOperator 
+{
+	public:
+		typedef KN<R> Kn;
+		typedef KN_<R> Kn_;
+		const int cas;
+
+
+		class ffcalfunc  //   to call the freefem function .. J 
+		{ 
+			public:
+				Stack stack;
+				Expression JJ,theparame;
+    
+				ffcalfunc(Stack s,Expression JJJ,Expression epar) : stack(s),JJ(JJJ), theparame(epar) {}
+				double J(Kn_  x) const 
+				{
+					KN<double> *p=GetAny<KN<double> *>( (*theparame)(stack) );
+					*p=x;
+					double ret= GetAny<R>( (*JJ)(stack));
+					WhereStackOfPtr2Free(stack)->clean();
+					return  ret; 
+				}
+		}; 
+		class CMA_ES : public CMAES
+		{
+			public:
+				typedef KN<double> Rn;
+				typedef KN_<double> Rn_;
+		
+		
+				CMA_ES() : CMAES(),x(0),fit(0) {}
+				/*CMA_ES(ffcalfunc &_ff,int d,Rn &xstart,double *stddev,long seed,int lambda)
+					: CMAES(d,xstart.n ? xstart:0,stddev,seed,lambda,"non"),x(&xstart),fit(&_ff) {}
+				CMA_ES(ffcalfunc &_ff,int d,Rn &xstart,const Rn &stddev,long seed,int lambda) 
+					: CMAES(d,xstart.n ? xstart:0,stddev,seed,lambda,"non"),x(&xstart),fit(&_ff) {}*/
+				CMA_ES(ffcalfunc &_ff,Rn &xstart,const Rn &stddev,long seed,int lambda)
+					: CMAES(xstart.n,xstart,stddev,seed,lambda,"non"),x(&xstart),fit(&_ff) {}
+				CMA_ES(ffcalfunc &_ff,Rn &xstart,const Rn &stddev,long seed,int lambda,const string &ipf)
+					: CMAES(xstart.n,xstart,stddev,seed,lambda,ipf.c_str()),x(&xstart),fit(&_ff) {}
+		
+		
+				void PopEval() {for(int i=0;i<popsize();++i) {Rn_ popi(pop[i],dimension()); fitvals[i] = fit->J(popi);}}
+				double * operator() () {return *x = Rn(x->n,CMAES::operator()());}
+			private:
+				ffcalfunc *fit;
+				Rn *x;
+		};
+
+  
+
+		class E_CMA_ES: public E_F0mps 
+		{ 
+			public:
+				const int cas;
+				static basicAC_F0::name_and_type name_param[] ;
+				static const int n_name_param =11;
+				Expression nargs[n_name_param];
+				Expression X;
+				C_F0 inittheparam,theparam,closetheparam; 
+				Expression JJ;
+				long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+				R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+      
+				E_CMA_ES(const basicAC_F0 & args,int cc) : cas(cc)
+				{
+					int nbj= args.size()-1;
+					Block::open(currentblock); // make a new block to 
+					X = to<Kn*>(args[nbj]);
+					C_F0 X_n(args[nbj],"n");
+					//  the expression to init the theparam of all 
+					inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+					theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+					args.SetNameParam(n_name_param,name_param,nargs);
+					const  Polymorphic * opJ=0;
+					if (nbj>0)
+					{
+						opJ=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+						assert(opJ);
+					}      
+					JJ= to<R>(C_F0(opJ,"(",theparam));
+					closetheparam=currentblock->close(currentblock);   // the cleanning block expression 
+				}
+    
+				virtual AnyType operator()(Stack stack)  const
+				{
+					double cost = 1e100;
+					WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005 
+					Kn &x = *GetAny<Kn *>((*X)(stack));	
+					long n=x.N();	
+					long seed =	arg(0,stack,0L); //The seed for random numbers generation
+					double initialStdDev = arg(1,stack,0.3); //Initial standard deviation
+					KN<double> iSD(n,1.);
+					iSD *= initialStdDev;
+					KN<double> initialStdDevs(nargs[2] ? GetAny<KN_<double> >((*nargs[2])(stack)) : (KN_<double>)iSD);
+					//cout << "dans le dylib :" << initialStdDevs << endl;
+					double stopTolFun = arg(3,stack,1.E-12);
+					double stopTolFunHist = arg(4,stack,0.);
+					double stopTolX = arg(5,stack,0.);
+					double stopTolUpXFactor = arg(6,stack,1.E3);
+					long popsize = arg(7,stack,4 + (long) floor(3*log(n)));
+					//long mu = arg(8,stack,popsize/2);
+					string pipf = nargs[10] ? *GetAny<string*>((*nargs[10])(stack)) : string("") ;
+					
+					long iprint = verbosity;	
+					ffcalfunc ffJ(stack,JJ,theparam);
+					
+					CMA_ES *optim=0;
+					if(pipf.size()>0)
+					{
+						cout << "input file : " << pipf << endl;
+						optim = new CMA_ES(ffJ,x,initialStdDevs,seed,popsize,pipf);
+					}
+					else 
+					{
+						cout << "no input file " << endl;
+						optim = new CMA_ES(ffJ,x,initialStdDevs,seed,popsize);
+						long meval = arg(8,stack,static_cast<long>(optim->maxeval()));
+						long mgen = arg(9,stack,static_cast<long>(optim->maxgen()));
+						optim->optimizer().sp.stopTolFun = stopTolFun;
+						optim->optimizer().sp.stopTolFunHist = stopTolFunHist;
+						optim->optimizer().sp.stopTolX = stopTolX;
+						optim->optimizer().sp.stopTolUpXFactor = stopTolUpXFactor;
+						optim->optimizer().sp.stopMaxFunEvals = meval;
+						optim->optimizer().sp.stopMaxIter = mgen;
+					}
+					
+					(*optim)();
+					cost = optim->fitness();
+					x = KN_<double>(optim->xbestever(),optim->dimension());
+					cout << "Number of fitness evalution(s) : " << optim->eval() << endl;
+					
+					closetheparam.eval(stack); // clean memory 
+					
+					if(optim) {delete optim; optim=0;}
+					WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+					return cost; //SetAny<long>(0);  Modif FH  july 2005       
+				}
+				    
+				operator aType () const { return atype<double>();}         
+		};
+  
+		E_F0 * code(const basicAC_F0 & args) const {return new E_CMA_ES(args,cas);}
+  
+		OptimCMA_ES(int c) :   OneOperator(atype<double>(),atype<Polymorphic*>(),atype<KN<R> *>()),cas(c){}
+};
+
+basicAC_F0::name_and_type  OptimCMA_ES::E_CMA_ES::name_param[]= 
+{
+	{"seed",						&typeid(long) },
+	{"initialStdDev",		&typeid(double) },
+	{"initialStdDevs",	&typeid(KN_<double>) },
+	{"stopTolFun",			&typeid(double) },
+	{"stopTolFunHist",	&typeid(double) },
+	{"stopTolX",				&typeid(double) },
+	{"stopTolUpXFactor",&typeid(double) },
+	{"popsize",					&typeid(long) },
+	{"stopMaxFunEval",  &typeid(long) },
+	{"stopMaxIter",			&typeid(long) },
+	{"paramFile",				&typeid(string*) }
+	//{"mu",							&typeid(long) }
+};
+
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init()  
+{
+  Global.Add("cmaes","(",new OptimCMA_ES(1)); 
+
+}
+
+
+
+
+
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/ff-get-dep.awk b/examples++-load/ff-get-dep.awk
new file mode 100644
index 0000000..b11308c
--- /dev/null
+++ b/examples++-load/ff-get-dep.awk
@@ -0,0 +1,36 @@
+BEGIN { nl=split(libs,l,"[ ]*"); err= 0;sp=" ";db=0;}
+$2=="LD" { 
+    if( ld[$1]=="" )  {
+	a=$1;
+	sub(/.* LD /,"");
+	ld[a]=$0 sp; 
+	if(db) print a,$0
+    }}
+$2=="INCLUDE" { if( inc[$1]=="" ) {
+	a=$1;sub(/.* INCLUDE /,"");
+	inc[a]=$0 sp;
+	if(db)	print a,$0;
+}}
+END {
+    msg=cpp sp;
+    for(i=1; i<=nl;++i)
+    {
+	libb=l[i];
+	if (match(libb,/^[ ]*$/)) continue; 
+	lib=libb;
+	nn=sub(/\[/,"",lib);
+	nn+=sub(/\]/,"",lib);
+	if (ld[lib]=="" && nn ==0) { lerr[err++]=lib ;}
+        if(ld[lib]!="" && nn==2) msg=msg "-DWITH_" lib sp;
+	if(db) print lib, err;
+	msg = msg ld[lib] sp inc[lib] sp; 
+    }
+    
+    if(err) {
+	for(i=0; i < err;++i)
+	    print " MISSING lib " , lerr[i] 
+	print " Check the WHERE-LIBRARY... files ";
+	exit 1; 
+    }
+    else printf("%s\n",msg); 
+}
\ No newline at end of file
diff --git a/examples++-load/ff-get-dep.in b/examples++-load/ff-get-dep.in
new file mode 100755
index 0000000..79a50d6
--- /dev/null
+++ b/examples++-load/ff-get-dep.in
@@ -0,0 +1,38 @@
+#!/bin/sh
+# ff-c++ `./ff-get-dep -ff metis.cpp`
+
+case "$1" in
+    -dlib)
+	shift
+	awk -F:  '/^[\/]+ff-c[+][+]-LIBRARY-dep:/  { printf("%s",$2); exit 0;}' $@
+	exit 0; 
+	;;
+    -dcpp)
+	shift
+	awk -F:  '/^[\/]+ff-c[+][+]-cpp-dep:/  { printf("%s",$2); exit 0;}' $@
+	exit 0; 
+	;;
+    -ff)
+	shift;
+#  ajout  de lib  with check
+	libs=`$0 -dlib $@`
+	cpp=`$0 -dcpp $@`" $@"
+	;;
+esac 
+dircommand=`dirname $0`
+if [   -f "WHERE_LIBRARY-download" ] ; then
+dircommand="./"
+elif [   -f "$dircommand/WHERE_LIBRARY-download" ] ; then
+    dirwhere=$dircommand
+elif [ -f '@ff_prefix_dir@/lib/WHERE_LIBRARY-download' ] ; then
+    dirwhere='@ff_prefix_dir@/lib'
+else
+   echo " error no WHERE_LIBRARY  file "
+   exit 1;
+fi
+cd "$dirwhere"
+wherel=WHERE_LIBRARY-download
+test -f WHERE_LIBRARY-config && wherel="$wherel  WHERE_LIBRARY-config"
+test -f WHERE_LIBRARY && wherel="$wherel WHERE_LIBRARY"
+awk -f ff-get-dep.awk -v libs="$libs"  -v cpp="$cpp" $wherel
+exit $?
diff --git a/examples++-load/ff-pkg-download.in b/examples++-load/ff-pkg-download.in
new file mode 100755
index 0000000..c279e76
--- /dev/null
+++ b/examples++-load/ff-pkg-download.in
@@ -0,0 +1,95 @@
+#!/bin/bash
+# Building WHERE_LIBRARY-download
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# ======================================================================
+# This file is part of Freefem++
+#
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh brief="Building WHERE_LIBRARY-download" default=0 freefem multipleauthors shell start=21/09/09 upmc
+
+ff=$0;
+bb=`basename $0`
+DIR=`dirname $ff`
+pp=`pwd`
+DESTDIR=""
+if [ -n "$1" ] ; then
+DESTDIR="$1/"
+elif [ $bb = $ff -a  \( '.' = "$DIR" -o -z "$DIR" \) ] ;  then
+  ff=`which $0`
+  DIR=`dirname $ff`
+  if [ '.' = "$DIR" -o -z "$DIR" ] ;  then
+     echo Sorry cant find the Directory  place of $0
+  fi
+fi
+case $DIR in 
+/*) ;;
+[.])  DIR=$pp;;
+*)  DIR="$pp/$DIR"
+esac
+DIRP=`dirname $DIR`
+#echo "WWWWW"  $DIRP 
+if [ -d "$DESTDIR$DIRP/download/lib" -a -d "$DESTDIR$DIRP/download/include"  ] ; then
+    DIR="$DIRP/download"
+    DIRW="$DIRP/examples++-load"
+elif [ -d "$DESTDIR$DIRP/lib" -a -d "$DESTDIR$DIRP/include"  ] ; then
+    DIR="$DIRP"
+    DIRW="$DIR/lib"
+else
+  DIR=@ff_prefix_dir@
+  DIRW="$DIRW/lib"
+fi
+
+if [   -d $DESTDIR$DIR/lib -a -d $DESTDIR$DIR/include  ] ; then
+    LIB="$DIR/lib"
+    INC="$DIR/include"
+    cd "$DESTDIR$LIB"
+#  set -x
+    for i in $LIB/WHERE.* ; do            
+	test -f $i && ( sed "s;@DIR@;$DIR;" <$i  )
+    done
+    # ALH - 6/1/14 - remove umfpack and amd because some versions of umfpack needs more than just adding -L (they need
+    # the colamd and cholmod libraries, which are setup in [[file:configure.ac]]).
+    cd "$DIRW"
+    for la in arpack fftw3 mmg3d; do
+        l=`echo $la |sed -e s/^tet$/tetgen/`
+	nbw=`awk "/^$la /" WHERE_LIBRARY WHERE_LIBRARY-config|wc -l`
+       if [ "$nbw" -ne 0 -a ! -f $LIB/WHERE.$l  ]; then
+	   if [ -z "$l" ];then l="$la";fi  
+	   if  ( ls  "lib$la"[-._0-9]*a 1>/dev/null 2>/dev/null ) ; then 
+	       ll=`ls  "lib$la"[-._0-9]*a|grep [.]a`
+	       if [ -n "$ll" ]; then 
+		   lib=`expr "$ll" : lib'\(.*\).a'`
+		   echo $l LD "'"-L$LIB"'" "'"-l$lib"'"
+		   if [ -d $INC/$la ] ; then
+		       echo $l INCLUDE "'"-I$INC/$la"'"
+		   else
+		       echo $l INCLUDE "'"-I$INC"'"
+		   fi
+	       fi
+	   fi
+       fi
+    done
+else
+    echo error not directory $DIR/lib and $DIR/include  $DIRP 
+fi
+
+# Local Variables:
+# mode:shell-script
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/examples++-load/ff_gsl_awk.hpp b/examples++-load/ff_gsl_awk.hpp
new file mode 100644
index 0000000..3392796
--- /dev/null
+++ b/examples++-load/ff_gsl_awk.hpp
@@ -0,0 +1,914 @@
+ /*  
+//  -- missing type "const double[]" 
+ missing: 5   gsl_ran_dirichlet_pdf  -> /usr/local/include/gsl/gsl_randist.h:double gsl_ran_dirichlet_pdf (const size_t K, const double alpha[], const double theta[]);
+ missing: 5   gsl_ran_dirichlet_lnpdf  -> /usr/local/include/gsl/gsl_randist.h:double gsl_ran_dirichlet_lnpdf (const size_t K, const double alpha[], const double theta[]);
+//  -- missing type "size_t" 
+ missing: 4   gsl_ran_discrete_pdf  -> /usr/local/include/gsl/gsl_randist.h:double gsl_ran_discrete_pdf (size_t k, const gsl_ran_discrete_t *g);
+//  -- missing type "const gsl_mode_t" 
+ missing: 5   gsl_sf_airy_Ai_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Ai_e(const double x, const gsl_mode_t mode, gsl_sf_result * result);
+//  -- missing type "gsl_mode_t" 
+ missing: 4   gsl_sf_airy_Ai  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Ai(const double x, gsl_mode_t mode);
+ missing: 5   gsl_sf_airy_Bi_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Bi_e(const double x, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_Bi  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Bi(const double x, gsl_mode_t mode);
+ missing: 5   gsl_sf_airy_Ai_scaled_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Ai_scaled_e(const double x, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_Ai_scaled  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Ai_scaled(const double x, gsl_mode_t mode);
+ missing: 5   gsl_sf_airy_Bi_scaled_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Bi_scaled_e(const double x, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_Bi_scaled  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Bi_scaled(const double x, gsl_mode_t mode);
+ missing: 5   gsl_sf_airy_Ai_deriv_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Ai_deriv_e(const double x, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_Ai_deriv  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Ai_deriv(const double x, gsl_mode_t mode);
+ missing: 5   gsl_sf_airy_Bi_deriv_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Bi_deriv_e(const double x, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_Bi_deriv  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Bi_deriv(const double x, gsl_mode_t mode);
+ missing: 5   gsl_sf_airy_Ai_deriv_scaled_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Ai_deriv_scaled_e(const double x, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_Ai_deriv_scaled  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Ai_deriv_scaled(const double x, gsl_mode_t mode);
+ missing: 5   gsl_sf_airy_Bi_deriv_scaled_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_Bi_deriv_scaled_e(const double x, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_Bi_deriv_scaled  -> /usr/local/include/gsl/gsl_sf_airy.h:double gsl_sf_airy_Bi_deriv_scaled(const double x, gsl_mode_t mode);
+//  -- missing type "gsl_sf_result *" 
+ missing: 4   gsl_sf_airy_zero_Ai_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_zero_Ai_e(unsigned int s, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_zero_Bi_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_zero_Bi_e(unsigned int s, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_zero_Ai_deriv_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_zero_Ai_deriv_e(unsigned int s, gsl_sf_result * result);
+ missing: 4   gsl_sf_airy_zero_Bi_deriv_e  -> /usr/local/include/gsl/gsl_sf_airy.h:int gsl_sf_airy_zero_Bi_deriv_e(unsigned int s, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_J0_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_J0_e(const double x,  gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_J1_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_J1_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_Jn_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Jn_e(int n, double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_Y0_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Y0_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_Y1_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Y1_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_Yn_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Yn_e(int n,const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_I0_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_I0_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_I1_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_I1_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_In_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_In_e(const int n, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_I0_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_I0_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_I1_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_I1_scaled_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_In_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_In_scaled_e(int n, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_K0_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_K0_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_K1_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_K1_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_Kn_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Kn_e(const int n, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_K0_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_K0_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_K1_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_K1_scaled_e(const double x, gsl_sf_result * result); 
+ missing: 5   gsl_sf_bessel_Kn_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Kn_scaled_e(int n, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_j0_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_j0_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_j1_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_j1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_j2_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_j2_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_jl_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_jl_e(const int l, const double x, gsl_sf_result * result);
+//  -- missing type "double *" 
+ missing: 5   gsl_sf_bessel_jl_array  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_jl_array(const int lmax, const double x, double * result_array);
+ missing: 5   gsl_sf_bessel_jl_steed_array  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_jl_steed_array(const int lmax, const double x, double * jl_x_array);
+ missing: 4   gsl_sf_bessel_y0_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_y0_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_y1_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_y1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_y2_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_y2_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_yl_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_yl_e(int l, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_yl_array  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_yl_array(const int lmax, const double x, double * result_array);
+ missing: 4   gsl_sf_bessel_i0_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_i0_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_i1_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_i1_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_i2_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_i2_scaled_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_il_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_il_scaled_e(const int l, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_il_scaled_array  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_il_scaled_array(const int lmax, const double x, double * result_array);
+ missing: 4   gsl_sf_bessel_k0_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_k0_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_k1_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_k1_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_k2_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_k2_scaled_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_kl_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_kl_scaled_e(int l, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_kl_scaled_array  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_kl_scaled_array(const int lmax, const double x, double * result_array);
+ missing: 5   gsl_sf_bessel_Jnu_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Jnu_e(const double nu, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_Ynu_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Ynu_e(double nu, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_Inu_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Inu_scaled_e(double nu, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_Inu_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Inu_e(double nu, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_Knu_scaled_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Knu_scaled_e(const double nu, const double x, gsl_sf_result * result);
+//  -- missing type "gsl_sf_result_e10 *" 
+ missing: 5   gsl_sf_bessel_Knu_scaled_e10_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Knu_scaled_e10_e(const double nu, const double x, gsl_sf_result_e10 * result);
+ missing: 5   gsl_sf_bessel_Knu_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_Knu_e(const double nu, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_lnKnu_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_lnKnu_e(const double nu, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_zero_J0_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_zero_J0_e(unsigned int s, gsl_sf_result * result);
+ missing: 4   gsl_sf_bessel_zero_J1_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_zero_J1_e(unsigned int s, gsl_sf_result * result);
+ missing: 5   gsl_sf_bessel_zero_Jnu_e  -> /usr/local/include/gsl/gsl_sf_bessel.h:int gsl_sf_bessel_zero_Jnu_e(double nu, unsigned int s, gsl_sf_result * result);
+ missing: 4   gsl_sf_clausen_e  -> /usr/local/include/gsl/gsl_sf_clausen.h:int gsl_sf_clausen_e(double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_hydrogenicR_1_e  -> /usr/local/include/gsl/gsl_sf_coulomb.h:int gsl_sf_hydrogenicR_1_e(const double Z, const double r, gsl_sf_result * result);
+ missing: 5   gsl_sf_coulomb_CL_e  -> /usr/local/include/gsl/gsl_sf_coulomb.h:int gsl_sf_coulomb_CL_e(double L, double eta, gsl_sf_result * result);
+ missing: 6   gsl_sf_coulomb_CL_e  -> /usr/local/include/gsl/gsl_sf_coulomb.h:int gsl_sf_coulomb_CL_array(double Lmin, int kmax, double eta, double * cl);
+ missing: 4   gsl_sf_dawson_e  -> /usr/local/include/gsl/gsl_sf_dawson.h:int     gsl_sf_dawson_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_debye_1_e  -> /usr/local/include/gsl/gsl_sf_debye.h:int     gsl_sf_debye_1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_debye_2_e  -> /usr/local/include/gsl/gsl_sf_debye.h:int     gsl_sf_debye_2_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_debye_3_e  -> /usr/local/include/gsl/gsl_sf_debye.h:int     gsl_sf_debye_3_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_debye_4_e  -> /usr/local/include/gsl/gsl_sf_debye.h:int     gsl_sf_debye_4_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_debye_5_e  -> /usr/local/include/gsl/gsl_sf_debye.h:int     gsl_sf_debye_5_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_debye_6_e  -> /usr/local/include/gsl/gsl_sf_debye.h:int     gsl_sf_debye_6_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_dilog_e  -> /usr/local/include/gsl/gsl_sf_dilog.h:int     gsl_sf_dilog_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_multiply_e  -> /usr/local/include/gsl/gsl_sf_elementary.h:int gsl_sf_multiply_e(const double x, const double y, gsl_sf_result * result);
+ missing: 5   gsl_sf_ellint_Kcomp_e  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_Kcomp_e(double k, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_ellint_Kcomp  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_Kcomp(double k, gsl_mode_t mode);
+ missing: 5   gsl_sf_ellint_Ecomp_e  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_Ecomp_e(double k, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_ellint_Ecomp  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_Ecomp(double k, gsl_mode_t mode);
+ missing: 6   gsl_sf_ellint_Ecomp  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_Pcomp_e(double k, double n, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 5   gsl_sf_ellint_Pcomp  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_Pcomp(double k, double n, gsl_mode_t mode);
+ missing: 5   gsl_sf_ellint_Dcomp_e  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_Dcomp_e(double k, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 4   gsl_sf_ellint_Dcomp  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_Dcomp(double k, gsl_mode_t mode);
+ missing: 6   gsl_sf_ellint_Dcomp  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_F_e(double phi, double k, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 5   gsl_sf_ellint_F  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_F(double phi, double k, gsl_mode_t mode);
+ missing: 6   gsl_sf_ellint_F  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_E_e(double phi, double k, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 5   gsl_sf_ellint_E  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_E(double phi, double k, gsl_mode_t mode);
+ missing: 7   gsl_sf_ellint_E  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_P_e(double phi, double k, double n, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 6   gsl_sf_ellint_E  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_P(double phi, double k, double n, gsl_mode_t mode);
+ missing: 7   gsl_sf_ellint_E  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_D_e(double phi, double k, double n, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 6   gsl_sf_ellint_E  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_D(double phi, double k, double n, gsl_mode_t mode);
+ missing: 6   gsl_sf_ellint_E  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_RC_e(double x, double y, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 5   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_RC(double x, double y, gsl_mode_t mode);
+ missing: 7   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_RD_e(double x, double y, double z, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 6   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_RD(double x, double y, double z, gsl_mode_t mode);
+ missing: 7   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_RF_e(double x, double y, double z, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 6   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_RF(double x, double y, double z, gsl_mode_t mode);
+ missing: 8   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_ellint.h:int gsl_sf_ellint_RJ_e(double x, double y, double z, double p, gsl_mode_t mode, gsl_sf_result * result);
+ missing: 7   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_ellint.h:double gsl_sf_ellint_RJ(double x, double y, double z, double p, gsl_mode_t mode);
+ missing: 7   gsl_sf_ellint_RC  -> /usr/local/include/gsl/gsl_sf_elljac.h:int gsl_sf_elljac_e(double u, double m, double * sn, double * cn, double * dn);
+ missing: 4   gsl_sf_erfc_e  -> /usr/local/include/gsl/gsl_sf_erf.h:int gsl_sf_erfc_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_log_erfc_e  -> /usr/local/include/gsl/gsl_sf_erf.h:int gsl_sf_log_erfc_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_erf_e  -> /usr/local/include/gsl/gsl_sf_erf.h:int gsl_sf_erf_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_erf_Z_e  -> /usr/local/include/gsl/gsl_sf_erf.h:int gsl_sf_erf_Z_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_erf_Q_e  -> /usr/local/include/gsl/gsl_sf_erf.h:int gsl_sf_erf_Q_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_hazard_e  -> /usr/local/include/gsl/gsl_sf_erf.h:int gsl_sf_hazard_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_exp_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_exp_e10_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_e10_e(const double x, gsl_sf_result_e10 * result);
+ missing: 5   gsl_sf_exp_mult_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_mult_e(const double x, const double y, gsl_sf_result * result);
+ missing: 5   gsl_sf_exp_mult_e10_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_mult_e10_e(const double x, const double y, gsl_sf_result_e10 * result);
+ missing: 4   gsl_sf_expm1_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_expm1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_exprel_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exprel_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_exprel_2_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exprel_2_e(double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_exprel_n_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exprel_n_e(const int n, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_exprel_n_CF_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exprel_n_CF_e(const double n, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_exp_err_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_err_e(const double x, const double dx, gsl_sf_result * result);
+ missing: 5   gsl_sf_exp_err_e10_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_err_e10_e(const double x, const double dx, gsl_sf_result_e10 * result);
+ missing: 7   gsl_sf_exp_err_e10_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_mult_err_e(const double x, const double dx, const double y, const double dy, gsl_sf_result * result);
+ missing: 7   gsl_sf_exp_err_e10_e  -> /usr/local/include/gsl/gsl_sf_exp.h:int gsl_sf_exp_mult_err_e10_e(const double x, const double dx, const double y, const double dy, gsl_sf_result_e10 * result);
+ missing: 4   gsl_sf_expint_E1_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_E1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_expint_E2_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_E2_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_expint_En_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_En_e(const int n, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_expint_E1_scaled_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_E1_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_expint_E2_scaled_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_E2_scaled_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_expint_En_scaled_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_En_scaled_e(const int n, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_expint_Ei_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_Ei_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_expint_Ei_scaled_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_Ei_scaled_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_Shi_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_Shi_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_Chi_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_Chi_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_expint_3_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_expint_3_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_Si_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_Si_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_Ci_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_Ci_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_atanint_e  -> /usr/local/include/gsl/gsl_sf_expint.h:int     gsl_sf_atanint_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fermi_dirac_m1_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_m1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fermi_dirac_0_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_0_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fermi_dirac_1_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fermi_dirac_2_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_2_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_fermi_dirac_int_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_int_e(const int j, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fermi_dirac_mhalf_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_mhalf_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fermi_dirac_half_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_half_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fermi_dirac_3half_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_3half_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_fermi_dirac_inc_0_e  -> /usr/local/include/gsl/gsl_sf_fermi_dirac.h:int     gsl_sf_fermi_dirac_inc_0_e(const double x, const double b, gsl_sf_result * result);
+ missing: 4   gsl_sf_lngamma_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_lngamma_e(double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_lngamma_sgn_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_lngamma_sgn_e(double x, gsl_sf_result * result_lg, double *sgn);
+ missing: 4   gsl_sf_gamma_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_gamma_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_gammastar_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_gammastar_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_gammainv_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_gammainv_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_taylorcoeff_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_taylorcoeff_e(const int n, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_fact_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_fact_e(const unsigned int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_doublefact_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_doublefact_e(const unsigned int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_lnfact_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_lnfact_e(const unsigned int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_lndoublefact_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_lndoublefact_e(const unsigned int n, gsl_sf_result * result);
+ missing: 5   gsl_sf_lnchoose_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_lnchoose_e(unsigned int n, unsigned int m, gsl_sf_result * result);
+ missing: 5   gsl_sf_choose_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_choose_e(unsigned int n, unsigned int m, gsl_sf_result * result);
+ missing: 5   gsl_sf_lnpoch_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_lnpoch_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_poch_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_poch_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_pochrel_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_pochrel_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_gamma_inc_Q_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_gamma_inc_Q_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_gamma_inc_P_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_gamma_inc_P_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_gamma_inc_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_gamma_inc_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_lnbeta_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_lnbeta_e(const double a, const double b, gsl_sf_result * result);
+ missing: 5   gsl_sf_beta_e  -> /usr/local/include/gsl/gsl_sf_gamma.h:int gsl_sf_beta_e(const double a, const double b, gsl_sf_result * result);
+ missing: 5   gsl_sf_gegenpoly_1_e  -> /usr/local/include/gsl/gsl_sf_gegenbauer.h:int gsl_sf_gegenpoly_1_e(double lambda, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_gegenpoly_2_e  -> /usr/local/include/gsl/gsl_sf_gegenbauer.h:int gsl_sf_gegenpoly_2_e(double lambda, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_gegenpoly_3_e  -> /usr/local/include/gsl/gsl_sf_gegenbauer.h:int gsl_sf_gegenpoly_3_e(double lambda, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_hyperg_0F1_e  -> /usr/local/include/gsl/gsl_sf_hyperg.h:int gsl_sf_hyperg_0F1_e(double c, double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_laguerre_1_e  -> /usr/local/include/gsl/gsl_sf_laguerre.h:int gsl_sf_laguerre_1_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_laguerre_2_e  -> /usr/local/include/gsl/gsl_sf_laguerre.h:int gsl_sf_laguerre_2_e(const double a, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_laguerre_3_e  -> /usr/local/include/gsl/gsl_sf_laguerre.h:int gsl_sf_laguerre_3_e(const double a, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_lambert_W0_e  -> /usr/local/include/gsl/gsl_sf_lambert.h:int     gsl_sf_lambert_W0_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_lambert_Wm1_e  -> /usr/local/include/gsl/gsl_sf_lambert.h:int     gsl_sf_lambert_Wm1_e(double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_legendre_Pl_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int     gsl_sf_legendre_Pl_e(const int l, const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_legendre_P1_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_P1_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_legendre_P2_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_P2_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_legendre_P3_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_P3_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_legendre_Q0_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_Q0_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_legendre_Q1_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_Q1_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_legendre_Ql_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_Ql_e(const int l, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_conicalP_half_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_conicalP_half_e(const double lambda, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_conicalP_mhalf_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_conicalP_mhalf_e(const double lambda, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_conicalP_0_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_conicalP_0_e(const double lambda, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_conicalP_1_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_conicalP_1_e(const double lambda, const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_legendre_H3d_0_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_H3d_0_e(const double lambda, const double eta, gsl_sf_result * result);
+ missing: 5   gsl_sf_legendre_H3d_1_e  -> /usr/local/include/gsl/gsl_sf_legendre.h:int gsl_sf_legendre_H3d_1_e(const double lambda, const double eta, gsl_sf_result * result);
+ missing: 4   gsl_sf_log_e  -> /usr/local/include/gsl/gsl_sf_log.h:int gsl_sf_log_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_log_abs_e  -> /usr/local/include/gsl/gsl_sf_log.h:int gsl_sf_log_abs_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_log_1plusx_e  -> /usr/local/include/gsl/gsl_sf_log.h:int gsl_sf_log_1plusx_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_log_1plusx_mx_e  -> /usr/local/include/gsl/gsl_sf_log.h:int gsl_sf_log_1plusx_mx_e(const double x, gsl_sf_result * result);
+//  -- missing type "gsl_sf_result" 
+ missing: 5   gsl_sf_mathieu_a  -> /usr/local/include/gsl/gsl_sf_mathieu.h:int gsl_sf_mathieu_a(int order, double qq, gsl_sf_result *result);
+ missing: 5   gsl_sf_mathieu_b  -> /usr/local/include/gsl/gsl_sf_mathieu.h:int gsl_sf_mathieu_b(int order, double qq, gsl_sf_result *result);
+ missing: 6   gsl_sf_mathieu_b  -> /usr/local/include/gsl/gsl_sf_mathieu.h:int gsl_sf_mathieu_a_coeff(int order, double qq, double aa, double coeff[]);
+ missing: 6   gsl_sf_mathieu_b  -> /usr/local/include/gsl/gsl_sf_mathieu.h:int gsl_sf_mathieu_b_coeff(int order, double qq, double aa, double coeff[]);
+ missing: 6   gsl_sf_mathieu_b  -> /usr/local/include/gsl/gsl_sf_mathieu.h:int gsl_sf_mathieu_ce(int order, double qq, double zz, gsl_sf_result *result);
+ missing: 6   gsl_sf_mathieu_b  -> /usr/local/include/gsl/gsl_sf_mathieu.h:int gsl_sf_mathieu_se(int order, double qq, double zz, gsl_sf_result *result);
+ missing: 5   gsl_sf_pow_int_e  -> /usr/local/include/gsl/gsl_sf_pow_int.h:int     gsl_sf_pow_int_e(double x, int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_psi_int_e  -> /usr/local/include/gsl/gsl_sf_psi.h:int     gsl_sf_psi_int_e(const int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_psi_e  -> /usr/local/include/gsl/gsl_sf_psi.h:int     gsl_sf_psi_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_psi_1piy_e  -> /usr/local/include/gsl/gsl_sf_psi.h:int     gsl_sf_psi_1piy_e(const double y, gsl_sf_result * result);
+ missing: 4   gsl_sf_psi_1_int_e  -> /usr/local/include/gsl/gsl_sf_psi.h:int     gsl_sf_psi_1_int_e(const int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_psi_1_e  -> /usr/local/include/gsl/gsl_sf_psi.h:int     gsl_sf_psi_1_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_psi_n_e  -> /usr/local/include/gsl/gsl_sf_psi.h:int     gsl_sf_psi_n_e(const int n, const double x, gsl_sf_result * result);
+//  -- missing type "const gsl_sf_result_e10 *" 
+ missing: 4   gsl_sf_result_smash_e  -> /usr/local/include/gsl/gsl_sf_result.h:int gsl_sf_result_smash_e(const gsl_sf_result_e10 * re, gsl_sf_result * r);
+ missing: 4   gsl_sf_synchrotron_1_e  -> /usr/local/include/gsl/gsl_sf_synchrotron.h:int     gsl_sf_synchrotron_1_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_synchrotron_2_e  -> /usr/local/include/gsl/gsl_sf_synchrotron.h:int     gsl_sf_synchrotron_2_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_transport_2_e  -> /usr/local/include/gsl/gsl_sf_transport.h:int     gsl_sf_transport_2_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_transport_3_e  -> /usr/local/include/gsl/gsl_sf_transport.h:int     gsl_sf_transport_3_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_transport_4_e  -> /usr/local/include/gsl/gsl_sf_transport.h:int     gsl_sf_transport_4_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_transport_5_e  -> /usr/local/include/gsl/gsl_sf_transport.h:int     gsl_sf_transport_5_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_sin_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_sin_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_cos_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_cos_e(double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_hypot_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_hypot_e(const double x, const double y, gsl_sf_result * result);
+ missing: 4   gsl_sf_sinc_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_sinc_e(double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_lnsinh_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_lnsinh_e(const double x, gsl_sf_result * result);
+ missing: 4   gsl_sf_lncosh_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_lncosh_e(const double x, gsl_sf_result * result);
+ missing: 5   gsl_sf_sin_err_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_sin_err_e(const double x, const double dx, gsl_sf_result * result);
+ missing: 5   gsl_sf_cos_err_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_cos_err_e(const double x, const double dx, gsl_sf_result * result);
+ missing: 3   gsl_sf_angle_restrict_symm_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_angle_restrict_symm_e(double * theta);
+ missing: 3   gsl_sf_angle_restrict_pos_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_angle_restrict_pos_e(double * theta);
+ missing: 4   gsl_sf_angle_restrict_symm_err_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_angle_restrict_symm_err_e(const double theta, gsl_sf_result * result);
+ missing: 4   gsl_sf_angle_restrict_pos_err_e  -> /usr/local/include/gsl/gsl_sf_trig.h:int gsl_sf_angle_restrict_pos_err_e(const double theta, gsl_sf_result * result);
+ missing: 4   gsl_sf_zeta_int_e  -> /usr/local/include/gsl/gsl_sf_zeta.h:int gsl_sf_zeta_int_e(const int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_zeta_e  -> /usr/local/include/gsl/gsl_sf_zeta.h:int gsl_sf_zeta_e(const double s, gsl_sf_result * result);
+ missing: 4   gsl_sf_zetam1_e  -> /usr/local/include/gsl/gsl_sf_zeta.h:int gsl_sf_zetam1_e(const double s, gsl_sf_result * result);
+ missing: 4   gsl_sf_zetam1_int_e  -> /usr/local/include/gsl/gsl_sf_zeta.h:int gsl_sf_zetam1_int_e(const int s, gsl_sf_result * result);
+ missing: 5   gsl_sf_hzeta_e  -> /usr/local/include/gsl/gsl_sf_zeta.h:int gsl_sf_hzeta_e(const double s, const double q, gsl_sf_result * result);
+ missing: 4   gsl_sf_eta_int_e  -> /usr/local/include/gsl/gsl_sf_zeta.h:int gsl_sf_eta_int_e(int n, gsl_sf_result * result);
+ missing: 4   gsl_sf_eta_e  -> /usr/local/include/gsl/gsl_sf_zeta.h:int gsl_sf_eta_e(const double s, gsl_sf_result * result);
+ */ 
+/*****************/
+/*****************/
+double gsl_cdf_ugaussian_P__(double const & x ) { return gsl_cdf_ugaussian_P( (const double) x );}
+double gsl_cdf_ugaussian_Q__(double const & x ) { return gsl_cdf_ugaussian_Q( (const double) x );}
+double gsl_cdf_ugaussian_Pinv__(double const & x ) { return gsl_cdf_ugaussian_Pinv( (const double) x );}
+double gsl_cdf_ugaussian_Qinv__(double const & x ) { return gsl_cdf_ugaussian_Qinv( (const double) x );}
+double gsl_cdf_gaussian_P__(double const & x , double const & y ){ return gsl_cdf_gaussian_P( (const double) x , (const double) y );}
+double gsl_cdf_gaussian_Q__(double const & x , double const & y ){ return gsl_cdf_gaussian_Q( (const double) x , (const double) y );}
+double gsl_cdf_gaussian_Pinv__(double const & x , double const & y ){ return gsl_cdf_gaussian_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_gaussian_Qinv__(double const & x , double const & y ){ return gsl_cdf_gaussian_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_gamma_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_gamma_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gamma_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_gamma_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gamma_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_gamma_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gamma_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_gamma_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_cauchy_P__(double const & x , double const & y ){ return gsl_cdf_cauchy_P( (const double) x , (const double) y );}
+double gsl_cdf_cauchy_Q__(double const & x , double const & y ){ return gsl_cdf_cauchy_Q( (const double) x , (const double) y );}
+double gsl_cdf_cauchy_Pinv__(double const & x , double const & y ){ return gsl_cdf_cauchy_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_cauchy_Qinv__(double const & x , double const & y ){ return gsl_cdf_cauchy_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_laplace_P__(double const & x , double const & y ){ return gsl_cdf_laplace_P( (const double) x , (const double) y );}
+double gsl_cdf_laplace_Q__(double const & x , double const & y ){ return gsl_cdf_laplace_Q( (const double) x , (const double) y );}
+double gsl_cdf_laplace_Pinv__(double const & x , double const & y ){ return gsl_cdf_laplace_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_laplace_Qinv__(double const & x , double const & y ){ return gsl_cdf_laplace_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_rayleigh_P__(double const & x , double const & y ){ return gsl_cdf_rayleigh_P( (const double) x , (const double) y );}
+double gsl_cdf_rayleigh_Q__(double const & x , double const & y ){ return gsl_cdf_rayleigh_Q( (const double) x , (const double) y );}
+double gsl_cdf_rayleigh_Pinv__(double const & x , double const & y ){ return gsl_cdf_rayleigh_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_rayleigh_Qinv__(double const & x , double const & y ){ return gsl_cdf_rayleigh_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_chisq_P__(double const & x , double const & y ){ return gsl_cdf_chisq_P( (const double) x , (const double) y );}
+double gsl_cdf_chisq_Q__(double const & x , double const & y ){ return gsl_cdf_chisq_Q( (const double) x , (const double) y );}
+double gsl_cdf_chisq_Pinv__(double const & x , double const & y ){ return gsl_cdf_chisq_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_chisq_Qinv__(double const & x , double const & y ){ return gsl_cdf_chisq_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_exponential_P__(double const & x , double const & y ){ return gsl_cdf_exponential_P( (const double) x , (const double) y );}
+double gsl_cdf_exponential_Q__(double const & x , double const & y ){ return gsl_cdf_exponential_Q( (const double) x , (const double) y );}
+double gsl_cdf_exponential_Pinv__(double const & x , double const & y ){ return gsl_cdf_exponential_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_exponential_Qinv__(double const & x , double const & y ){ return gsl_cdf_exponential_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_exppow_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_exppow_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_exppow_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_exppow_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_tdist_P__(double const & x , double const & y ){ return gsl_cdf_tdist_P( (const double) x , (const double) y );}
+double gsl_cdf_tdist_Q__(double const & x , double const & y ){ return gsl_cdf_tdist_Q( (const double) x , (const double) y );}
+double gsl_cdf_tdist_Pinv__(double const & x , double const & y ){ return gsl_cdf_tdist_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_tdist_Qinv__(double const & x , double const & y ){ return gsl_cdf_tdist_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_fdist_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_fdist_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_fdist_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_fdist_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_fdist_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_fdist_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_fdist_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_fdist_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_beta_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_beta_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_beta_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_beta_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_beta_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_beta_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_beta_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_beta_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_flat_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_flat_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_flat_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_flat_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_flat_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_flat_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_flat_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_flat_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_lognormal_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_lognormal_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_lognormal_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_lognormal_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_lognormal_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_lognormal_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_lognormal_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_lognormal_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel1_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel1_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel1_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel1_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel1_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel1_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel1_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel1_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel2_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel2_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel2_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel2_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel2_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel2_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_gumbel2_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_gumbel2_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_weibull_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_weibull_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_weibull_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_weibull_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_weibull_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_weibull_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_weibull_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_weibull_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_pareto_P__(double const & x , double const & y , double const & z ){ return gsl_cdf_pareto_P( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_pareto_Q__(double const & x , double const & y , double const & z ){ return gsl_cdf_pareto_Q( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_pareto_Pinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_pareto_Pinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_pareto_Qinv__(double const & x , double const & y , double const & z ){ return gsl_cdf_pareto_Qinv( (const double) x , (const double) y , (const double) z );}
+double gsl_cdf_logistic_P__(double const & x , double const & y ){ return gsl_cdf_logistic_P( (const double) x , (const double) y );}
+double gsl_cdf_logistic_Q__(double const & x , double const & y ){ return gsl_cdf_logistic_Q( (const double) x , (const double) y );}
+double gsl_cdf_logistic_Pinv__(double const & x , double const & y ){ return gsl_cdf_logistic_Pinv( (const double) x , (const double) y );}
+double gsl_cdf_logistic_Qinv__(double const & x , double const & y ){ return gsl_cdf_logistic_Qinv( (const double) x , (const double) y );}
+double gsl_cdf_binomial_P__(long const & x , double const & y , long const & z ){ return gsl_cdf_binomial_P( (const unsigned int) x , (const double) y , (const unsigned int) z );}
+double gsl_cdf_binomial_Q__(long const & x , double const & y , long const & z ){ return gsl_cdf_binomial_Q( (const unsigned int) x , (const double) y , (const unsigned int) z );}
+double gsl_cdf_poisson_P__(long const & x , double const & y ){ return gsl_cdf_poisson_P( (const unsigned int) x , (const double) y );}
+double gsl_cdf_poisson_Q__(long const & x , double const & y ){ return gsl_cdf_poisson_Q( (const unsigned int) x , (const double) y );}
+double gsl_cdf_geometric_P__(long const & x , double const & y ){ return gsl_cdf_geometric_P( (const unsigned int) x , (const double) y );}
+double gsl_cdf_geometric_Q__(long const & x , double const & y ){ return gsl_cdf_geometric_Q( (const unsigned int) x , (const double) y );}
+double gsl_cdf_negative_binomial_P__(long const & x , double const & y , double const & z ){ return gsl_cdf_negative_binomial_P( (const unsigned int) x , (const double) y , (const double) z );}
+double gsl_cdf_negative_binomial_Q__(long const & x , double const & y , double const & z ){ return gsl_cdf_negative_binomial_Q( (const unsigned int) x , (const double) y , (const double) z );}
+double gsl_cdf_pascal_P__(long const & x , double const & y , long const & z ){ return gsl_cdf_pascal_P( (const unsigned int) x , (const double) y , (const unsigned int) z );}
+double gsl_cdf_pascal_Q__(long const & x , double const & y , long const & z ){ return gsl_cdf_pascal_Q( (const unsigned int) x , (const double) y , (const unsigned int) z );}
+double gsl_ran_bernoulli_pdf__(long const & x , double const & y ){ return gsl_ran_bernoulli_pdf( (const unsigned int) x , (double) y );}
+double gsl_ran_beta__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_beta( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_beta_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_beta_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_binomial_pdf__(long const & x , double const & y , long const & z ){ return gsl_ran_binomial_pdf( (const unsigned int) x , (const double) y , (const unsigned int) z );}
+double gsl_ran_exponential__(gsl_rng ** const & x , double const & y ){ return gsl_ran_exponential( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_exponential_pdf__(double const & x , double const & y ){ return gsl_ran_exponential_pdf( (const double) x , (const double) y );}
+double gsl_ran_exppow__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_exppow( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_exppow_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_exppow_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_cauchy__(gsl_rng ** const & x , double const & y ){ return gsl_ran_cauchy( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_cauchy_pdf__(double const & x , double const & y ){ return gsl_ran_cauchy_pdf( (const double) x , (const double) y );}
+double gsl_ran_chisq__(gsl_rng ** const & x , double const & y ){ return gsl_ran_chisq( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_chisq_pdf__(double const & x , double const & y ){ return gsl_ran_chisq_pdf( (const double) x , (const double) y );}
+double gsl_ran_erlang__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_erlang( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_erlang_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_erlang_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_fdist__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_fdist( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_fdist_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_fdist_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_flat__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_flat( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_flat_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_flat_pdf( (double) x , (const double) y , (const double) z );}
+double gsl_ran_gamma__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_gamma( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_gamma_int__(gsl_rng ** const & x , long const & y ){ return gsl_ran_gamma_int( (const gsl_rng *)* x , (const unsigned int) y );}
+double gsl_ran_gamma_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_gamma_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_gamma_mt__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_gamma_mt( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_gamma_knuth__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_gamma_knuth( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_gaussian__(gsl_rng ** const & x , double const & y ){ return gsl_ran_gaussian( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_gaussian_ratio_method__(gsl_rng ** const & x , double const & y ){ return gsl_ran_gaussian_ratio_method( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_gaussian_ziggurat__(gsl_rng ** const & x , double const & y ){ return gsl_ran_gaussian_ziggurat( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_gaussian_pdf__(double const & x , double const & y ){ return gsl_ran_gaussian_pdf( (const double) x , (const double) y );}
+double gsl_ran_ugaussian__(gsl_rng ** const & x ) { return gsl_ran_ugaussian( (const gsl_rng *)* x );}
+double gsl_ran_ugaussian_ratio_method__(gsl_rng ** const & x ) { return gsl_ran_ugaussian_ratio_method( (const gsl_rng *)* x );}
+double gsl_ran_ugaussian_pdf__(double const & x ) { return gsl_ran_ugaussian_pdf( (const double) x );}
+double gsl_ran_gaussian_tail__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_gaussian_tail( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_gaussian_tail_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_gaussian_tail_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_ugaussian_tail__(gsl_rng ** const & x , double const & y ){ return gsl_ran_ugaussian_tail( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_ugaussian_tail_pdf__(double const & x , double const & y ){ return gsl_ran_ugaussian_tail_pdf( (const double) x , (const double) y );}
+double gsl_ran_landau__(gsl_rng ** const & x ) { return gsl_ran_landau( (const gsl_rng *)* x );}
+double gsl_ran_landau_pdf__(double const & x ) { return gsl_ran_landau_pdf( (const double) x );}
+double gsl_ran_geometric_pdf__(long const & x , double const & y ){ return gsl_ran_geometric_pdf( (const unsigned int) x , (const double) y );}
+double gsl_ran_gumbel1__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_gumbel1( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_gumbel1_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_gumbel1_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_gumbel2__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_gumbel2( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_gumbel2_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_gumbel2_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_logistic__(gsl_rng ** const & x , double const & y ){ return gsl_ran_logistic( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_logistic_pdf__(double const & x , double const & y ){ return gsl_ran_logistic_pdf( (const double) x , (const double) y );}
+double gsl_ran_lognormal__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_lognormal( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_lognormal_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_lognormal_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_logarithmic_pdf__(long const & x , double const & y ){ return gsl_ran_logarithmic_pdf( (const unsigned int) x , (const double) y );}
+double gsl_ran_negative_binomial_pdf__(long const & x , double const & y , double const & z ){ return gsl_ran_negative_binomial_pdf( (const unsigned int) x , (const double) y , (double) z );}
+double gsl_ran_pascal_pdf__(long const & x , double const & y , long const & z ){ return gsl_ran_pascal_pdf( (const unsigned int) x , (const double) y , (unsigned int) z );}
+double gsl_ran_pareto__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_pareto( (const gsl_rng *)* x , (double) y , (const double) z );}
+double gsl_ran_pareto_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_pareto_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_poisson_pdf__(long const & x , double const & y ){ return gsl_ran_poisson_pdf( (const unsigned int) x , (const double) y );}
+double gsl_ran_rayleigh__(gsl_rng ** const & x , double const & y ){ return gsl_ran_rayleigh( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_rayleigh_pdf__(double const & x , double const & y ){ return gsl_ran_rayleigh_pdf( (const double) x , (const double) y );}
+double gsl_ran_rayleigh_tail__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_rayleigh_tail( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_rayleigh_tail_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_rayleigh_tail_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_ran_tdist__(gsl_rng ** const & x , double const & y ){ return gsl_ran_tdist( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_tdist_pdf__(double const & x , double const & y ){ return gsl_ran_tdist_pdf( (const double) x , (const double) y );}
+double gsl_ran_laplace__(gsl_rng ** const & x , double const & y ){ return gsl_ran_laplace( (const gsl_rng *)* x , (const double) y );}
+double gsl_ran_laplace_pdf__(double const & x , double const & y ){ return gsl_ran_laplace_pdf( (const double) x , (const double) y );}
+double gsl_ran_levy__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_levy( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_weibull__(gsl_rng ** const & x , double const & y , double const & z ){ return gsl_ran_weibull( (const gsl_rng *)* x , (const double) y , (const double) z );}
+double gsl_ran_weibull_pdf__(double const & x , double const & y , double const & z ){ return gsl_ran_weibull_pdf( (const double) x , (const double) y , (const double) z );}
+double gsl_sf_airy_zero_Ai__(long const & x ) { return gsl_sf_airy_zero_Ai( (unsigned int) x );}
+double gsl_sf_airy_zero_Bi__(long const & x ) { return gsl_sf_airy_zero_Bi( (unsigned int) x );}
+double gsl_sf_airy_zero_Ai_deriv__(long const & x ) { return gsl_sf_airy_zero_Ai_deriv( (unsigned int) x );}
+double gsl_sf_airy_zero_Bi_deriv__(long const & x ) { return gsl_sf_airy_zero_Bi_deriv( (unsigned int) x );}
+double gsl_sf_bessel_J0__(double const & x ) { return gsl_sf_bessel_J0( (const double) x );}
+double gsl_sf_bessel_J1__(double const & x ) { return gsl_sf_bessel_J1( (const double) x );}
+double gsl_sf_bessel_Jn__(long const & x , double const & y ){ return gsl_sf_bessel_Jn( (const int) x , (const double) y );}
+double gsl_sf_bessel_Y0__(double const & x ) { return gsl_sf_bessel_Y0( (const double) x );}
+double gsl_sf_bessel_Y1__(double const & x ) { return gsl_sf_bessel_Y1( (const double) x );}
+double gsl_sf_bessel_Yn__(long const & x , double const & y ){ return gsl_sf_bessel_Yn( (const int) x , (const double) y );}
+double gsl_sf_bessel_I0__(double const & x ) { return gsl_sf_bessel_I0( (const double) x );}
+double gsl_sf_bessel_I1__(double const & x ) { return gsl_sf_bessel_I1( (const double) x );}
+double gsl_sf_bessel_In__(long const & x , double const & y ){ return gsl_sf_bessel_In( (const int) x , (const double) y );}
+double gsl_sf_bessel_I0_scaled__(double const & x ) { return gsl_sf_bessel_I0_scaled( (const double) x );}
+double gsl_sf_bessel_I1_scaled__(double const & x ) { return gsl_sf_bessel_I1_scaled( (const double) x );}
+double gsl_sf_bessel_In_scaled__(long const & x , double const & y ){ return gsl_sf_bessel_In_scaled( (const int) x , (const double) y );}
+double gsl_sf_bessel_K0__(double const & x ) { return gsl_sf_bessel_K0( (const double) x );}
+double gsl_sf_bessel_K1__(double const & x ) { return gsl_sf_bessel_K1( (const double) x );}
+double gsl_sf_bessel_Kn__(long const & x , double const & y ){ return gsl_sf_bessel_Kn( (const int) x , (const double) y );}
+double gsl_sf_bessel_K0_scaled__(double const & x ) { return gsl_sf_bessel_K0_scaled( (const double) x );}
+double gsl_sf_bessel_K1_scaled__(double const & x ) { return gsl_sf_bessel_K1_scaled( (const double) x );}
+double gsl_sf_bessel_Kn_scaled__(long const & x , double const & y ){ return gsl_sf_bessel_Kn_scaled( (const int) x , (const double) y );}
+double gsl_sf_bessel_j0__(double const & x ) { return gsl_sf_bessel_j0( (const double) x );}
+double gsl_sf_bessel_j1__(double const & x ) { return gsl_sf_bessel_j1( (const double) x );}
+double gsl_sf_bessel_j2__(double const & x ) { return gsl_sf_bessel_j2( (const double) x );}
+double gsl_sf_bessel_jl__(long const & x , double const & y ){ return gsl_sf_bessel_jl( (const int) x , (const double) y );}
+double gsl_sf_bessel_y0__(double const & x ) { return gsl_sf_bessel_y0( (const double) x );}
+double gsl_sf_bessel_y1__(double const & x ) { return gsl_sf_bessel_y1( (const double) x );}
+double gsl_sf_bessel_y2__(double const & x ) { return gsl_sf_bessel_y2( (const double) x );}
+double gsl_sf_bessel_yl__(long const & x , double const & y ){ return gsl_sf_bessel_yl( (const int) x , (const double) y );}
+double gsl_sf_bessel_i0_scaled__(double const & x ) { return gsl_sf_bessel_i0_scaled( (const double) x );}
+double gsl_sf_bessel_i1_scaled__(double const & x ) { return gsl_sf_bessel_i1_scaled( (const double) x );}
+double gsl_sf_bessel_i2_scaled__(double const & x ) { return gsl_sf_bessel_i2_scaled( (const double) x );}
+double gsl_sf_bessel_il_scaled__(long const & x , double const & y ){ return gsl_sf_bessel_il_scaled( (const int) x , (const double) y );}
+double gsl_sf_bessel_k0_scaled__(double const & x ) { return gsl_sf_bessel_k0_scaled( (const double) x );}
+double gsl_sf_bessel_k1_scaled__(double const & x ) { return gsl_sf_bessel_k1_scaled( (const double) x );}
+double gsl_sf_bessel_k2_scaled__(double const & x ) { return gsl_sf_bessel_k2_scaled( (const double) x );}
+double gsl_sf_bessel_kl_scaled__(long const & x , double const & y ){ return gsl_sf_bessel_kl_scaled( (const int) x , (const double) y );}
+double gsl_sf_bessel_Jnu__(double const & x , double const & y ){ return gsl_sf_bessel_Jnu( (const double) x , (const double) y );}
+double gsl_sf_bessel_Ynu__(double const & x , double const & y ){ return gsl_sf_bessel_Ynu( (const double) x , (const double) y );}
+double gsl_sf_bessel_Inu_scaled__(double const & x , double const & y ){ return gsl_sf_bessel_Inu_scaled( (double) x , (double) y );}
+double gsl_sf_bessel_Inu__(double const & x , double const & y ){ return gsl_sf_bessel_Inu( (double) x , (double) y );}
+double gsl_sf_bessel_Knu_scaled__(double const & x , double const & y ){ return gsl_sf_bessel_Knu_scaled( (const double) x , (const double) y );}
+double gsl_sf_bessel_Knu__(double const & x , double const & y ){ return gsl_sf_bessel_Knu( (const double) x , (const double) y );}
+double gsl_sf_bessel_lnKnu__(double const & x , double const & y ){ return gsl_sf_bessel_lnKnu( (const double) x , (const double) y );}
+double gsl_sf_bessel_zero_J0__(long const & x ) { return gsl_sf_bessel_zero_J0( (unsigned int) x );}
+double gsl_sf_bessel_zero_J1__(long const & x ) { return gsl_sf_bessel_zero_J1( (unsigned int) x );}
+double gsl_sf_bessel_zero_Jnu__(double const & x , long const & y ){ return gsl_sf_bessel_zero_Jnu( (double) x , (unsigned int) y );}
+double gsl_sf_clausen__(double const & x ) { return gsl_sf_clausen( (const double) x );}
+double gsl_sf_hydrogenicR_1__(double const & x , double const & y ){ return gsl_sf_hydrogenicR_1( (const double) x , (const double) y );}
+double gsl_sf_dawson__(double const & x ) { return gsl_sf_dawson( (double) x );}
+double gsl_sf_debye_1__(double const & x ) { return gsl_sf_debye_1( (const double) x );}
+double gsl_sf_debye_2__(double const & x ) { return gsl_sf_debye_2( (const double) x );}
+double gsl_sf_debye_3__(double const & x ) { return gsl_sf_debye_3( (const double) x );}
+double gsl_sf_debye_4__(double const & x ) { return gsl_sf_debye_4( (const double) x );}
+double gsl_sf_debye_5__(double const & x ) { return gsl_sf_debye_5( (const double) x );}
+double gsl_sf_debye_6__(double const & x ) { return gsl_sf_debye_6( (const double) x );}
+double gsl_sf_dilog__(double const & x ) { return gsl_sf_dilog( (const double) x );}
+double gsl_sf_multiply__(double const & x , double const & y ){ return gsl_sf_multiply( (const double) x , (const double) y );}
+double gsl_sf_erfc__(double const & x ) { return gsl_sf_erfc( (double) x );}
+double gsl_sf_log_erfc__(double const & x ) { return gsl_sf_log_erfc( (double) x );}
+double gsl_sf_erf__(double const & x ) { return gsl_sf_erf( (double) x );}
+double gsl_sf_erf_Z__(double const & x ) { return gsl_sf_erf_Z( (double) x );}
+double gsl_sf_erf_Q__(double const & x ) { return gsl_sf_erf_Q( (double) x );}
+double gsl_sf_hazard__(double const & x ) { return gsl_sf_hazard( (double) x );}
+double gsl_sf_exp__(double const & x ) { return gsl_sf_exp( (const double) x );}
+double gsl_sf_exp_mult__(double const & x , double const & y ){ return gsl_sf_exp_mult( (const double) x , (const double) y );}
+double gsl_sf_expm1__(double const & x ) { return gsl_sf_expm1( (const double) x );}
+double gsl_sf_exprel__(double const & x ) { return gsl_sf_exprel( (const double) x );}
+double gsl_sf_exprel_2__(double const & x ) { return gsl_sf_exprel_2( (const double) x );}
+double gsl_sf_exprel_n__(long const & x , double const & y ){ return gsl_sf_exprel_n( (const int) x , (const double) y );}
+double gsl_sf_expint_E1__(double const & x ) { return gsl_sf_expint_E1( (const double) x );}
+double gsl_sf_expint_E2__(double const & x ) { return gsl_sf_expint_E2( (const double) x );}
+double gsl_sf_expint_En__(long const & x , double const & y ){ return gsl_sf_expint_En( (const int) x , (const double) y );}
+double gsl_sf_expint_E1_scaled__(double const & x ) { return gsl_sf_expint_E1_scaled( (const double) x );}
+double gsl_sf_expint_E2_scaled__(double const & x ) { return gsl_sf_expint_E2_scaled( (const double) x );}
+double gsl_sf_expint_En_scaled__(long const & x , double const & y ){ return gsl_sf_expint_En_scaled( (const int) x , (const double) y );}
+double gsl_sf_expint_Ei__(double const & x ) { return gsl_sf_expint_Ei( (const double) x );}
+double gsl_sf_expint_Ei_scaled__(double const & x ) { return gsl_sf_expint_Ei_scaled( (const double) x );}
+double gsl_sf_Shi__(double const & x ) { return gsl_sf_Shi( (const double) x );}
+double gsl_sf_Chi__(double const & x ) { return gsl_sf_Chi( (const double) x );}
+double gsl_sf_expint_3__(double const & x ) { return gsl_sf_expint_3( (double) x );}
+double gsl_sf_Si__(double const & x ) { return gsl_sf_Si( (const double) x );}
+double gsl_sf_Ci__(double const & x ) { return gsl_sf_Ci( (const double) x );}
+double gsl_sf_atanint__(double const & x ) { return gsl_sf_atanint( (const double) x );}
+double gsl_sf_fermi_dirac_m1__(double const & x ) { return gsl_sf_fermi_dirac_m1( (const double) x );}
+double gsl_sf_fermi_dirac_0__(double const & x ) { return gsl_sf_fermi_dirac_0( (const double) x );}
+double gsl_sf_fermi_dirac_1__(double const & x ) { return gsl_sf_fermi_dirac_1( (const double) x );}
+double gsl_sf_fermi_dirac_2__(double const & x ) { return gsl_sf_fermi_dirac_2( (const double) x );}
+double gsl_sf_fermi_dirac_int__(long const & x , double const & y ){ return gsl_sf_fermi_dirac_int( (const int) x , (const double) y );}
+double gsl_sf_fermi_dirac_mhalf__(double const & x ) { return gsl_sf_fermi_dirac_mhalf( (const double) x );}
+double gsl_sf_fermi_dirac_half__(double const & x ) { return gsl_sf_fermi_dirac_half( (const double) x );}
+double gsl_sf_fermi_dirac_3half__(double const & x ) { return gsl_sf_fermi_dirac_3half( (const double) x );}
+double gsl_sf_fermi_dirac_inc_0__(double const & x , double const & y ){ return gsl_sf_fermi_dirac_inc_0( (const double) x , (const double) y );}
+double gsl_sf_lngamma__(double const & x ) { return gsl_sf_lngamma( (const double) x );}
+double gsl_sf_gamma__(double const & x ) { return gsl_sf_gamma( (const double) x );}
+double gsl_sf_gammastar__(double const & x ) { return gsl_sf_gammastar( (const double) x );}
+double gsl_sf_gammainv__(double const & x ) { return gsl_sf_gammainv( (const double) x );}
+double gsl_sf_taylorcoeff__(long const & x , double const & y ){ return gsl_sf_taylorcoeff( (const int) x , (const double) y );}
+double gsl_sf_fact__(long const & x ) { return gsl_sf_fact( (const unsigned int) x );}
+double gsl_sf_doublefact__(long const & x ) { return gsl_sf_doublefact( (const unsigned int) x );}
+double gsl_sf_lnfact__(long const & x ) { return gsl_sf_lnfact( (const unsigned int) x );}
+double gsl_sf_lndoublefact__(long const & x ) { return gsl_sf_lndoublefact( (const unsigned int) x );}
+double gsl_sf_lnchoose__(long const & x , long const & y ){ return gsl_sf_lnchoose( (unsigned int) x , (unsigned int) y );}
+double gsl_sf_choose__(long const & x , long const & y ){ return gsl_sf_choose( (unsigned int) x , (unsigned int) y );}
+double gsl_sf_lnpoch__(double const & x , double const & y ){ return gsl_sf_lnpoch( (const double) x , (const double) y );}
+double gsl_sf_poch__(double const & x , double const & y ){ return gsl_sf_poch( (const double) x , (const double) y );}
+double gsl_sf_pochrel__(double const & x , double const & y ){ return gsl_sf_pochrel( (const double) x , (const double) y );}
+double gsl_sf_gamma_inc_Q__(double const & x , double const & y ){ return gsl_sf_gamma_inc_Q( (const double) x , (const double) y );}
+double gsl_sf_gamma_inc_P__(double const & x , double const & y ){ return gsl_sf_gamma_inc_P( (const double) x , (const double) y );}
+double gsl_sf_gamma_inc__(double const & x , double const & y ){ return gsl_sf_gamma_inc( (const double) x , (const double) y );}
+double gsl_sf_lnbeta__(double const & x , double const & y ){ return gsl_sf_lnbeta( (const double) x , (const double) y );}
+double gsl_sf_beta__(double const & x , double const & y ){ return gsl_sf_beta( (const double) x , (const double) y );}
+double gsl_sf_beta_inc__(double const & x , double const & y , double const & z ){ return gsl_sf_beta_inc( (const double) x , (const double) y , (const double) z );}
+double gsl_sf_gegenpoly_1__(double const & x , double const & y ){ return gsl_sf_gegenpoly_1( (double) x , (double) y );}
+double gsl_sf_gegenpoly_2__(double const & x , double const & y ){ return gsl_sf_gegenpoly_2( (double) x , (double) y );}
+double gsl_sf_gegenpoly_3__(double const & x , double const & y ){ return gsl_sf_gegenpoly_3( (double) x , (double) y );}
+double gsl_sf_gegenpoly_n__(long const & x , double const & y , double const & z ){ return gsl_sf_gegenpoly_n( (int) x , (double) y , (double) z );}
+double gsl_sf_hyperg_0F1__(double const & x , double const & y ){ return gsl_sf_hyperg_0F1( (const double) x , (const double) y );}
+double gsl_sf_hyperg_1F1_int__(long const & x , long const & y , double const & z ){ return gsl_sf_hyperg_1F1_int( (const int) x , (const int) y , (double) z );}
+double gsl_sf_hyperg_1F1__(double const & x , double const & y , double const & z ){ return gsl_sf_hyperg_1F1( (double) x , (double) y , (double) z );}
+double gsl_sf_hyperg_U_int__(long const & x , long const & y , double const & z ){ return gsl_sf_hyperg_U_int( (const int) x , (const int) y , (const double) z );}
+double gsl_sf_hyperg_U__(double const & x , double const & y , double const & z ){ return gsl_sf_hyperg_U( (const double) x , (const double) y , (const double) z );}
+double gsl_sf_hyperg_2F0__(double const & x , double const & y , double const & z ){ return gsl_sf_hyperg_2F0( (const double) x , (const double) y , (const double) z );}
+double gsl_sf_laguerre_1__(double const & x , double const & y ){ return gsl_sf_laguerre_1( (double) x , (double) y );}
+double gsl_sf_laguerre_2__(double const & x , double const & y ){ return gsl_sf_laguerre_2( (double) x , (double) y );}
+double gsl_sf_laguerre_3__(double const & x , double const & y ){ return gsl_sf_laguerre_3( (double) x , (double) y );}
+double gsl_sf_laguerre_n__(long const & x , double const & y , double const & z ){ return gsl_sf_laguerre_n( (int) x , (double) y , (double) z );}
+double gsl_sf_lambert_W0__(double const & x ) { return gsl_sf_lambert_W0( (double) x );}
+double gsl_sf_lambert_Wm1__(double const & x ) { return gsl_sf_lambert_Wm1( (double) x );}
+double gsl_sf_legendre_Pl__(long const & x , double const & y ){ return gsl_sf_legendre_Pl( (const int) x , (const double) y );}
+double gsl_sf_legendre_P1__(double const & x ) { return gsl_sf_legendre_P1( (const double) x );}
+double gsl_sf_legendre_P2__(double const & x ) { return gsl_sf_legendre_P2( (const double) x );}
+double gsl_sf_legendre_P3__(double const & x ) { return gsl_sf_legendre_P3( (const double) x );}
+double gsl_sf_legendre_Q0__(double const & x ) { return gsl_sf_legendre_Q0( (const double) x );}
+double gsl_sf_legendre_Q1__(double const & x ) { return gsl_sf_legendre_Q1( (const double) x );}
+double gsl_sf_legendre_Ql__(long const & x , double const & y ){ return gsl_sf_legendre_Ql( (const int) x , (const double) y );}
+double gsl_sf_legendre_Plm__(long const & x , long const & y , double const & z ){ return gsl_sf_legendre_Plm( (const int) x , (const int) y , (const double) z );}
+double gsl_sf_legendre_sphPlm__(long const & x , long const & y , double const & z ){ return gsl_sf_legendre_sphPlm( (const int) x , (const int) y , (const double) z );}
+long gsl_sf_legendre_array_size__(long const & x , long const & y ){ return gsl_sf_legendre_array_size( (const int) x , (const int) y );}
+double gsl_sf_conicalP_half__(double const & x , double const & y ){ return gsl_sf_conicalP_half( (const double) x , (const double) y );}
+double gsl_sf_conicalP_mhalf__(double const & x , double const & y ){ return gsl_sf_conicalP_mhalf( (const double) x , (const double) y );}
+double gsl_sf_conicalP_0__(double const & x , double const & y ){ return gsl_sf_conicalP_0( (const double) x , (const double) y );}
+double gsl_sf_conicalP_1__(double const & x , double const & y ){ return gsl_sf_conicalP_1( (const double) x , (const double) y );}
+double gsl_sf_conicalP_sph_reg__(long const & x , double const & y , double const & z ){ return gsl_sf_conicalP_sph_reg( (const int) x , (const double) y , (const double) z );}
+double gsl_sf_conicalP_cyl_reg__(long const & x , double const & y , double const & z ){ return gsl_sf_conicalP_cyl_reg( (const int) x , (const double) y , (const double) z );}
+double gsl_sf_legendre_H3d_0__(double const & x , double const & y ){ return gsl_sf_legendre_H3d_0( (const double) x , (const double) y );}
+double gsl_sf_legendre_H3d_1__(double const & x , double const & y ){ return gsl_sf_legendre_H3d_1( (const double) x , (const double) y );}
+double gsl_sf_legendre_H3d__(long const & x , double const & y , double const & z ){ return gsl_sf_legendre_H3d( (const int) x , (const double) y , (const double) z );}
+double gsl_sf_log__(double const & x ) { return gsl_sf_log( (const double) x );}
+double gsl_sf_log_abs__(double const & x ) { return gsl_sf_log_abs( (const double) x );}
+double gsl_sf_log_1plusx__(double const & x ) { return gsl_sf_log_1plusx( (const double) x );}
+double gsl_sf_log_1plusx_mx__(double const & x ) { return gsl_sf_log_1plusx_mx( (const double) x );}
+double gsl_sf_pow_int__(double const & x , long const & y ){ return gsl_sf_pow_int( (const double) x , (const int) y );}
+double gsl_sf_psi_int__(long const & x ) { return gsl_sf_psi_int( (const int) x );}
+double gsl_sf_psi__(double const & x ) { return gsl_sf_psi( (const double) x );}
+double gsl_sf_psi_1piy__(double const & x ) { return gsl_sf_psi_1piy( (const double) x );}
+double gsl_sf_psi_1_int__(long const & x ) { return gsl_sf_psi_1_int( (const int) x );}
+double gsl_sf_psi_1__(double const & x ) { return gsl_sf_psi_1( (const double) x );}
+double gsl_sf_psi_n__(long const & x , double const & y ){ return gsl_sf_psi_n( (const int) x , (const double) y );}
+double gsl_sf_synchrotron_1__(double const & x ) { return gsl_sf_synchrotron_1( (const double) x );}
+double gsl_sf_synchrotron_2__(double const & x ) { return gsl_sf_synchrotron_2( (const double) x );}
+double gsl_sf_transport_2__(double const & x ) { return gsl_sf_transport_2( (const double) x );}
+double gsl_sf_transport_3__(double const & x ) { return gsl_sf_transport_3( (const double) x );}
+double gsl_sf_transport_4__(double const & x ) { return gsl_sf_transport_4( (const double) x );}
+double gsl_sf_transport_5__(double const & x ) { return gsl_sf_transport_5( (const double) x );}
+double gsl_sf_sin__(double const & x ) { return gsl_sf_sin( (const double) x );}
+double gsl_sf_cos__(double const & x ) { return gsl_sf_cos( (const double) x );}
+double gsl_sf_hypot__(double const & x , double const & y ){ return gsl_sf_hypot( (const double) x , (const double) y );}
+double gsl_sf_sinc__(double const & x ) { return gsl_sf_sinc( (const double) x );}
+double gsl_sf_lnsinh__(double const & x ) { return gsl_sf_lnsinh( (const double) x );}
+double gsl_sf_lncosh__(double const & x ) { return gsl_sf_lncosh( (const double) x );}
+double gsl_sf_angle_restrict_symm__(double const & x ) { return gsl_sf_angle_restrict_symm( (const double) x );}
+double gsl_sf_angle_restrict_pos__(double const & x ) { return gsl_sf_angle_restrict_pos( (const double) x );}
+double gsl_sf_zeta_int__(long const & x ) { return gsl_sf_zeta_int( (const int) x );}
+double gsl_sf_zeta__(double const & x ) { return gsl_sf_zeta( (const double) x );}
+double gsl_sf_zetam1__(double const & x ) { return gsl_sf_zetam1( (const double) x );}
+double gsl_sf_zetam1_int__(long const & x ) { return gsl_sf_zetam1_int( (const int) x );}
+double gsl_sf_hzeta__(double const & x , double const & y ){ return gsl_sf_hzeta( (const double) x , (const double) y );}
+double gsl_sf_eta_int__(long const & x ) { return gsl_sf_eta_int( (const int) x );}
+double gsl_sf_eta__(double const & x ) { return gsl_sf_eta( (const double) x );}
+
+/*****************/
+/*****************/
+ void init_gsl_sf() { 
+
+
+   Global.Add("gslcdfugaussianP","(",new OneOperator1_<double,double>( gsl_cdf_ugaussian_P__)); 
+   Global.Add("gslcdfugaussianQ","(",new OneOperator1_<double,double>( gsl_cdf_ugaussian_Q__)); 
+   Global.Add("gslcdfugaussianPinv","(",new OneOperator1_<double,double>( gsl_cdf_ugaussian_Pinv__)); 
+   Global.Add("gslcdfugaussianQinv","(",new OneOperator1_<double,double>( gsl_cdf_ugaussian_Qinv__)); 
+   Global.Add("gslcdfgaussianP","(",new OneOperator2_<double,double,double>( gsl_cdf_gaussian_P__)); 
+   Global.Add("gslcdfgaussianQ","(",new OneOperator2_<double,double,double>( gsl_cdf_gaussian_Q__)); 
+   Global.Add("gslcdfgaussianPinv","(",new OneOperator2_<double,double,double>( gsl_cdf_gaussian_Pinv__)); 
+   Global.Add("gslcdfgaussianQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_gaussian_Qinv__)); 
+   Global.Add("gslcdfgammaP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gamma_P__)); 
+   Global.Add("gslcdfgammaQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gamma_Q__)); 
+   Global.Add("gslcdfgammaPinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gamma_Pinv__)); 
+   Global.Add("gslcdfgammaQinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gamma_Qinv__)); 
+   Global.Add("gslcdfcauchyP","(",new OneOperator2_<double,double,double>( gsl_cdf_cauchy_P__)); 
+   Global.Add("gslcdfcauchyQ","(",new OneOperator2_<double,double,double>( gsl_cdf_cauchy_Q__)); 
+   Global.Add("gslcdfcauchyPinv","(",new OneOperator2_<double,double,double>( gsl_cdf_cauchy_Pinv__)); 
+   Global.Add("gslcdfcauchyQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_cauchy_Qinv__)); 
+   Global.Add("gslcdflaplaceP","(",new OneOperator2_<double,double,double>( gsl_cdf_laplace_P__)); 
+   Global.Add("gslcdflaplaceQ","(",new OneOperator2_<double,double,double>( gsl_cdf_laplace_Q__)); 
+   Global.Add("gslcdflaplacePinv","(",new OneOperator2_<double,double,double>( gsl_cdf_laplace_Pinv__)); 
+   Global.Add("gslcdflaplaceQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_laplace_Qinv__)); 
+   Global.Add("gslcdfrayleighP","(",new OneOperator2_<double,double,double>( gsl_cdf_rayleigh_P__)); 
+   Global.Add("gslcdfrayleighQ","(",new OneOperator2_<double,double,double>( gsl_cdf_rayleigh_Q__)); 
+   Global.Add("gslcdfrayleighPinv","(",new OneOperator2_<double,double,double>( gsl_cdf_rayleigh_Pinv__)); 
+   Global.Add("gslcdfrayleighQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_rayleigh_Qinv__)); 
+   Global.Add("gslcdfchisqP","(",new OneOperator2_<double,double,double>( gsl_cdf_chisq_P__)); 
+   Global.Add("gslcdfchisqQ","(",new OneOperator2_<double,double,double>( gsl_cdf_chisq_Q__)); 
+   Global.Add("gslcdfchisqPinv","(",new OneOperator2_<double,double,double>( gsl_cdf_chisq_Pinv__)); 
+   Global.Add("gslcdfchisqQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_chisq_Qinv__)); 
+   Global.Add("gslcdfexponentialP","(",new OneOperator2_<double,double,double>( gsl_cdf_exponential_P__)); 
+   Global.Add("gslcdfexponentialQ","(",new OneOperator2_<double,double,double>( gsl_cdf_exponential_Q__)); 
+   Global.Add("gslcdfexponentialPinv","(",new OneOperator2_<double,double,double>( gsl_cdf_exponential_Pinv__)); 
+   Global.Add("gslcdfexponentialQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_exponential_Qinv__)); 
+   Global.Add("gslcdfexppowP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_exppow_P__)); 
+   Global.Add("gslcdfexppowQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_exppow_Q__)); 
+   Global.Add("gslcdftdistP","(",new OneOperator2_<double,double,double>( gsl_cdf_tdist_P__)); 
+   Global.Add("gslcdftdistQ","(",new OneOperator2_<double,double,double>( gsl_cdf_tdist_Q__)); 
+   Global.Add("gslcdftdistPinv","(",new OneOperator2_<double,double,double>( gsl_cdf_tdist_Pinv__)); 
+   Global.Add("gslcdftdistQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_tdist_Qinv__)); 
+   Global.Add("gslcdffdistP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_fdist_P__)); 
+   Global.Add("gslcdffdistQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_fdist_Q__)); 
+   Global.Add("gslcdffdistPinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_fdist_Pinv__)); 
+   Global.Add("gslcdffdistQinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_fdist_Qinv__)); 
+   Global.Add("gslcdfbetaP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_beta_P__)); 
+   Global.Add("gslcdfbetaQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_beta_Q__)); 
+   Global.Add("gslcdfbetaPinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_beta_Pinv__)); 
+   Global.Add("gslcdfbetaQinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_beta_Qinv__)); 
+   Global.Add("gslcdfflatP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_flat_P__)); 
+   Global.Add("gslcdfflatQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_flat_Q__)); 
+   Global.Add("gslcdfflatPinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_flat_Pinv__)); 
+   Global.Add("gslcdfflatQinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_flat_Qinv__)); 
+   Global.Add("gslcdflognormalP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_lognormal_P__)); 
+   Global.Add("gslcdflognormalQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_lognormal_Q__)); 
+   Global.Add("gslcdflognormalPinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_lognormal_Pinv__)); 
+   Global.Add("gslcdflognormalQinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_lognormal_Qinv__)); 
+   Global.Add("gslcdfgumbel1P","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel1_P__)); 
+   Global.Add("gslcdfgumbel1Q","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel1_Q__)); 
+   Global.Add("gslcdfgumbel1Pinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel1_Pinv__)); 
+   Global.Add("gslcdfgumbel1Qinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel1_Qinv__)); 
+   Global.Add("gslcdfgumbel2P","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel2_P__)); 
+   Global.Add("gslcdfgumbel2Q","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel2_Q__)); 
+   Global.Add("gslcdfgumbel2Pinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel2_Pinv__)); 
+   Global.Add("gslcdfgumbel2Qinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_gumbel2_Qinv__)); 
+   Global.Add("gslcdfweibullP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_weibull_P__)); 
+   Global.Add("gslcdfweibullQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_weibull_Q__)); 
+   Global.Add("gslcdfweibullPinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_weibull_Pinv__)); 
+   Global.Add("gslcdfweibullQinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_weibull_Qinv__)); 
+   Global.Add("gslcdfparetoP","(",new OneOperator3_<double,double,double,double>( gsl_cdf_pareto_P__)); 
+   Global.Add("gslcdfparetoQ","(",new OneOperator3_<double,double,double,double>( gsl_cdf_pareto_Q__)); 
+   Global.Add("gslcdfparetoPinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_pareto_Pinv__)); 
+   Global.Add("gslcdfparetoQinv","(",new OneOperator3_<double,double,double,double>( gsl_cdf_pareto_Qinv__)); 
+   Global.Add("gslcdflogisticP","(",new OneOperator2_<double,double,double>( gsl_cdf_logistic_P__)); 
+   Global.Add("gslcdflogisticQ","(",new OneOperator2_<double,double,double>( gsl_cdf_logistic_Q__)); 
+   Global.Add("gslcdflogisticPinv","(",new OneOperator2_<double,double,double>( gsl_cdf_logistic_Pinv__)); 
+   Global.Add("gslcdflogisticQinv","(",new OneOperator2_<double,double,double>( gsl_cdf_logistic_Qinv__)); 
+   Global.Add("gslcdfbinomialP","(",new OneOperator3_<double,long,double,long>( gsl_cdf_binomial_P__)); 
+   Global.Add("gslcdfbinomialQ","(",new OneOperator3_<double,long,double,long>( gsl_cdf_binomial_Q__)); 
+   Global.Add("gslcdfpoissonP","(",new OneOperator2_<double,long,double>( gsl_cdf_poisson_P__)); 
+   Global.Add("gslcdfpoissonQ","(",new OneOperator2_<double,long,double>( gsl_cdf_poisson_Q__)); 
+   Global.Add("gslcdfgeometricP","(",new OneOperator2_<double,long,double>( gsl_cdf_geometric_P__)); 
+   Global.Add("gslcdfgeometricQ","(",new OneOperator2_<double,long,double>( gsl_cdf_geometric_Q__)); 
+   Global.Add("gslcdfnegativebinomialP","(",new OneOperator3_<double,long,double,double>( gsl_cdf_negative_binomial_P__)); 
+   Global.Add("gslcdfnegativebinomialQ","(",new OneOperator3_<double,long,double,double>( gsl_cdf_negative_binomial_Q__)); 
+   Global.Add("gslcdfpascalP","(",new OneOperator3_<double,long,double,long>( gsl_cdf_pascal_P__)); 
+   Global.Add("gslcdfpascalQ","(",new OneOperator3_<double,long,double,long>( gsl_cdf_pascal_Q__)); 
+   Global.Add("gslranbernoullipdf","(",new OneOperator2_<double,long,double>( gsl_ran_bernoulli_pdf__)); 
+   Global.Add("gslranbeta","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_beta__)); 
+   Global.Add("gslranbetapdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_beta_pdf__)); 
+   Global.Add("gslranbinomialpdf","(",new OneOperator3_<double,long,double,long>( gsl_ran_binomial_pdf__)); 
+   Global.Add("gslranexponential","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_exponential__)); 
+   Global.Add("gslranexponentialpdf","(",new OneOperator2_<double,double,double>( gsl_ran_exponential_pdf__)); 
+   Global.Add("gslranexppow","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_exppow__)); 
+   Global.Add("gslranexppowpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_exppow_pdf__)); 
+   Global.Add("gslrancauchy","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_cauchy__)); 
+   Global.Add("gslrancauchypdf","(",new OneOperator2_<double,double,double>( gsl_ran_cauchy_pdf__)); 
+   Global.Add("gslranchisq","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_chisq__)); 
+   Global.Add("gslranchisqpdf","(",new OneOperator2_<double,double,double>( gsl_ran_chisq_pdf__)); 
+   Global.Add("gslranerlang","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_erlang__)); 
+   Global.Add("gslranerlangpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_erlang_pdf__)); 
+   Global.Add("gslranfdist","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_fdist__)); 
+   Global.Add("gslranfdistpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_fdist_pdf__)); 
+   Global.Add("gslranflat","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_flat__)); 
+   Global.Add("gslranflatpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_flat_pdf__)); 
+   Global.Add("gslrangamma","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_gamma__)); 
+   Global.Add("gslrangammaint","(",new OneOperator2_<double,gsl_rng **,long>( gsl_ran_gamma_int__)); 
+   Global.Add("gslrangammapdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_gamma_pdf__)); 
+   Global.Add("gslrangammamt","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_gamma_mt__)); 
+   Global.Add("gslrangammaknuth","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_gamma_knuth__)); 
+   Global.Add("gslrangaussian","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_gaussian__)); 
+   Global.Add("gslrangaussianratiomethod","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_gaussian_ratio_method__)); 
+   Global.Add("gslrangaussianziggurat","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_gaussian_ziggurat__)); 
+   Global.Add("gslrangaussianpdf","(",new OneOperator2_<double,double,double>( gsl_ran_gaussian_pdf__)); 
+   Global.Add("gslranugaussian","(",new OneOperator1_<double,gsl_rng **>( gsl_ran_ugaussian__)); 
+   Global.Add("gslranugaussianratiomethod","(",new OneOperator1_<double,gsl_rng **>( gsl_ran_ugaussian_ratio_method__)); 
+   Global.Add("gslranugaussianpdf","(",new OneOperator1_<double,double>( gsl_ran_ugaussian_pdf__)); 
+   Global.Add("gslrangaussiantail","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_gaussian_tail__)); 
+   Global.Add("gslrangaussiantailpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_gaussian_tail_pdf__)); 
+   Global.Add("gslranugaussiantail","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_ugaussian_tail__)); 
+   Global.Add("gslranugaussiantailpdf","(",new OneOperator2_<double,double,double>( gsl_ran_ugaussian_tail_pdf__)); 
+   Global.Add("gslranlandau","(",new OneOperator1_<double,gsl_rng **>( gsl_ran_landau__)); 
+   Global.Add("gslranlandaupdf","(",new OneOperator1_<double,double>( gsl_ran_landau_pdf__)); 
+   Global.Add("gslrangeometricpdf","(",new OneOperator2_<double,long,double>( gsl_ran_geometric_pdf__)); 
+   Global.Add("gslrangumbel1","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_gumbel1__)); 
+   Global.Add("gslrangumbel1pdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_gumbel1_pdf__)); 
+   Global.Add("gslrangumbel2","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_gumbel2__)); 
+   Global.Add("gslrangumbel2pdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_gumbel2_pdf__)); 
+   Global.Add("gslranlogistic","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_logistic__)); 
+   Global.Add("gslranlogisticpdf","(",new OneOperator2_<double,double,double>( gsl_ran_logistic_pdf__)); 
+   Global.Add("gslranlognormal","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_lognormal__)); 
+   Global.Add("gslranlognormalpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_lognormal_pdf__)); 
+   Global.Add("gslranlogarithmicpdf","(",new OneOperator2_<double,long,double>( gsl_ran_logarithmic_pdf__)); 
+   Global.Add("gslrannegativebinomialpdf","(",new OneOperator3_<double,long,double,double>( gsl_ran_negative_binomial_pdf__)); 
+   Global.Add("gslranpascalpdf","(",new OneOperator3_<double,long,double,long>( gsl_ran_pascal_pdf__)); 
+   Global.Add("gslranpareto","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_pareto__)); 
+   Global.Add("gslranparetopdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_pareto_pdf__)); 
+   Global.Add("gslranpoissonpdf","(",new OneOperator2_<double,long,double>( gsl_ran_poisson_pdf__)); 
+   Global.Add("gslranrayleigh","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_rayleigh__)); 
+   Global.Add("gslranrayleighpdf","(",new OneOperator2_<double,double,double>( gsl_ran_rayleigh_pdf__)); 
+   Global.Add("gslranrayleightail","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_rayleigh_tail__)); 
+   Global.Add("gslranrayleightailpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_rayleigh_tail_pdf__)); 
+   Global.Add("gslrantdist","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_tdist__)); 
+   Global.Add("gslrantdistpdf","(",new OneOperator2_<double,double,double>( gsl_ran_tdist_pdf__)); 
+   Global.Add("gslranlaplace","(",new OneOperator2_<double,gsl_rng **,double>( gsl_ran_laplace__)); 
+   Global.Add("gslranlaplacepdf","(",new OneOperator2_<double,double,double>( gsl_ran_laplace_pdf__)); 
+   Global.Add("gslranlevy","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_levy__)); 
+   Global.Add("gslranweibull","(",new OneOperator3_<double,gsl_rng **,double,double>( gsl_ran_weibull__)); 
+   Global.Add("gslranweibullpdf","(",new OneOperator3_<double,double,double,double>( gsl_ran_weibull_pdf__)); 
+   Global.Add("gslsfairyzeroAi","(",new OneOperator1_<double,long>( gsl_sf_airy_zero_Ai__)); 
+   Global.Add("gslsfairyzeroBi","(",new OneOperator1_<double,long>( gsl_sf_airy_zero_Bi__)); 
+   Global.Add("gslsfairyzeroAideriv","(",new OneOperator1_<double,long>( gsl_sf_airy_zero_Ai_deriv__)); 
+   Global.Add("gslsfairyzeroBideriv","(",new OneOperator1_<double,long>( gsl_sf_airy_zero_Bi_deriv__)); 
+   Global.Add("gslsfbesselJ0","(",new OneOperator1_<double,double>( gsl_sf_bessel_J0__)); 
+   Global.Add("gslsfbesselJ1","(",new OneOperator1_<double,double>( gsl_sf_bessel_J1__)); 
+   Global.Add("gslsfbesselJn","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_Jn__)); 
+   Global.Add("gslsfbesselY0","(",new OneOperator1_<double,double>( gsl_sf_bessel_Y0__)); 
+   Global.Add("gslsfbesselY1","(",new OneOperator1_<double,double>( gsl_sf_bessel_Y1__)); 
+   Global.Add("gslsfbesselYn","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_Yn__)); 
+   Global.Add("gslsfbesselI0","(",new OneOperator1_<double,double>( gsl_sf_bessel_I0__)); 
+   Global.Add("gslsfbesselI1","(",new OneOperator1_<double,double>( gsl_sf_bessel_I1__)); 
+   Global.Add("gslsfbesselIn","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_In__)); 
+   Global.Add("gslsfbesselI0scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_I0_scaled__)); 
+   Global.Add("gslsfbesselI1scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_I1_scaled__)); 
+   Global.Add("gslsfbesselInscaled","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_In_scaled__)); 
+   Global.Add("gslsfbesselK0","(",new OneOperator1_<double,double>( gsl_sf_bessel_K0__)); 
+   Global.Add("gslsfbesselK1","(",new OneOperator1_<double,double>( gsl_sf_bessel_K1__)); 
+   Global.Add("gslsfbesselKn","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_Kn__)); 
+   Global.Add("gslsfbesselK0scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_K0_scaled__)); 
+   Global.Add("gslsfbesselK1scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_K1_scaled__)); 
+   Global.Add("gslsfbesselKnscaled","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_Kn_scaled__)); 
+   Global.Add("gslsfbesselj0","(",new OneOperator1_<double,double>( gsl_sf_bessel_j0__)); 
+   Global.Add("gslsfbesselj1","(",new OneOperator1_<double,double>( gsl_sf_bessel_j1__)); 
+   Global.Add("gslsfbesselj2","(",new OneOperator1_<double,double>( gsl_sf_bessel_j2__)); 
+   Global.Add("gslsfbesseljl","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_jl__)); 
+   Global.Add("gslsfbessely0","(",new OneOperator1_<double,double>( gsl_sf_bessel_y0__)); 
+   Global.Add("gslsfbessely1","(",new OneOperator1_<double,double>( gsl_sf_bessel_y1__)); 
+   Global.Add("gslsfbessely2","(",new OneOperator1_<double,double>( gsl_sf_bessel_y2__)); 
+   Global.Add("gslsfbesselyl","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_yl__)); 
+   Global.Add("gslsfbesseli0scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_i0_scaled__)); 
+   Global.Add("gslsfbesseli1scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_i1_scaled__)); 
+   Global.Add("gslsfbesseli2scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_i2_scaled__)); 
+   Global.Add("gslsfbesselilscaled","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_il_scaled__)); 
+   Global.Add("gslsfbesselk0scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_k0_scaled__)); 
+   Global.Add("gslsfbesselk1scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_k1_scaled__)); 
+   Global.Add("gslsfbesselk2scaled","(",new OneOperator1_<double,double>( gsl_sf_bessel_k2_scaled__)); 
+   Global.Add("gslsfbesselklscaled","(",new OneOperator2_<double,long,double>( gsl_sf_bessel_kl_scaled__)); 
+   Global.Add("gslsfbesselJnu","(",new OneOperator2_<double,double,double>( gsl_sf_bessel_Jnu__)); 
+   Global.Add("gslsfbesselYnu","(",new OneOperator2_<double,double,double>( gsl_sf_bessel_Ynu__)); 
+   Global.Add("gslsfbesselInuscaled","(",new OneOperator2_<double,double,double>( gsl_sf_bessel_Inu_scaled__)); 
+   Global.Add("gslsfbesselInu","(",new OneOperator2_<double,double,double>( gsl_sf_bessel_Inu__)); 
+   Global.Add("gslsfbesselKnuscaled","(",new OneOperator2_<double,double,double>( gsl_sf_bessel_Knu_scaled__)); 
+   Global.Add("gslsfbesselKnu","(",new OneOperator2_<double,double,double>( gsl_sf_bessel_Knu__)); 
+   Global.Add("gslsfbessellnKnu","(",new OneOperator2_<double,double,double>( gsl_sf_bessel_lnKnu__)); 
+   Global.Add("gslsfbesselzeroJ0","(",new OneOperator1_<double,long>( gsl_sf_bessel_zero_J0__)); 
+   Global.Add("gslsfbesselzeroJ1","(",new OneOperator1_<double,long>( gsl_sf_bessel_zero_J1__)); 
+   Global.Add("gslsfbesselzeroJnu","(",new OneOperator2_<double,double,long>( gsl_sf_bessel_zero_Jnu__)); 
+   Global.Add("gslsfclausen","(",new OneOperator1_<double,double>( gsl_sf_clausen__)); 
+   Global.Add("gslsfhydrogenicR1","(",new OneOperator2_<double,double,double>( gsl_sf_hydrogenicR_1__)); 
+   Global.Add("gslsfdawson","(",new OneOperator1_<double,double>( gsl_sf_dawson__)); 
+   Global.Add("gslsfdebye1","(",new OneOperator1_<double,double>( gsl_sf_debye_1__)); 
+   Global.Add("gslsfdebye2","(",new OneOperator1_<double,double>( gsl_sf_debye_2__)); 
+   Global.Add("gslsfdebye3","(",new OneOperator1_<double,double>( gsl_sf_debye_3__)); 
+   Global.Add("gslsfdebye4","(",new OneOperator1_<double,double>( gsl_sf_debye_4__)); 
+   Global.Add("gslsfdebye5","(",new OneOperator1_<double,double>( gsl_sf_debye_5__)); 
+   Global.Add("gslsfdebye6","(",new OneOperator1_<double,double>( gsl_sf_debye_6__)); 
+   Global.Add("gslsfdilog","(",new OneOperator1_<double,double>( gsl_sf_dilog__)); 
+   Global.Add("gslsfmultiply","(",new OneOperator2_<double,double,double>( gsl_sf_multiply__)); 
+   Global.Add("gslsferfc","(",new OneOperator1_<double,double>( gsl_sf_erfc__)); 
+   Global.Add("gslsflogerfc","(",new OneOperator1_<double,double>( gsl_sf_log_erfc__)); 
+   Global.Add("gslsferf","(",new OneOperator1_<double,double>( gsl_sf_erf__)); 
+   Global.Add("gslsferfZ","(",new OneOperator1_<double,double>( gsl_sf_erf_Z__)); 
+   Global.Add("gslsferfQ","(",new OneOperator1_<double,double>( gsl_sf_erf_Q__)); 
+   Global.Add("gslsfhazard","(",new OneOperator1_<double,double>( gsl_sf_hazard__)); 
+   Global.Add("gslsfexp","(",new OneOperator1_<double,double>( gsl_sf_exp__)); 
+   Global.Add("gslsfexpmult","(",new OneOperator2_<double,double,double>( gsl_sf_exp_mult__)); 
+   Global.Add("gslsfexpm1","(",new OneOperator1_<double,double>( gsl_sf_expm1__)); 
+   Global.Add("gslsfexprel","(",new OneOperator1_<double,double>( gsl_sf_exprel__)); 
+   Global.Add("gslsfexprel2","(",new OneOperator1_<double,double>( gsl_sf_exprel_2__)); 
+   Global.Add("gslsfexpreln","(",new OneOperator2_<double,long,double>( gsl_sf_exprel_n__)); 
+   Global.Add("gslsfexpintE1","(",new OneOperator1_<double,double>( gsl_sf_expint_E1__)); 
+   Global.Add("gslsfexpintE2","(",new OneOperator1_<double,double>( gsl_sf_expint_E2__)); 
+   Global.Add("gslsfexpintEn","(",new OneOperator2_<double,long,double>( gsl_sf_expint_En__)); 
+   Global.Add("gslsfexpintE1scaled","(",new OneOperator1_<double,double>( gsl_sf_expint_E1_scaled__)); 
+   Global.Add("gslsfexpintE2scaled","(",new OneOperator1_<double,double>( gsl_sf_expint_E2_scaled__)); 
+   Global.Add("gslsfexpintEnscaled","(",new OneOperator2_<double,long,double>( gsl_sf_expint_En_scaled__)); 
+   Global.Add("gslsfexpintEi","(",new OneOperator1_<double,double>( gsl_sf_expint_Ei__)); 
+   Global.Add("gslsfexpintEiscaled","(",new OneOperator1_<double,double>( gsl_sf_expint_Ei_scaled__)); 
+   Global.Add("gslsfShi","(",new OneOperator1_<double,double>( gsl_sf_Shi__)); 
+   Global.Add("gslsfChi","(",new OneOperator1_<double,double>( gsl_sf_Chi__)); 
+   Global.Add("gslsfexpint3","(",new OneOperator1_<double,double>( gsl_sf_expint_3__)); 
+   Global.Add("gslsfSi","(",new OneOperator1_<double,double>( gsl_sf_Si__)); 
+   Global.Add("gslsfCi","(",new OneOperator1_<double,double>( gsl_sf_Ci__)); 
+   Global.Add("gslsfatanint","(",new OneOperator1_<double,double>( gsl_sf_atanint__)); 
+   Global.Add("gslsffermidiracm1","(",new OneOperator1_<double,double>( gsl_sf_fermi_dirac_m1__)); 
+   Global.Add("gslsffermidirac0","(",new OneOperator1_<double,double>( gsl_sf_fermi_dirac_0__)); 
+   Global.Add("gslsffermidirac1","(",new OneOperator1_<double,double>( gsl_sf_fermi_dirac_1__)); 
+   Global.Add("gslsffermidirac2","(",new OneOperator1_<double,double>( gsl_sf_fermi_dirac_2__)); 
+   Global.Add("gslsffermidiracint","(",new OneOperator2_<double,long,double>( gsl_sf_fermi_dirac_int__)); 
+   Global.Add("gslsffermidiracmhalf","(",new OneOperator1_<double,double>( gsl_sf_fermi_dirac_mhalf__)); 
+   Global.Add("gslsffermidirachalf","(",new OneOperator1_<double,double>( gsl_sf_fermi_dirac_half__)); 
+   Global.Add("gslsffermidirac3half","(",new OneOperator1_<double,double>( gsl_sf_fermi_dirac_3half__)); 
+   Global.Add("gslsffermidiracinc0","(",new OneOperator2_<double,double,double>( gsl_sf_fermi_dirac_inc_0__)); 
+   Global.Add("gslsflngamma","(",new OneOperator1_<double,double>( gsl_sf_lngamma__)); 
+   Global.Add("gslsfgamma","(",new OneOperator1_<double,double>( gsl_sf_gamma__)); 
+   Global.Add("gslsfgammastar","(",new OneOperator1_<double,double>( gsl_sf_gammastar__)); 
+   Global.Add("gslsfgammainv","(",new OneOperator1_<double,double>( gsl_sf_gammainv__)); 
+   Global.Add("gslsftaylorcoeff","(",new OneOperator2_<double,long,double>( gsl_sf_taylorcoeff__)); 
+   Global.Add("gslsffact","(",new OneOperator1_<double,long>( gsl_sf_fact__)); 
+   Global.Add("gslsfdoublefact","(",new OneOperator1_<double,long>( gsl_sf_doublefact__)); 
+   Global.Add("gslsflnfact","(",new OneOperator1_<double,long>( gsl_sf_lnfact__)); 
+   Global.Add("gslsflndoublefact","(",new OneOperator1_<double,long>( gsl_sf_lndoublefact__)); 
+   Global.Add("gslsflnchoose","(",new OneOperator2_<double,long,long>( gsl_sf_lnchoose__)); 
+   Global.Add("gslsfchoose","(",new OneOperator2_<double,long,long>( gsl_sf_choose__)); 
+   Global.Add("gslsflnpoch","(",new OneOperator2_<double,double,double>( gsl_sf_lnpoch__)); 
+   Global.Add("gslsfpoch","(",new OneOperator2_<double,double,double>( gsl_sf_poch__)); 
+   Global.Add("gslsfpochrel","(",new OneOperator2_<double,double,double>( gsl_sf_pochrel__)); 
+   Global.Add("gslsfgammaincQ","(",new OneOperator2_<double,double,double>( gsl_sf_gamma_inc_Q__)); 
+   Global.Add("gslsfgammaincP","(",new OneOperator2_<double,double,double>( gsl_sf_gamma_inc_P__)); 
+   Global.Add("gslsfgammainc","(",new OneOperator2_<double,double,double>( gsl_sf_gamma_inc__)); 
+   Global.Add("gslsflnbeta","(",new OneOperator2_<double,double,double>( gsl_sf_lnbeta__)); 
+   Global.Add("gslsfbeta","(",new OneOperator2_<double,double,double>( gsl_sf_beta__)); 
+   Global.Add("gslsfbetainc","(",new OneOperator3_<double,double,double,double>( gsl_sf_beta_inc__)); 
+   Global.Add("gslsfgegenpoly1","(",new OneOperator2_<double,double,double>( gsl_sf_gegenpoly_1__)); 
+   Global.Add("gslsfgegenpoly2","(",new OneOperator2_<double,double,double>( gsl_sf_gegenpoly_2__)); 
+   Global.Add("gslsfgegenpoly3","(",new OneOperator2_<double,double,double>( gsl_sf_gegenpoly_3__)); 
+   Global.Add("gslsfgegenpolyn","(",new OneOperator3_<double,long,double,double>( gsl_sf_gegenpoly_n__)); 
+   Global.Add("gslsfhyperg0F1","(",new OneOperator2_<double,double,double>( gsl_sf_hyperg_0F1__)); 
+   Global.Add("gslsfhyperg1F1int","(",new OneOperator3_<double,long,long,double>( gsl_sf_hyperg_1F1_int__)); 
+   Global.Add("gslsfhyperg1F1","(",new OneOperator3_<double,double,double,double>( gsl_sf_hyperg_1F1__)); 
+   Global.Add("gslsfhypergUint","(",new OneOperator3_<double,long,long,double>( gsl_sf_hyperg_U_int__)); 
+   Global.Add("gslsfhypergU","(",new OneOperator3_<double,double,double,double>( gsl_sf_hyperg_U__)); 
+   Global.Add("gslsfhyperg2F0","(",new OneOperator3_<double,double,double,double>( gsl_sf_hyperg_2F0__)); 
+   Global.Add("gslsflaguerre1","(",new OneOperator2_<double,double,double>( gsl_sf_laguerre_1__)); 
+   Global.Add("gslsflaguerre2","(",new OneOperator2_<double,double,double>( gsl_sf_laguerre_2__)); 
+   Global.Add("gslsflaguerre3","(",new OneOperator2_<double,double,double>( gsl_sf_laguerre_3__)); 
+   Global.Add("gslsflaguerren","(",new OneOperator3_<double,long,double,double>( gsl_sf_laguerre_n__)); 
+   Global.Add("gslsflambertW0","(",new OneOperator1_<double,double>( gsl_sf_lambert_W0__)); 
+   Global.Add("gslsflambertWm1","(",new OneOperator1_<double,double>( gsl_sf_lambert_Wm1__)); 
+   Global.Add("gslsflegendrePl","(",new OneOperator2_<double,long,double>( gsl_sf_legendre_Pl__)); 
+   Global.Add("gslsflegendreP1","(",new OneOperator1_<double,double>( gsl_sf_legendre_P1__)); 
+   Global.Add("gslsflegendreP2","(",new OneOperator1_<double,double>( gsl_sf_legendre_P2__)); 
+   Global.Add("gslsflegendreP3","(",new OneOperator1_<double,double>( gsl_sf_legendre_P3__)); 
+   Global.Add("gslsflegendreQ0","(",new OneOperator1_<double,double>( gsl_sf_legendre_Q0__)); 
+   Global.Add("gslsflegendreQ1","(",new OneOperator1_<double,double>( gsl_sf_legendre_Q1__)); 
+   Global.Add("gslsflegendreQl","(",new OneOperator2_<double,long,double>( gsl_sf_legendre_Ql__)); 
+   Global.Add("gslsflegendrePlm","(",new OneOperator3_<double,long,long,double>( gsl_sf_legendre_Plm__)); 
+   Global.Add("gslsflegendresphPlm","(",new OneOperator3_<double,long,long,double>( gsl_sf_legendre_sphPlm__)); 
+   Global.Add("gslsflegendrearraysize","(",new OneOperator2_<long,long,long>( gsl_sf_legendre_array_size__)); 
+   Global.Add("gslsfconicalPhalf","(",new OneOperator2_<double,double,double>( gsl_sf_conicalP_half__)); 
+   Global.Add("gslsfconicalPmhalf","(",new OneOperator2_<double,double,double>( gsl_sf_conicalP_mhalf__)); 
+   Global.Add("gslsfconicalP0","(",new OneOperator2_<double,double,double>( gsl_sf_conicalP_0__)); 
+   Global.Add("gslsfconicalP1","(",new OneOperator2_<double,double,double>( gsl_sf_conicalP_1__)); 
+   Global.Add("gslsfconicalPsphreg","(",new OneOperator3_<double,long,double,double>( gsl_sf_conicalP_sph_reg__)); 
+   Global.Add("gslsfconicalPcylreg","(",new OneOperator3_<double,long,double,double>( gsl_sf_conicalP_cyl_reg__)); 
+   Global.Add("gslsflegendreH3d0","(",new OneOperator2_<double,double,double>( gsl_sf_legendre_H3d_0__)); 
+   Global.Add("gslsflegendreH3d1","(",new OneOperator2_<double,double,double>( gsl_sf_legendre_H3d_1__)); 
+   Global.Add("gslsflegendreH3d","(",new OneOperator3_<double,long,double,double>( gsl_sf_legendre_H3d__)); 
+   Global.Add("gslsflog","(",new OneOperator1_<double,double>( gsl_sf_log__)); 
+   Global.Add("gslsflogabs","(",new OneOperator1_<double,double>( gsl_sf_log_abs__)); 
+   Global.Add("gslsflog1plusx","(",new OneOperator1_<double,double>( gsl_sf_log_1plusx__)); 
+   Global.Add("gslsflog1plusxmx","(",new OneOperator1_<double,double>( gsl_sf_log_1plusx_mx__)); 
+   Global.Add("gslsfpowint","(",new OneOperator2_<double,double,long>( gsl_sf_pow_int__)); 
+   Global.Add("gslsfpsiint","(",new OneOperator1_<double,long>( gsl_sf_psi_int__)); 
+   Global.Add("gslsfpsi","(",new OneOperator1_<double,double>( gsl_sf_psi__)); 
+   Global.Add("gslsfpsi1piy","(",new OneOperator1_<double,double>( gsl_sf_psi_1piy__)); 
+   Global.Add("gslsfpsi1int","(",new OneOperator1_<double,long>( gsl_sf_psi_1_int__)); 
+   Global.Add("gslsfpsi1","(",new OneOperator1_<double,double>( gsl_sf_psi_1__)); 
+   Global.Add("gslsfpsin","(",new OneOperator2_<double,long,double>( gsl_sf_psi_n__)); 
+   Global.Add("gslsfsynchrotron1","(",new OneOperator1_<double,double>( gsl_sf_synchrotron_1__)); 
+   Global.Add("gslsfsynchrotron2","(",new OneOperator1_<double,double>( gsl_sf_synchrotron_2__)); 
+   Global.Add("gslsftransport2","(",new OneOperator1_<double,double>( gsl_sf_transport_2__)); 
+   Global.Add("gslsftransport3","(",new OneOperator1_<double,double>( gsl_sf_transport_3__)); 
+   Global.Add("gslsftransport4","(",new OneOperator1_<double,double>( gsl_sf_transport_4__)); 
+   Global.Add("gslsftransport5","(",new OneOperator1_<double,double>( gsl_sf_transport_5__)); 
+   Global.Add("gslsfsin","(",new OneOperator1_<double,double>( gsl_sf_sin__)); 
+   Global.Add("gslsfcos","(",new OneOperator1_<double,double>( gsl_sf_cos__)); 
+   Global.Add("gslsfhypot","(",new OneOperator2_<double,double,double>( gsl_sf_hypot__)); 
+   Global.Add("gslsfsinc","(",new OneOperator1_<double,double>( gsl_sf_sinc__)); 
+   Global.Add("gslsflnsinh","(",new OneOperator1_<double,double>( gsl_sf_lnsinh__)); 
+   Global.Add("gslsflncosh","(",new OneOperator1_<double,double>( gsl_sf_lncosh__)); 
+   Global.Add("gslsfanglerestrictsymm","(",new OneOperator1_<double,double>( gsl_sf_angle_restrict_symm__)); 
+   Global.Add("gslsfanglerestrictpos","(",new OneOperator1_<double,double>( gsl_sf_angle_restrict_pos__)); 
+   Global.Add("gslsfzetaint","(",new OneOperator1_<double,long>( gsl_sf_zeta_int__)); 
+   Global.Add("gslsfzeta","(",new OneOperator1_<double,double>( gsl_sf_zeta__)); 
+   Global.Add("gslsfzetam1","(",new OneOperator1_<double,double>( gsl_sf_zetam1__)); 
+   Global.Add("gslsfzetam1int","(",new OneOperator1_<double,long>( gsl_sf_zetam1_int__)); 
+   Global.Add("gslsfhzeta","(",new OneOperator2_<double,double,double>( gsl_sf_hzeta__)); 
+   Global.Add("gslsfetaint","(",new OneOperator1_<double,long>( gsl_sf_eta_int__)); 
+   Global.Add("gslsfeta","(",new OneOperator1_<double,double>( gsl_sf_eta__)); 
+ } 
+/*****************/
+/*****************/
diff --git a/examples++-load/fflapack.cpp b/examples++-load/fflapack.cpp
new file mode 100644
index 0000000..94aa2eb
--- /dev/null
+++ b/examples++-load/fflapack.cpp
@@ -0,0 +1,970 @@
+//ff-c++-LIBRARY-dep:   lapack
+//ff-c++-LIBRARY-dep:   blas
+#include "ff++.hpp"
+#include "RNM.hpp"
+#include "AFunction_ext.hpp" // Extension of "AFunction.hpp" to deal with more than 3 parameters function
+
+using namespace std;
+
+#ifdef __LP64__
+  typedef int intblas;
+  typedef int integer;
+#else
+  typedef long intblas;
+  typedef long integer;
+#endif
+
+typedef integer  logical;
+typedef float   LAPACK_real;
+typedef double   doublereal;
+typedef logical  (* L_fp)();
+typedef integer      ftnlen;
+
+typedef complex<float> LAPACK_complex;
+typedef complex<double> doublecomplex;
+typedef void VOID; 
+#define complex LAPACK_complex 
+#define real LAPACK_real 
+
+#include "clapack.h"
+#undef real
+#undef complex 
+
+long lapack_inv(KNM<double>* A)
+{
+  intblas n=A->N();
+  intblas m=A->M();
+  double *a=&(*A)(0,0);
+  intblas info;
+  intblas lda=n;
+  KN<intblas> ipiv(n);
+  intblas  lw=10*n;
+  KN<double> w(lw);
+  ffassert(n==m);
+  dgetrf_(&n,&n,a,&lda,ipiv,&info);
+  if(info) return info;
+  dgetri_(&n,a,&lda,ipiv,w,&lw,&info);
+  return info;
+}
+
+long lapack_inv(KNM<Complex>* A)
+{
+    intblas n=A->N();
+    intblas m=A->M();
+    Complex *a=&(*A)(0,0);
+    intblas info;
+    intblas lda=n;
+    KN<intblas> ipiv(n);
+    intblas  lw=10*n;
+    KN<Complex> w(lw);
+    ffassert(n==m);
+    zgetrf_(&n,&n,a,&lda,ipiv,&info);
+    if(info) return info;
+    zgetri_(&n,a,&lda,ipiv,w,&lw,&info);
+    return info;
+}
+
+// (computation of the eigenvalues and right eigenvectors of a real nonsymmetric matrix)
+long lapack_dgeev(KNM<double> *const &A,KN<Complex> *const &vp,KNM<Complex> *const &vectp)
+{
+  /*
+    SUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR, LDVR, WORK, LWORK, INFO )
+   *  JOBVL   (input) CHARACTER*1
+   *          = 'N': left eigenvectors of A are not computed;
+   *          = 'V': left eigenvectors of A are computed.
+   *
+   *  JOBVR   (input) CHARACTER*1
+   *          = 'N': right eigenvectors of A are not computed;
+   *          = 'V': right eigenvectors of A are computed.
+   *
+   *  N       (input) INTEGER
+   *          The order of the matrix A. N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the N-by-N matrix A.
+   *          On exit, A has been overwritten.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  WR      (output) DOUBLE PRECISION array, dimension (N)
+   *  WI      (output) DOUBLE PRECISION array, dimension (N)
+   *          WR and WI contain the real and imaginary parts,
+   *          respectively, of the computed eigenvalues.  Complex
+   *          conjugate pairs of eigenvalues appear consecutively
+   *          with the eigenvalue having the positive imaginary part
+   *          first.
+   *
+   *  VL      (output) DOUBLE PRECISION array, dimension (LDVL,N)
+   *          If JOBVL = 'V', the left eigenvectors u(j) are stored one
+   *          after another in the columns of VL, in the same order
+   *          as their eigenvalues.
+   *          If JOBVL = 'N', VL is not referenced.
+   *          If the j-th eigenvalue is real, then u(j) = VL(:,j),
+   *          the j-th column of VL.
+   *          If the j-th and (j+1)-st eigenvalues form a complex
+   *          conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and
+   *          u(j+1) = VL(:,j) - i*VL(:,j+1).
+   *
+   *  LDVL    (input) INTEGER
+   *          The leading dimension of the array VL.  LDVL >= 1; if
+   *          JOBVL = 'V', LDVL >= N.
+   *
+   *  VR      (output) DOUBLE PRECISION array, dimension (LDVR,N)
+   *          If JOBVR = 'V', the right eigenvectors v(j) are stored one
+   *          after another in the columns of VR, in the same order
+   *          as their eigenvalues.
+   *          If JOBVR = 'N', VR is not referenced.
+   *          If the j-th eigenvalue is real, then v(j) = VR(:,j),
+   *          the j-th column of VR.
+   *          If the j-th and (j+1)-st eigenvalues form a complex
+   *          conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and
+   *          v(j+1) = VR(:,j) - i*VR(:,j+1).
+   *
+   *  LDVR    (input) INTEGER
+   *          The leading dimension of the array VR.  LDVR >= 1; if
+   *          JOBVR = 'V', LDVR >= N.
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+   *
+   *  LWORK   (input) INTEGER
+   *          The dimension of the array WORK.  LWORK >= max(1,3*N), and
+   *          if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N.  For good
+   *          performance, LWORK must generally be larger.
+   *
+   *          If LWORK = -1, then a workspace query is assumed; the routine
+   *          only calculates the optimal size of the WORK array, returns
+   *          this value as the first entry of the WORK array, and no error
+   *          message related to LWORK is issued by XERBLA.
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value.
+   *          > 0:  if INFO = i, the QR algorithm failed to compute all the
+   *                eigenvalues, and no eigenvectors have been computed;
+   *                elements i+1:N of WR and WI contain eigenvalues which
+   *                have converged.
+   */
+  intblas n=A->N();
+  ffassert(A->M()==n);
+  ffassert(vectp->M()>=n);
+  ffassert(vectp->N()>=n);
+  ffassert(vp->N()>=n);
+  KN<double> wr(n),wi(n),w(1);
+  KNM<double> mat(*A),vr(n,n),vl(n,n);
+  intblas info,lw=-1;
+  char JOBVL='N',JOBVR='V';
+  dgeev_(&JOBVL,&JOBVR,&n,mat,&n,wr,wi,vl,&n,vr,&n,w,&lw,&info);
+  lw=w[0];
+  w.resize(lw);
+  //cout << mat << endl;
+  dgeev_(&JOBVL,&JOBVR,&n,mat,&n,wr,wi,vl,&n,vr,&n,w,&lw,&info);
+  //cout << wr << endl;
+  //cout << wi << endl;
+  if (info<0)
+     {
+     cout << "   dgeev: the " << info << "-th argument had an illegal value." << endl;
+     (*vp)=Complex();
+     (*vectp)=Complex();
+     }
+  else if (info>0)
+     {
+     cout << "   dgeev: the QR algorithm failed to compute all the eigenvalues, and no eigenvectors have been computed." << endl;
+     (*vp)=Complex();
+     (*vectp)=Complex();
+     }
+  else if (info==0)
+     {
+     for (int i=0;i<n;++i)
+        {
+        (*vp)[i]=Complex(wr[i],wi[i]);
+        if (verbosity>2)
+           cout << "   dgeev: vp "<< i << " : "  << (*vp)[i] << endl;
+        if (wi[i]==0)
+           for (int j=0;j<n;++j)
+              (*vectp)(j,i)=vr(j,i);
+        else if (wi[i]>0)
+	   {
+	   for (int j=0;j<n;++j)
+              (*vectp)(j,i)=Complex(vr(j,i),vr(j,i+1));
+           }
+	else if (wi[i]<0)
+	   {
+           for (int j=0;j<n;++j)
+              (*vectp)(j,i)=Complex(vr(j,i-1),-vr(j,i));	      
+           }
+        if (verbosity>5)
+           cout << "   dgeev:   " << (*vectp)(':',i) <<endl;
+        }
+     }
+  return info;
+}
+
+// (computation of the eigenvalues and right eigenvectors of a complex nonsymmetric matrix)
+long lapack_zgeev(KNM<Complex> *const &A,KN<Complex> *const &vp,KNM<Complex> *const &vectp)
+{
+  intblas nvp =0,zero=0;
+  intblas n= A->N();
+  ffassert(A->M()==n);
+  ffassert(vectp->M()>=n);
+  ffassert(vectp->N()>=n);
+  ffassert(vp->N()>=n);
+  KN<Complex> w(n),vr(n*n),vl(n*n);
+  KNM<Complex> mat(*A);
+  intblas info,lw=n*(n+1)*10;
+  KN<Complex> wk(lw);
+  KN<double> rwk(2*n);
+
+  char N='N',V='V';
+  // lw=1;// to get opt size value 
+  zgeev_(&N,&V,&n, mat,&n, w, vl,&n, vr,&n,wk,&lw,rwk,&info);
+  //  cout << lw << " " << wk[0] << " " << info <<   endl;
+  /* lw=wk[0].real();
+  w.resize(lw);
+  zgeev_(&N,&V,&n, mat,&n, w, vl,&n, vr,&n,wk,&lw,rwk,&info);
+  */
+  if(info)
+    cout << " info =  " << info << endl;
+  if(!info)
+    {
+      int k=0;
+      for(int i=0;i<n;++i)
+        {
+          (*vp)[i]=w[i];
+          if(verbosity>2)
+            cout << "   zgeev: vp "<< i << " : "  << (*vp)[i] << endl;
+	  for(int j=0;j<n;++j)
+              (*vectp)(j,i)=vr[k++];
+          if(verbosity>5)
+            cout << "   zgeev :   " << (*vectp)(':',i) <<endl;
+        }
+    }
+  else
+    {
+      nvp=0;
+      (*vp)=Complex();
+      (*vectp)=Complex();
+    }
+  return nvp;
+}
+
+// VL, 10/02/2010
+long lapack_dggev(KNM<double> *const &A,KNM<double> *const &B,KN<Complex> *const &vpa,KN<double> *const &vpb,KNM<Complex> *const &vectp)
+{
+    intblas nvp =0,zero=0;
+    intblas n=A->N();
+    ffassert(A->M()==n);
+    ffassert(B->M()==n);
+    ffassert(B->N()==n);
+    ffassert(vectp->M()>=n);
+    ffassert(vectp->N()>=n);
+    ffassert(vpa->N()>=n);
+    ffassert(vpb->N()>=n);
+    
+    KN<double> war(n),wai(n),wb(n),vr(n*n),vl(n*n);
+    KNM<double> matA(*A);
+    KNM<double> matB(*B);
+    intblas info,lw=-1;  
+    KN<double> w(1);
+    //char N='N',V='V'; VL: do not compute eigenvectors (if yes, switch with following line)
+    char VL='N',VR='N';
+    
+    dggev_(&VL,&VR,&n,matA,&n,matB,&n,war,wai,wb,vl,&n,vr,&n,w,&lw,&info);
+    lw=w[0];
+    // cout << lw << endl;
+    w.resize(lw);
+    dggev_(&VL,&VR,&n,matA,&n,matB,&n,war,wai,wb,vl,&n,vr,&n,w,&lw,&info);
+    if(info)
+	cout << " info =  " << info << endl;
+    if(!info)
+      {
+	int k=0;
+	for(int i=0;i<n;++i)
+	  {
+	    (*vpa)[i]=Complex(war[i],wai[i]);
+	    (*vpb)[i]=wb[i];
+	    if(verbosity>2)
+		cout << "   dggev: vp "<< i << " : "  << (*vpa)[i] << " ; " << (*vpb)[i] << endl;
+	    if( wai[i] == 0)
+		for(int j=0;j<n;++j)
+		    (*vectp)(j,i)=vr[k++];
+	    else if (  wai[i] >  0)
+	      {
+		int ki= k+n;
+		for(int j=0;j<n;++j)
+		    (*vectp)(j,i)=Complex(vr[k++],vr[ki++]);	      
+	      }
+	    else 
+	      {
+		int kr= k-n;
+		for(int j=0;j<n;++j)
+		    (*vectp)(j,i)=Complex(vr[kr++],-vr[k++]);	      
+	      }
+	    if(verbosity>5)
+		cout << "   dggev :   " << (*vectp)(':',i) <<endl;
+	  }
+      }
+    else
+      {
+	nvp=0;
+	(*vpa)=Complex();
+	(*vectp)=Complex();
+      }
+    return nvp;
+}
+
+// GL, 05/10/2011 (computation of all the eigenvalues and the eigenvectors of a real generalized symmetric-definite eigenproblem, of the form A*x=(lambda)*B*x)
+long lapack_dsygvd(KNM<double> *const &A,KNM<double> *const &B,KN<double> *const &vp,KNM<double> *const &vectp)
+{
+  /*
+    SUBROUTINE DSYGVD( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK, LWORK, IWORK, LIWORK, INFO )
+   *  ITYPE   (input) INTEGER
+   *          Specifies the problem type to be solved:
+   *          = 1:  A*x = (lambda)*B*x
+   *          = 2:  A*B*x = (lambda)*x
+   *          = 3:  B*A*x = (lambda)*x
+   *
+   *  JOBZ    (input) CHARACTER*1
+   *          = 'N':  Compute eigenvalues only;
+   *          = 'V':  Compute eigenvalues and eigenvectors.
+   *
+   *  UPLO    (input) CHARACTER*1
+   *          = 'U':  Upper triangles of A and B are stored;
+   *          = 'L':  Lower triangles of A and B are stored.
+   *
+   *  N       (input) INTEGER
+   *          The order of the matrices A and B.  N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
+   *          On entry, the symmetric matrix A.  If UPLO = 'U', the
+   *          leading N-by-N upper triangular part of A contains the
+   *          upper triangular part of the matrix A.  If UPLO = 'L',
+   *          the leading N-by-N lower triangular part of A contains
+   *          the lower triangular part of the matrix A.
+   *
+   *          On exit, if JOBZ = 'V', then if INFO = 0, A contains the
+   *          matrix Z of eigenvectors.  The eigenvectors are normalized
+   *          as follows:
+   *          if ITYPE = 1 or 2, Z**T*B*Z = I;
+   *          if ITYPE = 3, Z**T*inv(B)*Z = I.
+   *          If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
+   *          or the lower triangle (if UPLO='L') of A, including the
+   *          diagonal, is destroyed.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
+   *          On entry, the symmetric matrix B.  If UPLO = 'U', the
+   *          leading N-by-N upper triangular part of B contains the
+   *          upper triangular part of the matrix B.  If UPLO = 'L',
+   *          the leading N-by-N lower triangular part of B contains
+   *          the lower triangular part of the matrix B.
+   *
+   *          On exit, if INFO <= N, the part of B containing the matrix is
+   *          overwritten by the triangular factor U or L from the Cholesky
+   *          factorization B = U**T*U or B = L*L**T.
+   *
+   *  LDB     (input) INTEGER
+   *          The leading dimension of the array B.  LDB >= max(1,N).
+   *
+   *  W       (output) DOUBLE PRECISION array, dimension (N)
+   *          If INFO = 0, the eigenvalues in ascending order.
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+   *
+   *  LWORK   (input) INTEGER
+   *          The dimension of the array WORK.
+   *          If N <= 1,               LWORK >= 1.
+   *          If JOBZ = 'N' and N > 1, LWORK >= 2*N+1.
+   *          If JOBZ = 'V' and N > 1, LWORK >= 1 + 6*N + 2*N**2.
+   *
+   *          If LWORK = -1, then a workspace query is assumed; the routine
+   *          only calculates the optimal sizes of the WORK and IWORK
+   *          arrays, returns these values as the first entries of the WORK
+   *          and IWORK arrays, and no error message related to LWORK or
+   *          LIWORK is issued by XERBLA.
+   *
+   *  IWORK   (workspace/output) INTEGER array, dimension (MAX(1,LIWORK))
+   *          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
+   *
+   *  LIWORK  (input) INTEGER
+   *          The dimension of the array IWORK.
+   *          If N <= 1,                LIWORK >= 1.
+   *          If JOBZ  = 'N' and N > 1, LIWORK >= 1.
+   *          If JOBZ  = 'V' and N > 1, LIWORK >= 3 + 5*N.
+   *
+   *          If LIWORK = -1, then a workspace query is assumed; the
+   *          routine only calculates the optimal sizes of the WORK and
+   *          IWORK arrays, returns these values as the first entries of
+   *          the WORK and IWORK arrays, and no error message related to
+   *          LWORK or LIWORK is issued by XERBLA.
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  DPOTRF or DSYEVD returned an error code:
+   *             <= N:  if INFO = i and JOBZ = 'N', then the algorithm
+   *                    failed to converge; i off-diagonal elements of an
+   *                    intermediate tridiagonal form did not converge to
+   *                    zero;
+   *                    if INFO = i and JOBZ = 'V', then the algorithm
+   *                    failed to compute an eigenvalue while working on
+   *                    the submatrix lying in rows and columns INFO/(N+1)
+   *                    through mod(INFO,N+1);
+   *             > N:   if INFO = N + i, for 1 <= i <= N, then the leading
+   *                    minor of order i of B is not positive definite.
+   *                    The factorization of B could not be completed and
+   *                    no eigenvalues or eigenvectors were computed.
+   */
+  intblas n=A->N();
+  ffassert(A->M()==n);
+  ffassert(B->M()==n);
+  ffassert(B->N()==n);
+  ffassert(vp->N()>=n);
+  ffassert(vectp->M()>=n);
+  ffassert(vectp->N()>=n);
+  KN<double> war(n),wai(n),wb(n),vr(n*n),vl(n*n);
+  KNM<double> matA(*A),matB(*B);
+  intblas itype=1,info,lw=-1;
+  KN<double> w(1);
+  KN<intblas> iw(1);
+  char JOBZ='V',UPLO='U';
+  
+  dsygvd_(&itype,&JOBZ,&UPLO,&n,matA,&n,matB,&n,*vp,w,&lw,iw,&lw,&info);
+  lw=w[0];
+  w.resize(lw);
+  iw.resize(lw);
+  dsygvd_(&itype,&JOBZ,&UPLO,&n,matA,&n,matB,&n,*vp,w,&lw,iw,&lw,&info);
+  if (info<0)
+     {
+     cout << "   dsygvd: the " << info << "-th argument had an illegal value." << endl;
+     }
+  else if (info>0)
+     {
+     cout << "   dsygvd: DPOTRF or DSYEVD returned an error code." << endl;
+     }
+  else if (info==0)
+     {
+     for (int i=0;i<n;++i)
+        {
+        for (int i=0;i<n;++i)
+           {
+           for (int j=0;j<n;++j)
+              (*vectp)(j,i)=matA(j,i);	      
+           }
+        }  
+     }
+  return info;
+}
+
+// GL,27/09/2011 (singular value decomposition of a rectangular real matrix)
+long lapack_dgesdd(KNM<double> *const &A,KNM<double> *const &U,KN<double> *const &S,KNM<double> *const &V)
+{
+  /*
+    SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, IWORK, INFO )
+   *  JOBZ    (input) CHARACTER*1
+   *          Specifies options for computing all or part of the matrix U:
+   *          = 'A':  all M columns of U and all N rows of V**T are
+   *                  returned in the arrays U and VT;
+   *          = 'S':  the first min(M,N) columns of U and the first
+   *                  min(M,N) rows of V**T are returned in the arrays U
+   *                  and VT;
+   *          = 'O':  If M >= N, the first N columns of U are overwritten
+   *                  on the array A and all rows of V**T are returned in
+   *                  the array VT;
+   *                  otherwise, all columns of U are returned in the
+   *                  array U and the first M rows of V**T are overwritten
+   *                  in the array A;
+   *          = 'N':  no columns of U or rows of V**T are computed.
+   *
+   *  M       (input) INTEGER
+   *          The number of rows of the input matrix A.  M >= 0.
+   *
+   *  N       (input) INTEGER
+   *          The number of columns of the input matrix A.  N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the M-by-N matrix A.
+   *          On exit,
+   *          if JOBZ = 'O',  A is overwritten with the first N columns
+   *                          of U (the left singular vectors, stored
+   *                          columnwise) if M >= N;
+   *                          A is overwritten with the first M rows
+   *                          of V**T (the right singular vectors, stored
+   *                          rowwise) otherwise.
+   *          if JOBZ .ne. 'O', the contents of A are destroyed.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,M).
+   *
+   *  S       (output) DOUBLE PRECISION array, dimension (min(M,N))
+   *          The singular values of A, sorted so that S(i) >= S(i+1).
+   *
+   *  U       (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
+   *          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
+   *          UCOL = min(M,N) if JOBZ = 'S'.
+   *          If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
+   *          orthogonal matrix U;
+   *          if JOBZ = 'S', U contains the first min(M,N) columns of U
+   *          (the left singular vectors, stored columnwise);
+   *          if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
+   *
+   *  LDU     (input) INTEGER
+   *          The leading dimension of the array U.  LDU >= 1; if
+   *          JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.
+   *
+   *  VT      (output) DOUBLE PRECISION array, dimension (LDVT,N)
+   *          If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
+   *          N-by-N orthogonal matrix V**T;
+   *          if JOBZ = 'S', VT contains the first min(M,N) rows of
+   *          V**T (the right singular vectors, stored rowwise);
+   *          if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
+   *
+   *  LDVT    (input) INTEGER
+   *          The leading dimension of the array VT.  LDVT >= 1; if
+   *          JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;
+   *          if JOBZ = 'S', LDVT >= min(M,N).
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
+   *
+   *  LWORK   (input) INTEGER
+   *          The dimension of the array WORK. LWORK >= 1.
+   *          If JOBZ = 'N',
+   *            LWORK >= 3*min(M,N) + max(max(M,N),7*min(M,N)).
+   *          If JOBZ = 'O',
+   *            LWORK >= 3*min(M,N) + 
+   *                     max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).
+   *          If JOBZ = 'S' or 'A'
+   *            LWORK >= 3*min(M,N) +
+   *                     max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)).
+   *          For good performance, LWORK should generally be larger.
+   *          If LWORK = -1 but other input arguments are legal, WORK(1)
+   *          returns the optimal LWORK.
+   *
+   *  IWORK   (workspace) INTEGER array, dimension (8*min(M,N))
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit.
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value.
+   *          > 0:  DBDSDC did not converge, updating process failed.
+   */
+  intblas n=A->N();
+  intblas m=A->M();
+  U->resize(n,n);
+  S->resize(min(n,m));
+  V->resize(m,m);
+  KNM<double> VT(m,m);
+  KN<intblas> iw(8*min(n,m));
+  intblas info,lw=-1;
+  KN<double> w(1);
+  char JOBZ='A';
+  dgesdd_(&JOBZ,&n,&m,*A,&n,*S,*U,&n,VT,&m,w,&lw,iw,&info);
+  lw=w[0];
+  w.resize(lw);
+  dgesdd_(&JOBZ,&n,&m,*A,&n,*S,*U,&n,VT,&m,w,&lw,iw,&info);
+  if (info<0)
+     {
+     cout << "   dgesdd: the " << info << "-th argument had an illegal value." << endl;
+     }
+  else if (info>0)
+     {
+     cout << "   dgesdd: DBDSDC did not converge, updating process failed." << endl;
+     }
+  else if (info==0)
+     {
+     for (int i=0;i<m;++i)
+	for (int j=0;j<m;++j)
+	   (*V)(i,j)=VT(j,i);
+     }
+  return info;
+}
+
+// GL,28/09/2011 (computation of the eigenvalues and eigenvectors of a real symmetric matrix)
+long lapack_dsyev(KNM<double> *const &A,KN<double> *const &vp,KNM<double> *const &vectp)
+{
+  /*
+    SUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )
+   *  JOBZ    (input) CHARACTER*1
+   *          = 'N':  Compute eigenvalues only;
+   *          = 'V':  Compute eigenvalues and eigenvectors.
+   *
+   *  UPLO    (input) CHARACTER*1
+   *          = 'U':  Upper triangle of A is stored;
+   *          = 'L':  Lower triangle of A is stored.
+   *
+   *  N       (input) INTEGER
+   *          The order of the matrix A.  N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
+   *          On entry, the symmetric matrix A.  If UPLO = 'U', the
+   *          leading N-by-N upper triangular part of A contains the
+   *          upper triangular part of the matrix A.  If UPLO = 'L',
+   *          the leading N-by-N lower triangular part of A contains
+   *          the lower triangular part of the matrix A.
+   *          On exit, if JOBZ = 'V', then if INFO = 0, A contains the
+   *          orthonormal eigenvectors of the matrix A.
+   *          If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
+   *          or the upper triangle (if UPLO='U') of A, including the
+   *          diagonal, is destroyed.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  W       (output) DOUBLE PRECISION array, dimension (N)
+   *          If INFO = 0, the eigenvalues in ascending order.
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+   *
+   *  LWORK   (input) INTEGER
+   *          The length of the array WORK.  LWORK >= max(1,3*N-1).
+   *          For optimal efficiency, LWORK >= (NB+2)*N,
+   *          where NB is the blocksize for DSYTRD returned by ILAENV.
+   *
+   *          If LWORK = -1, then a workspace query is assumed; the routine
+   *          only calculates the optimal size of the WORK array, returns
+   *          this value as the first entry of the WORK array, and no error
+   *          message related to LWORK is issued by XERBLA.
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, the algorithm failed to converge; i
+   *                off-diagonal elements of an intermediate tridiagonal
+   *                form did not converge to zero.
+   */
+  intblas n=A->N();
+  ffassert(A->M()==n);
+  ffassert(vectp->N()==n);
+  ffassert(vectp->M()==n);
+  ffassert(vp->N()==n);
+  KNM<double> mat(*A);
+  intblas info,lw=-1;  
+  KN<double> w(1);
+  char JOBZ='V',UPLO='U';
+  dsyev_(&JOBZ,&UPLO,&n,mat,&n,*vp,w,&lw,&info);
+  lw=w[0];
+  w.resize(lw);
+  dsyev_(&JOBZ,&UPLO,&n,mat,&n,*vp,w,&lw,&info);
+  if (info<0)
+     {
+     cout << "   dsyev: the " << info << "-th argument had an illegal value." << endl;
+     }
+  else if (info>0)
+     {
+     cout << "   dsyev: the algorithm failed to converge." << endl;
+     }
+  else if (info==0)
+     {
+     *vectp=mat;
+     }
+  return info;
+}
+
+template<class T>
+class Inverse{ public:
+  T  t;
+  Inverse( T  v)
+   : t(v) {}
+  template<class TT> Inverse( TT  v) : t(v) {}  
+  template<class TT> Inverse( TT * v) : t(*v) {}  
+  operator const T & () const {return t;}
+};
+
+template<class T>
+class Mult{ public:
+    T  a;bool ta;
+  T  b;bool tb;
+  Mult( T  aa,T bb)
+    : a(aa),b(bb),ta(0),tb(0) {}
+    // Transpose<
+  Mult( Transpose<T>  aa,T bb)   
+    : a(aa),b(bb),ta(1),tb(0) {}
+  Mult( Transpose<T>  aa,Transpose<T> bb)   
+    : a(aa),b(bb),ta(1),tb(1) {}
+    Mult( T  aa,Transpose<T> bb)   
+    : a(aa),b(bb),ta(1),tb(1) {}
+    
+};
+
+template<class K>
+class OneBinaryOperatorRNM_inv : public OneOperator { public:  
+    OneBinaryOperatorRNM_inv() 
+      : OneOperator( atype< Inverse< KNM<K>* > >(),atype<KNM<K> *>(),atype<long>()) {}
+  E_F0 * code(const basicAC_F0 & args) const 
+  { Expression p=args[1];
+    if ( ! p->EvaluableWithOutStack() ) 
+      { 
+	bool bb=p->EvaluableWithOutStack();
+	cout << "  Error exposant ??? " <<  bb << " " <<  * p <<  endl;
+	CompileError(" A^p, The p must be a constant == -1, sorry");}
+    long pv = GetAny<long>((*p)(0));
+    if (pv !=-1)   
+      { char buf[100];
+	sprintf(buf," A^%ld, The pow must be  == -1, sorry",pv);
+	CompileError(buf);}     
+    return  new E_F_F0<Inverse< KNM<K>* > ,KNM<K> *>(Build<Inverse< KNM<K>* > ,KNM<K> *>,t[0]->CastTo(args[0])); 
+  }
+};
+
+
+template <int INIT>
+KNM<R>* Solve(KNM<R>* a,Inverse<KNM<R >*> b) 
+{
+  /*
+    SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
+   *  N       (input) INTEGER
+   *          The number of linear equations, i.e., the order of the
+   *          matrix A.  N >= 0.
+   *
+   *  NRHS    (input) INTEGER
+   *          The number of right hand sides, i.e., the number of columns
+   *          of the matrix B.  NRHS >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the N-by-N coefficient matrix A.
+   *          On exit, the factors L and U from the factorization
+   *          A = P*L*U; the unit diagonal elements of L are not stored.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  IPIV    (output) INTEGER array, dimension (N)
+   *          The pivot indices that define the permutation matrix P;
+   *          row i of the matrix was interchanged with row IPIV(i).
+   *
+   *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
+   *          On entry, the N-by-NRHS matrix of right hand side matrix B.
+   *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
+   *
+   *  LDB     (input) INTEGER
+   *          The leading dimension of the array B.  LDB >= max(1,N).
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
+   *                has been completed, but the factor U is exactly
+   *                singular, so the solution could not be computed.
+   *
+   */
+  typedef double R;
+  integer info;
+  KNM<R> B(*b);
+  integer  n= B.N();
+  KN<integer> p(n);
+  ffassert(B.M()==n);
+  if(INIT)
+      a->init(n,n);
+   else
+    a->resize(n,n);
+  *a=0.;
+  for(int i=0;i<n;++i)
+    (*a)(i,i)=(R) 1;;
+
+  dgesv_(&n,&n,B,&n,p,*a,&n,&info);
+  if(info) cerr << " error:  dgesv_ "<< info << endl;
+  return a;
+}
+
+
+// Template interface 
+inline int gemm(char *transa, char *transb, integer *m, integer *
+	   n, integer *k, double *alpha, double *a, integer *lda, 
+	   double *b, integer *ldb, double *beta, double *c, integer 
+	   *ldc) {
+   return  dgemm_(transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc);
+}
+inline int gemm(char *transa, char *transb, integer *m, integer *
+		 n, integer *k, Complex *alpha, Complex *a, integer *lda, 
+		 Complex *b, integer *ldb, Complex *beta, Complex *c, integer 
+		 *ldc) {
+    return  zgemm_(transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc);
+}
+
+
+template<class R,bool init, int ibeta> 
+KNM<R>* mult(KNM<R >* a,const KNM_<R> & A,const KNM_<R> & B) 
+{ // C=A*B 
+   
+    R alpha=1.,beta=R(ibeta);
+    char tA, tB;
+    if(init) a->init();
+    intblas N= A.N();
+    intblas M=B.M();
+    intblas K=A.M();
+    KNM<R> & C= *a;
+    C.resize(N,M); 
+    ffassert(K==B.N());
+    R *A00=&A(0,0), *A10= &A(1,0), *A01= &A(0,1); 
+    R *B00=&B(0,0), *B10= &B(1,0), *B01= &B(0,1); 
+    R *C00=&C(0,0), *C10= &C(1,0), *C01= &C(0,1); 
+    intblas lsa=A10-A00 ,lsb=B10-B00,lsc=C10-C00;
+    intblas lda=A01-A00 ,ldb=B01-B00,ldc=C01-C00;
+    if(verbosity>10) {
+	cout << lsa << " " << lsb << " "<< lsc << " init " << init <<  endl;
+	cout << lda << " " << ldb << " "<< ldc << endl;	
+    }
+    tA=lda==1?'T':'N';
+    tB=ldb==1?'T':'N';
+    
+    if(lda==1) lda=lsa;
+    if(ldb==1) ldb=lsb;
+    if(beta==0.)
+     C=R(); 
+#ifdef XXXXXXXXXXXXXX
+    
+    for(int i=0;i<N;++i)
+	 for(int j=0;j<M;++j)
+	      for(int k=0;k<K;++k)
+		  C(i,j) += A(i,k)*B(k,j)  ;
+#else    
+    gemm(&tB,&tA,&N,&M,&K,&alpha,A00,&lda,B00,&ldb,&beta,C00,&ldc);
+#endif
+    return a;
+    /*
+     The Fortran interface for these procedures are:
+     SUBROUTINE xGEMM ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC )
+     where TRANSA and TRANSB determines if the matrices A and B are to be transposed.
+     M is the number of rows in matrix A and C. N is the number of columns in matrix B and C. 
+     K is the number of columns in matrix A and rows in matrix B. 
+     LDA, LDB and LDC specifies the size of the first dimension of the matrices, as laid out in memory;
+     meaning the memory distance between the start of each row/column, depending on the memory structure (Dongarra et al. 1990).
+     */
+}
+template<class R,bool init, int ibeta> 
+KNM<R>* mult(KNM<R >* a,Mult<KNM<R >*> bc) 
+{
+    if( (bc.ta == 0) && (bc.tb == 0))
+     return  mult<R,init,ibeta>(a,*bc.a,*bc.b) ;
+    else if((bc.ta == 1 )&& (bc.tb == 0))
+     return  mult<R,init,ibeta>(a,bc.a->t(),*bc.b) ;
+    else if((bc.ta == 0) && (bc.tb == 1))
+	return  mult<R,init,ibeta>(a,*bc.a,bc.b->t()) ;
+    else if((bc.ta == 1) && (bc.tb == 1))
+	return  mult<R,init,ibeta>(a,bc.a->t(),bc.b->t()) ;
+    else
+        // should never happen
+        return NULL;
+}
+
+template <int INIT>
+KNM<Complex>* SolveC(KNM<Complex>* a,Inverse<KNM<Complex >*> b) 
+{
+  /*
+    SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
+   *  N       (input) INTEGER
+   *          The number of linear equations, i.e., the order of the
+   *          matrix A.  N >= 0.
+   *
+   *  NRHS    (input) INTEGER
+   *          The number of right hand sides, i.e., the number of columns
+   *          of the matrix B.  NRHS >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the N-by-N coefficient matrix A.
+   *          On exit, the factors L and U from the factorization
+   *          A = P*L*U; the unit diagonal elements of L are not stored.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  IPIV    (output) INTEGER array, dimension (N)
+   *          The pivot indices that define the permutation matrix P;
+   *          row i of the matrix was interchanged with row IPIV(i).
+   *
+   *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
+   *          On entry, the N-by-NRHS matrix of right hand side matrix B.
+   *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
+   *
+   *  LDB     (input) INTEGER
+   *          The leading dimension of the array B.  LDB >= max(1,N).
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
+   *                has been completed, but the factor U is exactly
+   *                singular, so the solution could not be computed.
+   *
+   */
+  typedef Complex R;
+  integer info;
+  KNM<R> B(*b);
+  integer   n= B.N();
+  KN<integer> p(n);
+  ffassert(B.M()==n);
+  if(INIT)
+     a->init(n,n);
+  else
+     a->resize(n,n);
+  *a=0.;
+  for(int i=0;i<n;++i)
+    (*a)(i,i)=(R) 1;;
+
+  zgesv_(&n,&n,(R*) B,&n,p, (R*) *a,&n,&info);
+  if(info) cerr << " error:  zgesv_ "<< info << endl;
+  return a;
+}
+
+
+template<class R,class A,class B> R Build2(A a,B b) {
+    return R(a,b);
+}
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+
+  if( map_type.find(typeid(Inverse<KNM<double >* >).name() ) == map_type.end() )
+    {
+      if(verbosity) 
+	cout << " Add lapack interface ..." ;
+      Dcl_Type< Inverse<KNM<double >* > > ();
+      Dcl_Type< Inverse<KNM<Complex >* > > ();
+      Dcl_Type< Mult<KNM<Complex >* > > ();
+      Dcl_Type< Mult<KNM<double >* > > ();
+      
+      TheOperators->Add("^", new OneBinaryOperatorRNM_inv<double>());
+      TheOperators->Add("*", new OneOperator2< Mult< KNM<double>* >,KNM<double>*,KNM<double>*>(Build2));
+      TheOperators->Add("*", new OneOperator2< Mult< KNM<Complex>* >,KNM<Complex>*,KNM<Complex>*>(Build2));
+      
+      TheOperators->Add("^", new OneBinaryOperatorRNM_inv<Complex>());
+      TheOperators->Add("=", new OneOperator2<KNM<double>*,KNM<double>*,Inverse<KNM<double >*> >( Solve<0>) );
+      TheOperators->Add("=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Inverse<KNM<Complex >*> >( SolveC<0>) );
+      TheOperators->Add("<-", new OneOperator2<KNM<double>*,KNM<double>*,Inverse<KNM<double >*> >( Solve<1>) );
+      TheOperators->Add("<-", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Inverse<KNM<Complex >*> >( SolveC<1>) );
+        
+      TheOperators->Add("=", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,false,0> ) );
+      TheOperators->Add("=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,false,0> ) );
+      
+      TheOperators->Add("+=", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,false,1> ) );
+      TheOperators->Add("+=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,false,1> ) );
+      
+      TheOperators->Add("-=", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,false,-1> ) );
+      TheOperators->Add("-=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,false,-1> ) );
+      
+      TheOperators->Add("<-", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,true,0> ) );
+      TheOperators->Add("<-", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,true,0> ) );
+      
+      Global.Add("inv","(",new  OneOperator1<long,KNM<double>*>(lapack_inv));  
+      Global.Add("inv","(",new  OneOperator1<long,KNM<Complex>*>(lapack_inv));
+        
+      Global.Add("dgeev","(",new  OneOperator3_<long,KNM<double>*,KN<Complex>*,KNM<Complex>*>(lapack_dgeev));
+      Global.Add("zgeev","(",new  OneOperator3_<long,KNM<Complex>*,KN<Complex>*,KNM<Complex>*>(lapack_zgeev));
+        // add FH
+       Global.Add("geev","(",new  OneOperator3_<long,KNM<double>*,KN<Complex>*,KNM<Complex>*>(lapack_dgeev));
+       Global.Add("geev","(",new  OneOperator3_<long,KNM<Complex>*,KN<Complex>*,KNM<Complex>*>(lapack_zgeev));
+        
+      Global.Add("dggev","(",new  OneOperator5_<long,KNM<double>*,KNM<double>*,KN<Complex>*,KN<double>*,KNM<Complex>*>(lapack_dggev));
+      Global.Add("dsygvd","(",new  OneOperator4_<long,KNM<double>*,KNM<double>*,KN<double>*,KNM<double>*>(lapack_dsygvd));
+      Global.Add("dgesdd","(",new  OneOperator4_<long,KNM<double>*,KNM<double>*,KN<double>*,KNM<double>*>(lapack_dgesdd));
+      Global.Add("dsyev","(",new  OneOperator3_<long,KNM<double>*,KN<double>*,KNM<double>*>(lapack_dsyev));
+    }
+  else
+    if(verbosity)
+      cout << "( load: lapack <=> fflapack , skeep ) ";
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/ffnewuoa.cpp b/examples++-load/ffnewuoa.cpp
new file mode 100644
index 0000000..612e66f
--- /dev/null
+++ b/examples++-load/ffnewuoa.cpp
@@ -0,0 +1,193 @@
+//ff-c++-cpp-dep: newuoa.f
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "Mesh3dn.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+
+typedef int integer;
+typedef int logical;
+
+
+typedef void  (*typecalfunc)( integer *, double *, double *f, void * );
+
+#define F77newuoa newuoa_
+
+extern "C" {
+double F77newuoa(integer *N, integer *NPT, double *x , double * rhob, double *rhog,
+		     integer *iprint, integer *maxfun,
+		     double *w, void * iwf,  typecalfunc  calfun);
+}
+
+
+void   calfun( integer * n, double * x, double *f, void * t);
+
+ 
+//template<class R>
+extern Block *currentblock;
+
+typedef double R;
+void   calfun( integer * n, double * x, double *f, void * t);
+class OptimNewoa : public OneOperator 
+{
+public:
+  typedef KN<R> Kn;
+  typedef KN_<R> Kn_;
+   const int cas;
+
+
+class ffcalfunc {  //   to call the freefem function .. J 
+    public:
+	Stack stack;
+	Expression JJ,theparame;
+    
+      ffcalfunc(Stack s,Expression JJJ,Expression epar)
+        : stack(s),JJ(JJJ), theparame(epar) {}
+    
+	double J(Kn_  x) const 
+	{
+	     KN<double> *p=GetAny<KN<double> *>( (*theparame)(stack) );
+	    *p=x;
+	    double  ret= GetAny<R>( (*JJ)(stack));
+	    WhereStackOfPtr2Free(stack)->clean();
+	return  ret; }
+	
+    }; 
+  
+
+  class E_newoa: public E_F0mps { public:
+    const int cas;
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =4;
+    Expression nargs[n_name_param];
+    Expression X;
+    C_F0 inittheparam,theparam,closetheparam; 
+    Expression JJ;
+    long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+      
+ 
+      
+    E_newoa(const basicAC_F0 & args,int cc) :
+      cas(cc)
+    {
+      int nbj= args.size()-1;
+      Block::open(currentblock); // make a new block to 
+      X = to<Kn*>(args[nbj]);
+      C_F0 X_n(args[nbj],"n");
+      //  the expression to init the theparam of all 
+      inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+      theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+      args.SetNameParam(n_name_param,name_param,nargs);
+      const  Polymorphic * opJ=0;
+      if (nbj>0)
+	{
+	  opJ=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+	  assert(opJ);
+	}      
+      JJ= to<R>(C_F0(opJ,"(",theparam));
+      closetheparam=currentblock->close(currentblock);   // the cleanning block expression 
+    }
+    
+    virtual AnyType operator()(Stack stack)  const
+    {
+      double cost = 1e100;
+      WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005 
+      Kn &x = *GetAny<Kn *>((*X)(stack));	
+      long n=x.N();	
+      double rhobeg=arg(0,stack,1E-6); // not used ....
+      double rhoend=arg(1,stack,2.); // not used ....
+      long maxfun=arg(2,stack,1000L); // bof bof 
+      long npt=arg(3,stack,n*2L+1L); // bof bof 
+      long iprint = verbosity;	
+      ffcalfunc ffJ(stack,JJ,theparam);
+      int lw =   (npt+13)*(npt+n)+3*n*(n+3)/2;
+      KN<double> w(lw);
+      integer N=n,NPT=npt,IPRINT=iprint,MAXFUN=maxfun;
+      cost= F77newuoa(&N,&NPT,(double *)x,&rhobeg,&rhoend,&IPRINT,&MAXFUN,(double *)w,(void *) &ffJ, calfun);
+      closetheparam.eval(stack); // clean memory 
+      WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+      return cost; //SetAny<long>(0);  Modif FH  july 2005       
+    }    
+    
+    
+    operator aType () const { return atype<double>();}         
+    
+  };
+  
+  
+  
+  E_F0 * code(const basicAC_F0 & args) const {
+    return new E_newoa(args,cas);}
+  
+  OptimNewoa(int c) :   OneOperator(atype<double>(),
+				    atype<Polymorphic*>(),
+				    atype<KN<R> *>()),cas(c){}
+      
+};
+
+basicAC_F0::name_and_type  OptimNewoa::E_newoa::name_param[]= 
+  {
+    {  "rhobeg", &typeid(double)  },
+    {  "rhoend", &typeid(double)  },
+    { "maxfun",&typeid(long) },
+    { "npt",&typeid(long) }
+  };
+
+void   calfun( integer * n, double * x, double *f, void * t)
+{
+  OptimNewoa::ffcalfunc * tt=static_cast<OptimNewoa::ffcalfunc *>(t); 
+  *f=tt->J(KN_<double>(x,*n));
+  if(verbosity>20)  cout << " F= " << * f << endl;
+}
+
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init()  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+{
+  Global.Add("newuoa","(",new OptimNewoa(1));  //  j + dJ
+
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/ffnewuoa.edp b/examples++-load/ffnewuoa.edp
new file mode 100644
index 0000000..14b3567
--- /dev/null
+++ b/examples++-load/ffnewuoa.edp
@@ -0,0 +1,105 @@
+/*  README NEWUOA:
+     This is the Fortran version of NEWUOA. Its purpose is to seek
+the least value of a function F of several variables, when derivatives
+are not available, where F is specified by the user through a subroutine
+called CALFUN. The algorithm is intended to change the variables to values
+that are close to a local minimum of F. The user, however, should assume
+responsibility for finding out if the calculations are satisfactory, by
+considering carefully the values of F that occur. The method is described
+in the report "The NEWUOA software for unconstrained optimization without
+derivatives", which is available on the web at www.damtp.cam.ac.uk, where
+you have to click on Numerical Analysis and then on Reports, the number
+of the report being NA2004/08. Let N be the number of variables. The main
+new feature of the method is that quadratic models are updated using only
+about NPT=2N+1 interpolation conditions, the remaining freedom being taken
+up by minimizing the Frobenius norm of the change to the second derivative
+matrix of the model.
+
+     The new software was developed from UOBYQA, which also forms quadratic
+models from interpolation conditions. That method requires NPT=(N+1)(N+2)/2
+conditions, however, because they have to define all the parameters of the
+model. The least Frobenius norm updating procedure with NPT=2N+1 is usually
+much more efficient when N is large, because the work of each iteration is
+much less than before, and in some experiments the number of calculations
+of the objective function seems to be only of magnitude N.
+
+     The attachments in sequence are a suitable Makefile, followed by a main
+program and a CALFUN routine for the Chebyquad problems, in order to provide
+an example for testing. Then NEWUOA and its five auxiliary routines, namely
+NEWUOB, BIGDEN, BIGLAG, TRSAPP and UPDATE, are given. Finally, the computed
+output that the author obtained for the Chebyquad problems is listed.
+
+     The way of calling NEWUOA should be clear from the Chebyquad example
+and from the comments of that subroutine. It is hoped that the software will
+be helpful to much future research and to many applications. There are no
+restrictions on or charges for its use. If you wish to refer to it, please
+cite the DAMTP report that is mentioned above, which has been submitted for
+publication in the proceedings of the 40th Workshop on Large Scale Nonlinear
+Optimization (Erice, Italy, 2004).
+
+December 16th, 2004                    M.J.D. Powell (mjdp at cam.ac.uk)
+*/
+
+load "ffnewuoa"
+/*
+      SUBROUTINE CALFUN (N,X,F,IWF)
+      IMPLICIT REAL*8 (A-H,O-Z)
+      DIMENSION X(*),Y(10,10),IWF(*)
+      DO 10 J=1,N
+      Y(1,J)=1.0D0
+   10 Y(2,J)=2.0D0*X(J)-1.0D0
+      DO 20 I=2,N
+      DO 20 J=1,N
+   20 Y(I+1,J)=2.0D0*Y(2,J)*Y(I,J)-Y(I-1,J)
+      F=0.0D0
+      NP=N+1
+      IW=1
+      DO 40 I=1,NP
+      SUM=0.0D0
+      DO 30 J=1,N
+   30 SUM=SUM+Y(I,J)
+      SUM=SUM/DFLOAT(N)
+      IF (IW .GT. 0) SUM=SUM+1.0D0/DFLOAT(I*I-2*I)
+      IW=-IW
+   40 F=F+SUM*SUM
+      RETURN
+      END 
+
+*/
+int N=2;
+real[int,int] Y(N+1,N);
+real[int] X(N);
+func real J(real[int] & X)
+{
+  Y(0,:)=1.;
+  Y(1,:)=2.*X;
+  for(int i=2;i<=N;++i)
+    for(int j=0;j<N;++j)
+      Y(i,j) = Y(1,j) * Y(i-1,j)- Y(i-2,j);
+
+  real f=0;
+  int np=N+1,iw=1;
+  for(int i=0;i<=N;i++)
+    {
+      real s=Y(i,:).sum/N;
+      int i1=i+1;
+      if(iw>0) s+= 1./(i1*i1-2.*i1);
+      iw=-iw;
+      f += s*s;
+    }
+  return 2.14+f;
+}
+real delta=1;
+mesh Th=square(30,30,[(x-0.5)*delta,(y-0.5)*delta]);
+fespace Vh(Th,P1);
+Vh u;
+for(int i=0;i<Th.nv;++i)
+  {X[0]=Th(i).x;X[1]=Th(i).y;
+    u[][i]=J(X);
+  }
+plot(u,wait=1);
+
+for(int i=0;i<N;++i)
+  X[i]=(i+1)/(N+1.);
+real mincost=newuoa(J,X,rhobeg=2*X[0],rhoend=1e-6,npt=2*N+1);
+cout << " min " << mincost << "  at :" << X << endl;
\ No newline at end of file
diff --git a/examples++-load/ffrandom.cpp b/examples++-load/ffrandom.cpp
new file mode 100644
index 0000000..c1c9be3
--- /dev/null
+++ b/examples++-load/ffrandom.cpp
@@ -0,0 +1,104 @@
+// Example C++ function "add random function ", dynamically loaded into "load.edp"                                                     
+// ---------------------------------------------------------------------                                                     
+// $Id$                                                              
+
+#include "config.h"
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+
+#include <iostream>
+#include <cstdlib>
+#include <fstream>
+#include <ctime>
+
+// FFCS: random() and srandom() do not seem to be available in MinGW
+#ifdef WIN32
+#define random rand
+#define srandom srand
+#endif
+
+unsigned long good_seed()
+{
+  unsigned long random_seed,  random_seed_a,random_seed_b;
+  std::ifstream file ("/dev/random", std::ios::binary);
+  if (file.is_open())
+    {
+      unsigned long memblock[10];
+      size_t size = sizeof(int);
+      file.read ((char*) (void *) memblock, size);
+      file.close();
+      random_seed_a = memblock[0];
+    }// end if
+  else
+    {
+      random_seed_a = 0;
+    }
+  random_seed_b = std::time(0);
+  random_seed = random_seed_a xor random_seed_b;
+  if(verbosity>1)
+  cout << " good_seed =" << random_seed << endl;
+  return random_seed;
+} // end good_seed()
+
+
+template<class R>
+class  OneOperator_0 : public OneOperator {
+  class E_F0_F :public  E_F0mps { public:
+    typedef  R (*func)( ) ; 
+    func f;
+    E_F0_F(func ff)  : f(ff) {}
+    AnyType operator()(Stack )  const {return SetAny<R>( f()) ;}  
+    operator aType () const { return atype<R>();} 
+
+  };
+
+  typedef  R (*func)() ; 
+  func  f;
+public: 
+  E_F0 * code(const basicAC_F0 & ) const 
+  { return  new E_F0_F(f);} 
+  OneOperator_0(func  ff): OneOperator(map_type[typeid(R).name()]),f(ff){}
+};
+
+// FFCS: rand() wants an int on Win32 and Win64, so we need to have a new function "long ffrandom()" to create the OneOperator
+// object which requires longs (and the MinGW compiler (g++ 4.5) refuses to compile if OneOperator and the underlying function do
+// not have the same type). FFCS patched this source with "long ffrandom(){return random();}" but FF now comes with
+// "genrand_int31()".
+
+#ifdef WIN32
+
+void init_by_array(unsigned long init_key[], int key_length);
+long genrand_int31(void);
+void init_genrand(unsigned long);
+//  hach for window ... F. HEcht 
+long ffsrandom(long  s) { init_genrand( (unsigned int ) s); return 0;}
+long ffrandom() { return genrand_int31();}
+long ffsrandomdev() { 
+  init_genrand(good_seed());
+  return 0;}
+#else 
+
+long ffsrandom(long  s) { srandom( (unsigned int ) s); return 0;}
+long ffrandom(){return random();}
+long ffsrandomdev() { 
+#ifdef HAVE_SRANDOMDEV
+  srandomdev(); 
+#else
+  srandom(good_seed());
+#endif
+
+return 0;}
+
+#endif
+
+void init(){
+  Global.Add("srandomdev","(",new OneOperator_0<long>(ffsrandomdev));
+  Global.Add("srandom","(",new OneOperator1<long>(ffsrandom));
+  Global.Add("random","(",new OneOperator_0<long>(ffrandom));
+}
+LOADFUNC(init); 
+/* These real versions are due to Isaku Wada, 2002/01/09 added */
+
diff --git a/examples++-load/ffrandom.edp b/examples++-load/ffrandom.edp
new file mode 100644
index 0000000..18247ea
--- /dev/null
+++ b/examples++-load/ffrandom.edp
@@ -0,0 +1,15 @@
+load "ffrandom"
+srandomdev();  
+//  warning under window this
+// change the seed by  randinit(random()) ) so all
+// freefem++ random function are change..
+
+cout << random() << endl;
+cout << random() << endl;
+cout << random() << endl;
+srandom(10);
+cout << random() << endl;
+cout << random() << endl;
+cout << random() << endl;
+
+
diff --git a/examples++-load/fig.pgm b/examples++-load/fig.pgm
new file mode 100644
index 0000000..979018b
--- /dev/null
+++ b/examples++-load/fig.pgm
@@ -0,0 +1,150 @@
+P5
+#AppleMark
+
+240 316
+255
+������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ [...]
+��������������������������������������������������������������������������������������������������������������������jW@>.)//76?>DRu������o|zT��^jO}������������������������������������������������������������������������dTLJC?DA>;+7>3
�������������������������������������������������������������������������������������������������������������wokjf`[]M<21" #&)6CCA]����}o�w\ssc`^R������������������������������������������������������������������������|jTLCBIHDB67=-

"�������� [...]

'681&

"=JQU-)*&+I��{������������������������������������������������������������������������������thMM?���������������������������������������������������������������������������������������zxwn\CEIPTj~vj[K`F:,0/()#&
,YP8

)/HPX5-!*C����������������������������������������������������������������������������������peR������������������������������������������������������������������������������������yqytlc\9GQcv�����oNIH;/+,()$

 #

+"A]`&&:F84$-X����������������������������������������������������������������������������������|i�����������������������������������������������������������������������������������wutmXRSRTy����}`dME:+2+$"!





%+$
$0SV9

*457!$.{����������������������������������������������������������������������������������|������������������������������������������������������������{����������������������zprdVSRXr���r[[f\WME94,





#!--+ 
!4.,:RF

)1*%
);~��������������������������������������������������������������������������������������������������������������������������������������~~��������������������������szjdZc}���ָ�WGDKmJIG=@'#
@)8?4!$/)+68">K:$


&)-!&f{�������������������������������������������������������������������������������������������������������������������������������������|�}��~���������������������}yth�x�����OIQ^�T8/*!&+% 



);9?N>'1;=1&I;4D<-$,+*
 * .
1p������������������������������������������������������������������������������������������������������������������������������������{��{�|�����~}||������������}{q�}�����jDVaLcek`Q0++%$
"".TLG\C,,OQ<(FNFG3--A.,
$)5%F������������������������������������������������������������������������������������������������������������������������������������~}|��x}��z��v|}{����������yu���������W at K]h}��rZK;0)(&%!&





%`kPU=?/<cE1M`4B5,-H9:
$(3
.g�������������������������������������������������������������������������������������������������������������������������~�}�������|{{���~�����{||�����u���~����䴛���mUPK^dtsu[SE<5''%$"


4�eggFI$Sm4;BH5<3
$D=#
2/I������������������������������������������������������������������������������������������������������������������������}�������{~�z��~|y���}|u}||���w�����������n\iVKQOVlbb\O;270$(


#89�waZTB.QN* [...]
W[/+
!+e�����������������������������������������������������������������������������[K������������������������������������z�}��}����~��~|��}���~�}|y}�~�����zpat~����jfg`hbXW\YB3HXD53*)+




4ZGAJUrAA(E~8@>531&�9/'
#-U����������������������������������������������������������������������������pYC�������������������������~}������}����|�~����|}{{�y~�����~|}x{}}�����sqbak����gXjmnhdM\VHAAZC53.(%'!)%


(7Onf=7X^10&P[02(/>6[7"#!)<Ub~ [...]
*&)&089<Wu������������������������������������������������yu������������������n������������������������������������������������~�������~~|x{y}|}|yoPG]\n������qfVeh������������mq�ZlSE>58692,'3,')$)%&&&&"&"'('%
&QKEBH')


$
!&/20+9Ojz���������������������������������������������pe��y���������������������������������������������������������������{z�����}�~z}��~�}~z{vra[bhpx}p�y{bSVGd}���������ǥ����dep`YIGA@?94/1.---*,&'$#('$%(#"(FCK=<(
!

	!

+.+06Ou��������������������������������������������bf��~���������������������������������z������������������|��������~qtw���|}zz��~����{rnh_kirw|owmWQVTRMh�v�������˜�����n{aULJFE9A6625111.)*(((&++,+*&"%
7;E;4.(


! !&532-*Qw������������������������������������������lh��������������������������������~zz|~�����������������}���������xlgfrzx~~~w}�~~��}ud]alzskm}s^XEEUTPWaml[fv�������{aUFD at BG;=F,34422/--.-11-,/*0.-)''34H=0('




*6127=c�����������������������������������������h��}����������������������������{~x�y������������������������}|}znbYVfstw||{~�{z�}vtg_bhmpsx��gMDGOQLIT\]eg�����͹���j^O<A>@7JR5<237764223412620.1232*-&):/5]*)




 $/5;=:ay����������������������������������������m��������������������������������}�����������z��~~x|�x���{�����lVPKNrdgu�}zzz{zzn`_ad}n��woPUVSXPOdgjsv|��}iJn��m^WJE?93=;EK=>969?A:69868<85721,-1//-3381O/*($





+>@A,Vr����������������w���������������������v���������������������������~�����~��������x}}z||��}~}}~}y~�}�`VLH:XY[g|~{vx{|yxZd`bw���sjWY]^`Z^hnfi^nnkfUYazjKKLI:;>63<EGGFGFDBED@=9886;454245//2/4),,55G $&



#DC86>m��������������rcq�wt��������������}r�wq������������������������{����|����������|}�{}~~}~~~y~|�|~}zfRDDFDSM`uxmpv�tnTL^z����nVCLcef`ok]`_�eb_Y���vCI at ADIHGJGNWXSIDJEJ@DB<6655952/23;858;82-$/5?/%#








&<B7=Kry������������|eKTcnw`Qj�������������n�vs���������������������������~���������~�}y{|yyx~�~y���~|�ztX/4UJGEThi\[lv�zjWd~�����nd�`omllb^Qgroilhy{hmwjl�|�w[jZEMZd^JJ\hLEJDDI;4561-.99<>;8<::2)$-6.$!8
+




+

6G4=Gn������������kG8M]`QEb�������������h[�{p�������������������������|�����}������{�}�}|y}{|w|�}��������w[@7<V8:EDQJ@\q�vnqy���ͪ�w��irg`hZRX\\fn��rq��������qi]WVdplkP\�tNMTMF?5-56867=?GEBAAA;80(+')&$3









+3?9GQp~����������}jI5QMSB1Ugdi|���������|Y�}k�������������������������������~�����~��}ws~x}{{�}������~��{cK4*H012897=Tkx{sm�����~vxvxo`SZ[PJUe_}�xjmn����zwjg`\h�pldXid^ZTOJA8326:=ABDDGE at BA==9/-,!$&
)

+








 0H?HMo���������um`M<IOTJCBH=Piw~��������a�~l�����������������������}��|�������������|yz}y}{}�}��}}~}z}���we;.(/'(,-23Eu{}po���Ҫ�pqwu��cSTVQQVoqs|yp�������ychagjxmqeX]_YVYKGA<:6:7>AHJEJGEE@?;=:1-(%  "(1















,T;GXv��������dOSIC>URJK@=:<\it��������f}m��������������������~������������}��{���uy||z{~z�~}~~{~����~��h=-%*(&",21L�vsq����ˬ�vw���wYZSQXTblvn������������x��|��ujbeX\QMOIF;>>>A=FLGFKFGC>;<73/+'% "#9












 BH^R[uyw�����gGBKDBMCFIF;6:j`h{������m��v�����������������������������������~��}x|{y}w~�{�}{�~���������tD0)*&
(26Lddg~�����������l]aW\[`q����������������}����zjebYS]ZOIGEAEABCADCB><>9<:314.)*'' 
0













'#+DM]Mgky~���vbG4<QKO?AJF=<5VVTny����onz~�����������������������������{�������~|y{yyv{~���~������������{\7)&$#&'58FX[z������z�����zmmsbpq�������������~�{���oke_\cif\OOLFHHEABC?;896930121/,-+'$

 






	

+





&"6D[[fhnvywxt\F<=@FIF?BC@>?COMdssyw��ih|~�����������������������������~�����~}�{yywwsz���������x}���������d;.&%,(-5<Q[e��������������q�~������������Ⱦ����������}�unde^prg\ZWOQNNMIJB>::/331110,./.'##






+


+





+/:LTV`elqonmaS@?DAEHA>9=;;>DKWjsu_u�cj�������������������������������~��}}z|xu{~|x�����~��}gz���������e>3*'0/09<[U~����ʜ������������������������̞���������wrk]nu|~wukf`^WYV]ZMMMJEB376652231/3'&" 

+


+









-(9DMFOZhnqmijTHEFDDFQA<8234;GOgjmad|nduuw������������������������������}~ywuwxv{xw{��~��~�vedu��������iJ9,)0.7<@S`����Ƥ�������������������������ѿж�������ddmmsz{���oh_]XWZ[\PQTOLLF?<?>=95715-$'











+'15<C=;Nbde_]XZG at IFCMTH?845/34CO_`YTji^zxn���������������������������z|��{wz~zwwwvz~t~��{x~|wtwncGSx������dK41.,/6=GR`����ϩ���ͬ���������������������گ�������p[Wlnv}v���m]\VWV[TSQORSRRKJ=DFE??<;:1,($!!!









!/<7:83 at ZURTTTSEDFGIWSR;72.+-119HKMTaYS~�t��������������������������|}~�{zxxwyxy{x~�}udtx}{wpa8Frmm����v[J3501./>KXr�����Ƶ���������������������л��аÕ�����aXSp{zph�~tjd\VPTXPYWQQVS`TOONPKD>@?<6412-#
	








.:<;,+:JFCIKOAF:BCDMSM>81&#$.1+97ATudZtwy��������������������}�����}{{~|{|yyy{vsu~~w}tr^iy�|{qaP5ekc��~w{[A8612.4;G\y���������������������������Ǯ��Ϯ�������l^glpusnpuoliaUUTSZYY[WWTVSQRLNRJHEC>?:6-/.'!





+

#9><2*/<;<:BE7>>=@ELRNG;-
$(,3279DVx`Wion~������������������������{{{|yvwts{xyx~y|��|vbXi}yursaHTs_�wyx^M;8<535:Nj��������ɴ�����������������ȥ�������°���hp��msqmntlhb\ZPUVW`Y]VWQVVUQPGGGFDKF@;5./,)$

	







8>>93)289309,97;>>ITVO at 1**/07B<;<L_ZQUX\t���������������������z~z}�{x~xttutxxuyyy}zwytaWhroqtp[APOeyw}v^F8<D:855P���������¹����������������ھ��������۽��s��ylimox�c^a_[ZX[]XY\RXSWVQMNHHGDFHC=;3,0''#
	












3<>:8-*-0-+155-66>JPMM=8567<;<?6.:ED=FHI`l��������������������|�uyx}tpvtutwutvwyys{wwyzt`;EYflfdr?BLKfqyeJ0:A at 717|��������������������������}��������������ujadq|ts`US^\[WZVW^QRX\UPONLJKCAEA=33+(*'%!
	





+


+

$9;884)'$,./223547BLJE883887895."'/:=C at Sm�������������������y{uvvvssqtwvvoxyw{||~v||rwaF12KZb[`F?@3 at by�eO:4A:-8S����������ʰ�����������������ۤ���������������zn_^u�bc_RT]XVUWWVYPUUZURNQKFEGGE?=20(()*"
"

+


+


+
:;9;3-,%+.,0245.45EI@;@@<7351+'& $.1:4Qm��������������}}zyxy~vvqzqntsxxwx�}{|t�����}pplQ&$1ETTYRC?46Qx�hWI50006o����������ٷ�����������������ѥ�������鬕Ł����tecl�Z`]TQUTUUWPU\WZZ]SOHKCGGHHE?4/,*(''&"#


+
+
+



4;964.1,)/0.1251-2:=:BE@>4512..) 
+:AYq~�������������wy{vzsuxwuwwwqx}}}|�����|��zhZXL*
-3<FMQJ846I`vqaSE<;3W�����������˫����������������ɷ³�������ŗ�z����sbkol_XSPUVTVSVV]]\_]RKDGCGGIOA<22+)&)!"#!
+
+
+	


 6774467-30034:-.32;=A@=8:1/640/.CJSj{}������������yy}ywvzwyvsuvnz����������~}yfBJL/
+/:9^C83=1Jenp]PF92^�����������ʲ�������������������Ȫ���͵���j~z��nmgojq^UQPOQTTYU]ca^i^NHFCEEDIFD60.(#%%$# 


+
	

+

$33:4387/2,,.33.0--4;<?@<979;<:8$
1KRD`pm�����������wz|xuxxsyztuzzz�}�����~|}{|xr]A4A7
!&=-7P<59?13Cfqg\[CA[�����������Ŵ�������������������긑�{������_gmuklkjtiYTOOPMRY\^fhgdfRMBCAFEFQED91+("
 " ""$







6.33.501'
%)1.12/)/58:;53229@>7,,+2I\\KQZ`������������|xyxwwxwyvxsw{y}���~��}x�yrsjZD'=2(
(734;6,=@5+2Whg]YNIm����������⽮��������������������ʚ������{idprjdfhx^WPTSOIP]gnmqk^\OIEFGHDBNE at 9.,("!
#!"$



+
+
!


3411.*'*&
!"$()-9,+'4>40+.,79A74277UdfPLE`y�����������ssyyxuvxstuvyx|x|{{~~��~}�txsl^F4;:2'*.:70,',A7!"8qa^ZW]�������������������������������������������||dfjofb`dfaWTSPONMX_vmsd]RPKDIHMOHO=<8/+%#

!

!!
			
+
+

.;840'""*

 '(/**",71.-/+17:82056JROGMTdz�����������quylnqpyvxyzzx}}v�~z|x|}�}uvrbP299I0-59?1/-*530,2_]^_\i������������˲�����������������������ڶ���ˎ�nuqha]Y[edTOQQPMPUgtxthYT[SOQUWXOK8<2-)$# 



"

	




#1<;7+(!

"
 &($!"11..+-,0,1,+656CDBRTgr�����������uktquuqusytzzzx{����{~|yxp~y~vjbD28A126?HB93!
*3@>iQV\dx������������ᬧ�������������������������ʫ���vsjc]RWXec[TONJNRbw|�xhb^`[XSUYVNHA92.&%! 

 








+








"%9;76+##"
! $
%*,/-)**,,''473>>=GMU\av���������pwwxuust}~w�����������x{y|y{}rr\ID@;9;:A:<: !!)4CbMXSj�����������������������������ʹ���������ֻ����qjhTTTWX\ZVPJIKPYgr��{j`jcZ\TPSQJA?91-,* 
!!
 #





"



!".410."(" 
"
"

"&'%"$(*$+1169;87GN at Sk���������{oxsxvy~~������������{~zxzzwunaWJ??@>?:24 
!)*<KQTp������������Ѫ����������������ĸ��������ڶ����rgxYPUVYRZTLIFHQRn���rjjoe_YTSTNKFB>6/)*"#

 
!






+



"
$
12520.&#" 
$'##$')$3179BG:DKCSf���������owwux����������������~|�y}zyzywrldYI=AD@:4)(! -1--8MWi��������������˴�������������������͸ʾкÎ���vdbbZ\WX]\PHIMPU_d���kuiega[ZYVOJFA550%&  !"
 





#

,676452.*-( %'+("#%(+/55:EE6<AGVl���������pvqw����������z}~x~z{{{{|{wxwswqdL??H><76410.0(..>J}�����������ټ����������������»��������ų������ee\Z[]VVZDFIQW_fo���uldaba^\WNJD@:..&!!!







$
 # " (788331-+.,

'+(%"$%*+11,0990):EPar��������mtty����������}xz�~y�~yttustrvz�fQGDAB:;5;7:*:44/-D}�����������ؽ���������������������������������}kkfaa_XSTQIHNWcgp��|pc[Zbh\YRGB=6.'%#!!$





  

$
  %%$ [...]

!'%
$(()+*++1--.5;DKVl�������jtty��������z�{}��������ztvlssrpx{_LJJIA;69;@C8B9>>?D������������Ī��������������Ī�����������������zkjiba\XUUNJGNTgea��}bZUU\bXRID:4.$%&$#$
!

 

 

  "&%$'%"$$'392/.&-+.0-"




+!"
#%$&'"(,&*+/47=<=R[tx�����kx{z��������������������wwzwzwqrsn_JALEB45;;<@LNELOQN����������������������������Ƹ������������������mfagV\XUXRGCIS^dv��k[VRV^bZS?73+'&!!# #!!!



  
 

 $%%"#'$!&!*6<2.,#&*,,'




+ 


 "%',
&,1897JSjmow}���mwxx��������������~��{}��{yz|tvrojUMNJD7,><=?>F at EJ^Zly�����������������������������������~|x����x��zca]\Z]Z]YNEBFPZdj��p]TV]^^UE;674-%'





 
 !


$
"$"&#,*)&,,:>9-(&%!$&&!
+

$&#!!'+39;;H]_njimq��uzr{|���������������}ry���wyy{xzongMQCG=4&:E?77==?HPal����������������������������¿����{z}|yx}{~���r_]\V[XXWVOGDEKRWbx�q_WZ__TM<<99-//$(








   
 



 "%$',.*&,6@=6,,*% 
""



$,#""'373=@CGbefijmpt��~���������������}{x{��ysu}yyqj^>FGG<2/)574*3;EDI[p}����������������������������ʺ����z~s��tukt��~s][VVT\WVSME<7?CR^mqi][]b\MGC=:7.-*'"""






!




!!

#$&'"..+
+8=91+*+*




&('),0.AONR_glhjifjqz{����������~���z�|zy}{wvttnvinbKCIIA55116+.3:?<JWqx���������������������������ƺ���������˯��~{�ne`ZWUUYXXRK>97:<DZhxigaifZI@?952)&')""#  




 
$



 


"%,-$)2'"*6<90+--% 





 
"%$&2DVWXZbggjihkhy|���~�����z~�}�{�~z{zxvrvuwrqxhMGHEE988460)2=>AQay{�~���������������̯������Ͽ�����������֣�����wfa\WVVW`XRF913089Yz|hupfQGB61/**%)!!&%  $" !

"

! 
  




!
,0/--)!$32771*&)  $ 
$6[^ZRF[bhhfghhuy����~���������������}�}wwz{yut�w^LFBE<876255-67<Plqxxsp�Ҋ�������������������ū���˷������ĭ�����|de^X[Yak^QB52..4<h�guz{}ZOC80(''*'&## ! "!"







 "#
  

**1/*'!'2.15/(!' 
 "!&$!'9U^ [...]

*"$2)##)>[\bSY`flfdigiy����������������������������}��w�jUD7:;9881-12(6<Iqru^DHO����������zW`RjB-5,/544AIST`_hq��������ztbSQMLVXfe]C60-)28ikey{xhVE at 72.,+'(($$!!#!!


 





 "! "$
 




)+2+,$%#)'$-.0$ 
#)
%

" )*#-8-#"1>V[scgbhdmkllex������������������������{�y|zxyz�pXB/276773,1/#+38mvK5::d�������{<:03:43/$$! 


)4<<J?Pam{{xof^NMLLTN^_T<3./,25en||�pTF81/-.,--(%"
!!""



"

! ## # !

 !

#*.-,(''&'(,-+ 
##(

"(!




$'*25.08&$!/AP^ilpjhkdllnekqlw��������������{�����|�{xmx}��}lVF:1/161/.+,*$*&hi?!LfhqosG�v�E///WQ3rX

  !
+4599FX\`SUM@<AGLVXK03-+02={~~nlQH=540,+*,-+*&#"! 



 ""# !%$"# 

##%
"+34-+$ %')0.*# "  ###"%"""139NE9 at 0#'(-8Uhkmkkptmmli`_^bm}�����������xz~���}zxyyt}��~|kRDB91,%732(.1/2Iqds99�|�~iSX�s�7-/5FmNLK7&

  

)6;447A<4258BMQ?8,/,55G�tmaND9541-),++*()%#" 



!'% %%%$$#"!%! 
#&-8-,(!&(-55//*''%&&%


#
'<LTnaC [...]

	 
#GKh�a=VM;4860Odjmjeiekhjk9882AWkoy������}|uw{~�~|yyy{�������]=?B<2,*43336;=~~ajYy������ibowV4())"
#
"#
  ' %#"$&*5:4,)%+0.=SYTF<24,*$#!  






%$%'&$##  $
 "&&&(&43,-*-+2;EA464301$
"'
#%

%!9NRi�aATU?8<HGK`lmhfdfijhc2898;9IVew���~�}~~xz{{{~{{wx~������kLCJ?83124458?E��uo~��������qc^Y&$)&%!""

"& 
&--+&%),/6CGD931*'#
 


"$$(*((%$%##!

$(*%,*:/-,(,!,9IA672/9*"
!
!!$7LYf�jCVRD8G\Y\gffeffhiigg28975045K^zz}vz|{xx{vz}{}||�|}���zs[HKG>353499;?U��uq�{�����ڧ�uRF+& #"$ 


#

$'.&%"*(.0151+*)% 

 !')*()&%#%"$# #*%#++0/.+(,!+25;83("-#%"&1DIUQqg7BO:8M[X`cefdchijjif.33.2%-10CKcosnmmszxxyqx||{zxzw~�~�rcJCGB7767;B:6X��V`�����������kA

"$




"),FJ:3.,(((+*%!





	


 %&'%%'%%!"!$%(&(&*.1-/'&/''1/26 
 
 &:0&=GIOMRG:=<96CJRSabjchihdije),+-%)),.2:@\d]Tcsr{nrbl{tnntxvv�{{ukcOBNG=>;73788n�waj����ş��Ǫ��Z


17573.)**(,#'

W) 
 "!"




+



 %&&!&(((
%'(***,//20*(*!%(0/**#

	),
,03&#=@@@>1-683012::JUN]ag^X[cgh$(%%#"+(--/?PONJ]dg_TR]{aVLcjd[skigaVFEMNH>G8447Fu{�}��yw�ɕ������z#



!:2!'042,)''()
�vF2(*+&0-+242'+##

$%&&&$&$  
,),-!-.220)*&


$+,&'1$*&
#"-+!03.)#$)91/+- /7KLJSUYUQW]WQ$&

" "#(+'*=EB=IRULKECaP8DYY\WMTPLQNDIKSH:>;85:_����nrerǷ��������$!!











:#2>942( %(-$"�w#
+



 )-+.)


#$"&$!"#%! 
-0+4#//4423(&!!*.+,-3-0'
$*,$($&
",)"" %$4,-31+/:MHJPPTGMJ?FC
"!"
")'"*C<@88BD>>9 at 2;DF=9IE>97=B?>FNE==;98>������qW�Ң��������3,!










+
3
#17855)'!!059!)

+






+
+
	

%,84$
 #"$#$#%%



&3/3%/11632+&"
*76.,+4753-,,$
 $
%#%!+0"--/&1;H=DDF5;HC>@E#
!"
!&$"'5 at C>2:=B6:239??845<6+61<?=EMDA<;>8]����ʹ�iu����������F-1#








+
+




  &3346+&+1#







+
+
+
+





&,&

!$  %"$%!!(631**0373/0((&,9@</.(*4324:.
 
.&(*0'
)%)+2;><<>;88=:::@&("
%'*"!%
0;=@5.>IL5C1 at DG<(.427>@>>>IGG;8<<E~�nS����{k��ݱ������j
1-$

+
!%2V:&1/$($
&,


	


	
+







&/&$#
  "!
'1/1.&-/3.2-/+,4?@914+,2-/10( 


,+,)&+)+&%$,3;:53553>DJFE<63.-/159;1+,+*5>;=AADTXPGCJOJ>3:@JDDJKIOF9::??E�c)")���|������������%+#"



$*V_MK?+% 







+
	






.6!&


""
#783/(0334/2/&*0=>:651.*)+(+'#
#
',)('(*&%
$.332/3<>FPEA<B=B>@AHE=>H>997:9==:@DMKSPBDE at B><B=<?BEDFHC9598Tm9 AKZ��������������[.'$

$!

 

$2}OA>81#




+


	
+

+



+6&
$ 

#3.2,'00)0++,!(/8;;891-))-'%*&"
"

!&$!&&
,46;<?@HVaDBB@?>AG?=GIB9?D=H>:86885;ILNG;AA;86647,0::99 at GA25,^~{>;\�w���p���������+3+-)+*


$

6</,-.*$


+
+
+

	


	


+
+






+$<
 

'/-,'
'*()--*$44:99774)**++.05




!
!$


.:;CEDEfgeYGDF@=:9=9AA;9;?AFF>8354*7FHJC=>B;*'006./220,7@?/7Dhy

<'/Wyt�x�b���������s-410'(!

(,('*)&"







+




+
+
+		
+






+=2



!%! +$(,+/(5B=94461+**-1023+$
!

%%''57::?AVYc]QLF;6937><42128:B=<52<?:64:=<91;4,+-8D=?-168?C at FF?r}$
?m�q}�������������]56.' "
%&,,,'((%













	
+	



+



*J




&,7
!

.
#*36-2>A;101.)'#'00110*-+%

! 
%'-0)'*/.,4=E\ihaUIAA:AD<;4/05=CA>732A>=<;0/...137.1=BFD?869>HJPW;�x2*O���h�~������������m& 
*"
*'9151+$#&!





	

+		




	$=" ', F-&0+'
#
367=BB=8,,+"$*&-,-01-15.%!
 "&02052*,*'
/<5kzvq\M<@GVPGB>7=?FKDF;.11893>B2+&235;=:>;=@:=<=3;BEHI~|?4o���v��������������ט2

 %)0TgncM<1'"" 

+
	
+
+
+	

	
+
+
	


%>C7:
$8>3)0,!
!
%.6;BND<5-+*&'&&')(--19<10,-'#$)(+0558;;47,,&!3GT����|`7>DMXMZCLOMLKMIF;-)4711:7&-9<=C89:8552==;8313;DtxU$7���Ҡy���������������o;*

+%%&'0u���nZH=1$"










+
+
+
+
	






&-**4/!!E<1*-*#
'**8@?C942.'$()+)&%'(0469:772*)':.(2258867:7236)-Ik|������538:AJKNNWNI<9LB:**330,0574;9=D;973/2178622-+-9f�WOEE����㖫�������������ɹ�W=&	


#'(1?St�Ĝ�wZK;/&!"


+
+







"
(

&*/(2.&
$(.5::?60-*'!!'+*'%&*15<A?5482--2235746179<8968.5G]cwyyld5111649:87@<4;<8;*&04)*$+4:<955163-)+*.$.40)(*7Ox_OQE����ܧ���������������ê�rY>&




&(#5I����ª�oZF:4(#

+
+

+

	






+ ,&#


 /*.)* #**).00+')*$&"$(!$)&&-3>A>6:>?.,010463535412/1/79 at JMV[XZZP+*(%).,12-,12120/.*2/+""(,;7./-*1-'$$%*#)--*&-35seKTP����ɡ��������������������rcF0 


!,$7Q����ɲ���v[@6($"

	








")"!%#
+)*/2+(
 '$*('.**')*'.)+#$&%(*1;<75BF;0(+1/720303,-,* /53<?CEEHGPR'$$"'+)-3)$(.)"*++&.))%
 #893-'"#'(
#%"%(+&!)21iuIUj������Ȕ��������������ȭ���tilXI4&++1Aj�Ͼ���¯ʕ�oQC4&"!




+



+







2%%&!&
##*0.($
$(*''%+% '+/*651(&#!#$+21699;621126:--..,'+ $#,333<CHDAIJE%

%(**3)!+'

%(*0**#

-;;,&''
%'&!%+%+0*%  .7FtDM|����g_�����������������ź���}skji_S>6/2)&4=Z���������ĭ���{gM=,(#   


+


	




	,&&)0 '++)*0('$ 

"&)+(#')( "',/7;7($$"!$('.151.461.6B7/(-./%!
" *2229<;BI>A>" $&')+"" %#'!%'&%'%""0=72*&(' )-"%)(.</) !)89�;4����uRX������������������é����{troenndoq~�ͥ��������������d_N7,$ "$








	$

)+,

$'-)*.,$,"!''))3%
!!0

'/0EB6)!#
 

$*33036+.7:3-))-(


'(./09?C<32)

&%$!!& #"$+'1/,)(%(6B9023/. &%&(*'25./.,4:+|?$���~hLwɔ�����������������­���}zokqptzu{���~ptu}���˷�����t[J5 %

 "








+
	
+
+
%
%+ - (.('*#&%(6-57.$"#"$$1.'7E5'"&" #%"551732/.4/--*-'



(((0394.,""!
&&($'!$172*,12&)'!
/6:<26682*(%"'+(05=>?=JG>m6)���w`M��������������������Ÿ����rikmpwxlejb[XS^k���¥����zjZF/&#


!"!















"



$
-'1)%$'()-&#-21#$$ 


%+"(60('(# ##!(99-21-/,*/102(!

 

!+,-00*$*.7C81?6(IfI5'5+)./*0470005.)(# #&(.<AIQNRT@`#F��|kaj¿������������������̭���}tjgdcfeZVPGE?BCTo��������wrbXI>*&


!!##
+



+
+

+










+


#

"#&!
%
"5/&'/.,*(&#00&$$#!

#+&"11'"&'" !"#,/&((%*-.051.$
'+,:;5.-21O^YajjLiyxia=1+,4/(*$66369866''122/5:CNWYdSV`
W��tb[�Ť������������������ǰ���vhTa[VUNHC;=4414i~�������wph]XOE5'


#$%&




	

+
+	
+

+

	
+
+


)


"%*$!'
+)+-*/*,'$$(,%!##!# &$#
&,.*$

#)*$$'
*/153/($


)2<XWHB655Jb|���vz�yuzO03<JE2/57A=C<?FGHJACAH>HSR[Z\X[[]��bRi�ū�����������������˵���zo_WVQJF?<640-.7R���������|qd_UPB6,%

!#&)(%



+				
			


+%


#'*#
'.4,/'*#&$ +/% 

&,#$"!
!*'(#!
#$$(*'1551/+(
!


!##"",8ERaVH>525evy�{njmfZ<1,3I at 3,012448:BLVPUJVRLEEIJNRFHAa�p]Pt�£���������������������{rcYQIF>9722.*).=����������nh[SK?2+"

'))%##


	

+			
+
+







! 


 '+&
#	+/#)&%"%!
))#

$$"!"$"&' "&&!$)"!

%'(+33742,(!"#

  &(&(4:CGTZTG<79GKajrnf\QHB at 20&32+&%)+2,)17EKGGLGFGE?AKKH<8/��gZM�ż���������������������~qcWQG>:554,+)%"0U�����������nd\SH<0( 
"$')*'$(

+

+
+


 $&





&,- 
'')%'#$
"&).&$"
&$%!"&(,+&%)$/1(##

!&()1-//-%'&&%


% &,/7 at KLGZWKCD@FQWcbbWPIE?B4;,-+&
%+,62,):H7>CKLECBCDJPJIB��jWQ��–��������������������qiXPE>9/752*($'(?������������r]VND8.$

$#%((*'" 









&++%##&*%$"#"')- &&&)'( *-.*2.!
+*%&+*
%  !$
'+*+*"'"(&


!%#
$*4:JMYDKI9DDFBOZ^WeW5>><522//. 
)-=/,5=<,1=FKFHHGLNLNNT$
��o[O�¯��������������������qdZPFA;5463/*""(&c����������m[SKA1)


 !#%#)*'%#!!







 [...]
!
#%$! 
(2899-)&,262155:72-*$-.&(%"!
!





$5846<GQHKFBECEHEB@<76.)+&)!

 ",60/3'$!.AGOLZS\irib_
�����������������������xaXMC<;442.(""%"#_�����������`SSGF:/,*(!!

 "&)--.19:74*')"
"  " "#"
!!(1+'+$"&$&!"03;>.'((:8631043+-'*+**)'%)

 



"1666SVbPECA>?668:63'*))((*#$
"/94(--!)6CHOPQHXc����(�������������������������tl]RI?<878,&
!"#*Mqw������zk]NKD=750./.)'%



 #++,.2=E<</**!!!!


!! ""!

  !)).(

*(#'&
 )2-665/'(4:660"!#)$(!

(()+.),)
',/41QVVVJC<982"$-0.*("$+&#))#
124)-)04FIKHLLHGp�Ǻ�
 ������������������������umbXK=8;6/+%


!$%%*4V\Ugq|wvti]TKHB@:64561-0(#




$!#!--0448;93.*##!!$!! ##!#$ 
 ! !
++'#(%+#&#
*4.+13.%%1.--,% !))& !#,&,+/1+%"+''*%CCIIJMG8<2$'+.-*$$$$ #& '121*''+/5NRZOO at O~����!)�����¡����������������}obXLF at 8760(


!!&(028<2;H`llcVMMB?=<;;:775/-*$
#


! %%--314783-*&#!""#!""""%$" !%%$(,.85(*++''$
$2.(1 [...]
.183.)&.0B\diT1&
*'&#!


!#'7*)4906/1+7<7IA at L��vt[\�������������������vm_RDC?9.&!"#&*--)-����������~^TE7-## !







"*.46734426'/./,0200/0/*+/,,*-),&"%)"
')1&&&'!


%"535986.0361.,#""

#
)!



-9A.((
<;:GH<A:56G6875'!!77.4$8BY]\\[^_[fXR^d��oog!/�������������������xbQMD@=6&" #"&*0+7Uu�Ǯ�������l`J=6+%#""!



$.4:64751.-0.0010100..,),++*+*)!

+
 %%"#*& #%
#'5:634//334/0) &%))%,$!
$#

+2B/4/->9AC>6==:BN1FF>/+)<B7<BLW`ejdfhtkffPhnlphoj8������������������sgUHEB20*#!$',+39St�����yy����hWE6- #%"$" 





#,66896535/0.00222233/..-,.,)') 
+#%"
%! 

&7=6.0/.027=4)$
&7-$#%!

&! !


1+F#7=IPNPJRLMVNXeNLVSFCGQiFNU\efedidlolc[UfkghnjiQ\�����������������{m]LDB:30"!'',.-- at kg|}���urs�wnfSB=&
"&&&$ !
 


)468:74771-10//322311...+++)*($	#%
"%4>5//+.1+71,& #!"1-% 

$-'$%




8AjLFTsfnkejqtvpntpsrorjkvzeOXWjgcbcfancd]Mdeehpfd`1�����������������xjXGF<51.$"'+.101J`bljWsmphck`][KC1# #&*1/'" 






%/558766652022100253-1++,--)()"
+	
!# 
.>=2+00137*&" #-%#!#%0$$(*"'
 

+
	
5?KJB8]ljhinmqmqrsvqrrrnmkbQ;E<Q_`d`bjk]^UM`jkeib`b,]���u�����������{xjUCA;61+(%,.0333D^`egZa_[Y^\YWPH?.#
"&.495'"  







+26:<95866/330/0013.0,./++**'(	
  !&#'
.794(3,/35+1)% &*$!!+10*0#-!'

$!&"

+

7@@?:6Akommnnquvqzwvuwuwvp\A,7AAM\a^^qlm`Zcptz{yyupRNgx|�����������yu_PDA82/)+++/4357GZ_hki\]PTTWXULG<*"$'-37<C7#&$
  





 
 
$,5<:88981/2310141,/0..++()())

"')+"
! $


.8=5.-*-0220,(&$

!&*'-1(!.2+&"
##&



+,;Z=04?iqtq]climkiljuy{yvy[.%5:=>@SUX_bde\^x{�������[M?e�����������xoYNCA76-,,).23/5;@cihif\Z[XSWT]RK?1*()53<CE:*%! %$ 

!






$"

-4::779:8460750100//,-.,,*,)*
)+,$#"
&##*!


!+=72+'&-01*'!


"2:3 (+.4-
%
**!


	
+6IqO46]tvvt\OV\RVV]X}z{|{uf8D6<:9>F<TWZfk[hxtww{���i&==4>�����������zsaNFA:110.+-230989^hgacYUSQLNOXPJB504937BAE;0*%' %##""!" "%##!$$!!!%+05:44:8545677102..1,++,,,.*(/-%  


!%(.&


"651/$##!#*/%$!
" 

!
$+79,.1133/,% 
%#!

8DcY at Bi�ytrXQPUXVMNbxv|zz{qE@?:;===5HR`gkYYs\\\\odlMB
:62�����������v`MB:6120-102//004CNMIGKE at E=;=DDBB9179749=;4/.+*,))*'$##$%$&'&((%$!$#.38877843479752301.,,,+/.+)*
+-. '

##%$'%! -22-,%#&
)+"!



##%/:3!&,/2855(%"$  !
:W[B68T��|tWNSTWXQYdx|{}}xfED at 6;>;:<HHYbh[aqQb at IiQMD; 	-12������������q_OE?76420---+,..),05733./.0+,+224:89:79=9542/21....,($*&#+,)/-,($""!#,058887468452522141.+++--,+"	
"(+&&'
#6)!$

>9.1*%'#&,



 !"%.2.  '7371-%! !)!
4ZwS22S���xZSPSXWRQ[z}�z�>IF>9<;==NBWgf]YpZ^KGbRL=82
)*z�����������qaVJC=:411-+)'.0-$
-'('$$'%&&"$&(,3633723321532590310./,*/+.1,-++###%.0863745754664202/.1.,,,+(,$
+((,-(",)%"
),832/(#
%%!



!%*&$!"%.35/('#('$7\�h=*e����\PRVTRUY\z���vrOJE9<<>;?P=QZhfaoS\CAcXO><1"'l�����������riUQKRK:72.)).227AHVnaY>N;67)$"%"%$%)#$%'#&+*)+//1441314-+,,.1-'%!"&-455558997645122/210--*,*$ 
 &.9(
**("
%-4/(662.'#'+,,!
 $%&!"'-/76(%-.)%
!#&%'>d�lG0r����cSQMFNRU[w��nk\CFEF>=?B?<GINZh^`bR\?>dAC74* -R����������{klW[[YNA800&).34R����������šqF9,%
!


! !$&(+02/4230/+-./++$$$$(/3455744452321-00.-./*,,#

+
 ',+$.)*
(09<% 8 at 8.+)!
-203)



'$*'$+39943-+.$"#%*1338t�w[/s����jPSG2HEX[���qf at ACALKHBIHBPSY\g[QRET8DeK=2-+/
)4�����������scVbeXPB9.-),44H{��������������p`aB+'"




!"'**/100/.+)++*%"%&+,226545462312/21/-/-./-,$
#'-"&&1.*"#*065-! 5 at E40.)&++,,*

$%+*?=:(+*2-''++286A��|mGT�����qsWIDS_hn���w]K at KLLPNMSFXYc^gYOTGGA9b`{W06-&
(�����������wpfhg_PF93*)(2G�����������ĩ���uhc_\S<%"#


#)*((-+*'(%&%&,00//1276753230+121-..,/-+%*3
!(1.,) #(,4+.-
"/4>@80+*+)/


'#$-=;1+-/.0-+'$/12Ak{u�\Jh�|~}oocMIMW`ZuuvYPPTUXPXWXVVZ^_\Z]U6DGE[b�v26<4,{�����������rmjiaTD91+,-Bv����������������n�xleZV<*







  !$&&&'&%$&,302123723442//1-..)/0.+,(	10	!*20--+'&+-),=6%)4;>:5.-))*
&&!#2511,,/0)(* $%'DJPXY[VOZ^`UOLNMKMNMKLS[[`]XZ]Z[bd]Y^dWWYRU]OPY\_botH?E@$
^�����������szqk`RA6/-/;f����������������~^SRT]ZLMH@/(!


!
! !!&&&((-1,313553../1/0//-..-/-.,++(
'-001/1%&/2))/3(*.1>A82*%!& 


$'$
/05*+03+##%!!SUY`dd_NR`^_TSVZWXVW^Y`abdaa_`^`ac`b^e^QX\]s�jca_alkMC7;5
=����������yvyul[UD811/A�������������z~yhW?:8=B=;<74/*&%$"#"#!"$ !!#
 ! 
 $#"++,22131333401.00/2-.1---,02
+-

'+0.-27) -4-**0+)5HI?=:4'(!% 









"(/*+24-(
%$
__elmnkbcindeebgf_W[]fbjkhf_^_bb\gabhjkU^_Vlljfa\^WdQH;6?$�����������y{tiaTD6001J���������yvthkaR at 5+'./1.,,).%/(''&&$+&'
!!#% "!
 

!$%)+.1121/11321200//0.0/1./.,,<',/-+33.*.014,2)1;IHB899-))%$#
%%



#((*/6,-)"  mbrrrqtomssjggja]ZSHUV`eeXa`Y`be]fgicfdbecdhoqga]XTWVF@:=A
t����������z{upaQD;0.8f��������tk`YOLNC*/'%*'(),)(**&'*)*+,*%& %%$""# 
!%&+)',-/00,/322210121/000.-03,
& [...]





 -36/+)+,+81,069<;3183*%('#!!

&(,%!
 

"#%))&#//2-
$tjonqtprttlkigfdc__``Z\]U_]VW[\b]ZUX[X\]bcab_V]_`^dTQOXRVe=&�����������||vl]UTXcq������|sqc[UM?>90+&%%$&
#%%*)(')/*/-*)+.'&''%" 

 
$&(*(//.34315-0.212/22/2156/1*
"
&
-%)/-(,482+*,43:=<:0&)%#
"&$
"+

!$"##("'.8/&&qrmnty{zwzuvoiiha]ZM[eihcW[^Z]WY^WVY\Y]_ib]_]_]gga`eb`gdc_]
y����������~}wnd`cgi|��������ssf`YM<>7/+'%'(&&&$'%$(()-+/*+-*+**)(&$$"" &(++*21-33112/0/.01033036404- 
	

!
$ 

%*0--+0;94)"'-,1/77,++"&%#$ !
"




#$#""
/2,(%msty|~�{��~}|xnlaXXUNUgnsmngd_dcab\Y^hmlrc`[Y_hpiffhkmnrpgh"Q����������}xwoupnnw���������wnf[NEC6/+)('% #" "##&*'),,+,)**(&*)%#$" #&)')+-213644321010/2436/24754/


+	

+&"!'-+ (,43/+&,1/22510--0(%!""!
!



$#!+/'' �|�|{~{|xxxrifb_[XSLObmtwqzyxuvwywv{{u{gcY[slpkonssntvtrJ
#����������{{~vswvv������������vod\MI@=0)-,$&$$"#&()()%+-.,**)(&($% !#" &).(.013646560230//3160234513)
	
+**($#)/%/%($-1/-01251/*-.1,-(&
##

"

$"#
��~}||z�}xwofjdhjifafepwv{x�{�}�w�zwwvpaPUGDSbbnqrwswyy~vw
u�����������~~�~wy}������������|qdXTMJ@;3/)*' %!"$!&(()+*,()%*'%(%$
!"$$%,(.00121033.201321532144210"
	
+*,1)$)+.2.*))261376.--
***('""*&%%(


!



�����������{rpwtlwxs^mx�yxqlnghlz��vphig]TOJF6=Ncmswuw}w{~�?���������������z���������������|�~k�hRWHDB..&(!&$&#%$(''+()**&$%%#$
!%$!$-./122.011.//1021052/42531.
+
'50/,%(&
'+.('&-:1521)'/.*)(!"#%'&#"%



�������}���~�~y�zzdQGlytq]b_YZ\u{�{|xwhsrqhkc^djvxt{{zv|�yI���������������������������������ö���~udhZI3)-!&#
&!$'&(*'))('&$#$ !&),+///25/0311///.23433054285+	
!,301)'#!
$&&#2:7:2-'
),*+&#  $!#




�������}�����xz��oMNIUcbUDDPN at CXbx{|}}}xvxzvuw}|x}~�����qww
m�����������������������������Խ�ٸ���|r_ZREA1)&$#"# "'$*(*'%"'&&##" ())-000220/201,00212445444232)	
'13 [...]
+"*2;51,'$"$&$&87--+/421+'
(73-(!#$&(#""


 �zuy|~uu`_ia]_]RBN\gsYUV\I?/33DJKUl~��y��x��~kpkikpusvrqzsom����������������������������������mlWROGD:40-)%!

 "!!%#$%"###%)'!,(-,,2-1..00/33563426405755+	
$.163+.&%%(
%)


 -.63210@%(*"
$.+-*((#&+!"" 
|}�|}zcONHSSDHOPNRWREPHQWTRIMPGGCO\�}~}}~yz}|~uni]XP`[eeXYMWY`!
+Cs�����������������������±������ɩ�|fSOELC</1-)%!


!
"$"#"%%%('&%*-,-+/.-,..1144441452224367#

+#-37/(+

!

.-'!
!+14-*+"#,&"+)$,-02%*

!('#*% 


�|�zwnRMNKKKLGGPOONXLF?FIHIMPMQLHEM`tz�~||x|}sebRURQFJIG at DCKV0!Y�����v��������������������į��ѽ��|q\LKROC<1/+*%
 
 "!"!!$#&"&&(++++,*,+,./00023143524447415,&#
(1(""$+"" #'33) 
!
&-2/1# $%$
&%(/59:2*!.64(

 

�y|xcYNNB9B>A9BBEIHGNEB<=@>AJDEEH at ITt���}y��wnnfidYVYT=LJHNQ\[Qy��������������������������������rhdTHJIA:80*('&



 !

""!&'#&#'#**+).--.-./046037021/436451%

+
'*)$"
(!&&.43)&! 

+45.
"#&%&&#&&".26=/()-/,+ 
!

|x|jZPJ@:89==>?@A<=C at DLC?@;DJHIBB>ADYvq}�}}zqmqklwokgjfbaZVWR[b83y�����������������������������{{o_cRRGA=>82))*%&! 
 ! """$#')&$(*),,--/.////2014224412/13223-





$)!


""$&$'2.)%

"+78./.%&''(-/% '..-(").-',

#!#

||�aJG;;88864;=<742=AFJFBECJLNMJI at 23CUU]beldXT]GIOWY]ghv|�utxwuZx�����z|���������������������wpmmVZRGB9;<8-',("'"
!!"!""#"&%&%&+)*),--0/0/100242121600/04231$"

+

 !
#
)

('


*52+/+%(&*).0%
!&###&+



" %'zsxdRE92.172.74>@9<CGABDGKA>>KOMEA1/68ACWPENZb^KHFALEMSTcw�|zv}�2
R�����~x|����������������~�~smhbVPFHA?9:?6+"+'!%$%"$###$$$'+'*,,+,/2-//1320535142501//3333,#	


"!# 
#

!"'$# ,<4/,')((!*,*%

 " )&

$!ZYubFC1/*/21)8 at DED<B9=<>EHAA=HGCDB846<7 at HJMQXXUOPKJKIGMRTH`aY^]f^"�����rv|}����������}vrjb^\SNFHB@;994,(%&''%%$!""$#"&%(**+**-,-26.20003523221300-00211."




+
### ! 
!# %(/!&*99.112140% %#



!)"
)
H<DK?961258937:DC?A9688;?<88=>38A@>8ABD@?IIPKMRUWVZXPOPPPJQJJKNQK5
�����z}xj{y{~}z�����~||ywnheXYXPJA@>:774/-*(*)$"$'&'$'''&(*+,+-/../300.0./02230420/.,,.22-)
 
	
 %



%


# +)+01.//2500,"

 *#&
$&#"!1 $!
:9<9=>759;;;>>?;CCA80124;::73367::@ERRLLSZZVUQX[[\`YPQNLQMHBGQM?FG�����x�wuotu|z����}}txqoi^[VSRHF>>957645..,.,,***')(&+()*+/..-01136063/024455611,.+-..10)$


#/

")%


"&&+++(.5/*)+  
$0*!',0)&)-7("

%$;:598?9.8978:AD@>@@53-35 at B>?51<?AFFK[^[JZ[FDWP_^ZVUOAHTZ_N?@HRZSH>/�����~yvzxuxyz�}��}}vmnpje__OVHI@>;48834330...-,+--,-&*()-/21/.035574164535856212..,,,00,"

!

"! [...]




%"#*/688:5,&#""$!+/2255,'/-..0)%$"

3398>8;8876,-<@>;:744+=?LHB<>GGJQQTYXXIbUE941.8C>GE;5MV_gd;9M]ikXg|�������|vssuqgz��|wkgc[aVPOPJJIDCB?8=>6:9987644241232/113445878::7967574573010.+-(.++)-#

"*('
+
"
  %)269;5>0+&(#
!#%+023-'*-$(-%$$#<><A?968662/0;B?<9:963<ABC96:JNPECHPRWOULC:74<=4<LC2L]hZ[bNHASKEORO�������xwsprcmyz��znkb[ZTMFLKFJHFFBCF?;<;6978:8543822236266:9;<<>;9789:;47534.,,,,)(*($

(29
""$#

$&+368=B=40*)$%(!
*.)&&.&!#$

 #

HKNIHF2,00/08<@A=BD?<6D?81851;GF:KCKL]IKI>:@>LTKPPbTia]NMHJZLHA><A8o�������y~yrqjfpvx~}xrea[RPNLMKLPLKKGHGACA@:=<;<8787;93:::96<>AA>@95:69<:98420-,+,+)'+%!



::
('+'!
 [...]
+47:213/$


.'+. ,/87:858:730+&$,0() !$% !$""$
]Zw|lnLMMNGK>FJ99F:GQcLAHP6:AB<FJHKGC<EEC79BFMNJAA;5<8.43:LQRCcVVD7`����������{|ursuiccfmplpjef_aZd_^][Z\VYXSRRRRIBDFJKIGIGFGGGFFFEDA at AA>5862-,+)+''($# 
"%
+
),%,31'

*-2(((37=@553422)&
()%"&$#"

 




\`g`^c\SFL at KEHKKGMRQSFOQYdZ:EGN]SILEA@@=77>CFFAB906;30,))2[EAETbhEAo����������z}|yttmkje[[ffohfnfdhe^^]_^ba]]^\`YYUQLMQPSQNPMIJIJGHCB at A@=8834,,++(*)$&#

 


	"64**44/*



$++$)%
'889/20--&'&
..*$,))


+
QXWPJJTREE;DEDPJFNRTPFERS^aJLUaa\KA>65:=9=BDF;;<9/,+*"('(>VD7ACOGf8o����������~�zxvvrolb]SSW_jj`d^cacbc`_]`a`b``b_]VQQTTPQSJKHJHLFCE@@=<<;7.*/,*#(*'!
!


#d.+26:9>



  /0!


(14-()'&
#*2+-7-"

 '


BIEGD?GC<FB>BDNLHGMKOJ at AFNSUTS^WU?MJ7:>HBDEFDD=<80+*((&!.??9/7>8>EAe������������}{wsroolaZ[^]`]e[^_hbbed`_abdgfbefa\\VWTLNHGHHJHHDAF?C?=:641/,*)(()% 




"bV4$3640)#

" $#

"%')##'*+,49%
!"

DORF=7H;EAEC=CKGHDDFGJFCBGOPTMJPEIRX==<;;DGBCB>;71,-,,&#288/0582172N�����������|��}spsnhc\]Z\[T]^_\]a`abfbeecbc^^Z[YYQRSOOJKIKIFGDFGCC<<72.0*'**(%%
 


"

+cb[D*-25-

#$)"#%"'' 



%+'/65

	
)

KYVVD63<A?ECB;BD;CIEGJJEBDHFG>9?7CLK at A;67;=@C:655+/-.&!%22351.256;:7������������}}|tosnic]a_^a]_X[_a^cg`YbbeX_Z]YWVVVQPLPFMFJEJ?CDDIE<=87*,- ++#"
 

!
!`_dYZ>791#
#$


(&#!
$ +& $)*'(& 
!!)0+

+ .!QPLF>7-:;92?>=288C8><HOMCEEF=?7 at B6:<A?62.6:;=61*+#+.+&#*.-74.0+319CH��������������ysrrnbb`X_\`_\a\`cdceafdgb^\\]YSUTSRMOLMFGHECDEB:;;851,.*  "(*&# 



!
+&ca`[_Y at 4*%

')(
 &)(
 #
"-..$#)-+)#"#%
.7350#)3

$S6:=41*5=85<::738:8>?<<CD:<A?APHE<557:80/36582(#!#&%+,"+GV=165/.+-66��������������}kthicehffedbccecabc^fdehbbe^[ZUVWUTQNKKJKHGG at BDD@9;4/.0.*#"+$#"  

 #
3X_baY\\3#

*/'



&*'#!"*'&12)+29(
##%#%29610$
8-+(D<=A54+9@;:3477425599?7<?<3<;2BD=>;11/2//0301-'("
&9 at 0;RSV;;4*.+%/*��������������~ooojghgidhmfebccdcfgcehefia\^ZWQSTPQQKLMIFCDCBEB>9600.00/))*(# 
&$!




EW\YZYX[Q #!


"-2.&+'&"


%%

#(%
,-*-2G
!$
'/3,00'*..0#
67:82+)8;4;0120/-.248;8168:::78;:0./,)).3/004.*)AB.,;L>8DAE;2-$'$",5���������������spmjd^ifiijggedcegjkmioigfgb[][UZURQROMOJFBC>BC>;411//0/.*(+%$!!'!




+KVXXZZ[VaT,# 
#!#)--++(*"


#!


$

+*,*!!!*((,'%*/31!
,)0.))0783..,.+*++-479842669<44322+0,%',--,+./,1EA12 at I?>=<=4)*(#!"(%��ǿ����������xrlikfijdfiehfa`lkkdlkljkhcacgc`[UVTMMOKGHGCDFC>752.,/0/'&%(#$#!!
"




	KW\RVVYW^__@(! %

!&!$(/0,)&%#"!





'()$ 
!(**&" */1-!  *(&-$))1/1-))'#$(+()588=<;H>4-(-*()+&$%**,/+$/5>@:14 at A99:;561-*+1./!���������������tsgjghdgehidjfkilrmnljjggf[hef]e^ZVTOKLGMHJF>@@924/--,,-+'#'#$%$ 






RWV]TWXTb^W[UA+!

"#  4&*-"*(




,!"&-%

$(,,%$% %'.-,%(/*&++'&&!'-03/.<F7HD8+
,-"($$%&*3,+#.19?A<32?=75926641.,:78.���͸����������|nhh^_hfdhmiknklnpnpkjjkhhfdaabdUXSQOLKJEEA==;330.0,/1-,(
"$#  



+W^`^\[[__Y\ZXZN4
#! !# '4-$#$!!
"
   
!#!+!)(*(&
#
"((#!#$!,&+)'''&!04.-8ML;7G8.',,&+($&(-33.),6:C9137><6732/20-.06; ,�������������}qnoehfcdhgimmnlropqmlljdaca``_aYYVRQNNNGG?9;:+10//00(()! !&!




 


+0V\[^dfbde^ZXXYXZM-
#&#%
"$$+%$


"*. 


( %!' " ""
&&"!%%#%!


!$)+)(%%,-02--<TB84>:,*0(+6:/!'+-11*-19><549<:55520-//+/3?;0s���¹�����������|qvgecihjfkjnppxuiknmlgihdd`cZ]WVUXTOKIBD>9544413/00-,+&$%$








@SXR\a_^fraa[WXYYUVO2!(&&


&



"1"! !&


!',)

"" (&%
(!"

 $"#)-/.2/,6OA:6DX80500-10#&'/259.-49:35=@9594471344207=3n��̺�������������wihgjggikfhmnijeolgijefddb]\\Z]VTSNKGA;=::73220,/*---)*)

 " 




!WS\\b^ZaabUY\ZYZZYY[YE-0/( " 








! $*&! 


"%0-'$!
##$#

   
$'.1113>D0?KNY8633-+32,),3269530==;63DA7=89F8<:6.93:_���Ǻ��������������}phcgfijhhfkminplmlhigidea]]aYTSQKEFEA;<9;62622.,(--**"!

 !



AU[^^^^_c`^][\X[YZ^\_]]]N61





!$#




%&,.''$'%!

!"#+-50179?<@RONA:66,154'*032?;4)5?@/697>CL?KOT[k�������������������������~yhc[difgkihgimkpjihedc`\^\\ZUSSOJEAA??9::6320./+-,,$' 
 
#%"  

+La_^Y]__]Z]]]\]YZ\\Z][\[]aK7$



% 


&*%'((" $,3,

 #$''.4734:EETOcK=@;922694:80;@Iq������������������������ֲ����������������vnlbadjjghhjjkiipfegfdYb^[ZWYSPIJHC=B:<8:725541-.+-&$ !

$"!!)

EZ]^\b]`\YZX[YZXZ[]^\Ya`^^^`dL' 

!


#&!


4858CF;/#!,='$(3466649I\\QSKB at C>A::;97Z�����������������������������糬���������������ypnibagbhgilhikhhebda`a`\XUORPMLDFC?B>>:;:87333.-*)"#  !!! 

<%
NTXY_\^c_XYWYY[Z[\Z\]\]_^^^__d[F  



LMNFKHJGE?A;Q4#-6=27;5AF^STRQVXDI?LVs��������������������������������������������������|lkd]V`dhefigkbkeddbc]\ZVQQMMNNIGDC?@@><7;;84651+)%#! ! ##"$!(A?	
JPW`a]\\VNWRVV [...]

!$NPSQTILEOXQTNPD83>28:<AMMXib^dc_j������������������������������������������������������vtld^^c`adjihihfcg`_aYXXTLMMLGHIEF@>?><?9;>:553/
'% #!$$$ #"%DL
	
IQXYa[VWXSZXXXZ\[aW]\\`bab`aab_bd]Y>

2,!
%
NOPTSPGHNQVWQdUOZE<+<3KXZF^Ugpw��������������������������������������������������������vqhfdcadeecdmfde^db`YXSRUOLLKHHEFEC>AA?><<<=83-+&'$'%%% %'"
0COD
HSW_a\UYWV[[\_`^`\]a^ad^`_ceddafbjah_7"((*


%TIMRSRSNNPSY[^TIQMI>CDRWZ[O[�������������������������������������������������������tpfeb^ccbiggebb`_^XWPQOONNKHIIICCBD?B?A<?>=820''&('(()'!%$



:IXZ<
+%FO\]ZZ[WZZ\W\``^b`a_`cbdbcdbdedcffecejV+
"$#

BEDLRNSPOST_aeSSTaZNXX_\agw����������������������������������������������������������zrea`_c^]ifee^_X\XVQSSRPNKIIKH?EDAC at AACF>=420,($')())'('!

;LZUZ

+5Jc]\ZZ^Z\\b___b`c``bbeeheffggbgfjigfecegG


)
BCCKVLMIOYXYac^ZW]bbbfid������������������������������������������������������������xoja\`addeca`baXXYYSTQPPLJNIGEDDCBJCDBCA981.+*(+(*(*(''($



"BXY^]S
<Q[ZX][^aZ\`c\_cbbcddeccdigegihhjhkhdfblbdW6

9
ABFGNHBGN[VSN\cb\^beaf{������������������������������������������������������������tpef_fc`abcc^^]YZ]SRSPPMMMIJIKGFCHGIHD?:65//*+(*,+,+,+'"

 
*Q]bf`\S


&VYXZ\ZX_bZ^__adehefcebjgliijhkelmhmnknjkfilqX
A) 
#6?CHKHIJMGMHGR]_UPbpX�������������������������������������������������ѳ��������������|pfb_idg_fc^d_YUX\VTTSSNMMLKKIHJJMKEC83;51./+...,*+.,(!"


!9Rdf]a`[U
+<OXY[`[]bb`ccddghgeefikmkkkijjnmfpijglkjmnkikiq<


"D##"#%9=CB:9CFIJI>CK_kY[SU��������������������������������������������������׻���������������lcbbcefjfbb``^XYVVWXTTQORMPTSNMJHID<@;774211/0--(#+0)!
$"!
B`egjec^Y\
 CIQZ\db^dcbcfeffgjhpmloonknopoomnoolmikillflmlglZ&%=.
%
'(-0=:567>?:CBDCMVladh����������������������������������������������������ʳ��������������ujdecdbk\ebb]_^^VZXWWUUVRQSPRMMHCC at A?A8553405/1.+)/-#
"""-W_hjmihecXU

:EMY\aeefhffjjhliloiopllprkpkommsrpqqqqrnmmsqlpmjnkH%1.%,:576><=913<<68-7==:;<BMW^nb������������������������������������������������������ʹ�������������|uoefefhjnefega^b_`]WVX[UONPMJIIDCC@?=:985723524011/"
"%
 )@W`onmoljeca6 4CN\`cddhikhmilollonppprpnqqoptrstrrttstssrspmqpnmjwX6%."

##:IMPHOPNLGKP=AAD>2?@:;BMb]ou��������������������������������������������������������������������qlcigigphoclhhgee`\[YRPLLJIFDDIFD?B=;=;57203914030"&''!*SfjqktuqojjcX
=GT[cdekgkokpnk [...]
0 .I`\echmostrqqqsvrvwsvvrvzzxw{{{xzuz|{x}�||zyyyvvqsyqoqL2/5 at 452=DH=Fe~QORI77ACIKP8NOWQOUq�������������������������������������������������������k���ҽ�����������{oheca_^_a__ba\XXXSUSPOSPEGFHJFDAD at A>:8:6869<874/+)-%@byu���|}z�xyqhU8
'=<
HW\lloqmqstwtswts{y||z{zxyz{y{}�}y}�|��~�~�}�}||{vwpprptYG?3;.9EVZZZ\[UNF<-=@>HF:WVSUNT��������������������������������������������������������i���˹�����������vkb[]\\_]\^Z\[\[ZUQ]NONPNMGHIIGEKAA=;56:96:=:883),./5Pnz��������{pel_?
@K?"
4Yjloqqsqtyw|xuy}y|z{x{{|~}�}���|~���~��������~~z|zzyxvurpsdGGbeZhfeiOTF<721<>JJ=BW][Zbe��������������������������������������������������������^���Ϻ�����������xh`VWWUVWV]\T][\VVSTLLMMIMHIJIGGB>>><=;5<<<;984+/0.5f�������~��|tc8`mF
+7='(Vfnnswvxxy|{|z}zz}}�~�����~�������������������~��~|~zyvsqtrcZ��eqqfZJF72'&A=DH<?TXVXV���������������������������������������������������������e���ɿ�����������zi]XXWTRTWZ]W[]XURPOJNOGKHHHH?HFCC@?B@@<@;8763./51Ms����������~{U9Q3`l


7Weqtvxyyz|~}�}{|}}����������������������������������|}x{zvywuwr���p`_QJH;1$&:4=?BOWWW^����������������������������������������������������������_����ǰ����������}e[XWTWQU[YYVXWWPOQNLGJIGHJIFIIHFEAAAA=979:5/01+Ba������������}kI)K5*gZ 
Ieisu}y�}}}|}����������������������������������������{|xywvvxw���rQS;??6.,.197ASSQZb����������������������������������������������������������c��ɽ�������|}ur]\OTUPUTVWTQTVNQLMJHLINNKMMHMMGDGCA?=:776220*2U���������������wpO+'?J/^eK8;Lanqyx|y�|���� [...]
\ No newline at end of file
diff --git a/examples++-load/freeyams.cpp b/examples++-load/freeyams.cpp
new file mode 100644
index 0000000..ef46ec0
--- /dev/null
+++ b/examples++-load/freeyams.cpp
@@ -0,0 +1,831 @@
+// ORIG-DATE:     Fev 2010
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : liaison medit freefem++ : adaptmesh in 3d 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:   freeyams libMesh
+//ff-c++-cpp-dep: 
+//  
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+/*
+ff-c++ -auto freeyams.cpp 
+*/
+
+// ./ff-c++ yams.cpp -I../src/libMesh/ -I../download/include/yams/ -L../download/lib/yams/ -lyams2 -L/Users/morice/work/postdoc/freefem++prod/src/libMesh/ -lMesh
+
+#include "ff++.hpp" 
+#include "msh3.hpp"
+//#define ADAPTLIBRARY
+#include "memory.h"
+#include "freeyamslib.h"
+#include "eigenv.h"  // include dans libMesh
+
+using namespace  Fem2D;
+using namespace  yams;
+
+// 3d mesh function
+
+void mesh3_to_yams_pSurfMesh( const Mesh3 &Th3 , int memory, int choix, 
+			      yams_pSurfMesh meshyams){
+
+  /*
+    Mesh3  :: maillage initiale
+    memory :: memoire pour yams
+    choix  :: option du remaillage
+    ref    :: 
+   */ 
+  int k;
+  int npinit,neinit;
+
+  meshyams->dim = 3;
+  meshyams->npfixe = Th3.nv;
+  meshyams->nefixe = Th3.nbe;
+  meshyams->ntet = Th3.nt;
+  meshyams->nafixe  = 0; // Edges
+  meshyams->nvfixe  = 0; // Normals 
+  meshyams->ntfixe  = 0; // Tangents 
+  npinit = meshyams->npfixe;
+  neinit = meshyams->nefixe;
+  // cette fonction change la taille des tableaux en fonctions des options : choix, memory, sm->type
+  zaldy1( meshyams->nefixe, meshyams->npfixe, meshyams->nvfixe, memory, meshyams, choix);
+
+  
+  yams_pPoint ppt;
+  for (k=1; k<=npinit; k++) {
+    ppt = &meshyams->point[k];
+    ppt->c[0] = Th3.vertices[k-1].x;
+    ppt->c[1] = Th3.vertices[k-1].y;
+    ppt->c[2] = Th3.vertices[k-1].z;
+    ppt->ref  = Th3.vertices[k-1].lab & 0x7fff;
+   
+    ppt->tag  = M_UNUSED;
+    ppt->color= 0;
+    ppt->size = -1.;
+    ppt->tge  = 0;
+    ppt->geom = M_CURVE;
+  }
+  meshyams->npfixe = npinit;
+  
+  /* read mesh triangles */
+  yams_pTriangle ptriangle;
+  for (k=1; k<=neinit; k++) {
+    const Triangle3 & K(Th3.be(k-1));
+    ptriangle = &meshyams->tria[k];
+    ptriangle->v[0] = Th3.operator()(K[0])+1;
+    ptriangle->v[1] = Th3.operator()(K[1])+1;
+    ptriangle->v[2] = Th3.operator()(K[2])+1;
+    ptriangle->ref = K.lab& 0x7fff; 
+  }
+
+  /* tetrahedra */
+  if( meshyams->ntet ){
+    yams_pTetra ptetra;
+    meshyams->tetra = (yams_Tetra*)calloc((meshyams->ntet+1),sizeof(yams_Tetra));
+    assert(meshyams->tetra);
+    
+    for (k=1; k<=meshyams->ntet; k++) {
+      const Tet & K(Th3.elements[k-1]);
+      ptetra = &meshyams->tetra[k];
+      ptetra->v[0] = Th3.operator()(K[0])+1;
+      ptetra->v[1] = Th3.operator()(K[1])+1;
+      ptetra->v[2] = Th3.operator()(K[2])+1;
+      ptetra->v[3] = Th3.operator()(K[3])+1;
+      ptetra->ref = K.lab & 0x7fff;
+    }
+  }
+
+  
+  meshyams->ne = meshyams->nefixe;
+  meshyams->np = meshyams->npfixe;
+}
+
+Mesh3 * yams_pSurfMesh_to_mesh3( yams_pSurfMesh sm, int infondang, int infocc, int choix){
+
+  /*
+    Mesh3  :: maillage initiale
+    memory :: memoire pour yams
+    choix  :: option du remaillage
+    ref    :: 
+   */ 
+  // variable a enlever par la suite
+  yams_pGeomSupp    gs;
+  yams_pGeomtge     gt;
+  yams_pPoint       ppt;
+  yams_pTriangle    pt1;
+  yams_pTetra       ptt;
+  yams_pEdge        pte;
+  int i,k,np,ne,nn,nt,nav,natv,tatv,nbl;
+  int          nedge,nridge,ndang,nrequis;
+  int          is1,is2,ncorner,prequis;
+   
+  // freefempp variable
+  int ff_nv, ff_nt, ff_nbe;
+  
+  
+  /* mark connected component */
+  ne = 0;
+  for (k=1; k<=sm->npmax; k++) {
+    ppt = & sm->point[k];
+    ppt->tag |= M_UNUSED;
+    ppt->flag = ppt->color = 0;
+  }
+  // a enlever pour l'instant  
+  if ( sm->connex > 0 ) {
+    for (k=1; k<=sm->ne; k++) {
+      pt1 = &sm->tria[k];
+      if ( pt1->v[0] > 0 && pt1->cc == sm->connex ) {
+        ne++;
+        for (i=0; i<3; i++) {
+          ppt = &sm->point[pt1->v[i]];
+          ppt->tag &= ~M_UNUSED;
+        }
+      }
+    }
+  }
+  else {
+    /* mark used faces */
+    for (k=1; k<=sm->ne; k++) {
+      pt1 = &sm->tria[k];
+      if ( !pt1->v[0] )  continue;
+      ++ne;
+      for (i=0; i<3; i++) {
+        ppt = &sm->point[pt1->v[i]];
+        ppt->tag &= ~M_UNUSED;
+      }
+    }
+  }
+  
+  cout << "sm->ntet=" << sm->ntet << endl;
+  // a enlever on ne garde pas les tetrahedres
+  // demander P. Frey
+  if ( choix == 6 && sm->ntet ) {
+    for (k=1; k<=sm->ntet; k++) {
+      ptt = &sm->tetra[k];
+      if ( !ptt->v[0] )  continue;
+      for (i=0; i<4; i++) {
+        ppt = &sm->point[ptt->v[i]];
+        ppt->tag &= ~M_UNUSED;
+      }
+    }
+  }
+
+  /* mark used vertices */
+  np = nav = 0;
+  ncorner = prequis = 0;
+  for (k=1; k<=sm->npmax; k++) {
+    ppt = &sm->point[k];
+    if ( ppt->tag & M_UNUSED )  continue;
+    ppt->tmp = ++np;
+    if ( ppt->tag == M_NOTAG )  nav++;
+  }
+
+  ff_nv = np;   // number of vertex
+  //
+  Vertex3 *ff_v = new Vertex3[ff_nv];
+  int kk=0;
+  for(k=1; k<=sm->npmax; k++) {
+    ppt = &sm->point[k];
+    if ( ppt->tag & M_UNUSED )  continue;
+    ff_v[kk].x = ppt->c[0];
+    ff_v[kk].y = ppt->c[1];
+    ff_v[kk].z = ppt->c[2];
+    ff_v[kk].lab = ppt->ref;
+    kk++;
+    if (ppt->tag & M_CORNER)    ncorner++;
+    if (ppt->tag & M_REQUIRED ) prequis++;    
+  }
+  assert(kk==ff_nv);
+  // write triangle
+  nedge  = sm->dim == 3 ? infondang : 0;
+  nridge = nrequis = nn = nt = natv = tatv = 0;
+  
+  for (k=1; k<=sm->ne; k++) {
+    pt1  = &sm->tria[k];
+    if ( !pt1->v[0] )  continue;
+    else if ( sm->connex > 0 && pt1->cc != sm->connex ) continue;
+    nt++;
+  }
+  
+  ff_nbe = nt;
+  Triangle3 *ff_b = new Triangle3[ff_nbe];
+  Triangle3 *ff_bb = ff_b;
+
+
+  for (k=1; k<=sm->ne; k++) {
+    int iv[3],lab;
+    pt1  = &sm->tria[k];
+    //    lab = pt1->ref; 
+    if ( !pt1->v[0] )  continue;
+    else if ( sm->connex > 0 && pt1->cc != sm->connex ) continue;
+    iv[0] = sm->point[pt1->v[0]].tmp-1;
+    iv[1] = sm->point[pt1->v[1]].tmp-1;
+    iv[2] = sm->point[pt1->v[2]].tmp-1;
+    lab =  pt1->ref; //  change fh 02/2013
+    //cout << " lab : " << sm->connex  << " " << pt1->cc << " " << pt1->ref<< " " << endl;
+    (*ff_bb++).set( ff_v, iv, lab);
+    
+    for (i=0; i<3; i++) {
+      ppt = &sm->point[pt1->v[i]];
+      gs  = &sm->geom[pt1->vn[i]];
+      gt  = &sm->tgte[ppt->tge];
+      if ( ppt->tag > M_NOTAG ) {
+        natv++;
+        if ( ppt->tag & M_CORNER )  tatv++;
+      }
+      if ( !gs->newnum )  gs->newnum = ++nn;
+      if ( !gt->newnum )  gt->newnum = ++nt;
+      if ( !pt1->edg[i] && pt1->tag[i] == M_NOTAG )  continue;
+      else if ( pt1->adj[i] && (k > pt1->adj[i]) )   continue;
+      nedge++;
+      if ( pt1->tag[i] & M_RIDGE_GEO )  nridge++;
+      if ( pt1->tag[i] & M_REQUIRED )   nrequis++;
+    } 
+    
+  }
+  
+  Tet *ff_t;
+  if ( choix == 6 && sm->ntet ) ff_t  = new Tet[sm->ntet];
+  Tet *ff_tt = ff_t;
+
+  if ( choix == 6 && sm->ntet ) {
+    int iv[4],lab;
+    for (k=1; k<=sm->ntet; k++) {
+      ptt  = &sm->tetra[k];
+      if ( !ptt->v[0] )  continue;
+      for (i=0; i<4; i++)
+        iv[i] = sm->point[ptt->v[i]].tmp-1;
+      lab = ptt->ref;
+      (*ff_tt++).set( ff_v, iv, lab); 
+    }
+  }
+
+
+  // les autres avoir par la suite
+  if( verbosity>1 ) cout << " nv " << ff_nv << " nbe" << ff_nbe << endl;
+  if( choix == 6 && sm->ntet){
+    int ff_nt = sm->ntet;
+    Mesh3 *TH3_T = new Mesh3(ff_nv,ff_nt,ff_nbe,ff_v,ff_t,ff_b);   
+    TH3_T->BuildGTree();
+    return TH3_T;
+  }
+  else{
+    Mesh3 *TH3_T = new Mesh3(ff_nv,ff_nbe,ff_v,ff_b);   
+    return TH3_T;
+  }
+}
+
+void solyams_pSurfMesh( yams_pSurfMesh sm, const int &type, const KN<double> & tabsol, float hmin, float hmax){
+  yams_pPoint ppt;
+  yams_pMetric  pm;
+  int i,k;
+  double   sizeh,m[6],lambda[3],vp[2][2],vp3[3][3];
+  hmin =  FLT_MAX;
+  hmax = -FLT_MAX;
+  float vpmin=FLT_MAX, vpmax=-FLT_MAX, mmin=FLT_MAX,mmax=-FLT_MAX;
+  
+  if(type == 1)
+    {
+      for (k=1; k<=sm->npfixe; k++) {
+	ppt = &sm->point[k];
+	ppt->size = (float) tabsol[k-1];// change FH nov 2010: k -> k-1
+	hmin = min(ppt->size,hmin);
+	hmax = max(ppt->size,hmax);
+	
+      }
+    }
+  else if( type == 3 ){
+    if ( !sm->metric && !zaldy3(sm,3) )  {
+      ExecError("Pb alloc metric in freeyam ??? ");
+    }
+    
+    for (k=1; k<=sm->npfixe; k++) {
+      ppt = &sm->point[k];    
+      pm  = &sm->metric[k];// coorrection FH dec 2010..
+      memset(pm->m,6*sizeof(float),0.);
+      
+      for (i=0; i<6; i++)
+	m[i] = (float) tabsol[(k-1)*6+i];
+      
+      pm->m[0] = m[0];
+      pm->m[1] = m[1];
+      pm->m[2] = m[3];
+      pm->m[3] = m[2];
+      pm->m[4] = m[4];
+      pm->m[5] = m[5];
+      pm->k1   = pm->k2 = (float)FLT_MAX;
+      for (i=0; i<6; i++)  m[i] = pm->m[i];
+      if ( !eigenv(1,m,lambda,vp3) ) {
+	fprintf(stderr,"  ## ERR 9201, inbbf, Not a metric tensor. Discarded\n");
+	free(sm->metric);
+	sm->metric = 0;
+	ExecError("freeyamerr: ## ERR 9201, inbbf, Not a metric tensor. Discarded");
+      }
+
+      float vmn = min(min(lambda[0],lambda[1]),lambda[2]);
+      float vmx = max(max(lambda[0],lambda[1]),lambda[2]);
+		      
+      vpmin= min(vpmin, vmn);
+      vpmax= max(vpmax,vmx);
+      sizeh     = vpmax;
+      ppt->size = max(1.0 / sqrt(sizeh),EPS);
+      hmin = min(ppt->size,hmin);
+      hmax = max(ppt->size,hmax);
+    }
+  }
+  //if(verbosity>4)
+    {
+      cout << " freeyams (metric in) :  hmin " <<  hmin << " , hmax " << hmax << endl;
+      if(type==3)
+      cout << "             min max of eigen val  " << vpmin << " " << vpmax << endl;
+    }
+
+  if(type==3 && vpmin <0 )
+    {
+      cout << "   Error Freeyam :  metric    min max of eigen val  " << vpmin << " " << vpmax << endl;
+      ExecError("Error in metric definition freeyams (negative eigen value");
+    }
+}
+
+
+static const int wrapper_intopt[13] = {  0,  3,  7,  8, 9,
+				       11, 12, 13, 14, 15,
+				       17, 18, 22};
+
+/*
+static const int wrapper_fopt[12] = {  0, 1, 3,  4,  6,
+                                       7, 8, 9, 10, 11,
+				      12, 13};
+*/
+static const int wrapper_fopt[11] = { 1, 3,  4,  6,
+                                      7, 8, 9, 10, 11,
+				      12, 13};
+
+void yams_inival(int intopt[23],double fopt[14]){
+
+/*
+    intopt : 0  !! anisotropie
+             1  !! ecp  // enl
+             2  !! extended out put file // enl
+	     3  !! FE correction 
+	     4  !! Formatted (ascii) output file // enl
+	     5  !! save metric file // enl
+	     6  !! msh2  // enl
+	     7  !! Split multiple connected points
+	     8  !! memory
+	     9  !! connected component
+	    10  !! vrml  //enl
+	    11  !! imprim  
+	    12  !! nm : Create point on straight edge (no mapping)
+	    13  !! nc : No validity check during smoothing (opt. 9)
+	    14  !! np : Specify number of points desired
+	    15  !! nit : Nb Iter
+	    16  !! nq  : Output quads // enl
+	    17  !! nr  : No ridge detection
+	    18  !! ns  : No point smoothing
+	    19  !! no  : No output file  // enl
+	    20  !! ref : Ignore face references // enl
+	    // rajouter lors de l'ouverture du fichiers yams
+	    21  !! absolute : opts.ctrl &= ~REL; par default 1 // enl
+	    22  !! set optim option
+
+    fopt   : 0  !! iso 
+             1  !! eps 
+	     pas de 2
+	     3  !! opts.lambda
+	     4  !! opts.mu
+	     pas de 5
+	     6  !! hgrad  :: opts.shock
+	     7  !! hmin   :: opts.hmin
+	     8  !! hmax   :: opts.hmax
+	     // rajouter lors de l'ouverture du fichiers yams
+	     9  !! tolerance :: opts.bande
+	     10 !! degrad :: opts.degrad
+	     11 !! declic :: opts.declic 
+	     12 !! walton :: opts.walton = cos(dummy/180.0*M_PI);
+	     13 !! ridge  :: opts.ridge
+   */
+
+/* Set default values for options */
+  // fopt 5,
+  fopt[7]   = -2.0;    
+  fopt[8]   = -2.0;
+  fopt[6]   =   1.3;       /* default mesh gradation     */
+  fopt[1]   =   0.01;      /* geometric approximation    */
+  fopt[0]   =   0.0;
+  fopt[11]  =   1.0 / BETAC;
+  fopt[3]   =   -1.0;
+  fopt[4]   =   -1.0;
+  fopt[13]  =   45.;  // default RIDG = 45.
+  //opts.ridge  =   cos(RIDG*M_PI/180.);
+  //opts.geom   =   cos(GEOM*M_PI/180.);
+  fopt[12] =   COS45DEG;  /* Walton limitation          */
+  fopt[9]  =   -2;       /* default = 1 unit           */
+  fopt[10] =   QUALCOE;   /* quality degradation        */
+  //opts.ctrl   =   REL | ISO;  initialisation by default
+  
+  
+
+  // intopt :: 3,7,13,14,15,20
+  intopt[15]  = -1;
+  intopt[13]  = 0;
+  intopt[14]  = -1;
+  
+  /* get decimation parameters */
+  intopt[20] = 0;
+  intopt[3]  = 0;
+  intopt[7]  = 0;//  Split multiple connected points  (no manifold) 
+  intopt[22] = 1;// set optim option
+
+  // demander P. Frey
+  intopt[0] = 0; //  anisotropie  
+  intopt[1] = 0; // 
+  intopt[2] = 0;  
+    
+  intopt[4] = 0;
+  intopt[5] = 0;
+  intopt[6] = 0;
+
+  intopt[8] = -1; // memory 
+  intopt[9] =  -1; // par default   connex connected component (tout) 
+  intopt[10] = 0;// vrml 
+  intopt[11] = verbosity;
+  intopt[12] = 0;   //nm
+
+  intopt[16] = 0; // quad
+  intopt[17] = 0;// noridge
+  intopt[18] = 0;// nosmooth
+  intopt[19] = 1;// 1
+  intopt[21] = 1;
+  
+}
+
+class yams_Op: public E_F0mps 
+{
+public:
+  typedef pmesh3  Result;
+  Expression eTh;
+  int nbsol;
+  int nbsolsize;
+  int type;
+  int dim;
+  vector<Expression> sol;
+
+  static const int n_name_param = 14; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack, long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  int  arg(int i,Stack stack, int a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  bool  arg(int i,Stack stack, bool a ) const{ return nargs[i] ? GetAny< bool >( (*nargs[i])(stack) ): a;}
+  
+  
+public:
+  yams_Op(const basicAC_F0 &  args) : sol( args.size()-1 )
+  {
+    
+    cout << "yams"<< endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    eTh=to<pmesh3>(args[0]); 
+    dim=3;
+    nbsol = args.size()-1;
+    if(nbsol >1) 
+      CompileError(" yams accept only one solution ");
+    int ksol=0; 
+      
+    if(nbsol == 1){
+      int i=1;
+      if (args[i].left()==atype<E_Array>())
+	{
+	  const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+	  ffassert(a);
+	  ksol+=a->size(); 
+	}
+      else
+	ksol++;
+      sol.resize(ksol); 
+      
+      // type :: 1 sca, 2 vector, 3 symtensor
+      
+      ksol=0; 
+      nbsolsize=0;
+      type = 0;
+          
+      if (args[i].left()==atype<E_Array>())
+	{
+	  const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+	  ffassert(a);
+	  int N=a->size();
+	  nbsolsize=nbsolsize+N;
+	  switch (N){
+	    /*
+	      case 3 :
+		type[i-1]=2; 
+		for (int j=0;j<N;j++)             
+		sol[ksol++]=to<double>((*a)[j]);
+		break;
+	    */
+	  case 6 :
+	    type=3;   
+	    for (int j=0;j<N;j++)             
+	      sol[ksol++]=to<double>((*a)[j]); 
+	    break;
+	  default :
+	    CompileError(" 3D solution for yams is a scalar (1 comp) or a symetric tensor (6 comp)");
+	    break;
+	  }
+	}
+      else 
+	{
+	  type=1;
+	  nbsolsize=nbsolsize+1;
+	  sol[ksol++]=to<double>(args[i]);
+	} 
+
+      if( nargs[2]  ) 
+	CompileError(" we give two metric for yams ");
+    }
+
+  }
+    
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype< pmesh3 >(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new yams_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+  operator aType () const { return atype< pmesh3 >();} 
+};
+
+
+basicAC_F0::name_and_type  yams_Op::name_param[]= {
+
+  {  "loptions", &typeid(KN_<long>)},  //0
+  {  "doptions", &typeid(KN_<double>)},
+  {  "metric", &typeid(KN_<double>)},
+  {  "aniso", &typeid(bool)} ,//3
+  {  "mem", &typeid(long)} ,
+  {  "hmin", &typeid(double)} ,
+  {  "hmax", &typeid(double)} ,//6
+  {  "gradation", &typeid(double)} ,
+  {  "option", &typeid(long)} , // 8
+  {  "ridgeangle", &typeid(double)} ,//9
+  {  "absolute", &typeid(bool)}, //10 
+  {  "verbosity", &typeid(long)}, //11 
+    
+  {  "nr", &typeid(long)}, // 12 no ridge
+  {  "ns", &typeid(long)} // 13 no point smoothing
+};
+
+AnyType yams_Op::operator()(Stack stack)  const 
+{
+  // initialisation
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  ffassert( pTh );
+  Mesh3 &Th3=*pTh;
+  int nv=Th3.nv;
+  int nt=Th3.nt;
+  int nbe=Th3.nbe;
+
+  KN<int> defaultintopt(23);
+  KN<double> defaultfopt(14);
+  defaultintopt = 0;
+  defaultfopt   = 0.;
+  yams_inival( defaultintopt, defaultfopt);
+  
+  KN<int> intopt(23);
+  for(int ii=0; ii< 23; ii++){
+    intopt[ii]=defaultintopt[ii];
+  }
+ 
+  KN<double> fopt(14);
+  for(int ii=0; ii< 14; ii++){
+    fopt[ii]=defaultfopt[ii];
+  }
+  assert( fopt.N() == 14 );
+  
+  if( nargs[0] ){
+    KN<int> intopttmp =  GetAny<KN_<long> >( (*nargs[0])(stack) );
+    if( intopttmp.N() != 13 ){
+      cerr <<"the size of vector loptions is 13 "  << endl;
+      exit(1);
+    }
+    else{
+      for(int ii=0; ii<13; ii++){
+	intopt[ wrapper_intopt[ii] ] = intopttmp[ii];
+      }
+    }
+  }
+  
+  if( nargs[1] ){
+    KN<double> fopttmp =  GetAny<KN_<double> >( (*nargs[1])(stack) );
+    if( fopttmp.N() != 11 ){
+      cerr <<"the size of vector loptions is 11 not "  << fopttmp.N()<< endl;
+	ExecError("FreeYams");
+    }
+    else{
+      for(int ii=0; ii<11; ii++){
+	fopt[ wrapper_fopt[ii] ] = fopttmp[ii];
+      }
+    }
+  }
+ 
+  intopt[0] = arg(3,stack,intopt[0]!=1);
+  intopt[8] = arg(4,stack,intopt[8]);
+  fopt[7] = arg(5,stack,fopt[7]);
+  fopt[8] = arg(6,stack,fopt[7]);
+  fopt[6] = arg(7,stack,fopt[6]);
+  intopt[22] = arg(8,stack, intopt[22] ); // optim option  
+  if(nargs[9]) intopt[17]=1; 
+  fopt[13] = arg(9,stack,fopt[13]); // ridge angle
+  intopt[21] = arg(10,stack, intopt[21] ); // absolue 
+  intopt[11] = arg(11,stack,(int) verbosity); // verbosity 
+  intopt[17] = arg(12,stack,intopt[17]); // no ridge 
+  intopt[18] = arg(13,stack,intopt[18]); // nb smooth 
+  if(verbosity>1)
+     {
+       cout << " fopt = [";
+       for(int i=0;i<11;++i)
+	   cout   << fopt[wrapper_fopt[i]]  <<  (i < 10 ? ",": "];\n") ;       
+       cout << " intopt = [";
+       for(int i=0;i<13;++i)
+	   cout << intopt[wrapper_intopt[i]]  <<  (i < 12 ? ",": "];\n" );         
+     }
+
+    
+ 
+  
+  /*
+    KN<int> intopt(arg(0,stack,defaultintopt));
+    assert( intopt.N() == 23 );
+    KN<double> fopt(arg(1,stack,defaultfopt));
+    assert( fopt.N() == 14 );
+  */
+  KN<double> metric;
+    
+  int mtype=type;
+  if( nargs[2]  )
+    { 
+      metric = GetAny<KN_<double> >( (*nargs[2])(stack) );
+      if(metric.N()==Th3.nv){
+	mtype=1;
+	intopt[1]=0;
+      }
+      else if(metric.N()==6*Th3.nv){ 
+	intopt[1]=1; 
+	mtype=3;
+      }
+      else 
+	cerr << "sizeof vector metric is incorrect, size will be Th.nv or 6*Th.nv" << endl;
+    }  
+  else if(nbsol>0)
+    {
+    if( type == 1 )
+      {
+	intopt[1]=0;
+	metric.resize(Th3.nv);
+	metric=0.;
+      }
+    else if( type ==3 )
+      {
+	intopt[1]=1;
+	metric.resize(6*Th3.nv);
+	metric=0.;
+      }
+    }
+  else
+    {
+      if( intopt[1]==0 ){ metric.resize(Th3.nv); metric=0.;}
+      else if ( intopt[1]==1 ){ metric.resize(6*Th3.nv); metric=0.;}
+    }
+  // mesh for yams
+  yams_pSurfMesh yamsmesh;
+  yamsmesh = (yams_pSurfMesh)calloc(1,sizeof(yams_SurfMesh));
+  if ( !yamsmesh ){
+    cerr << "allocation error for SurfMesh for yams" << endl;
+  }
+  yamsmesh->infile  = NULL;
+  yamsmesh->outfile = NULL;
+  yamsmesh->type    = M_SMOOTH | M_QUERY | M_DETECT | M_BINARY | M_OUTPUT;
+  
+  
+  mesh3_to_yams_pSurfMesh( Th3 , intopt[8], intopt[22], yamsmesh);
+    
+  
+  // solution for freeyams2
+  if(nbsol)
+    {
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      
+      KN<bool> takemesh(nv);
+      takemesh=false;
+      for(int it=0;it<nt;it++){
+	for(int iv=0;iv<4;iv++){
+	  int i=Th3(it,iv);
+	  
+	  if(takemesh[i]==false){
+	  mp3->setP(&Th3,it,iv);
+	  
+	  for(int ii=0;ii<nbsolsize;ii++){
+	    metric[i*nbsolsize+ii] = GetAny< double >( (*sol[ii])(stack) );
+	  }
+	  takemesh[i] = true; 
+	  }
+      }
+      }
+    }
+  if(verbosity>10)    
+  cout << "nbsol  " <<  nargs[2] << endl;
+  if( nargs[2] || (nbsol > 0) ){ 
+    float hmin,hmax;
+    solyams_pSurfMesh( yamsmesh, mtype, metric, hmin, hmax);
+    yamsmesh->nmfixe = yamsmesh->npfixe;
+    if( fopt[7] < 0.0 ) 
+      fopt[7]= max(fopt[7],hmin);
+    if( fopt[8] < 0.0 )
+      fopt[8]=max(fopt[8],hmax);
+  }
+  else{
+    yamsmesh->nmfixe = 0;
+  }
+  int infondang=0, infocc=0;
+  int res = yams_main( yamsmesh, intopt, fopt, infondang, infocc);
+  if(verbosity>10)
+   cout << " yamsmesh->dim " << yamsmesh->dim << endl;
+  if( res > 0){
+    cout << " problem with yams :: error " <<  res << endl; 
+      ExecError("Freeyams error");
+  }
+  
+  Mesh3 *Th3_T = yams_pSurfMesh_to_mesh3( yamsmesh, infondang, infocc ,intopt[22] );
+  
+  // recuperer la solution ????
+  if(verbosity>10)
+    {
+      cout << &yamsmesh->point << " " << &yamsmesh->tria << " "  <<&yamsmesh->geom << " "  << &yamsmesh->tgte << endl;
+      cout << &yamsmesh << endl;
+      
+    }
+  free(yamsmesh->point);
+  free(yamsmesh->tria);
+  free(yamsmesh->geom);
+  free(yamsmesh->tgte);
+  if ( yamsmesh->metric ) free(yamsmesh->metric);
+  if ( yamsmesh->edge )   free(yamsmesh->edge);
+  if ( yamsmesh->tetra )   free(yamsmesh->tetra);
+  free(yamsmesh);
+
+  *mp=mps;
+  Add2StackOfPtr2FreeRC(stack,Th3_T);
+  return SetAny<pmesh3>(Th3_T);
+}
+
+
+
+/*  class Init1 { public:
+  Init1();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  //typedef Mesh3 *pmesh3;
+  if(verbosity) cout << " load: freeyams  " << endl;
+  
+  Global.Add("freeyams","(",new OneOperatorCode<yams_Op>);
+ 
+}
+
+
+#define  WITH_NO_INIT
+#include "msh3.hpp" 
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/funcTemplate.cpp b/examples++-load/funcTemplate.cpp
new file mode 100644
index 0000000..1c63aee
--- /dev/null
+++ b/examples++-load/funcTemplate.cpp
@@ -0,0 +1,131 @@
+// Example C++ function "CppModTemplate" dynamically loaded into "load.edp"
+// ------------------------------------------------------------------------
+#include <ff++.hpp>
+#include "AFunction_ext.hpp" // Extension of "AFunction.hpp" to deal with more than 3 parameters function
+using namespace Fem2D;
+
+// see src/femlib/RNM.hpp
+
+// dummy routine to understand how to use vector
+double CppModTemplate3(KN<double> *const & A,                            // OUTPUT
+		       KN<double> *const & B, KN<double> *const & C)     // INPUTS
+{
+  
+  // Remarque:
+  // It might prove usefull to have a look in the cpp file where KN is defined: src/femlib/RNM.hpp
+  //
+  // To access value at node i of vector N, do as follow: *(N[0]+i)
+  // Explanation (C++ for dummies as I am ;-):
+  //   N         is an alias to the KN object.
+  //   N[0]      is a pointer to the first element of the vector.
+  //   N[0]+i    is a pointer to the ith element of the vector.
+  //   *(N[0]+i) is the value of the ith element of the vector.
+  
+  int nn = A->N(); // get number of nodes
+
+  cout << "nn: " << nn << endl;
+  
+  for(int i=0; i<nn; i++) {
+    (*(A[0]+i)) = (*(B[0]+i)) *  (*(C[0]+i));
+    cout << (*(A[0]+i)) << endl;
+  }
+
+  return 0.0;  // dummy return value.
+}
+
+double CppModTemplate4(KN<double> *const & A,                            // OUTPUT
+		       KN<double> *const & B, KN<double> *const & C,     // INPUTS
+		       KN<double> *const & D)   
+{
+  int nn = A->N(); // get number of nodes
+  cout << "nn: " << nn << endl;
+  for(int i=0; i<nn; i++) {
+    (*(A[0]+i)) = (*(B[0]+i)) *  (*(C[0]+i)) * (*(D[0]+i));
+    cout << (*(A[0]+i)) << endl;
+  }
+  return 0.0;  // dummy return value.
+}
+
+double CppModTemplate5(KN<double> *const & A,                            // OUTPUT
+		       KN<double> *const & B, KN<double> *const & C,     // INPUTS
+		       KN<double> *const & D, KN<double> *const & E)   
+{
+  int nn = A->N(); // get number of nodes
+  cout << "nn: " << nn << endl;
+  for(int i=0; i<nn; i++) {
+    (*(A[0]+i)) = (*(B[0]+i)) *  (*(C[0]+i)) * (*(D[0]+i)) * (*(E[0]+i));
+    cout << (*(A[0]+i)) << endl;
+  }
+  return 0.0;  // dummy return value.
+
+}
+
+
+double CppModTemplate6(KN<double> *const & A,                            // OUTPUT
+		       KN<double> *const & B, KN<double> *const & C,     // INPUTS
+		       KN<double> *const & D, KN<double> *const & E,
+		       KN<double> *const & F)   
+{
+  int nn = A->N(); // get number of nodes
+  cout << "nn: " << nn << endl;
+  for(int i=0; i<nn; i++) {
+    (*(A[0]+i)) = (*(B[0]+i)) *  (*(C[0]+i)) * (*(D[0]+i)) * (*(E[0]+i)) * (*(F[0]+i));
+    cout << (*(A[0]+i)) << endl;
+  }
+  return 0.0;  // dummy return value.
+}
+
+double CppModTemplate7(KN<double> *const & A,                            // OUTPUT
+		       KN<double> *const & B, KN<double> *const & C,     // INPUTS
+		       KN<double> *const & D, KN<double> *const & E,
+		       KN<double> *const & F, KN<double> *const & G)   
+{
+  int nn = A->N(); // get number of nodes
+  cout << "nn: " << nn << endl;
+  for(int i=0; i<nn; i++) {
+    (*(A[0]+i)) = (*(B[0]+i)) *  (*(C[0]+i)) * (*(D[0]+i)) * (*(E[0]+i)) * (*(F[0]+i)) * (*(G[0]+i));
+    cout << (*(A[0]+i)) << endl;
+  }
+  return 0.0;  // dummy return value.
+}
+
+double CppModTemplate8(KN<double> *const & A,                            // OUTPUT
+		       KN<double> *const & B, KN<double> *const & C,     // INPUTS
+		       KN<double> *const & D, KN<double> *const & E,
+		       KN<double> *const & F, KN<double> *const & G,
+		       KN<double> *const & H)   
+{
+  int nn = A->N(); // get number of nodes
+  cout << "nn: " << nn << endl;
+  for(int i=0; i<nn; i++) {
+    (*(A[0]+i)) = (*(B[0]+i)) *  (*(C[0]+i)) * (*(D[0]+i)) * (*(E[0]+i)) * (*(F[0]+i)) * (*(G[0]+i)) * (*(H[0]+i)) ;
+    cout << (*(A[0]+i)) << endl;
+  }
+  return 0.0;  // dummy return value.
+}
+
+double funcs3(Stack s,const double &a,const  double &b,const  double &c){  return a+b+c;}
+double funcs2(Stack s,const double &a,const  double &b){  return a+b;}
+double funcs1(Stack s,const double &a){  return a;}
+
+//   add the function name to the freefem++ table 
+/*  class Init { public:
+  Init();
+};
+$1 */
+static void Load_Init(){
+  // Add function with 3 arguments
+  Global.Add("funcs1","(",new OneOperator1s_<double, double>(funcs1)); 
+  Global.Add("funcs2","(",new OneOperator2s_<double, double, double >(funcs2)); 
+  Global.Add("funcs3","(",new OneOperator3s_<double, double, double, double  >(funcs3)); 
+  Global.Add("CppModTemplate3","(",new OneOperator3_<double, KN<double>*, KN<double>*, KN<double>*>(CppModTemplate3)); 
+  Global.Add("CppModTemplate4","(",new OneOperator4_<double, KN<double>*, KN<double>*, KN<double>*, KN<double>*>(CppModTemplate4)); 
+  Global.Add("CppModTemplate5","(",new OneOperator5_<double, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*>(CppModTemplate5)); 
+  Global.Add("CppModTemplate6","(",new OneOperator6_<double, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*>(CppModTemplate6)); 
+  Global.Add("CppModTemplate7","(",new OneOperator7_<double, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*>(CppModTemplate7)); 
+  Global.Add("CppModTemplate8","(",new OneOperator8_<double, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*, KN<double>*>(CppModTemplate8)); 
+}
+
+
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/funcTemplate.edp b/examples++-load/funcTemplate.edp
new file mode 100644
index 0000000..0246624
--- /dev/null
+++ b/examples++-load/funcTemplate.edp
@@ -0,0 +1,51 @@
+
+load "funcTemplate"
+ 
+mesh Th=square(3,3);
+fespace Vh(Th,P1);
+
+Vh N;
+for(int i=0; i<N.n; i++) {
+ N[][i] = i+0.1;
+}
+
+Vh P = 2.0;
+Vh uh1;
+real a;
+
+// OUTPUT:
+//    uh1[]
+// INPUT:
+//    N[]
+//    P[]
+// Description:
+//  make the product N[] .* P[]
+//
+CppModTemplate3(uh1[], N[], P[]);
+cout << endl;
+cout << "uh1: " << uh1[].min  << " " << uh1[].max << endl;
+
+
+CppModTemplate4(uh1[], N[], P[], P[]);
+cout << endl;
+cout << "uh1: " << uh1[].min  << " " << uh1[].max << endl;
+
+CppModTemplate5(uh1[], N[], P[], P[], P[]);
+cout << endl;
+cout << "5 args: uh1: " << uh1[].min  << " " << uh1[].max << endl;
+
+CppModTemplate6(uh1[], N[], P[], P[], P[], P[]);
+cout << endl;
+cout << "6 args: uh1: " << uh1[].min  << " " << uh1[].max << endl;                                                                                                                                           
+                                                                                                                                           
+CppModTemplate7(uh1[], N[], P[], P[], P[], P[], P[]);
+cout << endl;
+cout << "7 args: uh1: " << uh1[].min  << " " << uh1[].max << endl; 
+
+
+CppModTemplate8(uh1[], N[], P[], P[], P[], P[], P[], P[]);
+cout << endl;
+cout << "8 args: uh1: " << uh1[].min  << " " << uh1[].max << endl; 
+cout << " funcs1 " << funcs1(2) << endl;
+cout << " funcs2 " << funcs2(2,3) << endl;
+cout << " funcs3 " << funcs3(1,2,3) << endl;
\ No newline at end of file
diff --git a/examples++-load/glumesh3D.edp b/examples++-load/glumesh3D.edp
new file mode 100755
index 0000000..364a78a
--- /dev/null
+++ b/examples++-load/glumesh3D.edp
@@ -0,0 +1,54 @@
+load "msh3"
+
+real x0=-1.,x1=-0.5;
+real y0=-0.5,y1=0.5;
+
+mesh Th1=square(5,8,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+x0=-0.5;
+x1=-0.1;
+y0=-1;
+y1=1;
+mesh Th2=square(10,16,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+
+int[int] r1=[2,0],  r2=[4,0];
+Th1=change(Th1,label=r1);
+Th2=change(Th2,label=r2);
+
+plot( Th1, Th2, wait=1 );
+
+verbosity=2;
+
+cout << "================" << endl;
+cout << "   gluing mesh  " << endl;
+mesh Th2D=Th1+Th2;
+cout << "Vertex, Triangle, Border " << Th2D.nv << " "<< Th2D.nt << " " <<  endl; 
+//plot( Th2D, wait=1 );
+savemesh( Th2D, "glu2D.mesh");
+
+
+func zmin=0.;
+func zmax=1.;
+int MaxLayer=10;
+
+mesh3 Th31=buildlayers(Th1,MaxLayer,zbound=[zmin,zmax]); 
+savemesh( Th31, "bl31.mesh");
+
+mesh3 Th32=buildlayers(Th2,MaxLayer,zbound=[zmin,zmax]); 
+savemesh( Th32, "bl32.mesh");
+
+mesh3 Tht=Th31+Th32;
+savemesh( Tht, "glu3D.mesh");
+
+cout << "Vertex, Tet, Triangle " << Tht.nv << " "<< Tht.nt << " " << Tht.nbe << endl; 
+cout << "area  border = " << int2d(Tht)(1.) << endl; 
+verbosity =3;
+Tht = change(Tht,rmInternalFaces=1);
+cout << "area  border = " << int2d(Tht)(1.) <<endl;
+verbosity =1;
+func mv1x = 1+x;
+func mv1y = y;
+func mv1z = z;
+mesh3 Thmvs1 = movemesh3(Tht, transfo=[mv1x,mv1y,mv1z]);
+savemesh(Thmvs1,"movemeshglumesh.mesh");
diff --git a/examples++-load/gmsh.cpp b/examples++-load/gmsh.cpp
new file mode 100644
index 0000000..8f511c3
--- /dev/null
+++ b/examples++-load/gmsh.cpp
@@ -0,0 +1,841 @@
+// ORIG-DATE:   September 2009
+// -*- Mode : c++ -*%
+//
+// SUMMARY  : interface avec le logiciel gmsh    
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+//  FH   July 2009
+//   comment all
+//       Th3_t->BuildBound();
+//       Th3_t->BuildAdj();
+//       Th3_t->Buildbnormalv();  
+//       Th3_t->BuildjElementConteningVertex();
+//   is now in the constructor of Mesh3 to be consistante. 
+//   
+//  Vincent HUBER - vincent.huber at cemosis.fr   October 2014
+//  manage verbosity levels
+//
+#include "ff++.hpp"
+
+using namespace Fem2D;
+
+// Table of number of vertex for an element type of gmsh 
+static const int nvElemGmsh[30] = { 2, 3, 0, 4, 0, 
+				    0, 0, 0, 0, 0, 
+				    0, 0, 0, 0, 1, 
+				    0, 0, 0, 0, 0, 
+				    0, 0, 0, 0, 0, 
+				    0, 0, 0, 0, 0 };   
+// we considerer only edges, triangles and tetrahedrons in Freefem++
+// 15 :: Vertex Corner
+// 1  :: Edge/line
+// 2  :: triangles
+// 4  :: tetrahedrons
+void SwapBytes(char *array, int size, int n)
+  {
+    char *x = new char[size];
+    for(int i = 0; i < n; i++) {
+      char *a = &array[i * size];
+      memcpy(x, a, size);
+      for(int c = 0; c < size; c++)
+        a[size - 1 - c] = x[c];
+    }
+    delete [] x;
+  }
+
+
+class GMSH_LoadMesh_Op : public E_F0mps 
+{
+public:
+  Expression filename;
+  static const int n_name_param = 2; // 
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+public:
+  GMSH_LoadMesh_Op(const basicAC_F0 &  args,Expression ffname) 
+    : filename(ffname)
+  {
+    if(verbosity>1) cout << "Load mesh given by GMSH " << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+basicAC_F0::name_and_type GMSH_LoadMesh_Op::name_param[]= {
+  {  "reftri", &typeid(long)},
+  {  "renum", &typeid(long)}
+};
+
+
+class  GMSH_LoadMesh : public OneOperator { public:  
+    GMSH_LoadMesh() : OneOperator(atype<pmesh>(),atype<string *>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new GMSH_LoadMesh_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+Mesh * GMSH_Load(const string & filename)
+  {
+    // variable freefem++
+    int nv, nt=0, nbe=0;
+    Mesh::Vertex   *vff;
+    map<int,int> mapnumv;
+
+    // loading mesh and reading mesh in gmsh are in the file GModelIO_Mesh.cpp (directory Geo) 
+    char str[256]  = "ZZZ";
+    double version = 2.0;
+    bool binary = false, swap = false, postpro = false;
+    
+    FILE *fp = fopen(filename.c_str(), "rb");
+    if(!fp){
+      cerr << "Unable to open file " << filename.c_str() << endl;
+      exit(1);
+    }
+    
+    while( !feof(fp) ){
+      fgets(str, sizeof(str), fp);  
+      if( str[0] == '$'){
+	if(!strncmp(&str[1], "MeshFormat", 10)) {
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  int format, size;
+	  if(sscanf(str, "%lf %d %d", &version, &format, &size) != 3) exit(1);
+	  if(verbosity>1) cout << "Mesh Format is " <<  format << endl;
+	  if(format){
+	    binary = true;
+	    if(verbosity>2) cout << "Mesh is in binary format" << endl;
+	    int one;
+	    if(fread(&one, sizeof(int), 1, fp) != 1) exit(1);
+	    if(one != 1){
+	      swap = true;
+	      if(verbosity>2) cout << "Swapping bytes from binary file" << endl;
+	    }
+	  }
+	}
+	else if(!strncmp(&str[1], "PhysicalNames", 13)) {	  
+	  if(verbosity>0) cout << " PhysicalNames is not considered in freefem++ " << endl;
+	}
+	
+	else if(!strncmp(&str[1], "NO", 2) || !strncmp(&str[1], "Nodes", 5) ||
+		!strncmp(&str[1], "ParametricNodes", 15)) {
+	  
+	  const bool parametric = !strncmp(&str[1], "ParametricNodes", 15);
+	  if( parametric == true ){
+	    cerr << " ParametricNodes is not considered yet in freefem++" << endl;
+	    exit(1);
+	  }
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  
+	  if(sscanf(str, "%d", &nv) != 1) exit(1);
+	  printf("%d vertices\n", nv);
+	  
+	  // local variables freefem++
+	  vff = new Mesh::Vertex[nv]; 
+
+	  int minVertex = nv + 1, maxVertex = -1;
+	  for(int i = 0; i < nv; i++) {
+	    int num;	
+	    double xyz[3], uv[2];
+	    
+	    //if (!parametric){		
+	    if(!binary){
+	      if (fscanf(fp, "%d %lf %lf %lf", &num, &xyz[0], &xyz[1], &xyz[2]) != 4)
+		exit(1);	  
+	    }
+	    else{
+	      if(fread(&num, sizeof(int), 1, fp) != 1) exit(1);
+	      if(swap) SwapBytes((char*)&num, sizeof(int), 1);
+	      if(fread(xyz, sizeof(double), 3, fp) != 3) exit(1);
+	      if(swap) SwapBytes((char*)xyz, sizeof(double), 3);
+	    }
+	    
+	    assert( abs(xyz[2]) < 1.e-7);
+	    vff[i].x = xyz[0];
+	    vff[i].y = xyz[1];
+	    vff[i].lab = 1;
+	    mapnumv[num] = i;
+	  }
+	}
+	else if(!strncmp(&str[1], "ELM", 3) || !strncmp(&str[1], "Elements", 8)) {
+
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  int numElements;
+	  sscanf(str, "%d", &numElements);
+	   
+	  if(verbosity>2) cout << "Loading elements\n" << endl; 
+	  if(!binary){
+	    for(int i = 0; i < numElements; i++) {
+	      int num, type, physical = 0, elementary = 0, partition = 0, numVertices;
+	      if(version <= 1.0){
+		fscanf(fp, "%d %d %d %d %d", &num, &type, &physical, &elementary, &numVertices);		
+	      }
+	      else{
+		int numTags;
+		fscanf(fp, "%d %d %d", &num, &type, &numTags);
+		for(int j = 0; j < numTags; j++){
+		  int tag;
+		  fscanf(fp, "%d", &tag);       
+		  if(j == 0)      physical = tag;
+		  else if(j == 1) elementary = tag;
+		  else if(j == 2) partition = tag;
+		  // ignore any other tags for now
+		}
+		assert(type>=1 && type <=31);
+		if( (numVertices = nvElemGmsh[type-1]) == 0){
+		  cerr << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		  exit(1);
+		}
+	      }
+	      
+	      if( type == 1 ) nbe++;
+	      if( type == 2 ) nt++;
+	      if( type == 4 ){
+					cout << "We are loading a two dimensionnal mesh " << endl;
+					exit(1);
+	      }
+	      
+	      int indices[60];
+	      for(int j = 0; j < numVertices; j++) fscanf(fp, "%d", &indices[j]);
+	      
+	    }
+	  }
+	  else{
+	    int numElementsPartial = 0;
+	    while(numElementsPartial < numElements){
+	      int header[3];
+	      if( fread(header, sizeof(int), 3, fp) != 3 ) exit(1);
+	      if(swap) SwapBytes((char*)header, sizeof(int), 3);
+	      int type = header[0];
+	      int numElms = header[1];
+	      int numTags = header[2];
+	      int numVertices; 
+	      assert(type>=1 && type <=31);
+	      if( (numVertices = nvElemGmsh[type-1]) == 0){
+		cerr << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		exit(1);
+	      }
+	      unsigned int n = 1 + numTags + numVertices;
+	      int *data = new int[n];
+
+	      for(int i = 0; i < numElms; i++) {
+		if(fread(data, sizeof(int), n, fp) != n) exit(1);
+		if(swap) SwapBytes((char*)data, sizeof(int), n);
+		int num = data[0];
+		int physical = (numTags > 0) ? data[4 - numTags] : 0;
+		int elementary = (numTags > 1) ? data[4 - numTags + 1] : 0;
+		int partition = (numTags > 2) ? data[4 - numTags + 2] : 0;
+		int *indices = &data[numTags + 1];
+		
+		if( type == 1 )  nbe++;
+		if( type == 2 )  nt++;
+		if( type == 4 ){
+		  cout << "We are loading a two dimensionnal mesh " << endl;
+		  exit(1);
+		}
+		
+	      }
+	      delete [] data;
+	      numElementsPartial += numElms;
+	      
+	    }
+	  }
+	  break;
+	}
+      }
+    }
+    fclose(fp);
+    
+    Mesh::Triangle *tff  = new Mesh::Triangle[nt];
+    Mesh::Triangle *ttff = tff;
+
+    Mesh::BorderElement *bff  = new Mesh::BorderElement[nbe];
+    Mesh::BorderElement *bbff = bff;
+
+    // second reading
+    fp = fopen(filename.c_str(), "rb");
+    
+    while( !feof(fp) ){
+      fgets(str, sizeof(str), fp);  
+      if( str[0] == '$'){
+	
+	if(!strncmp(&str[1], "ELM", 3) || !strncmp(&str[1], "Elements", 8)) {
+
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  int numElements;
+	  sscanf(str, "%d", &numElements);
+	   
+	 
+	  if(!binary){
+
+	    int ie=0; 
+	    int it=0;
+
+	    for(int i = 0; i < numElements; i++) {
+	      int num, type, physical = 0, elementary = 0, partition = 0, numVertices;
+	      if(version <= 1.0){
+		fscanf(fp, "%d %d %d %d %d", &num, &type, &physical, &elementary, &numVertices);		
+	      }
+	      else{
+		int numTags;
+		fscanf(fp, "%d %d %d", &num, &type, &numTags);
+		for(int j = 0; j < numTags; j++){
+		  int tag;
+		  fscanf(fp, "%d", &tag);       
+		  if(j == 0)      physical = tag;
+		  else if(j == 1) elementary = tag;
+		  else if(j == 2) partition = tag;
+		  // ignore any other tags for now
+		}
+		assert(type>=1 && type <=31);
+		if( (numVertices = nvElemGmsh[type-1]) == 0){
+		  cerr << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		  exit(1);
+		}
+	      }
+
+	      int indices[60];
+	      for(int j = 0; j < numVertices; j++) fscanf(fp, "%d", &indices[j]);
+
+	      if( type == 1 ){
+		int iv0,iv1;
+		iv0 = mapnumv[ indices[0] ];	
+		iv1 = mapnumv[ indices[1] ];
+		if(verbosity>2) cout << "Elem " << ie+1 << " " << iv0+1 << " " << iv1+1 << endl;
+		(bbff++)->set(vff, iv0, iv1, physical);
+		ie++;
+	      }
+	      if( type == 2 ){
+		int iv0,iv1,iv2;
+		iv0 = mapnumv[ indices[0] ];	
+		iv1 = mapnumv[ indices[1] ];
+		iv2 = mapnumv[ indices[2] ];	
+		if(verbosity>2) cout << "Triangles " << it+1 << " " << iv0+1 << " " << iv1+1 << " " << iv2+1 << endl;
+		
+		(ttff++)->set(vff, iv0, iv1, iv2, physical);
+		if(verbosity>2) cout << "mes=" << tff[it].area << endl;
+		if( tff[it].area < 1e-8 ){
+		  cout << "bug : mes < 1e-8 !" << endl;
+		  exit(1);
+		}
+		it++;
+	      }
+	    }
+	    assert(it==nt);
+	    assert(ie==nbe);
+	  }
+	  else{
+	    
+	    int ie=0; 
+	    int it=0;
+
+	    int numElementsPartial = 0;
+	    while(numElementsPartial < numElements){
+	      int header[3];
+	      if( fread(header, sizeof(int), 3, fp) != 3 ) exit(1);
+	      if(swap) SwapBytes((char*)header, sizeof(int), 3);
+	      int type = header[0];
+	      int numElms = header[1];
+	      int numTags = header[2];
+	      int numVertices;
+	      assert(type>=1 && type <=31);
+	      if( (numVertices = nvElemGmsh[type-1]) == 0){
+		cerr << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		exit(1);
+	      }
+	      unsigned int n = 1 + numTags + numVertices;
+	      int *data = new int[n];
+	      for(int i = 0; i < numElms; i++) {
+		if(fread(data, sizeof(int), n, fp) != n) exit(1);
+		if(swap) SwapBytes((char*)data, sizeof(int), n);
+		int num = data[0];
+		int physical = (numTags > 0) ? data[4 - numTags] : 0;
+		int elementary = (numTags > 1) ? data[4 - numTags + 1] : 0;
+		int partition = (numTags > 2) ? data[4 - numTags + 2] : 0;
+		int *indices = &data[numTags + 1];
+		
+		if( type == 1 ){
+		  int iv0,iv1;
+		  iv0 = mapnumv[ indices[0] ];	
+		  iv1 = mapnumv[ indices[1] ];
+		  (bbff++)->set(vff, iv0, iv1, physical);
+		  ie++;
+		}
+		if( type == 2 ){
+		  double mes=-1;
+		  int iv0,iv1,iv2;
+		  iv0 = mapnumv[ indices[0] ];	
+		  iv1 = mapnumv[ indices[1] ];
+		  iv2 = mapnumv[ indices[2] ];		
+		  (ttff++)->set(vff, iv0, iv1, iv2, physical,mes);
+		  
+		  it++;
+		}
+		
+	      }
+	      delete [] data;
+	      numElementsPartial += numElms;
+	  
+	      
+	    }
+	    assert(it==nt);
+	    assert(ie==nbe);
+	  }
+	}
+        else if(!strncmp(&str[1], "NodeData", 8)) {
+	  if(verbosity>1) cout << " NodeData is not considered in freefem++ " << endl;
+	}
+	else if(!strncmp(&str[1], "ElementData", 11) ||
+		!strncmp(&str[1], "ElementNodeData", 15)){
+
+	  if(verbosity>1) cout << " ElementData/ElementNodeData is not considered in freefem++ " << endl;
+	}
+      }
+    }
+    fclose(fp);
+
+    Mesh *pTh = new Mesh(nv,nt,nbe,vff,tff,bff);
+    R2 Pn,Px;
+    pTh->BoundingBox(Pn,Px);
+    if(!pTh->quadtree)
+        pTh->quadtree=new Fem2D::FQuadTree(pTh,Pn,Px,pTh->nv);
+
+    return pTh;
+
+  }
+
+
+
+AnyType GMSH_LoadMesh_Op::operator()(Stack stack)  const 
+{
+ 
+  string * pffname= GetAny<string *>((*filename)(stack));
+  int renumsurf = 0; 
+  if( nargs[1] )  renumsurf = GetAny<long>( (*nargs[1])(stack) );
+  assert( renumsurf <=1 && renumsurf >= 0);
+
+  Mesh * Th = GMSH_Load( *pffname ); 
+   
+  Add2StackOfPtr2FreeRC(stack,Th);
+		
+  return Th;
+}
+
+// Load three dimensionnal mesh
+
+class GMSH_LoadMesh3_Op : public E_F0mps 
+{
+public:
+  Expression filename;
+  static const int n_name_param = 2; // 
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+public:
+  GMSH_LoadMesh3_Op(const basicAC_F0 &  args,Expression ffname) 
+    : filename(ffname)
+  {
+    if(verbosity>1) cout << "Load mesh given by GMSH " << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+basicAC_F0::name_and_type GMSH_LoadMesh3_Op::name_param[]= {
+  {  "reftet", &typeid(long)},
+  {  "renum", &typeid(long)}
+};
+
+
+class  GMSH_LoadMesh3 : public OneOperator { public:  
+    GMSH_LoadMesh3() : OneOperator(atype<pmesh3>(),atype<string *>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new GMSH_LoadMesh3_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+Mesh3 * GMSH_Load3(const string & filename)
+  {
+    // variable freefem++
+    int nv, nt=0, nbe=0;
+    Vertex3   *vff;
+    map<int,int> mapnumv; 
+	  
+    // loading mesh and reading mesh in gmsh are in the file GModelIO_Mesh.cpp (directory Geo) 
+    char str[256]  = "ZZZ";
+    double version = 2.0;
+    bool binary = false, swap = false, postpro = false;
+    
+    FILE *fp = fopen(filename.c_str(), "rb");
+    if(!fp){
+      cerr << "Unable to open file " << filename.c_str() << endl;
+      exit(1);
+    }
+    
+    while( !feof(fp) ){
+      fgets(str, sizeof(str), fp);  
+      if( str[0] == '$'){
+	if(!strncmp(&str[1], "MeshFormat", 10)) {
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  int format, size;
+	  if(sscanf(str, "%lf %d %d", &version, &format, &size) != 3) exit(1);
+	  if(format){
+	    binary = true;
+	    if(verbosity>1) cout << "Mesh is in binary format" << endl;
+	    int one;
+	    if(fread(&one, sizeof(int), 1, fp) != 1) exit(1);
+	    if(one != 1){
+	      swap = true;
+	      if(verbosity>1) cout << "Swapping bytes from binary file" << endl;
+	    }
+	  }
+	}
+	else if(!strncmp(&str[1], "PhysicalNames", 13)) {
+	  if(verbosity>1) cout << " PhysicalNames is not considered in freefem++ " << endl;
+	}
+	
+	else if(!strncmp(&str[1], "NO", 2) || !strncmp(&str[1], "Nodes", 5) ||
+		!strncmp(&str[1], "ParametricNodes", 15)) {
+	  
+	  const bool parametric = !strncmp(&str[1], "ParametricNodes", 15);
+	  if( parametric == true ){
+	    cerr << " ParametricNodes is not considered yet in freefem++" << endl;
+	    exit(1);
+	  }
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  
+	  if(sscanf(str, "%d", &nv) != 1) exit(1);
+	  printf("%d vertices\n", nv);
+	  
+	  // local variables freefem++
+	  vff = new Vertex3[nv]; 
+	  //map<int,int> mapnumv; 
+	  
+	  int minVertex = nv + 1, maxVertex = -1;
+	  for(int i = 0; i < nv; i++) {
+	    int num;	
+	    double xyz[3], uv[2];
+	    
+	    //if (!parametric){		
+	    if(!binary){
+	      if (fscanf(fp, "%d %lf %lf %lf", &num, &xyz[0], &xyz[1], &xyz[2]) != 4)
+		exit(1);	  
+	    }
+	    else{
+	      if(fread(&num, sizeof(int), 1, fp) != 1) exit(1);
+	      if(swap) SwapBytes((char*)&num, sizeof(int), 1);
+	      if(fread(xyz, sizeof(double), 3, fp) != 3) exit(1);
+	      if(swap) SwapBytes((char*)xyz, sizeof(double), 3);
+	    }
+	    
+	    vff[i].x = xyz[0];
+	    vff[i].y = xyz[1];
+	    vff[i].z = xyz[2];
+	    vff[i].lab = 1;
+	    mapnumv[num] = i;
+	  }
+	}
+	else if(!strncmp(&str[1], "ELM", 3) || !strncmp(&str[1], "Elements", 8)) {
+
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  int numElements;
+	  sscanf(str, "%d", &numElements);
+	   
+	  if(!binary){
+	    for(int i = 0; i < numElements; i++) 
+	      {
+		int num, type, physical = 0, elementary = 0, partition = 0, numVertices;
+		if(version <= 1.0)
+		  {
+		    fscanf(fp, "%d %d %d %d %d", &num, &type, &physical, &elementary, &numVertices);		
+		  }
+		else{
+		  int numTags;
+		  fscanf(fp, "%d %d %d", &num, &type, &numTags);
+		  for(int j = 0; j < numTags; j++){
+		    int tag;
+		    fscanf(fp, "%d", &tag);       
+		    if(j == 0)      physical = tag;
+		    else if(j == 1) elementary = tag;
+		    else if(j == 2) partition = tag;
+		    // ignore any other tags for now
+		  }
+		  assert(type>=1 && type <=31);
+		  if( (numVertices = nvElemGmsh[type-1]) == 0){		  
+		    cerr << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		    exit(1);
+		  }
+		}
+		
+		if( type == 1 ){
+		  if(i==0)
+		   if(verbosity>0)  cout << "edges in 3D mesh are not considered yet in freefem++, skeep data" << endl;	
+		}
+		if( type == 2 ) nbe++;
+		if( type == 4 ) nt++;
+		
+		int indices[60];
+		for(int j = 0; j < numVertices; j++) fscanf(fp, "%d", &indices[j]);
+		
+	      }
+	  }
+	  else
+	    {
+	      int numElementsPartial = 0;
+	      while(numElementsPartial < numElements){
+		int header[3];
+		if( fread(header, sizeof(int), 3, fp) != 3 ) exit(1);
+		if(swap) SwapBytes((char*)header, sizeof(int), 3);
+		int type = header[0];
+		int numElms = header[1];
+		int numTags = header[2];
+		int numVertices; 
+		assert(type>=1 && type <=31);
+		if( (numVertices = nvElemGmsh[type-1]) == 0){
+		  cout << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		  exit(1);
+	  }
+		unsigned int n = 1 + numTags + numVertices;
+		int *data = new int[n];
+		
+		for(int i = 0; i < numElms; i++) {
+		  if(fread(data, sizeof(int), n, fp) != n) exit(1);
+		  if(swap) SwapBytes((char*)data, sizeof(int), n);
+		  int num = data[0];
+		  int physical = (numTags > 0) ? data[4 - numTags] : 0;
+		  int elementary = (numTags > 1) ? data[4 - numTags + 1] : 0;
+		  int partition = (numTags > 2) ? data[4 - numTags + 2] : 0;
+		  int *indices = &data[numTags + 1];
+		  
+		  if( type == 1 && i==0 ){
+		   cout << "edges in 3D mesh are not used in freefem++,skeep data" << endl;
+		    //exit(1);
+		  }
+		  if( type == 2 ) nbe++;
+		  if( type == 4 ) nt++;
+		}
+		delete [] data;
+		numElementsPartial += numElms;
+		
+	    }
+	  }
+	  break;
+	}
+      }
+    }
+    fclose(fp);
+    
+   if(verbosity>1)  cout << "closing file " << nt << " " << nbe << endl;
+
+    Tet *tff  = new Tet[nt];
+    Tet *ttff = tff;
+
+    Triangle3 *bff  = new Triangle3[nbe];
+    Triangle3 *bbff = bff;
+
+    // second reading
+    fp = fopen(filename.c_str(), "rb");
+    
+    while( !feof(fp) ){
+      fgets(str, sizeof(str), fp);  
+      if( str[0] == '$'){
+	
+	if(!strncmp(&str[1], "ELM", 3) || !strncmp(&str[1], "Elements", 8)) {
+
+	  if(!fgets(str, sizeof(str), fp)) exit(1);
+	  int numElements;
+	  sscanf(str, "%d", &numElements);
+
+	  printf("%d tetrahedrons\n", nt);
+	  printf("%d triangles\n", nbe);
+	  printf("%d numElements\n", numElements);
+	  if(!binary){
+
+	    int ie=0; 
+	    int it=0;
+
+	    for(int i = 0; i < numElements; i++) {
+	      int num, type, physical = 0, elementary = 0, partition = 0, numVertices;
+	      if(version <= 1.0){
+		fscanf(fp, "%d %d %d %d %d", &num, &type, &physical, &elementary, &numVertices);		
+	      }
+	      else{
+		int numTags;
+		fscanf(fp, "%d %d %d", &num, &type, &numTags);
+		for(int j = 0; j < numTags; j++){
+		  int tag;
+		  fscanf(fp, "%d", &tag);  
+	 
+		  if(j == 0)      physical = tag;
+		  else if(j == 1) elementary = tag;
+		  else if(j == 2) partition = tag;
+		  // ignore any other tags for now
+		}
+		assert(type>=1 && type <=31);
+		if( (numVertices = nvElemGmsh[type-1]) == 0){
+		  cerr << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		  exit(1);
+		}
+	      }
+
+	      int indices[60];
+	      for(int j = 0; j < numVertices; j++){
+		fscanf(fp, "%d", &indices[j]);
+	      }
+	      if( type == 2 ){
+		int ivff[3];
+		for(int ii=0; ii < numVertices; ii++){
+		  ivff[ii] = mapnumv[ indices[ii] ];
+		  assert( ivff[ii]>=0 && ivff[ii]< nv );
+		}
+		(bbff++)->set(vff,ivff,physical);
+		ie++;
+	      }
+	      if( type == 4 ){
+		int ivff[4];
+		for(int ii=0; ii < numVertices; ii++){
+		  ivff[ii] = mapnumv[ indices[ii] ];
+		  assert( ivff[ii]>=0 && ivff[ii]< nv );
+		}
+		(ttff++)->set(vff,ivff,physical);
+		it++;
+	      }
+	    }
+	    assert( it==nt );
+	    assert( ie==nbe );
+	  }
+	  else{
+	    
+	    int ie=0; 
+	    int it=0;
+
+	    int numElementsPartial = 0;
+	    while(numElementsPartial < numElements){
+	      int header[3];
+	      if( fread(header, sizeof(int), 3, fp) != 3 ) exit(1);
+	      if(swap) SwapBytes((char*)header, sizeof(int), 3);
+	      int type = header[0];
+	      int numElms = header[1];
+	      int numTags = header[2];
+	      int numVertices;
+	      assert(type>=1 && type <=31);
+	      if( (numVertices = nvElemGmsh[type-1]) == 0){
+		cerr << "Element of type " << type  << " is not considered in Freefem++" << endl;
+		exit(1);
+	      }
+	      unsigned int n = 1 + numTags + numVertices;
+	      int *data = new int[n];
+	      for(int i = 0; i < numElms; i++) {
+		if(fread(data, sizeof(int), n, fp) != n) exit(1);
+		if(swap) SwapBytes((char*)data, sizeof(int), n);
+		int num = data[0];
+		int physical = (numTags > 0) ? data[4 - numTags] : 0;
+		int elementary = (numTags > 1) ? data[4 - numTags + 1] : 0;
+		int partition = (numTags > 2) ? data[4 - numTags + 2] : 0;
+		int *indices = &data[numTags + 1];
+
+		if( type == 2 ){
+		  int ivff[3];
+		  for(int ii=0; ii < numVertices; ii++) ivff[ii] = mapnumv[ indices[ii] ];		
+		  (bbff++)->set(vff,ivff,physical);
+		  ie++;
+		}
+		if( type == 4 ){
+		  int ivff[4];
+		  for(int ii=0; ii < numVertices; ii++) ivff[ii] = mapnumv[ indices[ii] ];		
+		  (ttff++)->set(vff,ivff,physical);
+		  it++;
+		}
+		
+	      }
+	      delete [] data;
+	      numElementsPartial += numElms;
+	     
+	    }
+	    assert(it==nt);
+	    assert(ie==nbe);
+	  }
+	}
+        else if(!strncmp(&str[1], "NodeData", 8)) {
+	  if(verbosity) cout << " NodeData is not considered in freefem++ " << endl;
+	}
+	else if(!strncmp(&str[1], "ElementData", 11) ||
+		!strncmp(&str[1], "ElementNodeData", 15)){
+
+	 if(verbosity)  cout << " ElementData/ElementNodeData is not considered in freefem++ " << endl;
+	}
+      }
+    }
+    fclose(fp);
+
+    if(nt==0){
+      Mesh3 *Th3 = new Mesh3(nv,nbe,vff,bff);
+      return Th3;
+    }
+    else{
+      Mesh3 *Th3 = new Mesh3(nv,nt,nbe,vff,tff,bff);
+      return Th3;  
+    }
+    
+
+  }
+
+
+
+AnyType GMSH_LoadMesh3_Op::operator()(Stack stack)  const 
+{
+ 
+  string * pffname= GetAny<string *>((*filename)(stack));
+  int renumsurf = 0; 
+  if( nargs[1] )  renumsurf = GetAny<long>( (*nargs[1])(stack) );
+  assert( renumsurf <=1 && renumsurf >= 0);
+
+  Mesh3 * Th3_t = GMSH_Load3( *pffname); 
+ 
+  Th3_t->BuildGTree();  
+  Add2StackOfPtr2FreeRC(stack,Th3_t);
+		
+  return Th3_t;
+}
+
+/*  class Init1 { public:
+  Init1();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  
+  //if (verbosity)
+  if(verbosity>1) cout << " load: gmsh " << endl;
+  Global.Add("gmshload3","(",new GMSH_LoadMesh3);
+  Global.Add("gmshload","(",new GMSH_LoadMesh);
+  if(verbosity>1) cout << " load: gmsh  " << endl;
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/gsl.awk b/examples++-load/gsl.awk
new file mode 100644
index 0000000..41804c6
--- /dev/null
+++ b/examples++-load/gsl.awk
@@ -0,0 +1,161 @@
+# egrep "^int|^double" /opt/local/include/gsl/gsl_sf* 
+# egrep "^int|^double|^long" /usr/local/include/gsl/gsl_{cdf,randist,sf_*}.h | egrep -v ',$'  
+#  export  LANG=C
+BEGIN {FS="[(),]";
+    FLOAD="gsl"
+    LANG="C";
+    edp=FLOAD ".idp";
+    c="\"";
+    pp=c "(" c;
+    print " /*  ";
+    print "// file create:  awk -f gsl.awk  gsl_list  > ff_gsl_awk.hpp " >edp
+    print "load",c FLOAD c  > edp
+    print "gslrng ffrng;" >edp
+    print " gslabortonerror=0; " >edp
+    #  convertion de type gsl .. ff++ 
+    
+    Tff["double"]="double";
+    Tff["const double"]="double";
+    Tff["int"]="long";
+    Tff["const size_t"]="long";
+    Tff["unsigned int"]="long";
+    Tff["const int"]="long";
+    Tff["const unsigned int"]="long";
+    Tff["const double"]="double";
+    Tff["const gsl_rng *"] = "gsl_rng **";
+#    Tff["gsl_mode_t"] = ""; 
+    Cff["const gsl_rng *"] = "*"; 
+    V0["double"]= 0.55;
+    V0["const double"]= 0.55; 
+    V0["const gsl_rng *"] = "ffrng";
+ }
+
+function f0(f) { xx=f;gsub("_","",xx) ; return  xx  };
+function ff(f) { return c f0(f) c };
+function VV(t) { if ( V0[t] !=0) return V0[t]; else return 0;}
+function ana1()
+{
+    ok = 0; 
+    xx1=$1;
+    nnn=split($1,xxx,":");
+    if(nnn == 2) xx1= xxx[2]; 
+
+    fonc=0; 
+    split(xx1,fff,"[ \t]*");
+    f=fff[2];
+    R=fff[1]; 
+
+    if( R=="int" || R =="double" ) ok=1;
+    #print " xx: " xx1, R, f, ok ; 
+
+}
+function anatype(kkk)
+{
+    if( ok !=1) return 0; ; 
+    v0=1;  
+    t = "";
+ 
+    nnn=split($(kkk+1),fff,"[ \t]*");
+    i2 =1; 
+    while( i2<nnn)
+	{
+	   if( t=="")
+	    t = fff[i2];
+	   else
+	    t= t " " fff[i2]; 
+	    i2++; 
+	}
+	tmp=match(fff[nnn],/.*\[\]/);
+	if(tmp) t = t "[]"; 
+	T[kkk]=t;
+	if( Tff[t] == "") ok=0; 
+	if( Tff[t] == "" && T00[t]=="") { print "//  -- missing type \"" t  "\" ";T00[t]=1;} 
+    return ok; 
+}
+
+NF ==3 {
+    ana1();
+    #print NF, "******",ok
+    anatype(1);
+    if( ok == 1)
+    {
+      ok==2;
+ 	  lw="";
+	  
+	   lw = Tff[R] " " f "__(" Tff[T[1]] " const & x ) { return " f "( (" T[1] ")" Cff[T[1]] " x );}\n" ;
+	  
+	gg = "\n   Global.Add(" ff(f) "," pp ",new OneOperator1_<" Tff[R] "," Tff[T[1]] ">( " f "__)); "
+	cw = cw  lw;
+	cm = cm  gg;
+	v0 = VV(T[1]);
+	print "cout << " c  f "("v0") =  " c " << " f0(f) "("v0")  << endl; "> edp
+	}
+}
+
+NF ==4 {
+    ana1();
+    anatype(1);
+    anatype(2);
+    if( ok == 1)
+    {
+      ok==2;
+ 	  lw="";
+	  
+	   lw = Tff[R] " " f "__(" Tff[T[1]] " const & x , " Tff[T[2]] " const & y )" \
+	   "{ return " f "( (" T[1] ")" Cff[T[1]] " x , (" T[2] ")" Cff[T[2]] " y );}\n" ;
+	  
+	gg = "\n   Global.Add(" ff(f) "," pp ",new OneOperator2_<" Tff[R] "," Tff[T[1]] "," Tff[T[2]] ">( " f "__)); "
+	cw = cw  lw;
+	cm = cm  gg;
+	v0 = VV(T[1]);
+	v1 = VV(T[2]);
+	
+	print "cout << " c  f "(" v0 ", "v1 ") =  " c " << " f0(f) "(" v0 ",",v1 ")  << endl; "> edp
+	}
+}
+
+NF ==5 {
+    ana1();
+    anatype(1);
+    anatype(2);
+    anatype(3);
+    if( ok == 1)
+    {
+      ok==2;
+ 	  lw="";
+	  
+	   lw = Tff[R] " " f "__(" Tff[T[1]] " const & x , "  Tff[T[2]] " const & y , " Tff[T[3]] " const & z )" \
+	   "{ return " f "( (" T[1] ")" Cff[T[1]] " x , (" T[2] ")" Cff[T[2]] " y , (" T[3] ")" Cff[T[3]] " z );}\n" ;
+	  
+	gg = "\n   Global.Add(" ff(f) "," pp ",new OneOperator3_<" Tff[R] "," Tff[T[1]] "," Tff[T[2]] "," Tff[T[3]] \
+	   ">( " f "__)); ";
+	cw = cw  lw;
+	cm = cm  gg;
+	v0 = VV(T[1]);
+	v1 = VV(T[2]);
+	v2 = VV(T[3]);
+	
+	print "cout << " c  f "(" v0 "," v1 "," v2 ") =  " c " << " f0(f) "(" v0 "," v1 "," v2 ")  << endl; "> edp
+	}
+}
+
+
+ok !=1 { 
+   print " missing:",NF," ", f , " -> " $0;
+}
+END {   print " */ "
+	print "/*****************/";
+	print "/*****************/";
+
+	print cw ;
+
+	print "/*****************/";
+	print "/*****************/";
+	print " void init_gsl_sf() { \n"
+ 	print cm ; 
+	print " } ";
+
+	print "/*****************/";
+	print "/*****************/";
+
+    }
\ No newline at end of file
diff --git a/examples++-load/gsl.cpp b/examples++-load/gsl.cpp
new file mode 100644
index 0000000..a3cc3fb
--- /dev/null
+++ b/examples++-load/gsl.cpp
@@ -0,0 +1,256 @@
+// Example C++ function "myfunction", dynamically loaded into "load.edp"
+// ---------------------------------------------------------------------
+// $Id$
+//ff-c++-LIBRARY-dep:   gsl
+//ff-c++-cpp-dep:  
+#include <ff++.hpp>
+#include <gsl/gsl_sf.h>
+#include <gsl/gsl_sf_airy.h>
+#include <gsl/gsl_sf_bessel.h>
+#include <gsl/gsl_sf_clausen.h>
+#include <gsl/gsl_sf_coulomb.h>
+#include <gsl/gsl_sf_coupling.h>
+#include <gsl/gsl_sf_dawson.h>
+#include <gsl/gsl_sf_debye.h>
+#include <gsl/gsl_sf_dilog.h>
+#include <gsl/gsl_sf_elementary.h>
+#include <gsl/gsl_sf_ellint.h>
+#include <gsl/gsl_sf_elljac.h>
+#include <gsl/gsl_sf_erf.h>
+#include <gsl/gsl_sf_exp.h>
+#include <gsl/gsl_sf_expint.h>
+#include <gsl/gsl_sf_fermi_dirac.h>
+#include <gsl/gsl_sf_gamma.h>
+#include <gsl/gsl_sf_gegenbauer.h>
+#include <gsl/gsl_sf_hyperg.h>
+#include <gsl/gsl_sf_laguerre.h>
+#include <gsl/gsl_sf_lambert.h>
+#include <gsl/gsl_sf_legendre.h>
+#include <gsl/gsl_sf_log.h>
+#include <gsl/gsl_sf_mathieu.h>
+#include <gsl/gsl_sf_pow_int.h>
+#include <gsl/gsl_sf_psi.h>
+#include <gsl/gsl_sf_result.h>
+#include <gsl/gsl_sf_synchrotron.h>
+#include <gsl/gsl_sf_transport.h>
+#include <gsl/gsl_sf_trig.h>
+#include <gsl/gsl_sf_zeta.h>
+#include <gsl/gsl_poly.h>
+
+#include <gsl/gsl_bspline.h>
+#include <gsl/gsl_multifit.h>
+
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+#include <gsl/gsl_cdf.h>
+
+#include "ff_gsl_awk.hpp"
+
+long gslpolysolvequadratic( KN_<double> a,  KN_<double> x)
+{
+  ffassert(a.N()>2 && x.N()>1);
+  return gsl_poly_solve_quadratic (a[2],a[1],a[0],&(x[0]),&(x[1]));
+}
+long gslpolysolvecubic( KN_<double> a,  KN_<double> x)
+{
+  ffassert(a.N()>2 && x.N()>2);
+  return gsl_poly_solve_cubic (a[2],a[1],a[0],&(x[0]),&(x[1]),&(x[2]));
+  }
+
+long gslpolycomplexsolve( KN_<double> a,  KN_<Complex> x)
+{
+  int n = a.N();
+  ffassert( n-1 <=  x.N()); 
+  KN<double> z(n*2); 
+  gsl_poly_complex_workspace * w= gsl_poly_complex_workspace_alloc (n);
+  int ok=gsl_poly_complex_solve (&a[0], n, w, &z[0]);
+  gsl_poly_complex_workspace_free (w);
+  for (long i = 0; i < n-1; i++)
+    x[i] = Complex(z[2*i], z[2*i+1]);
+  return ok; 
+}
+
+//  Ramdom part..
+AnyType  init_gsl_rng(Stack,const AnyType &x){
+  gsl_rng ** pp = PGetAny< gsl_rng *>(x);
+    *pp = gsl_rng_alloc(gsl_rng_default) ;
+    return  x;
+};
+AnyType delete_gsl_rng(Stack,const AnyType &x)
+{
+ gsl_rng ** pp = PGetAny< gsl_rng *>(x);
+ if(*pp) gsl_rng_free(*pp);
+ *pp=0;
+ return  Nothing;
+};
+
+gsl_rng ** init_gsl_rng_type( gsl_rng ** pp, const gsl_rng_type * g)
+{
+    *pp = gsl_rng_alloc(g) ;
+    return pp;
+}
+
+gsl_rng ** set_gsl_rng_type( gsl_rng ** pp, const gsl_rng_type * g)
+{
+    if(*pp) gsl_rng_free(*pp);
+    *pp = gsl_rng_alloc(g) ;
+    return pp;
+}
+gsl_rng ** set_gsl_cpy( gsl_rng ** pp, gsl_rng ** gg)
+{
+    if(*pp) gsl_rng_free(*pp);
+    *pp =  gsl_rng_clone(*gg);
+    return pp;
+}
+
+double gslrnguniform( gsl_rng ** pr) { return gsl_rng_uniform(*pr);}
+double gslrnguniformpos( gsl_rng ** pr) { return gsl_rng_uniform_pos(*pr);}
+long gsl_rng_get(gsl_rng ** pr){ return gsl_rng_get(*pr);}
+long gsl_rng_min(gsl_rng ** pr){ return gsl_rng_min(*pr);}
+long gsl_rng_max(gsl_rng ** pr){ return gsl_rng_max(*pr);}
+long gsl_rng_set(gsl_rng ** pr, long s){  gsl_rng_set(*pr,s);return 0; }
+string * gsl_name(Stack s,const gsl_rng_type * const & pr)
+  {return Add2StackOfPtr2Free(s,new string((*pr).name));}
+
+long  ngslrng =0;
+long  gslabort =1;
+static const gsl_rng_type ** gsl_rngpp; 
+
+const gsl_rng_type * gslrngtype(long i)
+{ 
+  ffassert(i >=0 && i < ngslrng);
+  return gsl_rngpp[i]; 
+}
+
+extern "C" {
+    void ffhandler (const char * reason,
+                  const char * file,
+                  int line,
+                    int gsl_errno);
+
+}
+void ffhandler (const char * reason,
+                const char * file,
+                int line,
+                int gsl_errno)
+{
+    cerr << "\n GSL Error = " << reason << " in " <<file << " at " << line << " err= " <<gsl_errno << endl;
+    if(gslabort) ExecError("Gsl errorhandler");
+}
+
+/*  class Init { public:
+  Init();
+};
+$1 */
+using  namespace Fem2D ;
+static void Load_Init(){
+    
+  Global.Add("gslpolysolvequadratic","(",new OneOperator2<long,KN_<double>,KN_<double> >( gslpolysolvequadratic));
+  Global.Add("gslpolysolvecubic","(",new OneOperator2<long,KN_<double>,KN_<double> >(gslpolysolvecubic));
+  Global.Add("gslpolycomplexsolve","(",new OneOperator2<long,KN_<double>,KN_<Complex> >( gslpolycomplexsolve));
+/* spline gsl and June 2013 */
+    /*
+    Dcl_Type<gsl_bspline_workspace**>(::InitializePtr<gsl_bspline_workspace **>,::DeletePtr<gsl_bspline_workspace **>);
+    zzzfff->Add("gslbspline",atype<gsl_bspline_workspace ** >());
+    TheOperators->Add("<-",
+                      new OneOperator3_<gsl_bspline_workspace **,gsl_bspline_workspace **,KNM_<double>  >(pBuilQFd<R1>),
+*/
+    // a faire ... interface randon of gsl ... 
+  gsl_rng_env_setup();
+  gsl_rngpp =gsl_rng_types_setup(); 
+  for(long  i=0; gsl_rngpp[i]; )
+    ngslrng=++i; 
+   Dcl_Type< gsl_rng **  > (init_gsl_rng,delete_gsl_rng);
+   Dcl_Type< const gsl_rng_type * > (); //gsl_rng_type
+   Global.New("ngslrng",CConstant<long>(ngslrng)); 
+//
+// all gsl random generator .???? .
+/*
+Global.New("gslrngborosh13",CConstant<const gsl_rng_type *>(gsl_rng_borosh13));
+Global.New("gslrngcoveyou",CConstant<const gsl_rng_type *>(gsl_rng_coveyou));
+Global.New("gslrngcmrg",CConstant<const gsl_rng_type *>(gsl_rng_cmrg));
+Global.New("gslrngfishman18",CConstant<const gsl_rng_type *>(gsl_rng_fishman18));
+Global.New("gslrngfishman20",CConstant<const gsl_rng_type *>(gsl_rng_fishman20));
+Global.New("gslrngfishman2x",CConstant<const gsl_rng_type *>(gsl_rng_fishman2x));
+Global.New("gslrnggfsr4",CConstant<const gsl_rng_type *>(gsl_rng_gfsr4));
+Global.New("gslrngknuthran",CConstant<const gsl_rng_type *>(gsl_rng_knuthran));
+Global.New("gslrngknuthran2",CConstant<const gsl_rng_type *>(gsl_rng_knuthran2));
+Global.New("gslrngknuthran2002",CConstant<const gsl_rng_type *>(gsl_rng_knuthran2002));
+Global.New("gslrnglecuyer21",CConstant<const gsl_rng_type *>(gsl_rng_lecuyer21));
+Global.New("gslrngminstd",CConstant<const gsl_rng_type *>(gsl_rng_minstd));
+Global.New("gslrngmrg",CConstant<const gsl_rng_type *>(gsl_rng_mrg));
+Global.New("gslrngmt19937",CConstant<const gsl_rng_type *>(gsl_rng_mt19937));
+Global.New("gslrngmt199371999",CConstant<const gsl_rng_type *>(gsl_rng_mt19937_1999));
+Global.New("gslrngmt199371998",CConstant<const gsl_rng_type *>(gsl_rng_mt19937_1998));
+Global.New("gslrngr250",CConstant<const gsl_rng_type *>(gsl_rng_r250));
+Global.New("gslrngran0",CConstant<const gsl_rng_type *>(gsl_rng_ran0));
+Global.New("gslrngran1",CConstant<const gsl_rng_type *>(gsl_rng_ran1));
+Global.New("gslrngran2",CConstant<const gsl_rng_type *>(gsl_rng_ran2));
+Global.New("gslrngran3",CConstant<const gsl_rng_type *>(gsl_rng_ran3));
+Global.New("gslrngrand",CConstant<const gsl_rng_type *>(gsl_rng_rand));
+Global.New("gslrngrand48",CConstant<const gsl_rng_type *>(gsl_rng_rand48));
+Global.New("gslrngrandom128bsd",CConstant<const gsl_rng_type *>(gsl_rng_random128_bsd));
+Global.New("gslrngrandom128glibc2",CConstant<const gsl_rng_type *>(gsl_rng_random128_glibc2));
+Global.New("gslrngrandom128libc5",CConstant<const gsl_rng_type *>(gsl_rng_random128_libc5));
+Global.New("gslrngrandom256bsd",CConstant<const gsl_rng_type *>(gsl_rng_random256_bsd));
+Global.New("gslrngrandom256glibc2",CConstant<const gsl_rng_type *>(gsl_rng_random256_glibc2));
+Global.New("gslrngrandom256libc5",CConstant<const gsl_rng_type *>(gsl_rng_random256_libc5));
+Global.New("gslrngrandom32bsd",CConstant<const gsl_rng_type *>(gsl_rng_random32_bsd));
+Global.New("gslrngrandom32glibc2",CConstant<const gsl_rng_type *>(gsl_rng_random32_glibc2));
+Global.New("gslrngrandom32libc5",CConstant<const gsl_rng_type *>(gsl_rng_random32_libc5));
+Global.New("gslrngrandom64bsd",CConstant<const gsl_rng_type *>(gsl_rng_random64_bsd));
+Global.New("gslrngrandom64glibc2",CConstant<const gsl_rng_type *>(gsl_rng_random64_glibc2));
+Global.New("gslrngrandom64libc5",CConstant<const gsl_rng_type *>(gsl_rng_random64_libc5));
+Global.New("gslrngrandom8bsd",CConstant<const gsl_rng_type *>(gsl_rng_random8_bsd));
+Global.New("gslrngrandom8glibc2",CConstant<const gsl_rng_type *>(gsl_rng_random8_glibc2));
+Global.New("gslrngrandom8libc5",CConstant<const gsl_rng_type *>(gsl_rng_random8_libc5));
+Global.New("gslrngrandombsd",CConstant<const gsl_rng_type *>(gsl_rng_random_bsd));
+Global.New("gslrngrandomglibc2",CConstant<const gsl_rng_type *>(gsl_rng_random_glibc2));
+Global.New("gslrngrandomlibc5",CConstant<const gsl_rng_type *>(gsl_rng_random_libc5));
+Global.New("gslrngrandu",CConstant<const gsl_rng_type *>(gsl_rng_randu));
+Global.New("gslrngranf",CConstant<const gsl_rng_type *>(gsl_rng_ranf));
+Global.New("gslrngranlux",CConstant<const gsl_rng_type *>(gsl_rng_ranlux));
+Global.New("gslrngranlux389",CConstant<const gsl_rng_type *>(gsl_rng_ranlux389));
+Global.New("gslrngranlxd1",CConstant<const gsl_rng_type *>(gsl_rng_ranlxd1));
+Global.New("gslrngranlxd2",CConstant<const gsl_rng_type *>(gsl_rng_ranlxd2));
+Global.New("gslrngranlxs0",CConstant<const gsl_rng_type *>(gsl_rng_ranlxs0));
+Global.New("gslrngranlxs1",CConstant<const gsl_rng_type *>(gsl_rng_ranlxs1));
+Global.New("gslrngranlxs2",CConstant<const gsl_rng_type *>(gsl_rng_ranlxs2));
+Global.New("gslrngranmar",CConstant<const gsl_rng_type *>(gsl_rng_ranmar));
+Global.New("gslrngslatec",CConstant<const gsl_rng_type *>(gsl_rng_slatec));
+Global.New("gslrngtaus",CConstant<const gsl_rng_type *>(gsl_rng_taus));
+Global.New("gslrngtaus2",CConstant<const gsl_rng_type *>(gsl_rng_taus2));
+Global.New("gslrngtaus113",CConstant<const gsl_rng_type *>(gsl_rng_taus113));
+Global.New("gslrngtransputer",CConstant<const gsl_rng_type *>(gsl_rng_transputer));
+Global.New("gslrngtt800",CConstant<const gsl_rng_type *>(gsl_rng_tt800));
+Global.New("gslrnguni",CConstant<const gsl_rng_type *>(gsl_rng_uni));
+Global.New("gslrnguni32",CConstant<const gsl_rng_type *>(gsl_rng_uni32));
+Global.New("gslrngvax",CConstant<const gsl_rng_type *>(gsl_rng_vax));
+Global.New("gslrngwaterman14",CConstant<const gsl_rng_type *>(gsl_rng_waterman14));
+Global.New("gslrngzuf",CConstant<const gsl_rng_type *>(gsl_rng_zuf));
+Global.New("gslrngdefault",CConstant<const gsl_rng_type *>(gsl_rng_default));
+*/    
+    
+zzzfff->Add("gslrng",atype<gsl_rng ** >());
+TheOperators->Add("<-",new OneOperator2<gsl_rng  **,gsl_rng  **, const gsl_rng_type *  >(init_gsl_rng_type));
+TheOperators->Add("=",new OneOperator2<gsl_rng  **,gsl_rng  **, const gsl_rng_type *  >(set_gsl_rng_type));
+TheOperators->Add("=",new OneOperator2<gsl_rng  **,gsl_rng  **, gsl_rng  **   >(set_gsl_cpy));
+//map_type[typeid(gsl_rng *).name()]->AddCast(   new E_F1_funcT<gsl_rng *,gsl_rng **>(UnRef<gsl_rng*>) );
+//map_type[typeid(gsl_rng *).name()]->AddCast(   new E_F1_funcT<gsl_rng *,gsl_rng **>(UnRef<gsl_rng*>) );
+
+Global.Add("gslrnguniform","(",new OneOperator1<double,gsl_rng **>( gslrnguniform));
+Global.Add("gslrnguniformpos","(",new OneOperator1<double,gsl_rng **>( gslrnguniformpos));
+    
+Global.Add("gslname","(",new OneOperator1s_<string * ,const gsl_rng_type *>( gsl_name));
+Global.Add("gslrngget","(",new OneOperator1<long   ,gsl_rng **>( gsl_rng_get));
+Global.Add("gslrngmin","(",new OneOperator1<long   ,gsl_rng **>( gsl_rng_min));
+Global.Add("gslrngmax","(",new OneOperator1<long   ,gsl_rng **>( gsl_rng_max));
+Global.Add("gslrngset","(",new OneOperator2<long   ,gsl_rng **, long>(gsl_rng_set));
+ Global.Add("gslrngtype","(",new OneOperator1<const gsl_rng_type * ,long>(gslrngtype));     
+  init_gsl_sf() ;
+ gslabort=1;
+ Global.New("gslabortonerror",CConstant<long*>(&gslabort));
+   
+ gsl_set_error_handler(ffhandler);
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/gsl.edp b/examples++-load/gsl.edp
new file mode 100644
index 0000000..5b2b55a
--- /dev/null
+++ b/examples++-load/gsl.edp
@@ -0,0 +1,23 @@
+include "gsl.idp"
+// FFCS - avoid using P2 and P3 which already define something very precise
+real [int] p2=[ 2,-3,1];
+real [int] p3=[ 8,-10,1,1];
+real [int] X(3);
+complex[int] Z(4);
+real [int] Q4=[ -1,0,0,0,1];
+gslpolysolvequadratic(p2,X);
+cout << X[0] << " " << X[1] << endl; 
+gslpolysolvecubic(p3,X);
+cout << X[0] << " " << X[1] << " " << X[2] << endl; 
+gslpolycomplexsolve(Q4,Z); 
+cout << Z[0] << " " << Z[1] << " " << Z[2] << " " << Z[3] <<endl;
+
+cout << "\n\n gsl random :\n\n";
+ cout << " list of generator " << ngslrng << endl;
+ for(int i=0; i <ngslrng ; ++i)
+   cout << i << " name  " <<  gslname(gslrngtype(i)) << endl; 
+gslrng r=gslrngtype(1);// chose a generator 
+// cout << r << endl;  no print .. 
+for (int i = 0; i < 10; i++) 
+   cout << gslrnguniform(r) << endl;;  
+ 
\ No newline at end of file
diff --git a/examples++-load/gsl.idp b/examples++-load/gsl.idp
new file mode 100644
index 0000000..07bce8a
--- /dev/null
+++ b/examples++-load/gsl.idp
@@ -0,0 +1,331 @@
+// file create:  awk -f gsl.awk  gsl_list  > ff_gsl_awk.hpp 
+load "gsl"
+gslrng ffrng;
+ gslabortonerror=0; 
+cout << "gsl_cdf_ugaussian_P(0.55) =  " << gslcdfugaussianP(0.55)  << endl; 
+cout << "gsl_cdf_ugaussian_Q(0.55) =  " << gslcdfugaussianQ(0.55)  << endl; 
+cout << "gsl_cdf_ugaussian_Pinv(0.55) =  " << gslcdfugaussianPinv(0.55)  << endl; 
+cout << "gsl_cdf_ugaussian_Qinv(0.55) =  " << gslcdfugaussianQinv(0.55)  << endl; 
+cout << "gsl_cdf_gaussian_P(0.55, 0.55) =  " << gslcdfgaussianP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_gaussian_Q(0.55, 0.55) =  " << gslcdfgaussianQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_gaussian_Pinv(0.55, 0.55) =  " << gslcdfgaussianPinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_gaussian_Qinv(0.55, 0.55) =  " << gslcdfgaussianQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_gamma_P(0.55,0.55,0.55) =  " << gslcdfgammaP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gamma_Q(0.55,0.55,0.55) =  " << gslcdfgammaQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gamma_Pinv(0.55,0.55,0.55) =  " << gslcdfgammaPinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gamma_Qinv(0.55,0.55,0.55) =  " << gslcdfgammaQinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_cauchy_P(0.55, 0.55) =  " << gslcdfcauchyP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_cauchy_Q(0.55, 0.55) =  " << gslcdfcauchyQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_cauchy_Pinv(0.55, 0.55) =  " << gslcdfcauchyPinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_cauchy_Qinv(0.55, 0.55) =  " << gslcdfcauchyQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_laplace_P(0.55, 0.55) =  " << gslcdflaplaceP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_laplace_Q(0.55, 0.55) =  " << gslcdflaplaceQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_laplace_Pinv(0.55, 0.55) =  " << gslcdflaplacePinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_laplace_Qinv(0.55, 0.55) =  " << gslcdflaplaceQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_rayleigh_P(0.55, 0.55) =  " << gslcdfrayleighP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_rayleigh_Q(0.55, 0.55) =  " << gslcdfrayleighQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_rayleigh_Pinv(0.55, 0.55) =  " << gslcdfrayleighPinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_rayleigh_Qinv(0.55, 0.55) =  " << gslcdfrayleighQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_chisq_P(0.55, 0.55) =  " << gslcdfchisqP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_chisq_Q(0.55, 0.55) =  " << gslcdfchisqQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_chisq_Pinv(0.55, 0.55) =  " << gslcdfchisqPinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_chisq_Qinv(0.55, 0.55) =  " << gslcdfchisqQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_exponential_P(0.55, 0.55) =  " << gslcdfexponentialP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_exponential_Q(0.55, 0.55) =  " << gslcdfexponentialQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_exponential_Pinv(0.55, 0.55) =  " << gslcdfexponentialPinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_exponential_Qinv(0.55, 0.55) =  " << gslcdfexponentialQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_exppow_P(0.55,0.55,0.55) =  " << gslcdfexppowP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_exppow_Q(0.55,0.55,0.55) =  " << gslcdfexppowQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_tdist_P(0.55, 0.55) =  " << gslcdftdistP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_tdist_Q(0.55, 0.55) =  " << gslcdftdistQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_tdist_Pinv(0.55, 0.55) =  " << gslcdftdistPinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_tdist_Qinv(0.55, 0.55) =  " << gslcdftdistQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_fdist_P(0.55,0.55,0.55) =  " << gslcdffdistP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_fdist_Q(0.55,0.55,0.55) =  " << gslcdffdistQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_fdist_Pinv(0.55,0.55,0.55) =  " << gslcdffdistPinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_fdist_Qinv(0.55,0.55,0.55) =  " << gslcdffdistQinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_beta_P(0.55,0.55,0.55) =  " << gslcdfbetaP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_beta_Q(0.55,0.55,0.55) =  " << gslcdfbetaQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_beta_Pinv(0.55,0.55,0.55) =  " << gslcdfbetaPinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_beta_Qinv(0.55,0.55,0.55) =  " << gslcdfbetaQinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_flat_P(0.55,0.55,0.55) =  " << gslcdfflatP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_flat_Q(0.55,0.55,0.55) =  " << gslcdfflatQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_flat_Pinv(0.55,0.55,0.55) =  " << gslcdfflatPinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_flat_Qinv(0.55,0.55,0.55) =  " << gslcdfflatQinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_lognormal_P(0.55,0.55,0.55) =  " << gslcdflognormalP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_lognormal_Q(0.55,0.55,0.55) =  " << gslcdflognormalQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_lognormal_Pinv(0.55,0.55,0.55) =  " << gslcdflognormalPinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_lognormal_Qinv(0.55,0.55,0.55) =  " << gslcdflognormalQinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel1_P(0.55,0.55,0.55) =  " << gslcdfgumbel1P(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel1_Q(0.55,0.55,0.55) =  " << gslcdfgumbel1Q(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel1_Pinv(0.55,0.55,0.55) =  " << gslcdfgumbel1Pinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel1_Qinv(0.55,0.55,0.55) =  " << gslcdfgumbel1Qinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel2_P(0.55,0.55,0.55) =  " << gslcdfgumbel2P(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel2_Q(0.55,0.55,0.55) =  " << gslcdfgumbel2Q(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel2_Pinv(0.55,0.55,0.55) =  " << gslcdfgumbel2Pinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_gumbel2_Qinv(0.55,0.55,0.55) =  " << gslcdfgumbel2Qinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_weibull_P(0.55,0.55,0.55) =  " << gslcdfweibullP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_weibull_Q(0.55,0.55,0.55) =  " << gslcdfweibullQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_weibull_Pinv(0.55,0.55,0.55) =  " << gslcdfweibullPinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_weibull_Qinv(0.55,0.55,0.55) =  " << gslcdfweibullQinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_pareto_P(0.55,0.55,0.55) =  " << gslcdfparetoP(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_pareto_Q(0.55,0.55,0.55) =  " << gslcdfparetoQ(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_pareto_Pinv(0.55,0.55,0.55) =  " << gslcdfparetoPinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_pareto_Qinv(0.55,0.55,0.55) =  " << gslcdfparetoQinv(0.55,0.55,0.55)  << endl; 
+cout << "gsl_cdf_logistic_P(0.55, 0.55) =  " << gslcdflogisticP(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_logistic_Q(0.55, 0.55) =  " << gslcdflogisticQ(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_logistic_Pinv(0.55, 0.55) =  " << gslcdflogisticPinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_logistic_Qinv(0.55, 0.55) =  " << gslcdflogisticQinv(0.55, 0.55)  << endl; 
+cout << "gsl_cdf_binomial_P(0,0.55,0) =  " << gslcdfbinomialP(0,0.55,0)  << endl; 
+cout << "gsl_cdf_binomial_Q(0,0.55,0) =  " << gslcdfbinomialQ(0,0.55,0)  << endl; 
+cout << "gsl_cdf_poisson_P(0, 0.55) =  " << gslcdfpoissonP(0, 0.55)  << endl; 
+cout << "gsl_cdf_poisson_Q(0, 0.55) =  " << gslcdfpoissonQ(0, 0.55)  << endl; 
+cout << "gsl_cdf_geometric_P(0, 0.55) =  " << gslcdfgeometricP(0, 0.55)  << endl; 
+cout << "gsl_cdf_geometric_Q(0, 0.55) =  " << gslcdfgeometricQ(0, 0.55)  << endl; 
+cout << "gsl_cdf_negative_binomial_P(0,0.55,0.55) =  " << gslcdfnegativebinomialP(0,0.55,0.55)  << endl; 
+cout << "gsl_cdf_negative_binomial_Q(0,0.55,0.55) =  " << gslcdfnegativebinomialQ(0,0.55,0.55)  << endl; 
+cout << "gsl_cdf_pascal_P(0,0.55,0) =  " << gslcdfpascalP(0,0.55,0)  << endl; 
+cout << "gsl_cdf_pascal_Q(0,0.55,0) =  " << gslcdfpascalQ(0,0.55,0)  << endl; 
+cout << "gsl_ran_bernoulli_pdf(0, 0.55) =  " << gslranbernoullipdf(0, 0.55)  << endl; 
+cout << "gsl_ran_beta(ffrng,0.55,0.55) =  " << gslranbeta(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_beta_pdf(0.55,0.55,0.55) =  " << gslranbetapdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_binomial_pdf(0,0.55,0) =  " << gslranbinomialpdf(0,0.55,0)  << endl; 
+cout << "gsl_ran_exponential(ffrng, 0.55) =  " << gslranexponential(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_exponential_pdf(0.55, 0.55) =  " << gslranexponentialpdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_exppow(ffrng,0.55,0.55) =  " << gslranexppow(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_exppow_pdf(0.55,0.55,0.55) =  " << gslranexppowpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_cauchy(ffrng, 0.55) =  " << gslrancauchy(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_cauchy_pdf(0.55, 0.55) =  " << gslrancauchypdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_chisq(ffrng, 0.55) =  " << gslranchisq(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_chisq_pdf(0.55, 0.55) =  " << gslranchisqpdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_erlang(ffrng,0.55,0.55) =  " << gslranerlang(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_erlang_pdf(0.55,0.55,0.55) =  " << gslranerlangpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_fdist(ffrng,0.55,0.55) =  " << gslranfdist(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_fdist_pdf(0.55,0.55,0.55) =  " << gslranfdistpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_flat(ffrng,0.55,0.55) =  " << gslranflat(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_flat_pdf(0.55,0.55,0.55) =  " << gslranflatpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_gamma(ffrng,0.55,0.55) =  " << gslrangamma(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_gamma_int(ffrng, 0) =  " << gslrangammaint(ffrng, 0)  << endl; 
+cout << "gsl_ran_gamma_pdf(0.55,0.55,0.55) =  " << gslrangammapdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_gamma_mt(ffrng,0.55,0.55) =  " << gslrangammamt(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_gamma_knuth(ffrng,0.55,0.55) =  " << gslrangammaknuth(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_gaussian(ffrng, 0.55) =  " << gslrangaussian(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_gaussian_ratio_method(ffrng, 0.55) =  " << gslrangaussianratiomethod(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_gaussian_ziggurat(ffrng, 0.55) =  " << gslrangaussianziggurat(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_gaussian_pdf(0.55, 0.55) =  " << gslrangaussianpdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_ugaussian(ffrng) =  " << gslranugaussian(ffrng)  << endl; 
+cout << "gsl_ran_ugaussian_ratio_method(ffrng) =  " << gslranugaussianratiomethod(ffrng)  << endl; 
+cout << "gsl_ran_ugaussian_pdf(0.55) =  " << gslranugaussianpdf(0.55)  << endl; 
+cout << "gsl_ran_gaussian_tail(ffrng,0.55,0.55) =  " << gslrangaussiantail(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_gaussian_tail_pdf(0.55,0.55,0.55) =  " << gslrangaussiantailpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_ugaussian_tail(ffrng, 0.55) =  " << gslranugaussiantail(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_ugaussian_tail_pdf(0.55, 0.55) =  " << gslranugaussiantailpdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_landau(ffrng) =  " << gslranlandau(ffrng)  << endl; 
+cout << "gsl_ran_landau_pdf(0.55) =  " << gslranlandaupdf(0.55)  << endl; 
+cout << "gsl_ran_geometric_pdf(0, 0.55) =  " << gslrangeometricpdf(0, 0.55)  << endl; 
+cout << "gsl_ran_gumbel1(ffrng,0.55,0.55) =  " << gslrangumbel1(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_gumbel1_pdf(0.55,0.55,0.55) =  " << gslrangumbel1pdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_gumbel2(ffrng,0.55,0.55) =  " << gslrangumbel2(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_gumbel2_pdf(0.55,0.55,0.55) =  " << gslrangumbel2pdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_logistic(ffrng, 0.55) =  " << gslranlogistic(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_logistic_pdf(0.55, 0.55) =  " << gslranlogisticpdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_lognormal(ffrng,0.55,0.55) =  " << gslranlognormal(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_lognormal_pdf(0.55,0.55,0.55) =  " << gslranlognormalpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_logarithmic_pdf(0, 0.55) =  " << gslranlogarithmicpdf(0, 0.55)  << endl; 
+cout << "gsl_ran_negative_binomial_pdf(0,0.55,0.55) =  " << gslrannegativebinomialpdf(0,0.55,0.55)  << endl; 
+cout << "gsl_ran_pascal_pdf(0,0.55,0) =  " << gslranpascalpdf(0,0.55,0)  << endl; 
+cout << "gsl_ran_pareto(ffrng,0.55,0.55) =  " << gslranpareto(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_pareto_pdf(0.55,0.55,0.55) =  " << gslranparetopdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_poisson_pdf(0, 0.55) =  " << gslranpoissonpdf(0, 0.55)  << endl; 
+cout << "gsl_ran_rayleigh(ffrng, 0.55) =  " << gslranrayleigh(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_rayleigh_pdf(0.55, 0.55) =  " << gslranrayleighpdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_rayleigh_tail(ffrng,0.55,0.55) =  " << gslranrayleightail(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_rayleigh_tail_pdf(0.55,0.55,0.55) =  " << gslranrayleightailpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_ran_tdist(ffrng, 0.55) =  " << gslrantdist(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_tdist_pdf(0.55, 0.55) =  " << gslrantdistpdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_laplace(ffrng, 0.55) =  " << gslranlaplace(ffrng, 0.55)  << endl; 
+cout << "gsl_ran_laplace_pdf(0.55, 0.55) =  " << gslranlaplacepdf(0.55, 0.55)  << endl; 
+cout << "gsl_ran_levy(ffrng,0.55,0.55) =  " << gslranlevy(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_weibull(ffrng,0.55,0.55) =  " << gslranweibull(ffrng,0.55,0.55)  << endl; 
+cout << "gsl_ran_weibull_pdf(0.55,0.55,0.55) =  " << gslranweibullpdf(0.55,0.55,0.55)  << endl; 
+cout << "gsl_sf_airy_zero_Ai(0) =  " << gslsfairyzeroAi(0)  << endl; 
+cout << "gsl_sf_airy_zero_Bi(0) =  " << gslsfairyzeroBi(0)  << endl; 
+cout << "gsl_sf_airy_zero_Ai_deriv(0) =  " << gslsfairyzeroAideriv(0)  << endl; 
+cout << "gsl_sf_airy_zero_Bi_deriv(0) =  " << gslsfairyzeroBideriv(0)  << endl; 
+cout << "gsl_sf_bessel_J0(0.55) =  " << gslsfbesselJ0(0.55)  << endl; 
+cout << "gsl_sf_bessel_J1(0.55) =  " << gslsfbesselJ1(0.55)  << endl; 
+cout << "gsl_sf_bessel_Jn(0, 0.55) =  " << gslsfbesselJn(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_Y0(0.55) =  " << gslsfbesselY0(0.55)  << endl; 
+cout << "gsl_sf_bessel_Y1(0.55) =  " << gslsfbesselY1(0.55)  << endl; 
+cout << "gsl_sf_bessel_Yn(0, 0.55) =  " << gslsfbesselYn(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_I0(0.55) =  " << gslsfbesselI0(0.55)  << endl; 
+cout << "gsl_sf_bessel_I1(0.55) =  " << gslsfbesselI1(0.55)  << endl; 
+cout << "gsl_sf_bessel_In(0, 0.55) =  " << gslsfbesselIn(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_I0_scaled(0.55) =  " << gslsfbesselI0scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_I1_scaled(0.55) =  " << gslsfbesselI1scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_In_scaled(0, 0.55) =  " << gslsfbesselInscaled(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_K0(0.55) =  " << gslsfbesselK0(0.55)  << endl; 
+cout << "gsl_sf_bessel_K1(0.55) =  " << gslsfbesselK1(0.55)  << endl; 
+cout << "gsl_sf_bessel_Kn(0, 0.55) =  " << gslsfbesselKn(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_K0_scaled(0.55) =  " << gslsfbesselK0scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_K1_scaled(0.55) =  " << gslsfbesselK1scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_Kn_scaled(0, 0.55) =  " << gslsfbesselKnscaled(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_j0(0.55) =  " << gslsfbesselj0(0.55)  << endl; 
+cout << "gsl_sf_bessel_j1(0.55) =  " << gslsfbesselj1(0.55)  << endl; 
+cout << "gsl_sf_bessel_j2(0.55) =  " << gslsfbesselj2(0.55)  << endl; 
+cout << "gsl_sf_bessel_jl(0, 0.55) =  " << gslsfbesseljl(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_y0(0.55) =  " << gslsfbessely0(0.55)  << endl; 
+cout << "gsl_sf_bessel_y1(0.55) =  " << gslsfbessely1(0.55)  << endl; 
+cout << "gsl_sf_bessel_y2(0.55) =  " << gslsfbessely2(0.55)  << endl; 
+cout << "gsl_sf_bessel_yl(0, 0.55) =  " << gslsfbesselyl(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_i0_scaled(0.55) =  " << gslsfbesseli0scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_i1_scaled(0.55) =  " << gslsfbesseli1scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_i2_scaled(0.55) =  " << gslsfbesseli2scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_il_scaled(0, 0.55) =  " << gslsfbesselilscaled(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_k0_scaled(0.55) =  " << gslsfbesselk0scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_k1_scaled(0.55) =  " << gslsfbesselk1scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_k2_scaled(0.55) =  " << gslsfbesselk2scaled(0.55)  << endl; 
+cout << "gsl_sf_bessel_kl_scaled(0, 0.55) =  " << gslsfbesselklscaled(0, 0.55)  << endl; 
+cout << "gsl_sf_bessel_Jnu(0.55, 0.55) =  " << gslsfbesselJnu(0.55, 0.55)  << endl; 
+cout << "gsl_sf_bessel_Ynu(0.55, 0.55) =  " << gslsfbesselYnu(0.55, 0.55)  << endl; 
+cout << "gsl_sf_bessel_Inu_scaled(0.55, 0.55) =  " << gslsfbesselInuscaled(0.55, 0.55)  << endl; 
+cout << "gsl_sf_bessel_Inu(0.55, 0.55) =  " << gslsfbesselInu(0.55, 0.55)  << endl; 
+cout << "gsl_sf_bessel_Knu_scaled(0.55, 0.55) =  " << gslsfbesselKnuscaled(0.55, 0.55)  << endl; 
+cout << "gsl_sf_bessel_Knu(0.55, 0.55) =  " << gslsfbesselKnu(0.55, 0.55)  << endl; 
+cout << "gsl_sf_bessel_lnKnu(0.55, 0.55) =  " << gslsfbessellnKnu(0.55, 0.55)  << endl; 
+cout << "gsl_sf_bessel_zero_J0(0) =  " << gslsfbesselzeroJ0(0)  << endl; 
+cout << "gsl_sf_bessel_zero_J1(0) =  " << gslsfbesselzeroJ1(0)  << endl; 
+cout << "gsl_sf_bessel_zero_Jnu(0.55, 0) =  " << gslsfbesselzeroJnu(0.55, 0)  << endl; 
+cout << "gsl_sf_clausen(0.55) =  " << gslsfclausen(0.55)  << endl; 
+cout << "gsl_sf_hydrogenicR_1(0.55, 0.55) =  " << gslsfhydrogenicR1(0.55, 0.55)  << endl; 
+cout << "gsl_sf_dawson(0.55) =  " << gslsfdawson(0.55)  << endl; 
+cout << "gsl_sf_debye_1(0.55) =  " << gslsfdebye1(0.55)  << endl; 
+cout << "gsl_sf_debye_2(0.55) =  " << gslsfdebye2(0.55)  << endl; 
+cout << "gsl_sf_debye_3(0.55) =  " << gslsfdebye3(0.55)  << endl; 
+cout << "gsl_sf_debye_4(0.55) =  " << gslsfdebye4(0.55)  << endl; 
+cout << "gsl_sf_debye_5(0.55) =  " << gslsfdebye5(0.55)  << endl; 
+cout << "gsl_sf_debye_6(0.55) =  " << gslsfdebye6(0.55)  << endl; 
+cout << "gsl_sf_dilog(0.55) =  " << gslsfdilog(0.55)  << endl; 
+cout << "gsl_sf_multiply(0.55, 0.55) =  " << gslsfmultiply(0.55, 0.55)  << endl; 
+cout << "gsl_sf_erfc(0.55) =  " << gslsferfc(0.55)  << endl; 
+cout << "gsl_sf_log_erfc(0.55) =  " << gslsflogerfc(0.55)  << endl; 
+cout << "gsl_sf_erf(0.55) =  " << gslsferf(0.55)  << endl; 
+cout << "gsl_sf_erf_Z(0.55) =  " << gslsferfZ(0.55)  << endl; 
+cout << "gsl_sf_erf_Q(0.55) =  " << gslsferfQ(0.55)  << endl; 
+cout << "gsl_sf_hazard(0.55) =  " << gslsfhazard(0.55)  << endl; 
+cout << "gsl_sf_exp(0.55) =  " << gslsfexp(0.55)  << endl; 
+cout << "gsl_sf_exp_mult(0.55, 0.55) =  " << gslsfexpmult(0.55, 0.55)  << endl; 
+cout << "gsl_sf_expm1(0.55) =  " << gslsfexpm1(0.55)  << endl; 
+cout << "gsl_sf_exprel(0.55) =  " << gslsfexprel(0.55)  << endl; 
+cout << "gsl_sf_exprel_2(0.55) =  " << gslsfexprel2(0.55)  << endl; 
+cout << "gsl_sf_exprel_n(0, 0.55) =  " << gslsfexpreln(0, 0.55)  << endl; 
+cout << "gsl_sf_expint_E1(0.55) =  " << gslsfexpintE1(0.55)  << endl; 
+cout << "gsl_sf_expint_E2(0.55) =  " << gslsfexpintE2(0.55)  << endl; 
+cout << "gsl_sf_expint_En(0, 0.55) =  " << gslsfexpintEn(0, 0.55)  << endl; 
+cout << "gsl_sf_expint_E1_scaled(0.55) =  " << gslsfexpintE1scaled(0.55)  << endl; 
+cout << "gsl_sf_expint_E2_scaled(0.55) =  " << gslsfexpintE2scaled(0.55)  << endl; 
+cout << "gsl_sf_expint_En_scaled(0, 0.55) =  " << gslsfexpintEnscaled(0, 0.55)  << endl; 
+cout << "gsl_sf_expint_Ei(0.55) =  " << gslsfexpintEi(0.55)  << endl; 
+cout << "gsl_sf_expint_Ei_scaled(0.55) =  " << gslsfexpintEiscaled(0.55)  << endl; 
+cout << "gsl_sf_Shi(0.55) =  " << gslsfShi(0.55)  << endl; 
+cout << "gsl_sf_Chi(0.55) =  " << gslsfChi(0.55)  << endl; 
+cout << "gsl_sf_expint_3(0.55) =  " << gslsfexpint3(0.55)  << endl; 
+cout << "gsl_sf_Si(0.55) =  " << gslsfSi(0.55)  << endl; 
+cout << "gsl_sf_Ci(0.55) =  " << gslsfCi(0.55)  << endl; 
+cout << "gsl_sf_atanint(0.55) =  " << gslsfatanint(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_m1(0.55) =  " << gslsffermidiracm1(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_0(0.55) =  " << gslsffermidirac0(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_1(0.55) =  " << gslsffermidirac1(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_2(0.55) =  " << gslsffermidirac2(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_int(0, 0.55) =  " << gslsffermidiracint(0, 0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_mhalf(0.55) =  " << gslsffermidiracmhalf(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_half(0.55) =  " << gslsffermidirachalf(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_3half(0.55) =  " << gslsffermidirac3half(0.55)  << endl; 
+cout << "gsl_sf_fermi_dirac_inc_0(0.55, 0.55) =  " << gslsffermidiracinc0(0.55, 0.55)  << endl; 
+cout << "gsl_sf_lngamma(0.55) =  " << gslsflngamma(0.55)  << endl; 
+cout << "gsl_sf_gamma(0.55) =  " << gslsfgamma(0.55)  << endl; 
+cout << "gsl_sf_gammastar(0.55) =  " << gslsfgammastar(0.55)  << endl; 
+cout << "gsl_sf_gammainv(0.55) =  " << gslsfgammainv(0.55)  << endl; 
+cout << "gsl_sf_taylorcoeff(0, 0.55) =  " << gslsftaylorcoeff(0, 0.55)  << endl; 
+cout << "gsl_sf_fact(0) =  " << gslsffact(0)  << endl; 
+cout << "gsl_sf_doublefact(0) =  " << gslsfdoublefact(0)  << endl; 
+cout << "gsl_sf_lnfact(0) =  " << gslsflnfact(0)  << endl; 
+cout << "gsl_sf_lndoublefact(0) =  " << gslsflndoublefact(0)  << endl; 
+cout << "gsl_sf_lnchoose(0, 0) =  " << gslsflnchoose(0, 0)  << endl; 
+cout << "gsl_sf_choose(0, 0) =  " << gslsfchoose(0, 0)  << endl; 
+cout << "gsl_sf_lnpoch(0.55, 0.55) =  " << gslsflnpoch(0.55, 0.55)  << endl; 
+cout << "gsl_sf_poch(0.55, 0.55) =  " << gslsfpoch(0.55, 0.55)  << endl; 
+cout << "gsl_sf_pochrel(0.55, 0.55) =  " << gslsfpochrel(0.55, 0.55)  << endl; 
+cout << "gsl_sf_gamma_inc_Q(0.55, 0.55) =  " << gslsfgammaincQ(0.55, 0.55)  << endl; 
+cout << "gsl_sf_gamma_inc_P(0.55, 0.55) =  " << gslsfgammaincP(0.55, 0.55)  << endl; 
+cout << "gsl_sf_gamma_inc(0.55, 0.55) =  " << gslsfgammainc(0.55, 0.55)  << endl; 
+cout << "gsl_sf_lnbeta(0.55, 0.55) =  " << gslsflnbeta(0.55, 0.55)  << endl; 
+cout << "gsl_sf_beta(0.55, 0.55) =  " << gslsfbeta(0.55, 0.55)  << endl; 
+cout << "gsl_sf_beta_inc(0.55,0.55,0.55) =  " << gslsfbetainc(0.55,0.55,0.55)  << endl; 
+cout << "gsl_sf_gegenpoly_1(0.55, 0.55) =  " << gslsfgegenpoly1(0.55, 0.55)  << endl; 
+cout << "gsl_sf_gegenpoly_2(0.55, 0.55) =  " << gslsfgegenpoly2(0.55, 0.55)  << endl; 
+cout << "gsl_sf_gegenpoly_3(0.55, 0.55) =  " << gslsfgegenpoly3(0.55, 0.55)  << endl; 
+cout << "gsl_sf_gegenpoly_n(0,0.55,0.55) =  " << gslsfgegenpolyn(0,0.55,0.55)  << endl; 
+cout << "gsl_sf_hyperg_0F1(0.55, 0.55) =  " << gslsfhyperg0F1(0.55, 0.55)  << endl; 
+cout << "gsl_sf_hyperg_1F1_int(0,0,0.55) =  " << gslsfhyperg1F1int(0,0,0.55)  << endl; 
+cout << "gsl_sf_hyperg_1F1(0.55,0.55,0.55) =  " << gslsfhyperg1F1(0.55,0.55,0.55)  << endl; 
+cout << "gsl_sf_hyperg_U_int(0,0,0.55) =  " << gslsfhypergUint(0,0,0.55)  << endl; 
+cout << "gsl_sf_hyperg_U(0.55,0.55,0.55) =  " << gslsfhypergU(0.55,0.55,0.55)  << endl; 
+cout << "gsl_sf_hyperg_2F0(0.55,0.55,0.55) =  " << gslsfhyperg2F0(0.55,0.55,0.55)  << endl; 
+cout << "gsl_sf_laguerre_1(0.55, 0.55) =  " << gslsflaguerre1(0.55, 0.55)  << endl; 
+cout << "gsl_sf_laguerre_2(0.55, 0.55) =  " << gslsflaguerre2(0.55, 0.55)  << endl; 
+cout << "gsl_sf_laguerre_3(0.55, 0.55) =  " << gslsflaguerre3(0.55, 0.55)  << endl; 
+cout << "gsl_sf_laguerre_n(0,0.55,0.55) =  " << gslsflaguerren(0,0.55,0.55)  << endl; 
+cout << "gsl_sf_lambert_W0(0.55) =  " << gslsflambertW0(0.55)  << endl; 
+cout << "gsl_sf_lambert_Wm1(0.55) =  " << gslsflambertWm1(0.55)  << endl; 
+cout << "gsl_sf_legendre_Pl(0, 0.55) =  " << gslsflegendrePl(0, 0.55)  << endl; 
+cout << "gsl_sf_legendre_P1(0.55) =  " << gslsflegendreP1(0.55)  << endl; 
+cout << "gsl_sf_legendre_P2(0.55) =  " << gslsflegendreP2(0.55)  << endl; 
+cout << "gsl_sf_legendre_P3(0.55) =  " << gslsflegendreP3(0.55)  << endl; 
+cout << "gsl_sf_legendre_Q0(0.55) =  " << gslsflegendreQ0(0.55)  << endl; 
+cout << "gsl_sf_legendre_Q1(0.55) =  " << gslsflegendreQ1(0.55)  << endl; 
+cout << "gsl_sf_legendre_Ql(0, 0.55) =  " << gslsflegendreQl(0, 0.55)  << endl; 
+cout << "gsl_sf_legendre_Plm(0,0,0.55) =  " << gslsflegendrePlm(0,0,0.55)  << endl; 
+cout << "gsl_sf_legendre_sphPlm(0,0,0.55) =  " << gslsflegendresphPlm(0,0,0.55)  << endl; 
+cout << "gsl_sf_legendre_array_size(0, 0) =  " << gslsflegendrearraysize(0, 0)  << endl; 
+cout << "gsl_sf_conicalP_half(0.55, 0.55) =  " << gslsfconicalPhalf(0.55, 0.55)  << endl; 
+cout << "gsl_sf_conicalP_mhalf(0.55, 0.55) =  " << gslsfconicalPmhalf(0.55, 0.55)  << endl; 
+cout << "gsl_sf_conicalP_0(0.55, 0.55) =  " << gslsfconicalP0(0.55, 0.55)  << endl; 
+cout << "gsl_sf_conicalP_1(0.55, 0.55) =  " << gslsfconicalP1(0.55, 0.55)  << endl; 
+cout << "gsl_sf_conicalP_sph_reg(0,0.55,0.55) =  " << gslsfconicalPsphreg(0,0.55,0.55)  << endl; 
+cout << "gsl_sf_conicalP_cyl_reg(0,0.55,0.55) =  " << gslsfconicalPcylreg(0,0.55,0.55)  << endl; 
+cout << "gsl_sf_legendre_H3d_0(0.55, 0.55) =  " << gslsflegendreH3d0(0.55, 0.55)  << endl; 
+cout << "gsl_sf_legendre_H3d_1(0.55, 0.55) =  " << gslsflegendreH3d1(0.55, 0.55)  << endl; 
+cout << "gsl_sf_legendre_H3d(0,0.55,0.55) =  " << gslsflegendreH3d(0,0.55,0.55)  << endl; 
+cout << "gsl_sf_log(0.55) =  " << gslsflog(0.55)  << endl; 
+cout << "gsl_sf_log_abs(0.55) =  " << gslsflogabs(0.55)  << endl; 
+cout << "gsl_sf_log_1plusx(0.55) =  " << gslsflog1plusx(0.55)  << endl; 
+cout << "gsl_sf_log_1plusx_mx(0.55) =  " << gslsflog1plusxmx(0.55)  << endl; 
+cout << "gsl_sf_pow_int(0.55, 0) =  " << gslsfpowint(0.55, 0)  << endl; 
+cout << "gsl_sf_psi_int(0) =  " << gslsfpsiint(0)  << endl; 
+cout << "gsl_sf_psi(0.55) =  " << gslsfpsi(0.55)  << endl; 
+cout << "gsl_sf_psi_1piy(0.55) =  " << gslsfpsi1piy(0.55)  << endl; 
+cout << "gsl_sf_psi_1_int(0) =  " << gslsfpsi1int(0)  << endl; 
+cout << "gsl_sf_psi_1(0.55) =  " << gslsfpsi1(0.55)  << endl; 
+cout << "gsl_sf_psi_n(0, 0.55) =  " << gslsfpsin(0, 0.55)  << endl; 
+cout << "gsl_sf_synchrotron_1(0.55) =  " << gslsfsynchrotron1(0.55)  << endl; 
+cout << "gsl_sf_synchrotron_2(0.55) =  " << gslsfsynchrotron2(0.55)  << endl; 
+cout << "gsl_sf_transport_2(0.55) =  " << gslsftransport2(0.55)  << endl; 
+cout << "gsl_sf_transport_3(0.55) =  " << gslsftransport3(0.55)  << endl; 
+cout << "gsl_sf_transport_4(0.55) =  " << gslsftransport4(0.55)  << endl; 
+cout << "gsl_sf_transport_5(0.55) =  " << gslsftransport5(0.55)  << endl; 
+cout << "gsl_sf_sin(0.55) =  " << gslsfsin(0.55)  << endl; 
+cout << "gsl_sf_cos(0.55) =  " << gslsfcos(0.55)  << endl; 
+cout << "gsl_sf_hypot(0.55, 0.55) =  " << gslsfhypot(0.55, 0.55)  << endl; 
+cout << "gsl_sf_sinc(0.55) =  " << gslsfsinc(0.55)  << endl; 
+cout << "gsl_sf_lnsinh(0.55) =  " << gslsflnsinh(0.55)  << endl; 
+cout << "gsl_sf_lncosh(0.55) =  " << gslsflncosh(0.55)  << endl; 
+cout << "gsl_sf_angle_restrict_symm(0.55) =  " << gslsfanglerestrictsymm(0.55)  << endl; 
+cout << "gsl_sf_angle_restrict_pos(0.55) =  " << gslsfanglerestrictpos(0.55)  << endl; 
+cout << "gsl_sf_zeta_int(0) =  " << gslsfzetaint(0)  << endl; 
+cout << "gsl_sf_zeta(0.55) =  " << gslsfzeta(0.55)  << endl; 
+cout << "gsl_sf_zetam1(0.55) =  " << gslsfzetam1(0.55)  << endl; 
+cout << "gsl_sf_zetam1_int(0) =  " << gslsfzetam1int(0)  << endl; 
+cout << "gsl_sf_hzeta(0.55, 0.55) =  " << gslsfhzeta(0.55, 0.55)  << endl; 
+cout << "gsl_sf_eta_int(0) =  " << gslsfetaint(0)  << endl; 
+cout << "gsl_sf_eta(0.55) =  " << gslsfeta(0.55)  << endl; 
diff --git a/examples++-load/ilut.cpp b/examples++-load/ilut.cpp
new file mode 100644
index 0000000..4fa981d
--- /dev/null
+++ b/examples++-load/ilut.cpp
@@ -0,0 +1,152 @@
+/*
+ * ilut.cpp: ILUT plugin for FreeFem++ wrapping GMM++ functions.
+ * Copyright (C) 2008, Alessandro Proverbio and David Radice.
+ *
+ * ilut.cpp is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation;
+ *
+ * ilut.cpp  is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with ilut.cpp; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//ff-c++-LIBRARY-dep:   gmm
+//ff-c++-cpp-dep: 
+
+#include <cmath>
+#include <iostream>
+#include "AFunction.hpp"
+#include "RNM.hpp"
+#include "error.hpp"
+#include <gmm/gmm.h>
+#include <vector>
+
+#define ILUT_K_FILLIN 5
+#define ILUT_EPS 1e-6
+
+#define PRINT(VAR) cout << VAR << endl
+
+using namespace std;
+using namespace gmm;
+
+typedef ilut_precond<row_matrix<rsvector<double> > > my_ilut_precond;
+
+class ILUT;
+
+class ILUT_Matrix {
+	private:
+		long * _i;
+		long * _j;
+		double * _c;
+
+		long _nelem;
+		long _size;
+	public:
+		ILUT_Matrix(KN<long> * const & i,
+				KN<long> * const & j,
+				KN<double> * const & c): _i(*i),
+					_j(*j),
+					_c(*c),
+					_nelem(c->N()) {
+			_size=max(i->max(),j->max());
+			++_size;
+		}
+	friend class ILUT;
+};
+
+class ILUT_Vector {
+	private:
+		double * _v;
+		long _size;
+	public:
+		ILUT_Vector(KN<double> * const & c) : _v(*c),_size(c->N()) {}
+	friend class ILUT;
+};
+
+class ILUT {
+	private:
+		static my_ilut_precond * p;
+		static long size;
+	public:
+		static long make_ilut_precond(ILUT_Matrix const & m) {
+			row_matrix<rsvector<double> > A(m._size,m._size);
+			row_matrix<wsvector<double> > w_A(m._size,m._size);
+
+			for(long k(0);k<m._nelem;++k) {
+				w_A[m._i[k]][m._j[k]]=m._c[k];
+			}
+
+			copy(w_A,A);  // A <-- w_A
+			delete p;
+			p = new my_ilut_precond(A,ILUT_K_FILLIN,ILUT_EPS);
+
+			size=m._size;
+
+			return 0;
+		}
+		static void apply_ilut_precond(ILUT_Vector const & v,
+				KN<double> * const & x) {
+
+			vector<double> vv(size);
+			vector<double> xx(size);
+
+			for(long k=0;k<size;++k) {
+				vv[k]=v._v[k];
+			}
+
+			mult(*p,vv,xx); // xx <-- p.solve(vv)
+
+			for(long k=0;k<size;++k) {
+				(*x)[k]=xx[k];
+			}
+
+			// If used for the full vector fill the remaining components
+			for(long k=0;k+size<x->N();++k) {
+				(*x)[k+size]=v._v[k+size];
+			}
+		}
+
+};
+
+my_ilut_precond * ILUT::p=0;
+long ILUT::size=0;
+
+long * make_ilut_precond_eq(long * const & errorcode,
+		ILUT_Matrix const & mat) {
+	*errorcode=ILUT::make_ilut_precond(mat);
+	return errorcode;
+}
+
+KN<double> * apply_ilut_precond_eq(KN<double> * const & x,
+		ILUT_Vector const & vec) {
+	ILUT::apply_ilut_precond(vec, x);
+	return x;
+}
+
+ILUT_Matrix make_ilut_precond(KN<long> * const & i,
+		KN<long> * const & j,
+		KN<double> * const & v) {
+	return ILUT_Matrix(i,j,v);
+}
+
+ILUT_Vector apply_ilut_precond(KN<double> * const & v) {
+	return ILUT_Vector(v);
+}
+
+static void Load_Init() {
+  if(verbosity) cout << " -- load ilut init : " << endl;
+  Dcl_Type<ILUT_Matrix>();
+  Dcl_Type<ILUT_Vector>();
+  Global.Add("applyIlutPrecond","(",new OneOperator1_<ILUT_Vector,KN<double>* >(apply_ilut_precond));
+  Global.Add("makeIlutPrecond","(", new OneOperator3_<ILUT_Matrix,KN<long> *,KN<long> *,KN<double> *>(make_ilut_precond));
+  TheOperators->Add("=", new OneOperator2_<long *,long *,ILUT_Matrix>(make_ilut_precond_eq));
+  TheOperators->Add("=", new OneOperator2_<KN<double> *, KN<double> *,ILUT_Vector>(apply_ilut_precond_eq));
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/ilut.edp b/examples++-load/ilut.edp
new file mode 100644
index 0000000..48cf74a
--- /dev/null
+++ b/examples++-load/ilut.edp
@@ -0,0 +1,44 @@
+load "ilut"
+mesh Th=square(10,10);
+fespace Qh(Th,P1);
+fespace Vh(Th,P2);
+real nu=1;
+varf mp(p,q)=int2d(Th)(p*q/nu);
+
+matrix Mp=mp(Qh,Qh);
+real[int] diagMp(Qh.ndof); diagMp=Mp.diag; diagMp=1/nu*diagMp;
+
+// We are putting this here to workaround a bug in freefem++
+real[int] ilutOUT(Vh.ndof+Qh.ndof);
+
+// Uses ILUT for the velocity part and the mass matrix for the pressure part
+func real[int] ilutMp(real[int] & xx) {
+	real[int] uuin(Vh.ndof);
+	real[int] ppin(Qh.ndof);
+
+	real[int] uuout(Vh.ndof);
+	real[int] ppout(Qh.ndof);
+
+	[uuin,ppin]=xx;
+
+	for(int k=0;k<Qh.ndof;++k)  {
+		ppout[k]=ppin[k]/diagMp[k];
+	}
+	//ppout=Mp^-1*ppin;
+	uuout=applyIlutPrecond(uuin);
+
+	ilutOUT=[uuout,ppin];
+	return ilutOUT;
+}
+//dumptable(cout);
+// Uses ILUT for the velocity and I for the pressure
+func real[int] ilut(real[int] & xx) {
+	ilutOUT=applyIlutPrecond(xx);
+	return ilutOUT;
+}
+
+// Dummy do-nothing preconditioner
+func real[int] dummy(real[int] & xx) {
+	ilutOUT=xx;
+	return ilutOUT;
+}
diff --git a/examples++-load/include.tar.gz b/examples++-load/include.tar.gz
new file mode 100644
index 0000000..a69ee19
Binary files /dev/null and b/examples++-load/include.tar.gz differ
diff --git a/examples++-load/iohd5-beam-2d.edp b/examples++-load/iohd5-beam-2d.edp
new file mode 100644
index 0000000..01acee7
--- /dev/null
+++ b/examples++-load/iohd5-beam-2d.edp
@@ -0,0 +1,40 @@
+//  Fluid-structure interaction for a weighting beam sitting on a
+// square cavity filled with a fluid.
+load "iohdf5"
+int bottombeam = 2;
+border a(t=2,0)  { x=0; y=t ;label=1;};        //  left beam
+border b(t=0,10) { x=t; y=0 ;label=bottombeam;};        //  bottom of beam
+border c(t=0,2)  { x=10; y=t ;label=1;};       //  rigth beam
+border d(t=0,10) { x=10-t; y=2; label=3;};     //  top beam 
+real E = 21.5;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+mesh th = buildmesh( b(20)+c(5)+d(20)+a(5));
+fespace Vh(th,[P1,P1]);
+Vh [uu,vv], [w,s];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+// deformation of a beam under its own weight 
+// definition of 2 macro :
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2)  [dx(u1),dy(u2),(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u,v) ( dx(u)+dy(v) ) // EOM
+
+solve bb([uu,vv],[w,s],solver=CG)=
+	int2d(th)(  
+		  lambda*div(w,s)*div(uu,vv)	
+                  +2.*mu*( epsilon(w,s)'*epsilon(uu,vv) ) 
+                 )
+  - int2d(th) (gravity*s)
+  + on(1,uu=0,vv=0)
+  ;
+
+//verbosity=100;
+plot([uu,vv],wait=1);
+plot([uu,vv],wait=1,bb=[[-0.5,2.5],[2.5,-0.5]]);
+mesh th1 = movemesh(th, [x+uu, y+vv]);
+plot(th1,wait=1);
+cout << " max deplacement = " << uu[].linfty << endl;
+savemesh(th1,"beam-2d-def.mesh.h5");
+savehdf5sol("beam-2d-def.sol.h5",th1,uu,"uu",[uu,vv],"U",(epsilon(uu,vv)),"eps");
\ No newline at end of file
diff --git a/examples++-load/iohd5-beam-3d.edp b/examples++-load/iohd5-beam-3d.edp
new file mode 100644
index 0000000..3d19867
--- /dev/null
+++ b/examples++-load/iohd5-beam-3d.edp
@@ -0,0 +1,42 @@
+load "medit"
+load "iohdf5"
+include "cube.idp"
+load "iovtk"
+verbosity=2;
+int[int]  Nxyz=[20,5,5];
+real [int,int]  Bxyz=[[0.,5.],[0.,1.],[0.,1.]];
+int [int,int]  Lxyz=[[1,2],[2,2],[2,2]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+
+real E = 21.5e4;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+
+fespace Vh(Th,[P1,P1,P1]);
+Vh [u1,u2,u3], [v1,v2,v3];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2,u3)  [dx(u1),dy(u2),dz(u3),(dz(u2)+dy(u3))/sqrt2,(dz(u1)+dx(u3))/sqrt2,(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u1,u2,u3) ( dx(u1)+dy(u2)+dz(u3) ) // EOM
+
+solve Lame([u1,u2,u3],[v1,v2,v3])=
+  int3d(Th)(  
+	    lambda*div(u1,u2,u3)*div(v1,v2,v3)	
+	    +2.*mu*( epsilon(u1,u2,u3)'*epsilon(v1,v2,v3) ) //')
+	      )
+  - int3d(Th) (gravity*v3)
+  + on(1,u1=0,u2=0,u3=0)
+  ;
+real dmax= u1[].max;
+cout << " max deplacement = " << dmax << endl;
+real coef= 0.1/dmax;
+int[int] ref2=[1,0,2,0];
+mesh3 Thm=movemesh3(Th,transfo=[x+u1*coef,y+u2*coef,z+u3*coef],label=ref2);
+Thm=change(Thm,label=ref2);
+plot(Th,Thm, wait=1,cmm="coef  amplification = "+coef );
+
+savemesh(Thm,"beam-3d-def.mesh.h5");
+savehdf5sol("beam-3d-def.sol.h5",Thm,u1,"ux",[u1,u2,u3],"U",(epsilon(u1,u2,u3)),"eps");
\ No newline at end of file
diff --git a/examples++-load/iohdf5.cpp b/examples++-load/iohdf5.cpp
new file mode 100644
index 0000000..3f244f7
--- /dev/null
+++ b/examples++-load/iohdf5.cpp
@@ -0,0 +1,734 @@
+// SUMMARY  :   add interface with partionning library scotch 
+// USAGE    : LGPL      
+// ORG      : CINES - http://www.cines.fr
+// AUTHOR   : Mathieu Cloirec
+// tel:04-67-14-14-51
+// E-MAIL   :  cloirec at cines.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:  hdf5
+//ff-c++-cpp-dep: 
+
+#include "ff++.hpp"
+#include "write_xdmf.hpp"
+#include "write_hdf5.hpp"
+
+
+#ifndef H5_NO_NAMESPACE
+#ifndef H5_NO_STD
+using std::cout;
+using std::endl;
+#endif  // H5_NO_STD
+#endif
+
+#include "H5Cpp.h"
+
+#ifndef H5_NO_NAMESPACE
+using namespace H5;
+#endif
+#ifdef DEBUG
+int debug=1;
+#else
+int debug=0;
+#endif
+
+using namespace std;
+
+class datasolHDF5Mesh2_Op : public E_F0mps 
+{
+  
+public:
+  
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  struct Expression2 
+  {
+    long what; // 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 1 scalar, 2 vector (3D), 3 symtensor(3D)
+    Expression e[3];
+    Expression lename;
+    Expression2() 
+    {
+      e[0]=0;
+      e[1]=0; 
+      e[2]=0;  
+      what=0; 
+      nbfloat=0;
+    };
+    Expression &operator[](int i)
+    {
+      return e[i];
+    }
+    double eval(int i,Stack stack) const  
+    { 
+      if (e[i]) 
+	{
+	  return GetAny< double >( (*e[i])(stack) );
+	}
+      else 
+	return 0;
+    }
+  };
+  vector<Expression2> l;
+  static const int n_name_param = 1;  
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  long    arg(int i,Stack stack,long a ) const
+  { 
+    return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;
+  }
+ 
+public:
+  datasolHDF5Mesh2_Op(const basicAC_F0 &  args) : l((args.size()-2)/2 )
+  {
+    int nbofsol;
+    int ddim=2;
+    int stsize=3;
+    cout << " " << endl;
+    
+    if(debug==1)
+      {
+	cout << "construction data hdf5 solution avec datasolHDF5Mesh2_Op" << endl;
+	cout << "taille de args " << args.size() << endl;
+      }
+    args.SetNameParam(n_name_param,name_param,nargs);
+    
+    if (BCastTo<string *>(args[0])) filename = CastTo<string *>(args[0]);
+    if (BCastTo<pmesh>(args[1])) eTh= CastTo<pmesh>(args[1]);
+    
+    nbofsol = l.size(); 
+    if(debug==1)
+      {
+	cout << "hdf5 solution 2d nb sol: "<< nbofsol  << endl;
+      }
+    size_t kk=0;
+    for (size_t i=2;i<(unsigned int)args.size();i=i+2)
+      {
+	size_t jj=i-2-kk;
+	if (BCastTo<double>( args[i] ))
+	  {	   
+	    l[jj].what=1;
+	    l[jj].nbfloat=1;
+	    l[jj][0]=to<double>( args[i] );
+	    if(debug==1)
+	      {
+		cout << "hdf5 solution 2d N° " << jj << " is scalar type "  << endl;
+	      }
+	  }
+	else if ( args[i].left()==atype<E_Array>() )
+	  {
+	    const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	    if (a0->size() != ddim && a0->size() != stsize) 
+	      CompileError("savesol in 2D: vector solution is 2 composant, tensor solution is 3 composant");
+	    
+	    if( a0->size() == ddim)
+	      {
+		// vector solution
+		if(debug==1)
+		  {
+		    cout << "hdf5 solution 2d N° " << jj << " is vector type" << endl;
+		  }
+		l[jj].what=2;
+		l[jj].nbfloat=ddim;
+		for(int j=0; j<ddim; j++)
+		  {
+		    l[jj][j] = to<double>( (*a0)[j]);
+		  }
+	      }
+	    else if( a0->size() == stsize)
+	      {
+		// symmetric tensor solution 
+		if(debug==1)
+		  {
+		    cout << "hdf5 solution 2d N° " << jj << " is tensor type" << endl;
+		  }
+		l[jj].what=3;
+		l[jj].nbfloat=stsize;
+		for(int j=0; j<stsize; j++)
+		  {
+		    l[jj][j] = to<double>( (*a0)[j]);
+		  }
+	      }
+	  }
+	else 
+	  {
+	    cout << " arg " << i << " " << args[i].left() << endl;
+	    CompileError("savesol in 2D: Sorry no way to save this kind of data");
+	  }
+	if (BCastTo<string *>(args[i+1])) l[jj].lename = CastTo<string *>(args[i+1]);
+	kk++;
+      }    
+  }
+
+  static ArrayOfaType  typeargs() 
+  { 
+    return  ArrayOfaType( atype<string *>(), atype<pmesh>(), true); 
+  }
+  
+  static  E_F0 * f(const basicAC_F0 & args) 
+  { 
+    return new datasolHDF5Mesh2_Op(args);
+  } 
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type datasolHDF5Mesh2_Op::name_param[]= 
+  {
+    {  "order",&typeid(long)}
+  };
+
+AnyType datasolHDF5Mesh2_Op::operator()(Stack stack)  const 
+{
+  //Hyp A
+  //-----
+  // A priori, paraview - hdf5 -xdmf impose qu un vecteur possede 3 composantes.
+  // Donc, pour stocker la solution, on transforme le resultat produit par le 
+  // code, i.e. vecteur 2D, en vecteur 3D en initialisant le vecteur 3D a zero.
+  //
+  
+  //Hyp B
+  //-----
+  // Etant donne que le tenseur est un tenseur 2d symetrique,
+  // on fait le choix, ici, pour paraview, de le representer sous forme
+  // d'un vecteur a 3 composantes Exx,Eyy,Exy=Eyx
+  // un autre choix possible serait de stocker les valeurs sous 
+  // un tenseur 3x3 avec Ezz=Exz=Ezx=Eyz=Ezy=0
+
+  // mp & mps set but not used 
+  //MeshPoint *mp(MeshPointStack(stack)), mps=*mp;
+
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  string * ffname= GetAny<string *>( (*filename)(stack) );
+  
+  ffassert(pTh);
+  Mesh &Th=*pTh;
+  int nt = Th.nt;
+  int nv = Th.nv;
+  //  int nbtype=l.size();
+  int nbsol;
+  int solnbfloat;
+  int resultorder= arg(0, stack, 1L);
+  string * datafieldname;
+  long longdefault = 0;
+ 
+  if(verbosity>2)
+    {
+      cout << "filename data hdf5 solution () : "<< ffname << endl;
+      cout << "hdf5 solution () nb vertices: "<< nv << endl;
+      cout << "hdf5 solution () nb triangles: "<< nt << endl; 
+      cout << "hdf5 solution () nb of fields: "<< l.size()  << endl;
+    }
+  
+  //write xdmf sol file
+  WriteXdmf * XdmfSolFile2D = new WriteXdmf(ffname->c_str(),nt,nv);
+  XdmfSolFile2D->WriteXdmfSolFile2DInit();
+  for (size_t i=0;i<l.size();i++)
+    { 
+      //Hyp A
+      int trans=-1;
+      if(l[i].nbfloat==2)
+  	{
+  	  trans=3;
+  	}
+      else
+  	{
+  	  trans=l[i].nbfloat;
+  	}
+      datafieldname= GetAny<string *>( (*(l[i].lename))(stack) );
+      XdmfSolFile2D->WriteXdmfSolFile2DAddField(datafieldname,  (l[i].what-1), resultorder, trans);
+    }
+  XdmfSolFile2D->WriteXdmfSolFile2DFinalize();
+  delete XdmfSolFile2D;
+
+  //write hdf5 sol file
+  WriteHdf5 * Hdf5SolFile2D = new WriteHdf5(ffname->c_str(),nt,nv);
+  Hdf5SolFile2D->WriteHdf5SolFile2DInit();
+
+  solnbfloat=0;
+
+  for (size_t ii=0;ii<l.size();ii++)
+    { 
+      datafieldname= GetAny<string *>( (*(l[ii].lename))(stack) );
+   
+      if(resultorder==0) 
+	{
+	  // ordre 0
+	  // a priori la solution est par triangle
+
+	  //Hyp A
+	  int trans=-1;
+	  if(l[ii].nbfloat==2)
+	    {
+	      trans=3;
+	    }
+	  else
+	    {
+	      trans=l[ii].nbfloat;
+	    }
+	  //initialisation a 0 du field tab
+	  float *tab_vfield;
+	  tab_vfield = new float[nt * trans];
+	  memset(tab_vfield, 0, sizeof(float) * nt * trans);
+
+
+	  solnbfloat=l[ii].nbfloat;
+	  nbsol = nt;  
+	  KN<double> valsol(solnbfloat*nbsol);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R2 Cdg_hat = R2(1./3.,1./3.);  
+      
+	  //boucle sur les triangles
+	  for (int it=0;it<nt;it++)
+	    {
+	      int h=0;
+	      const Mesh::Triangle  & K(Th.t(it));
+	      mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	      //boucle sur chaque champ des triangles
+	      for(size_t i=0;i<l.size();i++)
+		{
+		  //boucle sur les valeurs de chaque champ des triangles
+		  for(size_t j=0;j<(unsigned int)l[ii].nbfloat;j++)
+		    {
+		      valsol[it*solnbfloat+h] = l[ii].eval(j,stack);
+		      h=h+1;
+		    }
+		} 
+	      assert(solnbfloat==h);
+	    }
+	  
+	  //creation du tableau de valeur des champs par element (idem valsol mais pour le cas vecteur
+	  //il faut 0 sur la troisieme composante : Hyp A
+	  for(int i=0; i<nt; i++)
+	    {
+	      for(int h=0; h<solnbfloat; h++)
+		{
+		  tab_vfield[i*trans+h]=valsol[i*solnbfloat+h];
+		}
+	    }
+	  
+	  Hdf5SolFile2D->WriteHdf5SolFile2DAddField(datafieldname, resultorder, trans, (l[ii].what-1),tab_vfield);
+	  delete [] tab_vfield;
+	}
+      else
+	{
+	  //Hyp A
+	  int trans=-1;
+	  if(l[ii].nbfloat==2)
+	    {
+	      trans=3;
+	    }
+	  else
+	    {
+	      trans=l[ii].nbfloat;
+	    }
+	  //initialisation a 0 du field tab
+	  float *tab_vfield;
+	  tab_vfield = new float[nv * trans];
+	  memset(tab_vfield, 0, sizeof(float) * nv * trans);
+
+	  solnbfloat=l[ii].nbfloat;
+	  nbsol = nv;  
+	  KN<double> valsol(solnbfloat*nbsol);
+	  valsol=0.;
+	  KN<int> takemesh(nbsol);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  takemesh=0;
+	  
+	  //boucle sur les triangles
+	  for (int it=0;it<nt;it++)
+	    {
+	      //boucle sur les 3 noeuds du triangle
+	      for(int iv=0;iv<3;iv++)
+		{
+		  //i = numéro du noeud
+		  //ex : triangle 0 avec noeuds : 2 3 9
+		  int i=Th(it,iv);
+		  mp3->setP(&Th,it,iv);
+		  int h=0;
+		  
+		  for(size_t j=0;j<(unsigned int)l[ii].nbfloat;j++)
+		    {
+		      //calcul de la somme des valeurs du champ Ux (par exemple) sur un noeud
+		      //appartenant à plusieurs triangles
+		      //u_noeud_2_appartenant_au_triangle_0 + u_noeud_2_appartenant_au_triangle_23 + ...
+		      valsol[i*solnbfloat+h] = valsol[i*solnbfloat+h] + l[ii].eval(j,stack);
+		      h=h+1;
+		    }
+		  
+		  assert(solnbfloat==h);
+		  takemesh[i] = takemesh[i]+1;
+		}
+	    }
+	  for(int i=0; i<nv; i++)
+	    {
+	      for(int h=0; h<solnbfloat; h++)
+		{
+		  //calcul de la moyenne des valeurs du champ Ux (par exemple) sur un noeud
+		  //appartenant à plusieurs triangles
+		  valsol[i*solnbfloat+h] = valsol[i*solnbfloat+h]/takemesh[i]; 
+		}
+	    }
+	  for(int i=0; i<nv; i++)
+	    {
+	      for(int h=0; h<solnbfloat; h++)
+		{
+		  tab_vfield[i*trans+h]=valsol[i*solnbfloat+h];
+		}
+	    }
+	  if(verbosity>10)
+	    {
+	      for (int m=0;m<(solnbfloat*nbsol);m++) 
+		cout << "valsol[m] hdf5 solution : "<< valsol[m] << " for lii : " << ii << endl;
+	    }
+
+	  Hdf5SolFile2D->WriteHdf5SolFile2DAddField(datafieldname, resultorder, trans, (l[ii].what-1),tab_vfield);
+	  delete [] tab_vfield;
+	}
+    }
+  Hdf5SolFile2D->WriteHdf5SolFile2DFinalize();
+  delete Hdf5SolFile2D;
+  return longdefault; 
+};
+
+//datasolMesh3
+template<class v_fes>
+class datasolHDF5Mesh3_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  
+  struct Expression2 {
+    long what; // 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 1 scalar, 3 vector (3D), 6 symtensor(3D)
+    Expression e[6];
+    Expression lename;
+    Expression2() 
+    {
+      e[0]=0; 
+      e[1]=0; 
+      e[2]=0; 
+      e[3]=0; 
+      e[4]=0; 
+      e[5]=0; 
+      what=0; 
+      nbfloat=0;
+    };
+    Expression &operator[](int i)
+    {
+      return e[i];
+    }
+    double eval(int i,Stack stack) const  
+    { 
+      if (e[i]) 
+	{
+	  return GetAny< double >( (*e[i])(stack) );
+	}
+      else 
+	return 0;
+    }
+    
+  };
+  vector<Expression2> l; 
+  static const int n_name_param =1;  
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  long    arg(int i,Stack stack,long a ) const
+  { 
+    return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;
+  }
+ 
+public:
+  datasolHDF5Mesh3_Op(const basicAC_F0 &  args) :  l((args.size()-2)/2 )
+  {
+    int nbofsol;
+    int ddim=3;
+    int stsize=6;
+   
+    cout << " " << endl;
+    if(debug==1)
+      {
+	cout << "construction data hdf5 solution avec datasolHDF5Mesh3_Op" << endl;
+	cout << "taille de args " << args.size() << endl;
+      }
+
+    args.SetNameParam(n_name_param,name_param,nargs); 
+    if (BCastTo<string *>(args[0])) filename = CastTo<string *>(args[0]);
+    if (BCastTo<pmesh3>(args[1])) eTh= CastTo<pmesh3>(args[1]);
+
+    nbofsol = l.size();
+    if(verbosity > 1)
+      {
+	cout << "hdf5 solution 3d nb sol: "<< nbofsol  << endl;
+      }
+    size_t kk=0;
+    for (size_t i=2;i<(unsigned int)args.size();i=i+2)
+      {
+	size_t jj=i-2-kk;
+	if ( BCastTo<double>(args[i]))
+	  {
+	    l[jj].what=1;
+	    l[jj].nbfloat=1;
+	    l[jj][0]=to<double>( args[i] );
+	    if(verbosity > 9)
+	      {
+		cout << "hdf5 solution 3d N° " << jj << " is scalar type "  << endl;
+	      }
+	  }
+	else if ( args[i].left()==atype<E_Array>() )
+	  {
+	    const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	    if (a0->size() != ddim && a0->size() != stsize) 
+	      {
+		CompileError("savesol in 3D: vector solution is 3 composant, tensor solution is 6 composant");
+	      }
+
+	    if( a0->size() == ddim)
+	      {
+		// vector solution
+		if(verbosity > 9)
+		  {
+		    cout << "hdf5 solution 3d N° " << jj << " is vector type" << endl;
+		  }
+		l[jj].what=2;
+		l[jj].nbfloat=ddim;
+		for(int j=0; j<ddim; j++)
+		  {
+		    l[jj][j] = to<double>( (*a0)[j]);
+		  }
+	      }
+	    else if( a0->size() == stsize)
+	      {
+		// symmetric tensor solution
+		if(verbosity > 9)
+		  {
+		    cout << "hdf5 solution 3d N° " << jj << " is tensor type" << endl;
+		  }
+		l[jj].what=3;
+		l[jj].nbfloat=stsize;
+		for(int j=0; j<stsize; j++)
+		  {
+		    l[jj][j] = to<double>( (*a0)[j]);
+		  }
+	      }
+	  }
+	else 
+	  {
+	    CompileError("savesol in 3D: Sorry no way to save this kind of data");
+	  }
+	if (BCastTo<string *>(args[i+1])) l[jj].lename = CastTo<string *>(args[i+1]);
+	kk++;
+      }
+  }
+  static ArrayOfaType  typeargs() 
+  { 
+    return  ArrayOfaType( atype<string *>(), atype<pmesh3>(), true); 
+  }
+  static  E_F0 * f(const basicAC_F0 & args) 
+  { 
+    return new datasolHDF5Mesh3_Op(args);
+  } 
+  AnyType operator()(Stack stack)  const ;
+};
+
+template<class v_fes>
+basicAC_F0::name_and_type datasolHDF5Mesh3_Op<v_fes>::name_param[]= 
+  {
+    { "order",&typeid(long)}
+  };
+
+template<class v_fes>
+AnyType datasolHDF5Mesh3_Op<v_fes>::operator()(Stack stack)  const 
+{ 
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  string * ffname= GetAny<string *>( (*filename)(stack) );
+  ffassert(pTh);
+  Mesh3 &Th=*pTh;
+  int trans=-1;
+  int nt = Th.nt;
+  int nv = Th.nv;
+  int nbsol;
+  int solnbfloat;
+  int resultorder= arg(0, stack, 1);
+  long longdefault = 0;
+  string * datafieldname;
+ 
+  if(verbosity>2)
+    {
+      cout << "filename data hdf5 solution () : "<< ffname << endl;
+      cout << "hdf5 solution () nb vertices: "<< nv << endl;
+      cout << "hdf5 solution () nb tetrahedrons: "<< nt << endl; 
+      cout << "hdf5 solution () nb of fields: "<< l.size()  << endl;
+    }
+  
+  //write xdmf sol file
+  WriteXdmf * XdmfSolFile3D = new WriteXdmf(ffname->c_str(),nt,nv);
+  XdmfSolFile3D->WriteXdmfSolFile3DInit();
+  for (size_t i=0;i<l.size();i++)
+    { 
+      //Hyp A
+      trans=l[i].nbfloat;
+      datafieldname= GetAny<string *>( (*(l[i].lename))(stack) );
+      XdmfSolFile3D->WriteXdmfSolFile3DAddField(datafieldname,  (l[i].what-1), resultorder, trans);
+    }
+  XdmfSolFile3D->WriteXdmfSolFile3DFinalize();
+  delete XdmfSolFile3D;
+
+  //write hdf5 sol file
+  WriteHdf5 * Hdf5SolFile3D = new WriteHdf5(ffname->c_str(),nt,nv);
+  Hdf5SolFile3D->WriteHdf5SolFile3DInit();
+
+  solnbfloat=0;
+
+  for (size_t ii=0;ii<l.size();ii++)
+    {
+      datafieldname= GetAny<string *>( (*(l[ii].lename))(stack) );
+      trans=l[ii].nbfloat;
+      
+      if(resultorder==0)
+	{
+	  // Tetrahedra
+	  // ordre 0
+	  float  *tab_vfield;
+	  tab_vfield = new float[nt * trans];
+	  memset(tab_vfield, 0, sizeof(float) * nt * trans);
+	  solnbfloat=l[ii].nbfloat;
+	  
+	  nbsol = nt;
+	  KN<double> valsol(solnbfloat*nbsol);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R3 Cdg_hat = R3(1./4.,1./4.,1./4.);  
+	  //boucle sur les tetrahedres
+	  for (int it=0;it<nt;it++)
+	    {
+	      int h=0;
+	      const Tet & K(Th.elements[it]);
+	      mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	      //boucle sur chaque champ des tetrahedres
+	      for(size_t i=0;i<l.size();i++)
+		{
+		  //boucle sur les valeurs de chaque champ des tetrahedres
+		  for(size_t j=0;j<(unsigned int)l[ii].nbfloat;j++)
+		    {
+		      valsol[it*solnbfloat+h] = l[ii].eval(j,stack);
+		      h=h+1;
+		    }
+		}
+	      assert(solnbfloat==h);
+	    }
+	  //creation du tableau de valeur des champs par element
+	  for(int i=0; i<nt; i++)
+	    {
+	      for(int h=0; h<solnbfloat; h++)
+		{
+		  tab_vfield[i*trans+h]=valsol[i*solnbfloat+h];
+		}
+	    }
+	  Hdf5SolFile3D->WriteHdf5SolFile3DAddField(datafieldname, resultorder, trans, (l[ii].what-1),tab_vfield);
+	  delete [] tab_vfield;
+	}
+      if(resultorder==1)
+	{
+	  //ordre 1
+	  float *tab_vfield;
+	  tab_vfield = new float[nv * trans];
+	  memset(tab_vfield, 0, sizeof(float) * nv * trans);
+	  solnbfloat=l[ii].nbfloat;
+	  nbsol = nv;  
+	  KN<double> valsol(solnbfloat*nbsol);
+	  KN<int> takemesh(nbsol);
+	  MeshPoint *mp3(MeshPointStack(stack));
+	  //R3 Cdg_hat = R3(1./4.,1./4.,1./4.);
+	  takemesh=0;
+
+	  //boucle sur les tetrahedres
+	  for (int it=0;it<nt;it++)
+	    {
+	      //boucle sur les 4 noeuds du tetrahedre
+	      for(int iv=0;iv<4;iv++)
+		{
+		  int i=Th(it,iv);
+		  if(takemesh[i]==0)
+		    {
+		      mp3->setP(&Th,it,iv);
+		      int h=0;
+		      
+		      for(size_t j=0;j<(unsigned int)l[ii].nbfloat;j++)
+			{
+			  valsol[i*solnbfloat+h] = l[ii].eval(j,stack);
+			  h=h+1;
+			}
+		      assert(solnbfloat==h);
+		      takemesh[i] = takemesh[i]+1;
+		    }
+		}
+	    }
+	  
+	  for(int i=0; i<nv; i++)
+	    {
+	      for(int h=0; h<solnbfloat; h++)
+		{
+		  tab_vfield[i*trans+h]=valsol[i*solnbfloat+h];
+		}
+	    }
+	  if(verbosity>9)
+	    {
+	      for (int m=0;m<(solnbfloat*nbsol);m++) 
+		cout << "valsol[m] hdf5 solution : "<< valsol[m] << " for lii : " << ii << endl;
+	    }
+	  Hdf5SolFile3D->WriteHdf5SolFile3DAddField(datafieldname, resultorder, trans, (l[ii].what-1),tab_vfield);
+	  delete [] tab_vfield;
+	}
+    }
+  Hdf5SolFile3D->WriteHdf5SolFile3DFinalize();
+  delete Hdf5SolFile3D;
+  return longdefault;
+}
+
+
+/*  class Init { public:
+    Init();
+};
+
+$1 */
+
+static void Load_Init(){  
+
+  cout << " " << endl;
+  cout << " ---------------------- " << endl;  
+
+  typedef Mesh *pmesh;
+  typedef Mesh3 *pmesh3;
+
+  if (verbosity>2) cout << " load:popen.cpp  " << endl;
+  
+  // 2D
+  Global.Add("savehdf5sol","(",new OneOperatorCode<datasolHDF5Mesh2_Op> );
+  
+  // 3D
+  Global.Add("savehdf5sol","(",new OneOperatorCode< datasolHDF5Mesh3_Op<v_fes3> >);
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/iovtk.cpp b/examples++-load/iovtk.cpp
new file mode 100644
index 0000000..dde51d9
--- /dev/null
+++ b/examples++-load/iovtk.cpp
@@ -0,0 +1,4036 @@
+// ORIG-DATE:   September 2009
+// -*- Mode : c++ -*%
+//
+// SUMMARY  : READ/WRITE MESH AND SOLUTION IN FORMAT VTK    
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the #License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+//  FH   July 2009
+//   comment all
+//       Th3_t->BuildBound();
+//       Th3_t->BuildAdj();
+//       Th3_t->Buildbnormalv();  
+//       Th3_t->BuildjElementConteningVertex();
+//   is now in the constructor of Mesh3 to be consistante. 
+//  FH  nev 2009
+//  correct  gestion of nameofuser    variable
+//  JM :: VTU extension file
+#include  <iostream>
+#include  <cfloat>
+#include <cmath>
+#include <complex>
+using namespace std;
+
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+using namespace std;  
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include "fem.hpp"
+
+
+#include "FESpacen.hpp" 
+#include "FESpace.hpp" 
+
+#include "MatriceCreuse_tpl.hpp"
+#include "MeshPoint.hpp"
+#include "Operator.hpp" 
+#include "lex.hpp"
+
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+//#include "LayerMesh.hpp"
+//#include "TransfoMesh_v2.hpp"
+#include "msh3.hpp"
+//#include "GQuadTree.hpp"
+//#include "lex.hpp"
+#include <set>
+#include <vector>
+#include <list>
+#include <fstream>
+
+using namespace Fem2D;
+
+static const char* EncodeB64_LoopByte ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ ";
+
+static const char* EncodeB64_Mul4Byte ="AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999++++//// ";
+
+// =====================
+// Test for BigEndian
+// =====================
+bool isBigEndian() { 
+ 
+  const int i=1;
+  char *c=(char *)&i;
+  if (c[sizeof(int)-1]==0) return false;
+  else return true;
+}
+
+
+void encodeB64_3Bytes(unsigned char *in3Bytes, unsigned char *out4Bytes) {
+   if (in3Bytes==NULL || out4Bytes==NULL) return;
+   out4Bytes[0]=EncodeB64_Mul4Byte[in3Bytes[0]];
+   out4Bytes[1]=EncodeB64_LoopByte[((in3Bytes[0]&0x03)<<4)+
+                                 ((in3Bytes[1]&0xf0)>>4)];
+   out4Bytes[2]=EncodeB64_LoopByte[((in3Bytes[1]&0x0f)<<2)+
+                                 ((in3Bytes[2]&0xc0)>>6)];
+   out4Bytes[3]=EncodeB64_LoopByte[in3Bytes[2]];
+}
+
+// ===========================
+//                                   
+// ===========================
+int encodeB64(int n, unsigned char *inBytes, unsigned char *outBytes) {
+  if (inBytes==NULL || outBytes==NULL || n<=0) return 0;
+  int m=n-(n%3);
+  int ii, jj;
+  jj=0;
+  for ( ii=0; ii<m; ii+=3 ){  
+    encodeB64_3Bytes(inBytes+ii,outBytes+jj);
+    jj=jj+4;
+  }
+  if (m!=n) {
+   unsigned char lastBytes[3] = {0,0,0};
+   // give last (n-m) chars
+   lastBytes[0]=inBytes[ii];
+   if((n-m)==2) lastBytes[1]=inBytes[ii+1];
+   // encoding chars
+   encodeB64_3Bytes(lastBytes,outBytes+jj);
+   // definition of bytes which is not encoding 
+   outBytes[jj+3]='=';
+   if ((n-m)==1) outBytes[jj+2]='=';
+   jj=jj+4;
+  }
+  return jj;
+}
+
+int runEncodeB64(int n, unsigned char *inBytes, unsigned char *outBytes) {
+  static int nbcached=0;
+  static unsigned char charCache[3];
+  
+  int l=0;
+  
+  int nn=n;
+  int nbcachedInBytes=0;
+
+  if( n == 0 ){ 
+    // no bytes are given :: the bytes cached is encoding 
+    if (nbcached>0){
+       l=encodeB64(nbcached,charCache,outBytes);
+       nbcached=0;
+    } 
+  }
+  else{
+    // bytes are given :: 
+    if (nbcached>0) {
+      // give chars to the Cache 
+      if (nn>0) { 
+	charCache[nbcached++]=inBytes[nbcachedInBytes];
+	nbcachedInBytes++;
+	nn--; 
+      }
+      if(nbcached<3 && nn>0) { 
+	charCache[nbcached++]=inBytes[nbcachedInBytes];
+	nbcachedInBytes++;    
+	nn--; 
+      }
+      
+      if(nbcached==3) {
+	// the cache is filled :: encode bytes
+	l=encodeB64(nbcached,charCache,outBytes);
+	outBytes+=l;
+	nbcached=0;
+      }
+    }
+    if(nn==0) return l; 
+    
+    unsigned char *newInBytes  = &inBytes[nbcachedInBytes];
+    //unsigned char *newOutBytes = &outBytes[l];
+    int m=nn-nn%3;
+    if( nn==m) {
+      l+=encodeB64(nn,newInBytes,outBytes);
+      return l;
+    }
+    // cache left overs
+    charCache[nbcached++]=newInBytes[m];
+    if (m+1<nn) charCache[nbcached++]=newInBytes[m+1];
+    l+=encodeB64(m,newInBytes,outBytes);
+  }
+  return l;
+}
+
+char * newcopy(const char * s)
+{
+  char *r(new char  [strlen(s)+1]);
+  strcpy(r, s);
+  return r;
+}
+
+char * newcopy(const string * s)
+{
+  char *r(new char [s->size()+1]);
+  strcpy(r, s->c_str() );
+  return r;
+}
+
+// Tables of element type of VTK considered in Freefem++
+static const int nvElemVTK[25] = {  1, 0, 2, 0, 3, 
+				    0, 0, 0, 0, 4, 
+				    0, 0, 0, 0, 0, 
+				    0, 0, 0, 0, 0, 
+				    0, 0, 0, 0, 0 };   
+
+// we considerer only vertex, edges, triangles and tetrahedrons in Freefem++
+//  1  :: Vertex Corner
+//  3  :: Edge/line
+//  5  :: triangles
+// 10  :: tetrahedrons
+
+enum FFppCells{VTK_EDGE=3, VTK_TRI=5, VTK_TET=10};
+
+static const int NbColorTable=30;
+// Table of colors for Labels of elements :: RGB
+static const float ColorTable[30][3] = {  
+  {1.0,0.0,0.0},  /* red    */
+  {1.0,1.0,0.0},  /* yellow */
+  {1.0,0.0,1.0},  /* ????   */ 
+  {0.0,1.0,0.0},  /* green  */ 
+  {0.0,1.0,1.0},  /* cyan   */ 
+  {0.0,0.0,1.0},  /* blue   */ 
+  {1.0,  0.5, 0.0},  /* orange */
+  {0.5,  0.0, 1.0},  /* violet */ 
+  {1.0,  0.0, 0.5},  /* ???  */
+  {0.5,  1.0, 0.0},  /* ???  */
+  {0.0,  1.0, 0.5},  /* ???  */
+  {0.0,  0.5, 1.0},  /* ???  */
+  {1.0,  0.5, 0.5},  /*  ???    */
+  {1.0,  1.0, 0.5},  /*  ???    */
+  {1.0,  0.5, 1.0},  /*  ???    */ 
+  {0.5,  1.0, 0.5},  /*  ???    */ 
+  {0.5,  1.0, 1.0},  /*  ???   */ 
+  {0.5,  0.5, 1.0},  /*  ???   */ 
+  {0.4,  0.0, 0.0},  /* dark blue    */
+  {0.4,  0.4, 0.0},  /* dark yellow */
+  {0.4,  0.0, 0.4},  /* dark ????   */ 
+  {0.0,  0.4, 0.0},  /* dark green  */ 
+  {0.0,  0.4, 0.4},  /* dark cyan   */ 
+  {0.0,  0.0, 0.4},  /* dark blue   */
+  {0.8,  0.0, 0.0},  /*  ???    */
+  {0.8,  0.8, 0.0},  /*  ???    */
+  {0.8,  0.0, 0.8},  /*  ???    */ 
+  {0.0,  0.8, 0.0},  /*  ???    */ 
+  {0.0,  0.8, 0.8},  /*  ???    */ 
+  {0.0,  0.0, 0.8},  /*  ???    */
+};  // a voir F.Hecht
+
+void SwapBytes(char *array, int size, int n)
+  {
+    char *x = new char[size];
+    for(int i = 0; i < n; i++) {
+      char *a = &array[i * size];
+      memcpy(x, a, size);
+      for(int c = 0; c < size; c++)
+        a[size - 1 - c] = x[c];
+    }
+    delete [] x;
+  }
+
+
+//==============================================
+// Fichier Format .vtu
+//==============================================
+// general functions
+
+void VTU_BEGIN( FILE *fp ){ 
+  string version="1.0";
+  fprintf(fp,"<?xml version=\"%s\"?>\n",version.c_str());
+}
+
+void VTU_VTKFILE( FILE *fp, bool bigEndian){ 
+  string type("UnstructuredGrid");
+  string byte_big("BigEndian");
+  string byte_little("LittleEndian");
+  string version("0.1");
+
+  fprintf(fp,"<VTKFile type=\"%s\"",type.c_str());
+  fprintf(fp," version=\"%s\"",version.c_str()); 
+  if(bigEndian)
+    fprintf(fp," byte_order=\"%s\">\n",byte_big.c_str());
+  else
+    fprintf(fp," byte_order=\"%s\">\n", byte_little.c_str()); 
+
+  //fprintf(fp,"<%s>\n",type.c_str());
+}
+
+void VTU_PIECE( FILE *fp, const int &nv, const int &nc){ 
+  fprintf(fp,"<Piece NumberOfPoints=\"%d\" NumberOfCells=\"%d\">\n",nv,nc);
+}
+
+
+void VTU_DATA_ARRAY( FILE *fp, const string &type,const string &name,bool binary){ 
+  fprintf(fp,"<DataArray type=\"%s\"",type.c_str());
+  fprintf(fp," Name=\"%s\"",name.c_str());
+ 
+  if(binary) fprintf(fp," format=\"binary\"");  
+  else fprintf(fp," format=\"ascii\"");
+  fprintf(fp,">\n");
+}
+
+void VTU_DATA_ARRAY( FILE *fp, const string &type,const string &name,const long &noc,bool binary){ 
+  fprintf(fp,"<DataArray type=\"%s\"",type.c_str());
+  fprintf(fp," Name=\"%s\"",name.c_str());
+  fprintf(fp," NumberOfComponents=\"%ld\"",noc);
+  
+  if(binary) fprintf(fp," format=\"binary\"");
+  else fprintf(fp," format=\"ascii\"");
+
+  fprintf(fp,">\n");
+}
+
+void BEGINTYPE_VTU( FILE *fp, string begintype){ 
+  fprintf(fp,"<%s>\n",begintype.c_str());
+}
+
+void ENDTYPE_VTU( FILE *fp , string endtype){ 
+  fprintf(fp,"</%s>\n",endtype.c_str());
+}
+
+
+void VTU_WRITE_MESH( FILE *fp, const Mesh &Th, bool binary, int datasize, bool surface, bool bigEndian){
+  int nc,nv,nconnex;
+  if(surface) nc=Th.nt+Th.neb;
+  else nc=Th.nt;
+
+  if(surface) nconnex=3*Th.nt+2*Th.neb;
+  else nconnex=3*Th.nt;
+
+  unsigned char ElementChars[256];
+  fprintf(fp,"<?xml version=\"1.0\"?>\n");
+  fprintf(fp,"<VTKFile type=\"UnstructuredGrid\" ");
+  if (isBigEndian())
+    fprintf(fp,"byte_order=\"BigEndian\">\n"); 
+  else
+    fprintf(fp," byte_order=\"LittleEndian\">\n");  
+  
+  fprintf(fp,"<UnstructuredGrid>\n");
+  fprintf(fp,"<Piece NumberOfPoints=\"%d\" NumberOfCells=\" %d\">\n",Th.nv,nc);
+  
+  fprintf(fp,"<Points>\n");
+  fprintf(fp,"<DataArray type=\"Float32\" NumberOfComponents=\"3\"");
+  
+  // A definir coord 
+
+  float *coord= new float[3*Th.nv];
+  for(int ii=0; ii<Th.nv; ii++){
+    coord[3*ii] = Th.vertices[ii].x; 
+    coord[3*ii+1] = Th.vertices[ii].y;
+    coord[3*ii+2] = 0;//Th.vertices[ii].z;
+  }
+
+  if( binary ) {
+    fprintf(fp," format=\"binary\">\n	");
+    {
+      unsigned nbytes= 3*Th.nv*sizeof(float);
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      for (long i=0; i<Th.nv; i++){
+	l=runEncodeB64(3*sizeof(float),(unsigned char *)(coord+3*i),ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+    }
+  } 
+  else {
+    fprintf(fp," format=\"ascii\">\n");
+    for (long i=0; i<Th.nv; i++){
+      fprintf(fp,"%f %f %f ",coord[i*3+0],coord[i*3+1],coord[i*3+2]); 
+    }  
+  }  
+  fprintf(fp,"\n</DataArray>\n"); 
+  fprintf(fp,"</Points>\n");
+  fprintf(fp,"<Cells>\n"); 
+
+  delete [] coord;
+  long *ien= new long[nconnex];
+
+  for (long it=0; it<Th.nt; it++){ 
+    const Mesh::Triangle &K(Th.t(it) );
+    for(int ii=0; ii<3; ii++){
+      ien[3*it+ii] = Th.operator()(K[ii]);
+    } 			    
+  }
+  if(surface){     
+    for(long ibe=0; ibe<Th.neb; ibe++){
+      const Mesh::BorderElement &K( Th.be(ibe) );
+      for(int ii=0; ii<2; ii++){
+	ien[3*Th.nt+2*ibe+ii] = Th.operator()(K[ii]);
+      } 	
+    }
+  }
+  fprintf(fp,"<DataArray type=\"Int32\" Name=\"connectivity\" ");
+
+  // need ien vector
+  if( binary ){
+    fprintf(fp,"format=\"binary\">\n	");
+    unsigned nbytes= nconnex*sizeof(int);
+    int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+    ElementChars[l]=0;
+    fwrite(&ElementChars,l,1,fp);
+    for (long i=0; i<Th.nt; i++){       
+      l=runEncodeB64(sizeof(int),(unsigned char *)(ien+i*3),ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      
+      l=runEncodeB64(sizeof(int),(unsigned char *)(ien+i*3+1),ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      
+      l=runEncodeB64(sizeof(int),(unsigned char *)(ien+i*3+2),ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+    }
+    if(surface){
+      for (long i=0; i<Th.neb; i++){ 
+	l=runEncodeB64(sizeof(int),(unsigned char *)(ien+3*Th.nt+i*2),ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      
+	l=runEncodeB64(sizeof(int),(unsigned char *)(ien+3*Th.nt+i*2+1),ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+    }
+    // flush buffer
+    l=runEncodeB64(0,NULL,ElementChars);
+    ElementChars[l]=0;
+    fwrite(&ElementChars,l,1,fp);
+  }
+  else{
+    fprintf(fp," format=\"ascii\">\n");   
+    for (long i=0; i<Th.nt; i++){
+      fprintf(fp,"%ld %ld %ld ",ien[i*3+0],ien[i*3+1],ien[i*3+2]); 
+    }  
+    if(surface){
+      for (long i=0; i<Th.neb; i++){
+	fprintf(fp,"%ld %ld ",ien[i*2+3*Th.nt],ien[i*2+3*Th.nt+1]); 
+      }  
+    }
+  }
+  fprintf(fp,"\n</DataArray>\n");
+  delete [] ien;
+
+  fprintf(fp,"<DataArray type=\"Int32\" Name=\"offsets\" ");  
+  if(binary){
+    fprintf(fp,"format=\"binary\">\n	");    
+    {
+      unsigned nbytes= nc*sizeof(int);
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      long nelem=3;
+      for (long i=nelem; i <= nelem*Th.nt; i+=nelem){   
+	l=runEncodeB64(sizeof(int),(unsigned char *)&i,ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+      if(surface){
+	nelem=2;
+	for (long i=nelem+3*Th.nt; i <= nelem*Th.neb+3*Th.nt; i+=nelem){   
+	  l=runEncodeB64(sizeof(int),(unsigned char *)&i,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);      
+    }
+  }
+  else{
+    fprintf(fp,"format=\"ascii\" >\n");
+    long nelem=3;
+    for (long i=nelem; i <= nelem*Th.nt; i+=nelem){   
+      fprintf(fp,"%ld ",i);
+    }
+    if(surface){
+      nelem=2;
+      for (long i=nelem; i <= nelem*Th.neb; i+=nelem){
+	fprintf(fp,"%ld ",i+3*Th.nt);
+      }
+    }
+  }
+  fprintf(fp,"\n</DataArray>\n");
+  
+  fprintf(fp,"<DataArray type=\"UInt8\" Name=\"types\" "); 
+  if(binary){
+    fprintf(fp,"format=\"binary\" >\n	");
+    {
+      unsigned nbytes= nc;
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      for (long i=0; i<Th.nt; i++){   
+	unsigned char types= 5;
+	l=runEncodeB64(1,&types,ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+      if(surface){
+	for (long i=0; i<Th.neb; i++){   
+	  unsigned char types= 3;
+	  l=runEncodeB64(1,&types,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+    }
+  }
+  else{
+    fprintf(fp,"format=\"ascii\" >\n");
+    for (long i=0; i<Th.nt; i++){   
+      unsigned int types= 5;
+      fprintf(fp,"%d ",types);
+    }
+    if(surface){
+      for (long i=0; i<Th.neb; i++){   
+	unsigned int types= 3;
+	fprintf(fp,"%d ",types);
+      }
+    }
+  }
+  fprintf(fp,"\n</DataArray>\n");
+  fprintf(fp,"</Cells>\n");
+  //fprintf(fp,"</Piece>\n"); 
+  //fprintf(fp,"</UnstructuredGrid>\n");
+  //fprintf(fp,"</VTKFile>\n");
+}
+
+
+void VTU_WRITE_MESH( FILE *fp, const Mesh3 &Th, bool binary, int datasize, bool surface, bool bigEndian){
+  int nc,nv,nconnex;
+  if(surface) nc=Th.nt+Th.nbe;
+  else nc=Th.nt;
+
+  if(surface) nconnex=4*Th.nt+3*Th.nbe;
+  else nconnex=4*Th.nt;
+
+  unsigned char ElementChars[256];
+  fprintf(fp,"<?xml version=\"1.0\"?>\n");
+  fprintf(fp,"<VTKFile type=\"UnstructuredGrid\" ");
+  if (isBigEndian())
+    fprintf(fp,"byte_order=\"BigEndian\">\n"); 
+  else
+    fprintf(fp," byte_order=\"LittleEndian\">\n");  
+  
+  fprintf(fp,"<UnstructuredGrid>\n");
+  fprintf(fp,"<Piece NumberOfPoints=\"%d\" NumberOfCells=\" %d\">\n",Th.nv,nc);
+  
+  fprintf(fp,"<Points>\n");
+  fprintf(fp,"<DataArray type=\"Float32\" NumberOfComponents=\"3\"");
+  
+  // A definir coord 
+
+  float *coord= new float[3*Th.nv];
+  for(int ii=0; ii<Th.nv; ii++){
+    coord[3*ii] = Th.vertices[ii].x; 
+    coord[3*ii+1] = Th.vertices[ii].y;
+    coord[3*ii+2] = Th.vertices[ii].z;
+  }
+
+  if( binary ) {
+    fprintf(fp," format=\"binary\">\n	");
+    {
+      unsigned nbytes= 3*Th.nv*sizeof(float);
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      for (long i=0; i<Th.nv; i++){
+	l=runEncodeB64(3*sizeof(float),(unsigned char *)(coord+3*i),ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+    }
+  } 
+  else {
+    fprintf(fp," format=\"ascii\">\n");
+    for (long i=0; i<Th.nv; i++){
+      fprintf(fp,"%f %f %f ",coord[i*3+0],coord[i*3+1],coord[i*3+2]); 
+    }  
+  }  
+  fprintf(fp,"\n</DataArray>\n"); 
+  fprintf(fp,"</Points>\n");
+  fprintf(fp,"<Cells>\n"); 
+
+  delete [] coord;
+  long *ien= new long[nconnex];
+
+  for (long it=0; it<Th.nt; it++){ 
+    const Tet &K(Th.elements[it]);
+    for(int ii=0; ii<4; ii++){
+      ien[4*it+ii] = Th.operator()(K[ii]);
+    } 			    
+  }
+  if(surface){     
+    for(long ibe=0; ibe<Th.nbe; ibe++){
+      const Triangle3 &K( Th.be(ibe) );
+      for(int ii=0; ii<3; ii++){
+	ien[4*Th.nt+3*ibe+ii] = Th.operator()(K[ii]);
+      } 	
+    }
+  }
+  fprintf(fp,"<DataArray type=\"Int32\" Name=\"connectivity\" ");
+
+  // need ien vector
+  if( binary ){
+    fprintf(fp,"format=\"binary\">\n	");
+    unsigned nbytes= nconnex*sizeof(int);
+    int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+    ElementChars[l]=0;
+    fwrite(&ElementChars,l,1,fp);
+    for (long i=0; i<Th.nt; i++){ 
+      long nelem=4;
+      l=runEncodeB64(sizeof(int),(unsigned char *)(ien+i*nelem),ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      
+      l=runEncodeB64(sizeof(int),(unsigned char *)(ien+i*nelem+1),ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      
+      l=runEncodeB64(sizeof(int),(unsigned char *)(ien+i*nelem+2),ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      
+      l=runEncodeB64(sizeof(int),(unsigned char *)(ien+i*nelem+3),ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+    }
+    if(surface){
+      for (long i=0; i<Th.nbe; i++){ 
+	long nelem=3;
+	l=runEncodeB64(sizeof(int),(unsigned char *)(ien+4*Th.nt+i*nelem),ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      
+	l=runEncodeB64(sizeof(int),(unsigned char *)(ien+4*Th.nt+i*nelem+1),ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+	
+	l=runEncodeB64(sizeof(int),(unsigned char *)(ien+4*Th.nt+i*nelem+2),ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+    }
+    // flush buffer
+    l=runEncodeB64(0,NULL,ElementChars);
+    ElementChars[l]=0;
+    fwrite(&ElementChars,l,1,fp);
+  }
+  else{
+    fprintf(fp," format=\"ascii\">\n");   
+    for (long i=0; i<Th.nt; i++){
+      fprintf(fp,"%ld %ld %ld %ld ",ien[i*4+0],ien[i*4+1],ien[i*4+2],ien[i*4+3]);  // J.Morice 01/11 
+    }  
+    if(surface){
+      for (long i=0; i<Th.nbe; i++){
+	fprintf(fp,"%ld %ld %ld ",ien[i*3+4*Th.nt],ien[i*3+4*Th.nt+1],ien[i*3+4*Th.nt+2]); 
+      }  
+    }
+  }
+  fprintf(fp,"\n</DataArray>\n");
+  delete [] ien;
+
+  fprintf(fp,"<DataArray type=\"Int32\" Name=\"offsets\" ");  
+  if(binary){
+    fprintf(fp,"format=\"binary\">\n	");    
+    {
+      unsigned nbytes= nc*sizeof(int);
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      long nelem=4;
+      for (long i=nelem; i <= nelem*Th.nt; i+=nelem){   
+	l=runEncodeB64(sizeof(int),(unsigned char *)&i,ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+      if(surface){
+	nelem=3;
+	for (long i=nelem+4*Th.nt; i <= nelem*Th.nbe+4*Th.nt; i+=nelem){   
+	  l=runEncodeB64(sizeof(int),(unsigned char *)&i,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);      
+    }
+  }
+  else{
+    fprintf(fp,"format=\"ascii\" >\n");
+    long nelem=4;
+    for (long i=nelem; i <= nelem*Th.nt; i+=nelem){   
+      fprintf(fp,"%ld ",i);
+    }
+    if(surface){
+      nelem=3;
+      for (long i=nelem+4*Th.nt; i <= nelem*Th.nbe+4*Th.nt; i+=nelem){
+	fprintf(fp,"%ld ",i);
+      }
+    }
+  }
+  fprintf(fp,"\n</DataArray>\n");
+  
+  fprintf(fp,"<DataArray type=\"UInt8\" Name=\"types\" "); 
+  if(binary){
+    fprintf(fp,"format=\"binary\" >\n	");
+    {
+      unsigned nbytes= nc;
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      for (long i=0; i<Th.nt; i++){   
+	unsigned char types= 10;
+	l=runEncodeB64(1,&types,ElementChars);
+	ElementChars[l]=0;
+	fwrite(&ElementChars,l,1,fp);
+      }
+      if(surface){
+	for (long i=0; i<Th.nbe; i++){   
+	  unsigned char types= 5;
+	  l=runEncodeB64(1,&types,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+    }
+  }
+  else{
+    fprintf(fp,"format=\"ascii\" >\n");
+    for (long i=0; i<Th.nt; i++){   
+      unsigned int types= 10;
+      fprintf(fp,"%d ",types);
+    }
+    if(surface){
+      for (long i=0; i<Th.nbe; i++){   
+	unsigned int types= 5;
+	fprintf(fp,"%d ",types);
+      }
+    }
+  }
+  fprintf(fp,"\n</DataArray>\n");
+  fprintf(fp,"</Cells>\n");
+  //fprintf(fp,"</Piece>\n"); 
+  //fprintf(fp,"</UnstructuredGrid>\n");
+  //fprintf(fp,"</VTKFile>\n");
+}
+
+ 
+/* 
+void VTU_WRITE_MESH( FILE *fp, const Mesh3 &Th, bool binary, int datasize, bool surface, bool bigEndian){
+  int nc,nv;
+  if(surface) nc=Th.nt+Th.nbe;
+  else nc=Th.nt;
+  // Mesh
+  // Vertex coordinates
+  BEGINTYPE_VTU( fp, "Points");
+
+  if(datasize == sizeof(float)){    
+    VTU_DATA_ARRAY( fp, "Float32", "Points", 3 ,binary);
+  }
+  else if(datasize == sizeof(double)) {
+    VTU_DATA_ARRAY( fp, "Float64", "Points", 3 ,binary);
+  }
+
+  // write coordinate of vertices :: the same as extension .vtk
+  if(datasize == sizeof(float)){ 
+    for(unsigned int i = 0; i < Th.nv; i++){
+      const Vertex3 & P = Th.vertices[i];
+      float f[3];
+      f[0]=P.x;
+      f[1]=P.y;
+      f[2]=P.z;  
+      if(binary){
+	if(!bigEndian) SwapBytes((char*)&f, sizeof(float), 3);
+	fwrite(&f, sizeof(float), 3, fp);
+      }
+      else{
+	fprintf(fp,"%f %f %f\n",f[0],f[1],f[2]);
+      }
+    }  
+  }
+  else if(datasize == sizeof(double)){
+    for(unsigned int i = 0; i < Th.nv; i++){
+      const Vertex3 & P = Th.vertices[i];
+      double f[3];
+      f[0]=P.x;
+      f[1]=P.y;
+      f[2]=P.z;  
+      if(binary){
+	if(!bigEndian) SwapBytes((char*)&f, sizeof(double), 3);
+	fwrite(&f, sizeof(double), 3, fp);
+      }
+      else{
+	fprintf(fp,"%lf %lf %lf\n",f[0],f[1],f[2]);
+      }
+    }  
+  }
+  if(binary) fprintf(fp,"\n");
+  ENDTYPE_VTU( fp, "DataArray");
+  ENDTYPE_VTU( fp, "Points");
+
+  // Elemenents
+  BEGINTYPE_VTU( fp, "Cells");
+  VTU_DATA_ARRAY( fp, "Int32", "connectivity" , binary); // rgmin=0 ; rgmax=nc-1;
+  // begin :: connectivit� des elements
+  if(binary){
+    int IntType=4;
+    if(verbosity > 1) printf("writting tetrahedre elements \n");
+    for(int it=0; it< Th.nt; it++){    
+      const Tet & K( Th.elements[it] );
+      int iv[IntType];
+      
+      for(int ii=0; ii<IntType; ii++){
+	iv[ii] = Th.operator()(K[ii]);
+      }
+      
+      if(!bigEndian) SwapBytes((char*)&iv, sizeof(unsigned int), IntType);
+      fwrite(&iv, sizeof(unsigned int), IntType, fp);
+    }
+    if(surface){
+      if(verbosity > 1) printf("writting border elements \n");
+      IntType=3;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	const Triangle3 &K( Th.be(ibe) );
+      
+	int iv[IntType];    
+	for(int ii=0; ii<IntType; ii++){
+	  iv[ii] = Th.operator()(K[ii]);
+	}
+	 
+	if(!bigEndian) SwapBytes((char*)&iv, sizeof(unsigned int), IntType);
+	fwrite(&iv, sizeof(unsigned int), IntType, fp);
+      }
+    }
+  }
+  else{
+    int IntType=4;
+    if(verbosity > 1) printf("writting tetrahedrons elements \n");
+    for(int it=0; it< Th.nt; it++){
+      const Tet &K( Th.elements[it] );
+
+      int iv[IntType];         
+      for(int ii=0; ii<IntType; ii++){
+	iv[ii] = Th.operator()(K[ii]);
+      }
+      fprintf(fp,"%d %d %d %d\n", iv[0],iv[1],iv[2],iv[3]);
+    }
+    if(surface){
+      if(verbosity > 1) printf("writting border elements \n");
+      IntType=3;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	const Triangle3 &K( Th.be(ibe) );
+	
+	int iv[IntType];    
+	for(int ii=0; ii<IntType; ii++){
+	  iv[ii] = Th.operator()(K[ii]);
+	}
+	
+	fprintf(fp,"%d %d %d\n",iv[0],iv[1],iv[2]);
+      }
+    }
+  }
+  if(binary) fprintf(fp, "\n");
+  // end :: connectivit� des elements
+  ENDTYPE_VTU( fp, "DataArray");
+  
+  VTU_DATA_ARRAY( fp, "Int32", "offsets" , binary); // rgmin=; rgmax=;
+  if(binary){
+    int offsets=0;    
+    int offcell=4;
+    for(int it=0; it< Th.nt; it++){
+      offsets+=offcell;
+      if(!bigEndian) SwapBytes((char*)&offsets, sizeof(unsigned int), 1);
+      fwrite(&offsets, sizeof(unsigned int), 1, fp);
+    }
+    if(surface){   
+      offcell=3;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	offsets+=offcell;
+	if(!bigEndian) SwapBytes((char*)&offsets, sizeof(unsigned int), 1);
+	fwrite(&offsets, sizeof(unsigned int), 1, fp);	
+      }
+    }
+  }
+  else{
+    int offsets=0;
+    int offcell=4;
+    for(int it=0; it< Th.nt; it++){   
+      offsets+=offcell;
+      fprintf(fp,"%d ",offsets);
+    }
+    if(surface){ 
+      offcell=3;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	offsets+=offcell;
+	fprintf(fp,"%d ",offsets);
+      }
+    }
+  } 
+  fprintf(fp,"\n");
+  ENDTYPE_VTU( fp, "DataArray");
+
+  VTU_DATA_ARRAY( fp, "UInt8", "types", binary); // rgmin=3; rgmax=5;
+  // type cas 2D
+  if(binary){
+    unsigned int type;    
+    type = VTK_TET;  
+    for(int it=0; it< Th.nt; it++){
+     
+      if(!bigEndian) SwapBytes((char*)&type, sizeof(unsigned int), 1);
+      fwrite(&type, sizeof(unsigned int), 1, fp);
+    }
+    if(surface){
+      type=VTK_TRI;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	 
+	if(!bigEndian) SwapBytes((char*)&type, sizeof(unsigned int), 1);
+	fwrite(&type, sizeof(unsigned int), 1, fp);
+      }
+    }
+  }
+  else{
+    unsigned int type;
+    type= VTK_TET;
+    for(int it=0; it< Th.nt; it++){      
+      fprintf(fp,"%d ",type);
+    }
+    if(surface){
+      type=VTK_TRI;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	fprintf(fp,"%d ",type);
+      }
+    }
+  }
+  fprintf(fp,"\n");
+  // end type cas 3D
+  ENDTYPE_VTU( fp, "DataArray");
+
+  ENDTYPE_VTU( fp, "Cells");
+
+  ENDTYPE_VTU( fp, "Piece");
+  ENDTYPE_VTU( fp, "UnstructuredGrid");
+  ENDTYPE_VTU( fp, "VTKFile");
+}
+*/
+
+// two dimensional case
+
+// LOAD fichier.vtk
+class VTK_LoadMesh_Op : public E_F0mps 
+{
+public:
+  Expression filename;
+  static const int n_name_param = 4; // 
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+public:
+  VTK_LoadMesh_Op(const basicAC_F0 &  args,Expression ffname) 
+    : filename(ffname)
+  {
+    if(verbosity) cout << "Load mesh given by VTK " << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+basicAC_F0::name_and_type VTK_LoadMesh_Op::name_param[]= {
+  {  "reft", &typeid(long)},
+  {  "swap", &typeid(bool)},
+  {  "refe", &typeid(long)},
+  {  "namelabel",&typeid(string)}
+};
+
+
+class  VTK_LoadMesh : public OneOperator { public:  
+    VTK_LoadMesh() : OneOperator(atype<pmesh>(),atype<string *>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new VTK_LoadMesh_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+Mesh * VTK_Load(const string & filename, bool bigEndian)
+// swap = bigEndian or not bigEndian
+{
+  // variable freefem++
+  int nv, nt=0, nbe=0;
+  int nerr=0;
+
+  Mesh::Vertex   *vff;
+  map<int,int> mapnumv;
+
+  // Reading Mesh in vtk formats 
+
+  FILE *fp = fopen(filename.c_str(), "rb");
+  if(!fp){
+    cerr << "Unable to open file " << filename.c_str() << endl;
+    exit(1);
+  }
+
+  char buffer[256], buffer2[256];
+    
+  fgets(buffer, sizeof(buffer), fp); // version line
+  fgets(buffer, sizeof(buffer), fp); // title
+  
+  fscanf(fp, "%s", buffer); // ASCII or BINARY
+  bool binary = false;
+  if(!strncmp(buffer, "BINARY",6)) binary = true;
+    
+  if(fscanf(fp, "%s %s", buffer, buffer2) != 2) { 
+    cerr << "error in reading vtk files" << filename << endl;
+    ExecError("load vtk files");
+  }
+  if(strcmp(buffer, "DATASET") || strcmp(buffer2, "UNSTRUCTURED_GRID")){
+    cout << "VTK reader can only read unstructured datasets" << endl;
+    ExecError("load  vtk files");
+    exit(1);
+  }
+    
+  // read mesh vertices
+  if(fscanf(fp, "%s %d %s\n", buffer, &nv, buffer2) != 3)
+    { cout << "error in reading vtk files" << endl;
+      ExecError("load  vtk files reah vertices");
+      exit(1); }
+  if(strcmp(buffer, "POINTS") || !nv){
+    cerr << "No points in dataset" << endl;
+      ExecError("load  vtk files: No points in dataset");
+    exit(1);
+  }
+  int datasize;
+  if(!strncmp(buffer2, "double",6))
+    datasize = sizeof(double);
+  else if(!strncmp(buffer2, "float",5))
+    datasize = sizeof(float);
+  else {
+    cout <<"VTK reader only accepts float or double datasets" << endl;
+    ExecError("load  vtk files VTK reader only accepts float or double datasets");
+    exit(1);
+  }
+  if(verbosity>1)  
+    cout << "   vtkio: Reading %d points" << nv << endl;
+  vff = new Mesh::Vertex[nv];
+    
+  for(int i = 0 ; i < nv; i++){
+    double xyz[3];
+    if(binary){
+      if(datasize == sizeof(float)){
+	float f[3];
+	if(fread(f, sizeof(float), 3, fp) != 3){ 
+	  ExecError("load  vtk files VTK reader only accepts float or double datasets");
+	  ExecError("error in reading vtk file"); 
+	} 
+	if(!bigEndian) SwapBytes((char*)f, sizeof(float), 3);
+	for(int j = 0; j < 3; j++) xyz[j] = f[j];
+      }
+      else{
+	if(fread(xyz, sizeof(double), 3, fp) != 3) { cout << "error in reading vtk files" << endl; ExecError("error in reading vtk file"); }
+	if(!bigEndian) SwapBytes((char*)xyz, sizeof(double), 3);
+      }
+    }
+    else{
+      if(fscanf(fp, "%lf %lf %lf", &xyz[0], &xyz[1], &xyz[2]) != 3){ cout << "error in reading vtk files" << endl; ExecError("error in reading vtk file"); }
+    }    
+    vff[i].x = xyz[0];
+    vff[i].y = xyz[1];
+    if( abs(xyz[2]) > 1.e-7){
+      cout << "we are plotted a two dimensional mesh: z coordinate must be 0" << endl;
+      ExecError("error in reading vtk file,we are plotted a two dimensional mesh: z coordinate must be 0");
+    }    
+    vff[i].lab = 1;
+  }    
+
+  // read mesh elements
+  int numElements, numElements2, totalNumInt;
+  if(fscanf(fp, "%s %d %d\n", buffer, &numElements, &totalNumInt) != 3){ cout << "error in reading vtk files" << endl; ExecError("error in reading vtk file"); }
+  if(strcmp(buffer, "CELLS") || !numElements){
+    cout << "No cells in dataset" << endl;
+    ExecError("error in reading vtk file");
+  }
+  cout << "Reading cells" << numElements << endl;
+  
+  int *IntCells   = new int[totalNumInt-numElements];
+  int *firstCell  = new int[numElements+1];
+  int *TypeCells   = new int[numElements];
+  int numIntCells = 0;
+  
+  for(unsigned int i = 0; i < numElements; i++){
+    int numVerts, n[100];
+    for(int ii = 0; ii < 100; ii++) n[ii]=-1;
+    if(binary){
+      if( fread(&numVerts, sizeof(int), 1, fp) != 1 ) {
+	cout << "error in reading VTK files " << endl;
+	ExecError("error in reading vtk file");
+	}
+      if( !bigEndian) SwapBytes((char*)&numVerts, sizeof(int), 1);
+      if((int)fread(n, sizeof(int), numVerts, fp) != numVerts){
+	cout << "error in reading VTK files " << endl;
+	ExecError("error in reading vtk file");
+      }
+      if(!bigEndian) SwapBytes((char*)n, sizeof(int), numVerts);
+    }
+    else{
+      if(fscanf(fp, "%d", &numVerts) != 1){
+	cout << "error in reading VTK files " << endl;
+	  ExecError("error in reading vtk file");
+      }
+      for(int j = 0; j < numVerts; j++){
+	if(fscanf(fp, "%d", &n[j]) != 1){
+	  cout << "error in reading VTK files " << endl;
+	  ExecError("error in reading vtk file");
+	}
+      }
+    }
+    firstCell[i] = numIntCells;
+    for(int j = 0; j < numVerts; j++){
+      if(n[j] >= 0 && n[j] < nv){
+	IntCells[numIntCells] = n[j];
+	numIntCells++;
+      }	  
+      else{
+	cout << "Bad vertex index" << endl;
+	ExecError("error in reading vtk file");
+	}
+    }
+  }
+  firstCell[numElements] = totalNumInt-numElements;  
+  
+  if(fscanf(fp, "%s %d\n", buffer, &numElements2) != 2){
+    cout << " Error in reading CELL_TYPES ARGUMENT " << endl;
+    ExecError("error in reading vtk file");
+  }
+  if(strcmp(buffer, "CELL_TYPES") || numElements2 != (int)numElements){
+    cout <<"No or invalid number of cells types" << endl;
+    ExecError("error in reading vtk file");
+  }
+  
+  
+  // 2D
+  
+  for(unsigned int i = 0; i < numElements; i++){
+    int type;
+    if(binary){
+	if(fread(&type, sizeof(int), 1, fp) != 1){
+	  cout <<"bug in readings cell types" << endl;
+	  ExecError("error in reading vtk file");
+	}
+	if(!bigEndian) SwapBytes((char*)&type, sizeof(int), 1);
+    }
+    else{
+      if(fscanf(fp, "%d", &type) != 1){
+	cout <<"bug in readings cell types" << endl;
+	ExecError("error in reading vtk file");
+      }
+    }
+    TypeCells[i] = type;
+    switch(type){
+    case 1:  // Vertex
+      if(nerr++<10 && verbosity )
+           cout << "this type of cell (vertex) is not taking account in Freefem++ " << type <<  endl;
+      break;
+    case 3:  // Edge/line
+      nbe++; // 2D	
+      break;
+    case 5:  // Triangle
+      nt++; // 2D
+      break;   
+    case 10: // Tetrah�dre
+      cout << "We are loading a three dimensional mesh. Three is no tetrahedron." << endl;
+      ExecError("error in reading vtk file");
+      break;  
+    default: 
+      cout << "Error :: This type of cell is not considered in Freefem++ "<< type << endl;
+      ExecError("error in reading vtk file");
+      break;
+      }
+  }  
+  
+  fclose(fp);
+
+    // 2D Versions
+    Mesh::Triangle *tff; 
+    if(nt>0) tff = new Mesh::Triangle[nt];
+    Mesh::Triangle *ttff = tff;
+    
+    Mesh::BorderElement *bff;
+    if(nbe>0) bff= new Mesh::BorderElement[nbe];
+    Mesh::BorderElement *bbff = bff;
+    for(unsigned int i = 0; i < numElements; i++){
+      int type=TypeCells[i];
+      int iv[3];
+      int label=1;
+      switch(type){
+      case 1:  // Vertex
+              
+	if(nerr++<10 && verbosity ) cout << "this type of cell (vertex) is not taking account in Freefem++ " <<  type << " " << endl;
+	break;
+      case 3:  // Edge/line
+	assert( (firstCell[i+1]-firstCell[i]) == 2 );
+	for(int j=firstCell[i]; j<firstCell[i+1]; j++){
+    	  iv[j-firstCell[i]] = IntCells[j];
+	}
+	(bbff++)->set(vff, iv[0], iv[1], label);
+	break;
+      case 5:  // Triangle
+	assert( (firstCell[i+1]-firstCell[i]) == 3 );
+	for(int j=firstCell[i]; j<firstCell[i+1]; j++){
+    	  iv[j-firstCell[i]] = IntCells[j];
+	}
+	(ttff++)->set(vff, iv[0], iv[1], iv[2], label);
+	break;   
+      default: 
+	break;	
+      } 
+    }
+   
+    delete [] IntCells;   
+    delete [] firstCell; 
+    delete [] TypeCells;
+    
+    Mesh *pTh = new Mesh(nv,nt,nbe,vff,tff,bff);
+    return pTh;
+}
+
+AnyType VTK_LoadMesh_Op::operator()(Stack stack)  const 
+{
+ 
+  string * pffname= GetAny<string *>((*filename)(stack));
+  bool swap = false;
+  int reftri = 1;
+  int refedges = 1;
+  if( nargs[0] )  reftri = GetAny<long>((*nargs[0])(stack));
+  if( nargs[1] )  swap = GetAny< bool >((*nargs[1])(stack));
+  if( nargs[2] )  refedges = GetAny<long>((*nargs[2])(stack));
+
+  string *DataLabel;
+  if( nargs[3] ) DataLabel = GetAny<string *>((*nargs[3])(stack));
+
+  Mesh * Th = VTK_Load( *pffname , swap); 
+ 
+  // A faire fonction pour changer le label
+
+  Add2StackOfPtr2FreeRC(stack,Th);
+		
+  return Th;
+}
+
+//==============================================
+// ECRITURE DE FICHIER .vtk
+//==============================================
+
+class VTK_WriteMesh_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  
+  struct Expression2 {
+    string name;
+    long what; // 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 1 scalar, 2 vector (3D), 3 symtensor(3D)
+    Expression e[3];
+    Expression2() {e[0]=0; e[1]=0; e[2]=0;  what=0; nbfloat=0; };
+    Expression &operator[](int i){return e[i];}
+    double eval(int i,Stack stack) const  { 
+      if (e[i]) {
+	return GetAny< double >( (*e[i])(stack) );
+      }
+      else 
+	return 0;
+    }
+
+    void writesolutionP0_float_binary( FILE *fp, const Mesh &Th, Stack stack, bool surface, bool bigEndian) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R2 Cdg_hat = R2(1./3.,1./3.);  
+      
+      for (int it=0;it<Th.nt;it++){
+	const Mesh::Triangle  & K(Th.t(it));
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< nbfloat;j++){
+	  float value = eval(j,stack);
+	  
+	  if(!bigEndian) SwapBytes((char*)&value, sizeof(float), 1);
+	  fwrite(&value, sizeof(float), 1, fp);
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.neb;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Mesh::Triangle  & K(Th.t(it));
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< nbfloat;j++){
+	    float value = eval(j,stack);
+
+	    if(!bigEndian) SwapBytes((char*)&value, sizeof(float), 1);
+	    fwrite(&value, sizeof(float), 1, fp);	    
+	  } 
+	}
+      }
+      fprintf(fp,"\n");
+    }
+
+    void writesolutionP0_float( FILE *fp, const Mesh &Th, Stack stack, bool surface) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R2 Cdg_hat = R2(1./3.,1./3.);  
+      
+      for (int it=0;it<Th.nt;it++){
+	const Mesh::Triangle  & K(Th.t(it));
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< nbfloat;j++){
+	  float value = eval(j,stack);
+	 
+	  fprintf(fp,"%.8e ",value); 
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.neb;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Mesh::Triangle  & K(Th.t(it));
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< nbfloat;j++){
+	    float value = eval(j,stack);
+
+	    fprintf(fp,"%.8e ",value); 	 
+	  } 
+	}
+      }
+      fprintf(fp,"\n");
+    }
+
+    void writesolutionP0_float_XML( FILE *fp, const Mesh &Th, Stack stack, bool surface) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R2 Cdg_hat = R2(1./3.,1./3.);  
+
+      unsigned char ElementChars[256];
+      long nc=Th.nt;
+      if(surface) nc=nc+Th.neb;
+
+      unsigned nbytes= nc*sizeof(float)*(*this).nbfloat;
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+
+      for (int it=0;it<Th.nt;it++){
+	const Mesh::Triangle  & K(Th.t(it));
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< nbfloat;j++){
+	  float value = eval(j,stack);
+	
+	  l=runEncodeB64(sizeof(float),(unsigned char *)&value,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.neb;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Mesh::Triangle  & K(Th.t(it));
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< nbfloat;j++){
+	    float value = eval(j,stack);
+	    
+	    l=runEncodeB64(sizeof(float),(unsigned char *)&value,ElementChars);
+	    ElementChars[l]=0;
+	    fwrite(&ElementChars,l,1,fp);
+	  } 
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      fprintf(fp,"\n");
+    }
+    
+    void writesolutionP0_float( FILE *fp, const Mesh &Th, Stack stack, bool surface, bool binary, bool bigEndian, bool XML=false) const {
+      if(binary){
+	if(!XML){
+	  (*this).writesolutionP0_float_binary( fp, Th, stack, surface, bigEndian); 
+	}
+	else
+	  (*this).writesolutionP0_float_XML( fp, Th, stack, surface );
+      }
+      else 
+	(*this).writesolutionP0_float( fp, Th, stack, surface );
+    }
+
+    void writesolutionP0_double_binary( FILE *fp, const Mesh &Th, Stack stack, bool surface, bool bigEndian) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R2 Cdg_hat = R2(1./3.,1./3.);  
+      
+      for (int it=0;it<Th.nt;it++){
+	const Mesh::Triangle  & K(Th.t(it));
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< (*this).nbfloat;j++){
+	  double value = (*this).eval(j,stack);
+	  
+	  if(!bigEndian) SwapBytes((char*)&value, sizeof(double), 1);
+	  fwrite(&value, sizeof(double), 1, fp);
+	    
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.neb;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Mesh::Triangle  & K(Th.t(it));
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    double value = (*this).eval(j,stack);
+	    
+	    if(!bigEndian) SwapBytes((char*)&value, sizeof(double), 1);
+	    fwrite(&value, sizeof(double), 1, fp);
+	    
+	  } 
+	}
+      }           
+      fprintf(fp,"\n");
+    }
+
+   
+    void writesolutionP0_double( FILE *fp, const Mesh &Th, Stack stack, bool surface) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R2 Cdg_hat = R2(1./3.,1./3.);  
+      unsigned char ElementChars[256];
+
+      for (int it=0;it<Th.nt;it++){
+	const Mesh::Triangle  & K(Th.t(it));
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< (*this).nbfloat;j++){
+	  double value = (*this).eval(j,stack);
+	  
+	  fprintf(fp,"%.16e ",value); 	    	    
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.neb;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Mesh::Triangle  & K(Th.t(it));
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    double value = (*this).eval(j,stack);
+	    fprintf(fp,"%.16e ",value); 	      
+	  } 
+	}
+      }     
+      fprintf(fp,"\n");
+    }
+
+    void writesolutionP0_double_XML( FILE *fp, const Mesh &Th, Stack stack, bool surface) const {      
+      unsigned char ElementChars[256]; 
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R2 Cdg_hat = R2(1./3.,1./3.);  
+      long nc=Th.nt;
+      if(surface) nc=nc+Th.neb;
+
+      unsigned nbytes= nc*sizeof(double)*(*this).nbfloat;
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+
+      for (int it=0;it<Th.nt;it++){
+	const Mesh::Triangle  & K(Th.t(it));
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< (*this).nbfloat;j++){
+	  double value = (*this).eval(j,stack);
+
+	  l=runEncodeB64(sizeof(double),(unsigned char *)&value,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	}
+      }	
+      
+      if( surface ){
+	for (int ibe=0;ibe<Th.neb;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Mesh::Triangle  & K(Th.t(it));
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    double value = (*this).eval(j,stack);
+	    
+	     l=runEncodeB64(sizeof(double),(unsigned char *)&value,ElementChars);
+	     ElementChars[l]=0;
+	     fwrite(&ElementChars,l,1,fp);	     
+	  } 
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+          
+      fprintf(fp,"\n");
+    }
+
+    void writesolutionP0_double( FILE *fp, const Mesh &Th, Stack stack, bool surface, bool binary, bool bigEndian, bool XML=false) const {
+      if(binary){
+	if(!XML){
+	  (*this).writesolutionP0_double_binary( fp, Th, stack, surface, bigEndian); 
+	}
+	else
+	  (*this).writesolutionP0_double_XML( fp, Th, stack, surface );
+      }
+      else 
+	(*this).writesolutionP0_double( fp, Th, stack, surface );
+    }
+
+    void writesolutionP1_float( FILE *fp, const Mesh &Th, Stack stack,bool binary,bool bigEndian,bool XML=false) const {
+      unsigned char ElementChars[256]; 
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      KN<double> valsol(Th.nv*(*this).nbfloat);
+      KN<int> takemesh(Th.nv);
+      takemesh =0;
+      valsol   =0.;
+      for(int it=0;  it<Th.nt; it++){
+	for(int iv=0; iv<3; iv++){
+	   int i=Th(it,iv);
+	   mp3->setP(&Th,it,iv);
+	   
+	   for(int j=0;j<(*this).nbfloat;j++){
+	     valsol[ i*(*this).nbfloat+j ] = valsol[ i*(*this).nbfloat+j ] + (*this).eval(j,stack);	     
+	   }
+	   takemesh[i] = takemesh[i]+1;    
+	 }
+       }
+       
+       if(binary){
+	 if( !XML ){ 
+	   if( !bigEndian){
+	     for (int iv=0;iv<Th.nv;iv++){
+	       for(int j=0;j< (*this).nbfloat;j++){
+		 valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		 float value = valsol[iv*(*this).nbfloat+j];
+	       
+		 SwapBytes((char*)&value, sizeof(float), 1);
+		 fwrite(&value, sizeof(float), 1, fp);	   
+	       }		       
+	     }    
+	   }
+	   else{
+	     for (int iv=0;iv<Th.nv;iv++){
+	       for(int j=0;j< (*this).nbfloat;j++){
+		 valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		 float value = valsol[iv*(*this).nbfloat+j];
+	       
+		 fwrite(&value, sizeof(float), 1, fp);	   
+	       }		       
+	     }    
+	   }
+	 }
+	 else{
+	   long nc=Th.nv;
+	   
+	   unsigned nbytes= nc*sizeof(float)*(*this).nbfloat;
+	   int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+
+	   for (int iv=0;iv<Th.nv;iv++){
+	     for(int j=0;j< (*this).nbfloat;j++){
+	       valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	       float value = valsol[iv*(*this).nbfloat+j];
+	   
+	       l=runEncodeB64(sizeof(float),(unsigned char *)&value,ElementChars);
+	       ElementChars[l]=0;
+	       fwrite(&ElementChars,l,1,fp);
+	     }
+	   }
+	   // flush buffer
+	   l=runEncodeB64(0,NULL,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+	  
+	 }
+       }
+       else{
+	 for (int iv=0;iv<Th.nv;iv++){
+	   for(int j=0;j< (*this).nbfloat;j++){
+	     valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	     float value = valsol[iv*(*this).nbfloat+j];
+	     
+	     fprintf(fp,"%.8e ",value); 
+	   }
+	 }	   
+       }
+       fprintf(fp,"\n");
+       
+    }
+
+  
+
+    void writesolutionP1_double( FILE *fp, const Mesh &Th, Stack stack,bool binary,bool bigEndian, bool XML=false) const {
+      unsigned char ElementChars[256];
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      KN<double> valsol(Th.nv*(*this).nbfloat);
+      KN<int> takemesh(Th.nv);
+      takemesh =0;
+      valsol   =0.;
+      for(int it=0;  it<Th.nt; it++){
+	for(int iv=0; iv<3; iv++){
+	  int i=Th(it,iv);
+	  mp3->setP(&Th,it,iv);
+	  
+	  for(int j=0;j<(*this).nbfloat;j++){
+	    valsol[ i*(*this).nbfloat+j ] = valsol[ i*(*this).nbfloat+j ] + (*this).eval(j,stack);	     
+	  }
+	  takemesh[i] = takemesh[i]+1;    
+	}
+      }
+      
+      if(binary){	
+	if( !XML ){
+	  if( !bigEndian ){
+	    for (int iv=0;iv<Th.nv;iv++){
+	      for(int j=0;j< (*this).nbfloat;j++){
+		valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		double value = valsol[iv*(*this).nbfloat+j];
+		
+		SwapBytes((char*)&value, sizeof(double), 1);
+		fwrite(&value, sizeof(double), 1, fp);
+		
+	      }	   
+	    }
+	  }
+	  else{
+	    for (int iv=0;iv<Th.nv;iv++){
+	      for(int j=0;j< (*this).nbfloat;j++){
+		valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		double value = valsol[iv*(*this).nbfloat+j];
+		
+		fwrite(&value, sizeof(double), 1, fp);
+		
+	      }	   
+	    }
+	  }
+	}
+	else{
+	   long nc=Th.nv;
+	   
+	   unsigned nbytes= nc*sizeof(double)*(*this).nbfloat;
+	   int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+
+	   for (int iv=0;iv<Th.nv;iv++){
+	     for(int j=0;j< (*this).nbfloat;j++){
+	       valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	       double value = valsol[iv*(*this).nbfloat+j];
+	   
+	       l=runEncodeB64(sizeof(double),(unsigned char *)&value,ElementChars);
+	       ElementChars[l]=0;
+	       fwrite(&ElementChars,l,1,fp);
+	     }
+	   }
+	   // flush buffer
+	   l=runEncodeB64(0,NULL,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+	   
+	}
+
+      }
+      else{
+	for (int iv=0;iv<Th.nv;iv++){
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	    double value = valsol[iv*(*this).nbfloat+j];
+	
+	      fprintf(fp,"%.16e ",value); 
+	  
+	  }	   
+	}
+      }
+      fprintf(fp,"\n");
+    }    
+  };
+  vector<Expression2> l;
+  static const int n_name_param = 7;  
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  
+public:
+  VTK_WriteMesh_Op(const basicAC_F0 &  args) : l( args.size()-2 )
+  {
+    int nbofsol;
+    int ddim=2;
+    int stsize=3;
+
+    int sca=0,vec=0,ten=0;
+    
+    string scas("scalaire"); 
+    string vecs("vector"); 
+    string tens("tensor"); 
+
+    if(verbosity) cout << "Write Mesh and Solutions in VTK Formats" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+
+    if (BCastTo<string *>(args[0])) filename = CastTo<string *>(args[0]);
+    if (BCastTo<pmesh>(args[1])) eTh= CastTo<pmesh>(args[1]);
+  
+    nbofsol = l.size();
+    for (size_t i=2;i<args.size();i++){
+      size_t jj=i-2;
+      
+      if ( BCastTo<double>( args[i] ))
+	{
+	  l[jj].what=1;
+	  l[jj].nbfloat=1;
+	  l[jj][0]=to<double>( args[i] );
+	  
+	  char number[16];
+	  sprintf(number,"%li",jj+1);
+	  l[jj].name=scas;
+	  l[jj].name+=number;
+	  sca++;	  
+	}
+      else if ( args[i].left()==atype<E_Array>() )
+	{
+	  const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	  //cout << "taille" << a0->size() << endl;
+	  if (a0->size() != ddim && a0->size() != stsize) 
+	    CompileError("savesol in 2D: vector solution is 2 composant, tensor solution is 3 composant");
+	  
+	  if( a0->size() == ddim){
+	    // vector solution
+	    l[jj].what=2;
+	    l[jj].nbfloat=ddim;
+	   
+	    for(int j=0; j<ddim; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+
+	    char number[16];
+	    sprintf(number,"%li",jj+1);
+	    l[jj].name=vecs;
+	    l[jj].name+=number;
+	    vec++;	  
+	  }
+	  else if( a0->size() == stsize){
+	    // symmetric tensor solution
+	    l[jj].what=3;
+	    l[jj].nbfloat=stsize;
+	    for(int j=0; j<stsize; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	    char number[16];
+	    sprintf(number,"%li",jj+1);
+	    l[jj].name=tens;
+	    l[jj].name+=number;
+	    ten++;	
+	  }
+	  
+	}
+      else {
+	cout << " arg " << i << " " << args[i].left() << endl;
+	CompileError("save solution in 2D in format VTK: Sorry no way to save this kind of data");
+      }
+    }
+    
+  }
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<string *>(), atype<pmesh>(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new VTK_WriteMesh_Op(args);}   
+  AnyType operator()(Stack stack)  const ;
+};
+basicAC_F0::name_and_type VTK_WriteMesh_Op::name_param[]= {
+  {  "dataname", &typeid(string*)},
+  {  "withsurfacemesh", &typeid(bool)},
+  {  "order", &typeid(KN_<long>)},
+  // A rajouter dans le 3D
+  {  "floatmesh", &typeid(bool)},
+  {  "floatsol", &typeid(bool)},
+  {  "bin", &typeid(bool)},
+  {  "swap", &typeid(bool)}
+};
+
+
+
+void VTK_WRITE_MESH( const string &filename, FILE *fp, const Mesh &Th, bool binary, int datasize, bool surface, bool bigEndian){
+     
+  fprintf(fp, "# vtk DataFile Version 2.0\n");
+  fprintf(fp, "%s, Created by Freefem++ \n", filename.c_str());
+  if(binary)
+    fprintf(fp, "BINARY\n");
+  else
+    fprintf(fp, "ASCII\n");
+  fprintf(fp, "DATASET UNSTRUCTURED_GRID\n");
+  // get all the entities in the model
+
+  // write mesh vertices
+  
+  if(datasize == sizeof(float)) 
+    {      
+      fprintf(fp, "POINTS %d float\n", Th.nv);
+      for(unsigned int i = 0; i < Th.nv; i++){
+	const  Mesh::Vertex & P = Th.vertices[i];
+	float f[3];
+	f[0]=P.x;
+	f[1]=P.y;
+	f[2]=0;  // P.z; 3D case
+	if(binary){
+	  if(!bigEndian) SwapBytes((char*)&f, sizeof(float), 3);
+	  fwrite( &f, sizeof(float), 3, fp);
+	}
+      else{
+	fprintf(fp,"%.8g %.8g %.8g\n",P.x,P.y,0.);
+      }
+    }  
+  }
+  else if(datasize == sizeof(double)){
+    fprintf(fp, "POINTS %d double\n", Th.nv);
+    for(unsigned int i = 0; i < Th.nv; i++){
+      const  Mesh::Vertex & P = Th.vertices[i];
+      double f[3];
+      f[0]=P.x;
+      f[1]=P.y;
+      f[2]=0;  // P.z; 3D case
+      if(binary){
+	if(!bigEndian) SwapBytes((char*)&f, sizeof(double), 3);
+	fwrite( (unsigned char*)&f, sizeof(double), 3, fp);
+      }
+      else{
+	fprintf(fp,"%.15lg %.15lg %.15lg\n",f[0],f[1],f[2]);
+      }
+    }  
+  }
+  fprintf(fp,"\n");
+  if(verbosity > 1) printf("writting vertices is finish\n");
+  if(verbosity > 1) printf("writting elements now\n");
+  
+  //================
+  //    CELL 
+  //================
+  // loop over all elements we need to save and count vertices
+  int numElements, totalNumInt;
+  if(surface){
+    numElements = Th.nt+Th.neb; 
+    totalNumInt = Th.nt*3+Th.neb*2+numElements;
+  }
+  else{
+    numElements = Th.nt; 
+    totalNumInt = Th.nt*3+numElements;
+  }
+  if(verbosity > 1) printf("writting cells \n");
+  // print vertex indices in ascii or binary
+  fprintf(fp, "CELLS %d %d\n", numElements, totalNumInt);
+
+  if(binary){
+    int IntType=3;
+    if(verbosity > 1) printf("writting triangle elements \n");
+    for(int it=0; it< Th.nt; it++){
+     
+      const Mesh::Triangle & K( Th.t(it) );
+      int iv[IntType+1];
+      
+      iv[0] = IntType;
+      for(int ii=0; ii<IntType; ii++){
+	iv[ii+1] = Th.operator()(K[ii]);
+      }
+      
+      if(!bigEndian) SwapBytes((char*)&iv, sizeof(int), IntType+1);
+      fwrite(&iv, sizeof(int), IntType+1, fp);
+      
+    }
+    if(surface){
+      if(verbosity > 1) printf("writting edge elements \n");
+      IntType=2;
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	 const Mesh::BorderElement &K( Th.be(ibe) );
+      
+	 int iv[IntType+1];    
+	 iv[0] = IntType;
+	 for(int ii=0; ii<IntType; ii++){
+	   iv[ii+1] = Th.operator()(K[ii]);
+	 }
+	 
+	 if(!bigEndian) SwapBytes((char*)&iv, sizeof(int), IntType+1);
+	 fwrite(&iv, sizeof(int), IntType+1, fp);
+      }
+    }
+  }
+  else{
+    int IntType=3;
+    if(verbosity > 1) printf("writting triangle elements \n");
+    for(int it=0; it< Th.nt; it++){
+      const Mesh::Triangle &K( Th.t(it) );
+
+      int iv[IntType+1];      
+      iv[0] = IntType;
+      for(int ii=0; ii<IntType; ii++){
+	iv[ii+1] = Th.operator()(K[ii]);
+      }
+      fprintf(fp,"%d %d %d %d\n", iv[0],iv[1],iv[2],iv[3]);
+    }
+    if(surface){
+      if(verbosity > 1) printf("writting edge elements \n");
+      IntType=2;
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	const Mesh::BorderElement &K( Th.be(ibe) );
+	
+	int iv[IntType+1];    
+	iv[0] = IntType;
+	for(int ii=0; ii<IntType; ii++){
+	  iv[ii+1] = Th.operator()(K[ii]);
+	}
+	
+	fprintf(fp,"%d %d %d\n", iv[0],iv[1],iv[2]);
+      }
+    }
+  }
+  fprintf(fp, "\n");
+
+
+  // CELL_TYPE
+  // print element types in ascii or binary  
+  
+  fprintf(fp, "CELL_TYPES %d\n", numElements); 
+  if(binary){
+    int type;    
+    for(int it=0; it< Th.nt; it++){    
+      type = VTK_TRI;
+      if(!bigEndian) SwapBytes((char*)&type, sizeof(int), 1);
+      fwrite(&type, sizeof(int), 1, fp);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	type=VTK_EDGE;
+	if(!bigEndian) SwapBytes((char*)&type, sizeof(int), 1);	 
+	fwrite(&type, sizeof(int), 1, fp);
+      }
+    }
+  }
+  else{
+    int type;
+    type= VTK_TRI;
+    for(int it=0; it< Th.nt; it++){      
+      fprintf(fp,"%d ",type);
+    }
+    if(surface){
+      type=VTK_EDGE;
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	//fprintf(fp,"%d%c",type,(ibe%10==9)? '\n' : ' ');
+	fprintf(fp,"%d ",type);
+      }
+    }
+  } 
+
+  fprintf(fp, "\n");
+
+  //=================================
+  //  WRITE SOLUTION IN FORMAT VTK
+  //     LABEL OF ELEMENTS
+  //=================================
+
+  list<int> list_label_Elem;
+  //list<int> list_label_Border_Elem;
+  {
+    
+    for(int it=0; it< Th.nt; it++){
+      const Mesh::Triangle &K( Th.t(it) );
+      list<int>::const_iterator ilist;
+      int labOk=0;
+      for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+	  if( *ilist == K.lab ){ labOk = 1;   break; } 
+	}
+	if( labOk == 0){
+	  list_label_Elem.push_back(K.lab);
+	}
+    }
+    
+    if(surface){
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	const Mesh::BorderElement &K( Th.be(ibe) );
+	list<int>::const_iterator ilist;
+	int labOk=0;
+	for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+	  if( *ilist == K.lab ){ labOk = 1;   break; } 
+	}
+	if( labOk == 0){
+	  list_label_Elem.push_back(K.lab);
+	}
+      
+      }
+    }
+  
+  }
+  list_label_Elem.sort();
+
+  //=================================
+  //=================================
+  
+  fprintf(fp, "CELL_DATA %d\n", numElements);
+  int cell_fd=1;
+  int cell_lab=1;
+  /*
+  fprintf(fp, "COLOR_SCALARS Label 4\n");
+  if(binary){
+    int label;    
+    for(int it=0; it< Th.nt; it++){
+      const Mesh::Triangle &K( Th.t(it) );
+      label =K.lab;
+      if(!bigEndian) SwapBytes((char*)&label, sizeof(int), 1);
+      fwrite(&label, sizeof(int), 1, fp);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	const Mesh::BorderElement &K( Th.be(ibe) );
+	label =K.lab;
+	if(!bigEndian) SwapBytes((char*)&label, sizeof(int), 1);
+	fwrite(&label, sizeof(int), 1, fp);
+      }
+    }
+  }
+  else{
+    int label;
+    for(int it=0; it< Th.nt; it++){ 
+      const Mesh::Triangle &K( Th.t(it) );
+      list<int>::const_iterator ilist;
+      
+      for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+	  if( *ilist == K.lab ){ 
+	    
+	    fprintf(fp,"%f %f %f 1.0\n",ColorTable[abs(*ilist)%NbColorTable][0],
+		    ColorTable[abs(*ilist)%NbColorTable][1],
+		    ColorTable[abs(*ilist)%NbColorTable][2]);
+	    break; 
+	  } 
+      }
+      
+      
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	const Mesh::BorderElement &K( Th.be(ibe) );
+	list<int>::const_iterator ilist;
+	for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+	  if( *ilist == K.lab ){ 
+	    fprintf(fp,"%f %f %f 1.0\n",ColorTable[abs(*ilist)%NbColorTable][0],
+		    ColorTable[abs(*ilist)%NbColorTable][1],
+		    ColorTable[abs(*ilist)%NbColorTable][2]);
+	    break; 
+	  } 
+	}
+      }
+    }
+  } 
+  fprintf(fp,"\n");
+  */
+  fprintf(fp, "Scalars  Label int %d\n", cell_fd);
+  fprintf(fp, "LOOKUP_TABLE FreeFempp_table\n"); 
+  // Determination des labels
+  if(binary){
+    int label;    
+    for(int it=0; it< Th.nt; it++){
+      const Mesh::Triangle &K( Th.t(it) );
+      label =K.lab;
+      if(!bigEndian) SwapBytes((char*)&label, sizeof(int), 1);
+      fwrite(&label, sizeof(int), 1, fp);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	const Mesh::BorderElement &K( Th.be(ibe) );
+	label =K.lab;
+	if(!bigEndian) SwapBytes((char*)&label, sizeof(int), 1);
+	fwrite(&label, sizeof(int), 1, fp);
+      }
+    }
+  }
+  else{
+    int label;
+    for(int it=0; it< Th.nt; it++){ 
+      const Mesh::Triangle &K( Th.t(it) );
+      label =K.lab;
+      fprintf(fp,"%d\n",label);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.neb; ibe++){
+	const Mesh::BorderElement &K( Th.be(ibe) );
+	label =K.lab;
+	fprintf(fp,"%d\n",label);
+      }
+    }
+  } 
+  fprintf(fp,"\n");
+  
+  int size_list=0;
+  list<int>::const_iterator ilist;
+  for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++) size_list++;
+
+  fprintf(fp, "LOOKUP_TABLE FreeFempp_table %d\n",size_list);
+  { list<int>::const_iterator ilist;
+    for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+      
+     
+      if(binary){
+	int tab[4];
+	tab[0] = (int) ColorTable[abs(*ilist)%NbColorTable][0]*255;
+	tab[1] = (int) ColorTable[abs(*ilist)%NbColorTable][1]*255;
+	tab[2] = (int) ColorTable[abs(*ilist)%NbColorTable][2]*255;
+	tab[3] = 255;
+	
+	for(int itab=0; itab<4; itab++){
+	  char newvalue[sizeof(int)];
+	  int bid0= sprintf(newvalue,"%s", (char*)&tab[itab]);
+	  fwrite( &newvalue, sizeof(unsigned char), 1, fp);
+	}
+
+      }
+      else{
+	float tab[4];
+	tab[0] = ColorTable[abs(*ilist)%NbColorTable][0];
+	tab[1] = ColorTable[abs(*ilist)%NbColorTable][1];
+	tab[2] = ColorTable[abs(*ilist)%NbColorTable][2];
+	tab[3] = 1.;
+	fprintf(fp,"%.8f %.8f %.8f %.8f\n",tab[0],tab[1],tab[2],tab[3]);
+      }
+    }
+  }
+  fprintf(fp,"\n");
+  
+}
+
+
+
+AnyType VTK_WriteMesh_Op::operator()(Stack stack)  const 
+{
+ 
+  string * pffname= GetAny<string *>((*filename)(stack));
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  ffassert(pTh);
+  Mesh &Th=*pTh;
+  bool swap = false;
+  bool bigEndian=true;
+  bool binary = false;
+  bool surface = true;
+  bool floatmesh = true;
+  bool floatsol = true;
+  int datasize = sizeof(float);
+  int datasizeSol = sizeof(float);
+  string *dataname;
+  int nbofsol = l.size();
+  KN<int> order(nbofsol);
+  
+  char *nameofuser[nbofsol];
+
+  for(int ii=0; ii<nbofsol; ii++) order[ii] = 0;
+
+  if( nargs[0] ) dataname  = GetAny< string* >( (*nargs[0])(stack) );  
+  if( nargs[1] ) surface   = GetAny< bool >( (*nargs[1])(stack) );
+  if( nargs[2] ) order     = GetAny< KN_<long> >( (*nargs[2])(stack) );
+  if( nargs[3] ) floatmesh = GetAny< bool >( (*nargs[3])(stack) );
+  if( nargs[4] ) floatsol  = GetAny< bool  >( (*nargs[4])(stack) );
+  if( nargs[5] ) binary    = GetAny< bool  >( (*nargs[5])(stack) );
+  if( nargs[6] ) bigEndian = GetAny< bool  >( (*nargs[6])(stack) );
+
+  swap = bigEndian;
+
+  if( !floatmesh ) datasize = sizeof(double);
+  if( !floatsol ) datasizeSol= sizeof(double);
+
+  int iii=0;
+  if( nargs[0])
+    {
+      //char *data = newcopy(dataname->c_str()); 
+      char *data = newcopy(dataname); 
+      char * name = strtok(data," \t\n");
+      
+      nameofuser[iii] = newcopy(name);
+      if(verbosity>5)
+	cout << "   iovtk : value of iii  =" << iii << "  \""<<  nameofuser[iii] <<  "\"\n";
+      iii++;
+      {
+	
+	while( (name = strtok(NULL," \t\n\0")) ){
+	  
+	  if( iii >= nbofsol ){
+	    if(verbosity>5)
+	      cout << "   iovtk : The number of data name is too large " << endl;
+	    break;
+	  }
+	  nameofuser[iii] = newcopy(name);
+	  if(verbosity>5)
+	    cout << "   iovtk : value of iii  =" << iii << "  \""<<  nameofuser[iii] <<  "\"\n";
+	  iii++;
+	}
+	if( iii < nbofsol){	
+	  if(verbosity>6)
+	    cout << "   iovtk:  The number of data name is too small, we give default name " << endl;
+	}
+	delete [] data;
+      }
+    }
+  if( iii < nbofsol ){
+    for( int iiii=iii; iiii<nbofsol; iiii++){
+      //      char *dataff = new char[l[iii].name.size()+1];
+      //strcpy(dataff, l[iii].name.c_str());
+      nameofuser[iiii] = newcopy(l[iiii].name.c_str());//dataff;      
+    }
+  }
+
+  
+  FILE *fp = fopen( (*pffname).c_str(), "wb");
+  //FILE *fp = fopen( newcopy(pffname), "wb");
+  if(!fp){
+    cerr << "Unable to open file " << (*pffname).c_str() << endl;
+    ExecError("error in reading vtk file");
+  }
+  
+  // determination of number of order 0 et 1.
+  int Norder0=0;
+  for(int ii=0; ii< nbofsol; ii++)
+    if(order[ii] == 0) Norder0++;
+
+
+  char * pch = newcopy(pffname);
+  int VTK_FILE = 0;
+  int ls = 0;
+  int lll = strlen(pch);
+  if      (!strcmp(pch+ lll - (ls=4),".vtk"))  VTK_FILE = 1;
+  else if (!strcmp(pch + lll - (ls=4),".vtu")) VTK_FILE = 2;
+  if(verbosity) cout << " " << pffname << " VTK_FILE "<< VTK_FILE << endl;
+  if( VTK_FILE == 1 ){  
+    // CAS VTK
+    VTK_WRITE_MESH( *pffname, fp, Th, binary, datasize, surface, swap);    		
+    
+    // WRITE SOLUTIONS
+    if( datasizeSol == sizeof(float) ){
+      
+      if( Norder0 >0){
+	fprintf(fp, "FIELD FieldData %d\n", Norder0);
+	for(int ii=0; ii< nbofsol; ii++){
+	  if(order[ii] == 0){
+	    int nsol;
+	    if(surface){
+	      nsol = Th.nt+Th.neb;
+	    }
+	    else{
+	      nsol = Th.nt;
+	    }
+	    
+	    fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,nsol); 
+	    
+	    // changement ecriture solution
+	    l[ii].writesolutionP0_float( fp, Th, stack, surface, binary, swap);
+	  }
+	}
+      }
+      
+      if( Norder0 < nbofsol ){
+	fprintf(fp, "POINT_DATA %d\n", Th.nv);
+	fprintf(fp, "FIELD FieldData %d\n", nbofsol-Norder0);
+	for(int ii=0; ii< nbofsol; ii++){
+	  if(order[ii] == 1){
+	    
+	    //fprintf(fp,"%s %d %d float\n",l[ii].name.c_str(),l[ii].nbfloat,Th.nv); 
+	    fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,Th.nv); 
+	    if(verbosity>5)
+	      cout << "name of data("<< ii <<")=" << nameofuser[ii] << " " << l[ii].name << endl;
+	    
+	    // changement ecriture solution
+	    l[ii].writesolutionP1_float( fp, Th, stack, binary, swap);
+	  }
+	}
+      }    
+    }
+
+    if( datasizeSol == sizeof(double) ){
+      
+      if( Norder0 >0){
+	fprintf(fp, "FIELD FieldData %d\n", Norder0);
+	for(int ii=0; ii< nbofsol; ii++){
+	  if(order[ii] == 0){
+	    int nsol;
+	    if(surface){
+	      nsol = Th.nt+Th.neb;
+	    }
+	    else{
+	      nsol = Th.nt;
+	    }
+	    fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,nsol); 
+	    // changement ecriture solution
+	    l[ii].writesolutionP0_double( fp, Th, stack, surface, binary, swap);
+	    
+	  }
+	}
+	if( Norder0 < nbofsol ){
+	  fprintf(fp, "POINT_DATA %d\n", Th.nv);
+	  fprintf(fp, "FIELD FieldData %d\n", nbofsol-Norder0);
+	  for(int ii=0; ii< nbofsol; ii++){
+	    if(order[ii] == 1){
+	      
+	      
+	      fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,Th.nv); 
+	      if(verbosity>5)
+		cout << "name of data("<< ii <<")=" << nameofuser[ii]  << endl;
+	      // changement ecriture solution
+	      l[ii].writesolutionP1_double( fp, Th, stack, binary, swap);
+	    }
+	  }
+	}
+      }
+    }
+  }
+  else if( VTK_FILE == 2 ){    
+    /*
+      // Solution Order
+      // order 1
+      if( Norder0 != nbofsol){
+	 BEGINTYPE_VTU( fp, "PointData");
+	 for(int ii=0; ii< nbofsol; ii++){
+	   if(order[ii] == 1){
+	     
+	     if(datasize == sizeof(float)){    
+	       VTU_DATA_ARRAY( fp, "Float32", nameofuser[ii] , l[ii].nbfloat, binary);
+	       l[ii].writesolutionP1_float( fp, Th, stack, binary, swap);
+	     }
+	     else if(datasize == sizeof(double)) {
+	       VTU_DATA_ARRAY( fp, "Float64", nameofuser[ii] , l[ii].nbfloat, binary);
+	       l[ii].writesolutionP1_double( fp, Th, stack, binary, swap);
+	     }
+	     
+	     ENDTYPE_VTU( fp, "DataArray");	   
+	   }
+	 }
+	 ENDTYPE_VTU( fp, "PointData");
+      }
+      // order 0
+      if( Norder0 > 0 ){
+	BEGINTYPE_VTU( fp, "CellData");
+	for(int ii=0; ii< nbofsol; ii++){
+	  if(order[ii] == 0){
+	   
+	    if(datasize == sizeof(float)){    
+	       VTU_DATA_ARRAY( fp, "Float32", nameofuser[ii] , l[ii].nbfloat, binary);
+	       l[ii].writesolutionP0_float( fp, Th, stack, surface, binary, swap);
+	     }
+	     else if(datasize == sizeof(double)) {
+	       VTU_DATA_ARRAY( fp, "Float64", nameofuser[ii] , l[ii].nbfloat, binary);
+	       l[ii].writesolutionP0_double( fp, Th, stack, surface, binary, swap);
+	     }
+	    ENDTYPE_VTU( fp, "DataArray");
+	  }
+	}
+	ENDTYPE_VTU( fp, "CellData");
+      }
+      long offsetsol=0;
+      bool encode64=0;
+    */
+    VTU_WRITE_MESH( fp, Th, binary, datasize, surface, swap);
+
+    // Solution Order
+    // order 1
+    if( Norder0 != nbofsol){
+      BEGINTYPE_VTU( fp, "PointData");
+      for(int ii=0; ii< nbofsol; ii++){
+	if(order[ii] == 1){
+	  
+	  if(datasize == sizeof(float)){    
+	    VTU_DATA_ARRAY( fp, "Float32", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP1_float( fp, Th, stack, binary, swap, 1);
+	  }
+	  else if(datasize == sizeof(double)) {
+	    VTU_DATA_ARRAY( fp, "Float64", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP1_double( fp, Th, stack, binary, swap, 1);
+	  }
+	  
+	  ENDTYPE_VTU( fp, "DataArray");	   
+	}
+      }
+      ENDTYPE_VTU( fp, "PointData");
+    }
+    // order 0
+    if( Norder0 > 0 ){
+      BEGINTYPE_VTU( fp, "CellData");
+      for(int ii=0; ii< nbofsol; ii++){
+	if(order[ii] == 0){
+	  
+	  if(datasize == sizeof(float)){    
+	    VTU_DATA_ARRAY( fp, "Float32", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP0_float( fp, Th, stack, surface, binary, swap, 1);
+	  }
+	  else if(datasize == sizeof(double)) {
+	    VTU_DATA_ARRAY( fp, "Float64", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP0_double( fp, Th, stack, surface, binary, swap, 1);
+	  }
+	  ENDTYPE_VTU( fp, "DataArray");
+	}
+      }
+      ENDTYPE_VTU( fp,"CellData");
+      
+    }
+    fprintf(fp,"</Piece>\n"); 
+    fprintf(fp,"</UnstructuredGrid>\n");
+    fprintf(fp,"</VTKFile>\n");
+  }
+  else
+  {
+    cout << " iovtk extension file is not correct (" << VTK_FILE << " != 1 or 2 ) " <<  endl;
+    ExecError(" iovtk : extension file");
+  }
+  
+  // close file fp
+  fclose(fp);
+
+
+  for( int iiii=0; iiii<nbofsol; iiii++){
+    delete [] nameofuser[iiii];
+  }
+
+  delete [] pch;
+  return (Mesh *) NULL;
+}
+
+
+
+//==============================================
+// FIN ECRITURE DE FICHIER .vtk (2D)
+//==============================================
+
+//=======================
+// FIN 2D Fichier .vtk
+//=======================
+
+// three dimensional case
+// LOAD fichier.vtk
+class VTK_LoadMesh3_Op : public E_F0mps 
+{
+public:
+  Expression filename;
+  static const int n_name_param = 4; // 
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+public:
+  VTK_LoadMesh3_Op(const basicAC_F0 &  args,Expression ffname) 
+    : filename(ffname)
+  {
+    if(verbosity) cout << "Load mesh given by VTK " << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);   
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+basicAC_F0::name_and_type VTK_LoadMesh3_Op::name_param[]= {
+  {  "reftet", &typeid(long)},
+  {  "swap", &typeid(bool)},
+  {  "refface", &typeid(long)},
+  {  "namelabel",&typeid(string)}
+};
+
+
+class  VTK_LoadMesh3 : public OneOperator { public:  
+    VTK_LoadMesh3() : OneOperator(atype<pmesh3>(),atype<string *>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new VTK_LoadMesh3_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+Mesh3 * VTK_Load3(const string & filename, bool bigEndian)
+// swap = bigEndian or not bigEndian
+{
+  // variable freefem++
+  int nv, nt=0, nbe=0;
+    int nerr=0;
+  // Reading Mesh in vtk formats 
+  FILE *fp = fopen(filename.c_str(), "rb");
+  if(!fp){
+    cerr << "Unable to open file " << filename.c_str() << endl;
+    ExecError("error in reading vtk file");
+  }
+
+  char buffer[256], buffer2[256];
+    
+  fgets(buffer, sizeof(buffer), fp); // version line
+  fgets(buffer, sizeof(buffer), fp); // title
+  
+  fscanf(fp, "%s", buffer); // ASCII or BINARY
+  bool binary = false;
+  if( !strcmp(buffer, "BINARY") ) binary = true;
+    
+  if(fscanf(fp, "%s %s", buffer, buffer2) != 2){
+      cout << "error in reading vtk files" << endl;
+      ExecError("error in reading vtk file"); }
+  if(strcmp(buffer, "DATASET") || strcmp(buffer2, "UNSTRUCTURED_GRID")){
+    cout << "VTK reader can only read unstructured datasets" << endl;
+    ExecError("error in reading vtk file");
+  }
+    
+  // read mesh vertices
+  if(fscanf(fp, "%s %d %s\n", buffer, &nv, buffer2) != 3){
+      cout << "error in reading vtk files" << endl;
+      ExecError("error in reading vtk file"); }
+  if(strcmp(buffer, "POINTS") || !nv){
+    cerr << "No points in dataset" << endl;
+    ExecError("error in reading vtk file");
+  }
+  int datasize;
+  if( !strncmp(buffer2, "double",6))
+    datasize = sizeof(double);
+  else if( !strncmp(buffer2, "float",5))
+    datasize = sizeof(float);
+  else{
+    cout << "VTK reader only accepts float or double datasets" << endl;
+    ExecError("error in reading vtk file");
+  }
+  if(verbosity>3)
+   cout << "Reading %d points" << nv << " buffer2" <<  buffer2 << "binary"
+        << binary << " " << datasize << " "<< sizeof(float) << endl;
+  Vertex3   *vff = new Vertex3[nv];
+    
+  for(int i = 0 ; i < nv; i++){
+     if(verbosity>9)
+      cout << " i=" << i << endl;
+    double xyz[3];
+    if(binary){
+      if(datasize == sizeof(float)){
+	float f[3];
+	if(fread(f, sizeof(float), 3, fp) != 3){
+                cout << "error in reading vtk files" << endl;
+                ExecError("error in reading vtk file"); }
+	if(!bigEndian) SwapBytes((char*)f, sizeof(float), 3);
+	for(int j = 0; j < 3; j++) xyz[j] = f[j];
+      }
+      else{
+	if(fread(xyz, sizeof(double), 3, fp) != 3){
+               cout << "error in reading vtk files" << endl;
+               ExecError("error in reading vtk file"); }
+	if(!bigEndian) SwapBytes((char*)xyz, sizeof(double), 3);
+      }
+    }
+    else{
+      cout << datasize << " "<< sizeof(float) << endl;
+      if(datasize == sizeof(float)){ 
+	if(fscanf(fp, "%lf %lf %lf", &xyz[0], &xyz[1], &xyz[2]) != 3){
+               cout << "error in reading vtk files (float)" << endl;
+              ExecError("error in reading vtk file"); }
+      }
+      else{
+	if(fscanf(fp, "%lf %lf %lf", &xyz[0], &xyz[1], &xyz[2]) != 3){
+               cout << "error in reading vtk files (double)" << endl;
+               ExecError("error in reading vtk file"); }
+      }
+    }
+    vff[i].x = xyz[0];
+    vff[i].y = xyz[1];
+    vff[i].z = xyz[2];
+    vff[i].lab = 1;
+    if(verbosity>9)
+      printf( "xyz = %f %f %f\n", xyz[0],xyz[1], xyz[2]);
+  }    
+
+  // read mesh elements
+  int numElements, numElements2, totalNumInt;
+  if(fscanf(fp, "%s %d %d\n", buffer, &numElements, &totalNumInt) != 3){
+      cout << "error in reading vtk files" << endl;
+      ExecError("error in reading vtk file"); }
+   if(verbosity>3)
+    printf("reading parameter %s %d %d\n", buffer, numElements, totalNumInt);
+   if(strncmp(buffer, "CELLS",5) || !numElements){
+     cout << "No cells in dataset" << endl;
+     ExecError("error in reading vtk file");
+  }
+   if(verbosity>3)
+    cout << "Reading cells" << numElements << endl;
+  
+  int *IntCells   = new int[totalNumInt-numElements];
+  int *firstCell  = new int[numElements+1];
+  int *TypeCells   = new int[numElements];
+  int numIntCells = 0;
+  
+  for(unsigned int i = 0; i < numElements; i++){
+    int numVerts, n[100];
+     if(verbosity>9)
+    cout << "i=" << i << " " << numElements << endl;
+    for(int ii = 0; ii < 100; ii++) n[ii]=-1;
+    if(binary){
+      if( fread(&numVerts, sizeof(int), 1, fp) != 1 ) {
+	cout << "error in reading VTK files " << endl;
+	ExecError("error in reading vtk file");
+      }
+      if( !bigEndian) SwapBytes((char*)&numVerts, sizeof(int), 1);
+      if((int)fread(n, sizeof(int), numVerts, fp) != numVerts){
+	cout << "error in reading VTK files " << endl;
+	ExecError("error in reading vtk file");
+      }
+      if(!bigEndian) SwapBytes((char*)n, sizeof(int), numVerts);
+    }
+    else{
+      if(fscanf(fp, "%d", &numVerts) != 1){
+	cout << "error in reading VTK files " << endl;
+	ExecError("error in reading vtk file");
+      }
+      cout << "numVerts" << numVerts << endl;
+      for(int j = 0; j < numVerts; j++){
+	if(fscanf(fp, "%d", &n[j]) != 1){
+	  cout << "error in reading VTK files " << endl;
+	  ExecError("error in reading vtk file");
+	}
+        if(verbosity>9)
+	cout << "  n[j]" << n[j] << endl;
+      }
+    }
+    firstCell[i] = numIntCells;
+    for(int j = 0; j < numVerts; j++){
+      if(n[j] >= 0 && n[j] < nv){
+	IntCells[numIntCells] = n[j];
+	numIntCells++;
+      }	  
+      else{
+	cout << "Bad vertex index" << endl;
+	ExecError("error in reading vtk file");
+      }
+    }
+  }
+  firstCell[numElements] = totalNumInt-numElements;  
+  
+  if(fscanf(fp, "%s %d\n", buffer, &numElements2) != 2){
+    cout << " Error in reading CELL_TYPES ARGUMENT " << endl;
+    ExecError("error in reading vtk file");
+  }
+  if(strcmp(buffer, "CELL_TYPES") || numElements2 != (int)numElements){
+    cout <<"No or invalid number of cells types" << endl;
+    ExecError("error in reading vtk file");
+  }
+   if(verbosity>3)
+  printf( "reading parameter %s %d\n", buffer, numElements2);
+  
+  // 3D 
+  
+  for(unsigned int i = 0; i < numElements; i++){
+    int type;
+    if(binary){
+      if(fread(&type, sizeof(int), 1, fp) != 1){
+	cout <<"bug in readings cell types" << endl;
+	ExecError("error in reading vtk file");
+      }
+      if(!bigEndian) SwapBytes((char*)&type, sizeof(int), 1);
+    }
+    else{
+      if(fscanf(fp, "%d", &type) != 1){
+	cout <<"bug in readings cell types" << endl;
+	ExecError("error in reading vtk file");
+      }
+    }
+    TypeCells[i] = type;
+      switch(type){
+      case 1:  // Vertex
+	 if(nerr++< 3 && verbosity)  cout << "this type of cell (vertex) is not taking account in Freefem++ " << endl;
+	break;
+      case 3:  // Edge/line
+	cout << "this type of cell is not taking account in Freefem++ for a two dimensional mesh" << endl; // 3D
+	break;
+      case 5:  // Triangle
+	nbe++; // 3D
+	break;   
+      case 10: // Tetrah�dre
+	nt++;
+	break;  
+      default: 
+	cout << "Error :: This type of cell is not considered in Freefem++"<< endl;
+	ExecError("error in reading vtk file");
+	break;
+	
+      }
+    }  
+
+    fclose(fp);
+
+    
+    // 3D versions
+    
+    Tet *tff;
+    if( nt >0) tff = new Tet[nt];
+    Tet *ttff = tff;
+
+    Triangle3 *bff  = new Triangle3[nbe];
+    Triangle3 *bbff = bff;
+
+    for(unsigned int i = 0; i < numElements; i++){
+      int type=TypeCells[i];
+      int ivb[3],ivt[4];
+      int label=1;
+      switch(type){
+      case 1:  // Vertex
+	 if(nerr++<3 && verbosity) cout << "this type of cell is not taking account in Freefem++ " << endl;
+	break;
+      case 3:  // Edge/line
+	break;
+      case 5:  // Triangle
+	cout << i << " " << firstCell[i+1] << " " << firstCell[i] << endl;
+	assert( (firstCell[i+1]-firstCell[i]) == 3 );
+	for(int j=firstCell[i]; j<firstCell[i+1]; j++){
+    	  ivb[j-firstCell[i]] = IntCells[j];
+	}
+	(bbff++)->set(vff, ivb, label);
+	break;   
+      case 10: // Tetrah�dre
+	assert( (firstCell[i+1]-firstCell[i]) == 4 );
+	for(int j=firstCell[i]; j<firstCell[i+1]; j++){
+    	  ivt[j-firstCell[i]] = IntCells[j];
+	}
+	(ttff++)->set(vff, ivt, label);
+	break;  
+      default: 
+	break;	
+      } 
+    }
+    
+    delete [] IntCells;   
+    delete [] firstCell; 
+    delete [] TypeCells;
+
+    if(nt>0){
+      Mesh3 *pTh = new Mesh3(nv,nt,nbe,vff,tff,bff);
+      return pTh;
+    }
+    else{
+      Mesh3 *pTh = new Mesh3(nv,nbe,vff,bff);
+      return pTh;
+    }
+    
+}
+
+AnyType VTK_LoadMesh3_Op::operator()(Stack stack)  const 
+{
+ 
+  string * pffname= GetAny<string *>((*filename)(stack));
+  bool swap = false;
+  int reftetra=1; 
+  int reftri = 1;
+  
+  if( nargs[0] )  reftetra = GetAny<long>((*nargs[0])(stack));
+  if( nargs[1] )  swap = GetAny< bool >((*nargs[1])(stack));
+  if( nargs[2] )  reftri = GetAny<long>((*nargs[2])(stack));
+
+  string *DataLabel;
+  if( nargs[3] ) DataLabel = GetAny<string *>((*nargs[3])(stack));
+
+  Mesh3 * Th = VTK_Load3( *pffname, swap); 
+
+  // A faire fonction pour changer le label
+
+  Add2StackOfPtr2FreeRC(stack,Th);
+		
+  return Th;
+}
+
+//==============================================
+// ECRITURE DE FICHIER .vtk (3D)
+//==============================================
+
+class VTK_WriteMesh3_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  
+  struct Expression2 {
+    string name;
+    long what; // 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 1 scalar, 2 vector (3D), 3 symtensor(3D)
+    Expression e[6];
+    Expression2() {e[0]=0; e[1]=0; e[2]=0; e[3]=0; e[4]=0; e[5]=0; what=0; nbfloat=0;};
+    Expression &operator[](int i){return e[i];}
+    double eval(int i,Stack stack) const  { 
+    if (e[i]) {
+      return GetAny< double >( (*e[i])(stack) );
+    }
+    else 
+      return 0;
+    }
+    
+    void writesolutionP0_float_XML( FILE *fp, const Mesh3 &Th, Stack stack, bool surface) const {      
+      unsigned char ElementChars[256];
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R3 Cdg_hat = R3(1./4.,1./4.,1/4.);  
+      
+      long nc=Th.nt;
+      if(surface) nc=nc+Th.nbe;
+     
+      unsigned nbytes= nc*sizeof(float)*(*this).nbfloat;
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+ 
+      for (int it=0;it<Th.nt;it++){
+	const Tet  & K(Th.elements[it]);
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< nbfloat;j++){
+	  float value = eval(j,stack);
+	 	   
+	  l=runEncodeB64(sizeof(float),(unsigned char *)&value,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.nbe;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Tet & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< nbfloat;j++){
+	    float value = eval(j,stack);
+
+	    l=runEncodeB64(sizeof(float),(unsigned char *)&value,ElementChars);
+	    ElementChars[l]=0;
+	    fwrite(&ElementChars,l,1,fp);
+	    
+	  } 
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      fprintf(fp,"\n");
+       
+    }
+    void writesolutionP0_float_binary( FILE *fp, const Mesh3 &Th, Stack stack, bool surface, bool bigEndian) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R3 Cdg_hat = R3(1./4.,1./4.,1/4.);  
+      
+      if(!bigEndian){
+      
+	for (int it=0;it<Th.nt;it++){
+	  const Tet  & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< nbfloat;j++){
+	    float value = eval(j,stack);
+
+	    SwapBytes((char*)&value, sizeof(float), 1);
+	    fwrite(&value, sizeof(float), 1, fp);
+	  } 
+	}
+
+	if( surface ){
+	  for (int ibe=0;ibe<Th.nbe;ibe++){
+	    // determination du triangle contenant cette edge
+	    int ie;
+	    int it = Th.BoundaryElement( ibe, ie); 
+	    const Tet & K(Th.elements[it]);
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	    for(int j=0;j< nbfloat;j++){
+	      float value = eval(j,stack);
+       
+	      SwapBytes((char*)&value, sizeof(float), 1);
+	      fwrite(&value, sizeof(float), 1, fp);
+	    } 
+	  }
+	}
+      }
+      else{   
+	for (int it=0;it<Th.nt;it++){
+	  const Tet  & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< nbfloat;j++){
+	    float value = eval(j,stack);
+	   
+	    fwrite(&value, sizeof(float), 1, fp);	 
+	  } 
+	}
+
+	if( surface ){
+	  for (int ibe=0;ibe<Th.nbe;ibe++){
+	    // determination du triangle contenant cette edge
+	    int ie;
+	    int it = Th.BoundaryElement( ibe, ie); 
+	    const Tet & K(Th.elements[it]);
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	    for(int j=0;j< nbfloat;j++){
+	      float value = eval(j,stack);
+
+	      fwrite(&value, sizeof(float), 1, fp);  
+	    } 
+	  }
+	}
+      }
+      fprintf(fp,"\n"); 
+    }
+    void writesolutionP0_float( FILE *fp, const Mesh3 &Th, Stack stack, bool surface) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R3 Cdg_hat = R3(1./4.,1./4.,1/4.);  
+      
+      for (int it=0;it<Th.nt;it++){
+	const Tet  & K(Th.elements[it]);
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< nbfloat;j++){
+	  float value = eval(j,stack);
+	  
+	  fprintf(fp,"%.8e ",value); 
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.nbe;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Tet & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< nbfloat;j++){
+	    float value = eval(j,stack);
+	    
+	    fprintf(fp,"%.8e ",value); 
+	  } 
+	}
+      }
+      fprintf(fp,"\n"); 
+      
+    }
+
+    void writesolutionP0_float( FILE *fp, const Mesh3 &Th, Stack stack, bool surface, bool binary, bool bigEndian, bool XML=false) const {
+      if(binary){
+	if(!XML){
+	  (*this).writesolutionP0_float_binary( fp, Th, stack, surface, bigEndian); 
+	}
+	else
+	  (*this).writesolutionP0_float_XML( fp, Th, stack, surface );
+      }
+      else 
+	(*this).writesolutionP0_float( fp, Th, stack, surface );
+    }
+
+    void writesolutionP0_double_binary( FILE *fp, const Mesh3 &Th, Stack stack, bool surface, bool bigEndian) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R3 Cdg_hat = R3(1./4.,1./4.,1./4.);  
+      
+      if(!bigEndian){
+      
+	for (int it=0;it<Th.nt;it++){
+	  const Tet  & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    double value = (*this).eval(j,stack);
+	    
+	    SwapBytes((char*)&value, sizeof(double), 1);
+	    fwrite(&value, sizeof(double), 1, fp);
+	  } 	  
+	}
+	if( surface ){
+	  for (int ibe=0;ibe<Th.nbe;ibe++){
+	    // determination du triangle contenant cette edge
+	    int ie;
+	    int it = Th.BoundaryElement( ibe, ie); 
+	    const Tet & K(Th.elements[it]);
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	    for(int j=0;j< (*this).nbfloat;j++){
+	      double value = (*this).eval(j,stack);
+	     
+	      SwapBytes((char*)&value, sizeof(double), 1);
+	      fwrite(&value, sizeof(double), 1, fp);
+	    } 
+	  }	  
+	}
+      }
+      else{
+	for (int it=0;it<Th.nt;it++){
+	  const Tet  & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    double value = (*this).eval(j,stack);
+
+	    fwrite(&value, sizeof(double), 1, fp);
+	  } 	  
+	}
+	if( surface ){
+	  for (int ibe=0;ibe<Th.nbe;ibe++){
+	    // determination du triangle contenant cette edge
+	    int ie;
+	    int it = Th.BoundaryElement( ibe, ie); 
+	    const Tet & K(Th.elements[it]);
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	    for(int j=0;j< (*this).nbfloat;j++){
+	      double value = (*this).eval(j,stack);
+	    
+	      fwrite(&value, sizeof(double), 1, fp);
+	    } 
+	  }	  
+	}
+      }
+
+      fprintf(fp,"\n");
+    }
+    void writesolutionP0_double_XML( FILE *fp, const Mesh3 &Th, Stack stack, bool surface) const {   
+      unsigned char ElementChars[256];
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R3 Cdg_hat = R3(1./4.,1./4.,1./4.);  
+      long nc=Th.nt;
+      if(surface) nc=nc+Th.nbe;
+
+      unsigned nbytes= nc*sizeof(double)*(*this).nbfloat;
+      int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+
+      for (int it=0;it<Th.nt;it++){
+	const Tet  & K(Th.elements[it]);
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< (*this).nbfloat;j++){
+	  double value = (*this).eval(j,stack);
+	  
+	  l=runEncodeB64(sizeof(double),(unsigned char *)&value,ElementChars);
+	  ElementChars[l]=0;
+	  fwrite(&ElementChars,l,1,fp);
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.nbe;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Tet & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    double value = (*this).eval(j,stack);
+
+	    l=runEncodeB64(sizeof(double),(unsigned char *)&value,ElementChars);
+	    ElementChars[l]=0;
+	    fwrite(&ElementChars,l,1,fp);
+	    
+	  } 
+	  
+	}
+      }
+      // flush buffer
+      l=runEncodeB64(0,NULL,ElementChars);
+      ElementChars[l]=0;
+      fwrite(&ElementChars,l,1,fp);
+      fprintf(fp,"\n");
+    }
+    void writesolutionP0_double( FILE *fp, const Mesh3 &Th, Stack stack, bool surface) const {      
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      R3 Cdg_hat = R3(1./4.,1./4.,1./4.);  
+      
+      for (int it=0;it<Th.nt;it++){
+	const Tet  & K(Th.elements[it]);
+	mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	
+	for(int j=0;j< (*this).nbfloat;j++){
+	  double value = (*this).eval(j,stack);
+	  fprintf(fp,"%.16e ",value); 	  	  
+	} 
+      }
+      if( surface ){
+	for (int ibe=0;ibe<Th.nbe;ibe++){
+	  // determination du triangle contenant cette edge
+	  int ie;
+	  int it = Th.BoundaryElement( ibe, ie); 
+	  const Tet & K(Th.elements[it]);
+	  mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    double value = (*this).eval(j,stack);
+ 
+	    fprintf(fp,"%.16e ",value); 	   
+	  } 
+	  
+	}
+      }
+      //fprintf(fp,"\n");
+    }
+
+    void writesolutionP0_double( FILE *fp, const Mesh3 &Th, Stack stack, bool surface, bool binary, bool bigEndian, bool XML=false) const {
+      if(binary){
+	if(!XML){
+	  (*this).writesolutionP0_double_binary( fp, Th, stack, surface, bigEndian); 
+	}
+	else
+	  (*this).writesolutionP0_double_XML( fp, Th, stack, surface );
+      }
+      else 
+	(*this).writesolutionP0_double( fp, Th, stack, surface );
+    }
+
+    void writesolutionP1_float( FILE *fp, const Mesh3 &Th, Stack stack, bool binary, bool bigEndian,bool XML=false) const {
+      unsigned char ElementChars[256];
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      KN<double> valsol(Th.nv*(*this).nbfloat);
+      KN<int> takemesh(Th.nv);
+      takemesh =0;
+      valsol   =0.;
+       for(int it=0;  it<Th.nt; it++){
+	 for(int iv=0; iv<4; iv++){
+	   int i=Th(it,iv);
+	   mp3->setP(&Th,it,iv);
+	   
+	   for(int j=0;j<(*this).nbfloat;j++){
+	     valsol[ i*(*this).nbfloat+j ] = valsol[ i*(*this).nbfloat+j ] + (*this).eval(j,stack);	     
+	   }
+	   takemesh[i] = takemesh[i]+1;    
+	 }
+       }
+       
+       if(binary){
+	 if(!XML){
+	   if(!bigEndian){ 
+	     for (int iv=0;iv<Th.nv;iv++){
+	       for(int j=0;j< (*this).nbfloat;j++){
+		 valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		 float value = valsol[iv*(*this).nbfloat+j];
+		
+		 if(!bigEndian) SwapBytes((char*)&value, sizeof(float), 1);
+		 fwrite(&value, sizeof(float), 1, fp);
+		 
+	       }
+	     }
+	   }
+	   else{
+	     for (int iv=0;iv<Th.nv;iv++){
+	       for(int j=0;j< (*this).nbfloat;j++){
+		 valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		 float value = valsol[iv*(*this).nbfloat+j];
+		 
+		 fwrite(&value, sizeof(float), 1, fp);
+	       }
+	     }
+	   }
+	 }
+	 else{
+	   long nc=Th.nv;
+	   
+	   unsigned nbytes= nc*sizeof(float)*(*this).nbfloat;
+	   int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+
+	   for (int iv=0;iv<Th.nv;iv++){
+	     for(int j=0;j< (*this).nbfloat;j++){
+	       valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	       float value = valsol[iv*(*this).nbfloat+j];
+	   
+	       l=runEncodeB64(sizeof(float),(unsigned char *)&value,ElementChars);
+	       ElementChars[l]=0;
+	       fwrite(&ElementChars,l,1,fp);
+	     }
+	   }
+	   // flush buffer
+	   l=runEncodeB64(0,NULL,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+	  
+	 }	 
+       }
+       else{
+      
+	 for (int iv=0;iv<Th.nv;iv++){
+	   for(int j=0;j< (*this).nbfloat;j++){
+	     valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	     float value = valsol[iv*(*this).nbfloat+j];
+	     
+	     fprintf(fp," %.8e\n",value);
+	   }
+	 }
+       }
+       fprintf(fp,"\n");
+    }
+
+    void writesolutionP1_double( FILE *fp, const Mesh3 &Th, Stack stack, bool binary, bool bigEndian, bool XML=false) const {
+      unsigned char ElementChars[256];
+      MeshPoint *mp3(MeshPointStack(stack)); 
+      KN<double> valsol(Th.nv*(*this).nbfloat);
+      KN<int> takemesh(Th.nv);
+      takemesh =0;
+      valsol   =0.;
+      for(int it=0;  it<Th.nt; it++){
+	for(int iv=0; iv<4; iv++){
+	  int i=Th(it,iv);
+	  mp3->setP(&Th,it,iv);
+	  
+	  for(int j=0;j<(*this).nbfloat;j++){
+	    valsol[ i*(*this).nbfloat+j ] = valsol[ i*(*this).nbfloat+j ] + (*this).eval(j,stack);	     
+	  }
+	  takemesh[i] = takemesh[i]+1;    
+	}
+      }
+      
+      if(binary){	
+	if( !XML ){
+	  if( !bigEndian ){
+	    for (int iv=0;iv<Th.nv;iv++){
+	      for(int j=0;j< (*this).nbfloat;j++){
+		valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		double value = valsol[iv*(*this).nbfloat+j];
+		
+		SwapBytes((char*)&value, sizeof(double), 1);
+		fwrite(&value, sizeof(double), 1, fp);
+		
+	      }	   
+	    }
+	  }
+	  else{
+	    for (int iv=0;iv<Th.nv;iv++){
+	      for(int j=0;j< (*this).nbfloat;j++){
+		valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+		double value = valsol[iv*(*this).nbfloat+j];
+		
+		fwrite(&value, sizeof(double), 1, fp);
+		
+	      }	   
+	    }
+	  }
+	}
+	else{
+	   long nc=Th.nv;
+	   
+	   unsigned nbytes= nc*sizeof(double)*(*this).nbfloat;
+	   int l=runEncodeB64(sizeof(int),(unsigned char *)&nbytes,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+
+	   for (int iv=0;iv<Th.nv;iv++){
+	     for(int j=0;j< (*this).nbfloat;j++){
+	       valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	       double value = valsol[iv*(*this).nbfloat+j];
+	   
+	       l=runEncodeB64(sizeof(double),(unsigned char *)&value,ElementChars);
+	       ElementChars[l]=0;
+	       fwrite(&ElementChars,l,1,fp);
+	     }
+	   }
+	   // flush buffer
+	   l=runEncodeB64(0,NULL,ElementChars);
+	   ElementChars[l]=0;
+	   fwrite(&ElementChars,l,1,fp);
+	   
+	}
+
+      }
+      else{
+	for (int iv=0;iv<Th.nv;iv++){
+	  for(int j=0;j< (*this).nbfloat;j++){
+	    valsol[iv*(*this).nbfloat+j] = valsol[ iv*(*this).nbfloat+j ]/takemesh[iv];
+	    double value = valsol[iv*(*this).nbfloat+j];
+	
+	      fprintf(fp,"%.16e ",value); 
+	  
+	  }	   
+	}
+      }
+      fprintf(fp,"\n");     
+    }    
+  };
+  vector<Expression2> l;
+  static const int n_name_param = 7;  
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  
+public:
+  VTK_WriteMesh3_Op(const basicAC_F0 &  args) : l( args.size()-2 )
+  {
+    int nbofsol;
+    int ddim=3;
+    int stsize=6;
+
+     int sca=0,vec=0,ten=0;
+    
+    string scas("scalaire"); 
+    string vecs("vector"); 
+    string tens("tensor"); 
+
+    if(verbosity) cout << "Write Mesh and Solutions in VTK Formats" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+
+    if (BCastTo<string *>(args[0])) filename = CastTo<string *>(args[0]);
+    if (BCastTo<pmesh3>(args[1])) eTh= CastTo<pmesh3>(args[1]);
+    
+    nbofsol = l.size();
+    for (size_t i=2;i<args.size();i++){
+      size_t jj=i-2;
+      
+      if ( BCastTo<double>( args[i] ))
+	{
+	  l[jj].what=1;
+	  l[jj].nbfloat=1;
+	  l[jj][0]=to<double>( args[i] );
+	  
+	  char number[16];
+	  sprintf(number,"%li",jj+1);
+	  l[jj].name=scas;
+	  l[jj].name+=number;
+	  sca++;
+
+	}
+      else if ( args[i].left()==atype<E_Array>() )
+	{
+	  const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	  //cout << "taille" << a0->size() << endl;
+	  if (a0->size() != ddim && a0->size() != stsize) 
+	    CompileError("savesol in 3D: vector solution is 3 composant, tensor solution is 6 composant");
+	  
+	  if( a0->size() == ddim){
+	    // vector solution
+	    l[jj].what=2;
+	    l[jj].nbfloat=ddim;
+	    for(int j=0; j<ddim; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	     char number[16];
+	    sprintf(number,"%li",jj+1);
+	    l[jj].name=vecs;
+	    l[jj].name+=number;
+	    vec++;	  
+	    
+	  }
+	  else if( a0->size() == stsize){
+	    // symmetric tensor solution
+	    l[jj].what=3;
+	    l[jj].nbfloat=stsize;
+	    for(int j=0; j<stsize; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	    char number[16];
+	    sprintf(number,"%li",jj+1);
+	    l[jj].name=tens;
+	    l[jj].name+=number;
+	    ten++;
+	  }
+	  
+	}
+      else {
+	cout << " arg " << i << " " << args[i].left() << endl;
+	CompileError("savesol in 2D: Sorry no way to save this kind of data");
+      }
+    }
+  }
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<string *>(), atype<pmesh3>(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new VTK_WriteMesh3_Op(args);}   
+  AnyType operator()(Stack stack)  const ;
+};
+basicAC_F0::name_and_type VTK_WriteMesh3_Op::name_param[]= {
+  {  "dataname", &typeid(string*)},
+  {  "withsurfacemesh", &typeid(bool)},
+  {  "order", &typeid(KN_<long>)},
+  // A rajouter dans le 3D
+  {  "floatmesh", &typeid(bool)},
+  {  "floatsol", &typeid(bool)},
+  {  "bin", &typeid(bool)},
+  {  "swap", &typeid(bool)}
+};
+  
+void VTK_WRITE_MESH3( const string &filename, FILE *fp, const Mesh3 &Th, bool binary, int datasize, bool surface, bool bigEndian){
+     
+  fprintf(fp, "# vtk DataFile Version 2.0\n");
+  fprintf(fp, "%s, Created by Freefem++ \n", filename.c_str());
+  if(binary)
+    fprintf(fp, "BINARY\n");
+  else
+    fprintf(fp, "ASCII\n");
+  fprintf(fp, "DATASET UNSTRUCTURED_GRID\n");
+  // get all the entities in the model
+
+  // write mesh vertices
+  if(datasize == sizeof(float)) fprintf(fp, "POINTS %d float\n", Th.nv);
+  if(datasize == sizeof(double)) fprintf(fp, "POINTS %d double\n", Th.nv);
+  
+  if(datasize == sizeof(float)) {      
+    for(unsigned int i = 0; i < Th.nv; i++){
+      const  Vertex3 & P = Th.vertices[i];
+      float f[3];
+      f[0]=P.x;
+      f[1]=P.y;
+      f[2]=P.z; 
+      if(binary){
+	if(!bigEndian) SwapBytes((char*)&f, sizeof(float), 3);
+	fwrite(&f, sizeof(float), 3, fp);
+      }
+      else{
+	fprintf(fp,"%.8f %.8f %.8f\n",f[0],f[1],f[2]);
+      }
+    }  
+  }
+  else if(datasize == sizeof(double)){
+    for(unsigned int i = 0; i < Th.nv; i++){
+      const  Vertex3 & P = Th.vertices[i];
+      double f[3];
+      f[0]=P.x;
+      f[1]=P.y;
+      f[2]=P.z;    // 3D case
+      if(binary){
+	if(!bigEndian) SwapBytes((char*)&f, sizeof(float), 3);
+	fwrite(&f, sizeof(float), 3, fp);
+      }
+      else{
+	fprintf(fp,"%lf %lf %lf\n",f[0],f[1],f[2]);
+      }
+    }  
+  }
+  fprintf(fp,"\n");
+  if(verbosity > 1) printf("writting vertices is finish\n");
+  if(verbosity > 1) printf("writting elements now\n");
+  
+  //================
+  //    CELL 
+  //================
+  // loop over all elements we need to save and count vertices
+  int numElements, totalNumInt;
+  if(surface){
+    numElements = Th.nt+Th.nbe; 
+    totalNumInt = Th.nt*4+Th.nbe*3+numElements;
+  }
+  else{
+    numElements = Th.nt; 
+    totalNumInt = Th.nt*4+numElements;
+  }
+  if(verbosity > 1) printf("writting cells \n");
+  // print vertex indices in ascii or binary
+  fprintf(fp, "CELLS %d %d\n", numElements, totalNumInt);
+
+  if(binary){
+    int IntType=4;
+    if(verbosity > 1) printf("writting tetrahedron elements \n");
+    for(int it=0; it< Th.nt; it++){    
+      const Tet & K( Th.elements[it] );
+      int iv[IntType+1];
+      
+      iv[0] = IntType;
+      for(int ii=0; ii<IntType; ii++){
+	iv[ii+1] = Th.operator()(K[ii]);
+      }
+      
+      if(!bigEndian) SwapBytes((char*)&iv, sizeof(int), IntType+1);
+      fwrite(&iv, sizeof(int), IntType+1, fp);
+      
+    }
+    if(surface){
+      if(verbosity > 1) printf("writting triangle elements \n");
+      IntType=3;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	 const Triangle3 &K( Th.be(ibe) );
+      
+	 int iv[IntType+1];    
+	 iv[0] = IntType;
+	 for(int ii=0; ii<IntType; ii++){
+	   iv[ii+1] = Th.operator()(K[ii]);
+	 }
+	 
+	 if(!bigEndian) SwapBytes((char*)&iv, sizeof(int), IntType+1);
+	 fwrite(&iv, sizeof(int), IntType+1, fp);
+      }
+    }
+  }
+  else{
+    int IntType=4;
+    if(verbosity > 1) printf("writting tetrahedron elements \n");
+    for(int it=0; it< Th.nt; it++){   
+      const Tet &K( Th.elements[it] );
+
+      int iv[IntType+1];      
+      iv[0] = IntType;
+      for(int ii=0; ii<IntType; ii++){
+	iv[ii+1] = Th.operator()(K[ii]);
+      }
+      fprintf(fp,"%d %d %d %d %d\n", iv[0],iv[1],iv[2],iv[3],iv[4]);
+    }
+    if(surface){
+      if(verbosity > 1) printf("writting triangle elements \n");
+      IntType=3;
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	const Triangle3 &K( Th.be(ibe) );
+	
+	int iv[IntType+1];    
+	iv[0] = IntType;
+	for(int ii=0; ii<IntType; ii++){
+	  iv[ii+1] = Th.operator()(K[ii]);
+	}
+	
+	fprintf(fp,"%d %d %d %d\n", iv[0],iv[1],iv[2],iv[3]);
+      }
+    }
+  }
+  fprintf(fp, "\n");
+
+
+  // CELL_TYPE
+  // print element types in ascii or binary  
+  
+  fprintf(fp, "CELL_TYPES %d\n", numElements); 
+  if(binary){
+    unsigned int type;      
+    for(int it=0; it< Th.nt; it++){
+      type = VTK_TET; 
+      if(!bigEndian) SwapBytes((char*)&type, sizeof(int), 1);
+      fwrite(&type, sizeof(int), 1, fp);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	type=VTK_TRI;
+	if(!bigEndian) SwapBytes((char*)&type, sizeof(int), 1);
+	fwrite(&type, sizeof(int), 1, fp);
+      }
+    }
+  }
+  else{
+    unsigned int type;
+    for(int it=0; it< Th.nt; it++){  
+      type= VTK_TET;
+      fprintf(fp,"%d ",type);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	type=VTK_TRI;
+	fprintf(fp,"%d ",type);
+      }
+    }
+  } 
+
+  fprintf(fp, "\n");
+
+  //=================================
+  //  WRITE SOLUTION IN FORMAT VTK
+  //     LABEL OF ELEMENTS
+  //=================================
+
+  list<int> list_label_Elem;
+  //list<int> list_label_Border_Elem;
+  {
+    
+    for(int it=0; it< Th.nt; it++){
+      const Tet &K( Th.elements[it] );
+      list<int>::const_iterator ilist;
+      int labOk=0;
+      for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+	  if( *ilist == K.lab ){ labOk = 1;   break; } 
+	}
+	if( labOk == 0){
+	  list_label_Elem.push_back(K.lab);
+	}
+    }
+    
+    if(surface){
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	const Triangle3 &K( Th.be(ibe) );
+	list<int>::const_iterator ilist;
+	int labOk=0;
+	for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+	  if( *ilist == K.lab ){ labOk = 1;   break; } 
+	}
+	if( labOk == 0){
+	  list_label_Elem.push_back(K.lab);
+	}
+      
+      }
+    }
+  
+  }
+  list_label_Elem.sort();
+
+  //=================================
+  //=================================
+  
+  fprintf(fp, "CELL_DATA %d\n", numElements);
+  int cell_fd=1;
+  int cell_lab=1;
+  fprintf(fp, "Scalars  Label int%d\n", cell_fd);
+  fprintf(fp, "LOOKUP_TABLE FreeFempp_table\n"); 
+  // Determination des labels
+  if(binary){
+    int label;    
+    for(int it=0; it< Th.nt; it++){
+      const Tet &K( Th.elements[it] );
+      label =K.lab;
+      if(!bigEndian) SwapBytes((char*)&label, sizeof(int), 1);
+      fwrite(&label, sizeof(int), 1, fp);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	const Triangle3 &K( Th.be(ibe) );
+	label =K.lab;
+	if(!bigEndian) SwapBytes((char*)&label, sizeof(int), 1);
+	fwrite(&label, sizeof(int), 1, fp);
+      }
+    }
+  }
+  else{
+    int label;
+    for(int it=0; it< Th.nt; it++){ 
+      const Tet &K( Th.elements[it] );
+      label =K.lab;
+      fprintf(fp,"%d\n",label);
+    }
+    if(surface){
+      for(int ibe=0; ibe<Th.nbe; ibe++){
+	const Triangle3 &K( Th.be(ibe) );
+	label =K.lab;
+	fprintf(fp,"%d\n",label);
+      }
+    }
+  } 
+
+  fprintf(fp,"\n");
+
+  int size_list=0;
+  list<int>::const_iterator ilist;
+  for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++) size_list++;
+
+  fprintf(fp, "LOOKUP_TABLE FreeFempp_table %d\n",size_list);
+  { list<int>::const_iterator ilist;
+    for( ilist=list_label_Elem.begin(); ilist!=list_label_Elem.end(); ilist++){
+ 
+      if(binary){
+	 int tab[4];
+	 tab[0] = (int) ColorTable[abs(*ilist)%NbColorTable][0]*255;
+	 tab[1] = (int) ColorTable[abs(*ilist)%NbColorTable][1]*255;
+	 tab[2] = (int) ColorTable[abs(*ilist)%NbColorTable][2]*255;
+	 tab[3] = 255;
+	 
+	 for(int itab=0; itab<4; itab++){
+	   char newvalue[sizeof(int)];
+	   int bid0= sprintf(newvalue,"%s", (char*)&tab[itab]);
+	   fwrite( &newvalue, sizeof(unsigned char), 1, fp);
+	 }
+
+      }
+      else{
+	float tab[4];
+	tab[0] = ColorTable[abs(*ilist)%NbColorTable][0];
+	tab[1] = ColorTable[abs(*ilist)%NbColorTable][1];
+	tab[2] = ColorTable[abs(*ilist)%NbColorTable][2];
+	tab[3] = 1.0;
+
+	fprintf(fp,"%.8f %.8f %.8f %.8f\n",tab[0],tab[1],tab[2],tab[3]);
+      }
+    }
+  }
+  fprintf(fp,"\n");
+  
+}
+
+AnyType VTK_WriteMesh3_Op::operator()(Stack stack)  const 
+{
+ 
+  string * pffname= GetAny<string *>((*filename)(stack));
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  ffassert(pTh);
+  Mesh3 &Th=*pTh;
+  bool swap = false;
+  bool bigEndian = false;
+  bool binary = false;
+  bool surface = true;
+  bool floatmesh = true;
+  bool floatsol = true;
+  int datasize = sizeof(float);
+  int datasizeSol = sizeof(float);
+  string *dataname;
+  int nbofsol = l.size();
+  KN<int> order(nbofsol);
+  
+  char *nameofuser[nbofsol];
+
+  for(int ii=0; ii<nbofsol; ii++) order[ii] = 0;
+
+  if( nargs[0] ) dataname  = GetAny< string* >( (*nargs[0])(stack) );  
+  if( nargs[1] ) surface   = GetAny< bool >( (*nargs[1])(stack) );
+  if( nargs[2] ) order     = GetAny< KN_<long> >( (*nargs[2])(stack) );
+  if( nargs[3] ) floatmesh = GetAny< bool >( (*nargs[3])(stack) );
+  if( nargs[4] ) floatsol  = GetAny< bool  >( (*nargs[4])(stack) );
+  if( nargs[5] ) binary    = GetAny< bool  >( (*nargs[5])(stack) );
+  if( nargs[6] ) bigEndian = GetAny< bool  >( (*nargs[6])(stack) );
+
+  swap = bigEndian;
+
+  if( !floatmesh ) datasize = sizeof(double);
+  if( !floatsol ) datasizeSol= sizeof(double);
+
+
+  int iii=0;
+  if( nargs[0]){
+    char *data = newcopy(dataname);
+    if(verbosity>5)
+      cout << "   iovtk writeMesh3: names  \""<< data <<"\"" <<  endl;
+    char * name =strtok(data," \n\0\t");
+    nameofuser[iii] = newcopy(name);
+    if(verbosity>5)
+      cout << "   iovtk writeMesh3:value of iii=" << iii << " " << nameofuser[iii] <<endl;
+    iii++;
+    {
+      
+      while(( name= strtok(NULL," \n\0\t")) ){
+	if( iii >= nbofsol )
+	  {
+	    if(verbosity)
+	      cout << "   iovtk writeMesh3: The number of data name is too large " << endl;
+	    break;
+	  }
+	nameofuser[iii] = newcopy(name);
+	if(verbosity>5)
+	  cout << "   iovtk writeMesh3:value of iii=" << iii << " " << nameofuser[iii] <<endl;
+	iii++;
+      }
+      if( iii < nbofsol){	
+	if(verbosity)
+	cout << "   iovtk writeMesh3: The number of data name is too small, we give default name " << endl;
+      }
+      
+    }
+  }
+  if( iii < nbofsol ){
+    for( int iiii=iii; iiii<nbofsol; iiii++)
+      nameofuser[iiii] = newcopy(l[iiii].name.c_str());    
+  }
+
+  // determination of number of order 0 et 1.
+  int Norder0=0;
+  for(int ii=0; ii< nbofsol; ii++)
+    if(order[ii] == 0) Norder0++;
+
+  // lecture du nom des variables
+
+  FILE *fp = fopen( (*pffname).c_str(), "wb");
+  if(!fp){
+    cerr << "Unable to open file " << (*pffname).c_str() << endl;
+    ExecError("error in reading vtk file")  ;
+  }
+  
+  // type of VTK FILE
+  char * pch = newcopy(pffname);
+  int VTK_FILE = 0;
+  int ls = 0;
+  int lll = strlen(pch);
+  if      (!strcmp(pch+ lll - (ls=4),".vtk"))  VTK_FILE = 1;
+  else if (!strcmp(pch + lll - (ls=4),".vtu")) VTK_FILE = 2;
+  
+  if(VTK_FILE == 1){
+    VTK_WRITE_MESH3( *pffname, fp, Th, binary, datasize, surface, swap); 
+    
+    if( datasizeSol == sizeof(float) ){
+      
+      if( Norder0 >0){
+	fprintf(fp, "FIELD FieldData %d\n", Norder0);
+	for(int ii=0; ii< nbofsol; ii++){
+	  if(order[ii] == 0){
+	    int nsol;
+	    if(surface){
+	      nsol = Th.nt+Th.nbe;
+	    }
+	    else{
+	      nsol = Th.nt;
+	    }
+	    
+	    fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,nsol); 
+	    if(verbosity>5)	    
+	      cout << "   iovtk writeMesh3: name of data("<< ii <<")=" << nameofuser[ii]  << endl;
+	    
+	    // changement ecriture solution
+	    l[ii].writesolutionP0_float( fp, Th, stack, surface, binary, swap);
+	    //fprintf(fp,"\n");
+	  }
+	}
+      }
+      if( Norder0 < nbofsol )
+	{
+	  fprintf(fp, "POINT_DATA %d\n", Th.nv);
+	  fprintf(fp, "FIELD FieldData %d\n", nbofsol-Norder0);
+	  for(int ii=0; ii< nbofsol; ii++){
+	    if(order[ii] == 1)
+	      {
+		
+		fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,Th.nv); 
+		if(verbosity>5)
+		  cout << "   iovtk writeMesh3:name of data("<< ii <<")=" << nameofuser[ii]  << endl;
+		
+		// changement ecriture solution
+		l[ii].writesolutionP1_float( fp, Th, stack, binary, swap);
+	      	
+	      }
+	  }
+	}    
+    }
+    
+    if( datasizeSol == sizeof(double) ){
+    
+      if( Norder0 >0){
+	fprintf(fp, "FIELD FieldData %d\n", Norder0);
+	for(int ii=0; ii< nbofsol; ii++){
+	  if(order[ii] == 0){
+	    int nsol;
+	    if(surface){
+	      nsol = Th.nt+Th.nbe;
+	    }
+	    else{
+	      nsol = Th.nt;
+	    }
+	    
+	    fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,nsol); 
+	    if(verbosity>5)
+	      cout << "   iovtk writeMesh3:name of data("<< ii <<")=" << nameofuser[ii]  << endl;
+	    
+	    // changement ecriture solution
+	    l[ii].writesolutionP0_double( fp, Th, stack, surface, binary, swap);	   
+	  }
+	}
+      }
+      if( Norder0 < nbofsol ){
+	fprintf(fp, "POINT_DATA %d\n", Th.nv);
+	fprintf(fp, "FIELD FieldData %d\n", nbofsol-Norder0);
+	for(int ii=0; ii< nbofsol; ii++){
+	  if(order[ii] == 1){
+	    
+	    fprintf(fp,"%s %ld %d float\n",nameofuser[ii],l[ii].nbfloat,Th.nv); 
+	    if(verbosity>5)
+	      cout << "   iovtk writeMesh3:name of data("<< ii <<")=" << nameofuser[ii]  << endl;
+	    
+	    // changement ecriture solution
+	    l[ii].writesolutionP1_double( fp, Th, stack, binary, swap);	 
+
+	  }
+	}
+      }
+    }
+  }
+  else if(VTK_FILE == 2){
+    int nc,nv;
+      
+  
+   
+    VTU_WRITE_MESH( fp, Th, binary, datasize, surface, swap);
+    // Solution Order
+    // order 1
+    if( Norder0 != nbofsol){
+      BEGINTYPE_VTU( fp, "PointData");
+      for(int ii=0; ii< nbofsol; ii++){
+	if(order[ii] == 1){
+	  
+	  if(datasize == sizeof(float)){    
+	    VTU_DATA_ARRAY( fp, "Float32", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP1_float( fp, Th, stack, binary, swap,1);
+	  }
+	  else if(datasize == sizeof(double)) {
+	    VTU_DATA_ARRAY( fp, "Float64", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP1_double( fp, Th, stack, binary, swap,1);
+	  }
+	  
+	  ENDTYPE_VTU( fp, "DataArray");	   
+	}
+      }
+      ENDTYPE_VTU( fp, "PointData");
+      }
+    // order 0
+    if( Norder0 > 0 ){
+      BEGINTYPE_VTU( fp, "CellData");
+      for(int ii=0; ii< nbofsol; ii++){
+	if(order[ii] == 0){
+	  
+	  if(datasize == sizeof(float)){    
+	    VTU_DATA_ARRAY( fp, "Float32", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP0_float( fp, Th, stack, surface, binary, swap,1);
+	  }
+	  else if(datasize == sizeof(double)) {
+	    VTU_DATA_ARRAY( fp, "Float64", nameofuser[ii] , l[ii].nbfloat, binary);
+	    l[ii].writesolutionP0_double( fp, Th, stack, surface, binary, swap,1);
+	  }
+	  ENDTYPE_VTU( fp, "DataArray");
+	}
+      }
+      ENDTYPE_VTU( fp, "CellData");
+    }
+    ENDTYPE_VTU( fp, "Piece");
+    ENDTYPE_VTU( fp, "UnstructuredGrid");
+    ENDTYPE_VTU( fp, "VTKFile");
+  }
+  else{
+    cout << "extension file of VTK is not correct" << endl;
+    exit(1);
+  }
+  fclose(fp);
+  
+  for( int iiii=0; iiii<nbofsol; iiii++){
+    delete [] nameofuser[iiii];
+  }
+  delete [] pch;
+  return (Mesh3 *) NULL;
+}
+//==============================================
+// FIN ECRITURE DE FICHIER .vtk (3D)
+//==============================================
+
+//=======================
+// FIN 3D Fichier .vtk
+//=======================
+void saveMatlab(const string &file, const Mesh &Th)
+{
+  //   ErrorInsaveMesh e;
+   {
+     ofstream pf(file.c_str());
+     ffassert(pf);
+     typedef  Mesh::Element Element;
+     for(int k=0; k<Th.nt;++k)
+       {
+	 Element &K = Th[k];
+	 pf << "x = [ ";
+	 for (size_t n=0; n<3; n++)
+	   pf << std::setprecision(5) << setw(18) << K[n].x << " ";
+	 pf << std::setprecision(5) << setw(18) << K[0].x << " ]; ";
+	 pf << "y = [ ";
+	 for (size_t n=0; n<3; n++)
+	   pf << std::setprecision(5) << setw(18) << K[n].y << " ";
+	 pf << std::setprecision(5) << setw(18) << K[0].y  << " ]; ";
+	   pf << "line(x,y);" << endl;
+       }
+     pf.close();
+   }
+}
+
+void saveTecplot(const string &file, const Mesh &Th)
+{
+  string shape;
+  ofstream pf(file.c_str());
+  size_t n, m;
+  
+  pf << "TITLE = \" \"\n";
+  pf << "VARIABLES = \"X\", \"Y\"";
+  if (Th.dim==3)
+    pf << ", \"Z\"";
+  pf << endl;
+  if (Th.dim==2) {
+    m = 3;
+    shape = "TRIANGLE";
+  }
+  /*      else if (el->getShape()==LINE) {
+	  m = 2;
+	  shape = "LINESEG";
+	  }
+  */
+  
+  else if (Th.dim==3)
+	 {
+	   m = 4;
+	   shape = "TETRAHEDRON";
+	 }
+  
+  pf << "ZONE N=" << Th.nv  << ", E=" << Th.nt << ", F=FEPOINT, ET=" << shape << endl;
+  for (int i=0;i<Th.nv;i++)
+    pf << std::setprecision(5) << setw(18) << (R2) Th(i)  << " \n" ;
+  
+  
+  for (int k=0;k<Th.nt;++k)
+    {
+      for (n=0; n<m; n++)
+	pf << Th(k,n)+1  << "  ";
+      pf << endl;
+    }
+  
+  pf.close();
+}
+
+
+
+/*  class Init1 { public:
+  Init1();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  
+  typedef Mesh *pmesh;
+  //typedef Mesh2 *pmesh2;
+  typedef Mesh3 *pmesh3;
+  //if (verbosity)
+  if(verbosity) cout << " load: iovtk " << endl;
+  Global.Add("savevtk","(",new OneOperatorCode<VTK_WriteMesh_Op>);
+  Global.Add("savevtk","(",new OneOperatorCode<VTK_WriteMesh3_Op>);
+  Global.Add("vtkload3","(",new VTK_LoadMesh3);
+  Global.Add("vtkload","(",new VTK_LoadMesh);
+  
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/isoline.cpp b/examples++-load/isoline.cpp
new file mode 100644
index 0000000..cb30044
--- /dev/null
+++ b/examples++-load/isoline.cpp
@@ -0,0 +1,837 @@
+// ORIG-DATE: Novembre 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :
+// USAGE    : LGPL
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE
+// AUTHOR   : Jacques Morice, Modif par F. Hecht Dec. 2011
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/*
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01
+ */
+
+/*
+ calcul demander par F. Hecht
+ */
+
+#ifndef WITH_NO_INIT
+#include "ff++.hpp"
+#include "AFunction_ext.hpp"
+#endif
+
+
+using namespace std;
+
+#include <set>
+#include <vector>
+#include <map>
+#include <algorithm>
+//#include "msh3.hpp"
+
+using namespace  Fem2D;
+
+
+// fonction determinant les points d'intersection
+static int debug =0;
+class ISOLINE_P1_Op : public E_F0mps
+{
+public:
+    
+    Expression eTh,eff,emat,exx,eyy,exy,iso;
+    static const int n_name_param = 7; //
+    static basicAC_F0::name_and_type name_param[] ;
+    Expression nargs[n_name_param];
+    
+    double  arg(int i,Stack stack,double a) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+    long  arg(int i,Stack stack,long  a) const{ return nargs[i] ? GetAny< long  >( (*nargs[i])(stack) ): a;}
+    
+    KN<long> * arg(int i,Stack stack,KN<long> *  a) const{ return nargs[i] ? GetAny< KN<long> *  >( (*nargs[i])(stack) ): a;}
+    string * arg(int i,Stack stack,string *  a) const{ return nargs[i] ? GetAny< string  *  >( (*nargs[i])(stack) ): a;}
+    
+    
+    
+public:
+    ISOLINE_P1_Op(const basicAC_F0 &  args,Expression tth, Expression fff,Expression xxx,Expression yyy)
+    : eTh(tth),emat(0),eff(fff),exx(xxx),eyy(yyy),exy(0)
+    {
+        args.SetNameParam(n_name_param,name_param,nargs);
+    }
+    ISOLINE_P1_Op(const basicAC_F0 &  args,Expression tth, Expression fff,Expression xxyy)
+    : eTh(tth),emat(0),eff(fff),exx(0),eyy(0),exy(xxyy)
+    {
+        args.SetNameParam(n_name_param,name_param,nargs);
+    }
+    
+    AnyType operator()(Stack stack)  const ;
+};
+
+
+basicAC_F0::name_and_type ISOLINE_P1_Op::name_param[]= {
+    {  "iso", &typeid(double)},
+    {  "close", &typeid(long)},
+    {  "smoothing", &typeid(double)},
+    {  "ratio", &typeid(double)},
+    {  "eps", &typeid(double)},
+    {  "beginend", &typeid(KN<long> *  )},
+    {  "file", &typeid(string * )}
+};
+
+int IsoLineK(R2 *P,double *f,R2 *Q,int *i0,int *i1,double eps)
+{
+    
+    int kv=0,ke=0,e=3;
+    int tv[3],te[3],vk[3];
+    for(int i=0;i<3;++i)
+    {
+        if( abs(f[i]) <= eps) {
+            e -= tv[kv++]=i;
+            vk[i]=1;
+        }
+        else
+            vk[i]=0;
+    }
+    if(debug) cout << " ** " <<     kv << endl;
+    if(kv>1) //  on 2  vertex on the isoline ....
+    {
+        if(kv==2)
+        {
+            if(f[e] > 0.)
+            {
+                int j0=(e+1)%3;
+                int j1=(e+2)%3;
+                te[ke]=e+3,i0[ke]=j0,i1[ke]=j0,++ke;
+                te[ke]=e,i0[ke]=j1,i1[ke]=j1,++ke;
+                // pb d'unicity, need to see the adj triangle ...
+                //return 10+e ; // edge number + 10
+            }
+            else return 0; // skip edge ...
+            
+        }
+        else return 0; //  const funct...
+    }
+    else // see internal edge ..
+        for(int e=0;e<3;++e)
+        {
+            int j0=(e+1)%3;
+            int j1=(e+2)%3;
+            if( vk[j0]) //  the intial  point on iso line
+            {
+                if(0. < f[j1])
+                    te[ke]=e,i0[ke]=j0,i1[ke]=j0,++ke;
+                else
+                    te[ke]=e+3,i0[ke]=j0,i1[ke]=j0,++ke;
+            }
+            else if (vk[j1]); // skip the final point on iso line
+            else if( f[j0] < 0. && 0. < f[j1])  // good  sens
+                te[ke]=e,i0[ke]=j0,i1[ke]=j1,++ke;
+            else if ( f[j0] > 0. && 0. > f[j1]) // inverse  sens
+                te[ke]=e+3,i0[ke]=j1,i1[ke]=j0,++ke;
+        }
+    if( ke==2)
+    {
+        // the  K[i1[0]] , Q[0], Q[1] must be direct ...
+        // the  K[i0[1]] , Q[0], Q[1] must be direct ...
+        // Warning   no trivail case ..  make a plot to see
+        //  with is good
+        // the first edge must be
+        
+        if(te[0]<3)  // oriente the line
+	{
+            assert(te[1] >=3);
+            std::swap(te[0],te[1]);
+            std::swap(i0[0],i0[1]);
+            std::swap(i1[0],i1[1]);
+            if(debug) cout << " swap " << endl;
+	}
+        for(int i=0;i<2;++i)
+	{
+            int j0=i0[i],j1=i1[i];
+            if( j0== j1)
+                Q[i] = P[j0];
+            else
+                Q[i] = (P[j0]*(f[j1]) -  P[j1]*(f[j0]) ) /(f[j1]-f[j0]);
+            if(debug) cout << i << " " << j0 << " " << j1 << " : "
+                << Q[i] << "***" << endl;
+	}
+	if(debug)
+	{
+            cout << "i0 " << i0[0] << " " << i0[1] << " " << det(P[i1[0]],Q[0],Q[1]) <<endl;
+            cout << "i1 " << i1[0] << " " << i1[1] << " " << det(P[i0[1]],Q[1],Q[0]) <<endl;
+            cout << "f " << f[0] << " " << f[1] << " " << f[2] << endl;
+            cout << "P " << P[0] << ", " << P[1] << ", " << P[2] << endl;
+            cout << "Q " << Q[0] << ", " << Q[1]  << endl;
+	}
+	if(!vk[i1[0]])
+            assert( det(P[i1[0]],Q[0],Q[1]) > 0);
+	if(!vk[i0[1]])
+            assert( det(P[i0[1]],Q[1],Q[0]) > 0);
+	return 2;
+    }
+    // remark, the left of the line is upper .
+    return 0;
+}
+
+
+
+int LineBorder(R2 *P,double *f,long close,R2 *Q,int *i1,int *i2,double eps)
+{
+    int np=0;
+    if(close)
+    {
+        if(f[0]>-eps)
+	{
+            Q[np]=P[0];
+            i1[np]=i2[np]=0,np++;
+            
+	}
+        
+        if (f[0]*f[1] <= - eps*eps)
+	{
+            Q[np]= (P[0]*(f[1]) -  P[1]*(f[0]) ) /(f[1]-f[0]);
+            i1[np]=0,i2[np]=1,np++;
+	}
+        
+        if(f[1]>-eps)
+	{
+            Q[np]=P[1];
+            i1[np]=i2[np]=1,np++;
+	}
+        
+    }
+    else
+    {
+    }
+    return np;
+}
+struct R2_I2 {
+    R2 P;
+    int nx;
+    R2_I2(R2 A,int nxx=-1) : P(A),nx(nxx) {}
+    bool add(int k0,int k1,multimap<int,int> & L) {
+        if (nx==-1)  nx=k1;
+        else {
+            if(nx >0) {//  more than 2 seg ... put data in  the multi map ..
+                L.insert(make_pair(k0,nx));
+                L.insert(make_pair(k0,k1));
+                nx=-2;
+            }
+            else
+                L.insert(make_pair(k0,k1));
+            return false;
+        }
+        return true;}
+    
+    int next(int k0,multimap<int,int> & L,int rm=0)
+    {
+        int nxx=-1;
+        if(nx>=0) {
+            nxx=nx;
+            if(rm) nx=-2;}
+        else {
+            typedef multimap<int,int>::iterator IT;
+            IT  f= L.find(k0);
+            if(f == L.end())
+                nxx=-1; //
+            else
+            {
+                nxx = f->second;
+                if(rm)
+                    L.erase(f);
+            }
+            
+        }
+        return  nxx;
+    }
+    int count(int k0,const multimap<int,int> & L) const
+    {
+        if(nx>=0) return 1;
+        else return L.count(k0);
+    }
+};
+// Absact mesh for data on grid .... FH ..
+int Th_Grid(const KNM_<double> *g, int k,int ii)
+{
+    int N = g->N()-1;
+    int kq= k/2; // number of the quad
+    int k0 = k%2; // up or down
+    //  (0,0),(1,0),(1,1) Qd <=> (ii !=0,  ii==2)
+    //  (0,0),(1,1),(0,1) Q2  <=> (ii%2, ii != 0
+    int I =  kq%N + ( k0 ?  (ii%2)  : (ii !=0) ) ;
+    int J =  kq/N + ( k0 ?  (ii!=0) : (ii ==2) );
+
+   return J*(N+1)+I;
+}
+R2  V_Grid(const KNM_<double> *g, int k) 
+{
+  int i = k % g->N() , j = k / g->N() ; 
+  return R2( i,j);
+}
+int  EA_Grid(const KNM_<double> *g, int k,int & e) 
+{
+  int N = g->N()-1;
+  int kq= k/2; // number of the quad
+  int k0 = k%2; // up or down
+  bool intern = k0  ? (e==0)  : (e==2);
+  if(intern) {e = 2-e; return 2*kq+ 1-k0;}
+  ffassert(0);
+  return 0;
+}
+
+struct SMesh {
+  const Mesh *pTh;
+  const KNM_<double> *g;
+  int nv,nt, neb; 
+  int operator()(int k,int i) const  { return pTh ? (*pTh)(k,i) : Th_Grid(g,k,i);  }
+  R2  operator()(int i) const  { return pTh ? (*pTh)(i) : V_Grid(g,i);  }
+  int ElementAdj(int k,int &e) { return pTh ? pTh->ElementAdj(k,e) : EA_Grid(g,k,e);  }
+  SMesh(Mesh *PTh) : pTh(PTh),g(0)   , nv(pTh->nv), nt(pTh->nt),neb(pTh->neb) {}
+  SMesh(KNM_<double> *gg): pTh(0),g(gg)   ,
+			   nv(gg->N()*gg->M()),
+			   nt((gg->N()-1) *(gg->M()-1)*2),
+			   neb( ( gg->N()+gg->M()-2 )*2 ) {}
+};
+
+AnyType ISOLINE_P1_Op::operator()(Stack stack)  const
+{
+    MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+    KNM<double> * pxy=0;
+    KN<double> * pxx=0;
+    KN<double> * pyy=0;
+    if(exy)
+        pxy = GetAny<KNM<double>*>((*exy)(stack));
+    if(exx)
+        pxx = GetAny<KN<double>*>((*exx)(stack));
+    if(eyy)
+        pyy = GetAny<KN<double>*>((*eyy)(stack));
+    //  cout << pxx << " " << pyy << " " << pxy << endl;
+    ffassert( (pxx || pyy) ==  !pxy ) ;
+    Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+    ffassert(pTh);
+    SMesh Th(pTh);
+    int nbv=Th.nv; // nombre de sommet
+    int nbt=Th.nt; // nombre de triangles
+    int nbe=Th.neb; // nombre d'aretes fontiere
+    long nbc;
+    // value of isoline
+    int ka=0;
+    double isovalue = arg(0,stack,0.);
+    long close      = arg(1,stack,1L);
+    double smoothing   = arg(2,stack,0.);
+    double  ratio  = arg(3,stack,1.);
+    double  epsr    = arg(4,stack,1e-10);
+    KN<long> *pbeginend = arg(5,stack, (KN<long> *) 0);
+    string * file = arg(6,stack,(string*) 0);
+    vector< R2_I2 >  P;
+    multimap<int,int> L;
+    if(verbosity>= 1000) debug =verbosity/1000;
+    else debug = 0; 
+    map<pair<int,int>, int> FP;
+    const   double unset = -1e-100;
+    KN<double> tff(nbv, unset);
+    
+    // loop over triangle
+    if(pTh)
+    for (int it=0;it<Th.nt;++it)
+    {
+        for( int iv=0; iv<3; ++iv)
+	{
+            int i=Th(it,iv);
+            if(tff[i]==unset){
+                mp->setP(pTh,it,iv);
+                tff[i]=GetAny<double>((*eff)(stack))-isovalue;
+            }
+	}
+    }
+    else ffassert(0); 
+    if(close<0)
+    {
+        tff=-tff;
+        close=-close;
+    }
+    
+    
+    
+    double tffmax=tff.max(), tffmin=tff.min();
+    if(verbosity)
+        cout << " -- isoline close="<< close << " iso= "<< isovalue << " " << epsr << endl
+        <<      "    bound  isovalue :" << tffmin << " " << tffmax << endl;
+    double eps = (tffmax-tffmin)*epsr;
+    if( (tffmax <0.) || (tffmin > 0.)) return 0L;
+    if(epsr>0) eps = epsr;
+    ostream *fff=0;
+    if(debug>9) fff = new ofstream("g-iso");
+    for (int k=0;k<Th.nt;++k)
+    {
+        int iK[3]={Th(k,0),Th(k,1),Th(k,2)};
+        R2 Pk[3]={Th(iK[0]),Th(iK[1]),Th(iK[2]) };
+        R  fk[3]={tff[iK[0]],tff[iK[1]],tff[iK[2]] };
+        R2 Qk[6];
+        int i1[6],i2[6];
+        int np=IsoLineK(Pk,fk,Qk,i1,i2,eps);
+        if(np==2)
+	{
+            for(int i=0;i<np;++i) // sort i1,i2 ..
+            {
+	  	i1[i]=iK[i1[i]];
+	  	i2[i]=iK[i2[i]];
+	  	if(i2[i]<i1[i])
+                    std::swap(i1[i],i2[i]);
+                
+            }
+            int p[2]; // point number
+            for(int i=0;i<2;++i)
+	    {
+                pair< map<pair<int,int>, int>::iterator , bool > ii;
+                pair<int,int> e(i1[i],i2[i]);
+                ii=FP.insert(make_pair(e,P.size()));
+                if(ii.second)
+                    P.push_back(R2_I2(Qk[i]));
+                if(debug) cout << i1[i] << " ---  " << i2[i] <<" ;     " << ii.second<<  endl;
+                
+                p[i] = ii.first->second ;
+	    }
+            // add line k[0], k[1]
+            P[p[0]].add(p[0],p[1],L);
+            if(debug)
+                cout <<  " +++ " << Qk[0] << " ->  " << Qk[1] << " :: " << p[0] << " -> " << p[1] << endl;
+            if(fff) *fff << Qk[0] << "\n" << Qk[1] << "\n" << ((Qk[0]*0.4 + Qk[1]*.6)+R2(Qk[0],Qk[1]).perp()*.4) <<  "\n\n";
+            
+            
+	}
+    }
+    if(fff) delete fff;
+    if(close)
+    {
+        if(debug) cout<< " Close path " << endl;
+        for (int k=0;k<Th.nt;++k)
+	{
+	  // Triangle &K=Th[k];
+            for(int e=0;e<3;++e)
+	    {
+                int ee,kk=Th.ElementAdj(k,ee=e);
+                if( kk==k || kk<0)
+		{ // true border element edge
+                    int iK[2]={Th(k,(e+1)%3),Th(k,(e+2)%3)};
+                    R2 Pk[2]={Th(iK[0]),Th(iK[1])};
+                    R  fk[2]={tff[iK[0]],tff[iK[1]]};
+                    R2 Qk[2];
+                    int i1[2],i2[2];
+                    if(debug) cout << " LB : " << Pk[0] << ", " << fk[0] << " ->  "<< Pk[1] << ", " << fk[1]
+                        << " : " <<iK[0] << " " << iK[1]  << endl;
+                    int np=LineBorder(Pk,fk,close,Qk,i1,i2,eps);
+                    //		  cout << np << endl;
+                    if(np>=10)
+		    { // full edge
+                        int ke =  0;
+                        
+		    }
+                    else if(np==2)
+		    {
+                        for(int i=0;i<2;++i)
+			{
+                            i1[i]=iK[i1[i]];
+                            i2[i]=iK[i2[i]];
+                            if(i2[i]<i1[i])
+                                std::swap(i1[i],i2[i]);
+			}
+                        if(debug) cout << " add  : " <<  Qk[0] << ", " << i1[0] <<',' << i2[0]
+                            << " ->   " << Qk[1] << ", " << i1[1] <<',' << i2[1]<< endl;
+                        int p[2]; // point number
+                        for(int i=0;i<2;++i)
+			{
+                            pair< map<pair<int,int>, int>::iterator , bool > ii;
+                            pair<int,int> ee(i1[i],i2[i]);
+                            ii=FP.insert(make_pair(ee,P.size()));
+                            if(ii.second)
+                                P.push_back(R2_I2(Qk[i]));
+                            if(debug) cout << i1[i] << " ---  " << i2[i] <<" ;     " << ii.second<<  endl;
+                            p[i] = ii.first->second ;
+			}
+                        // add line k[0], k[1]
+                        P[p[0]].add(p[0],p[1],L);
+                        if(debug)
+                            cout <<  " +++ " << Qk[0] << " ->  " << Qk[1] << " :: " << p[0] << " -> " << p[1] << endl;
+		    }
+                    
+		}
+                
+	    }
+	}
+        if(debug) cout<< " End Close path " << endl;
+        
+    }
+    if(verbosity>99)
+    { // dump the data base
+        cout << " IsolineP1 " << endl;
+        for(int i=0;i<P.size();++i)
+            cout << "\t" <<i << " :  " <<  P[i].P << " ->  " << P[i].nx  << endl;
+        cout<< " multmap for execption " << endl;
+        for( multimap<int,int>::const_iterator i= L.begin(); i!= L.end();++i)
+            cout <<  "\t" << i->first << " -> " << i->second << endl;
+        cout<< " End multmap for execption " << endl;
+    }
+    
+    vector<int> iQ, QQ; // QQ the list of curve
+    int np= P.size();
+    KN<int> start(np);
+    start=-1;
+    int kkk=0;
+    for(int i=0;i<np;++i)
+    {
+      int nx = P[i].next(i,L,0);
+      if( nx>=0)  start[nx]=i;
+    }
+    vector<int> starting;
+    int iss=0; 
+    for( multimap<int,int>::const_iterator i= L.begin(); i!= L.end();++i)
+    {
+        starting.push_back(i->first);
+        start[i->second]=i->first;
+    }
+    
+    for(int i=0;i<np;++i)
+         if(start[i] == -1)
+             starting.push_back(i);
+    while(1)
+    {
+        ffassert(kkk++ < 100000);
+        int kk=0,k=0;
+        for(int i=0;i<np;++i) //  correction FH 18/9/2012 ....
+        {
+            kk+= P[i].count(i,L);
+            if(start[i] == -1)
+                k++;
+        }
+        if(kk==0)
+          break;
+       
+        
+	int i=-1;
+        if(iss<starting.size())
+            start[i = starting[iss++]]=-1;
+        else            
+        for(int ii=0;ii<np;++ii)
+          if(  (start[ii]>=0) ) i=ii;
+        
+        if(i<0) break;
+            {
+                if(verbosity>9)
+                    cout << "  isolineP1: start curve  = " << i << " -> " << P[i].next(i,L,0) ;
+                if(verbosity>99)
+                    cout << " (" <<  i  <<endl;
+                iQ.push_back(QQ.size());
+                QQ.push_back(i);
+                start[i]=-2;
+                int i0=i,i1=0,ie=i;
+                while(1)
+                {
+                    i1= P[i0].next(i0,L,1);
+                    if(i1<0) break;
+                    if(start[i1]<0) {
+                        if(verbosity>99)
+                            cout << " -- " << i1;
+                        QQ.push_back(i1);
+                        break;
+                    }
+                    
+                    QQ.push_back(i1);
+                    if(verbosity>99)
+                        cout << " " << i1;
+                    start[i1]=-2;
+                    i0=i1;
+                }
+ /*      do in brak          if(i1==ie) // close the path ..
+                {
+                    QQ.push_back(i1);
+                    if(verbosity>99)
+                        cout << " " << i1;
+                }
+  */
+                
+                if(verbosity>99)
+                    cout << ") "<< endl;
+                else if(verbosity>9) cout << endl;
+                iQ.push_back(QQ.size());
+                
+            }
+    }
+    // sort iQ
+    if(iQ.size()>2)
+    {
+        vector< pair<int , pair<int,int> > > sQ(iQ.size()/2);
+        for(int i=0,j=0; i<iQ.size();i+=2,++j)
+	{
+            int i0=iQ[i];
+            int i1=iQ[i+1];
+            sQ[j] = make_pair(i0-i1,make_pair(i0,i1));
+	}
+        std::sort(sQ.begin(), sQ.end());
+        for(int i=0,j=0; i<iQ.size();i+=2,++j)
+	{
+            iQ[i]   =sQ[j].second.first;
+            iQ[i+1] =sQ[j].second.second;
+	}
+    }
+    if(smoothing>0)
+    {
+        KN<R2> P1(QQ.size()),P2(QQ.size());
+        for(int i=0;i<QQ.size();++i)
+            P1[i]=  P[QQ[i]].P ;
+        
+        
+  	//  Smoothing the curve
+        double c1=1, c0=4, ct=2*c1+c0;
+        c1/=ct;
+        c0/=ct;
+        
+        
+        for(int i=0; i<iQ.size();)
+        {
+            int i0=iQ[i++];
+            int i1=iQ[i++]-1;
+            int nbsmoothing = pow((i1-i0),ratio)*smoothing;
+            if(verbosity>2)
+                cout << "     curve " << i << " size = " << i1-i0 << " nbsmoothing = " << nbsmoothing << " " << i0 << " " << i1 << endl;
+            P2=P1;
+            for( int step=0;step<nbsmoothing;++step)
+            {
+                for(int j=i0+1;j<i1;++j)
+                    P2[j] = c0*P1[j] +c1*P1[j-1] +c1*P1[j+1];
+                
+                if(QQ[i0]==QQ[i1]) // close curve
+                {
+                    int j0= i0+1; // prec
+                    int j1=  i1-1;  // next
+                    P2[i0]=P2[i1] = c0*P1[i0] +c1*P1[j0] +c1*P1[j1];
+                }
+                P1=P2;
+            }
+        }
+        
+        for(int i=0;i<QQ.size();++i)
+            P[QQ[i]].P=P1[i]   ;
+        
+    }
+    
+    if(pbeginend)
+    {
+        pbeginend->resize(iQ.size());
+        for(int i=0; i<iQ.size();++i)
+            (*pbeginend)[i]=iQ[i];
+    }
+    
+    if(pxx && pyy )
+    {
+        pxx->resize(QQ.size());
+        pyy->resize(QQ.size());
+        for(int i=0;i<QQ.size();++i)
+	{
+            int j=QQ[i];
+            (*pxx)[i]=  P[j].P.x ;
+            (*pyy)[i]=  P[j].P.y ;
+            
+	}
+    }
+    else if(pxy)
+    {
+        pxy->resize(3,QQ.size());
+        
+        
+        for(int k=0; k<iQ.size();k+=2)
+	{
+            int i0=iQ[k],i1=iQ[k+1];
+            double lg=0;
+            R2 Po=P[QQ[i0]].P;
+            for(int i=i0;i<i1;++i)
+	    {
+                int j=QQ[i];
+                (*pxy)(0,i)=  P[j].P.x ;
+                (*pxy)(1,i)=  P[j].P.y ;
+                lg += R2(P[j].P,Po).norme() ;
+                (*pxy)(2,i)=  lg; 
+                Po = P[j].P;
+	    }
+	}
+    }
+    else ffassert(0); 
+    
+    
+    nbc = iQ.size()/2; 
+    if(file) 
+    {
+        
+        ofstream fqq(file->c_str());
+        int i=0,i0,i1,n2= iQ.size(),k=0;
+        while(i<n2)
+        { 
+            k++;
+            i0=iQ[i++];
+            i1=iQ[i++];
+            //cout<< i0 << " " << i1 << endl;
+            for(int l=i0;l<i1;++l)
+            {
+                int j=QQ[l];	
+                fqq << P[j].P.x << " " << P[j].P.y << " " << k << " "<< j <<  endl;
+            }
+            fqq << endl;
+        }
+    }
+    /*
+     int err=0;
+     int pe[10];
+     for(int i=0;i< P.size();++i)
+     {
+     int pb = P[i].count(i,L);
+     if(pb) 
+     if(err<10) 
+     pe[err++]=i;
+     else
+     err++;
+     }
+     
+     if(err>0)
+     {
+     for(int i=0;i<10;i++)
+     cout << " PB point = " << pe[i] << " " << P[pe[i]].P << " odd count = " << P[pe[i]].count(pe[i],L)  << endl;
+     ffassert(0);
+     }
+     */  
+    // construction des courble 
+    
+    return nbc;
+}
+
+class  ISOLINE_P1: public OneOperator { public:  
+    typedef Mesh *pmesh;
+    int cas;
+    
+    ISOLINE_P1() : OneOperator(atype<long>(),atype<pmesh>(),atype<double>(), atype<KN<double>*>(),atype<KN<double>* >() ) ,cas(4){}
+    ISOLINE_P1(int ) : OneOperator(atype<long>(),atype<pmesh>(),atype<double>(), atype<KNM<double>*>() ),cas(3) {}
+    
+    E_F0 * code(const basicAC_F0 & args) const 
+    { 
+        if(cas==4)
+            return  new ISOLINE_P1_Op( args,
+                                      t[0]->CastTo(args[0]),
+                                      t[1]->CastTo(args[1]),
+                                      t[2]->CastTo(args[2]),
+                                      t[3]->CastTo(args[3]) ); 
+        else if(cas==3) 
+            return  new ISOLINE_P1_Op( args,
+                                      t[0]->CastTo(args[0]),
+                                      t[1]->CastTo(args[1]),
+                                      t[2]->CastTo(args[2]) ); 
+        else ffassert(0); // bug 
+    }
+    
+    
+    
+    
+    
+};
+
+
+
+R3  * Curve(Stack stack,const KNM_<double> &b,const  long &li0,const  long & li1,const double & ss)
+{
+    assert(b.N() >=3);
+    int i0=li0,i1=li1,im;
+    if(i0<0) i0=0;
+    if(i1<0) i1=b.M()-1;
+    double lg=b(2,i1);
+    R3 Q;
+    ffassert(lg>0 && b(2,0)==0.); 
+    double s = ss*lg;
+    int k=0,k1=i1;
+    while(i0 < i1-1)
+    {
+        ffassert(k++ < k1);
+        im = (i0+i1)/2;
+        if(s <b(2,im)  )
+	{ i1=im;
+	}
+        else if(s>b(2,im)  )
+	{ i0= im;
+	}
+        else {  Q=R3(b(0,im),b(1,im),0);  i0=i1=im;break;}
+    }
+    if(i0<i1)
+    {
+        ffassert(b(2,i0) <= s );
+        ffassert(b(2,i1) >= s );
+        R2 A(b(0,i0),b(1,i0));
+        R2 B(b(0,i1),b(1,i1));
+        double l1=(b(2,i1)-s);
+        double l0=s-b(2,i0);
+        Q= (l1*A + l0*B)/(l1+l0);
+    }
+    R3 *pQ = Add2StackOfPtr2Free(stack,new R3(Q));
+    // MeshPoint &mp= *MeshPointStack(stack); // the struct to get x,y, normal , value 
+    //mp.P.x=Q.x; // get the current x value
+    //mp.P.y=Q.y; // get the current y value
+    return pQ; 
+}
+double mesure(Stack stack,const KNM_<double> &b,const KN_<long> &be)
+{
+    double mes =0;
+    int nbc2 = be.N();
+    for (int k=0; k <nbc2 ;)
+    {
+        int i0= be[k++];
+        int i1= be[k++];
+         R2 A(b(0,i0),b(1,i0));
+        double mk=0;
+        for(int i=i0+1; i< i1; ++i)
+        {
+          R2 B(b(0,i-1),b(1,i-1));
+          R2 C(b(0,i),b(1,i));
+            mk += det(A,B,C);
+        }
+        if( verbosity>9) cout << " mesure: composante " << k/2 << "  mesure  " << mk/2. << endl;
+        mes += mk;
+    }
+    return mes/2.;
+}
+
+R3   * Curve(Stack stack,const KNM_<double> &b,const double & ss)
+{
+    return Curve(stack,b,-1,-1,ss);
+}
+
+
+
+void finit()
+{  
+    
+    typedef Mesh *pmesh;
+    
+    Global.Add("isoline","(",new ISOLINE_P1);
+    Global.Add("isoline","(",new ISOLINE_P1(1));
+    
+    Global.Add("Curve","(",new OneOperator2s_<R3*,KNM_<double>,double>(Curve));
+    Global.Add("Curve","(",new OneOperator4s_<R3*,KNM_<double>,long,long,double>(Curve));
+    
+    Global.Add("Area","(",new OneOperator2s_<double ,KNM_<double>,KN_<long> >(mesure));
+    
+}
+
+LOADFUNC(finit);  //  une variable globale qui serat construite  au chargement dynamique    
diff --git a/examples++-load/isoline.edp b/examples++-load/isoline.edp
new file mode 100644
index 0000000..4b3965e
--- /dev/null
+++ b/examples++-load/isoline.edp
@@ -0,0 +1,64 @@
+load "isoline"
+
+real[int,int] xy(3,1);
+int[int] be(1);
+{
+mesh Th=square(10,10);//,[x*.5,y*0.5]);
+fespace Vh(Th,P1);
+Vh u= sqrt(square(x-0.5)+square(y-0.5));
+real iso= 0.2 ;
+real[int] viso=[iso];
+plot(u,viso=viso,Th);
+
+int nbc= isoline(Th,u,xy,close=1,iso=iso,beginend=be,smoothing=0.1);
+/*
+
+  	iso =  value of the iso to compute
+	close =  close the iso line this the border (def. 0). 
+       smoothing =  nb of smoothing process =  smoothing * len curve ^ratio  
+                (def. 0.) 
+	   ratio =  (def. 1.) 
+	eps =  relative eps (see code ??)  (def 1e-10 )
+	beginend =  array to get begin end of sub line 
+	file =  filename 
+
+	remark:
+        sense  of the  isoline :  the upper part is a the left part  isoline 
+        so here : the minimiun is a 0.5,05 => the curve 1 turn in the clockwise sense 
+*/
+cout << " nb of the line  componant   = " << nbc << endl; 
+cout << " n = " << xy.m << endl; // nombre of points 
+cout << "be = " << be << endl; //  begin end of the componant
+
+// show the lines 
+for( int c=0;c<nbc; ++c) 
+{
+    int i0 = be[2*c], i1 = be[2*c+1]-1; // begin and end  the  connexe line comp. c       
+    for(int i=i0; i<= i1; ++i)
+       cout << " x = " <<  xy(0,i) << " y =  " << xy(1,i) << " s =  " << xy(2,i) << endl; 
+    plot([xy(0,i0:i1),xy(1,i0:i1)],wait=1,viso=viso,cmm = " curve "+c);
+}
+}
+
+cout << " len of the curve 1 = " << xy(2,xy.m-1) << endl;; 
+
+
+border Curve0(t=0,1) 
+{ int c =0; 
+  int i0 = be[2*c], i1 = be[2*c+1]-1;   
+  P=Curve(xy,i0,i1,t); 
+  label=1; 
+} 
+
+border Curve1(t=0,1) 
+{ int c =1; 
+  int i0 = be[2*c], i1 = be[2*c+1]-1;   
+  P=Curve(xy,i0,i1,t); 
+  label=1; 
+} 
+
+plot(Curve1(100)); 
+mesh Th= buildmesh(Curve1(-100));
+plot(Th,wait=1);
+
+
diff --git a/examples++-load/isolineP1.cpp b/examples++-load/isolineP1.cpp
new file mode 100644
index 0000000..282ae81
--- /dev/null
+++ b/examples++-load/isolineP1.cpp
@@ -0,0 +1,895 @@
+// ORIG-DATE: Novembre 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+/*
+calcul demander par F. Hecht
+*/
+
+#ifndef WITH_NO_INIT
+#include "ff++.hpp"
+#endif
+
+//  TransfoMesh_v2.cpp
+using namespace std;
+// LayerMesh.cpp
+// buildlayer.cpp
+// rajout global
+
+#include <set>
+#include <vector>
+//#include "msh3.hpp"
+
+using namespace  Fem2D;
+
+
+// fonction determinant les points d'intersection
+class ISOLINE_P1_Op : public E_F0mps 
+{
+public:
+  Expression eTh,filename,ff;
+  static const int n_name_param = 1; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+
+  double  arg(int i,Stack stack,double a) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+ 
+public:
+  ISOLINE_P1_Op(const basicAC_F0 &  args,Expression tth, Expression fff) 
+    : eTh(tth), filename(fff)
+  {
+    args.SetNameParam(n_name_param,name_param,nargs);
+ 
+    if (  BCastTo<double>(args[2])  )
+      {	 
+	ff=to<double>( args[2] );  
+      }
+    else {ffassert(0);
+      // ErrorCompile("no function to isolines \n");
+    }    
+    if( !nargs[0]) ffassert(0); 
+      //   ErrorCompile("no isolines selected \n");
+  } 
+    
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type ISOLINE_P1_Op::name_param[]= {
+  {  "iso", &typeid(double)}
+};
+
+AnyType ISOLINE_P1_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  string * ffname= GetAny<string *>( (*filename)(stack) );
+  ffassert(pTh);
+  Mesh &Th=*pTh;
+  Mesh *m= pTh;   // question a quoi sert *m ??
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int nbe=Th.neb; // nombre d'aretes fontiere
+  long valsortie;
+  // value of isoline
+  double isovalue;
+  isovalue = GetAny< double >( (*nargs[0])(stack) ); 
+
+  // evaluation de la fonction aux sommets
+  KN<int> takevertex(Th.nv);
+  KN<double> tff(Th.nv);
+
+  MeshPoint *mp3(MeshPointStack(stack)); 
+  
+  takevertex=0;
+  // loop over triangle 
+  for (int it=0;it<Th.nt;++it){
+    for( int iv=0; iv<3; ++iv){
+      int i=Th(it,iv);  
+      
+      if(takevertex[i]==0){
+	mp3->setP(&Th,it,iv);
+	tff[i]=GetAny<double>((*ff)(stack));
+	takevertex[i] = takevertex[i]+1;
+      }
+      
+    }
+  }
+
+  
+  // calcul des isolines dans les triangles
+  KN<double> EdgeIter(3*Th.nt);
+  KN<int> taketriangle(2*Th.nt);
+  
+  for(int ii=0; ii< 3*Th.nt; ii++){
+    EdgeIter[ii] = -1;
+  }
+  for(int ii=0; ii< 2*Th.nt; ii++){
+    taketriangle[ii] = -1;
+  }
+  
+  int VertexIso[Th.nv];
+  int VertexIsoTri[2*Th.nv];
+
+  for(int ii=0; ii< Th.nv; ii++)
+    VertexIso[ii] = 0;
+  
+  for(int ii=0; ii< 2*Th.nv; ii++)
+    VertexIsoTri[ii] = 0;
+
+  int NbIsoVertex    = 0;
+  int NbIsoNonVertex = 0;
+
+  for(int it=0; it< Th.nt; it++){
+    const  Mesh::Triangle & K(Th.t(it));
+
+    int nkeq[3];
+    int ivertex = 0;
+    int mark[3];
+
+    int im=0;
+    for(int ii=0; ii<3; ii++){ 
+      int j0,j1;
+      nkeq[ii] = 0;
+      mark[ii] = 0;
+      Th.VerticesNumberOfEdge( K, ii, j0, j1); 
+      //cout << "it=" << it << " ii= " << ii << " j0= " << j0 << "j1= " << j1 << endl;
+
+      double fi = tff[j0];
+      double fj = tff[j1];
+      double xf = isovalue;
+
+      if( Abs( tff[j0]- isovalue) < 1.e-11*(Abs(isovalue)+Abs(tff[j0])) ) {
+	nkeq[ii] = 1;
+	mark[ii] = 1;
+	EdgeIter[3*it+ii] =0.;
+	ivertex++; 
+      }
+      else{
+	if( Abs( tff[j1]- isovalue) < 1.e-11*(Abs(isovalue)+Abs(tff[j1])) ) {
+	  mark[(ii+1)%3] = 1;
+	}
+	else
+	  if( ((fi <= xf)&&(fj>=xf)) || ((fi>=xf)&&(fj<=xf)) ){
+	    int eo;
+	    eo=ii;
+	    int ito=Th.ElementAdj(it,eo);
+	    
+	    mark[ii] = 1;
+	    im++;
+	    
+	    double xlam = (fi-xf)/(fi-fj);
+	   
+	    if(ito<0){
+	      EdgeIter[3*it+ii] = xlam;	     
+	      NbIsoNonVertex++;
+	    }
+	    else if( 3*it+ii <= 3*ito+eo || it == ito  ){
+	      EdgeIter[3*it+ii] = xlam;	     
+	      NbIsoNonVertex++;
+	    }       
+	    
+	    if(it <=10 && verbosity>10) cout << "vertex (it="<< it << ", i="<< ii << ") :: " << j0 << " " << j1 <<" xlam= "<< xlam << endl;
+	  }
+
+      }
+    }
+    if( ivertex == 3){
+      cerr << " A triangle is a isovalue " << endl;
+      exit(1);
+    }
+
+    else if( ivertex == 2){
+      //*  search positive triangle *//
+      // deux possibilit�s
+      for(int iii=0;iii<3;iii++){
+	if( nkeq[iii] != 1 ){
+	  int j0,j1;
+	  Th.VerticesNumberOfEdge( K, iii, j0, j1); 
+	  R fi = tff[ j0 ];
+
+	  if(  fi > isovalue ){
+	     for(int i=0;i<3;i++) // for the  3 edges 
+	       {		 
+		 if( mark[i] == 1 && mark[(i+1)%3] == 1 ){
+		   int jj0,jj1;
+		   Th.VerticesNumberOfEdge( K, i, jj0, jj1); 
+
+		   taketriangle[2*it+1] = i;
+		   taketriangle[2*it] = (i+1)%3;
+		   
+		   VertexIso[ jj0 ]++;
+		   VertexIso[ jj1 ]++;
+		   
+		   if( VertexIso[ jj0 ] > 2 || VertexIso[ jj1 ] > 2 )
+		     cerr << " error:the iso value pass  is connected to more then 2 iso vertices " << endl;
+		   else{
+		     VertexIsoTri[ 2*jj0+VertexIso[ jj0 ] -1 ] = it;
+		     VertexIsoTri[ 2*jj1+VertexIso[ jj1 ] -1 ] = it;
+		   }
+		     
+		 }
+	       }
+	     
+	   }
+	}
+      }
+    }
+    else if( im == 1 && ivertex == 1){
+      for(int i=0;i<3;i++) // for the  3 edges 
+	{
+	  if( mark[i] == 1 && mark[(i+1)%3] == 1 ){
+	    int jj0,jj1;
+	    Th.VerticesNumberOfEdge( K, i, jj0, jj1);
+	    
+	    // determination
+	    if(1==nkeq[i]){
+	      EdgeIter[3*it+i] = 0.;
+	      VertexIso[ jj0 ]++;
+	      if( VertexIso[ jj0 ] > 2 )
+		cerr << " error:the iso value pass  is connected to more then 2 iso vertices " << endl;
+	      else{
+		VertexIsoTri[ 2*jj0+VertexIso[ jj0 ] -1 ] = it;
+	      }
+	    }
+	    else{
+	      EdgeIter[3*it+(i+1)%3] = 0.;
+	      VertexIso[ jj1 ]++;	
+	      if( VertexIso[ jj1 ] > 2 )
+		cerr << " error:the iso value pass  is connected to more then 2 iso vertices " << endl;
+		else{
+		  VertexIsoTri[ 2*jj1+VertexIso[ jj1 ] -1 ] = it;
+		}
+	    }
+	    int jj00,jj10;
+	    Th.VerticesNumberOfEdge( K, (i+2)%3, jj00, jj10);
+	    R fi2 = tff[ jj00 ];
+	    
+	    if( fi2 > isovalue ){
+	      taketriangle[2*it]   = (i+1)%3;
+	      taketriangle[2*it+1] = i;
+	    }
+	    else{
+	      taketriangle[2*it]   = i;
+	      taketriangle[2*it+1] = (i+1)%3;
+	    }
+	    
+	  
+
+	  }
+	}
+      
+    }
+    else if( im == 2){
+      
+      for(int i=0;i<3;i++) // for the  3 edges 
+	{
+	  
+	  if( mark[i] == 1 && mark[(i+1)%3] == 1 ){
+	    int jj0,jj1;
+	    Th.VerticesNumberOfEdge( K, i, jj0, jj1); 
+	    R fi1 = tff[ jj0 ];
+	   
+	    if( it < 10 )  cout << "vertex (it="<< it << ", i="<< i << ") :: " << jj0 << " " << jj1 << endl;
+	    if( fi1 > isovalue ){
+	      taketriangle[2*it]   = (i+1)%3;
+	      taketriangle[2*it+1] = i;
+	    }
+	    else{
+	      taketriangle[2*it]   = i;
+	      taketriangle[2*it+1] = (i+1)%3;
+	    }
+	    
+	    
+	    Th.VerticesNumberOfEdge( K, (i+1)%3, jj0, jj1); 	    
+	    if( it < 10 ) cout << "vertex (it="<< it << ", i="<< (i+1)%3 << ") :: " << jj0 << " " << jj1 << endl;
+
+	  }
+	}
+    }
+    
+    
+    
+  }
+ 
+  
+  //#################################  
+  int NbInterBord=0;
+  KN<int> ElementLink(Th.nt+Th.neb);
+  for(int it=0; it< Th.nt+Th.neb; it++)
+    ElementLink[it]=-1;
+
+  
+  for(int it=0; it< Th.nt; it++){
+    if( taketriangle[2*it] < 0 ) continue;
+
+    const  Mesh::Triangle & K(Th.t(it));
+    
+
+    int ii  = 2*it;
+    int eT1 = taketriangle[2*it];
+    int eT2 = taketriangle[2*it+1];
+    int eo1 = eT1;
+    int eo2 = eT2;
+    int adjeT1 = Th.ElementAdj(it,eo1);
+    int adjeT2 = Th.ElementAdj(it,eo2);
+    
+    /*
+      if( VertexIso[ numv ] == 2 ){     
+      if( VertexIsoTri[ 2*numv ] == it  ){
+      newit = VertexIsoTri[ 2*numv+1 ];
+      }
+      else 
+      newit = VertexIsoTri[ 2*numv ];
+      }
+    */
+    
+    // link with previous element 
+    {
+      int jj00,jj10;
+      Th.VerticesNumberOfEdge( K, eT1, jj00, jj10);
+      
+      int numv=jj00;
+      //cout << "eT1, jj00, jj10 " << eT1 << " " << jj00 << " " << jj10 << " VertexIso[ numv ] "<< VertexIso[ numv ] << endl;
+
+      if( VertexIso[ numv ] == 2 ){     
+	if( VertexIsoTri[ 2*numv ] == it  ){
+	  ElementLink[ VertexIsoTri[ 2*numv+1 ] ] = it;
+	  //newit = VertexIsoTri[ 2*numv+1 ];
+	}
+	else 
+	  ElementLink[ VertexIsoTri[ 2*numv] ] = it;
+	//newit = VertexIsoTri[ 2*numv ];
+      }
+      else if( VertexIso[ numv ] == 1 ){	
+	if(adjeT1 >= 0 && it!=adjeT1 ){
+	  
+	  // search the edge of it in the border
+	  int eT3 = 3-eT1-eT2;
+	  int eo3 = eT3;
+	  int adjeT3 = Th.ElementAdj(it,eo3);
+	  
+	  if(adjeT3 < 0 || it==adjeT3 ){
+	    int jj000,jj100;
+	    Th.VerticesNumberOfEdge( K, eT3, jj000, jj100);  
+	    cout << " bug une iso vertex definis une fois doit etre sur le bord ::  vertex " << numv << endl;
+	    int ibeV = Th.NumberOfTheBoundaryEdge(jj000,jj100); // old
+	 
+	    ElementLink[ ibeV+Th.nt ] = it;
+	    //NbInterBord++;
+	  }
+	  //exit(1);
+	}
+	else{
+	  // border 
+	  // int ibeV = Th.BorderElementAdj( jj00, jj10); //old
+	  int ibeV = Th.NumberOfTheBoundaryEdge( jj00, jj10);
+	  ElementLink[ibeV+Th.nt] = it;
+	  //NbInterBord++;
+	}
+      
+      }
+      else
+	if(adjeT1 >= 0 && it!=adjeT1 ){
+	  ElementLink[adjeT1] = it;
+	}
+	else{
+	  // border 
+	  int ibeV = Th.NumberOfTheBoundaryEdge(jj00,jj10);
+	  //ElementLink[Th.NumberOfTheBoundaryEdge(jj00,jj10)+Th.nt] = it; // old
+	  ElementLink[ibeV+Th.nt] = it;
+	  //NbInterBord++;
+	}
+    }
+    // link with the next element
+    {
+      int jj00,jj10;
+      Th.VerticesNumberOfEdge( K, eT2, jj00, jj10);     
+      int numv=jj00;
+
+      if( VertexIso[ numv ] == 2 ){     
+	if( VertexIsoTri[ 2*numv ] == it  ){
+	  ElementLink[ it ] = VertexIsoTri[ 2*numv+1 ];
+	  //newit = VertexIsoTri[ 2*numv+1 ];
+	}
+	else 
+	  ElementLink[ it ] = VertexIsoTri[ 2*numv];
+	//newit = VertexIsoTri[ 2*numv ];
+      }
+      else if( VertexIso[ numv ] == 1 ){
+	
+	if(adjeT2 >= 0 && it!=adjeT2 ){
+
+	  // search the edge of it in the border
+	  int eT3 = 3-eT1-eT2;
+	  int eo3 = eT3;
+	  int adjeT3 = Th.ElementAdj(it,eo3);
+	  
+	  if(adjeT3 < 0 || it==adjeT3 ){
+	    int jj000,jj100;
+	    Th.VerticesNumberOfEdge( K, eT3, jj000, jj100);  
+	    cout << " bug une iso vertex definis une fois doit etre sur le bord ::  vertex " << numv << endl;
+	    int ibeV = Th.NumberOfTheBoundaryEdge(jj000,jj100); // old
+	 
+	    ElementLink[ it ] = ibeV+Th.nt;
+	    NbInterBord++;
+	  }
+	  //exit(1);
+	}
+	else{
+	  // border 
+	  int ibeV = Th.NumberOfTheBoundaryEdge(jj00,jj10); // old
+	  //int ibeV =  Th.BorderElementAdj( jj00, jj10);
+	  ElementLink[ it ] = ibeV+Th.nt;
+	  NbInterBord++;
+	}
+      
+      }
+      else{
+	if(adjeT2 >= 0 && it!=adjeT2) 
+	  ElementLink[it] = adjeT2;
+	else{
+	  // border
+	  int ibeV = Th.NumberOfTheBoundaryEdge(jj00,jj10);
+	  ElementLink[it] = ibeV+Th.nt;
+	  // ElementLink[it] = Th.BorderElementAdj( jj00, jj10)+Th.nt; // old
+	  NbInterBord++;
+	}
+
+      //for(int iijj=0; iijj<10; iijj++){
+      //cout << "ElementLink["<< iijj <<"]=" << ElementLink[iijj] <<endl;
+      //}
+      }
+    }
+    /*
+      if(adjeT2 >= 0 && it!=adjeT2) 
+      ElementLink[it] = adjeT2;
+      else{
+      // border
+      const  Mesh::Triangle & K(Th.t(it));
+      int jj00,jj10;
+      Th.VerticesNumberOfEdge( K, taketriangle[ii], jj00, jj10);
+      ElementLink[it] = Th.TheBoundaryEdge(jj00,jj10)+Th.nt;
+      //NbInterBord++;
+      }
+    */
+  }
+ 
+
+  int NbBordVertex=0;
+  if(verbosity>10)cout << " NbInterBord = " << NbInterBord << endl;
+  if(NbInterBord>0){
+    //#################################
+    // boucle sur le bord    
+    // determination des points sur le bord  
+     
+    for(int ii=0; ii < Th.neb; ii++){
+      // determination du sens du bord
+      int edgebid;
+      int ffbid   = Th.BoundaryElement( ii, edgebid );     // ii : number of edge => sortie :: ffbid = numero triangles, edgebid = numero edges
+      int j0bid,j1bid;
+      Th.VerticesNumberOfEdge( Th.t(ffbid), edgebid, j0bid, j1bid);
+      // j0bid --> j1bid sens de parcours sur le triangle
+      double fi = tff[j0bid];
+      double fj = tff[j1bid];
+      double xf = isovalue;
+
+      // sens fi -> fj (same as local triangle) 
+ 
+      //  fi++ et fj++  ==> lien ibe ++ next border
+      //  fi==0 et fjj++ ==> lien triangle contenant cette vertex ++ vers next border
+      //  fj==0 et fi++  ==> lien ibe vers triangle contenant cette vertex
+      //  fi==0 et fj==0 ==> lien triangle contenant cette vertex vers - next bord  ( fjj >= 0 )
+      //                                                               - triangle contenant cette vertex (fjj < 0)
+
+      if( VertexIso[ j0bid ] > 0 ){	
+	// cas fi == isovalue
+	if( VertexIso[ j1bid ] > 0 ){     
+	  if(verbosity>10)cout << "the edge is a isovalue :: link is previously computed "<< endl;
+	  //assert( VertexIso[ j0bid ] == 2);
+	  //assert( VertexIso[ j1bid ] == 2);
+	}
+	else if( fj >=  isovalue){
+	  // cas fi iso  fj++
+	  //assert( VertexIso[ j0bid ] == 2);
+	  if( VertexIso[ j0bid ] == 2 ){
+	    if( VertexIsoTri[2*j0bid] == ffbid ){
+	      //ElementLink[ VertexIsoTri[2*j0bid+1] ] = Th.nt + Th.BorderElementAdj(j1bid,j0bid); // old orientation 
+	      ElementLink[  Th.nt + Th.NumberOfTheBoundaryEdge(j0bid,j1bid) ] = VertexIsoTri[2*j0bid+1];
+	    }
+	    else{
+	      //ElementLink[ VertexIsoTri[2*j0bid] ] = Th.nt + Th.BorderElementAdj(j1bid,j0bid);  // old orientation 
+	      ElementLink[  Th.nt + Th.NumberOfTheBoundaryEdge(j0bid,j1bid) ] = VertexIsoTri[2*j0bid];
+	    }
+	    NbBordVertex++;
+	  }
+	  if( VertexIso[ j0bid ] == 1 ){
+	    if(verbosity>10) cout << "j0bid, j1bid, ffbid " << j0bid << " "<< j1bid << " " << ffbid << endl; 
+	    //assert( VertexIsoTri[2*j0bid] == ffbid );
+	    //if( VertexIsoTri[2*j0bid] == ffbid ){
+	    ElementLink[  Th.nt + Th.NumberOfTheBoundaryEdge(j0bid,j1bid) ] = VertexIsoTri[2*j0bid];
+	    //}
+	    NbBordVertex++;
+	  }
+	}
+      }
+      else if( fi >=  isovalue){
+	// cas fi == isovalue++
+	if( VertexIso[ j1bid ] > 0 ){
+	  assert( VertexIso[ j1bid ] == 1);
+	  // ElementLink[ ii+Th.nt ] = VertexIsoTri[2*j1bid]; // old version
+	  ElementLink[ VertexIsoTri[2*j1bid] ] = ii+Th.nt;
+	  ElementLink[ ii+Th.nt ] = Th.BorderElementAdj(j0bid,j1bid)+Th.nt;
+	}
+	else if( fj >=  isovalue){
+	  //ElementLink[ii+Th.nt] = Th.nt + Th.BorderElementAdj(j1bid,j0bid); // old orientation
+	  ElementLink[ii+Th.nt] = Th.nt + Th.BorderElementAdj(j0bid,j1bid);
+	  NbBordVertex++;
+	}
+	//old version ::
+	else{
+	  ElementLink[ii+Th.nt] = Th.nt + Th.BorderElementAdj(j0bid,j1bid);
+	  NbBordVertex++;
+	}
+      }
+
+      /*
+	if( fi >=  isovalue && Abs( fi - isovalue) > 1.e-11*(Abs(isovalue)+Abs(fi)) ){
+	if( fj >= isovalue && Abs( fj - isovalue) > 1.e-11*(Abs(isovalue)+Abs(fj)) ){
+	ElementLink[ii+Th.nt] = Th.nt + Th.BorderElementAdj(ii,j0bid,j1bid);
+	}
+	
+	NbBordVertex++;
+	}
+      */
+    }
+    
+    // rappel: le lien a �t� effectuer entre les bords
+    //   -1 : pas de suivant
+    //   positive et nulle : le suivant border element
+    //   -2 : pas d'�lement � prendre en compte. 
+  }
+
+  if(verbosity>10)
+    {
+      cout << " NbInterBord = " << NbInterBord << endl;
+      for(int iijj=0; iijj<10; iijj++){
+	cout << "ElementLink["<< iijj <<"]=" << ElementLink[iijj] <<endl;
+      }
+      
+      cout << " NbInterBord = " << NbInterBord << endl;
+      for(int iijj=Th.nt; iijj<Th.nt+Th.neb; iijj++){
+	cout << "ElementLink["<< iijj <<"]=" << ElementLink[iijj] <<endl;
+      }
+    }
+
+  //#################################
+
+  int NbVertex=NbIsoNonVertex+NbBordVertex;
+  for(int i=0; i< Th.nv; i++){
+    if( VertexIso[i] > 0) 
+      NbVertex++;
+  }
+  
+  Vertex *VertexIsoP = new Vertex[NbVertex];
+  
+  KN<int> TriangleVu(Th.nt);
+  for(int iii=0; iii< Th.nt; iii++)
+    TriangleVu[iii]= -1;
+
+  int inv = 0;
+  int label = 0;
+  for(int it1=0; it1< Th.nt; it1++){
+    if( TriangleVu[it1] == 1 || taketriangle[2*it1]== -1) continue;
+    if(verbosity>10) cout << "it1 = " << it1 << " Th.nt "<< Th.nt << endl;
+    // First point is taken
+    TriangleVu[it1] = 1;
+    {
+      const  Mesh::Triangle & K(Th.t(it1));
+      int ii = 2*it1;
+      int eT1 = taketriangle[ii];
+      int eT2 = taketriangle[ii+1];   
+      assert(eT1>=0);
+      assert(eT2>=0);
+      int jj00,jj10;
+      Th.VerticesNumberOfEdge( K, eT1, jj00, jj10);
+      
+      if( EdgeIter[3*it1+eT1] > -0.1){ 
+	double xlam = EdgeIter[3*it1+eT1] ;
+	
+	VertexIsoP[inv].x   = (1-xlam)*Th.vertices[ jj00 ].x + xlam*Th.vertices[ jj10 ].x; 
+	VertexIsoP[inv].y   = (1-xlam)*Th.vertices[ jj00 ].y + xlam*Th.vertices[ jj10 ].y;
+	VertexIsoP[inv].lab = label;
+	
+	inv++;
+      }
+      else{
+	int eo1;
+	eo1=eT1;
+	int ito1=Th.ElementAdj(it1,eo1);
+	
+	double xlam = EdgeIter[3*ito1+eo1];
+	VertexIsoP[inv].x   = xlam*Th.vertices[ jj00 ].x + (1-xlam)*Th.vertices[ jj10 ].x; 
+	VertexIsoP[inv].y   = xlam*Th.vertices[ jj00 ].y + (1-xlam)*Th.vertices[ jj10 ].y;
+	VertexIsoP[inv].lab = label;
+	inv++;
+      }
+    }
+    
+    int it2=ElementLink[it1];
+      
+    for( int it=it2; it != it1; it=ElementLink[it]){   
+      assert(it >=0);
+     
+      if( it< Th.nt){
+	// sur un triangle
+	if(verbosity>10) cout << "it = " << it << " <--->  it2=" << it2 << " Th.nt "<< Th.nt << endl;
+	assert( TriangleVu[it] == -1);  
+	TriangleVu[it] = 1;
+
+	int ii = 2*it;
+	int eT1 = taketriangle[ii];
+	assert( eT1 >=0);
+	//int eT2 = taketriangle[ii+1];
+	const  Mesh::Triangle & K(Th.t(it));
+	int jj00,jj10;
+	Th.VerticesNumberOfEdge( K, eT1, jj00, jj10);
+	
+	if( EdgeIter[3*it+eT1] > -0.1){ 
+	  double xlam = EdgeIter[3*it+eT1] ;
+	  
+	  VertexIsoP[inv].x   = (1-xlam)*Th.vertices[ jj00 ].x + xlam*Th.vertices[ jj10 ].x; 
+	  VertexIsoP[inv].y   = (1-xlam)*Th.vertices[ jj00 ].y + xlam*Th.vertices[ jj10 ].y;
+	  VertexIsoP[inv].lab = label;
+	  
+	  inv++;
+	}
+	else{
+	  int eo1;
+	  eo1=eT1;
+	  assert( eo1 >=0);
+	  int ito1=Th.ElementAdj(it,eo1);
+	  
+	  double xlam = EdgeIter[3*ito1+eo1];
+	  VertexIsoP[inv].x   = xlam*Th.vertices[ jj00 ].x + (1-xlam)*Th.vertices[ jj10 ].x; 
+	  VertexIsoP[inv].y   = xlam*Th.vertices[ jj00 ].y + (1-xlam)*Th.vertices[ jj10 ].y;
+	  VertexIsoP[inv].lab = label;
+	  inv++;
+	}
+	 
+      }
+      else{
+	int ibe=it-Th.nt;
+	if(verbosity>10) cout << "ibe = " << ibe << " <--->  it2=" << it2 << " Th.nt "<< Th.nt << endl;
+	// sur le bord
+	int edgebid;
+	//int newit;
+	int ffbid   = Th.BoundaryElement( ibe, edgebid );     // ii : number of edge => sortie :: ffbid = numero triangles, edgebid = numero edges
+	int j0bid,j1bid;
+	Th.VerticesNumberOfEdge( Th.t(ffbid), edgebid, j0bid, j1bid);
+	if(verbosity>10) cout << "Edge Vertex Number "<< j0bid+1 << " " << j1bid+1 << " number of triangle " << ffbid << endl;
+	if( taketriangle[2*ffbid+1] == edgebid && VertexIso[j1bid] == 0){
+	  //if( taketriangle[2*ffbid+1] == edgebid && VertexIso[j0bid] == 0){ // old version
+	  if( EdgeIter[3*ffbid+edgebid] > -0.1){ 
+	    double xlam = EdgeIter[3*ffbid+edgebid] ;
+	    
+	    VertexIsoP[inv].x   = (1-xlam)*Th.vertices[ j0bid ].x + xlam*Th.vertices[ j1bid ].x; 
+	    VertexIsoP[inv].y   = (1-xlam)*Th.vertices[ j0bid ].y + xlam*Th.vertices[ j1bid ].y;
+	    VertexIsoP[inv].lab = label;
+	    
+	    inv++;
+	  }
+	  else{
+	    int eo1;
+	    eo1=edgebid;
+	    int ito1=Th.ElementAdj(ffbid,eo1);
+	    
+	    double xlam = EdgeIter[3*ito1+eo1];
+	    VertexIsoP[inv].x   = xlam*Th.vertices[ j0bid ].x + (1-xlam)*Th.vertices[ j1bid ].x; 
+	    VertexIsoP[inv].y   = xlam*Th.vertices[ j0bid ].y + (1-xlam)*Th.vertices[ j1bid ].y;
+	    VertexIsoP[inv].lab = label;
+	    inv++;
+	  }
+	  
+	}
+	else{
+	  // old  version j0bid � la place de j1bid
+	  VertexIsoP[inv].x   = Th.vertices[ j1bid ].x;
+	  VertexIsoP[inv].y   = Th.vertices[ j1bid ].y;
+	  VertexIsoP[inv].lab = label;
+	  inv++;
+	}
+	
+      }
+    }
+    label++;
+  }
+  
+
+//   int TriangleVu[Th.nt];
+//   for(int iii=0; iii< Th.nt; iii++)
+//     TriangleVu[iii]= -1;
+//   int label = 0;
+//   int inv  = 0;
+
+//   Vertex *VertexIsoP = new Vertex[NbVertex];
+  
+//   for(int it1=0; it1< Th.nt; it1++){
+//     if( taketriangle[2*it1] < 0  || TriangleVu[it1] == 1 ) continue;
+
+//     int it =it1;
+//     do {
+      
+//       const  Mesh::Triangle & K(Th.t(it));
+
+//       TriangleVu[it] = 1;
+     
+//       int ii = 2*it;
+//       int eT1 = taketriangle[ii];
+//       int eT2 = taketriangle[ii+1];
+      
+//       int jj00,jj10;
+//       Th.VerticesNumberOfEdge( K, eT1, jj00, jj10);
+      
+//       if( EdgeIter[3*it+eT1] > -0.1){ 
+// 	double xlam = EdgeIter[3*it+eT1] ;
+	
+// 	VertexIsoP[inv].x   = (1-xlam)*Th.vertices[ jj00 ].x + xlam*Th.vertices[ jj10 ].x; 
+// 	VertexIsoP[inv].y   = (1-xlam)*Th.vertices[ jj00 ].y + xlam*Th.vertices[ jj10 ].y;
+// 	VertexIsoP[inv].lab = label;
+
+// 	inv++;
+//       }
+//       else{
+// 	cerr << "bug in definition of vertex" << endl; 
+// 	int eo1;
+// 	eo1=eT1;
+// 	int ito1=Th.ElementAdj(it,eo1);
+	
+// 	double xlam = EdgeIter[3*ito1+eo1];
+// 	VertexIsoP[inv].x   = xlam*Th.vertices[ jj00 ].x + (1-xlam)*Th.vertices[ jj10 ].x; 
+// 	VertexIsoP[inv].y   = xlam*Th.vertices[ jj00 ].y + (1-xlam)*Th.vertices[ jj10 ].y;
+// 	VertexIsoP[inv].lab = label;
+// 	inv++;
+//       }
+      
+//       // on passe a eT2
+//       int newit;
+//       Th.VerticesNumberOfEdge( K, eT2, jj00, jj10);
+//       int numv  =  jj00;
+      
+//       if( VertexIso[ numv ] == 2 ){     
+// 	if( VertexIsoTri[ 2*numv ] == it  ){
+// 	  newit = VertexIsoTri[ 2*numv+1 ];
+// 	}
+// 	else 
+// 	  newit = VertexIsoTri[ 2*numv ];
+//       }
+//       else if( VertexIso[ numv ] == 1 ){     
+// 	newit = -1;
+//       }
+//       else{
+// 	int eo;
+// 	eo=eT2;
+// 	int ito=Th.ElementAdj(it,eo);
+	 	
+// 	if( (ito != it && taketriangle[2*ito] >= 0 ) && it >= 0){ 
+// 	  newit = ito; 
+// 	  if( taketriangle[2*ito] != eo){	    
+// 	    exit(1);
+// 	  }
+// 	}
+// 	else
+// 	  newit = -1;
+//       }         
+//       if( newit < 0 ){
+// 	 Th.VerticesNumberOfEdge( K, eT2, jj00, jj10);
+      
+// 	 if( EdgeIter[3*it+eT2] > -0.1){ 
+// 	   double xlam = EdgeIter[3*it+eT2] ;
+// 	   //cout << "vertex (it="<< it << ", eT1="<< eT1 << ") :: " << jj00 << " " << jj10 << endl; 
+// 	   VertexIsoP[inv].x   = (1-xlam)*Th.vertices[ jj00 ].x + xlam*Th.vertices[ jj10 ].x; 
+// 	   VertexIsoP[inv].y   = (1-xlam)*Th.vertices[ jj00 ].y + xlam*Th.vertices[ jj10 ].y;
+// 	   VertexIsoP[inv].lab = label;
+	  
+// 	   inv++;
+// 	 }
+// 	 else{
+// 	   //cerr << "bug in definition of vertex" << endl; 
+// 	   // determination du triangle adjacents contenant e1
+	   
+// 	   //int ito1 = Th.TheAdjacencesLink[3*it+eT1]/3;
+// 	   //int eo1  = Th.TheAdjacencesLink[3*it+eT1]%3;
+// 	   int eo1;
+// 	   eo1=eT2;
+// 	   int ito1=Th.ElementAdj(it,eo1);
+	   
+// 	   double xlam = EdgeIter[3*ito1+eo1];
+// 	   VertexIsoP[inv].x   = xlam*Th.vertices[ jj00 ].x + (1-xlam)*Th.vertices[ jj10 ].x; 
+// 	   VertexIsoP[inv].y   = xlam*Th.vertices[ jj00 ].y + (1-xlam)*Th.vertices[ jj10 ].y;
+// 	   VertexIsoP[inv].lab = label;
+	
+// 	   inv++;
+// 	 }
+//       }
+//       //if(newit>=0)TriangleVu[it] = newit;
+//       it = newit;
+      
+//     } while( it >= 0 && it!=it1 && taketriangle[2*it] >= 0  && TriangleVu[it] == -1 && inv <= NbVertex);
+
+//     label=label+1;
+//   } 
+  if(verbosity) cout << " IsolineP1 :inv= " << inv << endl;
+  if(verbosity) cout << "            NbVertex= " << NbVertex << endl;
+  if(verbosity) cout << "            label =" << label << endl;
+  assert(inv == NbVertex);
+  if(verbosity>2) cout << "     file point \"" << ffname->c_str() <<"\""<< endl;
+  FILE *fpoints = fopen(ffname->c_str(),"w");
+  int lab=VertexIsoP[0].lab;
+  for (int k=0; k<NbVertex; k++) {   
+    //fprintf(fpoints,"%f %f %d\n",VertexIsoP[k].x,VertexIsoP[k].y,VertexIsoP[k].lab);
+    if(VertexIsoP[k].lab != lab) fprintf(fpoints,"\n\n");
+    fprintf(fpoints,"%f %f \n",VertexIsoP[k].x,VertexIsoP[k].y);
+    lab=VertexIsoP[k].lab;
+  }
+  fclose(fpoints);
+
+  delete [] VertexIsoP;
+
+  return valsortie;
+}
+
+class  ISOLINE_P1: public OneOperator { public:  
+typedef Mesh *pmesh;
+  ISOLINE_P1() : OneOperator(atype<long>(),atype<pmesh>(),atype<string *>(),atype<double>() ) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new ISOLINE_P1_Op( args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]) ); 
+  }
+};
+
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+ 
+  typedef Mesh *pmesh;
+  cerr << " Warning obsolete load file version now use isolineP1 -> isoline " << endl;  
+  cerr << " see example for the syntaxe " << endl; 
+  cerr << " F . Hecht " << endl;   
+  CompileError("obsolet load filee (sorry) use: load \"isoline\" "); 
+  //Global.Add("isolineP1","(",new ISOLINE_P1);
+
+}
+   
+LOADFUNC(Load_Init)
diff --git a/examples++-load/lame-TD-NSS.edp b/examples++-load/lame-TD-NSS.edp
new file mode 100644
index 0000000..97c8339
--- /dev/null
+++ b/examples++-load/lame-TD-NSS.edp
@@ -0,0 +1,87 @@
+/*
+  Exemple of Mixte furmulation for Lame equation (Linear Elasticity)
+   
+  The Stress and Strian are  H(div div),  
+  for a Sym Stress S we have 
+      ( div(div S) in H^-1 
+  and S.nn are continuous
+
+  The Displacement u are H(Curl) (    u.tau is continuous )
+  where n,tau are normal / tangent 
+
+  This formulation is call TD-NSS
+*/
+load "Element_Mixte"
+load "Element_P3"
+int nn=10;
+mesh Th= square(nn*4,nn,[x*4,y]);
+
+// caoutchoouc 
+//real mu     = 0.012; 
+//real lambda = 0.4; 
+// rho rho=1e-16;
+// ALu
+real  mu = 3.8;
+real lambda= 6.2;
+real rho = 5e-4;
+//   s11, s12, s22 
+real twomu=mu*2;
+real mu1= 1./(twomu);
+real lambda1 = 1./(2*(2*lambda+twomu)) - 1./(twomu*2);
+macro BItr(a,b)  /* S-> a S + b tr(S) Id */  
+[ [ a + b , 0 , 0 ,b       ], 
+  [     0 , a , 0 ,0         ], 
+  [     0 , 0 , a ,0         ], 
+  [   b   , 0 , 0 , a+ b  ]    ] //
+
+func A = BItr(twomu,lambda) ;
+func A1 = BItr(mu1,lambda1) ;
+
+real gravity = -9.81*rho;
+
+
+
+macro Strain(u)  [dx(u#1),(dy(u#1)+dx(u#2))/2,(dy(u#1)+dx(u#2))/2,dy(u#2)] //EOM
+macro Strain2(s)  [s#11, s#12, s#12, s#22] //EOM
+macro S(s) [s#11,s#12,s#22]//
+  macro U(u) [u#1,u#2] //
+  macro dn(u) (U(u)'*[N.x,N.y]) //')
+  macro dnn(s) ( [N.x,N.y]' * [[ s#11,s#12] , [s#12, s#22] ] *[N.x,N.y]) //')
+
+fespace Wh(Th,[P2,P2]);
+fespace Sh(Th,TDNNS1);
+fespace Vh(Th,BDM1Ortho);
+Sh S(s),S(t);
+Vh U(u),U(v);;
+Wh U(w),U(ww);
+
+  solve Lame2([s11,s12,s22,u1,u2],[t11,t12,t22,v1,v2])=
+  int2d(Th)( 
+	       Strain2(s)'*(A1*Strain2(t)) //' 
+	    - Strain(u)'*Strain2(t)  //'
+	    - Strain(v)'*Strain2(s) //'
+     //      + 1e-6*(u1*v2+u2*v2)
+	     )
+  +  intalledges(Th)( dnn(t)*dn(u) + dnn(s)*dn(v) ) 
+  //  - int1d(Th,4) ( 0*dnn(t) ) // here  0 <=> U_d .n * dnn(t) 
+  +  int2d(Th) ( gravity*v2) //-int2d(Th,1,2,3) ( dNtau(t). v.tau) 
+  +on(1,2,3,s11=0,s12=0,s22=0)
+  +on(4,u1=0,u2=0); 
+
+
+
+  solve Lame1([w1,w2],[ww1,ww2])=
+  int2d(Th)( 
+	      Strain(w)'*(A*Strain(ww)) //' 
+	     )
+ -int2d(Th)(gravity*ww2)
+  +on(4,w1=0,w2=0); 
+plot([w1,w2], wait=1);
+plot([u1,u2], wait=1);
+
+real errl2 = sqrt(int2d(Th)( square(w1-u1) + square(w2-w2)));
+cout << " errL2 = " << errl2 << endl;
+
+
+
+
diff --git a/examples++-load/lap-solvers.edp b/examples++-load/lap-solvers.edp
new file mode 100644
index 0000000..54f55eb
--- /dev/null
+++ b/examples++-load/lap-solvers.edp
@@ -0,0 +1,29 @@
+load "SuperLu"
+load "NewSolver"
+verbosity=3;
+//  a example to test the level of optimisation
+// --------------------------------------------
+int nn=300;
+ mesh Th=square(nn,nn);
+verbosity=5;
+ fespace Vh(Th,P1);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+
+ problem laplace0(uh,vh) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  + int1d(Th,1)( - vh)
+  + int2d(Th)( -f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+defaulttoUMFPACK();
+real cpu=clock() ;
+laplace0; // solve the problem plot(uh); // to see the result
+cout << "-- lap UMFPACK " << nn << "x" << nn << "  : " <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
+uh=0;
+defaulttoSuperLU();
+cpu=clock() ;
+laplace0; // solve the problem plot(uh); // to see the result
+cout << "-- lap SuperLU " << nn << "x" << nn << "  : " <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
diff --git a/examples++-load/lapack.cpp b/examples++-load/lapack.cpp
new file mode 100644
index 0000000..94aa2eb
--- /dev/null
+++ b/examples++-load/lapack.cpp
@@ -0,0 +1,970 @@
+//ff-c++-LIBRARY-dep:   lapack
+//ff-c++-LIBRARY-dep:   blas
+#include "ff++.hpp"
+#include "RNM.hpp"
+#include "AFunction_ext.hpp" // Extension of "AFunction.hpp" to deal with more than 3 parameters function
+
+using namespace std;
+
+#ifdef __LP64__
+  typedef int intblas;
+  typedef int integer;
+#else
+  typedef long intblas;
+  typedef long integer;
+#endif
+
+typedef integer  logical;
+typedef float   LAPACK_real;
+typedef double   doublereal;
+typedef logical  (* L_fp)();
+typedef integer      ftnlen;
+
+typedef complex<float> LAPACK_complex;
+typedef complex<double> doublecomplex;
+typedef void VOID; 
+#define complex LAPACK_complex 
+#define real LAPACK_real 
+
+#include "clapack.h"
+#undef real
+#undef complex 
+
+long lapack_inv(KNM<double>* A)
+{
+  intblas n=A->N();
+  intblas m=A->M();
+  double *a=&(*A)(0,0);
+  intblas info;
+  intblas lda=n;
+  KN<intblas> ipiv(n);
+  intblas  lw=10*n;
+  KN<double> w(lw);
+  ffassert(n==m);
+  dgetrf_(&n,&n,a,&lda,ipiv,&info);
+  if(info) return info;
+  dgetri_(&n,a,&lda,ipiv,w,&lw,&info);
+  return info;
+}
+
+long lapack_inv(KNM<Complex>* A)
+{
+    intblas n=A->N();
+    intblas m=A->M();
+    Complex *a=&(*A)(0,0);
+    intblas info;
+    intblas lda=n;
+    KN<intblas> ipiv(n);
+    intblas  lw=10*n;
+    KN<Complex> w(lw);
+    ffassert(n==m);
+    zgetrf_(&n,&n,a,&lda,ipiv,&info);
+    if(info) return info;
+    zgetri_(&n,a,&lda,ipiv,w,&lw,&info);
+    return info;
+}
+
+// (computation of the eigenvalues and right eigenvectors of a real nonsymmetric matrix)
+long lapack_dgeev(KNM<double> *const &A,KN<Complex> *const &vp,KNM<Complex> *const &vectp)
+{
+  /*
+    SUBROUTINE DGEEV( JOBVL, JOBVR, N, A, LDA, WR, WI, VL, LDVL, VR, LDVR, WORK, LWORK, INFO )
+   *  JOBVL   (input) CHARACTER*1
+   *          = 'N': left eigenvectors of A are not computed;
+   *          = 'V': left eigenvectors of A are computed.
+   *
+   *  JOBVR   (input) CHARACTER*1
+   *          = 'N': right eigenvectors of A are not computed;
+   *          = 'V': right eigenvectors of A are computed.
+   *
+   *  N       (input) INTEGER
+   *          The order of the matrix A. N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the N-by-N matrix A.
+   *          On exit, A has been overwritten.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  WR      (output) DOUBLE PRECISION array, dimension (N)
+   *  WI      (output) DOUBLE PRECISION array, dimension (N)
+   *          WR and WI contain the real and imaginary parts,
+   *          respectively, of the computed eigenvalues.  Complex
+   *          conjugate pairs of eigenvalues appear consecutively
+   *          with the eigenvalue having the positive imaginary part
+   *          first.
+   *
+   *  VL      (output) DOUBLE PRECISION array, dimension (LDVL,N)
+   *          If JOBVL = 'V', the left eigenvectors u(j) are stored one
+   *          after another in the columns of VL, in the same order
+   *          as their eigenvalues.
+   *          If JOBVL = 'N', VL is not referenced.
+   *          If the j-th eigenvalue is real, then u(j) = VL(:,j),
+   *          the j-th column of VL.
+   *          If the j-th and (j+1)-st eigenvalues form a complex
+   *          conjugate pair, then u(j) = VL(:,j) + i*VL(:,j+1) and
+   *          u(j+1) = VL(:,j) - i*VL(:,j+1).
+   *
+   *  LDVL    (input) INTEGER
+   *          The leading dimension of the array VL.  LDVL >= 1; if
+   *          JOBVL = 'V', LDVL >= N.
+   *
+   *  VR      (output) DOUBLE PRECISION array, dimension (LDVR,N)
+   *          If JOBVR = 'V', the right eigenvectors v(j) are stored one
+   *          after another in the columns of VR, in the same order
+   *          as their eigenvalues.
+   *          If JOBVR = 'N', VR is not referenced.
+   *          If the j-th eigenvalue is real, then v(j) = VR(:,j),
+   *          the j-th column of VR.
+   *          If the j-th and (j+1)-st eigenvalues form a complex
+   *          conjugate pair, then v(j) = VR(:,j) + i*VR(:,j+1) and
+   *          v(j+1) = VR(:,j) - i*VR(:,j+1).
+   *
+   *  LDVR    (input) INTEGER
+   *          The leading dimension of the array VR.  LDVR >= 1; if
+   *          JOBVR = 'V', LDVR >= N.
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+   *
+   *  LWORK   (input) INTEGER
+   *          The dimension of the array WORK.  LWORK >= max(1,3*N), and
+   *          if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N.  For good
+   *          performance, LWORK must generally be larger.
+   *
+   *          If LWORK = -1, then a workspace query is assumed; the routine
+   *          only calculates the optimal size of the WORK array, returns
+   *          this value as the first entry of the WORK array, and no error
+   *          message related to LWORK is issued by XERBLA.
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value.
+   *          > 0:  if INFO = i, the QR algorithm failed to compute all the
+   *                eigenvalues, and no eigenvectors have been computed;
+   *                elements i+1:N of WR and WI contain eigenvalues which
+   *                have converged.
+   */
+  intblas n=A->N();
+  ffassert(A->M()==n);
+  ffassert(vectp->M()>=n);
+  ffassert(vectp->N()>=n);
+  ffassert(vp->N()>=n);
+  KN<double> wr(n),wi(n),w(1);
+  KNM<double> mat(*A),vr(n,n),vl(n,n);
+  intblas info,lw=-1;
+  char JOBVL='N',JOBVR='V';
+  dgeev_(&JOBVL,&JOBVR,&n,mat,&n,wr,wi,vl,&n,vr,&n,w,&lw,&info);
+  lw=w[0];
+  w.resize(lw);
+  //cout << mat << endl;
+  dgeev_(&JOBVL,&JOBVR,&n,mat,&n,wr,wi,vl,&n,vr,&n,w,&lw,&info);
+  //cout << wr << endl;
+  //cout << wi << endl;
+  if (info<0)
+     {
+     cout << "   dgeev: the " << info << "-th argument had an illegal value." << endl;
+     (*vp)=Complex();
+     (*vectp)=Complex();
+     }
+  else if (info>0)
+     {
+     cout << "   dgeev: the QR algorithm failed to compute all the eigenvalues, and no eigenvectors have been computed." << endl;
+     (*vp)=Complex();
+     (*vectp)=Complex();
+     }
+  else if (info==0)
+     {
+     for (int i=0;i<n;++i)
+        {
+        (*vp)[i]=Complex(wr[i],wi[i]);
+        if (verbosity>2)
+           cout << "   dgeev: vp "<< i << " : "  << (*vp)[i] << endl;
+        if (wi[i]==0)
+           for (int j=0;j<n;++j)
+              (*vectp)(j,i)=vr(j,i);
+        else if (wi[i]>0)
+	   {
+	   for (int j=0;j<n;++j)
+              (*vectp)(j,i)=Complex(vr(j,i),vr(j,i+1));
+           }
+	else if (wi[i]<0)
+	   {
+           for (int j=0;j<n;++j)
+              (*vectp)(j,i)=Complex(vr(j,i-1),-vr(j,i));	      
+           }
+        if (verbosity>5)
+           cout << "   dgeev:   " << (*vectp)(':',i) <<endl;
+        }
+     }
+  return info;
+}
+
+// (computation of the eigenvalues and right eigenvectors of a complex nonsymmetric matrix)
+long lapack_zgeev(KNM<Complex> *const &A,KN<Complex> *const &vp,KNM<Complex> *const &vectp)
+{
+  intblas nvp =0,zero=0;
+  intblas n= A->N();
+  ffassert(A->M()==n);
+  ffassert(vectp->M()>=n);
+  ffassert(vectp->N()>=n);
+  ffassert(vp->N()>=n);
+  KN<Complex> w(n),vr(n*n),vl(n*n);
+  KNM<Complex> mat(*A);
+  intblas info,lw=n*(n+1)*10;
+  KN<Complex> wk(lw);
+  KN<double> rwk(2*n);
+
+  char N='N',V='V';
+  // lw=1;// to get opt size value 
+  zgeev_(&N,&V,&n, mat,&n, w, vl,&n, vr,&n,wk,&lw,rwk,&info);
+  //  cout << lw << " " << wk[0] << " " << info <<   endl;
+  /* lw=wk[0].real();
+  w.resize(lw);
+  zgeev_(&N,&V,&n, mat,&n, w, vl,&n, vr,&n,wk,&lw,rwk,&info);
+  */
+  if(info)
+    cout << " info =  " << info << endl;
+  if(!info)
+    {
+      int k=0;
+      for(int i=0;i<n;++i)
+        {
+          (*vp)[i]=w[i];
+          if(verbosity>2)
+            cout << "   zgeev: vp "<< i << " : "  << (*vp)[i] << endl;
+	  for(int j=0;j<n;++j)
+              (*vectp)(j,i)=vr[k++];
+          if(verbosity>5)
+            cout << "   zgeev :   " << (*vectp)(':',i) <<endl;
+        }
+    }
+  else
+    {
+      nvp=0;
+      (*vp)=Complex();
+      (*vectp)=Complex();
+    }
+  return nvp;
+}
+
+// VL, 10/02/2010
+long lapack_dggev(KNM<double> *const &A,KNM<double> *const &B,KN<Complex> *const &vpa,KN<double> *const &vpb,KNM<Complex> *const &vectp)
+{
+    intblas nvp =0,zero=0;
+    intblas n=A->N();
+    ffassert(A->M()==n);
+    ffassert(B->M()==n);
+    ffassert(B->N()==n);
+    ffassert(vectp->M()>=n);
+    ffassert(vectp->N()>=n);
+    ffassert(vpa->N()>=n);
+    ffassert(vpb->N()>=n);
+    
+    KN<double> war(n),wai(n),wb(n),vr(n*n),vl(n*n);
+    KNM<double> matA(*A);
+    KNM<double> matB(*B);
+    intblas info,lw=-1;  
+    KN<double> w(1);
+    //char N='N',V='V'; VL: do not compute eigenvectors (if yes, switch with following line)
+    char VL='N',VR='N';
+    
+    dggev_(&VL,&VR,&n,matA,&n,matB,&n,war,wai,wb,vl,&n,vr,&n,w,&lw,&info);
+    lw=w[0];
+    // cout << lw << endl;
+    w.resize(lw);
+    dggev_(&VL,&VR,&n,matA,&n,matB,&n,war,wai,wb,vl,&n,vr,&n,w,&lw,&info);
+    if(info)
+	cout << " info =  " << info << endl;
+    if(!info)
+      {
+	int k=0;
+	for(int i=0;i<n;++i)
+	  {
+	    (*vpa)[i]=Complex(war[i],wai[i]);
+	    (*vpb)[i]=wb[i];
+	    if(verbosity>2)
+		cout << "   dggev: vp "<< i << " : "  << (*vpa)[i] << " ; " << (*vpb)[i] << endl;
+	    if( wai[i] == 0)
+		for(int j=0;j<n;++j)
+		    (*vectp)(j,i)=vr[k++];
+	    else if (  wai[i] >  0)
+	      {
+		int ki= k+n;
+		for(int j=0;j<n;++j)
+		    (*vectp)(j,i)=Complex(vr[k++],vr[ki++]);	      
+	      }
+	    else 
+	      {
+		int kr= k-n;
+		for(int j=0;j<n;++j)
+		    (*vectp)(j,i)=Complex(vr[kr++],-vr[k++]);	      
+	      }
+	    if(verbosity>5)
+		cout << "   dggev :   " << (*vectp)(':',i) <<endl;
+	  }
+      }
+    else
+      {
+	nvp=0;
+	(*vpa)=Complex();
+	(*vectp)=Complex();
+      }
+    return nvp;
+}
+
+// GL, 05/10/2011 (computation of all the eigenvalues and the eigenvectors of a real generalized symmetric-definite eigenproblem, of the form A*x=(lambda)*B*x)
+long lapack_dsygvd(KNM<double> *const &A,KNM<double> *const &B,KN<double> *const &vp,KNM<double> *const &vectp)
+{
+  /*
+    SUBROUTINE DSYGVD( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK, LWORK, IWORK, LIWORK, INFO )
+   *  ITYPE   (input) INTEGER
+   *          Specifies the problem type to be solved:
+   *          = 1:  A*x = (lambda)*B*x
+   *          = 2:  A*B*x = (lambda)*x
+   *          = 3:  B*A*x = (lambda)*x
+   *
+   *  JOBZ    (input) CHARACTER*1
+   *          = 'N':  Compute eigenvalues only;
+   *          = 'V':  Compute eigenvalues and eigenvectors.
+   *
+   *  UPLO    (input) CHARACTER*1
+   *          = 'U':  Upper triangles of A and B are stored;
+   *          = 'L':  Lower triangles of A and B are stored.
+   *
+   *  N       (input) INTEGER
+   *          The order of the matrices A and B.  N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
+   *          On entry, the symmetric matrix A.  If UPLO = 'U', the
+   *          leading N-by-N upper triangular part of A contains the
+   *          upper triangular part of the matrix A.  If UPLO = 'L',
+   *          the leading N-by-N lower triangular part of A contains
+   *          the lower triangular part of the matrix A.
+   *
+   *          On exit, if JOBZ = 'V', then if INFO = 0, A contains the
+   *          matrix Z of eigenvectors.  The eigenvectors are normalized
+   *          as follows:
+   *          if ITYPE = 1 or 2, Z**T*B*Z = I;
+   *          if ITYPE = 3, Z**T*inv(B)*Z = I.
+   *          If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
+   *          or the lower triangle (if UPLO='L') of A, including the
+   *          diagonal, is destroyed.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  B       (input/output) DOUBLE PRECISION array, dimension (LDB, N)
+   *          On entry, the symmetric matrix B.  If UPLO = 'U', the
+   *          leading N-by-N upper triangular part of B contains the
+   *          upper triangular part of the matrix B.  If UPLO = 'L',
+   *          the leading N-by-N lower triangular part of B contains
+   *          the lower triangular part of the matrix B.
+   *
+   *          On exit, if INFO <= N, the part of B containing the matrix is
+   *          overwritten by the triangular factor U or L from the Cholesky
+   *          factorization B = U**T*U or B = L*L**T.
+   *
+   *  LDB     (input) INTEGER
+   *          The leading dimension of the array B.  LDB >= max(1,N).
+   *
+   *  W       (output) DOUBLE PRECISION array, dimension (N)
+   *          If INFO = 0, the eigenvalues in ascending order.
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+   *
+   *  LWORK   (input) INTEGER
+   *          The dimension of the array WORK.
+   *          If N <= 1,               LWORK >= 1.
+   *          If JOBZ = 'N' and N > 1, LWORK >= 2*N+1.
+   *          If JOBZ = 'V' and N > 1, LWORK >= 1 + 6*N + 2*N**2.
+   *
+   *          If LWORK = -1, then a workspace query is assumed; the routine
+   *          only calculates the optimal sizes of the WORK and IWORK
+   *          arrays, returns these values as the first entries of the WORK
+   *          and IWORK arrays, and no error message related to LWORK or
+   *          LIWORK is issued by XERBLA.
+   *
+   *  IWORK   (workspace/output) INTEGER array, dimension (MAX(1,LIWORK))
+   *          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
+   *
+   *  LIWORK  (input) INTEGER
+   *          The dimension of the array IWORK.
+   *          If N <= 1,                LIWORK >= 1.
+   *          If JOBZ  = 'N' and N > 1, LIWORK >= 1.
+   *          If JOBZ  = 'V' and N > 1, LIWORK >= 3 + 5*N.
+   *
+   *          If LIWORK = -1, then a workspace query is assumed; the
+   *          routine only calculates the optimal sizes of the WORK and
+   *          IWORK arrays, returns these values as the first entries of
+   *          the WORK and IWORK arrays, and no error message related to
+   *          LWORK or LIWORK is issued by XERBLA.
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  DPOTRF or DSYEVD returned an error code:
+   *             <= N:  if INFO = i and JOBZ = 'N', then the algorithm
+   *                    failed to converge; i off-diagonal elements of an
+   *                    intermediate tridiagonal form did not converge to
+   *                    zero;
+   *                    if INFO = i and JOBZ = 'V', then the algorithm
+   *                    failed to compute an eigenvalue while working on
+   *                    the submatrix lying in rows and columns INFO/(N+1)
+   *                    through mod(INFO,N+1);
+   *             > N:   if INFO = N + i, for 1 <= i <= N, then the leading
+   *                    minor of order i of B is not positive definite.
+   *                    The factorization of B could not be completed and
+   *                    no eigenvalues or eigenvectors were computed.
+   */
+  intblas n=A->N();
+  ffassert(A->M()==n);
+  ffassert(B->M()==n);
+  ffassert(B->N()==n);
+  ffassert(vp->N()>=n);
+  ffassert(vectp->M()>=n);
+  ffassert(vectp->N()>=n);
+  KN<double> war(n),wai(n),wb(n),vr(n*n),vl(n*n);
+  KNM<double> matA(*A),matB(*B);
+  intblas itype=1,info,lw=-1;
+  KN<double> w(1);
+  KN<intblas> iw(1);
+  char JOBZ='V',UPLO='U';
+  
+  dsygvd_(&itype,&JOBZ,&UPLO,&n,matA,&n,matB,&n,*vp,w,&lw,iw,&lw,&info);
+  lw=w[0];
+  w.resize(lw);
+  iw.resize(lw);
+  dsygvd_(&itype,&JOBZ,&UPLO,&n,matA,&n,matB,&n,*vp,w,&lw,iw,&lw,&info);
+  if (info<0)
+     {
+     cout << "   dsygvd: the " << info << "-th argument had an illegal value." << endl;
+     }
+  else if (info>0)
+     {
+     cout << "   dsygvd: DPOTRF or DSYEVD returned an error code." << endl;
+     }
+  else if (info==0)
+     {
+     for (int i=0;i<n;++i)
+        {
+        for (int i=0;i<n;++i)
+           {
+           for (int j=0;j<n;++j)
+              (*vectp)(j,i)=matA(j,i);	      
+           }
+        }  
+     }
+  return info;
+}
+
+// GL,27/09/2011 (singular value decomposition of a rectangular real matrix)
+long lapack_dgesdd(KNM<double> *const &A,KNM<double> *const &U,KN<double> *const &S,KNM<double> *const &V)
+{
+  /*
+    SUBROUTINE DGESDD( JOBZ, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, IWORK, INFO )
+   *  JOBZ    (input) CHARACTER*1
+   *          Specifies options for computing all or part of the matrix U:
+   *          = 'A':  all M columns of U and all N rows of V**T are
+   *                  returned in the arrays U and VT;
+   *          = 'S':  the first min(M,N) columns of U and the first
+   *                  min(M,N) rows of V**T are returned in the arrays U
+   *                  and VT;
+   *          = 'O':  If M >= N, the first N columns of U are overwritten
+   *                  on the array A and all rows of V**T are returned in
+   *                  the array VT;
+   *                  otherwise, all columns of U are returned in the
+   *                  array U and the first M rows of V**T are overwritten
+   *                  in the array A;
+   *          = 'N':  no columns of U or rows of V**T are computed.
+   *
+   *  M       (input) INTEGER
+   *          The number of rows of the input matrix A.  M >= 0.
+   *
+   *  N       (input) INTEGER
+   *          The number of columns of the input matrix A.  N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the M-by-N matrix A.
+   *          On exit,
+   *          if JOBZ = 'O',  A is overwritten with the first N columns
+   *                          of U (the left singular vectors, stored
+   *                          columnwise) if M >= N;
+   *                          A is overwritten with the first M rows
+   *                          of V**T (the right singular vectors, stored
+   *                          rowwise) otherwise.
+   *          if JOBZ .ne. 'O', the contents of A are destroyed.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,M).
+   *
+   *  S       (output) DOUBLE PRECISION array, dimension (min(M,N))
+   *          The singular values of A, sorted so that S(i) >= S(i+1).
+   *
+   *  U       (output) DOUBLE PRECISION array, dimension (LDU,UCOL)
+   *          UCOL = M if JOBZ = 'A' or JOBZ = 'O' and M < N;
+   *          UCOL = min(M,N) if JOBZ = 'S'.
+   *          If JOBZ = 'A' or JOBZ = 'O' and M < N, U contains the M-by-M
+   *          orthogonal matrix U;
+   *          if JOBZ = 'S', U contains the first min(M,N) columns of U
+   *          (the left singular vectors, stored columnwise);
+   *          if JOBZ = 'O' and M >= N, or JOBZ = 'N', U is not referenced.
+   *
+   *  LDU     (input) INTEGER
+   *          The leading dimension of the array U.  LDU >= 1; if
+   *          JOBZ = 'S' or 'A' or JOBZ = 'O' and M < N, LDU >= M.
+   *
+   *  VT      (output) DOUBLE PRECISION array, dimension (LDVT,N)
+   *          If JOBZ = 'A' or JOBZ = 'O' and M >= N, VT contains the
+   *          N-by-N orthogonal matrix V**T;
+   *          if JOBZ = 'S', VT contains the first min(M,N) rows of
+   *          V**T (the right singular vectors, stored rowwise);
+   *          if JOBZ = 'O' and M < N, or JOBZ = 'N', VT is not referenced.
+   *
+   *  LDVT    (input) INTEGER
+   *          The leading dimension of the array VT.  LDVT >= 1; if
+   *          JOBZ = 'A' or JOBZ = 'O' and M >= N, LDVT >= N;
+   *          if JOBZ = 'S', LDVT >= min(M,N).
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK;
+   *
+   *  LWORK   (input) INTEGER
+   *          The dimension of the array WORK. LWORK >= 1.
+   *          If JOBZ = 'N',
+   *            LWORK >= 3*min(M,N) + max(max(M,N),7*min(M,N)).
+   *          If JOBZ = 'O',
+   *            LWORK >= 3*min(M,N) + 
+   *                     max(max(M,N),5*min(M,N)*min(M,N)+4*min(M,N)).
+   *          If JOBZ = 'S' or 'A'
+   *            LWORK >= 3*min(M,N) +
+   *                     max(max(M,N),4*min(M,N)*min(M,N)+4*min(M,N)).
+   *          For good performance, LWORK should generally be larger.
+   *          If LWORK = -1 but other input arguments are legal, WORK(1)
+   *          returns the optimal LWORK.
+   *
+   *  IWORK   (workspace) INTEGER array, dimension (8*min(M,N))
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit.
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value.
+   *          > 0:  DBDSDC did not converge, updating process failed.
+   */
+  intblas n=A->N();
+  intblas m=A->M();
+  U->resize(n,n);
+  S->resize(min(n,m));
+  V->resize(m,m);
+  KNM<double> VT(m,m);
+  KN<intblas> iw(8*min(n,m));
+  intblas info,lw=-1;
+  KN<double> w(1);
+  char JOBZ='A';
+  dgesdd_(&JOBZ,&n,&m,*A,&n,*S,*U,&n,VT,&m,w,&lw,iw,&info);
+  lw=w[0];
+  w.resize(lw);
+  dgesdd_(&JOBZ,&n,&m,*A,&n,*S,*U,&n,VT,&m,w,&lw,iw,&info);
+  if (info<0)
+     {
+     cout << "   dgesdd: the " << info << "-th argument had an illegal value." << endl;
+     }
+  else if (info>0)
+     {
+     cout << "   dgesdd: DBDSDC did not converge, updating process failed." << endl;
+     }
+  else if (info==0)
+     {
+     for (int i=0;i<m;++i)
+	for (int j=0;j<m;++j)
+	   (*V)(i,j)=VT(j,i);
+     }
+  return info;
+}
+
+// GL,28/09/2011 (computation of the eigenvalues and eigenvectors of a real symmetric matrix)
+long lapack_dsyev(KNM<double> *const &A,KN<double> *const &vp,KNM<double> *const &vectp)
+{
+  /*
+    SUBROUTINE DSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )
+   *  JOBZ    (input) CHARACTER*1
+   *          = 'N':  Compute eigenvalues only;
+   *          = 'V':  Compute eigenvalues and eigenvectors.
+   *
+   *  UPLO    (input) CHARACTER*1
+   *          = 'U':  Upper triangle of A is stored;
+   *          = 'L':  Lower triangle of A is stored.
+   *
+   *  N       (input) INTEGER
+   *          The order of the matrix A.  N >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA, N)
+   *          On entry, the symmetric matrix A.  If UPLO = 'U', the
+   *          leading N-by-N upper triangular part of A contains the
+   *          upper triangular part of the matrix A.  If UPLO = 'L',
+   *          the leading N-by-N lower triangular part of A contains
+   *          the lower triangular part of the matrix A.
+   *          On exit, if JOBZ = 'V', then if INFO = 0, A contains the
+   *          orthonormal eigenvectors of the matrix A.
+   *          If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
+   *          or the upper triangle (if UPLO='U') of A, including the
+   *          diagonal, is destroyed.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  W       (output) DOUBLE PRECISION array, dimension (N)
+   *          If INFO = 0, the eigenvalues in ascending order.
+   *
+   *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
+   *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+   *
+   *  LWORK   (input) INTEGER
+   *          The length of the array WORK.  LWORK >= max(1,3*N-1).
+   *          For optimal efficiency, LWORK >= (NB+2)*N,
+   *          where NB is the blocksize for DSYTRD returned by ILAENV.
+   *
+   *          If LWORK = -1, then a workspace query is assumed; the routine
+   *          only calculates the optimal size of the WORK array, returns
+   *          this value as the first entry of the WORK array, and no error
+   *          message related to LWORK is issued by XERBLA.
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, the algorithm failed to converge; i
+   *                off-diagonal elements of an intermediate tridiagonal
+   *                form did not converge to zero.
+   */
+  intblas n=A->N();
+  ffassert(A->M()==n);
+  ffassert(vectp->N()==n);
+  ffassert(vectp->M()==n);
+  ffassert(vp->N()==n);
+  KNM<double> mat(*A);
+  intblas info,lw=-1;  
+  KN<double> w(1);
+  char JOBZ='V',UPLO='U';
+  dsyev_(&JOBZ,&UPLO,&n,mat,&n,*vp,w,&lw,&info);
+  lw=w[0];
+  w.resize(lw);
+  dsyev_(&JOBZ,&UPLO,&n,mat,&n,*vp,w,&lw,&info);
+  if (info<0)
+     {
+     cout << "   dsyev: the " << info << "-th argument had an illegal value." << endl;
+     }
+  else if (info>0)
+     {
+     cout << "   dsyev: the algorithm failed to converge." << endl;
+     }
+  else if (info==0)
+     {
+     *vectp=mat;
+     }
+  return info;
+}
+
+template<class T>
+class Inverse{ public:
+  T  t;
+  Inverse( T  v)
+   : t(v) {}
+  template<class TT> Inverse( TT  v) : t(v) {}  
+  template<class TT> Inverse( TT * v) : t(*v) {}  
+  operator const T & () const {return t;}
+};
+
+template<class T>
+class Mult{ public:
+    T  a;bool ta;
+  T  b;bool tb;
+  Mult( T  aa,T bb)
+    : a(aa),b(bb),ta(0),tb(0) {}
+    // Transpose<
+  Mult( Transpose<T>  aa,T bb)   
+    : a(aa),b(bb),ta(1),tb(0) {}
+  Mult( Transpose<T>  aa,Transpose<T> bb)   
+    : a(aa),b(bb),ta(1),tb(1) {}
+    Mult( T  aa,Transpose<T> bb)   
+    : a(aa),b(bb),ta(1),tb(1) {}
+    
+};
+
+template<class K>
+class OneBinaryOperatorRNM_inv : public OneOperator { public:  
+    OneBinaryOperatorRNM_inv() 
+      : OneOperator( atype< Inverse< KNM<K>* > >(),atype<KNM<K> *>(),atype<long>()) {}
+  E_F0 * code(const basicAC_F0 & args) const 
+  { Expression p=args[1];
+    if ( ! p->EvaluableWithOutStack() ) 
+      { 
+	bool bb=p->EvaluableWithOutStack();
+	cout << "  Error exposant ??? " <<  bb << " " <<  * p <<  endl;
+	CompileError(" A^p, The p must be a constant == -1, sorry");}
+    long pv = GetAny<long>((*p)(0));
+    if (pv !=-1)   
+      { char buf[100];
+	sprintf(buf," A^%ld, The pow must be  == -1, sorry",pv);
+	CompileError(buf);}     
+    return  new E_F_F0<Inverse< KNM<K>* > ,KNM<K> *>(Build<Inverse< KNM<K>* > ,KNM<K> *>,t[0]->CastTo(args[0])); 
+  }
+};
+
+
+template <int INIT>
+KNM<R>* Solve(KNM<R>* a,Inverse<KNM<R >*> b) 
+{
+  /*
+    SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
+   *  N       (input) INTEGER
+   *          The number of linear equations, i.e., the order of the
+   *          matrix A.  N >= 0.
+   *
+   *  NRHS    (input) INTEGER
+   *          The number of right hand sides, i.e., the number of columns
+   *          of the matrix B.  NRHS >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the N-by-N coefficient matrix A.
+   *          On exit, the factors L and U from the factorization
+   *          A = P*L*U; the unit diagonal elements of L are not stored.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  IPIV    (output) INTEGER array, dimension (N)
+   *          The pivot indices that define the permutation matrix P;
+   *          row i of the matrix was interchanged with row IPIV(i).
+   *
+   *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
+   *          On entry, the N-by-NRHS matrix of right hand side matrix B.
+   *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
+   *
+   *  LDB     (input) INTEGER
+   *          The leading dimension of the array B.  LDB >= max(1,N).
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
+   *                has been completed, but the factor U is exactly
+   *                singular, so the solution could not be computed.
+   *
+   */
+  typedef double R;
+  integer info;
+  KNM<R> B(*b);
+  integer  n= B.N();
+  KN<integer> p(n);
+  ffassert(B.M()==n);
+  if(INIT)
+      a->init(n,n);
+   else
+    a->resize(n,n);
+  *a=0.;
+  for(int i=0;i<n;++i)
+    (*a)(i,i)=(R) 1;;
+
+  dgesv_(&n,&n,B,&n,p,*a,&n,&info);
+  if(info) cerr << " error:  dgesv_ "<< info << endl;
+  return a;
+}
+
+
+// Template interface 
+inline int gemm(char *transa, char *transb, integer *m, integer *
+	   n, integer *k, double *alpha, double *a, integer *lda, 
+	   double *b, integer *ldb, double *beta, double *c, integer 
+	   *ldc) {
+   return  dgemm_(transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc);
+}
+inline int gemm(char *transa, char *transb, integer *m, integer *
+		 n, integer *k, Complex *alpha, Complex *a, integer *lda, 
+		 Complex *b, integer *ldb, Complex *beta, Complex *c, integer 
+		 *ldc) {
+    return  zgemm_(transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc);
+}
+
+
+template<class R,bool init, int ibeta> 
+KNM<R>* mult(KNM<R >* a,const KNM_<R> & A,const KNM_<R> & B) 
+{ // C=A*B 
+   
+    R alpha=1.,beta=R(ibeta);
+    char tA, tB;
+    if(init) a->init();
+    intblas N= A.N();
+    intblas M=B.M();
+    intblas K=A.M();
+    KNM<R> & C= *a;
+    C.resize(N,M); 
+    ffassert(K==B.N());
+    R *A00=&A(0,0), *A10= &A(1,0), *A01= &A(0,1); 
+    R *B00=&B(0,0), *B10= &B(1,0), *B01= &B(0,1); 
+    R *C00=&C(0,0), *C10= &C(1,0), *C01= &C(0,1); 
+    intblas lsa=A10-A00 ,lsb=B10-B00,lsc=C10-C00;
+    intblas lda=A01-A00 ,ldb=B01-B00,ldc=C01-C00;
+    if(verbosity>10) {
+	cout << lsa << " " << lsb << " "<< lsc << " init " << init <<  endl;
+	cout << lda << " " << ldb << " "<< ldc << endl;	
+    }
+    tA=lda==1?'T':'N';
+    tB=ldb==1?'T':'N';
+    
+    if(lda==1) lda=lsa;
+    if(ldb==1) ldb=lsb;
+    if(beta==0.)
+     C=R(); 
+#ifdef XXXXXXXXXXXXXX
+    
+    for(int i=0;i<N;++i)
+	 for(int j=0;j<M;++j)
+	      for(int k=0;k<K;++k)
+		  C(i,j) += A(i,k)*B(k,j)  ;
+#else    
+    gemm(&tB,&tA,&N,&M,&K,&alpha,A00,&lda,B00,&ldb,&beta,C00,&ldc);
+#endif
+    return a;
+    /*
+     The Fortran interface for these procedures are:
+     SUBROUTINE xGEMM ( TRANSA, TRANSB, M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC )
+     where TRANSA and TRANSB determines if the matrices A and B are to be transposed.
+     M is the number of rows in matrix A and C. N is the number of columns in matrix B and C. 
+     K is the number of columns in matrix A and rows in matrix B. 
+     LDA, LDB and LDC specifies the size of the first dimension of the matrices, as laid out in memory;
+     meaning the memory distance between the start of each row/column, depending on the memory structure (Dongarra et al. 1990).
+     */
+}
+template<class R,bool init, int ibeta> 
+KNM<R>* mult(KNM<R >* a,Mult<KNM<R >*> bc) 
+{
+    if( (bc.ta == 0) && (bc.tb == 0))
+     return  mult<R,init,ibeta>(a,*bc.a,*bc.b) ;
+    else if((bc.ta == 1 )&& (bc.tb == 0))
+     return  mult<R,init,ibeta>(a,bc.a->t(),*bc.b) ;
+    else if((bc.ta == 0) && (bc.tb == 1))
+	return  mult<R,init,ibeta>(a,*bc.a,bc.b->t()) ;
+    else if((bc.ta == 1) && (bc.tb == 1))
+	return  mult<R,init,ibeta>(a,bc.a->t(),bc.b->t()) ;
+    else
+        // should never happen
+        return NULL;
+}
+
+template <int INIT>
+KNM<Complex>* SolveC(KNM<Complex>* a,Inverse<KNM<Complex >*> b) 
+{
+  /*
+    SUBROUTINE DGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
+   *  N       (input) INTEGER
+   *          The number of linear equations, i.e., the order of the
+   *          matrix A.  N >= 0.
+   *
+   *  NRHS    (input) INTEGER
+   *          The number of right hand sides, i.e., the number of columns
+   *          of the matrix B.  NRHS >= 0.
+   *
+   *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+   *          On entry, the N-by-N coefficient matrix A.
+   *          On exit, the factors L and U from the factorization
+   *          A = P*L*U; the unit diagonal elements of L are not stored.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  IPIV    (output) INTEGER array, dimension (N)
+   *          The pivot indices that define the permutation matrix P;
+   *          row i of the matrix was interchanged with row IPIV(i).
+   *
+   *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
+   *          On entry, the N-by-NRHS matrix of right hand side matrix B.
+   *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
+   *
+   *  LDB     (input) INTEGER
+   *          The leading dimension of the array B.  LDB >= max(1,N).
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
+   *                has been completed, but the factor U is exactly
+   *                singular, so the solution could not be computed.
+   *
+   */
+  typedef Complex R;
+  integer info;
+  KNM<R> B(*b);
+  integer   n= B.N();
+  KN<integer> p(n);
+  ffassert(B.M()==n);
+  if(INIT)
+     a->init(n,n);
+  else
+     a->resize(n,n);
+  *a=0.;
+  for(int i=0;i<n;++i)
+    (*a)(i,i)=(R) 1;;
+
+  zgesv_(&n,&n,(R*) B,&n,p, (R*) *a,&n,&info);
+  if(info) cerr << " error:  zgesv_ "<< info << endl;
+  return a;
+}
+
+
+template<class R,class A,class B> R Build2(A a,B b) {
+    return R(a,b);
+}
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+
+  if( map_type.find(typeid(Inverse<KNM<double >* >).name() ) == map_type.end() )
+    {
+      if(verbosity) 
+	cout << " Add lapack interface ..." ;
+      Dcl_Type< Inverse<KNM<double >* > > ();
+      Dcl_Type< Inverse<KNM<Complex >* > > ();
+      Dcl_Type< Mult<KNM<Complex >* > > ();
+      Dcl_Type< Mult<KNM<double >* > > ();
+      
+      TheOperators->Add("^", new OneBinaryOperatorRNM_inv<double>());
+      TheOperators->Add("*", new OneOperator2< Mult< KNM<double>* >,KNM<double>*,KNM<double>*>(Build2));
+      TheOperators->Add("*", new OneOperator2< Mult< KNM<Complex>* >,KNM<Complex>*,KNM<Complex>*>(Build2));
+      
+      TheOperators->Add("^", new OneBinaryOperatorRNM_inv<Complex>());
+      TheOperators->Add("=", new OneOperator2<KNM<double>*,KNM<double>*,Inverse<KNM<double >*> >( Solve<0>) );
+      TheOperators->Add("=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Inverse<KNM<Complex >*> >( SolveC<0>) );
+      TheOperators->Add("<-", new OneOperator2<KNM<double>*,KNM<double>*,Inverse<KNM<double >*> >( Solve<1>) );
+      TheOperators->Add("<-", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Inverse<KNM<Complex >*> >( SolveC<1>) );
+        
+      TheOperators->Add("=", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,false,0> ) );
+      TheOperators->Add("=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,false,0> ) );
+      
+      TheOperators->Add("+=", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,false,1> ) );
+      TheOperators->Add("+=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,false,1> ) );
+      
+      TheOperators->Add("-=", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,false,-1> ) );
+      TheOperators->Add("-=", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,false,-1> ) );
+      
+      TheOperators->Add("<-", new OneOperator2<KNM<double>*,KNM<double>*,Mult<KNM<double >*> >( mult<double,true,0> ) );
+      TheOperators->Add("<-", new OneOperator2<KNM<Complex>*,KNM<Complex>*,Mult<KNM<Complex >*> >( mult<Complex,true,0> ) );
+      
+      Global.Add("inv","(",new  OneOperator1<long,KNM<double>*>(lapack_inv));  
+      Global.Add("inv","(",new  OneOperator1<long,KNM<Complex>*>(lapack_inv));
+        
+      Global.Add("dgeev","(",new  OneOperator3_<long,KNM<double>*,KN<Complex>*,KNM<Complex>*>(lapack_dgeev));
+      Global.Add("zgeev","(",new  OneOperator3_<long,KNM<Complex>*,KN<Complex>*,KNM<Complex>*>(lapack_zgeev));
+        // add FH
+       Global.Add("geev","(",new  OneOperator3_<long,KNM<double>*,KN<Complex>*,KNM<Complex>*>(lapack_dgeev));
+       Global.Add("geev","(",new  OneOperator3_<long,KNM<Complex>*,KN<Complex>*,KNM<Complex>*>(lapack_zgeev));
+        
+      Global.Add("dggev","(",new  OneOperator5_<long,KNM<double>*,KNM<double>*,KN<Complex>*,KN<double>*,KNM<Complex>*>(lapack_dggev));
+      Global.Add("dsygvd","(",new  OneOperator4_<long,KNM<double>*,KNM<double>*,KN<double>*,KNM<double>*>(lapack_dsygvd));
+      Global.Add("dgesdd","(",new  OneOperator4_<long,KNM<double>*,KNM<double>*,KN<double>*,KNM<double>*>(lapack_dgesdd));
+      Global.Add("dsyev","(",new  OneOperator3_<long,KNM<double>*,KN<double>*,KNM<double>*>(lapack_dsyev));
+    }
+  else
+    if(verbosity)
+      cout << "( load: lapack <=> fflapack , skeep ) ";
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-load/lapack.edp b/examples++-load/lapack.edp
new file mode 100644
index 0000000..4bd400f
--- /dev/null
+++ b/examples++-load/lapack.edp
@@ -0,0 +1,122 @@
+load "lapack"
+// test of lapack load file ... 
+// .......................
+// load "fflapack" obsolete (F. Hecht version 3.8)
+// use  load "lapack"  
+int nerr=0; // nomber of err .. 
+//  to set a full matrix .. 
+macro SETM(A,i,j,fij) 
+{ 
+    for(int i=0;i<A.n;++i) 
+      for(int j=0;j<A.m;++j) 
+        A(i,j)= (fij) ;
+}//EOM 
+
+// The of Eigen Problem ..
+NewMacro TEST(Type,Typevp,vtype,ComputeEV)
+{     
+cout << "\n\n *****************   VP \n\n\n"; 
+int n=5;
+Type[int,int] A(n,n),A1(n,n),B(n,n),Id(n,n);
+SETM(A,i,j,(i==j) ? n+1 : 1); 
+SETM(Id,i,j,real(i==j)); 
+A(0,n-1)=vtype;
+
+cout << A << endl;
+A1=A^-1;
+cout << A1 << endl;
+
+Typevp[int] vp(n);
+Typevp[int,int] VP(n,n),KK(n,n);
+
+int nn= ComputeEV(A,vp,VP);
+ cout << "  vp = " <<vp << endl;
+ cout << " VP = " << VP << endl;
+ 
+ // verification ... 
+ KK =0.;
+ for(int i=0;i<n;++i)
+   for(int j=0;j<n;++j)
+     for(int k=0;k<n;++k)
+       KK(i,j) += (A(i,k) - vp[j]* real(i==k) ) *VP(k,j);
+ cout <<" ||KK|| " <<  KK.linfty << endl; 
+ nerr += KK.linfty > 1e-9; 
+B=0;
+B = A*A1; // version 3.13
+B -= Id; 
+cout <<" ||A*A1-Id|| " <<  B.linfty << endl; 
+nerr += B.linfty > 1e-9; 
+inv(A1);
+A1 -= A; 
+cout <<  "|| inv(A1) - A ||" << A1.linfty << endl;
+nerr += A1.linfty > 1e-9; 
+}
+EndMacro 
+
+TEST(real,complex,-100.,dgeev)
+TEST(complex,complex,100i,zgeev)
+TEST(real,real,1,dsyev)
+assert(nerr==0); 
+
+
+// FFCS - value for regression checks
+real regtest=0;
+
+{
+
+int n=5;
+real [int,int] A(n,n),  B(n,n),  C(n,n);
+SETM(C,i,j,1./(1+i+j)) ; 
+SETM(B,i,j,i==j?2.:1./n) ;
+ 
+A = B*C;
+cout << A << " " << endl;
+A = B + C;
+real[int]  b(n),c(n);
+real[int,int] AA=A;
+AA=A;
+real [int,int] At=A';
+
+b = A*c;
+
+At =A';
+{
+
+real [int,int] A=[[0,-1,2],[4,11,2],[0,-1,2],[4,11,2]];
+real [int,int] B=[[3,-1],[1,2],[6,1]];
+real [int,int] E=[[11,0],[35,20],[11,0],[35,20]];
+real [int,int]  At=A';
+real [int,int] C(A.n,B.m);
+C=A*B;
+cout << " C = " <<  C << endl;
+cout << " E = " <<  E << endl;
+
+C -= E;
+assert( C.linfty < 1e-10);
+C = A*B;
+C -=E; 
+assert( C.linfty < 1e-10);
+}
+{
+
+complex [int,int] A=[[0,-1,2],[4,11,2],[0,-1,2],[4,11,2]];
+complex [int,int] B=[[3,-1],[1,2],[6,1]];
+complex [int,int] E=[[11,0],[35,20],[11,0],[35,20]];
+
+complex [int,int] C(A.n,B.m);
+complex [int,int]  At=A';
+cout << "At = " << At << endl;
+C=A*B;
+cout << " C = " <<  C << endl;
+cout << " E = " <<  E << endl;
+
+C -= E;
+assert( C.linfty < 1e-10);
+C = A*B;
+C -=E; 
+assert( C.linfty < 1e-10);
+
+// FFCS - value for regression checks
+regtest=C.linfty;
+}
+}
diff --git a/examples++-load/layer.edp b/examples++-load/layer.edp
new file mode 100644
index 0000000..1cc9c0a
--- /dev/null
+++ b/examples++-load/layer.edp
@@ -0,0 +1,5 @@
+load "msh3"
+mesh Th=square(3,3);
+
+mesh3 Th3=buildlayers(Th,3);
+savemesh(Th3,"lll.mesh");
diff --git a/examples++-load/lg.pgm b/examples++-load/lg.pgm
new file mode 100644
index 0000000..2b73976
--- /dev/null
+++ b/examples++-load/lg.pgm
@@ -0,0 +1,4 @@
+P5
+322 200
+255
+gdqu�����zn��zrfvm}��jgdahokb``gjgbmrab^bp{v���}q~�uhwywqh}sieqqib��������u�xktzsjvy~aq�njlnnpptvxwx�����������ugptnslnqsvtpn����������������������������������|�������������wy}���~}}������vxx���}��{|��p��|�of^k~jsopehlmvv���������������xy�����������������~��y{����������������ryyh�������������wrtn���lsps�jga`_Y]aek_UNns}����zw�xefh_wmnulgffeqe[^bkgfoib`ehu�u|��yv~pvj~~{o^WO^lfgs}���������p��zrt|wvx��dnsomppmmslmoy��������||~��{lyqonnsklnio{x�������������������|�������������{v������ [...]
\ No newline at end of file
diff --git a/examples++-load/lgbmo.cpp b/examples++-load/lgbmo.cpp
new file mode 100644
index 0000000..fb76f62
--- /dev/null
+++ b/examples++-load/lgbmo.cpp
@@ -0,0 +1,327 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//ff-c++-cpp-dep:  bmo.cpp
+
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "Mesh3dn.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+#include "bmo.hpp"
+
+//template<class R>
+extern Block *currentblock;
+
+typedef double R;
+
+class OptimBMO : public OneOperator 
+{
+public:
+  typedef KN<R> Kn;
+  typedef KN_<R> Kn_;
+  typedef R REAL;
+  typedef KN<REAL> VECT;
+  typedef KNM<REAL> MAT;
+  typedef VirtualMatrice<REAL> VMAT;
+  
+   const int cas;
+  
+  
+  
+
+  class E_BMO: public E_F0mps { public:
+    const int cas;
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =16;
+    Expression nargs[n_name_param];
+    Expression X;
+    C_F0 inittheparam,theparam,closetheparam; 
+    Expression JJ,dJJ;
+    long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+     string *arg(int i,Stack stack,string * a) const{ return nargs[i] ? GetAny<string *>( (*nargs[i])(stack) ): a;}
+    void Set_arg(int i,Stack stack,Kn_ v) const  { if(nargs[i]) v= GetAny<Kn_>( (*nargs[i])(stack) );}
+      
+    class lgBMO: public BijanMO  {
+    private:
+      Stack stack;
+      Expression JJ,dJJ,theparame;
+    protected:
+      void setparam( const KN_<R>& x )
+      {
+	KN_<double> *p=GetAny<KN_<double> *>( (*theparame)(stack) );
+	ffassert( p->N() == x.N());
+	*p =x;
+      }
+      
+    public:
+      
+      lgBMO(Stack s,int n,Expression t,Expression J,Expression dJ,
+	    int wnbrestart=1,
+	    int wnbext1=1,
+	    int wnbbvp=5,
+	    int wnbgrad=5,
+	    double wepsfd=1e-5,
+	    double wrho000=100,
+	    double wepsloc=1e-4,
+	    double wepsij=1e-6,
+	    int nn100=100)
+	
+	: BijanMO(n,wnbrestart,wnbext1,wnbbvp,wnbgrad,wepsfd,wrho000,wepsloc,wepsij,nn100),
+	  stack(s),
+	  JJ(J),dJJ(dJ),theparame(t)
+      { 
+      }
+      
+      ~lgBMO() {
+      }
+      
+            
+      
+      /* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+      /* functional definition */
+      /* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+      
+      double J(Vect & x)
+      {
+	setparam(x);
+	
+	double  ret= GetAny<R>( (*JJ)(stack));
+	WhereStackOfPtr2Free(stack)->clean();
+	return  ret; }
+      
+      
+      /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+      /* gradient exact,   no defini => DF */  
+      /* cccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+      
+      double * DJ(Vect & x, Vect & fpx)
+      {
+	if(!dJJ) return 0;
+	setparam(x);
+	fpx=GetAny<Kn_>( (*dJJ)(stack));
+	WhereStackOfPtr2Free(stack)->clean(); 
+	return fpx;
+      }
+      void result(Vect & xoptg,Vect &vinit){} 
+      
+    };
+      
+    E_BMO(const basicAC_F0 & args,int cc) :
+      cas(cc)
+    {
+      int nbj= args.size()-1;
+      Block::open(currentblock); // make a new block to 
+      X = to<Kn*>(args[nbj]);
+      C_F0 X_n(args[nbj],"n");
+      //  the expression to init the theparam of all 
+      inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+      theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+      args.SetNameParam(n_name_param,name_param,nargs);
+      const  Polymorphic * opJ=0;
+      const  Polymorphic * opdJ=0;
+      if (nbj>0)
+	{  opJ=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+	  assert(opJ); }
+      if (nbj>1)
+	{   opdJ=  dynamic_cast<const  Polymorphic *>(args[1].LeftValue());
+	assert(opdJ); }
+      JJ=dJJ=0;
+      
+      JJ= to<R>(C_F0(opJ,"(",theparam));
+      if(opdJ)
+        dJJ= to<Kn_>(C_F0(opdJ,"(",theparam));// Modif FH 17102005 (a verifier) to<Kn*> ->to<Kn>
+      closetheparam=currentblock->close(currentblock);   // the cleanning block expression 
+    }
+     
+     virtual AnyType operator()(Stack stack)  const
+    {
+      
+      WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+
+      /*
+	basicAC_F0::name_and_type  OptimBMO::E_BMO::name_param[]= {
+	{  "eps", &typeid(double)  },
+	{ "nbrestart",&typeid(long) },
+	{ "nbbvp",&typeid(long)},
+	{ "nbgrad",&typeid(long)},
+	{ "epsfd",&typeid(double)},
+	{ "epsloc",&typeid(double)},
+	{ "epsij",&typeid(double)},
+	{ "n100",&typeid(long)} // 7
+	};
+	
+      */
+
+      R tol=arg(0,stack,1E-6); // not used ....
+      int nbrestart=arg(1,stack,5L);
+      int nbext1=5; // bof bof 
+      int nbbvp=arg(2,stack,5L);
+      int nbgrad=arg(3,stack,5L);
+      double epsfd=arg(4,stack,1e-5);
+      double rho000=arg(5,stack,1e-5);
+      double epsloc=arg(6,stack,1e-4);
+      double epsij=arg(7,stack,1e-6);
+      int n100=arg(8,stack,100L);
+      int  diagrand=arg(9,stack,0L);
+      R cmin = arg(9,stack,-1000.);
+      R cmax = arg(10,stack,1000.);
+      //KN_<double>  vmin = arg< KN_<double> >(11,stack, ccmin );
+     // KN_<double>  vmax = arg< KN_<double> >(12,stack, ccmax );
+      string * datahist =arg(13,stack, (string *) 0 );
+      string * datachist =arg(14,stack,  (string *) 0 );
+      int typealgo =arg(15,stack, 1L );
+	
+      try {     
+	Kn &x = *GetAny<Kn *>((*X)(stack));	
+	const int n=x.N();
+	  Kn xmin(n),xmax(n);
+	  xmin=cmin;
+	  xmax=cmax;
+	  Set_arg(11,stack,xmin);
+	  Set_arg(12,stack,xmax);
+	  
+	//Kn * para =
+	GetAny<KN<double>*>( inittheparam.eval(stack) ) ; // do allocation 
+	
+	KN_<R> param(x);
+	//cout << nbrestart << " ---- \n";
+	lgBMO nrj1(stack,n,theparam,JJ,dJJ,nbrestart,nbext1,nbbvp,nbgrad,epsfd,rho000,epsloc,epsij,n100);
+	nrj1.diagrand=diagrand;
+	nrj1.debug=verbosity;
+	  nrj1.typealgo=typealgo;
+	  nrj1.histpath=datahist;
+	  nrj1.histcpath=datachist;
+	double fopt=nrj1.main(x,xmin,xmax);
+	
+	if(verbosity)
+	  {
+	  cout <<endl<<"*** RESULTS SUMMARY ***"<<endl;
+	
+	  if(verbosity>1) {
+	    cout <<"  The number of call to  J : "<< nrj1.nbeval << endl;
+	  cout <<"  The number of call to dJ : "<< nrj1.nbevalp << endl; }
+	  if(verbosity) {
+	    cout <<"  Initial J value : " << nrj1.finit << endl;
+	    cout <<"  Final   J  value : " << fopt<< endl;}
+	  }
+	}
+	catch (...)
+	  {
+	    closetheparam.eval(stack); // clean memory 
+	    WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+	    throw ;        
+	  }
+	closetheparam.eval(stack); // clean memory 
+	WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+      
+	
+	return 0L; //SetAny<long>(0);  Modif FH  july 2005 
+       
+    }    
+
+      
+      operator aType () const { return atype<long>();}         
+      
+    };
+
+    
+    
+    E_F0 * code(const basicAC_F0 & args) const {
+      return new E_BMO(args,cas);}
+    
+    OptimBMO(int c) :   OneOperator(atype<long>(),
+				    atype<Polymorphic*>(),
+				    atype<KN<R> *>()),cas(c){}
+    
+    OptimBMO(int c,int cc) :   OneOperator(atype<long>(),
+					   atype<Polymorphic*>(),
+					   atype<Polymorphic*>(),
+					   atype<KN<R> *>()),cas(c){}
+  
+   
+};
+
+
+//template<class R>
+      /* 
+       BijanMO(
+       ndim, 
+       nbrestart=1,
+       nbext1=1,
+       nbbvp=5,
+       nbgrad=5,
+       epsfd=1e-5,
+       rho000=100,
+       epsloc=1e-4,
+       epsij=1e-6,
+       n100=100)
+       
+       */
+
+basicAC_F0::name_and_type  OptimBMO::E_BMO::name_param[]= {
+ {  "eps", &typeid(double)  },
+ { "nbrestart",&typeid(long) },
+ { "nbbvp",&typeid(long)},
+ { "nbgrad",&typeid(long)},
+ { "epsfd",&typeid(double)},
+ { "rho000",&typeid(double)},
+ { "epsloc",&typeid(double)},
+ { "epsij",&typeid(double)},
+ { "n100",&typeid(long)}, // 8
+{ "max",&typeid(double)}, // 9
+{ "min",&typeid(double)}, // 10
+{ "vmax",&typeid(double)}, // 11
+{ "vmin",&typeid(double)}, // 12
+{ "histfile", & typeid(string*)}, // 13
+{ "histcfile", & typeid(string*)}, // 14
+{ "algo", & typeid(long)} // 15
+};
+
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init()  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+{
+  Global.Add("bmo","(",new OptimBMO(1));  //  j + dJ
+  Global.Add("bmo","(",new OptimBMO(1,1));  //  j + dJ
+
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/load.edp b/examples++-load/load.edp
new file mode 100644
index 0000000..fa92c8f
--- /dev/null
+++ b/examples++-load/load.edp
@@ -0,0 +1,13 @@
+// Example of dynamic function load
+// --------------------------------
+// $Id$
+
+ load "myfunction"
+// dumptable(cout);
+ mesh Th=square(5,5);
+ fespace Vh(Th,P1);
+ Vh uh= myfunction(); // warning  do not forget () 
+ cout << uh[].min << " " << uh[].max << endl;
+ cout << " test io ( " << endl;
+ testio();
+ cout << " )  end test io .. " << endl;
\ No newline at end of file
diff --git a/examples++-load/load.link.in b/examples++-load/load.link.in
new file mode 100755
index 0000000..4c88353
--- /dev/null
+++ b/examples++-load/load.link.in
@@ -0,0 +1,292 @@
+#!/bin/sh
+# Create a loadable object from a C++ function defined in a .cpp file
+# $Id$
+thecommand="$0"
+dircommand=`dirname "$0"`
+
+FFVERSION='@VERSION@'
+FFCXXFLAGS='@CXXFLAGS@ @CPPFLAGS@'
+FFFFLAGS='@FFLAGS@'
+FFFLIBS='@FLIBS@'
+INCFF=
+if [ "@ENABLE_FFCS@" != "yes" ] ;then ffcs=0; else ffcs=1;fi 
+if [ -z "$CXX" ] ; then CXX='@CXX@' ; fi
+if [ -z "$MPICXX" ] ; then MPICXX="@MPICXX@" ; fi
+if [ -z "$MPI_LIB" ] ; then MPI_LIB="@MPI_LIB@" ; fi
+if [ -z "$F77" ] ; then F77="@F77@" ; fi
+if [ "$CXX" = '@'CXX'@' ] ; then CXX=""; fi
+if [ "$MPICXX" = '@'MPICXX'@' ] ; then MPICXX=""; fi
+if [ "$F77" = '@'F77'@' ] ; then F77=""; fi
+if [ "$FFCXXFLAGS" = '@'CXXFLAGS'@' ] ; then FFCXXFLAGS=""; fi
+if [ "$FFFFLAGS" = '@'FFLAGS'@' ] ; then FFFFLAGS=""; fi
+if [ "$FFFLIBS" = '@'FLIBS'@' ] ; then FFFLIBS=""; fi
+if [ "$FFVERSION" = '@'VERSION'@' ] ; then FFVERSION=""; fi
+if [ -z "$INCFF" ] ; then
+    if [ -f "@INCFF@/ff++.hpp" ] ; then
+	INCFF="-I at INCFF@"
+    elif [ -f "${dircommand}/include/ff++.hpp" ]; then
+	INCFF="-I${dircommand}/include"
+    elif [ -f ../examples++-load/include/ff++.hpp ]; then
+	INCFF="-I../examples++-load/include"
+    elif [ -f "FFAPPLI_INC/ff++.hpp" ] ; then 
+	INCFF="-IFFAPPLI_INC" 
+    elif [ -f '@ff_prefix_dir@/include/ff++.hpp' ] ; then 
+	INCFF='-I at ff_prefix_dir@/include' 
+    else
+	ff=`which freefem++.exe`;
+	ffinc=`dirname "$ff"`/examples++-load/include
+	if [ -f "$ffinc/ff++.hpp" ]; then
+	  INCFF=-I"'$ffinc'";
+        else	
+	  echo " erreur PB include freefem++ directory " ;
+	  exit 1;
+	fi
+    fi
+fi
+do="yes"
+DEBUG=""
+CONLY="false"
+uu=`uname -s` 
+INC=""
+LIBS=""
+DLL=""
+bin="."
+out=""
+files=""
+fileso=""
+OTHER="";
+WIN32="";
+
+case "$uu" in
+  CYGWIN*|MINGW*)
+  if [ -z "@WIN32DLLTARGET@" ] ; then 
+      onwin32=1; uu="cygwin-version";
+  else
+      onwin32=1; uu="win32"; # pure windows 
+  fi
+  WIN32="win32-"
+  wff=`which FreeFem++.exe`
+  dff=`dirname "$wff"`
+  if [ "$bin" = "." -a  -f ../src/bin-win32/libff.dll  ]; then
+    bin=../src/bin-win32 
+  elif [  -f "$dff/libff.dll"  ]; then
+#  modif for install on cygwin
+    bin="$dff"
+  elif [ "$bin" = "." -a  -f ../libff.dll  ]; then
+    bin=..
+  elif [ "$bin" = "." -a  -f ../../libff.dll  ]; then
+    bin=../..
+  fi;; 
+esac
+autodep=""
+withmpi=""
+args=""
+
+while [ $# -ne 0 ]  ; do
+    argsp=$args
+    args="$args '$1'"
+    case "$1" in
+	-[h?]*) echo usage $0 "[-n] [-g] [-win32] [-l libfile] [-I includedir]  files"
+	    echo "    -auto :  build automaticaly the dependance (in test FH) "
+	    echo "    -n  :  do nothing just print"
+	    echo "    -g  :  compile with -g option"
+	    echo "    -c  : compile only"
+	    echo "    -mpi:  with  mpi"
+	    echo "    -nompi:  without   $MPI_LIB links "
+	    echo "    -O*  :  compile with -O* option"
+	    echo "    -cygwin: compile for cygwin/win32 OS (Window XP, ...)"
+	    echo "    -win32:  compile for win32 OS (Window XP, ...) default under cygwin"
+	    echo "    -l files  add files to the ld process (link)"
+	    echo "    -I dir  add dir in include seach dir for compilation"
+	    echo "    -b dir  to change the default install  dir " 
+	    echo "    -dll file  add  dll and this file copie in the install dir"
+	    echo "    -o outputfile without suffix"
+	    echo "    file.{cpp,cp,cxx,c,f,F}"
+	    exit 0;
+	    ;;
+	F77=*) F77=`echo $1|sed 's/[A-Z0-9]*=//'` ;;
+	CXX=*) CXX=`echo $1|sed 's/[A-Z0-9]*=//'` ;;
+	MPICXX=*) MPICXX=`echo $1|sed 's/[A-Z0-9]*=//'`;withmpi=yes ;;
+	F77=*) F77=`echo $1|sed 's/[A-Z0-9]*=//'` ;;
+	CXXFLAGS=*) CXXFLAGS=`echo $1|sed 's/[A-Z0-9]*=//'` ;;
+	FFLAGS=*) FFLAGS=`echo $1|sed 's/[A-Z0-9]*=//'` ;;
+	MPI_LIB=*) MPI_LIB=`echo $1|sed 's/[A-Z0-9]*=//'` ;;
+	-auto) autodep=yes;args=$argsp;;
+	-mpi) withmpi=yes;;
+	-nompi) MPI_LIB='';withmpi='';;
+	-n)  do="no";;
+	-g)  DEBUG="$DEBUG $1";;
+	-c)  CONLY=yes;;
+	-O*) DEBUG="$DEBUG $1";;
+	-cygwin)  onwin32=1; uu="cygwin-version";; 
+	-win32)   onwin32=1; uu="win32";; 
+	-b)     bin=$2  ; shift;;
+	-I*)    INC="$INC '$1'";;
+	-D*)    INC="$INC '$1'";;
+	-dll)   DLL="$DLL '$2'";shift;;
+	-[Ll]*)    LIBS="$LIBS '$1'" ;; # FFCS - 27/10/11 - need quotes for MPICH libraries in 'Program Files' under Windows
+	*.a)     LIBS="$LIBS $1" ;;
+	*.so)    LIBS="$LIBS $1" ;;
+	*.dll)   if [ -f "$1" ] ; then  LIBS="$LIBS '$1'"  
+	    elif [ -f "$bin/$1" ] ; then  LIBS="$LIBS '$bin/$1'"
+	    else
+	      echo " erreur file not found $1" ;
+	      exit 1;
+	    fi;;
+	-Wl*)    LIBS="$LIBS $1" ;;
+	*.cpp) files="$files '$1'";  o=`basename "$1" .cpp` ; fileso="$fileso '$o.o'"; args=$argsp;; 
+	*.cp)  files="$files '$1'";  o=`basename "$1" .cp`   ; fileso="$fileso '$o.o'"; args=$argsp;; 
+	*.cxx) files="$files '$1'";  o=`basename "$1" .cxx` ; fileso="$fileso '$o.o'"; args=$argsp;;
+	*.c)   files="$files '$1'";  o=`basename "$1" .c` ; fileso="$fileso '$o.o'"; args=$argsp;;  
+	*.f)   ffiles="$ffiles '$1'";  o=`basename "$1" .f` ; fileso="$fileso '$o.o'";; 
+	*.F)   ffiles="$ffiles '$1'";  o=`basename "$1" .F` ; fileso="$fileso '$o.o'";; 
+	*.o)   fileso="$fileso '$1'"; o=`basename "$1" .o` ;; 
+	-o)    out="$2"; shift;;
+	*) OTHER="$OTHER $1";;
+    esac
+    shift
+done
+
+#  remove old file... FH sep 2013..
+SUF=@DYLIB_SUFFIX@
+
+if [ -n "$autodep"  ] ; then
+#    echo "$thecommand" $args  `eval "'$dircommand/ff-get-dep'" -ff $files`
+    argsdep=`eval "'$dircommand/ff-get-dep'" -ff $files`
+    
+     error=`echo "$argsdep"| grep ERROR`
+     if [ -n "$error" ] ; then
+	 echo " WARNING in  auto dependance seach ( missing plugin $2) .  sorry : $error "
+
+	 # FFCS - 28/11/11 - we need to stop compiling as soon as there is an error because we want a fixed set of features in
+	 # FFCS
+	 # return a error when FFCS enable .. FH. 
+	 echo " -- $error " >>Missing-plugins- at DYLIB_SUFFIX@.log
+	 exit $ffcs;
+     fi
+    echo eval "$thecommand" $args  $argsdep
+    eval "$thecommand" $args  $argsdep
+
+    # FFCS needs an error exit code to make sure that all libraries are correctly compiled
+    exit $?;
+fi
+
+if [  -n "$onwin32" -a ! -f "$bin/libff.dll"  ] ; then 
+    echo " Error the file libff.dll  must be exist in '$bin' the install directory," 
+    echo " to link on windows OS "
+    echo " Use the parameter -b to set the correct install directory " 
+    exit 1;
+fi
+
+if [ -z "$out" ] ; then  out=$o  ; fi;
+if [ -f  "$out.$SUF" ] ; then rm $out.$SUF ; fi 
+
+
+# Default compiler
+if [ -z "$CXX"  ];then  CXX=g++ ; fi
+if [ -n "$withmpi" ]; then  CXX=$MPICXX;fi
+
+test "$withmpi" = "yes" && WMPI_LIB="$MPI_LIB"
+
+# build a mpi version of the plugin if the plugin do exist un mpi dir
+# and if the mpi version exist and if 
+OWMPI=""
+test  -d ../examples++-mpi -a -n "$MPI_LIB" -a "$withmpi" != "yes" -a ! -f  "../examples++-mpi/$out.cpp"  &&  OWMPI="../examples++-mpi/$out.$SUF"
+test -f "$OWMPI" -a -n "$OWMPI" && rm "$OWMPI"
+
+
+
+INC="$INCFF $INC"  
+SHARED="-shared"
+case "$WIN32$uu" in
+    Darwin*) 
+#        echo "export MACOSX_DEPLOYMENT_TARGET=10.3"
+#	export MACOSX_DEPLOYMENT_TARGET=10.4
+#	SUF=dylib
+	SHARED="-bundle -undefined dynamic_lookup"  ;;
+    win32-CYGWIN*|win32-win32)
+        echo " Window without cygwin "
+	WMPI_LIB=''
+        b="$bin"
+        LIBS=" '$b/libff.dll' '$b/FreeFem++-api.dll' $LIBS $DLL"
+
+	# FFCS - 17/10/12 - --unresolved-symbols=ignore-all is not understood by the current mingw64 compilers
+        SHARED="-shared -Wl,--enable-auto-import"
+
+	# FFCS - 17/10/12 - -mno-cygwin is not understood by the current mingw64 compilers
+        ###FLAGS='  -mno-cygwin '
+#        SUF=dll
+	;;
+    win32-cygwin-version)
+        echo " cygwin-version "
+	WMPI_LIB=''
+        b=$bin
+        FLAGS=' '
+        LIBS="'$b/libff.dll' $LIBS $DLL"
+#        SUF=dll
+	;;
+    FreeBSD|NetBSD)
+	SHARED="-shared" 
+	FLAGS='-fPIC';;
+	# 64 bit Linux needs -fPIC (ALH)
+    SunOS)
+        SHARED="-shared"
+        FLAGS='-fPIC';;
+        # 64 bit Linux needs -fPIC (ALH)
+    Linux)
+	FLAGS='-fPIC'
+	SHARED="-shared " ;;
+    *)
+	echo "sorry unknown achitecture "`uname`
+	exit 1;;
+esac
+
+
+#FLAGS="$FLAGS $DEBUG $FFCXXFLAGS"
+#  change F. H Version 3.17 
+FLAGS="$FLAGS $DEBUG"
+
+if [ -n "$ffiles$files$fileso" ] ; then
+    if [  -n "$WIN32"  -a  ! -f "$bin/libff.dll"  ]; then
+	echo " Sorry, no freefem .dll file (libff.dll)  in $bin dir "
+	echo " try with -b dir-path where the file libff.dll exist"
+	exit 1;
+    fi
+    if [ "$files" ] ;then 
+	echo $CXX -c $FLAGS $CXXFLAGS $FFCXXFLAGS $INC $PIC $files
+	if [  $do = yes ] ; then 
+	    eval $CXX -c $INC $FLAGS $CXXFLAGS $FFCXXFLAGS  $PIC  $files
+	    ret=$?; if [ $ret -ne 0 ] ; then exit $ret ;fi
+	fi
+    fi
+    if [ "$ffiles" ] ;then 
+	echo $F77 -c $FLAGS $FFLAGS $FFFFLAGS $INC $PIC $ffiles
+	LIBS="$FFFLIBS $LIBS"
+	if [  $do = yes ] ; then 
+	    eval $F77 -c $INC $FFLAGS $FLAGS $FFFFLAGS $PIC  $ffiles
+	    ret=$?; if [ $ret -ne 0 ] ; then exit $ret ;fi
+	fi
+    fi
+    if [ "$CONLY" != yes ]; then
+	echo $CXX $SHARED $FLAGS $CXXFLAGS $FFCXXFLAGS $fileso -o $out.$SUF $LIBS $DLL $OTHER $WMPI_LIB
+	if [  $do = yes ] ; then 
+	   eval $CXX $SHARED $FLAGS $CXXFLAGS $FFCXXFLAGS $fileso -o $out.$SUF $LIBS $DLL $OTHER $WMPI_LIB
+	    ret=$?; if [ $ret -ne 0 ] ; then exit $ret ;fi
+	fi
+	if [  "$bin" != "." ]; then
+	    echo cp $out.$SUF  $bin
+	    test $do = yes &&   cp $out.$SUF  "$bin"
+	fi
+	if [ -n "$DLL" ] ; then
+	    echo cp $DLL $bin
+	    test $do = yes &&   cp $DLL "$bin"
+	fi 
+	if [ -n "$OWMPI" ] ; then
+	    echo $CXX $SHARED $FLAGS $CXXFLAGS $FFCXXFLAGS $fileso -o $OWMPI $LIBS $DLL $OTHER $MPI_LIB
+	    if [  $do = yes ] ; then 
+		eval $CXX $SHARED $FLAGS $CXXFLAGS $FFCXXFLAGS $fileso -o $OWMPI $LIBS $DLL $OTHER $MPI_LIB
+		ret=$?; if [ $ret -ne 0 ] ; then exit $ret ;fi
+	    fi
+	fi
+    fi
+fi
diff --git a/examples++-load/mat_dervieux.cpp b/examples++-load/mat_dervieux.cpp
new file mode 100644
index 0000000..bb7b141
--- /dev/null
+++ b/examples++-load/mat_dervieux.cpp
@@ -0,0 +1,159 @@
+//  Implementation of P1-P0 FVM-FEM
+// ---------------------------------------------------------------------
+// $Id$
+// compile and link with ./load.link  mat\_dervieux.cpp 
+#include  <iostream>
+using namespace std;
+#include "cfloat"
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "Mesh3dn.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+/*
+#include  <iostream>
+#include  <cfloat>
+#include  <cmath>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "RNM.hpp"
+// remove problem of include 
+#undef  HAVE_LIBUMFPACK
+#undef HAVE_CADNA
+#include "MatriceCreuse_tpl.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+*/
+class MatrixUpWind0 :  public E_F0mps { public:
+  typedef Matrice_Creuse<R> * Result;
+  Expression emat,expTh,expc,expu1,expu2;
+  MatrixUpWind0(const basicAC_F0 & args)
+  {
+
+    args.SetNameParam();
+    emat =args[0]; // the matrix expression
+    expTh= to<pmesh>(args[1]);  // a the expression to get the mesh
+    expc = CastTo<double>(args[2]); // the expression to get c  (must be a double)
+    //  a array expression [ a, b]
+    const E_Array * a= dynamic_cast<const E_Array*>((Expression) args[3]);
+    if (a->size() != 2) CompileError("syntax:  MatrixUpWind0(Th,rhi,[u1,u2])");
+    int err =0;
+    expu1= CastTo<double>((*a)[0]); // fist exp of the array (must be a  double)
+    expu2= CastTo<double>((*a)[1]); // second exp of the array (must be a  double)
+
+  }
+
+  ~MatrixUpWind0()
+  {
+  }
+
+  static ArrayOfaType  typeargs()
+  { return  ArrayOfaType(atype<Matrice_Creuse<R>*>(),
+			 atype<pmesh>(),atype<double>(),atype<E_Array>());}
+  static  E_F0 * f(const basicAC_F0 & args){ return new MatrixUpWind0(args);}
+  AnyType operator()(Stack s) const ;
+
+};
+
+int   fvmP1P0(double q[3][2], double u[2],double c[3], double a[3][3], double where[3] )
+{                               // computes matrix a on a triangle for the Dervieux FVM
+  for(int i=0;i<3;i++) for(int j=0;j<3;j++) a[i][j]=0;
+
+  for(int i=0;i<3;i++){
+    int ip = (i+1)%3, ipp =(ip+1)%3;
+    double unL =-((q[ip][1]+q[i][1]-2*q[ipp][1])*u[0]
+		  -(q[ip][0]+q[i][0]-2*q[ipp][0])*u[1])/6;
+    if(unL>0) { a[i][i] += unL; a[ip][i]-=unL;}
+    else{ a[i][ip] += unL; a[ip][ip]-=unL;}
+    if(where[i]&&where[ip]){        // this is a boundary edge
+      unL=((q[ip][1]-q[i][1])*u[0] -(q[ip][0]-q[i][0])*u[1])/2;
+      if(unL>0) { a[i][i]+=unL; a[ip][ip]+=unL;}
+    }
+  }
+  return 1;
+}
+
+// the evaluation routine
+AnyType MatrixUpWind0::operator()(Stack stack) const
+{
+  Matrice_Creuse<R> * sparce_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+  MatriceMorse<R> * amorse =0;
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh = GetAny<pmesh>((*expTh)(stack));
+  ffassert(pTh);
+  Mesh & Th (*pTh);
+  {
+    map< pair<int,int>, R> Aij;
+    KN<double> cc(Th.nv);
+    double infini=DBL_MAX;
+    cc=infini;
+    for (int it=0;it<Th.nt;it++)
+      for (int iv=0;iv<3;iv++)
+	{
+	  int i=Th(it,iv);
+	  if ( cc[i]==infini) { // if nuset the set
+	    mp->setP(&Th,it,iv);
+	    cc[i]=GetAny<double>((*expc)(stack));
+	  }
+	}
+
+    for (int k=0;k<Th.nt;k++)
+      {
+	const Triangle & K(Th[k]);
+	const Vertex & A(K[0]), &B(K[1]),&C(K[2]);
+	R2 Pt(1./3.,1./3.);
+	R u[2];
+	MeshPointStack(stack)->set(Th,K(Pt),Pt,K,K.lab);
+	u[0] = GetAny< R>( (*expu1)(stack) ) ;
+	u[1] = GetAny< R>( (*expu2)(stack) ) ;
+
+	int ii[3] ={  Th(A), Th(B),Th(C)};
+	double q[3][2]= { { A.x,A.y} ,{B.x,B.y},{C.x,C.y} } ;  // coordinates of 3 vertices (input)
+	double c[3]={cc[ii[0]],cc[ii[1]],cc[ii[2]]};
+	double a[3][3], where[3]={(double) A.lab, (double) B.lab, (double)C.lab};
+	if (fvmP1P0(q,u,c,a,where) )
+	  {
+	    for (int i=0;i<3;i++)
+	      for (int j=0;j<3;j++)
+		if (fabs(a[i][j]) >= 1e-30)
+		  { Aij[make_pair(ii[i],ii[j])]+=a[i][j];
+		  }
+	  }
+      }
+    amorse=  new MatriceMorse<R>(Th.nv,Th.nv,Aij,false);
+  }
+  sparce_mat->Uh=UniqueffId();
+  sparce_mat->Vh=UniqueffId();
+  sparce_mat->A.master(amorse);
+  sparce_mat->typemat=(amorse->n == amorse->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+  *mp=mps;
+
+  if(verbosity>3) { cout << "  End Build MatrixUpWind : " << endl;}
+
+  return sparce_mat;
+}
+
+
+/*  class Init { public:
+  Init();
+};
+$1 */
+static void Load_Init()
+{
+  cout << " lood: init Mat Chacon " << endl;
+  Global.Add("MatUpWind1","(", new OneOperatorCode<MatrixUpWind0 >( ));
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/mat_psi.cpp b/examples++-load/mat_psi.cpp
new file mode 100644
index 0000000..9cb3746
--- /dev/null
+++ b/examples++-load/mat_psi.cpp
@@ -0,0 +1,271 @@
+// Example C++ function "myfunction", dynamically loaded into "load.edp"
+// ---------------------------------------------------------------------
+// $Id$
+
+
+#include "ff++.hpp"
+
+class MatrixUpWind0 :  public E_F0 { public: 
+  typedef Matrice_Creuse<R> * Result;
+  Expression emat,expTh,expc,expu1,expu2; 
+  MatrixUpWind0(const basicAC_F0 & args) 
+  {   
+    
+    args.SetNameParam();
+    emat =args[0];
+    expTh= to<pmesh>(args[1]);
+    expc = CastTo<double>(args[2]);
+    const E_Array * a= dynamic_cast<const E_Array*>((Expression) args[3]);
+    if (a->size() != 2) CompileError("syntax:  MatrixUpWind0(Th,rhi,[u1,u2])");
+    int err =0;
+    expu1= CastTo<double>((*a)[0]);
+    expu2= CastTo<double>((*a)[1]);
+    
+  }
+  
+  ~MatrixUpWind0() 
+  {  
+  }     
+  
+  static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<Matrice_Creuse<R>*>(),atype<pmesh>(),atype<double>(),atype<E_Array>());}
+  static  E_F0 * f(const basicAC_F0 & args){ return new MatrixUpWind0(args);} 
+  AnyType operator()(Stack s) const ;
+  
+};
+
+class MatrixUpWind3 :  public E_F0 { public: 
+    typedef Matrice_Creuse<R> * Result;
+    Expression emat,expTh,expc,expu1,expu2,expu3; 
+    MatrixUpWind3(const basicAC_F0 & args) 
+    {   
+	
+	args.SetNameParam();
+	emat =args[0];
+	expTh= to<pmesh3>(args[1]);
+	expc = CastTo<double>(args[2]);
+	const E_Array * a= dynamic_cast<const E_Array*>((Expression) args[3]);
+	if (a->size() != 3) CompileError("syntax:  MatrixUpWind0(Th,rhi,[u1,u2])");
+	int err =0;
+	expu1= CastTo<double>((*a)[0]);
+	expu2= CastTo<double>((*a)[1]);
+	expu3= CastTo<double>((*a)[2]);
+	
+    }
+    
+    ~MatrixUpWind3() 
+    {  
+    }     
+    
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<Matrice_Creuse<R>*>(),atype<pmesh3>(),atype<double>(),atype<E_Array>());}
+    static  E_F0 * f(const basicAC_F0 & args){ return new MatrixUpWind3(args);} 
+    AnyType operator()(Stack s) const ;
+    
+};
+
+int   gladys(double q[3][2], double u[2],double c[3], double a[3][3] )  //PSI Deconninck
+{				// computes matrix a on a triangle for the Chacon-Reina Petrof-Galerkin upwind
+  
+  // working arrays
+  double dw[3][2]; // basis function gradients times  area
+  double ua[2], kk[3], beta[3]; // to define a[][]
+  double udc=0;  // u.grad(w)*area
+  bool oneaval=false;
+  int i1=-1;
+  
+  for(int i=0;i<3;i++)
+    {
+      int ip=(i+1)%3, ipp=(ip+1)%3;
+      for(int j=0;j<2;j++)
+	dw[i][1-j]= (2*j-1)*(q[ipp][j]-q[ip][j])/2;
+    }
+  
+  for(int i=0;i<3;i++){
+    kk[i] = u[0]*dw[i][0]+u[1]*dw[i][1] ;
+    udc += kk[i]*c[i];
+  }
+  
+  for(int i=0;i<3;i++)
+    {
+      ua[0]=u[0]; ua[1]=u[1];
+      int ip=(i+1)%3, ipp=(ip+1)%3;
+      if(kk[i]>0 && kk[ip]<=0 && kk[ipp]<=0)
+	{
+	  beta[i]=1; beta[ip]=0; beta[ipp]=0; oneaval=true;
+	}
+      else if(kk[i]<=0 && kk[ip]>0 && kk[ipp]>0) i1=i;
+    }
+  
+  if(!oneaval)
+    {
+      if(i1<0)cout<<"bug\n";
+      int i=i1, ip=(i+1)%3, ipp=(i+2)%3;
+      double lambda = (c[ip]-c[i])*(c[ipp]-c[i]);
+      if (fabs(lambda) < -1e-20)
+        {
+	  return 0;
+	}
+      if(lambda < 0)
+	{
+	  if (udc>0)
+	    {
+	      beta[i]=0; beta[ip]=0; beta[ipp]=1;
+	      ua[0] = udc*(q[ipp][0]-q[i][0])/(c[ipp]-c[i]); 
+	      ua[1] = udc*(q[ipp][1]-q[i][1])/(c[ipp]-c[i]);
+	    }
+	  else
+	    {
+	      beta[i]=0; beta[ipp]=0; beta[ip]=1;
+	      ua[0] = udc*(q[ip][0]-q[i][0])/(c[ip]-c[i]); 
+	      ua[1] = udc*(q[ip][1]-q[i][1])/(c[ip]-c[i]);
+	    }
+	}
+      else 
+	{
+	  beta[i]=0; 
+	  beta[ip]=kk[ip]*(c[ip]-c[i])/udc; 
+	  beta[ipp]=kk[ipp]*(c[ipp]-c[i])/udc;
+	}
+    }
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++)
+      a[i][j]= beta[i]*(ua[0]*dw[j][0]+ua[1]*dw[j][1]);
+  return 1;
+}		
+
+
+AnyType MatrixUpWind0::operator()(Stack stack) const 
+{
+  Matrice_Creuse<R> * sparce_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack)); 
+  MatriceMorse<R> * amorse =0; 
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh = GetAny<pmesh>((*expTh)(stack));
+  ffassert(pTh);
+  Mesh & Th (*pTh);
+  {
+    map< pair<int,int>, R> Aij;
+    KN<double> cc(Th.nv);
+    double infini=DBL_MAX;   
+    cc=infini;
+    for (int it=0;it<Th.nt;it++)
+      for (int iv=0;iv<3;iv++)
+	{
+	  int i=Th(it,iv);
+	  if ( cc[i]==infini) { // if nuset the set 
+	    mp->setP(&Th,it,iv);
+	    cc[i]=GetAny<double>((*expc)(stack));
+	  }
+	}
+    
+    for (int k=0;k<Th.nt;k++)
+      {   
+	const Triangle & K(Th[k]); 
+	const Vertex & A(K[0]), &B(K[1]),&C(K[2]);
+	R2 Pt(1./3.,1./3.);
+	R u[2];
+	MeshPointStack(stack)->set(Th,K(Pt),Pt,K,K.lab);
+	u[0] = GetAny< R>( (*expu1)(stack) ) ;
+	u[1] = GetAny< R>( (*expu2)(stack) ) ;
+	
+	int ii[3] ={  Th(A), Th(B),Th(C)};
+	double q[3][2]= { { A.x,A.y} ,{B.x,B.y},{C.x,C.y} } ;  // coordinates of 3 vertices (input)
+	double c[3]={cc[ii[0]],cc[ii[1]],cc[ii[2]]};
+	double a[3][3];
+	if (gladys(q,u,c,a) )
+	  {
+	    for (int i=0;i<3;i++)
+	      for (int j=0;j<3;j++)
+		if (fabs(a[i][j]) >= 1e-30)
+		  Aij[make_pair(ii[i],ii[j])]+=a[i][j];	   
+	  }
+      }
+    amorse=  new MatriceMorse<R>(Th.nv,Th.nv,Aij,false); 
+  }
+  sparce_mat->Uh=UniqueffId();
+  sparce_mat->Vh=UniqueffId();
+  sparce_mat->A.master(amorse);
+  sparce_mat->typemat=(amorse->n == amorse->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+  *mp=mps;
+  
+  if(verbosity>3) { cout << "  End Build MatrixUpWind : " << endl;}
+  
+  return sparce_mat;  
+}
+int   Marco(const Mesh3::Element & K, R3 U,R c[4], double a[4][4] )  //PSI Deconninck
+{
+    ExecError("Not Implemented Sorry Marco!");
+    return 0;
+}
+AnyType MatrixUpWind3::operator()(Stack stack) const 
+{
+    Matrice_Creuse<R> * sparce_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack)); 
+    MatriceMorse<R> * amorse =0; 
+    MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+    Mesh3 * pTh = GetAny<pmesh3>((*expTh)(stack));
+    ffassert(pTh);
+    Mesh3 & Th (*pTh);
+  {
+      map< pair<int,int>, R> Aij;
+      KN<double> cc(Th.nv);
+      double infini=DBL_MAX;   
+      cc=infini;
+      for (int it=0;it<Th.nt;it++)
+	  for (int iv=0;iv<4;iv++)
+	    {
+		int i=Th(it,iv);
+		if ( cc[i]==infini) { // if nuset the set 
+		    mp->setP(&Th,it,iv);
+		    cc[i]=GetAny<double>((*expc)(stack));
+		}
+	    }
+      
+      for (int k=0;k<Th.nt;k++)
+	{   
+	    const Mesh3::Element & K(Th[k]); 
+	    const Mesh3::Vertex & A(K[0]), &B(K[1]),&C(K[2]),&D(K[3]);
+	    R3 Pt(1./4.,1./4.,1./4.);
+	    R3 U;
+	    MeshPointStack(stack)->set(Th,K(Pt),Pt,K,K.lab);
+	    U.x = GetAny< R>( (*expu1)(stack) ) ;
+	    U.y = GetAny< R>( (*expu2)(stack) ) ;
+	    U.z = GetAny< R>( (*expu3)(stack) ) ;
+	    
+	    int ii[4] ={  Th(A), Th(B),Th(C),Th(D)};//  number of 4 vertex
+	   
+	    double c[4]={cc[ii[0]],cc[ii[1]],cc[ii[2]],cc[ii[3]]};
+	    double a[4][4];
+	    if (Marco(K,U,c,a) )
+	      {
+		  for (int i=0;i<4;i++)
+		      for (int j=0;j<4;j++)
+			  if (fabs(a[i][j]) >= 1e-30)
+			      Aij[make_pair(ii[i],ii[j])]+=a[i][j];	   
+	      }
+	}
+      amorse=  new MatriceMorse<R>(Th.nv,Th.nv,Aij,false); 
+  }
+    sparce_mat->Uh=UniqueffId();
+    sparce_mat->Vh=UniqueffId();
+    sparce_mat->A.master(amorse);
+    sparce_mat->typemat=(amorse->n == amorse->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+    *mp=mps;
+    
+    if(verbosity>3) { cout << "  End Build MatrixUpWind : " << endl;}
+    
+    return sparce_mat;  
+    
+}
+
+
+
+/*  class Init { public:
+  Init();
+};
+ Init init;
+*/
+ static void Load_Init()
+   {
+     cout << " lood: init Mat Chacon " << endl;
+     Global.Add("MatUpWind0","(", new OneOperatorCode<MatrixUpWind0 >( ));
+     Global.Add("MatUpWind0","(", new OneOperatorCode<MatrixUpWind3 >( ));
+ }
+LOADFUNC(Load_Init)
diff --git a/examples++-load/medit.cpp b/examples++-load/medit.cpp
new file mode 100644
index 0000000..bc72e4f
--- /dev/null
+++ b/examples++-load/medit.cpp
@@ -0,0 +1,2427 @@
+// ORIG-DATE:     Aout 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : liaison medit freefem++ : popen  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+#include "../src/Graphics/mode_open.hpp" // ALH - there should be a '-I'?
+#include "ff++.hpp"
+#define WrdSiz 4
+
+#ifdef WIN32
+string stringffmedit= "ffmedit.exe";
+//string stringemptymedit= "ffmedit.exe";
+#else
+string stringffmedit= "ffmedit";
+#endif
+
+
+const char *medit_popen="-popen";// 1";  // depend de l endroit ou se trouve medit
+const char *medit_bin="-filebin";
+const char *medit_addsol="-addsol";
+
+const char *medit_debug="-d";
+
+static bool TheWait=false;
+bool  NoWait=false;
+extern bool  NoGraphicWindow;
+using namespace std;
+using namespace Fem2D;
+
+//*******************************
+//
+// read solution of .sol or .solb
+//
+//*******************************
+
+class readsol_Op : public E_F0mps 
+{
+public:
+  typedef KN_<double> Result;
+  Expression eTh;
+  Expression filename;
+
+  static const int n_name_param = 1;  
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+ 
+public:
+  /*
+  readsol_Op(const basicAC_F0 &  args, Expression ffname) : filename(ffname)
+  {
+    if(verbosity>2)  cout << "readsol"<< endl;
+    args.SetNameParam(n_name_param,name_param,nargs);    
+  }
+  */
+  readsol_Op(const basicAC_F0 &  args) 
+  {
+    if(verbosity>2)  cout << "readsol"<< endl;
+    args.SetNameParam(n_name_param,name_param,nargs);    
+    if ( BCastTo<string *>(args[0]) ) 
+      filename = CastTo<string *>(args[0]);
+    else 
+      CompileError("no filename given");
+
+  }
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<string *>(),true ); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new readsol_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+  operator aType () const { return atype< KN_<double> >();} 
+};
+
+basicAC_F0::name_and_type readsol_Op::name_param[]= {
+  {  "number",&typeid(long) }
+};
+
+AnyType readsol_Op::operator()(Stack stack)  const 
+{ 
+  string * ffname= GetAny<string *>( (*filename)(stack) );
+  int         k,i,isol,type,inm,ver,dim,typtab[GmfMaxTyp],offset;
+  char        *ptr,data[128];
+  //          rajout freefem++
+  int         nv=0,ntet=0,ntri=0;
+  int         nsol;
+  int         key;
+
+  int numsol(arg(0,stack,-1L)); 
+  assert(abs(numsol)>=1);
+
+  char * charfile= new char[ffname->size()+1];
+  strncpy(charfile,ffname->c_str(),ffname->size()+1);
+
+  strcpy(data,charfile);
+  ptr = strstr(data,".sol");
+  if ( ptr )  *ptr = '\0';
+  strcat(data,".solb");
+  if( !(inm = GmfOpenMesh(data, GmfRead, &ver,&dim)) ) {
+    ptr  = strstr(data,".solb");
+    *ptr = '\0';
+    strcat(data,".sol");
+    if( !(inm = GmfOpenMesh(data, GmfRead, &ver,&dim)) ) {
+      cerr << "  ** "<< (char *) data << " NOT FOUND.\n" << endl;
+      exit(1);
+    }
+  }
+  if(verbosity>2)
+  cout <<"  %%%%" << (char *) data <<  " OPENED\n" << endl;
+
+  nv = GmfStatKwd(inm,GmfSolAtVertices,&type,&offset,&typtab);
+  if( nv ){
+    key  = GmfSolAtVertices;
+    nsol = nv;
+  }
+  else{
+    ntri = GmfStatKwd(inm,GmfSolAtTriangles,&type,&offset,&typtab);
+    if( ntri ){
+      key = GmfSolAtTriangles;
+      nsol = ntri;
+    }
+    else
+      ntet = GmfStatKwd(inm,GmfSolAtTetrahedra,&type,&offset,&typtab);
+    if( ntet ){
+      key = GmfSolAtTetrahedra;
+      nsol = ntet;
+    }
+  }
+
+  if ( (nv == 0) && (ntri == 0)  && (ntet == 0) ){
+    cerr << "  ** MISSING DATA" << endl;
+    exit(1);
+  }
+
+  int nbsol = nsol*offset;
+  int offsettab = 0;
+  int firstelem = 0;
+  if(numsol != -1){
+    if( typtab[numsol-1] == 1){
+      nbsol=nsol;
+      offsettab = 1;
+    }
+    else  if( typtab[numsol-1] == 2){
+      nbsol=nsol*dim;
+      offsettab = dim;
+    }
+    else  if( typtab[numsol-1] == 3){
+      nbsol=nsol*dim*(dim+1)/2;
+      offsettab = dim*(dim+1)/2;
+    }
+    else{
+      cerr << "bug in the definition of type of solution: 1 scalar, 2 vector, 3 symetric tensor" << endl;
+      exit(1);
+    }
+    
+    for(int ii=0; ii< (numsol-1); ii++)
+      if( typtab[ii] == 1)
+	firstelem=firstelem+1;
+      else  if( typtab[ii] == 2){
+	firstelem=firstelem+dim;
+      }
+      else  if( typtab[ii] == 3){
+	firstelem=firstelem+dim*(dim+1)/2;;
+      }
+      else{
+	cerr << "bug in the definition of type of solution: 1 scalar, 2 vector, 3 symetric tensor" << endl;
+	exit(1);
+      }
+  }
+  
+  if(verbosity >5) 
+    cout << "nbsol " << nbsol << " offset " << offset << "  " << nsol << " "<< endl;
+  
+  float       *buf =new float[offset];
+  double      tmp;
+  double      *bufd=new double[offset];
+  
+  KN<double> *ptabsol = new KN<double>(nbsol);
+  KN<double>  &tabsol =*ptabsol;
+  
+  if(numsol == -1){
+    GmfGotoKwd(inm,key);
+    if( ver == GmfFloat ){
+      for (k=1; k<=nsol; k++) {
+	isol = (k-1) * offset ;	
+	GmfGetLin(inm,key,buf);
+	for (i=0; i<offset; i++)
+	  tabsol[isol + i] = (double) buf[i];
+      }
+    }
+    else{
+      for (k=1; k<=nsol; k++) {
+	isol = (k-1) * offset ;	
+	GmfGetLin(inm,key,bufd);
+	for (i=0; i<offset; i++)
+	  tabsol[isol + i] = bufd[i];		
+      }
+    }
+  }
+  else{   
+    GmfGotoKwd(inm,key);
+    if( ver == GmfFloat ){
+      for (k=1; k<=nsol; k++) {
+	isol = (k-1)*offsettab;	
+	GmfGetLin(inm,key,buf);
+	for (i=0; i<offsettab; i++)
+	  tabsol[isol + i] = buf[i+firstelem];		
+	
+      }
+    }
+    else{
+      for (k=1; k<=nsol; k++) {
+	isol = (k-1)*offsettab;
+	GmfGetLin(inm,key,bufd);
+	for (i=0; i<offset; i++)
+	  tabsol[isol + i] = bufd[i+firstelem];		
+      }
+    }
+  }
+  /* // A prendre en compte dans la d�finition de la metriques dans MMG
+     // MMG_swap data 
+     if ( sol->offset == 6 ) {
+     tmp                = sol->met[isol + 2];
+     sol->met[isol + 2] = sol->met[isol + 3];
+     sol->met[isol + 3] = tmp;
+  */
+  
+  GmfCloseMesh(inm);
+  delete [] buf;
+  delete [] bufd;
+ 
+  Add2StackOfPtr2Free(stack,ptabsol);
+  return SetAny< KN<double> >(tabsol);  
+}
+  
+
+
+//*************************
+//
+//   creation point sol
+//
+//*************************
+// datasolMesh2
+
+class datasolMesh2_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  
+  struct Expression2 {
+    long what; // 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 1 scalar, 2 vector (3D), 3 symtensor(3D)
+    string *dataname; 
+    Expression e[3];
+    Expression2() {e[0]=0; e[1]=0; e[2]=0;  what=0; nbfloat=0;};
+    Expression &operator[](int i){return e[i];}
+    double eval(int i,Stack stack) const  { 
+    if (e[i]) {
+      return GetAny< double >( (*e[i])(stack) );
+    }
+    else 
+      return 0;
+    }
+  };
+  vector<Expression2> l;
+  static const int n_name_param = 1;  
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+ 
+public:
+  datasolMesh2_Op(const basicAC_F0 &  args) : l( args.size()-2 )
+  {
+    int nbofsol;
+    int ddim=2;
+    int stsize=3;
+    //cout << "construction data medit solution avec datasolMesh2_Op" << args << endl;
+    //cout << "taille de args" << args.size() << endl;
+    args.SetNameParam(n_name_param,name_param,nargs); 
+
+    if (BCastTo<string *>(args[0])) filename = CastTo<string *>(args[0]);
+    if (BCastTo<pmesh>(args[1])) eTh= CastTo<pmesh>(args[1]);
+   
+  
+    nbofsol = l.size();
+    for (size_t i=2;i<args.size();i++){
+      size_t jj=i-2;
+
+      if ( BCastTo<double>( args[i] ))
+	{
+	  l[jj].what=1;
+	  l[jj].nbfloat=1;
+	  l[jj][0]=to<double>( args[i] );	  
+	}
+      else if ( args[i].left()==atype<E_Array>() )
+	{
+	  const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	  //cout << "taille" << a0->size() << endl;
+	  if (a0->size() != ddim && a0->size() != stsize) 
+	    CompileError("savesol in 2D: vector solution is 2 composant, tensor solution is 3 composant");
+	  
+	  if( a0->size() == ddim){
+	    // vector solution
+	    l[jj].what=2;
+	    l[jj].nbfloat=ddim;
+	    for(int j=0; j<ddim; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }
+	  else if( a0->size() == stsize){
+	    // symmetric tensor solution
+	    l[jj].what=3;
+	    l[jj].nbfloat=stsize;
+	    for(int j=0; j<stsize; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }
+	  
+	}
+      else {
+	cout << " arg " << i << " " << args[i].left() << endl;
+	CompileError("savesol in 2D: Sorry no way to save this kind of data");
+      }
+      
+    }
+  }
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<string *>(), atype<pmesh>(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new datasolMesh2_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type datasolMesh2_Op::name_param[]= {
+  {  "order",&typeid(long)}
+};
+
+AnyType datasolMesh2_Op::operator()(Stack stack)  const 
+{ 
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  string * ffname= GetAny<string *>( (*filename)(stack) );
+  ffassert(pTh);
+  Mesh &Th=*pTh;
+
+  int nt = Th.nt;
+  int nv = Th.nv;
+
+  int nbtype=l.size();
+  int nbsol;
+  int solnbfloat;
+  int TypTab[l.size()];
+ 
+  int resultorder= arg(0, stack, 1L);
+  long longdefault;
+
+  int ver = GmfFloat, outm;
+  // determination de TypTab
+  solnbfloat=0;
+  for (size_t i=0;i<l.size();i++){
+    TypTab[i]=l[i].what;
+    solnbfloat=solnbfloat+l[i].nbfloat;
+  }
+  float *OutSolTab = new float[solnbfloat];
+
+  // determination de OutSolTab
+
+  char * ret= new char[ffname->size()+1];
+  strcpy(ret, ffname->c_str());
+
+  if ( !(outm = GmfOpenMesh( ret, GmfWrite, ver, 2)) ) {
+    cerr <<"  -- Mesh3::Save  UNABLE TO OPEN  :"<< ret << endl;
+    exit(1);
+  }
+ 
+  if(resultorder==0){
+    // ordre 0
+    nbsol = nt;  
+    
+    KN<double> valsol(solnbfloat*nbsol);
+ 
+    MeshPoint *mp3(MeshPointStack(stack)); 
+    R2 Cdg_hat = R2(1./3.,1./3.);  
+
+    for (int it=0;it<nt;it++){
+      int h=0;
+      const Mesh::Triangle  & K(Th.t(it));
+      mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+      for(size_t i=0;i<l.size();i++){
+	for(size_t j=0;j<l[i].nbfloat;j++){
+	  valsol[it*solnbfloat+h] = l[i].eval(j,stack);
+	  h=h+1;
+	}
+      } 
+      assert(solnbfloat==h);
+    }
+
+
+    GmfSetKwd(outm,GmfSolAtTriangles, nbsol, nbtype, TypTab);
+    for (int k=0; k<nbsol; k++){
+      for (int i=0; i<solnbfloat ;i++){
+	OutSolTab[i] = valsol(k*solnbfloat+i);
+      }
+      GmfSetLin(outm, GmfSolAtTriangles, OutSolTab); 
+    }
+  }
+  if(resultorder==1){
+    // ordre 1
+    nbsol = nv;  
+
+    KN<double> valsol(solnbfloat*nbsol);
+    valsol=0.;
+    KN<int> takemesh(nbsol);
+    MeshPoint *mp3(MeshPointStack(stack)); 
+    //R2 Cdg_hat = R2(1./3.,1./3.);
+    takemesh=0;
+    for (int it=0;it<nt;it++){
+      for(int iv=0;iv<3;iv++){
+	int i=Th(it,iv);
+
+	//if(takemesh[i]==0){
+	mp3->setP(&Th,it,iv);
+	int h=0;
+	
+	for(size_t ii=0;ii<l.size();ii++){
+	  for(size_t j=0;j<l[ii].nbfloat;j++){
+	    //cout << "ii=" << ii << " j=" << j<< endl;
+	    valsol[i*solnbfloat+h] = valsol[i*solnbfloat+h] + l[ii].eval(j,stack);
+	    h=h+1;
+	  }
+	} 
+	assert(solnbfloat==h);
+	takemesh[i] = takemesh[i]+1;
+	//}
+      }
+    }
+    for(int i=0; i<nv; i++){
+      for(int h=0; h<solnbfloat; h++){
+	valsol[i*solnbfloat+h] = valsol[i*solnbfloat+h]/takemesh[i]; 
+      }
+    }
+
+    GmfSetKwd(outm,GmfSolAtVertices, nbsol, nbtype, TypTab);
+    for (int k=0; k<nbsol; k++){
+      for (int i=0; i<solnbfloat ;i++){
+	OutSolTab[i] =  valsol(k*solnbfloat+i);
+      }
+      GmfSetLin(outm, GmfSolAtVertices, OutSolTab);
+    }
+  }
+  GmfCloseMesh(outm);
+  delete [] ret;
+  delete [] OutSolTab;
+  return longdefault;
+}
+  
+// datasolMesh3
+template<class v_fes>
+class datasolMesh3_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  
+  struct Expression2 {
+    long what; // 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 1 scalar, 3 vector (3D), 6 symtensor(3D)
+    Expression e[6];
+    Expression2() {e[0]=0; e[1]=0; e[2]=0; e[3]=0; e[4]=0; e[5]=0; what=0; nbfloat=0;};
+    Expression &operator[](int i){return e[i];}
+    double eval(int i,Stack stack) const  { 
+    if (e[i]) {
+      return GetAny< double >( (*e[i])(stack) );
+    }
+    else 
+      return 0;
+    }
+    
+  };
+  vector<Expression2> l; 
+  static const int n_name_param =1;  
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+ 
+public:
+  datasolMesh3_Op(const basicAC_F0 &  args) : l( args.size()-2 )
+  {
+    int nbofsol;
+    int ddim=3;
+    int stsize=6;
+    //cout << "construction data medit solution avec datasolMesh3_Op" << args << endl;
+    args.SetNameParam(n_name_param,name_param,nargs); 
+
+    //if (BCastTo<string *>(args[0])){
+      filename = CastTo<string *>(args[0]);
+      // }
+      //if (BCastTo<pmesh3>(args[1])){
+      eTh= CastTo<pmesh3>(args[1]);
+      // }
+    nbofsol = l.size();
+    for (size_t i=2;i<args.size();i++){
+      size_t jj=i-2;
+
+      if ( BCastTo<double>(args[i]))
+	{
+	  l[jj].what=1;
+	  l[jj].nbfloat=1;
+	  l[jj][0]=to<double>( args[i] );
+	  
+	}
+      else if ( args[i].left()==atype<E_Array>() )
+	{
+	  const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	  //cout << "taille" << a0->size() << endl;
+	  if (a0->size() != ddim && a0->size() != stsize) 
+	    CompileError("savesol in 3D: vector solution is 3 composant, vector solution is 6 composant");
+
+	  if( a0->size() == ddim){
+	    // vector solution
+	    l[jj].what=2;
+	    l[jj].nbfloat=ddim;
+	    for(int j=0; j<ddim; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }
+	  else if( a0->size() == stsize){
+	    // symmetric tensor solution
+	    l[jj].what=3;
+	    l[jj].nbfloat=stsize;
+	    for(int j=0; j<stsize; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }
+	  
+	}
+      else {
+	CompileError("savesol in 3D: Sorry no way to save this kind of data");
+      }
+
+    }
+  }
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<string *>(), atype<pmesh3>(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new datasolMesh3_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+};
+template<class v_fes>
+basicAC_F0::name_and_type datasolMesh3_Op<v_fes>::name_param[]= {
+  { "order",&typeid(long)}
+};
+template<class v_fes>
+AnyType datasolMesh3_Op<v_fes>::operator()(Stack stack)  const 
+{ 
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  string * ffname= GetAny<string *>( (*filename)(stack) );
+  ffassert(pTh);
+  Mesh3 &Th=*pTh;
+
+  int nt = Th.nt;
+  int nv = Th.nv;
+  int nbe = Th.nbe;
+  int nbtype=l.size();
+  int nbsol;
+  int solnbfloat;
+  int TypTab[l.size()];
+ 
+  int resultorder= arg(0, stack, 1);
+  long longdefault;
+
+  int ver = GmfFloat, outm;
+  // determination de TypTab
+  solnbfloat=0;
+  for (size_t i=0;i<l.size();i++){
+    TypTab[i]=l[i].what;
+    solnbfloat=solnbfloat+l[i].nbfloat;
+  }
+  float *OutSolTab = new float[solnbfloat];
+
+  // determination de OutSolTab
+
+  char * ret= new char[ffname->size()+1];
+  strcpy(ret, ffname->c_str());
+  if(verbosity>2)
+    cout << ret << endl;
+  if ( !(outm = GmfOpenMesh( ret, GmfWrite, ver, 3)) ) {
+    cerr <<"  -- Mesh3::Save  UNABLE TO OPEN  :"<< filename << endl;
+    exit(1);
+  }
+ 
+  if(resultorder==0){
+    // Tetrahedra
+    // ordre 0
+    nbsol = nt;      
+    KN<double> valsol(solnbfloat*nbsol);
+ 
+    MeshPoint *mp3(MeshPointStack(stack)); 
+    R3 Cdg_hat = R3(1./4.,1./4.,1./4.);  
+
+    for (int it=0;it<nt;it++){
+      int h=0;
+      const Tet & K(Th.elements[it]);
+      mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	  
+      for(size_t i=0;i<l.size();i++){
+	for(size_t j=0;j<l[i].nbfloat;j++){
+	  valsol[it*solnbfloat+h] = l[i].eval(j,stack);
+	  h=h+1;
+	}
+      } 
+      assert(solnbfloat==h);
+    }
+    
+    GmfSetKwd(outm,GmfSolAtTetrahedra, nbsol, nbtype, TypTab);
+    for (int k=0; k<nbsol; k++){
+      for (int i=0; i<solnbfloat ;i++){
+	OutSolTab[i] =  valsol(k*solnbfloat+i);
+      }
+      GmfSetLin(outm, GmfSolAtTetrahedra, OutSolTab); 
+    }
+    
+    /*
+    // Rajout des Triangles
+    nbsol = nbe;      
+    
+    KN<double> valsol2(solnbfloat*nbsol);
+    //cout << "value of triangles in the border nbe="<< nbe << endl;
+    MeshPoint *mp32(MeshPointStack(stack)); 
+     
+    for (int it=0;it<nbe;it++){
+      int h=0;
+      const Triangle3 & K(Th.be(it));
+      R xg,yg,zg;
+      int iv[3];
+      for(int jj=0; jj <3; jj++){
+	iv[jj] = Th.operator()(K[jj]); 
+      }
+
+      xg = Th.vertices[iv[0]].x + Th.vertices[iv[1]].x + Th.vertices[iv[2]].x;
+      yg = Th.vertices[iv[0]].y + Th.vertices[iv[1]].y + Th.vertices[iv[2]].y;
+      zg = Th.vertices[iv[0]].z + Th.vertices[iv[1]].z + Th.vertices[iv[2]].z;
+
+      xg=xg/3.;
+      yg=yg/3.;
+      zg=zg/3.;
+
+      mp32->set(xg,yg,zg);
+	  
+      for(size_t i=0;i<l.size();i++){
+	for(size_t j=0;j<l[i].nbfloat;j++){
+	  valsol2[it*solnbfloat+h] = l[i].eval(j,stack);
+	  h=h+1;
+	}
+      } 
+      assert(solnbfloat==h);
+    }
+
+    GmfSetKwd(outm,GmfSolAtTriangles, nbsol, nbtype, TypTab);
+    for (int k=0; k<nbsol; k++){
+      for (int i=0; i<solnbfloat ;i++){
+	OutSolTab[i] =  valsol2(k*solnbfloat+i);
+      }
+      //cout <<"GmfSetLin(outm, GmfSolAtTriangles, OutSolTab);"<< endl;
+      GmfSetLin(outm, GmfSolAtTriangles, OutSolTab); 
+    }
+
+    */
+  }
+  if(resultorder==1){
+    // ordre 1
+    nbsol = nv;  
+
+    KN<double> valsol(solnbfloat*nbsol);
+    KN<int> takemesh(nbsol);
+    MeshPoint *mp3(MeshPointStack(stack)); 
+    R3 Cdg_hat = R3(1./4.,1./4.,1./4.);
+    takemesh=0;
+    for (int it=0;it<nt;it++){
+      for(int iv=0;iv<4;iv++){
+	int i=Th(it,iv);
+
+	if(takemesh[i]==0){
+	    mp3->setP(&Th,it,iv);
+	    int h=0;
+
+	    for(size_t ii=0;ii<l.size();ii++){
+	      for(size_t j=0;j<l[ii].nbfloat;j++){
+		//cout << "ii=" << ii << " j=" << j<< endl;
+		valsol[i*solnbfloat+h] = l[ii].eval(j,stack);
+		h=h+1;
+	      }
+	    } 
+	    assert(solnbfloat==h);
+	    takemesh[i] = takemesh[i]+1;
+	}
+      }
+    }
+
+
+    GmfSetKwd(outm,GmfSolAtVertices, nbsol, nbtype, TypTab);
+    for (int k=0; k<nbsol; k++){
+      for (int i=0; i<solnbfloat ;i++){
+	OutSolTab[i] =  valsol(k*solnbfloat+i);
+      }
+      GmfSetLin(outm, GmfSolAtVertices, OutSolTab);
+    }
+  }
+  GmfCloseMesh(outm);
+  delete [] ret;
+  delete [] OutSolTab;
+  return longdefault;
+}
+
+//*************************
+//
+//  medit
+//
+//*************************
+
+static char * meditcmd(long filebin, int nbsol, int smedit, const string &meditff, const string & ffnn)
+{
+  string meditcmm=meditff;
+  int ddebug=0;
+  if(ddebug)
+    {
+      meditcmm += ' ';
+      meditcmm += medit_debug;
+    }
+  meditcmm += ' ';
+  meditcmm += medit_popen;
+  if(filebin)
+    {
+      meditcmm += ' ';
+      meditcmm += medit_bin;
+    }
+  if(nbsol) 
+    {
+      meditcmm += ' ';
+      meditcmm += medit_addsol;
+    }
+  
+  char meditsol[5];
+  sprintf(meditsol," %i",smedit);
+  meditcmm += meditsol; 
+   
+  meditcmm += ' ';
+
+  KN<char>  ret1(ffnn.size()+1);
+  strcpy( ret1, ffnn.c_str()); 
+  
+  int nbstrings=1;
+  char *tictac;
+  tictac= strtok(ret1," \n");
+  
+  meditcmm += ' ';
+  meditcmm += tictac;
+  while( tictac != NULL && nbstrings < nbsol){
+    tictac = strtok(NULL," \n");
+     meditcmm += ' ';
+     meditcmm += tictac;
+    nbstrings++;
+  }
+  if(nbstrings != smedit ){
+    cout << "The number of string defined in string parameter is different of the number of solution" << endl;
+    if( nbstrings < smedit ){
+      // Add strings
+      while( nbstrings < smedit ){
+	nbstrings++;
+	char newsol[10];
+	sprintf(newsol," ffsol%i",nbstrings);
+	meditcmm += newsol;
+      }
+    }
+  }
+  
+
+  char * ret= new char[meditcmm.size()+1];
+  //char ret[meditcmm.size()+1];
+  strcpy( ret, meditcmm.c_str()); 
+  return ret;
+}
+
+void writetabsol(const int &tsize, const int &nbofsol,const KN<double> &v1, KNM<double> &vv){
+  
+  for(int i=0; i<tsize; i++){
+    vv(nbofsol,i)   = v1(i);
+  }
+}
+
+void writetabsol(const int &tsize, const int &nbofsol,const KN<double> &v1, const KN<double> &v2, KNM<double> &vv){
+
+  for(int i=0; i<tsize; i++){
+    vv(nbofsol,i)   = v1(i);
+    vv(nbofsol+1,i) = v2(i);
+  }
+}
+
+void writetabsol(const int &tsize, const int &nbofsol,const KN<double> &v1, const KN<double> &v2, const KN<double> &v3, KNM<double> &vv){
+  
+  for(int i=0; i<tsize; i++){
+    vv(nbofsol,i)   = v1(i);
+    vv(nbofsol+1,i) = v2(i);
+    vv(nbofsol+2,i) = v3(i);
+  }
+
+}
+
+void writetabsol(const int &tsize, const int &nbofsol,const KN<double> &v1, const KN<double> &v2, const KN<double> &v3, 
+	     const KN<double> &v4, const KN<double> &v5, const KN<double> &v6,KNM<double> &vv){
+  
+  for(int i=0; i<tsize; i++){
+    vv(nbofsol,i)   = v1(i);
+    vv(nbofsol+1,i) = v2(i);
+    vv(nbofsol+2,i) = v3(i);
+    vv(nbofsol+3,i) = v4(i);
+    vv(nbofsol+4,i) = v5(i);
+    vv(nbofsol+5,i) = v6(i);
+  }
+
+}
+
+class PopenMeditMesh_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  long offset;
+  long nbTh;
+  struct Expression2 {
+    long what; // 0 mesh, 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 1 scalar, 2 vector (2D), 3 symtensor(2D) 
+    Expression e[3];
+    Expression2() {e[0]=0; e[1]=0; e[2]=0;  what=0; nbfloat=0;};
+    Expression &operator[](int i){return e[i];}
+    double eval(int i,Stack stack) const  { 
+    if (e[i]) {
+      return GetAny< double >( (*e[i])(stack) );
+    }
+    else 
+      return 0;
+    }
+    const Mesh & evalm(int i,Stack stack) const  { throwassert(e[i]);return  * GetAny< pmesh >((*e[i])(stack)) ;}
+  };
+  vector<Expression2> l;
+
+  static const int n_name_param =5;  
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  string*  arg(int i,Stack stack, string* a ) const{ return nargs[i] ? GetAny< string* >( (*nargs[i])(stack) ): a;}
+  
+public:
+  PopenMeditMesh_Op(const basicAC_F0 &  args) : l( args.size()-1 )
+  {
+    int nbofsol;
+    int ddim=2;
+    int stsize=3;
+    char   *tictac;
+
+    args.SetNameParam(n_name_param,name_param,nargs);   
+  
+    if(BCastTo<string *>(args[0])) filename = CastTo<string *>(args[0]);
+    /*
+      string * ffname  = GetAny<string *>( args[0] );
+      
+      char * ret= new char[ffname->size()+1];
+      strcpy( ret, ffname->c_str()); 
+      
+      int nbstrings=1;
+      tictac = strtok(ret," \n");
+      cout << "tictac" << tictac << endl;
+      while( tictac != NULL ){
+      tictac = strtok(NULL," \n");
+      nbstrings++;
+      }
+    */
+
+    for (size_t i=1;i<args.size();i++){
+      size_t jj=i-1;
+      
+      if (  BCastTo<double>(args[i])  )
+	{
+	  l[jj].what=1;
+	  l[jj].nbfloat=1;
+	  l[jj][0]=to<double>( args[i] );	  
+	}
+      else if ( args[i].left()==atype<E_Array>() )
+	{
+	  const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	 
+	  if (a0->size() != ddim && a0->size() != stsize) 
+	    CompileError("medit in 2D: vector solution is 2 composant, tensor solution is 3 composant");
+
+	  if( a0->size() == ddim){
+	    // vector solution
+	    l[jj].what=2;
+	    l[jj].nbfloat=ddim;
+	    for(int j=0; j<ddim; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }
+	  else if( a0->size() == stsize){
+	    // symmetric tensor solution
+	    l[jj].what=3;
+	    l[jj].nbfloat=stsize;
+	    for(int j=0; j<stsize; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }	  
+	}
+      else if( BCastTo<pmesh>(args[i]) ){
+	l[jj].what    = 0;
+	l[jj].nbfloat = 0;
+	l[jj][0] = CastTo<pmesh>(args[i]);
+      }
+      else {
+	CompileError("medit in 2D: Sorry no way to save this kind of data");
+      }
+    }
+    
+    offset=0;
+    nbTh=1;
+    // determination of the number of solutions
+    //  =============================
+    //  0 2 3 2 ! 0 2 3 2 ! 0 2  3  2
+    //  0 1 2 3 ! 4 5 6 7 ! 8 9 10 11
+    //  =============================
+    for(size_t jj=1; jj<l.size(); jj++){
+      if(l[jj].what==0 && offset==0) offset=jj;
+      if(l[jj].what==0){
+	nbTh++;
+	if( jj != (nbTh-1)*offset ){ 
+	   CompileError("the number of solution by mesh is different");
+	}
+      }
+    }    
+
+    /*
+      if( offset-1 != nbstrings ){
+      CompileError("The number of string defined in string parameter is different of the number of solution");
+      }
+    */
+
+    if( nbTh==1){
+      // case of one mesh
+      offset=l.size();
+    }
+    else{
+      // analyse of the different solution
+      for(size_t jj=offset; jj<l.size(); jj++){
+	if( l[jj].what != l[ jj%offset ].what ){
+	  char StringError[256]; 
+	  snprintf(StringError,256,"compile error ::  The solution %ld of mesh 1 and mesh %ld is not the same type",jj%offset,jj/offset+1);
+	  CompileError(StringError);
+	}
+      }
+    }
+    /*
+    // determination of the number of solutions.
+    size_t lastTh=0;
+    long offset1;
+    offset=0;
+    nbTh=0;
+    for(size_t jj=0; jj<l.size(); jj++){
+      if(l[jj].what==0){
+	nbTh++;
+	offset1=jj-lastTh;
+	if(offset==0){
+	  offset=offset1;
+	}
+	else if(offset != offset1){
+	  CompileError("the number of solution by mesh is different");
+	}
+      }
+    }
+    if(offset==0) offset=l.size();
+    */
+    // The number of solution is exactly:  offset-1
+
+    // verification que la nature des solutions sont identiques pour les differents maillages.
+
+    //cout << "number of solution = " << offset-1 << endl;
+    //cout << "number of mesh     = " << nbTh << endl;
+  } 
+  
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<string *>(), atype<pmesh>(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new PopenMeditMesh_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type PopenMeditMesh_Op::name_param[]= {
+  {  "order", &typeid(long)},
+  {  "meditff", &typeid(string*)},
+  {  "save",&typeid(string*)},
+  {  "wait",&typeid(bool)},
+  {  "bin",&typeid(long)}
+};
+
+
+AnyType PopenMeditMesh_Op::operator()(Stack stack)  const 
+{
+  if(NoGraphicWindow) return Nothing;
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  long order (arg(0,stack,1));
+  //
+  int ver = GmfFloat;
+  int dimp =2;
+  float fx,fy;
+  //
+  long valsortie=0;
+  int typsol,nbsol;
+  nbsol= offset-1;
+  
+  int TypTab[l.size()-1];
+  for (size_t i=0;i<l.size()-1;i++){
+    TypTab[i]=l[i+1].what;
+  }
+
+  //  string stringffmedit= string("medit.exe"); 
+  string * ffname  = GetAny<string *>( (*filename)(stack) );
+  string * meditff(arg(1,stack,&stringffmedit));
+
+  long filebin (arg(4,stack,1));
+  int smedit=max(1,nbsol);
+  
+  char * commandline = meditcmd( filebin, nbsol, smedit, *meditff, *ffname);
+  printf("version de medit %s\n",commandline);
+
+ 
+  // lecture des differents maillages
+  int nv=0,nt=0,nbe=0; // sommet, triangles, arretes du maillage unifies
+
+  //cout << "commencement du maillage " << endl;
+  for(size_t i=0; i<l.size();i=i+offset){
+    if(l[i].what!=0)
+      cerr << "this element is not a mesh" << i << endl;
+    const Mesh &Thtmp =l[i].evalm(0,stack);
+    nv  += Thtmp.nv;
+    nt  += Thtmp.nt;
+    nbe += Thtmp.neb;  
+    //cout << "valeur de i=" << i << "l.size()=" << l.size() << endl;
+    //cout << "vertex "<< nv << " triangle "<< nt << " edge " << nbe << endl;  
+  }
+  
+  Mesh::Vertex        *v= new Mesh::Vertex[nv];
+  Mesh::Triangle      *t= new Mesh::Triangle[nt];
+  Mesh::BorderElement *b= new Mesh::BorderElement[nbe]; 
+  Mesh::Triangle      *tt=t;
+  Mesh::BorderElement *bb=b;
+ 
+  int iv,it,ibe;
+  iv=0;
+  it=0;
+  ibe=0;
+
+  int numTht[nt]; // numero of Th assoctiated with a triangles 
+  //int numTht[nbe]; // numero of Th assoctiated with a BoundaryEdge
+
+  int jt=0;
+
+
+  for(size_t i=0; i<l.size();i=i+offset){
+    int nvtmp  = iv;
+    int nttmp  = it;
+    int nbetmp = ibe;
+      
+    const Mesh &Thtmp =l[i].evalm(0,stack);
+    for (int ii=0;ii<Thtmp.nv;ii++){
+      const Mesh::Vertex &vi(Thtmp(ii));
+      v[iv] = vi;
+      iv++;
+    }
+
+    for (int ii=0;ii<Thtmp.nt;ii++){
+      const Mesh::Triangle &vi(Thtmp.t(ii));
+      int i0 = nvtmp + Thtmp(ii,0);
+      int i1 = nvtmp + Thtmp(ii,1);
+      int i2 = nvtmp + Thtmp(ii,2);
+      (*tt++).set(v,i0,i1,i2,vi.lab);
+      numTht[it] = jt;
+      it++;      
+    }
+
+    for (int ii=0;ii<Thtmp.neb;ii++){
+      const Mesh::BorderElement &vi(Thtmp.be(ii));  //const BoundaryEdge &vi(Thtmp(ii));  
+      int i0 = nvtmp +  Thtmp.operator()(vi[0]);
+      int i1 = nvtmp +  Thtmp.operator()(vi[1]);
+      (*bb++).set(v,i0,i1,vi.lab);
+      ibe++;
+    }
+    jt++;
+  }
+  assert( it==nt ); assert(iv==nv); assert(ibe=nbe);
+  if(verbosity>2) cout << "Popen medit : vertex "<< nv << " triangle "<< nt << " edge " << nbe << endl;  
+
+  Mesh *pTh = new Mesh(nv,nt,nbe,v,t,b);
+  Mesh &Th = *pTh;
+
+  // determination of the number of elements to represent the solution
+  int datasize;
+  if(order == 0) datasize= nt;
+  if(order == 1) datasize= nv;
+
+  // cas de sauvegarde
+  bool boolsave = false;
+  int solnbfloat=0;
+  KNM<double> solsave(1,1);
+  string * saveff;
+  KN<double> vxx,vyx,vyy;
+ 
+  if(nbsol > 0){
+    
+    vxx.init(datasize);
+    vyx.init(datasize);
+    vyy.init(datasize);
+    
+    if( nargs[2] ){
+      boolsave= true;
+      saveff = GetAny<string *>( (*nargs[2])(stack) );
+      int ddim = 2;
+    
+      for (size_t i=0;i<offset;i++){
+	solnbfloat = solnbfloat + l[i].nbfloat;
+	//else if( TypTab[i] == 2) solnbfloat = solnbfloat+ddim;
+	//else if( TypTab[i] == 3) solnbfloat = solnbfloat+ddim*(ddim+1)/2;
+      }
+      
+      solsave.init(solnbfloat,datasize);
+      //cout << "solsave.size()= " << solsave.size()  << endl;
+      solsave=0.;
+      //cout << solsave  << endl;
+    }
+
+  }
+
+  int nboftmp = 0;
+
+  FILE *popenstream= popen(commandline,MODE_WRITE_BINARY);
+  if( !popenstream){
+    cerr << " Error popen : " << commandline<<endl;
+    exit(1);
+  }
+
+  // mesh
+  int jojo1;
+  
+  for(int jojo=0; jojo<smedit; jojo++){
+
+    if( filebin ){
+      int cod = 1;
+      int KwdCod;
+      int NulPos = 0;
+      
+      // determination of number solutions associated with a mesh
+      fwrite( (unsigned char *) &cod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &ver, WrdSiz,1,popenstream );
+      KwdCod = GmfDimension;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &dimp, WrdSiz,1,popenstream );
+     
+
+      // vertex 
+      KwdCod = GmfVertices;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &nv, WrdSiz,1,popenstream );
+      for (int k=0; k<nv; k++) {
+	const  Mesh::Vertex & P = Th.vertices[k];
+	fx=P.x; fy=P.y;
+	fwrite( (unsigned char *) &fx, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &fy, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &(P.lab), WrdSiz,1,popenstream );
+	//fprintf(popenstream,"%f %f %i\n",fx,fy,P.lab);
+      }
+    
+      // triangles
+      KwdCod = GmfTriangles;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &nt, WrdSiz,1,popenstream );
+      for (int k=0; k<nt; k++) {
+	const Mesh::Triangle & K(Th.t(k));
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int i2=Th.operator()(K[2])+1;
+	int lab=K.lab;
+	fwrite( (unsigned char *) &i0, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i1, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i2, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &lab, WrdSiz,1,popenstream );
+	//fprintf(popenstream,"%i %i %i %i\n",i0,i1,i2,lab);
+      }
+      
+
+      // Edges
+      KwdCod = GmfEdges;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &nbe, WrdSiz,1,popenstream );
+      //fprintf(popenstream,"Edges\n");
+      //fprintf(popenstream,"%i\n",nbe);
+      for (int k=0; k<nbe; k++) {
+	const Mesh::BorderElement & K(Th.be(k));
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int lab=K.lab;
+	fwrite( (unsigned char *) &i0, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i1, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &lab, WrdSiz,1,popenstream );
+	//fprintf(popenstream,"%i %i %i\n",i0,i1,lab);
+      }
+
+      // End
+      KwdCod = GmfEnd;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      //fprintf(popenstream,"End\n");
+    }
+    else{
+      // determination of number solutions associated with a mesh
+      fprintf(popenstream,"MeshVersionFormatted\n");
+      fprintf(popenstream,"%i\n",ver);
+      fprintf(popenstream,"Dimension\n");
+      fprintf(popenstream,"%i\n",dimp);
+      
+      fprintf(popenstream,"Vertices\n");
+      fprintf(popenstream,"%i\n",nv);        	
+      for (int k=0; k<nv; k++) {
+	const  Mesh::Vertex & P = Th.vertices[k];
+	fx=P.x; fy=P.y;
+	fprintf(popenstream,"%f %f %i\n",fx,fy,P.lab);
+      }
+    
+      fprintf(popenstream,"Triangles\n");
+      fprintf(popenstream,"%i\n",nt);
+      for (int k=0; k<nt; k++) {
+	const Mesh::Triangle & K(Th.t(k));
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int i2=Th.operator()(K[2])+1;
+	int lab=K.lab;
+	fprintf(popenstream,"%i %i %i %i\n",i0,i1,i2,lab);
+      }
+      
+      fprintf(popenstream,"Edges\n");
+      fprintf(popenstream,"%i\n",nbe);
+      for (int k=0; k<nbe; k++) {
+	const Mesh::BorderElement & K(Th.be(k));
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int lab=K.lab;
+	fprintf(popenstream,"%i %i %i\n",i0,i1,lab);
+      }
+      fprintf(popenstream,"End\n");
+    }
+
+
+    // solution with a mesh
+    if( nbsol > 0){
+      
+      if(filebin){
+	int cod = 1;
+	int NulPos = 0;
+	int KwdCod;
+	int codtypjm = 1;
+	// determination of number solutions associated with a mesh
+	fwrite( (unsigned char *) &cod, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &ver, WrdSiz,1,popenstream );
+	KwdCod = GmfDimension;
+	fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &dimp, WrdSiz,1,popenstream );
+	
+	if(order==0){
+	  KwdCod = GmfSolAtTriangles;
+	  fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &nt, WrdSiz,1,popenstream );
+
+	  printf("SolAtTriangles nt=%i\n",nt);
+	}
+	if(order==1){
+	  KwdCod = GmfSolAtVertices;
+	  fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &nv, WrdSiz,1,popenstream );
+	  
+	  printf("SolAtVertices nv=%i\n",nv);
+
+	}
+	typsol = TypTab[jojo];
+
+	fwrite( (unsigned char *) &codtypjm, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &typsol, WrdSiz,1,popenstream );
+	//printf(popenstream,"%i %i\n",codtypjm,typsol);
+      }
+      else{
+	fprintf(popenstream,"MeshVersionFormatted %i\n",ver);
+	fprintf(popenstream,"Dimension %i\n",dimp);
+	if(order==0){
+	  fprintf(popenstream,"SolAtTriangles\n");
+	  fprintf(popenstream,"%i\n",nt);
+	}
+	if(order==1){
+	  fprintf(popenstream,"SolAtVertices\n");
+	  fprintf(popenstream,"%i\n",nv);
+	}
+	typsol = TypTab[jojo];
+	
+	fprintf(popenstream,"%i %i\n",1,typsol);
+      }
+
+      
+      if(typsol==1){
+	if(order==0){
+	  
+	  vxx=0.;
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R2 Cdg_hat = R2(1./3.,1./3.);  
+	  
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    const Mesh::Triangle & K(Th.t(it));
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    vxx[it] =  l[jojo1].eval(0,stack);                     //GetAny< double >( (*nargs[1])(stack) );
+	  }
+	  
+	  if(filebin){
+	    for(int k=0; k<nt; k++){
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz,2,popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nt; k++){
+	      fprintf(popenstream,"%f\n",vxx[k]);
+	    }
+	  }
+	}
+	
+	else if(order==1){
+	  //KN<double> solsca(nv);    
+	  vxx=0.;
+	  KN<int> takemesh(nv);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  
+	  takemesh=0;
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    for( int iv=0; iv<3; ++iv){
+	      int i=Th(it,iv);  
+		  
+	      mp3->setP(&Th,it,iv);
+	      vxx[i] = vxx[i]+l[jojo1].eval(0,stack); //GetAny< double >( (*nargs[1])(stack) );		  
+	      takemesh[i] = takemesh[i]+1;
+	    }
+	  }
+	  if(filebin){
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];	      
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz,2,popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      fprintf(popenstream,"%f\n",vxx[k]);
+	    }
+	  }
+	}
+      }
+      else if(typsol==2){
+	if(order==0){	
+	  //KN<double>  vxx(nt),vyy(nt);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R2 Cdg_hat = R2(1./3.,1./3.);  
+	  
+	  vxx=0.; vyy=0.;
+	  
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    const Mesh::Triangle & K(Th.t(it));
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    vxx[it] =  l[jojo1].eval(0,stack); //GetAny< double >( (*xx)(stack) );
+	    vyy[it] =  l[jojo1].eval(1,stack); //GetAny< double >( (*yy)(stack) );
+	  }
+	  
+	  if(filebin){
+	    for(int k=0; k<nt; k++){
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz,2,popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nt; k++){
+	      fprintf(popenstream,"%f %f\n",vxx[k],vyy[k]);
+	    }
+	  }
+	}
+	
+	else if(order==1){
+	  //KN<double> vxx(nv),vyy(nv);
+	  KN<int> takemesh(nv);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  
+	  takemesh=0;
+	  vxx=0.; vyy=0.;
+	  
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    for( int iv=0; iv<3; ++iv){
+	      int i=Th(it,iv);  
+	      
+	      //if(takemesh[i]==0){
+	      mp3->setP(&Th,it,iv);
+	      vxx[i] = vxx[i]+l[jojo1].eval(0,stack); //GetAny< double >( (*xx)(stack) );
+	      vyy[i] = vyy[i]+l[jojo1].eval(1,stack); //GetAny< double >( (*yy)(stack) );
+	      
+	      takemesh[i] = takemesh[i]+1;
+	      //}
+	    }
+	  }
+
+	  if(filebin){
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz, 2, popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      fprintf(popenstream,"%f %f\n", vxx[k], vyy[k]);
+	    }
+	  }
+	  
+	}
+      }
+      else if(typsol==3){
+	if(order==0){
+	  //KN<double>  vxx(nt),vyx(nt),vyy(nt);
+	  vxx=0.; vyx=0.; vyy=0.;
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R2 Cdg_hat = R2(1./3.,1./3.);  
+	  
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    const Mesh::Triangle & K(Th.t(it));
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    vxx[it] = l[jojo1].eval(0,stack); //GetAny< double >( (*tsxx)(stack) );
+	    vyx[it] = l[jojo1].eval(1,stack); //GetAny< double >( (*tsyx)(stack) );
+	    vyy[it] = l[jojo1].eval(2,stack); //GetAny< double >( (*tsyy)(stack) );
+	  }
+	  
+	  if(filebin){
+	    for(int k=0; k<nt; k++){
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz, 2, popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nt; k++){
+	      fprintf(popenstream,"%f %f %f\n", vxx[k], vyx[k], vyy[k]);
+	    }
+	  }
+	}
+	else if(order==1){
+	  //KN<double> vxx(nv),vyx(nv),vyy(nv);
+	  KN<int> takemesh(nv);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  
+	  takemesh=0;
+	  vxx=0.; vyx=0.; vyy=0.;
+	  
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    for( int iv=0; iv<3; ++iv){
+	      int i=Th(it,iv);  
+	      
+	      //if(takemesh[i]==0){
+	      mp3->setP(&Th,it,iv);
+	      vxx[i] = vxx[i]+l[jojo1].eval(0,stack); //GetAny< double >( (*tsxx)(stack) );
+	      vyx[i] = vyx[i]+l[jojo1].eval(0,stack); //GetAny< double >( (*tsyx)(stack) );
+	      vyy[i] = vyy[i]+l[jojo1].eval(0,stack);  //GetAny< double >( (*tsyy)(stack) );
+	      
+	      takemesh[i] = takemesh[i]+1;
+	      //}
+	    }
+	  }
+	  
+	  if(filebin){
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyx[k]=vyx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz, 2, popenstream );
+	      
+	      //fprintf(popenstream,"%f %f %f\n",vxx[k],vyx[k],vyy[k]);
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyx[k]=vyx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      fprintf(popenstream,"%f %f %f\n",vxx[k],vyx[k],vyy[k]);
+	    }
+	  }
+	}
+      }
+
+      if(filebin){
+	int NulPos = 0;
+	int KwdCod = GmfEnd;
+	fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      }
+      else{
+	fprintf(popenstream,"End\n");
+      }
+
+      if(boolsave){
+	if(verbosity>2) cout << "writing solution in file"  << endl;
+	if(typsol==1){
+	  writetabsol( datasize, nboftmp, vxx, solsave);
+	  nboftmp=nboftmp+1;
+	}
+	else if(typsol==2){
+	  writetabsol( datasize, nboftmp, vxx, vyy, solsave);
+	  nboftmp=nboftmp+2;
+	}
+	else if(typsol==3){
+	  writetabsol( datasize, nboftmp, vxx, vyx, vyy, solsave);
+	  nboftmp=nboftmp+3;
+	}
+	/*cout << "fin writing solution in file nboftmp=" << nboftmp << endl;
+	  if(verbosity>2)
+	  {
+	  cout << "datasize=" << datasize << " " << "solnbfloat=" << solnbfloat << " boolsave=" << boolsave << endl;
+	  for(int iy=0; iy<datasize; iy++){
+	  if(iy==0 || iy==datasize-1) cout << iy <<" " <<solsave(0,iy) << endl;	      
+	  }
+	}
+	*/
+      }
+    }
+  }
+
+  // rajout pour wait
+  bool wait=TheWait;
+  if (nargs[3]) wait= GetAny<bool>((*nargs[3])(stack));
+  
+  bool plotting = true;   
+  //  drawing part  ------------------------------
+  
+  //  suppression du no wait car plante sur mac
+  //  il faut faire thread qui lance ca de maniere asyncrone ... 
+  //   a faire .. FH ...
+  //  if (wait && !NoWait) 
+    {
+      pclose(popenstream);
+    }
+    //else
+    // {
+    //  fclose(popenstream);
+    //}
+  
+  // rajout pout la sauvegarde de la solution
+  if(boolsave){
+    //cout <<"save solution in file avec printf\n"<< endl;;
+    int outm;
+    int nbtype=nbsol;
+    float *OutSolTab = new float[solnbfloat];
+    
+    if ( !(outm = GmfOpenMesh(saveff->c_str(),GmfWrite,ver,2)) ) {
+      cerr <<"  -- Mesh3::Save  UNABLE TO OPEN  :"<< saveff << endl;
+      exit(1);
+    }
+    
+    if(order == 0){	  
+      GmfSetKwd(outm,GmfSolAtTriangles, datasize, nbtype, TypTab);
+      for (int k=0; k<datasize; k++){
+	for (int i=0; i<solnbfloat ;i++){
+	  OutSolTab[i] =  solsave(i,k);
+	}
+	GmfSetLin(outm, GmfSolAtTriangles, OutSolTab); 
+      }
+    }
+    else if(order == 1){
+      GmfSetKwd(outm,GmfSolAtVertices, datasize, nbtype, TypTab);
+      for (int k=0; k<datasize; k++){
+	for (int i=0; i<solnbfloat ;i++){
+	  OutSolTab[i] =  solsave(i,k);
+	}
+	GmfSetLin(outm, GmfSolAtVertices, OutSolTab);
+      }
+    }
+   
+    GmfCloseMesh(outm);
+
+    delete [] OutSolTab;
+    
+  }
+  delete [] commandline;  
+  delete pTh;
+    
+  return valsortie;
+}
+
+template<class v_fes>
+class PopenMeditMesh3_Op : public E_F0mps 
+{
+public:
+  typedef long  Result;
+  Expression eTh;
+  Expression filename;
+  long offset;
+  long nbTh;
+  struct Expression2 {
+    long what; // 0 mesh, 1 scalar, 2 vector, 3 symtensor
+    long nbfloat; // 0 mesh(3D), 1 scalar, 2 vector (3D), 3 symtensor(3D)
+    Expression e[6];
+    Expression2() {e[0]=0; e[1]=0; e[2]=0;  e[3]=0; e[4]=0; e[5]=0; what=0; nbfloat=0;};
+    Expression &operator[](int i){return e[i];}
+    double eval(int i,Stack stack) const  { 
+    if (e[i]) {
+      return GetAny< double >( (*e[i])(stack) );
+    }
+    else 
+      return 0;
+    }
+    const Mesh3 & evalm(int i,Stack stack) const  { throwassert(e[i]);return  * GetAny< pmesh3 >((*e[i])(stack)) ;}
+  };
+  vector<Expression2> l;
+
+  static const int n_name_param = 5;  
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  string*  arg(int i,Stack stack, string* a ) const{ return nargs[i] ? GetAny< string* >( (*nargs[i])(stack) ): a;}
+
+public:
+  PopenMeditMesh3_Op(const basicAC_F0 &  args) : l( args.size()-1 )
+  {
+    int nbofsol;
+    int ddim=3;
+    int stsize=6;
+    
+    args.SetNameParam(n_name_param,name_param,nargs);   
+   
+    if (BCastTo<string *>(args[0])) filename = CastTo<string *>(args[0]);
+    //if (BCastTo<pmesh3>(args[1])) eTh= CastTo<pmesh3>(args[1]);
+    
+    for (size_t i=1;i<args.size();i++){
+      size_t jj=i-1;
+      if ( BCastTo<double>(args[i]) )
+	{
+	  l[jj].what=1;
+	  l[jj].nbfloat=1;
+	  l[jj][0]=to<double>( args[i] );
+	}
+      else if ( args[i].left()==atype<E_Array>() )
+	{
+	  const E_Array * a0  = dynamic_cast<const E_Array *>( args[i].LeftValue() );
+	  //cout << "taille" << a0->size() << endl;
+	  if (a0->size() != ddim && a0->size() != stsize) 
+	    CompileError("medit in 3D: vector solution is 3 composant, tensor solution is 6 composant");
+
+	  if( a0->size() == ddim){
+	    // vector solution
+	    l[jj].what=2;
+	    l[jj].nbfloat=ddim;
+	    for(int j=0; j<ddim; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }
+	  else if( a0->size() == stsize){
+	    // symmetric tensor solution
+	    l[jj].what=3;
+	    l[jj].nbfloat=stsize;
+	    for(int j=0; j<stsize; j++){
+	      l[jj][j] = to<double>( (*a0)[j]);
+	    }
+	  }
+	  
+	}
+      else if( BCastTo<pmesh3>(args[i]) ){
+	l[jj].what    = 0;
+	l[jj].nbfloat = 0;
+	l[jj][0] = CastTo<pmesh3>(args[i]);
+      }
+      else {
+	CompileError("medit 3d: Sorry no way to save this kind of data");
+      }      
+    }
+    // determination of the number of solutions.
+    size_t lastTh=0;
+    long offset1;
+    offset=0;
+    nbTh=0;
+    for(size_t jj=0; jj<l.size(); jj++){
+      if(l[jj].what==0){
+	nbTh++;
+	offset1=jj-lastTh;
+	if(offset==0){
+	  offset=offset1;
+	}
+	else if(offset != offset1){
+	  CompileError("the number of solution by mesh is different");
+	}
+      }
+    }
+    if(offset==0) offset=l.size(); 
+    
+  }
+  
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<string *>(), atype<pmesh3>(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new PopenMeditMesh3_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+};
+template<class v_fes>
+basicAC_F0::name_and_type PopenMeditMesh3_Op<v_fes>::name_param[]= {
+  {  "order", &typeid(long)},
+  {  "meditff", &typeid(string*)},
+  {  "save",&typeid(string*)},
+  {  "wait",&typeid(bool)},
+  {  "bin",&typeid(long)}
+};
+
+template<class v_fes>
+AnyType PopenMeditMesh3_Op<v_fes>::operator()(Stack stack)  const 
+{
+  if(NoGraphicWindow) return Nothing;
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  long order (arg(0,stack,1L));
+  //
+  int ver = GmfFloat;
+  int dimp =3;
+  float fx,fy,fz;
+  //
+  long valsortie=0;
+  int typsol,nbsol;
+  nbsol = offset-1;
+  
+  int TypTab[l.size()-1];
+  for (size_t i=0;i<l.size()-1;i++){
+    TypTab[i]=l[i+1].what;
+  }
+
+  //  string stringemptymedit= string("medit");
+  string * ffname  = GetAny<string *>( (*filename)(stack) );
+  string * meditff(arg(1,stack,&stringffmedit));
+
+  long filebin (arg(4,stack,1L));
+  int smedit=max(1,nbsol);     
+  char * commandline = meditcmd( filebin, nbsol, smedit, *meditff, *ffname);
+  
+  printf("version de medit %s\n",commandline);  
+  if(verbosity>2) cout << "number of solution = " << offset-1 << endl;
+  if(verbosity>2) cout << "number of mesh     = " << nbTh << endl;
+
+  // lecture des differents maillages
+  int nv=0,nt=0,nbe=0; // sommet, triangles, arretes du maillage unifies
+
+  //cout << "commencement du maillage " << endl;
+  for(size_t i=0; i<l.size();i=i+offset){
+    if(l[i].what!=0)
+      cerr << "this element is not a mesh" << i << endl;
+    const Mesh3 &Thtmp =l[i].evalm(0,stack);
+    nv  += Thtmp.nv;
+    nt  += Thtmp.nt;
+    nbe += Thtmp.nbe;  
+    //cout << "valeur de i=" << i << "l.size()=" << l.size() << endl;
+    //cout << "vertex "<< nv << " tetrahedra "<< nt << " triangle " << nbe << endl;  
+  }
+  
+  Vertex3    *v = new Vertex3[nv];
+  Tet        *t;
+  if(nt !=0 ) t = new Tet[nt];
+  Triangle3  *b = new Triangle3[nbe]; 
+  Tet       *tt = t;
+  Triangle3 *bb = b;
+
+  int iv=0,it=0,ibe=0;
+  int *numTht = new int[nt]; // numero of Th assoctiated with a tetrahedra 
+
+  int jt=0;
+  for(size_t i=0; i<l.size();i=i+offset){
+    int nvtmp  = iv;
+    int nttmp  = it;
+    int nbetmp = ibe;
+      
+    const Mesh3 &Thtmp =l[i].evalm(0,stack);
+    for (int ii=0;ii<Thtmp.nv;ii++){
+      const Vertex3 &vi(Thtmp.vertices[ii]);
+      v[iv].x = vi.x;
+      v[iv].y = vi.y;
+      v[iv].z = vi.z;
+      v[iv].lab = vi.lab;
+      iv++;
+    }
+
+    for (int ii=0;ii<Thtmp.nt;ii++){
+      const Tet &vi(Thtmp.elements[ii]);
+      int iv[4];
+      iv[0] = nvtmp + Thtmp.operator()(vi[0]);
+      iv[1] = nvtmp + Thtmp.operator()(vi[1]);
+      iv[2] = nvtmp + Thtmp.operator()(vi[2]);
+      iv[3] = nvtmp + Thtmp.operator()(vi[3]);
+      (*tt++).set(v,iv,vi.lab);
+      numTht[it] = jt;
+      it++;      
+    }
+
+    for (int ii=0;ii<Thtmp.nbe;ii++){
+      const  Triangle3 &vi(Thtmp.be(ii));
+      int iv[3];
+      iv[0] = nvtmp + Thtmp.operator()(vi[0]);
+      iv[1] = nvtmp + Thtmp.operator()(vi[1]);
+      iv[2] = nvtmp + Thtmp.operator()(vi[2]);
+      (*bb++).set(v,iv,vi.lab);
+      ibe++;
+    }
+    jt++;
+  }
+  assert( it==nt ); assert(iv==nv); assert(ibe=nbe);
+  if(verbosity>2) cout << "meditff :: Value of elements: vertex "<< nv << " Tet "<< nt << " triangle " << nbe << endl;  
+
+  Mesh3 *pTh = new Mesh3(nv,nt,nbe,v,t,b);
+  Mesh3 &Th = *pTh;
+
+  //cout << "Mesh is created" << endl;
+  // determination of the number of elements to represent the solution
+  int datasize;
+  if(order == 0) datasize= nt;
+  if(order == 1) datasize= nv;
+
+  // cas de sauvegarde
+  bool boolsave = false;
+  int solnbfloat=0;
+  KNM<double> solsave(1,1);
+  string * saveff;
+  KN<double> vxx,vyx,vyy,vzx,vzy,vzz;
+ 
+  //cout << "nbsol=" << endl;
+
+  if(nbsol > 0){
+    
+    vxx.init(datasize);
+    vyx.init(datasize);
+    vyy.init(datasize);
+    vzx.init(datasize);
+    vzy.init(datasize);
+    vzz.init(datasize);
+    
+    if( nargs[2] ){
+      boolsave= true;
+      saveff = GetAny<string *>( (*nargs[2])(stack) );
+      int ddim = 3;
+    
+      for (size_t i=0;i<offset;i++){
+	solnbfloat = solnbfloat + l[i].nbfloat;
+      }
+      
+      solsave.init(solnbfloat,datasize);
+      //cout << "solsave.size()= " << solsave.size()  << endl;
+      solsave=0.;
+      //cout << solsave  << endl;
+    }
+
+  }
+
+  int nboftmp = 0;
+    
+  FILE *popenstream= popen(commandline,MODE_WRITE_BINARY);
+  if( !popenstream){
+    cerr << " Error popen : " << commandline<<endl;
+    exit(1);
+  }
+ 
+  // mesh
+  int jojo1;
+  for(int jojo=0; jojo<smedit; jojo++){
+
+    if(filebin){
+      int cod = 1;
+      int KwdCod;
+      int NulPos = 0;
+      
+      // determination of number solutions associated with a mesh
+      fwrite( (unsigned char *) &cod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &ver, WrdSiz,1,popenstream );
+      KwdCod = GmfDimension;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &dimp, WrdSiz,1,popenstream );
+     
+
+      // vertex 
+      KwdCod = GmfVertices;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &nv, WrdSiz,1,popenstream );   
+      for (int k=0; k<nv; k++) {
+	const  Vertex3 & P = Th.vertices[k];
+	fx=P.x; fy=P.y; fz=P.z;
+	fwrite( (unsigned char *) &fx, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &fy, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &fz, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &(P.lab), WrdSiz,1,popenstream );
+	//fprintf(popenstream,"%f %f %i\n",fx,fy,P.lab);
+      }
+    
+      // tetrahedra
+      KwdCod= GmfTetrahedra;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &nt, WrdSiz,1,popenstream );  
+      for (int k=0; k<nt; k++) {
+	const Tet & K(Th.elements[k]);
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int i2=Th.operator()(K[2])+1;
+	int i3=Th.operator()(K[3])+1;
+	int lab=K.lab;
+	fwrite( (unsigned char *) &i0, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i1, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i2, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i3, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &lab, WrdSiz,1,popenstream );
+	//fprintf(popenstream,"%i %i %i %i %i\n",i0,i1,i2,i3,lab);
+      }
+
+      // triangles
+      KwdCod = GmfTriangles;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &nbe, WrdSiz,1,popenstream );
+      for (int k=0; k<nbe; k++) {
+	const Triangle3 & K(Th.be(k));
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int i2=Th.operator()(K[2])+1;
+	int lab=K.lab;
+	fwrite( (unsigned char *) &i0, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i1, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &i2, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &lab, WrdSiz,1,popenstream );
+	//fprintf(popenstream,"%i %i %i %i\n",i0,i1,i2,lab);
+      }
+            
+      // End
+      KwdCod = GmfEnd;
+      fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+      fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      //fprintf(popenstream,"End\n");
+    }
+    else{
+      fprintf(popenstream,"MeshVersionFormatted\n");
+      fprintf(popenstream,"%i\n",ver);
+      fprintf(popenstream,"Dimension\n");
+      fprintf(popenstream,"%i\n",dimp);
+      fprintf(popenstream,"Vertices\n");
+      fprintf(popenstream,"%i\n",nv);
+      
+      for (int k=0; k<nv; k++) {
+	const  Vertex3 & P = Th.vertices[k];
+	fx=P.x; fy=P.y; fz=P.z;
+	fprintf(popenstream,"%f %f %f %i\n",fx,fy,fz,P.lab);
+      }
+      fprintf(popenstream,"Tetrahedra\n");
+      fprintf(popenstream,"%i\n",nt);
+      for (int k=0; k<nt; k++) {
+	const Tet & K(Th.elements[k]);
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int i2=Th.operator()(K[2])+1;
+	int i3=Th.operator()(K[3])+1;
+	int lab=K.lab;
+	fprintf(popenstream,"%i %i %i %i %i\n",i0,i1,i2,i3,lab);
+      }
+      fprintf(popenstream,"Triangles\n");
+      fprintf(popenstream,"%i\n",nbe);
+      for (int k=0; k<nbe; k++) {
+	const Triangle3 & K(Th.be(k));
+	int i0=Th.operator()(K[0])+1;
+	int i1=Th.operator()(K[1])+1;
+	int i2=Th.operator()(K[2])+1;
+	int lab=K.lab;
+	fprintf(popenstream,"%i %i %i %i\n",i0,i1,i2,lab);
+      }
+      fprintf(popenstream,"End");
+    }
+    
+    if(nbsol > 0){
+      if(filebin){
+	int cod = 1;
+	int NulPos = 0;
+	int KwdCod;
+	fwrite( (unsigned char *) &cod, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &ver, WrdSiz,1,popenstream );
+	KwdCod = GmfDimension;
+	fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &dimp, WrdSiz,1,popenstream );
+      }
+      else{
+	fprintf(popenstream,"MeshVersionFormatted %i\n",ver);
+	fprintf(popenstream,"Dimension %i\n",dimp);
+	
+	// detemination of solution
+	// default scalaire // faire tableau pour plusieurs
+      }
+      
+      typsol = TypTab[jojo];
+	
+      //fprintf(popenstream,"%i %i\n",1,typsol);
+      
+      
+      if(order == 0){
+	if(filebin){
+	  int NulPos = 0;
+	  int KwdCod = GmfSolAtTetrahedra;
+	  int codtypjm = 1;
+	  fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &datasize, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &codtypjm, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &typsol, WrdSiz,1,popenstream );
+	}
+	else{
+	  fprintf(popenstream,"SolAtTetrahedra\n");
+	  fprintf(popenstream,"%i\n",datasize);
+	  fprintf(popenstream,"%i %i\n",1,typsol);
+	}
+	if(typsol==1){
+	  //KN<double> solsca(nv);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R3 Cdg_hat = R3(1./4.,1./4.,1./4.);  
+
+	  vxx=0.;
+	  for (int it=0;it<nt;it++){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    const Tet & K(Th.elements[it]);
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	    vxx[it] = l[jojo1].eval(0,stack); //GetAny< double >( (*nargs[1])(stack) );
+	    
+	  }
+	  
+	  if(filebin){
+	    for(int k=0; k<nt; k++){
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz,2,popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nt; k++){
+	      fprintf(popenstream,"%f\n",vxx[k]);
+	    }
+	  }
+	}
+	else if(typsol==2){
+	  //KN<double> vxx(nv),vyy(nv),vzz(nv);
+	  vxx=0.; vyy=0.; vzz=0.;    
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R3 Cdg_hat = R3(1./4.,1./4.,1./4.); 
+	  
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    const Tet & K(Th.elements[it]);
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	    vxx[it] = l[jojo1].eval(0,stack); //GetAny< double >( (*xx)(stack) );
+	    vyy[it] = l[jojo1].eval(1,stack); //GetAny< double >( (*yy)(stack) );
+	    vzz[it] = l[jojo1].eval(2,stack); //GetAny< double >( (*zz)(stack) );
+	    
+	  }
+	  if(filebin){
+	    for(int k=0; k<nt; k++){
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vzz[k]), WrdSiz,2,popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nt; k++){
+	      fprintf(popenstream,"%f %f %f\n", vxx[k], vyy[k], vzz[k]);
+	    }
+	  }
+	}
+	else if(typsol==3){
+	  //KN<double> vxx(nv),vyx(nv),vyy(nv),vzx(nv),vzy(nv),vzz(nv);
+	  vxx(nv)=0.;vyx(nv)=0.;vyy(nv)=0.;
+	  vzx(nv)=0.;vzy(nv)=0.;vzz(nv)=0.;
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  R3 Cdg_hat = R3(1./4.,1./4.,1./4.); 
+	  
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    const Tet & K(Th.elements[it]);
+	    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+	    
+	    vxx[it] = l[jojo1].eval(0,stack); //GetAny< double >( (*tsxx)(stack) );
+	    vyx[it] = l[jojo1].eval(1,stack); //GetAny< double >( (*tsyx)(stack) );
+	    vyy[it] = l[jojo1].eval(2,stack); //GetAny< double >( (*tsyy)(stack) );
+	    vzx[it] = l[jojo1].eval(3,stack); //GetAny< double >( (*tszx)(stack) );
+	    vzy[it] = l[jojo1].eval(4,stack); //GetAny< double >( (*tszy)(stack) );
+	    vzz[it] = l[jojo1].eval(5,stack); //GetAny< double >( (*tszz)(stack) );
+	    
+	  }
+	  if(filebin){
+	    for(int k=0; k<nt; k++){
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vyx[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vzx[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vzy[k]), WrdSiz,2,popenstream );
+	      fwrite( (unsigned char *) &(vzz[k]), WrdSiz,2,popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nt; k++){
+	      fprintf(popenstream,"%f %f %f %f %f %f\n",vxx[k],vyx[k],vyy[k],vzx[k],vzy[k],vzz[k]);
+	    } 
+	  }
+	}
+      }
+      else if(order == 1){
+	if(filebin){
+	  int NulPos = 0;
+	  int KwdCod = GmfSolAtVertices;
+	  int codtypjm = 1;
+	  fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &datasize, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &codtypjm, WrdSiz,1,popenstream );
+	  fwrite( (unsigned char *) &typsol, WrdSiz,1,popenstream );
+	}
+	else{
+	  fprintf(popenstream,"SolAtVertices\n");
+	  fprintf(popenstream,"%i\n",datasize);
+	  fprintf(popenstream,"%i %i\n",1,typsol);
+	}
+	if(typsol==1){
+	  //KN<double> solsca(nv);
+	  KN<int> takemesh(nv);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  	  
+	  takemesh=0;
+	  vxx=0.;
+
+	  for (int it=0;it<Th.nt;it++){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    for( int iv=0; iv<4;iv++){
+	      int i=Th(it,iv);  
+	      
+	      mp3->setP(&Th,it,iv);
+	      vxx[i] = vxx[i]+l[jojo1].eval(0,stack); //GetAny< double >( (*nargs[1])(stack) );
+	      
+	      takemesh[i] = takemesh[i]+1;
+	    }
+	  }
+	  if(filebin){
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];	      
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz,2,popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      fprintf(popenstream,"%f\n",vxx[k]);
+	    }
+	  }
+	}
+	else if(typsol==2){
+	  //KN<double> vxx(nv),vyy(nv),vzz(nv);
+	  KN<int> takemesh(nv);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+	  
+	  vxx=0.;
+	  vyy=0.;
+	  vzz=0.;
+	  takemesh=0;
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    for( int iv=0; iv<4; ++iv){
+	      int i=Th(it,iv);  
+	      
+	      //if(takemesh[i]==0){
+	      mp3->setP(&Th,it,iv);
+	      vxx[i] = vxx[i]+l[jojo1].eval(0,stack); //GetAny< double >( (*xx)(stack) );
+	      vyy[i] = vyy[i]+l[jojo1].eval(1,stack); //GetAny< double >( (*yy)(stack) );
+	      vzz[i] = vzz[i]+l[jojo1].eval(2,stack); //GetAny< double >( (*zz)(stack) );
+	      
+	      takemesh[i] = takemesh[i]+1;
+	      //}
+	    }
+	  }
+	  if(filebin){
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      vzz[k]=vzz[k]/takemesh[k];
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vzz[k]), WrdSiz, 2, popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      vzz[k]=vzz[k]/takemesh[k];
+	      fprintf(popenstream,"%f %f %f\n", vxx[k], vyy[k], vzz[k]);
+	    }
+	  }
+	}
+	else if(typsol==3){
+	  //KN<double> vxx(nv),vyx(nv),vyy(nv),vzx(nv),vzy(nv),vzz(nv);
+	  KN<int> takemesh(nv);
+	  MeshPoint *mp3(MeshPointStack(stack)); 
+
+	  vxx=0.;
+	  vyx=0.;
+	  vyy=0.;
+	  vzx=0.;
+	  vzy=0.;
+	  vzz=0.;
+	  takemesh=0;
+	  for (int it=0;it<Th.nt;++it){
+	    jojo1 = jojo+1+offset*numTht[it];
+	    for( int iv=0; iv<4; ++iv){
+	      int i=Th(it,iv);  
+	      
+	      mp3->setP(&Th,it,iv);
+	      vxx[i] = vxx[i] + l[jojo1].eval(0,stack); //GetAny< double >( (*tsxx)(stack) );
+	      vyx[i] = vyx[i] + l[jojo1].eval(1,stack); //GetAny< double >( (*tsyx)(stack) );
+	      vyy[i] = vyy[i] + l[jojo1].eval(2,stack); //GetAny< double >( (*tsyy)(stack) );
+	      vzx[i] = vzx[i] + l[jojo1].eval(3,stack); //GetAny< double >( (*tszx)(stack) );
+	      vzy[i] = vzy[i] + l[jojo1].eval(4,stack); //GetAny< double >( (*tszy)(stack) );
+	      vzz[i] = vzz[i] + l[jojo1].eval(5,stack); //GetAny< double >( (*tszz)(stack) );
+	      
+	      takemesh[i] = takemesh[i]+1; 	
+	    }
+	  }
+	  if(filebin){
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyx[k]=vyx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      vzx[k]=vzx[k]/takemesh[k];
+	      vzy[k]=vzy[k]/takemesh[k];
+	      vzz[k]=vzz[k]/takemesh[k];
+
+	      fwrite( (unsigned char *) &(vxx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vyy[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vzx[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vzy[k]), WrdSiz, 2, popenstream );
+	      fwrite( (unsigned char *) &(vzz[k]), WrdSiz, 2, popenstream );
+	    }
+	  }
+	  else{
+	    for(int k=0; k<nv; k++){
+	      vxx[k]=vxx[k]/takemesh[k];
+	      vyx[k]=vyx[k]/takemesh[k];
+	      vyy[k]=vyy[k]/takemesh[k];
+	      vzx[k]=vzx[k]/takemesh[k];
+	      vzy[k]=vzy[k]/takemesh[k];
+	      vzz[k]=vzz[k]/takemesh[k];
+	      
+	      fprintf(popenstream,"%f %f %f %f %f %f\n",vxx[k], vyx[k], vyy[k], vzx[k], vzy[k], vzz[k]);
+	    }
+	  }
+
+	}
+      }
+
+      if(filebin){
+	int NulPos = 0;
+	int KwdCod = GmfEnd;
+	fwrite( (unsigned char *) &KwdCod, WrdSiz,1,popenstream );
+	fwrite( (unsigned char *) &NulPos, WrdSiz,1,popenstream );
+      }
+      else{
+	fprintf(popenstream,"End");
+      }
+ 
+      if(boolsave){
+	if(verbosity>2) cout << "writing solution in file" << endl;
+	if(typsol==1){
+	  writetabsol( datasize, nboftmp, vxx, solsave);
+	  nboftmp=nboftmp+1;
+	}
+	else if(typsol==2){
+	  writetabsol( datasize, nboftmp, vxx, vyy, vzz, solsave);
+	  nboftmp=nboftmp+3;
+	}
+	else if(typsol==3){
+	  writetabsol( datasize, nboftmp, vxx, vyx, vyy, vzx, vzy, vzz, solsave);
+	  nboftmp=nboftmp+6;
+	}
+	//cout << "finish writing solution in file" << endl;
+	//cout << "datasize=" << datasize << " " << "solnbfloat=" << solnbfloat << endl;
+      }
+
+    }
+  }
+  delete [ ] numTht;
+  // fermeture du stream pour popen
+  bool wait=TheWait;
+  if (nargs[3]) wait= GetAny<bool>((*nargs[3])(stack));
+  
+  bool plotting = true;   
+  //  drawing part  ------------------------------
+  
+  //    if (wait && !NoWait) 
+    {
+      pclose(popenstream);
+    }
+    /*else
+    {
+      fclose(popenstream);
+      }*/
+  
+  if(boolsave){
+    int outm;
+    int nbtype=nbsol;
+    float *OutSolTab = new float[solnbfloat];
+    
+    if ( !(outm = GmfOpenMesh(saveff->c_str(),GmfWrite,ver,3)) ) {
+      cerr <<"  -- Mesh3::Save  UNABLE TO OPEN  :"<< saveff << endl;
+      exit(1);
+    }
+    
+    if(order == 0){	  
+      GmfSetKwd(outm,GmfSolAtTetrahedra, datasize, nbtype, TypTab);
+      for (int k=0; k<datasize; k++){
+	for (int i=0; i<solnbfloat ;i++){
+	  OutSolTab[i] =  solsave(i,k);
+	}
+	GmfSetLin(outm, GmfSolAtTetrahedra, OutSolTab); 
+      }
+    }
+    else if(order == 1){
+      GmfSetKwd(outm,GmfSolAtVertices, datasize, nbtype, TypTab);
+      for (int k=0; k<datasize; k++){
+	for (int i=0; i<solnbfloat ;i++){
+	  OutSolTab[i] =  solsave(i,k);
+	}
+	GmfSetLin(outm, GmfSolAtVertices, OutSolTab);
+      }
+    }
+    delete [] OutSolTab;
+    GmfCloseMesh(outm);
+  }
+
+  delete [] commandline;
+  delete pTh; 
+
+  return valsortie;
+}
+
+//  truc pour que la fonction 
+// static void Load_Init() soit appele a moment du chargement dynamique
+// du fichier 
+//
+  
+
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  typedef Mesh *pmesh;
+  typedef Mesh3 *pmesh3;
+  
+  if (verbosity>2)
+    cout << " load:popen.cpp  " << endl;
+  
+  // 2D
+  Global.Add("medit","(",new OneOperatorCode<PopenMeditMesh_Op>);
+  Global.Add("savesol","(",new OneOperatorCode<datasolMesh2_Op> );
+  
+  // 3D
+  Global.Add("medit","(",new OneOperatorCode< PopenMeditMesh3_Op<v_fes3> >);
+  Global.Add("savesol","(",new OneOperatorCode< datasolMesh3_Op<v_fes3> >);
+  
+
+  Global.Add("readsol","(",new OneOperatorCode< readsol_Op >);
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/meditddm.edp b/examples++-load/meditddm.edp
new file mode 100644
index 0000000..90e929e
--- /dev/null
+++ b/examples++-load/meditddm.edp
@@ -0,0 +1,50 @@
+// meditddm.edp
+load "medit"
+
+/********************************************
+ Initial Problem:
+Resolution of the following EDP:
+$- \Delta u = f$ on   $\Omega =\{ (x,y) |  1 \leq sqrt(x^2+y^2) \geq 2}$
+$- \Delta u = f1$ on  $\Omega_{1} =\{ (x,y) |  0.5 \leq sqrt(x^2+y^2) \geq 1.}$
+$u = 1$ on $\Gamma$  +  Null Neumman condition on $\Gamma_{1}$ and on $\Gamma_{2}$	
+We find the solution $u$ in solving two EDP defined on domain $\Omega$ and $\Omega_{1}$
+This solution is vizualize with ffmedit 
+*********************************************/
+verbosity=3;
+
+border Gamma(t=0,2*pi){x=cos(t); y=sin(t); label=1;};
+border Gamma1(t=0,2*pi){x=2*cos(t); y=2*sin(t); label=2;};
+border Gamma2(t=0,2*pi){x=0.5*cos(t); y=0.5*sin(t); label=3;};
+
+// construction of mesh of domain $\Omega$
+mesh Th=buildmesh(Gamma1(40)+Gamma(-40)); 
+
+fespace Vh(Th,P2);
+func f=sqrt(x*x+y*y);
+Vh us,v;
+macro Grad2(us) [dx(us),dy(us)]  // EOM
+
+problem Lap2dOmega(us,v,init=false)=int2d(Th)(Grad2(v)' *Grad2(us)) - int2d(Th)(f*v)+on(Gamma,us=1) ;
+//  Resolution of EDP defined on the domain $\Omega$
+// $- \Delta u = f$ on $\Omega$ 
+//      $u = 1$  on $\Gamma
+//   + Null Neumann condition on $\Gamma_{1}$
+Lap2dOmega;
+
+// construction of mesh of domain $\Omega1 =\{ (x,y) |  0.5 \leq sqrt(x^2+y^2) \geq 1.}$
+mesh Th1=buildmesh(Gamma(40)+Gamma2(-40));
+
+fespace Vh1(Th1,P2);
+func f1=10*sqrt(x*x+y*y);
+Vh1 u1,v1;
+macro Grad21(u1) [dx(u1),dy(u1)]  // EOM
+
+problem Lap2dOmega1(u1,v1,init=false)=int2d(Th1)(Grad21(v1)' *Grad21(u1)) - int2d(Th1)(f1*v1)+on(Gamma,u1=1) ;
+//   Resolution of EDP defined on the domain $\Omega_{1}$
+// $- \Delta u = f1$ on $\Omega_{1}$ 
+//      $u = 1$ on $\Gamma$
+//   + Null Neumann condition on $\Gamma_{2}$
+Lap2dOmega1; 
+
+// vizualisation of solution of the initial problem
+medit("solution",Th,us,Th1,u1,order=1,meditff="ffmedit",save="testsavemedit.solb");	
diff --git a/examples++-load/metis.cpp b/examples++-load/metis.cpp
new file mode 100644
index 0000000..6bd6025
--- /dev/null
+++ b/examples++-load/metis.cpp
@@ -0,0 +1,133 @@
+// SUMMARY  :   add interface with partionning library scotch 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : F. Hecht
+// E-MAIL   : F. Hecht <hecht at ljll.math.upmc.fr>
+//  date : 2009 ????
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:   metis
+//ff-c++-cpp-dep: 
+//  
+
+#include <ff++.hpp>
+#include <cmath>
+typedef KNM<double> * pRnm;
+typedef KN<double> * pRn;
+typedef string * pstring;
+extern "C" {
+#include <metis.h>
+}
+
+#ifdef  METIS_VER_MAJOR 
+//  METIS_PartMeshDual(&ne, &nn, elmnts, &etype, &numflag, &nparts, &edgecut, epart, npart);
+extern "C" {
+real_t libmetis__ComputeElementBalance(idx_t ne, idx_t nparts, idx_t *where); 
+}
+#else 
+typedef idxtype idx_t ;
+#endif
+template<class Mesh,int NO,typename R>
+KN<R> * partmetis(Stack s,KN<R> * const & part,Mesh * const & pTh,long const & lparts)
+{
+    ffassert(pTh);
+    const Mesh & Th(*pTh);
+    int nt=Th.nt,nv=Th.nv;
+    int nve = Mesh::Rd::d+1;
+    
+    KN<idx_t> eptr(nt+1),elmnts(nve*nt), epart(nt), npart(nv);
+    for(int k=0,i=0;k<nt;++k)
+      {
+	eptr[k]=i;
+	for(int j=0;j<nve;j++)
+	  elmnts[i++] = Th(k,j);
+	eptr[k+1]=i;
+      }
+    int numflag=0;
+    int nparts=lparts;
+    int edgecut;
+    int etype =nve-2; // triangle or tet .  change FH fevr 2010 
+    idx_t ncommon = 1; 
+#ifdef  METIS_VER_MAJOR 
+    if(NO==0)
+      METIS_PartMeshNodal(&nt, &nv, eptr, (idx_t *) elmnts,  0,0, &nparts, 0,0, &edgecut, (idx_t  *) epart, (idx_t  *) npart);
+    else
+      METIS_PartMeshDual(&nt, &nv, eptr, (idx_t *) elmnts , 0,0, &ncommon,  &nparts, 0,0, &edgecut, (idx_t  *) epart,(idx_t  *)  npart);
+    if(verbosity)
+      printf("  --metisOA: %d-way Edge-Cut: %7d, Balance: %5.2f Nodal=0/Dual %d\n", nparts, nve, libmetis__ComputeElementBalance(nt, nparts, epart),NO);
+#else
+    if(NO==0)
+     METIS_PartMeshNodal(&nt, &nv, elmnts, &etype , &numflag, &nparts, &edgecut, epart, npart);
+    else
+     METIS_PartMeshDual(&nt, &nv, elmnts, &etype , &numflag, &nparts, &edgecut, epart, npart);
+    if(verbosity)
+      printf("  --metis: %d-way Edge-Cut: %7d, Balance: %5.2f Nodal=0/Dual %d\n", nparts, nve, ComputeElementBalance(nt, nparts, epart),NO);
+#endif 
+    part->resize(nt);
+    *part=epart;
+    return part;
+}
+KN<long> * partmetisd(Stack s,KN<long> * const & part,Mesh * const & pTh,long const & lparts)
+{
+    ffassert(pTh);
+    const Mesh & Th(*pTh);
+    int nt=Th.nt,nv=Th.nv;
+    int nve = Mesh::Element::NbV;
+    
+    KN<idx_t> elmnts(nve*nt), epart(nt), npart(nv);
+    for(int k=0,i=0;k<nt;++k)
+	for(int j=0;j<nve;j++)
+	    elmnts[i++] = Th(k,j);
+    int numflag=0;
+    int nparts=lparts;
+    int edgecut;
+    int etype =nve-2; // triangle
+#ifdef  METIS_VER_MAJOR    
+    printf("  %d-way Edge-Cut: %7d, Balance: %5.2f\n", nparts, nve, libmetis__ComputeElementBalance(nt, nparts, epart));
+#else
+    printf("  %d-way Edge-Cut: %7d, Balance: %5.2f\n", nparts, nve, ComputeElementBalance(nt, nparts, epart));
+#endif
+    part->resize(nt);
+    *part=epart;
+    return part;
+}
+/*  class Init { public:
+    Init();
+};
+// E_F_StackF0F0
+
+$1 */
+static void Load_Init(){
+  if(verbosity && mpirank == 0) 
+  cout << " lood: init metis  " << endl;
+  Global.Add("metisnodal","(",new OneOperator3_<KN<long> *,KN<long> *,Mesh *,long , E_F_stackF0F0F0_<KN<long> *,KN<long> *,Mesh *,long> >(&partmetis<Mesh,0>));
+  Global.Add("metisdual","(",new OneOperator3_<KN<long> *,KN<long> *,Mesh *,long , E_F_stackF0F0F0_<KN<long> *,KN<long> *,Mesh *,long> >(&partmetis<Mesh,1>));
+    Global.Add("metisnodal","(",new OneOperator3_<KN<long> *,KN<long> *,Mesh3 *,long , E_F_stackF0F0F0_<KN<long> *,KN<long> *,Mesh3 *,long> >(&partmetis<Mesh3,0>));
+    Global.Add("metisdual","(",new OneOperator3_<KN<long> *,KN<long> *,Mesh3 *,long , E_F_stackF0F0F0_<KN<long> *,KN<long> *,Mesh3 *,long> >(&partmetis<Mesh3,1>));
+    
+    Global.Add("metisnodal","(",new OneOperator3_<KN<double> *,KN<double> *,Mesh *,long , E_F_stackF0F0F0_<KN<double> *,KN<double> *,Mesh *,long> >(&partmetis<Mesh,0>));
+    Global.Add("metisdual","(",new OneOperator3_<KN<double> *,KN<double> *,Mesh *,long , E_F_stackF0F0F0_<KN<double> *,KN<double> *,Mesh *,long> >(&partmetis<Mesh,1>));
+    Global.Add("metisnodal","(",new OneOperator3_<KN<double> *,KN<double> *,Mesh3 *,long , E_F_stackF0F0F0_<KN<double> *,KN<double> *,Mesh3 *,long> >(&partmetis<Mesh3,0>));
+    Global.Add("metisdual","(",new OneOperator3_<KN<double> *,KN<double> *,Mesh3 *,long , E_F_stackF0F0F0_<KN<double> *,KN<double> *,Mesh3 *,long> >(&partmetis<Mesh3,1>));
+    
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/metis.edp b/examples++-load/metis.edp
new file mode 100644
index 0000000..3c2a335
--- /dev/null
+++ b/examples++-load/metis.edp
@@ -0,0 +1,15 @@
+load "metis"
+mesh Th=square(100,100);
+fespace Ph(Th,P0);
+int[int] nupart(Th.nt);
+Ph  part;
+
+metisnodal(nupart,Th,100);
+for(int i=0;i<nupart.n;++i)
+  part[][i]=nupart[i];
+plot(part,fill=1,cmm="nodal",wait=1);
+
+metisdual(nupart,Th,100);
+for(int i=0;i<nupart.n;++i)
+  part[][i]=nupart[i];
+plot(part,fill=1,cmm="dual",wait=1);
\ No newline at end of file
diff --git a/examples++-load/mmg3d-v4.0.cpp b/examples++-load/mmg3d-v4.0.cpp
new file mode 100644
index 0000000..5ea0209
--- /dev/null
+++ b/examples++-load/mmg3d-v4.0.cpp
@@ -0,0 +1,440 @@
+// ORIG-DATE:     Fev 2010
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : liaison medit freefem++ : adaptmesh in 3d 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// Modif    : F. hecht  : Frederic.hecht at upmc.fr
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+
+//
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:   mmg3d-v4
+//ff-c++-cpp-dep: 
+//  
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+//  ./ff-c++ mmg3dv4.cpp  -I../download/include/mmg3d/  -lmmg3d4 
+
+#include "ff++.hpp" 
+#include "msh3.hpp"
+//#define ADAPTLIBRARY"
+#include "dataff.h"
+
+using namespace  Fem2D;
+//using namespace  mmg3d;
+
+inline void add2(int *k,int n, int a)
+{
+    for (int i=0;i<n;++i)
+      k[i] += a; 
+}
+void set_mesh(void *dataff,int *data,int ldata)
+{
+    DataFF *dff=(DataFF *) dataff;
+    
+    int nnv= data[ff_id_vertex];
+    int nnt= data[ff_id_tet];
+    int nnbe= data[ff_id_tria];
+    Vertex3 *vv = new Vertex3[nnv];
+    Tet *tt= new Tet[nnt]; 
+    Triangle3 *bb=new Triangle3[nnbe];
+    
+    Mesh3 * pTh= new Mesh3();
+    pTh->nv = nnv;
+    pTh->nt = nnt;
+    pTh->nbe =nnbe;
+    
+    pTh->vertices = vv;
+    pTh->elements = tt;
+    pTh->borderelements = bb;
+    
+    pTh->mes=0.;
+    pTh->mesb=0.;
+    
+    dff->mesh= pTh; 
+    if(verbosity>5) cout << " Set_mesh nv=" << nnv << " nTet " << nnt<< " NTria " <<nnbe << endl;
+}
+void end_mesh(void *dataff)
+{
+    DataFF *dff=(DataFF *) dataff;
+
+    Mesh3 &  Th = *(Mesh3 *) dff->mesh;
+    
+    Th.mes=0.;
+    Th.mesb=0.;
+    
+    for (int i=0;i<Th.nbe;i++)  
+	Th.mesb += Th.be(i).mesure();  
+
+    //  Add FH to be consitant we all constructor ...  July 09
+    Th.BuildBound();
+    //Th.Save("TTTh.mesh");
+    if(verbosity>5)
+      cout << "end_mesh:  Th.mes = " << Th.mes << " Th.mesb = " << Th.mesb << endl;
+    if(Th.nt > 0){ 
+	Th.BuildAdj();
+	Th.Buildbnormalv();  
+	Th.BuildjElementConteningVertex();  
+    }
+    //  end add       
+    
+    if(verbosity>1)
+	cout << "  -- End of Construct  mesh3: mesure = " << Th.mes << " border mesure " << Th.mesb <<  endl;  
+    ffassert(Th.mes>=0); // add F. Hecht sep 2009.
+        
+}
+void set_v(void *dataff,int i,double *xyz,int lab)
+{
+  i--; 
+  DataFF *dff=(DataFF *) dataff;
+  ffassert(dff->mesh);
+  Mesh3 &  Th= * (Mesh3 *) dff->mesh;
+  Th.vertices[i].x = xyz[0];
+  Th.vertices[i].y = xyz[1];
+  Th.vertices[i].z = xyz[2];
+  Th.vertices[i].lab = lab;
+  if(verbosity>10) 
+    cout << " set_v3 " <<i << " " <<  xyz[0] << " "  << xyz[1] << " "  << xyz[02] << " "  << lab  << endl;
+  
+}
+void set_elmt(void *dataff,int id,int i,int *k,int lab)
+{
+  i--;
+  int n=0;
+    DataFF *dff=(DataFF *) dataff;
+    ffassert(dff->mesh);
+    Mesh3 &  Th= *(Mesh3 *) dff->mesh;
+      if( id == 2) 
+      {
+	n=3;
+	Mesh3::BorderElement & K(Th.be(i));
+	add2(k,3,-1);		  
+	K.set(Th.vertices,k,lab);
+      }
+	
+    else if ( id== 3) 
+      {
+	n=4; 
+	Mesh3::Element & K(Th.t(i));
+	add2(k,4,-1);
+	K.set(Th.vertices,k,lab);
+      }
+    else
+      {
+	cout << " unknows id = " << id << " not 2 or 3 " << endl;
+	ffassert(0); 
+      }
+
+  if(verbosity>10) 
+    {
+      cout << " set_ele"<< n << " "  <<i << " "  ;
+      for(int j=0;j<n;j++)
+	cout << k[j] << " ";
+      cout << lab << endl;
+    }
+
+}
+void get_mesh(void *dataff,int *data,int ldata)
+{
+    DataFF *dff=(DataFF *) dataff;
+    assert(ldata>5);
+    for(int i=0;i<ldata;++i)
+	data[i]=0;
+    ffassert(dff->mesh);
+    Mesh3 &  Th= *(Mesh3*) dff->mesh;
+    data[ff_id_vertex]=  Th.nv;
+    data[ff_id_tria]=  Th.nbe;
+    data[ff_id_tet]=  Th.nt;
+    if(verbosity>9) 
+      cout << " get_mesh " << Th.nv << " "<< Th.nbe << " "<< Th.nt << endl; 
+    
+}
+void get_v3(void *dataff,int i,double *xyz,int *lab)
+{
+  i--;
+  DataFF *dff=(DataFF *) dataff;
+  ffassert(dff->mesh);
+  Mesh3 &  Th= *(Mesh3*) dff->mesh;
+  xyz[0] = Th.vertices[i].x ;
+  xyz[1] = Th.vertices[i].y ;
+  xyz[2] = Th.vertices[i].z ;
+  *lab = Th.vertices[i].lab ;
+  if(verbosity>10) 
+    cout << " get_v3 " <<i << " " <<  xyz[0] << " "  << xyz[1] << " "  << xyz[2] << " "  << *lab  << endl;
+    
+  
+}
+void get_elmt(void *dataff,int id,int i,int *k,int *lab)
+{
+  i--;
+  DataFF *dff=(DataFF *) dataff;
+  ffassert(dff->mesh);
+  Mesh3 &  Th= *(Mesh3*)dff->mesh;
+  int n =0;
+  if( id == 2) 
+    {
+      n=3; 
+      Mesh3::BorderElement & K(Th.be(i));
+      for (int j=0; j<n;++j)
+	k[j]=Th(K[j]); 
+      
+      *lab = K.lab;
+    }
+  
+  else if ( id== 3) 
+    {
+      n=4;
+	Mesh3::Element & K(Th.t(i));
+        for (int j=0; j<n;++j)
+	  k[j]=Th(K[j]); 	
+	*lab=K.lab;
+    } 
+  else {
+    cout << "  id != 2, 3 , id = = "<< id  << endl;  
+    ffassert(0); 
+  }
+  add2(k,n,+1);
+  
+  if(verbosity>10) 
+    {
+      cout << " get_ele"<< n << " "  <<i << " "  ;
+      for(int j=0;j<n;j++)
+	cout << k[j] << " ";
+      cout << *lab << endl;
+    }
+  
+}
+
+
+
+class mmg3d_Op: public E_F0mps 
+{
+public:
+  Expression eTh,xx,yy,zz;
+  static const int n_name_param = 5; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>   karg(int i,Stack stack) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): KN_<long>((long*) 0,0L) ;}
+
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  string  arg(int i,Stack stack,const char * a ) const{ return nargs[i] ? *GetAny< string * >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack, long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  
+  
+public:
+  mmg3d_Op(const basicAC_F0 &  args ,Expression tth) 
+    : eTh(tth),xx(0),yy(0),zz(0) 
+  {
+    if(verbosity >1) 
+      cout << "mmg3d v4 "<< endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    
+    const E_Array * a1=0 ;
+    if(nargs[1])  a1  = dynamic_cast<const E_Array *>(nargs[1]);
+  
+    if(a1) {
+      if(a1->size() !=3) 
+	CompileError("mmg3d(Th,displacement=[X,Y,Z],) ");
+      xx=to<double>( (*a1)[0]); 
+      yy=to<double>( (*a1)[1]);
+      zz=to<double>( (*a1)[2]);
+    }    
+    else if ( nargs[1] ) 
+      CompileError("mmg3d(Th,displacement=[X,Y,Z], .... ) ");
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+
+basicAC_F0::name_and_type  mmg3d_Op::name_param[]= {
+  {  "metric", &typeid(KN<double> *)},   // 0
+  {  "displacement", &typeid(E_Array)},  // 1
+  {  "displVect", &typeid(KN_<double>)},   // 2
+  {  "opt", &typeid(string*)}, // 3
+  {  "Mb",&typeid(long)} // 4
+};
+
+class mmg3d_ff : public OneOperator { public:  
+     mmg3d_ff() : OneOperator( atype<pmesh3>(), atype<pmesh3>() ) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+	return  new  mmg3d_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+AnyType mmg3d_Op::operator()(Stack stack)  const 
+{
+  // initialisation
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  ffassert( pTh );
+  Mesh3 &Th3=*pTh;
+    string sarg= arg(3,stack,"");
+    DataFF dff;
+    dff.memory= arg(4,stack,128L); // 128 Mb .. ????  
+    ffassert( dff.memory < 2048 );// 2 GiGa bytes   limite of integer .. 
+    dff.typesol=0;
+    dff.np=pTh->nv;
+    dff.mesh=pTh;
+    dff.meshname="Th";
+    dff.imprim=verbosity;
+    dff.sol=0;
+    dff.mov=0;
+    dff.set_mesh =set_mesh;
+    dff.end_mesh =end_mesh;
+    dff.set_v = set_v;
+    dff.set_elmt = set_elmt;
+    dff.get_mesh = get_mesh;
+    dff.get_v3 = get_v3;
+    dff.get_elmt= get_elmt;
+
+  KN<double> *pmetric=0;
+  
+  if( nargs[0] ){ 
+    pmetric = GetAny< KN<double> *>( (*nargs[0])(stack) );
+    ffassert(pmetric) ;
+  }
+
+  KN<double>  cmetric; 
+  if(pmetric)
+    {
+      int m=pmetric->N();
+      if( m == Th3.nv*6) // 
+	{
+	  cmetric = (*pmetric);
+	  dff.typesol=6;
+	  dff.np = Th3.nv;
+	  for(int i=0;i <m; i += 6)
+	    std::swap(cmetric[i+2],cmetric[i+3]); 
+	  dff.sol= &cmetric[0];
+	  dff.solname="metrix-aniso";
+	}
+      else if ( m == Th3.nv) 
+	{
+	  dff.typesol = 1;
+	  dff.np = Th3.nv;
+	  dff.sol = &(*pmetric)[0];
+	  dff.solname="metrix-iso";
+	}
+      else
+	ExecError(" mmg3d v4: incompatibility  metric array  mesh ");
+    }
+
+
+ 
+ 
+  bool BoolMoving=0;
+  KN<double> Moving(0);
+  
+  if( nargs[1] || nargs[2] ){
+    BoolMoving=1;
+    if( nargs[2] ){
+      Moving = GetAny<double>( (*nargs[2])(stack) );
+      assert( Moving.N() == 3*Th3.nv );
+      dff.movename="move";
+      dff.mov = Moving;
+      if( Moving.N() != 3*Th3.nv ){ cerr << " Displacement vector is of size 3*Th.nv" << endl;
+	ExecError(" mmg3d v4");} 
+    }
+    else{ 
+      MeshPoint *mp3(MeshPointStack(stack));
+      Moving.resize(3*Th3.nv);
+      for( int i=0; i<Th3.nv; ++i){
+	mp3->set( Th3.vertices[i].x, Th3.vertices[i].y, Th3.vertices[i].z );
+	if(xx) Moving[3*i]   = GetAny<double>((*xx)(stack)); 
+	if(yy) Moving[3*i+1] = GetAny<double>((*yy)(stack));
+	if(zz) Moving[3*i+2] = GetAny<double>((*zz)(stack));  
+      }
+      dff.mov = Moving;
+      dff.movename="move";
+    }
+    //if(verbosity > 2) 
+    if(verbosity >2) cout << "displacement vector is loading" << endl;
+  }
+
+    int argc=1;
+    char * argv[1000];
+    char ff[10]="ff++";
+    KN<char> args(sarg.size()+1);
+    argv[0] = ff; 
+    argv[1] = & args[0]; 
+    strcpy(args, sarg.c_str());
+    //cout << sarg << " == " << &args[0] << endl;
+    char cc='\0';
+    for(int i=0;i<args.N();cc=args[i++])
+      {
+	if (isspace(args[i]) &&  cc!='\\' ) cc=args[i]='\0';		
+	else if ( !cc ) argv[argc++]=& args[i];	
+	ffassert(argc<1000);
+      }
+    
+ //   for(int i=0;i< argc; ++i)
+//	cout << " *** arg " << i << " " << argv[i] << endl;
+	    		
+  int res= mainmmg3d(argc,argv,&dff);
+  Mesh3 * pTh3 = (Mesh3 *) dff.mesh;
+  if( res > 0){
+      dff.mesh=0;
+    cout << " problem of remeshing with mmg3d :: error" <<  res << endl; 
+  }
+
+  if(! pTh3 ){
+	  cout << " problem of remeshing with mmg3d v 4 (no mesh)  :: error" <<  res << endl; 
+      ExecError(" Error mmg3d" );} 
+  else {
+      //  end build of TH3...
+      if(verbosity > 10) cout << "buildGtree" << endl;
+      pTh3->BuildGTree();
+  }
+  
+  *mp=mps;
+  Add2StackOfPtr2FreeRC(stack,pTh3);
+  return pTh3;
+}
+
+
+/*  class Init1 { public:
+  Init1();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  
+  //if (verbosity)
+  if(verbosity) cout << " load: mmg3d  " << endl;
+  
+  Global.Add("mmg3d","(",new mmg3d_ff);
+  
+}
+
+
+#define  WITH_NO_INIT
+#include "msh3.hpp" 
+LOADFUNC(Load_Init)
diff --git a/examples++-load/msh3.cpp b/examples++-load/msh3.cpp
new file mode 100644
index 0000000..0f01897
--- /dev/null
+++ b/examples++-load/msh3.cpp
@@ -0,0 +1,5875 @@
+// ORIG-DATE: Novembre 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+//  FH   July 2009
+//   comment all
+//       Th3_t->BuildBound();
+//       Th3_t->BuildAdj();
+//       Th3_t->Buildbnormalv();  
+//       Th3_t->BuildjElementConteningVertex();
+//   is now in the constructor of Mesh3 to be consistante. 
+//   
+#ifndef WITH_NO_INIT
+#include "ff++.hpp"
+#endif
+#include "AFunction_ext.hpp"
+
+
+//  TransfoMesh_v2.cpp
+using namespace std;
+// LayerMesh.cpp
+// buildlayer.cpp
+// trunc3d.cpp
+// rajout global
+
+#include <set>
+#include <vector>
+#include "msh3.hpp"
+#include "splitsimplex.hpp"
+
+using namespace  Fem2D;
+
+int  ChangeLab3D(const map<int,int> & m,int lab);
+
+void TestSameVertexMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int & nv_t, int *Numero_Som){
+  
+  Vertex3  *v=new Vertex3[Th3.nv];
+  nv_t=0;
+  
+  EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(v,Pinf,Psup,0);
+  
+  // creation of octree
+  for (int ii=0;ii<Th3.nv;ii++){
+    const R3 r3vi( Th3.vertices[ii].x, Th3.vertices[ii].y, Th3.vertices[ii].z );
+    const Vertex3 &vi(r3vi);
+    
+    Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+    
+    if(!pvi){
+      v[nv_t].x = vi.x;
+      v[nv_t].y = vi.y;
+      v[nv_t].z = vi.z;
+      v[nv_t].lab = Th3.vertices[ii].lab; // lab mis a zero par default
+      Numero_Som[ii] = nv_t; 
+      gtree->Add( v[nv_t] );
+      nv_t=nv_t+1;
+    }
+    else{
+      Numero_Som[ii] = pvi-v;
+    }
+  }
+  
+  delete gtree;
+  delete [] v;
+}
+
+void TestSameTetrahedraMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int & nt_t ){
+
+  Vertex3 *vt=new Vertex3[Th3.nt];
+  EF23::GTree<Vertex3> *gtree_t = new EF23::GTree<Vertex3>(vt,Pinf,Psup,0);
+  
+  nt_t=0;
+  // creation of octree
+  for (int ii=0;ii<Th3.nt;ii++){
+    const Tet & K(Th3.elements[ii]);
+    int iv[4];
+
+    for(int jj=0; jj <4; jj++)
+      iv[jj] = Th3.operator()(K[jj]);
+    
+    const double Cdg_x = ( Th3.vertices[iv[0]].x + Th3.vertices[iv[1]].x + Th3.vertices[iv[2]].x + Th3.vertices[iv[3]].x )/4.;
+    const double Cdg_y = ( Th3.vertices[iv[0]].y + Th3.vertices[iv[1]].y + Th3.vertices[iv[2]].y + Th3.vertices[iv[3]].y )/4.;
+    const double Cdg_z = ( Th3.vertices[iv[0]].z + Th3.vertices[iv[1]].z + Th3.vertices[iv[2]].z + Th3.vertices[iv[3]].z )/4.;
+
+    const R3 r3vi( Cdg_x, Cdg_y, Cdg_z );
+    const Vertex3 &vi(r3vi);
+    
+    Vertex3 * pvi=gtree_t->ToClose(vi,hseuil);
+    
+    if(!pvi){
+      vt[nt_t].x = vi.x;
+      vt[nt_t].y = vi.y;
+      vt[nt_t].z = vi.z;
+      vt[nt_t].lab = K.lab ; // lab mis a zero par default
+      gtree_t->Add( vt[nt_t] );
+      nt_t=nt_t+1;
+    }
+  }
+  
+  delete gtree_t;
+  delete [] vt;
+} 
+
+void TestSameTetrahedraMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int *Elem_ok, int & nt_t ){
+
+  Vertex3 *vt=new Vertex3[Th3.nt];
+  EF23::GTree<Vertex3> *gtree_t = new EF23::GTree<Vertex3>(vt,Pinf,Psup,0);
+  
+  nt_t=0;
+  // creation of octree
+  for (int ii=0;ii<Th3.nt;ii++){
+    if(Elem_ok[ii]!=1) continue;
+    const Tet & K(Th3.elements[ii]);
+    int iv[4];
+
+    for(int jj=0; jj <4; jj++)
+      iv[jj] = Th3.operator()(K[jj]);
+    
+    const double Cdg_x = ( Th3.vertices[iv[0]].x + Th3.vertices[iv[1]].x + Th3.vertices[iv[2]].x + Th3.vertices[iv[3]].x )/4.;
+    const double Cdg_y = ( Th3.vertices[iv[0]].y + Th3.vertices[iv[1]].y + Th3.vertices[iv[2]].y + Th3.vertices[iv[3]].y )/4.;
+    const double Cdg_z = ( Th3.vertices[iv[0]].z + Th3.vertices[iv[1]].z + Th3.vertices[iv[2]].z + Th3.vertices[iv[3]].z )/4.;
+
+    const R3 r3vi( Cdg_x, Cdg_y, Cdg_z );
+    const Vertex3 &vi(r3vi);
+    
+    Vertex3 * pvi=gtree_t->ToClose(vi,hseuil);
+    
+    if(!pvi){
+      vt[nt_t].x = vi.x;
+      vt[nt_t].y = vi.y;
+      vt[nt_t].z = vi.z;
+      vt[nt_t].lab = K.lab ; // lab mis a zero par default
+      gtree_t->Add( vt[nt_t] );
+      nt_t=nt_t+1;
+    }
+    else{
+      Elem_ok[ii]=0;
+    }
+  }
+  
+  delete gtree_t;
+  delete [] vt;
+} 
+
+
+void TestSameTriangleMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int & nbe_t){
+
+  Vertex3  *vbe= new Vertex3[Th3.nbe];
+  EF23::GTree<Vertex3> *gtree_be = new EF23::GTree<Vertex3>(vbe,Pinf,Psup,0);
+  
+  nbe_t=0;
+  // creation of octree
+  for (int ii=0;ii<Th3.nbe;ii++){
+    const Triangle3 & K(Th3.be(ii));
+    int iv[3];
+
+    for(int jj=0; jj<3; jj++)
+      iv[jj] = Th3.operator()(K[jj]);
+    
+    const double Cdg_x = ( Th3.vertices[iv[0]].x + Th3.vertices[iv[1]].x + Th3.vertices[iv[2]].x )/3.;
+    const double Cdg_y = ( Th3.vertices[iv[0]].y + Th3.vertices[iv[1]].y + Th3.vertices[iv[2]].y )/3.;
+    const double Cdg_z = ( Th3.vertices[iv[0]].z + Th3.vertices[iv[1]].z + Th3.vertices[iv[2]].z )/3.;
+
+    const R3 r3vi( Cdg_x, Cdg_y, Cdg_z );
+    const Vertex3 &vi(r3vi);
+    
+    Vertex3 * pvi=gtree_be->ToClose(vi,hseuil);
+    
+    if(!pvi){
+      vbe[nbe_t].x = vi.x;
+      vbe[nbe_t].y = vi.y;
+      vbe[nbe_t].z = vi.z;
+      vbe[nbe_t].lab = K.lab ; // lab mis a zero par default
+      gtree_be->Add( vbe[nbe_t] );
+      nbe_t=nbe_t+1;
+    }
+   
+  }
+  
+  delete gtree_be;
+  delete [] vbe;
+} 
+
+void TestSameTriangleMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int *Border_ok ,int & nbe_t ){
+
+  Vertex3 *vbe=new Vertex3 [Th3.nbe];
+  EF23::GTree<Vertex3> *gtree_be = new EF23::GTree<Vertex3>(vbe,Pinf,Psup,0);
+  
+  nbe_t=0;
+  // creation of octree
+  for (int ii=0;ii<Th3.nbe;ii++){
+    if(Border_ok[ii]!=1) continue;
+    const Triangle3 & K(Th3.be(ii));
+    int iv[3];
+
+    for(int jj=0; jj<3; jj++)
+      iv[jj] = Th3.operator()(K[jj]);
+    
+    const double Cdg_x = ( Th3.vertices[iv[0]].x + Th3.vertices[iv[1]].x + Th3.vertices[iv[2]].x )/3.;
+    const double Cdg_y = ( Th3.vertices[iv[0]].y + Th3.vertices[iv[1]].y + Th3.vertices[iv[2]].y )/3.;
+    const double Cdg_z = ( Th3.vertices[iv[0]].z + Th3.vertices[iv[1]].z + Th3.vertices[iv[2]].z )/3.;
+
+    const R3 r3vi( Cdg_x, Cdg_y, Cdg_z );
+    const Vertex3 &vi(r3vi);
+    
+    Vertex3 * pvi=gtree_be->ToClose(vi,hseuil);
+    
+    if(!pvi){
+      vbe[nbe_t].x = vi.x;
+      vbe[nbe_t].y = vi.y;
+      vbe[nbe_t].z = vi.z;
+      vbe[nbe_t].lab = K.lab ; // lab mis a zero par default
+      gtree_be->Add( vbe[nbe_t] );
+      nbe_t=nbe_t+1;
+    }
+    else{      
+      if(K.lab == vbe[pvi-vbe].lab )  Border_ok[ii] = 0;
+    }
+  }
+  
+  delete gtree_be;
+  delete [] vbe;
+} 
+
+int TestElementMesh3( const Mesh3 & Th3 ) 
+// Test si le maillage � des �l�ments communs : Sommet, triangle, ...
+{
+//  FH 31/09/2009:  Change  int* to KN<int> to remove pb of missing free in some case 
+  R3 Pinf(1e100,1e100,1e100),Psup(-1e100,-1e100,-1e100);   // Extremit� de la bo�te englobante
+  double hmin=1e10;   // longueur minimal des arr�tes
+  double hseuil;
+  KN<int> Numero_Som(Th3.nv);
+  int nv_t,nt_t,nbe_t;
+  
+  // calcul de la boite englobante
+  for (int ii=0;ii<Th3.nv;ii++){ 
+    R3 P( Th3.vertices[ii].x, Th3.vertices[ii].y, Th3.vertices[ii].z);
+    Pinf=Minc(P,Pinf);
+    Psup=Maxc(P,Psup);     
+  }
+
+
+  // calcul de la longueur minimal des arr�tes
+  for (int k=0;k<Th3.nt;k++){
+    for (int e=0;e<6;e++){
+      if( Th3[k].lenEdge(e) < Norme2(Psup-Pinf)/1e9 )
+	{
+	  const Tet & K(Th3.elements[k]);
+	  int iv[4];
+	  for(int jj=0; jj <4; jj++){
+	    iv[jj] = Th3.operator()(K[jj]);
+	  }
+	  for (int eh=0;eh<6;eh++){
+	    cout << "tetrahedra: " << k << " edge : " << eh << " lenght "<<  Th3[k].lenEdge(eh) << endl;
+	    cout << " Tet vertices : " <<iv[0] << " " << iv[1] << " " << iv[2] << " " << iv[3] << " " << endl;
+	  }
+	  cout << " A tetrahedra with a very small edge was created " << endl;
+	 
+	  return 1;
+	}
+      hmin=min(hmin,Th3[k].lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+    }
+  }
+  
+  for (int k=0;k<Th3.nbe;k++){
+    for (int e=0;e<3;e++){
+      if( Th3.be(k).lenEdge(e) < Norme2(Psup-Pinf)/1e9 )
+	{
+	  for (int eh=0;eh<3;e++){
+	    cout << "triangles: " << k << " edge : " << eh << " lenght "<<  Th3.be(k).lenEdge(e) << endl;
+	  }
+	  cout << " A triangle with a very small edges was created " << endl;
+	  return 1;
+	}
+      hmin=min(hmin,Th3.be(k).lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+    }
+  }
+
+  if(verbosity > 1) cout << "      - hmin =" <<  hmin << " ,  Bounding Box: " << Pinf << " "<< Psup << endl;
+
+  ffassert(hmin>Norme2(Psup-Pinf)/1e9);
+
+  // determination du nombre de sommets confondus
+  hseuil = hmin/10.;     
+  
+  if(verbosity >1) cout << "TestSameVertexMesh3 " << hseuil << " size" <<Th3.nv<< endl;
+  TestSameVertexMesh3( Th3, hseuil, Psup, Pinf, nv_t, Numero_Som );
+  
+  if(verbosity >1) cout << "hseuil=" << hseuil << endl; 
+  if(verbosity >1) cout << "NbVertexRecollement " << nv_t << " / " << "NbVertex(anc)" << Th3.nv <<endl;   
+
+  if(nv_t != Th3.nv) {
+   // delete [] Numero_Som;
+    cout << " A vertex was referenced twice or more " << endl;
+    return 1;
+  }
+  /* degenerate element ??? */ 
+  KN<int> Elem_ok(Th3.nt);
+  int i_elem=0;
+  for(int ii=0; ii< Th3.nt; ii++){
+    const Tet & K(Th3.elements[ii]);
+    int iv[4];
+    
+    Elem_ok[ii] = 1;
+    
+    for(int jj=0; jj <4; jj++){
+      iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+    }
+      
+    for(int jj=0; jj<4; jj++){
+      for(int kk=jj+1; kk<4; kk++){
+	if( iv[jj]==iv[kk] ){
+	  Elem_ok[ii] = 0;
+	}
+      }
+    }
+    i_elem = i_elem + Elem_ok[ii];
+  }
+   
+  if( i_elem != Th3.nt ){
+    cout << "There are a false tetrahedra in the mesh" << endl;
+    assert( i_elem == Th3.nt);
+  }
+
+  KN<int> Border_ok(Th3.nbe);
+  int i_border= 0;
+  for( int ii=0; ii< Th3.nbe; ii++){
+    Border_ok[ii]=1;
+    
+    const Triangle3 & K(Th3.be(ii));
+    int iv[3];
+    
+    for(int jj=0; jj <3; jj++){
+      iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+      assert( iv[jj] >= 0 && iv[jj] < nv_t);
+    }
+    
+    for(int jj=0; jj<3; jj++){
+      for(int kk=jj+1; kk<3; kk++){
+	if( iv[jj]==iv[kk] ) Border_ok[ii]=0;
+      }
+    }
+    i_border = i_border + Border_ok[ii];
+  }
+  
+  if( i_border != Th3.nbe){
+    cout << "There are a false tetrahedra in the mesh" << endl;
+    assert( i_elem == Th3.nt);
+  }
+
+  /* determination du nombre de tetrahedre confondus */ 
+  hseuil = hmin/10.;
+  hseuil = hseuil/4.;
+  
+  if(verbosity >1) cout << "TestSameTetrahedraMesh3 " << hseuil << " size "<< Th3.nt <<endl;
+  TestSameTetrahedraMesh3( Th3, hseuil, Psup, Pinf, Elem_ok, nt_t );
+
+  if(verbosity >1) cout << "hseuil=" << hseuil << endl; 
+  if(verbosity >1) cout << "NbTetrahedraRecollement " << nt_t << " / " << "NbVertex(anc)" << Th3.nt <<endl;  
+
+  if(nt_t != Th3.nt){
+    cout << " a tetrahedra was referenced twice or more " << endl;
+    return 1;
+  }
+  /* determination du nombre de triangles confondus */ 
+  hseuil = hmin/10.;
+  hseuil = hseuil/3.;
+  if(verbosity >1) cout << "TestSameTriangleMesh3 " << hseuil << endl;
+  TestSameTriangleMesh3( Th3, hseuil, Psup, Pinf, Border_ok,  nbe_t );
+ 
+  if(verbosity >1) cout << "hseuil=" << hseuil << endl; 
+  if(verbosity >1) cout << "NbVertexRecollement " << nbe_t << " / " << "NbVertex(anc)" << Th3.nbe <<endl;  
+
+  if(nbe_t != Th3.nbe){
+    cout << " a triangle was referenced twice or more " << endl;
+    return 1;
+  }
+    
+  return 0;
+}
+
+
+Mesh3 *TestElementMesh3_patch( const Mesh3 & Th3 ) 
+// Test si le maillage � des �l�ments communs : Sommet, triangle, ...
+{
+  R3 Pinf(1e100,1e100,1e100),Psup(-1e100,-1e100,-1e100);   // Extremit� de la bo�te englobante
+  double hmin=1e10;   // longueur minimal des arr�tes
+  double hseuil;
+  int *Numero_Som = new int [Th3.nv];
+  int nv_t,nt_t,nbe_t;
+  
+  // calcul de la boite englobante
+  for (int ii=0;ii<Th3.nv;ii++){ 
+    R3 P( Th3.vertices[ii].x, Th3.vertices[ii].y, Th3.vertices[ii].z);
+    Pinf=Minc(P,Pinf);
+    Psup=Maxc(P,Psup);     
+  }
+
+  // calcul de la longueur minimal des arr�tes
+  for (int k=0;k<Th3.nt;k++){
+    for (int e=0;e<6;e++){
+      if( Th3[k].lenEdge(e) < Norme2(Psup-Pinf)/1e9 ) continue;
+      hmin=min(hmin,Th3[k].lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+    }
+  }
+  
+  for (int k=0;k<Th3.nbe;k++){
+    for (int e=0;e<3;e++){
+      if( Th3[k].lenEdge(e) < Norme2(Psup-Pinf)/1e9 ) continue;
+      hmin=min(hmin,Th3.be(k).lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+    }
+  }
+
+  if(verbosity > 1) cout << "      - hmin =" <<  hmin << " ,  Bounding Box: " << Pinf << " "<< Psup << endl;
+
+  ffassert(hmin>Norme2(Psup-Pinf)/1e9);
+
+  // determination du nombre de sommets confondus
+  hseuil = hmin/10.;     
+  if(verbosity >1) cout << "TestSameVertexMesh3" << endl;
+  TestSameVertexMesh3( Th3, hseuil, Psup, Pinf, nv_t, Numero_Som );
+  
+  if(verbosity >1) cout << "hseuil=" << hseuil << endl; 
+  if(verbosity >1) cout << "NbVertexRecollement " << nv_t << " / " << "NbVertex(anc)" << Th3.nv <<endl;   
+
+  /* degenerate element ??? */ 
+  int *Elem_ok=new int[Th3.nt];
+  int i_elem=0;
+  for(int ii=0; ii< Th3.nt; ii++){
+    const Tet & K(Th3.elements[ii]);
+    int iv[4];
+    
+    Elem_ok[ii] = 1;
+    
+    for(int jj=0; jj <4; jj++){
+      iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+    }
+      
+    for(int jj=0; jj<4; jj++){
+      for(int kk=jj+1; kk<4; kk++){
+	if( iv[jj]==iv[kk] ){
+	  Elem_ok[ii] = 0;
+	}
+      }
+    }
+    i_elem = i_elem + Elem_ok[ii];
+  }
+   
+  if( i_elem != Th3.nt ){
+    cout << "There are a false tetrahedra in the mesh" << endl;
+    //assert( i_elem == Th3.nt);
+  }
+
+  int *Border_ok=new int[Th3.nbe];
+  int i_border= 0;
+  for( int ii=0; ii< Th3.nbe; ii++){
+    Border_ok[ii]=1;
+    
+    const Triangle3 & K(Th3.be(ii));
+    int iv[3];
+    
+    for(int jj=0; jj <3; jj++){
+      iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+      assert( iv[jj] >= 0 && iv[jj] < nv_t);
+    }
+    
+    for(int jj=0; jj<3; jj++){
+      for(int kk=jj+1; kk<3; kk++){
+	if( iv[jj]==iv[kk] ) Border_ok[ii]=0;
+      }
+    }
+    i_border = i_border + Border_ok[ii];
+  }
+  
+  if( i_border != Th3.nbe){
+    cout << "There are a false tetrahedra in the mesh" << endl;
+    //assert( i_elem == Th3.nt);
+  }
+
+  /* determination du nombre de tetrahedre confondus */ 
+  hseuil = hmin/10.;
+  hseuil = hseuil/4.;
+  nt_t=0;
+  TestSameTetrahedraMesh3( Th3, hseuil, Psup, Pinf, Elem_ok, nt_t );
+
+  if(verbosity >1) cout << "hseuil=" << hseuil << endl; 
+  if(verbosity >1) cout << "NbVertexRecollement " << nt_t << " / " << "NbVertex(anc)" << Th3.nt <<endl;  
+
+  /* determination du nombre de triangles confondus */ 
+  hseuil = hmin/10.;
+  hseuil = hseuil/3.;
+  TestSameTriangleMesh3( Th3, hseuil, Psup, Pinf, Border_ok,  nbe_t );
+ 
+  if(verbosity >1) cout << "hseuil=" << hseuil << endl; 
+  if(verbosity >1) cout << "NbVertexRecollement " << nbe_t << " / " << "NbVertex(anc)" << Th3.nbe <<endl;  
+
+  Vertex3   *v= new Vertex3[nv_t];
+  Tet       *t= new Tet[nt_t];
+  Triangle3 *b= new Triangle3[nbe_t]; 
+  Tet       *tt=t;
+  Triangle3 *bb=b; 
+
+  EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(v,Pinf,Psup,0);
+
+  // determination des nouveaux sommets
+  int nbv = 0; 
+  hseuil = hmin/10.;
+  for (int ii=0;ii<Th3.nv;ii++){
+    const Vertex3 &vi(Th3.vertices[ii]); 
+    Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+      
+    if(!pvi){
+      v[nbv].x = vi.x;
+      v[nbv].y = vi.y;
+      v[nbv].z = vi.z;
+      v[nbv].lab = vi.lab;
+      gtree->Add( v[nbv++] );
+    }
+   
+  }
+  delete gtree;
+  assert(nbv == nv_t);
+
+  // determination des nouveaux tetrahedres
+  int nbt = 0; 
+  hseuil = hmin/10.;
+  hseuil = hseuil/4.;
+  for (int ii=0;ii<Th3.nt;ii++){
+    if(Elem_ok[ii] == 0) continue; 
+    const Tet  &K(Th3.elements[ii]);
+    int iv[4];
+    iv[0]=Numero_Som[Th3.operator()(K[0])];
+    iv[1]=Numero_Som[Th3.operator()(K[1])];
+    iv[2]=Numero_Som[Th3.operator()(K[2])];
+    iv[3]=Numero_Som[Th3.operator()(K[3])];
+    (tt++)->set(v,iv,K.lab);
+ 
+  }
+  assert(nbv == nv_t);
+
+  // determination des nouveaux trianglesxs
+  int nbbe = 0; 
+  hseuil = hmin/10.;
+  hseuil = hseuil/4.;
+  for (int ii=0;ii<Th3.nbe;ii++){
+    if(Border_ok[ii] == 0) continue; 
+    const Triangle3 & K(Th3.be(ii));
+    int iv[3];
+    iv[0]=Numero_Som[Th3.operator()(K[0])]; 
+    iv[1]=Numero_Som[Th3.operator()(K[1])]; 
+    iv[2]=Numero_Som[Th3.operator()(K[2])]; 
+  
+    (bb++)->set(v,iv,K.lab);
+  }
+  assert(nbbe == nbe_t);
+
+  delete [] Numero_Som;
+  delete [] Border_ok;
+  delete [] Elem_ok;
+  
+  Mesh3 *Th3_new = new Mesh3(nv_t,nt_t,nbe_t,v,t,b); 
+  return Th3_new;
+}
+
+
+
+
+
+// TransfoMesh_v2.cpp
+
+
+// LayerMesh.cpp
+
+// remarque choix 2 est a encore a determiner
+double  zmin_func_mesh( const int choix, const double x, const double y  )
+{
+  
+  switch(choix){
+  case 0: 
+    return 0.;
+    break;
+  case 1:
+    return 0.;   
+    break;
+  case 2:
+    return sqrt(pow(x,2)+pow(y,2));
+    break;
+  default :
+    cout << "zmin_func no defined" << endl;
+    return 0.;
+  }
+}
+
+double  zmax_func_mesh( const int choix, const double x, const double y  ){
+  
+  switch(choix){
+  case 0: 
+    return 1.;
+    break;
+  case 1:
+    return 1.;   
+    break;
+  case 2:
+    return 3.+sqrt(pow(x,2)+pow(y,2));
+    break;
+  default :
+    cout << "zmaxfunc no defined" << endl;
+    return 0.;
+  }
+}
+
+int Ni_func_mesh( const int choix, const double x, const double y  ){
+  const int multi=1;
+  int res;
+  switch(choix){
+  case 0:
+    if( x==0. && y==0.){
+      res = 3;
+    }
+    if( x==1. && y==0.){
+      res = 5;
+    }
+    if( x==0. && y==1.){
+      res = 7;
+    }
+    if( x==0.5 && y==0.5){
+      res = 6;
+    }
+    return res ;
+    //return multi;
+    break;
+  case 1:
+    return 2;   
+    break;
+  case 2:
+    return int(multi*(3+sqrt(pow(x,2)+pow(y,2))));
+    break;
+  default :
+    cout << "Ni_func no defined" << endl;
+    return 0;
+  }
+}
+
+void discretisation_max_mesh(const int choix,  const Mesh & Th2, int & Nmax){  
+  int Ni;
+
+  Nmax = 0;  
+
+  /*for(int ii=0; ii < A2D.NbSommet2D;ii++){
+    Ni   = Ni_func( choix, A2D.CoorSommet2D[ii][0], A2D.CoorSommet2D[ii][1]); 
+  	Nmax = max(Ni,Nmax);
+  }
+  Nmax=4;*/
+  for(int ii=0; ii < Th2.nv; ii++){
+     const  Mesh::Vertex & P = Th2.vertices[ii];
+     Ni   = Ni_func_mesh( choix, P.x, P.y); 
+  	 Nmax = max(Ni,Nmax);
+  }
+}
+
+void tab_zmin_zmax_Ni_mesh(const int choix, const Mesh & Th2, int & Nmax,double *tab_zmin, double *tab_zmax,int *tab_Ni){
+   Nmax = 0;	
+   for(int ii=0; ii < Th2.nv; ii++){
+	 const  Mesh::Vertex & P = Th2.vertices[ii];
+     tab_Ni[ii] = Ni_func_mesh( choix, P.x, P.y);
+	 tab_zmin[ii] = zmin_func_mesh( choix, P.x, P.y );
+     tab_zmax[ii] = zmax_func_mesh( choix, P.x, P.y );    
+     Nmax = max(tab_Ni[ii],Nmax);
+   }
+}
+/* Fonction permettant de transformer maillage 2D en maillage 3D*/
+
+void Tet_mesh3_mes_neg(Mesh3 & Th3){
+    int iv[4];
+    int lab;
+    
+    for(int ii=0; ii< Th3.nt; ii++){
+      const Tet & K(Th3.t(ii));
+      lab   = K.lab;
+ 
+      iv[0] = Th3.operator()(K[0]);
+      iv[2] = Th3.operator()(K[1]);
+      iv[1] = Th3.operator()(K[2]);
+      iv[3] = Th3.operator()(K[3]);
+      R3 A(Th3.vertices[iv[0]]);
+      R3 B(Th3.vertices[iv[1]]);
+      R3 C(Th3.vertices[iv[2]]);
+      R3 D(Th3.vertices[iv[3]]);
+      double mes=det(A,B,C,D)/6.;
+      Th3.t(ii).set(Th3.vertices, iv, lab,mes);	
+    }
+}
+
+//=======================================================================//
+//   Rajout pour s'assurer un unique label pour les vertices
+//=======================================================================//
+
+void build_layer_map_tetrahedra(const Mesh &Th2, map<int, int> &maptet ){
+  
+  int numero_label=0;
+  //cout << "in: buil_layer_map_tetrahedra" << endl;
+  for(int ii=0; ii< Th2.nt; ii++){
+    //cout << "ii= " << ii  << "Th2.nt=" << Th2.nt <<endl; 
+    const  Mesh::Triangle & K(Th2.t(ii));
+    map<int,int>::const_iterator imap=maptet.find(K.lab);
+    //cout << "K.lab= " << K.lab << endl; 
+    if(imap == maptet.end()){
+	maptet[ K.lab ] = K.lab; //  modif FH .. numero_label;
+      numero_label = numero_label+1;
+    }
+  }
+  //cout << "number of tetraedra label=" << numero_label << endl;
+}
+void build_layer_map_triangle(const Mesh &Th2, map<int, int> &maptrimil, map<int, int> &maptrizmax, map<int, int> &maptrizmin ){
+  
+  int numero_label=0;
+  //cout << "in: buil_layer_map_triangle" << endl;
+  for(int ii=0; ii< Th2.nt; ii++){
+    const Mesh::Triangle & K(Th2.t(ii));
+    map<int,int>::const_iterator imap=maptrizmax.find(K.lab);
+    
+    if(imap == maptrizmax.end()){
+	maptrizmax[ K.lab ] = K.lab;// modif FH jan 2010  numero_label;
+      numero_label = numero_label+1;
+    }
+  }
+  
+  for(int ii=0; ii< Th2.nt; ii++){
+    const Mesh::Triangle & K(Th2.t(ii));
+    map<int,int>::const_iterator imap=maptrizmin.find(K.lab);
+    
+    if(imap == maptrizmin.end()){
+	maptrizmin[ K.lab ] =  K.lab;// modif FH jan 2010 numero_label;
+      numero_label = numero_label+1;
+    }
+  }
+  
+  for(int ii=0; ii< Th2.neb; ii++){
+    const Mesh::BorderElement & K(Th2.be(ii));
+    map<int,int>::const_iterator imap=maptrimil.find(K.lab);
+    
+    if(imap == maptrimil.end()){
+	maptrimil[ K.lab ] = K.lab  ;//modif FH jan 2010 numero_label;
+      numero_label = numero_label+1;
+    }
+  }
+  
+}
+	
+void build_layer_map_edge(const Mesh &Th2, map<int, int> &mapemil, map<int, int> &mapezmax, map<int, int> &mapezmin ){
+  
+  int numero_label=0;
+		
+  for(int ii=0; ii< Th2.neb; ii++){
+    const Mesh::BorderElement & K(Th2.be(ii));
+    map<int,int>::const_iterator imap1=mapezmax.find(K.lab);
+    map<int,int>::const_iterator imap2=mapemil.find(K.lab);
+    map<int,int>::const_iterator imap3=mapezmin.find(K.lab);
+    
+    if(imap1 == mapezmax.end()){
+	mapezmax[ K.lab ] = K.lab ;//modif FH jan 2010 numero_label;
+      numero_label = numero_label+1;
+    }
+			
+    if(imap2 == mapemil.end()){
+      mapemil[ K.lab ] = K.lab ;//modif FH jan 2010 numero_label;numero_label;
+      numero_label = numero_label+1;
+    }
+    
+    if(imap3 == mapezmin.end()){
+      mapezmin[ K.lab ] = K.lab ;//modif FH jan 2010 numero_label;numero_label;
+      numero_label = numero_label+1;
+    }
+    
+  }
+ 	
+}
+
+	
+Mesh3 * build_layer (const Mesh & Th2, const int Nmax, const int *tab_Ni, 
+		const double *tab_zmin, const double *tab_zmax, 
+		const map<int, int> &maptet, const map<int, int> &maptrimil, const map<int, int> &maptrizmax, const map<int, int> &maptrizmin, 
+		const map<int, int> &mapemil, const map<int, int> &mapezmax, const map<int, int> &mapezmin ){
+
+  int MajSom, MajElem, MajBord2D;     
+  Mesh3 *Th3=new Mesh3;
+  NbSom3D_NbElem3D_NbBord2D_mesh_product_mesh_tab( Nmax, tab_Ni, Th2, MajSom, MajElem, MajBord2D);   
+  if(verbosity > 1) cout << "MajSom = " <<  MajSom  << "  "  << "MajElem = " <<  MajElem  << " " << "MajBord2D =" << MajBord2D << endl;
+  
+  if(verbosity > 1) cout << "debut :   Th3.set(MajSom, MajElem, MajBord2D);     "<< endl;
+  Th3->set(MajSom,MajElem,MajBord2D);
+  
+  if(verbosity > 1) cout << "debut :   Som3D_mesh_product_Version_Sommet_mesh_tab( Nmax, tab_Ni, tab_zmin, tab_zmax, Th2, Th3);   "<< endl;
+  Som3D_mesh_product_Version_Sommet_mesh_tab( Nmax, tab_Ni, tab_zmin, tab_zmax, Th2, 
+			maptet, maptrimil, maptrizmax, maptrizmin, mapemil, mapezmax, mapezmin, *Th3);    
+  
+  
+  //  Add FH because remove in call function.. 
+  
+  Th3->BuildBound();
+  Th3->BuildAdj();
+  Th3->Buildbnormalv();  
+  Th3->BuildjElementConteningVertex();
+  
+    
+  return Th3;
+}
+
+void NbSom3D_NbElem3D_NbBord2D_mesh_product_mesh_tab(const int Nmax, const int *tab_Ni, const Mesh &Th2,  int &MajSom, int &MajElem, int &MajBord2D){  
+  int i;
+  
+  MajSom = 0;  
+  for(int ii=0; ii < Th2.nv;ii++){  
+    MajSom = MajSom + (tab_Ni[ii]+1);        
+  	assert(tab_Ni[ii]<=Nmax);
+  }
+
+  MajElem = 0;  
+  for(int ii=0; ii < Th2.nt; ii++){   
+    const Mesh::Triangle & K(Th2.t(ii));
+    for(int jj=0; jj < 3; jj++){ 
+      //i  = A2D.ElemPoint2D[ii][jj]; 
+      i  = Th2.operator()(K[jj]); 
+      MajElem = MajElem + tab_Ni[i]; 
+    }
+  }
+  
+  // determination of NbBord2D
+  MajBord2D = 2*Th2.nt;  
+ 
+  for(int ii=0; ii < Th2.neb;ii++)
+    {
+      const Mesh::BorderElement  & K(Th2.be(ii));
+      for(int jj=0; jj < 2; jj++)
+	{  
+	  // i  = A2D.ElemBord1D[ii][jj];
+	  i=Th2.operator()(K[jj]); 
+	  
+	  MajBord2D = MajBord2D + tab_Ni[i];
+	  assert( tab_Ni[i] <= Nmax);	
+	}
+    }
+  //exit(1);
+}
+
+void Som3D_mesh_product_Version_Sommet_mesh_tab(const int Nmax, 
+			const int *tab_Ni, const double *tab_zmin, const double *tab_zmax, const Mesh &Th2, 
+			const map<int, int> &maptet, const map<int, int> &maptrimil, const map<int, int> &maptrizmax, const map<int, int> &maptrizmin, 
+			const map<int, int> &mapemil, const map<int, int> &mapezmax, const map<int, int> &mapezmin, 
+			Mesh3 & Th3){
+  // intent(in)  Nmax,Mesh &A2D
+  // intent(out) Mesh3 &A3D
+  
+  double val_zmin,val_zmax,val_dz;
+  int    Ni;
+  int    NumSommet;
+  int    NumElement;
+  KN<int>  tab_NumSommet(Th2.nv+1);
+
+  // variable tet
+  int    SommetPrisme[6];
+ 
+  // variable creer pour le bord
+  int    i_ind1,Ni_ind1;
+  int    i_ind2,Ni_ind2; 
+  int    i_recoll_1pp,i_recoll_2pp; 
+  int    i_recoll_1, i_recoll_2; 
+  //int    pas_recoll_1, pas_recoll_2; 
+  int    type_dec_border; 
+  
+  // avec data
+  int i_recoll_jMax,i_recoll_jMaxpp;
+  int cas_decoupage; //, cas_data; 
+  int int_decoup[3] = {1,2,4};
+  int Ni_elem[3]; 
+  int DiagMax1,DiagMax2;
+
+  // determination of maximum label for vertices 
+  NumSommet = 0;
+
+  for( int ii=0; ii < Th2.nv; ii++){
+    const  Mesh::Vertex & P = Th2.vertices[ii];
+
+    val_zmin = tab_zmin[ii];
+    val_zmax = tab_zmax[ii];    
+    Ni       = tab_Ni[ii];
+
+   
+    //val_dz = (val_zmax - val_zmin)/Ni;
+    if( Ni == 0){
+      val_dz = 0.;
+    }
+    else{
+      val_dz = (val_zmax - val_zmin)/Ni;
+      //if( abs(val_dz) < 1e-9 ) Ni=0; 
+    }
+    
+
+    tab_NumSommet[ii] = NumSommet; // Numero du premier sommet 3D associ� au sommet 2D ii.
+    //cout << "ii, tab_NumSommet[ii]= "<< ii <<" "<< tab_NumSommet[ii] << endl;
+    
+    for(int j=0; j <= Ni; j++){ //changer
+      Th3.vertices[NumSommet].x = P.x; 
+      Th3.vertices[NumSommet].y = P.y; 
+      Th3.vertices[NumSommet].z = val_zmin + val_dz*j;
+
+      Th3.vertices[NumSommet].lab = P.lab; 
+      // cas maillage du bas et du haut, on un nouveau label
+      if(j==0)  Th3.vertices[NumSommet].lab = P.lab ;
+      if(j==Ni) Th3.vertices[NumSommet].lab = P.lab ;      
+      NumSommet = NumSommet+1;
+    }
+  
+  }
+  tab_NumSommet[Th2.nv] = NumSommet;
+
+  assert( NumSommet == Th3.nv );
+  
+  /*********************************/
+  /*  new label for edges of cube  */
+  /*********************************/ 
+  /*
+  cout << " new label for edges of cubes  " << endl;
+  for(int ii=0; ii < Th2.neb; ii++){ 
+	const Mesh::BorderElement & K(Th2.be(ii));
+	int ib[2];
+	ib[0] = Th2.operator()(K[0]);
+    ib[1] = Th2.operator()(K[1]);  
+    //map<int,int>:: const_iterator imap;
+    
+    for(int kk=0; kk<2;kk++){
+	    // label zmin
+	    map<int,int>:: const_iterator imap1;
+	    imap1=mapezmin.find( K.lab );
+
+	    assert( imap1!=mapezmin.end() );
+	    Th3.vertices[ tab_NumSommet[ib[kk]] ].lab = imap1->second;  
+	       
+	    // label zmax
+	    map<int,int>:: const_iterator imap2;
+	    imap2=mapezmax.find( K.lab );
+	    assert( imap2!=mapezmax.end() );
+	       
+	    Th3.vertices[ tab_NumSommet[ ib[kk] ] + tab_Ni[ib[kk]] ].lab = imap2->second; 
+	       
+	       // label c�t�
+	     map<int,int>:: const_iterator imap3;
+	     imap3=mapemil.find ( K.lab );
+	     assert( imap3!=mapemil.end() );
+	       
+	     for(int jj=1; jj < tab_Ni[ib[kk]]; jj++){
+		       Th3.vertices[ tab_NumSommet[ ib[kk] ] + jj ].lab = imap3->second;
+		 }
+		 }
+  }
+  */
+  
+  
+  //=======================================================================
+  // creation des bord du maillage 3D a partir du bord 1D et du maillage 2D
+  //=======================================================================
+
+  if(verbosity > 1) cout << "calcul element du bord " << endl;
+ 
+  // A mettre plus haut
+  int ElemBord;
+
+  ElemBord = 0;
+
+  // bord d�finies en zmax
+  
+  for(int ii=0; ii < Th2.nt; ii++){
+    int ijj[3];
+    const Mesh::Element & K(Th2.t(ii));
+    int lab;
+    map<int,int>::const_iterator imap=maptrizmax.find(K.lab);
+    assert( imap!=maptrizmax.end() );
+    lab=imap->second;
+   
+    for(int kk=0; kk < 3; kk++){
+      ijj[kk] = Th2.operator()(K[kk]);
+      ijj[kk] = tab_NumSommet[ijj[kk]+1]-1;
+    }
+     
+    Th3.be(ElemBord).set(Th3.vertices,ijj,lab);
+    
+    ElemBord = ElemBord+1;
+  }
+
+  //cout << "bord en zmin" << endl;
+ 
+  for(int ii=0; ii < Th2.nt; ii++){
+    int ijj[3];//bjj[3];
+    const Mesh::Element & K(Th2.t(ii));
+    int lab; 
+    map<int,int>::const_iterator imap=maptrizmin.find(K.lab);
+    assert( imap!=maptrizmin.end() );
+    lab = imap->second; 
+    
+  
+    for(int kk=0; kk < 3; kk++){
+      ijj[2-kk] = Th2.operator()(K[kk]);
+      //bjj[2-kk] = ijj[2-kk] ;
+      ijj[2-kk] = tab_NumSommet[ijj[2-kk]];
+    }
+
+    Th3.be(ElemBord).set(Th3.vertices,ijj,lab);
+
+    ElemBord = ElemBord+1;
+  }
+  
+  //cout << "bord sur le cote" << endl;
+
+  for(int ii=0; ii < Th2.neb; ii++){ // Th2.neb ??
+    int ijj[3];
+	
+    const Mesh::BorderElement & K(Th2.be(ii));
+    int lab;
+    
+    map<int,int>::const_iterator imap=maptrimil.find(K.lab);
+    assert( imap!=maptrimil.end() );
+    lab=imap->second;
+
+    int edgebid ;
+    int ffbid   = Th2.BoundaryElement( ii, edgebid );     // ii : number of edge => sortie :: ffbid = numero triangles, edgebid = numero edges
+    int j0bid,j1bid;
+    Th2.VerticesNumberOfEdge( Th2.t(ffbid), edgebid, j0bid, j1bid);
+
+    //bool ffsens = Th2.SensOfEdge( Th2.t(ffbid), edgebid ); // sens du parcours de la edge correcte ou non
+
+    /*
+      if( ffsens == true){
+      i_ind1  = Th2.operator()(K[0]);
+      i_ind2  = Th2.operator()(K[1]);
+      }
+      else{
+      i_ind1  = Th2.operator()(K[1]);
+      i_ind2  = Th2.operator()(K[0]);
+      }
+      
+
+      printf("value of vertex edge (verticesNumberOfEdge) :: %d--%d \n", j0bid, j1bid );
+      printf("value of vertex edge ( Th2.operator() ) :: %d--%d \n",  Th2.operator()(K[0]), Th2.operator()(K[1]) );
+      printf("value of vertex edge ( bool sens  ) :: %d--%d \n",  i_ind1, i_ind2 );
+    */
+    i_ind1 = j0bid;
+    i_ind2 = j1bid;
+
+
+    Ni_ind1 =  tab_Ni[i_ind1]; 
+    Ni_ind2 =  tab_Ni[i_ind2]; 
+	  
+    assert( Ni_ind1 <= Nmax);
+    assert( Ni_ind2 <= Nmax);
+	
+    for(int jNmax=Nmax-1; jNmax >=0; jNmax--){
+	    
+      /*
+      i_recoll_1pp = int((jNmax+1)*Ni_ind1/Nmax);
+      i_recoll_2pp = int((jNmax+1)*Ni_ind2/Nmax); 
+      
+      i_recoll_1 = int(jNmax*Ni_ind1/Nmax);
+      i_recoll_2 = int(jNmax*Ni_ind2/Nmax); 
+      */
+      
+      i_recoll_1 = int((jNmax+1)*Ni_ind1/Nmax);
+      i_recoll_2 = int((jNmax+1)*Ni_ind2/Nmax); 
+      
+      i_recoll_1pp = int(jNmax*Ni_ind1/Nmax);
+      i_recoll_2pp = int(jNmax*Ni_ind2/Nmax);
+      
+//       if( (i_ind1== 11 ||  i_ind1== 0) && (i_ind2==11 || i_ind2==0) ) {
+// 	printf("i_recoll1   %d,    i_recoll2 %d\n", i_recoll_1, i_recoll_2);
+// 	printf("i_recoll1pp %d,  i_recoll2pp %d\n", i_recoll_1pp, i_recoll_2pp);
+//       }
+      /*
+
+	1     ===   2 
+	
+	|           |
+	|           |
+	
+	1pp   ===   2pp   
+	
+	sens 2D : 1pp => 2pp et 1 => 2
+
+	type_dec_border = 0  tous les points sont confondus
+	type_dec_border = 1  les points 1pp et 1 sont differents
+	type_dec_border = 2  les points 2pp et 2 sont differents
+	type_dec_border = 3  les points 1pp et 1 et les points 2pp et 2 sont differents 
+
+	rappel :  1pp(0) 2pp(1) 2(2) 1(3) 
+	data_dec_border 1 :   {3 1 0}
+	data_dec_border 2 :   {2 1 0}
+	data_dec_border 3 : type1 : { {2 1 0}{0 3 2} }
+	                  : type2 : { {3 1 0}{1 3 2} }
+      */
+      type_dec_border = 0; 
+      
+      if( i_recoll_1pp != i_recoll_1){ 
+	type_dec_border = type_dec_border + 1;
+      }
+      
+      if( i_recoll_2pp != i_recoll_2){ 
+	type_dec_border = type_dec_border + 2;
+      }
+
+//   if( (i_ind1== 11 ||  i_ind1== 0) && (i_ind2==11 || i_ind2==0) ) 
+// 	cout << "type decoupage bord= " <<  type_dec_border <<endl;
+           
+      switch( type_dec_border ){
+      case 0:
+	// rien n a faire
+	break;
+      case 1:
+	// 2pp = 2
+	// avant 2,1,0 --> 0,1,2
+	ijj[0] = tab_NumSommet[i_ind1]+i_recoll_1pp;   
+	ijj[1] = tab_NumSommet[i_ind2]+i_recoll_2pp;
+	ijj[2] = tab_NumSommet[i_ind1]+i_recoll_1; 
+	
+	Th3.be(ElemBord).set(Th3.vertices,ijj,lab);
+	
+	ElemBord = ElemBord+1;
+	break;
+      case 2:
+	// 1pp = 1
+	// avant 2,1,0 --> 0,1,2
+	ijj[0] = tab_NumSommet[i_ind1]+i_recoll_1pp;
+	ijj[1] = tab_NumSommet[i_ind2]+i_recoll_2pp;
+	ijj[2] = tab_NumSommet[i_ind2]+i_recoll_2; 
+	
+	Th3.be(ElemBord).set(Th3.vertices,ijj,lab);
+	
+	ElemBord = ElemBord+1;
+	break;
+      case 3:
+	int idl;
+	// determination de la diagonale Max
+	DiagMax1 = max( tab_NumSommet[i_ind1]+i_recoll_1pp, tab_NumSommet[i_ind2]+i_recoll_2 );
+	DiagMax2 = max( tab_NumSommet[i_ind2]+i_recoll_2pp, tab_NumSommet[i_ind1]+i_recoll_1 );	
+
+	
+	if(DiagMax1 > DiagMax2){  
+	  idl = 1; 
+      
+	  ijj[0] = tab_NumSommet[i_ind1]+i_recoll_1pp;
+	  ijj[1] = tab_NumSommet[i_ind2]+i_recoll_2pp;
+	  ijj[2] = tab_NumSommet[i_ind2]+i_recoll_2; 
+	
+	  Th3.be(ElemBord).set(Th3.vertices,ijj,lab);
+
+	  ijj[0] = tab_NumSommet[i_ind2]+i_recoll_2;
+	  ijj[1] = tab_NumSommet[i_ind1]+i_recoll_1;
+	  ijj[2] = tab_NumSommet[i_ind1]+i_recoll_1pp; 
+	
+	  Th3.be(ElemBord+1).set(Th3.vertices,ijj,lab);
+
+	}
+	else{
+	  idl = 2;
+	  
+	  ijj[0] = tab_NumSommet[i_ind1]+i_recoll_1pp;
+	  ijj[1] = tab_NumSommet[i_ind2]+i_recoll_2pp;
+	  ijj[2] = tab_NumSommet[i_ind1]+i_recoll_1; 
+
+	  Th3.be(ElemBord).set(Th3.vertices,ijj,lab);
+	  
+	  ijj[0] = tab_NumSommet[i_ind2]+i_recoll_2;
+	  ijj[1] = tab_NumSommet[i_ind1]+i_recoll_1;
+	  ijj[2] = tab_NumSommet[i_ind2]+i_recoll_2pp; 
+
+	  Th3.be(ElemBord+1).set(Th3.vertices,ijj,lab);
+	}
+	//cout << "idl=" << idl << endl; 
+	ElemBord = ElemBord+2;
+	break;
+      default:
+	break;
+      }     
+    }    
+  }
+  
+  assert( ElemBord == Th3.nbe );
+  //=========================================
+  // Creation + determination tetraedre
+
+  if(verbosity > 1) cout << "calcul element tetraedre " << endl;
+  
+  NumElement =  0;
+
+  for(int ii=0; ii < Th2.nt; ii++){
+      /*  
+	  nouvelle numerotation : 
+	  -----------------------
+	  Valeur de cas_deoupage
+	  -----------------------
+	  1 : sommet 0 et 3 differents
+	  2 : sommet 1 et 4 differents
+	  4 : sommet 2 et 5 differents
+	  ============================
+	  3 : sommet 0 et 3 differents + sommet 1 et 4 differents
+	  5 : sommet 0 et 3 differents + sommet 2 et 5 differents
+	  6 : sommet 1 et 4 differents + sommet 2 et 5 differents
+	  ============================
+	  7 : aucun sommets confondus
+
+	  data_tetraedre 
+	  ==============
+	  1: 0++,1++,2++,SomDiff :  {0 1 2 3}        :: data 1
+	  2: 0++,1++,2++,SomDiff :  {0 1 2 4}        :: data 2
+	  4: 0++,1++,2++,SomDiff :  {0 1 2 5}        :: data 3
+	  ==============
+	  = deux cas possible depend du sommet le plus grand : Sommet le plus grand est un ++
+	  = 0++,1++,2++,SomDiffMin  ||  SomDiffMax++, j_SomDiff_py[j_SomEgal][0], j_SomDiff_py[j_SomEgal][1], Som_Egal 
+	  3:a: SommetMax diag 04  {0,1,2,4} {5,4,3,0} :: data 4
+	  3:b: SommetMax diag 13  {0,1,2,3} {5,4,3,1} :: data 5
+	  =============================================
+	  5:a: SommetMax diag 05  {0,1,2,5} {5,4,3,0} :: data 6
+	  5:b: SommetMax diag 23  {0,1,2,3} {5,4,3,2} :: data 7
+	  =============================================
+	  6:a: SommetMax diag 15  {0,1,2,5} {5,4,3,1} :: data 8
+	  6:b: SommetMax diag 24  {0,1,2,4} {5,4,3,2} :: data 9
+	  =============================================
+	  7: aller chercher dans la fonction          :: data 10 a data 
+	  == voir hecht routine
+
+      */
+      const Mesh::Element & K(Th2.t(ii));
+      int somv[4];
+      int K_jj[3];
+      int lab;
+      
+      map<int,int>::const_iterator imap=maptet.find(K.lab); 
+      assert( imap != maptet.end() );
+      lab=imap->second;
+     
+      // valeur de Nombre de points
+      for(int jj=0; jj <3; jj++){
+        K_jj[jj] = Th2.operator()(K[jj]);   
+        Ni_elem[jj] = tab_Ni[ K_jj[jj] ];    
+      }
+     
+      for(int jNmax=Nmax-1; jNmax >=0; jNmax--){
+	// determination des sommets + cas decoupage
+	cas_decoupage = 0;
+	for(int jj=0; jj<3; jj++){
+	  
+	  i_recoll_jMax   = int( (jNmax)*Ni_elem[jj]/Nmax );
+	  i_recoll_jMaxpp = int( (jNmax+1)*Ni_elem[jj]/Nmax );
+	  
+	  SommetPrisme[jj+3] = tab_NumSommet[ K_jj[jj] ] + i_recoll_jMaxpp;
+	  SommetPrisme[jj] = tab_NumSommet[ K_jj[jj] ] + i_recoll_jMax;
+	  
+	  assert( SommetPrisme[jj]   <= Th3.nv);
+	  assert( SommetPrisme[jj+3] <= Th3.nv);
+	  if( i_recoll_jMax != i_recoll_jMaxpp) cas_decoupage = cas_decoupage + int_decoup[jj];
+	}
+	
+	//cout << "cas du decoupage= " << cas_decoupage << endl;
+	
+	switch( cas_decoupage ){
+	  
+	case 0 : 
+	// les points sont tous confondus pas d ajout element : rien a faire
+	  break;
+	  /*
+	    CAS CREATION D UN TETRAEDRE : cas decoupage 1 2 4
+	    
+	  */
+	case 1 :
+	  // On a un tetraedre
+	
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1]; 
+	  somv[2] = SommetPrisme[2]; 
+	  somv[3] = SommetPrisme[3];
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	
+	  
+	  NumElement = NumElement+1;
+	  break;
+	case 2 :
+	  // On a un tetraedre
+	  
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1]; 
+	  somv[2] = SommetPrisme[2]; 
+	  somv[3] = SommetPrisme[4];
+
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	
+	  
+	  NumElement = NumElement+1;
+	  break;
+	case 4 :
+	  // On a un tetraedre
+	  
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1]; 
+	  somv[2] = SommetPrisme[2]; 
+	  somv[3] = SommetPrisme[5];
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	
+	
+	  NumElement = NumElement+1;
+	  break;
+	/*
+	  On a une pyramide a base rectangle: decoupe deux tetraedres
+	  cas decoupage 3 5 6
+	*/
+      case 3 :
+	// determination de la diagonale dominante
+	DiagMax1 = max( SommetPrisme[0], SommetPrisme[4] );
+	DiagMax2 = max( SommetPrisme[1], SommetPrisme[3] );
+	
+	//cout << "DiagMax1=" << DiagMax1 << " "<< SommetPrisme[0]<<" " <<SommetPrisme[4] << endl;
+
+	if( DiagMax1 > DiagMax2){
+	  //------------------
+	  // premier tetraedre 
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1];	
+	  somv[2] = SommetPrisme[2];
+	  somv[3] = SommetPrisme[4]; 
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	
+	  // deuxieme tetraedre
+	  somv[0] = SommetPrisme[5];
+	  somv[1] = SommetPrisme[4];	
+	  somv[2] = SommetPrisme[3];
+	  somv[3] = SommetPrisme[0]; 
+	  
+	  Th3.elements[NumElement+1].set(Th3.vertices, somv, lab);	
+	}			  
+	else{
+	  //------------------
+	  // premier tetraedre 
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1];	
+	  somv[2] = SommetPrisme[2];
+	  somv[3] = SommetPrisme[3];
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	 
+	  // deuxieme tetraedre
+	  somv[0] = SommetPrisme[5];
+	  somv[1] = SommetPrisme[4];	
+	  somv[2] = SommetPrisme[3];
+	  somv[3] = SommetPrisme[1]; 
+	  
+	  Th3.elements[NumElement+1].set(Th3.vertices, somv, lab);	
+	}
+      
+	NumElement = NumElement+2;
+	break;
+
+      case 5 :
+	// determination de la diagonale dominante
+	DiagMax1 = max( SommetPrisme[0], SommetPrisme[5] );
+	DiagMax2 = max( SommetPrisme[2], SommetPrisme[3] );
+	
+	//cout << "DiagMax1=" << DiagMax1 << " "<< SommetPrisme[0]<<" " <<SommetPrisme[5] << endl;
+
+	if( DiagMax1 > DiagMax2){
+	  //------------------
+	  // premier tetraedre 
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1];	
+	  somv[2] = SommetPrisme[2];
+	  somv[3] = SommetPrisme[5];
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	 
+	  // deuxieme tetraedre
+	  somv[0] = SommetPrisme[5];
+	  somv[1] = SommetPrisme[4];	
+	  somv[2] = SommetPrisme[3];
+	  somv[3] = SommetPrisme[0]; 
+	  
+	  Th3.elements[NumElement+1].set(Th3.vertices, somv, lab);	
+	}			  
+	else{
+	  //------------------
+	  // premier tetraedre 
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1];	
+	  somv[2] = SommetPrisme[2];
+	  somv[3] = SommetPrisme[3];
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	 
+	  // deuxieme tetraedre
+	  somv[0] = SommetPrisme[5];
+	  somv[1] = SommetPrisme[4];	
+	  somv[2] = SommetPrisme[3];
+	  somv[3] = SommetPrisme[2]; 
+	  
+	  Th3.elements[NumElement+1].set(Th3.vertices, somv, lab);	
+	}
+      
+	NumElement = NumElement+2;
+	break;
+
+      case 6 :
+	// determination de la diagonale dominante
+	DiagMax1 = max( SommetPrisme[1], SommetPrisme[5] );
+	DiagMax2 = max( SommetPrisme[2], SommetPrisme[4] );
+
+	//cout << "DiagMax1=" << DiagMax1 << " "<< SommetPrisme[1]<<" " <<SommetPrisme[5] << endl;
+	
+	if( DiagMax1 > DiagMax2){
+	  //------------------
+	  // premier tetraedre 
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1];	
+	  somv[2] = SommetPrisme[2];
+	  somv[3] = SommetPrisme[5];
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	 
+	  // deuxieme tetraedre
+	  somv[0] = SommetPrisme[5];
+	  somv[1] = SommetPrisme[4];	
+	  somv[2] = SommetPrisme[3];
+	  somv[3] = SommetPrisme[1]; 
+	  
+	  Th3.elements[NumElement+1].set(Th3.vertices, somv, lab);	
+	}			  
+	else{
+	  //------------------
+	  // premier tetraedre 
+	  somv[0] = SommetPrisme[0];
+	  somv[1] = SommetPrisme[1];	
+	  somv[2] = SommetPrisme[2];
+	  somv[3] = SommetPrisme[4];
+	  
+	  Th3.elements[NumElement].set(Th3.vertices, somv, lab);	 
+	  // deuxieme tetraedre
+	  somv[0] = SommetPrisme[5];
+	  somv[1] = SommetPrisme[4];	
+	  somv[2] = SommetPrisme[3];
+	  somv[3] = SommetPrisme[2]; 
+	  
+	  Th3.elements[NumElement+1].set(Th3.vertices, somv, lab);	
+	}
+      
+	NumElement = NumElement+2;
+	break;
+
+      case 7 :
+	// on a un prisme 
+	int nbe;
+	int option=1;
+	int idl[3];
+	int nu[12];
+	
+	DiagMax1 = max( SommetPrisme[0], SommetPrisme[5] );
+	DiagMax2 = max( SommetPrisme[2], SommetPrisme[3] );	
+	
+	// determination de idl
+	// idl[0] : choix sommet 0 ou 2 (dpent1 equivalent 1 ou 3)
+	
+	if(DiagMax1 > DiagMax2){  
+	  idl[0]=1;
+	}
+	else{
+	  idl[0]=2;
+	}
+    
+	DiagMax1 = max( SommetPrisme[0], SommetPrisme[4] );
+	DiagMax2 = max( SommetPrisme[1], SommetPrisme[3] );	
+	
+	// idl[1] : choix sommet 0 ou 1 (dpent1 equivalent 1 ou 2)	
+    if(DiagMax1 > DiagMax2){
+	  idl[1]=1;
+	}
+	else{
+	  idl[1]=2;
+	}
+	
+	DiagMax1 = max( SommetPrisme[1], SommetPrisme[5] );
+	DiagMax2 = max( SommetPrisme[2], SommetPrisme[4] );	
+	
+	// idl[2] : choix sommet 1 ou 2 (dpent1 equivalent 2 ou 3)	
+	if(DiagMax1 > DiagMax2){
+	  idl[2]=1;
+	}
+	else{
+	  idl[2]=2;
+	}
+	//cout << "idl[0] << << idl[1] << << idl[2]" << endl;
+	//cout << idl[0] << " " << idl[1] << "  "<< idl[2] << endl;
+	
+	nbe = 0;
+
+	dpent1_mesh( idl, nu, nbe, option);
+      
+	if(nbe!=3){cout << nbe << endl; cerr << "probleme dans dpent1_mesh" << endl;  };
+	
+	//------------------
+	// premier tetraedre 
+	somv[0] = SommetPrisme[nu[0]];
+	somv[1] = SommetPrisme[nu[1]];	
+	somv[2] = SommetPrisme[nu[2]];	
+	somv[3] = SommetPrisme[nu[3]];
+	
+	Th3.elements[NumElement].set(Th3.vertices, somv, lab);		
+	// deuxieme tetraedre
+	somv[0] = SommetPrisme[nu[4]]; 
+	somv[1] = SommetPrisme[nu[5]]; 
+	somv[2] = SommetPrisme[nu[6]]; 
+	somv[3] = SommetPrisme[nu[7]];
+	
+	Th3.elements[NumElement+1].set(Th3.vertices, somv, lab);	 	
+	// troisieme tetraedre
+	somv[0] = SommetPrisme[nu[8]]; 
+	somv[1] = SommetPrisme[nu[9]]; 
+	somv[2] = SommetPrisme[nu[10]]; 
+	somv[3] = SommetPrisme[nu[11]]; 
+	
+	Th3.elements[NumElement+2].set(Th3.vertices, somv, lab);	
+	
+	NumElement = NumElement+3;
+	break;
+      }
+      
+   }
+  // Au final : les sommers des tetraedres et la conectivit� des tetraedres finaux
+  assert(NumElement <= Th3.nt);
+  }
+
+}
+
+void dpent1_mesh(int idl[3],int nu[12],int &nbe,int &option){
+  // intent(inout)  :: idl
+  // intent(out)    :: nu,nbe,option
+  // option ne sert � rien
+  //* version simplifie pour le mailleur par couche 2D 3D
+  //-----------------------------------------------------------------------
+  //      subroutine dpent1 (idl,nu,nbe,option)
+  //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  //                s.p. dpent1
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  //  but : decoupe un pentaedre en 3 tetreadres suivant la decoupe des 3
+  // ---   faces frontieres a 4 cotes
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  //  parametres en entre :
+  //   idl : parametre de decoupe de face calculer comme ceci :
+  //       si idl(i) = 0 alors la face n'est pas  decoupee
+  //       idl(1)= 1 si la face 1463 est decoupe par l'arete 16 ,sinon 2
+  //       idl(2)= 1 si la face 1254 est decoupe par l'arete 15 ,sinon 2
+  //       idl(3)= 1 si la face 2365 est decoupe par l'arete 26 ,sinon 2
+  //          id = i1 + i2 * 2 + i3 * 4
+  //  parametres en sortie :
+  //   nbe : nbe de tetraedre de la decoupe
+  //         nbe = 0 => decoup impossible
+  //         nbe = 3 => decoup possible le tableau nu est genere
+  //   nu(1:4,1:nbe) : tableau de numero des sommet 3 tetraedres dans le
+  //                   pentaedre
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  //  programmation : f77 ->c++ subroutine de f. hecht upmc 
+
+  int idp[8];
+  int i1,i2,i3,i,nbdp,idf,idecou;
+  const int pdd[8] = {1,0,2,3,4,5,0,6};
+
+  int mu[6][12];
+  const int mu0[12] = {1,6,2,3, 1,5,2,6, 1,6,4,5};
+  const int mu1[12] = {1,6,2,3, 1,4,2,6, 2,6,4,5};
+  const int mu2[12] = {1,4,2,3, 2,6,3,4, 2,6,4,5};
+  const int mu3[12] = {1,5,2,3, 1,5,3,6, 1,6,4,5};
+  const int mu4[12] = {1,5,2,3, 1,5,3,4, 3,6,4,5};
+  const int mu5[12] = {1,4,2,3, 2,5,3,4, 3,6,4,5};
+
+  for(int jj=0; jj<12; jj++){
+    mu[0][jj] = mu0[jj];
+    mu[1][jj] = mu1[jj];
+    mu[2][jj] = mu2[jj];
+    mu[3][jj] = mu3[jj];
+    mu[4][jj] = mu4[jj];
+    mu[5][jj] = mu5[jj];
+  }
+
+  // calcul des descoupes possible du pentaedre
+  idf  = -1;
+  nbdp =  0;
+
+  for(i3=1; i3<=2; i3++){
+    for(i2=1; i2<=2; i2++){
+      for(i1=1; i1<=2; i1++){
+	idf=idf+1;
+	if( (pdd[idf] != 0) 
+	    && (  idl[0]==0  || idl[0]==i1 )
+	    && (  idl[1]==0  || idl[1]==i2 )
+	    && (  idl[2]==0  || idl[2]==i3 ) ){
+	  //nbdp=nbdp+1;
+	  idp[nbdp]=idf;
+	  nbdp=nbdp+1;
+	}
+      }
+    }
+  }
+  
+  if(nbdp == 0){
+    nbe=0;
+  }
+  else{
+    nbe=3;
+    idf=idp[0];
+    idecou=pdd[idf];
+   /* i=idf;  
+    j=i/4;
+    i=i-4*j;
+    idl[2]=j+1;
+    j=i/2;
+    idl[1]=j+1;
+    idl[0]=i-2*j+1;
+    //cout << "idecou= " << idecou << endl;*/
+    for(i=0; i<12;i++){
+      nu[i]=mu[idecou-1][i]-1;
+      //cout << "i, nu[i] "<< i <<" " << nu[i] << endl;
+    }
+  }
+
+  }
+//----------------------------------------------------------------------- 
+
+
+
+
+
+
+// glumesh3D
+
+class listMesh3 { 
+public:
+  list<Mesh3 *> *lth;
+  void init()  { lth=new list<Mesh3 *>;}
+  void destroy() { delete lth;}
+  listMesh3(Stack s,Mesh3 *th) : lth(Add2StackOfPtr2Free(s,new list<Mesh3*>)) { lth->push_back(th);}
+  listMesh3(Stack s,Mesh3 *tha,Mesh3 *thb) : lth(Add2StackOfPtr2Free(s,new list<Mesh3*>)) { lth->push_back(tha);lth->push_back(thb);}
+  listMesh3(Stack s,const listMesh3 &l,Mesh3 *th) : lth(Add2StackOfPtr2Free(s,new list<Mesh3*>(*l.lth))) { lth->push_back(th);}
+
+};
+
+Mesh3 * GluMesh3(listMesh3 const & lst)
+{ 
+  int flagsurfaceall = 0;
+
+  int nbt=0;
+  int nbe=0;
+  int nbex=0;
+  int nbv=0;
+  int nbvx=0;
+  
+  double hmin=1e100;
+  R3 Pn(1e100,1e100,1e100),Px(-1e100,-1e100,-1e100);
+  const list<Mesh3 *> lth(*lst.lth);
+  Mesh3 * th0=0;
+  int kk=0; 
+  for(list<Mesh3 *>::const_iterator i=lth.begin();i != lth.end();i++)
+    {
+      if( ! *i) continue ;
+      kk++;
+      Mesh3 &Th3(**i);  // definis ???
+      th0=&Th3;
+      if(verbosity>1)  cout << " determination of hmin : GluMesh3D + "<< Th3.nv << " " << Th3.nt << " "<< Th3.nbe << endl;
+      
+      nbt  += Th3.nt;
+      nbvx += Th3.nv;
+      nbex += Th3.nbe;
+      
+      for (int k=0;k<Th3.nt;k++){
+	for (int e=0;e<6;e++){
+	  hmin=min(hmin,Th3[k].lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+	}
+      }
+      
+      for (int k=0;k<Th3.nbe;k++){
+	for (int e=0;e<3;e++){
+	  hmin=min(hmin,Th3.be(k).lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+	}
+      }
+      
+      for (int ii=0;ii<Th3.nv;ii++){ 
+	R3 P( Th3.vertices[ii].x, Th3.vertices[ii].y, Th3.vertices[ii].z);
+	Pn=Minc(P,Pn);
+	Px=Maxc(P,Px);     
+      }
+    } 
+  if(kk==0) return 0; // no mesh ....
+
+  if(verbosity > 1) cout << "      - hmin =" <<  hmin << " ,  Bounding Box: " << Pn << " "<< Px << endl;
+  
+  // probleme memoire
+  Vertex3  *v= new Vertex3[nbvx];
+  Tet      *t;
+  if(nbt!=0) t= new Tet[nbt];
+  Tet      *tt=t;
+  Triangle3 *b= new Triangle3[nbex];
+  Triangle3 *bb= b;
+  
+  ffassert(hmin>Norme2(Pn-Px)/1e9);
+  double hseuil =hmin/10.; 
+
+  //int *NumSom= new int[nbvx];
+
+  // VERSION morice
+  if(verbosity > 1) cout << " creation of : BuildGTree" << endl;   
+  EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(v,Pn,Px,0);  
+  
+  nbv=0;
+  //int nbv0=0;
+  for(list<Mesh3 *>::const_iterator i=lth.begin(); i!=lth.end();i++)
+    {
+      if( ! *i) continue ;
+      const Mesh3 &Th3(**i);
+      if(verbosity>1)  cout << " loop over mesh for create new mesh "<< endl;
+      if(verbosity>1)  cout << " GluMesh3D + "<< Th3.nv << " " << Th3.nt <<" " << Th3.nbe << endl;
+      //nbv0 =+Th3.nv;
+      
+      for (int ii=0;ii<Th3.nv;ii++){
+	const Vertex3 &vi(Th3.vertices[ii]);
+	Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+
+	   
+	if(!pvi){
+	  v[nbv].x = vi.x;
+	  v[nbv].y = vi.y;
+	  v[nbv].z = vi.z;
+	  v[nbv].lab = vi.lab;
+	  //NumSom[ii+nbv0] = nbv;
+	  gtree->Add( v[nbv] );
+	  nbv++;
+	}
+	/*
+	  else{
+	  NumSom[ii+nbv0] = pvi-v;
+	  assert(pvi-v <nbv); 
+	  }
+	*/
+      }
+	  
+      for (int k=0;k<Th3.nt;k++){
+	const Tet  &K(Th3.elements[k]);
+	int iv[4];
+	iv[0]=gtree->ToClose(K[0],hseuil)-v;
+	iv[1]=gtree->ToClose(K[1],hseuil)-v;
+	iv[2]=gtree->ToClose(K[2],hseuil)-v;  
+	iv[3]=gtree->ToClose(K[3],hseuil)-v;  
+	(tt++)->set(v,iv,K.lab);
+      }
+      //nbv0 =+Th3.nv;
+    }
+  
+  if(verbosity > 1) cout << " creation of : BuildGTree for border elements" << endl;
+  Vertex3  *becog= new Vertex3[nbex];  
+  //Vertex3  becog[nbex]; 
+  EF23::GTree<Vertex3> *gtree_be = new EF23::GTree<Vertex3>(becog,Pn,Px,0);
+  
+  double hseuil_border = hseuil/3.;
+  //nbv0=0;
+  for(list<Mesh3 *>::const_iterator i=lth.begin();i != lth.end();i++)
+    {
+      if( ! *i) continue ;
+      const Mesh3 &Th3(**i);
+      
+    for (int k=0;k<Th3.nbe;k++)
+      {
+	const Triangle3 & K(Th3.be(k));
+	int iv[3];
+	iv[0]=Th3.operator()(K[0]); 
+	iv[1]=Th3.operator()(K[1]); 
+	iv[2]=Th3.operator()(K[2]); 
+
+	R cdgx,cdgy,cdgz;
+	  
+	cdgx = (Th3.vertices[iv[0]].x+ Th3.vertices[iv[1]].x+ Th3.vertices[iv[2]].x)/3.;
+	cdgy = (Th3.vertices[iv[0]].y+ Th3.vertices[iv[1]].y+ Th3.vertices[iv[2]].y)/3.;
+	cdgz = (Th3.vertices[iv[0]].z+ Th3.vertices[iv[1]].z+ Th3.vertices[iv[2]].z)/3.;
+	 
+	const R3 r3vi( cdgx, cdgy, cdgz ); 
+	const Vertex3 &vi( r3vi);
+	    
+	Vertex3 * pvi=gtree_be->ToClose(vi,hseuil_border);
+	if(!pvi){
+	  becog[nbe].x = vi.x;
+	  becog[nbe].y = vi.y;
+	  becog[nbe].z = vi.z;
+	  becog[nbe].lab = vi.lab;
+	  gtree_be->Add( becog[nbe++]);
+		  
+	  int igluv[3];
+	  igluv[0]= gtree->ToClose(K[0],hseuil)-v; //NumSom[iv[0]+nbv0];  
+	  igluv[1]= gtree->ToClose(K[1],hseuil)-v; //NumSom[iv[1]+nbv0]; 
+	  igluv[2]= gtree->ToClose(K[2],hseuil)-v; //NumSom[iv[2]+nbv0]; 
+	 
+	  (bb++)->set(v,igluv,K.lab);
+	}
+      }
+    //nbv0 =+Th3.nv;
+  }
+  delete gtree;
+  delete gtree_be;
+  delete [] becog;
+  
+  if(verbosity > 2) cout << " nbv="  << nbv  << endl;
+  if(verbosity > 2) cout << " nbvx=" << nbvx << endl;
+  if(verbosity > 2) cout << " nbt="  << nbt  << endl;
+  if(verbosity > 2) cout << " nbe="  << nbe  << endl;
+  if(verbosity > 2) cout << " nbex=" << nbex << endl;
+  if(verbosity>1)
+    {
+      cout << "     Nb of glu3D  point " << nbvx-nbv;
+      cout << "     Nb of glu3D  Boundary faces " << nbex-nbe << endl;
+    }
+
+  if(nbt==0){
+    Mesh3 *mpq= new Mesh3(nbv,nbe,v,b);  
+    if(flagsurfaceall==1) mpq->BuildBoundaryElementAdj();
+    return mpq;
+  }
+  else{
+    Mesh3 *mpq= new Mesh3(nbv,nbt,nbe,v,t,b);  
+ /* 
+    mpq->BuildBound();
+    if(verbosity > 1) cout << "fin de BuildBound" << endl;
+    mpq->BuildAdj();
+    if(verbosity > 1) cout << "fin de BuildAdj" << endl;
+    mpq->Buildbnormalv();  
+    if(verbosity > 1) cout << "fin de Buildnormalv()" << endl;
+    mpq->BuildjElementConteningVertex();
+    if(verbosity > 1) cout << "fin de ConteningVertex()" << endl;
+  */
+    mpq->BuildGTree();
+    if(verbosity > 2) cout << "fin de BuildGTree()" << endl;
+    
+    //Add2StackOfPtr2FreeRC(stack,mpq);
+  
+    return mpq;
+  }
+}
+
+
+template<class RR,class AA=RR,class BB=AA> 
+struct Op3_addmesh: public binary_function<AA,BB,RR> { 
+  static RR f(Stack s,const AA & a,const BB & b)  
+  { return RR(s, a, b );} 
+};
+
+template<bool INIT,class RR,class AA=RR,class BB=AA> 
+struct Op3_setmesh: public binary_function<AA,BB,RR> { 
+  static RR f(Stack stack,const AA & a,const BB & b)  
+  {
+    ffassert(a );
+    pmesh3  p=GluMesh3(b);
+    
+    if(!INIT && *a){
+      //Add2StackOfPtr2FreeRC(stack,*a);
+       (**a).destroy();
+      cout << "destruction du pointeur" << endl;
+    }
+    //Add2StackOfPtr2FreeRC(stack,p); //  the pointer is use to set variable so no remove. 
+    *a=p;
+    return a;
+  } 
+};
+
+// Movemesh3D
+
+class Movemesh3D_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  Expression xx,yy,zz;
+  //Expression  lab,reg;  
+  static const int n_name_param =7+2; // add FH for cleanning name  //  "+1" add to reorient tetrahedrons
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,int ii,Stack stack,KN_<long> a ) const
+    {  ffassert( ! (nargs[i] && nargs[ii]) ); i= nargs[i] ? i : ii;
+	return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+public:
+/*  Movemesh3D_Op(const basicAC_F0 &  args,Expression tth)
+    : eTh(tth), xx(0) , yy(0) , zz(0)
+  {
+    args.SetNameParam(n_name_param,name_param,nargs);
+    const E_Array * a1=0 ;
+    if(nargs[0])  a1  = dynamic_cast<const E_Array *>(nargs[0]);
+    int err =0;
+    if( nargs[1] && nargs[7] ) 
+	CompileError("uncompatible movemesh3 (Th, region= , reftet=  ");
+    if( nargs[2] && nargs[8] ) 
+	CompileError("uncompatible movemesh3 (Th, label= , refface=  ");
+
+    if(a1) {
+      if(a1->size() !=3) 
+	CompileError("movemesh3 (Th,transfo=[X,Y,Z],) ");
+      xx=to<double>( (*a1)[0]); 
+      yy=to<double>( (*a1)[1]);
+      zz=to<double>( (*a1)[2]);
+    }    
+  }*/
+    Movemesh3D_Op(const basicAC_F0 &  args,Expression tth,Expression xxx=0,Expression yyy=0,Expression zzz=0  )
+    : eTh(tth), xx(xxx) , yy(yyy) , zz(zzz)
+    {
+        args.SetNameParam(n_name_param,name_param,nargs);
+        const E_Array * a1=0 ;
+        if(nargs[0])  a1  = dynamic_cast<const E_Array *>(nargs[0]);
+        int err =0;
+        if( nargs[1] && nargs[7] )
+            CompileError("uncompatible movemesh3 (Th, region= , reftet=  ");
+        if( nargs[2] && nargs[8] )
+            CompileError("uncompatible movemesh3 (Th, label= , refface=  ");
+        
+        if(a1) {
+            if(a1->size() !=3 ||  xx || yy || zz)
+                CompileError("movemesh3 (Th,transfo=[X,Y,Z],) ");
+            xx=to<double>( (*a1)[0]);
+            yy=to<double>( (*a1)[1]);
+            zz=to<double>( (*a1)[2]);
+        }    
+    } 
+    
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type Movemesh3D_Op::name_param[]= {
+  {  "transfo", &typeid(E_Array)}, //0
+  {  "reftet", &typeid(KN_<long>)},// 1
+  {  "refface", &typeid(KN_<long>)},
+  {  "ptmerge", &typeid(double)},
+  {  "facemerge",&typeid(long)},
+  {  "boolsurface",&typeid(long)}, // 5
+  {  "orientation",&typeid(long)},
+  {  "region", &typeid(KN_<long> )}, //7 
+  {  "label", &typeid(KN_<long> )} // 8
+  // option a rajouter
+  // facemerge 0,1 + label
+};
+
+AnyType Movemesh3D_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  
+  ffassert(pTh);
+  Mesh3 &Th=*pTh;
+  Mesh3 *m= pTh;   // question a quoi sert *m ??
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int nbe=Th.nbe; // nombre d'aretes fontiere
+  if(verbosity>5)  cout << "before movemesh: Vertex " << nbv<< " Tetrahedra " << nbt << " triangles "<< nbe << endl; 
+ 
+ // lecture des references
+   
+  KN<long> zzempty;
+  KN<long> nrtet  (arg(1,7,stack,zzempty));  
+  KN<long> nrf (arg(2,8,stack,zzempty)); 
+  double precis_mesh( arg(3,stack,1e-7));
+  long  mergefacemesh( arg(4,stack,1L) );
+  long  flagsurfaceall( arg(5,stack,0L) );
+    long orientationelement( arg(6,stack,1L) );
+
+
+  //if( nrtet.N() && nrfmid.N() && nrfup.N() && nrfdown.N() ) return m;
+  ffassert( nrtet.N() %2 ==0);
+  ffassert( nrf.N() %2 ==0);
+  
+  map<int,int> mapface;
+  for(int i=0;i<nrf.N();i+=2)
+    {
+      if( nrf[i] != nrf[i+1] ){	
+	mapface[nrf[i]] = nrf[i+1];
+      }      
+    }
+  
+  map<int,int> maptet;
+  for(int i=0;i<nrtet.N();i+=2)
+    {
+      if( nrtet[i] != nrtet[i+1] ){	
+	maptet[nrtet[i]] = nrtet[i+1];
+      }      
+    }
+
+
+
+  // realisation de la map par default
+  
+  assert((xx) && (yy) && (zz) );
+  
+  KN<double> txx(Th.nv), tyy(Th.nv), tzz(Th.nv);
+  
+  Mesh3 &rTh3 = Th;
+ 
+  KN<int> takemesh(Th.nv);
+  MeshPoint *mp3(MeshPointStack(stack)); 
+  
+  takemesh=0;
+  // loop over tetrahedral 
+  for (int it=0;it<Th.nt;++it){
+    for( int iv=0; iv<4; ++iv){
+      int i=Th(it,iv);  
+      
+      if(takemesh[i]==0){
+	mp3->setP(&Th,it,iv);
+          if(xx){ txx[i]=GetAny<double>((*xx)(stack));} else txx[i]=mp3->P.x;
+	if(yy){ tyy[i]=GetAny<double>((*yy)(stack));}else tyy[i]=mp3->P.y;
+	if(zz){ tzz[i]=GetAny<double>((*zz)(stack));}else tzz[i]=mp3->P.z;
+	takemesh[i] = takemesh[i]+1;
+      }
+    }
+  }
+
+  // loop over border elements
+   // loop over tetrahedral 
+  for (int it=0;it<Th.nbe;++it){
+    const Triangle3 &K(Th.be(it));
+    int iv[3];
+    iv[0]=Th.operator()(K[0]); 
+    iv[1]=Th.operator()(K[1]);
+    iv[2]=Th.operator()(K[2]);
+    
+    R coordx,coordy,coordz;
+    for(int jj=0; jj< 3; jj++){
+      int i=iv[jj];
+      if(takemesh[i]==0){	 
+	mp3->set( Th.vertices[i].x, Th.vertices[i].y, Th.vertices[i].z );
+	if(xx){ txx[i]=GetAny<double>((*xx)(stack));}
+	if(yy){ tyy[i]=GetAny<double>((*yy)(stack));}
+	if(zz){ tzz[i]=GetAny<double>((*zz)(stack));}
+	takemesh[i] = takemesh[i]+1;
+      }
+    }
+  }
+  
+  // option (Transfo_Mesh3) :: 
+  
+  // border_only = 0, recollement_border=1, point_confondus_ok=0;   == > 1900 triangles
+  // border_only = 0, recollement_border=0, point_confondus_ok=0;   == > 1980 triangles
+  // border_only = 0, recollement_border=1, point_confondus_ok=1;   == > 1820 triangles
+
+  // border_only = 1, recollement_border=1, point_confondus_ok=0;   == > 1900 triangles
+  // border_only = 1, recollement_border=0, point_confondus_ok=0;   == > 1980 triangles
+  // border_only = 1, recollement_border=1, point_confondus_ok=1;   == > 1820 triangles
+
+
+  int border_only=0; // ne sert a rien !!!!! A enlever
+  int recollement_elem=0;
+  int recollement_border, point_confondus_ok;
+  
+  if(mergefacemesh == 0)
+    {
+      recollement_border=0;
+      point_confondus_ok=0;
+    }
+  if(mergefacemesh == 1)
+    { 
+      recollement_border=1;
+      point_confondus_ok=0;
+    }
+  if(mergefacemesh == 2)
+    { 
+      recollement_border=1;
+      point_confondus_ok=1;
+    }
+  
+  Mesh3 *T_Th3=Transfo_Mesh3( precis_mesh,rTh3, txx, tyy, tzz, border_only, 
+			      recollement_elem, recollement_border, point_confondus_ok,orientationelement);
+  
+  if( nrtet.N() >0)
+   {
+    for (int i=0;i<nbt;i++)
+      {
+	const Tet &K( T_Th3->elements[i] );	
+	int lab=K.lab;
+	T_Th3->elements[i].lab = ChangeLab3D(maptet,lab);
+      }  
+  }
+  // les arete frontieres qui n'ont pas change
+    
+  if( nrf.N()>0)
+    {
+    for (int i=0;i<nbe;i++)
+      { 
+	const Triangle3 &K( T_Th3->be(i) );
+	int l0,l1=ChangeLab3D(mapface,l0=K.lab) ;
+	T_Th3->be(i).lab = l1;
+      }
+   }
+  
+
+   if(flagsurfaceall==1) T_Th3->BuildBoundaryElementAdj();
+
+   T_Th3->BuildGTree();
+   Add2StackOfPtr2FreeRC(stack,T_Th3);
+ 
+  *mp=mps;
+  return T_Th3;
+}
+
+class  Movemesh3D : public OneOperator { public:
+    int cas;
+    Movemesh3D() : OneOperator(atype<pmesh3>(),atype<pmesh3>()), cas(0) {}
+    Movemesh3D(int ) : OneOperator(atype<pmesh3>(),atype<pmesh3>(),atype<E_Array>()), cas(1) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  {
+	if(cas==0)
+            return  new Movemesh3D_Op(args,t[0]->CastTo(args[0]));
+        else if (cas == 1)
+        {
+            const E_Array * a = dynamic_cast<const E_Array *>(args[1].LeftValue());
+            
+            ffassert(a);
+            if (a->size() !=3) CompileError("movemesh(Th,[X,Y,Z],...) need 3 componates in array ",atype<pmesh>());
+            Expression X=to<double>( (*a)[0]);
+            Expression Y=to<double>( (*a)[1]);
+            Expression Z=to<double>( (*a)[2]);
+            return   new Movemesh3D_Op(args,t[0]->CastTo(args[0]),X,Y,Z);
+        }
+      else return 0;
+  }
+};
+
+
+
+
+
+
+
+
+
+
+//// version 3D de change label
+
+class SetMesh3D_Op : public E_F0mps 
+{
+public:
+  Expression a; 
+  
+  static const int n_name_param =2+2+2+2; //
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+    { ffassert( !(nargs[i] && nargs[i+2]));
+      i = nargs[i] ? i : i+2;
+      return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+    long  arg(int i,Stack stack, long  a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    bool   arg(int i,Stack stack, bool   a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+
+  
+public:
+  SetMesh3D_Op(const basicAC_F0 &  args,Expression aa) : a(aa) {
+    args.SetNameParam(n_name_param,name_param,nargs);
+      if( nargs[0] && nargs[2] ) 
+	  CompileError("uncompatible change(... region= , reftet=  ");
+      if( nargs[1] && nargs[3] ) 
+	  CompileError("uncompatible  change(...label= , refface=  ");
+      
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type SetMesh3D_Op::name_param[]= {
+  {  "reftet", &typeid(KN_<long> )},
+  {  "refface", &typeid(KN_<long> )},
+  {  "region", &typeid(KN_<long> )},
+  {  "label", &typeid(KN_<long> )},
+  {  "fregion", &typeid(long)},
+  {  "flabel", &typeid(long )},
+  {  "rmlfaces", &typeid(long)},
+  {  "rmInternalFaces", &typeid(bool)}
+
+};
+//  besoin en cas de fichier 2D / fichier 3D 
+
+int  ChangeLab3D(const map<int,int> & m,int lab)
+{
+  map<int,int>::const_iterator i=m.find(lab);
+  if(i != m.end())
+    lab=i->second;
+  return lab;
+}
+
+AnyType SetMesh3D_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*a)(stack));
+  Mesh3 & Th=*pTh;
+  if(!pTh) return pTh;
+  Mesh3 *m= pTh;
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int nbe=Th.nbe; // nombre d'aretes fontiere
+  //cout << "Number of Vertex="<< nbv << "Number of BorderElement=" << nbe << endl;  
+  KN<long> zz;
+  KN<long> nrtet (arg(0,stack,zz));  
+  KN<long> nrface (arg(1,stack,zz));  
+  Expression freg = nargs[4];
+  Expression flab = nargs[5];
+    bool  rm_faces = nargs[6];
+    long  rmlabfaces (arg(6,stack,0L));
+    bool  rm_i_faces (arg(7,stack,false));
+
+ // cout << " Chnage " << freg << " " << flab << endl;   
+  if(nrface.N() <=0 && nrtet.N() <=0 && (!freg) && (!flab) && !rmlabfaces && !rm_i_faces ) return m; // modf J.M. oct 2010
+  ffassert( nrtet.N() %2 ==0);
+  ffassert( nrface.N() %2 ==0);
+  
+  map<int,int> maptet,mapface;
+  
+  int z00 = false;
+  for(int i=0;i<nrface.N();i+=2)
+    { z00 = z00 || ( nrface[i]==0 && nrface[i+1]==0);
+
+      if( nrface[i] != nrface[i+1] ){	
+      mapface[nrface[i]] = nrface[i+1];
+      }      
+    }
+      
+  for(int i=0;i<nrtet.N();i+=2)
+    maptet[nrtet[i]]=nrtet[i+1];
+  
+  // sert a quoi ???  
+  int nben =0;
+  for(int i=0;i<nbe;++i)
+  {
+  	const Triangle3 & K = Th.be(i);	
+	int l0,l1=ChangeLab3D(mapface, l0= K.lab) ;
+	nben++;
+  }
+	  
+	  
+  Vertex3   *v = new Vertex3[nbv];
+  Tet       *t;
+  if(nbt!=0) t=new Tet[nbt];
+  Triangle3 *b = new Triangle3[nben];
+  // generation des nouveaux sommets 
+  Vertex3 *vv=v;
+  // copie des anciens sommets (remarque il n'y a pas operateur de copy des sommets)
+  for (int i=0;i<nbv;i++)
+    {
+     const Vertex3 & V(Th.vertices[i]);
+     vv->x=V.x;
+     vv->y=V.y;
+     vv->z=V.z;
+     vv->lab = V.lab;
+     vv++;      
+   }
+
+  //  generation des triangles 
+  Tet *tt= t; 
+  int lmn= 2000000000;
+  int lmx= -2000000000;
+  int nberr=0;
+   R3 PtHat(1./4.,1./4.,1./4.);
+    for (int i=0;i<nbt;i++)
+    {
+      const Tet &K( Th.elements[i] );	
+      int iv[4];
+      //int i0=Th(i,0), i1=Th(i,1),i2=Th(i,2);
+      iv[0]= Th.operator()(K[0]);
+      iv[1]= Th.operator()(K[1]);
+      iv[2]= Th.operator()(K[2]);
+      iv[3]= Th.operator()(K[3]);
+      // les 3 triangles par triangles origines 
+      int lab=K.lab;
+      
+      tt->set( v, iv, ChangeLab3D(maptet,lab));
+      if(freg)
+	{//      R3 B(1./4.,1./4.,1./4.);  // 27/09/10 : J.Morice error in msh3.cpp
+	      mp->set(Th,K(PtHat),PtHat,K,0);
+	      tt->lab =GetAny<long>( (* freg)(stack)) ;  
+	      lmn= min (lmn,tt->lab);
+	      lmx= max (lmx,tt->lab);
+	    }
+      tt++;
+	
+    }  
+    if(freg && verbosity> 1 ) cout << "    -- Change : new region number bound : " << lmn << " "<< lmx << endl;
+    // les arete frontieres qui n'ont pas change
+     lmn= 2000000000;
+     lmx= -2000000000;
+  
+  Triangle3 * bb=b;
+     R2 PtHat2(1./3.,1./3.);
+    int nrmf=0; 
+  for (int i=0;i<nbe;i++)
+    { 
+      const Triangle3 &K( Th.be(i) );
+      int fk,ke = Th.BoundaryElement(i,fk); // element co
+      int fkk,kke = Th.ElementAdj(ke,fkk=fk); // element co
+      bool onborder = (kke==ke) || (kke <0) ;
+      const Tet & KE(Th[ke]);
+      R3 B= KE.PBord(fk,PtHat2);
+      int iv[3];       
+      bool  rmf = rm_i_faces && ! onborder; 
+      iv[0] = Th.operator()(K[0]);
+      iv[1] = Th.operator()(K[1]);
+      iv[2] = Th.operator()(K[2]);
+      
+      int l0,l1=ChangeLab3D(mapface,l0=K.lab) ;
+      if(flab)
+	  {//      R3 B(1./4.,1./4.,1./4.);  // 27/09/10 : J.Morice error in msh3.cpp
+              R3 NN= KE.N(fk);
+              double mes=NN.norme();
+              NN/=mes;
+	      mp->set(Th,KE(B),B,KE,K.lab,NN,fk);
+	      l1 =GetAny<long>( (* flab)(stack)) ;
+	      lmn= min (lmn,bb->lab);
+	      lmx= max (lmx,bb->lab);
+	  }
+        if( !rmf && rm_faces)
+          rmf =  !onborder &&  ( l1 == rmlabfaces  );
+        if(rmf)
+            nrmf++;
+        else
+         (*bb++).set( v, iv, l1);
+
+	
+    }
+    if(nrmf && verbosity > 2) cout << "   change  mesh3 : number of removed  internal faces " << nrmf << " == " << nbe - (bb-b) << endl;
+    
+  nben -= nrmf;
+  nbe -= nrmf;
+  assert(nben==bb-b);
+  *mp=mps; 
+  if(nbt != 0)
+    {
+      Mesh3 *mpq = new Mesh3(nbv,nbt,nbe,v,t,b);
+      
+	//mpq->BuildBound();
+     // mpq->BuildAdj();
+     // mpq->Buildbnormalv();  
+     // mpq->BuildjElementConteningVertex(); 
+      mpq->BuildGTree();
+      //mpq->decrement();   // ?? decrement enlever ???
+      Add2StackOfPtr2FreeRC(stack,mpq);  
+      
+      return mpq;
+    }
+  if(nbt == 0)
+    {
+      Mesh3 *mpq = new Mesh3(nbv,nbe,v,b);
+      
+     // mpq->BuildBound();
+      Add2StackOfPtr2FreeRC(stack,mpq);  
+      
+      return mpq;
+    }
+
+  Mesh3 *mpq = NULL;
+  return mpq;
+}
+
+
+class SetMesh3D : public OneOperator { public:  
+typedef Mesh3 *pmesh3;
+    SetMesh3D() : OneOperator(atype<pmesh3>(),atype<pmesh3>() ) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new SetMesh3D_Op(args,t[0]->CastTo(args[0])); 
+  }
+};
+
+// ---------------------------------
+// Movemesh2d_3D_surf
+
+
+class Movemesh2D_3D_surf_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  Expression xx,yy,zz; 
+  static const int n_name_param =5+1; 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const{ 
+      return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  long arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+  double arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny<double>( (*nargs[i])(stack) ): a;}
+public:
+  Movemesh2D_3D_surf_Op(const basicAC_F0 &  args,Expression tth) : 
+  eTh(tth),xx(0),yy(0),zz(0) 
+  {
+
+    args.SetNameParam(n_name_param,name_param,nargs);
+    
+    const E_Array * a1=0 ;
+    if(nargs[0])  a1  = dynamic_cast<const E_Array *>(nargs[0]);
+    int err =0;
+    if( nargs[2] && nargs[5] ) 
+    	CompileError("uncompatible movemesh23 (Th, label= , refface=  ");
+    if(a1) {
+      if(a1->size() !=3) 
+	CompileError("movemesh23 (Th,transfo=[X,Y,Z],) ");
+      xx=to<double>( (*a1)[0]);
+      yy=to<double>( (*a1)[1]);
+      zz=to<double>( (*a1)[2]);
+    }    
+    
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type Movemesh2D_3D_surf_Op::name_param[]= {
+  {  "transfo", &typeid(E_Array )},
+  {  "orientation", &typeid(long)},
+  {  "refface", &typeid(KN_<long>)},
+  {  "ptmerge", &typeid(double)},
+  {  "boolsurface",&typeid(long)},
+  {  "label", &typeid(KN_<long> )}
+    
+};
+
+AnyType Movemesh2D_3D_surf_Op::operator()(Stack stack)  const 
+{
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  Mesh & Th=*pTh;
+  Mesh *m= pTh;
+  int nbv=Th.nv;  // nombre de sommet 
+  int nbt=Th.nt;  // nombre de triangles
+  int nbe=Th.neb; // nombre d'aretes fontiere
+  if(verbosity>5)
+    cout << "before movemesh: Vertex Triangle Edge"<< nbv << " "  << nbt << " " << nbe << endl;  
+  
+  KN<long> zzempty;
+  //int intempty=0;
+  int mesureM (arg(1,stack,0L));
+  KN<long> nrface (arg(2,stack,arg(5,stack,zzempty)));
+  double precis_mesh(arg(3,stack,-1.));
+  long flagsurfaceall(arg(4,stack,-1L));
+  
+  if(nrface.N()<0 ) return m;
+  ffassert( nrface.N() %2 ==0);
+  
+  map<int,int> mapface;
+  
+  int z00 = false;
+  for(int i=0;i<nrface.N();i+=2)
+    { z00 = z00 || ( nrface[i]==0 && nrface[i+1]==0);
+
+      if( nrface[i] != nrface[i+1] ){	
+      mapface[nrface[i]] = nrface[i+1];
+      }      
+    }
+  
+  int surface_orientation=1; 
+  if( mesureM <0 ){
+    surface_orientation=-1;
+  }
+        
+
+  KN<double> txx(nbv), tyy(nbv), tzz(nbv);
+  MeshPoint *mp3(MeshPointStack(stack)); 
+  
+  {
+    KN<int> takemesh(nbv);  
+    takemesh=0;  
+    Mesh &rTh = Th;
+    for (int it=0; it<nbt; ++it){
+      for( int iv=0; iv<3; ++iv){
+	int i=Th(it,iv);
+	if(takemesh[i]==0){
+	  mp3->setP(&Th,it,iv);
+	  if(xx){ 
+	    txx[i]=GetAny<double>((*xx)(stack));
+	  }
+	  if(yy){ 
+	    tyy[i]=GetAny<double>((*yy)(stack));
+	  }
+	  if(zz){ 
+	    tzz[i]=GetAny<double>((*zz)(stack));
+	  }
+	  takemesh[i] = takemesh[i]+1;
+	}
+      }
+    }
+  }
+  
+  //Mesh3 *Th3; //= new Mesh3;
+  
+  int vertex_out=1;
+  
+  if( vertex_out == 1){
+    /* determinate the same vertex */ 
+    int border_only = 0;
+    int recollement_border=1, point_confondus_ok=0;
+
+    // faire version de Transfo_Mesh2_tetgen pour ce cas pr�cis.
+    Mesh3 *Th3= MoveMesh2_func( precis_mesh, Th, txx, tyy, tzz, 
+			 border_only, recollement_border, point_confondus_ok);
+	
+    // Rajouter fonction flip a l interieure
+    int nbflip=0;
+    for(int ii=0; ii < Th3->nbe; ii++){
+      const Triangle3 & K(Th3->be(ii)); 
+      int iv[3];
+      int lab;
+      double mes_triangle3;
+	
+    
+      iv[0] = Th3->operator()(K[0]);
+      iv[1] = Th3->operator()(K[1]);
+      iv[2] = Th3->operator()(K[2]);
+		
+      map< int, int>:: const_iterator imap;
+      imap = mapface.find(K.lab); 
+		
+      if(imap!= mapface.end()){
+	lab=imap->second;
+      } 
+      else{
+	lab=K.lab;
+      }
+		
+      Th3->be(ii).set( Th3->vertices, iv, lab ) ;
+      mes_triangle3 = Th3->be(ii).mesure();
+		
+      if( surface_orientation*mes_triangle3 < 0){
+	int iv_temp=iv[1];
+	iv[1]=iv[2];
+	iv[2]=iv_temp;
+	Th3->be(ii).set( Th3->vertices, iv, lab ) ;
+	nbflip++;
+      }
+		
+      /* autre methode a tester */
+      /*
+	Triangle3 Kmes;
+	Kmes.set( Th3->vertices, iv, lab ) ;
+	mes_triangle3 = Kmes.mesure();
+	if( surface_orientation*mes_triangle3) < 0){
+	int iv_temp=iv[1];
+	iv[1]=iv[2];
+	iv[2]=iv_temp;
+	}
+	Th3->be(ii).set( Th3->vertices, iv, lab ) ;
+      */
+    }
+    
+    assert(nbflip==0 || nbflip== Th3->nbe);
+    if(flagsurfaceall==1) Th3->BuildBoundaryElementAdj();
+    Add2StackOfPtr2FreeRC(stack,Th3);
+   
+    return Th3;
+  }
+  else   if( vertex_out == 0){
+	  
+    //Tet       *t = new Tet[1];
+    Vertex3   *v = new Vertex3[nbv];
+    Triangle3 *b = new Triangle3[nbe];
+    // generation des nouveaux sommets 
+    Vertex3 *vv=v;
+    // copie des anciens sommets (remarque il n'y a pas operateur de copy des sommets)
+    for (int i=0;i<nbv;i++)
+      {
+	const Mesh::Vertex & V( Th.vertices[i]);
+	vv->x = txx[i];
+	vv->y = tyy[i];
+	vv->z = tzz[i];
+	vv->lab = V.lab;
+	vv++;      
+      }
+ 
+    // les arete frontieres qui n'ont pas change
+  
+    Triangle3 * bb=b;
+    for (int i=0;i<nbt;i++)
+      { 
+      	const Mesh::Triangle &K( Th.t(i) );
+      	int iv[3];       
+    
+      	iv[0] = Th.operator()(K[0]);
+      	iv[1] = Th.operator()(K[1]);
+      	iv[2] = Th.operator()(K[2]);
+      	
+      	(*bb++).set( v, iv, K.lab);
+		
+      }
+      
+    //Mesh3 *Th3 = new Mesh3(nbv,0,nbt,v,t,b);
+    Mesh3 *Th3 = new Mesh3(nbv,nbt,v,b);
+
+    int nbflip=0;
+    for (int i=0;i<Th3->nbe;i++)
+      { 
+	double mes_triangle3= Th3->be(i).mesure();
+	
+	if( surface_orientation*mes_triangle3 < 0){
+	  const Triangle3 &K( Th3->be(i) );
+	  int iv[3];       
+	  
+	  iv[0] = Th3->operator()(K[0]);
+	  iv[1] = Th3->operator()(K[1]);
+	  iv[2] = Th3->operator()(K[2]);
+	  
+	  int iv_temp=iv[1];
+	  iv[1]=iv[2];
+	  iv[2]=iv_temp;
+	  Th3->be(i).set( Th3->vertices, iv, K.lab ) ;
+	  nbflip++;
+	}
+      }
+    assert(nbflip==0 || nbflip== Th3->nbe);
+    if(flagsurfaceall==1) Th3->BuildBoundaryElementAdj();
+    Add2StackOfPtr2FreeRC(stack,Th3);
+    return Th3;
+  }
+  return (Mesh3*) 0;
+}
+
+
+class Movemesh2D_3D_surf : public OneOperator { public:  
+typedef Mesh *pmesh;
+typedef Mesh3 *pmesh3;
+    
+  Movemesh2D_3D_surf() : OneOperator(atype<pmesh3>(),atype<pmesh>() ) {}
+    E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new Movemesh2D_3D_surf_Op(args,t[0]->CastTo(args[0]));  // CastTo(args[]); // plus tard
+  }
+};
+
+
+/* ancien fichier de TransfoMesh */
+
+Mesh3 * Transfo_Mesh3(const double &precis_mesh,const Mesh3 & Th3, const double *tab_XX, const double *tab_YY, const double *tab_ZZ,
+		      int &border_only, int &recollement_element, int &recollement_border, int &point_confondus_ok,int orientation)
+{
+    // cas besoin memoire important
+    
+    //Mesh3 *T_Th3=new Mesh3;
+    int nv_t,nt_t,nbe_t;
+    
+    int* Numero_Som;
+    
+    int* ind_nv_t;
+    int* ind_nt_t;
+    int* ind_nbe_t;
+    
+    int* label_nt_t;
+    int* label_nbe_t;
+    
+    int i_som, i_elem, i_border;
+    
+    Numero_Som = new int[Th3.nv];
+    
+    ind_nv_t   = new int[Th3.nv];
+    ind_nt_t   = new int[Th3.nt];
+    ind_nbe_t  = new int[Th3.nbe];
+    
+    label_nt_t   = new int[Th3.nt];
+    label_nbe_t  = new int[Th3.nbe];
+    
+    
+    //cout << "Vertex, Tetrahedra, Border : "<<Th3.nv << ", "<<Th3.nt<< ", " << Th3.nbe<< endl;
+    
+    for(int ii=0; ii<Th3.nv; ii++){
+        Numero_Som[ii]=ii;
+    }
+    
+    if(verbosity > 1) cout <<" debut: SamePointElement " <<endl;
+    
+    SamePointElement( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th3, recollement_element, recollement_border, point_confondus_ok,
+                     Numero_Som, ind_nv_t, ind_nt_t, ind_nbe_t, label_nt_t, label_nbe_t, nv_t, nt_t, nbe_t);
+    
+    if(verbosity > 1) cout <<" fin: SamePointElement " <<endl;
+    
+    
+    
+    // set size of Mesh T_Th3
+    //T_Th3->set(nv_t,nt_t,nbe_t);
+    Vertex3 *v = new Vertex3[nv_t];
+    Tet     *t = new Tet[nt_t];
+    Tet     *tt=t;
+    Triangle3 *b= new Triangle3[nbe_t];
+    Triangle3 *bb=b;
+    double mes=0,mesb=0;
+    cout << "Transfo TH3 : Vertex, Tetrahedra, Border : "<< "nv_t="<< nv_t << " nt_t=" << nt_t << " nbe_t=" << nbe_t << endl;
+    
+    // determination of vertex
+    i_som = 0;
+    for(int i=0; i<nv_t; i++){
+        
+        int & ii = ind_nv_t[i];
+        assert( Numero_Som[ii] == i_som );
+        
+        const Vertex3 & K(Th3.vertices[ii]);
+        
+        v[i_som].x = tab_XX[ii];
+        v[i_som].y = tab_YY[ii];
+        v[i_som].z = tab_ZZ[ii];
+        v[i_som].lab = K.lab;
+        
+        
+        i_som = i_som + 1;
+    }
+    assert( i_som == nv_t);
+    
+    
+    //cout << " Transfo volume elements " << endl;
+    // determination of volume elements
+    i_elem = 0;
+    for( int i=0; i< nt_t; i++){
+        int & ii=ind_nt_t[i];
+        
+        // creation of elements
+        
+        const Tet & K(Th3.elements[ii]);
+        int iv[4];
+        int lab;
+        lab = label_nt_t[i];
+        
+        for(int jj=0; jj <4; jj++){
+            iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+            assert( iv[jj] >= 0 && iv[jj] < nv_t);
+        }
+        if(orientation<0) swap(iv[1],iv[2]) ;
+        (tt)->set(v, iv, lab);
+        mes += tt++->mesure();
+        i_elem++;
+    }
+    
+    assert( i_elem == nt_t);
+    
+    //cout << " Transfo border elements " << endl;
+    // determination of border elements
+    i_border= 0;
+    for( int i=0; i< nbe_t; i++){
+        int & ii=ind_nbe_t[i];
+        // creation of elements
+        const Triangle3 & K(Th3.be(ii));
+        int iv[3];
+        int lab;
+        lab = label_nbe_t[i];
+        
+        for(int jj=0; jj <3; jj++)
+        {
+            iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+            assert( iv[jj] >= 0 && iv[jj] < nv_t);
+        }
+        if(orientation<0) swap(iv[1],iv[2]) ;
+        
+        bb->set(v, iv, lab);
+        mesb += bb++->mesure();
+        i_border=i_border+1;
+    }
+    assert( i_border == nbe_t);
+    if  ( mes  < 0 )
+    {
+        cerr << " E rror of mesh orientation , current orientation = "<< orientation << endl;
+        cerr << " volume mesh = " << mes << endl;
+        cerr << " surface border mesh = " << mesb << endl;
+        ErrorExec(" movemesh 3d ",1);
+    }
+    
+    delete [] Numero_Som;
+    delete [] ind_nv_t;   
+    delete [] ind_nt_t;  
+    delete [] ind_nbe_t;
+    delete [] label_nt_t;
+    delete [] label_nbe_t;
+    
+    if( nt_t !=0){
+        Mesh3 *T_Th3 = new Mesh3(nv_t,nt_t,nbe_t,v,t,b);
+        
+        return T_Th3;
+    }
+    else{
+        Mesh3 *T_Th3 = new Mesh3(nv_t,nbe_t,v,b);
+        
+        delete [] t;
+        return T_Th3;
+    }
+    
+    
+}
+void SamePointElement( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh3 & Th3, 
+	int &recollement_element, int &recollement_border, int &point_confondus_ok,
+	int *Numero_Som, int *ind_nv_t, int *ind_nt_t, int *ind_nbe_t, 
+	int *label_nt_t, int *label_nbe_t, int & nv_t, int & nt_t,int & nbe_t ){
+		
+  int Elem_ok, Border_ok;
+  double hmin,hmin_elem,hmin_border;
+  R3 bmin,bmax;
+  //int recollement_element=1,recollement_border=1;
+  
+  if(verbosity > 2) cout << "    BuilBound " <<endl;
+  BuildBoundMinDist_th3( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th3, bmin, bmax, hmin);
+  if(verbosity > 2) cout << "   =============================== " << endl;
+		
+  double bmin3[3], bmax3[3];
+  bmin3[0] = bmin.x;
+  bmin3[1] = bmin.y;
+  bmin3[2] = bmin.z;
+		
+  bmax3[0] = bmax.x;
+  bmax3[1] = bmax.y;
+  bmax3[2] = bmax.z;
+ 
+
+
+  if(verbosity > 2) cout << "    OrderVertexTransfo_hcode gtree " << endl;
+  OrderVertexTransfo_hcode_nv_gtree( Th3.nv, bmin, bmax, hmin, tab_XX, tab_YY, tab_ZZ, Numero_Som, ind_nv_t, nv_t );
+  if(verbosity > 2) cout << "    fin order vertex gtree: nv_t=" << nv_t << endl;
+  if(verbosity > 2) cout << "   =============================== " << endl;
+		
+  /* determination de nt_t et de nbe_t*/ 
+  int i_elem, i_border;
+		
+  i_elem = 0;
+  for(int ii=0; ii< Th3.nt; ii++){
+    const Tet & K(Th3.elements[ii]);
+    int iv[4];
+			
+    Elem_ok = 1;
+			
+    for(int jj=0; jj <4; jj++){
+      iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+    }
+			
+    for(int jj=0; jj<4; jj++){
+      for(int kk=jj+1; kk<4; kk++){
+	if( iv[jj]==iv[kk] ){
+	  Elem_ok = 0;
+	}
+      }
+    }
+			
+    if(Elem_ok==1){
+      ind_nt_t[i_elem]= ii;
+      label_nt_t[i_elem] = K.lab;
+      i_elem = i_elem + 1;
+    }
+  } 
+  nt_t=i_elem;
+		
+  if(recollement_element ==1){
+    //int point_confondus_ok_e = 0;
+    if(verbosity > 1) cout << "debut recollement : nt_t= "<< nt_t << endl; 
+			
+    int np,dim=3;
+    int *ind_np = new int [nt_t];
+    int *label_t = new int [nt_t];
+    double **Cdg_t=new double *[nt_t];
+    for(int i=0; i<nt_t; i++) Cdg_t[i] = new double[dim];
+			
+    for( int i_elem=0; i_elem< nt_t; i_elem++){
+      int & ii=ind_nt_t[i_elem];
+      const Tet & K(Th3.elements[ii]);
+      int iv[4];
+      for(int jj=0; jj <4; jj++){
+	iv[jj] = Th3.operator()(K[jj]) ;
+      }
+      Cdg_t[i_elem][0] = ( tab_XX[iv[0]] + tab_XX[iv[1]] + tab_XX[iv[2]] + tab_XX[iv[3]] )/4.;
+      Cdg_t[i_elem][1] = ( tab_YY[iv[0]] + tab_YY[iv[1]] + tab_YY[iv[2]] + tab_YY[iv[3]] )/4.;
+      Cdg_t[i_elem][2] = ( tab_ZZ[iv[0]] + tab_ZZ[iv[1]] + tab_ZZ[iv[2]] + tab_ZZ[iv[3]] )/4.;
+      label_t[i_elem]  = K.lab;
+    }
+			
+    hmin_elem = hmin/4;
+    //PointCommun_hcode( dim, nt_t, 0, Cdg_t, bmin3, bmax3, hmin_elem, ind_np, np); //ancien
+    PointCommun_hcode_gtree( dim, nt_t, 0, Cdg_t, label_t, bmin, bmax, hmin_elem, 
+			     ind_np, label_nt_t, np); // nv
+			
+    assert( np <= nt_t );
+			
+    int *ind_nt_t_tmp= new int [np];
+			
+    for( int i_elem=0; i_elem< np; i_elem++){
+      assert( ind_np[i_elem] >=0 && ind_np[i_elem] <= nt_t );
+      ind_nt_t_tmp[ i_elem ] = ind_nt_t[ ind_np[i_elem] ]; 
+    }
+    for( int i_elem=0; i_elem< np; i_elem++){
+      ind_nt_t[ i_elem ] = ind_nt_t_tmp[ i_elem ]; 
+    }
+			
+    
+    delete [] ind_np; 
+    delete [] label_t;
+    for(int i=0; i<nt_t; i++) delete [ ] Cdg_t[i];
+    delete [] Cdg_t;
+
+    delete [] ind_nt_t_tmp;
+		
+    nt_t = np;
+    if(verbosity > 1) cout << "fin recollement : nt_t= "<< nt_t << endl; 
+  }
+		
+  // determination of border elements
+  i_border= 0;
+  for( int ii=0; ii< Th3.nbe; ii++){
+    Border_ok=1;
+		
+    const Triangle3 & K(Th3.be(ii));
+    int iv[3];
+			
+    for(int jj=0; jj <3; jj++){
+      iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+      assert( iv[jj] >= 0 && iv[jj] < nv_t);
+    }
+			
+    for(int jj=0; jj<3; jj++){
+      for(int kk=jj+1; kk<3; kk++){
+	if( iv[jj]==iv[kk] ) Border_ok=0;
+      }
+    }
+    if(Border_ok==1){
+      ind_nbe_t[i_border]   = ii;
+      label_nbe_t[i_border] = K.lab;
+      i_border=i_border+1;
+    }
+  }
+  nbe_t = i_border;
+		
+  if( recollement_border == 1){
+    //int point_confondus_ok = 1;
+    if(verbosity > 1) cout << "debut recollement : nbe_t= "<< nbe_t << endl; 
+			
+    int np,dim=3;
+    int *ind_np = new int [nbe_t];
+    double **Cdg_be=new double *[nbe_t];
+    int *label_be = new int [nbe_t];
+    for(int i=0; i<nbe_t; i++) Cdg_be[i] = new double[dim];
+			
+    for( int i_border=0; i_border< nbe_t; i_border++){
+				
+      int & ii=ind_nbe_t[i_border];
+      const Triangle3 & K(Th3.be(ii));
+      int iv[3];
+				
+      for(int jj=0; jj <3; jj++){
+	iv[jj] = Th3.operator()(K[jj]);
+      }
+      Cdg_be[i_border][0] = ( tab_XX[iv[0]] + tab_XX[iv[1]] + tab_XX[iv[2]] )/3.; //( Th3.vertices[iv[0]].x + Th3.vertices[iv[1]].x + Th3.vertices[iv[2]].x )/3.;
+      Cdg_be[i_border][1] = ( tab_YY[iv[0]] + tab_YY[iv[1]] + tab_YY[iv[2]] )/3.; //( Th3.vertices[iv[0]].y + Th3.vertices[iv[1]].y + Th3.vertices[iv[2]].y )/3.;
+      Cdg_be[i_border][2] = ( tab_ZZ[iv[0]] + tab_ZZ[iv[1]] + tab_ZZ[iv[2]] )/3.; //( Th3.vertices[iv[0]].z + Th3.vertices[iv[1]].z + Th3.vertices[iv[2]].z )/3.;		
+				
+      label_be[i_border] = K.lab;
+    }
+    hmin_border=hmin/3.;
+    if(verbosity > 1) cout << "hmin_border=" << hmin_border << endl;
+			
+    if(verbosity > 1) cout << "appele de PointCommun_hcode := " << point_confondus_ok<< endl;
+    //PointCommun_hcode( dim, nbe_t, point_confondus_ok, Cdg_be, bmin3, bmax3, hmin_border, ind_np, np);
+    PointCommun_hcode_gtree( dim, nbe_t, point_confondus_ok, Cdg_be, label_be, 
+			     bmin, bmax, hmin_border, ind_np, label_nbe_t, np); 
+    if(verbosity > 1) cout << "fin appele de PointCommun_hcode" << endl;
+			
+    assert( np <= nbe_t );
+			
+    int *ind_nbe_t_tmp= new int [np];
+		
+    for( int i_border=0; i_border<np; i_border++){
+      ind_nbe_t_tmp[ i_border ] = ind_nbe_t[ ind_np[i_border] ]; 
+    }
+		
+    for( int i_border=0; i_border< np; i_border++){
+      ind_nbe_t[ i_border ] = ind_nbe_t_tmp[ i_border ]; 
+    }
+   
+    delete [] ind_np; 
+    delete [] label_be;
+    for(int i=0; i<nbe_t; i++) delete [ ] Cdg_be[i];
+    delete [] Cdg_be;
+
+    delete [] ind_nbe_t_tmp;
+			
+    nbe_t = np;
+    if(verbosity > 1) cout << "fin recollement : nbe_t= "<< nbe_t << endl; 
+			
+    // Affectation de la nouvelle valeur du label
+			
+  }
+}
+
+// 3D surface
+
+Mesh3 * Transfo_Mesh3_surf(const double &precis_mesh, const Mesh3 & Th3, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+	int &recollement_border, int &point_confondus_ok){
+	// cas besoin memoire important
+	
+	//Mesh3 *T_Th3=new Mesh3;
+	int nv_t,nbe_t;
+	int nt_t=0;
+	
+	int* Numero_Som;
+	int* ind_nv_t;
+	int* ind_nbe_t;
+	int* label_nbe_t;
+	
+	int i_som, i_elem, i_border;
+	
+	assert( Th3.nt == 0);
+	
+	Numero_Som = new int[Th3.nv];
+	ind_nv_t   = new int[Th3.nv];
+	ind_nbe_t  = new int[Th3.nbe];
+	label_nbe_t  = new int[Th3.nbe];
+	
+    
+	if(verbosity > 1) cout << "Vertex, Tetrahedra, Border : "<<Th3.nv << ", "<<Th3.nt<< ", " << Th3.nbe<< endl;
+    
+	for(int ii=0; ii<Th3.nv; ii++){
+		Numero_Som[ii]=ii;
+	}
+	
+	if(verbosity > 1) cout <<" debut: SamePointElement " <<endl;
+	
+	SamePointElement_surf( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th3, 
+			       recollement_border, point_confondus_ok, Numero_Som,
+			       ind_nv_t, ind_nbe_t, label_nbe_t, nv_t, nbe_t);
+	
+	if(verbosity > 1) cout <<" fin: SamePointElement " <<endl;
+	
+	// set size of Mesh T_Th3 
+
+
+	//T_Th3->set(nv_t,nt_t,nbe_t);
+	Vertex3 *v = new Vertex3[nv_t];
+	//Tet     *t;
+	Triangle3 *b= new Triangle3[nbe_t];
+	Triangle3 *bb=b;
+
+
+	if(verbosity > 1) cout << "Transfo TH3 : Vertex, Tetrahedra, Border : "<< "nv_t="<< nv_t << " nt_t=" << nt_t << " nbe_t=" << nbe_t << endl;
+		
+	// determination of vertex		
+	i_som = 0;
+	for(int i=0; i<nv_t; i++){
+		
+	  int & ii = ind_nv_t[i];
+	  assert( Numero_Som[ii] == i_som );
+	  
+	  const Vertex3 & K(Th3.vertices[ii]);
+	  /*
+	    T_Th3->vertices[i_som].x = tab_XX[ii];
+	    T_Th3->vertices[i_som].y = tab_YY[ii];
+	    T_Th3->vertices[i_som].z = tab_ZZ[ii];
+	    T_Th3->vertices[i_som].lab = K.lab; 
+	  */
+	   v[i_som].x = tab_XX[ii];
+	   v[i_som].y = tab_YY[ii];
+	   v[i_som].z = tab_ZZ[ii];
+	   v[i_som].lab = K.lab; 
+
+	  i_som = i_som + 1;		
+	}	
+	if(verbosity > 1) cout << "i_som, nv_t=" <<i_som << " "<<nv_t << endl;
+	assert( i_som == nv_t);
+	
+	if(verbosity > 1) cout << " Transfo border elements " << endl;
+	// determination of border elements
+	i_border= 0;
+	for( int i=0; i< nbe_t; i++){
+	  int & ii=ind_nbe_t[i];
+	  
+	  // creation of elements
+	  const Triangle3 & K(Th3.be(ii));
+	  int iv[3];
+	  int lab;
+	  
+	  //lab = K.lab; 
+	  lab = label_nbe_t[i];
+	  
+	  for(int jj=0; jj <3; jj++){
+	    iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+	    assert( iv[jj] >= 0 && iv[jj] <= nv_t);
+	  }
+	  //T_Th3->be(i_border).set(T_Th3->vertices, iv, lab);
+	  (bb++)->set(v, iv, lab);
+	  i_border=i_border+1;
+	} 
+	assert( i_border == nbe_t);
+
+	delete [] Numero_Som;
+	delete [] ind_nv_t;
+	delete [] ind_nbe_t;  
+	delete [] label_nbe_t;
+
+	//Mesh3* T_Th3 = new Mesh3(nv_t,nt_t,nbe_t,v,t,b); 
+	Mesh3* T_Th3 = new Mesh3(nv_t,nbe_t,v,b);
+
+	return T_Th3;
+}
+
+void SamePointElement_surf( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh3 & Th3, 
+	int &recollement_border, int &point_confondus_ok, int *Numero_Som, 
+	int *ind_nv_t, int *ind_nbe_t, int *label_nbe_t, int & nv_t,int & nbe_t ){
+		
+  int Elem_ok, Border_ok;
+  double hmin,hmin_elem,hmin_border;
+  R3 bmin,bmax;
+  //int recollement_element=1,recollement_border=1;
+  
+  if(verbosity > 1) cout << "  OrderVertexTransfo_hcode gtree " <<endl;
+  BuildBoundMinDist_th3( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th3, bmin, bmax, hmin);
+  if(verbosity > 1) cout << " =============================== " << endl;
+  
+  double bmin3[3], bmax3[3];
+  bmin3[0] = bmin.x;
+  bmin3[1] = bmin.y;
+  bmin3[2] = bmin.z;
+  
+  bmax3[0] = bmax.x;
+  bmax3[1] = bmax.y;
+  bmax3[2] = bmax.z;
+  
+  /*
+    cout << "  OrderVertexTransfo_hcode " << endl;
+    OrderVertexTransfo_hcode_nv( Th3.nv, tab_XX, tab_YY, tab_ZZ, bmin3, bmax3, hmin, Numero_Som, ind_nv_t, nv_t );
+    cout << "fin order vertex: nv_t=" << nv_t << endl;
+  */
+  if(verbosity > 1) cout << "  OrderVertexTransfo_hcode gtree " << endl;
+  OrderVertexTransfo_hcode_nv_gtree( Th3.nv, bmin, bmax, hmin, tab_XX, tab_YY, tab_ZZ, Numero_Som, ind_nv_t, nv_t );
+  if(verbosity > 1) cout << "fin order vertex gtree: nv_t=" << nv_t << endl;
+  
+  if(verbosity > 1) cout << " =============================== " << endl;
+  
+  /* determination de nt_t et de nbe_t*/ 
+  int i_border;
+  
+  // determination of border elements
+  i_border= 0;
+  for( int ii=0; ii< Th3.nbe; ii++){
+    Border_ok=1;
+    
+    const Triangle3 & K(Th3.be(ii));
+    int iv[3];
+			
+    for(int jj=0; jj <3; jj++){
+      iv[jj] = Numero_Som[ Th3.operator()(K[jj]) ];
+    }
+			
+    for(int jj=0; jj<3; jj++){
+      for(int kk=jj+1; kk<3; kk++){
+	if( iv[jj]==iv[kk] ) Border_ok=0;
+      }
+    }
+    if(Border_ok==1){
+      ind_nbe_t[i_border]   = ii;
+      label_nbe_t[i_border] = K.lab;
+      i_border=i_border+1;
+    }
+  }
+  nbe_t = i_border;
+		
+  if( recollement_border == 1){
+    //int point_confondus_ok = 1;
+    if(verbosity > 1) cout << "debut recollement : nbe_t= "<< nbe_t << endl; 
+			
+    int np,dim=3;
+    int *ind_np = new int [nbe_t];
+    int *label_be = new int [nbe_t];
+
+    double **Cdg_be=new double *[nbe_t];
+    for(int i=0; i<nbe_t; i++) Cdg_be[i] = new double[dim];
+  
+		
+    for( int i_border=0; i_border< nbe_t; i_border++){
+				
+      int & ii=ind_nbe_t[i_border];
+      const Triangle3 & K(Th3.be(ii));
+      int iv[3];
+				
+      for(int jj=0; jj <3; jj++){
+	iv[jj] = Th3.operator()(K[jj]);
+      }
+      Cdg_be[i_border][0] = ( tab_XX[iv[0]] + tab_XX[iv[1]] + tab_XX[iv[2]] )/3.; //( Th3.vertices[iv[0]].x + Th3.vertices[iv[1]].x + Th3.vertices[iv[2]].x )/3.;
+      Cdg_be[i_border][1] = ( tab_YY[iv[0]] + tab_YY[iv[1]] + tab_YY[iv[2]] )/3.; //( Th3.vertices[iv[0]].y + Th3.vertices[iv[1]].y + Th3.vertices[iv[2]].y )/3.;
+      Cdg_be[i_border][2] = ( tab_ZZ[iv[0]] + tab_ZZ[iv[1]] +  tab_ZZ[iv[2]] )/3.; //( Th3.vertices[iv[0]].z + Th3.vertices[iv[1]].z + Th3.vertices[iv[2]].z )/3.;		
+				
+      label_be[i_border] = K.lab;
+    }
+    hmin_border=hmin/3.;
+    if(verbosity > 1) cout << "hmin_border=" << hmin_border << endl;
+			
+    if(verbosity > 1) cout << "appele de PointCommun_hcode := " << point_confondus_ok<< endl;
+    //PointCommun_hcode( dim, nbe_t, point_confondus_ok, Cdg_be, bmin3, bmax3, hmin_border, ind_np, np);
+    PointCommun_hcode_gtree( dim, nbe_t, point_confondus_ok, Cdg_be, label_be, 
+			     bmin, bmax, hmin_border, ind_np, label_nbe_t, np); 
+    if(verbosity > 1) cout << "fin appele de PointCommun_hcode" << endl;
+			
+    assert( np <= nbe_t );
+			
+    int *ind_nbe_t_tmp= new int [np];
+		
+    for( int i_border=0; i_border<np; i_border++){
+      ind_nbe_t_tmp[ i_border ] = ind_nbe_t[ ind_np[i_border] ]; 
+    }
+		
+    for( int i_border=0; i_border< np; i_border++){
+      ind_nbe_t[ i_border ] = ind_nbe_t_tmp[ i_border ]; 
+    }
+  
+
+    delete [] ind_np; 
+    delete [] label_be;
+    delete [] ind_nbe_t_tmp;
+    for(int i=0; i<nbe_t; i++) delete [] Cdg_be[i];
+    delete [] Cdg_be;
+	
+    nbe_t = np;
+    if(verbosity > 1) cout << "fin recollement : nbe_t= "<< nbe_t << endl; 
+			
+    // Affectation de la nouvelle valeur du label
+		
+  }
+}
+
+void Transfo_Mesh2_map_face(const Mesh &Th2, map<int, int> &maptri ){
+		
+  int numero_label=0;
+  for(int ii=0; ii< Th2.nt; ii++){
+    const Mesh::Triangle & K(Th2.t(ii));
+    map<int,int>::const_iterator imap=maptri.find(K.lab);
+			
+    if(imap == maptri.end()){
+      maptri[ K.lab ] = numero_label;
+      numero_label = numero_label+1;
+    }
+  }
+}
+
+
+Mesh3 * MoveMesh2_func( const double &precis_mesh, const Mesh & Th2, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+	int &border_only, int &recollement_border, int &point_confondus_ok){
+	
+  //Mesh3 *T_Th3= new Mesh3;
+	int nv_t,nt_t,nbe_t;
+	int* Numero_Som;
+	
+	int* ind_nv_t;
+	int* ind_nt_t=0;
+	int* ind_nbe_t;
+	int* label_nbe_t;
+	
+	//int i_som;
+	Numero_Som = new int[Th2.nv];
+	ind_nv_t   = new int[Th2.nv];
+	ind_nbe_t  = new int[Th2.nt];   
+	label_nbe_t = new int[Th2.nt];
+	if(verbosity>5)
+	cout << "before movemesh::Vertex  triangle2  border " << Th2.nv << " "<<Th2.nt<< " " << Th2.neb<< endl;
+	
+	for(int ii=0; ii<Th2.nv; ii++){ 
+		Numero_Som[ii]=ii;
+	}
+	
+	if(verbosity > 1) cout <<" debut: SamePointElement " <<endl;
+	
+	SamePointElement_Mesh2( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th2, recollement_border, point_confondus_ok, 
+		Numero_Som, ind_nv_t, ind_nt_t, ind_nbe_t, label_nbe_t, nv_t, nt_t, nbe_t);
+	
+	if(verbosity > 1) cout <<" fin: SamePointElement " <<endl;
+	
+	cout << "After movemesh::Vertex  triangle2  border " << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+	
+	Vertex3 *v=new Vertex3[nv_t];
+	Tet *t;
+	Triangle3 *b=new Triangle3[nbe_t];
+	Triangle3 *bb=b;
+
+	//T_Th3->set(nv_t,0,nbe_t);
+	
+	for(int nnv=0; nnv < nv_t; nnv++)
+	{
+		int ii = ind_nv_t[nnv];
+		assert( Numero_Som[ii] == nnv );
+		const Mesh::Vertex & K = Th2.vertices[ii];//const Vertex2 & K(Th2.vertices[ii]); //Version Mesh2   
+		/*
+		  T_Th3->vertices[nnv].x = tab_XX[ii];
+		  T_Th3->vertices[nnv].y = tab_YY[ii];
+		  T_Th3->vertices[nnv].z = tab_ZZ[ii];       
+		  T_Th3->vertices[nnv].lab =  K.lab;   
+		*/
+		v[nnv].x = tab_XX[ii];
+		v[nnv].y = tab_YY[ii];
+		v[nnv].z = tab_ZZ[ii];       
+		v[nnv].lab =  K.lab;
+		
+	}
+	  
+	for(int ibe=0; ibe < nbe_t; ibe++){
+		int lab;
+		int iv[3];
+		int ii=ind_nbe_t[ibe];
+		// creation of elements
+		const Mesh::Triangle & K(Th2.t(ii)); // const Triangle2 & K(Th2.elements[ii]); // Version Mesh2  
+		iv[0] = Numero_Som[ Th2.operator()(K[0]) ];
+		iv[1] = Numero_Som[ Th2.operator()(K[1]) ];
+		iv[2] = Numero_Som[ Th2.operator()(K[2]) ];
+		
+		/*
+		map< int, int>:: const_iterator imap;
+		imap = maptri.find(K.lab); // imap= maptri.find( label_nbe_t[ibe] );
+		assert( imap != maptri.end());
+		lab = imap->second; // K.lab; // before 
+		*/
+		//T_Th3->be(ibe).set(T_Th3->vertices,iv,K.lab);
+		(bb++)->set(v,iv,K.lab);
+	}  
+
+
+	//Mesh3 *T_Th3 = new Mesh3(nv_t,0,nbe_t,v,t,b);
+	Mesh3 *T_Th3 = new Mesh3(nv_t,nbe_t,v,b);
+
+ 	delete [ ] Numero_Som;
+	delete [ ] ind_nv_t;
+	delete [ ] ind_nbe_t;
+	delete [ ] label_nbe_t;
+
+	return T_Th3;
+}
+
+void SamePointElement_Mesh2( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh & Th2, 
+	int &recollement_border, int &point_confondus_ok, int *Numero_Som, 
+	int *ind_nv_t, int *ind_nt_t, int *ind_nbe_t, int* label_nbe_t,
+	int & nv_t, int & nt_t,int & nbe_t ){
+
+  int Border_ok;
+  //int recollement_border=0;
+  R3 bmin,bmax;
+  double hmin,hmin_border;
+		
+  if(verbosity > 1) cout << "calculus of bound and minimal distance" << endl;
+  BuildBoundMinDist_th2( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th2, bmin, bmax, hmin);
+  // assertion pour la taille de l octree
+  assert(hmin>Norme2(bmin-bmax)/1e9);
+		
+  double bmin3[3], bmax3[3];
+  bmin3[0] = bmin.x;
+  bmin3[1] = bmin.y;
+  bmin3[2] = bmin.z;
+		
+  bmax3[0] = bmax.x;
+  bmax3[1] = bmax.y;
+  bmax3[2] = bmax.z;
+  /*
+    cout << "debut: OrderVertexTransfo_hcode " <<endl;
+    OrderVertexTransfo_hcode_nv( Th2.nv, tab_XX, tab_YY, tab_ZZ, bmin3, bmax3, hmin, Numero_Som, ind_nv_t, nv_t );
+    cout << "fin order vertex: nv_t=" << nv_t << endl;
+  */
+  if(verbosity > 1) cout << "debut: OrderVertexTransfo_hcode_gtree " <<endl;
+  OrderVertexTransfo_hcode_nv_gtree( Th2.nv, bmin, bmax, hmin, tab_XX, tab_YY, tab_ZZ, Numero_Som, ind_nv_t, nv_t);
+  if(verbosity > 1) cout << "fin: OrderVertexTransfo_hcode_gtree " <<endl;
+		
+		
+  /* determination de nt_t et de nbe_t*/ 
+  nt_t = 0;
+  int i_border;
+		
+  // determination of border elements
+  i_border= 0;
+  for( int
+	 ii=0; ii< Th2.nt; ii++){
+    Border_ok=1;
+    const Mesh::Triangle & K(Th2.t(ii)); // const Triangle2 & K(Th2.elements[ii]); // avant Mesh2
+    int iv[3];
+			
+    for(int jj=0; jj <3; jj++){
+      iv[jj] = Numero_Som[ Th2.operator()(K[jj]) ];
+    }
+			
+    for(int jj=0; jj<3; jj++){
+      for(int kk=jj+1; kk<3; kk++){
+	if( iv[jj]==iv[kk] ) Border_ok=0;
+      }
+    }
+    if(Border_ok==1){
+      ind_nbe_t[i_border] = ii;
+      label_nbe_t[i_border] = K.lab;
+      i_border=i_border+1;
+    }
+  }
+  nbe_t = i_border;
+		
+  if( recollement_border == 1){
+    //int point_confondus_ok=1;
+    if(verbosity > 1) cout << "debut recollement : nbe_t= "<< nbe_t << endl; 
+			
+    int np,dim=3;
+    int *ind_np = new int [nbe_t];
+    int *label_be = new int [nbe_t ];
+    double **Cdg_be=new double *[nbe_t];
+		
+    for(int i=0; i<nbe_t; i++) Cdg_be[i] = new double[dim];
+		
+    for( int i_border=0; i_border< nbe_t; i_border++){
+      int & ii=ind_nbe_t[i_border];
+      const Mesh::Triangle & K(Th2.t(ii)); //const Triangle2 & K(Th2.elements[ii]);  // avant Mesh2
+      int iv[3];
+				
+      for(int jj=0; jj <3; jj++){
+	iv[jj] = Th2.operator()(K[jj]);
+      }
+      
+      Cdg_be[i_border][0] = ( tab_XX[iv[0]] + tab_XX[iv[1]] + tab_XX[iv[2]] )/3.; 
+      Cdg_be[i_border][1] = ( tab_YY[iv[0]] + tab_YY[iv[1]] + tab_YY[iv[2]] )/3.; 
+      Cdg_be[i_border][2] = ( tab_ZZ[iv[0]] + tab_ZZ[iv[1]] + tab_ZZ[iv[2]] )/3.; 
+				
+      label_be[i_border] = K.lab;
+    }
+			
+    hmin_border=hmin/3.;
+    if(verbosity > 1) cout << "points commun " << endl;
+    //PointCommun_hcode( dim, nbe_t, point_confondus_ok, Cdg_be, bmin3, bmax3, hmin_border, ind_np, np); // ancien
+    PointCommun_hcode_gtree( dim, nbe_t, point_confondus_ok, Cdg_be, label_be, bmin, bmax, hmin_border, 
+			     ind_np, label_nbe_t,np); // new
+    if(verbosity > 1) cout << "points commun finis " <<endl;
+    assert( np <= nbe_t );
+
+    	
+    //int *ind_nbe_t_tmp= new int [np];
+    int ind_nbe_t_tmp[np];
+	
+    for( int i_border=0; i_border<np; i_border++){
+      ind_nbe_t_tmp[ i_border ] = ind_nbe_t[ ind_np[i_border] ]; 
+    }
+			
+    for( int i_border=0; i_border< np; i_border++){
+      ind_nbe_t[ i_border ] = ind_nbe_t_tmp[ i_border ]; 
+    }	
+		
+   
+    delete [ ] ind_np; //= new int [nbe_t];
+    delete [ ] label_be;// = new int [nbe_t ];
+    for(int i=0; i<nbe_t; i++) delete [ ] Cdg_be[i];
+    delete [ ] Cdg_be; //=new double *[nbe_t];
+    
+    nbe_t = np;
+    if(verbosity > 1) cout << "fin recollement : nbe_t= "<< nbe_t << endl; 
+
+  }
+}
+
+
+//======================
+//    Fin cas 2D
+//======================
+// version Mesh2
+void BuildBoundMinDist_th2( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh & Th2, R3 &bmin, R3 &bmax, double &hmin){
+  //determination de la boite englobante
+  //R3 bmin,bmax;
+  double precispt;
+		
+  bmin.x = tab_XX[0];
+  bmin.y = tab_YY[0];
+  bmin.z = tab_ZZ[0];
+		
+  bmax.x = bmin.x;
+  bmax.y = bmin.y;
+  bmax.z = bmin.z;
+		
+  //R3 bmax = new R3(bmin);
+  
+  if(verbosity >1) cout << " determination of bmin and bmax" << endl;
+		
+  for(int ii=1; ii<Th2.nv; ii++){
+    bmin.x = min(bmin.x,tab_XX[ii]);
+    bmin.y = min(bmin.y,tab_YY[ii]);
+    bmin.z = min(bmin.z,tab_ZZ[ii]);
+		
+    bmax.x = max(bmax.x,tab_XX[ii]);
+    bmax.y = max(bmax.y,tab_YY[ii]);
+    bmax.z = max(bmax.z,tab_ZZ[ii]);
+  }
+  double longmini_box=1e10;
+		
+  longmini_box = pow(bmax.x-bmin.x,2)+pow(bmax.y-bmin.y,2)+ pow(bmax.z-bmin.z,2);
+  longmini_box = sqrt(longmini_box);
+		
+  // determination de hmin 
+  if(precis_mesh< 0){
+    precispt=longmini_box*1e-7;
+  }
+  else{
+    precispt=precis_mesh;
+  }
+
+  hmin = 1e10;
+  for( int ii=0; ii< Th2.nt; ii++){
+    const Mesh :: Triangle & K(Th2.t(ii)); // const Triangle2 & K(Th2.elements[ii]);
+    double longedge;
+    int iv[3];
+    for(int jj=0; jj<3; jj++){
+      iv[jj] = Th2.operator()(K[jj]) ;
+    }
+			
+    for( int jj=0; jj<3; jj++){
+      for( int kk=jj+1; kk<3; kk++){ 
+	int & i1= iv[jj];
+	int & i2= iv[kk];
+	longedge = pow(tab_XX[i1]-tab_XX[i2],2) 
+	  + pow(tab_YY[i1]-tab_YY[i2],2) 
+	  + pow(tab_ZZ[i1]-tab_ZZ[i2],2);
+	longedge = sqrt(longedge);
+	//cout << "longedge=" << longedge << endl; 
+	if( longedge > precispt ) hmin = min( hmin, longedge);
+      }
+    }
+  }
+  if(verbosity >5) cout << "    longmin_box=" << longmini_box << endl;
+  if(verbosity >5) cout << "    hmin =" << hmin << endl;
+  if(verbosity >5) cout << "    Norme2(bmin-bmax)=" <<  Norme2(bmin-bmax) << endl;
+  assert( hmin < longmini_box);
+
+  // assertion pour la taille de l octree
+  assert(hmin>Norme2(bmin-bmax)/1e9);
+
+  /*  // ?????????
+    hmin = 1e10;
+    for( int ii=0; ii< Th2.nt; ii++){
+      const Mesh :: Triangle & K(Th2.t(ii)); // const Triangle2 & K(Th2.elements[ii]);
+      double longedge;
+      int iv[3];
+      for(int jj=0; jj<3; jj++){
+	iv[jj] = Th2.operator()(K[jj]) ;
+      }
+			
+      for( int jj=0; jj<3; jj++){
+	for( int kk=jj+1; kk<3; kk++){ 
+	  int & i1= iv[jj];
+	  int & i2= iv[kk];
+	  longedge = pow(tab_XX[i1]-tab_XX[i2],2) 
+	    + pow(tab_YY[i1]-tab_YY[i2],2) 
+	    + pow(tab_ZZ[i1]-tab_ZZ[i2],2);
+	  longedge = sqrt(longedge);
+	  //cout << "longedge=" << longedge << endl; 
+	  if( longedge > longmini_box*1e-7 ) hmin = min( hmin, longedge);
+	}
+      }
+    }
+    cout << "longmin_box=" << longmini_box << endl;
+    cout << "hmin =" << hmin << endl;
+    cout << "Norme2(bmin-bmax)=" <<  Norme2(bmin-bmax) << endl;
+    assert( hmin < longmini_box);
+    // assertion pour la taille de l octree
+    assert(hmin>Norme2(bmin-bmax)/1e9);
+  */
+}
+
+// version Mesh3
+
+void BuildBoundMinDist_th3(  const double &precis_mesh,  const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh3& Th3, R3 &bmin, R3 &bmax, double &hmin){
+  //determination de la boite englobante
+  //R3 bmin,bmax;
+  double precispt;
+  bmin.x = tab_XX[0];
+  bmin.y = tab_YY[0];
+  bmin.z = tab_ZZ[0];
+		
+  bmax.x = bmin.x;
+  bmax.y = bmin.y;
+  bmax.z = bmin.z;
+		
+  //R3 bmax = new R3(bmin);
+		
+  if(verbosity >1) cout << " determination of bmin and bmax" << endl;
+		
+  for(int ii=1; ii<Th3.nv; ii++){
+    bmin.x = min(bmin.x,tab_XX[ii]);
+    bmin.y = min(bmin.y,tab_YY[ii]);
+    bmin.z = min(bmin.z,tab_ZZ[ii]);
+		
+    bmax.x = max(bmax.x,tab_XX[ii]);
+    bmax.y = max(bmax.y,tab_YY[ii]);
+    bmax.z = max(bmax.z,tab_ZZ[ii]);
+  }
+		
+  double longmini_box;
+		
+  //longmini_box = min(bmax.x-bmin.x, bmax.y-bmin.y);
+  //longmini_box = min(longmini_box, bmax.z-bmin.z);
+		
+  longmini_box = pow(bmax.x-bmin.x,2)+pow(bmax.y-bmin.y,2)+ pow(bmax.z-bmin.z,2);
+  longmini_box = sqrt(longmini_box);
+		
+		
+  if(verbosity >1) cout << " bmin := " << bmin.x << " " << bmin.y << " " << bmin.z << endl;
+  if(verbosity >1) cout << " bmax := " << bmax.x << " " << bmax.y << " " << bmax.z << endl;
+  if(verbosity >1) cout << " box volume :=" << longmini_box << endl;
+	
+
+  if(precis_mesh< 0){
+    precispt=longmini_box*1e-7;
+  }
+  else{
+    precispt=precis_mesh;
+  }
+  // determination de hmin 
+		
+  hmin = 1e10;
+  for( int ii=0; ii< Th3.nt; ii++){
+    const Tet & K(Th3.elements[ii]);
+    double longedge;
+    int iv[4];
+    for(int jj=0; jj <4; jj++){
+      iv[jj] = Th3.operator()(K[jj]) ;
+    }
+			
+    for( int jj=0; jj<4; jj++){
+      for( int kk=jj+1; kk<4; kk++){ 
+	int & i1= iv[jj];
+	int & i2= iv[kk];
+	longedge = pow(tab_XX[i1]-tab_XX[i2],2) 
+	  + pow(tab_YY[i1]-tab_YY[i2],2) 
+	  + pow(tab_ZZ[i1]-tab_ZZ[i2],2);
+	longedge = sqrt(longedge);
+	if(longedge > precispt ) hmin = min( hmin, longedge);
+      }
+    }
+  }
+
+  if( Th3.nt == 0){
+    for( int ii=0; ii< Th3.nbe; ii++){
+      if(verbosity >10) cout << "border " << ii <<" hmin =" << hmin << endl;
+      const Triangle3 & K(Th3.be(ii));
+      double longedge;
+      int iv[3];
+      for(int jj=0; jj <3; jj++){
+	iv[jj] = Th3.operator()(K[jj]) ;
+      }
+			
+      for( int jj=0; jj<3; jj++){
+	for( int kk=jj+1; kk<3; kk++){ 
+	  int & i1= iv[jj];
+	  int & i2= iv[kk];
+	  longedge = pow(tab_XX[i1]-tab_XX[i2],2) 
+	    + pow(tab_YY[i1]-tab_YY[i2],2) 
+	    + pow(tab_ZZ[i1]-tab_ZZ[i2],2);
+	  longedge = sqrt(longedge);
+	  if(longedge > precispt ) hmin = min( hmin, longedge);
+	}
+      }
+    }
+  }
+
+  if(verbosity >5) cout << "    longmini_box" << longmini_box << endl;
+  if(verbosity >5) cout << "    hmin =" << hmin << endl;
+  assert( hmin < longmini_box);
+  if(verbosity >5) cout << "    Norme2(bmin-bmax)=" <<  Norme2(bmin-bmax) << endl;
+  // assertion pour la taille de l octree
+  assert(hmin>Norme2(bmin-bmax)/1e9);
+}
+
+//======================
+//
+//======================
+void OrderVertexTransfo_hcode_nv( const int &tab_nv, const double *tab_XX, const double *tab_YY, const double *tab_ZZ,  
+				  const double *bmin, const double *bmax, const double hmin,int *Numero_Som, int * ind_nv_t, int & nv_t){
+  size_t i;
+  size_t j[3];
+  size_t k[3];
+  size_t NbCode = 100000;
+  int *tcode; //= new int[NbCode];	
+
+  int *posv = new int[tab_nv];
+  double epsilon= hmin/10.;
+  /*
+    double epsilon=0.001;
+			
+    // determination de boite englobante
+    double bmin[3],bmax[3];
+	
+    bmin[0] = tab_XX[0];
+    bmin[1] = tab_YY[0];
+    bmin[2] = tab_ZZ[0];
+	
+    bmax[0] = bmin[0];
+    bmax[1] = bmin[1];
+    bmax[2] = bmin[2];
+	
+    cout << " determination bmin et bmax" << endl;
+	
+    for(int ii=1; ii<tab_nv; ii++){
+    bmin[0] = min(bmin[0],tab_XX[ii]);
+    bmin[1] = min(bmin[1],tab_YY[ii]);
+    bmin[2] = min(bmin[2],tab_ZZ[ii]);
+ 		
+    bmax[0] = max(bmax[0],tab_XX[ii]);
+    bmax[1] = max(bmax[1],tab_YY[ii]);
+    bmax[2] = max(bmax[2],tab_ZZ[ii]);
+    }
+  */
+	
+  k[0] = int( (bmax[0]-bmin[0])/epsilon ); 
+  k[1] = int( (bmax[1]-bmin[1])/epsilon ); 
+  k[2] = int( (bmax[2]-bmin[2])/epsilon ); 
+	
+  int numberofpoints=0;
+  int numberofpointsdiff;
+	
+  for(int ii=0; ii<tab_nv; ii++){
+    numberofpointsdiff=0;
+    for(int jj=ii+1; jj<tab_nv; jj++){
+      double dist = 0.;
+      dist = pow(tab_XX[jj]-tab_XX[ii],2)+pow(tab_YY[jj]-tab_YY[ii],2)+pow(tab_ZZ[jj]-tab_ZZ[ii],2); //pow(Coord_Point[jj][kk]-Coord_Point[ii][kk],2);
+      if( sqrt(dist) < epsilon ){
+	numberofpointsdiff=1;
+      } 
+    }
+    if( numberofpointsdiff==0) numberofpoints=numberofpoints+1;
+  }
+	
+  if(verbosity >4) cout << "   -- numberofpoints " << numberofpoints << endl;
+  if(verbosity >4) cout << "   -- taille boite englobante =" << endl;
+  if(verbosity >4)
+    {
+      for(int ii=0; ii<3; ii++){
+	cout << "ii=" << ii << " " << bmin[ii] << " " << bmax[ii] <<endl;
+      }
+      
+      for(int ii=0; ii<3; ii++){
+	cout << "k[" << ii << "]= " << k[ii]<<endl;
+      }
+    }
+  NbCode = min( 4*(k[0]+k[1]+k[2]), NbCode );
+  tcode = new int[NbCode];
+	
+	
+  /* initialisation des codes */
+  for(int ii=0; ii< NbCode; ii++){
+    tcode[ii] = -1;
+  }
+	
+	
+  for(int ii=0; ii < tab_nv; ii++){
+    // boucle dans l autre sens pour assurer l'ordre des elements pour la suite
+    //cout << "vertex ii " << ii << "  max : " << tab_nv;  
+    j[0] = int( (tab_XX[ii]-bmin[0])/epsilon  );
+    j[1] = int( (tab_YY[ii]-bmin[1])/epsilon  );
+    j[2] = int( (tab_ZZ[ii]-bmin[2])/epsilon  );  
+		
+    assert( j[0] <=k[0] && j[0]>=0);
+    assert( j[1] <=k[1] && j[1]>=0);
+    assert( j[2] <=k[2] && j[2]>=0);
+    i = (j[2]*(k[1]+1)+j[1]*(k[0]+1)+j[0]);
+    //cout << i << endl;	
+    i = i%NbCode;    
+    assert( i < NbCode );
+    posv[ii] = tcode[i];
+    tcode[i] = ii;
+  }
+	
+  if(verbosity >1) cout << " boucle numero de Sommet " << endl;
+  for(int ii=0; ii<tab_nv; ii++){
+    Numero_Som[ii]=-1;
+  }
+	
+  if(verbosity >1) cout << " determinations des points confondus et numerotation " << endl;
+	
+  nv_t=0;
+  for(int	icode =0; icode < NbCode; icode++){
+    //int ii,jj;		
+    double dist;		
+		
+    for(int ii=tcode[icode]; ii!=-1; ii=posv[ii]){
+      if(Numero_Som[ii] != -1) continue; 
+      Numero_Som[ii] = nv_t;				
+      for(int jj=posv[ii]; jj!=-1; jj=posv[jj]){
+	if(Numero_Som[jj] != -1) continue; 
+	dist=pow(tab_XX[jj]-tab_XX[ii],2)+pow(tab_YY[jj]-tab_YY[ii],2)+pow(tab_ZZ[jj]-tab_ZZ[ii],2);	
+			
+	if( sqrt(dist) < epsilon ){
+	  // point semblable
+	  Numero_Som[jj] = Numero_Som[ii];
+	  //cout << "point semblable" << endl;
+	  //exit(-1); 
+	}
+				
+      }
+      ind_nv_t[nv_t] = ii; // Remarque on donne a nv_t le plus grand
+      nv_t++; //nv_t = nvt+1;
+    }
+  }
+  if(verbosity >1) cout << "      nv_t = " << nv_t << " / " << "nv_t(anc)" << tab_nv <<endl;
+  assert( nv_t == numberofpoints);
+
+  delete [] posv;
+  delete [] tcode;
+}
+
+void PointCommun_hcode( const int &dim, const int &NbPoints, const int &point_confondus_ok, double **Coord_Point, 
+			const double *bmin, const double *bmax, const double hmin, int * ind_np, int & np){
+	
+  size_t i;
+  size_t j[dim];
+  size_t k[dim];
+  size_t NbCode = 100000;
+  int *tcode; //= new int[NbCode];
+  int *posv = new int[NbPoints];
+  int *Numero_Som =new int[NbPoints];
+	
+  double epsilon=hmin/10.;
+  /*
+    double epsilon=0.0001;
+    double bmin[dim],bmax[dim];
+	
+    for(int jj=0; jj<dim; jj++){ 
+    bmin[jj] = Coord_Point[0][jj];
+    bmax[jj] = bmin[jj];
+    }
+    for(int ii=1; ii<NbPoints; ii++){
+    for(int jj=0; jj<dim; jj++){ 
+    bmin[jj] = min(bmin[jj],Coord_Point[ii][jj]);
+    bmax[jj] = max(bmax[jj],Coord_Point[ii][jj]);
+    }
+    }
+  */
+  assert( dim > 1);
+	
+  for(int jj=0; jj<dim; jj++){ 
+    k[jj] = int( (bmax[jj]-bmin[jj])/epsilon );
+  } 
+	
+  int numberofpoints=0;
+  int numberofpointsdiff;
+	
+  for(int ii=0; ii<NbPoints; ii++){
+    numberofpointsdiff=0;
+    for(int jj=ii+1; jj<NbPoints; jj++){
+      double dist = 0.;
+      for( int kk=0; kk<3; kk++){
+	dist = dist +  pow(Coord_Point[jj][kk]-Coord_Point[ii][kk],2);
+      }
+      if( sqrt(dist) < 1e-10){
+	numberofpointsdiff=1;
+      } 
+    }
+    if( numberofpointsdiff==0) numberofpoints=numberofpoints+1;
+  }
+	
+  if(verbosity >1) cout << "numberofpoints " << numberofpoints << endl;
+	
+  NbCode = min( 4*(k[0]+k[1]+k[2]), NbCode);
+  if(verbosity >1) cout << "NbCode=" << NbCode << endl;
+  tcode = new int[NbCode];
+  /* initialisation des codes */
+  for(int ii=0; ii< NbCode; ii++){
+    tcode[ii] = -1;
+  }
+	
+  for(int ii=0; ii < NbPoints; ii++){
+    // boucle dans l autre sens pour assurer l'ordre des elements pour la suite
+		
+    for( int jj=0; jj<dim; jj++){
+      j[jj] = int( (Coord_Point[ii][jj]-bmin[jj])/epsilon  );
+    }
+	
+    assert( j[0] <=k[0] && j[0]>=0);
+    assert( j[1] <=k[1] && j[1]>=0);
+    assert( j[2] <=k[2] && j[2]>=0);
+		
+    i = j[0];
+    for(int jj=1; jj<dim; jj++){
+      i=i+j[jj]*(k[jj-1]+1);
+    }
+    i = i%NbCode;    
+		
+    assert( i < NbCode );
+    posv[ii] = tcode[i];
+    tcode[i] = ii;
+  }
+  for(int ii=0; ii < NbPoints; ii++){
+    ind_np[ii] = -1;
+    Numero_Som[ii] = -1;
+  }
+	
+  /* Resolution probleme dans le cas o� le maillage se colle */
+	
+  /* maintenant determinations des points confondus et numerotation*/
+	
+  switch( point_confondus_ok ){
+	
+  case 0:
+    np=0;
+    for(int	icode =0; icode < NbCode; icode++){
+      //int ii,jj;		
+      double dist;		
+		
+      for(int ii=tcode[icode]; ii!=-1; ii=posv[ii]){
+			
+	if( Numero_Som[ii]!= -1 ) continue;
+	//minimum_np=ii;
+	Numero_Som[ii] = np;
+			
+	for(int jj=posv[ii]; jj!=-1; jj=posv[jj]){
+				
+	  if(Numero_Som[jj] != -1) continue; 
+	  dist = 0.;
+				
+	  for( int kk=0; kk<dim; kk++){
+	    dist = dist +  pow(Coord_Point[jj][kk]-Coord_Point[ii][kk],2);
+	  }
+					
+	  if( sqrt(dist) < epsilon ){
+	    // point semblable
+	    Numero_Som[jj] = Numero_Som[ii];
+	    //minimum_np = min( jj, minimum_np);
+	  }
+	}
+	ind_np[np] = ii; //min(ii,minimum_np);	// Remarque on donne a np le plus petit element
+	np++; //nv_t = nvt+1;
+      }
+    }
+    break;
+		
+  case 1:
+    int point_multiple;
+    np=0;
+    for(int icode =0; icode < NbCode; icode++){
+      //int ii,jj;		
+      double dist;		
+		
+      for(int ii=tcode[icode]; ii!=-1; ii=posv[ii]){
+			
+	if( Numero_Som[ii]!= -1 ) continue;										
+	//minimum_np=ii;
+	Numero_Som[ii] = np;
+	point_multiple = 0; 
+				
+				
+	for(int jj=posv[ii]; jj!=-1; jj=posv[jj]){
+				
+	  if(Numero_Som[jj] != -1) continue; 				
+	  dist = 0.;
+				
+	  for( int kk=0; kk<dim; kk++){
+	    dist = dist +  pow(Coord_Point[jj][kk]-Coord_Point[ii][kk],2);
+	  }
+							
+	  if( sqrt(dist) < epsilon ){
+	    // point semblable
+	    Numero_Som[jj] = Numero_Som[ii];
+	    point_multiple = 1; 
+	    //minimum_np = min( jj, minimum_np);
+	  }				
+	}
+	if(point_multiple ==0){
+	  ind_np[np] = ii; //min(ii,minimum_np);	// Remarque on donne a np le plus petit element
+	  np++; //nv_t = nvt+1;
+	}
+      }
+    }
+    break;
+  default:
+    cout << " point_confondus_ok dans fonction PointCommun_hcode vaut 1 ou 0." << endl;
+    exit(-1);
+  }
+
+  delete [] tcode; 
+  delete [] posv;
+  delete [] Numero_Som;
+
+}
+
+void OrderVertexTransfo_hcode_nv_gtree( const int & tab_nv, const R3 &bmin, const R3 &bmax, const double &hmin,  
+					const double *tab_XX, const double *tab_YY, const double *tab_ZZ, int *Numero_Som, int * ind_nv_t, int & nv_t){
+
+  size_t i;
+  size_t j[3];
+  size_t k[3];
+	
+  // parametre interne pour debugger le code
+  int verifnumberofpoints;
+  verifnumberofpoints = 1;
+	
+  // hmin a determiner plus haut
+  assert(hmin>Norme2(bmin-bmax)/1e9);
+  double hseuil =hmin/10.; 
+
+  //hseuil = hseuil/10.;
+	
+  Vertex3  *v= new Vertex3[tab_nv];
+  //Vertex3  v[tab_nv];
+  
+  EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(v,bmin,bmax,0);
+	
+  if(verbosity >2){
+    cout << "  -- taille de la boite " << endl;
+    cout << "\t" <<  bmin.x << " " << bmin.y << " " << bmin.z <<  endl;
+    cout << "\t"  << bmax.x << " " << bmax.y << " " << bmax.z <<  endl;
+  }
+	
+  // creation of octree
+  nv_t = 0;
+  for (int ii=0;ii<tab_nv;ii++){
+    const R3 r3vi( tab_XX[ii], tab_YY[ii],tab_ZZ[ii]);
+    /*vi.x = tab_XX[ii];
+      vi.y = tab_YY[ii];
+      vi.z = tab_ZZ[ii];*/
+    const Vertex3 &vi(r3vi);
+    /*vi.x = tab_XX[ii];
+      vi.y = tab_YY[ii];
+      vi.z = tab_ZZ[ii];*/
+	
+
+    Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+    if(!pvi){
+      v[nv_t].x = vi.x;
+      v[nv_t].y = vi.y;
+      v[nv_t].z = vi.z;
+      v[nv_t].lab = vi.lab; // lab mis a zero par default
+      ind_nv_t[nv_t] = ii;
+      Numero_Som[ii] = nv_t;
+      gtree->Add( v[nv_t] );
+      nv_t=nv_t+1;
+    }
+
+    else{
+      Numero_Som[ii] = pvi-v;
+    }
+  }
+
+  delete gtree;
+  delete [] v;
+	
+  if(verbosity >3) cout << "    hseuil=" << hseuil <<endl;
+  if(verbosity >3) cout << "    nv_t = " << nv_t << " / " << "nv_t(anc)" << tab_nv <<endl;
+  
+  if(verifnumberofpoints ==1){
+    int numberofpoints=0;
+    int numberofpointsdiff;
+	
+    for(int ii=0; ii<tab_nv; ii++){
+      numberofpointsdiff=0;
+      for(int jj=ii+1; jj<tab_nv; jj++){
+	double dist = 0.;
+	dist = pow(tab_XX[jj]-tab_XX[ii],2)+pow(tab_YY[jj]-tab_YY[ii],2)+pow(tab_ZZ[jj]-tab_ZZ[ii],2);
+	if( sqrt(dist) < hseuil){
+	  numberofpointsdiff=1;
+	} 
+      }
+      if( numberofpointsdiff==0) numberofpoints=numberofpoints+1;
+    }
+    if(verbosity >2) cout << "  -- numberofpoints " << numberofpoints << endl;
+//    if(verbosity >2) cout << "  -- taille boite englobante =" << endl;
+    //    assert(nv_t==numberofpoints);
+  }
+}
+
+void PointCommun_hcode_gtree( const int &dim, const int &NbPoints, const int &point_confondus_ok, 
+			      double **Coord_Point, const int * label_point, 
+			      const R3 & bmin, const R3 & bmax, const double &hmin, int * ind_np, int * ind_label, int & np){
+	
+  double hseuil =hmin/10.; 
+  Vertex3  *v= new Vertex3[NbPoints];
+  //Vertex3 v[NbPoints];
+  EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(v,bmin,bmax,0);
+	
+  if(verbosity >1) cout<< "verif hmin vertex3 GTree switch: " << point_confondus_ok << endl;
+	
+  int int_point_confondus_ok = point_confondus_ok;
+	
+  if(int_point_confondus_ok == 0){
+    // accepte les points double 
+    np = 0;
+    for (int ii=0;ii<NbPoints;ii++){
+      const R3 r3vi( Coord_Point[ii][0], Coord_Point[ii][1], Coord_Point[ii][2] ); 
+      const Vertex3 &vi( r3vi);
+      Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+			
+      if(!pvi){
+	v[np].x = vi.x;
+	v[np].y = vi.y;
+	v[np].z = vi.z;
+	v[np].lab = vi.lab; // lab mis a zero par default
+	ind_np[np] = ii;
+	ind_label[np] = label_point[ii];
+	gtree->Add( v[np++] );
+      }
+      else{
+	ind_label[pvi-v] = min( ind_label[pvi-v], label_point[ii] );
+      }
+    }
+    if(verbosity >1) cout << "np="<< np << endl;
+		
+  }
+  if(int_point_confondus_ok == 1){
+    // accepte les points double sont enleves
+    np = 0;
+    for (int ii=0;ii<NbPoints;ii++){
+      const R3 r3vi( Coord_Point[ii][0], Coord_Point[ii][1], Coord_Point[ii][2] ); 
+      //int label = label_point[ii];
+      const Vertex3 &vi( r3vi);
+      Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+			
+      if(!pvi){
+	v[np].x = vi.x;
+	v[np].y = vi.y;
+	v[np].z = vi.z;
+	v[np].lab = vi.lab; // lab mis a zero par default
+	ind_np[np] = ii;
+	ind_label[np] = label_point[ii];
+	gtree->Add( v[np++] );
+      }
+      else{
+	ind_label[pvi-v] = min( ind_label[pvi-v], label_point[ii] );
+      }
+    }
+		
+    int ind_multiple[np];
+		
+    for(int ii=0; ii<np; ii++){
+      ind_multiple[ii]=-1;
+    }
+    for (int ii=0;ii<NbPoints;ii++){
+      const R3 r3vi(Coord_Point[ii][0], Coord_Point[ii][1], Coord_Point[ii][2] );
+      //int label =  label_point[ii];
+      const Vertex3 & vi(r3vi);
+      Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+      ind_multiple[pvi-v]=ind_multiple[pvi-v]+1; 
+    }
+		
+    int jnp;
+    jnp=0;
+    for(int ii=0; ii<np; ii++){
+      if(ind_multiple[ii]==0){
+	assert( jnp <= ii);
+	ind_np[jnp] = ind_np[ii];
+	ind_label[jnp] = ind_label[ii];
+	jnp++;
+      }
+    }
+    np=jnp;
+  }
+  if( int_point_confondus_ok != 0 && int_point_confondus_ok != 1){
+    cout << " point_confondus_ok dans fonction PointCommun_hcode vaut 1 ou 0." << endl;
+    exit(1);
+  }
+	
+  delete gtree;
+  delete [] v; 
+
+  /*
+    int z_verifnumberofpoints;
+    z_verifnumberofpoints = 0;
+    if(z_verifnumberofpoints ==1){
+    int numberofpoints=0;
+    int numberofpointsdiff;
+    for(int ii=0; ii<NbPoints; ii++){
+    numberofpointsdiff=0;
+    for(int jj=ii+1; jj<NbPoints; jj++){
+    double dist = 0.;
+    for( int kk=0; kk<3; kk++){
+    dist = dist +  pow(Coord_Point[jj][kk]-Coord_Point[ii][kk],2);
+    }
+    if( sqrt(dist) < hseuil/10){
+    numberofpointsdiff=1;
+    } 
+    }
+    if( numberofpointsdiff==0) numberofpoints=numberofpoints+1;
+    if( point_confondus_ok==1 && numberofpointsdiff==1) numberofpoints=numberofpoints-1;
+    }
+    cout << "numberofpoints =" << numberofpoints<< endl;
+    cout << "np =" << np<< endl;
+    //assert( numberofpoints == np);
+    }
+  */
+}
+
+/* fin TransfoMesh_v2.cpp*/
+
+/* debut buildlayer.cpp */
+class BuildLayeMesh_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  Expression enmax,ezmin,ezmax,xx,yy,zz;
+  static const int n_name_param =9+4; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  //int    arg(int i,Stack stack,int a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+public:
+  BuildLayeMesh_Op(const basicAC_F0 &  args,Expression tth,Expression nmaxx) 
+    : eTh(tth),enmax(nmaxx), ezmin(0),ezmax(0),xx(0),yy(0),zz(0)
+  {
+    if(verbosity >1) cout << "construction par BuilLayeMesh_Op" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    const E_Array * a2 =0, *a1=0 ;
+    if(nargs[0])  a1  = dynamic_cast<const E_Array *>(nargs[0]);
+    if(nargs[1])  a2  = dynamic_cast<const E_Array *>(nargs[1]);
+    int err =0;
+    //cout << nargs[0] << " "<< a1 << endl;
+    //cout << nargs[1] << " "<< a2 << endl;
+    if(a1) {
+      if(a1->size() !=2) 
+	CompileError("LayerMesh (Th,n, zbound=[zmin,zmax],) ");
+	  //cout << "lecture de ezmin , ezmax" << endl; 
+      ezmin=to<double>( (*a1)[0]);
+      ezmax=to<double>( (*a1)[1]); 
+    }
+    if(a2) {
+      if(a2->size() !=3) 
+	CompileError("LayerMesh (Th,n, transfo=[X,Y,Z],) ");
+      xx=to<double>( (*a2)[0]);
+      yy=to<double>( (*a2)[1]);
+      zz=to<double>( (*a2)[2]);
+    }  
+    if( nargs[3] && nargs[9] ) 
+	CompileError("uncompatible buildlayer (Th, region= , reftet=  ");
+    if( nargs[4] && nargs[10] ) 
+	CompileError("uncompatible buildlayer (Th, midlabel= , reffacemid=  ");
+    if( nargs[5] && nargs[11] ) 
+	CompileError("uncompatible buildlayer (Th, toplabel= , reffaceup=  ");
+    if( nargs[6] && nargs[12] ) 
+	CompileError("uncompatible buildlayer (Th, downlabel= , reffacelow=  ");
+    
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type BuildLayeMesh_Op::name_param[]= {
+  {  "zbound", &typeid(E_Array)},
+  {  "transfo", &typeid(E_Array)},
+  {  "coef", &typeid(double)},
+  {  "reftet", &typeid(KN_<long>)}, // 3
+  {  "reffacemid", &typeid(KN_<long> )},
+  {  "reffaceup", &typeid(KN_<long> )},
+  {  "reffacelow", &typeid(KN_<long> )},
+  {  "facemerge", &typeid(long)},
+  {  "ptmerge",&typeid(double)},
+  {  "region", &typeid(KN_<long>)}, // 9
+  {  "labelmid", &typeid(KN_<long> )},
+  {  "labelup", &typeid(KN_<long> )},
+  {  "labeldown", &typeid(KN_<long> )}, // 12
+    
+};
+
+
+class  BuildLayerMesh : public OneOperator { public:  
+    BuildLayerMesh() : OneOperator(atype<pmesh3>(),atype<pmesh>(),atype<long>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  {
+    if(verbosity >1) cout << " je suis dans code(const basicAC_F0 & args) const" << endl; 
+    //cout << "args: " << args << endl;   
+    return  new BuildLayeMesh_Op(args,t[0]->CastTo(args[0]),t[1]->CastTo(args[1])); 
+  }
+};
+
+AnyType BuildLayeMesh_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  int nlayer = (int) GetAny<long>((*enmax)(stack));
+  ffassert(pTh && nlayer>0);
+  Mesh &Th=*pTh;
+  Mesh *m= pTh;   // question a quoi sert *m ??
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int neb=Th.neb; // nombre d'aretes fontiere
+  if(verbosity>2)
+  cout << "  -- BuildLayeMesh_Op input: nv" << nbv<< "  nt: "<< nbt << " nbe "<< neb << endl; 
+  KN<double> zmin(nbv),zmax(nbv);
+  KN<double> clayer(nbv); //  nombre de layer est nlayer*clayer
+  
+  clayer=-1;
+  zmin=0.;
+  zmax=1.;
+    double maxdz = 0;   
+  for (int it=0;it<nbt;++it){
+    for(int iv=0;iv<3;++iv)      
+    {
+      int i=Th(it,iv);
+       if(clayer[i]<0)
+	{
+	  mp->setP(&Th,it,iv);
+	  //cout << "mp: fait " << endl;
+	  if(ezmin){ zmin[i]=GetAny<double>((*ezmin)(stack));}
+	  if(ezmax){ zmax[i]=GetAny<double>((*ezmax)(stack));}
+	  maxdz = max(maxdz, abs(zmin[i]-zmax[i]));
+	  clayer[i]=Max( 0. , Min( 1. , arg(2,stack,1.) ) ); 
+	
+	}	     
+    }
+  }
+  
+  ffassert(clayer.min() >=0);
+
+  if(verbosity >1) cout << "lecture valeur des references " << endl;
+  
+  KN<long> zzempty;
+  KN<long> nrtet  (arg(3,stack,arg(3+6,stack,zzempty)));  
+  KN<long> nrfmid (arg(4,stack,arg(4+6,stack,zzempty)));  
+  KN<long> nrfup  (arg(5,stack,arg(5+6,stack,zzempty)));  
+  KN<long> nrfdown (arg(6,stack,arg(6+6,stack,zzempty)));  
+  int point_confondus_ok (arg(7,stack,0L));
+  double precis_mesh (arg(8,stack,-1L));
+
+  
+  //if( nrtet.N() && nrfmid.N() && nrfup.N() && nrfdown.N() ) return m;
+  ffassert( nrtet.N() %2 ==0);
+  ffassert( nrfmid.N() %2 ==0);
+  ffassert( nrfup.N() %2 ==0);
+  ffassert( nrfdown.N() %2 ==0);
+  
+  // realisation de la map par default
+  
+  map< int, int > maptet; 
+  map< int, int > maptrimil, maptrizmax, maptrizmin;
+  map< int, int > mapemil, mapezmax, mapezmin;
+  
+  build_layer_map_tetrahedra( Th, maptet );
+  build_layer_map_triangle( Th, maptrimil, maptrizmax, maptrizmin );
+  build_layer_map_edge( Th, mapemil, mapezmax, mapezmin );
+    
+  // Map utilisateur
+  map< int, int > :: iterator imap;
+  for( int ii=0; ii < nrtet.N(); ii+=2){
+	imap = maptet.find(nrtet[ii]);
+	if( imap != maptet.end()){
+		imap -> second = nrtet[ii+1];
+	}
+  }  
+
+  for( int ii=0; ii < nrfmid.N(); ii+=2){
+	imap = maptrimil.find(nrfmid[ii]);
+	if( imap != maptrimil.end()){
+		imap -> second = nrfmid[ii+1];
+	}
+  }  
+  
+  for( int ii=0; ii < nrfup.N(); ii+=2){
+	imap = maptrizmax.find(nrfup[ii]);
+	if( imap != maptrizmax.end()){
+		imap -> second = nrfup[ii+1];
+	}
+  }  
+  
+  for( int ii=0; ii < nrfdown.N(); ii+=2){
+	imap = maptrizmin.find(nrfdown[ii]);
+	if( imap != maptrizmin.end()){
+		imap -> second = nrfdown[ii+1];
+	}
+  }  
+    
+  int nebn =0;
+  KN<int> ni(nbv);
+    double epsz = maxdz *1e-6;
+ if(verbosity>9999)    cout << "BuildLayeMesh_Op:: epsz " << epsz <<endl; 
+  for(int i=0;i<nbv;i++)
+    {
+      ni[i]=Max(0,Min(nlayer,(int) lrint(nlayer*clayer[i])));
+      if(abs(zmin[i]-zmax[i]) < epsz) ni[i]=0; // Corr FH aug. 2014...
+    }
+  if(verbosity>9999)    cout << " BuildLayeMesh_Op: ni = " << ni << endl; 
+  // triangle 
+  for (int it=0;it<nbt;++it){
+    const Mesh::Element &K(Th.t(it));
+    int i0 = Th.operator()(K[0]); 
+    int i1 = Th.operator()(K[1]); 
+    int i2 = Th.operator()(K[2]); 
+    
+    if( ni[i0] == 0 && ni[i1] == 0 && ni[i2] == 0 ){
+      cout << "A tetrahedra with null volume will be created with triangle " << it << " of 2D Mesh " << endl;
+      cout << "stop procedure of buildlayer" << endl;
+      exit(1);
+    }
+
+  }
+
+  // cas maillage volumique + surfacique
+  Mesh3 *Th3= build_layer(Th, nlayer, ni, zmin, zmax, maptet, maptrimil, maptrizmax, maptrizmin, mapemil, mapezmax, mapezmin);
+  // cas maillage surfacique simplement // A construire Jacques + donner le numero des edges que l'on veut pas creer � l'int�rieure
+    
+  
+  if( !(xx) && !(yy) && !(zz) )
+    {
+	 /*
+	  map< int, int > maptet; 
+	  map< int, int > maptrimil, maptrizmax, maptrizmin;
+	  map< int, int > mapemil, mapezmax, mapezmin;
+	   
+	  build_layer_map_tetrahedra( Th, maptet );
+	  build_layer_map_triangle( Th, maptrimil, maptrizmax, maptrizmin );
+	  build_layer_map_edge( Th, mapemil, mapezmax, mapezmin );
+	  
+	  Mesh3 *Th3= build_layer(Th, nlayer, ni, zmin, zmax, maptet, maptrimil, maptrizmax, maptrizmin, mapemil, mapezmax, mapezmin);
+	  */
+      
+     // Th3->BuildBound();
+     // Th3->BuildAdj();
+     // Th3->Buildbnormalv();  
+     // Th3->BuildjElementConteningVertex();
+      
+      Th3->BuildGTree(); //A decommenter
+
+      Add2StackOfPtr2FreeRC(stack,Th3);
+      *mp=mps;
+      return Th3;
+    }
+  else
+    {  
+      //Mesh3 *Th3= build_layer(Th, nlayer, ni, zmin, zmax);
+	  
+      KN<double> txx(Th3->nv), tyy(Th3->nv), tzz(Th3->nv);
+      KN<int> takemesh(Th3->nv);
+      //MeshPoint *mp3(MeshPointStack(stack)); 
+	  
+      takemesh=0;  
+      Mesh3 &rTh3 = *Th3;
+      for (int it=0;it<Th3->nt;++it){
+	for( int iv=0; iv<4; ++iv){
+	  int i=(*Th3)(it,iv);  
+	  if(takemesh[i]==0){
+	    mp->setP(Th3,it,iv);
+	    if(xx){ txx[i]=GetAny<double>((*xx)(stack));}
+	    if(yy){ tyy[i]=GetAny<double>((*yy)(stack));}
+	    if(zz){ tzz[i]=GetAny<double>((*zz)(stack));}
+
+	    takemesh[i] = takemesh[i]+1;
+	  }
+	}
+      }
+		
+      int border_only = 0;
+      int recollement_elem=0, recollement_border=1; 
+      if(point_confondus_ok == 2){
+	recollement_border = 0;
+	point_confondus_ok = 1;
+      }
+
+        Mesh3 *T_Th3=Transfo_Mesh3( precis_mesh, rTh3, txx, tyy, tzz, border_only, recollement_elem, recollement_border, point_confondus_ok,1);
+		  
+      
+      // T_Th3->BuildBound();
+      //  T_Th3->BuildAdj();
+      // T_Th3->Buildbnormalv();  
+      // T_Th3->BuildjElementConteningVertex();
+      
+      
+      T_Th3->BuildGTree(); //A decommenter
+      
+      delete Th3;
+      Add2StackOfPtr2FreeRC(stack,T_Th3);
+      *mp=mps;
+      return T_Th3;
+
+    }
+}
+
+
+// function nouveau nom de fonction
+
+class Movemesh2D_3D_surf_cout_Op : public E_F0mps 
+{
+public:
+  Movemesh2D_3D_surf_cout_Op(const basicAC_F0 &  args,Expression tth)  
+  {
+    CompileError("The keyword movemesh2D3Dsurf is remplaced now by the keyword movemesh23 (see Manual) ::: Moreover, the parameter mesuremesh are denoted now orientation ");
+  } 
+   AnyType operator()(Stack stack)const { return 0L; }
+  
+};
+
+
+
+
+class Movemesh2D_3D_surf_cout : public OneOperator { public:  
+typedef Mesh *pmesh;
+typedef Mesh3 *pmesh3;
+    
+  Movemesh2D_3D_surf_cout() : OneOperator(atype<pmesh3>(),atype<pmesh>() ) {}
+    E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new Movemesh2D_3D_surf_cout_Op(args,t[0]->CastTo(args[0]));  // CastTo(args[]); // plus tard
+  }
+};
+
+
+/***********************************************/
+
+class Movemesh3D_cout_Op : public E_F0mps 
+{
+ 
+public:
+  Movemesh3D_cout_Op(const basicAC_F0 &  args,Expression tth)  
+ 
+  {
+    CompileError("The keyword movemesh3D is remplaced in this new version of freefem++ by the keyword movemesh3 (see manual)");
+  } 
+  
+  AnyType operator()(Stack stack)  const {return 0L;}
+  
+};
+
+
+
+
+class Movemesh3D_cout : public OneOperator { public:  
+typedef Mesh *pmesh;
+typedef Mesh3 *pmesh3;
+    
+  Movemesh3D_cout() : OneOperator(atype<pmesh3>(),atype<pmesh>() ) {}
+    E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new Movemesh3D_cout_Op(args,t[0]->CastTo(args[0]));  // CastTo(args[]); // plus tard
+  }
+};
+
+
+//
+
+class DeplacementTab_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  //Expression xx,yy,zz;
+  static const int n_name_param =6; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+public:
+  DeplacementTab_Op(const basicAC_F0 &  args,Expression tth) 
+    : eTh(tth)  //, xx(0) , yy(0) , zz(0)
+  {
+    args.SetNameParam(n_name_param,name_param,nargs);
+   
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type DeplacementTab_Op::name_param[]= {
+  {  "deltax", &typeid(KN_<double>)},
+  {  "deltay", &typeid(KN_<double>)},
+  {  "deltaz", &typeid(KN_<double>)},
+  {  "ptmerge", &typeid(double)},
+  {  "facemerge", &typeid(long)},
+  {  "boolsurface",&typeid(long)}
+};
+
+AnyType DeplacementTab_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  
+  ffassert(pTh);
+  Mesh3 &Th=*pTh;
+  Mesh3 *m= pTh;   // question a quoi sert *m ??
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int nbe=Th.nbe; // nombre d'aretes fontiere
+  if(verbosity>5)
+  cout << "before movemesh: Vertex " << nbv<< " Tetrahedra " << nbt << " triangles "<< nbe << endl; 
+ 
+ // lecture des references
+   
+  KN<double> zzempty;
+  KN<double> dx (arg(0,stack,zzempty));
+  KN<double> dy (arg(1,stack,zzempty));
+  KN<double> dz (arg(2,stack,zzempty));
+  double precis_mesh( arg(3,stack,1e-7));
+
+  ffassert( dx.N() == Th.nv);
+  ffassert( dy.N() == Th.nv);
+  ffassert( dz.N() == Th.nv);
+    
+  // realisation de la map par default
+ 
+  KN<double> txx(Th.nv), tyy(Th.nv), tzz(Th.nv);
+  // loop over tetrahedral 
+  for (int i=0;i<Th.nv;++i){   
+    txx[i]=Th.vertices[i].x+dx[i];
+    tyy[i]=Th.vertices[i].y+dy[i];
+    tzz[i]=Th.vertices[i].z+dz[i];
+  }
+  
+  int border_only = 0;
+  int recollement_elem=0;
+  int recollement_border,point_confondus_ok;
+  
+  int  mergefacemesh( arg(4,stack,0L) );
+  long  flagsurfaceall( arg(5,stack,1L) );
+
+   if(mergefacemesh == 0)
+    {
+      recollement_border=0;
+      point_confondus_ok=0;
+    }
+  if(mergefacemesh == 1)
+    { 
+      recollement_border=1;
+      point_confondus_ok=0;
+    }
+  if(mergefacemesh == 2)
+    { 
+      recollement_border=1;
+      point_confondus_ok=1;
+    }
+
+  Mesh3 *T_Th3=Transfo_Mesh3( precis_mesh,Th, txx, tyy, tzz, border_only, 
+			      recollement_elem, recollement_border, point_confondus_ok,1);
+  
+  if(nbt != 0)
+    {
+      //T_Th3->BuildBound();
+    
+      //T_Th3->BuildAdj();
+
+      if(flagsurfaceall==1) T_Th3->BuildBoundaryElementAdj();
+      
+      //T_Th3->Buildbnormalv();  
+
+     // T_Th3->BuildjElementConteningVertex();
+      
+      T_Th3->BuildGTree();
+      
+      //	T_Th3->decrement(); 
+    }
+  else
+    {
+       if(flagsurfaceall==1) T_Th3->BuildBoundaryElementAdj();
+    }
+  Add2StackOfPtr2FreeRC(stack,T_Th3);
+ 
+  *mp=mps;
+  return T_Th3;
+}
+
+class  DeplacementTab : public OneOperator { public:  
+    DeplacementTab() : OneOperator(atype<pmesh3>(),atype<pmesh3>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  {
+	return  new DeplacementTab_Op(args,t[0]->CastTo(args[0])); 
+  }
+
+};
+
+// CheckSurfaceMesh ==> 
+
+int  GetBEManifold( Expression bb,  Expression &label, Expression &orient);
+void GetNumberBEManifold( Expression surf, int & mani_nbe);
+
+void GetManifolds( Expression mani, int & nbcmanifold,  int * &mani_nbe, Expression * &manifold)
+{
+  if ( mani ) 
+    {
+      int i,j;
+      const E_Array * a= dynamic_cast<const  E_Array *>(mani);
+      ffassert(a);
+      int n = a->size();
+      if( verbosity>1) 
+	cout << "    the number of manifold " << n << endl;
+      
+      nbcmanifold = n;  // nombre de manifold d�finis
+      
+      //manifold = new Expression[n]; 
+      mani_nbe = new int[n];
+      int size = 0;
+      for ( i=0; i<n; i++){
+	GetNumberBEManifold( (*a)[i], mani_nbe[i]);
+	cout << "number of manifold = " << n << "manifold i=" << i << "nb BE label=" << mani_nbe[i] << endl;
+	size=size+mani_nbe[i];
+      }
+   
+      manifold = new Expression[size*2];
+      int count=0;
+      for ( i=0; i<n; i++){
+	Expression tmp=(*a)[i];
+	const E_Array * aa = dynamic_cast<const  E_Array *>( tmp );
+	for( j=0; j< mani_nbe[i]; j++){
+	  if(GetBEManifold( (*aa)[j], manifold[count], manifold[count+1] ) ==0)   
+	    CompileError(" a manifold is defined by a pair of [label, orientation ]");
+	  count=count+2;
+	}
+      }
+      assert(count == 2*size);
+    }  
+}
+
+void GetNumberBEManifold( Expression surf, int & mani_nbe)
+{
+  if ( surf ) 
+    {
+      int i,j;
+      if( verbosity>1) 
+	cout << "  -- Manifoldal Condition to do" << endl;
+      const E_Array * a= dynamic_cast<const  E_Array *>(surf);
+      ffassert(a);
+      mani_nbe = a->size();
+      
+    }
+}
+
+
+// void GetManifold( Expression surf, int & mani_nbe, Expression * &manifold)
+// {
+//   if ( surf ) 
+//     {
+//       int i,j;
+//       if( verbosity>1) 
+// 	cout << "  -- Manifoldal Condition to do" << endl;
+//       const E_Array * a= dynamic_cast<const  E_Array *>(surf);
+//       ffassert(a);
+//       int n = a->size()/2;
+//       mani_nbe = n;
+//       if( verbosity>1) 
+// 	cout << "    the number of face label in a manifold " << n << endl;
+//       if( n*2 != a->size() )
+// 	CompileError(" a manifold is defined by a pair of [label, orientation ]");
+//       manifold = new Expression[n*2]; 
+//       for ( i=0,j=0;i<n;i++,j+=2)
+// 	if (GetBEManifold((*a)[i],manifold[j],manifold[j+1])==0)
+// 	  CompileError(" a sub array of a sub manifold must be [label, orientation ]");
+//     }
+// }
+
+int GetBEManifold( Expression bb, Expression &label, Expression &orient)
+{
+  
+  const E_Array * a= dynamic_cast<const  E_Array *>(bb);
+  if( a &&  a->size() == 2 ){
+    label  =  to<long>((*a)[0]);
+    orient =  to<long>((*a)[1]);
+    
+    return 1;
+  }
+  else
+    return 0;
+}
+
+class CheckManifoldMesh_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  static const int n_name_param =1; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  int nbmanifold;
+  int *mani_nbe;
+  Expression *manifolds;
+
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+public:
+  CheckManifoldMesh_Op(const basicAC_F0 &  args,Expression tth) 
+    : eTh(tth)
+  {
+    args.SetNameParam(n_name_param,name_param,nargs);
+    if(nargs[0])   
+      GetManifolds(nargs[0],nbmanifold, mani_nbe, manifolds);
+    else
+      CompileError("check ::: no definition of manifold");
+   
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type CheckManifoldMesh_Op::name_param[]= {
+  {  "manifolds", &typeid(E_Array)}
+  // option a rajouter
+  // facemerge 0,1 + label
+};
+
+AnyType CheckManifoldMesh_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+
+
+  int size=0;
+  KN<int> BeginManifold(nbmanifold+1);
+  
+  for (int i=0; i< nbmanifold; i++){
+    BeginManifold[i]=size;
+    size=size+mani_nbe[i];
+  }
+  BeginManifold[nbmanifold]=size;
+  
+  KN<int> TabLabelManifold(size ), OrientLabelManifold(size );
+    
+  int count=0;
+  for (int i=0; i< nbmanifold; i++){
+    for(int j=0; j< mani_nbe[i]; j++){
+      TabLabelManifold   [count]  = GetAny< long > ( ( *manifolds[2*count] )(stack) ); 
+      OrientLabelManifold [count] = GetAny< long > ( ( *manifolds[2*count+1] )(stack) ); 
+      count++;
+    }
+  }
+  assert(count == size);
+
+//   int count=0;
+//   for(int ii=0; ii<nbvariete; ii++)
+//     {
+//       beginvariete[ii]=count;
+//       for(int jj=0; jj<labelvariete[ii]; jj++)
+// 	{
+// 	  TabLabelVariete    [count] = GetAny< long > ( (*surface[2*ii+1][2*jj])(stack) ); 
+// 	  OrientLabelVariete [count] = GetAny< long > ( (*surface[2*ii+1][2*jj+1])(stack) ); 
+// 	  count++;
+// 	}
+//     }
+//   beginvariete[nbvariete]=count;
+  
+  long resultat=1;
+  pTh->BuildBoundaryElementAdj( nbmanifold, BeginManifold,TabLabelManifold,OrientLabelManifold); // nbvariete, beginvariete, TabLabelVariete, OrientLabelVariete);
+  
+  cout << "utilisation V2" << endl;
+  *mp=mps;
+  return resultat;
+}
+      
+
+class  CheckManifoldMesh : public OneOperator { public:  
+    CheckManifoldMesh() : OneOperator(atype<long>(),atype<pmesh3>() ) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  {
+	return  new CheckManifoldMesh_Op(args,t[0]->CastTo(args[0])); 
+  }
+};
+
+
+
+
+Mesh3 * truncmesh(const Mesh3 &Th,const long &kksplit,int *split, bool kk, const int newbelabel);
+
+struct Op_trunc_mesh3 : public OneOperator {
+  typedef Mesh3 *pmesh3;
+  class Op: public E_F0mps   { 
+  public:
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =4;
+    Expression nargs[n_name_param];
+    
+    Expression getmesh,bbb;
+    long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    KN<long> *  arg(int i,Stack stack) const{ return nargs[i] ? GetAny<KN<long> *>( (*nargs[i])(stack) ): 0;}
+      
+    Op(const basicAC_F0 &  args,Expression t,Expression b) : getmesh(t),bbb(b) 
+    { args.SetNameParam(n_name_param,name_param,nargs); }
+    AnyType operator()(Stack s)  const ;
+  };
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { return new Op(args,t[0]->CastTo(args[0]),t[1]->CastTo(args[1])); }
+  Op_trunc_mesh3() : 
+    OneOperator(atype<pmesh3>(),atype<pmesh3>(),atype<bool>()) {};     
+};
+
+basicAC_F0::name_and_type Op_trunc_mesh3::Op::name_param[Op_trunc_mesh3::Op::n_name_param] =
+ {
+   {  "split",             &typeid(long)},
+   {  "label",             &typeid(long)},
+     { "new2old", &typeid(KN<long>*)},  //  ajout FH pour P. Jovilet jan 2014
+     { "old2new", &typeid(KN<long>*)}   //  ajout FH pour P. Jovilet jan 2014
+
+ };
+
+
+Mesh3 * truncmesh(const Mesh3 &Th,const long &kksplit,int *split, bool kk, const int newbelabel)
+{
+    
+    static const int FaceTriangle[4]={3,0,1,2};  //={{3,2,1}, {0,2,3},{ 3,1,0},{ 0,1,2}}
+    
+    
+    // computation of number of border elements and vertex without split
+    int nbe = 0;
+    int nt  = 0;
+    int nv  = 0;
+    int nvtrunc =0;
+    int nedge=0;
+    int nface=0;
+    double hmin=1e100;
+    R3 bmin,bmax;
+    int nbeee=0,nbfi=0;
+    const int kksplit2 = kksplit*kksplit;
+    const int kksplit3 = kksplit2*kksplit;
+    int ntsplit =0;
+    int tagb[4]={1,2,4,8} ;
+    KN<int> tagTonB(Th.nt);
+    tagTonB=0;
+    
+    for( int ibe=0; ibe < Th.nbe; ibe++)
+    {
+        int iff;
+        int it=Th.BoundaryElement(ibe,iff);
+        tagTonB[it]|= tagb[iff];
+        int ifff=iff,itt=Th.ElementAdj(it,ifff);
+        if(itt >=0 &&  itt != it)
+            tagTonB[itt]|= tagb[ifff];
+    }
+    
+    for (int i=0;i<Th.nt;i++)
+        if(split[i])
+        {
+            ++ntsplit;
+            // computation of number of tetrahedrons
+            nt=nt+kksplit3;
+            // computation of number of border elements
+            for (int j=0;j<4;j++)
+            {
+                int jt=j,it=Th.ElementAdj(i,jt);
+                if ( (it==i || it <0)  || ! split[it]) nbeee++;// boundary face ...
+                else nbfi++; // internal face count 2 times ...
+                if(it==i || it <0) nbe += kksplit2;  //on est sur la frontiere
+                else if (!split[it]) nbe += kksplit2; //le voisin ne doit pas etre decoupe
+                else if ( (tagTonB[i]&tagb[j] ) != 0 && i<it) nbe += kksplit2; // internal boundary ..
+            }
+            
+            for (int e=0;e<6;e++){
+                hmin=min(hmin,Th[i].lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+            }
+        }
+    ffassert( nbfi %2 ==0) ;
+    nface = nbeee + nbfi/2;
+    double hseuil = (hmin/kksplit)/1000.;
+    if(verbosity>5)
+        cout << "  number of  not intern boundary faces = " << nbeee << ",  all faces  =  " << nbe << ", hseuil=" << hseuil <<endl;
+    
+    /* determination de bmin, bmax et hmin */
+    
+    KN<int> takevertex(Th.nv,-1);
+    
+    for(int i=0; i<Th.nt; i++){
+        if(split[i])
+        {
+            const Tet &K(Th.elements[i]);
+            for(int ii=0; ii<4; ii++)
+            {
+                int iv= Th.operator()( K[ii] );
+                if( takevertex[iv] == -1 )
+                {
+                    bmin=Minc(Th.vertices[iv],bmin);
+                    bmax=Maxc(Th.vertices[iv],bmax);
+                    takevertex[iv]=nvtrunc++;
+                }
+            }
+            
+        }
+    }
+    
+    if( kksplit > 1 )
+    { // compute the number of slip edge ...
+        nedge=0;
+        HashTable<SortArray<int,2>,int> edges(3*nface,nface);
+        for(int i=0; i<Th.nt; i++){
+            if(split[i])
+            {
+                const Tet &K(Th.elements[i]);
+                for(int e=0;e<6;++e)
+                {
+                    
+                    int e1 = Th( K[ Th[i].nvedge[e][0] ] );
+                    int e2 = Th( K[ Th[i].nvedge[e][1] ] );
+                    SortArray<int,2> key(e1,e2);
+                    if(!edges.find(key) )
+                        edges.add(key,nedge++);
+                }
+            }
+        }
+    }
+    if(verbosity>10) cout << "    -- nvertex  " << nvtrunc << ", nedges = "<< nedge
+        << ", nfaces = " << nface << " ntet =" << ntsplit
+        << endl
+        << "    -- Euler/Poincare constante = " << nvtrunc-nedge+nface-ntsplit
+        << endl;
+    
+    /* determination des vertex, triangles et tetrahedre obtenue apres splitting dans le Simplex */
+    
+    int nfacesub = kksplit2;
+    int ntetsub = kksplit3;
+    int nvsub = (kksplit+1)*(kksplit+2)*(kksplit+3)/6;
+    int ntrisub = 4*kksplit2;
+    
+    R3 *vertexsub; //[nvsub];
+    int *tetsub;   //[4*ntetsub];
+    int *trisub;   //[4*kksplit*kksplit];
+    
+    SplitSimplex<R3>( kksplit, nvsub, vertexsub, ntetsub, tetsub);
+    SplitSurfaceSimplex( kksplit, ntrisub, trisub);
+    
+    if(verbosity>3)
+        cout << "  -- trunc (3d) : Th.nv= " << Th.nv << "kksplit="<< kksplit << endl;
+    
+    int ntnosplit  = nt/kksplit3;
+    int nbenosplit = nbe/kksplit2;
+    int nfacenosplit = (4*ntnosplit+nbenosplit)/2;
+    nv = ntnosplit*(nvsub - 4*( (kksplit+1)*(kksplit+2)/2 - 3*(kksplit-1) -3 ) - 6*( kksplit-1 ) - 4);
+    if(verbosity>100) cout << "       1) nv= " << nv << endl;
+    nv = nv + nfacenosplit*( (kksplit+1)*(kksplit+2)/2 - 3*(kksplit-1) -3 );
+    if(verbosity>100) cout << "       2) nv= " << nv << endl;
+    nv = nv + nedge*( kksplit-1 );
+    if(verbosity>100) cout << "       3) nv= " << nv << endl;
+    nv = nv + nvtrunc;
+    if(verbosity>100) cout << "       4) nv= " << nv << endl;
+    
+    
+    
+    int itt=0;
+    int ie=0;
+    
+    
+    Vertex3 *v=new Vertex3[nv];
+    Tet *t = new Tet[nt];
+    Tet *tt = t;
+    
+    Triangle3 *b  = new Triangle3[nbe];
+    Triangle3 *bb = b;
+    R3 hh = (bmax-bmax)/10.;
+    EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(v,bmin-hh,bmax+hh,0);
+    const R3 * pP[4];
+    int np=0; // nb of new points .. 
+
+    {
+        KN<R3>  vertextetsub(nvsub);
+        KN<int> newindex (nvsub);
+        
+        for(int i=0; i<Th.nt; i++)
+            if(split[i])
+            {
+                const Tet &K(Th.elements[i]);
+                
+                for(int ii=0; ii< 4; ii++)
+                    pP[ii] = & K[ii];
+                
+                for( int iv=0; iv<nvsub; iv++)
+                    (R3&) vertextetsub[iv]= vertexsub[iv].Bary(pP);
+                
+                for( int iv=0; iv<nvsub; iv++)
+                {
+                    Vertex3 * pvi=gtree->ToClose(vertextetsub[iv],hseuil);
+                    
+                    if(!pvi)
+                    {
+                        (R3&) v[np]   = vertextetsub[iv];
+                        v[np].lab = K.lab;
+                        newindex[iv] = np;
+                        gtree->Add( v[np] );
+                        np++;
+                    }
+                    else
+                        newindex[iv] = pvi-v;
+                    
+                    ffassert( np <= nv );
+                }
+                
+                for( int ii=0; ii<ntetsub; ii++)
+                {
+                    int ivt[4];
+                    for( int jj=0; jj< 4; jj++)
+                    {
+                        ivt[jj] = newindex[tetsub[4*ii+jj]];
+                        assert( tetsub[4*ii+jj] < nvsub );
+                        assert( ivt[jj] < np );
+                    }
+                    (tt++)->set( v, ivt, K.lab);
+                    itt++;
+                    assert( itt <= nt );
+                }
+                
+                for (int j=0;j<4;j++)
+                {
+                    int jt=j,it=Th.ElementAdj(i,jt);
+                    
+                    if ( ( (tagTonB[i]&tagb[j]) ==0 ) &&  !(it==i || it <0)  && !split[it])
+                    {
+                        // new border not on boundary
+                        int ivb[3];
+                        
+                        for( int ii=0; ii<nfacesub; ii++)
+                        {
+                            int iface = 3*FaceTriangle[j]*nfacesub+3*ii;
+                            
+                            for( int jjj=0; jjj<3; jjj++)
+                            {
+                                ivb[jjj] = newindex[ trisub[iface+jjj] ];
+                                assert( trisub[ iface+jjj ] < nvsub );
+                                assert( ivb[jjj] < np );
+                            }
+                            
+                            (bb++)->set( v, ivb, newbelabel);
+                            ie++;
+                        }
+                    }
+                    assert( ie <= nbe);
+                    
+                }
+            }
+    }
+    if(verbosity>10)
+        cout  << "    ++ np=" << np << "==  nv=" << nv << endl;
+    ffassert( np == nv); 
+    if(verbosity>8)
+        cout << "   -- Number of new  border face not on Border " << ie << endl;
+    delete [] vertexsub; //[nvsub];
+    delete [] tetsub;   //[4*ntetsub];
+    delete [] trisub;   //[4*kksplit*kksplit];
+    
+    // split border elements
+    int nv2Dsub   = (kksplit+1)*(kksplit+2)/4;
+    int ntri2Dsub = kksplit2;
+    R2 *vertex2Dsub; //[nvsub];
+    int *tri2Dsub;   //[4*kksplit*kksplit];
+    
+    SplitSimplex<R2>( kksplit, nv2Dsub, vertex2Dsub, ntri2Dsub, tri2Dsub);
+    
+    
+    for( int ibe=0; ibe < Th.nbe; ibe++)
+    {
+        int iff;
+        int it=Th.BoundaryElement(ibe,iff);
+        int ifff=iff,itt=Th.ElementAdj(it,ifff);
+        if(itt<0) itt=it;
+        if( split[it] == 0 && split[itt] == 0) continue; // boundary not on one element
+        
+        const Triangle3 &K(Th.be(ibe));
+        int ivv[3];
+        
+        ivv[0] = Th.operator()(K[0]);
+        ivv[1] = Th.operator()(K[1]);
+        ivv[2] = Th.operator()(K[2]);
+        
+        R3 *vertextrisub = new R3  [nv2Dsub];
+        int *newindex = new int[nv2Dsub];
+        for( int iv=0; iv<nv2Dsub; iv++)
+        {
+            double alpha=vertex2Dsub[iv].x;
+            double beta=vertex2Dsub[iv].y;
+            
+            vertextrisub[iv].x = (1-alpha-beta)*Th.vertices[ivv[0]].x + alpha*Th.vertices[ivv[1]].x + beta*Th.vertices[ivv[2]].x;
+            vertextrisub[iv].y = (1-alpha-beta)*Th.vertices[ivv[0]].y + alpha*Th.vertices[ivv[1]].y + beta*Th.vertices[ivv[2]].y;
+            vertextrisub[iv].z = (1-alpha-beta)*Th.vertices[ivv[0]].z + alpha*Th.vertices[ivv[1]].z + beta*Th.vertices[ivv[2]].z;
+            
+        }
+        
+        for( int iv=0; iv<nv2Dsub; iv++)
+        {
+            const Vertex3 &vi( vertextrisub[iv] );
+            Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+            assert(pvi);
+            newindex[iv] = pvi-v;
+        }
+        
+        for( int ii=0; ii<nfacesub; ii++)
+        {
+            int ivb[3];
+            for( int jjj=0; jjj<3; jjj++)
+            {
+                ivb[jjj] = newindex[ tri2Dsub[3*ii+jjj] ];
+                assert( tri2Dsub[ 3*ii+jjj  ] < nvsub );
+                if(verbosity > 199 ) cout << "        " << ivb[jjj] << " np:" << np<< endl;
+                assert( ivb[jjj] < np );
+            }
+            
+            (bb++)->set( v, ivb, K.lab);
+            ie++;
+            assert( ie <= nbe);
+        }
+        delete [] vertextrisub;
+        delete [] newindex;
+        
+        
+    }
+    
+    delete [] vertex2Dsub;   //[4*ntetsub];
+    delete [] tri2Dsub;   //[4*kksplit*kksplit];
+    
+    
+    if(verbosity>99)
+    {
+        cout << "nbofv initial" << Th.nv << endl;
+        cout << "nv=" << nv << " np=" << np << endl;
+        cout << "itt=" << itt << " nt=" << nt << endl;
+        cout << "ie=" << ie << " nbe=" << nbe << endl;
+    }
+    ffassert( nv == np );
+    ffassert( ie ==nbe);
+    ffassert( itt == nt );
+    
+    //delete gtree;
+    
+    Mesh3 *Tht = new Mesh3( nv, nt, nbe, v, t, b);
+    Tht->BuildGTree(); // Add JM. Oct 2010
+    delete gtree;
+    
+    
+    return Tht;
+}
+
+
+AnyType Op_trunc_mesh3::Op::operator()(Stack stack)  const {
+    
+  Mesh3 *pTh = GetAny<Mesh3 *>((*getmesh)(stack));
+  Mesh3 &Th = *pTh;
+  long kkksplit =arg(0,stack,1L);
+  long label =arg(1,stack,2L);
+   KN<long> * pn2o =  arg(2,stack);
+KN<long> * po2n =  arg(3,stack);
+
+  KN<int> split(Th.nt);
+  split=kkksplit;
+  MeshPoint *mp= MeshPointStack(stack),mps=*mp;
+  long kk=0;
+  long ks=kkksplit*kkksplit*kkksplit;
+  for (int k=0;k<Th.nt;k++)
+    { 
+      const Tet & K( Th.elements[k] );
+      R3 B(1./4.,1./4.,1./4.);  // 27/09/10 : J.Morice error in msh3.cpp
+      mp->set(Th,K(B),B,K,0);
+      if (  GetAny<bool>( (*bbb)(stack) )  ) kk++;
+      else  split[k]=0  ;    
+    }
+  //*mp=mps;
+  if (verbosity>1) 
+    cout << "  -- Trunc mesh: Nb of Tetrahedrons = " << kk << " label=" <<label <<endl;
+  Mesh3 * Tht = truncmesh(Th,kkksplit,split,false,label);
+  
+    if(pn2o)
+    {
+        pn2o->resize(kk*ks);
+        KN<long> &n2o(*pn2o);
+        int l=0;
+        for(int k=0; k< Th.nt; ++k)
+            if( split[k] )
+                for(int i=0; i< ks; ++i)
+                    n2o[l++] = k;
+    }
+    if(po2n)
+    {
+        po2n->resize(Th.nt);
+        KN<long> &o2n(*po2n);
+        int l=0;
+        for(int k=0; k< Th.nt; ++k)
+            if( split[k] )
+            {
+                o2n[k] = l;
+                l+=ks;
+            }
+            else o2n[k]=-1;
+    }
+
+  Add2StackOfPtr2FreeRC(stack,Tht);//  07/2008 FH
+  *mp=mps;
+  return Tht;
+ };
+ 
+//////////////////
+// new functions added by J. Morice 05/10
+//  --  extractmesh2D
+//  --  extractmesh
+//  --  movemesh32       // projection
+
+class ExtractMesh2D_Op : public E_F0mps 
+	{
+	public:
+		Expression eTh;
+		static const int n_name_param = 4; // 
+		static basicAC_F0::name_and_type name_param[] ;
+		Expression nargs[n_name_param];
+		KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+		{ return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+	        KN_<long>  arg(int i,int j,Stack stack,KN_<long> a ) const
+	        { 
+		  if( nargs[i]) 
+		    return GetAny<KN_<long> >( (*nargs[i])(stack) );
+		  else 
+		    return nargs[j] ? GetAny<KN_<long> >( (*nargs[j])(stack) ): a;
+		}
+		double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+		//long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+		long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+	public:
+		ExtractMesh2D_Op(const basicAC_F0 &  args,Expression tth) 
+		: eTh(tth)
+		{
+			if(verbosity >1) cout << "construction par ExtractMesh_Op" << endl;
+			args.SetNameParam(n_name_param,name_param,nargs); 
+			if( nargs[1] && nargs[3] ) 
+			  CompileError("uncompatible extractmesh (Th, region= , reft=  ");
+			if( nargs[0] && nargs[2] ) 
+			  CompileError("uncompatible extractmesh (Th, label= , refe=  ");
+		} 
+		
+		AnyType operator()(Stack stack)  const ;
+	};
+
+basicAC_F0::name_and_type ExtractMesh2D_Op::name_param[]= {
+{  "refe", &typeid(KN_<long>)},
+{  "reft", &typeid(KN_<long>)},
+{  "label", &typeid(KN_<long>)},
+{  "region", &typeid(KN_<long>)}
+};
+
+
+class   ExtractMesh2D : public OneOperator { public:  
+    ExtractMesh2D() : OneOperator(atype<pmesh>(),atype<pmesh>()) {}
+	
+	E_F0 * code(const basicAC_F0 & args) const 
+	{
+		return  new ExtractMesh2D_Op(args,t[0]->CastTo(args[0])); 
+	}
+};
+
+AnyType ExtractMesh2D_Op::operator()(Stack stack)  const 
+{
+	MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+	Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+	Mesh &Th=*pTh;
+	
+	int nbv=Th.nv; // nombre de sommet 
+	int nbt=Th.nt; // nombre de triangles
+	int nbe=Th.neb; // nombre d'aretes fontiere
+	
+	KN<long> zzempty(0);
+	// recuperation des labels pour les surfaces et les elements
+	KN<long> labelface (arg(0,2,stack,zzempty));  
+	KN<long> labelelement (arg(1,3,stack,zzempty));  
+	
+	// a trier les tableaux d'entier 
+	
+	int nv=0, nt=0, ns=0;
+	int boolsurf=0;
+	int boolelement=0;
+	if( nargs[0] || nargs[2]){
+	  boolsurf=1;
+	}
+	if( nargs[1] || nargs[3]){
+	  boolelement=1;
+	  if( boolsurf == 0){ 
+	    cerr << "we need edge label to extract the mesh "<< " (This will be changed in a new version of freefem++)" << endl;
+	    exit(1);
+	  }
+	  // a prevoir une fonction pour recalculer les differents labels des surfaces	  
+	}
+	
+	if( boolsurf==1 && boolelement==1 ){
+		// Volumetric mesh
+		
+		KN<int> takevertex(Th.nv,-1);
+		KN<int> takeelem(Th.nt,0);
+		KN<int> takebe(Th.neb,0);
+		int neLab=0;
+		for(int ie=0; ie<Th.nt; ie++){
+		  const Mesh::Triangle & K(Th.t(ie));			
+		  for(int ii=0; ii<labelelement.N(); ii++){
+		    if( K.lab == labelelement[ii] ){
+		      neLab++;
+		      takeelem[ie] = 1;
+		      for(int jj=0; jj<3; jj++){
+			if( takevertex[ Th.operator()(K[jj]) ] != -1) continue;
+			takevertex[ Th.operator()(K[jj]) ] = nv;
+			nv++;
+		      }
+		      break;		      
+		    }
+		  }
+		}
+		
+		
+		int nbeLab=0;
+		for(int ibe=0; ibe<Th.neb; ibe++){
+		  const Mesh::BorderElement & K(Th.be(ibe));			
+		  for(int ii=0; ii<labelface.N(); ii++){
+		    if( K.lab == labelface[ii] ){
+		      nbeLab++;
+		      takebe[ibe] = 1;
+		      for(int jj=0; jj<2; jj++){
+			if( takevertex[ Th.operator()(K[jj]) ] == -1){
+			  cerr << "Volumetric extract mesh: error in the definition of surface mesh " <<endl;
+			  cerr << "The edges of label "<< labelface[ii]  << " is not the extract mesh " << endl;
+			}
+		      }
+		      break;
+		    }
+		  }
+		}
+		
+		ns = nbeLab;
+		nt = neLab;
+		
+		if( nt == 0) { cerr << " The label of 2D element is not correct :: there is no element" << endl; exit(1); } 
+		Mesh::Vertex   *v  = new Mesh::Vertex[nv]; 
+		Mesh::Triangle *t  = new Mesh::Triangle[nt];
+		Mesh::Triangle *tt = t;
+		Mesh::BorderElement *b  = new Mesh::BorderElement[ns];
+		Mesh::BorderElement *bb = b;
+		
+		for(int ii=0; ii<Th.nv; ii++){
+		  if( takevertex[ ii ] == -1) continue;
+		  int iv = takevertex[ii];
+		  assert(iv>=0 && iv< nv);
+		  v[iv].x = Th.vertices[ii].x;
+		  v[iv].y = Th.vertices[ii].y;
+		  v[iv].lab = Th.vertices[ii].lab;
+		}
+		
+		for(int ie=0; ie<Th.nt; ie++){
+		  if( takeelem[ ie ] != 1) continue;
+		  const Mesh::Triangle & K(Th.t(ie));	
+		  int ivv[3];
+		  for(int jj=0; jj<3; jj++) ivv[jj] =  takevertex[ Th.operator()(K[jj]) ];      
+		  (tt++)->set(v,ivv[0],ivv[1],ivv[2],K.lab);
+		}
+		
+		
+		for(int ibe=0; ibe<Th.neb; ibe++){
+		  if( takebe[ ibe ] != 1) continue;
+		  const Mesh::BorderElement &K( Th.be(ibe) );
+		  int ivv[2];
+		  for(int jj=0; jj<2; jj++) ivv[jj] =  takevertex[ Th.operator()(K[jj]) ];      
+		  (bb++)->set(v,ivv[0],ivv[1],K.lab);
+		}
+		
+		
+		Mesh *pThnew = new Mesh(nv,nt,ns,v,t,b);  // attention aux composantes connexes.
+		//Lorenzo
+		R2 Pn,Px;
+		pThnew->BoundingBox(Pn,Px);
+		if(!pThnew->quadtree)
+			pThnew->quadtree=new Fem2D::FQuadTree(pTh,Pn,Px,pTh->nv);
+		//Lorenzo
+				
+		return pThnew;
+		
+	}
+	
+	
+	
+	
+	if( boolsurf==1 && boolelement==0 ){
+		// case only surface mesh
+		// demander � F. pour la pertinence
+		KN<int> takevertex(Th.nv,-1);
+		KN<int> takebe(Th.neb,0);
+		int nbeLab=0;
+		for(int ibe=0; ibe<Th.neb; ibe++){
+		  const Mesh::BorderElement & K(Th.be(ibe));			
+		  for(int ii=0; ii<labelface.N(); ii++){
+		    if( K.lab == labelface[ii] ){
+		      nbeLab++;
+		      takebe[ibe] = 1;
+		      for(int jj=0; jj<2; jj++){
+			if( takevertex[ Th.operator()(K[jj]) ] != -1) continue;
+			takevertex[ Th.operator()(K[jj]) ] = nv;
+			nv++;
+		      }
+		      break;
+		    }
+		  }
+		}
+		
+		ns = nbeLab;
+		
+		Mesh::Vertex        *v  = new Mesh::Vertex[nv]; 
+		Mesh::BorderElement *b  = new Mesh::BorderElement[ns];
+		Mesh::BorderElement *bb = b;
+		
+		for(int ii=0; ii<Th.nv; ii++){
+			if( takevertex[ ii ] == -1) continue;
+			int iv = takevertex[ii];
+			assert(iv>=0 && iv< nv);
+			v[iv].x = Th.vertices[ii].x;
+			v[iv].y = Th.vertices[ii].y;
+			v[iv].lab = Th.vertices[ii].lab;
+		}
+		
+		for(int ibe=0; ibe<Th.neb; ibe++){
+		  if( takebe[ ibe ] != 1) continue;
+		  const Mesh::BorderElement &K( Th.be(ibe) );
+		  int ivv[2];
+		  for(int jj=0; jj<2; jj++) ivv[jj] =  takevertex[ Th.operator()(K[jj]) ];      
+		  (bb++)->set(v,ivv[0],ivv[1],K.lab);
+		}
+		
+		
+		Mesh *pThnew =0; //= new Mesh(nv,ns,v,b);  // a definir
+		// attention aux composantes connexes.
+		ffassert(0); 
+		
+		return pThnew;
+		
+	}
+	return (Mesh*) 0;
+	
+}
+
+//////////////////////////////////
+//
+//
+//      Fin du 2D
+//
+//
+//////////////////////////////////
+
+//////////////////////////////////
+//
+//
+//      Debut du 3D
+//
+//
+///////////////////////////////////////////////////////////
+//  recuperer une partie du maillage � l'aide des labels
+
+class ExtractMesh_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  static const int n_name_param = 4; // 
+  static basicAC_F0::name_and_type name_param[];
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<long>  arg(int i,int j,Stack stack,KN_<long> a ) const
+  { 
+    if( nargs[i]) 
+      return GetAny<KN_<long> >( (*nargs[i])(stack) );
+    else 
+      return nargs[j] ? GetAny<KN_<long> >( (*nargs[j])(stack) ): a;
+  }
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long    arg(int i,Stack stack,long a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+public:
+  ExtractMesh_Op(const basicAC_F0 &  args,Expression tth) 
+    : eTh(tth)
+  {
+    if(verbosity >1) cout << "construction par ExtractMesh_Op" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);    
+
+    if( nargs[1] && nargs[3] ) 
+      CompileError("uncompatible extractmesh (Th, region= , reftet=  ");
+    if( nargs[0] && nargs[2] ) 
+      CompileError("uncompatible extractmesh (Th, label= , refface=  ");
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type ExtractMesh_Op::name_param[]= {
+  {  "refface", &typeid(KN_<long>)},
+  {  "reftet", &typeid(KN_<long>)},
+  {  "label", &typeid(KN_<long>)},
+  {  "region", &typeid(KN_<long>)},
+};
+
+
+class   ExtractMesh : public OneOperator { public:  
+    ExtractMesh() : OneOperator(atype<pmesh3>(),atype<pmesh3>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  {
+    return  new ExtractMesh_Op(args,t[0]->CastTo(args[0])); 
+  }
+};
+
+AnyType ExtractMesh_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 *pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  Mesh3  &Th=*pTh;
+  
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int nbe=Th.nbe; // nombre d'aretes fontiere
+  
+  KN<long> zzempty(0);
+  KN<long> labelface (arg(0,2,stack,zzempty));  
+  KN<long> labelelement  (arg(1,3,stack,zzempty));  
+ 
+  // a trier les tableaux d'entier 
+
+  int nv=0, nt=0, ns=0;
+  int boolsurf=0;
+  int boolelement=0;
+  if( nargs[0] || nargs[2] ){
+    boolsurf=1;
+  }
+  if( nargs[1] || nargs[3] ){
+    boolelement=1;
+  }
+  cout << " labelface.N()  " << labelface.N() << endl;
+  for(int ii=0; ii<labelface.N(); ii++)
+    cout << ii << " " << labelface[ii] << endl;
+ 
+  cout << " labelelement.N()  " << labelelement.N() << endl;
+  for(int ii=0; ii<labelelement.N(); ii++)
+    cout << ii << " " << labelelement[ii] << endl;
+
+
+  if( boolsurf==1 && boolelement==1 ){
+    // case only surface mesh
+    KN<int> takevertex(Th.nv,-1);
+    KN<int> takeelem(Th.nt,0);
+    KN<int> takebe(Th.nbe,0);
+    int neLab=0;
+
+    for(int ie=0; ie<Th.nt; ie++){
+      const Tet & K(Th.elements[ie]);		
+      for(int ii=0; ii<labelelement.N(); ii++){
+	if( K.lab == labelelement[ii] ){	  
+	  neLab++;
+	  takeelem[ie] = 1;
+	  for(int jj=0; jj<4; jj++){
+	    if( takevertex[ Th.operator()(K[jj]) ] != -1) continue;
+	    takevertex[ Th.operator()(K[jj]) ] = nv;
+	    nv++;
+	  }
+	  break;
+	}
+      }
+    }
+        
+    int nbeLab=0;
+    for(int ibe=0; ibe<Th.nbe; ibe++){
+      const Triangle3 & K(Th.be(ibe));			
+      for(int ii=0; ii<labelface.N(); ii++){
+	if( K.lab == labelface[ii] ){
+	  nbeLab++;
+	  takebe[ibe] = 1;
+	  for(int jj=0; jj<3; jj++){
+	    if( takevertex[ Th.operator()(K[jj]) ] == -1){
+	      int iivv=Th.operator()(K[jj]);
+	      cerr << "Error(Extract Mesh):: the vertex ("<< Th.vertices[iivv].x  << ", " <<Th.vertices[iivv].y << ", " <<Th.vertices[iivv].z <<") is not in the volume mesh" << endl;
+	    }
+	    //continue;
+	    //takevertex[ Th.operator()(K[jj]) ] = nv;
+	    //nv++;
+	  }
+	  break;
+	}
+      }
+    }
+    
+    ns = nbeLab;
+    nt = neLab;
+    cout << nt <<" " << ns << endl;
+    if( nt == 0) { cerr << " The label of 3D element is not correct :: there is no element" << endl; exit(1); } 
+    Vertex3 *v  = new Vertex3[nv]; 
+    Tet *t  = new Tet[nt];
+    Tet *tt = t;
+    Triangle3 *b  = new Triangle3[ns];
+    Triangle3 *bb = b;
+    
+    for(int ii=0; ii<Th.nv; ii++){
+      if( takevertex[ ii ] == -1) continue;
+      int iv = takevertex[ii];
+      assert(iv>=0 && iv< nv);
+      v[iv].x = Th.vertices[ii].x;
+      v[iv].y = Th.vertices[ii].y;
+      v[iv].z = Th.vertices[ii].z;
+      v[iv].lab = Th.vertices[ii].lab;
+    }
+    
+    for(int ie=0; ie<Th.nt; ie++){
+      if( takeelem[ ie ] != 1) continue;
+      const Tet & K(Th.elements[ie]);	
+      int ivv[4];
+      for(int jj=0; jj<4; jj++) ivv[jj] =  takevertex[ Th.operator()(K[jj]) ];      
+      (tt++)->set(v,ivv,K.lab);
+    }
+		
+    
+    for(int ibe=0; ibe<Th.nbe; ibe++){
+      if( takebe[ ibe ] != 1) continue;
+      const Triangle3 &K( Th.be(ibe) );
+      int ivv[3];
+      for(int jj=0; jj<3; jj++) ivv[jj] =  takevertex[ Th.operator()(K[jj]) ];      
+      (bb++)->set(v,ivv,K.lab);
+    }
+    
+    
+    Mesh3 *pThnew = new Mesh3(nv,nt,ns,v,t,b);  // peut etre a définir ???
+    // attention aux composantes connexes.
+	pThnew->BuildGTree();  //Lorenzo
+    
+    return pThnew;
+    
+  }
+  
+  if( boolsurf==1 && boolelement==0 ){
+		
+		
+    KN<int> takevertex(Th.nv,-1);
+    for(int iv=0; iv<Th.nv; iv++) takevertex[iv]=-1;
+    KN<int> takebe(Th.nbe,-1);
+    for(int iv=0; iv<Th.nv; iv++) takebe[iv]=-1;
+    int nbeLab=0;
+    for(int ibe=0; ibe<Th.nbe; ibe++){
+      const Triangle3 &K( Th.be(ibe) );
+      
+      for(int ii=0; ii<labelface.N(); ii++){
+	
+	if( K.lab == labelface[ii] ){
+	  nbeLab++;
+	  cout << "takeface" << endl;
+	  takebe[ibe] = 1;
+	  for(int jj=0; jj<3; jj++){
+	    if( takevertex[ Th.operator()(K[jj]) ] != -1) continue;
+	    takevertex[ Th.operator()(K[jj]) ] = nv;
+	    nv++;
+	  }
+					
+	  //break;
+	}
+      }
+    }
+    
+    ns = nbeLab;
+    
+    Vertex3   *v  = new Vertex3[nv]; 
+    Triangle3 *b  = new Triangle3[ns];
+    Triangle3 *bb = b;
+    
+    for(int ii=0; ii<Th.nv; ii++){
+      if( takevertex[ ii ] == -1) continue;
+      int iv = takevertex[ii];
+      assert(iv>=0 && iv< nv);
+      v[iv].x = Th.vertices[ii].x;
+      v[iv].y = Th.vertices[ii].y;
+      v[iv].z = Th.vertices[ii].z;
+		  v[iv].lab = Th.vertices[ii].lab;
+    }
+    
+    for(int ibe=0; ibe<Th.nbe; ibe++){
+      if( takebe[ ibe ] != 1) continue;
+      const Triangle3 &K( Th.be(ibe) );
+      int ivv[3];
+      for(int jj=0; jj<3; jj++) ivv[jj] =  takevertex[ Th.operator()(K[jj]) ];      
+      (bb++)->set(v,ivv,K.lab);
+    }
+    
+    
+    cout <<" nv" << nv << " ns " << endl;  
+    Mesh3 *pThnew = new Mesh3(nv,ns,v,b);  
+	pThnew->BuildGTree();  //Lorenzo	
+    return pThnew;    
+  }
+   
+  Mesh3 *pThnew = NULL;
+  return pThnew;    
+}
+
+bool AddLayers(Mesh3 * const & pTh, KN<double> * const & psupp, long const & nlayer,KN<double> * const & pphi)
+{
+    ffassert(pTh && psupp && pphi);
+    const int nve = Mesh3::Element::nv;
+    Mesh3 & Th= *pTh;
+    const int nt = Th.nt;
+    const int nv = Th.nv;
+    
+    KN<double> & supp(*psupp);
+    KN<double> u(nv), s(nt);
+    KN<double> & phi(*pphi);
+    ffassert(supp.N()==nt);//P0
+    ffassert(phi.N()==nv); // P1
+    s = supp;
+    phi=0.;
+    // supp = 0.;
+    // cout << " s  " << s << endl;
+    
+    for(int step=0; step < nlayer; ++ step)
+    {
+        
+        
+        u = 0.;
+        for(int k=0; k<nt; ++k)
+            for(int i=0; i<nve; ++i)
+                u[Th(k,i)] += s[k];
+        
+        for(int v=0; v < nv; ++v)
+            u[v] = u[v] >0.;
+        // cout << " u  " << u << endl;
+        
+        phi += u;
+        
+        s = 0.;
+        for(int k=0; k<nt; ++k)
+            for(int i=0; i<nve; ++i)
+                s[k] += u[Th(k,i)];
+        
+        for(int k=0; k < nt; ++k)
+            s[k] = s[k] > 0.;
+        supp += s;
+        // cout << " s  " << s << endl;
+    }
+    // cout << " phi  " << phi << endl;
+    phi *= (1./nlayer);
+    // supp =s;
+    return true;
+}
+
+
+
+
+// because i include this file in tetgen.cpp (very bad)
+#ifndef WITH_NO_INIT
+
+static void Load_Init()
+{  
+  
+  Dcl_Type<listMesh3>();
+  typedef Mesh *pmesh;
+  typedef Mesh3 *pmesh3;
+  
+  if (verbosity && mpirank == 0)
+    cout << " load: msh3  " << endl;
+  
+  TheOperators->Add("+",new OneBinaryOperator_st< Op3_addmesh<listMesh3,pmesh3,pmesh3>  >      );
+  TheOperators->Add("+",new OneBinaryOperator_st< Op3_addmesh<listMesh3,listMesh3,pmesh3>  >      );
+  //TheOperators->Add("=",new OneBinaryOperator< Op3_setmesh<false,pmesh3*,pmesh3*,listMesh3>  >     );
+  //TheOperators->Add("<-",new OneBinaryOperator< Op3_setmesh<true,pmesh3*,pmesh3*,listMesh3>  >     );
+  
+  TheOperators->Add("=",new OneBinaryOperator_st< Op3_setmesh<false,pmesh3*,pmesh3*,listMesh3>  >     );
+  TheOperators->Add("<-",new OneBinaryOperator_st< Op3_setmesh<true,pmesh3*,pmesh3*,listMesh3>  >     );
+
+
+  Global.Add("change","(",new SetMesh3D);
+  Global.Add("movemesh23","(",new Movemesh2D_3D_surf);
+  Global.Add("movemesh2D3Dsurf","(",new Movemesh2D_3D_surf_cout);// 
+  Global.Add("movemesh3","(",new Movemesh3D);
+  Global.Add("movemesh","(",new Movemesh3D(1));
+  Global.Add("movemesh3D","(", new Movemesh3D_cout);
+  Global.Add("deplacement","(",new DeplacementTab);
+  Global.Add("checkbemesh","(",new CheckManifoldMesh);  
+  Global.Add("buildlayers","(",new  BuildLayerMesh);  
+  Global.Add("trunc","(", new Op_trunc_mesh3);
+
+  Global.Add("extract","(",new ExtractMesh);
+  Global.Add("extract","(",new ExtractMesh2D);
+    
+  Global.Add("AddLayers","(",new OneOperator4_<bool, Mesh3 * , KN<double> *,long, KN<double> * >(AddLayers));
+  typedef Mesh3 *pmesh3;
+ // Global.Add("trunc","(", new Op_trunc_mesh3);
+}
+LOADFUNC(Load_Init)
+#endif
+
diff --git a/examples++-load/msh3.hpp b/examples++-load/msh3.hpp
new file mode 100755
index 0000000..4944d91
--- /dev/null
+++ b/examples++-load/msh3.hpp
@@ -0,0 +1,106 @@
+#ifndef MSH3_HPP_
+#define MSH3_HPP_
+
+
+#include<iostream>
+#include<cmath>
+#include<cassert>
+#include <map>
+#include "Mesh2dn.hpp"
+#include "Mesh3dn.hpp"
+
+using namespace std;
+
+/* avant TransfoMesh_v2.cpp */
+void BuildBoundMinDist_th2( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh  & Th2, R3 &bmin, R3 &bmax, double &hmin);
+void BuildBoundMinDist_th3( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh3 & Th3, R3 &bmin, R3 &bmax, double &hmin);
+
+//void PointCommun_hcode( const int &dim, const int &NbPoints, const int &point_confondus_ok,double **Coord_Point, int * ind_np, int & np);
+void PointCommun_hcode( const int &dim, const int &NbPoints, const int &point_confondus_ok,double **Coord_Point, 
+const double *bmin, const double *bmax, const double hmin, int * ind_np, int & np);
+void PointCommun_hcode_gtree( const int &dim, const int &NbPoints, const int &point_confondus_ok, 
+	double **Coord_Point, const int * label_point,
+	const R3 & bmin, const R3 & bmax, const double &hmin, int * ind_np, int * ind_label, int & np);
+//void OrderVertexTransfo_base(const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh3 & Th3, int *Numero_Som, int * ind_nv_t, int & nv_t );
+
+void OrderVertexTransfo_hcode_nv(const int &tab_nv,const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+const double *bmin, const double *bmax, const double hmin, int *Numero_Som, int * ind_nv_t, int & nv_t );
+
+void OrderVertexTransfo_hcode_nv_gtree( const int & tab_nv, const R3 &bmin, const R3 &bmax, const double & hmin, 
+    const double *tab_XX, const double *tab_YY, const double *tab_ZZ, int *Numero_Som, int * ind_nv_t, int & nv_t);
+
+void SamePointElement( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh3 & Th3, 
+	int &recollement_element, int &recollement_border, int &point_confondus_ok,
+	int *Numero_Som, int *ind_nv_t, int *ind_nt_t, int *ind_nbe_t, int *label_nt_t, int *label_nbe_t, int & nv_t, int & nt_t,int & nbe_t );
+
+Mesh3 * Transfo_Mesh3(const double &precis_mesh, const Mesh3 & Th3, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, int &border_only, 
+	int &recollement_element, int &recollement_border, int &point_confondus_ok,int orientation);
+
+// CAS 3D surfacique
+
+void SamePointElement_surf( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh3 & Th3, 
+	int &recollement_border, int &point_confondus_ok, int *Numero_Som, 
+	int *ind_nv_t, int *ind_nbe_t, int *label_nbe_t, int & nv_t,int & nbe_t);
+
+Mesh3 * Transfo_Mesh3_surf(const double &precis_mesh, const Mesh3 & Th3, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+	int &recollement_border, int &point_confondus_ok);
+
+	
+// fonction pour le cas 2D
+
+void SamePointElement_Mesh2( const double &precis_mesh, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, const Mesh & Th2,
+	int &recollement_border, int &point_confondus_ok, int *Numero_Som, int *ind_nv_t, int *ind_nt_t, int *ind_nbe_t, 
+	int *label_nbe_t, int & nv_t, int & nt_t,int & nbe_t );
+
+// Mesh3 * Transfo_Mesh2(const Mesh2 & Th2, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, int &border_only);
+
+void Transfo_Mesh2_map_face(const Mesh &Th2, map<int, int> &maptri );
+
+Mesh3 * MoveMesh2_func( const double &precis_mesh, const Mesh & Th2, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+	int &border_only, int &recollement_border, int &point_confondus_ok);
+
+
+/* avant LayerMesh.cpp */
+void recollement_maillage_mesh(const int Nmax, const int N, int *tab_recollement);
+void dpent1_mesh(int idl[3],int nu[12],int &nbe,int &option);
+
+double  zmin_func_mesh( const int choix, const double x, const double y  );
+double  zmax_func_mesh( const int choix, const double x, const double y  );
+int       Ni_func_mesh( const int choix, const double x, const double y  );
+
+void tab_zmin_zmax_Ni_mesh(const int choix, const Mesh & Th2, int & Nmax,double *tab_zmin, double *tab_zmax,int *tab_Ni);
+
+void Tet_mesh3_mes_neg(Mesh3 & Th3);
+
+void build_layer_map_tetrahedra(const Mesh &Th2, map<int, int> &maptet );
+void build_layer_map_triangle(const Mesh &Th2, map<int, int> &maptrimil, map<int, int> &maptrizmax, map<int, int> &maptrizmin );
+void build_layer_map_edge(const Mesh &Th2, map<int, int> &mapemil, map<int, int> &mapezmax, map<int, int> &mapezmin );
+
+void NbSom3D_NbElem3D_NbBord2D_mesh_product_mesh_tab(const int Nmax, const int *tab_Ni, 
+						const Mesh &Th,  int &MajSom, int &MajElem, int &MajBord2D);
+
+void Som3D_mesh_product_Version_Sommet_mesh_tab(const int Nmax, const int *tab_Ni, const double *tab_zmin, 
+						const double *tab_zmax, const Mesh &Th2, 
+						const map<int, int> &maptet, 
+						const map<int, int> &maptrimil, const map<int, int> &maptrizmax, const map<int, int> &maptrizmin, 
+						const map<int, int> &mapemil, const map<int, int> &mapezmax, const map<int, int> &mapezmin,  Mesh3 & Th3);
+
+void transformation_2D_3D_maillage_mesh_tab(const Mesh & Th2, const int Nmax, const int *tab_Ni, const double *tab_zmin, const double *tab_zmax, Mesh3 & Th3);
+
+Mesh3 * build_layer (const Mesh & Th2, const int Nmax, const int *tab_Ni, const double *tab_zmin, const double *tab_zmax,
+			const map<int, int> &maptet, 
+			const map<int, int> &maptrimil, const map<int, int> &maptrizmax, const map<int, int> &maptrizmin, 
+			const map<int, int> &mapemil, const map<int, int> &mapezmax, const map<int, int> &mapezmin );
+
+
+// add 04/01/09
+void TestSameVertexMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int & nv_t, int *Numero_Som);
+void TestSameTetrahedraMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int & nt_t );
+void TestSameTetrahedraMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int *Elem_ok, int & nt_t );
+void TestSameTriangleMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int & nbe_t );
+void TestSameTriangleMesh3( const Mesh3 & Th3, const double & hseuil, const R3 & Psup, const R3 &Pinf, int *Border_ok ,int & nbe_t );
+int TestElementMesh3( const Mesh3 & Th3 );
+Mesh3 *TestElementMesh3_patch( const Mesh3 & Th3 );
+
+
+#endif
diff --git a/examples++-load/mshmet.cpp b/examples++-load/mshmet.cpp
new file mode 100644
index 0000000..d147e62
--- /dev/null
+++ b/examples++-load/mshmet.cpp
@@ -0,0 +1,757 @@
+// ORIG-DATE:     Fev 2010
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : liaison medit freefem++ : adaptmesh in 3d 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:  mshmet libMesh
+//ff-c++-cpp-dep:
+//  
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+// ./ff-c++ mshmet.cpp -I/Users/morice/Desktop/adaptmesh3d/mshmet.2009.09.16/sources -L/Users/morice/Desktop/adaptmesh3d/mshmet.2009.09.16/objects/i386/ -lmshmet -L/Users/morice/work/postdoc/freefem++prod/src/libMesh/ -lMesh
+
+// ./ff-c++ mshmet.cpp -I../download/include/mshmet/ -L../download/lib/mshmet/ -lmshmet -L/Users/morice/work/postdoc/freefem++prod/src/libMesh/ -lMesh
+
+#include "ff++.hpp" 
+#include "msh3.hpp"
+//#define ADAPTLIBRARY
+//#include "libmesh5.h"
+#include "mshmetlib.h"
+
+using namespace  Fem2D;
+using namespace  mshmet;
+
+// 2d mesh function
+//  Add FH thank to I. Bajc.  (iztok.bajc at fmf.uni-lj.si) 03/14
+//
+static void myMSHMET_free( MSHMET_pMesh mesh, MSHMET_pSol sol)
+{
+    /* free mem */
+    free(mesh->point);
+    if ( mesh->nt )  free(mesh->tria);
+    if ( mesh->ne )  free(mesh->tetra);
+    free(mesh->adja);
+    free(mesh);
+    free(sol->sol);
+    free(sol->met);
+    free(sol);
+   }
+
+MSHMET_pMesh mesh_to_MSHMET_pMesh( const Mesh &Th ){
+  MSHMET_pMesh meshMSHMET;
+  meshMSHMET = (MSHMET_pMesh)calloc(1,sizeof(MSHMET_Mesh)) ;
+  
+  meshMSHMET->dim = 2;
+  meshMSHMET->np = Th.nv;
+  meshMSHMET->nt = Th.nt;
+  meshMSHMET->ne = 0;
+
+  meshMSHMET->point = (MSHMET_pPoint)calloc(meshMSHMET->np+1,sizeof(MSHMET_Point));
+  meshMSHMET->tria = (MSHMET_pTria)calloc(meshMSHMET->nt+1,sizeof(MSHMET_Tria));
+  meshMSHMET->adja = (int*)calloc(3*meshMSHMET->nt+5,sizeof(int)); 
+  
+  int k;
+  MSHMET_pPoint ppt;
+  for (k=1; k<=meshMSHMET->np; k++) {
+    ppt = &meshMSHMET->point[k];
+    ppt->c[0] = Th.vertices[k-1].x;
+    ppt->c[1] = Th.vertices[k-1].y;
+    ppt->c[2] = 0.;
+    //ppt->mark  = Th.vertices[k-1].lab;
+  }
+
+ 
+  MSHMET_pTria ptriangle;
+  MSHMET_pPoint p0,p1,p2;
+  double       ux,uy,h1,h2,h3,pe,rins;
+  int i;
+  for (k=1; k<=meshMSHMET->nt; k++) {
+    const Mesh::Triangle  & K(Th.t(k-1));
+    ptriangle = &meshMSHMET->tria[k];
+    ptriangle->v[0] = Th.operator()(K[0])+1;
+    ptriangle->v[1] = Th.operator()(K[1])+1;
+    ptriangle->v[2] = Th.operator()(K[2])+1;
+    //ptriangle->mark = K.lab;
+
+    for (i=0; i<3; i++) {    
+      ppt = &meshMSHMET->point[ptriangle->v[i]];
+        if ( !ppt->s )  ppt->s = k;
+      }
+      p0 = &meshMSHMET->point[ptriangle->v[0]];
+      p1 = &meshMSHMET->point[ptriangle->v[1]];
+      p2 = &meshMSHMET->point[ptriangle->v[2]];
+
+      ux = p1->c[0] - p0->c[0];
+      uy = p1->c[1] - p0->c[1];
+      h1 = sqrt(ux*ux + uy*uy);
+
+      ux = p2->c[0] - p0->c[0];
+      uy = p2->c[1] - p0->c[1];
+      h2 = sqrt(ux*ux + uy*uy);
+
+      ux = p2->c[0] - p1->c[0];
+      uy = p2->c[1] - p1->c[1];
+      h3 = sqrt(ux*ux + uy*uy);
+      /*
+      pe        = 0.5 * (h1 + h2 + h3);
+      double aire = pe * (pe-h1) * (pe-h2) * (pe-h3);
+      //aire = sqrt(ptriangle->aire);
+      //rins      = 2.0 * aire / pe;
+
+      //p0->aire += ptriangle->aire;
+      //p0->rins += rins;
+
+      //p1->aire += ptriangle->aire;
+      //p1->rins += rins;
+
+      //p2->aire += ptriangle->aire;
+      //p2->rins += rins;
+      */
+  }
+  
+  return meshMSHMET;
+}
+
+
+// 3d mesh function
+
+MSHMET_pMesh mesh3_to_MSHMET_pMesh( const Mesh3 &Th3 ){
+  MSHMET_pMesh meshMSHMET;
+  meshMSHMET = (MSHMET_pMesh)calloc(1,sizeof(MSHMET_Mesh)) ;
+  
+  meshMSHMET->dim = 3;
+  meshMSHMET->np = Th3.nv;
+  meshMSHMET->nt = 0;
+  meshMSHMET->ne = Th3.nt;
+
+  meshMSHMET->point = (MSHMET_pPoint)calloc(meshMSHMET->np+1,sizeof(MSHMET_Point));
+  meshMSHMET->tetra = (MSHMET_pTetra)calloc(meshMSHMET->ne+1,sizeof(MSHMET_Tetra));
+  meshMSHMET->adja = (int*)calloc(4*meshMSHMET->ne+5,sizeof(int)); 
+  
+  int k;
+  MSHMET_pPoint ppt;
+  for (k=1; k<=meshMSHMET->np; k++) {
+    ppt = &meshMSHMET->point[k];
+    ppt->c[0] = Th3.vertices[k-1].x;
+    ppt->c[1] = Th3.vertices[k-1].y;
+    ppt->c[2] = Th3.vertices[k-1].z;
+    //ppt->mark  = 0; //Th3.vertices[k-1].lab;
+  }
+
+
+
+  int i;
+  MSHMET_pTetra ptetra;
+  for (k=1; k<=meshMSHMET->ne; k++) {
+    const Tet & K(Th3.elements[k-1]);
+    ptetra = &meshMSHMET->tetra[k];
+    ptetra->v[0] = Th3.operator()(K[0])+1;
+    ptetra->v[1] = Th3.operator()(K[1])+1;
+    ptetra->v[2] = Th3.operator()(K[2])+1;
+    ptetra->v[3] = Th3.operator()(K[3])+1;
+    //ptetra->mark = 0;//K.lab;
+    
+    for (i=0; i<4; i++) {
+      ppt = &meshMSHMET->point[ptetra->v[i]];
+      if ( meshMSHMET->dim == 3 && !ppt->s )  ppt->s = k;
+    }
+
+  }
+
+  return meshMSHMET;
+}
+
+
+
+MSHMET_pSol sol_mshmet(const int &dim, const int & np, const int &type, const int &size, int *typtab, const KN<double> &solutions){
+  static const int wrapperMetric[6]={0,1,3,2,4,5};
+  MSHMET_pSol sol;
+  int k,ia,i;
+
+  sol= (MSHMET_pSol)calloc(1,sizeof(MSHMET_Sol)) ;
+  sol->ver = 0;
+  sol->np  = np;
+  sol->dim = dim;
+  sol->type = type;      // nombre de solutions differentes
+  sol->size = size;
+  for(i=0; i<sol->type; i++)
+    sol->typtab[i] = typtab[i];  // types des differentes solutions
+
+  sol->sol = (double*) calloc(sol->np+1,sol->size*sizeof(double));
+  assert(sol->sol);
+
+  for (k=1; k<=sol->np; k++) {
+    ia = (k-1)*sol->size + 1;
+    for (i=0; i<sol->size; i++){
+      sol->sol[ia+i] = solutions[(ia-1)+i]; 
+    }
+  }
+
+  return sol;
+}
+
+void metric_mshmet( MSHMET_pSol sol, MSHMET_Info *info, const KN<double> &metric){
+  static const int wrapperMetric[6]={0,1,3,2,4,5};
+  int k,ia,i;
+  
+  cout << " info->iso " << info->iso << endl;
+  if( info->iso == 1 ){
+    cout << " info->iso 11 " << info->iso << endl;
+    sol->met = (double*)calloc(sol->np+1,sizeof(double));
+    assert(sol->met);
+    // isotrope
+    for (k=1; k<=sol->np; k++) {
+      sol->met[k] = metric[ k-1 ]; 
+    }
+  }
+  else{
+    // anisotropie :: Hessian
+    sol->met = (double*)calloc(sol->np+1,6*sizeof(double));
+    assert(sol->met);
+  
+    for (k=1; k<=sol->np; k++) {
+      ia = (k-1)*6 + 1;
+      for (i=0; i<6; i++){
+	sol->met[ia+i] = metric[ (ia-1)+wrapperMetric[i] ]; 
+      }
+    }
+  }
+  
+}
+
+
+void metric_mshmet_to_ff_metric(MSHMET_pSol sol, MSHMET_Info *info, KN<double> &metric){
+  static const int invwrapperMetric[6]={0,1,3,2,4,5};
+  int k,ia,i;
+  if( info->iso == 1 ){
+    cout << " info->iso " << " metric "<< metric.N() <<" " << sol->np << endl;
+    // isotrope
+    for (k=1; k<=sol->np; k++) {
+      metric[ k-1 ] = sol->met[k]; 
+      //cout << "k " << k << " " << sol->met[k] << endl;
+    }
+  }
+  else{
+    for (k=1; k<=sol->np; k++) {
+      ia = (k-1)*6 + 1;
+      for (i=0; i< 6; i++)
+	metric[(ia-1)+i]= sol->met[ia + invwrapperMetric[i]];
+    }
+  }
+}
+
+
+class mshmet3d_Op: public E_F0mps 
+{
+public:
+  typedef KN_<double>  Result;
+  Expression eTh;
+  int nbsol;
+  int nbsolsize;
+  int typesol[GmfMaxTyp];
+  int dim;
+  vector<Expression> sol;
+
+  static const int n_name_param = 12; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  int  arg(int i,Stack stack, int a ) const{ return nargs[i] ? GetAny< long  >( (*nargs[i])(stack) ): a;}
+  int  arg(int i,Stack stack, bool a ) const{ return nargs[i] ? GetAny< bool  >( (*nargs[i])(stack) ): a;}
+  
+  
+public:
+  mshmet3d_Op(const basicAC_F0 &  args) : sol( args.size()-1 )
+  {
+    
+    //cout << "mshmet3d"<< endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    eTh=to<pmesh3>(args[0]); 
+    dim=3;
+    nbsol = args.size()-1;
+    int ksol=0; 
+    ffassert(nbsol<GmfMaxTyp);
+
+    for (int i=1;i<nbsol+1;i++)       
+      if (args[i].left()==atype<E_Array>())
+	{
+	  const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+	  ffassert(a);
+	  ksol+=a->size(); 
+	}
+      else
+	ksol++;
+    sol.resize(ksol); 
+
+    // typesol :: 1 sca, 2 vector, 3 symtensor
+
+    ksol=0; 
+    nbsolsize=0;
+    for (int i=1;i<nbsol+1;i++)       
+      if (args[i].left()==atype<E_Array>())
+	{
+	  const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+	  ffassert(a);
+	  int N=a->size();
+	  nbsolsize=nbsolsize+N;
+	  switch (N){
+	  
+	  case 3 :
+	    typesol[i-1]=2; 
+	    for (int j=0;j<N;j++)             
+	      sol[ksol++]=to<double>((*a)[j]);
+	    break;
+	  case 6 :
+	    typesol[i-1]=3;   
+	    for (int j=0;j<N;j++)             
+	      sol[ksol++]=to<double>((*a)[j]); 
+	    break;
+	  default :
+	    CompileError(" 3D solution for mshmest is vector (3 comp) or symetric tensor (6 comp)");
+	    break;
+	  }
+	}
+      else 
+	{
+	  typesol[i-1]=1;
+	  nbsolsize=nbsolsize+1;
+	  sol[ksol++]=to<double>(args[i]);
+	} 
+  }
+    
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype< pmesh3 >(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new mshmet3d_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+  operator aType () const { return atype< KN_<double> >();} 
+};
+
+
+basicAC_F0::name_and_type  mshmet3d_Op::name_param[]= {
+  {  "loptions", &typeid(KN_<long>)}, //0
+  {  "doptions", &typeid(KN_<double>)},
+  {  "metric", &typeid(KN_<double>)},
+  {  "normalization", &typeid(bool)},
+  {  "aniso", &typeid(bool)},
+  {  "levelset", &typeid(bool)},// 5
+  {  "verbosity", &typeid(long)},
+  {  "nbregul", &typeid(long)},
+  {  "hmin", &typeid(double)},
+  {  "hmax", &typeid(double)},//9
+  {  "err", &typeid(double)},//10
+  {  "width", &typeid(double)}//11
+
+};
+
+template<class T>
+ostream & dumpp(const T * p,int n,ostream & f)
+{
+  for(int i=0;i<n;++i)
+    f << p[i] << " ";
+  return f; 
+}
+
+AnyType mshmet3d_Op::operator()(Stack stack)  const 
+{
+  // initialisation
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  ffassert( pTh );
+  Mesh3 &Th3=*pTh;
+  int nv=Th3.nv;
+  int nt=Th3.nt;
+  int nbe=Th3.nbe;
+
+ 
+  KN<double> defaultfopt(4);
+  /*
+  info->hmin   = fopt[0]; // 0.01;
+  info->hmax   = fopt[1]; // 1.0;
+  info->eps    = fopt[2]; // 0.01;
+  info->width  = fopt[3]; // 0.05;
+  */
+  defaultfopt(0)= 0.01;
+  defaultfopt(1)= 1.0;
+  defaultfopt(2)= 0.01;
+  defaultfopt(3)= 0.00;
+  KN<long> defaultintopt(7);
+  /*
+    info->nnu    = intopt[0]; //  0;
+    info->iso    = intopt[1]; //  1;
+    info->ls     = intopt[2]; //  0;
+    info->ddebug = intopt[3]; //  0;
+    info->imprim = intopt[4]; // 10;
+    info->nlis   = intopt[5]; //  0;
+    info->metric =  intopt[6]; // 0; // metric given besoin ???
+  */  
+  defaultintopt(0)= 1;
+  defaultintopt(1)= 1;
+  defaultintopt(2)= 0;
+  defaultintopt(3)= 0; 
+  defaultintopt(4)= verbosity;
+  defaultintopt(5)= 0;
+  defaultintopt(6)= 0;
+  if(nargs[11]) {defaultintopt[2]=1;defaultfopt[3]=0;}//  level set ...  
+  KN<int> intopt(arg(0,stack,defaultintopt));
+  KN<double> fopt(arg(1,stack,defaultfopt));
+  KN<double> *pmetric=new KN<double>(Th3.nv);
+  KN<double> &metric=*pmetric;
+
+
+  intopt[0]=arg(3,stack, intopt[0]!=0);// normaliz
+  intopt[1]=!arg(4,stack,intopt[1]==0);//  aniso
+  intopt[2]=arg(5,stack,intopt[2]!=0);// levelset 
+  intopt[4]=arg(6,stack,intopt[4]); // verbo
+  intopt[5]=arg(7,stack,intopt[5]); // nbregul
+  fopt[0]=arg(8,stack,fopt[0]); //hmin
+  fopt[1]=arg(9,stack,fopt[1]); //hmax
+  fopt[2]=arg(10,stack,fopt[2]);// err
+  fopt[3]=arg(11,stack,fopt[3]);// width
+
+
+  if(verbosity>2) 
+    {
+      cout<< "    -- mshmet : lopt " ;  dumpp((int*) intopt,intopt.N(),cout)  <<endl;
+      cout<< "              : dopt " ; dumpp((double*)fopt,fopt.N(),cout)  <<endl;
+    }
+
+  metric=0.;
+  if(intopt.N() != 7 )
+    ExecError(" Size of array of loption are wrong != 7");
+  if(fopt.N() != 4 )
+    ExecError(" Size of array of doption are wrong != 4");
+
+
+  if( intopt[1]==0){ 
+    metric.resize(6*Th3.nv);
+    metric=0.;
+  }
+
+  // definiton d'une metric par default
+  if( nargs[2]  ){ 
+    metric = GetAny<KN_<double> >( (*nargs[2])(stack) ); 
+    assert(metric.N()==Th3.nv || metric.N()==6*Th3.nv);
+    intopt[6]=1;
+    if(metric.N()==Th3.nv) intopt[1]=1;
+    if(metric.N()==6*Th3.nv) intopt[1]=0;
+  }
+
+
+  MSHMET_pMesh mshmetmesh = mesh3_to_MSHMET_pMesh( Th3 );
+  int TypTab[nbsol];
+  for(int ii=0; ii<nbsol;ii++)
+    TypTab[ii] = typesol[ii];
+
+
+  KN<double> tabsol(nbsolsize*nv);
+  tabsol=0.;
+  {
+    MeshPoint *mp3(MeshPointStack(stack)); 
+    
+    KN<bool> takemesh(nv);
+    takemesh=false;
+    for(int it=0;it<nt;it++){
+      for(int iv=0;iv<4;iv++){
+	int i=Th3(it,iv);
+	
+	if(takemesh[i]==false){
+	  mp3->setP(&Th3,it,iv);
+	  
+	  for(int ii=0;ii<nbsolsize;ii++){
+	    tabsol[i*nbsolsize+ii] = GetAny< double >( (*sol[ii])(stack) );
+	  }
+	  takemesh[i] = true; 
+	}
+      }
+    }
+  }
+  if(verbosity>5)
+    cout << "    min/max tabsol:  " << tabsol.min() << " " <<tabsol.max() << endl;
+  MSHMET_pSol mshmetsol = sol_mshmet(dim, nv, nbsol, nbsolsize, TypTab, tabsol);
+  if( intopt[1] == 1) 
+    mshmetmesh->info.iso = 1;
+  else
+    mshmetmesh->info.iso = 0;
+  if( nargs[2]  ) metric_mshmet( mshmetsol, &mshmetmesh->info, metric);
+
+  int res = MSHMET_mshmet(intopt, fopt, mshmetmesh, mshmetsol);
+  
+  if( res > 0){
+    cout << " problem with mshmet :: error " <<  res << endl; 
+    exit(1);
+  }
+  
+  metric_mshmet_to_ff_metric( mshmetsol, &mshmetmesh->info, metric);
+  
+  // faire les free
+    
+  myMSHMET_free( mshmetmesh, mshmetsol);
+
+  Add2StackOfPtr2Free(stack,pmetric);
+  *mp=mps;
+  return SetAny< KN<double> >(metric);
+}
+
+
+
+
+// mshmet2d
+class mshmet2d_Op: public E_F0mps 
+{
+public:
+  typedef KN_<double>  Result;
+  Expression eTh;
+  int nbsol;
+  int nbsolsize;
+  int typesol[GmfMaxTyp];
+  int dim;
+  vector<Expression> sol;
+
+  static const int n_name_param = 12; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack, long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  
+  
+public:
+  mshmet2d_Op(const basicAC_F0 &  args) : sol( args.size()-1 )
+  {
+    
+    cout << "mshmet2d"<< endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    eTh=to<pmesh>(args[0]); 
+    dim=3;
+    nbsol = args.size()-1;
+    int ksol=0; 
+    ffassert(nbsol<GmfMaxTyp);
+
+    for (int i=1;i<nbsol+1;i++)       
+      if (args[i].left()==atype<E_Array>())
+	{
+	  const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+	  ffassert(a);
+	  ksol+=a->size(); 
+	}
+      else
+	ksol++;
+    sol.resize(ksol); 
+
+    // typesol :: 1 sca, 2 vector, 3 symtensor
+
+    ksol=0; 
+    nbsolsize=0;
+    for (int i=1;i<nbsol+1;i++)       
+      if (args[i].left()==atype<E_Array>())
+	{
+	  const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+	  ffassert(a);
+	  int N=a->size();
+	  nbsolsize=nbsolsize+N;
+	  switch (N){
+	  case 2 :
+	    typesol[i-1]=2; 
+	    for (int j=0;j<N;j++)             
+	      sol[ksol++]=to<double>((*a)[j]);
+	    break;
+	  case 3 :
+	    typesol[i-1]=3;   
+	    for (int j=0;j<N;j++)             
+	      sol[ksol++]=to<double>((*a)[j]); 
+	    break;
+	  default :
+	    CompileError(" 2D solution for mshmest is vector (2 comp) or symetric tensor (3 comp)");
+	    break;
+	  }
+	}
+      else 
+	{
+	  typesol[i-1]=1;
+	  nbsolsize=nbsolsize+1;
+	  sol[ksol++]=to<double>(args[i]);
+	} 
+  }
+    
+  static ArrayOfaType  typeargs() { return  ArrayOfaType( atype< pmesh >(), true); }// all type
+  static  E_F0 * f(const basicAC_F0 & args) { return new mshmet2d_Op(args);} 
+  AnyType operator()(Stack stack)  const ;
+  operator aType () const { return atype< KN_<double> >();} 
+};
+
+
+basicAC_F0::name_and_type  mshmet2d_Op::name_param[]= {
+  {  "loptions", &typeid(KN_<long>)},
+  {  "doptions", &typeid(KN_<double>)},
+  {  "metric", &typeid(KN_<double>)}
+};
+
+AnyType mshmet2d_Op::operator()(Stack stack)  const 
+{
+  // initialisation
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  ffassert( pTh );
+  Mesh &Th=*pTh;
+  int nv=Th.nv;
+  int nt=Th.nt;
+  int nbe=Th.neb;
+
+ 
+  KN<double> defaultfopt(4);
+  /*
+  info->hmin   = fopt[0]; // 0.01;
+  info->hmax   = fopt[1]; // 1.0;
+  info->eps    = fopt[2]; // 0.01;
+  info->width  = fopt[3]; // 0.05;
+  */
+  defaultfopt(0)= 0.01;
+  defaultfopt(1)= 1.0;
+  defaultfopt(2)= 0.01;
+  defaultfopt(3)= 0.05;
+  KN<long> defaultintopt(7);
+  /*
+    info->nnu    = intopt[0]; //  0;
+    info->iso    = intopt[1]; //  1;
+    info->ls     = intopt[2]; //  0;
+    info->ddebug = intopt[3]; //  0;
+    info->imprim = intopt[4]; // 10;
+    info->nlis   = intopt[5]; //  0;
+    info->metric =  intopt[6]; // 0; // metric given besoin ???
+  */  
+  defaultintopt(0)= 0;
+  defaultintopt(1)= 1;
+  defaultintopt(2)= 0;
+  defaultintopt(3)= 1;
+  defaultintopt(4)= 10;
+  defaultintopt(5)= 0;
+  defaultintopt(6)= 0;
+
+  KN<int> intopt(arg(0,stack,defaultintopt));
+  KN<double> fopt(arg(1,stack,defaultfopt));
+  
+  KN<double> *pmetric = new KN<double>(Th.nv);
+  KN<double> &metric = *pmetric; 
+ 
+  if( intopt[1]== 1){
+    metric.resize(6*Th.nv);
+    metric=0.;
+  }
+ 
+  // definiton d'une metric par default
+  if( nargs[2]  ){ 
+    metric = GetAny<KN_<double> >( (*nargs[2])(stack) ); 
+    assert(metric.N()==Th.nv || metric.N()==6*Th.nv);
+    intopt[6]=1;
+    if(metric.N()==Th.nv) intopt[1]=1;
+    if(metric.N()==6*Th.nv) intopt[1]=0;
+  }
+
+
+  MSHMET_pMesh mshmetmesh = mesh_to_MSHMET_pMesh( Th );
+  int TypTab[nbsol];
+  for(int ii=0; ii<nbsol;ii++)
+    TypTab[ii] = typesol[ii];
+
+  KN<double> tabsol(nbsolsize*nv);
+  tabsol=0.;
+  {
+    MeshPoint *mp3(MeshPointStack(stack)); 
+    
+    KN<bool> takemesh(nv);
+    takemesh=false;
+    for(int it=0;it<nt;it++){
+      for(int iv=0;iv<3;iv++){
+	int i=Th(it,iv);
+	
+	if(takemesh[i]==false){
+	  mp3->setP(&Th,it,iv);
+	  
+	  for(int ii=0;ii<nbsolsize;ii++){
+	    tabsol[i*nbsolsize+ii] = GetAny< double >( (*sol[ii])(stack) );
+	  }
+	  takemesh[i] = true; 
+	}
+      }
+    }
+  }
+  MSHMET_pSol mshmetsol = sol_mshmet(dim, nv, nbsol, nbsolsize, TypTab, tabsol);
+  if( intopt[1] == 1) 
+    mshmetmesh->info.iso = 1;
+  else
+    mshmetmesh->info.iso = 0;
+  if( nargs[2]  ) metric_mshmet( mshmetsol, &mshmetmesh->info, metric);
+
+  int res = MSHMET_mshmet(intopt, fopt, mshmetmesh, mshmetsol);
+  
+  if( res > 0){
+    cout << " problem with mshmet :: error " <<  res << endl; 
+    exit(1);
+  }
+  
+  metric_mshmet_to_ff_metric( mshmetsol, &mshmetmesh->info, metric);
+  
+  // faire les free
+  myMSHMET_free( mshmetmesh, mshmetsol);
+  *mp=mps;
+
+  Add2StackOfPtr2Free(stack,pmetric);
+  return SetAny< KN<double> >(metric);
+}
+
+
+
+/*  class Init1 { public:
+  Init1();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  
+  //if (verbosity)
+  if(verbosity) cout << " load: mshmet  " << endl;
+  
+  Global.Add("mshmet","(",new OneOperatorCode<mshmet2d_Op>);
+  Global.Add("mshmet","(",new OneOperatorCode<mshmet3d_Op>);
+  //Global.Add("mshmet","(",new OneOperatorCode<mshmet2d_Op> );
+  
+}
+
+
+#define  WITH_NO_INIT
+#include "msh3.hpp" 
+LOADFUNC(Load_Init)
diff --git a/examples++-load/mshmet.edp b/examples++-load/mshmet.edp
new file mode 100644
index 0000000..8c84994
--- /dev/null
+++ b/examples++-load/mshmet.edp
@@ -0,0 +1 @@
+cout  << " remove example see ../examples++-3d/Laplace-Adapt-3d.edp  \n" <<endl; 
\ No newline at end of file
diff --git a/examples++-load/myType.edp b/examples++-load/myType.edp
new file mode 100644
index 0000000..265b593
--- /dev/null
+++ b/examples++-load/myType.edp
@@ -0,0 +1,6 @@
+load "addNewType"
+
+myType ff("toto"); 
+cout << ff(1,2).x << endl; 
+
+cout << ff(1,2).N.x  << endl; 
\ No newline at end of file
diff --git a/examples++-load/myfunction.cpp b/examples++-load/myfunction.cpp
new file mode 100644
index 0000000..dd94dc8
--- /dev/null
+++ b/examples++-load/myfunction.cpp
@@ -0,0 +1,62 @@
+// Example C++ function "myfunction", dynamically loaded into "load.edp"
+// ---------------------------------------------------------------------
+// $Id$
+#include <ff++.hpp>
+using namespace Fem2D;
+double myfunction(Stack stack)
+{
+  //  to get FreeFem++  data
+  MeshPoint &mp= *MeshPointStack(stack); // the struct to get x,y, normal , value 
+  double x= mp.P.x; // get the current x value
+  double y= mp.P.y; // get the current y value
+  // cout << "x = " << x << " y=" << y << " " << sin(x)*cos(y) <<  endl;
+  return sin(x)*cos(y);
+}
+
+//  A class build the link with freefem++ 
+// generaly this class are already in AFunction.hpp
+// but unfortunatly, I have no simple function with no parameter
+// in freefem++ depending of the mesh,  
+template<class R>
+class  OneOperator0s : public OneOperator {
+
+  // the class to defined a evaluated a new function 
+  //  It  must devive from  E_F0 if it is mesh independent
+  //   or from E_F0mps if it is mesh dependent 
+  class E_F0_F :public  E_F0mps { public:   
+    typedef  R (*func)(Stack stack) ; 
+    func f; // the pointeur to the fnction myfunction 
+    E_F0_F(func ff)  : f(ff) {}
+    // the operator evaluation in freefem++ 
+    AnyType operator()(Stack stack)  const {return SetAny<R>( f(stack)) ;}  
+
+  };
+
+  typedef  R (*func)(Stack ) ; 
+  func  f; 
+public: 
+  // the function which build the freefem++ byte code 
+  E_F0 * code(const basicAC_F0 & ) const { return  new E_F0_F(f);} 
+  // the constructor to say ff is a function without parameter
+  // and returning a R
+  OneOperator0s(func  ff): OneOperator(map_type[typeid(R).name()]),f(ff){}
+};
+
+double testio(Stack stack)
+{
+  double x=M_PI;
+  long l= (1<<9) ;
+  cout << " test cout " << x << endl;
+  cout << " test cout " << l << endl;
+
+  cerr << " test cerr " << x << endl;
+  cerr << " test cerr " << l << endl;
+  return 0.; 
+}
+
+void init(){
+  Global.Add("myfunction","(",new OneOperator0s<double>(myfunction));
+  Global.Add("testio","(",new OneOperator0s<double>(testio));
+}
+
+LOADFUNC(init);
diff --git a/examples++-load/myfunction2.cpp b/examples++-load/myfunction2.cpp
new file mode 100644
index 0000000..091e61f
--- /dev/null
+++ b/examples++-load/myfunction2.cpp
@@ -0,0 +1,21 @@
+// Example C++ function "myfunction", dynamically loaded into "load.edp"
+// ---------------------------------------------------------------------
+// $Id$
+#include <ff++.hpp>
+using namespace Fem2D;
+double myf(string * s) {
+  cout << *s << endl;
+  return 0.;
+}
+double f(const double& x) { return x*x+1;} 
+//  Hack to do something at initialisation time
+//   to add the name myfunction to the freefem++ table 
+/*  class Init { public:
+  Init();
+};
+$1 */
+static void Load_Init(){
+  Global.Add("Why","(",new OneOperator1<double,string*>(myf));
+  Global.Add("f","(",new OneOperator1_<double,double>(f));
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/myfunction2.edp b/examples++-load/myfunction2.edp
new file mode 100644
index 0000000..9b7a1ed
--- /dev/null
+++ b/examples++-load/myfunction2.edp
@@ -0,0 +1,9 @@
+// Example of dynamic function load
+// --------------------------------
+// $Id$
+
+ load "myfunction2"
+  string toto="xxxx";
+ Why(toto);
+ Why("qqsdqs.wwc.dqqs");
+ cout << f(3.) << endl; 
\ No newline at end of file
diff --git a/examples++-load/newuoa.f b/examples++-load/newuoa.f
new file mode 100644
index 0000000..ef003a0
--- /dev/null
+++ b/examples++-load/newuoa.f
@@ -0,0 +1,1455 @@
+C  version modif by F. HECHT
+C ---------------------------
+C The code in fortran is totally free, and the interface is under LGPL 
+C http://www.inrialpes.fr/bipop/people/guilbert/newuoa/newuoa.pdf 
+C  original source :
+C http://www.inrialpees.fr/bipop/people/guilbert/newuoa/newuoa.tar.gz
+C --------------------
+      SUBROUTINE BIGDEN (N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KOPT,
+     1  KNEW,D,W,VLAG,BETA,S,WVEC,PROD)
+      IMPLICIT REAL*8 (A-H,O-Z)
+      DIMENSION XOPT(*),XPT(NPT,*),BMAT(NDIM,*),ZMAT(NPT,*),D(*),
+     1  W(*),VLAG(*),S(*),WVEC(NDIM,*),PROD(NDIM,*)
+      DIMENSION DEN(9),DENEX(9),PAR(9)
+C
+C     N is the number of variables.
+C     NPT is the number of interpolation equations.
+C     XOPT is the best interpolation point so far.
+C     XPT contains the coordinates of the current interpolation points.
+C     BMAT provides the last N columns of H.
+C     ZMAT and IDZ give a factorization of the first NPT by NPT submatrix of H.
+C     NDIM is the first dimension of BMAT and has the value NPT+N.
+C     KOPT is the index of the optimal interpolation point.
+C     KNEW is the index of the interpolation point that is going to be moved.
+C     D will be set to the step from XOPT to the new point, and on entry it
+C       should be the D that was calculated by the last call of BIGLAG. The
+C       length of the initial D provides a trust region bound on the final D.
+C     W will be set to Wcheck for the final choice of D.
+C     VLAG will be set to Theta*Wcheck+e_b for the final choice of D.
+C     BETA will be set to the value that will occur in the updating formula
+C       when the KNEW-th interpolation point is moved to its new position.
+C     S, WVEC, PROD and the private arrays DEN, DENEX and PAR will be used
+C       for working space.
+C
+C     D is calculated in a way that should provide a denominator with a large
+C     modulus in the updating formula when the KNEW-th interpolation point is
+C     shifted to the new position XOPT+D.
+C
+C     Set some constants.
+C
+      HALF=0.5D0
+      ONE=1.0D0
+      QUART=0.25D0
+      TWO=2.0D0
+      ZERO=0.0D0
+      TWOPI=8.0D0*DATAN(ONE)
+      NPTM=NPT-N-1
+C
+C     Store the first NPT elements of the KNEW-th column of H in W(N+1)
+C     to W(N+NPT).
+C
+      DO 10 K=1,NPT
+   10 W(N+K)=ZERO
+      DO 20 J=1,NPTM
+      TEMP=ZMAT(KNEW,J)
+      IF (J .LT. IDZ) TEMP=-TEMP
+      DO 20 K=1,NPT
+   20 W(N+K)=W(N+K)+TEMP*ZMAT(K,J)
+      ALPHA=W(N+KNEW)
+C
+C     The initial search direction D is taken from the last call of BIGLAG,
+C     and the initial S is set below, usually to the direction from X_OPT
+C     to X_KNEW, but a different direction to an interpolation point may
+C     be chosen, in order to prevent S from being nearly parallel to D.
+C
+      DD=ZERO
+      DS=ZERO
+      SS=ZERO
+      XOPTSQ=ZERO
+      DO 30 I=1,N
+      DD=DD+D(I)**2
+      S(I)=XPT(KNEW,I)-XOPT(I)
+      DS=DS+D(I)*S(I)
+      SS=SS+S(I)**2
+   30 XOPTSQ=XOPTSQ+XOPT(I)**2
+      IF (DS*DS .GT. 0.99D0*DD*SS) THEN
+          KSAV=KNEW
+          DTEST=DS*DS/SS
+          DO 50 K=1,NPT
+          IF (K .NE. KOPT) THEN
+              DSTEMP=ZERO
+              SSTEMP=ZERO
+              DO 40 I=1,N
+              DIFF=XPT(K,I)-XOPT(I)
+              DSTEMP=DSTEMP+D(I)*DIFF
+   40         SSTEMP=SSTEMP+DIFF*DIFF
+              IF (DSTEMP*DSTEMP/SSTEMP .LT. DTEST) THEN
+                  KSAV=K
+                  DTEST=DSTEMP*DSTEMP/SSTEMP
+                  DS=DSTEMP
+                  SS=SSTEMP
+              END IF
+          END IF
+   50     CONTINUE
+          DO 60 I=1,N
+   60     S(I)=XPT(KSAV,I)-XOPT(I)
+      END IF
+      SSDEN=DD*SS-DS*DS
+      ITERC=0
+      DENSAV=ZERO
+C
+C     Begin the iteration by overwriting S with a vector that has the
+C     required length and direction.
+C
+   70 ITERC=ITERC+1
+      TEMP=ONE/DSQRT(SSDEN)
+      XOPTD=ZERO
+      XOPTS=ZERO
+      DO 80 I=1,N
+      S(I)=TEMP*(DD*S(I)-DS*D(I))
+      XOPTD=XOPTD+XOPT(I)*D(I)
+   80 XOPTS=XOPTS+XOPT(I)*S(I)
+C
+C     Set the coefficients of the first two terms of BETA.
+C
+      TEMPA=HALF*XOPTD*XOPTD
+      TEMPB=HALF*XOPTS*XOPTS
+      DEN(1)=DD*(XOPTSQ+HALF*DD)+TEMPA+TEMPB
+      DEN(2)=TWO*XOPTD*DD
+      DEN(3)=TWO*XOPTS*DD
+      DEN(4)=TEMPA-TEMPB
+      DEN(5)=XOPTD*XOPTS
+      DO 90 I=6,9
+   90 DEN(I)=ZERO
+C
+C     Put the coefficients of Wcheck in WVEC.
+C
+      DO 110 K=1,NPT
+      TEMPA=ZERO
+      TEMPB=ZERO
+      TEMPC=ZERO
+      DO 100 I=1,N
+      TEMPA=TEMPA+XPT(K,I)*D(I)
+      TEMPB=TEMPB+XPT(K,I)*S(I)
+  100 TEMPC=TEMPC+XPT(K,I)*XOPT(I)
+      WVEC(K,1)=QUART*(TEMPA*TEMPA+TEMPB*TEMPB)
+      WVEC(K,2)=TEMPA*TEMPC
+      WVEC(K,3)=TEMPB*TEMPC
+      WVEC(K,4)=QUART*(TEMPA*TEMPA-TEMPB*TEMPB)
+  110 WVEC(K,5)=HALF*TEMPA*TEMPB
+      DO 120 I=1,N
+      IP=I+NPT
+      WVEC(IP,1)=ZERO
+      WVEC(IP,2)=D(I)
+      WVEC(IP,3)=S(I)
+      WVEC(IP,4)=ZERO
+  120 WVEC(IP,5)=ZERO
+C
+C     Put the coefficents of THETA*Wcheck in PROD.
+C
+      DO 190 JC=1,5
+      NW=NPT
+      IF (JC .EQ. 2 .OR. JC .EQ. 3) NW=NDIM
+      DO 130 K=1,NPT
+  130 PROD(K,JC)=ZERO
+      DO 150 J=1,NPTM
+      SUM=ZERO
+      DO 140 K=1,NPT
+  140 SUM=SUM+ZMAT(K,J)*WVEC(K,JC)
+      IF (J .LT. IDZ) SUM=-SUM
+      DO 150 K=1,NPT
+  150 PROD(K,JC)=PROD(K,JC)+SUM*ZMAT(K,J)
+      IF (NW .EQ. NDIM) THEN
+          DO 170 K=1,NPT
+          SUM=ZERO
+          DO 160 J=1,N
+  160     SUM=SUM+BMAT(K,J)*WVEC(NPT+J,JC)
+  170     PROD(K,JC)=PROD(K,JC)+SUM
+      END IF
+      DO 190 J=1,N
+      SUM=ZERO
+      DO 180 I=1,NW
+  180 SUM=SUM+BMAT(I,J)*WVEC(I,JC)
+  190 PROD(NPT+J,JC)=SUM
+C
+C     Include in DEN the part of BETA that depends on THETA.
+C
+      DO 210 K=1,NDIM
+      SUM=ZERO
+      DO 200 I=1,5
+      PAR(I)=HALF*PROD(K,I)*WVEC(K,I)
+  200 SUM=SUM+PAR(I)
+      DEN(1)=DEN(1)-PAR(1)-SUM
+      TEMPA=PROD(K,1)*WVEC(K,2)+PROD(K,2)*WVEC(K,1)
+      TEMPB=PROD(K,2)*WVEC(K,4)+PROD(K,4)*WVEC(K,2)
+      TEMPC=PROD(K,3)*WVEC(K,5)+PROD(K,5)*WVEC(K,3)
+      DEN(2)=DEN(2)-TEMPA-HALF*(TEMPB+TEMPC)
+      DEN(6)=DEN(6)-HALF*(TEMPB-TEMPC)
+      TEMPA=PROD(K,1)*WVEC(K,3)+PROD(K,3)*WVEC(K,1)
+      TEMPB=PROD(K,2)*WVEC(K,5)+PROD(K,5)*WVEC(K,2)
+      TEMPC=PROD(K,3)*WVEC(K,4)+PROD(K,4)*WVEC(K,3)
+      DEN(3)=DEN(3)-TEMPA-HALF*(TEMPB-TEMPC)
+      DEN(7)=DEN(7)-HALF*(TEMPB+TEMPC)
+      TEMPA=PROD(K,1)*WVEC(K,4)+PROD(K,4)*WVEC(K,1)
+      DEN(4)=DEN(4)-TEMPA-PAR(2)+PAR(3)
+      TEMPA=PROD(K,1)*WVEC(K,5)+PROD(K,5)*WVEC(K,1)
+      TEMPB=PROD(K,2)*WVEC(K,3)+PROD(K,3)*WVEC(K,2)
+      DEN(5)=DEN(5)-TEMPA-HALF*TEMPB
+      DEN(8)=DEN(8)-PAR(4)+PAR(5)
+      TEMPA=PROD(K,4)*WVEC(K,5)+PROD(K,5)*WVEC(K,4)
+  210 DEN(9)=DEN(9)-HALF*TEMPA
+C
+C     Extend DEN so that it holds all the coefficients of DENOM.
+C
+      SUM=ZERO
+      DO 220 I=1,5
+      PAR(I)=HALF*PROD(KNEW,I)**2
+  220 SUM=SUM+PAR(I)
+      DENEX(1)=ALPHA*DEN(1)+PAR(1)+SUM
+      TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,2)
+      TEMPB=PROD(KNEW,2)*PROD(KNEW,4)
+      TEMPC=PROD(KNEW,3)*PROD(KNEW,5)
+      DENEX(2)=ALPHA*DEN(2)+TEMPA+TEMPB+TEMPC
+      DENEX(6)=ALPHA*DEN(6)+TEMPB-TEMPC
+      TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,3)
+      TEMPB=PROD(KNEW,2)*PROD(KNEW,5)
+      TEMPC=PROD(KNEW,3)*PROD(KNEW,4)
+      DENEX(3)=ALPHA*DEN(3)+TEMPA+TEMPB-TEMPC
+      DENEX(7)=ALPHA*DEN(7)+TEMPB+TEMPC
+      TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,4)
+      DENEX(4)=ALPHA*DEN(4)+TEMPA+PAR(2)-PAR(3)
+      TEMPA=TWO*PROD(KNEW,1)*PROD(KNEW,5)
+      DENEX(5)=ALPHA*DEN(5)+TEMPA+PROD(KNEW,2)*PROD(KNEW,3)
+      DENEX(8)=ALPHA*DEN(8)+PAR(4)-PAR(5)
+      DENEX(9)=ALPHA*DEN(9)+PROD(KNEW,4)*PROD(KNEW,5)
+C
+C     Seek the value of the angle that maximizes the modulus of DENOM.
+C
+      SUM=DENEX(1)+DENEX(2)+DENEX(4)+DENEX(6)+DENEX(8)
+      DENOLD=SUM
+      DENMAX=SUM
+      ISAVE=0
+      IU=49
+      TEMP=TWOPI/DFLOAT(IU+1)
+      PAR(1)=ONE
+      DO 250 I=1,IU
+      ANGLE=DFLOAT(I)*TEMP
+      PAR(2)=DCOS(ANGLE)
+      PAR(3)=DSIN(ANGLE)
+      DO 230 J=4,8,2
+      PAR(J)=PAR(2)*PAR(J-2)-PAR(3)*PAR(J-1)
+  230 PAR(J+1)=PAR(2)*PAR(J-1)+PAR(3)*PAR(J-2)
+      SUMOLD=SUM
+      SUM=ZERO
+      DO 240 J=1,9
+  240 SUM=SUM+DENEX(J)*PAR(J)
+      IF (DABS(SUM) .GT. DABS(DENMAX)) THEN
+          DENMAX=SUM
+          ISAVE=I
+          TEMPA=SUMOLD
+      ELSE IF (I .EQ. ISAVE+1) THEN
+          TEMPB=SUM
+      END IF
+  250 CONTINUE
+      IF (ISAVE .EQ. 0) TEMPA=SUM
+      IF (ISAVE .EQ. IU) TEMPB=DENOLD
+      STEP=ZERO
+      IF (TEMPA .NE. TEMPB) THEN
+          TEMPA=TEMPA-DENMAX
+          TEMPB=TEMPB-DENMAX
+          STEP=HALF*(TEMPA-TEMPB)/(TEMPA+TEMPB)
+      END IF
+      ANGLE=TEMP*(DFLOAT(ISAVE)+STEP)
+C
+C     Calculate the new parameters of the denominator, the new VLAG vector
+C     and the new D. Then test for convergence.
+C
+      PAR(2)=DCOS(ANGLE)
+      PAR(3)=DSIN(ANGLE)
+      DO 260 J=4,8,2
+      PAR(J)=PAR(2)*PAR(J-2)-PAR(3)*PAR(J-1)
+  260 PAR(J+1)=PAR(2)*PAR(J-1)+PAR(3)*PAR(J-2)
+      BETA=ZERO
+      DENMAX=ZERO
+      DO 270 J=1,9
+      BETA=BETA+DEN(J)*PAR(J)
+  270 DENMAX=DENMAX+DENEX(J)*PAR(J)
+      DO 280 K=1,NDIM
+      VLAG(K)=ZERO
+      DO 280 J=1,5
+  280 VLAG(K)=VLAG(K)+PROD(K,J)*PAR(J)
+      TAU=VLAG(KNEW)
+      DD=ZERO
+      TEMPA=ZERO
+      TEMPB=ZERO
+      DO 290 I=1,N
+      D(I)=PAR(2)*D(I)+PAR(3)*S(I)
+      W(I)=XOPT(I)+D(I)
+      DD=DD+D(I)**2
+      TEMPA=TEMPA+D(I)*W(I)
+  290 TEMPB=TEMPB+W(I)*W(I)
+      IF (ITERC .GE. N) GOTO 340
+      IF (ITERC .GT. 1) DENSAV=DMAX1(DENSAV,DENOLD)
+      IF (DABS(DENMAX) .LE. 1.1D0*DABS(DENSAV)) GOTO 340
+      DENSAV=DENMAX
+C
+C     Set S to half the gradient of the denominator with respect to D.
+C     Then branch for the next iteration.
+C
+      DO 300 I=1,N
+      TEMP=TEMPA*XOPT(I)+TEMPB*D(I)-VLAG(NPT+I)
+  300 S(I)=TAU*BMAT(KNEW,I)+ALPHA*TEMP
+      DO 320 K=1,NPT
+      SUM=ZERO
+      DO 310 J=1,N
+  310 SUM=SUM+XPT(K,J)*W(J)
+      TEMP=(TAU*W(N+K)-ALPHA*VLAG(K))*SUM
+      DO 320 I=1,N
+  320 S(I)=S(I)+TEMP*XPT(K,I)
+      SS=ZERO
+      DS=ZERO
+      DO 330 I=1,N
+      SS=SS+S(I)**2
+  330 DS=DS+D(I)*S(I)
+      SSDEN=DD*SS-DS*DS
+      IF (SSDEN .GE. 1.0D-8*DD*SS) GOTO 70
+C
+C     Set the vector W before the RETURN from the subroutine.
+C
+  340 DO 350 K=1,NDIM
+      W(K)=ZERO
+      DO 350 J=1,5
+  350 W(K)=W(K)+WVEC(K,J)*PAR(J)
+      VLAG(KOPT)=VLAG(KOPT)+ONE
+      RETURN
+      END 
+      SUBROUTINE BIGLAG (N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KNEW,
+     1  DELTA,D,ALPHA,HCOL,GC,GD,S,W)
+      IMPLICIT REAL*8 (A-H,O-Z)
+      DIMENSION XOPT(*),XPT(NPT,*),BMAT(NDIM,*),ZMAT(NPT,*),D(*),
+     1  HCOL(*),GC(*),GD(*),S(*),W(*)
+C
+C     N is the number of variables.
+C     NPT is the number of interpolation equations.
+C     XOPT is the best interpolation point so far.
+C     XPT contains the coordinates of the current interpolation points.
+C     BMAT provides the last N columns of H.
+C     ZMAT and IDZ give a factorization of the first NPT by NPT submatrix of H.
+C     NDIM is the first dimension of BMAT and has the value NPT+N.
+C     KNEW is the index of the interpolation point that is going to be moved.
+C     DELTA is the current trust region bound.
+C     D will be set to the step from XOPT to the new point.
+C     ALPHA will be set to the KNEW-th diagonal element of the H matrix.
+C     HCOL, GC, GD, S and W will be used for working space.
+C
+C     The step D is calculated in a way that attempts to maximize the modulus
+C     of LFUNC(XOPT+D), subject to the bound ||D|| .LE. DELTA, where LFUNC is
+C     the KNEW-th Lagrange function.
+C
+C     Set some constants.
+C
+      HALF=0.5D0
+      ONE=1.0D0
+      ZERO=0.0D0
+      TWOPI=8.0D0*DATAN(ONE)
+      DELSQ=DELTA*DELTA
+      NPTM=NPT-N-1
+C
+C     Set the first NPT components of HCOL to the leading elements of the
+C     KNEW-th column of H.
+C
+      ITERC=0
+      DO 10 K=1,NPT
+   10 HCOL(K)=ZERO
+      DO 20 J=1,NPTM
+      TEMP=ZMAT(KNEW,J)
+      IF (J .LT. IDZ) TEMP=-TEMP
+      DO 20 K=1,NPT
+   20 HCOL(K)=HCOL(K)+TEMP*ZMAT(K,J)
+      ALPHA=HCOL(KNEW)
+C
+C     Set the unscaled initial direction D. Form the gradient of LFUNC at
+C     XOPT, and multiply D by the second derivative matrix of LFUNC.
+C
+      DD=ZERO
+      DO 30 I=1,N
+      D(I)=XPT(KNEW,I)-XOPT(I)
+      GC(I)=BMAT(KNEW,I)
+      GD(I)=ZERO
+   30 DD=DD+D(I)**2
+      DO 50 K=1,NPT
+      TEMP=ZERO
+      SUM=ZERO
+      DO 40 J=1,N
+      TEMP=TEMP+XPT(K,J)*XOPT(J)
+   40 SUM=SUM+XPT(K,J)*D(J)
+      TEMP=HCOL(K)*TEMP
+      SUM=HCOL(K)*SUM
+      DO 50 I=1,N
+      GC(I)=GC(I)+TEMP*XPT(K,I)
+   50 GD(I)=GD(I)+SUM*XPT(K,I)
+C
+C     Scale D and GD, with a sign change if required. Set S to another
+C     vector in the initial two dimensional subspace.
+C
+      GG=ZERO
+      SP=ZERO
+      DHD=ZERO
+      DO 60 I=1,N
+      GG=GG+GC(I)**2
+      SP=SP+D(I)*GC(I)
+   60 DHD=DHD+D(I)*GD(I)
+      SCALE=DELTA/DSQRT(DD)
+      IF (SP*DHD .LT. ZERO) SCALE=-SCALE
+      TEMP=ZERO
+      IF (SP*SP .GT. 0.99D0*DD*GG) TEMP=ONE
+      TAU=SCALE*(DABS(SP)+HALF*SCALE*DABS(DHD))
+      IF (GG*DELSQ .LT. 0.01D0*TAU*TAU) TEMP=ONE
+      DO 70 I=1,N
+      D(I)=SCALE*D(I)
+      GD(I)=SCALE*GD(I)
+   70 S(I)=GC(I)+TEMP*GD(I)
+C
+C     Begin the iteration by overwriting S with a vector that has the
+C     required length and direction, except that termination occurs if
+C     the given D and S are nearly parallel.
+C
+   80 ITERC=ITERC+1
+      DD=ZERO
+      SP=ZERO
+      SS=ZERO
+      DO 90 I=1,N
+      DD=DD+D(I)**2
+      SP=SP+D(I)*S(I)
+   90 SS=SS+S(I)**2
+      TEMP=DD*SS-SP*SP
+      IF (TEMP .LE. 1.0D-8*DD*SS) GOTO 160
+      DENOM=DSQRT(TEMP)
+      DO 100 I=1,N
+      S(I)=(DD*S(I)-SP*D(I))/DENOM
+  100 W(I)=ZERO
+C
+C     Calculate the coefficients of the objective function on the circle,
+C     beginning with the multiplication of S by the second derivative matrix.
+C
+      DO 120 K=1,NPT
+      SUM=ZERO
+      DO 110 J=1,N
+  110 SUM=SUM+XPT(K,J)*S(J)
+      SUM=HCOL(K)*SUM
+      DO 120 I=1,N
+  120 W(I)=W(I)+SUM*XPT(K,I)
+      CF1=ZERO
+      CF2=ZERO
+      CF3=ZERO
+      CF4=ZERO
+      CF5=ZERO
+      DO 130 I=1,N
+      CF1=CF1+S(I)*W(I)
+      CF2=CF2+D(I)*GC(I)
+      CF3=CF3+S(I)*GC(I)
+      CF4=CF4+D(I)*GD(I)
+  130 CF5=CF5+S(I)*GD(I)
+      CF1=HALF*CF1
+      CF4=HALF*CF4-CF1
+C
+C     Seek the value of the angle that maximizes the modulus of TAU.
+C
+      TAUBEG=CF1+CF2+CF4
+      TAUMAX=TAUBEG
+      TAUOLD=TAUBEG
+      ISAVE=0
+      IU=49
+      TEMP=TWOPI/DFLOAT(IU+1)
+      DO 140 I=1,IU
+      ANGLE=DFLOAT(I)*TEMP
+      CTH=DCOS(ANGLE)
+      STH=DSIN(ANGLE)
+      TAU=CF1+(CF2+CF4*CTH)*CTH+(CF3+CF5*CTH)*STH
+      IF (DABS(TAU) .GT. DABS(TAUMAX)) THEN
+          TAUMAX=TAU
+          ISAVE=I
+          TEMPA=TAUOLD
+      ELSE IF (I .EQ. ISAVE+1) THEN
+          TEMPB=TAU
+      END IF
+  140 TAUOLD=TAU
+      IF (ISAVE .EQ. 0) TEMPA=TAU
+      IF (ISAVE .EQ. IU) TEMPB=TAUBEG
+      STEP=ZERO
+      IF (TEMPA .NE. TEMPB) THEN
+          TEMPA=TEMPA-TAUMAX
+          TEMPB=TEMPB-TAUMAX
+          STEP=HALF*(TEMPA-TEMPB)/(TEMPA+TEMPB)
+      END IF
+      ANGLE=TEMP*(DFLOAT(ISAVE)+STEP)
+C
+C     Calculate the new D and GD. Then test for convergence.
+C
+      CTH=DCOS(ANGLE)
+      STH=DSIN(ANGLE)
+      TAU=CF1+(CF2+CF4*CTH)*CTH+(CF3+CF5*CTH)*STH
+      DO 150 I=1,N
+      D(I)=CTH*D(I)+STH*S(I)
+      GD(I)=CTH*GD(I)+STH*W(I)
+  150 S(I)=GC(I)+GD(I)
+      IF (DABS(TAU) .LE. 1.1D0*DABS(TAUBEG)) GOTO 160
+      IF (ITERC .LT. N) GOTO 80
+  160 RETURN
+      END 
+      FUNCTION NEWUOA (N,NPT,X,RHOBEG,RHOEND,IPRINT,MAXFUN,W,IWF,
+     1  CALFUN)
+      IMPLICIT REAL*8 (A-H,O-Z)
+      DIMENSION X(*),W(*),IWF(*)
+      EXTERNAL CALFUN
+      real*8 NEWUOB, NEWUOA
+C
+C     This subroutine seeks the least value of a function of many variables,
+C     by a trust region method that forms quadratic models by interpolation.
+C     There can be some freedom in the interpolation conditions, which is
+C     taken up by minimizing the Frobenius norm of the change to the second
+C     derivative of the quadratic model, beginning with a zero matrix. The
+C     arguments of the subroutine are as follows.
+C
+C     N must be set to the number of variables and must be at least two.
+C     NPT is the number of interpolation conditions. Its value must be in the
+C       interval [N+2,(N+1)(N+2)/2].
+C     Initial values of the variables must be set in X(1),X(2),...,X(N). They
+C       will be changed to the values that give the least calculated F.
+C     RHOBEG and RHOEND must be set to the initial and final values of a trust
+C       region radius, so both must be positive with RHOEND<=RHOBEG. Typically
+C       RHOBEG should be about one tenth of the greatest expected change to a
+C       variable, and RHOEND should indicate the accuracy that is required in
+C       the final values of the variables.
+C     The value of IPRINT should be set to 0, 1, 2 or 3, which controls the
+C       amount of printing. Specifically, there is no output if IPRINT=0 and
+C       there is output only at the return if IPRINT=1. Otherwise, each new
+C       value of RHO is printed, with the best vector of variables so far and
+C       the corresponding value of the objective function. Further, each new
+C       value of F with its variables are output if IPRINT=3.
+C     MAXFUN must be set to an upper bound on the number of calls of CALFUN.
+C     The array W will be used for working space. Its length must be at least
+C     (NPT+13)*(NPT+N)+3*N*(N+3)/2.
+C
+C     SUBROUTINE CALFUN (N,X,F) must be provided by the user. It must set F to
+C     the value of the objective function for the variables X(1),X(2),...,X(N).
+C
+C     Partition the working space array, so that different parts of it can be
+C     treated separately by the subroutine that performs the main calculation.
+C
+      NP=N+1
+      NPTM=NPT-NP
+      IF (NPT .LT. N+2 .OR. NPT .GT. ((N+2)*NP)/2) THEN
+          PRINT 10
+   10     FORMAT (/4X,'Return from NEWUOA because NPT is not in',
+     1      ' the required interval')
+          GO TO 20
+      END IF
+      NDIM=NPT+N
+      IXB=1
+      IXO=IXB+N
+      IXN=IXO+N
+      IXP=IXN+N
+      IFV=IXP+N*NPT
+      IGQ=IFV+NPT
+      IHQ=IGQ+N
+      IPQ=IHQ+(N*NP)/2
+      IBMAT=IPQ+NPT
+      IZMAT=IBMAT+NDIM*N
+      ID=IZMAT+NPT*NPTM
+      IVL=ID+N
+      IW=IVL+NDIM
+C
+C     The above settings provide a partition of W for subroutine NEWUOB.
+C     The partition requires the first NPT*(NPT+N)+5*N*(N+3)/2 elements of
+C     W plus the space that is needed by the last array of NEWUOB.
+C
+      NEWUOA= NEWUOB (N,NPT,X,RHOBEG,RHOEND,IPRINT,MAXFUN,W(IXB),
+     1  W(IXO),W(IXN),W(IXP),W(IFV),W(IGQ),W(IHQ),W(IPQ),W(IBMAT),
+     2  W(IZMAT),NDIM,W(ID),W(IVL),W(IW),
+     3  IWF, CALFUN)
+   20 RETURN
+      END 
+
+
+
+
+
+
+      FUNCTION NEWUOB (N,NPT,X,RHOBEG,RHOEND,IPRINT,MAXFUN,XBASE,
+     1  XOPT,XNEW,XPT,FVAL,GQ,HQ,PQ,BMAT,ZMAT,NDIM,D,VLAG,W,IWF,CALFUN)
+      IMPLICIT REAL*8 (A-H,O-Z)
+      DIMENSION X(*),XBASE(*),XOPT(*),XNEW(*),XPT(NPT,*),FVAL(*),
+     1  GQ(*),HQ(*),PQ(*),BMAT(NDIM,*),ZMAT(NPT,*),D(*),VLAG(*),W(*),
+     2  IWF(*)
+      EXTERNAL CALFUN
+      REAL*8 NEWUOB
+C
+C     The arguments N, NPT, X, RHOBEG, RHOEND, IPRINT and MAXFUN are identical
+C       to the corresponding arguments in SUBROUTINE NEWUOA.
+C     XBASE will hold a shift of origin that should reduce the contributions
+C       from rounding errors to values of the model and Lagrange functions.
+C     XOPT will be set to the displacement from XBASE of the vector of
+C       variables that provides the least calculated F so far.
+C     XNEW will be set to the displacement from XBASE of the vector of
+C       variables for the current calculation of F.
+C     XPT will contain the interpolation point coordinates relative to XBASE.
+C     FVAL will hold the values of F at the interpolation points.
+C     GQ will hold the gradient of the quadratic model at XBASE.
+C     HQ will hold the explicit second derivatives of the quadratic model.
+C     PQ will contain the parameters of the implicit second derivatives of
+C       the quadratic model.
+C     BMAT will hold the last N columns of H.
+C     ZMAT will hold the factorization of the leading NPT by NPT submatrix of
+C       H, this factorization being ZMAT times Diag(DZ) times ZMAT^T, where
+C       the elements of DZ are plus or minus one, as specified by IDZ.
+C     NDIM is the first dimension of BMAT and has the value NPT+N.
+C     D is reserved for trial steps from XOPT.
+C     VLAG will contain the values of the Lagrange functions at a new point X.
+C       They are part of a product that requires VLAG to be of length NDIM.
+C     The array W will be used for working space. Its length must be at least
+C       10*NDIM = 10*(NPT+N).
+C
+C     Set some constants.
+C
+      HALF=0.5D0
+      ONE=1.0D0
+      TENTH=0.1D0
+      ZERO=0.0D0
+      NP=N+1
+      NH=(N*NP)/2
+      NPTM=NPT-NP
+      NFTEST=MAX0(MAXFUN,1)
+C
+C     Set the initial elements of XPT, BMAT, HQ, PQ and ZMAT to zero.
+C
+      DO 20 J=1,N
+      XBASE(J)=X(J)
+      DO 10 K=1,NPT
+   10 XPT(K,J)=ZERO
+      DO 20 I=1,NDIM
+   20 BMAT(I,J)=ZERO
+      DO 30 IH=1,NH
+   30 HQ(IH)=ZERO
+      DO 40 K=1,NPT
+      PQ(K)=ZERO
+      DO 40 J=1,NPTM
+   40 ZMAT(K,J)=ZERO
+C
+C     Begin the initialization procedure. NF becomes one more than the number
+C     of function values so far. The coordinates of the displacement of the
+C     next initial interpolation point from XBASE are set in XPT(NF,.).
+C
+      RHOSQ=RHOBEG*RHOBEG
+      RECIP=ONE/RHOSQ
+      RECIQ=DSQRT(HALF)/RHOSQ
+      NF=0
+   50 NFM=NF
+      NFMM=NF-N
+      NF=NF+1
+      IF (NFM .LE. 2*N) THEN
+          IF (NFM .GE. 1 .AND. NFM .LE. N) THEN
+              XPT(NF,NFM)=RHOBEG
+          ELSE IF (NFM .GT. N) THEN
+              XPT(NF,NFMM)=-RHOBEG
+          END IF
+      ELSE
+          ITEMP=(NFMM-1)/N
+          JPT=NFM-ITEMP*N-N
+          IPT=JPT+ITEMP
+          IF (IPT .GT. N) THEN
+              ITEMP=JPT
+              JPT=IPT-N
+              IPT=ITEMP
+          END IF
+          XIPT=RHOBEG
+          IF (FVAL(IPT+NP) .LT. FVAL(IPT+1)) XIPT=-XIPT
+          XJPT=RHOBEG
+          IF (FVAL(JPT+NP) .LT. FVAL(JPT+1)) XJPT=-XJPT
+          XPT(NF,IPT)=XIPT
+          XPT(NF,JPT)=XJPT
+      END IF
+C
+C     Calculate the next value of F, label 70 being reached immediately
+C     after this calculation. The least function value so far and its index
+C     are required.
+C
+      DO 60 J=1,N
+   60 X(J)=XPT(NF,J)+XBASE(J)
+      GOTO 310
+   70 FVAL(NF)=F
+      IF (NF .EQ. 1) THEN
+          FBEG=F
+          FOPT=F
+          KOPT=1
+      ELSE IF (F .LT. FOPT) THEN
+          FOPT=F
+          KOPT=NF
+      END IF
+C
+C     Set the nonzero initial elements of BMAT and the quadratic model in
+C     the cases when NF is at most 2*N+1.
+C
+      IF (NFM .LE. 2*N) THEN
+          IF (NFM .GE. 1 .AND. NFM .LE. N) THEN
+              GQ(NFM)=(F-FBEG)/RHOBEG
+              IF (NPT .LT. NF+N) THEN
+                  BMAT(1,NFM)=-ONE/RHOBEG
+                  BMAT(NF,NFM)=ONE/RHOBEG
+                  BMAT(NPT+NFM,NFM)=-HALF*RHOSQ
+              END IF
+          ELSE IF (NFM .GT. N) THEN
+              BMAT(NF-N,NFMM)=HALF/RHOBEG
+              BMAT(NF,NFMM)=-HALF/RHOBEG
+              ZMAT(1,NFMM)=-RECIQ-RECIQ
+              ZMAT(NF-N,NFMM)=RECIQ
+              ZMAT(NF,NFMM)=RECIQ
+              IH=(NFMM*(NFMM+1))/2
+              TEMP=(FBEG-F)/RHOBEG
+              HQ(IH)=(GQ(NFMM)-TEMP)/RHOBEG
+              GQ(NFMM)=HALF*(GQ(NFMM)+TEMP)
+          END IF
+C
+C     Set the off-diagonal second derivatives of the Lagrange functions and
+C     the initial quadratic model.
+C
+      ELSE
+          IH=(IPT*(IPT-1))/2+JPT
+          IF (XIPT .LT. ZERO) IPT=IPT+N
+          IF (XJPT .LT. ZERO) JPT=JPT+N
+          ZMAT(1,NFMM)=RECIP
+          ZMAT(NF,NFMM)=RECIP
+          ZMAT(IPT+1,NFMM)=-RECIP
+          ZMAT(JPT+1,NFMM)=-RECIP
+          HQ(IH)=(FBEG-FVAL(IPT+1)-FVAL(JPT+1)+F)/(XIPT*XJPT)
+      END IF
+      IF (NF .LT. NPT) GOTO 50
+C
+C     Begin the iterative procedure, because the initial model is complete.
+C
+      RHO=RHOBEG
+      DELTA=RHO
+      IDZ=1
+      DIFFA=ZERO
+      DIFFB=ZERO
+      ITEST=0
+      XOPTSQ=ZERO
+      DO 80 I=1,N
+      XOPT(I)=XPT(KOPT,I)
+   80 XOPTSQ=XOPTSQ+XOPT(I)**2
+   90 NFSAV=NF
+C
+C     Generate the next trust region step and test its length. Set KNEW
+C     to -1 if the purpose of the next F will be to improve the model.
+C
+  100 KNEW=0
+      CALL TRSAPP (N,NPT,XOPT,XPT,GQ,HQ,PQ,DELTA,D,W,W(NP),
+     1  W(NP+N),W(NP+2*N),CRVMIN)
+      DSQ=ZERO
+      DO 110 I=1,N
+  110 DSQ=DSQ+D(I)**2
+      DNORM=DMIN1(DELTA,DSQRT(DSQ))
+      IF (DNORM .LT. HALF*RHO) THEN
+          KNEW=-1
+          DELTA=TENTH*DELTA
+          RATIO=-1.0D0
+          IF (DELTA .LE. 1.5D0*RHO) DELTA=RHO
+          IF (NF .LE. NFSAV+2) GOTO 460
+          TEMP=0.125D0*CRVMIN*RHO*RHO
+          IF (TEMP .LE. DMAX1(DIFFA,DIFFB,DIFFC)) GOTO 460
+          GOTO 490
+      END IF
+C
+C     Shift XBASE if XOPT may be too far from XBASE. First make the changes
+C     to BMAT that do not depend on ZMAT.
+C
+  120 IF (DSQ .LE. 1.0D-3*XOPTSQ) THEN
+          TEMPQ=0.25D0*XOPTSQ
+          DO 140 K=1,NPT
+          SUM=ZERO
+          DO 130 I=1,N
+  130     SUM=SUM+XPT(K,I)*XOPT(I)
+          TEMP=PQ(K)*SUM
+          SUM=SUM-HALF*XOPTSQ
+          W(NPT+K)=SUM
+          DO 140 I=1,N
+          GQ(I)=GQ(I)+TEMP*XPT(K,I)
+          XPT(K,I)=XPT(K,I)-HALF*XOPT(I)
+          VLAG(I)=BMAT(K,I)
+          W(I)=SUM*XPT(K,I)+TEMPQ*XOPT(I)
+          IP=NPT+I
+          DO 140 J=1,I
+  140     BMAT(IP,J)=BMAT(IP,J)+VLAG(I)*W(J)+W(I)*VLAG(J)
+C
+C     Then the revisions of BMAT that depend on ZMAT are calculated.
+C
+          DO 180 K=1,NPTM
+          SUMZ=ZERO
+          DO 150 I=1,NPT
+          SUMZ=SUMZ+ZMAT(I,K)
+  150     W(I)=W(NPT+I)*ZMAT(I,K)
+          DO 170 J=1,N
+          SUM=TEMPQ*SUMZ*XOPT(J)
+          DO 160 I=1,NPT
+  160     SUM=SUM+W(I)*XPT(I,J)
+          VLAG(J)=SUM
+          IF (K .LT. IDZ) SUM=-SUM
+          DO 170 I=1,NPT
+  170     BMAT(I,J)=BMAT(I,J)+SUM*ZMAT(I,K)
+          DO 180 I=1,N
+          IP=I+NPT
+          TEMP=VLAG(I)
+          IF (K .LT. IDZ) TEMP=-TEMP
+          DO 180 J=1,I
+  180     BMAT(IP,J)=BMAT(IP,J)+TEMP*VLAG(J)
+C
+C     The following instructions complete the shift of XBASE, including
+C     the changes to the parameters of the quadratic model.
+C
+          IH=0
+          DO 200 J=1,N
+          W(J)=ZERO
+          DO 190 K=1,NPT
+          W(J)=W(J)+PQ(K)*XPT(K,J)
+  190     XPT(K,J)=XPT(K,J)-HALF*XOPT(J)
+          DO 200 I=1,J
+          IH=IH+1
+          IF (I .LT. J) GQ(J)=GQ(J)+HQ(IH)*XOPT(I)
+          GQ(I)=GQ(I)+HQ(IH)*XOPT(J)
+          HQ(IH)=HQ(IH)+W(I)*XOPT(J)+XOPT(I)*W(J)
+  200     BMAT(NPT+I,J)=BMAT(NPT+J,I)
+          DO 210 J=1,N
+          XBASE(J)=XBASE(J)+XOPT(J)
+  210     XOPT(J)=ZERO
+          XOPTSQ=ZERO
+      END IF
+C
+C     Pick the model step if KNEW is positive. A different choice of D
+C     may be made later, if the choice of D by BIGLAG causes substantial
+C     cancellation in DENOM.
+C
+      IF (KNEW .GT. 0) THEN
+          CALL BIGLAG (N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KNEW,DSTEP,
+     1      D,ALPHA,VLAG,VLAG(NPT+1),W,W(NP),W(NP+N))
+      END IF
+C
+C     Calculate VLAG and BETA for the current choice of D. The first NPT
+C     components of W_check will be held in W.
+C
+      DO 230 K=1,NPT
+      SUMA=ZERO
+      SUMB=ZERO
+      SUM=ZERO
+      DO 220 J=1,N
+      SUMA=SUMA+XPT(K,J)*D(J)
+      SUMB=SUMB+XPT(K,J)*XOPT(J)
+  220 SUM=SUM+BMAT(K,J)*D(J)
+      W(K)=SUMA*(HALF*SUMA+SUMB)
+  230 VLAG(K)=SUM
+      BETA=ZERO
+      DO 250 K=1,NPTM
+      SUM=ZERO
+      DO 240 I=1,NPT
+  240 SUM=SUM+ZMAT(I,K)*W(I)
+      IF (K .LT. IDZ) THEN
+          BETA=BETA+SUM*SUM
+          SUM=-SUM
+      ELSE
+          BETA=BETA-SUM*SUM
+      END IF
+      DO 250 I=1,NPT
+  250 VLAG(I)=VLAG(I)+SUM*ZMAT(I,K)
+      BSUM=ZERO
+      DX=ZERO
+      DO 280 J=1,N
+      SUM=ZERO
+      DO 260 I=1,NPT
+  260 SUM=SUM+W(I)*BMAT(I,J)
+      BSUM=BSUM+SUM*D(J)
+      JP=NPT+J
+      DO 270 K=1,N
+  270 SUM=SUM+BMAT(JP,K)*D(K)
+      VLAG(JP)=SUM
+      BSUM=BSUM+SUM*D(J)
+  280 DX=DX+D(J)*XOPT(J)
+      BETA=DX*DX+DSQ*(XOPTSQ+DX+DX+HALF*DSQ)+BETA-BSUM
+      VLAG(KOPT)=VLAG(KOPT)+ONE
+C
+C     If KNEW is positive and if the cancellation in DENOM is unacceptable,
+C     then BIGDEN calculates an alternative model step, XNEW being used for
+C     working space.
+C
+      IF (KNEW .GT. 0) THEN
+          TEMP=ONE+ALPHA*BETA/VLAG(KNEW)**2
+          IF (DABS(TEMP) .LE. 0.8D0) THEN
+              CALL BIGDEN (N,NPT,XOPT,XPT,BMAT,ZMAT,IDZ,NDIM,KOPT,
+     1          KNEW,D,W,VLAG,BETA,XNEW,W(NDIM+1),W(6*NDIM+1))
+          END IF
+      END IF
+C
+C     Calculate the next value of the objective function.
+C
+  290 DO 300 I=1,N
+      XNEW(I)=XOPT(I)+D(I)
+  300 X(I)=XBASE(I)+XNEW(I)
+      NF=NF+1
+  310 IF (NF .GT. NFTEST) THEN
+          NF=NF-1
+          IF (IPRINT .GT. 0) PRINT 320
+  320     FORMAT (/4X,'Return from NEWUOA because CALFUN has been',
+     1      ' called MAXFUN times.')
+          GOTO 530
+      END IF
+      CALL CALFUN (N,X,F,IWF)
+      IF (IPRINT .EQ. 3) THEN
+          PRINT 330, NF,F,(X(I),I=1,N)
+  330      FORMAT (/4X,'Function number',I6,'    F =',1PD18.10,
+     1       '    The corresponding X is:'/(2X,5D15.6))
+      END IF
+      IF (NF .LE. NPT) GOTO 70
+      IF (KNEW .EQ. -1) GOTO 530
+C
+C     Use the quadratic model to predict the change in F due to the step D,
+C     and set DIFF to the error of this prediction.
+C
+      VQUAD=ZERO
+      IH=0
+      DO 340 J=1,N
+      VQUAD=VQUAD+D(J)*GQ(J)
+      DO 340 I=1,J
+      IH=IH+1
+      TEMP=D(I)*XNEW(J)+D(J)*XOPT(I)
+      IF (I .EQ. J) TEMP=HALF*TEMP
+  340 VQUAD=VQUAD+TEMP*HQ(IH)
+      DO 350 K=1,NPT
+  350 VQUAD=VQUAD+PQ(K)*W(K)
+      DIFF=F-FOPT-VQUAD
+      DIFFC=DIFFB
+      DIFFB=DIFFA
+      DIFFA=DABS(DIFF)
+      IF (DNORM .GT. RHO) NFSAV=NF
+C
+C     Update FOPT and XOPT if the new F is the least value of the objective
+C     function so far. The branch when KNEW is positive occurs if D is not
+C     a trust region step.
+C
+      FSAVE=FOPT
+      IF (F .LT. FOPT) THEN
+          FOPT=F
+          XOPTSQ=ZERO
+          DO 360 I=1,N
+          XOPT(I)=XNEW(I)
+  360     XOPTSQ=XOPTSQ+XOPT(I)**2
+      END IF
+      KSAVE=KNEW
+      IF (KNEW .GT. 0) GOTO 410
+C
+C     Pick the next value of DELTA after a trust region step.
+C
+      IF (VQUAD .GE. ZERO) THEN
+          IF (IPRINT .GT. 0) PRINT 370
+  370     FORMAT (/4X,'Return from NEWUOA because a trust',
+     1      ' region step has failed to reduce Q.')
+          GOTO 530
+      END IF
+      RATIO=(F-FSAVE)/VQUAD
+      IF (RATIO .LE. TENTH) THEN
+          DELTA=HALF*DNORM
+      ELSE IF (RATIO. LE. 0.7D0) THEN
+          DELTA=DMAX1(HALF*DELTA,DNORM)
+      ELSE
+          DELTA=DMAX1(HALF*DELTA,DNORM+DNORM)
+      END IF
+      IF (DELTA .LE. 1.5D0*RHO) DELTA=RHO
+C
+C     Set KNEW to the index of the next interpolation point to be deleted.
+C
+      RHOSQ=DMAX1(TENTH*DELTA,RHO)**2
+      KTEMP=0
+      DETRAT=ZERO
+      IF (F .GE. FSAVE) THEN
+          KTEMP=KOPT
+          DETRAT=ONE
+      END IF
+      DO 400 K=1,NPT
+      HDIAG=ZERO
+      DO 380 J=1,NPTM
+      TEMP=ONE
+      IF (J .LT. IDZ) TEMP=-ONE
+  380 HDIAG=HDIAG+TEMP*ZMAT(K,J)**2
+      TEMP=DABS(BETA*HDIAG+VLAG(K)**2)
+      DISTSQ=ZERO
+      DO 390 J=1,N
+  390 DISTSQ=DISTSQ+(XPT(K,J)-XOPT(J))**2
+      IF (DISTSQ .GT. RHOSQ) TEMP=TEMP*(DISTSQ/RHOSQ)**3
+      IF (TEMP .GT. DETRAT .AND. K .NE. KTEMP) THEN
+          DETRAT=TEMP
+          KNEW=K
+      END IF
+  400 CONTINUE
+      IF (KNEW .EQ. 0) GOTO 460
+C
+C     Update BMAT, ZMAT and IDZ, so that the KNEW-th interpolation point
+C     can be moved. Begin the updating of the quadratic model, starting
+C     with the explicit second derivative term.
+C
+  410 CALL UPDATE (N,NPT,BMAT,ZMAT,IDZ,NDIM,VLAG,BETA,KNEW,W)
+      FVAL(KNEW)=F
+      IH=0
+      DO 420 I=1,N
+      TEMP=PQ(KNEW)*XPT(KNEW,I)
+      DO 420 J=1,I
+      IH=IH+1
+  420 HQ(IH)=HQ(IH)+TEMP*XPT(KNEW,J)
+      PQ(KNEW)=ZERO
+C
+C     Update the other second derivative parameters, and then the gradient
+C     vector of the model. Also include the new interpolation point.
+C
+      DO 440 J=1,NPTM
+      TEMP=DIFF*ZMAT(KNEW,J)
+      IF (J .LT. IDZ) TEMP=-TEMP
+      DO 440 K=1,NPT
+  440 PQ(K)=PQ(K)+TEMP*ZMAT(K,J)
+      GQSQ=ZERO
+      DO 450 I=1,N
+      GQ(I)=GQ(I)+DIFF*BMAT(KNEW,I)
+      GQSQ=GQSQ+GQ(I)**2
+  450 XPT(KNEW,I)=XNEW(I)
+C
+C     If a trust region step makes a small change to the objective function,
+C     then calculate the gradient of the least Frobenius norm interpolant at
+C     XBASE, and store it in W, using VLAG for a vector of right hand sides.
+C
+      IF (KSAVE .EQ. 0 .AND. DELTA .EQ. RHO) THEN
+          IF (DABS(RATIO) .GT. 1.0D-2) THEN
+              ITEST=0
+          ELSE
+              DO 700 K=1,NPT
+  700         VLAG(K)=FVAL(K)-FVAL(KOPT)
+              GISQ=ZERO
+              DO 720 I=1,N
+              SUM=ZERO
+              DO 710 K=1,NPT
+  710         SUM=SUM+BMAT(K,I)*VLAG(K)
+              GISQ=GISQ+SUM*SUM
+  720         W(I)=SUM
+C
+C     Test whether to replace the new quadratic model by the least Frobenius
+C     norm interpolant, making the replacement if the test is satisfied.
+C
+              ITEST=ITEST+1
+              IF (GQSQ .LT. 1.0D2*GISQ) ITEST=0
+              IF (ITEST .GE. 3) THEN
+                  DO 730 I=1,N
+  730             GQ(I)=W(I)
+                  DO 740 IH=1,NH
+  740             HQ(IH)=ZERO
+                  DO 760 J=1,NPTM
+                  W(J)=ZERO
+                  DO 750 K=1,NPT
+  750             W(J)=W(J)+VLAG(K)*ZMAT(K,J)
+  760             IF (J .LT. IDZ) W(J)=-W(J)
+                  DO 770 K=1,NPT
+                  PQ(K)=ZERO
+                  DO 770 J=1,NPTM
+  770             PQ(K)=PQ(K)+ZMAT(K,J)*W(J)
+                  ITEST=0
+              END IF
+          END IF
+      END IF
+      IF (F .LT. FSAVE) KOPT=KNEW
+C
+C     If a trust region step has provided a sufficient decrease in F, then
+C     branch for another trust region calculation. The case KSAVE>0 occurs
+C     when the new function value was calculated by a model step.
+C
+      IF (F .LE. FSAVE+TENTH*VQUAD) GOTO 100
+      IF (KSAVE .GT. 0) GOTO 100
+C
+C     Alternatively, find out if the interpolation points are close enough
+C     to the best point so far.
+C
+      KNEW=0
+  460 DISTSQ=4.0D0*DELTA*DELTA
+      DO 480 K=1,NPT
+      SUM=ZERO
+      DO 470 J=1,N
+  470 SUM=SUM+(XPT(K,J)-XOPT(J))**2
+      IF (SUM .GT. DISTSQ) THEN
+          KNEW=K
+          DISTSQ=SUM
+      END IF
+  480 CONTINUE
+C
+C     If KNEW is positive, then set DSTEP, and branch back for the next
+C     iteration, which will generate a "model step".
+C
+      IF (KNEW .GT. 0) THEN
+          DSTEP=DMAX1(DMIN1(TENTH*DSQRT(DISTSQ),HALF*DELTA),RHO)
+          DSQ=DSTEP*DSTEP
+          GOTO 120
+      END IF
+      IF (RATIO .GT. ZERO) GOTO 100
+      IF (DMAX1(DELTA,DNORM) .GT. RHO) GOTO 100
+C
+C     The calculations with the current value of RHO are complete. Pick the
+C     next values of RHO and DELTA.
+C
+  490 IF (RHO .GT. RHOEND) THEN
+          DELTA=HALF*RHO
+          RATIO=RHO/RHOEND
+          IF (RATIO .LE. 16.0D0) THEN
+              RHO=RHOEND
+          ELSE IF (RATIO .LE. 250.0D0) THEN
+              RHO=DSQRT(RATIO)*RHOEND
+          ELSE
+              RHO=TENTH*RHO
+          END IF
+          DELTA=DMAX1(DELTA,RHO)
+          IF (IPRINT .GE. 2) THEN
+              IF (IPRINT .GE. 3) PRINT 500
+  500         FORMAT (5X)
+              PRINT 510, RHO,NF
+  510         FORMAT (/4X,'New RHO =',1PD11.4,5X,'Number of',
+     1          ' function values =',I6)
+              PRINT 520, FOPT,(XBASE(I)+XOPT(I),I=1,N)
+  520         FORMAT (4X,'Least value of F =',1PD23.15,9X,
+     1          'The corresponding X is:'/(2X,5D15.6))
+          END IF
+          GOTO 90
+      END IF
+C
+C     Return from the calculation, after another Newton-Raphson step, if
+C     it is too short to have been tried before.
+C
+      IF (KNEW .EQ. -1) GOTO 290
+  530 IF (FOPT .LE. F) THEN
+          DO 540 I=1,N
+  540     X(I)=XBASE(I)+XOPT(I)
+          F=FOPT
+      END IF
+      IF (IPRINT .GE. 1) THEN
+          PRINT 550, NF
+  550     FORMAT (/4X,'At the return from NEWUOA',5X,
+     1      'Number of function values =',I6)
+          PRINT 520, F,(X(I),I=1,N)
+      END IF
+      NEWUOB =F
+      RETURN 
+      END 
+      SUBROUTINE TRSAPP (N,NPT,XOPT,XPT,GQ,HQ,PQ,DELTA,STEP,
+     1  D,G,HD,HS,CRVMIN)
+      IMPLICIT REAL*8 (A-H,O-Z)
+      DIMENSION XOPT(*),XPT(NPT,*),GQ(*),HQ(*),PQ(*),STEP(*),
+     1  D(*),G(*),HD(*),HS(*)
+C
+C     N is the number of variables of a quadratic objective function, Q say.
+C     The arguments NPT, XOPT, XPT, GQ, HQ and PQ have their usual meanings,
+C       in order to define the current quadratic model Q.
+C     DELTA is the trust region radius, and has to be positive.
+C     STEP will be set to the calculated trial step.
+C     The arrays D, G, HD and HS will be used for working space.
+C     CRVMIN will be set to the least curvature of H along the conjugate
+C       directions that occur, except that it is set to zero if STEP goes
+C       all the way to the trust region boundary.
+C
+C     The calculation of STEP begins with the truncated conjugate gradient
+C     method. If the boundary of the trust region is reached, then further
+C     changes to STEP may be made, each one being in the 2D space spanned
+C     by the current STEP and the corresponding gradient of Q. Thus STEP
+C     should provide a substantial reduction to Q within the trust region.
+C
+C     Initialization, which includes setting HD to H times XOPT.
+C
+      HALF=0.5D0
+      ZERO=0.0D0
+      TWOPI=8.0D0*DATAN(1.0D0)
+      DELSQ=DELTA*DELTA
+      ITERC=0
+      ITERMAX=N
+      ITERSW=ITERMAX
+      DO 10 I=1,N
+   10 D(I)=XOPT(I)
+      GOTO 170
+C
+C     Prepare for the first line search.
+C
+   20 QRED=ZERO
+      DD=ZERO
+      DO 30 I=1,N
+      STEP(I)=ZERO
+      HS(I)=ZERO
+      G(I)=GQ(I)+HD(I)
+      D(I)=-G(I)
+   30 DD=DD+D(I)**2
+      CRVMIN=ZERO
+      IF (DD .EQ. ZERO) GOTO 160
+      DS=ZERO
+      SS=ZERO
+      GG=DD
+      GGBEG=GG
+C
+C     Calculate the step to the trust region boundary and the product HD.
+C
+   40 ITERC=ITERC+1
+      TEMP=DELSQ-SS
+      BSTEP=TEMP/(DS+DSQRT(DS*DS+DD*TEMP))
+      GOTO 170
+   50 DHD=ZERO
+      DO 60 J=1,N
+   60 DHD=DHD+D(J)*HD(J)
+C
+C     Update CRVMIN and set the step-length ALPHA.
+C
+      ALPHA=BSTEP
+      IF (DHD .GT. ZERO) THEN
+          TEMP=DHD/DD
+          IF (ITERC .EQ. 1) CRVMIN=TEMP
+          CRVMIN=DMIN1(CRVMIN,TEMP)
+          ALPHA=DMIN1(ALPHA,GG/DHD)
+      END IF
+      QADD=ALPHA*(GG-HALF*ALPHA*DHD)
+      QRED=QRED+QADD
+C
+C     Update STEP and HS.
+C
+      GGSAV=GG
+      GG=ZERO
+      DO 70 I=1,N
+      STEP(I)=STEP(I)+ALPHA*D(I)
+      HS(I)=HS(I)+ALPHA*HD(I)
+   70 GG=GG+(G(I)+HS(I))**2
+C
+C     Begin another conjugate direction iteration if required.
+C
+      IF (ALPHA .LT. BSTEP) THEN
+          IF (QADD .LE. 0.01D0*QRED) GOTO 160
+          IF (GG .LE. 1.0D-4*GGBEG) GOTO 160
+          IF (ITERC .EQ. ITERMAX) GOTO 160
+          TEMP=GG/GGSAV
+          DD=ZERO
+          DS=ZERO
+          SS=ZERO
+          DO 80 I=1,N
+          D(I)=TEMP*D(I)-G(I)-HS(I)
+          DD=DD+D(I)**2
+          DS=DS+D(I)*STEP(I)
+   80     SS=SS+STEP(I)**2
+          IF (DS .LE. ZERO) GOTO 160
+          IF (SS .LT. DELSQ) GOTO 40
+      END IF
+      CRVMIN=ZERO
+      ITERSW=ITERC
+C
+C     Test whether an alternative iteration is required.
+C
+   90 IF (GG .LE. 1.0D-4*GGBEG) GOTO 160
+      SG=ZERO
+      SHS=ZERO
+      DO 100 I=1,N
+      SG=SG+STEP(I)*G(I)
+  100 SHS=SHS+STEP(I)*HS(I)
+      SGK=SG+SHS
+      ANGTEST=SGK/DSQRT(GG*DELSQ)
+      IF (ANGTEST .LE. -0.99D0) GOTO 160
+C
+C     Begin the alternative iteration by calculating D and HD and some
+C     scalar products.
+C
+      ITERC=ITERC+1
+      TEMP=DSQRT(DELSQ*GG-SGK*SGK)
+      TEMPA=DELSQ/TEMP
+      TEMPB=SGK/TEMP
+      DO 110 I=1,N
+  110 D(I)=TEMPA*(G(I)+HS(I))-TEMPB*STEP(I)
+      GOTO 170
+  120 DG=ZERO
+      DHD=ZERO
+      DHS=ZERO
+      DO 130 I=1,N
+      DG=DG+D(I)*G(I)
+      DHD=DHD+HD(I)*D(I)
+  130 DHS=DHS+HD(I)*STEP(I)
+C
+C     Seek the value of the angle that minimizes Q.
+C
+      CF=HALF*(SHS-DHD)
+      QBEG=SG+CF
+      QSAV=QBEG
+      QMIN=QBEG
+      ISAVE=0
+      IU=49
+      TEMP=TWOPI/DFLOAT(IU+1)
+      DO 140 I=1,IU
+      ANGLE=DFLOAT(I)*TEMP
+      CTH=DCOS(ANGLE)
+      STH=DSIN(ANGLE)
+      QNEW=(SG+CF*CTH)*CTH+(DG+DHS*CTH)*STH
+      IF (QNEW .LT. QMIN) THEN
+          QMIN=QNEW
+          ISAVE=I
+          TEMPA=QSAV
+      ELSE IF (I .EQ. ISAVE+1) THEN
+          TEMPB=QNEW
+      END IF
+  140 QSAV=QNEW
+      IF (ISAVE .EQ. ZERO) TEMPA=QNEW
+      IF (ISAVE .EQ. IU) TEMPB=QBEG
+      ANGLE=ZERO
+      IF (TEMPA .NE. TEMPB) THEN
+          TEMPA=TEMPA-QMIN
+          TEMPB=TEMPB-QMIN
+          ANGLE=HALF*(TEMPA-TEMPB)/(TEMPA+TEMPB)
+      END IF
+      ANGLE=TEMP*(DFLOAT(ISAVE)+ANGLE)
+C
+C     Calculate the new STEP and HS. Then test for convergence.
+C
+      CTH=DCOS(ANGLE)
+      STH=DSIN(ANGLE)
+      REDUC=QBEG-(SG+CF*CTH)*CTH-(DG+DHS*CTH)*STH
+      GG=ZERO
+      DO 150 I=1,N
+      STEP(I)=CTH*STEP(I)+STH*D(I)
+      HS(I)=CTH*HS(I)+STH*HD(I)
+  150 GG=GG+(G(I)+HS(I))**2
+      QRED=QRED+REDUC
+      RATIO=REDUC/QRED
+      IF (ITERC .LT. ITERMAX .AND. RATIO .GT. 0.01D0) GOTO 90
+  160 RETURN
+C
+C     The following instructions act as a subroutine for setting the vector
+C     HD to the vector D multiplied by the second derivative matrix of Q.
+C     They are called from three different places, which are distinguished
+C     by the value of ITERC.
+C
+  170 DO 180 I=1,N
+  180 HD(I)=ZERO
+      DO 200 K=1,NPT
+      TEMP=ZERO
+      DO 190 J=1,N
+  190 TEMP=TEMP+XPT(K,J)*D(J)
+      TEMP=TEMP*PQ(K)
+      DO 200 I=1,N
+  200 HD(I)=HD(I)+TEMP*XPT(K,I)
+      IH=0
+      DO 210 J=1,N
+      DO 210 I=1,J
+      IH=IH+1
+      IF (I .LT. J) HD(J)=HD(J)+HQ(IH)*D(I)
+  210 HD(I)=HD(I)+HQ(IH)*D(J)
+      IF (ITERC .EQ. 0) GOTO 20
+      IF (ITERC .LE. ITERSW) GOTO 50
+      GOTO 120
+      END
+
+      SUBROUTINE UPDATE (N,NPT,BMAT,ZMAT,IDZ,NDIM,VLAG,BETA,KNEW,W)
+      IMPLICIT REAL*8 (A-H,O-Z)
+      DIMENSION BMAT(NDIM,*),ZMAT(NPT,*),VLAG(*),W(*)
+C
+C     The arrays BMAT and ZMAT with IDZ are updated, in order to shift the
+C     interpolation point that has index KNEW. On entry, VLAG contains the
+C     components of the vector Theta*Wcheck+e_b of the updating formula
+C     (6.11), and BETA holds the value of the parameter that has this name.
+C     The vector W is used for working space.
+C
+C     Set some constants.
+C
+      ONE=1.0D0
+      ZERO=0.0D0
+      NPTM=NPT-N-1
+C
+C     Apply the rotations that put zeros in the KNEW-th row of ZMAT.
+C
+      JL=1
+      DO 20 J=2,NPTM
+      IF (J .EQ. IDZ) THEN
+          JL=IDZ
+      ELSE IF (ZMAT(KNEW,J) .NE. ZERO) THEN
+          TEMP=DSQRT(ZMAT(KNEW,JL)**2+ZMAT(KNEW,J)**2)
+          TEMPA=ZMAT(KNEW,JL)/TEMP
+          TEMPB=ZMAT(KNEW,J)/TEMP
+          DO 10 I=1,NPT
+          TEMP=TEMPA*ZMAT(I,JL)+TEMPB*ZMAT(I,J)
+          ZMAT(I,J)=TEMPA*ZMAT(I,J)-TEMPB*ZMAT(I,JL)
+   10     ZMAT(I,JL)=TEMP
+          ZMAT(KNEW,J)=ZERO
+      END IF
+   20 CONTINUE
+C
+C     Put the first NPT components of the KNEW-th column of HLAG into W,
+C     and calculate the parameters of the updating formula.
+C
+      TEMPA=ZMAT(KNEW,1)
+      IF (IDZ .GE. 2) TEMPA=-TEMPA
+      IF (JL .GT. 1) TEMPB=ZMAT(KNEW,JL)
+      DO 30 I=1,NPT
+      W(I)=TEMPA*ZMAT(I,1)
+      IF (JL .GT. 1) W(I)=W(I)+TEMPB*ZMAT(I,JL)
+   30 CONTINUE
+      ALPHA=W(KNEW)
+      TAU=VLAG(KNEW)
+      TAUSQ=TAU*TAU
+      DENOM=ALPHA*BETA+TAUSQ
+      VLAG(KNEW)=VLAG(KNEW)-ONE
+C
+C     Complete the updating of ZMAT when there is only one nonzero element
+C     in the KNEW-th row of the new matrix ZMAT, but, if IFLAG is set to one,
+C     then the first column of ZMAT will be exchanged with another one later.
+C
+      IFLAG=0
+      IF (JL .EQ. 1) THEN
+          TEMP=DSQRT(DABS(DENOM))
+          TEMPB=TEMPA/TEMP
+          TEMPA=TAU/TEMP
+          DO 40 I=1,NPT
+   40     ZMAT(I,1)=TEMPA*ZMAT(I,1)-TEMPB*VLAG(I)
+          IF (IDZ .EQ. 1 .AND. TEMP .LT. ZERO) IDZ=2
+          IF (IDZ .GE. 2 .AND. TEMP .GE. ZERO) IFLAG=1
+      ELSE
+C
+C     Complete the updating of ZMAT in the alternative case.
+C
+          JA=1
+          IF (BETA .GE. ZERO) JA=JL
+          JB=JL+1-JA
+          TEMP=ZMAT(KNEW,JB)/DENOM
+          TEMPA=TEMP*BETA
+          TEMPB=TEMP*TAU
+          TEMP=ZMAT(KNEW,JA)
+          SCALA=ONE/DSQRT(DABS(BETA)*TEMP*TEMP+TAUSQ)
+          SCALB=SCALA*DSQRT(DABS(DENOM))
+          DO 50 I=1,NPT
+          ZMAT(I,JA)=SCALA*(TAU*ZMAT(I,JA)-TEMP*VLAG(I))
+   50     ZMAT(I,JB)=SCALB*(ZMAT(I,JB)-TEMPA*W(I)-TEMPB*VLAG(I))
+          IF (DENOM .LE. ZERO) THEN
+              IF (BETA .LT. ZERO) IDZ=IDZ+1
+              IF (BETA .GE. ZERO) IFLAG=1
+          END IF
+      END IF
+C
+C     IDZ is reduced in the following case, and usually the first column
+C     of ZMAT is exchanged with a later one.
+C
+      IF (IFLAG .EQ. 1) THEN
+          IDZ=IDZ-1
+          DO 60 I=1,NPT
+          TEMP=ZMAT(I,1)
+          ZMAT(I,1)=ZMAT(I,IDZ)
+   60     ZMAT(I,IDZ)=TEMP
+      END IF
+C
+C     Finally, update the matrix BMAT.
+C
+      DO 70 J=1,N
+      JP=NPT+J
+      W(JP)=BMAT(KNEW,J)
+      TEMPA=(ALPHA*VLAG(JP)-TAU*W(JP))/DENOM
+      TEMPB=(-BETA*W(JP)-TAU*VLAG(JP))/DENOM
+      DO 70 I=1,JP
+      BMAT(I,J)=BMAT(I,J)+TEMPA*VLAG(I)+TEMPB*W(I)
+      IF (I .GT. NPT) BMAT(JP,I-NPT)=BMAT(I,J)
+   70 CONTINUE
+      RETURN
+      END 
diff --git a/examples++-load/pcm.cpp b/examples++-load/pcm.cpp
new file mode 100644
index 0000000..7113a06
--- /dev/null
+++ b/examples++-load/pcm.cpp
@@ -0,0 +1,244 @@
+
+/*
+ * pcm.c - contains the methods for the PCM class
+ *
+ * Author: Dion Crannitch (adapted from Dave Mason's complexMap class)
+ * Last Modified : 22 June 1999
+ * Last Modified: 20 Oct. 2009  (F. Hecht,  Frederic.Hecht at upmc.fr)   for g++ v4 
+ *  change ENDIANESS interface
+ *         add  missing read max value in file        
+ *         add const in char * declaration  for g++-4.
+ *         change 32 in 4  for the size of float . 
+ */
+
+using namespace std;
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <cmath>
+//#include "bytesex.h"
+#include <fstream>
+#include "pcm.hpp"
+#include <iostream>
+
+#define BINARY_IN  ios::binary | ios::in
+#define BINARY_OUT ios::binary | ios::out
+#define TOKEN_SIZE 100
+
+
+PCM::PCM(int w, int h) {
+  width=w; height=h; pixels=w*h; max=0.0;
+  image=new pcm_complex[pixels];
+  
+}
+
+
+PCM::PCM(const char *filename) 
+: image(0)
+  {
+  Load(filename);
+}
+
+
+void PCM::CalcMax() {
+  unsigned long p;
+  float i,r,m;
+  
+  max=m=0.0;
+
+  for(p=0; p<pixels; p++) {
+    r=image[p].r; i=image[p].i;
+    m=r*r+i*i;
+    if (m>max) max=m;
+  }
+  max=sqrt(max);
+}
+
+
+void PCM::Set(int x, int y, pcm_complex c){
+  if ((x>=0)&&(y>=0)&&(x<width)&&(y<height))
+    image[(y*width)+x]=c;
+}
+
+
+pcm_complex *PCM::Get(int x, int y){
+  if ((x>=0)&&(y>=0)&&(x<width)&&(y<height)) {
+    return &image[(y*width)+x];
+  } else {
+    return NULL;
+  }
+}
+
+
+PCM::~PCM() {
+  delete[] image;
+}
+
+
+// fatal error function - print error message then exit
+void fatal_error(const char *mesg){
+  fprintf(stderr, "%s\nFatal error - exitting\n", mesg);
+  exit(0);
+}
+
+
+/* For compatibility between systems, the floats in PCM files are 
+ * always saved as little endian. Therefore on big endian platforms, 
+ * they must be converted during load and save procedures.
+ */
+
+// change float from BIG_ENDIAN to LITTLE_ENDIAN and vice versa 
+void swap_float_endian(float *number){
+
+  if (sizeof(float)!=4)
+    {
+      fatal_error("PCM -> sizeof(float) != 4.\nProgram cannot continue - exiting.");
+   
+    }
+  
+  float in = *number;
+  float out;
+  ((char *) &out)[0] = ((char *) &in)[3];
+  ((char *) &out)[1] = ((char *) &in)[2];
+  ((char *) &out)[2] = ((char *) &in)[1];
+  ((char *) &out)[3] = ((char *) &in)[0];
+  *number = out;
+}
+
+
+// dummy function
+void do_nothing(float *number){
+  // do nothing
+}
+
+
+// get a token from the input stream
+void extract_token(ifstream &input_stream, char *token, int max_size){
+  int count=0;
+  char ch;
+
+  // skip any whitespace or comments
+  do { 
+    input_stream.read((char *)&ch, sizeof(char));
+    // if we've hit a comment char then read till the next "\n" 
+    if (ch == '#')
+      while (ch != '\n')
+	input_stream.read((char *)&ch, sizeof(char *));
+  } while (ch == ' ' || ch == '\t' || ch == '\n');
+
+  // copy data into 'token'
+  do {
+    if (count >= max_size-1) fatal_error("extract_token -> token too large");
+    token[count++] = ch;
+    input_stream.read((char *)&ch, sizeof(char));
+  } while (ch != ' ' && ch != '\t' && ch != '\n' && ch != '.');
+  input_stream.putback(ch);
+  token[count] = '\0';
+}
+
+
+void PCM::Load(const char *filename) {
+
+  char token[TOKEN_SIZE];
+  ifstream input_stream(filename,BINARY_IN);
+  if (!input_stream) fatal_error("PCM::Load -> file not found.");
+
+  // check magic number
+  extract_token(input_stream,token,TOKEN_SIZE);
+  if (strcmp(token,"PC") != 0){
+    fprintf(stderr,"Magic number \"%s\" != PC\n", token);
+    fatal_error("PCM::Load -> bad magic number");
+  }
+
+  // get dimensions
+  extract_token(input_stream,token,TOKEN_SIZE);
+  width = atoi(token);
+  extract_token(input_stream,token,TOKEN_SIZE);
+  height = atoi(token);
+  extract_token(input_stream,token,TOKEN_SIZE);
+  max = atof(token);
+  cout <<" pcm : " <<  width << "x" << height << "  max :" << max << endl;
+  // Reallocate memory, if necessary.
+  unsigned long p = (long)(width * height); 
+  if (p!=pixels) {
+    pixels=p;
+    if (image) {
+      delete[] image; image=NULL;
+    }
+  }
+  if (!image) image=new pcm_complex[pixels];
+
+
+  // skip max cols
+  extract_token(input_stream,token,TOKEN_SIZE);
+  char ch;
+  input_stream.read((char*)&ch, sizeof(char));
+
+  // if machine is big endian then we need to convert floats from little endian 
+  void (*endian_filter)(float *);
+    int i4=1;
+    char zero_is_little_endian=  * ((static_cast<const char *>((void *) &i4))+3);
+  
+  if( zero_is_little_endian == 0)
+  endian_filter = (void (*)(float *))do_nothing;
+  else
+  endian_filter = (void (*)(float *))swap_float_endian;
+
+  // read data
+  for (int y = 0; y < height; y++)
+    for (int x = 0; x < width; x++){    
+      pcm_complex c;
+      input_stream.read((char *)(void *)&c.r, sizeof(c.r));
+      input_stream.read((char *)(void *)&c.i, sizeof(c.i));
+    if (x < 0 && y < 0)
+      cout << x << y << "   " << c.r << " " << c.i << endl;
+      endian_filter(&c.r);
+      endian_filter(&c.i);
+      Set(x,y,c);
+    }
+
+  input_stream.close();
+
+}
+
+
+
+void PCM::Save(const char *filename){
+    
+  ofstream output_stream(filename, BINARY_OUT);
+  if (!output_stream) fatal_error("PCM::Save -> error creating file.");
+
+  // find the maximum vector magnitude
+  CalcMax();
+
+  char header[100];
+  sprintf(header,"PC\n%d %d\n%f\n",width,height,max);
+  output_stream.write(header,strlen(header));
+
+    void (*endian_filter)(float *);
+    int i4=1;
+    char zero_is_little_endian=  * ((static_cast<const char *>((void *) &i4))+3);
+    
+    if( zero_is_little_endian == 0)
+	endian_filter = (void (*)(float *))do_nothing;
+    else
+	endian_filter = (void (*)(float *))swap_float_endian;
+    
+   // write data
+  pcm_complex *c;
+  for (int y = 0; y < height; y++)
+    for (int x = 0; x < width; x++){
+      c = Get(x,y);
+      if (c) {
+	endian_filter(&(c->r));
+	endian_filter(&(c->i));
+	output_stream.write((const char *)(const void *)&(c->r), sizeof(c->r));
+	output_stream.write((const char *)(const void *)&(c->i), sizeof(c->i));
+      }
+    }
+  output_stream.close();
+}
+
+
+
+
diff --git a/examples++-load/pcm.hpp b/examples++-load/pcm.hpp
new file mode 100644
index 0000000..c00c68a
--- /dev/null
+++ b/examples++-load/pcm.hpp
@@ -0,0 +1,44 @@
+
+/*
+ * pcm.h
+ *
+ * Author: Dion Crannitch (adapted from Dave Mason's complexMap class)
+ * Modified : 22 June 1999
+ * Last Modified: 20 Oct. 2009  (F. Hecht,  Frederic.Hecht at upmc.fr)   for g++ v4 
+ *
+ * Declarations for PCM class, a data structure containing a 2D vector
+ * image, with encapsulated operations for reading and writing PCM files.
+ *
+ */
+
+#ifndef __PCM__
+#define __PCM__
+
+#include <cstdio>
+using namespace std;
+typedef struct { 
+  float r,i;
+} pcm_complex;
+
+class PCM {
+  void CalcMax();
+ public:
+  int  width,height;
+  unsigned long pixels;
+  float max;
+  pcm_complex *image; 
+  PCM(int w,int h);
+  PCM(const char *filename);
+  pcm_complex *Get(int x, int y);
+  void Set(int x, int y, pcm_complex c);
+  void Load(const char *filename);
+  void Save(const char *filename);
+  ~PCM();
+private:
+    PCM (const PCM &);
+    void operator=(const PCM &);
+};
+
+#endif
+
+
diff --git a/examples++-load/pcm2rnm.cpp b/examples++-load/pcm2rnm.cpp
new file mode 100644
index 0000000..4b11afa
--- /dev/null
+++ b/examples++-load/pcm2rnm.cpp
@@ -0,0 +1,121 @@
+// SUMMARY  :   add interface to read pcm or pmm  bitmap imahe  image 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : F. Hecht
+// E-MAIL   : F. Hecht <hecht at ljll.math.upmc.fr>
+//  date : 2008  ????
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+//  for auto dependance ... 
+//ff-c++-cpp-dep:pcm.cpp
+
+//   tools to read ppm file 
+/*  use in freefem++ edp
+  see :
+  real[int,int] ff1("tt.pmm"); // read  image and set to an array. 
+  real[int]  ff(ff1.nx*ff1.ny);
+  ff=ff1; 
+ */
+//   tools to read ppm file 
+/*  use in freefem++ edp file:
+  -----------------------------
+  complex[int,int] cc(1,1);
+  readpcm("tt.pcm",cc); // read  the flow image and set to un complex matrix array. 
+  or 
+  real[int,int] u(1,1),v(1,1);
+  readpcm("tt.pcm",u,v); // read the flow image and set to 2  real  matrix array. 
+*/
+#include "pcm.hpp"
+#include  <iostream>
+#include  <cfloat>
+
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+using namespace std;  
+
+#include "RNM.hpp"
+#include <cmath>
+
+
+long read1(const long& ,const long&){
+    return 1;
+}
+
+    
+KNM<Complex> * read_pcm(string * filename,KNM<Complex> * p)
+    {
+      
+      PCM pcm(filename->c_str());
+      p->resize(pcm.width,pcm.height);
+      pcm_complex *pc=pcm.image;
+      for(int j=0;j<pcm.height;++j)
+      for(int i=0;i<pcm.width;++i,pc++)
+	      (*p)(i,j)= Complex(pc->r,pc->i);
+	      
+
+      return p;	  
+    }
+long read_pcm(string * const &filename,KNM<double> * const &u,KNM<double> * const &v)
+{
+    
+    PCM pcm(filename->c_str());
+    cout << " pcm  " << filename->c_str() << " : " <<pcm.width << " x " << pcm.height << endl;
+    u->resize(pcm.width,pcm.height);
+    v->resize(pcm.width,pcm.height);
+    pcm_complex *pc;
+    float x1=-1e+30,x2=-1e+30;
+    for(int j=0;j<pcm.height;++j)
+	for(int i=0;i<pcm.width;++i)
+	  {
+	    pc = pcm.Get(i,j);
+	    if(pc)
+	      {
+		
+	      
+	    (*u)(i,j)= pc->r;
+	    (*v)(i,j)= pc->i;
+	    
+	    x1 = max(x1,pc->r);
+	    x2 = max(x2,pc->i);
+	    if(i<0 && j < 0)
+	    cout << i << " " << j << " " << pc->r << " " << pc->i << endl;
+	       }
+	  }
+    cout << " max uv : " << x1 << " " << x2 << endl;
+    return pcm.width*pcm.height;	  
+}
+
+ /*  class Init { public:
+  Init();
+};
+
+$1 */
+static void Load_Init(){
+  cout << " load: init pcm2rmn  " << endl;
+ 
+
+    Global.Add("readpcm", "(",
+    new OneOperator2<KNM<Complex> *,string*,KNM<Complex> * >(&read_pcm),
+    new OneOperator3_<long,string*,KNM<double> *,KNM<double> * >(&read_pcm)
+		    );
+  
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/pipe.cpp b/examples++-load/pipe.cpp
new file mode 100644
index 0000000..25ca0c2
--- /dev/null
+++ b/examples++-load/pipe.cpp
@@ -0,0 +1,203 @@
+// to compile ff-c++ pipe.cpp
+//  warning do not compile under windows...
+#include "ff++.hpp"
+#include <cstdio>
+#include <unistd.h>
+
+
+#ifdef WIN32
+#include <Windows.h>
+
+
+long ffsleep(long  s) { Sleep(s*1000);return 0;}
+long ffusleep(long  s) {  Sleep(s/1000);return 0;}
+#else
+long ffsleep(long  s) { return sleep(s);}
+long ffusleep(long  s) { return usleep(s);}
+#endif
+
+#if __clang_major__ > 4
+
+#include "pstream.h"
+
+struct pstream {
+    redi::basic_pstream<char>  * fb;
+    //stdiofilebuf * fb;
+    ostream *os;
+    istream *is;
+    pstream(redi::basic_pstream<char>  *ff,std::ios_base::openmode mode)
+    : fb(ff) ,os(0),is(0)
+    {  if(verbosity>10) cout << " mode " << mode << endl;
+        basic_iostream<char> *   bs = fb;//->rdbuf();
+        ffassert(bs);
+        if(mode & ios_base::in )  {is = dynamic_cast<istream *>(bs);  assert(is);}//new istream(fb);
+        if(mode & ios_base::out ) {os = dynamic_cast<ostream *>(bs);assert(os);} //new ostream(fb);
+        if(verbosity>10)  cout << is << " " << os << " ******* " << endl;
+    }
+    ~pstream() {
+       // if(f)  delete f;;
+     //   if(os) delete os;
+      //  if(is) delete is;
+        if(fb) delete(fb);
+       // f=0;
+        os=0;
+        is=0;
+        fb=0;
+    }
+    void flush()
+    {
+        if( os ) os->flush();
+        //if( is ) is->flush();
+    }
+    
+};
+
+static pstream **  pstream_init(pstream **const & p,string * const & a,string * const & b)
+{
+    string mode= b ? *b: "w";
+    if (mode.length() ==0) mode = "wr";
+   /* redi::pstreams::pmode omp = redi::pstreams::pstdin|redi::pstreams::pstdout;
+    if (mode == "r+" )      omp = redi::pstreams::pstdin|redi::pstreams::pstdout;
+    else if( mode == "w"  ) omp = redi::pstreams::pstdout;
+    else if(  mode == "r" ) omp = redi::pstreams::pstdin;
+*/
+    std::ios_base::openmode  om = ios_base::in| ios_base::out;
+    if (mode == "r+" )      om =ios_base::in| ios_base::out;
+    else if( mode == "w"  ) om = ios_base::out;
+    else if(  mode == "r" ) om =  ios_base::in;
+    else  ExecError("Invalide mode pstream r,r+,w ");
+    if(verbosity>10)  *ffapi::cout()  << "pstream_init: om " << om << "(" <<ios_base::in << ios_base::out << ") mode:"
+        << mode << " '" << *a <<"'"<<  endl;
+
+    redi::basic_pstream<char>  *pp = new redi::pstream(a->c_str(),om);
+    ffassert(pp);
+    *p =  new pstream(pp,om);
+    
+    if ( !*p || !pp) {
+        cerr << " Error openning pipe  " << *a << endl;
+        ExecError("Error openning pipe");}
+    
+    return p;
+};
+
+static pstream **  pstream_init(pstream **const & p,string * const & a)
+{
+    return pstream_init(p,a,0);
+};
+
+#else
+// VERSION GNU
+#include <ext/stdio_filebuf.h>
+
+
+typedef __gnu_cxx::stdio_filebuf<char> stdiofilebuf;
+struct pstream {
+    FILE * f; 
+    stdiofilebuf * fb;
+    ostream *os;
+    istream *is;
+    pstream(FILE *ff,std::ios_base::openmode mode)
+     : f(ff),fb(new stdiofilebuf(f,mode) ) ,os(0),is(0)
+    {  if(verbosity>10) cout << " mode " << mode << endl;
+        if(mode & ios_base::in )  is = new istream(fb);
+        if(mode & ios_base::out ) os = new ostream(fb);
+        if(verbosity>10)  cout << is << " " << os << " ******* " << endl;
+    }
+    ~pstream() {
+        if(f) pclose(f);
+        if(os) delete os;
+        if(is) delete is;
+        if(fb) delete(fb);
+        f=0;
+        os=0;
+        is=0;
+        fb=0;
+}
+   void flush()
+    {
+        if( os ) os->flush();
+        if( f) fflush(f);
+    }
+};
+//typedef redi::pstream pstream;
+// typedef std::string string;
+
+static pstream **  pstream_init(pstream **const & p,string * const & a,string * const & b)
+{
+    string mode= b ? *b: "w";
+    if (mode.length() ==0) mode = "wr";
+    std::ios_base::openmode  om = ios_base::in| ios_base::out;
+    if (mode == "r+" )      om =ios_base::in| ios_base::out;
+    else if( mode == "w"  ) om = ios_base::out;
+    else if(  mode == "r" ) om =  ios_base::in;
+    else  ExecError("Invalide mode pstream r,r+,w ");
+    if(verbosity>10)  *ffapi::cout()  << "pstream_init: om " << om << "(" <<ios_base::in << ios_base::out << ") mode:"
+        << mode << " '" << *a <<"'"<<  endl;
+#ifdef WIN32
+    FILE * pp =_popen(a->c_str(),mode.c_str());
+#else
+    FILE * pp =popen(a->c_str(),mode.c_str());
+#endif
+    *p =  new pstream(pp,om);
+    
+    if ( !*p || !pp) {
+        cerr << " Error openning pipe  " << *a << endl;
+        ExecError("Error openning pipe");}
+    
+    return p;
+};
+
+static pstream **  pstream_init(pstream **const & p,string * const & a)
+{
+    return pstream_init(p,a,0);
+};
+#endif
+
+
+
+AnyType pstream2o(Stack,const AnyType &a) {
+    pstream* p = *PGetAny<pstream*>(a);
+    ffassert(p->os);
+    return   SetAny<ostream*>(p->os);}
+    
+AnyType pstream2i(Stack,const AnyType &a) {
+        pstream* p = *PGetAny<pstream*>(a);
+        ffassert(p->is);
+        return   SetAny<istream*>(p->is);}
+
+class istream_good { public:
+    istream_good(istream * ff) :f(ff) {}
+    istream * f;
+    operator bool () const {return f->good();}
+};
+long cflush(pstream ** ppf) 
+{
+  pstream & f = **ppf;
+    f.flush();
+ // if( f.os ) f.os->flush();
+ // if( f.f) fflush(f.f);
+  return  0; 
+}; 
+inline istream_good to_istream_good(pstream **f){ ffassert((**f).is) ; return istream_good((**f).is);}
+inline bool get_eof(pstream ** p){ return (**p).is ? (**p).is->eof(): EOF;}
+void inittt()
+{
+  Dcl_TypeandPtr<pstream*>(0,0,::InitializePtr<pstream*>,::DeletePtr<pstream*>);
+  atype<istream* >()->AddCast( new E_F1_funcT<istream*,pstream**>(pstream2i));
+  atype<ostream* >()->AddCast( new E_F1_funcT<ostream*,pstream**>(pstream2o));
+  TheOperators->Add("<-",new OneOperator2_<pstream**,pstream**,string*>(pstream_init) );
+  TheOperators->Add("<-",new OneOperator3_<pstream**,pstream**,string*,string*>(pstream_init) );
+  zzzfff->Add("pstream",atype< pstream ** >());
+  Add<pstream**>("good",".",new OneOperator1<istream_good,pstream**>(to_istream_good));
+  Add<pstream**>("eof",".",new OneOperator1<bool,pstream**>(get_eof));
+  Global.Add("flush","(",new OneOperator1<long,pstream **> ( cflush)) ; 
+  Global.Add("sleep","(",new OneOperator1<long,long> ( ffsleep)) ; 
+  Global.Add("usleep","(",new OneOperator1<long,long> ( ffusleep)) ; 
+#ifdef WIN32
+   Global.New("onWIN32",CConstant<bool>(true));
+#else    
+  Global.New("onWIN32",CConstant<bool>(false));
+#endif
+}
+
+LOADFUNC(inittt);
diff --git a/examples++-load/pipe.edp b/examples++-load/pipe.edp
new file mode 100644
index 0000000..b5b9214
--- /dev/null
+++ b/examples++-load/pipe.edp
@@ -0,0 +1,35 @@
+// PARAM -cd -ns
+load "pipe"
+// example for with pipe 
+string sgnuplot ="gnuplot -persist";
+string sls ="ls -l";
+if (onWIN32)
+{ // windows command ...
+ sls="dir"; 
+ sgnuplot= "\"C:\\Program Files (x86)\\gnuplot\\bin\\pgnuplot.exe\" -persist";
+}
+
+if(1) {// input case ..
+    pstream  ls(sls,"r");
+
+while (!ls.eof)
+{
+    string file;
+     getline(ls,file);
+     cout <<  file << endl; 
+    
+}
+}
+cout << "pipe on " << sgnuplot << endl; 
+pstream  f(sgnuplot,"w");
+try {
+for(int i=0;i<100; i++)
+{
+  cout << "plot sin(x+" + (i*.01) + ") w l;" << endl;
+  f  << "plot sin(x+" + (i*.01) + ") w l;" << endl;
+}
+f << "pause 10"<<endl;
+
+}
+catch (...)
+  {cout << " catch  error ??? "<< endl;}
\ No newline at end of file
diff --git a/examples++-load/plot-fb-P3.edp b/examples++-load/plot-fb-P3.edp
new file mode 100644
index 0000000..2c3a15d
--- /dev/null
+++ b/examples++-load/plot-fb-P3.edp
@@ -0,0 +1,44 @@
+load "Element_P3"
+mesh Th=square(1,1);
+plot(Th,wait=1);
+mesh th=square(150,150);
+fespace Vh(Th,P3);
+fespace Wh(th,P1);
+func p9=x*x*x+2*y*y*y+3*x*x*y+4*x*y*y+5*x*x+6*x*y+7*y*y+8*x+9*y+10;
+func p9x=3 * x * x + 6 * x * y + 4 * y * y + 10 * x + 6 * y + 8;
+func p9y=6 * y * y + 3 * x * x + 8 * x * y + 6 * x + 14 * y + 9;
+func p9yy= 12 * y + 8 * x + 14;
+func p9xx=6 * x + 6 * y + 10;
+func p9xy=6 * x + 8 * y + 6;
+
+
+
+Vh vi=p9;
+
+cout << " 0.2,0.1 : " << vi(0.2,0.1)<<  " " << p9(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dx(vi)(0.2,0.1)<<  " " << p9x(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dy(vi)(0.2,0.1)<<  " " << p9y(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxx(vi)(0.2,0.1)<<  " " << p9xx(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dyy(vi)(0.2,0.1)<<  " " << p9yy(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxy(vi)(0.2,0.1)<<  " " << p9xy(0.2,0.1) << endl;
+vi=0;
+if(!NoUseOfWait)
+  for (int i=0;i<min(vi[].n,5);++i)
+ {
+    vi[][i]=1;
+    vi;
+    plot(vi,wait=0,cmm=" v"+i);
+    if(0)
+      {
+      load "medit" load "msh3"
+      mesh3 Th3= movemesh23(th,transfo=[x,y,vi*0.5]);
+      medit("mm",Th3); 
+      //savemesh(th,"mm",[x,y,vi*0.5]);   //save *.points and *.faces file for medit
+      //if(!NoGraphicWindow) exec("ffmedit mm");
+      //exec(" rm mm.faces mm.points");
+      }	
+    vi=vi;	
+    cout << i << " vi = "<< vi[]<<endl;
+    vi[]=0;
+    
+ }
diff --git a/examples++-load/plot-fb-P3dc.edp b/examples++-load/plot-fb-P3dc.edp
new file mode 100644
index 0000000..96d94e2
--- /dev/null
+++ b/examples++-load/plot-fb-P3dc.edp
@@ -0,0 +1,45 @@
+load "Element_P3dc"
+mesh Th=square(1,1);
+plot(Th,wait=1);
+mesh th=square(150,150);
+fespace Vh(Th,P3dc);
+fespace Wh(th,P1);
+func p9=x*x*x+2*y*y*y+3*x*x*y+4*x*y*y+5*x*x+6*x*y+7*y*y+8*x+9*y+10;
+func p9x=3 * x * x + 6 * x * y + 4 * y * y + 10 * x + 6 * y + 8;
+func p9y=6 * y * y + 3 * x * x + 8 * x * y + 6 * x + 14 * y + 9;
+func p9yy= 12 * y + 8 * x + 14;
+func p9xx=6 * x + 6 * y + 10;
+func p9xy=6 * x + 8 * y + 6;
+
+
+
+Vh vi=p9;
+
+cout << " 0.2,0.1 : " << vi(0.2,0.1)<<  " " << p9(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dx(vi)(0.2,0.1)<<  " " << p9x(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dy(vi)(0.2,0.1)<<  " " << p9y(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxx(vi)(0.2,0.1)<<  " " << p9xx(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dyy(vi)(0.2,0.1)<<  " " << p9yy(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxy(vi)(0.2,0.1)<<  " " << p9xy(0.2,0.1) << endl;
+vi=0;
+if(!NoUseOfWait)
+  for (int i=0;i<min(vi[].n,5);++i)
+ {
+    vi[][i]=1;
+    vi;
+    plot(vi,wait=0,cmm=" v"+i);
+    if(!NoGraphicWindow && 0 )
+      {
+      load "medit" load "msh3"
+      mesh3 Th3= movemesh23(th,transfo=[x,y,vi*0.5]);
+      medit("mm",Th3); 
+ 
+//      savemesh(th,"mm",[x,y,vi*0.5]);   //save *.points and *.faces file for medit
+//      exec("ffmedit mm");
+//      exec(" rm mm.faces mm.points");
+      }	
+    vi=vi;	
+    cout << i << " vi = "<< vi[]<<endl;
+    vi[]=0;
+    
+ }
diff --git a/examples++-load/plot-fb-P4.edp b/examples++-load/plot-fb-P4.edp
new file mode 100644
index 0000000..3cbf2aa
--- /dev/null
+++ b/examples++-load/plot-fb-P4.edp
@@ -0,0 +1,37 @@
+load "Element_P4" load "msh3" load "medit"
+mesh Th=square(1,1);
+plot(Th,wait=1);
+mesh th=square(150,150);
+fespace Vh(Th,P4);
+fespace Wh(th,P1);
+func p9=x*x*x+2*y*y*y+3*x*x*y+4*x*y*y+5*x*x+6*x*y+7*y*y+8*x+9*y+10;
+func p9x=3 * x * x + 6 * x * y + 4 * y * y + 10 * x + 6 * y + 8;
+func p9y=6 * y * y + 3 * x * x + 8 * x * y + 6 * x + 14 * y + 9;
+func p9yy= 12 * y + 8 * x + 14;
+func p9xx=6 * x + 6 * y + 10;
+func p9xy=6 * x + 8 * y + 6;
+
+
+
+Vh vi=p9;
+
+cout << " 0.2,0.1 : " << vi(0.2,0.1)<<  " " << p9(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dx(vi)(0.2,0.1)<<  " " << p9x(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dy(vi)(0.2,0.1)<<  " " << p9y(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxx(vi)(0.2,0.1)<<  " " << p9xx(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dyy(vi)(0.2,0.1)<<  " " << p9yy(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxy(vi)(0.2,0.1)<<  " " << p9xy(0.2,0.1) << endl;
+vi=0;
+if(!NoUseOfWait)
+  for (int i=0;i<min(vi[].n,5);++i)
+ {
+    vi[][i]=1;
+    vi;
+    plot(vi,wait=0,cmm=" v"+i);
+    mesh3 Th3= movemesh23(th,transfo=[x,y,vi*0.5]);
+    medit("mm",Th3); 
+    vi=vi;	
+    cout << i << " vi = "<< vi[]<<endl;
+    vi[]=0;
+    
+ }
diff --git a/examples++-load/plot-fb-P4dc.edp b/examples++-load/plot-fb-P4dc.edp
new file mode 100644
index 0000000..3e5fa50
--- /dev/null
+++ b/examples++-load/plot-fb-P4dc.edp
@@ -0,0 +1,46 @@
+load "Element_P4dc"
+mesh Th=square(1,1);
+plot(Th,wait=1);
+mesh th=square(150,150);
+fespace Vh(Th,P4dc);
+fespace Wh(th,P1);
+func p9=x*x*x+2*y*y*y+3*x*x*y+4*x*y*y+5*x*x+6*x*y+7*y*y+8*x+9*y+10;
+func p9x=3 * x * x + 6 * x * y + 4 * y * y + 10 * x + 6 * y + 8;
+func p9y=6 * y * y + 3 * x * x + 8 * x * y + 6 * x + 14 * y + 9;
+func p9yy= 12 * y + 8 * x + 14;
+func p9xx=6 * x + 6 * y + 10;
+func p9xy=6 * x + 8 * y + 6;
+
+
+
+Vh vi=p9;
+
+cout << " 0.2,0.1 : " << vi(0.2,0.1)<<  " " << p9(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dx(vi)(0.2,0.1)<<  " " << p9x(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dy(vi)(0.2,0.1)<<  " " << p9y(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxx(vi)(0.2,0.1)<<  " " << p9xx(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dyy(vi)(0.2,0.1)<<  " " << p9yy(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxy(vi)(0.2,0.1)<<  " " << p9xy(0.2,0.1) << endl;
+vi=0;
+
+if(!NoUseOfWait)
+  for (int i=0;i<min(vi[].n,5);++i)
+ {
+    vi[][i]=1;
+    vi;
+    plot(vi,wait=0,cmm=" v"+i);
+    if(0)
+      { 
+      load "medit" load "msh3"
+      mesh3 Th3= movemesh23(th,transfo=[x,y,vi*0.5]);
+      medit("mm",Th3); 
+
+      //savemesh(th,"mm",[x,y,vi*0.5]);   //save *.points and *.faces file for medit
+      //exec("ffmedit mm");
+      //exec(" rm mm.faces mm.points");
+      }	
+    vi=vi;	
+    cout << i << " vi = "<< vi[]<<endl;
+    vi[]=0;
+    
+ }
diff --git a/examples++-load/plotfb.edp b/examples++-load/plotfb.edp
new file mode 100644
index 0000000..2ec2070
--- /dev/null
+++ b/examples++-load/plotfb.edp
@@ -0,0 +1,34 @@
+//load "Element_P3dc"
+mesh Th=square(10,10);
+plot(Th,wait=1);
+mesh th=square(150,150);
+fespace Vh(Th,P1);
+fespace Wh(th,P1);
+func p9=x*x*x+2*y*y*y+3*x*x*y+4*x*y*y+5*x*x+6*x*y+7*y*y+8*x+9*y+10;
+func p9x=3 * x * x + 6 * x * y + 4 * y * y + 10 * x + 6 * y + 8;
+func p9y=6 * y * y + 3 * x * x + 8 * x * y + 6 * x + 14 * y + 9;
+func p9yy= 12 * y + 8 * x + 14;
+func p9xx=6 * x + 6 * y + 10;
+func p9xy=6 * x + 8 * y + 6;
+
+
+
+Vh vi=p9;
+
+cout << " 0.2,0.1 : " << vi(0.2,0.1)<<  " " << p9(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dx(vi)(0.2,0.1)<<  " " << p9x(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dy(vi)(0.2,0.1)<<  " " << p9y(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxx(vi)(0.2,0.1)<<  " " << p9xx(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dyy(vi)(0.2,0.1)<<  " " << p9yy(0.2,0.1) << endl;
+cout << " 0.2,0.1 : " << dxy(vi)(0.2,0.1)<<  " " << p9xy(0.2,0.1) << endl;
+vi=0;
+if(!NoUseOfWait)
+  for (int i=min(vi[].n,20);i<min(vi[].n,50);++i)
+ {
+   vi[][i]=1;
+   Wh w=vi;
+    plot(w,wait=1,cmm=" v"+i,dim=3);	
+    //    cout << i << " vi = "<< vi[]<<endl;
+    vi[]=0;
+    
+ }
diff --git a/examples++-load/ppm2rnm.cpp b/examples++-load/ppm2rnm.cpp
new file mode 100644
index 0000000..df35cf9
--- /dev/null
+++ b/examples++-load/ppm2rnm.cpp
@@ -0,0 +1,326 @@
+//   tools to read ppm file 
+/*  use in freefem++ edp
+  see :
+  real[int,int] ff1("tt.pmm"); // read  image and set to an array. 
+  real[int]  ff(ff1.nx*ff1.ny);
+  ff=ff1; 
+ */
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+using namespace std;  
+
+#include "RNM.hpp"
+#include <cmath>
+typedef KNM<double> * pRnm;
+typedef KN<double> * pRn;
+typedef string * pstring;
+#include "ppmimg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+    
+    
+    PPMimage *loadPPM(const char *imgname,ubyte *type,ubyte quiet) {
+	pPPMimage  result;
+	FILE      *fp;
+	int        i,k,typimg,ret,r,g,b,s,maxval,bitsize;
+	const char      *ptr;
+	char c,buff[1024],data[256];
+	
+	/* search for image */
+	fprintf(stdout," Loading image: %s\n",imgname);
+	ptr = strstr(imgname,".ppm");
+	strcpy(data,imgname);
+	if ( !ptr ) {
+	    ptr = strstr(imgname,".pgm");
+	    if ( !ptr )  strcat(data,".ppm");
+	    fp = fopen(data,"rb");
+	} 
+	else
+	    fp = fopen(data,"rb");
+	if ( !fp ) {
+	    fprintf(stderr,"  ## UNABLE TO OPEN FILE %s.\n",data);
+	    return(0);
+	}
+	if ( !quiet )
+	    fprintf(stdout,"  opening %s\n",data);
+	
+	if ( !fgets(buff,sizeof(buff),fp) ) {
+	    fprintf(stderr,"  ## INVALID HEADER.\n");
+	    return(0);
+	}
+	
+	/* check header file */
+	if ( buff[0] != 'P' ) {
+	    fprintf(stderr,"  ## INVALID IMAGE FORMAT (MUST BE 'PX').\n");
+	    return(0);
+	}
+	
+	switch(buff[1]) {
+	    case '2': typimg = P2;  break;
+	    case '3': typimg = P3;  break;
+	    case '4': typimg = P4;  break;
+	    case '5': typimg = P5;  break;
+	    case '6': typimg = P6;  break;
+	    default:
+		fprintf(stderr,"  ## INVALID IMAGE FORMAT (MUST BE 'PX').\n");
+		return(0);
+	}
+	
+	/* allocate memory to store imagee */
+	result = (PPMimage*) malloc(sizeof(PPMimage));
+	assert(result);
+	
+	do {
+	    ret = fscanf(fp,"%s",buff);
+	    if ( ret == EOF ) break;
+	    /* check and strip comments */
+	    if ( buff[0] == '#' )
+		do
+		    c = getc(fp);
+	    while ( c != '\n' );
+	    else break;
+	}
+	while (1);
+	
+	/* read columns + lines */
+	ret  = sscanf(buff,"%d",&s);
+	result->sizeX = (short)s;
+	ret += fscanf(fp,"%d",&s);
+	result->sizeY = (short)s;
+	if ( ret != 2 ) {
+	    fprintf(stderr,"  ## ERROR LOADING IMAGE.\n");
+	    free(result);
+	    return(0);
+	}
+	if ( fscanf(fp,"%d",&maxval) != 1 ) {
+	    fprintf(stderr,"  ## INVALID IMAGE SIZE.\n");
+	    free(result);
+	    return(0);
+	}
+	
+	/* strip line */
+	while ( fgetc(fp) != '\n' ) ;
+	
+	/* size based on type */
+	if ( typimg == P2 || typimg == P5 || typimg == P4 )
+	    bitsize = result->sizeX*result->sizeY;
+	else
+	    bitsize = 3*result->sizeX*result->sizeY;
+	if ( !quiet )
+	    fprintf(stdout,"   image size: %dx%d  %d bytes\n",
+		    result->sizeX,result->sizeY,bitsize);
+	
+	result->data = (ubyte*)malloc(1+bitsize*sizeof(ubyte));
+	assert(result->data);
+	
+	/* read data file */
+	switch( typimg ) {
+	    case P2:  /* ascii file (grey)  */
+	    case P3:  /* ascii file (color) */
+		for (i=0; i<bitsize; i++) {
+		    int rr=fscanf(fp,"%d",&r);
+		    result->data[i] = (ubyte)r;
+		}
+		break;
+		
+	    case P5:  /* binary file (grey) */
+	    case P6:  /* binary file (color) */
+		ret = fread(result->data,sizeof(ubyte),bitsize,fp);
+		if ( ret != bitsize ) {
+		    fprintf(stderr,"  ## ERROR LOADING IMAGE.\n");
+		    free(result->data);
+		    free(result);
+		    return(0);
+		}
+		break;
+	}
+	fclose(fp);
+	
+	if ( *type == DEFAULT )
+	    if ( typimg == P2 || typimg == P5 )
+		*type = GREY;
+	    else
+		*type = COLOR;
+	
+	/* convert to grey levels */
+	    else if ( *type == GREY && (typimg == P3 || typimg == P6) ) {
+		fprintf(stdout,"  converting to grey levels\n");
+		for (i=0,k=0; i<bitsize; i+=3,k++) {
+		    r = (int)result->data[i];
+		    g = (int)result->data[i+1];
+		    b = (int)result->data[i+2];
+		    result->data[k] = (ubyte)(0.3*r+0.59*g+0.11*b);
+		}
+		result->data = (ubyte*)realloc(result->data,sizeof(ubyte)*bitsize/3+1);
+	    }
+	
+	return(result);
+    }
+    
+    
+    int savePPM(const char *imgname,pPPMimage img,int typimg) {
+	FILE      *out;
+	int        i,c,bitsize;
+	
+	/* open file */
+	out = fopen(imgname,"w");
+	if ( !out ) {
+	    fprintf(stderr,"  ## UNABLE TO OPEN FILE %s.\n",imgname);
+	    return 0;
+	}
+	
+	/* write out image file */
+	bitsize = img->sizeX*img->sizeY;
+	switch(typimg) {
+	    case P2:
+		fprintf(out,"P2\n");
+		fprintf(out,"# CREATOR: QIZIP Version 1, Rev. 2/2003, (c) INRIA\n");
+		fprintf(out,"%d %d\n",img->sizeX,img->sizeY);
+		fprintf(out,"255\n");
+		c = 0;
+		for (i=0; i<img->sizeX*img->sizeY; i++) {
+		    fprintf(out,"%3d ",(int)img->data[i]);
+		    if ( ++c == 17 ) { 
+			c = 0; 
+			fprintf(out,"\n");
+		    }
+		}
+		fprintf(out,"\n");
+		break;
+	    case P5:
+		fprintf(out,"P5\n");
+		fprintf(out,"# CREATOR: QIZIP Version 1, Rev. 2/2003, (c) INRIA\n");
+		fprintf(out,"%d %d\n",img->sizeX,img->sizeY);
+		fprintf(out,"255\n");
+		fwrite(img->data,sizeof(ubyte),bitsize,out);
+		break;
+	    case P6:
+		fprintf(out,"P6\n");
+		fprintf(out,"# CREATOR: QIZIP Version 1, Rev. 2/2003, (c) INRIA\n");
+		fprintf(out,"%d %d\n",img->sizeX,img->sizeY);
+		fprintf(out,"255\n");
+		fwrite(img->data,sizeof(ubyte),3*bitsize,out);
+		break;
+	}
+	fclose(out);
+	
+	return(1);
+    }
+    
+    /* compute difference image */
+    pPPMimage diffImg(pPPMimage bits,pPPMimage img,ubyte itype) {
+	pPPMimage  dif;
+	double     psnr,dd;
+	int        i,bitsize,dmax;
+	
+	fprintf(stdout,"  Difference image\n");
+	bitsize = (int)bits->sizeX*bits->sizeY;
+	if ( itype == COLOR )  bitsize *= 3;
+	
+	dif = (PPMimage *)malloc(sizeof(PPMimage));
+	if ( !dif ) {
+	    fprintf(stderr,"  Sorry, not enough memory. Bye.\n");
+	    return 0;
+	}
+	dif->sizeX = bits->sizeX; 
+	dif->sizeY = bits->sizeY;
+	dif->data = (ubyte*)malloc(bitsize*sizeof(ubyte));
+	if ( !dif->data ) {
+	    fprintf(stderr,"  Sorry, not enough memory. Bye.\n");
+	    free(dif);
+	    return 0;
+	}
+	
+	dmax = 0;
+	psnr = 0.0f;
+	for (i=0; i<bitsize; i++) {
+	    dd    = abs((int)(bits->data[i]-img->data[i]));
+	    dmax  = max(dmax,dd);
+	    psnr += (double)dd*dd;
+	    dif->data[i] = (ubyte)(255-dd);
+	}
+	if ( psnr == 0.0f )  fprintf(stderr,"    PSNR problem!");
+	else {
+	    psnr = 65025.0f / psnr;
+	    psnr = 10.0 * log10(bitsize*psnr);
+	}
+	fprintf(stdout,"    PSNR = %.2f    dmax = %d\n",psnr,dmax);
+	
+	return(dif);
+    }
+    
+    
+#ifdef __cplusplus
+}
+#endif
+
+
+pRnm  read_image( pRnm  const & a,const pstring & b)
+{
+  ubyte type,quiet=1;
+  PPMimage * image =loadPPM(b->c_str(),&type, quiet);
+  if(!image) {
+    std::cerr << " error loadPPM image "<< *b  << endl;
+    CompileError("error loadPPM image ");
+    return a;
+  }
+  if(verbosity)   
+  cout << " size of image : " << image->sizeX << " x " << image->sizeY << " type =" <<  (int) type << endl; 
+  int n = image->sizeX;
+  int m = image->sizeY ;
+  a->init(n,m);
+  ubyte * dd= image->data;
+
+  //  cout << (double) dd[0] / 256. << " "
+  //     << (double) dd[250] / 256. << " "
+  //     << (double) dd[500] / 256. << "\n "
+  //  ;
+  int k=0;
+  double *mm=*a;
+  for(int i=0;i<n;++i)
+    for(int j=0;j<m;++j)
+      *mm++= (double) dd[k++] / 256. ;
+  KN_<double> aa=*a;
+  // cout << aa[0] << " "<< aa[250] << "" << aa[500] << endl;
+  assert(k==n*m);
+  free(image->data);
+  free(image);
+  return a;
+}
+pRn  seta( pRn  const & a,const pRnm & b)
+{
+  *a=*b;
+  KN_<double> aa=*a;
+  //  cout << aa[0] << " "<< aa[250] << "" << aa[500] << endl;
+  return a;
+}
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+static void Load_Init(){
+  cout << " lood: init ppm2rmn  " << endl;
+
+
+  TheOperators->Add("<-", 
+		    new OneOperator2_<KNM<double> *,KNM<double> *,string*>(&read_image)
+		    );
+  TheOperators->Add("=", 
+		    new OneOperator2_<KN<double> *,KN<double> *,KNM<double>* >(seta)
+		    );
+  /*
+  map_type[typeid(KN<double> ).name()]->AddCast(
+						new E_F1_funcT<KN<double>,KNM<double>*>(UnRef<KN<double>,KNM<double> >));
+					      //  map_type[typeid(KN<double> ).name()]->AddCast(
+						//new E_F1_funcT<KN<double>*,KNM<double>*>(Cast<KN<double>*,KNM<double>*>));
+					       
+						*/
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/ppm2rnm.edp b/examples++-load/ppm2rnm.edp
new file mode 100644
index 0000000..ae24bef
--- /dev/null
+++ b/examples++-load/ppm2rnm.edp
@@ -0,0 +1,12 @@
+load "ppm2rnm"
+bool wait=false;
+string namef1="fig.pgm";
+real[int,int] ff1(namef1); // read  image and set to an array. 
+int nx = ff1.n, ny=ff1.m; 
+mesh Th=square(nx-1,ny-1,[(nx-1)*(x)/nx,(ny-1)*(1-y)/ny]);
+// warning  the numbering is of the vertices (x,y) is 
+// given by $  i = x/nx + nx* y/ny $
+fespace Vh(Th,P1);
+Vh f1;
+f1[]=ff1;
+plot(f1,wait=1);
diff --git a/examples++-load/ppmimg.h b/examples++-load/ppmimg.h
new file mode 100644
index 0000000..ac3ec7a
--- /dev/null
+++ b/examples++-load/ppmimg.h
@@ -0,0 +1,27 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char ubyte;
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+enum imgtyp {DEFAULT=0, P2,P3,P4,P5,P6,
+             GREY,RGB,RED,GREEN,BLUE,COLOR};
+                     
+typedef struct {
+  short    sizeX,sizeY;
+  ubyte   *data;
+} PPMimage;
+typedef PPMimage * pPPMimage;
+
+/* prototypes */
+PPMimage *loadPPM(const char *imgname,ubyte *type,ubyte quiet);
+int       savePPM(const char *imgname,pPPMimage img,int typimg);
+pPPMimage diffImg(pPPMimage bits,pPPMimage img,ubyte ityp);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/examples++-load/provadxw.edp b/examples++-load/provadxw.edp
new file mode 100644
index 0000000..5d67803
--- /dev/null
+++ b/examples++-load/provadxw.edp
@@ -0,0 +1,14 @@
+// test of DxWriter  from Sala Lorenzo.
+load "DxWriter"
+mesh Th=square(5,5);
+DxWriter ff("pippo");
+Dxaddmesh(ff, Th);
+Dxaddtimeseries(ff, "Vx",Th);
+fespace Vh(Th, P1);
+real t=1.0;
+Vh vx=x*y*t;
+Dxaddsol2ts(ff,"Vx",t, vx);
+t=2.0;
+vx=x*y*t;
+Dxaddsol2ts(ff,"Vx",t, vx);
+cout<<"Hello";
\ No newline at end of file
diff --git a/examples++-load/pstream.h b/examples++-load/pstream.h
new file mode 100644
index 0000000..72ae04f
--- /dev/null
+++ b/examples++-load/pstream.h
@@ -0,0 +1,2199 @@
+/*
+PStreams - POSIX Process I/O for C++
+Copyright (C) 2001-2013 Jonathan Wakely
+
+This file is part of PStreams.
+
+PStreams is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+PStreams is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file pstream.h
+ * @brief Declares all PStreams classes.
+ * @author Jonathan Wakely
+ *
+ * Defines classes redi::ipstream, redi::opstream, redi::pstream
+ * and redi::rpstream.
+ */
+
+#ifndef REDI_PSTREAM_H_SEEN
+#define REDI_PSTREAM_H_SEEN
+
+#include <ios>
+#include <streambuf>
+#include <istream>
+#include <ostream>
+#include <string>
+#include <vector>
+#include <algorithm>    // for min()
+#include <cerrno>       // for errno
+#include <cstddef>      // for size_t, NULL
+#include <cstdlib>      // for exit()
+#include <sys/types.h>  // for pid_t
+#include <sys/wait.h>   // for waitpid()
+#include <sys/ioctl.h>  // for ioctl() and FIONREAD
+#if defined(__sun)
+# include <sys/filio.h> // for FIONREAD on Solaris 2.5
+#endif
+#include <unistd.h>     // for pipe() fork() exec() and filedes functions
+#include <signal.h>     // for kill()
+#include <fcntl.h>      // for fcntl()
+#if REDI_EVISCERATE_PSTREAMS
+# include <stdio.h>     // for FILE, fdopen()
+#endif
+
+
+/// The library version.
+#define PSTREAMS_VERSION 0x0080   // 0.8.0
+
+/**
+ *  @namespace redi
+ *  @brief  All PStreams classes are declared in namespace redi.
+ *
+ *  Like the standard iostreams, PStreams is a set of class templates,
+ *  taking a character type and traits type. As with the standard streams
+ *  they are most likely to be used with @c char and the default
+ *  traits type, so typedefs for this most common case are provided.
+ *
+ *  The @c pstream_common class template is not intended to be used directly,
+ *  it is used internally to provide the common functionality for the
+ *  other stream classes.
+ */
+namespace redi
+{
+  /// Common base class providing constants and typenames.
+  struct pstreams
+  {
+    /// Type used to specify how to connect to the process.
+    typedef std::ios_base::openmode           pmode;
+
+    /// Type used to hold the arguments for a command.
+    typedef std::vector<std::string>          argv_type;
+
+    /// Type used for file descriptors.
+    typedef int                               fd_type;
+
+    static const pmode pstdin  = std::ios_base::out; ///< Write to stdin
+    static const pmode pstdout = std::ios_base::in;  ///< Read from stdout
+    static const pmode pstderr = std::ios_base::app; ///< Read from stderr
+
+  protected:
+    enum { bufsz = 32 };  ///< Size of pstreambuf buffers.
+    enum { pbsz  = 2 };   ///< Number of putback characters kept.
+  };
+
+  /// Class template for stream buffer.
+  template <typename CharT, typename Traits = std::char_traits<CharT> >
+    class basic_pstreambuf
+    : public std::basic_streambuf<CharT, Traits>
+    , public pstreams
+    {
+    public:
+      // Type definitions for dependent types
+      typedef CharT                             char_type;
+      typedef Traits                            traits_type;
+      typedef typename traits_type::int_type    int_type;
+      typedef typename traits_type::off_type    off_type;
+      typedef typename traits_type::pos_type    pos_type;
+      /** @deprecated use pstreams::fd_type instead. */
+      typedef fd_type                           fd_t;
+
+      /// Default constructor.
+      basic_pstreambuf();
+
+      /// Constructor that initialises the buffer with @a command.
+      basic_pstreambuf(const std::string& command, pmode mode);
+
+      /// Constructor that initialises the buffer with @a file and @a argv.
+      basic_pstreambuf( const std::string& file,
+                        const argv_type& argv,
+                        pmode mode );
+
+      /// Destructor.
+      ~basic_pstreambuf();
+
+      /// Initialise the stream buffer with @a command.
+      basic_pstreambuf*
+      open(const std::string& command, pmode mode);
+
+      /// Initialise the stream buffer with @a file and @a argv.
+      basic_pstreambuf*
+      open(const std::string& file, const argv_type& argv, pmode mode);
+
+      /// Close the stream buffer and wait for the process to exit.
+      basic_pstreambuf*
+      close();
+
+      /// Send a signal to the process.
+      basic_pstreambuf*
+      kill(int signal = SIGTERM);
+
+      /// Send a signal to the process' process group.
+      basic_pstreambuf*
+      killpg(int signal = SIGTERM);
+
+      /// Close the pipe connected to the process' stdin.
+      void
+      peof();
+
+      /// Change active input source.
+      bool
+      read_err(bool readerr = true);
+
+      /// Report whether the stream buffer has been initialised.
+      bool
+      is_open() const;
+
+      /// Report whether the process has exited.
+      bool
+      exited();
+
+#if REDI_EVISCERATE_PSTREAMS
+      /// Obtain FILE pointers for each of the process' standard streams.
+      std::size_t
+      fopen(FILE*& in, FILE*& out, FILE*& err);
+#endif
+
+      /// Return the exit status of the process.
+      int
+      status() const;
+
+      /// Return the error number (errno) for the most recent failed operation.
+      int
+      error() const;
+
+    protected:
+      /// Transfer characters to the pipe when character buffer overflows.
+      int_type
+      overflow(int_type c);
+
+      /// Transfer characters from the pipe when the character buffer is empty.
+      int_type
+      underflow();
+
+      /// Make a character available to be returned by the next extraction.
+      int_type
+      pbackfail(int_type c = traits_type::eof());
+
+      /// Write any buffered characters to the stream.
+      int
+      sync();
+
+      /// Insert multiple characters into the pipe.
+      std::streamsize
+      xsputn(const char_type* s, std::streamsize n);
+
+      /// Insert a sequence of characters into the pipe.
+      std::streamsize
+      write(const char_type* s, std::streamsize n);
+
+      /// Extract a sequence of characters from the pipe.
+      std::streamsize
+      read(char_type* s, std::streamsize n);
+
+      /// Report how many characters can be read from active input without blocking.
+      std::streamsize
+      showmanyc();
+
+    protected:
+      /// Enumerated type to indicate whether stdout or stderr is to be read.
+      enum buf_read_src { rsrc_out = 0, rsrc_err = 1 };
+
+      /// Initialise pipes and fork process.
+      pid_t
+      fork(pmode mode);
+
+      /// Wait for the child process to exit.
+      int
+      wait(bool nohang = false);
+
+      /// Return the file descriptor for the output pipe.
+      fd_type&
+      wpipe();
+
+      /// Return the file descriptor for the active input pipe.
+      fd_type&
+      rpipe();
+
+      /// Return the file descriptor for the specified input pipe.
+      fd_type&
+      rpipe(buf_read_src which);
+
+      void
+      create_buffers(pmode mode);
+
+      void
+      destroy_buffers(pmode mode);
+
+      /// Writes buffered characters to the process' stdin pipe.
+      bool
+      empty_buffer();
+
+      bool
+      fill_buffer(bool non_blocking = false);
+
+      /// Return the active input buffer.
+      char_type*
+      rbuffer();
+
+      buf_read_src
+      switch_read_buffer(buf_read_src);
+
+    private:
+      basic_pstreambuf(const basic_pstreambuf&);
+      basic_pstreambuf& operator=(const basic_pstreambuf&);
+
+      void
+      init_rbuffers();
+
+      pid_t         ppid_;        // pid of process
+      fd_type       wpipe_;       // pipe used to write to process' stdin
+      fd_type       rpipe_[2];    // two pipes to read from, stdout and stderr
+      char_type*    wbuffer_;
+      char_type*    rbuffer_[2];
+      char_type*    rbufstate_[3];
+      /// Index into rpipe_[] to indicate active source for read operations.
+      buf_read_src  rsrc_;
+      int           status_;      // hold exit status of child process
+      int           error_;       // hold errno if fork() or exec() fails
+    };
+
+  /// Class template for common base class.
+  template <typename CharT, typename Traits = std::char_traits<CharT> >
+    class pstream_common
+    : virtual public std::basic_ios<CharT, Traits>
+    , virtual public pstreams
+    {
+    protected:
+      typedef basic_pstreambuf<CharT, Traits>       streambuf_type;
+
+      typedef pstreams::pmode                       pmode;
+      typedef pstreams::argv_type                   argv_type;
+
+      /// Default constructor.
+      pstream_common();
+
+      /// Constructor that initialises the stream by starting a process.
+      pstream_common(const std::string& command, pmode mode);
+
+      /// Constructor that initialises the stream by starting a process.
+      pstream_common(const std::string& file, const argv_type& argv, pmode mode);
+
+      /// Pure virtual destructor.
+      virtual
+      ~pstream_common() = 0;
+
+      /// Start a process.
+      void
+      do_open(const std::string& command, pmode mode);
+
+      /// Start a process.
+      void
+      do_open(const std::string& file, const argv_type& argv, pmode mode);
+
+    public:
+      /// Close the pipe.
+      void
+      close();
+
+      /// Report whether the stream's buffer has been initialised.
+      bool
+      is_open() const;
+
+      /// Return the command used to initialise the stream.
+      const std::string&
+      command() const;
+
+      /// Return a pointer to the stream buffer.
+      streambuf_type*
+      rdbuf() const;
+
+#if REDI_EVISCERATE_PSTREAMS
+      /// Obtain FILE pointers for each of the process' standard streams.
+      std::size_t
+      fopen(FILE*& in, FILE*& out, FILE*& err);
+#endif
+
+    protected:
+      std::string       command_; ///< The command used to start the process.
+      streambuf_type    buf_;     ///< The stream buffer.
+    };
+
+
+  /**
+   * @class basic_ipstream
+   * @brief Class template for Input PStreams.
+   *
+   * Reading from an ipstream reads the command's standard output and/or
+   * standard error (depending on how the ipstream is opened)
+   * and the command's standard input is the same as that of the process
+   * that created the object, unless altered by the command itself.
+   */
+
+  template <typename CharT, typename Traits = std::char_traits<CharT> >
+    class basic_ipstream
+    : public std::basic_istream<CharT, Traits>
+    , public pstream_common<CharT, Traits>
+    , virtual public pstreams
+    {
+      typedef std::basic_istream<CharT, Traits>     istream_type;
+      typedef pstream_common<CharT, Traits>         pbase_type;
+
+      using pbase_type::buf_;  // declare name in this scope
+
+      pmode readable(pmode mode)
+      {
+        if (!(mode & (pstdout|pstderr)))
+          mode |= pstdout;
+        return mode;
+      }
+
+    public:
+      /// Type used to specify how to connect to the process.
+      typedef typename pbase_type::pmode            pmode;
+
+      /// Type used to hold the arguments for a command.
+      typedef typename pbase_type::argv_type        argv_type;
+
+      /// Default constructor, creates an uninitialised stream.
+      basic_ipstream()
+      : istream_type(NULL), pbase_type()
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param command  a string containing a shell command.
+       * @param mode     the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      basic_ipstream(const std::string& command, pmode mode = pstdout)
+      : istream_type(NULL), pbase_type(command, readable(mode))
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param file  a string containing the pathname of a program to execute.
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_ipstream( const std::string& file,
+                      const argv_type& argv,
+                      pmode mode = pstdout )
+      : istream_type(NULL), pbase_type(file, argv, readable(mode))
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling
+       * @c do_open(argv[0],argv,mode|pstdout)
+       *
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_ipstream(const argv_type& argv, pmode mode = pstdout)
+      : istream_type(NULL), pbase_type(argv.at(0), argv, mode|pstdout)
+      { }
+
+      /**
+       * @brief Destructor.
+       *
+       * Closes the stream and waits for the child to exit.
+       */
+      ~basic_ipstream()
+      { }
+
+      /**
+       * @brief Start a process.
+       *
+       * Calls do_open( @a %command , @a mode|pstdout ).
+       *
+       * @param command  a string containing a shell command.
+       * @param mode     the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      void
+      open(const std::string& command, pmode mode = pstdout)
+      {
+        this->do_open(command, readable(mode));
+      }
+
+      /**
+       * @brief Start a process.
+       *
+       * Calls do_open( @a file , @a argv , @a mode|pstdout ).
+       *
+       * @param file  a string containing the pathname of a program to execute.
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      void
+      open( const std::string& file,
+            const argv_type& argv,
+            pmode mode = pstdout )
+      {
+        this->do_open(file, argv, readable(mode));
+      }
+
+      /**
+       * @brief Set streambuf to read from process' @c stdout.
+       * @return  @c *this
+       */
+      basic_ipstream&
+      out()
+      {
+        this->buf_.read_err(false);
+        return *this;
+      }
+
+      /**
+       * @brief Set streambuf to read from process' @c stderr.
+       * @return  @c *this
+       */
+      basic_ipstream&
+      err()
+      {
+        this->buf_.read_err(true);
+        return *this;
+      }
+    };
+
+
+  /**
+   * @class basic_opstream
+   * @brief Class template for Output PStreams.
+   *
+   * Writing to an open opstream writes to the standard input of the command;
+   * the command's standard output is the same as that of the process that
+   * created the pstream object, unless altered by the command itself.
+   */
+
+  template <typename CharT, typename Traits = std::char_traits<CharT> >
+    class basic_opstream
+    : public std::basic_ostream<CharT, Traits>
+    , public pstream_common<CharT, Traits>
+    , virtual public pstreams
+    {
+      typedef std::basic_ostream<CharT, Traits>     ostream_type;
+      typedef pstream_common<CharT, Traits>         pbase_type;
+
+      using pbase_type::buf_;  // declare name in this scope
+
+    public:
+      /// Type used to specify how to connect to the process.
+      typedef typename pbase_type::pmode            pmode;
+
+      /// Type used to hold the arguments for a command.
+      typedef typename pbase_type::argv_type        argv_type;
+
+      /// Default constructor, creates an uninitialised stream.
+      basic_opstream()
+      : ostream_type(NULL), pbase_type()
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param command  a string containing a shell command.
+       * @param mode     the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      basic_opstream(const std::string& command, pmode mode = pstdin)
+      : ostream_type(NULL), pbase_type(command, mode|pstdin)
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param file  a string containing the pathname of a program to execute.
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_opstream( const std::string& file,
+                      const argv_type& argv,
+                      pmode mode = pstdin )
+      : ostream_type(NULL), pbase_type(file, argv, mode|pstdin)
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling
+       * @c do_open(argv[0],argv,mode|pstdin)
+       *
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_opstream(const argv_type& argv, pmode mode = pstdin)
+      : ostream_type(NULL), pbase_type(argv.at(0), argv, mode|pstdin)
+      { }
+
+      /**
+       * @brief Destructor
+       *
+       * Closes the stream and waits for the child to exit.
+       */
+      ~basic_opstream() { }
+
+      /**
+       * @brief Start a process.
+       *
+       * Calls do_open( @a %command , @a mode|pstdin ).
+       *
+       * @param command  a string containing a shell command.
+       * @param mode     the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      void
+      open(const std::string& command, pmode mode = pstdin)
+      {
+        this->do_open(command, mode|pstdin);
+      }
+
+      /**
+       * @brief Start a process.
+       *
+       * Calls do_open( @a file , @a argv , @a mode|pstdin ).
+       *
+       * @param file  a string containing the pathname of a program to execute.
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      void
+      open( const std::string& file,
+            const argv_type& argv,
+            pmode mode = pstdin)
+      {
+        this->do_open(file, argv, mode|pstdin);
+      }
+    };
+
+
+  /**
+   * @class basic_pstream
+   * @brief Class template for Bidirectional PStreams.
+   *
+   * Writing to a pstream opened with @c pmode @c pstdin writes to the
+   * standard input of the command.
+   * Reading from a pstream opened with @c pmode @c pstdout and/or @c pstderr
+   * reads the command's standard output and/or standard error.
+   * Any of the process' @c stdin, @c stdout or @c stderr that is not
+   * connected to the pstream (as specified by the @c pmode)
+   * will be the same as the process that created the pstream object,
+   * unless altered by the command itself.
+   */
+  template <typename CharT, typename Traits = std::char_traits<CharT> >
+    class basic_pstream
+    : public std::basic_iostream<CharT, Traits>
+    , public pstream_common<CharT, Traits>
+    , virtual public pstreams
+    {
+      typedef std::basic_iostream<CharT, Traits>    iostream_type;
+      typedef pstream_common<CharT, Traits>         pbase_type;
+
+      using pbase_type::buf_;  // declare name in this scope
+
+    public:
+      /// Type used to specify how to connect to the process.
+      typedef typename pbase_type::pmode            pmode;
+
+      /// Type used to hold the arguments for a command.
+      typedef typename pbase_type::argv_type        argv_type;
+
+      /// Default constructor, creates an uninitialised stream.
+      basic_pstream()
+      : iostream_type(NULL), pbase_type()
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param command  a string containing a shell command.
+       * @param mode     the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      basic_pstream(const std::string& command, pmode mode = pstdout|pstdin)
+      : iostream_type(NULL), pbase_type(command, mode)
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param file  a string containing the pathname of a program to execute.
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_pstream( const std::string& file,
+                     const argv_type& argv,
+                     pmode mode = pstdout|pstdin )
+      : iostream_type(NULL), pbase_type(file, argv, mode)
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling
+       * @c do_open(argv[0],argv,mode)
+       *
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_pstream(const argv_type& argv, pmode mode = pstdout|pstdin)
+      : iostream_type(NULL), pbase_type(argv.at(0), argv, mode)
+      { }
+
+      /**
+       * @brief Destructor
+       *
+       * Closes the stream and waits for the child to exit.
+       */
+      ~basic_pstream() { }
+
+      /**
+       * @brief Start a process.
+       *
+       * Calls do_open( @a %command , @a mode ).
+       *
+       * @param command  a string containing a shell command.
+       * @param mode     the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      void
+      open(const std::string& command, pmode mode = pstdout|pstdin)
+      {
+        this->do_open(command, mode);
+      }
+
+      /**
+       * @brief Start a process.
+       *
+       * Calls do_open( @a file , @a argv , @a mode ).
+       *
+       * @param file  a string containing the pathname of a program to execute.
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      void
+      open( const std::string& file,
+            const argv_type& argv,
+            pmode mode = pstdout|pstdin )
+      {
+        this->do_open(file, argv, mode);
+      }
+
+      /**
+       * @brief Set streambuf to read from process' @c stdout.
+       * @return  @c *this
+       */
+      basic_pstream&
+      out()
+      {
+        this->buf_.read_err(false);
+        return *this;
+      }
+
+      /**
+       * @brief Set streambuf to read from process' @c stderr.
+       * @return  @c *this
+       */
+      basic_pstream&
+      err()
+      {
+        this->buf_.read_err(true);
+        return *this;
+      }
+    };
+
+
+  /**
+   * @class basic_rpstream
+   * @brief Class template for Restricted PStreams.
+   *
+   * Writing to an rpstream opened with @c pmode @c pstdin writes to the
+   * standard input of the command.
+   * It is not possible to read directly from an rpstream object, to use
+   * an rpstream as in istream you must call either basic_rpstream::out()
+   * or basic_rpstream::err(). This is to prevent accidental reads from
+   * the wrong input source. If the rpstream was not opened with @c pmode
+   * @c pstderr then the class cannot read the process' @c stderr, and
+   * basic_rpstream::err() will return an istream that reads from the
+   * process' @c stdout, and vice versa.
+   * Reading from an rpstream opened with @c pmode @c pstdout and/or
+   * @c pstderr reads the command's standard output and/or standard error.
+   * Any of the process' @c stdin, @c stdout or @c stderr that is not
+   * connected to the pstream (as specified by the @c pmode)
+   * will be the same as the process that created the pstream object,
+   * unless altered by the command itself.
+   */
+
+  template <typename CharT, typename Traits = std::char_traits<CharT> >
+    class basic_rpstream
+    : public std::basic_ostream<CharT, Traits>
+    , private std::basic_istream<CharT, Traits>
+    , private pstream_common<CharT, Traits>
+    , virtual public pstreams
+    {
+      typedef std::basic_ostream<CharT, Traits>     ostream_type;
+      typedef std::basic_istream<CharT, Traits>     istream_type;
+      typedef pstream_common<CharT, Traits>         pbase_type;
+
+      using pbase_type::buf_;  // declare name in this scope
+
+    public:
+      /// Type used to specify how to connect to the process.
+      typedef typename pbase_type::pmode            pmode;
+
+      /// Type used to hold the arguments for a command.
+      typedef typename pbase_type::argv_type        argv_type;
+
+      /// Default constructor, creates an uninitialised stream.
+      basic_rpstream()
+      : ostream_type(NULL), istream_type(NULL), pbase_type()
+      { }
+
+      /**
+       * @brief  Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param command a string containing a shell command.
+       * @param mode the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      basic_rpstream(const std::string& command, pmode mode = pstdout|pstdin)
+      : ostream_type(NULL) , istream_type(NULL) , pbase_type(command, mode)
+      { }
+
+      /**
+       * @brief  Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling do_open() with the supplied
+       * arguments.
+       *
+       * @param file a string containing the pathname of a program to execute.
+       * @param argv a vector of argument strings passed to the new program.
+       * @param mode the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_rpstream( const std::string& file,
+                      const argv_type& argv,
+                      pmode mode = pstdout|pstdin )
+      : ostream_type(NULL), istream_type(NULL), pbase_type(file, argv, mode)
+      { }
+
+      /**
+       * @brief Constructor that initialises the stream by starting a process.
+       *
+       * Initialises the stream buffer by calling
+       * @c do_open(argv[0],argv,mode)
+       *
+       * @param argv  a vector of argument strings passed to the new program.
+       * @param mode  the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      basic_rpstream(const argv_type& argv, pmode mode = pstdout|pstdin)
+      : ostream_type(NULL), istream_type(NULL),
+        pbase_type(argv.at(0), argv, mode)
+      { }
+
+      /// Destructor
+      ~basic_rpstream() { }
+
+      /**
+       * @brief  Start a process.
+       *
+       * Calls do_open( @a %command , @a mode ).
+       *
+       * @param command a string containing a shell command.
+       * @param mode the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, pmode)
+       */
+      void
+      open(const std::string& command, pmode mode = pstdout|pstdin)
+      {
+        this->do_open(command, mode);
+      }
+
+      /**
+       * @brief  Start a process.
+       *
+       * Calls do_open( @a file , @a argv , @a mode ).
+       *
+       * @param file a string containing the pathname of a program to execute.
+       * @param argv a vector of argument strings passed to the new program.
+       * @param mode the I/O mode to use when opening the pipe.
+       * @see   do_open(const std::string&, const argv_type&, pmode)
+       */
+      void
+      open( const std::string& file,
+            const argv_type& argv,
+            pmode mode = pstdout|pstdin )
+      {
+        this->do_open(file, argv, mode);
+      }
+
+      /**
+       * @brief  Obtain a reference to the istream that reads
+       *         the process' @c stdout.
+       * @return @c *this
+       */
+      istream_type&
+      out()
+      {
+        this->buf_.read_err(false);
+        return *this;
+      }
+
+      /**
+       * @brief  Obtain a reference to the istream that reads
+       *         the process' @c stderr.
+       * @return @c *this
+       */
+      istream_type&
+      err()
+      {
+        this->buf_.read_err(true);
+        return *this;
+      }
+    };
+
+
+  /// Type definition for common template specialisation.
+  typedef basic_pstreambuf<char> pstreambuf;
+  /// Type definition for common template specialisation.
+  typedef basic_ipstream<char> ipstream;
+  /// Type definition for common template specialisation.
+  typedef basic_opstream<char> opstream;
+  /// Type definition for common template specialisation.
+  typedef basic_pstream<char> pstream;
+  /// Type definition for common template specialisation.
+  typedef basic_rpstream<char> rpstream;
+
+
+  /**
+   * When inserted into an output pstream the manipulator calls
+   * basic_pstreambuf<C,T>::peof() to close the output pipe,
+   * causing the child process to receive the end-of-file indicator
+   * on subsequent reads from its @c stdin stream.
+   *
+   * @brief   Manipulator to close the pipe connected to the process' stdin.
+   * @param   s  An output PStream class.
+   * @return  The stream object the manipulator was invoked on.
+   * @see     basic_pstreambuf<C,T>::peof()
+   * @relates basic_opstream basic_pstream basic_rpstream
+   */
+  template <typename C, typename T>
+    inline std::basic_ostream<C,T>&
+    peof(std::basic_ostream<C,T>& s)
+    {
+      typedef basic_pstreambuf<C,T> pstreambuf;
+      if (pstreambuf* p = dynamic_cast<pstreambuf*>(s.rdbuf()))
+        p->peof();
+      return s;
+    }
+
+
+  /*
+   * member definitions for pstreambuf
+   */
+
+
+  /**
+   * @class basic_pstreambuf
+   * Provides underlying streambuf functionality for the PStreams classes.
+   */
+
+  /** Creates an uninitialised stream buffer. */
+  template <typename C, typename T>
+    inline
+    basic_pstreambuf<C,T>::basic_pstreambuf()
+    : ppid_(-1)   // initialise to -1 to indicate no process run yet.
+    , wpipe_(-1)
+    , wbuffer_(NULL)
+    , rsrc_(rsrc_out)
+    , status_(-1)
+    , error_(0)
+    {
+      init_rbuffers();
+    }
+
+  /**
+   * Initialises the stream buffer by calling open() with the supplied
+   * arguments.
+   *
+   * @param command a string containing a shell command.
+   * @param mode    the I/O mode to use when opening the pipe.
+   * @see   open()
+   */
+  template <typename C, typename T>
+    inline
+    basic_pstreambuf<C,T>::basic_pstreambuf(const std::string& command, pmode mode)
+    : ppid_(-1)   // initialise to -1 to indicate no process run yet.
+    , wpipe_(-1)
+    , wbuffer_(NULL)
+    , rsrc_(rsrc_out)
+    , status_(-1)
+    , error_(0)
+    {
+      init_rbuffers();
+      open(command, mode);
+    }
+
+  /**
+   * Initialises the stream buffer by calling open() with the supplied
+   * arguments.
+   *
+   * @param file  a string containing the name of a program to execute.
+   * @param argv  a vector of argument strings passsed to the new program.
+   * @param mode  the I/O mode to use when opening the pipe.
+   * @see   open()
+   */
+  template <typename C, typename T>
+    inline
+    basic_pstreambuf<C,T>::basic_pstreambuf( const std::string& file,
+                                             const argv_type& argv,
+                                             pmode mode )
+    : ppid_(-1)   // initialise to -1 to indicate no process run yet.
+    , wpipe_(-1)
+    , wbuffer_(NULL)
+    , rsrc_(rsrc_out)
+    , status_(-1)
+    , error_(0)
+    {
+      init_rbuffers();
+      open(file, argv, mode);
+    }
+
+  /**
+   * Closes the stream by calling close().
+   * @see close()
+   */
+  template <typename C, typename T>
+    inline
+    basic_pstreambuf<C,T>::~basic_pstreambuf()
+    {
+      close();
+    }
+
+  /**
+   * Starts a new process by passing @a command to the shell (/bin/sh)
+   * and opens pipes to the process with the specified @a mode.
+   *
+   * If @a mode contains @c pstdout the initial read source will be
+   * the child process' stdout, otherwise if @a mode  contains @c pstderr
+   * the initial read source will be the child's stderr.
+   *
+   * Will duplicate the actions of  the  shell  in searching for an
+   * executable file if the specified file name does not contain a slash (/)
+   * character.
+   *
+   * @warning
+   * There is no way to tell whether the shell command succeeded, this
+   * function will always succeed unless resource limits (such as
+   * memory usage, or number of processes or open files) are exceeded.
+   * This means is_open() will return true even if @a command cannot
+   * be executed.
+   * Use pstreambuf::open(const std::string&, const argv_type&, pmode)
+   * if you need to know whether the command failed to execute.
+   *
+   * @param   command  a string containing a shell command.
+   * @param   mode     a bitwise OR of one or more of @c out, @c in, @c err.
+   * @return  NULL if the shell could not be started or the
+   *          pipes could not be opened, @c this otherwise.
+   * @see     <b>execl</b>(3)
+   */
+  template <typename C, typename T>
+    basic_pstreambuf<C,T>*
+    basic_pstreambuf<C,T>::open(const std::string& command, pmode mode)
+    {
+      const char * shell_path = "/bin/sh";
+#if 0
+      const std::string argv[] = { "sh", "-c", command };
+      return this->open(shell_path, argv_type(argv, argv+3), mode);
+#else
+      basic_pstreambuf<C,T>* ret = NULL;
+
+      if (!is_open())
+      {
+        switch(fork(mode))
+        {
+        case 0 :
+          // this is the new process, exec command
+          ::execl(shell_path, "sh", "-c", command.c_str(), (char*)NULL);
+
+          // can only reach this point if exec() failed
+
+          // parent can get exit code from waitpid()
+          ::_exit(errno);
+          // using std::exit() would make static dtors run twice
+
+        case -1 :
+          // couldn't fork, error already handled in pstreambuf::fork()
+          break;
+
+        default :
+          // this is the parent process
+          // activate buffers
+          create_buffers(mode);
+          ret = this;
+        }
+      }
+      return ret;
+#endif
+    }
+
+  /**
+   * @brief  Helper function to close a file descriptor.
+   *
+   * Inspects @a fd and calls <b>close</b>(3) if it has a non-negative value.
+   *
+   * @param   fd  a file descriptor.
+   * @relates basic_pstreambuf
+   */
+  inline void
+  close_fd(pstreams::fd_type& fd)
+  {
+    if (fd >= 0 && ::close(fd) == 0)
+      fd = -1;
+  }
+
+  /**
+   * @brief  Helper function to close an array of file descriptors.
+   *
+   * Calls @c close_fd() on each member of the array.
+   * The length of the array is determined automatically by
+   * template argument deduction to avoid errors.
+   *
+   * @param   fds  an array of file descriptors.
+   * @relates basic_pstreambuf
+   */
+  template <int N>
+    inline void
+    close_fd_array(pstreams::fd_type (&fds)[N])
+    {
+      for (std::size_t i = 0; i < N; ++i)
+        close_fd(fds[i]);
+    }
+
+  /**
+   * Starts a new process by executing @a file with the arguments in
+   * @a argv and opens pipes to the process with the specified @a mode.
+   *
+   * By convention @c argv[0] should be the file name of the file being
+   * executed.
+   *
+   * If @a mode contains @c pstdout the initial read source will be
+   * the child process' stdout, otherwise if @a mode  contains @c pstderr
+   * the initial read source will be the child's stderr.
+   *
+   * Will duplicate the actions of  the  shell  in searching for an
+   * executable file if the specified file name does not contain a slash (/)
+   * character.
+   *
+   * Iff @a file is successfully executed then is_open() will return true.
+   * Otherwise, pstreambuf::error() can be used to obtain the value of
+   * @c errno that was set by <b>execvp</b>(3) in the child process.
+   *
+   * The exit status of the new process will be returned by
+   * pstreambuf::status() after pstreambuf::exited() returns true.
+   *
+   * @param   file  a string containing the pathname of a program to execute.
+   * @param   argv  a vector of argument strings passed to the new program.
+   * @param   mode  a bitwise OR of one or more of @c out, @c in and @c err.
+   * @return  NULL if a pipe could not be opened or if the program could
+   *          not be executed, @c this otherwise.
+   * @see     <b>execvp</b>(3)
+   */
+  template <typename C, typename T>
+    basic_pstreambuf<C,T>*
+    basic_pstreambuf<C,T>::open( const std::string& file,
+                                 const argv_type& argv,
+                                 pmode mode )
+    {
+      basic_pstreambuf<C,T>* ret = NULL;
+
+      if (!is_open())
+      {
+        // constants for read/write ends of pipe
+        enum { RD, WR };
+
+        // open another pipe and set close-on-exec
+        fd_type ck_exec[] = { -1, -1 };
+        if (-1 == ::pipe(ck_exec)
+            || -1 == ::fcntl(ck_exec[RD], F_SETFD, FD_CLOEXEC)
+            || -1 == ::fcntl(ck_exec[WR], F_SETFD, FD_CLOEXEC))
+        {
+          error_ = errno;
+          close_fd_array(ck_exec);
+        }
+        else
+        {
+          switch(fork(mode))
+          {
+          case 0 :
+            // this is the new process, exec command
+            {
+              char** arg_v = new char*[argv.size()+1];
+              for (std::size_t i = 0; i < argv.size(); ++i)
+              {
+                const std::string& src = argv[i];
+                char*& dest = arg_v[i];
+                dest = new char[src.size()+1];
+                dest[ src.copy(dest, src.size()) ] = '\0';
+              }
+              arg_v[argv.size()] = NULL;
+
+              ::execvp(file.c_str(), arg_v);
+
+              // can only reach this point if exec() failed
+
+              // parent can get error code from ck_exec pipe
+              error_ = errno;
+
+              while (::write(ck_exec[WR], &error_, sizeof(error_)) == -1
+                  && errno == EINTR)
+              { }
+
+              ::close(ck_exec[WR]);
+              ::close(ck_exec[RD]);
+
+              ::_exit(error_);
+              // using std::exit() would make static dtors run twice
+            }
+
+          case -1 :
+            // couldn't fork, error already handled in pstreambuf::fork()
+            close_fd_array(ck_exec);
+            break;
+
+          default :
+            // this is the parent process
+
+            // check child called exec() successfully
+            ::close(ck_exec[WR]);
+            switch (::read(ck_exec[RD], &error_, sizeof(error_)))
+            {
+            case 0:
+              // activate buffers
+              create_buffers(mode);
+              ret = this;
+              break;
+            case -1:
+              error_ = errno;
+              break;
+            default:
+              // error_ contains error code from child
+              // call wait() to clean up and set ppid_ to 0
+              this->wait();
+              break;
+            }
+            ::close(ck_exec[RD]);
+          }
+        }
+      }
+      return ret;
+    }
+
+  /**
+   * Creates pipes as specified by @a mode and calls @c fork() to create
+   * a new process. If the fork is successful the parent process stores
+   * the child's PID and the opened pipes and the child process replaces
+   * its standard streams with the opened pipes.
+   *
+   * If an error occurs the error code will be set to one of the possible
+   * errors for @c pipe() or @c fork().
+   * See your system's documentation for these error codes.
+   *
+   * @param   mode  an OR of pmodes specifying which of the child's
+   *                standard streams to connect to.
+   * @return  On success the PID of the child is returned in the parent's
+   *          context and zero is returned in the child's context.
+   *          On error -1 is returned and the error code is set appropriately.
+   */
+  template <typename C, typename T>
+    pid_t
+    basic_pstreambuf<C,T>::fork(pmode mode)
+    {
+      pid_t pid = -1;
+
+      // Three pairs of file descriptors, for pipes connected to the
+      // process' stdin, stdout and stderr
+      // (stored in a single array so close_fd_array() can close all at once)
+      fd_type fd[] = { -1, -1, -1, -1, -1, -1 };
+      fd_type* const pin = fd;
+      fd_type* const pout = fd+2;
+      fd_type* const perr = fd+4;
+
+      // constants for read/write ends of pipe
+      enum { RD, WR };
+
+      // N.B.
+      // For the pstreambuf pin is an output stream and
+      // pout and perr are input streams.
+
+      if (!error_ && mode&pstdin && ::pipe(pin))
+        error_ = errno;
+
+      if (!error_ && mode&pstdout && ::pipe(pout))
+        error_ = errno;
+
+      if (!error_ && mode&pstderr && ::pipe(perr))
+        error_ = errno;
+
+      if (!error_)
+      {
+        pid = ::fork();
+        switch (pid)
+        {
+          case 0 :
+          {
+            // this is the new process
+
+            // for each open pipe close one end and redirect the
+            // respective standard stream to the other end
+
+            if (*pin >= 0)
+            {
+              ::close(pin[WR]);
+              ::dup2(pin[RD], STDIN_FILENO);
+              ::close(pin[RD]);
+            }
+            if (*pout >= 0)
+            {
+              ::close(pout[RD]);
+              ::dup2(pout[WR], STDOUT_FILENO);
+              ::close(pout[WR]);
+            }
+            if (*perr >= 0)
+            {
+              ::close(perr[RD]);
+              ::dup2(perr[WR], STDERR_FILENO);
+              ::close(perr[WR]);
+            }
+
+#ifdef _POSIX_JOB_CONTROL
+            // Change to a new process group
+            ::setpgid(0, 0);
+#endif
+
+            break;
+          }
+          case -1 :
+          {
+            // couldn't fork for some reason
+            error_ = errno;
+            // close any open pipes
+            close_fd_array(fd);
+            break;
+          }
+          default :
+          {
+            // this is the parent process, store process' pid
+            ppid_ = pid;
+
+            // store one end of open pipes and close other end
+            if (*pin >= 0)
+            {
+              wpipe_ = pin[WR];
+              ::close(pin[RD]);
+            }
+            if (*pout >= 0)
+            {
+              rpipe_[rsrc_out] = pout[RD];
+              ::close(pout[WR]);
+            }
+            if (*perr >= 0)
+            {
+              rpipe_[rsrc_err] = perr[RD];
+              ::close(perr[WR]);
+            }
+          }
+        }
+      }
+      else
+      {
+        // close any pipes we opened before failure
+        close_fd_array(fd);
+      }
+      return pid;
+    }
+
+  /**
+   * Closes all pipes and calls wait() to wait for the process to finish.
+   * If an error occurs the error code will be set to one of the possible
+   * errors for @c waitpid().
+   * See your system's documentation for these errors.
+   *
+   * @return  @c this on successful close or @c NULL if there is no
+   *          process to close or if an error occurs.
+   */
+  template <typename C, typename T>
+    basic_pstreambuf<C,T>*
+    basic_pstreambuf<C,T>::close()
+    {
+      const bool running = is_open();
+
+      sync(); // this might call wait() and reap the child process
+
+      // rather than trying to work out whether or not we need to clean up
+      // just do it anyway, all cleanup functions are safe to call twice.
+
+      destroy_buffers(pstdin|pstdout|pstderr);
+
+      // close pipes before wait() so child gets EOF/SIGPIPE
+      close_fd(wpipe_);
+      close_fd_array(rpipe_);
+
+      do
+      {
+        error_ = 0;
+      } while (wait() == -1 && error() == EINTR);
+
+      return running ? this : NULL;
+    }
+
+  /**
+   *  Called on construction to initialise the arrays used for reading.
+   */
+  template <typename C, typename T>
+    inline void
+    basic_pstreambuf<C,T>::init_rbuffers()
+    {
+      rpipe_[rsrc_out] = rpipe_[rsrc_err] = -1;
+      rbuffer_[rsrc_out] = rbuffer_[rsrc_err] = NULL;
+      rbufstate_[0] = rbufstate_[1] = rbufstate_[2] = NULL;
+    }
+
+  template <typename C, typename T>
+    void
+    basic_pstreambuf<C,T>::create_buffers(pmode mode)
+    {
+      if (mode & pstdin)
+      {
+        delete[] wbuffer_;
+        wbuffer_ = new char_type[bufsz];
+        this->setp(wbuffer_, wbuffer_ + bufsz);
+      }
+      if (mode & pstdout)
+      {
+        delete[] rbuffer_[rsrc_out];
+        rbuffer_[rsrc_out] = new char_type[bufsz];
+        rsrc_ = rsrc_out;
+        this->setg(rbuffer_[rsrc_out] + pbsz, rbuffer_[rsrc_out] + pbsz,
+            rbuffer_[rsrc_out] + pbsz);
+      }
+      if (mode & pstderr)
+      {
+        delete[] rbuffer_[rsrc_err];
+        rbuffer_[rsrc_err] = new char_type[bufsz];
+        if (!(mode & pstdout))
+        {
+          rsrc_ = rsrc_err;
+          this->setg(rbuffer_[rsrc_err] + pbsz, rbuffer_[rsrc_err] + pbsz,
+              rbuffer_[rsrc_err] + pbsz);
+        }
+      }
+    }
+
+  template <typename C, typename T>
+    void
+    basic_pstreambuf<C,T>::destroy_buffers(pmode mode)
+    {
+      if (mode & pstdin)
+      {
+        this->setp(NULL, NULL);
+        delete[] wbuffer_;
+        wbuffer_ = NULL;
+      }
+      if (mode & pstdout)
+      {
+        if (rsrc_ == rsrc_out)
+          this->setg(NULL, NULL, NULL);
+        delete[] rbuffer_[rsrc_out];
+        rbuffer_[rsrc_out] = NULL;
+      }
+      if (mode & pstderr)
+      {
+        if (rsrc_ == rsrc_err)
+          this->setg(NULL, NULL, NULL);
+        delete[] rbuffer_[rsrc_err];
+        rbuffer_[rsrc_err] = NULL;
+      }
+    }
+
+  template <typename C, typename T>
+    typename basic_pstreambuf<C,T>::buf_read_src
+    basic_pstreambuf<C,T>::switch_read_buffer(buf_read_src src)
+    {
+      if (rsrc_ != src)
+      {
+        char_type* tmpbufstate[] = {this->eback(), this->gptr(), this->egptr()};
+        this->setg(rbufstate_[0], rbufstate_[1], rbufstate_[2]);
+        for (std::size_t i = 0; i < 3; ++i)
+          rbufstate_[i] = tmpbufstate[i];
+        rsrc_ = src;
+      }
+      return rsrc_;
+    }
+
+  /**
+   * Suspends execution and waits for the associated process to exit, or
+   * until a signal is delivered whose action is to terminate the current
+   * process or to call a signal handling function. If the process has
+   * already exited (i.e. it is a "zombie" process) then wait() returns
+   * immediately.  Waiting for the child process causes all its system
+   * resources to be freed.
+   *
+   * error() will return EINTR if wait() is interrupted by a signal.
+   *
+   * @param   nohang  true to return immediately if the process has not exited.
+   * @return  1 if the process has exited and wait() has not yet been called.
+   *          0 if @a nohang is true and the process has not exited yet.
+   *          -1 if no process has been started or if an error occurs,
+   *          in which case the error can be found using error().
+   */
+  template <typename C, typename T>
+    int
+    basic_pstreambuf<C,T>::wait(bool nohang)
+    {
+      int exited = -1;
+      if (is_open())
+      {
+        int status;
+        switch(::waitpid(ppid_, &status, nohang ? WNOHANG : 0))
+        {
+          case 0 :
+            // nohang was true and process has not exited
+            exited = 0;
+            break;
+          case -1 :
+            error_ = errno;
+            break;
+          default :
+            // process has exited
+            ppid_ = 0;
+            status_ = status;
+            exited = 1;
+            // Close wpipe, would get SIGPIPE if we used it.
+            destroy_buffers(pstdin);
+            close_fd(wpipe_);
+            // Must free read buffers and pipes on destruction
+            // or next call to open()/close()
+            break;
+        }
+      }
+      return exited;
+    }
+
+  /**
+   * Sends the specified signal to the process.  A signal can be used to
+   * terminate a child process that would not exit otherwise.
+   *
+   * If an error occurs the error code will be set to one of the possible
+   * errors for @c kill().  See your system's documentation for these errors.
+   *
+   * @param   signal  A signal to send to the child process.
+   * @return  @c this or @c NULL if @c kill() fails.
+   */
+  template <typename C, typename T>
+    inline basic_pstreambuf<C,T>*
+    basic_pstreambuf<C,T>::kill(int signal)
+    {
+      basic_pstreambuf<C,T>* ret = NULL;
+      if (is_open())
+      {
+        if (::kill(ppid_, signal))
+          error_ = errno;
+        else
+        {
+#if 0
+          // TODO call exited() to check for exit and clean up? leave to user?
+          if (signal==SIGTERM || signal==SIGKILL)
+            this->exited();
+#endif
+          ret = this;
+        }
+      }
+      return ret;
+    }
+
+  /**
+   * Sends the specified signal to the process group of the child process.
+   * A signal can be used to terminate a child process that would not exit
+   * otherwise, or to kill the process and its own children.
+   *
+   * If an error occurs the error code will be set to one of the possible
+   * errors for @c getpgid() or @c kill().  See your system's documentation
+   * for these errors. If the child is in the current process group then
+   * NULL will be returned and the error code set to EPERM.
+   *
+   * @param   signal  A signal to send to the child process.
+   * @return  @c this on success or @c NULL on failure.
+   */
+  template <typename C, typename T>
+    inline basic_pstreambuf<C,T>*
+    basic_pstreambuf<C,T>::killpg(int signal)
+    {
+      basic_pstreambuf<C,T>* ret = NULL;
+#ifdef _POSIX_JOB_CONTROL
+      if (is_open())
+      {
+        pid_t pgid = ::getpgid(ppid_);
+        if (pgid == -1)
+          error_ = errno;
+        else if (pgid == ::getpgrp())
+          error_ = EPERM;  // Don't commit suicide
+        else if (::killpg(pgid, signal))
+          error_ = errno;
+        else
+          ret = this;
+      }
+#endif
+      return ret;
+    }
+
+  /**
+   *  This function can call pstreambuf::wait() and so may change the
+   *  object's state if the child process has already exited.
+   *
+   *  @return  True if the associated process has exited, false otherwise.
+   *  @see     basic_pstreambuf<C,T>::wait()
+   */
+  template <typename C, typename T>
+    inline bool
+    basic_pstreambuf<C,T>::exited()
+    {
+      return ppid_ == 0 || wait(true)==1;
+    }
+
+
+  /**
+   *  @return  The exit status of the child process, or -1 if wait()
+   *           has not yet been called to wait for the child to exit.
+   *  @see     basic_pstreambuf<C,T>::wait()
+   */
+  template <typename C, typename T>
+    inline int
+    basic_pstreambuf<C,T>::status() const
+    {
+      return status_;
+    }
+
+  /**
+   *  @return  The error code of the most recently failed operation, or zero.
+   */
+  template <typename C, typename T>
+    inline int
+    basic_pstreambuf<C,T>::error() const
+    {
+      return error_;
+    }
+
+  /**
+   *  Closes the output pipe, causing the child process to receive the
+   *  end-of-file indicator on subsequent reads from its @c stdin stream.
+   */
+  template <typename C, typename T>
+    inline void
+    basic_pstreambuf<C,T>::peof()
+    {
+      sync();
+      destroy_buffers(pstdin);
+      close_fd(wpipe_);
+    }
+
+  /**
+   * Unlike pstreambuf::exited(), this function will not call wait() and
+   * so will not change the object's state.  This means that once a child
+   * process is executed successfully this function will continue to
+   * return true even after the process exits (until wait() is called.)
+   *
+   * @return  true if a previous call to open() succeeded and wait() has
+   *          not been called and determined that the process has exited,
+   *          false otherwise.
+   */
+  template <typename C, typename T>
+    inline bool
+    basic_pstreambuf<C,T>::is_open() const
+    {
+      return ppid_ > 0;
+    }
+
+  /**
+   * Toggle the stream used for reading. If @a readerr is @c true then the
+   * process' @c stderr output will be used for subsequent extractions, if
+   * @a readerr is false the the process' stdout will be used.
+   * @param   readerr  @c true to read @c stderr, @c false to read @c stdout.
+   * @return  @c true if the requested stream is open and will be used for
+   *          subsequent extractions, @c false otherwise.
+   */
+  template <typename C, typename T>
+    inline bool
+    basic_pstreambuf<C,T>::read_err(bool readerr)
+    {
+      buf_read_src src = readerr ? rsrc_err : rsrc_out;
+      if (rpipe_[src]>=0)
+      {
+        switch_read_buffer(src);
+        return true;
+      }
+      return false;
+    }
+
+  /**
+   * Called when the internal character buffer is not present or is full,
+   * to transfer the buffer contents to the pipe.
+   *
+   * @param   c  a character to be written to the pipe.
+   * @return  @c traits_type::eof() if an error occurs, otherwise if @a c
+   *          is not equal to @c traits_type::eof() it will be buffered and
+   *          a value other than @c traits_type::eof() returned to indicate
+   *          success.
+   */
+  template <typename C, typename T>
+    typename basic_pstreambuf<C,T>::int_type
+    basic_pstreambuf<C,T>::overflow(int_type c)
+    {
+      if (!empty_buffer())
+        return traits_type::eof();
+      else if (!traits_type::eq_int_type(c, traits_type::eof()))
+        return this->sputc(c);
+      else
+        return traits_type::not_eof(c);
+    }
+
+
+  template <typename C, typename T>
+    int
+    basic_pstreambuf<C,T>::sync()
+    {
+      return !exited() && empty_buffer() ? 0 : -1;
+    }
+
+  /**
+   * @param   s  character buffer.
+   * @param   n  buffer length.
+   * @return  the number of characters written.
+   */
+  template <typename C, typename T>
+    std::streamsize
+    basic_pstreambuf<C,T>::xsputn(const char_type* s, std::streamsize n)
+    {
+      std::streamsize done = 0;
+      while (done < n)
+      {
+        if (std::streamsize nbuf = this->epptr() - this->pptr())
+        {
+          nbuf = std::min(nbuf, n - done);
+          traits_type::copy(this->pptr(), s + done, nbuf);
+          this->pbump(nbuf);
+          done += nbuf;
+        }
+        else if (!empty_buffer())
+          break;
+      }
+      return done;
+    }
+
+  /**
+   * @return  true if the buffer was emptied, false otherwise.
+   */
+  template <typename C, typename T>
+    bool
+    basic_pstreambuf<C,T>::empty_buffer()
+    {
+      const std::streamsize count = this->pptr() - this->pbase();
+      if (count > 0)
+      {
+        const std::streamsize written = this->write(this->wbuffer_, count);
+        if (written > 0)
+        {
+          if (const std::streamsize unwritten = count - written)
+            traits_type::move(this->pbase(), this->pbase()+written, unwritten);
+          this->pbump(-written);
+          return true;
+        }
+      }
+      return false;
+    }
+
+  /**
+   * Called when the internal character buffer is is empty, to re-fill it
+   * from the pipe.
+   *
+   * @return The first available character in the buffer,
+   * or @c traits_type::eof() in case of failure.
+   */
+  template <typename C, typename T>
+    typename basic_pstreambuf<C,T>::int_type
+    basic_pstreambuf<C,T>::underflow()
+    {
+      if (this->gptr() < this->egptr() || fill_buffer())
+        return traits_type::to_int_type(*this->gptr());
+      else
+        return traits_type::eof();
+    }
+
+  /**
+   * Attempts to make @a c available as the next character to be read by
+   * @c sgetc().
+   *
+   * @param   c   a character to make available for extraction.
+   * @return  @a c if the character can be made available,
+   *          @c traits_type::eof() otherwise.
+   */
+  template <typename C, typename T>
+    typename basic_pstreambuf<C,T>::int_type
+    basic_pstreambuf<C,T>::pbackfail(int_type c)
+    {
+      if (this->gptr() != this->eback())
+      {
+        this->gbump(-1);
+        if (!traits_type::eq_int_type(c, traits_type::eof()))
+          *this->gptr() = traits_type::to_char_type(c);
+        return traits_type::not_eof(c);
+      }
+      else
+         return traits_type::eof();
+    }
+
+  template <typename C, typename T>
+    std::streamsize
+    basic_pstreambuf<C,T>::showmanyc()
+    {
+      int avail = 0;
+      if (sizeof(char_type) == 1)
+        avail = fill_buffer(true) ? this->egptr() - this->gptr() : -1;
+#ifdef FIONREAD
+      else
+      {
+        if (::ioctl(rpipe(), FIONREAD, &avail) == -1)
+          avail = -1;
+        else if (avail)
+          avail /= sizeof(char_type);
+      }
+#endif
+      return std::streamsize(avail);
+    }
+
+  /**
+   * @return  true if the buffer was filled, false otherwise.
+   */
+  template <typename C, typename T>
+    bool
+    basic_pstreambuf<C,T>::fill_buffer(bool non_blocking)
+    {
+      const std::streamsize pb1 = this->gptr() - this->eback();
+      const std::streamsize pb2 = pbsz;
+      const std::streamsize npb = std::min(pb1, pb2);
+
+      char_type* const rbuf = rbuffer();
+
+      traits_type::move(rbuf + pbsz - npb, this->gptr() - npb, npb);
+
+      std::streamsize rc = -1;
+
+      if (non_blocking)
+      {
+        const int flags = ::fcntl(rpipe(), F_GETFL);
+        if (flags != -1)
+        {
+          const bool blocking = !(flags & O_NONBLOCK);
+          if (blocking)
+            ::fcntl(rpipe(), F_SETFL, flags | O_NONBLOCK);  // set non-blocking
+
+          error_ = 0;
+          rc = read(rbuf + pbsz, bufsz - pbsz);
+
+          if (rc == -1 && error_ == EAGAIN)  // nothing available
+            rc = 0;
+          else if (rc == 0)  // EOF
+            rc = -1;
+
+          if (blocking)
+            ::fcntl(rpipe(), F_SETFL, flags); // restore
+        }
+      }
+      else
+        rc = read(rbuf + pbsz, bufsz - pbsz);
+
+      if (rc > 0 || (rc == 0 && non_blocking))
+      {
+        this->setg( rbuf + pbsz - npb,
+                    rbuf + pbsz,
+                    rbuf + pbsz + rc );
+        return true;
+      }
+      else
+      {
+        this->setg(NULL, NULL, NULL);
+        return false;
+      }
+    }
+
+  /**
+   * Writes up to @a n characters to the pipe from the buffer @a s.
+   *
+   * @param   s  character buffer.
+   * @param   n  buffer length.
+   * @return  the number of characters written.
+   */
+  template <typename C, typename T>
+    inline std::streamsize
+    basic_pstreambuf<C,T>::write(const char_type* s, std::streamsize n)
+    {
+      std::streamsize nwritten = 0;
+      if (wpipe() >= 0)
+      {
+        nwritten = ::write(wpipe(), s, n * sizeof(char_type));
+        if (nwritten == -1)
+          error_ = errno;
+        else
+          nwritten /= sizeof(char_type);
+      }
+      return nwritten;
+    }
+
+  /**
+   * Reads up to @a n characters from the pipe to the buffer @a s.
+   *
+   * @param   s  character buffer.
+   * @param   n  buffer length.
+   * @return  the number of characters read.
+   */
+  template <typename C, typename T>
+    inline std::streamsize
+    basic_pstreambuf<C,T>::read(char_type* s, std::streamsize n)
+    {
+      std::streamsize nread = 0;
+      if (rpipe() >= 0)
+      {
+        nread = ::read(rpipe(), s, n * sizeof(char_type));
+        if (nread == -1)
+          error_ = errno;
+        else
+          nread /= sizeof(char_type);
+      }
+      return nread;
+    }
+
+  /** @return a reference to the output file descriptor */
+  template <typename C, typename T>
+    inline pstreams::fd_type&
+    basic_pstreambuf<C,T>::wpipe()
+    {
+      return wpipe_;
+    }
+
+  /** @return a reference to the active input file descriptor */
+  template <typename C, typename T>
+    inline pstreams::fd_type&
+    basic_pstreambuf<C,T>::rpipe()
+    {
+      return rpipe_[rsrc_];
+    }
+
+  /** @return a reference to the specified input file descriptor */
+  template <typename C, typename T>
+    inline pstreams::fd_type&
+    basic_pstreambuf<C,T>::rpipe(buf_read_src which)
+    {
+      return rpipe_[which];
+    }
+
+  /** @return a pointer to the start of the active input buffer area. */
+  template <typename C, typename T>
+    inline typename basic_pstreambuf<C,T>::char_type*
+    basic_pstreambuf<C,T>::rbuffer()
+    {
+      return rbuffer_[rsrc_];
+    }
+
+
+  /*
+   * member definitions for pstream_common
+   */
+
+  /**
+   * @class pstream_common
+   * Abstract Base Class providing common functionality for basic_ipstream,
+   * basic_opstream and basic_pstream.
+   * pstream_common manages the basic_pstreambuf stream buffer that is used
+   * by the derived classes to initialise an iostream class.
+   */
+
+  /** Creates an uninitialised stream. */
+  template <typename C, typename T>
+    inline
+    pstream_common<C,T>::pstream_common()
+    : std::basic_ios<C,T>(NULL)
+    , command_()
+    , buf_()
+    {
+      this->std::basic_ios<C,T>::rdbuf(&buf_);
+    }
+
+  /**
+   * Initialises the stream buffer by calling
+   * do_open( @a command , @a mode )
+   *
+   * @param command a string containing a shell command.
+   * @param mode    the I/O mode to use when opening the pipe.
+   * @see   do_open(const std::string&, pmode)
+   */
+  template <typename C, typename T>
+    inline
+    pstream_common<C,T>::pstream_common(const std::string& command, pmode mode)
+    : std::basic_ios<C,T>(NULL)
+    , command_(command)
+    , buf_()
+    {
+      this->std::basic_ios<C,T>::rdbuf(&buf_);
+      do_open(command, mode);
+    }
+
+  /**
+   * Initialises the stream buffer by calling
+   * do_open( @a file , @a argv , @a mode )
+   *
+   * @param file  a string containing the pathname of a program to execute.
+   * @param argv  a vector of argument strings passed to the new program.
+   * @param mode  the I/O mode to use when opening the pipe.
+   * @see do_open(const std::string&, const argv_type&, pmode)
+   */
+  template <typename C, typename T>
+    inline
+    pstream_common<C,T>::pstream_common( const std::string& file,
+                                         const argv_type& argv,
+                                         pmode mode )
+    : std::basic_ios<C,T>(NULL)
+    , command_(file)
+    , buf_()
+    {
+      this->std::basic_ios<C,T>::rdbuf(&buf_);
+      do_open(file, argv, mode);
+    }
+
+  /**
+   * This is a pure virtual function to make @c pstream_common abstract.
+   * Because it is the destructor it will be called by derived classes
+   * and so must be defined.  It is also protected, to discourage use of
+   * the PStreams classes through pointers or references to the base class.
+   *
+   * @sa If defining a pure virtual seems odd you should read
+   * http://www.gotw.ca/gotw/031.htm (and the rest of the site as well!)
+   */
+  template <typename C, typename T>
+    inline
+    pstream_common<C,T>::~pstream_common()
+    {
+    }
+
+  /**
+   * Calls rdbuf()->open( @a command , @a mode )
+   * and sets @c failbit on error.
+   *
+   * @param command a string containing a shell command.
+   * @param mode    the I/O mode to use when opening the pipe.
+   * @see   basic_pstreambuf::open(const std::string&, pmode)
+   */
+  template <typename C, typename T>
+    inline void
+    pstream_common<C,T>::do_open(const std::string& command, pmode mode)
+    {
+      if (!buf_.open((command_=command), mode))
+        this->setstate(std::ios_base::failbit);
+    }
+
+  /**
+   * Calls rdbuf()->open( @a file, @a  argv, @a mode )
+   * and sets @c failbit on error.
+   *
+   * @param file  a string containing the pathname of a program to execute.
+   * @param argv  a vector of argument strings passed to the new program.
+   * @param mode  the I/O mode to use when opening the pipe.
+   * @see   basic_pstreambuf::open(const std::string&, const argv_type&, pmode)
+   */
+  template <typename C, typename T>
+    inline void
+    pstream_common<C,T>::do_open( const std::string& file,
+                                  const argv_type& argv,
+                                  pmode mode )
+    {
+      if (!buf_.open((command_=file), argv, mode))
+        this->setstate(std::ios_base::failbit);
+    }
+
+  /** Calls rdbuf->close() and sets @c failbit on error. */
+  template <typename C, typename T>
+    inline void
+    pstream_common<C,T>::close()
+    {
+      if (!buf_.close())
+        this->setstate(std::ios_base::failbit);
+    }
+
+  /**
+   * @return  rdbuf()->is_open().
+   * @see     basic_pstreambuf::is_open()
+   */
+  template <typename C, typename T>
+    inline bool
+    pstream_common<C,T>::is_open() const
+    {
+      return buf_.is_open();
+    }
+
+  /** @return a string containing the command used to initialise the stream. */
+  template <typename C, typename T>
+    inline const std::string&
+    pstream_common<C,T>::command() const
+    {
+      return command_;
+    }
+
+  /** @return a pointer to the private stream buffer member. */
+  // TODO  document behaviour if buffer replaced.
+  template <typename C, typename T>
+    inline typename pstream_common<C,T>::streambuf_type*
+    pstream_common<C,T>::rdbuf() const
+    {
+      return const_cast<streambuf_type*>(&buf_);
+    }
+
+
+#if REDI_EVISCERATE_PSTREAMS
+  /**
+   * @def REDI_EVISCERATE_PSTREAMS
+   * If this macro has a non-zero value then certain internals of the
+   * @c basic_pstreambuf template class are exposed. In general this is
+   * a Bad Thing, as the internal implementation is largely undocumented
+   * and may be subject to change at any time, so this feature is only
+   * provided because it might make PStreams useful in situations where
+   * it is necessary to do Bad Things.
+   */
+
+  /**
+   * @warning  This function exposes the internals of the stream buffer and
+   *           should be used with caution. It is the caller's responsibility
+   *           to flush streams etc. in order to clear any buffered data.
+   *           The POSIX.1 function <b>fdopen</b>(3) is used to obtain the
+   *           @c FILE pointers from the streambuf's private file descriptor
+   *           members so consult your system's documentation for
+   *           <b>fdopen</b>(3).
+   *
+   * @param   in    A FILE* that will refer to the process' stdin.
+   * @param   out   A FILE* that will refer to the process' stdout.
+   * @param   err   A FILE* that will refer to the process' stderr.
+   * @return  An OR of zero or more of @c pstdin, @c pstdout, @c pstderr.
+   *
+   * For each open stream shared with the child process a @c FILE* is
+   * obtained and assigned to the corresponding parameter. For closed
+   * streams @c NULL is assigned to the parameter.
+   * The return value can be tested to see which parameters should be
+   * @c !NULL by masking with the corresponding @c pmode value.
+   *
+   * @see <b>fdopen</b>(3)
+   */
+  template <typename C, typename T>
+    std::size_t
+    basic_pstreambuf<C,T>::fopen(FILE*& in, FILE*& out, FILE*& err)
+    {
+      in = out = err = NULL;
+      std::size_t open_files = 0;
+      if (wpipe() > -1)
+      {
+        if ((in = ::fdopen(wpipe(), "w")))
+        {
+            open_files |= pstdin;
+        }
+      }
+      if (rpipe(rsrc_out) > -1)
+      {
+        if ((out = ::fdopen(rpipe(rsrc_out), "r")))
+        {
+            open_files |= pstdout;
+        }
+      }
+      if (rpipe(rsrc_err) > -1)
+      {
+        if ((err = ::fdopen(rpipe(rsrc_err), "r")))
+        {
+            open_files |= pstderr;
+        }
+      }
+      return open_files;
+    }
+
+  /**
+   *  @warning This function exposes the internals of the stream buffer and
+   *  should be used with caution.
+   *
+   *  @param  in   A FILE* that will refer to the process' stdin.
+   *  @param  out  A FILE* that will refer to the process' stdout.
+   *  @param  err  A FILE* that will refer to the process' stderr.
+   *  @return A bitwise-or of zero or more of @c pstdin, @c pstdout, @c pstderr.
+   *  @see    basic_pstreambuf::fopen()
+   */
+  template <typename C, typename T>
+    inline std::size_t
+    pstream_common<C,T>::fopen(FILE*& fin, FILE*& fout, FILE*& ferr)
+    {
+      return buf_.fopen(fin, fout, ferr);
+    }
+
+#endif // REDI_EVISCERATE_PSTREAMS
+
+
+} // namespace redi
+
+/**
+ * @mainpage PStreams Reference
+ * @htmlinclude mainpage.html
+ */
+
+#endif  // REDI_PSTREAM_H_SEEN
+
+// vim: ts=2 sw=2 expandtab
+
diff --git a/examples++-load/qf11to25.cpp b/examples++-load/qf11to25.cpp
new file mode 100644
index 0000000..6aa87d2
--- /dev/null
+++ b/examples++-load/qf11to25.cpp
@@ -0,0 +1,864 @@
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include <fstream>
+#include "error.hpp"
+#include "AFunction.hpp"
+using namespace std;
+
+
+#include "RNM.hpp"
+#include "rgraph.hpp"
+#include "fem.hpp"
+#include "QuadratureFormular.hpp"
+using  namespace Fem2D ; 
+/* awk -F[ t=:]* -f tt.awk  coords.txt >QF.cpp
+
+/integration/ { if(ii) {print "};" 
+  print "const QuadratureFormular QuadratureFormular_T_" ii "(3," ii " ," N ",P_QuadratureFormular_T_" ii ");"
+  print ""
+  print ""			 
+};ii=$3;N=$5;
+ print "static const QuadraturePoint P_QuadratureFormular_T_" $3 "[] = {";}
+!/integration/ {print "QuadraturePoint(" $4 "/2," $2"," $3"),"}
+END {print "};";
+  print "const QuadratureFormular QuadratureFormular_T_" ii "(3," ii " ," N ",P_QuadratureFormular_T_" ii ");"
+  print ""
+    print ""			 
+}
+*/
+/* 
+static const QuadraturePoint P_QuadratureFormular_T_2[] = {
+QuadraturePoint(0.6666666666667/2,0.1666666666667,0.6666666666667),
+QuadraturePoint(0.6666666666667/2,0.6666666666667,0.1666666666667),
+QuadraturePoint(0.6666666666667/2,0.1666666666667,0.1666666666667),
+};
+const QuadratureFormular QuadratureFormular_T_2(3,2 ,3,P_QuadratureFormular_T_2);
+
+
+static const QuadraturePoint P_QuadratureFormular_T_4[] = {
+QuadraturePoint(0.2199034873106/2,0.0915762135098,0.0915762135098),
+QuadraturePoint(0.2199034873106/2,0.8168475729805,0.0915762135098),
+QuadraturePoint(0.2199034873106/2,0.0915762135098,0.8168475729805),
+QuadraturePoint(0.4467631793560/2,0.1081030181681,0.4459484909160),
+QuadraturePoint(0.4467631793560/2,0.4459484909160,0.1081030181681),
+QuadraturePoint(0.4467631793560/2,0.4459484909160,0.4459484909160),
+};
+const QuadratureFormular QuadratureFormular_T_4(3,4 ,6,P_QuadratureFormular_T_4);
+
+
+static const QuadraturePoint P_QuadratureFormular_T_5[] = {
+QuadraturePoint(0.0262712099504/2,0.0000000000000,1.0000000000000),
+QuadraturePoint(0.0262716612068/2,1.0000000000000,0.0000000000000),
+QuadraturePoint(0.0274163947600/2,0.0000000000000,0.0000000000000),
+QuadraturePoint(0.2348383865823/2,0.2673273531185,0.6728199218710),
+QuadraturePoint(0.2348412238268/2,0.6728175529461,0.2673288599482),
+QuadraturePoint(0.2480251793114/2,0.0649236350054,0.6716530111494),
+QuadraturePoint(0.2480304922521/2,0.6716498539042,0.0649251690029),
+QuadraturePoint(0.2518604605529/2,0.0654032456800,0.2693789366453),
+QuadraturePoint(0.2518660533658/2,0.2693767069140,0.0654054874919),
+QuadraturePoint(0.4505789381914/2,0.3386738503896,0.3386799893027),
+};
+const QuadratureFormular QuadratureFormular_T_5(3,5 ,10,P_QuadratureFormular_T_5);
+
+
+static const QuadraturePoint P_QuadratureFormular_T_7[] = {
+QuadraturePoint(0.0102558174092/2,1.0000000000000,0.0000000000000),
+QuadraturePoint(0.0102558174092/2,0.0000000000000,0.0000000000000),
+QuadraturePoint(0.0102558174092/2,0.0000000000000,1.0000000000000),
+QuadraturePoint(0.1116047046647/2,0.7839656651012,0.0421382841642),
+QuadraturePoint(0.1116047046647/2,0.1738960507345,0.7839656651012),
+QuadraturePoint(0.1116047046647/2,0.1738960507345,0.0421382841642),
+QuadraturePoint(0.1116047046647/2,0.0421382841642,0.1738960507345),
+QuadraturePoint(0.1116047046647/2,0.7839656651012,0.1738960507345),
+QuadraturePoint(0.1116047046647/2,0.0421382841642,0.7839656651012),
+QuadraturePoint(0.1679775595335/2,0.4743880861752,0.4743880861752),
+QuadraturePoint(0.1679775595335/2,0.4743880861752,0.0512238276497),
+QuadraturePoint(0.1679775595335/2,0.0512238276497,0.4743880861752),
+QuadraturePoint(0.2652238803946/2,0.2385615300181,0.5228769399639),
+QuadraturePoint(0.2652238803946/2,0.5228769399639,0.2385615300181),
+QuadraturePoint(0.2652238803946/2,0.2385615300181,0.2385615300181),
+};
+const QuadratureFormular QuadratureFormular_T_7(3,7 ,15,P_QuadratureFormular_T_7);
+
+
+static const QuadraturePoint P_QuadratureFormular_T_9[] = {
+QuadraturePoint(0.0519871420646/2,0.0451890097844,0.0451890097844),
+QuadraturePoint(0.0519871420646/2,0.0451890097844,0.9096219804312),
+QuadraturePoint(0.0519871420646/2,0.9096219804312,0.0451890097844),
+QuadraturePoint(0.0707034101784/2,0.7475124727339,0.0304243617288),
+QuadraturePoint(0.0707034101784/2,0.2220631655373,0.0304243617288),
+QuadraturePoint(0.0707034101784/2,0.7475124727339,0.2220631655373),
+QuadraturePoint(0.0707034101784/2,0.2220631655373,0.7475124727339),
+QuadraturePoint(0.0707034101784/2,0.0304243617288,0.7475124727339),
+QuadraturePoint(0.0707034101784/2,0.0304243617288,0.2220631655373),
+QuadraturePoint(0.0909390760952/2,0.1369912012649,0.2182900709714),
+QuadraturePoint(0.0909390760952/2,0.6447187277637,0.2182900709714),
+QuadraturePoint(0.0909390760952/2,0.1369912012649,0.6447187277637),
+QuadraturePoint(0.0909390760952/2,0.2182900709714,0.6447187277637),
+QuadraturePoint(0.0909390760952/2,0.2182900709714,0.1369912012649),
+QuadraturePoint(0.0909390760952/2,0.6447187277637,0.1369912012649),
+QuadraturePoint(0.1032344051380/2,0.0369603304334,0.4815198347833),
+QuadraturePoint(0.1032344051380/2,0.4815198347833,0.0369603304334),
+QuadraturePoint(0.1032344051380/2,0.4815198347833,0.4815198347833),
+QuadraturePoint(0.1881601469167/2,0.4036039798179,0.1927920403641),
+QuadraturePoint(0.1881601469167/2,0.4036039798179,0.4036039798179),
+QuadraturePoint(0.1881601469167/2,0.1927920403641,0.4036039798179),
+};
+const QuadratureFormular QuadratureFormular_T_9(3,9 ,21,P_QuadratureFormular_T_9);
+*/
+
+static  QuadraturePoint P_QuadratureFormular_T_11[] = {
+QuadraturePoint(0.0114082494033/2,0.0000000000000,0.9451704450174),
+QuadraturePoint(0.0114082494033/2,0.9451704450173,0.0000000000000),
+QuadraturePoint(0.0132691285720/2,0.9289002405719,0.0685505797224),
+QuadraturePoint(0.0132691285720/2,0.0685505797224,0.9289002405717),
+QuadraturePoint(0.0155865773350/2,0.0243268355615,0.0243268355616),
+QuadraturePoint(0.0408274780428/2,0.1279662835335,0.0277838749488),
+QuadraturePoint(0.0408274780429/2,0.0277838749488,0.1279662835337),
+QuadraturePoint(0.0579849665116/2,0.0287083428360,0.7498347588657),
+QuadraturePoint(0.0579849665116/2,0.7498347588656,0.0287083428360),
+QuadraturePoint(0.0601385247663/2,0.7228007909707,0.2497602062385),
+QuadraturePoint(0.0601385247663/2,0.2497602062386,0.7228007909707),
+QuadraturePoint(0.0625273888433/2,0.0865562992839,0.8325513856997),
+QuadraturePoint(0.0625273888433/2,0.8325513856998,0.0865562992839),
+QuadraturePoint(0.0639684321504/2,0.3061619157672,0.0303526617491),
+QuadraturePoint(0.0639684321504/2,0.0303526617491,0.3061619157675),
+QuadraturePoint(0.0661325872161/2,0.4868610595047,0.4868610595047),
+QuadraturePoint(0.0668503236820/2,0.6657904293017,0.1765456154219),
+QuadraturePoint(0.0668503236821/2,0.1765456154221,0.6657904293016),
+QuadraturePoint(0.0686904305977/2,0.0293121007360,0.5295657488669),
+QuadraturePoint(0.0686904305977/2,0.5295657488667,0.0293121007360),
+QuadraturePoint(0.1002717543859/2,0.1444673824391,0.1444673824391),
+QuadraturePoint(0.1143136784099/2,0.3299740111411,0.5361815729050),
+QuadraturePoint(0.1143136784099/2,0.5361815729052,0.3299740111409),
+QuadraturePoint(0.1223648146752/2,0.5511507516862,0.1437790861923),
+QuadraturePoint(0.1223648146752/2,0.1437790861923,0.5511507516862),
+QuadraturePoint(0.1394422334178/2,0.3348066587327,0.1529619437161),
+QuadraturePoint(0.1394422334178/2,0.1529619437161,0.3348066587327),
+QuadraturePoint(0.1744377829182/2,0.3430183498147,0.3430183498147),
+};
+const QuadratureFormular QuadratureFormular_T_11(11 ,28,P_QuadratureFormular_T_11);
+
+
+static  QuadraturePoint P_QuadratureFormular_T_13[] = {
+QuadraturePoint(0.0166240998757/2,0.0242935351590,0.9493059293846),
+QuadraturePoint(0.0166811699778/2,0.0265193427722,0.0242695130640),
+QuadraturePoint(0.0166830569067/2,0.9492126023551,0.0265067966437),
+QuadraturePoint(0.0175680870083/2,0.0033775763749,0.4767316412363),
+QuadraturePoint(0.0184474661845/2,0.4757672298101,0.5198921829102),
+QuadraturePoint(0.0197942410188/2,0.5190783193471,0.0055912706202),
+QuadraturePoint(0.0203540395855/2,0.8616839745321,0.0133996048618),
+QuadraturePoint(0.0206852863940/2,0.1249209759926,0.8613054321334),
+QuadraturePoint(0.0208271366086/2,0.0138565453861,0.1247733717358),
+QuadraturePoint(0.0317819778279/2,0.0211887064222,0.8438438351223),
+QuadraturePoint(0.0320472035241/2,0.8432296787219,0.1354563645830),
+QuadraturePoint(0.0320607681146/2,0.1354231797865,0.0213482820656),
+QuadraturePoint(0.0430765959183/2,0.3088853510679,0.0221919663014),
+QuadraturePoint(0.0438473415339/2,0.6685057595169,0.3089012879389),
+QuadraturePoint(0.0439209672733/2,0.0226545012557,0.6691709943321),
+QuadraturePoint(0.0479951923691/2,0.2808515408772,0.6924718155106),
+QuadraturePoint(0.0483806260733/2,0.6922446749051,0.0268723345026),
+QuadraturePoint(0.0484867423375/2,0.0268617447119,0.2810093973222),
+QuadraturePoint(0.0556964488024/2,0.1141778485470,0.7973581413586),
+QuadraturePoint(0.0561026364356/2,0.7974807922061,0.0879806508791),
+QuadraturePoint(0.0565190123693/2,0.0892807293894,0.1145020561128),
+QuadraturePoint(0.0689289890670/2,0.1052487892455,0.6686904119922),
+QuadraturePoint(0.0717213336089/2,0.6663022280740,0.2275051631832),
+QuadraturePoint(0.0727453920976/2,0.2307803737547,0.1054572561221),
+QuadraturePoint(0.0788807336737/2,0.1705059157540,0.5174064398658),
+QuadraturePoint(0.0810114345512/2,0.5086593973043,0.3170523855209),
+QuadraturePoint(0.0825725299055/2,0.3141823862281,0.1810706361659),
+QuadraturePoint(0.0842044567330/2,0.4617460817864,0.4678594539804),
+QuadraturePoint(0.0843585533305/2,0.0693087496081,0.4622856042085),
+QuadraturePoint(0.0851969868488/2,0.4651955259268,0.0724357805669),
+QuadraturePoint(0.0902845328052/2,0.2578625857893,0.6131395039177),
+QuadraturePoint(0.0914283143485/2,0.6112627766779,0.1300360834609),
+QuadraturePoint(0.0916279065409/2,0.1305182135934,0.2581713828884),
+QuadraturePoint(0.1025573374896/2,0.4281437991828,0.2362005969817),
+QuadraturePoint(0.1033159661413/2,0.3356995783730,0.4311026308588),
+QuadraturePoint(0.1035854367193/2,0.2305424298836,0.3456013949376),
+};
+const QuadratureFormular QuadratureFormular_T_13(13 ,36,P_QuadratureFormular_T_13);
+
+
+static  QuadraturePoint P_QuadratureFormular_T_14[] = {
+QuadraturePoint(0.0010616711990/2,0.0000000000000,1.0000000000000),
+QuadraturePoint(0.0010616711990/2,1.0000000000000,0.0000000000000),
+QuadraturePoint(0.0010616711990/2,0.0000000000000,0.0000000000000),
+QuadraturePoint(0.0131460236101/2,0.0573330873026,0.0151382269814),
+QuadraturePoint(0.0131460236101/2,0.0573330873026,0.9275286857160),
+QuadraturePoint(0.0131460236101/2,0.9275286857160,0.0573330873026),
+QuadraturePoint(0.0131460236101/2,0.0151382269814,0.0573330873026),
+QuadraturePoint(0.0131460236101/2,0.9275286857160,0.0151382269814),
+QuadraturePoint(0.0131460236101/2,0.0151382269814,0.9275286857160),
+QuadraturePoint(0.0242881926949/2,0.8159625040711,0.1659719969565),
+QuadraturePoint(0.0242881926949/2,0.8159625040711,0.0180654989724),
+QuadraturePoint(0.0242881926949/2,0.1659719969565,0.8159625040711),
+QuadraturePoint(0.0242881926949/2,0.0180654989724,0.8159625040711),
+QuadraturePoint(0.0242881926949/2,0.1659719969565,0.0180654989724),
+QuadraturePoint(0.0242881926949/2,0.0180654989724,0.1659719969565),
+QuadraturePoint(0.0316799866332/2,0.3165475556378,0.0186886898773),
+QuadraturePoint(0.0316799866332/2,0.6647637544849,0.0186886898773),
+QuadraturePoint(0.0316799866332/2,0.0186886898773,0.6647637544849),
+QuadraturePoint(0.0316799866332/2,0.0186886898773,0.3165475556378),
+QuadraturePoint(0.0316799866332/2,0.3165475556378,0.6647637544849),
+QuadraturePoint(0.0316799866332/2,0.6647637544849,0.3165475556378),
+QuadraturePoint(0.0349317947036/2,0.0192662192492,0.4903668903754),
+QuadraturePoint(0.0349317947036/2,0.4903668903754,0.0192662192492),
+QuadraturePoint(0.0349317947036/2,0.4903668903754,0.4903668903754),
+QuadraturePoint(0.0383664533945/2,0.0875134669581,0.8249730660837),
+QuadraturePoint(0.0383664533945/2,0.0875134669581,0.0875134669581),
+QuadraturePoint(0.0383664533945/2,0.8249730660837,0.0875134669581),
+QuadraturePoint(0.0578369491210/2,0.0935526036219,0.2079865423167),
+QuadraturePoint(0.0578369491210/2,0.0935526036219,0.6984608540613),
+QuadraturePoint(0.0578369491210/2,0.2079865423167,0.0935526036219),
+QuadraturePoint(0.0578369491210/2,0.6984608540613,0.0935526036219),
+QuadraturePoint(0.0578369491210/2,0.6984608540613,0.2079865423167),
+QuadraturePoint(0.0578369491210/2,0.2079865423167,0.6984608540613),
+QuadraturePoint(0.0725821687394/2,0.0974892983467,0.5380088595149),
+QuadraturePoint(0.0725821687394/2,0.3645018421383,0.0974892983467),
+QuadraturePoint(0.0725821687394/2,0.5380088595149,0.0974892983467),
+QuadraturePoint(0.0725821687394/2,0.5380088595149,0.3645018421383),
+QuadraturePoint(0.0725821687394/2,0.3645018421383,0.5380088595149),
+QuadraturePoint(0.0725821687394/2,0.0974892983467,0.3645018421383),
+QuadraturePoint(0.0897856524107/2,0.2217145894873,0.5565708210253),
+QuadraturePoint(0.0897856524107/2,0.5565708210253,0.2217145894873),
+QuadraturePoint(0.0897856524107/2,0.2217145894873,0.2217145894873),
+QuadraturePoint(0.1034544533617/2,0.3860471669296,0.2279056661408),
+QuadraturePoint(0.1034544533617/2,0.2279056661408,0.3860471669296),
+QuadraturePoint(0.1034544533617/2,0.3860471669296,0.3860471669296),
+};
+const QuadratureFormular QuadratureFormular_T_14(14 ,45,P_QuadratureFormular_T_14);
+
+
+static  QuadraturePoint P_QuadratureFormular_T_16[] = {
+QuadraturePoint(0.0006202599851/2,1.0000000000000,0.0000000000000),
+QuadraturePoint(0.0006315174712/2,0.0000000000000,1.0000000000000),
+QuadraturePoint(0.0007086601559/2,0.0000000000000,0.0000000000000),
+QuadraturePoint(0.0055163716168/2,0.9398863583577,0.0049848744634),
+QuadraturePoint(0.0062692407656/2,0.0543806683058,0.9386405618617),
+QuadraturePoint(0.0078531408826/2,0.0093940049164,0.0526424462697),
+QuadraturePoint(0.0094551483864/2,0.0164345086362,0.9469035517351),
+QuadraturePoint(0.0097824511271/2,0.9469487269862,0.0363373677167),
+QuadraturePoint(0.0099861643489/2,0.0426604005768,0.0151224541799),
+QuadraturePoint(0.0137553818816/2,0.0122269495439,0.8693773510664),
+QuadraturePoint(0.0140979178040/2,0.8673696521047,0.1204917285774),
+QuadraturePoint(0.0149646864337/2,0.8456744021389,0.0157763967870),
+QuadraturePoint(0.0156097503612/2,0.1395759632103,0.8448120870375),
+QuadraturePoint(0.0157683693348/2,0.1317821743231,0.0135009605584),
+QuadraturePoint(0.0175794546383/2,0.0157955126300,0.1455274938536),
+QuadraturePoint(0.0204113840270/2,0.7365462884436,0.0155697540908),
+QuadraturePoint(0.0209562878616/2,0.0139688430330,0.7379836894450),
+QuadraturePoint(0.0210713412998/2,0.2547895186039,0.7297615689771),
+QuadraturePoint(0.0217646760202/2,0.7316386522555,0.2543076683315),
+QuadraturePoint(0.0222288408699/2,0.0157253728951,0.2696239795791),
+QuadraturePoint(0.0224186693682/2,0.2662302843647,0.0144783956308),
+QuadraturePoint(0.0230122616993/2,0.8673504065214,0.0591679410400),
+QuadraturePoint(0.0236813902500/2,0.0741493666957,0.8634782575061),
+QuadraturePoint(0.0257464643368/2,0.0159285948360,0.4191238955238),
+QuadraturePoint(0.0257956801608/2,0.0156061028068,0.5809222921146),
+QuadraturePoint(0.0258072327610/2,0.5910094817484,0.0159251452651),
+QuadraturePoint(0.0260343232059/2,0.4034771496889,0.5806700368104),
+QuadraturePoint(0.0265768141609/2,0.5694745628526,0.4149495146302),
+QuadraturePoint(0.0265784761831/2,0.0678493700650,0.0761218678591),
+QuadraturePoint(0.0267532329238/2,0.4265968590272,0.0157509692312),
+QuadraturePoint(0.0375787806641/2,0.0670982507890,0.7741898312421),
+QuadraturePoint(0.0383065894195/2,0.7528310231480,0.0819119495639),
+QuadraturePoint(0.0384849695025/2,0.7753727783557,0.1577128457292),
+QuadraturePoint(0.0389619825852/2,0.1689073157787,0.7503943099742),
+QuadraturePoint(0.0394604111547/2,0.1687335832919,0.0708311507268),
+QuadraturePoint(0.0412364778098/2,0.0821244708436,0.1762996626771),
+QuadraturePoint(0.0512872438483/2,0.6288705363345,0.0807744953317),
+QuadraturePoint(0.0516405641935/2,0.0811413015266,0.3054373589776),
+QuadraturePoint(0.0518230042269/2,0.2969112065080,0.6227485988871),
+QuadraturePoint(0.0528527988181/2,0.0767542314171,0.6247247149546),
+QuadraturePoint(0.0538505573027/2,0.6223022333845,0.3011485821166),
+QuadraturePoint(0.0541895329319/2,0.3103786288051,0.0779098365079),
+QuadraturePoint(0.0584737146444/2,0.0819218215187,0.4603633038351),
+QuadraturePoint(0.0592863168363/2,0.4717022665013,0.0821554006797),
+QuadraturePoint(0.0594358276749/2,0.4546603415250,0.4637565033890),
+QuadraturePoint(0.0631800255863/2,0.1701091339237,0.6422277808188),
+QuadraturePoint(0.0632926845153/2,0.6406004329487,0.1898293537256),
+QuadraturePoint(0.0640707361772/2,0.1912267583717,0.1739955685343),
+QuadraturePoint(0.0812040595918/2,0.1885315767070,0.4798914070406),
+QuadraturePoint(0.0814437513530/2,0.4772929957691,0.3348356598119),
+QuadraturePoint(0.0814679201241/2,0.3126974621760,0.4957972197259),
+QuadraturePoint(0.0815050548084/2,0.4961225945946,0.1927553668904),
+QuadraturePoint(0.0815164664939/2,0.1928805312867,0.3161015807261),
+QuadraturePoint(0.0816931059623/2,0.3360041453816,0.1894892801290),
+QuadraturePoint(0.0923218334531/2,0.3337280550848,0.3343571021811),
+};
+const QuadratureFormular QuadratureFormular_T_16(16 ,55,P_QuadratureFormular_T_16);
+
+
+static QuadraturePoint P_QuadratureFormular_T_18[] = {
+QuadraturePoint(0.0025165756986/2,0.0116731059668,0.9812565951289),
+QuadraturePoint(0.0025273452007/2,0.9810030858388,0.0071462504863),
+QuadraturePoint(0.0033269295333/2,0.0106966317092,0.0115153933376),
+QuadraturePoint(0.0081503492125/2,0.9382476983551,0.0495570591341),
+QuadraturePoint(0.0086135525742/2,0.0126627518417,0.9370123620615),
+QuadraturePoint(0.0087786746179/2,0.0598109409984,0.0121364578922),
+QuadraturePoint(0.0097099585562/2,0.0137363297927,0.0612783625597),
+QuadraturePoint(0.0102466211915/2,0.9229527959405,0.0141128270602),
+QuadraturePoint(0.0108397688341/2,0.0633107354993,0.9220197291727),
+QuadraturePoint(0.0129385390176/2,0.0117265100335,0.1500520475229),
+QuadraturePoint(0.0136339823583/2,0.1554720587323,0.8325147121589),
+QuadraturePoint(0.0138477328147/2,0.8343293888982,0.0125228158759),
+QuadraturePoint(0.0139421540105/2,0.8501638031957,0.1371997508736),
+QuadraturePoint(0.0144121399968/2,0.0128816350522,0.8477627063479),
+QuadraturePoint(0.0153703455534/2,0.1510801608959,0.0136526924039),
+QuadraturePoint(0.0162489802253/2,0.0101917879217,0.5770438618345),
+QuadraturePoint(0.0169718304280/2,0.2813372399303,0.7066853759623),
+QuadraturePoint(0.0170088532421/2,0.7124374628501,0.0124569780990),
+QuadraturePoint(0.0170953520675/2,0.2763025250863,0.0121741311386),
+QuadraturePoint(0.0173888854559/2,0.0109658368561,0.4194306712466),
+QuadraturePoint(0.0174543962439/2,0.4289110517884,0.5599616067469),
+QuadraturePoint(0.0178406757287/2,0.4215420555115,0.0116475994785),
+QuadraturePoint(0.0178446863879/2,0.5711258590444,0.0118218313989),
+QuadraturePoint(0.0179046337552/2,0.5826868270511,0.4057889581177),
+QuadraturePoint(0.0181259756201/2,0.0130567806713,0.2725023750868),
+QuadraturePoint(0.0184784838882/2,0.0130760400964,0.7224712523233),
+QuadraturePoint(0.0185793564371/2,0.7263437062407,0.2602984019251),
+QuadraturePoint(0.0203217151777/2,0.0687230068637,0.0631417277210),
+QuadraturePoint(0.0213771661809/2,0.8652302101529,0.0720611837338),
+QuadraturePoint(0.0231916854098/2,0.0648599071037,0.8590433543910),
+QuadraturePoint(0.0274426710859/2,0.1483494943362,0.7888788352240),
+QuadraturePoint(0.0290301922340/2,0.0624359898396,0.1493935499354),
+QuadraturePoint(0.0294522738505/2,0.7871369011735,0.0656382042757),
+QuadraturePoint(0.0299436251629/2,0.0519104921610,0.5255635695605),
+QuadraturePoint(0.0307026948119/2,0.1543129927444,0.0716383926917),
+QuadraturePoint(0.0325263365863/2,0.2617842745603,0.0621479485288),
+QuadraturePoint(0.0327884208506/2,0.7667257872813,0.1658211554831),
+QuadraturePoint(0.0331234675192/2,0.2582103676627,0.6800119766139),
+QuadraturePoint(0.0346167526875/2,0.0679065925147,0.7571515437782),
+QuadraturePoint(0.0347081373976/2,0.5293578274804,0.4121503841107),
+QuadraturePoint(0.0347372049404/2,0.0666036150484,0.2612513087886),
+QuadraturePoint(0.0348528762454/2,0.0585675461899,0.3902236114535),
+QuadraturePoint(0.0348601561186/2,0.0644535360411,0.6373626559761),
+QuadraturePoint(0.0355471569975/2,0.6748138429151,0.0637583342061),
+QuadraturePoint(0.0360182996383/2,0.3914602310369,0.5503238090563),
+QuadraturePoint(0.0362926285843/2,0.6487701492307,0.2836728360263),
+QuadraturePoint(0.0381897702083/2,0.3946498220408,0.0605175522554),
+QuadraturePoint(0.0392252800118/2,0.5390137151933,0.0611990176936),
+QuadraturePoint(0.0482710125888/2,0.1627895082785,0.6861322141035),
+QuadraturePoint(0.0489912121566/2,0.6812436322641,0.1567968345899),
+QuadraturePoint(0.0497220833872/2,0.1542832878020,0.1667512624020),
+QuadraturePoint(0.0507065736986/2,0.2522727750445,0.2504803933395),
+QuadraturePoint(0.0509771994043/2,0.2547981532407,0.4994090649043),
+QuadraturePoint(0.0521360063667/2,0.1485580549194,0.5756023096087),
+QuadraturePoint(0.0523460874925/2,0.2930239606436,0.5656897354162),
+QuadraturePoint(0.0524440683552/2,0.2808991272310,0.1437921574248),
+QuadraturePoint(0.0527459644823/2,0.4820989592971,0.2518557535865),
+QuadraturePoint(0.0529449063728/2,0.5641878245444,0.1462966743153),
+QuadraturePoint(0.0542395594501/2,0.1307699644344,0.4489577586117),
+QuadraturePoint(0.0543470203419/2,0.1479692221948,0.3001174386829),
+QuadraturePoint(0.0547100548639/2,0.5638684222946,0.2813772089298),
+QuadraturePoint(0.0557288345913/2,0.4361157428790,0.4252053446420),
+QuadraturePoint(0.0577734264233/2,0.3603263935285,0.2599190004889),
+QuadraturePoint(0.0585393781623/2,0.4224188334674,0.1453238443303),
+QuadraturePoint(0.0609039250680/2,0.3719001833052,0.3780122703567),
+QuadraturePoint(0.0637273964449/2,0.2413645006928,0.3847563284940),
+};
+const QuadratureFormular QuadratureFormular_T_18(18 ,66,P_QuadratureFormular_T_18);
+
+
+static  QuadraturePoint P_QuadratureFormular_T_20[] = {
+QuadraturePoint(0.0021744545399/2,0.0089411337112,0.0086983293702),
+QuadraturePoint(0.0028987135265/2,0.9792622629807,0.0102644133744),
+QuadraturePoint(0.0030846029337/2,0.0105475382112,0.9785514202515),
+QuadraturePoint(0.0034401633104/2,0.0023777061947,0.0636551098604),
+QuadraturePoint(0.0041898472012/2,0.0630425115795,0.0041506347509),
+QuadraturePoint(0.0044738051498/2,0.9308422496730,0.0048053482263),
+QuadraturePoint(0.0047054420814/2,0.0629076555490,0.9316790069481),
+QuadraturePoint(0.0048867935750/2,0.9315962246381,0.0626264881801),
+QuadraturePoint(0.0051927643369/2,0.0061951689415,0.9293587058564),
+QuadraturePoint(0.0074073058981/2,0.0287125819237,0.0310202122997),
+QuadraturePoint(0.0079755410301/2,0.9293844478305,0.0342152968219),
+QuadraturePoint(0.0083550522910/2,0.0375457566621,0.9257868884669),
+QuadraturePoint(0.0096166660864/2,0.0086895739064,0.1584971251510),
+QuadraturePoint(0.0096318257850/2,0.1547597053965,0.8363606657688),
+QuadraturePoint(0.0098577460758/2,0.8331025294185,0.0089257244824),
+QuadraturePoint(0.0102657880301/2,0.8374231073526,0.1529167304078),
+QuadraturePoint(0.0103188103111/2,0.1559362505234,0.0094966240058),
+QuadraturePoint(0.0106291001630/2,0.0098599642095,0.8342211493596),
+QuadraturePoint(0.0106881306895/2,0.4055873733289,0.0074389302008),
+QuadraturePoint(0.0106969021010/2,0.5964727898618,0.3956330809311),
+QuadraturePoint(0.0109026461714/2,0.0080747800416,0.4031319425903),
+QuadraturePoint(0.0109899783575/2,0.0075073977721,0.5851609594681),
+QuadraturePoint(0.0113423055229/2,0.3936764519237,0.5974896592899),
+QuadraturePoint(0.0120535642930/2,0.5846530726212,0.0087250464968),
+QuadraturePoint(0.0139619193821/2,0.4870804112120,0.0202129229912),
+QuadraturePoint(0.0141147991536/2,0.2683512811785,0.7202340088668),
+QuadraturePoint(0.0141930347046/2,0.7223956288748,0.2662399366456),
+QuadraturePoint(0.0144212676268/2,0.2716826742357,0.0112882698808),
+QuadraturePoint(0.0144704346855/2,0.0112580842046,0.7169695963325),
+QuadraturePoint(0.0144949769872/2,0.0115034734370,0.2740067110166),
+QuadraturePoint(0.0145386775694/2,0.7140525900564,0.0113511560497),
+QuadraturePoint(0.0145964190926/2,0.4902871053112,0.4936491841468),
+QuadraturePoint(0.0147314578466/2,0.0201423425209,0.4832573459601),
+QuadraturePoint(0.0167463963304/2,0.0361107464859,0.0935679501582),
+QuadraturePoint(0.0168955500458/2,0.8607998819851,0.0397379067075),
+QuadraturePoint(0.0169422662884/2,0.1005891526001,0.8586343419352),
+QuadraturePoint(0.0173070172095/2,0.0918740717058,0.0395513001973),
+QuadraturePoint(0.0174524546493/2,0.8604888296191,0.0966224057079),
+QuadraturePoint(0.0177217222159/2,0.0439842178673,0.8561886349107),
+QuadraturePoint(0.0282824024023/2,0.2011017606735,0.7449115835626),
+QuadraturePoint(0.0284996712488/2,0.7449993726263,0.0536865638166),
+QuadraturePoint(0.0285005646539/2,0.0532186641310,0.1963754275935),
+QuadraturePoint(0.0300647223478/2,0.7453984647401,0.1982065805550),
+QuadraturePoint(0.0302031277082/2,0.1957289932876,0.0555713833156),
+QuadraturePoint(0.0303987136077/2,0.1092532057988,0.6100036182413),
+QuadraturePoint(0.0305668796074/2,0.0567625702001,0.7409121894959),
+QuadraturePoint(0.0306067413002/2,0.0483837933475,0.6075135660978),
+QuadraturePoint(0.0309330068201/2,0.1080612809760,0.1122081510437),
+QuadraturePoint(0.0309773820835/2,0.6185605900991,0.2698753703035),
+QuadraturePoint(0.0313146250545/2,0.7721296013497,0.1114117395333),
+QuadraturePoint(0.0313573493392/2,0.6115734801133,0.3389367677931),
+QuadraturePoint(0.0314320469287/2,0.3381326103376,0.0494693938787),
+QuadraturePoint(0.0315182143894/2,0.1173084128254,0.7696451309795),
+QuadraturePoint(0.0324248137985/2,0.2674551260596,0.1115718808154),
+QuadraturePoint(0.0347512152386/2,0.6542100160026,0.1906548314700),
+QuadraturePoint(0.0350393454927/2,0.0538297481158,0.3358616826849),
+QuadraturePoint(0.0350717420310/2,0.1848840324117,0.1551831523851),
+QuadraturePoint(0.0352129215334/2,0.3376267104744,0.6081402596294),
+QuadraturePoint(0.0352615504981/2,0.6067102034499,0.0542632795598),
+QuadraturePoint(0.0366403220343/2,0.4612614085496,0.0688176670722),
+QuadraturePoint(0.0367733107670/2,0.1525465365671,0.6510240845749),
+QuadraturePoint(0.0371675662937/2,0.0700582543543,0.4661904392742),
+QuadraturePoint(0.0373371571606/2,0.4704201379032,0.4634826455353),
+QuadraturePoint(0.0403973346588/2,0.1216461693746,0.2381494875516),
+QuadraturePoint(0.0413580040638/2,0.6371404052702,0.1238399384513),
+QuadraturePoint(0.0421957791870/2,0.2379904515119,0.6370216452326),
+QuadraturePoint(0.0495451004037/2,0.1483929857177,0.4894188577780),
+QuadraturePoint(0.0500419261141/2,0.3598069571550,0.1452880866253),
+QuadraturePoint(0.0505794587115/2,0.4941441055095,0.3610216383818),
+QuadraturePoint(0.0520037210188/2,0.1440630687981,0.3513508341887),
+QuadraturePoint(0.0521533567886/2,0.5019764440004,0.1435491663293),
+QuadraturePoint(0.0524899152358/2,0.3555423834298,0.5016491599502),
+QuadraturePoint(0.0599159762516/2,0.2443439540771,0.2406052129104),
+QuadraturePoint(0.0599609997426/2,0.2437064989342,0.5109017277055),
+QuadraturePoint(0.0599915272129/2,0.5122200807321,0.2452737973543),
+QuadraturePoint(0.0634133183449/2,0.2526038315178,0.3700319555094),
+QuadraturePoint(0.0635311861108/2,0.3759895652851,0.2505406611631),
+QuadraturePoint(0.0637206605672/2,0.3729077987144,0.3753750277549),
+};
+const QuadratureFormular QuadratureFormular_T_20(20 ,78,P_QuadratureFormular_T_20);
+
+
+static  QuadraturePoint P_QuadratureFormular_T_21[] = {
+QuadraturePoint(0.0006704436439/2,0.0035524391922,0.0035524391922),
+QuadraturePoint(0.0006704436439/2,0.0035524391922,0.9928951216156),
+QuadraturePoint(0.0006704436439/2,0.9928951216156,0.0035524391922),
+QuadraturePoint(0.0045472608074/2,0.9553548273730,0.0087898929093),
+QuadraturePoint(0.0045472608074/2,0.0358552797177,0.0087898929093),
+QuadraturePoint(0.0045472608074/2,0.9553548273730,0.0358552797177),
+QuadraturePoint(0.0045472608074/2,0.0087898929093,0.0358552797177),
+QuadraturePoint(0.0045472608074/2,0.0087898929093,0.9553548273730),
+QuadraturePoint(0.0045472608074/2,0.0358552797177,0.9553548273730),
+QuadraturePoint(0.0052077585320/2,0.8865264879047,0.1082329745017),
+QuadraturePoint(0.0052077585320/2,0.8865264879047,0.0052405375935),
+QuadraturePoint(0.0052077585320/2,0.0052405375935,0.1082329745017),
+QuadraturePoint(0.0052077585320/2,0.0052405375935,0.8865264879047),
+QuadraturePoint(0.0052077585320/2,0.1082329745017,0.8865264879047),
+QuadraturePoint(0.0052077585320/2,0.1082329745017,0.0052405375935),
+QuadraturePoint(0.0065435432887/2,0.0466397432150,0.9067205135700),
+QuadraturePoint(0.0065435432887/2,0.0466397432150,0.0466397432150),
+QuadraturePoint(0.0065435432887/2,0.9067205135700,0.0466397432150),
+QuadraturePoint(0.0092737841533/2,0.2075720456946,0.0082759241284),
+QuadraturePoint(0.0092737841533/2,0.2075720456946,0.7841520301770),
+QuadraturePoint(0.0092737841533/2,0.7841520301770,0.2075720456946),
+QuadraturePoint(0.0092737841533/2,0.0082759241284,0.7841520301770),
+QuadraturePoint(0.0092737841533/2,0.0082759241284,0.2075720456946),
+QuadraturePoint(0.0092737841533/2,0.7841520301770,0.0082759241284),
+QuadraturePoint(0.0095937782623/2,0.0858119489725,0.0314836947701),
+QuadraturePoint(0.0095937782623/2,0.8827043562574,0.0314836947701),
+QuadraturePoint(0.0095937782623/2,0.0314836947701,0.0858119489725),
+QuadraturePoint(0.0095937782623/2,0.0858119489725,0.8827043562574),
+QuadraturePoint(0.0095937782623/2,0.8827043562574,0.0858119489725),
+QuadraturePoint(0.0095937782623/2,0.0314836947701,0.8827043562574),
+QuadraturePoint(0.0114247809167/2,0.6688778233826,0.0095150760625),
+QuadraturePoint(0.0114247809167/2,0.0095150760625,0.3216071005550),
+QuadraturePoint(0.0114247809167/2,0.0095150760625,0.6688778233826),
+QuadraturePoint(0.0114247809167/2,0.6688778233826,0.3216071005550),
+QuadraturePoint(0.0114247809167/2,0.3216071005550,0.6688778233826),
+QuadraturePoint(0.0114247809167/2,0.3216071005550,0.0095150760625),
+QuadraturePoint(0.0117216964174/2,0.4379999543113,0.0099859785681),
+QuadraturePoint(0.0117216964174/2,0.0099859785681,0.5520140671206),
+QuadraturePoint(0.0117216964174/2,0.4379999543113,0.5520140671206),
+QuadraturePoint(0.0117216964174/2,0.0099859785681,0.4379999543113),
+QuadraturePoint(0.0117216964174/2,0.5520140671206,0.4379999543113),
+QuadraturePoint(0.0117216964174/2,0.5520140671206,0.0099859785681),
+QuadraturePoint(0.0188197155232/2,0.7974931072148,0.0405093994119),
+QuadraturePoint(0.0188197155232/2,0.0405093994119,0.1619974933734),
+QuadraturePoint(0.0188197155232/2,0.0405093994119,0.7974931072148),
+QuadraturePoint(0.0188197155232/2,0.1619974933734,0.7974931072148),
+QuadraturePoint(0.0188197155232/2,0.7974931072148,0.1619974933734),
+QuadraturePoint(0.0188197155232/2,0.1619974933734,0.0405093994119),
+QuadraturePoint(0.0235260980271/2,0.3864215551955,0.3864215551955),
+QuadraturePoint(0.0235260980271/2,0.3864215551955,0.2271568896090),
+QuadraturePoint(0.0235260980271/2,0.2271568896090,0.3864215551955),
+QuadraturePoint(0.0235571466151/2,0.8090129379329,0.0954935310336),
+QuadraturePoint(0.0235571466151/2,0.0954935310336,0.8090129379329),
+QuadraturePoint(0.0235571466151/2,0.0954935310336,0.0954935310336),
+QuadraturePoint(0.0268246207430/2,0.2745425238718,0.0479840480721),
+QuadraturePoint(0.0268246207430/2,0.0479840480721,0.6774734280561),
+QuadraturePoint(0.0268246207430/2,0.6774734280561,0.0479840480721),
+QuadraturePoint(0.0268246207430/2,0.6774734280561,0.2745425238718),
+QuadraturePoint(0.0268246207430/2,0.2745425238718,0.6774734280561),
+QuadraturePoint(0.0268246207430/2,0.0479840480721,0.2745425238718),
+QuadraturePoint(0.0314289776779/2,0.4053472446667,0.5429849622344),
+QuadraturePoint(0.0314289776779/2,0.0516677930989,0.4053472446667),
+QuadraturePoint(0.0314289776779/2,0.4053472446667,0.0516677930989),
+QuadraturePoint(0.0314289776779/2,0.5429849622344,0.0516677930989),
+QuadraturePoint(0.0314289776779/2,0.0516677930989,0.5429849622344),
+QuadraturePoint(0.0314289776779/2,0.5429849622344,0.4053472446667),
+QuadraturePoint(0.0337196192159/2,0.1877738615539,0.1068148267588),
+QuadraturePoint(0.0337196192159/2,0.7054113116872,0.1877738615539),
+QuadraturePoint(0.0337196192159/2,0.7054113116872,0.1068148267588),
+QuadraturePoint(0.0337196192159/2,0.1068148267588,0.7054113116872),
+QuadraturePoint(0.0337196192159/2,0.1877738615539,0.7054113116872),
+QuadraturePoint(0.0337196192159/2,0.1068148267588,0.1877738615539),
+QuadraturePoint(0.0427745294213/2,0.1195059712009,0.3057122990643),
+QuadraturePoint(0.0427745294213/2,0.1195059712009,0.5747817297348),
+QuadraturePoint(0.0427745294213/2,0.5747817297348,0.1195059712009),
+QuadraturePoint(0.0427745294213/2,0.5747817297348,0.3057122990643),
+QuadraturePoint(0.0427745294213/2,0.3057122990643,0.5747817297348),
+QuadraturePoint(0.0427745294213/2,0.3057122990643,0.1195059712009),
+QuadraturePoint(0.0441138932737/2,0.5981245743363,0.2009377128319),
+QuadraturePoint(0.0441138932737/2,0.2009377128319,0.5981245743363),
+QuadraturePoint(0.0441138932737/2,0.2009377128319,0.2009377128319),
+QuadraturePoint(0.0461469594684/2,0.2160775200005,0.3121360256673),
+QuadraturePoint(0.0461469594684/2,0.3121360256673,0.2160775200005),
+QuadraturePoint(0.0461469594684/2,0.2160775200005,0.4717864543321),
+QuadraturePoint(0.0461469594684/2,0.3121360256673,0.4717864543321),
+QuadraturePoint(0.0461469594684/2,0.4717864543321,0.3121360256673),
+QuadraturePoint(0.0461469594684/2,0.4717864543321,0.2160775200005),
+QuadraturePoint(0.0469152468624/2,0.4376579903849,0.4376579903849),
+QuadraturePoint(0.0469152468624/2,0.4376579903849,0.1246840192303),
+QuadraturePoint(0.0469152468624/2,0.1246840192303,0.4376579903849),
+QuadraturePoint(0.0551199980347/2,0.3333333333333,0.3333333333333),
+};
+const QuadratureFormular QuadratureFormular_T_21(21 ,91,P_QuadratureFormular_T_21);
+
+
+static  QuadraturePoint P_QuadratureFormular_T_23[] = {
+QuadraturePoint(0.0006438298261/2,0.0087809303836,0.9903676436772),
+QuadraturePoint(0.0006438413076/2,0.9903675314220,0.0087809216232),
+QuadraturePoint(0.0010134735710/2,0.0027029276450,0.0335914404439),
+QuadraturePoint(0.0010134752576/2,0.0335909214524,0.0027028946710),
+QuadraturePoint(0.0019679929935/2,0.0091675068606,0.0091676353051),
+QuadraturePoint(0.0033467313784/2,0.9675568182558,0.0084737176656),
+QuadraturePoint(0.0033467339208/2,0.0084737200688,0.9675569435345),
+QuadraturePoint(0.0042873323375/2,0.0078781948792,0.0676784943862),
+QuadraturePoint(0.0042873459885/2,0.0676785477700,0.0078781659291),
+QuadraturePoint(0.0043003801372/2,0.9470266955047,0.0442974541187),
+QuadraturePoint(0.0043003849098/2,0.0442974755680,0.9470266676487),
+QuadraturePoint(0.0056934629205/2,0.9144243214882,0.0081735455132),
+QuadraturePoint(0.0056934640134/2,0.0081735424459,0.9144244234031),
+QuadraturePoint(0.0061643868015/2,0.2497452292741,0.3833232434720),
+QuadraturePoint(0.0061644756418/2,0.3833232646055,0.2497451268005),
+QuadraturePoint(0.0062014513591/2,0.8876850353557,0.1035328809446),
+QuadraturePoint(0.0062014531952/2,0.1035329228297,0.8876849931840),
+QuadraturePoint(0.0069636330294/2,0.0077255923618,0.1403190991974),
+QuadraturePoint(0.0069636331842/2,0.1403192425107,0.0077255934624),
+QuadraturePoint(0.0075066257720/2,0.8104591009652,0.1809642523926),
+QuadraturePoint(0.0075066264565/2,0.1809643003717,0.8104590515334),
+QuadraturePoint(0.0079074768339/2,0.8330767948684,0.0083010939677),
+QuadraturePoint(0.0079074772485/2,0.0083010907126,0.8330768545392),
+QuadraturePoint(0.0080353344623/2,0.0348407706147,0.0348406969482),
+QuadraturePoint(0.0087963441074/2,0.2740287679608,0.7173981847948),
+QuadraturePoint(0.0087963448112/2,0.7173982224778,0.2740287304386),
+QuadraturePoint(0.0091304195716/2,0.2394976858234,0.0081859182262),
+QuadraturePoint(0.0091304213611/2,0.0081859185845,0.2394975566677),
+QuadraturePoint(0.0092821748751/2,0.0068836152075,0.4843740892687),
+QuadraturePoint(0.0092821815662/2,0.4843741485699,0.0068836232949),
+QuadraturePoint(0.0094499806178/2,0.4960767772741,0.4960767529507),
+QuadraturePoint(0.0094627468484/2,0.6112936776245,0.3804323691239),
+QuadraturePoint(0.0094627485294/2,0.3804323980345,0.6112936466533),
+QuadraturePoint(0.0095555772285/2,0.7303890713524,0.0083987179701),
+QuadraturePoint(0.0095555792843/2,0.0083987168639,0.7303890895407),
+QuadraturePoint(0.0096138842488/2,0.6128525675612,0.0075475979695),
+QuadraturePoint(0.0096138846826/2,0.0075475961037,0.6128525484582),
+QuadraturePoint(0.0099991524212/2,0.0079525316513,0.3559773826721),
+QuadraturePoint(0.0099991551850/2,0.3559774870460,0.0079525358502),
+QuadraturePoint(0.0100301319277/2,0.9110236977966,0.0437233665345),
+QuadraturePoint(0.0100301346636/2,0.0437233605166,0.9110236807446),
+QuadraturePoint(0.0124936676185/2,0.0388480061835,0.0967030908282),
+QuadraturePoint(0.0124936726125/2,0.0967032117936,0.0388479942386),
+QuadraturePoint(0.0140197309137/2,0.0873226911312,0.0873226620391),
+QuadraturePoint(0.0143336216896/2,0.0421445202084,0.8485617789108),
+QuadraturePoint(0.0143336272125/2,0.8485617974961,0.0421445420915),
+QuadraturePoint(0.0153604142740/2,0.8477921333864,0.1067435942472),
+QuadraturePoint(0.0153604183425/2,0.1067435889398,0.8477921328146),
+QuadraturePoint(0.0184523825614/2,0.1833966521991,0.0416340521608),
+QuadraturePoint(0.0184523863146/2,0.0416340541167,0.1833965196930),
+QuadraturePoint(0.0195833983573/2,0.7611632251560,0.1941599202852),
+QuadraturePoint(0.0195834019994/2,0.1941599254144,0.7611632153938),
+QuadraturePoint(0.0197632751342/2,0.7579378747173,0.0439826608586),
+QuadraturePoint(0.0197632766677/2,0.0439826512395,0.7579378242308),
+QuadraturePoint(0.0198806391019/2,0.0369760535918,0.5363186076436),
+QuadraturePoint(0.0198806485776/2,0.5363187134342,0.0369760780935),
+QuadraturePoint(0.0207181838484/2,0.1001256948921,0.7912267093545),
+QuadraturePoint(0.0207181934893/2,0.7912266693524,0.1001257554673),
+QuadraturePoint(0.0208943071440/2,0.0379866714177,0.4157413128558),
+QuadraturePoint(0.0208943251956/2,0.4157414028965,0.0379867061535),
+QuadraturePoint(0.0214864573885/2,0.6507106491463,0.0420141226713),
+QuadraturePoint(0.0214864586007/2,0.0420141133438,0.6507105645084),
+QuadraturePoint(0.0222218133036/2,0.0425548444254,0.2920626023484),
+QuadraturePoint(0.0222218160203/2,0.2920627107240,0.0425548546753),
+QuadraturePoint(0.0223345305455/2,0.5389729538180,0.4193031469005),
+QuadraturePoint(0.0223345378739/2,0.4193031828489,0.5389729093610),
+QuadraturePoint(0.0224758924946/2,0.6549472009700,0.3007352636162),
+QuadraturePoint(0.0224758980440/2,0.3007352790917,0.6549471812731),
+QuadraturePoint(0.0229701395845/2,0.3752400771585,0.3453980130752),
+QuadraturePoint(0.0229703394438/2,0.3453980282786,0.3752400695673),
+QuadraturePoint(0.0232798376102/2,0.0994532168761,0.1598308695187),
+QuadraturePoint(0.0232798427506/2,0.1598309359585,0.0994531960132),
+QuadraturePoint(0.0269483199647/2,0.1797326661667,0.7124585430924),
+QuadraturePoint(0.0269483307107/2,0.7124584461943,0.1797327722240),
+QuadraturePoint(0.0280438758010/2,0.1066065678636,0.7001701784175),
+QuadraturePoint(0.0280438764607/2,0.7001701904096,0.1066065855677),
+QuadraturePoint(0.0287526270172/2,0.0993303629801,0.6065647984796),
+QuadraturePoint(0.0287526387271/2,0.6065648052521,0.0993303896769),
+QuadraturePoint(0.0298980829063/2,0.1023223542704,0.2533381579528),
+QuadraturePoint(0.0298980922759/2,0.2533382324938,0.1023223826189),
+QuadraturePoint(0.0309004358516/2,0.6166226715217,0.2769502060575),
+QuadraturePoint(0.0309004385956/2,0.2769500693109,0.6166227900624),
+QuadraturePoint(0.0314031017088/2,0.0904184571873,0.4981522637001),
+QuadraturePoint(0.0314031073955/2,0.4981522767248,0.0904185045149),
+QuadraturePoint(0.0319191553024/2,0.0928231860168,0.3738418516908),
+QuadraturePoint(0.0319191668378/2,0.3738418699229,0.0928232584790),
+QuadraturePoint(0.0321429924062/2,0.2521678840407,0.2521680925697),
+QuadraturePoint(0.0330395601388/2,0.5087500218708,0.3905580544330),
+QuadraturePoint(0.0330395631829/2,0.3905579116731,0.5087501437661),
+QuadraturePoint(0.0356169095589/2,0.1706141469096,0.5266738039554),
+QuadraturePoint(0.0356169276054/2,0.5266737761312,0.1706142257537),
+QuadraturePoint(0.0365741189998/2,0.3487581527629,0.2588055084886),
+QuadraturePoint(0.0365741515204/2,0.2588053596017,0.3487583491703),
+QuadraturePoint(0.0365977646990/2,0.1696614558053,0.3013522183964),
+QuadraturePoint(0.0365978053889/2,0.3013521806875,0.1696615963219),
+QuadraturePoint(0.0369945680114/2,0.2580202409759,0.4584741774478),
+QuadraturePoint(0.0369945775059/2,0.4584740860198,0.2580203819011),
+QuadraturePoint(0.0374053623787/2,0.1848898683498,0.1848898704551),
+QuadraturePoint(0.0375550258317/2,0.6130740338465,0.1921611994069),
+QuadraturePoint(0.0375550312530/2,0.1921611750994,0.6130740398389),
+QuadraturePoint(0.0388887693486/2,0.4180541160599,0.1650613336416),
+QuadraturePoint(0.0388887708342/2,0.1650612642036,0.4180541199244),
+QuadraturePoint(0.0392705643548/2,0.5159205739625,0.2982719005229),
+QuadraturePoint(0.0392705802517/2,0.2982718935750,0.5159205534362),
+QuadraturePoint(0.0398766879831/2,0.4098894602340,0.4098894317792),
+};
+const QuadratureFormular QuadratureFormular_T_23(23 ,105,P_QuadratureFormular_T_23);
+
+
+static  QuadraturePoint P_QuadratureFormular_T_25[] = {
+QuadraturePoint(0.0014873417859/2,0.0082881595033,0.9848202768869),
+QuadraturePoint(0.0014889035262/2,0.4618422030241,0.5381577969759),
+QuadraturePoint(0.0015005944380/2,0.0071066441239,0.0080842361390),
+QuadraturePoint(0.0015059208313/2,0.9847613141699,0.0070015755134),
+QuadraturePoint(0.0015318868715/2,0.5374447869049,0.4625552130951),
+QuadraturePoint(0.0023032634487/2,0.0000000000000,0.4887676880140),
+QuadraturePoint(0.0023649067042/2,0.4914131929361,0.0000000000000),
+QuadraturePoint(0.0028751143611/2,0.0070345937020,0.9574158053697),
+QuadraturePoint(0.0029862488735/2,0.9564734714228,0.0364655449485),
+QuadraturePoint(0.0030384162737/2,0.0370198792045,0.0070908577166),
+QuadraturePoint(0.0032092459688/2,0.1024124542747,0.8936125594937),
+QuadraturePoint(0.0037029598435/2,0.5928065811509,0.0049451705600),
+QuadraturePoint(0.0037407186035/2,0.0050948422371,0.0996676659189),
+QuadraturePoint(0.0038452543223/2,0.0081562023689,0.0415561148784),
+QuadraturePoint(0.0038670778668/2,0.0424936107568,0.9494865260352),
+QuadraturePoint(0.0039192555178/2,0.9495543500844,0.0081794507292),
+QuadraturePoint(0.0039573282688/2,0.8932787471239,0.0053224326262),
+QuadraturePoint(0.0044032251724/2,0.0069317612927,0.9065401020433),
+QuadraturePoint(0.0045907108173/2,0.9035839030665,0.0894771171077),
+QuadraturePoint(0.0047023669435/2,0.0905665738209,0.0070525342005),
+QuadraturePoint(0.0050014843818/2,0.0083929332787,0.6663179931111),
+QuadraturePoint(0.0052387830156/2,0.6261245686071,0.0092197583153),
+QuadraturePoint(0.0054422104092/2,0.0062801592979,0.8335207460527),
+QuadraturePoint(0.0056931248912/2,0.8272539257367,0.1665134939330),
+QuadraturePoint(0.0059107422989/2,0.0062005875353,0.7424693255229),
+QuadraturePoint(0.0059687967687/2,0.1676900311185,0.0065717743528),
+QuadraturePoint(0.0067262190287/2,0.7199353069567,0.0064354534962),
+QuadraturePoint(0.0068307848624/2,0.2749740090237,0.7185296120719),
+QuadraturePoint(0.0069531259112/2,0.0079257582005,0.1766411374714),
+QuadraturePoint(0.0072460270642/2,0.0069981220752,0.2704767254004),
+QuadraturePoint(0.0072728189613/2,0.8125248773263,0.0082299533210),
+QuadraturePoint(0.0073008930847/2,0.0073536969970,0.5934167875453),
+QuadraturePoint(0.0073604666776/2,0.7283665935411,0.2648817553752),
+QuadraturePoint(0.0074119923255/2,0.1800642304565,0.8115848976682),
+QuadraturePoint(0.0074892214336/2,0.2658102467762,0.0068553525429),
+QuadraturePoint(0.0078604067260/2,0.0070892364520,0.3757632659744),
+QuadraturePoint(0.0078621726423/2,0.3774054302043,0.6148573533757),
+QuadraturePoint(0.0080506361066/2,0.0369649608668,0.9210792302893),
+QuadraturePoint(0.0081442860473/2,0.9203194109805,0.0426025082114),
+QuadraturePoint(0.0081478804152/2,0.0425477806431,0.0372689941794),
+QuadraturePoint(0.0092444146612/2,0.6191278394983,0.3724055713809),
+QuadraturePoint(0.0094674635165/2,0.3762697209178,0.0081436422011),
+QuadraturePoint(0.0097132210137/2,0.0956111149690,0.8771098372601),
+QuadraturePoint(0.0099753581151/2,0.0302473410377,0.0943858903393),
+QuadraturePoint(0.0103367803673/2,0.8739905691754,0.0313198990883),
+QuadraturePoint(0.0112263277166/2,0.8604133734958,0.1049019782046),
+QuadraturePoint(0.0114309118745/2,0.0347307852352,0.8609856462886),
+QuadraturePoint(0.0115550567487/2,0.1043606608343,0.0357152881004),
+QuadraturePoint(0.0135575856957/2,0.7797622824754,0.1872318199265),
+QuadraturePoint(0.0135984962900/2,0.0185865164256,0.4834397678794),
+QuadraturePoint(0.0137754813837/2,0.0324585286618,0.7783474916042),
+QuadraturePoint(0.0137961015942/2,0.8371293901157,0.0804060570156),
+QuadraturePoint(0.0138408839904/2,0.0836602075315,0.8421414817051),
+QuadraturePoint(0.0140634019977/2,0.0784070242501,0.0849927089145),
+QuadraturePoint(0.0140991451009/2,0.4929238648458,0.4892855914710),
+QuadraturePoint(0.0142004111991/2,0.1870637584073,0.0345210858281),
+QuadraturePoint(0.0144518424517/2,0.4892636967025,0.0190774755077),
+QuadraturePoint(0.0150245979639/2,0.0401982618372,0.1691143187109),
+QuadraturePoint(0.0152817804122/2,0.7894259278865,0.0412206731484),
+QuadraturePoint(0.0155550724169/2,0.1686260456429,0.7894860640585),
+QuadraturePoint(0.0164570886000/2,0.3750901913174,0.5895318272013),
+QuadraturePoint(0.0165275759573/2,0.0356362876880,0.3681256217699),
+QuadraturePoint(0.0166847554451/2,0.5887548164804,0.0359968962541),
+QuadraturePoint(0.0167409312985/2,0.0373308082182,0.6790704673533),
+QuadraturePoint(0.0168674663361/2,0.2820769993374,0.0373639992361),
+QuadraturePoint(0.0168882230165/2,0.6819277603320,0.2803330345725),
+QuadraturePoint(0.0172087112691/2,0.0374938324382,0.2634016180014),
+QuadraturePoint(0.0174681068264/2,0.6984079204127,0.0364154673322),
+QuadraturePoint(0.0176663899614/2,0.2654390894079,0.6980717436193),
+QuadraturePoint(0.0182967621475/2,0.1429848440800,0.7612254618453),
+QuadraturePoint(0.0183576852459/2,0.7623554007647,0.0943741220275),
+QuadraturePoint(0.0186392569521/2,0.0934222022749,0.1479799836832),
+QuadraturePoint(0.0189781060590/2,0.5759004479923,0.3821329641698),
+QuadraturePoint(0.0191847922578/2,0.3822427332525,0.0426716362301),
+QuadraturePoint(0.0194080442044/2,0.0411414081675,0.5718082874432),
+QuadraturePoint(0.0194720072193/2,0.0802462538379,0.7702204382042),
+QuadraturePoint(0.0200855080495/2,0.7625229819410,0.1559420577362),
+QuadraturePoint(0.0201673909332/2,0.1524941445131,0.0842965421322),
+QuadraturePoint(0.0221742162761/2,0.0622159195833,0.4538181318873),
+QuadraturePoint(0.0229702440508/2,0.1109539036076,0.4586014071171),
+QuadraturePoint(0.0233465117399/2,0.4575627212057,0.4795313560210),
+QuadraturePoint(0.0234883135338/2,0.4322865136374,0.1230591237472),
+QuadraturePoint(0.0240682099018/2,0.5865002850241,0.0834119779793),
+QuadraturePoint(0.0240910792953/2,0.0869359250818,0.6755677013351),
+QuadraturePoint(0.0245677049481/2,0.0929594906936,0.2326500892727),
+QuadraturePoint(0.0246536315719/2,0.6661932141454,0.2448294007406),
+QuadraturePoint(0.0246756530052/2,0.4780306362227,0.0661749044835),
+QuadraturePoint(0.0249704602710/2,0.4372215294577,0.4442145585244),
+QuadraturePoint(0.0250026544082/2,0.6779224504669,0.0929096534577),
+QuadraturePoint(0.0250490869426/2,0.2423431255660,0.0889793655129),
+QuadraturePoint(0.0250936250125/2,0.2288925420305,0.6780053081672),
+QuadraturePoint(0.0251482076226/2,0.3315065049959,0.5847381559741),
+QuadraturePoint(0.0255010290447/2,0.3424200526607,0.5139245722736),
+QuadraturePoint(0.0256544511979/2,0.0862630046475,0.3340976249234),
+QuadraturePoint(0.0257974750630/2,0.5113188946635,0.1380154720554),
+QuadraturePoint(0.0270007753993/2,0.1538977841001,0.6788062619562),
+QuadraturePoint(0.0274431536844/2,0.6779951348472,0.1663358925269),
+QuadraturePoint(0.0277072401488/2,0.1664600469411,0.1582214504849),
+QuadraturePoint(0.0278284415364/2,0.0950910318888,0.5666590332543),
+QuadraturePoint(0.0287207381105/2,0.3436048136712,0.0978960873457),
+QuadraturePoint(0.0288826834956/2,0.5560417025366,0.3468917820947),
+QuadraturePoint(0.0293302729759/2,0.1452404029513,0.3599534491052),
+QuadraturePoint(0.0318902879557/2,0.1619685156238,0.5810131373330),
+QuadraturePoint(0.0319083660286/2,0.5800164844262,0.2560674640672),
+QuadraturePoint(0.0320938960329/2,0.2450201223288,0.5881469552102),
+QuadraturePoint(0.0321618608780/2,0.2557621891794,0.1652244065047),
+QuadraturePoint(0.0322424127534/2,0.2205239985511,0.3496507466106),
+QuadraturePoint(0.0327072446421/2,0.4940183111285,0.2549448448453),
+QuadraturePoint(0.0329946316695/2,0.2531570689798,0.2543369115017),
+QuadraturePoint(0.0331828096025/2,0.5846891116357,0.1666603916479),
+QuadraturePoint(0.0334857162651/2,0.1660333602278,0.2523240191705),
+QuadraturePoint(0.0335468472792/2,0.2505426292461,0.4959007627528),
+QuadraturePoint(0.0337049042988/2,0.3519336802182,0.1805380367800),
+QuadraturePoint(0.0340361462767/2,0.3502668835419,0.4358582329881),
+QuadraturePoint(0.0342465235323/2,0.4400892485512,0.2120576104941),
+QuadraturePoint(0.0345528817251/2,0.4680855471546,0.3552681570774),
+QuadraturePoint(0.0356782875703/2,0.1770237763947,0.4670352922266),
+QuadraturePoint(0.0364656225016/2,0.3900920779501,0.3323152819300),
+QuadraturePoint(0.0365172708706/2,0.2805847774120,0.3898041176680),
+QuadraturePoint(0.0371924811018/2,0.3361523347440,0.2778500044356),
+};
+const QuadratureFormular QuadratureFormular_T_25(25 ,120,P_QuadratureFormular_T_25);
+
+
+template<class Rd>
+const GQuadratureFormular<Rd> * BuilQFd(const long & nex,const KNM_<double> & qf) {
+  ffassert( qf.M()== Rd::d+1) ;
+  int np = qf.N(); 
+  GQuadraturePoint<Rd> *pq= new GQuadraturePoint<Rd>[np];
+  for(int i=0;i<np;++i)
+    {
+      pq[i].a = qf(i,0);
+      for(int j=0;j<Rd::d;++j)
+	pq[i][j]=qf(i,j+1);
+      // cout << i << " " << pq[i].a << " " << (const Rd&)  pq[i] << " " << qf(':',i) << endl;
+    }
+  return new GQuadratureFormular<Rd>(nex,np,pq,true) ;
+} 
+
+template<typename T > T* CCopy(T * pr,T  p)
+{
+  *pr = p;
+  return pr; 
+}
+ 
+
+template<class Rd>
+const GQuadratureFormular<Rd> ** pBuilQFd(const GQuadratureFormular<Rd> ** const & pr,const long & nex,const KNM_<double> & qf) 
+{
+  // cout << "pBuilQFd " << pr << " " << *pr << endl; 
+  ffassert(pr );
+  *pr = BuilQFd<Rd>(nex,qf);
+  return pr; 
+}
+
+ 
+
+// to add new FreeFem++ type ... 
+
+#include "lex.hpp"
+extern  mylex *zzzfff;
+
+static void Load_Init(){
+  /*
+grep QuadratureFormular QF.cpp|grep ^const|awk -F"[_(]" '{print "Global.New(@qf" $3 "pT@,CConstant<const QuadratureFormular *>(&QuadratureFormular_T_"$3"));"}'|sed -e 's/@/"/g'
+   */
+	     Global.New("qf11pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_11));
+	     Global.New("qf13pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_13));
+	     Global.New("qf14pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_14));
+	     Global.New("qf16pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_16));
+	     Global.New("qf18pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_18));
+	     Global.New("qf20pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_20));
+	     Global.New("qf21pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_21));
+	     Global.New("qf23pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_23));
+	     Global.New("qf25pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_25));
+	     Global.New("qf11pE",CConstant<const QuadratureFormular1d *>(new QuadratureFormular1d(-1+2*11,11,GaussLegendre(11),true)));
+	     Global.New("qf12pE",CConstant<const QuadratureFormular1d *>(new QuadratureFormular1d(-1+2*12,12,GaussLegendre(12),true)));
+	     Global.New("qf13pE",CConstant<const QuadratureFormular1d *>(new QuadratureFormular1d(-1+2*13,13,GaussLegendre(13),true)));
+
+	     Global.Add("QF1d","(",new OneOperator2_<const GQuadratureFormular<R1> *,long,KNM_<double> >(BuilQFd<R1>));
+	     Global.Add("QF2d","(",new OneOperator2_<const GQuadratureFormular<R2> *,long,KNM_<double> >(BuilQFd<R2>));
+	     Global.Add("QF3d","(",new OneOperator2_<const GQuadratureFormular<R3> *,long,KNM_<double> >(BuilQFd<R3>));
+
+	     Dcl_Type<const GQuadratureFormular<R1> **>(::InitializePtr<const GQuadratureFormular<R1> *>,::DeletePtr<const GQuadratureFormular<R1> *>);
+	     Dcl_Type<const GQuadratureFormular<R2> **>(::InitializePtr<const GQuadratureFormular<R2> *>,::DeletePtr<const GQuadratureFormular<R2> *>);
+	     Dcl_Type<const GQuadratureFormular<R3> **>(::InitializePtr<const GQuadratureFormular<R3> *>,::DeletePtr<const GQuadratureFormular<R3> *>);
+
+	     zzzfff->Add("QF1",atype<const GQuadratureFormular<R1> ** >());
+	     zzzfff->Add("QF2",atype<const GQuadratureFormular<R2> ** >());
+	     zzzfff->Add("QF3",atype<const GQuadratureFormular<R3> ** >());
+
+	     TheOperators->Add("<-",
+			       new OneOperator3_<const GQuadratureFormular<R1> **,const GQuadratureFormular<R1> **,long,KNM_<double>  >(pBuilQFd<R1>),
+			       new OneOperator3_<const GQuadratureFormular<R2> **,const GQuadratureFormular<R2> **,long,KNM_<double>  >(pBuilQFd<R2>),
+			       new OneOperator3_<const GQuadratureFormular<R3> **,const GQuadratureFormular<R3> **,long,KNM_<double>  >(pBuilQFd<R3>)
+			       
+
+        
+			       );
+	     //  cast ** -> * 
+	     map_type[typeid(const GQuadratureFormular<R1> *).name()]->AddCast(   new E_F1_funcT<const GQuadratureFormular<R1> *,const GQuadratureFormular<R1> **>(UnRef<const GQuadratureFormular<R1> *>) );
+	     map_type[typeid(const GQuadratureFormular<R2> *).name()]->AddCast(   new E_F1_funcT<const GQuadratureFormular<R2> *,const GQuadratureFormular<R2> **>(UnRef<const GQuadratureFormular<R2> *>) );
+	     map_type[typeid(const GQuadratureFormular<R3> *).name()]->AddCast(   new E_F1_funcT<const GQuadratureFormular<R3> *,const GQuadratureFormular<R3> **>(UnRef<const GQuadratureFormular<R3> *>) );
+ 
+
+}
+
+ 
+LOADFUNC(Load_Init)
diff --git a/examples++-load/ref.edp b/examples++-load/ref.edp
new file mode 100644
index 0000000..0b7a259
--- /dev/null
+++ b/examples++-load/ref.edp
@@ -0,0 +1 @@
+real REFload=0.841471;
diff --git a/examples++-load/refinesphere.edp b/examples++-load/refinesphere.edp
new file mode 100644
index 0000000..91b52f5
--- /dev/null
+++ b/examples++-load/refinesphere.edp
@@ -0,0 +1,56 @@
+// file adaptsphere.edp
+load "msh3"
+load "tetgen"
+load "medit"
+
+mesh Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},frac{-pi}{2}[\times]0,2\pi[ $
+//  a parametrization of a sphere 
+func f1 =cos(x)*cos(y);
+func f2 =cos(x)*sin(y);
+func f3 = sin(x);
+//  partiel derivative of the parametrization DF
+func f1x=sin(x)*cos(y);   
+func f1y=-cos(x)*sin(y);
+func f2x=-sin(x)*sin(y);
+func f2y=cos(x)*cos(y);
+func f3x=cos(x);
+func f3y=0;
+// $  M = DF^t DF $
+func m11=f1x^2+f2x^2+f3x^2;
+func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+func m22=f1y^2+f2y^2+f3y^2;
+
+func perio=[[4,y],[2,y],[1,x],[3,x]];  
+real hh=0.1;
+real vv= 1/square(hh);
+verbosity=2;
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+
+verbosity=2;
+
+// construction of the surface of spheres
+real Rmin  = 1.;
+func f1min = Rmin*f1;
+func f2min = Rmin*f2;
+func f3min = Rmin*f3;
+
+mesh3 Th3=movemesh23(Th,transfo=[f1min,f2min,f3min],orientation=-1);
+
+real[int] domain = [0.,0.,0.,145,0.01];
+mesh3 Th3sph=tetg(Th3,switch="paAAQYY",nbofregions=1,regionlist=domain);
+
+int[int] newlabel = [145,18];
+real[int] domainrefine = [0.,0.,0.,145,0.0001];
+
+mesh3 Th3sphrefine=tetgreconstruction(Th3sph,switch="raAQ",region=newlabel,nbofregions=1,regionlist=domainrefine,sizeofvolume=0.0001);
+
+int[int] newlabel2 = [145,53];
+func fsize = 0.01/(( 1 + 5*sqrt( (x-0.5)^2+(y-0.5)^2+(z-0.5)^2) )^3);
+mesh3 Th3sphrefine2=tetgreconstruction(Th3sph,switch="raAQ",region=newlabel2,sizeofvolume=fsize);
+
+medit("sphere",Th3sph);
+medit("sphererefinedomain",Th3sphrefine);
+medit("sphererefinelocal",Th3sphrefine2);
+
diff --git a/examples++-load/regtests.m4 b/examples++-load/regtests.m4
new file mode 100644
index 0000000..2282c25
--- /dev/null
+++ b/examples++-load/regtests.m4
@@ -0,0 +1,30 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+include(../regtests.m4)
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+ONETEST(load,uh[].max,0.0001)
+ONETEST(testFE)
+ONETEST(testFEMorley)
+ONETEST(funcTemplate)
+ONETEST( LapDG3)
+ONETEST( LapDG4)
+ONETEST( LaplaceP3)
+ONETEST( LaplaceP4)
+ONETEST( bilapMorley)
+ONETEST( plot-fb-P3)
+ONETEST( plot-fb-P3dc)
+ONETEST( plot-fb-P4)
+ONETEST( plot-fb-P4dc)
+ONETEST( splitmesh3)
+ONETEST( splitmesh6)
+ONETEST( testFE-PkEdge)
+ONETEST( testFE)
+ONETEST( testFEMorley)
+
+
diff --git a/examples++-load/schwarz-nm.edp b/examples++-load/schwarz-nm.edp
new file mode 100644
index 0000000..1c8a46d
--- /dev/null
+++ b/examples++-load/schwarz-nm.edp
@@ -0,0 +1,173 @@
+bool withmetis=0;
+bool RAS=0;
+int sizeoverlaps=2; // size off overlap 
+int nn=2,mm=2;
+
+func bool AddLayers(mesh & Th,real[int] &ssd,int n,real[int] &unssd)
+{
+  //  build a continuous function  uussd (P1) :
+  //  ssd in the caracteristics function on the input sub domain.
+  //  such that : 
+  //   unssd = 1 when   ssd =1;
+  //   add n layer of element (size of the overlap)
+  //   and unssd = 0 ouside of this layer ...
+  // ---------------------------------
+  fespace Vh(Th,P1);
+  fespace Ph(Th,P0);
+  Ph s;
+  assert(ssd.n==Ph.ndof);
+  assert(unssd.n==Vh.ndof);
+  unssd=0;
+  s[]= ssd;
+  //  plot(s,wait=1,fill=1);
+  Vh u;
+  varf vM(u,v)=int2d(Th,qforder=1)(u*v/area);
+  matrix M=vM(Ph,Vh);
+  
+  for(int i=0;i<n;++i)
+    {
+      u[]= M*s[];
+      // plot(u,wait=1);
+      u = u>.1; 
+      // plot(u,wait=1);
+      unssd+= u[];
+      s[]= M'*u[];//';
+      s = s >0.1;
+    }
+  unssd /= (n);
+  u[]=unssd;
+  ssd=s[];      
+  return true;
+}
+
+int withplot=3;
+mesh Th=square(50,50);
+int[int] chlab=[1,1  ,2,1  ,3,1  ,4,1  ];
+Th=change(Th,refe=chlab);
+int npart= nn*mm;
+fespace Ph(Th,P0);
+fespace Vh(Th,P1);
+
+Ph  part;
+Vh  sun=0,unssd=0;
+Ph xx=x,yy=y,nupp;
+part = int(xx*nn)*mm + int(yy*mm);
+//plot(part,wait=1);
+if(withmetis)
+  {
+    load "metis";
+    int[int] nupart(Th.nt);
+    metisdual(nupart,Th,npart); 
+    for(int i=0;i<nupart.n;++i)
+      part[][i]=nupart[i];
+  }
+if(withplot>1)
+plot(part,fill=1,cmm="dual",wait=1);
+mesh[int] aTh(npart);
+mesh Thi=Th;
+fespace Vhi(Thi,P1);
+Vhi[int] au(npart),pun(npart);
+matrix[int] Rih(npart);
+matrix[int] Dih(npart);
+matrix[int] aA(npart);
+Vhi[int] auntgv(npart);
+Vhi[int] rhsi(npart);
+
+for(int i=0;i<npart;++i)
+  {
+    Ph suppi= abs(part-i)<0.1;
+    AddLayers(Th,suppi[],sizeoverlaps,unssd[]);
+    Thi=aTh[i]=trunc(Th,suppi>0,label=10,split=1);
+    Rih[i]=interpolate(Vhi,Vh,inside=1); //  Vh -> Vhi
+    if(RAS)
+      {
+        suppi= abs(part-i)<0.1;
+        varf vSuppi(u,v)=int2d(Th,qforder=1)(suppi*v/area);
+        unssd[]= vSuppi(0,Vh);
+        unssd = unssd>0.;
+        if(withplot>19)
+          plot(unssd,wait=1);
+      }
+    pun[i][]=Rih[i]*unssd[];
+    sun[] += Rih[i]'*pun[i][];//';
+    if(withplot>9)
+      plot(part,aTh[i],fill=1,wait=1);
+  }
+plot(sun,wait=1,dim=3,fill=1);
+for(int i=0;i<npart;++i)
+  {
+    Thi=aTh[i];
+    pun[i]= pun[i]/sun;
+    if(withplot>8)
+      plot(pun[i],wait=1);    
+  }
+
+//  verif partition of unite 
+
+macro Grad(u) [dx(u),dy(u)]//EOM 
+  sun=0;
+
+for(int i=0;i<npart;++i)
+  {
+    cout << " build part :" << i << "/" << npart << endl;
+    Thi=aTh[i];
+    varf va(u,v) = 
+      int2d(Thi)(Grad(u)'*Grad(v))//')
+      +on(1,u=1) + int2d(Thi)(v)
+      +on(10,u=0) ; 
+    
+    
+    aA[i]=va(Vhi,Vhi);
+    set(aA[i],solver=UMFPACK);
+    rhsi[i][]= va(0,Vhi);
+    Dih[i]=pun[i][];
+    real[int]  un(Vhi.ndof);
+    un=1.;
+    real[int] ui=Dih[i]*un; 
+    sun[] += Rih[i]'*ui;;//';
+    varf vaun(u,v) = on(10,u=1);
+    auntgv[i][]=vaun(0,Vhi); // store arry of tgv on Gamma intern.
+  }
+if(withplot>5)
+  plot(sun,fill=1,wait=1);
+cout << sun[].max << " " << sun[].min<< endl;
+// verification of the partition of the unite.
+assert( 1.-1e-9 <= sun[].min  && 1.+1e-9 >= sun[].max);  
+
+// FFCS: reference value for regression tests
+Vh ref;
+
+int nitermax=1000;
+{
+  Vh un=0;
+  for(int iter=0;iter<nitermax;++iter)
+    {
+      real err=0;
+      Vh un1=0;
+      for(int i=0;i<npart;++i)
+        {
+          Thi=aTh[i];
+          real[int] ui=Rih[i]*un[];//';
+          //{   Vhi uuu; uuu[]=ui;      plot(uuu,wait=1);}
+          real[int] bi = ui .* auntgv[i][];
+          bi = auntgv[i][] ? bi :  rhsi[i][];  
+          ui=au[i][];
+          ui= aA[i] ^-1 * bi;
+          //{   Vhi uuu; uuu[]=ui;      plot(uuu,wait=1);}
+          bi = ui-au[i][];
+          err += bi'*bi;//';
+          au[i][]= ui;
+          bi = Dih[i]*ui;
+          un1[] += Rih[i]'*bi;//';
+        }
+      err= sqrt(err);
+      cout << iter << " Err = " << err << endl;
+      if(err<1e-2) break;
+      //    plot(un1,wait=1);
+      un[]=un1[];
+      if(withplot>2)
+        plot(au,dim=3,wait=0,cmm=" iter  "+iter,fill=1 );
+    }
+  plot(un,wait=1,dim=3,fill=1);
+  ref=un;
+}
diff --git a/examples++-load/scotch.cpp b/examples++-load/scotch.cpp
new file mode 100644
index 0000000..aa9f06b
--- /dev/null
+++ b/examples++-load/scotch.cpp
@@ -0,0 +1,152 @@
+// SUMMARY  :   add interface with partionning library scotch 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : P. Jolivet 
+// E-MAIL   : Pierre Jolivet <pierre.jolivet at ljll.math.upmc.fr>
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep: scotch
+//ff-c++-cpp-dep: 
+//
+//
+// P. Jolivet   april 2012
+// ----------------------------
+
+
+#include "ff++.hpp"
+#include <vector>
+#include <cmath>
+#include <scotch.h>
+
+template<class T, class V>
+class SCOTCH_Op : public E_F0mps {
+    public:
+        Expression partition;
+        Expression Th;
+        Expression lpartition;
+        static const int n_name_param = 1;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        SCOTCH_Op(const basicAC_F0&  args, Expression param1, Expression param2, Expression param3) : partition(param1), Th(param2), lpartition(param3) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+
+        AnyType operator()(Stack stack) const;
+};
+
+// FFCS - keywords/dumptable is not able to scan class names if they contain spaces, even in template arguments
+template<class T, class V>
+basicAC_F0::name_and_type SCOTCH_Op<T,V>::name_param[] = {
+    {"weight", &typeid(KN<long>*)}
+};
+
+
+template<class T, class V>
+class  SCOTCH : public OneOperator {
+    public:
+        SCOTCH() : OneOperator(atype<long>(), atype<KN<long>* >(), atype<V>(), atype<long>()) {}
+
+        E_F0* code(const basicAC_F0& args) const
+        {
+            return new SCOTCH_Op<T, V>(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]), t[2]->CastTo(args[2]));
+        }
+};
+
+
+template<class T, class V>
+AnyType SCOTCH_Op<T, V>::operator()(Stack stack)  const {
+    T* pTh = GetAny<T*>((*Th)(stack));
+    ffassert(pTh);
+    int nt = pTh->nt;
+    KN<long>* part = GetAny<KN<long>* >((*partition)(stack));
+    ffassert(part);
+
+    int nve = T::Rd::d+1;
+    long lpart = GetAny<long>((*lpartition)(stack));
+    ffassert(lpart > 1 && part->n == nt && lpart < nt);
+
+    KN<long>* weight = nargs[0] ? GetAny<KN<long>* >((*nargs[0])(stack)) : (KN<long>*) 0;
+
+    SCOTCH_Graph GraphSCOTCH;
+    SCOTCH_Strat StratSCOTCH;
+    SCOTCH_graphInit(&GraphSCOTCH);
+    SCOTCH_stratInit(&StratSCOTCH);
+    SCOTCH_Num baseval = 0;
+    SCOTCH_Num vertnbr = nt;
+    SCOTCH_Num edgenbr;
+    SCOTCH_Num* verttab = new SCOTCH_Num[vertnbr + 1];
+    vector<SCOTCH_Num> edgevec;
+    SCOTCH_Num prev;
+    int cptNode = 0;
+    int cptEdge = 0;
+    int accum = 0;
+    verttab[cptNode++] = baseval;
+    for (int it = 0; it < nt; ++it) {
+        for (int jt = 0; jt < nve; ++jt) {
+            int jtt = jt, itt = pTh->ElementAdj(it, jtt);
+            if( (itt != it) && (itt >= 0) ) {
+                ++accum;
+                edgevec.push_back(baseval + itt);
+            }
+        }
+        verttab[cptNode++] = accum;
+    }
+    edgenbr = accum;
+    SCOTCH_Num* edgetab = &edgevec[0];
+    SCOTCH_Num* velotab;
+
+    if(weight) {
+        velotab = new SCOTCH_Num[nt];
+        for(int i = 0; i < nt; ++i)
+            velotab[i] = (SCOTCH_Num)(*weight)[i];
+    } else
+        velotab = NULL;
+
+    SCOTCH_Num* vendtab = NULL;
+    SCOTCH_Num* vlbltab = NULL;
+    SCOTCH_Num* edlotab = NULL;
+    SCOTCH_graphBuild(&GraphSCOTCH, baseval, vertnbr, verttab, vendtab, velotab, vlbltab, edgenbr, edgetab, edlotab);
+    SCOTCH_graphCheck(&GraphSCOTCH);
+
+    KN<SCOTCH_Num> epart(nt);
+    SCOTCH_graphPart(&GraphSCOTCH, lpart, &StratSCOTCH, epart);
+    SCOTCH_graphExit(&GraphSCOTCH);
+    SCOTCH_stratExit(&StratSCOTCH);
+    *part = epart;
+    delete[] verttab;
+    if(velotab)
+        delete[] velotab;
+
+    return 1L;
+}
+
+/*  class Init {
+    public:
+        Init();
+};
+
+Init init;*/
+static void Load_Init( ){
+    Global.Add("scotch", "(", new SCOTCH<Mesh, pmesh>);
+    Global.Add("scotch", "(", new SCOTCH<Mesh3, pmesh3>);
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/scotch.edp b/examples++-load/scotch.edp
new file mode 100644
index 0000000..0229327
--- /dev/null
+++ b/examples++-load/scotch.edp
@@ -0,0 +1,45 @@
+load "scotch"
+load "metis"
+border C(t=0, 2*pi){ x=cos(t); y=sin(t); }
+mesh Th = buildmesh(C(1000)); // first mesh: a simple circle
+int lpart = 10; // how many clusters must be created ?
+fespace Ph(Th, P0); // using P0 FE to store the partition
+int[int] nupart(Th.nt); // the actual partition
+Ph part = nuTriangle; // number of each triangles in the mesh
+int[int] weight(Th.nt); // array of integers to store weights
+for(int i = 0; i < Th.nt;++i)
+    weight[i] = Th[i][1].x > 0. && Th[i][1].y > 0. ? 10 : 1; // if we want to partition has much as possible the region x > 0 && y > 0
+plot(Th, part, value = 1, fill = 1, wait = 1, cmm = "original");
+scotch(nupart, Th, lpart, weight = weight); // with weight
+Ph balance;
+for(int i = 0; i < Th.nt; ++i)
+    balance[][i] = nupart[i];
+plot(Th, balance, value = 1, fill = 1, wait = 1, cmm = "SCOTCH with weights");
+scotch(nupart, Th, lpart); // without weight
+for(int i = 0; i < Th.nt; ++i)
+    balance[][i] = nupart[i];
+plot(Th, balance, value = 1, fill = 1, wait = 1, cmm = "SCOTCH");
+metisdual(nupart, Th, lpart);
+for(int i = 0; i < Th.nt; ++i)
+    balance[][i] = nupart[i];
+plot(Th, balance, value = 1, fill = 1, wait = 1, cmm = "Metis");
+Th = square(400, 400); // second mesh: a simple square
+balance = 0;
+part = nuTriangle;
+weight.resize(Th.nt);
+nupart.resize(Th.nt);
+for(int i = 0; i < Th.nt;++i)
+    weight[i] = Th[i][1].x > 0.5 && Th[i][1].y > 0.5 ? 100 : 1; // if we want to partition has much as possible the region x > 0.5 && y > 0.5
+plot(Th, part, value = 1, fill = 1, wait = 1, cmm = "original");
+scotch(nupart, Th, lpart, weight = weight);
+for(int i = 0; i < Th.nt; ++i)
+    balance[][i] = nupart[i];
+plot(Th, balance, value = 1, fill = 1, wait = 1, cmm = "SCOTCH with weights");
+scotch(nupart, Th, lpart);
+for(int i = 0; i < Th.nt; ++i)
+    balance[][i] = nupart[i];
+plot(Th, balance, value = 1, fill = 1, wait = 1, cmm = "SCOTCH");
+metisdual(nupart, Th, lpart);
+for(int i = 0; i < Th.nt; ++i)
+    balance[][i] = nupart[i];
+plot(Th, balance, value = 1, fill = 1, wait = 1, cmm = "Metis");
diff --git a/examples++-load/shell.cpp b/examples++-load/shell.cpp
new file mode 100644
index 0000000..ecd1a17
--- /dev/null
+++ b/examples++-load/shell.cpp
@@ -0,0 +1,144 @@
+// Example C++ function "myfunction", dynamically loaded into "load.edp"
+// ---------------------------------------------------------------------
+// $Id$
+#include <ff++.hpp>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dirent.h> 
+#include <strings.h>
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+//#include <tr1/regex> 
+using namespace Fem2D;
+long ff_chdir(string * c) { return chdir(c->c_str());}
+long ff_rmdir(string * c) { return rmdir(c->c_str());}
+long ff_unlink(string * c) { return unlink(c->c_str());}
+#ifndef WIN32
+long ff_mkdir(string * c,long mm) {mode_t m=mm;cout << " mkdir " << *c << "mode =" << m << endl;  return mkdir(c->c_str(),m);}
+#endif
+long ff_chmod(string * c,long mm) {mode_t m=mm;cout << " mkdir " << *c << "mode =" << m << endl;  return chmod(c->c_str(),m);}
+long ff_mkdir(string * c) {mode_t m=07777;
+#ifdef WIN32
+  return mkdir(c->c_str());
+#else
+  return mkdir(c->c_str(),m);
+#endif
+  }
+long ff_stat(string * c) {
+struct stat buff;
+return stat(c->c_str(),&buff);}
+long   ff_isdir(string * c) {
+struct stat buff;
+ if( 0==  stat(c->c_str(),&buff))
+   return  ( buff.st_mode  & S_IFDIR) ? 1 : 0 ;
+ else return  -1; // err 
+}
+
+DIR ** OpenDir(DIR **pp,string *n)
+{
+  *pp=opendir(n->c_str());
+  return pp; 
+}
+string * ReadDir(Stack s,DIR ** const &dirpp){
+  if(*dirpp) 
+    {
+      struct dirent * dp =   readdir(*dirpp);
+      if(dp)
+	return Add2StackOfPtr2Free(s,new string(dp->d_name));
+    }
+  return Add2StackOfPtr2Free(s,new string(""));
+} 
+ inline AnyType CloseDir(Stack,const AnyType &x){
+  DIR ** dirpp=PGetAny<DIR*>(x);
+  if(*dirpp) (void)closedir(*dirpp);
+  *dirpp=0;
+  return  Nothing;
+}
+#ifdef WIN32 
+string * ffgetenv(Stack s,string * const & k)
+{
+    const int LEN = 4096;
+    char envv[LEN];
+
+     GetEnvironmentVariable(k->c_str(),envv,LEN);
+    
+    return Add2StackOfPtr2Free(s,new string(envv));
+}
+
+long  ffsetenv(string * const & k,string * const & v)
+{
+ 
+    char * vv = strcpy((char*)malloc(v->size()+2),v->c_str());
+    char * kk = strcpy((char*)malloc(k->size()+2),k->c_str());
+    SetEnvironmentVariable(vv,kk);
+    return SetEnvironmentVariable(vv,kk) ;
+}
+long  ffunsetenv(string * const & k)
+{
+    SetEnvironmentVariable(k->c_str(),0);
+    return 0 ;
+}
+#else
+string * ffgetenv(Stack s,string * const & k)
+{
+    const char *env = getenv(k->c_str());
+    if(!env) env ="";
+    return Add2StackOfPtr2Free(s,new string(env));
+}
+
+long  ffsetenv(string * const & k,string * const & v)
+{
+    char * vv = strcpy((char*)malloc(v->size()+2),v->c_str());
+    char * kk = strcpy((char*)malloc(k->size()+2),k->c_str());
+    long r= setenv(vv,kk,1);
+    return r ;
+}
+long  ffunsetenv(string * const & k)
+{
+    long r= unsetenv(k->c_str());
+    return r ;
+}
+#endif
+
+extern  mylex *zzzfff;
+
+void init(){
+  Dcl_Type< DIR **  > (0,CloseDir,0);
+  zzzfff->Add("Directory",atype<DIR ** >());
+  TheOperators->Add("<-",   new OneOperator2<DIR **,DIR **,string *  >(OpenDir));
+  Global.Add("readdir","(",new OneOperator1s_<string*,DIR**>(ReadDir));
+  Global.New("modeRWXu long",CConstant<bool>(0700));
+  Global.New("modeRWXg long",CConstant<bool>(070));
+  Global.New("modeRWXo long",CConstant<bool>(07));
+
+  Global.New("modeRu long",CConstant<bool>(0400));
+  Global.New("modeRg long",CConstant<bool>(040));
+  Global.New("modeRo long",CConstant<bool>(04));
+
+  Global.New("modeWu long",CConstant<bool>(0200));
+  Global.New("modeWg long",CConstant<bool>(020));
+  Global.New("modeWo long",CConstant<bool>(02));
+
+  Global.New("modeXu long",CConstant<bool>(0100));
+  Global.New("modeXg long",CConstant<bool>(010));
+  Global.New("modeXo long",CConstant<bool>(01));
+
+  Global.Add("unlink","(",new OneOperator1<long,string*>(ff_unlink));
+  Global.Add("rmdir","(",new OneOperator1<long,string*>(ff_rmdir));
+  Global.Add("cddir","(",new OneOperator1<long,string*>(ff_chdir));
+  Global.Add("chdir","(",new OneOperator1<long,string*>(ff_chdir));
+  #ifndef WIN32
+  Global.Add("mkdir","(",new OneOperator2<long,string*,long>(ff_mkdir));
+  #endif
+  Global.Add("chmod","(",new OneOperator2<long,string*,long>(ff_chmod));
+  Global.Add("mkdir","(",new OneOperator1<long,string*>(ff_mkdir));
+  Global.Add("stat","(",new OneOperator1<long,string*>(ff_stat));
+  Global.Add("isdir","(",new OneOperator1<long,string*>(ff_isdir));
+  Global.Add("getenv","(",new OneOperator1s_<string*,string*>(ffgetenv));
+  Global.Add("setenv","(",new OneOperator2_<long,string*,string*>(ffsetenv));
+  Global.Add("unsetenv","(",new OneOperator1_<long,string*>(ffunsetenv));
+}
+
+LOADFUNC(init);
diff --git a/examples++-load/shell.edp b/examples++-load/shell.edp
new file mode 100644
index 0000000..e790b20
--- /dev/null
+++ b/examples++-load/shell.edp
@@ -0,0 +1,15 @@
+load "shell"
+Directory  c=".";
+
+while(1)
+{
+	string n=readdir(c);
+	if( n != "") 
+	  cout << n << " " << isdir(n) << endl; 
+	else break; 
+}
+
+cout << " login " << getenv("LOGIN") << endl;
+setenv("FF_TOTO","toto");
+setenv("FF_TOTO","toto");
+cout << " FF_TOTO  " << getenv("FF_TOTO") << endl;
diff --git a/examples++-load/splitedges.cpp b/examples++-load/splitedges.cpp
new file mode 100644
index 0000000..6b67cf2
--- /dev/null
+++ b/examples++-load/splitedges.cpp
@@ -0,0 +1,248 @@
+
+#include "ff++.hpp" 
+
+  using namespace  Fem2D;
+
+Mesh * Split_Edges(Fem2D::Mesh * const & pTh, long  *dK)
+{
+  bool  v10 = verbosity>10;
+  bool  vp = verbosity>1;
+  assert(pTh);
+  const Mesh & Th(*pTh);  // le maillage d'origne a decoupe
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  int nbtn =Th.nt;
+  int nbvn =Th.nv;
+  int nebn =Th.neb;
+  for(int k=0;k<Th.nt;++k)
+    for(int e=0;e<3;++e)
+      if( dK[k] & (1<<e)) {
+	nbtn++;
+	int ee(e),kk;
+	kk=Th.ElementAdj(k,ee);
+	// if(kk<0 || kk==k) nebn++; // bug ?????????????????? cas de arete de bord interne ....
+	if (kk<=k) nbvn++;
+      }
+  // bug corrige ????
+  for (int i=0;i<Th.neb;i++)
+    {        
+      int ek,k=Th.BoundaryElement(i,ek);
+      if( dK[k] & (1<<ek)) nebn++; 
+    }
+  if(vp)
+    cout << " Split_Edges:  nbv " << nbvn << " nbtn = " << nbtn << " nebn = " <<  nebn << endl;      
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int neb=Th.neb; // nombre d'aretes fontiere
+  // allocation des nouveaux items du maillage  
+  Vertex * v= new Vertex[nbvn];
+  Triangle *t= new Triangle[nbtn];
+  BoundaryEdge *b= new BoundaryEdge[nebn];
+  // generation des nouveaus sommets 
+  Vertex *vv=v;
+  // copie des anciens sommets (remarque il n'y a pas operateur de copy des sommets)
+  for (int i=0;i<nbv;i++)
+   {
+     Vertex & V=Th(i);
+     vv->x=V.x;
+     vv->y=V.y;
+     vv->lab = V.lab;
+     vv++;      
+   }
+  KNM<int> NGP(3,nbt);
+  // generation des points barycentre dearete a decoupe 
+  for (int k=0;k<nbt;k++)
+    for(int e=0;e<3;++e)
+      if( dK[k] & (1<<e)) {
+	int ee(e),kk;
+ 	kk=Th.ElementAdj(k,ee);
+	if (kk<=k) {
+	  Triangle & K=Th[k];
+	  int i0=(e+1)%3;
+	  int i1=(e+2)%3;
+	  R2 A = ( (R2) K[i0] + K[i1])  / 2.;
+	  vv->x=A.x;
+	  vv->y=A.y;
+	  vv->lab = 0;
+	  int j=vv-v;
+	  NGP(e,k)=j;
+	  if( (kk!=k) && (kk >=0 )) NGP(ee,kk)=j;
+	  vv++;
+	}
+      }
+  ffassert(vv-v==nbvn);
+  //  generation des triangles 
+  Triangle *tt= t; 
+  int nberr=0;
+   
+  for (int k=0;k<nbt;k++)
+    {
+      Triangle & K=Th[k];
+      int j0=Th(k,0),j1=Th(k,1),j2=Th(k,2);
+      int p[]={0,1,2} ; 
+      R Le[]={K.lenEdge2(0),K.lenEdge2(1),K.lenEdge2(2)};
+      if(Le[p[0]]<Le[p[1]]) Exchange(p[0],p[1]);
+      if(Le[p[1]]<Le[p[2]]) Exchange(p[1],p[2]);
+      if(Le[p[0]]<Le[p[1]]) Exchange(p[0],p[1]);
+      if(v10) cout << k << " \t " << j0 << " " << j1 << " " << j2 << " ------ " << tt-t << endl;
+      Triangle * t0[]={tt,tt,tt}; 
+      (*tt++).set(v,j0,j1,j2,Th[k].lab);
+      for(int ie=0;ie<3;++ie)
+	{
+	  int e = p[ie];
+	  int e1= (e+1)%3, e2=(e+2)%3;
+	  Triangle * td = t0[e], &Kd=*td;
+	  ffassert(td);
+
+	  if( dK[k] & (1<<e)) {
+	    Triangle *tn=tt++; 
+	    int iee=  NGP(e,k);
+	    int id[]={  int(&(Kd[0])-v),int(&(Kd[1])-v), int(&(Kd[2])-v)};
+	    int in[]={ id[0],id[1],id[2]};
+	    id[e1]=iee;
+	    in[e2]=iee;
+
+
+	    if(v10) cout << k << " \t " << in[0]  << " " << in[1] << " " <<in[2] << "  nn " << tn-t << " " << Le[e] << endl;
+	    (*td).set(v,id[0],id[1],id[2],Th[k].lab);
+	    if(v10) cout << k << " \t " << id[0]  << " " << id[1] << " " <<id[2] << "  dd " << td-t << endl;
+	    (*tn).set(v,in[0],in[1],in[2],Th[k].lab);
+	    t0[e]=0; // done ..
+	    if( t0[e1]  && t0[e2])
+	      {
+		t0[e1]= td;
+		t0[e2]= tn;
+	      }
+	  }}
+    } 
+  ffassert(tt-t==nbtn);
+  // les arete frontieres qui n'ont pas change
+  BoundaryEdge * bb=b;
+  for (int i=0;i<neb;i++)
+    {        
+      int ek,k=Th.BoundaryElement(i,ek);
+      int i1=Th(Th.bedges[i][0]);
+      int i2=Th(Th.bedges[i][1]);
+      int lab=Th.bedges[i].lab;     
+      if( dK[k] & (1<<ek)) {
+	int iee=  NGP(ek,k);
+	assert(iee>0);
+	if(v10) cout << " " << i1 << " " << iee << " " << i2 << " " << lab << " " << endl;
+	*bb++ = BoundaryEdge(v,i1,iee,lab);   
+	*bb++ = BoundaryEdge(v,iee,i2,lab);   
+      }
+      else 
+      *bb++ = BoundaryEdge(v,i1,i2,lab);   
+    }
+  ffassert(bb-b==nebn);
+  //  generation de la class Mesh a partir des 3 tableaux : v,t,b
+  {
+    Mesh * m = new Mesh(nbvn,nbtn,nebn,v,t,b);
+    R2 Pn,Px;
+    m->BoundingBox(Pn,Px);
+    m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+    m->decrement();
+    return m;
+  }
+}
+
+//  truc pour que la fonction 
+// static void Load_Init() soit appele a moment du chargement dynamique
+// du fichier 
+//  
+/*  class Init { public:
+  Init();
+};
+*/
+class SplitEdges :  public E_F0mps 
+{
+public:
+  typedef pmesh  Result;
+  Expression expTh;
+  Expression spt;
+  
+  SplitEdges(const basicAC_F0 & args)
+  {
+
+    args.SetNameParam();
+    expTh= to<pmesh>(args[0]);  // a the expression to get the mesh
+    spt= to<double>(args[1]);  // a the expression to get the mesh
+  }
+  static ArrayOfaType  typeargs()
+  { return  ArrayOfaType(
+			 atype<pmesh>(),
+			 atype<double>());
+  }
+  static  E_F0 * f(const basicAC_F0 & args){ return new SplitEdges(args);}
+  AnyType operator()(Stack s) const ;
+
+};
+
+
+AnyType SplitEdges::operator()(Stack stack) const 
+  {
+    Mesh * pTh =  GetAny<pmesh>((*expTh)(stack));
+    MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+    bool v10= verbosity>10; 
+    ffassert(pTh);
+    Mesh & Th(*pTh);
+    KN<long> dK(Th.nt);
+    dK=0L;
+    int ne=0;
+    for (int k=0;k<Th.nt;k++)
+      for (int e=0;e<3;e++)
+	{
+	  Triangle &K=Th[k];
+	  int e1=(e+1)%3;
+	  int e2=(e+2)%3;
+	  R2 P1=K[e1],P2=K[e2];
+	  R2 P=(P1+P2)/2.;
+	  MeshPointStack(stack)->set(P.x,P.y);
+	  double de =  fabs(GetAny<double>((*spt)(stack)));
+	  bool be= fabs(de)>1e-30;
+          if(be) 
+	    {
+	      dK[k] += (1<<e); 
+	      ne++;
+	    }
+      
+	  if(v10) cout << k << " " << e << "   f " << P << " = " << de << " " << be << " " << dK[k] << " " << (1<<e) << endl;
+	  int ee(e),kk;
+	  kk=Th.ElementAdj(k,ee);
+ 	  if( (kk<k) && (kk>=0))
+	    { 
+	      bool bee = dK[kk] & (1<<ee);
+	      if( bee != be) {
+		cout << " Bizarre edge right != compatible left " <<  k << " " << e << " P = " << P << " kk " << kk << " " << ee << " " << dK[kk] <<endl;
+		dK[k] = dK[k] |  (1<<e);
+		dK[kk] = dK[kk] |  (1<<ee);
+	      }}
+	}
+    if(verbosity>0)
+      cout << "  SplitEdges: nb split edge = " << ne << endl;
+    *mp=mps;
+    return SetAny<pmesh>( Split_Edges(pTh,(long *) dK));      
+  }
+ 
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  if (verbosity)
+    cout << " lood: Split3  " << endl;
+  Global.Add("SplitEdgeMesh","(", new OneOperatorCode<SplitEdges >( ));
+  // utilisation 
+  // mesh Th,Th3;
+  //  ... construction du maillage Th ici 
+  //   Th3=splitmesh3(Th);
+  /*  example complet : splitmesh3.edp
+      load "splitedge"
+      mesh Th=square(5,5);
+      mesh Th3=SplitEdgeMesh(Th,x<0.51 && y < 0.49 );
+      plot(Th3,wait=1);
+  */
+
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/splitedges.edp b/examples++-load/splitedges.edp
new file mode 100644
index 0000000..1ab1307
--- /dev/null
+++ b/examples++-load/splitedges.edp
@@ -0,0 +1,10 @@
+      load "splitedges"
+      mesh Th=square(50,50);
+      real xx=1.1,yy=1.1;	
+      for(int i=0;i<4;++i)
+	{     
+	  xx *= 0.5;
+	  yy *= 0.5;
+	  Th=SplitEdgeMesh(Th,x<yy && y < yy );
+	  plot(Th,wait=1);
+	}
diff --git a/examples++-load/splitmesh3.cpp b/examples++-load/splitmesh3.cpp
new file mode 100644
index 0000000..bc6657a
--- /dev/null
+++ b/examples++-load/splitmesh3.cpp
@@ -0,0 +1,115 @@
+// $Id$
+
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+using namespace std;  
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include <fem.hpp>
+#include <cmath>
+
+  using namespace  Fem2D;
+
+Mesh * SplitMesh3(Fem2D::Mesh * const & pTh)
+{
+  assert(pTh);
+  const Mesh & Th(*pTh);  // le maillage d'origne a decoupe
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int neb=Th.neb; // nombre d'aretes fontiere
+  // allocation des nouveaux items du maillage  
+  Vertex * v= new Vertex[nbv+nbt];
+  Triangle *t= new Triangle[nbt*3];
+  BoundaryEdge *b= new BoundaryEdge[neb];
+  // generation des nouveaus sommets 
+  Vertex *vv=v;
+  // copie des anciens sommets (remarque il n'y a pas operateur de copy des sommets)
+  for (int i=0;i<nbv;i++)
+   {
+     Vertex & V=Th(i);
+     vv->x=V.x;
+     vv->y=V.y;
+     vv->lab = V.lab;
+     vv++;      
+   }
+  // generation des points barycentre de trianngles 
+  for (int k=0;k<nbt;k++)
+    {
+      Triangle & K=Th[k];
+      R2 G= ( (R2) K[0] + K[1] + K[2] )  / 3.;
+      vv->x=G.x;
+      vv->y=G.y;
+      vv->lab = 0;
+      vv++;
+    }   
+
+  //  generation des triangles 
+  Triangle *tt= t; 
+  int nberr=0;
+   
+  for (int i=0;i<nbt;i++)
+    {
+      int i0=Th(i,0), i1=Th(i,1),i2=Th(i,2);
+      int ii = nbv + i; // numero du 
+      // les 3 triangles par triangles origines 
+      (*tt++).set(v,ii,i1,i2,Th[i].lab);
+      (*tt++).set(v,i0,ii,i2,Th[i].lab);
+      (*tt++).set(v,i0,i1,ii,Th[i].lab);
+    }  
+
+  // les arete frontieres qui n'ont pas change
+  BoundaryEdge * bb=b;
+  for (int i=0;i<neb;i++)
+    {        
+      int i1=Th(Th.bedges[i][0]);
+      int i2=Th(Th.bedges[i][1]);
+      int lab=Th.bedges[i].lab;     
+      *bb++ = BoundaryEdge(v,i1,i2,lab);   
+    }
+  //  generation de la class Mesh a partir des 3 tableaux : v,t,b
+  {
+    Mesh * m = new Mesh(nbv+nbt,nbt*3,neb,v,t,b);
+    R2 Pn,Px;
+    m->BoundingBox(Pn,Px);
+    m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+    m->decrement();
+    return m;
+  }
+}
+
+//  truc pour que la fonction 
+// static void Load_Init() soit appele a moment du chargement dynamique
+// du fichier 
+//  
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  if (verbosity)
+    cout << " lood: Split3  " << endl;
+  Global.Add("splitmesh3","(",new OneOperator1_<Mesh *,Mesh *>(SplitMesh3));
+  // utilisation 
+  // mesh Th,Th3;
+  //  ... construction du maillage Th ici 
+  //   Th3=splitmesh3(Th);
+  /*  example complet : splitmesh3.edp
+      load "splitmesh3"
+      mesh Th=square(5,5);
+      mesh Th3=splitmesh3(Th);
+      plot(Th3,wait=1);
+  */
+
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/splitmesh3.edp b/examples++-load/splitmesh3.edp
new file mode 100644
index 0000000..c0175f8
--- /dev/null
+++ b/examples++-load/splitmesh3.edp
@@ -0,0 +1,4 @@
+load "splitmesh3"
+mesh Th=square(5,5);
+mesh Th3=splitmesh3(Th);
+plot(Th3,wait=1);
\ No newline at end of file
diff --git a/examples++-load/splitmesh6.cpp b/examples++-load/splitmesh6.cpp
new file mode 100644
index 0000000..4198715
--- /dev/null
+++ b/examples++-load/splitmesh6.cpp
@@ -0,0 +1,162 @@
+// $Id$
+
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+using namespace std;  
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include <fem.hpp>
+#include <cmath>
+
+  using namespace  Fem2D;
+
+Mesh * SplitMesh6(Fem2D::Mesh * const & pTh)
+{
+  assert(pTh);
+  const Mesh & Th(*pTh);  // le maillage d'origne a decoupe
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int neb=Th.neb; // nombre d'aretes fontiere
+  // allocation des nouveaux items du maillage  
+  int nbe = 0;
+  for(int k=0; k <nbt; ++k)
+    for (int e = 0; e<3;++e)
+    {
+	int ee=e;
+	int kk = Th.ElementAdj(k,ee);
+	if( kk<=k) nbe++;
+    }
+  Vertex * v= new Vertex[nbv+nbt+nbe];
+  Triangle *t= new Triangle[nbt*6];
+  BoundaryEdge *b= new BoundaryEdge[neb*2];
+  // generation des nouveaus sommets 
+  Vertex *vv=v;
+  KN<int> mm(3*nbt);
+  // copie des anciens sommets (remarque il n'y a pas operateur de copy des sommets)
+  for (int i=0;i<nbv;i++)
+   {
+     Vertex & V=Th(i);
+     vv->x=V.x;
+     vv->y=V.y;
+     vv->lab = V.lab;
+     vv++;      
+   }
+  // generation des points barycentre de trianngles 
+  for (int k=0;k<nbt;k++)
+    {
+      Triangle & K=Th[k];
+      R2 G= ( (R2) K[0] + K[1] + K[2] )  / 3.;
+      vv->x=G.x;
+      vv->y=G.y;
+      vv->lab = 0;
+      vv++;
+    }   
+// generation des milieux des cote
+  int nn=0;
+  for(int k=0; k <nbt; ++k)
+      for (int e = 0; e<3;++e)
+      {
+	  int ee=e;
+	  int kk = Th.ElementAdj(k,ee);
+	  if( (kk>=k) || (kk <0) ) { 
+	      int v0=Th(k,EdgesVertexTriangle[e][0]);
+	      int v1=Th(k,EdgesVertexTriangle[e][1]);
+	      R2  M = ((R2) Th(v0) + Th(v1)) /2.;
+	      int lab=0;
+	      BoundaryEdge *be=Th.TheBoundaryEdge(v0,v1);
+	      if( be) 
+	      {
+		  lab= be->lab;
+	      }
+		
+	      vv->x=M.x;
+	      vv->y=M.y;
+	      vv->lab = lab;
+	      
+	       mm[k*3+e]= vv-v;// numero du sommet
+	       vv++;      
+	       nn++;
+	  }
+	  else   mm[k*3+e] = mm[kk*3+ee];
+      }
+	  cout << " nb edge = " << nbe << " == " << nn << endl;
+  ffassert(nbe==nn);	
+  
+  //  generation des triangles 
+  Triangle *tt= t; 
+  int nberr=0;
+   
+  for (int i=0;i<nbt;i++)
+    {
+      int i0=Th(i,0), i1=Th(i,1),i2=Th(i,2);
+      int j0=mm[i*3], j1=mm[i*3+1],j2=mm[i*3+2];
+      int ii = nbv + i; // numero du 
+      // les 3 triangles par triangles origines 
+      (*tt++).set(v,ii,i1,j0,Th[i].lab);
+      (*tt++).set(v,ii,j0,i2,Th[i].lab);
+      (*tt++).set(v,i0,ii,j1,Th[i].lab);
+      (*tt++).set(v,j1,ii,i2,Th[i].lab);
+      (*tt++).set(v,i0,j2,ii,Th[i].lab);
+      (*tt++).set(v,j2,i1,ii,Th[i].lab);
+    }  
+
+  // les arete frontieres qui n'ont pas change
+  BoundaryEdge * bb=b;
+  for (int i=0;i<neb;i++)
+    {        
+      int ki;
+      int k=Th.BoundaryElement(i,ki);
+      int i1=Th(Th.bedges[i][0]);
+      int i2=Th(Th.bedges[i][1]);
+      int ii = mm[3*k+ki]; 
+      int lab=Th.bedges[i].lab;     
+      *bb++ = BoundaryEdge(v,i1,ii,lab);   
+      *bb++ = BoundaryEdge(v,ii,i2,lab);   
+    }
+  //  generation de la class Mesh a partir des 3 tableaux : v,t,b
+  {
+    Mesh * m = new Mesh(nbv+nbt+nbe,nbt*6,neb*2,v,t,b);
+    R2 Pn,Px;
+    m->BoundingBox(Pn,Px);
+    m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+    m->decrement();
+    return m;
+  }
+}
+
+//  truc pour que la fonction 
+// static void Load_Init() soit appele a moment du chargement dynamique
+// du fichier 
+//  
+/*  class Init { public:
+  Init();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  if (verbosity)
+    cout << " lood: Split6  " << endl;
+  Global.Add("splitmesh6","(",new OneOperator1_<Mesh *,Mesh *>(SplitMesh6));
+  // utilisation 
+  // mesh Th,Th3;
+  //  ... construction du maillage Th ici 
+  //   Th3=splitmesh3(Th);
+  /*  example complet : splitmesh3.edp
+      load "splitmesh3"
+      mesh Th=square(5,5);
+      mesh Th3=splitmesh3(Th);
+      plot(Th3,wait=1);
+  */
+
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/splitmesh6.edp b/examples++-load/splitmesh6.edp
new file mode 100644
index 0000000..b04d21c
--- /dev/null
+++ b/examples++-load/splitmesh6.edp
@@ -0,0 +1,36 @@
+load "splitmesh6"
+mesh Th=square(5,5);
+mesh Th6=splitmesh6(Th);
+plot(Th6,wait=1);
+
+fespace Vh(Th,P1);
+fespace Nh(Th,P0);
+
+fespace Vh6(Th6,P1);
+fespace Nh6(Th6,P0);
+fespace RT6(Th6,RT0); // Raviart Thomas ordre 0
+
+//  
+varf vM6(u,v) = int2d(Th6,qforder=1)(u*v*3/area);
+matrix  M610= vM6(Nh6,Vh6);
+matrix  I61 = interpolate(Vh,Vh6);
+matrix  S61 =  I61*M610;
+
+Nh6 eta6=1;
+Vh  eta;
+eta[]= S61*eta6[];
+plot(eta,wait=1);
+
+RT6  [u6,v6];
+RT6  [uu6,vv6];
+
+Nh6 x6=x,y6=y;
+
+//solve  PP([u6,v6],[uu6,vv6]) = intalledges(Th6)(  u6*uu6*N.x + v6*vv6*N.y)
+//- intalledges(Th6)(  mean(x6)*uu6*N.x + mean(y6)*vv6*N.y);
+
+  [u6,v6] = [mean(x6),mean(y6)]; // OK version 2.19 
+ [uu6,vv6] = [x6,y6];
+ plot( [u6,v6],  [uu6,vv6], wait=1);
+ 
+ 
\ No newline at end of file
diff --git a/examples++-load/symmetrizeCSR.cpp b/examples++-load/symmetrizeCSR.cpp
new file mode 100644
index 0000000..3903c08
--- /dev/null
+++ b/examples++-load/symmetrizeCSR.cpp
@@ -0,0 +1,80 @@
+// SUMMARY  :   remove the upper part of a CSR if the supplied matrix is not symmetric
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : P. Jolivet 
+// E-MAIL   : Pierre Jolivet <pierre.jolivet at ljll.math.upmc.fr>
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+#include "ff++.hpp"
+
+template<class T>
+long symmetrizeCSR(Matrice_Creuse<T>* const &A) {
+    MatriceMorse<T>* mA = static_cast<MatriceMorse<T>*>(&(*A->A));
+    if(!mA->symetrique) {
+        mA->symetrique = true;
+        std::vector<int> cl;
+        std::vector<T> a;
+        a.reserve(mA->nbcoef);
+        cl.reserve(mA->nbcoef);
+        unsigned int save = mA->lg[0];
+        for(unsigned int i = 0; i < mA->n; ++i) {
+            for(unsigned int j = save; j < mA->lg[i + 1]; ++j) {
+                int col = mA->cl[j];
+                if(col <= i) {
+                    T val = mA->a[j];
+                    if(abs(val) > 1e-14) {
+                        a.push_back(val);
+                        cl.push_back(col);
+                    }
+                }
+                else
+                    break;
+            }
+            save = mA->lg[i + 1];
+            mA->lg[i + 1] = cl.size();
+        }
+        delete [] mA->cl;
+        delete [] mA->a;
+        int* col = new int[cl.size()];
+        T* val = new T[cl.size()];
+        for(unsigned int i = 0; i < cl.size(); ++i) {
+            col[i] = cl[i];
+            val[i] = a[i];
+        }
+        mA->cl = col;
+        mA->a = val;
+        mA->nbcoef = cl.size();
+    }
+    return 1L;
+}
+
+/*  class Init {
+    public:
+        Init();
+};
+
+Init init;
+*/
+static void Load_Init() {
+    Global.Add("symmetrizeCSR", "(", new OneOperator1_<long, Matrice_Creuse<double>* >(symmetrizeCSR<double>));
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/test-ElementMixte.edp b/examples++-load/test-ElementMixte.edp
new file mode 100644
index 0000000..8158240
--- /dev/null
+++ b/examples++-load/test-ElementMixte.edp
@@ -0,0 +1,225 @@
+
+load "Element_P4"
+load "Element_Mixte"
+
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+macro dn(f) ( N.x*dx(f)+N.y*dy(f)) //
+macro ccn(f) ( N.x*f#1+N.y*f#2) //
+macro cctau(f) ( -N.y*f#1+N.x*f#2) //
+macro dnn(f) ( N.x*N.x*f#11+2.*N.y*N.x*f#12+ N.y*N.y*f#22) //
+mesh Th=square(1,1,flags=1);//,[10*(x+y/3),10*(y-x/3)]);
+Th=trunc(Th,(x+y)<1.1);plot(Th,wait=1);
+Th=movemesh(Th,[0.1*(x+y/3),0.1*(y-x/3)]);
+Th=movemesh(Th,[0.1*(x),0.1*(y)]);
+real x1=0.7,y1=0.9, h=1e-6;
+int it1=Th(x1,y1).nuTriangle; 
+
+fespace Zh(Th,P1dc); 
+Zh  f11= 1, f12=0, f22=0;
+
+fespace Vh(Th,TDNNS1);
+cout << Vh.ndof << endl;
+cout << Vh.ndofK << endl;
+fespace Eh(Th,P0edge);
+fespace P3h(Th,[P0,P0,P0]);
+
+
+Eh  edges;
+ macro SS(a) [a#11,a#12,a#22] //
+
+P3h SS(pp);
+
+Vh SS(a),SS(b),SS(c);
+
+varf vFlux([ax11,ax12,ax22],[e]) = intalledges(Th,qforder=1)( dnn(a)*e*lenEdge);
+edges=x; 
+cout << " x = " << edges[]<< endl; 
+edges=y; 
+cout << " y = " << edges[]<< endl; 
+
+real gx=1./3., gy(1./3); 
+
+
+for(int j=0; j<Vh.ndofK;++j)
+{int i= Vh(0,j);
+ cout << "****" << j << " "  << i << endl; 
+ a11[]=0;
+ a11[][i]=1;
+/*
+ x=0; y = 0.5;  N.x = -1; N.y = 0; 
+  cout << " ------ dnn (0.,0.5) " << dnn(a) <<  "   " ;
+ x=0.5; y = 0.5;  N.x = 1; N.y = 1; 
+ cout << " dnn (.5,.5) " << dnn(a) << "     " ;
+ x=0.5; y = 0.;  N.x = 0; N.y = -1; 
+  cout << " dnn (0.5,0) " << dnn(a) << endl;
+  cout << " (0,0.5)  = " << a11(0,0.5) << " " << a12(0,0.5) << " " << a22(0,0.5) << endl;
+  cout << " (0.5,0)  = " << a11(0.5,0) << " " << a12(0.5,0) << " " << a22(0.5,0) << endl;
+  cout << " (0.5,0.5)  = " << a11(0.5,0.5) << " " << a12(0.5,0.5) << " " << a22(0.5,0.5) << endl;
+*/
+ // cout << " ...... " << int2d(Th)(a11) << " " << int2d(Th)(a12) << " " <<int2d(Th)(a22) << endl;
+
+// plot(a11,wait=1,cmm="a00 "+i);
+// plot(a22,wait=1,cmm="a22 "+i);
+// plot(a12,wait=1,cmm="a12 "+i);
+edges[]=vFlux(0,Eh);
+// cout << a11(gx,gy) << " " << a12(gx,gy) << " " << a22(gx,gy) << " at G "<< " " <<OA
+  cout << " ...... " << int2d(Th)(a11) << " " << int2d(Th)(a12) << " " <<int2d(Th)(a22)  << "   --- " ; 
+  for(int j=0;j<3;++j)
+   cout << edges[](Eh(0,j)) << " " ;
+ cout << "   *** Edges flux n.n " << j  << endl;  
+
+}
+ 
+SS(a) =SS(f);
+cout << a11[].n << " a = "<< a11[] <<endl; 
+
+ cout << a11(0.6,0.2) << " == " << f11(0.6,0.2) << endl;
+ cout << a12(0.6,0.2) << " == " << f12(0.6,0.2) << endl;
+ cout << a22(0.6,0.2) << " == " << f22(0.6,0.2) << endl;
+ cout << " 00 = " << int2d(Th)(square(a11-f11)) << endl;
+ cout << " 00 = " << int2d(Th)(square(a22-f22)) << endl;
+ cout << " 00 = " << int2d(Th)(square(a12-f12)) << endl;
+//plot(a11,wait=1);
+
+//Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+//it1=Th(x1,y1).nuTriangle;
+
+
+for (int i=0;i<Vh.ndofK;++i)
+	cout <<  i << " l  -> G " << Vh(0,i) << endl;
+ macro diff(err,dd,c,a,s) { real ddd = int2d(Th) (square( dd(a)-dd(c))) ;
+  cout << " ddd " << s << " : " <<ddd <<endl;
+ if (ddd>1e-10)  err++ ;} //
+int err=0;
+for (int i=0;i<Vh.ndofK;++i)
+{
+  cout << " ***  node " << i << " of Traingle " << it1 << endl;
+  a11[]=0;	
+  int j=Vh(it1,i);
+  a11[][j]=1;
+  SS(b)=SS(a);
+  cout << " b = " << b11[] << endl; 
+  b11[]-=a11[];
+  edges[]=vFlux(0,Eh);
+  cout << "Mean  edges = " << edges[] << "  diff = " << b11[].linfty <<endl; 
+  if (b11[].linfty > 1e-10) err++; 
+  Zh c11=a11,c12=a12,c22=a22;
+ 
+    
+ // plot(a12,wait=1,cmm="a12 "+i );
+ // plot(c12,wait=1,cmm="c12 "+i );
+  diff(err, ,c11,a11," ");
+  diff(err, ,c12,a12," ");
+  diff(err, ,c22,a22," ");
+  diff(err, dx,c11,a11,"dx");
+  diff(err, dx,c12,a12,"dx");
+  diff(err, dx,c22,a22,"dx");
+
+  diff(err, dy,c11,a11,"dy");
+  diff(err, dy,c12,a12,"dy");
+  diff(err, dy,c22,a22,"dy");
+
+
+  
+} 
+assert(err==0);
+for(int i=0;i<P3h.ndof;++i)
+ {
+ 	cout << " i =" << i << endl;
+ 	pp11[]=0;
+ 	pp11[][i]=1;
+ 	SS(a)=SS(pp);
+ 	diff(err, ,pp22,a22," ");
+ 	diff(err, ,pp11,a11," ");
+ 	diff(err, ,pp12,a12," ");
+
+ }
+
+// FFCS - reference value
+real ref;
+
+{
+assert(err==0);
+
+NewMacro V(u) [u#1,u#2] EndMacro
+NewMacro CheckRT(RT,RTname,xx,yy,dxxx,V)
+cout << " Check  ***********" << RTname <<  "\n"; 
+
+{
+fespace Wh1 (Th,RT);
+fespace Ph1 (Th,P1);
+fespace Ph2 (Th,P2dc);
+fespace Kh (Th,P2);
+fespace Eh0 (Th,P1nc);
+Wh1 V(u), V(w);
+
+int err1=0;
+for( int j=0;j<Wh1.ndofK;++j)
+{
+  int i=Wh1(0,j); 
+  u1[] =0;
+  u1[][i]=1;
+  Ph2 U1=u1,U2=u2;
+  U1=u1;
+  U2=u2;
+  cout << j << " " << i << " int K = " << int2d(Th,qforder=3)(u1) << " --- " << int2d(Th,qforder=3)(u2) << "   ---  " << int1d(Th,qforder=2)( u1*N.x + u2*N.y) <<  endl;
+  V(w)=V(u);
+  varf veeee(uu,E) = intalledges(Th)( (nTonEdge==2) *E*( jump(dxxx(u))));
+  real ddcc=intalledges(Th)( (nTonEdge==2) *square( jump(dxxx(u))));
+  if(ddcc > 1e-10) {err1++;  cout << j<< " " << i << " err disc " << ddcc << endl;
+  Eh0 eee; eee[]=veeee(0,Eh0);
+  plot(eee,cmm=" jump ",fill=1,wait=1); 
+   mesh Tg=trunc(Th,1,split=5);
+  fespace WWh(Tg,P2dc);
+  WWh  gu1=u1,gu2=u2;
+   plot([gu1,gu2],wait=1,cmm=" dof "+j+" K=0 ");}
+  w1[][i]-=1;
+  if(w1[].linfty > 1e-10) { w1[][i]+=1;cout << j << " " << i << " diff = "   << w1[] << endl;}
+  cout << " ||w - (\delta_ij)_j=  || " << w1[].linfty << endl;
+  assert( w1[].linfty < 1e-10);
+  NewMacro diff2(op) int2d(Th)(square(op(u1)-op(U1))+square(op(u2)-op(U2))) EndMacro 
+  assert( diff2( 0+ )) ;
+  assert( diff2(dx)) ;
+  assert( diff2(dy)) ;
+
+
+}
+assert(err1==0);
+
+Th=square(5,5,[10*(x+y/3),10*(y-x/3)]);
+V(u)=[0,0];
+V(w)=[0,0];
+
+  func p1=2+x+y*2;
+  func uu1 =  1+xx*p1;
+  func uu2 =  2+yy*p1;
+
+
+ [u1,u2] = [uu1 ,uu2];
+ cout << int2d(Th)( square(uu1-u1) )/ Th.area << endl;
+ cout << int2d(Th)( square(uu2-u2) )/Th.area << endl;
+ plot([u1,u2],wait=1);
+
+for( int i=0;i<Wh1.ndof;++i)
+{
+
+  u1[] =0;
+  u1[][i]=1;
+  V(w)=V(u);
+  w1[][i]-=1;
+  assert( w1[].linfty < 1e-10);
+
+  // FFCS reference value
+  ref=w1[].linfty;
+}
+
+cout << " End  Check  ***********" << RTname <<  " Ok .... \n"; 
+}
+EndMacro
+
+CheckRT(RT1,"RT11",x,y,ccn,V)
+CheckRT(RT1Ortho,"RT1Ortho",-y,x,cctau,V)
+CheckRT(BDM1,"BDM1",x,y,ccn,V)
+CheckRT(BDM1Ortho,"BDM1Ortho",-y,x,cctau,V)
+
+}
diff --git a/examples++-load/testFE-P3.edp b/examples++-load/testFE-P3.edp
new file mode 100644
index 0000000..17f4544
--- /dev/null
+++ b/examples++-load/testFE-P3.edp
@@ -0,0 +1,61 @@
+load "Element_P3"
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+macro DD2(f,hx,hy) ( (-2*f(x1,y1)+f(x1+hx,y1+hy)+f(x1-hx,y1-hy))/(square(hx+hy))) //
+macro dn(f) ( N.x*dx(f)+N.y*dy(f)) //
+macro dnn(f) ( N.x*f#2+N.y*f#3) //
+mesh Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+
+real x1=0.7,y1=0.9, h=1e-4;
+int it1=Th(x1,y1).nuTriangle; 
+
+fespace Vh(Th,P3);
+fespace Eh(Th,P0edge);
+
+Eh  edges;
+
+Vh a1,b1,c1;
+ 
+varf vFlux([a],[e]) = intalledges(Th)( dn(a1)*e*(jump(real(nuTriangle))<= 0));
+varf vMean([a],[e]) = intalledges(Th)( (a1)*e*(jump(real(nuTriangle))<= 0)/lenEdge);
+
+
+for (int i=0;i<Vh.ndofK;++i)
+	cout << i << " -> " << Vh(0,i) << endl;
+for (int i=0;i<Vh.ndofK;++i)
+{
+  cout << " ***  node " << i << " of Traingle " << it1 << endl;
+  a1[]=0;	
+  int j=Vh(it1,i);
+  a1[][j]=1;
+  edges[]=vFlux(0,Eh);
+  cout << "Flux  edges = " << edges[] << endl; 
+  edges[]=vMean(0,Eh);
+  cout << " Mean   edges = " << edges[] << endl; 
+
+  plot(a1, wait=1,cmm="w_"+i); 
+  b1=a1;
+
+  plot(a1,b1,cmm="w"+i, wait=1); 
+
+  c1[] = a1[] - b1[];
+
+  cout << " ---------" << i << " " << c1[].max << " " << c1[].min << endl;	
+  cout << " a = " << a1[] <<endl;
+  cout << " b = " << b1[] <<endl;
+
+  assert(c1[].max < 1e-5 && c1[].min > -1e-9);
+
+  cout << " dx(a1)(x1,y1) = " << dx(a1)(x1,y1) << " == " << DD(a1,h,0) << endl; 
+  cout << " dy(a1)(x1,y1) = " << dy(a1)(x1,y1) << " == " << DD(a1,0,h)  << endl; 
+  cout << " dxx(a1)(x1,y1) = " << dxx(a1)(x1,y1) << " == " << DD2(a1,h,0) << endl; 
+  cout << " dyy(a1)(x1,y1) = " << dyy(a1)(x1,y1) << " == " << DD2(a1,0,h)  << endl; 
+
+  assert( abs(dx(a1)(x1,y1)-DD(a1,h,0) ) < 1e-4);
+  assert( abs(dxx(a1)(x1,y1)-DD2(a1,h,0) ) < 1e-4);
+  assert( abs(dy(a1)(x1,y1)-DD(a1,0,h) ) < 1e-4);
+  assert( abs(dyy(a1)(x1,y1)-DD2(a1,0,h) ) < 1e-4);
+
+
+
+} 
+
diff --git a/examples++-load/testFE-P3dc.edp b/examples++-load/testFE-P3dc.edp
new file mode 100644
index 0000000..455adcc
--- /dev/null
+++ b/examples++-load/testFE-P3dc.edp
@@ -0,0 +1,61 @@
+load "Element_P3dc"
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+macro DD2(f,hx,hy) ( (-2*f(x1,y1)+f(x1+hx,y1+hy)+f(x1-hx,y1-hy))/(square(hx+hy))) //
+macro dn(f) ( N.x*dx(f)+N.y*dy(f)) //
+macro dnn(f) ( N.x*f#2+N.y*f#3) //
+mesh Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+
+real x1=0.7,y1=0.9, h=1e-4;
+int it1=Th(x1,y1).nuTriangle; 
+
+fespace Vh(Th,P3dc);
+fespace Eh(Th,P0edge);
+
+Eh  edges;
+
+Vh a1,b1,c1;
+ 
+varf vFlux([a],[e]) = intalledges(Th)( dn(a1)*e*(jump(real(nuTriangle))<= 0));
+varf vMean([a],[e]) = intalledges(Th)( (a1)*e*(jump(real(nuTriangle))<= 0)/lenEdge);
+
+
+for (int i=0;i<Vh.ndofK;++i)
+	cout << i << " -> " << Vh(0,i) << endl;
+for (int i=0;i<Vh.ndofK;++i)
+{
+  cout << " ***  node " << i << " of Traingle " << it1 << endl;
+  a1[]=0;	
+  int j=Vh(it1,i);
+  a1[][j]=1;
+  edges[]=vFlux(0,Eh);
+  cout << "Flux  edges = " << edges[] << endl; 
+  edges[]=vMean(0,Eh);
+  cout << " Mean   edges = " << edges[] << endl; 
+
+  plot(a1, wait=1,cmm="w_"+i); 
+  b1=a1;
+
+  plot(a1,b1,cmm="w"+i, wait=1); 
+
+  c1[] = a1[] - b1[];
+
+  cout << " ---------" << i << " " << c1[].max << " " << c1[].min << endl;	
+  cout << " a = " << a1[] <<endl;
+  cout << " b = " << b1[] <<endl;
+
+  assert(c1[].max < 1e-5 && c1[].min > -1e-9);
+
+  cout << " dx(a1)(x1,y1) = " << dx(a1)(x1,y1) << " == " << DD(a1,h,0) << endl; 
+  cout << " dy(a1)(x1,y1) = " << dy(a1)(x1,y1) << " == " << DD(a1,0,h)  << endl; 
+  cout << " dxx(a1)(x1,y1) = " << dxx(a1)(x1,y1) << " == " << DD2(a1,h,0) << endl; 
+  cout << " dyy(a1)(x1,y1) = " << dyy(a1)(x1,y1) << " == " << DD2(a1,0,h)  << endl; 
+
+  assert( abs(dx(a1)(x1,y1)-DD(a1,h,0) ) < 1e-4);
+  assert( abs(dxx(a1)(x1,y1)-DD2(a1,h,0) ) < 1e-4);
+  assert( abs(dy(a1)(x1,y1)-DD(a1,0,h) ) < 1e-4);
+  assert( abs(dyy(a1)(x1,y1)-DD2(a1,0,h) ) < 1e-4);
+
+
+
+} 
+
diff --git a/examples++-load/testFE-P4.edp b/examples++-load/testFE-P4.edp
new file mode 100644
index 0000000..377ba3b
--- /dev/null
+++ b/examples++-load/testFE-P4.edp
@@ -0,0 +1,61 @@
+load "Element_P4"
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+macro DD2(f,hx,hy) ( (-2*f(x1,y1)+f(x1+hx,y1+hy)+f(x1-hx,y1-hy))/(square(hx+hy))) //
+macro dn(f) ( N.x*dx(f)+N.y*dy(f)) //
+macro dnn(f) ( N.x*f#2+N.y*f#3) //
+mesh Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+
+real x1=0.7,y1=0.9, h=1e-4;
+int it1=Th(x1,y1).nuTriangle; 
+
+fespace Vh(Th,P4);
+fespace Eh(Th,P0edge);
+
+Eh  edges;
+
+Vh a1,b1,c1;
+ 
+varf vFlux([a],[e]) = intalledges(Th)( dn(a1)*e*(jump(real(nuTriangle))<= 0));
+varf vMean([a],[e]) = intalledges(Th)( (a1)*e*(jump(real(nuTriangle))<= 0)/lenEdge);
+
+
+for (int i=0;i<Vh.ndofK;++i)
+	cout << i << " -> " << Vh(0,i) << endl;
+for (int i=0;i<Vh.ndofK;++i)
+{
+  cout << " ***  node " << i << " of Traingle " << it1 << endl;
+  a1[]=0;	
+  int j=Vh(it1,i);
+  a1[][j]=1;
+  edges[]=vFlux(0,Eh);
+  cout << "Flux  edges = " << edges[] << endl; 
+  edges[]=vMean(0,Eh);
+  cout << " Mean   edges = " << edges[] << endl; 
+
+  plot(a1, wait=1,cmm="w_"+i); 
+  b1=a1;
+
+  plot(a1,b1,cmm="w"+i, wait=1); 
+
+  c1[] = a1[] - b1[];
+
+  cout << " ---------" << i << " " << c1[].max << " " << c1[].min << endl;	
+  cout << " a = " << a1[] <<endl;
+  cout << " b = " << b1[] <<endl;
+
+  assert(c1[].max < 1e-5 && c1[].min > -1e-9);
+
+  cout << " dx(a1)(x1,y1) = " << dx(a1)(x1,y1) << " == " << DD(a1,h,0) << endl; 
+  cout << " dy(a1)(x1,y1) = " << dy(a1)(x1,y1) << " == " << DD(a1,0,h)  << endl; 
+  cout << " dxx(a1)(x1,y1) = " << dxx(a1)(x1,y1) << " == " << DD2(a1,h,0) << endl; 
+  cout << " dyy(a1)(x1,y1) = " << dyy(a1)(x1,y1) << " == " << DD2(a1,0,h)  << endl; 
+
+  assert( abs(dx(a1)(x1,y1)-DD(a1,h,0) ) < 1e-4);
+  assert( abs(dxx(a1)(x1,y1)-DD2(a1,h,0) ) < 1e-4);
+  assert( abs(dy(a1)(x1,y1)-DD(a1,0,h) ) < 1e-4);
+  assert( abs(dyy(a1)(x1,y1)-DD2(a1,0,h) ) < 1e-4);
+
+
+
+} 
+
diff --git a/examples++-load/testFE-P4dc.edp b/examples++-load/testFE-P4dc.edp
new file mode 100644
index 0000000..c61edb3
--- /dev/null
+++ b/examples++-load/testFE-P4dc.edp
@@ -0,0 +1,61 @@
+load "Element_P4dc"
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+macro DD2(f,hx,hy) ( (-2*f(x1,y1)+f(x1+hx,y1+hy)+f(x1-hx,y1-hy))/(square(hx+hy))) //
+macro dn(f) ( N.x*dx(f)+N.y*dy(f)) //
+macro dnn(f) ( N.x*f#2+N.y*f#3) //
+mesh Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+
+real x1=0.7,y1=0.9, h=1e-4;
+int it1=Th(x1,y1).nuTriangle; 
+
+fespace Vh(Th,P4dc);
+fespace Eh(Th,P0edge);
+
+Eh  edges;
+
+Vh a1,b1,c1;
+ 
+varf vFlux([a],[e]) = intalledges(Th)( dn(a1)*e*(jump(real(nuTriangle))<= 0));
+varf vMean([a],[e]) = intalledges(Th)( (a1)*e*(jump(real(nuTriangle))<= 0)/lenEdge);
+
+
+for (int i=0;i<Vh.ndofK;++i)
+	cout << i << " -> " << Vh(0,i) << endl;
+for (int i=0;i<Vh.ndofK;++i)
+{
+  cout << " ***  node " << i << " of Traingle " << it1 << endl;
+  a1[]=0;	
+  int j=Vh(it1,i);
+  a1[][j]=1;
+  edges[]=vFlux(0,Eh);
+  cout << "Flux  edges = " << edges[] << endl; 
+  edges[]=vMean(0,Eh);
+  cout << " Mean   edges = " << edges[] << endl; 
+
+  plot(a1, wait=1,cmm="w_"+i); 
+  b1=a1;
+
+  plot(a1,b1,cmm="w"+i, wait=1); 
+
+  c1[] = a1[] - b1[];
+
+  cout << " ---------" << i << " " << c1[].max << " " << c1[].min << endl;	
+  cout << " a = " << a1[] <<endl;
+  cout << " b = " << b1[] <<endl;
+
+  assert(c1[].max < 1e-5 && c1[].min > -1e-9);
+
+  cout << " dx(a1)(x1,y1) = " << dx(a1)(x1,y1) << " == " << DD(a1,h,0) << endl; 
+  cout << " dy(a1)(x1,y1) = " << dy(a1)(x1,y1) << " == " << DD(a1,0,h)  << endl; 
+  cout << " dxx(a1)(x1,y1) = " << dxx(a1)(x1,y1) << " == " << DD2(a1,h,0) << endl; 
+  cout << " dyy(a1)(x1,y1) = " << dyy(a1)(x1,y1) << " == " << DD2(a1,0,h)  << endl; 
+
+  assert( abs(dx(a1)(x1,y1)-DD(a1,h,0) ) < 1e-4);
+  assert( abs(dxx(a1)(x1,y1)-DD2(a1,h,0) ) < 1e-4);
+  assert( abs(dy(a1)(x1,y1)-DD(a1,0,h) ) < 1e-4);
+  assert( abs(dyy(a1)(x1,y1)-DD2(a1,0,h) ) < 1e-4);
+
+
+
+} 
+
diff --git a/examples++-load/testFE-PkEdge.edp b/examples++-load/testFE-PkEdge.edp
new file mode 100644
index 0000000..69543b2
--- /dev/null
+++ b/examples++-load/testFE-PkEdge.edp
@@ -0,0 +1,65 @@
+load "Element_PkEdge"
+// a macro the compute numerical derivative
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+mesh Th=square(1,1,flags=0,[10*(x+y/3),10*(y-x/3)]);
+Th=square(1,1,flags=0   );
+plot(Th,wait=1);
+//savemesh(Th,"Th.msh");
+real x1=0.4,y1=0.4;//10*(x+y/3),y1=10*(y-x/3), 
+real h=1e-5 ;
+int it1=Th(x1,y1).nuTriangle; 
+
+// FFCS: store reference value
+real regtest;
+
+ macro Check(PkEdge)
+{ 
+  cout << " Test Finite Element " <<endl << endl;
+  fespace Vh(Th,PkEdge);
+
+  Vh a1,b1,c1;
+  c1=x+y;
+  real[int] viso(100);
+  real v0= -100;
+  real dv = 200./(viso.n+1);
+  for(int i=0;i<viso.n;++i)
+     viso[i]=v0+i*dv;
+  plot(c1,fill=1,wait=1,viso=viso);
+  for (int i=0;i<Vh.ndofK;++i)
+    cout << i << " " << Vh(0,i) << endl;
+  for (int i=0;i<Vh.ndofK;++i)
+    {
+      a1[]=0;	
+      int j=Vh(it1,i);
+      a1[][j]=1;
+      plot(a1, wait=1); 
+      b1=a1;/* do the interpolation */
+      
+      
+      c1[] = a1[] - b1[];
+      cout << " ---------" << i << " " << c1[].max << " " << c1[].min << endl;	
+      cout << " a = " << a1[] <<endl;
+      cout << " b = " << b1[] <<endl;
+      assert(c1[].max < 1e-9 && c1[].min > -1e-9); /* check if the interpolation is correct */
+      
+      /*  check the derivative and numerical derivative */
+      /* no derivative in this element.  */
+      
+      
+	cout << " dx(a1)(x1,y1) =  " << dx(a1)(x1,y1) << "  == " 
+	   << DD(a1,h,0) << " DD " << " /  " 
+	   << (a1(0.001,0.001) -  a1(0.999,0.999))/2 <<endl; 
+	assert( abs(dx(a1)(x1,y1)-DD(a1,h,0) ) < 1e-4);
+	assert( abs(dy(a1)(x1,y1)-DD(a1,0,h) ) < 1e-4);
+	/*sassert( abs(dy(a2)(x1,y1)-DD(a2,0,h) ) < 1e-5);*/
+     
+      
+    } 
+  regtest=a1'*a1;
+}  //EOM
+
+Check(P1edge)
+Check(P2edge)
+Check(P3edge)
+Check(P4edge)
+Check(P5edge)
diff --git a/examples++-load/testFE.edp b/examples++-load/testFE.edp
new file mode 100644
index 0000000..40047bf
--- /dev/null
+++ b/examples++-load/testFE.edp
@@ -0,0 +1,42 @@
+load "BernadiRaugel"
+// a macro the compute numerical derivative
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+mesh Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+
+real x1=0.7,y1=0.9, h=1e-7;
+int it1=Th(x1,y1).nuTriangle; 
+
+fespace Vh(Th,P2BR);
+
+Vh [a1,a2],[b1,b2],[c1,c2];
+
+
+for (int i=0;i<Vh.ndofK;++i)
+	cout << i << " " << Vh(0,i) << endl;
+for (int i=0;i<Vh.ndofK;++i)
+{
+  a1[]=0;	
+  int j=Vh(it1,i);
+  a1[][j]=1;
+  plot([a1,a2], wait=1); 
+  [b1,b2]=[a1,a2];// do the interpolation
+
+
+  c1[] = a1[] - b1[];
+  cout << " ---------" << i << " " << c1[].max << " " << c1[].min << endl;	
+  cout << " a = " << a1[] <<endl;
+  cout << " b = " << b1[] <<endl;
+  assert(c1[].max < 1e-9 && c1[].min > -1e-9); // check if the interpolation is correct
+
+ //  check the derivative and numerical derivative
+ 
+
+  cout << " dx(a1)(x1,y1) = " << dx(a1)(x1,y1) << " == " << DD(a1,h,0) << endl; 
+  assert( abs(dx(a1)(x1,y1)-DD(a1,h,0) ) < 1e-5);
+  assert( abs(dx(a2)(x1,y1)-DD(a2,h,0) ) < 1e-5);
+  assert( abs(dy(a1)(x1,y1)-DD(a1,0,h) ) < 1e-5);
+  assert( abs(dy(a2)(x1,y1)-DD(a2,0,h) ) < 1e-5);
+
+
+} 
+
diff --git a/examples++-load/testFEMorley.edp b/examples++-load/testFEMorley.edp
new file mode 100644
index 0000000..6338ee3
--- /dev/null
+++ b/examples++-load/testFEMorley.edp
@@ -0,0 +1,99 @@
+load "Morley"
+macro DD(f,hx,hy) ( (f(x1+hx,y1+hy)-f(x1-hx,y1-hy))/(2*(hx+hy))) //
+macro dn(f) ( N.x*dx(f)+N.y*dy(f)) //
+macro dnn(f) ( N.x*f#2+N.y*f#3) //
+mesh Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+
+real x1=0.7,y1=0.9, h=1e-6;
+int it1=Th(x1,y1).nuTriangle; 
+
+func ff =  2*x*x + 3*y*y + 4.5*y*x + 5*x + 6*y + 7;
+func ffx = 4*x + 4.5*y + 5;
+func ffy = 6*y + 4.5*x + 6;
+func ffxx = 4.;
+func ffyy = 6.;
+func ffxy =4.5;
+
+fespace Vh(Th,P2Morley);
+fespace Eh(Th,P0edge);
+
+Eh  edges;
+
+Vh [a1,a2,a3],[b1,b2,b3],[c1,c2,c3];
+ 
+[a1,a2,a3] = [ ff,ffx,ffy];
+
+ cout << a1(0.6,0.2) << " == " << ff(0.6,0.2) << endl;
+ cout << a2(0.6,0.2) << " == " << ffx(0.6,0.2) << endl;
+  cout << a3(0.6,0.2) << " == " << ffy(0.6,0.2) << endl;
+  cout << dxx(a1)(0.6,0.2) << " xx== " << ffxx(0.6,0.2) << endl;
+  cout << dyy(a1)(0.6,0.2) << " yy== " << ffyy(0.6,0.2) << endl;
+  cout << dxy(a1)(0.6,0.2) << " xy== " << ffxy(0.6,0.2) << endl;
+  cout << dyx(a1)(0.6,0.2) << " yx== " << ffxy(0.6,0.2) << endl;
+ cout << a1(0.2,0.6) << " == " << ff(0.2,0.6) << endl;
+ cout << a2(0.2,0.6) << " == " << ffx(0.2,0.6) << endl;
+  cout << a3(0.2,0.6) << " == " << ffy(0.2,0.6) << endl;
+ cout << " 00 = " << int2d(Th)(square(a1-ff)) << endl;
+ cout << " 00 = " << int2d(Th)(square(a2-ffx)) << endl;
+ cout << " 00 = " << int2d(Th)(square(a3-ffy)) << endl;
+plot(a1,wait=1);
+
+Th=square(1,1,[10*(x+y/3),10*(y-x/3)]);
+
+varf vFlux([a],[e]) = intalledges(Th)( dn(a1)*e*(jump(real(nuTriangle))<= 0));
+varf vMean([a],[e]) = intalledges(Th)( (a1)*e*(jump(real(nuTriangle))<= 0)/lenEdge);
+
+
+for (int i=0;i<Vh.ndofK;++i)
+	cout << i << " -> " << Vh(0,i) << endl;
+for (int i=0;i<Vh.ndofK;++i)
+{
+  cout << " ***  node " << i << " of Traingle " << it1 << endl;
+  a1[]=0;	
+  int j=Vh(it1,i);
+  a1[][j]=1;
+  edges[]=vFlux(0,Eh);
+  cout << "Flux  edges = " << edges[] << endl; 
+  edges[]=vMean(0,Eh);
+  cout << " Mean   edges = " << edges[] << endl; 
+
+  plot(a1, wait=1,cmm="w_"+i); 
+  [b1,b2,b3]=[a1,a2,a3];
+
+  plot(a1,b1,cmm="w"+i, wait=1); 
+
+  c1[] = a1[] - b1[];
+  cout << " int_1 " <<  int1d(Th,1) (dn(a1)) << endl;
+  cout << " int_3 " <<  int1d(Th,3) (dn(a1)) << endl;
+  cout << " int_2 " <<  int1d(Th,2) (dn(a1)) << endl;
+  cout << " int_4 " <<  int1d(Th,4) (dn(a1)) << endl;
+
+  cout << " int_1 " <<  int1d(Th,1) (dnn(a)) << endl;
+  cout << " int_3 " <<  int1d(Th,3) (dnn(a)) << endl;
+  cout << " int_2 " <<  int1d(Th,2) (dnn(a)) << endl;
+  cout << " int_4 " <<  int1d(Th,4) (dnn(a)) << endl;
+
+  cout << " ---------" << i << " " << c1[].max << " " << c1[].min << endl;	
+  cout << " a = " << a1[] <<endl;
+  cout << " b = " << b1[] <<endl;
+
+  assert(c1[].max < 1e-5 && c1[].min > -1e-9);
+
+  cout << " dx(a1)(x1,y1) = " << dx(a1)(x1,y1) << " == " << DD(a1,h,0) << " == " << a2(x1,y1) << endl; 
+  cout << " dy(a1)(x1,y1) = " << dy(a1)(x1,y1) << " == " << DD(a1,0,h) << " == " << a3(x1,y1) << endl; 
+
+  cout << " dx(a2)(x1,y1) = " << dx(a2)(x1,y1) << " == " << DD(a2,h,0)  << " == " << dxx(a1) << endl; 
+  cout << " dy(a2)(x1,y1) = " << dy(a2)(x1,y1) << " == " << DD(a2,0,h)  << " == " << dxy(a1) << endl; 
+  cout << " dx(a3)(x1,y1) = " << dx(a3)(x1,y1) << " == " << DD(a3,h,0)  << " == " << dxy(a1) << endl; 
+  cout << " dy(a3)(x1,y1) = " << dy(a3)(x1,y1) << " == " << DD(a3,0,h)  << " == " << dyy(a1) << endl; 
+
+  assert( abs(dx(a1)(x1,y1)-DD(a1,h,0) ) < 1e-4);
+  assert( abs((a2)(x1,y1)-DD(a1,h,0) ) < 1e-4);
+  assert( abs((a3)(x1,y1)-DD(a1,0,h) ) < 1e-4);
+  assert( abs(dx(a2)(x1,y1)-DD(a2,h,0) ) < 1e-4);
+  assert( abs(dy(a1)(x1,y1)-DD(a1,0,h) ) < 1e-4);
+  assert( abs(dy(a2)(x1,y1)-DD(a2,0,h) ) < 1e-4);
+
+
+} 
+
diff --git a/examples++-load/tetgen.cpp b/examples++-load/tetgen.cpp
new file mode 100644
index 0000000..ecf90e4
--- /dev/null
+++ b/examples++-load/tetgen.cpp
@@ -0,0 +1,2536 @@
+// ORIG-DATE:     Juin 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : liaison medit freefem++ : popen  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep:   tetgen 
+//ff-c++-cpp-dep: 
+//  
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+// $Id$
+
+//  FH   July 2009
+//   comment all
+//       Th3_t->BuildBound();
+//       Th3_t->BuildAdj();
+//       Th3_t->Buildbnormalv();  
+//       Th3_t->BuildjElementConteningVertex();
+//   is now in the constructor of Mesh3 to be consistante. 
+//   
+
+
+#include "ff++.hpp" 
+#include "msh3.hpp"
+#define TETLIBRARY
+#include "tetgen.h"
+
+using namespace  Fem2D;
+
+/*
+// function to return inside point in a volume mesh 
+// A rajouter par la suite //
+void insidepoint( const Mesh3 &Th3
+
+*/
+// subroutine use for tetegen call
+
+void mesh3_tetgenio_out(const tetgenio &out, Mesh3 & Th3);
+
+void mesh3_tetgenio_out(const tetgenio &out, const int & label_tet, Mesh3 & Th3);
+
+void mesh3_tetgenio_out(const tetgenio &out, const int & label_tet, const int & label_face, Mesh3 & Th3);
+
+Mesh3 * mesh3_tetgenio_out(const tetgenio &out);
+
+Mesh3 *mesh3_tetgenio_out(const tetgenio &out, const int & label_tet);
+
+Mesh3 * mesh3_tetgenio_out(const tetgenio &out, const int & label_tet, const int & label_face);
+
+
+Mesh3 * Convexhull_3Dpoints( char* switch_tetgen, const int &nv_t, const double *Xcoord, const double *Ycoord, const double *Zcoord, const int &label_tet);
+
+Mesh3 * RemplissageSurf3D_tetgen( char* switch_tetgen, const Mesh3 & Th3, const int & label_tet);
+
+Mesh3 * RemplissageSurf3D_tetgen_new( char* switch_tetgen, const Mesh3 & Th3, const int & label_tet,
+				  const int &nbhole, const double *tabhole, 
+				  const int & nbregion, const double *tabregion, 
+				  const int &nbfacecl, const double *tabfacecl);
+
+Mesh3 * Transfo_Mesh2_tetgen( const double &precis_mesh, char* switch_tetgen, const Mesh & Th2, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+		int &border_only, int &recollement_border, int &point_confondus_ok, 
+		const int &label_tet,const map<int, int> &maptri );
+
+Mesh3 *Transfo_Mesh2_tetgen_new(const double &precis_mesh, char *switch_tetgen,const Mesh & Th2, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+				 int &border_only, int &recollement_border, int &point_confondus_ok, 
+				 const int &label_tet, const map<int, int> &maptri, 
+				 const int &nbhole, const double *tabhole, 
+				 const int & nbregion, const double *tabregion, 
+				 const int &nbfacecl, const double *tabfacecl);
+
+Mesh3 *  ReconstructionRefine_tetgen(char *switch_tetgen,const Mesh3 & Th3, 
+				     const int &nbhole, const double *tabhole, 
+				     const int & nbregion, const double *tabregion, 
+		                     const int &nbfacecl, const double *tabfacecl, const double *tsizevol);
+
+
+class Build2D3D_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  Expression xx,yy,zz;
+  static const int n_name_param =13+2; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long   arg(int i,Stack stack, long  a) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  string*  arg(int i,Stack stack, string* a) const{ return nargs[i] ? GetAny< string* >( (*nargs[i])(stack) ): a;}
+public:
+  Build2D3D_Op(const basicAC_F0 &  args,Expression tth) 
+    : eTh(tth),xx(0),yy(0),zz(0)
+  {
+    if(verbosity) cout << "construction par BuilLayeMesh_Op" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    const E_Array * a1=0 ;
+    if(nargs[0])  a1  = dynamic_cast<const E_Array *>(nargs[0]);
+    int err =0;
+   
+    if(a1) {
+      if(a1->size() !=3) 
+      CompileError("Build2D3D (Th,transfo=[X,Y,Z],) ");
+      xx=to<double>( (*a1)[0]);
+      yy=to<double>( (*a1)[1]);
+      zz=to<double>( (*a1)[2]);
+    }    
+    if( nargs[2] && nargs[13] ) 
+	CompileError("uncompatible movemesh3 (Th, region= , reftet=  ");
+    if( nargs[3] && nargs[14] ) 
+	CompileError("uncompatible movemesh3 (Th, label= , refface=  ");
+    
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+
+basicAC_F0::name_and_type Build2D3D_Op::name_param[]= {
+  {  "transfo", &typeid(E_Array)},//0
+  {  "switch", &typeid(string*)},
+  {  "reftet", &typeid(long)}, //2
+  {  "refface", &typeid(KN_<long>)},//3
+  {  "facemerge", &typeid(long)},
+  {  "ptmerge", &typeid(double)},
+  // nouvelle variable
+  {  "nbofholes", &typeid(long)},//6
+  {  "holelist", &typeid(KN_<double>)},
+  {  "nbofregions", &typeid(long)},
+  {  "regionlist", &typeid(KN_<double>)},
+  {  "nboffacetcl", &typeid(long)},
+  {  "facetcl", &typeid(KN_<double>)},//11
+  // mesure mesh
+  {  "mesuremesh", &typeid(long)},
+  {  "region", &typeid(long)}, //13
+  {  "label", &typeid(KN_<long>)}//14
+    
+};
+
+class  Build2D3D : public OneOperator { public:  
+    Build2D3D() : OneOperator(atype<pmesh3>(),atype<pmesh>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+	return  new Build2D3D_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+AnyType Build2D3D_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh * pTh= GetAny<Mesh *>((*eTh)(stack));
+  ffassert( pTh );
+  Mesh &Th=*pTh;
+  Mesh *m= pTh;   // question a quoi sert *m ??
+  int nbv=Th.nv; // nombre de sommet 
+
+  int nbt=Th.nt; // nombre de triangles
+  int neb=Th.neb; // nombre d'aretes fontiere
+  if(verbosity) cout << " Vertex Triangle Border " << nbv<< "  "<< nbt << " " << neb << endl; 
+
+  if(verbosity >1) cout <<" ======================= " << endl;
+  if(verbosity >1) cout <<" == Build2D_3D_Op==" << endl;
+ 
+  KN<long> zzempty;
+  string  stringempty = string("pqaAAYCQ");
+  string* switch_tet= (arg(1,stack,&stringempty));  
+  int label_tet(arg(2,stack,arg(13,stack,0L)));  
+  KN<long> nrf (arg(3,stack,arg(14,stack,zzempty)));
+  int point_confondus_ok(arg(4,stack,0L));
+  double precis_mesh(arg(5,stack,-1.));
+
+  // new parameters
+  KN<double> zdzempty;
+  int nbhole (arg(6,stack,0L));
+  KN<double> tabhole (arg(7,stack,zdzempty));
+  int nbregion (arg(8,stack,0L));
+  KN<double> tabregion (arg(9,stack,zdzempty));
+  int nbfacecl (arg(10,stack,0L));
+  KN<double> tabfacecl (arg(11,stack,zdzempty));
+  if(nbhole && nbhole*3 != tabhole.N())
+    {ExecError(" nbhole and holes are incompatibale ");}
+  if(!nbhole) nbhole=tabhole.N()/3; // modif FH dec 2010...
+  // mesuremesh parameters
+  int mesureM(arg(12,stack,1L));
+  int surface_orientation=1; 
+  if( mesureM <0 ){
+    surface_orientation=-1;
+  }
+    
+    
+    if(nbregion==0) nbregion=tabregion.N()/5;
+    if(nbhole==0) nbhole=tabhole.N()/3;
+    if(nbfacecl==0) nbfacecl=tabfacecl.N()/2;
+    
+  // assertion au niveau de la taille
+  ffassert( tabhole.N()   == 3*nbhole);
+  ffassert( tabregion.N() == 5*nbregion);
+  ffassert( tabfacecl.N() == 2*nbfacecl);
+
+  //====================================
+  //  How to change string* into char* 
+  //====================================
+  cout << "string" << switch_tet << endl; 
+
+  size_t size_switch_tet = switch_tet->size()+1;
+  char* switch_tetgen =new char[size_switch_tet];
+  strncpy(switch_tetgen, switch_tet->c_str(), size_switch_tet); 
+
+  cout << "switch_tetgen=" << switch_tetgen << endl;
+  //exit(1);
+  ffassert( nrf.N() %2 ==0);
+  
+  map<int,int> mapf;
+  for(int i=0;i<nrf.N();i+=2)
+    {
+      if(nrf[i] != nrf[i+1]){
+	mapf[nrf[i]]=nrf[i+1];
+      }
+    }
+  
+  map<int, int> mapfme;  
+  
+  Transfo_Mesh2_map_face( Th, mapfme );  
+  
+  // Map utilisateur
+  map< int, int > :: iterator imap;
+  for( int ii=0; ii < nrf.N(); ii+=2){
+	imap = mapfme.find(nrf[ii]);
+	if( imap != mapfme.end()){
+		imap -> second = nrf[ii+1];
+	}
+  }  
+  
+  //KN<double> txx(nbv), tyy(nbv), tzz(nbv);
+  //KN<int> takemesh(nbv);
+  double *txx=new double[nbv];
+  double *tyy=new double[nbv];
+  double *tzz=new double[nbv];
+  int *takemesh=new int[nbv];
+
+  MeshPoint *mp3(MeshPointStack(stack)); 
+  
+  for(int ii=0; ii<nbv; ii++) 
+      takemesh[ii]=0;  
+
+  Mesh &rTh = Th;
+  for (int it=0; it<nbt; ++it){
+    for( int iv=0; iv<3; ++iv){
+      int i=Th(it,iv);
+      if(takemesh[i]==0){
+	mp3->setP(&Th,it,iv);
+	if(xx){ 
+	  txx[i]=GetAny<double>((*xx)(stack));
+	}
+	if(yy){ 
+	  tyy[i]=GetAny<double>((*yy)(stack));
+	}
+	if(zz){ 
+	  tzz[i]=GetAny<double>((*zz)(stack));
+	}
+	takemesh[i] = takemesh[i]+1;
+      }
+    }
+  }
+
+  delete [] takemesh;
+  int border_only = 0;
+  int recollement_border=1;
+  /*
+    Mesh3 *Th3=Transfo_Mesh2_tetgen( precis_mesh, switch_tetgen, Th, txx, tyy, tzz, border_only, 
+				   recollement_border, point_confondus_ok, label_tet, mapfme);  
+  */
+
+  Mesh3 *Th3_tmp = MoveMesh2_func( precis_mesh, Th, txx, tyy, tzz, border_only, recollement_border, point_confondus_ok);
+
+  /* delete array */
+  delete [] txx;
+  delete [] tyy;
+  delete [] tzz;
+
+  /* check orientation of the mesh and flip if necessary*/ 
+  Th3_tmp->flipSurfaceMesh3(surface_orientation);
+  
+  int addcheckorientation=0;
+  if( addcheckorientation==1  ){
+    cout << "check :: orientation des surfaces" << endl;
+    Th3_tmp->BuildBoundaryElementAdj();
+    cout << "fin check :: orientation des surfaces" << endl;
+  }
+  /* set label of surface Th3_tmp */
+  for(int ii=0; ii< Th3_tmp->nbe; ii++)
+    {
+      const Triangle3 & K(Th3_tmp->be(ii)); 
+      int iv[3];
+      int lab;
+     
+      iv[0] = Th3_tmp->operator()(K[0]);
+      iv[1] = Th3_tmp->operator()(K[1]);
+      iv[2] = Th3_tmp->operator()(K[2]);
+		
+      map< int, int>:: const_iterator imap;
+      imap = mapfme.find(K.lab); 
+		
+      if(imap!= mapfme.end()){
+	lab=imap->second;	
+      } 
+      else{
+	lab=K.lab;
+      }
+		
+      Th3_tmp->be(ii).set( Th3_tmp->vertices, iv, lab ) ;
+    }
+  /* mesh domains with tetgen */ 
+  Mesh3 *Th3 = RemplissageSurf3D_tetgen_new( switch_tetgen, *Th3_tmp, label_tet,
+					     nbhole, tabhole, nbregion, tabregion, 
+					     nbfacecl, tabfacecl);
+
+
+  /*
+  Mesh3 *Th3=Transfo_Mesh2_tetgen_new( precis_mesh, switch_tetgen, Th, txx, tyy, tzz, border_only, 
+				   recollement_border, point_confondus_ok, label_tet, mapfme, 
+				   nbhole, tabhole, nbregion, tabregion, nbfacecl,tabfacecl);
+
+  */
+
+  delete Th3_tmp;
+  
+//Th3->BuildBound();
+//  Th3->BuildAdj();
+//  Th3->Buildbnormalv();  
+//  Th3->BuildjElementConteningVertex();
+  Th3->BuildGTree();
+  //Th3->decrement();    
+  Add2StackOfPtr2FreeRC(stack,Th3);
+
+  delete [] switch_tetgen;
+		
+  *mp=mps;
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return Th3;
+}
+
+// Fonction pour tetgen
+// new parameter
+void mesh3_tetgenio_out(const tetgenio &out, Mesh3 & Th3)
+{ 
+  int i;
+
+// All indices start from 1.
+  if(out.firstnumber != 1){
+    cout << " probleme ???" << endl;
+    exit(1);
+  }   
+  
+  if(out.numberoffacets !=0){
+    cout << "tetgen: faces non triangulaire" << endl;
+    exit(1);
+  }
+  
+  if(out.numberofcorners !=4){
+    cout << "tetgen: element subparametric of order 2" <<endl;
+    exit(1);
+  }
+
+  cout << "Th3 :: Vertex Element Border :: " << out.numberofpoints << " " <<out.numberoftetrahedra  << " " << out.numberoftrifaces << endl;
+  Th3.set(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces);
+
+  // new parameter
+  if( out.numberoftetrahedronattributes !=  1){
+    cout << "out.numberoftetrahedronattributes" << out.numberoftetrahedronattributes << endl;
+  }
+   
+  i=0;
+  for(int nnv=0; nnv < Th3.nv; nnv++){
+    Th3.vertices[nnv].x=out.pointlist[i];
+    Th3.vertices[nnv].y=out.pointlist[i+1];
+    Th3.vertices[nnv].z=out.pointlist[i+2];       
+    Th3.vertices[nnv].lab=out.pointmarkerlist[nnv];
+    i=i+3;    
+  }
+    
+  i=0;
+  for(int nnt=0; nnt < Th3.nt; nnt++){
+    int iv[4],lab;
+    iv[0] = out.tetrahedronlist[i]-1;
+    iv[1] = out.tetrahedronlist[i+1]-1;
+    iv[2] = out.tetrahedronlist[i+2]-1;
+    iv[3] = out.tetrahedronlist[i+3]-1;
+    //lab   = label_tet;
+    for(int jj=0; jj<4; jj++){
+      assert( iv[jj] >=0 && iv[jj] <Th3.nv );
+    }
+    //cout << "nnt= " <<  nnt << " " << lab  << " " << out.tetrahedronattributelist[nnt] << endl;
+    lab =  out.tetrahedronattributelist[nnt];
+    //cout << "nnt= " <<  lab  << " " << out.tetrahedronattributelist[nnt] << endl;
+      
+    Th3.elements[nnt].set( Th3.vertices, iv, lab);
+    i=i+4;
+  }
+ 
+  for(int ibe=0; ibe < Th3.nbe; ibe++){
+    int iv[3];
+    iv[0] = out.trifacelist[3*ibe]-1;
+    iv[1] = out.trifacelist[3*ibe+1]-1;
+    iv[2] = out.trifacelist[3*ibe+2]-1; 
+    for(int jj=0; jj<3; jj++){
+      if(iv[jj]>= Th3.nv || iv[jj]< 0 ) cout << "iv[jj]=" << iv[jj] << " triangle" << ibe << endl;
+      assert( iv[jj] >=0 && iv[jj] <Th3.nv );
+    }
+    Th3.be(ibe).set( Th3.vertices, iv, out.trifacemarkerlist[ibe]);
+  }
+
+  /*
+  if( out.numberoftetrahedronattributes != 1 ){
+    cout << "out.numberoftetrahedronattributes" << out.numberoftetrahedronattributes  << endl;
+    exit(1);
+   }
+  */
+}
+
+
+void mesh3_tetgenio_out(const tetgenio &out, const int & label_tet, Mesh3 & Th3)
+{ 
+  int i;
+
+// All indices start from 1.
+  if(out.firstnumber != 1){
+    cout << " probleme ???" << endl;
+    exit(1);
+  }   
+  
+  if(out.numberoffacets !=0){
+    cout << "tetgen: faces non triangulaire" << endl;
+    exit(1);
+  }
+  
+  if(out.numberofcorners !=4){
+    cout << "tetgen: element subparametric of order 2" <<endl;
+    exit(1);
+  }
+  
+  cout << "Th3 :: Vertex Element Border :: " << out.numberofpoints << " " <<out.numberoftetrahedra  << " " << out.numberoftrifaces << endl;
+  Th3.set(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces);
+   
+  i=0;
+  for(int nnv=0; nnv < Th3.nv; nnv++){
+    Th3.vertices[nnv].x=out.pointlist[i];
+    Th3.vertices[nnv].y=out.pointlist[i+1];
+    Th3.vertices[nnv].z=out.pointlist[i+2];       
+    Th3.vertices[nnv].lab=out.pointmarkerlist[nnv];
+    i=i+3;    
+  }
+    
+  i=0;
+  for(int nnt=0; nnt < Th3.nt; nnt++){
+    int iv[4],lab;
+    iv[0] = out.tetrahedronlist[i]-1;
+    iv[1] = out.tetrahedronlist[i+1]-1;
+    iv[2] = out.tetrahedronlist[i+2]-1;
+    iv[3] = out.tetrahedronlist[i+3]-1;
+    lab   = label_tet;
+    //lab = out.tetrahedronmarkerlist[nnt];
+    Th3.elements[nnt].set( Th3.vertices, iv, lab);
+    i=i+4;
+  }
+ 
+  for(int ibe=0; ibe < Th3.nbe; ibe++){
+    int iv[3];
+    iv[0] = out.trifacelist[3*ibe]-1;
+    iv[1] = out.trifacelist[3*ibe+1]-1;
+    iv[2] = out.trifacelist[3*ibe+2]-1; 
+    Th3.be(ibe).set( Th3.vertices, iv, out.trifacemarkerlist[ibe]);
+  }
+
+}
+
+void mesh3_tetgenio_out(const tetgenio &out, const int & label_tet, const int & label_face, Mesh3 & Th3)
+{ 
+  int i;
+
+// All indices start from 1.
+  if(out.firstnumber != 1){
+    cout << " probleme ???" << endl;
+    exit(1);
+  }   
+  
+  if(out.numberoffacets !=0){
+    cout << "tetgen: faces non triangulaire" << endl;
+    exit(1);
+  }
+  
+  if(out.numberofcorners !=4){
+    cout << "tetgen: element subparametric of order 2" <<endl;
+    exit(1);
+  }
+  
+  cout << "Th3 :: Vertex Element Border :: " << out.numberofpoints << " " <<out.numberoftetrahedra  << " " << out.numberoftrifaces << endl;
+  Th3.set(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces);
+   
+  i=0;
+  for(int nnv=0; nnv < Th3.nv; nnv++){
+    Th3.vertices[nnv].x=out.pointlist[i];
+    Th3.vertices[nnv].y=out.pointlist[i+1];
+    Th3.vertices[nnv].z=out.pointlist[i+2];       
+    Th3.vertices[nnv].lab=out.pointmarkerlist[nnv];
+    i=i+3;    
+  }
+    
+  i=0;
+  for(int nnt=0; nnt < Th3.nt; nnt++){
+    int iv[4],lab;
+    iv[0] = out.tetrahedronlist[i]-1;
+    iv[1] = out.tetrahedronlist[i+1]-1;
+    iv[2] = out.tetrahedronlist[i+2]-1;
+    iv[3] = out.tetrahedronlist[i+3]-1;
+    lab   = label_tet;
+    //lab = out.tetrahedronmarkerlist[nnt];
+    Th3.elements[nnt].set( Th3.vertices, iv, lab);
+    i=i+4;
+  }
+
+  if(verbosity) cout << &out.trifacemarkerlist << endl;
+  
+  for(int ibe=0; ibe < Th3.nbe; ibe++){
+    int iv[3];
+    iv[0] = out.trifacelist[3*ibe]-1;
+    iv[1] = out.trifacelist[3*ibe+1]-1;
+    iv[2] = out.trifacelist[3*ibe+2]-1; 
+    Th3.be(ibe).set( Th3.vertices, iv, label_face);
+  }
+
+}
+// verison Mesh3 *
+
+Mesh3 * mesh3_tetgenio_out(const tetgenio &out)
+{ 
+  int i;
+
+// All indices start from 1.
+  if(out.firstnumber != 1){
+    cout << " probleme ???" << endl;
+    exit(1);
+  }   
+  
+  if(out.numberoffacets !=0){
+    cout << "tetgen: faces non triangulaire" << endl;
+    exit(1);
+  }
+  
+  if(out.numberofcorners !=4){
+    cout << "tetgen: element subparametric of order 2" <<endl;
+    exit(1);
+  }
+
+  cout << "Th3 :: Vertex Element Border :: " << out.numberofpoints << " " <<out.numberoftetrahedra  << " " << out.numberoftrifaces << endl;
+  //Th3.set(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces);
+
+  // new parameter
+  if( out.numberoftetrahedronattributes !=  1){
+    cout << "out.numberoftetrahedronattributes" << out.numberoftetrahedronattributes << endl;
+  }
+   
+  Vertex3 *v = new Vertex3[out.numberofpoints];
+  Tet *t  = new Tet[out.numberoftetrahedra];
+  Tet *tt = t;
+  Triangle3 *b  = new Triangle3[out.numberoftrifaces];
+  Triangle3 *bb = b;
+
+  i=0;
+  for(int nnv=0; nnv<out.numberofpoints; nnv++){
+    v[nnv].x=out.pointlist[i];
+    v[nnv].y=out.pointlist[i+1];
+    v[nnv].z=out.pointlist[i+2];       
+    v[nnv].lab=out.pointmarkerlist[nnv];
+    i=i+3;    
+  }
+
+  // test pour la distance minimale entre les points 
+//   {
+//     double dist,dist1;
+//     dist = 1000000000000.;
+//     for(int nnv=0; nnv<out.numberofpoints; nnv++){
+//       for(int nnv1=nnv+1; nnv1< out.numberofpoints; nnv1++){
+// 	dist1=(v[nnv].x-v[nnv1].x)*(v[nnv].x-v[nnv1].x)+(v[nnv].y-v[nnv1].y)*(v[nnv].y-v[nnv1].y)
+// 	  +(v[nnv].z-v[nnv1].z)*(v[nnv].z-v[nnv1].z);
+// 	dist=min(dist,sqrt(dist1));
+// 	if( sqrt(dist1) < 1e-12){ 
+// 	  cout << "point confondus" << nnv << "<--->" <<nnv1 << endl;
+// 	  if( sqrt( pow(v[nnv].x,2)+pow(v[nnv].y,2)+pow(v[nnv].z,2) ) > 1e-10   )  cout << v[nnv] << " " << v[nnv1] << endl;
+// 	}
+//       }
+//     }
+//     cout << "dist entre les points du maillage tetgen" << dist << endl;
+//   }
+    
+  i=0;
+  for(int nnt=0; nnt < out.numberoftetrahedra; nnt++){
+    int iv[4],lab;
+    iv[0] = out.tetrahedronlist[i]-1;
+    iv[1] = out.tetrahedronlist[i+1]-1;
+    iv[2] = out.tetrahedronlist[i+2]-1;
+    iv[3] = out.tetrahedronlist[i+3]-1;
+    //lab   = label_tet;
+    for(int jj=0; jj<4; jj++){
+      assert( iv[jj] >=0 && iv[jj] < out.numberofpoints );
+    }
+    
+    //cout << "nnt= " <<  nnt << " " << lab  << " " << out.tetrahedronattributelist[nnt] << endl;
+    lab =  out.tetrahedronattributelist[nnt];
+    //cout << "nnt= " <<  lab  << " " << out.tetrahedronattributelist[nnt] << endl;
+    //Th3.elements[nnt].set( Th3.vertices, iv, lab);
+    (*tt++).set( v, iv, lab);   
+    i=i+4;
+  }
+ 
+  for(int ibe=0; ibe < out.numberoftrifaces; ibe++){
+    int iv[3];
+    iv[0] = out.trifacelist[3*ibe]-1;
+    iv[1] = out.trifacelist[3*ibe+1]-1;
+    iv[2] = out.trifacelist[3*ibe+2]-1; 
+    for(int jj=0; jj<3; jj++){
+      if(iv[jj]>= out.numberofpoints || iv[jj]< 0 ) cout << "iv[jj]=" << iv[jj] << " triangle" << ibe << endl;
+      assert( iv[jj] >=0 && iv[jj] < out.numberofpoints );
+    }
+    //Th3.be(ibe).set( Th3.vertices, iv, out.trifacemarkerlist[ibe]);
+    (*bb++).set( v, iv, out.trifacemarkerlist[ibe]);   
+  }
+
+  Mesh3 *T_TH3 = new Mesh3(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces, v, t, b);
+  cout << "FreeFem++: Check mesh given by tetgen" << endl;
+  //return T_TH3;
+
+  if( TestElementMesh3(*T_TH3) != 1){  
+    return T_TH3;
+  }
+  else{
+    //Mesh3 *T2_TH3 = TestElementMesh3_patch( *T_TH3 );
+    //return T2_TH3;
+    exit(1);
+  }
+
+}
+
+
+Mesh3* mesh3_tetgenio_out(const tetgenio &out, const int & label_tet)
+{ 
+  int i;
+
+// All indices start from 1.
+  if(out.firstnumber != 1){
+    cout << " probleme ???" << endl;
+    exit(1);
+  }   
+  
+  if(out.numberoffacets !=0){
+    cout << "tetgen: faces non triangulaire" << endl;
+    exit(1);
+  }
+  
+  if(out.numberofcorners !=4){
+    cout << "tetgen: element subparametric of order 2" <<endl;
+    exit(1);
+  }
+  
+  cout << "Th3 :: Vertex Element Border :: " << out.numberofpoints << " " <<out.numberoftetrahedra  << " " << out.numberoftrifaces << endl;
+  //Th3.set(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces);
+   
+  Vertex3 *v = new Vertex3[out.numberofpoints];
+  Tet *t  = new Tet[out.numberoftetrahedra];
+  Tet *tt = t;
+  Triangle3 *b  = new Triangle3[out.numberoftrifaces];
+  Triangle3 *bb = b;
+    
+   
+  i=0;
+  for(int nnv=0; nnv < out.numberofpoints ; nnv++){
+    v[nnv].x=out.pointlist[i];
+    v[nnv].y=out.pointlist[i+1];
+    v[nnv].z=out.pointlist[i+2];       
+    v[nnv].lab=out.pointmarkerlist[nnv];
+    i=i+3;    
+  }
+    
+  i=0;
+  for(int nnt=0; nnt < out.numberoftetrahedra; nnt++){
+    int iv[4],lab;
+    iv[0] = out.tetrahedronlist[i]-1;
+    iv[1] = out.tetrahedronlist[i+1]-1;
+    iv[2] = out.tetrahedronlist[i+2]-1;
+    iv[3] = out.tetrahedronlist[i+3]-1;
+    lab   = label_tet;
+    //lab = out.tetrahedronmarkerlist[nnt];
+    //Th3.elements[nnt].set( Th3.vertices, iv, lab);
+    (*tt++).set( v, iv, lab);   
+    i=i+4;
+  }
+ 
+  for(int ibe=0; ibe < out.numberoftrifaces ; ibe++){
+    int iv[3];
+    iv[0] = out.trifacelist[3*ibe]-1;
+    iv[1] = out.trifacelist[3*ibe+1]-1;
+    iv[2] = out.trifacelist[3*ibe+2]-1; 
+    //Th3.be(ibe).set( Th3.vertices, iv, out.trifacemarkerlist[ibe]);
+    (*bb++).set( v, iv, out.trifacemarkerlist[ibe]);  
+  }
+  Mesh3 *T_TH3 = new Mesh3(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces, v, t, b);
+  //return T_TH3;
+  cout << "FreeFem++: Check mesh given by tetgen" << endl;
+  if( TestElementMesh3(*T_TH3) != 1){  
+    return T_TH3;
+  }
+  else{ 
+    //cout << "patch pour tetgen " << endl;
+    //Mesh3 *T2_TH3 = TestElementMesh3_patch( *T_TH3 );
+    //return T2_TH3;
+    exit(1);
+  }
+}
+
+Mesh3* mesh3_tetgenio_out(const tetgenio &out, const int & label_tet, const int & label_face)
+{ 
+  int i;
+
+// All indices start from 1.
+  if(out.firstnumber != 1){
+    cout << " probleme ???" << endl;
+    exit(1);
+  }   
+  
+  if(out.numberoffacets !=0){
+    cout << "tetgen: faces non triangulaire" << endl;
+    exit(1);
+  }
+  
+  if(out.numberofcorners !=4){
+    cout << "tetgen: element subparametric of order 2" <<endl;
+    exit(1);
+  }
+  
+  cout << "Th3 :: Vertex Element Border :: " << out.numberofpoints << " " <<out.numberoftetrahedra  << " " << out.numberoftrifaces << endl;
+  //Th3.set(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces);
+
+  Vertex3 *v = new Vertex3[out.numberofpoints];
+  Tet *t  = new Tet[out.numberoftetrahedra];
+  Tet *tt = t;
+  Triangle3 *b  = new Triangle3[out.numberoftrifaces];
+  Triangle3 *bb = b;
+
+  i=0;
+  for(int nnv=0; nnv < out.numberofpoints; nnv++){
+    v[nnv].x=out.pointlist[i];
+    v[nnv].y=out.pointlist[i+1];
+    v[nnv].z=out.pointlist[i+2];       
+    v[nnv].lab=out.pointmarkerlist[nnv];
+    i=i+3;    
+  }
+    
+  i=0;
+  for(int nnt=0; nnt < out.numberoftetrahedra; nnt++){
+    int iv[4],lab;
+    iv[0] = out.tetrahedronlist[i]-1;
+    iv[1] = out.tetrahedronlist[i+1]-1;
+    iv[2] = out.tetrahedronlist[i+2]-1;
+    iv[3] = out.tetrahedronlist[i+3]-1;
+    lab   = label_tet;
+    //lab = out.tetrahedronmarkerlist[nnt];
+    //Th3.elements[nnt].set( Th3.vertices, iv, lab);
+    (*tt++).set( v, iv, lab); 
+    i=i+4;
+  }
+
+  if(verbosity) cout << &out.trifacemarkerlist << endl;
+  
+  for(int ibe=0; ibe < out.numberoftrifaces ; ibe++){
+    int iv[3];
+    iv[0] = out.trifacelist[3*ibe]-1;
+    iv[1] = out.trifacelist[3*ibe+1]-1;
+    iv[2] = out.trifacelist[3*ibe+2]-1; 
+    //Th3.be(ibe).set( Th3.vertices, iv, label_face);
+    (*bb++).set( v, iv, label_face);  
+  }
+
+  Mesh3 *T_TH3 = new Mesh3(out.numberofpoints, out.numberoftetrahedra, out.numberoftrifaces, v, t, b);
+
+  if( TestElementMesh3( *T_TH3 ) != 1){  
+    return T_TH3;
+  }
+  else{
+    exit(1);
+    //Mesh3 *T2_TH3 = TestElementMesh3_patch( *T_TH3 );
+    //return T2_TH3;
+  }
+}
+
+
+
+Mesh3 * Convexhull_3Dpoints(char *switch_tetgen, const int &nv_t, const double *Xcoord, const double *Ycoord, 
+const double *Zcoord, const int &label_tet, const int &label_face){
+	
+  //Mesh3 *T_Th3= new Mesh3;
+		
+  tetgenio in,out;
+  //tetgenio::facet *f;
+  //tetgenio::polygon *p;
+
+  cout << " tetgenio: vertex " << endl;
+  int itet,jtet;
+
+  in.firstnumber = 1;
+  in.numberofpoints = nv_t;
+  in.pointlist = new REAL[in.numberofpoints*3];
+  in.pointmarkerlist = new int[in.numberofpoints];
+  itet=0;
+  jtet=0;
+  for(int nnv=0; nnv < nv_t; nnv++)
+    {
+      in.pointlist[itet]   = Xcoord[nnv];
+      in.pointlist[itet+1] = Ycoord[nnv];
+      in.pointlist[itet+2] = Zcoord[nnv];       
+      in.pointmarkerlist[nnv] =  0;
+      
+      itet=itet+3;
+    }
+  assert(itet==in.numberofpoints*3);
+	
+  in.numberoffacets = 0;
+
+  cout << "tetgen: before tetrahedralize( , &in, &out): switch=" << switch_tetgen<< endl;
+  tetrahedralize(switch_tetgen, &in, &out);
+	 
+  cout << "tetgen: finish tetrahedralize( , &in, &out);" << endl;
+  //mesh3_tetgenio_out( out, label_tet, label_face,*T_Th3);
+  Mesh3* T_Th3=mesh3_tetgenio_out( out, label_tet, label_face);
+  cout <<" Finish Mesh3 tetgen :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return T_Th3; 
+}
+
+
+Mesh3 * RemplissageSurf3D_tetgen(char *switch_tetgen,const Mesh3 & Th3, const int & label_tet){
+	
+  //Mesh3 *T_Th3= new Mesh3;
+	
+  assert(Th3.nt == 0 );
+  int nv_t = Th3.nv;
+  int nt_t = Th3.nt;
+  int nbe_t = Th3.nbe;
+	
+  if(verbosity) cout << "3D RemplissageSurf3D:: Vertex  triangle2  border "    << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+  
+
+  // Creation des tableau de tetgen
+	
+  tetgenio in,out;
+  //tetgenio::facet *f;
+  //tetgenio::polygon *p;
+	
+  if(verbosity) cout << " tetgenio: vertex " << endl;
+  int itet,jtet;
+  // All indices start from 1.
+  in.firstnumber = 1;
+  in.numberofpoints = nv_t;
+  in.pointlist = new REAL[in.numberofpoints*3];
+  in.pointmarkerlist = new int[in.numberofpoints];
+  itet=0;
+  jtet=0;
+  for(int nnv=0; nnv < nv_t; nnv++)
+    {
+      in.pointlist[itet]   = Th3.vertices[nnv].x;
+      in.pointlist[itet+1] = Th3.vertices[nnv].y;
+      in.pointlist[itet+2] = Th3.vertices[nnv].z;       
+      in.pointmarkerlist[nnv] =  Th3.vertices[nnv].lab;   
+      itet=itet+3;
+    }
+  assert(itet==in.numberofpoints*3);
+	
+  if(verbosity) cout << " tetgenio: facet " << endl;
+  // Version avec des facettes
+  in.numberoffacets = nbe_t;
+  in.facetlist = new tetgenio::facet[in.numberoffacets];
+  in.facetmarkerlist = new int[in.numberoffacets];
+	  
+  for(int ibe=0; ibe < nbe_t; ibe++){
+    tetgenio::facet *f;
+    tetgenio::polygon *p;
+    f = &in.facetlist[ibe];
+    f->numberofpolygons = 1;
+    f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
+    f->numberofholes = 0;
+    f->holelist = NULL;
+		
+    p = &f->polygonlist[0];
+    p->numberofvertices = 3;
+    p->vertexlist = new int[3];
+		
+    // creation of elements
+    const Triangle3 & K(Th3.be(ibe)); // const Triangle2 & K(Th2.elements[ii]); // Version Mesh2  
+    p->vertexlist[0] = Th3.operator()(K[0])+1;
+    p->vertexlist[1] = Th3.operator()(K[1])+1;
+    p->vertexlist[2] = Th3.operator()(K[2])+1;
+		
+    for( int kkk=0; kkk<3; kkk++){ 
+      assert( p->vertexlist[kkk]<= in.numberofpoints && p->vertexlist[kkk]>0);
+    }
+		
+    in.facetmarkerlist[ibe] = K.lab; 
+		
+  }  
+  cout << "tetgen: before tetrahedralize( , &in, &out);" << endl;
+	
+  tetrahedralize(switch_tetgen, &in, &out);
+	 
+  cout << "tetgen: after tetrahedralize( , &in, &out);" << endl;
+  //mesh3_tetgenio_out( out, label_tet, *T_Th3);
+  Mesh3 *T_Th3 = mesh3_tetgenio_out( out, label_tet);
+  cout <<" Finish Mesh3 tetgen :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return T_Th3;
+}
+
+Mesh3 * RemplissageSurf3D_tetgen_new(char *switch_tetgen,const Mesh3 & Th3, const int & label_tet,
+				     const int &nbhole, const double *tabhole, 
+				     const int & nbregion, const double *tabregion, 
+				     const int &nbfacecl, const double *tabfacecl){
+	
+  //Mesh3 *T_Th3= new Mesh3;
+	
+  assert(Th3.nt == 0 );
+  int nv_t = Th3.nv;
+  int nt_t = Th3.nt;
+  int nbe_t = Th3.nbe;
+
+ 
+  if(verbosity) cout << "3D RemplissageSurf3D:: Vertex  triangle2  border " << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+  // Creation des tableau de tetgen
+	
+  tetgenio in,out;
+  //tetgenio::facet *f;
+  //tetgenio::polygon *p;
+	
+  if(verbosity) cout << " tetgenio: vertex " << endl;
+  int itet,jtet;
+  // All indices start from 1.
+  in.firstnumber = 1;
+  in.numberofpoints = nv_t;
+  in.pointlist = new REAL[in.numberofpoints*3];
+  in.pointmarkerlist = new int[in.numberofpoints];
+  itet=0;
+  jtet=0;
+  for(int nnv=0; nnv < nv_t; nnv++)
+    {
+      in.pointlist[itet]   = Th3.vertices[nnv].x;
+      in.pointlist[itet+1] = Th3.vertices[nnv].y;
+      in.pointlist[itet+2] = Th3.vertices[nnv].z;       
+      in.pointmarkerlist[nnv] =  Th3.vertices[nnv].lab;   
+      itet=itet+3;
+    }
+  assert(itet==in.numberofpoints*3);
+	
+  if(verbosity) cout << " tetgenio: facet " << endl;
+  // Version avec des facettes
+  in.numberoffacets = nbe_t;
+  in.facetlist = new tetgenio::facet[in.numberoffacets];
+  in.facetmarkerlist = new int[in.numberoffacets];
+	  
+  for(int ibe=0; ibe < nbe_t; ibe++){
+    tetgenio::facet *f;
+    tetgenio::polygon *p;
+    f = &in.facetlist[ibe];
+    f->numberofpolygons = 1;
+    f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
+    f->numberofholes = 0;
+    f->holelist = NULL;
+		
+    p = &f->polygonlist[0];
+    p->numberofvertices = 3;
+    p->vertexlist = new int[3];
+		
+    // creation of elements
+    const Triangle3 & K(Th3.be(ibe)); // const Triangle2 & K(Th2.elements[ii]); // Version Mesh2  
+    p->vertexlist[0] = Th3.operator()(K[0])+1;
+    p->vertexlist[1] = Th3.operator()(K[1])+1;
+    p->vertexlist[2] = Th3.operator()(K[2])+1;
+		
+    for( int kkk=0; kkk<3; kkk++){ 
+      assert( p->vertexlist[kkk]<= in.numberofpoints && p->vertexlist[kkk]>0);
+    }
+		
+    in.facetmarkerlist[ibe] = K.lab; 
+		
+  }  
+  // mise a jour des nouvelles variables
+ 
+  in.numberofholes = nbhole;
+  in.holelist = new REAL[3*nbhole];
+  
+  for(int ii=0; ii<3*in.numberofholes; ii++){
+    in.holelist[ii]   = tabhole[ii];
+  }
+
+  in.numberofregions = nbregion;
+  in.regionlist = new REAL[5*nbregion];
+  for(int ii=0; ii<5*in.numberofregions; ii++){
+    in.regionlist[ii] = tabregion[ii];
+  }
+
+  in.numberoffacetconstraints = nbfacecl;
+  in.facetconstraintlist = new REAL[2*in.numberoffacetconstraints];
+
+  for(int ii=0; ii<2*in.numberoffacetconstraints; ii++){
+    in.facetconstraintlist[ii+1] = tabfacecl[ii+1];
+  }
+
+
+  cout << "tetgen: before tetrahedralize( , &in, &out);" << endl;
+  cout << "numberof regions "<<  in.numberofregions  << endl;
+  cout << "numberof hole "<<  in.numberofholes  << endl;
+	
+  tetrahedralize(switch_tetgen, &in, &out);
+	 
+  cout << "tetgen: after tetrahedralize( , &in, &out);" << endl;
+  //mesh3_tetgenio_out( out, *T_Th3);
+  Mesh3* T_Th3=mesh3_tetgenio_out( out);
+  cout <<" Finish Mesh3 tetgen :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return T_Th3;
+}
+
+Mesh3 * RemplissageSurf3D_tetgen_new(char *switch_tetgen,const Mesh3 & Th3, const int & label_tet,
+				     const int &nbhole, const double *tabhole, 
+				     const int & nbregion, const double *tabregion, 
+				     const int &nbfacecl, const double *tabfacecl, 
+				     const int &nbinside, const double *InsidePoint, 
+				     const int &sizeofmetric, const double *metric){
+	
+  //Mesh3 *T_Th3= new Mesh3;
+	
+  assert(Th3.nt == 0 );
+  int nv_t = Th3.nv;
+  int nt_t = Th3.nt;
+  int nbe_t = Th3.nbe;
+
+ 
+  if(verbosity) cout << "3D RemplissageSurf3D:: Vertex  triangle2  border " << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+  // Creation des tableau de tetgen
+	
+  tetgenio in,out;
+  tetgenio addin;
+
+  if(verbosity) cout << " tetgenio: vertex " << endl;
+  int itet,jtet;
+  // All indices start from 1.
+  in.firstnumber = 1;
+  in.numberofpoints = nv_t;
+  in.pointlist = new REAL[in.numberofpoints*3];
+  in.pointmarkerlist = new int[in.numberofpoints];
+  itet=0;
+  jtet=0;
+  for(int nnv=0; nnv < nv_t; nnv++)
+    {
+      in.pointlist[itet]      = Th3.vertices[nnv].x;
+      in.pointlist[itet+1]    = Th3.vertices[nnv].y;
+      in.pointlist[itet+2]    = Th3.vertices[nnv].z;       
+      in.pointmarkerlist[nnv] = Th3.vertices[nnv].lab;   
+      itet=itet+3;
+    }
+  assert(itet==in.numberofpoints*3);
+   
+  // Add inside point
+  if( nbinside ){
+    cout << "nbinside=" << nbinside << endl;
+    addin.firstnumber = 1;
+    addin.numberofpoints = nbinside;
+    addin.pointlist= new REAL[3*nbinside];
+    addin.pointmarkerlist = new int[addin.numberofpoints];
+    for(int nnv=0; nnv < 3*nbinside; nnv++)
+      addin.pointlist[nnv] = InsidePoint[nnv];
+    for(int nnv=0; nnv < nbinside; nnv++)
+      addin.pointmarkerlist[nnv] = 111;
+  }
+
+  // Add metric
+  if( sizeofmetric ){
+    cout << "sizeofmetric=" << sizeofmetric << endl;
+    in.numberofpointmtrs = sizeofmetric;
+    in.pointmtrlist = new REAL[in.numberofpointmtrs*in.numberofpoints];
+    for(int nnv=0; nnv < in.numberofpointmtrs*in.numberofpoints; nnv++)
+      in.pointmtrlist[nnv]=metric[nnv]; 
+  }
+ 
+ if(verbosity) cout << " tetgenio: facet " << endl;
+  // Version avec des facettes
+  in.numberoffacets = nbe_t;
+  in.facetlist = new tetgenio::facet[in.numberoffacets];
+  in.facetmarkerlist = new int[in.numberoffacets];
+	  
+  for(int ibe=0; ibe < nbe_t; ibe++){
+    tetgenio::facet *f;
+    tetgenio::polygon *p;
+    f = &in.facetlist[ibe];
+    f->numberofpolygons = 1;
+    f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
+    f->numberofholes = 0;
+    f->holelist = NULL;
+		
+    p = &f->polygonlist[0];
+    p->numberofvertices = 3;
+    p->vertexlist = new int[3];
+		
+    // creation of elements
+    const Triangle3 & K(Th3.be(ibe)); // const Triangle2 & K(Th2.elements[ii]); // Version Mesh2  
+    p->vertexlist[0] = Th3.operator()(K[0])+1;
+    p->vertexlist[1] = Th3.operator()(K[1])+1;
+    p->vertexlist[2] = Th3.operator()(K[2])+1;
+		
+    for( int kkk=0; kkk<3; kkk++){ 
+      assert( p->vertexlist[kkk]<= in.numberofpoints && p->vertexlist[kkk]>0);
+    }
+		
+    in.facetmarkerlist[ibe] = K.lab; 
+		
+  }  
+  // mise a jour des nouvelles variables
+ 
+  in.numberofholes = nbhole;
+  in.holelist = new REAL[3*nbhole];
+  
+  for(int ii=0; ii<3*in.numberofholes; ii++){
+    in.holelist[ii]   = tabhole[ii];
+  }
+
+  in.numberofregions = nbregion;
+  in.regionlist = new REAL[5*nbregion];
+  for(int ii=0; ii<5*in.numberofregions; ii++){
+    in.regionlist[ii] = tabregion[ii];
+  }
+
+  in.numberoffacetconstraints = nbfacecl;
+  in.facetconstraintlist = new REAL[2*in.numberoffacetconstraints];
+
+  for(int ii=0; ii<2*in.numberoffacetconstraints; ii++){
+    in.facetconstraintlist[ii+1] = tabfacecl[ii+1];
+  }
+
+
+  cout << "tetgen: before tetrahedralize( , &in, &out);" << endl;
+  cout << "numberof regions "<<  in.numberofregions  << endl;
+  cout << "numberof hole "<<  in.numberofholes  << endl;
+	
+  tetrahedralize(switch_tetgen, &in, &out, &addin);
+	 
+  cout << "tetgen: after tetrahedralize( , &in, &out);" << endl;
+  //mesh3_tetgenio_out( out, *T_Th3);
+  Mesh3* T_Th3=mesh3_tetgenio_out( out);
+  cout <<" Finish Mesh3 tetgen :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return T_Th3;
+}
+
+
+Mesh3 * Transfo_Mesh2_tetgen(const double &precis_mesh, char *switch_tetgen,const Mesh & Th2, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+	int &border_only, int &recollement_border, int &point_confondus_ok, 
+	const int &label_tet, const map<int, int> &maptri ){
+  
+  //Mesh3 *T_Th3= new Mesh3;
+        int nv_t,nt_t,nbe_t;
+        int* Numero_Som;
+	
+	int* ind_nv_t;
+	int* ind_nt_t;
+	int* ind_nbe_t;
+	
+	int* label_nbe_t;
+	
+	//int i_som;
+	Numero_Som = new int[Th2.nv];
+	ind_nv_t   = new int[Th2.nv];
+	ind_nbe_t  = new int[Th2.nt];
+	     
+	label_nbe_t = new int[Th2.nt];
+	
+        if(verbosity) cout << "2D: Mesh::Vertex  triangle2  border " << Th2.nv << " "<<Th2.nt<< " " << Th2.neb<< endl;
+	
+	for(int ii=0; ii<Th2.nv; ii++){ 
+		Numero_Som[ii]=ii;
+	}
+	if(verbosity) cout <<" debut: SamePointElement " <<endl;
+	
+	SamePointElement_Mesh2( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th2, recollement_border, point_confondus_ok, 
+		Numero_Som, ind_nv_t, ind_nt_t, ind_nbe_t, label_nbe_t, nv_t, nt_t, nbe_t);
+	
+	if(verbosity) cout <<" fin: SamePointElement " <<endl;
+	
+	if(verbosity) cout << "2D transfo: Mesh::Vertex  triangle2  border " << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+	// Creation des tableau de tetgen
+	
+	
+	tetgenio in,out;
+	//tetgenio::facet *f;
+	//tetgenio::polygon *p;
+	
+	if(verbosity) cout << " tetgenio: vertex " << endl;
+	int itet,jtet;
+// All indices start from 1.
+	in.firstnumber = 1;
+	in.numberofpoints = nv_t;
+	in.pointlist = new REAL[in.numberofpoints*3];
+	in.pointmarkerlist = new int[in.numberofpoints];
+	itet=0;
+	jtet=0;
+	for(int nnv=0; nnv < nv_t; nnv++)
+	{
+		int & ii = ind_nv_t[nnv];
+		//cout << "nnv ,  ii  =" << nnv << "  " << ii << endl;
+		//cout << "tab_XX[ii], tab_YY[ii], tab_ZZ[ii]=" <<  tab_XX[ii] << " "<< tab_YY[ii] << " "<< tab_ZZ[ii] << endl;
+		assert( Numero_Som[ii] == nnv );
+		const Mesh::Vertex & K = Th2.vertices[ii];//const Mesh::Vertex & K(Th2.vertices[ii]); //Version Mesh2   
+		in.pointlist[itet]   = tab_XX[ii];
+		in.pointlist[itet+1] = tab_YY[ii];
+		in.pointlist[itet+2] = tab_ZZ[ii];       
+		in.pointmarkerlist[nnv] =  K.lab;   
+		itet=itet+3;
+	}
+	assert(itet==in.numberofpoints*3);
+	
+	if(verbosity) cout << " tetgenio: facet " << endl;
+	// Version avec des facettes
+	in.numberoffacets = nbe_t;
+	in.facetlist = new tetgenio::facet[in.numberoffacets];
+	in.facetmarkerlist = new int[in.numberoffacets];
+	  
+	for(int ibe=0; ibe < nbe_t; ibe++){
+	  tetgenio::facet *f;
+	  tetgenio::polygon *p;
+	  f = &in.facetlist[ibe];
+	  f->numberofpolygons = 1;
+	  f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
+	  f->numberofholes = 0;
+	  f->holelist = NULL;
+		
+	  p = &f->polygonlist[0];
+	  p->numberofvertices = 3;
+	  p->vertexlist = new int[3];
+		
+	  int & ii=ind_nbe_t[ibe];
+	  // creation of elements
+	  const Mesh::Triangle & K(Th2.t(ii)); // const Triangle2 & K(Th2.elements[ii]); // Version Mesh2  
+	  p->vertexlist[0] = Numero_Som[ Th2.operator()(K[0]) ]+1;
+	  p->vertexlist[1] = Numero_Som[ Th2.operator()(K[1]) ]+1;
+	  p->vertexlist[2] = Numero_Som[ Th2.operator()(K[2]) ]+1;
+		
+	  for( int kkk=0; kkk<3; kkk++){ 
+	    assert( p->vertexlist[kkk]<= in.numberofpoints && p->vertexlist[kkk]> 0);
+	  }
+	  map< int, int>:: const_iterator imap;
+	  imap = maptri.find(K.lab); // imap= maptri.find( label_nbe_t[ibe] );
+	  assert( imap != maptri.end());
+	  in.facetmarkerlist[ibe] = imap->second; // K.lab; // before 
+		
+	}  
+
+	cout << "tetgen: before tetrahedralize( , &in, &out);" << endl;
+	
+	tetrahedralize(switch_tetgen, &in, &out);
+	 
+	cout << "tetgen: after tetrahedralize( , &in, &out);" << endl;
+	//mesh3_tetgenio_out( out, label_tet, *T_Th3);
+	Mesh3 *T_Th3=mesh3_tetgenio_out( out, label_tet);
+	cout <<" Finish Mesh3 :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+	
+	
+
+	delete [] Numero_Som;
+	delete [] ind_nv_t;
+	delete [] ind_nbe_t;
+	delete [] label_nbe_t;
+
+	cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+	return T_Th3;
+
+
+}
+
+Mesh3 * Transfo_Mesh2_tetgen_new(const double &precis_mesh, char *switch_tetgen,const Mesh & Th2, const double *tab_XX, const double *tab_YY, const double *tab_ZZ, 
+				 int &border_only, int &recollement_border, int &point_confondus_ok, 
+				 const int &label_tet, const map<int, int> &maptri, 
+				 const int &nbhole, const double *tabhole, const int & nbregion, const double *tabregion, 
+				 const int &nbfacecl, const double *tabfacecl){
+  //Mesh3 *T_Th3= new Mesh3;
+  int nv_t,nt_t,nbe_t;
+  int* Numero_Som;
+	
+  int* ind_nv_t;
+  int* ind_nt_t;
+  int* ind_nbe_t;
+	
+  int* label_nbe_t;
+	
+  //int i_som;
+  Numero_Som = new int[Th2.nv];
+  ind_nv_t   = new int[Th2.nv];
+  ind_nbe_t  = new int[Th2.nt];
+	     
+  label_nbe_t = new int[Th2.nt];
+	
+  if(verbosity) cout << "2D: Mesh::Vertex  triangle2  border " << Th2.nv << " "<<Th2.nt<< " " << Th2.neb<< endl;
+	
+  for(int ii=0; ii<Th2.nv; ii++){ 
+    Numero_Som[ii]=ii;
+  }
+  if(verbosity) cout <<" debut: SamePointElement " <<endl;
+	
+  SamePointElement_Mesh2( precis_mesh, tab_XX, tab_YY, tab_ZZ, Th2, recollement_border, point_confondus_ok, 
+			  Numero_Som, ind_nv_t, ind_nt_t, ind_nbe_t, label_nbe_t, nv_t, nt_t, nbe_t);
+	
+  if(verbosity) cout <<" fin: SamePointElement " <<endl;
+	
+  if(verbosity) cout << "2D transfo: Mesh::Vertex  triangle2  border " << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+  // Creation des tableau de tetgen
+	
+	
+  tetgenio in,out;
+  //tetgenio::facet *f;
+  //tetgenio::polygon *p;
+	
+  if(verbosity) cout << " tetgenio: vertex " << endl;
+  int itet,jtet;
+  // All indices start from 1.
+  in.firstnumber = 1;
+  in.numberofpoints = nv_t;
+  in.pointlist = new REAL[in.numberofpoints*3];
+  in.pointmarkerlist = new int[in.numberofpoints];
+  itet=0;
+  jtet=0;
+  for(int nnv=0; nnv < nv_t; nnv++)
+    {
+      int & ii = ind_nv_t[nnv];
+      //cout << "nnv ,  ii  =" << nnv << "  " << ii << endl;
+      //cout << "tab_XX[ii], tab_YY[ii], tab_ZZ[ii]=" <<  tab_XX[ii] << " "<< tab_YY[ii] << " "<< tab_ZZ[ii] << endl;
+      assert( Numero_Som[ii] == nnv );
+      const Mesh::Vertex & K = Th2.vertices[ii];//const Mesh::Vertex & K(Th2.vertices[ii]); //Version Mesh2   
+      in.pointlist[itet]   = tab_XX[ii];
+      in.pointlist[itet+1] = tab_YY[ii];
+      in.pointlist[itet+2] = tab_ZZ[ii];       
+      in.pointmarkerlist[nnv] =  K.lab;   
+      itet=itet+3;
+    }
+  assert(itet==in.numberofpoints*3);
+	
+  if(verbosity) cout << " tetgenio: facet " << endl;
+  // Version avec des facettes
+  in.numberoffacets = nbe_t;
+  in.facetlist = new tetgenio::facet[in.numberoffacets];
+  in.facetmarkerlist = new int[in.numberoffacets];
+	  
+  for(int ibe=0; ibe < nbe_t; ibe++){
+    tetgenio::facet *f;
+    tetgenio::polygon *p;
+    f = &in.facetlist[ibe];
+    f->numberofpolygons = 1;
+    f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
+    f->numberofholes = 0;
+    f->holelist = NULL;
+		
+    p = &f->polygonlist[0];
+    p->numberofvertices = 3;
+    p->vertexlist = new int[3];
+		
+    int & ii=ind_nbe_t[ibe];
+    // creation of elements
+    const Mesh::Triangle & K(Th2.t(ii)); // const Triangle2 & K(Th2.elements[ii]); // Version Mesh2  
+    
+    
+    p->vertexlist[0] = Numero_Som[ Th2.operator()(K[0]) ]+1;
+    p->vertexlist[1] = Numero_Som[ Th2.operator()(K[1]) ]+1;
+    p->vertexlist[2] = Numero_Som[ Th2.operator()(K[2]) ]+1;
+		
+    for( int kkk=0; kkk<3; kkk++){ 
+      assert( p->vertexlist[kkk]<= in.numberofpoints && p->vertexlist[kkk]> 0);
+    }
+    map< int, int>:: const_iterator imap;
+    imap = maptri.find(K.lab); // imap= maptri.find( label_nbe_t[ibe] );
+    assert( imap != maptri.end());
+    in.facetmarkerlist[ibe] = imap->second; // K.lab; // before 
+		
+  }  
+
+  // mise a jour des nouvelles variables
+
+  in.numberofholes = nbhole;
+  in.holelist = new REAL[3*nbhole];
+  
+  for(int ii=0; ii<3*in.numberofholes; ii++){
+    in.holelist[ii]   = tabhole[ii];
+  }
+
+
+  in.numberofregions = nbregion;
+  in.regionlist = new REAL[5*nbregion];
+  for(int ii=0; ii<5*in.numberofregions; ii++){
+    in.regionlist[ii] = tabregion[ii];
+  }
+
+  in.numberoffacetconstraints = nbfacecl;
+  in.facetconstraintlist = new REAL[2*in.numberoffacetconstraints];
+
+  for(int ii=0; ii<2*in.numberoffacetconstraints; ii++){
+    in.facetconstraintlist[ii+1] = tabfacecl[ii+1];
+  }
+  
+  cout << "tetgen: before tetrahedralize( , &in, &out);" << endl;
+  
+  tetrahedralize(switch_tetgen, &in, &out);
+  
+  cout << "tetgen: after tetrahedralize( , &in, &out);" << endl;
+  //mesh3_tetgenio_out( out, *T_Th3);
+  Mesh3 *T_Th3=mesh3_tetgenio_out( out);
+  cout <<" Finish Mesh3 :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+
+  delete [] Numero_Som;
+  delete [] ind_nv_t;
+  delete [] ind_nbe_t;
+  delete [] label_nbe_t;
+  
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return T_Th3;
+}
+
+// Fonction Refine avec tetgen
+
+Mesh3 * ReconstructionRefine_tetgen(char *switch_tetgen,const Mesh3 & Th3, 
+				     const int &nbhole, const double *tabhole, 
+				     const int & nbregion, const double *tabregion, 
+				     const int &nbfacecl, const double *tabfacecl, const double *tsizevol){
+
+  // verif option refine
+  int i;	
+  assert(Th3.nt != 0 );
+  {
+    size_t testr, testp;
+    int lenswitch;
+    const char* test_tetgen = switch_tetgen;
+    
+    testr = strcspn(test_tetgen,"r");
+    testp = strcspn(test_tetgen,"p");
+    
+    if( testr == strlen(test_tetgen) )
+      { 
+	cout << "The option 'r' of tetgen is not used" << endl;
+	exit(1);
+      }
+    testp = strcspn(test_tetgen,"p");
+    if( testp != strlen(test_tetgen) )
+      { 
+	cout << "With TetGen :: the option 'p' is not possible to use with option 'r' " << endl;
+	exit(1);
+      }
+  }
+
+  int nv_t = Th3.nv;
+  int nt_t = Th3.nt;
+  int nbe_t = Th3.nbe;
+	
+  if(verbosity) cout << "3D RemplissageSurf3D:: Vertex  triangle2  border "  << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+  // Creation des tableau de tetgen
+	
+  tetgenio in,out;
+  //tetgenio::facet *f;
+  //tetgenio::polygon *p;
+	
+  if(verbosity) cout << " tetgenio: vertex " << endl;
+  int itet,jtet;
+  // All indices start from 1.
+  in.firstnumber = 1;
+  in.numberofpoints = nv_t;
+  in.pointlist = new REAL[in.numberofpoints*3];
+  in.pointmarkerlist = new int[in.numberofpoints];
+  itet=0;
+  jtet=0;
+  for(int nnv=0; nnv < nv_t; nnv++)
+    {
+      in.pointlist[itet]   = Th3.vertices[nnv].x;
+      in.pointlist[itet+1] = Th3.vertices[nnv].y;
+      in.pointlist[itet+2] = Th3.vertices[nnv].z;       
+      in.pointmarkerlist[nnv] =  Th3.vertices[nnv].lab;   
+      itet=itet+3;
+    }
+  assert(itet==in.numberofpoints*3);
+
+  // Tetrahedrons
+  if(verbosity) cout << "tetrahedrons" << endl;
+  in.numberofcorners = 4;
+  in.numberoftetrahedra = Th3.nt;
+  in.tetrahedronlist = new int[in.numberofcorners*in.numberoftetrahedra];
+  in.numberoftetrahedronattributes = 1;
+  in.tetrahedronattributelist = new REAL[in.numberoftetrahedronattributes*in.numberoftetrahedra];
+  
+  in.tetrahedronvolumelist = new REAL[in.numberoftetrahedra];
+
+  i=0;
+  for(int nnt=0; nnt < Th3.nt; nnt++){
+    const Tet & K(Th3.elements[nnt]);
+
+    in.tetrahedronlist[i]   = Th3.operator()(K[0])+1;
+    in.tetrahedronlist[i+1] = Th3.operator()(K[1])+1;
+    in.tetrahedronlist[i+2] = Th3.operator()(K[2])+1;
+    in.tetrahedronlist[i+3] = Th3.operator()(K[3])+1;
+
+    in.tetrahedronvolumelist[nnt] = tsizevol[nnt];
+    in.tetrahedronattributelist[nnt] = K.lab;
+    
+    i=i+4;
+  }
+
+  
+  if(verbosity) cout << "lecture des facettes" << endl;
+  in.numberoftrifaces = Th3.nbe;
+  in.trifacelist = new int[3*in.numberoftrifaces];
+  in.trifacemarkerlist = new int[in.numberoftrifaces];
+
+  for(int ibe=0; ibe < Th3.nbe; ibe++){
+    const Triangle3 & K(Th3.be(ibe));
+    
+    in.trifacelist[3*ibe]   = Th3.operator()(K[0])+1;
+    in.trifacelist[3*ibe+1] = Th3.operator()(K[1])+1;
+    in.trifacelist[3*ibe+2] = Th3.operator()(K[2])+1; 					      
+    in.trifacemarkerlist[ibe] = K.lab;
+
+  }
+  
+  // mise a jour des nouvelles variables
+ 
+  in.numberofholes = nbhole;
+  in.holelist = new REAL[3*nbhole];
+  
+  for(int ii=0; ii<3*in.numberofholes; ii++){
+    in.holelist[ii]   = tabhole[ii];
+    if(verbosity) cout << "in.holelist[ii]=" << in.holelist[ii] << endl;
+  }
+
+  in.numberofregions = nbregion;
+  in.regionlist = new REAL[5*nbregion];
+  for(int ii=0; ii<5*in.numberofregions; ii++){
+    in.regionlist[ii] = tabregion[ii];
+    if(verbosity) cout << "in.regionlist[ii]=" << in.regionlist[ii] << endl;
+  }
+
+  in.numberoffacetconstraints = nbfacecl;
+  in.facetconstraintlist = new REAL[2*in.numberoffacetconstraints];
+
+  for(int ii=0; ii<2*in.numberoffacetconstraints; ii++){
+    in.facetconstraintlist[ii+1] = tabfacecl[ii+1];
+  }
+
+  if(verbosity > 0){
+    cout << "tetgen: before tetrahedralize( , &in, &out);" << endl;
+    cout << "numberof regions "<<  in.numberofregions  << endl;
+    cout << "numberof hole "<<  in.numberofholes  << endl;
+  }
+  tetrahedralize(switch_tetgen, &in, &out);
+
+  if(verbosity > 0)
+    cout << "tetgen: after tetrahedralize( , &in, &out);" << endl;
+ 
+  Mesh3 *T_Th3=mesh3_tetgenio_out( out);
+  if(verbosity > 0){
+    cout <<" Finish Mesh3 tetgen :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+    cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  }
+  return T_Th3;
+}
+
+
+// Fonction Refine avec tetgen � l'aide d'une metrique
+
+Mesh3 * ReconstructionRefine_tetgen(char *switch_tetgen,const Mesh3 & Th3, 
+				     const int &nbhole, const double *tabhole, 
+				     const int & nbregion, const double *tabregion, 
+				     const int &nbfacecl, const double *tabfacecl, 
+				     const double *tsizevol, const int &sizeofmetric, const double *metric){
+
+  // verif option refine
+  int i;	
+  assert(Th3.nt != 0 );
+  {
+    size_t testr, testp;
+    int lenswitch;
+    const char* test_tetgen = switch_tetgen;
+    
+    testr = strcspn(test_tetgen,"r");
+    testp = strcspn(test_tetgen,"p");
+    
+    if( testr == strlen(test_tetgen) )
+      { 
+	cout << "The option 'r' of tetgen is not used" << endl;
+	exit(1);
+      }
+    testp = strcspn(test_tetgen,"p");
+    if( testp != strlen(test_tetgen) )
+      { 
+	cout << "With TetGen :: the option 'p' is not possible to use with option 'r' " << endl;
+	exit(1);
+      }
+  }
+
+  int nv_t = Th3.nv;
+  int nt_t = Th3.nt;
+  int nbe_t = Th3.nbe;
+	
+  if(verbosity) cout << "3D RemplissageSurf3D:: Vertex  triangle2  border "  << nv_t << " "<< nt_t << " " << nbe_t<< endl;
+  // Creation des tableau de tetgen
+	
+  tetgenio in,out;
+  //tetgenio::facet *f;
+  //tetgenio::polygon *p;
+	
+  if(verbosity) cout << " tetgenio: vertex " << endl;
+  int itet,jtet;
+  // All indices start from 1.
+  in.firstnumber = 1;
+  in.numberofpoints = nv_t;
+  in.pointlist = new REAL[in.numberofpoints*3];
+  in.pointmarkerlist = new int[in.numberofpoints];
+  itet=0;
+  jtet=0;
+  for(int nnv=0; nnv < nv_t; nnv++)
+    {
+      in.pointlist[itet]   = Th3.vertices[nnv].x;
+      in.pointlist[itet+1] = Th3.vertices[nnv].y;
+      in.pointlist[itet+2] = Th3.vertices[nnv].z;       
+      in.pointmarkerlist[nnv] =  Th3.vertices[nnv].lab;   
+      itet=itet+3;
+    }
+  assert(itet==in.numberofpoints*3);
+
+  if( verbosity ) 
+    cout << "sizeofmetric=" << sizeofmetric << endl;
+  in.numberofpointmtrs = sizeofmetric;
+  in.pointmtrlist = new REAL[in.numberofpointmtrs*in.numberofpoints];
+  for(int nnv=0; nnv < in.numberofpointmtrs*in.numberofpoints; nnv++)
+    in.pointmtrlist[nnv]=metric[nnv]; 
+
+  // Tetrahedrons
+  if(verbosity) cout << "tetrahedrons" << endl;
+  in.numberofcorners = 4;
+  in.numberoftetrahedra = Th3.nt;
+  in.tetrahedronlist = new int[in.numberofcorners*in.numberoftetrahedra];
+  in.numberoftetrahedronattributes = 1;
+  in.tetrahedronattributelist = new REAL[in.numberoftetrahedronattributes*in.numberoftetrahedra];
+  
+  in.tetrahedronvolumelist = new REAL[in.numberoftetrahedra];
+
+  i=0;
+  for(int nnt=0; nnt < Th3.nt; nnt++){
+    const Tet & K(Th3.elements[nnt]);
+
+    in.tetrahedronlist[i]   = Th3.operator()(K[0])+1;
+    in.tetrahedronlist[i+1] = Th3.operator()(K[1])+1;
+    in.tetrahedronlist[i+2] = Th3.operator()(K[2])+1;
+    in.tetrahedronlist[i+3] = Th3.operator()(K[3])+1;
+
+    in.tetrahedronvolumelist[nnt] = tsizevol[nnt];
+    in.tetrahedronattributelist[nnt] = K.lab;
+    
+    i=i+4;
+  }
+
+  
+  if(verbosity) cout << "lecture des facettes" << endl;
+  in.numberoftrifaces = Th3.nbe;
+  in.trifacelist = new int[3*in.numberoftrifaces];
+  in.trifacemarkerlist = new int[in.numberoftrifaces];
+
+  for(int ibe=0; ibe < Th3.nbe; ibe++){
+    const Triangle3 & K(Th3.be(ibe));
+    
+    in.trifacelist[3*ibe]   = Th3.operator()(K[0])+1;
+    in.trifacelist[3*ibe+1] = Th3.operator()(K[1])+1;
+    in.trifacelist[3*ibe+2] = Th3.operator()(K[2])+1; 					      
+    in.trifacemarkerlist[ibe] = K.lab;
+
+  }
+  
+  // mise a jour des nouvelles variables
+ 
+  in.numberofholes = nbhole;
+  in.holelist = new REAL[3*nbhole];
+  
+  for(int ii=0; ii<3*in.numberofholes; ii++){
+    in.holelist[ii]   = tabhole[ii];
+    if(verbosity) cout << "in.holelist[ii]=" << in.holelist[ii] << endl;
+  }
+
+  in.numberofregions = nbregion;
+  in.regionlist = new REAL[5*nbregion];
+  for(int ii=0; ii<5*in.numberofregions; ii++){
+    in.regionlist[ii] = tabregion[ii];
+    if(verbosity) cout << "in.regionlist[ii]=" << in.regionlist[ii] << endl;
+  }
+
+  in.numberoffacetconstraints = nbfacecl;
+  in.facetconstraintlist = new REAL[2*in.numberoffacetconstraints];
+
+  for(int ii=0; ii<2*in.numberoffacetconstraints; ii++){
+    in.facetconstraintlist[ii+1] = tabfacecl[ii+1];
+  }
+
+  if(verbosity > 0){
+    cout << "tetgen: before tetrahedralize( , &in, &out);" << endl;
+    cout << "numberof regions "<<  in.numberofregions  << endl;
+    cout << "numberof hole "<<  in.numberofholes  << endl;
+  }
+  tetrahedralize(switch_tetgen, &in, &out);
+
+  if(verbosity > 0)
+    cout << "tetgen: after tetrahedralize( , &in, &out);" << endl;
+ 
+  Mesh3 *T_Th3=mesh3_tetgenio_out( out);
+  if(verbosity > 0){
+    cout <<" Finish Mesh3 tetgen :: Vertex, Element, Border" << T_Th3->nv << " "<< T_Th3->nt << " " << T_Th3->nbe << endl;
+    cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  }
+  return T_Th3;
+}
+
+// declaration pour FreeFem++
+
+class Remplissage_Op : public E_F0mps 
+{
+public:
+  //typedef pmesh3 Result;
+  Expression eTh;    // Surface mesh
+  // ====================
+  // This parameter allow to add inside points of this initial volume mesh
+  Expression eVolTh;  
+  bool bVol;
+  // ====================
+  static const int n_name_param =9+2+1+1; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long   arg(int i,Stack stack, long  a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  string*  arg(int i,Stack stack, string* a ) const{ return nargs[i] ? GetAny< string* >( (*nargs[i])(stack) ): a;}
+public:
+  Remplissage_Op(const basicAC_F0 &  args,Expression tth) 
+    : eTh(tth)
+  {
+    if(verbosity >1) cout << "Remplissage du bord" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    if( nargs[2] && nargs[9] ) 
+	CompileError("uncompatible movemesh3 (Th, region= , reftet=  ");
+    if( nargs[3] && nargs[10] ) 
+	CompileError("uncompatible movemesh3 (Th, label= , refface=  ");
+    
+    bVol=false;
+    /*
+    if( BCastTo<Mesh3 *>(args[1]) ){
+      eVolTh = CastTo<Mesh3 *>(args[1]);
+      bVol=true;
+    }
+    else{
+      bVol=false;
+    } 
+    */
+  }
+  Remplissage_Op(const basicAC_F0 &  args,Expression tth, Expression vth) 
+    : eTh(tth),eVolTh(vth)
+  {
+    if(verbosity >1) cout << "Remplissage du bord" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    if( nargs[2] && nargs[9] ) 
+	CompileError("uncompatible movemesh3 (Th, region= , reftet=  ");
+    if( nargs[3] && nargs[10] ) 
+	CompileError("uncompatible movemesh3 (Th, label= , refface=  ");
+    
+    bVol=true;
+  }
+  /*
+    static ArrayOfaType  typeargs() { return  ArrayOfaType( atype<pmesh3>(),true ); }// all type
+    static  E_F0 * f(const basicAC_F0 & args) { return new Remplissage_Op(args);} 
+    operator aType () const { return atype<pmesh3>();} 
+  */
+  AnyType operator()(Stack stack)  const ;
+};
+
+
+basicAC_F0::name_and_type Remplissage_Op::name_param[]= {
+  {  "switch", &typeid(string*)},
+  {  "reftet", &typeid(long)}, //1
+  {  "refface", &typeid(KN_<long> )},//2
+  // new parmameters
+  {  "nbofholes", &typeid(long)},
+  {  "holelist", &typeid(KN_<double>)},
+  {  "nbofregions", &typeid(long)},
+  {  "regionlist", &typeid(KN_<double>)},
+  {  "nboffacetcl", &typeid(long)},
+  {  "facetcl", &typeid(KN_<double>)},
+  {  "region", &typeid(long)}, //9
+  {  "label", &typeid(KN_<long>)},//10
+  {  "addpointlist", &typeid(KN_<long>)}, // 11
+  {  "metric", &typeid(KN_<long>)}
+};
+
+class  Remplissage : public OneOperator { public:  
+    Remplissage() : OneOperator(atype<pmesh3>(),atype<pmesh3>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+	return  new Remplissage_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+
+class  RemplissageAddPoint : public OneOperator { public:  
+    RemplissageAddPoint() : OneOperator(atype<pmesh3>(),atype<pmesh3>(),atype<pmesh3>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new Remplissage_Op( args,t[0]->CastTo(args[0]),t[1]->CastTo(args[1]) ); 
+  }
+};
+
+AnyType Remplissage_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  ffassert( pTh );
+  Mesh3 &Th=*pTh;
+  Mesh3 *m= pTh;   // question a quoi sert *m ??
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int nbe=Th.nbe; // nombre d'aretes fontiere
+  cout << "Tetgen : Vertex Triangle Border " << nbv<< "  "<< nbt << " nbe "<< nbe << endl; 
+ 
+  KN<long> zzempty;
+  //int intempty=0;
+  string stringempty= string("pqaAAYQC");
+  string* switch_tet(arg(0,stack,&stringempty));
+  int label_tet(arg(1,stack,arg(9,stack,0L)));  
+  KN<long> nrf (arg(2,stack,arg(10,stack,zzempty)));
+
+  // new parameters
+  KN<double> zdzempty;
+  int nbhole (arg(3,stack,0L));
+  KN<double> tabhole (arg(4,stack,zdzempty));
+  int nbregion (arg(5,stack,0L));
+  KN<double> tabregion (arg(6,stack,zdzempty));
+  int nbfacecl (arg(7,stack,0L));
+  KN<double> tabfacecl (arg(8,stack,zdzempty));
+  // parameter inside point
+  // need to add "i" to the switch
+  KN<double> InsidePoint(arg(11,stack,zdzempty)); // Add inside point in the volume mesh generated by tetgen
+  // need to add "m" to the switch
+  KN<double> metric(arg(12,stack,zdzempty)); // Add metric for tetgen
+
+  //=========================
+  // Add  a metric
+  int sizeofmetric= metric.N()/Th.nv;
+  if( nargs[12] ){
+    cout << " size of the metric " << metric.N()/Th.nv << endl;
+    assert( (metric.N()/Th.nv)*Th.nv == metric.N() );
+  }
+  // fin add a metric
+  //==========================
+  
+  //==========================
+  // Add inside points
+
+  if( nargs[11] )
+    assert( ((InsidePoint.N()/3)*3) == InsidePoint.N() );
+  // case with a inside meshes
+
+  if( bVol ){
+    // Inside point is given by a mesh
+    Mesh3 *pvolTh = GetAny<Mesh3 *>((*eVolTh)(stack));
+    Mesh3 &volTh=*pvolTh;
+    
+    KN<int> takevertex(volTh.nv);
+    takevertex = 1;
+    // determination of vertices in the border
+    for(int ibe=0; ibe<volTh.nbe; ibe++){
+      const Triangle3 & K(volTh.be(ibe));
+      takevertex[volTh.operator()(K[0])] = 0;
+      takevertex[volTh.operator()(K[1])] = 0;
+      takevertex[volTh.operator()(K[2])] = 0;
+    }
+    int nvInside=0;
+    // number of vertices inside the volume mesh
+    for(int iv=0; iv<volTh.nv; iv++){ 
+      if( takevertex[iv] == 1)
+	nvInside++;      
+    }
+    InsidePoint.resize(3*nvInside);
+    int loopnv=0;
+    for(int iv=0; iv<volTh.nv; iv++){ 
+      if( takevertex[iv] == 1){
+	InsidePoint[loopnv]   = volTh.vertices[iv].x;
+	InsidePoint[loopnv+1] = volTh.vertices[iv].y;
+	InsidePoint[loopnv+2] = volTh.vertices[iv].z;
+	loopnv=loopnv+3;
+      }      
+    }
+    assert( loopnv/3 == nvInside );
+  }
+  
+  if( !bVol && !nargs[11] ) assert( 	InsidePoint.N() == 0 ); 
+
+  //  fin add inisde point
+  //=========================
+    
+    if(nbregion==0) nbregion=tabregion.N()/5;
+    if(nbhole==0) nbhole=tabhole.N()/3;
+    if(nbfacecl==0) nbfacecl=tabfacecl.N()/2;
+    
+
+  // assertion au niveau de la taille 
+  ffassert( tabhole.N()   == 3*nbhole);
+  ffassert( tabregion.N() == 5*nbregion);
+  ffassert( tabfacecl.N() == 2*nbfacecl);
+
+  
+
+  //====================================
+  //  How to change string* into char* 
+  //====================================
+  cout << "string" << *switch_tet << endl; 
+  size_t size_switch_tet = switch_tet->size()+1;
+  char* switch_tetgen =new char[size_switch_tet];
+  strncpy(switch_tetgen, switch_tet->c_str(), size_switch_tet); 
+   
+  cout << "char" << switch_tetgen << endl; 
+  
+  ffassert( nrf.N() %2 ==0);
+
+  map<int,int> mapf;
+  for(int i=0;i<nrf.N();i+=2)
+    {
+      if(nrf[i] != nrf[i+1]){
+	mapf[nrf[i]]=nrf[i+1];
+      }
+    }
+  
+  if(verbosity>1) cout << "tetgen:" << "nbhole="   << nbhole << "nbregion=" << nbregion << endl;
+
+  /*
+    int addcheckorientation=0;
+    if( addcheckorientation==1  ){
+    cout << "check :: orientation des surfaces" << endl;
+    Th.BuildBoundaryElementAdj();
+    cout << "fin check :: orientation des surfaces" << endl;
+    }
+  */
+
+  int nbinside=InsidePoint.N()/3;
+  Mesh3 *Th3 = 0;
+
+  if( nargs[11] || nargs[12] || bVol){
+    Th3 = RemplissageSurf3D_tetgen_new( switch_tetgen, Th, label_tet, nbhole, tabhole, nbregion, tabregion, nbfacecl, tabfacecl, nbinside, InsidePoint, sizeofmetric, metric);
+    // delete multiple vertex
+    Th3->TrueVertex();
+  }
+  else
+    Th3 = RemplissageSurf3D_tetgen_new( switch_tetgen, Th, label_tet, nbhole, tabhole, nbregion, tabregion, nbfacecl, tabfacecl);
+  
+
+  cout << "finish tetgen " << endl;
+  // changement de label 
+  if( nrf.N() > 0){
+    cout << "changement de label" << endl;
+    for(int ii=0; ii< Th3->nbe; ii++){
+      const Triangle3 & K(Th3->be(ii));
+      int lab;
+      int iv[3];
+			
+      iv[0] = Th3->operator()(K[0]);
+      iv[1] = Th3->operator()(K[1]);
+      iv[2] = Th3->operator()(K[2]);
+			
+      map< int, int> :: const_iterator imap;
+      imap = mapf.find(K.lab);
+      if( imap != mapf.end() ){
+	lab = imap -> second;
+      }
+      else{
+	lab = K.lab;
+      }
+      Th3->be(ii).set(Th3->vertices,iv,lab);
+    }
+  }
+  cout << "action sur le maillage" << endl;
+
+ // Th3->BuildBound();
+ // Th3->BuildAdj();
+ // Th3->Buildbnormalv();  
+ // Th3->BuildjElementConteningVertex();
+  Th3->BuildGTree();
+  //Th3->decrement();    
+  Add2StackOfPtr2FreeRC(stack,Th3);
+  
+  *mp=mps;
+  delete [] switch_tetgen; 
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return Th3;
+}
+
+// Refine et Recontruction 
+
+class ReconstructionRefine_Op : public E_F0mps 
+{
+public:
+  Expression eTh;
+  static const int n_name_param =10+2+1; // 
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long   arg(int i,Stack stack, long  a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  string*  arg(int i,Stack stack, string* a ) const{ return nargs[i] ? GetAny< string* >( (*nargs[i])(stack) ): a;}
+public:
+  ReconstructionRefine_Op(const basicAC_F0 &  args,Expression tth) 
+    : eTh(tth)
+  {
+    if(verbosity >1) cout << "ReconstructionRefine du bord"<< endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    if( nargs[2] && nargs[10] ) 
+	CompileError("uncompatible ... (Th, region= , reftet=  ");
+    if( nargs[3] && nargs[11] ) 
+	CompileError("uncompatible ... (Th, label= , refface=  ");
+    
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+
+basicAC_F0::name_and_type ReconstructionRefine_Op::name_param[]= {
+  {  "switch", &typeid(string*)},
+  {  "reftet", &typeid(KN_<long>)}, 
+  {  "refface", &typeid(KN_<long> )},
+  // new parmameters
+  {  "nbofholes", &typeid(long)},
+  {  "holelist", &typeid(KN_<double>)},
+  {  "nbofregions", &typeid(long)},
+  {  "regionlist", &typeid(KN_<double>)},
+  {  "nboffacetcl", &typeid(long)},
+  {  "facetcl", &typeid(KN_<double>)},
+  {  "sizeofvolume", &typeid(double)},
+  {  "region", &typeid(KN_<long>)}, //10
+  {  "label", &typeid(KN_<long>)},//11
+  {  "metric", &typeid(KN_<double>)}//12  // parameter for tetgen
+    
+};
+
+class  ReconstructionRefine : public OneOperator { public:  
+
+  ReconstructionRefine() : OneOperator(atype<pmesh3>(),atype<pmesh3>()) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new ReconstructionRefine_Op( args, t[0]->CastTo(args[0]) ); 
+  }
+};
+
+AnyType ReconstructionRefine_Op::operator()(Stack stack)  const 
+{
+  MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+  Mesh3 * pTh= GetAny<Mesh3 *>((*eTh)(stack));
+  //double msvol= GetAny<double>((*maxvol)(stack));
+ 
+  ffassert( pTh );
+  Mesh3 &Th=*pTh;
+  Mesh3 *m= pTh;   // question a quoi sert *m ??
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int nbe=Th.nbe; // nombre d'aretes fontiere
+  cout << "refine tetgen: Vertex Triangle Border " << nbv<< "  "<< nbt << " "<< nbe << endl; 
+ 
+  KN<long> zzempty;
+  //int intempty=0;
+  string stringempty= string("rqaAAYQC");
+  string* switch_tet(arg(0,stack,&stringempty));
+  KN<long> nrtet(arg(1,stack,arg(10,stack,zzempty)));  
+  KN<long> nrf (arg(2,stack,arg(11,stack,zzempty)));
+
+  // new parameters
+  KN<double> zdzempty;
+  int nbhole (arg(3,stack,0L));
+  KN<double> tabhole (arg(4,stack,zdzempty));
+  int nbregion (arg(5,stack,0L));
+  KN<double> tabregion (arg(6,stack,zdzempty));
+  int nbfacecl (arg(7,stack,0L));
+  KN<double> tabfacecl (arg(8,stack,zdzempty));
+
+  KN<double> metric(arg(12,stack,zdzempty)); // Add metric for tetgen
+
+  //=========================
+  // Add  a metric
+  int sizeofmetric = metric.N()/Th.nv;
+  if( nargs[12] ){
+    cout << " size of the metric " << metric.N()/Th.nv << endl;
+    assert( (metric.N()/Th.nv)*Th.nv == metric.N() );
+  }
+  // fin add a metric
+  //==========================
+    if(nbregion==0) nbregion=tabregion.N()/5;
+    if(nbhole==0) nbhole=tabhole.N()/3;
+    if(nbfacecl==0) nbfacecl=tabfacecl.N()/2;
+    
+  // assertion au niveau de la taille
+    
+  ffassert( tabhole.N()   == 3*nbhole);
+  ffassert( tabregion.N() == 5*nbregion);
+  ffassert( tabfacecl.N() == 2*nbfacecl);
+  
+  //====================================
+  //  How to change string* into char* 
+  //====================================
+  size_t size_switch_tet = switch_tet->size()+1;
+  char* switch_tetgen =new char[size_switch_tet];
+  strncpy(switch_tetgen, switch_tet->c_str(), size_switch_tet); 
+   
+  ffassert( nrf.N() %2 ==0);
+  map<int,int> mapf;
+  for(int i=0;i<nrf.N();i+=2)
+    {
+      if(nrf[i] != nrf[i+1]){
+	mapf[nrf[i]]=nrf[i+1];
+      }
+    }
+
+  ffassert( nrtet.N() %2 ==0);
+  map<int,int> maptet;
+  for(int i=0;i<nrtet.N();i+=2)
+    {
+      if(nrtet[i] != nrtet[i+1]){
+	maptet[nrtet[i]]=nrtet[i+1];
+      }
+    }
+
+  KN<double> tsizevol(nbt);
+  MeshPoint *mp3(MeshPointStack(stack)); 
+	
+  R3 Cdg_hat = R3(1./4.,1./4.,1./4.);
+
+  for (int it=0; it<nbt; it++){
+    Tet & K(Th.elements[it]);
+
+    mp3->set( Th, K(Cdg_hat), Cdg_hat, K, K.lab);
+    if( nargs[9]){
+      tsizevol[it]=  GetAny< double >( (*nargs[9])(stack) );
+    }
+    else if(tabregion.N()==0){
+      for(int i=0; i< nbregion;i++){
+	if( K.lab == tabregion[3+5*i] ){
+	  tsizevol[it] = tabregion[4+5*i];
+	}
+      }
+      
+    }
+    else{
+      tsizevol[it] = K.mesure();
+    }
+  }
+
+  cout << "Before reconstruction:" << " nbhole="   << nbhole << " nbregion=" << nbregion << endl;
+ 
+  Mesh3 *Th3=0; 
+  
+  int RefineMethod=-1;
+  if( nargs[9] ) 
+    RefineMethod=1;
+  if( nargs[12] ) 
+    RefineMethod=0;
+  
+  // Add parameter "perhaps' with add a metric which defined sizeofvolume
+
+  if( RefineMethod == 1) 
+    Th3 = ReconstructionRefine_tetgen(switch_tetgen, Th, nbhole, tabhole, nbregion, tabregion, nbfacecl,tabfacecl,tsizevol);
+  else if( RefineMethod == 0) 
+    Th3 = ReconstructionRefine_tetgen(switch_tetgen, Th, nbhole, tabhole, nbregion, tabregion, nbfacecl,tabfacecl,tsizevol,sizeofmetric,metric);
+  else{
+    cerr << " We can't refine the initial mesh with tetgen. No sizeofvolume or metric is given " << endl;
+    exit(1);
+  }
+
+  cout << "finish reconstruction " << endl;
+  // changement de label 1
+ 
+  if( nrtet.N() > 0){
+    for(int ii=0; ii< Th3->nt; ii++){
+      const Tet & K(Th3->elements[ii]);
+      int lab;
+      int iv[4];
+			
+      iv[0] = Th3->operator()(K[0]);
+      iv[1] = Th3->operator()(K[1]);
+      iv[2] = Th3->operator()(K[2]);
+      iv[3] = Th3->operator()(K[3]);
+
+      map< int, int> :: const_iterator imap;
+      imap = maptet.find(K.lab);
+      if( imap != maptet.end() ){
+	lab = imap -> second;
+      }
+      else{
+	lab = K.lab;
+      }
+      Th3->elements[ii].set(Th3->vertices,iv,lab);
+    }
+  }
+
+  if( nrf.N() > 0){
+    for(int ii=0; ii< Th3->nbe; ii++){
+      const Triangle3 & K(Th3->be(ii));
+      int lab;
+      int iv[3];
+			
+      iv[0] = Th3->operator()(K[0]);
+      iv[1] = Th3->operator()(K[1]);
+      iv[2] = Th3->operator()(K[2]);
+			
+      map< int, int> :: const_iterator imap;
+      imap = mapf.find(K.lab);
+      if( imap != mapf.end() ){
+	lab = imap -> second;
+      }
+      else{
+	lab = K.lab;
+      }
+      Th3->be(ii).set(Th3->vertices,iv,lab);
+    }
+  }
+  //cout << "fin du changement de label " << endl;
+  
+//  Th3->BuildBound();
+//  Th3->BuildAdj();
+//  Th3->Buildbnormalv();  
+//  Th3->BuildjElementConteningVertex();
+  Th3->BuildGTree();
+  //Th3->decrement();    
+  Add2StackOfPtr2FreeRC(stack,Th3);
+
+  delete [] switch_tetgen;
+  *mp=mps;
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return Th3;
+}
+
+
+
+// ConvexHull3D_tetg_Op
+
+class ConvexHull3D_tetg_Op : public E_F0mps 
+{
+public:
+  Expression numofpts;
+  Expression xx,yy,zz;
+  static const int n_name_param =5; //
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long   arg(int i,Stack stack, long  a ) const{ return nargs[i] ? GetAny< long  >( (*nargs[i])(stack) ): a;}
+  string*  arg(int i,Stack stack, string* a ) const{ return nargs[i] ? GetAny< string* >( (*nargs[i])(stack) ): a;}
+  
+public:
+  ConvexHull3D_tetg_Op(const basicAC_F0 &  args, Expression nop, 
+  Expression ffxx, Expression ffyy, Expression ffzz ) 
+    : numofpts(nop), xx(ffxx), yy(ffyy), zz(ffzz)
+  {
+    if(verbosity) cout << "Convex Hull with TetGen" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    if( nargs[2] && nargs[3] ) 
+	CompileError("uncompatible ... (Th, region= , reftet=  ");
+    if( nargs[3] && nargs[4] ) 
+	CompileError("uncompatible ... (Th, label= , refface=  ");
+    
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+
+basicAC_F0::name_and_type  ConvexHull3D_tetg_Op::name_param[]= {
+  {  "switch", &typeid(string*)},
+  {  "reftet", &typeid(long)}, 
+  {  "refface", &typeid(long)},
+    {  "region", &typeid(long)}, 
+    {  "label", &typeid(long)}
+};
+
+class ConvexHull3D_tetg : public OneOperator { public:  
+     ConvexHull3D_tetg() : OneOperator( atype<pmesh3>(), atype<long>(), 
+     atype< KN_<double> >(), atype< KN_<double> >(), atype< KN_<double> >() ) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+	return  new  ConvexHull3D_tetg_Op( args,t[0]->CastTo(args[0]), 
+	      t[1]->CastTo(args[1]), t[2]->CastTo(args[2]), t[3]->CastTo(args[3]) ); 
+  }
+};
+
+AnyType  ConvexHull3D_tetg_Op::operator()(Stack stack)  const 
+{
+  int nbv = (int) GetAny<long>((*numofpts)(stack));
+  KN<double> cxx(nbv),cyy(nbv),czz(nbv);
+  
+  cxx = GetAny< KN<double> > ((*xx)(stack));
+  cyy = GetAny< KN<double> > ((*yy)(stack));
+  czz = GetAny< KN<double> > ((*zz)(stack));
+  
+
+  assert( cxx.N() == nbv );
+  assert( cyy.N() == nbv );
+  assert( czz.N() == nbv );
+     
+  KN<long> zzempty;
+  //int intempty=0;
+  string stringempty= string("YqaAAQC");
+  string* switch_tet(arg(0,stack,&stringempty));
+  int label_tet(arg(1,stack,arg(3,stack,0L)));  
+  int label_face(arg(2,stack,arg(4,stack,1L)));
+
+  //====================================
+  //  How to change string* into char* 
+  //====================================
+  size_t size_switch_tet = switch_tet->size()+1;
+  char* switch_tetgen =new char[size_switch_tet];
+  strncpy(switch_tetgen, switch_tet->c_str(), size_switch_tet); 
+  //======================================
+ 
+  Mesh3 *Th3 =  Convexhull_3Dpoints ( switch_tetgen, nbv, cxx, cyy, czz, label_tet, label_face );
+	
+//  Th3->BuildBound();
+//  Th3->BuildAdj();
+//  Th3->Buildbnormalv();  
+//  Th3->BuildjElementConteningVertex();
+  Th3->BuildGTree();
+  //Th3->decrement();   
+  Add2StackOfPtr2FreeRC(stack,Th3);
+  
+  delete [] switch_tetgen;
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return Th3;
+}
+
+// ConvexHull3D_tetg_file_Op
+
+class ConvexHull3D_tetg_file_Op: public E_F0mps 
+{
+public:
+  Expression filename;
+  static const int n_name_param =5; //
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  KN_<double>  arg(int i,Stack stack,KN_<double> a ) const
+  { return nargs[i] ? GetAny<KN_<double> >( (*nargs[i])(stack) ): a;}
+  double  arg(int i,Stack stack,double a ) const{ return nargs[i] ? GetAny< double >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack, long a ) const{ return nargs[i] ? GetAny< long >( (*nargs[i])(stack) ): a;}
+  string*  arg(int i,Stack stack, string* a ) const{ return nargs[i] ? GetAny< string* >( (*nargs[i])(stack) ): a;}
+  
+public:
+  ConvexHull3D_tetg_file_Op(const basicAC_F0 &  args, Expression zfilename ) 
+    : filename(zfilename)
+  {
+    if(verbosity) cout << "Convex Hull with TetGen" << endl;
+    args.SetNameParam(n_name_param,name_param,nargs);
+    if( nargs[1] && nargs[3] )
+	CompileError("uncompatible ... (Th, region= , reftet=  ");
+    if( nargs[2] && nargs[4] )
+	CompileError("uncompatible ... (Th, label= , refface=  ");
+    
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+
+basicAC_F0::name_and_type  ConvexHull3D_tetg_file_Op::name_param[]= {
+  {  "switch", &typeid(string*)},
+  {  "reftet", &typeid(long)}, 
+  {  "refface", &typeid(long)},
+    {  "region", &typeid(long)}, 
+    {  "label", &typeid(long)}
+    
+};
+
+class ConvexHull3D_tetg_file : public OneOperator { public:  
+     ConvexHull3D_tetg_file() : OneOperator( atype<pmesh3>(), atype<string *>() ) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+	return  new  ConvexHull3D_tetg_file_Op( args,t[0]->CastTo(args[0]) ); 
+  }
+};
+
+AnyType  ConvexHull3D_tetg_file_Op::operator()(Stack stack)  const 
+{
+  string*  pointsfile = GetAny<string*>((*filename)(stack));
+
+  // lecture du fichier contenant les points
+  int nbv;
+  //int lec;
+ 
+  ifstream fp( pointsfile->c_str() );
+
+  if(!fp) {
+    cerr << "  -- tetgconvexhull : Erreur openning " << pointsfile <<endl; 
+    exit(1);
+  }
+  if(verbosity>1)
+    cout << "  -- tetgconvexhull:  Read On file \"" << pointsfile <<"\""<<  endl;
+
+  fp >> nbv;
+ 
+  if(verbosity>1)
+  cout << "  -- Nb of Points " << nbv << endl;
+  KN<double> cxx(nbv), cyy(nbv), czz(nbv);
+
+  
+  for(int lec=0;lec<nbv;lec++)
+    {
+      fp >> cxx[lec] >> cyy[lec] >> czz[lec];
+    }
+  ffassert(fp.good()); 
+  if(verbosity>1)
+  cout << " bound x " << cxx.min() << " " << cxx.max() 
+       <<  "  y " << cyy.min() << " "<< cyy.max()
+       <<  "  z " << czz.min() << " "<< czz.max() << endl; 
+//  if( lec !=nbv ) {
+//     cerr << "  -- tetgconvexhull : Erreur Reading File " << pointsfile <<endl; 
+//     cerr << " number of points " << nbv << " " <<"number of lecture" << lec << endl;  
+//     exit(1);
+//   }
+//   assert(lec==nbv);
+
+  fp.close();    
+
+  KN<long> zzempty;
+  //int intempty=0;
+  string stringempty= string("YQV");
+  string* switch_tet(arg(0,stack,&stringempty));
+  int label_tet(arg(1,stack,arg(3,stack,0L)));  
+  int label_face(arg(2,stack,arg(4,stack,1L)));
+
+  //====================================
+  //  How to change string* into char* 
+  //====================================
+  size_t size_switch_tet = switch_tet->size()+1;
+  char* switch_tetgen =new char[size_switch_tet];
+  strncpy(switch_tetgen, switch_tet->c_str(), size_switch_tet); 
+  //======================================
+ 
+  Mesh3 *Th3 =new Mesh3; 
+  
+  Th3 = Convexhull_3Dpoints( switch_tetgen, nbv, cxx, cyy, czz, label_tet, label_face );
+	
+//  Th3->BuildBound();
+//  Th3->BuildAdj();
+//  Th3->Buildbnormalv();  
+//  Th3->BuildjElementConteningVertex();
+  Th3->BuildGTree();
+  //Th3->decrement();    
+  Add2StackOfPtr2FreeRC(stack,Th3);
+
+  delete [] switch_tetgen;
+  cout << "FreeFem++: End check mesh given by tetgen" << endl;  
+  return Th3;
+}
+
+
+/*  class Init1 { public:
+  Init1();
+};
+
+$1 */
+
+static void Load_Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  
+  //if (verbosity)
+  if(verbosity) cout << " load: tetgen  " << endl;
+  
+  Global.Add("tetgconvexhull","(",new ConvexHull3D_tetg_file);
+  Global.Add("tetgconvexhull","(",new ConvexHull3D_tetg);
+  Global.Add("tetgtransfo","(",new Build2D3D);
+  Global.Add("tetg","(",new Remplissage);
+  Global.Add("tetg","(",new RemplissageAddPoint);
+  Global.Add("tetgreconstruction","(",new ReconstructionRefine);
+
+}
+// because i include this file in tetgen.cpp (very bad) FH
+// a will correct this in next version ...
+#define  WITH_NO_INIT
+#include "msh3.cpp" 
+LOADFUNC(Load_Init)
diff --git a/examples++-load/tetgencube.edp b/examples++-load/tetgencube.edp
new file mode 100644
index 0000000..658d9b5
--- /dev/null
+++ b/examples++-load/tetgencube.edp
@@ -0,0 +1,82 @@
+// file tetgencube.edp
+load "msh3"
+load "tetgen"
+load "medit"
+
+real x0,x1,y0,y1;
+x0=1.; x1=2.; y0=0.; y1=2*pi;
+mesh Thsq1 = square(5,35,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+func ZZ1min = 0;
+func ZZ1max = 1.5;
+func XX1 = x;
+func YY1 = y;
+
+int[int] ref31h = [0,12];
+int[int] ref31b = [0,11];
+
+mesh3 Th31h = movemesh23(Thsq1,transfo=[XX1,YY1,ZZ1max],label=ref31h,orientation=1);
+mesh3 Th31b = movemesh23(Thsq1,transfo=[XX1,YY1,ZZ1min],label=ref31b,orientation=-1);   
+
+//medit("haut",Th31h);
+//medit("bas",Th31b);
+
+/////////////////////////////////
+x0=1.; x1=2.; y0=0.; y1=1.5;
+mesh Thsq2 = square(5,8,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+
+func ZZ2 = y;
+func XX2 = x;
+func YY2min = 0.;
+func YY2max = 2*pi;
+
+int[int] ref32h = [0,13];
+int[int] ref32b = [0,14];
+
+mesh3 Th32h = movemesh23(Thsq2,transfo=[XX2,YY2max,ZZ2],label=ref32h,orientation=-1);  
+mesh3 Th32b = movemesh23(Thsq2,transfo=[XX2,YY2min,ZZ2],label=ref32b,orientation=1);
+
+/////////////////////////////////
+x0=0.; x1=2*pi; y0=0.; y1=1.5;
+mesh Thsq3 = square(35,8,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+func XX3min = 1.;
+func XX3max = 2.;
+
+func YY3 = x;
+func ZZ3 = y;
+
+int[int] ref33h = [0,15];
+int[int] ref33b = [0,16];
+
+mesh3 Th33h = movemesh23(Thsq3,transfo=[XX3max,YY3,ZZ3],label=ref33h,orientation=1);  
+mesh3 Th33b = movemesh23(Thsq3,transfo=[XX3min,YY3,ZZ3],label=ref33b,orientation=-1); 
+
+////////////////////////////////
+mesh3 Th33 = Th31h+Th31b+Th32h+Th32b+Th33h+Th33b; // "gluing" surface meshs to obtain the surface of cube
+//medit("glumesh",Th33);
+savemesh(Th33,"Th33.mesh");
+
+// build a mesh of a axis parallel box with TetGen
+//real[int] domaine = [1.5,pi,0.75,145,0.001];
+//mesh3 Thfinal = tetg(Th33,switch="pqaAAYYQ",nbofregions=1,regionlist=domaine);    // Tetrahelize the interior of the cube with tetgen
+//medit("tetg",Thfinal);
+//savemesh(Thfinal,"Thfinal.mesh");
+
+
+// build a mesh of a half cylindrical shell of interior radius 1. and exterior radius 2 and heigh 1.5
+func mv2x = x*cos(y);
+func mv2y = x*sin(y);
+func mv2z = z;
+//mesh3 Thmv2 = movemesh3(Thfinal, transfo=[mv2x,mv2y,mv2z]);
+//savemesh(Thmv2,"halfcylindricalshell.mesh");
+verbosity=2;
+mesh3 Thmv2surf = movemesh(Th33, [mv2x,mv2y,mv2z], facemerge=0);
+cout << "\b\b Thmv2surf.mesure=" << Thmv2surf.mesure << endl;
+cout << " Thmv2surf.bordermesure=" << Thmv2surf.bordermesure << endl;
+
+medit("maiAllagesurf",Thmv2surf,wait=1);
+//savemesh(Thmv2surf,"maillagesurfacecylindre.mesh");
+//medit("maillageplein",Thmv2);
+
+
+
diff --git a/examples++-load/tetgenholeregion_rugby.edp b/examples++-load/tetgenholeregion_rugby.edp
new file mode 100644
index 0000000..1c7fa57
--- /dev/null
+++ b/examples++-load/tetgenholeregion_rugby.edp
@@ -0,0 +1,88 @@
+// file tetgenholeregion_rugby.edp
+load "msh3"
+load "tetgen"
+load "medit"
+verbosity=2;
+
+// Test 1
+
+// data of rugby ball
+real Ra=2.; 
+real Rb=2.;
+real Rc=1.;
+
+mesh Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},\frac{-pi}{2}[\times]0,2\pi[ $
+//  a parametrization of a ellipsoid
+func f1 = Ra*cos(x)*cos(y);
+func f2 = Rb*cos(x)*sin(y);
+func f3 = Rc*sin(x);
+//  partiel derivative of the parametrization DF
+func f1x=Ra*sin(x)*cos(y);   
+func f1y=-Ra*cos(x)*sin(y);
+func f2x=-Rb*sin(x)*sin(y);
+func f2y=Rb*cos(x)*cos(y);
+func f3x=Rc*cos(x);
+func f3y=0;
+// $  M = DF^t DF $
+func m11=f1x^2+f2x^2+f3x^2;
+func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+func m22=f1y^2+f2y^2+f3y^2;
+
+func perio=[[4,y],[2,y],[1,x],[3,x]];  
+real hh=0.1;
+real vv= 1/square(hh);
+verbosity=2;
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+
+verbosity=2;
+
+// construction of the surface of prolate ellipsoide
+real Rmin  = 1.;
+func f1min = Rmin*f1;
+func f2min = Rmin*f2;
+func f3min = Rmin*f3;
+
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+mesh3 Th3sph=movemesh23(Th,transfo=[f1min,f2min,f3min],orientation=1);
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+real Rmax  = 2.;
+func f1max = Rmax*f1;
+func f2max = Rmax*f2;
+func f3max = Rmax*f3;
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+mesh3 Th3sph2=movemesh23(Th,transfo=[f1max,f2max,f3max],orientation=-1);
+cout << "=====================" << endl;
+cout << "=====================" << endl;
+cout << "addition" << endl;
+mesh3 Th3=Th3sph+Th3sph2;
+savemesh(Th3sph,"ellipsoide.mesh");
+
+real[int] domain2 = [1.5*Ra,0.,0.,145,0.001,0.,0.,0.,18,0.001];
+cout << "==============================" << endl;
+cout << " tetgen call without hole " << endl;
+cout << "==============================" << endl;
+mesh3 Th3fin=tetg(Th3,switch="paAAYYCCV",nbofregions=2,regionlist=domain2);
+cout << "=============================" << endl;
+cout << "finish: tetgen call without hole" << endl;
+cout << "=============================" << endl;
+savemesh(Th3fin,"spherewithtworegion.mesh"); 
+medit("maillagetwo",Th3fin);
+
+real[int] hole = [0.,0.,0.];
+real[int] domain = [1.5*Ra,0.,0.,53,0.001];
+cout << "=============================" << endl;
+cout << "  tetgen call with hole   " << endl;
+cout << "=============================" << endl;
+mesh3 Th3finhole=tetg(Th3,switch="paAAYCCV",nbofholes=1,holelist=hole,nbofregions=1,regionlist=domain);
+cout << "=============================" << endl;
+cout << "finish: tetgen call with hole   " << endl;
+cout << "=============================" << endl;
+savemesh(Th3finhole,"spherewithahole.mesh"); 
+
+
+
diff --git a/examples++-load/thresholdings.cpp b/examples++-load/thresholdings.cpp
new file mode 100644
index 0000000..8d35dd4
--- /dev/null
+++ b/examples++-load/thresholdings.cpp
@@ -0,0 +1,91 @@
+// ORIG-DATE:   September 2010
+// -*- Mode : c++ -*%
+//
+// SUMMARY  : seuillage des matrices EF de freefem++   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+   
+#include "ff++.hpp"
+
+//using namespace Fem2D;
+
+template<class T> struct  Thresholding{ 
+  Matrice_Creuse<T> *v;
+  Thresholding( Matrice_Creuse<T> * vv) : v(vv) {}
+ }; 
+
+template<class R> 
+Matrice_Creuse<R> *thresholding2(const Thresholding<R> & t,const double &threshold)
+ {  
+     Matrice_Creuse<R> * sparse_mat =t.v;
+     if(sparse_mat) 
+       {
+	 int n=sparse_mat->N(),m=sparse_mat->M();
+	 map<pair<int,int>,R> M;
+	 if (n >0 && m>0 && sparse_mat->A) 
+	   {
+	     int nrt = sparse_mat->A->NbCoef();
+	     sparse_mat->A->addMatTo(R(1.),M,false,0,0,false,threshold);	    
+	 //    (M)[make_pair(n-1,m-1)]+=R();
+	     bool sym=false; // bof bof  
+	     sparse_mat->typemat=TypeSolveMat(TypeSolveMat::GMRES); //  none square matrice (morse)
+	     sparse_mat->A.master(new MatriceMorse<R>(n,m,M,sym));
+	     nrt-=sparse_mat->A->NbCoef();
+	     if(verbosity) cout << "  thresholding= remove " << nrt << " them in the matrix " << sparse_mat << " " << threshold << endl; 
+	   }
+	 else if(verbosity) cout << " empty matrix " <<sparse_mat << endl;
+       }
+  return  t.v;
+ }
+
+template<class T> 
+Thresholding<T> to_Thresholding( Matrice_Creuse<T> *v){ return Thresholding<T>(v);}
+
+
+/*  class Init1 { public:
+  Init1();
+};
+ 
+$1 */
+
+static void Load_Init()
+{  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+    typedef Thresholding<double>  TMR ;
+    typedef Thresholding<Complex>  TMC ;
+    typedef Matrice_Creuse<double>  MR ;
+    typedef Matrice_Creuse<Complex>  MC ;
+    Dcl_Type< TMR > ();
+    Dcl_Type< TMC > ();
+    TMR t(0);
+    thresholding2(t,0.);
+    Add<MR *>("thresholding",".",new OneOperator1< TMR ,MR *>(to_Thresholding));
+    Add<TMR   >("(","",new OneOperator2_<MR  *, TMR , double >(thresholding2)); 
+    Add<MC *>("thresholding",".",new OneOperator1< TMC ,MC *>(to_Thresholding));
+    Add<TMC >("(","",new OneOperator2_<MC *, TMC, double >(thresholding2)); 
+    
+}
+LOADFUNC(Load_Init)
diff --git a/examples++-load/thresholdings.edp b/examples++-load/thresholdings.edp
new file mode 100644
index 0000000..ecced22
--- /dev/null
+++ b/examples++-load/thresholdings.edp
@@ -0,0 +1,14 @@
+load "thresholdings"
+mesh Th = square(2,2);
+fespace Xh(Th,P1);
+Xh u,v;
+macro grad(u)[dx(u),dy(u)] // EOM
+func f=1;
+
+varf Lapl(u,v) = int2d(Th)( grad(u)'*grad(v) ) + int2d(Th)( f*v );   // ' for emacs
+
+matrix M=Lapl(Xh,Xh);
+
+cout << M << endl;
+M.thresholding(0.7);// remove all term less then 0.7 
+cout << M << endl;
\ No newline at end of file
diff --git a/examples++-load/ttestio.edp b/examples++-load/ttestio.edp
new file mode 100644
index 0000000..30f557d
--- /dev/null
+++ b/examples++-load/ttestio.edp
@@ -0,0 +1,43 @@
+load "gmsh"
+load "iovtk"
+load "medit"
+verbosity = 1;
+
+// example gmsh
+
+mesh3 Th = gmshload3("cube.msh");
+//medit("gmsh3d",Th,wait=1);
+
+// example iovtk
+
+border Gamma(t=0,2*pi){x=cos(t);y=sin(t);label=3;}
+border Gamma1(t=0,2*pi){x=2*cos(t);y=2*sin(t);label=5;}
+mesh Th2 = buildmesh( Gamma(10)+Gamma1(20) ); 
+
+fespace Vh(Th2,P1);     // P1 FE space
+func gg=x;
+Vh uh,vh,u;   
+Vh ggg=gg;
+solve laplacep(uh,vh,solver=CG,tgv=1e5) =      //  definion of  the problem 
+    int2d(Th2)( dx(uh)*dx(vh) + dy(uh)*dy(vh) )   //  bilinear form
+       + on(3,uh=1)+ on(5,uh=2) ;                        //  boundary condition form
+
+cout << "vtk information" << endl;
+int[int] fforder=[0,0,1,0,1];
+savevtk("disque.vtk",Th2,uh,ggg,uh,[uh,ggg],[uh,ggg],dataname="kkdjd jyqql bidule45 vector nnn nn44233T",order=fforder);
+
+
+mesh3 Th3;
+try {
+Th3=readmesh3("spherewithahole.mesh"); // This .mesh file is obtaing with tetgenholeregion.edp
+}
+catch (...) {
+  // FFCS - path to example scripts are changed, so this needs to be in the local directory to be common to FF and FFCS
+  include "tetgenholeregion_rugby.edp"
+}
+fespace Vh3(Th3,P1);     // P1 FE space
+func gg2=x+y;
+int[int] fforder2=[0,0,1,1];
+verbosity=6;
+savevtk("bidule.vtk",Th3,gg2,[gg2,gg2,gg2],gg2,[gg2,gg2,gg2],order=fforder2,dataname="kkdjd jyqql bidule45"); // The fourth solution Have no name. This name is vector4 (4 ==> fourth solution and vector ==> vector solution).
+
diff --git a/examples++-mpi/._DDM-NSUzawaCahouetChabart.edp b/examples++-mpi/._DDM-NSUzawaCahouetChabart.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-mpi/._DDM-NSUzawaCahouetChabart.edp differ
diff --git a/examples++-mpi/._MUMPS_FreeFem.cpp b/examples++-mpi/._MUMPS_FreeFem.cpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/examples++-mpi/._MUMPS_FreeFem.cpp differ
diff --git a/examples++-mpi/._PETSc.hpp b/examples++-mpi/._PETSc.hpp
new file mode 100755
index 0000000..ca8f93d
Binary files /dev/null and b/examples++-mpi/._PETSc.hpp differ
diff --git a/examples++-mpi/._additional.idp b/examples++-mpi/._additional.idp
new file mode 100755
index 0000000..f6e69b8
Binary files /dev/null and b/examples++-mpi/._additional.idp differ
diff --git a/examples++-mpi/._complex_SuperLU_DIST_FreeFem.cpp b/examples++-mpi/._complex_SuperLU_DIST_FreeFem.cpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/examples++-mpi/._complex_SuperLU_DIST_FreeFem.cpp differ
diff --git a/examples++-mpi/._complex_pastix_FreeFem.cpp b/examples++-mpi/._complex_pastix_FreeFem.cpp
new file mode 100644
index 0000000..63e1130
Binary files /dev/null and b/examples++-mpi/._complex_pastix_FreeFem.cpp differ
diff --git a/examples++-mpi/._dSuperLU_DIST.cpp b/examples++-mpi/._dSuperLU_DIST.cpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/examples++-mpi/._dSuperLU_DIST.cpp differ
diff --git a/examples++-mpi/._real_SuperLU_DIST_FreeFem.cpp b/examples++-mpi/._real_SuperLU_DIST_FreeFem.cpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/examples++-mpi/._real_SuperLU_DIST_FreeFem.cpp differ
diff --git a/examples++-mpi/._removeDOF.cpp b/examples++-mpi/._removeDOF.cpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/examples++-mpi/._removeDOF.cpp differ
diff --git a/examples++-mpi/._schwarz.cpp b/examples++-mpi/._schwarz.cpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/examples++-mpi/._schwarz.cpp differ
diff --git a/examples++-mpi/._schwarz.edp b/examples++-mpi/._schwarz.edp
new file mode 100644
index 0000000..f6e69b8
Binary files /dev/null and b/examples++-mpi/._schwarz.edp differ
diff --git a/examples++-mpi/._stokes-2d.edp b/examples++-mpi/._stokes-2d.edp
new file mode 100755
index 0000000..f6e69b8
Binary files /dev/null and b/examples++-mpi/._stokes-2d.edp differ
diff --git a/examples++-mpi/AddLayer2d.idp b/examples++-mpi/AddLayer2d.idp
new file mode 100644
index 0000000..df68abd
--- /dev/null
+++ b/examples++-mpi/AddLayer2d.idp
@@ -0,0 +1,62 @@
+// AddLayer2d.idf file..  version 0. 
+// Frederic Hecht 2010 
+// LGPL licence 
+// Author Frederic.Hecht at upmc.fr
+// ------------------------------- 
+
+func bool same(mesh & Th1,mesh & Th2)
+{
+  bool ret=0; 
+  //cout << mpirank << " same Th ?? " << Th1.nt << " "<< Th2.nt << " " << Th1.nv << " "<< Th2.nv << endl;
+  if(Th1.nt == Th2.nt && Th1.nv == Th2.nv)
+  {
+  	fespace V1(Th1,P1);
+  	fespace V2(Th2,P1);
+  	V1 x1=x,y1=y;
+  	V2 x2=x,y2=y;
+  	real err1= sqrt(int2d(Th1,qft=qf1pTlump)( square(x-x2) + square(y-y2)));
+  	real err2= sqrt(int2d(Th2,qft=qf1pTlump)( square(x-x1) + square(y-y1)));
+  	if(err1+err2 < Th1.nv*1e-6) ret=1;
+  	else if(verbosity>1) cout << "same no same mesh " << err1 << " " << err2 << endl; 
+  }
+  return  ret;
+}
+
+func bool AddLayers(mesh & Th,real[int] &ssd,int n,real[int] &unssd)
+{
+  //  build a continuous function  uussd (P1) and modifies ssd :
+  //  IN: ssd in the caracteristics function on the input sub domain.
+  //  OUT: ssd and unssd
+  //  such that : 
+  //   ssd is a boolean function 
+  //   unssd is a smooth function
+  //   ssd = 1 when   unssd >0;
+  //   add n layer of element (size of the overlap)
+  //   and unssd = 0 ouside of this layer ...
+  // ---------------------------------
+  fespace Vh(Th,P1);
+  fespace Ph(Th,P0);
+  Ph s;
+  assert(ssd.n==Ph.ndof);
+  assert(unssd.n==Vh.ndof);
+  unssd=0;
+  s[]= ssd;
+  Vh u;
+  varf vM(uuuu,v)=int2d(Th,qforder=1)(uuuu*v/area);
+  matrix M=vM(Ph,Vh);
+  
+  for(int i=0;i<n;++i)
+    {
+      u[]= M*s[];
+      u = u>.1; 
+      unssd+= u[];
+      s[]= M'*u[];
+      s = s >0.1;
+    }
+  unssd /= (n);
+  u[]=unssd;
+  ssd=s[];      
+  return true;
+}
+
+
diff --git a/examples++-mpi/AddLayer3d.idp b/examples++-mpi/AddLayer3d.idp
new file mode 100644
index 0000000..45c7543
--- /dev/null
+++ b/examples++-mpi/AddLayer3d.idp
@@ -0,0 +1,62 @@
+// AddLayer2d.idf file..  version 0. 
+// Frederic Hecht 2010 
+// LGPL licence 
+// Author Frederic.Hecht at upmc.fr
+// ------------------------------- 
+
+func bool same(mesh3 & Th1,mesh3 & Th2)
+{
+  bool ret=0; 
+  //cout << mpirank << " same Th ?? " << Th1.nt << " "<< Th2.nt << " " << Th1.nv << " "<< Th2.nv << endl;
+  if(Th1.nt == Th2.nt && Th1.nv == Th2.nv)
+  {
+  	fespace V1(Th1,P1);
+  	fespace V2(Th2,P1);
+  	V1 x1=x,y1=y,z1=z;
+  	V2 x2=x,y2=y,z2=z;
+  	real err1= sqrt(int3d(Th1,qft=qf1pTlump)( square(x-x2) + square(y-y2)+ square(z-z2)));
+  	real err2= sqrt(int3d(Th2,qft=qf1pTlump)( square(x-x1) + square(y-y1)+ square(z-z1)));
+  	if(err1+err2 < Th1.nv*1e-6) ret=1;
+  	else if(verbosity>1) cout << "same no same mesh " << err1 << " " << err2 << endl; 
+  }
+  return  ret;
+}
+
+func bool AddLayers(mesh3 & Th,real[int] &ssd,int n,real[int] &unssd)
+{
+  //  build a continuous function  uussd (P1) and modifies ssd :
+  //  IN: ssd in the caracteristics function on the input sub domain.
+  //  OUT: ssd and unssd
+  //  such that : 
+  //   ssd is a boolean function 
+  //   unssd is a smooth function
+  //   ssd = 1 when   unssd >0;
+  //   add n layer of element (size of the overlap)
+  //   and unssd = 0 ouside of this layer ...
+  // ---------------------------------
+  fespace Vh(Th,P1);
+  fespace Ph(Th,P0);
+  Ph s;
+  assert(ssd.n==Ph.ndof);
+  assert(unssd.n==Vh.ndof);
+  unssd=0;
+  s[]= ssd;
+  Vh u;
+  varf vM(uuuu,v)=int3d(Th,qforder=1)(uuuu*v/volume);
+  matrix M=vM(Ph,Vh);
+  
+  for(int i=0;i<n;++i)
+    {
+      u[]= M*s[];
+      u = u>.1; 
+      unssd+= u[];
+      s[]= M'*u[];
+      s = s >0.1;
+    }
+  unssd /= (n);
+  u[]=unssd;
+  ssd=s[];      
+  return true;
+}
+
+
diff --git a/examples++-mpi/DDM-NSUzawaCahouetChabart.edp b/examples++-mpi/DDM-NSUzawaCahouetChabart.edp
new file mode 100644
index 0000000..a73c9d8
--- /dev/null
+++ b/examples++-mpi/DDM-NSUzawaCahouetChabart.edp
@@ -0,0 +1,120 @@
+/*
+  example of 
+*/
+load "MPICG"  load "medit"  load "metis" 
+include "getARGV.idp"
+include "MPIplot.idp"
+include "DDM-Schwarz-macro.idp"
+include "AddLayer2d.idp"
+include "DDM-funcs-v2.idp"
+
+real D=0.1, H=0.41;
+real cx0 = 0.2, cy0 = 0.2; // center of cyl. 
+real xa = 0.15, ya=0.2, xe = 0.25,ye =0.2;
+border fr1(t=0,2.2){x=t; y=0; label=1;}
+border fr2(t=0,H){x=2.2; y=t; label=2;}
+border fr3(t=2.2,0){x=t; y=H; label=1;}
+border fr4(t=H,0){x=0; y=t; label=1;}
+border fr5(t=2*pi,0){x=cx0+D*sin(t)/2; y=cy0+D*cos(t)/2; label=3;}
+int nn=15;
+ 
+mesh Th=buildmesh(fr1(5*nn)+fr2(nn)+fr3(5*nn)+fr4(nn)+fr5(-nn*3));
+real Um= 1.5;// max velocity (Rey 100) 
+func Ub = Um*2./3.; 
+real nu = 1e-3; 
+real Rey = Ub*D/nu;
+// Boundary condition 
+func U1 = 4.*Um*y*(H-y)/(H*H)  ;
+func U2 = 0. ;
+
+ real T=2,t=0; 
+ real dt = D/nn/Um;// CFL = 1 
+ cout << " dt = " << dt <<endl;
+real alpha=1/dt,epspq=1e-10;
+
+
+fespace Mh(Th,[P1]);
+fespace Xh(Th,[P2]);
+fespace Wh(Th,[P1dc]);
+macro grad(u) [dx(u),dy(u)] //
+macro div(u1,u2) (dx(u1)+dy(u2)) //
+
+ 
+ varf von1([u1,u2,p],[v1,v2,q]) =  on(3,u1=0,u2=0) + on(1,u1=U1,u2=U2);
+
+//remark : the value 100 in next line is manualy fitted, because free outlet. 
+ varf vA(p,q) =int2d(Th)((grad( p ) '*grad(q)) ) + int1d(Th,2)(100*p*q) ;
+ varf vM(p,q) =int2d(Th,qft=qf2pT)(  p*q );
+
+ varf vu([u1],[v1]) = int2d(Th)(alpha*(u1*v1)+nu*(grad(u1)'*grad(v1) )) 
+                       + on(1,3,u1=0) ;
+ varf vu1([p],[v1]) = int2d(Th)(p*dx(v1)) ;
+ varf vu2([p],[v1]) = int2d(Th)(p*dy(v1)) ;
+   
+
+ matrix pAM=vM(Mh,Mh,solver=UMFPACK); 
+ matrix pAA=vA(Mh,Mh,solver=UMFPACK); 
+ matrix AU=vu(Xh,Xh,solver=UMFPACK); 
+ matrix B1=vu1(Mh,Xh);
+ matrix B2=vu2(Mh,Xh);
+ Xh u1,u2;
+ Mh p;
+varf vonu1([u1],[v1]) =  on(1,u1=U1) + on(3,u1=0);
+varf vonu2([u1],[v1]) =  on(1,u1=U2) + on(3,u1=0);
+
+
+real[int] brhs1 = vonu1(0,Xh);
+real[int] brhs2 = vonu2(0,Xh);
+ 
+varf  vrhs1(uu,vv)  = int2d(Th) (convect([u1,u2],-dt,u1)*vv*alpha)+vonu1 ;
+varf  vrhs2(v2,v1)  = int2d(Th) (convect([u1,u2],-dt,u2)*v1*alpha)+vonu2;
+
+
+func  real[int]   JUzawa(real[int] & pp) 
+{
+	real[int] b1=brhs1; b1 += B1*pp;
+	real[int] b2=brhs2; b2 += B2*pp;
+	u1[] = AU^-1 * b1;
+	u2[] = AU^-1 * b2;
+	pp  = B1'*u1[];
+	pp += B2'*u2[];
+	pp = -pp; 
+	return pp; 
+}
+
+func  real[int]   Precon(real[int] & p)
+ {  
+    real[int] pa= pAA^-1*p;
+    real[int] pm= pAM^-1*p;
+    real[int] pp= alpha*pa+nu*pm;
+ 
+  	return pp;
+ }
+
+ verbosity = 0; 
+ p=0;
+ 
+   
+ Wh w; // to store voticity ..
+  
+ real eps=1e-4;
+ int ndt = T/dt;
+ for(int i=0;i<ndt;++i)
+ {
+     brhs1 = vrhs1(0,Xh);
+     brhs2 = vrhs2(0,Xh);
+     int res=LinearCG(JUzawa,p[],precon=Precon,nbiter=100,verbosity=10,veps=eps); 
+     assert(res==1) ; 
+     eps = -abs(eps); 
+     w = -dy(u1)+dx(u2);
+     plot(w,fill=1,wait=0, nbiso=40,WindowIndex=1);
+    
+     dt = min(dt,T-t);
+     t += dt; 
+     if( dt < 1e-10*T) break;    
+ }
+ plot(w,fill=1,wait=0, nbiso=40,ps="NScahouetChabart.eps");
+ cout << " u1 max " << u1[].linfty 
+      << " u2 max " << u2[].linfty 
+      << " p max = " << p[].max << endl; 
+ 
\ No newline at end of file
diff --git a/examples++-mpi/DDM-Schwarz-Lame-2d.edp b/examples++-mpi/DDM-Schwarz-Lame-2d.edp
new file mode 100644
index 0000000..b1e7ffa
--- /dev/null
+++ b/examples++-mpi/DDM-Schwarz-Lame-2d.edp
@@ -0,0 +1,151 @@
+// NBPROC 50
+// ff-mpirun -np 4 DDM-Schwarz-Lap-3d.edp -glut ffglut  -n 11 -k 1  -d 1 -ns -gmres 1
+/*
+  a first true parallele example fisrt freefem++ 
+  Ok up to 200 proc for a Poisson equation.. 
+  See the Doc for full explaiantion
+
+  F Hecht Dec. 2010. 
+  -------------------
+usage :
+ff-mpirun [mpi parameter] MPIGMRES2d.edp  [-glut ffglut]  [-n N] [-k K]  [-d D] [-ns] [-gmres [0|1]
+ argument: 
+   -glut ffglut : to see graphicaly the process
+   -n N:  set the mesh cube split NxNxN
+   -d D:  set debug flag D must be one for mpiplot 
+   -k K:  to refined by K all  elemnt
+   -ns: reomove script dump
+   -gmres 0   : use iterative schwarz algo.  
+          1   :  Algo GMRES on residu of schwarz algo.
+          2   :  DDM GMRES 
+          3   :  DDM GMRES with coarse grid preconditionner (Good one)  
+*/
+load "MPICG"  load "medit"  load "metis"
+include "getARGV.idp"
+include "DDM-Schwarz-macro.idp"
+include "AddLayer2d.idp"
+include "DDM-funcs-v2.idp"
+
+
+searchMethod=1; // more safe seach algo (warning can be very expensive in case lot of ouside point) 
+// 0 by default
+assert(version >=3.11);
+real[int] ttt(10);int ittt=0;
+macro settt {ttt[ittt++]=mpiWtime();}//
+
+
+verbosity=getARGV("-vv",0);
+int vdebug=getARGV("-d",1);
+int ksplit=getARGV("-k",1);
+int nloc = getARGV("-n",10);
+string sff=getARGV("-p","");
+int gmres=getARGV("-gmres",3); 
+int nC = getARGV("-N" ,max(nloc/10,5)); 
+int sizeoverlaps=1; // size of overlap
+bool RAS=1; // select kind of  of $\pi_i$ 
+
+
+if(mpirank==0 && verbosity)
+  cout << " vdebug: " << vdebug << " kspilt "<< ksplit << " nloc "<< nloc << " sff "<< sff <<"."<< endl;
+
+
+string sPk="P2-Lame-2gd";     
+func Pk=[P2,P2];
+ 
+func bool  plotMPIall(mesh &Th,real[int] & u,string  cm)
+{if(vdebug) PLOTMPIALLU(mesh,Pk, defPk2, Th, u, allu1, { cmm=cm,nbiso=10,fill=1,dim=3,value=1}); return 1;}
+
+
+mpiComm comm(mpiCommWorld,0,0);// trick : make a no split mpiWorld 
+
+
+int ipart= mpiRank(comm); // current partition number 
+
+if(ipart==0)  cout << " Final N=" << ksplit*nloc << " nloc =" << nloc << " split =" << ksplit <<  endl;
+int[int] l111=[2,2,2,1]; 
+settt 
+
+mesh Thg=square(nloc*4,nloc,[x*4,y],label=l111);
+mesh ThC=square(nC*4,nC,[x*4,y],label=l111);//   Coarse Mesh
+fespace VhC(ThC,[P1,P1]); // of the coarse problem.. 
+
+BuildPartitioning(sizeoverlaps,mesh,Thg,Thi,aThij,RAS,pii,jpart,comm,vdebug)
+
+if(ksplit>1)
+{
+for(int jp=0;jp<jpart.n;++jp)
+  aThij[jp]  = trunc(aThij[jp],1,split=ksplit);
+Thi =   trunc(Thi,1,split=ksplit);
+}
+
+BuildTransferMat(ipart,mesh,Pk,2,[0,1],Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,vdebug)
+
+
+
+
+
+/* the definition of the Problem .... */
+
+
+// the definition of the Problem ....
+real E = 21.5e4;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2)  [dx(u1),dy(u2),(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u1,u2) ( dx(u1)+dy(u2) ) // EOM
+  
+varf vPb([u1,u2],[v1,v2])=
+  int2d(Thi)(  
+	    lambda*div(u1,u2)*div(v1,v2)	
+	    +2.*mu*( epsilon(u1,u2)'*epsilon(v1,v2) ) //')
+	      )
+  + int2d(Thi) (gravity*v2)
+  + on(1,10,u1=0,u2=0)
+  ;
+  
+varf vPbC([u1,u2],[v1,v2])=
+  int2d(ThC)(  
+	    lambda*div(u1,u2)*div(v1,v2)	
+	    +2.*mu*( epsilon(u1,u2)'*epsilon(v1,v2) ) //')
+	      )
+  + on(1,u1=0,u2=0)
+  ;
+
+varf vPbon10([u1,u2],[v1,v2])=on(10,u1=1,u2=1)+on(1,u1=0,u2=0);
+varf vPBC(U,V)=on(1,U=0);
+
+
+
+real[int] onG10 = vPbon10(0,Whi); // on 1 
+real[int] Bi=vPb(0,Whi);
+
+
+matrix Ai = vPb(Whi,Whi,solver=sparsesolver); 
+
+DMMDeffuncAndGlobals(Lame2,comm,jpart,Whi,Vhc,2,Ai,vPbC,onG10,Pii,Usend,Vrecv,[0,1])
+
+Lame2CheckUpdate();
+  
+Whi [u,u1],[v,v1];
+ 
+
+u[]=vPBC(0,Whi,tgv=1); 
+real eps=1e-10;
+Lame2DDMSolver(Bi,u,v,gmres,eps,vdebug)
+
+
+real errg =1,umaxg;
+{ 
+  real umax = u[].max,umaxg;
+  real[int] aa=[umax], bb(1);
+  mpiAllReduce(aa,bb,comm,mpiMAX);
+  errg=bb[0];
+  if(ipart==0)
+    cout << " umax global  = " << bb[0] << " Wtime = " << (ttt[ittt-1]-ttt[ittt-2])  << " s " <<  " " << Lame2kiter <<  endl;
+}
+
+Lame2Saveff(sff,eps,ksplit,nloc,sizeoverlaps); 
\ No newline at end of file
diff --git a/examples++-mpi/DDM-Schwarz-Lame-3d.edp b/examples++-mpi/DDM-Schwarz-Lame-3d.edp
new file mode 100644
index 0000000..7d64841
--- /dev/null
+++ b/examples++-mpi/DDM-Schwarz-Lame-3d.edp
@@ -0,0 +1,161 @@
+// NBPROC 10
+// ff-mpirun -np 4 DDM-Schwarz-Lap-3d.edp -glut ffglut  -n 11 -k 1  -d 1 -ns -gmres 1
+/*
+  a first true parallele example fisrt freefem++ 
+  Ok up to 200 proc for a Poisson equation.. 
+  See the Doc for full explaiantion
+
+  F Hecht Dec. 2010. 
+  -------------------
+usage :
+ff-mpirun [mpi parameter] MPIGMRES2d.edp  [-glut ffglut]  [-n N] [-k K]  [-d D] [-ns] [-gmres [0|1]
+ argument: 
+   -glut ffglut : to see graphicaly the process
+   -n N:  set the mesh cube split NxNxN
+   -d D:  set debug flag D must be one for mpiplot 
+   -k K:  to refined by K all  elemnt
+   -ns: reomove script dump
+   -gmres 0   : use iterative schwarz algo.  
+          1   :  Algo GMRES on residu of schwarz algo.
+          2   :  DDM GMRES 
+          3   :  DDM GMRES with coarse grid preconditionner (Good one)  
+*/
+load "MPICG"  load "medit"  load "metis"
+include "getARGV.idp"
+include "DDM-Schwarz-macro.idp"
+include "AddLayer3d.idp"
+include "DDM-funcs-v2.idp"
+include "cube.idp" 
+
+
+searchMethod=1; // more safe seach algo (warning can be very expensive in case lot of ouside point) 
+// 0 by default
+assert(version >=3.11);
+real[int] ttt(10);int ittt=0;
+macro settt {ttt[ittt++]=mpiWtime();}//
+
+
+verbosity=getARGV("-vv",0);
+int vdebug=getARGV("-d",1);
+int ksplit=getARGV("-k",1);
+int nloc = getARGV("-n",5);
+string sff=getARGV("-p","");
+int gmres=getARGV("-gmres",3); 
+int nC = getARGV("-N" ,max(nloc/10,5)); 
+int sizeoverlaps=1; // size of overlap
+bool RAS=1; 
+
+if(mpirank==0 && verbosity)
+  cout << " vdebug: " << vdebug << " kspilt "<< ksplit << " nloc "<< nloc << " sff "<< sff <<"."<< endl;
+
+string sPk="P2-Lame-3gd";     
+func Pk=[P2,P2,P2];
+
+func bool  plotMPIall(mesh3 &Th,real[int] & u,string  cm)
+{if(vdebug) PLOTMPIALLU(mesh3,Pk, defPk3, Th, u, allu2, { cmm=cm,nbiso=20,fill=1,dim=3,value=1}); return 1;}
+
+
+mpiComm comm(mpiCommWorld,0,0);// trick : make a no split mpiWorld 
+
+
+int ipart= mpiRank(comm); // current partition number 
+
+if(ipart==0)  cout << " Final N=" << ksplit*nloc << " nloc =" << nloc << " split =" << ksplit <<  endl;
+int[int] l111=[1,1,1,1]; 
+settt 
+
+
+int[int,int] LL=[[1,1],[2,1],[1,1]];
+real[int,int] BB=[[0,1],[0,5],[0,1]];
+int[int] NN=[nloc,nloc*5,nloc]; 
+int[int] NNC=[nC,nC*5,nC]; 
+
+
+settt 
+mesh3 Thg=Cube(NN,BB,LL);
+mesh3 ThC=Cube(NNC,BB,LL);
+
+fespace VhC(ThC,[P1,P1,P1]); // of the coarse problem.. 
+
+
+BuildPartitioning(sizeoverlaps,mesh3,Thg,Thi,aThij,RAS,pii,jpart,comm,vdebug)
+
+if(ksplit>1)
+{
+for(int jp=0;jp<jpart.n;++jp)
+  aThij[jp]  = trunc(aThij[jp],1,split=ksplit);
+Thi =   trunc(Thi,1,split=ksplit);
+}
+
+BuildTransferMat(ipart,mesh3,Pk,3,[0,1,2],Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,vdebug)
+
+
+
+
+
+/* the definition of the Problem .... */
+
+
+// the definition of the Problem ....
+real E = 21.5e4;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2,u3)  [dx(u1),dy(u2),dz(u3),(dz(u2)+dy(u3))/sqrt2,(dz(u1)+dx(u3))/sqrt2,(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u1,u2,u3) ( dx(u1)+dy(u2)+dz(u3) ) // EOM
+  
+varf vPb([u1,u2,u3],[v1,v2,v3])=
+  int3d(Thi)(  
+	    lambda*div(u1,u2,u3)*div(v1,v2,v3)	
+	    +2.*mu*( epsilon(u1,u2,u3)'*epsilon(v1,v2,v3) ) //')
+	      )
+  + int3d(Thi) (gravity*v3)
+  + on(2,10,u1=0,u2=0,u3=0)
+  ;
+  
+varf vPbC([u1,u2,u3],[v1,v2,v3])=
+  int3d(ThC)(  
+	    lambda*div(u1,u2,u3)*div(v1,v2,v3)	
+	    +2.*mu*( epsilon(u1,u2,u3)'*epsilon(v1,v2,v3) ) //')
+	      )
+  + int3d(ThC) (gravity*v3)
+  + on(2,u1=0,u2=0,u3=0)
+  ;
+
+varf vPbon10([u1,u2,u3],[v1,v2,v3])=on(10,u1=1,u2=1,u3=1)+on(2,u1=0,u2=0,u3=0);
+varf vPBC(U,V)=on(2,U=0);
+
+
+
+real[int] onG10 = vPbon10(0,Whi); // on 1 
+real[int] Bi=vPb(0,Whi);
+
+
+matrix Ai = vPb(Whi,Whi,solver=sparsesolver); 
+
+DMMDeffuncAndGlobals(Lame3,comm,jpart,Whi,Vhc,3,Ai,vPbC,onG10,Pii,Usend,Vrecv,[0,1,2])
+
+Lame3CheckUpdate();
+  
+Whi [u,u1,u2],[v,v1,v2];
+ 
+
+u[]=vPBC(0,Whi,tgv=1); 
+real eps=1e-10;
+Lame3DDMSolver(Bi,u,v,gmres,eps,vdebug)
+
+
+real errg =1,umaxg;
+{ 
+  real umax = u[].max,umaxg;
+  real[int] aa=[umax], bb(1);
+  mpiAllReduce(aa,bb,comm,mpiMAX);
+  errg=bb[0];
+  if(ipart==0)
+    cout << " umax global  = " << bb[0] << " Wtime = " << (ttt[ittt-1]-ttt[ittt-2])  << " s " <<  " " << Lame3kiter <<  endl;
+}
+
+Lame3Saveff(sff,eps,ksplit,nloc,sizeoverlaps); 
\ No newline at end of file
diff --git a/examples++-mpi/DDM-Schwarz-Lap-2dd.edp b/examples++-mpi/DDM-Schwarz-Lap-2dd.edp
new file mode 100644
index 0000000..34e0fd8
--- /dev/null
+++ b/examples++-mpi/DDM-Schwarz-Lap-2dd.edp
@@ -0,0 +1,131 @@
+// NBPROC 10
+/*
+  a first true parallele example fisrt freefem++ 
+  Ok up to 200 proc for a Poisson equation.. 
+  See the Doc for full explaiantion
+
+  F Hecht Dec. 2010. 
+  -------------------
+usage :
+ff-mpirun [mpi parameter]  DDM-Schwarz-Lap-2dd.edp  [-glut ffglut]  [-n N] [-k K]  [-d D] [-ns] [-gmres [0|1]
+ argument: 
+   -glut ffglut : to see graphicaly the process
+   -n N:  set the mesh cube split NxNxN
+   -d D:  set debug flag D must be one for mpiplot 
+   -k K:  to refined by K all  elemnt
+   -ns: reomove script dump
+   -gmres 0   : use iterative schwarz algo.  
+          1   :  Algo GMRES on residu of schwarz algo.
+          2   :  DDM GMRES 
+          3   :  DDM GMRES with coarse grid preconditionner (Good one)  
+*/
+load "MPICG"  load "medit"  load "metis"
+include "getARGV.idp"
+include "MPIplot.idp"
+include "DDM-Schwarz-macro.idp"
+include "AddLayer2d.idp"
+include "DDM-funcs-v2.idp"
+
+
+searchMethod=1; // more safe seach algo (warning can be very expensive in case lot of ouside point) 
+// 0 by default
+
+assert(version >=3.11);
+real[int] ttt(10);int ittt=0;
+macro settt {ttt[ittt++]=mpiWtime();}//
+
+
+verbosity=getARGV("-vv",0);
+int vdebug=getARGV("-d",1);
+int ksplit=getARGV("-k",1);
+int nloc = getARGV("-n",10);
+string sff=getARGV("-p","");
+int gmres=getARGV("-gmres",3); 
+int nC = getARGV("-N" ,max(nloc/10,5)); 
+int sizeoverlaps=1; // size of overlap
+bool RAS=1;  // Global Variable ..
+
+
+
+if(mpirank==0 && verbosity)
+  cout << " vdebug: " << vdebug << " kspilt "<< ksplit << " nloc "<< nloc << " sff "<< sff <<"."<< endl;
+
+string sPk="P2-2gd";     
+func Pk=P2;
+
+func bool  plotMPIall(mesh &Th,real[int] & u,string  cm)
+{if(vdebug) PLOTMPIALL(mesh,Pk, Th, u,{ cmm=cm,nbiso=20,fill=1,dim=3,value=1}); return 1;}
+
+mpiComm comm(mpiCommWorld,0,0);// trick : make a no split mpiWorld 
+
+
+int iiipart= mpiRank(comm); // current partition number 
+
+
+if(iiipart==0)  cout << " Final N=" << ksplit*nloc << " nloc =" << nloc << " split =" << ksplit <<  endl;
+int[int] l111=[1,2,2,2]; 
+settt 
+
+mesh Thg=square(nloc,nloc*5,[x,5*y],label=l111);
+mesh ThC=square(nC,nC*5,[x,5*y],label=l111);//   Caarse Mesh
+fespace VhC(ThC,P1); // of the coarse problem.. 
+
+
+BuildPartitioning(sizeoverlaps,mesh,Thg,Thi,aThij,RAS,pii,jpart,comm,vdebug)
+
+if(ksplit>1)
+{
+ for(int jp=0;jp<jpart.n;++jp)
+  aThij[jp]  = trunc(aThij[jp],1,split=ksplit);
+ Thi =   trunc(Thi,1,split=ksplit);
+}
+
+BuildTransferMat(iiipart,mesh,Pk,1,[0],
+                 Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,vdebug)
+
+Whi ui,vi; 
+
+
+
+/* the definition of the Problem .... */
+func G=1.; /* ok  */
+func F=1.; /* ok  */
+macro grad(u) [dx(u),dy(u)] //
+// warning for Dir. BC. the last win 
+varf vPb(U,V)= int2d(Thi)(grad(U)'*grad(V)) + int2d(Thi)(F*V) + on(10,U=0)+on(1,U=G) ; //');// for emacs
+varf vPbC(U,V)= int2d(ThC)(grad(U)'*grad(V))  +on(1,U=0) ; //');// for emacs
+varf vPbon10(U,V)=on(10,U=1)+on(1,U=0);
+
+varf vPBC(U,V)=on(1,U=G);
+
+
+real[int] onG10 = vPbon10(0,Whi); // on 1 
+real[int] Bi=vPb(0,Whi);
+
+
+matrix Ai = vPb(Whi,Whi,solver=sparsesolver); 
+
+DMMDeffuncAndGlobals(Lap2,comm,jpart,Whi,Vhc,1,Ai,vPbC,onG10,Pii,Usend,Vrecv,[0])
+
+Lap2CheckUpdate(); 
+  
+Whi u=0,v;
+ 
+
+u[]=vPBC(0,Whi,tgv=1); 
+real eps=1e-10;
+Lap2DDMSolver(Bi,u,v,gmres,eps,vdebug)
+
+
+real errg =1,umaxg;
+
+{ 
+  real umax = u[].max,umaxg;
+  real[int] aa=[umax], bb(1);
+  mpiAllReduce(aa,bb,comm,mpiMAX);
+  errg=bb[0];
+  if(iiipart==0)
+    cout << " umax global  = " << bb[0] << " Wtime = " << (ttt[ittt-1]-ttt[ittt-2])  << " s " <<  " " << Lap2kiter <<  endl;
+}
+
+Lap2Saveff(sff,eps,ksplit,nloc,sizeoverlaps); 
\ No newline at end of file
diff --git a/examples++-mpi/DDM-Schwarz-Lap-3d.edp b/examples++-mpi/DDM-Schwarz-Lap-3d.edp
new file mode 100644
index 0000000..f70d268
--- /dev/null
+++ b/examples++-mpi/DDM-Schwarz-Lap-3d.edp
@@ -0,0 +1,136 @@
+// NBPROC 10
+// ff-mpirun -np 4 DDM-Schwarz-Lap-3d.edp -glut ffglut  -n 11 -k 1  -d 1 -ns -gmres 1
+/*
+  a first true parallele example fisrt freefem++ 
+  Ok up to 200 proc for a Poisson equation.. 
+  See the Doc for full explaiantion
+
+  F Hecht Dec. 2010. 
+  -------------------
+ argument: 
+   -glut ffglut : to see graphicaly the process
+   -n N:  set the mesh cube split NxNxN
+   -d D:  set debug flag D must be one for mpiplot 
+   -k K:  to refined by K all  elemnt
+   -ns: reomove script dump
+   -gmres 0   : use iterative schwarz algo.  
+          1   :  Algo GMRES on residu of schwarz algo.
+          2   :  DDM GMRES 
+          3   :  DDM GMRES with coarse grid preconditionner (Good one)  
+*/
+
+load "MPICG"  load "medit"  load "metis"
+include "getARGV.idp"
+include "DDM-Schwarz-macro.idp"
+include "AddLayer3d.idp"
+include "DDM-funcs-v2.idp"
+include "cube.idp" 
+include "MPIplot.idp"
+
+searchMethod=1; // more safe seach algo (warning can be very expensive in case lot of ouside point) 
+// 0 by default
+assert(version >=3.11);
+real[int] ttt(10);int ittt=0;
+macro settt {ttt[ittt++]=mpiWtime();}//
+
+
+verbosity=getARGV("-vv",0);
+int vdebug=getARGV("-d",1);
+int ksplit=getARGV("-k",1);
+int nloc = getARGV("-n",20);
+string sff=getARGV("-p","");
+int gmres=getARGV("-gmres",3);
+int tsolver = getARGV("-ts",int(CG)); 
+int nC = getARGV("-N" ,max(nloc/10,5)); 
+int sizeoverlaps=1; // size of overlap
+bool RAS=1; 
+
+if(mpirank==0 && verbosity)
+  cout << " vdebug: " << vdebug << " kspilt "<< ksplit << " nloc "<< nloc << " sff "<< sff <<"."<< endl;
+
+string sPk="P2-3gd";     
+func Pk=P2;
+int Pknbcomp=1; 
+
+func bool  plotMPIall(mesh3 &Th,real[int] & u,string  cm)
+{ if(vdebug) PLOTMPIALL(mesh3,Pk, Th, u,{ cmm=cm,nbiso=4,fill=1,dim=3,value=1}); return 1;}
+
+mpiComm comm(mpiCommWorld,0,0);// trick : make a no split mpiWorld 
+
+
+int ipart= mpiRank(comm); // current partition number 
+
+if(ipart==0)  cout << " Final N=" << ksplit*nloc << " nloc =" << nloc << " split =" << ksplit <<  endl;
+
+int[int] l111=[1,1,1,1]; 
+settt 
+
+
+int[int,int] LL=[[1,1],[1,1],[1,1]];
+real[int,int] BB=[[0,1],[0,1],[0,1]];
+int[int] NN=[nloc,nloc,nloc]; 
+int[int] NNC=[nC,nC,nC]; 
+settt 
+mesh3 Thg=Cube(NN,BB,LL);
+mesh3 ThC=Cube(NNC,BB,LL);
+
+fespace VhC(ThC,P1); // of the coarse problem.. 
+
+
+BuildPartitioning(sizeoverlaps,mesh3,Thg,Thi,aThij,RAS,pii,jpart,comm,vdebug)
+
+if(ksplit>1)
+{
+for(int jp=0;jp<jpart.n;++jp)
+  aThij[jp]  = trunc(aThij[jp],1,split=ksplit);
+Thi =   trunc(Thi,1,split=ksplit);
+}
+
+BuildTransferMat(ipart,mesh3,Pk,1,[0],
+                 Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,vdebug)
+
+Whi ui,vi; 
+
+
+
+/* the definition of the Problem .... */
+func G=1.; /* ok  */
+func F=1.; /* ok  */
+macro grad(u) [dx(u),dy(u),dz(u)] //
+// warning for Dir. BC. the last win 
+varf vPb(U,V)= int3d(Thi)(grad(U)'*grad(V)) + int3d(Thi)(F*V) + on(10,U=0)+on(1,U=G) ; //');// for emacs
+varf vPbC(U,V)= int3d(ThC)(grad(U)'*grad(V))  +on(1,U=0) ; //');// for emacs
+varf vPbon10(U,V)=on(10,U=1)+on(1,U=0);
+
+varf vPBC(U,V)=on(1,U=G);
+
+
+real[int] onG10 = vPbon10(0,Whi); // on 1 
+real[int] Bi=vPb(0,Whi);
+
+
+matrix Ai = vPb(Whi,Whi,solver=tsolver); 
+
+DMMDeffuncAndGlobals(Lap3,comm,jpart,Whi,Vhc,1,Ai,vPbC,onG10,Pii,Usend,Vrecv,[0])
+
+Lap3CheckUpdate();
+  
+Whi u=0,v;
+ 
+
+u[]=vPBC(0,Whi,tgv=1); 
+real eps=1e-10;
+Lap3DDMSolver(Bi,u,v,gmres,eps,vdebug)
+
+
+real errg =1,umaxg;
+{ 
+  real umax = u[].max,umaxg;
+  real[int] aa=[umax], bb(1);
+  mpiAllReduce(aa,bb,comm,mpiMAX);
+  errg=bb[0];
+  if(ipart==0)
+    cout << " umax global  = " << bb[0] << " Wtime = " << (ttt[ittt-1]-ttt[ittt-2])  << " s " <<  " " << Lap3kiter <<  endl;
+}
+
+Lap3Saveff(sff,eps,ksplit,nloc,sizeoverlaps); 
\ No newline at end of file
diff --git a/examples++-mpi/DDM-Schwarz-Stokes-2d.edp b/examples++-mpi/DDM-Schwarz-Stokes-2d.edp
new file mode 100644
index 0000000..f04575a
--- /dev/null
+++ b/examples++-mpi/DDM-Schwarz-Stokes-2d.edp
@@ -0,0 +1,168 @@
+// NBPROC 2
+// ff-mpirun -np 4 DDM-Schwarz-Stokes-2d.edp -glut ffglut  -n 11 -k 1  -d 1 -ns -gmres 1
+/*
+  a first true parallele example fisrt freefem++ 
+  Ok up to 200 proc for a Poisson equation.. 
+  See the Doc for full explaiantion
+
+  F Hecht Dec. 2010. 
+  -------------------
+usage :
+ff-mpirun [mpi parameter]  DDM-Schwarz-Stokes-2d.edp   [-glut ffglut]  [-n N] [-k K]  [-d D] [-ns] [-gmres [0|1]
+ argument: 
+   -glut ffglut : to see graphicaly the process
+   -n N:  set the mesh cube split NxNxN
+   -d D:  set debug flag D must be one for mpiplot 
+   -k K:  to refined by K all  elemnt
+   -ns: reomove script dump
+   -gmres 0   : use iterative schwarz algo.  
+          1   :  Algo GMRES on residu of schwarz algo.
+          2   :  DDM GMRES 
+          3   :  DDM GMRES with coarse grid preconditionner (Good one)  
+*/
+load "MPICG"  load "medit"  load "metis"
+include "getARGV.idp"
+include "DDM-Schwarz-macro.idp"
+include "AddLayer2d.idp"
+include "DDM-funcs-v2.idp"
+
+
+searchMethod=1; // more safe seach algo (warning can be very expensive in case lot of ouside point) 
+// 0 by default
+assert(version >=3.11);
+real[int] ttt(10);int ittt=0;
+macro settt {ttt[ittt++]=mpiWtime();}//
+
+
+verbosity=getARGV("-vv",0);
+int vdebug=getARGV("-d",1);
+int ksplit=getARGV("-k",1);
+int nloc = getARGV("-n",10);
+string sff=getARGV("-p","");
+int gmres=getARGV("-gmres",0); 
+int nC = getARGV("-N" ,max(nloc/10,5)); 
+bool RAS=1; 
+int sizeoverlaps=1; // size of overlap
+
+
+if(mpirank==0 && verbosity)
+  cout << " vdebug: " << vdebug << " kspilt "<< ksplit << " nloc "<< nloc << " sff "<< sff <<"."<< endl;
+
+
+string sPk="P2-Stokes-2gd";     
+func Pk=[P2,P2,P1];
+//int  Pknbcomp=3; 
+
+func bool  plotMPIall(mesh &Th,real[int] & u,string  cm)
+{if(vdebug) PLOTMPIALLU(mesh,Pk, defPk3, Th, u, allu1, { cmm=cm,nbiso=10,fill=1,dim=3,value=1}); return 1;}
+func bool  plotMPIallp(mesh &Th,real[int] & u,string  cm)
+{if(vdebug) PLOTMPIALLU(mesh,Pk, defPk3, Th, u, allu2, { cmm=cm,nbiso=10,fill=1,dim=3,value=1}); return 1;}
+
+
+mpiComm comm(mpiCommWorld,0,0);// trick : make a no split mpiWorld 
+
+
+int ipart= mpiRank(comm); // current partition number 
+
+if(ipart==0)  cout << " Final N=" << ksplit*nloc << " nloc =" << nloc << " split =" << ksplit <<  endl;
+int[int] l111=[1,1,2,1]; 
+settt 
+
+mesh Thg=square(nloc,nloc,[x,y],label=l111);
+mesh ThC=square(nC,nC,[x,y],label=l111);//   Coarse Mesh
+
+fespace VhC(ThC,[P2,P2,P1]); // of the coarse problem.. 
+
+
+BuildPartitioning(sizeoverlaps,mesh,Thg,Thi,aThij,RAS,pii,jpart,comm,vdebug)
+
+if(ksplit>1)
+{
+for(int jp=0;jp<jpart.n;++jp)
+  aThij[jp]  = trunc(aThij[jp],1,split=ksplit);
+Thi =   trunc(Thi,1,split=ksplit);
+}
+
+BuildTransferMat(ipart,mesh,Pk,3,[0,1,-1],Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,vdebug)
+
+
+
+
+
+/* the definition of the Problem .... */
+
+
+// the definition of the Problem ....
+// the definition of the Problem ....
+func u1bc= (1.-x)*(x)*4.;
+// the definition of the Problem ....
+macro grad(u) [dx(u),dy(u)] //  
+macro div(u1,u2) (dx(u1)+dy(u2)) // 
+real nu=1,alpha=0;
+varf vPb([u1,u2,p],[v1,v2,q])=
+  int2d(Thi)(  
+       [u1,u2]'*[v1,v2]* alpha
+	   + (   grad(u1)'*grad(v1)
+	       + grad(u2)'*grad(v2)
+	        ) *nu
+	       - div(u1,u2)*q - div(v1,v2)*p +1e-9*p*q)
+  + on(10,u1=0,u2=0)	      
+  + on(2,u1=u1bc,u2=0)
+  + on(1,u1=0,u2=0)
+ ;
+  
+varf vPbC([u1,u2,p],[v1,v2,q])=
+  int2d(ThC)(  
+       [u1,u2]'*[v1,v2]* alpha
+	   + (   grad(u1)'*grad(v1)
+	       + grad(u2)'*grad(v2)
+	        ) *nu
+	       - div(u1,u2)*q - div(v1,v2)*p +1e-9*p*q)	      
+  + on(1,2,u1=0,u2=0)
+  ;
+ 
+varf vPbon10([u1,u2,p],[v1,v2,q])=on(10,u1=1,u2=1)+on(1,2,u1=0,u2=0);
+varf vPBC(U,V)=on(1,2,U=0);
+
+
+
+
+real[int] onG10 = vPbon10(0,Whi); // on 1 on 10 
+real[int] Bi=vPb(0,Whi);
+
+
+matrix Ai = vPb(Whi,Whi,solver=sparsesolver); 
+
+DMMDeffuncAndGlobals(Stokes2,comm,jpart,Whi,Vhc,3,Ai,vPbC,onG10,Pii,Usend,Vrecv,[0,1,-1])
+
+
+  
+Whi [u,u1,p],[v,v1,q];
+ 
+
+u[]=vPb(0,Whi,tgv=1); 
+real eps=1e-10;
+Stokes2DDMSolver(Bi,u,v,gmres,eps,vdebug)
+
+
+plotMPIall(Thi,v[],"u-final");
+plotMPIallp(Thi,v[],"p-final");
+{  //  update the pressure 
+   /* find c_i such that 
+    i,j  (O_i \cap O_j)  int(O_i \cap O_j) (p_i -  c_i - p_j + c_j) = 0
+    int (O_i \cap O_j) (c_i - c_j) = int (O_i \cap O_j) p_i - p_j ;  
+   */
+   1;
+}
+
+real errg =1,umaxg;
+{ 
+  real umax = u[].max,umaxg;
+  real[int] aa=[umax], bb(1);
+  mpiAllReduce(aa,bb,comm,mpiMAX);
+  errg=bb[0];
+  if(ipart==0)
+    cout << " umax global  = " << bb[0] << " Wtime = " << (ttt[ittt-1]-ttt[ittt-2])  << " s " <<  " " << Stokes2kiter <<  endl;
+}
+
+Stokes2Saveff(sff,eps,ksplit,nloc,sizeoverlaps); 
\ No newline at end of file
diff --git a/examples++-mpi/DDM-Schwarz-macro.idp b/examples++-mpi/DDM-Schwarz-macro.idp
new file mode 100644
index 0000000..8843a72
--- /dev/null
+++ b/examples++-mpi/DDM-Schwarz-macro.idp
@@ -0,0 +1,396 @@
+// MPIGMRSmacro.idp  file..  version 0.1
+// include in MPIGMRES.edp file ..
+// Frederic Hecht 2010 
+// LGPL licence 
+// Author Frederic.Hecht at upmc.fr
+// ------------------------------- 
+
+//  macro to def // send-recv message 
+// -----------------------------------
+
+/******************************************************************/ 
+func real  maxM(matrix & A)
+  {
+  	int[int] I(1),J(1);
+  	real[int] C(1);
+  	[I,J,C] =A;
+  	return C.max ;
+  }
+  
+/******************************************************************/   
+macro  InitU(n,Vh,Th,aTh,U)
+Vh[int] U(n);
+for(int j=0;j<n;++j)
+  {  
+  	 Th=aTh[j];
+  	 U[j]=0;
+  }
+//EOM
+
+/******************************************************************/ 
+macro   ISendRecvAny(comm,jpart,Si,Ri)
+{ /* sorry no Irecv of complex objet ...*/
+  int n= jpart.n,nn=n+n;
+  if(vdebug) cout << mpirank << " --ISendRecvAny " << n << endl;
+  mpiRequest[int] rq(nn);
+  
+  for (int j=0;j<n;++j)
+    Irecv(processor(jpart[j],comm,rq[j]),Ri[j]);
+  if(vdebug) cout << mpirank << " ++ISendRecvAny " << n << endl;
+  
+  for (int j=0;j<n;++j)
+    Isend(processor(jpart[j],comm,rq[n+j]),Si[j]);
+for (int j=0;j<nn;++j)
+  {
+  int k= mpiWaitAny(rq);
+  if(vdebug)
+    cout << " ++ISendRecvAny wait: get " << k << endl;
+  }
+}
+//EOM
+
+/******************************************************************/ 
+macro   SendRecvAny(comm,jpart,Si,Ri)
+{  verbosity=200;
+ 	int n= jpart.n;
+ 	for (int j=0;j<n;++j)
+       processor(comm,jpart[j]) << Si[j];
+    cout << " ** wait revc " << endl;
+ 	for (int j=0;j<n;++j)
+       processor(comm,jpart[j]) >> Ri[j];
+}
+// EOM 
+
+/******************************************************************/ 
+macro CheckUV(comm,jpart,Si,Ri)
+{
+	 	int n= jpart.n;
+  		int[int] rn(n),sn(n),in(n);
+ 		for (int j=0;j<n;++j) 
+ 		  { sn[j]= Si[j][].n;		  	  
+ 		   processor(jpart[j],comm) << sn[j];
+ 		   processor(jpart[j],comm) << ipart;
+ 		  }
+ 		 for (int j=0;j<n;++j) 
+ 		   processor(jpart[j],comm) >> rn[j];
+ 		 for (int j=0;j<n;++j) 
+ 		   processor(jpart[j],comm) >> in[j];
+
+ 		 int err=0;
+ 		 for (int j=0;j<n;++j) 
+ 		  { 
+ 		   int rj=Ri[j][].n;
+ 		   err += rj != rn[j];
+ 		   cout << rj << " s ========= r " << rn[j] << "      " << ipart << " <->  " << in[j] << " " << err << endl;  
+ 		   
+ 		  }
+ 	     assert(err==0);
+}//EOM
+
+/******************************************************************/ 
+macro   SendRecvUV(comm,jpart,Si,Ri)
+{
+ 	int n= jpart.n;
+	mpiRequest[int] rq(n);
+    for (int j=0;j<n;++j)
+       Irecv(processor(jpart[j],comm,rq[j]), Ri[j][]);
+       
+ 	for (int j=0;j<n;++j)
+       processor(jpart[j],comm) << Si[j][];
+  /* 	for (int j=0;j<n;++j)
+       processor(jpart[j],comm) >> Ri[j][];*/
+ 
+    for (int j=0;j<n;++j)
+	   int k= mpiWaitAny(rq);
+}
+// EOF 
+
+   /* Trick  */
+ 
+/**********************************************************/
+macro BuildPartitioning(sizeoverlaps,mesh,Thg,Thi,aThij,RAS,pii,jpart,comm,vdebug) 
+/**********************************************************/
+
+int[int] jpart(mpiSize(comm)); /*  list of jpart */
+mesh[int] aThij(1); 
+mesh Thi;
+Thi=Thg;
+fespace Vhi(Thi,P1); /**/
+Vhi pii;  
+
+{
+ int npart = mpiSize(comm);
+ fespace Phg(Thg,P0);
+ fespace Vhg(Thg,P1);
+
+  int njpart=0;
+  int ipart= mpiRank(comm);
+    /* a good trick : int#mesh =  */
+  func  intmesh= int2d;
+  func  intmesh3=int3d;
+  /* end trick */ 
+int dplot1 =0;
+int vdebug1 = vdebug;
+Phg  part;
+mesh Thin;
+/* build the partitioning ...  */
+{    
+ int[int] nupart(Thg.nt);
+ nupart=0; 
+ if(npart>1 && ipart==0)
+   metisdual(nupart,Thg,npart); 
+   
+ broadcast(processor(0,comm),nupart);
+ for(int i=0;i<nupart.n;++i)
+    part[][i]=nupart[i];
+  
+} /* build ...  */
+
+
+if(vdebug>10&& mpirank==0 && !NoGraphicWindow)
+  plot(part,fill=1,cmm="dual",wait=1);
+
+/* overlapping partition  */
+
+ Phg suppi= abs(part-ipart)<0.1; 
+ Vhg unssd;                       /* boolean function 1 in the subdomain 0 elswhere  */
+ Thin=trunc(Thg,suppi>0,label=10); /* non-overlapping mesh, interfaces have label 10 */
+ int nnn = sizeoverlaps*2;/* to be sure  */
+ AddLayers(Thg,suppi[],nnn,unssd[]);    /* see above ! suppi and unssd are modified   */
+ unssd[] *= nnn;  /*  to put value nnn a 0   */
+ real nnn0 = nnn - sizeoverlaps +  0.001   ;
+ Thi=trunc(Thg,unssd>nnn0 ,label=10); /* overlapping mesh, interfaces have label 10 */
+ 
+ settt 
+
+
+ int npij=npart;
+ Vhi[int] pij(npij);/* local partition of unit + pii  */
+ 
+ 
+ real nnn1=  + 0.001  ;
+ { /*
+   construction of the partition of the unit,
+    let phi_i P1 FE function 1 on Thin and zero ouside of Thi and positive
+    the partition is build with  
+  $$  p_i = phi_i/ \sum phi_i 
+    
+    to build the partition of one domain i
+    we nned to find all j such that supp(phi_j) \cap supp(phi_j) is not empty
+    <=> int phi_j
+ */
+ /*   build a local mesh of thii such that all compuation of the unit partition are  */
+ /*   exact in thii  */
+ mesh Thii=trunc(Thg,unssd>nnn1 ,label=10); /* overlapping mesh, interfaces have label 10  */
+
+
+ {  
+   /* find all j  mes (supp(p_j) \cap supp(p_i)) >0   */
+   /* compute all phi_j on Thii  */
+   /*  remark supp p_i include in Thi  */
+   /*   */
+   fespace Phii(Thii,P0);
+   fespace Vhii(Thii,P1);
+   Vhi sumphi=0;
+   jpart=0;
+   njpart=0;
+   int nlayer=RAS?1:sizeoverlaps;
+   if(ipart==0) 
+     cout <<" nlayer=" << nlayer << endl;
+   pii= max(unssd-nnn+nlayer,0.)/nlayer;
+   if(dplot1) plot(pii,wait=1,cmm=" 0000");
+   sumphi[] +=  pii[];
+   if(dplot1) plot(sumphi,wait=1,cmm=" summ 0000");
+   Vhii phii=0;
+   real epsmes=1e-10*Thii.mesure;
+   /*cout <<  " epsmes = " << epsmes <<endl;*/
+   for (int i=0;i<npart;++i)
+     if(i != ipart ) 
+       { 
+	    Phii suppii=abs(i-part)<0.2; 
+	    if(suppii[].max > 0.5) 
+	    {
+	     AddLayers(Thii,suppii[],nlayer,phii[]);
+	 	 assert(phii[].min >= -1e-10);
+	     real interij = int#mesh(Thi)(  phii); 
+	     if(interij>epsmes) 
+	       {  
+		     pij[njpart]=abs(phii);	 
+		     if(vdebug1>2) cout << " ***** " << int#mesh(Thi)(real(pij[njpart])<0) << " " <<pij[njpart][].min << " " << phii[].min << endl;
+		     assert(int#mesh(Thi)(real(pij[njpart])<0) ==0);
+		     if(dplot1)  plot(pij[njpart],wait=1,cmm=" j = "+ i + " " + njpart);
+		     sumphi[] += pij[njpart][]; 
+		     if(dplot1)  plot(sumphi,wait=1,cmm=" sum j = "+ i + " " + njpart);
+		     jpart[njpart++]=i;
+	       }}}
+    
+    
+    
+   if(dplot1) plot(sumphi,wait=1,dim=3,cmm="sum ",fill=1 );
+   pii[]=pii[] ./ sumphi[];
+   for (int j=0;j<njpart;++j)
+     pij[j][] = pij[j][] ./ sumphi[];
+   jpart.resize(njpart);
+    for (int j=0;j<njpart;++j)
+     assert(pij[j][].max<=1);
+   {
+     cout << ipart << " number of jpart " << njpart << " : ";
+     for (int j=0;j<njpart;++j)
+       cout << jpart[j] << " ";
+  	cout << endl;
+   }
+   sumphi[]=pii[];
+   for (int j=0;j<njpart;++j)
+     sumphi[]+= pij[j][];
+   if(vdebug1>2)  
+     cout << " sum min " <<sumphi[].min << " " << sumphi[].max << endl;
+   assert(sumphi[].min> 1.-1e-6 && sumphi[].max< 1.+1e-6);  
+   /*  verification  */
+ }}/* (Thii is remove here)  */
+  /* end of the construction of the local partition of the unity ... */
+  /* on Thi ...   */
+  /* ----------------------------------------------------------------- */
+if(mpiRank(comm)==0) cout << " *** end build partition " << endl;
+
+/*  computation of  number of intersection .. */
+/* ------------------------------------------ */
+
+/* here  pii and the pij is the locate partition of the unite on  */
+/* Thi ( mesh with overlap ).... */
+/*Thi=splitmesh(Thi,2); */
+if(dplot1 ) 
+  { plot(Thi,wait=1); 
+    for(int j=0;j<njpart;++j)
+      plot(pij[j],cmm=" j="+j ,wait=1); } 
+      
+/*  Partition of the unity on Thi ..  */
+/* computation of message.  */
+/* all j> we have to recive  */
+/* data on intersection of the support of pij[0] and pij[j] */
+settt 
+
+
+  
+ aThij.resize(njpart);
+/* construction of the mesh intersect i,j part  */
+for(int jp=0;jp<njpart;++jp)
+  aThij[jp]  = trunc(Thi,pij[jp]>1e-6,label=10); /* mesh of the supp of pij  */
+}
+if(mpiRank(comm)==0) cout << " *** end build mesh  intersection  " << endl;
+// EOM 
+macro defPk1(i,j) i j // 
+macro defPk2(i,j) [i j,i#1 j]// 
+macro defPk3(i,j) [i j,i#1 j,i#2 j]// 
+macro defPk4(i,j) [i j,i#1 j,i#2 j,i#3 j]// 
+macro defPk5(i,j) [i j,i#1 j,i#2 j,i#3 j, i#4 j]// 
+macro Times1(i) i  // 
+macro Times2(i) [i,i]// 
+macro Times3(i) [i,i,i]// 
+macro Times4(i) [i,i,i,i]// 
+macro Times5(i) [i,i,i,i,i]// 
+macro  InitUdef(n,Vh,Th,aTh,U,N)
+Vh[int] defPk#N(U,)(n);
+for(int j=0;j<n;++j)
+  {  
+  	 Th=aTh[j];
+  	 defPk#N(U,[j])=Times#N(0.);
+  }
+//EOM
+
+
+/******************************************************************/ 
+macro BuildTransferMat2(ipart,mesh,Pk,N,U2V,Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,Pii,vdebug)
+/******************************************************************/ 
+/* construction of transfert  matrix  
+mesh: mesh or mesh3
+Pk : the Pk def 
+N : the number of componant
+Whi: the FE space on Thi (def here)
+Whij: the array of FE on each intersection 
+Thij: the mesh variable to change Whij mesh
+aThij: the array of intersect mesh with Thi
+
+jpart[j]: the j th Sub Domain intersecting Thi
+*/
+
+
+matrix[int] sMj(jpart.n), rMj(jpart.n); /* M of send to j  */
+fespace Whi(Thi,Pk);
+mesh Thij=Thi;
+fespace Whij(Thij,Pk);/*  */
+ matrix Pii; 
+{
+ 
+ int njpart= jpart.n; /* njpart:  number of intersection which */
+  Whi defPk#N(wpii,)=Times#N(pii);
+  Pii = wpii[];
+  for(int jp=0;jp<njpart;++jp)
+    {
+      int j=jpart[jp];
+      Thij = aThij[jp];
+      int [int] U2Vdata=[0];
+      matrix I = interpolate(Whij,Whi,U2Vc=U2Vdata); /* Whji <- Whi  */
+      sMj[jp] = I*Pii;  /* Whi -> s Whij   */
+      rMj[jp] = interpolate(Whij,Whi,t=1,U2Vc=U2Vdata);   /* Whji -> Whi  */
+      if(vdebug>10) {
+      {Whi defPk#N(uuu,)=Times#N(1),defPk#N(vvv,)=Times#N(-1); 
+       vvv[]+=I*uuu[]; cout << jp << " %%% " << vvv[].linfty << endl; assert(vvv[].linfty < 1e-6);}
+      {Whi  defPk#N(uuu,)=Times#N(1),defPk#N(vvv,)=Times#N(-1) ;
+       vvv[]+=rMj[jp]'*uuu[]; cout << jp << " ### " << vvv[].linfty << endl; assert(vvv[].linfty < 1e-6);}}
+    }}
+if(ipart==0) cout << " *** end build transfert matrix " << endl;
+settt 
+
+/* alloc array of send and recv data ..  */
+
+InitUdef(jpart.n,Whij,Thij,aThij,Usend,N)  /* initU(n,Vh,Th,aTh,U) */
+InitUdef(jpart.n,Whij,Thij,aThij,Vrecv,N) /* ... */
+if(ipart==0) cout << " *** end init  data for send/revc  " << endl;
+// 
+/******************************************************************/ 
+macro BuildTransferMat(ipart,mesh,Pk,N,U2V,Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,vdebug)
+ BuildTransferMat2(ipart,mesh,Pk,N,U2V,Thi,Whi,Whij,Thij,aThij,Usend,Vrecv,jpart,Pii,vdebug)
+ //
+/******************************************************************/ 
+
+
+/******************************************************************/ 
+// usage uplot is  allu or [allu,allu1] :
+macro PLOTMPIALLU(mesh,Pk,defPk, Th, u, uplot, plotparm)
+{ int ver=verbosity;
+  verbosity=0;
+  if(NoGraphicWindow==0)
+  {
+  if(mpirank==0)
+    {
+      mesh Thi=Th;
+      mesh[int] ath(mpisize);
+      fespace Xh(Thi,Pk);
+      Xh[int] defPk(allu,)(mpisize);
+      allu[0][]=u;
+      ath[0]=Th;
+      mpiRequest[int] rq(mpisize);
+      for(int i= 1; i <mpisize;++i)
+	   Irecv(processor(i,rq[i]),ath[i]);
+      for (int i=1;i<mpisize;++i)
+       	int k= mpiWaitAny(rq);
+      for (int i=1;i<mpisize;++i)
+	   { Thi=ath[i];
+	     Irecv(processor(i,rq[i]),allu[i][]);}
+      for (int i=1;i<mpisize;++i)
+       	int k= mpiWaitAny(rq); 
+      plot(uplot,plotparm);
+    }
+  else
+    {
+      processor(0)<<Th;
+      processor(0)<<u;
+    }
+  mpiBarrier(mpiCommWorld);
+  }
+  verbosity=ver;
+  return true;
+}
+//EOM ...
+/******************************************************************/ 
+
diff --git a/examples++-mpi/DDM-funcs-v2.idp b/examples++-mpi/DDM-funcs-v2.idp
new file mode 100644
index 0000000..68f30af
--- /dev/null
+++ b/examples++-mpi/DDM-funcs-v2.idp
@@ -0,0 +1,261 @@
+NewMacro DMMDeffuncAndGlobals(prefix,comm,jpart,Whi,Vhc,Pknbcomp,Ai,vPbC,onG10,Pii,Usend,Vrecv,U2V)
+/*
+    
+*/
+
+int prefix#rgmres=0;
+int prefix#kiter=-1;
+/*  the global name user... */
+/*
+  jpart,njpart : partition 
+  Usend, Vrecv : buffer
+  Ai , Bi 
+  rMj, sMj : matrices
+  
+  onG10:  tgv only on DDM s Gamma and not on Gamma
+*/
+/*----  for coarse  solver ... */
+
+
+matrix prefix#AC,prefix#Rci,prefix#Pci;/**/
+{
+int[int] Sigma11=U2V;   
+prefix#Pci=   interpolate(Whi,VhC,U2Vc=Sigma11);
+prefix#Rci =  prefix#Pci'*Pii; 
+/*Rci=   interpolate(Whi,VhC,t=1,U2Vc=Sigma11(0:Pknbcomp-1));
+Pci =  Pii*Rci'; */
+}
+
+/*----End of Global Def -------------*/
+
+/*-----------------*/
+/*-----------------*/
+
+
+func bool prefix#Update(real[int] &ui, real[int] &vi)
+{
+  for(int j=0;j<jpart.n;++j)
+    Usend[j][]=sMj[j]*ui; 
+   SendRecvUV(comm,jpart,Usend,Vrecv)
+     vi = Pii*ui;
+   for(int j=0;j<jpart.n;++j)
+     vi += rMj[j]*Vrecv[j][]; 
+   return true;
+}
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+ 
+func bool  prefix#CoarseSolve(real[int]& V,real[int]& U,mpiComm& comm)
+{
+    if(prefix#AC.n==0 && mpiRank(comm)==0)
+      prefix#AC = vPbC(VhC,VhC,solver=sparsesolver);
+   /*  solvibg the coarse probleme */
+   real[int] Uc(prefix#Rci.n),Bc(Uc.n); 
+   Uc= prefix#Rci*U;
+   mpiReduce(Uc,Bc,processor(0,comm),mpiSUM);
+   if(mpiRank(comm)==0) 
+      Uc = prefix#AC^-1*Bc;
+    broadcast(processor(0,comm),Uc);
+   V = prefix#Pci*Uc;
+}
+
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+
+func real[int] prefix#DJ(real[int]& U)
+{ 
+  ++prefix#kiter;
+  real[int] V(U.n); 
+  V =  Ai*U;
+  V = onG10 ? 0.: V;  
+  return V; 
+}
+
+func real[int] prefix#PDJ(real[int]& U) /* C1*/
+{ 
+  real[int] V(U.n); 
+  
+  real[int] b= onG10 ? 0. :  U; 
+  V =  Ai^-1*b;	
+  prefix#Update(V,U);
+  return U; 
+}
+
+func real[int] prefix#PDJC(real[int]& U) /**/ 
+{ /* Precon  C1= Precon , C2  precon Coarse
+   Idea : F. Nataf. 
+     0 ~  (I-C1A)(I-C2A) => I ~  - C1AC2A +C1A +C2A 
+     New Prec P= C1+C2 - C1AC2   = C1(I- A C2) +C2
+   (  C1(I- A C2) +C2 ) Uo 
+     V =  - C2*Uo
+  .... */
+  real[int] V(U.n); 
+  prefix#CoarseSolve(V,U,comm);
+  V = -V; /*  -C2*Uo  */
+  U  += Ai*V; /* U =  (I-A C2) Uo */
+  real[int] b= onG10 ? 0. :  U; 
+  U =  Ai^-1*b;	/*  ( C1( I -A C2) Uo */
+  V = U -V; /**/
+  prefix#Update(V,U);
+  return U; 
+}
+
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+
+func real[int] prefix#PDJC2(real[int]& U) /*  bogus ???? */
+{ /* Precon  C1= precon Coarse C2  precon Precon
+   Idea : F. Nataf. 
+      0 ~  (I C1A)(I-C2A) => I ~  - C1AC2A +C1A +C2A 
+      New Prec P= C1+C2 - C1AC2   = C1(I- A C2) +C2
+      (  C1(I- A C2) +C2 ) Uo 
+      V =  - C2*Uo
+      .... 
+      V = - C2 Uo 
+      W = Uo + A V 
+      V + C1 W  
+      */
+  real[int] V(U.n);
+  real[int] b= onG10 ? 0. :  U; 
+  V =  Ai^-1*b;	
+  b=U; 
+  
+  V = -V; 
+  prefix#Update(V,U);
+  U  += Ai*V;  
+
+  prefix#CoarseSolve(U,b,comm);
+  V = U -V;   
+  prefix#Update(V,U);
+  return U; 
+}
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+
+ func real[int] prefix#DJ0(real[int]& U)
+{ 
+  ++prefix#kiter;
+  real[int] V(U.n); 
+  real[int] b= onG10 .* U;
+  b  = onG10 ? b : Bi ;  
+  V = Ai^-1*b;	
+  prefix#Update(V,U);
+  V -= U;
+   return V; 
+}
+
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+
+func bool  prefix#CheckUpdate()
+{ /* verification.....*/
+
+  Whi defPk#Pknbcomp(u,) =Times#Pknbcomp(1),defPk#Pknbcomp(v,);
+  prefix#Update(u[],v[]);
+  u[]-=v[];
+  if(mpirank==0) cout << "CheckUpdate  " << u[].linfty << endl;
+  assert( u[].linfty<1e-6); 
+  
+  return 1; }
+
+func bool prefix#Saveff(string sff,real epss,int ksplit,int nloc,int sizeoverlaps)
+{  if(sff != "")
+  {
+    ofstream ff(sff+".txt",append);
+    cout << " ++++  " ;
+    cout  << mpirank <<"/" <<  mpisize << " k=" <<  ksplit << " n= " << nloc << " " 
+           << sizeoverlaps << " it=  " << prefix#kiter  ;  
+    for (int i=1; i<ittt;++i)	
+      cout << " " << ttt[i]-ttt[i-1] << " ";
+    cout << epss << " " << Ai.nbcoef << " " << Ai.n << endl;
+    
+    /*
+      1 mpirank
+      2 mpisize 
+      3 ksplit 
+      4 nloc
+      5 sizeoverlaps
+      6 kiter
+      7 mesh & part build  
+      8 build the partion 
+      9 build mesh, transfere , and the fine mesh .. 
+      10 build the matrix,  the trans matrix, factorizatioon 
+      11 GMRES 
+    */
+    ff   << mpirank << " " << mpisize << " " << sPk << " " ;
+    ff <<  ksplit << " " << nloc << " " << sizeoverlaps << " " << prefix#kiter  ;  
+    for (int i=1; i<ittt;++i)	
+      ff << " " << ttt[i]-ttt[i-1] << " ";
+    ff << epss << " " << Ai.nbcoef << " " << Ai.n << " " << gmres << endl;
+    
+  }
+  return 1;
+}
+//
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+/*-----------------*/
+
+
+NewMacro prefix#DDMSolver(Bi,u,v,gmres,epss,vdebug) 
+{
+ settt
+ int ipart=mpiRank(comm);
+ if(gmres==1)
+  {
+   prefix#rgmres=MPIAffineGMRES(prefix#DJ0,u[],veps=epss,nbiter=300,comm=comm,dimKrylov=100,verbosity=ipart ? 0: 50);
+   real[int] b= onG10 .* u[];
+   b  = onG10 ? b : Bi ;
+   v[] = Ai^-1*b;	
+   prefix#Update(v[],u[]);
+  }
+else if(gmres==2)
+  prefix#rgmres= MPILinearGMRES(prefix#DJ,precon=prefix#PDJ,u[],Bi,veps=epss,nbiter=1000,comm=comm,
+                         dimKrylov=100,verbosity=ipart ? 0: 50);
+else if(gmres==3)
+  prefix#rgmres= MPILinearGMRES(prefix#DJ,precon=prefix#PDJC,u[],Bi,veps=epss,nbiter=1000,comm=comm,
+                          dimKrylov=100,verbosity=ipart ? 0: 50);
+else if(gmres==4)
+   prefix#rgmres= MPILinearGMRES(prefix#DJ,precon=prefix#PDJC2,u[],Bi,veps=epss,nbiter=1000,comm=comm,
+                          dimKrylov=100,verbosity=ipart ? 0: 50);
+else /*algo Shwarz for demo */
+   for(int iter=0;iter <100; ++iter)
+     {
+       prefix#kiter=iter;
+       real[int] b= onG10 .* u[];
+       b  = onG10 ? b : Bi ;
+       v[] = Ai^-1*b;	
+       b=v[];
+       prefix#Update(v[],u[]);
+       if(vdebug) plotMPIall(Thi,u[],"u-"+iter);
+        b -= u[];
+       
+       real err = b.l1;
+       real umax = u[].max;
+       real[int] aa=[err,umax], bb(2);
+       mpiAllReduce(aa,bb,comm,mpiMAX);
+       real errg = bb[0];
+       real umaxg = bb[1];
+       
+       if(ipart==0)
+	     cout << ipart << " " << iter << " err = " << errg << " u. max  " << umaxg << endl;
+       if(errg< 1e-10 ) break;
+     }
+     prefix#Update(u[],v[]);  
+ 
+if(vdebug) plotMPIall(Thi,v[],"u-final");
+ u[]=v[];
+ settt
+}
+EndMacro  /*prefix#DDMSolver*/
+
+EndMacro
+
+
diff --git a/examples++-mpi/Heat3d.idp b/examples++-mpi/Heat3d.idp
new file mode 100644
index 0000000..3c6ee60
--- /dev/null
+++ b/examples++-mpi/Heat3d.idp
@@ -0,0 +1,104 @@
+load "msh3"
+load "medit"
+include "getARGV.idp"
+
+func f= 1. ; // right hand side function
+func g=0.; ; // boundary condition function
+func u0= 0;
+real dt=getARGV("-dt",0.01);
+int nn=getARGV("-n",20);
+int imax=getARGV("-niter",10);
+int op=getARGV("-op",1);
+int pplot=getARGV("-plot",0);
+
+mesh Th2D=square(nn,nn);
+int[int] refm=[1,1,2,1,3,1,4,1];
+int[int] refu=[0,1];
+mesh3 Th=buildlayers(Th2D,nn,zbound=[0.,1.],labelmid=refm,labelup=refu,labeldown=refu);
+
+
+// to slip integral on each processor 
+// set a region number of a processor number 
+real ccc = mpisize/real(Th.nt) ;
+if(op) Th=change(Th,fregion= min(mpisize-1,int(nuTriangle* ccc+1e-10)));
+else Th=change(Th,fregion=0);
+int reg= op ? mpirank : 0;
+//  end of trick
+cout << "  *** Th: vol " << Th.mesure << "  " << int3d(Th,reg)(1.) << endl;
+fespace Vh(Th,P2) ; // P1 FE space
+Vh uh=u0 ; // unkown and test function.
+
+
+real temps=clock();
+
+real time1,time2,time6;
+time1=clock();
+
+// compute only on region number = processor number 
+varf vlaplace(uh,vh) = // definition de problem
+      int3d(Th,reg)( uh*vh+ dt*(dx(uh)*dx(vh) + dy(uh)*dy(vh)+ dz(uh)*dz(vh)) ) // bil. form
+    + int3d(Th,reg)( dt*vh*f) + on(1,uh=g) ;
+varf vmasse(u,v) = int3d(Th,reg)(u*v);
+varf von1(uh,vh) = on(1,uh=1) ;
+
+matrix AA = vlaplace(Vh,Vh,tgv=ttgv) ;
+time1=clock()-time1;
+// reduce the matrice to get the full matrice 
+// warning the tgv number is now mpisize*tgv for B.C.
+matrix A; 
+time6=clock();
+if(op) mpiAllReduce(AA,A,mpiCommWorld,mpiSUM);
+else A=AA;
+time6 = clock()-time6;
+time2=clock();
+set(A,solver=sparsesolver,tgv=ttgv,sparams=ssparams) ; // factorize
+time2=clock()-time2;
+
+real time3=clock();
+matrix M = vmasse(Vh,Vh);
+time3=clock()-time3;
+
+real [int] b(A.n),bb(A.n) ;
+real[int] bcl= vlaplace(0,Vh,tgv=ttgv) ; // The B.C vector   
+real[int] Gamma = von1(0,Vh,tgv=1);  // 
+
+real time4=0,time5=0;
+
+for(int i=0 ;i<imax;i++)
+{
+
+real time4tmp=clock();
+bb = M*uh[];
+bb += bcl ; 
+
+time4=time4+(clock()-time4tmp);
+real time6tmp=clock();
+if(op) mpiAllReduce(bb,b,mpiCommWorld,mpiSUM);
+else b=bb;
+time6=time6+(clock()-time6tmp);
+real time5tmp=clock();
+uh[] = A^-1*b ; // resolution
+time5=time5+(clock()-time5tmp);
+	if(mpirank==0)
+        cout << "  -- time " << (i+1)*dt << " ||uh|| " << uh[].linfty << " ||b|| " << b.linfty << endl;
+
+}
+//savesol("Heat-Time-"+imax+"-nn-"+nn+"-superludist.sol",Th,uh);
+//savemesh(Th,"Heat-Time-"+imax+"-nn-"+nn+"-superludist.mesh");
+cout << "Time resolution " << clock()-temps << endl;
+if( mpirank==0 && pplot) medit("Heat",Th,uh);
+cout << "======================================" << endl;
+cout << " CPU TIME :                  " << endl;
+cout << " matrix A                    " << time1 << endl;
+cout << " factorization               " << time2 << endl;
+cout << " mass matrix                 " << time3 << endl;
+cout << " RHS  (Matrix vector Product with mass matrix)  " << endl;
+cout << "                             " << time4/imax << endl;
+cout << " solving                     " << time5/imax  << endl;
+cout << " MpiReduce                   " << time6  << endl;
+cout << " all                         " << clock()-temps << endl;
+cout << "======================================" << endl;
+
+
+
+
diff --git a/examples++-mpi/Laplace3d-hips.edp b/examples++-mpi/Laplace3d-hips.edp
new file mode 100644
index 0000000..66c39ae
--- /dev/null
+++ b/examples++-mpi/Laplace3d-hips.edp
@@ -0,0 +1,101 @@
+/*
+   Warning in before version 3.2-1 the nomarl are interal normal
+   after the signe is correct and now the noral was exterior normal. 
+ */
+verbosity=2;
+load "msh3"
+load "hips_FreeFem"
+
+int[int] iparm(16);
+real[int] dparm(6);
+iparm=-1;
+dparm=-1;
+/*  the sol trap  if we use...
+iparm[0]=1; // use iterative solver   0 => trap why ???? FH ..... 
+iparm[1]=0; // PCG as Krylov method
+iparm[4]=1; // Matrix are symmetric
+iparm[5]=1; // Pattern are also symmetric
+iparm[9]=0; // Scale matrix
+dparm[0]=1e-13; // Tolerance to convergence
+dparm[1]=5e-4; // Threshold in ILUT
+dparm[2]=5e-4; // Threshold for Schur preconditionner
+dparm[4]=1e-2; // drop tol
+dparm[5]=1e-2; // drop tol 
+*/
+int nn=10;
+mesh Th2=square(nn,nn,region=0);
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+
+fespace Vh(Th,P2);
+
+func ue =   2*x*x + 3*y*y + 4*z*z + 5*x*y+6*x*z+1;
+func uex=   4*x+  5*y+6*z;
+func uey=   6*y + 5*x;
+func uez=   8*z +6*x;
+func f= -18. ;
+Vh uhe = ue; //
+
+cout << " uhe min:  " << uhe[].min << " max:" << uhe[].max << endl;
+
+Vh u,v;
+
+macro Grad3(u) [dx(u),dy(u),dz(u)]  // EOM
+
+/*
+problem  Lapl3d(u,v)  =
+  int3d(Th)(Grad3(v)' *Grad3(u)) //') for emacs
+  + int2d(Th,2)(u*v)
+  - int3d(Th)(f*v)
+  - int2d(Th,2) ( ue*v + (uex*N.x +uey*N.y +uez*N.z)*v )
+  + on(1,u=ue);
+
+Lapl3d;
+*/
+  varf Lapl3d(u,v)  =
+  int3d(Th)(Grad3(v)' *Grad3(u)) //') for emacs 
+  + int2d(Th,2)(u*v)  
+  + int3d(Th)(f*v) 
+  + int2d(Th,2) ( ue*v + (uex*N.x +uey*N.y +uez*N.z)*v )
+  + on(1,u=ue);
+
+
+matrix A = Lapl3d(Vh,Vh,tgv=-1);//  to remove line this BC. 
+cout << A.n  << " " << A.m << " " << A.nbcoef << endl;
+verbosity=4; 
+set(A,solver=sparsesolver,dparams=dparm, lparams=iparm);
+cout <<A.n  <<" " << A.m << " " << A.nbcoef << endl;
+
+real[int] b = Lapl3d(0,Vh,tgv=-1);
+ 
+u[] = A^-1*b;
+cout << " b min:: " << b.min << " max: " << b.max << endl;
+cout << " u min::   " << u[]. min << "  max: " << u[].max << endl;
+real err= int3d(Th)( square(u-ue) );
+real aa1= int3d(Th,qfV=qfV1)(u) ;
+real aa2= int3d(Th,qfV=qfV1lump)(u) ;
+
+cout << " aa1 = " << aa1 << endl;
+cout << " aa2 = " << aa2 << endl;
+cout << int3d(Th)(1.) << " = " << Th.mesure << endl;
+cout << int3d(Th,qfV=qfV1)(1.) << " = " << Th.mesure << endl;
+cout << int3d(Th,qfV=qfV1lump)(1.) << " = " << Th.mesure << endl;
+Vh d= ue-u;
+cout <<  " err = " << err <<  " diff l^\intfy = " << d[].linfty << endl;
+real  aire2=int2d(Th,2)(1.); // bug correct in version 3.0-4 
+cout << " aire2 = " << aire2 << endl;
+func uuu= 2.+x;
+cout << uuu(1,1,1) << endl;
+assert( abs(aire2-1.) < 1e-6);
+plot(u,wait=1);
+if(mpirank==0) cout << " err = " << err<<endl;
+assert( err < 1e-5);
+
diff --git a/examples++-mpi/Laplace3d-hypre.edp b/examples++-mpi/Laplace3d-hypre.edp
new file mode 100644
index 0000000..0d59b70
--- /dev/null
+++ b/examples++-mpi/Laplace3d-hypre.edp
@@ -0,0 +1,100 @@
+/*
+   Warning in before version 3.2-1 the nomarl are interal normal
+   after the signe is correct and now the noral was exterior normal. 
+ */
+verbosity=2;
+load "msh3"
+load "hypre_FreeFem"
+
+// for hypre
+int[int] iparm(20);
+real[int] dparm(6);
+for(int iii=0;iii<20;iii++)iparm[iii]=-1;
+for(int iii=0;iii<6;iii++) dparm[iii]=-1;
+iparm[0]=2; // PCG as krylov method
+iparm[1]=0; // AMG as preconditionner 2: if ParaSails
+iparm[7]=7; // Interpolation
+iparm[9]=6; // AMG Coarsen type
+iparm[10]=1; // Measure type
+iparm[16]=2; // Additive schwarz as smoother
+dparm[0]=1e-13; // Tolerance to convergence
+dparm[1]=5e-4; // Threshold
+dparm[2]=5e-4; // truncation factor
+
+
+int nn=10;
+mesh Th2=square(nn,nn,region=0);
+fespace Vh2(Th2,P1);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+
+fespace Vh(Th,P1);
+
+func ue =   2*x*x + 3*y*y + 4*z*z + 5*x*y+6*x*z+1;
+func uex=   4*x+  5*y+6*z;
+func uey=   6*y + 5*x;
+func uez=   8*z +6*x;
+func f= -18. ;
+Vh uhe = ue; //
+
+cout << " uhe min:  " << uhe[].min << " max:" << uhe[].max << endl;
+
+Vh u,v;
+
+macro Grad3(u) [dx(u),dy(u),dz(u)]  // EOM
+
+/*
+problem  Lapl3d(u,v)  =
+  int3d(Th)(Grad3(v)' *Grad3(u)) //') for emacs
+  + int2d(Th,2)(u*v)
+  - int3d(Th)(f*v)
+  - int2d(Th,2) ( ue*v + (uex*N.x +uey*N.y +uez*N.z)*v )
+  + on(1,u=ue);
+
+Lapl3d;
+*/
+  varf Lapl3d(u,v)  =
+  int3d(Th)(Grad3(v)' *Grad3(u)) //') for emacs 
+  + int2d(Th,2)(u*v)  
+  + int3d(Th)(f*v) 
+  + int2d(Th,2) ( ue*v + (uex*N.x +uey*N.y +uez*N.z)*v )
+  + on(1,u=ue);
+
+real tgv = -1;
+matrix A = Lapl3d(Vh,Vh,tgv=tgv);
+cout << A.n  << " " << A.m << " " << A.nbcoef << endl;
+set(A,solver=sparsesolver,dparams=dparm, lparams=iparm);
+cout <<A.n  <<" " << A.m << " " << A.nbcoef << endl;
+
+real[int] b = Lapl3d(0,Vh,tgv=tgv);
+ 
+u[] = A^-1*b;
+cout << " b min:: " << b.min << " max: " << b.max << endl;
+cout << " u min::   " << u[]. min << "  max: " << u[].max << endl;
+real err= int3d(Th)( square(u-ue) );
+real aa1= int3d(Th,qfV=qfV1)(u) ;
+real aa2= int3d(Th,qfV=qfV1lump)(u) ;
+
+cout << " aa1 = " << aa1 << endl;
+cout << " aa2 = " << aa2 << endl;
+cout << int3d(Th)(1.) << " = " << Th.mesure << endl;
+cout << int3d(Th,qfV=qfV1)(1.) << " = " << Th.mesure << endl;
+cout << int3d(Th,qfV=qfV1lump)(1.) << " = " << Th.mesure << endl;
+Vh d= ue-u;
+cout <<  " err = " << err <<  " diff l^\intfy = " << d[].linfty << endl;
+real  aire2=int2d(Th,2)(1.); // bug correct in version 3.0-4 
+cout << " aire2 = " << aire2 << endl;
+func uuu= 2.+x;
+cout << uuu(1,1,1) << endl;
+assert( abs(aire2-1.) < 1e-6);
+plot(u,wait=1);
+
+assert( err < 1e-3);
+
diff --git a/examples++-mpi/LaplaceRT-3d-matrix-mumps.edp b/examples++-mpi/LaplaceRT-3d-matrix-mumps.edp
new file mode 100644
index 0000000..5cef744
--- /dev/null
+++ b/examples++-mpi/LaplaceRT-3d-matrix-mumps.edp
@@ -0,0 +1,209 @@
+/*
+   $ - \Delta p = f $   on $\Omega$, 
+   $ dp / dn = (g1d,g2d). n  $ on $\Gamma_{1}$ 
+   $ p = gd  $ on $\Gamma_{2}$    
+   with de Mixte finite element formulation 
+
+   Find $p\in L^2(\Omega) $  and $u\in H(div) $ such than 
+   $$  u - Grad p = 0    $$
+   $$ - div u =  f $$
+   $$  u. n = (g1d,g2d). n   \mbox{ on } \Gamma_{2}$$
+   $$ p = gd  \mbox{ on }\Gamma_{1}$$
+   the variationnel form is: 
+                                                                                                                   
+ $\forall v\in H(div)$;  $v.n = 0$ on $\Gamma_{2} $:  
+
+  $ \int_\Omega  u v + p div v -\int_{\Gamma_{1}} gd* v.n  = 0 $ 
+ $\forall q\in L^2$:   $  +\int_\Omega q div u = -\int_Omega f q  $
+and $ u.n = (g1n,g2n).n$ on $\Gamma_2$
+
+*/
+
+// brochet
+load "medit"
+load "MUMPS_FreeFem"
+include "cube.idp"
+
+
+real ttgv = 1e30;
+string ssparams = "nprow=1, npcol="+mpisize;
+
+    //int[int]  Nxyz=[18,18,18];
+    int[int]  Nxyz=[10,10,10];
+    real [int,int]  Bxyz=[[0,1],[0,1],[0,1]];
+    int [int,int]  Lxyz=[[1,1],[1,1],[2,1]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+fespace Vh(Th,P1);
+fespace Rh(Th,RT03d);
+fespace Nh(Th,Edge03d);//  Nedelec Finite element. 
+fespace Ph(Th,P0);
+
+func gd = 1.;
+
+func g1n = 2.;
+func g2n = 3.; 
+func g3n = 4.; 
+
+func f = 1.;
+
+Rh [u1,u2,u3],[v1,v2,v3];
+Nh [e1,e2,e3];
+[u1,u2,u3]=[1+100*x,2+100*y,3+100*z];
+
+// a + b ^ x = 
+/*
+  b1    x     a1 + b2*z - b3*y 
+  b2 ^  y  =  a2 - b1*z + b3*x
+  b3    z     a3 + b1*y - b2*x
+*/
+real b1=30,b2=10,b3=20;
+func ex1=100+b2*z-b3*y;
+
+func ex1x=0.;
+func ex1y=-b3+0;
+func ex1z=b2+0;
+
+func ex2=200.- b1*z + b3*x ;
+func ex2x= b3 +0;
+func ex2y= 0. ;
+func ex2z= -b1 +0;
+func ex3=300.+b1*y - b2*x ;
+func ex3x= -b2 +0;
+func ex3y= b1 +0;
+func ex3z= 0. ;
+[e1,e2,e3]=[ex1,ex2,ex3]; 
+
+int k=Th(.1,.2,.3).nuTriangle ;
+cout << " u = " << u1(.1,.2,.3)  << " " << u2(.1,.2,.3) << " " << u3(.1,.2,.3) << endl;
+cout << " dx u = " << dx(u1)(.1,.2,.3)  << " " << dy(u2)(.1,.2,.3) << " " << dz(u3)(.1,.2,.3) << endl;
+
+cout << " e  = " << e1(.1,.2,.3)  << " " << e2(.1,.2,.3) << " " << e3(.1,.2,.3) << endl;
+cout << " ex = " << ex1(.1,.2,.3)  << " " << ex2(.1,.2,.3) << " " << ex3(.1,.2,.3) << endl;
+
+
+cout << " dx,dy,dz   e1x= " << ex1x(.1,.2,.3)  << " " << ex1y(.1,.2,.3) << " " << ex1z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2x= " << ex2x(.1,.2,.3)  << " " << ex2y(.1,.2,.3) << " " << ex2z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3x= " << ex3x(.1,.2,.3)  << " " << ex3y(.1,.2,.3) << " " << ex3z(.1,.2,.3) << endl;
+
+cout << " dx,dy,dz   e1 = " << dx(e1)(.1,.2,.3)  << " " << dy(e1)(.1,.2,.3) << " " << dz(e1)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2 = " << dx(e2)(.1,.2,.3)  << " " << dy(e2)(.1,.2,.3) << " " << dz(e2)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3 = " << dx(e3)(.1,.2,.3)  << " " << dy(e3)(.1,.2,.3) << " " << dz(e3)(.1,.2,.3) << endl;
+
+
+cout << " k = " << k << endl;
+cout << Rh(k,0) << " " <<Rh(k,1) << " " <<Rh(k,2) << " " <<Rh(k,3) << endl;
+cout << " df = " << u1[][Rh(k,0)] <<  " " << u1[][Rh(k,1)]  <<" " << u1[][Rh(k,2)]  << " " << u1[][Rh(k,2)] << endl;
+// cout << u1[] << endl;
+
+Vh P,Q;
+Ph p,q; 
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //
+macro Grad(u) [dx(u),dy(u),dz(u)]  //
+
+// Laplace resolution
+real timeLapl = clock();
+{
+/*
+problem laplace(P,Q,solver=CG) = 
+  int3d(Th) ( Grad(P)'*Grad(Q)) //') for emacs
+  - int3d(Th)(f*Q) 
+  + on(1,P=gd) 
+  - int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q);
+*/
+// matrix resolution
+varf vlap(P,Q) = int3d(Th) ( Grad(P)'*Grad(Q))+on(1,P=gd); //') for emacs
+
+varf vsdc(P,Q) = int3d(Th)(f*Q) + int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q)+ on(1,P=gd);
+
+matrix Mlap=vlap(Vh,Vh,solver=sparsesolver);
+real[int] sdc=vsdc(0,Vh);
+/*
+varf vtot(P,Q) = int3d(Th) ( Grad(P)'*Grad(Q)) +int3d(Th)(f*Q) + int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q)+ on(1,P=gd); //') for emacs
+
+matrix Mlap = vtot(Vh,Vh,solver=CG);
+real[int] sdc = vtot(0,Vh);
+*/
+P[] = Mlap^-1*sdc;
+}
+timeLapl = clock()-timeLapl;
+
+// some verification of Boundary condition
+fespace RPh(Th,[RT03d,P0]);
+
+varf von1([u1,u2,u3,p],[v1,v2,v3,q])  = 
+   int3d(Th)( p*q*1e-15+ u1*v1 + u2*v2 + u3*v3 + p*div(v1,v2,v3) + div(u1,u2,u3)*q )
+ - int3d(Th) ( f*q)
+ + int2d(Th,1)( gd*(v1*N.x +v2*N.y + v3*N.z) )  //  int on gamma 
+ + on(2,u1=g1n,u2=g2n,u3=g3n);
+
+RPh [vv1,vv2,vv3,qq];
+// some verification Boundary Condition
+// and interpolation ...
+real[int]  ron=von1(0,RPh);
+vv3[]=von1(0,RPh);
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << endl;
+[vv1,vv2,vv3,qq]=[g1n,g2n,g3n,100];
+[v1,v2,v3]=[g1n,g2n,g3n];
+
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << " " << qq(.1,.2,.001) << endl;
+cout << " v : = " << v1(.1,.2,.001)  << " " << v2(.1,.2,.001) << " " << v3(.1,.2,.001)  << endl;
+
+// end of verification of Boundary Condition ... 
+
+
+/*
+problem laplaceMixte([u1,u2,u3,p],[v1,v2,v3,q],solver=sparsesolver,tgv=1e30,sparams="nprow=1, npcol="+mpisize, dimKrylov=400) = 
+int3d(Th)( p*q*1e-15+ u1*v1 + u2*v2 + u3*v3 + p*div(v1,v2,v3) + div(u1,u2,u3)*q )
+ + int3d(Th) ( f*q)
+ - int2d(Th,1)( gd*(v1*N.x +v2*N.y + v3*N.z) )  //  int on gamma 
+ + on(2,u1=g1n,u2=g2n,u3=g3n);
+*/
+
+RPh [uu1,uu2,uu3,pp];
+//RPh [v1,v2,v3,q];
+
+real tMatrix=clock();
+varf vlaplaceMixte([uu1,uu2,uu3,pp],[v1,v2,v3,q]) = int3d(Th)( pp*q*1e-15+ uu1*v1 + uu2*v2 + uu3*v3 + pp*div(v1,v2,v3) + div(uu1,uu2,uu3)*q )+on(2,uu1=g1n,uu2=g2n,uu3=g3n);
+matrix MlaplaceMixte = vlaplaceMixte(RPh,RPh,tgv=ttgv,solver=sparsesolver);
+tMatrix=clock()-tMatrix;
+
+real tFact=clock();
+set(MlaplaceMixte,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+tFact=clock()-tFact;
+
+real tscd=clock();
+varf vsdcLM([uu1,uu2,uu3,pp],[v1,v2,v3,q]) = -int3d(Th) ( f*q) + int2d(Th,1)( gd*(v1*N.x+v2*N.y + v3*N.z) )+on(2,uu1=g1n,uu2=g2n,uu3=g3n);
+real[int] sdcLM = vsdcLM(0,RPh);
+tscd=clock()-tscd;
+
+real tsolve=clock();
+uu1[] = MlaplaceMixte^-1*sdcLM;
+tsolve=clock()-tsolve;
+
+cout << "=============================" << endl;
+cout << "CPU TIME Lapl: " << timeLapl << endl;
+cout << "=============================" << endl;
+
+cout << "=============================" << endl;
+cout << "CPU TIME Lapl Mixte:         " << endl;
+cout << " matrix         "<< tMatrix << endl;
+cout << " factorization  "<< tFact   << endl;
+cout << " second menber  "<< tscd    << endl;
+cout << " solving        "<< tsolve  << endl;
+cout << "=============================" << endl;
+
+//if(mpirank==0){
+real errL2=sqrt(int3d(Th)(square(P-pp))) ;
+cout << " int 2 x,yz "<<int2d(Th,2)(x) << " " << int2d(Th,2)(y) << " " << int2d(Th,2)(z) << endl;
+cout << " int 2 gn "<<int2d(Th,2)(g1n) << " " << int2d(Th,2)(g2n) << " " << int2d(Th,2)(g3n) << endl;
+cout << " int 2 U  "<<int2d(Th,2)(uu1) << " " << int2d(Th,2)(uu2) << " " << int2d(Th,2)(uu3) << endl;
+cout << " int 2 V  "<<int2d(Th,2)(v1) << " " << int2d(Th,2)(v2) << " " << int2d(Th,2)(v3) << endl;
+cout << " int 2 DP "<<int2d(Th,2)(dx(P)) << " " << int2d(Th,2)(dy(P)) << " " << int2d(Th,2)(dz(P)) << endl;
+  
+cout << "  diff: u Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (uu1*N.x +uu2*N.y + uu3*N.z) ) ) ) <<endl;
+cout << "  diff: P Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (dx(P)*N.x +dy(P)*N.y + dz(P)*N.z) ) ) ) <<endl;
+cout << " diff err L2 :" << errL2 << endl;
+cout << "    P     L2 :" <<sqrt(int3d(Th)(square(P))) << endl;
+cout << "    p     L2 :" <<sqrt(int3d(Th)(square(pp))) << endl;
+assert(errL2<0.05);
+//}
\ No newline at end of file
diff --git a/examples++-mpi/LaplaceRT-3d-matrix-pastix.edp b/examples++-mpi/LaplaceRT-3d-matrix-pastix.edp
new file mode 100644
index 0000000..d8598c1
--- /dev/null
+++ b/examples++-mpi/LaplaceRT-3d-matrix-pastix.edp
@@ -0,0 +1,199 @@
+
+/*
+   $ - \Delta p = f $   on $\Omega$, 
+   $ dp / dn = (g1d,g2d). n  $ on $\Gamma_{1}$ 
+   $ p = gd  $ on $\Gamma_{2}$    
+   with de Mixte finite element formulation 
+
+   Find $p\in L^2(\Omega) $  and $u\in H(div) $ such than 
+   $$  u - Grad p = 0    $$
+   $$ - div u =  f $$
+   $$  u. n = (g1d,g2d). n   \mbox{ on } \Gamma_{2}$$
+   $$ p = gd  \mbox{ on }\Gamma_{1}$$
+   the variationnel form is: 
+                                                                                                                   
+ $\forall v\in H(div)$;  $v.n = 0$ on $\Gamma_{2} $:  
+
+  $ \int_\Omega  u v + p div v -\int_{\Gamma_{1}} gd* v.n  = 0 $ 
+ $\forall q\in L^2$:   $  +\int_\Omega q div u = -\int_Omega f q  $
+and $ u.n = (g1n,g2n).n$ on $\Gamma_2$
+
+*/
+
+load "medit"
+load "real_pastix_FreeFem"
+include "cube.idp"
+
+real ttgv = 1e10;
+string ssparams ="nprow=1, npcol="+mpisize;
+
+    int[int]  Nxyz=[12,12,12];
+    real [int,int]  Bxyz=[[0,1],[0,1],[0,1]];
+    int [int,int]  Lxyz=[[1,1],[1,1],[2,1]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+fespace Vh(Th,P1);
+fespace Rh(Th,RT03d);
+fespace Nh(Th,Edge03d);//  Nedelec Finite element. 
+fespace Ph(Th,P0);
+
+func gd = 1.;
+
+func g1n = 2.;
+func g2n = 3.; 
+func g3n = 4.; 
+
+func f = 1.;
+
+Rh [u1,u2,u3],[v1,v2,v3];
+Nh [e1,e2,e3];
+[u1,u2,u3]=[1+100*x,2+100*y,3+100*z];
+
+// a + b ^ x = 
+/*
+  b1    x     a1 + b2*z - b3*y 
+  b2 ^  y  =  a2 - b1*z + b3*x
+  b3    z     a3 + b1*y - b2*x
+*/
+real b1=30,b2=10,b3=20;
+func ex1=100+b2*z-b3*y;
+
+func ex1x=0.;
+func ex1y=-b3+0;
+func ex1z=b2+0;
+
+func ex2=200.- b1*z + b3*x ;
+func ex2x= b3 +0;
+func ex2y= 0. ;
+func ex2z= -b1 +0;
+func ex3=300.+b1*y - b2*x ;
+func ex3x= -b2 +0;
+func ex3y= b1 +0;
+func ex3z= 0. ;
+[e1,e2,e3]=[ex1,ex2,ex3]; 
+
+int k=Th(.1,.2,.3).nuTriangle ;
+cout << " u = " << u1(.1,.2,.3)  << " " << u2(.1,.2,.3) << " " << u3(.1,.2,.3) << endl;
+cout << " dx u = " << dx(u1)(.1,.2,.3)  << " " << dy(u2)(.1,.2,.3) << " " << dz(u3)(.1,.2,.3) << endl;
+
+cout << " e  = " << e1(.1,.2,.3)  << " " << e2(.1,.2,.3) << " " << e3(.1,.2,.3) << endl;
+cout << " ex = " << ex1(.1,.2,.3)  << " " << ex2(.1,.2,.3) << " " << ex3(.1,.2,.3) << endl;
+
+
+cout << " dx,dy,dz   e1x= " << ex1x(.1,.2,.3)  << " " << ex1y(.1,.2,.3) << " " << ex1z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2x= " << ex2x(.1,.2,.3)  << " " << ex2y(.1,.2,.3) << " " << ex2z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3x= " << ex3x(.1,.2,.3)  << " " << ex3y(.1,.2,.3) << " " << ex3z(.1,.2,.3) << endl;
+
+cout << " dx,dy,dz   e1 = " << dx(e1)(.1,.2,.3)  << " " << dy(e1)(.1,.2,.3) << " " << dz(e1)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2 = " << dx(e2)(.1,.2,.3)  << " " << dy(e2)(.1,.2,.3) << " " << dz(e2)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3 = " << dx(e3)(.1,.2,.3)  << " " << dy(e3)(.1,.2,.3) << " " << dz(e3)(.1,.2,.3) << endl;
+
+
+cout << " k = " << k << endl;
+cout << Rh(k,0) << " " <<Rh(k,1) << " " <<Rh(k,2) << " " <<Rh(k,3) << endl;
+cout << " df = " << u1[][Rh(k,0)] <<  " " << u1[][Rh(k,1)]  <<" " << u1[][Rh(k,2)]  << " " << u1[][Rh(k,2)] << endl;
+// cout << u1[] << endl;
+
+Vh P,Q;
+Ph p,q; 
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //
+macro Grad(u) [dx(u),dy(u),dz(u)]  //
+
+// Laplace resolution
+real timeLapl = clock();
+{
+/*
+problem laplace(P,Q,solver=CG) = 
+  int3d(Th) ( Grad(P)'*Grad(Q)) //') for emacs
+  - int3d(Th)(f*Q) 
+  + on(1,P=gd) 
+  - int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q);
+*/
+// matrix resolution
+varf vlap(P,Q) = int3d(Th) ( Grad(P)'*Grad(Q))+on(1,P=gd); //') for emacs
+
+varf vsdc(P,Q) = int3d(Th)(f*Q) + int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q)+ on(1,P=gd);
+
+matrix Mlap=vlap(Vh,Vh,solver=CG);
+real[int] sdc=vsdc(0,Vh);
+/*
+varf vtot(P,Q) = int3d(Th) ( Grad(P)'*Grad(Q)) +int3d(Th)(f*Q) + int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q)+ on(1,P=gd); //') for emacs
+
+matrix Mlap = vtot(Vh,Vh,solver=CG);
+real[int] sdc = vtot(0,Vh);
+*/
+P[] = Mlap^-1*sdc;
+}
+timeLapl = clock()-timeLapl;
+
+// some verification of Boundary condition
+fespace RPh(Th,[RT03d,P0]);
+
+varf von1([u1,u2,u3,p],[v1,v2,v3,q])  = 
+   int3d(Th)( p*q*1e-15+ u1*v1 + u2*v2 + u3*v3 + p*div(v1,v2,v3) + div(u1,u2,u3)*q )
+ - int3d(Th) ( f*q)
+ + int2d(Th,1)( gd*(v1*N.x +v2*N.y + v3*N.z) )  //  int on gamma 
+ + on(2,u1=g1n,u2=g2n,u3=g3n);
+
+RPh [vv1,vv2,vv3,qq];
+// some verification Boundary Condition
+// and interpolation ...
+real[int]  ron=von1(0,RPh);
+vv3[]=von1(0,RPh);
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << endl;
+[vv1,vv2,vv3,qq]=[g1n,g2n,g3n,100];
+[v1,v2,v3]=[g1n,g2n,g3n];
+
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << " " << qq(.1,.2,.001) << endl;
+cout << " v : = " << v1(.1,.2,.001)  << " " << v2(.1,.2,.001) << " " << v3(.1,.2,.001)  << endl;
+
+// end of verification of Boundary Condition ... 
+
+
+
+RPh [uu1,uu2,uu3,pp];
+
+real tMatrix=clock();
+varf vlaplaceMixte([uu1,uu2,uu3,pp],[v1,v2,v3,q]) = int3d(Th)( pp*q*1e-15+ uu1*v1 + uu2*v2 + uu3*v3 + pp*div(v1,v2,v3) + div(uu1,uu2,uu3)*q )+on(2,uu1=g1n,uu2=g2n,uu3=g3n);
+matrix MlaplaceMixte = vlaplaceMixte(RPh,RPh,tgv=ttgv,solver=sparsesolver);
+tMatrix=clock()-tMatrix;
+
+real tFact=clock();
+set(MlaplaceMixte,solver=sparsesolver,tgv=ttgv,sparams="nprow=1, npcol="+mpisize, dimKrylov=400);
+tFact=clock()-tFact;
+
+real tscd=clock();
+varf vsdcLM([uu1,uu2,uu3,pp],[v1,v2,v3,q]) = -int3d(Th) ( f*q) + int2d(Th,1)( gd*(v1*N.x+v2*N.y + v3*N.z) )+on(2,uu1=g1n,uu2=g2n,uu3=g3n);
+real[int] sdcLM = vsdcLM(0,RPh);
+tscd=clock()-tscd;
+
+real tsolve=clock();
+uu1[] = MlaplaceMixte^-1*sdcLM;
+tsolve=clock()-tsolve;
+
+cout << "=============================" << endl;
+cout << "CPU TIME Lapl: " << timeLapl << endl;
+cout << "=============================" << endl;
+
+cout << "=============================" << endl;
+cout << "CPU TIME Lapl Mixte:         " << endl;
+cout << " matrix         "<< tMatrix << endl;
+cout << " factorization  "<< tFact   << endl;
+cout << " second menber  "<< tscd    << endl;
+cout << " solving        "<< tsolve  << endl;
+cout << "=============================" << endl;
+
+//if(mpirank==0){
+real errL2=sqrt(int3d(Th)(square(P-pp))) ;
+cout << " int 2 x,yz "<<int2d(Th,2)(x) << " " << int2d(Th,2)(y) << " " << int2d(Th,2)(z) << endl;
+cout << " int 2 gn "<<int2d(Th,2)(g1n) << " " << int2d(Th,2)(g2n) << " " << int2d(Th,2)(g3n) << endl;
+cout << " int 2 U  "<<int2d(Th,2)(uu1) << " " << int2d(Th,2)(uu2) << " " << int2d(Th,2)(uu3) << endl;
+cout << " int 2 V  "<<int2d(Th,2)(v1) << " " << int2d(Th,2)(v2) << " " << int2d(Th,2)(v3) << endl;
+cout << " int 2 DP "<<int2d(Th,2)(dx(P)) << " " << int2d(Th,2)(dy(P)) << " " << int2d(Th,2)(dz(P)) << endl;
+  
+cout << "  diff: u Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (uu1*N.x +uu2*N.y + uu3*N.z) ) ) ) <<endl;
+cout << "  diff: P Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (dx(P)*N.x +dy(P)*N.y + dz(P)*N.z) ) ) ) <<endl;
+cout << " diff err L2 :" << errL2 << endl;
+cout << "    P     L2 :" <<sqrt(int3d(Th)(square(P))) << endl;
+cout << "    p     L2 :" <<sqrt(int3d(Th)(square(pp))) << endl;
+assert(errL2<0.05);
+//}
diff --git a/examples++-mpi/LaplaceRT-3d-matrix-superludist.edp b/examples++-mpi/LaplaceRT-3d-matrix-superludist.edp
new file mode 100644
index 0000000..fcfef4a
--- /dev/null
+++ b/examples++-mpi/LaplaceRT-3d-matrix-superludist.edp
@@ -0,0 +1,207 @@
+/*
+   $ - \Delta p = f $   on $\Omega$, 
+   $ dp / dn = (g1d,g2d). n  $ on $\Gamma_{1}$ 
+   $ p = gd  $ on $\Gamma_{2}$    
+   with de Mixte finite element formulation 
+
+   Find $p\in L^2(\Omega) $  and $u\in H(div) $ such than 
+   $$  u - Grad p = 0    $$
+   $$ - div u =  f $$
+   $$  u. n = (g1d,g2d). n   \mbox{ on } \Gamma_{2}$$
+   $$ p = gd  \mbox{ on }\Gamma_{1}$$
+   the variationnel form is: 
+                                                                                                                   
+ $\forall v\in H(div)$;  $v.n = 0$ on $\Gamma_{2} $:  
+
+  $ \int_\Omega  u v + p div v -\int_{\Gamma_{1}} gd* v.n  = 0 $ 
+ $\forall q\in L^2$:   $  +\int_\Omega q div u = -\int_Omega f q  $
+and $ u.n = (g1n,g2n).n$ on $\Gamma_2$
+
+*/
+
+load "medit"
+load "real_SuperLU_DIST_FreeFem"
+include "cube.idp"
+
+real ttgv = 1e30;
+string ssparams ="nprow=1, npcol="+mpisize;
+
+    //int[int]  Nxyz=[18,18,18];
+    int[int]  Nxyz=[8,8,8];
+    real [int,int]  Bxyz=[[0,1],[0,1],[0,1]];
+    int [int,int]  Lxyz=[[1,1],[1,1],[2,1]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+fespace Vh(Th,P1);
+fespace Rh(Th,RT03d);
+fespace Nh(Th,Edge03d);//  Nedelec Finite element. 
+fespace Ph(Th,P0);
+
+func gd = 1.;
+
+func g1n = 2.;
+func g2n = 3.; 
+func g3n = 4.; 
+
+func f = 1.;
+
+Rh [u1,u2,u3],[v1,v2,v3];
+Nh [e1,e2,e3];
+[u1,u2,u3]=[1+100*x,2+100*y,3+100*z];
+
+// a + b ^ x = 
+/*
+  b1    x     a1 + b2*z - b3*y 
+  b2 ^  y  =  a2 - b1*z + b3*x
+  b3    z     a3 + b1*y - b2*x
+*/
+real b1=30,b2=10,b3=20;
+func ex1=100+b2*z-b3*y;
+
+func ex1x=0.;
+func ex1y=-b3+0;
+func ex1z=b2+0;
+
+func ex2=200.- b1*z + b3*x ;
+func ex2x= b3 +0;
+func ex2y= 0. ;
+func ex2z= -b1 +0;
+func ex3=300.+b1*y - b2*x ;
+func ex3x= -b2 +0;
+func ex3y= b1 +0;
+func ex3z= 0. ;
+[e1,e2,e3]=[ex1,ex2,ex3]; 
+
+int k=Th(.1,.2,.3).nuTriangle ;
+cout << " u = " << u1(.1,.2,.3)  << " " << u2(.1,.2,.3) << " " << u3(.1,.2,.3) << endl;
+cout << " dx u = " << dx(u1)(.1,.2,.3)  << " " << dy(u2)(.1,.2,.3) << " " << dz(u3)(.1,.2,.3) << endl;
+
+cout << " e  = " << e1(.1,.2,.3)  << " " << e2(.1,.2,.3) << " " << e3(.1,.2,.3) << endl;
+cout << " ex = " << ex1(.1,.2,.3)  << " " << ex2(.1,.2,.3) << " " << ex3(.1,.2,.3) << endl;
+
+
+cout << " dx,dy,dz   e1x= " << ex1x(.1,.2,.3)  << " " << ex1y(.1,.2,.3) << " " << ex1z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2x= " << ex2x(.1,.2,.3)  << " " << ex2y(.1,.2,.3) << " " << ex2z(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3x= " << ex3x(.1,.2,.3)  << " " << ex3y(.1,.2,.3) << " " << ex3z(.1,.2,.3) << endl;
+
+cout << " dx,dy,dz   e1 = " << dx(e1)(.1,.2,.3)  << " " << dy(e1)(.1,.2,.3) << " " << dz(e1)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e2 = " << dx(e2)(.1,.2,.3)  << " " << dy(e2)(.1,.2,.3) << " " << dz(e2)(.1,.2,.3) << endl;
+cout << " dx,dy,dz   e3 = " << dx(e3)(.1,.2,.3)  << " " << dy(e3)(.1,.2,.3) << " " << dz(e3)(.1,.2,.3) << endl;
+
+
+cout << " k = " << k << endl;
+cout << Rh(k,0) << " " <<Rh(k,1) << " " <<Rh(k,2) << " " <<Rh(k,3) << endl;
+cout << " df = " << u1[][Rh(k,0)] <<  " " << u1[][Rh(k,1)]  <<" " << u1[][Rh(k,2)]  << " " << u1[][Rh(k,2)] << endl;
+// cout << u1[] << endl;
+
+Vh P,Q;
+Ph p,q; 
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //
+macro Grad(u) [dx(u),dy(u),dz(u)]  //
+
+// Laplace resolution
+real timeLapl = clock();
+{
+/*
+problem laplace(P,Q,solver=CG) = 
+  int3d(Th) ( Grad(P)'*Grad(Q)) //') for emacs
+  - int3d(Th)(f*Q) 
+  + on(1,P=gd) 
+  - int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q);
+*/
+// matrix resolution
+varf vlap(P,Q) = int3d(Th) ( Grad(P)'*Grad(Q))+on(1,P=gd); //') for emacs
+
+varf vsdc(P,Q) = int3d(Th)(f*Q) + int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q)+ on(1,P=gd);
+
+matrix Mlap=vlap(Vh,Vh,solver=CG);
+real[int] sdc=vsdc(0,Vh);
+/*
+varf vtot(P,Q) = int3d(Th) ( Grad(P)'*Grad(Q)) +int3d(Th)(f*Q) + int2d(Th,2) ( (g1n*N.x+g2n*N.y+g3n*N.z)*Q)+ on(1,P=gd); //') for emacs
+
+matrix Mlap = vtot(Vh,Vh,solver=CG);
+real[int] sdc = vtot(0,Vh);
+*/
+P[] = Mlap^-1*sdc;
+}
+timeLapl = clock()-timeLapl;
+
+// some verification of Boundary condition
+fespace RPh(Th,[RT03d,P0]);
+
+varf von1([u1,u2,u3,p],[v1,v2,v3,q])  = 
+   int3d(Th)( p*q*1e-15+ u1*v1 + u2*v2 + u3*v3 + p*div(v1,v2,v3) + div(u1,u2,u3)*q )
+ - int3d(Th) ( f*q)
+ + int2d(Th,1)( gd*(v1*N.x +v2*N.y + v3*N.z) )  //  int on gamma 
+ + on(2,u1=g1n,u2=g2n,u3=g3n);
+
+RPh [vv1,vv2,vv3,qq];
+// some verification Boundary Condition
+// and interpolation ...
+real[int]  ron=von1(0,RPh);
+vv3[]=von1(0,RPh);
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << endl;
+[vv1,vv2,vv3,qq]=[g1n,g2n,g3n,100];
+[v1,v2,v3]=[g1n,g2n,g3n];
+
+cout << " vv: = " << vv1(.1,.2,.001)  << " " << vv2(.1,.2,.001) << " " << vv3(.1,.2,.001) << " " << qq(.1,.2,.001) << endl;
+cout << " v : = " << v1(.1,.2,.001)  << " " << v2(.1,.2,.001) << " " << v3(.1,.2,.001)  << endl;
+
+// end of verification of Boundary Condition ... 
+
+
+/*
+problem laplaceMixte([u1,u2,u3,p],[v1,v2,v3,q],solver=sparsesolver,tgv=1e30,sparams="nprow=1, npcol=2", dimKrylov=400) = 
+int3d(Th)( p*q*1e-15+ u1*v1 + u2*v2 + u3*v3 + p*div(v1,v2,v3) + div(u1,u2,u3)*q )
+ + int3d(Th) ( f*q)
+ - int2d(Th,1)( gd*(v1*N.x +v2*N.y + v3*N.z) )  //  int on gamma 
+ + on(2,u1=g1n,u2=g2n,u3=g3n);
+*/
+
+RPh [uu1,uu2,uu3,pp];
+//RPh [v1,v2,v3,q];
+
+real tMatrix=clock();
+varf vlaplaceMixte([uu1,uu2,uu3,pp],[v1,v2,v3,q]) = int3d(Th)( pp*q*1e-15+ uu1*v1 + uu2*v2 + uu3*v3 + pp*div(v1,v2,v3) + div(uu1,uu2,uu3)*q )+on(2,uu1=g1n,uu2=g2n,uu3=g3n);
+matrix MlaplaceMixte = vlaplaceMixte(RPh,RPh,tgv=ttgv,solver=sparsesolver);
+tMatrix=clock()-tMatrix;
+
+real tFact=clock();
+set(MlaplaceMixte,solver=sparsesolver,tgv=ttgv,sparams="nprow=1, npcol=2", dimKrylov=400);
+tFact=clock()-tFact;
+
+real tscd=clock();
+varf vsdcLM([uu1,uu2,uu3,pp],[v1,v2,v3,q]) = -int3d(Th) ( f*q) + int2d(Th,1)( gd*(v1*N.x+v2*N.y + v3*N.z) )+on(2,uu1=g1n,uu2=g2n,uu3=g3n);
+real[int] sdcLM = vsdcLM(0,RPh);
+tscd=clock()-tscd;
+
+real tsolve=clock();
+uu1[] = MlaplaceMixte^-1*sdcLM;
+tsolve=clock()-tsolve;
+
+cout << "=============================" << endl;
+cout << "CPU TIME Lapl: " << timeLapl << endl;
+cout << "=============================" << endl;
+
+cout << "=============================" << endl;
+cout << "CPU TIME Lapl Mixte:         " << endl;
+cout << " matrix         "<< tMatrix << endl;
+cout << " factorization  "<< tFact   << endl;
+cout << " second menber  "<< tscd    << endl;
+cout << " solving        "<< tsolve  << endl;
+cout << "=============================" << endl;
+
+//if(mpirank==0){
+real errL2=sqrt(int3d(Th)(square(P-pp))) ;
+cout << " int 2 x,yz "<<int2d(Th,2)(x) << " " << int2d(Th,2)(y) << " " << int2d(Th,2)(z) << endl;
+cout << " int 2 gn "<<int2d(Th,2)(g1n) << " " << int2d(Th,2)(g2n) << " " << int2d(Th,2)(g3n) << endl;
+cout << " int 2 U  "<<int2d(Th,2)(uu1) << " " << int2d(Th,2)(uu2) << " " << int2d(Th,2)(uu3) << endl;
+cout << " int 2 V  "<<int2d(Th,2)(v1) << " " << int2d(Th,2)(v2) << " " << int2d(Th,2)(v3) << endl;
+cout << " int 2 DP "<<int2d(Th,2)(dx(P)) << " " << int2d(Th,2)(dy(P)) << " " << int2d(Th,2)(dz(P)) << endl;
+  
+cout << "  diff: u Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (uu1*N.x +uu2*N.y + uu3*N.z) ) ) ) <<endl;
+cout << "  diff: P Gamma_2 " <<    sqrt(int2d(Th,2) ( square((g1n*N.x+g2n*N.y+g3n*N.z) - (dx(P)*N.x +dy(P)*N.y + dz(P)*N.z) ) ) ) <<endl;
+cout << " diff err L2 :" << errL2 << endl;
+cout << "    P     L2 :" <<sqrt(int3d(Th)(square(P))) << endl;
+cout << "    p     L2 :" <<sqrt(int3d(Th)(square(pp))) << endl;
+assert(errL2<0.05);
+//}
\ No newline at end of file
diff --git a/examples++-mpi/MPICG.cpp b/examples++-mpi/MPICG.cpp
new file mode 100644
index 0000000..dc7a955
--- /dev/null
+++ b/examples++-mpi/MPICG.cpp
@@ -0,0 +1,501 @@
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+//ff-c++-LIBRARY-dep:  mpi
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include "mpi.h"
+#include  <iostream>
+using namespace std;
+
+#include "ff++.hpp"
+#include "CGNL.hpp"
+//#include "gmres.hpp"
+
+
+template<class R,class DJ,class P> 
+int NLCG(const DJ & dJ,const P & C,KN_<R> &x,const int nbitermax, double &eps,long kprint,MPI_Comm * )
+{
+    //  -------------
+    assert(&x && &dJ && &C);
+    typedef KN<R> Rn;
+    int n=x.N();
+    
+    R ro=1;
+    Rn g(n),h(n),Ah(n), & Cg(Ah);  // on utilise Ah pour stocke Cg  
+    g=dJ*x;// dJ(x,g);  
+    Cg = C*g; // gradient preconditionne 
+    h =-Cg; 
+    R g2 = (Cg,g);
+    if (g2 < 1e-30) 
+      { if(kprint>1)
+	  cout << "GCNL  g^2 =" << g2 << " < 1.e-30  Nothing to do " << endl;
+	  return 2;  }
+    if (kprint>5 ) 
+	cout << " 0 GCNL  g^2 =" << g2 << endl;
+    R reps2 =eps >0 ?  eps*eps*g2 : -eps; // epsilon relatif 
+    eps = reps2;
+    for (int iter=0;iter<=nbitermax;iter++)
+      { 
+	  ro = argmin(ro,dJ,x,h,g,Ah);
+	  
+	  Cg = C*g;
+	  R g2p=g2; 
+	  g2 = (Cg,g);
+	  if (  kprint < nbitermax )
+	      cout << "CGNL:" <<iter <<  ",  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+	  if (g2 < reps2) { 
+	      if (kprint< nbitermax )
+		  cout << "CGNL converge: " << iter <<",  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+	      return 1;// ok 
+	  }
+	  R gamma = g2/g2p;       
+	  h *= gamma;
+	  h -= Cg;  //  h = -Cg * gamma* h       
+      }
+    if(verbosity)
+	cout << " Non convergence of the NL cojugate gradient " <<endl;
+    return 0; 
+}
+template<class T> struct MPI_TYPE {};
+template<> struct MPI_TYPE<long>      {static const MPI_Datatype  TYPE(){return MPI_LONG;}};
+template<> struct MPI_TYPE<int>      {static const MPI_Datatype TYPE(){return MPI_INT;}};
+template<> struct MPI_TYPE<double>    {static const MPI_Datatype TYPE(){return MPI_DOUBLE;}};
+template<> struct MPI_TYPE<char>    {static const MPI_Datatype TYPE(){return MPI_BYTE;}};
+
+template<class R>
+R ReduceSum1(R s,MPI_Comm * comm)
+{
+  R r=0;
+  //  nt MPI_Allreduce( void *sendbuf, void *recbuf,  int count,
+  //	    MPI_Datatype datatype, MPI_Op op, MPI_Comm comm )
+  MPI_Allreduce( &s, &r, 1 ,MPI_TYPE<R>::TYPE(),   MPI_SUM,  *comm );
+  return r; 
+}
+
+template<class R,class M,class P> 
+int ConjuguedGradient2(const M & A,const P & C,KN_<R> &x,const KN_<R> &b,const int nbitermax, double &eps,long kprint,MPI_Comm * commworld)
+{
+    //  ConjuguedGradient2 affine A*x = 0 est toujours appele avec les condition aux limites 
+    //  -------------
+    throwassert(&x  && &A && &C);
+    typedef KN<R> Rn;
+    int n=x.N();
+   // if (verbosity>99) kprint=1;
+    R ro=1;
+    Rn g(n),h(n),Ah(n), & Cg(Ah);  // on utilise Ah pour stocke Cg  
+    g = A*x;
+    g -= b;  
+    Cg = C*g; // gradient preconditionne 
+    h =-Cg; 
+    R g2 = ReduceSum1((Cg,g),commworld);
+    if (g2 < 1e-30) 
+      { if(kprint<=nbitermax)
+	  cout << "GC  g^2 =" << g2 << " < 1.e-30  Nothing to do " << endl;
+	  return 2;  }
+    if (kprint<5 ) 
+	cout << " 0 GC  g^2 =" << g2 << endl;
+    R reps2 =eps >0 ?  eps*eps*g2 : -eps; // epsilon relatif 
+    eps = reps2;
+    for (int iter=0;iter<=nbitermax;iter++)
+      { 
+	  R rop = ro; 
+	  x += rop*h;      //   x+ rop*h  , g=Ax   (x old)
+	  //       ((Ah = A*x - b) - g);
+	  // Ah -= b;        //   Ax + rop*Ah = rop*Ah + g  =
+	  // Ah -= g;         //   Ah*rop  
+	  Ah = A*x;
+	  Ah -= b;        //   Ax + rop*Ah = rop*Ah + g  =
+	  Ah -= g;         //   Ah*rop  
+	 
+	  R hAh =ReduceSum1((h,Ah),commworld);
+	  R gh = ReduceSum1((g,h),commworld);
+	  if (RNM::norm2(hAh)<1e-100) ExecError("CG2: Matrix is not defined (/0), sorry ");
+	  ro =  -gh*rop/hAh ; // ro optimal (produit scalaire usuel)
+	  x += (ro-rop) *h;
+	  g += (ro/rop) *Ah; // plus besoin de Ah, on utilise avec Cg optimisation
+	  Cg = C*g;
+	  R g2p=g2; 
+	  g2 = ReduceSum1((Cg,g),commworld);
+	  if ( ( (iter%kprint) == kprint-1)  )
+	      cout << "CG:" <<iter <<  "  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+	  if (g2 < reps2) { 
+	      if (kprint <= nbitermax)
+		  cout << "CG converges " << iter <<  "  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+	      return 1;// ok 
+          }
+	  R gamma = g2/g2p;       
+	  h *= gamma;
+	  h -= Cg;  //  h = -Cg * gamma* h       
+      }
+    //    if (itermax <= nbitermax  )
+	cout << "CG does'nt converge: " << nbitermax <<   " ||g||^2 = " << g2 << " reps2= " << reps2 << endl; 
+    return 0; 
+}
+
+
+template < class Operator, class Vector, class Preconditioner,
+class Matrix, class Real >
+int 
+GMRES_MPI(const Operator &A, Vector &x, const Vector &b,
+      const Preconditioner &M, Matrix &H, int &m, int &max_iter,
+      Real &tol,MPI_Comm * commworld,long verbosity)
+{
+    Real resid;
+    int i, j = 1, k;
+    Vector s(m+1), cs(m+1), sn(m+1), w,r,Ax;
+    r=M*b;
+    Real normb = sqrt(ReduceSum1((r,r),commworld));
+    
+    Ax=A * x;
+    Ax=b-Ax;
+    r = M*(Ax);
+    Real beta = sqrt(ReduceSum1((r,r),commworld));
+    
+    if ( abs(normb) < 1.e-30)
+	normb = 1;
+    
+    if ((resid = beta / normb) <= tol) {
+	tol = resid;
+	max_iter = 0;
+	return 0;
+    }
+    
+    Vector *v = new Vector[m+1];
+    
+    while (j <= max_iter) {
+	v[0] = r / beta;    
+	s = 0.0;
+	s(0) = beta;
+	
+	for (i = 0; i < m && j <= max_iter; i++, j++) {
+	    w = M*(Ax=A * v[i]);
+	    for (k = 0; k <= i; k++) {
+		H(k, i) = ReduceSum1((w, v[k]),commworld);
+		w -= H(k, i) * v[k];
+	    }
+	    H(i+1, i) = sqrt(ReduceSum1((w,w),commworld));
+	    v[i+1] = w  / H(i+1, i) ; 
+	    
+	    for (k = 0; k < i; k++)
+		ApplyPlaneRotation(H(k,i), H(k+1,i), cs(k), sn(k));
+	    
+	    GeneratePlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
+	    ApplyPlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
+	    ApplyPlaneRotation(s(i), s(i+1), cs(i), sn(i));
+	    if(verbosity>5 || (verbosity>2 && j%100==0) )
+		cout << "GMRES: " << j << " " << abs(s(i+1)) << " " <<  normb << " " 
+		<<  abs(s(i+1)) / normb << " < " << tol << endl;
+	    
+	    if ((resid = abs(s(i+1)) / normb) < tol) {
+		if(verbosity)
+		    cout << "GMRES converges: " << j << " " << abs(s(i+1)) << " " <<  normb << " " 
+		    <<  abs(s(i+1)) / normb << " < " << tol << endl;
+		
+		Update(x, i, H, s, v);
+		tol = resid;
+		max_iter = j;
+		delete [] v;
+		return 0;
+	    }
+	}
+	if(!(j <= max_iter)) break;
+	Update(x, i-1 , H, s, v);
+	Ax = A*x;
+	Ax = b-Ax;
+	
+	r = M*(Ax);
+	beta = sqrt(ReduceSum1((r,r),commworld));
+	if(verbosity>4)
+	    cout << "GMRES: restart" << j << " " << beta << " " <<  normb << " " 
+	    <<  beta / normb << " < " << tol << endl;
+	if ((resid = beta / normb) < tol) {
+	    tol = resid;
+	    max_iter = j;
+	    delete [] v;
+	    return 0;
+	}
+    }
+    
+    if(verbosity)
+	cout << "WARNING: GMRES do not converges: " << j <<"/" << max_iter << ",  resid = " << resid 
+	<< ", tol=  " << tol << ", normb "<< normb << endl;
+    tol = resid;
+    delete [] v;
+    
+    return 1;
+}
+
+
+template<class R>
+class MPILinearCG : public OneOperator 
+{ 
+public:
+    typedef KN<R> Kn;
+    typedef KN_<R> Kn_;
+    const int cas,CG;
+    
+    class MatF_O: VirtualMatrice<R> { public:
+	Stack stack;
+	mutable  Kn x;       
+	C_F0 c_x;
+	Kn *b;
+	
+	Expression  mat1,mat;
+	typedef  typename VirtualMatrice<R>::plusAx plusAx;
+	MatF_O(int n,Stack stk,const OneOperator * op,Kn *bb=0) 
+	: VirtualMatrice<R>(n),stack(stk),
+	x(n),c_x(CPValue(x)),b(bb),
+	mat1(op->code(basicAC_F0_wa(c_x))),
+	mat( CastTo<Kn_>(C_F0(mat1,(aType)*op))) {
+	    //ffassert(atype<Kn_ >() ==(aType) *op);
+	    // WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+	    
+	}
+	~MatF_O() { 
+	    // cout << " del MatF_O mat " << endl;
+	    if(mat1 != mat) 
+		delete mat;
+	    delete mat1;
+	    // cout << " del MatF_Ocx ..." <<  endl;
+	    Expression zzz = c_x;
+	    // cout << " zzz "<< zzz << endl;
+	    delete zzz;
+	    // WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+	    
+	}
+	void addMatMul(const  Kn_  & xx, Kn_ & Ax) const { 
+	    ffassert(xx.N()==Ax.N());
+	    x =xx;
+	    Ax  += GetAny<Kn_>((*mat)(stack));
+	    if(b && &Ax!=b) Ax += *b; // Ax -b => add b (not in cas of init. b c.a.d  &Ax == b 
+	    WhereStackOfPtr2Free(stack)->clean();
+	} 
+	plusAx operator*(const Kn &  x) const {return plusAx(this,x);} 
+	virtual bool ChecknbLine(int n) const { return true;}  
+	virtual bool ChecknbColumn(int m) const { return true;} 
+	
+    };  
+    
+    
+    class E_LCG: public E_F0mps { public:
+	const int cas;// <0 => Nolinear
+	const int CG; 
+	static const int n_name_param=7;
+	
+	static basicAC_F0::name_and_type name_param[] ;
+	
+	
+	Expression nargs[n_name_param];
+	
+	const OneOperator *A, *C; 
+	Expression X,B;
+	
+	E_LCG(const basicAC_F0 & args,int cc,int gc) :cas(cc),CG(gc) 
+	{
+	  args.SetNameParam(n_name_param,name_param,nargs);
+	  {  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+	      ffassert(op);
+	      A = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); }
+	  if (nargs[2]) 
+	    {  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(nargs[2]);
+		ffassert(op); 
+		C = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); }
+	  else  C =0;
+	  X = to<Kn*>(args[1]);
+	  if (args.size()>2)
+	      B = to<Kn*>(args[2]);
+	  else 
+	      B=0;
+	}
+	
+	virtual AnyType operator()(Stack stack)  const {
+	    int ret=-1;
+	    
+	    // WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+	    try {
+		Kn &x = *GetAny<Kn *>((*X)(stack));
+		int n=x.N();
+		double eps = 1.0e-6;
+		int nbitermax=  100;
+		long verb = verbosity;
+		
+		pcommworld vcommworld=0;
+		long dKrylov=50; 
+		if (nargs[0]) eps= GetAny<double>((*nargs[0])(stack));
+		if (nargs[1]) nbitermax = GetAny<long>((*nargs[1])(stack));
+		if (nargs[3]) eps= *GetAny<double*>((*nargs[3])(stack));
+		if (nargs[4]) vcommworld = GetAny<pcommworld>((*nargs[4])(stack));
+		if (nargs[5])  dKrylov= GetAny<long>((*nargs[5])(stack));
+                if (nargs[6]) verb=Abs(GetAny<long>((*nargs[6])(stack)));
+		long gcverb=51L-Min(Abs(verb),50L);
+		if(verb==0) gcverb = 1000000000;// no print 
+
+		MPI_Comm mpiCommWorld = MPI_COMM_WORLD;
+		MPI_Comm * commworld= vcommworld ? (MPI_Comm *) vcommworld: & mpiCommWorld ;
+		KN<R>  bzero(B?1:n); // const array zero
+		bzero=R(); 
+		KN<R> *bb=&bzero; 
+		if (B) {
+		    Kn &b = *GetAny<Kn *>((*B)(stack));
+		    R p = (b,b);
+		    if (p) 
+		      {
+			// ExecError("Sorry MPILinearCG work only with nul right hand side, so put the right hand in the function");
+		      }
+		    bb = &b;
+		}
+		KN<R> * bbgmres =0;
+		if ( !B && !CG) bbgmres=bb; // none zero if gmres without B 		
+		MatF_O AA(n,stack,A,bbgmres);
+		if(bbgmres ){
+		    *bbgmres= AA* *bbgmres; // Ok Ax == b -> not translation of b .
+		    *bbgmres = - *bbgmres;
+		    if(verbosity>1) cout << "  ** GMRES set b =  -A(0);  : max=" << bbgmres->max() << " " << bbgmres->min()<<endl;
+		}
+		
+		if(CG)
+		  {
+		    
+		  
+		 if (cas<0) {
+		    if (C) 
+		      { MatF_O CC(n,stack,C);
+			ret = NLCG(AA,CC,x,nbitermax,eps, gcverb ,commworld );}
+		    else 
+		      ret = NLCG(AA,MatriceIdentite<R>(n),x,nbitermax,eps, gcverb ,commworld);
+		}
+		 else 
+		    if (C) 
+		      { MatF_O CC(n,stack,C);
+			ret = ConjuguedGradient2(AA,CC,x,*bb,nbitermax,eps, gcverb ,commworld);}
+		    else 
+		      ret = ConjuguedGradient2(AA,MatriceIdentite<R>(n),x,*bb,nbitermax,eps, gcverb ,commworld);
+		  }
+		else {// GMRES 
+		    
+		    KNM<R> H(dKrylov+1,dKrylov+1);
+		    int k=dKrylov;//,nn=n;
+		    if (cas<0) {
+			ErrorExec("NL GMRES:  to do! sorry ",1);
+			/*       if (C) 
+			 { MatF_O CC(n,stack,C);
+			 ret = NLGMRES(AA,CC,x,nbitermax,eps, 51L-Min(Abs(verbosity),50L) );}
+			 else 
+			 ret = NLGMRES(AA,MatriceIdentite<R>(n),x,nbitermax,eps, 51L-Min(Abs(verbosity),50L));
+			 ConjuguedGradient  */
+		    }
+		    else 
+		      {
+			if (C)
+			  { MatF_O CC(n,stack,C); 
+			      ret=GMRES_MPI(AA,(KN<R> &)x, *bb,CC,H,k,nbitermax,eps,commworld,verb);}
+			else
+			    ret=GMRES_MPI(AA,(KN<R> &)x, *bb,MatriceIdentite<R>(n),H,k,nbitermax,eps,commworld,verb);       
+		      }
+		    
+		}
+		
+		
+
+		if( nargs[3]) *GetAny<double*>((*nargs[3])(stack)) = -(eps);
+	    }
+	    catch(...)
+	  {
+	    // WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+	    throw;
+	  }
+	    // WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+	    
+	    return SetAny<long>(ret);
+	    
+	}  
+	operator aType () const { return atype<long>();}         
+	
+    };
+    
+    E_F0 * code(const basicAC_F0 & args) const {
+	return new E_LCG(args,cas,CG);}
+
+    MPILinearCG() :   OneOperator(atype<long>(),
+			       atype<Polymorphic*>(),
+ 			       atype<KN<R> *>(),atype<KN<R> *>()),cas(2),CG(1){}
+    
+    MPILinearCG(int cc,int CGG) :   OneOperator(atype<long>(),
+			       atype<Polymorphic*>(),
+			       atype<KN<R> *>(),atype<KN<R> *>()),cas(cc),CG(CGG){}
+
+    MPILinearCG(int cc,int CGG,int ) :   OneOperator(atype<long>(),
+						atype<Polymorphic*>(),
+						atype<KN<R> *>()),cas(cc),CG(CGG){}
+    
+    MPILinearCG(int cc) :   OneOperator(atype<long>(),
+				     atype<Polymorphic*>(),
+				     atype<KN<R> *>()),cas(cc),CG(1){}
+    
+};
+
+
+
+
+template<class R>
+basicAC_F0::name_and_type  MPILinearCG<R>::E_LCG::name_param[]= {
+    {   "eps", &typeid(double)  },
+    {   "nbiter",&typeid(long) },
+    {   "precon",&typeid(Polymorphic*)},
+    {   "veps" ,  &typeid(double*) },
+    { "comm", &typeid(pcommworld)} ,
+    {   "dimKrylov", &typeid(long) },
+    {   "verbosity", &typeid(long) }
+};
+
+
+
+
+
+/* --FH:   class Init { public:
+    Init();
+};
+
+LOADINIT(Init);
+*/ 
+static void Load_Init()
+{ 
+
+    Global.Add("MPILinearCG","(",new MPILinearCG<R>()); // old form  with rhs (must be zer
+    Global.Add("MPIAffineCG","(",new MPILinearCG<R>(1)); //  without right handsize
+    Global.Add("MPILinearGMRES","(",new MPILinearCG<R>(0,0)); //  with  right handsize
+    Global.Add("MPIAffineGMRES","(",new MPILinearCG<R>(0,0,0)); //  with  right handsize
+    Global.Add("MPINLCG","(",new MPILinearCG<R>(-1)); //  without right handsize
+    
+}
+
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/MPICGLap.edp b/examples++-mpi/MPICGLap.edp
new file mode 100644
index 0000000..3464a41
--- /dev/null
+++ b/examples++-mpi/MPICGLap.edp
@@ -0,0 +1,182 @@
+load "MPICG"
+
+// the grad of the bilinear part of J (the RHS in remove)
+   int n=3;
+  real[int]  b(n),u(n);
+  b=1;
+   u=0; // set  right hand side and initial gest
+
+  func real[int] matId(real[int] &u) { return u;};
+  func real[int] DJ0(real[int] &u)
+    { 
+      for (int i=0;i<u.n;i++)
+	u[i]=10*mpirank+(i+1)*u[i];
+      return u;  // return of global variable ok 
+   };
+  func real error(real[int] & u,real[int] & b)
+   {
+   real s=0;
+     for (int i=0;i<u.n;i++)
+	s += abs(10*mpirank+(i+1)*u[i] - b[i]);
+   return s;    
+   }
+
+  b=1; u=0; // set  right hand side and initial gest
+  MPILinearCG(DJ0,u,b,eps=1.e-6,nbiter=20,precon=matId);
+  cout << "LinearCG (Linear)  err=" << error(u,b) << endl;
+  assert(error(u,b) < 1e-5);
+
+
+{
+  int[int] procs=[0,1];
+  mpiGroup gpr(procs);
+  cout << " before  ...  " << mpirank << endl;
+  mpiComm comm(gpr);
+  if(comm)  // ..  comm 
+    {
+      int rank=mpiRank(comm);
+      cout << " rank = " << rank << endl; 
+      mesh[int]  aTh(2);
+      int[int]  ll=[1,2-rank,1,1+rank];
+      aTh[rank]=square(4,4,[rank+x,y], label=ll);	  
+      broadcast(processor(0,comm),aTh[0]);
+      broadcast(processor(1,comm),aTh[1]);
+      mesh Th=aTh[rank];
+      mesh Thi=aTh[1-rank]; 
+      mesh Thh = Th+Thi;
+      
+      
+      fespace Vh(Th,P1);	
+      fespace Vhi(Thi,P1);
+      
+      matrix Ihi=interpolate(Vh,Vhi, inside=1);// Vh <-Vhi
+      cout << rank << " Ihi = "<< Ihi << " ---- " << endl;
+      
+      // compresse row numbering to min. th comm.
+      int [int] Ii(Vhi.ndof),II(Vh.ndof);
+      real[int] dhi(Vh.ndof);
+      int nn,NN;
+      { 
+	Vh uh=1.; Vhi ui=1;
+	real[int] vi(0:ui[].n-1);
+	ui[] =Ihi'*uh[];//';
+	ui[] = ui[] ? 1 : 0;
+	nn = rint(ui[].sum);
+	vi = ui[] ? vi : 1e30;
+	vi.sort;
+	//	   cout << vi[nn] << " " << vi[nn-1] << endl;
+	assert(vi[nn]>1e10 && vi[nn-1] < 1e10);
+	vi.resize(nn);
+	Ii.resize(nn);
+	for(int i=0;i<nn;++i)
+	  Ii[i]=vi[i];
+	processor(1-rank,comm) << nn;
+	processor(1-rank,comm) >> NN;
+	assert( nn == NN) ;
+	//   II.resize(NN);
+	processor(1-rank,comm) <<Ii;
+	processor(1-rank,comm) >>II;	     
+	//cout << Ii << endl;
+	real Ihioo=0;
+	try {
+	  Ihioo= Ihi(Vh.ndof-1,Ii[nn-1]);
+	}
+	   catch(...) {;};
+	int[int] I(0:Vh.ndof-1);
+	Ihi = Ihi(I,Ii);
+	assert(Ihi(Vh.ndof-1,nn-1) == Ihioo);
+	// cout << rank << " Ihi = "<< Ihi << " ---- " << endl;
+	dhi=1;
+	vi=1;
+	dhi += Ihi*vi;
+	real[int] one(dhi);one=1.;
+	dhi = one ./ dhi;
+	cout << dhi << endl;
+      }
+      
+      real[int] tosend(NN),torecv(nn);
+      real tgv=1e3;
+      macro  Grad(u) [dx(u),dy(u)] //
+	varf va(u,v)=int2d(Th)(u*v+Grad(u)'*Grad(v)) - int2d(Th)( x*v ) -int1d(Th,1)( N.x*v)  ;	      ;//');
+      matrix A=va(Vh,Vh,tgv=tgv);
+      real[int] b=va(0,Vh,tgv=tgv);   
+      int kiter=0;
+      func real[int] projC(real[int] &u)
+      {
+	verbosity=0;
+	processor(1-rank,comm) << (tosend = u(II));
+	processor(1-rank,comm) >> torecv;
+	//cout << "to send " << tosend << endl;
+	u += Ihi*torecv;
+	//  u = u .* dhi;
+	Vh uu; uu[]=u;
+	//     cout << kiter++ << " " << mpirank <<  " ---  " <<  uu(1,0.5) << endl; 	      
+	return   u;	      
+      }	  
+      
+      func real[int] projD(real[int] &u)
+      {
+	verbosity=0;
+	processor(1-rank,comm) << (tosend = u(II));
+	processor(1-rank,comm) >> torecv;
+	u += Ihi*torecv;
+	u = u .* dhi;
+	Vh uu; uu[]=u;
+	//   cout << kiter++ << " " << mpirank <<  " ---  " <<  uu(1,0.5) << endl; 	      
+	return   u;	      
+      }	
+  
+      func bool  Plot(real[int] & uu)
+      {
+	Vh u; u[]=uu;
+	Vhi ui;
+	if(rank==0)
+	  {     
+	    processor(1,comm) >> ui[];
+	    plot(u,ui,wait=1);
+	  }
+	else
+	  processor(0,comm) << u[];
+	return true;
+      }
+      
+      func real[int] DJJ(real[int] &v)
+      { 
+	verbosity=0;
+	// Plot(v);
+	v = projD(v);
+	real[int] u=A*v;
+	u += b; 
+	u = projC(u);
+	verbosity=101;
+	return u;  // return 
+      };		  
+      
+      func real[int] matId(real[int] &u) { 
+	verbosity=0;
+	u =projD(u);
+	verbosity=100;
+	return u;};
+      
+      
+      
+      
+      Vh u=0;
+      
+      u=0;
+      verbosity=100;
+      MPIAffineCG(DJJ,u[],eps=1.e-4,nbiter=200,precon=matId,comm=comm);
+      projD(u[]);
+      Plot(u[]);
+      if(rank==0)
+	{
+	  fespace Vhh(Thh,P1);
+	  Vhh uuu,vvv;
+	  // u = x , dn(x) = N.x 
+	  solve PPPP(uuu,vvv) = int2d(Thh)(uuu*vvv+Grad(uuu)'*Grad(vvv)) - int2d(Thh)( x*vvv ) -int1d(Thh,1)( N.x*vvv)  ; //');
+	  cout << " err = " << int2d(Th)( square(uuu-u)) << " " << int2d(Thh)( square(uuu-x)) << endl;
+	  savemesh(Thh,"/tmp/Thh.msh");
+	}
+    }
+}
+
diff --git a/examples++-mpi/MPIGMRES2D.edp b/examples++-mpi/MPIGMRES2D.edp
new file mode 100644
index 0000000..057ed10
--- /dev/null
+++ b/examples++-mpi/MPIGMRES2D.edp
@@ -0,0 +1,468 @@
+// NBPROC 10
+// ff-mpirun -np 4 MPIGMRES2D.edp -glut ffglut  -n 11 -k 1  -d 1 -ns -gmres 1
+/*
+  a first true parallele example fisrt freefem++ 
+  Ok up to 200 proc for a Poisson equation.. 
+  See the Doc for full explaiantion
+
+  F Hecht Dec. 2010. 
+  -------------------
+usage :
+ff-mpirun [mpi parameter] MPIGMRES2d.edp  [-glut ffglut]  [-n N] [-k K]  [-d D] [-ns] [-gmres [0|1]
+ argument: 
+   -glut ffglut : to see graphicaly the process
+   -n N:  set the mesh cube split NxNxN
+   -d D:  set debug flag D must be one for mpiplot 
+   -k K:  to refined by K all  elemnt
+   -ns: reomove script dump
+   -gmres 0   : use iterative schwarz algo.  
+          1   :  Algo GMRES on residu of schwarz algo.
+          2   :  DDM GMRES 
+          3   :  DDM GMRES with coarse grid preconditionner (Good one)  
+*/
+load "MPICG"  load "medit"  load "metis"
+include "getARGV.idp"
+include "MPIplot.idp"
+include "MPIGMRESmacro.idp"
+include "AddLayer2d.idp" 
+
+searchMethod=1; // more safe seach algo (warning can be very expensive in case lot of ouside point) 
+assert(version >=3.11);
+real[int] ttt(10);int ittt=0;
+macro settt {ttt[ittt++]=mpiWtime();}//
+
+
+verbosity=getARGV("-vv",0);
+int vdebug=getARGV("-d",1);
+int ksplit=getARGV("-k",3);
+int nloc = getARGV("-n",10);
+string sff=getARGV("-p,","");
+int gmres=getARGV("-gmres",2); 
+bool dplot=getARGV("-dp",0);
+int nC = getARGV("-N" ,max(nloc/10,4)); 
+
+if(mpirank==0 && verbosity)
+{
+  cout << "ARGV : ";
+  for(int i=0;i<ARGV.n;++i)
+    cout << ARGV[i] <<" ";
+  cout << endl;
+}
+
+
+if(mpirank==0 && verbosity)
+  cout << " vdebug: " << vdebug << " kspilt "<< ksplit << " nloc "<< nloc << " sff "<< sff <<"."<< endl;
+
+int withplot=0;
+bool withmetis=1;
+bool RAS=1; 
+string sPk="P2-2gd";     
+func Pk=P2;
+
+func bool  plotMPIall(mesh &Th,real[int] & u,string  cm)
+{if(vdebug) PLOTMPIALL(mesh,Pk, Th, u,{ cmm=cm,nbiso=20,fill=1,dim=3,value=1}); return 1;}
+
+int sizeoverlaps=1; // size of overlap
+
+mpiComm comm(mpiCommWorld,0,0);// trick : make a no split mpiWorld 
+ 
+int npart=mpiSize(comm); // total number of partion
+int ipart= mpiRank(comm); // current partition number 
+
+int njpart=0; // nb of part with intersection (a jpart) with ipart without ipart
+int[int] jpart(npart); //  list of jpart ..
+if(ipart==0)  cout << " Final N=" << ksplit*nloc << " nloc =" << nloc << " split =" << ksplit <<  endl;
+int[int] l111=[1,1,1,1]; 
+settt 
+
+mesh Thg=square(nloc,nloc,label=l111);
+mesh ThC=square(nC,nC,label=l111);//   Caarse Mesh
+
+mesh Thi,Thin;//  with overlap, without olverlap  
+fespace Phg(Thg,P0);
+fespace Vhg(Thg,P1);
+fespace VhC(ThC,P1); // of the coarse problem.. 
+
+
+Phg  part;
+
+// build the partitioning ...  
+{    
+ int[int] nupart(Thg.nt);
+ nupart=0; 
+ if(npart>1 && ipart==0)
+   metisdual(nupart,Thg,npart); 
+   
+ broadcast(processor(0,comm),nupart);
+ for(int i=0;i<nupart.n;++i)
+    part[][i]=nupart[i];
+  
+} // build ... 
+
+
+if(withplot>1)
+  plot(part,fill=1,cmm="dual",wait=1);
+
+// overlapping partition
+
+ Phg suppi= abs(part-ipart)<0.1; 
+ Vhg unssd;                       // boolean function 1 in the subdomain 0 elswhere 
+ Thin=trunc(Thg,suppi>0,label=10); // non-overlapping mesh, interfaces have label 10
+ int nnn = sizeoverlaps*2;// to be sure 
+ AddLayers(Thg,suppi[],nnn,unssd[]);    // see above ! suppi and unssd are modified  
+ unssd[] *= nnn;  //  to put value nnn a 0  
+ real nnn0 = nnn - sizeoverlaps +  0.001   ;
+ Thi=trunc(Thg,unssd>nnn0 ,label=10); // overlapping mesh, interfaces have label 10
+ 
+ settt 
+
+ fespace Vhi(Thi,P1);
+ int npij=npart;
+ Vhi[int] pij(npij);// local partition of unit + pii 
+ Vhi pii;  
+ 
+ real nnn1=  + 0.001  ;
+ { /*
+   construction of the partition of the unit,
+    let phi_i P1 FE function 1 on Thin and zero ouside of Thi and positive
+    the partition is build with  
+  $$  p_i = phi_i/ \sum phi_i 
+    
+    to build the partition of one domain i
+    we nned to find all j such that supp(phi_j) \cap supp(phi_j) is not empty
+    <=> int phi_j
+ */
+ //   build a local mesh of thii such that all compuation of the unit partition are
+ //   exact in thii
+ mesh Thii=trunc(Thg,unssd>nnn1 ,label=10); // overlapping mesh, interfaces have label 10
+
+
+ {  
+   // find all j  mes (supp(p_j) \cap supp(p_i)) >0  
+   // compute all phi_j on Thii
+   //  remark supp p_i include in Thi 
+   //  
+   fespace Phii(Thii,P0);
+   fespace Vhii(Thii,P1);
+   Vhi sumphi=0;
+   jpart=0;
+   njpart=0;
+   int nlayer=RAS?1:sizeoverlaps;
+   if(ipart==0) 
+     cout <<" nlayer=" << nlayer << endl;
+   pii= max(unssd-nnn+nlayer,0.)/nlayer;
+   if(dplot) plot(pii,wait=1,cmm=" 0000");
+   sumphi[] +=  pii[];
+   if(dplot) plot(sumphi,wait=1,cmm=" summ 0000");
+   Vhii phii=0;
+   real epsmes=1e-10*Thii.area;
+   for (int i=0;i<npart;++i)
+     if(i != ipart ) 
+       { 
+	    Phii suppii=abs(i-part)<0.2; 
+	    if(suppii[].max > 0.5) 
+	    {
+	     AddLayers(Thii,suppii[],nlayer,phii[]);
+	     assert(phii[].min >=0);
+	     real interij = int2d(Thi)(  phii); 
+	     if(interij>epsmes) 
+	       {  
+		     pij[njpart]=abs(phii);	 
+		     if(vdebug>2) cout << " ***** " << int2d(Thi)(real(pij[njpart])<0) << " " <<pij[njpart][].min << " " << phii[].min << endl;
+		     assert(int2d(Thi)(real(pij[njpart])<0) ==0);
+		     if(dplot)  plot(pij[njpart],wait=1,cmm=" j = "+ i + " " + njpart);
+		     sumphi[] += pij[njpart][]; 
+		     if(dplot)  plot(sumphi,wait=1,cmm=" sum j = "+ i + " " + njpart);
+		     jpart[njpart++]=i;
+	       }}}
+   
+   if(dplot) plot(sumphi,wait=1,dim=3,cmm="sum ",fill=1 );
+   pii[]=pii[] ./ sumphi[];
+   for (int j=0;j<njpart;++j)
+     pij[j][] = pij[j][] ./ sumphi[];
+   jpart.resize(njpart);	
+   for (int j=0;j<njpart;++j)
+     assert(pij[j][].max<=1);
+   {
+     cout << ipart << " number of jpart " << njpart << " : ";
+     for (int j=0;j<njpart;++j)
+       cout << jpart[j] << " ";
+  	cout << endl;
+   }
+   sumphi[]=pii[];
+   for (int j=0;j<njpart;++j)
+     sumphi[]+= pij[j][];
+   if(vdebug>2)  
+     cout << " sum min " <<sumphi[].min << " " << sumphi[].max << endl;
+   assert(sumphi[].min> 1.-1e-6 && sumphi[].max< 1.+1e-6);  
+   //  verification 
+ }}// (Thii is remove here) 
+  // end of the construction of the local partition of the unity ...
+  // on Thi ...  
+  // -----------------------------------------------------------------
+if(ipart==0) cout << " *** end build partition " << endl;
+
+//  computation of  number of intersection ..
+// ------------------------------------------
+
+// here  pii and the pij is the locate partition of the unite on 
+// Thi ( mesh with overlap )....
+//Thi=splitmesh(Thi,2);
+if(dplot ) 
+  { plot(Thi,wait=1); 
+    for(int j=0;j<njpart;++j)
+      plot(pij[j],cmm=" j="+j ,wait=1); } 
+      
+//  Partition of the unity on Thi ..
+// computation of message.
+// all j> we have to recive 
+// data on intersection of the support of pij[0] and pij[j]
+settt 
+
+ if(vdebug) plotMPIall(Thi,pii[],"pi_i");
+
+mesh[int] aThij(njpart); 
+matrix Pii;  
+matrix[int] sMj(njpart); // M of send to j
+matrix[int] rMj(njpart); // M to recv from j
+fespace Whi(Thi,Pk);
+mesh Thij=Thi;
+fespace Whij(Thij,Pk);// 
+
+// construction of the mesh intersect i,j part 
+for(int jp=0;jp<njpart;++jp)
+  aThij[jp]  = trunc(Thi,pij[jp]>1e-6,label=10); // mesh of the supp of pij
+
+for(int jp=0;jp<njpart;++jp)
+  aThij[jp]  = trunc(aThij[jp],1,split=ksplit);
+
+Thi =   trunc(Thi,1,split=ksplit);
+
+settt 
+
+if(ipart==0) cout << " *** end build mesh  intersection  " << endl;
+// construction of transfert  matrix
+{
+  Whi wpii=pii;
+  Pii = wpii[];
+  for(int jp=0;jp<njpart;++jp)
+    {
+      int j=jpart[jp];
+      Thij = aThij[jp];
+      matrix I = interpolate(Whij,Whi); // Whji <- Whi
+      sMj[jp] = I*Pii;  // Whi -> s Whij  
+      rMj[jp] = interpolate(Whij,Whi,t=1);   // Whji -> Whi
+      if(vdebug>10) {
+      {Whi uuu=1;Whij vvv=-1; vvv[]+=I*uuu[]; cout << jp << " %%% " << vvv[].linfty << endl; assert(vvv[].linfty < 1e-6);}
+      {Whi uuu=1;Whij vvv=-1; vvv[]+=rMj[jp]'*uuu[]; cout << jp << " ### " << vvv[].linfty << endl; assert(vvv[].linfty < 1e-6);}}
+    }}
+if(ipart==0) cout << " *** end build transfert matrix " << endl;
+// alloc array of send and recv data ..
+
+InitU(njpart,Whij,Thij,aThij,Usend)  // initU(n,Vh,Th,aTh,U)
+InitU(njpart,Whij,Thij,aThij,Vrecv) // ...
+if(ipart==0) cout << " *** end init  data for send/revc  " << endl;
+
+Whi ui,vi; 
+
+func bool Update(real[int] &ui, real[int] &vi)
+{
+  for(int j=0;j<njpart;++j)
+    Usend[j][]=sMj[j]*ui; 
+   SendRecvUV(comm,jpart,Usend,Vrecv)
+     vi = Pii*ui;
+   for(int j=0;j<njpart;++j)
+     vi += rMj[j]*Vrecv[j][]; 
+   return true;
+}
+
+
+// the definition of the Problem ....
+func G=x*0.1; // ok 
+func F=1.; // ok 
+macro grad(u) [dx(u),dy(u)] // 
+varf vBC(U,V)=  on(1,U=G); 
+varf vPb(U,V)= int2d(Thi)(grad(U)'*grad(V)) + int2d(Thi)(F*V) + on(10,U=0)+on(1,U=G) ; //');// for emacs
+varf vPbC(U,V)= int2d(ThC)(grad(U)'*grad(V))  +on(1,U=0) ; //');// for emacs
+varf vPbon(U,V)=on(10,U=1)+on(1,U=1);
+varf vPbon10only(U,V)=on(10,U=1)+on(1,U=0); 
+// remark the order is important we want 0 part on 10 and 1
+
+
+//----  
+
+matrix Ai = vPb(Whi,Whi,solver=sparsesolver);
+matrix AC,Rci,Pci;// 
+
+
+if(mpiRank(comm)==0)
+  AC = vPbC(VhC,VhC,solver=sparsesolver);
+
+Pci=   interpolate(Whi,VhC);
+Rci =  Pci'*Pii; 
+
+real[int] onG10 = vPbon10only(0,Whi);
+real[int] onG = vPbon(0,Whi);
+real[int] Bi=vPb(0,Whi);
+
+
+
+
+
+int kiter=-1;
+
+
+func bool  CoarseSolve(real[int]& V,real[int]& U,mpiComm& comm)
+{
+   //  solving the coarse probleme 
+   real[int] Uc(Rci.n),Bc(Uc.n); 
+   Uc= Rci*U;
+   mpiReduce(Uc,Bc,processor(0,comm),mpiSUM);
+   if(mpiRank(comm)==0) 
+      Uc = AC^-1*Bc;
+    broadcast(processor(0,comm),Uc);
+   V = Pci*Uc;
+}//EOF ...
+func real[int] DJ(real[int]& U)
+{ 
+  ++kiter;
+  real[int] V(U.n); 
+   V =  Ai*U;
+  V = onG10 ? 0.: V;  // remove internal boundary  
+  return V; 
+}
+
+func real[int] PDJ(real[int]& U) // C1
+{ 
+  real[int] V(U.n); 
+  
+  real[int] b= onG10 ? 0. :  U; 
+  V =  Ai^-1*b;	
+  Update(V,U);
+  return U; 
+}
+
+func real[int] PDJC(real[int]& U) // 
+{ // Precon  C1= Precon //, C2  precon Coarse
+// Idea : F. Nataf. 
+  //  0 ~  (I C1A)(I-C2A) => I ~  - C1AC2A +C1A +C2A 
+  //  New Prec P= C1+C2 - C1AC2   = C1(I- A C2) +C2
+  // (  C1(I- A C2) +C2 ) Uo 
+  //   V =  - C2*Uo
+  // .... 
+  real[int] V(U.n); 
+  CoarseSolve(V,U,comm);
+  V = -V; //  -C2*Uo 
+  U  += Ai*V; // U =  (I-A C2) Uo 
+  real[int] b= onG10 ? 0. :  U; 
+  U =  Ai^-1*b;	//  ( C1( I -A C2) Uo 
+  V = U -V; //  
+  Update(V,U);
+  return U; 
+}
+
+
+ func real[int] DJ0(real[int]& U)
+{ 
+  ++kiter;
+  real[int] V(U.n); 
+  real[int] b= onG .* U;
+  b  = onG ? b : Bi ;  
+  V = Ai^-1*b;	
+  Update(V,U);
+  V -= U;
+   return V; 
+}
+
+
+Whi u=0,v;
+{ // verification.....
+  Whi u=1,v;
+  Update(u[],v[]);
+  u[]-=v[];
+  assert( u[].linfty<1e-6); }
+  
+
+
+settt
+u[]=vBC(0,Whi,tgv=1); // set u with tge BC value ...
+
+real epss=1e-6;
+int rgmres=0;
+if(gmres==1)
+  {
+   rgmres=MPIAffineGMRES(DJ0,u[],veps=epss,nbiter=300,comm=comm,dimKrylov=100,verbosity=ipart ? 0: 50);
+   real[int] b= onG .* u[];
+   b  = onG ? b : Bi ;
+   v[] = Ai^-1*b;	
+   Update(v[],u[]);
+  }
+else if(gmres==2)
+  rgmres= MPILinearGMRES(DJ,precon=PDJ,u[],Bi,veps=epss,nbiter=300,comm=comm,dimKrylov=100,verbosity=ipart ? 0: 50);
+else if(gmres==3)
+   rgmres= MPILinearGMRES(DJ,precon=PDJC,u[],Bi,veps=epss,nbiter=300,comm=comm,dimKrylov=100,verbosity=ipart ? 0: 50);
+else // algo Shwarz for demo ...
+   for(int iter=0;iter <10; ++iter)
+     {
+       real[int] b= onG .* u[];
+       b  = onG ? b : Bi ;
+       v[] = Ai^-1*b;	
+       
+       Update(v[],u[]);
+       if(vdebug) plotMPIall(Thi,u[],"u-"+iter);
+        v[] -= u[];
+       
+       real err = v[].linfty;
+       real umax = u[].max;
+       real[int] aa=[err,umax], bb(2);
+       mpiAllReduce(aa,bb,comm,mpiMAX);
+       real errg = bb[0];
+       real umaxg = bb[1];
+       
+       if(ipart==0)
+	     cout << ipart << " err = " << errg << " u. max  " << umaxg << endl;
+       if(errg< 1e-5) break;
+     }
+if(vdebug) plotMPIall(Thi,u[],"u-final");
+
+settt
+
+real errg =1,umaxg;
+{ 
+  real umax = u[].max,umaxg;
+  real[int] aa=[umax], bb(1);
+  mpiAllReduce(aa,bb,comm,mpiMAX);
+  errg=bb[0];
+  if(ipart==0)
+    cout << " umax global  = " << bb[0] << " Wtime = " << (ttt[ittt-1]-ttt[ittt-2])  << " s " <<  " " << kiter <<  endl;
+}
+
+if(sff != "")
+  {
+    ofstream ff(sff+".txt",append);
+    cout << " ++++  " ;
+    cout  << mpirank <<"/" <<  mpisize << " k=" <<  ksplit << " n= " << nloc << " " << sizeoverlaps << " it=  " << kiter  ;  
+    for (int i=1; i<ittt;++i)	
+      cout << " " << ttt[i]-ttt[i-1] << " ";
+    cout << epss << " " << Ai.nbcoef << " " << Ai.n << endl;
+    
+    /*
+      1 mpirank
+      2 mpisize 
+      3 ksplit 
+      4 nloc
+      5 sizeoverlaps
+      6 kiter
+      7 mesh & part build  
+      8 build the partion 
+      9 build mesh, transfere , and the fine mesh .. 
+      10 build the matrix,  the trans matrix, factorizatioon 
+      11 GMRES 
+    */
+    ff   << mpirank << " " << mpisize << " " << sPk << " " ;
+    ff <<  ksplit << " " << nloc << " " << sizeoverlaps << " " << kiter  ;  
+    for (int i=1; i<ittt;++i)	
+      ff << " " << ttt[i]-ttt[i-1] << " ";
+    ff << epss << " " << Ai.nbcoef << " " << Ai.n << " " << gmres << endl;
+    
+  }
diff --git a/examples++-mpi/MPIGMRES3D.edp b/examples++-mpi/MPIGMRES3D.edp
new file mode 100644
index 0000000..b4b69cb
--- /dev/null
+++ b/examples++-mpi/MPIGMRES3D.edp
@@ -0,0 +1,473 @@
+// NBPROC 10
+// ff-mpirun -np 4 MPIGMRES2D.edp -glut ffglut  -n 11 -k 1  -d 1 -ns -gmres 1
+/*
+  a first true parallele example fisrt freefem++ 
+  Ok up to 200 proc for a Poisson equation.. 
+  See the Doc for full explaiantion
+
+  F Hecht Dec. 2010. 
+  -------------------
+usage :
+ff-mpirun [mpi parameter] MPIGMRES3d.edp  [-glut ffglut]  [-n N] [-k K]  [-d D] [-ns] [-gmres [0|1|2|3]
+ argument: 
+   -glut ffglut : to see graphicaly the process
+   -n N:  set the mesh3 cube split NxNxN
+   -d D:  set debug flag D must be one for mpiplot 
+   -k K:  to refined by K all  elemnt
+   -ns: reomove script dump
+   -gmres 0   : use iterative schwarz algo.  
+          1   :  Algo GMRES on residu of schwarz algo.
+          2   :  DDM GMRES 
+          3   :  DDM GMRES with coarse grid preconditionner (Good one)  
+*/
+load "MPICG"  load "medit"  load "metis"
+include "getARGV.idp"
+include "MPIplot.idp"
+include "MPIGMRESmacro.idp"
+include "AddLayer3d.idp" 
+include  "cube.idp"
+
+
+searchMethod=1; // more safe seach algo (warning can be very expensive in case lot of ouside point) 
+assert(version >3.11);
+real[int] ttt(10);int ittt=0;
+macro settt {ttt[ittt++]=mpiWtime();}//
+
+
+verbosity=getARGV("-vv",0);
+int vdebug=getARGV("-d",1);
+int ksplit=getARGV("-k",2);
+int nloc = getARGV("-n",10);
+string sff=getARGV("-p,","");
+int gmres=getARGV("-gmres",3); 
+bool dplot=getARGV("-dp",0);
+int nC = getARGV("-N" ,max(nloc/10,4)); 
+
+if(mpirank==0 && verbosity)
+{
+  cout << "ARGV : ";
+  for(int i=0;i<ARGV.n;++i)
+    cout << ARGV[i] <<" ";
+  cout << endl;
+}
+
+
+if(mpirank==0 && verbosity)
+  cout << " vdebug: " << vdebug << " kspilt "<< ksplit << " nloc "<< nloc << " sff "<< sff <<"."<< endl;
+
+int withplot=0;
+bool withmetis=1;
+bool RAS=1; 
+string sPk="P2-3gd";     
+func Pk=P2;
+
+func bool  plotMPIall(mesh3 &Th,real[int] & u,string  cm)
+{if(vdebug) PLOTMPIALL(mesh3,Pk, Th, u,{ cmm=cm,nbiso=3,fill=0,dim=3,value=1}); return 1;}
+
+int sizeoverlaps=1; // size of overlap
+
+mpiComm comm(mpiCommWorld,0,0);// trick : make a no split mpiWorld 
+ 
+int npart=mpiSize(comm); // total number of partion
+int ipart= mpiRank(comm); // current partition number 
+
+int njpart=0; // nb of part with intersection (a jpart) with ipart without ipart
+int[int] jpart(npart); //  list of jpart ..
+if(ipart==0)  cout << " Final N=" << ksplit*nloc << " nloc =" << nloc << " split =" << ksplit <<  endl;
+int[int] l111=[1,1,1,1]; 
+settt 
+
+int[int,int] LL=[[1,1],[1,1],[1,1]];
+real[int,int] BB=[[0,1],[0,1],[0,1]];
+int[int] NN=[nloc,nloc,nloc]; 
+int[int] NNC=[nC,nC,nC]; 
+settt 
+mesh3 Thg=Cube(NN,BB,LL);
+mesh3 ThC=Cube(NNC,BB,LL);
+
+mesh3 Thi,Thin;//  with overlap, without olverlap  
+fespace Phg(Thg,P0);
+fespace Vhg(Thg,P1);
+fespace VhC(ThC,P1); // of the coarse problem.. 
+
+
+Phg  part;
+
+// build the partitioning ...  
+{    
+ int[int] nupart(Thg.nt);
+ nupart=0; 
+ if(npart>1 && ipart==0)
+   metisdual(nupart,Thg,npart); 
+   
+ broadcast(processor(0,comm),nupart);
+ for(int i=0;i<nupart.n;++i)
+    part[][i]=nupart[i];
+  
+} // build ... 
+
+
+if(withplot>1)
+  plot(part,fill=1,cmm="dual",wait=1);
+
+// overlapping partition
+
+ Phg suppi= abs(part-ipart)<0.1; 
+ Vhg unssd;                       // boolean function 1 in the subdomain 0 elswhere 
+ Thin=trunc(Thg,suppi>0,label=10); // non-overlapping mesh3, interfaces have label 10
+ int nnn = sizeoverlaps*2;// to be sure 
+ AddLayers(Thg,suppi[],nnn,unssd[]);    // see above ! suppi and unssd are modified  
+ unssd[] *= nnn;  //  to put value nnn a 0  
+ real nnn0 = nnn - sizeoverlaps +  0.001   ;
+ Thi=trunc(Thg,unssd>nnn0 ,label=10); // overlapping mesh3, interfaces have label 10
+ 
+ settt 
+
+ fespace Vhi(Thi,P1);
+ int npij=npart;
+ Vhi[int] pij(npij);// local partition of unit + pii 
+ Vhi pii;  
+ 
+ real nnn1=  + 0.001  ;
+ { /*
+   construction of the partition of the unit,
+    let phi_i P1 FE function 1 on Thin and zero ouside of Thi and positive
+    the partition is build with  
+  $$  p_i = phi_i/ \sum phi_i 
+    
+    to build the partition of one domain i
+    we nned to find all j such that supp(phi_j) \cap supp(phi_j) is not empty
+    <=> int phi_j
+ */
+ //   build a local mesh3 of thii such that all compuation of the unit partition are
+ //   exact in thii
+ mesh3 Thii=trunc(Thg,unssd>nnn1 ,label=10); // overlapping mesh3, interfaces have label 10
+
+
+ {  
+   // find all j  mes (supp(p_j) \cap supp(p_i)) >0  
+   // compute all phi_j on Thii
+   //  remark supp p_i include in Thi 
+   //  
+   fespace Phii(Thii,P0);
+   fespace Vhii(Thii,P1);
+   Vhi sumphi=0;
+   jpart=0;
+   njpart=0;
+   int nlayer=RAS?1:sizeoverlaps;
+   if(ipart==0) 
+     cout <<" nlayer=" << nlayer << endl;
+   pii= max(unssd-nnn+nlayer,0.)/nlayer;
+   if(dplot) plot(pii,wait=1,cmm=" 0000");
+   sumphi[] +=  pii[];
+   if(dplot) plot(sumphi,wait=1,cmm=" summ 0000");
+   Vhii phii=0;
+   real epsmes=1e-10*Thii.mesure;
+   for (int i=0;i<npart;++i)
+     if(i != ipart ) 
+       { 
+	    Phii suppii=abs(i-part)<0.2; 
+	    if(suppii[].max > 0.5) 
+	    {
+	     AddLayers(Thii,suppii[],nlayer,phii[]);
+	     assert(phii[].min >=0);
+	     real interij = int3d(Thi)(  phii); 
+	     if(interij>epsmes) 
+	       {  
+		     pij[njpart]=abs(phii);	 
+		     if(vdebug>2) cout << " ***** " << int3d(Thi)(real(pij[njpart])<0) << " " <<pij[njpart][].min << " " << phii[].min << endl;
+		     assert(int3d(Thi)(real(pij[njpart])<0) ==0);
+		     if(dplot)  plot(pij[njpart],wait=1,cmm=" j = "+ i + " " + njpart);
+		     sumphi[] += pij[njpart][]; 
+		     if(dplot)  plot(sumphi,wait=1,cmm=" sum j = "+ i + " " + njpart);
+		     jpart[njpart++]=i;
+	       }}}
+   
+   if(dplot) plot(sumphi,wait=1,dim=3,cmm="sum ",fill=1 );
+   pii[]=pii[] ./ sumphi[];
+   for (int j=0;j<njpart;++j)
+     pij[j][] = pij[j][] ./ sumphi[];
+   jpart.resize(njpart);	
+   for (int j=0;j<njpart;++j)
+     assert(pij[j][].max<=1);
+   {
+     cout << ipart << " number of jpart " << njpart << " : ";
+     for (int j=0;j<njpart;++j)
+       cout << jpart[j] << " ";
+  	cout << endl;
+   }
+   sumphi[]=pii[];
+   for (int j=0;j<njpart;++j)
+     sumphi[]+= pij[j][];
+   if(vdebug)  
+     cout << " sum min " <<sumphi[].min << " " << sumphi[].max << endl;
+   assert(sumphi[].min> 1.-1e-6 && sumphi[].max< 1.+1e-6);  
+   //  verification 
+ }}// (Thii is remove here) 
+  // end of the construction of the local partition of the unity ...
+  // on Thi ...  
+  // -----------------------------------------------------------------
+if(ipart==0) cout << " *** end build partition " << endl;
+
+//  computation of  number of intersection ..
+// ------------------------------------------
+
+// here  pii and the pij is the locate partition of the unite on 
+// Thi ( mesh3 with overlap )....
+//Thi=splitmesh(Thi,2);
+if(dplot ) 
+  { plot(Thi,wait=1); 
+    for(int j=0;j<njpart;++j)
+      plot(pij[j],cmm=" j="+j ,wait=1); } 
+      
+//  Partition of the unity on Thi ..
+// computation of message.
+// all j> we have to recive 
+// data on intersection of the support of pij[0] and pij[j]
+settt 
+
+ plotMPIall(Thi,pii[],"pi_i");
+
+mesh3[int] aThij(njpart); 
+matrix Pii;  
+matrix[int] sMj(njpart); // M of send to j
+matrix[int] rMj(njpart); // M to recv from j
+fespace Whi(Thi,Pk);
+mesh3 Thij=Thi;
+fespace Whij(Thij,Pk);// 
+
+// construction of the mesh3 intersect i,j part 
+for(int jp=0;jp<njpart;++jp)
+  aThij[jp]  = trunc(Thi,pij[jp]>1e-6,label=10); // mesh3 of the supp of pij
+
+for(int jp=0;jp<njpart;++jp)
+  aThij[jp]  = trunc(aThij[jp],1,split=ksplit);
+
+Thi =   trunc(Thi,1,split=ksplit);
+
+settt 
+
+if(ipart==0) cout << " *** end build mesh3  intersection  " << endl;
+// construction of transfert  matrix
+{
+  Whi wpii=pii;
+  Pii = wpii[];
+  for(int jp=0;jp<njpart;++jp)
+    {
+      int j=jpart[jp];
+      Thij = aThij[jp];
+      matrix I = interpolate(Whij,Whi); // Whji <- Whi
+      sMj[jp] = I*Pii;  // Whi -> s Whij  
+      rMj[jp] = interpolate(Whij,Whi,t=1);   // Whji -> Whi
+      if(vdebug>10) {
+      {Whi uuu=1;Whij vvv=-1; vvv[]+=I*uuu[]; cout << jp << " %%% " << vvv[].linfty << endl; assert(vvv[].linfty < 1e-6);}
+      {Whi uuu=1;Whij vvv=-1; vvv[]+=rMj[jp]'*uuu[]; cout << jp << " ### " << vvv[].linfty << endl; assert(vvv[].linfty < 1e-6);}}
+    }}
+if(ipart==0) cout << " *** end build transfert matrix " << endl;
+// alloc array of send and recv data ..
+
+InitU(njpart,Whij,Thij,aThij,Usend)  // initU(n,Vh,Th,aTh,U)
+InitU(njpart,Whij,Thij,aThij,Vrecv) // ...
+if(ipart==0) cout << " *** end init  data for send/revc  " << endl;
+
+Whi ui,vi; 
+
+func bool Update(real[int] &ui, real[int] &vi)
+{
+  for(int j=0;j<njpart;++j)
+    Usend[j][]=sMj[j]*ui; 
+   SendRecvUV(comm,jpart,Usend,Vrecv)
+     vi = Pii*ui;
+   for(int j=0;j<njpart;++j)
+     vi += rMj[j]*Vrecv[j][]; 
+   return true;
+}
+
+
+// the definition of the Problem ....
+func G=1.; // ok 
+func F=1.; // ok 
+macro grad(u) [dx(u),dy(u),dz(u)] // 
+varf vBC(U,V)=  on(1,U=G); 
+varf vPb(U,V)= int3d(Thi)(grad(U)'*grad(V)) + int3d(Thi)(F*V) + on(10,U=0)+on(1,U=G) ; //');// for emacs
+varf vPbC(U,V)= int3d(ThC)(grad(U)'*grad(V))  +on(1,U=0) ; //');// for emacs
+varf vPbon(U,V)=on(10,U=1)+on(1,U=1);
+varf vPbon10only(U,V)=on(10,U=1)+on(1,U=0); 
+
+//----  
+
+matrix Ai = vPb(Whi,Whi,solver=sparsesolver);
+matrix AC,Rci,Pci;// 
+
+
+if(mpiRank(comm)==0)
+  AC = vPbC(VhC,VhC,solver=sparsesolver);
+
+Pci=   interpolate(Whi,VhC);
+Rci =  Pci'*Pii; 
+
+real[int] onG10 = vPbon10only(0,Whi);
+real[int] onG = vPbon(0,Whi);
+real[int] Bi=vPb(0,Whi);
+
+
+
+
+
+int kiter=-1;
+
+
+func bool  CoarseSolve(real[int]& V,real[int]& U,mpiComm& comm)
+{
+   //  solving the coarse probleme 
+   real[int] Uc(Rci.n),Bc(Uc.n); 
+   Uc= Rci*U;
+   mpiReduce(Uc,Bc,processor(0,comm),mpiSUM);
+   if(mpiRank(comm)==0) 
+      Uc = AC^-1*Bc;
+    broadcast(processor(0,comm),Uc);
+   V = Pci*Uc;
+}//EOF ...
+func real[int] DJ(real[int]& U)
+{ 
+  ++kiter;
+  real[int] V(U.n); 
+   V =  Ai*U;
+  V = onG10 ? 0.: V;  // remove internal boundary  
+  return V; 
+}
+
+func real[int] PDJ(real[int]& U) // C1
+{ 
+  real[int] V(U.n); 
+  
+  real[int] b= onG10 ? 0. :  U; 
+  V =  Ai^-1*b;	
+  Update(V,U);
+  return U; 
+}
+
+func real[int] PDJC(real[int]& U) // 
+{ // Precon  C1= Precon //, C2  precon Coarse
+// Idea : F. Nataf. 
+  //  0 ~  (I C1A)(I-C2A) => I ~  - C1AC2A +C1A +C2A 
+  //  New Prec P= C1+C2 - C1AC2   = C1(I- A C2) +C2
+  // (  C1(I- A C2) +C2 ) Uo 
+  //   V =  - C2*Uo
+  // .... 
+  real[int] V(U.n); 
+  CoarseSolve(V,U,comm);
+  V = -V; //  -C2*Uo 
+  U  += Ai*V; // U =  (I-A C2) Uo 
+  real[int] b= onG10 ? 0. :  U; 
+  U =  Ai^-1*b;	//  ( C1( I -A C2) Uo 
+  V = U -V; //  
+  Update(V,U);
+  return U; 
+}
+
+
+ func real[int] DJ0(real[int]& U)
+{ 
+  ++kiter;
+  real[int] V(U.n); 
+  real[int] b= onG .* U;
+  b  = onG ? b : Bi ;  
+  V = Ai^-1*b;	
+  Update(V,U);
+  V -= U;
+   return V; 
+}
+
+
+Whi u=0,v;
+{ // verification.....
+  Whi u=1,v;
+  Update(u[],v[]);
+  u[]-=v[];
+  assert( u[].linfty<1e-6); }
+  
+
+
+settt
+u[]=vBC(0,Whi,tgv=1); // set u with tge BC value ...
+
+real epss=1e-6;
+int rgmres=0;
+if(gmres==1)
+  {
+   rgmres=MPIAffineGMRES(DJ0,u[],veps=epss,nbiter=300,comm=comm,dimKrylov=100,verbosity=ipart ? 0: 50);
+   real[int] b= onG .* u[];
+   b  = onG ? b : Bi ;
+   v[] = Ai^-1*b;	
+   Update(v[],u[]);
+  }
+else if(gmres==2)
+  rgmres= MPILinearGMRES(DJ,precon=PDJ,u[],Bi,veps=epss,nbiter=300,comm=comm,dimKrylov=100,verbosity=ipart ? 0: 50);
+else if(gmres==3)
+   rgmres= MPILinearGMRES(DJ,precon=PDJC,u[],Bi,veps=epss,nbiter=300,comm=comm,dimKrylov=100,verbosity=ipart ? 0: 50);
+else // algo Shwarz for demo ...
+   for(int iter=0;iter <10; ++iter)
+     {
+       real[int] b= onG .* u[];
+       b  = onG ? b : Bi ;
+       v[] = Ai^-1*b;	
+       
+       Update(v[],u[]);
+       if(vdebug) plotMPIall(Thi,u[],"u-"+iter);
+        v[] -= u[];
+       
+       real err = v[].linfty;
+       real umax = u[].max;
+       real[int] aa=[err,umax], bb(2);
+       mpiAllReduce(aa,bb,comm,mpiMAX);
+       real errg = bb[0];
+       real umaxg = bb[1];
+       
+       if(ipart==0)
+	     cout << ipart << " err = " << errg << " u. max  " << umaxg << endl;
+       if(errg< 1e-5) break;
+     }
+if(vdebug) plotMPIall(Thi,u[],"u-final");
+
+settt
+
+real errg =1,umaxg;
+{ 
+  real umax = u[].max,umaxg;
+  real[int] aa=[umax], bb(1);
+  mpiAllReduce(aa,bb,comm,mpiMAX);
+  errg=bb[0];
+  if(ipart==0)
+    cout << " umax global  = " << bb[0] << " Wtime = " << (ttt[ittt-1]-ttt[ittt-2])  << " s " <<  " " << kiter <<  endl;
+}
+
+if(sff != "")
+  {
+    ofstream ff(sff+".txt",append);
+    cout << " ++++  " ;
+    cout  << mpirank <<"/" <<  mpisize << " k=" <<  ksplit << " n= " << nloc << " " << sizeoverlaps << " it=  " << kiter  ;  
+    for (int i=1; i<ittt;++i)	
+      cout << " " << ttt[i]-ttt[i-1] << " ";
+    cout << epss << " " << Ai.nbcoef << " " << Ai.n << endl;
+    
+    /*
+      1 mpirank
+      2 mpisize 
+      3 ksplit 
+      4 nloc
+      5 sizeoverlaps
+      6 kiter
+      7 mesh3 & part build  
+      8 build the partion 
+      9 build mesh3, transfere , and the fine mesh3 .. 
+      10 build the matrix,  the trans matrix, factorizatioon 
+      11 GMRES 
+    */
+    ff   << mpirank << " " << mpisize << " " << sPk << " " ;
+    ff <<  ksplit << " " << nloc << " " << sizeoverlaps << " " << kiter  ;  
+    for (int i=1; i<ittt;++i)	
+      ff << " " << ttt[i]-ttt[i-1] << " ";
+    ff << epss << " " << Ai.nbcoef << " " << Ai.n << " " << gmres << endl;
+    
+  }
diff --git a/examples++-mpi/MPIGMRESmacro.idp b/examples++-mpi/MPIGMRESmacro.idp
new file mode 100644
index 0000000..d063b0f
--- /dev/null
+++ b/examples++-mpi/MPIGMRESmacro.idp
@@ -0,0 +1,109 @@
+// MPIGMRSmacro.idp  file..  version 0. 
+// include in MPIGMRES.edp file ..
+// Frederic Hecht 2010 
+// LGPL licence 
+// Author Frederic.Hecht at upmc.fr
+// ------------------------------- 
+
+//  macro to def // send-recv message 
+// -----------------------------------
+
+
+func real  maxM(matrix & A)
+  {
+  	int[int] I(1),J(1);
+  	real[int] C(1);
+  	[I,J,C] =A;
+  	return C.max ;
+  }
+  
+  
+macro  InitU(n,Vh,Th,aTh,U)
+Vh[int] U(n);
+for(int j=0;j<n;++j)
+  {  
+  	 Th=aTh[j];
+  	 U[j]=0;
+  }
+//EOM
+
+
+macro   ISendRecvAny(comm,jpart,Si,Ri)
+{ /* sorry no Irecv of complex objet ...*/
+  int n= jpart.n,nn=n+n;
+  if(vdebug) cout << mpirank << " --ISendRecvAny " << n << endl;
+  mpiRequest[int] rq(nn);
+  
+  for (int j=0;j<n;++j)
+    Irecv(processor(jpart[j],comm,rq[j]),Ri[j]);
+  if(vdebug) cout << mpirank << " ++ISendRecvAny " << n << endl;
+  
+  for (int j=0;j<n;++j)
+    Isend(processor(jpart[j],comm,rq[n+j]),Si[j]);
+for (int j=0;j<nn;++j)
+  {
+  int k= mpiWaitAny(rq);
+  if(vdebug)
+    cout << " ++ISendRecvAny wait: get " << k << endl;
+  }
+}
+//EOM
+
+
+macro   SendRecvAny(comm,jpart,Si,Ri)
+{  verbosity=200;
+ 	int n= jpart.n;
+ 	for (int j=0;j<n;++j)
+       processor(comm,jpart[j]) << Si[j];
+    cout << " ** wait revc " << endl;
+ 	for (int j=0;j<n;++j)
+       processor(comm,jpart[j]) >> Ri[j];
+}
+// EOM 
+
+
+macro CheckUV(comm,jpart,Si,Ri)
+{
+	    int ipart=mpiRank(comm);
+	 	int n= jpart.n;
+  		int[int] rn(n),sn(n),in(n);
+ 		for (int j=0;j<n;++j) 
+ 		  { sn[j]= Si[j][].n;		  	  
+ 		   processor(jpart[j],comm) << sn[j];
+ 		   processor(jpart[j],comm) << ipart;
+ 		  }
+ 		 for (int j=0;j<n;++j) 
+ 		   processor(jpart[j],comm) >> rn[j];
+ 		 for (int j=0;j<n;++j) 
+ 		   processor(jpart[j],comm) >> in[j];
+
+ 		 int err=0;
+ 		 for (int j=0;j<n;++j) 
+ 		  { 
+ 		   int rj=Ri[j][].n;
+ 		   err += rj != rn[j];
+ 		   cout << rj << " s ========= r " << rn[j] << "      " << ipart << " <->  " << in[j] << " " << err << endl;  
+ 		   
+ 		  }
+ 	     assert(err==0);
+}//EOM
+
+
+macro   SendRecvUV(comm,jpart,Si,Ri)
+{
+ 	int n= jpart.n;
+	mpiRequest[int] rq(n);
+    for (int j=0;j<n;++j)
+       Irecv(processor(jpart[j],comm,rq[j]), Ri[j][]);
+       
+ 	for (int j=0;j<n;++j)
+       processor(jpart[j],comm) << Si[j][];
+  /* 	for (int j=0;j<n;++j)
+       processor(jpart[j],comm) >> Ri[j][];*/
+ 
+    for (int j=0;j<n;++j)
+	   int k= mpiWaitAny(rq);
+}
+// EOF 
+
+
diff --git a/examples++-mpi/MPIplot.idp b/examples++-mpi/MPIplot.idp
new file mode 100644
index 0000000..28af128
--- /dev/null
+++ b/examples++-mpi/MPIplot.idp
@@ -0,0 +1,36 @@
+macro PLOTMPIALL(mesh,Pk, Th, u, plotparm)
+{ int ver=verbosity;
+  verbosity=0;
+  if(NoGraphicWindow==0)
+  { 
+  if(mpirank==0)
+    {
+      mesh Thi=Th;
+      mesh[int] ath(mpisize);
+      fespace Xh(Thi,Pk);
+      Xh[int] uh(mpisize);
+      uh[0][]=u;
+      ath[0]=Th;
+      mpiRequest[int] rq(mpisize);
+      for(int i= 1; i <mpisize;++i)
+	   Irecv(processor(i,rq[i]),ath[i]);
+      for (int i=1;i<mpisize;++i)
+       	int k= mpiWaitAny(rq);
+      for (int i=1;i<mpisize;++i)
+	   { Thi=ath[i];
+	     Irecv(processor(i,rq[i]),uh[i][]);}
+      for (int i=1;i<mpisize;++i)
+       	int k= mpiWaitAny(rq); 
+      plot(uh,plotparm);
+    }
+  else
+    {
+      processor(0)<<Th;
+      processor(0)<<u;
+    }
+  mpiBarrier(mpiCommWorld);
+  }
+  verbosity=ver;
+  return true;
+}
+//EOM ...
diff --git a/examples++-mpi/MUMPS-dist.edp b/examples++-mpi/MUMPS-dist.edp
new file mode 100755
index 0000000..c36856d
--- /dev/null
+++ b/examples++-mpi/MUMPS-dist.edp
@@ -0,0 +1,40 @@
+load "MUMPS"
+load "symmetrizeCSR"
+int[int] l = [1, 1, 2, 2];
+mesh Th = square(150, 150, label = l);
+if(mpirank != 0) // no need to store the matrix on ranks other than 0
+    Th = square(1, 1, label = l);
+fespace Vh(Th, P2);
+Vh u, v;
+varf lap(u,v) = int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v)) + int2d(Th)(v) + on(1, u = 1);
+real[int] b = lap(0, Vh);
+matrix A = lap(Vh, Vh);
+matrix B = A;
+symmetrizeCSR(B);
+verbosity = 2;
+// If you want, you can pass an array of integer (int[int] t)
+// for specifying the ordering you want to use
+// 1 : AMD
+// 3 : AMF
+// 4 : SCOTCH
+// 5 : PORD
+// 6 : METIS
+// 7 : QAMD
+// 10 : PT-SCOTCH
+// 11 : ParMETIS
+//
+// You can also set on which MPI rank the matrix is defined
+// as the current interface only supports centralized matrices
+//
+// Example :
+// If one wants to use SCOTCH with a matrix stored on mpirank == 1
+int[int] t=[0,-1];// ; t(0) = 4; t(1) = 1;
+// set(A, solver = sparsesolver, lparams = t);
+set(A, solver = sparsesolver);
+set(B, solver = sparsesolver);
+verbosity = 0;
+Vh x;
+x[] = A^-1 * b;
+plot(Th, x, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver unsymmetric", value = 1);
+x[] = B^-1 * b;
+plot(Th, x, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver symmetric", value = 1);
diff --git a/examples++-mpi/MUMPS-old.edp b/examples++-mpi/MUMPS-old.edp
new file mode 100755
index 0000000..d3ce0b6
--- /dev/null
+++ b/examples++-mpi/MUMPS-old.edp
@@ -0,0 +1,44 @@
+load "MUMPS-old"
+load "symmetrizeCSR"
+int[int] l = [1, 1, 2, 2];
+mesh Th = square(150, 150, label = l);
+if(mpirank != 0) // no need to store the matrix on ranks other than 0
+    Th = square(1, 1, label = l);
+fespace Vh(Th, P2);
+Vh u, v;
+varf lap(u,v) = int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v)) + int2d(Th)(v) + on(1, u = 1);
+real[int] b = lap(0, Vh);
+matrix A = lap(Vh, Vh);
+matrix B = A;
+symmetrizeCSR(B);
+verbosity = 2;
+// If you want, you can pass an array of integer (int[int] t)
+// for specifying the ordering you want to use
+// 1 : AMD
+// 3 : AMF
+// 4 : SCOTCH
+// 5 : PORD
+// 6 : METIS
+// 7 : QAMD
+// 10 : PT-SCOTCH
+// 11 : ParMETIS
+//
+// You can also set on which MPI rank the matrix is defined
+// as the current interface only supports centralized matrices
+//
+// Example :
+// If one wants to use SCOTCH with a matrix stored on mpirank == 1
+// int[int] t(2); t(0) = 4; t(1) = 1;
+// set(A, solver = sparsesolver, lparams = t);
+set(A, solver = sparsesolver);
+set(B, solver = sparsesolver);
+verbosity = 0;
+Vh x;
+x[] = A^-1 * b;
+if(mpirank==0) cout << " A :  x " << x[].l1 << " " << x[].linfty << endl; 
+if(mpirank==0)
+plot(Th, x, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver unsymmetric", value = 1);
+x[] = B^-1 * b;
+if(mpirank==0) cout << " B :  x " << x[].l1 << " " << x[].linfty << endl; 
+if(mpirank==0)
+plot(Th, x, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver symmetric", value = 1);
diff --git a/examples++-mpi/MUMPS.cpp b/examples++-mpi/MUMPS.cpp
new file mode 100644
index 0000000..1db1efb
--- /dev/null
+++ b/examples++-mpi/MUMPS.cpp
@@ -0,0 +1,318 @@
+// SUMMARY  :   simpler MUMPS interface
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : P. Jolivet 
+// E-MAIL   : Pierre Jolivet <pierre.jolivet at ljll.math.upmc.fr>
+//
+//ff-c++-LIBRARY-dep:  mumps parmetis ptscotch  scalapack blas  mpifc  fc mpi  pthread 
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+#include <mpi.h>
+#include "rgraph.hpp"
+#include "AFunction.hpp"
+
+// FFCS - 23/4/13 - instanciate some global symbols which are not found by default in MS MPI Fortran libraries
+#ifdef WIN32
+__declspec(dllexport) int toto;
+MPI_Fint* _imp__MPI_F_STATUS_IGNORE;
+MPI_Fint* _imp__MPI_F_STATUSES_IGNORE;
+#endif
+
+#include "MatriceCreuse.hpp"
+
+#include "dmatrix.hpp"
+#include <dmumps_c.h>
+#include <zmumps_c.h>
+#define JOB_INIT -1
+#define JOB_END -2
+#define USE_COMM_WORLD -987654
+#define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */
+#define INFOG(I) infog[(I)-1] /* macro s.t. indices match documentation */
+#define INFO(I) info[(I)-1]   /* macro s.t. indices match documentation */
+
+template<typename RR> struct MUMPS_STRUC_TRAIT {typedef void MUMPS;  typedef void R; };
+template<> struct MUMPS_STRUC_TRAIT<double>  {typedef DMUMPS_STRUC_C MUMPS; typedef double R;};
+template<> struct MUMPS_STRUC_TRAIT<Complex>  {typedef ZMUMPS_STRUC_C MUMPS; typedef ZMUMPS_COMPLEX R;};
+void mumps_c(DMUMPS_STRUC_C *id) { dmumps_c(id);}  
+void mumps_c(ZMUMPS_STRUC_C *id) { zmumps_c(id);}  
+
+template<class T> struct MPI_TYPE {static const MPI_Datatype  TYPE(){return MPI_BYTE;}};;
+template<> struct MPI_TYPE<long>      {static const MPI_Datatype  TYPE(){return MPI_LONG;}};
+template<> struct MPI_TYPE<int>      {static const MPI_Datatype TYPE(){return MPI_INT;}};
+template<> struct MPI_TYPE<double>    {static const MPI_Datatype TYPE(){return MPI_DOUBLE;}};
+template<> struct MPI_TYPE<char>    {static const MPI_Datatype TYPE(){return MPI_BYTE;}};
+template<> struct MPI_TYPE<Complex>    {static const MPI_Datatype TYPE(){return MPI_DOUBLE_COMPLEX;}};
+
+
+static std::string analysis[] = {"AMD", "", "AMF", "SCOTCH", "PORD", "METIS", "QAMD", "automatic sequential", "automatic parallel", "PT-SCOTCH", "ParMetis"};
+
+template<class R>
+class SolverMumps : public MatriceMorse<R>::VirtualSolver {
+
+
+
+    private:
+         mutable typename MUMPS_STRUC_TRAIT<R>::MUMPS * _id; 
+  //mutable DMUMPS_STRUC_C* _id;
+        mutable unsigned char   _strategy;
+    bool distributed;
+    MPI_Comm comm;
+    int mpirank;
+    public:
+        typedef typename  MUMPS_STRUC_TRAIT<R>::R MR; 
+  SolverMumps(const MatriceMorse<R> &A, KN<long> &param_int, KN<double> &param_R, MPI_Comm* pcomm,int strategy=3,int matrank=0)
+    : comm( pcomm ? *pcomm :MPI_COMM_WORLD ),
+      distributed(matrank<0)
+  {
+    
+    MPI_Comm_rank(comm, &mpirank);
+    int master = mpirank==matrank;  
+    _id = new typename MUMPS_STRUC_TRAIT<R>::MUMPS ;
+    _id->job = JOB_INIT;
+    _id->par = 1;
+    
+    _id->comm_fortran = MPI_Comm_c2f(comm);
+    _id->sym = A.symetrique;
+    _strategy = strategy;
+    mumps_c(_id);
+    int* I = 0;
+    int* J = 0;
+    R * C = 0;
+    long nnz=0;
+    if( distributed || (mpirank == matrank) )
+        {
+            	
+	if(_id->sym == 0) 
+	  {
+	    nnz = A.nbcoef;
+	    I = new int[A.nbcoef];
+	    CSR2COO<'C', 'U'>(A.n, A.lg, I);
+	    C =  A.a;
+	    J = A.cl;
+	    for(unsigned int i = 0; i < A.nbcoef; ++i)
+	      ++J[i];
+	  }
+	else 
+	  {
+	    if(A.symetrique) 
+	      {
+		nnz = A.nbcoef;
+		I = new int[A.nbcoef];
+		J = new int[A.nbcoef];
+		C = new R[A.nbcoef];
+		for(unsigned int i = 0; i < A.n; ++i)
+		  C[i] = A.a[A.lg[i + 1] - 1];
+		std::generate(I, I + A.n, step(0, 1));
+		CSR2COO<'C', 'L'>(A.n, A.lg, I + A.n);
+		std::copy(I, I + A.n, J);
+		for(unsigned int i = 1; i < A.n; ++i) {
+		  for(unsigned int j = A.lg[i]; j < A.lg[i + 1] - 1; ++j) {
+		    J[A.n + j - i] = A.cl[j] + 1;
+		    C[A.n + j - i] = A.a[j];
+		  }
+		}
+	      }
+	    else 
+	      {
+		nnz = A.n + (A.nbcoef - A.n) / 2;
+		I = new int[A.n + (A.nbcoef - A.n) / 2];
+		J = new int[A.n + (A.nbcoef - A.n) / 2];
+		C = new R[A.n + (A.nbcoef - A.n) / 2];
+		trimCSR<false, 'F',R>(A.n, I + A.n, A.lg, J + A.n, A.cl, C + A.n, A.a);
+		for(unsigned int i = 0; i < A.n - 1; ++i)
+		  C[i] = A.a[A.lg[i + 1] - (I[i + 1 + A.n] - I[i + A.n]) - 1];
+		C[A.n - 1] = A.a[A.nbcoef - 1];
+		std::generate(I, I + A.n, step(0, 1));
+		CSR2COO<'F', 'U'>(A.n - 1, I + A.n, I + A.n);
+		std::copy(I, I + A.n, J);
+	      }
+	  }
+        _id->n = A.n;
+        if(!distributed)
+	  {
+	    _id->nz=nnz;
+	    _id->a =reinterpret_cast<MR *>( C);
+	    _id->irn = I;
+	    _id->jcn = J;
+	  }
+        else
+	  {
+	    
+            _id->nz_loc=nnz;
+            _id->a_loc =reinterpret_cast<MR *>( C);
+            _id->irn_loc = I;
+            _id->jcn_loc = J;
+	  }
+	
+	}
+    else 
+      { // no matrix ...
+	_id->nz=0;
+	_id->a =0; 
+	_id->irn = 0;;
+	_id->jcn = 0;
+      }
+    _id->nrhs = 1;
+    _id->ICNTL(1) = 0;
+    _id->ICNTL(2) = 0;
+    _id->ICNTL(3) = verbosity > 1 ? 6 : 0;
+    _id->ICNTL(4) = 0; // verbose level
+    _id->ICNTL(5) = 0;                                                          // assembled format
+    if(_strategy > 0 && _strategy < 9 && _strategy != 2) 
+      {
+	_id->ICNTL(28) = 1;             // 1: sequential analysis
+	_id->ICNTL(7)  = _strategy - 1; //     0: AMD
+      }     
+    //     1:
+    //     2: AMF
+    //     3: SCOTCH
+    //     4: PORD
+    //     5: METIS
+    //     6: QAMD
+    //     7: automatic
+    else
+      {
+	_id->ICNTL(28) = 1;
+	_id->ICNTL(7)  = 7;
+      }
+    if(_strategy > 8 && _strategy < 12) 
+      {
+	_id->ICNTL(28) = 2;              // 2: parallel analysis
+	_id->ICNTL(29) = _strategy - 9;  //     0: automatic
+      }                                   //     1: PT-STOCH
+    //     2: ParMetis
+    _id->ICNTL(9)  = 1;
+    _id->ICNTL(11) = 0;                 // verbose level
+    _id->ICNTL(18) = distributed ? 3: 0;        // centralized matrix input if !distributed
+    _id->ICNTL(20) = 0;                 // dense RHS
+    _id->ICNTL(14) = 30;                // percentage increase in the estimated working space
+    _id->job = 4;
+    mumps_c(_id);
+    if(_id->INFOG(1) != 0)
+      std::cout << "BUG MUMPS, INFOG(1) = " << _id->INFOG(1) << " distributed: " << distributed << " master " << matrank << std::endl;
+    if(I) {
+      if(_id->sym == 0) {
+	for(unsigned int i = 0; i < A.nbcoef; ++i)
+	  --J[i];
+      }
+      else {
+	delete [] C;
+	delete [] J;
+      }
+      delete [] I;
+    }
+  };
+  
+  void Solver(const MatriceMorse<R> &A, KN_<R> &x, const KN_<R> &b) const
+    {
+     _id->ICNTL(20) = 0; // dense RHS
+     _id->ICNTL(21) = 0; // centralized dense solution 
+     if(distributed)
+     {
+       MPI_Reduce( (void *) (R*) b,(void *) (R*) x  , x.N() , MPI_TYPE<R>::TYPE(),MPI_SUM,0,comm);
+     }
+     else if(mpirank==0)  x = b;
+    _id->ICNTL(3) = verbosity > 1 ? 6 : 0;
+    
+    _id->rhs = reinterpret_cast<MR*>((R*) x);
+    _id->job = 3;
+    mumps_c(_id);
+   if(distributed)
+        {
+          MPI_Bcast(reinterpret_cast<void*> ( (R*) x), x.N(), MPI_TYPE<R>::TYPE(), 0,comm);
+        }
+    
+  };
+  
+  ~SolverMumps() {
+    _id->job = JOB_END;
+    mumps_c(_id);
+    if(_id)
+      delete _id;
+  };
+};
+
+
+template<class  R>
+typename MatriceMorse<R>::VirtualSolver* buildSolver(DCL_ARG_SPARSE_SOLVER(R, A)) 
+{// gestion de la star
+ 
+  MPI_Comm cw = MPI_COMM_WORLD, * pcw= (MPI_Comm*) ds.commworld;
+  if(!pcw) pcw = & cw;
+  int mpirank ;
+  MPI_Comm_rank(*pcw, &mpirank);
+  int strategy = ds.strategy,matrank=0;
+  if(Data_Sparse_Solver_version()>0 ) matrank=ds.master;
+  if( !strategy && ds.lparams.N() > 0) strategy = ds.lparams[0]; 
+  if(ds.lparams.N()>1) matrank = ds.lparams[1];// <0 => distri mat ..
+  if( ! strategy) strategy=3;
+  int mat = mpirank == matrank || matrank < 0; 
+  if(A)
+    return new SolverMumps<R>(*A, ds.lparams, ds.dparams, pcw,strategy,matrank);
+  else 
+    ffassert(0); 
+  return new SolverMumps<R>(*A, ds.lparams, ds.dparams, pcw,strategy,matrank);
+}
+
+//  the 2 default sparse solver double and complex
+
+
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+DefSparseSolverSym<double>::SparseMatSolver SparseMatSolverSym_R ; ;
+DefSparseSolverSym<Complex>::SparseMatSolver SparseMatSolverSym_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetMUMPS()
+{
+    if(verbosity>1)
+      cout << " SetDefault sparse solver to MUMPS" << endl;
+    DefSparseSolver<double>::solver  = buildSolver<double>;
+    DefSparseSolver<Complex>::solver = buildSolver<Complex>;
+    DefSparseSolverSym<double>::solver  = buildSolver<double>;
+    DefSparseSolverSym<Complex>::solver = buildSolver<Complex>; 
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return  true;
+}
+
+
+void initMUMPS()
+{    
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  SparseMatSolverSym_R= DefSparseSolverSym<double>::solver;
+  SparseMatSolverSym_C= DefSparseSolverSym<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: MUMPS:  defaultsolver defaultsolverMUMPS_" << endl;
+  DefSparseSolver<double>::solver  = buildSolver;
+  DefSparseSolver<Complex>::solver = buildSolver;
+  DefSparseSolverSym<double>::solver  = buildSolver;
+  DefSparseSolverSym<Complex>::solver = buildSolver; 
+  TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+  if(! Global.Find("defaulttoMUMPS").NotNull() )
+    Global.Add("defaulttoMUMPS","(",new OneOperator0<bool>(SetMUMPS));  
+}
+
+
+LOADFUNC(initMUMPS);
diff --git a/examples++-mpi/MUMPS.edp b/examples++-mpi/MUMPS.edp
new file mode 100755
index 0000000..e180384
--- /dev/null
+++ b/examples++-mpi/MUMPS.edp
@@ -0,0 +1,60 @@
+load "MUMPS"
+load "symmetrizeCSR"
+int[int] l = [1, 1, 2, 2];
+mesh Th = square(150, 150, label = l);
+int master = 0; //  no choose see MUMPS doc sect 4.3 
+if(mpirank != master) // no need to store the matrix on ranks other than 0
+    Th = square(1, 1, label = l);
+fespace Vh(Th, P2);
+
+varf lap(u,v) = int2d(Th)(dx(u)*dx(v) + dy(u)*dy(v)) + int2d(Th)(v) + on(1, u = 1);
+real[int] b = lap(0, Vh);
+matrix A,B;
+//if( mpirank==master) // => trap pb of size  in  A^-1 * b;
+{ // def only on master .. 
+	A = lap(Vh, Vh); B = A;
+	symmetrizeCSR(B);
+} 
+verbosity = 2;
+// If you want, you can pass an array of integer (int[int] t)
+// for specifying the ordering you want to use
+// 1 : AMD
+// 3 : AMF
+// 4 : SCOTCH
+// 5 : PORD
+// 6 : METIS
+// 7 : QAMD
+// 10 : PT-SCOTCH
+// 11 : ParMETIS
+//
+// You can also set on which MPI rank the matrix is defined
+// as the current interface only supports centralized matrices
+//
+// Example :
+// If one wants to use SCOTCH with a matrix stored on mpirank == 0
+// int[int] t(2); t(0) = 4; t(1) = 1;
+// set(A, solver = sparsesolver, lparams = t);
+set(A, solver = sparsesolver,master=master);
+set(B, solver = sparsesolver,master=master);
+verbosity = 0;
+Vh u;
+u[] = A^-1 * b;
+if(mpirank==master) cout << " A :  u " << u[].l1 << " " << u[].linfty << endl; 
+if(mpirank==0-master)
+plot(Th, u, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver unsymmetric", value = 1);
+u[] = B^-1 * b;
+if(mpirank==master) cout << " B :  u " << u[].l1 << " " << u[].linfty << endl; 
+if(mpirank==master)
+plot(Th, u, wait = 1, dim = 3, fill = 1, cmm = "sparsesolver symmetric", value = 1);
+
+//  try distributed  version ...
+ Th = square(150, 150, label = l);
+u=0; // resize u..
+b.resize(Vh.ndof);
+Th=change(Th,fregion= nuTriangle%mpisize);
+varf lapd(u,v) = int2d(Th,mpirank)(dx(u)*dx(v) + dy(u)*dy(v)) + int2d(Th,mpirank)(v) + on(1, u = 1);
+A = lapd(Vh, Vh,solver=CG);
+set(A, solver = sparsesolver,master=-1);// distruteb
+b = lapd(0, Vh);
+u[] = A^-1 * b;
+cout << " D u " << u[].l1 << " " << u[].linfty << " " << mpirank << endl; 
\ No newline at end of file
diff --git a/examples++-mpi/MUMPS_FreeFem.cpp b/examples++-mpi/MUMPS_FreeFem.cpp
new file mode 100644
index 0000000..01c0f1a
--- /dev/null
+++ b/examples++-mpi/MUMPS_FreeFem.cpp
@@ -0,0 +1,2605 @@
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+//ff-c++-LIBRARY-dep: mumps parmetis ptscotch scalapack blas mpifc fc mpi pthread 
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include <mpi.h>
+#include  <iostream>
+using namespace std;
+
+#ifdef WIN32
+
+// ALH - this activates the Windows DLL default export mechanism
+
+__declspec(dllexport) int not_used;
+
+// FFCS - 23/4/13 - instanciate some global symbols which are not found by default in MS MPI Fortran libraries
+
+MPI_Fint* _imp__MPI_F_STATUS_IGNORE;
+MPI_Fint* _imp__MPI_F_STATUSES_IGNORE;
+#endif
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dmumps_c.h"
+#include "zmumps_c.h"
+
+// read options for MUMPS in freefem++
+int s_(char* str, const char* cmp[])
+{
+  int i = 0;
+  while( cmp[i] != 0){
+    if( strcmp(str, cmp[i]) == 0){
+      //cout << *str << " return" << i << endl;
+      return i+1 ;
+    }
+    i++;
+  }
+  //cout << *str << " return 0" << endl;
+  return 0;
+}
+
+void read_options_freefem(string *string_option, int *SYM, int *PAR){
+  
+  static const char* comp[] = {"SYM", "PAR", 0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  cout << "data=" << data << endl;
+  char * tictac;
+  tictac = strtok(data," =,\t\n");
+  cout << "tictac=" << data << endl;
+
+  while(tictac != NULL){
+    
+    int id_option = s_(tictac, comp);
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 1 : // SYM
+	*SYM = atoi(tictac);
+	// strtol ???
+	if(*SYM != 0 && *SYM !=1) 
+	  cout << "SYM must be equal to 1 or 0 for MUMPS" << endl;
+	
+	break;
+      case 2:  // PAR
+	*PAR = atoi(tictac);
+	if(*PAR != 0 && *PAR !=1) 
+	  cout << "PAR must be equal to 1 or 0" << endl;
+	//strtol ???
+	break;
+      case 0: // Equivalent of case default
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+  
+}
+
+class dSolveMUMPSmpi :   public MatriceMorse<double>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  mutable MPI_Comm comm;
+  double            *a;
+  int       *irn, *jcn;
+  int          n, m, nz; 
+ 
+  // parameter MUMPS
+  
+  KN_<long>        perm_r; /* row permutations from partial pivoting */
+  KN_<long>        perm_c;
+  KN_<double>     scale_r;
+  KN_<double>     scale_c;
+  string string_option;
+  string data_option;
+  int SYM;
+  int PAR;
+  int myid;
+
+  // distribuer
+  int nz_loc;
+  int *jcn_loc, *irn_loc;
+  double *a_loc;
+  
+
+
+  static const int JOB_INIT=-1;
+  static const int JOB_END=-2;
+  static const int USE_COMM_WORLD= -987654;
+
+  // variable reel
+  mutable DMUMPS_STRUC_C id;
+  
+#define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */
+#define CNTL(I) cntl[(I)-1] /* macro s.t. indices match documentation */
+#define RINFOG(I) rinfog[(I)-1] /* macro s.t. indices match documentation */
+#define INFOG(I) infog[(I)-1] /* macro s.t. indices match documentation */
+public:
+  dSolveMUMPSmpi(const MatriceMorse<double> &AA,int strategy,double ttgv, double epsilon,
+		 double pivot,double pivot_sym, string param_string, string datafile, KN<long> &param_int, 
+		 KN<double> &param_double, KN<long> &pperm_r, KN<long> &pperm_c, KN<double> &pscale_r,KN<double> &pscale_c, MPI_Comm  * mpicommw
+		) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv), string_option(param_string), data_option(datafile), perm_r(pperm_r), perm_c(pperm_c), 
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot), scale_r(pscale_r), scale_c(pscale_c)
+  { 
+    long int starttime,finishtime;
+    long int timeused;
+
+    if(verbosity) starttime = clock();
+    int dataint[40];
+    double datadouble[15];
+    int ierr;
+
+     if(mpicommw==0){
+	comm=MPI_COMM_WORLD;
+	}
+	else
+	comm= *mpicommw;
+
+
+    /* ------------------------------------------------------------
+       INITIALIZE THE MUMPS PROCESS GRID. 
+       ------------------------------------------------------------*/
+    ierr = MPI_Comm_rank(comm, &myid);
+    
+    if( myid ==0){
+      n    = AA.n;
+      m    = AA.m; 
+      nz   = AA.nbcoef;
+    
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+    else{
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+    
+    if( !(param_int==NULL) ) 
+      assert( param_int.N() == 42);
+    if( !(param_double==NULL) ) 
+      assert( param_double.N() == 15);
+    if(perm_r)
+      assert( perm_r.N() == n);
+    if(perm_c)
+      assert( perm_c.N() == m);
+    if(scale_r) 
+      assert( scale_r.N() == n);
+    if(scale_c) 
+      assert( scale_c.N() == m);
+
+    if( n != m )
+      cerr << "only square matrix are supported by MUMPS" << endl;
+   
+  
+    // initialisation par defaut
+    SYM=0; PAR=1;
+    
+    /*
+      if(!string_option.empty()) 
+      {
+      if(myid==0){
+      cout << "read string option" <<endl;
+      read_options_freefem(&string_option,&SYM,&PAR);
+      
+      MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+      }
+      else{
+      MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+      }
+      }
+    */
+    if( !(param_int==NULL) ){
+      SYM = param_int[0];
+      PAR = param_int[1];
+      cout << "param :: myid =" << myid << endl;
+    }
+    else if( !data_option.empty() )
+      {	
+	cout << "myid =" << myid << endl;
+	if(myid==0){
+	  
+	  char * retfile= new char[data_option.size()+1];
+	  strcpy(retfile, (&data_option)->c_str());
+	  printf("read data option file %s\n",retfile);
+	  FILE *pFile=fopen(retfile,"rt");
+	
+	  int     i_data=0;
+	  int     d_data=0;
+	  char    data[256];
+	  char   *tictac;
+	  
+	  fgets(data,256,pFile);
+	  tictac = strtok(data," /!#\t\n");
+	  SYM = atoi(tictac);
+	  
+	  fgets(data,256,pFile);
+	  tictac = strtok(data," /!#\t\n");
+	  PAR = atoi(tictac);
+	  
+	  while( !feof(pFile) && i_data < 40){
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    dataint[i_data] = (int)atol(tictac);
+	    i_data++;
+	  }  
+	  assert(i_data == 40);
+	  while( !feof(pFile) && d_data < 15){
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    datadouble[d_data] = (double)atof(tictac);
+	    d_data++;
+	  }  
+	  assert(d_data == 15);
+	  /*
+	    for(int ii=0; ii< 40; ii++){
+	    cout << "double int["<< ii <<"] ="<< dataint[ii] << endl;
+	    }  
+	    for(int ii=0; ii< 15; ii++){
+	    cout << "double data["<< ii <<"] ="<< datadouble[ii] << endl;
+	    }  
+	  */
+	  MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	  MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+
+	  cout << "myid =" << myid << " init parameter :: PAR & SYM " << PAR << " " << SYM << endl; 
+
+	  MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	  MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+
+
+	  fclose(pFile);
+	  delete [] retfile;
+	}
+	else{
+	  
+
+	  MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	  MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+	  
+	  cout << "myid =" << myid << "  init parameter :: PAR & SYM " << PAR << " " << SYM << endl; 
+
+
+	  MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	  MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+	}
+      }
+    
+  
+    /* Initialize a MUMPS instance. Use comm */
+    id.job=JOB_INIT; 
+    id.par=PAR; 
+    id.sym=SYM;
+    id.comm_fortran= (MUMPS_INT) MPI_Comm_c2f( comm );
+    //id.comm_fortran= (F_INT) comm;
+
+    if(verbosity>2) cout << " MUMPS_FreeFem init parameter :: PAR & SYM " << PAR << " " << SYM << endl; 
+
+    dmumps_c(&id);
+
+    if(verbosity>10) cout << "fin init parameter" << endl; 
+
+    /* set parameter of mumps */
+    if( !(param_int == NULL) || !(param_double == NULL) ){
+      if(!data_option.empty()){ 
+	printf("MUMPS ERROR:  parameters are given on the file %s and in the array lparams and dparams => double definition of parameters.",data_option.c_str());
+	exit(1);
+      }
+      
+      if( !(param_int == NULL) ){
+	cout << "internal parameter" << endl;
+	for(int ii=0; ii<40; ii++)	  
+	  id.ICNTL(ii+1) = param_int[ii+2];
+      }
+      else{
+
+	// parameter by default
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+      }
+      if( !(param_double == NULL) ){
+	cout << "internal parameter" << endl;
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = param_double[ii];
+      }
+    }    
+    else 
+      if(!data_option.empty()){
+	for(int ii=0; ii<40; ii++)
+	  id.ICNTL(ii+1) = dataint[ii];
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = datadouble[ii];
+      }
+      else{
+	// parameter by default
+	if(verbosity>10) 
+	cout << "default parameter" << endl;
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+    }
+
+    // uniquement donner au host 
+    if(myid==0)
+      {
+	if( !(perm_r==NULL) && id.ICNTL(7)==1){
+	  for(int ii=0; ii<n; ii++) id.perm_in[ii] = pperm_r[ii];
+	}
+	// a decommenter
+	//if( !(perm_c==NULL) && id.ICNTL(6)==1){
+	//for(int ii=0; ii<m; ii++) id.perm_in[ii] = pperm_c[ii];
+      //}
+	if( !(scale_r==NULL) && !(scale_c==NULL) && id.ICNTL(8)==-1 ){
+	  // param_double[0::n-1] :: row  
+	  // param_double[n::n+m-1] :: column 
+	  for(int ii=0; ii<n; ii++) id.rowsca[ii] = scale_r[ii]; 
+	  for(int ii=0; ii<m; ii++) id.colsca[ii] = scale_c[ii];
+	}
+      }
+
+    irn = NULL;
+    jcn = NULL;
+
+    /* valeur par defaut mis dans le dur */      
+    //id.ICNTL(5)  = 0;  
+    //id.ICNTL(18) = 0;
+    
+    // Distribution depend de la valeur de ICNTL(18)
+    if( id.ICNTL(5) != 0 ){
+      printf("we consider only assembled format \n");
+      printf("forced assembled format ==> id.ICNTL(5)  = 0;  \n");
+      id.ICNTL(5)  = 0;  
+      exit(1);
+    }
+
+    if (myid == 0) {
+      id.n = n; id.nz =nz; 
+      //id.irn=irn; id.jcn=jcn;
+      //id.a = a; //id.rhs = rhs;
+    }
+
+    if( id.ICNTL(18) == 0)
+      {
+        
+	// CASE:: NON DISTRIBUTED MATRIX
+	if (myid == 0) { // nouveau
+
+	  a=AA.a;
+	  // ATTENTION 
+	  // AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	  // index of row and colummn by 1
+	  jcn = AA.cl;
+	  for(int ii=0; ii<nz; ii++)
+	    jcn[ii] = jcn[ii]+1;
+	  
+	  if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	    printf("problem allocation jcn ");
+	    exit(1);
+	  }
+	
+	  assert(AA.lg[n] == nz);
+	  for(int ii=0; ii< n; ii++)
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	      irn[ii1] = ii+1;  
+		
+	  // if (myid == 0) {   // ancien
+	  id.irn=irn; id.jcn=jcn;
+	  id.a = a; //id.rhs = rhs;
+	}
+
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation 
+	id.job=4;
+	dmumps_c(&id);
+	
+      }
+
+
+    if( id.ICNTL(18) == 1 || id.ICNTL(18) == 2 )
+      {
+
+	if(verbosity > 1) cout <<"id.ICNTL(18) = 1 || id.ICNTL(18) == 2 "<< endl;
+	// ATTENTION 
+	// AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	// index of row and column by 1
+	
+	if (myid == 0) { // new host process 
+	
+	  jcn = AA.cl;
+	  for(int ii=0; ii<nz; ii++)
+	    jcn[ii] = jcn[ii]+1;
+	  
+	  if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	    printf("problem allocation irn ");
+	    exit(1);
+	  }
+	  
+	  assert(AA.lg[n] == nz);
+	  for(int ii=0; ii< n; ii++)
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	      irn[ii1] = ii+1;  
+	  
+	  
+	  //if (myid == 0) {  // enlever new host
+	  id.irn=irn; id.jcn=jcn;
+	}
+	
+	/* Call the MUMPS package. */
+	// Analyse   
+	id.job=1;
+	dmumps_c(&id);
+
+	if(id.ICNTL(18) == 1 ){
+	  
+	   if( PAR == 0 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    double *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    cout << commSize << "commSize" << "nz =" << nz << endl;
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      assert(nz_loc_procs[0] == 0);
+	      nz_loc_procs[0] = 2;
+
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      jcn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      a_g   = (double*) malloc( sizeof(double)*(nz+2) );
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      irn_g[ 0 ] = 1;
+	      jcn_g[ 0 ] = 1;
+	      a_g  [ 0 ] = 1.;
+	      
+	      irn_g[ 1 ] = 1;
+	      jcn_g[ 1 ] = 1;
+	      a_g  [ 1 ] = 1.;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+		assert(jj2 > 1);
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		cout << "jj2= " << jj2 << endl;
+		assert( jj2 < nz+2);
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    cout << "myid=" << myid <<" nz_loc=" << nz_loc << endl;
+	    if( myid == 1){
+	      cout << "nz_loc=" << nz_loc << endl;
+	      for(int ii=0;ii<nz_loc; ii++){
+		cout << "a_loc[ii]" << a_loc[ii] << endl;
+	
+	      }
+	    }
+	    
+	    if( myid > 0){
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = a_loc;
+	    }
+	    
+	    if( myid == 0){
+	      //free( irn_loc );
+	      //free( jcn_loc );
+	      //free( a_loc );
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	   }
+	
+	  
+	  if( PAR == 1 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    double *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );
+	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc(sizeof(int)*nz);
+	      jcn_g = (int*) malloc(sizeof(int)*nz);
+	      a_g   = (double*) malloc(sizeof(double)*nz);
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = a_loc;
+	    
+	    
+	    if( myid == 0){
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	  }
+	  // version all procs
+// 	    if(myid==0){
+//	    
+// 	    MPI_Bcast( id.mapping, nz, MPI_INT,  0, comm );
+//    
+// 	    nz_loc=0;
+// 	    for(int ii=0;ii<nz; ii++){
+// 	      if( id.mapping[ii] == myid) nz_loc++;
+// 	    }
+//   
+// 	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    a_loc   = (double*) malloc(sizeof(double)*nz_loc);
+//
+// 	    int jj=0;
+// 	    for(int ii=0;ii<nz; ii++)
+// 	      if( id.mapping[ii] == myid){
+// 		irn_loc[jj] = irn[ ii ];
+// 		jcn_loc[jj] = jcn[ ii ];
+// 		a_loc[jj] = AA.a[ ii ];
+// 		jj++;
+// 	      }
+// 	    assert(jj==nz_loc);
+//	    
+// 	    if(PAR==1){
+// 	      id.nz_loc = nz_loc;
+// 	      id.irn_loc = irn_loc;
+// 	      id.jcn_loc = jcn_loc;
+// 	      id.a_loc = a_loc;
+// 	    }
+//	    
+// 	  }
+// 	  else{
+// 	    int *mapping;
+// 	    mapping = (int*) malloc(sizeof(int)*nz);
+// 	    MPI_Bcast( mapping, nz, MPI_INT,  0, comm );
+// 	    nz_loc=0;
+//
+// 	    for(int ii=0;ii<nz; ii++)
+// 	      if( mapping[ii] == myid) nz_loc++;
+//	    
+// 	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    a_loc    = (double*) malloc(sizeof(double)* nz_loc);
+//	    
+// 	    //==============================
+// 	    //    besoin de irn, jcn, AA.a
+// 	    //==============================
+//
+// 	    int jj=0.;
+// 	    for(int ii=0;ii<nz; ii++)
+// 	      if( mapping[ii] == myid){
+// 		irn_loc[jj] = irn[ ii ];  
+// 		jcn_loc[jj] = jcn[ ii ];
+// 		a_loc[jj] = AA.a[ ii ];
+// 		jj++;
+// 	      }
+// 	    assert(jj==nz_loc);
+//
+// 	    free(mapping);
+//
+// 	    id.nz_loc = nz_loc;
+// 	    id.irn_loc = irn_loc;
+// 	    id.jcn_loc = jcn_loc;
+// 	    id.a_loc = a_loc;
+// 	  }
+	 
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  dmumps_c(&id);	  
+	  
+	}
+      
+
+	if(id.ICNTL(18) == 2 ){
+	  printf("id.ICNTL(18)==2 not avaible yet \n");
+	  exit(1);
+
+
+	  if(PAR == 0){ 
+	    printf("id.ICNTL(18)==2 with PAR=0 not available yet \n");
+	    exit(1);
+	    if(myid !=0) {
+	      
+	      //==============================
+	      //    besoin de irn, jcn, AA.a
+	      //==============================
+	      
+	      int commSize;	    
+	      ierr=MPI_Comm_size(comm,&commSize);
+	      commSize=commSize-1;
+	      int myidpar=myid-1;
+	      int m_loc_fst = m/commSize;
+	      int m_loc;
+	      if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+		m_loc = m-m_loc_fst*( commSize-1 );
+	      else
+		m_loc = m_loc_fst;
+	      
+	      int fst_row= myidpar*m_loc_fst;
+	      nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	      
+	      // allocation des tableaux
+	      irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	      
+	      int fst_nnz = AA.lg[fst_row];
+	      for(int ii=0; ii < nz_loc; ii++){
+		a_loc[ii] = AA.a[fst_nnz+ii];
+		jcn_loc[ii] = AA.cl[fst_nnz+ii]; // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	      }
+	      
+	      for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+		for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		  irn_loc[ii1-fst_nnz] = ii+1;  
+	      }
+	      
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = a_loc;
+	    }
+	  }
+	  if(PAR == 1){
+
+	    //==============================
+	    //    besoin de irn, jcn, AA.a
+	    //==============================
+	      
+	    int commSize;	    
+	    ierr=MPI_Comm_size(comm,&commSize);
+	    int m_loc_fst = m/commSize;
+	    int m_loc;
+	    if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	      m_loc = m-m_loc_fst*( commSize-1 );
+	    else
+	      m_loc = m_loc_fst;
+	    
+	    int fst_row= myid*m_loc_fst;
+	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+	    // allocation des tableaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	    
+	    int fst_nnz = AA.lg[fst_row];
+	    for(int ii=0; ii < nz_loc; ii++){
+	      a_loc[ii] = AA.a[fst_nnz+ii];
+	      jcn_loc[ii] = AA.cl[fst_nnz+ii];  // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	    }
+	    
+	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+	      for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		irn_loc[ii1-fst_nnz] = ii+1;  
+	    }
+	  
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = a_loc;
+	    
+	  }
+
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  dmumps_c(&id);
+	}
+      }
+	
+    if( id.ICNTL(18) == 3 )
+      {	
+	// indices et colonnes de la matrice
+	
+// 	//  Cas Matrice parallele ::
+// 	//  ========================
+//	
+// 	// Cas stockage Morse parallele
+// 	m_loc = AA.m_loc;       // Nombre de lignes prise en compte
+// 	nz_loc = AA.nbcoef_loc;   // Nombre de coefficients non nulles 
+// 	// indice des colonnes
+// 	jcn_loc = AA.cl_loc;       // indices des colonnes dans la matrice locale
+//	
+// 	if( !(irn_loc = (int*) malloc(sizeof(int)*nz_loc)) ){
+// 	  printf("problem allocation jcn ");
+// 	  exit(1);
+// 	}
+// 	assert(AA.lg_loc[nrow_loc] == nz_loc);
+// 	for(int ii=0; ii< nrow_loc; ii++)
+// 	  for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 	    irn_loc[ii1] = ii+1;
+//
+// 	a_loc=AA.a_loc;
+//
+	// Pas de matrice parallele ==> utilisation astuce de SuperLU
+	// Matrice :: distribution bloc continue de lignes :: voir SuperLU 
+	// Attention :: performance ???
+	
+// 	    //==================
+// 	    // pour un proc :
+// 	    // a:     AA.a[fstow]   , ..., AA.a[fstrow+nz_loc-1] 
+// 	    // jcn:   AA.cl[fstrow] , ..., AA.cl[fstrow+nz_loc-1]
+// 	    // irn:   AA.lg[fstrow] , ..., AA.lg[fstrow+m_loc] 
+// 	    //==================
+// 	    // apres reception : 
+// 	    // irn_reel:  
+// 	    //  int jj=0, 
+// 	    //  do ii=0,m_loc-1
+// 	    //      do ii1=irn_donnee[ii],irn_donnee[ii+1]-1
+// 	    //         irn_reel[jj] = fst_row+ii+1;
+// 	    //         jj++
+// 	    //      end do
+// 	    //  end do
+// 	    //=================
+
+	cout <<"id.ICNTL(18) = 3,  PAR="<< PAR << endl;
+
+	if(PAR == 0){
+	  	  
+	    
+// 	  if(myid != 0) {
+// 	    int commSize;	    
+// 	    ierr=MPI_Comm_size(comm,&commSize);
+// 	    commSize=commSize-1;
+// 	    int myidpar=myid-1;
+// 	    int m_loc_fst;
+// 	    m_loc_fst= m/commSize;
+// 	    int m_loc;
+// 	    if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+// 	      m_loc = m-m_loc_fst*( commSize-1 );
+// 	    else
+// 	      m_loc = m_loc_fst;
+	    
+// 	    int fst_row;
+// 	    fst_row= myidpar*m_loc_fst;
+// 	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+// 	    // allocation des tableaux
+// 	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    a_loc    = (double*) malloc(sizeof(double)* nz_loc);
+	    
+// 	    int fst_nnz;
+// 	    fst_nnz = AA.lg[fst_row];
+// 	    for(int ii=0; ii < nz_loc; ii++){
+// 	      a_loc[ii] = AA.a[fst_nnz+ii];
+// 	      jcn_loc[ii] = AA.cl[fst_nnz+ii]+1;
+// 	    }
+	    
+// 	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+// 	      for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 		irn_loc[ii1-fst_nnz] = ii+1;  
+// 	    }
+	 
+// 	    id.nz_loc = nz_loc;
+// 	    id.irn_loc = irn_loc;
+// 	    id.jcn_loc = jcn_loc;
+// 	    id.a_loc = a_loc;
+// 	  }
+
+
+	  // definition de variables
+	  int commSize;
+	  int m_loc_fst;	 
+	  int m_loc;
+	  int fst_row;
+	  
+
+	  int *nz_loc_procs;
+	  int *fst_nz_procs;
+	  int *m_loc_procs;
+	  int *fst_row_procs;
+	 
+
+	  double *tab_a;
+	  int *tab_cl;
+	  int *tab_lg;
+	  int *tab_lg_loc;
+
+	  MPI_Comm_size(comm,&commSize);
+	  
+	  if( myid !=0){
+	    int commSizemm;
+	    int myidpar=myid-1;
+
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+	  
+	    if( myidpar == commSizemm-1 && ( m_loc_fst*commSizemm != m ) )  
+	      m_loc = m-m_loc_fst*( commSizemm-1 );
+	    else
+	      m_loc = m_loc_fst;
+	  
+	    if(verbosity > 5){
+	      fst_row = myidpar*m_loc_fst;
+	      cout << "   myid = " << myid << endl;
+	      cout <<"   m_loc = " << m_loc << endl;
+	      cout <<" fst_row = " << fst_row << endl;
+	    }
+
+	  }
+	  if( myid ==0){
+
+	    int commSizemm;
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+
+	    fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	    m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	    fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	    nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+	    
+	    
+	    fst_row_procs [0] = 0;
+	    m_loc_procs   [0] = 0;
+
+	    for( int ii= 1; ii<commSize; ii++){
+	      fst_row_procs [ii] = (ii-1)*m_loc_fst;
+	      m_loc_procs [ii] = m_loc_fst;
+	    }
+	    
+	    if( m_loc_fst*(commSize-1) != m ) 
+	      m_loc_procs [commSize-1] = m-m_loc_fst*( (commSize-1)-1 );
+
+
+	    nz_loc_procs [0] = 0;
+	    fst_nz_procs [0] = 0;
+	    
+	    for( int ii= 1; ii<commSize; ii++){
+	      nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	      fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	    }
+
+	   
+	    /*
+	      tab_a= (int* ) malloc( nz*sizeof(double) );
+	      tab_cl = (int* ) malloc( nz*sizeof(int) );
+	      tab_lg = (int* ) malloc ( n*sizeof(int) );
+	    */
+	    tab_a  = AA.a;
+	    tab_cl = AA.cl;
+	    tab_lg = AA.lg;
+	  }
+
+	  MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( m_loc_procs,  1, MPI_INT, &m_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( fst_row_procs,  1, MPI_INT, &fst_row, 1, MPI_INT, 0, comm);
+
+	  if(verbosity > 5){
+	    cout << "after scatter " << myid << endl;
+	    cout << "   myid = " << myid << endl;
+	    cout <<"   m_loc = " << m_loc << endl;
+	    cout <<" fst_row = " << fst_row << endl;
+	  }
+	  // allocation des tableaux locaux
+	  irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	  tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	  
+	
+
+	  MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	  MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	  MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	  
+	
+	  int jj=0;
+	  for(int  ii=0; ii<m_loc-1; ii++)
+	    for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	      irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	    }
+	  
+	  for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	    irn_loc[jj] = fst_row+(m_loc-1)+1;
+	    jj++;
+	  }
+	  
+	  for(int ii=0; ii < nz_loc; ii++){	    
+	    jcn_loc[ii] = jcn_loc[ii]+1; 
+	  }
+
+	  assert( jj == nz_loc );
+	  
+	  free( tab_lg_loc );
+	  
+	  id.nz_loc = nz_loc;
+	  id.irn_loc = irn_loc;
+	  id.jcn_loc = jcn_loc;
+	  id.a_loc = a_loc;
+	 
+	  if( myid == 0 ){
+	    free( fst_row_procs );
+	    free( m_loc_procs );
+	    free( fst_nz_procs );
+	    free( nz_loc_procs );
+	  }
+
+	}
+	if(PAR ==1) {
+	  /*
+	    int commSize;
+	    ierr=MPI_Comm_size(comm,&commSize);
+	    int m_loc_fst;
+	    m_loc_fst= m/commSize;
+	    int m_loc;
+	    if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	    m_loc = m-m_loc_fst*( commSize-1 );
+	    else
+	    m_loc = m_loc_fst;	  
+	    
+	    int fst_row;
+	    fst_row = myid*m_loc_fst;
+	    
+	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+	    // allocation des tableaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)* nz_loc);
+	    
+	    int fst_nnz;
+	    fst_nnz= AA.lg[fst_row];
+	    for(int ii=0; ii < nz_loc; ii++){
+	    a_loc[ii] = AA.a[fst_nnz+ii];
+	    jcn_loc[ii] = AA.cl[fst_nnz+ii]+1; 
+	    }
+	  
+	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++)
+	    irn_loc[ii1-fst_nnz] = ii+1;  
+	    }
+	    
+	  */
+
+	  // definition de variables
+	  int commSize;
+	  int m_loc_fst;	 
+	  int m_loc;
+	  int fst_row;
+	  
+
+	  int *nz_loc_procs;
+	  int *fst_nz_procs;
+	  int *m_loc_procs;
+	  int *fst_row_procs;
+	 
+
+	  double *tab_a;
+	  int *tab_cl;
+	  int *tab_lg;
+	  int *tab_lg_loc;
+
+	  MPI_Comm_size(comm,&commSize);
+	  m_loc_fst= m/commSize;
+	  
+	  if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	    m_loc = m-m_loc_fst*( commSize-1 );
+	  else
+	    m_loc = m_loc_fst;	  
+	  
+	  fst_row = myid*m_loc_fst;
+	  
+	  if( myid ==0){
+	    fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	    m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	    fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	    nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+
+	    for( int ii= 0; ii<commSize; ii++){
+	      fst_row_procs [ii] = ii*m_loc_fst;
+	      m_loc_procs [ii] = m_loc_fst;
+	    }
+	    
+	    if( m_loc_fst*commSize != m ) 
+	      m_loc_procs [commSize-1] = m-m_loc_fst*( commSize-1 );
+	    
+	    for( int ii= 0; ii<commSize; ii++){
+	      nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	      fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	    }
+
+	   
+	    /*
+	      tab_a= (int* ) malloc( nz*sizeof(double) );
+	      tab_cl = (int* ) malloc( nz*sizeof(int) );
+	      tab_lg = (int* ) malloc ( n*sizeof(int) );
+	    */
+	    tab_a  = AA.a;
+	    tab_cl = AA.cl;
+	    tab_lg = AA.lg;
+	  }
+
+	  MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  cout << "nz_loc("<<myid<<")="<< nz_loc << endl;
+	  cout << "m_loc("<<myid<<")="<< m_loc << endl;
+	  // allocation des tableaux locaux
+	  irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	  tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	
+	  MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	  MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	  MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	
+	  int jj=0;
+	  for(int  ii=0; ii<m_loc-1; ii++)
+	    for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	      irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	    }
+	  
+	  for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	    irn_loc[jj] = fst_row+(m_loc-1)+1;
+	    jj++;
+	  }
+	  
+	  for(int ii=0; ii < nz_loc; ii++){	    
+	    jcn_loc[ii] = jcn_loc[ii]+1; 
+	  }
+
+	  assert( jj == nz_loc );
+	  
+	  free( tab_lg_loc );
+	  
+	  id.nz_loc = nz_loc;
+	  id.irn_loc = irn_loc;
+	  id.jcn_loc = jcn_loc;
+	  id.a_loc = a_loc;
+	 
+	  if( myid == 0 ){
+	    free( fst_row_procs );
+	    free( m_loc_procs );
+	    free( fst_nz_procs );
+	    free( nz_loc_procs );
+	  }
+	}
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation
+	 
+	 id.job=1;
+	 dmumps_c(&id);
+
+	 id.job=2;
+	 dmumps_c(&id);
+      }
+    
+    
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if( jcn != NULL )
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+
+    if( irn != NULL && id.ICNTL(18) >0 ){
+      free(irn); 
+      irn=NULL;
+    }
+
+
+    
+    if( verbosity > 1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Factorisation ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+    
+    if( verbosity )
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << "MUMPS : time factorisation  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+
+  }
+  void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+    long int starttime,finishtime;
+    long int timeused;
+    /////////////////////////////
+    double *rhs;
+    int job;
+
+    if(verbosity) starttime = clock();
+    
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+  
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]+1;
+   
+
+    if ( !(rhs = (double*) malloc(sizeof(double)*m) ) ){
+      printf("Pb allocate rhs in MUMPS\n");
+      exit(1);
+    }
+   
+    for(int ii=0; ii<m; ++ii){
+      rhs[ii] = b[ii];
+    }
+
+    if( myid == 0 )
+      id.rhs=rhs;
+
+    /* solve linear problem */
+
+    id.job=3;
+    dmumps_c(&id);
+
+    if( myid==0 ){
+      x=id.rhs;
+      MPI_Bcast( x, n, MPI_DOUBLE, 0, comm );
+    }
+    else
+      MPI_Bcast( x, n, MPI_DOUBLE, 0, comm );
+    
+    // deallocation de rhs
+    free(rhs);
+
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+    
+    if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+
+    
+
+
+    if( verbosity >1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Solving       ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+
+    if( verbosity ){
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << "MUMPS : time solve step  :: " << timeused << " ms,  Mem usage " << id.INFOG(16) << "Mb  \n";
+	printf("=====================================================\n");
+      }
+    }
+  }
+
+  ~dSolveMUMPSmpi() { 
+    if(verbosity>10)
+      cout << "~SolveMUMPS S:" << endl;
+    
+     id.job=JOB_END; 
+     dmumps_c(&id); /* Terminate instance */
+
+     if( irn != NULL){
+      free(irn); 
+      irn=NULL;
+     }
+     /*
+       free(jcn_loc);
+       free(irn_loc);
+       free(a_loc);
+     */
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+static mumps_double_complex *mumps_dc(Complex *p)  { return (mumps_double_complex *) (void *) p;}
+static Complex *inv_mumps_dc(mumps_double_complex *p)  { return (Complex *) (void *) p;}
+
+class zSolveMUMPSmpi :   public MatriceMorse<Complex>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  mutable MPI_Comm comm;
+
+  Complex           *a;
+  int       *irn, *jcn;
+  int          n, m, nz; 
+   
+  // parameter MUMPS
+  KN<int>        perm_r; /* row permutations from partial pivoting */
+  KN<int>        perm_c;
+  KN<double>     scale_r;
+  KN<double>     scale_c;
+  string  string_option;
+  string data_option;
+  int SYM;
+  int PAR;
+  int myid;
+
+  // distribuer
+  int nz_loc;
+  int *jcn_loc, *irn_loc;
+  Complex *a_loc;
+
+
+  static const int JOB_INIT=-1;
+  static const int JOB_END=-2;
+  static const int USE_COMM_WORLD= -987654;
+
+  // variable complex 
+  mutable ZMUMPS_STRUC_C id;
+
+  /* variable d'informations */ 
+  
+#define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */
+#define CNTL(I) cntl[(I)-1] /* macro s.t. indices match documentation */
+#define RINFOG(I) rinfog[(I)-1] /* macro s.t. indices match documentation */
+#define INFOG(I) infog[(I)-1] /* macro s.t. indices match documentation */
+public:
+  zSolveMUMPSmpi(const MatriceMorse<Complex> &AA,int strategy,double ttgv, double epsilon,
+		 double pivot,double pivot_sym, string param_string, string datafile, KN<long> &param_int, 
+		 KN<double> &param_double, KN<long> &pperm_r, KN_<long> &pperm_c, KN<double> &pscale_r,KN<double> &pscale_c, MPI_Comm  * mpicommw) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv), string_option(param_string), data_option(datafile), perm_r(pperm_r), perm_c(pperm_c), 
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot), scale_r(pscale_r), scale_c(pscale_c)
+  { 
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+    int dataint[40];
+    double datadouble[15];
+    int ierr;
+
+    if(mpicommw==0){
+      comm=MPI_COMM_WORLD;
+    }
+    else
+      comm= *mpicommw;
+    
+    /* ------------------------------------------------------------
+       INITIALIZE THE MUMPS PROCESS GRID. 
+       ------------------------------------------------------------*/
+    ierr = MPI_Comm_rank(comm, &myid);
+    if( myid ==0){
+      n    = AA.n;
+      m    = AA.m; 
+      nz   = AA.nbcoef;
+    
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+    else{
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+   
+
+    if( !(param_int==NULL) ) 
+      assert( param_int.N() == 42);
+    if( !(param_double==NULL) ) 
+      assert( param_double.N() == 15);
+    if(pperm_r)
+      assert( perm_r.N() == n);
+    if(pscale_r) 
+      assert( scale_r.N() == n+m );
+    if(pscale_c) 
+       assert( scale_c.N() == n+m );
+    if( n != m )
+      cerr << "only square matrix are supported by MUMPS" << endl;
+   
+      /* ------------------------------------------------------------
+       INITIALIZE THE MUMPS PROCESS GRID. 
+       ------------------------------------------------------------*/
+   
+    // initialisation par defaut
+ 
+    SYM=0; PAR=1;
+    
+    //      if(!string_option.empty()) 
+    //       {	
+    // 	read_options_freefem(&string_option,&SYM,&PAR);
+    //       }
+    if( !(param_int==NULL) ){
+      SYM = param_int[0];
+      PAR = param_int[1];
+    }
+    else 
+      if(!data_option.empty())
+	{
+	  if(myid==0){
+	    char * retfile= new char[data_option.size()+1];
+	    strcpy(retfile, (&data_option)->c_str());
+	    printf("read data from file %s\n", retfile);
+	    FILE *pFile=fopen(retfile,"rt");
+	    
+	    int     i_data=0;
+	    int     d_data=0.;
+	    char    data[256];
+	    char   *tictac;
+	    
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    SYM = atoi(tictac);
+	    
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    PAR = atoi(tictac);
+	    
+	    while( !feof(pFile) && i_data < 40){
+	      fgets(data,256,pFile);
+	      tictac = strtok(data," /!#\t\n");
+	      dataint[i_data] = (int)atol(tictac);
+	      i_data++;
+	    }  
+	    assert(i_data == 40);
+	    while( !feof(pFile) && d_data < 15){
+	      fgets(data,256,pFile);
+	      tictac = strtok(data," /!#\t\n");
+	      datadouble[d_data] = (double)atof(tictac);
+	      d_data++;
+	    }  
+	    assert(d_data == 15);
+	    fclose(pFile);
+	    delete [] retfile;
+	    
+	    MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	    MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+	    
+	    MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	    MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+	    
+	    fclose(pFile);
+	    delete [] retfile;
+	  }
+	  else{
+	    
+	    MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	    MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+	    
+	    MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	    MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+	  }
+	}
+    
+    /* Initialize a MUMPS instance. Use comm */
+    id.job=JOB_INIT; 
+    id.par=PAR; 
+    id.sym=SYM;
+    id.comm_fortran=(MUMPS_INT) MPI_Comm_c2f(comm); 
+
+    zmumps_c(&id);
+
+     /* set parameter of mumps */
+    if( !(param_int==NULL) || !(param_double==NULL) ){
+      if(!data_option.empty()){ 
+	printf("read option before with the file %s\n",data_option.c_str());
+	exit(1);
+      }
+      
+      if( !(param_int==NULL) ){ 
+	for(int ii=0; ii<40; ii++)
+	  id.ICNTL(ii+1) = param_int[ii+2];
+      }
+      else
+	// parameter by default
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+
+      if( !(param_double==NULL) )
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = param_double[ii];
+      
+    }    
+    else 
+      if(!data_option.empty()){
+	for(int ii=0; ii<40; ii++)
+	  id.ICNTL(ii+1) = dataint[ii];
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = datadouble[ii];
+      }
+      else{
+	// parameter by default
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+      }
+
+    // uniquement donner au host 
+    if(myid==0){
+      if( !(perm_r==NULL) && id.ICNTL(7)==1){
+	for(int ii=0; ii<n; ii++) id.perm_in[ii] = pperm_r[ii];
+      }
+      // a decommenter
+      //if( !(perm_c==NULL) && id.ICNTL(6)==1){
+      //for(int ii=0; ii<m; ii++) id.perm_in[ii] = pperm_c[ii];
+      //}
+      if( !(scale_r==NULL) && !(scale_c==NULL) && id.ICNTL(8)==-1 ){
+	for(int ii=0; ii<n; ii++) id.rowsca[ii] = scale_r[ii]; 
+	for(int ii=0; ii<m; ii++) id.colsca[ii] = scale_c[ii];
+      }
+    }
+
+    
+    /* valeur par defaut mis dans le dur */
+   
+    irn = NULL;
+    jcn = NULL;
+
+
+    if( id.ICNTL(5) != 0 ){
+      printf("we consider only assembled format \n");
+      exit(1);
+    }
+   
+    
+    /* Define the problem on the host */
+    if (myid == 0) {
+      id.n = n; id.nz =nz; 
+      //id.irn=irn; id.jcn=jcn;
+      //id.a = mumps_dc(a); //id.rhs = rhs;
+    }
+
+    if( id.ICNTL(18) == 0)
+      {
+	// CASE:: NON DISTRIBUTED MATRIX
+	a=AA.a;
+	// ATTENTION 
+	// AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	// index of row and colummn by 1
+	jcn = AA.cl;
+	for(int ii=0; ii<nz; ii++)
+	  jcn[ii] = jcn[ii]+1;
+	
+	if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	  printf("problem allocation jcn ");
+	  exit(1);
+	}
+	
+	assert(AA.lg[n] == nz);
+	for(int ii=0; ii< n; ii++)
+	  for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	    irn[ii1] = ii+1;  
+		
+	if (myid == 0) {
+	  id.irn=irn; id.jcn=jcn;
+	  id.a = mumps_dc(a); //id.rhs = rhs;
+	}
+
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation 
+	id.job=4;
+	zmumps_c(&id);
+	
+      }
+
+    
+    if( id.ICNTL(18) == 1 || id.ICNTL(18) == 2 )
+      {
+
+	cout <<"id.ICNTL(18) = 1 || id.ICNTL(18) == 2 "<< endl;;
+	// ATTENTION 
+	// AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	// index of row and column by 1
+
+	if(myid == 0) { // uniquement sur le proc 0
+	  jcn = AA.cl;
+	  for(int ii=0; ii<nz; ii++)
+	    jcn[ii] = jcn[ii]+1;
+	  
+	  if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	    printf("problem allocation irn ");
+	    exit(1);
+	  }
+	
+	  assert(AA.lg[n] == nz);
+	  for(int ii=0; ii< n; ii++)
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	      irn[ii1] = ii+1;  
+
+
+	  //if (myid == 0) { // changement uniquement sur le proc 0
+	  id.irn=irn; id.jcn=jcn;
+	}
+	
+	/* Call the MUMPS package. */
+	// Analyse   
+	id.job=1;
+	zmumps_c(&id);
+
+	if(id.ICNTL(18) == 1 ){
+
+	   if( PAR == 0 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    Complex *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    cout << commSize << "commSize" << "nz =" << nz << endl;
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      assert(nz_loc_procs[0] == 0);
+	      nz_loc_procs[0] = 2;
+
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      jcn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      a_g   = (Complex*) malloc( 2*sizeof(double)*(nz+2) );
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      irn_g[ 0 ] = 1;
+	      jcn_g[ 0 ] = 1;
+	      a_g  [ 0 ] = 1.;
+	      
+	      irn_g[ 1 ] = 1;
+	      jcn_g[ 1 ] = 1;
+	      a_g  [ 1 ] = 1.;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+		assert(jj2 > 1);
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		cout << "jj2= " << jj2 << endl;
+		assert( jj2 < nz+2);
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    	    
+	    if( myid > 0){
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = mumps_dc(a_loc);
+	    }
+	    
+	    if( myid == 0){
+	      //free( irn_loc );
+	      //free( jcn_loc );
+	      //free( a_loc );
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	   }
+	
+	  
+	  if( PAR == 1 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    Complex *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );
+	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc(sizeof(int)*nz);
+	      jcn_g = (int*) malloc(sizeof(int)*nz);
+	      a_g   = (Complex*) malloc(2*sizeof(double)*nz);
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc   = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = mumps_dc(a_loc);
+	    
+	    
+	    if( myid == 0){
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	  }
+
+
+
+
+	  //printf("id.ICNTL(18)==1 pas prevus a construire \n");
+	  //exit(1);
+
+	  /* // version matrice sur tous les processeurs
+	  if(myid==0){
+
+	    MPI_Bcast( id.mapping, nz, MPI_INT,  0, comm );
+
+	    nz_loc=0;
+	    for(int ii=0;ii<nz; ii++){
+	      if( id.mapping[ii] == myid) nz_loc++;
+	    }
+	   
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc   = (Complex*) malloc(sizeof(Complex)*nz_loc);
+
+	    int jj=0;
+	    for(int ii=0;ii<nz; ii++)
+	      if( id.mapping[ii] == myid){
+		irn_loc[jj] = irn[ ii ];
+		jcn_loc[jj] = jcn[ ii ];
+		a_loc[jj] = AA.a[ ii ];
+		jj++;
+	      }
+	    assert(jj==nz_loc);
+	    
+	    if(PAR==1){
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = mumps_dc(a_loc);
+	    }
+  
+	  }
+	  else{
+	    int *mapping;
+	    mapping = (int*) malloc(sizeof(int)*nz);
+	    MPI_Bcast( mapping, nz, MPI_INT,  0, comm );
+	    nz_loc=0;
+
+	    for(int ii=0;ii<nz; ii++)
+	      if( mapping[ii] == myid) nz_loc++;
+	    
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (Complex*) malloc(sizeof(Complex)* nz_loc);
+	    
+	    int jj=0.;
+	    for(int ii=0;ii<nz; ii++)
+	      if( mapping[ii] == myid){
+		irn_loc[jj] = irn[ ii ];
+		jcn_loc[jj] = jcn[ ii ];
+		a_loc[jj] = AA.a[ ii ];
+		jj++;
+	      }
+	    assert(jj==nz_loc);
+
+	    free(mapping);
+
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = mumps_dc(a_loc);
+
+
+
+	  }
+	  */
+
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  zmumps_c(&id);	  
+	  
+	}
+      
+
+	if(id.ICNTL(18) == 2 ){
+	   printf("id.ICNTL(18)==2 not yet available \n");
+	   exit(1);
+
+	  if(PAR == 0){ 
+	    printf("id.ICNTL(18)==2 pas prevus \n");
+	    exit(1);
+	    if(myid !=0) {
+	      int commSize;	    
+	      ierr=MPI_Comm_size(comm,&commSize);
+	      commSize=commSize-1;
+	      int myidpar=myid-1;
+	      int m_loc_fst = m/commSize;
+	      int m_loc;
+	      if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+		m_loc = m-m_loc_fst*( commSize-1 );
+	      else
+		m_loc = m_loc_fst;
+	      
+	      int fst_row= myidpar*m_loc_fst;
+	      nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	      
+	      // allocation des tableaux
+	      irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      a_loc    = (Complex*) malloc(sizeof(Complex)*nz_loc);
+	      
+	      int fst_nnz = AA.lg[fst_row];
+	      for(int ii=0; ii < nz_loc; ii++){
+		a_loc[ii] = AA.a[fst_nnz+ii];
+		jcn_loc[ii] = AA.cl[fst_nnz+ii]; // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	      }
+	      
+	      for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+		for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		  irn_loc[ii1-fst_nnz] = ii+1;  
+	      }
+	      
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = mumps_dc(a_loc);
+	    }
+	  }
+	  if(PAR == 1){
+
+	    int commSize;	    
+	    ierr=MPI_Comm_size(comm,&commSize);
+	    int m_loc_fst = m/commSize;
+	    int m_loc;
+	    if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	      m_loc = m-m_loc_fst*( commSize-1 );
+	    else
+	      m_loc = m_loc_fst;
+	    
+	    int fst_row= myid*m_loc_fst;
+	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+	    // allocation des tableaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (Complex*) malloc(sizeof(Complex)*nz_loc);
+	    
+	    int fst_nnz = AA.lg[fst_row];
+	    for(int ii=0; ii < nz_loc; ii++){
+	      a_loc[ii] = AA.a[fst_nnz+ii];
+	      jcn_loc[ii] = AA.cl[fst_nnz+ii];  // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	    }
+	    
+	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+	      for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		irn_loc[ii1-fst_nnz] = ii+1;  
+	    }
+	  
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = mumps_dc(a_loc);
+
+	  }
+
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  zmumps_c(&id);
+	}
+      }
+	
+    if( id.ICNTL(18) == 3 )
+      {	
+	// indices et colonnes de la matrice
+	
+// 	//  Cas Matrice parallele ::
+// 	//  ========================
+//	
+// 	// Cas stockage Morse parallele
+// 	m_loc = AA.m_loc;       // Nombre de lignes prise en compte
+// 	nz_loc = AA.nbcoef_loc;   // Nombre de coefficients non nulles 
+// 	// indice des colonnes
+// 	jcn_loc = AA.cl_loc;       // indices des colonnes dans la matrice locale
+//	
+// 	if( !(irn_loc = (int*) malloc(sizeof(int)*nz_loc)) ){
+// 	  printf("problem allocation jcn ");
+// 	  exit(1);
+// 	}
+// 	assert(AA.lg_loc[nrow_loc] == nz_loc);
+// 	for(int ii=0; ii< nrow_loc; ii++)
+// 	  for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 	    irn_loc[ii1] = ii+1;
+//
+// 	a_loc=AA.a_loc;
+//
+	// Pas de matrice parallele ==> utilisation astuce de SuperLU
+	// Matrice :: distribution bloc continue de lignes :: voir SuperLU 
+	// Attention :: performance ???
+	
+
+	cout <<"id.ICNTL(18) = 3,  PAR="<< PAR << endl;
+
+	 if(PAR == 0){ 
+// 	    if(myid !=0) {
+// 	      int commSize;	    
+// 	      ierr=MPI_Comm_size(comm,&commSize);
+// 	      commSize=commSize-1;
+// 	      int myidpar=myid-1;
+// 	      int m_loc_fst;
+// 	      m_loc_fst= m/commSize;
+// 	      int m_loc;
+// 	      if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+// 		m_loc = m-m_loc_fst*( commSize-1 );
+// 	      else
+// 		m_loc = m_loc_fst;
+//	      
+// 	      int fst_row;
+// 	      fst_row= myidpar*m_loc_fst;
+// 	      nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+//	      
+// 	      // allocation des tableaux
+// 	      irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	      jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	      a_loc    = (Complex*) malloc(sizeof(Complex)* nz_loc);
+//	      
+// 	      int fst_nnz;
+// 	      fst_nnz = AA.lg[fst_row];
+// 	      for(int ii=0; ii < nz_loc; ii++){
+// 		a_loc[ii] = AA.a[fst_nnz+ii];
+// 		jcn_loc[ii] = AA.cl[fst_nnz+ii]+1;
+// 	      }	      
+// 	      for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+// 		for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 		  irn_loc[ii1-fst_nnz] = ii+1;  
+// 	      }	      
+// 	      id.nz_loc = nz_loc;
+// 	      id.irn_loc = irn_loc;
+// 	      id.jcn_loc = jcn_loc;
+// 	      id.a_loc = mumps_dc(a_loc);
+// 	    }
+
+	    // definition de variables
+	  int commSize;
+	  int m_loc_fst;	 
+	  int m_loc;
+	  int fst_row;
+	  
+
+	  int *nz_loc_procs;
+	  int *fst_nz_procs;
+	  int *m_loc_procs;
+	  int *fst_row_procs;
+	 
+
+	  Complex *tab_a;
+	  int *tab_cl;
+	  int *tab_lg;
+	  int *tab_lg_loc;
+
+	  MPI_Comm_size(comm,&commSize);
+	  
+	  if( myid !=0){
+	    int commSizemm;
+	    int myidpar=myid-1;
+
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+	  
+	    if( myidpar == commSizemm-1 && ( m_loc_fst*commSizemm != m ) )  
+	      m_loc = m-m_loc_fst*( commSizemm-1 );
+	    else
+	      m_loc = m_loc_fst;
+	  
+	    if(verbosity > 5){
+	      fst_row = myidpar*m_loc_fst;
+	      cout << "   myid = " << myid << endl;
+	      cout <<"   m_loc = " << m_loc << endl;
+	      cout <<" fst_row = " << fst_row << endl;
+	    }
+
+	  }
+	  if( myid ==0){
+
+	    int commSizemm;
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+
+	    fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	    m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	    fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	    nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+	    
+	    
+	    fst_row_procs [0] = 0;
+	    m_loc_procs   [0] = 0;
+
+	    for( int ii= 1; ii<commSize; ii++){
+	      fst_row_procs [ii] = (ii-1)*m_loc_fst;
+	      m_loc_procs [ii] = m_loc_fst;
+	    }
+	    
+	    if( m_loc_fst*(commSize-1) != m ) 
+	      m_loc_procs [commSize-1] = m-m_loc_fst*( (commSize-1)-1 );
+
+
+	    nz_loc_procs [0] = 0;
+	    fst_nz_procs [0] = 0;
+	    
+	    for( int ii= 1; ii<commSize; ii++){
+	      nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	      fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	    }
+
+	   
+	    /*
+	      tab_a= (int* ) malloc( nz*sizeof(double) );
+	      tab_cl = (int* ) malloc( nz*sizeof(int) );
+	      tab_lg = (int* ) malloc ( n*sizeof(int) );
+	    */
+	    tab_a  = AA.a;
+	    tab_cl = AA.cl;
+	    tab_lg = AA.lg;
+	  }
+
+	  MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( m_loc_procs,  1, MPI_INT, &m_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( fst_row_procs,  1, MPI_INT, &fst_row, 1, MPI_INT, 0, comm);
+
+	  if(verbosity > 5){
+	    cout << "after scatter " << myid << endl;
+	    cout << "   myid = " << myid << endl;
+	    cout <<"   m_loc = " << m_loc << endl;
+	    cout <<" fst_row = " << fst_row << endl;
+	  }
+	  // allocation des tableaux locaux
+	  irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  a_loc    = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	  tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	  
+	
+
+	  MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	  MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	  MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	  
+	
+	  int jj=0;
+	  for(int  ii=0; ii<m_loc-1; ii++)
+	    for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	      irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	    }
+	  
+	  for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	    irn_loc[jj] = fst_row+(m_loc-1)+1;
+	    jj++;
+	  }
+	  
+	  for(int ii=0; ii < nz_loc; ii++){	    
+	    jcn_loc[ii] = jcn_loc[ii]+1; 
+	  }
+
+	  assert( jj == nz_loc );
+	  
+	  free( tab_lg_loc );
+	  
+	  id.nz_loc = nz_loc;
+	  id.irn_loc = irn_loc;
+	  id.jcn_loc = jcn_loc;
+	  id.a_loc = mumps_dc(a_loc);
+	 
+	  if( myid == 0 ){
+	    free( fst_row_procs );
+	    free( m_loc_procs );
+	    free( fst_nz_procs );
+	    free( nz_loc_procs );
+	  }
+	   
+
+	 }
+	 if(PAR ==1) {
+	  
+	   
+// 	   int commSize;
+// 	   ierr=MPI_Comm_size(comm,&commSize);
+// 	   int m_loc_fst;
+// 	   m_loc_fst= m/commSize;
+// 	   int m_loc;
+// 	   if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+// 	     m_loc = m-m_loc_fst*( commSize-1 );
+// 	   else
+// 	     m_loc = m_loc_fst;
+//	   
+// 	   int fst_row;
+// 	   fst_row = myid*m_loc_fst;
+// 	   nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+//	    
+// 	   allocation des tableaux
+// 	   irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	   jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	   a_loc    = (Complex*) malloc(sizeof(Complex)*nz_loc);
+//	   
+// 	   int fst_nnz;
+// 	   fst_nnz= AA.lg[fst_row];
+// 	   for(int ii=0; ii < nz_loc; ii++){
+// 	     a_loc[ii] = AA.a[fst_nnz+ii];
+// 	     jcn_loc[ii] = AA.cl[fst_nnz+ii]+1; 
+// 	   }
+//   
+// 	   for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+// 	     for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 	       irn_loc[ii1-fst_nnz] = ii+1;  
+// 	   }
+//	   
+// 	   id.nz_loc = nz_loc;
+// 	   id.irn_loc = irn_loc;
+// 	   id.jcn_loc = jcn_loc;
+// 	   id.a_loc = mumps_dc(a_loc);
+
+	   // definition de variables
+	   int commSize;
+	   int m_loc_fst;	 
+	   int m_loc;
+	   int fst_row;
+	   
+
+	   int *nz_loc_procs;
+	   int *fst_nz_procs;
+	   int *m_loc_procs;
+	   int *fst_row_procs;
+	   
+	   
+	   Complex *tab_a;
+	   int *tab_cl;
+	   int *tab_lg;
+	   int *tab_lg_loc;
+	   
+	   MPI_Comm_size(comm,&commSize);
+	   m_loc_fst= m/commSize;
+	   
+	   if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	     m_loc = m-m_loc_fst*( commSize-1 );
+	   else
+	     m_loc = m_loc_fst;	  
+	   
+	   fst_row = myid*m_loc_fst;
+	   
+	   if( myid ==0){
+	     fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	     m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	     fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	     nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+
+	     for( int ii= 0; ii<commSize; ii++){
+	       fst_row_procs [ii] = ii*m_loc_fst;
+	       m_loc_procs [ii] = m_loc_fst;
+	     }
+	     
+	     if( m_loc_fst*commSize != m ) 
+	       m_loc_procs [commSize-1] = m-m_loc_fst*( commSize-1 );
+	     
+	     for( int ii= 0; ii<commSize; ii++){
+	       nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	       fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	     }
+	     
+	     
+	     /*
+	       tab_a= (int* ) malloc( nz*sizeof(double) );
+	       tab_cl = (int* ) malloc( nz*sizeof(int) );
+	       tab_lg = (int* ) malloc ( n*sizeof(int) );
+	     */
+	     tab_a  = AA.a;
+	     tab_cl = AA.cl;
+	     tab_lg = AA.lg;
+	   }
+	   
+	   MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  
+	   // allocation des tableaux locaux
+	   irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	   jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	   a_loc    = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	   tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	   
+	   MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	   MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	   MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	
+	   int jj=0;
+	   for(int  ii=0; ii<m_loc-1; ii++)
+	     for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	       irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	     }
+	   
+	   for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	     irn_loc[jj] = fst_row+(m_loc-1)+1;
+	     jj++;
+	   }
+	   
+	   for(int ii=0; ii < nz_loc; ii++){	    
+	     jcn_loc[ii] = jcn_loc[ii]+1; 
+	   }
+	   
+	   assert( jj == nz_loc );
+	   
+	   free( tab_lg_loc );
+	   
+	   id.nz_loc  = nz_loc;
+	   id.irn_loc = irn_loc;
+	   id.jcn_loc = jcn_loc;
+	   id.a_loc = mumps_dc(a_loc);
+	 
+	   if( myid == 0 ){
+	     free( fst_row_procs );
+	     free( m_loc_procs );
+	     free( fst_nz_procs );
+	     free( nz_loc_procs );
+	   }
+	   
+
+	 }
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation
+	 
+	 id.job=1;
+	 zmumps_c(&id);
+
+	 id.job=2;
+	 zmumps_c(&id);
+      }
+    
+    
+    
+
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if( jcn != NULL )
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+
+    if( irn != NULL ) free(irn); 
+ 
+
+    if( verbosity >1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Factorisation ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+    if( verbosity){
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << "MUMPS : time factorisation :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+    }
+        
+  
+  }
+
+  void Solver(const MatriceMorse<Complex> &AA,KN_<Complex> &x,const KN_<Complex> &b) const  {
+    long int starttime,finishtime;
+    long int timeused;
+    //*******************************************************************//
+    //    depend pas de la forme de la matrice: distribuer ou assembler
+    Complex *rhs;
+    int job;
+    
+    if(verbosity) starttime = clock();
+
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+  
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]+1;
+    
+    if ( !(rhs = (Complex*) malloc(sizeof(Complex)*m) ) ){
+      printf("Pb allocate rhs in MUMPS\n");
+      exit(1);
+    }
+   
+    for(int ii=0; ii<m; ++ii){
+      rhs[ii] = b[ii];
+    }
+
+    if( myid == 0 )
+      id.rhs=mumps_dc(rhs);
+
+    /* solve linear problem */
+    id.job=3;
+    zmumps_c(&id);
+
+   
+    if( myid==0 ){
+      x=inv_mumps_dc(id.rhs); 
+      MPI_Bcast( x,  n, MPI_DOUBLE_COMPLEX,  0, comm );
+    }
+    else
+      MPI_Bcast( x,  n, MPI_DOUBLE_COMPLEX,  0, comm );
+    
+  
+    
+    // deallocation de rhs
+    free(rhs);
+
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+
+
+    if( verbosity > 1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Solving       ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+
+    if(verbosity)
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << " MUMPS : time solve  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+    
+  }
+
+  ~zSolveMUMPSmpi() { 
+    //*******************************************************************//
+    //    depend pas de la forme de la matrice: distribuer ou assembler
+    if(verbosity)
+      cout << "~SolveMUMPS Z:" << endl;
+    
+     id.job=JOB_END; 
+     zmumps_c(&id); /* Terminate instance */
+     
+  }
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+     
+}; 
+
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverMUMPSmpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+      cout << " BuildSolverMUMPS<double>" << endl;
+    return new dSolveMUMPSmpi(*A,ds.strategy, ds.tgv, ds.epsilon, ds.tol_pivot, ds.tol_pivot_sym, ds.sparams, ds.data_filename,
+			      ds.lparams, ds.dparams, ds.perm_r, ds.perm_c, ds.scale_r, ds.scale_c,(MPI_Comm *)ds.commworld);
+}
+
+
+
+
+MatriceMorse<Complex>::VirtualSolver *
+BuildSolverMUMPSmpi(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+    if(verbosity>9)
+      cout << " BuildSolverMUMPS<Complex>" << endl;
+    return new zSolveMUMPSmpi(*A,ds.strategy, ds.tgv, ds.epsilon, ds.tol_pivot, ds.tol_pivot_sym, ds.sparams, ds.data_filename,  
+			      ds.lparams, ds.dparams, ds.perm_r, ds.perm_c, ds.scale_r, ds.scale_c,(MPI_Comm *)ds.commworld);
+}
+
+
+/*  class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+static DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; 
+static DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+static TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+}
+
+bool SetMUMPSmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to MUMPSmpi" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverMUMPSmpi;
+    DefSparseSolver<Complex>::solver =BuildSolverMUMPSmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+}
+
+
+
+//LOADINIT(Init);
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: MUMPS ,  defaultsolver defaultsolverMUMPS " << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverMUMPSmpi;
+  DefSparseSolver<Complex>::solver =BuildSolverMUMPSmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoMUMPS","(",new OneOperator0<bool>(SetMUMPSmpi));
+}
+
+
+void ffinit()
+{
+
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+
+  if(verbosity>1)
+    cout << "\n Add: MUMPS ,  defaultsolver defaultsolverMUMPS " << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverMUMPSmpi;
+  DefSparseSolver<Complex>::solver =BuildSolverMUMPSmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoMUMPS","(",new OneOperator0<bool>(SetMUMPSmpi));
+}
+#include "InitFunct.hpp"
+addingInitFunct FFinit(100,ffinit,"MUMPS_FreeFem");
+
+LOADFUNC(Load_Init);
diff --git a/examples++-mpi/Makefile.am b/examples++-mpi/Makefile.am
new file mode 100644
index 0000000..dd2f2d3
--- /dev/null
+++ b/examples++-mpi/Makefile.am
@@ -0,0 +1,112 @@
+# ======================================================================
+# Laboratoire Jacques-Louis Lions
+# Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+# http://www.ljll.math.upmc.fr/lehyaric
+# ======================================================================
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+# 
+# Freefem++ is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+# ======================================================================
+# headeralh default=0 freefem make multipleauthors start=19/03/10 upmc
+
+TESTS=  schwarz.edp DDM-Schwarz-Lame-2d.edp DDM-Schwarz-Lame-3d.edp DDM-Schwarz-Lap-2dd.edp DDM-Schwarz-Lap-3d.edp	\
+	DDM-Schwarz-Stokes-2d.edp LaplaceRT-3d-matrix-mumps.edp MPICGLap.edp MPIGMRES2D.edp MPIGMRES3D.edp MUMPS.edp	\
+	NSI3d-carac-mumps.edp NSI3d-carac.edp Stokes-v1-matrix-mumps.edp Stokes-v1-matrix-superludist.edp		\
+	Stokes-v2-matrix-mumps.edp Stokes-v3-matrix-mumps.edp VG.edp beam-3d-matrix-superludist.edp			\
+	cavityNewtow-MUMPS.edp chaleur3D-hips.edp chaleur3D-mumps.edp chaleur3D-superludist.edp cmaes-mpi-VarIneq.edp	\
+	essai.edp mortar-DN-4-mpi.edp testsolver_MUMPS.edp testsolver_SuperLU_DIST.edp testsolver_pastix.edp
+
+XFAIL_TESTS=$(TESTS)
+
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPPMPI) FLAGS_FFPP="-np 4 -nw" SKIP=$(SKIP_TESTS_MPI)
+
+LIST_IDP= AddLayer2d.idp		DDM-Schwarz-macro.idp	MPIGMRESmacro.idp	getARGV.idp \
+AddLayer3d.idp		DDM-funcs-v2.idp	MPIplot.idp		mortar-msh.idp Heat3d.idp
+
+EXTRA_DIST=*.edp *.idp  regtests.sh  \
+MPICG.cpp \
+MUMPS_FreeFem.cpp \
+complex_SuperLU_DIST_FreeFem.cpp \
+complex_pastix_FreeFem.cpp \
+dSuperLU_DIST.cpp \
+ffsuperludistoption-1.hpp \
+ffsuperludistoption.hpp \
+generaldefs.h \
+hips_FreeFem.cpp \
+hypre_FreeFem.cpp \
+interfacepastix.cpp \
+parms_FreeFem.cpp \
+real_SuperLU_DIST_FreeFem.cpp \
+real_pastix_FreeFem.cpp mpi-cmaes.cpp \
+ffmumps_fileparam.txt		ffpastix_iparm_dparm.txt	ffsuperlu_dist_fileparam.txt \
+MUMPS.cpp   \
+MUMPS.edp  dmatrix.hpp  \
+PETSc.hpp additional.idp removeDOF.cpp schwarz.cpp schwarz.edp stokes-2d.edp utility.cpp schwarz-2d.edp
+
+# FFCS - list modified to disable some downloaded tools depending on the platform (see
+# [[file:../../../configure.ac::tools_problems_all_platforms]] for reasons why some tools may be
+# deactivated).
+
+LIST_COMPILE=@TOOL_DYLIB_mumps@ @TOOL_DYLIB_hips@ @TOOL_DYLIB_superludist@ @TOOL_DYLIB_pastix@ MPICG.$(DYLIB_SUFFIX)	\
+ at TOOL_DYLIB_parms@ mpi-cmaes.$(DYLIB_SUFFIX) @TOOL_DYLIB_schwarz@
+
+if FFCS_MPIOK
+
+# FFCS - do not set loadpath to be able to run an external version of FF on the examples in this directory with
+# [[../../mkffref]]
+
+all-local:$(LIST_COMPILE)
+	@echo Warning missing mpi plugin: `for i in $(LIST_COMPILE); do if test ! -s $i ; then j=1; echo "$i," ;fi; done`
+	echo "finish compile load mpi solver !"
+else
+all-local:
+endif
+
+.cpp.$(DYLIB_SUFFIX): ../examples++-load/ff-c++ ../examples++-load/WHERE_LIBRARY-download
+#	FFCS needs an error exit code to make sure that all libraries are correctly compiled
+#
+#	FFCS on Windows inserts all MPI options (include, lib, ...) in the $MPICXX compiler script, instead of "$CXX $MPI_xxx",
+#	but it needs '-mpi' to do that
+#
+###	-../examples++-load/ff-c++ -auto  $< 
+	../examples++-load/ff-c++ -auto -mpi $<
+
+install-exec-local:: 
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/lib/mpi
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/include
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/etc
+	-for i in $(LIST_COMPILE); do \
+	 if [ -f $$i ] ; then 	$(INSTALL)  -m 555 $$i $(DESTDIR)$(ff_prefix_dir)/lib/mpi; fi; done
+	$(INSTALL)  -m 555  $(LIST_IDP)  $(DESTDIR)$(ff_prefix_dir)/idp
+
+
+freefem++.pref:Makefile
+	echo loadpath = \"../examples++-load/\" >freefem++.pref
+	echo includepath = \"../examples++-3d/\" >>freefem++.pref
+	echo includepath += \"../examples++-tutorial/\" >>freefem++.pref
+	echo loadpath += \"./\" >>freefem++.pref
+# force the build for freefem++.pref  FH.. 
+DDM-Schwarz-Lame-2d.edp:freefem++.pref
+# FFCS - cleaning is useful sometimes
+clean-local::
+	-rm *.$(DYLIB_SUFFIX)
+	-rm *.$(OBJEXT)
+
+# Local Variables:
+# mode:makefile
+# ispell-local-dictionary:"british"
+# coding:utf-8
+# End:
diff --git a/examples++-mpi/NSI3d-carac-mumps.edp b/examples++-mpi/NSI3d-carac-mumps.edp
new file mode 100644
index 0000000..0a50f58
--- /dev/null
+++ b/examples++-mpi/NSI3d-carac-mumps.edp
@@ -0,0 +1,154 @@
+load "msh3"
+load "MUMPS_FreeFem"
+////////////////////
+//  parameters
+
+real ttgv=1e30;
+string ssparams="nprow=1, npcol="+mpisize;
+////////////////////
+real nu=0.01,dt=0.3;
+real alpha=1./dt,alpha2=sqrt(alpha);
+
+int nn=10;
+
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  // region=r1, 
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+fespace VVh(Th,[P23d,P23d,P23d,P13d]);
+fespace Vh(Th,P23d);
+fespace Ph(Th,P13d);
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+  
+cout << "initilisation" << endl;
+
+real t1,t2,t3,t4;
+
+t1=clock();
+varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3) //' for emacs
+             - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+ + on(2,u1=1.,u2=0,u3=0)
+ + on(1,u1=0,u2=0,u3=0)
+ ;
+matrix A=vStokes( VVh, VVh, tgv=ttgv, sparams=ssparams );
+t1=clock()-t1;
+
+t4=clock();
+set(A,solver=sparsesolver, sparams=ssparams );
+t4=clock()-t4;
+
+t2=clock();
+real[int] b= vStokes(0,VVh);
+t2=clock()-t2;
+
+VVh [u1,u2,u3,p];
+VVh [X1,X2,X3,Xp];
+VVh [x1,x2,x3,xp]=[x,y,z,0];
+
+t3=clock();
+u1[]= A^-1 * b;
+t3=clock()-t3;
+
+ux= u1(x,0.5,y);
+uz= u3(x,0.5,y);
+p2= p(x,0.5,y);
+plot([ux,uz],p2,cmm=" cut y = 0.5",wait=1);
+macro XX1() (x-u1*dt)//
+macro XX2() (y-u2*dt)//
+macro XX3() (z-u3*dt)//
+
+  varf vNS([uu1,uu2,uu3,p],[v1,v2,v3,q]) = 
+  int3d(Th)( alpha*(uu1*v1+uu2*v2+uu3*v3) + nu*(Grad(uu1)'*Grad(v1) +  Grad(uu2)'*Grad(v2) +  Grad(uu3)'*Grad(v3)) //' for emacs
+  - div(uu1,uu2,uu3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,uu1=1,uu2=0,uu3=0)
+  + on(1,uu1=0,uu2=0,uu3=0)
+ 
+  +  int3d(Th,optimize=1,qforder=4)(   alpha*(  convect([u1,u2,u3],-dt,u1)*v1  +   convect([u1,u2,u3],-dt,u2)*v2  +   convect([u1,u2,u3],-dt,u3)*v3 )  ) ;
+  //   +  int3d(Th,optimize=1)(   alpha*(  u1(X1,X2,X3)*v1  +  u2(X1,X2,X3)*v2  +  u3(X1,X2,X3)*v3 )  ) ;
+//  +  int3d(Th,optimize=1)(   alpha*(  u1(XX1,XX2,XX3)*v1  +  u2(XX1,XX2,XX3)*v2  +  u3(XX1,XX2,XX3)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1(x,y,z)*v1  +  u2(x,y,z)*v2  +  u3(x,y,z)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1*v1  +  u2*v2  +  u3*v3 )  ) ;
+
+real time1,time2=0.,time3=0.,time4,time5;
+
+time1=clock();
+A = vNS( VVh, VVh, tgv=ttgv, sparams=ssparams);
+time1=clock()-time1;
+
+time5=clock();
+set(A,solver=sparsesolver,sparams=ssparams);
+time5=clock()-time5;
+
+time4=clock();
+real t=0;
+int nbtemps=5;
+for(int i=0;i<nbtemps;++i)
+  {
+    real time2tmp,time3tmp;
+    t += dt;
+    cout << " iteration " << i << " t = " << t << endl;
+    X1[]=x1[]+u1[]*(-dt);
+    //    verbosity=1000;
+
+    time2tmp=clock();
+    b=vNS(0,VVh);
+    time2=time2+(clock()-time2tmp);
+
+    time3tmp=clock();
+    u1[]= A^-1 * b;
+    time3=time3+(clock()-time3tmp);
+
+    ux= u1(x,0.5,y);
+    uz= u3(x,0.5,y);
+    p2= p(x,0.5,y);
+    plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=0);
+    if(i%5==6)
+    {
+      //exec("mkdir dd");
+      string prefu="dd/pastix-nn-"+nn+"+u-"+(100+i);
+      string prefp="dd/pastix-nn-"+nn+"p-"+(100+i);
+      savemesh(Th,prefu+".mesh");
+      savemesh(Th,prefp+".mesh");
+     
+      ofstream file(prefu+".bb"); 
+      ofstream filep(prefp+".bb"); 
+      Ph up1=u1,up2=u2,up3=u3,pp=p;
+      file << "3 1 3 "<< up1[].n << " 2 \n";
+      filep << "3 1 1 "<< pp[].n << " 2 \n";
+      for (int j=0;j<up1[].n ; j++)  
+	{
+	  file << up1[][j] <<" " <<up2[][j] <<" "<< up3[][j] <<"\n";
+	  filep << pp[][j] <<  endl; 
+	}  
+    }
+  }
+time4=clock()-time4;
+
+//plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=1);
+cout << "============ CPU TIME ==========================" << endl;
+cout << "= Intialisation Stokes :::         =" << endl;
+cout << "= matrix                           =" << t1<< endl;
+cout << "= Factorization                    =" << t4 << endl; 
+cout << "= second member                    =" << t2 << endl;
+cout << "= solving                          =" << t3<< endl;
+cout << "= all                              =" << t1+t2+t3+t4 << endl; 
+cout << "============ CPU TIME ==========================" << endl;
+cout << "= Navier Stokes :::                =" << endl;
+cout << "= matrix                           =" << time1<< endl;
+cout << "= Factorization                    =" << time5 << endl; 
+cout << "= second member by step (dt)       =" << time2/nbtemps << endl;
+cout << "= solving by step (dt)             =" << time3/nbtemps<< endl;
+cout << "= all step solving                 =" << time4 << endl;
+cout << "= solving Navier Stokes            =" << time1+time2+time3+time4+time5 << endl; 
+cout << "============ CPU TIME ==========================" << endl;
\ No newline at end of file
diff --git a/examples++-mpi/NSI3d-carac-pastix.edp b/examples++-mpi/NSI3d-carac-pastix.edp
new file mode 100644
index 0000000..bb7927c
--- /dev/null
+++ b/examples++-mpi/NSI3d-carac-pastix.edp
@@ -0,0 +1,154 @@
+load "msh3"
+load "real_pastix_FreeFem"
+////////////////////
+//  parameters
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+////////////////////
+real nu=0.01,dt=0.3;
+real alpha=1./dt,alpha2=sqrt(alpha);
+
+int nn=10;
+
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  // region=r1, 
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+fespace VVh(Th,[P23d,P23d,P23d,P13d]);
+fespace Vh(Th,P23d);
+fespace Ph(Th,P13d);
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+  
+cout << "initilisation" << endl;
+
+real t1,t2,t3,t4;
+
+t1=clock();
+varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3) //' for emacs
+             - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+ + on(2,u1=1.,u2=0,u3=0)
+ + on(1,u1=0,u2=0,u3=0)
+ ;
+matrix A=vStokes( VVh, VVh, tgv=ttgv, sparams=ssparams );
+t1=clock()-t1;
+
+t4=clock();
+set(A,solver=sparsesolver, sparams=ssparams );
+t4=clock()-t4;
+
+t2=clock();
+real[int] b= vStokes(0,VVh);
+t2=clock()-t2;
+
+Vh [u1,u2,u3,p];
+VVh [X1,X2,X3,Xp];
+VVh [x1,x2,x3,xp]=[x,y,z,0];
+
+t3=clock();
+u1[]= A^-1 * b;
+t3=clock()-t3;
+
+ux= u1(x,0.5,y);
+uz= u3(x,0.5,y);
+p2= p(x,0.5,y);
+plot([ux,uz],p2,cmm=" cut y = 0.5",wait=1);
+macro XX1() (x-u1*dt)//
+macro XX2() (y-u2*dt)//
+macro XX3() (z-u3*dt)//
+
+  varf vNS([uu1,uu2,uu3,p],[v1,v2,v3,q]) = 
+  int3d(Th)( alpha*(uu1*v1+uu2*v2+uu3*v3) + nu*(Grad(uu1)'*Grad(v1) +  Grad(uu2)'*Grad(v2) +  Grad(uu3)'*Grad(v3)) //' for emacs
+  - div(uu1,uu2,uu3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,uu1=1,uu2=0,uu3=0)
+  + on(1,uu1=0,uu2=0,uu3=0)
+ 
+  +  int3d(Th,optimize=1,qforder=4)(   alpha*(  convect([u1,u2,u3],-dt,u1)*v1  +   convect([u1,u2,u3],-dt,u2)*v2  +   convect([u1,u2,u3],-dt,u3)*v3 )  ) ;
+  //   +  int3d(Th,optimize=1)(   alpha*(  u1(X1,X2,X3)*v1  +  u2(X1,X2,X3)*v2  +  u3(X1,X2,X3)*v3 )  ) ;
+//  +  int3d(Th,optimize=1)(   alpha*(  u1(XX1,XX2,XX3)*v1  +  u2(XX1,XX2,XX3)*v2  +  u3(XX1,XX2,XX3)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1(x,y,z)*v1  +  u2(x,y,z)*v2  +  u3(x,y,z)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1*v1  +  u2*v2  +  u3*v3 )  ) ;
+
+real time1,time2=0.,time3=0.,time4,time5;
+
+time1=clock();
+A = vNS( VVh, VVh, tgv=ttgv, sparams=ssparams);
+time1=clock()-time1;
+
+time5=clock();
+set(A,solver=sparsesolver,sparams=ssparams);
+time5=clock()-time5;
+
+time4=clock();
+real t=0;
+int nbtemps=10;
+for(int i=0;i<nbtemps;++i)
+  {
+    real time2tmp,time3tmp;
+    t += dt;
+    cout << " iteration " << i << " t = " << t << endl;
+    X1[]=x1[]+u1[]*(-dt);
+    //    verbosity=1000;
+
+    time2tmp=clock();
+    b=vNS(0,VVh);
+    time2=time2+(clock()-time2tmp);
+
+    time3tmp=clock();
+    u1[]= A^-1 * b;
+    time3=time3+(clock()-time3tmp);
+
+    ux= u1(x,0.5,y);
+    uz= u3(x,0.5,y);
+    p2= p(x,0.5,y);
+    plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=0);
+    if(i%5==6)
+    {
+      //exec("mkdir dd");
+      string prefu="dd/pastix-nn-"+nn+"+u-"+(100+i);
+      string prefp="dd/pastix-nn-"+nn+"p-"+(100+i);
+      savemesh(Th,prefu+".mesh");
+      savemesh(Th,prefp+".mesh");
+     
+      ofstream file(prefu+".bb"); 
+      ofstream filep(prefp+".bb"); 
+      Ph up1=u1,up2=u2,up3=u3,pp=p;
+      file << "3 1 3 "<< up1[].n << " 2 \n";
+      filep << "3 1 1 "<< pp[].n << " 2 \n";
+      for (int j=0;j<up1[].n ; j++)  
+	{
+	  file << up1[][j] <<" " <<up2[][j] <<" "<< up3[][j] <<"\n";
+	  filep << pp[][j] <<  endl; 
+	}  
+    }
+  }
+time4=clock()-time4;
+
+//plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=1);
+cout << "============ CPU TIME ==========================" << endl;
+cout << "= Intialisation Stokes :::         =" << endl;
+cout << "= matrix                           =" << t1<< endl;
+cout << "= Factorization                    =" << t4 << endl; 
+cout << "= second member                    =" << t2 << endl;
+cout << "= solving                          =" << t3<< endl;
+cout << "= all                              =" << t1+t2+t3+t4 << endl; 
+cout << "============ CPU TIME ==========================" << endl;
+cout << "= Navier Stokes :::                =" << endl;
+cout << "= matrix                           =" << time1<< endl;
+cout << "= Factorization                    =" << time5 << endl; 
+cout << "= second member by step (dt)       =" << time2/nbtemps << endl;
+cout << "= solving by step (dt)             =" << time3/nbtemps<< endl;
+cout << "= all step solving                 =" << time4 << endl;
+cout << "= solving Navier Stokes            =" << time1+time2+time3+time4+time5 << endl; 
+cout << "============ CPU TIME ==========================" << endl;
\ No newline at end of file
diff --git a/examples++-mpi/NSI3d-carac-superludist.edp b/examples++-mpi/NSI3d-carac-superludist.edp
new file mode 100644
index 0000000..3f41a81
--- /dev/null
+++ b/examples++-mpi/NSI3d-carac-superludist.edp
@@ -0,0 +1,154 @@
+load "msh3"
+load "real_SuperLU_DIST_FreeFem"
+////////////////////
+//  parameters
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+////////////////////
+real nu=0.01,dt=0.3;
+real alpha=1./dt,alpha2=sqrt(alpha);
+
+int nn=10;
+
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);
+Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],
+  // region=r1, 
+  labelmid=rmid, 
+  reffaceup = rup,
+  reffacelow = rdown);
+
+fespace VVh(Th,[P23d,P23d,P23d,P13d]);
+fespace Vh(Th,P23d);
+fespace Ph(Th,P13d);
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+  
+cout << "initilisation" << endl;
+
+real t1,t2,t3,t4;
+
+t1=clock();
+varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3) //' for emacs
+             - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+ + on(2,u1=1.,u2=0,u3=0)
+ + on(1,u1=0,u2=0,u3=0)
+ ;
+matrix A=vStokes( VVh, VVh, tgv=ttgv, sparams=ssparams );
+t1=clock()-t1;
+
+t4=clock();
+set(A,solver=sparsesolver, sparams=ssparams );
+t4=clock()-t4;
+
+t2=clock();
+real[int] b= vStokes(0,VVh);
+t2=clock()-t2;
+
+VVh [u1,u2,u3,p];
+VVh [X1,X2,X3,Xp];
+VVh [x1,x2,x3,xp]=[x,y,z,0];
+
+t3=clock();
+u1[]= A^-1 * b;
+t3=clock()-t3;
+
+ux= u1(x,0.5,y);
+uz= u3(x,0.5,y);
+p2= p(x,0.5,y);
+plot([ux,uz],p2,cmm=" cut y = 0.5",wait=1);
+macro XX1() (x-u1*dt)//
+macro XX2() (y-u2*dt)//
+macro XX3() (z-u3*dt)//
+
+  varf vNS([uu1,uu2,uu3,p],[v1,v2,v3,q]) = 
+  int3d(Th)( alpha*(uu1*v1+uu2*v2+uu3*v3) + nu*(Grad(uu1)'*Grad(v1) +  Grad(uu2)'*Grad(v2) +  Grad(uu3)'*Grad(v3)) //' for emacs
+  - div(uu1,uu2,uu3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,uu1=1,uu2=0,uu3=0)
+  + on(1,uu1=0,uu2=0,uu3=0)
+ 
+  +  int3d(Th,optimize=1,qforder=4)(   alpha*(  convect([u1,u2,u3],-dt,u1)*v1  +   convect([u1,u2,u3],-dt,u2)*v2  +   convect([u1,u2,u3],-dt,u3)*v3 )  ) ;
+  //   +  int3d(Th,optimize=1)(   alpha*(  u1(X1,X2,X3)*v1  +  u2(X1,X2,X3)*v2  +  u3(X1,X2,X3)*v3 )  ) ;
+//  +  int3d(Th,optimize=1)(   alpha*(  u1(XX1,XX2,XX3)*v1  +  u2(XX1,XX2,XX3)*v2  +  u3(XX1,XX2,XX3)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1(x,y,z)*v1  +  u2(x,y,z)*v2  +  u3(x,y,z)*v3 )  ) ;
+//+  int3d(Th,optimize=1)(   alpha*(  u1*v1  +  u2*v2  +  u3*v3 )  ) ;
+
+real time1,time2=0.,time3=0.,time4,time5;
+
+time1=clock();
+A = vNS( VVh, VVh, tgv=ttgv, sparams=ssparams);
+time1=clock()-time1;
+
+time5=clock();
+set(A,solver=sparsesolver,sparams=ssparams);
+time5=clock()-time5;
+
+time4=clock();
+real t=0;
+int nbtemps=5;
+for(int i=0;i<nbtemps;++i)
+  {
+    real time2tmp,time3tmp;
+    t += dt;
+    cout << " iteration " << i << " t = " << t << endl;
+    X1[]=x1[]+u1[]*(-dt);
+    //    verbosity=1000;
+
+    time2tmp=clock();
+    b=vNS(0,VVh);
+    time2=time2+(clock()-time2tmp);
+
+    time3tmp=clock();
+    u1[]= A^-1 * b;
+    time3=time3+(clock()-time3tmp);
+
+    ux= u1(x,0.5,y);
+    uz= u3(x,0.5,y);
+    p2= p(x,0.5,y);
+    plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=0);
+    if(i%5==6)
+    {
+      //exec("mkdir dd");
+      string prefu="dd/pastix-nn-"+nn+"+u-"+(100+i);
+      string prefp="dd/pastix-nn-"+nn+"p-"+(100+i);
+      savemesh(Th,prefu+".mesh");
+      savemesh(Th,prefp+".mesh");
+     
+      ofstream file(prefu+".bb"); 
+      ofstream filep(prefp+".bb"); 
+      Ph up1=u1,up2=u2,up3=u3,pp=p;
+      file << "3 1 3 "<< up1[].n << " 2 \n";
+      filep << "3 1 1 "<< pp[].n << " 2 \n";
+      for (int j=0;j<up1[].n ; j++)  
+	{
+	  file << up1[][j] <<" " <<up2[][j] <<" "<< up3[][j] <<"\n";
+	  filep << pp[][j] <<  endl; 
+	}  
+    }
+  }
+time4=clock()-time4;
+
+//plot([ux,uz],p2,cmm=" cut y = 0.5, time ="+t,wait=1);
+cout << "============ CPU TIME ==========================" << endl;
+cout << "= Intialisation Stokes :::         =" << endl;
+cout << "= matrix                           =" << t1<< endl;
+cout << "= Factorization                    =" << t4 << endl; 
+cout << "= second member                    =" << t2 << endl;
+cout << "= solving                          =" << t3<< endl;
+cout << "= all                              =" << t1+t2+t3+t4 << endl; 
+cout << "============ CPU TIME ==========================" << endl;
+cout << "= Navier Stokes :::                =" << endl;
+cout << "= matrix                           =" << time1<< endl;
+cout << "= Factorization                    =" << time5 << endl; 
+cout << "= second member by step (dt)       =" << time2/nbtemps << endl;
+cout << "= solving by step (dt)             =" << time3/nbtemps<< endl;
+cout << "= all step solving                 =" << time4 << endl;
+cout << "= solving Navier Stokes            =" << time1+time2+time3+time4+time5 << endl; 
+cout << "============ CPU TIME ==========================" << endl;
\ No newline at end of file
diff --git a/examples++-mpi/NSI3d-carac.edp b/examples++-mpi/NSI3d-carac.edp
new file mode 100644
index 0000000..c84d0d6
--- /dev/null
+++ b/examples++-mpi/NSI3d-carac.edp
@@ -0,0 +1 @@
+cout << "\n\n empty file remove NSI3d-carac.edp\n\n" << endl;
diff --git a/examples++-mpi/PETSc.hpp b/examples++-mpi/PETSc.hpp
new file mode 100755
index 0000000..976ba44
--- /dev/null
+++ b/examples++-mpi/PETSc.hpp
@@ -0,0 +1,427 @@
+#include <mpi.h>
+#include <iostream>
+
+extern KN<String>* pkarg;
+
+#include "petsc.h"
+#if PETSC_VERSION_LT(3,6,0)
+#define MatCreateVecs MatGetVecs
+#endif
+
+class DistributedCSR {
+    public:
+        HpSchwarz<>*                _A;
+        Mat                     _petsc;
+        Vec                         _x;
+        unsigned int*             _num;
+        int*                       _ia;
+        int*                       _ja;
+        double*                     _c;
+        unsigned int            _first;
+        unsigned int             _last;
+        unsigned int           _global;
+        bool                     _free;
+        DistributedCSR() : _A(), _num(), _ia(), _ja(), _c(), _first(), _last() { };
+        ~DistributedCSR() {
+            VecDestroy(&_x);
+            MatDestroy(&_petsc);
+            delete [] _num;
+            if(_free) {
+                delete []  _ia;
+                delete []  _ja;
+                delete []   _c;
+            }
+            delete _A;
+        }
+};
+
+void finalizePETSc() {
+    PetscFinalize();
+}
+
+long initEmptyCSR(DistributedCSR* const&) {
+    return 0;
+}
+
+template<class Type>
+class initCSR_Op : public E_F0mps {
+    public:
+        Expression A;
+        Expression K;
+        Expression O;
+        Expression R;
+        Expression D;
+        static const int n_name_param = 1;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        initCSR_Op(const basicAC_F0& args, Expression param1, Expression param2, Expression param3, Expression param4, Expression param5) : A(param1), K(param2), O(param3), R(param4), D(param5) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+
+        AnyType operator()(Stack stack) const;
+};
+
+template<class Type>
+basicAC_F0::name_and_type initCSR_Op<Type>::name_param[] = {
+    {"bs", &typeid(long)}
+};
+
+template<class Type>
+class initCSR : public OneOperator {
+    public:
+        initCSR() : OneOperator(atype<DistributedCSR*>(), atype<DistributedCSR*>(), atype<Matrice_Creuse<double>*>(), atype<KN<long>*>(), atype<KN<KN<long>>*>(), atype<KN<double>*>()) { }
+
+        E_F0* code(const basicAC_F0& args) const {
+            return new initCSR_Op<Type>(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]), t[2]->CastTo(args[2]), t[3]->CastTo(args[3]), t[4]->CastTo(args[4]));
+        }
+};
+
+template<class Type>
+AnyType initCSR_Op<Type>::operator()(Stack stack) const {
+    DistributedCSR* ptA = GetAny<DistributedCSR*>((*A)(stack));
+    KN<KN<long>>* ptR = GetAny<KN<KN<long>>*>((*R)(stack));
+    KN<long>* ptO = GetAny<KN<long>*>((*O)(stack));
+    KN<double>* ptD = GetAny<KN<double>*>((*D)(stack));
+    long bs = nargs[0] ? GetAny<long>((*nargs[0])(stack)) : 1;
+    ptA->_A = new HpSchwarz<>;
+    MatriceMorse<double> *mA = static_cast<MatriceMorse<double>*>(&(*GetAny<Matrice_Creuse<double>*>((*K)(stack))->A));
+    if(ptO && ptA) {
+        HPDDM::MatrixCSR<double>* dA = new HPDDM::MatrixCSR<double>(mA->n, mA->m, mA->nbcoef, mA->a, mA->lg, mA->cl, mA->symetrique);
+        ptA->_A->Subdomain<double>::initialize(dA, STL<long>(*ptO), *ptR);
+    }
+    ptA->_A->HpSchwarz<>::initialize(*ptD);
+    if(!ptA->_num)
+        ptA->_num = new unsigned int[ptA->_A->getDof()];
+    double timing = MPI_Wtime();
+    ptA->_A->distributedNumbering(ptA->_num, ptA->_first, ptA->_last, ptA->_global);
+    if(mpirank == 0)
+        cout << " --- global numbering created (in " << MPI_Wtime() - timing << ")" << endl;
+    timing = MPI_Wtime();
+    ptA->_free = ptA->_A->distributedCSR(ptA->_num, ptA->_first, ptA->_last, ptA->_ia, ptA->_ja, ptA->_c);
+    MatCreate(PETSC_COMM_WORLD, &(ptA->_petsc));
+    if(bs > 1)
+        MatSetBlockSize(ptA->_petsc, bs);
+    MatSetSizes(ptA->_petsc, ptA->_last - ptA->_first, ptA->_last - ptA->_first, ptA->_global, ptA->_global);
+    if(mpisize > 1) {
+        MatSetType(ptA->_petsc, MATMPIAIJ);
+        MatMPIAIJSetPreallocationCSR(ptA->_petsc, ptA->_ia, ptA->_ja, ptA->_c);
+    }
+    else {
+        MatSetType(ptA->_petsc, MATSEQAIJ);
+        MatSeqAIJSetPreallocationCSR(ptA->_petsc, ptA->_ia, ptA->_ja, ptA->_c);
+    }
+    if(mA->symetrique)
+        MatSetOption(ptA->_petsc, MAT_SYMMETRIC, PETSC_TRUE);
+    if(mpirank == 0)
+        cout << " --- global CSR created (in " << MPI_Wtime() - timing << ")" << endl;
+    return ptA;
+}
+
+template<class Type>
+class setOptions_Op : public E_F0mps {
+    public:
+        Expression A;
+        static const int n_name_param = 2;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        setOptions_Op(const basicAC_F0& args, Expression param1) : A(param1) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+
+        AnyType operator()(Stack stack) const;
+};
+
+template<class Type>
+basicAC_F0::name_and_type setOptions_Op<Type>::name_param[] = {
+    {"sparams", &typeid(std::string*)},
+    {"nearnullspace", &typeid(FEbaseArrayKn<double>*)}
+};
+
+template<class Type>
+class setOptions : public OneOperator {
+    public:
+        setOptions() : OneOperator(atype<long>(), atype<DistributedCSR*>()) { }
+
+        E_F0* code(const basicAC_F0& args) const {
+            return new setOptions_Op<Type>(args, t[0]->CastTo(args[0]));
+        }
+};
+
+template<class Type>
+AnyType setOptions_Op<Type>::operator()(Stack stack) const {
+    DistributedCSR* ptA = GetAny<DistributedCSR*>((*A)(stack));
+    std::string* options = nargs[0] ? GetAny<std::string*>((*nargs[0])(stack)) : NULL;
+    if(options) {
+        std::vector<std::string> elems;
+        std::stringstream ss(*options);
+        std::string item;
+        while (std::getline(ss, item, ' '))
+            elems.push_back(item);
+        int argc = elems.size() + 1;
+        char** data = new char*[argc];
+        data[0] = new char[options->size() + argc]();
+        data[1] = data[0] + 1;
+        for(int i = 0; i < argc - 1; ++i) {
+            if(i > 0)
+                data[i + 1] = data[i] + elems[i - 1].size() + 1;
+            strcpy(data[i + 1], elems[i].c_str());
+        }
+        PetscOptionsInsert(&argc, &data, NULL);
+        delete [] *data;
+        delete [] data;
+    }
+    FEbaseArrayKn<double>* ptNS = nargs[1] ? GetAny<FEbaseArrayKn<double>*>((*nargs[1])(stack)) : 0;
+    int dim = 0;
+    if(ptNS)
+        dim = ptNS->N;
+    if(dim) {
+        Vec x;
+        MatCreateVecs(ptA->_petsc, &x, NULL);
+        Vec* ns;
+        VecDuplicateVecs(x, dim, &ns);
+        for(unsigned short i = 0; i < dim; ++i) {
+            double* x;
+            VecGetArray(ns[i], &x);
+            ptA->_A->distributedVec<0>(ptA->_num, ptA->_first, ptA->_last, *(ptNS->get(i)), x, ptA->_A->getDof());
+            VecRestoreArray(ns[i], &x);
+        }
+        MatNullSpace sp;
+        MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, dim, ns, &sp);
+        MatSetNearNullSpace(ptA->_petsc, sp);
+        MatNullSpaceDestroy(&sp);
+        if(ns)
+            VecDestroyVecs(dim, &ns);
+        delete [] ns;
+    }
+    return 0L;
+}
+
+long distributedNumbering(DistributedCSR* const& A, KN<double>* const& vec) {
+    if(!A->_num)
+        A->_num = new unsigned int[vec->n];
+    double timing = MPI_Wtime();
+    A->_A->distributedNumbering(A->_num, A->_first, A->_last, A->_global);
+    if(mpirank == 0)
+        cout << " --- global numbering created (in " << MPI_Wtime() - timing << ")" << endl;
+    for(int i = 0; i < vec->n; ++i)
+        vec->operator[](i) = A->_num[i];
+    return 0;
+}
+long renumberCSR(DistributedCSR* const& A, FEbaseArrayKn<double>* const& nullspace) {
+    double timing = MPI_Wtime();
+    A->_free = A->_A->distributedCSR(A->_num, A->_first, A->_last, A->_ia, A->_ja, A->_c);
+    MatCreate(PETSC_COMM_WORLD, &(A->_petsc));
+    MatSetSizes(A->_petsc, A->_last - A->_first, A->_last - A->_first, A->_global, A->_global);
+    MatSetBlockSize(A->_petsc, (nullspace->N == 3) ? 2 : ((nullspace->N == 6) ? 3 : 1));
+    MatSetType(A->_petsc, MATMPIAIJ);
+    MatMPIAIJSetPreallocationCSR(A->_petsc, A->_ia, A->_ja, A->_c);
+    MatSetOption(A->_petsc, MAT_SPD, PETSC_TRUE);
+    if(mpirank == 0)
+        cout << " --- global CSR created (in " << MPI_Wtime() - timing << ")" << endl;
+    int dim = nullspace->N;
+    if(dim) {
+        Vec x;
+        MatCreateVecs(A->_petsc, &x, NULL);
+        timing = MPI_Wtime();
+        Vec* ns;
+        VecDuplicateVecs(x, dim, &ns);
+        for(unsigned short i = 0; i < dim; ++i) {
+            double* x;
+            VecGetArray(ns[i], &x);
+            A->_A->distributedVec<0>(A->_num, A->_first, A->_last, *(nullspace->get(i)), x, A->_A->getDof());
+            VecRestoreArray(ns[i], &x);
+        }
+        MatNullSpace sp;
+        MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, dim, ns, &sp);
+        MatSetNearNullSpace(A->_petsc, sp);
+        if(mpirank == 0)
+            cout << " --- near null space set (in " << MPI_Wtime() - timing << ")" << endl;
+        MatNullSpaceDestroy(&sp);
+        if(ns)
+            VecDestroyVecs(dim, &ns);
+        delete [] ns;
+#if 0
+        PetscViewer viewer;
+        const Vec* vecs;
+        PetscViewerBinaryOpen(PETSC_COMM_WORLD, "A", FILE_MODE_WRITE, &viewer);
+        MatView(A->_petsc, viewer);
+        MatNullSpace mnull;
+        MatGetNearNullSpace(A->_petsc, &mnull);
+        MatNullSpaceGetVecs(mnull, NULL, &dim, &vecs);
+        for(unsigned short i = 0; i < dim; ++i)
+            VecView(vecs[i], viewer);
+        PetscViewerDestroy(&viewer);
+#endif
+    }
+    return 0;
+}
+long solvePETSc(DistributedCSR* const& A, KN<double>* const& in) {
+    KSP ksp;
+    Vec y;
+    double timing = MPI_Wtime();
+    KSPCreate(PETSC_COMM_WORLD, &ksp);
+    KSPSetOperators(ksp, A->_petsc, A->_petsc);
+    double eps = 1e-8;
+    PetscOptionsGetReal(NULL, "-eps", &eps, NULL);
+    int it = 100;
+    PetscOptionsGetInt(NULL, "-iter", &it, NULL);
+    KSPSetTolerances(ksp, eps, PETSC_DEFAULT, PETSC_DEFAULT, it);
+    KSPSetFromOptions(ksp);
+    KSPSetUp(ksp);
+    if(mpirank == 0)
+        cout << " --- PETSc preconditioner built (in " << MPI_Wtime() - timing << ")" << endl;
+    MatCreateVecs(A->_petsc, &(A->_x), &y);
+    double* x;
+    VecGetArray(A->_x, &x);
+    A->_A->distributedVec<0>(A->_num, A->_first, A->_last, *in, x, A->_A->getDof());
+    VecRestoreArray(A->_x, &x);
+    std::fill(static_cast<double*>(*in), static_cast<double*>(*in) + in->n, 0);
+    timing = MPI_Wtime();
+    KSPSolve(ksp, A->_x, y);
+    if(mpirank == 0)
+        cout << " --- system solved with PETSc (in " << MPI_Wtime() - timing << ")" << endl;
+    VecGetArray(y, &x);
+    A->_A->distributedVec<1>(A->_num, A->_first, A->_last, *in, x, A->_A->getDof());
+#if 0
+    Vec z;
+    MatCreateVecs(A->_petsc, &z, NULL);
+    MatMult(A->_petsc, y, z);
+    VecAXPY(z, -1, A->_x);
+    double err[2];
+    VecNorm(z, NORM_2, err);
+    VecNorm(A->_x, NORM_2, err + 1);
+    if(mpirank == 0)
+        std::cout << " --- PETSc error = " << err[0] << " / " << err[1] << std::endl;
+#endif
+    VecRestoreArray(y, &x);
+    VecDestroy(&y);
+    KSPDestroy(&ksp);
+    A->_A->Subdomain<double>::exchange(*in);
+    return 0;
+}
+
+class DistributedCSR_inv  { public:
+  DistributedCSR* A;
+  DistributedCSR_inv(DistributedCSR* AA) : A(AA) {assert(A);}
+  operator DistributedCSR& () const {return *A;}
+  operator DistributedCSR* () const {return A;}
+};
+
+class OneBinaryOperatorPETSc : public OneOperator {
+    public:
+        OneBinaryOperatorPETSc() : OneOperator(atype<DistributedCSR_inv>(), atype<DistributedCSR*>(), atype<long>()) { }
+        E_F0* code(const basicAC_F0 & args) const {
+            Expression p = args[1];
+            if(!p->EvaluableWithOutStack())
+                CompileError("A^p, The p must be a constant == -1, sorry");
+            long pv = GetAny<long>((*p)(NullStack));
+            if(pv != -1) {
+                char buf[100];
+                sprintf(buf, "A^%ld, The pow must be == -1, sorry", pv);
+                CompileError(buf);
+            }
+            return new E_F_F0<DistributedCSR_inv, DistributedCSR*>(Build<DistributedCSR_inv, DistributedCSR*>, t[0]->CastTo(args[0]));
+        }
+};
+
+
+template<class T, class U>
+class Inv {
+    public:
+        const T t;
+        const U u;
+        Inv(T v, U w) : t(v), u(w) {}
+        void solve(U out) const {
+            KSP ksp;
+            Vec y;
+            double timing = MPI_Wtime();
+            KSPCreate(PETSC_COMM_WORLD, &ksp);
+            KSPSetOperators(ksp, (*t)._petsc, (*t)._petsc);
+            double eps = 1e-8;
+            PetscOptionsGetReal(NULL, "-eps", &eps, NULL);
+            int it = 100;
+            PetscOptionsGetInt(NULL, "-iter", &it, NULL);
+            KSPSetTolerances(ksp, eps, PETSC_DEFAULT, PETSC_DEFAULT, it);
+            KSPSetFromOptions(ksp);
+            KSPSetUp(ksp);
+            if(mpirank == 0)
+                cout << " --- PETSc preconditioner built (in " << MPI_Wtime() - timing << ")" << endl;
+            MatCreateVecs((*t)._petsc, &((*t)._x), &y);
+            double* x;
+            VecGetArray((*t)._x, &x);
+            (*t)._A->template distributedVec<0>((*t)._num, (*t)._first, (*t)._last, static_cast<double*>(*u), x, (*t)._A->getDof());
+            VecRestoreArray((*t)._x, &x);
+            std::fill(static_cast<double*>(*out), static_cast<double*>(*out) + out->n, 0);
+            timing = MPI_Wtime();
+            KSPSolve(ksp, (*t)._x, y);
+            if(mpirank == 0)
+                cout << " --- system solved with PETSc (in " << MPI_Wtime() - timing << ")" << endl;
+            VecGetArray(y, &x);
+            (*t)._A->template distributedVec<1>((*t)._num, (*t)._first, (*t)._last, *out, x, (*t)._A->getDof());
+            VecRestoreArray(y, &x);
+            VecDestroy(&y);
+            KSPDestroy(&ksp);
+            (*t)._A->HPDDM::template Subdomain<double>::exchange(*out);
+        };
+};
+
+KN<double>* InvPETSc(KN<double>* Ax, Inv<DistributedCSR_inv, KN<double>*> A) {
+    A.solve(Ax);
+    return Ax;
+}
+
+template<class T, class U>
+class GMV {
+    public:
+        const T t;
+        const U u;
+        GMV(T v, U w) : t(v), u(w) {}
+        void prod(U x) const;
+};
+
+template<class U>
+class GMV<HpSchwarz<>*, U> {
+    public:
+        const HpSchwarz<>* t;
+        const U u;
+        GMV(HpSchwarz<>* v, U w) : t(v), u(w) {}
+        void prod(U x) const { t->GMV(*(this->u), *x); };
+};
+
+template<class R, class A, class B> R Build(A a, B b) {
+    return R(a, b);
+}
+
+template<class K>
+KN<K>* GlobalMV(KN<K>* Ax, GMV<HpSchwarz<>*, KN<K>*> A) {
+    A.prod(Ax);
+    return Ax;
+}
+
+template<class U>
+class GMV<DistributedCSR*, U> {
+    public:
+        const DistributedCSR* t;
+        const U u;
+        GMV(DistributedCSR* v, U w) : t(v), u(w) {}
+        void prod(U x) const {
+            Vec z;
+            Vec y;
+            MatCreateVecs(t->_petsc, &z, &y);
+            double* w;
+            VecGetArray(z, &w);
+            t->_A->distributedVec<0>(t->_num, t->_first, t->_last, *u, w, t->_A->getDof());
+            VecRestoreArray(z, &w);
+            MatMult(t->_petsc, z, y);
+            VecGetArray(y, &w);
+            t->_A->template distributedVec<1>(t->_num, t->_first, t->_last, *x, w, t->_A->getDof());
+            VecRestoreArray(y, &w);
+            VecDestroy(&y);
+            VecDestroy(&z);
+            t->_A->Subdomain<double>::exchange(*x);
+        };
+};
+KN<double>* GlobalMV(KN<double>* Ax, GMV<DistributedCSR*, KN<double>*> A) {
+    A.prod(Ax);
+    return Ax;
+}
diff --git a/examples++-mpi/Stokes-v1-matrix-mumps.edp b/examples++-mpi/Stokes-v1-matrix-mumps.edp
new file mode 100644
index 0000000..eda15da
--- /dev/null
+++ b/examples++-mpi/Stokes-v1-matrix-mumps.edp
@@ -0,0 +1,81 @@
+/*
+to change locatation of daynamic lib. set   freefem++.pref   file like :
+more freefem++.pref  
+loadpath = "../examples++-load/"
+loadpath += "./"
+*/
+
+load "msh3"
+//load "medit"
+load "MUMPS_FreeFem"
+include "getARGV.idp"
+
+verbosity=0;
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+
+
+int nn=getARGV("-n",15);
+int pplot=getARGV("-plot",0);
+
+
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+
+VVh [u1,u2,u3,p];
+VVh [v1,v2,v3,q];
+
+real timeI=mpiWtime();
+real time1=mpiWtime();
+varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3)   //' for emacs
+                  - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,u1=fup,u2=0,u3=0) + on(1,u1=0,u2=0,u3=0) ;
+
+
+matrix MStokes=vStokes(VVh,VVh,tgv=ttgv);
+cout << "size of matrix " << MStokes.n << " x " << MStokes.m << " nn nzero coef  = " << MStokes.nbcoef << endl;
+time1=mpiWtime()-time1;
+
+real timeF=mpiWtime();
+set(MStokes,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+timeF=mpiWtime()-timeF;
+
+real time2=mpiWtime();
+real[int] b=vStokes(0,VVh);
+time2=mpiWtime()-time2;
+
+real time3=mpiWtime();
+u1[] = MStokes^-1*b;
+time3=mpiWtime()-time3;
+
+timeI=mpiWtime()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << "size of matrix " << MStokes.n << " x " << MStokes.m << " nn nzero coef  = " << MStokes.nbcoef << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+//if(mpirank==0 && pplot) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/Stokes-v1-matrix-pastix.edp b/examples++-mpi/Stokes-v1-matrix-pastix.edp
new file mode 100644
index 0000000..092c55a
--- /dev/null
+++ b/examples++-mpi/Stokes-v1-matrix-pastix.edp
@@ -0,0 +1,69 @@
+
+// other
+load "msh3"
+load "medit"
+load "real_pastix_FreeFem"
+
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int nn=10;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+
+VVh [u1,u2,u3,p];
+VVh [v1,v2,v3,q];
+
+real timeI=clock();
+real time1=clock();
+varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3)   //' for emacs
+                  - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,u1=fup,u2=0,u3=0) + on(1,u1=0,u2=0,u3=0) ;
+
+
+matrix MStokes=vStokes(VVh,VVh,tgv=ttgv);
+time1=clock()-time1;
+
+real timeF=clock();
+set(MStokes,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time2=clock();
+real[int] b=vStokes(0,VVh);
+time2=clock()-time2;
+
+real time3=clock();
+u1[] = MStokes^-1*b;
+time3=clock()-time3;
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+
+//if(mpirank==0) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/Stokes-v1-matrix-superludist.edp b/examples++-mpi/Stokes-v1-matrix-superludist.edp
new file mode 100644
index 0000000..883701b
--- /dev/null
+++ b/examples++-mpi/Stokes-v1-matrix-superludist.edp
@@ -0,0 +1,66 @@
+// other
+load "msh3"
+load "medit"
+load "real_SuperLU_DIST_FreeFem"
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int nn=10;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+
+VVh [u1,u2,u3,p];
+VVh [v1,v2,v3,q];
+
+real timeI=clock();
+real time1=clock();
+varf vStokes([u1,u2,u3,p],[v1,v2,v3,q]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3)   //' for emacs
+                  - div(u1,u2,u3)*q - div(v1,v2,v3)*p + 1e-10*q*p ) 
+  + on(2,u1=fup,u2=0,u3=0) + on(1,u1=0,u2=0,u3=0) ;
+
+
+matrix MStokes=vStokes(VVh,VVh,tgv=ttgv);
+time1=clock()-time1;
+
+real timeF=clock();
+set(MStokes,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time2=clock();
+real[int] b=vStokes(0,VVh);
+time2=clock()-time2;
+
+real time3=clock();
+u1[] = MStokes^-1*b;
+time3=clock()-time3;
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+//if(mpirank==0)medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/Stokes-v2-matrix-mumps.edp b/examples++-mpi/Stokes-v2-matrix-mumps.edp
new file mode 100644
index 0000000..f8bc820
--- /dev/null
+++ b/examples++-mpi/Stokes-v2-matrix-mumps.edp
@@ -0,0 +1,104 @@
+// other
+load "msh3"
+load "medit"
+load "MUMPS_FreeFem"
+
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int nn=15;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+//medit("c10x10x10",Th);
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+Uh u1,u2,u3;
+Uh v1,v2,v3;
+Ph p,q;
+
+real timeI=clock();
+real time1=clock();
+
+//VVh [uu1,uu2,uu3,up];
+varf vlaplace([u1,u2,u3],[v1,v2,v3]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3) ) 
+  + on(2,u1=fup,u2=0,u3=0) + on(1,u1=0,u2=0,u3=0) ; //'
+
+varf vdiv([u1,u2,u3],[q])=int3d(Th,qforder=3)(- div(u1,u2,u3)*q );
+varf vdivT([q],[u1,u2,u3])=int3d(Th,qforder=3)(- div(u1,u2,u3)*q );
+varf vmass(p,q) = int3d(Th,qforder=3)( 1e-10*p*q );
+
+matrix M=vmass(Ph,Ph);
+matrix L=vlaplace(UUh,UUh,tgv=ttgv);
+matrix B=vdiv(UUh,Ph);
+matrix BT=vdivT(Ph,UUh);
+
+matrix A = [ [ L, BT ],     //'
+	     [ B, M  ]];
+
+time1=clock()-time1;
+
+real timeF=clock();
+set(A,solver=sparsesolver,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time2=clock();
+real[int] b(VVh.ndof);
+real[int] xx(VVh.ndof);
+{ 
+  real[int] b1 = vlaplace(0,UUh);
+  
+  for(int ii=0; ii<UUh.ndof; ii++)
+    {
+      b[ii]=b1[ii];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      b[ii+UUh.ndof]=0;
+    }
+}
+time2=clock()-time2;
+
+real time3=clock();
+xx = A^-1*b;
+time3=clock()-time3;
+
+for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      u1[][ii]=xx[3*ii];
+      u2[][ii]=xx[3*ii+1];
+      u3[][ii]=xx[3*ii+2];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      p[][ii]=xx[ii+UUh.ndof];
+    }
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+
+//if(mpirank==0) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/Stokes-v2-matrix-pastix.edp b/examples++-mpi/Stokes-v2-matrix-pastix.edp
new file mode 100644
index 0000000..5c24a7e
--- /dev/null
+++ b/examples++-mpi/Stokes-v2-matrix-pastix.edp
@@ -0,0 +1,104 @@
+
+// other
+load "msh3"
+load "medit"
+load "real_pastix_FreeFem"
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int nn=10;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+//medit("c10x10x10",Th);
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+Uh u1,u2,u3;
+Uh v1,v2,v3;
+Ph p,q;
+
+real timeI=clock();
+real time1=clock();
+
+//VVh [uu1,uu2,uu3,up];
+varf vlaplace([u1,u2,u3],[v1,v2,v3]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3) ) 
+  + on(2,u1=fup,u2=0,u3=0) + on(1,u1=0,u2=0,u3=0) ; //'
+
+varf vdiv([u1,u2,u3],[q])=int3d(Th,qforder=3)(- div(u1,u2,u3)*q );
+varf vdivT([q],[u1,u2,u3])=int3d(Th,qforder=3)(- div(u1,u2,u3)*q );
+varf vmass(p,q) = int3d(Th,qforder=3)( 1e-10*p*q );
+
+matrix M=vmass(Ph,Ph);
+matrix L=vlaplace(UUh,UUh,tgv=ttgv);
+matrix B=vdiv(UUh,Ph);
+matrix BT=vdivT(Ph,UUh);
+
+matrix A = [ [ L, BT ],     //'
+	     [ B, M  ]];
+
+time1=clock()-time1;
+
+real timeF=clock();
+set(A,solver=sparsesolver,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time2=clock();
+real[int] b(VVh.ndof);
+real[int] xx(VVh.ndof);
+{ 
+  real[int] b1 = vlaplace(0,UUh);
+  
+  for(int ii=0; ii<UUh.ndof; ii++)
+    {
+      b[ii]=b1[ii];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      b[ii+UUh.ndof]=0;
+    }
+}
+time2=clock()-time2;
+
+real time3=clock();
+xx = A^-1*b;
+time3=clock()-time3;
+
+for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      u1[][ii]=xx[3*ii];
+      u2[][ii]=xx[3*ii+1];
+      u3[][ii]=xx[3*ii+2];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      p[][ii]=xx[ii+UUh.ndof];
+    }
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+
+//if(mpirank==0) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/Stokes-v2-matrix-superludist.edp b/examples++-mpi/Stokes-v2-matrix-superludist.edp
new file mode 100644
index 0000000..61279dc
--- /dev/null
+++ b/examples++-mpi/Stokes-v2-matrix-superludist.edp
@@ -0,0 +1,103 @@
+
+load "msh3"
+load "medit"
+load "real_SuperLU_DIST_FreeFem"
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int nn=10;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+//medit("c10x10x10",Th);
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+Uh u1,u2,u3;
+Uh v1,v2,v3;
+Ph p,q;
+
+real timeI=clock();
+real time1=clock();
+
+//VVh [uu1,uu2,uu3,up];
+varf vlaplace([u1,u2,u3],[v1,v2,v3]) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) +  Grad(u2)'*Grad(v2) +  Grad(u3)'*Grad(v3) ) 
+  + on(2,u1=fup,u2=0,u3=0) + on(1,u1=0,u2=0,u3=0) ; //'
+
+varf vdiv([u1,u2,u3],[q])=int3d(Th,qforder=3)(- div(u1,u2,u3)*q );
+varf vdivT([q],[u1,u2,u3])=int3d(Th,qforder=3)(- div(u1,u2,u3)*q );
+varf vmass(p,q) = int3d(Th,qforder=3)( 1e-10*p*q );
+
+matrix M=vmass(Ph,Ph);
+matrix L=vlaplace(UUh,UUh,tgv=ttgv);
+matrix B=vdiv(UUh,Ph);
+matrix BT=vdivT(Ph,UUh);
+
+matrix A = [ [ L, BT ],     //'
+	     [ B, M  ]];
+
+time1=clock()-time1;
+
+real timeF=clock();
+set(A,solver=sparsesolver,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time2=clock();
+real[int] b(VVh.ndof);
+real[int] xx(VVh.ndof);
+{ 
+  real[int] b1 = vlaplace(0,UUh);
+  
+  for(int ii=0; ii<UUh.ndof; ii++)
+    {
+      b[ii]=b1[ii];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      b[ii+UUh.ndof]=0;
+    }
+}
+time2=clock()-time2;
+
+real time3=clock();
+xx = A^-1*b;
+time3=clock()-time3;
+
+for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      u1[][ii]=xx[3*ii];
+      u2[][ii]=xx[3*ii+1];
+      u3[][ii]=xx[3*ii+2];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      p[][ii]=xx[ii+UUh.ndof];
+    }
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+
+//if(mpirank==0) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/Stokes-v3-matrix-mumps.edp b/examples++-mpi/Stokes-v3-matrix-mumps.edp
new file mode 100644
index 0000000..c12918b
--- /dev/null
+++ b/examples++-mpi/Stokes-v3-matrix-mumps.edp
@@ -0,0 +1,122 @@
+
+// other
+load "msh3"
+load "medit"
+load "MUMPS_FreeFem"
+
+real ttgv=-1;
+string ssparams="nprow=1, npcol="+mpisize;
+
+
+int nn=5;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+
+real ccc = mpisize/real(Th.nt) ;
+Th=change(Th,fregion= min(mpisize-1,int(nuTriangle* ccc+1e-10)));
+if(mpirank==0)
+for(int i=0;i<=mpisize;++i)
+	 cout<< " Volume region  " <<  i << " " << int3d(Th,i)(1.) << endl;
+//if(mpirank==0) medit("c10x10x10",Th);
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+Uh u1,u2,u3;
+Uh v1,v2,v3;
+Ph p,q;
+
+//VVh [uu1,uu2,uu3,up];
+real timeI=clock();
+real time1=clock();
+varf vlaplace1(u1,v1) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) ) + on(2,u1=fup) + on(1,u1=0); //' for emacs 
+
+varf vlaplacenull(u2,v2) = 
+  int3d(Th,qforder=3)( Grad(u2)'*Grad(v2) ) + on(2,u2=0) + on(1,u2=0); //' for emacs 
+
+varf vdx(u1,q) = int3d(Th,qforder=3)( -dx(u1)*q );
+varf vdy(u2,q) = int3d(Th,qforder=3)( -dy(u2)*q ); 
+varf vdz(u3,q) = int3d(Th,qforder=3)( -dz(u3)*q );
+
+varf vmass(p,q) = int3d(Th,qforder=3)( 1e-10*p*q );
+
+matrix M     = vmass(Ph,Ph,tgv=ttgv);
+matrix L1    = vlaplace1(Uh,Uh,tgv=ttgv);
+matrix Lnull = vlaplacenull(Uh,Uh);
+matrix Bx = vdx(Uh,Ph);
+matrix By = vdy(Uh,Ph);
+matrix Bz = vdz(Uh,Ph);
+
+
+matrix A = [ [ L1,     0,     0, Bx' ],     
+	         [  0, Lnull,     0, By' ],
+             [  0,     0, Lnull, Bz' ],
+             [ Bx,    By,    Bz,  M  ] ];    //' for emacs
+
+
+time1=clock()-time1;
+
+real time2=clock();
+real[int] b(VVh.ndof);
+real[int] xx(VVh.ndof);
+{ 
+  real[int] b1 = vlaplace1(0,Uh,tgv=ttgv);
+  real[int] b2 = vlaplacenull(0,Uh,tgv=ttgv);
+  
+  for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      b[ii]=b1[ii];
+      b[ii+Uh.ndof]=b2[ii];
+      b[ii+2*Uh.ndof]=b2[ii];
+    }
+  for(int ii=UUh.ndof; ii<UUh.ndof+Ph.ndof; ii++)
+    {
+      b[ii]=0;
+    }
+}
+time2=clock()-time2;
+
+real timeF=clock();
+set(A,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time3=clock();
+xx = A^-1*b;
+time3=clock()-time3;
+
+for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      u1[][ii]=xx[ii];
+      u2[][ii]=xx[ii+Uh.ndof];
+      u3[][ii]=xx[ii+2*Uh.ndof];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      p[][ii]=xx[ii+UUh.ndof];
+    }
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+
+//if(mpirank==0) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/Stokes-v3-matrix-pastix.edp b/examples++-mpi/Stokes-v3-matrix-pastix.edp
new file mode 100644
index 0000000..435731e
--- /dev/null
+++ b/examples++-mpi/Stokes-v3-matrix-pastix.edp
@@ -0,0 +1,119 @@
+// other
+load "msh3"
+load "medit"
+load "real_pastix_FreeFem"
+
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+
+int nn=12;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+//medit("c10x10x10",Th);
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+Uh u1,u2,u3;
+Uh v1,v2,v3;
+Ph p,q;
+
+//VVh [uu1,uu2,uu3,up];
+real timeI=clock();
+real time1=clock();
+varf vlaplace1(u1,v1) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) ) + on(2,u1=fup) + on(1,u1=0); //' for emacs 
+
+varf vlaplacenull(u2,v2) = 
+  int3d(Th,qforder=3)( Grad(u2)'*Grad(v2) ) + on(2,u2=0) + on(1,u2=0); //' for emacs 
+
+varf vdx(u1,q) = int3d(Th,qforder=3)( -dx(u1)*q );
+varf vdy(u2,q) = int3d(Th,qforder=3)( -dy(u2)*q ); 
+varf vdz(u3,q) = int3d(Th,qforder=3)( -dz(u3)*q );
+
+varf vmass(p,q) = int3d(Th,qforder=3)( 1e-10*p*q );
+
+matrix M     = vmass(Ph,Ph,tgv=ttgv);
+matrix L1    = vlaplace1(Uh,Uh,tgv=ttgv);
+matrix Lnull = vlaplacenull(Uh,Uh);
+matrix Bx = vdx(Uh,Ph);
+matrix By = vdy(Uh,Ph);
+matrix Bz = vdz(Uh,Ph);
+
+
+matrix A = [ [ L1,     0,     0, Bx' ],     
+	         [  0, Lnull,     0, By' ],
+             [  0,     0, Lnull, Bz' ],
+             [ Bx,    By,    Bz,  M  ] ];    //' for emacs
+
+
+time1=clock()-time1;
+
+real time2=clock();
+real[int] b(VVh.ndof);
+real[int] xx(VVh.ndof);
+{ 
+  real[int] b1 = vlaplace1(0,Uh);
+  real[int] b2 = vlaplacenull(0,Uh);
+  
+  for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      b[ii]=b1[ii];
+      b[ii+Uh.ndof]=b2[ii];
+      b[ii+2*Uh.ndof]=b2[ii];
+    }
+  for(int ii=UUh.ndof; ii<UUh.ndof+Ph.ndof; ii++)
+    {
+      b[ii]=0;
+    }
+}
+time2=clock()-time2;
+
+real timeF=clock();
+set(A,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time3=clock();
+xx = A^-1*b;
+time3=clock()-time3;
+
+for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      u1[][ii]=xx[ii];
+      u2[][ii]=xx[ii+Uh.ndof];
+      u3[][ii]=xx[ii+2*Uh.ndof];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      p[][ii]=xx[ii+UUh.ndof];
+    }
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+
+//if(mpirank==0) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
+// FFCS: testing 3d plots
+plot(Th,[u1,u2,u3],p);
diff --git a/examples++-mpi/Stokes-v3-matrix-superludist.edp b/examples++-mpi/Stokes-v3-matrix-superludist.edp
new file mode 100644
index 0000000..7a4bffc
--- /dev/null
+++ b/examples++-mpi/Stokes-v3-matrix-superludist.edp
@@ -0,0 +1,116 @@
+// other
+load "msh3"
+load "medit"
+load "real_SuperLU_DIST_FreeFem"
+
+real ttgv=-1;
+string ssparams="nprow=1, npcol="+mpisize;
+
+
+int nn=12;
+mesh Th2=square(nn,nn);
+fespace Vh2(Th2,P2);  Vh2 ux,uz,p2;
+int[int] rup=[0,2],  rdown=[0,1], rmid=[1,1,2,1,3,1,4,1];
+real zmin=0,zmax=1;
+mesh3 Th=buildlayers(Th2,nn,
+  zbound=[zmin,zmax],  labelmid=rmid, 
+  reffaceup = rup,     reffacelow = rdown);
+  
+//medit("c10x10x10",Th);
+fespace VVh(Th,[P2,P2,P2,P1]);
+fespace UUh(Th,[P2,P2,P2]);
+fespace Uh(Th,P2);
+fespace Ph(Th,P1);
+
+macro Grad(u) [dx(u),dy(u),dz(u)]// EOM
+macro div(u1,u2,u3) (dx(u1)+dy(u2)+dz(u3)) //EOM
+
+func fup = (1-x)*(x)*y*(1-y)*16;
+
+Uh u1,u2,u3;
+Uh v1,v2,v3;
+Ph p,q;
+
+//VVh [uu1,uu2,uu3,up];
+real timeI=clock();
+real time1=clock();
+varf vlaplace1(u1,v1) = 
+  int3d(Th,qforder=3)( Grad(u1)'*Grad(v1) ) + on(2,u1=fup) + on(1,u1=0); //' for emacs 
+
+varf vlaplacenull(u2,v2) = 
+  int3d(Th,qforder=3)( Grad(u2)'*Grad(v2) ) + on(2,u2=0) + on(1,u2=0); //' for emacs 
+
+varf vdx(u1,q) = int3d(Th,qforder=3)( -dx(u1)*q );
+varf vdy(u2,q) = int3d(Th,qforder=3)( -dy(u2)*q ); 
+varf vdz(u3,q) = int3d(Th,qforder=3)( -dz(u3)*q );
+
+varf vmass(p,q) = int3d(Th,qforder=3)( 1e-10*p*q );
+
+matrix M     = vmass(Ph,Ph,tgv=ttgv);
+matrix L1    = vlaplace1(Uh,Uh,tgv=ttgv);
+matrix Lnull = vlaplacenull(Uh,Uh);
+matrix Bx = vdx(Uh,Ph);
+matrix By = vdy(Uh,Ph);
+matrix Bz = vdz(Uh,Ph);
+
+
+matrix A = [ [ L1,     0,     0, Bx' ],     
+	         [  0, Lnull,     0, By' ],
+             [  0,     0, Lnull, Bz' ],
+             [ Bx,    By,    Bz,  M  ] ];    //' for emacs
+
+
+time1=clock()-time1;
+
+real time2=clock();
+real[int] b(VVh.ndof);
+real[int] xx(VVh.ndof);
+{ 
+  real[int] b1 = vlaplace1(0,Uh);
+  real[int] b2 = vlaplacenull(0,Uh);
+  
+  for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      b[ii]=b1[ii];
+      b[ii+Uh.ndof]=b2[ii];
+      b[ii+2*Uh.ndof]=b2[ii];
+    }
+  for(int ii=UUh.ndof; ii<UUh.ndof+Ph.ndof; ii++)
+    {
+      b[ii]=0;
+    }
+}
+time2=clock()-time2;
+
+real timeF=clock();
+set(A,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+timeF=clock()-timeF;
+
+real time3=clock();
+xx = A^-1*b;
+time3=clock()-time3;
+
+for(int ii=0; ii<Uh.ndof; ii++)
+    {
+      u1[][ii]=xx[ii];
+      u2[][ii]=xx[ii+Uh.ndof];
+      u3[][ii]=xx[ii+2*Uh.ndof];
+    }
+  for(int ii=0; ii<Ph.ndof; ii++)
+    {
+      p[][ii]=xx[ii+UUh.ndof];
+    }
+
+timeI=clock()-timeI;
+
+cout << "============= CPU TIME ============" << endl;
+cout << " matrix                  " <<  time1 << endl;
+cout << " Fact                    " <<  timeF << endl;
+cout << " second member           " <<  time2 << endl;
+cout << " solve                   " <<  time3 << endl;
+cout << "                          ------------" << endl;
+cout << " all                     " <<  timeI << endl;
+cout << "============= CPU TIME ============" << endl;
+
+//if(mpirank==0) medit("UV2 PV2",Th,[u1,u2,u3],p);
+
diff --git a/examples++-mpi/VG.edp b/examples++-mpi/VG.edp
new file mode 100644
index 0000000..56abb32
--- /dev/null
+++ b/examples++-mpi/VG.edp
@@ -0,0 +1,72 @@
+// other
+//load "medit"
+load "MUMPS_FreeFem"
+include "cube.idp"
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int[int]  Nxyz=[40,8,8];
+real [int,int]  Bxyz=[[0.,5.],[0.,1.],[0.,1.]];
+int [int,int]  Lxyz=[[1,1],[2,2],[2,2]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+
+real E = 21.5e4;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+
+fespace Vh(Th,[P2,P2,P2]);
+//fespace Vh(Th,[P1,P1,P1]);
+Vh [u1,u2,u3], [v1,v2,v3];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2,u3)  [dx(u1),dy(u2),dz(u3),(dz(u2)+dy(u3))/sqrt2,(dz(u1)+dx(u3))/sqrt2,(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u1,u2,u3) ( dx(u1)+dy(u2)+dz(u3) ) // EOM
+real time=clock();  
+
+real tMatrix = clock();
+varf vLame([u1,u2,u3],[v1,v2,v3]) = 
+int3d(Th)(
+		 lambda*div(u1,u2,u3)*div(v1,v2,v3)	
+	    + 2.*mu*( epsilon(u1,u2,u3)'*epsilon(v1,v2,v3) ) //') for emacs
+	      )
+	      + on(1,u1=0,u2=0,u3=0);
+
+matrix MLame=vLame(Vh,Vh,tgv=ttgv);
+tMatrix = clock()-tMatrix;
+
+real tFact = clock();
+set(MLame,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+tFact = clock()-tFact;
+
+real tsdc = clock();
+varf vsdc([u1,u2,u3],[v1,v2,v3])=int3d(Th) (gravity*v3)+ on(1,u1=0,u2=0,u3=0);
+real[int] sdc= vsdc(0,Vh); 
+tsdc = clock()-tsdc;
+
+real tsolve=clock();
+u1[] = MLame^-1*sdc;
+tsolve= clock()-tsolve;
+cout << "===============================================" << endl;
+cout << "====            CPU time                  =====" << endl;
+cout << "===============================================" << endl;
+cout << " ALL solving steps :::: "  << clock()-time << endl;
+cout << " Matrix            :::: "  << tMatrix << endl;
+cout << " Fact              :::: "  << tFact   << endl;
+cout << " Second member     :::: "  << tsdc    << endl;
+cout << " Solve             :::: "  << tsolve  << endl;
+cout << "===============================================" << endl;
+
+real dmax= u1[].max;
+cout << " max deplacement = " << dmax << endl;
+real coef= 0.01/dmax;
+int[int] ref2=[1,0,2,0];
+if(mpirank==0)
+{
+searchMethod=1;		
+  mesh3 Thm=movemesh3(Th,transfo=[x+u1*coef,y+u2*coef,z+u3*coef],label=ref2);
+  savemesh(Thm,"beam-deformed-mumps.mesh");
+}
\ No newline at end of file
diff --git a/examples++-mpi/additional.idp b/examples++-mpi/additional.idp
new file mode 100755
index 0000000..5a6d9d2
--- /dev/null
+++ b/examples++-mpi/additional.idp
@@ -0,0 +1,206 @@
+macro plotMPI(Th, u, legend, Pk, def, d, w)
+    if(mpirank == 0) {
+        meshN ThCurrent = Th;
+        meshN[int] meshTab(mpisize);
+        fespace Xh(ThCurrent, Pk);
+        Xh<real>[int] def(uTab)(mpisize);
+        uTab[0][] = u;
+        meshTab[0] = Th;
+        mpiRequest[int] rq(mpisize - 1);
+        for(i = 1; i < mpisize; ++i)
+            Irecv(processor(i, mpiCommWorld, rq[i - 1]), meshTab[i]);
+        for(i = 1; i < mpisize; ++i)
+            mpiWaitAny(rq);
+        for(i = 1; i < mpisize; ++i) {
+            ThCurrent = meshTab[i];
+            Irecv(processor(i, mpiCommWorld, rq[i - 1]), uTab[i][]);
+        }
+        for(i = 1; i < mpisize; ++i)
+            mpiWaitAny(rq);
+        plot(uTab, wait = w, nbiso = 40, fill = 1, value = 1, dim = d, cmm = legend);
+    }
+    else {
+        mpiRequest[int] rq(2);
+        Isend(processor(0, rq[0]), Th);
+        Isend(processor(0, rq[1]), u);
+        mpiWait(rq[0]);
+        mpiWait(rq[1]);
+    }// EOM
+func bool AddLayersFF(meshN & Th, real[int] &ssd,int n,real[int] &unssd)
+{
+  //  build a continuous function  uussd (P1) and modifies ssd :
+  //  IN: ssd in the caracteristics function on the input sub domain.
+  //  OUT: ssd and unssd
+  //  such that : 
+  //   ssd is a boolean function 
+  //   unssd is a smooth function
+  //   ssd = 1 when   unssd >0;
+  //   add n layer of element (size of the overlap)
+  //   and unssd = 0 ouside of this layer ...
+  // ---------------------------------
+  fespace Vh(Th,P1);
+  fespace Ph(Th,P0);
+  Ph s;
+  // assert(ssd.n==Ph.ndof);
+  // assert(unssd.n==Vh.ndof);
+  unssd=0;
+  s[]= ssd;
+  Vh u;
+  varf vM(uuuu,v)=intN(Th,qforder=1)(uuuu*v/measureN);
+  matrix M=vM(Ph,Vh);
+  
+  for(int i=0;i<n;++i)
+    {
+      u[]= M*s[];
+      u = u>.1; 
+      unssd+= u[];
+      s[]= M'*u[];
+      s = s >0.1;
+    }
+  return true;
+}
+
+macro AddLayersMacro(M, Ph, Vh, ssd, n, unssd)
+    unssd = 0;
+    Vh u;
+    for(j = 0; j < n; ++j) {
+        u[] = M * ssd[];
+        u = u > .1;
+        unssd += u[];
+        ssd[] = M' * u[];
+        ssd = ssd > 0.1;
+    }
+    unssd /= n;// EOM
+
+macro partition(meshName, borderName, overlapName, s, D, Vh, P, comm)
+        meshName = trunc(overlapName, abs(part - mpiRank(comm)) < 0.1, label = 10);
+        mpiBarrier(comm);
+        real timerPartition = mpiWtime();
+        {
+            fespace PhLocal(meshName, P0);
+            PhLocal overshoot = hTriangle;
+            real max = 2. * overlap * overshoot[].max;
+            bbN(meshName, max, overlapName)
+        }
+        fespace VhGlobal(overlapName, P1);
+        PhGlobal supp = abs(part - mpiRank(comm)) < 0.1;
+        VhGlobal suppSmooth;
+        AddLayersFF(overlapName, supp[], overlap * 2, suppSmooth[]);
+        {
+            meshN neighbors = trunc(overlapName, suppSmooth > 0.001 && (suppSmooth < 2 * overlap - 0.001));
+            fespace Oh(neighbors, P0);
+            Oh partOverlap = part;
+            findDiff(partOverlap[], arrayIntersection);
+        }
+        fespace Vh(meshName, P1);
+        Vh[int] partitionIntersection(arrayIntersection.n);
+        if(s > 1) {
+            overlapName = trunc(overlapName, suppSmooth > 0.001, split = s);
+            supp = abs(part - mpiRank(comm)) < 0.1;
+            suppSmooth = 0;
+            AddLayersFF(overlapName, supp[], overlap * 2, suppSmooth[]);
+        }
+        overlapName = trunc(overlapName, suppSmooth > overlap - 0.999);
+        supp = supp;
+        suppSmooth = suppSmooth;
+        meshName = trunc(overlapName, suppSmooth > overlap + 0.001, label = 10);
+        borderName = trunc(overlapName, (suppSmooth > overlap - 0.999) && (suppSmooth < overlap + 0.001), label = 20);
+        Vh khi = max(suppSmooth - overlap, 0.) / overlap;
+        Vh sum = khi;
+        VhGlobal phi = 0;
+        varf vM(u, v) = intN(overlapName, qforder = 1)(u * v / measureN);
+        matrix M = vM(PhGlobal, VhGlobal);
+        for(i = 0; i < arrayIntersection.n; ++i) {
+            PhGlobal suppPartition = abs(arrayIntersection[i] - part) < 0.1;
+            AddLayersMacro(M, PhGlobal, VhGlobal, suppPartition, overlap, phi[])
+            partitionIntersection[numberIntersection] = phi;
+            sum[] += partitionIntersection[numberIntersection][];
+            arrayIntersection[numberIntersection++] = arrayIntersection[i];
+        }
+
+        khi[] = khi[] ./= sum[];
+        if(solver != 3 && solver != 5)
+            overlapName = minimalMesh;
+        else
+            overlapName = trunc(meshName, khi < 0.99);
+        if(numberIntersection != arrayIntersection.n)
+            arrayIntersection.resize(numberIntersection);
+        Wh def(func2vec) = init(khi);
+        D.resize(Wh.ndof);
+        D = func2vec[];
+        restrictionIntersection.resize(numberIntersection);
+        for(i = 0; i < numberIntersection; ++i) {
+            meshN meshIntersection = trunc(meshName, partitionIntersection[i] > 1e-6);
+            fespace WhIntersection(meshIntersection, P);
+            matrix R = interpolate(WhIntersection, Wh);
+            real[int] C;
+            int[int] I;
+            [I, restrictionIntersection[i], C] = R;
+            restrictionIntersection[i].resize(R.nbcoef);
+        }
+// EOM
+
+macro build(globalTh, Th, ThBorder, ThOverlap, s, D, numberIntersection, arrayIntersection, restrictionIntersection, Wh, P, comm)
+meshN ThOverlap, ThBorder;
+
+/*# partition #*/
+int[int] arrayIntersection;
+int[int][int] restrictionIntersection(0);
+real[int] D;
+
+int numberIntersection = 0;
+real timing;
+{
+    timing = mpiWtime();
+    if(mpisize > 1) {
+        globalTh(ThOverlap);
+        fespace PhGlobal(ThOverlap, P0);
+        PhGlobal part;
+        int[int] balancing(ThOverlap.nt);
+        balancing = 0;
+        if(mpiRank(comm) == 0) {
+            cout.scientific << " --- global mesh of " << ThOverlap.nt << " elements (prior to refinement) generated (in " << mpiWtime() - timing << ") and partitioned with ";
+            timing = mpiWtime();
+            metisdual(balancing, ThOverlap, mpiSize(comm));
+            cout << "Metis";
+            cout.scientific << " (in " << mpiWtime() - timing << ")" << endl;
+        }
+        timing = mpiWtime();
+        broadcast(processor(0, comm), balancing);
+        fast(part[], balancing);
+        partition(Th, ThBorder, ThOverlap, s, D, Vh, P, comm)
+    }
+    else if(mpisize == 1) {
+        globalTh(Th);
+        D.resize(Wh.ndof);
+        D = 1.;
+    }
+    mpiBarrier(mpiCommWorld);
+    if(mpirank == 0) cout.scientific << " --- partition of unity built (in " << mpiWtime() - timing << ")" << endl;
+}
+/*# partitionEnd #*/
+// EOM
+
+macro assemble(mat, rhs, Wh, Th, ThBorder, Varf)
+real[int] rhs;
+matrix<real> mat;
+{ /* all memory of objects defined between this set of curly brackets
+     will be freed when the closing bracket is reached */
+    meshN ThAugmented = Th + ThBorder; /* ⠶$\Omega^{\delta + 1}_k = \Omega^\delta_k \cup \left(\Omega^{\delta + 1}_k \setminus \Omega^{\delta}_k\right)$⠶ */
+    ThBorder = minimalMesh;
+    Varf(vPb, ThAugmented, PhAugmented)
+    fespace WhAugmented(ThAugmented, Pk);
+    mat = vPb(WhAugmented, WhAugmented/*, solver = CG*/);
+    real[int] rhsFull = vPb(0, WhAugmented);
+    matrix R = interpolate(Wh, WhAugmented);
+
+    removeDOF(mat, R, rhsFull, rhs);
+}
+// EOM
+
+macro assembleUnsym(mat, rhs, Wh, Th, ThBorder, Varf)
+{
+    Varf(vPb, Th, Ph)
+    mat = vPb(Wh, Wh);
+}
+// EOM
diff --git a/examples++-mpi/beam-3d-matrix-pastix.edp b/examples++-mpi/beam-3d-matrix-pastix.edp
new file mode 100644
index 0000000..001253e
--- /dev/null
+++ b/examples++-mpi/beam-3d-matrix-pastix.edp
@@ -0,0 +1,68 @@
+// other
+load "medit"
+load "real_pastix_FreeFem"
+include "cube.idp"
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int[int]  Nxyz=[40,8,8];
+real [int,int]  Bxyz=[[0.,5.],[0.,1.],[0.,1.]];
+int [int,int]  Lxyz=[[1,1],[2,2],[2,2]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+
+real E = 21.5e4;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+
+fespace Vh(Th,[P2,P2,P2]);
+//fespace Vh(Th,[P1,P1,P1]);
+Vh [u1,u2,u3], [v1,v2,v3];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2,u3)  [dx(u1),dy(u2),dz(u3),(dz(u2)+dy(u3))/sqrt2,(dz(u1)+dx(u3))/sqrt2,(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u1,u2,u3) ( dx(u1)+dy(u2)+dz(u3) ) // EOM
+real time=clock();  
+
+real tMatrix = clock();
+varf vLame([u1,u2,u3],[v1,v2,v3]) = 
+int3d(Th)(
+		 lambda*div(u1,u2,u3)*div(v1,v2,v3)	
+	    + 2.*mu*( epsilon(u1,u2,u3)'*epsilon(v1,v2,v3) ) //') for emacs
+	      )
+	      + on(1,u1=0,u2=0,u3=0);
+
+matrix MLame=vLame(Vh,Vh,tgv=ttgv);
+tMatrix = clock()-tMatrix;
+
+real tFact = clock();
+set(MLame,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+tFact = clock()-tFact;
+
+real tsdc = clock();
+varf vsdc([u1,u2,u3],[v1,v2,v3])=int3d(Th) (gravity*v3)+ on(1,u1=0,u2=0,u3=0);
+real[int] sdc= vsdc(0,Vh); 
+tsdc = clock()-tsdc;
+
+real tsolve=clock();
+u1[] = MLame^-1*sdc;
+tsolve= clock()-tsolve;
+cout << "===============================================" << endl;
+cout << "====            CPU time                  =====" << endl;
+cout << "===============================================" << endl;
+cout << " ALL solving steps :::: "  << clock()-time << endl;
+cout << " Matrix            :::: "  << tMatrix << endl;
+cout << " Fact              :::: "  << tFact   << endl;
+cout << " Second member     :::: "  << tsdc    << endl;
+cout << " Solve             :::: "  << tsolve  << endl;
+cout << "===============================================" << endl;
+
+real dmax= u1[].max;
+cout << " max deplacement = " << dmax << endl;
+real coef= 0.1/dmax;
+int[int] ref2=[1,0,2,0];
+mesh3 Thm=movemesh3(Th,transfo=[x+u1*coef,y+u2*coef,z+u3*coef],label=ref2);
+savemesh(Thm,"beam-deformed-pastix.mesh");
diff --git a/examples++-mpi/beam-3d-matrix-superludist.edp b/examples++-mpi/beam-3d-matrix-superludist.edp
new file mode 100644
index 0000000..94056a5
--- /dev/null
+++ b/examples++-mpi/beam-3d-matrix-superludist.edp
@@ -0,0 +1,73 @@
+// other
+load "msh3"
+load "medit"
+load "real_SuperLU_DIST_FreeFem"
+include "cube.idp"
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize;
+
+int[int]  Nxyz=[40,8,8];
+real [int,int]  Bxyz=[[0.,5.],[0.,1.],[0.,1.]];
+int [int,int]  Lxyz=[[1,1],[2,2],[2,2]];
+mesh3 Th=Cube(Nxyz,Bxyz,Lxyz);
+
+real E = 21.5e4;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+
+fespace Vh(Th,[P2,P2,P2]);
+//fespace Vh(Th,[P1,P1,P1]);
+Vh [u1,u2,u3], [v1,v2,v3];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2,u3)  [dx(u1),dy(u2),dz(u3),(dz(u2)+dy(u3))/sqrt2,(dz(u1)+dx(u3))/sqrt2,(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u1,u2,u3) ( dx(u1)+dy(u2)+dz(u3) ) // EOM
+real time=clock();  
+
+real tMatrix = clock();
+varf vLame([u1,u2,u3],[v1,v2,v3]) = 
+int3d(Th)(
+		 lambda*div(u1,u2,u3)*div(v1,v2,v3)	
+	    + 2.*mu*( epsilon(u1,u2,u3)'*epsilon(v1,v2,v3) ) //') for emacs
+	      )
+	      + on(1,u1=0,u2=0,u3=0);
+
+matrix MLame=vLame(Vh,Vh,tgv=ttgv);
+tMatrix = clock()-tMatrix;
+
+real tFact = clock();
+set(MLame,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+tFact = clock()-tFact;
+
+real tsdc = clock();
+varf vsdc([u1,u2,u3],[v1,v2,v3])=int3d(Th) (gravity*v3)+ on(1,u1=0,u2=0,u3=0);
+real[int] sdc= vsdc(0,Vh); 
+tsdc = clock()-tsdc;
+
+real tsolve=clock();
+u1[] = MLame^-1*sdc;
+tsolve= clock()-tsolve;
+cout << "===============================================" << endl;
+cout << "====            CPU time                  =====" << endl;
+cout << "===============================================" << endl;
+cout << " ALL solving steps :::: "  << clock()-time << endl;
+cout << " Matrix            :::: "  << tMatrix << endl;
+cout << " Fact              :::: "  << tFact   << endl;
+cout << " Second member     :::: "  << tsdc    << endl;
+cout << " Solve             :::: "  << tsolve  << endl;
+cout << "===============================================" << endl;
+
+real dmax= u1[].max;
+cout << " max deplacement = " << dmax << endl;
+real coef= 0.01/dmax;
+int[int] ref2=[1,0,2,0];
+if(mpirank==0)
+{
+searchMethod=1; 
+mesh3 Thm=movemesh3(Th,transfo=[x+u1*coef,y+u2*coef,z+u3*coef],label=ref2);
+savemesh(Thm,"beam-deformed-superlu.mesh");
+}
diff --git a/examples++-mpi/cavityNewtow-MUMPS.edp b/examples++-mpi/cavityNewtow-MUMPS.edp
new file mode 100644
index 0000000..77752e4
--- /dev/null
+++ b/examples++-mpi/cavityNewtow-MUMPS.edp
@@ -0,0 +1,133 @@
+load "MUMPS_FreeFem"
+
+string ssparams="";//nprow="+npr+", npcol="+npc;
+real ttgv=1e10;
+
+/*
+  Incompressible Navier Stokes 
+    with Taylor-Hood Finite element
+    No linearity : Newton methode 
+    continuation on Reynols Number
+    Mesh adaptation 
+*/
+real  reymax = 1600; // ok < 125000 
+mesh Th=square(8,8);
+fespace Xh(Th,P2);
+fespace Mh(Th,P1);
+fespace XXMh(Th,[P2,P2,P1]);
+XXMh [u1,u2,p];
+XXMh [v1,v2,q]; 
+
+macro div(u1,u2) (dx(u1)+dy(u2))//
+macro grad(u1,u2) [dx(u1),dy(u2)]//
+macro ugrad(u1,u2,v) (u1*dx(v)+u2*dy(v)) //
+macro Ugrad(u1,u2,v1,v2) [ugrad(u1,u2,v1),ugrad(u1,u2,v2)]//
+
+solve Stokes ([u1,u2,p],[v1,v2,q],solver=sparsesolver,tgv=ttgv,sparams=ssparams) =
+    int2d(Th)( ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            - p*div(v1,v2)-q*div(u1,u2)
+           )
+  + on(3,u1=4*x*(1-x),u2=0) 
+  + on(1,2,4,u1=0,u2=0);
+
+ Xh uu1=u1,uu2=u2;  
+if(mpirank==0)
+plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[uu1,uu2],wait=0);
+
+Xh psi,phi;
+
+
+solve streamlines(psi,phi) = 
+      int2d(Th)( dx(psi)*dx(phi) + dy(psi)*dy(phi))
+   +  int2d(Th)( -phi*(dy(u1)-dx(u2)))
+   +  on(1,2,3,4,psi=0);
+if(mpirank==0)
+plot(psi,wait=0);
+int i=0;
+real  nu=1./100.;
+real dt=0.1;
+real alpha=1/dt;
+
+
+
+/* NL 
+ varf   vNS ([u1,u2,p],[v1,v2,q],solver=Crout,init=i) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            + p*dx(v1)+ p*dy(v2)
+            + dx(u1)*q+ dy(u2)*q
+            + Ugrad(u1,u2,u1,u2)'*[v1,v2]
+           )   
+  + on(3,u1=1,u2=0) 
+  + on(1,2,4,u1=0,u2=0) 
+*/
+
+XXMh [up1,up2,pp];
+varf   vDNS ([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+            
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            + p*dx(v1)+ p*dy(v2)
+            + dx(u1)*q+ dy(u2)*q
+            + Ugrad(u1,u2,up1,up2)'*[v1,v2]
+            + Ugrad(up1,up2,u1,u2)'*[v1,v2]
+           )
+  + on(1,2,3,4,u1=0,u2=0) 
+;
+
+
+varf   vNS ([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+          
+            + nu * ( dx(up1)*dx(v1) + dy(up1)*dy(v1)
+            +  dx(up2)*dx(v2) + dy(up2)*dy(v2) )
+            + pp*q*(0.000001) 
+            + pp*dx(v1)+ pp*dy(v2)
+            + dx(up1)*q+ dy(up2)*q
+            + Ugrad(up1,up2,up1,up2)'*[v1,v2]//'
+	      )
+  + on(1,2,3,4,u1=0,u2=0) 
+  ;
+
+for(real re=100;re<=reymax;re *=2)
+  { 
+    
+    real lerr=0.04;
+    
+    if(re>8000) lerr=0.01;
+    if(re>10000) lerr=0.005; 
+    for(int step=0;step<2;step++)
+      {
+	Th=adaptmesh(Th,[u1,u2],p,err=lerr,nbvx=100000);
+	//plot(Th,wait=0);
+	[u1,u2,p]=[u1,u2,p];
+	[up1,up2,pp]=[up1,up2,pp];
+	
+	for (i=0;i<=20;i++)
+	  {
+	    nu =1./re;
+	    up1[]=u1[];
+	    real[int] b = vNS(0,XXMh,tgv=ttgv);
+	    matrix Ans=vDNS(XXMh,XXMh,tgv=ttgv);
+	    set(Ans,solver=sparsesolver,tgv=ttgv,sparams=ssparams);
+	    real[int] w = Ans^-1*b;
+	    u1[] -= w;
+	    cout << " iter = "<< i << "  " << w.l2 <<  " rey = " << re << endl;
+	    if(w.l2<1e-6) break; 
+	    // uu1=u1;uu2=u2;
+	    //plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[uu1,uu2]);  
+	    
+	  } ;
+      }
+    uu1=u1;uu2=u2;
+    streamlines;
+    if( mpirank==0) 
+    plot(coef=0.2,cmm="rey="+re+" [u1,u2] et p  ",psi,[uu1,uu2],wait=0,nbiso=20,ps="cavity-"+re+".ps");  
+  }
diff --git a/examples++-mpi/chaleur3D-hips.edp b/examples++-mpi/chaleur3D-hips.edp
new file mode 100644
index 0000000..d68a372
--- /dev/null
+++ b/examples++-mpi/chaleur3D-hips.edp
@@ -0,0 +1,9 @@
+// NBPROC 5
+//  bug with 4 proc very strange (Debug in progress)
+//ff-mpirun -np 4 chaleur3D-mumps.edp -glut ffglut -n 20 -op 1  -dt 0.01 -niter 10
+load "hips_FreeFem"
+real ttgv=1e10;
+string ssparams="";//"nprow=1, npcol="+mpisize; 
+verbosity=4; include "Heat3d.idp"
+
+
diff --git a/examples++-mpi/chaleur3D-hypre.edp b/examples++-mpi/chaleur3D-hypre.edp
new file mode 100644
index 0000000..edfb222
--- /dev/null
+++ b/examples++-mpi/chaleur3D-hypre.edp
@@ -0,0 +1,94 @@
+
+ // other
+load "msh3"
+load "medit"
+load "hypre_FreeFem"
+
+
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize; 
+
+func bool GetNoBC(matrix & A,real[int] & in)
+{ // def a array in such what
+// on unkwnon i
+// in[i] = 1 if no boundary condition
+// in[i] = 0 if boundary condition
+in = A.diag ; // take the daig of the matrix
+real tgv = in.max ;
+for(int i=0 ;i<in.n ;i++)
+in[i]= in[i] < tgv ; //
+cout << "tgv" << tgv << endl;
+return true ;
+}
+int nn=20;
+mesh Th2D=square(nn,nn);
+int[int] refm=[1,1,2,2,3,3,4,4];
+int[int] refu=[0,1];
+mesh3 Th=buildlayers(Th2D,nn,zbound=[0.,1.],labelmid=refm,labelup=refu,labeldown=refu);
+fespace Vh(Th,P2) ; // P1 FE space
+Vh uh,vh,u1=0 ; // unkown and test function.
+func f=1 ; // right hand side function
+func g=0 ; // boundary condition function
+real dt=0.01 ;
+
+real temps=clock();
+
+real time1,time2;
+time1=clock();
+varf vlaplace(uh,vh) = // definition de problem
+int3d(Th)( uh*vh+ dt*(dx(uh)*dx(vh) + dy(uh)*dy(vh)+ dz(uh)*dz(vh)) ) // bil. form
++ int3d(Th)( dt*vh*f) + on(1,2,3,4,uh=g) ;
+matrix A = vlaplace(Vh,Vh,tgv=ttgv) ;
+time1=clock()-time1;
+
+time2=clock();
+set(A,solver=sparsesolver,tgv=ttgv,sparams=ssparams) ; // factorisation
+time2=clock()-time2;
+
+real time3=clock();
+varf vmasse(u,v) = int3d(Th)(u*v);
+matrix M = vmasse(Vh,Vh);
+time3=clock()-time3;
+
+real [int] b(A.n) ;
+real[int] bcl(A.n) ;
+bcl = vlaplace(0,Vh) ; // les termes CL + second membre
+real[int] in(A.n) ; // un tableau : 1 si interne 0 si frontiere
+GetNoBC(A,in) ; // pour p´enalisation exact de CL (tgv sur aii)
+
+real time4=0,time5=0;
+int imax=10;
+for(int i=0 ;i<imax;i++)
+{
+cout << "time " << (i+1)*dt << endl;
+
+real time4tmp=clock();
+b = M*uh[];
+b = b.*in ; // mise a zero des noeud frontiere
+b += bcl ; // ajout des terme de CL + second membre
+time4=time4+(clock()-time4tmp);
+
+real time5tmp=clock();
+uh[] = A^-1*b ; // resolution
+time5=time5+(clock()-time5tmp);
+
+}
+savesol("Chaleur-Time-"+imax+"-nn-"+nn+"-superludist.sol",Th,uh);
+savemesh(Th,"Chaleur-Time-"+imax+"-nn-"+nn+"-superludist.mesh");
+cout << "temps resolution " << clock()-temps << endl;
+
+cout << "======================================" << endl;
+cout << " CPU TIME :                  " << endl;
+cout << " matrix A                    " << time1 << endl;
+cout << " factorization               " << time2 << endl;
+cout << " mass matrix                 " << time3 << endl;
+cout << " second member (Matrix vector Product with mass matrix)  " << endl;
+cout << "                             " << time4/imax << endl;
+cout << " solving                     " << time5/imax  << endl;
+cout << " all                         " << clock()-temps << endl;
+cout << "======================================" << endl;
+
+
+
+
diff --git a/examples++-mpi/chaleur3D-mumps.edp b/examples++-mpi/chaleur3D-mumps.edp
new file mode 100644
index 0000000..eb0cb37
--- /dev/null
+++ b/examples++-mpi/chaleur3D-mumps.edp
@@ -0,0 +1,8 @@
+// NBPROC 4
+//ff-mpirun -np 4 chaleur3D-mumps.edp -glut ffglut -n 20 -op 1  -dt 0.01 -niter 10
+load "MUMPS_FreeFem"
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize; 
+include "Heat3d.idp"
+
+
diff --git a/examples++-mpi/chaleur3D-pastix.edp b/examples++-mpi/chaleur3D-pastix.edp
new file mode 100644
index 0000000..9cc8736
--- /dev/null
+++ b/examples++-mpi/chaleur3D-pastix.edp
@@ -0,0 +1,91 @@
+ // other
+load "msh3"
+load "medit"
+load "real_pastix_FreeFem"
+
+real ttgv=1e10;
+string ssparams="nprow=1, npcol="+mpisize; 
+
+func bool GetNoBC(matrix & A,real[int] & in)
+{ // def a array in such what
+// on unkwnon i
+// in[i] = 1 if no boundary condition
+// in[i] = 0 if boundary condition
+in = A.diag ; // take the daig of the matrix
+real tgv = in.max ;
+for(int i=0 ;i<in.n ;i++)
+in[i]= in[i] < tgv ; //
+cout << "tgv" << tgv << endl;
+return true ;
+}
+int nn=20;
+mesh Th2D=square(nn,nn);
+int[int] refm=[1,1,2,2,3,3,4,4];
+int[int] refu=[0,1];
+mesh3 Th=buildlayers(Th2D,nn,zbound=[0.,1.],labelmid=refm,labelup=refu,labeldown=refu);
+fespace Vh(Th,P2) ; // P1 FE space
+Vh uh,vh,u1=0 ; // unkown and test function.
+func f=1 ; // right hand side function
+func g=0 ; // boundary condition function
+real dt=0.01 ;
+
+real temps=clock();
+
+real time1,time2;
+time1=clock();
+varf vlaplace(uh,vh) = // definition de problem
+int3d(Th)( uh*vh+ dt*(dx(uh)*dx(vh) + dy(uh)*dy(vh)+ dz(uh)*dz(vh)) ) // bil. form
++ int3d(Th)( dt*vh*f) + on(1,2,3,4,uh=g) ;
+matrix A = vlaplace(Vh,Vh,tgv=ttgv) ;
+time1=clock()-time1;
+
+time2=clock();
+set(A,solver=sparsesolver,tgv=ttgv,sparams=ssparams) ; // factorisation
+time2=clock()-time2;
+
+real time3=clock();
+varf vmasse(u,v) = int3d(Th)(u*v);
+matrix M = vmasse(Vh,Vh);
+time3=clock()-time3;
+
+real [int] b(A.n) ;
+real[int] bcl(A.n) ;
+bcl = vlaplace(0,Vh) ; // les termes CL + second membre
+real[int] in(A.n) ; // un tableau : 1 si interne 0 si frontiere
+GetNoBC(A,in) ; // pour p´enalisation exact de CL (tgv sur aii)
+
+real time4=0,time5=0;
+int imax=10;
+for(int i=0 ;i<imax;i++)
+{
+cout << "time " << (i+1)*dt << endl;
+
+real time4tmp=clock();
+b = M*uh[];
+b = b.*in ; // mise a zero des noeud frontiere
+b += bcl ; // ajout des terme de CL + second membre
+time4=time4+(clock()-time4tmp);
+
+real time5tmp=clock();
+uh[] = A^-1*b ; // resolution
+time5=time5+(clock()-time5tmp);
+
+}
+savesol("Chaleur-Time-"+imax+"-nn-"+nn+"-pastix.sol",Th,uh);
+savemesh(Th,"Chaleur-Time-"+imax+"-nn-"+nn+"-pastix.mesh");
+cout << "temps resolution " << clock()-temps << endl;
+
+cout << "======================================" << endl;
+cout << " CPU TIME :                  " << endl;
+cout << " matrix A                    " << time1 << endl;
+cout << " factorization               " << time2 << endl;
+cout << " mass matrix                 " << time3 << endl;
+cout << " second member (Matrix vector Product with mass matrix)  " << endl;
+cout << "                             " << time4/imax << endl;
+cout << " solving                     " << time5/imax  << endl;
+cout << " all                         " << clock()-temps << endl;
+cout << "======================================" << endl;
+
+
+
+
diff --git a/examples++-mpi/chaleur3D-superludist.edp b/examples++-mpi/chaleur3D-superludist.edp
new file mode 100644
index 0000000..9fe555b
--- /dev/null
+++ b/examples++-mpi/chaleur3D-superludist.edp
@@ -0,0 +1,8 @@
+ // other
+ // NBPROC 2
+// ff-mpirun -np 4 chaleur3D-superludist.edp -glut ffglut  -n 20 -op 1  -dt 0.01 -niter 10
+
+load "real_SuperLU_DIST_FreeFem"
+real ttgv=-1;
+string ssparams="nprow=1, npcol="+mpisize; 
+include "Heat3d.idp"
\ No newline at end of file
diff --git a/examples++-mpi/cmaes-mpi-VarIneq.edp b/examples++-mpi/cmaes-mpi-VarIneq.edp
new file mode 100644
index 0000000..ab0d7df
--- /dev/null
+++ b/examples++-mpi/cmaes-mpi-VarIneq.edp
@@ -0,0 +1,122 @@
+load "mpi-cmaes"
+
+
+int NN = 10;
+mesh Th = square(NN,NN);
+func f1=1.;
+func f2=-1.;
+func g1=0.;
+func g2=0.1;
+int iter=0;
+int nadapt=1;
+real starttol=1e-10,bctol=6.e-12;
+fespace Vh(Th,P1);
+Vh ou1,ou2;
+real pena=1000;
+
+
+for(int al=0;al<nadapt;++al)
+{
+	
+varf BVF(v,w) = int2d(Th)(0.5*dx(v)*dx(w) + 0.5*dy(v)*dy(w));
+varf LVF1(v,w) = int2d(Th)(f1*w);
+varf LVF2(v,w) = int2d(Th)(f2*w);
+matrix A =  BVF(Vh,Vh);
+real[int] b1 = LVF1(0,Vh) , b2 = LVF2(0,Vh); 
+
+varf Vbord(v,w) = on(1,2,3,4,v=1);
+//real[int] bord = Vbord(0,Vh);
+//real[int] in = bord ? 0 : 1;
+Vh In,Bord;
+Bord[] = Vbord(0,Vh,tgv=1);
+In[] = Bord[] ? 0:1;
+Vh gh1=Bord*g1,gh2=Bord*g2;
+
+
+
+//Function which create a vector of the search space type from
+//two finite element functions
+func int FEFToSSP(real[int] &fef1,real[int] &fef2,real[int] &ssp)
+{
+	int kX=0;
+	for(int i=0;i<Vh.ndof;++i)
+	{
+		if(In[][i])
+		{
+			ssp[kX] = fef1[i];
+			ssp[kX+In[].sum] = fef2[i];
+			++kX;
+		}
+	}
+	return 1;
+}
+//Function spliting a vector from the search space and fills
+//two finite element functions with it
+func int SSPToFEF(real[int] &fef1,real[int] &fef2,real[int] &ssp)
+{
+	int kX=0;
+	for(int i=0;i<Vh.ndof;++i)
+	{
+		if(In[][i])
+		{
+			fef1[i] = ssp[kX];
+			fef2[i] = ssp[kX+In[].sum];
+			++kX;
+		}
+		else
+		{
+			fef1[i] = gh1[][i];
+			fef2[i] = gh2[][i];
+		}
+	}
+	return 1;
+}
+
+
+func real IneqC(real[int] &X)
+{
+	real[int] constraints(In[].sum);
+	for(int i=0;i<In[].sum;++i)
+	{
+		constraints[i] = X[i] - X[i+In[].sum];
+		constraints[i] = constraints[i] <= 0 ? 0. : constraints[i];
+	}
+	return constraints.l2;
+}
+
+
+func real J(real[int] &X)
+{
+	Vh u1,u2;
+	SSPToFEF(u1[],u2[],X);
+	iter++;
+	real[int] Au1 = A*u1[], Au2 = A*u2[];
+	Au1 -= b1;
+	Au2 -= b2;
+	real val = u1[]'*Au1 + u2[]'*Au2;
+	val +=  pena * IneqC(X);
+	plot(u1,u2,nbiso=30,fill=1,dim=3,cmm="adapt level " + al + " - iteration " + iter + " - J = " + val,value=1);
+	return val ;
+}
+
+
+
+real[int] start(2*In[].sum);
+
+if(al==0)
+{
+	start(0:In[].sum-1) = 0.;
+	start(In[].sum:2*In[].sum-1) = 0.1;
+}
+else FEFToSSP(ou1[],ou2[],start);
+
+
+real mini = cmaesMPI(J,start,stopMaxFunEval=10000*(al+1),stopTolX=1.e-4/(10*(al+1)),initialStdDev=(0.025/(pow(100.,al))));
+Vh best1,best2;
+SSPToFEF(best1[],best2[],start);
+
+Th = adaptmesh(Th,best1,best2);
+ou1 = best1;
+ou2 = best2;
+
+}
\ No newline at end of file
diff --git a/examples++-mpi/complex_SuperLU_DIST_FreeFem.cpp b/examples++-mpi/complex_SuperLU_DIST_FreeFem.cpp
new file mode 100644
index 0000000..fadbfbb
--- /dev/null
+++ b/examples++-mpi/complex_SuperLU_DIST_FreeFem.cpp
@@ -0,0 +1,843 @@
+//   for automatic  compilation with ff-c++
+// FFCS - 23/5/12 - remove metis dependency because it interfers with identically-named libmetis.a from parmetis
+//ff-c++-LIBRARY-dep: superlu_dist  blas parmetis mpi fc
+//ff-c++-cpp-dep: 
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+/*
+  Interface freefem++ et SuperLU_DIST_2.3 
+
+  /bin/sh ff-mpic++ zSuperLU_DIST.cpp -I/Users/morice/librairie/SuperLU_DIST_2.3/SRC/ -L/Users/morice/librairie/openmpi/lib/ -lmpi -lopen-pal -lopen-rte -L/Users/morice/librairie/PATCHVECLIB/ -lwrapperdotblas -framework veclib -L/Users/morice/librairie/ParMetis-3.1/ -lparmetis -lmetis -L/Users/morice/librairie/SuperLU_DIST_2.3/lib/ -lsuperlu_dist_2.3
+
+*/
+
+// FFCS - required to define __int64 for MSMPI
+#include <stdint.h>
+
+#include <mpi.h>
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "superlu_zdefs.h"
+#include "ffsuperludistoption.hpp"
+
+
+template <class R> struct SuperLUmpiDISTDriver
+{
+    
+};
+template <> struct SuperLUmpiDISTDriver<Complex>
+{
+  /* Driver routines */
+   /* Driver routines */
+  static  Dtype_t R_SLU_T() { return SLU_Z;} 
+  static doublecomplex *dc(Complex *p)  { return (doublecomplex *) (void *) p;}
+  static doublecomplex **dc(Complex **p)  { return (doublecomplex **) (void *) p;}
+
+  // Remplacement doublecomplex par Complex
+  static void
+  pgssvx(superlu_options_t *p1, SuperMatrix *p2, 
+	  ScalePermstruct_t *p3,
+	  Complex *p4, int p5, int p6, gridinfo_t *p7,
+	  LUstruct_t *p8, SOLVEstruct_t *p9, double *p10,
+	  SuperLUStat_t *p11, int *p12)
+  {
+     pzgssvx( p1,p2,p3,
+	      dc(p4),p5,p6,p7,p8,p9,p10,p11,p12 );
+  }
+    
+  static void
+  pgssvx_ABglobal(superlu_options_t *p1, SuperMatrix *p2, 
+		  ScalePermstruct_t *p3, 
+		  Complex *p4, int p5, int p6, gridinfo_t *p7,
+		  LUstruct_t *p8, double *p9,
+		  SuperLUStat_t *p10, int *p11)
+   
+  {
+    pzgssvx_ABglobal( p1,p2,p3,
+		      dc(p4),p5,p6,p7,p8,p9,p10,p11 );
+  }
+
+
+  static void
+  Create_CompCol_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+			      Complex *p5, int_t *p6, int_t *p7,
+			      Stype_t p8, Dtype_t p9, Mtype_t p10)
+  {
+    zCreate_CompCol_Matrix_dist( p1,p2,p3,
+				 p4,dc(p5),p6,p7,p8,p9,p10 );
+  }
+
+  static  void
+  Create_CompRowLoc_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3,
+				 int_t p4, int_t p5, int_t p6,
+				 Complex *p7, int_t *p8, int_t *p9,
+				 Stype_t p10, Dtype_t p11, Mtype_t p12)
+  {
+    zCreate_CompRowLoc_Matrix_dist( p1,p2,p3,
+				    p4,p5,p6,dc(p7),p8,p9,p10,p11,p12 );
+  }
+
+  static  void
+  CompRow_to_CompCol_dist(int_t p1, int_t p2, int_t p3, 
+			   Complex *p4, int_t *p5, int_t *p6,
+			   Complex **p7, int_t **p8, int_t **p9)
+  {
+    zCompRow_to_CompCol_dist( p1,p2,p3,
+			      dc(p4),p5,p6,dc(p7),p8,p9 );
+  }
+
+
+  static void
+  Create_Dense_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, Complex *p4,
+			  int_t p5, Stype_t p6, Dtype_t p7,Mtype_t p8)
+  {
+     zCreate_Dense_Matrix_dist( p1,p2,p3,
+				dc(p4),p5,p6,p7,p8  );
+  }
+
+
+
+  static void
+  Create_SuperNode_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+			       Complex *p5, int_t *p6,
+			       int_t *p7, int_t *p8,
+			       int_t *p9, int_t *p10,
+			       Stype_t p11, Dtype_t p12, Mtype_t p13)
+  {
+    zCreate_SuperNode_Matrix_dist( p1,p2,p3,
+				   p4,dc(p5),p6,p7,p8,p9,p10,p11,p12,p13 );
+  }
+  
+  static void
+  Print_CompRowLoc_Matrix_dist(SuperMatrix *p1)
+  {
+    zPrint_CompRowLoc_Matrix_dist(p1);
+  }
+
+
+};
+
+template<class R>
+class ZSolveSuperLUmpi :   public MatriceMorse<R>::VirtualSolver, public SuperLUmpiDISTDriver<R>   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+   
+   
+  //mutable char           equed[1];
+  //yes_no_t       equil;
+  mutable SuperMatrix    A;
+  NCformat       *Astore;
+  //NCformat       *Ustore;
+  //SCformat       *Lstore;
+
+  mutable superlu_options_t options;
+  mutable mem_usage_t    mem_usage;
+  mutable ScalePermstruct_t ScalePermstruct;
+  mutable LUstruct_t        LUstruct;
+  mutable SOLVEstruct_t     SOLVEstruct;
+  mutable gridinfo_t        grid;
+
+  string string_option;
+  string data_option;
+  R             *a;
+  int           *asub, *xa;
+  int_t m, n, nnz;
+  // rajout pour //
+  int_t nprow,npcol;  /* process rows and process columns*/
+
+
+  int matrixdist; // type of distributed matrix
+  MPI_Comm commworld ;
+
+  static const int assembled =0;
+  static const int distributedglobal =1;
+  static const int distributed =2;
+
+public:
+  ZSolveSuperLUmpi(const MatriceMorse<R> &AA,int strategy,double ttgv, double epsilon,
+		  double pivot,double pivot_sym, string datafile,
+		   string param_char, KN<long> &pperm_r, KN<long> &pperm_c, void * ccommworld ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),string_option(param_char),data_option(datafile),
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+    commworld = ccommworld ? *static_cast<MPI_Comm*>( ccommworld) : MPI_COMM_WORLD;    
+    
+    R*      B;
+    //R*      X;
+    SuperLUStat_t stat;
+    int            info, ldb, nrhs=0;
+    int            i;
+    double*        berr;
+    
+    int iam;
+
+    // Add for distributed matrix
+    int_t         m_loc, m_loc_fst, fst_row, nnz_loc, fst_nnz;
+    R             *aloc;
+    int           *asubloc, *xaloc;
+    // End Add for distributed matrix
+    
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+
+    A.Store=0;  
+    /* Defaults */
+    nrhs  = 0;
+
+    /* lecture de nprow and npcol */
+    // Cas max deux procs
+    nprow = 1;
+    MPI_Comm_size(commworld,&npcol);
+
+    matrixdist=0;
+    /* set the default options */
+    set_default_options_dist(&options);
+    DiagScale_t optionDiagScale;
+    
+    //if(verbosity > 10) print_options_dist(&options);
+
+    if(!string_option.empty()) read_nprow_npcol_freefem( &string_option, &nprow, &npcol, &matrixdist);
+    if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+
+    if(!data_option.empty()) read_options_superlu_datafile(&data_option,&options,&nprow, &npcol, &matrixdist,&optionDiagScale);
+
+    //if(verbosity > 10) print_options_dist(&options);
+    
+     /* ------------------------------------------------------------
+	 INITIALIZE THE SUPERLU PROCESS GRID. 
+	 ------------------------------------------------------------*/
+    cout << "Complex superlu_gridinit " << commworld << " "<< ccommworld << " : "  << nprow << "X" <<  npcol <<endl;
+    superlu_gridinit(commworld , nprow, npcol, &grid);
+    cout << " --\n";
+    /* Bail out if I do not belong in the grid. */
+    iam = grid.iam;
+    if ( iam >= nprow * npcol ){
+      //superlu_gridexit(&grid);
+      printf("this process is not used in superlu %d \n",iam);
+    }
+    else
+      {
+	// matrix to procs and vectors
+	if( matrixdist == assembled ){
+	  
+	  if(!iam){
+	    cout <<  "iam=" << iam << endl;
+	    printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	    
+	    /* create the matrix for superlu_dist */
+	    n=AA.n;
+	    m=AA.m;
+	    nnz=AA.nbcoef;
+	  
+	    assert( AA.lg[n] == nnz );	   
+	    printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	    
+	    /* transform Row to Col */
+	    // cela coute cher comme fonction //
+	    // dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    // dCompRow_to_CompCol_dist(m,n,nnz,arow,asubrow,xarow,&a,&asub,&xa);
+	    
+	    // FFCS - "this->" required by g++ 4.7
+	    this->CompRow_to_CompCol_dist(m,n,nnz,AA.a,AA.cl,AA.lg,&a,&asub,&xa);
+	  
+	    /* Broadcast matrix A to the other PEs. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+
+	    MPI_Bcast( a,    nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );	    
+	    
+	  }
+	  else{
+	    /*
+	      printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	       Receive matrix A from PE 0. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    
+	    /* Allocate storage for compressed column representation. */
+	    // FFCS - "this->" required by g++ 4.7
+	    zallocateA_dist(n, nnz, this->dc(&a), &asub, &xa);
+	    
+	    MPI_Bcast( a, nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	  }
+	  
+	  Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	  
+	  cout << "Debut: Create_CompCol_Matrix_dist" <<endl;
+	  // FFCS - "this->" required by g++ 4.7
+	  this->Create_CompCol_Matrix_dist(&A, m, n, nnz, a, asub, xa, SLU_NC, R_SLU, SLU_GE);      
+	  cout << "Fin: Create_CompCol_Matrix_dist" <<endl;
+	  /* creation of pseudo solution + second member */
+	  
+	  if ( !(B = new Complex[m] ) ){
+	    //if ( !(B = doublecomplexMalloc_dist(m )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+
+	 
+// 	  /* set the default options */
+// 	  set_default_options_dist(&options);
+// 	  DiagScale_t optionDiagScale;
+// 	  if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	  
+	  /* Initialize ScalePermstruct and LUstruct. */
+	  ScalePermstructInit(m, n, &ScalePermstruct);
+	  if(!(pperm_r==NULL)  || !(pperm_c==NULL) ) ScalePermstruct.DiagScale=optionDiagScale;
+	  if( !(pperm_r==NULL) ) 
+	    for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[ii];
+	  if( !(pperm_c==NULL) )
+	    for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii]= pperm_c[ii];
+	  
+	  if( ScalePermstruct.DiagScale != NOEQUIL ){
+	    printf("FreeFem++ doesn't support change of the original matrix"); 
+	    exit(1);
+	  }
+	  LUstructInit(m, n, &LUstruct);
+	  
+	  /* Initialize the statistics variables. */
+	  PStatInit(&stat);
+	  
+	  ldb = m;
+	  nrhs=1;
+	  if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  berr[0]=0.;
+    	
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	
+	  /* INIT LU struct*/
+	  
+	  /* ONLY PERFORM THE LU DECOMPOSITION */
+	  //B.ncol = 0;  /* Indicate not to solve the system */
+	  
+	  nrhs=0;
+	  SuperLUmpiDISTDriver<R>::pgssvx_ABglobal(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					       &LUstruct, berr, &stat, &info);
+	
+	  if(verbosity)
+	    printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	  
+	  if ( verbosity) PStatPrint(&options,&stat,&grid);
+	  PStatFree(&stat);
+	  	 
+	}
+	//##########################################################
+	//
+	//       matrix distributed with matrix global given
+	//
+	//##########################################################
+	else if( matrixdist == distributedglobal) {
+	   if(!iam){
+
+	     printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	
+	     /* create the matrix for superlu_dist */
+	     n=AA.n;
+	     m=AA.m;
+	     nnz=AA.nbcoef;
+	     a=AA.a;
+	     asub=AA.cl;
+	     xa=AA.lg;
+	     
+	     xa[n] = nnz;
+	     printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	     
+	     /* Broadcast matrix A to the other PEs. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     MPI_Bcast( AA.a,    nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	     MPI_Bcast( AA.cl, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( AA.lg,   n+1, mpi_int_t,  0, grid.comm );
+	     
+	     
+	   }
+	   else
+	     {
+	     
+	     printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	     /* Receive matrix A from PE 0. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     /* Allocate storage for compressed column representation. */
+	     // FFCS - "this->" required by g++ 4.7
+	     zallocateA_dist(n, nnz, this->dc(&a), &asub, &xa);
+	     
+	     MPI_Bcast( a, nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	     MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+
+	   }
+	   
+	   /* Compute the number of rows to be distributed to local process */
+	   m_loc = m / (grid.nprow * grid.npcol); 
+	   m_loc_fst = m_loc;
+	   /* When m / procs is not an integer */
+	   if ((m_loc * grid.nprow * grid.npcol) != m) {
+	     /*m_loc = m_loc+1;
+	       m_loc_fst = m_loc;*/
+	     if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	       m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	   }
+	   
+	   fst_row = iam * m_loc_fst;
+	   
+	   nnz_loc = xa[fst_row+m_loc]-xa[fst_row];
+	   // FFCS - "this->" required by g++ 4.7
+	   zallocateA_dist(m_loc, nnz_loc, this->dc(&aloc), &asubloc, &xaloc);
+	   
+	   //xaloc = (int_t*) intMalloc_dist(m_loc+1);
+	   for(int ii=0; ii < m_loc; ii++){
+	     xaloc[ii] = xa[fst_row+ii]-xa[fst_row];	
+	   }
+	   
+	   xaloc[m_loc]=nnz_loc;
+	   
+	   fst_nnz = xa[fst_row];
+	   //aloc    = new R[nnz_loc];
+	   //aloc    = (Complex*) doubleMalloc_dist(nnz_loc);
+	   //asubloc = (int_t*)  intMalloc_dist(nnz_loc);
+	   
+	   for(int ii=0; ii < nnz_loc; ii++){
+	     aloc[ii] = a[fst_nnz+ii];
+	     asubloc[ii] = asub[fst_nnz+ii];
+	   }
+	   
+	   if( iam ){
+	     SUPERLU_FREE( a );
+	     SUPERLU_FREE( asub );
+	     SUPERLU_FREE( xa );
+	   }
+	   
+	   Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	   
+	   if(verbosity) cout << "Debut: Create_CompRowCol_Matrix_dist" <<endl;
+	   // FFCS - "this->" required by g++ 4.7
+	   if(verbosity) this->Create_CompRowLoc_Matrix_dist(&A, m, n, nnz_loc, m_loc, fst_row, aloc, asubloc, xaloc, SLU_NR_loc, R_SLU, SLU_GE);
+	   
+	   cout << "Fin: Create_CompRowCol_Matrix_dist" <<endl;
+	   /* creation of pseudo solution + second member */
+	   
+	   
+	   if ( !(B = new Complex[m_loc]) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   
+	   for(int ii=0; ii < m_loc; ii++){
+	     B[ii] = 1.; //BB[fst_row+ii];
+	   }
+     
+	   if(verbosity)
+	     printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   
+	   /* set the default options */
+	   set_default_options_dist(&options);
+	   DiagScale_t optionDiagScale;
+	   if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	   	   
+	   m=A.nrow;
+	   n=A.ncol;
+	   printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   /* Initialize ScalePermstruct and LUstruct. */
+	   ScalePermstructInit(m, n, &ScalePermstruct);
+	   if(pperm_r  ||  pperm_c ) ScalePermstruct.DiagScale=optionDiagScale;
+	   if(pperm_r) 
+	     for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[fst_row+ii];
+	   if(pperm_c) 
+	     for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii] = pperm_c[ii];
+	   
+	   LUstructInit(m, n, &LUstruct);
+	   
+
+
+	   /* Initialize the statistics variables. */
+	   PStatInit(&stat);
+	   
+	   ldb = m_loc;
+	   //ldx = m_loc;
+	   
+	   nrhs=1;
+	   if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   berr[0]=0.;
+	   
+	   /* ONLY PERFORM THE LU DECOMPOSITION */
+    
+	   nrhs=0;
+	   SuperLUmpiDISTDriver<R>::pgssvx(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					   &LUstruct, &SOLVEstruct, berr, &stat, &info);
+	   
+	   if(verbosity)
+	     printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	   
+	   if ( verbosity) PStatPrint(&options,&stat,&grid);
+	   PStatFree(&stat);
+	}
+	else if( matrixdist == distributed) {
+	  printf("in construction\n");
+	  exit(1);
+	}
+	else{
+	  printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	  exit(1);
+	}
+	
+	delete [] B;
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	nrhs=1;
+	SUPERLU_FREE(berr);  	
+
+	if(iam==0){
+	  finishtime = clock();
+	  timeused= (finishtime-starttime)/(1000 );
+	  printf("=====================================================\n");
+	  cout << "SuperLU_DIST : time factorisation :: " << timeused << " ms" <<endl;
+	  printf("=====================================================\n");
+	}
+	 
+      }
+  }
+
+  void Solver(const MatriceMorse<R> &AA,KN_<R> &x,const KN_<R> &b) const  {
+    R*        B;
+    SuperLUStat_t  stat;
+    int            iam;
+    int            info=0, ldb=m, nrhs=1;
+    int            i;
+    double*        berr;
+    double         ferr; 
+    double         rpg, rcond;
+      
+    int_t    m_loc,m_loc_fst,fst_row;
+    
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+
+    iam = grid.iam;
+    if( iam < nprow*npcol){
+
+      if(verbosity) starttime = clock();
+
+      if(n != m) exit(1);
+      
+      ffassert ( &x[0] != &b[0]);
+      epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+      
+      Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+      nrhs= 1;
+      
+      
+      /* Initialize the statistics variables. */
+      PStatInit(&stat);
+      
+      /* cas matrix assembled */ 
+      if( matrixdist == assembled ){
+      
+      if( !(B = new R[m*nrhs] ) ){
+	printf("probleme d allocation\n");
+	exit(1);
+	}
+	
+	for(int ii=0; ii<n; ii++){
+	  B[ii]=b[ii];
+	}
+	
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */   
+	ldb = m;
+	//nrhs= 1;
+	SuperLUmpiDISTDriver<R>::pgssvx_ABglobal (&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+						  &LUstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if(verbosity) PStatPrint(&options, &stat, &grid);   
+	
+	for(int ii=0; ii<n; ii++){
+	  x[ii] = B[ii]; 
+	}
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+      }
+      else if( matrixdist == distributedglobal) {
+	R*    xtemp;
+	iam = grid.iam;
+	/* Compute the number of rows to be distributed to local process */
+	m_loc = m / (grid.nprow * grid.npcol); 
+	m_loc_fst = m_loc;
+	/* When m / procs is not an integer */
+	if ((m_loc * grid.nprow * grid.npcol) != m) {
+	  /*m_loc = m_loc+1;
+	    m_loc_fst = m_loc;*/
+	  if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	    m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	}
+	
+	fst_row = iam * m_loc_fst;
+	
+	if ( !(B = new R[m_loc] ) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	//printf("initilisation B:");
+	for(int ii=0; ii<m_loc; ++ii){
+	  B[ii] = b[ii+fst_row];
+	  //printf("  B[%d]= %f  ",ii,B[ii]);
+	}
+	//printf(" :: fin \n");
+	//fflush(stdout);
+	
+      
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	//options.Equil = YES;
+	//options.Trans = TRANS;
+	
+	
+	ldb = m;
+	SuperLUmpiDISTDriver<R>::pgssvx(&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+					&LUstruct, &SOLVEstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if ( !(xtemp = new R[AA.n]) ){
+	  printf("probleme d allocation de xtemp\n");
+	  exit(1);
+	}
+	
+      
+	int disp[nprow*npcol];
+	MPI_Allgather(&fst_row, 1, MPI_INT, disp, 1, MPI_INT, grid.comm);
+	
+	int recv[nprow*npcol];
+	MPI_Allgather(&m_loc, 1, MPI_INT, recv, 1, MPI_INT, grid.comm);
+	
+	MPI_Allgatherv(B, m_loc, SuperLU_MPI_DOUBLE_COMPLEX, xtemp, recv, disp, SuperLU_MPI_DOUBLE_COMPLEX, grid.comm);
+	
+	for(int ii= 0; ii< AA.n ; ii++)
+	  x[ii] = xtemp[ii];
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+	delete [] xtemp;
+      
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+      
+
+      delete [] B;
+      SUPERLU_FREE( berr );
+      
+      PStatFree(&stat);
+
+      if(iam==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << " SuperLU_DIST : time solve  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+    }
+  }
+    
+  ~ZSolveSuperLUmpi() { 
+    int iam;
+    iam = grid.iam;
+    if(iam < nprow*npcol){
+      if(verbosity)
+	cout << "~SolveSuperLUmpi Complex:" << endl;
+      
+      if( matrixdist == assembled) {
+	//if( A.Store)  Destroy_CompCol_Matrix_dist(&A);
+	//if( L.Store && U.Store )  {
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	//}
+	if ( options.SolveInitialized ) {
+	  zSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributedglobal) {
+	if( A.Store)  Destroy_CompRowLoc_Matrix_dist(&A);
+	
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	
+	if ( options.SolveInitialized ) {
+	  zSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+    }
+    printf("superlu_gridexit(&grid), %d\n",iam);
+    superlu_gridexit(&grid); 
+   
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+
+
+MatriceMorse<Complex>::VirtualSolver *
+BuildSolverSuperLUmpi(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  if(verbosity>9)
+      cout << " BuildSolverSuperLUmpi<double>" << endl;
+  return new ZSolveSuperLUmpi<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym,
+				       ds.data_filename, ds.sparams, ds.perm_r, ds.perm_c, ds.commworld);
+}
+
+
+/* --FH:   class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+//DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    //DefSparseSolver<double>::solver =SparseMatSolver_R;
+    DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+
+    return false;
+}
+
+bool SetSuperLUmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to SuperLUmpi double" << endl;
+    //DefSparseSolver<double>::solver  =BuildSolverSuperLUmpi;
+    DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+
+    return false;
+}
+
+
+
+
+static void Load_Init()
+{ 
+  
+  //SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: Complex SuperLU_DIST,  defaultsolver defaultsolverSuperLUdist" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  //DefSparseSolver<double>::solver =BuildSolverSuperLUmpi;
+  DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("complexdefaulttoSuperLUdist","(",new OneOperator0<bool>(SetSuperLUmpi));
+}
+
+
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/complex_pastix_FreeFem.cpp b/examples++-mpi/complex_pastix_FreeFem.cpp
new file mode 100644
index 0000000..adc996b
--- /dev/null
+++ b/examples++-mpi/complex_pastix_FreeFem.cpp
@@ -0,0 +1,686 @@
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+//ff-c++-LIBRARY-dep: complex_pastix   blas parmetis metis scotch mpi fc
+//ff-c++-cpp-dep: 
+/*
+  Interface entre freefem++ et pastix
+*/
+#include <mpi.h>
+
+#include  <iostream>
+using namespace std;
+   
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+#include "pastix_long_complex.h"
+
+#undef memFree_null
+#define memFree_null(x) {if (x ==NULL) {fprintf(stdout,"%s:%d freeing NULL\n",__FILE__,__LINE__);} free(x); x=NULL;}
+
+#define STR_SIZE 256
+
+static pastix_int_t * pastixint(int * ii){ return (pastix_int_t*) (void *) ii;} 
+static pastix_float_t * pastixfloat(Complex * ii){ return (pastix_float_t*) (void *) ii;} 
+
+typedef struct pastix_param {
+  pastix_data_t          *pastix_data; /*Pointer used by PaStiX to keep information alive between calls */
+  MPI_Comm                comm;        /* Communicator used by PaStiX                                    */
+  pastix_int_t            Ncol;        /* Size of the Matrix                                             */
+  pastix_int_t           *ia;          /* Index of first element of each column in ja and avals          */  
+  pastix_int_t           *ja;          /* Rows of the unknows of the matrix                              */
+  pastix_float_t         *avals;       /* Values of the matrix                                           */
+  pastix_int_t           *perm;        /* Permutation used for re-numbering of the unknowns              */
+  pastix_int_t           *invp;        /* Inverse permutation                                            */
+  pastix_float_t         *rhs;         /* Right hand side                                                */
+  pastix_int_t           *iparm;       /* Integer parameters                                             */
+  double                 *dparm;       /* Floating parameters                                            */
+} pastix_param_t;
+
+
+
+void
+Morse_to_CSC(int m, int n, int nnz, 
+	     Complex *a, int *colind, int  *rowptr,
+	     pastix_float_t **at, pastix_int_t **rowind, 
+	     pastix_int_t **colptr)
+{
+    register int i, j, col, relpos;
+    pastix_int_t *marker;
+
+    /* Allocate storage for another copy of the matrix. */
+    *at     = (pastix_float_t *) malloc(sizeof(pastix_float_t)*nnz);
+    *rowind = (pastix_int_t *) malloc(sizeof(pastix_int_t)*nnz);
+    *colptr = (pastix_int_t *) malloc(sizeof(pastix_int_t)*(n+1));
+    marker  = (pastix_int_t *) malloc(sizeof(pastix_int_t)*n);
+    
+    for (i = 0; i < n; ++i)
+      marker[i] = 0;
+    /* Get counts of each column of A, and set up column pointers */
+    for (i = 0; i < m; ++i)
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) ++marker[colind[j]];
+    (*colptr)[0] = 0;
+    for (j = 0; j < n; ++j) {
+	(*colptr)[j+1] = (*colptr)[j] + marker[j];
+	marker[j] = (*colptr)[j];
+    }
+
+    /* Transfer the matrix into the compressed column storage. */
+    for (i = 0; i < m; ++i) {
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) {
+	    col = colind[j];
+	    relpos = marker[col];
+	    (*rowind)[relpos] = i;
+	    (*at)[relpos] = a[j];
+	    ++marker[col];
+	}
+    }
+
+    free(marker);
+}
+
+
+
+static const int MAX_CHAR_PER_LINE=256;
+//void read_datafile_pastixff(const string &datafile, pastix_int_t *iparmtab, double *dparmtab){
+void read_datafile_pastixff(const string &datafile, int &mpi_flag, pastix_int_t *iparmtab, double *dparmtab){
+  FILE*   m_File;
+  int     i = 0;
+  char    szbuff[MAX_CHAR_PER_LINE];
+  char*   token;
+
+  char filename[datafile.size()+1];  
+  strcpy( filename, datafile.c_str()); 
+
+  m_File = fopen(filename,"rt");
+
+  if(!m_File)
+    {
+      printf("error in reading filename %s\n",filename);
+    }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  
+  if( !(strcmp(token,"matrix") == 0) ){
+    printf("freefem++: error in reading matrix parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading matrix parameter for pastix \n");    
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+  
+  if(strcmp(token,"assembled") == 0)
+    mpi_flag = 0;
+  else if(strcmp(token,"distributedglobal") == 0) 
+    mpi_flag = 1;
+  else if(strcmp(token,"distributed") == 0) 
+    mpi_flag = 2;
+  else{
+    printf("value of parameter matrix is not correct %s \n", token );
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  if( !(strcmp(token,"iparm") == 0) ){
+    printf("freefem++: error in reading iparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading iparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      iparmtab[i] = (pastix_int_t)atol(token);
+      i++;
+    }
+
+  i=0;
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");  
+  if( !(strcmp(token,"dparm") == 0) ){
+    printf("freefem++: error in reading dparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading dparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      dparmtab[i] = atof(token);
+      i++;
+    }
+ 
+  fclose(m_File);
+
+#ifdef OOC
+/*   if (iparmtab[IPARM_OOC_THREAD] > 1) */
+    iparmtab[IPARM_OOC_THREAD] = 1;
+#endif
+  /* On empeche le 2d avec NUMA_ALLOC */
+#ifdef NUMA_ALLOC
+  if (iparmtab[IPARM_DISTRIBUTION_LEVEL] != 0)
+    {
+      errorPrint("2D not available with NUMA allocation\n");
+      exit(-1);
+    }
+#endif
+}
+
+// ATTENTION :: pastix_float_t  
+//      peut �tre soit un complex ou un reel cela depend de la maniere dont on a compiler pastix
+
+// CAS COMPLEX SEULEMENT 
+
+
+class zSolvepastixmpi :   public MatriceMorse<Complex>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  
+
+  int paraoption;
+  int myid, mpi_size;
+  int Nrow;
+  int mpi_flag;
+  int init_raff;
+  int thrd_flag;
+  int SYM;
+  
+  string data_option;
+  
+  mutable pastix_int_t    iparm[64];
+  mutable double          dparm[64];
+  mutable pastix_int_t    Ncol;
+  mutable pastix_int_t   *ia;
+  mutable pastix_int_t   *ja;
+  mutable pastix_float_t *avals;
+  mutable pastix_int_t   *loc2glob;
+  //char           *Type    = NULL;
+  //char           *RhsType = NULL;
+  mutable pastix_float_t *rhs;
+  mutable pastix_int_t   *perm;
+  mutable pastix_int_t   *invp;
+  mutable pastix_data_t  *pastix_data;
+  MPI_Comm commworld ;
+
+
+public:
+
+  zSolvepastixmpi(const MatriceMorse<Complex> &AA,int strategy,double ttgv, double epsilon,
+		  double pivot,double pivot_sym, string datafile, KN<long> &param_int, KN<double> &param_double, 
+		  KN<long> &pperm_r, KN<long> &pperm_c,void * ccommworld) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),tol_pivot_sym(pivot_sym),tol_pivot(pivot),
+    data_option(datafile) 
+  { 
+    commworld = ccommworld ? *static_cast<MPI_Comm*>( ccommworld) : MPI_COMM_WORLD;
+    //KN_<long> param_int(pparam_int);
+    //KN_<double> param_double(pparam_double);
+
+    //int m;
+    //int ierr;
+    struct timeval  tv1, tv2;
+    int nnz;
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+
+    ia    = NULL;
+    ja    = NULL;
+    avals   = NULL;
+    loc2glob = NULL;
+    rhs     = NULL;
+    pastix_data = NULL;
+    
+    // matrix assembled on host
+    MPI_Comm_rank(commworld, &myid);
+    printf("- Rang MPI : %d\n", myid);
+    MPI_Comm_size(commworld, &mpi_size);
+    // SYMETRIQUE
+    // MPI_flag need to unselect for non distributed matrix
+    mpi_flag  = 0;
+    thrd_flag = 0;
+
+    // ######################  
+    //pastix_int_t init_raff;
+    fprintf(stdout,"-- INIT PARAMETERS --\n");
+    
+    // reading iparm from array    
+    if(!data_option.empty()){
+      read_datafile_pastixff(data_option,mpi_flag,iparm,dparm);
+      if(mpi_flag != 0) 
+	cerr << "ERROR :: GLOBAT INPUT MATRIX FOR ALL PROCS  matrix=assembled" << endl;
+    }
+    else if( !(param_int==NULL) || !(param_double==NULL)){
+	if( ! (param_int==NULL) ) 
+      {
+	cout << "internal param_int" << endl;
+	assert(param_int.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  iparm[ii] = param_int[ii];
+	iparm[IPARM_MODIFY_PARAMETER] = API_YES;
+      }
+	if( !(param_double==NULL) ) 
+      {
+	cout << "internal param_double" << endl;
+	assert(param_double.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  dparm[ii] = param_double[ii];
+      }
+    }  
+    else{
+      iparm[IPARM_MODIFY_PARAMETER] = API_NO;
+      cout << "initialize default parameter" << endl;
+    }
+    
+    //################################
+    if(myid == 0){
+      Ncol = AA.m;
+      Nrow = AA.n;
+      nnz  = AA.nbcoef;
+      // Avant : on ecrit la transpos�e
+      
+      // AA.cl : indices des colonnes
+      // AA.lg : pointeurs des lignes
+      Morse_to_CSC( AA.n , AA.m, AA.nbcoef, AA.a, AA.cl, AA.lg, &avals, &ja, &ia);
+      // ia : pointeurs des colonnes
+      // ja : indices des lignes
+      
+      cout << "AA.n= "<< AA.n << " AA.m=" <<  AA.m << " AA.nbcoef=" << AA.nbcoef << endl;
+      
+      for(int ii=0; ii < Ncol+1; ii++){
+	ia[ii] = ia[ii]+1;
+      }
+      assert( ia[Ncol]-1 == AA.nbcoef );
+      for(int ii=0; ii < ia[Ncol]-1; ii++){
+	ja[ii] = ja[ii]+1; 
+      }
+      MPI_Bcast( &Ncol,   1,    MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast( &Nrow,   1,    MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast( &nnz,    1,    MPI_PASTIX_INT,   0, commworld );
+
+      MPI_Bcast( avals, nnz,    MPI_PASTIX_FLOAT, 0, commworld );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, commworld );
+    }
+    else{
+      MPI_Bcast( &Ncol, 1,        MPI_PASTIX_INT,  0, commworld );
+      MPI_Bcast( &Nrow, 1,        MPI_PASTIX_INT,  0, commworld );
+      MPI_Bcast( &nnz,  1,        MPI_PASTIX_INT,  0, commworld );
+      
+      avals = (pastix_float_t *) malloc( nnz*sizeof(pastix_float_t) );
+      ia = (pastix_int_t *) malloc( (Ncol+1)*sizeof(pastix_int_t) );
+      ja = (pastix_int_t *) malloc( nnz*sizeof(pastix_int_t) );
+
+      MPI_Bcast( avals, nnz,  MPI_PASTIX_FLOAT,   0, commworld );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, commworld );
+    }
+
+    perm = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    invp = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    
+    rhs = (pastix_float_t *) malloc(Ncol*sizeof(pastix_float_t));
+    
+    // reading permutation given by the user
+    if(pperm_r) 
+      for(int ii=0; ii < Ncol; ii++)
+	perm[ii] = pperm_r[ii];
+    if(pperm_c)  
+      for(int ii=0; ii < Ncol; ii++)
+	invp[ii] = pperm_c[ii];
+   
+  
+    iparm[IPARM_START_TASK] = API_TASK_INIT;
+    iparm[IPARM_END_TASK]   = API_TASK_INIT;
+    iparm[IPARM_SYM] = API_SYM_NO; // Matrix is considered nonsymetric    
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm); 
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    fprintf(stdout,"-- FIN INIT PARAMETERS --\n");
+    init_raff = iparm[IPARM_ITERMAX];
+    cout << "init_raff=" << init_raff << endl;
+    fflush(stdout);
+    /* Passage en mode verbose */
+    
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    if( (param_int==NULL) && data_option.empty() ){
+      iparm[IPARM_MATRIX_VERIFICATION] = API_YES;
+      iparm[IPARM_REFINEMENT] = API_RAF_GMRES;
+      iparm[IPARM_INCOMPLETE] = API_NO;
+    }
+
+    if( (param_double==NULL) && data_option.empty()){
+      dparm[DPARM_EPSILON_REFINEMENT] = 1e-12;
+      dparm[DPARM_EPSILON_MAGN_CTRL] = 1e-32;
+    }
+
+  
+ //    cscd_checksym(Ncol, ia, ja, loc2glob, commworld);
+    
+//     if (iparm[IPARM_SYM]==API_SYM_YES)
+//       {
+// 	/* Symetric problem */
+// 	/* Build non oriented graph */
+// 	/* build non symmetric csc from symmetric csc */
+// 	/*maillage global*/
+// 	INT *tmpia;
+// 	INT *tmpja;
+// 	INT  tmpn;
+	
+// 	cscd_symgraph_int(*n2,   *col2,  *row2 , NULL,
+// 			  &tmpn, &tmpia, &tmpja, NULL,
+// 			  *loc2glob2, pastix_comm, API_YES);
+	
+// 	memFree_null(*col2);
+// 	*col2 = tmpia;
+// 	memFree_null(*row2);
+// 	*row2 = tmpja;
+// 	*n2   = tmpn;
+//       }
+    
+
+    SYM = AA.symetrique; 
+    cout << "SYM = "<< SYM << endl;
+    // SYMETRIQUE
+    if( SYM == 1 ){
+      iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    
+    /* Scotch */
+    fprintf(stdout,"-- Scotch --\n");
+    fflush(stdout);
+    iparm[IPARM_START_TASK] = API_TASK_ORDERING;
+    iparm[IPARM_END_TASK]   = API_TASK_ORDERING; 
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl;  
+    iparm[IPARM_SYM] = API_SYM_NO;
+    /* Fax */
+    fprintf(stdout,"-- Fax --\n");
+    iparm[IPARM_START_TASK] = API_TASK_SYMBFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_SYMBFACT;
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    /* Blend */
+    fprintf(stdout,"-- Blend --\n");
+    iparm[IPARM_START_TASK] = API_TASK_ANALYSE;
+    iparm[IPARM_END_TASK]   = API_TASK_ANALYSE;
+    if( SYM == 1 ){
+      iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+   
+    /* Factorisation */
+    iparm[IPARM_START_TASK] = API_TASK_NUMFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_NUMFACT;
+    gettimeofday(&tv1, NULL);
+    fprintf(stdout,"-- SOPALIN --\n");
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+       cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call factorization : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+    
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    
+    //for(int ii=0; ii < ia[Ncol]-1; ii++)
+    //  ja[ii] = ja[ii]-1;
+
+    if(myid==0){
+      finishtime = clock();
+      timeused= (finishtime-starttime)/(1000 );
+      printf("=====================================================\n");
+      cout << " pastix : time factorization  :: " << timeused << " ms" <<endl;
+      printf("=====================================================\n");
+    }
+
+    
+  }
+  void Solver(const MatriceMorse<Complex> &AA,KN_<Complex> &x,const KN_<Complex> &b) const  {
+  
+    struct timeval  tv1, tv2;
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+    
+    // index for pastix    
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]+1;
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]+1;
+    
+    
+    // give value of the second member
+    for(int ii=0; ii < Ncol; ii++){
+      rhs[ii] = b[ii];  
+    }
+    
+  
+
+
+    //fprintf(stdout,"SOLVE STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    
+    /* updo */
+    iparm[IPARM_START_TASK] = API_TASK_SOLVE;
+    iparm[IPARM_END_TASK]   = API_TASK_SOLVE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call updown : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));    
+    
+    if(verbosity > 1)
+      for(int jj=0; jj < Ncol; jj++)
+	cout << "rhs["<< jj << "]=" << rhs[jj] << endl;
+    
+    
+    //fprintf(stdout,"RAFF STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    /* raff */
+    
+    
+    iparm[IPARM_START_TASK] = API_TASK_REFINE;
+    iparm[IPARM_END_TASK]   = API_TASK_REFINE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    iparm[IPARM_ITERMAX]    = init_raff;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call refinement : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+
+    
+    for(int ii=0; ii < Ncol; ii++)
+      x[ii] = rhs[ii];
+       
+    // index for freefem
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    
+    //for(int ii=0; ii < ia[Ncol]-1; ii++)
+    //  ja[ii] = ja[ii]-1;
+
+    if(myid==0){
+      finishtime = clock();
+      timeused= (finishtime-starttime)/(1000 );
+      printf("=====================================================\n");
+      cout << " pastix : time solve  :: " << timeused << " ms" <<endl;
+      printf("=====================================================\n");
+    }
+    
+    
+  }
+
+  ~zSolvepastixmpi(){
+    /* mem free */
+    iparm[IPARM_START_TASK] = API_TASK_CLEAN;
+    iparm[IPARM_END_TASK]   = API_TASK_CLEAN;
+    
+    pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+   
+    memFree_null(ia);
+    memFree_null(ja);
+    
+    /* Free mem no longer necessary */
+    memFree_null(perm);
+    memFree_null(rhs);
+    
+  }
+  
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+
+};
+
+MatriceMorse<Complex>::VirtualSolver *
+BuildSolverpastix_complex_mpi(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverpastix_complex_mpi<complex>" << endl;
+    return new zSolvepastixmpi(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym, ds.data_filename, 
+			       ds.lparams, ds.dparams, ds.perm_r, ds.perm_c,ds.commworld);
+}
+
+ /*  class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+//DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    //DefSparseSolver<double>::solver =SparseMatSolver_R;
+    DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+    return false;
+}
+
+bool Setpastixmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to pastixmpi" << endl;
+    //DefSparseSolver<double>::solver  =BuildSolverpastix_complex_mpi;
+    DefSparseSolver<Complex>::solver =BuildSolverpastix_complex_mpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+    return false;
+}
+
+
+
+static void Load_Init()
+{ 
+  
+  //SparseMatSolver_R= DefSparseSolver<d>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: pastix,  defaultsolver defaultsolverpastix" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  //DefSparseSolver<double>::solver =BuildSolverpastix_complex_mpi;
+  DefSparseSolver<Complex>::solver =BuildSolverpastix_complex_mpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("complexdefaulttopastix","(",new OneOperator0<bool>(Setpastixmpi));
+}
+
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/dSuperLU_DIST.cpp b/examples++-mpi/dSuperLU_DIST.cpp
new file mode 100644
index 0000000..54f5754
--- /dev/null
+++ b/examples++-mpi/dSuperLU_DIST.cpp
@@ -0,0 +1,740 @@
+//ff-c++-LIBRARY-dep: metis  superlu_dist parmetis blas mpi fc
+//ff-c++-cpp-dep: 
+/*
+  Interface freefem++ et SuperLU_DIST_2.3 
+
+  /bin/sh ff-mpic++ dSuperLU_DIST.cpp -I/Users/morice/librairie/SuperLU_DIST_2.3/SRC/ -L/Users/morice/librairie/openmpi/lib/ -lmpi -lopal -lorte -L/Users/morice/librairie/PATCHVECLIB/ -lwrapperdotblas -framework veclib -L/Users/morice/librairie/ParMetis-3.1/ -lparmetis -lmetis -L/Users/morice/librairie/SuperLU_DIST_2.3/lib/ -lsuperlu_dist_2.3
+
+*/
+#include <mpi.h>
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include "superlu_ddefs.h"
+#include "ffsuperludistoption-1.hpp"
+
+template <class R> struct SuperLUmpiDISTDriver
+{
+    
+};
+
+template <> struct SuperLUmpiDISTDriver<double>
+{
+  /* Driver routines */
+  static  Dtype_t R_SLU_T() { return SLU_D;} 
+  static void
+  
+  pgssvx(superlu_options_t *p1, SuperMatrix *p2, ScalePermstruct_t *p3,
+	  double *p4, int p5, int p6, gridinfo_t *p7,
+	  LUstruct_t *p8, SOLVEstruct_t *p9, double *p10,
+	  SuperLUStat_t *p11, int *p12)
+  { pdgssvx( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 ); }
+  
+    
+  static void
+  pgssvx_ABglobal(superlu_options_t *p1, SuperMatrix *p2, 
+	 ScalePermstruct_t *p3,
+	 double *p4, int p5, int p6, gridinfo_t *p7,
+	 LUstruct_t *p8, double *p9,
+	 SuperLUStat_t *p10, int *p11)
+  { pdgssvx_ABglobal( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11); }
+        
+  static void
+  Print_CompRowLoc_Matrix_dist(SuperMatrix *p1)
+  {
+    dPrint_CompRowLoc_Matrix_dist(p1);
+  }
+
+  static void
+  Create_CompCol_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+			     double *p5, int_t *p6, int_t *p7,
+			    Stype_t p8, Dtype_t p9, Mtype_t p10)
+  {
+    dCreate_CompCol_Matrix_dist(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
+  }
+  
+  static void
+  Create_CompRowLoc_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3,
+				 int_t p4, int_t p5, int_t p6,
+				 double *p7, int_t *p8, int_t *p9,
+				 Stype_t p10, Dtype_t p11, Mtype_t p12)
+  {
+    dCreate_CompRowLoc_Matrix_dist( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
+  }
+   
+  static void
+  CompRow_to_CompCol_dist(int_t p1, int_t p2, int_t p3, 
+                         double *p4, int_t *p5, int_t *p6,
+                         double **p7, int_t **p8, int_t **p9)
+  {
+    dCompRow_to_CompCol_dist( p1,p2,p3,p4,p5,p6,p7,p8,p9 );
+  }
+
+  static void
+  Create_Dense_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, double *p4,
+			    int_t p5, Stype_t p6, Dtype_t p7,
+			    Mtype_t p8)
+  {
+    dCreate_Dense_Matrix_dist( p1,p2,p3,p4,p5,p6,p7,p8 );  
+  }
+
+  static void
+  Create_SuperNode_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+				double *p5, int_t *p6,
+				int_t *p7, int_t *p8,
+				int_t *p9, int_t *p10,
+				Stype_t p11, Dtype_t p12, Mtype_t p13)
+  {
+    dCreate_SuperNode_Matrix_dist(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,  p11,p12,p13);
+  }
+
+};
+
+template<class R>
+class SolveSuperLUmpi :   public MatriceMorse<R>::VirtualSolver, public SuperLUmpiDISTDriver<R>   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+   
+   
+  //mutable char           equed[1];
+  //yes_no_t       equil;
+  mutable SuperMatrix    A;
+  NCformat       *Astore;
+  //NCformat       *Ustore;
+  //SCformat       *Lstore;
+
+  mutable superlu_options_t options;
+  mutable mem_usage_t    mem_usage;
+  mutable ScalePermstruct_t ScalePermstruct;
+  mutable LUstruct_t        LUstruct;
+  mutable SOLVEstruct_t     SOLVEstruct;
+  mutable gridinfo_t        grid;
+
+  string string_option;
+  string data_option;
+  R             *a;
+  int           *asub, *xa;
+  int_t m, n, nnz;
+  // rajout pour //
+  int_t nprow,npcol;  /* process rows and process columns*/
+
+
+  int matrixdist; // type of distributed matrix
+
+  static const int assembled =0;
+  static const int distributedglobal =1;
+  static const int distributed =2;
+
+public:
+  SolveSuperLUmpi(const MatriceMorse<R> &AA,string datafile,
+		  string param_char, KN<long> &pperm_r, KN<long> &pperm_c, MPI_Comm  * mpicommw) : 
+    string_option(param_char),data_option(datafile)
+  { 
+    
+    R*      B;
+    //R*      X;
+    SuperLUStat_t stat;
+    int            info, ldb, nrhs=0;
+    int            i;
+    double*        berr;
+    
+    int iam;
+    // Add for distributed matrix
+    int_t         m_loc, m_loc_fst, fst_row, nnz_loc, fst_nnz;
+    R             *aloc;
+    int           *asubloc, *xaloc;
+    // End Add for distributed matrix
+    A.Store=0;
+   
+    int status;
+   
+    /* Defaults */
+    nrhs  = 0;
+
+    /* lecture de nprow and npcol */
+    // Cas max deux procs
+    nprow = 1;
+    npcol = 1;
+    matrixdist=0;
+    /* set the default options */
+    set_default_options_dist(&options);
+    DiagScale_t optionDiagScale;
+    
+    //if(verbosity > 10) print_options_dist(&options);
+
+    if(!string_option.empty()) read_nprow_npcol_freefem( &string_option, &nprow, &npcol, &matrixdist);
+    if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+
+    if(!data_option.empty()) read_options_superlu_datafile(&data_option,&options,&nprow, &npcol, &matrixdist,&optionDiagScale);
+
+    //if(verbosity > 10) print_options_dist(&options);
+    
+     /* ------------------------------------------------------------
+	 INITIALIZE THE SUPERLU PROCESS GRID. 
+	 ------------------------------------------------------------*/
+    cout << "superlu_gridinit" <<endl;
+    if(mpicommw)
+      superlu_gridinit(*mpicommw, nprow, npcol, &grid);
+    else
+      // FFCS - MPI::COMM_WORLD is not accepted on mingw64+MSMPI?
+      superlu_gridinit(MPI_COMM_WORLD, nprow, npcol, &grid);
+    
+    /* Bail out if I do not belong in the grid. */
+    iam = grid.iam;
+    if ( iam >= nprow * npcol ){
+      //superlu_gridexit(&grid);
+      printf("this process is not used in superlu %d \n",iam);
+    }
+    else
+      {
+	// matrix to procs and vectors
+	if( matrixdist == assembled ){
+	  
+	  if(!iam){
+	    cout <<  "iam=" << iam << endl;
+	    printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	    
+	    /* create the matrix for superlu_dist */
+	    n=AA.n;
+	    m=AA.m;
+	    nnz=AA.nbcoef;
+	  
+	    assert( AA.lg[n] == nnz );	   
+	    printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	    
+	    /* transform Row to Col */
+	    // cela coute cher comme fonction //
+	    //dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    //dCompRow_to_CompCol_dist(m,n,nnz,arow,asubrow,xarow,&a,&asub,&xa);
+	    
+	    dCompRow_to_CompCol_dist(m,n,nnz,AA.a,AA.cl,AA.lg,&a,&asub,&xa);
+	  
+	    /* Broadcast matrix A to the other PEs. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    int infobcast=MPI_Bcast( a,    nnz, MPI_DOUBLE, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	    
+	  }
+	  else{
+	    /*
+	      printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	       Receive matrix A from PE 0. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    
+	    /* Allocate storage for compressed column representation. */
+	    dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    
+	    int infobcast=MPI_Bcast( a, nnz, MPI_DOUBLE, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	  }
+	  
+	  Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	  
+	  cout << "Debut: Create_CompCol_Matrix_dist" <<endl;
+	  // FFCS - "this->" required by g++ 4.7
+	  this->Create_CompCol_Matrix_dist(&A, m, n, nnz, a, asub, xa, SLU_NC, R_SLU, SLU_GE);      
+	  cout << "Fin: Create_CompCol_Matrix_dist" <<endl;
+	  /* creation of pseudo solution + second member */
+	  
+	  if ( !(B = doubleMalloc_dist(m )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+
+	 
+// 	  /* set the default options */
+// 	  set_default_options_dist(&options);
+// 	  DiagScale_t optionDiagScale;
+// 	  if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	  
+	  /* Initialize ScalePermstruct and LUstruct. */
+	  ScalePermstructInit(m, n, &ScalePermstruct);
+	  if(pperm_r  ||  pperm_c ) ScalePermstruct.DiagScale=optionDiagScale;
+	  if(pperm_r) 
+	    for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[ii];
+	  if(pperm_c)
+	    for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii]= pperm_c[ii];
+	  
+	  if( ScalePermstruct.DiagScale != NOEQUIL ){
+	    printf("FreeFem++ doesn't support change of the original matrix"); 
+	    exit(1);
+	  }
+	  LUstructInit(m, n, &LUstruct);
+	  
+	  /* Initialize the statistics variables. */
+	  PStatInit(&stat);
+	  
+	  ldb = m;
+	  nrhs=1;
+	  if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  berr[0]=0.;
+    	
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	
+	  /* INIT LU struct*/
+	  
+	  /* ONLY PERFORM THE LU DECOMPOSITION */
+	  //B.ncol = 0;  /* Indicate not to solve the system */
+	  
+	  nrhs=0;
+	  SuperLUmpiDISTDriver<R>::pgssvx_ABglobal(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					       &LUstruct, berr, &stat, &info);
+	
+	  if(verbosity)
+	    printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	  
+	  if ( verbosity) PStatPrint(&options,&stat,&grid);
+	  PStatFree(&stat);
+	  	 
+	}
+	//##########################################################
+	//
+	//       matrix distributed with matrix global given
+	//
+	//##########################################################
+	else if( matrixdist == distributedglobal) {
+	   if(!iam){
+
+	     printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	
+	     /* create the matrix for superlu_dist */
+	     n=AA.n;
+	     m=AA.m;
+	     nnz=AA.nbcoef;
+	     a=AA.a;
+	     asub=AA.cl;
+	     xa=AA.lg;
+	     
+	     xa[n] = nnz;
+	     printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	     
+	     /* Broadcast matrix A to the other PEs. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     MPI_Bcast( AA.a,    nnz, MPI_DOUBLE, 0, grid.comm );
+	     MPI_Bcast( AA.cl, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( AA.lg,   n+1, mpi_int_t,  0, grid.comm );
+	     
+	     
+	   }
+	   else{
+	     
+	     printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	     /* Receive matrix A from PE 0. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     /* Allocate storage for compressed column representation. */
+	     dallocateA_dist(n, nnz, &a, &asub, &xa);
+	     
+	     MPI_Bcast( a, nnz, MPI_DOUBLE, 0, grid.comm );
+	     MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+
+	   }
+	   
+	   /* Compute the number of rows to be distributed to local process */
+	   m_loc = m / (grid.nprow * grid.npcol); 
+	   m_loc_fst = m_loc;
+	   /* When m / procs is not an integer */
+	   if ((m_loc * grid.nprow * grid.npcol) != m) {
+	     /*m_loc = m_loc+1;
+	       m_loc_fst = m_loc;*/
+	     if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	       m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	   }
+	   
+	   fst_row = iam * m_loc_fst;
+	   
+	   nnz_loc = xa[fst_row+m_loc]-xa[fst_row];
+	   
+	   xaloc = (int_t*) intMalloc_dist(m_loc+1);
+	   for(int ii=0; ii < m_loc; ii++){
+	     xaloc[ii] = xa[fst_row+ii]-xa[fst_row];	
+	   }
+	   
+	   xaloc[m_loc]=nnz_loc;
+	   
+	   fst_nnz = xa[fst_row];
+	   aloc    = (double*) doubleMalloc_dist(nnz_loc);
+	   asubloc = (int_t*)  intMalloc_dist(nnz_loc);
+	   
+	   for(int ii=0; ii < nnz_loc; ii++){
+	     aloc[ii] = a[fst_nnz+ii];
+	     asubloc[ii] = asub[fst_nnz+ii];
+	   }
+	   
+	   
+	   Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	   
+	   cout << "Debut: Create_CompRowCol_Matrix_dist" <<endl;
+	   dCreate_CompRowLoc_Matrix_dist(&A, m, n, nnz_loc, m_loc, fst_row, aloc, asubloc, xaloc, SLU_NR_loc, R_SLU, SLU_GE);
+	   
+	   cout << "Fin: Create_CompRowCol_Matrix_dist" <<endl;
+	   /* creation of pseudo solution + second member */
+	   
+	   
+	   if ( !(B = doubleMalloc_dist(m_loc)) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   
+	   for(int ii=0; ii < m_loc; ii++){
+	     B[ii] = 1.; //BB[fst_row+ii];
+	   }
+     
+	   if(verbosity)
+	     printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   
+	   /* set the default options */
+	   set_default_options_dist(&options);
+	   DiagScale_t optionDiagScale;
+	   if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	   	   
+	   m=A.nrow;
+	   n=A.ncol;
+	   printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   /* Initialize ScalePermstruct and LUstruct. */
+	   ScalePermstructInit(m, n, &ScalePermstruct);
+	   if(pperm_r  ||  pperm_c ) ScalePermstruct.DiagScale=optionDiagScale;
+	   if(pperm_r) 
+	     for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[fst_row+ii];
+	   if(pperm_c) 
+	     for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii] = pperm_c[ii];
+	   
+	   LUstructInit(m, n, &LUstruct);
+	   
+
+
+	   /* Initialize the statistics variables. */
+	   PStatInit(&stat);
+	   
+	   ldb = m_loc;
+	   //ldx = m_loc;
+	   
+	   nrhs=1;
+	   if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   berr[0]=0.;
+	   
+	   /* ONLY PERFORM THE LU DECOMPOSITION */
+    
+	   nrhs=0;
+	   SuperLUmpiDISTDriver<R>::pgssvx(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					   &LUstruct, &SOLVEstruct, berr, &stat, &info);
+	   
+	   if(verbosity)
+	     printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	   
+	   if ( verbosity) PStatPrint(&options,&stat,&grid);
+	   PStatFree(&stat);
+	}
+	else if( matrixdist == distributed) {
+	  printf("in construction\n");
+	  exit(1);
+	}
+	else{
+	  printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	  exit(1);
+	}
+	
+	SUPERLU_FREE( B );
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	nrhs=1;
+	SUPERLU_FREE(berr);  	
+      }
+    }
+
+  void Solver(const MatriceMorse<R> &AA,KN_<R> &x,const KN_<R> &b) const  {
+    R*        B;
+    SuperLUStat_t  stat;
+    int            iam;
+    int            info=0, ldb=m, nrhs=1;
+    int            i;
+    double*        berr;
+    double         ferr; 
+    double         rpg, rcond;
+      
+    int_t    m_loc,m_loc_fst,fst_row;
+    
+    if(n != m) exit(1);
+
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+
+    Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+    nrhs= 1;
+    
+     
+    /* Initialize the statistics variables. */
+    PStatInit(&stat);
+
+    iam = grid.iam;
+    if( iam < nprow*npcol){
+      /* cas matrix assembled */ 
+      if( matrixdist == assembled ){
+	
+	if( !(B = doubleMalloc_dist(m*nrhs)) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	for(int ii=0; ii<n; ii++){
+	  B[ii]=b[ii];
+	}
+	
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */   
+	ldb = m;
+	//nrhs= 1;
+	SuperLUmpiDISTDriver<R>::pgssvx_ABglobal (&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+						  &LUstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if(verbosity) PStatPrint(&options, &stat, &grid);   
+	
+	for(int ii=0; ii<n; ii++){
+	  x[ii] = B[ii]; 
+	}
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+      }
+      else if( matrixdist == distributedglobal) {
+	double*    xtemp;
+	iam = grid.iam;
+	/* Compute the number of rows to be distributed to local process */
+	m_loc = m / (grid.nprow * grid.npcol); 
+	m_loc_fst = m_loc;
+	/* When m / procs is not an integer */
+	if ((m_loc * grid.nprow * grid.npcol) != m) {
+	  /*m_loc = m_loc+1;
+	    m_loc_fst = m_loc;*/
+	  if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	    m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	}
+	
+	fst_row = iam * m_loc_fst;
+	
+	if ( !(B = doubleMalloc_dist(m_loc )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	//printf("initilisation B:");
+	for(int ii=0; ii<m_loc; ++ii){
+	  B[ii] = b[ii+fst_row];
+	  //printf("  B[%d]= %f  ",ii,B[ii]);
+	}
+	//printf(" :: fin \n");
+	//fflush(stdout);
+	
+      
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	//options.Equil = YES;
+	//options.Trans = TRANS;
+	
+	
+	ldb = m;
+	SuperLUmpiDISTDriver<R>::pgssvx(&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+					&LUstruct, &SOLVEstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if ( !(xtemp = doubleMalloc_dist(AA.n)) ){
+	  printf("probleme d allocation de xtemp\n");
+	  exit(1);
+	}
+	
+      
+	int disp[nprow*npcol];
+	MPI_Allgather(&fst_row, 1, MPI_INT, disp, 1, MPI_INT, grid.comm);
+	
+	int recv[nprow*npcol];
+	MPI_Allgather(&m_loc, 1, MPI_INT, recv, 1, MPI_INT, grid.comm);
+	
+	MPI_Allgatherv(B, m_loc, MPI_DOUBLE, xtemp, recv, disp, MPI_DOUBLE, grid.comm);
+	
+	for(int ii= 0; ii< AA.n ; ii++)
+	  x[ii] = xtemp[ii];
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+	SUPERLU_FREE( xtemp );
+      
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+      
+
+      SUPERLU_FREE( B );
+      SUPERLU_FREE( berr );
+      
+      PStatFree(&stat);
+    }
+  }
+    
+  ~SolveSuperLUmpi() { 
+    int iam;
+    iam = grid.iam;
+    if(iam < nprow*npcol){
+      if(verbosity)
+	cout << "~SolveSuperLUmpi double:" << endl;
+      
+      if( matrixdist == assembled) {
+	//if( A.Store)  Destroy_CompCol_Matrix_dist(&A);
+	//if( L.Store && U.Store )  {
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	//}
+	if ( options.SolveInitialized ) {
+	  dSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributedglobal) {
+	if( A.Store)  Destroy_CompRowLoc_Matrix_dist(&A);
+	
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	
+	if ( options.SolveInitialized ) {
+	  dSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+    }
+    printf("superlu_gridexit(&grid), %d\n",iam);
+    superlu_gridexit(&grid); 
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverSuperLUmpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverSuperLUmpi<double>" << endl;
+    return new SolveSuperLUmpi<double>(*A,ds.data_filename, ds.sparams, ds.perm_r, ds.perm_c,static_cast<MPI_Comm*>(ds.commworld));
+}
+
+
+/* --FH:   class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+
+    return false;
+}
+
+bool SetSuperLUmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to SuperLUmpi double" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverSuperLUmpi;
+    //DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+
+    return false;
+}
+
+
+
+
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: SuperLUmpi,  defaultsolver defaultsolverSuperLUmpi" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverSuperLUmpi;
+  //DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoSuperLUmpi","(",new OneOperator0<bool>(SetSuperLUmpi));
+}
+
+
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/dmatrix.hpp b/examples++-mpi/dmatrix.hpp
new file mode 100755
index 0000000..555f2e3
--- /dev/null
+++ b/examples++-mpi/dmatrix.hpp
@@ -0,0 +1,88 @@
+// SUMMARY  :   matrix manipulation
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : P. Jolivet 
+// E-MAIL   : Pierre Jolivet <pierre.jolivet at ljll.math.upmc.fr>
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ */
+
+#include <vector>
+#include <mpi.h>
+#include <iostream>
+#include <numeric>
+
+struct step {
+    public:
+        step(int x, int y) : x(x), y(y) { }
+        int operator()() { return x += y; }
+
+    private:
+        int x, y;
+};
+
+template<unsigned char M, unsigned char S>
+static void CSR2COO(unsigned int n, int* compressedI, int* uncompressedI) {
+    if(S == 'U') {
+        for(int i = n - 1; i > -1; --i) {
+            if(M == 'F')
+                std::fill(uncompressedI + compressedI[i] - 1, uncompressedI + compressedI[i + 1] - 1, i + 1);
+            else
+                std::fill(uncompressedI + compressedI[i], uncompressedI + compressedI[i + 1], i + 1);
+        }
+    }
+    else if(S == 'L') {
+        for(int i = 1; i < n; ++i) {
+            if(M == 'F')
+                std::fill(uncompressedI + compressedI[i] - i - 1, uncompressedI + compressedI[i + 1] - i - 1, i + 1);
+            else
+                std::fill(uncompressedI + compressedI[i] - i, uncompressedI + compressedI[i + 1] - i - 1, i + 1);
+        }
+    }
+};
+
+template<bool WithDiagonal, unsigned char N,typename Scalar>
+static unsigned int trimCSR(unsigned int n, int* trimmedI, int* untrimmedI, int* trimmedJ, int* untrimmedJ, Scalar* trimmedC, Scalar* untrimmedC) {
+    unsigned int upper = 0;
+    for(unsigned int i = 0; i < n - WithDiagonal; ++i) {
+        trimmedI[i] = upper + (N == 'F');
+        int* jIndex = lower_bound(untrimmedJ + untrimmedI[i], untrimmedJ + untrimmedI[i + 1], i + !WithDiagonal);
+        unsigned int j = untrimmedI[i] + jIndex - (untrimmedJ + untrimmedI[i]);
+        if(N == 'F') {
+            for(unsigned int k = j; k < untrimmedI[i + 1]; ++k)
+                trimmedJ[upper + k - j] = untrimmedJ[k] + 1;
+
+        } else
+            std::copy(untrimmedJ + j, untrimmedJ + untrimmedI[i + 1], trimmedJ + upper);
+        std::copy(untrimmedC + j, untrimmedC + untrimmedI[i + 1], trimmedC + upper);
+        upper += untrimmedI[i + 1] - j;
+    }
+    if(WithDiagonal) {
+        trimmedI[n - 1] = upper + (N == 'F');
+        trimmedI[n] = trimmedI[n - 1] + 1;
+        trimmedJ[upper] = n - (N == 'C');
+        trimmedC[upper] = untrimmedC[untrimmedI[n] - 1];
+        return trimmedI[n];
+    }
+    else {
+        trimmedI[n] = trimmedI[n - 1];
+        return trimmedI[n + 1];
+    }
+};
diff --git a/examples++-mpi/essai-com.edp b/examples++-mpi/essai-com.edp
new file mode 100644
index 0000000..bb62e50
--- /dev/null
+++ b/examples++-mpi/essai-com.edp
@@ -0,0 +1,38 @@
+
+verbosity=100;
+cout << " rank = " << mpirank << " " << " size " << mpisize << endl;
+if ( mpisize > 1) 
+  if( mpirank==0) 
+    {
+      cout << " send to 1 " << endl;
+      processor(1) << 123456;
+    }
+  else if (mpirank==1) 
+    {
+      int k;
+      processor(0) >> k;
+      cout << " recived " << k << endl;
+    }
+int l= mpirank+100;
+cout << " l == " << l << " broadcast l from 0   mpirank = " << mpirank << endl;
+broadcast(processor(0),l);
+cout << " l == " << l << "  mpirank ="<< mpirank << endl;
+
+matrix<complex> A;
+
+if( mpirank==0)
+   A=[[1+1i,1i],[0,2-1i]];
+broadcast(processor(0),A);
+
+if (mpirank==1)
+  { A=A+A;
+    processor(0) << A;
+  }
+ else if(mpirank==0)
+   processor(1) >>  A;
+cout << " mpirank = " << " A =  " <<  A << endl;
+
+cout << " " <<  norm(A(1,1) - 2-1i) << endl;
+
+int[int] procs=[1,4,8];
+mpiGroup group(procs);
diff --git a/examples++-mpi/essai.edp b/examples++-mpi/essai.edp
new file mode 100644
index 0000000..e633db3
--- /dev/null
+++ b/examples++-mpi/essai.edp
@@ -0,0 +1,159 @@
+
+verbosity=2;
+cout << " rank = " << mpirank << " " << " size " << mpisize << endl;
+cout << " rank = " << mpiRank(mpiCommWorld) << " " << " size " << mpiSize(mpiCommWorld) << endl;
+if(mpisize>4)
+  { 
+    int[int] procs=[1,4];
+    mpiGroup gpr(procs);
+    cout << " before  ...  " << mpirank << endl;
+    mpiComm comm(gpr);
+    cout << " after ...  " << mpirank << "  in : " << bool(comm)   
+	 << " rank " << mpiRank(comm) << " / " << mpiSize(comm) <<endl;
+    mpiComm  n0comm(mpiCommWorld,mpirank%3,0);// MPI_Comm_split
+    mpiComm  n1comm(mpiCommWorld,mpirank%3,1);// MPI_Comm_split
+    mpiComm  n2comm(mpiCommWorld,mpirank%3,2);// MPI_Comm_split
+    if( ! n1comm)  // not in n1comm 
+      {
+	// MPI_Intercomm_create constructor 
+	mpiComm  nicomm(processor(n1comm,1),processor(n2comm,2),1000); 
+	mpiComm  n12comm(nicomm,true);  // MPI_Intercomm_merge cosntructor 
+      }
+  }
+
+if ( mpirank<2 && mpisize>=2)
+  { 
+    
+    if( mpirank==0) 
+      {
+	cout << mpirank << " send to 1 " << endl;
+	processor(1) << 123456; //  unblock send
+      }
+    else if (mpirank==1) 
+      {
+	int k;
+	processor(0) >> k; // block recv 
+	cout << " recived " << k << endl;
+      }
+    {
+      // UnBlock communication 
+      mpiRequest rq;
+      if( mpirank==0) 
+	{
+	  Isend(processor(1,rq),16.);
+	  mpiWait(rq);// Send
+	}
+      else if (mpirank==1) 
+	{
+	  real  k;
+	  Irecv(processor(0,rq),k);
+	  mpiWait(rq);// Recv 
+	  assert(k==16.);// verif..
+	}
+    }
+
+
+    {
+    //  Block Communication
+      if( mpirank==0) 
+	  Send(processor(1),16.);
+      else if (mpirank==1) 
+	{
+	  real  k;
+	  Recv(processor(0),k);
+	  assert(k==16.);// verif..
+	}
+    }
+
+  }
+int l= mpirank+100;
+cout << " l == " << l << " broadcast l from 0   mpirank = " << mpirank << endl;
+broadcast(processor(0),l);
+cout << " l == " << l << "  mpirank ="<< mpirank << endl;
+
+{
+matrix<complex> A;
+
+if( mpirank==0)
+   A=[[1+1i,1i],[0,2-1i]];
+broadcast(processor(0),A);
+
+
+if (mpirank==1)
+  { A=A+A;
+    processor(0) << A;
+  }
+ else if (mpirank==0)
+   processor(1) >>  A;
+
+cout << " mpirank = " << mpirank << " A =  " << endl;
+cout <<   A << endl;
+
+cout << " " <<  norm(A(1,1) - 2-1i) << endl;
+}
+
+// asyncronous  send/recv  messages....
+mpiRequest rr;
+real[int] vv(mpirank*mpisize:mpirank*mpisize+mpisize-1),ww(mpisize);
+processor(0,rr) << vv;
+if(mpirank==0)
+  {
+    mpiRequest[int] rq(mpisize);
+    cout << " --- in ++ " <<mpisize << endl;
+    for (int i=0;i<mpisize;++i)
+       processor(i,rq[i]) >> ww;
+    cout << " --- out ++ " <<mpisize << endl;
+
+    int k=0;
+    for (int i=0;i<mpisize;++i)
+      {
+	int k= mpiWaitAny(rq);
+	cout << k << "  mpiWaitAny " << ww << endl; 
+      }
+  }
+cout << " mpiWait " << mpiWait(rr) << " " << mpirank << endl;
+//  a way to get data from any proc ... 
+processor(0,rr) << vv;
+if(mpirank==0)
+  {
+    for (int i=0;i<mpisize;++i)
+      {
+	processor(-1) >> ww;  
+	cout << " case " << i << "   " <<  ww[0] << endl ;
+      }
+  }
+
+
+mpiAlltoall(vv,ww);
+cout << " all2all " << mpirank << " :  "  ;
+for(int i=0;i<mpisize;i++) 
+  cout << vv[i] << " ";
+cout << " -> "  ;
+for(int i=0;i<mpisize;i++) 
+  cout << ww[i] << " ";
+cout << endl; 
+
+
+real s0=mpiWtime();
+real[int,int] aa(10,mpisize),bb(10,mpisize);
+real [int,int] ss(10,mpisize);
+for(int i=0;i<10;i++)
+  for(int j=0;j<mpisize;j++) 
+    aa(i,j)=100*i+j;
+mpiAlltoall(aa,bb);
+mpiAlltoall(aa,bb,mpiCommWorld);
+mpiAllgather(aa(:,mpirank),ss);
+if(mpirank == 1) // just printing the result of one process ..
+    cout << " AllGather " << ss << endl;
+mpiGather (aa(:,mpirank),ss,processor(0,mpiCommWorld));
+if(mpirank == 0)
+    cout << " Gather " << ss << endl;
+
+mpiScatter(aa,bb(:,mpirank),processor(0,mpiCommWorld));
+
+cout << " all2all " << mpirank << " " << mpiWtime()-s0 << "s :  "  ;
+cout << mpirank << " aa = " << aa << endl;
+cout << mpirank << " bb = " << bb << endl;
+
+
+mpiBarrier(mpiCommWorld);
diff --git a/examples++-mpi/ffmumps_fileparam.txt b/examples++-mpi/ffmumps_fileparam.txt
new file mode 100644
index 0000000..28e9520
--- /dev/null
+++ b/examples++-mpi/ffmumps_fileparam.txt
@@ -0,0 +1,57 @@
+0         /* SYM :: 0 for unsymmetric matrix, 1 for symmetric definite positive matrix and 2 general symmetric matrix*/
+1        /* PAR :: 0 host not working during factorization and solves steps, 1 host working during factorization and solves steps*/
+ -1        /* ICNTL(1) :: output stream for error message  */ 
+ -1        /* ICNTL(2) :: output for diagnostic printing, statics and warning message */
+ -1        /* ICNTL(3) :: for global information */
+ 0         /* ICNTL(4) :: Level of printing for error, warning and diagnostic message */
+ 0         /* ICNTL(5) :: matrix format : 0 assemebled format, 1 elemental format. */
+ 7         /* ICNTL(6) :: control option for permuting and/or scalling the matrix in analysis phase  */
+ 6        /* ICNTL(7) :: pivot order strategy : AMD, AMF, metis, pord scotch*/
+ 77        /* ICNTL(8) :: Row and Column scalling strategy */
+ 1         /* ICNTL(9) :: 0 solve Ax = b, 1 solve the transposed system  A^t x = b :  parameter is not considered in the current version of freefem++*/
+ 0         /* ICNTL(10) :: number of steps of iterative refinement */
+ 0         /* ICNTL(11) :: statics related to linear system depending on ICNTL(9) */
+ 1         /* ICNTL(12) :: constrained ordering strategy for general symmetric matrix */
+ 0         /* ICNTL(13) :: method to control splitting of the root frontal matrix */
+ 20        /* ICNTL(14) :: percentage increase in the estimated working space (default 20%)*/
+ 0         /* ICNTL(15) :: not used in this version of MUMPS */
+ 0         /* ICNTL(16) :: not used in this version of MUMPS */
+ 0         /* ICNTL(17) :: not used in this version of MUMPS */
+ 1         /* ICNTL(18) :: method for given : matrix pattern and matrix entries  : */
+ 0         /* ICNTL(19) :: method to return schur complement matrix */
+ 0         /* ICNTL(20) :: right hand side form ( 0 dense form, 1 sparse form)  : parameter will be set to 0 for freefem++ */
+ 0         /* ICNTL(21) :: 0, 1 kept distributed solution  :  parameter is not considered in the current version of freefem++ */
+ 0         /* ICNTL(22) :: controls the in-core/out-of-core (OOC) facility */
+ 0         /* ICNTL(23) :: maximum size of the working memory in MegaByte than MUMPS can allocate per working processor */
+ 0         /* ICNTL(24) :: control the detection of null pivot */
+ 0         /* ICNTL(25) :: control the computation of a null space basis */
+ 0         /* ICNTL(26) :: This parameter is only significant with Schur option (ICNTL(19) not zero). : parameter is not considered in the current version of freefem++ */
+ -8        /* ICNTL(27) (Experimental parameter subject to change in next release of MUMPS) :: control the blocking factor for multiple rightand side during the solution phase : parameter is not considered in the current version of freefem++ */
+ 0         /* ICNTL(28) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(29) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(30) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(31) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(32) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(33) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(34) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(35) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(36) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(37) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(38) :: not used in this version of MUMPS*/
+ 1         /* ICNTL(39) :: not used in this version of MUMPS*/
+ 0         /* ICNTL(40) :: not used in this version of MUMPS*/
+ 0.01	   /* CNTL(1) :: relative threshold for numerical pivoting */
+ 1e-8      /* CNTL(2) :: stopping criteria for iterative refinement */
+ -1        /* CNTL(3) :: threshold for null pivot detection */
+ -1	   /* CNTL(4) :: determine the threshold for partial pivoting */
+ 0.0	   /* CNTL(5) :: fixation for null pivots */
+  0	   /* CNTL(6) :: not used in this version of MUMPS */
+  0	   /* CNTL(7) :: not used in this version of MUMPS */
+  0	   /* CNTL(8) :: not used in this version of MUMPS */
+  0	   /* CNTL(9) :: not used in this version of MUMPS */
+  0	   /* CNTL(10) :: not used in this version of MUMPS */
+  0	   /* CNTL(11) :: not used in this version of MUMPS */
+  0	   /* CNTL(12) :: not used in this version of MUMPS */
+  0	   /* CNTL(13) :: not used in this version of MUMPS */
+  0	   /* CNTL(14) :: not used in this version of MUMPS */
+  0	   /* CNTL(15) :: not used in this version of MUMPS */	  
diff --git a/examples++-mpi/ffpastix_iparm_dparm.txt b/examples++-mpi/ffpastix_iparm_dparm.txt
new file mode 100644
index 0000000..c196481
--- /dev/null
+++ b/examples++-mpi/ffpastix_iparm_dparm.txt
@@ -0,0 +1,132 @@
+matrix
+assembled #  assembled (input global matrix to proc), distributedglobal ( the input global matrix is distributed to procs ), distributed  (input distributed matrix). distributedglobal and distrbuted not work yet with FreeFem++.
+iparm
+1         #  Indicate if parameters have been set by user                 index : IPARM_MODIFY_PARAMETER (IN)
+1         #  Indicate the first step to execute (see PaStiX steps)        index : IPARM_START_TASK (IN)
+7         #  Indicate the last step to execute (see PaStiX steps)         index : IPARM_END_TASK (IN)
+1         #  Verbose mode (see Verbose modes)                             index : IPARM_VERBOSE (IN)
+1         #  Degree of freedom per node                                   index : IPARM_DOF_NBR (IN)
+250       #  Maximum iteration number for refinement                      index : IPARM_ITERMAX (IN)
+0         #  Check the input matrix                                       index : IPARM_MATRIX_VERIFICATION (IN)
+0         #  MC64 operation <pastix.h> IGNORE                             index : IPARM_MC64 (IN)
+0         #  Refinement only                                              index : IPARM_ONLY_RAFF (IN)
+0         #  Indicate if the cscd has been redistributed after blend      index : IPARM_CSCD_CORRECT (IN)
+0         #  Number of iterations performed in refinement                 index : IPARM_NBITER (OUT)
+0         #  Trace format (see Trace modes)                               index : IPARM_TRACEFMT (IN)
+1         #  Specify if the given graph is distributed or not             index : IPARM_GRAPHDIST (IN)
+5         #  Amalgamation level                                           index : IPARM_AMALGAMATION_LEVEL (IN)
+0         #  Choose ordering                                              index : IPARM_ORDERING (IN)
+1         #  Use default ordering parameters with scotch or metis         index : IPARM_DEFAULT_ORDERING (IN)
+120       #  Ordering switch level    (see Scotch User's Guide)           index : IPARM_ORDERING_SWITCH_LEVEL (IN)
+0         #  Ordering cmin parameter  (see Scotch User's Guide)           index : IPARM_ORDERING_CMIN (IN)
+100000    #  Ordering cmax parameter  (see Scotch User's Guide)           index : IPARM_ORDERING_CMAX (IN)
+8         #  Ordering frat parameter  (see Scotch User's Guide)           index : IPARM_ORDERING_FRAT (IN)
+0         #  Static pivoting                                              index : IPARM_STATIC_PIVOTING (OUT)
+0         #  Metis pfactor                                                index : IPARM_METIS_PFACTOR (IN)
+0         #  Number of Non Zeros in initial matrix                        index : IPARM_NNZEROS (OUT)
+0         #  Number of Non Zeros in the factorized matrix                 index : IPARM_ALLOCATED_TERMS (OUT)
+0         #  Baseval used for the matrix                                  index : IPARM_BASEVAL (IN)
+60        #  Minimum blocksize                                            index : IPARM_MIN_BLOCKSIZE (OUT)
+120       #  Maximum blocksize                                            index : IPARM_MAX_BLOCKSIZE (OUT)
+0         #  unused                                                       index : 27  
+0         #  unused                                                       index : 28  
+0         #  unused                                                       index : 29  
+1         #  Factorization mode (see Factorization modes)                 index : IPARM_FACTORIZATION (IN)
+0         #  unused                                                       index : 31  
+0         #  Number of CPU per SMP node                                   index : IPARM_CPU_BY_NODE (IN)
+1         #  Thread binding mode (see Thread binding modes)               index : IPARM_BINDTHRD (IN)
+1         #  Number of thread per MPI process                             index : IPARM_THREAD_NBR (IN)
+0         #  Distribution level IGNORE                                    index : IPARM_DISTRIBUTION_LEVEL (IN)
+1         #  Level of fill for incomplete factorization                   index : IPARM_LEVEL_OF_FILL (IN)
+0         #  IO strategy (see Check-points modes)                         index : IPARM_IO_STRATEGY (IN)
+1         #  Right-hand-side making (see Rhight-hand-side modes)          index : IPARM_RHS_MAKING (IN)
+0         #  Refinement type (see Refinement modes)                       index : IPARM_REFINEMENT (IN)
+0         #  Symmetric matrix mode (see Symmetric modes)                  index : IPARM_SYM (IN)
+0         #  Incomplete factorization                                     index : IPARM_INCOMPLETE (IN)
+0         #  ABS (Automatic Blocksize Splitting)                          index : IPARM_ABS (IN)
+0         #  ESP (Enhanced Sparse Parallelism)                            index : IPARM_ESP (IN)
+25        #  GMRES restart parameter                                      index : IPARM_GMRES_IM (IN)
+0         #  Free user CSC                                                index : IPARM_FREE_CSCUSER (IN)
+0         #  Free internal CSC (Use only without call to Refin. step)     index : IPARM_FREE_CSCPASTIX (IN)
+2000      #  Out of core memory limit (Mo)                                index : IPARM_OOC_LIMIT (IN)
+1         #  Out of core thread number IGNORE                             index : IPARM_OOC_THREAD (IN)
+0         #  Out of core run ID        IGNORE                             index : IPARM_OOC_ID (OUT)
+0         #  Number of SMP node used   IGNORE                             index : IPARM_NB_SMP_NODE_USED (IN)
+0         #  Threaded communication mode (see Communication modes)        index : IPARM_THREAD_COMM_MODE (IN)
+1         #  Number of thread(s) for communication                        index : IPARM_NB_THREAD_COMM (IN)
+0         #  Initialize matrix coefficients (for test only)  IGNORE       index : IPARM_FILL_MATRIX (IN)
+0         #  Return the inertia (symmetric matrix without pivoting)       index : IPARM_INERTIA (OUT)
+0         #  Return the NUMBER OF TASKS GENERATED BY ESP                  index : IPARM_ESP_NBTASKS (OUT)
+0         #  unused                                                       index : 56  
+0         #  unused                                                       index : 57  
+0         #  unused                                                       index : 58  
+0         #  unused                                                       index : 59  
+0         #  unused                                                       index : 60  
+0         #  unused                                                       index : 61  
+0         #  unused                                                       index : 62  
+0         #  Return value                                                 index : IPARM_ERROR_NUMBER (OUT)
+dparm
+0         #  unused                                                       index : 0  
+0         #  unused                                                       index : 1  
+0         #  unused                                                       index : 2  
+0         #  unused                                                       index : 3  
+0         #  unused                                                       index : 4  
+1e-12     #  Epsilon for refinement                                       index : 5 (IN)
+0         #  Relative backward error                                      index : 6 (OUT)
+0         #  unused                                                       index : 7  
+0         #  unused                                                       index : 8  
+0         #  unused                                                       index : 9  
+1e-31     #  Epsilon for magnitude control                                index : 10 (IN)
+0         #  unused                                                       index : 11  
+0         #  unused                                                       index : 12  
+0         #  unused                                                       index : 13  
+0         #  unused                                                       index : 14  
+0         #  unused                                                       index : 15  
+0         #  unused                                                       index : 16  
+0         #  unused                                                       index : 17  
+0         #  Analize time                                                 index : 18 (OUT)
+0         #  Predicted factorization time                                 index : 19 (OUT)
+0         #  Factorization time                                           index : 20 (OUT)
+0         #  Solving time                                                 index : 21 (OUT)
+0         #  Factorization flops                                          index : 22 (OUT)
+0         #  Solving flops                                                index : 23 (OUT)
+0         #  Refinement time                                              index : 24 (OUT)
+0         #  unused                                                       index : 25  
+0         #  unused                                                       index : 26  
+0         #  unused                                                       index : 27  
+0         #  unused                                                       index : 28  
+0         #  unused                                                       index : 29  
+0         #  unused                                                       index : 30  
+0         #  unused                                                       index : 31  
+0         #  unused                                                       index : 32  
+0         #  unused                                                       index : 33  
+0         #  unused                                                       index : 34  
+0         #  unused                                                       index : 35  
+0         #  unused                                                       index : 36  
+0         #  unused                                                       index : 37  
+0         #  unused                                                       index : 38  
+0         #  unused                                                       index : 39  
+0         #  unused                                                       index : 40  
+0         #  unused                                                       index : 41  
+0         #  unused                                                       index : 42  
+0         #  unused                                                       index : 43  
+0         #  unused                                                       index : 44  
+0         #  unused                                                       index : 45  
+0         #  unused                                                       index : 46  
+0         #  unused                                                       index : 47  
+0         #  unused                                                       index : 48  
+0         #  unused                                                       index : 49  
+0         #  unused                                                       index : 50  
+0         #  unused                                                       index : 51  
+0         #  unused                                                       index : 52  
+0         #  unused                                                       index : 53  
+0         #  unused                                                       index : 54  
+0         #  unused                                                       index : 55  
+0         #  unused                                                       index : 56  
+0         #  unused                                                       index : 57  
+0         #  unused                                                       index : 58  
+0         #  unused                                                       index : 59  
+0         #  unused                                                       index : 60  
+0         #  unused                                                       index : 61  
+0         #  unused                                                       index : 62  
+0         #  unused                                                       index : 63  
diff --git a/examples++-mpi/ffsuperlu_dist_fileparam.txt b/examples++-mpi/ffsuperlu_dist_fileparam.txt
new file mode 100644
index 0000000..8ca1564
--- /dev/null
+++ b/examples++-mpi/ffsuperlu_dist_fileparam.txt
@@ -0,0 +1,16 @@
+2                     /* nprow : integer value     */
+1                     /* npcol : integer value     */
+distributedglobal             /* matrix input : assembled, distributedglobal, distributed */
+DOFACT                /* Fact  : DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED */
+NO                    /* Equil : NO, YES */
+YES                    /* ParSymbFact : NO, YES */
+METIS_AT_PLUS_A       /* ColPerm : NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A, PARMETIS, MY_PERMC */
+LargeDiag             /* RowPerm : NOROWPERM, LargeDiag, MY_PERMR */
+1.0                   /* DiagPivotThresh : real value */
+NOREFINE              /* IterRefine : NOREFINE, SINGLE, DOUBLE, EXTRA */
+NOTRANS               /* Trans      : NOTRANS, TRANS, CONJ*/
+NO                    /* ReplaceTinyPivot  : NO, YES*/
+NO                    /* SolveInitialized  : NO, YES*/
+NO                    /* RefineInitialized : NO, YES*/
+NO                    /* PrintStat : NO, YES*/
+NOEQUIL               /* DiagScale : NOEQUIL, ROW, COL, BOTH*/ 
diff --git a/examples++-mpi/ffsuperludistoption-1.hpp b/examples++-mpi/ffsuperludistoption-1.hpp
new file mode 100644
index 0000000..09bf277
--- /dev/null
+++ b/examples++-mpi/ffsuperludistoption-1.hpp
@@ -0,0 +1,507 @@
+// read options for superlu in freefem++
+int s_(char* str, const char* cmp[])
+{
+  int i = 0;
+  while( cmp[i] != 0){
+    if( strcmp(str, cmp[i]) == 0){
+      //cout << *str << " return" << i << endl;
+      return i+1 ;
+    }
+    i++;
+  }
+  //cout << *str << " return 0" << endl;
+  return 0;
+}
+
+void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol){
+  
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+  
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2 = tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 13: // nprow
+	*nprow = atoi(tictac);
+	break;
+      case 14: // npcol 
+	*npcol = atoi(tictac);
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+	    exit(1);
+	  }	  
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+}
+
+void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol, int *matrixdist){
+  
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol","matrix",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+  
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2 = tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+    printf("param %s = value %s , id_option %d\n",tictac2,tictac,id_option);
+    switch (id_option)
+      { 
+      case 13: // nprow
+	*nprow = atoi(tictac);
+	break;
+      case 14: // npcol 
+	*npcol = atoi(tictac);
+	break;
+      case 15: // matrix
+	printf("parameter matrix \n");
+	if(strcmp(tictac,"assembled") == 0)
+	  *matrixdist = 0;
+	else if(strcmp(tictac,"distributedglobal") == 0) 
+	  *matrixdist = 1;
+	else if(strcmp(tictac,"distributed") == 0) 
+	  *matrixdist = 2;
+	else{
+	  printf("value of parameter matrix is not correct %s \n", tictac );
+	}
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+	    exit(1);
+	  }	  
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+}
+
+
+void read_options_freefem(string *string_option, superlu_options_t *options, DiagScale_t *diag){
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[6] = {NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A,PARMETIS, MY_PERMC};
+  static const rowperm_t  enumrowperm_t[3] = {NOROWPERM, LargeDiag, MY_PERMR};
+  static const DiagScale_t enumDiagScale_t[4] = {NOEQUIL, ROW, COL, BOTH};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const IterRefine_t enumIterRefine_t[4] = {NOREFINE, SLU_SINGLE, SLU_DOUBLE, SLU_EXTRA};  
+  //static const MemType enumMemType_t[4] = {LUSUP, UCOL, LSUB, USUB};  
+  //static const stack_end_t enumstack_end_t[2] = {HEAD, TAIL};
+  //static const LU_space_t enumLU_space_t[2] = {SYSTEM, USER};
+
+ 
+  static const char* compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* comprowperm_t[] = {"NOROWPERM", "LargeDiag", "MY_PERMR",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_AT_PLUS_A", "MMD_ATA", "METIS_AT_PLUS_A", "PARMETIS", "MY_PERMC",0};
+  static const char* compDiagScale_t[] = {"NOEQUIL", "ROW", "COL", "BOTH",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  //static const char* compMemType_t[] = {"LUSUP", "UCOL", "LSUB", "USUB",0};  
+  //static const char* compstack_end_t[] = {"HEAD", "TAIL",0};
+  //static const char* compLU_space_t[] = {"SYSTEM", "USER",0};
+
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol","DiagScale","matrix",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  cout << "data=" << data << endl;
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2=tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 1 : // Fact
+	//char* comp1[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+	val_options= s_(tictac,compfact_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+	  exit(1);
+	}
+	options->Fact = enumfact_t[val_options-1];
+	break;
+      case 2:  // Equil
+	//char* comp2[] = {"NO", "YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+	  exit(1);
+	}
+	options->Equil = enumyes_no_t[val_options-1];
+	break;
+      case 3:  // ParSymbFact
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ParSymbFact = enumyes_no_t[val_options-1];
+	break;
+      case 4:  // ColPerm
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compcolperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ColPerm = enumcolperm_t[val_options-1];
+	break;
+      case 5:  // RowPerm
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,comprowperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->RowPerm = enumrowperm_t[val_options-1];
+	break;
+      case 6:  // DiagPivotThresh
+	options->DiagPivotThresh= strtod(tictac,&tictac);
+	break;
+      case 7:  // IterRefine
+	val_options= s_(tictac,compIterRefine_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->IterRefine = enumIterRefine_t[val_options-1];
+	break;
+      case 8:  // Trans
+	//char* comp5[] = {"NOTRANS", "TRANS", "CONJ", 0};
+	val_options= s_(tictac, comptrans_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+	  exit(1);
+	}
+	options->Trans = enumtrans_t[val_options-1];
+	break;
+      case 9:  // ReplaceTinyPivot
+	//char* comp7[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+	  exit(1);
+	}
+	options->ReplaceTinyPivot= enumyes_no_t[val_options-1]; 
+	break;
+      case 10:  // SolveInitialized
+	//char* comp8[] = {"NO","YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+	  exit(1);
+	}
+	options->SolveInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 11:  // RefineInitialized
+	//char* comp9[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+	  exit(1);
+	}
+	options->RefineInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 12: // PrintStat
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+	options->PrintStat = enumyes_no_t[val_options-1];
+	break;
+	// case 13 nprow
+	// case 14 npcol
+      case 15: // DiagScale_t
+	val_options= s_(tictac, compDiagScale_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+        *diag = enumDiagScale_t[val_options-1];
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2);
+	    exit(1);
+	  }	 
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+  
+}
+
+// void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol, int *matrixdist){
+  
+//   static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+// 			       "DiagPivotThresh","IterRefine","Trans",
+// 			       "ReplaceTinyPivot","SolveInitialized",
+// 			       "RefineInitialized","PrintStat","nprow","npcol","matrix",0};
+
+//   char data[string_option->size()+1];  
+//   strcpy( data, string_option->c_str()); 
+//   char *tictac;
+//   char *tictac2;
+//   tictac = strtok(data," =,\t\n");
+  
+//   while(tictac != NULL){
+//     int id_option = s_(tictac, comp);
+//     tictac2 = tictac;
+//     tictac = strtok(NULL," =,\t\n");
+//     int val_options;
+//     printf("param %s = value %s , id_option %d\n",tictac2,tictac,id_option);
+//     switch (id_option)
+//       { 
+//       case 13: // nprow
+// 	*nprow = atoi(tictac);
+// 	break;
+//       case 14: // npcol 
+// 	*npcol = atoi(tictac);
+// 	break;
+//       case 15: // matrix
+// 	printf("parameter matrix \n");
+// 	if(strcmp(tictac,"assembled") == 0)
+// 	  *matrixdist = 0;
+// 	else if(strcmp(tictac,"distributedglobal") == 0) 
+// 	  *matrixdist = 1;
+// 	else if(strcmp(tictac,"distributed") == 0) 
+// 	  *matrixdist = 2;
+// 	else{
+// 	  printf("value of parameter matrix is not correct %s \n", tictac );
+// 	}
+// 	break;
+//       default: // Equivalent of case default
+// 	if(id_option == 0)
+// 	  {
+// 	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+// 	    exit(1);
+// 	  }	  
+// 	break;
+//       }  
+//     tictac = strtok(NULL," =,\t\n");
+//   }
+// }
+
+void read_options_superlu_datafile(string *data_option, superlu_options_t *options, int_t *nprow, int_t *npcol, int *matrixdist, DiagScale_t *diag){
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[6] = {NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A,PARMETIS, MY_PERMC};
+  static const rowperm_t  enumrowperm_t[3] = {NOROWPERM, LargeDiag, MY_PERMR};
+  static const DiagScale_t enumDiagScale_t[4] = {NOEQUIL, ROW, COL, BOTH};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const IterRefine_t enumIterRefine_t[4] = {NOREFINE, SLU_SINGLE, SLU_DOUBLE, SLU_EXTRA};  
+  //static const MemType enumMemType_t[4] = {LUSUP, UCOL, LSUB, USUB};  
+  //static const stack_end_t enumstack_end_t[2] = {HEAD, TAIL};
+  //static const LU_space_t enumLU_space_t[2] = {SYSTEM, USER};
+
+ 
+  static const char* compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* comprowperm_t[] = {"NOROWPERM", "LargeDiag", "MY_PERMR",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_AT_PLUS_A", "MMD_ATA", "METIS_AT_PLUS_A", "PARMETIS", "MY_PERMC",0};
+  static const char* compDiagScale_t[] = {"NOEQUIL", "ROW", "COL", "BOTH",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  
+  //int_t ffnprow,ffnpcol;
+  //int matrixdist;
+
+  char datafile[data_option->size()+1];  
+  strcpy( datafile, data_option->c_str()); 
+  
+  FILE* pfile= fopen( datafile,"rt");
+  char data[256];
+  char *tictac;
+  
+  fgets(data,256,pfile);
+  cout << "data=" << data << endl;
+  tictac = strtok(data," /!#\t\n");
+  *nprow = (int) atol(tictac);
+  if(verbosity) printf("nprow=%d\n",*nprow);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  *npcol = (int) atol(tictac);
+  if(verbosity) printf("npcol=%d\n",*npcol);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  if(strcmp(tictac,"assembled") == 0)
+    *matrixdist = 0;
+  else if(strcmp(tictac,"distributedglobal") == 0) 
+    *matrixdist = 1;
+  else if(strcmp(tictac,"distributed") == 0) 
+    *matrixdist = 2;
+  else{
+    printf("matrix input %s for superlu_dist is not correct\n", tictac );
+    exit(1);
+  }
+
+  int id_option=0;
+  
+  while( !feof(pfile) && id_option<12){
+    fgets(data,256,pfile);
+    tictac = strtok(data," /!#\t\n");
+    id_option++;
+    int val_options;
+    switch (id_option)
+      { 
+	
+      case 1 : // Fact
+	//char* comp1[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+	val_options= s_(tictac,compfact_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+	  exit(1);
+	}
+	
+	options->Fact = enumfact_t[val_options-1];
+	break;
+      case 2:  // Equil
+	//char* comp2[] = {"NO", "YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+	  exit(1);
+	}
+	options->Equil = enumyes_no_t[val_options-1];
+	break;
+      case 3:  // ParSymbFact
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ParSymbFact = enumyes_no_t[val_options-1];
+	break;
+      case 4:  // ColPerm
+	val_options= s_(tictac,compcolperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ColPerm = enumcolperm_t[val_options-1];
+	break;
+      case 5:  // RowPerm
+	val_options= s_(tictac,comprowperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->RowPerm = enumrowperm_t[val_options-1];
+	break;
+      case 6:  // DiagPivotThresh
+	options->DiagPivotThresh= strtod(tictac,&tictac);
+	break;
+      case 7:  // IterRefine
+	val_options= s_(tictac,compIterRefine_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->IterRefine = enumIterRefine_t[val_options-1];
+	break;
+      case 8:  // Trans
+	//char* comp5[] = {"NOTRANS", "TRANS", "CONJ", 0};
+	val_options= s_(tictac, comptrans_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+	  exit(1);
+	}
+	options->Trans = enumtrans_t[val_options-1];
+	break;
+      case 9:  // ReplaceTinyPivot
+	//char* comp7[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+	  exit(1);
+	}
+	options->ReplaceTinyPivot= enumyes_no_t[val_options-1]; 
+	break;
+      case 10:  // SolveInitialized
+	//char* comp8[] = {"NO","YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+	  exit(1);
+	}
+	options->SolveInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 11:  // RefineInitialized
+	//char* comp9[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+	  exit(1);
+	}
+	options->RefineInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 12: // PrintStat
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+	options->PrintStat = enumyes_no_t[val_options-1];
+	break;
+      case 13: // DiagScale_t
+	val_options= s_(tictac, compDiagScale_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+        *diag = enumDiagScale_t[val_options-1];
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0 && id_option > 13)
+	  {
+	    printf("Error in reading data file for superlu_dist %s\n",datafile);
+	    exit(1);
+	  }	 
+	break;
+      }  
+  }
+  fclose(pfile);
+}
diff --git a/examples++-mpi/ffsuperludistoption.hpp b/examples++-mpi/ffsuperludistoption.hpp
new file mode 100644
index 0000000..ba0522f
--- /dev/null
+++ b/examples++-mpi/ffsuperludistoption.hpp
@@ -0,0 +1,548 @@
+// read options for superlu in freefem++
+int s_(char* str, const char* cmp[])
+{
+  int i = 0;
+  while( cmp[i] != 0){
+    if( strcmp(str, cmp[i]) == 0){
+      //cout << *str << " return" << i << endl;
+      return i+1 ;
+    }
+    i++;
+  }
+  //cout << *str << " return 0" << endl;
+  return 0;
+}
+
+void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol){
+  
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+  
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2 = tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 13: // nprow
+	*nprow = atoi(tictac);
+	break;
+      case 14: // npcol 
+	*npcol = atoi(tictac);
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+	    exit(1);
+	  }	  
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+}
+
+void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol, int *matrixdist){
+  
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol","matrix",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+  
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2 = tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+    if(verbosity>4)
+    printf("param %s = value %s , id_option %d\n",tictac2,tictac,id_option);
+    switch (id_option)
+      { 
+      case 13: // nprow
+	*nprow = atoi(tictac);
+	break;
+      case 14: // npcol 
+	*npcol = atoi(tictac);
+	break;
+      case 15: // matrix
+	if(verbosity>4) printf("parameter matrix \n");
+	if(strcmp(tictac,"assembled") == 0)
+	  *matrixdist = 0;
+	else if(strcmp(tictac,"distributedglobal") == 0) 
+	  *matrixdist = 1;
+	else if(strcmp(tictac,"distributed") == 0) 
+	  *matrixdist = 2;
+	else{
+	  if(verbosity>4)printf("value of parameter matrix is not correct %s \n", tictac );
+	}
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+	    exit(1);
+	  }	  
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+}
+
+
+void read_options_freefem(string *string_option, superlu_options_t *options, DiagScale_t *diag){
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[6] = {NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A,PARMETIS, MY_PERMC};
+  static const rowperm_t  enumrowperm_t[3] = {NOROWPERM, LargeDiag, MY_PERMR};
+  static const DiagScale_t enumDiagScale_t[4] = {NOEQUIL, ROW, COL, BOTH};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const IterRefine_t enumIterRefine_t[4] = {NOREFINE,SLU_SINGLE, SLU_DOUBLE, SLU_EXTRA};  
+  //static const MemType enumMemType_t[4] = {LUSUP, UCOL, LSUB, USUB};  
+  //static const stack_end_t enumstack_end_t[2] = {HEAD, TAIL};
+  //static const LU_space_t enumLU_space_t[2] = {SYSTEM, USER};
+
+ 
+  static const char* compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* comprowperm_t[] = {"NOROWPERM", "LargeDiag", "MY_PERMR",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_AT_PLUS_A", "MMD_ATA", "METIS_AT_PLUS_A", "PARMETIS", "MY_PERMC",0};
+  static const char* compDiagScale_t[] = {"NOEQUIL", "ROW", "COL", "BOTH",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  //static const char* compMemType_t[] = {"LUSUP", "UCOL", "LSUB", "USUB",0};  
+  //static const char* compstack_end_t[] = {"HEAD", "TAIL",0};
+  //static const char* compLU_space_t[] = {"SYSTEM", "USER",0};
+
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol","DiagScale","matrix",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  if(verbosity>4)
+  cout << "data=" << data << endl;
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2=tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 1 : // Fact
+	//char* comp1[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+	val_options= s_(tictac,compfact_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+	  exit(1);
+	}
+	options->Fact = enumfact_t[val_options-1];
+	break;
+      case 2:  // Equil
+	//char* comp2[] = {"NO", "YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+	  exit(1);
+	}
+	options->Equil = enumyes_no_t[val_options-1];
+	break;
+      case 3:  // ParSymbFact
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ParSymbFact = enumyes_no_t[val_options-1];
+	break;
+      case 4:  // ColPerm
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compcolperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ColPerm = enumcolperm_t[val_options-1];
+	break;
+      case 5:  // RowPerm
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,comprowperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->RowPerm = enumrowperm_t[val_options-1];
+	break;
+      case 6:  // DiagPivotThresh
+	options->DiagPivotThresh= strtod(tictac,&tictac);
+	break;
+      case 7:  // IterRefine
+	val_options= s_(tictac,compIterRefine_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->IterRefine = enumIterRefine_t[val_options-1];
+	break;
+      case 8:  // Trans
+	//char* comp5[] = {"NOTRANS", "TRANS", "CONJ", 0};
+	val_options= s_(tictac, comptrans_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+	  exit(1);
+	}
+	options->Trans = enumtrans_t[val_options-1];
+	break;
+      case 9:  // ReplaceTinyPivot
+	//char* comp7[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+	  exit(1);
+	}
+	options->ReplaceTinyPivot= enumyes_no_t[val_options-1]; 
+	break;
+      case 10:  // SolveInitialized
+	//char* comp8[] = {"NO","YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+	  exit(1);
+	}
+	options->SolveInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 11:  // RefineInitialized
+	//char* comp9[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+	  exit(1);
+	}
+	options->RefineInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 12: // PrintStat
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+	options->PrintStat = enumyes_no_t[val_options-1];
+	break;
+	// case 13 nprow
+	// case 14 npcol
+      case 15: // DiagScale_t
+	val_options= s_(tictac, compDiagScale_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+        *diag = enumDiagScale_t[val_options-1];
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2);
+	    exit(1);
+	  }	 
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+  
+}
+
+// void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol, int *matrixdist){
+  
+//   static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+// 			       "DiagPivotThresh","IterRefine","Trans",
+// 			       "ReplaceTinyPivot","SolveInitialized",
+// 			       "RefineInitialized","PrintStat","nprow","npcol","matrix",0};
+
+//   char data[string_option->size()+1];  
+//   strcpy( data, string_option->c_str()); 
+//   char *tictac;
+//   char *tictac2;
+//   tictac = strtok(data," =,\t\n");
+  
+//   while(tictac != NULL){
+//     int id_option = s_(tictac, comp);
+//     tictac2 = tictac;
+//     tictac = strtok(NULL," =,\t\n");
+//     int val_options;
+//     printf("param %s = value %s , id_option %d\n",tictac2,tictac,id_option);
+//     switch (id_option)
+//       { 
+//       case 13: // nprow
+// 	*nprow = atoi(tictac);
+// 	break;
+//       case 14: // npcol 
+// 	*npcol = atoi(tictac);
+// 	break;
+//       case 15: // matrix
+// 	printf("parameter matrix \n");
+// 	if(strcmp(tictac,"assembled") == 0)
+// 	  *matrixdist = 0;
+// 	else if(strcmp(tictac,"distributedglobal") == 0) 
+// 	  *matrixdist = 1;
+// 	else if(strcmp(tictac,"distributed") == 0) 
+// 	  *matrixdist = 2;
+// 	else{
+// 	  printf("value of parameter matrix is not correct %s \n", tictac );
+// 	}
+// 	break;
+//       default: // Equivalent of case default
+// 	if(id_option == 0)
+// 	  {
+// 	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+// 	    exit(1);
+// 	  }	  
+// 	break;
+//       }  
+//     tictac = strtok(NULL," =,\t\n");
+//   }
+// }
+
+void read_nprow_npcol_matrixdist_superlu_datafile(string *data_option, int_t *nprow, int_t *npcol, int *matrixdist){
+ 
+  char datafile[data_option->size()+1];  
+  strcpy( datafile, data_option->c_str()); 
+  
+  FILE* pfile= fopen( datafile,"rt");
+  char data[256];
+  char *tictac;
+  
+  fgets(data,256,pfile);
+  if(verbosity>4)
+  cout << "data=" << data << endl;
+  tictac = strtok(data," /!#\t\n");
+  *nprow = (int) atol(tictac);
+  if(verbosity>1) printf("nprow=%d\n",*nprow);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  *npcol = (int) atol(tictac);
+  if(verbosity>1) printf("npcol=%d\n",*npcol);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  if(strcmp(tictac,"assembled") == 0)
+    *matrixdist = 0;
+  else if(strcmp(tictac,"distributedglobal") == 0) 
+    *matrixdist = 1;
+  else if(strcmp(tictac,"distributed") == 0) 
+    *matrixdist = 2;
+  else{
+    printf("matrix input %s for superlu_dist is not correct\n", tictac );
+    exit(1);
+  }
+ 
+  fclose(pfile);
+}
+
+
+void read_options_superlu_datafile(string *data_option, superlu_options_t *options, int_t *nprow, int_t *npcol, int *matrixdist, DiagScale_t *diag){
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[6] = {NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A,PARMETIS, MY_PERMC};
+  static const rowperm_t  enumrowperm_t[3] = {NOROWPERM, LargeDiag, MY_PERMR};
+  static const DiagScale_t enumDiagScale_t[4] = {NOEQUIL, ROW, COL, BOTH};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const IterRefine_t enumIterRefine_t[4] = {NOREFINE, SLU_SINGLE, SLU_DOUBLE, SLU_EXTRA};  
+  //static const MemType enumMemType_t[4] = {LUSUP, UCOL, LSUB, USUB};  
+  //static const stack_end_t enumstack_end_t[2] = {HEAD, TAIL};
+  //static const LU_space_t enumLU_space_t[2] = {SYSTEM, USER};
+
+ 
+  static const char* compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* comprowperm_t[] = {"NOROWPERM", "LargeDiag", "MY_PERMR",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_AT_PLUS_A", "MMD_ATA", "METIS_AT_PLUS_A", "PARMETIS", "MY_PERMC",0};
+  static const char* compDiagScale_t[] = {"NOEQUIL", "ROW", "COL", "BOTH",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  
+  //int_t ffnprow,ffnpcol;
+  //int matrixdist;
+
+  char datafile[data_option->size()+1];  
+  strcpy( datafile, data_option->c_str()); 
+  
+  FILE* pfile= fopen( datafile,"rt");
+  char data[256];
+  char *tictac;
+  
+  fgets(data,256,pfile);
+  if(verbosity>4)
+  cout << "data=" << data << endl;
+  tictac = strtok(data," /!#\t\n");
+  *nprow = (int) atol(tictac);
+  if(verbosity) printf("nprow=%d\n",*nprow);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  *npcol = (int) atol(tictac);
+  if(verbosity) printf("npcol=%d\n",*npcol);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  if(strcmp(tictac,"assembled") == 0)
+    *matrixdist = 0;
+  else if(strcmp(tictac,"distributedglobal") == 0) 
+    *matrixdist = 1;
+  else if(strcmp(tictac,"distributed") == 0) 
+    *matrixdist = 2;
+  else{
+    printf("matrix input %s for superlu_dist is not correct\n", tictac );
+    exit(1);
+  }
+
+  int id_option=0;
+  
+  while( !feof(pfile) && id_option<12){
+    fgets(data,256,pfile);
+    tictac = strtok(data," /!#\t\n");
+    id_option++;
+    int val_options;
+    switch (id_option)
+      { 
+	
+      case 1 : // Fact
+	//char* comp1[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+	val_options= s_(tictac,compfact_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+	  exit(1);
+	}
+	
+	options->Fact = enumfact_t[val_options-1];
+	break;
+      case 2:  // Equil
+	//char* comp2[] = {"NO", "YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+	  exit(1);
+	}
+	options->Equil = enumyes_no_t[val_options-1];
+	break;
+      case 3:  // ParSymbFact
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ParSymbFact = enumyes_no_t[val_options-1];
+	break;
+      case 4:  // ColPerm
+	val_options= s_(tictac,compcolperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ColPerm = enumcolperm_t[val_options-1];
+	break;
+      case 5:  // RowPerm
+	val_options= s_(tictac,comprowperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->RowPerm = enumrowperm_t[val_options-1];
+	break;
+      case 6:  // DiagPivotThresh
+	options->DiagPivotThresh= strtod(tictac,&tictac);
+	break;
+      case 7:  // IterRefine
+	val_options= s_(tictac,compIterRefine_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->IterRefine = enumIterRefine_t[val_options-1];
+	break;
+      case 8:  // Trans
+	//char* comp5[] = {"NOTRANS", "TRANS", "CONJ", 0};
+	val_options= s_(tictac, comptrans_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+	  exit(1);
+	}
+	options->Trans = enumtrans_t[val_options-1];
+	break;
+      case 9:  // ReplaceTinyPivot
+	//char* comp7[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+	  exit(1);
+	}
+	options->ReplaceTinyPivot= enumyes_no_t[val_options-1]; 
+	break;
+      case 10:  // SolveInitialized
+	//char* comp8[] = {"NO","YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+	  exit(1);
+	}
+	options->SolveInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 11:  // RefineInitialized
+	//char* comp9[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+	  exit(1);
+	}
+	options->RefineInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 12: // PrintStat
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+	options->PrintStat = enumyes_no_t[val_options-1];
+	break;
+      case 13: // DiagScale_t
+	val_options= s_(tictac, compDiagScale_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+        *diag = enumDiagScale_t[val_options-1];
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0 && id_option > 13)
+	  {
+	    printf("Error in reading data file for superlu_dist %s\n",datafile);
+	    exit(1);
+	  }	 
+	break;
+      }  
+  }
+  fclose(pfile);
+}
diff --git a/examples++-mpi/generaldefs.h b/examples++-mpi/generaldefs.h
new file mode 100755
index 0000000..802cef4
--- /dev/null
+++ b/examples++-mpi/generaldefs.h
@@ -0,0 +1,82 @@
+#if defined(AIX)
+#define wreadmtc wreadmtc
+#define userread userread  
+#define nod2dom nod2dom
+#define roscal roscal
+#define coscal coscal
+#define csrcsc csrcsc
+#define aplb   aplb
+#define expnddom expnddom
+#elif defined(BGL)
+#define wreadmtc wreadmtc
+#define userread userread
+#define nod2dom nod2dom
+#define roscal roscal
+#define coscal coscal
+#define csrcsc csrcsc
+#define aplb   aplb
+#define expnddom expnddom
+#elif defined(LINUX)
+#define wreadmtc wreadmtc_
+#define userread userread_  
+#define nod2dom nod2dom_
+#define roscal roscal_
+#define coscal coscal_
+#define csrcsc csrcsc_
+#define aplb   aplb_
+#define expnddom expnddom_
+#elif defined(CRAY)
+#define wreadmtc WREADMTC
+#define userread USERREAD
+#define nod2dom NOD2DOM
+#define roscal ROSCAL
+#define coscal COSCAL
+#define csrcsc CSRCSC
+#define aplb   APLB
+#define expnddom EXPNDDOM
+#else
+#define wreadmtc wreadmtc_
+#define userread userread_
+#define nod2dom nod2dom_
+#define roscal roscal_
+#define coscal coscal_
+#define csrcsc csrcsc_
+#define aplb   aplb_
+#define expnddom expnddom_
+#endif
+
+/* for outer and inner functions */
+extern void setpar(char *filename, char *matrix, int *iov, int *scale, 
+		   int *unsym, int *method, PrePar prepar, IterPar ipar,
+		   DistMatrix dm) ;
+
+int assignprecon( char *precon_str, DistMatrix dm);
+
+void set_def_params(PrePar prepar, IterPar ipar) ;
+
+extern void userread(char *fname, int *len, int *job, int *n, int
+                      *nnz, double *a, int *ja, int *ia, int *nrhs,
+                      double *rhs, int *ierr); 
+extern void wreadmtc(int *nmax, int *nzmax, int *job, char *fname,int
+                     *len, double *a, int *ja, int *ia, double *rhs, 
+		     int *nrhs, char *guesol, int *nrow, int *ncol,
+		     int *nnz, char *title, char *key, char *type, int 
+		     *ierr) ;
+extern void nod2dom(int *n, int *ndom, int *nodes, int *pointer, int
+		    *map, int *mapsize, int *ier);
+extern void roscal(int *n, int *job, int *nrm, double *a, int *ja, int
+		   *ia, double *diag, double *b, int *jb, int *ib, int
+		   *ierr);
+extern void coscal(int *n, int *job, int *nrm, double *a, int *ja, int
+		   *ia, double *diag, double *b, int *jb, int *ib, int
+		   *ierr);
+extern void csrcsc(int *n, int *job, int *ipos, double *a, int *ja,
+		   int *ia, double *ao, int *jao, int *iao);
+extern void aplb(int *nrow, int *ncol, int *job, double *a, int *ja,
+		 int *ia, double *b, int *jb, int *ib, double *c, int
+		 *jc, int *ic, int *nnzmax, int *iw, int *ierr);
+extern  void expnddom(int *, int *,  int *,  int *, int *, int *, int 
+		       *, int *, int *, int *);
+
+/*-----------------------------------------------------------------------*/
+
diff --git a/examples++-mpi/getARGV.idp b/examples++-mpi/getARGV.idp
new file mode 100644
index 0000000..21243c7
--- /dev/null
+++ b/examples++-mpi/getARGV.idp
@@ -0,0 +1,90 @@
+ // for gestion of FreeFem++ argument and in version 3.10-1 FH
+ // F. Hecht 
+ // Usage:  getARGV(n,defaultvalue) // get the fist used default valeu
+ //  or     getARGV(after,defaultvalue) // get the arg after after 
+ // the type of delfaut value given the return type: int,double, string
+ func int usedARGV(int n)
+{
+  int k=1,ii=1,kk=1,ret=-1;
+  for(int i=1;i<ARGV.n;++i)
+   {
+   // cout <<i<< " "<< ARGV[i] << " " <<(ARGV[i]=="-v") << " " << kk << "==" 
+   //      << n << " " << ARGV[i].rfind("dp") << " " <<ARGV[i].length-2  << endl;
+        
+       if(ARGV[i]=="-v") i++;
+       else if(ARGV[i]=="-fglut") i++;
+       else if(ARGV[i]=="-ffg") i++;
+       else if(ARGV[i]=="-glut") i++;
+       else if(ARGV[i]=="-f") i++;
+       else if(ARGV[i]=="-nw") ii;
+       else if(ARGV[i]=="-wait") ii;
+       else if(ARGV[i]=="-ne") ii;
+       else if(ARGV[i]=="-cd") ii;
+       //else if(ARGV[i].rfind(".edp")==ARGV[i].length-4 ) ii;
+       else if(i==1) ii;
+       else if(kk++==n) {ret=i;}
+      // else cout << " +++ \n";
+     }
+   //  cout << ret << endl;
+    return ret;
+}
+
+func int usedARGV(string after)
+{
+  int ret=-1;
+  for(int i=ARGV.n-1;i>=0;--i)        
+       if(ARGV[i]==after) { ret=++i; break;}
+  if(ARGV.n<ret) ret=-1;
+  return ret;
+}
+
+func int getARGV(int n,int default)
+{
+   int d=default;
+   int k=usedARGV(n);
+   if(k>0) d=atoi(ARGV[k]);
+    return d;
+}
+func real getARGV(int n,real default)
+{
+   real d=default;
+   int k=usedARGV(n);
+   if(k>0) d=atof(ARGV[k]);
+   return d;
+}
+func string getARGV(int n,string default)
+{
+   string d=default;
+   int k=usedARGV(n);
+   if(k>0) d=ARGV[k];
+    return d;
+}
+
+func int getARGV(string after,int default)
+{
+   int d=default;
+   int k=usedARGV(after);
+   if(k>0) d=atoi(ARGV[k]);
+    return d;
+}
+func real getARGV(string after,real default)
+{
+   real d=default;
+   int k=usedARGV(after);
+   if(k>0) d=atof(ARGV[k]);
+   return d;
+}
+func string getARGV(string after,string default)
+{
+   string d=default;
+   int k=usedARGV(after);
+   if(k>0) d=ARGV[k];
+    return d;
+}
+
+/*
+cout << getARGV(1,100) << endl;
+cout << getARGV(2,200.) << endl;
+cout << getARGV(3,"300.000") << endl;
+cout << getARGV("-n"," xxx") << endl;
+*/
diff --git a/examples++-mpi/hips_FreeFem.cpp b/examples++-mpi/hips_FreeFem.cpp
new file mode 100644
index 0000000..4e02187
--- /dev/null
+++ b/examples++-mpi/hips_FreeFem.cpp
@@ -0,0 +1,767 @@
+// ORIG-DATE: 04/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : INRIA FUTUR
+// AUTHOR   : Guy Atenekeng 
+//         Modif by F. Hecht 2011
+// E-MAIL   : Guy_Antoine_Atenekeng_Kahou at lri.fr
+//
+//ff-c++-LIBRARY-dep:  hips metis  blas  mpi
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+#include <mpi.h>
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#ifndef  MPI_SUCCESS
+#define  MPI_SUCCESS
+#endif
+
+extern "C" {
+#include "hips.h"  
+#include "metis.h"
+}
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFLEN 200
+#define MCW MPI_COMM_WORLD
+
+
+int roscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpr , int *ierr)
+{
+    /*---------------------------------------------------------------------
+     |
+     | This routine scales each row of mata so that the norm is 1.
+     |
+     |----------------------------------------------------------------------
+     | on entry:
+     | mata  = the matrix (in SparRow form)
+     | nrm   = type of norm
+     |          0 (\infty),  1 or 2
+     |
+     | on return
+     | diag  = diag[j] = 1/norm(row[j])
+     |
+     |     0 --> normal return
+     |     j --> row j is a zero row
+     |--------------------------------------------------------------------*/
+    /*   local variables    */
+    int i, k;
+    double  scal;
+    
+    for (i=0; i<n; i++) {
+	scal = 0.0;
+	// kr = &(AAv[pr[i]]);
+	if (nrm == 0) {
+	    for (k=pr[i]; k<pr[i+1]; k++)
+		if (fabs(AAv[k]) > scal) scal = fabs(AAv[k]);
+	}
+	else if (nrm == 1) {
+	    for (k=pr[i]; k<pr[i+1]; k++)
+		scal += fabs(AAv[k]);
+	}
+	else {  /* nrm = 2 */
+	    for (k=pr[i]; k<(pr[i+1]); k++)
+		scal += AAv[k]*AAv[k];
+	}
+	if (nrm == 2) scal = sqrt(scal);
+	if (scal == 0.0) {
+	    *ierr=i;
+	    return i+1;
+	}
+	else 
+	    scal = 1.0 / scal;
+	scaletmpr[i] = scal;
+	for (k=pr[i]; k<(pr[i+1]); k++)
+	    AAv[k] = AAv[k] * scal;
+	
+    }
+    *ierr=0;
+    return 0;
+}
+/*---------------end of roscalC-----------------------------------------
+ ----------------------------------------------------------------------*/
+int coscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpc , int * ierr)
+{
+    /*---------------------------------------------------------------------
+     |
+     | This routine scales each column of mata so that the norm is 1.
+     |
+     |----------------------------------------------------------------------
+     | on entry:
+     | mata  = the matrix (in SparRow form)
+     | nrm   = type of norm
+     |          0 (\infty),  1 or 2
+     |
+     | on return
+     | diag  = diag[j] = 1/norm(row[j])
+     |
+     |     0 --> normal return
+     |     j --> column j is a zero column
+     |--------------------------------------------------------------------*/
+    /*   local variables    */
+    int i, j, k;
+    double *kr;
+    int *ki;
+    for (i=0; i<n; i++)
+	scaletmpc[i] = 0.0;
+    /*---------------------------------------
+     |   compute the norm of each column
+     |--------------------------------------*/
+    for (i=0; i<n; i++) {
+	kr = &(AAv[pr[i]]);
+	ki = &(pr[i]);
+	if (nrm == 0) {
+	    for (k=pr[i]; k<pr[i+1]; k++) {
+		j = pr[i];
+		if (fabs(AAv[k]) > scaletmpc[p[k]]) scaletmpc[p[k]] = fabs(AAv[k]);
+	    }
+	}
+	else if (nrm == 1) {
+	    for (k=pr[i]; k<pr[i+1]; k++)
+		scaletmpc[p[k]] += fabs(AAv[k]);
+	}
+	else {
+	    for (k=pr[i]; k<pr[i+1]; k++)
+		scaletmpc[p[k]] += fabs(AAv[k])*fabs(AAv[k]);
+	}
+    }
+    if (nrm == 2) {
+	for (i=0; i<n; i++)
+	    scaletmpc[i] = sqrt(scaletmpc[i]);
+    }
+    /*---------------------------------------
+     |   invert
+     |--------------------------------------*/
+    for (i=0; i<n; i++) {
+	if (scaletmpc[i] == 0.0)
+	  {
+	    *ierr=i+1;
+	    return i+1;
+	  }
+	else 
+	    scaletmpc[i] = 1.0 / scaletmpc[i];
+    }
+    /*---------------------------------------
+     |   C = A * D
+     |--------------------------------------*/
+    for (i=0; i<n; i++) {
+	
+	for (k=pr[i]; k<pr[i+1]; k++)
+	    AAv[k]=AAv[k]*scaletmpc[p[k]];
+	
+    }
+    *ierr=0;
+    return 0;
+}
+/*---------------end of coscalC-----------------------------------------
+ ----------------------------------------------------------------------*/
+
+
+
+
+
+
+void parm_param(string datafile,KN<long> param_int,KN<double> param_double)
+{
+    char buf[BUFLEN];
+    int num,in_val;
+    double val;
+    FILE *fp;
+    char * filename=new char[datafile.length()+1]; 
+    strcpy(filename,datafile.c_str()); 
+    int i;
+    for(i=0;i<16;i++) param_int[i]=-1; for(i=0;i<9;i++) param_double[i]=-1.0;
+    /* read parameters for preconditioner and iteration from file  'filename' */
+    /*  ---- start modification by MS   */
+    if( (fp = fopen(filename, "r")) == NULL ){
+	fprintf(stderr, "Cannot open file inputs\n");
+	exit(1);
+    }
+    num = 0;
+    
+    while(fgets(buf, BUFLEN, fp) != NULL) {
+	if(num<=15) {sscanf(buf, "%d", &in_val); param_int[num]=in_val;}
+	else 
+	  {sscanf(buf, "%lf", &val); param_double[num]=val;}
+	num++;
+    }
+    fclose(fp);
+}
+
+
+
+
+class HipsSolver :   public MatriceMorse<double>::VirtualSolver   {
+    double eps;
+    mutable double  epsr;
+    double tgv;	
+    double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+    string data_option;
+    mutable INTS master;//
+    MPI_Comm  comm;
+    mutable INTS id,  i, j;
+    mutable INTS *unknownlist;
+    mutable double *x;
+    mutable INTS   ln;
+    mutable INTS ierr;
+  mutable INTS n,nnz,nnzl;
+    mutable double * a;
+    mutable INTS *ia, *ja;
+    mutable int *pp;
+    int loc_size,pbegin, pend;
+    INTS domsize, nproc,proc_id;
+    mutable int sym_pattern, sym_matrix;
+    KN<long> param_int;
+    KN<double> param_double;
+    mutable double *scaletmpr, *scaletmpc;
+    
+    mutable int *mapptr,*maptmp,*iwork,*riord,*iwork1,scale;
+    mutable int *pr, *p;
+    mutable double * AAv;
+
+   
+private:
+  static const int MaxIds=100;
+  static int Ids[MaxIds];
+  static int  GetId() {
+    static bool Initialized=false;
+    if(!Initialized)
+      {
+	Initialized=true;
+	if(verbosity>2)
+	cout << "  Hips HIPS_Initialize " << MaxIds <<endl;
+	INTS ierr = HIPS_Initialize(MaxIds);
+	HIPS_ExitOnError(ierr);
+	for(int i=0;i<MaxIds;++i)
+	  {
+	    Ids[i]=-1; // ununsed 
+	  }
+      }
+    INTS id =-1;
+    for(int i=0;i<MaxIds;++i)
+      if( Ids[i] <0)  
+	{
+	  Ids[i]=i;
+	  if(verbosity>8) cout << "   find HipsSoler :  id = " << i << "/" <<   MaxIds << endl;
+	  return i;
+	}
+    cerr<< " All id of Hips are busy " << MaxIds << " try to store less matrix or change MaxIds (FH.) in " << endl; 
+    ffassert(0); 
+    return -1; 
+  }
+public:
+  static void Def_iopt(long * param_intd)
+  {
+    param_intd[0]= HIPS_ITERATIVE  ; //  HIPS_STRA
+    param_intd[1]= 0  ; //  HIPS_KRYLOV_METHOD
+    param_intd[2]= 1000  ; //  HIPS_ITMAX
+    param_intd[3]= 40  ; //  HIPS_KRYLOV_RESTART
+    param_intd[4]= 1  ; //  HIPS_SYMMETRIC
+    param_intd[5]= 1  ; //  HIPS_GRAPH_SYM
+    param_intd[6]= 0  ; //  HIPS_PARTITION_TYPE
+    param_intd[7]= 2  ; //  HIPS_LOCALLY
+    param_intd[8]= 0  ; //  HIPS_FORTRAN_NUMBERING
+    param_intd[9]= 1  ; //  HIPS_SCALE
+    param_intd[10]= 1  ; //  HIPS_REORDER
+    param_intd[11]= 1  ; //  HIPS_DOF
+    param_intd[12]= 2  ; //  HIPS_SCALENBR
+    param_intd[13]=  max(0L,verbosity-2)  ; //  HIPS_VERBOSE
+    param_intd[14]= 2  ; //  HIPS_DOMSIZE
+    param_intd[15]= 2  ; //  HIPS_SCHUR_METHOD
+    param_intd[16]= 2  ; //  HIPS_ITMAX_SCHUR
+  }
+
+  static void Def_dopt(double *d)
+  {
+    d[0]= 1e-09  ; //  HIPS_PREC
+    d[1]= 0.005  ; //  HIPS_DROPTOL0
+    d[2]= 0.005  ; //  HIPS_DROPTOL1
+    d[3]= 0.005  ; //  HIPS_DROPTOLE
+    d[4]= 0.005  ; //  HIPS_AMALG
+    d[5]= 0.005  ; //  HIPS_DROPSCHUR
+  }
+
+public:
+  
+  
+  HipsSolver(const MatriceMorse<double> &AA,double eeps,string datafile, const KN<long> &param_int1,
+             const KN<double> &param_double1,int mmaster,  MPI_Comm  * mpicommw  )
+    : eps(eeps),data_option(datafile) ,param_int(17), param_double(6),id(GetId())
+  {
+    master=mmaster;
+    if(mpicommw==0)
+	comm=MPI_COMM_WORLD;
+    else 
+	comm= *mpicommw;
+    
+    MPI_Comm_rank(comm, &proc_id);
+    MPI_Comm_size(comm, &nproc);
+    if(proc_id==0  || verbosity>2)
+	cout << "  Hips Comm " << proc_id<< " / "<< nproc << endl;
+    
+    Def_iopt(param_int);
+    Def_dopt(param_double);
+
+    static int dopt_wrapper[6] = {
+      HIPS_PREC ,
+      HIPS_DROPTOL0 ,
+      HIPS_DROPTOL1 ,
+      HIPS_DROPTOLE ,
+      HIPS_AMALG ,
+      HIPS_DROPSCHUR 
+ };
+
+    static int iopt_wrapper[17] = {
+      -1,// DEf STRATEGIC not in H
+      HIPS_KRYLOV_METHOD ,
+      HIPS_ITMAX,
+      HIPS_KRYLOV_RESTART,
+      HIPS_SYMMETRIC,
+      HIPS_GRAPH_SYM,
+      HIPS_PARTITION_TYPE, 
+      HIPS_LOCALLY,
+      HIPS_FORTRAN_NUMBERING,
+      HIPS_SCALE,
+      HIPS_REORDER,
+      HIPS_DOF,
+      HIPS_SCALENBR, 
+      HIPS_VERBOSE,
+      HIPS_DOMSIZE,
+      HIPS_SCHUR_METHOD, 
+      HIPS_ITMAX_SCHUR
+    }     ; 
+    
+    int ic,sym=AA.symetrique ,symm=AA.symetrique; 
+
+ 
+    if(!data_option.empty())
+      parm_param(datafile,param_int,param_double);
+    else
+      {
+	for(int i=0;i< min(param_int.N(),param_int1.N()); ++i) 
+	  if(param_int1[i]>-1)  param_int[i]=param_int1[i];	    
+	for(int i=0;i< min(param_double.N(),param_double1.N()); ++i) 
+	  if(param_double1[i]>-0.9999)  param_double[i]=param_double1[i];	    
+      }
+    // force param  value ... 
+    param_int[0]=max(min(param_int[0],2L),0L);
+    param_int[5]= sym;
+    param_int[4]= symm;
+
+    if(eps>0 &&( param_double1.N() ==0 ||  param_double1[0]<0) ) param_double[0]= eps;
+    else eps = param_double[0];
+
+    ic = param_int[0];
+    scale=param_int[9];
+    
+    if(verbosity>3 && proc_id==0  )
+      {
+	cout << " Hips INT  opts " << param_int << endl;
+	cout << " Hips REAL  opts " << param_double << endl;
+      }
+
+    HIPS_SetDefaultOptions(id, param_int[0] );
+    
+    for(int i=1;i<param_int.N();++i)     // the fist value is teh STRATEGIE KING not aoption
+      if(param_int[i]>=0) HIPS_SetOptionINT(id,iopt_wrapper[i],param_int[i] );
+    for(int i=0;i<param_double.N();++i)    
+      if(param_double[i]>=0.)HIPS_SetOptionREAL(id,dopt_wrapper[i],param_double[i] );
+ 
+    if(!data_option.empty()) 
+      parm_param(datafile,param_int,param_double);
+    
+    HIPS_SetCommunicator(id,comm);
+    
+    n=AA.n; nnz=AA.nbcoef;
+    
+    int ierr;
+    /*
+    pr= new int[n+1];
+    p=  new int[nnz];
+    AAv=new double[nnz];
+    
+    
+    for(int i=0;i<nnz;i++)
+      {
+	AAv[i]=AA.a[i];
+	p[i]=AA.cl[i];
+	if(i<=n) pr[i]=AA.lg[i];
+      }
+    */
+    
+    int job, tmp;
+    if(scale) {
+      job = 1;
+      tmp = 2; /*-- compute 2-norm */
+      scaletmpr=new double[n];
+      scaletmpc=new double[n]; 
+      
+      roscal(n,job,tmp,AA.a,AA.cl,AA.lg,scaletmpr,&ierr);
+      if (ierr) fprintf(stderr, "Error: in roscal, ierr = %d\n", ierr);
+      /*------- scale the RHS according to row scaling coefficients */
+      
+      coscal(n,job,tmp,AA.a,AA.cl,AA.lg,scaletmpc,&ierr);
+      if (ierr) fprintf(stderr, "Error: in coscal, ierr = %d\n", ierr);
+      
+    } /*--- end of branch on scaling */
+    
+    
+    int wgtflag=0, numflag=0, volume;
+    
+    riord= new int[n]; //(int *)malloc(sizeof(int)*n);
+    if(riord==NULL) {
+      if(nproc==0)
+	printf("%s","Memory allocation failed in partition stage \n"); 
+      exit(1);
+    }
+    int option[5];	option[0]=0;
+    if(nproc>1){
+      METIS_PartGraphKway(&n, AA.lg, AA.cl, NULL, NULL, &wgtflag, &numflag,&nproc, option, &volume, riord);
+    }
+    else if(nproc==1){
+      for (int i=0; i<n; i++) 
+	riord[i]=0;
+    }
+
+    iwork= new int[nproc+1];// (int *)malloc(sizeof(int)*n);
+    maptmp= new int [n];//(int *)malloc(sizeof(int)*n);
+    mapptr= new int [nproc+1];//(int *)malloc(sizeof(int)*(nproc+1));
+    iwork1= new int[nproc+1];//(int *)malloc(sizeof(int)*(nproc+1));
+    
+    for(int i=0; i<=nproc; i++)
+      iwork[i]=iwork1[i]=0;
+
+    for(int j=0; j<n; j++)
+      {
+	iwork[riord[j]]++;
+	iwork1[riord[j]]++;
+      }
+    numflag=0;
+    for(int i=0; i<nproc; i++)
+      {
+	mapptr[i]=numflag;
+	numflag+=iwork[i];
+      }
+    
+    mapptr[nproc]=numflag;
+    
+    for (int i=0; i<nproc; i++){
+      iwork[i]=mapptr[i];
+    }
+    if(nproc==0) 
+      iwork[0]=mapptr[0];
+    
+    for(int i=0; i<n; i++){
+      maptmp[iwork[riord[i]]]=i;
+      iwork[riord[i]]++;
+    }
+    int nnzz;
+    nnzz=0;
+      for(int i=0;i<n;i++) 
+	if(riord[i]==proc_id)
+	  {
+	    nnzz+=(AA.lg[i+1]-AA.lg[i]);
+	  }
+      ierr = HIPS_GraphBegin(id, n, nnzz);
+      HIPS_ExitOnError(ierr);
+      nnzl=nnzz;
+      if(verbosity > 5)
+	cout << "   Hips : proc " << proc_id << " / nzz   = " << nnzz << " / nzzg " << nnz <<  endl;
+      
+      
+      for(int i=0;i<n;i++)
+	{
+	  if(riord[i]==proc_id){
+	    for(int j=AA.lg[i];j<AA.lg[i+1];j++)
+	      {
+		ierr = HIPS_GraphEdge(id, i, AA.cl[j]);
+		HIPS_ExitOnError(ierr);	
+	      }
+	  }
+	  
+	}
+      
+      ierr = HIPS_GraphEnd(id);
+      HIPS_ExitOnError(ierr);
+      if(master==-1)
+      {
+          
+          // HERE distributed matrix ????
+          ffassert(0); // to be done in future ...
+      }
+      if(proc_id==0)
+	{
+	  ierr = HIPS_SetPartition(id, nproc, mapptr, maptmp);
+	  HIPS_ExitOnError(ierr);
+	}
+      //symm=1;
+      if( nproc ==1)
+	{
+	  ierr = HIPS_MatrixGlobalCSR(id, n, AA.lg, AA.cl, AA.a, 0, HIPS_ASSEMBLY_OVW, sym_matrix);
+	  HIPS_ExitOnError(ierr);
+	  
+	}
+      else 
+	{	  
+	  ierr = HIPS_AssemblyBegin(id, nnzz, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_FOOL,symm);
+	  HIPS_ExitOnError(ierr);
+	    int kkk;
+	  for(int i=0;i<n;i++)
+	    {
+	      if(riord[i]==proc_id){
+		  for(int k=AA.lg[i];k<AA.lg[i+1];k++)
+		    {			
+			kkk++;
+			if(verbosity >100) cout << "       " << proc_id << " a( " << i << ", " <<AA.cl[k] << ")= " << AA.a[k] << endl;
+			ierr = HIPS_AssemblySetValue(id, i, AA.cl[k], AA.a[k]);
+			HIPS_ExitOnError(ierr);
+		    }
+	      }
+	      
+	    }
+	    ffassert(kkk);
+	  ierr = HIPS_AssemblyEnd(id);
+	  
+	  HIPS_ExitOnError(ierr);
+
+	}
+
+   }
+
+  void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+    /***************************************************/
+    /*                                                 */
+    /*          ENTER THE RIGHT-HAND-SIDE              */
+    /*                                                 */
+    /***************************************************/
+    int i,nloc;
+    nloc=0; 
+    int nnsize;
+    MPI_Comm_size(comm,&nnsize);
+    if(master==-1)
+      {
+          
+          // HERE distributed rhs ????
+          ffassert(0); // to be done in future ...
+      }
+    
+    
+    COEF * rhsloc = new COEF[iwork1[proc_id]] ;//(COEF *)malloc(sizeof(COEF)*iwork1[proc_id]);
+    COEF * xx =  new COEF[iwork1[proc_id]] ;// (COEF *)malloc(sizeof(COEF)*iwork1[proc_id]);
+    INTS * unknownlist =  new INTS [iwork1[proc_id]] ;//(INTS *)malloc(sizeof(INTS)*iwork1[proc_id]);
+    COEF * xz = new COEF[n]; // (COEF *)malloc(sizeof(COEF)*n);
+    
+    nloc=0;
+    // if(scale)
+      {
+	for(i=0;i<n;i++)
+	  {
+	    if(riord[i]==proc_id){
+	      if(scale) rhsloc[nloc]=b[i]*scaletmpr[i]; 
+	      unknownlist[nloc++]=i;
+	    }
+	  }
+      }
+    for(i=0;i<iwork1[proc_id];i++) 
+      xx[i]=0.0;
+    ierr = HIPS_SetRHS(id, nloc, unknownlist, rhsloc, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_FOOL);
+    HIPS_ExitOnError(ierr);
+    
+    /****************************************************/
+    /* Get the local solution                           */
+    /****************************************************/ 
+    
+    ierr = HIPS_GetSolution(id, nloc, unknownlist, xx, HIPS_ASSEMBLY_FOOL);
+    
+    HIPS_ExitOnError(ierr);
+    INTL nnzp;
+    ierr= HIPS_GetInfoINT(id,HIPS_INFO_NNZ_PEAK,&nnzp); 
+
+    
+    int *perm = new int[n], *invp= new int[n];
+    
+    MPI_Gatherv(xx,iwork1[proc_id], MPI_DOUBLE, xz,iwork1,mapptr,MPI_DOUBLE,0,comm);
+    MPI_Gatherv(unknownlist,iwork1[proc_id], MPI_INT, perm,iwork1,mapptr,MPI_INT,0,comm);
+    MPI_Bcast(xz,n,MPI_DOUBLE,0, comm);
+    MPI_Bcast(perm,n,MPI_INT,0, comm);
+    
+    for(int i=0;i<n;i++) 
+      invp[perm[i]]=i;
+
+      {
+	for(int i=0;i<n;i++) 
+	  {
+	    x[i]=xz[invp[i]];
+	    if(scale) x[i]=x[i]*scaletmpc[i];
+	  }
+      }
+    REAL residu;
+    INTL ninner,nouter;
+
+    ierr= HIPS_GetInfoREAL (id,HIPS_INFO_RES_NORM,&residu);
+    ierr= HIPS_GetInfoINT(id,HIPS_INFO_INNER_ITER,&ninner); 
+    ierr= HIPS_GetInfoINT(id,HIPS_INFO_OUTER_ITER,&nouter); 
+    if(residu >eps) 
+      cout << "\n\n WARNING Hips Do not Converge " << id << " Resudual = " <<residu<< " / " <<eps 
+	   << " Itertion ninner :"<< ninner 
+	   <<" , outer : " << nouter <<"\n\n"<< endl; 
+      else if( verbosity > 1 && proc_id==0 )
+	cout << "  Hips " << id << ", Res = " <<residu << " / " <<eps 
+	 << " Iter  inner : "<< ninner 
+	     <<" , outer : " << nouter << " nzz peak =" <<nnzp << " nnz " << nnz  <<  endl; 
+    /**************************************************/
+    /* Free HIPS internal structure for problem "id"  */
+    /*************************************************/
+    //HIPS_INFO_RES_NORM
+      /*
+    */
+    delete [] xz;
+    delete [] perm;
+    delete [] invp;
+    delete [] rhsloc; 
+    delete [] unknownlist;
+    delete [] xx;
+    
+    
+  }
+							 
+  ~HipsSolver()
+  {
+    assert(id>=0);
+    if( (verbosity>3 && proc_id==0 ) ||(verbosity>9) )
+	cout << "   ~Hips_Solver S:" << id << endl;
+  //  HIPS_SetOptionINT(id,HIPS_DISABLE_PRECOND,0);
+  //  HIPS_ExitOnError(ierr);
+    ierr = HIPS_Clean(id);
+    HIPS_ExitOnError(ierr);	
+
+    delete [] iwork1;
+    delete [] mapptr;
+
+    delete [] iwork;
+    delete [] maptmp;
+    
+    if(id>0 && id< MaxIds) Ids[id]=-2;
+    id=-2; 
+ 	
+  }
+  
+  
+  void addMatMul(const KN_<double> & x, KN_<double> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<double> &) (*this) * x; 
+  }
+private:// no copy
+    HipsSolver(const HipsSolver &);  
+    HipsSolver & operator=(const HipsSolver &); 
+};  // CLASS HipsSolver
+  
+int HipsSolver::Ids[HipsSolver::MaxIds];
+
+
+
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildSolverHipsSolvermpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+  if(verbosity>9)
+    cout << " BuildSolverSuperLU<double>" << endl;
+  return new HipsSolver(*A,ds.epsilon,ds.data_filename, ds.lparams, ds.dparams,ds.master,(MPI_Comm *)ds.commworld);
+		    }
+/* --FH:   class Init { public:
+    Init();
+    }; */
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+  if(verbosity>1)
+    cout << " SetDefault sparse to default" << endl;
+  DefSparseSolver<double>::solver =SparseMatSolver_R;
+  //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+  TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+  return 1;
+}
+bool HipsDefaults(KN<long>* piop,KN<double> * pdop)
+{
+  if(piop)
+    {
+      piop->resize(17);
+      HipsSolver::Def_iopt(*piop);
+    }
+  if(pdop)
+    {
+      pdop->resize(6);
+      HipsSolver::Def_dopt(*pdop);      
+    }
+  
+  return true;
+    }
+bool SetHipsSolver()
+{
+  if(verbosity>1)
+    cout << " SetDefault sparse solver to Hips" << endl;
+  DefSparseSolver<double>::solver  =BuildSolverHipsSolvermpi;
+		      //DefSparseSolver<Complex>::solver =BuildSolverHipsSolvermpi;    
+  TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+  return 1;
+}
+
+static void Load_Init()
+{   
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: Hips,  defaultsolver defaultsolverHips" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver  =BuildSolverHipsSolvermpi;
+  //  DefSparseSolver<Complex>::solver =BuildSolverHipsSolver;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoHips","(",new OneOperator0<bool>(SetHipsSolver));
+  if(! Global.Find("HipsDefaults").NotNull() )
+    Global.Add("HipsDefaults","(",new OneOperator2<bool,KN<long>*,KN<double> *>(HipsDefaults));
+  
+}
+		      
+		      
+		      
+		      
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/hypre_FreeFem.cpp b/examples++-mpi/hypre_FreeFem.cpp
new file mode 100644
index 0000000..ab9a1ed
--- /dev/null
+++ b/examples++-mpi/hypre_FreeFem.cpp
@@ -0,0 +1,1761 @@
+
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : INRIA Saclay 
+// AUTHOR   : Guy Atenekeng
+// E-MAIL   : Guy_Antoine_Atenekeng_Kahou at lri.fr
+//
+//ff-c++-LIBRARY-dep: hypre  metis  blas  mpi
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+// FFCS: add requirement for MPI
+//ff-c++-LIBRARY-dep: hypre mpi
+//ff-c++-cpp-dep: 
+
+// add F.Hecht ...  oct 2010 
+#define HYPRE_TIMING
+// .. end add
+#include <mpi.h>
+
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#ifdef __cplusplus
+ extern "C" {
+ #include "metis.h"
+ #endif
+ #ifdef __cplusplus
+ }
+ #endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#ifdef MPI_WTIME_IS_GLOBAL
+#undef MPI_WTIME_IS_GLOBAL
+#endif
+#define MPI_WTIME_IS_GLOBAL 1
+#define STATS
+
+#include "_hypre_utilities.h"
+#include "HYPRE.h"
+#include "HYPRE_krylov.h"
+#include "HYPRE_IJ_mv.h"
+#include "HYPRE_parcsr_ls.h"
+#include "_hypre_parcsr_mv.h"
+#include "fortran_matrix.h"
+#include "HYPRE_lobpcg.h"
+
+#include "interpreter.h"
+#include "multivector.h"
+#include "HYPRE_MatvecFunctions.h"
+
+#include "HYPRE_parcsr_int.h"
+
+
+
+
+#define CHECK_ZERO
+#define MCW MPI_COMM_WORLD
+#define BUFLEN 100
+#define SCALE 0
+
+
+#ifdef SUN 
+/*
+ * 	It uses the system call gethrtime(3C), which is accurate to 
+ *	nanoseconds. 
+*/
+#include <sys/time.h>
+ 
+double dwalltime() {
+			 return ( (double)gethrtime() / 1e9 );
+				 }
+
+#else
+
+#ifndef NO_TIMER
+#include <sys/types.h>
+#include <sys/times.h>
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+#ifndef CLK_TCK
+#define CLK_TCK 60
+#endif
+
+				 double dwalltime()
+		 {
+#ifdef NO_TIMER
+			 /* no sys/times.h on WIN32 */
+			 double tmp;
+			 tmp = 0.0;
+#else
+			 struct tms use;
+			 double tmp;
+			 times(&use);
+			 tmp = use.tms_utime;
+			 tmp += use.tms_stime;
+#endif
+			 return (double)(tmp) / CLK_TCK;
+		 }
+
+#endif
+
+
+
+
+
+int roscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpr , int *ierr)
+{
+/*---------------------------------------------------------------------
+|
+| This routine scales each row of mata so that the norm is 1.
+|
+|----------------------------------------------------------------------
+| on entry:
+| mata  = the matrix (in SparRow form)
+| nrm   = type of norm
+|          0 (\infty),  1 or 2
+|
+| on return
+| diag  = diag[j] = 1/norm(row[j])
+|
+|     0 --> normal return
+|     j --> row j is a zero row
+|--------------------------------------------------------------------*/
+/*   local variables    */
+   int i, k;
+   double  scal;
+   
+   for (i=0; i<n; i++) {
+      scal = 0.0;
+    // kr = &(AAv[pr[i]]);
+      if (nrm == 0) {
+	 for (k=pr[i]; k<pr[i+1]; k++)
+	    if (fabs(AAv[k]) > scal) scal = fabs(AAv[k]);
+      }
+      else if (nrm == 1) {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scal += fabs(AAv[k]);
+      }
+      else {  /* nrm = 2 */
+         for (k=pr[i]; k<(pr[i+1]); k++)
+            scal += AAv[k]*AAv[k];
+      }
+      if (nrm == 2) scal = sqrt(scal);
+      if (scal == 0.0) {
+	*ierr=i;
+	 return i+1;
+      }
+      else 
+	 scal = 1.0 / scal;
+      scaletmpr[i] = scal;
+      for (k=pr[i]; k<(pr[i+1]); k++)
+	 AAv[k] = AAv[k] * scal;
+     
+   }
+   *ierr=0;
+   return 0;
+}
+/*---------------end of roscalC-----------------------------------------
+----------------------------------------------------------------------*/
+int coscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpc , int * ierr)
+{
+/*---------------------------------------------------------------------
+|
+| This routine scales each column of mata so that the norm is 1.
+|
+|----------------------------------------------------------------------
+| on entry:
+| mata  = the matrix (in SparRow form)
+| nrm   = type of norm
+|          0 (\infty),  1 or 2
+|
+| on return
+| diag  = diag[j] = 1/norm(row[j])
+|
+|     0 --> normal return
+|     j --> column j is a zero column
+|--------------------------------------------------------------------*/
+/*   local variables    */
+   int i, j, k;
+   double *kr;
+   int *ki;
+   for (i=0; i<n; i++)
+      scaletmpc[i] = 0.0;
+/*---------------------------------------
+|   compute the norm of each column
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+      kr = &(AAv[pr[i]]);
+      ki = &(pr[i]);
+      if (nrm == 0) {
+	 for (k=pr[i]; k<pr[i+1]; k++) {
+	    j = pr[i];
+	    if (fabs(AAv[k]) > scaletmpc[p[k]]) scaletmpc[p[k]] = fabs(AAv[k]);
+	 }
+      }
+      else if (nrm == 1) {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scaletmpc[p[k]] += fabs(AAv[k]);
+      }
+      else {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scaletmpc[p[k]] += fabs(AAv[k])*fabs(AAv[k]);
+      }
+   }
+   if (nrm == 2) {
+      for (i=0; i<n; i++)
+	 scaletmpc[i] = sqrt(scaletmpc[i]);
+   }
+/*---------------------------------------
+|   invert
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+      if (scaletmpc[i] == 0.0)
+	{
+	 *ierr=i+1;
+	 return i+1;
+	}
+      else 
+	 scaletmpc[i] = 1.0 / scaletmpc[i];
+   }
+/*---------------------------------------
+|   C = A * D
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+    
+      for (k=pr[i]; k<pr[i+1]; k++)
+	AAv[k]=AAv[k]*scaletmpc[p[k]];
+	
+   }
+   *ierr=0;
+   return 0;
+}
+/*---------------end of coscalC-----------------------------------------
+----------------------------------------------------------------------*/
+
+
+typedef struct sparse_mat_loc
+{
+        int *ptr;  //index of the beginning of rows in id_cols and vals
+        int *rows; //index of non empty rows
+        int *id_cols;
+        double *vals;
+	int ilower; // lower index limit
+	int iupper; //upper index limit
+        int n_loc ; /*number of rows*/
+        int *ncols; /*number of columns in each row*/
+}sparse_mat_loc;
+
+
+/* 
+  **Function to distribute a sparse matrix as blocks rows on several processes**
+  
+  A: (input) sparse matrix.
+    (matrix A as input is available on each process
+  type :(input) 0=CSR format, any other value=CSC
+  size: (input) size of the communicator
+  rk: (input) rank of the process in the communicator
+  A_loc: (output) sparse matrix in CSR reduced on local process
+  */
+  
+int dist_matrix(int n, int *ptr, int* id_rows, double *vals, int type, int size, int rk,int * mapptr,int *maptmp, int *iwork1 ,sparse_mat_loc *A_loc)
+{
+  	int     i, j, ilower, iupper;
+	int     n_loc, nnz_loc, relpos;
+	int     *marker;
+	
+	/* Compute the number of rows to distribute to local process */
+    n_loc =n/size;
+    if(rk==size-1) n_loc=n_loc+n%size;
+
+   
+   int i1,i2,ncols;	
+    //save the lower index (ilower) and upper (iupper) for each process
+    (A_loc)->ilower=rk*(n/size);
+    ilower=(A_loc)->ilower;
+    (A_loc)->iupper=(rk+1)*(n/size)-1; 
+    if(rk==size-1) (A_loc)->iupper=(A_loc)->iupper+n%size;
+    iupper=(A_loc)->iupper;
+    (A_loc)->n_loc=n_loc;
+  
+    
+	
+        if( !((A_loc)->ptr=(int *)malloc((n_loc+1)*sizeof(int))) ) {printf("%s","Malloc fails for ptr \n"); exit(1);}
+	if( !((A_loc)->rows=(int *)malloc((n_loc)*sizeof(int))) ) {printf("%s","Malloc fails for rows \n");exit(1);}
+	if( !((A_loc)->ncols=(int *)malloc((n_loc)*sizeof(int))) ) {printf("%s","Malloc fails for ncols \n");exit(1);}
+	
+    //Change global Input matrix (A) to local (A_loc) on each process
+	if(type==0){  //Matrix A is in CSR format
+		
+		//Gets local nnz 
+		 i1=(A_loc)->ilower;
+	         i2=(A_loc)->iupper; 
+		 (A_loc)->ilower=i1; (A_loc)->iupper=i2; nnz_loc=0;
+		 for(i=i1;i<=i2;i++){
+			nnz_loc+=ptr[i+1]-ptr[i];
+		 }
+		//Allocate memory for local matrix
+		
+		
+		if( !((A_loc)->id_cols=(int *)malloc(nnz_loc*sizeof(int))) ) {printf("%s","Malloc fails for id_cols \n");exit(1);}
+		if( !((A_loc)->vals=(double *)malloc(nnz_loc*sizeof(double))) ) {printf("%s","Malloc fails for vals"); exit(1);}
+		
+		//Transfer the corresponding values from global to local
+		relpos=0; 
+		//int ncols; //count number of elements in each row
+		for(i=i1;i<=i2;i++){
+			(A_loc)->rows[i-i1]=i;
+			(A_loc)->ptr[i-i1]=relpos;
+			ncols=relpos;
+			for(j=ptr[i];j<ptr[i+1];j++){
+				(A_loc)->id_cols[relpos]=id_rows[j];
+				(A_loc)->vals[relpos]=vals[j];
+				relpos++;
+			}
+			(A_loc)->ncols[i-i1]=relpos-ncols;
+		}
+		//cout << "taille des sous domaines" << nnz_loc << endl;
+	}
+	else{ //matrix A is in CSC format
+		marker= (int *)calloc(n, sizeof(int)); //count number of elements in each row
+		for(i=0; i<n; i++)
+			for(j=ptr[i]; j<ptr[i+1]; j++)
+				marker[id_rows[j]]++;
+		
+		(A_loc)->ptr[0]=0; //set up the beginning of each row
+		for(i=0; i<n_loc; i++){
+			(A_loc)->ptr[i+1] = (A_loc)->ptr[i] + marker[i+ilower];
+				(A_loc)->id_cols[relpos]=id_rows[j];
+				(A_loc)->vals[relpos]=vals[j];
+				relpos++;
+			}
+			(A_loc)->ncols[i-ilower]=relpos-ncols;
+		}
+    return 0;
+}
+
+
+
+
+class hypreParam {
+ //Solveur and preconditionner
+  public: 
+  char  solver[BUFLEN];
+  char  precon[BUFLEN];
+ //BoomerAMG parameter
+  int                  amg_coarsentype ;    /* Falgout coarsening */
+  int                  amg_relaxtype;      /* hybrid Gauss-Seidel or SOR */ 
+  int			amg_interptype;		/* default*/
+  int 			amg_maxlevels;
+  int                  amg_numsweeps;        /*default*/
+  double               amg_strongthreshold;/*suitable for 3D Laplace Operator*/
+  double		amg_truncfactor; 
+  int                  amg_prntlevel;        /* print setup info */
+  double			amg_tol;			//BoomerAMG Tolerance
+  int			amg_maxiter;
+  int 			scale;
+  int 			gsmg_sample, measure_type,cycle_type;
+  int                  solv_stopcrit ;
+  double trunc_factor;
+   
+  //More complex smoothers (Schwarz methods, Pilut, Parasails, Euclid)
+  int					smooth_type;
+  int 					smooth_numlevels; 
+  int 					smooth_numsweeps;
+  double				pilut_droptol;
+  double 				pilut_maxnz;
+  int					schwarz_overlap;
+  int 					schwarz_variant;
+  int					schwarz_domaintype;
+  
+  //parasails parameter
+  int                  sai_max_levels ;
+  double               sai_threshold ;
+
+  double               sai_filter ;
+  int                  sai_sym ;
+  int                  sai_log ;
+  int                  VERBOSE;
+
+  /***************************HYPRE_BOOMERAMG***********************/
+  double strong_threshold;
+ 
+  int * num_grid_sweeps;  
+  int * grid_relax_type;  
+  int * grid_relax_points;
+  double * relax_weight;
+  double *  omega;   
+  //Solver parameter (used for GMRES , PCG or BiCGStab)
+  double               solv_tol ;
+  int                  solv_maxiter;
+  int                  solv_kdim;
+  int                  solv_log;
+  int                  solv_prntlevel;
+  int                     precond_id, solver_id,matrix_id,solver_type;
+  int smooth_num_levels,smooth_num_sweeps,max_levels,Two_Norm;
+  int domain_type, num_functions,variant,overlap,nonzeros_to_keep;
+  double max_row_sum,drop_tol;
+  int *dof_func; 
+  int                 pcg_max_its,rrow_size,Rel_change;
+  int                 dscg_max_its,coarsen_type,hybrid,k_dim,num_sweep; 
+  int 		      pmax_iter;
+  double              cf_tol,tol,pc_tol;
+  double schwarz_rlx_weight;
+ 
+  /*For timing*/
+  int timing;
+public : hypreParam(const KN<long> &param_int, const KN<double> &param_double)
+  {
+    amg_coarsentype =6;    /* Falgout coarsening */
+    amg_relaxtype =3;      /* hybrid Gauss-Seidel or SOR */ 
+    amg_interptype=0;		/* default*/
+    amg_maxlevels=25;
+    amg_numsweeps=1;        /*default*/
+    amg_strongthreshold = 0.25;/*suitable for 3D Laplace Operator*/
+    amg_truncfactor=0.3; 
+    amg_prntlevel =1;        /* print setup info */
+    amg_tol=0.0;			//BoomerAMG Tolerance
+    amg_maxiter=20;
+    gsmg_sample=1;
+   //More complex smoothers (Schwarz methods, Pilut, Parasails, Euclid)
+    smooth_type=6;
+    smooth_numlevels=3; 
+    smooth_numsweeps=1;
+    pilut_droptol=1.0e-4;
+    pilut_maxnz=100;
+    schwarz_overlap=10;
+    schwarz_variant=2;
+    schwarz_domaintype=2;
+   //parasails parameter
+    sai_max_levels = 1;
+    sai_threshold = 0.1;
+    sai_filter = 0.1;
+    sai_sym =0;
+    sai_log = 1;
+    int i;
+			
+   //Solver parameter (used for GMRES or BiCGStab)
+    solv_tol = 1.0e-11;
+    solv_maxiter = 1000;
+    solv_kdim =40;
+    
+    solv_log = 0;
+    solv_prntlevel = 2;
+    precond_id=0;//BOOMER AMG 	
+    solver_id=1; //GMRES as solver
+    VERBOSE=0;
+    scale=1;
+    pmax_iter=30;
+    rrow_size=1000;
+    solv_stopcrit=1;
+
+    amg_interptype =6;  gsmg_sample =5; amg_coarsentype =6; 
+
+    measure_type =1;amg_strongthreshold=0.25; trunc_factor=1e-2; 
+
+    amg_maxiter=20; cycle_type=1;  smooth_num_levels=3; 
+    smooth_num_sweeps=1; max_levels=25; hybrid=1;
+   k_dim = 5;  smooth_type = 6;  num_functions = 1;  smooth_num_levels = 3;
+   smooth_num_sweeps = 2; num_sweep = 1;      variant = 0;
+   overlap = 10;  domain_type = 2;     nonzeros_to_keep = 1000;
+   tol = 1.e-8;  pc_tol = 0.;
+   drop_tol = -1.;  max_row_sum = 0.9; schwarz_rlx_weight = 1.;  sai_threshold = 0.1;
+   sai_filter = 0.1;
+	
+
+    relax_weight      = hypre_CTAlloc(double, max_levels);
+    omega             = hypre_CTAlloc(double, max_levels);
+    for (i=0; i < max_levels; i++)
+      {
+	relax_weight[i] = 1.;
+	omega[i] = 1.;
+      }
+    max_row_sum=0.9;  schwarz_rlx_weight=1.; variant=0; 
+    num_functions=1; overlap=10; domain_type= 2;
+		  		 	 
+    if(param_int.N()>0) {if((param_int[0]>=0)&&(param_int[0]<=9)) solver_id=param_int[0]; 
+      else solver_id=1;} //GMRES as solver
+	       
+    if((solver_id!=4)&&(solver_id!=5)){      
+      if(param_int.N()>1) {if((param_int[1]>=0)&&(param_int[1]<=9)) 
+	  precond_id=param_int[1]; else precond_id=0;}//BOOMER AMG }
+      if(param_int.N()>2) {if(param_int[2]>0)  solv_maxiter = param_int[2];else solv_maxiter=1000;}
+      if(param_int.N()>3) {if(param_int[3]>0)  solv_kdim =param_int[3];else solv_kdim=40;}
+      if(param_int.N()>4) {if(param_int[4]>=0) solv_prntlevel = param_int[4];}
+      if(param_int.N()>5) {if(param_int[5]>=0) solv_log = param_int[5];}
+      if(param_int.N()>6) {if(param_int[6]>=0) solv_stopcrit = param_int[6];}
+		
+
+      if(param_double.N()>0) {if(param_double[0]>0) solv_tol = param_double[0];}
+      switch(precond_id)
+	{
+	case 0 : //Preconditionner AMG
+	  if(param_int.N()>7)  {if(param_int[7]>=0) amg_interptype =param_int[7];}
+	  if(param_int.N()>8)  {if(param_int[8]>=0) gsmg_sample =param_int[8];}
+	  if(param_int.N()>9)  {if(param_int[9]>=0) amg_coarsentype =param_int[9];}
+	  if(param_int.N()>10) {if(param_int[10]>=0) measure_type =param_int[10];}
+	  if(param_double.N()>1) {if(param_double[1]>0) amg_strongthreshold = param_double[1];}
+	  if(param_double.N()>2) {if(param_double[2]>0) trunc_factor = param_double[2];}
+	  //if(param_int.N()>11)  {if(param_int[11]>0) amg_maxiter=param_int[11];}
+	  if(param_int.N()>11)  {if(param_int[11]>0) cycle_type=param_int[11];}
+	  if(param_int.N()>12)  {if(param_int[12]>0)  smooth_type=param_int[12];}
+	  if(param_int.N()>13) {if(param_int[13]>0) smooth_num_levels=param_int[13];}
+	  if(param_int.N()>14) {if(param_int[14]>0) smooth_num_sweeps=param_int[14];}
+	  if(param_int.N()>15) {if(param_int[15]>0) max_levels = param_int[15];}
+	  relax_weight      = hypre_CTAlloc(double, max_levels);
+	  omega      = hypre_CTAlloc(double, max_levels);
+	  for (i=0; i < max_levels; i++)
+	    {
+	      relax_weight[i] = 1.;
+	      omega[i] = 1.;
+	    }
+	  if(param_double.N()>3) {if(param_double[3]>0) max_row_sum = param_double[3];else max_row_sum=0.9;} else max_row_sum=0.9;
+	  if(param_double.N()>4) {if(param_double[4]>0) schwarz_rlx_weight = param_double[4];else schwarz_rlx_weight=1.;} else schwarz_rlx_weight=1.;
+	  if(param_int.N()>16) {if(param_int[16]>0) variant = param_int[16];else variant=3;} else variant=3;
+	  if(param_int.N()>17) {if(param_int[17]>0) num_functions = param_int[17];else num_functions=1;} else num_functions=1;
+	  if(param_int.N()>18) {if(param_int[18]>0) overlap = param_int[18];else overlap=10;} else overlap=10;
+	  if(param_int.N()>19) {if(param_int[19]>0) domain_type = param_int[19]; else domain_type= 2;} else domain_type= 2;				
+	  break;
+	  
+	case 1: //Preconditionner PILUT
+	  
+	  if(param_double.N()>1) {if(param_double[1]>0) drop_tol = param_double[1]; else drop_tol=1e-5;} else drop_tol=1e-5;
+	  if(param_int.N()>7)    {if(param_int[7]>0) nonzeros_to_keep = param_int[7]; else nonzeros_to_keep=1000;} else nonzeros_to_keep=1000;
+	  if(param_int.N()>8)    {if(param_int[8]>0) pmax_iter = param_int[8];}
+	  if(param_int.N()>9)    {if(param_int[9]>0) rrow_size = param_int[9];} 
+	  
+	  break;
+
+	case 2://Preconditionner ParaSails
+	  if(param_double.N()>1) {if(param_double[1]>0) sai_filter = param_double[1];else sai_filter=0.1;} else sai_filter=0.1;
+	  if(param_double.N()>2) {if(param_double[2]>0) sai_threshold = param_double[2];else sai_threshold=0.1;} else sai_threshold=0.1;
+	  if(param_int.N()>7)    {if(param_int[7]>0) max_levels = param_int[7];else max_levels=1;} else max_levels=1;
+	  if(param_int.N()>8)    {if(param_int[8]>0) sai_sym =param_int[8];else sai_sym=0;} else sai_sym=0;
+	  break;
+
+	case 3: //Preconditionner Schwarz
+	  if(param_double.N()>1) {if(param_double[1]>0) schwarz_rlx_weight = param_double[1];schwarz_rlx_weight=1;} 
+	  else schwarz_rlx_weight=1.;
+	  if(param_int.N()>7)    {if(param_int[7]>0) variant = param_int[7];else variant=1;} else variant=1;
+	  if(param_int.N()>8)    {if(param_int[8]>0) overlap = param_int[8];else overlap=1;} else overlap=1;
+	  if(param_int.N()>9)    {if(param_int[9]>0) domain_type = param_int[9];else domain_type=3;} else domain_type=3;
+	  break;
+
+	default:
+	  break;
+	}
+    }
+
+
+	
+		if(solver_id==4) // Solver AMG_HYBRID
+		{
+		 
+		 if(param_double.N()>1)  {if(param_double[1]>=0) amg_tol =param_double[1];else amg_tol=1e-9;} else amg_tol=1e-9;
+		 if(param_double.N()>2)  {if(param_double[2]>=0) cf_tol =param_double[2];else cf_tol= 1e-3;}  else cf_tol= 1e-3;
+		 if(param_int.N()>1)  {if(param_int[1]>=0) solver_type =param_int[1];else solver_type=1;} else solver_type=1;
+		 if(param_int.N()>2)  {if(param_int[2]>0) dscg_max_its=param_int[2];else dscg_max_its=1000;}  else dscg_max_its=1000;
+		 if(param_int.N()>3)  {if(param_int[3]>0) pcg_max_its=param_int[3];else pcg_max_its=200;}   else pcg_max_its=200;
+		 if(param_int.N()>4)  {if(param_int[4]>0) coarsen_type=param_int[4]; else coarsen_type=6;}  else coarsen_type=6;
+		 if(param_double.N()>3) {if(param_double[3]>0) strong_threshold = param_double[3]; else strong_threshold=1e-3;} else strong_threshold=1e-3;
+		 if(param_double.N()>4) {if(param_double[4]>0) trunc_factor = param_double[4]; else trunc_factor=1e-2;} else trunc_factor=1e-2;
+		 if(param_int.N()>5) {if(param_int[5]>0) max_levels = param_int[5]; else max_levels=25;} else max_levels=25;
+        	 if(param_double.N()>5) {if(param_double[5]>0) max_row_sum = param_double[5];else max_row_sum=0.9;} else max_row_sum=0.9;
+
+		 relax_weight      = hypre_CTAlloc(double, max_levels);
+   		 omega      = hypre_CTAlloc(double, max_levels);
+		for (i=0; i < max_levels; i++)
+		   {
+			relax_weight[i] = 1.;
+			omega[i] = 1.;
+		   }
+		}
+		if(solver_id==3)
+		{
+			if(param_int.N()>7)  {if(param_int[7]>=0) Two_Norm =param_int[7];else Two_Norm=2;} else Two_Norm=2;
+			if(param_int.N()>8)  {if(param_int[8]>=0) Rel_change =param_int[8];else Rel_change=1;} else Rel_change=1;
+		}
+		if(solver_id==5) //Solver AMG
+		{
+		 if(param_int.N()>7)  {if(param_int[7]>=0) amg_interptype =param_int[7];}
+		 if(param_int.N()>8)  {if(param_int[8]>=0) gsmg_sample =param_int[8];}
+		 if(param_int.N()>9)  {if(param_int[9]>=0) amg_coarsentype =param_int[9];}
+		 if(param_int.N()>10) {if(param_int[10]>=0) measure_type =param_int[10];}
+   		 if(param_double.N()>2) {if(param_double[2]>0) amg_strongthreshold = param_double[2];}
+   		 if(param_double.N()>3) {if(param_double[3]>0) trunc_factor = param_double[3];}
+                 if(param_int.N()>11)  {if(param_int[11]>0) amg_maxiter=param_int[11];}
+		 if(param_int.N()>12)  {if(param_int[12]>0) cycle_type=param_int[12];}
+		 if(param_int.N()>13)  {if(param_int[13]>0)  smooth_type=param_int[13];}
+		 if(param_int.N()>14) {if(param_int[14]>0) smooth_num_levels=param_int[14];}
+  		 if(param_int.N()>15) {if(param_int[15]>0) smooth_num_sweeps=param_int[15];}
+		 if(param_int.N()>16) {if(param_int[16]>0) max_levels = param_int[16];}
+		 relax_weight      = hypre_CTAlloc(double, max_levels);
+   		 omega      = hypre_CTAlloc(double, max_levels);
+		for (i=0; i < max_levels; i++)
+		   {
+			relax_weight[i] = 1.;
+			omega[i] = 1.;
+		   }
+		 if(param_double.N()>4) {if(param_double[4]>0) max_row_sum = param_double[4];else max_row_sum=1e-1;} else max_row_sum=1e-1;
+		 if(param_double.N()>5) {if(param_double[5]>0) schwarz_rlx_weight = param_double[5];else schwarz_rlx_weight=1.;} else schwarz_rlx_weight=1.;
+		 if(param_int.N()>17) {if(param_int[17]>0) variant = param_int[17];else variant=1;} else variant=1;
+		 if(param_int.N()>19) {if(param_int[18]>0) num_functions = param_int[18];else num_functions=5;} else num_functions=5;
+		 if(param_int.N()>20) {if(param_int[19]>0) overlap = param_int[19];else overlap=1;} else overlap=1;
+		 if(param_int.N()>21) {if(param_int[20]>0) domain_type = param_int[20];else domain_type= 1;} else domain_type= 1;
+		}
+		if(param_int.N()>22) {if(param_int[22]>0) VERBOSE = param_int[22];}
+		if(param_int.N()>23) {if(param_int[23]>0) scale = param_int[23]; else scale=1;} else scale=1;
+		if(param_int.N()>24) {if(param_int[24]>0) timing = param_int[24]; else timing=1;} else timing=1; 
+             }
+
+  public : hypreParam()
+	{
+		int i;
+		amg_coarsentype =6;    /* Falgout coarsening */
+   		amg_relaxtype =3;      /* hybrid Gauss-Seidel or SOR */ 
+	 	amg_interptype=0;		/* default*/
+   		amg_maxlevels=25;
+   		amg_numsweeps=1;        /*default*/
+		amg_strongthreshold = 0.25;/*suitable for 3D Laplace Operator*/
+   		amg_truncfactor=0.3; 
+		amg_prntlevel =1;        /* print setup info */
+		amg_tol=1e-7;			//BoomerAMG Tolerance
+		amg_maxiter=1;
+		gsmg_sample=1;
+	
+   
+			
+   //Solver parameter (used for GMRES or BiCGStab)
+   		solv_tol = 1.0e-11;
+		solv_maxiter = 1000;
+		solv_kdim =40;
+
+		solv_log = 0;
+		solv_prntlevel = 2;
+		precond_id=0;//BOOMER AMG 	
+		solver_id=1; //GMRES as solver
+	        VERBOSE=0;
+		scale=1;
+                pmax_iter=30;
+		rrow_size=1000;
+
+
+		amg_interptype =0;  gsmg_sample =1; amg_coarsentype =6; measure_type =1;amg_strongthreshold=0.25;
+		trunc_factor=1e-2;  amg_maxiter=20; cycle_type=1; smooth_type=6; smooth_num_levels=0; smooth_num_sweeps=2; max_levels=25;
+
+		relax_weight      = hypre_CTAlloc(double, max_levels);
+   		omega             = hypre_CTAlloc(double, max_levels);
+		for (i=0; i < max_levels; i++)
+		   {
+			relax_weight[i] = 1.;
+			omega[i] = 1.;
+		   }
+		 max_row_sum=0.9;  schwarz_rlx_weight=1.; variant=0;  num_functions=1; overlap=10; domain_type= 0;
+		
+		 
+
+
+		
+	}
+  public : hypreParam(char * fileparameter, MPI_Comm comm)
+	{
+		FILE *f;
+        	char buf[BUFLEN];
+		int num;
+		int rk, size;
+		MPI_Comm_rank(comm,&rk);
+		MPI_Comm_size(comm, &size);
+
+		
+		amg_coarsentype =6;    /* Falgout coarsening */
+   		amg_relaxtype =3;      /* hybrid Gauss-Seidel or SOR */ 
+	 	amg_interptype=0;		/* default*/
+   		amg_maxlevels=25;
+   		amg_numsweeps=1;        /*default*/
+		amg_strongthreshold = 0.25;/*suitable for 3D Laplace Operator*/
+   		amg_truncfactor=0.3; 
+		amg_prntlevel =1;        /* print setup info */
+		amg_tol=0.0;			//BoomerAMG Tolerance
+		amg_maxiter=20;
+   //More complex smoothers (Schwarz methods, Pilut, Parasails, Euclid)
+		smooth_type=6;
+		smooth_numlevels=3; 
+		smooth_numsweeps=1;
+		pilut_droptol=1.0e-4;
+ 		pilut_maxnz=100;
+		schwarz_overlap=10;
+		schwarz_variant=2;
+		schwarz_domaintype=2;
+   //parasails parameter
+  		sai_max_levels = 1;
+		sai_threshold = 0.1;
+		sai_filter = 0.05;
+	        sai_sym =0;
+	        sai_log = 1;
+	
+   //Solver parameter (used for GMRES or BiCGStab)
+   		solv_tol = 1.0e-30;
+		solv_maxiter = 80;
+		solv_kdim =40;
+  //  int                  solv_stopcrit = 1; //only for BiCGSTAB
+		solv_log = 0;
+		solv_prntlevel = 0;
+		precond_id=0;//BOOMER AMG 	
+		solver_id=1; //GMRES as solver
+		VERBOSE=0;
+		scale=1;
+		
+
+
+
+		if(fileparameter==NULL)
+		{
+			if(rk==0) printf("%s","Set default parameter because you not precise the parameter file \n \n");
+			solver_id=1; //GMRES as solver
+			precond_id=0;//BOOMER AMG 
+		
+		}
+		else if( (f=fopen(fileparameter,"r") )==NULL)
+			{
+			if(rk==0)printf("%s","Set default parameter because your parameter file not exist \n \n");
+			solver_id=1; //GMRES as solver
+			precond_id=0;//BOOMER AMG 	
+			}	
+			else
+			{
+			 if(rk==0) printf("%s%s%s","Read parameter from file ", fileparameter, "\n \n");
+			 num =0;
+			 while(fgets(buf, BUFLEN, f) != NULL) 
+			 {
+				switch(num) {
+				case 0:
+				sscanf(buf, "%s", solver); 
+				break;
+				case 1:
+ 				sscanf(buf, "%d", &solver_id);
+			        break;
+				case 2:
+ 				sscanf(buf, "%lf", &solv_tol);
+			        break;
+				case 3:
+ 				sscanf(buf, "%d", &solv_maxiter);
+			        break;
+				case 4:
+ 				sscanf(buf, "%d", &solv_prntlevel);
+			        break;
+				case 5:
+ 				sscanf(buf, "%d", &solv_log);
+				if(solver_id!=1) {fgets(buf, BUFLEN, f);num++;}
+				break;				
+				case 6:
+				sscanf(buf, "%d", &solv_kdim);
+			        break;
+				case 7:
+				sscanf(buf, "%s", precon); 
+				break;
+				case 8:
+				sscanf(buf, "%d", &precond_id); 
+				 	
+				if(precond_id==2) //The parameter of preconditionner is inside file
+				{
+					fclose(f);
+					exit(1);
+				}
+				break;
+				case 9:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_coarsentype); 
+				if(precond_id==1)
+				sscanf(buf, "%lf", &sai_threshold); 
+				break;
+				case 10:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_prntlevel); 
+				if(precond_id==1)
+				sscanf(buf, "%d", &sai_max_levels); 
+				break;
+				case 11:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_interptype); 
+				if(precond_id==1)
+				sscanf(buf, "%lf", &sai_filter); 
+				break;
+				case 12:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_maxlevels); 
+				if(precond_id==1)
+				case 17:
+				sscanf(buf, "%d", &amg_prntlevel); 
+				break;
+				case 18:
+				sscanf(buf, "%lf", &amg_tol); 
+				break;
+				case 19:
+				sscanf(buf, "%d", &amg_maxiter); 
+				break;	
+				case 20:
+				sscanf(buf, "%d", &scale); 
+				break;						
+				default:
+				break;
+				}	
+         		 num++;	
+			 }
+			 if(fclose(f)==EOF) printf("%s","Error while closing the file \n"); else printf("%s","File is well close \n");			
+			}
+	}
+	
+};
+
+class HypreSolver :   public MatriceMorse<double>::VirtualSolver   {
+  mutable HYPRE_IJMatrix       ij_A;
+  mutable HYPRE_IJVector       ij_B;
+  mutable HYPRE_IJVector       ij_X;
+  mutable HYPRE_ParCSRMatrix   par_A;
+  mutable HYPRE_ParVector      par_B;
+  mutable HYPRE_ParVector      par_X;
+  void               *object;
+  HYPRE_ParCSRMatrix  parcsr_A;
+
+  string data_option;
+  mutable int		       time_index,time_index1;
+  mutable HYPRE_Solver         solver;
+  mutable HYPRE_Solver         precond;
+  mutable hypreParam           *param;
+  mutable double *scaletmpr, *scaletmpc;
+  mutable int rk,size;
+  int                  jlower, jupper;
+  int                  ilower, iupper;
+  mutable    int num_iter;
+  mutable   double 		final_res_norm;
+  mutable   double 		tgv,eps,tol_pivot,tol_pivot_sym,epsr;
+  sparse_mat_loc	A_loc;
+  mutable int *iwork, *maptmp, *mapptr, *iwork1,*riord;
+  mutable int n_loc,n,VERBOSE;
+  mutable MPI_Comm comm;
+  mutable int pcg_num_its,dscg_num_its; 
+
+ 
+public:
+  HypreSolver(const MatriceMorse<double> &AA,string datafile,
+	      KN<long> &param_int,  KN<double> &param_double,  
+	      MPI_Comm  * mpicommw )	
+  { 
+    int i,j,ierrr;
+    if(mpicommw==NULL){
+     comm=MPI_COMM_WORLD; 
+    }
+    else
+      comm= *mpicommw;
+	
+    /*****INITIALIZE MPI ENVIRONMENT*****/
+
+    ierrr = MPI_Comm_rank(comm, &rk);
+    ierrr = MPI_Comm_size(comm, &size);
+
+    
+    if(((param_double!=NULL)||(param_int!=NULL))&&(datafile.empty()))
+      {
+	if(rk==0)
+	  cout << "#########PARAMETERS ARE SET INSIDE A VECTOR###"<< endl;
+	param=new hypreParam(param_int,param_double);
+      }
+    if((datafile.empty())&&((param_int==NULL)&&(param_double==NULL)))
+      {
+	if(rk==0)
+	cout << "###########DEFAULT PARAMETERS WILL BE SET#######"<< endl;
+	param= new hypreParam();
+      }
+    if((!datafile.empty())&&((param_int==NULL)&&(param_double==NULL)))
+      {
+	if(rk==0)
+	  cout << "#########PARAMETERS ARE INSIDE A FILE#########"<< endl;
+	char *p;
+	p=new char[datafile.length()+1]; strcpy(p,datafile.c_str()); 
+	param= new hypreParam(p,comm);
+      }
+	
+    /*###################################################
+                         USING HYPRE
+    ####################################################*/
+    int n,nnz, *pr, *p,ierr;
+    double * AAv;
+    n=AA.n; nnz=AA.nbcoef;
+    /*##################################################
+                      COPY ENTRY MATRIX
+     ##################################################*/   
+	if(param->timing){
+	time_index = hypre_InitializeTiming("MATRIX DISTRIBUTION");
+   	hypre_BeginTiming(time_index);
+	}
+   
+ 
+    pr= new int[n+1];p=  new int[nnz];	AAv=new double[nnz];
+    for(i=0;i<nnz;i++){
+      AAv[i]=AA.a[i]; p[i]=AA.cl[i];
+      if(i<=n) pr[i]=AA.lg[i];
+    }
+    int job, tmp;
+    if(param->scale) {
+      job = 1; /*-- compute  1-norm */
+      tmp = 2; /*-- compute 2-norm  */
+      scaletmpr=new double[n]; 	 scaletmpc=new double[n]; 
+      roscal(n,job,tmp,AAv,p,pr,scaletmpr,&ierr);
+      if (ierr) fprintf(stderr, "ERROR: IN ROSCAL, IERR = %d\n", ierr);
+      /*------- scale the RHS according to row scaling coefficients */
+      coscal(n,job,tmp,AAv,p,pr,scaletmpc,&ierr);
+      if (ierr) fprintf(stderr, "ERROR : IN COSCAL, IERR = %d\n", ierr);
+    } /*--- end of branch on scaling */
+
+	
+	/*************************************************************
+	Distribute input matrix into local structures
+	*************************************************************/
+    int type=0,wgtflag=0, numflag=0, volume; //0=CSR; 1=CSC
+    int option[5];  option[0]=0;
+    riord=(int *)malloc(sizeof(int)*n);
+    if(riord==NULL){if(rk==0) printf("%s","IN PARTITION , MEMORY ALLOCATION FAILED \n");exit(1);}
+    /************************USE METIS FOR DATA DISTRIBUTION**************************/
+    if(size>1)
+      METIS_PartGraphKway(&n, pr, p, NULL, NULL, &wgtflag, &numflag,&size, option, &volume, riord);
+    else if(size==1){
+      for (i=0; i<n; i++) riord[i]=0;}
+    iwork= new int[n]; maptmp = new int[n]; mapptr = new int[size+1]; iwork1= new int[size+1];
+    for(i=0; i<size; i++){
+      iwork[i]=0;iwork1[i]=0; }
+    for(j=0; j<n; j++){
+      iwork[riord[j]]++;
+      iwork1[riord[j]]++;
+    }
+    numflag=0;
+    for(i=0; i<size; i++){
+      mapptr[i]=numflag;
+      numflag+=iwork[i];
+    }
+    mapptr[size]=numflag;
+
+    for (i=0; i<size; i++){
+      iwork[i]=mapptr[i];
+    }
+    for(i=0; i<n; i++){
+      maptmp[iwork[riord[i]]]=i;
+      iwork[riord[i]]++;
+    }
+    
+    dist_matrix(AA.n,pr,p,AAv, type, size, rk,mapptr,maptmp,iwork1, &A_loc); 	
+    /***Distribute vector***/
+    n_loc=A_loc.n_loc;
+    /**** Preparing Matrix *****/
+    ierr=0;
+    ilower=A_loc.ilower; jlower=ilower;	iupper=A_loc.iupper; jupper=iupper;
+    ierr+=HYPRE_IJMatrixCreate(comm, ilower, iupper, jlower, jupper, &ij_A);
+    
+	if (ierr)
+   {
+     printf("Error in driver building IJMatrix from parcsr matrix. \n");
+     exit(-1);
+   }
+        
+
+    ierr+=HYPRE_IJMatrixSetObjectType(ij_A, HYPRE_PARCSR);
+    ierr+=HYPRE_IJMatrixInitialize(ij_A);
+    
+   int taille;
+
+    for(i=ilower;i<=iupper;i++){
+	   taille=pr[i+1]-pr[i];
+	  
+	   ierr+=HYPRE_IJMatrixSetValues(ij_A, 1, &taille, &i , &(p[pr[i]]), &(AAv[pr[i]]));
+	}
+   
+    ierr+=HYPRE_IJMatrixAssemble(ij_A);
+   /*Extract HYPRE Object data structures suitable for the solvers*/
+    ierr+=HYPRE_IJMatrixGetObject(ij_A, (void **) &par_A);	   
+
+
+   /*Free local matrix in A_loc, B and X*/
+    free(A_loc.rows); free(A_loc.id_cols); free(A_loc.vals); free(A_loc.ncols); 
+    if(param->timing){
+	     hypre_EndTiming(time_index);
+   	     hypre_PrintTiming("IJ Matrix Setup", comm);
+	     hypre_FinalizeTiming(time_index);
+   	     hypre_ClearTiming();
+	}
+   
+   
+   
+    /*************************************************************
+                Create preconditioner 
+   
+                  Setup and Use solver
+   **************************************************************/
+   
+
+  param->timing=1;
+
+  
+
+   switch(param->solver_id){
+       case 0 : //BiCGStab solver
+	 HYPRE_ParCSRBiCGSTABCreate(comm, &solver);           
+	 HYPRE_ParCSRBiCGSTABSetTol(solver, param->solv_tol);
+	 HYPRE_ParCSRBiCGSTABSetMaxIter(solver, param->solv_maxiter);
+	 //HYPRE_ParCSRBiCGSTABSetStopCrit(solver, solv_stopcrit);
+	 HYPRE_ParCSRBiCGSTABSetPrintLevel(solver, param->solv_prntlevel);
+	 HYPRE_ParCSRBiCGSTABSetLogging(solver, param->solv_log);
+	
+
+            //Set Preconditioner
+	 switch (param->precond_id){
+	 case 0 : //set BoomerAMG as preconditioner
+	   if(rk==0) printf("SOLVER: BOOMERAMG-BiCGSTAB\n");
+	   HYPRE_BoomerAMGCreate(&precond);
+	
+
+	HYPRE_BoomerAMGSetInterpType(precond, param->amg_interptype);
+    
+       HYPRE_BoomerAMGSetTol(precond, param->amg_tol);
+       HYPRE_BoomerAMGSetCoarsenType(precond, param->amg_coarsentype); 
+       HYPRE_BoomerAMGSetMeasureType(precond,param-> measure_type);
+       HYPRE_BoomerAMGSetStrongThreshold(precond, param->amg_strongthreshold);
+
+       HYPRE_BoomerAMGSetTruncFactor(precond,param->trunc_factor);
+
+       HYPRE_BoomerAMGSetMaxIter(precond, param->amg_maxiter);
+       HYPRE_BoomerAMGSetCycleType(precond,param->cycle_type);
+       
+       HYPRE_BoomerAMGSetSmoothType(precond,param->smooth_type);
+       HYPRE_BoomerAMGSetSmoothNumLevels(precond,param->smooth_num_levels);
+       HYPRE_BoomerAMGSetSmoothNumSweeps(precond,param->smooth_num_sweeps);
+       HYPRE_BoomerAMGSetMaxLevels(precond,param->max_levels);
+       HYPRE_BoomerAMGSetMaxRowSum(precond,param->max_row_sum);
+       
+       HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);
+       
+      
+       HYPRE_BiCGSTABSetPrecond(solver, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup, 
+			     precond);
+	   break;
+	 case 4:
+	   /*use diagonal scaling as preconditioner*/
+	   if(rk==0) printf("SOLVER: DS-BiCGSTAB\n");
+	   precond=NULL;
+	   HYPRE_ParCSRBiCGSTABSetPrecond(solver, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScale, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScaleSetup, 
+					  precond);
+	   break;
+	 case 1:
+	   /*Use PILUT as preconditioner*/
+	   if(rk==0) printf("SOLVER: PILUT-BiCGSTAB\n");
+	   ierr=HYPRE_ParCSRPilutCreate(comm,&precond);
+	   if(ierr) printf("ERROR: PILUT-BiCGSTAB\n");
+	  
+	   if(param->drop_tol>=0)
+	     HYPRE_ParCSRPilutSetDropTolerance(precond,param->drop_tol);
+	   if(param->nonzeros_to_keep>=0)
+	     HYPRE_ParCSRPilutSetFactorRowSize(precond,param->nonzeros_to_keep);
+
+	   HYPRE_ParCSRBiCGSTABSetPrecond(solver, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSolve, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSetup, 
+					  precond);
+	   break;
+	 case 2:
+	   if(rk==0) printf("SOLVER: ParaSails-BicGSTAB\n");
+	   ierr=HYPRE_ParaSailsCreate(comm,&precond);
+	   if(ierr) printf("ERROR: ParaSails-BicGSTAB\n");
+	   HYPRE_ParaSailsSetParams(precond,param->sai_threshold,param->max_levels);
+	   HYPRE_ParaSailsSetFilter(precond,param->sai_filter);	  
+	   HYPRE_ParaSailsSetSym(precond,param->sai_sym);
+
+	   HYPRE_ParCSRBiCGSTABSetPrecond(solver, 
+					   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSolve, 
+					   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSetup, 
+					   precond);
+	   break;
+	case 3:
+       if(rk==0) printf("SOLVER: Schwarz-PCG \n");
+       	 HYPRE_SchwarzCreate(&precond);
+         HYPRE_SchwarzSetVariant(precond,param->variant);
+         HYPRE_SchwarzSetOverlap(precond,param->overlap);
+         HYPRE_SchwarzSetDomainType(precond,param->domain_type);
+       //HYPRE_SchwarzSetRelaxWeight(precond,param->schwarz_rlx_weight);
+       /*HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);*/
+
+       HYPRE_BiCGSTABSetPrecond(solver, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSolve, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSetup, 
+			   precond);
+
+       break;
+
+	 
+	 default: break;
+	   
+	 }
+	  
+  	break;
+  
+   case 2:/*USE PCG AS SOLVER*/
+     HYPRE_ParCSRPCGCreate(comm, &solver);
+     HYPRE_ParCSRPCGSetTol(solver, param->solv_tol);
+     HYPRE_PCGSetMaxIter(solver, param->solv_maxiter);   
+     HYPRE_PCGSetPrintLevel(solver, param->solv_prntlevel);
+     
+
+     HYPRE_PCGSetTwoNorm(solver, param->Two_Norm);
+     HYPRE_PCGSetRelChange(solver,param->Rel_change);
+     HYPRE_PCGGetPrecond(solver,&precond);
+     switch (param->precond_id){
+     case 0 : //set BoomerAMG as preconditioner in PCG
+       if(rk==0) printf("SOLVER: AMG-PCG\n");
+	HYPRE_BoomerAMGCreate(&precond);
+     
+      HYPRE_BoomerAMGSetInterpType(precond, param->amg_interptype);
+    
+       HYPRE_BoomerAMGSetTol(precond, param->amg_tol);
+       HYPRE_BoomerAMGSetCoarsenType(precond, param->amg_coarsentype); 
+       HYPRE_BoomerAMGSetMeasureType(precond,param-> measure_type);
+       HYPRE_BoomerAMGSetStrongThreshold(precond, param->amg_strongthreshold);
+
+       HYPRE_BoomerAMGSetTruncFactor(precond,param->trunc_factor);
+
+       HYPRE_BoomerAMGSetMaxIter(precond, param->amg_maxiter);
+       HYPRE_BoomerAMGSetCycleType(precond,param->cycle_type);
+       
+       HYPRE_BoomerAMGSetSmoothType(precond,param->smooth_type);
+       HYPRE_BoomerAMGSetSmoothNumLevels(precond,param->smooth_num_levels);
+       HYPRE_BoomerAMGSetSmoothNumSweeps(precond,param->smooth_num_sweeps);
+       HYPRE_BoomerAMGSetMaxLevels(precond,param->max_levels);
+       HYPRE_BoomerAMGSetMaxRowSum(precond,param->max_row_sum);
+       
+       HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);
+       
+     
+ 
+       HYPRE_PCGSetPrecond(solver, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup, 
+			     precond);
+
+       break;
+    
+     case 2:
+       if(rk==0) printf("SOLVER: ParaSails-PCG\n");
+         ierr=HYPRE_ParaSailsCreate(comm,&precond);
+       if(ierr) printf("ERROR: ParaSails-PCG\n");
+       HYPRE_ParaSailsSetParams(precond,param->sai_threshold,param->max_levels);
+       HYPRE_ParaSailsSetFilter(precond,param->sai_filter);
+       HYPRE_ParaSailsSetSym(precond,param->sai_sym);
+       HYPRE_PCGSetPrecond(solver, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSolve, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSetup, 
+			   precond);
+       break;
+     case 3:
+       if(rk==0) printf("SOLVER: Schwarz-PCG \n");
+       HYPRE_SchwarzCreate(&precond);
+       HYPRE_SchwarzSetVariant(precond,param->variant);
+       HYPRE_SchwarzSetOverlap(precond,param->overlap);
+       HYPRE_SchwarzSetDomainType(precond,param->domain_type);
+      //HYPRE_SchwarzSetRelaxWeight(precond,param->schwarz_rlx_weight);
+       /*HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);*/
+
+       HYPRE_PCGSetPrecond(solver, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSolve, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSetup, 
+			   precond);
+
+       break;
+
+     default: break;
+	    }
+    
+     break;
+   case 5:
+     if(rk==0) printf("SOLVER: AMG \n");
+     
+     HYPRE_BoomerAMGCreate(&solver);
+     HYPRE_BoomerAMGSetInterpType(solver, param->amg_interptype);
+     HYPRE_BoomerAMGSetNumSamples(solver, param->gsmg_sample);
+     HYPRE_BoomerAMGSetTol(solver, param->amg_tol);
+     HYPRE_BoomerAMGSetCoarsenType(solver, param->amg_coarsentype); 
+     HYPRE_BoomerAMGSetMeasureType(solver,param-> measure_type);
+     HYPRE_BoomerAMGSetStrongThreshold(solver, param->amg_strongthreshold);
+     HYPRE_BoomerAMGSetTruncFactor(solver,param->trunc_factor);
+     HYPRE_BoomerAMGSetMaxIter(solver, param->amg_maxiter);
+     HYPRE_BoomerAMGSetCycleType(solver,param->cycle_type);
+     HYPRE_BoomerAMGSetRelaxWeight(solver,param->relax_weight);
+     HYPRE_BoomerAMGSetOmega(solver,param->omega);
+    
+     HYPRE_BoomerAMGSetSmoothType(solver,param->smooth_type);
+     HYPRE_BoomerAMGSetSmoothNumLevels(solver,param->smooth_num_levels);
+     HYPRE_BoomerAMGSetSmoothNumSweeps(solver,param->smooth_num_sweeps);
+     HYPRE_BoomerAMGSetMaxLevels(solver,param->max_levels);
+     HYPRE_BoomerAMGSetMaxRowSum(solver,param->max_row_sum);
+	
+     HYPRE_BoomerAMGSetVariant(solver, param->variant);
+    // HYPRE_BoomerAMGSetNumFunctions(solver, param->num_functions);
+     //HYPRE_BoomerAMGSetSchwarzRlxWeight(solver,param->schwarz_rlx_weight);
+     HYPRE_BoomerAMGSetOverlap(solver, param->overlap);
+     HYPRE_BoomerAMGSetVariant(solver, param->domain_type);
+     /* if(param->num_functions>1)
+       HYPRE_BoomerAMGSetDofFunc(solver,param->dof_func);*/
+    
+     break;    
+   case 4:
+     if(rk==0) printf("SOLVER: AMG_HYBRID \n");
+    
+     HYPRE_ParCSRHybridCreate(&solver);
+     HYPRE_ParCSRHybridSetTol(solver, param->amg_tol);
+      
+    HYPRE_ParCSRHybridSetCoarsenType(solver,param->coarsen_type);
+     HYPRE_ParCSRHybridSetStrongThreshold(solver, param->strong_threshold);
+     HYPRE_ParCSRHybridSetTruncFactor(solver,param->trunc_factor);
+     HYPRE_ParCSRHybridSetDSCGMaxIter(solver,param->dscg_max_its);
+     HYPRE_ParCSRHybridSetPCGMaxIter(solver,param->pcg_max_its);
+     HYPRE_ParCSRHybridSetConvergenceTol(solver, param->cf_tol);
+     HYPRE_ParCSRHybridSetSolverType(solver, param->solver_type); 
+  
+     HYPRE_ParCSRHybridSetRelaxWeight(solver,param->relax_weight);
+     HYPRE_ParCSRHybridSetOmega(solver,param->omega);
+     HYPRE_ParCSRHybridSetMaxLevels(solver,param->max_levels);
+     HYPRE_ParCSRHybridSetMaxRowSum(solver,param->max_row_sum);
+    
+     break;
+  
+   case 1:/*GMRES AS SOLVER*/
+     HYPRE_ParCSRFlexGMRESCreate (comm, &solver);
+   
+     HYPRE_ParCSRFlexGMRESSetPrintLevel(solver,VERBOSE);
+ 
+     HYPRE_ParCSRFlexGMRESSetKDim(solver,param->solv_kdim);
+     HYPRE_ParCSRFlexGMRESSetMaxIter(solver, param->solv_maxiter );
+     HYPRE_ParCSRFlexGMRESSetTol(solver,param->solv_tol );     
+     HYPRE_FlexGMRESSetLogging(solver, param->solv_log);
+     HYPRE_ParCSRGMRESSetPrintLevel(solver,param->solv_prntlevel);
+     
+ //Set Preconditioner
+     switch (param->precond_id){
+     case 0 : //set BoomerAMG as preconditioner
+       if(rk==0) printf("SOLVER: AMG-GMRES\n");
+       HYPRE_BoomerAMGCreate(&precond);
+       
+       HYPRE_BoomerAMGSetInterpType(precond, param->amg_interptype);
+    
+     //  HYPRE_BoomerAMGSetTol(precond, param->amg_tol);
+       HYPRE_BoomerAMGSetCoarsenType(precond, param->amg_coarsentype); 
+       HYPRE_BoomerAMGSetMeasureType(precond,param-> measure_type);
+       HYPRE_BoomerAMGSetStrongThreshold(precond, param->amg_strongthreshold);
+
+       HYPRE_BoomerAMGSetTruncFactor(precond,param->trunc_factor);
+
+       HYPRE_BoomerAMGSetMaxIter(precond, param->amg_maxiter);
+       HYPRE_BoomerAMGSetCycleType(precond,param->cycle_type);
+       
+       HYPRE_BoomerAMGSetSmoothType(precond,param->smooth_type);
+       HYPRE_BoomerAMGSetSmoothNumLevels(precond,param->smooth_num_levels);
+       HYPRE_BoomerAMGSetSmoothNumSweeps(precond,param->smooth_num_sweeps);
+       HYPRE_BoomerAMGSetMaxLevels(precond,param->max_levels);
+       HYPRE_BoomerAMGSetMaxRowSum(precond,param->max_row_sum);
+       
+       HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);
+      
+       
+
+ 
+       HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_BoomerAMGSolve, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_BoomerAMGSetup, 
+			     precond);
+	
+       break;
+     case 4:
+       /*use diagonal scaling as preconditioner*/
+       if(rk==0) printf("SOLVER: DS-GMRES\n");
+	precond = NULL;
+      HYPRE_ParCSRFlexGMRESSetPrecond (solver, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScale, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScaleSetup, 
+			     precond);
+	
+       break;
+     case 1:
+       /*Use PILUT as preconditioner*/
+       if(rk==0) printf("SOLVER: PILUT-GMRES\n");
+       ierr=HYPRE_ParCSRPilutCreate(comm,&precond);
+    
+       HYPRE_ParCSRPilutSetMaxIter(precond,param->pmax_iter);
+       if(param->drop_tol>=0)
+	 HYPRE_ParCSRPilutSetDropTolerance(precond,param->drop_tol);
+       if(param->nonzeros_to_keep>=0)
+	 HYPRE_ParCSRPilutSetFactorRowSize(precond,param->nonzeros_to_keep);
+       if(ierr) printf("ERROR: PILUT-GMRES \n");
+      HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSolve, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSetup, 
+			     precond);
+       break;
+  
+    case 3:
+       if(rk==0) printf("SOLVER: Schwarz-GMRES \n");
+       HYPRE_SchwarzCreate(&precond);
+       HYPRE_SchwarzSetVariant(precond,param->variant);
+       HYPRE_SchwarzSetOverlap(precond,param->overlap);
+       HYPRE_SchwarzSetDomainType(precond,param->domain_type);
+       //HYPRE_SchwarzSetRelaxWeight(precond,param->schwarz_rlx_weight);
+       /*HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);*/
+
+      HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_SchwarzSolve, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_SchwarzSetup, 
+			   precond);
+
+       break;    
+   case 2:
+       if(rk==0) printf("SOLVER: ParaSails-GMRES\n");
+       ierr=HYPRE_ParaSailsCreate(comm,&precond);
+	
+       if(ierr) printf("ERROR: ParaSails-GMRES\n");
+       HYPRE_ParaSailsSetParams(precond,param->sai_threshold,param->max_levels);
+       HYPRE_ParaSailsSetFilter(precond,param->sai_filter);
+       HYPRE_ParaSailsSetSym(precond,param->sai_sym);
+	
+       HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSolve, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSetup, 
+			   precond);
+	
+       break; 
+     }
+     
+   default:
+	
+     break;
+   }
+	
+
+}
+	
+	void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+	 ffassert ( &x[0] != &b[0]);
+	 epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+	 int i, i1,i2;
+	 int *row,*row1;
+	 double * b_loc,*X_loc,*rhs,*xx;
+	 n=AA.n;
+
+	 rhs= (double *)malloc(sizeof(double)*n);
+	 xx= (double *)malloc(sizeof(double)*n);
+	 x= (double *)malloc(sizeof(double)*n);
+	 i1=ilower;
+	 i2=iupper; 
+	double t2,t1;
+	
+	
+
+	
+	for(i=0;i<n;i++) rhs[i]=b[i];
+
+	if(param->scale)
+	      for(i = 0; i < n; i++) 
+		rhs[i] *= scaletmpr[i];
+   	
+	b_loc=(double *)malloc(n_loc*sizeof(double));
+	X_loc=(double *)malloc(n_loc*sizeof(double));
+	row=(int *)malloc(n_loc*sizeof(int));
+	row1=(int *)malloc(n_loc*sizeof(int));
+	
+	for(i=i1;i <=i2; i++){
+	// node = maptmp[i];
+	b_loc[i-i1]=rhs[i];
+	X_loc[i-i1]=0.0;  //Initial Guest
+	row[i-i1]=i;  //used to get results later
+	row1[i-i1]=i;
+	}
+       int ierr=0;
+	HYPRE_IJVectorCreate(comm, ilower, iupper, &ij_B);
+	HYPRE_IJVectorCreate(comm, ilower, iupper, &ij_X);
+	
+
+	 HYPRE_IJVectorSetObjectType(ij_B, HYPRE_PARCSR);
+	 HYPRE_IJVectorSetObjectType(ij_X, HYPRE_PARCSR);
+	  
+	
+	
+	 HYPRE_IJVectorInitialize(ij_B);
+	 HYPRE_IJVectorInitialize(ij_X);
+	 
+	 HYPRE_IJVectorSetValues(ij_B, n_loc, row, b_loc); 
+	
+   	 HYPRE_IJVectorSetValues(ij_X, n_loc, row, X_loc);
+	  
+	 HYPRE_IJVectorAssemble(ij_B);
+	 HYPRE_IJVectorAssemble(ij_X);
+       
+	 ierr=HYPRE_IJVectorGetObject(ij_B, (void **) &par_B); 
+        
+	 
+   	ierr=HYPRE_IJVectorGetObject(ij_X, (void **) &par_X);
+         
+ 	
+	
+	switch (param->solver_id){
+	case 0 : //BICGSTAB solver
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("BiCGSTAB SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	  HYPRE_ParCSRBiCGSTABSetup (solver, par_A, par_B, par_X);
+	 if(param->timing){
+	      hypre_EndTiming(time_index1);
+	      hypre_PrintTiming("BiCGSTAB SETUP TIME", comm);
+	      hypre_FinalizeTiming(time_index1);
+	      hypre_ClearTiming();}
+
+	   if(param->timing){
+	    time_index1 = hypre_InitializeTiming("ParCSR BICGSTAB Solver");
+	    hypre_BeginTiming(time_index1);}
+
+		  
+	   HYPRE_ParCSRBiCGSTABSolve (solver, par_A, par_B, par_X);
+	   
+	   if(param->timing){
+	      hypre_EndTiming(time_index1);
+	      hypre_PrintTiming("SOLVE PHASE TIMES", comm);
+	      hypre_FinalizeTiming(time_index1);
+	      hypre_ClearTiming();}
+
+
+
+	   HYPRE_ParCSRBiCGSTABGetNumIterations(solver, &num_iter);
+	   HYPRE_ParCSRBiCGSTABGetFinalRelativeResidualNorm(solver, &final_res_norm);
+		
+		  //HYPRE_ParCSRBiCGSTABDestroy(solver);
+                    break;
+	case 1 : //GMRES Solver
+            if(param->timing){
+	   time_index1 = hypre_InitializeTiming("GMRES SETUP");
+	   hypre_BeginTiming(time_index1);
+	   }
+
+	     HYPRE_FlexGMRESSetup(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X);
+	   if(param->timing){
+	   hypre_EndTiming(time_index);
+      	   hypre_PrintTiming("SETUP PHASE TIME", comm);
+           hypre_FinalizeTiming(time_index);
+       	   hypre_ClearTiming();
+	     }
+	  
+	 
+	    if(param->timing){
+	    time_index1 = hypre_InitializeTiming("ParCSR GMRES Solver");
+	    hypre_BeginTiming(time_index1);
+		
+		}
+
+	 HYPRE_FlexGMRESSolve(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X);
+	  if(param->timing){
+	    hypre_EndTiming(time_index1);
+	    hypre_PrintTiming("Solve phase times", comm);
+	    hypre_FinalizeTiming(time_index1);
+	    hypre_ClearTiming();}
+
+	 HYPRE_GMRESGetNumIterations(solver, &num_iter);
+	 HYPRE_GMRESGetFinalRelativeResidualNorm(solver, &final_res_norm);
+		
+		//HYPRE_ParCSRGMRESDestroy(solver);
+                    break;
+	case 2 : //PCG
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("PCG SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	
+	  HYPRE_PCGSetup(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X);
+	   if(param->timing){
+	       hypre_EndTiming(time_index);
+	       hypre_PrintTiming("SETUP PHASE TIME", comm);
+	       hypre_FinalizeTiming(time_index);
+	       hypre_ClearTiming();
+	     }
+	 
+	  if(param->timing){
+	    time_index1 = hypre_InitializeTiming("ParCSR PCG Solve");
+	    hypre_BeginTiming(time_index1);}
+
+	  HYPRE_PCGSolve(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X); 
+
+	  if(param->timing){
+	    hypre_EndTiming(time_index1);
+	    hypre_PrintTiming("Solve phase times", comm);
+	    hypre_FinalizeTiming(time_index1);
+	    hypre_ClearTiming();}
+
+ 	
+	  HYPRE_ParCSRPCGGetNumIterations(solver,&dscg_num_its);
+	  HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver,&final_res_norm);
+
+	  break;
+	case 4:
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("HYBRID SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	  HYPRE_ParCSRHybridSetup(solver,par_A,par_B,par_X);
+	   if(param->timing){
+      	  hypre_EndTiming(time_index);
+       	  hypre_PrintTiming("SETUP PHASE TIME", comm);
+     	  hypre_FinalizeTiming(time_index);
+      	  hypre_ClearTiming();
+  	   }
+
+	   if(param->timing){
+	  time_index1 = hypre_InitializeTiming("ParCSR Hybrid Solve");
+	  hypre_BeginTiming(time_index1);}
+
+	  HYPRE_ParCSRHybridSolve(solver,par_A,par_B,par_X);
+	  if(param->timing){
+	  hypre_EndTiming(time_index1);
+	  hypre_PrintTiming("Solve phase times", comm);
+	  hypre_FinalizeTiming(time_index1);
+	  hypre_ClearTiming();}
+
+	  HYPRE_ParCSRHybridGetNumIterations(solver,&num_iter);
+	  HYPRE_ParCSRHybridGetPCGNumIterations(solver,&pcg_num_its);
+	  HYPRE_ParCSRHybridGetDSCGNumIterations(solver,&dscg_num_its);
+	  HYPRE_ParCSRHybridGetFinalRelativeResidualNorm(solver,&final_res_norm);
+	   if(rk==0){
+		        printf("\n");
+         		printf("Iterations = %d\n", num_iter);
+        		printf("PCG_Iterations = %d\n", pcg_num_its);
+		        printf("DSCG_Iterations = %d\n", dscg_num_its);
+		        printf("Final Relative Residual Norm = %e\n", final_res_norm);
+		        printf("\n");
+		      }
+	  break;
+	case 5:
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("BoomerAMG  SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	  HYPRE_BoomerAMGSetup(solver,par_A, par_B,par_X);
+	  if(param->timing){
+	  time_index1 = hypre_InitializeTiming("BoomerAMG SETUP Solve");
+	  hypre_BeginTiming(time_index1);}
+	  HYPRE_BoomerAMGSolve(solver,par_A,par_B,par_X);
+	  if(param->timing){
+	    hypre_EndTiming(time_index1);
+	    hypre_PrintTiming("Solve phase times", comm);
+	    hypre_FinalizeTiming(time_index1);
+	    hypre_ClearTiming();}
+	  break;
+
+	  
+	default :
+	  break;
+	}
+	
+	   
+	   /*Reconstruction of vector*/
+	  delete [] iwork1; delete []mapptr;
+	  iwork1=new int[size+1]; mapptr=new int[size+1];
+	  int disp=0;
+          for(i=0;i<size;i++){
+          iwork1[i]=n/size; if(i==size-1) iwork1[i]=(n/size)+n%size;
+	   mapptr[i]=disp; disp+=iwork1[i];
+	  }
+	  mapptr[i]=disp;
+
+	    HYPRE_IJVectorGetValues(ij_X, n_loc, row1, X_loc);
+	    MPI_Gatherv(X_loc,n_loc, MPI_DOUBLE, xx,iwork1,mapptr,MPI_DOUBLE,0,comm);
+	    MPI_Bcast(xx,n,MPI_DOUBLE,0, comm);
+	     
+	    for(i=0;i<n;i++) {x[i]=xx[i]; if(param->scale) x[i]=x[i]*scaletmpc[i];}
+
+	    if(verbosity==0) {
+	     MPI_Barrier(comm);
+             t2 = dwalltime();
+	     t2=t2-t1;
+	     MPI_Reduce(&t2, &t1, 1, MPI_DOUBLE, MPI_MAX, 0,comm);
+	     MPI_Bcast(&t1, 1, MPI_DOUBLE,0,comm);
+             
+	     if(rk==0){printf("%s%18.6g%s","TIME FOR SOLVING ", fabs(t1) ,"\n \n");
+		       printf("%s%18.6g%s","RELATIVE RESIDU  ", final_res_norm ,"\n \n");	
+			printf("%s%d%s","NUMBER OF ITERATION ", num_iter ," \n \n");
+		      }
+         }
+
+	   
+
+	    if(X_loc!=NULL) free(X_loc);  if(rhs!=NULL) free(rhs); if(xx!=NULL) free(xx);
+	    if(b_loc!=NULL) free(b_loc);  if(row!=NULL) free(row); 
+	    if(iwork1!=NULL) delete [] iwork1; 
+	    if(mapptr!=NULL) delete [] mapptr;
+            }
+	  ~HypreSolver() { 
+	    	if(verbosity){
+	        cout << "~HypreSolver():" << endl;
+  		HYPRE_IJMatrixDestroy(ij_A);
+		HYPRE_IJVectorDestroy(ij_B);
+		HYPRE_IJVectorDestroy(ij_X);
+		switch (param->solver_id){
+                case 0 : //BICGSTAB solver
+          	  	 HYPRE_ParCSRBiCGSTABDestroy(solver);
+			switch(param->precond_id){
+			case 0:  HYPRE_BoomerAMGDestroy(precond); break;
+			case 5:  HYPRE_ParaSailsDestroy(precond); break;
+			case 6:  HYPRE_SchwarzDestroy(precond); break;
+			case 4:  HYPRE_ParCSRPilutDestroy(precond); break;
+			default:   break;
+			
+			}
+			break;
+
+                case 1 : //GMRES Solver
+			 HYPRE_ParCSRFlexGMRESDestroy(solver);
+			switch(param->precond_id){
+			case 0:  HYPRE_BoomerAMGDestroy(precond); break;
+			case 5:  HYPRE_ParaSailsDestroy(precond); break;
+			case 6:  HYPRE_SchwarzDestroy(precond); break;
+			case 4:  HYPRE_ParCSRPilutDestroy(precond); break;
+			default:  break;
+			
+			}
+			break;
+                   
+                case 3 : //PCG
+			 
+			 HYPRE_ParCSRPCGDestroy(solver);
+			switch(param->precond_id){
+			case 0:  HYPRE_BoomerAMGDestroy(precond); break;
+			case 5:  HYPRE_ParaSailsDestroy(precond); break;
+			case 6:  HYPRE_SchwarzDestroy(precond); break;
+			default:  break;
+			}
+			
+                  break;
+		case 4: //AMG-Hybrid
+			 HYPRE_ParCSRHybridDestroy(solver);  break;
+		case 5: //AMG
+			 HYPRE_BoomerAMGDestroy(solver);  break;
+		  default :  break;
+		}
+			}
+	}
+ void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+};
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildHypreSolver(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+      cout << " BuildSolverHypre>" << endl;
+	
+    return new HypreSolver(*A,ds.data_filename, ds.lparams, ds.dparams,(MPI_Comm *)ds.commworld);
+}
+
+
+/* --FH:   class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; 
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+   
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+        return 1;
+
+ 
+
+}
+
+bool SetHypreSolver()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to Hyprempi" << endl;
+    DefSparseSolver<double>::solver  =BuildHypreSolver;
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+    return 1;
+
+
+}
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  if(verbosity>1)
+    cout << "\n Add: Hyprempi,  defaultsolver defaultsolverHyprempi" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildHypreSolver;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoHyprempi","(",new OneOperator0<bool>(SetHypreSolver));
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-mpi/interfacepastix.cpp b/examples++-mpi/interfacepastix.cpp
new file mode 100644
index 0000000..da1e638
--- /dev/null
+++ b/examples++-mpi/interfacepastix.cpp
@@ -0,0 +1,551 @@
+/*
+  Interface entre freefem++ et pastix
+*/
+//ff-c++-LIBRARY-dep: double_pastix   blas parmetis metis scotch  mpi fc
+//ff-c++-cpp-dep: 
+#include <mpi.h>
+#include  <iostream>
+using namespace std;
+   
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+
+
+// #include <ctype.h>
+// #include <stdio.h>
+// #include <stdlib.h>
+// #include <unistd.h>
+// //#include <pthread.h>
+// #include <string.h>
+// #include <time.h>
+// #include <sys/time.h>
+// #include "mpi.h"
+   
+// #include <assert.h>
+// #include "pastix.h"
+// #include "cscd_utils.h"
+// #include "read_matrix.h"
+
+#include <assert.h>
+extern "C"{
+#include "pastix.h"
+}
+//#include "cscd_utils.h"
+//#include "read_matrix.h"
+
+#undef memFree_null
+#define memFree_null(x) {if (x ==NULL) {fprintf(stdout,"%s:%d freeing NULL\n",__FILE__,__LINE__);} free(x); x=NULL;}
+
+#define STR_SIZE 256
+
+static pastix_int_t * pastixint(int * ii){ return (pastix_int_t*) (void *) ii;} 
+static pastix_float_t * pastixfloat(double * ii){ return (pastix_float_t*) (void *) ii;} 
+
+typedef struct pastix_param {
+  pastix_data_t          *pastix_data; /*Pointer used by PaStiX to keep information alive between calls */
+  MPI_Comm                comm;        /* Communicator used by PaStiX                                    */
+  pastix_int_t            Ncol;        /* Size of the Matrix                                             */
+  pastix_int_t           *ia;          /* Index of first element of each column in ja and avals          */  
+  pastix_int_t           *ja;          /* Rows of the unknows of the matrix                              */
+  pastix_float_t         *avals;       /* Values of the matrix                                           */
+  pastix_int_t           *perm;        /* Permutation used for re-numbering of the unknowns              */
+  pastix_int_t           *invp;        /* Inverse permutation                                            */
+  pastix_float_t         *rhs;         /* Right hand side                                                */
+  pastix_int_t           *iparm;       /* Integer parameters                                             */
+  double                 *dparm;       /* Floating parameters                                            */
+} pastix_param_t;
+
+
+
+void
+Morse_to_CSC(int m, int n, int nnz, 
+	     double *a, int *colind, int  *rowptr,
+	     pastix_float_t **at, pastix_int_t **rowind, 
+	     pastix_int_t **colptr)
+{
+    register int i, j, col, relpos;
+    pastix_int_t *marker;
+
+    /* Allocate storage for another copy of the matrix. */
+    *at     = (pastix_float_t *) malloc(sizeof(pastix_float_t)*nnz);
+    *rowind = (pastix_int_t *) malloc(sizeof(pastix_int_t)*nnz);
+    *colptr = (pastix_int_t *) malloc(sizeof(pastix_int_t)*(n+1));
+    marker  = (pastix_int_t *) malloc(sizeof(pastix_int_t)*n);
+    
+    for (i = 0; i < n; ++i)
+      marker[i] = 0;
+    /* Get counts of each column of A, and set up column pointers */
+    for (i = 0; i < m; ++i)
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) ++marker[colind[j]];
+    (*colptr)[0] = 0;
+    for (j = 0; j < n; ++j) {
+	(*colptr)[j+1] = (*colptr)[j] + marker[j];
+	marker[j] = (*colptr)[j];
+    }
+
+    /* Transfer the matrix into the compressed column storage. */
+    for (i = 0; i < m; ++i) {
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) {
+	    col = colind[j];
+	    relpos = marker[col];
+	    (*rowind)[relpos] = i;
+	    (*at)[relpos] = a[j];
+	    ++marker[col];
+	}
+    }
+
+    free(marker);
+}
+
+static const int MAX_CHAR_PER_LINE=256;
+void read_datafile_pastixff(const string &datafile, pastix_int_t *iparmtab, double *dparmtab){
+ 
+  FILE*   m_File;
+  int     i = 0;
+  char    szbuff[MAX_CHAR_PER_LINE];
+  char*   token;
+
+  char filename[datafile.size()+1];  
+  strcpy( filename, datafile.c_str()); 
+
+  m_File = fopen(filename,"rt");
+
+  if(!m_File)
+    {
+      printf("error in reading filename %s\n",&filename);
+    }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+  
+  if( !(strcmp(token,"iparm") == 0) ){
+    printf("freefem++: error in reading iparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading iparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      iparmtab[i] = (pastix_int_t)atol(token);
+      i++;
+    }
+
+  i=0;
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");  
+  if( !(strcmp(token,"dparm") == 0) ){
+    printf("freefem++: error in reading dparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading dparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      dparmtab[i] = atof(token);
+      i++;
+    }
+ 
+  fclose(m_File);
+
+#ifdef OOC
+/*   if (iparmtab[IPARM_OOC_THREAD] > 1) */
+    iparmtab[IPARM_OOC_THREAD] = 1;
+#endif
+  /* On empeche le 2d avec NUMA_ALLOC */
+#ifdef NUMA_ALLOC
+  if (iparmtab[IPARM_DISTRIBUTION_LEVEL] != 0)
+    {
+      errorPrint("2D not available with NUMA allocation\n");
+      exit(-1);
+    }
+#endif
+}
+
+// ATTENTION :: pastix_float_t  
+//      peut �tre soit un complex ou un reel cela depend de la maniere dont on a compiler pastix
+
+// CAS DOUBLE SEULEMENT 
+
+
+class dSolvepastixmpi :   public MatriceMorse<double>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  
+
+  int paraoption;
+  int myid, mpi_size;
+  int Nrow;
+  int mpi_flag;
+  int init_raff;
+  int thrd_flag;
+  int SYM;
+  
+  string data_option;
+  
+  mutable pastix_int_t    iparm[64];
+  mutable double          dparm[64];
+  mutable pastix_int_t    Ncol;
+  mutable pastix_int_t   *ia;
+  mutable pastix_int_t   *ja;
+  mutable pastix_float_t *avals;
+  mutable pastix_int_t   *loc2glob;
+  //char           *Type    = NULL;
+  //char           *RhsType = NULL;
+  mutable pastix_float_t *rhs;
+  mutable pastix_int_t   *perm;
+  mutable pastix_int_t   *invp;
+  mutable pastix_data_t  *pastix_data;
+  
+
+public:
+
+  dSolvepastixmpi(const MatriceMorse<double> &AA, string datafile, KN<long> &param_int, KN<double> &param_double, 
+		  KN<long> &pperm_r, KN<long> &pperm_c) : 
+    data_option(datafile) 
+  { 
+    //int m;
+    //int ierr;
+    struct timeval  tv1, tv2;
+   
+    ia    = NULL;
+    ja    = NULL;
+    avals   = NULL;
+    loc2glob = NULL;
+    rhs     = NULL;
+    pastix_data = NULL;
+    
+    // matrix assembled on host
+    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
+    printf("- Rang MPI : %d\n", myid);
+    MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
+    // SYMETRIQUE
+    mpi_flag  = 0;
+    thrd_flag = 0;
+        
+    Ncol = AA.m;
+    Nrow = AA.n;
+  
+    // Avant : on ecrit la transpos�e
+    /*
+      ia = (pastix_int_t *) malloc( (Ncol+1)*sizeof(pastix_int_t));
+      for(int ii=0; ii < Ncol+1; ii++){
+      ia[ii] = AA.lg[ii]+1;
+      }
+      assert( ia[Ncol]-1 == AA.nbcoef );
+      
+      ja = (pastix_int_t *) malloc((ia[Ncol]-1)*sizeof(pastix_int_t));
+      for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = AA.cl[ii]+1;
+      
+      
+      if( sizeof(pastix_float_t) == sizeof(double) ){
+      avals = (pastix_float_t *) malloc( (ia[Ncol]-1)*sizeof(pastix_float_t));
+      for(int ii=0; ii < ia[Ncol]-1; ii++)
+      avals[ii] = AA.a[ii];
+      }
+    */    
+    // AA.cl : indices des colonnes
+    // AA.lg : pointeurs des lignes
+    Morse_to_CSC( AA.n , AA.m, AA.nbcoef, AA.a, AA.cl, AA.lg, &avals, &ja, &ia);
+    // ia : pointeurs des colonnes
+    // ja : indices des lignes
+    
+    cout << "AA.n= "<< AA.n << " AA.m=" <<  AA.m << " AA.nbcoef=" << AA.nbcoef << endl;
+    
+    for(int ii=0; ii < Ncol+1; ii++){
+      ia[ii] = ia[ii]+1;
+    }
+    assert( ia[Ncol]-1 == AA.nbcoef );
+    for(int ii=0; ii < ia[Ncol]-1; ii++){
+      ja[ii] = ja[ii]+1; 
+    }
+       
+    perm = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    invp = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    
+    rhs = (pastix_float_t *) malloc(Ncol*sizeof(pastix_float_t));
+    
+    // reading permutation given by the user
+    if(pperm_r) 
+      for(int ii=0; ii < Ncol; ii++)
+	perm[ii] = pperm_r[ii];
+    if(pperm_c)  
+      for(int ii=0; ii < Ncol; ii++)
+	invp[ii] = pperm_c[ii];
+   
+
+    // CAS DE LA  MATRICE NON DISTRIBUER
+    pastix_int_t init_raff;
+    fprintf(stdout,"-- INIT PARAMETERS --\n");
+    
+    
+
+    // reading iparm from array    
+    if(!data_option.empty()) read_datafile_pastixff(data_option,iparm,dparm);
+    else if(param_int || param_double){
+      if( param_int ) 
+      {
+	cout << "read param_int" << endl;
+	assert(param_int.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  iparm[ii] = param_int[ii];
+	iparm[IPARM_MODIFY_PARAMETER] = API_YES;
+      }
+      if( param_double ) 
+      {
+	cout << "read param_double" << endl;
+	assert(param_double.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  dparm[ii] = param_double[ii];
+      }
+    }  
+    else{
+      iparm[IPARM_MODIFY_PARAMETER] = API_NO;
+      cout << "initialize parameter" << endl;
+    }
+  
+    iparm[IPARM_START_TASK] = API_TASK_INIT;
+    iparm[IPARM_END_TASK]   = API_TASK_INIT;
+    iparm[IPARM_SYM] = API_SYM_NO; // Matrix is considered nonsymetric
+    
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm); 
+    fprintf(stdout,"-- FIN INIT PARAMETERS --\n");
+    init_raff = iparm[IPARM_ITERMAX];
+    
+    fflush(stdout);
+    /* Passage en mode verbose */
+    
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    if( !param_int && data_option.empty() ){
+      iparm[IPARM_MATRIX_VERIFICATION] = API_YES;
+      iparm[IPARM_REFINEMENT] = API_RAF_GMRES;
+      iparm[IPARM_INCOMPLETE] = API_NO;
+    }
+
+    if( !param_double && data_option.empty()){
+      dparm[DPARM_EPSILON_REFINEMENT] = 1e-12;
+      dparm[DPARM_EPSILON_MAGN_CTRL] = 1e-32;
+    }
+
+    SYM = AA.symetrique; 
+    cout << "SYM = "<< SYM << endl;
+    // SYMETRIQUE
+    if( SYM == 1 ){
+      iparm[IPARM_SYM] = API_SYM_YES;
+      //iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      iparm[IPARM_SYM] = API_SYM_NO;
+      //iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    
+    /* Scotch */
+    fprintf(stdout,"-- Scotch --\n");
+    fflush(stdout);
+    iparm[IPARM_START_TASK] = API_TASK_ORDERING;
+    iparm[IPARM_END_TASK]   = API_TASK_ORDERING; 
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    
+    /* Fax */
+    fprintf(stdout,"-- Fax --\n");
+    iparm[IPARM_START_TASK] = API_TASK_SYMBFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_SYMBFACT;
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    
+    /* Blend */
+    fprintf(stdout,"-- Blend --\n");
+    iparm[IPARM_START_TASK] = API_TASK_ANALYSE;
+    iparm[IPARM_END_TASK]   = API_TASK_ANALYSE;
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    
+    if( SYM == 1 ){
+      //iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      //iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+
+    /* Factorisation */
+    iparm[IPARM_START_TASK] = API_TASK_NUMFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_NUMFACT;
+    gettimeofday(&tv1, NULL);
+    fprintf(stdout,"-- SOPALIN --\n");
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call factorization : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+    
+  
+    
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+  }
+  void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+  
+    struct timeval  tv1, tv2;
+     // index for pastix
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]+1;
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]+1;
+
+    // give value of the second member
+    for(int ii=0; ii < Ncol; ii++)
+      rhs[ii] = b[ii];
+    
+    //fprintf(stdout,"SOLVE STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    
+    /* updo */
+    iparm[IPARM_START_TASK] = API_TASK_SOLVE;
+    iparm[IPARM_END_TASK]   = API_TASK_SOLVE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    gettimeofday(&tv1, NULL);
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call updown : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));    
+    
+    //for(int jj=0; jj < Ncol; jj++)
+    //  cout << "rhs["<< jj << "]=" << rhs[jj] << endl;
+    
+    
+    //fprintf(stdout,"RAFF STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    /* raff */
+
+    
+    iparm[IPARM_START_TASK] = API_TASK_REFINE;
+    iparm[IPARM_END_TASK]   = API_TASK_REFINE;
+    //iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    iparm[IPARM_ITERMAX]    = init_raff;
+    gettimeofday(&tv1, NULL);
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call refinement : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+    
+    for(int ii=0; ii < Ncol; ii++)
+      x[ii] = rhs[ii];
+   
+    // index for freefem
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    
+  }
+
+  ~dSolvepastixmpi(){
+    /* mem free */
+    iparm[IPARM_START_TASK] = API_TASK_CLEAN;
+    iparm[IPARM_END_TASK]   = API_TASK_CLEAN;
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    
+    if( sizeof(pastix_int_t) != sizeof(int) )
+      {
+	memFree_null(ia);
+	memFree_null(ja);
+      }
+    /* Free mem no longer necessary */
+    memFree_null(rhs);
+   
+  }
+  
+  void addMatMul(const KN_<double> & x, KN_<double> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<double> &) (*this) * x; 
+  }
+
+};
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverpastixmpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverpastixmpi<double>" << endl;
+    return new dSolvepastixmpi(*A,ds.data_filename, 
+			       ds.lparams, ds.dparams, ds.perm_r, ds.perm_c);
+}
+
+
+/* --FH:   class Init { public:
+    Init();
+    };*/ 
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+    return false;
+}
+
+bool Setpastixmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to pastixmpi" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverpastixmpi;
+    //DefSparseSolver<Complex>::solver =BuildSolverpastixmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+    return false;
+}
+
+
+
+
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: pastixmpi,  defaultsolver defaultsolverpastixmpi" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverpastixmpi;
+  //DefSparseSolver<Complex>::solver =BuildSolverpastixmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttopastixmpi","(",new OneOperator0<bool>(Setpastixmpi));
+}
+
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/mortar-DN-4-mpi.edp b/examples++-mpi/mortar-DN-4-mpi.edp
new file mode 100644
index 0000000..3a99cd3
--- /dev/null
+++ b/examples++-mpi/mortar-DN-4-mpi.edp
@@ -0,0 +1,230 @@
+assert(version>=2.23);
+if ( mpisize != 4 ) 
+  {
+    cout << " sorry number of processeur !=4 " << endl;
+    exit(1);
+  }
+
+//  Mortar  (4 sub domain) 
+//  with matrix -et Precon Conjugade Gradient --
+//    Neuman -> Dirichlet . 
+//  -------------------------------
+
+func f=1+x+y;
+real g=1; 
+int withprecon=1; 
+macro Grad(u) [ dx(u), dy(u) ] //
+int nbsd=4;
+
+macro Psd(U) U[0],U[1],U[2],U[3] //
+
+int labext= nbsd+1;
+real meshsize=0.03; 
+real meshsizem=meshsize*1.5; 
+bool noconforme=0;
+
+mesh Tha,Thm,Thmm;
+int [int] regsd(4);	
+
+
+if(mpirank==0)
+  {
+    
+    mesh Thacopy; //hack to dcl Tha ouside of mortar-msh.idp
+    {  
+      include "mortar-msh.idp"  
+	Thacopy=Tha;
+      regsd=regi;
+    }   
+    Tha=Thacopy;
+    cout << "mortar : " << endl;
+    Thm=Tha;
+    Thm=adaptmesh(Thm,meshsizem,IsMetric=1,thetamax=60);
+    Thm=emptymesh(Thm);       Thmm=Thm;
+    Thmm=trunc(Thm,split=4,1); // for fine integration
+    Thmm=emptymesh(Thmm);
+    plot(Thm,wait=0,ps="mortar-Thm.eps");
+  }
+
+// send meshes 
+verbosity=1;
+broadcast(processor(0),Tha);
+broadcast(processor(0),Thm);
+broadcast(processor(0),Thmm);
+broadcast(processor(0),regsd);
+
+// build sub domaine mesh :
+mesh Thi=trunc(Tha,region==regsd[mpirank],split=1);// les sous domaines
+
+if(noconforme)
+ Thi=adaptmesh(Thi,meshsize*(1+0.1*mpirank),IsMetric=1,nbvx=100000,thetamax=60);// les sous domaines
+
+
+fespace Lh(Thm,P1);
+fespace RTh(Thm,[P0edge,P0edge]);
+ RTh [Nmx,Nmy]; // ne marche pas car la normal 
+//                             n'est definie que une un bord
+varf  vNN([ux,uy],[nx,ny]) = int1d(Thm,1)(( nx*N.x + ny*N.y)/lenEdge);
+Nmx[]= vNN(0,RTh);
+
+// les joint P0 sur le squelette 
+// -----   \int [q] l + \int[p] m 
+Lh  lh=0,rhsl=0;
+
+fespace Vhi(Thi,P1);
+fespace Ehi(Thi,P0edge);
+matrix Asd,Csd,PAsd,PIsd,PJsd;
+Vhi usd,vsd,rhssd, pusd,bcsd;
+Ehi epssd;
+   
+real tgv=1e30;
+
+
+
+varf cci([l],[u]) = int1d(Thmm,1,qforder=3)(l*u*epssd);
+varf vepsi(u,v)= int1d(Thi,1,qforder=10)( (Nmx*N.x + Nmy*N.y)*v/lenEdge);
+
+varf vLapMi([ui],[vi],tgv=tgv) =
+			   int2d(Thi)(  Grad(ui)'*Grad(vi)  )
+			   // + int1d(Thi,1,qfe=qf1pElump)(alpha*ui*vi)
+			   +  int2d(Thi) (f*vi)   +  on(labext,ui=g);  
+
+varf vPLapMi([ui],[vi],tgv=tgv) =
+			   int2d(Thi)(  Grad(ui)'*Grad(vi)  )
+			   // + int1d(Thi,1,qfe=qf1pElump)(alphap*ui*vi)
+			   + on(labext,1,ui=0);
+;  
+
+varf  vrhsMi(ui,vi) =   on(labext,ui=g);
+
+
+usd=0;
+vsd=0;
+epssd[]= vepsi(0,Ehi);
+epssd = -real(epssd <-0.00001) + real(epssd >0.00001);
+
+Csd  = cci(Lh,Vhi);
+Asd  = vLapMi(Vhi,Vhi,solver=UMFPACK);
+PAsd = vPLapMi(Vhi,Vhi,solver=UMFPACK);
+matrix IVL=interpolate(Vhi,Lh,inside=1);
+//   v = IVL*l 
+varf vonext(u,v)=on(labext,u=1);
+varf von1(u,v)=on(1,u=1);
+real[int]  onext=vonext(0,Vhi);
+real[int]  on1=von1(0,Vhi);
+on1= on1 ? 1 : 0;
+on1 = onext ? 0 : on1; //  remove df of ext
+matrix I1(on1);//   matrix    tgv $i\in Gamma_1 \ Gamma_e $ , 0 otherwise
+PIsd=  I1*IVL;//  remove of line not on $Gamma_1 \ Gamma_e $
+// so PIsd*l  =  tgv * Interpole l on $Gamma_1 \ Gamma_e $
+I1.diag=on1;
+matrix AA=I1*Asd;//  remove line not on lab 1 
+PJsd= IVL'*AA;
+rhssd[]=vLapMi(0,Vhi);
+
+varf  vML(u,v) = int2d(Thm)(u*v*1e-10)+int1d(Thm,1)(u*v);
+matrix ML=vML(Lh,Lh);
+
+
+lh[]=0;
+int itera=0;
+
+varf  vbc(u,v) =   int1d(Thm,labext)(v);
+real[int] lbc(Lh.ndof),lbc0(Lh.ndof);
+lbc=vbc(0,Lh);
+lbc = lbc ? 0 : 1 ; 
+
+int what; //  to choose which  funct call 1  SkPb 2:PSkPb, 3:end
+// the preconditionner 
+func real[int] PSkPb(real[int] &l)
+{ 
+  if(withprecon)
+    {	
+      if(mpirank==0)  
+	{ 
+	  what=2;
+	  broadcast(processor(0),what); // get from SkBk routine
+	} 
+      if(what!=2) return l;   	
+      
+      int verb=verbosity;   verbosity=0;   itera++;
+      real[int] ll= ML^-1*l;
+      broadcast(processor(0),ll);     
+      ll= lbc .* ll; 
+      ll *= tgv;
+      pusd[] = PAsd^-1*(vsd[]= PIsd* ll);
+      ll  = PJsd*pusd[];  
+      if(mpirank==0)
+	{
+	  for (int i=1;i<4;++i)
+	    {
+	      processor(i) >> l;
+	      ll += l; 
+	    }
+	  l = ML^-1*ll; 	
+	  l= lbc .* l; 
+	}
+      else 
+	processor(0) << ll;        
+      verbosity=verb; 
+    }
+  return l ;
+};
+
+func real[int] SkPb(real[int] &l)
+{ 
+  int verb=verbosity;   verbosity=0;   itera++;
+  if(mpirank==0 && what!=3) what=1;
+  broadcast(processor(0),what);  
+  if(what==2) return PSkPb(l); 
+  else if (what !=1) return l;
+  broadcast(processor(0),l);   	
+  
+  vsd[]  = rhssd[];
+  vsd[] += Csd* l;
+  usd[]  = Asd^-1*vsd[];      
+  l  = Csd'*usd[]; 	
+  l= lbc .* l;
+
+  if(mpirank==0)
+   {
+    real[int] ll(l.n);
+    for (int i=1;i<4;++i)
+      {
+        processor(i) >> ll;
+        l += ll; 
+      }
+    }
+  else 
+    processor(0) << l;
+  verbosity=verb; 
+  return l ;
+};
+
+
+
+
+
+if(mpirank==0)
+  {
+    verbosity=100;
+    lh[]=0;
+     LinearCG(SkPb,lh[],eps=1.e-5,nbiter=100,precon=PSkPb);
+    what=3;
+    SkPb(lh[]);
+  }
+ else
+   while(what!=3)
+     SkPb(lh[]);
+
+plot(usd,bb=[[-1,-1],[1,1]],ps="mortar-"+mpirank+".eps");
+cout << "Fin CG  " << mpirank <<  endl;
+
+/*
+Brochet:examples++-mpi hecht$ (grep -vh showpage  mortar-?.eps;echo showpage) > mortar.eps
+Brochet:examples++-mpi hecht$ gv mortar.eps 
+*/
+
+
+
+
diff --git a/examples++-mpi/mortar-msh.idp b/examples++-mpi/mortar-msh.idp
new file mode 100644
index 0000000..8572f93
--- /dev/null
+++ b/examples++-mpi/mortar-msh.idp
@@ -0,0 +1,42 @@
+// --- begin  meshes  building --------------
+real[int] theta(nbsd+1),cost(nbsd),sint(nbsd);
+
+for (int i=0;i<nbsd;i++)
+ {
+  real t=i*2*pi/nbsd;
+  theta[i]= t;
+  theta[i+1]= (i+1)*2*pi/nbsd;
+  cost[i]=cos(t);
+  sint[i]=sin(t);
+ }
+
+
+border g1(t=0,1){x=cost[0]*t;y=sint[0]*t;label=1;};
+border g2(t=0,1){x=cost[1]*t;y=sint[1]*t;label=1;};
+border g3(t=0,1){x=cost[2]*t;y=sint[2]*t;label=1;};
+border g4(t=0,1){x=cost[3]*t;y=sint[3]*t;label=1;};
+
+border e12(t=theta[0],theta[1]){x=cos(t);y=sin(t);label=labext;};
+border e23(t=theta[1],theta[2]){x=cos(t);y=sin(t);label=labext;};
+border e34(t=theta[2],theta[3]){x=cos(t);y=sin(t);label=labext;};
+border e41(t=theta[3],theta[4]){x=cos(t);y=sin(t);label=labext;};
+
+ int Ng = 5;
+ int Ne = 5 ;
+
+plot(g1(Ng)+g2(Ng)+g3(Ng)+g4(Ng) + e12(Ne) + e23(Ne)+ e34(Ne) + e41(Ne) ,wait=1);
+
+mesh Tha = buildmesh( g1(Ng)+g2(Ng)+g3(Ng)+g4(Ng) + e12(Ne) + e23(Ne)+ e34(Ne) + e41(Ne) );
+
+int [int] regi(4);
+for (int i=0;i<4;i++)
+  {
+    real tt = (theta[i]+theta[i+1])*0.5;
+    regi[i]=Tha(0.5*cos(tt),0.5*sin(tt)).region;
+  }
+
+
+Tha=adaptmesh(Tha,meshsize*3,IsMetric=1,thetamax=60,nbvx=100000);
+Tha=adaptmesh(Tha,meshsize*1.5,IsMetric=1,thetamax=60,nbvx=100000);
+Tha=adaptmesh(Tha,meshsize,IsMetric=1,thetamax=60,nbvx=100000);
+
diff --git a/examples++-mpi/mpi-cmaes.cpp b/examples++-mpi/mpi-cmaes.cpp
new file mode 100644
index 0000000..8ceb0f0
--- /dev/null
+++ b/examples++-mpi/mpi-cmaes.cpp
@@ -0,0 +1,392 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Sylvain Auliac
+// E-MAIL   : auliac at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//ff-c++-LIBRARY-dep: mpi 
+//ff-c++-cpp-dep: ../examples++-load/cmaes.cpp -I../examples++-load
+
+/* 
+	This is a freefem interface of the Hansen's CMA-ES C optimizer.
+	The class CMAES is a quick C++ interface for the contents of the C files
+	then follow the real FreeFem++ stuff.
+*/
+
+
+#include  <iostream>
+using namespace std;
+#include "ff++.hpp"
+#include "mpi.h"
+#include "cmaes_interface.h"
+
+
+
+template<class T> struct MPI_TYPE {};
+template<> struct MPI_TYPE<long>      {static const MPI_Datatype  TYPE(){return MPI_LONG;}};
+template<> struct MPI_TYPE<int>      {static const MPI_Datatype TYPE(){return MPI_INT;}};
+template<> struct MPI_TYPE<double>    {static const MPI_Datatype TYPE(){return MPI_DOUBLE;}};
+template<> struct MPI_TYPE<char>    {static const MPI_Datatype TYPE(){return MPI_BYTE;}};
+
+
+class CMAES //Abstract class, because the fitness function prototype may differ from users to users
+{
+	public:
+		//typedef double (*FFT)(double const *); //Fitness Function Type
+		CMAES() : pop(0),fitvals(0),evo() {}
+		CMAES(int d,double *xstart,double *stddev,long seed,int lambda,const char *ipf="initials.par") : pop(0),fitvals(0),evo()
+		{
+			fitvals = init(d,xstart,stddev,seed,lambda,ipf);
+			cout << SayHello() << endl;
+		}
+		virtual ~CMAES() {exit();}
+		
+		void resume_distribution(char *filename) {return cmaes_resume_distribution(&evo, filename);}
+		double * const * & SamplePopulation() {return pop = cmaes_SamplePopulation(&evo);}
+		double * UpdateDistribution() {return cmaes_UpdateDistribution(&evo,fitvals);}
+		const char * TestForTermination() const {return cmaes_TestForTermination(&evo);}
+		double * const * & ReSampleSingle(int index) {return pop = cmaes_ReSampleSingle(&evo,index);}
+		double const * ReSampleSingle_old(double *rgx) {return cmaes_ReSampleSingle_old(&evo,rgx);}
+		void UpdateEigensystem(int flgforce) {return cmaes_UpdateEigensystem(&evo, flgforce);}
+		virtual void PopEval() =0;
+		//{for(int i=0;i<popsize();++i) fitvals[i] = ff(pop[i]);} //the thing to parralelize
+		
+		double axisratio() const {return cmaes_Get(&evo,"axisratio");}	//between lengths of longest and shortest principal axis of the distribution ellipsoid 
+		int eval() const {return floor(cmaes_Get(&evo,"eval"));}				//number of function evaluations
+		double fitness() const {return cmaes_Get(&evo,"fitness");}			//recent best function evaluation
+		double fbestever() const {return cmaes_Get(&evo,"fbestever");}  //ever best function value
+		int generation() const {return floor(cmaes_Get(&evo,"generation"));}
+		int maxeval() const {return floor(cmaes_Get(&evo,"maxeval"));}	//maximal number of function evaluations
+		int maxgen() const {return floor(cmaes_Get(&evo,"maxgen"));}		//maximal number of generations
+		double maxaxislength() const {return cmaes_Get(&evo,"maxaxislength");}
+		double minaxislength() const {return cmaes_Get(&evo,"minaxislength");}
+		double maxstddev() const {return cmaes_Get(&evo,"maxstddev");}
+		double minstddev() const {return cmaes_Get(&evo,"minstddev");}
+		int dimension() const {return floor(cmaes_Get(&evo,"dimension"));}
+		int popsize() const {return floor(cmaes_Get(&evo,"lambda"));}
+		double sigma() const {return cmaes_Get(&evo,"sigma");}
+		double * diagC() const {return const_cast<double*>(cmaes_GetPtr(&evo,"diag(C)"));}
+		double * diagD() const {return const_cast<double*>(cmaes_GetPtr(&evo,"diag(D)"));}
+		double * stddev() const {return const_cast<double*>(cmaes_GetPtr(&evo,"stddev"));}
+		double * xbestever() const {return const_cast<double*>(cmaes_GetPtr(&evo,"xbestever"));}
+		double * xbest() const {return const_cast<double*>(cmaes_GetPtr(&evo,"xbest"));}
+		double * xmean() const {return const_cast<double*>(cmaes_GetPtr(&evo,"xmean"));}
+		
+		void ReadSignals(char const * filename) const {cmaes_ReadSignals(&evo,filename);}
+		char * SayHello() const {return cmaes_SayHello(&evo);}
+		void WriteToFile(char const * keyword,char const * output_filename) const {cmaes_WriteToFile(&evo,keyword,output_filename);}
+		
+		virtual double * operator() () 
+		{
+			//ReadSignals("signals.par");
+			while(!TestForTermination())
+			{
+				SamplePopulation();
+				PopEval();
+				UpdateDistribution();
+				//ReadSignals("signals.par");
+			}
+			cout << "Stop : " << TestForTermination() << endl;
+			return xmean();
+		}
+		cmaes_t& optimizer() {return evo;}
+	protected:
+		double * const * pop;
+		double * fitvals;
+		double*& init(int dimension,double *xstart,double *stddev,long seed,int lambda,const char *input_parameter_filename)
+			{return fitvals = cmaes_init(&evo,dimension,xstart,stddev,seed,lambda,input_parameter_filename);}
+	private:
+		void exit() {cmaes_exit(&evo);}
+		mutable cmaes_t evo;
+};
+
+
+
+
+/*
+	Now comes the FreeFem ++ part :
+*/
+
+extern Block *currentblock;
+
+typedef double R;
+
+class OptimCMA_ES : public OneOperator 
+{
+	public:
+		typedef KN<R> Kn;
+		typedef KN_<R> Kn_;
+		const int cas;
+
+
+		class ffcalfunc  //   to call the freefem function .. J 
+		{ 
+			public:
+				Stack stack;
+				Expression JJ,theparame;
+				mutable int counter;
+    
+				ffcalfunc(Stack s,Expression JJJ,Expression epar) : stack(s),JJ(JJJ), theparame(epar), counter(0) {}
+				double J(Kn_  x) const 
+				{
+					++counter;
+					KN<double> *p=GetAny<KN<double> *>( (*theparame)(stack) );
+					*p=x;
+					double ret= GetAny<R>( (*JJ)(stack));
+					WhereStackOfPtr2Free(stack)->clean();
+					return  ret; 
+				}
+		}; 
+		
+		
+		class CMA_ES_MPI : public CMAES
+		{
+			public:
+				typedef KN<double> Rn;
+				typedef KN_<double> Rn_;
+		
+		
+				//CMA_ES_MPI() : CMAES(),x(0),fit(0) {}
+				/*CMA_ES(ffcalfunc &_ff,int d,Rn &xstart,double *stddev,long seed,int lambda)
+					: CMAES(d,xstart.n ? xstart:0,stddev,seed,lambda,"non"),x(&xstart),fit(&_ff) {}
+				CMA_ES(ffcalfunc &_ff,int d,Rn &xstart,const Rn &stddev,long seed,int lambda) 
+					: CMAES(d,xstart.n ? xstart:0,stddev,seed,lambda,"non"),x(&xstart),fit(&_ff) {}*/
+					
+				CMA_ES_MPI(ffcalfunc &_ff,Rn &xstart,const Rn &stddev,long seed,int lambda,MPI_Comm *_com)
+					: CMAES(),x(0),fit(&_ff),com(_com),myid(0),nproc(1),my_number_of_fitness_eval(0),index(0)
+				{
+					MPI_Comm_size(*com,&nproc);
+					MPI_Comm_rank(*com,&myid);
+					x = &xstart;
+					init(x->n,xstart.n ? xstart:0,stddev,seed,lambda,"non");
+					my_number_of_fitness_eval = (lambda/nproc) + (myid < (lambda%nproc) ? 1:0);
+					index = new int[nproc];
+					for(int i=0;i<nproc;++i) 
+					{
+						int inofe = lambda/nproc + ((i-1)<(lambda%nproc) ? 1:0);
+						index[i] = i>0 ? index[i-1]+inofe : 0;
+					}	
+					if(myid==0) cout << SayHello() << endl;
+				}
+				CMA_ES_MPI(ffcalfunc &_ff,Rn &xstart,const Rn &stddev,long seed,int lambda,MPI_Comm *_com,const char *ifname)
+					: CMAES(),x(0),fit(&_ff),com(_com),myid(0),nproc(1),my_number_of_fitness_eval(0),index(0)
+				{
+					MPI_Comm_size(*com,&nproc);
+					MPI_Comm_rank(*com,&myid);
+					x = &xstart;
+					init(x->n,xstart.n ? xstart:0,stddev,seed,lambda,ifname);
+					my_number_of_fitness_eval = (lambda/nproc) + (myid < (lambda%nproc) ? 1:0);
+					index = new int[nproc];
+					for(int i=0;i<nproc;++i) 
+					{
+						int inofe = lambda/nproc + ((i-1)<(lambda%nproc) ? 1:0);
+						index[i] = i>0 ? index[i-1]+inofe : 0;
+					}	
+					if(myid==0) cout << SayHello() << endl;
+				}
+				~CMA_ES_MPI()
+				{
+					if(index) delete [] index;
+					index=0;
+				}
+		
+				void PopEval() 
+				{
+					//cout << endl << "***** in popeval myid = " << myid << "*****" << endl;
+					for(int i=0;i<my_number_of_fitness_eval;++i) 
+					{
+						Rn_ popi(pop[i+index[myid]],dimension()); 
+						fitvals[i+index[myid]] = fit->J(popi);
+					}
+				}
+				double * operator() () 
+				{
+					while(!TestForTermination())
+					{
+						MPI_Barrier(*com);
+						SamplePopulation();//Every proc samples its own population... but only the one from proc 0 is used. Fortunately, this is a quick computation regarding the time spent on fitness function evaluation
+						for(int i=0;i<popsize();++i) MPI_Bcast(pop[i],dimension(),MPI_DOUBLE,0,*com); //send the population to every proc
+						PopEval(); //each proc do its work gently
+						for(int i=0;i<nproc;++i) 
+						{
+							int nn = i<nproc-1 ? index[i+1] - index[i] : popsize()/nproc;
+							MPI_Bcast(&fitvals[index[i]],nn,MPI_DOUBLE,i,*com);
+						}
+						UpdateDistribution();//There again, only proc 0 would really need to update its distribution
+					}
+					if(myid==0) cout << "Stop : " << TestForTermination() << endl;
+					return xmean();
+				}
+			private:
+				CMA_ES_MPI(const CMA_ES_MPI &);
+				CMA_ES_MPI& operator=(const CMA_ES_MPI &);
+				ffcalfunc *fit;
+				Rn *x;
+				MPI_Comm *com;
+				int nproc,myid,my_number_of_fitness_eval;
+				int * index;
+		};
+
+  
+
+		class E_CMA_ES: public E_F0mps 
+		{ 
+			public:
+				const int cas;
+				static basicAC_F0::name_and_type name_param[] ;
+				static const int n_name_param =12;
+				Expression nargs[n_name_param];
+				Expression X;
+				C_F0 inittheparam,theparam,closetheparam; 
+				Expression JJ;
+				long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+				R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+      
+				E_CMA_ES(const basicAC_F0 & args,int cc) : cas(cc)
+				{
+					int nbj= args.size()-1;
+					Block::open(currentblock); // make a new block to 
+					X = to<Kn*>(args[nbj]);
+					C_F0 X_n(args[nbj],"n");
+					//  the expression to init the theparam of all 
+					inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+					theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+					args.SetNameParam(n_name_param,name_param,nargs);
+					const  Polymorphic * opJ=0;
+					if (nbj>0)
+					{
+						opJ=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+						assert(opJ);
+					}      
+					JJ= to<R>(C_F0(opJ,"(",theparam));
+					closetheparam=currentblock->close(currentblock);   // the cleanning block expression 
+				}
+    
+				virtual AnyType operator()(Stack stack)  const
+				{
+					double cost = 1e100;
+					WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005 
+					Kn &x = *GetAny<Kn *>((*X)(stack));	
+					long n=x.N();	
+					long seed =	arg(0,stack,0L); //The seed for random numbers generation
+					double initialStdDev = arg(1,stack,0.3); //Initial standard deviation
+					KN<double> iSD(n,1.);
+					iSD *= initialStdDev;
+					KN<double> initialStdDevs(nargs[2] ? GetAny<KN_<double> >((*nargs[2])(stack)) : (KN_<double>)iSD);
+					//cout << "dans le dylib :" << initialStdDevs << endl;
+					double stopTolFun = arg(3,stack,1.E-12);
+					double stopTolFunHist = arg(4,stack,0.);
+					double stopTolX = arg(5,stack,0.);
+					double stopTolUpXFactor = arg(6,stack,1.E3);
+					long popsize = arg(7,stack,4 + (long) floor(3*log(n)));
+					pcommworld vcommworld=0;
+					if (nargs[8]) vcommworld = GetAny<pcommworld>((*nargs[8])(stack));
+					
+					MPI_Comm mpiCommWorld = MPI_COMM_WORLD;
+					MPI_Comm * commworld= vcommworld ? (MPI_Comm *) vcommworld : & mpiCommWorld ;
+					//long mu = arg(8,stack,popsize/2);
+					
+					long iprint = verbosity;	
+					ffcalfunc ffJ(stack,JJ,theparam);
+					
+					//cout << endl << "ATTENTION :  " << *commworld << endl;
+					
+					int myid=0,nproc=1;
+					
+					MPI_Comm_size(*commworld,&nproc);
+					MPI_Comm_rank(*commworld,&myid);
+					
+					
+					
+					//cout << endl << "nbr de proc : " << nproc << " -- myid=" << myid << " -- world id=" << wr <<  endl;
+					
+					CMA_ES_MPI *optim=0;
+					if(nargs[9]) optim = new CMA_ES_MPI(ffJ,x,initialStdDevs,seed,popsize,commworld,(GetAny<string*>((*nargs[9])(stack)))->c_str());
+					else optim = new CMA_ES_MPI(ffJ,x,initialStdDevs,seed,popsize,commworld);
+					if(!nargs[9])
+					{
+						optim->optimizer().sp.stopTolFun = stopTolFun;
+						optim->optimizer().sp.stopTolFunHist = stopTolFunHist;
+						optim->optimizer().sp.stopTolX = stopTolX;
+						optim->optimizer().sp.stopTolUpXFactor = stopTolUpXFactor;
+						long meval = arg(10,stack,static_cast<long>(optim->maxeval()));
+						long mgen = arg(11,stack,static_cast<long>(optim->maxgen()));
+						optim->optimizer().sp.stopMaxFunEvals = meval;
+						optim->optimizer().sp.stopMaxIter = mgen;
+					}
+					
+					(*optim)();
+					cost = optim->fitness();
+					x = KN_<double>(optim->xbestever(),optim->dimension());
+					
+					delete optim;
+					closetheparam.eval(stack); // clean memory 
+					WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+					return cost; //SetAny<long>(0);  Modif FH  july 2005       
+				}
+				    
+				operator aType () const { return atype<double>();}         
+		};
+  
+		E_F0 * code(const basicAC_F0 & args) const {return new E_CMA_ES(args,cas);}
+  
+		OptimCMA_ES(int c) :   OneOperator(atype<double>(),atype<Polymorphic*>(),atype<KN<R> *>()),cas(c){}
+};
+
+basicAC_F0::name_and_type  OptimCMA_ES::E_CMA_ES::name_param[]= 
+{
+	{"seed",						&typeid(long) },
+	{"initialStdDev",		&typeid(double) },
+	{"initialStdDevs",	&typeid(KN_<double>) },
+	{"stopTolFun",			&typeid(double) },
+	{"stopTolFunHist",	&typeid(double) },
+	{"stopTolX",				&typeid(double) },
+	{"stopTolUpXFactor",&typeid(double) },
+	{"popsize",					&typeid(long) },
+	{"comm",						&typeid(pcommworld)},
+	{"paramFile",				&typeid(string*) },
+	{"stopMaxFunEval",  &typeid(long) },
+	{"stopMaxIter",  &typeid(long) }
+	
+	//{"mu",							&typeid(long) }
+};
+
+/* --FH:   class Init { public:
+  Init();
+  };*/
+
+
+static void Load_Init()  
+{
+  Global.Add("cmaesMPI","(",new OptimCMA_ES(1)); 
+
+}
+
+
+
+
+
+
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/parms_FreeFem.cpp b/examples++-mpi/parms_FreeFem.cpp
new file mode 100644
index 0000000..dea32b4
--- /dev/null
+++ b/examples++-mpi/parms_FreeFem.cpp
@@ -0,0 +1,1069 @@
+// ORIG-DATE: 04/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : INRIA FUTUR
+// AUTHOR   : Guy Atenekeng
+// E-MAIL   : Guy_Antoine_Atenekeng_Kahou at lri.fr
+//
+// ALH - need reference to MPI to have the proper include for mpi.h on MacOS10.8
+//ff-c++-LIBRARY-dep: parms metis blas mpifc fc mpi pthread
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#include <mpi.h>
+#include  <iostream>
+using namespace std;
+
+
+#define MCW MPI_COMM_WORLD
+
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+
+/* Explain here what foobar does */
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "psparslib.h"
+#include "generaldefs.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+extern "C" {
+
+  // ALH - 24/7/13 - we need to include metis/defs.h explicitely
+  // because pARMS also contains an include file called defs.h and
+  // both include directories are specified on the command line to
+  // compile this file.  Without this only one defs.h would be
+  // included, the one from the first package specified above on the
+  // line [[LIBRARY-dep]]
+
+  #include "../download/include/metis/defs.h"
+
+  #include "metis.h"
+}
+
+#ifdef WIN32
+
+// ALH - this activates the Windows DLL default export mechanism
+
+__declspec(dllexport) int not_used;
+
+// ALH - 24/7/13 - instanciate some global symbols which are not found by default in MS MPI Fortran libraries
+
+MPI_Fint* _imp__MPI_F_STATUS_IGNORE;
+MPI_Fint* _imp__MPI_F_STATUSES_IGNORE;
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define BUFLEN 100
+#define NORHS 0
+
+#define BUFLEN 100
+
+//This functions come from pARMS package and consist to scale matrix 
+
+
+
+
+
+
+
+class parm_param {
+public:
+	mutable PrePar prepar;
+	mutable IterPar ipar;
+	mutable int sol_type;
+	mutable int  iov,scale, unsymm,method;
+	mutable int solver;
+	mutable int VERBOSE;
+	
+
+	public: parm_param(){
+		PARMS_malloc(prepar,1,_PrePar);
+		PARMS_malloc(ipar,1,_IterPar);  
+		/*----------------------------------------------------------------------  *
+		 * This function  sets some default  parameters just to get  started with *
+		 * pARMS.  There are  two arrays  which define  the parameters  in pARMS. *
+		 * Because ther\ e are so many methods, the number of parameters may seem *
+		 * overwhelming.. However\ , not all  are used. For example when add_ilut *
+		 * is  used  only  two parameters  are  r\  equired  which are  the  drop *
+		 * tolerance and the  max fill per row.. This  function s\ ets everything *
+		 * so that all the methods can be safely tested. YS -                     *
+		 *                                                                        *
+		 *------------------------------------------------------------------------*/
+		  int i; 
+		/*------------------------------------------------------------------------*/
+		  for (i=1; i<18; i++)
+		    ipar->ipar[i] = 0;
+		/* parameters to be set for the solver -- not all of these are used --  
+		     depending on the method selected -                                   */
+		/* parameters associated with various accelerators (inner/outer)          */
+		  ipar->ipar[0] = 3;       /* nlev in arms when used                      */
+		  ipar->ipar[1] = 20;      /* block size in arms when used                */
+		  ipar->ipar[5] = 30;      /* Outer iteration Krylov subs. dimension      */
+		  ipar->ipar[6] = 200;     /* Max. outer iterations                       */
+		  ipar->ipar[3] = 3;       /* Inner iteration Krylov subs. dimension      */
+		  ipar->ipar[4] = 3;       /* Max. inner iterations  */
+		  
+		  ipar->pgfpar[0] = 0.01;  /* tolerance for inner iteration when used     */
+		  ipar->pgfpar[1] = 1.e-10;/* tolerance for outer iteration               */
+		/* preconditioning parameters                                             */
+		  prepar->tolind = 0.1;    /* tolerance used for diag dom. filtration alg.*/
+		  prepar->lfil[0] = 20;    /* lfil0 (ilut, iluk, and arms)                */
+		  prepar->lfil[4] = 20;    /* lfil for Schur complement const.            */ 
+		  prepar->lfil[5] = 20;    /* lfil for Schur complement const.            */ 
+		  prepar->droptol[0]=.001; /* droptol0 (ilut, iluk, and arms)             */
+		  prepar->droptol[4]=.001; /* droptol for Schur complement const.         */ 
+		  prepar->droptol[5]=.001; /* droptol for Schur complement const.         */ 
+		  prepar->mc = 1;          /* multicoloring or not in ILU when used       */
+		 //Integer parameter
+		 iov=0; scale=1; unsymm=1; method= 2; VERBOSE=0; /*no statistic infos has print*/
+		 /*VERBOSE=1 Only informations on convergence will be print*/
+		 /*VERBOSE=2 Only informations on time will be print*/
+		  solver=0;
+		 
+		  memcpy(prepar->ipar, ipar->ipar, sizeof(int)*18);
+
+		  for (i=1; i<4; i++) {
+		    prepar->droptol[i] = prepar->droptol[0]; 
+		    prepar->lfil[i] = prepar->lfil[0];
+		  }
+		  prepar->lfil[6] = prepar->lfil[5];
+		  ipar->in_iters = 0;
+		 
+		/*-------------------- done  */                       
+	}
+	public: parm_param(const KN<long> &param_int, const KN<double> &param_double)
+	{
+		 int i; 
+		PARMS_malloc(prepar,1,_PrePar);
+		PARMS_malloc(ipar,1,_IterPar);  
+		for (i=1; i<18; i++)
+		 ipar->ipar[i] = 0;
+		
+		if(param_int.N()>0){if((param_int[0]<0)||(param_int[0]>2)) 
+		{printf("%s","WRONG SOLVER INDEX WE SET DEFAULT ONE \n"); solver=0; } else solver=param_int[0];}else solver=0;
+
+		if(param_int.N()>1){if((param_int[1]<0)||(param_int[1]>13)) 
+		{printf("%s","WRONG INDEX FOR PRECONDITIONER, WE SET DEFAULT ONE \n"); method=2; } 
+		else if((param_int[1]>=0)||(param_int[1]<=13)) method=param_int[1];}else method=2;
+		
+		if(param_int.N()>2){if(param_int[2]>0) ipar->ipar[5]=param_int[2]; else ipar->ipar[5]=30;}
+		else ipar->ipar[5]=30; /* Outer iteration Krylov subs. dimension      */
+
+
+		if(param_int.N()>3){if(param_int[3]>0) ipar->ipar[6]=param_int[3]; else ipar->ipar[6]=1000;}
+		else ipar->ipar[6]=1000; /* Max. outer iterations    */
+
+
+		if((method==3)||(method==7)||(method==11)) {if(param_int.N()>4) {if(param_int[4]>0) ipar->ipar[0]=param_int[4]; 
+		else ipar->ipar[0]=3;}	else ipar->ipar[0]=3;  } /* nlev in arms when used                      */
+
+		if(param_int.N()>5){ if(param_int[5]>0) ipar->ipar[3]=param_int[5]; else ipar->ipar[3]=3;}
+		else ipar->ipar[3]=3; /* Inner iteration Krylov subs. dimension */
+
+		if(param_int.N()>6){if(param_int[6]>0) ipar->ipar[4]=param_int[6]; else ipar->ipar[4]=3;}
+		else ipar->ipar[4]=3;  /* Max. inner iterations  */
+
+		if(param_int.N()>7){if(param_int[7]>=0) unsymm=param_int[7]; else unsymm=0;} else unsymm=0;
+
+		if(param_int.N()>8) {if(param_int[8]>=0) iov=param_int[8]; else iov=0;} else iov=0;
+		if(param_int.N()>9) {if(param_int[9]>0) scale=param_int[9]; else scale=1;}else scale=1;
+
+		if(param_int.N()>10){if(param_int[10]>0) ipar->ipar[1]=param_int[10]; else ipar->ipar[1]=20; }else ipar->ipar[1]=20;
+		 
+			
+
+		if(param_int.N()>11){if(param_int[11]>0) prepar->lfil[0]=param_int[11]; else prepar->lfil[0]=20;}
+		else prepar->lfil[0]=20; /* lfil0(ilut, iluk, and arms)   */
+
+		if(param_int.N()>12){if(param_int[12]>0) prepar->lfil[4]=param_int[12]; else prepar->lfil[4]=20;}
+		else prepar->lfil[4]=20; /* lfil for Schur complement const.   */
+
+		if(param_int.N()>13){if(param_int[13]>0) prepar->lfil[5]=param_int[13]; else prepar->lfil[5]=20;}
+		else prepar->lfil[5]=20; /* lfil for Schur complement const.   */		
+
+		if(param_int.N()>14){if(param_int[14]>0) prepar->mc=param_int[14]; else prepar->mc=1; }
+		else prepar->mc=1; 
+
+		if(param_int.N()>15){if(param_int[15]>0) ipar->in_iters=param_int[15]; else ipar->in_iters=0; }
+		else ipar->in_iters=0;
+		
+		if(param_int.N()>16){if(param_int[16]>0) VERBOSE=param_int[16]; else VERBOSE=0; }else VERBOSE=0;
+
+
+			
+
+
+		if(param_double.N()>0){if(param_double[0]>0) ipar->pgfpar[1]=param_double[0]; else ipar->pgfpar[1]=1.e-08;}
+		ipar->pgfpar[1]=1.e-08; /* tolerance for outer iteration               */
+
+		if(param_double.N()>1){if(param_double[1]>0) ipar->pgfpar[0]=param_double[1]; else ipar->pgfpar[0]=0.01;}
+		else ipar->pgfpar[0]=0.01;  /* tolerance for inner iteration when used     */
+
+		if(param_double.N()>2) {if(param_double[2]>0) prepar->tolind = param_double[2]; else prepar->tolind=0.1;}
+		else prepar->tolind=0.1; /* tolerance used for diag dom. filtration alg.*/
+
+		if(param_double.N()>3){if(param_double[3]>0) prepar->droptol[0]=param_double[3]; else prepar->droptol[0]=.001;}
+		else prepar->droptol[0]=.001;	/* droptol0 (ilut, iluk, and arms) */
+		if(param_double.N()>4) {if(param_double[4]>0) prepar->droptol[4]=param_double[4]; else prepar->droptol[4]=.001;}
+		else prepar->droptol[4]=.001; /* droptol for Schur complement const.         */ 
+
+		if(param_double.N()>5){if(param_double[5]>0) prepar->droptol[5]=param_double[5]; else prepar->droptol[5]=.001;}
+		else prepar->droptol[5]=.001; /* droptol for Schur complement const.         */ 
+
+		
+
+		memcpy(prepar->ipar, ipar->ipar, sizeof(int)*18);
+		  for (i=1; i<4; i++) {
+		    prepar->droptol[i] = prepar->droptol[0]; 
+		    prepar->lfil[i] = prepar->lfil[0];
+		  }
+		  prepar->lfil[6] = prepar->lfil[5];
+		 
+		 
+	}
+
+  public: parm_param(string datafile,DistMatrix dm)
+	{
+	  FILE *fp;
+	  char buf[BUFLEN], meth_buf[BUFLEN];
+	  int num;
+	  PARMS_malloc(prepar,1,_PrePar);
+  	  PARMS_malloc(ipar,1,_IterPar);  
+
+          parm_param();
+
+	  char * filename=new char[datafile.length()+1]; 
+                strcpy(filename,datafile.c_str()); 
+ 	 /* read parameters for preconditioner and iteration from file  'filename' */
+  /*  ---- start modification by MS
+   */
+ 	 if( (fp = fopen(filename, "r")) == NULL ){
+          fprintf(stderr, "Cannot open file inputs\n");
+    	  PARMS_Final();exit(1);
+    	}
+	  for (num=0; num< 18; num++)
+	    ipar->ipar[num] = 0; 
+
+  	num = 1;
+
+  while(fgets(buf, BUFLEN, fp) != NULL) {
+    switch(num) {
+     case 1:                             /* solver */
+      sscanf(buf, "%d", &solver);
+	if((solver!=0)&&(solver!=1)&&(solver!=2))
+	{printf("%s","WRONG SOLVER INDEX, WE SET DEFAULT ONE \n"); solver=0;}
+      break;
+    case 2:                             /* preconditionner */
+      sscanf(buf,"%s",meth_buf); 
+      method = assignprecon(meth_buf, dm);
+	if((method<0)||(method>13)) 
+	{printf("%s","WRONG INDEX FOR PRECONDITIONER, WE SET DEFAULT ONE \n"); method=2; }		
+      break;
+    case 3:                             /* im (Outer Krylov subs dim) */
+      sscanf(buf,"%d",&ipar->ipar[5]);
+      break;	
+    case 4:                             /* im (Outer Krylov subs dim) */
+      sscanf(buf,"%d",&ipar->ipar[6]);
+      break;	
+    case 5:                             /* outer tol */
+      sscanf(buf,"%lf",&ipar->pgfpar[1]);
+      break;	
+    case 6:                             /* inner tol */
+      sscanf(buf,"%lf",&ipar->pgfpar[0]);
+      break;
+    case 7:                             /* unsym */
+      sscanf(buf, "%d", &unsymm);
+      break;
+    case 8:                             /* inim (inned Krylov subs dim) */
+      sscanf(buf, "%d", &ipar->ipar[3]);
+      break;
+    case 9:                             /* Max. inner iterations     */ 
+      sscanf(buf,"%d",&ipar->ipar[4]);
+      break;
+    case 10:                             /* nlev   */
+      sscanf(buf, "%d", &iov);
+      break;
+    case 11:                             /*  scale  */ 
+      sscanf(buf,"%d",&scale);
+      break;
+    case 12:                             /* For printing result */ 
+      sscanf(buf, "%d", &VERBOSE);
+      break;
+    case 13:                             /* lfil0 (ilut, iluk, and arms) */
+      sscanf(buf, "%d", &prepar->lfil[0]);
+      break;
+    case 14:                             /* lfil 4 (schur construction) */
+      sscanf(buf, "%d", &prepar->lfil[4]);
+      break;
+    case 15:                             /* lfil 5 (ILUT for Schur) */
+      sscanf(buf, "%d", &prepar->lfil[5]);
+      break;
+    case 16:                             /* bsize   */
+      sscanf(buf,"%d",&ipar->ipar[1]);
+      break;
+    case 17:                              /* tolerance used for diag dom. filtration alg.*/  
+      sscanf(buf,"%lf",&prepar->tolind);
+      break;
+    case 18:                             /*droptol (0) -- simliar to lfil0*/
+      sscanf(buf, "%lf", &prepar->droptol[0]);
+      break;
+    case 19:                             /*droptol (4) -- simliar to lfil4*/
+      sscanf(buf, "%lf", &prepar->droptol[4]);
+      break;
+    case 20:                             /*droptol (5) -- simliar to lfil5*/
+      sscanf(buf, "%lf", &prepar->droptol[5]);
+      break;
+    case 21:                             /* multicoloring or not */ 
+      sscanf(buf, "%d", &prepar->mc);
+      break;
+    
+    default:
+      break;
+    }
+    num++;
+  }
+  fclose(fp);
+  
+  memcpy(prepar->ipar, ipar->ipar, sizeof(int)*18);
+  
+  prepar->droptol[1] = prepar->droptol[2] = prepar->droptol[3] =
+    prepar->droptol[0]; 
+  prepar->droptol[6] = prepar->droptol[5];
+  
+  prepar->lfil[1] = prepar->lfil[2] = prepar->lfil[3] =
+    prepar->lfil[0];
+  prepar->lfil[6] = prepar->lfil[5];
+  ipar->in_iters = 0; free(filename);
+
+	}
+	~parm_param(){
+		free(prepar); free(ipar); 
+	
+	}
+};
+
+
+int assignprecon( char *precon_str, DistMatrix dm) 
+{
+/*------------------------------------------------------------------ 
+     create preconditioner handler  
+   * precon    --  preconditioning handler
+   * add_ilu0  --  additive schwarz preconditioner with ilu0 as local
+                   preconditioner
+   * add_ilut  --  additive schwarz preconditioner with ilut as local
+                   preconditioner
+   * add_iluk  --  additive schwarz preconditioner with iluk as local
+                   preconditioner
+   * add_arms  --  additive schwarz preconditioner with arms as local
+                   preconditioner
+   * lsch_ilu0 --  schur complement preconditioner with ilu0 as local
+                   preconditioner		  
+   * lsch_ilut --  schur complement preconditioner with ilut as local
+                   preconditioner		  
+   * lsch_iluk --  schur complement preconditioner with iluk as local
+                   preconditioner		  
+   * lsch_arms --  schur complement preconditioner with arms as local
+                   preconditioner
+   * sch_gilu0 --  parallel ilu0 preconditioner
+   * sch_sgs   --  Schur-Symmetric GS preconditioner
+   *------------------------------------------------------------------*/
+  /* set the method label for preconditioning and parameter for inner
+     iteration -- actual labels (int) are defined in SRC/ARMS/data.h */ 
+
+  int ierr, method;
+
+  ierr = 0; method=0;
+
+  if(!strcmp(precon_str, "add_ilu0")) method = add_ilu0;
+  else if(!strcmp(precon_str, "add_ilut")) method = add_ilut;
+  else if(!strcmp(precon_str, "add_iluk")) method = add_iluk;
+  else if(!strcmp(precon_str, "add_arms")) method = add_arms;
+  else if(!strcmp(precon_str, "lsch_ilu0")) method = lsch_ilu0;
+  else if(!strcmp(precon_str, "lsch_ilut")) method = lsch_ilut;
+  else if(!strcmp(precon_str, "lsch_iluk")) method = lsch_iluk;
+  else if(!strcmp(precon_str, "lsch_arms")) method = lsch_arms;
+  else if(!strcmp(precon_str, "rsch_ilu0")) method = rsch_ilu0;
+  else if(!strcmp(precon_str, "rsch_ilut")) method = rsch_ilut;
+  else if(!strcmp(precon_str, "rsch_iluk")) method = rsch_iluk;
+  else if(!strcmp(precon_str, "rsch_arms")) method = rsch_arms;
+  else if(!strcmp(precon_str, "sch_sgs")) method = sch_sgs;
+  else if(!strcmp(precon_str, "sch_gilu0")) method = sch_gilu0;
+  else ierr = 1; 
+  char pcrM[40];
+  strcpy(pcrM,"invalid choice for the preconditioner \n");
+ 
+  if (ErrHand(ierr, dm, pcrM)) 
+      exit(1) ; 
+  return method;cout << "Cette resolution semble prendre du temps" << endl;
+
+  }
+
+
+
+#define minint(a, b)       ( (a) < (b) ? (a) : (b) )
+#define maxint(a, b)       ( (a) > (b) ? (a) : (b) )
+#define max(a, b)       ( (a) > (b) ? (a) : (b) )
+#define min(a, b)   ( a < b ? (a) : (b) )
+#define fabsmin(a, b)   ( fabs(a) < fabs(b) ? (a) : (b) )
+#define fabsmax(a, b)   ( fabs(a) > fabs(b) ? (a) : (b) )
+
+
+
+class dSolvePARMS :   public MatriceMorse<double>::VirtualSolver   {
+
+	char 					mat_domain[BUFLEN];
+    	int *riord;
+	mutable int                     n, nnz, nloc;
+
+	int 					iov, scale, unsymm, method,solver,VERBOSE;
+	string data_option;
+	int                     rk, size;
+	mutable double 					*rhs1, res;
+	//double 					t1, t2, t3, t4;
+	double 					*u, *v;
+	int 					job,i1,i2;
+	mutable DistMatrix 				dm;  		//distributed matrix object
+	mutable PrePar 					prepar;  
+	mutable PreCon 					precon;  	//structure for preconditioner
+	mutable IterPar 				ipar;		//structure for iteration
+	mutable  int * maptmp1, *mapptr1;
+	double eps, tol_pivot_sym,tgv, tol_pivot,epsr;
+	mutable double t1,t2,t3,t4;
+	mutable char * meth[14];
+	mutable int *maptmp, *mapptr,*iwork1,*iwork;
+	mutable double *scaletmpr, *scaletmpc;
+	mutable MPI_Comm comm;
+	char *p;
+//Constructor construct the distribute matrix and also preconditionner
+public:
+  dSolvePARMS(const MatriceMorse<double> &AA,string datafile,  KN<long> &param_int,  KN<double> &param_double,  MPI_Comm  * mpicommw)
+	{
+	int n,i,job,nnz,ierr,tmp;
+	int *ptr2,*id_rows2;
+	double *vals2;
+	double *AAv;
+	int *p, *pr;	
+	
+
+	int 	 j,    node;
+	/* Initialize PARMSARSLIB environment */
+	 if(mpicommw==NULL){
+	comm=MPI_COMM_WORLD;
+	}
+	else
+	comm= *mpicommw;
+	// comm=MPI_COMM_WORLD;
+	 ierr = MPI_Comm_rank(comm, &rk);
+	 ierr = MPI_Comm_size(comm, &size);
+	 parm_param * pp;
+	/*Differents preconditionners use*/
+	 meth[0]=(char *)malloc(sizeof(char)*9); strcpy(meth[0],"add_ilu0"); meth[1]=(char *)malloc(sizeof(char)*9); strcpy(meth[1],"add_ilut"); 
+	 meth[2]=(char *)malloc(sizeof(char)*9); strcpy(meth[2],"add_iluk"); meth[3]=(char *)malloc(sizeof(char)*9); strcpy(meth[3],"add_arms");
+	 // FFCS - fixed "buffer overflow" warning by JHunt
+	 meth[4]=(char *)malloc(sizeof(char)*10); strcpy(meth[4],"lsch_ilu0"); meth[5]=(char *)malloc(sizeof(char)*10); strcpy(meth[5],"lsch_ilut");  
+	 meth[6]=(char *)malloc(sizeof(char)*10); strcpy(meth[6],"lsch_iluk"); meth[7]=(char *)malloc(sizeof(char)*10); strcpy(meth[7],"lsch_arms"); 	
+	 meth[8]=(char *)malloc(sizeof(char)*10); strcpy(meth[8],"rsch_ilu0"); meth[9]=(char *)malloc(sizeof(char)*10); strcpy(meth[9],"rsch_ilut");
+         meth[10]=(char *)malloc(sizeof(char)*10); strcpy(meth[10],"rsch_iluk"); meth[11]=(char *)malloc(sizeof(char)*10); strcpy(meth[11],"rsch_arms");
+	 meth[12]=(char *)malloc(sizeof(char)*10); strcpy(meth[12],"sch_gilu0"); meth[13]=(char *)malloc(sizeof(char)*8); strcpy(meth[13],"sch_sgs");
+	/*storage format of the matrix*/
+         char pcrM[4];
+	strcpy(pcrM,"csr");
+	
+	/*- Create Distributed Matrix dm in CSR format */
+		
+	CreateMat(&dm, pcrM);
+	
+	dm->comm->mpi_comm=comm;dm->comm->myproc=rk; dm->comm->npro=size; 
+
+	/*------ Create PrePar /iterPar pointer */
+	
+		
+	/*---- parameters for preconditioning and iteration*/
+	if((datafile.empty())&&(param_double==NULL)&&(param_int==NULL)){
+		if(dm->comm->myproc==0)
+		printf("%s","We are going to set default parameters because user did not specify any one  \n \n ");
+		
+		parm_param * pp= new parm_param(); 
+		 
+		iov=pp->iov; scale=pp->scale; unsymm=pp->unsymm; 
+		
+		method= assignprecon(meth[pp->method], dm);
+		
+		prepar=pp->prepar; ipar=pp->ipar; VERBOSE=pp->VERBOSE; solver=pp->solver;
+	
+	}
+	if(((param_double!=NULL)||(param_int!=NULL))&&(datafile.empty()))
+	{
+		if(dm->comm->myproc==0)
+  		  printf("%s","User have set parameter inside vector of parameter  \n");	
+
+	        parm_param * pp= new parm_param(param_int, param_double); 
+		iov=pp->iov; scale=pp->scale; unsymm=pp->unsymm; method= assignprecon(meth[pp->method], dm); 
+		prepar=pp->prepar; ipar=pp->ipar; VERBOSE=pp->VERBOSE; solver=pp->solver;
+              
+	}
+	if((!datafile.empty())&&((param_double==NULL)&&(param_int==NULL)))
+	{
+		if(dm->comm->myproc==0)
+		printf("%s","User have set parameter inside file of parameter  \n");
+		parm_param * pp= new parm_param(datafile, dm); 
+		iov=pp->iov; scale=pp->scale; unsymm=pp->unsymm; method=pp->method; 
+		prepar=pp->prepar; ipar=pp->ipar; VERBOSE=pp->VERBOSE; solver=pp->solver;
+	}
+	if(((solver==1)||(solver==2))&&((method!=0)||(method!=4))) 
+	{
+		if(dm->comm->myproc==0) 
+		printf("%s%s%s", "WE NOT GARANTI THE PRECONDITIONNER WILL WORK BECAUSE ACCELARATOR ", meth[method] ," NO NEED INNER ITERATION \n");
+		//MPI_Finalize();
+	}
+	if((dm->comm->myproc==0)&&(VERBOSE>=0)){
+		printf("###########################################\n");
+		printf("######### CALLING PARMS PACKAGE ###########\n");
+		if(solver==0)
+		printf("########### SOLVER : FGMRES #######\n");
+		if(solver==1)
+		printf("########### SOLVER : BiCGStab #######\n");
+		if(solver==2)
+		printf("########### SOLVER : DGMRES #######\n");
+		printf("%s%s%s","########### PRECONDITIONNER : ",  meth[method], "\n" );
+		printf("###########################################\n");
+	}
+
+	/*----from zero-based to 1-based before calling pARMS routine----*/
+	n=AA.n; nnz=AA.nbcoef;
+	PARMS_malloc(pr,n+1,int) ;
+	PARMS_malloc(p,nnz,int) ;
+	PARMS_malloc(AAv,nnz,double) ;
+
+	for(i=0;i<nnz;i++){
+	AAv[i]=AA.a[i];
+	p[i]=AA.cl[i];
+	if(i<=n) pr[i]=AA.lg[i];
+	}
+        
+	for(j=0; j<pr[n]; j++){
+		p[j]+=1;
+	}	
+	for(i=0; i<=n; i++){
+		pr[i]+=1;
+	}
+//	pr[0]=1;
+
+	double * vals1;
+	int * id_rows1, *ptr1;
+	/*-------- transpose the matrix to CSC format--*/
+	PARMS_malloc(vals1,nnz,double) ;
+	PARMS_malloc(id_rows1,nnz,int) ;
+	PARMS_malloc(ptr1,n+1,int) ;
+	job=1;
+	i=1;
+	
+	csrcsc(&n, &job, &i, AAv, p, pr, vals1, id_rows1, ptr1);
+	
+ /*----------- compute C=A+B where B=transpose(A) -------*/	
+	
+	 if(unsymm) {
+	
+	PARMS_malloc(iwork,n,int);
+	PARMS_malloc(vals2, 2*nnz, double);
+	PARMS_malloc(id_rows2, 2*nnz, int);
+	PARMS_malloc(ptr2, n+1, int);
+	
+	for(i=0; i<nnz; i++) AAv[i]=0.0;
+	job=1;
+	i1=2*nnz; 
+
+	aplb(&n, &n, &job, vals1, id_rows1, ptr1, AAv, p, pr, 
+		  vals2, id_rows2, ptr2, &i1, iwork, &ierr);
+
+	
+
+	if(ierr) printf("error: in aplb, ierr=%d\n",ierr);
+	nnz=ptr2[n]-1;
+	if (!rk)
+        printf("Matrix pattern has been symmetrized; added %d nonzeros.\n",
+           ptr2[n]-pr[n]);
+
+	memcpy(pr, ptr2, (n+1)*sizeof(int));
+	p=(int *)realloc(p, nnz*sizeof(int));
+	AAv=(double *)realloc(AAv, nnz*sizeof(double));
+	memcpy(p, id_rows2, nnz*sizeof(int));
+	memcpy(AAv, vals2, nnz*sizeof(double));
+	free(vals1); free(vals2); free(id_rows1); free(id_rows2); free(ptr1); free(ptr2);
+	
+	}
+
+	 else {
+/*-------- simply overwrite A with B (transposed matrix)  */
+          nnz = ptr1[n]-1;
+      memcpy(pr, ptr1, (n+1)*sizeof(int));
+      memcpy(p, id_rows1, nnz*sizeof(int));
+      memcpy(AAv,  vals1, nnz*sizeof(double));
+    }
+	
+
+	/*------ scale the matrix */
+	  if(scale) {
+	    job = 1;
+	    tmp = 2; /*-- compute 2-norm */
+	    PARMS_malloc(scaletmpr,n,double) ; PARMS_malloc(scaletmpc,n,double) ;
+	    roscal(&n,&job,&tmp,AAv,p,pr,scaletmpr,AAv,p,pr,&ierr);
+	    if (ierr) fprintf(stderr, "Error: in roscal, ierr = %d\n", ierr);
+	
+	    coscal(&n,&job,&tmp,AAv,p,pr,scaletmpc,AAv,p,pr,&ierr);
+	    if (ierr) fprintf(stderr, "Error: in coscal, ierr = %d\n", ierr);
+	  } /*--- end of branch on scaling */
+
+	/* -------Matrix partitioning : Use Metis ----------*/
+	
+	PARMS_malloc(riord, n, int);
+	int wgtflag=0, numflag=1, volume;
+	
+	int option[5];
+	option[0]=0;
+	if(size>1){
+		METIS_PartGraphVKway(&n, pr, p, NULL, NULL, &wgtflag, &numflag,&size, option, &volume, riord);
+	}
+	else if(size==1){
+		for (i=0; i<n; i++) riord[i]=1;
+	}
+	
+	PARMS_malloc(iwork, n, int);
+	PARMS_malloc(maptmp, n, int);
+	PARMS_malloc(mapptr, size+1, int);
+	PARMS_malloc(iwork1, size+1, int);	
+	for(i=0; i<size; i++){
+		iwork[i]=0;
+	}
+	for(j=0; j<n; j++){
+		iwork[riord[j]-1]++;
+		
+	}
+	numflag=1;
+	for(i=0; i<size; i++){
+		mapptr[i]=numflag;
+		numflag+=iwork[i];
+	}
+	mapptr[size]=numflag;
+	
+	for (i=0; i<size; i++){
+		iwork[i]=mapptr[i]-1;
+	}
+	for(i=0; i<n; i++){
+		maptmp[iwork[riord[i]-1]]=i+1;
+		iwork[riord[i]-1]++;
+	}
+  	
+	
+	if(iov == 0) {
+/*------ in non-overlapping case, simply copy the node-to-processor info */
+ 	   maptmp1= maptmp ;
+   	   mapptr1 = mapptr;
+  	}
+
+	if(iov != 0) {
+/*----- expand sub-domain if overlapping is desired */
+	int maxmp;
+   	 maxmp = 15*n;
+	
+    	 PARMS_malloc(maptmp1,maxmp,int) ;
+    	 PARMS_malloc(mapptr1,size+1,int) ;
+         expnddom(&n, &size, p, pr, maptmp, mapptr, maptmp1, &maxmp,mapptr1, iwork);   	
+	free(maptmp); free(mapptr);
+  }
+	
+	
+/*---map from global node lables to local ---*/
+	getmap(dm, maptmp1, mapptr1, &n);	
+/*---prepare for extraction of local submatrix  --*/
+	int tmp0=1;
+	tmp =1;
+	i1=mapptr1[rk];
+	i2=mapptr1[rk+1]-1;
+	nloc=i2-i1+1;
+	nnz=0;
+
+	for(i=i1; i <=i2; i++){
+		node=maptmp1[i-1];
+		nnz += pr[node]-pr[node-1];
+		
+	}
+	PARMS_malloc(vals1, nnz, double);
+	PARMS_malloc(id_rows1, nnz, int);
+	PARMS_malloc(ptr1, nloc+1, int);
+	/*---- extract the submatrix to be owned by rk */
+	
+
+	DPERM1(&i1,&i2,AAv,p,pr,vals1,id_rows1,ptr1,maptmp1,&tmp0,&tmp);
+	
+	
+	
+
+	 free(p); p=NULL; free(pr); pr=NULL; free(AAv); AAv=NULL;
+
+/* --- CSR to Distributed matrix structure ---*/
+	
+	 CopyCsrToDm(dm, vals1, id_rows1, ptr1);
+	 free(vals1); free(id_rows1); free(ptr1);
+	 vals1=NULL; id_rows1=NULL; ptr1=NULL;
+	
+/*--- create boundary information */
+ 	 bdry(dm);
+
+/*--- set up the local data strucutre for the sparse matrix */
+	 setup(dm);
+	
+	
+	
+/*check consistency of input parameters for 'rsch*' and 'lsch*' preconditioners.
+	 -- at least one iteration on inner iterative solver should be performed for
+	 -- them, e.g., inner convergence tolerance; inner number of iterations and
+	 -- the inner subspace size should be nonzero.
+*/
+	
+	
+	 if (!strncmp(meth[method], "lsch", 4) || !strncmp(meth[method], "rsch", 4) ){
+		 ierr = 0;
+		 if (ipar->pgfpar[0] == 0.0){
+			 if (rk == 0)
+				 fprintf(stderr, "Error: Tolerance for inner solver\n");
+			 ierr = 1;
+		 }
+		 if (ipar->ipar[3] == 0){
+			 if (rk == 0)
+				 fprintf(stderr, "Error: Krylov subspace size for inner solver\n");
+			 ierr = 1;
+		 }
+		 if (ipar->ipar[4] == 0){
+			 if (rk == 0)
+				 fprintf(stderr, "Error: Maximum number of inner iterations\n");
+			 ierr = 1;
+		 }
+		 if (ierr == 1){
+			 if (rk == 0)
+				 fprintf(stderr,"should be nonzero to invoke the Schur Complement iteration\n ");
+			 PARMS_Final();
+			 exit(1);
+		 }
+	 }
+	
+	
+	 /*----- create preconditioner */
+	if(VERBOSE==3){
+	
+	  MPI_Barrier(dm->comm->mpi_comm);
+	 t1 = dwalltime();}
+	
+	 ierr = CreatePrec(dm,&precon,method,prepar,ipar);
+	
+	 
+	 if(VERBOSE==3) {
+	  MPI_Barrier(dm->comm->mpi_comm);
+	 t2 = dwalltime();
+	 t2 = fabs(t2-t1);
+	 double tmax=0.0;
+          MPI_Reduce(&t2, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0,dm->comm->mpi_comm);
+   	  MPI_Bcast(&tmax, 1, MPI_INT,0,dm->comm->mpi_comm);
+	t2=tmax;
+	 }
+	 
+	 /*----- check for errors in preconditioning construction, quit if any */
+	 if (ierr != 0)
+	 fprintf(stderr, "Fatal Error (ierr = %d) in preconditioner construction on processor %d\nExiting...\n", ierr, rk);
+	 ierr = ierr*ierr;
+	 int tmp_ierr=0;
+
+	 MPI_Allreduce(&ierr, &tmp_ierr, 1, MPI_INT, MPI_SUM, dm->comm->mpi_comm);
+	 
+	 if ( tmp_ierr > 0 ){ 
+		 /* delete distributed local matrix */
+		 DeleteMat(&dm);
+		 /* delete distributed local vector */	 
+		 free(prepar);
+		 free(ipar);
+		 free(pp); 
+	         
+		 /* exit PARMS and MPI environment */
+		 PARMS_Final();
+		 exit(1);
+	 }	
+	
+}
+	void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+	/* Vec structure
+	 rhs -- right hand side,
+	 sol -- solution,   
+	 xsol -- exact solution */
+	
+         Vec 	sol, rhs;
+	 int i,comt,node;
+	 int * poloc;
+	 double res1;
+	 double 	dnnz_pre, dgprec_nnz;
+	 nnz=AA.nbcoef;	
+
+	 CreateVec(&rhs);
+	 CreateVec(&sol);
+	 n=AA.n;
+	  double * rhsb=(double *)malloc(sizeof(double)*n);
+	 for(i=0;i<n;i++) rhsb[i]=b[i];
+	 /* Copy communication structure to Vec */
+	 CopyComm(dm,rhs);
+	 CopyComm(dm,sol);
+	 
+	 PARMS_malloc(rhs->vec, nloc, double); PARMS_malloc(poloc, nloc, int);
+	comt=0;
+	 if(scale)
+	     { for(i = 0; i < n; i++) 
+		rhsb[i] *= scaletmpr[i];
+		
+	}
+	
+
+	for(i=i1;i<=i2;i++)
+	{
+		  node = maptmp1[i-1];poloc[comt]=node-1;
+		  rhs->vec[comt]=rhsb[node-1];comt++;
+		  
+	}
+/*----Iteration count-------------------------------------*/
+	ipar->in_iters=0;
+	ipar->iters=0;
+	
+/*--- Permute RHS according to result of setup routine ---*/
+	 setuprhs(rhs);
+	   
+/*------- populate the initial guess with values */
+	 VecSetVal(sol,0.0); 
+/*------- calculate the norm of the residual on input */
+	 res1 = ResiNorm2(dm, sol, rhs);
+	 
+
+	 if(VERBOSE==3){
+	MPI_Barrier(dm->comm->mpi_comm);
+	 t3 = dwalltime(); }
+	double dgnnz;
+	if(VERBOSE==3){
+	dnnz_pre = precon->nnz_pre;
+        dgnnz = (double)nnz;
+	dgprec_nnz=0;
+	 MPI_Reduce(&dgprec_nnz, &dnnz_pre, 1, MPI_DOUBLE, MPI_SUM, 0, dm->comm->mpi_comm); 
+         }
+
+
+	 if(rk == 0) 	{
+			printf("Total NNZ(PreCon) / (NNZ*npro) = %6.2f\n",dgprec_nnz/dgnnz);
+			
+			
+		}
+		
+
+	if(solver==0) fgmresd(dm,precon,ipar,rhs,sol);
+	if(solver==1) dgmresd(dm,precon,ipar,rhs,sol);
+	if(solver==2) bcgstabd(dm,precon,ipar,rhs,sol);
+	
+	
+	 res = ResiNorm2(dm, sol, rhs);
+	
+
+	
+
+	if(VERBOSE==3){	
+	MPI_Barrier(dm->comm->mpi_comm);
+	 t4 = dwalltime(); 
+	 t4 = fabs(t4-t3); 
+	  double tmax=0;
+         MPI_Reduce(&t4, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0,dm->comm->mpi_comm);
+   	 MPI_Bcast(&tmax, 1, MPI_DOUBLE,0,dm->comm->mpi_comm);
+	t4=tmax;
+	 }
+	 
+	 
+	 /*----find the norm of the solution error */
+	 i=1;
+	 t3 = -1.0;
+	 int j;
+	  for (i=0; i<nloc; i++){
+       		j=sol->node[i]-1; /* get the global node corresponding to node i*/
+		poloc[i]=j;
+    	 }
+	
+	 if (scale){
+/*--------- apply permutations to scaletmp */
+   	for (i=0; i<nloc; i++){
+       		j=sol->node[i]-1; /* get the global node corresponding to node i*/
+	        sol->vec[i] = sol->vec[i]*scaletmpc[j];
+	/*---- find the residual of the computed solution */  
+	}
+  }	
+	 /*-----  compute the relative error of computed solution */
+
+	 if((dm->comm->myproc == 0)&&(VERBOSE==3)) {
+		 fprintf(stdout,"################   SOLVER STATISTICS     ####################\n");
+		 fprintf(stdout, "OUTER ITERATIONS COUNT IS %d\n", ipar->iters);
+		 fprintf(stdout, "INNER ITERATION COUNT IS %d\n", ipar->in_iters);
+		 fprintf(stdout, "THE TOTAL TIME IS %16.8f\n", t2+t4);
+		 fprintf(stdout, "THE TIME FOR CREATING PRECONDITIONER IS %16.8f\n", t2);
+		 fprintf(stdout, "THE TIME FOR SOLVING PROCESS is %16.8f\n", t4);
+		 fprintf(stdout, "The 2-NORM OF THE RELATIVE RESIDUAL IS %16.8g\n", res/res1);
+	 }
+	 if((dm->comm->myproc == 0)&&(VERBOSE==2)) {
+		 fprintf(stdout, "THE TOTAL TIME IS %16.8f\n", t2+t4);
+		 fprintf(stdout, "THE TIME FOR CREATING PRECONDITIONER IS %16.8f\n", t2);
+		 fprintf(stdout, "THE TIME FOR SOLVING PROCESS is %16.8f\n", t4);
+	 }
+	 if((dm->comm->myproc == 0)&&(VERBOSE==1)) {
+		 fprintf(stdout, "OUTER ITERATIONS COUNT IS %d\n", ipar->iters);
+		 fprintf(stdout, "INNER ITERATION COUNT IS %d\n", ipar->in_iters);
+		 fprintf(stdout, "The 2-NORM OF THE RELATIVE RESIDUAL IS %16.8g\n", res/res1);
+		 
+		
+	 }
+
+  	  double *  xx= (double *)malloc(sizeof(double)*n);
+	 
+	 
+	   comt=0;
+	    
+	    
+	   for(i=0;i<dm->comm->npro;i++) mapptr[i]--;
+	   int *displs, *perm; 
+	   PARMS_malloc(displs, nloc, int);PARMS_malloc(perm, n, int);
+	 
+	
+	   MPI_Gatherv(&(sol->vec[0]), nloc, MPI_DOUBLE, &(xx[0]), iwork, mapptr ,  MPI_DOUBLE, 0,comm );
+	   MPI_Gatherv(&(poloc[0]), nloc, MPI_INT, &(perm[0]), iwork, mapptr ,  MPI_INT, 0,comm );
+	   MPI_Bcast(perm,AA.n,MPI_INT,0, comm);
+	   
+	   int *invp=(int *)malloc(sizeof(int)*n);
+	   for(i=0;i<n;i++) invp[perm[i]]=i;
+
+	   if(dm->comm->myproc==0){for(i=0;i<n;i++) x[i]=xx[invp[i]];  } 
+	   MPI_Bcast(x,AA.n,MPI_DOUBLE,0, comm);
+	   for(i=0;i<dm->comm->npro;i++) mapptr[i]++;
+	  /*Delete use vectors*/
+	   DeleteVec(&sol); DeleteVec(&rhs); free(xx);
+	   //This should be in Destructor
+	   free(perm); free(invp);
+	  	
+	
+	}
+	~dSolvePARMS()
+	{
+	 if(VERBOSE==3){
+	  cout << "~SolvePARMS:" << endl;
+	 free(mapptr);
+	 DeletePrec(precon); free(scaletmpc); free(scaletmpr);
+	 /*---- Delete distributed local matrix */
+	 DeleteMat(&dm);
+	 /*---- Delete distributed local vector */
+	free(prepar); free(ipar);
+	/*Delete matrix and right hand side*/
+	
+	}
+	 
+	  //PARMS_Final();
+
+         }
+     void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+     {  
+      ffassert(x.N()==Ax.N());
+      Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+     }
+};
+
+
+inline MatriceMorse<double>::VirtualSolver *
+BuilddSolvePARMS(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+	 if(verbosity>9)
+      cout << " BuildSolverMUMPSmpi<double>" << endl;
+
+	
+
+    return new dSolvePARMS(*A,ds.data_filename, ds.lparams, ds.dparams,(MPI_Comm *)ds.commworld);
+}
+
+/* --FH:   class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; 
+
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity>1)
+    cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+    return TRUE;
+}
+
+bool SetdSolvePARMS()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to PARMS" << endl;
+      DefSparseSolver<double>::solver  =BuilddSolvePARMS;
+     TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+     return TRUE;
+}
+
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: pARMSmpi,  defaultsolver defaultsolverpARMSmpi" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuilddSolvePARMS;
+  //DefSparseSolver<Complex>::solver =BuildSolverMUMPSmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttopARMSmpi","(",new OneOperator0<bool>(SetdSolvePARMS));
+}
+
+
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/real_SuperLU_DIST_FreeFem.cpp b/examples++-mpi/real_SuperLU_DIST_FreeFem.cpp
new file mode 100644
index 0000000..b416ac8
--- /dev/null
+++ b/examples++-mpi/real_SuperLU_DIST_FreeFem.cpp
@@ -0,0 +1,813 @@
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep: superlu_dist  blas parmetis metis mpi fc
+//ff-c++-cpp-dep: 
+//
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+#include <mpi.h>
+
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include "superlu_ddefs.h"
+#include "ffsuperludistoption.hpp"
+
+template <class R> struct SuperLUmpiDISTDriver
+{
+    
+};
+
+template <> struct SuperLUmpiDISTDriver<double>
+{
+  /* Driver routines */
+  static  Dtype_t R_SLU_T() { return SLU_D;} 
+  static void
+  
+  pgssvx(superlu_options_t *p1, SuperMatrix *p2, ScalePermstruct_t *p3,
+	  double *p4, int p5, int p6, gridinfo_t *p7,
+	  LUstruct_t *p8, SOLVEstruct_t *p9, double *p10,
+	  SuperLUStat_t *p11, int *p12)
+  { pdgssvx( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 ); }
+  
+    
+  static void
+  pgssvx_ABglobal(superlu_options_t *p1, SuperMatrix *p2, 
+	 ScalePermstruct_t *p3,
+	 double *p4, int p5, int p6, gridinfo_t *p7,
+	 LUstruct_t *p8, double *p9,
+	 SuperLUStat_t *p10, int *p11)
+  { pdgssvx_ABglobal( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11); }
+        
+  static void
+  Print_CompRowLoc_Matrix_dist(SuperMatrix *p1)
+  {
+    dPrint_CompRowLoc_Matrix_dist(p1);
+  }
+
+  static void
+  Create_CompCol_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+			     double *p5, int_t *p6, int_t *p7,
+			    Stype_t p8, Dtype_t p9, Mtype_t p10)
+  {
+    dCreate_CompCol_Matrix_dist(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
+  }
+  
+  static void
+  Create_CompRowLoc_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3,
+				 int_t p4, int_t p5, int_t p6,
+				 double *p7, int_t *p8, int_t *p9,
+				 Stype_t p10, Dtype_t p11, Mtype_t p12)
+  {
+    dCreate_CompRowLoc_Matrix_dist( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
+  }
+   
+  static void
+  CompRow_to_CompCol_dist(int_t p1, int_t p2, int_t p3, 
+                         double *p4, int_t *p5, int_t *p6,
+                         double **p7, int_t **p8, int_t **p9)
+  {
+    dCompRow_to_CompCol_dist( p1,p2,p3,p4,p5,p6,p7,p8,p9 );
+  }
+
+  static void
+  Create_Dense_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, double *p4,
+			    int_t p5, Stype_t p6, Dtype_t p7,
+			    Mtype_t p8)
+  {
+    dCreate_Dense_Matrix_dist( p1,p2,p3,p4,p5,p6,p7,p8 );  
+  }
+
+  static void
+  Create_SuperNode_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+				double *p5, int_t *p6,
+				int_t *p7, int_t *p8,
+				int_t *p9, int_t *p10,
+				Stype_t p11, Dtype_t p12, Mtype_t p13)
+  {
+    dCreate_SuperNode_Matrix_dist(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,  p11,p12,p13);
+  }
+
+};
+
+template<class R>
+class SolveSuperLUmpi :   public MatriceMorse<R>::VirtualSolver, public SuperLUmpiDISTDriver<R>   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+   
+   
+  //mutable char           equed[1];
+  //yes_no_t       equil;
+  mutable SuperMatrix    A;
+  NCformat       *Astore;
+  //NCformat       *Ustore;
+  //SCformat       *Lstore;
+
+  mutable superlu_options_t options;
+  mutable mem_usage_t    mem_usage;
+  mutable ScalePermstruct_t ScalePermstruct;
+  mutable LUstruct_t        LUstruct;
+  mutable SOLVEstruct_t     SOLVEstruct;
+  mutable gridinfo_t        grid;
+
+  string string_option;
+  string data_option;
+  R             *a;
+  int           *asub, *xa;
+  int_t m, n, nnz;
+  // rajout pour //
+  int_t nprow,npcol;  /* process rows and process columns*/
+
+
+  int matrixdist; // type of distributed matrix
+  MPI_Comm commworld ;
+  static const int assembled =0;
+  static const int distributedglobal =1;
+  static const int distributed =2;
+
+  int iam;
+
+public:
+  SolveSuperLUmpi(const MatriceMorse<R> &AA,int strategy,double ttgv, double epsilon,
+		  double pivot,double pivot_sym, string datafile,
+		  string param_char, KN<long> &pperm_r, KN<long> &pperm_c,void * ccommworld=0) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),string_option(param_char),data_option(datafile),
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+    commworld = ccommworld ? *static_cast<MPI_Comm*>( ccommworld) : MPI_COMM_WORLD;  
+    int rank;
+    MPI_Comm_rank(commworld, &rank); 
+    R*      B;
+    //R*      X;
+    SuperLUStat_t stat;
+    int            info, ldb, nrhs=0;
+    int            i;
+    double*        berr;
+    
+    //int iam;
+    // Add for distributed matrix
+    int_t         m_loc, m_loc_fst, fst_row, nnz_loc, fst_nnz;
+    R             *aloc;
+    int           *asubloc, *xaloc;
+    // End Add for distributed matrix
+    A.Store=0;
+   
+    int status;
+    // time variables
+
+    long int starttime,finishtime;
+    long int timeused;
+
+    // rajout debug
+    int myid;
+    if(verbosity) starttime = clock();
+
+
+    /* Defaults */
+    nrhs  = 0;
+
+    /* lecture de nprow and npcol */
+    // Cas max deux procs
+    nprow = 1;
+    npcol = 1;
+    matrixdist=0;
+    
+    
+    if(!data_option.empty()) read_nprow_npcol_matrixdist_superlu_datafile(&data_option, &nprow, &npcol, &matrixdist);
+    if(!string_option.empty()) read_nprow_npcol_freefem( &string_option, &nprow, &npcol, &matrixdist);
+    
+     /* ------------------------------------------------------------
+	 INITIALIZE THE SUPERLU PROCESS GRID. 
+	 ------------------------------------------------------------*/
+    if( (verbosity>1) && (rank ==0))
+    cout << "Real superlu_gridinit" << " " << commworld << " " << ccommworld <<endl;
+    superlu_gridinit(commworld, nprow, npcol, &grid);
+
+    /* Bail out if I do not belong in the grid. */
+    iam = grid.iam;
+    if ( iam >= nprow * npcol ){      
+      printf("this process is not used in superlu %d \n",iam);
+    }
+    else
+      {
+	/* set the default options */
+	set_default_options_dist(&options);
+	DiagScale_t optionDiagScale;
+
+	if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);	
+	if(!data_option.empty()) read_options_superlu_datafile(&data_option,&options,&nprow, &npcol, &matrixdist,&optionDiagScale);
+
+	// matrix to procs and vectors
+	if( matrixdist == assembled ){
+	  
+	  if(!iam){
+	    if(verbosity>5)
+	      {
+		
+	    cout <<  "iam=" << iam << " " ;
+	    printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	      }
+	    /* create the matrix for superlu_dist */
+	    n=AA.n;
+	    m=AA.m;
+	    nnz=AA.nbcoef;
+	  
+	    assert( AA.lg[n] == nnz );	   
+	    if(verbosity>5) printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	    
+	    /* transform Row to Col */
+	    // cela coute cher comme fonction //
+	    //dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    //dCompRow_to_CompCol_dist(m,n,nnz,arow,asubrow,xarow,&a,&asub,&xa);
+	    
+	    dCompRow_to_CompCol_dist(m,n,nnz,AA.a,AA.cl,AA.lg,&a,&asub,&xa);
+	    
+	    /* Broadcast matrix A to the other PEs. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    int infobcast=MPI_Bcast( a,    nnz, MPI_DOUBLE, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	    
+	  }
+	  else{
+	    /*
+	      printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	       Receive matrix A from PE 0. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    
+	    /* Allocate storage for compressed column representation. */
+	    dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    
+	    int infobcast=MPI_Bcast( a, nnz, MPI_DOUBLE, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	  }
+	  
+	  Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	  if(verbosity>6)
+	  cout << "Debut: Create_CompCol_Matrix_dist" <<endl;
+	  // FFCS - "this->" required by g++ 4.7
+	  this->Create_CompCol_Matrix_dist(&A, m, n, nnz, a, asub, xa, SLU_NC, R_SLU, SLU_GE); 
+	  if(verbosity>6)
+	  cout << "Fin: Create_CompCol_Matrix_dist" <<endl;
+	  /* creation of pseudo solution + second member */
+	  
+	  if ( !(B = doubleMalloc_dist(m )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  
+	  if(verbosity>2 && rank ==0)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+
+	  
+	  /* Initialize ScalePermstruct and LUstruct. */
+	  ScalePermstructInit(m, n, &ScalePermstruct);
+	  if( !(pperm_r==NULL)  ||  !(pperm_c==NULL) ) ScalePermstruct.DiagScale=optionDiagScale;
+	  if( !(pperm_r==NULL) ) 
+	    for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[ii];
+	  if( !(pperm_c==NULL) )
+	    for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii]= pperm_c[ii];
+	  
+	  if( ScalePermstruct.DiagScale != NOEQUIL ){
+	    printf("FreeFem++ doesn't support change of the original matrix"); 
+	    exit(1);
+	  }
+	  LUstructInit(m, n, &LUstruct);
+	  
+	  /* Initialize the statistics variables. */
+	  PStatInit(&stat);
+	  
+	  ldb = m;
+	  nrhs=1;
+	  if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  berr[0]=0.;
+    	
+	  if(verbosity && rank ==0)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	
+	  /* INIT LU struct*/
+	  
+	  /* ONLY PERFORM THE LU DECOMPOSITION */
+	  //B.ncol = 0;  /* Indicate not to solve the system */
+	  
+	  nrhs=0;
+	  SuperLUmpiDISTDriver<R>::pgssvx_ABglobal(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					       &LUstruct, berr, &stat, &info);
+	
+	  if(verbosity>2 && rank ==0)
+	    printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	  
+	  if ( verbosity) PStatPrint(&options,&stat,&grid);
+	  PStatFree(&stat);
+	  	 
+	}
+	//##########################################################
+	//
+	//       matrix distributed with matrix global given
+	//
+	//##########################################################
+	else if( matrixdist == distributedglobal) {
+	   if(!iam){
+
+	     if(verbosity>2) printf("\tProcess grid\t%d X %d iam=%d \n", grid.nprow, grid.npcol,iam);
+	
+	     /* create the matrix for superlu_dist */
+	     n=AA.n;
+	     m=AA.m;
+	     nnz=AA.nbcoef;
+	     a=AA.a;
+	     asub=AA.cl;
+	     xa=AA.lg;
+	     
+	     xa[n] = nnz;
+	     if(verbosity>6) printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	     
+	     /* Broadcast matrix A to the other PEs. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     MPI_Bcast( AA.a,    nnz, MPI_DOUBLE, 0, grid.comm );
+	     MPI_Bcast( AA.cl, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( AA.lg,   n+1, mpi_int_t,  0, grid.comm );
+	     
+	     
+	   }
+	   else{
+	     
+	     if(verbosity>6)printf("\tProcess grid\t%d X %d iam=%d \n", grid.nprow, grid.npcol,iam);
+	     /* Receive matrix A from PE 0. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     /* Allocate storage for compressed column representation. */
+	     dallocateA_dist(n, nnz, &a, &asub, &xa);
+	     
+	     MPI_Bcast(    a,   nnz, MPI_DOUBLE,  0, grid.comm );
+	     MPI_Bcast( asub,   nnz,  mpi_int_t,  0, grid.comm );
+	     MPI_Bcast(   xa,   n+1,  mpi_int_t,  0, grid.comm );
+
+	   }
+	   
+	   /* Compute the number of rows to be distributed to local process */
+	   m_loc = m / (grid.nprow * grid.npcol); 
+	   m_loc_fst = m_loc;
+	   /* When m / procs is not an integer */
+	   if ((m_loc * grid.nprow * grid.npcol) != m) {
+	     /*m_loc = m_loc+1;
+	       m_loc_fst = m_loc;*/
+	     if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	       m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	   }
+	   
+	   fst_row = iam * m_loc_fst;
+	   
+	   nnz_loc = xa[fst_row+m_loc]-xa[fst_row];
+	   
+	   xaloc = (int_t*) intMalloc_dist(m_loc+1);
+	   for(int ii=0; ii < m_loc; ii++){
+	     xaloc[ii] = xa[fst_row+ii]-xa[fst_row];	
+	   }
+	   
+	   xaloc[m_loc]=nnz_loc;
+	   
+	   fst_nnz = xa[fst_row];
+	   aloc    = (double*) doubleMalloc_dist(nnz_loc);
+	   asubloc = (int_t*)  intMalloc_dist(nnz_loc);
+	   
+	   for(int ii=0; ii < nnz_loc; ii++){
+	     aloc[ii] = a[fst_nnz+ii];
+	     asubloc[ii] = asub[fst_nnz+ii];
+	   }
+
+	   if( iam ){
+	     SUPERLU_FREE( a );
+	     SUPERLU_FREE( asub );
+	     SUPERLU_FREE( xa );
+	   }
+	   Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	   
+	   if(verbosity>6) cout << "Debut: Create_CompRowCol_Matrix_dist" <<endl;
+	   dCreate_CompRowLoc_Matrix_dist(&A, m, n, nnz_loc, m_loc, fst_row, aloc, asubloc, xaloc, SLU_NR_loc, R_SLU, SLU_GE);
+	   
+	   if(verbosity>6) cout << "Fin: Create_CompRowCol_Matrix_dist" <<endl;
+	   /* creation of pseudo solution + second member */
+	   
+	   
+	   if ( !(B = doubleMalloc_dist(m_loc)) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   
+	   for(int ii=0; ii < m_loc; ii++){
+	     B[ii] = 1.; //BB[fst_row+ii];
+	   }
+     
+	   if(verbosity >2 && rank ==0)
+	     printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   
+	   /* set the default options */
+	   //set_default_options_dist(&options);
+	   //DiagScale_t optionDiagScale;
+	   //if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	   	   
+	   m=A.nrow;
+	   n=A.ncol;
+	   //printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   /* Initialize ScalePermstruct and LUstruct. */
+	   ScalePermstructInit(m, n, &ScalePermstruct);
+	   if(pperm_r  ||  pperm_c ) ScalePermstruct.DiagScale=optionDiagScale;
+	   if(pperm_r) 
+	     for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[fst_row+ii];
+	   if(pperm_c) 
+	     for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii] = pperm_c[ii];
+	   
+	   LUstructInit(m, n, &LUstruct);
+	   
+	   /* Initialize the statistics variables. */
+	   PStatInit(&stat);
+	   
+	   ldb = m_loc;
+	   //ldx = m_loc;
+	   
+	   nrhs=1;
+	   if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   berr[0]=0.;
+	   
+	   /* ONLY PERFORM THE LU DECOMPOSITION */
+    
+	   nrhs=0;
+	   SuperLUmpiDISTDriver<R>::pgssvx(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					   &LUstruct, &SOLVEstruct, berr, &stat, &info);
+	   
+	   if(verbosity >1 && rank ==0)
+	     printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	   
+	   if ( verbosity > 2 ) PStatPrint(&options,&stat,&grid);
+	   PStatFree(&stat);
+	}
+	else if( matrixdist == distributed) {
+	  printf("in construction\n");
+	  exit(1);
+	}
+	else{
+	  printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	  exit(1);
+	}
+	
+	SUPERLU_FREE( B );
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	nrhs=1;
+	SUPERLU_FREE(berr);  	
+      
+	if(iam==0){
+	  finishtime = clock();
+	  timeused= (finishtime-starttime)/(1000 );
+	  if(verbosity>1)
+	    {
+	      
+	  printf("=====================================================\n");
+	  cout << "SuperLU_DIST : time factorisation :: " << timeused << " ms" <<endl;
+	  printf("=====================================================\n");
+	    }
+	}
+      }
+  }
+
+  void Solver(const MatriceMorse<R> &AA,KN_<R> &x,const KN_<R> &b) const  {
+    R*        B;
+    SuperLUStat_t  stat;
+    //int            iam;
+    int            info=0, ldb=m, nrhs=1;
+    int            i;
+    double*        berr;
+    double         ferr; 
+    double         rpg, rcond;
+      
+    int_t    m_loc,m_loc_fst,fst_row;
+    // time variable
+    long int starttime,finishtime;
+    long int timeused;
+
+    if( iam < nprow*npcol){
+
+      if(verbosity) starttime = clock();
+      
+      if(n != m) exit(1);
+      
+      ffassert ( &x[0] != &b[0]);
+      epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+      
+      Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+      nrhs= 1;
+      
+
+  
+      //iam = grid.iam;
+      //if( iam < nprow*npcol){
+      /* Initialize the statistics variables. */
+      PStatInit(&stat);
+      /* cas matrix assembled */ 
+      if( matrixdist == assembled ){
+	
+	if( !(B = doubleMalloc_dist(m*nrhs)) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	for(int ii=0; ii<n; ii++){
+	  B[ii]=b[ii];
+	}
+	
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */   
+	ldb = m;
+	//nrhs= 1;
+	SuperLUmpiDISTDriver<R>::pgssvx_ABglobal (&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+						  &LUstruct, berr, &stat, &info );
+	
+	if(verbosity>3)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if(verbosity) PStatPrint(&options, &stat, &grid);   
+	
+	for(int ii=0; ii<n; ii++){
+	  x[ii] = B[ii]; 
+	}
+	
+	if(verbosity>2) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+      }
+      else if( matrixdist == distributedglobal) {
+	double*    xtemp;
+	//iam = grid.iam;
+	/* Compute the number of rows to be distributed to local process */
+	m_loc = m / (grid.nprow * grid.npcol); 
+	m_loc_fst = m_loc;
+	/* When m / procs is not an integer */
+	if ((m_loc * grid.nprow * grid.npcol) != m) {
+	  /*m_loc = m_loc+1;
+	    m_loc_fst = m_loc;*/
+	  if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	    m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	}
+	
+	fst_row = iam * m_loc_fst;
+	
+	if ( !(B = doubleMalloc_dist(m_loc )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	//printf("initilisation B:");
+	for(int ii=0; ii<m_loc; ++ii){
+	  B[ii] = b[ii+fst_row];
+	  //printf("  B[%d]= %f  ",ii,B[ii]);
+	}
+	//printf(" :: fin \n");
+	//fflush(stdout);
+	
+      
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	//options.Equil = YES;
+	//options.Trans = TRANS;
+	
+	
+	ldb = m;
+	SuperLUmpiDISTDriver<R>::pgssvx(&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+					&LUstruct, &SOLVEstruct, berr, &stat, &info );
+	
+	if(verbosity>3)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if ( !(xtemp = doubleMalloc_dist(AA.n)) ){
+	  printf("probleme d allocation de xtemp\n");
+	  exit(1);
+	}
+	
+      
+	int disp[nprow*npcol];
+	MPI_Allgather(&fst_row, 1, MPI_INT, disp, 1, MPI_INT, grid.comm);
+	
+	int recv[nprow*npcol];
+	MPI_Allgather(&m_loc, 1, MPI_INT, recv, 1, MPI_INT, grid.comm);
+	
+	MPI_Allgatherv(B, m_loc, MPI_DOUBLE, xtemp, recv, disp, MPI_DOUBLE, grid.comm);
+	
+	for(int ii= 0; ii< AA.n ; ii++)
+	  x[ii] = xtemp[ii];
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+	SUPERLU_FREE( xtemp );
+      
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+      
+
+      SUPERLU_FREE( B );
+      SUPERLU_FREE( berr );
+      
+      PStatFree(&stat);
+   
+      if(iam==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	if(verbosity>1)
+	  {
+	    
+	  
+	printf("=====================================================\n");
+	cout << "SuperLu_DIST: time solve step :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+	  }
+      }
+    }
+    
+  }
+    
+  ~SolveSuperLUmpi() { 
+    //int iam;
+    //iam = grid.iam;
+    if(iam < nprow*npcol){
+      if(verbosity>4)
+	cout << "~SolveSuperLUmpi double:" << endl;
+      
+      if( matrixdist == assembled) {
+	//if( A.Store)  Destroy_CompCol_Matrix_dist(&A);
+	//if( L.Store && U.Store )  {
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	//}
+	if ( options.SolveInitialized ) {
+	  dSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributedglobal) {
+	Destroy_CompRowLoc_Matrix_dist(&A);
+	
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	
+	if ( options.SolveInitialized ) {
+	  dSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+    }
+    printf("Real superlu_gridexit(&grid), %d\n",iam);
+    superlu_gridexit(&grid); 
+    
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverSuperLUmpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverSuperLUmpi<double>" << endl;
+    return new SolveSuperLUmpi<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym,
+				       ds.data_filename, ds.sparams, ds.perm_r, ds.perm_c, ds.commworld);
+}
+
+
+/* --FH:   class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+
+    return false;
+}
+
+bool SetSuperLUmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to SuperLUmpi double" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverSuperLUmpi;
+    //DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+
+    return false;
+}
+
+
+
+
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: Real SuperLUdist,  defaultsolver defaultsolverSuperLUdist" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverSuperLUmpi;
+  //DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("realdefaulttoSuperLUdist","(",new OneOperator0<bool>(SetSuperLUmpi));
+}
+
+LOADFUNC(Load_Init)
diff --git a/examples++-mpi/real_pastix_FreeFem.cpp b/examples++-mpi/real_pastix_FreeFem.cpp
new file mode 100644
index 0000000..760f525
--- /dev/null
+++ b/examples++-mpi/real_pastix_FreeFem.cpp
@@ -0,0 +1,719 @@
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+//ff-c++-LIBRARY-dep: double_pastix   blas parmetis metis scotch  mpi fc
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+/*
+  Interface entre freefem++ et pastix
+*/
+#include <mpi.h>
+#include  <iostream>
+using namespace std;
+   
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+
+
+// #include <ctype.h>
+// #include <stdio.h>
+// #include <stdlib.h>
+// #include <unistd.h>
+// //#include <pthread.h>
+// #include <string.h>
+// #include <time.h>
+// #include <sys/time.h>
+// #include "mpi.h"
+   
+// #include <assert.h>
+// #include "pastix.h"
+// #include "cscd_utils.h"
+// #include "read_matrix.h"
+
+#include <assert.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "pastix.h"
+//#include "cscd_utils.h"
+#ifdef __cplusplus
+}
+#endif
+//#include "read_matrix.h"
+
+#undef memFree_null
+#define memFree_null(x) {if (x ==NULL) {fprintf(stdout,"%s:%d freeing NULL\n",__FILE__,__LINE__);} free(x); x=NULL;}
+
+#define STR_SIZE 256
+
+static pastix_int_t * pastixint(int * ii){ return (pastix_int_t*) (void *) ii;} 
+static pastix_float_t * pastixfloat(double * ii){ return (pastix_float_t*) (void *) ii;} 
+
+typedef struct pastix_param {
+  pastix_data_t          *pastix_data; /*Pointer used by PaStiX to keep information alive between calls */
+  MPI_Comm                comm;        /* Communicator used by PaStiX                                    */
+  pastix_int_t            Ncol;        /* Size of the Matrix                                             */
+  pastix_int_t           *ia;          /* Index of first element of each column in ja and avals          */  
+  pastix_int_t           *ja;          /* Rows of the unknows of the matrix                              */
+  pastix_float_t         *avals;       /* Values of the matrix                                           */
+  pastix_int_t           *perm;        /* Permutation used for re-numbering of the unknowns              */
+  pastix_int_t           *invp;        /* Inverse permutation                                            */
+  pastix_float_t         *rhs;         /* Right hand side                                                */
+  pastix_int_t           *iparm;       /* Integer parameters                                             */
+  double                 *dparm;       /* Floating parameters                                            */
+} pastix_param_t;
+
+
+
+void
+Morse_to_CSC(int m, int n, int nnz, 
+	     double *a, int *colind, int  *rowptr,
+	     pastix_float_t **at, pastix_int_t **rowind, 
+	     pastix_int_t **colptr)
+{
+    register int i, j, col, relpos;
+    pastix_int_t *marker;
+
+    /* Allocate storage for another copy of the matrix. */
+    *at     = (pastix_float_t *) malloc(sizeof(pastix_float_t)*nnz);
+    *rowind = (pastix_int_t *) malloc(sizeof(pastix_int_t)*nnz);
+    *colptr = (pastix_int_t *) malloc(sizeof(pastix_int_t)*(n+1));
+    marker  = (pastix_int_t *) malloc(sizeof(pastix_int_t)*n);
+    
+    for (i = 0; i < n; ++i)
+      marker[i] = 0;
+    /* Get counts of each column of A, and set up column pointers */
+    for (i = 0; i < m; ++i)
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) ++marker[colind[j]];
+    (*colptr)[0] = 0;
+    for (j = 0; j < n; ++j) {
+	(*colptr)[j+1] = (*colptr)[j] + marker[j];
+	marker[j] = (*colptr)[j];
+    }
+
+    /* Transfer the matrix into the compressed column storage. */
+    for (i = 0; i < m; ++i) {
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) {
+	    col = colind[j];
+	    relpos = marker[col];
+	    (*rowind)[relpos] = i;
+	    (*at)[relpos] = a[j];
+	    ++marker[col];
+	}
+    }
+
+    free(marker);
+}
+
+static const int MAX_CHAR_PER_LINE=256;
+//void read_datafile_pastixff(const string &datafile, pastix_int_t *iparmtab, double *dparmtab){
+void read_datafile_pastixff(const string &datafile, int &mpi_flag, pastix_int_t *iparmtab, double *dparmtab){
+  FILE*   m_File;
+  int     i = 0;
+  char    szbuff[MAX_CHAR_PER_LINE];
+  char*   token;
+  
+  char filename[datafile.size()+1];  
+  strcpy( filename, datafile.c_str()); 
+
+  m_File = fopen(filename,"rt");
+
+  if(!m_File)
+    {
+      printf("error in reading filename %s\n",filename);
+    }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  
+  if( !(strcmp(token,"matrix") == 0) ){
+    printf("freefem++: error in reading matrix parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading matrix parameter for pastix \n");    
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+  
+  if(strcmp(token,"assembled") == 0)
+    mpi_flag = 0;
+  else if(strcmp(token,"distributedglobal") == 0) 
+    mpi_flag = 1;
+  else if(strcmp(token,"distributed") == 0) 
+    mpi_flag = 2;
+  else{
+    printf("value of parameter matrix is not correct %s \n", token );
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  if( !(strcmp(token,"iparm") == 0) ){
+    printf("freefem++: error in reading iparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading iparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      iparmtab[i] = (pastix_int_t)atol(token);
+      i++;
+    }
+
+  i=0;
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");  
+  if( !(strcmp(token,"dparm") == 0) ){
+    printf("freefem++: error in reading dparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading dparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      dparmtab[i] = atof(token);
+      i++;
+    }
+ 
+  fclose(m_File);
+
+#ifdef OOC
+/*   if (iparmtab[IPARM_OOC_THREAD] > 1) */
+    iparmtab[IPARM_OOC_THREAD] = 1;
+#endif
+  /* On empeche le 2d avec NUMA_ALLOC */
+#ifdef NUMA_ALLOC
+  if (iparmtab[IPARM_DISTRIBUTION_LEVEL] != 0)
+    {
+      errorPrint("2D not available with NUMA allocation\n");
+      exit(-1);
+    }
+#endif
+}
+
+// ATTENTION :: pastix_float_t  
+//      peut �tre soit un complex ou un reel cela depend de la maniere dont on a compiler pastix
+
+// CAS DOUBLE SEULEMENT 
+
+
+
+class dSolvepastixmpi :   public MatriceMorse<double>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  
+
+  int paraoption;
+  int myid, mpi_size;
+  int Nrow;
+  int mpi_flag;
+  int init_raff;
+  int thrd_flag;
+  int SYM;
+  
+  string data_option;
+  
+  mutable pastix_int_t  iparm[64];
+  mutable double        dparm[64];
+  mutable pastix_int_t    Ncol;
+  mutable pastix_int_t   *ia;
+  mutable pastix_int_t   *ja;
+  mutable pastix_float_t *avals;
+  mutable pastix_int_t   *loc2glob;
+  //char           *Type    = NULL;
+  //char           *RhsType = NULL;
+  mutable pastix_float_t *rhs;
+  mutable pastix_int_t   *perm;
+  mutable pastix_int_t   *invp;
+  mutable pastix_data_t  *pastix_data;
+  MPI_Comm commworld ;
+
+public:
+
+  dSolvepastixmpi(const MatriceMorse<double> &AA, int strategy, double ttgv, double epsilon,
+		  double pivot, double pivot_sym, string datafile, KN<long> &pparam_int, KN<double> &pparam_double, 
+		  KN<long> &pperm_r, KN<long> &pperm_c,void * ccommworld ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),tol_pivot_sym(pivot_sym),tol_pivot(pivot),
+    data_option(datafile) 
+  { 
+    commworld = ccommworld ? *static_cast<MPI_Comm*>( ccommworld) : MPI_COMM_WORLD;    
+
+    KN_<long> param_int(pparam_int);
+    KN_<double> param_double(pparam_double);
+
+    //int m;
+    //int ierr;
+    struct timeval  tv1, tv2;
+    int nnz;
+   
+     // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+
+    ia    = NULL;
+    ja    = NULL;
+    avals   = NULL;
+    loc2glob = NULL;
+    rhs     = NULL;
+    pastix_data = NULL;
+    
+    // matrix assembled on host
+    MPI_Comm_rank(commworld, &myid);
+    printf("- Rang MPI : %d\n", myid);
+    MPI_Comm_size(commworld, &mpi_size);
+    // SYMETRIQUE
+    // MPI_flag need to unselect for non distributed matrix
+    mpi_flag  = 0;
+    thrd_flag = 0;
+
+    // ######################  
+    //pastix_int_t init_raff;
+    fprintf(stdout,"-- INIT PARAMETERS --\n");
+    
+    // reading iparm from array    
+    if(!data_option.empty()){
+      read_datafile_pastixff(data_option,mpi_flag,iparm,dparm);
+      if(mpi_flag != 0) 
+	cerr << "ERROR :: GLOBAT INPUT MATRIX FOR ALL PROCS  matrix=assembled" << endl;
+    }
+    else if( !(param_int==NULL) || !(param_double==NULL) ){
+      if( !(param_int==NULL) ) 
+      {
+	cout << "read param_int" << endl;
+	assert(param_int.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  iparm[ii] = param_int[ii];
+	iparm[IPARM_MODIFY_PARAMETER] = API_YES;
+      }
+      if( !(param_double==NULL) ) 
+      {
+	cout << "read param_double" << endl;
+	assert(param_double.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  dparm[ii] = param_double[ii];
+      }
+    }  
+    else{
+      iparm[IPARM_MODIFY_PARAMETER] = API_NO;
+      cout << "initialize parameter" << endl;
+    }
+    
+    //################################
+    if( myid==0 ){
+      Ncol = AA.m;
+      Nrow = AA.n;
+      nnz  = AA.nbcoef;
+
+      // Avant : on ecrit la transpos�e
+      
+      // AA.cl : indices des colonnes
+      // AA.lg : pointeurs des lignes
+      Morse_to_CSC( AA.n , AA.m, AA.nbcoef, AA.a, AA.cl, AA.lg, &avals, &ja, &ia);
+      // ia : pointeurs des colonnes
+      // ja : indices des lignes
+      if(verbosity)
+      cout << "AA.n= "<< AA.n << " AA.m=" <<  AA.m << " AA.nbcoef=" << AA.nbcoef << endl;
+    
+     
+      for(int ii=0; ii < Ncol+1; ii++){
+	ia[ii] = ia[ii]+1;
+      }
+      assert( ia[Ncol]-1 == AA.nbcoef );
+      for(int ii=0; ii < ia[Ncol]-1; ii++){
+	ja[ii] = ja[ii]+1; 
+      }
+      //cout << " put  " << Ncol << " " << Nrow << " " << nnz << endl;            
+      MPI_Bcast( &Ncol,   1,    MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast( &Nrow,   1,    MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast( &nnz,    1,    MPI_PASTIX_INT,   0, commworld );
+
+      MPI_Bcast( avals, nnz,    MPI_PASTIX_FLOAT, 0, commworld );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, commworld );
+    }
+    else{
+      MPI_Bcast( &Ncol, 1,        MPI_PASTIX_INT,  0, commworld );
+      MPI_Bcast( &Nrow, 1,        MPI_PASTIX_INT,  0, commworld );
+      MPI_Bcast( &nnz,  1,        MPI_PASTIX_INT,  0, commworld );
+      //cout << " get " << Ncol << " " << Nrow << " " << nnz << endl;
+      avals = (pastix_float_t *) malloc( nnz*sizeof(pastix_float_t) );
+      ia = (pastix_int_t *) malloc( (Ncol+1)*sizeof(pastix_int_t) );
+      ja = (pastix_int_t *) malloc( nnz*sizeof(pastix_int_t) );
+
+      MPI_Bcast( avals, nnz,  MPI_PASTIX_FLOAT,   0, commworld );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, commworld );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, commworld );
+    }
+    //cout << " " << Ncol << " " << endl; 
+    perm = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    invp = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    
+    rhs = (pastix_float_t *) malloc(Ncol*sizeof(pastix_float_t));
+    
+    // reading permutation given by the user
+    if(pperm_r) 
+      for(int ii=0; ii < Ncol; ii++)
+	perm[ii] = pperm_r[ii];
+    if(pperm_c)  
+      for(int ii=0; ii < Ncol; ii++)
+	invp[ii] = pperm_c[ii];
+
+      
+    iparm[IPARM_START_TASK] = API_TASK_INIT;
+    iparm[IPARM_END_TASK]   = API_TASK_INIT;
+    iparm[IPARM_SYM] = API_SYM_NO; // Matrix is considered nonsymetric    
+
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm); 
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    fprintf(stdout,"-- FIN INIT PARAMETERS --\n");
+    init_raff = iparm[IPARM_ITERMAX];
+    
+    fflush(stdout);
+    /* Passage en mode verbose */
+    
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    if( (param_int==NULL) && data_option.empty() ){
+      iparm[IPARM_MATRIX_VERIFICATION] = API_YES;
+      iparm[IPARM_REFINEMENT] = API_RAF_GMRES;
+      iparm[IPARM_INCOMPLETE] = API_NO;
+    }
+
+    if( (param_double==NULL) && data_option.empty()){
+      dparm[DPARM_EPSILON_REFINEMENT] = 1e-12;
+      dparm[DPARM_EPSILON_MAGN_CTRL] = 1e-32;
+    }
+
+//    cscd_checksym(Ncol, ia, ja, loc2glob, commworld);
+    
+//     if (iparm[IPARM_SYM]==API_SYM_YES)
+//       {
+// 	/* Symetric problem */
+// 	/* Build non oriented graph */
+// 	/* build non symmetric csc from symmetric csc */
+// 	/*maillage global*/
+// 	INT *tmpia;
+// 	INT *tmpja;
+// 	INT  tmpn;
+	
+// 	cscd_symgraph_int(*n2,   *col2,  *row2 , NULL,
+// 			  &tmpn, &tmpia, &tmpja, NULL,
+// 			  *loc2glob2, pastix_comm, API_YES);
+	
+// 	memFree_null(*col2);
+// 	*col2 = tmpia;
+// 	memFree_null(*row2);
+// 	*row2 = tmpja;
+// 	*n2   = tmpn;
+//       }
+    
+
+    SYM = AA.symetrique; 
+    cout << "SYM = "<< SYM << endl;
+    // SYMETRIQUE
+    if( SYM == 1 ){
+      iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    
+    /* Scotch */
+    fprintf(stdout,"-- Scotch --\n");
+    fflush(stdout);
+    iparm[IPARM_START_TASK] = API_TASK_ORDERING;
+    iparm[IPARM_END_TASK]   = API_TASK_ORDERING; 
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl;  
+    iparm[IPARM_SYM] = API_SYM_NO;
+    /* Fax */
+    fprintf(stdout,"-- Fax --\n");
+    iparm[IPARM_START_TASK] = API_TASK_SYMBFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_SYMBFACT;
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    /* Blend */
+    fprintf(stdout,"-- Blend --\n");
+    iparm[IPARM_START_TASK] = API_TASK_ANALYSE;
+    iparm[IPARM_END_TASK]   = API_TASK_ANALYSE;
+    if( SYM == 1 ){
+      //iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      //iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+   
+    /* Factorisation */
+    iparm[IPARM_START_TASK] = API_TASK_NUMFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_NUMFACT;
+    gettimeofday(&tv1, NULL);
+    fprintf(stdout,"-- SOPALIN --\n");
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+       cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call factorization : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+    
+   
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    
+    if(verbosity)
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000);
+	printf("=====================================================\n");
+	cout << " pastix : time factorization  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+  }
+  void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+  
+    struct timeval  tv1, tv2;
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+    
+
+    // index for pastix    
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]+1;
+    assert( ia[Ncol]-1 == AA.nbcoef );
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]+1;
+    
+    
+    // give value of the second member
+    for(int ii=0; ii < Ncol; ii++){
+      rhs[ii] = b[ii];  
+    }
+    
+    
+
+    //fprintf(stdout,"SOLVE STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    
+    /* updo */
+    iparm[IPARM_START_TASK] = API_TASK_SOLVE;
+    iparm[IPARM_END_TASK]   = API_TASK_SOLVE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call updown : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));    
+    
+    //if(verbosity > 1)
+    //  for(int jj=0; jj < Ncol; jj++)
+    //cout << "rhs["<< jj << "]=" << rhs[jj] << endl;
+    
+    
+    //fprintf(stdout,"RAFF STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    /* raff */
+    
+    
+    iparm[IPARM_START_TASK] = API_TASK_REFINE;
+    iparm[IPARM_END_TASK]   = API_TASK_REFINE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    iparm[IPARM_ITERMAX]    = init_raff;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call refinement : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+
+    
+    for(int ii=0; ii < Ncol; ii++)
+      x[ii] = rhs[ii];
+       
+    // index for freefem
+    assert( ia[Ncol]-1 == AA.nbcoef );
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+
+    if(verbosity)
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << " pastix : time solve  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+  
+  }
+
+  ~dSolvepastixmpi(){
+    /* mem free */
+    iparm[IPARM_START_TASK] = API_TASK_CLEAN;
+    iparm[IPARM_END_TASK]   = API_TASK_CLEAN;
+    
+    pastix(&pastix_data, commworld, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+      
+    //if( sizeof(pastix_int_t) != sizeof(int) )
+    //  {
+    memFree_null(ia);
+    memFree_null(ja);
+    //}
+    memFree_null(avals);
+    /* Free mem no longer necessary */
+    memFree_null(perm);
+    memFree_null(invp);
+    memFree_null(rhs);
+    
+  
+    
+  }
+  
+  void addMatMul(const KN_<double> & x, KN_<double> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<double> &) (*this) * x; 
+  }
+
+};
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverpastix_real_mpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverpastix_real_mpi<double>" << endl;
+    return new dSolvepastixmpi(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym, ds.data_filename, 
+			       ds.lparams, ds.dparams, ds.perm_r, ds.perm_c, ds.commworld);
+}
+
+
+/* --FH:   class Init { public:
+    Init();
+    };*/
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+    return false;
+}
+
+bool Setpastixmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to pastixmpi" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverpastix_real_mpi;
+    //DefSparseSolver<Complex>::solver =BuildSolverpastix_real_mpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+    return false;
+}
+
+
+
+
+static void Load_Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: pastix,  defaultsolver defaultsolverpastix" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverpastix_real_mpi;
+  //DefSparseSolver<Complex>::solver =BuildSolverpastix_real_mpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("realdefaulttopastix","(",new OneOperator0<bool>(Setpastixmpi));
+}
+ LOADFUNC(Load_Init)
diff --git a/examples++-mpi/regtests.sh b/examples++-mpi/regtests.sh
new file mode 100755
index 0000000..7a583d3
--- /dev/null
+++ b/examples++-mpi/regtests.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Testing procedure for MPI version of FreeFem++
+# $Id$
+
+NPROCS=2 REGEDP=essai.edp ../regtests.sh
+if test $? != 0
+    then
+    exit 1
+fi
+NPROCS=2 REGEDP=schwarz.edp ../regtests.sh
+if test $? != 0
+    then
+    exit 1
+fi
+NPROCS=2 REGEDP=schwarz-b.edp ../regtests.sh
+if test $? != 0
+    then
+    exit 1
+fi
+NPROCS=2 REGEDP=schwarz-c.edp ../regtests.sh
+if test $? != 0
+    then
+    exit 1
+fi
+NPROCS=4 REGEDP=mortar-DN-4-mpi.edp ../regtests.sh
+if test $? != 0
+    then
+    exit 1
+fi
+
diff --git a/examples++-mpi/removeDOF.cpp b/examples++-mpi/removeDOF.cpp
new file mode 100644
index 0000000..0e6d122
--- /dev/null
+++ b/examples++-mpi/removeDOF.cpp
@@ -0,0 +1,274 @@
+#ifndef _ALL_IN_ONE_
+#include "ff++.hpp"
+#include <algorithm>
+#include <vector>
+#include <cmath>
+#endif
+#include <utility>
+
+#ifndef EPS
+#define EPS 1e-12
+#endif
+
+template<class T>
+class removeDOF_Op : public E_F0mps {
+    public:
+        Expression A;
+        Expression R;
+        Expression x;
+        Expression out;
+        static const int n_name_param = 3;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        removeDOF_Op(const basicAC_F0&  args, Expression param1, Expression param2, Expression param3, Expression param4) : A(param1), R(param2), x(param3), out(param4) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+
+        AnyType operator()(Stack stack) const;
+};
+
+template<class T>
+basicAC_F0::name_and_type removeDOF_Op<T>::name_param[] = {
+    {"symmetrize", &typeid(bool)},
+    {"condensation", &typeid(KN<long>*)},
+    {"interaction", &typeid(Matrice_Creuse<T>*)}
+};
+
+template<class T>
+class removeDOF : public OneOperator {
+    public:
+        removeDOF() : OneOperator(atype<long>(), atype<Matrice_Creuse<T>*>(), atype<Matrice_Creuse<double>*>(), atype<KN<T>*>(), atype<KN<T>*>()) {}
+
+        E_F0* code(const basicAC_F0& args) const {
+            return new removeDOF_Op<T>(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]), t[2]->CastTo(args[2]), t[3]->CastTo(args[3]));
+        }
+};
+
+template<class T>
+AnyType removeDOF_Op<T>::operator()(Stack stack)  const {
+    Matrice_Creuse<T>* pA = GetAny<Matrice_Creuse<T>* >((*A)(stack));
+    Matrice_Creuse<T>* pR = GetAny<Matrice_Creuse<T>* >((*R)(stack));
+    KN<T>* pX = GetAny<KN<T>* >((*x)(stack));
+    KN<T>* pOut = GetAny<KN<T>* >((*out)(stack));
+    ffassert(pA && pR && pX && pOut);
+    pA->Uh = pR->Uh;
+    pA->Vh = pR->Vh;
+    MatriceMorse<T> *mA = static_cast<MatriceMorse<T>*>(&(*pA->A));
+    MatriceMorse<T> *mR = static_cast<MatriceMorse<T>*>(&(*pR->A));
+    bool symmetrize = nargs[0] ? GetAny<bool>((*nargs[0])(stack)) : false;
+    KN<long>* condensation = nargs[1] ? GetAny<KN<long>* >((*nargs[1])(stack)) : (KN<long>*) 0;
+
+    unsigned int n = condensation ? condensation->n : mR->nbcoef;
+    int* lg = new int[n + 1];
+    int* cl;
+    T* val;
+    T* b;
+    if(pOut->n == 0) {
+        b = new T[n];
+        pOut->set(b, n);
+    }
+
+    std::vector<signed int> tmpVec;
+    if(!condensation) {
+        tmpVec.resize(mA->n);
+        for(unsigned int i = 0; i < n; ++i)
+            tmpVec[mR->cl[i]] = i + 1;
+        if(!mA->symetrique) {
+            std::vector<std::pair<int, T> > tmp;
+            tmp.reserve(mA->nbcoef);
+
+            lg[0] = 0;
+            for(unsigned int i = 0; i < n; ++i) {
+                for(unsigned int j = mA->lg[mR->cl[i]]; j < mA->lg[mR->cl[i] + 1]; ++j) {
+                    unsigned int col = tmpVec[mA->cl[j]];
+                    if(col != 0 && abs(mA->a[j]) > EPS) {
+                        if(symmetrize) {
+                            if(col - 1 <= i)
+                                tmp.emplace_back(col - 1, mA->a[j]);
+                        }
+                        else
+                            tmp.emplace_back(col - 1, mA->a[j]);
+                    }
+                }
+                std::sort(tmp.begin() + lg[i], tmp.end(), [](const std::pair<unsigned int, T>& lhs, const std::pair<unsigned int, T>& rhs) { return lhs.first < rhs.first; });
+                *(*pOut + i) = *(*pX + mR->cl[i]);
+                lg[i + 1] = tmp.size();
+            }
+            mA->nbcoef = tmp.size();
+            if(symmetrize)
+                mA->symetrique = true;
+            else
+                mA->symetrique = false;
+
+            cl = new int[tmp.size()];
+            val = new T[tmp.size()];
+
+            for(unsigned int i = 0; i < tmp.size(); ++i) {
+                cl[i]  = tmp[i].first;
+                val[i] = tmp[i].second;
+            }
+        }
+        else {
+            std::vector<std::vector<std::pair<unsigned int, T> > > tmp(n);
+            for(unsigned int i = 0; i < n; ++i)
+                tmp[i].reserve(mA->lg[mR->cl[i] + 1] - mA->lg[mR->cl[i]]);
+
+            unsigned int nnz = 0;
+            for(unsigned int i = 0; i < n; ++i) {
+                for(unsigned int j = mA->lg[mR->cl[i]]; j < mA->lg[mR->cl[i] + 1]; ++j) {
+                    unsigned int col = tmpVec[mA->cl[j]];
+                    if(col != 0 && abs(mA->a[j]) > EPS) {
+                        if(i < col - 1)
+                            tmp[col - 1].emplace_back(i, mA->a[j]);
+                        else
+                            tmp[i].emplace_back(col - 1, mA->a[j]);
+                        ++nnz;
+                    }
+                }
+                *(*pOut + i) = *(*pX + mR->cl[i]);
+            }
+            mA->nbcoef = nnz;
+            cl = new int[nnz];
+            val = new T[nnz];
+            nnz = 0;
+            lg[0] = 0;
+            for(unsigned int i = 0; i < n; ++i) {
+                std::sort(tmp[i].begin(), tmp[i].end(), [](const std::pair<unsigned int, T>& lhs, const std::pair<unsigned int, T>& rhs) { return lhs.first < rhs.first; });
+                for(typename std::vector<std::pair<unsigned int, T> >::const_iterator it = tmp[i].begin(); it != tmp[i].end(); ++it) {
+                    cl[nnz] = it->first;
+                    val[nnz++] = it->second;
+                }
+                lg[i + 1] = nnz;
+            }
+
+        }
+        delete [] mA->cl;
+        delete [] mA->lg;
+        delete [] mA->a;
+        mA->n = n;
+        mA->m = n;
+        mA->N = n;
+        mA->M = n;
+        mA->lg = lg;
+        mA->cl = cl;
+        mA->a = val;
+    }
+    else {
+        tmpVec.reserve(mA->n);
+        unsigned int i = 0, j = 1;
+        for(unsigned int k = 0; k < mA->n; ++k) {
+            if(k == *(*condensation + i)) {
+                ++i;
+                tmpVec.emplace_back(i);
+            }
+            else {
+                tmpVec.emplace_back(-j);
+                ++j;
+            }
+        }
+
+
+//        if(!mA->symetrique) {
+            std::vector<std::pair<int, T> > tmpInterior;
+            std::vector<std::pair<int, T> > tmpBoundary;
+            std::vector<std::pair<int, T> > tmpInteraction;
+            tmpInterior.reserve(mA->nbcoef);
+            tmpBoundary.reserve(mA->nbcoef);
+            tmpInteraction.reserve(mA->nbcoef);
+
+            lg[0] = 0;
+            for(unsigned int i = 0; i < mA->n; ++i) {
+                int row = tmpVec[i];
+                if(row < 0) {
+                    for(unsigned int j = mA->lg[i]; j < mA->lg[i + 1]; ++j) {
+                        int col = tmpVec[mA->cl[j]];
+                        if(col < 0)
+                            tmpInterior.emplace_back(-col - 1, mA->a[j]);
+                        else
+                            tmpInteraction.emplace_back(col - 1, mA->a[j]);
+                    }
+
+                }
+                else {
+                    for(unsigned int j = mA->lg[i]; j < mA->lg[i + 1]; ++j) {
+                        int col = tmpVec[mA->cl[j]];
+                        if(col > 0)
+                            tmpBoundary.emplace_back(col - 1, mA->a[j]);
+                    }
+                    // std::sort(tmp.begin() + lg[i], tmp.end());
+                    *(*pOut + i) = *(*pX + *(*condensation + i));
+                    lg[i + 1] = tmpBoundary.size();
+                }
+            }
+            cl = new int[tmpBoundary.size()];
+            val = new T[tmpBoundary.size()];
+            for(unsigned int i = 0; i < tmpBoundary.size(); ++i) {
+                cl[i]  = tmpBoundary[i].first;
+                val[i] = tmpBoundary[i].second;
+            }
+//        }
+        MatriceMorse<T>* m = new MatriceMorse<T>(n, n, tmpBoundary.size(), mA->symetrique, val, lg, cl, true);
+        pR->typemat = TypeSolveMat(TypeSolveMat::GMRES);
+        pR->A.master(m);
+        m->dummy = false;
+    }
+    return 0L;
+}
+
+template<class T>
+long symmetrizeCSR(Matrice_Creuse<T>* const& A) {
+    MatriceMorse<T>* mA = static_cast<MatriceMorse<T>*>(&(*A->A));
+    if(!mA->symetrique) {
+        mA->symetrique = true;
+        std::vector<int> cl;
+        std::vector<T> a;
+        a.reserve(mA->nbcoef);
+        cl.reserve(mA->nbcoef);
+        unsigned int save = mA->lg[0];
+        for(unsigned int i = 0; i < mA->n; ++i) {
+            for(unsigned int j = save; j < mA->lg[i + 1]; ++j) {
+                int col = mA->cl[j];
+                if(col <= i) {
+                    T val = mA->a[j];
+                    if(abs(val) > EPS) {
+                        a.emplace_back(val);
+                        cl.emplace_back(col);
+                    }
+                }
+                else
+                    break;
+            }
+            save = mA->lg[i + 1];
+            mA->lg[i + 1] = cl.size();
+        }
+        delete [] mA->cl;
+        delete [] mA->a;
+        int* col = new int[cl.size()];
+        T* val = new T[cl.size()];
+        for(unsigned int i = 0; i < cl.size(); ++i) {
+            col[i] = cl[i];
+            val[i] = a[i];
+        }
+        mA->cl = col;
+        mA->a = val;
+        mA->nbcoef = cl.size();
+    }
+    return 0L;
+}
+
+#ifndef _ALL_IN_ONE_
+/* --FH:   class Init {
+    public:
+        Init();
+	};
+Init ...; */
+static void Load_Initrm() {
+    Global.Add("removeDOF", "(", new removeDOF<double>);
+    Global.Add("removeDOF", "(", new removeDOF<std::complex<double>>);
+    Global.Add("symmetrizeCSR", "(", new OneOperator1_<long, Matrice_Creuse<double>* >(symmetrizeCSR<double>));
+}
+ LOADFUNC(Load_Initrm)
+#endif
+
+// std::sort(tmp.begin() + lg[i], tmp.end(), [](const std::pair<int, T>& lhs, const std::pair<int, T>& rhs) { return lhs.first < rhs.first; } );
+
diff --git a/examples++-mpi/schwarz-2d.edp b/examples++-mpi/schwarz-2d.edp
new file mode 100644
index 0000000..f7c36e5
--- /dev/null
+++ b/examples++-mpi/schwarz-2d.edp
@@ -0,0 +1,68 @@
+if ( mpisize != 2 ) {
+cout << " sorry number of processeur !=2 " << endl;
+exit(1);}
+verbosity=3;
+real pi=4*atan(1);
+int inside = 2;
+int outside = 1;
+border a(t=1,2){x=t;y=0;label=outside;};
+border b(t=0,1){x=2;y=t;label=outside;};
+border c(t=2,0){x=t ;y=1;label=outside;};
+border d(t=1,0){x = 1-t; y = t;label=inside;};
+border e(t=0, pi/2){ x= cos(t); y = sin(t);label=inside;};
+border e1(t=pi/2, 2*pi){ x= cos(t); y = sin(t);label=outside;}; 
+int n=4;
+mesh th,TH;
+
+if (mpirank == 0) 
+ {
+ th = buildmesh( a(5*n) + b(5*n) + c(10*n) + d(5*n));
+ cout << " end th  " << endl;
+// processor(1) << th ;
+// processor(1) >> TH;
+}
+else
+ {
+ TH = buildmesh ( e(5*n) + e1(25*n) );
+ cout << " end TH  " << endl;
+// processor(0) << TH ;
+// processor(0) >> th;
+ }
+broadcast(processor(0),th);
+broadcast(processor(1),TH);
+
+
+
+fespace vh(th,P1);
+fespace VH(TH,P1);
+vh u=0,v; VH U,V;
+int i=0;
+
+problem PB(U,V,init=i,solver=Cholesky) = 
+    int2d(TH)( dx(U)*dx(V)+dy(U)*dy(V) )
+  + int2d(TH)( -V) + on(inside,U = u)  +    on(outside,U= 0 ) ;
+problem pb(u,v,init=i,solver=Cholesky) = 
+    int2d(th)( dx(u)*dx(v)+dy(u)*dy(v) )
+  + int2d(th)( -v) + on(inside ,u = U) +    on(outside,u = 0 ) ;
+
+
+for ( i=0 ;i< 10; i++) 
+{ 
+  cout << mpirank << " looP " << i << endl;
+  if (mpirank == 0)
+  {   
+   PB;
+   processor(1) << U[];
+   processor(1) >> u[];
+  }
+  else 
+  {
+   pb;
+   processor(0) >> U[];
+   processor(0) << u[];
+  }
+  //  if (mpirank==0)  
+  // plot(U,u,wait=true,ps="Uu"+i+".eps");
+};
+ if (mpirank==0)  
+    plot(U,u,ps="Uu.eps");
diff --git a/examples++-mpi/schwarz-3.edp b/examples++-mpi/schwarz-3.edp
new file mode 100644
index 0000000..7462366
--- /dev/null
+++ b/examples++-mpi/schwarz-3.edp
@@ -0,0 +1,93 @@
+/* to run : in a Shell.  cut and past:
+cd /Users/hecht/work/freefem++/examples++-mpi 
+mpirun -np 2 FreeFem++-mpi schwarz-3.edp -glut ffglut
+*/
+load "msh3"
+if ( mpisize != 2 ) {
+cout << " sorry number of processeur !=2 " << endl;
+exit(1);}
+verbosity=4;
+real pi=4*atan(1);
+int inside = 2;
+int outside = 1;
+real zmin =0, zmax=1;
+border a(t=1,2){x=t;y=0;label=outside;};
+border b(t=0,1){x=2;y=t;label=outside;};
+border c(t=2,0){x=t ;y=1;label=outside;};
+border d(t=1,0){x = 1-t; y = t;label=inside;};
+border e(t=0, pi/2){ x= cos(t); y = sin(t);label=inside;};
+border e1(t=pi/2, 2*pi){ x= cos(t); y = sin(t);label=outside;}; 
+int n=4;
+mesh th2,TH2;
+mesh3 th,TH;
+int[int] rup=[0,0], rdown=[0,0], rmid=[outside,outside,inside,inside];;
+if (mpirank == 0) 
+ {
+ th2 = buildmesh( a(5*n) + b(5*n) + c(10*n) + d(5*n));
+ th =  buildlayers(th2,n,
+	     zbound=[zmin,zmax],  labelmid=rmid, 
+	     reffaceup = rup,     reffacelow = rdown);
+
+ cout << " end th  " << endl;
+}
+else
+ {
+ TH2 = buildmesh ( e(5*n) + e1(25*n) );
+ TH =  buildlayers(TH2,n,
+	     zbound=[zmin,zmax],  labelmid=rmid, 
+	     reffaceup = rup,     reffacelow = rdown);
+
+ cout << " end TH  " << endl;
+ }
+broadcast(processor(0),th);
+broadcast(processor(1),TH);
+
+
+fespace vh(th,P1);
+fespace VH(TH,P1);
+fespace ph(th,P1);
+fespace PH(TH,P1);
+vh u=0,v; VH U,V;
+ph chi=1;
+PH CHI=1;
+int i=0;
+
+problem PB(U,V,init=i,solver=CG) = 
+  int3d(TH)( dx(U)*dx(V)+dy(U)*dy(V) +dz(U)*dz(V))
+  + int3d(TH)( -V) + on(inside,U = u)  +    on(outside,U= 0 ) ;
+problem pb(u,v,init=i,solver=CG) = 
+    int3d(th)( dx(u)*dx(v)+dy(u)*dy(v)+dz(u)*dz(v) )
+  + int3d(th)( -v) + on(inside ,u = U) +    on(outside,u = 0 ) ;
+
+
+for ( i=0 ;i< 10; i++) 
+{ 
+  cout << mpirank << " looP " << i << endl;
+  if (mpirank == 0)
+  {   
+   PB;
+   processor(1) << U[];
+   processor(1) >> u[];
+  }
+  else 
+  {
+   pb;
+   processor(0) << u[];
+   processor(0) >> U[];
+  }
+  if (mpirank==0)     plot(U,u,wait=1,fill=1);
+  
+  if(mpirank==0)
+    {
+      real ERR= int3d(TH)( square(U-u)*CHI*chi) ;
+      cout << " ERR= " << ERR<< endl;
+    }
+  else
+    {
+      real err= int3d(th)( square(U-u)*CHI*chi) ;
+      cout << " err= " << err<< endl;
+    }
+  
+};
+ if (mpirank==0)  
+    plot(U,u,ps="Uu.eps",fill=1);
diff --git a/examples++-mpi/schwarz-b.edp b/examples++-mpi/schwarz-b.edp
new file mode 100644
index 0000000..9d207b2
--- /dev/null
+++ b/examples++-mpi/schwarz-b.edp
@@ -0,0 +1,71 @@
+//  a new coding  methode de schwarz 
+//  -------------------------------
+// F.Hecht december 2003
+// ----------------------------------
+//  to test the broadcast instruction 
+//  add add the stop test 
+//  ---------------------------------
+// NBPROC 2
+
+if ( mpisize != 2 ) {
+cout << " sorry number of processeur !=2 " << endl;
+exit(1);}
+verbosity=3;
+real pi=4*atan(1);
+int inside = 2;
+int outside = 1;
+border a(t=1,2){x=t;y=0;label=outside;};
+border b(t=0,1){x=2;y=t;label=outside;};
+border c(t=2,0){x=t ;y=1;label=outside;};
+border d(t=1,0){x = 1-t; y = t;label=inside;};
+border e(t=0, pi/2){ x= cos(t); y = sin(t);label=inside;};
+border e1(t=pi/2, 2*pi){ x= cos(t); y = sin(t);label=outside;}; 
+int n=4;
+mesh Th0,Th1;
+
+if (mpirank == 0) 
+ Th0 = buildmesh( a(5*n) + b(5*n) + c(10*n) + d(5*n));
+else
+ Th1 = buildmesh ( e(5*n) + e1(25*n) );
+
+broadcast(processor(0),Th0);
+broadcast(processor(1),Th1);
+
+fespace Vh1(Th1,P1);
+fespace Vh0(Th0,P1);
+Vh0 u0,v0;	
+Vh1 u1=0,v1;
+
+int i=0;
+
+problem pb0(u0,v0,init=i,solver=Cholesky) = 
+    int2d(Th0)( dx(u0)*dx(v0)+dy(u0)*dy(v0) )
+  + int2d(Th0)( -v0) + on(inside,u0 = u1)  +    on(outside,u0= 0 ) ;
+
+problem pb1(u1,v1,init=i,solver=Cholesky) = 
+    int2d(Th1)( dx(u1)*dx(v1)+dy(u1)*dy(v1) )
+  + int2d(Th1)( -v1) + on(inside ,u1 = u0) +    on(outside,u1 = 0 ) ;
+
+
+for ( i=0 ;i< 20; i++) 
+{ 
+  cout << mpirank << " looP " << i << endl;
+  if (mpirank == 0)
+    pb0; 
+   else
+    pb1;
+   broadcast(processor(0),u0[]);
+   broadcast(processor(1),u1[]);
+   real err0,err1;
+   if (mpirank == 0)
+     err0 = int1d(Th0,inside)(square(u0-u1)) ;
+   else 
+     err1= int1d(Th1,inside)(square(u0-u1)) ;
+   broadcast(processor(0),err0);
+   broadcast(processor(1),err1);  
+   real err= sqrt(err0+err1);
+   cout <<" err = " << err << " err0 = " << err0 << ", err1 = " << err1 << endl;
+   if(err<1e-3) break;
+};
+ if (mpirank==0)  
+    plot(u0,u1,ps="u0-u1.eps");
diff --git a/examples++-mpi/schwarz-c.edp b/examples++-mpi/schwarz-c.edp
new file mode 100644
index 0000000..dec44be
--- /dev/null
+++ b/examples++-mpi/schwarz-c.edp
@@ -0,0 +1,60 @@
+// NBPROC 2
+//  a new coding  methode de schwarz 
+// with 2 proc. 
+//  -------------------------------
+// F.Hecht december 2003
+// ----------------------------------
+//  to test the broadcast instruction 
+//  and array of mesh 
+//  add add the stop test 
+//  ---------------------------------
+
+if ( mpisize != 2 ) {
+cout << " sorry, number of processors !=2 " << endl;
+exit(1);}
+verbosity=3;
+int interior = 2;
+int exterior = 1;
+border a(t=1,2){x=t;y=0;label=exterior;};
+border b(t=0,1){x=2;y=t;label=exterior;};
+border c(t=2,0){x=t ;y=1;label=exterior;};
+border d(t=1,0){x = 1-t; y = t;label=interior;};
+border e(t=0, pi/2){ x= cos(t); y = sin(t);label=interior;};
+border e1(t=pi/2, 2*pi){ x= cos(t); y = sin(t);label=exterior;}; 
+int n=4;
+mesh[int]  Th(mpisize);
+if (mpirank == 0) 
+ Th[0] = buildmesh( a(5*n) + b(5*n) + c(10*n) + d(5*n));
+else
+ Th[1] = buildmesh ( e(5*n) + e1(25*n) );
+
+broadcast(processor(0),Th[0]);
+broadcast(processor(1),Th[1]);
+
+fespace Vh(Th[mpirank],P1);
+fespace Vhother(Th[1-mpirank],P1);
+
+Vh u=0,v;
+Vhother U=0;
+int i=0;
+
+problem pb(u,v,init=i,solver=Cholesky) = 
+    int2d(Th[mpirank])( dx(u)*dx(v)+dy(u)*dy(v) )
+  + int2d(Th[mpirank])( -v) + on(interior,u = U)  +    on(exterior,u= 0 ) ;
+
+for ( i=0 ;i< 20; i++) 
+{ 
+  cout << mpirank << " looP " << i << endl;
+   pb; 
+   //  send u  to the other proc, receive in U
+   processor(1-mpirank) << u[];    processor(1-mpirank) >> U[];
+   real err0,err1;
+   err0 = int1d(Th[mpirank],interior)(square(U-u)) ;
+   // send err0  to the other proc, receive in err1
+   processor(1-mpirank)<<err0;   processor(1-mpirank)>>err1;
+   real err= sqrt(err0+err1);
+   cout <<" err = " << err << " err0 = " << err0 << ", err1 = " << err1 << endl;
+   if(err<1e-3) break;
+};
+if (mpirank==0)  
+    plot(u,U,ps="uU.eps");
diff --git a/examples++-mpi/schwarz.cpp b/examples++-mpi/schwarz.cpp
new file mode 100644
index 0000000..4d8a883
--- /dev/null
+++ b/examples++-mpi/schwarz.cpp
@@ -0,0 +1,445 @@
+//ff-c++-LIBRARY-dep:   hpddm  umfpack amd mumps scalapack blas [mkl]   mpifc  fc mpi  pthread   [petsc]
+//ff-c++-cpp-dep: 
+
+#ifdef WITH_mkl
+#include <complex>
+#define MKL_Complex16 std::complex<double>
+#define MKL_Complex8 std::complex<float>
+#define MKL_INT int
+#include <mkl.h>
+#endif
+
+
+#ifndef WITH_PETSC 
+#pragma message("schwarz plugin compile without PETSc")
+#endif
+
+#define HPDDM_BDD  0
+#define HPDDM_FETI 0
+
+
+#include <math.h>
+#include <mpi.h>
+#include <ff++.hpp>
+#include "AFunction_ext.hpp"
+#include <HPDDM.hpp>
+
+template<class T>
+class STL {
+    T* const _it;
+    const int _size;
+    public:
+        STL(const KN<T>& v) : _it(v), _size(v.size()) { };
+        int size() const {
+            return _size;
+        }
+        T* begin() const {
+            return _it;
+        }
+        T* end() const {
+            return _it + _size;
+        }
+};
+template<class K>
+class Pair {
+    public:
+        Pair() : p() { };
+        std::pair<MPI_Request, const K*>* p;
+        void init() {
+        }
+        void destroy() {
+        }
+};
+
+#ifdef WITH_PETSC
+#include "PETSc.hpp"
+#endif
+
+namespace Schwarz {
+template<class Type, class K>
+class initDDM_Op : public E_F0mps {
+    public:
+        Expression A;
+        Expression Mat;
+        Expression o;
+        Expression R;
+        static const int n_name_param = 3;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        initDDM_Op(const basicAC_F0& args, Expression param1, Expression param2, Expression param3, Expression param4) : A(param1), Mat(param2), o(param3), R(param4) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+
+        AnyType operator()(Stack stack) const;
+};
+template<class Type, class K>
+basicAC_F0::name_and_type initDDM_Op<Type, K>::name_param[] = {
+    {"communicator", &typeid(pcommworld)},
+    {"scaling", &typeid(KN<typename HPDDM::Wrapper<K>::ul_type>*)},
+    {"deflation", &typeid(FEbaseArrayKn<K>*)},
+};
+template<class Type, class K>
+class initDDM : public OneOperator {
+    public:
+        initDDM() : OneOperator(atype<Type*>(), atype<Type*>(), atype<Matrice_Creuse<K>*>(), atype<KN<long>*>(), atype<KN<KN<long>>*>()) { }
+
+        E_F0* code(const basicAC_F0& args) const {
+            return new initDDM_Op<Type, K>(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]), t[2]->CastTo(args[2]), t[3]->CastTo(args[3]));
+        }
+};
+template<class Type, class K>
+AnyType initDDM_Op<Type, K>::operator()(Stack stack) const {
+    Type* ptA = GetAny<Type*>((*A)(stack));
+    MatriceMorse<K>* mA = static_cast<MatriceMorse<K>*>(&(*GetAny<Matrice_Creuse<K>*>((*Mat)(stack))->A));
+    KN<long>* ptO = GetAny<KN<long>*>((*o)(stack));
+    KN<KN<long>>* ptR = GetAny<KN<KN<long>>*>((*R)(stack));
+    MPI_Comm* comm = nargs[0] ? (MPI_Comm*)GetAny<pcommworld>((*nargs[0])(stack)) : 0;
+    if(ptO && mA) {
+        HPDDM::MatrixCSR<K>* dA = new HPDDM::MatrixCSR<K>(mA->n, mA->m, mA->nbcoef, mA->a, mA->lg, mA->cl, mA->symetrique);
+        ptA->HPDDM::template Subdomain<K>::initialize(dA, STL<long>(*ptO), *ptR, comm);
+    }
+    FEbaseArrayKn<K>* deflation = nargs[2] ? GetAny<FEbaseArrayKn<K>*>((*nargs[2])(stack)) : 0;
+    K** const& v = ptA->getVectors();
+    if(deflation && deflation->N > 0 && !v) {
+        K** ev = new K*[deflation->N];
+        *ev = new K[deflation->N * deflation->get(0)->n];
+        for(int i = 0; i < deflation->N; ++i) {
+            ev[i] = *ev + i * deflation->get(0)->n;
+            std::copy(&(*deflation->get(i))[0], &(*deflation->get(i))[deflation->get(i)->n], ev[i]);
+        }
+        ptA->setVectors(ev);
+        ptA->Type::super::initialize(deflation->N);
+    }
+    KN<typename HPDDM::Wrapper<K>::ul_type>* ptD = nargs[1] ? GetAny<KN<typename HPDDM::Wrapper<K>::ul_type>*>((*nargs[1])(stack)) : 0;
+    if(ptD)
+        ptA->initialize(*ptD);
+    else
+        std::cerr << "Something is really wrong here !" << std::endl;
+    return ptA;
+}
+
+template<class Type, class K>
+class attachCoarseOperator_Op : public E_F0mps {
+    public:
+        Expression comm;
+        Expression A;
+        static const int n_name_param = 7;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        attachCoarseOperator_Op(const basicAC_F0& args, Expression param1, Expression param2) : comm(param1), A(param2) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+
+        AnyType operator()(Stack stack) const;
+};
+template<class Type, class K>
+basicAC_F0::name_and_type attachCoarseOperator_Op<Type, K>::name_param[] = {
+    {"A", &typeid(Matrice_Creuse<K>*)},
+    {"B", &typeid(Matrice_Creuse<K>*)},
+    {"pattern", &typeid(Matrice_Creuse<K>*)},
+    {"threshold", &typeid(typename HPDDM::Wrapper<K>::ul_type)},
+    {"parameters", &typeid(KN<long>*)},
+    {"timing", &typeid(KN<double>*)},
+    {"ret", &typeid(Pair<K>*)}
+};
+template<class Type, class K>
+class attachCoarseOperator : public OneOperator {
+    public:
+        attachCoarseOperator() : OneOperator(atype<long>(), atype<pcommworld>(), atype<Type*>()) { }
+
+        E_F0* code(const basicAC_F0& args) const {
+            return new attachCoarseOperator_Op<Type, K>(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]));
+        }
+};
+template<class Type, class K>
+AnyType attachCoarseOperator_Op<Type, K>::operator()(Stack stack) const {
+    pcommworld ptComm = GetAny<pcommworld>((*comm)(stack));
+    MPI_Comm comm = *(MPI_Comm*)ptComm;
+    Type* ptA = GetAny<Type*>((*A)(stack));
+    MatriceMorse<K>* mA = nargs[0] ? static_cast<MatriceMorse<K>*>(&(*GetAny<Matrice_Creuse<K>*>((*nargs[0])(stack))->A)) : 0;
+    KN<long>* ptParm = nargs[4] ? GetAny<KN<long>*>((*nargs[4])(stack)) : 0;
+    if(ptParm && ptParm->n != 5) {
+        if(ptParm->n == 1) {
+            ptParm->resize(5);
+            (*ptParm)[HPDDM::P] = 1;
+        }
+        else if(ptParm->n == 2)
+            ptParm->resize(5);
+        else
+            cout << "Input array must be of size 1, 2, or 5 !" << endl;
+        if(ptParm->n == 5) {
+            (*ptParm)[HPDDM::TOPOLOGY] = 0;
+            (*ptParm)[HPDDM::DISTRIBUTION] = HPDDM::DMatrix::NON_DISTRIBUTED;
+            (*ptParm)[HPDDM::STRATEGY] = 3;
+        }
+    }
+    KN<double>* timing = nargs[5] ? GetAny<KN<double>*>((*nargs[5])(stack)) : 0;
+    Pair<K>* pair = nargs[6] ? GetAny<Pair<K>*>((*nargs[6])(stack)) : 0;
+    typename HPDDM::Wrapper<K>::ul_type threshold = nargs[3] ? GetAny<typename HPDDM::Wrapper<K>::ul_type>((*nargs[3])(stack)) : 0;
+    std::vector<unsigned short> parm(5);
+    if(ptParm) {
+        parm[HPDDM::P]            = (*ptParm)[HPDDM::P];
+        parm[HPDDM::TOPOLOGY]     = (*ptParm)[HPDDM::TOPOLOGY];
+        parm[HPDDM::DISTRIBUTION] = (*ptParm)[HPDDM::DISTRIBUTION];
+        parm[HPDDM::STRATEGY]     = (*ptParm)[HPDDM::STRATEGY];
+    }
+    else {
+        parm[HPDDM::P]            = 1;
+        parm[HPDDM::TOPOLOGY]     = 0;
+        parm[HPDDM::DISTRIBUTION] = HPDDM::DMatrix::NON_DISTRIBUTED;
+        parm[HPDDM::STRATEGY]     = 3;
+    }
+    unsigned short nu = ptParm ? (*ptParm)[HPDDM::NU] : 20;
+    nu = std::max(nu, static_cast<unsigned short>(1));
+    std::pair<MPI_Request, const K*>* ret = nullptr;
+    if(mA) {
+        HPDDM::MatrixCSR<K> dA(mA->n, mA->m, mA->nbcoef, mA->a, mA->lg, mA->cl, mA->symetrique);
+        MatriceMorse<K>* mB = nargs[1] ? static_cast<MatriceMorse<K>*>(&(*GetAny<Matrice_Creuse<K>*>((*nargs[1])(stack))->A)) : nullptr;
+        MatriceMorse<K>* mP = nargs[2] ? static_cast<MatriceMorse<K>*>(&(*GetAny<Matrice_Creuse<K>*>((*nargs[2])(stack))->A)) : nullptr;
+        const HPDDM::MatrixCSR<K>* const dP = mP ? new HPDDM::MatrixCSR<K>(mP->n, mP->m, mP->nbcoef, mP->a, mP->lg, mP->cl, mP->symetrique) : nullptr;
+        double t = MPI_Wtime();
+        if(mB) {
+            HPDDM::MatrixCSR<K> dB(mB->n, mB->m, mB->nbcoef, mB->a, mB->lg, mB->cl, mB->symetrique);
+            ptA->template solveGEVP<EIGENSOLVER>(&dA, nu, threshold, &dB, dP);
+        }
+        else
+            ptA->template solveGEVP<EIGENSOLVER>(&dA, nu, threshold, nullptr, dP);
+        mA->nbcoef = dA._nnz;
+        mA->a = dA._a;
+        mA->lg = dA._ia;
+        mA->cl = dA._ja;
+        if(timing)
+            (*timing)[3] = MPI_Wtime() - t;
+        delete dP;
+        parm[HPDDM::NU]           = nu;
+        if(ptA->exclusion(comm)) {
+            if(pair)
+                pair->p = ptA->template buildTwo<1>(comm, parm);
+            else
+                ret = ptA->template buildTwo<1>(comm, parm);
+        }
+        else {
+            if(pair)
+                pair->p = ptA->template buildTwo<0>(comm, parm);
+            else
+                ret = ptA->template buildTwo<0>(comm, parm);
+        }
+    }
+    else {
+        if(!threshold) {
+            parm[HPDDM::NU]       = nu;
+            ret = ptA->template buildTwo<2>(comm, parm);
+        }
+    }
+    delete ret;
+    return 0L;
+}
+
+template<class Type, class K>
+class solveDDM_Op : public E_F0mps {
+    public:
+        Expression A;
+        Expression x;
+        Expression rhs;
+        static const int n_name_param = 9;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        solveDDM_Op(const basicAC_F0& args, Expression param1, Expression param2, Expression param3) : A(param1), x(param2), rhs(param3) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+
+        AnyType operator()(Stack stack) const;
+};
+template<class Type, class K>
+basicAC_F0::name_and_type solveDDM_Op<Type, K>::name_param[] = {
+    {"eps", &typeid(typename HPDDM::Wrapper<K>::ul_type)},
+    {"dim", &typeid(long)},
+    {"iter", &typeid(long)},
+    {"timing", &typeid(KN<double>*)},
+    {"solver", &typeid(long)},
+    {"pipelined", &typeid(long)},
+    {"excluded", &typeid(bool)},
+    {"ret", &typeid(Pair<K>*)},
+    {"O", &typeid(Matrice_Creuse<K>*)}
+};
+template<class Type, class K>
+class solveDDM : public OneOperator {
+    public:
+        solveDDM() : OneOperator(atype<long>(), atype<Type*>(), atype<KN<K>*>(), atype<KN<K>*>()) { }
+
+        E_F0* code(const basicAC_F0& args) const {
+            return new solveDDM_Op<Type, K>(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]), t[2]->CastTo(args[2]));
+        }
+};
+template<class Type, class K>
+AnyType solveDDM_Op<Type, K>::operator()(Stack stack) const {
+    KN<K>* ptX = GetAny<KN<K>*>((*x)(stack));
+    KN<K>* ptRHS = GetAny<KN<K>*>((*rhs)(stack));
+    Type* ptA = GetAny<Type*>((*A)(stack));
+    typename HPDDM::Wrapper<K>::ul_type eps = nargs[0] ? GetAny<typename HPDDM::Wrapper<K>::ul_type>((*nargs[0])(stack)) : 1e-8;
+    unsigned short dim = nargs[1] ? GetAny<long>((*nargs[1])(stack)) : 50;
+    unsigned short iter = nargs[2] ? GetAny<long>((*nargs[2])(stack)) : 50;
+    KN<double>* timing = nargs[3] ? GetAny<KN<double>*>((*nargs[3])(stack)) : 0;
+    Pair<K>* pair = nargs[7] ? GetAny<Pair<K>*>((*nargs[7])(stack)) : 0;
+    if(pair)
+        if(pair->p) {
+            int flag;
+            MPI_Test(&(pair->p->first), &flag, MPI_STATUS_IGNORE);
+        }
+    MatriceMorse<K>* mA = nargs[8] ? static_cast<MatriceMorse<K>*>(&(*GetAny<Matrice_Creuse<K>*>((*nargs[8])(stack))->A)) : 0;
+    long solver = nargs[4] ? GetAny<long>((*nargs[4])(stack)) : 0;
+    double timer = MPI_Wtime();
+    if(mA && (solver == 6 || solver == 7)) {
+        HPDDM::MatrixCSR<K> dA(mA->n, mA->m, mA->nbcoef, mA->a, mA->lg, mA->cl, mA->symetrique);
+        ptA->callNumfact(&dA);
+    }
+    else
+        ptA->callNumfact(nullptr);
+    ptA->setType(solver == 1 || solver == 6 || solver == 11);
+    if(timing) (*timing)[1] = MPI_Wtime() - timer;
+    long pipelined = nargs[5] ? GetAny<long>((*nargs[5])(stack)) : 0;
+    bool excluded = nargs[6] ? GetAny<bool>((*nargs[6])(stack)) : false;
+    if(pair)
+        if(pair->p) {
+            if(timing)
+                timer = MPI_Wtime();
+            MPI_Wait(&(pair->p->first), MPI_STATUS_IGNORE);
+            if(timing)
+                (*timing)[4] = MPI_Wtime() - timer;
+            delete [] pair->p->second;
+            delete pair->p;
+        }
+    timer = MPI_Wtime();
+    int rank;
+    MPI_Comm_rank(ptA->getCommunicator(), &rank);
+    if(!excluded) {
+        if(solver == 1)
+            HPDDM::IterativeMethod::CG(*ptA, (K*)*ptX, (K*)*ptRHS, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0);
+        else
+            switch(pipelined) {
+#if (OMPI_MAJOR_VERSION > 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION >= 7)) || MPICH_NUMVERSION >= 30000000
+                case 1:  HPDDM::IterativeMethod::GMRES<HPDDM::PIPELINED>(*ptA, (K*)*ptX, (K*)*ptRHS, dim, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0); break;
+#endif
+#if defined(DPASTIX) || defined(DMKL_PARDISO)
+                case 2:  HPDDM::IterativeMethod::GMRES<HPDDM::FUSED>(*ptA, (K*)*ptX, (K*)*ptRHS, dim, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0); break;
+#endif
+                default: HPDDM::IterativeMethod::GMRES<HPDDM::CLASSICAL>(*ptA, (K*)*ptX, (K*)*ptRHS, dim, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0); break;
+            }
+    }
+    else {
+        if(solver == 1)
+            HPDDM::IterativeMethod::CG(*ptA, (K*)nullptr, (K*)nullptr, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0);
+        else
+            switch(pipelined) {
+#if (OMPI_MAJOR_VERSION > 1 || (OMPI_MAJOR_VERSION == 1 && OMPI_MINOR_VERSION >= 7)) || MPICH_NUMVERSION >= 30000000
+                case 1:  HPDDM::IterativeMethod::GMRES<HPDDM::PIPELINED, true>(*ptA, (K*)nullptr, (K*)nullptr, dim, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0); break;
+#endif
+#if defined(DPASTIX) || defined(DMKL_PARDISO)
+                case 2:  HPDDM::IterativeMethod::GMRES<HPDDM::FUSED, true>(*ptA, (K*)nullptr, (K*)nullptr, dim, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0); break;
+#endif
+                default: HPDDM::IterativeMethod::GMRES<HPDDM::CLASSICAL, true>(*ptA, (K*)nullptr, (K*)nullptr, dim, iter, eps, MPI_COMM_WORLD, rank == 0 && !excluded ? 1 : 0); break;
+            }
+    }
+    timer = MPI_Wtime() - timer;
+    if(!excluded) {
+        if(rank == 0)
+            std::cout << scientific << " --- system solved (in " << timer << ")" << std::endl;
+        typename HPDDM::Wrapper<K>::ul_type storage[2];
+        ptA->computeError(*ptX, *ptRHS, storage);
+        if(rank == 0)
+            std::cout << scientific << " --- error = " << storage[1] << " / " << storage[0] << std::endl;
+    }
+    return 0L;
+}
+
+double distributedDot(KN<double>* const& A, KN<double>* const& in, KN<double>* const& out) {
+    double* tmp = new double[in->n];
+    HPDDM::Wrapper<double>::diagv(in->n, *A, *in, tmp);
+    KN_<double> KN(tmp, in->n);
+    double dot = (KN, *out);
+    MPI_Allreduce(MPI_IN_PLACE, &dot, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
+    delete [] tmp;
+    return dot;
+}
+
+template<class T, class U>
+class GMV {
+    public:
+        const T t;
+        const U u;
+        GMV(T v, U w) : t(v), u(w) {}
+        void prod(U x) const;
+};
+template<class Type, class U>
+class GMV<Type*, U> {
+    public:
+        const Type* t;
+        const U u;
+        GMV(Type* v, U w) : t(v), u(w) {}
+        void prod(U x) const { t->GMV(*(this->u), *x); };
+};
+template<class R, class A, class B> R Build(A a, B b) {
+    return R(a, b);
+}
+template<class Type, class K>
+KN<K>* GlobalMV(KN<K>* Ax, GMV<Type*, KN<K>*> A) {
+    A.prod(Ax);
+    return Ax;
+}
+
+template<template<class, char> class Type, class K, char S>
+void add() {
+    Dcl_Type<Type<K, S>*>(Initialize<Type<K, S>>, Delete<Type<K, S>>);
+
+    TheOperators->Add("<-", new initDDM<Type<K, S>, K>);
+    Global.Add("attachCoarseOperator", "(", new attachCoarseOperator<Type<K, S>, K>);
+    Global.Add("DDM", "(", new solveDDM<Type<K, S>, K>);
+    Dcl_Type<GMV<Type<K, S>*, KN<K>*>>();
+    TheOperators->Add("*", new OneOperator2<GMV<Type<K, S>*, KN<K>*>, Type<K, S>*, KN<K>*>(Build));
+    TheOperators->Add("=", new OneOperator2<KN<K>*, KN<K>*, GMV<Type<K, S>*, KN<K>*>>(GlobalMV));
+    if(std::is_same<K, double>::value)
+        Global.Add("dscalprod", "(", new OneOperator3_<double, KN<double>*, KN<double>*, KN<double>*>(distributedDot));
+}
+}
+
+
+
+static void  Load_Init() {
+    const char ds = 'S';
+    const char zs = 'G';
+    Schwarz::add<HpSchwarz, double, ds>();
+    zzzfff->Add("dschwarz", atype<HpSchwarz<double, ds>*>());
+    Schwarz::add<HpSchwarz, std::complex<double>, zs>();
+    zzzfff->Add("zschwarz", atype<HpSchwarz<std::complex<double>, zs>*>());
+#ifdef WITH_PETSC
+    int argc = pkarg->n;
+    char** argv = new char*[argc];
+    for(int i = 0; i < argc; ++i)
+        argv[i] = const_cast<char*>((*(*pkarg)[i].getap())->c_str());
+    PetscInitialize(&argc, &argv, 0, "");
+    delete [] argv;
+    ff_atend(finalizePETSc);
+    Dcl_Type<DistributedCSR*>(Initialize<DistributedCSR>, Delete<DistributedCSR>);
+    Dcl_Type<GMV<DistributedCSR*, KN<double>*>>();
+    zzzfff->Add("dmatrix", atype<DistributedCSR*>());
+    TheOperators->Add("<-", new OneOperator1_<long, DistributedCSR*>(initEmptyCSR));
+    TheOperators->Add("<-", new initCSR<double>);
+    TheOperators->Add("*", new OneOperator2<GMV<DistributedCSR*, KN<double>*>, DistributedCSR*, KN<double>*>(Build));
+    TheOperators->Add("=", new OneOperator2<KN<double>*, KN<double>*, GMV<DistributedCSR*, KN<double>*>>(GlobalMV));
+    Global.Add("set", "(", new setOptions<double>());
+    Global.Add("distributedNumbering", "(", new OneOperator2_<long, DistributedCSR*, KN<double>*>(distributedNumbering));
+    Global.Add("renumber", "(", new OneOperator2_<long, DistributedCSR*, FEbaseArrayKn<double>*>(renumberCSR));
+    Global.Add("solvePETSc", "(", new OneOperator2_<long, DistributedCSR*, KN<double>*>(solvePETSc));
+    Dcl_Type<DistributedCSR_inv>();
+    TheOperators->Add("^", new OneBinaryOperatorPETSc());
+    Dcl_Type<Inv<DistributedCSR_inv, KN<double>*>>();
+    TheOperators->Add("*", new OneOperator2<Inv<DistributedCSR_inv, KN<double>*>, DistributedCSR_inv, KN<double>*>(Build));
+    TheOperators->Add("=", new OneOperator2<KN<double>*, KN<double>*, Inv<DistributedCSR_inv, KN<double>*>>(InvPETSc));
+#endif
+    Dcl_Type<Pair<double>*>(InitP<Pair<double>>, Destroy<Pair<double>>);
+    zzzfff->Add("dpair", atype<Pair<double>*>());
+    Dcl_Type<Pair<std::complex<double>>*>(InitP<Pair<std::complex<double>>>, Destroy<Pair<std::complex<double>>>);
+    zzzfff->Add("zpair", atype<Pair<std::complex<double>>*>());
+}
+
+LOADFUNC(Load_Init);
diff --git a/examples++-mpi/schwarz.edp b/examples++-mpi/schwarz.edp
new file mode 100644
index 0000000..b0e4f77
--- /dev/null
+++ b/examples++-mpi/schwarz.edp
@@ -0,0 +1,62 @@
+load "schwarz"
+load "metis"
+load "utility"
+load "removeDOF"
+include "getARGV.idp"
+
+searchMethod = 1;
+
+macro minimalMesh()square(1, 1)// EOM
+macro generateTh(name)name = square(global, global, [x, y], label = l);// EOM
+macro grad(u)[dx(u), dy(u)]// EOM
+macro bbN(boundingMesh, overshoot, ThGlobal)
+            real[int] bb(4);
+            bb2d(bb, boundingMesh/*, intersection = possibleIntersection, offset = 2. * overlap / global*/);
+            bb(0) -= overshoot;
+            bb(1) += overshoot;
+            bb(2) -= overshoot;
+            bb(3) += overshoot;
+
+            ThGlobal = trunc(ThGlobal, (x >= bb(0) && x <= bb(1) && y >= bb(2) && y <= bb(3)));// EOM
+macro meshN()mesh// EOM
+macro intN()int2d// EOM
+macro measureN()area// EOM
+macro def(u)u// EOM
+macro init(u)u// EOM
+include "additional.idp"
+
+int overlap = getARGV("-overlap", 1);
+func Pk = P1;
+
+verbosity = getARGV("-v", 0);
+int s = getARGV("-split", 1);
+int global = getARGV("-global", 200);
+int solver = getARGV("-solver", 3); // 1: Additive Schwarz + CG, 2: RAS + GMRES, 3: GENEO + GMRES
+int i, j;
+int[int] l = [1, 2, 2, 2];
+
+mesh Th = minimalMesh;
+fespace Wh(Th, Pk);
+build(generateTh, Th, ThBorder, ThOverlap, s, D, numberIntersection, arrayIntersection, restrictionIntersection, Wh, Pk, mpiCommWorld)
+
+macro Varf(varfName, meshName, PhName)
+    varf varfName(u, v) = intN(meshName)((grad(u)' * grad(v))) + intN(meshName)(v) + on(1, u = 0.0);// EOM
+assemble(Mat, rhs, Wh, Th, ThBorder, Varf)
+
+dschwarz A(Mat, arrayIntersection, restrictionIntersection, scaling = D);
+
+if(mpisize > 1 && solver == 3) {
+    int[int] parm(1);
+    parm(0) = getARGV("-nu", 20);
+    macro EVproblem(varfName, meshName, PhName)
+        varf varfName(u, v) = intN(meshName)((grad(u)' * grad(v))) + on(1, u = 0.0);// EOM
+    EVproblem(vPbNoPen, Th, Ph)
+    matrix<real> noPen = vPbNoPen(Wh, Wh, solver = CG);
+    if(solver == 3) // standard GenEO, no need for RHS -> deduced from LHS (Neumann matrix)
+        attachCoarseOperator(mpiCommWorld, A, A = noPen, parameters = parm);
+}
+
+Wh<real> def(u); // this will be the solution
+
+DDM(A, u[], rhs, dim = getARGV("-gmres_restart", 60), iter = getARGV("-iter", 60), eps = getARGV("-eps", 1e-8), solver = solver);
+plotMPI(Th, u[], "Global solution", Pk, def, 3, 1)
diff --git a/examples++-mpi/stokes-2d.edp b/examples++-mpi/stokes-2d.edp
new file mode 100755
index 0000000..c614589
--- /dev/null
+++ b/examples++-mpi/stokes-2d.edp
@@ -0,0 +1,55 @@
+load "schwarz"
+load "metis"
+load "utility"
+include "getARGV.idp"
+
+searchMethod = 1;
+
+macro minimalMesh()square(1, 1)// EOM
+macro grad(u)[dx(u), dy(u)]// EOM
+macro bbN(boundingMesh, overshoot, ThGlobal)
+            real[int] bb(4);
+            bb2d(bb, boundingMesh);
+            bb(0) -= overshoot;
+            bb(1) += overshoot;
+            bb(2) -= overshoot;
+            bb(3) += overshoot;
+
+            ThGlobal = trunc(ThGlobal, (x >= bb(0) && x <= bb(1) && y >= bb(2) && y <= bb(3)));// EOM
+macro meshN()mesh// EOM
+macro intN()int2d// EOM
+macro measureN()area// EOM
+macro def(u)[u, u#B, u#C]// EOM
+macro init(u)[u, u, u]// EOM
+include "additional.idp"
+
+int overlap = getARGV("-overlap", 1);
+func Pk = [P2, P2, P0];
+
+verbosity = getARGV("-v", 0);
+int s = getARGV("-split", 1);
+int global = getARGV("-global", 200);
+int solver = getARGV("-solver", 3); // 1: Additive Schwarz + CG, 2: RAS + GMRES, 3: GENEO + GMRES
+int i, j;
+
+real Sqrt = sqrt(2.);
+macro epsilon(u)[dx(u), dy(u#B), (dy(u) + dx(u#B)) / Sqrt]// EOM
+macro div(u)(dx(u) + dy(u#B))// EOM
+
+mesh ThGlobal = square(getARGV("-global", 20), getARGV("-global", 20), [x, y]);
+
+ThGlobal = trunc(ThGlobal, (x < 0.5) || (y < 0.5), label = 5);
+mesh Th = movemesh(ThGlobal, [-x, y]);
+ThGlobal = ThGlobal + Th;
+macro generateTh(name)name = ThGlobal;// EOM
+fespace Wh(Th, Pk);
+build(generateTh, Th, ThBorder, ThOverlap, s, D, numberIntersection, arrayIntersection, restrictionIntersection, Wh, Pk, mpiCommWorld)
+
+varf vPb([u, uB, p], [v, vB, q]) = intN(Th)(grad(u)' * grad(v) + grad(uB)' * grad(vB) - div(u) * q - div(v) * p + 1e-10 * p * q) + on(1, 3, 5, u = 0, uB = 0) + on(2, u = y*(0.5-y), uB = 0);
+matrix K = vPb(Wh, Wh);
+real[int] rhs = vPb(0, Wh);
+
+dmatrix Mat(K, arrayIntersection, restrictionIntersection, D, bs = 1);
+Wh def(b);
+b[] = Mat^-1 * rhs;
+plotMPI(Th, b[], "Global solution PETSc", Pk, def, 3, 1);
diff --git a/examples++-mpi/testsolver_MUMPS.edp b/examples++-mpi/testsolver_MUMPS.edp
new file mode 100644
index 0000000..b79ac18
--- /dev/null
+++ b/examples++-mpi/testsolver_MUMPS.edp
@@ -0,0 +1,89 @@
+load "MUMPS_FreeFem"  // load the library dynamic correspond to MUMPS interface
+verbosity = 0;
+int[int] ICNTL(40); // declaration of ICNTL parameter for MUMPS
+
+// get value of ICNTL from file
+if(mpirank == 0) 
+{	
+	ifstream ff("ffmumps_fileparam.txt");
+	string line;
+	getline(ff,line);
+	getline(ff,line);
+	for(int iii=0; iii<40;iii++){
+	ff >> ICNTL[iii];      	
+	getline(ff,line);
+	} 
+}
+     	
+broadcast(processor(0),ICNTL);
+
+// Given data of MUMPS solver in array lparams(SYM,PAR,ICNTL) 
+// There is no symmetric storage for a matrix associated with a sparse solver.
+// Therefore, the matrix will be considered unsymmetric for parallel sparse solver even if symmetric.
+// This fact will be change in new version of FreeFem++ 
+{
+    int SYM = 0; 
+    int PAR = 1;
+    matrix A = 
+      [[ 40,  0,     45,  0, 0],
+       [ 0,    12,     0,  0 , 0],
+       [ 0,     0,  40,  0, 0], 
+       [ 12,     0,    0,  22, 0],
+       [ 0,     0,    20,  0., 22]];
+
+    // construction of integer parameter for MUMPS
+    int[int] MumpsLParams(42);
+    MumpsLParams[0] = SYM; 
+    MumpsLParams[1] = PAR;  	
+    for(int ii=0; ii< 40; ii++) MumpsLParams[ii+2] = ICNTL[ii]; // ICNTL begin with index 0 here
+
+    real[int] xx = [ 1,32,45,7,2], x(5), b(5), di(5); 
+    b=A*xx;
+    if(mpirank ==0) cout << "xx=" << xx << endl;
+    
+    set(A,solver=sparsesolver,lparams=MumpsLParams); // We take the default value for CNTL MUMPS parameter  
+   
+    if(mpirank ==0)  cout << "solving solution" << endl;
+    x = A^-1*b;		
+    if(mpirank ==0) cout << "b=" << b << endl;
+    if(mpirank ==0) cout << "x=" << endl; cout << x << endl;
+    di = xx-x;
+    if(mpirank==0){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    }
+}
+
+// FFCS - reference value for regression tests
+real regtest;
+
+// Read parameter of MUMPS solver in file ffmumps_fileparam.txt
+
+{
+matrix A = 
+      [[ 40,  0,     45,  0, 0],
+       [ 0,    12,     0,  0 , 0],
+       [ 0,     0,  40,  0, 0], 
+       [ 12,     0,    0,  22, 0],
+       [ 0,     0,    20,  0., 22]];
+
+
+    real[int] xx = [ 1,32,45,7000,2], x(5), b(5), di(5); // xb(4),bbb(4);
+    b=A*xx;
+    cout << "b="  << b  << endl;
+    cout << "xx=" << xx << endl;
+    
+    set(A,solver=sparsesolver,datafilename="ffmumps_fileparam.txt"); 
+   
+    cout << "solving solution" << endl;
+    x = A^-1*b;		
+    
+    cout << "b=" << b << endl;
+    cout << "x=" << endl; cout << x << endl;
+    di = xx-x;
+    if(mpirank==0){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    regtest=di.l2;
+    }
+}
+
+
diff --git a/examples++-mpi/testsolver_SuperLU_DIST.edp b/examples++-mpi/testsolver_SuperLU_DIST.edp
new file mode 100644
index 0000000..63ee388
--- /dev/null
+++ b/examples++-mpi/testsolver_SuperLU_DIST.edp
@@ -0,0 +1,160 @@
+load "real_SuperLU_DIST_FreeFem"
+load "complex_SuperLU_DIST_FreeFem"
+assert(mpisize>=2);
+int[int] procs=[0,1];
+mpiGroup gpr(procs);
+mpiComm comm(gpr);
+
+// FFCS - reference value for regression tests
+real regtest;
+
+if ( bool(comm))
+  {
+    /////////////////////////////
+    //  real arithmetics case
+    /////////////////////////////
+    // read parameter for SuperLU\_DIST from file
+    verbosity=1;
+    {
+      
+      matrix A = 
+	[[ 1e16,  2,     2,  1, 1],
+	 [ 2,    12,     0,  10 , 10],
+	 [ 2,     0,  1e16,  0, 2], 
+	 [ 1,     10,    0,  22, 0.],
+	 [ 1,     10,    2,  0., 22]];
+      
+      
+      real[int] xx = [ 1,32,45,7,2], x(5), b(5), di(5); 
+      b=A*xx;
+      cout << "b="  << b  << endl;
+      cout << "xx=" << xx << endl;
+      
+      set(A,solver=sparsesolver,datafilename="ffsuperlu_dist_fileparam.txt",commworld=comm);		
+      cout << "solving solution" << endl;
+      x = A^-1*b;		
+      cout << "b=" << b << endl;
+      cout << "x=" << endl; cout << x << endl;
+      di = xx-x;
+      if(mpirank==0){	
+	cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+      }
+    }
+    
+    // give parameter for superlu in this file with string parameter (sparams) 
+    {
+      
+      matrix A = 
+	[[ 1e16,  2,     2,  1, 1],
+	 [ 2,    12,     0,  10 , 10],
+	 [ 2,     0,  1e16,  0, 2], 
+	 [ 1,     10,    0,  22, 0.],
+	 [ 1,     10,    2,  0., 22]];
+  
+      
+      real[int] xx = [ 1,32,45,7,2], x(5), b(5), di(5); 
+      b=A*xx;
+      cout << "b="  << b  << endl;
+      cout << "xx=" << xx << endl;
+      
+      set(A,solver=sparsesolver,sparams="nprow=2,npcol=1,matrix=distributedglobal,ColPerm=MMD_AT_PLUS_A",commworld=comm); 
+      // option selected for SuperLU_DIST
+      // nprow= 2, npcol = 1               
+      // matrix = distributedglobal
+      // ParSymbFact = NO, ColPerm = MMD_AT_PLUS_A, RowPerm = LargeDiag
+      // DiagPivotThresh = 1.0, DiagScale = NOEQUIL
+      // ReplaceTinyPivot = NO, SolveInitialized = NO, RefineInitialized = NO
+      // IterRefine = NOREFINE
+      
+      cout << "solving solution" << endl;
+      x = A^-1*b;		
+      cout << "b=" << b << endl;
+      cout << "x=" << endl; cout << x << endl;
+      di = xx-x;
+      if(mpirank==0){	
+	cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+      }
+      b=A*xx;
+      cout << "b="  << b  << endl;
+      cout << "xx=" << xx << endl;
+    }
+    
+    /////////////////////////////
+    //  complex arithmetics case
+    /////////////////////////////
+    // read parameter for SuperLU\_DIST from file
+     if (1) {
+      // Resolution avec SuperLU_DIST COMPLEX
+      int N=40;
+      complex[int,int] AA(N,N);
+      AA=0.+0i;	
+      for(int ii=1;ii<N;ii=ii+1) AA(ii-1,ii)=1.+ii*1i;
+      for(int ii=1;ii<N;ii=ii+1) AA(ii,ii-1)=1.+ii*1i;	
+      AA(0,N-1)=1.+(N+1)*N/2*1i;
+      AA(N-1,0)=1.+N*1i;	
+      
+      matrix<complex> A;
+      A = AA;
+      
+      complex[int] xx(N), x(N), b(N),b1(N), di(N);
+      for(int j=0;j<N;j++) xx[j] = 0+j*1i;
+      xx[0]= N+N*1i;
+      b = A*xx;
+
+      set(A,solver=sparsesolver,datafilename="ffsuperlu_dist_fileparam.txt",commworld=comm); // reading SuperLU_DIST parameter on file ffsuperlu_dist_fileparam.txt
+      cout << " ################### " << endl;            
+
+      x = A^-1*b;
+      if(mpirank==0){
+	cout << "x=  "<< x << endl;
+	cout << "xx= " << xx << endl;	
+	di=(xx-x);
+	cout << "error " << sqrt( abs(di'*di) ) << endl;//'));
+	regtest=di.l2;
+      }
+
+    
+    }
+    
+    // give parameter for superlu in this file with string parameter (sparams) 
+    if(0)
+    {
+      // Resolution avec MUMPS COMPLEX
+      int N=40;
+      complex[int,int] AA(N,N);
+      AA=0.+0i;
+      for(int ii=1;ii<N;ii=ii+1) AA(ii-1,ii)=1.+ii*1i;
+      for(int ii=1;ii<N;ii=ii+1) AA(ii,ii-1)=1.+ii*1i;	
+      AA(0,N-1)=1.+(N+1)*N/2*1i;
+      AA(N-1,0)=1.+N*1i;
+      
+      matrix<complex> A;
+      A = AA;
+      
+      complex[int] xx(N), x(N), b(N),b1(N), di(N);
+      for(int j=0;j<N;j++) xx[j] = 2*j^2+j*1i;
+      xx[0]= 0.+N*1i;
+      b = A*xx;
+      
+      set(A,solver=sparsesolver,sparams="nprow=2,npcol=1,matrix=distributedglobal,ColPerm=METIS_AT_PLUS_A",commworld=comm); 
+      // option selected for SuperLU_DIST
+      // nprow= 2, npcol = 1               
+      // matrix = distributedglobal
+      // ParSymbFact = NO, ColPerm = METIS_AT_PLUS_A, RowPerm = LargeDiag
+      // DiagPivotThresh = 1.0, DiagScale = NOEQUIL
+      // ReplaceTinyPivot = NO, SolveInitialized = NO, RefineInitialized = NO
+      // IterRefine = NOREFINE
+      
+      x = A^-1*b;	
+      if(mpirank==0){
+	cout << "x=  "<< x << endl;
+	cout << "xx= " << xx << endl;
+	di=(xx-x);
+	cout << "error " << sqrt( abs(di'*di) ) << endl;//'));
+      }
+    }
+    
+  }
+cout << " ************  Fin.." <<mpirank <<endl;
+mpiBarrier(mpiCommWorld);	
+cout << " Fin.." <<mpirank <<endl;
diff --git a/examples++-mpi/testsolver_dsuperlu_dist.edp b/examples++-mpi/testsolver_dsuperlu_dist.edp
new file mode 100644
index 0000000..e0e3ea0
--- /dev/null
+++ b/examples++-mpi/testsolver_dsuperlu_dist.edp
@@ -0,0 +1,62 @@
+load "dSuperLU_DIST"
+
+// FFCS - reference value for regressions tests
+real regtest;
+
+// read parameter for superlu from file
+verbosity=2;
+{
+
+matrix A = 
+      [[ 1e16,  2,     2,  1, 1],
+       [ 2,    12,     0,  10 , 10],
+       [ 2,     0,  1e16,  0, 2], 
+       [ 1,     10,    0,  22, 0.],
+       [ 1,     10,    2,  0., 22]];
+
+
+    real[int] xx = [ 1,32,45,7,2], x(5), b(5), di(5); // xb(4),bbb(4);
+    b=A*xx;
+    cout << "b="  << b  << endl;
+    cout << "xx=" << xx << endl;
+  
+    set(A,solver=sparsesolver,datafilename="ffsuperlu_dist_fileparam.txt");		
+    cout << "solving solution" << endl;
+    x = A^-1*b;		
+    cout << "b=" << b << endl;
+    cout << "x=" << endl; cout << x << endl;
+    di = xx-x;
+    if(mpirank==0){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    }
+}
+
+// read parameter for superlu from string and 
+verbosity=2;
+{
+
+matrix A = 
+      [[ 1e16,  2,     2,  1, 1],
+       [ 2,    12,     0,  10 , 10],
+       [ 2,     0,  1e16,  0, 2], 
+       [ 1,     10,    0,  22, 0.],
+       [ 1,     10,    2,  0., 22]];
+
+
+    real[int] xx = [ 1,32,45,7,2], x(5), b(5), di(5); // xb(4),bbb(4);
+    b=A*xx;
+    cout << "b="  << b  << endl;
+    cout << "xx=" << xx << endl;
+  
+    set(A,solver=sparsesolver,sparams="nprow=2,npcol=1,matrix=distributedglobal,ColPerm=MMD_AT_PLUS_A");		
+    cout << "solving solution" << endl;
+    x = A^-1*b;		
+    cout << "b=" << b << endl;
+    cout << "x=" << endl; cout << x << endl;
+    di = xx-x;
+    if(mpirank==0){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    regtest=di.l2;
+    }
+}
+
diff --git a/examples++-mpi/testsolver_pastix.edp b/examples++-mpi/testsolver_pastix.edp
new file mode 100644
index 0000000..23428ce
--- /dev/null
+++ b/examples++-mpi/testsolver_pastix.edp
@@ -0,0 +1,198 @@
+load "real_pastix_FreeFem"
+load "complex_pastix_FreeFem"
+verbosity=1;
+
+//#################################
+//#  real arithmetic
+//#################################
+// reading parameter of pastix from data file
+{
+
+matrix A = 
+      [[  100,  1,  0,  10],
+       [  1,  100,  2,  0 ],
+       [  0,  2,  100,  3 ], 
+       [  10,  0,  3,  100 ]];
+
+    real[int] xx = [ 1,2,3,4], x(4), b(4), di(4); // xb(4),bbb(4);
+
+    b=A*xx;
+    cout << "b="  << b  << endl;
+    cout << "xx=" << xx << endl;
+    if(mpirank==0) cout << "A="<< A << endl;
+    set(A,solver=sparsesolver,datafilename="ffpastix_iparm_dparm.txt");	 	
+    cout << "solving solution" << endl;
+    x = A^-1*b;		
+    cout << "b=" << b << endl;
+    cout << "x=" << endl; cout << x << endl;
+    di = xx-x;
+    if(mpirank==0){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    }
+    if(mpirank==1){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    }
+    if(mpirank==0) cout << "A="<< A << endl;
+    x = A^-1*b;	
+    cout << "b=" << b << endl;
+    cout << "x=" << endl; cout << x << endl;
+}
+
+// definition of pastix parameter iparm and dparm in this file 
+// These parameters must be given to lparams and dparams respectively
+
+{
+matrix A = 
+      [[ 1e16,  2,     2,  1, 1],
+       [ 2,    12,     0,  10 , 10],
+       [ 2,     0,  1e16,  0, 2], 
+       [ 1,     10,    0,  22, 0.],
+       [ 1,     10,    2,  0., 22]];
+
+
+    real[int] xx = [ 1,32,45,7,2], x(5), b(5), di(5); 
+    b=A*xx;
+    cout << "b="  << b  << endl;
+    cout << "xx=" << xx << endl;
+
+    int[int] iparm(64);
+    real[int] dparm(64);
+
+    if(mpirank == 0){
+    	// read iparm and dparm from data file with processor 0 
+        ifstream datapastix("ffpastix_iparm_dparm.txt");
+        string line;
+    	getline(datapastix,line);
+    	cout << " line= "<< line << endl;
+	getline(datapastix,line);	
+    	cout << " line= "<< line << endl;
+	getline(datapastix,line);	
+    	cout << " line= "<< line << endl;	
+    	for(int iii=0; iii<64;iii++){
+    	    datapastix >> iparm[iii]; // read iii+2 lines of the file ffpastix_iparm_dparm.txt
+	    getline(datapastix,line); 	   
+    	}
+    	getline(datapastix,line); 
+	cout << " line= "<< line << endl;
+    	for(int iii=0; iii<64;iii++){
+    	    datapastix >> dparm[iii]; // read iii+66 lines of the file ffpastix_iparm_dparm.txt
+    	    getline(datapastix,line); 	  
+       }
+    }
+    broadcast(processor(0),iparm); // broadcast iparm to the other processor
+    broadcast(processor(0),dparm); // broadcast dparm to the other processor
+    if(mpirank ==0){
+       cout << "iparm=" << iparm << endl;
+       cout << "dparm =" << dparm << endl;
+    }      	    
+    set(A,solver=sparsesolver,lparams=iparm,dparams=dparm);  // set to pastix solver the parameter iparm and dparm
+    if(mpirank) cout << "solving solution" << endl;
+
+    x = A^-1*b;		
+    
+    di = xx-x;
+    if(mpirank==0){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    }
+    if(mpirank==1){	
+    cout << "x-xx="<< endl; cout << "Linf "<< di.linfty << " L2 " << di.l2 << endl;
+    }
+}
+
+//#################################
+//#  complex arithmetic
+//#################################
+// read parameter for pastix from data file
+{
+// Resolution with complex pastix
+int N=40;
+complex[int,int] AA(N,N);
+AA=0.+0i;	
+for(int ii=1;ii<N;ii=ii+1) AA(ii-1,ii)=1.+ii*1i;
+//for(int ii=1;ii<N;ii=ii+1) AA(ii,ii)=100.;
+for(int ii=1;ii<N;ii=ii+1) AA(ii,ii-1)=1.+ii*1i;	
+AA(0,N-1)=1.+1.*(N+1)*N/2*1i;
+AA(N-1,0)=1.+N*1i;	
+
+matrix<complex> A;
+A = AA;
+  
+complex[int] xx(N), x(N), b(N),b1(N), di(N);
+for(int j=0;j<N;j++) xx[j] = j+j*1i;
+xx[0]= N+N*1i;
+b = A*xx;
+
+set(A,solver=sparsesolver,datafilename="ffpastix_iparm_dparm.txt"); // reading pastix parameter on file ffsuperlu_dist_fileparam.txt
+
+x = A^-1*b;
+if(mpirank==0){
+cout << "x=  "<< x << endl;
+cout << "xx= " << xx << endl;	
+di=(xx-x);
+cout << "error " << sqrt( abs(di'*di) ) << endl;
+}
+}
+
+// definition of pastix parameter iparm and dparm in this file 
+// These parameters must be given to lparams and dparams respectively
+{
+// Solving with pastix solver
+int N=40;
+complex[int,int] AB(N,N);
+AB=0.+0i;
+for(int ii=1;ii<N;ii=ii+1) AB(ii-1,ii)=1.+ii*1i;
+for(int ii=1;ii<N;ii=ii+1) AB(ii,ii-1)=1.+ii*1i;	
+AB(0,N-1)=1.+(N+1)*N/2*1i;
+AB(N-1,0)=1.+N*1i;
+
+matrix<complex> A1;
+A1 = AB;
+ 
+complex[int] xx(N), x(N), b(N),b1(N), di(N);
+for(int j=0;j<N;j++) xx[j] = j^2+j*1i;
+xx[0]= N+N*1i;
+b = A1*xx;
+
+int[int] iparm(64);
+real[int] dparm(64);
+
+if(mpirank == 0){
+    // read iparm and dparm from data file with processor 0 
+    ifstream datapastix("ffpastix_iparm_dparm.txt");
+    string line;
+    getline(datapastix,line);
+    cout << " line= "<< line << endl;
+    getline(datapastix,line);	
+    cout << " line= "<< line << endl;
+    getline(datapastix,line);	
+    cout << " line= "<< line << endl;	
+    for(int iii=0; iii<64;iii++){
+       datapastix >> iparm[iii]; // read iii+2 lines of the file ffpastix_iparm_dparm.txt
+       getline(datapastix,line); 	   
+    }
+    getline(datapastix,line); 
+    cout << " line= "<< line << endl;
+    for(int iii=0; iii<64;iii++){
+       datapastix >> dparm[iii]; // read iii+66 lines of the file ffpastix_iparm_dparm.txt
+       getline(datapastix,line); 	  
+       }
+    }
+    broadcast(processor(0),iparm); // broadcast iparm to the other processor
+    broadcast(processor(0),dparm); // broadcast dparm to the other processor
+    if(mpirank ==0){
+       cout << "iparm=" << iparm << endl;
+       cout << "dparm =" << dparm << endl;
+    }      	    
+
+    set(A1,solver=sparsesolver,lparams=iparm,dparams=dparm);
+    if(mpirank == 0) cout << "solving solution" << endl;
+
+    x = A1^-1*b;	
+    if(mpirank==0){
+    cout << "x=  "<< x << endl;
+    cout << "xx= " << xx << endl;
+    di=(xx-x);
+    cout << "error " << sqrt( abs(di'*di) ) << endl;
+    }
+}
+
diff --git a/examples++-mpi/utility.cpp b/examples++-mpi/utility.cpp
new file mode 100644
index 0000000..57cd4ac
--- /dev/null
+++ b/examples++-mpi/utility.cpp
@@ -0,0 +1,426 @@
+//ff-c++-LIBRARY-dep:  hpddm  scalapack blas  mpifc  fc mpi  pthread 
+//ff-c++-cpp-dep: 
+#ifndef _ALL_IN_ONE_
+#include "ff++.hpp"
+#include "AFunction_ext.hpp"
+#include <vector>
+#include <cmath>
+#include <mpi.h>
+#endif
+
+class Boundingbox2D_Op : public E_F0mps {
+    public:
+        Expression arrayBB;
+        Expression Th;
+        static const int n_name_param = 0;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        Boundingbox2D_Op(const basicAC_F0& args, Expression param1, Expression param2) : arrayBB(param1), Th(param2) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+        AnyType operator()(Stack stack) const;
+};
+
+class Boundingbox2D : public OneOperator {
+    public:
+        Boundingbox2D() : OneOperator(atype<long>(), atype<KN<double>* >(), atype<pmesh>()) {}
+        E_F0* code(const basicAC_F0& args) const
+        {
+            return new Boundingbox2D_Op(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]));
+        }
+};
+
+AnyType Boundingbox2D_Op::operator()(Stack stack) const {
+    Mesh* pTh = GetAny<Mesh*>((*Th)(stack));
+    KN<double> minmax(4); // x.min, x.max, y.min, y.max
+    R2 p1(pTh->bedges[0][0]);
+    R2 p2(pTh->bedges[0][1]);
+    /* If array has even number of elements then
+       initialize the first two elements as minimum and
+       maximum */
+    if(p1.x > p2.x) {
+        minmax[1] = p1.x;
+        minmax[0] = p2.x;
+    }
+    else {
+        minmax[0] = p1.x;
+        minmax[1] = p2.x;
+    }
+    if(p1.y > p2.y) {
+        minmax[3] = p1.y;
+        minmax[2] = p2.y;
+    }
+    else {
+        minmax[2] = p1.y;
+        minmax[3] = p2.y;
+    }
+    for(int e = 1; e < pTh->neb; ++e) {
+        R2 p1(pTh->bedges[e][0]);
+        R2 p2(pTh->bedges[e][1]);
+
+        if(p1.x > p2.x) {
+            if(p1.x > minmax[1])
+                minmax[1] = p1.x;
+            if(p2.x < minmax[0])
+                minmax[0] = p2.x;
+        }
+        else {
+            if(p2.x > minmax[1])
+                minmax[1] = p2.x;
+            if(p1.x < minmax[0])
+                minmax[0] = p1.x;
+        }
+        if(p1.y > p2.y) {
+            if(p1.y > minmax[3])
+                minmax[3] = p1.y;
+            if(p2.y < minmax[2])
+                minmax[2] = p2.y;
+        }
+        else {
+            if(p2.y > minmax[3])
+                minmax[3] = p2.y;
+            if(p1.y < minmax[2])
+                minmax[2] = p1.y;
+        }
+    }
+    KN<double>* bb = GetAny<KN<double>* >((*arrayBB)(stack));
+    *bb = minmax;
+    return 0L;
+}
+
+class Boundingbox3D_Op : public E_F0mps {
+    public:
+        Expression arrayBB;
+        Expression Th;
+        static const int n_name_param = 0;
+        static basicAC_F0::name_and_type name_param[];
+        Expression nargs[n_name_param];
+        Boundingbox3D_Op(const basicAC_F0& args, Expression param1, Expression param2) : arrayBB(param1), Th(param2) {
+            args.SetNameParam(n_name_param, name_param, nargs);
+        }
+        AnyType operator()(Stack stack) const;
+};
+
+basicAC_F0::name_and_type Boundingbox3D_Op::name_param[] = { };
+basicAC_F0::name_and_type Boundingbox2D_Op::name_param[] = { };
+
+class Boundingbox3D : public OneOperator {
+    public:
+        Boundingbox3D() : OneOperator(atype<long>(), atype<KN<double>* >(), atype<pmesh3>()) {}
+        E_F0* code(const basicAC_F0& args) const
+        {
+            return new Boundingbox3D_Op(args, t[0]->CastTo(args[0]), t[1]->CastTo(args[1]));
+        }
+};
+
+AnyType Boundingbox3D_Op::operator()(Stack stack) const {
+    Mesh3* pTh = GetAny<Mesh3*>((*Th)(stack));
+    KN<double> minmax(6); // x.min, x.max, y.min, y.max, z.min, z.max
+    const Triangle3& K1(pTh->be(0));
+    const Triangle3& K2(pTh->be(1));
+    if(K1[0].x > K1[1].x) {
+        minmax[1] = K1[0].x;
+        minmax[0] = K1[1].x;
+    }
+    else {
+        minmax[0] = K1[0].x;
+        minmax[1] = K1[1].x;
+    }
+    if(K1[0].y > K1[1].y) {
+        minmax[3] = K1[0].y;
+        minmax[2] = K1[1].y;
+    }
+    else {
+        minmax[2] = K1[0].y;
+        minmax[3] = K1[1].y;
+    }
+    if(K1[0].z > K1[1].z) {
+        minmax[5] = K1[0].z;
+        minmax[4] = K1[1].z;
+    }
+    else {
+        minmax[4] = K1[0].z;
+        minmax[5] = K1[1].z;
+    }
+    //
+    if(K1[2].x > K2[0].x) {
+        if(K1[2].x > minmax[1])
+            minmax[1] = K1[2].x;
+        if(K2[0].x < minmax[0])
+            minmax[0] = K2[0].x;
+    }
+    else {
+        if(K2[0].x > minmax[1])
+            minmax[1] = K2[0].x;
+        if(K1[2].x < minmax[0])
+            minmax[0] = K1[2].x;
+    }
+    if(K1[2].y > K2[0].y) {
+        if(K1[2].y > minmax[3])
+            minmax[3] = K1[2].y;
+        if(K2[0].y < minmax[2])
+            minmax[2] = K2[0].y;
+    }
+    else {
+        if(K2[0].y > minmax[3])
+            minmax[3] = K2[0].y;
+        if(K1[2].y < minmax[2])
+            minmax[2] = K1[2].y;
+    }
+    if(K1[2].z > K2[0].z) {
+        if(K1[2].z > minmax[5])
+            minmax[5] = K1[2].z;
+        if(K2[0].z < minmax[4])
+            minmax[4] = K2[0].z;
+    }
+    else {
+        if(K2[0].z > minmax[5])
+            minmax[5] = K2[0].z;
+        if(K1[2].z < minmax[4])
+            minmax[4] = K1[2].z;
+    }
+    //
+    if(K2[1].x > K2[2].x) {
+        if(K2[1].x > minmax[1])
+            minmax[1] = K2[1].x;
+        if(K2[2].x < minmax[0])
+            minmax[0] = K2[2].x;
+    }
+    else {
+        if(K2[2].x > minmax[1])
+            minmax[1] = K2[2].x;
+        if(K2[1].x < minmax[0])
+            minmax[0] = K2[1].x;
+    }
+    if(K2[1].y > K2[2].y) {
+        if(K2[1].y > minmax[3])
+            minmax[3] = K2[1].y;
+        if(K2[2].y < minmax[2])
+            minmax[2] = K2[2].y;
+    }
+    else {
+        if(K2[2].y > minmax[3])
+            minmax[3] = K2[2].y;
+        if(K2[1].y < minmax[2])
+            minmax[2] = K2[1].y;
+    }
+    if(K2[1].z > K2[2].z) {
+        if(K2[1].z > minmax[5])
+            minmax[5] = K2[1].z;
+        if(K2[2].z < minmax[4])
+            minmax[4] = K2[2].z;
+    }
+    else {
+        if(K2[2].z > minmax[5])
+            minmax[5] = K2[2].z;
+        if(K2[1].z < minmax[4])
+            minmax[4] = K2[1].z;
+    }
+
+    int i = 3;
+    while(i < (pTh->nbe)-1) {
+        const Triangle3& Ka(pTh->be(i));
+        const Triangle3& Kb(pTh->be(i+1));
+        if(Ka[0].x > Ka[1].x) {
+            if(Ka[0].x > minmax[1])
+                minmax[1] = Ka[0].x;
+            if(Ka[1].x < minmax[0])
+                minmax[0] = Ka[1].x;
+        }
+        else {
+            if(Ka[1].x > minmax[1])
+                minmax[1] = Ka[1].x;
+            if(Ka[0].x < minmax[0])
+                minmax[0] = Ka[0].x;
+        }
+        if(Ka[0].y > Ka[1].y) {
+            if(Ka[0].y > minmax[3])
+                minmax[3] = Ka[0].y;
+            if(Ka[1].y < minmax[2])
+                minmax[2] = Ka[1].y;
+        }
+        else {
+            if(Ka[1].y > minmax[3])
+                minmax[3] = Ka[1].y;
+            if(Ka[0].y < minmax[2])
+                minmax[2] = Ka[0].y;
+        }
+        if(Ka[0].z > Ka[1].z) {
+            if(Ka[0].z > minmax[5])
+                minmax[5] = Ka[0].z;
+            if(Ka[1].z < minmax[4])
+                minmax[4] = Ka[1].z;
+        }
+        else {
+            if(Ka[1].z > minmax[5])
+                minmax[5] = Ka[1].z;
+            if(Ka[0].z < minmax[4])
+                minmax[4] = Ka[0].z;
+        }
+        //
+        if(Ka[2].x > Kb[0].x) {
+            if(Ka[2].x > minmax[1])
+                minmax[1] = Ka[2].x;
+            if(Kb[0].x < minmax[0])
+                minmax[0] = Kb[0].x;
+        }
+        else {
+            if(Kb[0].x > minmax[1])
+                minmax[1] = Kb[0].x;
+            if(Ka[2].x < minmax[0])
+                minmax[0] = Ka[2].x;
+        }
+        if(Ka[2].y > Kb[0].y) {
+            if(Ka[2].y > minmax[3])
+                minmax[3] = Ka[2].y;
+            if(Kb[0].y < minmax[2])
+                minmax[2] = Kb[0].y;
+        }
+        else {
+            if(Kb[0].y > minmax[3])
+                minmax[3] = Kb[0].y;
+            if(Ka[2].y < minmax[2])
+                minmax[2] = Ka[2].y;
+        }
+        if(Ka[2].z > Kb[0].z) {
+            if(Ka[2].z > minmax[5])
+                minmax[5] = Ka[2].z;
+            if(Kb[0].z < minmax[4])
+                minmax[4] = Kb[0].z;
+        }
+        else {
+            if(Kb[0].z > minmax[5])
+                minmax[5] = Kb[0].z;
+            if(Ka[2].z < minmax[4])
+                minmax[4] = Ka[2].z;
+        }
+        //
+        if(Kb[1].x > Kb[2].x) {
+            if(Kb[1].x > minmax[1])
+                minmax[1] = Kb[1].x;
+            if(Kb[2].x < minmax[0])
+                minmax[0] = Kb[2].x;
+        }
+        else {
+            if(Kb[2].x > minmax[1])
+                minmax[1] = Kb[2].x;
+            if(Kb[1].x < minmax[0])
+                minmax[0] = Kb[1].x;
+        }
+        if(Kb[1].y > Kb[2].y) {
+            if(Kb[1].y > minmax[3])
+                minmax[3] = Kb[1].y;
+            if(Kb[2].y < minmax[2])
+                minmax[2] = Kb[2].y;
+        }
+        else {
+            if(Kb[2].y > minmax[3])
+                minmax[3] = Kb[2].y;
+            if(Kb[1].y < minmax[2])
+                minmax[2] = Kb[1].y;
+        }
+        if(Kb[1].z > Kb[2].z) {
+            if(Kb[1].z > minmax[5])
+                minmax[5] = Kb[1].z;
+            if(Kb[2].z < minmax[4])
+                minmax[4] = Kb[2].z;
+        }
+        else {
+            if(Kb[2].z > minmax[5])
+                minmax[5] = Kb[2].z;
+            if(Kb[1].z < minmax[4])
+                minmax[4] = Kb[1].z;
+        }
+        i += 2;
+    }
+    if((pTh->nbe)%2 == 1) {
+        const Triangle3& Ka(pTh->be(i));
+        if(Ka[0].x > Ka[1].x) {
+            if(Ka[0].x > minmax[1])
+                minmax[1] = Ka[0].x;
+            if(Ka[1].x < minmax[0])
+                minmax[0] = Ka[1].x;
+        }
+        else {
+            if(Ka[1].x > minmax[1])
+                minmax[1] = Ka[1].x;
+            if(Ka[0].x < minmax[0])
+                minmax[0] = Ka[0].x;
+        }
+        if(Ka[0].y > Ka[1].y) {
+            if(Ka[0].y > minmax[3])
+                minmax[3] = Ka[0].y;
+            if(Ka[1].y < minmax[2])
+                minmax[2] = Ka[1].y;
+        }
+        else {
+            if(Ka[1].y > minmax[3])
+                minmax[3] = Ka[1].y;
+            if(Ka[0].y < minmax[2])
+                minmax[2] = Ka[0].y;
+        }
+        if(Ka[0].z > Ka[1].z) {
+            if(Ka[0].z > minmax[5])
+                minmax[5] = Ka[0].z;
+            if(Ka[1].z < minmax[4])
+                minmax[4] = Ka[1].z;
+        }
+        else {
+            if(Ka[1].z > minmax[5])
+                minmax[5] = Ka[1].z;
+            if(Ka[0].z < minmax[4])
+                minmax[4] = Ka[0].z;
+        }
+
+        if(Ka[2].x < minmax[0])
+            minmax[0] = Ka[2].x;
+        else if(Ka[2].x > minmax[1])
+            minmax[1] = Ka[2].x;
+        if(Ka[2].y < minmax[2])
+            minmax[2] = Ka[2].y;
+        else if(Ka[2].y > minmax[3])
+            minmax[3] = Ka[2].y;
+        if(Ka[2].z < minmax[4])
+            minmax[4] = Ka[2].z;
+        else if(Ka[2].z > minmax[5])
+            minmax[5] = Ka[2].z;
+    }
+    KN<double>* bb = GetAny<KN<double>* >((*arrayBB)(stack));
+    *bb = minmax;
+
+    return 0L;
+}
+
+long long_to_double(KN<double>* const& A, KN<long>* const& B) {
+    for(int i = 0; i < B->n; ++i)
+        A->operator[](i) = B->operator[](i);
+    return 0L;
+}
+
+long findDiff(KN<double>* const& array, KN<long>* const& val) {
+    std::set<double> vals;
+    for(unsigned int i = 0; i < array->n; ++i)
+        vals.insert(array->operator[]((int)i));
+    val->resize(vals.size());
+    unsigned short i = 0;
+    for(std::set<double>::iterator it = vals.begin(); it != vals.end(); ++it, ++i)
+        val->operator[]((int)i) = *it;
+    return 0L;
+}
+
+#ifndef _ALL_IN_ONE_
+/* --FH:   class Init {
+    public:
+        Init();
+};
+
+Init ...; */
+static void Load_Init() {
+    Global.Add("bb2d", "(", new Boundingbox2D);
+    Global.Add("bb3d", "(", new Boundingbox3D);
+    Global.Add("fast", "(", new OneOperator2_<long, KN<double>*, KN<long>*>(long_to_double));
+    Global.Add("findDiff", "(", new OneOperator2_<long, KN<double>*, KN<long>*>(findDiff));
+}
+ LOADFUNC(Load_Init)
+#endif
+
diff --git a/examples++-other/Makefile.am b/examples++-other/Makefile.am
new file mode 100644
index 0000000..699f4ae
--- /dev/null
+++ b/examples++-other/Makefile.am
@@ -0,0 +1,5 @@
+# $Id$
+TESTS=lap3-cpu.edp
+EXTRA_DIST=*.edp speedtest.sh
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPP) FLAGS_FFPP=-nw
diff --git a/examples++-other/graphics-benchmark.edp b/examples++-other/graphics-benchmark.edp
new file mode 100644
index 0000000..58ca2a0
--- /dev/null
+++ b/examples++-other/graphics-benchmark.edp
@@ -0,0 +1,127 @@
+// Profiling script, adapted from
+// examples++-tutorial/NSUzawaCahouetChabart.edp
+// (chosen for the large amount of graphics it displays)
+
+// correct bug in CahuetChabard routine 
+// sign of pressure correct 
+// and change Bx, By in Bx' By' (back and forth) in  version>1.18
+//  correction in CahouetChabard routine in version 1.26
+ 
+assert(version>1.18); //  for big bug is non symetric matrix see HISTORY 
+real s0=clock();
+mesh Th=square(10,10);
+fespace Xh(Th,P2),Mh(Th,P1);
+Xh u1,u2,v1,v2;
+Mh p,q,ppp;
+real[int] pwork(p.n);
+
+int i=0;
+real one =1;
+varf bx(u1,q) = int2d(Th,qforder=4)( dx(u1)*q ); 
+
+varf by(u1,q) = int2d(Th,qforder=4)( dy(u1)*q );
+
+varf a(u1,u2)= int2d(Th,qforder=4)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) )
+                   +  on(3,u1=1)  +  on(1,2,4,u1=0)  ;
+
+
+varf vfMass(p,q) = int2d(Th)(p*q);
+matrix MassMh=vfMass(Mh,Mh,solver=CG);
+p[]=1;
+ppp[]= MassMh*p[];
+real aire = ppp[].sum;
+cout << " area of Omega = " << aire << endl;
+Xh bc1; bc1[] = a(0,Xh);
+Xh b;
+                   
+matrix A= a(Xh,Xh,solver=CG); 
+matrix Bx= bx(Xh,Mh); //  Mh corresponding to line and Xh to column
+matrix By= by(Xh,Mh);
+Xh bcx=(1-x)*x*4,bcy=0;
+Xh b1=0,b2=0;  //  right hand side (0) for Stokes 
+
+func real[int] divup(real[int] & pp)
+{ 
+   pwork= MassMh*pp;
+   cout << " pp moy = " << pwork.sum/aire << " " ;
+   pp -= pwork.sum/aire;;
+   b = b1; b[]  += Bx'*pp; b[] += bc1[] .*bcx[];
+   u1[] = A^-1*b[];
+   b = b2; b[]  += By'*pp; b[] += bc1[] .*bcy[];
+   u2[] = A^-1*b[];
+   ppp[]  =   Bx*u1[];
+   ppp[] +=   By*u2[];
+   pwork= MassMh*ppp[];
+   cout << " moy = " << pwork.sum/aire << endl;
+ //   ppp[] -=  pwork.sum/aire;
+   return ppp[] ;
+};
+
+
+p=0;q=0;u1=0;v1=0;
+//cout << " -------- A = " << A << endl;
+        
+LinearCG(divup,p[],q[],eps=1.e-6,nbiter=50);
+divup(p[]);
+
+plot([u1,u2],p,wait=0,value=true,coef=0.1);
+
+real dt=0.05, alpha=1/dt;
+if ( alpha > 1e30) exit(1);
+real xnu=1./400.;
+cout << " alpha = " << alpha << " nu = " << xnu << endl;
+cout << "------------------------------------------ " << endl;
+varf at(u1,u2)=   int2d(Th)( xnu*dx(u1)*dx(u2) + xnu*dy(u1)*dy(u2)  + u1*u2*alpha  ) 
+               +  on(3,u1=1)  +  on(1,2,4,u1=0)  ;
+
+A = at(Xh,Xh,solver=CG);
+//cout << " -------- AA = " << AA << endl;
+
+varf  vfconv1(uu,vv)  = int2d(Th,qforder=5) (convect([u1,u2],-dt,u1)*vv*alpha);
+varf  vfconv2(v2,v1)  = int2d(Th,qforder=5) (convect([u1,u2],-dt,u2)*v1*alpha);
+int idt;
+real temps=0; 
+
+Mh pprec,prhs;
+
+varf vfLap(p,q)  = int2d(Th)(dx(p)*dx(q) + dy(p)*dy(q) + p*q*1e-3);
+matrix LapMh= vfLap(Mh,Mh,solver=Cholesky,factorize=true);
+
+real[int] unMh(pprec.n);
+pprec[]=1; 
+unMh = MassMh*pprec[]; 
+ 
+   
+
+func real[int]  CahouetChabart(real[int] & xx)
+{   //  xx = \int (div u) w_i
+   //   $ \alpha \Delta^{-1}  + \nu I $ 
+   //   $ \alpha \LapMh ^{-1}  + \nu MassMh^-1 $ 
+   real mxx= unMh'*xx;
+   xx -= mxx*Th.area;
+   pprec[]= LapMh^-1* xx; 
+   prhs[] =  MassMh^-1*xx;
+   pprec[] = alpha*pprec[]+xnu* prhs[];
+//   xx = LapMh*pprec[];
+//   pprec[] -= xx.sum;
+   return pprec[];
+};
+
+Xh up1,up2;
+for (idt = 1; idt < 50; idt++)
+ {
+    up1=u1;
+    up2=u2;
+   temps += dt;
+   cout << " --------- temps " << temps << " \n ";
+   b1[] =  vfconv1(0,Xh);
+   b2[] =  vfconv2(0,Xh);
+   cout << "  min b1 b2  " << b1[].min << " " << b2[].min 
+        << "  max b1 b2  " << b1[].max << " " << b2[].max << endl;
+   LinearCG(divup,p[],q[],eps=-1.e-6,nbiter=50,precon=CahouetChabart);
+   divup(p[]); 
+   real errl2 = sqrt(int2d(Th)( (u1-up1)^2 + (u2-up2)^2 ) );
+   cout << " errl2 " << errl2 << endl;
+   plot([u1,u2],p,wait=0,value= 1,coef=0.1,cmm="[u1,u2],p || u^n+1 - u^n ]]_L2 ="+errl2);     
+   if (errl2 < 1e-4) break;
+ }
diff --git a/examples++-other/lap3-cpu.edp b/examples++-other/lap3-cpu.edp
new file mode 100644
index 0000000..2fad915
--- /dev/null
+++ b/examples++-other/lap3-cpu.edp
@@ -0,0 +1,80 @@
+//  a example to test the level of optimisation
+// --------------------------------------------
+int nn=300;
+ mesh Th=square(nn,nn);
+verbosity=5;
+ fespace Vh(Th,P1);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+
+ problem laplace0(uh,vh,solver=Cholesky,tgv=1e30) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  + int1d(Th,1)( - vh)
+  + int2d(Th)( -f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+ problem laplace1(uh,vh,solver=CG,tgv=1e30) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  + int1d(Th,1)( - vh)
+  + int2d(Th)( -f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+ problem laplaceLU(uh,vh,solver=LU,tgv=1e30) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  + int1d(Th,1)( - vh)
+  + int2d(Th)( -f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+ problem laplaceCrout(uh,vh,solver=Crout,tgv=1e30) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  + int1d(Th,1)( - vh)
+  + int2d(Th)( -f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+real cpu=clock() ;
+laplace0; // solve the problem plot(uh); // to see the result
+cout << "-- lap Cholesky " << nn << "x" << nn << "  : " <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
+uh=0;
+cpu=clock() ;
+laplace1; // solve the problem plot(uh); // to see the result
+cout << "-- lap CG       " << nn << "x" << nn << "  : " <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
+uh=0;
+
+cpu=clock() ;
+laplaceLU; // solve the problem plot(uh); // to see the result
+cout << "-- lap LU       " << nn << "x" << nn << "  : " <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
+uh=0;
+
+cpu=clock() ;
+laplaceCrout; // solve the problem plot(uh); // to see the result
+cout << "-- lap Crout    " << nn << "x" << nn << "  : " <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
+
+// FFCS: reference value for regression tests
+real regtest=uh[].max;
+
+uh=0;
+
+if(HaveUMFPACK){
+  problem laplace2(uh,vh,solver=UMFPACK,tgv=1e30) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+    + int1d(Th,1)( uh*vh) 
+    + int1d(Th,1)( - vh)
+    + int2d(Th)( -f*vh )                          //  linear form
+    + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+  cpu=clock(); 
+  laplace2; // solve the problem plot(uh); // to see the result
+  cout << "-- lap UMFPACK  " << nn << "x" << nn << "  : "
+       <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
+}
+else{
+  cout << "-- lap UMFPACK  " << nn << "x" << nn << "  : "
+       <<  "not available" << endl;
+}
+
+//  plot(uh,ps="lap1-cpu.eps",value=true);
diff --git a/examples++-other/speedtest.sh b/examples++-other/speedtest.sh
new file mode 100755
index 0000000..1772545
--- /dev/null
+++ b/examples++-other/speedtest.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# Speed benchmark for FreeFem++
+# $Id$
+
+# The FreeFem++ executable
+ffexe=${PROGLOC}/nw/FreeFem++-nw${EXEEXT}
+if test ! -x $ffexe
+then
+    echo $ffexe non existent
+    exit 1
+fi
+
+# Write some build information into the trace file
+echo ------------------------------------------- >> speedtest.out
+date >> speedtest.out
+echo CXXFLAGS=$CXXFLAGS >> speedtest.out
+
+# Run the actual test
+$ffexe lap3-cpu.edp	\
+		|grep -E --					\
+		'-- lap (Cholesky|CG|UMFPACK|LU|Crout) +[0-9]+x[0-9]+'	\
+		|tee -a speedtest.out
+if test $PIPESTATUS != 0
+    then
+    exit 1
+fi
diff --git a/examples++-tutorial/._NSUzawaCahouetChabart.edp b/examples++-tutorial/._NSUzawaCahouetChabart.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-tutorial/._NSUzawaCahouetChabart.edp differ
diff --git a/examples++-tutorial/._cavityNewtow.edp b/examples++-tutorial/._cavityNewtow.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-tutorial/._cavityNewtow.edp differ
diff --git a/examples++-tutorial/._schwarz-no-overlap.edp b/examples++-tutorial/._schwarz-no-overlap.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-tutorial/._schwarz-no-overlap.edp differ
diff --git a/examples++-tutorial/._string.edp b/examples++-tutorial/._string.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++-tutorial/._string.edp differ
diff --git a/examples++-tutorial/AdaptResidualErrorIndicator.edp b/examples++-tutorial/AdaptResidualErrorIndicator.edp
new file mode 100644
index 0000000..054853d
--- /dev/null
+++ b/examples++-tutorial/AdaptResidualErrorIndicator.edp
@@ -0,0 +1,113 @@
+// macro the get the current mesh size 
+// parameter 
+//  in:  Th the mesh
+//       Vh  P1 fespace on Th
+//  out : 
+// h: the Vh finite element finite set to the current mesh size 
+macro  MeshSizecomputation(Th,Vh,h)
+{  /* Th mesh
+	 Vh  P1 finite element space 
+	 h   the P1 mesh size value */
+	real[int]  count(Th.nv);
+	/* mesh size  (lenEdge = $\int_e 1$)  */
+	varf vmeshsizen(u,v)=intalledges(Th,qfnbpE=1)(v); 
+	/* number of edge / par vertex */ 
+	varf vedgecount(u,v)=intalledges(Th,qfnbpE=1)(v/lenEdge); 
+   /*
+	  computation of the mesh size
+	  ----------------------------- */ 
+	count=vedgecount(0,Vh);
+	h[]=0.;
+	h[]=vmeshsizen(0,Vh);
+	cout << " count min = "<< count.min << " " << count.max << endl;
+	h[]=h[]./count;
+    cout << " -- bound meshsize = " <<h[].min << " " << h[].max << endl;
+} // end of macro MeshSizecomputation
+
+// macro to remesh according the de residual indicator 
+// in: 
+//     Th the mesh
+//     Ph  P0 fespace on Th
+//     Vh  P1 fespace on Th
+//     vindicator the varf of to evaluate the indicator to ^2
+//     coef on etameam ..
+// ------
+macro  ReMeshIndicator(Th,Ph,Vh,vindicator,coef)
+{
+	Vh h=0;
+	/*evalutate the mesh size  */
+	MeshSizecomputation(Th,Vh,h); 
+	Ph etak;  
+	etak[]=vindicator(0,Ph);
+	cout << " global  Eta  : " << sqrt(etak[].sum) << "  ......... " <<  Th.nv<< endl;
+	etak[]=sqrt(etak[]); 
+        plot(etak,ps="arei-etak.eps",fill=1,value=1);
+	real etastar= coef*(etak[].sum/etak[].n);
+	cout << " etastar = " << etastar << " sum=" << etak[].sum << " " << endl;
+
+	/* here etaK is discontinous 
+	   we use the P1 L2 projection with mass lumping . */
+	
+	Vh fn,sigma;
+	varf veta(unused,v)=int2d(Th)(etak*v);
+	varf vun(unused,v)=int2d(Th)(1*v);
+	fn[]  = veta(0,Vh);
+	sigma[]= vun(0,Vh);
+	fn[]= fn[]./ sigma[];
+	fn =  max(min(fn/etastar,3.),0.3333) ; 
+	
+	/* new mesh size */ 
+	h = h / fn ; 
+	/* plot(h,wait=1); */
+	Th=adaptmesh(Th,IsMetric=1,h,splitpbedge=1,nbvx=10000);
+}
+
+// the classical  L space problem. 
+
+// mesh definition 
+border ba(t=0,1.0){x=t;   y=0;  label=1;}; 
+border bb(t=0,0.5){x=1;   y=t;  label=2;};
+border bc(t=0,0.5){x=1-t; y=0.5;label=3;};
+border bd(t=0.5,1){x=0.5; y=t;  label=4;};
+border be(t=0.5,1){x=1-t; y=1;  label=5;};
+border bf(t=0.0,1){x=0;   y=1-t;label=6;};
+mesh Th = buildmesh (ba(6) + bb(4) + bc(4) +bd(4) + be(4) + bf(6));
+
+// FE space definition ---
+fespace Vh(Th,P1); // for the mesh size 
+fespace Ph(Th,P0); // for the indicator   
+
+real hinit=0.2; // 
+Vh   h=hinit; // the FE fonction  for the mesh size 
+// to build a mesh with a given mesh size  : meshsize
+Th=adaptmesh(Th,h,IsMetric=1,splitpbedge=1,nbvx=10000);
+plot(Th,wait=1,ps="RRI-Th-init.eps");
+
+Vh u,v; 
+
+func f=(x-y);
+
+problem Poisson(u,v) =
+    int2d(Th,qforder=5)( u*v*1.0e-10+  dx(u)*dx(v) + dy(u)*dy(v)) 
+  - int2d(Th,qforder=5)( f*v);
+
+ varf indicator2(unused,chiK) = 
+     intalledges(Th)(chiK*lenEdge*square(jump(N.x*dx(u)+N.y*dy(u))))
+    +int2d(Th)(chiK*square(hTriangle*(f+dxx(u)+dyy(u))) );
+
+
+
+
+for (int i=0;i< 10;i++)
+{
+	u=u;
+	Poisson;
+	plot(Th,u,wait=1);
+	real cc=0.7;
+	if(i>5) cc=1;
+        if(i<9)
+	 ReMeshIndicator(Th,Ph,Vh,indicator2,cc);
+	plot(u,Th,wait=1,ps="arei-Thu.eps",value=1);
+}
+
+
diff --git a/examples++-tutorial/BEM-C.edp b/examples++-tutorial/BEM-C.edp
new file mode 100644
index 0000000..508017f
--- /dev/null
+++ b/examples++-tutorial/BEM-C.edp
@@ -0,0 +1,95 @@
+//  compute the solution of a Laplace operator in a Semi infini domain.
+//  with coupling of Boundary element with periodicity BC in x . 
+// -------------------------------------------------------------
+real eps0=0.1;
+int labup=3;
+int nharm= 50; // Number of  Harmonique
+
+ 
+
+macro Grad(u) [dx(u),dy(u)] // eom
+real R=0.75;
+border C00(t=0,2*pi) { x=0.5+0.2*cos(t); y=0.2*sin(t); label=1;}
+border C01(t=0,2*pi) { x=-0.5+0.2*cos(t); y=0.2*sin(t); label=2;}
+border C1(t=0,2*pi) { x=R*cos(t); y=R*sin(t); label=3;}
+border C2(t=0,2*pi) { x=30*cos(t); y=30*sin(t); label=4;}
+
+mesh Th=buildmesh(C1(100)+C01(100)+C00(100));
+fespace Vh(Th,P1);
+
+Vh uref; // la solution de reference. 
+
+{ // calcule de la solution de reference in  Huge Domaine.
+mesh Th1=buildmesh(C2(100)+C1(100)+C01(100)+C00(100));; // pour la solution de reference 
+fespace Uh(Th1,P1);
+Uh uu,vv;
+solve Pref(uu,vv)=int2d(Th1)(eps0*(Grad(uu)'*Grad(vv)))+on(1,uu=1)+on(2,uu=-1);
+ uref=uu; 
+ plot(uu,wait=1,cmm=" ref sol / large Th ");
+} // pour nettoyer la memoire
+
+plot(uref,wait=1,cmm=" ref sol / Th");
+
+
+varf vP(u,v)=int2d(Th)(eps0*(Grad(u)'*Grad(v)))+on(1,u=1)+on(2,u=-1);
+matrix<complex> A=vP(Vh,Vh);  // la matrice sans BEM. 
+complex[int] b=vP(0,Vh);
+Vh<complex> u;
+
+{// for cleanning all local varaible at end of block.
+ // computation of the matrice BEM
+ int kdfBEM=0; // nb of  DoF on border 
+ int[int] IdfB2Vh(0:Vh.ndof-1); // for numbering IdfB2Vh[i]==i 
+ {
+ int lbord = labup; // label of the BEM border
+ varf vbord(u1,v1) = on(lbord,u1= atan(y,-x)-2*pi);//  negative value ..
+ real[int] xb=vbord(0,Vh,tgv=1);
+ sort(xb,IdfB2Vh); // sort of  array  xb and IdfB2Vh
+ xb = xb ? 1 : 0;//  put 1 if none zero
+ kdfBEM = xb.sum +0.5; //  number of DoF on border 
+ IdfB2Vh.resize(kdfBEM);  // IdfB2Vh[i] -> number DoF of border 
+ }
+//  end of the numbering computation
+ // so  IdfB2Vh[ibem] = iVh where ibem is a df of on bem , and iVh is a df in Vh space. 
+
+   complex  cci=1i;
+   int n=0;// 
+   // Use of higher order Quadarture formular ...
+   varf vWn(u,w)=int1d(Th,3,qforder=7)(exp(-cci*n*atan2(y,x))*w);
+   // Lap  polar :  1/r^2 u_tt + u_rr + 1/u u_r  (t = theta ) 
+   // see http://www.medphys.ucl.ac.uk/~mbanaji/MATH6502/LaplacePolar.pdf
+   //   f_n = exp( i ( n  theta) )  gn(r) , a mode .. 
+   //  -  n^2 gn + gn'r + r^2 gn'' = 0
+   // find gn = r^l =>  l = ± n  so gn = c1 r^n + c2 r^-n
+   // if n = 0;  then g0 = c1 + c2 log(r)  => g0 = 1 
+   //   BC 0 a infinity , gn =1 on R 
+   // gives           
+   //  gn = R^|n| r^-|n|
+   //  gn'   =   -R^|n| |n| gn / r 
+   //  gn''  =   -R^|n| |n|(-|n|-1) gn / r^2   => OK 
+   
+   
+   complex[int,int] ABemFull(kdfBEM,kdfBEM);// the full bem matrix in Bem numbering.
+   ABemFull=0;//  set of 0 
+   for ( n=-nharm;n<=nharm;++n)
+    {
+    	complex[int] wwn(kdfBEM);
+    	complex[int] wn=vWn(0,Vh);
+    	wwn=wn(IdfB2Vh);
+        complex Gn=abs(n)*eps0/(2*pi)/R^2; 
+    	ABemFull += Gn*wwn*wwn';
+    }
+    
+ 
+  matrix<complex> ABem=ABemFull(IdfB2Vh^-1,IdfB2Vh^-1); // Build the sparse BEm matrix
+  A = A + ABem;
+  }// for cleanning all local varaible at end of block. ABem ABemFull
+  set(A,solver=UMFPACK);
+  u[]=A^-1*b;
+  Vh ur=real(u),ui=imag(u);
+  Vh  err=ur-uref;
+  cout << " err Linty=" << err[].linfty << " /  " <<  uref[].linfty << endl; 
+
+  plot(ur,uref,wait=1,cmm="ur + uref ");
+
+    
diff --git a/examples++-tutorial/BEM.edp b/examples++-tutorial/BEM.edp
new file mode 100644
index 0000000..8eacd48
--- /dev/null
+++ b/examples++-tutorial/BEM.edp
@@ -0,0 +1,86 @@
+//  compute the solution of a Laplace operator in a Semi infini domain.
+//  with coupling of Boundary element with periodicity BC in x . 
+// -------------------------------------------------------------
+real eps0=1;
+int labup=3, labdown=1;
+int nharm= 10; // Number of  Harmonique
+
+func ug= max(0.,-(x-0.5)*(x-0.75)); // boundary condition.. 
+
+macro Grad(u) [dx(u),dy(u)] // eom
+
+
+real Xmax=1,Ymax=0.3;
+int NNx=100,NNy=NNx*Ymax;
+mesh Th=square(NNx,NNy,[x*Xmax,y*Ymax]); 
+fespace Vh(Th,P1,periodic=[[2,y],[4,y]]);
+
+Vh uref; // la solution de reference. 
+
+{ // calcule de la solution de reference in  Huge Domaine.
+mesh Th1=square(NNx,NNx*10,[x*Xmax,10*Xmax*y]); // pour la solution de reference 
+fespace Uh(Th1,P1,periodic=[[2,y],[4,y]]);
+Uh uu,vv;
+solve Pref(uu,vv)=int2d(Th1)(eps0*(Grad(uu)'*Grad(vv)))+on(labdown,uu=ug);
+ uref=uu; 
+ plot(uu,wait=1,cmm=" ref sol / large Th ");
+} // pour nettoyer la memoire
+
+plot(uref,wait=1,cmm=" ref sol / Th");
+
+
+varf vP(u,v)=int2d(Th)(eps0*(Grad(u)'*Grad(v)))+on(labdown,u=ug);
+varf vF(u,v)=on(labdown,u=ug);
+matrix<complex> A=vP(Vh,Vh);  // la matrice sans BEM. 
+
+complex[int] b=vF(0,Vh);
+Vh<complex> u;
+
+{// for cleanning all local varaible at end of block.
+ // computation of the matrice BEM
+ int kdfBEM=0; // nb of  DoF on border 
+ int[int] IdfB2Vh(0:Vh.ndof-1); // for numbering IdfB2Vh[i]==i 
+ {
+ int lbord = labup; // label of the BEM border
+ varf vbord(u1,v1) = on(lbord,u1=x-10);//  negative value ..
+ real[int] xb=vbord(0,Vh,tgv=1);
+ sort(xb,IdfB2Vh); // sort of  array  xb and IdfB2Vh
+ xb = xb ? 1 : 0;//  put 1 if none zero
+ kdfBEM = xb.sum +0.5; //  number of DoF on border 
+ IdfB2Vh.resize(kdfBEM);  // IdfB2Vh[i] -> number DoF of border 
+ }
+//  end of the numbering computation
+ // so  IdfB2Vh[ibem] = iVh where ibem is a df of on bem , and iVh is a df in Vh space. 
+   real perio=Xmax;
+   complex  deuxpii=2*pi*1i;
+   int n=0;// 
+   // Use of higher order Quadarture formular ...
+   varf vWn(u,w)=int1d(Th,labup,qforder=10)(exp(-deuxpii*(n)*x)*w);
+      
+   //complex[int] wn=vWn(0,Vh);//  with Vh numbering.. 
+
+   complex[int,int] ABemFull(kdfBEM,kdfBEM);// the full bem matrix in Bem numbering.
+   ABemFull=0;//  set of 0 
+   for ( n=-nharm;n<=nharm;++n)
+    {
+    	complex[int] wwn(kdfBEM);
+    	complex[int] wn=vWn(0,Vh);
+    	wwn=wn(IdfB2Vh);//  wwn(i) = wn(IdfB2Vh(i))  i=0 a wwn.n -1 
+        complex Gs=+2.*pi*abs(n/perio/perio)*eps0;
+    	ABemFull += Gs*wwn*wwn';
+    }
+    
+ 
+  matrix<complex> ABem=ABemFull(IdfB2Vh^-1,IdfB2Vh^-1); // Build the sparse BEm matrix
+   //  ABem(IdfB2Vh(ib),IdfB2Vh(jb)) = ABemFull(ib,jb) 
+  A = A + ABem;
+  }// for cleanning all local varaible at end of block. ABem ABemFull
+  set(A,solver=UMFPACK);
+  u[]=A^-1*b;
+  Vh ur=real(u),ui=imag(u);
+  Vh  err=ur-uref;
+  cout << " err Linty=" << err[].linfty << " /  " <<  uref[].linfty << endl; 
+
+  plot(ur,uref,wait=1,cmm="ur + uref ");
+
+    
diff --git a/examples++-tutorial/FE.edp b/examples++-tutorial/FE.edp
new file mode 100644
index 0000000..fa654a5
--- /dev/null
+++ b/examples++-tutorial/FE.edp
@@ -0,0 +1,53 @@
+//  test all FEspace
+verbosity=10;
+mesh Th=square(5,5);
+verbosity = 10;
+cout << " P0 " << endl;
+fespace Ph(Th,P0);
+cout << " P1 " << endl;
+fespace Vh(Th,P1);
+cout << " P2 " << endl;
+fespace Wh(Th,P2);
+cout << " nb of degre of freedom           : " << Wh.ndof << endl;
+cout << " nb of degre of freedom / ELEMENT : " << Wh.ndofK << endl;
+//*  don't work to day in progresse
+{
+ int k= 2;
+ int kdf= Wh.ndofK ;
+cout << " df of element " << k << ":" ;
+for (int i=0;i<kdf;i++)
+  cout << Wh(k,i) << " ";
+ cout << endl;
+}
+//*/
+cout << " P1nc " << endl;
+fespace Vnch(Th,P1nc);
+Vnch u1nc=x+10*y;
+cout << " Interpola P1nc : " << int2d(Th)(square(u1nc-(x+10*y))) << endl;
+
+cout << " P2dc " << endl;
+fespace Wdch(Th,P2dc);
+
+cout << " P1dc " << endl;
+fespace Vdch(Th,P1dc);
+Vdch u1dc=x+10*y;
+cout << " Interpola P1dc : " << int2d(Th)(square(u1dc-(x+10*y))) << endl;
+
+Wh w=x*x*y,dxw=2*x*y;
+
+Vdch vdc = dx(w);
+Wdch wdc = dx(w)*x;
+plot(vdc,dxw,wait=1);
+plot(wdc);
+Vnch vnc = x*x;
+Vh vh = x*x;
+Ph p = x*x;
+
+{
+func f=x*x+10*y*y+50*x*y;
+cout << " P2b " << endl;
+fespace Wh2b(Th,P2);
+Wh2b vh=f;
+cout << " ?? " << vh(0.1,0.4) << " == " << f(0.1,0.4) <<  " diff = " << vh(0.1,0.4) - f(0.1,0.4) <<endl;
+assert( abs(vh(0.1,0.4) - f(0.1,0.4)) < 1e-12 );
+}
diff --git a/examples++-tutorial/FEComplex.edp b/examples++-tutorial/FEComplex.edp
new file mode 100644
index 0000000..5bdc249
--- /dev/null
+++ b/examples++-tutorial/FEComplex.edp
@@ -0,0 +1,51 @@
+//  test all FEspace
+verbosity=2;
+real a=real(1+1i);
+verbosity=2;
+mesh Th=square(5,5);
+verbosity = 2;
+cout << " P0 " << endl;
+fespace Ph(Th,P0);
+cout << " P1 " << endl;
+fespace Vh(Th,P1);
+fespace Wh(Th,RT0);
+Vh<real> v=x,diff;
+Vh<complex> w=x+1i*y;
+cout << "w[][10] "  << " " << w[][10] << endl;
+w=y+1i*y;
+cout << "w[][10] " << w[][10] << " " << (w[][10])' << endl;
+Wh<complex> [wx,wy]=[x+1i*y,y];
+[wx,wy]=[x+1i*y,y];
+
+func ue= (x*x+2.*y*y+(x*y*y+3.*x*x*y)*1i);
+func uexx = 2.+6.i*y;
+func ueyy = 4.+2.i*x;
+
+func f= (-uexx-(2i+1)*ueyy);
+func g= ue;
+Vh<complex> uh,vh;
+ problem laplace(uh,vh,solver=LU,tgv=1e5) =                    //  definion of  the problem 
+    int2d(Th,optimize=1)( dx(uh)*dx(vh) + (2i+1)*dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th,optimize=1)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+//verbosity=102;
+  laplace; // solve the problem plot(uh); // to see the result
+  real err = int2d(Th)(norm(uh-ue));
+  cout << " -- err = " << err << endl;
+  assert(err<0.01);
+//  cout << " -- uh = " << uh[] << endl;
+  cout << " uh(0.5,0.5) = " << uh(0.5,0.5) << " ~  " << ue(0.5,0.5) << endl;
+  Vh vr=real(uh(x,y));
+  Vh vi=imag(uh(x,y));
+  vr = real(uh);
+  vi = imag(uh);
+  Vh ver = real(ue);
+  Vh vei = imag(ue);
+
+ // for (int i=0;i<vi[].n;i++)
+ // vi[][i] = imag(uh[][i]);
+
+// now no complex plot 
+  plot(vr,ver,ps="Lr.eps",cmm="real",value=true,wait=1);
+  plot(vi,vei,ps="Li.eps",cmm="imag",value=true,wait=1);
+
diff --git a/examples++-tutorial/LapDG2.edp b/examples++-tutorial/LapDG2.edp
new file mode 100644
index 0000000..170eb69
--- /dev/null
+++ b/examples++-tutorial/LapDG2.edp
@@ -0,0 +1,53 @@
+//    Discontinous Galerlin Method
+//   based on paper from 
+// Riviere, Beatrice; Wheeler, Mary F.; Girault, Vivette
+// title: 
+// A priori error estimates for finite element 
+// methods based on discontinuous approximation spaces
+//  for elliptic problems.
+//  SIAM J. Numer. Anal. 39 (2001), no. 3, 902--931 (electronic).
+//  ---------------------------------
+//  Formulation given by Vivette Girault
+//  ------ 
+// Author: F. Hecht , december 2003
+// -------------------------------
+//   nonsymetric bilinear form
+//   ------------------------
+//  solve $ -\Delta u = f$ on $\Omega$ and $u= g$ on $\Gamma$
+macro dn(u) (N.x*dx(u)+N.y*dy(u) ) //  def the normal derivative 
+
+mesh Th = square(10,10); // unite square 
+fespace Vh(Th,P2dc);     // Discontinous P2 finite element
+fespace Xh(Th,P2);
+//  if param = 0 => Vh must be P2 otherwise we need some penalisation  
+real pena=0; // a paramater to add penalisation 
+varf Ans(u,v)= 
+   int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v)  )
+ + intalledges(Th)(//  loop on all  edge of all triangle 
+       // the edge are see nTonEdge times so we / nTonEdge
+       // remark: nTonEdge =1 on border edge and =2 on internal 
+       // we are in a triange th normal is the exterior normal
+       // def: jump = external - internal value; on border exter value =0
+       //      mean = (external + internal value)/2, on border just internal value
+            ( jump(v)*mean(dn(u)) -  jump(u)*mean(dn(v)) 
+          + pena*jump(u)*jump(v) ) / nTonEdge 
+)
+ + int1d(Th,3)(pena*0.*v)
+;
+func f=1;
+func g=0;
+Vh u,v;
+Xh uu,vv;
+problem A(u,v,solver=UMFPACK) = Ans 
+- int2d(Th)(f*v) 
+- int1d(Th)(g*dn(v)  + pena*g*v) 
+;
+problem A1(uu,vv,solver=CG) 
+= 
+ int2d(Th)(dx(uu)*dx(vv)+dy(uu)*dy(vv)) - int2d(Th)(f*vv) + on(1,2,3,4,uu=g);
+ 
+ A; // solve  DG
+ A1; // solve continuous
+
+plot(u,uu,cmm="Discontinue Galerkin",wait=1,value=1);
+plot(u,cmm="Discontinue Galerkin",wait=1,value=1,fill=1);
diff --git a/examples++-tutorial/Laplace-RHS-Dirac.edp b/examples++-tutorial/Laplace-RHS-Dirac.edp
new file mode 100644
index 0000000..5596a6b
--- /dev/null
+++ b/examples++-tutorial/Laplace-RHS-Dirac.edp
@@ -0,0 +1,38 @@
+ // Laplace operator with RHS sum of Dirac 
+ //  f = sum  cdelta_i \delta_i
+ real[int] xdelta = [0.25,0.6];//  coord x de delta_i
+ real[int] ydelta = [0.25,0.6];//  coord x de delta_j
+ real[int] cdelta=[1.,2.];//  coef    delta_i
+  mesh Th=square(10,10);
+  verbosity=0;
+
+// Reference value for FFCS regression tests
+real ref;
+
+ for(int iter=0;iter < 13;iter++)
+ {
+
+ fespace Vh(Th,P1);     // P1 FE space
+ 
+ matrix D = interpolate(Vh,xdelta,ydelta); // the interpolation matrix  
+ // at point (xdelta[j],ydelta[i] ) \hfilll
+ // so $D_ij = w^i((xdelta[j],ydelta[i]) $ where $w^i$ are the basic function of $V_h$. 
+ 
+ Vh uh,vh;  // unkown and test function. 
+ func g=0;                 //  boundary condition function
+ Vh b;
+ b[]= D*cdelta;
+ b[]= -b[];
+ problem laplace(uh,vh) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + b[]                         //  linear form of the rhs (so an array)
+  + on(1,2,3,4,uh=0) ;          //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  cout <<iter << "max uh = " << uh[].max << " nv =  "<< Th.nv <<  endl; 
+  plot(uh,wait=1,dim=3,fill=1);
+  Th=adaptmesh(Th,uh,nbvx=100000,err= 0.01*1.15^-iter);
+  
+  // Reference value for FFCS regression tests
+  ref=uh[]'*uh[];//'
+  }
\ No newline at end of file
diff --git a/examples++-tutorial/Laplace-lagrange-mult.edp b/examples++-tutorial/Laplace-lagrange-mult.edp
new file mode 100644
index 0000000..2bd5290
--- /dev/null
+++ b/examples++-tutorial/Laplace-lagrange-mult.edp
@@ -0,0 +1,47 @@
+/*
+   solving   laplace operator with neumam boundary condition
+   with 1D lagrange multiplier
+   
+   The variationnal form is
+   find (u,l) such that
+
+   $\forall (v,m)   a(u,v) + b(u,m) + b(v,l) = L(v) $
+   where $b(u,m) = int u*m dx$
+   
+*/
+ mesh Th=square(10,10);
+ fespace Vh(Th,P1);     // P1 FE space
+int n = Vh.ndof;
+int n1 = n+1;
+
+ Vh uh,vh;              // unkown and test function. 
+ func f=1+x-y;                 //  right hand side function 
+  
+varf va(uh,vh) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+;
+varf vL(uh,vh)=  int2d(Th)( f*vh )  ;
+varf vb(uh,vh)= int2d(Th)(1.*vh);
+
+matrix A=va(Vh,Vh);
+
+real[int] b(n);
+b = vL(0,Vh);
+
+real[int]  B = vb(0,Vh); 	
+// the block matrix
+
+matrix AA = [ [ A ,  B ] ,
+              [ B', 0 ] ] ;
+
+real[int]  bb(n+1),x(n+1),b1(1),l(1);
+b1=0;
+// build the block rhs 
+bb = [ b, b1];
+set(AA,solver=UMFPACK);
+x = AA^-1*bb; // solve the linear systeme 
+
+[uh[],l] = x;  // set the value 
+cout << " l = " << l(0) <<  " ,  b(u,1)  =" << B'*uh[]  << endl;  
+plot(uh,wait=1);
+
diff --git a/examples++-tutorial/Laplace.cpp b/examples++-tutorial/Laplace.cpp
new file mode 100644
index 0000000..56f7f15
--- /dev/null
+++ b/examples++-tutorial/Laplace.cpp
@@ -0,0 +1,59 @@
+/*!
+ * \file 
+ * 
+ * \brief C++ version of Laplace.edp test script
+ * 
+ * 
+ * \author Written by Antoine Le Hyaric
+ * \author Laboratoire Jacques-Louis Lions
+ * \author Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+ * \author http://www.ljll.math.upmc.fr/lehyaric
+ * 
+ * \copyright This file is part of Freefem++
+ * 
+ * \copyright Freefem++ is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * \copyright Freefem++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * 
+ * \copyright You should have received a copy of the GNU Lesser General Public
+ * License along with Freefem++; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * 
+ * headeralh brief="C++ version of Laplace.edp test script" cpp default=0 dox freefem upmc written
+ */
+
+// [[file:~/ff/loc/src/fflib/ffapi.hpp::API]]
+#include "../src/fflib/ffapi.hpp"
+
+int main(int argc,char *argv[]){
+
+  // ffapi mention is required for Doxygen to distinguish ffapi::mesh and ::mesh
+  ffapi::mesh Th=ffapi::square(10,10);
+
+  fespace Vh(Th,P1);     // P1 FE space
+  Vh uh,vh;              // unkown and test function. 
+  func f=1;                 //  right hand side function 
+  func g=0;                 //  boundary condition function
+ 
+  problem laplace(uh,vh,solver=GMRES,tgv=1e5) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+    - int2d(Th)( f*vh )                          //  linear form
+    + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="Laplace.eps",value=true);
+}
+
+/*!
+ * Local Variables:
+ * mode:c++
+ * ispell-local-dictionary:"british"
+ * coding:utf-8
+ * End:
+ */
diff --git a/examples++-tutorial/Laplace.edp b/examples++-tutorial/Laplace.edp
new file mode 100644
index 0000000..c3911c8
--- /dev/null
+++ b/examples++-tutorial/Laplace.edp
@@ -0,0 +1,13 @@
+ mesh Th=square(10,10);
+ fespace Vh(Th,P1);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh,solver=GMRES,tgv=1e5) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="Laplace.eps",value=true);
diff --git a/examples++-tutorial/LaplaceP1.edp b/examples++-tutorial/LaplaceP1.edp
new file mode 100644
index 0000000..44ecf03
--- /dev/null
+++ b/examples++-tutorial/LaplaceP1.edp
@@ -0,0 +1,15 @@
+ mesh Th=square(10,10);
+ fespace Vh(Th,P1);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh,solver=GMRES,tgv=1e5) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  - int1d(Th,1)( vh)
+  - int2d(Th)( f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP1.eps",value=true);
diff --git a/examples++-tutorial/LaplaceP1P2h.edp b/examples++-tutorial/LaplaceP1P2h.edp
new file mode 100644
index 0000000..9223864
--- /dev/null
+++ b/examples++-tutorial/LaplaceP1P2h.edp
@@ -0,0 +1,28 @@
+ mesh Th=square(10,10);
+ fespace Vh(Th,P1);     // P1 FE space
+ Vh uh,vh;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh,solver=CG) =          //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  - int1d(Th,1)( vh)
+  - int2d(Th)( f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="LaplaceP1P2h.eps",value=true);
+//  if error on macos version codeworrior 
+//  remove in panal  PPC linker FreeFEm++ Setting Dead-strip Static Initializition Code Flag
+  fespace V2h(Th,P2);
+ V2h u2h,v2h;              // unkown and test function. 
+
+ problem errorh (u2h,v2h,solver=CG) =           //  definion of  the problem 
+    int2d(Th)( dx(u2h)*dx(v2h) + dy(u2h)*dy(v2h) ) //  bilinear form
+  + int1d(Th,1)( u2h*v2h) 
+  - int1d(Th,1)( v2h)
+  - int2d(Th)( f*v2h )                          //  linear form
+  + on(2,3,4,u2h=g) ;                      //  boundary condition form
+ errorh;
+plot(u2h,ps="ErrorHerachical.ps",value=true,wait=1);
\ No newline at end of file
diff --git a/examples++-tutorial/LaplaceP1bis.edp b/examples++-tutorial/LaplaceP1bis.edp
new file mode 100644
index 0000000..d0bf70a
--- /dev/null
+++ b/examples++-tutorial/LaplaceP1bis.edp
@@ -0,0 +1,28 @@
+ mesh Th=square(10,10);
+ fespace Vh(Th,P1);     // P1 FE space
+ Vh uh,vh,u;              // unkown and test function. 
+ func f=1;                 //  right hand side function 
+ func g=0.;                 //  boundary condition function
+ 
+ problem laplace(uh,vh,solver=GMRES,tgv=1e5) =                    //  definion of  the problem 
+  - int2d(Th)( -dx(uh)*dx(vh) - dy(uh)*dy(vh) ) //  bilinear form
+  - int1d(Th,1)( -uh*vh) 
+  - int1d(Th,1)(  vh)
+  - int2d(Th)( f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+ problem laplacep(uh,vh,solver=CG,tgv=1e5) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int1d(Th,1)( uh*vh) 
+  + int1d(Th,1)( - vh)
+  + int2d(Th)( -f*vh )                          //  linear form
+  + on(2,3,4,uh=g) ;                      //  boundary condition form
+
+  
+  laplace; // solve the problem plot(uh); // to see the result
+  u=uh;
+  laplacep; // solve the problem plot(uh); // to see the result
+  
+  plot(uh,u,value=true);
+  u[] -= uh[];
+  cout << "Diff min = "<< u[].min << " max=" << u[].max << endl ;
diff --git a/examples++-tutorial/LaplaceRT.edp b/examples++-tutorial/LaplaceRT.edp
new file mode 100644
index 0000000..47a80cd
--- /dev/null
+++ b/examples++-tutorial/LaplaceRT.edp
@@ -0,0 +1,41 @@
+/*
+   Solving the following Poisson problem 
+   Find $p$, such that;
+   $ - \Delta p = f $   on $\Omega$, 
+   $ dp / dn = (g1d,g2d). n  $ on $\Gamma_{123}$ 
+   $ p = gd  $ on $\Gamma_{1}$ 
+  with de Mixte finite element formulation 
+   Find $p\in L^2(\Omega)   and $u\in H(div) $ such than  
+    u - Grad p = 0
+    - div u =  f
+   $  u. n = (g1d,g2d). n  $ on $\Gamma_{123}$
+   $ p = gd  $ on $\Gamma_{1}$
+
+   the variationnel form is:
+ $\forall v\in H(div)$;  $v.n = 0$ on $\Gamma_{4}\} $:    $ \int_\Omega  u v + p div v -\int_{\Gamma_{123}} gd* v.n  = 0 $
+
+ $\forall q\in L^2$:   $  -\int_\Omega q div u = \int_Omega f q  $ 
+and $ u.n = (g1n,g2n).n$ on $\Gamma_4$ 
+
+*/
+mesh Th=square(10,10);
+fespace Vh(Th,RT0);
+fespace Ph(Th,P0);
+
+func gd = 1.;
+func g1n = 1.;
+func g2n = 1.; 
+func f = 1.;
+
+Vh [u1,u2],[v1,v2];
+Ph p,q; 
+
+problem laplaceMixte([u1,u2,p],[v1,v2,q],solver=UMFPACK,eps=1.0e-10,tgv=1e30,dimKrylov=150) =
+   int2d(Th)( p*q*0e-10+ u1*v1 + u2*v2 + p*(dx(v1)+dy(v2)) + (dx(u1)+dy(u2))*q )
+ + int2d(Th) ( f*q)
+ - int1d(Th,1,2,3)( gd*(v1*N.x +v2*N.y))   //  int on gamma 
+ + on(4,u1=g1n,u2=g2n);
+
+ laplaceMixte;
+ plot([u1,u2],coef=0.1,wait=1,ps="lapRTuv.eps",value=true); 
+ plot(p,fill=1,wait=1,ps="laRTp.eps",value=true);  
diff --git a/examples++-tutorial/Makefile.am b/examples++-tutorial/Makefile.am
new file mode 100644
index 0000000..b676262
--- /dev/null
+++ b/examples++-tutorial/Makefile.am
@@ -0,0 +1,47 @@
+# $Id$
+
+all-local: all.edp regtests.edp  freefem++.pref
+TESTS=adapt.edp adaptindicatorP1.edp adaptindicatorP2.edp algo.edp array.edp a_tutorial.edp beam.edp  calculus.edp cavity.edp convect2.edp convect-apt.edp convect.edp dumptable.edp ex-vf.edp FE.edp fluidStructAdapt.edp fluidStruct.edp freeboundary.edp freeboundary-weak.edp LapDG2.edp Laplace.edp LaplaceP1bis.edp LaplaceP1.edp LaplaceP1P2h.edp LaplaceRT.edp mesh.edp movemesh.edp nolinear-elas.edp NSUzawaCahouetChabart.edp onde.edp periodic4.edp Periodic.edp plot.edp readmesh.edp region.ed [...]
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPP) FLAGS_FFPP=-nw
+
+
+LIST_IDP=*.idp
+EXTRA_DIST=*.edp *.idp aile.msh xyf all.edp regtests.edp regtests.m4 ref.edp
+
+
+all.edp:
+	(echo "NoUseOfWait=true;int verbosityy=verbosity;"; \
+	for i in *`ls *.edp|grep -v -E '^(all|regtests|makeref|ref)\.edp$$'` ; do  \
+		echo ' cout << "--------- file : '$$i' --------------------------------------------------------" << endl;' ;\
+		echo "verbosity=verbosityy;" ; \
+		echo \{ include \"$$i\"\;\}\; ;\
+		echo ' cout << "------------------------------------------------------------------------------ " << endl;' ;\
+	done) > $@
+
+clean-local:
+	-rm *.fg *.eps *~ *.ps  *.mesh *.mesh.gmsh f.txt	u.txt A.matrix	mm.matrix mm.b sphere-a.faces	sphere-a.points	sphere.faces	sphere.points toto.Th		toto.am_fmt	toto.dbg.gmsh toto.Th.gmsh	toto.dbg	toto.msh plot.gp ListOfAllocPtr-8.bin ffglut*.ppm th.msh Th1.msh		Th12.msh	th.msh 	emptymesh-2.msh	 thermic.dat
+# To create a new set of reference values in "ref.edp"
+Ref: makeref.edp freefem++.pref
+	../src/nw/FreeFem++-nw makeref.edp
+install-exec-local:: 
+	$(mkinstalldirs) -m 755 $(DESTDIR)$(ff_prefix_dir)/idp
+	$(INSTALL)  -m 555  $(LIST_IDP)  $(DESTDIR)$(ff_prefix_dir)/idp
+
+
+makeref.edp: regtests.m4 ../regtests.m4
+	m4 regtests.m4 > makeref.edp
+freefem++.pref:
+	echo loadpath = \"../examples++-load/\" >freefem++.pref
+	echo loadpath += \"./\" >>freefem++.pref
+
+# FreeFem API tests
+# -----------------
+
+EXTRA_PROGRAMS=Laplace
+Laplace_SOURCES=Laplace.cpp
+
+# To check the scripts against their reference values
+regtests.edp: regtests.m4 ../regtests.m4
+	m4 -DASSERT regtests.m4 > regtests.edp
+FORCE:
\ No newline at end of file
diff --git a/examples++-tutorial/NS-BackwardStep.edp b/examples++-tutorial/NS-BackwardStep.edp
new file mode 100644
index 0000000..87f7e54
--- /dev/null
+++ b/examples++-tutorial/NS-BackwardStep.edp
@@ -0,0 +1,171 @@
+/*
+  Incompressible Navier Stokes 
+    with Taylor-Hood Finite element
+    No linearity : Newton method 
+    continuation on Reynols Number
+    Mesh adaptation 
+    
+    Test case Laminar Flow over a Backward Facing Step  Gamm Workshop
+    
+     K.Morgan, J.Périaux and F.Thomasset, Analysis of laminar flow over a backward facing step, Vol9 of Notes on Num. Fluid Mech., Vieweg, 1984. 
+    
+*/
+
+// FFCS regression test value
+real regtest;
+
+real[int] Reynold=[50,150,300,400,500];
+real[int] HH=[1.5,1]; 
+real[int,int] reattachP=[ [ 2.8, 2 ], [ 5.16, 3.7 ]] ;  // reattachP[irey,cas]  
+int nerr=0; 
+bool adapt=1; // do adap or not 
+bool dplot=0; // debug plot 
+for(int cas=0;cas<2;++cas)
+{
+real h=HH[cas]-0.5,H=HH[cas],l=3,L=22;
+int[int] ll=[3,2,5,1];
+// label 1 in
+//       2  out 
+//       3  down wall
+//       4   step 
+//       5   up wall 
+func zoom=[[2.5,0],[10,H]];
+mesh Th=square(22,6,[x*22,y*H],label=ll);
+Th=trunc(Th, (x>l) | (y >0.5),label=4); 
+func meshsize= 2*max(0.05,max(max(x-l,0.0)/19./5.,max(l-x,0.0)/3./8. ));
+func uin=(H-y)*(y-0.5)/square((H-0.5)/2.);
+Th=adaptmesh(Th,meshsize,IsMetric=1);
+Th=adaptmesh(Th,meshsize,IsMetric=1);
+plot(Th,wait=0);
+fespace Xh(Th,P2);
+fespace Mh(Th,P1);
+fespace XXMh(Th,[P2,P2,P1]);
+XXMh [u1,u2,p];
+XXMh [v1,v2,q]; 
+
+macro div(u1,u2) (dx(u1)+dy(u2))//
+macro grad(u1,u2) [dx(u1),dy(u2)]//
+macro ugrad(u1,u2,v) (u1*dx(v)+u2*dy(v)) //
+macro Ugrad(u1,u2,v1,v2) [ugrad(u1,u2,v1),ugrad(u1,u2,v2)]//
+
+solve Stokes ([u1,u2,p],[v1,v2,q],solver=UMFPACK) =
+    int2d(Th)( ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            - p*div(v1,v2)-q*div(u1,u2)
+           )
+  + on(1,u1=uin,u2=0) 
+  + on(3,4,5,u1=0,u2=0);
+
+ Xh uu1=u1,uu2=u2;  
+plot(coef=0.2,cmm="Stokes [u1,u2] et p  ",p,[uu1,uu2],wait=0);
+plot(coef=0.2,cmm="Stokes  p  ",p,wait=0);
+Mh psi,phi;
+
+
+solve streamlines(psi,phi) = 
+      int2d(Th)( dx(psi)*dx(phi) + dy(psi)*dy(phi))
+   +  int2d(Th)( -phi*(dy(u1)-dx(u2)))
+   +  on(3,4,psi=0)+ on(5,psi=-2./3.*(H-0.5))
+   ;
+real[int] psiviso(31);
+{int k=0;
+for(int i=-20;i<0;i++)
+ psiviso[k++] = i*2./3.*(H-0.5)/20;
+for(int i=0;i<=10;i++)
+ psiviso[k++] = i*2./3.*(H-0.5)/100/(H*H*H);
+}
+
+plot(psi,wait=0,viso=psiviso);
+int i=0;
+real  nu=1./100.;
+real dt=0.1;
+real alpha=1/dt;
+
+
+
+
+
+XXMh [up1,up2,pp];
+varf   vDNS ([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+            
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            + p*dx(v1)+ p*dy(v2)
+            + dx(u1)*q+ dy(u2)*q
+            + Ugrad(u1,u2,up1,up2)'*[v1,v2]
+            + Ugrad(up1,up2,u1,u2)'*[v1,v2]
+           )
+  + on(1,3,4,5,u1=0,u2=0) 
+;
+
+
+varf   vNS ([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+          
+            + nu * ( dx(up1)*dx(v1) + dy(up1)*dy(v1)
+            +  dx(up2)*dx(v2) + dy(up2)*dy(v2) )
+            + pp*q*(0.000001) 
+            + pp*dx(v1)+ pp*dy(v2)
+            + dx(up1)*q+ dy(up2)*q
+            + Ugrad(up1,up2,up1,up2)'*[v1,v2]//'
+	      )
+  + on(1,3,4,5,u1=0,u2=0) 
+  ;
+
+for(int krey=0;krey<Reynold.n;++krey)
+  { 
+    real re=Reynold[krey];
+    real lerr=0.01;
+    
+    for(int step=0;step<(adapt?2:1) ;step++)
+      {
+     if(adapt)
+     {
+	  Th=adaptmesh(Th,[u1,u2],p,abserror=1,cutoff=1e-5,err=lerr,nbvx=100000,hmin=0.01);
+	  if(dplot) plot(Th,wait=0,bb=zoom);
+     }
+	[u1,u2,p]=[u1,u2,p];
+	[up1,up2,pp]=[up1,up2,pp];
+	
+	for (i=0;i<=20;i++)
+	  {
+	    nu = (H-h)/re;
+	    up1[]=u1[];
+	    real[int] b = vNS(0,XXMh);
+	    matrix Ans=vDNS(XXMh,XXMh);
+	    set(Ans,solver=UMFPACK);
+	    real[int] w = Ans^-1*b;
+	    u1[] -= w;
+	    cout << " iter = "<< i << "  " << w.l2 <<  " rey = " << re << endl;
+	    if(w.l2<1e-6) break; 
+	    // uu1=u1;uu2=u2;
+	    if(dplot) plot(coef=0.2,cmm="H="+H+" re "+re+ " [u1,u2] et p  ",p,[uu1,uu2],bb=zoom);  
+	    
+	  } ;
+      }
+    uu1=u1;uu2=u2;
+    streamlines;
+    real rp1=1./(H-h)*int1d(Th,3)( real( (x>=l & x < (l+0.5)) | (x>(l+0.4)) & (x<10)& (dy(psi) >= 1e-5)) ) ;
+    real rp2=1./(H-h)*int1d(Th,3)( real( (x>=l & x < (l+0.5)) | (x>(l+0.4)) & (x<10)& (dy(psi) >= -1e-5)) ) ;
+    real rp3=1./(H-h)*int1d(Th,3)( real( (x>=l & x < (l+0.5)) | (x>(l+0.4)) & (x<10)& (dy(u1)<=0)       ) ) ;
+    cout << " Reattach point " << rp2 << " " << rp2 << " " << rp3 << endl;
+    real rp = (rp1+rp2)/2;
+    real rppaper =  krey < 2 ? reattachP(krey,cas) : rp; 
+    real err= abs(rppaper - rp)/rp;
+    if( err>0.5 ) nerr++;//  
+    cout << "\n\n\n";
+    cout << "H= " << H << " Re " << re << " Reattach point " << rp << " paper=" << rppaper << " err "<< err 
+         << "  psi max = " << psi[].max <<endl; 
+    cout << "\n\n\n";
+    plot(coef=0.2,cmm="H="+H+", rey="+re+" [u1,u2] et p  ",p,[uu1,uu2],wait=0,nbiso=20,bb=zoom);//,ps="Upstep-"+H+"-"+re
+    plot(coef=0.2,cmm="H="+H+", rey="+re+" [u1,u2] et p  ",p,[uu1,uu2],wait=0,nbiso=20,bb=zoom);//,ps="Upstep-"+H+"-"+re+".ps");  
+    plot(coef=0.2,cmm="H="+H+", rey="+re+" [u1,u2] et p  ",psi,bb=zoom,viso=psiviso);//,ps="psi-step-"+H+"-"+re+".ps");  
+
+    // FFCS regression test value
+    regtest=uu1[]'*uu1[];//'
+     }
+}
+assert(nerr==0); 
\ No newline at end of file
diff --git a/examples++-tutorial/NSUzawaCahouetChabart.edp b/examples++-tutorial/NSUzawaCahouetChabart.edp
new file mode 100644
index 0000000..c4d637e
--- /dev/null
+++ b/examples++-tutorial/NSUzawaCahouetChabart.edp
@@ -0,0 +1,110 @@
+real D=0.1, H=0.41;
+real cx0 = 0.2, cy0 = 0.2; // center of cyl. 
+real xa = 0.15, ya=0.2, xe = 0.25,ye =0.2;
+border fr1(t=0,2.2){x=t; y=0; label=1;}
+border fr2(t=0,H){x=2.2; y=t; label=2;}
+border fr3(t=2.2,0){x=t; y=H; label=1;}
+border fr4(t=H,0){x=0; y=t; label=1;}
+border fr5(t=2*pi,0){x=cx0+D*sin(t)/2; y=cy0+D*cos(t)/2; label=3;}
+int nn=15;
+ 
+mesh Th=buildmesh(fr1(5*nn)+fr2(nn)+fr3(5*nn)+fr4(nn)+fr5(-nn*3));
+real Um= 1.5;// max velocity (Rey 100) 
+func Ub = Um*2./3.; 
+real nu = 1e-3; 
+real Rey = Ub*D/nu;
+// Boundary condition 
+func U1 = 4.*Um*y*(H-y)/(H*H)  ;
+func U2 = 0. ;
+
+ real T=2,t=0; 
+ real dt = D/nn/Um;// CFL = 1 
+ cout << " dt = " << dt <<endl;
+real alpha=1/dt,epspq=1e-10;
+
+
+fespace Mh(Th,[P1]);
+fespace Xh(Th,[P2]);
+fespace Wh(Th,[P1dc]);
+macro grad(u) [dx(u),dy(u)] //
+macro div(u1,u2) (dx(u1)+dy(u2)) //
+
+ 
+ varf von1([u1,u2,p],[v1,v2,q]) =  on(3,u1=0,u2=0) + on(1,u1=U1,u2=U2);
+
+//remark : the value 1000 in next line is manualy fitted, because free outlet. 
+ varf vA(p,q) =int2d(Th)((grad( p ) '*grad(q)) ) + int1d(Th,2)(1000*p*q) ;
+ varf vM(p,q) =int2d(Th,qft=qf2pT)(  p*q );
+
+ varf vu([u1],[v1]) = int2d(Th)(alpha*(u1*v1)+nu*(grad(u1)'*grad(v1) )) 
+                       + on(1,3,u1=0) ;
+ varf vu1([p],[v1]) = int2d(Th)(p*dx(v1)) ;
+ varf vu2([p],[v1]) = int2d(Th)(p*dy(v1)) ;
+   
+
+ matrix pAM=vM(Mh,Mh,solver=UMFPACK); 
+ matrix pAA=vA(Mh,Mh,solver=UMFPACK); 
+ matrix AU=vu(Xh,Xh,solver=UMFPACK); 
+ matrix B1=vu1(Mh,Xh);
+ matrix B2=vu2(Mh,Xh);
+ Xh u1,u2;
+ Mh p;
+varf vonu1([u1],[v1]) =  on(1,u1=U1) + on(3,u1=0);
+varf vonu2([u1],[v1]) =  on(1,u1=U2) + on(3,u1=0);
+
+
+real[int] brhs1 = vonu1(0,Xh);
+real[int] brhs2 = vonu2(0,Xh);
+ 
+varf  vrhs1(uu,vv)  = int2d(Th) (convect([u1,u2],-dt,u1)*vv*alpha)+vonu1 ;
+varf  vrhs2(v2,v1)  = int2d(Th) (convect([u1,u2],-dt,u2)*v1*alpha)+vonu2;
+
+
+func  real[int]   JUzawa(real[int] & pp) 
+{
+	real[int] b1=brhs1; b1 += B1*pp;
+	real[int] b2=brhs2; b2 += B2*pp;
+	u1[] = AU^-1 * b1;
+	u2[] = AU^-1 * b2;
+	pp  = B1'*u1[];
+	pp += B2'*u2[];
+	pp = -pp; 
+	return pp; 
+}
+
+func  real[int]   Precon(real[int] & p)
+ {  
+    real[int] pa= pAA^-1*p;
+    real[int] pm= pAM^-1*p;
+    real[int] pp= alpha*pa+nu*pm;
+ 
+  	return pp;
+ }
+
+ verbosity = 0; 
+ p=0;
+ 
+   
+ Wh w; // to store voticity ..
+  
+ real eps=1e-6;
+ int ndt = T/dt;
+ for(int i=0;i<ndt;++i)
+ {
+     brhs1 = vrhs1(0,Xh);
+     brhs2 = vrhs2(0,Xh);
+     int res=LinearCG(JUzawa,p[],precon=Precon,nbiter=100,verbosity=10,veps=eps); 
+     assert(res==1) ; 
+     eps = -abs(eps); 
+     w = -dy(u1)+dx(u2);
+     plot(w,fill=1,wait=0, nbiso=40,WindowIndex=0);
+    
+     dt = min(dt,T-t);
+     t += dt; 
+     if( dt < 1e-10*T) break;    
+ }
+ plot(w,fill=1,wait=0, nbiso=40,ps="NScahouetChabart.eps");
+ cout << " u1 max " << u1[].linfty 
+      << " u2 max " << u2[].linfty 
+      << " p max = " << p[].max << endl; 
+ 
\ No newline at end of file
diff --git a/examples++-tutorial/Newton.edp b/examples++-tutorial/Newton.edp
new file mode 100644
index 0000000..c925abd
--- /dev/null
+++ b/examples++-tutorial/Newton.edp
@@ -0,0 +1,70 @@
+// FFCS: making a numerical value visible for regression tests
+real regtest;
+
+{ // ---  a real non linear test ---
+mesh Th=square(10,10);  // mesh definition of $\Omega$
+Th = adaptmesh(Th,0.05,IsMetric=1,splitpbedge=1);
+
+//plot(Th,wait=1);
+//Th = adaptmesh(Th,0.1,IsMetric=1,splitpbedge=1);
+plot(Th,wait=0);
+fespace Vh(Th,P1);      // finite element space
+fespace Ph(Th,P1dc);      // make optimization 
+
+Vh b=1;  // to defined b 
+// $ J(u) = 1/2 \int_\Omega f(|\nabla u|^2) - \int\Omega  u b $
+// $ f(x) = a*x + x-ln(1+x), \quad f'(x) = a+\frac{x}{1+x}, \quad f''(x) =  \frac{1}{(1+x)^2}$
+real a=0.001;
+func real f(real u) { return u*a+u-log(1+u); }
+func real df(real u) { return a+u/(1+u);}
+func real ddf(real u) { return 1/((1+u)*(1+u));}
+
+Vh u=0; //  the current value of the solution
+Ph alpha; // to store  $ (|\nabla u|^2)$
+Ph dfalpha; // to store  $f' (|\nabla u|^2)$
+Ph ddfalpha ; //to store = $2 f''( |\nabla u|^2) $  optimisation
+
+int iter=0;
+
+
+//   methode of  Newton Ralphson to solve dJ(u)=0;
+//    $$ u^{n+1} = u^n - (\frac{\partial dJ}{\partial u_i})^{-1}*dJ(u^n) $$ 
+//   ---------------------------------------------
+  // the variationnal form of evaluate  dJ 
+  // --------------------------------------
+  //  dJ =  f'()*( dx(u)*dx(vh) + dy(u)*dy(vh) 
+  varf vdJ(uh,vh) =  int2d(Th)( dfalpha*( dx(u)*dx(vh) + dy(u)*dy(vh) ) - b*vh)
+  + on(1,2,3,4, uh=0);
+  // the variationnal form of evaluate  ddJ   
+  // hJ(uh,vh) =  f'()*( dx(uh)*dx(vh) + dy(uh)*dy(vh)
+  //            + f''()( dx(u)*dx(uh) + dy(u)*dy(uh) ) * (dx(u)*dx(vh) + dy(u)*dy(vh)) 
+  varf vhJ(uh,vh) = int2d(Th)( dfalpha*( dx(uh)*dx(vh) + dy(uh)*dy(vh) )
+   +  ddfalpha*( dx(u)*dx(vh) + dy(u)*dy(vh)  )*( dx(u)*dx(uh) + dy(u)*dy(uh) ) )
+   + on(1,2,3,4, uh=0);
+   
+ // the newton algorithm  
+  Vh v,w; 
+  u=0;
+  for (int i=0;i<100;i++)
+   {
+    alpha = dx(u)*dx(u) + dy(u)*dy(u);// optimization
+    dfalpha = df( alpha ) ; // optimization
+    ddfalpha = 2*ddf(alpha ) ; // optimization
+    v[]= vdJ(0,Vh);
+    real res= v[]'*v[]; //'
+    cout << i <<  " residu^2 = " <<  res  << endl;
+    matrix H;
+    if( res< 1e-12) break;
+    H= vhJ(Vh,Vh,factorize=1,solver=LU);
+    w[]=H^-1*v[];
+    u[] -= w[];
+    plot (u,wait=0,cmm="solution with Newton Raphson");
+
+    // FFCS: regression tests
+    regtest=u[]'*u[]; //'
+   }
+
+load "medit" load "msh3"  
+    mesh3 Th3= movemesh23(Th,transfo=[x,y,u*1.5]);
+    medit("N",Th3);
+}
diff --git a/examples++-tutorial/Periodic.edp b/examples++-tutorial/Periodic.edp
new file mode 100644
index 0000000..7a53d07
--- /dev/null
+++ b/examples++-tutorial/Periodic.edp
@@ -0,0 +1,16 @@
+ mesh Th=square(10,10,[2*x*pi,2*y*pi]);
+ fespace Vh(Th,P2,periodic=[[2,y],[4,y],[1,x],[3,x]]);     // the label 2 and 4 are periodic
+ //  [a1,b1,b2,f1],[b,fb] the degree of freedom of of the border a1,b1,c1 and b are equivalent 
+ //  via fonctions f1 and f2 
+ //  here full periodic in x and y direction
+ Vh uh,vh;              // unkown and test function. 
+ func f=sin(x+pi/4.)*cos(y+pi/4.);                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ 
+ problem laplace(uh,vh) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int2d(Th)( -f*vh )                          //  linear form
+;                
+
+  laplace; // solve the problem plot(uh); // to see the result
+  plot(uh,ps="period.eps",value=true);
diff --git a/examples++-tutorial/StokesUzawa.edp b/examples++-tutorial/StokesUzawa.edp
new file mode 100644
index 0000000..6ed7e9f
--- /dev/null
+++ b/examples++-tutorial/StokesUzawa.edp
@@ -0,0 +1,46 @@
+//  signe of pressure is correct 
+assert(version>1.18); 
+real s0=clock();
+mesh Th=square(10,10);
+fespace Xh(Th,P2),Mh(Th,P1);
+Xh u1,u2,v1,v2;
+Mh p,q,ppp;
+
+
+varf bx(u1,q) = int2d(Th)( (dx(u1)*q)); 
+
+varf by(u1,q) = int2d(Th)( (dy(u1)*q));
+
+varf a(u1,u2)= int2d(Th)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) )
+                    +  on(1,2,4,u1=0)  +  on(3,u1=1) ;
+
+Xh bc1; bc1[] = a(0,Xh);
+Xh b;
+                   
+matrix A= a(Xh,Xh,solver=CG); 
+matrix Bx= bx(Xh,Mh);
+matrix By= by(Xh,Mh);
+Xh bcx=1,bcy=0;
+
+func real[int] divup(real[int] & pp)
+{ 
+  int verb=verbosity;
+   verbosity=0;
+   b[]  = Bx'*pp; b[] += bc1[] .*bcx[];
+   u1[] = A^-1*b[];
+   b[]  = By'*pp; b[] += bc1[] .*bcy[];
+   u2[] = A^-1*b[];
+   ppp[] =   Bx*u1[];
+   ppp[] +=  By*u2[];
+   verbosity=verb;
+   return ppp[] ;
+};
+p=0;q=0;u1=0;v1=0;
+
+        
+LinearCG(divup,p[],q[],eps=1.e-6,nbiter=50);
+
+divup(p[]);
+
+plot([u1,u2],p,wait=1,value=true,coef=0.1);
+
diff --git a/examples++-tutorial/VI-adap.edp b/examples++-tutorial/VI-adap.edp
new file mode 100644
index 0000000..d7c17dc
--- /dev/null
+++ b/examples++-tutorial/VI-adap.edp
@@ -0,0 +1,125 @@
+// variationnal inequality 
+// --------------------------
+//  Probleme:
+//  $ - \Delta u = f , \quad u=g \on \Gamma, \quad u < umax  $
+//  algo of   Primal-Dual Active set strategy as a semi smoth Newton Method
+//   HinterMuller , K. Ito, K. Kunisch 
+//  to appeared in SIAM Option
+// Thank to O. Pironneau 
+// --------------------------
+// F. Hecht
+//  -----------------------
+ mesh Th=square(10,10);
+ real eps=1e-10;
+ fespace Vh(Th,P1);     // P1 FE space
+ int n = Vh.ndof; // number of Degree of freedom
+ Vh uh,uhp,Ah;              // unkown and test function. 
+real[int] rhs(n);
+real cc=1000; 
+ func f=1;                 //  right hand side function 
+ func g=0;                 //  boundary condition function
+ func gmax=0.05;
+ Vh umax=gmax;
+//
+real tol=0.05,tolmin=0.002;  
+real tgv = 1e30;
+real res=0;
+ varf a(uh,vh) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=g) ;                      //  boundary condition form
+varf vM(uh,vh) = int2d(Th)(uh*vh);
+
+
+matrix A=a(Vh,Vh,tgv=tgv,solver=CG);
+matrix AA=a(Vh,Vh);
+matrix M=vM(Vh,Vh);
+rhs = a(0,Vh,tgv=tgv);
+real[int] Aii(n),Aiin(n),Ah1(n),b(n);
+
+Aii=A.diag; // get the diagonal of the matrix 
+//cout << " Aii= " << Aii << endl;
+Ah =0;
+uhp=0;
+Vh lh=0;
+int kadapt=0,kkadapt=0;
+for(int iter=0;iter<100;++iter)
+{
+  
+  // solve the problem plot(uh); // to see the result
+  b = rhs;
+  //  add new lock condition on i / if (Ah[i] ==1 )
+  Ah1= 1.; Ah1  -= Ah[];  // Ah1  = ! Ah 
+  b = Ah[] .* umax[];  b *= tgv;       b  -=  Ah1 .* rhs;
+  Aiin = Ah[] *  tgv; Aiin  +=  Ah1  .* Aii;
+  A.diag = Aiin;
+  set(A,solver=CG); // important to change precondiconning 
+  uh[] = A^-1* b;
+  lh[] = AA * uh[];
+  lh[] += rhs;
+  //  plot(lh,wait=1);
+  Ah = ( lh + cc*( umax- uh)) < 0.; 
+  
+  // plot(Ah, wait=1,cmm=" lock ",value=1 );
+  plot(uh,wait=1,cmm="uh");
+  real[int] d(n),Md(n);
+  d= uh[]-uhp[];    
+  Md = M*d;
+  real err = sqrt(Md'*d);
+  Md=M*uh[];
+  Ah1=1.;
+  real intuh  = (Ah1'*Md); // int uh; 
+  cout << " err norm L2 " << err << " "
+       << " int uh = " << intuh  
+      <<  " kkadapt =" << kkadapt <<endl;
+  res = intuh;
+  if(err< eps && kkadapt ) break;
+  bool adapt = err< eps || (iter%5 == 4)  ;
+  if(adapt)
+    { 
+      kadapt++;
+      Th=adaptmesh(Th,uh,err=tol);
+      kkadapt = tol == tolmin; // we reacht  the bound       
+      tol = max(tol/2,tolmin);
+       cout << " ++ tol = " << tol << "  " << kadapt << " " << kkadapt <<endl;
+      plot(Th,wait=0);
+      uhp=uhp;
+      n=uhp.n;	
+      uh=uh;
+      Ah=Ah;
+      lh=lh;
+      umax = gmax; 
+      A=a(Vh,Vh,tgv=tgv,solver=CG);
+      AA=a(Vh,Vh);
+      M=vM(Vh,Vh);
+      Aii.resize(n);	
+      Aiin.resize(n);
+      Ah1.resize(n);
+      b.resize(n);
+      rhs.resize(n); 
+      Aii=A.diag; // get the diagonal of the matrix 
+      rhs = a(0,Vh,tgv=tgv);
+    }
+  uhp[]=uh[];
+} 
+savemesh(Th,"mm",[x,y,uh*10]);
+{
+  int nn=100;
+
+  real[int] xx(nn+1),yy(nn+1),pp(nn+1);
+  for (int i=0;i<=nn;i++)
+   {
+   
+     xx[i]=i/real(nn);
+     yy[i]=uh(0.5,i/real(nn));
+    }
+   plot([xx,yy],wait=1,cmm="u1 x=0.5 cup");
+}
+
+Aiin=M*uh[];
+Aii=1.;
+cout << " -- int uh = " << res  << endl;
+assert( abs(res-0.0288611) < 0.001);  
+   
+  
+  
diff --git a/examples++-tutorial/VI.edp b/examples++-tutorial/VI.edp
new file mode 100644
index 0000000..03c30da
--- /dev/null
+++ b/examples++-tutorial/VI.edp
@@ -0,0 +1,82 @@
+// variationnal inequality 
+// --------------------------
+//  Probleme:
+//  $ - \Delta u = f , \quad u=gd \on \Gamma, \quad u < g $
+//  algo of   Primal-Dual Active set strategy as a semi smoth Newton Method
+//   HinterMuller , K. Ito, K. Kunisch 
+//  to appeared in SIAM Option
+// Thank to O. Pironneau 
+// --------------------------
+// F. Hecht april 2005
+//  -----------------------
+ mesh Th=square(20,20);
+ real eps=1e-5;
+ fespace Vh(Th,P1);     // P1 FE space
+ int n = Vh.ndof; // number of Degree of freedom
+ Vh uh,uhp;              // solution and previous one
+ Vh Ik; //  to def the set where the containt is reached. 
+ real[int] rhs(n); // to store the right and side of the equation 
+ real c=10;  // the parameter of the algoritme
+ func f=1;         //  right hand side function 
+ func fd=0;         // Dirichlet   boundary condition function
+ Vh g=0.05;
+// array to store   
+real[int] Aii(n),Aiin(n); // store the diagonal of the matrix
+
+
+
+
+ real tgv = 1e30; // a hude value of exact penalisation of boundary condition
+//  the variatonnal form of the problem:
+ varf a(uh,vh) =                    //  definion of  the problem 
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  - int2d(Th)( f*vh )                          //  linear form
+  + on(1,2,3,4,uh=fd) ;                      //  boundary condition form
+
+
+
+// two version of the problem  
+matrix A=a(Vh,Vh,tgv=tgv,solver=CG);
+matrix AA=a(Vh,Vh);
+
+//  the mass Matrix construction: 
+varf vM(uh,vh) = int2d(Th)(uh*vh);
+matrix M=vM(Vh,Vh); // to do a fast computing of $L^2$ norm : sqrt( u'*(w=M*u)) 
+Aii=A.diag; // get the diagonal of the matrix 
+
+rhs = a(0,Vh,tgv=tgv);
+Ik =0;
+uhp=0;
+Vh lambda=0;
+for(int iter=0;iter<100;++iter)
+{
+  real[int] b(n) ; b=rhs;  //  get a copy of the Right hand side 
+  real[int] Ak(n); //  the complementary of Ik ( !Ik = (Ik-1))
+  // Today  the operator Ik- 1. is not implement so we do:
+  Ak= 1.; Ak  -= Ik[];  // build Ak  = ! Ik 
+  //  adding new locking  condition on b and on the diagonal if (Ik ==1 )
+  b = Ik[] .* g[];      b *= tgv;     b  -=  Ak .* rhs;
+  Aiin = Ik[] *  tgv;      Aiin  +=  Ak  .* Aii;  //set  Aii= tgv  $ i \in Ik $
+  A.diag = Aiin; //  set the matrix diagonal 
+  set(A,solver=CG); // important to change precondiconning  for solving
+  uh[] = A^-1* b;   //  solve the problem with more locking condition
+  lambda[] = AA * uh[]; //  compute the resudal ( fast with matrix)
+  lambda[] += rhs; // remark rhs = $-\int f v $ 
+
+  Ik = ( lambda + c*( g- uh)) < 0.;  //  set the new value 
+  
+   plot(Ik, wait=1,cmm=" lock set ",value=1 );
+   plot(uh,wait=1,cmm="uh");
+   // trick to compute  $L^2$ norm of the variation
+      real[int] diff(n),Mdiff(n);  
+      diff= uh[]-uhp[];    
+      Mdiff = M*diff; 
+      real err = sqrt(Mdiff'*diff);
+  cout << "  || u_{k=1} - u_{k} ||_2 " << err << endl;
+  if(err< eps) break; // stop test 
+  uhp[]=uh[] ; // set the previous solution 
+} 
+savemesh(Th,"mm",[x,y,uh*10]);
+  
+  
+  
diff --git a/examples++-tutorial/a_tutorial.edp b/examples++-tutorial/a_tutorial.edp
new file mode 100644
index 0000000..224b559
--- /dev/null
+++ b/examples++-tutorial/a_tutorial.edp
@@ -0,0 +1,38 @@
+// This test shows some powerful features of freefem++ on a
+// simple example: $-\Delta(u)=1$ in the unit cercle with $u=0$ on the
+// border of the unit cercle. this problem has an analytical solution
+// u = (1-x^2-y^2)/4
+real pi=4*atan(1);
+border a(t=0,2*pi){ x = cos(t); y = sin(t);label=1;};
+
+mesh disk = buildmesh(a(50));
+plot(disk);
+fespace femp1(disk,P1);  
+femp1 u,v; 
+
+problem laplace(u,v) = 
+    int2d(disk)( dx(u)*dx(v) + dy(u)*dy(v) )     //  bilinear form
+  + int2d(disk)( -1*v )                          //  linear form
+  + on(1,u=0) ;                                // boundary condition 
+
+laplace; 
+femp1 err=u-(1-x^2-y^2)/4;
+
+plot (u,value=true,wait=true);
+plot(err,value=true,wait=true);
+
+cout << "error L2=" << sqrt(int2d(disk)( (u-(1-x^2-y^2)/4) ^2) )<< endl;
+cout << "error H10=" << sqrt(   int2d(disk)((dx(u)+x/2)^2) 
+                              + int2d(disk)((dy(u)+y/2)^2))<< endl;
+
+ disk = adaptmesh(disk,u,err=0.01);
+plot(disk,wait=1);
+
+laplace; 
+
+plot (u,value=true,wait=true);
+err =u-(1-x^2-y^2)/4;
+plot(err,value=true,wait=true);
+cout << "error L2=" << sqrt(int2d(disk)( (u-(1-x^2-y^2)/4) ^2) )<< endl;
+cout << "error H10=" << sqrt(  int2d(disk)((dx(u)+x/2)^2) 
+                             + int2d(disk)((dy(u)+y/2)^2))<< endl;
diff --git a/examples++-tutorial/adapt.edp b/examples++-tutorial/adapt.edp
new file mode 100644
index 0000000..2453c0a
--- /dev/null
+++ b/examples++-tutorial/adapt.edp
@@ -0,0 +1,25 @@
+border a(t=0,1.0){x=t;   y=0;  label=1;};// comment 
+border b(t=0,0.5){x=1;   y=t;  label=2;};
+border c(t=0,0.5){x=1-t; y=0.5;label=3;};
+border d(t=0.5,1){x=0.5; y=t;  label=4;};
+border e(t=0.5,1){x=1-t; y=1;  label=5;};
+border f(t=0.0,1){x=0;   y=1-t;label=6;};
+mesh Th = buildmesh (a(6) + b(4) + c(4) +d(4) + e(4) + f(6));
+savemesh(Th,"th.msh");
+fespace Vh(Th,P1);
+Vh u,v;
+real error=0.01;
+problem Probem1(u,v,solver=CG,eps=1.0e-6) =
+    int2d(Th,qforder=2)( u*v*1.0e-10+  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th,qforder=2)( (x-y)*v);
+int i;
+for (i=0;i< 4;i++)
+{   
+  Probem1; 
+   cout << u[].min << " " << u[].max << endl; 
+   plot(u,wait=1);
+   Th=adaptmesh(Th,u,err=error);
+   plot(Th,wait=1);
+  u=u;
+  error = error/2;
+} ;
diff --git a/examples++-tutorial/adaptindicatorP1.edp b/examples++-tutorial/adaptindicatorP1.edp
new file mode 100644
index 0000000..3d366a6
--- /dev/null
+++ b/examples++-tutorial/adaptindicatorP1.edp
@@ -0,0 +1,50 @@
+border ba(t=0,1.0){x=t;   y=0;  label=1;}; // comment 
+border bb(t=0,0.5){x=1;   y=t;  label=2;};
+border bc(t=0,0.5){x=1-t; y=0.5;label=3;};
+border bd(t=0.5,1){x=0.5; y=t;  label=4;};
+border be(t=0.5,1){x=1-t; y=1;  label=5;};
+border bf(t=0.0,1){x=0;   y=1-t;label=6;};
+mesh Th = buildmesh (ba(6) + bb(4) + bc(4) +bd(4) + be(4) + bf(6));
+savemesh(Th,"th.msh");
+fespace Vh(Th,P1);
+fespace Nh(Th,P0);
+Vh u,v;
+Nh rho;
+real[int] viso(21);
+for (int i=0;i<viso.n;i++)
+  viso[i]=10.^(+(i-16.)/2.);
+real error=0.01;
+func f=(x-y);
+problem Probem1(u,v,solver=CG,eps=1.0e-6) =
+    int2d(Th,qforder=5)( u*v*1.0e-10+  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th,qforder=5)( -f*v);
+/*
+
+  $$\eta_{K} =\left(  h_{K}^{2} || f -\Delta u_{{h}} ||_{L^{2}(K)}^{2} +\sum_{e\in \AK} h_{e} \,||\, [ \frac{\partial u_{h}}{\partial n_{k}}] \,||^{2}_{L^{2}(e)} \right)^{\frac{1}{2}}
+   $$
+
+ $$ \rho_{K}= \left( || f -\Delta u_{{h}} ||_{L^{2}(K)}^{2} +\sum_{e\in \AK} \frac{1}{h_{e}} \,||\, [ \frac{\partial u_{h}}{\partial n_{k}}] \,||^{2}_{L^{2}(e)} \right)^{\frac{1}{2}} $$
+
+
+*/
+
+varf indicator2(uu,chiK) = 
+     intalledges(Th)(chiK*lenEdge*square(jump(N.x*dx(u)+N.y*dy(u))))
+    +int2d(Th)(chiK*square(hTriangle*(f+dxx(u)+dyy(u))) );
+for (int i=0;i< 4;i++)
+{   
+  Probem1; 
+   cout << u[].min << " " << u[].max << endl; 
+   plot(u,wait=1);
+   cout << " indicator2 " << endl;
+   
+   rho[] = indicator2(0,Nh);
+   rho=sqrt(rho);
+   cout << "rho =   min " << rho[].min << " max=" << rho[].max << endl;
+   plot(rho,fill=1,wait=1,cmm="indicator density ",ps="rhoP2.eps",value=1,viso=viso,nbiso=viso.n);
+   Th=adaptmesh(Th,u,err=error,anisomax=1);
+   plot(Th,wait=1);
+   u=u;
+   rho=rho;
+  error = error/2;
+} ;
diff --git a/examples++-tutorial/adaptindicatorP2.edp b/examples++-tutorial/adaptindicatorP2.edp
new file mode 100644
index 0000000..8361681
--- /dev/null
+++ b/examples++-tutorial/adaptindicatorP2.edp
@@ -0,0 +1,54 @@
+border ba(t=0,1.0){x=t;   y=0;  label=1;}; // comment 
+border bb(t=0,0.5){x=1;   y=t;  label=2;};
+border bc(t=0,0.5){x=1-t; y=0.5;label=3;};
+border bd(t=0.5,1){x=0.5; y=t;  label=4;};
+border be(t=0.5,1){x=1-t; y=1;  label=5;};
+border bf(t=0.0,1){x=0;   y=1-t;label=6;};
+mesh Th = buildmesh (ba(6) + bb(4) + bc(4) +bd(4) + be(4) + bf(6));
+savemesh(Th,"th.msh");
+fespace Vh(Th,P2);
+fespace Nh(Th,P0);
+Vh u,v;
+Nh rho,logrho;
+real[int] viso(21);
+
+for (int i=0;i<viso.n;i++)
+  viso[i]=10.^(+(i-16.)/2.);
+real error=0.01;
+func f=(x-y);
+problem Probem1(u,v,solver=CG,eps=1.0e-6) =
+    int2d(Th,qforder=5)( u*v*1.0e-10+  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th,qforder=10)( -f*v);
+/*
+
+  $$\eta_{K} =\left(  h_{K}^{2} || f -\Delta u_{{h}} ||_{L^{2}(K)}^{2} +\sum_{e\in \AK} h_{e} \,||\, [ \frac{\partial u_{h}}{\partial n_{k}}] \,||^{2}_{L^{2}(e)} \right)^{\frac{1}{2}}
+   $$
+
+ $$ \rho_{K}= \left( || f -\Delta u_{{h}} ||_{L^{2}(K)}^{2} +\sum_{e\in \AK} \frac{1}{h_{e}} \,||\, [ \frac{\partial u_{h}}{\partial n_{k}}] \,||^{2}_{L^{2}(e)} \right)^{\frac{1}{2}} $$
+
+
+*/
+
+varf indicator2(uu,chiK) = 
+     intalledges(Th)(chiK*lenEdge*square(jump(N.x*dx(u)+N.y*dy(u))))
+    +int2d(Th)(chiK*square(hTriangle*(f+dxx(u)+dyy(u))) );
+for (int i=0;i< 4;i++)
+{   
+  Probem1; 
+   cout << u[].min << " " << u[].max << endl; 
+   plot(u,wait=1);
+   cout << " indicator2 " << endl;
+   
+   rho[] = indicator2(0,Nh);
+   rho=sqrt(rho);
+   logrho=log10(rho);
+   cout << "rho =   min " << rho[].min << " max=" << rho[].max << endl;
+   plot(rho,fill=1,wait=1,cmm="indicator density ",ps="rhoP2.eps",value=1,viso=viso,nbiso=viso.n);
+   plot(logrho,fill=1,wait=1,cmm="log 10 indicator density ",ps="logrhoP2.eps",value=1,nbiso=10);
+   plot(Th,wait=1,cmm="Mesh ",ps="ThrhoP2.eps");
+   Th=adaptmesh(Th,[dx(u),dy(u)],err=error,anisomax=1);
+   plot(Th,wait=1);
+   u=u;
+   rho=rho;
+  error = error/2;
+} ;
diff --git a/examples++-tutorial/aile.msh b/examples++-tutorial/aile.msh
new file mode 100644
index 0000000..1974e5b
--- /dev/null
+++ b/examples++-tutorial/aile.msh
@@ -0,0 +1,337 @@
+ 112 184 40
+   4.075497E+00   8.003750E-01       1
+   3.468245E+00   9.339829E-01       1
+   2.857521E+00   1.039934E+00       1
+   2.231503E+00   1.131899E+00       1
+   1.596009E+00   1.213341E+00       1
+   9.782588E-01   1.283559E+00       1
+   3.468041E-01   1.347639E+00       1
+  -2.795196E-01   1.404281E+00       1
+  -9.100614E-01   1.454697E+00       1
+  -1.537047E+00   1.498263E+00       1
+  -2.171066E+00   1.535326E+00       1
+  -2.793453E+00   1.564127E+00       1
+  -3.431808E+00   1.584451E+00       1
+  -4.065853E+00   1.592797E+00       1
+  -4.688077E+00   1.584438E+00       1
+  -5.305153E+00   1.547287E+00       1
+  -5.914978E+00   1.398924E+00       1
+  -6.476645E+00   1.117341E+00       1
+  -6.972389E+00   7.314404E-01       1
+  -7.382722E+00   2.559056E-01       1
+  -7.674503E+00  -2.996254E-01       1
+   2.686152E+00   9.200337E-01       1
+   1.290776E+00   9.916314E-01       1
+  -1.058211E-01   1.019319E+00       1
+  -1.489369E+00   9.981937E-01       1
+  -2.891748E+00   9.439344E-01       1
+  -4.288854E+00   8.350767E-01       1
+  -5.664926E+00   5.838397E-01       1
+  -6.364868E+00  -5.272588E-01       1
+  -7.066498E+00  -1.478878E+00       1
+   1.019193E+01  -7.961763E-01       1
+   7.782479E+00   6.619352E+00       1
+   1.474454E+00   1.120240E+01       1
+  -6.322694E+00   1.120240E+01       1
+  -1.263072E+01   6.619351E+00       1
+  -1.504017E+01  -7.961774E-01       1
+  -1.263072E+01  -8.211705E+00       1
+  -6.322695E+00  -1.279475E+01       1
+   1.474456E+00  -1.279475E+01       1
+   7.782482E+00  -8.211700E+00       1
+  -1.050187E+01  -3.774225E+00       0
+  -1.030402E+01   1.760113E+00       0
+  -1.062298E+01  -9.409381E-01       0
+  -8.120244E+00  -6.890119E+00       0
+  -8.327751E+00   1.114643E+00       0
+  -7.030205E+00   3.655890E+00       0
+  -5.705182E+00   2.251289E+00       0
+  -5.233823E+00   2.586788E+00       0
+  -3.568635E+00  -1.971066E-01       0
+  -3.864839E+00   4.360435E+00       0
+  -1.868891E+00   2.562439E+00       0
+  -1.347341E+00  -2.504814E+00       0
+  -6.859015E-01   1.758138E+00       0
+  -5.138293E+00  -7.542873E+00       0
+  -8.016615E+00  -4.056562E+00       0
+  -8.900968E+00   4.022112E+00       0
+   2.436143E-01   4.142326E+00       0
+  -2.172804E+00  -5.206747E-01       0
+  -1.846865E+00   3.983616E+00       0
+  -5.449497E-01   2.949911E+00       0
+   1.796799E+00   2.113467E+00       0
+   3.521564E+00  -4.406007E+00       0
+   5.387890E+00   2.588071E+00       0
+   2.493658E+00   2.880930E+00       0
+   6.233596E+00  -3.148530E+00       0
+   1.151424E+00  -2.496122E+00       0
+  -6.611673E+00   5.729552E+00       0
+   1.909933E+00  -6.032418E-01       0
+   2.557634E+00   5.670380E+00       0
+  -8.797068E+00  -1.072165E-02       0
+  -1.857090E+00  -8.452744E+00       0
+  -7.845343E+00   2.301641E+00       0
+  -2.536231E+00   1.918698E+00       0
+  -1.874209E+00   1.878176E+00       0
+  -3.863200E+00   2.121552E+00       0
+  -3.667961E+00  -1.848395E+00       0
+  -1.273230E+00   1.884726E+00       0
+  -3.328228E+00  -4.736179E+00       0
+  -2.058262E+00   6.607205E+00       0
+  -4.799016E+00  -4.393931E-01       0
+  -1.170004E-01  -4.384110E-01       0
+  -2.552725E-01   1.825780E+00       0
+   5.865835E-02  -5.068399E+00       0
+   3.903476E+00   1.427050E+00       0
+   2.657649E+00   1.593844E+00       0
+  -6.770658E+00   1.814122E+00       0
+  -6.113464E+00  -4.835857E+00       0
+  -5.535376E+00   3.640081E+00       0
+  -2.976545E+00   3.245543E+00       0
+   1.189424E-01   2.193703E+00       0
+  -8.507294E+00  -1.916803E+00       0
+   1.083397E+00   1.824587E+00       0
+   1.875683E+00   1.569242E+00       0
+   5.374640E+00  -2.497857E-01       0
+   8.662421E-01   2.677091E+00       0
+   4.311450E+00  -2.071755E+00       0
+   2.890089E+00  -2.017998E+00       0
+  -5.951860E+00   1.815626E+00       0
+  -5.236918E+00  -1.528655E+00       0
+  -7.297338E+00   1.219361E+00       0
+  -3.150111E+00   2.389109E+00       0
+  -4.548691E+00   2.131815E+00       0
+  -4.164779E+00   2.921586E+00       0
+   3.374693E-01   1.648933E+00       0
+   3.541547E+00  -5.395558E-01       0
+   2.197370E+00  -7.784485E+00       0
+  -6.838565E+00  -2.848820E+00       0
+  -5.231667E+00  -2.938977E+00       0
+  -7.554908E-01   2.195015E+00       0
+  -6.305655E+00   2.573771E+00       0
+  -5.234858E+00   1.989110E+00       0
+  -6.141749E+00  -1.868861E+00       0
+     45     42     70       1
+     43     70     42       1
+     37     44     41       1
+     47    110     98       1
+     35     36     42       1
+     38     44     37       1
+     41     55     91       1
+     54     38     71       1
+    100     18     86       1
+     76     80     99       1
+     45     20    100       1
+     98     16    111       1
+     80     28     29       1
+    111     15    102       1
+     73    101     13       1
+     73     51    101       1
+     80     27     28       1
+     47     98    111       1
+     51     73     74       1
+     58     26     49       1
+     48     47    111       1
+     77      9     53       1
+     58     49     76       1
+     51     74     77       1
+      5     93     92       1
+     52     76     78       1
+     44     54     87       1
+     46     67     56       1
+     36     43     42       1
+     33     34     79       1
+     49     27     80       1
+     51     77    109       1
+     58     52     81       1
+     53      8     82       1
+      4      3     85       1
+     52     78     83       1
+     94     84      1       1
+     64     61     85       1
+     61     93     85       1
+     62     40     65       1
+     68     23     81       1
+     45     70     20       1
+     50     79     67       1
+     19    100     20       1
+     23     24     81       1
+     43     36     41       1
+     32     33     69       1
+     37     41     36       1
+     31     32     63       1
+     70     91     21       1
+     56     67     35       1
+     18     17     98       1
+     75    102     14       1
+     72     86    110       1
+     74     73     11       1
+    110     48     88       1
+     49     26     27       1
+     55     44     87       1
+     67     79     34       1
+    103     75    101       1
+     53      9      8       1
+     88     48    103       1
+     62     83    106       1
+     25     58     81       1
+    104      8      7       1
+     82      8    104       1
+     54     44     38       1
+     39     71     38       1
+     55    107     91       1
+     44     55     41       1
+     56     35     42       1
+     45     72     42       1
+      6      5     92       1
+      4     85     93       1
+     81     52     66       1
+     26     58     25       1
+     59     57     79       1
+     88    103     50       1
+     60     57     59       1
+     51     60     59       1
+     84     85      2       1
+     60     90     95       1
+     65     40     31       1
+    105     68     97       1
+     63     84     94       1
+     69     63     32       1
+     64     63     69       1
+     90     92     95       1
+     94     31     63       1
+     62     65     96       1
+     66     52     83       1
+     96     94    105       1
+     67     34     35       1
+     88     67     46       1
+     96     97     62       1
+     23     68     22       1
+     69     33     79       1
+     64     69     57       1
+     70     43     91       1
+     20     70     21       1
+     83     71    106       1
+     78     71     83       1
+     72     46     56       1
+     42     72     56       1
+     73     13     12       1
+     11     73     12       1
+     74     11     10       1
+      9     77     10       1
+     75     14     13       1
+     51     89    101       1
+     87    108    107       1
+     58     76     52       1
+     77     74     10       1
+     82    109     53       1
+     87     78    108       1
+     71     78     54       1
+     79     50     59       1
+     69     79     57       1
+    112     29     30       1
+     49     80     76       1
+     81     66     68       1
+     25     81     24       1
+     92    104      6       1
+     77     53    109       1
+    106     71     39       1
+     66     83     62       1
+     84      2      1       1
+     64     84     63       1
+     85      3      2       1
+     64     85     84       1
+     86     98    110       1
+     45    100     72       1
+     87     54     78       1
+     76     99    108       1
+     88     50     67       1
+    110     88     46       1
+     89     51     59       1
+     50     89     59       1
+     95     61     64       1
+    109     90     60       1
+     91     30     21       1
+     41     91     43       1
+     92     61     95       1
+     82    104     90       1
+     93     61     92       1
+      4     93      5       1
+     94      1    105       1
+     31     94     65       1
+     95     64     57       1
+     60     95     57       1
+     96     65     94       1
+     22     68    105       1
+     97     68     66       1
+     62     97     66       1
+     98     86     18       1
+     16     98     17       1
+     99     80     29       1
+    107    108    112       1
+    100     19     18       1
+     72    100     86       1
+    101     89    103       1
+     13    101     75       1
+    102     15     14       1
+    103    102     75       1
+    103     48    102       1
+     50    103     89       1
+    104      7      6       1
+     90    104     92       1
+    105      1     22       1
+     96    105     97       1
+    106     39     40       1
+     62    106     40       1
+    107     30     91       1
+     87    107     55       1
+    108     78     76       1
+    112    108     99       1
+    109     82     90       1
+     51    109     60       1
+    110     47     48       1
+     72    110     46       1
+    111     16     15       1
+     48    111    102       1
+    112     99     29       1
+    107    112     30       1
+      1      2       1
+      2      3       1
+      3      4       1
+      4      5       1
+      5      6       1
+      6      7       1
+      7      8       1
+      8      9       1
+      9     10       1
+     10     11       1
+     11     12       1
+     12     13       1
+     13     14       1
+     14     15       1
+     15     16       1
+     16     17       1
+     17     18       1
+     18     19       1
+     19     20       1
+     20     21       1
+      1     22       1
+     22     23       1
+     23     24       1
+     24     25       1
+     25     26       1
+     26     27       1
+     27     28       1
+     28     29       1
+     29     30       1
+     30     21       1
+     31     32       1
+     32     33       1
+     33     34       1
+     34     35       1
+     35     36       1
+     36     37       1
+     37     38       1
+     38     39       1
+     39     40       1
+     40     31       1
diff --git a/examples++-tutorial/algo.edp b/examples++-tutorial/algo.edp
new file mode 100644
index 0000000..3db3fa4
--- /dev/null
+++ b/examples++-tutorial/algo.edp
@@ -0,0 +1,179 @@
+//  cleanning version 07/2008  FH in Sevilla.
+int nerr =0; 
+int debugJ =0; 
+int debugdJ =0; 
+real umax=0;
+{
+ func  bool stop(int iter,real[int] u,real[int] g)	
+{
+  cout << " stop = " << iter << " " << u.linfty << " " << g.linfty << endl;
+  return g.linfty < 1e-5 || iter > 15;;
+}
+  // minimisation of $J(u) = \frac12\sum (i+1) u_i^2 - b_i $	
+  // work array 
+  real[int] b(10),u(10); 
+  
+  func real J(real[int] & u)
+    {
+      real s=0;
+      for (int i=0;i<u.n;i++)
+	s +=(i+1)*u[i]*u[i]*0.5 - b[i]*u[i];
+      if(debugJ) cout << "J ="<< s << " u =" <<  u[0] << " " << u[1] << "...\n" ;
+      return s;
+    }
+
+//  the grad of J (this is a affine version (the RHS is in  )
+  func real[int] DJ(real[int] &u)
+    { 
+      for (int i=0;i<u.n;i++)
+	u[i]=(i+1)*u[i];
+      if(debugdJ) cout << "dJ0  ="<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;	
+      u -= b; 
+      if(debugdJ) cout << "dJ-b ="<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;	
+      return u;  // return of global variable ok 
+    };
+
+// the grad of the bilinear part of J (the RHS in remove)
+  func real[int] DJ0(real[int] &u)
+    { 
+      for (int i=0;i<u.n;i++)
+	u[i]=(i+1)*u[i];
+      if(debugdJ) cout << "dJ0 ="<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;	
+      return u;  // return of global variable ok 
+    };
+
+
+  func real error(real[int] & u,real[int] & b)
+   {
+   real s=0;
+     for (int i=0;i<u.n;i++)
+	s += abs((i+1)*u[i] - b[i]);
+   return s;    
+   }
+  func real[int] matId(real[int] &u) { return u;};
+  int verb=5; // verbosity of algo ..
+  b=1. ; u=0.; // set  right hand side and initial gest
+  LinearCG(DJ,u,eps=1.e-6,nbiter=20,precon=matId,verbosity=verb);
+  cout << "LinearGC (Affine) : J(u) = " << J(u) << " err=" << error(u,b) << endl;
+  nerr += !(error(u,b) < 1e-5);
+  if(nerr) cout << "    sol: "<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;		
+
+  b=1; u=0; 
+  LinearCG(DJ,u,eps=1.e-15,nbiter=20,precon=matId,verbosity=50,stop=stop);
+  cout << "LinearGC (Affine with stop) : J(u) = " << J(u) << " err=" << error(u,b) << endl;
+  nerr += !(error(u,b) < 1e-5);
+  if(nerr) cout << "    sol: "<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;		
+
+  b=1; u=0; // set  right hand side and initial gest
+  LinearCG(DJ0,u,b,eps=1.e-6,nbiter=20,precon=matId,verbosity=verb);
+  cout << "LinearGC (Linear) : J(u) = " << J(u) << " err=" << error(u,b) << endl;
+  nerr += !(error(u,b) < 1e-5);
+  if(nerr) cout << "    sol: "<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;		
+
+
+  b=1; u=0; // set  right hand side and initial gest
+  AffineGMRES(DJ,u,eps=1.e-6,nbiter=20,precon=matId,verbosity=verb); // correct in version 3.11 
+  cout << "LinearGMRES (Affine) : J(u) = " << J(u) << " err=" << error(u,b) << endl;
+  nerr += !(error(u,b) < 1e-5);
+  if(nerr) cout << "    sol: "<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;		
+
+  b=1; u=0; // set  right hand side and initial gest
+  LinearGMRES(DJ0,u,b,eps=1.e-6,nbiter=20,precon=matId,verbosity=verb);
+  cout << "LinearGMRES (Linear) : J(u) = " << J(u) << " err=" << error(u,b) << endl;
+  nerr += !(error(u,b) < 1e-5);
+  if(nerr) cout << "    sol: "<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;		
+
+
+  b=1; u=0; // set  right hand side and initial gest
+  NLCG(DJ,u,eps=1.e-6,nbiter=20,precon=matId,verbosity=verb);
+  cout << "NLCG: J(u) = " << J(u) << " err=" << error(u,b) << endl;
+  nerr += !(error(u,b) < 1e-5);
+  if(nerr) cout << "    sol: "<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;		
+
+
+  // warning BFGS use a full matrix of size nxn (where n=u.n) 
+  b=1; u=2; // set  right hand side and initial gest
+  BFGS(J,DJ,u,eps=1.e-6,nbiter=20,nbiterline=20);
+   cout << "BFGS: J(u) = " << J(u) << " err=" << error(u,b) << endl;
+  assert(error(u,b) < 1e-5);
+  if(nerr) cout << "    sol: "<< " u =" <<  u[0] << " " << u[1] << " " << u[2]  << "...\n" ;		
+ 
+
+  assert(nerr==0);
+};
+{ // ---  a real non linear test ---
+mesh Th=square(10,10);  // mesh definition of $\Omega$
+fespace Vh(Th,P1);      // finite element space
+fespace Ph(Th,P0);      // make optimization
+
+Vh b=1;  // to defined b 
+// $ J(u) = 1/2\int_\Omega f(|\nabla u|^2) - \int\Omega  u b $
+// $ f(u) = a*u + u-ln(1+u), \quad f'(u) = a+\frac{u}{1+u}, \quad f''(u) =  \frac{1}{(1+u)^2}$
+real a=0.001;
+func real f(real u) { return u*a+u-log(1+u); }
+func real df(real u) { return a+u/(1+u);}
+func real ddf(real u) { return 1/((1+u)*(1+u));}
+
+// the functionnal J 
+
+func real J(real[int] & u)
+  {
+    Vh w;w[]=u; 
+    real r=int2d(Th)(0.5*f( dx(w)*dx(w) + dy(w)*dy(w) ) - b*w) ;
+    cout << "J(u) =" << r << " " << u.min <<  " " << u.max << endl;
+    return r;
+  }
+// -----------------------
+
+Vh u=0; //  the current value of the solution
+Ph alpha; // of store  $df(|\nabla u|^2)$
+int iter=0;
+alpha=df( dx(u)*dx(u) + dy(u)*dy(u) ); // optimization 
+
+func real[int] dJ(real[int] & u)
+  {
+    Vh w;w[]=u; 
+    alpha=df( dx(w)*dx(w) + dy(w)*dy(w) ); // optimization 
+    varf au(uh,vh) = int2d(Th)( alpha*( dx(w)*dx(vh) + dy(w)*dy(vh) ) - b*vh)
+    + on(1,2,3,4,uh=0);
+    u= au(0,Vh);  
+    return u; // warning no return of local array  
+  }
+
+varf alap(uh,vh)=  
+   int2d(Th)( alpha *( dx(uh)*dx(vh) + dy(uh)*dy(vh) ))   + on(1,2,3,4,uh=0);
+
+varf amass(uh,vh)=  int2d(Th)( uh*vh)  + on(1,2,3,4,uh=0);
+
+matrix Amass = amass(Vh,Vh,solver=CG);
+
+matrix Alap=  alap(Vh,Vh,solver=Cholesky,factorize=1);   
+
+func real[int] C(real[int] & u)
+{
+   real[int] w=Amass*u;
+   u = Alap^-1*w;
+   return u; // no return of local array  variable 
+}
+   int conv=0;
+   real eps=1e-6; 
+   for(int i=0;i<20;i++)
+   {
+     conv=NLCG(dJ,u[],nbiter=10,precon=C,veps=eps,verbosity=5); 
+
+     if (conv) break; 
+     alpha=df( dx(u)*dx(u) + dy(u)*dy(u) ); // optimization 
+     Alap = alap(Vh,Vh,solver=Cholesky,factorize=1);   
+     cout << " restart with new preconditionner " << conv << " eps =" << eps << endl;
+   }
+   plot (u,wait=1,cmm="solution with NLCG");
+   umax = u[].max; 
+
+   Vh sss= df( dx(u)*dx(u) + dy(u)*dy(u) ) ;
+   plot (sss,wait=0,fill=1,value=1);
+
+// the  method of  Newton Ralphson to solve dJ(u)=0;
+//  see Newton.edp example
+
+}
+assert(nerr==0); 
\ No newline at end of file
diff --git a/examples++-tutorial/all.edp b/examples++-tutorial/all.edp
new file mode 100644
index 0000000..02d2f0a
--- /dev/null
+++ b/examples++-tutorial/all.edp
@@ -0,0 +1,253 @@
+NoUseOfWait=true;int verbosityy=verbosity;
+ cout << "--------- file : AdaptResidualErrorIndicator.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "AdaptResidualErrorIndicator.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : FE.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "FE.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : FEComplex.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "FEComplex.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LapDG2.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LapDG2.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Laplace-lagrange-mult.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Laplace-lagrange-mult.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Laplace.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Laplace.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LaplaceP1.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LaplaceP1.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LaplaceP1P2h.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LaplaceP1P2h.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LaplaceP1bis.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LaplaceP1bis.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : LaplaceRT.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "LaplaceRT.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : NSUzawaCahouetChabart.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "NSUzawaCahouetChabart.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Newton.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Newton.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Periodic.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Periodic.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : StokesUzawa.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "StokesUzawa.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : VI-adap.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "VI-adap.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : VI.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "VI.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : a_tutorial.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "a_tutorial.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : adapt.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "adapt.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : adaptindicatorP1.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "adaptindicatorP1.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : adaptindicatorP2.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "adaptindicatorP2.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : algo.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "algo.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : array.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "array.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : beam.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "beam.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : calculus.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "calculus.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : cavity.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "cavity.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : cavityNewtow.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "cavityNewtow.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : convect-apt.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "convect-apt.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : convect.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "convect.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : convect2.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "convect2.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : dumptable.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "dumptable.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : ex-vf.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "ex-vf.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : exception.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "exception.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : fluidStruct.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "fluidStruct.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : fluidStructAdapt.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "fluidStructAdapt.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : freeboundary-weak.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "freeboundary-weak.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : freeboundary.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "freeboundary.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : glumesh.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "glumesh.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : gnuplot.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "gnuplot.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : mat_interpol.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "mat_interpol.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : medit.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "medit.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : mesh.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "mesh.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : mortar-DN-4.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "mortar-DN-4.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : movemesh.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "movemesh.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : nl-elast-neo-Hookean.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "nl-elast-neo-Hookean.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : nolinear-elas.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "nolinear-elas.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : onde.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "onde.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : periodic4.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "periodic4.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : periodic4bis.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "periodic4bis.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : plot.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "plot.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : readmesh.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "readmesh.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : region.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "region.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : saverestore.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "saverestore.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : schwarz-gc.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "schwarz-gc.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : schwarz-no-overlap.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "schwarz-no-overlap.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : schwarz-overlap.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "schwarz-overlap.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : shur-comp.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "shur-comp.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : sparse-cmatrix.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "sparse-cmatrix.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : sparse-matrix.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "sparse-matrix.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : sphere.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "sphere.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : string.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "string.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : tablefunction.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "tablefunction.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : thermic-fast.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "thermic-fast.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : uniformmesh.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "uniformmesh.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
diff --git a/examples++-tutorial/array.edp b/examples++-tutorial/array.edp
new file mode 100644
index 0000000..ae9810b
--- /dev/null
+++ b/examples++-tutorial/array.edp
@@ -0,0 +1,357 @@
+int i;
+real [int] tab(10), tab1(10); // 2 array of 10 real 
+complex [int] ctab(10), ctab1(10); // 2 array of 10 complex 
+//string [int] stab(10);   pas code ... 
+
+
+//  real [int] tab2; //  bug 
+tab = 1;  //  set all the array to 1
+tab[1]=2;
+ctab = 1+2i;  //  set all the array to 1+2i
+ctab[1]=2;
+cout << tab[1] << " " << tab[9] << " size of tab = " << tab.n << endl;
+cout << ctab[1] << " " << ctab[9] << " size of ctab = " << ctab.n << endl;
+
+tab1=tab;
+tab=tab+tab1;
+tab=2*tab+tab1*5;
+tab1=2*tab-tab1*5;
+tab+=tab;
+cout << tab << endl;
+cout << tab[1] << " " << tab[9] <<  endl;
+
+ctab1=ctab;
+ctab=ctab+ctab1;
+ctab=2*ctab+ctab1*5;
+ctab1=2*ctab-ctab1*5;
+ctab+=ctab;
+cout << ctab << endl;
+cout << ctab[1] << " " << ctab[9] <<  endl;
+
+
+real [string] map; //  a dynamique array
+ string[string] smap;
+for (i=0;i<10;i=i+1)
+  {
+    tab[i] = i*i;
+    cout << i << " " << tab[i] << "\n";
+  };
+
+map["1"]=2.0;
+map[2]=3.0; //  2 is automaticaly cast to the string "2"
+
+cout << " map[\"1\"] = " << map["1"] << " == 2.0 ; "<< endl;
+cout << " map[2] = " << map[2] << " == 3.0 "<< endl;
+assert( abs(map["1"]-2.0)<1.e-6);
+assert(abs(map[2]-3.0)<1e-6);
+
+
+
+real [int] tab2=[1,2,3,3.14];
+int  [int] itab2=[1,2,3,5];
+
+cout << tab2 << endl;
+cout << itab2 << endl;
+tab2.resize(10);
+for (int i=4;i<10;i++) tab2[i]=i;
+cout << "tab2 = " << tab2 << endl;
+tab2 /= 2; // bug  before v2.0-3
+cout << "tab2 = " << tab2 << endl;
+tab2 *= 2;
+cout << "tab2 = " << tab2 << endl;
+
+
+real [int,int] mat(10,10),mmat(10,10);
+mat=0;
+for(int i=0;i<mat.n;i++)
+  for(int j=0;j<mat.m;j++)
+    mat(i,j)=i+100*(j+1);
+mmat=mat;
+cout << mmat << endl;
+mat.resize(15,15);
+for(int i=10;i<mat.n;i++)
+  for(int j=0;j<mat.m;j++)
+    mat(i,j)=i+100*(j+1);
+for(int i=0;i<mat.n;i++)
+  for(int j=10;j<mat.m;j++)
+    mat(i,j)=i+100*(j+1);
+cout << mat << endl; // wrong
+//mat(0:9,0:9)=mmat;  todo 
+//cout << mat << endl; // wrong
+
+// array of mesh 
+mesh[int] aTh(10);
+aTh[1]= square(2,2);
+plot(aTh[1]);
+
+// add 1 sep 2005 FH 
+real[int]  a(5),b(5),c(5),d(5);
+a = 1;
+b = 2;
+c = 3;
+a[2]=0;
+d = ( a ? b : c ); // i = 0, n-1  d[i] = a[i] ? b[i] : c[i] , 
+cout << d << endl;
+cout << "==   2       2       3       2       2 \n";
+d = (a ? 1 : 10);
+cout << " (a ? 1 : 10) "<< d << endl;
+d = (a ? b : -1);
+cout << " (a ? b : -1 ) "<< d << endl;
+d = (a ? -2 : c);
+cout << " (a ? -2 : c) " <<  d << endl;
+d =   1./d; 
+cout << " 1/ d == (a ? -2 : c) " <<  d << endl;
+d =   a/3.; 
+cout << "a/3 ==  " <<  d << endl;
+
+// Liste all array operator and method 
+// ok in version 2.0-3 
+// they exist in the 3 type of array
+// real[int] , long[int], complex[int] 
+// ---------------------------------
+int N=5;
+{
+real[int] a(N),b(N),c(N);
+a =1; 
+ a(0:4:2) = 2;
+a(3:4) = 4;
+cout <<" a = " << a << endl;
+b = a+ a;
+cout <<" b = a+a : " << b << endl;
+b += a;
+cout <<" b += a : " << b << endl;
+b += 2*a;
+cout <<" b += 2*a : " << b << endl;
+b /= 2;
+cout <<" b /= 2 : " << b << endl;
+b .*= a; // same b = b .* a 
+cout << "b*=a; b =" << b << endl;
+b ./= a; // same b = b ./ a 
+cout << "b/=a; b =" << b << endl;
+c = a+b;
+cout << " c =a+b : c=" << c << endl;
+c = 2*a+4*b;
+cout << " c =2*a+4b : c= " << c << endl;
+
+c = a+4*b;
+cout << " c =a+4b : c= " << c << endl;
+c = -a+4*b;
+cout << " c =-a+4b : c= " << c << endl;
+c = -a-4*b;
+cout << " c =-a-4b : c= " << c << endl;
+c = -a-b;
+cout << " c =-a-b : c= " << c << endl;
+
+c = a .* b; 
+cout << " c =a.*b  : c= " << c << endl;
+c = a ./ b; 
+cout << " c =a./b  : c= " << c << endl;
+c = 2 * b;
+cout << " c =2*b   : c= " << c << endl;
+c =  b*2 ;
+cout << " c =b*2   : c= " << c << endl;
+
+/*  this operator do not exist 
+c =  b/2 ;
+cout << " c =b/2   : c= " << c << endl;
+*/
+
+// ---- the  methods --
+cout << " ||a||_1     = " <<  a.l1     << endl;
+cout << " ||a||_2     = " <<  a.l2     << endl;
+cout << " ||a||_infty = " <<  a.linfty << endl;
+cout << " sum a_i     = " <<  a.sum    << endl;
+cout << " max a_i     = " <<  a.max  << " a[  " << a.imax << " ] = " << a[a.imax]     << endl;
+cout << " imax a_i     = " <<  a.imax  << " a[  " << a.imax << " ] = " << a[a.imax]     << endl;
+cout << " min a_i     = " <<  a.min  << " a[  " << a.imin << " ] = " << a[a.imin]    << endl;
+cout << " imin a_i     = " <<  a.imin  << " a[  " << a.imin << " ] = " << a[a.imin]    << endl;
+cout << " a'*a        = " <<  (a'*a)   << endl;
+cout << " a quantile 0.2 =  " <<  a.quantile(0.2) << endl;
+
+// array mapping  after version 2.3
+int[int] I=[2,3,4,-1,3];
+b=c=-3; 
+b= a(I); // for( i=0;i<b.n;i++) if(I[i] >=0)  b[i]=a[I[i]];
+c(I)= a; // for( i=0;i<I.n;i++) if(I[i] >=0)  C(I[i])=a[i];
+cout << " b = a(I) : " << b << "\n  c(I) = a " << c << endl;
+c(I) += a;// for( i=0;i<I.n;i++) if(I[i] >=0)  C(I[i])+=a[i];
+cout << " b = a(I) : " << b << "\n  c(I) = a " << c << endl;   
+
+
+}
+{
+// bidimensionnal  array
+  int N=3,M=4;
+
+  real[int,int] A(N,M);
+  real[int]  b(N),c(M);
+  b=[1,2,3];
+  c=[4,5,6,7];
+
+  complex[int,int]  C(N,M);
+  complex[int]  cb=[1,2,3],cc=[10i,20i,30i,40i];
+
+
+  b=[1,2,3];
+
+  int [int] I=[2,0,1];
+  int [int] J=[2,0,1,3];
+
+  A=1; // set the all matrix
+  A(2,:) = 4; //  the full line 2
+  A(:,1) = 5; //  the full column 1
+  A(0:N-1,2) = 2; // set the column 2
+  A(1,0:2) = 3; // set the line 1 from 0 to 2
+
+  cout << " A = " << A << endl;
+  // outer product 
+  C  =  cb*cc';
+  C +=  3*cb*cc';
+  C -=  5i*cb*cc';
+  cout << " C = " << C << endl;
+  // the way to transform a array to a sparce matrix
+  matrix B;
+  B = A; 
+  B=A(I,J); // B(i,j)= A(I(i),J(j))
+  B=A(I^-1,J^-1);  // B(I(i),J(j))= A(i,j)  
+
+  A = 2.*b*c'; // outer product  
+  cout << " A = " << A << endl;
+  cout << " A(1,2) " << A(1,2)  << endl;
+  B = b*c'; // outer product  B(i,j)  = b(i)*c(j) 
+  B = b*c'; // outer product  B(i,j)  = b(i)*c(j) 
+  B = (2*b*c')(I,J); //   outer product  B(i,j)  = b(I(i))*c(J(j)) 
+  B = (3.*b*c')(I^-1,J^-1); // outer product  B(I(i),J(j))  = b(i)*c(j) 
+  cout << "B = (3.*b*c')(I^-1,J^-1) =  " << B << endl;  
+  cout << " b =" <<  b << endl;
+  b = exp(b) ;
+  cout << " exp(b) =" <<  b << endl;
+  cb += complex(10.)*cc(0:2);
+  cout << " cb =" <<  cb << endl;
+  cb = exp(cb) ;
+  cout << " exp(cb) =" <<  cb << endl;
+  cout << " exp(cb).re =" <<  cb.re << endl;
+  cout << " exp(cb).im =" <<  cb.im << endl;
+  cb.im = 0.;
+  cout << cb << endl;
+  b += cb.re + cb.im;   //  do not work to do
+  cout << " b = " << endl; 
+ 
+}
+{
+// sort array : 
+real[int] a=[3,5,7,9,0];
+real[int] b(a);
+int[int] p=[0,1,2,3,4];
+
+b=a;
+cout << " a =" <<a << endl;
+sort(b,p);
+cout << " b.sort=" <<  b << endl;
+cout << " b = " << b << endl;
+cout << " p =  " << p << endl;
+b=a;
+b(0:5:2).sort;
+cout << b << endl; 
+cout << b(0:5:2)  << endl; 
+cout << " quantile(0.2)  = " <<  b.quantile(0.2) << endl; 
+p[0] = 1000;
+p[1] = 888;
+cout << "before    p(1:3).sort  " << p  << endl; 
+p(1:3).sort;
+cout << "after   p(1:3).sort " << p  << endl; 
+p.sort; // version 3.19 ##
+cout << "after   p.sort " << p  << endl; 
+
+macro AA [ [1,2],[3,4]] //
+macro BB [ [1,2],[5,10]] //
+ cout << AA[1][0] << " 3  " << endl;
+ cout << trace( AA * BB' + AA - BB' ) <<endl;
+}
+//  version 3.2  mai 2009
+//  like math lab. and scilab
+{
+int[int] tt(2:10); //  2,3,4,5,6,7,8,9,10  
+int[int] t1(2:3:10); // 2,5,8,
+cout << " tt(2:10)= " << tt << endl;
+cout << " t1(2:3:10)= " << t1 << endl;
+tt=1:2:5;
+cout << " 1.:2:5 =>  " << tt << endl;
+}
+
+{
+real[int] tt(2:10); //  2,3,4,5,6,7,8,9,10  
+real[int] t1(2.:3:10.); // 2,5,8,
+cout << " tt(2:10) = = " << tt << endl;
+cout << " t1(2.:3:10.)= " << t1 << endl;
+tt=1.:0.5:3.999;
+cout << " 1.:0.5:3.999 =>  " << tt << endl;
+}
+{
+complex[int] tt(2.+0i:10.+0i); //  2,3,4,5,6,7,8,9,10  
+complex[int] t1(2.:3.:10.); // 2,5,8,
+cout << " tt(2.+0i:10.+0i)= " << tt << endl;
+cout << " t1(2.:3.:10.);= " << t1 << endl;
+cout << " tt.re real part array   " << tt.re << endl ; 
+ //  the real part array of the complex array \index{re}\index{array!re}
+cout << " tt.im imag part array   " << tt.im << endl ; 
+//  the imag part array of the complex array \index{im}\index{array!im}
+
+
+}
+{
+
+real [int] tab(10), tab1(10); // 2 array of 10 real
+//real [int] tab2;    //  bug array with no size
+tab = 1.03;                //  set all the array to 1.03
+tab[1]=2.15;
+cout << tab[1] << " " << tab[9] << " size of tab = "
+     << tab.n << " min: " << tab.min << "  max:" << tab.max
+     << " sum : "   << tab.sum <<   endl; //
+tab.resize(12); //  change the size of array tab
+  // to 12 with preserving first value
+tab(10:11)=3.14; //  set unset value
+cout <<" resize tab: " <<  tab << endl;
+real [string] tt;
+tt["+"]=1.5;
+cout<<tt["a"]<<"  "<<tt["+"]<<endl;
+real[int]  a(5),b(5),c(5),d(5);
+a = 1;
+b = 2;
+c = 3;
+a[2]=0;
+d = ( a ? b : c ); // for i = 0, n-1  : d[i] = a[i] ? b[i] : c[i] ,
+cout << " d = ( a ? b : c )  is " << d << endl;
+d = ( a ? 1 : c );// for i = 0, n-1: d[i] = a[i] ? 1 : c[i] ,   (v2.23-1)
+d = ( a ? b : 0 );// for i = 0, n-1: d[i] = a[i] ? b[i] : 0 ,   (v2.23-1)
+d = ( a ? 1 : 0 );// for i = 0, n-1: d[i] = a[i] ? 0 : 1 ,     \hfill(v2.23-1)
+ tab.sort ; //  sort the array tab  (version 2.18) 
+cout << " tab (after sort) "  << tab << endl;
+int[int] ii(0:d.n-1); // set array ii to 0,1, ..., d.n-1
+d=-1:-5; // set d to  -1,-2, .. -5
+sort(d,ii); // sort array d and ii in parallele
+cout << " d " << d << "\n ii = " << ii << endl;
+
+}
+
+//  version 3.8-1
+for(int i=0;i<ARGV.n;++i)
+  {
+    cout << ARGV[i] << endl;
+  }
+// Array of FE.
+{
+mesh Th=square(2,2);
+fespace Vh(Th,P1);// scalar 
+fespace Wh(Th,[P1,P1]);// vector
+Vh[int] vh(10);
+Wh[int] [uh,wh](10); 
+vh[2]=x;
+[uh[2],wh[2]]=[y,x];
+[uh[2],wh[2]]=[y,x]; // set 3rd value 
+cout << wh.n << endl;
+cout << vh.n <<endl;
+vh.resize(20);
+cout << vh.n <<endl;
+}
+
diff --git a/examples++-tutorial/beam.edp b/examples++-tutorial/beam.edp
new file mode 100644
index 0000000..03c24ab
--- /dev/null
+++ b/examples++-tutorial/beam.edp
@@ -0,0 +1,38 @@
+//  Fluid-structure interaction for a weighting beam sitting on a
+// square cavity filled with a fluid.
+
+int bottombeam = 2;
+border a(t=2,0)  { x=0; y=t ;label=1;};        //  left beam
+border b(t=0,10) { x=t; y=0 ;label=bottombeam;};        //  bottom of beam
+border c(t=0,2)  { x=10; y=t ;label=1;};       //  rigth beam
+border d(t=0,10) { x=10-t; y=2; label=3;};     //  top beam 
+real E = 21.5;
+real sigma = 0.29;
+real mu = E/(2*(1+sigma));
+real lambda = E*sigma/((1+sigma)*(1-2*sigma));
+real gravity = -0.05;
+mesh th = buildmesh( b(20)+c(5)+d(20)+a(5));
+fespace Vh(th,[P1,P1]);
+Vh [uu,vv], [w,s];
+cout << "lambda,mu,gravity ="<<lambda<< " " << mu << " " << gravity << endl;
+// deformation of a beam under its own weight 
+// definition of 2 macro :
+real sqrt2=sqrt(2.);
+macro epsilon(u1,u2)  [dx(u1),dy(u2),(dy(u1)+dx(u2))/sqrt2] // EOM
+macro div(u,v) ( dx(u)+dy(v) ) // EOM
+
+solve bb([uu,vv],[w,s],solver=CG)=
+	int2d(th)(  
+		  lambda*div(w,s)*div(uu,vv)	
+                  +2.*mu*( epsilon(w,s)'*epsilon(uu,vv) ) 
+                 )
+  - int2d(th) (gravity*s)
+  + on(1,uu=0,vv=0)
+  ;
+
+//verbosity=100;
+plot([uu,vv],wait=1);
+plot([uu,vv],wait=1,bb=[[-0.5,2.5],[2.5,-0.5]]);
+mesh th1 = movemesh(th, [x+uu, y+vv]);
+plot(th1,wait=1);
+cout << " max deplacement = " << uu[].linfty << endl;
diff --git a/examples++-tutorial/calculus.edp b/examples++-tutorial/calculus.edp
new file mode 100644
index 0000000..f2609d3
--- /dev/null
+++ b/examples++-tutorial/calculus.edp
@@ -0,0 +1,56 @@
+real  x=3.14,y;
+int  i,j;
+complex c;
+cout << " x = " << x << "\n";
+
+x = 1;y=2;
+x=y;
+
+i=0;j=1;
+
+cout << 1 + 3 << " " <<  1/3 << "\n";
+cout << 10 ^10   << "\n";
+cout << 10 ^-10   << "\n";
+cout << -10^-2+5   << "== 4.99 \n";
+cout << 10^-2+5    << "==  5.01 \n";
+cout << "------------------ complex ---- \n" ;
+cout << 10-10i   << " \n";
+int prec=cout.precision(12);
+cout.scientific << " scientific : \n"; 
+cout << " -1^(1/3) = " << (-1+0i)^(1./3.)   << " (precision=12)\n";
+cout.precision(prec);
+cout.fixed;
+cout.showpos << " fixed and showpos :\n";
+cout << " -1^(1/3) = " << (-1+0i)^(1./3.)   << " (precision="<<prec << ")\n";
+cout.noshowpos << "noshowpos\n"; 
+cout << " 8^(1/3)= " << (8)^(1./3.)   << " \n";
+cout << " sqrt(-1) = " << sqrt(-1+0i) << " \n";
+complex a=10+1i;
+cout.default << "default \n";
+cout << a << endl;
+cout << " real(a) = " <<real(a) << " conj(a)" << conj(a) 
+     << " arg(a) = " << arg(a) << endl;
+
+cout << " ++i =" <<  ++i ;
+cout <<  " i=" << i << "\n";
+cout << " i++ = "<< i++ << "\n";
+cout << " i   = " << i << "\n";
+// ----  string concatenation ----------
+ string str,str1;
+ str="abc+";
+ str1="+abcddddd+";
+ str=str + str1;
+ str = str + 2 ;
+ cout << "str=  " << str << "== abc++abcddddd+2;\n";
+ 
+ { real x=0;
+ for (int i=0;i<10;i++)
+   x += i*i;
+ cout << " x= " << x << endl;
+ // example of if arithmetic expression 
+ real a =  x == 0 ? x : -1;
+ real b =  x != 0 ? x : -1;
+ cout << " a = " << a << " b = " << b << endl; 
+ string ss="\z\a\b\f\\--\\";
+ cout << "\""<< ss << "\"" <<  endl; 
+ }
diff --git a/examples++-tutorial/cavity.edp b/examples++-tutorial/cavity.edp
new file mode 100644
index 0000000..0abe2ba
--- /dev/null
+++ b/examples++-tutorial/cavity.edp
@@ -0,0 +1,61 @@
+mesh Th=square(8,8);
+fespace Xh(Th,P2);
+fespace Mh(Th,P1);
+Xh u2,v2;
+Xh u1,v1; 
+Mh p,q;
+
+solve Stokes ([u1,u2,p],[v1,v2,q],solver=Crout) =
+    int2d(Th)( ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            + p*dx(v1)+ p*dy(v2)
+            + dx(u1)*q+ dy(u2)*q
+           )
+  + on(3,u1=1,u2=0) 
+  + on(1,2,4,u1=0,u2=0);
+  
+plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2]);
+
+Xh psi,phi;
+
+solve streamlines(psi,phi) = 
+      int2d(Th)( dx(psi)*dx(phi) + dy(psi)*dy(phi))
+   +  int2d(Th)( -phi*(dy(u1)-dx(u2)))
+   +  on(1,2,3,4,psi=0);
+
+plot(psi,wait=1);
+int i=0;
+real  nu=1./100.;
+real dt=0.1;
+real alpha=1/dt;
+
+Xh up1,up2; 
+
+problem  NS ([u1,u2,p],[v1,v2,q],solver=Crout,init=i) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            + p*dx(v1)+ p*dy(v2)
+            + dx(u1)*q+ dy(u2)*q
+           )
+  + int2d(Th) ( -alpha*convect([up1,up2],-dt,up1)*v1 -alpha*convect([up1,up2],-dt,up2)*v2 )
+  + on(3,u1=1,u2=0) 
+  + on(1,2,4,u1=0,u2=0)
+;
+
+for (i=0;i<=20;i++)
+ {
+   up1=u1;
+   up2=u2;
+   NS;
+   if ( !(i % 10)) 
+    plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2]);  
+    
+ } ;
+if ( (i % 10))  
+  plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2]);  
+streamlines;
+plot(psi,wait=1);
diff --git a/examples++-tutorial/cavityNewtow.edp b/examples++-tutorial/cavityNewtow.edp
new file mode 100644
index 0000000..6afbceb
--- /dev/null
+++ b/examples++-tutorial/cavityNewtow.edp
@@ -0,0 +1,126 @@
+/*
+  Incompressible Navier Stokes 
+    with Taylor-Hood Finite element
+    No linearity : Newton methode 
+    continuation on Reynols Number
+    Mesh adaptation 
+*/
+real  reymax = 1600; // ok < 125000 
+mesh Th=square(8,8);
+fespace Xh(Th,P2);
+fespace Mh(Th,P1);
+fespace XXMh(Th,[P2,P2,P1]);
+XXMh [u1,u2,p];
+XXMh [v1,v2,q]; 
+
+macro div(u1,u2) (dx(u1)+dy(u2))//
+macro grad(u1,u2) [dx(u1),dy(u2)]//
+macro ugrad(u1,u2,v) (u1*dx(v)+u2*dy(v)) //
+macro Ugrad(u1,u2,v1,v2) [ugrad(u1,u2,v1),ugrad(u1,u2,v2)]//
+
+solve Stokes ([u1,u2,p],[v1,v2,q],solver=UMFPACK) =
+    int2d(Th)( ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            - p*div(v1,v2)-q*div(u1,u2)
+           )
+  + on(3,u1=4*x*(1-x),u2=0) 
+  + on(1,2,4,u1=0,u2=0);
+
+ Xh uu1=u1,uu2=u2;  
+plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[uu1,uu2],wait=1);
+
+Xh psi,phi;
+
+
+solve streamlines(psi,phi) = 
+      int2d(Th)( dx(psi)*dx(phi) + dy(psi)*dy(phi))
+   +  int2d(Th)( -phi*(dy(u1)-dx(u2)))
+   +  on(1,2,3,4,psi=0);
+
+plot(psi,wait=1);
+int i=0;
+real  nu=1./100.;
+real dt=0.1;
+real alpha=1/dt;
+
+
+
+/* NL 
+ varf   vNS ([u1,u2,p],[v1,v2,q],solver=Crout,init=i) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            + p*dx(v1)+ p*dy(v2)
+            + dx(u1)*q+ dy(u2)*q
+            + Ugrad(u1,u2,u1,u2)'*[v1,v2]
+           )   
+  + on(3,u1=1,u2=0) 
+  + on(1,2,4,u1=0,u2=0) 
+*/
+
+XXMh [up1,up2,pp];
+varf   vDNS ([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+            
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            + p*dx(v1)+ p*dy(v2)
+            + dx(u1)*q+ dy(u2)*q
+            + Ugrad(u1,u2,up1,up2)'*[v1,v2]
+            + Ugrad(up1,up2,u1,u2)'*[v1,v2]
+           )
+  + on(1,2,3,4,u1=0,u2=0) 
+;
+
+
+varf   vNS ([u1,u2,p],[v1,v2,q]) =
+    int2d(Th)(
+          
+            + nu * ( dx(up1)*dx(v1) + dy(up1)*dy(v1)
+            +  dx(up2)*dx(v2) + dy(up2)*dy(v2) )
+            + pp*q*(0.000001) 
+            + pp*dx(v1)+ pp*dy(v2)
+            + dx(up1)*q+ dy(up2)*q
+            + Ugrad(up1,up2,up1,up2)'*[v1,v2]//'
+	      )
+  + on(1,2,3,4,u1=0,u2=0) 
+  ;
+
+for(real re=100;re<=reymax;re *=2)
+  { 
+    
+    real lerr=0.1;
+    
+    if(re>8000) lerr=0.05;
+    if(re>10000) lerr=0.01; 
+    for(int step=0;step<2;step++)
+      {
+	Th=adaptmesh(Th,[u1,u2],p,err=lerr,nbvx=100000,abserror=0, cutoff=0.01);
+	//plot(Th,wait=0);
+	[u1,u2,p]=[u1,u2,p];
+	[up1,up2,pp]=[up1,up2,pp];
+	
+	for (i=0;i<=20;i++)
+	  {
+	    nu =1./re;
+	    up1[]=u1[];
+	    real[int] b = vNS(0,XXMh);
+	    matrix Ans=vDNS(XXMh,XXMh);
+	    set(Ans,solver=UMFPACK);
+	    real[int] w = Ans^-1*b;
+	    u1[] -= w;
+	    cout << " iter = "<< i << "  " << w.l2 <<  " rey = " << re << endl;
+	    if(w.l2<1e-6) break; 
+	    // uu1=u1;uu2=u2;
+	    //plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[uu1,uu2]);  
+	    
+	  } ;
+      }
+    uu1=u1;uu2=u2;
+    streamlines;
+    plot(coef=0.2,cmm="rey="+re+" [u1,u2] et p  ",psi,[uu1,uu2],wait=0,nbiso=20,ps="cavity-"+re+".ps");  
+  }
diff --git a/examples++-tutorial/convect-apt.edp b/examples++-tutorial/convect-apt.edp
new file mode 100755
index 0000000..6ffcfd0
--- /dev/null
+++ b/examples++-tutorial/convect-apt.edp
@@ -0,0 +1,86 @@
+// This a the rotating hill problem with one turn.
+// First 1/2 turn is a convection equation and second 1/2 a convection diffusion
+int kt=6;
+int kloop=5;
+int nbadap=5;
+
+bool inq=0;
+real tol=0.05;
+real tol2=1e-4;
+
+border a(t=0, 2*pi)     {    x = cos(t);    y = sin(t);  }; // the unit circle
+mesh th = buildmesh(a(70));                                 // triangulates the disk
+fespace Vh(th,P1);
+
+Vh u1 = y, u2 = -x;           // rotation velocity
+Vh m11=0,m22=0,m12=0;         // to store the metric field
+Vh vT;                        // to save the initial in big loop
+int i;
+Vh vv,vo,vp; // working  Finite element function 
+
+
+
+func rhill=sqrt((x-0.3)^2 +(y-0.3)^2);
+func  hill = 1-tanh(30*(rhill-0.2));
+//func real hill(real r2)  { return 1-tanh(100*(r2-0.04));}
+
+Vh v = hill;//((x-0.3)^2 +(y-0.3)^2);     // initial condition
+
+plot(v);
+vp=0;
+
+for (int i=0;i<nbadap;i++)
+ {
+  th=adaptmesh(th,v,err=tol,inquire=inq);
+  v = hill;//((x-0.3)^2 +(y-0.3)^2);
+        real errl2= sqrt(int2d(th)(square(vp-v))) ;
+  vp=vp-v;      
+  cout << " interation adp =" << i << "  err l2 = " << errl2 
+       << " diff min = " << vp[].min << " max =" << vp[].max << endl
+       << " --------------- " << endl; 
+  vp=v;
+  if (errl2  < tol2) break;
+ } 
+plot(th,wait=1);
+
+real dt = 0.17,t=0;                                                 // time step
+
+vT[]=v[];
+
+real error=0;
+for ( i=0; i< 20/kt ; i++) {
+    real T=t; 
+    vp=0;
+    for (int k=0;k<kloop;k++)
+     {
+       t=T; //  restart
+       v=vT; // interpolation
+       m11=0;m22=0;m12=0; // reset metric   
+       adaptmesh(th,v,err=tol,metric=[m11[],m12[],m22[]],nomeshgeneration= true );  // warning change the order in version 1.28
+       
+       cout << "m11  = " << m11[].min << " " << m11[].max << endl;
+       cout << "m22  = " << m22[].min << " " << m22[].max << endl;
+       cout << "m12  = " << m12[].min << " " << m12[].max << endl;
+        
+       for (int j=0;j<kt;j++)
+        {
+          t = t+dt;
+          vo[]=v[];
+          v=convect([u1,u2],-dt,vo);                          // convect v by u1,u2, dt seconds, results in f
+          plot(v,cmm="convection: t="+t + ", min=" + v[].min + ", max=" +  v[].max,wait=1,dim=3);
+          adaptmesh(th,v,err=tol,metric=[m11[],m12[],m22[]],nomeshgeneration= true);
+        }
+        th=adaptmesh(th,v,err=tol,metric=[m11[],m12[],m22[]]);
+        vo=0; //
+        plot(th,wait=1,cmm="k=" + k + ", t= " + t + " ,i= " + i );  
+        real errl2= sqrt(int2d(th)(square(vp-v))) ;
+        cout << " interation " << k << "  err l2 = " << errl2 << " --------------- " <<endl; 
+        vp=v;
+  	error=errl2;
+        if (errl2  < tol2) break;
+     }
+     vT=v; 
+};
+
+
+plot(th,v,wait=1);
diff --git a/examples++-tutorial/convect.edp b/examples++-tutorial/convect.edp
new file mode 100755
index 0000000..dfcef91
--- /dev/null
+++ b/examples++-tutorial/convect.edp
@@ -0,0 +1,29 @@
+// This a the rotating hill problem with one turn.
+// First 1/2 turn is a convection equation and second 1/2 a convection diffusion
+
+border a(t=0, 2*pi)     {    x = cos(t);    y = sin(t);  }; // the unit circle
+mesh th = buildmesh(a(70));                                 // triangulates the disk
+fespace Vh(th,P1);
+func  real hill(real r2){return exp(-10*(r2));}
+
+Vh v = hill( (x-0.3)^2 +(y-0.3)^2);                  // initial condition
+plot(v);
+
+real dt = 0.17,t=0;                                                 // time step
+Vh u1 = y, u2 = -x;                                        // rotation velocity
+int i;
+Vh vv,vo; // work  Finite element function 
+for ( i=0; i< 20 ; i++) {
+    t += dt;
+    vo=v;
+    v=convect([u1,u2],-dt,vo);                          // convect v by u1,u2, dt seconds, results in f
+ // convec(u1,u2,dt,v,v) won't work
+    plot(v,cmm="convection: t="+t + ", min=" + v[].min + ", max=" +  v[].max,wait=0);
+};
+
+problem  A(v,vv,solver=CG) = int2d(th)(v*vv/dt + 0.01*(dx(v)*dx(vv)+dy(v)*dy(vv)) )
+  + int2d(th)(-vv*convect([u1,u2],-dt,vo)/dt)  + on(a,v=0);
+  
+  
+
+plot(v,wait=1);
diff --git a/examples++-tutorial/convect2.edp b/examples++-tutorial/convect2.edp
new file mode 100755
index 0000000..8ef4663
--- /dev/null
+++ b/examples++-tutorial/convect2.edp
@@ -0,0 +1,35 @@
+// This a the rotating hill problem with one turn.
+// First 1/2 turn is a convection equation and second 1/2 a convection diffusion
+
+border a(t=0, 2*pi)     {    x = cos(t);    y = sin(t);  }; // the unit circle
+mesh th2 = buildmesh(a(35));                                 // triangulates the disk
+mesh th= trunc(th2,1,split=2);
+fespace Vh(th,P1);
+fespace Vh2(th2,P2);
+Vh2 v = exp(-10*((x-0.3)^2 +(y-0.3)^2));                  // initial condition
+plot(v);
+
+real dt = 0.17,t=0;                                                 // time step
+Vh u1 = y, u2 = -x;                                        // rotation velocity
+int i;
+Vh2 vv,vo; // work  Finite element function 
+for ( i=0; i< 20 ; i++) {
+    t += dt;
+    vo=v;
+    v=convect([u1,u2],-dt,vo);                          // convect v by u1,u2, dt seconds, results in f
+ // convec(u1,u2,dt,v,v) won't work
+    plot(v,cmm="convection: t="+t + ", min=" + v[].min + ", max=" +  v[].max,wait=0);
+};
+
+problem  A(v,vv,solver=CG) = int2d(th2)(v*vv/dt + 0.01*(dx(v)*dx(vv)+dy(v)*dy(vv)) )
+  + int2d(th2)(-vv*convect([u1,u2],-dt,vo)/dt)  + on(a,v=0);
+  
+for ( i=0; i< 20 ; i++) 
+{ 
+    t += dt;
+  vo=v;
+  A; // solve le problem A
+  plot(v,cmm="convection& diffusive: t="+t + ", min=" + v[].min + ", max=" +  v[].max);
+};  
+
+plot(v,wait=1);
diff --git a/examples++-tutorial/dumptable.edp b/examples++-tutorial/dumptable.edp
new file mode 100644
index 0000000..78dfc9e
--- /dev/null
+++ b/examples++-tutorial/dumptable.edp
@@ -0,0 +1,3 @@
+ofstream table("lestables");
+dumptable(table);
+if (!exec("ls")) cout << " execution ok " << endl;
diff --git a/examples++-tutorial/ex-vf.edp b/examples++-tutorial/ex-vf.edp
new file mode 100644
index 0000000..94d68bd
--- /dev/null
+++ b/examples++-tutorial/ex-vf.edp
@@ -0,0 +1,27 @@
+//  signe of pressure if correct 
+assert(version>1.18); 
+mesh Th=square(10,10);
+fespace Xh(Th,P2),Mh(Th,P1);
+Xh u1,u2,v1,v2;
+Mh p,q,ppp;
+
+
+varf bx(u1,q) = int2d(Th)( (dx(u1)*q)); 
+
+varf by(u1,q) = int2d(Th)( (dy(u1)*q));
+
+varf a(u1,u2)= int2d(Th)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) )
+                    +  on(1,2,4,u1=0)  +  on(3,u1=1) ;
+
+Xh bc1; bc1[] = a(0,Xh);
+Xh b;
+                   
+matrix A= a(Xh,Xh,solver=CG); 
+matrix Bx= bx(Xh,Mh);
+matrix By= by(Xh,Mh);
+Xh bcx=1,bcy=0;
+Mh f=x;
+Xh g=sin(x);
+b[]  = Bx'*f[]; 
+b[] += bc1[] .*bcx[];
+u1[] = A^-1*b[];
diff --git a/examples++-tutorial/exception.edp b/examples++-tutorial/exception.edp
new file mode 100644
index 0000000..9a1c581
--- /dev/null
+++ b/examples++-tutorial/exception.edp
@@ -0,0 +1,35 @@
+real a;
+try { 
+  a=1./0.;
+}
+catch  (...) 
+{
+  cout << " get a ExecError " << endl;
+  a =0;
+}
+
+verbosity=10;
+
+int nn=5	;
+mesh Th=square(nn,nn);
+verbosity=5;
+fespace Vh(Th,P1);     // P1 FE space
+Vh uh,vh;              // unkown and test function. 
+func f=1;                 //  right hand side function 
+func g=0;                 //  boundary condition function
+real   cpu=clock(); 
+problem laplace(uh,vh,solver=Cholesky,tolpivot=1e-6) =                    //  definion of  the problem 
+int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+  + int2d(Th)( -f*vh )                          //  linear form
+  ;
+
+try {
+  cout << " Try Cholesky \n";
+  laplace; // solve the problem plot(uh); // to see the result
+  cout << "-- lap Cholesky " << nn << "x" << nn << "  : " <<  -cpu+clock() << " s,  max =" << uh[].max << endl;
+} 
+catch(...) {
+  cout << " Catch cholesky PB " << endl;
+}
+
+
diff --git a/examples++-tutorial/fluidStruct.edp b/examples++-tutorial/fluidStruct.edp
new file mode 100644
index 0000000..417092b
--- /dev/null
+++ b/examples++-tutorial/fluidStruct.edp
@@ -0,0 +1,106 @@
+assert(version>=1.24); //  for big bug is non symetric matrix see HISTORY, and sign in int1d 
+include "beam.edp"
+// Stokes on square  b,e,f,g  driven cavite on left side g 
+border e(t=0,10) { x=t; y=-10; label= 1; };      //  bottom
+border f(t=0,10) { x=10; y=-10+t ; label= 1; };   //  right
+border g(t=0,10) { x=0; y=-t ;label= 2;};       //  left
+border h(t=0,10) { x=t; y=vv(t,0)*( t>=0.001 )*(t <= 9.999); label=3;};   //  top of cavity deforme 
+
+
+mesh sh = buildmesh(h(-20)+f(10)+e(10)+g(10));
+plot(sh,wait=1);
+
+fespace Xh(sh,P2),Mh(sh,P1);
+fespace V1h(sh,P2);
+
+Xh u1,u2,v1,v2;
+Mh p,q,ppp;
+
+
+varf bx(u1,q) = int2d(sh)( -(dx(u1)*q)); 
+
+varf by(u1,q) = int2d(sh)( -(dy(u1)*q));
+
+varf Lap(u1,u2)= int2d(sh)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) )
+                   +  on(2,u1=1) +  on(1,3,u1=0)   ;
+
+varf Mass(p,q)=int2d(sh)(p*q);
+
+Xh bc1; 
+Xh brhs;
+                   
+matrix A= Lap(Xh,Xh,solver=CG); 
+matrix M= Mass(Mh,Mh,solver=CG); 
+matrix Bx= bx(Xh,Mh);
+matrix By= by(Xh,Mh);
+
+Xh bcx,bcy;
+func real[int] divup(real[int] & pp)
+{ //  
+  int verb=verbosity;
+   verbosity=1;
+   brhs[]  = Bx'*pp; brhs[] += bc1[] .*bcx[];
+   u1[] = A^-1*brhs[];
+   brhs[]  = By'*pp; brhs[] += bc1[] .*bcy[];
+   u2[] = A^-1*brhs[];
+   ppp[] = M^-1*pp;
+   ppp[] = 1.e-6*ppp[];
+   ppp[] =   Bx*u1[];
+   ppp[] +=  By*u2[];
+   verbosity=verb;
+   return ppp[] ;
+};
+p=0;q=0;u1=0;v1=0;
+
+int i;
+for( i=0;i<2;i++)
+ {    
+bcx=0;
+bcy= (-y)*(10.+y)/25.;
+
+ cout << " loop " << i << endl; 
+ bc1[] = Lap(0,Xh);
+ q=0;   
+ verbosity=50;
+ LinearCG(divup,p[],eps=1.e-3,nbiter=50);
+ divup(p[]);
+ verbosity=1;
+ plot([u1,u2],p,wait=1,value=true,coef=0.1,cmm="[u1,u2],p");
+
+ real coef=0.2;
+
+V1h sigma11,sigma22,sigma12;
+Vh [uu1,vv1];
+  [uu1,vv1]=[uu,vv];
+
+  sigma11([x+uu,y+vv]) = (2*dx(u1)-p);
+  sigma22([x+uu,y+vv]) = (2*dy(u2)-p);
+  sigma12([x+uu,y+vv]) = (dx(u2)+dy(u1));
+
+
+solve  bbst([uu,vv],[w,s],init=i)  = 
+    int2d(th)(
+		  lambda*div(w,s)*div(uu,vv)	
+                  +2.*mu*( epsilon(w,s)'*epsilon(uu,vv) ) 
+             )
+  + int2d(th) (-gravity*s)
+  + int1d(th,bottombeam)( coef*(sigma11*N.x*w + sigma22*N.y*s + sigma12*(N.y*w+N.x*s) )  )
+  + on(1,uu=0,vv=0) 
+  ;
+cout << " max deplacement " << uu[].linfty << endl;
+ plot([uu,vv],wait=1);
+ real  err = sqrt(int2d(th)( (uu-uu1)^2 + (vv-vv1)^2 )); 
+ cout << " ----- Iteration = " << i <<  " Erreur L2 = " << err << "----------\n";
+ th1 = movemesh(th, [x+uu, y+vv]);
+ plot(th1,wait=1);
+ sh = buildmesh(h(-20)+f(10)+e(10)+g(10));
+ plot(sh);
+ p=p;q=q;u1=u1;u2=u2;brhs=brhs;ppp=ppp;
+ A= Lap(Xh,Xh,solver=CG); 
+ M= Mass(Mh,Mh,solver=CG); 
+ Bx= bx(Xh,Mh);
+ By= by(Xh,Mh);
+ bc1=0;  // for resize
+ bc1[] = Lap(0,Xh);
+}
+cout << " max deplacement " << uu[].linfty << endl;
diff --git a/examples++-tutorial/fluidStructAdapt.edp b/examples++-tutorial/fluidStructAdapt.edp
new file mode 100644
index 0000000..97c8cc0
--- /dev/null
+++ b/examples++-tutorial/fluidStructAdapt.edp
@@ -0,0 +1,170 @@
+assert(version>=1.24); //  for big bug is non symetric matrix see HISTORY, and sign in int1d 
+int method1=0;
+int iwait=0;
+include "beam.edp"
+// Stokes on square  b,e,f,g  driven cavite on left side g 
+border e(t=0,10) { x=t; y=-10; label= 1; };      //  bottom
+border f(t=0,10) { x=10; y=-10+t ; label= 1; };   //  right
+border g(t=0,10) { x=0; y=-t ;label= 2;};       //  left
+border h(t=0,10) { x=t; y=vv(t,0)*( t>=0.001 )*(t <= 9.999); label=3;};   //  top of cavity deforme 
+
+real err=10;
+mesh sh = buildmesh(h(-20)+f(10)+e(10)+g(10));
+plot(sh,wait=iwait);
+
+fespace Xh(sh,P2),Mh(sh,P1);
+fespace V1h(sh,P2);
+
+Xh u1,u2,v1,v2;
+Mh p,q,ppp;
+
+real veps=1e-4;
+varf bx(u1,q) = int2d(sh)( -(dx(u1)*q)); 
+
+varf by(u1,q) = int2d(sh)( -(dy(u1)*q));
+
+varf Lap(u1,u2)= int2d(sh)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) )
+                   +  on(2,u1=1) +  on(1,3,u1=0)   ;
+
+varf Mass(p,q)=int2d(sh)(p*q);
+
+Xh bc1; 
+Xh brhs;
+                   
+matrix A= Lap(Xh,Xh,solver=CG); 
+matrix M= Mass(Mh,Mh,solver=CG); 
+matrix Bx= bx(Xh,Mh);
+matrix By= by(Xh,Mh);
+func cly =(-y)*(10.+y)/25.;
+Xh bcx=0,bcy=cly;
+func real[int] divup(real[int] & pp)
+{ //  
+  int verb=verbosity;
+   verbosity=1;
+   brhs[]  = Bx'*pp; brhs[] += bc1[] .*bcx[];
+   u1[] = A^-1*brhs[];
+   brhs[]  = By'*pp; brhs[] += bc1[] .*bcy[];
+   u2[] = A^-1*brhs[];
+   ppp[] = M^-1*pp;
+   ppp[] = 1.e-6*ppp[];
+   ppp[] =   Bx*u1[];
+   ppp[] +=  By*u2[];
+   verbosity=verb;
+   return ppp[] ;
+};
+p=0;q=0;u1=0;v1=0;
+
+int i;
+ th1 = movemesh(th, [x+uu, y+vv]);
+for( i=0;i<6;i++)
+ {    
+ bc1=0; 
+ brhs=0;
+ bc1[] = Lap(0,Xh);
+ q=0;   
+ verbosity=50;
+ LinearCG(divup,p[],veps=veps,nbiter=100);
+ divup(p[]);
+ verbosity=1;
+ plot([u1,u2],p,wait=iwait,value=true,coef=0.1);
+
+ real coef=0.2;
+
+Vh [uu1,vv1];
+[uu1,vv1]=[uu,vv];
+
+if(method1==1)
+ {
+ V1h sigma11,sigma22,sigma12;
+
+  sigma11([x+uu,y+vv]) = (2*dx(u1)-p);
+  sigma22([x+uu,y+vv]) = (2*dy(u2)-p);
+  sigma12([x+uu,y+vv]) = (dx(u2)+dy(u1));
+
+solve  bbst([uu,vv],[w,s],init=i)  = 
+    int2d(th)(
+		  lambda*div(w,s)*div(uu,vv)	
+                  +2.*mu*( epsilon(w,s)'*epsilon(uu,vv) ) 
+              )
+  + int2d(th) (-gravity*s)
+  + int1d(th,bottombeam)( coef*(sigma11*N.x*w + sigma22*N.y*s + sigma12*(N.y*w+N.x*s) )  )
+  + on(1,uu=0,vv=0) 
+  ;
+  }
+ else
+ {
+ // this piece of code is crucial to mixe adaptation and fluid structure 
+ fespace  Vh11(th1,[P1,P1]);
+ varf vFS([yyyy],[w,s])= int1d(th1,bottombeam)( 
+     coef*((2*dx(u1)-p)*N.x*w + (2*dy(u2)-p)*N.y*s + (dx(u1)+dy(u2))*(N.y*w+N.x*s)) 
+   );
+ Vh11 [FS,FS1];[FS,FS1]=[0,0];
+ FS[]= vFS(0,Vh11);
+ cout << FS[].min << " " << FS[].max << endl;
+ 
+ plot([FS,FS1],wait=iwait,value=1);
+ solve  bbst2([uu,vv],[w,s],init=i)  = 
+    int2d(th)(
+		  lambda*div(w,s)*div(uu,vv)	
+                  +2.*mu*( epsilon(w,s)'*epsilon(uu,vv) ) 
+              )
+  + int2d(th) (-gravity*s)
+  + FS[] // + int1d(th,bottombeam)( coef*(sigma11*N.x*w + sigma22*N.y*s + sigma12*(N.y*w+N.x*s) )  )
+  + on(1,uu=0,vv=0) 
+  ;
+   
+ }
+ //plot([uu,vv],wait=1);
+  err = sqrt(int2d(th)( (uu-uu1)^2 + (vv-vv1)^2 )); 
+ cout << " ----- Iteration = " << i <<  " Erreur L2 = " << err << "----------\n";
+ cout << " max deplacement " << uu[].linfty << endl;
+ bool iadapt=err>0.05;
+ if(iadapt)
+ th = adaptmesh(th,[uu,vv],err=1.e-2);
+ [uu,vv]=[uu,vv];
+ [w,s]=[0,0];
+ 
+ th1 = movemesh(th, [x+uu, y+vv]);
+ //plot(th1,wait=1);
+ if(method1==1)
+   sh = buildmesh(h(-20)+f(10)+e(10)+g(10));
+ else 
+  {
+    fespace VVh(sh,P1);VVh  uh,vh;
+    solve lapllll(uh,vh,solver=CG,tgv=1e5) =                    //  definion of  the problem 
+    //  compute a deformation field for moving the fluid mesh
+    
+    //  x -> vv(x,0) is the new deformation y 
+    //  x -> y is the position of the mesh on border 3
+    int2d(sh)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) //  bilinear form
+    + on(1,2,uh=0)+ on(3,uh=(vv(x,0)-y)*( x>=0.001 )*(x <= 9.999))  ;    //  boundary condition form
+    
+    sh = movemesh(sh,[x,y+uh]);
+   if(iadapt)
+    {
+    sh = adaptmesh(sh,[u1,u2],p,err=2.e-2);
+    lapllll;  
+    sh = movemesh(sh,[x,y+uh]);    
+    }
+    plot(th1,sh,wait=iwait);
+    p=p;
+    u1=u1; 
+    u2=u2;
+    A= Lap(Xh,Xh,solver=CG); 
+    M= Mass(Mh,Mh,solver=CG); 
+    Bx= bx(Xh,Mh);
+    By= by(Xh,Mh);
+    bcx=0;
+    bcy=cly;
+  }
+
+
+ p=p;q=q;u1=u1;u2=u2;brhs=brhs;ppp=ppp;
+ A= Lap(Xh,Xh,solver=CG); 
+ M= Mass(Mh,Mh,solver=CG); 
+ Bx= bx(Xh,Mh);
+ By= by(Xh,Mh);
+ bc1=0;  // for resize
+ bc1[] = Lap(0,Xh);
+}
+cout << " max deplacement " << uu[].linfty << endl;
diff --git a/examples++-tutorial/freeboundary-weak.edp b/examples++-tutorial/freeboundary-weak.edp
new file mode 100755
index 0000000..6b53e61
--- /dev/null
+++ b/examples++-tutorial/freeboundary-weak.edp
@@ -0,0 +1,101 @@
+//  
+//   calcul d'une zone saturation en eau (nappe phreatique)
+//
+verbosity=1;
+real weak=1;
+string com= "  avec du/dn ";
+if(weak) com = " avec du/du = residu  ";
+real L=10;        // longueur du domaine					   	
+real Q=0.02;      // flux entrant
+real K=0.5;	      //permeabilite	
+
+real  erradap=0.001;
+real  coef=1;
+
+
+
+real h=2.1;	 // hauteur du bord gauche
+real h1=0.35;    // hauteur du bord droite
+
+//  maillage d'un tapeze
+border a(t=0,L){x=t;y=0;};       // bas			   	
+border b(t=0,h1){x=L;y=t;};      // droite
+border f(t=L,0){x=t;y=t*(h1-h)/L+h;}; //  free surface
+border d(t=h,0){x=0;y=t;};      // gauche
+
+int n=10;
+mesh Th=buildmesh (a(L*n)+b(h1*n)+f(sqrt(L^2+(h-h1)^2)*n)+d(h*n));
+
+plot(Th,ps="dTh.eps");
+
+fespace Vh(Th,P1);
+
+int j=0,ii=0;
+
+Vh p,v,pp,vv;
+
+varf vPp(p,pp) = int2d(Th)( dx(p)*dx(pp)+dy(p)*dy(pp));
+varf vonfree(p,pp) =on(f,p=1);
+Vh onfree,wdpdn;
+onfree[]=vonfree(0,Vh);
+cout << "pb ?" << endl;
+onfree[]/=onfree[].max; // sauce
+cout << "pb non " << endl;
+matrix A= vPp(Vh,Vh,solver=CG);
+
+
+problem Pp(p,pp,solver=CG) = int2d(Th)( dx(p)*dx(pp)+dy(p)*dy(pp)) 
+  + on(b,f,p=y) ;
+
+//  --  imprecise (fort)
+problem Pv(v,vv,solver=CG) = int2d(Th)( dx(v)*dx(vv)+dy(v)*dy(vv)) 
+  +  on (a, v=0) + int1d(Th,f)(vv*((Q/K)*N.y- (dx(p)*N.x+dy(p)*N.y))); 
+//   -- precise (faible)
+problem Pw(v,vv,solver=CG) = int2d(Th)( dx(v)*dx(vv)+dy(v)*dy(vv)) 
+  +  on (a, v=0) + int1d(Th,f)(vv*((Q/K)*N.y)) + wdpdn[]; 
+  
+
+real errv=1;
+verbosity=1;
+while(errv>1e-6)
+{
+  j++;       
+  Pp;
+  if (weak) {   wdpdn[] = A*p[]; wdpdn[] = wdpdn[].*onfree[];   wdpdn[] = -wdpdn[];
+             Pw;}
+  else Pv;
+  errv=int1d(Th,f)(v*v);
+  plot(Th,p,v ,cmm=com+"   iter = "+j+ "  errv =" +errv,wait=0);
+  
+//  if (j%10==0)
+//    Th=adaptmesh(Th,p,err=erradap ) ;
+  real coef=1;
+  real mintcc = checkmovemesh(Th,[x,y])/5.; 
+  real mint = checkmovemesh(Th,[x,y-v*coef]); 
+  
+  if (mint<mintcc ||  j%10==0) {  
+    Th=adaptmesh(Th,p,err=erradap ) ;
+    
+     mintcc = checkmovemesh(Th,[x,y])/5.;     
+     wdpdn=0; 	
+     onfree=0;
+  }
+  
+  while (1) 
+  {  	    
+    real mint = checkmovemesh(Th,[x,y-v*coef]); 
+    
+    if (mint>mintcc) break;
+    
+    cout << " min |T]  " << mint << endl;    
+    coef /= 1.5;
+  }
+  
+  Th=movemesh(Th,[x,y-coef*v]); // calcul de la deformation 
+  A= vPp(Vh,Vh,solver=CG);	
+  onfree[]=vonfree(0,Vh);onfree[]/=onfree[].max; // sauce
+  cout << "\n\n"<<j <<"------------ errv = " << errv << "\n\n";
+
+}
+//plot(Th,wiat=1,ps="d_Thf.eps",cmm=com);
+plot(p,wait=1,ps="d_u.eps",cmm=com);
diff --git a/examples++-tutorial/freeboundary.edp b/examples++-tutorial/freeboundary.edp
new file mode 100755
index 0000000..f1a7a6f
--- /dev/null
+++ b/examples++-tutorial/freeboundary.edp
@@ -0,0 +1,76 @@
+//  
+//   calcul d'une zone saturation en eau (nappe phréatique)
+//
+real L=10;        // longueur du domaine					   	
+real q=0.02;      // flux entrant
+real K=0.5;	      //permeabilité	
+
+real  erradap=0.001;
+real  coef=1;
+
+
+
+real h=2.1;	 // hauteur du bord gauche
+real h1=0.35;    // hauteur du bord droite
+
+//  maillage d'un tapeze
+border a(t=0,L){x=t;y=0;};       // bas			   	
+border b(t=0,h1){x=L;y=t;};      // droite
+border f(t=L,0){x=t;y=t*(h1-h)/L+h;}; //  free surface
+border d(t=h,0){x=0;y=t;};      // gauche
+
+int n=10;
+mesh Th=buildmesh (a(L*n)+b(h1*n)+f(sqrt(L^2+(h-h1)^2)*n)+d(h*n));
+plot(Th,ps="dTh.eps");
+
+fespace Vh(Th,P1);
+int j=0,ii=0;
+
+Vh u,v,uu,vv;
+
+problem Pu(u,uu,solver=CG) = int2d(Th)( dx(u)*dx(uu)+dy(u)*dy(uu)) 
+  + on(b,f,u=y) ;
+
+problem Pv(v,vv,solver=CG) = int2d(Th)( dx(v)*dx(vv)+dy(v)*dy(vv)) 
+  +  on (a, v=0) + int1d(Th,f)(vv*((q/K)*N.y- (dx(u)*N.x+dy(u)*N.y))); 
+  
+
+real errv=1;
+verbosity=1;
+while(errv>1e-6)
+{
+  j++;       
+  Pu;
+  Pv;
+  plot(Th,u,v ,wait=0);
+  errv=int1d(Th,f)(v*v);
+  
+//  if (j%10==0)
+//    Th=adaptmesh(Th,u,err=erradap ) ;
+  real coef=1;
+  real mintcc = checkmovemesh(Th,[x,y])/5.; 
+  real mint = checkmovemesh(Th,[x,y-v*coef]); 
+  
+  if (mint<mintcc ||  j%10==0) {  
+    Th=adaptmesh(Th,u,err=erradap ) ;
+    v=v;
+    u=u;
+    mintcc = checkmovemesh(Th,[x,y])/5.;     
+  }
+  
+  while (1) 
+  {  	    
+    real mint = checkmovemesh(Th,[x,y-v*coef]); 
+    
+    if (mint>mintcc) break;
+    
+    cout << " min |T]  " << mint << endl;    
+    coef /= 1.5;
+  }
+  
+  Th=movemesh(Th,[x,y-coef*v]); // calcul de la deformation 
+  cout << "\n\n"<<j <<"------------ errv = " << errv << "\n\n";
+
+}
+plot(Th,ps="d_Thf.eps");
+plot(u,wait=1,ps="d_u.eps",fill=1);
diff --git a/examples++-tutorial/func.edp b/examples++-tutorial/func.edp
new file mode 100644
index 0000000..d539d6b
--- /dev/null
+++ b/examples++-tutorial/func.edp
@@ -0,0 +1,63 @@
+//  test of diff kind of freefem++ function
+// work if version >= 3.3 
+
+verbosity=500;
+
+real[int] G=[7,8,9];
+
+func mesh carre(int n) 
+{ mesh th=square(n,n);
+  return th;}
+  
+  
+func real[int]   aaa(int n) 
+{ real[int] a(n);
+  a=0;
+  a[2]=n;
+  return a;}
+  
+  
+ func real[int]   bb(real[int] &a) 
+{ cout << " sum " <<a.sum <<endl;
+  return a;}
+ func real[int]   bbb(real[int] a) 
+{ cout << " sum " <<a.sum <<endl;
+  a[0]=100; // change the value of the parameter  
+  return a;}
+
+ func real[int]   GG(int i) 
+{ G[1]=i;
+  return G;}
+ 
+ func real[int]   GGG(int i) 
+{ G[1]=i;
+  return G(1:2);} 
+
+  
+  
+mesh Th=  carre(2);
+carre(3); // the mesh is lose 
+cout << Th.nt << endl;
+cout << aaa(3) << endl;
+  
+real[int] A=[1,4,7];
+cout << bb(A) << endl;
+real[int] aa=bb(A);
+real[int] ac=bbb(A); //  warning A[0] is set to 100.
+cout << " xxxx "<< endl;
+cout << aa << " == "  << A <<endl;
+assert(A[0]==100);
+cout << ac << " == " << A << endl;
+cout << GG(3) << endl;
+cout << GGG(5) << endl;
+
+verbosity=1;
+
+//  test Nan and inf  version 3.19 
+
+real x=1e1000;
+cout << x << " " << isInf(x) << " " << isNaN(x) << " " << isNormal(x) <<endl;
+x =1;
+cout << x << " " << isInf(x) << " " << isNaN(x) << " " << isNormal(x)<<endl;
+x = NaN();
+cout << x << " " << isInf(x) << " " << isNaN(x) << " " << isNormal(x)<<endl;
\ No newline at end of file
diff --git a/examples++-tutorial/glumesh.edp b/examples++-tutorial/glumesh.edp
new file mode 100644
index 0000000..8ffc62e
--- /dev/null
+++ b/examples++-tutorial/glumesh.edp
@@ -0,0 +1,45 @@
+
+mesh Th1=square(10,10);
+mesh Th2=square(20,10,[x+1,y]);
+verbosity=3;
+int[int] r1=[2,18],  r2=[4,0];
+savemesh(Th1,"meshTh1_av.mesh");
+Th1=change(Th1,refe=r1);
+savemesh(Th1,"meshTh1_ap.mesh");
+Th2=change(Th2,refe=r2);
+mesh Th=Th1+Th2;
+cout << " nb ref = " << int1d(Th1,1,3,4)(1./lenEdge)+int1d(Th2,1,2,3)(1./lenEdge) 
+     << " == " << int1d(Th,1,2,3,4)(1./lenEdge) <<" == " << ((10+20)+10)*2 << endl; 
+plot(Th,wait=1);
+fespace Vh(Th,P1);
+macro Grad(u) [dx(u),dy(u)]//
+Vh u,v;
+solve P(u,v)=int2d(Th)(Grad(u)'*Grad(v))-int2d(Th)(v)+on(1,3,u=0);
+plot(u,wait=1);
+
+// FFCS: for regression tests
+real regtest;
+
+{
+// ---------------
+real R=50.*sqrt(2.); //  theta = 
+//un quart du paraboloide
+border t1(t=0,R) {x=t;y=0;    label=1;}
+border t2(t=0,R) {x=(R-t);y=t;label=2;}
+border t3(t=R,0) {x=0;y=t;    label=3;}
+int nn=3;
+mesh Th= buildmesh(t1(5*nn)+t2(5*sqrt(2.)*nn)+t3(5*nn));  
+plot(Th,wait=0);
+
+ mesh Th4;
+
+mesh th1=movemesh(Th,[x,-y]);
+mesh th2=movemesh(Th,[-x,-y]);
+mesh th3=movemesh(Th,[-x,y]);
+plot(Th,th1,th2,th3,wait=1);
+ Th4=Th+th1+th2+th3;
+
+plot(Th4,wait=1);
+Th=Th4;
+regtest=Th.nv;
+}
diff --git a/examples++-tutorial/gnuplot.edp b/examples++-tutorial/gnuplot.edp
new file mode 100644
index 0000000..e69f6da
--- /dev/null
+++ b/examples++-tutorial/gnuplot.edp
@@ -0,0 +1,31 @@
+int n=20,nn=n+10;
+real[int] xx(nn),yy(nn);
+mesh Th=square(5,5);
+fespace Vh(Th,P2);
+Vh uh=x*x+y*y,vh=-y^2+x^2;
+assert(n+1 < nn);
+//  compute a cut 
+for (int i=0;i<=n;i++)
+ {
+   xx[i]=i;
+   yy[i]=uh(real(i)/n,real(i)/n); // value of uh at point (i/10. , i/10.) 
+ }
+ 
+ plot(Th,uh,[uh,vh],value=true,ps="three.eps",wait=true); // plot mesh, isovalue, and vector
+ plot([xx(0:n),yy(0:n)],[xx(0:n:5),yy(0:n:5)],ps="likegnu.eps",wait=true); //  like gnuplot plot a cut of uh
+// file for gnuplot
+{
+  ofstream gnu("plot.gp");
+for (int i=0;i<=n;i++)
+ {
+  gnu <<  xx[i] << " " << yy[i] << endl;
+ }
+}
+//  to call gnuplot command and wait 5 second (tanks to unix command)
+//  and make postscipt plot 
+exec("echo 'plot \"plot.gp\" w l \
+pause 5 \
+set term postscript \
+set output \"gnuplot.eps\" \
+replot \
+quit' | gnuplot"); 
\ No newline at end of file
diff --git a/examples++-tutorial/intlevelset.edp b/examples++-tutorial/intlevelset.edp
new file mode 100644
index 0000000..cad1aa6
--- /dev/null
+++ b/examples++-tutorial/intlevelset.edp
@@ -0,0 +1,76 @@
+int err=0;
+mesh Th=square(50,50,[3*x-1.5,3*y-1.5]);
+func r = sqrt(x*x +y*y);
+// wrong ...
+real lc ;
+verbosity=0;
+lc = int1d(Th,levelset=r-1.)(1.) ; 
+cout << " len of the level set = " <<  lc  << " =  2pi " << 2*pi ;
+cout << ", Ok = " << (abs(lc-2*pi) < 1e-1) << endl; 
+if( abs(lc-2*pi) > 1e-1) err++;
+fespace Vh(Th,P1);
+// test linear and bilinear ... 
+varf vl(u,v) = int1d(Th,levelset=r-1.)(v) + int1d(Th,levelset=r-1.)(u*v);
+real[int] vv=vl(0,Vh);
+
+cout << " len of the level set (varf linear ) = " <<  (lc=vv.sum)  << "=  2pi " << 2*pi ;
+cout  << ", Ok = " << (abs(lc-2*pi) < 1e-1) << endl;
+if( abs(lc-2*pi) > 1e-1) err++; 
+real[int]  one(Vh.ndof); 
+one=1.;
+matrix VV=vl(Vh,Vh); //  matrix with levelset
+vv = VV*one;
+cout << " len of the level set (varf bilinear same) = " <<  (lc=vv.sum)  << "=  2pi " << 2*pi;
+cout << ", Ok = " << (abs(lc-2*pi) < 1e-1) << endl;; 
+if( abs(lc-2*pi) > 1e-1) err++;
+
+//  just for test a idea approximation of int of negative part of levelset 
+//   to we just change the mesure of the element not the quadrature point 
+{ // test new stuff for level set  ... 
+    macro grad(u) [dx(u),dy(u)] //
+    Vh u,v;
+    solve Pxx(u,v) = int2d(Th) ( grad(u)'*grad(v)*1e-8 ) + int2d(Th, levelset= 1-r) ( grad(u)'*grad(v) ) + on(1,u=0) + int2d(Th, levelset= 1-r) ( 1*v);
+    plot(u,wait=1);   
+    varf vxx(u,v) =  int2d(Th, levelset= 1-r) ( u*v ) + int2d(Th, levelset= 1-r) ( 1*v);
+  matrix XX=vxx(Vh,Vh);
+  real[int] xx=vxx(0,Vh);
+  real area1= int2d(Th, levelset= 1-r)(1.);
+  cout << "  area1 = " << area1 << "  ~= " << Th.area - pi << endl;
+  assert(abs(area1-(Th.area - pi)) < 0.1); 
+  cout << " xx.sum = " << xx.sum << " == " << area1 <<endl;
+  assert(abs(area1-xx.sum) < 1e-8); 
+  
+  real[int] yy(Vh.ndof); yy=1;
+  xx= XX*yy;
+  cout << " XX.sum = " << xx.sum << " == " << area1 << endl;
+  assert(abs(area1-xx.sum) < 1e-8); 
+}
+
+
+
+if(1){// test on diff mesh  not wet implemented (FH  frev 2014)
+mesh Th1=square(10,10,[3*x-1.5,3*y-1.5]);
+mesh Th2=square(11,11,[3*x-1.5,3*y-1.5]);
+fespace Vh1(Th1,P1);
+fespace Vh2(Th2,P1);
+
+varf vl(u,v) = int1d(Th,levelset=r-1.)(v) + int1d(Th,levelset=r-1.)(u*v);
+real[int] vv=vl(0,Vh2);
+
+cout << " len of the level set (varf linear diff    ) = " <<  (lc=vv.sum)  << "=  2pi " << 2*pi ;
+cout  << ", Ok = " << (abs(lc-2*pi) < 1e-1) << endl;
+if( abs(lc-2*pi) > 1e-1) err++; 
+real[int]  one(Vh1.ndof); 
+one=1.;
+// sorry not implemented to day ... FH 
+//verbosity=10000;
+matrix VV=vl(Vh1,Vh2); // no build of matrix with levelset 
+vv = VV*one;
+cout << " len of the level set (varf bilinear diff ) = " <<  (lc=vv.sum)  << "=  2pi " << 2*pi;
+cout << ", Ok = " << (abs(lc-2*pi) < 1e-1) << endl;; 
+if( abs(lc-2*pi) > 1e-1) err++;
+
+}
+cout << " Nb err " << err << endl;
+assert(err==0);
+
diff --git a/examples++-tutorial/io.edp b/examples++-tutorial/io.edp
new file mode 100644
index 0000000..478e419
--- /dev/null
+++ b/examples++-tutorial/io.edp
@@ -0,0 +1,50 @@
+border floor(t=0,1){ x=t; y=0; label=1;}; // the unit square
+border right(t=0,1){ x=1; y=t; label=5;};
+border ceiling(t=1,0){ x=t; y=1; label=5;};
+border left(t=1,0){ x=0; y=t; label=5;};
+int n=10;
+mesh th= buildmesh(floor(n)+right(n)+ceiling(n)+left(n));
+savemesh(th,"toto.am_fmt");// format "formated Marrocco"
+savemesh(th,"toto.Th");//format database "bamg"
+savemesh(th,"toto.dbg");//format debug
+savemesh(th,"toto.msh"); //format freefem
+mesh th2 = readmesh("toto.msh");
+fespace femp1(th,P1);
+femp1 f = sin(x)*cos(y),g;
+int where;
+real xx;
+{
+  
+  ofstream file("f.txt");
+  file.precision(16);
+  file << f[] << endl;
+  where=file.tellp();
+  file << 0.1 ;
+  //  file << " " << 0.2 ;
+  cout << " where in file " << where << endl;
+}
+{
+  ifstream file("f.txt");
+  cout << " where " << file.seekg << endl; 
+  file.seekg(where);
+  file >> xx;
+  cout <<  " xx = " << xx << " good ? " << file.good() << endl;
+  assert(xx==0.1);
+  file.seekg(0);
+  cout << " where " << file.tellg() << " " << file.good() << endl; 
+  file >> g[] ;
+}
+fespace Vh2(th2,P1);
+Vh2 u,v;
+plot(g);
+solve pb(u,v) =
+    int2d(th2)( u*v -dx(u)*dx(v)-dy(u)*dy(v) )
+  + int2d(th2)(-g*v) 
+  + int1d(th2,5)( -g*v)
+  + on(1,u=0) ;
+plot (th2,u);
+cout << " (u[],u[]) = " << (u[]'*u[]) << endl; 
+{
+ofstream file("u.txt");
+file << u[] << endl;
+}
diff --git a/examples++-tutorial/mat_interpol.edp b/examples++-tutorial/mat_interpol.edp
new file mode 100644
index 0000000..33f1605
--- /dev/null
+++ b/examples++-tutorial/mat_interpol.edp
@@ -0,0 +1,62 @@
+mesh Th=square(4,4);
+mesh Th4=square(2,2,[x*0.5,y*0.5]);
+plot(Th,Th4,ps="ThTh4.eps",wait=1);
+fespace Vh(Th,P1);
+fespace Vh4(Th4,P1);
+fespace Wh(Th,P0);
+fespace Wh4(Th4,P0);
+
+// remark in previous version (before v1.44)
+// the name of interpolate function is interplotematrix
+
+matrix IV= interpolate(Vh,Vh4); //  here the function is 
+// exended by continuity
+
+cout << " IV Vh<-Vh4 " << IV << endl;
+Vh v;          Vh4 v4=x*y;
+v=v4;           real[int]   vv= IV*v4[];
+// here   v[]  == vv    =>  
+real[int]  diff= vv - v[]; 
+cout << " || v - vv || = " <<  diff.linfty << endl;
+assert( diff.linfty<= 1e-6); // 
+
+matrix IV0= interpolate(Vh,Vh4,inside=0);//  here the function is 
+// exended by zero
+
+cout << " IV Vh<-Vh4 (inside=1)  " << IV0 << endl;
+
+matrix IVt0= interpolate(Vh,Vh4,inside=1,t=1);
+cout << " IV Vh<-Vh4^t (inside=1)  " << IVt0 << endl;
+
+matrix IV4t0= interpolate(Vh4,Vh);
+cout << " IV Vh4<-Vh^t  " << IV4t0 << endl;
+
+matrix IW4= interpolate(Wh4,Wh);
+cout << " IV Wh4<-Wh  " << IW4  << endl;
+
+matrix IW4V= interpolate(Wh4,Vh);
+cout << " IV Wh4<-Vh  " << IW4  << endl;
+
+
+
+fespace V4h(Th4,[P1,P1,P1,P1]);
+fespace V3h(Th,[P1,P1,P1]);
+int[int] u2vc=[1,3,-1];// -1 => put zero on the componante ;
+matrix IV34= interpolate(V3h,V4h,inside=0,U2Vc=u2vc);//  here the function is 
+V4h [a1,a2,a3,a4]=[1,2,3,4];
+V3h [b1,b2,b3]=[10,20,30];
+b1[]=IV34*a1[];
+
+cout << "b1 = " << b1(.25,.25) << " == " << 2 << endl;
+cout << "b2 = " << b2(.25,.25) << " == " << 4 <<endl;
+cout << "b3 = " << b3(.25,.25) << " == " << 0 <<endl;
+// Build interplation matrix a_ij at points (xx[j],yy[j]) j = 0, 1 :
+//  $a_ij = d_op(w^i_c (xx[j],yy[j]))$ where $w_i$ is the basic function.  
+real[int] xx=[.3,.4],yy=[.1,.4];
+int c=0,dop=0; //  component and d operator 
+matrix Ixx= interpolate(Vh,xx,yy,op=dop,composante=c);
+cout << Ixx << endl;
+Vh ww;
+real[int] dd=[1,2]; 
+ww[]= Ixx*dd;
+plot(ww,wait=1);
\ No newline at end of file
diff --git a/examples++-tutorial/medit.edp b/examples++-tutorial/medit.edp
new file mode 100644
index 0000000..14e54bc
--- /dev/null
+++ b/examples++-tutorial/medit.edp
@@ -0,0 +1,32 @@
+int n=20,nn=n+10;
+real[int] xx(nn),yy(nn);
+// build square $]-1,1[^2$
+mesh Th=square(10,10,[2*x-1,2*y-1]); 
+fespace Vh(Th,P1);
+Vh u=2-x*x-y*y;
+// old code ::
+if(1)
+{
+   savemesh(Th,"mm",[x,y,u*.5]); //  save mm.points and mm.faces file for medit
+   // build a mm.bb file 
+	{ ofstream file("mm.bb"); 
+	file << "2 1 1 "<< u[].n << " 2 \n";
+	int j;
+	for (j=0;j<u[].n ; j++)  
+	  file << u[][j] << endl; 
+    }  
+    // call ffmedit command 	
+    if(!NoGraphicWindow) exec("ffmedit mm");
+    // clean files
+    exec("rm mm.bb mm.faces mm.points");
+}
+else 
+{
+// new code 
+load "medit" load "msh3"  
+    mesh3 Th3= movemesh23(Th,transfo=[x,y,u*0.5]);
+    medit("mm",Th3);// bug un color of u ... FH 
+}
+
+// FFCS: testing 3D plots
+plot(u);
diff --git a/examples++-tutorial/mesh.edp b/examples++-tutorial/mesh.edp
new file mode 100644
index 0000000..72c1198
--- /dev/null
+++ b/examples++-tutorial/mesh.edp
@@ -0,0 +1,340 @@
+// FFCS: for regression tests
+real regtest;
+{
+ // build from bamg geometrie
+
+  { // build the geom file
+    ofstream ff("g.mesh");
+    int n = 8;
+    real h = 0.1;
+    ff <<"MeshVersionFormatted 0\n";
+    ff <<"AngleOfCornerBound 46\n";
+    ff <<"Dimension 2 \n";
+    ff << "Vertices "<< n <<  endl;
+    for (int i=0;i<n;i++)
+      ff << cos(i*pi*2./n) << " " << sin(i*pi*2./n) << " 1\n"; 
+    
+    ff << "Edges "<< n<< endl;
+    for (int i=0;i<n;i++)
+      ff << i+1 << " " << (i+1)%n +1 << " 1\n";
+    
+    ff << "hVertices"<< endl;
+    for (int i=0;i<n;i++)
+      ff << h << endl;
+  }
+  
+  mesh Th=buildmesh("g.mesh",nbvx=100000);
+  plot(Th,wait=1);
+}
+
+//    example for mesh work 
+// --------------------------
+{ // square 
+  real x0=1.2,x1=1.8;
+  real y0=0,y1=1;
+  int n=5,m=20;
+  mesh Th=square(n,m,[x0+(x1-x0)*x,y0+(y1-y0)*y]);
+  int[int] lab=[5,5,5,5]; // the 4 side 1,2,3,4 have label 5
+  mesh th=square(4,5,label=lab,region=1);
+  plot(Th,th,ps="twosquare.eps");
+
+}
+// ------------------------------------------------------------
+{ //    hole 
+real pi=4*atan(1);
+border a(t=0,2*pi){ x=cos(t); y=sin(t);label=1;}
+border b(t=0,2*pi){ x=0.3+0.3*cos(t); y=0.3*sin(t);label=2;}
+border c(t=0,2*pi){ x=0.3+0.0001*cos(t); y=0.0001*sin(t);label=2;}
+mesh Thwithouthole= buildmesh(a(50)+b(+30));
+mesh Thwithhole   = buildmesh(a(50)+b(-30));
+// to change the default maximun number of vertices to 100000
+mesh Thwithtinyhole   = buildmesh(a(50)+c(-5),nbvx=100000); 
+plot(Thwithouthole,wait=1,ps="Thwithouthole.eps");
+plot(Thwithhole,wait=1,ps="Thwithhole.eps");
+plot(Thwithtinyhole,wait=1,ps="Thwithtinyhole.eps");
+
+}
+// ------------------------------------------------------------
+{ //  square with border 
+border a(t=0,2){x=t; y=0;label=1;};
+border b(t=0,1){x=2; y=t;label=1;};
+border c(t=2,0){x=t; y=1;label=1;};
+border d(t=1,0){x=0; y=t;label=1;};
+int n = 20;
+plot(a(2*n)+b(n)+c(2*n)+d(n),wait=1,ps="squarebb.eps");
+mesh th= buildmesh(a(2*n)+b(n)+c(2*n)+d(n)); 
+plot(th,ps="squareb.eps");
+}
+// ------------------------------------------------------------
+// bug before version 2.24
+{ // L shape 
+border a(t=0,1){x=t;y=0;label=1;};
+border b(t=0,0.5){x=1;y=t;label=1;};
+border c(t=0,0.5){x=1-t;y=0.5;label=1;};
+border d(t=0.5,1){x=0.5;y=t;label=1;};
+border e(t=0.5,1){x=1-t;y=1;label=1;};
+border f(t=0,1){x=0;y=1-t;label=1;};
+assert(version >= 2.24);
+ func abc=  a(6) + b(4) + c(4)  ;
+ func def = d(4) + e(4) + f(6);
+ plot(abc  + def,wait=1);
+mesh rh = buildmesh (abc  + def );
+plot(rh,ps="lshape.eps");
+
+}
+// ------------------------------------------------------------
+{ // readmesh 
+  mesh th("aile.msh");
+  plot(th);
+  
+}
+// ------------------------------------------------------------
+{ // movemesh 
+  real Pi=atan(1)*4;
+  verbosity=4;
+  border a(t=0,1){x=t;y=0;label=1;};
+  border b(t=0,0.5){x=1;y=t;label=1;};
+  border c(t=0,0.5){x=1-t;y=0.5;label=1;};
+  border d(t=0.5,1){x=0.5;y=t;label=1;};
+  border e(t=0.5,1){x=1-t;y=1;label=1;};
+  border f(t=0,1){x=0;y=1-t;label=1;};
+  func uu= sin(y*Pi)/10;
+  func vv= cos(x*Pi)/10;
+  
+  mesh Th = buildmesh ( a(6) + b(4) + c(4) +d(4) + e(4) + f(6));
+  
+  // find a good deformation coef. 
+  // ---------------------------------
+  // return the minimal area of a triangle of Th 
+  real okareamin = checkmovemesh(Th,[x,y])/10;
+  // we accept to divide by 10 the area of the smallest triangles
+  real coef=1000,cc=0;
+  while (okareamin > (cc=checkmovemesh(Th,[x+coef*uu,y+coef*vv]) ) )
+    {
+      cout << " coef = " << coef << " min area " << cc << endl;
+      coef /=2;
+    }
+  
+  
+  Th=movemesh(Th,[x+coef*uu,y+coef*vv]);
+  plot(Th,wait=1,fill=1,ps="movemesh.eps");
+  
+  // save mesh 
+  int i=12;
+  string filename="Th"+i+".msh";
+  savemesh(Th,filename);
+}
+// ------------------------------------------------------------
+{  //  trunc mesh  tools exemples 
+  mesh Th=square(3,3);
+  int[int] n2o(1); 
+  fespace Vh(Th,P1);
+  Vh u;	
+  int i,n=u.n;
+  u=0;
+  for (i=0;i<n;i++)
+    {
+      u[][i]=1;
+      plot(u,wait=1);
+      mesh Shi=trunc(Th,abs(u)>1e-10,split=2,label=2,new2old=n2o);
+      plot(Th,Shi,wait=1,ps="trunc"+i+".eps");                    
+      cout << " n2o " << n2o << endl; // where the element come
+      u[][i]=0;
+    }
+}
+// ------------------------------------------------------------
+{  //  new stuff 2004 splitmesh (version 1.37)
+  assert(version>=1.37);
+  border a(t=0,2*pi){ x=cos(t); y=sin(t);label=1;}
+  mesh Th=buildmesh(a(20));
+  plot(Th,wait=1,ps="nosplitmesh.eps");
+  plot(Th,wait=1);
+  Th=splitmesh(Th,1+5*(square(x-0.5)+y*y));
+  plot(Th,wait=1,ps="splitmesh.eps");
+}
+
+// ------------------------------------------------------------
+{  //  new stuff 2004 emptymesh (version 1.40)
+ // -- usefull to build Multiplicator space 
+ //  build a mesh without internal point
+ // with the same boundary 
+ //  -----
+  assert(version>=1.40);
+  border a(t=0,2*pi){ x=cos(t); y=sin(t);label=1;}
+  mesh Th=buildmesh(a(20));
+  plot(Th,wait=1,ps="nosplitmesh.eps");
+  plot(Th,wait=1);
+  Th=emptymesh(Th);
+  plot(Th,wait=1,ps="emptymesh-1.eps");
+}
+{  //  new stuff 2004 emptymesh (version 1.40)
+ // -- usefull to build Multiplicator space 
+ //  build a mesh without internal point
+ //   if the adj triangle 
+ //  -----
+  assert(version>=1.40);
+  mesh Th=square(10,10);
+  int[int] ssd(Th.nt);
+  fespace Ph(Th,P0);
+   Ph sd;
+  for(int i=0;i<ssd.n;i++)
+   {  int iq=i/2;   // because 2 traingle per quad 
+      int ix=iq%10;
+      int iy=iq/10;  
+    ssd[i]= 1 + (ix>=5) +  (iy>=5)*2;
+    sd[][i]=ssd[i];
+   }
+  plot(sd,fill=1,wait=1);
+  Th=emptymesh(Th,ssd);
+  plot(Th,wait=1,ps="emptymesh-2.eps");
+  savemesh(Th,"emptymesh-2.msh");
+}
+
+  // ------------------------------------------------------------
+{  // get mesh information (version 1.37)
+  mesh Th=square(2,2);
+  // get data of the mesh 
+  int nbtriangles=Th.nt;
+  cout << " nb of Triangles = " << nbtriangles << endl;
+  for (int i=0;i<nbtriangles;i++)
+    for (int j=0; j <3; j++)
+      cout << i << " " << j << " Th[i][j] = "
+	   << Th[i][j] << "  x = "<< Th[i][j].x  << " , y= "<< Th[i][j].y 
+	   << ",  label=" << Th[i][j].label << endl;
+	    
+//   Th(i)   return   the vextex i of Th
+//   Th[k]   return   the triangle k of Th.
+//   Th.be(i)  return  the boundary element 
+  fespace femp1(Th,P1);
+  femp1 Thx=x,Thy=y; 
+  // get vertices information : 
+  int nbvertices=Th.nv;
+  cout << " nb of vertices = " << nbvertices << endl;
+  for (int i=0;i<nbvertices;i++)
+	cout << "Th(" <<i  << ") : "   // << endl;	
+	     << Th(i).x << " " << Th(i).y  << " " << Th(i).label // version 2.19 
+	     << "       old method: " << Thx[][i] << " " << Thy[][i] << endl;
+
+// method to find information of point (0.55,0.6) 
+  int it00 = Th(0.55,0.6).nuTriangle;// then triangle numbe 
+  int nr00 = Th(0.55,0.6).region;
+  
+  real area00 = Th[it00].area; // new in version 2.19 
+  real nrr00 = Th[it00].region; // new in version 2.19 
+  real nll00 = Th[it00].label; // same as region in this case.
+      
+ //Hack  to get a triangle contening point x,y
+  //     or   region number
+  // -----------------------------------------
+  fespace femp0(Th,P0);
+  femp0 nuT; // a P0 function  to get triangle numbering
+    for (int i=0;i<Th.nt;i++)
+     nuT[][i]=i; 
+  femp0 nuReg=region; // a P0 function to get the region number
+  //  inquire 
+  int it0=nuT(0.55,0.6); //  number of triangle Th's contening point (0.55,0,6);
+  int nr0=nuReg(0.55,0.6); //  number of region of Th mesh contening point (0.55,0,6);
+  // dump  
+  cout << "  point (0.55,0,6) :triangle number " << it00 << " " << it00 
+       << ", region = " << nr0 << " == " << nr00 << ",  area K " << area00 << endl;
+
+  // new method to get boundary inforamtion 
+ 
+  // version >3.4-1
+  // --------- new stuff -----------------
+  int k=0,l=1,e=1;
+  Th.nbe ; // return the number of boundary element \hfilll
+  Th.be(k);   // return the boundary element k $\in \{0,...,Th.nbe-1\}$ \hfilll
+  Th.be(k)[l];   // return the vertices l $\in \{0,1\}$ of  boundary element k \hfilll
+  Th.be(k).Element ;   // return the triangle contening the  boundary element k \hfilll
+  Th.be(k).whoinElement ;   // return the egde number of triangle contening the  boundary element k \hfilll
+  Th[k].adj(e) ; // return adjacent triangle to k by edge e, and change the value of e to \hfilll
+  // the corresponding edge in the adjacent triangle
+  Th[k] == Th[k].adj(e) ;// non adjacent triangle return the same 
+  Th[k] != Th[k].adj(e) ;// true adjacent triangle 
+  
+  cout << " print mesh connectivity " << endl;
+  int nbelement = Th.nt; 
+  for (int k=0;k<nbelement;++k)
+    cout << k << " :  " << int(Th[k][0]) << " " << int(Th[k][1]) << " " <<  int(Th[k][2])
+	 << " , label  " << Th[k].label << endl; 
+  //  
+  
+  for (int k=0;k<nbelement;++k)
+    for (int e=0,ee;e<3;++e) 
+      //  remark FH hack:  set ee to e, and ee is change by method adj, 
+      //  in () to make difference with  named parameters. 
+      {
+	    cout << k <<  " " << e << " <=>  " << int(Th[k].adj((ee=e))) << " " << ee  
+	     << "  adj: " << ( Th[k].adj((ee=e)) != Th[k]) << endl;  
+      }
+      // note :     if k == int(Th[k].adj(ee=e)) not adjacent element 
+
+
+  int nbboundaryelement = Th.nbe; 
+  Th.be;
+    for (int k=0;k<nbboundaryelement;++k)
+      cout << k << " : " <<  Th.be(k)[0] << " " << Th.be(k)[1] << " , label " << Th.be(k).label 
+	   <<  " tria  " << int(Th.be(k).Element) << " " << Th.be(k).whoinElement <<  endl; 
+
+regtest=Th.nv;
+}
+//   test to catch bogus boundary ( just a test)
+{
+int err;
+real c0,c1;
+c0=0;
+c1=0;
+mesh Th;
+for( int i=0;i<=4;i++)
+{
+    c1=sin(i*pi/8);
+try 
+{
+err=0; 
+border a(t=0,2*pi){ x=cos(t); y=sin(t);label=1;}
+border b(t=0,2*pi){ x=c0+0.3*cos(t); y=c1+0.3*sin(t);label=2;}
+plot(a(50)+b(30),wait=1);
+Th   = buildmesh(a(50)+b(30));
+}
+catch(...)
+{
+  err=1;
+  plot(a(50)+b(30),wait=1,cmm="bogus border ",ps="bogusborder.eps");  
+}
+if(err==0)
+  plot(Th,wait=1,cmm="mesh ok");
+}
+}
+// in test ... 
+{ 
+// multy border syntax version 3.30 avril 2014 ... 
+  real[int] xx=[0,1,1,0],
+            yy=[0,0,1,1];
+  // radius, centre of the 4 circles .. 
+  real[int] RC=[ 0.1, 0.05, 0.05, 0.1],
+            XC= [0.2,0.8,0.2,0.8],
+            YC= [0.2,0.8,0.8,0.2];
+  int[int]  NC=[-10,-11,-12,13]; //list number of $\pm$ segments
+  // of the 4 circles borders  
+
+  border bb(t=0,1;i) 
+  {
+  // i is the the index variable of the multi border loop 
+    int ii = (i+1)%4; real t1 = 1-t;
+    x =  xx[i]*t1 + xx[ii]*t;
+    y =  yy[i]*t1 + yy[ii]*t;
+    label = 0; ; 
+  }
+  
+  border cc(t=0,2*pi;i) 
+ {
+    x = RC[i]*cos(t)+XC[i];
+    y = RC[i]*sin(t)+YC[i];
+    label = i+1; 
+  }
+  int[int] nn=[4,4,5,7];// 4 border , with 4,4,5,7 segment respectively . 
+  plot(bb(nn),cc(NC),wait=1);
+  mesh th= buildmesh(bb(nn)+cc(NC)) ; 
+  plot(th,wait=1,ps="multy-border.eps"); 
+}
diff --git a/examples++-tutorial/mortar-DN-4.edp b/examples++-tutorial/mortar-DN-4.edp
new file mode 100644
index 0000000..8916c95
--- /dev/null
+++ b/examples++-tutorial/mortar-DN-4.edp
@@ -0,0 +1,230 @@
+assert(version>=2.23);
+//  Mortar  (4 sub domain) 
+//  with matrix -et Precon Conjugade Gradient --
+//    Neuman -> Dirichlet . 
+//  -------------------------------
+
+func f=1+x+y;
+real g=1; 
+int withprecon=1; 
+macro Grad(u) [ dx(u), dy(u) ] //
+int nbsd=4;
+
+macro Psd(U) U[0],U[1],U[2],U[3] //
+int labext= nbsd+1;
+real meshsize=0.025; 
+real meshsizem=meshsize*1.5; 
+bool noconforme=0;
+include "mortar-msh.idp"
+cout << "mortar : " << endl;
+mesh Thm=Tha;
+Thm=adaptmesh(Thm,meshsizem,IsMetric=1,thetamax=60,nbvx=100000);
+Thm=adaptmesh(Thm,meshsizem,IsMetric=1,thetamax=60,nbvx=1000000);
+
+Thm=emptymesh(Thm);
+mesh Thmm=Thm;
+if(noconforme)
+  {  //  need a find mesh to integrate on Thm. 
+    Thmm=trunc(Thm,split=4,1); // for fine integration
+    Thmm=emptymesh(Thmm);
+  }
+plot(Thm,wait=0);
+
+verbosity=1;
+
+
+mesh[int] Thsd(nbsd);
+
+for(int sd=0;sd<nbsd;++sd)
+ Thsd[sd]=trunc(Tha,region==regi[sd],split=1);// les sous domaines
+
+if(noconforme)
+{
+for(int sd=0;sd<nbsd;++sd)
+ Thsd[sd]=adaptmesh(Thsd[sd],meshsize*(1+sd*0.05),IsMetric=1,nbvx=100000,thetamax=60);// les sous domaines
+
+}
+plot(Thsd,Thm);
+// a faire : plot(Thsd,Thm,wait=1); 
+
+fespace Lh(Thm,P1);
+fespace RTh(Thm,[P0edge,P0edge]);
+ RTh [Nmx,Nmy]; // ne marche pas car la normal 
+//                             n'est definie que une un bord
+varf  vNN([ux,uy],[nx,ny]) = int1d(Thm,1)(( nx*N.x + ny*N.y)/lenEdge);
+Nmx[]= vNN(0,RTh);
+
+// les joint P0 sur le squelette 
+// -----   \int [q] l + \int[p] m 
+Lh  lh=0,rhsl=0;
+
+mesh Thi=Thsd[0];
+
+// remark: operator # is  the concatenation operator in macro 
+
+//   cout << " Domaine " << i<< " --------" << endl;
+fespace Vhi(Thi,P1);
+fespace Ehi(Thi,P0edge);
+matrix[int] Asd(nbsd),Csd(nbsd),PAsd(nbsd),PIsd(nbsd),PJsd(nbsd);
+Vhi[int] usd(nbsd),vsd(nbsd),rhssd(nbsd), pusd(nbsd),bcsd(nbsd);
+Ehi[int] epssd(nbsd);
+   
+real tgv=1e30;
+for(int sd=0;sd<nbsd;++sd)
+{
+
+  varf cci([l],[u]) = int1d(Thmm,1,qforder=3)(l*u*epssd[sd]);
+  varf vepsi(u,v)= int1d(Thi,1,qforder=10)( (Nmx*N.x + Nmy*N.y)*v/lenEdge);
+  
+  varf vLapMi([ui],[vi],tgv=tgv) =
+         int2d(Thi)(  Grad(ui)'*Grad(vi)  )
+      // + int1d(Thi,1,qfe=qf1pElump)(alpha*ui*vi)
+    +  int2d(Thi) (f*vi)   +  on(labext,ui=g);  
+    
+  varf vPLapMi([ui],[vi],tgv=tgv) =
+        int2d(Thi)(  Grad(ui)'*Grad(vi)  )
+     // + int1d(Thi,1,qfe=qf1pElump)(alphap*ui*vi)
+      + on(labext,1,ui=0);
+   ;  
+
+   varf  vrhsMi(ui,vi) =   on(labext,ui=g);
+
+   Thi=Thsd[sd];
+   usd[sd]=0;
+   vsd[sd]=0;
+   epssd[sd][]= vepsi(0,Ehi);
+   epssd[sd] = -real(epssd[sd] <-0.00001) + real(epssd[sd] >0.00001);
+   
+   Csd[sd]  = cci(Lh,Vhi);
+   Asd[sd]  = vLapMi(Vhi,Vhi,solver=UMFPACK);
+   PAsd[sd] = vPLapMi(Vhi,Vhi,solver=UMFPACK);
+   matrix IVL=interpolate(Vhi,Lh,inside=1);
+   //   v = IVL*l 
+   varf vonext(u,v)=on(labext,u=1);
+   varf von1(u,v)=on(1,u=1);
+   real[int]  onext=vonext(0,Vhi);
+   real[int]  on1=von1(0,Vhi);
+   on1= on1 ? 1 : 0;
+   on1 = onext ? 0 : on1; //  remove df of ext
+   matrix I1(on1);//   matrix    tgv $i\in Gamma_1 \ Gamma_e $ , 0 otherwise
+   
+   PIsd[sd]=  I1*IVL;//  remove of line not on $Gamma_1 \ Gamma_e $
+ 
+    // so PIsd[sd]*l  =  tgv * Interpole l on $Gamma_1 \ Gamma_e $
+   I1.diag=on1;
+   matrix AA=I1*Asd[sd];//  remove line not on lab 1 
+   PJsd[sd]= IVL'*AA;
+   
+   
+   rhssd[sd][]=vLapMi(0,Vhi);
+
+}
+
+plot(epssd,cmm="eps 0,1,2,3",wait=0,value=1);
+
+
+lh[]=0;
+varf  vDD(u,v) = int2d(Thm)(u*v*1e-10);
+varf  vML(u,v) = int2d(Thm)(u*v*1e-10)+int1d(Thm,1)(u*v);
+matrix ML=vML(Lh,Lh);
+
+
+
+
+matrix DD=vDD(Lh,Lh);
+
+matrix M=[ 
+  [ Asd[0] ,0      ,0      ,0      ,Csd[0] ],
+  [ 0      ,Asd[1] ,0      ,0      ,Csd[1] ],
+  [ 0      ,0      ,Asd[2] ,0      ,Csd[2] ],
+  [ 0      ,0      ,0      ,Asd[3] ,Csd[3] ],
+  [ Csd[0]',Csd[1]',Csd[2]',Csd[3]',DD     ] 
+ ];
+
+real[int] xx(M.n);
+
+real[int] bb =[rhssd[0][], rhssd[1][],rhssd[2][],rhssd[3][],rhsl[] ];
+set(M,solver=UMFPACK);
+
+xx = M^-1 * bb;
+
+[usd[0][],usd[1][],usd[2][],usd[3][],lh[]] = xx; // dispatch the solution 
+
+plot(usd,cmm="u1,u2,u3,u4",wait=1); 
+
+
+int itera=0;
+
+varf  vbc(u,v) =   int1d(Thm,labext)(v);
+real[int] lbc(Lh.ndof),lbc0(Lh.ndof);
+lbc=vbc(0,Lh);
+lbc = lbc ? 0 : 1 ; 
+
+func real[int] SkPb(real[int] &l)
+{ 
+   int verb=verbosity;   verbosity=0;   itera++;
+   for(int sd=0;sd<nbsd;++sd)
+    {
+      Thi=Thsd[sd];  //  for initialisation of vsd with the correct size 
+      vsd[sd][]  = rhssd[sd][];
+      vsd[sd][] += Csd[sd]* l;
+      usd[sd][]  = Asd[sd]^-1*vsd[sd][];
+
+    }
+    l=0;
+   for(int sd=0;sd<nbsd;++sd)
+     	l  += Csd[sd]'*usd[sd][];  
+     	
+    l= lbc .* l; 
+    plot(usd,wait=0,cmm="CG iteration u");
+   verbosity=verb; 
+   return l ;
+};
+
+func real[int] PSkPb(real[int] &l)
+{ 
+  if(withprecon)
+  {  	
+   int verb=verbosity;   verbosity=0;   itera++;
+   real[int] ll= ML^-1*l;
+   ll= lbc .* ll; 
+   ll *= tgv;
+ 
+   for(int sd=0;sd<nbsd;++sd)
+    {
+      Thi=Thsd[sd];              
+      pusd[sd][] = PAsd[sd]^-1*(vsd[sd][]= PIsd[sd]* ll);
+    }
+    ll=0;
+   for(int sd=0;sd<nbsd;++sd)
+     ll  += PJsd[sd]*pusd[sd][];  
+    l = ML^-1*ll; 	
+    l= lbc .* l; 
+   verbosity=verb; 
+  }
+  return l ;
+};
+
+
+verbosity=100;
+lh[]=0;
+LinearCG(SkPb,lh[],eps=1.e-7,nbiter=100,precon=PSkPb);
+verbosity=1; 
+
+plot(usd,wait=1,cmm="CG");
+
+// FFCS: for regression tests
+real regtest;
+{  
+fespace Vha(Tha,P1);
+Vha vah,uah;
+solve vLapMM([uah],[vah]) =
+       int2d(Tha)(  Grad(uah)'*Grad(vah) )
+    -  int2d(Tha) (f*vah)
+    +  on(labext,uah=g)
+   ;
+verbosity =3;
+plot(uah,usd,cmm="uah",wait=1); 
+regtest=uah[]'*uah[];
+}
+
diff --git a/examples++-tutorial/mortar-msh.idp b/examples++-tutorial/mortar-msh.idp
new file mode 100644
index 0000000..8572f93
--- /dev/null
+++ b/examples++-tutorial/mortar-msh.idp
@@ -0,0 +1,42 @@
+// --- begin  meshes  building --------------
+real[int] theta(nbsd+1),cost(nbsd),sint(nbsd);
+
+for (int i=0;i<nbsd;i++)
+ {
+  real t=i*2*pi/nbsd;
+  theta[i]= t;
+  theta[i+1]= (i+1)*2*pi/nbsd;
+  cost[i]=cos(t);
+  sint[i]=sin(t);
+ }
+
+
+border g1(t=0,1){x=cost[0]*t;y=sint[0]*t;label=1;};
+border g2(t=0,1){x=cost[1]*t;y=sint[1]*t;label=1;};
+border g3(t=0,1){x=cost[2]*t;y=sint[2]*t;label=1;};
+border g4(t=0,1){x=cost[3]*t;y=sint[3]*t;label=1;};
+
+border e12(t=theta[0],theta[1]){x=cos(t);y=sin(t);label=labext;};
+border e23(t=theta[1],theta[2]){x=cos(t);y=sin(t);label=labext;};
+border e34(t=theta[2],theta[3]){x=cos(t);y=sin(t);label=labext;};
+border e41(t=theta[3],theta[4]){x=cos(t);y=sin(t);label=labext;};
+
+ int Ng = 5;
+ int Ne = 5 ;
+
+plot(g1(Ng)+g2(Ng)+g3(Ng)+g4(Ng) + e12(Ne) + e23(Ne)+ e34(Ne) + e41(Ne) ,wait=1);
+
+mesh Tha = buildmesh( g1(Ng)+g2(Ng)+g3(Ng)+g4(Ng) + e12(Ne) + e23(Ne)+ e34(Ne) + e41(Ne) );
+
+int [int] regi(4);
+for (int i=0;i<4;i++)
+  {
+    real tt = (theta[i]+theta[i+1])*0.5;
+    regi[i]=Tha(0.5*cos(tt),0.5*sin(tt)).region;
+  }
+
+
+Tha=adaptmesh(Tha,meshsize*3,IsMetric=1,thetamax=60,nbvx=100000);
+Tha=adaptmesh(Tha,meshsize*1.5,IsMetric=1,thetamax=60,nbvx=100000);
+Tha=adaptmesh(Tha,meshsize,IsMetric=1,thetamax=60,nbvx=100000);
+
diff --git a/examples++-tutorial/movemesh.edp b/examples++-tutorial/movemesh.edp
new file mode 100644
index 0000000..b2b7b1b
--- /dev/null
+++ b/examples++-tutorial/movemesh.edp
@@ -0,0 +1,27 @@
+// simple movemesh example
+mesh Th=square(10,10);
+fespace Vh(Th,P1); 
+real t=0;
+// ---
+//  problem is how to build data without interpolation
+//  so the data u is moving with the mesh hse you can see in the plot
+// ---
+Vh u=y;
+for (int i=0;i<4;i++)
+{ 
+ t=i*0.1;
+ Vh f= x*t;
+ real minarea=checkmovemesh(Th,[x,y+f]);
+ if (minarea >0 ) //  the movemesh will be ok
+   Th=movemesh(Th,[x,y+f]);
+ cout << " Min area  " << minarea << endl;
+//  u=(Vh,u[]);  // the new syntaxe  FH
+ Vh tmp;     // =u[],  sorry no init of FEspace function with array. 
+ tmp[]=u[];  //save the value  
+ u=0;        // to change the FEspace and mesh  associated to u
+ u[]=tmp[];  // set le value of the array without no mesh update 
+ plot(Th,u,wait=1);
+};
+//  remark, in this programme we have no solution with link to a previous mesh
+// so all the previoux are delete in memory
+//   -------- 
diff --git a/examples++-tutorial/nl-elast-neo-Hookean.edp b/examples++-tutorial/nl-elast-neo-Hookean.edp
new file mode 100644
index 0000000..d782f9b
--- /dev/null
+++ b/examples++-tutorial/nl-elast-neo-Hookean.edp
@@ -0,0 +1,588 @@
+//  See comment on  documentation chapter 9, 
+//   section:  Compressible Neo-Hookean Materials: Computational So- 
+//    lutions
+// -----------  Author  Alex Sadovsky (mail:sashas at gmail.com)
+// ================================================================
+//  non linear elasticity model: a neo-Hookean material of the
+//  Simo-Pister type, with the strain energy density function given
+//  by:
+//
+//  W = (mu / 2) * ( I1 - tr(I1) - 2 ln(J) ), where we have used 
+//  the notation
+//  F = deformation gradient,
+//  J = det(F),
+//  C = F^T F,
+//  I1 = tr(C),
+//  I = the identity tensor of rank 2
+//  For details, see formula (12) in the following paper:
+//  ====================================================================
+//  Horgan, C; Saccomandi, G;
+//  ``Constitutive Models for Compressible Nonlinearly Elastic
+//  Materials with Limiting Chain Extensibility,''
+//   Journal of Elasticity, Volume 77, Number 2, November 2004, pp. 123-138(16)
+//  ====================================================================
+//  For an exposition of nonlinear elasticity, see the book 
+//  "Nonlinear Elastic Deformations" by R. Ogden.  Other good sources 
+//  are A.J.M. Spencer's "Continuum Mechanics" and P. Chadwick's 
+//  book with the same title.  For the FEM formulation, see 
+//  Prof. Alan Bower's course notes, posted at:
+//  http://www.engin.brown.edu/courses/en222/Notes/FEMfinitestrain/FEMfinitestrain.htm
+//  
+//
+//  The domain of the following problem is a circular or 
+//  elliptical disc with a concentric elliptical hole.  Zero
+//  displacements are prescribed on the outer boundary; the 
+//  dead stress load Pa, on the inner boundary.
+
+//  ====================================================================
+
+
+
+//  Macros for the gradient of a vector field (u1, u2)
+macro grad11(u1, u2) (dx(u1)) //
+macro grad21(u1, u2) (dy(u1)) //
+macro grad12(u1, u2) (dx(u2)) //
+macro grad22(u1, u2) (dy(u2)) //
+
+//  Macros for the deformation gradient
+macro F11(u1, u2) (1.0 + grad11(u1,u2)) //
+macro F12(u1, u2) (0.0 + grad12(u1,u2)) //
+macro F21(u1, u2) (0.0 + grad21(u1,u2)) //
+macro F22(u1, u2) (1.0 + grad22(u1,u2)) //
+
+//  Macros for the incremental deformation gradient
+macro dF11(varu1, varu2) (grad11(varu1, varu2)) //
+macro dF12(varu1, varu2) (grad12(varu1, varu2)) //
+macro dF21(varu1, varu2) (grad21(varu1, varu2)) //
+macro dF22(varu1, varu2) (grad22(varu1, varu2)) //
+
+
+//  Macro for the determinant of the deformation gradient
+macro J(u1, u2) (
+F11(u1, u2)*F22(u1, u2) - F12(u1, u2)*F21(u1, u2)
+) //
+
+//  Macros for the inverse of the deformation gradient
+macro Finv11 (u1, u2) (
+F22(u1, u2) / J(u1, u2)
+) //
+macro Finv22 (u1, u2) (
+F11(u1, u2) / J(u1, u2)
+) //
+macro Finv12 (u1, u2) (
+-F12(u1, u2) / J(u1, u2)
+) //
+macro Finv21 (u1, u2) (
+-F21(u1, u2) / J(u1, u2)
+) //
+
+
+//  Macros for the square of the inverse of the deformation gradient
+macro FFinv11 (u1, u2) (
+Finv11(u1, u2)^2 + Finv12(u1, u2)*Finv21(u1, u2)
+) //
+
+macro FFinv12 (u1, u2) (
+Finv12(u1, u2)*(Finv11(u1, u2) + Finv22(u1, u2))
+) //
+
+macro FFinv21 (u1, u2) (
+Finv21(u1, u2)*(Finv11(u1, u2) + Finv22(u1, u2))
+) //
+
+macro FFinv22 (u1, u2) (
+Finv12(u1, u2)*Finv21(u1, u2) + Finv22(u1, u2)^2
+) //
+
+
+//  Macros for the inverse of the transpose of the deformation gradient
+macro FinvT11(u1, u2) (Finv11(u1, u2)) //
+macro FinvT12(u1, u2) (Finv21(u1, u2)) //
+macro FinvT21(u1, u2) (Finv12(u1, u2)) //
+macro FinvT22(u1, u2) (Finv22(u1, u2)) //
+
+
+
+
+//  The left Cauchy-Green strain tensor 
+macro B11(u1, u2)
+(
+F11(u1, u2)^2 + F12(u1, u2)^2
+)//
+
+macro B12(u1, u2)
+(
+F11(u1, u2)*F21(u1, u2) + F12(u1, u2)*F22(u1, u2)
+)//
+
+macro B21(u1, u2)
+(
+F11(u1, u2)*F21(u1, u2) + F12(u1, u2)*F22(u1, u2)
+)//
+
+macro B22(u1, u2)
+(
+F21(u1, u2)^2 + F22(u1, u2)^2
+)//
+
+
+
+//===========================================================================
+//  The macros for the auxiliary tensors (D0, D1, D2, ...): Begin
+
+
+////  The tensor quantity D0 = F_{n} (\delta F_{n+1})^T
+
+
+macro d0Aux11 (u1, u2, varu1, varu2) 
+(
+dF11(varu1, varu2) * F11(u1, u2) + dF12(varu1, varu2) * F12(u1, u2)
+)//
+
+macro d0Aux12 (u1, u2, varu1, varu2) 
+(
+dF21(varu1, varu2) * F11(u1, u2) + dF22(varu1, varu2) * F12(u1, u2)
+)//
+
+macro d0Aux21 (u1, u2, varu1, varu2) 
+(
+dF11(varu1, varu2) * F21(u1, u2) + dF12(varu1, varu2) * F22(u1, u2)
+)//
+
+macro d0Aux22 (u1, u2, varu1, varu2) 
+(
+dF21(varu1, varu2) * F21(u1, u2) + dF22(varu1, varu2) * F22(u1, u2)
+)//
+
+
+
+////  The tensor quantity D1 = D0 + D0^T
+macro d1Aux11 (u1, u2, varu1, varu2) 
+(
+2.0 * d0Aux11 (u1, u2, varu1, varu2) 
+)//
+
+macro d1Aux12 (u1, u2, varu1, varu2) 
+(
+d0Aux12 (u1, u2, varu1, varu2) + d0Aux21 (u1, u2, varu1, varu2) 
+)//
+
+macro d1Aux21 (u1, u2, varu1, varu2) 
+(
+d1Aux12 (u1, u2, varu1, varu2) 
+)//
+
+macro d1Aux22 (u1, u2, varu1, varu2) 
+(
+2.0 * d0Aux22 (u1, u2, varu1, varu2) 
+)//
+
+
+////  The tensor quantity D2 = F^{-T}_{n} dF_{n+1}
+macro d2Aux11 (u1, u2, varu1, varu2) 
+(
+dF11(varu1, varu2) * FinvT11(u1, u2) + dF21(varu1, varu2) * FinvT12(u1, u2)
+)//
+
+macro d2Aux12 (u1, u2, varu1, varu2) 
+(
+dF12(varu1, varu2) * FinvT11(u1, u2) + dF22(varu1, varu2) * FinvT12(u1, u2)
+)//
+
+macro d2Aux21 (u1, u2, varu1, varu2) 
+(
+dF11(varu1, varu2) * FinvT21(u1, u2) + dF21(varu1, varu2) * FinvT22(u1, u2)
+)//
+
+macro d2Aux22 (u1, u2, varu1, varu2) 
+(
+dF12(varu1, varu2) * FinvT21(u1, u2) + dF22(varu1, varu2) * FinvT22(u1, u2)
+)//
+
+
+
+
+
+
+
+////  The tensor quantity D3 = F^{-2}_{n} dF_{n+1}
+macro d3Aux11 (u1, u2, varu1, varu2, w1, w2) 
+(
+dF11(varu1, varu2) *FFinv11(u1, u2) *grad11(w1, w2) + dF21(varu1, varu2) *FFinv12(u1, u2)
+*grad11(w1, w2) 
++ dF11(varu1, varu2) *FFinv21(u1, u2) *grad12(w1, w2) + dF21(varu1, varu2) *FFinv22(u1, u2) *grad12(w1, w2)
+)//
+
+macro d3Aux12 (u1, u2, varu1, varu2, w1, w2) 
+(
+dF12(varu1, varu2) *FFinv11(u1, u2) *grad11(w1, w2) + dF22(varu1, varu2) *FFinv12(u1, u2)
+*grad11(w1, w2) 
++ dF12(varu1, varu2) *FFinv21(u1, u2) *grad12(w1, w2) + dF22(varu1, varu2) *FFinv22(u1, u2) *grad12(w1, w2)
+)//
+
+macro d3Aux21 (u1, u2, varu1, varu2, w1, w2) 
+(
+dF11(varu1, varu2) *FFinv11(u1, u2) *grad21(w1, w2) + dF21(varu1, varu2) *FFinv12(u1, u2)
+*grad21(w1, w2) 
++ dF11(varu1, varu2) *FFinv21(u1, u2) *grad22(w1, w2) + dF21(varu1, varu2) *FFinv22(u1, u2) *grad22(w1, w2)
+)//
+
+macro d3Aux22 (u1, u2, varu1, varu2, w1, w2) 
+(
+dF12(varu1, varu2) *FFinv11(u1, u2) *grad21(w1, w2) + dF22(varu1, varu2) *FFinv12(u1, u2)
+*grad21(w1, w2) 
++ dF12(varu1, varu2) *FFinv21(u1, u2) *grad22(w1, w2) + dF22(varu1, varu2) *FFinv22(u1, u2) *grad22(w1, w2)
+)//
+
+
+
+
+
+
+
+
+
+////  The tensor quantity D4 = (grad w) * Finv
+macro d4Aux11 (w1, w2, u1, u2) 
+(
+Finv11(u1, u2)*grad11(w1, w2) + Finv21(u1, u2)*grad12(w1, w2)
+)//
+
+macro d4Aux12 (w1, w2, u1, u2) 
+(
+Finv12(u1, u2)*grad11(w1, w2) + Finv22(u1, u2)*grad12(w1, w2)
+)//
+
+macro d4Aux21 (w1, w2, u1, u2) 
+(
+Finv11(u1, u2)*grad21(w1, w2) + Finv21(u1, u2)*grad22(w1, w2)
+)//
+
+macro d4Aux22 (w1, w2, u1, u2) 
+(
+Finv12(u1, u2)*grad21(w1, w2) + Finv22(u1, u2)*grad22(w1, w2)
+)//
+
+
+
+//  The macros for the auxiliary tensors (D0, D1, D2, ...): End
+//----------------------------------------------------------------------------
+
+//===========================================================================
+//  The macros for the various stress measures: BEGIN
+
+//  The Kirchhoff stress tensor
+macro StressK11(u1, u2)
+(
+mu * (B11(u1, u2) - 1.0)
+)//
+
+//  The Kirchhoff stress tensor
+macro StressK12(u1, u2)
+(
+mu * B12(u1, u2) 
+)//
+
+//  The Kirchhoff stress tensor
+macro StressK21(u1, u2)
+(
+mu * B21(u1, u2) 
+)//
+
+//  The Kirchhoff stress tensor
+macro StressK22(u1, u2)
+(
+mu * (B22(u1, u2) - 1.0)
+)//
+
+
+
+//  The tangent Kirchhoff stress tensor
+macro TanK11(u1, u2, varu1, varu2)
+(
+mu * d1Aux11(u1, u2, varu1, varu2) 
+)//
+
+macro TanK12(u1, u2, varu1, varu2)
+(
+mu * d1Aux12(u1, u2, varu1, varu2) 
+)//
+
+macro TanK21(u1, u2, varu1, varu2)
+(
+mu * d1Aux21(u1, u2, varu1, varu2) 
+)//
+
+macro TanK22(u1, u2, varu1, varu2)
+(
+mu * d1Aux22(u1, u2, varu1, varu2) 
+)//
+
+
+
+//  The macros for the stress tensor components: END
+//----------------------------------------------------------------------------
+
+
+
+// END OF MACROS
+// ----------------------------------------------------------------------------
+
+
+
+
+
+// ************************************************
+// THE (BIO)MECHANICAL PARAMETERS: Begin
+
+//  Elastic coefficients
+real mu = 5.e2; //  kg/cm^2
+
+real D = 1.e3; //  (1 / compressibility)
+
+//  Stress loads
+real Pa = -3.e2;
+
+
+// THE (BIO)MECHANICAL PARAMETERS: End
+// ************************************************
+
+
+// ************************************************
+// THE COMPUTATIONAL PARAMETERS: Begin
+
+//  The wound radius
+real InnerRadius = 1.e0;
+
+//  The outer (truncated) radius
+real OuterRadius = 4.e0;
+
+//  Tolerance (L^2)
+real tol = 1.e-4;
+
+//  Extension of the inner ellipse ((major axis) - (minor axis))
+real InnerEllipseExtension = 1.e0;
+
+// THE COMPUTATIONAL PARAMETERS: End
+// ************************************************
+
+
+int m = 40, n = 20;
+
+border InnerEdge(t = 0, 2.0*pi) {x = (1.0 + InnerEllipseExtension) * InnerRadius * cos(t); y = InnerRadius * sin(t); label = 1;}
+
+border OuterEdge(t = 0, 2.0*pi) {x = (1.0 + 0.0 * InnerEllipseExtension) * OuterRadius * cos(t); y = OuterRadius * sin(t); label = 2;}
+
+mesh Th = buildmesh(InnerEdge(-m) + OuterEdge(n));
+
+int bottom=1, right=2,upper=3,left=4;
+
+plot(Th);
+
+fespace Wh(Th,P1dc);
+fespace Vh(Th,[P1,P1]);
+fespace Sh(Th,P1);
+
+
+Vh [w1, w2], [u1n,u2n], [varu1, varu2];
+
+varf vfMass1D(p,q) = int2d(Th)(p*q);
+matrix Mass1D = vfMass1D(Sh,Sh,solver=CG);
+
+Sh p, ppp;
+
+p[] = 1;
+ppp[] = Mass1D * p[];
+
+real DomainMass = ppp[].sum;
+
+cout << "****************************************" << endl;
+cout << "DomainMass = " << DomainMass << endl;
+cout << "****************************************" << endl;
+
+varf vmass([u1,u2],[v1,v2],solver=CG) 
+=  int2d(Th)( (u1*v1 + u2*v2) / DomainMass );
+
+matrix Mass = vmass(Vh,Vh);
+
+matrix Id = vmass(Vh,Vh);
+
+
+//  Define the standard Euclidean basis functions
+Vh [ehat1x, ehat1y], [ehat2x, ehat2y]; 
+[ehat1x, ehat1y] = [1.0, 0.0];
+[ehat2x, ehat2y] = [0.0, 1.0]; 
+
+
+// The individual elements of the total 1st Piola-Kirchoff stress
+Vh [auxVec1, auxVec2];
+
+// Sh Stress1PK11, Stress1PK12, Stress1PK21, Stress1PK22;
+
+Sh StrK11, StrK12, StrK21, StrK22;
+
+Vh [ef1, ef2];
+
+
+real ContParam, dContParam;
+
+
+problem 
+neoHookeanInc
+([varu1, varu2], [w1, w2], solver = LU)=
+
+int2d(Th, qforder=1)
+( // BILINEAR part
+
+-(
+  StressK11 (u1n, u2n) * d3Aux11(u1n, u2n, varu1, varu2, w1, w2) 
++ StressK12 (u1n, u2n) * d3Aux12(u1n, u2n, varu1, varu2, w1, w2) 
++ StressK21 (u1n, u2n) * d3Aux21(u1n, u2n, varu1, varu2, w1, w2) 
++ StressK22 (u1n, u2n) * d3Aux22(u1n, u2n, varu1, varu2, w1, w2) 
+)
+
++ TanK11 (u1n, u2n, varu1, varu2) * d4Aux11(w1, w2, u1n, u2n) 
++ TanK12 (u1n, u2n, varu1, varu2) * d4Aux12(w1, w2, u1n, u2n)
++ TanK21 (u1n, u2n, varu1, varu2) * d4Aux21(w1, w2, u1n, u2n) 
++ TanK22 (u1n, u2n, varu1, varu2) * d4Aux22(w1, w2, u1n, u2n) 
+
+)
+
++
+
+ int2d(Th, qforder=1)
+( // LINEAR part
+
+  StressK11 (u1n, u2n) * d4Aux11(w1, w2, u1n, u2n) 
++ StressK12 (u1n, u2n) * d4Aux12(w1, w2, u1n, u2n) 
++ StressK21 (u1n, u2n) * d4Aux21(w1, w2, u1n, u2n) 
++ StressK22 (u1n, u2n) * d4Aux22(w1, w2, u1n, u2n) 
+
+
+)
+
+//  Choose one of the following two boundary conditions involving Pa:
+
+// Load vectors normal to the boundary:
+ - int1d(Th,1)( Pa * (w1*N.x + w2*N.y) ) 
+
+//  Load vectors tangential to the boundary:
+// - int1d(Th,1)( Pa * (w1*N.y - w2*N.x) ) 
+
+   + on(2, varu1 = 0, varu2 = 0);
+;
+
+
+
+// The Lagrange-Green strain tensor,  E = (1/2)(C - I)
+// Wh E111, E12, E121, E12;
+
+
+//  Auxiliary variables
+matrix auxMat;
+
+
+// Newton's method
+// ---------------
+Sh u1,u2;
+
+
+ContParam = 0.0;
+dContParam = 0.01;
+
+//  Initialization:
+[varu1,varu2] = [0.0, 0.0]; 
+
+[u1n, u2n] = [0.0, 0.0];
+
+real res = 2.0 * tol;
+
+real eforceres;
+
+int loopcount = 0;
+int loopmax = 45;
+
+//  Iteration:
+while (loopcount <= loopmax && res >= tol) 
+{
+  loopcount ++;
+
+  ////////////////////////////////////////////////////////////
+
+  cout << "Loop " << loopcount << endl;
+
+//  plot([u1n,u2n], wait=0, cmm="displacement:" );
+
+/*
+  cout << "TESTING: Begin" << endl;
+  cout << "dFStress2PK11 = " << dFStress2PK11 (u1n, u2n, varu1, varu2) << endl; 
+  cout << "TESTING: End" << endl;
+
+  cout << "B11 = " << B11(u1n, u2n) << endl;
+  cout << "B12 = " << B12(u1n, u2n) << endl;
+  cout << "B21 = " << B21(u1n, u2n) << endl;
+  cout << "B22 = " << B22(u1n, u2n) << endl << endl;
+
+  cout << "J = " << J(u1n, u2n) << endl << endl;
+
+  StrK11 = StressK11(u1n, u2n);
+  StrK12 = StressK12(u1n, u2n);  
+  StrK21 = StressK21(u1n, u2n);
+  StrK22 = StressK22(u1n, u2n);
+
+  cout << "StressK11 = " << StrK11 << endl;
+  cout << "StressK12 = " << StrK12 << endl;
+  cout << "StressK21 = " << StrK21 << endl;
+  cout << "StressK22 = " << StrK22 << endl;
+*/
+
+  neoHookeanInc;  //  compute [varu1,varu2] = (D^2 J(u1n))^{-1}(D  J(u1n))
+
+//  cout << "This marker reached" << endl;
+
+
+  u1 = varu1;
+  u2 = varu2;
+    
+  w1[]   = Mass*varu1[];
+
+  res = sqrt(w1[]' * varu1[]); //  norme  L^2 of [varu1, varu2]
+
+//  cout << " u1 min =" <<u1[].min << ", u1 max= " << u1[].max << endl;
+//  cout << " u2 min =" << u2[].min << ", u2 max= " << u2[].max << endl;
+
+//  plot([varu1, varu2], wait=1, cmm=" varu1, varu2 " );
+
+  u1n[] += varu1[]; 
+
+  cout << " L^2 residual = " << res << endl;
+
+  plot([u1n,u2n], wait=0, cmm="displacement:" );
+
+//  Calculate the elastic force residue
+  
+
+
+/*
+  if (res < tol)
+  {
+	loopcount = 1;
+	res = 1.0 + tol;
+	ContParam += dContParam;
+	cout << "ContParam = " << ContParam << endl;
+  } 
+*/
+
+}
+
+// plot([u1n,u2n], wait=1, cmm="displacement:" );
+
+// plot([u1n,u2n],wait=1);
+
+plot(Th, wait=2, ps="ref-config.eps");
+
+mesh Th1 = movemesh(Th, [x+u1n, y+u2n]);
+
+plot(Th1, wait=2, ps="def-config-neo-Hookean.eps");
+
+plot([u1n,u2n], wait=0, ps="displacement-neo-Hookean.eps" );
\ No newline at end of file
diff --git a/examples++-tutorial/nolinear-elas.edp b/examples++-tutorial/nolinear-elas.edp
new file mode 100644
index 0000000..6e0539d
--- /dev/null
+++ b/examples++-tutorial/nolinear-elas.edp
@@ -0,0 +1,143 @@
+//  non linear elasticity model 
+//   
+//  -------------------------------
+//  with huge utilisation of  macro  new version
+// more simple 
+// ---------------------------
+//   optimize version 
+// ------------
+//  problem is  find $(uu,vn)$  minimizing  $J$
+//  $ min J(un,vn) = \int f(F2) -  int Pa * un $
+//   $ dJ(u,u,uu,vv) = int dF2(u,v,uu,vv) df(F2(u,v)) $
+//   where $F2 =  (^t {E}  A {E} ) $,
+//   $E(U) =  1/2 (\nabla U + \nabla U^t + \nabla U^t  \nabla U) $
+//         ($u_1$)
+//  with U=(   )
+//         ($u_2$)
+// so: 
+//$$ E_ij = 0.5 ( d_i u_j + d_j u_i ) + \sum_k d_i u_k * d_j*u_k  \leqno(1)$$
+//  the symetric tensor $t_{ij}$ are a vector  [t11,2*t12,t22] 
+macro EL(u,v) [dx(u),(dx(v)+dy(u)),dy(v)] // is $[\epsilon_{11},2\epsilon_{12},\epsilon_{22}]$
+
+macro ENL(u,v) [ 
+(dx(u)*dx(u)+dx(v)*dx(v))*0.5,
+(dx(u)*dy(u)+dx(v)*dy(v))    ,
+(dy(u)*dy(u)+dy(v)*dy(v))*0.5 ] // EOM ENL 
+
+macro dENL(u,v,uu,vv) [(dx(u)*dx(uu)+dx(v)*dx(vv)),
+ (dx(u)*dy(uu)+dx(v)*dy(vv)+dx(uu)*dy(u)+dx(vv)*dy(v)),
+ (dy(u)*dy(uu)+dy(v)*dy(vv)) ] // 
+ 
+ 
+macro E(u,v) (EL(u,v)+ENL(u,v)) // is $[\E{11},\sqrt2\E{12},\E{22}]
+macro dE(u,v,uu,vv) (EL(uu,vv)+dENL(u,v,uu,vv)) //
+macro ddE(u,v,uu,vv,uuu,vvv) dENL(uuu,vvv,uu,vv) //
+macro F2(u,v) (E(u,v)'*A*E(u,v)) // 
+macro dF2(u,v,uu,vv)  (E(u,v)'*A*dE(u,v,uu,vv)*2. ) //
+macro ddF2(u,v,uu,vv,uuu,vvv) (
+            (dE(u,v,uu,vv)'*A*dE(u,v,uuu,vvv))*2. 
+          + (E(u,v)'*A*ddE(u,v,uu,vv,uuu,vvv))*2.  )// EOM
+
+//  for hyper elasticity problem 
+//  -----------------------------
+macro f(u) (u) // end of macro
+macro df(u) (1) // end of macro
+macro ddf(u) (0) // end of macro
+
+//  -- du caouchouc --- CF cours de Herve Le Dret.
+// -------------------------------
+real mu = 0.012e5; //  kg/cm^2
+real lambda =  0.4e5; //  kg/cm^2
+//  
+//   $  \sigma = 2 \mu E + \lambda tr(E) Id $
+//   $   A(u,v)= \sigma(u):\E(v) $
+//   
+//   ( a b )
+//   ( b c )
+//
+//  tr*Id : (a,b,c) -> (a+c,0,a+c) 
+// so the associed matrix is:
+//   ( 1 0 1 )
+//   ( 0 0 0 )
+//   ( 1 0 1 ) 
+// ------------------
+real a11= 2*mu +  lambda  ;
+real a22= mu ; //  because [0,2*t12,0]' A [0,2*s12,0]  = 2*mu*(t12*s12+t21*s21) = 4*mu*t12*s12
+real a33= 2*mu +   lambda ;
+real a12= 0 ;
+real a13= lambda ;
+real a23= 0 ;
+//  symetric part
+real a21= a12 ;
+real a31= a13 ;
+real a32= a23 ;
+func A = [ [ a11,a12,a13],[ a21,a22,a23],[ a31,a32,a33] ];  
+
+real Pa=1e2; //  a pressure of 100 Pa
+// ----------------
+
+int n=30,m=10;
+mesh Th= square(n,m,[x,.3*y]); // label: 1 bottom, 2 right, 3 up, 4 left;
+int bottom=1, right=2,upper=3,left=4;
+
+plot(Th);
+
+
+ 
+fespace Wh(Th,P1dc);
+fespace Vh(Th,[P1,P1]);
+fespace Sh(Th,P1);
+
+
+
+
+
+Wh e2,fe2,dfe2,ddfe2; // optimisation 
+Wh ett,ezz,err,erz; // optimisation 
+
+Vh [uu,vv], [w,s],[un,vn];
+[un,vn]=[0,0];//  intialisation 
+[uu,vv]=[0,0];
+
+varf vmass([uu,vv],[w,s],solver=CG) =  int2d(Th)( uu*w + vv*s );
+matrix M=vmass(Vh,Vh);
+problem NonLin([uu,vv],[w,s],solver=LU)=
+ int2d(Th,qforder=1)( // (D^2 J(un)) part
+                       dF2(un,vn,uu,vv)*dF2(un,vn,w,s)*ddfe2
+                    +  ddF2(un,vn,w,s,uu,vv)*dfe2        
+	            )
+   - int1d(Th,3)(Pa*s) 
+   - int2d(Th,qforder=1)( // (D J(un)) part
+           dF2(un,vn,w,s)*dfe2   ) 
+   + on(right,left,uu=0,vv=0);
+;
+// Newton's method
+// ---------------
+Sh u1,v1;
+for (int i=0;i<10;i++)
+{
+  cout << "Loop " << i << endl;
+  e2 = F2(un,vn);
+  dfe2 = df(e2) ;
+  ddfe2 = ddf(e2);
+  cout << "  e2 max " <<e2[].max << " , min" << e2[].min << endl;
+  cout << " de2 max "<< dfe2[].max << " , min" << dfe2[].min << endl;
+  cout << "dde2 max "<< ddfe2[].max << " , min" << ddfe2[].min << endl;
+  NonLin; //  compute [uu,vv] = (D^2 J(un))^{-1}(D J(un))
+  
+  w[]   = M*uu[];
+  real res = sqrt(w[]' * uu[]); //  norme  L^2 of [uu,vv]
+  u1 = uu;
+  v1 = vv;
+  cout << " L^2 residual = " << res << endl;
+  cout << " u1 min =" <<u1[].min << ", u1 max= " << u1[].max << endl;
+  cout << " v1 min =" <<v1[].min << ", v2 max= " << v1[].max << endl;
+  plot([uu,vv],wait=1,cmm=" uu, vv " );
+  un[] -= uu[]; 
+  plot([un,vn],wait=1,cmm=" deplacement " );
+  if (res<1e-5) break;
+}
+
+plot([un,vn],wait=1);
+mesh th1 = movemesh(Th, [x+un, y+vn]);
+plot(th1,wait=1,ps="nl-elas.eps");
diff --git a/examples++-tutorial/onde.edp b/examples++-tutorial/onde.edp
new file mode 100644
index 0000000..c228a69
--- /dev/null
+++ b/examples++-tutorial/onde.edp
@@ -0,0 +1,34 @@
+int i, N=20;
+mesh Th=square(N,N);
+fespace RTh(Th,RT0);
+fespace P0h(Th,P0);
+fespace P1h(Th,P1);
+
+RTh [Vx,Vy],[vx,vy];
+P0h up,u,um;
+
+real dt=0.125/N, pi=4*atan(1.0);
+[Vx,Vy]=[0,0];
+um= sin(pi*x)*sin(pi*y);
+u=um;
+
+problem prob(Vx,Vy,vx,vy,solver=Cholesky,init=i)
+    = int2d(Th) (Vx*vx+Vy*vy) + int2d(Th)(up*(dx(vx)+dy(vy)))
+//     + on(1,2,3,4,Vx=pi*cos(pi*x)*sin(pi*y)*cos(i*dt*pi*sqrt(2.))
+//                 ,Vy=pi*sin(pi*x)*cos(pi*y)*cos(i*dt*pi*sqrt(2.)) )
+;
+for (i=0;i<20;i++)
+ {
+     up = 2*u-um+dt*dt*(dx(Vx)+dy(Vy));
+     prob;
+     um=u;
+     u=up;
+     cout<< int2d(Th)((u-sin(pi*x)*sin(pi*y)*cos(i*dt*pi*sqrt(2.)))^2)
+     /int2d(Th)((sin(pi*x)*sin(pi*y)*cos(i*dt*pi*sqrt(2.)))^2)<< endl;
+//     plot([Vx,Vy],wait=0, value=1);
+ }
+P1h w,W = 0;
+problem prob1(W,w,solver=Cholesky,init=0)
+    = int2d(Th) (W*w) + int2d(Th)(up*w);
+    prob1;
+    plot(W,wait=1,value=1);
diff --git a/examples++-tutorial/periodic4.edp b/examples++-tutorial/periodic4.edp
new file mode 100644
index 0000000..d18468e
--- /dev/null
+++ b/examples++-tutorial/periodic4.edp
@@ -0,0 +1,34 @@
+real r=0.25;
+// a diamond with a hole
+border a(t=0,1){x=-t+1; y=t;label=1;}; 
+border b(t=0,1){ x=-t; y=1-t;label=2;};
+border c(t=0,1){ x=t-1; y=-t;label=3;};
+border d(t=0,1){ x=t; y=-1+t;label=4;};
+border e(t=0,2*pi){ x=r*cos(t); y=-r*sin(t);label=0;};
+int n = 10;
+mesh Th= buildmesh(a(n)+b(n)+c(n)+d(n)+e(n)); 
+plot(Th,wait=1);
+real r2=1.732;
+func abs=sqrt(x^2+y^2);
+//  warning for periodic condition:
+//  side a and c \hfilll
+//  on side a (label 1) $ x \in [0,1] $ or $ x-y\in [-1,1] $ \hfilll
+//  on side c (label 3) $ x \in [-1,0]$ or $ x-y\in[-1,1] $\hfilll
+// so the common abcissa can be repectively $x$ and $x+1$
+// or you can can try curviline abcissa $x-y$ and $x-y$ 
+//  1 first way
+// fespace Vh(Th,P2,periodic=[[2,1+x],[4,x],[1,x],[3,1+x]]);     
+// 2 second way
+ fespace Vh(Th,P2,periodic=[[2,x+y],[4,x+y],[1,x-y],[3,x-y]]);     
+
+ Vh uh,vh;             
+
+ func f=(y+x+1)*(y+x-1)*(y-x+1)*(y-x-1);                
+ real intf = int2d(Th)(f);
+ real mTh = int2d(Th)(1.);
+real moyf =  intf/mTh;
+cout << moyf << endl; 
+ problem laplace(uh,vh) =                     
+    int2d(Th)( dx(uh)*dx(vh) + dy(uh)*dy(vh) ) + int2d(Th)( (moyf-f)*vh ) ;                
+laplace; 
+  plot(uh,wait=1,ps="perio4.eps");
\ No newline at end of file
diff --git a/examples++-tutorial/periodic4bis.edp b/examples++-tutorial/periodic4bis.edp
new file mode 100644
index 0000000..6cd2fb1
--- /dev/null
+++ b/examples++-tutorial/periodic4bis.edp
@@ -0,0 +1,48 @@
+// irregular boundary condition. 
+real Ax=0.9,Ay=1;
+real Bx=2,By=1;
+real Cx=2.5,Cy=2.5;
+real Dx=1,Dy=2;
+real gx = (Ax+Bx+Cx+Dx)/4.;
+real gy = (Ay+By+Cy+Dy)/4.;
+
+macro  LINEBORDER(A,B,lab) border A#B(t=0,1){real t1=1.-t;x=A#x*t1+B#x*t;y=A#y*t1+B#y*t;label=lab;}//EOM
+
+LINEBORDER(A,B,1)
+LINEBORDER(B,C,2)
+LINEBORDER(C,D,3)
+LINEBORDER(D,A,4)
+
+// , A (1-x)(1-y) B x(1-y)  C: x*y  , D (x-1)*y) 
+//mesh Th=square(10,10,[Cx*x*y+ Bx*(1-x)*y + Cx*(1-x)*(1-y) + Dx*(x)*(1-y),Ay*x*y+ By*(1-x)*y + Cy*(1-x)*(1-y) + Dy*(x)*(1-y)]  );
+int n=10;
+macro dist(ax,ay,bx,by) sqrt(square((ax)-(bx))+ square((ay)-(by)))  // EOM  
+real l1=dist(Ax,Ay,Bx,By);
+real l2=dist(Bx,By,Cx,Cy);
+real l3=dist(Cx,Cy,Dx,Dy);
+real l4=dist(Dx,Dy,Ax,Ay);
+func s1=dist(Ax,Ay,x,y)/l1;
+func s2=dist(Bx,By,x,y)/l2;
+func s3=dist(Cx,Cy,x,y)/l3;
+func s4=dist(Dx,Dy,x,y)/l4;
+cout << " l1:4 = "<< l1 << " " << l2 << " "<< l3 << " " <<l4 << endl;
+cout << "  s1:4 (final point: :)= " << s1(Bx,By) << " " 
+     << s2(Cx,Cy) << " " 
+     << s3(Dx,Dy) << " " 
+     << s4(Ax,Ay) << "\n "; 
+
+mesh Th=buildmesh(AB(n)+BC(n)+CD(n)+DA(n),fixeborder=1);
+
+verbosity=6;// to see the abscisse value pour the periodic condition.
+fespace Vh(Th,P1,periodic=[[1,s1],[3,s3],[2,s2],[4,s4]]);
+verbosity=1;
+macro Grad(u) [dx(u),dy(u)]//EOM
+Vh u,v;
+
+real cc=0;
+cc= int2d(Th)((x-gx)*(y-gy)-cc)/Th.area;
+cout << " compatibility =" << int2d(Th)((x-gx)*(y-gy)-cc) <<endl;
+
+solve Poission(u,v)=int2d(Th)(Grad(u)'*Grad(v)+ 1e-10*u*v)-int2d(Th)(10*v*((x-gx)*(y-gy)-cc));
+plot(u,wait=1,value=1);
+
diff --git a/examples++-tutorial/plot.edp b/examples++-tutorial/plot.edp
new file mode 100644
index 0000000..f567a70
--- /dev/null
+++ b/examples++-tutorial/plot.edp
@@ -0,0 +1,46 @@
+int n=20,nn=n+10;
+real[int] xx(nn),yy(nn);
+//  \url{from:   http://en.wikipedia.org/wiki/HSV_color_space} 
+//The HSV (Hue, Saturation, Value) model, 
+//   defines a color space in terms of three constituent components:
+//
+//HSV color space as a color wheel
+//Hue, the color type (such as red, blue, or yellow):
+//   Ranges from 0-360 (but normalized to 0-100% h ere)
+// Saturation, the "vibrancy" of the color: Ranges     from 0-100%
+//    The lower the saturation of a color, the more "grayness" is present 
+//    and the more faded the color will appear.
+// Value, the brightness of the color:
+//   Ranges from 0-100%
+// 
+real[int] colorhsv=[  // color hsv model
+  4./6., 1 , 0.5, // dark blue
+  4./6., 1 , 1, //  blue
+  5./6., 1 , 1, //  magenta
+  1, 1. , 1, //  red
+  1, 0.5 , 1 // light red 
+   ];
+mesh Th=square(5,5);
+fespace Vh(Th,P2);
+Vh uh=x*x+y*y,vh=-y^2+x^2;
+assert(n+1 < nn);
+//  compute a cut 
+for (int i=0;i<=n;i++)
+ {
+   xx[i]=i;
+   yy[i]=uh(real(i)/n,real(i)/n); // value of uh at point (i/10. , i/10.) 
+ }
+ 
+ plot(Th,uh,[uh,vh],value=true,ps="three.eps",wait=true); // plot mesh, isovalue, and vector
+ //  zoom on box defined by the two corner points [0.1,0.2] and [0.5,0.6]
+ plot(uh,[uh,vh],bb=[[0.1,0.2],[0.5,0.6]],wait=true,grey=1,fill=1,value=1,ps="threeg.eps");  // in grey with filling
+ plot([xx(0:n),yy(0:n)],[xx(0:n:5),yy(0:n:5)],ps="likegnu.eps",wait=true); //  like gnuplot plot a cut of uh
+
+ real[int] viso(31);
+ 
+ for (int i=0;i<viso.n;i++)
+   viso[i]=i*0.1;
+   
+ plot(uh,viso=viso(0:viso.n-1),value=1,fill=1,wait=1,hsv=colorhsv,ps="threehsv.eps");
+
+   
\ No newline at end of file
diff --git a/examples++-tutorial/readmesh.edp b/examples++-tutorial/readmesh.edp
new file mode 100644
index 0000000..bca1257
--- /dev/null
+++ b/examples++-tutorial/readmesh.edp
@@ -0,0 +1,77 @@
+border floor(t=0,1){ x=t; y=0; label=1;}; // the unit square
+border right(t=0,1){ x=1; y=t; label=5;};
+border ceiling(t=1,0){ x=t; y=1; label=5;};
+border left(t=1,0){ x=0; y=t; label=5;};
+int n=10;
+mesh th= buildmesh(floor(n)+right(n)+ceiling(n)+left(n));
+savemesh(th,"toto.am_fmt");// format "formated Marrocco"
+savemesh(th,"toto.Th");//format database "bamg"
+savemesh(th,"toto.dbg");//format debug
+savemesh(th,"toto.msh"); //format freefem
+mesh th2 = readmesh("toto.msh");
+fespace femp1(th,P1);
+femp1 f = sin(x)*cos(y),g;
+int where;
+real xx;
+{
+  
+  ofstream file("f.txt",binary);// for windows add binary version 3.30 
+  file.precision(16);
+  file << f[] << endl;
+  where=file.tellp();
+  file << 0.1 ;
+  //  file << " " << 0.2 ;
+  cout << " where in file " << where << endl;
+  file << " # comment bla bla ...  0.3 \n";
+  file << 0.2 << endl; 
+}
+//  Idea to skip comment in a file ...  start with  # too EOL
+func ifstream skipcomment(ifstream &ff)
+{
+    
+    while(1)
+    {
+    int where = ff.tellg(); // store file position 
+    string comment;
+    ff >> comment; 
+    if ( ! ff.good() ) break; 
+    if( comment(0:0)=="#") {
+         getline(ff,comment);
+         cout << " -- #" << comment << endl;
+    }
+    else {
+        ff.seekg(where); //restore file position 
+        break;        
+    }    
+    }
+    return ff;
+}
+
+
+{
+  ifstream file("f.txt",binary); // for windows (pb CRNL EOL  translation ) 
+  cout << " where " << file.seekg << endl; 
+  file.seekg(where);
+  file >> xx;
+  cout <<  " xx = " << xx << " good ? " << file.good() << endl;
+  assert(xx==0.1);
+  skipcomment(file) >> xx;
+  assert(xx==0.2);
+  file.seekg(0);
+  cout << " where " << file.tellg() << " " << file.good() << endl; 
+  file >> g[] ;
+}
+fespace Vh2(th2,P1);
+Vh2 u,v;
+plot(g);
+solve pb(u,v) =
+    int2d(th2)( u*v -dx(u)*dx(v)-dy(u)*dy(v) )
+  + int2d(th2)(-g*v) 
+  + int1d(th2,5)( -g*v)
+  + on(1,u=0) ;
+plot (th2,u);
+cout << " (u[],u[]) = " << (u[]'*u[]) << endl; 
+{
+ofstream file("u.txt");
+file << u[] << endl;
+}
diff --git a/examples++-tutorial/ref.edp b/examples++-tutorial/ref.edp
new file mode 100644
index 0000000..c428e95
--- /dev/null
+++ b/examples++-tutorial/ref.edp
@@ -0,0 +1,37 @@
+real REFadapt=0.238829;
+real REFadaptindicatorP1=0.239154;
+real REFadaptindicatorP2=0.239362;
+real REFalgo=0.283188;
+real REFalgowithmacro=0.283188;
+real REFaXtutorial=1+0.000305788;
+real REFbeam=2.25164;
+real REFBlackSchole=58.0181;
+real REFcavity=0.423606;
+real REFconvect2=2.54096;
+real REFconvectXapt=0.00195759;
+real REFconvect=9.88705;
+real REFFE=84.9337;
+real REFfluidStructAdapt=4.36689;
+real REFfluidStruct=1.2965;
+real REFfreeboundary=1071.12;
+real REFfreeboundaryXweak=1071.12;
+real REFLapDG2=2.04649;
+real REFLaplace=0.167397;
+real REFLaplaceP1bis=3.4845e-14;
+real REFLaplaceP1=2.34669;
+real REFLaplaceP1P2h=8.60123;
+real REFLaplaceRT=0.433835;
+real REFmovemesh=42.35;
+real REFnolinearXelas=0.11349;
+real REFNSUzawaCahouetChabart=2.01994;
+real REFonde=146.865;
+real REFplot=85.3776;
+real REFreadmesh=110.015;
+real REFregion=0.010438;
+real REFschwarzXgc=3.29683;
+real REFschwarzXnoXoverlap=5.11085;
+real REFschwarzXoverlap=5.04675;
+real REFsparseXmatrix=116.382;
+real REFsparseXcmatrix=232.764;
+real REFStokesUzawa=32.7781;
+real REFtablefunction=66.5851;
diff --git a/examples++-tutorial/region.edp b/examples++-tutorial/region.edp
new file mode 100644
index 0000000..05e9d0c
--- /dev/null
+++ b/examples++-tutorial/region.edp
@@ -0,0 +1,30 @@
+//   example using region keywork
+// construct a mesh with 4 regions (sub-domains)
+border a(t=0,1){x=t;y=0;};
+border b(t=0,0.5){x=1;y=t;};
+border c(t=0,0.5){x=1-t;y=0.5;};
+border d(t=0.5,1){x=0.5;y=t;};
+border e(t=0.5,1){x=1-t;y=1;};
+border f(t=0,1){x=0;y=1-t;};
+//  internal boundary 
+border i1(t=0,0.5){x=t;y=1-t;};
+border i2(t=0,0.5){x=t;y=t;};
+border i3(t=0,0.5){x=1-t;y=t;};
+   
+mesh th = buildmesh (a(6) + b(4) + c(4) +d(4) + e(4) + 
+    f(6)+i1(6)+i2(6)+i3(6));
+fespace Ph(th,P0);
+fespace Vh(th,P1);
+Ph reg=region;
+plot(reg,fill=1,wait=1,value=1,ps="region.eps");
+int nupper=reg(0.4,0.9);
+int nlower=reg(0.9,0.1);
+cout << " nlower " <<  nlower << ", nupper = " << nupper<< endl;
+//  defined the characteristics fonctions of upper and lower region
+Ph nu=1+5*(region==nlower) + 10*(region==nupper);
+if ( nu[].sum < 1) { cout << " Bug in region.edp (bad version try new one)"<< endl; exit(1);}
+plot(nu,fill=1,wait=1,value=1,ps="region_nu.eps");
+Vh u,v;
+solve lap(u,v) =   int2d(th)( nu*(dx(u)*dx(v) +dy(u)*dy(v)))  + int2d(th)(-1*v) + on(a,b,c,d,e,f,u=0);
+plot(u,value=1,ps="region_u.eps");
+
diff --git a/examples++-tutorial/regtests.edp b/examples++-tutorial/regtests.edp
new file mode 100644
index 0000000..4a415ea
--- /dev/null
+++ b/examples++-tutorial/regtests.edp
@@ -0,0 +1,525 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+// Regression tests
+// ----------------
+
+// The tests are checked against reference values by "make check" in
+// each examples subdirectory
+
+// "ref.edp" contains all reference values and may be rebuilt with
+// "make Ref"
+
+// $Id$
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+NoUseOfWait=true;
+int verbosityy=verbosity;
+
+
+
+
+include "ref.edp";
+
+
+
+
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+
+cout << "--------- file : adapt.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "adapt.edp";
+	real TESTadapt=u[].max-u[].min;
+		cout<<"adapt reference value = "<<REFadapt
+				<<" test value ="<<TESTadapt<<endl;
+			assert(TESTadapt<REFadapt*(1+0.01));
+				assert(TESTadapt>REFadapt*(1-0.01));
+};
+
+cout << "--------- file : adaptindicatorP1.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "adaptindicatorP1.edp";
+	real TESTadaptindicatorP1=u[].max-u[].min;
+		cout<<"adaptindicatorP1 reference value = "<<REFadaptindicatorP1
+				<<" test value ="<<TESTadaptindicatorP1<<endl;
+			assert(TESTadaptindicatorP1<REFadaptindicatorP1*(1+0.01));
+				assert(TESTadaptindicatorP1>REFadaptindicatorP1*(1-0.01));
+};
+
+cout << "--------- file : adaptindicatorP2.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "adaptindicatorP2.edp";
+	real TESTadaptindicatorP2=u[].max-u[].min;
+		cout<<"adaptindicatorP2 reference value = "<<REFadaptindicatorP2
+				<<" test value ="<<TESTadaptindicatorP2<<endl;
+			assert(TESTadaptindicatorP2<REFadaptindicatorP2*(1+0.01));
+				assert(TESTadaptindicatorP2>REFadaptindicatorP2*(1-0.01));
+};
+
+cout << "--------- file : algo.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "algo.edp";
+	real TESTalgo=umax;
+		cout<<"algo reference value = "<<REFalgo
+				<<" test value ="<<TESTalgo<<endl;
+			assert(TESTalgo<REFalgo*(1+0.01));
+				assert(TESTalgo>REFalgo*(1-0.01));
+};
+
+cout << "--------- file : array.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "array.edp";
+	
+};
+
+cout << "--------- file : a_tutorial.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "a_tutorial.edp";
+	real TESTaXtutorial=1+max(err[].max,-err[].min);
+		cout<<"a_tutorial reference value = "<<REFaXtutorial
+				<<" test value ="<<TESTaXtutorial<<endl;
+			assert(TESTaXtutorial<REFaXtutorial*(1+0.001));
+				assert(TESTaXtutorial>REFaXtutorial*(1-0.001));
+};
+
+cout << "--------- file : beam.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "beam.edp";
+	real TESTbeam=uu[]'*uu[];
+		cout<<"beam reference value = "<<REFbeam
+				<<" test value ="<<TESTbeam<<endl;
+			assert(TESTbeam<REFbeam*(1+5e-2));
+				assert(TESTbeam>REFbeam*(1-5e-2));
+};
+
+cout << "--------- file : calculus.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "calculus.edp";
+	
+};
+
+cout << "--------- file : cavity.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "cavity.edp";
+	real TESTcavity=psi[]'*psi[];
+		cout<<"cavity reference value = "<<REFcavity
+				<<" test value ="<<TESTcavity<<endl;
+			assert(TESTcavity<REFcavity*(1+1e-2));
+				assert(TESTcavity>REFcavity*(1-1e-2));
+};
+
+cout << "--------- file : convect2.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "convect2.edp";
+	real TESTconvect2=v[]'*v[];
+		cout<<"convect2 reference value = "<<REFconvect2
+				<<" test value ="<<TESTconvect2<<endl;
+			assert(TESTconvect2<REFconvect2*(1+1e-1));
+				assert(TESTconvect2>REFconvect2*(1-1e-1));
+};
+
+cout << "--------- file : convect-apt.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "convect-apt.edp";
+	real TESTconvectXapt=error;
+		cout<<"convect-apt reference value = "<<REFconvectXapt
+				<<" test value ="<<TESTconvectXapt<<endl;
+			assert(TESTconvectXapt<REFconvectXapt*(1+5e-1));
+				assert(TESTconvectXapt>REFconvectXapt*(1-5e-1));
+};
+
+cout << "--------- file : convect.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "convect.edp";
+	real TESTconvect=v[]'*v[];
+		cout<<"convect reference value = "<<REFconvect
+				<<" test value ="<<TESTconvect<<endl;
+			assert(TESTconvect<REFconvect*(1+1e-1));
+				assert(TESTconvect>REFconvect*(1-1e-1));
+};
+
+cout << "--------- file : dumptable.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "dumptable.edp";
+	
+};
+
+cout << "--------- file : ex-vf.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "ex-vf.edp";
+	
+};
+
+cout << "--------- file : FE.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "FE.edp";
+	real TESTFE=wdc[]'*wdc[];
+		cout<<"FE reference value = "<<REFFE
+				<<" test value ="<<TESTFE<<endl;
+			assert(TESTFE<REFFE*(1+1e-2));
+				assert(TESTFE>REFFE*(1-1e-2));
+};
+
+cout << "--------- file : fluidStructAdapt.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "fluidStructAdapt.edp";
+	real TESTfluidStructAdapt=uu[]'*uu[];
+		cout<<"fluidStructAdapt reference value = "<<REFfluidStructAdapt
+				<<" test value ="<<TESTfluidStructAdapt<<endl;
+			assert(TESTfluidStructAdapt<REFfluidStructAdapt*(1+2e-1));
+				assert(TESTfluidStructAdapt>REFfluidStructAdapt*(1-2e-1));
+};
+
+cout << "--------- file : fluidStruct.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "fluidStruct.edp";
+	real TESTfluidStruct=uu[]'*uu[];
+		cout<<"fluidStruct reference value = "<<REFfluidStruct
+				<<" test value ="<<TESTfluidStruct<<endl;
+			assert(TESTfluidStruct<REFfluidStruct*(1+2e-1));
+				assert(TESTfluidStruct>REFfluidStruct*(1-2e-1));
+};
+
+
+
+
+cout << "--------- file : LapDG2.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "LapDG2.edp";
+	real TESTLapDG2=u[]'*u[];
+		cout<<"LapDG2 reference value = "<<REFLapDG2
+				<<" test value ="<<TESTLapDG2<<endl;
+			assert(TESTLapDG2<REFLapDG2*(1+1e-2));
+				assert(TESTLapDG2>REFLapDG2*(1-1e-2));
+};
+
+cout << "--------- file : Laplace.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "Laplace.edp";
+	real TESTLaplace=uh[]'*uh[];
+		cout<<"Laplace reference value = "<<REFLaplace
+				<<" test value ="<<TESTLaplace<<endl;
+			assert(TESTLaplace<REFLaplace*(1+1e-2));
+				assert(TESTLaplace>REFLaplace*(1-1e-2));
+};
+
+cout << "--------- file : LaplaceP1bis.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "LaplaceP1bis.edp";
+	real TESTLaplaceP1bis=u[]'*u[];
+		cout<<"LaplaceP1bis reference value = "<<REFLaplaceP1bis
+				<<" test value ="<<TESTLaplaceP1bis<<endl;
+			assert(TESTLaplaceP1bis<REFLaplaceP1bis*(1+1e-2));
+				assert(TESTLaplaceP1bis>REFLaplaceP1bis*(1-1e-2));
+};
+
+cout << "--------- file : LaplaceP1.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "LaplaceP1.edp";
+	real TESTLaplaceP1=uh[]'*uh[];
+		cout<<"LaplaceP1 reference value = "<<REFLaplaceP1
+				<<" test value ="<<TESTLaplaceP1<<endl;
+			assert(TESTLaplaceP1<REFLaplaceP1*(1+1e-2));
+				assert(TESTLaplaceP1>REFLaplaceP1*(1-1e-2));
+};
+
+cout << "--------- file : LaplaceP1P2h.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "LaplaceP1P2h.edp";
+	real TESTLaplaceP1P2h=u2h[]'*u2h[];
+		cout<<"LaplaceP1P2h reference value = "<<REFLaplaceP1P2h
+				<<" test value ="<<TESTLaplaceP1P2h<<endl;
+			assert(TESTLaplaceP1P2h<REFLaplaceP1P2h*(1+1e-2));
+				assert(TESTLaplaceP1P2h>REFLaplaceP1P2h*(1-1e-2));
+};
+
+cout << "--------- file : LaplaceRT.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "LaplaceRT.edp";
+	real TESTLaplaceRT=u1[]'*u1[];
+		cout<<"LaplaceRT reference value = "<<REFLaplaceRT
+				<<" test value ="<<TESTLaplaceRT<<endl;
+			assert(TESTLaplaceRT<REFLaplaceRT*(1+1e-2));
+				assert(TESTLaplaceRT>REFLaplaceRT*(1-1e-2));
+};
+
+cout << "--------- file : mesh.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "mesh.edp";
+	
+};
+
+cout << "--------- file : movemesh.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "movemesh.edp";
+	real TESTmovemesh=u[]'*u[];
+		cout<<"movemesh reference value = "<<REFmovemesh
+				<<" test value ="<<TESTmovemesh<<endl;
+			assert(TESTmovemesh<REFmovemesh*(1+1e-2));
+				assert(TESTmovemesh>REFmovemesh*(1-1e-2));
+};
+
+cout << "--------- file : nolinear-elas.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "nolinear-elas.edp";
+	real TESTnolinearXelas=un[]'*un[];
+		cout<<"nolinear-elas reference value = "<<REFnolinearXelas
+				<<" test value ="<<TESTnolinearXelas<<endl;
+			assert(TESTnolinearXelas<REFnolinearXelas*(1+1e-2));
+				assert(TESTnolinearXelas>REFnolinearXelas*(1-1e-2));
+};
+
+cout << "--------- file : NSUzawaCahouetChabart.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "NSUzawaCahouetChabart.edp";
+	real TESTNSUzawaCahouetChabart=u1[].linfty;
+		cout<<"NSUzawaCahouetChabart reference value = "<<REFNSUzawaCahouetChabart
+				<<" test value ="<<TESTNSUzawaCahouetChabart<<endl;
+			assert(TESTNSUzawaCahouetChabart<REFNSUzawaCahouetChabart*(1+1e-2));
+				assert(TESTNSUzawaCahouetChabart>REFNSUzawaCahouetChabart*(1-1e-2));
+};
+
+cout << "--------- file : onde.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "onde.edp";
+	real TESTonde=u[]'*u[];
+		cout<<"onde reference value = "<<REFonde
+				<<" test value ="<<TESTonde<<endl;
+			assert(TESTonde<REFonde*(1+1e-2));
+				assert(TESTonde>REFonde*(1-1e-2));
+};
+
+
+
+cout << "--------- file : plot.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "plot.edp";
+	real TESTplot=uh[]'*uh[];
+		cout<<"plot reference value = "<<REFplot
+				<<" test value ="<<TESTplot<<endl;
+			assert(TESTplot<REFplot*(1+1e-2));
+				assert(TESTplot>REFplot*(1-1e-2));
+};
+
+cout << "--------- file : readmesh.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "readmesh.edp";
+	real TESTreadmesh=u[]'*u[];
+		cout<<"readmesh reference value = "<<REFreadmesh
+				<<" test value ="<<TESTreadmesh<<endl;
+			assert(TESTreadmesh<REFreadmesh*(1+2e-1));
+				assert(TESTreadmesh>REFreadmesh*(1-2e-1));
+};
+
+cout << "--------- file : region.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "region.edp";
+	real TESTregion=u[]'*u[];
+		cout<<"region reference value = "<<REFregion
+				<<" test value ="<<TESTregion<<endl;
+			assert(TESTregion<REFregion*(1+1e-1));
+				assert(TESTregion>REFregion*(1-1e-1));
+};
+
+cout << "--------- file : saverestore.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "saverestore.edp";
+	
+};
+
+cout << "--------- file : schwarz-gc.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "schwarz-gc.edp";
+	real TESTschwarzXgc=u1[]'*u1[];
+		cout<<"schwarz-gc reference value = "<<REFschwarzXgc
+				<<" test value ="<<TESTschwarzXgc<<endl;
+			assert(TESTschwarzXgc<REFschwarzXgc*(1+5e-2));
+				assert(TESTschwarzXgc>REFschwarzXgc*(1-5e-2));
+};
+
+cout << "--------- file : schwarz-no-overlap.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "schwarz-no-overlap.edp";
+	real TESTschwarzXnoXoverlap=u[]'*u[];
+		cout<<"schwarz-no-overlap reference value = "<<REFschwarzXnoXoverlap
+				<<" test value ="<<TESTschwarzXnoXoverlap<<endl;
+			assert(TESTschwarzXnoXoverlap<REFschwarzXnoXoverlap*(1+5e-2));
+				assert(TESTschwarzXnoXoverlap>REFschwarzXnoXoverlap*(1-5e-2));
+};
+
+cout << "--------- file : schwarz-overlap.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "schwarz-overlap.edp";
+	real TESTschwarzXoverlap=u[]'*u[];
+		cout<<"schwarz-overlap reference value = "<<REFschwarzXoverlap
+				<<" test value ="<<TESTschwarzXoverlap<<endl;
+			assert(TESTschwarzXoverlap<REFschwarzXoverlap*(1+5e-2));
+				assert(TESTschwarzXoverlap>REFschwarzXoverlap*(1-5e-2));
+};
+
+cout << "--------- file : sparse-matrix.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "sparse-matrix.edp";
+	real TESTsparseXmatrix=xx[]'*xx[];
+		cout<<"sparse-matrix reference value = "<<REFsparseXmatrix
+				<<" test value ="<<TESTsparseXmatrix<<endl;
+			assert(TESTsparseXmatrix<REFsparseXmatrix*(1+5e-2));
+				assert(TESTsparseXmatrix>REFsparseXmatrix*(1-5e-2));
+};
+
+cout << "--------- file : sparse-cmatrix.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "sparse-cmatrix.edp";
+	real TESTsparseXcmatrix=real(xx[]'*xx[]);
+		cout<<"sparse-cmatrix reference value = "<<REFsparseXcmatrix
+				<<" test value ="<<TESTsparseXcmatrix<<endl;
+			assert(TESTsparseXcmatrix<REFsparseXcmatrix*(1+5e-2));
+				assert(TESTsparseXcmatrix>REFsparseXcmatrix*(1-5e-2));
+};
+
+cout << "--------- file : StokesUzawa.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "StokesUzawa.edp";
+	real TESTStokesUzawa=u1[]'*u1[];
+		cout<<"StokesUzawa reference value = "<<REFStokesUzawa
+				<<" test value ="<<TESTStokesUzawa<<endl;
+			assert(TESTStokesUzawa<REFStokesUzawa*(1+5e-2));
+				assert(TESTStokesUzawa>REFStokesUzawa*(1-5e-2));
+};
+
+cout << "--------- file : tablefunction.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "tablefunction.edp";
+	real TESTtablefunction=fxy[]'*fxy[];
+		cout<<"tablefunction reference value = "<<REFtablefunction
+				<<" test value ="<<TESTtablefunction<<endl;
+			assert(TESTtablefunction<REFtablefunction*(1+1e-2));
+				assert(TESTtablefunction>REFtablefunction*(1-1e-2));
+};
+
diff --git a/examples++-tutorial/regtests.m4 b/examples++-tutorial/regtests.m4
new file mode 100644
index 0000000..1898fb5
--- /dev/null
+++ b/examples++-tutorial/regtests.m4
@@ -0,0 +1,66 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+include(../regtests.m4)
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+dnl (syntax of ONETEST macro defined in ../regtests.m4)
+
+ONETEST(adapt,u[].max-u[].min,0.01)
+ONETEST(adaptindicatorP1,u[].max-u[].min,0.01)
+ONETEST(adaptindicatorP2,u[].max-u[].min,0.01)
+ONETEST(algo,umax,0.01)
+ONETEST(array)
+ONETEST(a_tutorial,1+max(err[].max,-err[].min),0.001)
+ONETEST(beam,uu[]'*uu[],5e-2)
+dnl this exemple was wrong it replace by the correct one in chap3 
+dnl ONETEST(BlackSchole,normvL2,0.1)
+ONETEST(calculus)
+ONETEST(cavity,psi[]'*psi[],1e-2)
+ONETEST(convect2,v[]'*v[],1e-1)
+ONETEST(convect-apt,error,5e-1)
+ONETEST(convect,v[]'*v[],1e-1)
+ONETEST(dumptable)
+ONETEST(ex-vf)
+ONETEST(FE,wdc[]'*wdc[],1e-2)
+ONETEST(fluidStructAdapt,uu[]'*uu[],2e-1)
+ONETEST(fluidStruct,uu[]'*uu[],2e-1)
+
+dnl This test always crashes under Mingw
+dnl ("Error move mesh triangles was reverse")
+
+dnl ONETEST(freeboundary,u[]'*u[],5e-2)
+dnl ONETEST(freeboundary-weak,p[]'*p[],5e-2)
+
+ONETEST(LapDG2,u[]'*u[],1e-2)
+ONETEST(Laplace,uh[]'*uh[],1e-2)
+ONETEST(LaplaceP1bis,u[]'*u[],1e-2)
+ONETEST(LaplaceP1,uh[]'*uh[],1e-2)
+ONETEST(LaplaceP1P2h,u2h[]'*u2h[],1e-2)
+ONETEST(LaplaceRT,u1[]'*u1[],1e-2)
+ONETEST(mesh)
+ONETEST(movemesh,u[]'*u[],1e-2)
+ONETEST(nolinear-elas,un[]'*un[],1e-2)
+ONETEST(NSUzawaCahouetChabart,u1[].linfty,1e-2)
+ONETEST(onde,u[]'*u[],1e-2)
+
+dnl The following two tests have suspicious results (1e20 and bigger)
+dnl ONETEST(periodic4,uh[]'*uh[],1e-2)
+dnl ONETEST(Periodic,uh[]'*uh[],1e-2)
+
+ONETEST(plot,uh[]'*uh[],1e-2)
+ONETEST(readmesh,u[]'*u[],2e-1)
+ONETEST(region,u[]'*u[],1e-1)
+ONETEST(saverestore)
+ONETEST(schwarz-gc,u1[]'*u1[],5e-2)
+ONETEST(schwarz-no-overlap,u[]'*u[],5e-2)
+ONETEST(schwarz-overlap,u[]'*u[],5e-2)
+ONETEST(sparse-matrix,xx[]'*xx[],5e-2)
+ONETEST(sparse-cmatrix,real(xx[]'*xx[]),5e-2)
+ONETEST(StokesUzawa,u1[]'*u1[],5e-2)
+ONETEST(tablefunction,fxy[]'*fxy[],1e-2)
diff --git a/examples++-tutorial/saverestore.edp b/examples++-tutorial/saverestore.edp
new file mode 100644
index 0000000..4a09608
--- /dev/null
+++ b/examples++-tutorial/saverestore.edp
@@ -0,0 +1,31 @@
+// bug  save - restore P2 
+verbosity=3;
+int nn=2;
+mesh Th=square(nn,nn);
+savemesh(Th,"Th.msh");
+func f=x+y+0.1234567890e-5;
+fespace Vh(Th,P2);
+Vh u=f;
+{ofstream f("u.txt");
+  f.precision; 
+ cout << " f.precision() = " << f.precision() << endl;
+ f.precision(12);
+ cout << " f.precision() = " << f.precision() << endl;
+
+f <<u[];
+}
+real regtest;//FFCS regression test value
+{
+mesh Th=readmesh("Th.msh"); // il y a un changement de numerotation des traingle ou??
+// mesh Th("Th.msh"); // oK ..
+savemesh(Th,"Th1.msh");
+fespace VVh(Th,P2);
+VVh u=f,v,e;
+ifstream f("u.txt");
+f >> v[] ;
+e[] = u[] -v[];
+cout << e[].max << " " << e[].min << endl;
+plot(e,wait=1,value=1);
+assert(e[].max-e[].min < 1e-6);
+regtest=e[].max-e[].min;
+}
diff --git a/examples++-tutorial/schwarz-gc.edp b/examples++-tutorial/schwarz-gc.edp
new file mode 100644
index 0000000..c2be3bb
--- /dev/null
+++ b/examples++-tutorial/schwarz-gc.edp
@@ -0,0 +1,68 @@
+// Schwarz without overlapping (Shur complenement Neumann -> Dirichet)  
+verbosity=2;
+real cpu=clock();
+int inside = 2; 
+int outside = 1;
+border Gamma1(t=1,2){x=t;y=0;label=outside;};
+border Gamma2(t=0,1){x=2;y=t;label=outside;};
+border Gamma3(t=2,0){x=t ;y=1;label=outside;};
+
+border GammaInside(t=1,0){x = 1-t; y = t;label=inside;};
+
+border GammaArc(t=pi/2, 2*pi){ x= cos(t); y = sin(t);label=outside;}; 
+int n=4;
+mesh Th1 = buildmesh( Gamma1(5*n) + Gamma2(5*n) + GammaInside(5*n) + Gamma3(5*n));
+mesh Th2 = buildmesh ( GammaInside(-5*n) + GammaArc(25*n) );
+
+plot(Th1,Th2);
+
+fespace Vh1(Th1,P1),      Vh2(Th2,P1);
+Vh1 u1=0,v1;              Vh2 u2,v2;
+Vh1 lambda=0;  // take $\lambda \in V_{h1}$
+/*
+Remark, to day is not possible to
+defined a function just on a border, so the $\ lambda $
+function is defined on the all domain $\Omega_1$
+by:
+*/
+int i=0;  // for factorization optimization 
+
+
+problem Pb2(u2,v2,init=i,solver=Cholesky) = 
+    int2d(Th2)( dx(u2)*dx(v2)+dy(u2)*dy(v2) )
+  + int2d(Th2)( -v2) 
+  + int1d(Th2,inside)(-lambda*v2) +    on(outside,u2= 0 ) ;
+problem Pb1(u1,v1,init=i,solver=Cholesky) = 
+    int2d(Th1)( dx(u1)*dx(v1)+dy(u1)*dy(v1) )
+  + int2d(Th1)( -v1) 
+  + int1d(Th1,inside)(+lambda*v1) +    on(outside,u1 = 0 ) ;
+
+varf b(u2,v2,solver=CG) =int1d(Th1,inside)(u2*v2);
+matrix B= b(Vh1,Vh1,solver=CG);
+
+//  $\lambda \longrightarrow  \int_{\Gamma_i }(u_1-u_2) v_{1}$
+func real[int] BoundaryProblem(real[int] &l)
+{ 
+   lambda[]=l;
+   Pb1; 
+   Pb2;
+   i++;
+   v1=-(u1-u2); 
+   lambda[]=B*v1[];
+   return lambda[] ;
+};
+/*
+Remark, the  difference between the tow notation \ttCC{v1} and \ttCC{v1[]}  is: 
+ \ttCC{v1} is the finite element  function and \ttCC{v1[]} 
+is the vector in the canonical basis of the   finite element  function  \ttCC{v1} .
+*/
+Vh1 p=0,q=0; 
+//  solve the problem with Conjugue Gradient
+
+LinearCG(BoundaryProblem,p[],q[],eps=1.e-6,nbiter=100);
+//  compute the final solution, because CG works with increment
+BoundaryProblem(p[]); // solve again  to have right u1,u2
+cout << " -- CPU time  schwarz-gc:" <<  clock()-cpu << endl;
+
+plot(u1,u2);
+
diff --git a/examples++-tutorial/schwarz-no-overlap.edp b/examples++-tutorial/schwarz-no-overlap.edp
new file mode 100644
index 0000000..2b9313c
--- /dev/null
+++ b/examples++-tutorial/schwarz-no-overlap.edp
@@ -0,0 +1,41 @@
+// schwarz1 without overlapping
+int inside = 2;
+int outside = 1;
+border a(t=1,2){x=t;y=0;label=outside;};
+border b(t=0,1){x=2;y=t;label=outside;};
+border c(t=2,0){x=t ;y=1;label=outside;};
+border d(t=1,0){x = 1-t; y = t;label=inside;};
+border e(t=0, 1){ x= 1-t; y = t;label=inside;};
+border e1(t=pi/2, 2*pi){ x= cos(t); y = sin(t);label=outside;}; 
+int n=4;
+mesh th = buildmesh( a(5*n) + b(5*n) + c(10*n) + d(5*n));
+mesh TH = buildmesh ( e(5*n) + e1(25*n) );
+plot(th,TH,wait=1,ps="schwarz-no-th.eps");
+fespace vh(th,P1);
+fespace VH(TH,P1);
+vh u=0,v; VH U,V;
+vh lambda=0;
+int i=0;
+
+problem PB(U,V,init=i,solver=Cholesky) = 
+    int2d(TH)( dx(U)*dx(V)+dy(U)*dy(V) )
+  + int2d(TH)( -V) 
+  + int1d(TH,inside)(lambda*V) +    on(outside,U= 0 ) ;
+problem pb(u,v,init=i,solver=Cholesky) = 
+    int2d(th)( dx(u)*dx(v)+dy(u)*dy(v) )
+  + int2d(th)( -v) 
+  + int1d(th,inside)(-lambda*v) +    on(outside,u = 0 ) ;
+
+
+for ( i=0 ;i< 20; i++) 
+{   
+   PB; 
+   pb;
+   lambda = lambda - (u-U)/2;
+//  if (i==0)
+
+    // FFCS: add 3d view
+  plot(U,u,wait=true,ps="schwarz-no-u"+i+".eps",dim=3,fill=1);
+};
+
+plot(U,u,ps="schwarz-no-u.eps");
diff --git a/examples++-tutorial/schwarz-overlap.edp b/examples++-tutorial/schwarz-overlap.edp
new file mode 100644
index 0000000..f920dfe
--- /dev/null
+++ b/examples++-tutorial/schwarz-overlap.edp
@@ -0,0 +1,34 @@
+real pi=4*atan(1);
+int inside = 2;
+int outside = 1;
+border a(t=1,2){x=t;y=0;label=outside;};
+border b(t=0,1){x=2;y=t;label=outside;};
+border c(t=2,0){x=t ;y=1;label=outside;};
+border d(t=1,0){x = 1-t; y = t;label=inside;};
+border e(t=0, pi/2){ x= cos(t); y = sin(t);label=inside;};
+border e1(t=pi/2, 2*pi){ x= cos(t); y = sin(t);label=outside;}; 
+int n=4;
+mesh th = buildmesh( a(5*n) + b(5*n) + c(10*n) + d(5*n));
+mesh TH = buildmesh ( e(5*n) + e1(25*n) );
+plot(th,TH,ps="schwarz-th.eps");
+fespace vh(th,P1);
+fespace VH(TH,P1);
+vh u=0,v; VH U,V;
+int i=0;
+
+problem PB(U,V,init=i,solver=Cholesky) = 
+    int2d(TH)( dx(U)*dx(V)+dy(U)*dy(V) )
+  + int2d(TH)( -V) + on(inside,U = u)  +    on(outside,U= 0 ) ;
+problem pb(u,v,init=i,solver=Cholesky) = 
+    int2d(th)( dx(u)*dx(v)+dy(u)*dy(v) )
+  + int2d(th)( -v) + on(inside ,u = U) +    on(outside,u = 0 ) ;
+
+
+for ( i=0 ;i< 10; i++) 
+{   
+   PB; 
+   pb;
+   if (i==0)      plot(U,u,wait=true,ps="schwarz-u"+i+".eps");
+};
+
+plot(U,u,ps="schwarz-u.eps");
diff --git a/examples++-tutorial/shur-comp.edp b/examples++-tutorial/shur-comp.edp
new file mode 100644
index 0000000..8543b51
--- /dev/null
+++ b/examples++-tutorial/shur-comp.edp
@@ -0,0 +1,164 @@
+// Schwarz without overlapping (Shur complement Neumann -> Dirichet)  
+//  with matrix ---
+//  ------------
+verbosity=2;
+real cpu=clock();
+
+macro laplacien(u,v) (dx(u)*dx(v)+dy(u)*dy(u)) //
+
+// --- beging  meshes  building --------------
+int nbsd=4;
+int labext= nbsd+1;
+real[int] theta(nbsd+1),cost(nbsd),sint(nbsd);
+
+for (int i=0;i<nbsd;i++)
+ {
+  real t=i*2*pi/nbsd;
+  theta[i]= t;
+  theta[i+1]= (i+1)*2*pi/nbsd;
+  cost[i]=cos(t);
+  sint[i]=sin(t);
+ }
+
+
+border g1(t=0,1){x=cost[0]*t;y=sint[0]*t;label=1;};
+border g2(t=0,1){x=cost[1]*t;y=sint[1]*t;label=2;};
+border g3(t=0,1){x=cost[2]*t;y=sint[2]*t;label=3;};
+border g4(t=0,1){x=cost[3]*t;y=sint[3]*t;label=4;};
+
+border e12(t=theta[0],theta[1]){x=cos(t);y=sin(t);label=labext;};
+border e23(t=theta[1],theta[2]){x=cos(t);y=sin(t);label=labext;};
+border e34(t=theta[2],theta[3]){x=cos(t);y=sin(t);label=labext;};
+border e41(t=theta[3],theta[4]){x=cos(t);y=sin(t);label=labext;};
+
+ int Ng = 10;
+ int Ne = 10;
+
+plot(g1(Ng)+g2(Ng)+g3(Ng)+g4(Ng) + e12(Ne) + e23(Ne)+ e34(Ne) + e41(Ne) ,wait=1);
+
+mesh Thf = buildmesh( g1(Ng)+g2(Ng)+g3(Ng)+g4(Ng) + e12(Ne) + e23(Ne)+ e34(Ne) + e41(Ne) );
+fespace Phf(Thf,P0);
+fespace Vhf(Thf,P1);
+Phf reg=region;
+int rr1 = 0; 
+int rr2 = 1;
+int rr3 = 2; 
+int rr4 = 3;
+
+func rreg1 = reg==rr1;
+func rreg2 = reg==rr2;
+func rreg3 = reg==rr3;
+func rreg4 = reg==rr4;
+
+Vhf reg1=rreg1, reg2=rreg2, reg3=rreg3, reg4=rreg4;
+
+int[int] ssd(Thf.nt);
+for (int i=0;i<Thf.nt;i++)
+ ssd[i]=reg[][i];
+
+mesh The = emptymesh(Thf,ssd);
+plot(Thf,wait=1);
+plot(The,wait=1);
+
+fespace Phe(The,P0); //
+
+Phe rege=reg;
+plot(rege,fill=1,wait=1);
+fespace Whe(The,P1dc); // espace des multilicateur de Lagrange
+fespace Mhe(The,P1); // espace des multilicateur de Lagrange
+Whe trace;
+Mhe lambda; 
+Mhe intern; //  1 if the vertex in internal and 0 if on the real boundary 
+
+intern=  (square(x)+square(y))  < 0.999; 
+
+//   - end of  meshes building  . 
+mesh[int] aTh(nbsd);
+for (int i=0;i<nbsd;i++)
+  aTh[i]=trunc(Thf,region==i);
+
+int i=0;
+
+fespace Xh1(aTh[0],P1);
+Xh1 u1,v1,dnu1;
+
+fespace Xh2(aTh[1],P1);
+Xh2 u2,v2,dnu2;
+
+fespace Xh3(aTh[2],P1);
+Xh3 u3,v3,dnu3;
+
+fespace Xh4(aTh[3],P1);
+Xh4 u4,v4,dnu4;
+
+matrix I1=interpolate(Xh1,Mhe); // build interpolation matrix  Mhe -> Xh1
+matrix I2=interpolate(Xh2,Mhe); // build interpolation matrix  Mhe -> Xh2
+matrix I3=interpolate(Xh3,Mhe); // build interpolation matrix  Mhe -> Xh2
+matrix I4=interpolate(Xh4,Mhe); // build interpolation matrix  Mhe -> Xh3
+
+int nm = Mhe.ndof;
+real [int]  l1(nm),l2(nm),l3(nm),l4(nm);
+
+func f = (x+1)*(y-2);
+varf vgamma(u,v) = on(1,2,3,4,u=1);
+Mhe  gamma;
+gamma[] = vgamma(0,Mhe,tgv=1);
+plot(gamma,wait=1,cmm="gamma",value=1);
+varf vM(u,v) =  int1d(The)( u*v) ;
+matrix M = vM(Mhe,Mhe,solver=UMFPACK) ;
+ 
+// debut macro par ssd 
+macro Pb(A,B,a,P,Th,u1,v1,Xh)
+   cout << " -- PB -- " << endl;
+  varf a(u1,v1) =   int2d(Th)( dx(u1)*dx(v1)+dy(u1)*dy(v1) )
+  - int2d(Th)( f*v1) ;
+problem P(u1,v1,init=i,solver=Cholesky) = 
+  int2d(Th)( dx(u1)*dx(v1)+dy(u1)*dy(v1) )
+  - int2d(Th)( f*v1) 
+  + on(labext,u1= 0 ) 
+  + on(1,2,3,4,u1=lambda)
+  ;
+
+matrix A = a(Xh,Xh,solver=GMRES) ;
+real[int] B(Xh.ndof);
+B=a(0,Xh);
+
+// Fin macro ssd -------
+
+
+Pb(A1,b1,va1,Pb1,aTh[0],u1,v1,Xh1);
+Pb(A2,b2,va2,Pb2,aTh[1],u2,v2,Xh2);
+Pb(A3,b3,va3,Pb3,aTh[2],u3,v3,Xh3);
+Pb(A4,b4,va4,Pb4,aTh[3],u4,v4,Xh4);
+
+
+func real[int] BoundaryProblem(real[int] &l)
+{
+  int vv = verbosity;
+  verbosity=0; 
+  lambda[]=l;
+  Pb1;  dnu1[]= A1*u1[];dnu1[]+=b1;  l1= I1'*dnu1[];
+  Pb2;  dnu2[]= A2*u2[];dnu2[]+=b2;  l2= I2'*dnu2[];
+  Pb3;  dnu3[]= A3*u3[];dnu3[]+=b3;  l3= I3'*dnu3[];
+  Pb4;  dnu4[]= A4*u4[];dnu4[]+=b4;  l4= I4'*dnu4[];
+  l1 += l2;
+  l1 += l3;
+  l1 += l4;
+  l1 = l1.* intern[]; 
+  cout << " residu = " <<  l1.max << " " << l1.min << endl;
+  lambda[]=M*l1;
+  plot(lambda,wait=1,cmm="lamdba");
+  lambda[]=lambda[].* intern[];
+  i++;
+  verbosity=vv; 
+  return lambda[] ;
+};
+
+lambda=0;
+
+Mhe p=0;
+
+verbosity=100;
+LinearCG(BoundaryProblem,p[],eps=1.e-6,nbiter=100);
+BoundaryProblem(p[]);
+plot(u1,u2,u3,u4,wait=1,cmm="u1,u2,u3,u4");
diff --git a/examples++-tutorial/sparse-cmatrix.edp b/examples++-tutorial/sparse-cmatrix.edp
new file mode 100644
index 0000000..6cd3188
--- /dev/null
+++ b/examples++-tutorial/sparse-cmatrix.edp
@@ -0,0 +1,156 @@
+//  sparse matrix test  ---
+// example of the new matrix feature in version 1.40
+// -------------------------------------------------
+for(int step=0; step <2; ++step)
+{
+mesh  TH = square(3,4);
+mesh  th = square(2,3);
+mesh  Th = square(4,4);
+
+complex ccc;
+ccc= 1;
+cout << ccc << endl;
+fespace VH(TH,P1);
+fespace Vh(th,P1);
+fespace Wh(Th,P1);
+
+matrix RB= interpolate(VH,Vh);  // build interpolation matrix Vh->Vh 
+matrix RBB= interpolate(Wh,Vh);  // build interpolation matrix
+matrix<complex> B=RB;
+B = B*(1+2i);
+
+matrix<complex> BB=RBB;
+
+varf vA(u,v) = int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))+ int1d(Th)(u*v); 
+matrix<complex> A=vA(Wh,Wh);
+Vh<complex> ml=0;
+cout << " ml " << ml[] << endl;
+varf vML(u,v) = int2d(th)(1.*v);
+ml[]=vML(0,Vh); // build the P1 mass lump of P1
+cout << ml[] << endl;
+matrix<complex> ML(ml[]); // matrix diagonal
+cout << "ML="<<ML << endl;
+cout << "B="<<B << endl;
+matrix<complex> BML=B*ML; // a faire 
+matrix<complex> tB=B';        //'; transpose and conjugate 
+cout << "tB=" << tB << endl;
+matrix<complex> MLtB=ML'*B'; // 
+
+cout << "BML="<<BML << endl;
+cout << "MLtB=" << MLtB << endl;
+
+// WARNING if UMFPACK is not install
+// the UMFPACK solver is replace by LU 
+//  but LU need skyline matrix 
+int typesolver=UMFPACK;
+if(HaveUMFPACK) typesolver=GMRES; 
+  set(A,solver=typesolver); // set a solver 
+
+VH<complex> uH=0;
+Vh<complex> uh=x+y+1i*(x-y);
+uH[]= B*uh[];
+Vh uHr = imag(uH);
+plot(uHr,wait=1);
+matrix<complex> BtA = BB'*A;//';
+matrix<complex> BtAB = BtA*BB;
+if(HaveUMFPACK)  
+  set(BtAB,solver=UMFPACK);  
+ else 
+  set(BtAB,solver=GMRES);  
+  Vh<complex> ff=1+1i;
+Vh<complex> xx;
+Vh xxr;
+cout << " ------ " << endl;
+
+xx[]=BtAB^-1*ff[];
+cout << " ------ " << endl;
+xx[]=BtAB^-1*ff[];
+cout << " ------ " << endl;
+xxr=imag(xx);
+plot(xxr, wait=1);
+
+{
+  int N=10;
+  complex [int,int] A(N,N);
+  complex [int] a(N),b(N),bb(N);
+  A =0;
+  for (int i=0;i<N;i++)
+    {
+      A(i,i)=1.+i;
+      if(i+1 < N)    A(i,i+1)=-i-1i*i;
+      a[i]=i*(1.+2i);
+    }
+  b=A*a;
+  
+  cout << " b =" << b << endl ;
+  cout << " a =" << a << endl ;
+  cout << " b'*b (hermissian product) = " << b'*b << endl; //';
+  cout << " a'*a = " << a'*a << endl;//';;
+  assert( abs(imag(b'*b)) <1e-5);//')));
+  cout << "xxxx\n"; 
+  matrix<complex> sparseA=A;
+  
+  cout << sparseA << endl;
+  sparseA = 2*sparseA+sparseA;
+  sparseA = 4*sparseA+sparseA*(5+1i); //  * 27
+  matrix<complex> sparseB=sparseA;//+sparseA+sparseA; ;
+  cout << sparseA << endl;
+  cout << sparseB << endl; // *81 
+  cout << "sparseB = " << sparseB(0,0) << endl;
+  // ajoute version  2.0-2
+  sparseA=A;
+  verbosity=4;
+  if(HaveUMFPACK)		
+    set(sparseA,solver=UMFPACK,tolpivot=1e-10,tolpivotsym=1e-9);  
+  else 
+    set(sparseA,solver=GMRES);  
+  bb=sparseA^-1*a;
+  verbosity=1;
+  b = sparseA*bb;
+  b -= a;
+  cout << " nb coef sparseA " << sparseA.nbcoef << endl; 
+  cout << " ||b.||_1  " << b.l1 << endl;
+  cout << " ||b.||_2  " << b.l2 << endl;
+  cout << " ||b.||_infty  " << b.linfty << endl;
+  assert(b.l1 < 1e-10);
+}
+{// version 3.8    
+  mesh Th=square(2,2);
+  fespace Xh(Th,P1);
+  varf vv(u,v)= int2d(Th)( ((2+1i)*u*v)')+int2d(Th)((3+2i)*v);//');
+  varf vr(u,v)= int2d(Th)( u*v);//');
+
+  matrix<complex> A=vv(Xh,Xh);
+  matrix  Ar=vr(Xh,Xh);
+  complex[int] vc=vv(0,Xh);
+  real[int] vrr=vc.re,vii=vc.im;
+  vrr=vc.re;
+  vii=vc.im;
+  cout << "vc[0] = " <<vc[0] << " = " << vc.re[0] << " +i " << vc.im[0] <<endl;
+  cout << [ 1i, 1i]'*[ 1i, 1i] <<endl;//'; 
+  // real part un complex par of matrix . 
+  Ar = A.re;
+  cout <<" A(0,0) = " << A(0,0)  << "   ";
+  cout << " A.re(0.0) = " << Ar(0,0) << "   " ;
+  Ar = A.im; 
+  cout << " A.im(0.0) = " << Ar(0,0) << endl  ;
+
+  
+  macro Grada(u) [  phia*dx(u) + phiax*u ,dy(u) ]// ...
+    func phia = exp(-2i*pi*x);
+  func phiax = -2i*pi*exp(-2i*pi*x);
+
+  varf va(u,v)= int2d(Th)( Grada(v)'*Grada(u) ) ;//');
+  A = va(Xh,Xh);
+  matrix<complex> At=A';
+  cout << A(1,2)' << " ==  " << At(2,1) << endl;
+  A = A+ (-1)*At;
+  cout << A << endl;
+  // copy and initialisation of complex matric with real matrix. 
+ A = Ar; 
+ matrix<complex> Ac=Ar; 
+
+
+
+}
+}
\ No newline at end of file
diff --git a/examples++-tutorial/sparse-matrix.edp b/examples++-tutorial/sparse-matrix.edp
new file mode 100644
index 0000000..23e4ead
--- /dev/null
+++ b/examples++-tutorial/sparse-matrix.edp
@@ -0,0 +1,244 @@
+//  sparse matrix test  ---
+// example of the new matrix feature in version 1.40
+// -------------------------------------------------
+for(int step=0; step<2; ++step) // make to time the test to find memoire leak ..
+{ 
+mesh  TH = square(3,4);
+mesh  th = square(2,3);
+mesh  Th = square(4,4);
+
+
+fespace VH(TH,P1);
+fespace Vh(th,P1);
+fespace Wh(Th,P1);
+
+matrix B= interpolate(VH,Vh);  // build interpolation matrix Vh->Vh 
+matrix BB= interpolate(Wh,Vh);  // build interpolation matrix
+varf vA(u,v) = int2d(Th)(dx(u)*dx(v)+dy(u)*dy(v))+ int1d(Th)(u*v); 
+matrix A=vA(Wh,Wh);
+
+
+
+Vh ml=0;
+varf vML(u,v) = int2d(th)(1*v);
+ml[]=vML(0,Vh); // build the P1 mass lump of P1
+cout << ml[] << endl;
+matrix ML(ml[]); // matrix diagonal
+cout << "ML="<<ML << endl;
+cout << "B="<<B << endl;
+matrix BML=B*ML;
+matrix tB=B';        //'; transpose 
+//cout << "tB=" << tB << endl;
+matrix MLtB=ML'*B'; // 
+
+//cout << "BML="<<BML << endl;
+//cout << "MLtB=" << MLtB << endl;
+
+// WARNING if UMFPACK is not install
+// the UMFPACK solver is replace by LU 
+//  but LU need skyline matrix 
+if(HaveUMFPACK)
+  set(A,solver=UMFPACK); // set a solver 
+ else 
+   set(A,solver=GMRES); // set a solver 
+VH uH=0;
+Vh uh=x+y;
+uH[]= B*uh[];
+plot(uH,wait=1);
+matrix BtA = BB'*A;//';
+matrix BtAB = BtA*BB;
+if(HaveUMFPACK)  
+  set(BtAB,solver=UMFPACK);  
+ else 
+   set(BtAB,solver=GMRES);  
+Vh ff=1;
+Vh xx;
+cout << " ------ " << xx[].n << " = " << BtAB.n << "x" << BtAB.m << " " << ff[].n <<  endl;
+
+xx[]=BtAB^-1*ff[];
+cout << " ------ " << endl;
+xx[]=BtAB^-1*ff[];
+cout << " ------ " << endl;
+plot(xx, wait=1);
+
+{
+  int N=10;
+  real [int,int] A(N,N);
+  real [int] a(N),b(N),c(N);
+  int [int] II(N);
+  int [int] JJ(N);
+  int [int] III(N);
+  int [int] JJJ(N);
+  for (int i=0;i<N;i++)
+    {
+      II(i)=i*2;
+      III(i)=(i*1023)%N;
+      JJJ(i)=(i*7)%N;
+      JJ(i)=20-i;
+    }	
+  A =0;
+  for (int i=0;i<N;i++)
+    {
+      A(i,i)=1+i;
+      if(i+1 < N)    A(i,i+1)=-i;
+      a[i]=i;
+    }
+  b=a(III);  //  b(i)=a(iii(i))
+  c(III)=a;  //  c(III(i)) = a(i)
+  cout << " III = " << III << endl;
+  cout << " a(III)     " <<  b << endl;
+  cout << " a(III^1) = " << c  << endl;
+  for (int i=0;i<N;i++)
+    assert( int(c[int(b[i])]) == i);
+  
+  matrix sA=A;
+  {
+    {
+      ofstream ff("A.matrix");
+      ff  << sA; 
+    }
+    matrix ssA;
+    {
+      ifstream ff("A.matrix");
+      ff >> ssA;
+      ssA = (1.)*sA+ (-1.)*ssA;
+      cout  << ssA << endl; 
+    }
+  }
+  
+  matrix tAA=sA+sA';//';
+  matrix ttAA=sA'+sA;//';
+  // matrix tttAA=sA'-sA;
+  // matrix ttAA=sA'-sA;
+  A += 2*a*a';  //'//  produit tensoriel
+  matrix A1=   A(II^-1,JJ^-1);   //  do A1(II(i),JJ(j)) = A(i),j) $
+  matrix A2=   A(III,JJJ);   //  do   $A2(i,j) = A(III(i),JJJ(i)) $
+  matrix sA1=   sA(II^-1,JJ^-1); //  do A1(II(i),JJ(i)) = A( 
+  matrix sA2=   sA(III,JJJ);   //  do A = A 
+  
+  matrix A0 = (a*a')(II^-1,JJ^-1); //');
+  matrix A3 = (a*a')(III,JJJ);//');
+  
+  cout << " ------------------- " << endl;
+  // cout <<  " A  = " << A << endl;
+  // cout <<  " A1 = " << A1 <<endl;
+  cout << " 8,9 -> " <<II[8] << " " <<  JJ[9] <<" " << A(9,8)<< " " << A1(II[9],JJ[8]) << endl;
+  assert(A(9,1) == 2*a[9]*a[1]);  
+  
+  for (int i9=0;i9<N;++i9)
+    for (int j9=0;j9<N;++j9)
+      {
+	
+	if( abs(A(j9,i9))> 0.01) 
+	  assert(A1(II[j9],JJ[i9]) == A(j9,i9));
+	if( abs(A(III(j9),JJJ(i9))) > 0.01) 
+	  assert(A2(j9,i9) == A(III(j9),JJJ(i9) )) ;
+	//     cout << " i9,j9 -> " <<II[i9] << " " <<  JJ[j9] <<endl;
+	if( abs(a[i9]*a[j9])> 0.01) 
+	  assert(A0(II[i9],JJ[j9]) == a[i9]*a[j9]);
+	if( abs(a[III[i9]]*a[JJJ[j9]])> 0.01) 
+	  assert(A3(i9,j9) == a[III[i9]]*a[JJJ[j9]]);
+      }
+  b=A*a;
+  c=-9;
+  cout << "xxxx\n"; 
+  matrix sparseA=A;
+  //cout << sparseA << endl;
+  sparseA = 2*sparseA+sparseA;
+  sparseA = 4*sparseA+sparseA*5; //  * 27
+  matrix sparseB=sparseA+sparseA+sparseA; ;
+  //cout << sparseA << endl;
+  //cout << sparseB << endl; // *81 
+  cout << "sparseB = " << sparseB(0,0) << endl;
+  
+  cout << " -------- block matrix \n " << endl;
+  matrix B = [ [sparseA, 0 , sparseA ], 
+               [ 0, sparseA , 0 ] ,
+               [0, 0, sparseB' ]];//']];
+  matrix B2 = [ [sparseA], [sparseA]];
+  
+  assert( B2.n == sparseA.n*2);
+  assert( B2.m == sparseA.m);
+  
+  matrix B1 = [ [sparseA, sparseA] ];
+  assert( B1.m == sparseA.m*2); // FH. bug before version  2.11-4 (10/01/2007)
+  assert( B1.n == sparseA.n);
+  
+  
+  real[int] x([a,b,c]); //  construct the block vector x form a,b,c,
+  //  where the size is  sum of size of a,b,c, 
+  x=[a,b,c]; // set x to to the block vector (the vector x is  resize if it necessary
+  cout << " abc =" << a[2] << " " << b[3] << " "<< c[4] << endl;
+  cout << " xxx =" << x[2] << " " << x[3+N] << " "<< x[4+N*2] << endl;
+  x = x*10;
+  [a,b,c]=x; // set the block vector a,b,c  from concecutive part of  x;
+  cout << " abc*10 == "  << a[2] << " " << b[3] << " "<< c[4] << endl;
+  
+  
+  // remark  the size of sum of size must be equal to the size of x.  
+  //cout << " B = " << B << endl; 
+  cout << B(8,29) << " ===  " <<  sparseA(8,9) << endl;
+  cout << B(28,27)
+       << " ===  " <<  sparseB(7,8) << endl;
+  B(8,29)=100;  // change the value an existing coef 
+  cout << " B(8,29) " <<  B(8,29) << endl;
+  cout << " -------- block matrix \n " << endl;
+}
+//  build FE  matrice with differente meshes (here 3) 
+varf vM(u,v)=int1d(Th,qforder=1)(u*v);
+matrix MM=vM(Vh,VH);
+//cout << MM << endl;
+Vh unVh=0,wVh=0;
+VH unVH=0,wVH=0;
+unVh[]=1;
+unVH[]=1;
+wVh[] = MM' * unVH[] ; //'
+wVH[] = MM * unVh[] ; 
+
+//cout << "wWh : " << wVh[] << endl;
+//cout <<" wVH : " << wVH[] << endl;
+// array of matrix v2.4-1 
+cout << " array of matrix   \n" ;
+matrix[int]  aM(10);
+aM[0]= MM;
+aM[3]= MM;
+aM[9]= MM;
+// aM.resize(4);
+//  aM.resize(10);  bug on debian ? FH 
+
+//  add version 2.17 --- 
+{
+  real[int] coef([1,2,3,5,6]);
+  int[int]  lg(  [1,3,6,9,100]);
+  int[int]  cl(  [1,4,9,0,0]);
+  
+  // a diagonal matrix
+  matrix A=[coef];
+  cout << " A = " << A << endl;
+  // a raw matrix  
+  matrix B=[lg,cl,coef];
+  cout << " B = " << B << endl;
+  [lg,cl,coef] = A; 
+  cout<< " lg    : "  << lg << endl;
+  cout << " cl   : " << cl << endl;
+  cout << " coef = "<< coef << endl;
+  
+}
+
+// version 3.1-1
+cout << MM << endl;
+MM.resize(10,100);
+cout << MM << endl;
+
+{  //  test renumbering of sub mesh ..
+  func Pk=P2;
+  int[int] n2ok(1); 
+  mesh ThC = trunc(Th,x < 0.5,new2old=n2ok);
+  fespace VFh(Th,Pk);
+  fespace VCh(ThC,Pk);
+  verbosity= 100; 
+  int[int] n2o=restrict(VCh,VFh,n2ok);
+  cout << " n2o " << n2o << endl;
+  
+}
+}
\ No newline at end of file
diff --git a/examples++-tutorial/sphere.edp b/examples++-tutorial/sphere.edp
new file mode 100644
index 0000000..01dffbe
--- /dev/null
+++ b/examples++-tutorial/sphere.edp
@@ -0,0 +1,40 @@
+mesh Th=square(10,20,[x*pi-pi/2,2*y*pi]);  //  $]\frac{-pi}{2},frac{-pi}{2}[\times]0,2\pi[ $
+//  a paratrization of a sphere 
+func f1 =cos(x)*cos(y);
+func f2 =cos(x)*sin(y);
+func f3 = sin(x);
+//  de  partiel derivatrive of the parametrization DF
+func f1x=sin(x)*cos(y);   
+func f1y=-cos(x)*sin(y);
+func f2x=-sin(x)*sin(y);
+func f2y=cos(x)*cos(y);
+func f3x=cos(x);
+func f3y=0;
+// $  M = DF^t DF $
+func m11=f1x^2+f2x^2+f3x^2;
+func m21=f1x*f1y+f2x*f2y+f3x*f3y;
+func m22=f1y^2+f2y^2+f3y^2;
+
+func perio=[[4,y],[2,y],[1,x],[3,x]];  // to store the periodic condition 
+
+// the intial mesh
+savemesh(Th,"sphere",[f1,f2,f3]);
+
+real hh=0.1;
+real vv= 1/square(hh);
+verbosity=2;
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,inquire=1,periodic=perio);
+plot(Th,wait=1);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+plot(Th,wait=1);
+Th=adaptmesh(Th,m11*vv,m21*vv,m22*vv,IsMetric=1,periodic=perio);
+load "msh3" load "medit" 
+//savemesh(Th,"sphere-a",[f1,f2,f3]);
+plot(Th,wait=1);
+mesh3 Th3= movemesh23(Th,transfo=[f1,f2,f3]);
+plot(Th3,wait=1); 
+medit("sphere-a",Th3);// bug un color of u ... FH 
+
+//exec("ffmedit sphere-a");
diff --git a/examples++-tutorial/string.edp b/examples++-tutorial/string.edp
new file mode 100644
index 0000000..c3474ff
--- /dev/null
+++ b/examples++-tutorial/string.edp
@@ -0,0 +1,70 @@
+//  bug string macro parameter   version < 1.41
+// bug in string parameter version before <2.5
+// -----------------
+
+ macro tyty(uu) uu//  
+cout << tyty("toto") << endl;
+
+func string   write(string  fn,real[int] & u)
+{
+  cout <<"write :   " <<  fn << " u = "<<  u << endl;  //  delete 2 times before version 2.5 
+  return fn; 
+}
+
+func string   write1(string  fn,real[int] & u)
+{
+  cout << "write 1 " << fn << " u = " << u << endl;   
+  string toto=fn; ;
+  return toto+"dfsdf"; 
+}
+
+real[int] u(3);
+u=1;
+
+string tt=tyty("toto1"+1+" -- 77");
+
+string t1="0123456789";// write(tt,u);
+
+string t2;
+
+
+  {
+    t2=  write1(t1,u)+write1(tt,u); // 
+    // because the local variable of write1 are  delete 2 times at the  ;
+    cout << " t2 = " << t2 << endl;
+  }
+if(0)
+   { // the correct way
+     t2=  write1(t1,u);
+     t2=t2 + write1(tt,u); 
+    cout << " t2 = " << t2 << endl;
+   }
+// new operator
+t2 ="12340005678";
+t2(4:3) = "abcdefghijk-"; 
+string t55=t2(4:3);
+//t2 = "12340abcdefghijk-005678";
+cout << t2 << endl;
+cout << "  find abc " << t2.find("abc") << endl;
+cout << "r find abc " << t2.rfind("abc") << endl;
+cout << " find abc from 10  " << t2.find("abc",10) << endl;
+cout << " ffind abc from 10 " <<t2.rfind("abc",10) << endl;
+cout << "   " << string("abcc").length << endl; 
+cout << " t55 " << t55 << endl;
+{  // add getline version 3.0-6 jan 2009 FH
+string s;
+ifstream toto("xyf");
+for (int i=0;i<10;++i)
+  {
+   getline(toto,s);
+   cout << i << " : " << s << endl;
+  }
+}
+// add  3.29 + Stringification, LINE, FILE, ltime ..
+
+macro aa()  "tyty"  //
+cout << aa << endl; 
+cout << "in " << FILE << " line " << LINE << "    -- '" << Stringification( "zzz" aa  () {} +  /* */  bb cc) << "'" << endl;
+cout << " unix time = " << time() << " " << ltime() << endl;
+
+ 
diff --git a/examples++-tutorial/tablefunction.edp b/examples++-tutorial/tablefunction.edp
new file mode 100644
index 0000000..8935d88
--- /dev/null
+++ b/examples++-tutorial/tablefunction.edp
@@ -0,0 +1,21 @@
+verbosity=2;
+mesh Thxy=triangulate("xyf");
+plot(Thxy,wait=1,ps="Thxy.ps");
+fespace Vhxy(Thxy,P1);
+Vhxy fxy;
+
+{ ifstream file("xyf");
+   real xx,yy;
+   for(int i=0;i<fxy.n;i++)
+   file >> xx >>yy >> fxy[][i]; 
+}
+
+plot(fxy,wait=1,ps="xyf.ps");
+
+// new way to bluid a mesh   version 2.23-2
+Vhxy xx=x,yy=y;
+
+mesh Th=triangulate(xx[],yy[]);
+cout << " region = " <<  triangulate(xx[],yy[])[1].region  <<endl; 
+cout << fxy[]'*fxy[] << endl;
+plot(Th,wait=1); 
diff --git a/examples++-tutorial/taboftab.edp b/examples++-tutorial/taboftab.edp
new file mode 100644
index 0000000..8107712
--- /dev/null
+++ b/examples++-tutorial/taboftab.edp
@@ -0,0 +1,34 @@
+// version 3.18-2 ...
+real[int] a,b(10);
+a.resize(b.n); // `
+a=b;  
+a=[1,2];
+a.resize(5); //  Pas init a voir ??? 
+cout << "a="<<a << endl;
+real[int,int][int] m(10);
+real[int][int] v(10);
+for(int i=0;i<v.n;++i)
+{
+  v[i].resize(i+1);
+  for(int j=0;j<v[i].n;++j)
+    v[i][j] = 100*i + j;   
+}
+
+cout << " v = " << v << endl;
+v.resize(4);
+cout << " v = " << v << endl;
+v.resize(10);
+cout << " v = " << v << endl;
+
+// test sub array of full matrix ... 
+real[int,int] A(10,5);
+for(int i=0;i<A.n;++i)
+for(int j=0;j<A.m;++j)
+  A(i,j)=i*100+j;
+
+cout << " A( 2:4,1:2) =" << A( 2:4,1:2) << endl;
+cout << " A( 2,1:2) =" << A( 2,1:2) << endl;
+cout << " A( 1:3,1) =" << A( 1:3,1) << endl;
+cout << " A( :,1) =" << A( :,1) << endl;
+cout << " A( :,1).sum =" << A( :,1).sum << endl;
+cout << " A( :,1).min =" << A( :,1).min << endl;
diff --git a/examples++-tutorial/thermic-fast.edp b/examples++-tutorial/thermic-fast.edp
new file mode 100755
index 0000000..c0aec16
--- /dev/null
+++ b/examples++-tutorial/thermic-fast.edp
@@ -0,0 +1,45 @@
+// file thermal-fast.edp    same problem than thermal.edp
+
+func fu0 =10+90*x/6;
+func k = 1.8*(y<0.5)+0.2;
+real ue = 25. , alpha=0.25, T=5, dt=0.1 ;
+
+mesh Th=square(30,5,[6*x,y]);
+fespace Vh(Th,P1);
+
+Vh u0=fu0,u=u0;
+
+varf vthermic (u,v)= int2d(Th)(u*v/dt + k*(dx(u) * dx(v) + dy(u) * dy(v)))  
+  +  int1d(Th,1,3)(alpha*u*v)
+  + on(2,4,u=1); 
+
+varf vthermic0(u,v) =   int1d(Th,1,3)(alpha*ue*v);
+
+varf vMass (u,v)= int2d(Th)( u*v/dt)  + on(2,4,u=1);
+
+real tgv = 1e30;
+matrix A= vthermic(Vh,Vh,tgv=tgv,solver=CG);
+matrix M= vMass(Vh,Vh);
+
+
+real[int]  b0  = vthermic0(0,Vh); // constant part of the RHS 
+real[int]  bcn = vthermic(0,Vh); //  tgv on Dirichlet boundary  node  ( !=0 )
+// we have for the node $i$ : $i\in \Gamma_{24}  \quad \Leftrightarrow \quad bcn[i] \ne 0 $ 
+real[int]  bcl=tgv*u0[]; //  the Dirichlet boundary condition part 
+
+
+ofstream ff("thermic.dat");
+for(real t=0;t<T;t+=dt){
+    real[int] b = b0 ; // for  the  RHS
+    b += M*u[]; //  add the the time dependant part
+    // to lock boundary 2,4 part:
+    b = bcn ? bcl  : b ; // do $\forall i$:  b[i] =  bcn[i] ? bcl[i] : b[i]  ;      
+    u[] = A^-1*b;    
+    ff<< t << " " << u(3,0.5) <<endl;
+    plot(u);
+}
+for(int i=0;i<20;i++) 
+  cout<<dy(u)(6.0*i/20.0,0.9)<<endl;
+plot(u,fill=true,wait=1,ps="thermic.eps");
+
+
diff --git a/examples++-tutorial/uniformmesh.edp b/examples++-tutorial/uniformmesh.edp
new file mode 100644
index 0000000..b80f0e5
--- /dev/null
+++ b/examples++-tutorial/uniformmesh.edp
@@ -0,0 +1,9 @@
+mesh Th=square(2,2);
+plot(Th,wait=1,ps="square-0.eps");
+Th= adaptmesh(Th,1./30.,IsMetric=1,nbvx=10000);// \index{mesh!uniforme}
+plot(Th,wait=1,ps="square-1.eps");
+Th= adaptmesh(Th,1./30.,IsMetric=1,nbvx=10000);//  more the one time du to
+Th= adaptmesh(Th,1./30.,IsMetric=1,nbvx=10000);//  adaptation  bound \texttt{maxsubdiv=}
+plot(Th,wait=1,ps="square-2.eps");
+
+
diff --git a/examples++-tutorial/xyf b/examples++-tutorial/xyf
new file mode 100644
index 0000000..d0c699d
--- /dev/null
+++ b/examples++-tutorial/xyf
@@ -0,0 +1,100 @@
+0.51387 0.175741 0.636237
+0.308652 0.534534 0.746765
+0.947628 0.171736 0.899823
+0.702231 0.226431 0.800819
+0.494773 0.12472 0.580623
+0.0838988 0.389647 0.456045
+0.277226 0.368071 0.601435
+0.983437 0.535398 0.99865
+0.765682 0.646473 0.987443
+0.767139 0.780237 0.999726
+0.822951 0.151932 0.827637
+0.625477 0.314685 0.807653
+0.346901 0.917204 0.953338
+0.51976 0.401154 0.796155
+0.606758 0.785402 0.984087
+0.931523 0.869921 0.973519
+0.866525 0.67452 0.999557
+0.7584 0.581893 0.973552
+0.389248 0.355635 0.677885
+0.200232 0.826927 0.855833
+0.415903 0.463522 0.770373
+0.979163 0.126436 0.893733
+0.212637 0.958451 0.921175
+0.737463 0.409056 0.911337
+0.780113 0.757899 0.999463
+0.956842 0.028096 0.833238
+0.318728 0.756934 0.879905
+0.242995 0.589542 0.739641
+0.0434244 0.956025 0.841173
+0.319133 0.0593598 0.369521
+0.441876 0.91502 0.97721
+0.572247 0.118838 0.637374
+0.569771 0.252048 0.732386
+0.495858 0.236734 0.668799
+0.476961 0.406093 0.772681
+0.872998 0.426963 0.963548
+0.358218 0.381988 0.67444
+0.0431799 0.160587 0.20236
+0.522351 0.696581 0.938732
+0.0971005 0.400847 0.477623
+0.773432 0.244827 0.851195
+0.342824 0.229994 0.542003
+0.297877 0.304546 0.566641
+0.887207 0.0366694 0.797944
+0.651147 0.398606 0.867301
+0.676297 0.732578 0.986919
+0.937797 0.23328 0.92117
+0.838481 0.96721 0.972539
+0.778638 0.431518 0.935671
+0.674103 0.809358 0.996189
+0.158765 0.279899 0.42473
+0.135323 0.864187 0.841206
+0.750185 0.207999 0.818148
+0.139963 0.294589 0.421005
+0.802806 0.218934 0.853017
+0.563082 0.715602 0.957638
+0.197542 0.989825 0.927387
+0.250038 0.430608 0.629295
+0.755274 0.860929 0.998969
+0.894781 0.978088 0.954722
+0.395412 0.432205 0.73632
+0.12714 0.457675 0.552045
+0.237831 0.986032 0.94042
+0.652831 0.604246 0.951192
+0.241906 0.454873 0.641751
+0.78996 0.0788191 0.763541
+0.47641 0.152588 0.588335
+0.245752 0.944993 0.928646
+0.61402 0.988186 0.999507
+0.477276 0.799684 0.95714
+0.744184 0.380735 0.902233
+0.479891 0.526908 0.845125
+0.0980991 0.594211 0.638317
+0.347183 0.143366 0.47111
+0.77954 0.710997 0.996781
+0.446139 0.704569 0.913053
+0.0953091 0.962825 0.871442
+0.551302 0.740264 0.961268
+0.579039 0.637876 0.938035
+0.781656 0.187904 0.824637
+0.302103 0.282807 0.552124
+0.684006 0.292919 0.82878
+0.565391 0.418449 0.83263
+0.306581 0.44453 0.682451
+0.56569 0.487929 0.869218
+0.606633 0.41586 0.85341
+0.130424 0.25596 0.376841
+0.0357581 0.977097 0.848347
+0.114506 0.378054 0.472883
+0.646711 0.350446 0.839931
+0.553049 0.358411 0.790399
+0.565451 0.475635 0.862953
+0.163682 0.615225 0.702501
+0.17217 0.554712 0.664543
+0.292231 0.872162 0.918548
+0.835062 0.844895 0.994048
+0.895509 0.594763 0.99676
+0.540566 0.168211 0.650906
+0.654958 0.690519 0.974723
+0.263855 0.106692 0.362125
diff --git a/examples++/._NSP1P2.edp b/examples++/._NSP1P2.edp
new file mode 100644
index 0000000..f7a8f68
Binary files /dev/null and b/examples++/._NSP1P2.edp differ
diff --git a/examples++/D2.edp b/examples++/D2.edp
new file mode 100644
index 0000000..ba1b668
--- /dev/null
+++ b/examples++/D2.edp
@@ -0,0 +1,15 @@
+int n = 40;
+mesh Th=square(n,n,[2*x-1,2*y-1]);
+fespace Xh(Th,P2);
+Xh x2=x^2,y2=y^2,xy=x*y;
+Xh w,ww;
+
+w=dxx(x2); cout << "dxx(x2) " << w[].max << " " << w[].min << endl;
+w=dyy(y2); cout << "dyy(y2) " << w[].max << " " << w[].min << endl;
+w=dyy(xy); cout << "dyy(xy) " << w[].max << " " << w[].min << endl;
+
+w=dxy(xy); cout << "dxy(xy) " << w[].max << " " << w[].min << endl;
+w=dyx(xy); cout << "dyx(xy) " << w[].max << " " << w[].min << endl;
+w=dyx(x2); cout << "dyx(x2) " << w[].max << " " << w[].min << endl;
+//  for regtest 
+real regvalue=int2d(Th)(w*w);
\ No newline at end of file
diff --git a/examples++/FE-medit.edp b/examples++/FE-medit.edp
new file mode 100644
index 0000000..9d791bb
--- /dev/null
+++ b/examples++/FE-medit.edp
@@ -0,0 +1,30 @@
+int n=20,nn=n+10;
+real[int] xx(nn),yy(nn);
+// build square $]-1,1[^2$
+mesh Th2=square(2,2,[2*x-1,2*y-1]); 
+mesh Th=square(100,100,[2*x-1,2*y-1]); 
+fespace Wh(Th2,P0edge);
+Wh w=0;
+
+fespace Vh(Th,P1);
+
+w[]=0;
+w[][6]=1;
+Vh u=w;
+
+plot(u,Th2,wait=1);
+   savemesh(Th,"mm",[x,y,u*.5]); //  save mm.points and mm.faces file for medit
+   // build a mm.bb file 
+	{ ofstream file("mm.bb"); 
+	file << "2 1 1 "<< u[].n << " 2 \n";
+	int j;
+	for (j=0;j<u[].n ; j++)  
+	  file << u[][j] << endl; 
+    }  
+    // call ffmedit command 	
+   if(!NoGraphicWindow) exec("ffmedit mm");
+    // clean files
+    exec("rm mm.bb mm.faces mm.points");
+    
+
+
diff --git a/examples++/Makefile.am b/examples++/Makefile.am
new file mode 100644
index 0000000..da915f0
--- /dev/null
+++ b/examples++/Makefile.am
@@ -0,0 +1,35 @@
+# $Id$
+
+all-local: all.edp regtests.edp freefem++.pref
+
+TESTS=aadaptation.edp aalapacien.edp aalaplace-nc.edp aamove.edp aaRT.edp arrayoFVh.edp bilap.edp D2.edp demo1.edp demo.edp funct.edp lapacienprecon.edp lap_mat.edp NSP1P1b.edp NSP1P1.edp NSP1P2.edp parareal.edp Richard.edp teste.edp testFE.edp wafer-heating-laser-axi.edp
+LOG_DRIVER=$(SHELL) $(top_srcdir)/test-driver-ff
+TESTS_ENVIRONMENT=TEST_FFPP=$(TEST_FFPP) FLAGS_FFPP=-nw
+
+EXTRA_DIST=*.edp all.edp regtests.edp regtests.m4 ref.edp
+
+all.edp:
+	(echo "NoUseOfWait=true;int verbosityy=verbosity;"; \
+	for i in *`ls *.edp|grep -v -E '^(all|regtests|makeref|ref)\.edp$$'` ; do  \
+		echo ' cout << "--------- file : '$$i' --------------------------------------------------------" << endl;' ;\
+		echo "verbosity=verbosityy;" ; \
+		echo \{ include \"$$i\"\;\}\; ;\
+		echo ' cout << "------------------------------------------------------------------------------ " << endl;' ;\
+	done) > $@
+
+# To create a new set of reference values in "ref.edp"
+clean-local:
+	-rm *.fg *.eps *~ *.ps  Th?.faces  Th?.points Th?.BB Th?.mesh.gmsh   ListOf?llocPtr*.bin ffglut*.ppm 	toto.txt
+Ref: makeref.edp
+	../src/nw/FreeFem++-nw makeref.edp
+
+makeref.edp: regtests.m4 ../regtests.m4
+	m4 regtests.m4 > makeref.edp
+freefem++.pref:
+	echo loadpath = \"../examples++-load/\" >freefem++.pref
+	echo loadpath += \"./\" >>freefem++.pref
+
+# To check the scripts against their reference values
+regtests.edp: regtests.m4 ../regtests.m4
+	m4 -DASSERT regtests.m4 > regtests.edp
+FORCE:
diff --git a/examples++/NSP1P1.edp b/examples++/NSP1P1.edp
new file mode 100644
index 0000000..2a951c4
--- /dev/null
+++ b/examples++/NSP1P1.edp
@@ -0,0 +1,66 @@
+// correct pressure sign 
+real s0=clock();
+mesh Th=square(10,10);
+fespace Vh2(Th,P1);
+fespace Vh(Th,P1);
+Vh2 u2,v2,up1,up2;
+Vh2 u1,v1; 
+Vh  u1x=0,u1y,u2x,u2y, vv;
+problem Pu1(u1x,vv,solver=CG) = int2d(Th)( u1x*vv) + int2d(Th)(-vv*u1);
+problem Pu2(u2x,vv,solver=CG) = int2d(Th)( u2x*vv) + int2d(Th)(-vv*u2);
+
+up1=0;
+up2=0; 
+func g=(x)*(1-x)*4; 
+Vh p=0,q;
+real alpha=0;
+real  nu=1;
+int i=0,iter=0;
+real dt=0;
+solve NS (u1,u2,p,v1,v2,q,solver=Crout,init=i) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +  dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + (dx(p)*dx(q)+dy(p)*dy(q))*(0.00001) // stabilization term
+            - p*dx(v1) - p*dy(v2)
+            - dx(u1)*q - dy(u2)*q
+           )
+  + int2d(Th) ( -alpha*convect([up1,up2],-dt,up1)*v1 -alpha*convect([up1,up2],-dt,up2)*v2 )
+  + on(3,u1=g,u2=0) 
+  + on(1,2,4,u1=0,u2=0) ;
+plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],value=1);
+
+dt = 0.1;
+int nbiter = 3;
+real coefdt = 0.25^(1./nbiter);
+real coefcut = 0.25^(1./nbiter) , cut=0.4;
+real tol=0.8,coeftol = 0.5^(1./nbiter);
+nu=0.01;   
+
+for (iter=0;iter<nbiter;iter++)
+{
+  cout << " dt = " << dt << " ------------------------ " << endl;
+  alpha=1/dt;
+  for (i=0;i<=10;i++)
+   {
+     up1=u1;
+     up2=u2;
+     NS;
+     if ( !(i % 10)) 
+     plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="plotNS_"+iter+"_"+i+".eps",value=1);  
+     cout << "CPU " << clock()-s0 << "s " << endl;     
+   } 
+ 
+  if (iter>= nbiter) break;
+ 
+  u1x=0;u1y=0;
+  Pu1;Pu2;
+  plot([u1x,u2x],wait=1);
+  Th=adaptmesh(Th,[u1x,u2x],abserror=0,cutoff=cut,err=tol, inquire=0);
+  plot(Th);
+  dt = dt*coefdt;
+  tol = tol *coeftol;
+  cut = cut *coefcut;
+}
+cout << "CPU " << clock()-s0 << "s " << endl;     
diff --git a/examples++/NSP1P1b.edp b/examples++/NSP1P1b.edp
new file mode 100644
index 0000000..7964ab4
--- /dev/null
+++ b/examples++/NSP1P1b.edp
@@ -0,0 +1,76 @@
+// remark: the sign of p is correct 
+real s0=clock();
+mesh Th=square(20,20);
+  Th=adaptmesh(Th,1./20.,IsMetric=1,splitpbedge=1);
+fespace Vh2(Th,P1b);
+fespace Vh(Th,P1);
+Vh2 u2,v2,up1,up2;
+Vh2 u1,v1; 
+Vh  u1x=0,u1y,u2x,u2y, vv;
+
+real reylnods=400;
+//cout << " Enter the reynolds number :"; cin >> reylnods;
+assert(reylnods>1 && reylnods < 100000); 
+up1=0;
+up2=0; 
+func g=(x)*(1-x)*4; 
+Vh p=0,q;
+real alpha=0;
+real  nu=1;
+int i=0,iter=0;
+real dt=0;
+solve NS ([u1,u2,p],[v1,v2,q],solver=Crout,init=i) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +        dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            - p*dx(v1) - p*dy(v2)
+            - dx(u1)*q - dy(u2)*q
+           )
+  + int2d(Th) ( -alpha*convect([up1,up2],-dt,up1)*v1 -alpha*convect([up1,up2],-dt,up2)*v2 )
+  + on(3,u1=g,u2=0) 
+  + on(1,2,4,u1=0,u2=0) ;
+plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="StokesP2P1.eps",value=1,wait=1);
+{
+  real[int] xx(21),yy(21),pp(21);
+  for (int i=0;i<21;i++)
+   {
+     yy[i]=i/20.;
+     xx[i]=u1(0.5,i/20.);
+     pp[i]=p(i/20.,0.999);
+    }
+      cout << " " << yy << endl;
+     plot([xx,yy],wait=1,cmm="u1 x=0.5 cup");
+     plot([yy,pp],wait=1,cmm="pressure y=0.999 cup");
+}
+
+dt = 0.05;
+int nbiter = 3;
+real coefdt = 0.25^(1./nbiter);
+real coefcut = 0.25^(1./nbiter) , cut=0.01;
+real tol=0.5,coeftol = 0.5^(1./nbiter);
+nu=1./reylnods;   
+
+for (iter=1;iter<=nbiter;iter++)
+{
+  cout << " dt = " << dt << " ------------------------ " << endl;
+  alpha=1/dt;
+  for (i=0;i<=50;i++)
+   {
+     up1=u1;
+     up2=u2;
+     NS;
+     if ( !(i % 10)) 
+     plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="plotNS_"+iter+"_"+i+".eps");  
+     cout << "CPU " << clock()-s0 << "s " << endl;     
+   } 
+ 
+  if (iter>= nbiter) break;
+   Th=adaptmesh(Th,[dx(u1),dy(u1),dx(u1),dy(u2)],splitpbedge=1,abserror=0,cutoff=cut,err=tol, inquire=0,ratio=1.5,hmin=1./1000);
+  plot(Th,ps="ThNS.eps");
+  dt = dt*coefdt;
+  tol = tol *coeftol;
+  cut = cut *coefcut;
+}
+cout << "CPU " << clock()-s0 << "s " << endl;     
diff --git a/examples++/NSP1P2.edp b/examples++/NSP1P2.edp
new file mode 100644
index 0000000..3ed1be9
--- /dev/null
+++ b/examples++/NSP1P2.edp
@@ -0,0 +1,77 @@
+// remark: the sign of p is correct 
+real s0=clock();
+mesh Th=square(10,10);
+fespace Vh2(Th,P2);
+fespace Vh(Th,P1);
+Vh2 u2,v2,up1,up2;
+Vh2 u1,v1; 
+Vh  u1x=0,u1y,u2x,u2y, vv;
+
+real reylnods=1000;
+//cout << " Enter the reynolds number :"; cin >> reylnods;
+assert(reylnods>1 && reylnods < 100000); 
+up1=0;
+up2=0; 
+func g=(x)*(1-x)*4; 
+Vh p=0,q;
+real alpha=0;
+real  nu=1;
+int i=0,iter=0;
+real dt=0;
+solve NS ([u1,u2,p],[v1,v2,q],solver=Crout,init=i) =
+    int2d(Th)(
+             alpha*( u1*v1 + u2*v2) 
+            + nu * ( dx(u1)*dx(v1) + dy(u1)*dy(v1)
+            +        dx(u2)*dx(v2) + dy(u2)*dy(v2) )
+            + p*q*(0.000001) 
+            - p*dx(v1) - p*dy(v2)
+            - dx(u1)*q - dy(u2)*q
+           )
+  + int2d(Th) ( -alpha*convect([up1,up2],-dt,up1)*v1 -alpha*convect([up1,up2],-dt,up2)*v2 )
+  + on(3,u1=g,u2=0) 
+  + on(1,2,4,u1=0,u2=0) ;
+plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="StokesP2P1.eps",value=1,wait=1);
+{
+  real[int] xx(21),yy(21),pp(21);
+  for (int i=0;i<21;i++)
+   {
+     yy[i]=i/20.;
+     xx[i]=u1(0.5,i/20.);
+     pp[i]=p(i/20.,0.999);
+    }
+      cout << " " << yy << endl;
+     plot([xx,yy],wait=1,cmm="u1 x=0.5 cup");
+     plot([yy,pp],wait=1,cmm="pressure y=0.999 cup");
+}
+
+dt = 0.1;
+int nbiter = 5;
+real coefdt = 0.25^(1./nbiter);
+real coefcut = 0.25^(1./nbiter) , cut=0.01;
+real tol=0.5,coeftol = 0.25^(1./nbiter);
+nu=1./reylnods;   
+
+for (iter=1;iter<=nbiter;iter++)
+{
+  cout << " dt = " << dt << " ------------------------ " << endl;
+  alpha=1/dt;
+  for (i=0;i<=50;i++)
+   {
+     up1=u1;
+     up2=u2;
+     NS;
+     if ( !(i % 10)) 
+     plot(coef=0.2,cmm=" [u1,u2] et p  ",p,[u1,u2],ps="plotNS_"+iter+"_"+i+".eps");  
+     cout << "CPU " << clock()-s0 << "s " << endl;     
+   } 
+ 
+  if (iter>= nbiter) break;
+ 
+  Th=adaptmesh(Th,[dx(u1),dy(u1),dx(u1),dy(u2)],
+              abserror=0,cutoff=cut,err=tol, inquire=0,ratio=1.5,hmin=1./1000);
+  plot(Th,ps="ThNS.eps");
+  dt = dt*coefdt;
+  tol = tol *coeftol;
+  cut = cut *coefcut;
+}
+cout << "CPU " << clock()-s0 << "s " << endl;     
diff --git a/examples++/Richard.edp b/examples++/Richard.edp
new file mode 100644
index 0000000..5739ee7
--- /dev/null
+++ b/examples++/Richard.edp
@@ -0,0 +1,126 @@
+real Ks=0.01,
+     hg=30,
+     thetas=0.3,
+     eta = 6.55,
+     m = 0.173,
+     n = 2/(1-m);
+     
+     
+real z0=215;
+real q0=15/3600.;
+real dt=60;
+real hmax=0;
+
+// $A(h) - \partial h / \partial t - div(K(h)(\nabla(h-y)) = f $ dans $ \Omega$
+//  -K(h)(\nabla(h-y)). n = q0 $ sur $ \Gamma_1$
+//  h = h_0$ sur $\Gamma_0$
+//  + condition initial $d_d$
+//   A(h) = h <0 ? C(h) : 0; 
+//  
+
+
+// remarque z == y 
+real xmax = 300, ymax=300, x0=60, y0= 215;
+
+border ba(t=0,ymax)   { x=0; y=ymax-t ;label=2;};  // gauche   
+   
+border bb1(t=x0,0)    { x=t; y=ymax ;label=1;};   // haut     1 
+border bb2(t=xmax,x0) { x=t; y=ymax ;label=2;};  // haut   2   
+ 
+border bc1(t=y0,0) { x=xmax; y=ymax-t ;label=2;};  // droite     
+border bc2(t=ymax,y0) { x=xmax; y=ymax-t ;label=3;};  // droite  
+   
+border bd(t=0,xmax)   { x=t; y=0; label=4;};   // bas
+
+int Gamma0=3;
+int Gamma1=1;
+
+int nn=20;
+int nn1=nn*x0/xmax,nn2=nn-nn1;
+int ny1=nn*y0/ymax,ny2=nn-ny1;
+plot(ba(nn)+bb1(nn1)+bb2(nn2)+bc1(ny1)+bc2(ny2)+bd(nn),wait=1);
+mesh Th=buildmesh(ba(nn)+bb1(nn1)+bb2(nn2)+bc1(ny1)+bc2(ny2)+bd(nn));
+plot(Th,wait=1);
+
+fespace Vh(Th,P1);
+Vh h,v,hhh;
+
+macro theta(h) (thetas*(1+((abs(h)/hg))^n)^(-m))//
+macro dtheta(h) (m*n*thetas*(1+((abs(h)/hg))^n)^(-m-1)*(((abs(h)/hg))^(n-1))/hg)
+//
+macro A(h)  ( (h<=0)* dtheta(h) ) 
+//
+macro K(h) (Ks*((h<=0)*((theta(h)/thetas)^eta)+ (h>0)))
+//
+
+Vh hd= -y0+(ymax-y); // bof bof ????
+Vh hn=hd,hh;
+Vh Ahdt,Kh;
+
+int nbiso=20;
+real[int] viso(3+(75+110/2)/5);
+
+{int k=0;
+for(int i=-75;i<0;i+=5)
+ viso(k++)=i;
+ viso(k++)=-0.5;
+ viso(k++)=0.;
+ viso(k++)=0.5;
+for(int i=5;i<=110;i+=5*2)
+ viso(k++)=i;
+}
+/* 
+problem Richard(h,v) =
+  int2d(Th)( Ahdt * h * v+ Kh* (dx(h)*dx(v)+dy(h)*dy(v)) )
+- int2d(Th)( Ahdt* hn*v - Kh* dy(v) )
+- int1d(Th,Gamma1)(q0*v)
++ on(3,h=(ymax-y)-y0)
+;
+*/
+
+real pena=1e10;
+problem Richard(h,v) =
+  int2d(Th)( Ahdt * h * v+ Kh* (dx(h)*dx(v)+dy(h)*dy(v)) )
+- int2d(Th)( Ahdt* hn*v - Kh* dy(v) )
+- int1d(Th,Gamma1)(q0*v)
+ +int1d(Th,3)(pena*h*v)-int1d(Th,3)(pena*((ymax-y)-y0)* v)
+
+;
+
+
+plot(hn,wait=1,cmm=" hd ");
+
+Ahdt=0; Kh=1;
+// Richard;
+// plot(hd,wait=1,cmm="hd ----");
+real temps=0;
+for(int i=0;i<100;i++)
+{
+  string scmm="h + temps "+int(temps)/3600+"h "+ ((temps)%3600/60.) + "mn ";
+  for(int k=0;k<3;k++) 
+  {
+  Kh=K(h);
+  Ahdt=A(h)/dt;
+  
+  cout << " "<< Kh[].min << " " << Kh[].max << endl;
+ // plot(Ahdt,fill=1,value=1,wait=1,cmm="Ahdt");
+ // plot(Kh,fill=1,value=1,wait=1,cmm="Kh");
+ // plot(Kh,wait=1,cmm="Kh");
+  Richard;
+  cout << " h: min " << h[].min << " max  " << h[].max <<endl;
+  hmax=h[].max ;
+  // plot(h,wait=0,cmm=scmm,viso=viso);
+//  hhh = h <0;
+  }
+  if(i%10==1) {
+  Th=adaptmesh(Th,h,ratio=1.1);
+//  plot(Th,h,cmm="h ",value=1,wait=1);
+  }
+ // plot(hhh,wait=1,cmm="h < 0");
+  plot(h,wait=0,cmm=scmm,viso=viso,value=1);
+//  plot(h,cmm="h ",value=1);
+  hn=h;
+  temps += dt;
+}
+
+cout <<  " hmax = " << hmax << endl;
\ No newline at end of file
diff --git a/examples++/aaRT.edp b/examples++/aaRT.edp
new file mode 100644
index 0000000..a6515fe
--- /dev/null
+++ b/examples++/aaRT.edp
@@ -0,0 +1,59 @@
+verbosity=4;
+
+mesh Th=square(10,10,[10*x,5*y]);
+fespace Vh(Th,RT0);
+fespace Rh(Th,RT0Ortho);
+fespace Ph(Th,P0);
+
+Vh [u1,u2],[v1,v2];
+Rh [r1,r2];
+Ph p,q; 
+cout << 1. / 2. << endl;
+[u1,u2]= [1+x,2+y];
+[r1,r2]= [-2-y,1+x];
+//  verification of the finite function 
+cout << "   [u1,u2]  = ["<< u1(1,2) << "," << u2(1,2) << "]  == [2,4] \n";
+cout << "dx([u1,u2]) = ["<< dx(u1)(1,2) << "," << dx(u2)(1,2) << "]  == [1,0] \n";
+cout << "dy([u1,u2]) = ["<< dy(u1)(1,2) << "," << dy(u2)(1,2) << "]  == [0,1] \n";
+//  verification of the finite function 
+cout << "   [r1,r2]  = ["<< r1(1,2) << "," << r2(1,2) << "]  == [-4,2] \n";
+cout << "dx([r1,r2]) = ["<< dx(r1)(1,2) << "," << dx(r2)(1,2) << "]  == [0,1] \n";
+cout << "dy([r1,r2]) = ["<< dy(r1)(1,2) << "," << dy(r2)(1,2) << "]  == [-1,0] \n";
+ 
+plot(u1,u2,[u1,u2],wait=1);
+plot(r1,r2,[r1,r2],wait=1);
+
+problem Probem1(u1,u2,v1,v2,solver=LU,eps=-1.0e-6) =
+    int2d(Th)(  u1*v1+u2*v2 + dx(u1)*v1+ u2*dx(v2)) 
+  + int2d(Th) ( x*v1+y*v2 + v1 + y*dx(v2) ) 
+  
+  + on(1,2,3,4,u1=-x,u2=-y)  ;
+
+problem Probem2(p,q,solver=LU,eps=-1.0e-6) =
+    int2d(Th)(  p*q ) + int2d(Th) ( q ) 
+  ;
+
+cout << " probem 1 \n";
+Probem1; // solve problem1
+cout << " probem 2 \n";
+Probem2; // solve problem2
+
+plot(u1,u2,[u1,u2]);
+
+problem lap(u1,u2,p,v1,v2,q,solver=LU,eps=1.0e-30) =
+    int2d(Th)( p*q*1e-10+ u1*v1 + u2*v2 + p*(dx(v1)+dy(v2)) + (dx(u1)+dy(u2))*q )
+    + int2d(Th) ( q)
+   + int1d(Th)( (v1*N.x +v2*N.y)/-2);
+
+cout << " lap RT \n";
+    
+lap;
+
+plot([u1,u2],wait=1); 
+   
+plot(p,fill=1,wait=1);    
+    
+cout << " int2d(Th)(p-0.5) " << int2d(Th)(p-0.5) << "  == 0 " << endl;
+
+cout << " int2d(Th)(x+y) " << int2d(Th)(x+y) << " ==  " << (10*5)*(10+5)/2 <<  endl;
+cout << " -------------\n\n " << endl;
diff --git a/examples++/aaa-adp.edp b/examples++/aaa-adp.edp
new file mode 100644
index 0000000..1742b5a
--- /dev/null
+++ b/examples++/aaa-adp.edp
@@ -0,0 +1,69 @@
+//  -----  
+real eps =  0.0001;
+real h=1;
+real hmin=0.000005;
+real val=10; 
+real coef=50; // err = 1/100
+int nbiter=6,firstplot=3;
+func f = y*x*x+y*y*y+h*tanh(val*(sin(5.0*y)-2.0*x));
+
+cout << atanh(1) << endl;
+func fx = .0*y*x-0.2E1*h*(1.0-pow(tanh(val*(sin(0.5E1*y)-0.2E1*x)),2.0))*val;
+func fy =  x*x+3.0*y*y+0.5E1*h*(1.0-pow(tanh(val*(sin(0.5E1*y)-0.2E1*x)),2.0))*val*cos(0.5E1*y);
+
+func  fxy =   2.0*(x*pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0)+10.0*h*val*val*cos(5.0*y)
+		   *sinh(val*sin(5.0*y)-2.0*val*x))/pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0);
+
+func  fxx= 2.0*(y*pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0)-4.0*h*val*val
+		*sinh(val*sin(5.0*y)-2.0*val*x))/pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0);
+
+func  d = fx*fy - fxy*fxy;
+func  fyy=(6.0*y*pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0)-50.0*h*val*val*
+	   pow(cos(5.0*y),2.0)*sinh(val*sin(5.0*y)-2.0*val*x)-25.0*h*val*sin(5.0*y)*cosh(val*
+           sin(5.0*y)-2.0*val*x))/pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0);
+           
+border cercle(t=0,2*pi){ x=cos(t);y=sin(t);}
+mesh Th=buildmesh(cercle(20));
+
+fespace Ph(Th,P0);
+fespace Vh(Th,P1);
+fespace V2h(Th,P2);
+Vh fh=f;
+plot(fh,wait=0); //
+
+for (int i=0;i<nbiter;i++)
+{
+  //  Th=adaptmesh(Th,f);
+  verbosity=4;
+  Vh fxxh=fxx, fxyh=fxy, fyyh = fyy;
+  cout << " min max f_xx :  " <<  fxxh[].min << " " << fxxh[].max << endl;
+  cout << " min max f_yy :  " <<  fyyh[].min << " " << fyyh[].max << endl;
+  cout << " min max f_xy :  " <<  fxyh[].min << " " << fxyh[].max << endl;
+  Th=adaptmesh(Th,fxx*coef,fxy*coef,fyy*coef,IsMetric=1,nbvx=10000,hmin=hmin,ratio  = 5, 
+	       nbsmooth = 0, omega = 1);
+  fh=f;
+  Ph e=log10(abs(fh-f));
+  Vh dh=(d>0)*2-1;
+  plot(Th,fh,dh);
+  real[int] vviso(20);
+  for (int i=0;i<20;i++)
+    vviso[i]=(-20+i)/2.;
+  cout << " min max fh " << fh[].min << " " << fh[].max << endl;  
+  cout << " min max log(e) " << e[].min << " " << e[].max << endl;  
+
+  if (i>=firstplot) 
+    {
+      plot(e,fill=1,value=1,wait=0,viso=vviso,cmm="log10(e) err="+1./coef);
+      savemesh(Th,"Thh"+i+".mesh");
+      savemesh(Th,"Th"+i,[x,y,fh/2]);
+      { 
+        Vh eh=e;
+	ofstream file("Th"+i+".BB");
+	file << "2 1 1 "<< fh[].n << " 2 \n";
+	int j;
+	for (j=0;j<fh[].n ; j++)  {
+	  file << eh[][j] << endl; }
+      }	
+     if(!NoGraphicWindow) exec("ffmedit `pwd`/Th"+i);
+    }
+}
diff --git a/examples++/aadaptation.edp b/examples++/aadaptation.edp
new file mode 100644
index 0000000..7013619
--- /dev/null
+++ b/examples++/aadaptation.edp
@@ -0,0 +1,42 @@
+verbosity=2;
+border aaa(t=0,1){x=t;y=0;};
+border bbb(t=0,0.5){x=1;y=t;};
+border ccc(t=0,0.5){x=1-t;y=0.5;};
+border ddd(t=0.5,1){x=0.5;y=t;};
+border eee(t=0.5,1){x=1-t;y=1;};
+border fff(t=0,1){x=0;y=1-t;};
+mesh Th = buildmesh (aaa(6) + bbb(4) + ccc(4) +ddd(4) + eee(4) + fff(6));
+fespace Vh(Th,P1);
+
+Vh u,v,zero;
+
+u=0;
+u=0;
+zero=0;
+func f= 1;
+func g= 0;
+int i=0;
+real error=0.1, coef= 0.1^(1./5.);
+problem Probem1(u,v,solver=CG,eps=-1.0e-6) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th) ( v*f ) 
+  + on(aaa,bbb,ccc,ddd,eee,fff,u=g)  ;
+  
+real cpu=clock();
+
+for (i=0;i< 5;i++)
+{ 
+  
+  real d = clock();
+  Probem1; 
+  plot(u,zero,wait=1,ps="Lm"+i+".eps");
+  plot(u,zero,wait=1,ps="Lu"+i+".eps");
+  Th=adaptmesh(Th,u,inquire=1,err=error);
+  cout << " CPU = " << clock()-d << endl;
+  error = error * coef;
+} ;
+
+ cout << " CPU = " << clock()-cpu << endl;
+//  for regtest 
+real regvalue=int2d(Th)(u*u);
+cout<<"regvalue="<<regvalue<<endl;
diff --git a/examples++/aalapacien.edp b/examples++/aalapacien.edp
new file mode 100644
index 0000000..35b2a10
--- /dev/null
+++ b/examples++/aalapacien.edp
@@ -0,0 +1,32 @@
+verbosity=4;
+
+mesh Th=square(10,10,[10*x,5*y]);
+fespace Vh(Th,P1);
+
+Vh u,v;
+
+u=0;
+func f= 0;
+func g= 5*x+y;
+int i=0;
+real error=0.1, coef= 0.1^(1./5.);
+// exact solution  is g in this exemple : 
+//  remark $dg/dn = -1$ on $Gamma_1$ (lower side)   $n=(0,-1)$ 
+//  remark $dg/dn = 5$ on $Gamma_2$ (left side)   $n=(1,0)$ 
+//  u + du/dn = g - 1 , because du
+// $$ - \Delta u = 0,\quad  u_{|\Gamma_3 \cup \Gamma_4} = g, \frac{\partial u}{\partial n} + u = g-1 \mbox{on}\Gamma_4$$
+problem Probem1(u,v,solver=LU,init=i,eps=-1.0e-6) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int1d(Th,1) ( u*v )        //  $ \frac{\partial u}{\partial n} + u  = \ldots $
+  + int1d(Th,1) ( (+1-g)*v)    //  $ \ldots  = g-1 $ 
+  + int2d(Th) ( v*f )  
+  + int1d(Th,2) (-5*v)  //  $ \frac{\partial u}{\partial n} = 5 $ 
+  + on(3,4,u=g)  ;
+  
+real cpu=clock();
+Probem1; // SOLVE THE PROBLEM 1
+plot(u);
+real err= sqrt( int2d(Th)( (u-g)^2) );
+cout << "err L^2=" << err <<endl;
+assert(err<1e-5); //  check the solution 
+cout << " CPU = " << clock()-cpu << endl;
diff --git a/examples++/aalaplace-nc.edp b/examples++/aalaplace-nc.edp
new file mode 100644
index 0000000..577c4ce
--- /dev/null
+++ b/examples++/aalaplace-nc.edp
@@ -0,0 +1,20 @@
+
+mesh Th=square(10,10);
+fespace Vh(Th,P1nc);
+Vh u,v;
+u=0;
+plot(u);
+func f= 0;
+func g= x*x+y*y*2;
+u=0; 
+int i=0;
+// dcl the problem 
+problem a(u,v,solver=CG,init=i) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th) ( v*f ) 
+  + on(1,2,3,4,u=g+i); 
+cout << "-------------------" << i << endl;  
+i++;
+a; //  solve  the problem 
+cout << "-------------------" << endl;  
+plot(u);
diff --git a/examples++/aamove.edp b/examples++/aamove.edp
new file mode 100644
index 0000000..1c533ff
--- /dev/null
+++ b/examples++/aamove.edp
@@ -0,0 +1,30 @@
+verbosity=4;
+border a(t=0,1){x=t;y=0;label=1;};
+border b(t=0,0.5){x=1;y=t;label=1;};
+border c(t=0,0.5){x=1-t;y=0.5;label=1;};
+border d(t=0.5,1){x=0.5;y=t;label=1;};
+border e(t=0.5,1){x=1-t;y=1;label=1;};
+border f(t=0,1){x=0;y=1-t;label=1;};
+func uu= sin(y*pi)/10;
+func vv= cos(x*pi)/10;
+
+mesh Th = buildmesh ( a(6) + b(4) + c(4) +d(4) + e(4) + f(6));
+Th=movemesh(Th,[x+uu,y+vv]);
+plot(Th,wait=1,fill=1);
+fespace Vh(Th,P2);
+
+Vh u,v;
+
+u=0;
+func ff= 1;
+func gg= 0;
+int i=0;
+problem Probem1(u,v,solver=LU,init=i,eps=-1.0e-6) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th) ( v*ff ) 
+  + on(1,u=gg)  ;
+  
+real cpu=clock();
+Probem1; // SOLVE THE PROBLEM 1
+plot(u,wait=1);
+cout << " CPU = " << clock()-cpu << endl;
diff --git a/examples++/all.edp b/examples++/all.edp
new file mode 100644
index 0000000..856ef83
--- /dev/null
+++ b/examples++/all.edp
@@ -0,0 +1,105 @@
+NoUseOfWait=true;int verbosityy=verbosity;
+ cout << "--------- file : D2.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "D2.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : FE-medit.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "FE-medit.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : NSP1P1.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "NSP1P1.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : NSP1P1b.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "NSP1P1b.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : NSP1P2.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "NSP1P2.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : Richard.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "Richard.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : aaRT.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "aaRT.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : aaa-adp.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "aaa-adp.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : aadaptation.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "aadaptation.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : aalapacien.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "aalapacien.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : aalaplace-nc.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "aalaplace-nc.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : aamove.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "aamove.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : arrayoFVh.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "arrayoFVh.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : bilap.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "bilap.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : ccc-adp.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "ccc-adp.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : demo.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "demo.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : demo1.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "demo1.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : funct.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "funct.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : include.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "include.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : lap_mat.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "lap_mat.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : lapacienprecon.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "lapacienprecon.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : parareal.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "parareal.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : testFE.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "testFE.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : testadp.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "testadp.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : teste.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "teste.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
+ cout << "--------- file : wafer-heating-laser-axi.edp --------------------------------------------------------" << endl;
+verbosity=verbosityy;
+{ include "wafer-heating-laser-axi.edp";};
+ cout << "------------------------------------------------------------------------------ " << endl;
diff --git a/examples++/arrayoFVh.edp b/examples++/arrayoFVh.edp
new file mode 100644
index 0000000..662d538
--- /dev/null
+++ b/examples++/arrayoFVh.edp
@@ -0,0 +1,36 @@
+verbosity=1;
+mesh Th=square(5,5);
+fespace Vh(Th,P1);
+Vh u,v;
+real[int] X(9);  // array of 9 real
+X=5; // fill X with 1
+cout << "  norme^2 of X  " <<  sqrt(X' * X) <<  " == 15 \n";
+Vh[int] uu(10);  // array of 10 solution 
+/*  to do 
+mesh[int] aTh(10); // array of 10 meshes 
+aTh[1]= square(2,2);
+*/ 
+int i;
+for ( i=0;i<10;i++)
+ uu[i]=x+i*y; 
+
+func f= 0;
+func g= x*x+y*y*2;
+u=0; 
+// dcl the problem and solve
+solve a(u,v,solver=CG) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th) ( v*f ) 
+  + on(1,2,3,4,u=g+i); 
+
+cout << "-------------------" << endl;  
+plot(u);
+
+// exemple de calcul de semi norme H_1
+varf  lap(u,v)  = int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v) ); 
+matrix A= lap(Vh,Vh);
+cout <<  " (semi norme H^1)^2 of u =" << (v[]=A*u[])' * u[] << endl; 
+cout <<  " (semi norme H^1)^2 of u =" << int2d(Th)(  dx(u)*dx(u) + dy(u)*dy(u) ) << endl; 
+
+for ( i=0;i<10;i++)
+ cout << "|x +"<< i <<"y|_H_1 = " << sqrt((v[]=A*uu[i][])' * uu[i][])  << endl;
diff --git a/examples++/bilap.edp b/examples++/bilap.edp
new file mode 100644
index 0000000..49d14be
--- /dev/null
+++ b/examples++/bilap.edp
@@ -0,0 +1,24 @@
+int n=100,nn=n+10;
+real[int] xx(nn),yy(nn);
+
+mesh Th=square(40,40);  // mesh definition of $\Omega$
+fespace Vh(Th,P1);      // finite element space
+macro laplacien(u,v) (dx(u)*dx(v)+dy(u)*dy(v)) // fin macro 
+real f=1;
+Vh u,uu,v,vv;
+
+solve bilap([u,uu],[v,vv],solver=sparsesolver,eps=1.0e-6) =
+    int2d(Th)(  laplacien(u,vv)+uu*vv //  - Delta u + uu =0 (vv)
+    	         + laplacien(uu,v)  )     //  - Delta uu = 1 (v)
+    	        
+   - int2d(Th)(f*v)
+   + on(1,2,3,4,u=0); // => v=0 also on 1,2,3,4
+   
+plot(u,wait=1);
+
+for (int i=0;i<=n;i++)
+ {
+   xx[i]=real(i)/n;
+   yy[i]=u(0.5,real(i)/n); // value of uh at point (0.5, i/10.) 
+ }
+ plot([xx(0:n),yy(0:n)],wait=1);
diff --git a/examples++/ccc-adp.edp b/examples++/ccc-adp.edp
new file mode 100644
index 0000000..93b6ece
--- /dev/null
+++ b/examples++/ccc-adp.edp
@@ -0,0 +1,48 @@
+//  -----  
+real eps =  0.0001;
+real h=1;
+real hmin=0.000005;
+real val=50; 
+real coef=50; // err = 1/100
+int nbiter=10,firstplot=3;
+func f = y*x*x+y*y*y+h*tanh(val*(sin(5.0*y)-2.0*x));
+ofstream fff("err.dat");
+cout << atanh(1) << endl;
+func fx = .0*y*x-0.2E1*h*(1.0-pow(tanh(val*(sin(0.5E1*y)-0.2E1*x)),2.0))*val;
+func fy =  x*x+3.0*y*y+0.5E1*h*(1.0-pow(tanh(val*(sin(0.5E1*y)-0.2E1*x)),2.0))*val*cos(0.5E1*y);
+
+func  fxy =   2.0*(x*pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0)+10.0*h*val*val*cos(5.0*y)
+		   *sinh(val*sin(5.0*y)-2.0*val*x))/pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0);
+
+func  fxx= 2.0*(y*pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0)-4.0*h*val*val
+		*sinh(val*sin(5.0*y)-2.0*val*x))/pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0);
+
+func  d = fx*fy - fxy*fxy;
+func  fyy=(6.0*y*pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0)-50.0*h*val*val*
+	   pow(cos(5.0*y),2.0)*sinh(val*sin(5.0*y)-2.0*val*x)-25.0*h*val*sin(5.0*y)*cosh(val*
+           sin(5.0*y)-2.0*val*x))/pow(cosh(val*sin(5.0*y)-2.0*val*x),3.0);
+           
+border cercle(t=0,2*pi){ x=cos(t);y=sin(t);}
+mesh Th=buildmesh(cercle(20));
+
+fespace Ph(Th,P0);
+fespace Vh(Th,P1);
+fespace V2h(Th,P2);
+Vh fh=f;
+plot(fh,wait=0); //
+real err;
+for (int i=0;i<nbiter;i++)
+{
+  //  Th=adaptmesh(Th,f);
+  verbosity=4;
+  Vh fxxh=fxx, fxyh=fxy, fyyh = fyy;
+  cout << " min max f_xx :  " <<  fxxh[].min << " " << fxxh[].max << endl;
+  cout << " min max f_yy :  " <<  fyyh[].min << " " << fyyh[].max << endl;
+  cout << " min max f_xy :  " <<  fxyh[].min << " " << fxyh[].max << endl;
+  Th=adaptmesh(Th,f,err=0.1);
+  fh=f;
+  err=sqrt(int2d(Th)(square(fh-f)));
+  fff  << i<< " " << err << " " << Th.nt << " " << Th.nv <<  endl;  
+}
+//  for regtest 
+real regvalue=err;
diff --git a/examples++/demo.edp b/examples++/demo.edp
new file mode 100644
index 0000000..f7fc087
--- /dev/null
+++ b/examples++/demo.edp
@@ -0,0 +1,51 @@
+border aaa(t=0,1){x=t;y=0;label=1;};
+border bbb(t=0,0.5){x=1;y=t;label=2;};
+border ccc(t=0,0.5){x=1-t;y=0.5;label=3;};
+border ddd(t=0.5,1){x=0.5;y=t;label=4;};
+border eee(t=0.5,1){x=1-t;y=1;label=5;};
+border fff(t=0,1){x=0;y=1-t;label=6;};
+mesh Th = buildmesh (aaa(6) + bbb(4) + ccc(4) +ddd(4) + eee(4) + fff(6));
+mesh Th2 = movemesh(Th,[x+1.1,y]);
+fespace Vh(Th,P1);
+fespace Vh2(Th2,P2);
+fespace Vh21(Th2,P1);
+
+Vh u,v,zero;
+Vh2 u2,v2;
+Vh21 dxu2,dyu2;
+u=0;
+u2=0;
+zero=0;
+func f= 1;
+func g= 0;
+int i=0;
+real error=0.1, coef= 0.1^(1./5.);
+problem Probem1(u,v,solver=CG,init=i,eps=-1.0e-6) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th) ( v*f ) 
+  + on(1,2,3,4,5,6,u=g)  ;
+  
+problem Probem2(u2,v2,solver=CG,init=i,eps=-1.0e-6) =
+    int2d(Th2)(  dx(u2)*dx(v2) + dy(u2)*dy(v2)) 
+  + int2d(Th2) ( v2*f ) 
+  + on(1,2,3,4,5,6,u2=g)  ;
+  
+real cpu=clock();
+
+for (i=0;i< 10;i++)
+{ 
+  
+  real d = clock();
+  Probem1; 
+  Probem2; 
+  plot(Th,u,Th2,u2,wait=1);
+  Th=adaptmesh(Th,u,inquire=1,err=error);
+  dxu2=dx(u2);
+  dyu2=dy(u2);
+  Th2=adaptmesh(Th2,dxu2,dyu2,inquire=1,err=error,ratio=1.5,hmin=1e-5);
+  
+  cout << " CPU = " << clock()-d << endl;
+  error = error * coef;
+} ;
+
+ cout << " CPU = " << clock()-cpu << endl;
diff --git a/examples++/demo1.edp b/examples++/demo1.edp
new file mode 100644
index 0000000..8db550e
--- /dev/null
+++ b/examples++/demo1.edp
@@ -0,0 +1,53 @@
+border aaa(t=0,1){x=t;y=0;label=1;};
+border bbb(t=0,0.5){x=1;y=t;label=2;};
+border ccc(t=0,0.5){x=1-t;y=0.5;label=3;};
+border ddd(t=0.5,1){x=0.5;y=t;label=4;};
+border eee(t=0.5,1){x=1-t;y=1;label=5;};
+border fff(t=0,1){x=0;y=1-t;label=6;};
+mesh Th = buildmesh (aaa(6) + bbb(4) + ccc(4) +ddd(4) + eee(4) + fff(6));
+// mesh Th2 = movemesh(Th,[x+1.1,y]);
+fespace Ph(Th,P0);
+fespace Vh(Th,P1);
+fespace Vh2(Th,P2);
+fespace Vh21(Th,P1);
+
+Vh u,v,zero;
+Vh2 u2,v2;
+Vh21 dxu2,dyu2;
+Ph eh;
+u=0;
+u2=0;
+zero=0;
+func f= 1;
+func g= 0;
+int i=0;
+real error=0.1, coef= 0.1^(1./5.);
+problem Probem1(u,v,solver=CG,init=i,eps=-1.0e-6) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int2d(Th) ( v*f ) 
+  + on(1,2,3,4,5,6,u=g)  ;
+  
+problem Probem2(u2,v2,solver=CG,init=i,eps=-1.0e-6) =
+    int2d(Th)(  dx(u2)*dx(v2) + dy(u2)*dy(v2)) 
+  + int2d(Th) ( v2*f ) 
+  + on(1,2,3,4,5,6,u2=g)  ;
+  
+real cpu=clock();
+
+for (i=0;i< 10;i++)
+{ 
+  
+  real d = clock();
+  Probem1; 
+  Probem2; 
+  plot(Th,u,wait=1);
+  eh= abs(u-u2);
+  plot(Th,eh,fill=1,wait=1);
+  
+  Th=adaptmesh(Th,u,inquire=1,err=error,anisomax=1e6);
+  
+  cout << " CPU = " << clock()-d << endl;
+  error = error * coef;
+} ;
+
+ cout << " CPU = " << clock()-cpu << endl;
diff --git a/examples++/funct.edp b/examples++/funct.edp
new file mode 100644
index 0000000..ecdeaab
--- /dev/null
+++ b/examples++/funct.edp
@@ -0,0 +1,14 @@
+ // routine
+func int fi(real  a1)
+{
+   int i=a1*a1/1;
+   return i;
+}; 
+func real myfunction(real a,real b)
+{
+   real aa=a;
+   real z =fi(aa)+b;
+   return z;
+};
+// appele 
+cout << myfunction(1.0,3.) << " " << myfunction(1,3)  << endl;
diff --git a/examples++/include.edp b/examples++/include.edp
new file mode 100644
index 0000000..b401bc2
--- /dev/null
+++ b/examples++/include.edp
@@ -0,0 +1,2 @@
+{ include "funct.edp"; cout << " ---------- \n";  }
+{ include "aamove.edp";  }
\ No newline at end of file
diff --git a/examples++/lap_mat.edp b/examples++/lap_mat.edp
new file mode 100644
index 0000000..f1952ec
--- /dev/null
+++ b/examples++/lap_mat.edp
@@ -0,0 +1,34 @@
+//  laplace with matrix  
+verbosity=10;
+mesh Th=square(10,10);
+fespace Vh(Th,P1);
+Vh u1,u2;
+                    
+varf  a(u1,u2)= int2d(Th)(  dx(u1)*dx(u2) + dy(u1)*dy(u2) )
+                    +  on(1,2,3,4,u1=1);
+                   
+varf b([u1],[u2]) = int2d(Th)(  u1*u2 );
+
+matrix A= a(Vh,Vh,solver=CG); 
+matrix B= b(Vh,Vh,solver=CG,eps=1e-20); 
+
+Vh bb ,bc,rhs;
+bc[]= a(0,Vh);       // to save the
+u1=x;
+bb[] = bc[] .* u1[];
+u1[] = A^-1*bb[];
+//plot(u1,cmm="solution = x ",wait=1,value=1);
+u1=x*y;
+bb[] = bc[] .* u1[];
+u1[] = A^-1*bb[];
+//plot(u1,cmm="solution = x*y ",wait=1,value=1);
+u1=-4;  //  $-\Delta (x^2 + y^2) $
+bb[] = B*u1[];
+u1= x^2 + y^2 ;
+bb[] += bc[] .* u1[];
+u1[] = A^-1*bb[];
+u2= x^2 + y^2;
+
+cout << "  u1(1,2) =" <<  u1(.1,.2) << " ~= " << u2(.1,.2) 
+     << " ==  " << .1^2+.2^2 <<  endl;
+plot(u1,cmm="solution = $x^2 + y^2$ ",wait=1,value=1);
diff --git a/examples++/lapacienprecon.edp b/examples++/lapacienprecon.edp
new file mode 100644
index 0000000..1b74958
--- /dev/null
+++ b/examples++/lapacienprecon.edp
@@ -0,0 +1,42 @@
+// Warning we forgot to remove 3 pointer in this exemple
+// precon=Precon correct in version 1.26 
+verbosity=4;
+
+mesh Th=square(10,10,[10*x,5*y]);
+fespace Vh(Th,P1);
+
+Vh u,v;
+
+u=0;
+func f= 0;
+func g= 5*x+y;
+int i=0;
+real error=0.1, coef= 0.1^(1./5.);
+varf vAA(u,v) =    
+   int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int1d(Th,1) ( u*v ) 
+  + on(3,4,u=0) ;
+int pprc=1;
+matrix AA = vAA(Vh,Vh,solver=CG);
+func real[int]  Precon(real[int] & xx)
+{
+ cout << xx[0] << " -----" ;
+//  xx[0]=1001;
+   
+   real[int] xpre = xx;
+   if(pprc) xpre = AA^-1*xx;
+  return xpre;
+};
+
+problem Probem1(u,v,solver=CG,init=i,eps=1.0e-6,precon=Precon) =
+    int2d(Th)(  dx(u)*dx(v) + dy(u)*dy(v)) 
+  + int1d(Th,1) ( u*v ) 
+  + int2d(Th) ( v*f ) 
+  + int1d(Th,2) (-5*v)
+  + int1d(Th,1) ( (+1-g)*v)
+  + on(3,4,u=g)  ;
+  
+real cpu=clock();
+Probem1; // SOLVE THE PROBLEM 1
+plot(u);
+cout << " CPU = " << clock()-cpu << endl;
diff --git a/examples++/makeref.edp b/examples++/makeref.edp
new file mode 100644
index 0000000..d87484e
--- /dev/null
+++ b/examples++/makeref.edp
@@ -0,0 +1,248 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+// Regression tests
+// ----------------
+
+// The tests are checked against reference values by "make check" in
+// each examples subdirectory
+
+// "ref.edp" contains all reference values and may be rebuilt with
+// "make Ref"
+
+// $Id$
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+NoUseOfWait=true;
+int verbosityy=verbosity;
+
+
+
+
+ofstream ref("ref.edp");
+
+
+
+
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+
+cout << "--------- file : aadaptation.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aadaptation.edp";
+	real TESTaadaptation=regvalue;
+		ref<<"real REFaadaptation="<<TESTaadaptation<<";"<<endl;
+};
+;
+cout << "--------- file : aalapacien.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aalapacien.edp";
+	real TESTaalapacien=1+err;
+		ref<<"real REFaalapacien="<<TESTaalapacien<<";"<<endl;
+};
+;
+cout << "--------- file : aalaplace-nc.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aalaplace-nc.edp";
+	real TESTaalaplaceXnc=u[]'*u[];
+		ref<<"real REFaalaplaceXnc="<<TESTaalaplaceXnc<<";"<<endl;
+};
+;
+cout << "--------- file : aamove.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aamove.edp";
+	real TESTaamove=u[]'*u[];
+		ref<<"real REFaamove="<<TESTaamove<<";"<<endl;
+};
+;
+cout << "--------- file : aaRT.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aaRT.edp";
+	real TESTaaRT=u1[]'*u1[];
+		ref<<"real REFaaRT="<<TESTaaRT<<";"<<endl;
+};
+;
+cout << "--------- file : arrayoFVh.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "arrayoFVh.edp";
+	real TESTarrayoFVh=u[]'*u[];
+		ref<<"real REFarrayoFVh="<<TESTarrayoFVh<<";"<<endl;
+};
+;
+cout << "--------- file : bilap.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "bilap.edp";
+	real TESTbilap=xx(0:n)'*xx(0:n);
+		ref<<"real REFbilap="<<TESTbilap<<";"<<endl;
+};
+;
+cout << "--------- file : D2.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "D2.edp";
+	real TESTD2=w[]'*w[];
+		ref<<"real REFD2="<<TESTD2<<";"<<endl;
+};
+;
+cout << "--------- file : demo1.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "demo1.edp";
+	real TESTdemo1=u[]'*u[];
+		ref<<"real REFdemo1="<<TESTdemo1<<";"<<endl;
+};
+;
+cout << "--------- file : demo.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "demo.edp";
+	real TESTdemo=u[]'*u[];
+		ref<<"real REFdemo="<<TESTdemo<<";"<<endl;
+};
+;
+cout << "--------- file : funct.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "funct.edp";
+	real TESTfunct=myfunction(1.0,3.);
+		ref<<"real REFfunct="<<TESTfunct<<";"<<endl;
+};
+;
+cout << "--------- file : lapacienprecon.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "lapacienprecon.edp";
+	real TESTlapacienprecon=u[]'*u[];
+		ref<<"real REFlapacienprecon="<<TESTlapacienprecon<<";"<<endl;
+};
+;
+cout << "--------- file : lap_mat.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "lap_mat.edp";
+	real TESTlapXmat=u1[]'*u1[];
+		ref<<"real REFlapXmat="<<TESTlapXmat<<";"<<endl;
+};
+;
+cout << "--------- file : NSP1P1b.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "NSP1P1b.edp";
+	real TESTNSP1P1b=int2d(Th)(square(u1)+square(u2));
+		ref<<"real REFNSP1P1b="<<TESTNSP1P1b<<";"<<endl;
+};
+;
+cout << "--------- file : NSP1P1.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "NSP1P1.edp";
+	real TESTNSP1P1=int2d(Th)(square(u1)+square(u2));
+		ref<<"real REFNSP1P1="<<TESTNSP1P1<<";"<<endl;
+};
+;
+cout << "--------- file : NSP1P2.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "NSP1P2.edp";
+	real TESTNSP1P2=int2d(Th)(square(u1)+square(u2));
+		ref<<"real REFNSP1P2="<<TESTNSP1P2<<";"<<endl;
+};
+;
+cout << "--------- file : parareal.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "parareal.edp";
+	real TESTparareal=pu'*pu;
+		ref<<"real REFparareal="<<TESTparareal<<";"<<endl;
+};
+;
+
+ cout << "--------- file : Richard.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "Richard.edp";
+	real TESTRichard=hmax;
+		ref<<"real REFRichard="<<TESTRichard<<";"<<endl;
+};
+;
+
+cout << "--------- file : teste.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "teste.edp";
+	real TESTteste=P.x;
+		ref<<"real REFteste="<<TESTteste<<";"<<endl;
+};
+;
+cout << "--------- file : testFE.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "testFE.edp";
+	
+};
+;
+cout << "--------- file : wafer-heating-laser-axi.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "wafer-heating-laser-axi.edp";
+	real TESTwaferXheatingXlaserXaxi=xx'*xx;
+		ref<<"real REFwaferXheatingXlaserXaxi="<<TESTwaferXheatingXlaserXaxi<<";"<<endl;
+};
+;
diff --git a/examples++/parareal.edp b/examples++/parareal.edp
new file mode 100644
index 0000000..db2e7ad
--- /dev/null
+++ b/examples++/parareal.edp
@@ -0,0 +1,181 @@
+//int Nh=20;
+// d u /dt = cos(t), u= sin(t) + u0
+//  avec de methode para reel.
+// schema euler explicite 
+//   (u,v)' = (v,-u) 
+//    u_n+1 - u_n = v_n*dt,  u_n+1 = u_n + v_n*dt
+//    v_n+1 - v_n = -u_n*dt,
+//   u=cos(t)  u' = - sin(t) = v
+//   v=sin(t), v' = cos(t) = u
+// ----------------------------
+real DT=0.4;
+int nbT=50;   // nb de big time step 
+int ksub=50;  // nb of small time step 
+int Nbig=20;  // max  number of Big iteration
+real T0=0;    // initial time
+real tol=1e-5; // tolerance 
+// ----------------------------------------------------
+int nbt=ksub*nbT;
+real dt=DT/ksub;
+//  array for plotting 
+real[int] pt(nbt+1),pT(nbT+1),pu(nbt+1),pU(nbT+1);
+
+//  gros maillage
+mesh TH=square(3,3);
+// maillage fin
+mesh Th=trunc(TH,1,split=1);
+fespace VH(TH,P1);
+fespace Vh(Th,P1);
+int n=2;
+int N=2;
+
+func real Norm(real[int] & U)
+{
+  return sqrt(square(U[10])+square(U[11]));
+}
+// restriction
+func bool h2H(real[int] & u,real[int] & U)
+{
+ U=0;
+ U[10+0]=u[0];
+ U[10+1]=u[1];
+
+ return true;
+}
+//  prolongement
+func bool H2h(real[int] & U,real[int] & u)
+{
+ u=0;
+ u[0]=U[10+0];
+ u[1]=U[10+1];
+ return true;
+}
+
+func bool initG(real[int]  & U)
+{
+  U=0;
+  U[10+0]=1;// cos(0)
+  U[10+1]=0;// sin(0)
+}
+// un pas de temps  FIN
+
+func bool  F(real[int]  & u,real[int]  & up)
+{
+   u[0] = up[0] + up[1]*dt;
+   u[1] = up[1] - up[0]*dt;
+//   cout << up[0] << " " << up[1] << endl;
+   return true;
+}
+
+// pas de temps grossier
+func bool  G(real[int]  & U,real[int]  & Up)
+{
+   U[0+10] = Up[0+10] + Up[1+10]*DT;
+   U[1+10] = Up[1+10] - Up[0+10]*DT;
+//   cout << Up[10] << " " << Up[11] << endl;
+   return true;
+}
+
+func bool AddGp(real[int]  & U,int I)
+{
+  pT[I]= T0+I*DT;
+  pU[I]=U[10];
+  return true;
+}
+func bool AddFp(real[int]  & u,int I,int i)
+{
+  pt[I*ksub+i]= T0+I*DT+i*dt;
+  pu[I*ksub+i]= u[0];
+  return true;
+}
+
+Vh ustart[nbT+1],uend[nbT]; // start 
+VH Uend[nbT];
+VH U0,U1;
+
+
+
+real t=T0,T=T0; // temps courant
+int it=0,iT=0; 
+pt[it]=t;
+pT[iT]=T;
+initG(U0[]);
+AddGp(U0[],iT);
+H2h(U0[], ustart[iT][]);
+
+//  initial 
+for (int I=0;I<nbT;I++)
+  {
+    G(U1[],U0[]);
+    U0[]=U1[];
+    Uend[I][]=U1[];
+    H2h(U0[],ustart[I+1][]);
+    AddGp(U1[],I+1); 
+  }
+cout << pT.max << " " << pU.min << " " << pU.max << endl;
+
+
+real[int] exact(nbt+1),fu(nbt+1);
+{
+Vh u0,u1; 
+u0[]=ustart[0][];
+for (int i=0;i<=nbt;i++)
+ {
+   pt[i]=T0+i*dt;
+   exact[i]=cos(pt[i]);
+   F(u1[],u0[]);
+   u0[]=u1[];
+   AddFp(u0[],0,i);
+ }
+}
+fu=pu;
+plot([pT,pU],[pt,exact],[pt,fu],wait=1);
+// big loop 
+for (int K=0;K< Nbig;K++)
+{
+
+//  para real loop --
+
+for (int I=0;I<nbT;I++)
+ {
+    Vh u0,u1;
+    u0[]=ustart[I][];
+    AddFp(u0[],I,0);
+    for (int i=0;i<ksub;i++)
+     {
+      F(u1[],u0[]);
+      u0[]=u1[];
+      AddFp(u0[],I,i+1);
+     }
+    uend[I][]=u0[];
+ }
+
+plot([pT,pU],[pt,pu],[pt,exact],cmm="iteration "+K);
+ 
+// update loop  
+ustart[K+1]=uend[K];
+real err=0;
+for (int I=K+1;I<nbT;I++)
+ {
+   // Attention  pb fin grossier 
+   VH U0,U1;
+   h2H(ustart[I][],U0[]);
+   AddGp(U0[],I); 
+   G(U1[],U0[]);
+   AddGp(U1[],I+1); 
+   U0[]=U1[];
+   U1[] -=Uend[I][]; // U1=U1-U1(old)
+   err += Norm(U1[]);
+   Uend[I][]=U0[]; // save U1 
+   Vh u1;
+   H2h(U1[],u1[]);
+   ustart[I+1][] = u1[]+ uend[I][] ;     
+ }
+
+ cout << "\n\n big iteration " <<  K << "  err= " << err << endl;
+ if (err < tol) break;
+//plot([pT,pU],wait=1,clean=0);
+
+}
+plot([pt,pu],[pt,exact],[pt,fu],wait=1,cmm=" final fin");
+plot([pT,pU],[pt,exact],[pt,fu],wait=1,cmm=" final grossier");
diff --git a/examples++/ref.edp b/examples++/ref.edp
new file mode 100644
index 0000000..7db6061
--- /dev/null
+++ b/examples++/ref.edp
@@ -0,0 +1,20 @@
+real REFaadaptation=0.000319285;
+real REFaalapacien=1;
+real REFaalaplaceXnc=1713.48;
+real REFaamove=0.0662979;
+real REFaaRT=280.925;
+real REFarrayoFVh=4560.74;
+real REFbilap=33.835;
+real REFD2=0;
+real REFdemo1=1.33172;
+real REFdemo=1.33172;
+real REFfunct=4;
+real REFlapacienprecon=122059;
+real REFlapXmat=85.3776;
+real REFNSP1P1b=0.0460503;
+real REFNSP1P1=0.0483801;
+real REFNSP1P2=0.0453758;
+real REFparareal=1383.27;
+real REFRichard=95.9051;
+real REFteste=1;
+real REFwaferXheatingXlaserXaxi=285;
diff --git a/examples++/regtests.edp b/examples++/regtests.edp
new file mode 100644
index 0000000..7b17c83
--- /dev/null
+++ b/examples++/regtests.edp
@@ -0,0 +1,308 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+// Regression tests
+// ----------------
+
+// The tests are checked against reference values by "make check" in
+// each examples subdirectory
+
+// "ref.edp" contains all reference values and may be rebuilt with
+// "make Ref"
+
+// $Id$
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+NoUseOfWait=true;
+int verbosityy=verbosity;
+
+
+
+
+include "ref.edp";
+
+
+
+
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+
+cout << "--------- file : aadaptation.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aadaptation.edp";
+	real TESTaadaptation=regvalue;
+		cout<<"aadaptation reference value = "<<REFaadaptation
+				<<" test value ="<<TESTaadaptation<<endl;
+			assert(TESTaadaptation<REFaadaptation*(1+0.1));
+				assert(TESTaadaptation>REFaadaptation*(1-0.1));
+};
+;
+cout << "--------- file : aalapacien.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aalapacien.edp";
+	real TESTaalapacien=1+err;
+		cout<<"aalapacien reference value = "<<REFaalapacien
+				<<" test value ="<<TESTaalapacien<<endl;
+			assert(TESTaalapacien<REFaalapacien*(1+0.00001));
+				assert(TESTaalapacien>REFaalapacien*(1-0.00001));
+};
+;
+cout << "--------- file : aalaplace-nc.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aalaplace-nc.edp";
+	real TESTaalaplaceXnc=u[]'*u[];
+		cout<<"aalaplace-nc reference value = "<<REFaalaplaceXnc
+				<<" test value ="<<TESTaalaplaceXnc<<endl;
+			assert(TESTaalaplaceXnc<REFaalaplaceXnc*(1+0.1));
+				assert(TESTaalaplaceXnc>REFaalaplaceXnc*(1-0.1));
+};
+;
+cout << "--------- file : aamove.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aamove.edp";
+	real TESTaamove=u[]'*u[];
+		cout<<"aamove reference value = "<<REFaamove
+				<<" test value ="<<TESTaamove<<endl;
+			assert(TESTaamove<REFaamove*(1+0.1));
+				assert(TESTaamove>REFaamove*(1-0.1));
+};
+;
+cout << "--------- file : aaRT.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "aaRT.edp";
+	real TESTaaRT=u1[]'*u1[];
+		cout<<"aaRT reference value = "<<REFaaRT
+				<<" test value ="<<TESTaaRT<<endl;
+			assert(TESTaaRT<REFaaRT*(1+0.1));
+				assert(TESTaaRT>REFaaRT*(1-0.1));
+};
+;
+cout << "--------- file : arrayoFVh.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "arrayoFVh.edp";
+	real TESTarrayoFVh=u[]'*u[];
+		cout<<"arrayoFVh reference value = "<<REFarrayoFVh
+				<<" test value ="<<TESTarrayoFVh<<endl;
+			assert(TESTarrayoFVh<REFarrayoFVh*(1+0.1));
+				assert(TESTarrayoFVh>REFarrayoFVh*(1-0.1));
+};
+;
+cout << "--------- file : bilap.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "bilap.edp";
+	real TESTbilap=xx(0:n)'*xx(0:n);
+		cout<<"bilap reference value = "<<REFbilap
+				<<" test value ="<<TESTbilap<<endl;
+			assert(TESTbilap<REFbilap*(1+0.1));
+				assert(TESTbilap>REFbilap*(1-0.1));
+};
+;
+cout << "--------- file : D2.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "D2.edp";
+	real TESTD2=w[]'*w[];
+		cout<<"D2 reference value = "<<REFD2
+				<<" test value ="<<TESTD2<<endl;
+			assert(TESTD2<REFD2+1e-20);
+				assert(TESTD2>REFD2-1e-20);
+};
+;
+cout << "--------- file : demo1.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "demo1.edp";
+	real TESTdemo1=u[]'*u[];
+		cout<<"demo1 reference value = "<<REFdemo1
+				<<" test value ="<<TESTdemo1<<endl;
+			assert(TESTdemo1<REFdemo1*(1+0.1));
+				assert(TESTdemo1>REFdemo1*(1-0.1));
+};
+;
+cout << "--------- file : demo.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "demo.edp";
+	real TESTdemo=u[]'*u[];
+		cout<<"demo reference value = "<<REFdemo
+				<<" test value ="<<TESTdemo<<endl;
+			assert(TESTdemo<REFdemo*(1+0.1));
+				assert(TESTdemo>REFdemo*(1-0.1));
+};
+;
+cout << "--------- file : funct.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "funct.edp";
+	real TESTfunct=myfunction(1.0,3.);
+		cout<<"funct reference value = "<<REFfunct
+				<<" test value ="<<TESTfunct<<endl;
+			assert(TESTfunct<REFfunct*(1+0.1));
+				assert(TESTfunct>REFfunct*(1-0.1));
+};
+;
+cout << "--------- file : lapacienprecon.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "lapacienprecon.edp";
+	real TESTlapacienprecon=u[]'*u[];
+		cout<<"lapacienprecon reference value = "<<REFlapacienprecon
+				<<" test value ="<<TESTlapacienprecon<<endl;
+			assert(TESTlapacienprecon<REFlapacienprecon*(1+0.1));
+				assert(TESTlapacienprecon>REFlapacienprecon*(1-0.1));
+};
+;
+cout << "--------- file : lap_mat.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "lap_mat.edp";
+	real TESTlapXmat=u1[]'*u1[];
+		cout<<"lap_mat reference value = "<<REFlapXmat
+				<<" test value ="<<TESTlapXmat<<endl;
+			assert(TESTlapXmat<REFlapXmat*(1+0.1));
+				assert(TESTlapXmat>REFlapXmat*(1-0.1));
+};
+;
+cout << "--------- file : NSP1P1b.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "NSP1P1b.edp";
+	real TESTNSP1P1b=int2d(Th)(square(u1)+square(u2));
+		cout<<"NSP1P1b reference value = "<<REFNSP1P1b
+				<<" test value ="<<TESTNSP1P1b<<endl;
+			assert(TESTNSP1P1b<REFNSP1P1b*(1+0.2));
+				assert(TESTNSP1P1b>REFNSP1P1b*(1-0.2));
+};
+;
+cout << "--------- file : NSP1P1.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "NSP1P1.edp";
+	real TESTNSP1P1=int2d(Th)(square(u1)+square(u2));
+		cout<<"NSP1P1 reference value = "<<REFNSP1P1
+				<<" test value ="<<TESTNSP1P1<<endl;
+			assert(TESTNSP1P1<REFNSP1P1*(1+10));
+				assert(TESTNSP1P1>REFNSP1P1*(1-10));
+};
+;
+cout << "--------- file : NSP1P2.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "NSP1P2.edp";
+	real TESTNSP1P2=int2d(Th)(square(u1)+square(u2));
+		cout<<"NSP1P2 reference value = "<<REFNSP1P2
+				<<" test value ="<<TESTNSP1P2<<endl;
+			assert(TESTNSP1P2<REFNSP1P2*(1+0.2));
+				assert(TESTNSP1P2>REFNSP1P2*(1-0.2));
+};
+;
+cout << "--------- file : parareal.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "parareal.edp";
+	real TESTparareal=pu'*pu;
+		cout<<"parareal reference value = "<<REFparareal
+				<<" test value ="<<TESTparareal<<endl;
+			assert(TESTparareal<REFparareal*(1+0.1));
+				assert(TESTparareal>REFparareal*(1-0.1));
+};
+;
+
+ cout << "--------- file : Richard.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "Richard.edp";
+	real TESTRichard=hmax;
+		cout<<"Richard reference value = "<<REFRichard
+				<<" test value ="<<TESTRichard<<endl;
+			assert(TESTRichard<REFRichard*(1+0.1));
+				assert(TESTRichard>REFRichard*(1-0.1));
+};
+;
+
+cout << "--------- file : teste.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "teste.edp";
+	real TESTteste=P.x;
+		cout<<"teste reference value = "<<REFteste
+				<<" test value ="<<TESTteste<<endl;
+			assert(TESTteste<REFteste*(1+0.1));
+				assert(TESTteste>REFteste*(1-0.1));
+};
+;
+cout << "--------- file : testFE.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "testFE.edp";
+	
+};
+;
+cout << "--------- file : wafer-heating-laser-axi.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+		
+	
+	include "wafer-heating-laser-axi.edp";
+	real TESTwaferXheatingXlaserXaxi=xx'*xx;
+		cout<<"wafer-heating-laser-axi reference value = "<<REFwaferXheatingXlaserXaxi
+				<<" test value ="<<TESTwaferXheatingXlaserXaxi<<endl;
+			assert(TESTwaferXheatingXlaserXaxi<REFwaferXheatingXlaserXaxi*(1+0.1));
+				assert(TESTwaferXheatingXlaserXaxi>REFwaferXheatingXlaserXaxi*(1-0.1));
+};
+;
diff --git a/examples++/regtests.m4 b/examples++/regtests.m4
new file mode 100644
index 0000000..bf3995c
--- /dev/null
+++ b/examples++/regtests.m4
@@ -0,0 +1,37 @@
+// Regression tests
+// ----------------
+
+// $Id$
+
+include(../regtests.m4)
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+dnl (syntax of ONETEST macro defined in ../regtests.m4)
+
+ONETEST(aadaptation,regvalue,0.1);
+ONETEST(aalapacien,1+err,0.00001);
+ONETEST(aalaplace-nc,u[]'*u[],0.1);
+ONETEST(aamove,u[]'*u[],0.1);
+ONETEST(aaRT,u1[]'*u1[],0.1);
+ONETEST(arrayoFVh,u[]'*u[],0.1);
+ONETEST(bilap,xx(0:n)'*xx(0:n),0.1);
+ONETEST(D2,w[]'*w[],1e-20,1e-20);
+ONETEST(demo1,u[]'*u[],0.1);
+ONETEST(demo,u[]'*u[],0.1);
+ONETEST(funct,myfunction(1.0,3.),0.1);
+ONETEST(lapacienprecon,u[]'*u[],0.1);
+ONETEST(lap_mat,u1[]'*u1[],0.1);
+ONETEST(NSP1P1b,int2d(Th)(square(u1)+square(u2)),0.2);
+ONETEST(NSP1P1,int2d(Th)(square(u1)+square(u2)),10);
+ONETEST(NSP1P2,int2d(Th)(square(u1)+square(u2)),0.2);
+ONETEST(parareal,pu'*pu,0.1);
+
+dnl alh - 30/6/04 - unstable?
+ ONETEST(Richard,hmax,0.1);
+
+ONETEST(teste,P.x,0.1);
+ONETEST(testFE);
+ONETEST(wafer-heating-laser-axi,xx'*xx,0.1);
diff --git a/examples++/testFE.edp b/examples++/testFE.edp
new file mode 100644
index 0000000..0456587
--- /dev/null
+++ b/examples++/testFE.edp
@@ -0,0 +1,48 @@
+real regtest;// for FFCS regression tests
+// exact solution is [x*x,y]  -Delta [x*x,y] = [-2,0]
+// This exemple is buggus before version 1.26
+{ 
+// test of product of same FE
+  verbosity = 2;
+ mesh Th=square(2,2);
+ fespace Vh(Th,P2);
+ 
+ Vh uHx=0;
+ Vh uHy=0;
+ Vh vHx;
+ Vh vHy;
+ 
+ solve  deuxlap([uHx,uHy],[vHx,vHy],solver=CG) =
+    int2d(Th)(    dx(uHx)*dx(vHx) + dy(uHx)*dy(vHx)
+               +  dx(uHy)*dx(vHy) + dy(uHy)*dy(vHy)  )
+    - int2d(Th)( -2* vHx )        
+    +  on(1,2,3,4,uHx=x*x,uHy=y);
+   // plot(uHx, uHy,wait=1);
+    real err2= sqrt( int2d(Th)(square(uHx-x*x)+square(uHy-y)));
+    cout << " Error in L2 norme " << err2 << endl ;
+    assert(err2 < 1e-10);
+}
+
+{ 
+// test of product of different  FE
+verbosity = 2;
+ mesh Th=square(2,2);
+ fespace Vh(Th,P2);
+ fespace Vh1(Th,P1);
+ 
+ Vh uHx=0;
+ Vh1 uHy=0;
+ Vh vHx;
+ Vh1 vHy;
+ 
+ solve  deuxlap([uHx,uHy],[vHx,vHy],solver=CG) =
+    int2d(Th)(    dx(uHx)*dx(vHx) + dy(uHx)*dy(vHx)
+               +  dx(uHy)*dx(vHy) + dy(uHy)*dy(vHy)  )
+    - int2d(Th)( -2* vHx )        
+    +  on(1,2,3,4,uHx=x*x,uHy=y);
+   // plot(uHx, uHy,wait=1);
+    real err2= sqrt( int2d(Th)(square(uHx-x*x)+square(uHy-y)));
+    cout << " Error in L2 norme " << err2 << endl ;
+    assert(err2 < 1e-10);
+    regtest=err2;
+}
diff --git a/examples++/testadp.edp b/examples++/testadp.edp
new file mode 100644
index 0000000..648b942
--- /dev/null
+++ b/examples++/testadp.edp
@@ -0,0 +1,52 @@
+//  -----  
+real eps =  0.0001;
+real h=1;
+real hmin=0.05;
+func f = 10.0*x*x*x+y*y*y+h*atan2(eps,sin(5.0*y)-2.0*x);
+
+func fx = 30.0*x*x+h*2.0*eps/pow(sin(5.0*y)-2.0*x,2.0)/(1.0+eps*eps/pow(sin(5.0*y)-2.0*x,2.0));
+
+func  fy =  3.0*y*y-h*5.0*eps/pow(sin(5.0*y)-2.0*x,2.0)*cos(5.0*y)/(1.0+eps*eps/pow(sin(5.0*y)-2.0*x,2.0));
+
+func  fxy =  h*(-20.0*eps/pow(sin(5.0*y)-2.0*x,3.0)*cos(5.0*y)/(1.0+eps*eps/pow(sin(5.0*y)-2.0*x,2.0))
++20.0*eps*eps*eps/pow(sin(5.0*y)-2.0*x,5.0)*cos(5.0*y)/pow(1.0+eps*eps/pow(sin(5.0*y)-2.0*x,2.0),2.0));
+
+func  fxx= 60.0*x+h*(8.0*eps/pow(sin(5.0*y)-2.0*x,3.0)/(1.0+eps*eps/pow(sin(5.0*y)
+-2.0*x,2.0))-8.0*eps*eps*eps/pow(sin(5.0*y)-2.0*x,5.0)/pow(1.0+eps*eps/pow(sin(
+5.0*y)-2.0*x,2.0),2.0));
+
+func  d = fx*fy - fxy*fxy;
+func  fyy= 6.0*y+h*(50.0*eps/pow(sin(5.0*y)-2.0*x,3.0)*pow(cos(5.0*y),2.0)/(1.0+
+eps*eps/pow(sin(5.0*y)-2.0*x,2.0))+25.0*eps/pow(sin(5.0*y)-2.0*x,2.0)*sin(5.0*y
+)/(1.0+eps*eps/pow(sin(5.0*y)-2.0*x,2.0))-50.0*eps*eps*eps/pow(sin(5.0*y)-2.0*x
+,5.0)*pow(cos(5.0*y),2.0)/pow(1.0+eps*eps/pow(sin(5.0*y)-2.0*x,2.0),2.0));
+
+border cercle(t=0,2*pi){ x=cos(t);y=sin(t);}
+mesh Th=buildmesh(cercle(20));
+fespace Ph(Th,P0);
+fespace Vh(Th,P1);
+fespace V2h(Th,P2);
+Vh fh=f;
+int i;
+real coef=10;
+for ( i=0;i<5;i++)
+ {
+ //  Th=adaptmesh(Th,f);
+      verbosity=4;
+      Th=adaptmesh(Th,fxx*coef,fxy*coef,fyy*coef,IsMetric=1,nbvx=10000,hmin=hmin);
+
+   fh=f;
+   Ph e=abs(fh-f);
+   Vh dh=(d>0)*2-1;
+   plot(Th,fh,dh,wait=1);
+   plot(e,fill=1,value=1,wait=1);
+   savemesh(Th,"Th"+i+".mesh");
+   savemesh(Th,"Thh"+i,[x,y,fh/2]);
+ {   ofstream file("Th"+i+".gbb");
+   file << "2 1 1 "<< fh[].n << " 2 \n";
+   int j;
+   for (j=0;j<fh[].n ; j++)  {
+     file << fh[][j] << endl; }
+ }	
+  if(!NoGraphicWindow)  exec("ffmedit `pwd`/Thh"+i);
+ }
diff --git a/examples++/teste.edp b/examples++/teste.edp
new file mode 100644
index 0000000..726e840
--- /dev/null
+++ b/examples++/teste.edp
@@ -0,0 +1,147 @@
+ // routine
+func real myfunction(real a,real b)
+{
+   real z =a+b;
+   return z;
+};
+{
+real[int] matx(10),b(10),x(10); 
+func real[int] mat(real[int] &x)
+{ int i;
+  for (i=0;i<x.n;i++)
+    matx[i]=(i+1)*x[i];
+  matx -= b; // sub the right hand side
+  return matx;  // return of global variable ok 
+};
+func real[int] matId(real[int] &x) { return x;};
+b=1; x=0; // set  right hand side and initial gest
+LinearCG(mat,x,eps=1.e-6,nbiter=20,precon=matId);
+cout << x;
+  for (int i=0;i<x.n;i++)
+    assert(abs(x[i]*(i+1) - b[i]) < 1e-5);
+b=1; x=0; // set  right hand side and initial gest
+NLCG(mat,x,eps=1.e-6,nbiter=20,precon=matId);
+cout << x;
+  for (int i=0;i<x.n;i++)
+    assert(abs(x[i]*(i+1) - b[i]) < 1e-5);
+
+};
+ cout << myfunction(1.0,3.) << " " << myfunction(1,3)  << endl;
+//   a array 
+{
+border a(t=0,1){x=t;y=0;};
+border b(t=0,0.5){x=1;y=t;};
+border c(t=0,0.5){x=1-t;y=0.5;};
+border d(t=0.5,1){x=0.5;y=t;};
+border e(t=0.5,1){x=1-t;y=1;};
+border f(t=0,1){x=0;y=1-t;};
+mesh th = buildmesh ( a(6) + b(4) + c(4) +d(4) + e(4) + f(6));
+plot(th,wait=1,fill=1);
+
+};
+cout << (1==2) * 3. + (1==1)*4. << endl;
+
+real [int] tab(10), tab1(10); // 2 array of 10 real 
+//  real [int] tab2; //  bug 
+tab = 1;  //  set all the array to 1
+tab[1]=2;
+cout << tab[1] << " " << tab[9] << " size of tab = " << tab.n << endl;
+tab1=tab;
+tab=tab+tab1;
+tab=2*tab+tab1*5;
+tab1=2*tab-tab1*5;
+tab+=tab;
+cout << tab << endl;
+cout << tab[1] << " " << tab[9] <<  endl;
+real [string] map; //  a dynamique array
+cout << "-------------------------------------------------------------" << endl;
+x=cos(0.1);
+y=1.1;
+z=2.1;
+cout << z << " ==  " << P << endl;
+{real z;
+ func f=z+1;
+z=1;
+cout << " entre z=?" ;
+//cin >> z;
+cout << " z = " << z << " f=" << f << endl;};
+{
+mesh Th = square(5,5);
+fespace Vh(Th); // P1
+Vh uh;
+uh=2*x+10*y; //  do P1 interpolation
+x=0.5;
+y=0.9;
+real uhxy=uh; // get the value of uh at point (x,y)= 0.5,0.9
+cout << "uh at (0.5,0.9) =" << uhxy << endl; 
+};
+
+{
+  ofstream f("toto.txt");
+  f << "coucou'\n";
+};
+{
+  ofstream f("toto.txt",append);
+  f << "add coucou'\n";
+};
+
+
+// no current mesh 
+
+map["1"]=2.0;
+map[2]=3.0; //  2 is automaticaly cast to the string "2"
+
+cout << " map[\"1\"] = " << map["1"] << "; "<< endl;
+cout << " map[2] = " << map[2] << "; "<< endl;
+{
+  real a,b,c;
+  int i,j,k;  
+};
+string str,str1;
+ str="abc+";
+ str1="+abcddddd+";
+ str=str + str1;
+ str = str + 2 ;
+cout << "str=  " << str << "== abc++abcddddd+2;\n";
+
+real  x=3.14,y;
+int  i,j;
+complex c;
+
+cout << " x = " << x << "\n";
+
+x = 1;y=2;
+x=y;
+
+i=0;j=1;
+
+cout << 1 + 3 << "\n";
+cout << 10 ^10   << "\n";
+cout << 10 ^-10   << "\n";
+cout << -10^-2+5   << "== 4.99 \n";
+cout << 10^-2+5    << "==  5.01 \n";
+cout << "------------------ complex ---- \n" ;
+cout << 10-10i   << " \n";
+cout << " -1^(1/3) = " << (-1+0i)^(1./3.)   << " \n";
+cout << " 8^(1/3)= " << (8)^(1./3.)   << " \n";
+cout << " sqrt(-1) = " << sqrt(-1+0i) << " \n";
+
+cout << " ++i =" <<  ++i ;
+cout <<  " i=" << i << "\n";
+cout << " i++ = "<< i++ << "\n";
+cout << " i   = " << i << "\n";
+cout << " for (i=0;i<10;i=i+1) \n";
+
+for (int i=0;i<100;i=i+1)
+  {
+    if (i>=10) break;
+    real a=i;
+    tab[i] = i*i;
+    if (i>5) continue;
+    cout << i << " " << tab[i] << "\n";
+  };
+  
+R3 P;
+P.x=1;
+x=P.x;
+cout << P.x << "\n";  
diff --git a/examples++/wafer-heating-laser-axi.edp b/examples++/wafer-heating-laser-axi.edp
new file mode 100644
index 0000000..5b1e4c0
--- /dev/null
+++ b/examples++/wafer-heating-laser-axi.edp
@@ -0,0 +1,128 @@
+// simulation of wafer heating by a laser.
+/**************************************************************
+From:  Fabian Dortu
+
+Materials and Components Analysis group (MCA)
+SPDT division
+
+IMEC, Kapeldreef 75, B-3001 Leuven, Belgium
+tel: +32/16 28 8774
+e-mail: Fabian.Dortu at imec.be <mailto:Fabian.Dortu at imec.be> 
+**************************************************************/
+// The poisson equation (here the heat equation) is solved in cylindrical coordinates:
+//   $ \Delta u = 1/r \partial_r(r \partial_r u) + \partial_{zz} u +  1/r^2 \partial_{\theta^2} u $
+// so the variationnal formulation is after integer on the 3d cylinder 
+// rotation invariant given $\partial_{\theta} u =0$
+//  $ - \Delta u = f $
+//  on the 1/2 plan $ \theta =0$ 
+//  $ \int r ( \partial_r u \partial_r v + \partial_z u \partial_z v ) = \int r f v  - \int_{\Gamma} r \partial_n u v $  
+//  the radial coordinate 'r' is called 'x'.
+//  the depth coordinate 'z' is called 'y'.
+// The wafer stuck is a rectangle with upper left corner at (0,0)
+//  and lower right corner at (radius,-thickness)
+// The laser beam it the surface from top to bottom at the center (0,0). 
+// The units assumed for the distance is the micrometer (um)
+
+
+//***********************
+//*** User parameters ***
+//***********************
+
+real radius=1000;   // the wafer radius (um)
+real thick=600;     // the wafer thickness (um)
+real thC=1.5e-4;    // the thermal conductivity (W/K/um)
+real beamr=2;     // the laser beam radius (in the sens of a gaussian)
+real refl=0.55;     // reflection coefficient Air/Silicon
+real Eg=1.12;       // Band gap of Silicon (eV)
+real En=1.49;       // Energy of laser (eV) - must be greater than Eg.
+real I0=1e-2;       // Laser beam intensity (W/um^2)
+real alpha=0.2;     // absorption coefficient (um^-1)
+func f=I0 * (1-refl) * (En-Eg)/En * alpha * exp(alpha*y) * exp(-x*x/beamr/beamr);
+                    // the heat generation function: a laser beam of radius 'beamr'
+                    // lateral shape is gaussian.
+                    // in depth shape is decreasing exponential because of absorption.
+real g=300;          // temperature at right and bottom surfaces (in Kelvin)
+
+//********************************
+//*** Geometry/Mesh definition ***
+//********************************
+
+
+//--- less basic mesh ---
+border bottom1(t=0,radius/5) {x=t; y=-thick; label=1;}
+border bottom2(t=radius/5,radius) {x=t; y=-thick; label=2;}
+border right1(t=-thick,0) {x=radius; y=t; label=3;};  // 'right' actually means external surface
+border top1(t=radius,radius/5*3) {x=t; y=0; label=4;};
+border top2(t=radius/5*3,radius/5) {x=t; y=0; label=5;}
+border top3(t=radius/5,0) {x=t; y=0; label=6;};
+border left1(t=0,-thick/5) {x=0; y=t; label=7;}; // 'left' actually means center of cylinder
+border left2(t=-thick/5,-thick) {x=0; y=t; label=8;}; // 'left' actually means center of cylinder
+mesh Th = buildmesh ( bottom1(20) + bottom2(10) + right1(20) + top1(10) + top2(20) + top3(50) + left1(50) + left2(25) );
+
+plot(Th,wait=1,fill=1,ps="wafer_mesh2.eps");
+//savemesh(Th,"wafer_stuck.msh");
+
+
+//**************************
+//*** Problem definition ***
+//**************************
+
+
+
+fespace Vh(Th,P1);
+Vh u,v,zero;
+
+u=0;     // The temperature variable.
+v=0;     // The weight function.
+zero=0;  // used to set initial condition
+int i=0; // variable used for mesh reconstruction
+real error=0.1, coef=0.1^(1./5.);
+
+
+//--- Variational Form ----
+problem Problem1(u,v,solver=CG,init=i,eps=1.0e-8) =
+int2d(Th) ( x*dx(u)*dx(v) + x*dy(u)*dy(v) )
+  + int2d(Th) ( -v*x*f/thC )    // the source term = laser heating 
+  + on( 1,2,3,u=g ) ;             // fixed temperature at bottom and right surface.
+
+
+
+//*************
+//*** Solve ***
+//*************
+
+
+real cpu=clock();
+
+cout << "***USER*** " << "Begin solve/adapt iterations" << endl;
+
+for (i=0;i<10;i++)
+{
+  cout << "***USER*** " << "Iteration number: " << i << endl;
+  real d = clock();
+  Problem1;
+  plot(u,wait=1);
+  Th=adaptmesh(Th,u,inquire=1,err=error);
+  cout << " CPU = " << clock()-d << endl;
+
+  error = error * coef;
+  
+} ;
+
+plot(Th,wait=1,bb=[[0,0],[-10,-10]],nbiso=20,ps="adaptedmesh.eps"); // plot the last adapted mesh
+plot(u,wait=1,bb=[[0,0],[-10,-10]],nbiso=20,ps="temperature.eps"); // plot the solution
+
+
+//Plot a cut section at r=0
+real[int] xx(10),yy(10);
+for (i=0;i<10;i++)
+{
+  x=0.; y=i/10.; // this line is used by the next one 
+  xx[i]=i;
+  yy[i]=u; // value of u at point (0. , i/10.)
+}
+
+plot([xx,yy],ps="likegnu.eps",wait=true);
+
+
+cout << " CPU = " << clock()-cpu << endl;
diff --git a/examples-bamg/NACA012/ad.sh b/examples-bamg/NACA012/ad.sh
new file mode 100755
index 0000000..b413502
--- /dev/null
+++ b/examples-bamg/NACA012/ad.sh
@@ -0,0 +1,91 @@
+#!/bin/sh -eu
+#   the -e option to stop  on error
+#   we are with awk to do real operation in the shell
+#
+bamg=../../bamg-g
+NSC2KE=s/NSC2KE
+
+# for awk because in french the number 1/1000 is written 0,001 not 0.001
+# to be sure the RADIXCHAR  is '.'   (cf.  Native Language Support)
+LANG=C
+export LANG
+
+#  some VAR
+ifin=2
+j=0
+INIT=0
+LastIteration=0
+NBITER=50
+HMIN=0.05
+HMINGLOBAL=0.0005
+HCOEF=0.8
+
+#  clean of the output file 
+rm -f [A-Z]*
+
+#  create the geometry file 
+awk -f naca.awk </dev/null >MESH_g.msh 
+
+#  create the initial mesh  MESH_0.amdba
+$bamg  -g MESH_g.msh -o  MESH_$j.msh -hmax 2 -oamdba MESH_$j.amdba
+
+while [ $j -lt $ifin ] ; do
+   #  i = j + 1
+   i=`expr $j + 1`
+
+   #  LastIteration = LastIteration + NBITER
+   LastIteration=`expr $LastIteration + $NBITER`
+
+
+   ## set the current MESH
+   rm -f  MESH
+   ln -s MESH_$j.amdba MESH
+
+   ## create the DATA file for NSC2KE form file data
+   ##  change  2 lines for initialisation 
+   rm -f DATA
+   sed -e "s/^INIT/$INIT/" -e "s/^LastIteration/$LastIteration/" <data >DATA
+
+   echo "--------- NSC2KE iteration $j    -----------"
+   $NSC2KE
+   ## mv the GNU file 
+   for file in GNU.MACH  GNU.MESH  GNU.PRES  GNU.TEMP  GNU.TURB  GNU.VECT;do
+     mv -f $file $file.$j 
+   done
+   ##  find the nb of vertices in the file MESH 
+   nbv=`head -1 MESH|awk '{print $1}'`
+
+   ##  create the bb file for interpolation 
+   echo "2 4 $nbv  2" > SOL_$j.bb
+   cat  SOL_NS  >> SOL_$j.bb
+
+   ## create the bb file for metric construction 
+   ## in file SOL_NS  on each line i we have  ro ro*u ro*v  energy 
+   ## at vertex i 
+   ## + a last line with 2 number last iteration and last time
+   echo "2 1 $nbv  2" > MACH.bb
+   awk 'NF==4 { print sqrt($2*$2+$3*$3)/$1}' SOL_NS >>  MACH.bb
+
+   ##  put all the residual in one file 
+   cat RESIDUAL >>RESIDU
+
+   ## set HMIN = MAX($HMINGLOBAL,$HMIN*$HCOEF) 
+   HMIN=`awk "END {c=$HMIN*$HCOEF;c=c<$HMINGLOBAL ?$HMINGLOBAL:c; print c};" </dev/null`
+
+   echo    -b MESH_$j.msh -err 0.001 -errg 0.05 -AbsError \
+      -hmin $HMIN -hmax 3 -Mbb MACH.bb  -o  MESH_$i.msh \
+      -oamdba MESH_$i.amdba  -raison 2 -rbb SOL_$j.bb -wbb INIT_$i.bb  \
+      -maxsubdiv 2 > DATA_bamg
+     $bamg  
+
+   
+
+   ##  creation of the INIT_NS for NSC2KE
+   ##  remove fisrt line form bb file and  add the last line of  SOL_NS
+   sed 1d <INIT_$i.bb >INIT_NS
+   tail -1 SOL_NS >>INIT_NS
+
+   # change i and not initialisation
+   j=$i
+   INIT=1
+done
diff --git a/examples-bamg/NACA012/adap.sh b/examples-bamg/NACA012/adap.sh
new file mode 100755
index 0000000..4c16a17
--- /dev/null
+++ b/examples-bamg/NACA012/adap.sh
@@ -0,0 +1,99 @@
+#!/bin/sh -eu
+#   the -e option to stop  on error
+#   we are with awk to do real operation in the shell
+#
+bamg=../../bamg
+NSC2KE=s/NSC2KE
+
+# for awk because in french the number 1/1000 is written 0,001 not 0.001
+# to be sure the RADIXCHAR  is '.'   (cf.  Native Language Support)
+LANG=C
+export LANG
+
+#  some VAR
+ifin=20
+j=0
+INIT=0
+LastIteration=0
+NBITER=500
+# ---------
+HMIN=1e-6
+HMINGLOBAL=$HMIN
+HCOEF=1
+# -------
+ERR=0.1
+ERRCOEF=0.8608916593317348
+ERRGLOBAL=0.01
+# -----------
+#  end of some parameters 
+# ----------
+#  clean of the output file 
+rm -f [A-Z]*
+
+#  create the geometry file 
+awk -f naca.awk </dev/null >MESH_g.msh 
+
+#  create the initial mesh  MESH_0.amdba
+$bamg  -g MESH_g.msh -o  MESH_$j.msh -hmax 1 -oamdba MESH_$j.amdba
+
+while [ $j -lt $ifin ] ; do
+   #  i = j + 1
+   i=`expr $j + 1`
+
+   #  LastIteration = LastIteration + NBITER
+   LastIteration=`expr $LastIteration + $NBITER`
+
+
+   ## set the current MESH
+   rm -f  MESH
+   ln -s MESH_$j.amdba MESH
+
+   ## create the DATA file for NSC2KE form file data
+   ##  change  2 lines for initialisation 
+   rm -f DATA
+   sed -e "s/^INIT/$INIT/" -e "s/^LastIteration/$LastIteration/" <data >DATA
+
+   echo "--------- NSC2KE iteration $j    -----------"
+   $NSC2KE
+
+   ##  find the nb of vertices in the file MESH 
+   nbv=`head -1 MESH|awk '{print $1}'`
+
+   ##  create the bb file for interpolation 
+   echo "2 4 $nbv  2" > SOL_$j.bb
+   cat  SOL_NS  >> SOL_$j.bb
+
+   ## create the bb file for metric construction 
+   ## in file SOL_NS  on each line i we have  ro ro*u ro*v  energy 
+   ## at vertex i 
+   ## + a last line with 2 number last iteration and last time
+   echo "2 1 $nbv  2" > MACH.bb
+   awk 'NF==4 { print sqrt($2*$2+$3*$3)/$1}' SOL_NS >>  MACH.bb
+
+   ##  put all the residual in one file 
+   cat RESIDUAL >>RESIDU
+
+   ## set HMIN = MAX($HMINGLOBAL,$HMIN*$HCOEF) 
+   HMIN=`awk "END {c=$HMIN*$HCOEF;c=c<$HMINGLOBAL ?$HMINGLOBAL:c; print c};" </dev/null`
+   ERR=`awk "END {c=$ERR*$ERRCOEF;c=c<$ERRGLOBAL ?$ERRGLOBAL:c; print c};" </dev/null`
+
+   echo " -b MESH_$j.msh -err $ERR -errg 0.05 -AbsError  
+      -hmin $HMIN -hmax 1 -Mbb SOL_$j.bb   -o  MESH_$i.msh 
+      -oamdba MESH_$i.amdba  -raison 2.5  -rbb SOL_$j.bb   
+      -splitpbedge  -maxsubdiv 1.8
+      -wbb INIT_$i.bb -v 4 ">DATA_bamg
+
+   echo --- bamg parameters ---
+   cat DATA_bamg
+   echo ----------------------
+   $bamg 
+
+   ##  creation of the INIT_NS for NSC2KE
+   ##  remove fisrt line form bb file and  add the last line of  SOL_NS
+   sed 1d <INIT_$i.bb >INIT_NS
+   tail -1 SOL_NS >>INIT_NS
+
+   # change i and not initialisation
+   j=$i
+   INIT=1
+done
diff --git a/examples-bamg/NACA012/adap.sh-g b/examples-bamg/NACA012/adap.sh-g
new file mode 100755
index 0000000..0427857
--- /dev/null
+++ b/examples-bamg/NACA012/adap.sh-g
@@ -0,0 +1,89 @@
+#!/bin/sh -eu
+#   the -e option to stop  on error
+#   we are with awk to do real operation in the shell
+#
+bamg=../../bamg-g
+NSC2KE=s/NSC2KE
+
+# for awk because in french the number 1/1000 is written 0,001 not 0.001
+# to be sure the RADIXCHAR  is '.'   (cf.  Native Language Support)
+LANG=C
+export LANG
+
+#  some VAR
+ifin=20
+j=0
+INIT=0
+LastIteration=0
+NBITER=500
+HMIN=0.05
+HMINGLOBAL=0.0005
+HCOEF=0.8
+
+#  clean of the output file 
+rm -f [A-Z]*
+
+#  create the geometry file 
+awk -f naca.awk </dev/null >MESH_g.msh 
+
+#  create the initial mesh  MESH_0.amdba
+echo -- $bamg  -g MESH_g.msh -o  MESH_$j.msh -hmax 2 -oamdba MESH_$j.amdba
+$bamg  -g MESH_g.msh -o  MESH_$j.msh -hmax 2 -oamdba MESH_$j.amdba
+
+while [ $j -lt $ifin ] ; do
+   #  i = j + 1
+   i=`expr $j + 1`
+
+   #  LastIteration = LastIteration + NBITER
+   LastIteration=`expr $LastIteration + $NBITER`
+
+
+   ## set the current MESH
+   rm -f  MESH
+   ln -s MESH_$j.amdba MESH
+
+   ## create the DATA file for NSC2KE form file data
+   ##  change  2 lines for initialisation 
+   rm -f DATA
+   sed -e "s/^INIT/$INIT/" -e "s/^LastIteration/$LastIteration/" <data >DATA
+
+   echo "--------- NSC2KE iteration $j    -----------"
+   $NSC2KE
+
+   ##  find the nb of vertices in the file MESH 
+   nbv=`head -1 MESH|awk '{print $1}'`
+
+   ##  create the bb file for interpolation 
+   echo "2 4 $nbv  2" > SOL_$j.bb
+   cat  SOL_NS  >> SOL_$j.bb
+
+   ## create the bb file for metric construction 
+   ## in file SOL_NS  on each line i we have  ro ro*u ro*v  energy 
+   ## at vertex i 
+   ## + a last line with 2 number last iteration and last time
+   echo "2 1 $nbv  2" > MACH.bb
+   awk 'NF==4 { print sqrt($2*$2+$3*$3)/$1}' SOL_NS >>  MACH.bb
+
+   ##  put all the residual in one file 
+   cat RESIDUAL >>RESIDU
+
+   ## set HMIN = MAX($HMINGLOBAL,$HMIN*$HCOEF) 
+   HMIN=`awk "END {c=$HMIN*$HCOEF;c=c<$HMINGLOBAL ?$HMINGLOBAL:c; print c};" </dev/null`
+  echo -----
+  echo  $bamg  -b MESH_$j.msh -err 0.001 -errg 0.05 -AbsError '\\'
+  echo       -hmin $HMIN -hmax 3 -Mbb MACH.bb  -o  MESH_$i.msh '\\'
+  echo      -oamdba MESH_$i.amdba  -raison 2 -rbb SOL_$j.bb -wbb INIT_$i.bb  
+
+   $bamg  -b MESH_$j.msh -err 0.001 -errg 0.05 -AbsError \
+      -hmin $HMIN -hmax 3 -Mbb MACH.bb  -o  MESH_$i.msh \
+      -oamdba MESH_$i.amdba  -raison 2 -rbb SOL_$j.bb -wbb INIT_$i.bb 
+
+   ##  creation of the INIT_NS for NSC2KE
+   ##  remove fisrt line form bb file and  add the last line of  SOL_NS
+   sed 1d <INIT_$i.bb >INIT_NS
+   tail -1 SOL_NS >>INIT_NS
+
+   # change i and not initialisation
+   j=$i
+   INIT=1
+done
diff --git a/examples-bamg/NACA012/data b/examples-bamg/NACA012/data
new file mode 100644
index 0000000..11a47a8
--- /dev/null
+++ b/examples-bamg/NACA012/data
@@ -0,0 +1,25 @@
+0          --> =0 2D, =1 AXISYMMETRIC
+0          --> =0 Euler, =1 Navier-Stokes
+1.e2       --> Reynolds by meter (the mesh is given in meter)
+0.         --> inverse of Froude number (=0 no gravity)
+0.96        --> inflow Mach number
+1.         --> ratio pout/pin
+1          --> wall =1 newmann b.c.(adiabatic wall), =2 (isothermal wall)
+300.       --> inflow temperature (in Kelvin) for Sutherland laws
+288.       --> if isothermal walls , wall temperature (in Kelvin)
+0.0        --> angle of attack
+1          --> Euler fluxes =1 roe, =2 osher,=3 kinetic
+3          --> nordre = 1st order scheme, =2 2ndorder, =3 limited 2nd order
+1          --> =0 global time steping (unsteady), =1 local Euler, =2 local N.S.
+1.        --> cfl 
+LastIteration --> number of time step
+500        --> frequence for the  solution to be saved
+1.e10      --> maximum physical time for run (for unsteady problems)
+-4.        --> order of magnitude for the residual to be reduced (for steady problems)
+INIT        --> =0 start with uniform solution, =1 restart from INIT_NS
+cccc  turbulence  ccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+0          --> =0 no turbulence model, =1 k-epsilon model
+0          --> =0 two-layer technique, =1 wall laws
+1.e-2      --> delta in wall laws or limit of the one-eq. model. (in meter)
+0          --> =0 start from uniform solution for k-epsilon, =1 from INIT_KE
+-1.e10 1.e10 -1.e10 1.e10    --> xtmin,xtmax,ytmin,ytmax (BOX for k-epsilon r.h.s)
diff --git a/examples-bamg/NACA012/data-orign b/examples-bamg/NACA012/data-orign
new file mode 100644
index 0000000..013f902
--- /dev/null
+++ b/examples-bamg/NACA012/data-orign
@@ -0,0 +1,25 @@
+0          --> =0 2D, =1 AXISYMMETRIC
+0          --> =0 Euler, =1 Navier-Stokes
+1.e2       --> Reynolds by meter (the mesh is given in meter)
+0.         --> inverse of Froude number (=0 no gravity)
+0.8        --> inflow Mach number
+1.         --> ratio pout/pin
+1          --> wall =1 newmann b.c.(adiabatic wall), =2 (isothermal wall)
+300.       --> inflow temperature (in Kelvin) for Sutherland laws
+288.       --> if isothermal walls , wall temperature (in Kelvin)
+0.0        --> angle of attack
+1          --> Euler fluxes =1 roe, =2 osher,=3 kinetic
+3          --> nordre = 1st order scheme, =2 2ndorder, =3 limited 2nd order
+1          --> =0 global time steping (unsteady), =1 local Euler, =2 local N.S.
+1.        --> cfl 
+LastIteration --> number of time step
+500        --> frequence for the  solution to be saved
+1.e10      --> maximum physical time for run (for unsteady problems)
+-4.        --> order of magnitude for the residual to be reduced (for steady problems)
+INIT        --> =0 start with uniform solution, =1 restart from INIT_NS
+cccc  turbulence  ccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+0          --> =0 no turbulence model, =1 k-epsilon model
+0          --> =0 two-layer technique, =1 wall laws
+1.e-2      --> delta in wall laws or limit of the one-eq. model. (in meter)
+0          --> =0 start from uniform solution for k-epsilon, =1 from INIT_KE
+-1.e10 1.e10 -1.e10 1.e10    --> xtmin,xtmax,ytmin,ytmax (BOX for k-epsilon r.h.s)
diff --git a/examples-bamg/NACA012/naca.awk b/examples-bamg/NACA012/naca.awk
new file mode 100644
index 0000000..c473cd7
--- /dev/null
+++ b/examples-bamg/NACA012/naca.awk
@@ -0,0 +1,47 @@
+END {
+Pi=3.14159265358979;
+i20=20;
+i8=8;
+r = 5;
+c0x = 1;
+c0y=0;
+print "Dimension",2;
+print "MaximalAngleOfCorner 46";
+
+
+print "Vertices",i20+i20+i8;
+
+# the vertex on naca012  wing ( clock wise)
+ for (i=-i20;i<i20;i++) {
+   x = i/i20;
+   x = x^4; 
+   t = 1.008930411365*x;
+   y = 5*.12*(0.2969*sqrt(t) - 0.126*t - 0.3516*t^2 + 0.2843*t^3 - 0.1015*t^4);
+   if(i<0) y=-y;
+   print x,y,3;}
+ 
+# vertex on circle  (counter clock wise)
+ for (i=0;i<i8;i++) {
+   t=i*Pi*2/i8;
+   print c0x+r*(cos(t)),c0y+r*sin(t),5;}
+
+
+ print "Edges",i20+i20+i8;
+
+#  edge on wing  
+ k = 1
+ j = i20+i20-1; # previous points
+ for (i=0;i<i20+i20;j=i++) 
+   { print j+k,i+k,3;} # previous, current vertex
+
+# edge on circle 
+ k = i20+i20+1;
+ j = i8-1;# previous points
+ for (i=0;i<i8;j=i++) 
+   { print k+j,k+i,5;} # previous, current vertex
+
+#   one subdomain, region on left side of the wing
+#   because clock wise sens.
+ print "SubDomain",1;
+ print 2,1,1,0;
+}
diff --git a/examples-bamg/NACA012/plot.fv b/examples-bamg/NACA012/plot.fv
new file mode 100644
index 0000000..c23ced4
--- /dev/null
+++ b/examples-bamg/NACA012/plot.fv
@@ -0,0 +1,62 @@
+  listing 
+
+  character*20 MMMM,MACH,SOL, chari
+  integer nbv,dim,nbfield
+  dynamique mach(*),sol(*,*)
+  real aaa,bbb
+  integer i,j 
+  MMMM = ' '
+  MACH = ' '
+
+  do i = 0,19
+   destroy all
+c   exec('./MkMach '//charac(i))
+   MMMM = 'MESH_'//charac(i)
+   MACH = 'MACH_'//charac(i)
+   SOL  = 'SOL_'//charac(i)
+   print *,'"',MACH,'"  "',SOL,'"'
+   readg emc2 MMMM
+   print *,'"',MACH,'"  "',SOL,'"'
+   readg bb  SOL 
+   print *,'--------'
+   look : 1   emc2 D2 MMMM
+  print *,'1 --------'
+  sizeof SOL nbfield ,nbv,dim
+  print *,'2 --------',nbv,dim,nbfield
+  new sol(nbfield,nbv)
+  get SOL sol
+  print *,'3 --------'
+  new mach(nbv)
+  aaa=0
+  bbb=1000
+  do j=1,nbv
+    mach(j) = sqrt(sol(1,j)**2 +  sol(2,j)**2)
+    aaa=max(aaa,mach(j))
+    bbb=min(bbb,mach(j))
+  enddo
+  print *,'min = ',bbb,' max = ',aaa,' ------------------'
+  print *,'----------------------------------------------'
+  set ssom D2 scal  MACH mach nbv 
+  how2look faces_vues
+  how2look line_skin
+  zoomp 1, 41.74853, 45.43906, 50.96038, 56.97087
+  refresh
+  exec('rm '// MMMM(1:index(MMMM,' ')-1) //'.ps '//MACH(1:index(MACH,' ')-1)//'.ps')
+!  soft_copy 'np  nlogo ncadre v x10 y7 f'//MMMM 
+!  refresh
+ look : 1   scal D2 MACH
+  with isovalue number 50 from 1 to 1.5 ! bw
+  zoomp 1, 41.74853, 45.43906, 50.96038, 56.97087
+!  refresh
+!  how2look no_skin
+  refresh
+  with isovalue drawing
+  with isovalue filling
+  soft_copy 'np  color nlogo ncadre v x10 y7 f'//MACH 
+!  soft_copy 'np  nlogo ncadre v x10 y7 f'//MACH 
+  free sol
+  free mach
+  enddo
+  print *,' ON A FINI ET OUI'
+  end
+;
diff --git a/examples-bamg/quadloop/dotest.pl b/examples-bamg/quadloop/dotest.pl
new file mode 100755
index 0000000..f053995
--- /dev/null
+++ b/examples-bamg/quadloop/dotest.pl
@@ -0,0 +1,175 @@
+#!/usr/bin/perl
+# -- so option
+ 
+##$f="10 +  1/(1+ 100**(sin(x*3)-y)) ";
+$f = "10 + sin(x/10)*cos(y/3)";
+$err=0.001;
+$errg=0.05;
+$nbiteration=3;
+$bamg="../../src/bamg/bamg";
+$quadoption="";
+$bamgoption=" -AbsError -NbJacobi 3  -ratio 2 -anisomax 30";
+$quadoption=" -2q -thetaquad 30 -coef 2";
+
+# ---  change x in $x and y in $y 
+$_=$f;
+s/x/\$x/g;
+s/y/\$y/g;
+$f="$_;";
+print "The function = f(x,y) = $f \n";
+
+#--------------------------
+$suffixe=".mesh";
+$iteration=0;
+$GH="Gh$suffixe";
+$TH="Th$iteration$suffixe";
+$, = ' ';               # set output field separator
+$\ = "\n";              # set output record separator
+##  -------------------------------------------------------------
+##  --- construction the Geometry file Gh.mesh 
+##  a naca0012 wing in a big circle radius 5 
+##   20 points on the up wing 
+##   20 points on the down wing 
+##    8 points on circle of radius r 
+open(GH,">$GH")  || die "Can't redirect stdout";
+$Pi = 3.14159265358979;
+$i20 = 20;
+$i8 = 8;
+$r = 5;
+$c0x = 1;
+$c0y = 0;
+print GH 'Dimension', 2;
+print GH 'MaximalAngleOfCorner 46';
+
+print GH 'Vertices';
+print GH $i20 + $i20 + $i8;
+
+# the vertex on naca012  wing ( clock wise)
+for ($i = -$i20; $i < $i20; $i++) {
+    $X = $i / $i20;
+    $X = $X ** 4;
+
+    $t = 1.008930411365 * $X;
+    $Y = 5 * .12 * (0.2969 * sqrt($t) - 0.126 * $t - 0.3516 * $t ** 2 + 0.2843
+
+      * $t ** 3 - 0.1015 * $t ** 4);
+    if ($i < 0) {
+        $Y = -$Y;
+    }
+    print GH $X, $Y, 3;
+}
+
+# vertex on circle  (counter clock wise)
+for ($i = 0; $i < $i8; $i++) {
+    $t = $i * $Pi * 2 / $i8;
+    print GH $c0x + $r * (cos($t)), $c0y + $r * sin($t), 5;
+}
+
+print GH 'Edges', $i20 + $i20 + $i8;
+
+#  edge on wing  
+$k = 1;
+$j = $i20 + $i20 - 1;
+# previous points
+for ($i = 0; $i < $i20 + $i20; $j = $i++) {
+    print GH $j + $k, $i + $k, 3;
+}
+# previous, current vertex
+
+# edge on circle 
+$k = $i20 + $i20 + 1;
+$j = $i8 - 1;
+# previous points
+for ($i = 0; $i < $i8; $j = $i++) {
+    print GH $k + $j, $k + $i, 5;
+}
+# previous, current vertex
+
+#   one subdomain, region on left side of the wing
+#   because clock wise sens.
+print GH 'SubDomain', 1;
+print GH 2, 1, 1, 0;
+close GH;
+##  -------------- END construct of the geom 
+## 
+
+# -- make the DATA file for the mesh to also  save the arguments 
+open(BAMG,">DATA_bamg")  || die "Can't open  DATA_bamg";
+print BAMG "$quadoption $bamgoption  -g $GH -o $TH  -v 9";
+close(BAMG);
+
+## constructio the inital  mesh 
+!system($bamg) || die "Error in bamg construction of initial  mesh $Th";
+
+##  the adpatation loop 
+while ($iteration<$nbiteration) {
+
+    
+    $BB="$iteration.bb";
+    
+##  construction of the solution  
+    $errsol=0;
+    open (TH,"<$TH") ||  die "Can't open  $TH";
+    open (BB,">$BB") ||  die "Can't open  $BB";
+    open (PLOT,">PLOT") || die "Can't open PLOT";
+    while (<TH>) {
+	if(/^Vertices$/) {
+	    $nbv=<TH>;
+	    chop($nbv);
+	    print BB "2 1 $nbv 2";
+	    for ($i=1;$i<=$nbv;$i++) {
+		($x,$y,$ref)=split(/[\ \t\n]+/, <TH>);
+		$fxy=eval $f;
+
+		$xx[$i]=$x;
+		$yy[$i]=$y;
+		$ff[$i]=$fxy;
+
+		print BB $fxy;
+	    };
+	};
+	if(/^Triangles$/) {
+	    print " Nb of Triangles = $nbt \n";
+	    $nbt=<TH>;
+	    chop($nbt);
+	    for ($i=1;$i<=$nbt;$i++) {
+		($i0,$i1,$i2,$ref)=split(/[\ \t\n]+/, <TH>);
+		print PLOT "$xx[$i0] $yy[$i0] $ff[$i0]";
+		print PLOT "$xx[$i1] $yy[$i1] $ff[$i1]";
+		print PLOT "$xx[$i2] $yy[$i2] $ff[$i2]";
+		print PLOT "$xx[$i0] $yy[$i0] $ff[$i0]";
+		print PLOT "";
+
+		$x   = ($xx[$i0]+$xx[$i1]+$xx[$i2])/3;
+		$y   = ($yy[$i0]+$yy[$i1]+$yy[$i2])/3;
+		$fm  = ($ff[$i0]+$ff[$i1]+$ff[$i2])/3;
+		$fxy = eval $f;
+		$vv=($fm-$fxy);
+		$vv= ($vv<0)?-$vv:$vv;
+	#	print " $i0 $i1 $i2 $xx[$i0] $xx[$i1] $xx[$i2] ";
+	#	print " $i $x $y $fm $fxy err= $errsol diff=$vv";
+		$errsol = ($errsol>$vv) ? $errsol : $vv;
+	    };
+	};
+
+    };
+    close TH;
+    close BB;
+    close PLOT;
+    print " ---------------------------------------------\n";
+    print "\n\n Iteration $iteration\n Erreur L_infini = $errsol \n\n";
+    print " ---------------------------------------------\n";
+
+##  -----------------------
+    
+    $iteration++;
+    $BTH=$TH;
+    $TH="Th$iteration$suffixe";
+    
+    open(BAMG,">DATA_bamg")  || die "Can't open  DATA_bamg";
+    print BAMG "$quadoption  $bamgoption  -Mbb $BB -errg $errg -err $err   -b $BTH -o $TH  -v 9";
+    close(BAMG);
+    !system($bamg) ||    die "Error in bamg construction of adapted $iteration  mesh $Th";
+}
+
+print "Normal End\n";
diff --git a/examples-bamg/square/circle_g.mesh b/examples-bamg/square/circle_g.mesh
new file mode 100644
index 0000000..54499df
--- /dev/null
+++ b/examples-bamg/square/circle_g.mesh
@@ -0,0 +1,25 @@
+MeshVersionFormatted 0
+MaximalAngleOfCorner 46
+Dimension 2
+Vertices 8
+1 0 1
+.7071067811865476 .7071067811865476 1
+0 1 1
+-.7071067811865476 .7071067811865476 1
+-1 0 1
+-.7071067811865476 -.7071067811865476 1
+0 -1 1
+.7071067811865476 -.7071067811865476 1
+
+Edges 8
+1 2 1
+2 3 1
+3 4 1
+4 5 1
+5 6 1
+6 7 1
+7 8 1
+8 1 1
+
+hVertices
+0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 
diff --git a/examples-bamg/square/doadapt b/examples-bamg/square/doadapt
new file mode 100755
index 0000000..f7044e6
--- /dev/null
+++ b/examples-bamg/square/doadapt
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+prefix=circle
+equation='100*x*x*x+y*y+20*x*y'
+
+ if [ -z "$bamg" ] ;then bamg=../../bamg; fi
+
+#   for compatibility  pb in awk if  LANG=French 
+LANG=C
+export LANG
+
+##   initialisation 
+  i=0 
+  MESH=${prefix}_$i.mesh
+  GEOM=${prefix}_g.mesh
+  echo    ${bamg} -g $GEOM   -o $MESH -oam_fmt $MESH.am_fmt
+  ${bamg} -g $GEOM   -o $MESH -oam_fmt $MESH.am_fmt
+##  do a simple loop of adpation i1 = i-1   
+  for i in 1 2 3  ; do
+
+	 BACK=${MESH}
+ 	 MESH=${prefix}_$i.mesh
+ 	 SOL=${BACK}.bb
+
+  #  generation of the solution file with awk 
+	 awk '   BEGIN {k=0}
+  	         k>0  {k--; x=$1;y=$2;print '$equation'}
+	        (k==-1)  {k=$1; print 2,1,k,2;}
+                $1=="Vertices"  {k=-1;}
+              ' $BACK > $SOL
+  # generation of the adapted mesh 
+  echo  ${bamg} -AbsError -v 8 -b $BACK -Mbb $SOL -err 0.005 -hmin 0.00001   -NbSmooth 3 -NbJacobi 3 -o $MESH	-oam_fmt $MESH.am_fmt
+	${bamg} -AbsError -v 8 -b $BACK -Mbb $SOL -err 0.005 -hmin 0.00001   -NbSmooth 3 -NbJacobi 3 -o $MESH	-oam_fmt $MESH.am_fmt
+	echo "to see the result enter :  ../../drawbdmesh $MESH"
+   done 
diff --git a/examples-bamg/square/dotest b/examples-bamg/square/dotest
new file mode 100755
index 0000000..00870b5
--- /dev/null
+++ b/examples-bamg/square/dotest
@@ -0,0 +1,45 @@
+rm -f *[0s].mesh
+g=
+quad=
+if [ "$1" = "-g" ] ;then g=-g;shift; fi
+if [ "$1" = "-q" ] ;then quad="-2q -coef 2 -thetaquad 10" ;shift; fi
+if [ "$1" = "-g" ] ;then g=-g;shift; fi
+
+if [ -z "$bamg" -o ! -x "$bamg" ] ;then bamg=../../bamg$g; fi
+echo " to close the graphic enter f on graphic window until they exist "
+echo "Mesh  square " 
+echo ${bamg} -g  square_g.mesh -o square_0.mesh $quad
+${bamg} -g  square_g.mesh -o square_0.mesh $quad
+if [  $? -ne 0 -o ! -s square_0.mesh ] ; then echo "the file square_0.mesh  is empty or d'ont exist";exit 1 ; fi
+
+echo ${bamg} -g  square_g.mesh -o square_0.mesh $quad
+${bamg} -splitpbedge  -g  square_g.mesh -o square_s.mesh  $quad
+if [  $? -ne 0 -o ! -s square_0.mesh ] ; then echo "the file square_s.mesh  is empty or d'ont exist";exit 1 ; fi
+
+echo "Mesh  circle  " 
+${bamg} -g  circle_g.mesh -o circle_0.mesh $quad
+if [ $? -ne 0 -o  ! -s circle_0.mesh ] ; then echo "the file circle_0.mesh  is empty or d'ont exist";exit 1 ; fi
+
+echo "Mesh  a octogone  " 
+${bamg} -g  octogone_g.mesh -o octogone_0.mesh $quad
+if [ ! -s octogone_0.mesh ] ; then echo "the file octogone_0.mesh  is empty or d'ont exist";exit 1 ; fi
+
+echo "Mesh  a  square with raff  " 
+${bamg} -g  square_raf_g.mesh -o square_raf_0.mesh $quad
+if [ $? -ne 0 -o ! -s  square_raf_0.mesh ] ; then echo "the file  square_raf_0.mesh  is empty or d'ont exist";exit 1 ; fi
+
+echo "Mesh  a  square with raff  split pb edge" 
+${bamg} -splitpbedge -g  square_raf_g.mesh -o square_raf_s.mesh $quad
+if [ $? -ne 0 -o ! -s  square_raf_0.mesh ] ; then echo "the file  square_raf_0.mesh  is empty or d'ont exist";exit 1 ; fi
+
+echo "Mesh  a  square with anisotropique mesh  " 
+${bamg} -g  square_raf_g.mesh -o square_raf_ani_0.mesh -M square_raf_ani_g.mtr $quad
+if [ $? -ne 0 -o ! -s  square_raf_ani_0.mesh ] ; then echo "the file  square_raf_ani_0.mesh  is empty or d'ont exist";exit 1 ; fi
+
+echo "Mesh  a  square with anisotropique mesh with -splitpbedge " 
+${bamg} -splitpbedge -g  square_raf_g.mesh -o square_raf_ani_s.mesh -M square_raf_ani_g.mtr $quad
+if [ $? -ne 0 -o ! -s  square_raf_ani_s.mesh ] ; then echo "the file  square_raf_ani_s.mesh  is empty or d'ont exist";exit 1 ; fi
+
+${bamg} -splitpbedge -g  l_g.mesh -o l_0.mesh  $quad
+if [ $? -ne 0 -o ! -s  l_0.mesh ] ; then echo "the file   l_0.mesh  is empty or d'ont exist";exit 1 ; fi
+
diff --git a/examples-bamg/square/l_g.mesh b/examples-bamg/square/l_g.mesh
new file mode 100644
index 0000000..2af20e4
--- /dev/null
+++ b/examples-bamg/square/l_g.mesh
@@ -0,0 +1,488 @@
+ MeshVersionFormatted 0
+
+ Dimension
+ 2
+
+ AngleOfCornerBound
+ 30
+
+ Vertices
+ 226
+ 7.5 -2.27374E-13 5
+ 7.1962 2.11299 4
+ 6.3094 4.05481 4
+ 4.91146 5.66812 4
+ 3.11561 6.82224 4
+ 1.06736 7.42366 4
+ -1.06736 7.42366 4
+ -3.11561 6.82224 4
+ -4.91146 5.66812 4
+ -6.3094 4.05481 4
+ -7.1962 2.113 4
+ -7.5 -2.44381E-06 5
+ -6.0 58.86447 3
+ -6.44157 61.39993 3
+ -7.71429 63.63684 2
+ -9.09783 12.54909 5
+ -7.43538 14.2087 3
+ -6.36787 16.30117 3
+ -6.0 18.62123 3
+ 7.71429 63.63684 2
+ 6.44157 61.39993 3
+ 6.0 58.86447 3
+ 8.96137 65.56223 2
+ 9.73688 67.72115 2
+ 6.0 18.62123 3
+ 6.36787 16.30117 3
+ 7.43538 14.2087 3
+ 9.09783 12.54909 5
+ 6.0 56.85231 3
+ 6.0 54.84015 3
+ 6.0 52.82799 3
+ 6.0 50.81583 3
+ 6.0 48.80367 3
+ 6.0 46.7915 3
+ 6.0 44.77934 3
+ 6.0 42.76718 3
+ 6.0 40.75502 3
+ 6.0 38.74286 3
+ 6.0 36.7307 3
+ 6.0 34.71854 3
+ 6.0 32.70638 3
+ 6.0 30.69421 3
+ 6.0 28.68205 3
+ 6.0 26.66989 3
+ 6.0 24.65773 3
+ 6.0 22.64557 3
+ 6.0 20.63341 3
+ 12.54909 9.09783 6
+ 14.2087 7.43538 6
+ 16.30117 6.36787 6
+ 18.62123 6.0 6
+ 28.86447 6.0 6
+ 31.39993 6.44157 6
+ 33.63684 7.71429 7
+ 33.63684 -7.71429 7
+ 31.39993 -6.44157 6
+ 28.86447 -6.0 6
+ 3.5 70.0 2
+ 2.83156 72.05725 1
+ 1.08156 73.3287 1
+ -1.08156 73.3287 1
+ -2.83156 72.05725 1
+ -3.5 70.0 2
+ 43.5 .0 7
+ 42.83156 2.05725 8
+ 41.08156 3.3287 8
+ 38.91844 3.3287 8
+ 37.16844 2.05725 8
+ 36.5 -1.14045E-06 7
+ 10.96016 10.96016 5
+ 20.66988 6.0 6
+ 22.71853 6.0 6
+ 24.76718 6.0 6
+ 26.81582 6.0 6
+ 35.34489 -8.85042 7
+ 37.24883 -9.61411 7
+ 39.26855 -9.97321 7
+ 41.31905 -9.91262 7
+ 43.31404 -9.43489 7
+ 45.16957 -8.56012 7
+ 46.80755 -7.32511 7
+ 48.15905 -5.78185 7
+ 49.16721 -3.99528 7
+ 49.78959 -2.04058 7
+ 50.0 -4.29153E-06 7
+ 26.81582 -6.0 6
+ 24.76717 -6.0 6
+ 22.71852 -6.0 6
+ 20.66987 -6.0 6
+ 18.62123 -6.0 6
+ -10.7016 11.21272 5
+ -12.1113 9.67296 5
+ -13.3013 7.95773 5
+ -14.25 6.09815 5
+ -14.9402 4.12794 5
+ -15.3594 2.08286 5
+ -15.5 9.53674E-07 5
+ -6.0 20.63339 3
+ -6.0 22.64555 3
+ -6.0 24.65771 3
+ -6.0 26.66987 3
+ -6.0 28.68204 3
+ -6.0 30.6942 3
+ -6.0 32.70636 3
+ -6.0 34.71852 3
+ -6.0 36.73068 3
+ -6.0 38.74284 3
+ -6.0 40.755 3
+ -6.0 42.76717 3
+ -6.0 44.77933 3
+ -6.0 46.79149 3
+ -6.0 48.80365 3
+ -6.0 50.81581 3
+ -6.0 52.82797 3
+ -6.0 54.84013 3
+ -6.0 56.85229 3
+ 16.30117 -6.36787 6
+ 14.2087 -7.43538 6
+ 12.54909 -9.09783 6
+ -6.13758 62.10506 3
+ -4.26429 60.95479 3
+ -2.18493 60.24162 3
+ 5.24521E-06 60.0 3
+ 2.18494 60.24162 3
+ 4.2643 60.9548 3
+ 6.13759 62.10507 3
+ 32.10506 6.13758 7
+ 30.95479 4.26429 7
+ 30.24162 2.18494 7
+ 30.0 -4.76837E-07 7
+ 7.26591 13.69148 5
+ 5.29303 14.56825 5
+ 3.21746 15.16239 5
+ 1.07947 15.46237 5
+ -1.07947 15.46237 5
+ -3.21746 15.16239 5
+ -5.29303 14.56825 5
+ -7.26591 13.69148 5
+ 13.816 -7.02624 6
+ 14.74383 -4.78221 6
+ 15.30979 -2.42082 6
+ 15.5 -1.43051E-06 6
+ 49.78959 2.04058 7
+ 49.16721 3.99528 7
+ 48.15906 5.78185 7
+ 46.80755 7.32511 7
+ 45.16957 8.56011 7
+ 43.31404 9.43489 7
+ 41.31905 9.91262 7
+ 39.26855 9.97321 7
+ 37.24883 9.61411 7
+ 35.34489 8.85042 7
+ 45.66667 -1.11262E-06 0
+ 47.83334 -5.56310E-07 0
+ 30.24162 -2.18494 7
+ 30.95479 -4.2643 7
+ 32.10506 -6.13759 7
+ 37.16844 -2.05725 8
+ 38.91844 -3.3287 8
+ 41.08156 -3.3287 8
+ 42.83156 -2.05725 8
+ 34.33333 -1.58946E-07 0
+ 32.16666 -3.17892E-07 0
+ 15.30979 2.42081 6
+ 14.74383 4.78222 6
+ 13.816 7.02625 6
+ -7.1962 -2.11299 4
+ -6.3094 -4.05481 4
+ -4.91146 -5.66812 4
+ -3.11561 -6.82224 4
+ -1.06736 -7.42366 4
+ 1.06736 -7.42366 4
+ 3.11561 -6.82224 4
+ 4.91145 -5.66812 4
+ 6.3094 -4.05481 4
+ 7.1962 -2.113 4
+ -15.3645 -2.04516 5
+ -14.9603 -4.05455 5
+ -14.2945 -5.99305 5
+ -13.3788 -7.82675 5
+ -12.2291 -9.52359 5
+ -10.8656 -11.0539 5
+ -9.31208 -12.3909 5
+ -7.59574 -13.5113 5
+ -5.74658 -14.3954 5
+ -3.79693 -15.0278 5
+ -1.78089 -15.3974 5
+ .2662987 -15.4977 5
+ 2.30883 -15.3271 5
+ 4.31098 -14.8884 5
+ 6.23775 -14.1895 5
+ 8.05545 -13.2424 5
+ 9.73229 -12.0637 5
+ 11.23895 -10.6741 5
+ -13.5 1.93710E-07 0
+ -11.5 -8.94168E-08 0
+ -9.5 -3.72544E-07 0
+ 9.5 -2.29475E-06 0
+ 11.5 -2.32456E-06 0
+ 13.5 -2.35437E-06 0
+ 9.78148 72.07912 2
+ 9.13545 74.06737 2
+ 8.09017 75.87785 2
+ 6.69131 77.43145 2
+ 5.0 78.66026 2
+ 3.09017 79.51057 2
+ 1.04528 79.94522 2
+ -1.04529 79.94522 2
+ -3.09017 79.51057 2
+ -5.0 78.66026 2
+ -6.69131 77.43144 2
+ -8.09017 75.87785 2
+ -9.13546 74.06736 2
+ -9.78148 72.07912 2
+ -10.0 70.0 2
+ -2.83156 67.94275 1
+ -1.08156 66.6713 1
+ 1.08156 66.6713 1
+ 2.83156 67.94275 1
+ -9.73688 67.72115 2
+ -8.96137 65.56223 2
+ -7.83333 70.0 0
+ -5.66667 70.0 0
+ 10.0 70.0 2
+ 5.66667 70.0 0
+ 7.83333 70.0 0
+
+ Edges
+ 236
+ 97 177 5
+ 196 197 0
+ 97 195 0
+ 177 178 5
+ 197 12 0
+ 46 45 3
+ 96 97 5
+ 179 180 5
+ 12 11 4
+ 95 96 5
+ 180 181 5
+ 164 165 6
+ 167 12 4
+ 168 167 4
+ 176 175 4
+ 92 93 5
+ 182 183 5
+ 183 184 5
+ 16 91 5
+ 185 186 5
+ 99 98 3
+ 17 16 3
+ 16 138 5
+ 18 17 3
+ 138 137 5
+ 19 18 3
+ 137 136 5
+ 135 134 5
+ 171 170 4
+ 193 194 5
+ 134 133 5
+ 172 171 4
+ 131 132 5
+ 198 199 0
+ 133 132 5
+ 119 139 6
+ 2 1 4
+ 1 198 0
+ 192 193 5
+ 25 47 3
+ 174 173 4
+ 1 176 4
+ 194 119 5
+ 98 19 3
+ 3 2 4
+ 27 26 3
+ 200 142 0
+ 28 27 3
+ 131 28 5
+ 199 200 0
+ 175 174 4
+ 140 141 6
+ 70 28 5
+ 49 48 6
+ 48 166 6
+ 118 117 6
+ 166 165 6
+ 140 139 6
+ 119 118 6
+ 117 90 6
+ 142 164 6
+ 100 99 3
+ 26 25 3
+ 191 192 5
+ 50 49 6
+ 102 101 3
+ 4 3 4
+ 190 191 5
+ 5 4 4
+ 87 86 6
+ 189 190 5
+ 106 105 3
+ 86 57 6
+ 188 189 5
+ 187 188 5
+ 57 56 6
+ 53 52 6
+ 73 72 6
+ 163 130 0
+ 130 155 7
+ 155 156 7
+ 129 130 7
+ 34 33 3
+ 157 156 7
+ 6 5 4
+ 55 157 7
+ 56 55 6
+ 127 54 7
+ 54 53 6
+ 163 162 0
+ 55 75 7
+ 128 127 7
+ 33 32 3
+ 128 129 7
+ 69 68 7
+ 76 77 7
+ 7 6 4
+ 69 162 0
+ 169 168 4
+ 77 78 7
+ 8 7 4
+ 150 151 7
+ 9 8 4
+ 29 22 3
+ 65 64 7
+ 64 153 0
+ 153 154 0
+ 160 159 8
+ 91 92 5
+ 14 13 3
+ 115 114 3
+ 64 161 7
+ 184 185 5
+ 124 125 3
+ 15 14 2
+ 120 15 2
+ 146 147 7
+ 122 123 3
+ 121 120 3
+ 154 85 0
+ 161 160 8
+ 126 125 3
+ 10 9 4
+ 93 94 5
+ 22 21 3
+ 84 85 7
+ 85 143 7
+ 126 20 2
+ 94 95 5
+ 21 20 2
+ 23 24 2
+ 220 221 2
+ 222 215 0
+ 215 220 2
+ 63 62 1
+ 63 223 0
+ 24 224 2
+ 214 215 2
+ 58 225 0
+ 58 219 1
+ 201 202 2
+ 62 61 1
+ 224 201 2
+ 226 224 0
+ 60 59 1
+ 59 58 1
+ 211 212 2
+ 178 179 5
+ 209 210 2
+ 196 195 0
+ 207 208 2
+ 141 142 6
+ 48 70 5
+ 42 41 3
+ 101 100 3
+ 103 102 3
+ 41 40 3
+ 104 103 3
+ 47 46 3
+ 51 50 6
+ 40 39 3
+ 39 38 3
+ 107 106 3
+ 109 108 3
+ 108 107 3
+ 74 73 6
+ 136 135 5
+ 35 34 3
+ 52 74 6
+ 32 31 3
+ 159 158 8
+ 111 110 3
+ 152 54 7
+ 170 169 4
+ 114 113 3
+ 113 112 3
+ 78 79 7
+ 151 152 7
+ 79 80 7
+ 149 150 7
+ 124 123 3
+ 80 81 7
+ 66 65 8
+ 81 82 7
+ 116 115 3
+ 82 83 7
+ 148 149 7
+ 122 121 3
+ 13 116 3
+ 147 148 7
+ 143 144 7
+ 145 146 7
+ 144 145 7
+ 20 23 2
+ 221 15 2
+ 223 222 0
+ 219 218 1
+ 226 225 0
+ 208 209 2
+ 61 60 1
+ 203 204 2
+ 213 214 2
+ 181 182 5
+ 212 213 2
+ 204 205 2
+ 210 211 2
+ 206 207 2
+ 44 43 3
+ 11 10 4
+ 186 187 5
+ 173 172 4
+ 88 87 6
+ 72 71 6
+ 38 37 3
+ 75 76 7
+ 68 67 8
+ 112 111 3
+ 30 29 3
+ 83 84 7
+ 205 206 2
+ 43 42 3
+ 90 89 6
+ 89 88 6
+ 105 104 3
+ 37 36 3
+ 36 35 3
+ 110 109 3
+ 158 69 7
+ 67 66 8
+ 217 216 1
+ 216 63 1
+ 218 217 1
+ 202 203 2
+ 31 30 3
+ 45 44 3
+ 71 51 6
+
+ SubDomain
+ 8
+ 2 1 1 5
+ 2 50 1 4
+ 2 40 1 3
+ 2 65 1 6
+ 2 79 1 8
+ 2 94 1 7
+ 2 114 1 2
+ 2 149 1 1
+
+ End
diff --git a/examples-bamg/square/octogone_g.mesh b/examples-bamg/square/octogone_g.mesh
new file mode 100644
index 0000000..d51cd66
--- /dev/null
+++ b/examples-bamg/square/octogone_g.mesh
@@ -0,0 +1,25 @@
+MeshVersionFormatted 0
+MaximalAngleOfCorner 44
+Dimension 2
+Vertices 8
+1 0 1
+.7071067811865476 .7071067811865476 1
+0 1 1
+-.7071067811865476 .7071067811865476 1
+-1 0 1
+-.7071067811865476 -.7071067811865476 1
+0 -1 1
+.7071067811865476 -.7071067811865476 1
+
+Edges 8
+1 2 1
+2 3 1
+3 4 1
+4 5 1
+5 6 1
+6 7 1
+7 8 1
+8 1 1
+
+hVertices
+0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 
diff --git a/examples-bamg/square/square_g.mesh b/examples-bamg/square/square_g.mesh
new file mode 100644
index 0000000..166265a
--- /dev/null
+++ b/examples-bamg/square/square_g.mesh
@@ -0,0 +1,17 @@
+MeshVersionFormatted 0
+Dimension 2
+Vertices 4
+ -1 -1 1
+ 1 -1 2
+ 1 1 3
+ -1 1 4
+Edges 4
+1 2 1
+2 3 1
+3 4 2
+4 1 2
+hVertices 
+0.666 0.666 0.666 0.666
+
+
+
diff --git a/examples-bamg/square/square_raf_ani_g.mtr b/examples-bamg/square/square_raf_ani_g.mtr
new file mode 100644
index 0000000..9c70340
--- /dev/null
+++ b/examples-bamg/square/square_raf_ani_g.mtr
@@ -0,0 +1,6 @@
+5 3
+500 0 25
+25 0 25
+25 0 25
+25 0 25
+25 0 100
diff --git a/examples-bamg/square/square_raf_g.mesh b/examples-bamg/square/square_raf_g.mesh
new file mode 100644
index 0000000..61d0c62
--- /dev/null
+++ b/examples-bamg/square/square_raf_g.mesh
@@ -0,0 +1,23 @@
+MeshVersionFormatted 0
+Dimension 2
+Vertices 5
+ -1 -1 1
+ 1 -1 2
+ 1 1 3
+ -1 1 4
+0 0 0
+Edges 4
+1 2 1
+2 3 1
+3 4 2
+4 1 2
+hVertices
+0.666 0.666 0.666 0.666 0.01
+#  if you do not say that the vertex number 5 is required
+#  the mesher lost this information so no refement 
+#  around the vertex (0.,0.) is done
+
+RequiredVertices 1
+5
+
+
diff --git a/examples-bamg/square/square_raf_g.mtr b/examples-bamg/square/square_raf_g.mtr
new file mode 100644
index 0000000..7766fdc
--- /dev/null
+++ b/examples-bamg/square/square_raf_g.mtr
@@ -0,0 +1,2 @@
+5 1
+0.666 0.666 0.666 0.666 0.01
diff --git a/examples-bamg/test/dotest.pl b/examples-bamg/test/dotest.pl
new file mode 100755
index 0000000..3c307b0
--- /dev/null
+++ b/examples-bamg/test/dotest.pl
@@ -0,0 +1,168 @@
+#!/usr/local/bin/perl
+# -----  clean ---
+unlink <*.mesh>;
+unlink <*.am_fmt>;
+unlink <*.mtr>;
+unlink <*.bb>;
+unlink <*.BB>;
+unlink <YG_trace*>;
+unlink 'PLOT';
+
+##$f="10 +  1/(1+ 100**(sin(x*3)-y)) ";
+#$f1 = "(10*x*x*x+y*y*y) + 10/(1+10**(10*((sin(5*x)-2*y)))) ";
+$f1=" sin(3*x)*cos(5*y)+ atan2(0.001,x**2 + y**2 - 0.5 )";
+#$f1=" 8*(x-y)**2 + (x+y)**2";
+
+$err=0.1;
+$errg=0.01;
+$nbiteration=10;
+$bamg=$ENV{'bamg'};
+$quadoption="";
+$bamgoption=" -AbsError -NbJacobi 2  -NbSmooth 5 -anisomax 5 -hmax 0.5   -ratio 2  -nbv 100000 ";
+#$bamgoption=" -AbsError -NbJacobi 3  -ratio 2 -anisomax 30";
+#$quadoption=" -2q -thetaquad 30 -coef 2";
+
+# ---  change x in $x and y in $y 
+$_=$f1;
+s/x/\$x/g;
+s/y/\$y/g;
+$f1="$_;";
+
+print "The function = f1(x,y) = $f1 \n";
+
+#--------------------------
+$suffixe=".mesh";
+$iteration=0;
+$GH="Gh$suffixe";
+$TH="Th$iteration$suffixe";
+$, = ' ';               # set output field separator
+$\ = "\n";              # set output record separator
+##  -------------------------------------------------------------
+##  --- construction the Geometry file Gh.mesh 
+
+##    8 points on circle of radius r 
+open(GH,">$GH")  || die "Can't redirect stdout";
+$Pi = 3.14159265358979;
+
+$i8 = 8;
+$r = 1;
+$c0x = 0;
+$c0y = 0;
+print GH 'Dimension', 2;
+print GH 'MaximalAngleOfCorner 46';
+
+print GH 'Vertices';
+print GH   $i8;
+
+# vertex on circle  (counter clock wise)
+for ($i = 0; $i < $i8; $i++) {
+    $t = $i * $Pi * 2 / $i8;
+    print GH $c0x + $r * (cos($t)), $c0y + $r * sin($t), 5;
+}
+
+print GH 'Edges',  $i8+1;
+
+print GH 1,5,10;
+# edge on circle 
+$k =  1;
+$j = $i8 - 1;
+# previous points
+for ($i = 0; $i < $i8; $j = $i++) {
+    print GH $k + $j, $k + $i, 5;
+}
+# previous, current vertex
+
+#   one subdomain, region on left side of the wing
+#   because clock wise sens.
+print GH 'SubDomain', 2;
+print GH 2, 1, 1, 0;
+print GH 2, 1, -1, 1;
+close GH;
+##  -------------- END construct of the geom 
+## 
+
+# -- make the DATA file for the mesh to also  save the arguments 
+open(BAMG,">DATA_bamg")  || die "Can't open  DATA_bamg";
+print BAMG "$quadoption $bamgoption  -g $GH -o $TH  -v 9 -oam_fmt $TH.am_fmt";
+close(BAMG);
+
+## constructio the inital  mesh 
+!system($bamg) || die "Error in bamg construction of initial  mesh $Th";
+
+##  the adpatation loop 
+while ($iteration<$nbiteration) {
+
+    
+
+    $BB="$iteration.BB";   
+    $ERRBB="err$iteration.bb";   
+
+    
+##  construction of the solution  
+    $errsol=0;
+    open (TH,"<$TH") ||  die "Can't open  $TH";
+    open (BB,">$BB") ||  die "Can't open  $BB";
+    open (ERRBB,">$ERRBB") ||  die "Can't open  $ERRBB";
+
+
+    while (<TH>) {
+	if(/^Vertices$/) {
+	    $nbv=<TH>;
+	    chop($nbv);
+	    print BB "2 1 1 $nbv 2";
+
+	    for ($i=1;$i<=$nbv;$i++) {
+		($x,$y,$ref)=split(/[\ \t\n]+/, <TH>);
+		$f1xy=eval $f1;
+
+		$xx[$i]=$x;
+		$yy[$i]=$y;
+		$ff[$i]=$f1xy;
+
+
+		print BB $f1xy ;
+
+	    };
+	};
+	if(/^Triangles$/) {
+	    $nbt=<TH>;
+	    chop($nbt);
+	    print " Nb of Triangles = $nbt \n";
+	    print ERRBB "2 1 $nbt 1";
+	    for ($i=1;$i<=$nbt;$i++) {
+		($i0,$i1,$i2,$ref)=split(/[\ \t\n]+/, <TH>);
+
+		$x   = ($xx[$i0]+$xx[$i1]+$xx[$i2])/3;
+		$y   = ($yy[$i0]+$yy[$i1]+$yy[$i2])/3;
+		$fm  = ($ff[$i0]+$ff[$i1]+$ff[$i2])/3;
+		$fxy = eval $f1;
+		$vv=($fm-$fxy);
+		$vv= ($vv<0)?-$vv:$vv;
+		print ERRBB $vv;
+		$errsol = ($errsol>$vv) ? $errsol : $vv;
+	    };
+	};
+
+    };
+    close TH;
+    close BB;
+    close ERRBB;
+    print " ---------------------------------------------\n";
+    print "\n\n Iteration $iteration\n Erreur L_infini = $errsol \n\n";
+    print " ---------------------------------------------\n";
+
+##  -----------------------
+    
+    $MTR="M$iteration.mtr";
+
+    $iteration++;
+    $BTH=$TH;
+    $TH="Th$iteration$suffixe";
+
+    open(BAMG,">DATA_bamg")  || die "Can't open  DATA_bamg";
+    print BAMG "$quadoption  $bamgoption  -MBB $BB -errg $errg -err $err   -b $BTH -o $TH  -v 9 -oM $MTR -oam_fmt $TH.am_fmt -wBB /tmp/tyty ";
+    close(BAMG);
+    !system($bamg) ||    die "Error in bamg construction of adapted $iteration  mesh $Th";
+}
+
+print "Normal End\n";
diff --git a/freefem++.spec b/freefem++.spec
new file mode 100644
index 0000000..75bf19a
--- /dev/null
+++ b/freefem++.spec
@@ -0,0 +1,98 @@
+Summary: FreeFem++
+Name: freefem++
+Version: 2.8
+Release: 0
+Source: %{name}-%{version}.tar.gz
+Patch:   %{name}-config.patch
+Patch1:   %{name}-gcc4.patch
+%if %{?_with_cadna:1}%{!?_with_cadna:0} 
+Source2: CadnaC_gcc-3.2_Linux_i386.tar.gz
+Patch2:  cadna-gcc4.patch
+%endif
+License: GPL
+Group: Applications/Engineering
+URL: http://www.freefem.org/ff++/
+Packager: Christophe  Trophime <christophe.trophime at grenoble.cnrs.fr>
+Prereq: /sbin/install-info
+Buildroot: %{_tmppath}/%{name}-buildroot
+Requires: arpack, ufsparse
+BuildRequires: arpack-devel, ufsparse-devel
+BuildRequires: fltk >= 1.1
+BuildRequires: fltk >= 1.1
+BuildRequires: gsl >= 1.2
+BuildRequires: rpm >= 4.1
+%if %{?_with_mpi:1}%{!?_with_mpi:0} 
+BuildRequires: lam
+%endif
+%{!?_without_freedesktop:BuildRequires: desktop-file-utils}
+Requires: mesa-libGL >= 6.7.0-9
+Requires: mesa-libGLU >= 6.7.0-9
+Requires: gsl >= 1.2
+Requires: fltk >= 1.1
+Prefix: /usr
+
+%description 
+FreeFem++ is an implementation of a language dedicated to the finite element method. 
+It enables you to solve Partial Differential Equations (PDE) easily.
+
+Problems involving PDE from several branches of physics such as fluid-structure interactions 
+require interpolations of data on several meshes and their manipulation within one program. 
+FreeFem++ includes a fast quadtree-based interpolation algorithm and a language for the manipulation 
+of data on multiple meshes (generated with bamg).
+
+
+
+%prep
+
+%setup -q -n %{name}-%{version}
+%patch -p1 -b .umfpack
+%patch1 -p1 -b .gcc4
+
+%if %{?_with_cadna:1}%{!?_with_cadna:0}
+mkdir -p cadna
+mkdir -p download/cadna
+tar zxvf %{SOURCE2} -C cadna 
+mv cadna/include/cadnafree.h download/cadna
+mv cadna/lib/libcadnafreeC.a download/cadna
+pushd download/cadna/
+ln -sf libcadnafreeC.a libcadnafree.a
+popd
+%patch2 -p1 -b .cadna-gcc4.patch
+%endif
+
+autoreconf -f -i
+
+%build
+%if %{?_with_mpi:1}%{!?_with_mpi:0}
+%configure --with-mpi=lam
+%else
+%configure --without-mpi --with-blas="-L/usr/lib/atlas -lf77blas -lcblas"
+%endif
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+make install DESTDIR=$RPM_BUILD_ROOT
+
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%{_bindir}/FreeFem++
+%{_bindir}/FreeFem++-cs
+%{_bindir}/FreeFem++-nw
+%{_bindir}/FreeFem++-glx
+%{_bindir}/FreeFem++-ide
+%{_bindir}/FreeFem++-server
+%{_bindir}/FreeFem++-client
+%{_bindir}/bamg
+%{_bindir}/cvmsh2
+%{_bindir}/drawbdmesh
+%if %{?_with_mpi:1}%{!?_with_mpi:0}
+%{_bindir}/FreeFem++-mpi
+%endif
+
diff --git a/logo.ico b/logo.ico
new file mode 100644
index 0000000..e89ad7a
Binary files /dev/null and b/logo.ico differ
diff --git a/mode-mi-edp.zip b/mode-mi-edp.zip
new file mode 100644
index 0000000..19ad677
Binary files /dev/null and b/mode-mi-edp.zip differ
diff --git a/reconfigure b/reconfigure
new file mode 100755
index 0000000..180eaf8
--- /dev/null
+++ b/reconfigure
@@ -0,0 +1,7 @@
+#!/bin/sh
+if [ -f ./configure.param ]; then 
+  echo ./configure `cat ./configure.param` "$@"
+  echo ./configure `cat ./configure.param` "$@"|sh
+else
+  echo " sorry not previouly configurate, sorry "
+fi
\ No newline at end of file
diff --git a/regtests.m4 b/regtests.m4
new file mode 100644
index 0000000..1999b17
--- /dev/null
+++ b/regtests.m4
@@ -0,0 +1,53 @@
+// Regression tests
+// ----------------
+
+// The tests are checked against reference values by "make check" in
+// each examples subdirectory
+
+// "ref.edp" contains all reference values and may be rebuilt with
+// "make Ref"
+
+// $Id$
+
+// The values tested here may not have a physical or mathematical
+// meaning. Their main property is to gather numerical values from the
+// whole domain, to be checked for consistency with previous runs.
+
+NoUseOfWait=true;
+int verbosityy=verbosity;
+
+dnl May write or read a reference file
+changequote([[,]])
+
+define(REFFILE,"ref.edp")
+ifdef([[ASSERT]],
+	include REFFILE;,
+	ofstream ref(REFFILE);)
+
+dnl $1=file name
+dnl $2=reference value (if there is one)
+dnl $3=precision of reference value (if there is one)
+dnl	or minimum absolute variation if $4 is defined
+dnl $4=maximum absolute variation (if defined)
+
+define(ONETEST,
+[[cout << "--------- file : $1.edp -----------------" << endl;
+verbosity=verbosityy;
+{
+	dnl Place the dash first to avoid any confusion with things like "a-z"
+	define([[TESTVAR]],TEST[[]]translit($1,-_,XX))
+	define([[REFVAR]],REF[[]]translit($1,-_,XX))
+	include "$1.edp";
+	ifelse($2,,,
+		[[real TESTVAR=$2;
+		ifdef([[ASSERT]],
+			cout<<"$1 reference value = "<<REFVAR
+				<<" test value ="<<TESTVAR<<endl;
+			ifelse($4,,
+				assert(TESTVAR<REFVAR*(1+$3));
+				assert(TESTVAR>REFVAR*(1-$3));,
+				assert(TESTVAR<REFVAR+$4);
+				assert(TESTVAR>REFVAR-$3);),
+			ref<<"real REFVAR="<<TESTVAR<<";"<<endl;)]])
+};
+]])
diff --git a/regtests.sh b/regtests.sh
new file mode 100755
index 0000000..bbd218a
--- /dev/null
+++ b/regtests.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+# Runs all regression tests on all compiled FreeFem++ versions
+# ------------------------------------------------------------
+MPIRUN=`awk  '$1 =="MPIRUN" {print $3}' Makefile`
+# Antoine Le Hyaric - LJLL Paris 6 - lehyaric at ann.jussieu.fr - 19/5/04
+# $Id$
+
+# To run one set of tests on one executable
+# $1=program to run
+# $2=tag for trace file
+# $3=EDP script to run
+function dotest(){
+
+    # Running FreeFem++ on regtests.edp (specific to regression
+    # tests), otherwise on all.edp.
+    echo regtests.sh: running $1 $3, result in regtests-$2.log
+    $1 $3|tee regtests-$2.log
+    if test $PIPESTATUS != 0
+	then
+	exit 1
+    fi
+}
+
+# For the example++-load tests
+export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:."
+
+# In visual checks, we can run even the most invasive programs
+script=$REGEDP
+if test "$VISUALCHECK" = yes -a "$REGEDP" = regtests.edp
+then
+    script=all.edp
+fi
+
+# Number of processors in parallel mode
+if test "$NPROCS" != ""
+    then
+    nprocs=$NPROCS
+else
+    nprocs=1
+fi
+
+# Do not test windowed programs by default, because their windows are
+# too invasive.
+
+if test "$VISUALCHECK" = yes
+then
+    export PATH="${PROGLOC}/nw/:$PATH";  dotest FreeFem++${EXEEXT} std $script
+fi
+
+if test $nprocs = 1
+    then
+    dotest ${PROGLOC}/nw/FreeFem++-nw${EXEEXT} nw $script
+fi
+
+if test "${X11PROG}" != "" -a "${VISUALCHECK}" = "yes"
+then
+    dotest ${PROGLOC}/x11/FreeFem++-x11${EXEEXT} x11 $script
+fi
+
+if test "${GLXPROG}" != "" -a "${VISUALCHECK}" = "yes"
+then
+    dotest ${PROGLOC}/glx/FreeFem++-glx${EXEEXT} glx $script
+fi
+
+if test "${AGLPROG}" != "" -a "${VISUALCHECK}" = "yes"
+then
+    dotest ${PROGLOC}/agl/FreeFem++-agl${EXEEXT} agl $script
+fi
+
+if test "${MPIPROG}" != ""
+    then
+    mpich=`${MPIRUN=mpirun} -h 2>&1 |grep mpich  |wc  -l`
+    host=`hostname`
+    echo $host>machinefile
+    echo $host>>machinefile
+    if [ $mpich -ne 0 ] ; then
+    dotest "${MPIRUN} -np $nprocs -machinefile machinefile ${PROGLOC}/mpi/FreeFem++-mpi${EXEEXT}" mpi $script
+    else
+	[[ -f "$(which lamboot 2>/dev/null)" ]] && lamboot	
+     dotest "${MPIRUN} -np $nprocs ${PROGLOC}/mpi/FreeFem++-mpi${EXEEXT}" mpi $script
+    fi
+fi
+
+if test "${IDEPROG}" != "" -a "${VISUALCHECK}" = "yes"
+then
+    dotest ${PROGLOC}/ide/FreeFem++-cs${EXEEXT} ide $script
+fi
diff --git a/src/Algo/BFGS.hpp b/src/Algo/BFGS.hpp
new file mode 100644
index 0000000..f472305
--- /dev/null
+++ b/src/Algo/BFGS.hpp
@@ -0,0 +1,181 @@
+#ifndef BFGS_HH
+#define BFGS_HH
+
+#include "Optima.hpp"
+#include "defs.hpp"
+
+// BFGS Quasi-Newton Optimization Method
+/* At the present version, you must use the CubicLineSearch 
+   procedure */
+
+// Necessite une "vraie" classe Matrice
+template <class LS>
+class BFGS : public Optima<LS>
+{
+  typedef typename LS::Real Real;
+  typedef typename LS::Param Param;
+  typedef typename LS::Vect Vect;
+  typedef typename LS::VMat VMat;
+  typedef typename LS::Mat Mat;
+  typedef list<Real> mlist;
+
+public:
+  
+  BFGS(///pointer to the line-search object.
+	   LS* ls, 
+	   ///Maximum number of iterations
+	   int iter, 
+	   ///minimum accepted gradient at optimum solution
+	   Real tol,
+	   ///vebose or quiet
+	   int verb=0);
+  ~BFGS(){;}
+  
+  // the BFGS search starting from model0, returns an optimum model 
+  Param optimizer(Param& model0);
+
+};
+
+template <class LS>
+BFGS<LS>::BFGS(LS* p, int it, Real eps, int verb) 
+  :Optima<LS>(verb)
+{
+  this->ls=p;
+  this->iterMax 	= 	it;
+  this->tol 		= 	eps;
+  this->iterNum 	= 	0;
+}
+
+// N�cessite pour la classe MAT:
+// - un constructeur de matrice avec nbre de lig, nbre de col
+// - un constructeur de matrice avec la diagonale comme param�tre
+// - le produit matrice vecteur
+// - une m�thode outProduct qui construit � partir de 2 vecteurs u et v la matrice A_{i,j}=u(i)v(j)
+// - une m�thode t()
+// - un op�rateur +
+// - un op�rateur = Real
+// - un op�rateur = Vect
+template <class LS>
+typename BFGS<LS>::Param BFGS<LS>::optimizer(Param& model0)
+{
+  //reset the residue history for every new optimizer
+  this->iterNum = 0;
+  if (this->residue != NULL)
+	{
+      delete this->residue;
+      this->residue = new mlist;
+	}
+  
+  // Initial settings for some parameters
+  int n = model0.size();
+  Vect g0(n);
+  double lambda = 0.025;
+  double descent = 0.;
+  
+
+  g0= *(this->ls->gradient(model0));
+	
+  // check the gradient, in case the initial model is the optimal
+  double err = (Real)sqrt((g0,g0));
+  
+  if (this->isVerbose) cerr << "Initial residue : " << err << endl;
+
+  this->appendResidue(err);	// residual
+
+  if (err < this->tol)
+	{
+      if (this->isVerbose) cerr << "Initial guess was great! \n";
+      this->isSuccess = 1;
+      return model0;
+	}
+   
+   //initial identical matrix for estimating inverse of the Hessian
+   //Vect diag(n,1.);
+
+   Mat H(n,n);H=0;diagonal(H)=1;
+   Real d, dd, scale;
+   Param model1(model0);
+   Vect s(n),gamma(n),delta(n),g1(n);
+
+   //searching directions
+   s=Real();
+   s -= H*g0;
+   descent = (s,g0);
+   assert(s.max() <1e100);
+   
+   //cubic line search for a new model
+   model1 = this->ls->search(model0, s, descent, lambda);
+   g1 = *(this->ls->gradient(model1));
+   err = (Real)sqrt((g1,g1));
+   if (this->isVerbose)
+	 cerr << "Iteration (" << this->iterNum << ") : "
+		  <<"current value of the objective function: "
+		  <<this->ls->currentValue() << "\t current residue: "<< err << endl;
+
+   this->appendResidue(err);	// residual
+   this->iterNum ++;
+
+   Mat B(n,n);
+
+   
+   while (this->finalResidue() > this->tol && this->iterNum < this->iterMax)
+   {
+	 gamma = g1 - g0;
+	 delta = model1 - model0;
+
+	 //replace the searching direction with temporal storage
+	 s = H*gamma;
+
+	 //factor of the denominator
+	 dd = (delta,gamma);
+
+	 // Modif TONY
+	 // Au d�part, il y avait : if (dd < 0.00000001)
+	 // Mais Adel ne fait pas ce test non plus...
+	 if (Abs(dd)<1e-20)
+	   {
+		 // re-initialize the Hessian Matrix
+		 // Il faut d'abord le mettre a zero : cf. Matrix.hpp
+		 H = 0.; diagonal(H)=1.;
+		
+	   }
+	 else
+	   {
+		 assert(dd);
+		 d = 1./dd;
+		 
+		 scale = d*((gamma,s));
+		 scale += 1;
+		 scale *= d;
+		 
+		 // update the first term
+		 H += scale*delta*delta.t();
+		 
+		 //update the second term
+		 H -= d*s*delta.t();
+		 H -= d*delta*s.t();
+		 
+		 //store the current model and gradient
+		 g0 = g1;
+		 model0 = model1;
+	   }
+	 s=Real();
+	 s -= H*g0;
+	 descent = (s,g0);
+	 model1 = this->ls->search(model0, s, descent, lambda);
+	 g1 = *(this->ls->gradient(model1));
+	 err = (Real)sqrt((g1,g1));
+	 
+	 if (this->isVerbose)
+	   cerr << "Iteration (" << this->iterNum << ") : "<<"current value of the objective function: "
+			<<this->ls->currentValue() << "\t current residue: "<< err << endl;
+
+	 this->appendResidue(err);	// residual
+	 this->iterNum ++;
+   }
+   
+   return(model1);
+}
+
+#endif
+
diff --git a/src/Algo/BrentLS.hpp b/src/Algo/BrentLS.hpp
new file mode 100644
index 0000000..8a3be7a
--- /dev/null
+++ b/src/Algo/BrentLS.hpp
@@ -0,0 +1,361 @@
+//======================================================================
+// Definition of the BrentLineSearch class
+// Brent's line search algorithm
+// author: Wenceslau Gouveia, Adapted from Numerical Recipes in C
+// Modified to fit into new classes.  H. Lydia Deng, 02/21/94, 03/15/94
+// Tony : cf. page 301 section 10.2
+//========================================================================
+// .B BrentLineSearch()
+// This routine, inpired by the Numerical Recipes book, performs a unidimensional search
+// for the minimum of the objective function along a specified direction. The minimum is
+// at first bracket using the Golden search procedure. After bracketing the Brent's 
+// algorithm is used to isolate the minimum to a fractional precision of about the specified 
+// tolerance.
+// 
+// .SECTION Description
+// Public Operations
+// Constructors: 
+//		BrentLineSearch (ObjectiveFunction *f, int iter);
+// 		Here:
+//			f: Define the objective function
+//			iter: Maximum number of iterations
+// Methods:
+//		model <> BrentLineSearch::search(Model<double>& model0, Vector<double>& direction, 
+//						  	                 double tol, double delta)
+//		Here:
+//			model0:  Initial model to initiate the bracketing procedure
+// 			direction: Vector that defines the direction of the line search
+//			tol: The minimum is within the returned this->value +/- tol
+//			delta: Used in the bracketing procedure. The initial interval
+//				  for the bracketing is from 0 to delta * STEP_MAX, where
+//				  STEP_MAX is hard coded to 5.
+//
+//			The sought minimum is returned by the function.
+//
+// .SECTION Caveats
+// This line search was not thoroughly tested. The CubicLineSearch procedure, that requires
+// certain derivative information on the objective function (that can be provided by numerical
+// methods) has demonstrated to be a  more efficient line search procedure.
+
+// Cela me semble louche... cf. les commentaires BIZARRE !
+// Ceci dit, le premiers tests semblent OK...
+
+#include "defs.hpp"
+#include <stdio.h>
+
+
+#ifndef BRENT_LINE_SEARCH_HH
+#define BRENT_LINE_SEARCH_HH
+
+#include "LineSearch.hpp"
+
+#define CGOLD 		.3819660
+#define ZEPS 		1.e-10
+#define GOLD 		1.618034
+#define STEP_MAX	5
+#define GLIMIT 		100.
+
+/*
+   BrentLineSearch class was inpired by the Numerical Recipes book, 
+   performs an unidimensional search for the minimum of the objective 
+   function along a specified direction. The minimum is at first
+   bracket using the Golden search procedure. After bracketing 
+   the Brent's algorithm is used to isolate the minimum to a 
+   fractional precision of about the specified tolerance.
+
+   This line search was not thoroughly tested. The 
+   CubicLineSearch procedure, that requires certain 
+   derivative information on the objective function
+   (that can be provided by numerical methods) has
+   demonstrated to be a  more efficient line search procedure.
+
+*/
+
+template <class LS>
+class BrentLineSearch : public LS
+{
+  typedef typename LS::Real Real;
+  typedef typename LS::Param Param;
+  typedef typename LS::Vect Vect;
+  typedef typename LS::VMat VMat;
+  typedef typename LS::Mat Mat;
+  typedef typename LS::NRJ NRJ;
+   public:				
+
+   BrentLineSearch(NRJ* f, int iter);
+   ~BrentLineSearch();
+
+  // Implementation of the Brent Search
+  // search for minimum model along a 1-D direction
+  Param search(///initial model to initiate the bracketing procedure
+			Param& m0, 
+			///the direction of the line search
+			Vect& direction, 
+			///the minimum is within the returned this->value +/- tol
+			Real tol, 
+			///a parameter used in the bracketing procedure
+			double delta);
+   /*The initial interval for the bracketing is from $0$ to 
+   $delta \times STEP\_MAX$, where $STEP\_MAX$ is hard coded to $5$.
+   The sought minimum is returned by the function.  */
+   //@ManMemo: search for minimum model along a 1-D direction
+};
+
+template <class LS>
+BrentLineSearch<LS>::BrentLineSearch(NRJ * f, int it) 
+: LS(f)
+{
+  this->iterMax 	= 	it;
+}
+
+template <class LS>
+BrentLineSearch<LS>::~BrentLineSearch()
+{;}
+
+// Code for the BrentBrent line search
+template <class LS>
+typename BrentLineSearch<LS>::Param BrentLineSearch<LS>::search(Param& model0,Vect& direction, Real tol, double delta)
+{
+    this->iterNum	=	0;
+	KN<double> steps(3);			// brackets
+	Vect of_values(3);			// OF evaluated inside bracket
+	Real dum;					// auxiliary quantity
+	Real r, q, ulim;				// auxiliary quantity
+	Real u, fu;					// define the new bracket limit
+	
+	// Variables related to Brent's algorithm
+	Real d, fv, fw, fx, p;			// auxiliary variables
+	double tol1, tol2, v, w, xm;			// auxiliary variables
+	double x, e = 0.,etemp;				// auxiliary variables
+	int i;						// counter
+
+	// Ajout Tony
+	d=0; // Sinon, il n'est pas initialise : BIZARRE !
+	
+	
+	// Beggining of the bracketing stage
+
+	steps[0] = 0.;
+	steps[1] = STEP_MAX * delta;
+
+	of_values[0]= this->nrj->getVal(model0);
+	of_values[1] =this->nrj->getVal(update(model0,1,steps[1],direction));
+	this->iterNum += 2;
+
+	if (of_values[1] > of_values[0])
+	{
+	   dum = steps[0]; steps[0] = steps[1]; steps[1] = dum;
+	   dum = of_values[0]; of_values[0] = of_values[1]; of_values[1] = dum;
+	}	
+
+	steps[2] = steps[1] + GOLD * (steps[1] - steps[0]);
+	of_values[2] = this->nrj->getVal(update(model0,1,steps[2],direction));
+	this->iterNum++;
+	while (of_values[1] > of_values[2])
+	{
+		r = (steps[1] - steps[0]) * (of_values[1] - of_values[2]);
+		q = (steps[1] - steps[2]) * (of_values[1] - of_values[0]);
+		u = steps[1] - ((steps[1] - steps[2]) * q - 
+				(steps[1] - steps[0]) * r) / 
+		    (2. * Abs(Max(Abs(q - r), TINY)) / Sgn(q - r));
+		ulim = steps[1] + GLIMIT * (steps[2] - steps[1]);
+
+		if ((steps[1] - u) * (u - steps[2]) > 0.)
+		{
+			fu = this->nrj->getVal(update(model0,1,u,direction));
+			this->iterNum++;
+			if (fu < of_values[2])
+			{
+				steps[0] = steps[1];
+				steps[1] = u;
+				of_values[0] = of_values[1];
+				of_values[1] = fu;
+				break;
+			}
+			else if (fu > of_values[1])
+			{
+				steps[2] = u;
+				of_values[2] = fu;
+				break;
+			}
+
+			u = steps[2] + GOLD * (steps[2] - steps[1]);
+			fu = this->nrj->getVal(update(model0,1,u,direction));
+			this->iterNum++;
+
+		}
+		else if ((steps[2] - u) * (u - ulim) > 0.)
+		{
+			fu = this->nrj->getVal(update(model0,1,u,direction));
+			this->iterNum++;
+			if (fu < of_values[2])
+			{
+				steps[1] = steps[2];
+				steps[2] = u;
+				u = steps[2] + GOLD * (steps[2] - steps[1]);
+
+				of_values[1] = of_values[2];
+				of_values[2] = fu;
+				fu = this->nrj->getVal(update(model0,1,u,direction));
+				this->iterNum ++;
+			}
+		}
+		else if ((u - ulim) * (ulim * steps[2]) >= 0.)
+		{
+			u = ulim;
+			fu = this->nrj->getVal(update(model0,1,u,direction));
+			this->iterNum ++;
+		}
+		else
+		{
+			u = steps[2] + GOLD * (steps[2] - steps[1]);
+			fu = this->nrj->getVal(update(model0,1,u,direction));
+			this->iterNum ++;
+		}
+
+		steps[0] = steps[1]; steps[1] = steps[2]; steps[2] = u;
+		of_values[0] = of_values[1]; of_values[1] = of_values[2]; 
+		of_values[2] = fu;
+
+	}
+	
+	// Sorting STEPS in ascending order
+	for (i = 0; i < 2; i++)
+	{
+		if (steps[0] > steps[i+1])
+		{
+			dum = steps[0];
+			steps[0] = steps[i+1];
+			steps[i+1] = dum;
+
+			dum = of_values[0];
+			of_values[0] = of_values[i+1];
+			of_values[i+1] = dum;
+		}
+	}
+
+	if (steps[1] > steps[2])
+	{
+		dum = steps[1];
+		steps[1] = steps[2];
+		steps[2] = dum;
+
+		dum = of_values[1];
+		of_values[1] = of_values[2];
+		of_values[2] = dum;
+	}
+
+	// The line minimization will be performed now using as
+	// bracket the 3 first steps given in vector steps 
+	// The algorithm is due to Brent
+
+	// initializations
+	x = w = v = steps[1];
+	fw = fv = fx = of_values[1];
+
+	for (; this->iterNum <= this->iterMax; this->iterNum++)
+	{
+		xm = .5 * (steps[0] + steps[2]);
+		tol1 = tol * Abs(x) + ZEPS;
+		tol2 = 2.0 * tol1;
+		if (Abs(x - xm) <= (tol2 - .5 * (steps[2] - steps[0])))
+		{
+			this->value = fx;
+			Param new_model(update(model0,1,x,direction));
+			
+			return new_model;
+		}
+						// minimum along a line
+		if (Abs(e) > tol1)
+		{
+			r = (x - w) * (fx - fv);
+			q = (x - v) * (fx - fw);
+			p = (x - v) * q - (x - w) * r;
+			q = 2.0 * (q - r);
+			// Tony
+			// ??? ERREUR ???
+			// dans le numerical recipe, c'est p=-p...
+			// BIZARRE !
+			if (q > 0.){
+			  cerr<<"BIZARRE BrentLS"<<endl;
+			  p = -q;
+			}
+			
+			q = Abs(q);
+			etemp = e;
+			e = d;
+			if (Abs(p) >= Abs(.5 * q * etemp) ||
+			    p <= q * (steps[0] - x) ||
+			    p >= q * (steps[2] - x))
+			{	// parabolic fit
+				if (x >= xm)
+					e = steps[0] - x;
+				else
+					e = steps[2] - x;
+				d = CGOLD * e;
+			}
+			else
+			{
+				d = p / q;
+				u = x + d;
+				if (u - steps[0] < tol2 ||
+				    steps[2] - u < tol2)
+					d = Abs(tol1) / Sgn(xm-x);
+			}
+		}
+		else
+		{
+			if (x >= xm)
+				e = steps[0] - x;
+			else
+				e = steps[2] - x;
+
+			d = CGOLD * e;
+		}
+
+		if (Abs(d) >= tol1)
+			u = x + d;
+		else
+			u = x + Abs(tol1) / Sgn(d);
+
+		fu  = this->nrj->getVal(update(model0,1,u,direction));
+
+		if (fu <= fx)
+		{
+			if (u >= x)
+				steps[0] = x;
+			else
+				steps[2] = x;
+			v = w; w = x; x = u;
+			fv = fw; fw = fx; fx = fu;
+		}
+		else
+		{
+			if (u < x)
+				steps[0] = u;
+			else
+				steps[2] = u;
+
+			if (fu <= fw || w == x)
+			{
+				v = w; w = u; fv = fw; fw = fu;
+			}
+
+			else if (fu <= fw || v == x || v == w)
+
+			{
+				v = u; fv = fu;
+			}
+		}
+	}
+	
+    this->appendSearchNumber();
+	//    cout << " Maximum number of iterations reached " << endl;
+
+
+	Param new_model(update(model0,1,x,direction));
+	this->value = this->nrj->getVal(new_model);			
+	return new_model;
+}
+
+#endif
diff --git a/src/Algo/CG.hpp b/src/Algo/CG.hpp
new file mode 100644
index 0000000..d47db2f
--- /dev/null
+++ b/src/Algo/CG.hpp
@@ -0,0 +1,215 @@
+//=============================
+// Definition of the conjugate gradient class
+// Non-linear conjugate gradient algorithm
+// author:  Wenceslau Gouveia
+// modified:  H. Lydia Deng, 02/23/94,  /03/14/94
+//=============================
+
+// .NAME ConjugateGradient class
+// .LIBRARY Base
+// .HEADER Optimization Algorithms
+// .INCLUDE defs.hpp
+// .FILE CG.hpp
+
+// .SECTION Description
+// .B ConjugateGradient()
+// The conjugate gradient procedure implemented in this object is an extension of
+// the conjugate gradient used in linear system solving to handle non quadratic
+// objective functions. Such extensions amount basically to the inclusion of a 
+// line search step and a modification in the computation of the conjugate directions.
+// Details can be found in the classic (and tough!) book Practical Optimization by
+// Powell.
+// 
+// .SECTION Description
+// Public Operations
+// Constructors: 
+//		ConjugateGradient(LineSearch* ls, int iter, double tol)
+// 		Here:
+//			ls: Defines the line search used. At the present version you should use the
+//			    CubicLineSearch procedure.
+//			iter: Maximum number of iterations
+//		 	tol: Minimum accepted module of the gradient at optimum solution
+// Methods:
+//		Model<>ConjugateGradient::optimizer(Model<double>&)
+//		Here:
+//			model0:  Initial model for the conjugate gradient procedure.
+//
+//			The optimum model is returned by the function.
+//
+// .SECTION Caveats
+// This procedure requires the derivatives of the objective function. At the present version the
+// COOOL library cannot handle analytic derivatives provided by the user. Here the derivatives
+// are computed numerically by a centered finite differencing scheme in a automatic fashion. 
+// The hability to support user-provided derivatives will hopefully be 
+// implemented in the near future.
+
+#ifndef CONJUGATE_GRADIENT_HH
+#define CONJUGATE_GRADIENT_HH
+
+#include "Optima.hpp"
+#include "defs.hpp"
+#include "Param.hpp"
+
+// Nonlinear Conjugate Gradient 
+/*
+    This conjugate gradient procedure implemented in this 
+    object is an extension of the conjugate gradient 
+    used in linear system solving to handle non quadratic
+    objective functions. Such extensions amount basically
+    to the inclusion of a line search step and a 
+    modification in the computation of the conjugate directions.
+    Details can be found in the classic (and tough!) book 
+    Practical Optimization by Powell.
+
+*/
+
+template <class LS>
+class ConjugateGradient : public Optima<LS>
+{
+  typedef typename LS::Real Real;
+  typedef typename LS::Param Param;
+  typedef typename LS::Vect Vect;
+  typedef typename LS::VMat VMat;
+  typedef LS  LineSearch;
+
+   public:
+   
+   // a constructor
+  ConjugateGradient(///pointer to the line-search object.
+					LS * ls,
+					///Maximum number of iterations
+					int iter, 
+					///minimum accepted gradient at optimum solution
+					Real tol,
+					///vebose or quiet
+					int verb=0);
+  /* At the present version, you must use the CubicLineSearch procedure */
+   // a constructor
+  ~ConjugateGradient(){;}
+
+  // conjugate gradient search starting from m0, returns an optimum Model 
+  Param optimizer(Param& m0);
+
+};
+
+
+template <class LS>
+ConjugateGradient<LS>::ConjugateGradient(LS * p, int it, Real eps, int verb)
+  : Optima<LS>(verb)
+{
+  ls=p;
+  iterMax 	= 	it;
+  tol 		= 	eps;
+  iterNum 	= 	0;
+}
+
+// Necessite :
+// un produit scalaire sur Vect : (u,v)
+// un produit de Vect par un Real : operator*
+// un produit de Vect par un Real : operator*=
+// une diff�rence de Vect : operator-
+template <class LS>
+ConjugateGradient<LS>::Param ConjugateGradient<LS>::optimizer(Param& model0)
+{ 
+  //reset the residue history for every new optimizer
+  iterNum = 0;
+  isSuccess = 0;
+  if (residue != NULL) 
+	{
+	  delete residue;
+	  residue = new list<Real>;
+	}
+
+  int n = model0.size();
+  Param model1(model0);     		// new model 
+  Vect 		search(n);		// search direction
+  Vect 		g0(n);			// old gradient vector
+  Vect 		g1(n);			// new gradient vector
+  double 			beta;			// beta parameter
+  double 			lambda = .025;		// line search parameter
+  double 			descent = 0.;		// descent direction
+
+  // Beginning iterations
+  g0 = *(ls->gradient(model0));
+
+  // check the gradient, in case the initial model is the optimal,
+  Real err = (Real)sqrt((g0,g0));
+  if (isVerbose) cout << "Initial residue : " << err << endl;
+  appendResidue(err);	// residual
+  if (err < tol) {
+	if (isVerbose) cout << "Initial guess was great! \n";
+	isSuccess = 1;
+	return model0;
+  }
+  
+  // Considering first iteration 
+  search = -1. * g0;
+  descent = (search,g0);
+  
+  // On utilise un CubicLineSearch
+//    cerr<<"Line Search"<<endl;
+//    cerr<<"model0 "<<model0;
+//    cerr<<"search "<<(Param)search; // on le caste en param rien que pour afficher
+//    cerr<<"descent "<<descent<<endl;
+//    cerr<<"lambda "<<lambda<<endl;
+//    cerr<<endl;
+  
+  model1 = ls->search(model0, search, descent, lambda);
+  g1 = *(ls->gradient(model1));		// Gradient at new model
+  err = (Real)sqrt((g1,g1));
+  if (isVerbose) cout << "Iteration (0) : " << "current value of the objective function: "
+					  << ls->currentValue() << "\t current residue: "<< err << endl;
+  appendResidue(err);	// residual
+  
+  iterNum = 0;
+  Real temp;
+  do 
+	{
+
+      iterNum++;
+	  
+      temp 	= 	1./((g0,g0));
+      beta	=	((g1-g0),g1);		
+      beta 	*= 	temp;			// computation Polak & Ribiere
+	  
+      search =  beta * search - g1;		// search direction
+      
+      descent = (search,g1);			// descent
+      if (descent > 0.)
+		{
+		  if (isVerbose){
+			cout << "Reset search direction to gradient vector! \n";
+		  }
+		  search = -1.*g1;
+		  descent = (search,g1);
+		} 
+	  
+      model0 = model1;
+      g0 = g1;	// save the old model and gradient before new search
+	  
+	  // On utilise un CubicLineSearch
+//  	  cerr<<"Line Search"<<endl;
+//  	  cerr<<"model0 "<<model0;
+//  	  cerr<<"search "<<(Param)search; // on le caste en param rien que pour afficher
+//  	  cerr<<"descent "<<descent<<endl;
+//  	  cerr<<"lambda "<<lambda<<endl;
+//  	  cerr<<endl;
+      
+      model1 = ls->search(model0, search, descent, lambda); // line search
+      g1 = *(ls->gradient(model1));
+	    
+      err = (Real)sqrt((g1,g1));
+      if (isVerbose) 
+		cout << "Iteration (" << iterNum << ") : "<<"current value of the nrj : "
+			 <<ls->currentValue() << "\t current residue : "<< err << endl;
+      appendResidue(err);	// residual
+
+	} while (finalResidue() > tol && iterNum < iterMax); // stopping criterion
+  
+  if (finalResidue() <= tol) isSuccess = 1;
+  
+  return(model1);			// hopefully answer
+}
+
+#endif
+
diff --git a/src/Algo/CubicLS.hpp b/src/Algo/CubicLS.hpp
new file mode 100644
index 0000000..25e2d0d
--- /dev/null
+++ b/src/Algo/CubicLS.hpp
@@ -0,0 +1,178 @@
+// Tony : lambda=0.25 ou lambda=0.025 ???
+// cf. CG.hpp
+//
+//			The minimizer along the search direction is returned by the function.
+//
+/*
+  CubicLineSearch() class implements the efficient line search procedure
+  described in Dennis and Schbabel's book entitled "Numerical
+  Methods for Unconstrained and Nonlinear Equations. The 
+  objective is to perform a unidimensional search for a minimum
+  point along a specified direction in a multidimensional 
+  space.
+*/
+// This procedure seems to be fairly robust. It has worked for a fairly broad class of
+// problems from optimization of standard test functons in optimization theory and
+// to hard geophysical problems as stacking power optimization and amplitude 
+// seismogram inversion
+
+#ifndef CUBIC_LINE_SEARCH_HH
+#define CUBIC_LINE_SEARCH_HH
+
+#include "LineSearch.hpp"
+#include <limits.h>
+#include <float.h>
+
+template <class LS>
+class CubicLineSearch : public LS
+{
+  typedef typename LS::Real Real;
+  typedef typename LS::Param Param;
+  typedef typename LS::Vect Vect;
+  typedef typename LS::VMat VMat;
+  typedef LS  LineSearch;
+  typedef tNRJ<Param,Vect,VMat,Real> NRJ;
+public:
+  //a constructor with the default delta
+  CubicLineSearch(NRJ* f, int iter);
+  //a constructor with the specified delta
+  CubicLineSearch(NRJ* f, int iter, Vect* delta);
+   /*    The parameter $delta$ is not used by the line search 
+         itself. Rather it is used in the numerical computation
+         of the derivatives using centered differences. For
+         example the derivative of f(x) at the point x0 would be
+         given by 
+         \[f(x0 - delta) - f(x0 + delta) / 2 * delta\]
+	 */
+   ~CubicLineSearch();
+
+   //search for the minimum model along a 1-D direction
+    Param search(///initial model for the line search
+			 const Param& m0, 
+			 ///search direction
+			 Vect& direction, 
+			 /// product of search direction and gradient
+			 Real descent,
+			 ///a parameter
+			 double lambda);
+   /* The parameter $lambda$ controls the accuraccy of the  
+     line search. $lambda = .25$ is a good choice.
+    The minimizer along the search direction is returned 
+    by the function.  */
+
+  // lambda=0.25 ou lambda=0.025 ???
+  // cf. CG.hpp
+};
+
+template <class LS>
+CubicLineSearch<LS>::CubicLineSearch(NRJ* f, int it) 
+: LS(f)
+{	this->iterMax	=	it;
+}
+
+template <class LS>
+CubicLineSearch<LS>::CubicLineSearch(NRJ* f, int it, Vect* interval)
+: LS(f,interval)
+{	this->iterMax	=	it;
+}
+
+template <class LS>
+CubicLineSearch<LS>::~CubicLineSearch()
+{}
+
+// Code for the Cubic Line Search
+template <class LS>
+typename CubicLineSearch<LS>::Param CubicLineSearch<LS>::search(const Param& current_solution, Vect& p, Real slope, double lambda){
+  
+  int tst = 0;					// useful vars
+  Real alpha2=0, alpha_tmp=0, alpha_prev=0;
+  Real alpha_prev2=0, alpha=0;
+  Real f1=0, f2=0, fprev=0;
+  Real a=0, b=0;
+  Real c=0, cm11=0, cm12=0, cm21=0, cm22=0;
+  Real disc=0;
+  Real new_m=0, old_m=0;
+  Param new_solution(current_solution);
+  cout << " search " << p.max() << endl;
+  assert(p.max() <1e100);
+  old_m = this->nrj->getVal(current_solution); // Evaluation at the current solution
+  this->iterNum = 0; this->iterNum++;				// iteration counter
+  alpha = 1.;					// updating step
+
+  new_solution = this->update(current_solution,1,alpha,p);	// updating
+  new_m = this->nrj->getVal(new_solution);     	// Evaluation at the 
+							// new solution
+  this->iterNum++;
+
+  // Implementing Goldstein's test for alpha too small
+  while (new_m < old_m + (1. - lambda)*alpha*slope && this->iterNum< this->iterMax)
+	{
+	  alpha *= 3;
+	  new_solution = this->update(current_solution,1, alpha, p);
+	  new_m = this->nrj->getVal(new_solution);
+	  this->iterNum++;
+	}
+  if (this->iterNum == this->iterMax)
+	cerr << "Alpha overflowed! \n";
+  
+  // Armijo's test for alpha too large
+  alpha_prev = alpha; // H.L. Deng, 6/13/95
+  while (new_m > old_m + lambda*alpha*slope && this->iterNum < this->iterMax)
+	{
+	  alpha2 = alpha * alpha;
+	  f1 = new_m - old_m - slope * alpha;
+	  
+	  if (tst == 0)
+		{
+		  alpha_tmp = -slope * alpha2 / (f1 * 2.);
+		  // tentative alpha
+		  
+		  tst = 1;
+		}
+	  else
+		{
+		  alpha_prev2 = alpha_prev * alpha_prev;
+		  f2 = fprev - old_m - alpha_prev * slope;
+		  
+		  c = 1. / (alpha - alpha_prev);
+		  cm11 = 1. / alpha2;
+		  cm12 = -1. / alpha_prev2;
+		  cm21 = -alpha_prev / alpha2;
+		  cm22 = alpha / alpha_prev2;
+		  
+		  a = c * (cm11 * f1 + cm12 * f2);
+		  b = c * (cm21 * f1 + cm22 * f2);
+		  disc = b * b - 3. * a * slope;
+		  
+		  if ((Abs(a) > FLT_MIN) && (disc > FLT_MIN))
+			alpha_tmp = (-b + sqrt(disc)) / (3. * a);
+		  else
+			alpha_tmp = slope * alpha2 / (2. * f1);
+		  
+		  if (alpha_tmp >= .5 * alpha)
+			alpha_tmp = .5 * alpha;
+		}
+	  alpha_prev = alpha;
+	  fprev = new_m;
+	  
+	  if (alpha_tmp < .1 * alpha)
+		alpha *= .1;
+	  else
+		alpha = alpha_tmp;
+	  
+	  new_solution = this->update(current_solution,1, alpha, p);
+	  new_m = this->nrj->getVal(new_solution);
+	  this->iterNum++;
+	}
+  if (this->iterNum == this->iterMax){
+	cerr << "Alpha underflowed! \n";
+	cerr << this->iterMax;
+  }
+  
+  this->value = new_m;
+  this->appendSearchNumber();
+  return (new_solution);				// # of iterations
+}
+
+#endif
+
diff --git a/src/Algo/LineSearch.hpp b/src/Algo/LineSearch.hpp
new file mode 100644
index 0000000..24a751b
--- /dev/null
+++ b/src/Algo/LineSearch.hpp
@@ -0,0 +1,259 @@
+#ifndef LINE_SEARCH_HH
+#define LINE_SEARCH_HH
+
+#include <list>
+#include "defs.hpp"
+#include "NRJ.hpp"
+#include <limits.h>
+#include <float.h>
+
+#define MAX_IT_LS	1000
+
+/* 
+  This is the base class for one dimensional
+  line search algorithms. Some optimization
+  algorithms need to find the optimimal point
+  on one searching directions.
+  Classes derived from this class inherit features of 
+  LineSearch. This class cannot be used directly.
+*/
+
+// Attention :
+// pas de copie
+// pas d'op�rateur =
+
+template <class P, class V,class M,class VM,class R>
+class LineSearch { 
+public:
+	typedef R Real;
+	typedef VM VMat;
+	typedef M Mat;
+	typedef P Param;
+	typedef V Vect;
+	typedef  tNRJ<Param,Vect,VMat,Real> NRJ;
+
+private:
+  //ne sert que si on calcule le gradient de mani�re num�rique
+  //dans ce cas, on lui alloue de la m�moire
+  //sinon, ce n'est qu'un pointeur vers le gradient de nrj
+  Vect* grad;
+  int ref; //ref vaut 1 quand on a cr�� le gradient de mani�re num�rique
+
+  void numericalGradient(const Param &);
+
+
+protected:
+  //maxinum number of iterations allowed;
+  int iterMax;
+  //the number iterations so far
+  // � r�initialiser dans les classes d�riv�es
+  int iterNum;
+  //the history of number of iteration of iteration
+  list<int>* iterHistory;
+  //the value at the minimum along the direction
+  //mis a jour dans les classes derivees
+  Real value;
+  //the delta used for calculating numerical gradient
+  // c'est du meme type que le gradient
+  Vect* step;
+  //pointer to the nrj
+  NRJ *	nrj;
+  
+  void appendSearchNumber();
+  
+public:
+  
+  //a constructor with pointer to the nrj and
+  //to the step if numerical gradient is computed
+  LineSearch(NRJ* f,Vect* interval = NULL);
+  virtual ~LineSearch();
+
+  // point de d�part et direction de descente + des param�tres
+  virtual Param search(const Param&, Vect&, Real, double);
+
+  //compute the gradient Vector
+  //C'est tjs le linesearch � qui on demande le gradient dans la suite
+  Vect* gradient(const Param& m);
+  //C'est tjs le linesearch � qui on demande le hessien dans la suite
+  VMat* hessian(const Param& m);
+  //evaluate the nrj;
+  Real evaluate(const Param& m);
+  
+  //number of iterations for all line searches.
+  list<int> allSearchIterations();
+
+  //number of iterations in the current line search;
+  int searchIterations();
+  // value of the objective function for the current Model
+  Real currentValue();
+
+  Param update(const Param&,Real, Real, const Vect&) const;
+
+};
+
+template <class P, class V,class M,class VM,class R>
+LineSearch<P,V,M,VM,R>::LineSearch(NRJ* p, Vect* interval )
+{
+   iterMax 	= 	MAX_IT_LS;
+   iterNum 	= 	0;
+   nrj 		= 	p;
+   step		=	interval;
+   iterHistory 	= 	new list<int>;
+   grad = NULL;
+   ref=0;
+   value=0.;
+}
+
+template <class P, class V,class M,class VM,class R>
+LineSearch<P,V,M,VM,R>::~LineSearch(){
+  if (iterHistory!=NULL) delete	iterHistory;
+  if (ref==1 && grad!=NULL) delete grad;
+  if (step!=NULL) delete step;
+}
+
+template <class P, class V,class M,class VM,class R>
+void	LineSearch<P,V,M,VM,R>::appendSearchNumber()
+{
+  iterHistory[0].push_back(iterNum);
+}
+
+template <class P, class V,class M,class VM,class R>
+list<int>	LineSearch<P,V,M,VM,R>::allSearchIterations()
+{ return iterHistory[0];}
+
+template <class P, class V,class M,class VM,class R>
+int 		LineSearch<P,V,M,VM,R>::searchIterations()
+{return iterNum;}
+
+template <class P, class V,class M,class VM,class R>
+typename LineSearch<P,V,M,VM,R>::Real 		LineSearch<P,V,M,VM,R>::currentValue()
+{return value;}
+
+template <class P, class V,class M,class VM,class R>
+typename LineSearch<P,V,M,VM,R>::Param LineSearch<P,V,M,VM,R>::search(const Param& m,Vect& v,Real alpha, double beta) 
+{
+  cerr << "You need to specify the LineSearch method!"<<endl;
+  exit(1);
+  return	0;
+}
+
+// Calcul par diff�rence finie centr�e
+template <class P, class V,class M,class VM,class R>
+void LineSearch<P,V,M,VM,R>::numericalGradient(const Param& m)
+{
+    int	n 		= 	m.size();
+
+	// au premier appel, on initialise le gradient
+	if (grad==NULL){
+	  grad = new Vect(n);
+	  ref=1;
+	}
+
+    Real diffValue, newValue, off;
+    Param	m1(m);
+
+	if (step!=NULL){	  
+	  for (int i = 0; i < n; i++) {
+		off		= 	step[0][i];
+		m1[i] 		-= 	off;
+		newValue	=	nrj->getVal(m1);
+		m1[i]           +=      2*off;
+		diffValue	=	nrj->getVal(m1);
+		diffValue	-=	newValue;
+		(*grad)[i] 	= 	diffValue/(2*off);
+		m1[i]		=	m[i];
+	  }
+	}
+	else{ // Par d�faut, on fait un pas de taille relative 10^-3
+	  for (int i = 0; i < n; i++) {
+		off		= 	m[i]/1000;
+		m1[i] 		-= 	off;
+		newValue	=	nrj->getVal(m1);
+		m1[i]           +=      2*off;
+		diffValue	=	nrj->getVal(m1);
+		diffValue	-=	newValue;
+		(*grad)[i] 	= 	diffValue/(2*off);
+		m1[i]		=	m[i];
+	  }
+	}
+	
+}
+
+template <class P, class V,class M,class VM,class R>
+typename LineSearch<P,V,M,VM,R>::Vect*	LineSearch<P,V,M,VM,R>::gradient(const Param& m)
+{
+  Vect* g;
+    
+  g=nrj->getGradient(m);
+
+  if (g==NULL){
+	cerr<<"Undefined gradient for this NRJ function !"<<endl;
+	cerr<<"will use a numerical gradient..."<<endl;
+	numericalGradient(m);
+  }
+  else
+	grad=g;
+  
+  return grad;
+}
+
+template <class P, class V,class M,class VM,class R>
+typename LineSearch<P,V,M,VM,R>::VMat*	LineSearch<P,V,M,VM,R>::hessian(const Param& m)
+{
+  VMat* h;
+    
+  h=nrj->getHessian(m);
+
+  if (h==NULL){
+	cerr<<"Hessien is undefined for this NRJ function !"<<endl;
+	exit(1);
+  }
+  
+  return h;
+}
+
+
+template <class P, class V,class M,class VM,class R>
+typename LineSearch<P,V,M,VM,R>::Real LineSearch<P,V,M,VM,R>::evaluate(const Param& m)
+{
+  return nrj->getVal(m);
+}
+
+// on avance depuis alpha*m, m �tant le point actuel dans la direction dmod, de beta
+// on v�rifie qu'on est dans les bornes
+
+template <class P, class V,class M,class VM,class R>
+typename  LineSearch<P,V,M,VM,R>::Param LineSearch<P,V,M,VM,R>::update(const Param& m,Real alpha, Real beta, const Vect& dmod) const
+{
+  Param newparam(m);
+  long ndim=m.size();
+  
+  Vect direction(dmod);
+  
+  if (direction.size() != ndim) {
+	cerr << "Size of direction is different from dimensions." << endl;
+	exit(1);
+  }
+  
+  // check to see if the new model is out of the upper bound
+    cout << "update "<<  m.min() << " " << m.max() <<  " " << direction.max() << " " << dmod.max() ;
+  direction = alpha * m + beta * direction;
+  newparam = direction;  
+  cout << " ;  "<<  newparam.min() << " " << newparam.max() << endl;
+  if ((m.modMax() != NULL) && (m.modMin() != NULL))
+	{
+	  for (long i=0; i<ndim; i++){
+		
+		if ((newparam[i]-(*(m.modMax()))[i])>0)
+		  newparam[i] = (*(m.modMax()))[i];
+		
+		if ((newparam[i]-(*(m.modMin()))[i])<0)
+		  newparam[i] = (*(m.modMin()))[i];
+	  }
+    }
+  
+  
+  return newparam;
+}
+
+#endif
diff --git a/src/Algo/Makefile.am b/src/Algo/Makefile.am
new file mode 100644
index 0000000..c963b6d
--- /dev/null
+++ b/src/Algo/Makefile.am
@@ -0,0 +1,10 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+
+# This is not compiled as a separate library because its
+# interconnections with other libraries have not been solved.
+
+EXTRA_DIST=BFGS.hpp BrentLS.hpp CG.hpp CubicLS.hpp defs.hpp lgalgo.cpp	\
+LineSearch.hpp NewtonRaphson.hpp NRJ.hpp Optima.hpp Param.hpp		\
+RosenBrock.hpp
diff --git a/src/Algo/NRJ.hpp b/src/Algo/NRJ.hpp
new file mode 100644
index 0000000..40755e5
--- /dev/null
+++ b/src/Algo/NRJ.hpp
@@ -0,0 +1,107 @@
+#ifndef NRJ_HH
+#define NRJ_HH
+
+#include "defs.hpp"
+
+// Attention :
+// pas de copie
+// pas d'op�rateur =
+
+template <class Param, class Vect, class Mat,class Real>
+class tNRJ{
+protected:
+
+  int				nappel_val;
+  int				nappel_grad;
+  int				nappel_hess;
+  int               nparam;
+  
+  Real              val;
+  Vect*             grad;
+  Mat*              hess;
+  
+public:
+
+  // Attention : dans le constructeur de l'tNRJ, il faut vraiment
+  // initialiser grad ou hess, si on les utilise... Ce n'est pas
+  // fait ici (parce que l'initialisation d�pend trop du type)
+  tNRJ(int);
+  virtual ~tNRJ();
+  
+  // � preciser pour chaque fonction tNRJ
+  virtual Real Val(const Param&) = 0;
+  
+  Real getVal(const Param&);
+
+  // � preciser �ventuellement, sinon �a rend nul
+  virtual Vect* Gradient(const Param&);
+  
+  Vect* getGradient(const Param&);
+
+  // � preciser �ventuellement, sinon �a rend nul
+  virtual Mat* Hessian(const Param&);
+
+  Mat* getHessian(const Param&);
+  
+
+  int Appel_Val() const {return nappel_val;};
+  int Appel_Grad() const {return nappel_grad;};
+  int Appel_Hess() const {return nappel_hess;};
+  
+
+};
+
+template <class Param, class Vect, class Mat,class Real>
+tNRJ<Param,Vect, Mat, Real>::~tNRJ()
+{
+  if (grad!=NULL) delete grad;
+  if (hess!=NULL) delete hess;
+}
+
+template <class Param, class Vect, class Mat,class Real>
+tNRJ<Param,Vect, Mat, Real>::tNRJ(int n)
+{
+  nparam=n;
+  nappel_val=0;
+  nappel_grad=0;
+  nappel_hess=0;
+  grad = NULL;
+  hess = NULL;
+  val=0.;
+}
+
+template <class Param, class Vect, class Mat,class Real>
+Real tNRJ<Param,Vect, Mat, Real>::getVal(const Param& p)
+{
+	nappel_val++;
+	return Val(p);
+}
+
+template <class Param, class Vect, class Mat,class Real>
+Vect* tNRJ<Param,Vect, Mat, Real>::getGradient(const Param& p)
+{
+	nappel_grad++;
+	return Gradient(p);
+}
+
+template <class Param, class Vect, class Mat,class Real>
+Vect* tNRJ<Param,Vect, Mat, Real>::Gradient(const Param&)
+{
+  return NULL;
+}
+
+template <class Param, class Vect, class Mat,class Real>
+Mat* tNRJ<Param,Vect, Mat, Real>::getHessian(const Param& p)
+{
+	nappel_hess++;
+	return Hessian(p);
+}
+
+template <class Param, class Vect, class Mat,class Real>
+Mat* tNRJ<Param,Vect, Mat, Real>::Hessian(const Param&)
+{
+  return NULL;
+}
+
+
+#endif
diff --git a/src/Algo/NewtonRaphson.hpp b/src/Algo/NewtonRaphson.hpp
new file mode 100644
index 0000000..6bbf262
--- /dev/null
+++ b/src/Algo/NewtonRaphson.hpp
@@ -0,0 +1,115 @@
+#ifndef NEWTONRAPHSON_HH
+#define NEWTONRAPHSON_HH
+
+#include "Optima.hpp"
+#include "defs.hpp"
+
+/* At the present version, you must use the CubicLS procedure */
+
+// Necessite une "vraie" classe Matrice
+template <class LS>
+class Newt : public Optima<LS>
+{
+  typedef typename LS::Real Real;
+  typedef typename LS::Param Param;
+  typedef typename LS::Vect Vect;
+  typedef typename LS::VMat VMat;
+  typedef typename LS::Mat Mat;
+  typedef list<Real> mlist;
+public:
+ 
+  Newt(///pointer to the line-search object.
+	   LS * ls, 
+	   ///Maximum number of iterations
+	   int iter, 
+	   ///minimum accepted gradient at optimum solution
+	   Real tol,
+	   ///vebose or quiet
+	   int verb=0);
+  ~Newt(){;}
+  
+  // the Newt search starting from model0, returns an optimum model 
+  Param optimizer(Param& model0);
+
+};
+
+
+template <class LS>
+Newt<LS>::Newt(LS* p, int it, Real eps, int verb) 
+  :Optima<LS>(verb)
+{
+  this->ls=p;
+  this->iterMax 	= 	it;
+  this->tol 		= 	eps;
+  this->iterNum 	= 	0;
+}
+
+// N�cessite pour la classe MAT:
+// - une m�thode de r�solution de Ax=b
+template <class LS>
+typename Newt<LS>::Param Newt<LS>::optimizer( Param& model0)
+{
+  //reset the this->residue history for every new optimizer
+  this->iterNum = 0;
+  if (this->residue != NULL)
+	{
+      delete this->residue;
+      this->residue = new mlist;
+	}
+  
+  // Initial settings for some parameters
+  int n = model0.size();
+  Vect g0(n);
+  double lambda = 0.025;
+  double descent = 0.;
+
+  g0= *(this->ls->gradient(model0));
+  
+  // check the gradient, in case the initial model is the optimal
+  double err = (Real)sqrt((g0,g0));
+  
+  if (this->isVerbose) cerr << "Initial this->residue : " << err << endl;
+
+  this->appendResidue(err);	// residual
+
+  if (err < this->tol)
+	{
+      if (this->isVerbose) cerr << "Initial guess was great! \n";
+      this->isSuccess = 1;
+      return model0;
+	}
+   
+  Vect g1(n);
+  Vect s(n);
+  Param model1(model0);
+  
+  while (this->finalResidue() > this->tol && this->iterNum < this->iterMax)
+	{
+	  //searching directions
+	 // s = g0/(*this->ls->hessian(model0)); //on r�initialise LU a chaque fois
+	  this->ls->hessian(model0)->Solve(s,g0);
+	  s = -1.*s;
+
+	  descent = (s,g0);
+	  // Cubic Line Search
+	  model1 = this->ls->search(model0, s, descent, lambda);
+	  g1 = *(this->ls->gradient(model1));
+	  err = (Real)sqrt((g1,g1));
+	  
+	  if (this->isVerbose)
+		cerr << "Iteration (" << this->iterNum << ") : "<<"current value of the objective function: "
+			 <<this->ls->currentValue() << "\t current this->residue: "<< err << endl;
+	  
+	  this->appendResidue(err);	// residual
+	  
+	  g0=g1;
+	  model0=model1;
+	  
+	  this->iterNum ++;
+	}
+  
+  return(model1);
+}
+
+#endif
+
diff --git a/src/Algo/Optima.hpp b/src/Algo/Optima.hpp
new file mode 100644
index 0000000..f4decee
--- /dev/null
+++ b/src/Algo/Optima.hpp
@@ -0,0 +1,116 @@
+#ifndef OPTIMA_HH
+#define OPTIMA_HH
+
+#include "NRJ.hpp"
+#include <limits.h>
+#include "defs.hpp"
+
+#define MAX_IT_OPT 1000
+
+//==================
+//define the base class for  optimization classes
+//	H. Lydia Deng, 03/14/94
+//======================
+
+/*
+  This is the base class for general optimization classes.
+  Classes derived from this class inherit features of 
+  Optima. This class cannot be instantiated directly.
+*/
+
+// Attention :
+// pas de copie
+// pas d'op�rateur =
+
+template <class LS>
+class Optima {
+  typedef typename LS::Real Real;
+  typedef typename LS::Param Param;
+  typedef typename LS::Vect Vect;
+  typedef typename LS::VMat VMat;
+  typedef LS  LineSearch;
+  typedef list<Real> mlist;
+
+protected:
+  // maximum number of iterations
+  int iterMax;
+  int iterNum;
+  // tolerance error
+  // c'est une tol�rance sur la norme euclidienne du gradient
+  Real  tol;
+  // mlist of residue 
+  mlist *  residue;
+  // pointer to LS
+  LS * ls;
+  // verbose or quiet
+  int  isVerbose;
+  // the flag indicating if the search was a success
+  int  isSuccess; 
+  // append the new residue to the mlist
+  void appendResidue(Real res); 
+  
+public:
+  
+  Optima(int verb=0);
+  virtual ~Optima();
+  
+  virtual Param optimizer(Param&) = 0;
+  
+  //Output residues
+
+  int   ifSuccess();
+  //  residue of the last iteration
+  Real finalResidue();
+  // residue of the first iteration
+  Real firstResidue();
+  //  residues of all iterations
+  mlist allResidue();
+  //  normalized residues of all iterations
+  mlist normResidue();
+
+};
+
+template <class LS>
+Optima<LS>::Optima(int verbose){ 
+  residue 	= 	new mlist; 
+  isVerbose 	= 	verbose;
+  isSuccess       =       0;
+  ls		=	NULL;
+  tol		=	0.;
+  iterMax		=	MAX_IT_OPT;
+}
+
+template <class LS>
+Optima<LS>::~Optima() { 
+  if (residue!=NULL) delete residue;
+}
+
+//Output residues
+template <class LS>
+int Optima<LS>::ifSuccess()
+{return isSuccess;}
+
+template <class LS>
+typename Optima<LS>::Real Optima<LS>::finalResidue()
+{return residue->back();}
+
+template <class LS>
+typename Optima<LS>::Real Optima<LS>::firstResidue()
+{return residue->front();}
+
+template <class LS>
+typename Optima<LS>::mlist Optima<LS>::allResidue()
+{return *residue;}
+
+template <class LS>
+typename Optima<LS>::mlist Optima<LS>::normResidue()
+{return normalize(*residue);} //cf. defs.hpp
+
+template <class LS>
+void Optima<LS>::appendResidue(Real res)
+{
+  (residue[0]).push_back(res);
+}      
+
+#endif
+
diff --git a/src/Algo/Param.hpp b/src/Algo/Param.hpp
new file mode 100644
index 0000000..4b8ea3a
--- /dev/null
+++ b/src/Algo/Param.hpp
@@ -0,0 +1,232 @@
+// Class Param
+// C'est la classe des param�tres par rapport auxquels on optimise
+// Derive de la classe KN
+// On pourra �ventuellement lui ajouter des contraintes
+
+#ifndef PARAM_HH
+#define PARAM_HH
+
+#include <iostream>
+using namespace std;
+
+#include "defs.hpp"
+//#include "mvvtp.h"
+//#include "mvblas.h"
+
+// on a besoin du type Vect pour la fonction update
+template <class Real>
+class Param: public KN<Real> {
+  
+private:
+  int	ndim;
+  // Ces bornes servent �ventuellement dans la m�thode update de LineSearch.hpp
+  // C'est une mani�re d'impl�menter le gradient projet�...
+  KN<Real>*	maxParam;
+  KN<Real>*	minParam;
+  
+public:
+  Param();
+  //construct a continuous model with size n
+  Param(int n);
+  //construct a continuous model space with boundary and initial values
+  Param(const KN<Real>& maxp, const KN<Real>& minp, const KN<Real>& initmod);
+  //construct a continuous model space with boundary
+  Param(const KN<Real>& maxp, const KN<Real>& minp);
+  //construct a continuous model space with initial values 
+  Param(const KN<Real>& initmod);
+  //operateur de copie
+  Param(const Param<Real>& p);
+  virtual ~Param();
+
+  Param<Real>& operator=(const Param<Real>&);
+  
+  KN<Real>* modMax() const;
+  KN<Real>* modMin() const;
+  void setModMax(const KN<Real>& v);
+  void setModMin(const KN<Real>& v);
+  
+  //cf. Stroustrup page 612-613 pour l'impl�mentation de operator<<
+  virtual ostream& toto(ostream&) const;
+  private: // pas de copy
+};
+
+// Constructors
+
+template <class Real>
+Param<Real>::Param(void)
+  :KN<Real>()
+{
+  //  cerr<<"Constructeur par d�faut Param"<<endl;
+  
+   maxParam = NULL;
+   minParam = NULL;
+}
+
+
+template <class Real>
+Param<Real>::Param(int n)
+  :KN<Real>(n)
+{
+  //  cerr<<"Constructeur 0 Param"<<endl;
+  
+   maxParam = NULL;
+   minParam = NULL;
+}
+
+
+template <class Real>
+Param<Real>::Param(const KN<Real>& maxp, const KN<Real>& minp, const KN<Real>& initmod)
+  :KN<Real>(initmod)
+{
+  int ndim=initmod.size();
+
+  //  cerr<<"Constructeur 1 Param"<<endl;
+  
+  maxParam = new KN<Real>(ndim);
+  minParam = new KN<Real>(ndim);
+  maxParam[0] = maxp;
+  minParam[0] = minp;
+}
+
+template <class Real>
+Param<Real>::Param(const KN<Real>& maxp, const KN<Real>& minp)
+  :KN<Real>(Min(minp.size(),maxp.size()))
+{
+  int ndim=Min(minp.size(),maxp.size());
+
+  //  cerr<<"Constructeur 2 Param"<<endl;
+	
+  maxParam = new KN<Real>(ndim);
+  minParam = new KN<Real>(ndim);
+  maxParam[0] = maxp;
+  minParam[0] = minp;
+}
+
+
+template <class Real>
+Param<Real>::Param(const KN<Real>& initmod)
+  :KN<Real>(initmod)
+{
+  //  cerr<<"Constructeur 3 Param"<<endl;
+  
+  maxParam = NULL;
+  minParam = NULL;
+  
+}
+
+// op�rateur de copie
+template <class Real>
+Param<Real>::Param(const Param& p)
+  :KN<Real>(p)
+{
+  //  cerr<<"Operateur de copie de Param"<<endl;
+  
+  if ((p.maxParam)==NULL)
+	maxParam=NULL;
+  else{
+	maxParam = new KN<Real>(ndim);
+	*maxParam=*(p.maxParam);
+  }
+  
+  if ((p.minParam)==NULL)
+	minParam=NULL;
+  else{
+	minParam = new KN<Real>(ndim);
+	*minParam=*(p.minParam);
+  }
+}
+
+template<class Real>
+Param<Real>& Param<Real>::operator=(const Param<Real>& p)
+{
+  //  cerr<<"Operateur = de Param"<<endl;
+  // modif FH 042005 for gcc4.0 
+  KN<Real> & a1= *this;
+  const KN<Real> & a2= p;
+  a1=a2; // Operateur de copie de KN
+  
+  int ndim=p.size();
+  
+  if ((p.maxParam)==NULL)
+	maxParam=NULL;
+  else{ 
+        if(maxParam) delete maxParam;
+	maxParam = new KN<Real>(ndim);
+	*maxParam=*(p.maxParam);
+  }
+  
+  if ((p.minParam)==NULL)
+	minParam=NULL;
+  else{
+        if(minParam) delete minParam;
+	minParam = new KN<Real>(ndim);
+	*minParam=*(p.minParam);
+  }
+ 
+  return (*this);
+  
+}
+ 
+template<class Real>
+Param<Real>::~Param()
+{
+  //  cerr<<"Destructeur de Param"<<endl;
+
+  if (maxParam != NULL)  delete maxParam;
+  if (minParam != NULL)  delete minParam;
+
+}
+
+
+
+template<class Real>
+KN<Real>* Param<Real>::modMax() const
+{
+  return maxParam;
+}
+ 
+template<class Real>
+KN<Real>* Param<Real>::modMin() const
+{
+  return minParam;
+}
+ 
+template<class Real>
+void Param<Real>::setModMax(const KN<Real>& v)
+{ 
+  if (maxParam!=NULL) delete maxParam;
+  maxParam= new KN<Real>(v);
+	}
+ 
+template<class Real>
+void Param<Real>::setModMin(const KN<Real>& v)
+{
+  if (minParam!=NULL) delete minParam;
+  minParam= new KN<Real>(v);
+	}
+
+
+
+//cf. Stroustrup page 612-613 pour l'impl�mentation de operator<<
+
+template<class Real>
+ostream& Param<Real>::toto (ostream& os) const
+{
+  for (long i=0;i<(*this).size();i++)
+	os << (*this)[i]<<" ";
+  os<<endl;
+  
+  return os;
+}
+
+template<class Real>
+ostream& operator <<(ostream& os, const Param<Real>& d)
+{
+  return d.toto(os);
+}
+
+
+#endif
+
+
+
diff --git a/src/Algo/RosenBrock.hpp b/src/Algo/RosenBrock.hpp
new file mode 100644
index 0000000..fb0e50c
--- /dev/null
+++ b/src/Algo/RosenBrock.hpp
@@ -0,0 +1,120 @@
+#ifndef ROSENBROCK_HH
+#define ROSENBROCK_HH
+
+#include "NRJ.hpp"
+#include "Param.hpp"
+//#include "mvvtp.h"
+//#include "mvblas.h"
+
+template <class Real,class Mat>
+class RosenBrock : public tNRJ<Param<Real>,KN<Real>,Mat,Real> {
+private:
+protected:
+  
+public:
+  //Constructors and Destructors
+  RosenBrock(int);
+  ~RosenBrock();
+  
+  
+  Real Val(const Param<Real>&);
+  KN<Real>* Gradient(const Param<Real>&);
+  Mat* Hessian(const Param<Real>&);
+  
+};
+
+template <class Real,class Mat>
+RosenBrock<Real,Mat>::RosenBrock(int n)
+  :tNRJ<Param<Real>,KN<Real>,Mat,Real>(n)
+{  // On initialise le gradient
+  this->grad= new KN<Real>(n);
+  // On initialise le hessien
+  // Si on utlise pas le hessien, il suffit qu'il existe un constructeur
+  // pour le type Mat qui prend un parametre entier. C'est vrai pour les
+  // doubles par exemple...
+  this->hess= new Mat(n); 
+  (*this->hess)=0;
+}
+
+template <class Real,class Mat>
+RosenBrock<Real,Mat>::~RosenBrock()
+{ ; }
+
+template <class Real,class Mat>
+Real RosenBrock<Real,Mat>::Val(const Param<Real>& param)
+{	
+  Real ti_1, ti, tt;
+  Real d=0;
+
+  ti_1=param[0];
+  
+  for (int i=1; i < this->nparam; i++) 
+	{
+      ti = param[i];
+      tt = 1-ti_1;
+      d += tt*tt;
+	  tt=ti-ti_1*ti_1;
+	  d += 100*tt*tt;
+	  
+	  ti_1=ti;
+	}
+
+  this->val=d;
+  
+  return d;
+}
+
+template <class Real,class Mat>
+KN<Real>* RosenBrock<Real,Mat>::Gradient(const Param<Real>& param)
+{
+   Real ti_1,ti;
+   ti_1=param[0];
+   ti=param[1];
+
+   (*this->grad)[0]=-200*2*ti_1*(ti-ti_1*ti_1)-2*(1-ti_1);
+   
+   for (int i=1; i<this->nparam-1; i++){
+	 (*this->grad)[i]=200*(ti-ti_1*ti_1);
+	 ti_1=ti;
+	 ti=param[i+1];
+	 (*this->grad)[i] += -200*2*ti_1*(ti-ti_1*ti_1)-2*(1-ti_1);
+   }
+   
+   (*this->grad)[this->nparam-1]=200*(ti-ti_1*ti_1);
+
+   
+   return	this->grad;
+}
+
+
+template <class Real,class Mat>
+Mat* RosenBrock<Real,Mat>::Hessian(const Param<Real>& param)
+{
+  Real ti_1,ti;
+  ti_1=param[0];
+  ti=param[1];
+
+  (*this->hess)(0,0)=-200*2*(ti-ti_1*ti_1)+200*2*2*ti_1*ti_1+2;
+  (*this->hess)(0,1)=-200*2*ti_1;
+  
+  for (int i=1; i<this->nparam-1; i++){
+	(*this->hess)(i,i)=200;
+	(*this->hess)(i,i-1)=-200*2*ti_1;
+	ti_1=ti;
+	ti=param[i+1];
+	(*this->hess)(i,i) += -200*2*(ti-ti_1*ti_1)+200*2*2*ti_1*ti_1+2;
+	(*this->hess)(i,i+1)=-200*2*ti_1;
+  }
+  
+  (*this->hess)(this->nparam-1,this->nparam-1)=200;
+  (*this->hess)(this->nparam-1,this->nparam-2)=-200*2*ti_1;
+  
+  return this->hess;
+}
+
+
+
+#endif
+
+
+
diff --git a/src/Algo/defs.hpp b/src/Algo/defs.hpp
new file mode 100644
index 0000000..077f08a
--- /dev/null
+++ b/src/Algo/defs.hpp
@@ -0,0 +1,118 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef DEFS_H
+#define DEFS_H
+
+#ifndef GLIB
+#define GLIB
+
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+#include <cstdio>
+#include <stddef.h>
+//#include <cassert>
+#include <cmath>
+#include <string.h>
+#include <list>
+using namespace std;
+
+//#include "mvvtp.h"
+//#include "mvblas.h"
+
+#endif
+
+// DEFINE simple constants
+#ifndef Pi
+#define Pi (3.141592653589793)
+#endif
+#ifndef TINY // sert dans BrentLS et Matrix
+#define TINY 		1.0e-20
+#endif
+#ifndef True
+#define True (1)
+#endif
+#ifndef False
+#define False (0)
+#endif
+#ifndef Yes
+#define Yes (1)
+#endif
+#ifndef No
+#define No (0)
+#endif
+
+//Define some simple template functions
+#ifndef Sgn
+#define Sgn(x) ((x) < 0 ? -1.0 : 1.0)
+#endif
+#ifndef Abs
+#define Abs(x) ((x) < 0 ? -(x) : (x))
+#endif
+#ifndef Max
+#define Max(x,y) ((x) > (y) ? (x) : (y))
+#endif
+#ifndef Min
+#define Min(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+#ifndef inValidSize
+#define inValidSize() cerr<<"Warning: incompatible sizes!"<<endl;
+#endif
+
+// Op�rations sur les listes
+//
+template<class Type>
+void affiche(list<Type> l)
+{
+  typename list<Type>::iterator il;
+  for (il=l.begin();il!=l.end();il++) cout <<(*il)<<" ";
+  cout<<endl;
+}
+
+template<class Type>
+list<Type> normalize(list<Type> l) {
+  list<Type> v(l);
+  Type scale = l.front();
+  typename list<Type>::iterator il;
+	
+  if (scale == 0) {
+	cerr << "First element is zero, cannot be normed! \n";
+	return v;
+  }
+  
+  else {
+	for (il=v.begin();il!=v.end();il++)
+	  *il /= scale;
+	return v;
+  }
+}
+
+#endif
+
+
diff --git a/src/Algo/lgalgo.cpp b/src/Algo/lgalgo.cpp
new file mode 100644
index 0000000..b2fb788
--- /dev/null
+++ b/src/Algo/lgalgo.cpp
@@ -0,0 +1,302 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "Mesh3dn.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+#include "NRJ.hpp"
+#include "RosenBrock.hpp"
+#include "LineSearch.hpp"
+#include "CubicLS.hpp"
+#include  "BrentLS.hpp"
+#include "Optima.hpp"
+#include "BFGS.hpp"
+//#include  "CG.hpp"
+#include  "NewtonRaphson.hpp"
+
+//template<class R>
+extern Block *currentblock;
+
+typedef double R;
+
+class PrintErrorCompileNewtow :  public E_F0info { public:  
+ typedef double  Result;
+ static E_F0 *   f(const basicAC_F0 & args)  
+    {   
+     lgerror("\n\n *** change Newtow in Newton .\n  *** Bad name in previous version,\n *** sorry FH.\n\n");
+     return 0;  }   
+    static ArrayOfaType  typeargs() {return  ArrayOfaType(true);}
+    operator aType () const { return atype<double>();} 
+
+};
+class OptimAlgo : public OneOperator 
+{ public:
+  typedef KN<R> Kn;
+  typedef KN_<R> Kn_;
+  typedef R REAL;
+  typedef Param<REAL> PARAM;
+  typedef KN<REAL> VECT;
+  typedef KNM<REAL> MAT;
+  typedef VirtualMatrice<REAL> VMAT;
+  
+   const int cas;
+  
+  
+  
+
+  class E_LCG: public E_F0mps { public:
+    const int cas;
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =3;
+    Expression nargs[n_name_param];
+    Expression X;
+    C_F0 inittheparam,theparam,closetheparam; 
+    Expression J,dJ,hJ;
+    long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    R arg(int i,Stack stack,R a) const{ return nargs[i] ? GetAny<R>( (*nargs[i])(stack) ): a;}
+    
+    class lgNRJ : public tNRJ<PARAM,VECT,VMAT,REAL> {
+    private:
+      Stack stack;
+      Expression J,dJ,hJ,theparame;
+      VECT * gg;
+    protected:
+      void setparam( const Param<R>& x )
+      {
+	KN<double> *p=GetAny<KN<double> *>( (*theparame)(stack) );
+	ffassert( p->N() == x.N());
+	*p =x;
+      }
+    public:
+
+      lgNRJ(Stack s,int n,Expression t,Expression JJ,Expression dJJ,Expression hJJ) 
+	: tNRJ<PARAM,VECT,VMAT,REAL>(n), stack(s),
+	  J(JJ),dJ(dJJ),hJ(hJJ),theparame(t),
+	  gg(0)  
+      { 
+	if(dJ) gg=new VECT(n); 
+      }
+      
+      ~lgNRJ() {
+	if(gg) delete gg;}
+      
+      REAL Val(const Param<R>& x) {
+	setparam(x);
+	assert(J);
+	R ret= GetAny<R>( (*J)(stack));
+	WhereStackOfPtr2Free(stack)->clean();
+	return  ret; }
+      
+      VECT* Gradient(const Param<R>& x) {
+	setparam(x);
+	if ( dJ) { *gg=GetAny<Kn_>( (*dJ)(stack));
+	WhereStackOfPtr2Free(stack)->clean(); }
+	return gg ; //dJ ? GetAny<Kn*>( (*dJ)(stack)) :0;}
+     }
+      
+      VMAT* Hessian(const Param<R>& x) {
+	setparam(x);
+	if (!hJ) return 0;
+	Matrice_Creuse<R> * M=  GetAny<Matrice_Creuse<R> *>( (*hJ)(stack));
+	WhereStackOfPtr2Free(stack)->clean(); 
+	assert(M && M->A );
+	return (VirtualMatrice<R>*) M->A;}
+      
+    };
+    
+    E_LCG(const basicAC_F0 & args,int cc) :
+      cas(cc)
+    {
+      int nbj= args.size()-1;
+      Block::open(currentblock); // make a new block to 
+      X = to<Kn*>(args[nbj]);
+      C_F0 X_n(args[nbj],"n");
+      //  the expression to init the theparam of all 
+      inittheparam = currentblock->NewVar<LocalVariable>("the parameter",atype<KN<R> *>(),X_n);
+      theparam = currentblock->Find("the parameter"); //  the expression for the parameter
+      args.SetNameParam(n_name_param,name_param,nargs);
+      const  Polymorphic * opJ=0;
+      const  Polymorphic * opdJ=0;
+      const  Polymorphic * ophJ=0;
+      if (nbj>0)
+	{  opJ=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+	assert(opJ); }
+      if (nbj>1)
+	{   opdJ=  dynamic_cast<const  Polymorphic *>(args[1].LeftValue());
+	assert(opdJ); }
+      if (nbj>2)   
+	{  ophJ=  dynamic_cast<const  Polymorphic *>(args[2].LeftValue());
+	assert(ophJ); }
+      J=dJ=hJ=0;
+      
+      J= to<R>(C_F0(opJ,"(",theparam));
+      if(opdJ)
+        dJ= to<Kn_>(C_F0(opdJ,"(",theparam));// mai2009 (bug????) Modif FH 17102005 (a verifier) to<Kn*> ->to<Kn>
+      if(ophJ)
+	hJ= to< Matrice_Creuse<R> *>(C_F0(ophJ,"(",theparam));
+      
+      closetheparam=currentblock->close(currentblock);   // the cleanning block expression 
+      /*         
+		 if (nargs[2]) 
+		 {  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(nargs[2]);
+		 assert(op); 
+		 C = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); }
+		 else  C =0; */
+    }
+     
+     virtual AnyType operator()(Stack stack)  const
+    {
+      
+      WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+      typedef LineSearch<PARAM,VECT,MAT,VMAT,REAL> LS;
+      typedef CubicLineSearch<LS> CLS;
+      KN<double> * delta =0;    
+      R tol=arg(0,stack,1E-6);
+      int itMax=arg(1,stack,100L);
+      int itMaxLine=arg(2,stack,100L);
+      bool verbose=verbosity>3;
+      
+      try {     
+	Kn &x = *GetAny<Kn *>((*X)(stack));
+	
+	const int n=x.N();
+	//Kn * para =
+	GetAny<KN<double>*>( inittheparam.eval(stack) ) ; // do allocation 
+	
+	Param<R> param(x);
+	lgNRJ nrj1(stack,n,theparam,J,dJ,hJ);
+	if (!dJ) delta = new KN<double>(n); 
+	CLS ls( & nrj1,itMaxLine,delta);
+	REAL initialNrj = nrj1.getVal(param);
+	Optima<LS> *opt=0;
+	if(cas==1) 
+	  opt=new BFGS<LS>((CLS*)&ls,itMax,tol,verbose);
+	else if(cas==2)
+	  opt=new Newt<LS>((CLS*)&ls,itMax,tol,verbose);
+	else
+	  ErrorExec("lgalgo: Case no available Sorry internal bug",cas);
+	
+	
+	
+	param = opt->optimizer(param);
+	
+	REAL finalNrj = nrj1.getVal(param);
+	
+	
+	if(verbosity)
+	  cout <<endl<<"*** RESULTS SUMMARY ***"<<endl;
+	
+	if(verbosity>1) {
+	  cout <<"  The number of call to NRJ : "<< nrj1.Appel_Val() << endl;
+	  cout <<"  The number of call to gradient : "<< nrj1.Appel_Grad() << endl;
+	  cout <<"  The number of call to hessian : "<< nrj1.Appel_Hess() << endl; }
+	if(verbosity>2)
+	  {
+	    cout <<"Normalized residue : ";
+	    affiche(opt->allResidue());
+	  }
+	if(verbosity) {
+	  cout <<"  Initial NRJ value : " << initialNrj << endl;
+	  cout <<"  Final NRJ value : " << finalNrj << endl;}
+	delete opt;
+	
+	/// cout<<"The final optimized parameters : "<<param;
+	x=param;
+      }
+      catch (...)
+	{
+	  closetheparam.eval(stack); // clean memory 
+	  WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+	  if( delta) delete delta; 
+	  
+	  throw ;        
+	}
+      if( delta) delete delta; 
+      closetheparam.eval(stack); // clean memory 
+      WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+      
+      
+      return 0L; //SetAny<long>(0);  Modif FH  july 2005 
+    } 
+
+    
+    operator aType () const { return atype<long>();}         
+    
+  };
+
+
+  
+  E_F0 * code(const basicAC_F0 & args) const {
+    return new E_LCG(args,cas);}
+  
+  OptimAlgo(int c) :   OneOperator(atype<long>(),
+				   atype<Polymorphic*>(),
+				   atype<KN<R> *>()),cas(c){}
+  
+  OptimAlgo(int c,int cc) :   OneOperator(atype<long>(),
+					  atype<Polymorphic*>(),
+					  atype<Polymorphic*>(),
+					  atype<KN<R> *>()),cas(c){}
+  
+  OptimAlgo(int c,int cc,int ccc) :   OneOperator(atype<long>(),
+						  atype<Polymorphic*>(),
+						  atype<Polymorphic*>(),
+						  atype<Polymorphic*>(),
+						  atype<KN<R> *>()),cas(c){}
+   
+};
+
+
+//template<class R>
+
+basicAC_F0::name_and_type  OptimAlgo::E_LCG::name_param[]= {
+ {  "eps", &typeid(double)  },
+ { "nbiter",&typeid(long) },
+   { "nbiterline",&typeid(long)}
+};
+void init_algo();
+
+void init_algo()
+{
+  Global.Add("BFGS","(",new OptimAlgo(1,1));  //  j + dJ
+  Global.Add("Newton","(",new OptimAlgo(2,2,2));  //  j + dJ
+  Global.Add("Newtow","(",new OneOperatorCode<PrintErrorCompileNewtow>);  //  error 
+}
+
+//#include "InitFunct.hpp"
+//static addingInitFunct TheaddingInitFunct(-9,init_algo);
diff --git a/src/Carbon.r b/src/Carbon.r
new file mode 100755
index 0000000..855cd7b
--- /dev/null
+++ b/src/Carbon.r
@@ -0,0 +1,18 @@
+/*
+ *  Permit this Carbon application to launch on OS X
+ *
+ *  � 1997-2000 Metrowerks Corp.
+ *
+ *  Questions and comments to:
+ *       <mailto:support at metrowerks.com>
+ *       <http://www.metrowerks.com/>
+ */
+
+
+/*----------------------------carb � Carbon on OS X launch information --------------------------*/
+type 'carb' {
+};
+
+
+resource 'carb'(0) {
+};
\ No newline at end of file
diff --git a/src/Eigen/arpackff.hpp b/src/Eigen/arpackff.hpp
new file mode 100644
index 0000000..d9e8a67
--- /dev/null
+++ b/src/Eigen/arpackff.hpp
@@ -0,0 +1,439 @@
+/*
+  The freefem++ arpack interface without arpack ++ 
+  aprack++ is do  too much c++ error  with modern  compiler
+  but a by tanks  to arpack++ for the idea of this code
+   F. Hecht. 
+*/
+//  Change V[1] -> V[0]
+//  Change workev[1] -> workev[0]
+#ifndef ARPACKFF_HPP
+#define ARPACKFF_HPP
+#include "error.hpp"
+
+typedef int integer;
+typedef int logical;
+
+#define F77NAME(x) x ## _
+
+#define HIDDEN_HBW ,int,int,int
+#define HIDDEN_BW ,int,int
+#define HIDDEN_12 ,1,2
+#define HIDDEN_112 ,1,1,2
+
+
+extern "C"
+{
+  /*
+// debug "common" statement.
+
+  struct { 
+    integer logfil, ndigit, mgetv0;
+    integer msaupd, msaup2, msaitr, mseigt, msapps, msgets, mseupd;
+    integer mnaupd, mnaup2, mnaitr, mneigt, mnapps, mngets, mneupd;
+    integer mcaupd, mcaup2, mcaitr, mceigt, mcapps, mcgets, mceupd;
+  } F77NAME(debug);
+
+  // add FH pour lib dynamic so win 32 
+  struct { 
+    integer           nopx, nbx, nrorth, nitref, nrstrt;
+    float           tsaupd, tsaup2, tsaitr, tseigt, tsgets, tsapps, tsconv,
+      tnaupd, tnaup2, tnaitr, tneigh, tngets, tnapps, tnconv,
+      tcaupd, tcaup2, tcaitr, tceigh, tcgets, tcapps, tcconv,
+      tmvopx, tmvbx, tgetv0, titref, trvec;
+    
+    
+  } F77NAME(timing);
+
+*/
+// double precision symmetric routines.
+
+  void F77NAME(dsaupd)(integer *ido, char *bmat, integer *n, char *which,
+                       integer *nev, double *tol, double *resid,
+                       integer *ncv, double *V, integer *ldv,
+                       integer *iparam, integer *ipntr, double *workd,
+                       double *workl, integer *lworkl, integer *info HIDDEN_BW);
+
+  void F77NAME(dseupd)(logical *rvec, char *HowMny, logical *select,
+                       double *d, double *Z, integer *ldz,
+                       double *sigma, char *bmat, integer *n,
+                       char *which, integer *nev, double *tol,
+                       double *resid, integer *ncv, double *V,
+                       integer *ldv, integer *iparam, integer *ipntr,
+                       double *workd, double *workl,
+                       integer *lworkl, integer *info HIDDEN_HBW );
+
+// double precision nonsymmetric routines.
+
+  void F77NAME(dnaupd)(integer *ido, char *bmat, integer *n, char *which,
+                       integer *nev, double *tol, double *resid,
+                       integer *ncv, double *V, integer *ldv,
+                       integer *iparam, integer *ipntr, double *workd,
+                       double *workl, integer *lworkl, integer *info HIDDEN_BW);
+
+  void F77NAME(dneupd)(logical *rvec, char *HowMny, logical *select,
+                       double *dr, double *di, double *Z,
+                       integer *ldz, double *sigmar,
+                       double *sigmai, double *workev,
+                       char *bmat, integer *n, char *which,
+                       integer *nev, double *tol, double *resid,
+                       integer *ncv, double *V, integer *ldv,
+                       integer *iparam, integer *ipntr,
+                       double *workd, double *workl,
+                       integer *lworkl, integer *info HIDDEN_HBW);
+
+// single precision symmetric routines.
+
+  void F77NAME(ssaupd)(integer *ido, char *bmat, integer *n, char *which,
+                       integer *nev, float *tol, float *resid,
+                       integer *ncv, float *V, integer *ldv,
+                       integer *iparam, integer *ipntr, float *workd,
+                       float *workl, integer *lworkl, integer *info HIDDEN_BW);
+
+  void F77NAME(sseupd)(logical *rvec, char *HowMny, logical *select,
+                       float *d, float *Z, integer *ldz,
+                       float *sigma, char *bmat, integer *n,
+                       char *which, integer *nev, float *tol,
+                       float *resid, integer *ncv, float *V,
+                       integer *ldv, integer *iparam, integer *ipntr,
+                       float *workd, float *workl,
+                       integer *lworkl, integer *info HIDDEN_HBW);
+
+// single precision nonsymmetric routines.
+
+  void F77NAME(snaupd)(integer *ido, char *bmat, integer *n, char *which,
+                       integer *nev, float *tol, float *resid,
+                       integer *ncv, float *V, integer *ldv,
+                       integer *iparam, integer *ipntr, float *workd,
+                       float *workl, integer *lworkl, integer *info HIDDEN_BW);
+
+  void F77NAME(sneupd)(logical *rvec, char *HowMny, logical *select,
+                       float *dr, float *di, float *Z,
+                       integer *ldz, float *sigmar,
+                       float *sigmai, float *workev, char *bmat,
+                       integer *n, char *which, integer *nev,
+                       float *tol, float *resid, integer *ncv,
+                       float *V, integer *ldv, integer *iparam,
+                       integer *ipntr, float *workd, float *workl,
+                       integer *lworkl, integer *info HIDDEN_HBW);
+
+
+  void F77NAME(cnaupd)(integer *ido, char *bmat, integer *n, char *which,
+                       integer *nev, float *tol, complex<float> *resid,
+                       integer *ncv, complex<float> *V, integer *ldv,
+                       integer *iparam, integer *ipntr, complex<float> *workd,
+                       complex<float> *workl, integer *lworkl,
+                       float *rwork, integer *info HIDDEN_BW);
+
+  void F77NAME(cneupd)(logical *rvec, char *HowMny, logical *select,
+                       complex<float> *d, complex<float> *Z, integer *ldz,
+                       complex<float> *sigma, complex<float> *workev,
+                       char *bmat, integer *n, char *which, integer *nev,
+                       float *tol, complex<float> *resid, integer *ncv,
+                       complex<float> *V, integer *ldv, integer *iparam,
+                       integer *ipntr, complex<float> *workd,
+                       complex<float> *workl, integer *lworkl,
+                       float *rwork, integer *info HIDDEN_HBW);
+
+// double precision complex routines.
+
+  void F77NAME(znaupd)(integer *ido, char *bmat, integer *n, char *which,
+                       integer *nev, double *tol, complex<double> *resid,
+                       integer *ncv, complex<double> *V, integer *ldv,
+                       integer *iparam, integer *ipntr, complex<double> *workd,
+                       complex<double> *workl, integer *lworkl,
+                       double *rwork, integer *info HIDDEN_BW);
+
+  void F77NAME(zneupd)(logical *rvec, char *HowMny, logical *select,
+                       complex<double> *d, complex<double> *Z, integer *ldz,
+                       complex<double> *sigma, complex<double> *workev,
+                       char *bmat, integer *n, char *which, integer *nev,
+                       double *tol, complex<double> *resid, integer *ncv,
+                       complex<double> *V, integer *ldv, integer *iparam,
+                       integer *ipntr, complex<double> *workd,
+                       complex<double> *workl, integer *lworkl,
+                       double *rwork, integer *info HIDDEN_HBW);
+
+}
+
+inline void saupp(int& ido, char bmat, int n, char* which, int nev,
+                  double& tol, double resid[], int ncv, double V[],
+                  int ldv, int iparam[], int ipntr[], double workd[],
+                  double workl[], int lworkl, int& info)
+
+{
+
+  F77NAME(dsaupd)(&ido, &bmat, &n, which, &nev, &tol, resid, &ncv,
+                  &V[0], &ldv, &iparam[1], &ipntr[1], &workd[1], &workl[1],
+                  &lworkl, &info HIDDEN_12);
+
+} // saupp (double).
+
+inline void saupp(int& ido, char bmat, int n, char* which, int nev,
+                  float& tol, float resid[], int ncv, float V[],
+                  int ldv, int iparam[], int ipntr[], float workd[],
+                  float workl[], int lworkl, int& info)
+
+{
+
+  F77NAME(ssaupd)(&ido, &bmat, &n, which, &nev, &tol, resid, &ncv,
+                  &V[0], &ldv, &iparam[1], &ipntr[1], &workd[1], &workl[1],
+                  &lworkl, &info HIDDEN_12);
+
+} // saupp (float).
+
+
+inline void seupp(bool rvec, char HowMny, double d[], double Z[],
+                  int ldz, double sigma, char bmat, int n,
+                  char* which, int nev, double tol, double resid[],
+                  int ncv, double V[], int ldv, int iparam[],
+                  int ipntr[], double workd[], double workl[],
+                  int lworkl, int& info)
+
+{
+
+  int      irvec;
+  logical* iselect;
+  double*  iZ;
+
+  irvec   = (int) rvec;
+  iselect = new logical[ncv];
+  iZ = (Z == NULL) ? &V[0] : Z;
+
+  F77NAME(dseupd)(&irvec, &HowMny, iselect, d, iZ, &ldz, &sigma, &bmat,
+                  &n, which, &nev, &tol, resid, &ncv, &V[0], &ldv, &iparam[1],
+                  &ipntr[1], &workd[1], &workl[1], &lworkl, &info HIDDEN_112);
+
+  delete[] iselect;
+
+} // seupp (double).
+inline void seupp(bool rvec, char HowMny, float d[], float Z[],
+                  int ldz, float sigma, char bmat, int n,
+                  char* which, int nev, float tol, float resid[],
+                  int ncv, float V[], int ldv, int iparam[],
+                  int ipntr[], float workd[], float workl[],
+                  int lworkl, int& info)
+{
+
+  int      irvec;
+  logical* iselect;
+  float*   iZ;
+
+  irvec   = (int) rvec;
+  iselect = new logical[ncv];
+  iZ = (Z == NULL) ? &V[0] : Z;
+
+  F77NAME(sseupd)(&irvec, &HowMny, iselect, d, iZ, &ldz, &sigma, &bmat,
+                  &n, which, &nev, &tol, resid, &ncv, &V[0], &ldv, &iparam[1],
+                  &ipntr[1], &workd[1], &workl[1], &lworkl, &info HIDDEN_112 );
+
+  delete[] iselect;
+
+} // seupp (float).
+
+inline void naupp(int& ido, char bmat, int n, char* which, int nev,
+                  double& tol, double resid[], int ncv, double V[],
+                  int ldv, int iparam[], int ipntr[], double workd[],
+                  double workl[], int lworkl, int& info)
+{
+
+  F77NAME(dnaupd)(&ido, &bmat, &n, which, &nev, &tol, resid, &ncv,
+                  &V[0], &ldv, &iparam[1], &ipntr[1], &workd[1], &workl[1],
+                  &lworkl, &info HIDDEN_12);
+
+} // naupp (double).
+
+inline void naupp(int& ido, char bmat, int n, char* which, int nev,
+                  float& tol, float resid[], int ncv, float V[],
+                  int ldv, int iparam[], int ipntr[], float workd[],
+                  float workl[], int lworkl, int& info)
+
+{
+
+  F77NAME(snaupd)(&ido, &bmat, &n, which, &nev, &tol, resid, &ncv,
+                  &V[0], &ldv, &iparam[1], &ipntr[1], &workd[1], &workl[1],
+                  &lworkl, &info HIDDEN_12 );
+
+} // naupp (float).
+
+
+
+inline void caupp(int& ido, char bmat, int n, char* which, int nev,
+                  double& tol, complex<double> resid[], int ncv,
+                  complex<double> V[], int ldv, int iparam[], int ipntr[],
+                  complex<double> workd[], complex<double> workl[],
+                  int lworkl, double rwork[], int& info)
+
+{
+
+  F77NAME(znaupd)(&ido, &bmat, &n, which, &nev, &tol, resid, &ncv,
+                  &V[0], &ldv, &iparam[1], &ipntr[1], &workd[1],
+                  &workl[1], &lworkl, &rwork[1], &info HIDDEN_12 );
+
+} // caupp 
+
+inline void caupp(int& ido, char bmat, int n, char* which, int nev,
+                  float& tol, complex<float> resid[], int ncv,
+                  complex<float> V[], int ldv, int iparam[], int ipntr[],
+                  complex<float> workd[], complex<float> workl[],
+                  int lworkl, float rwork[], int& info)
+{
+
+  F77NAME(cnaupd)(&ido, &bmat, &n, which, &nev, &tol, resid, &ncv,
+                  &V[0], &ldv, &iparam[1], &ipntr[1], &workd[1],
+                  &workl[1], &lworkl, &rwork[1], &info HIDDEN_12);
+
+} // caupp 
+
+inline void ceupp(bool rvec, char HowMny, complex<double> d[],
+		 complex<double> Z[], int ldz, complex<double> sigma,
+		 complex<double> workev[], char bmat, int n, char* which,
+		 int nev, double tol, complex<double> resid[], int ncv,
+		 complex<double> V[], int ldv, int iparam[], int ipntr[],
+		 complex<double> workd[], complex<double> workl[],
+		 int lworkl, double rwork[], int& info)
+{
+
+  int                irvec;
+  logical*           iselect;
+  complex<double>* iZ;
+
+  irvec   = (int) rvec;
+  iselect = new logical[ncv];
+  iZ = (Z == NULL) ? &V[0] : Z;
+
+  F77NAME(zneupd)(&irvec, &HowMny, iselect, d, iZ, &ldz, &sigma,
+                  &workev[0], &bmat, &n, which, &nev, &tol, resid,
+                  &ncv, &V[0], &ldv, &iparam[1], &ipntr[1],
+                  &workd[1], &workl[1], &lworkl, &rwork[1], &info HIDDEN_112);
+
+  delete[] iselect;
+
+} // ceupp (complex<double>).
+
+inline void ceupp(bool rvec, char HowMny, complex<float> d[],
+                  complex<float> Z[], int ldz, complex<float> sigma,
+                  complex<float> workev[], char bmat, int n, char* which,
+                  int nev, float tol, complex<float> resid[], int ncv,
+                  complex<float> V[], int ldv, int iparam[], int ipntr[],
+                  complex<float> workd[], complex<float> workl[],
+                  int lworkl, float rwork[], int& info)
+
+{
+
+  int               irvec;
+  logical*          iselect;
+  complex<float>* iZ;
+
+  irvec   = (int) rvec;
+  iselect = new logical[ncv];
+  iZ = (Z == NULL) ? &V[0] : Z;
+
+  F77NAME(cneupd)(&irvec, &HowMny, iselect, d, iZ, &ldz, &sigma,
+                  &workev[0], &bmat, &n, which, &nev, &tol, resid,
+                  &ncv, &V[0], &ldv, &iparam[1], &ipntr[1],
+                  &workd[1], &workl[1], &lworkl, &rwork[1], &info HIDDEN_112);
+
+  delete[] iselect;
+
+} // ceupp (complex<float>).
+
+inline void neupp(bool rvec, char HowMny, double dr[],
+		 double di[], double Z[], int ldz, double sigmar,
+		 double sigmai, double workv[], char bmat, int n,
+		 char* which, int nev, double tol, double resid[],
+		 int ncv, double V[], int ldv, int iparam[],
+		 int ipntr[], double workd[], double workl[],
+		 int lworkl, int& info)
+{
+
+  int      irvec;
+  logical* iselect;
+  double*  iZ;
+
+  irvec   = (int) rvec;
+  iselect = new logical[ncv];
+  iZ = (Z == NULL) ? &V[0] : Z;
+
+  F77NAME(dneupd)(&irvec, &HowMny, iselect, dr, di, iZ, &ldz, &sigmar,
+                  &sigmai, &workv[1], &bmat, &n, which, &nev, &tol,
+                  resid, &ncv, &V[0], &ldv, &iparam[1], &ipntr[1],
+                  &workd[1], &workl[1], &lworkl, &info HIDDEN_112);
+
+  delete[] iselect;
+
+} // neupp (double).                                                                                  
+
+inline void neupp(bool rvec, char HowMny, float dr[],
+                  float di[], float Z[], int ldz, float sigmar,
+                  float sigmai, float workv[], char bmat, int n,
+                  char* which, int nev, float tol, float resid[],
+                  int ncv, float V[], int ldv, int iparam[],
+                  int ipntr[], float workd[], float workl[],
+                  int lworkl, int& info)
+
+{
+
+  int      irvec;
+  logical* iselect;
+  float*   iZ;
+
+  irvec   = (int) rvec;
+  iselect = new logical[ncv];
+  iZ = (Z == NULL) ? &V[0] : Z;
+
+  F77NAME(sneupd)(&irvec, &HowMny, iselect, dr, di, iZ, &ldz, &sigmar,
+                  &sigmai, &workv[1], &bmat, &n, which, &nev, &tol,
+                  resid, &ncv, &V[0], &ldv, &iparam[1], &ipntr[1],
+                  &workd[1], &workl[1], &lworkl, &info HIDDEN_112);
+
+  delete[] iselect;
+
+} // neupp (float).  
+
+inline void sauppError(int info)
+{
+  if(info<0)
+    cerr << " erreur arpack sauppError" <<info <<  endl;
+  switch (info) {
+  case     0:
+    return;
+  case    -8:
+    throw ErrorExec("lapack error [sd]aupp ",info);
+  case    -9:
+    throw ErrorExec("arpack error START_RESID_ZERO  [sd]aupp ",info);
+  case -9999:
+    throw ErrorExec("arpack error ARNOLDI_NOT_BUILD  [sd]aupp ",info);
+  case     1:
+    throw ErrorExec("arpack error MAX_ITERATIONS  [sd]aupp ",info);
+    return;
+  case     3:
+    throw ErrorExec("arpack error NO_SHIFTS_APPLIED  [sd]aupp ",info);
+    return;
+  default   :
+    throw ErrorExec("arpack error AUPP_ERROR  [sd]aupp ",info);
+  }
+
+}
+
+inline void seuppError(int info)
+{
+  if(info<0)
+    cerr << " erreur arpack seuppError" <<info <<  endl;
+  switch (info) {
+  case   0:
+    return;
+  case  -8:
+  case  -9:
+    throw ErrorExec("lapack LAPACK_ERROR [sd]eupp ",info);
+  case -14:
+    throw ErrorExec("lapack NOT_ACCURATE_EIG [sd]eupp ",info);
+  case   1:
+    throw ErrorExec("lapack REORDERING_ERROR [sd]eupp ",info);
+  default :
+    throw ErrorExec("lapack error [sd]eupp ",info);
+  }
+
+} // EuppError.
+
+
+#endif // ARPACKFF_HPP
diff --git a/src/Eigen/eigenvalue.cpp b/src/Eigen/eigenvalue.cpp
new file mode 100644
index 0000000..0967293
--- /dev/null
+++ b/src/Eigen/eigenvalue.cpp
@@ -0,0 +1,1053 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <fstream>
+#include <iostream>
+#include <cassert>
+#include <algorithm>
+#include <complex>
+
+
+
+using namespace std;
+#include "error.hpp"
+#include "arpackff.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "Mesh3dn.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+//#include "ffstack.hpp"
+extern Block *currentblock;
+
+typedef double R;
+static  bool dddd=false;
+template<class K>
+void Show(int ido,KN_<K> w,const char *cmm)
+{
+  cout << cmm << ido << " max " << w.max() << " min  " << w.min() << " sum  =" 
+       << w.sum()  << endl;
+}
+
+
+ template<class R>
+ class FuncMat: public VirtualMatrice<R> { public:
+ //    typedef double K;
+typedef KN<R> Kn;
+     typedef KN_<R> Kn_;
+     
+ Stack stack;
+     int cas;
+ mutable  Kn x;
+ C_F0 c_x;
+ Kn *b;
+ Expression  mat1,mat;
+ typedef  typename VirtualMatrice<R>::plusAx plusAx;
+ FuncMat(int kas,int n,Stack stk,const OneOperator * op,Kn *bb=0)
+ : VirtualMatrice<R>(n),
+ stack(stk),cas(kas),
+ x(n),c_x(CPValue(x)),b(bb),
+ mat1(op->code(basicAC_F0_wa(c_x))),
+ mat( CastTo<Kn_>(C_F0(mat1,(aType)*op))  ) {
+
+ }
+ FuncMat() { if(mat1!=mat) delete mat; delete mat1; delete c_x.LeftValue();}
+ void addMatMul(const  Kn_  & xx, Kn_ & Ax) const {
+  //   cout <<" addMatMul " <<xx.N()<< " " << Ax.N() << " " << cas << endl;
+ ffassert(xx.N()==Ax.N() && cas == 1);
+ x =xx;
+ Ax  += GetAny<Kn_>((*mat)(stack));
+ if(b && &Ax!=b) Ax += *b; // Ax -b => add b (not in cas of init. b c.a.d  &Ax == b
+ WhereStackOfPtr2Free(stack)->clean(); //  add dec 2008
+ }
+     
+ void Solve( KN_<R> & Ax  ,const KN_<R> & xx) const
+     {
+         ffassert(xx.N()==Ax.N() && cas == -1);
+         x =xx;
+         Ax  = GetAny<Kn_>((*mat)(stack));
+         if(b && &Ax!=b) Ax += *b; // Ax -b => add b (not in cas of init. b c.a.d  &Ax == b
+         WhereStackOfPtr2Free(stack)->clean(); //  add dec 2008
+         
+     }
+ plusAx operator*(const Kn &  x) const {return plusAx(this,x);}
+ virtual bool ChecknbLine(int n) const { return true;}
+ virtual bool ChecknbColumn(int m) const { return true;}
+ 
+ };
+ 
+
+
+
+template<class K,class Mat>
+void  DoIdoAction(int ido,int mode,KN_<K> &xx,KN_<K> &yy,KN_<K> &zz,KN_<K> &work,Mat &OP1,Mat &B)
+{
+  if(mode>2) // inverse mode 
+    switch (ido) {
+    case -1: //y <--- OP*x = inv[A-SIGMA*M]*M*x   
+      if(dddd) Show(ido,xx,"  <- (xx) ");
+      OP1.Solve(yy,work=B*xx);
+      if(dddd) Show(ido,yy,"  -> (yy) ");
+      break;
+    case  1://  y <-- OP*x = inv[A-sigma*M]*z
+      if(dddd) Show(ido,zz,"  <- (zz) ");
+      OP1.Solve(yy,zz);
+      if(dddd) Show(ido,yy,"  -> (yy) ");
+      break;
+    case  2: //  y <--- M*x 
+      if(dddd) Show(ido,xx,"  <- (xx) ");
+      yy = B*xx;
+      if(dddd) Show(ido,yy,"  -> (yy) ");
+      break;
+    default :
+      ffassert(0);
+    }
+  else // direct mode 
+    switch (ido)
+      {
+      case -1: // y <--- OP*x = inv[M]*A*x
+      case  1: 
+	if(mode== 1)  // M = Id
+	  yy=OP1*xx;
+	else
+	  B.Solve(yy,work=OP1*xx);
+	break;
+      case 2: //  y <--- M*x. // not use mode = 1
+	yy = B*xx;
+	break;
+      default :
+	ffassert(0);  
+      }
+}
+class EigenValue : public OneOperator
+{ public:
+  typedef R K;
+  typedef KN<K> Kn;
+  typedef KN_<K> Kn_;
+  const int cas;
+  class E_EV: public E_F0mps { public:
+      const int cas;
+    
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =12;
+    Expression nargs[n_name_param];
+    Expression expOP1,expB,expn;
+    const OneOperator * codeOP1, *codeB;
+    template<class T>
+    T arg(int i,Stack stack,const T & a) const{ return nargs[i] ? GetAny<T>( (*nargs[i])(stack) ): a;}
+    E_EV(const basicAC_F0 & args,int cc) :
+    cas(cc)
+    {
+      // OP1 = (A-sigma*B)        
+      //                int nbj= args.size()-1;
+      args.SetNameParam(n_name_param,name_param,nargs);
+      if( cas==1 || cas ==2)
+      {
+          expn=to< long>(args[0]);
+          expOP1=0;
+          expB=0;
+          const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(args[1].LeftValue());
+          ffassert(op);
+          codeOP1 = op->Find("(",ArrayOfaType(atype<Kn* >(),false));
+          if( cas== 2)
+          {
+              const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(args[2].LeftValue());
+              ffassert(op);
+              codeB = op->Find("(",ArrayOfaType(atype<Kn* >(),false));
+              
+          }
+      }
+      else
+      {
+      expOP1=to< Matrice_Creuse<K> *>(args[0]);
+      expB=to< Matrice_Creuse<K> *>(args[1]);
+      codeOP1=0;
+      codeB=0;
+      expn=0;
+      }
+    }
+    
+    AnyType operator()(Stack stack)  const;
+    operator aType () const { return atype<long>();}         
+    
+  };
+  
+  E_F0 * code(const basicAC_F0 & args) const {
+    return new E_EV(args,cas);}
+  
+  EigenValue() :
+    OneOperator(atype<long>(),
+		atype<Matrice_Creuse<K> *>(),
+		atype<Matrice_Creuse<K> *>()),
+    cas(0){}
+    
+  EigenValue(int ,int ) :
+    OneOperator(atype<long>(),atype<long>(),
+		atype<Polymorphic *>(),
+		atype<Polymorphic *>()),
+    cas(2){}
+    EigenValue(int  ) :
+    OneOperator(atype<long>(),atype<long>(),
+		atype<Polymorphic *>()),
+    cas(1){}
+    
+};
+
+class EigenValueC : public OneOperator
+{ public:
+    typedef Complex K;
+    typedef double R;
+    typedef KN<K> Kn;
+    typedef KN_<K> Kn_;
+    const int cas;
+    class E_EV: public E_F0mps { public:
+        const int cas;
+        
+        static basicAC_F0::name_and_type name_param[] ;
+        static const int n_name_param =10;
+        Expression nargs[n_name_param];
+        Expression expOP1,expB,expn;
+        const OneOperator * codeOP1, *codeB;
+        template<class T>
+        T arg(int i,Stack stack,const T & a) const{ return nargs[i] ? GetAny<T>( (*nargs[i])(stack) ): a;}
+        E_EV(const basicAC_F0 & args,int cc) :
+        cas(cc)
+        {
+            // OP1 = (A-sigma*B)
+            //                int nbj= args.size()-1;
+            args.SetNameParam(n_name_param,name_param,nargs);
+            if( cas==1 || cas ==2)
+            {
+                expn=to< long>(args[0]);
+                expOP1=0;
+                expB=0;
+                const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(args[1].LeftValue());
+                ffassert(op);
+                codeOP1 = op->Find("(",ArrayOfaType(atype<Kn* >(),false));
+                if( cas== 2)
+                {
+                    const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(args[2].LeftValue());
+                    ffassert(op);
+                    codeB = op->Find("(",ArrayOfaType(atype<Kn* >(),false));
+                }
+            }
+            else
+            {
+                expOP1=to< Matrice_Creuse<K> *>(args[0]);
+                expB=to< Matrice_Creuse<K> *>(args[1]);
+                codeOP1=0;
+                codeB=0;
+                expn=0;
+            }
+        }
+        
+        AnyType operator()(Stack stack)  const;
+        operator aType () const { return atype<long>();}
+        
+    };
+    
+    E_F0 * code(const basicAC_F0 & args) const {
+        return new E_EV(args,cas);}
+    
+    EigenValueC() :
+    OneOperator(atype<long>(),
+		atype<Matrice_Creuse<K> *>(),
+		atype<Matrice_Creuse<K> *>()),
+    cas(0){}
+    
+    EigenValueC(int ,int ) :
+    OneOperator(atype<long>(),atype<long>(),
+		atype<Polymorphic *>(),
+		atype<Polymorphic *>()),
+    cas(2){}
+    EigenValueC(int  ) :
+    OneOperator(atype<long>(),atype<long>(),
+		atype<Polymorphic *>()),
+    cas(1){}
+    
+};
+
+
+
+/*
+class EigenValueC : public OneOperator
+{ public:
+  typedef Complex K;
+  typedef double R;
+  typedef KN<K> Kn;
+  typedef KN_<K> Kn_;
+  const int cas;
+  class E_EV: public E_F0mps { public:
+      const int cas;
+    
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =10;
+    Expression nargs[n_name_param];
+    Expression expOP1,expB;
+    template<class T>
+    T arg(int i,Stack stack,const T & a) const{ return nargs[i] ? GetAny<T>( (*nargs[i])(stack) ): a;}
+    E_EV(const basicAC_F0 & args,int cc) :
+      cas(cc)
+    {
+      // OP1 = (A-sigma*B)        
+      //                int nbj= args.size()-1;
+      args.SetNameParam(n_name_param,name_param,nargs);
+      expOP1=to< Matrice_Creuse<K> *>(args[0]);
+      expB=to< Matrice_Creuse<K> *>(args[1]);
+      
+    }
+    
+    AnyType operator()(Stack stack)  const;
+    operator aType () const { return atype<long>();}         
+    
+  };
+  
+  E_F0 * code(const basicAC_F0 & args) const {
+    return new E_EV(args,cas);}
+  
+  EigenValueC(int c) :   
+    OneOperator(atype<long>(),
+		atype<Matrice_Creuse<K> *>(),
+		atype<Matrice_Creuse<K> *>()),
+    cas(c){}
+  
+};
+*/
+basicAC_F0::name_and_type  EigenValue::E_EV::name_param[]= {
+  {   "tol", &typeid(double)  },
+  {   "nev",&typeid(long) },
+  {   "sym",&typeid(bool)},
+  {   "sigma",&typeid(double)},
+  {   "value",&typeid(KN<double> *)},
+  {   "vector",&typeid(FEbaseArrayKn<double> *) }, // pferarray
+  {   "ncv",&typeid(long) }, // the number of Arnoldi vectors generated 
+  {   "maxit",&typeid(long)}, // the maximum number of Arnoldi iterations 
+  {   "ivalue",&typeid(KN<double> *)},
+  {   "rawvector",&typeid(KNM<double> *) },
+  {   "resid",&typeid(KN<double> *) },
+  {   "mode",&typeid(long) } // 12 ieme
+  
+  
+};
+
+basicAC_F0::name_and_type  EigenValueC::E_EV::name_param[]= {
+  {  "tol", &typeid(double)  },
+  {  "nev",&typeid(long) },
+  {  "sigma",&typeid(K)},
+  {  "value",&typeid(KN<Complex> *)},
+  {  "vector",&typeid(FEbaseArrayKn<Complex> *) }, // pfecarray
+  {  "ncv",&typeid(long) }, // the number of Arnoldi vectors generated 
+  {  "maxit",&typeid(long)}, // the maximum number of Arnoldi iterations 
+  {  "rawvector",&typeid(KNM<Complex> *) }, 
+  {  "resid",&typeid(KN<Complex> *)},
+  {   "mode",&typeid(long) } // 10 ieme   
+  
+};
+
+
+AnyType EigenValue::E_EV::operator()(Stack stack)  const 
+{
+  dddd = (verbosity>=200);
+  double tol=1e-6;
+  long nconv=0; 
+  long nbev=1;
+  bool sym=false;
+  long ncv =0;  // the number of Arnoldi vectors generated 
+  long maxit=0;  // the maximum number of Arnoldi iterations 
+  double sigma=0;
+  int mode = 3; //  
+  KN<double> * evalue=0;
+  KN<double> * evaluei=0;
+  KN<double> * resid=0;
+  KNM<double> * rawvector=0;
+  //double ws,vs;           // for debugging FH ++++++++++
+ // pferarray  evector2;
+  FEbaseArrayKn<double> *   evector=0;// change mai 2009
+  tol=arg<double>(0,stack,0);
+  nbev=arg<long>(1,stack,10);
+  sym=arg<bool>(2,stack,false);
+  sigma=arg<double>(3,stack,0.0);
+  evalue=arg<KN<double> *>(4,stack,0);
+  evector =arg<FEbaseArrayKn<double> *>(5,stack,0); 
+  ncv= arg<long>(6,stack,0);
+  maxit= arg<long>(7,stack,0);
+  evaluei=arg<KN<double> *>(8,stack,0);
+  rawvector=arg<KNM<double> *>(9,stack,0);
+  resid=arg<KN<double> *>(10,stack,0);
+  mode = arg<long>(11,stack,3);
+
+ 
+ // evector=evector2.first;
+    
+    Matrice_Creuse<K> *pOP1=0, *pB=0;
+   if(expOP1)
+   pOP1 =  GetAny<Matrice_Creuse<K> *>((*expOP1)(stack));
+   if(expB)
+   pB =  GetAny<Matrice_Creuse<K> *>((*expB)(stack));
+  double * residptr=resid? (double*) *resid : 0;
+  cout << " residptr = " << residptr <<endl;
+  long  n=0;
+  if( pOP1)
+      n =pOP1->A->n;
+  else {
+      ffassert(expn);
+     n = GetAny<long>((*expn)(stack));
+  }
+  
+  if(evalue) nbev=Max( (long)evalue->N(),nbev);
+  
+  const VirtualMatrice<K> * ptOP1, *ptB;
+   if(pOP1)
+     ptOP1= & (const VirtualMatrice<K>&)(pOP1->A);
+   if(pB)
+     ptB = &  (const VirtualMatrice<K>&)(pB->A);
+ 
+  FuncMat<R> *pcOP1=0,  *pcB=0;
+  if(codeOP1)
+   ptOP1=pcOP1= new FuncMat<K>(-1,n,stack,codeOP1);
+  if(codeB)
+   ptB=pcB= new FuncMat<K>(1,n,stack,codeB);
+  MatriceIdentite<K>  Id(n);
+    
+  if(!ptB) ptB = &Id;
+  const VirtualMatrice<K> &OP1= *ptOP1, &B=*ptB;
+  if(sym)
+    {
+      nbev=min(n-1,nbev);
+      if(!ncv) 	ncv = min(nbev*2+1,n);
+    }
+  else
+    {
+      nbev=min(nbev,n-2);
+      if(!ncv)     ncv = nbev*2+1;        
+    }
+  ncv = max(nbev+2,ncv);
+  ncv = min(ncv,n);
+
+  if(!maxit)  maxit = 100*nbev;
+    
+    const char *serr[10];
+    int err=0;
+    if( ! (nbev < n) )
+	serr[err++]="  Number of eigenvalues of OP to be computed nev <= n ";
+    
+    if( (mode < 1 || mode > 5) && sym) 
+        serr[err++]="  the mode = 1 ,2 ,3, 4, 5  ";
+    if( (mode < 1 || mode > 4) && !sym) 
+        serr[err++]="  the mode = 1 ,2 ,3, 4  ";
+    // 2 <= NCV-NEV and NCV <= N
+    
+    if( ! (   ncv <= n) && sym ) 
+	serr[err++]="   ( ncv <= n) (symetric  case) ";
+    if( ! ( (   ncv <= n) && 2 <= (ncv-nbev ) ) && !sym )
+	serr[err++]="   ( ncv <= n)  2 <= (ncv-nev ) ( no-symetric  case) ";
+    
+    if (n != OP1.M)
+	serr[err++]=" the first matrix in EigneValue is not square.";
+    if (n != B.N )
+	serr[err++]="Sorry the row's number of the secand matrix in EigneValue is wrong.";
+    if (n != B.M )
+	serr[err++]="Sorry the colum's number of the secand matrix in EigneValue is wrong.";
+	
+   if(verbosity)
+   {
+    if(sym)
+      cout << "Real symmetric eigenvalue problem: A*x - B*x*lambda" << endl;
+    else
+      cout << "Real non symmetric eigenvalue problem: A*x - B*x*lambda" << endl;
+   }
+        
+    if(verbosity>9 || err)
+	cout << "    n " << n << ", nev "<< nbev << ", tol =" << tol << ", maxit =" << maxit 
+	<< ", ncv = " <<ncv << ", mode = " << mode << endl;
+    if(err) 
+      {
+	  cerr << " list of the error " << endl;
+	  for (int i=0;i<err;++i)
+	      cerr << "\n-  " <<  serr[i] << endl;
+	  ExecError("Fatal Error in EigenValue (real) ");
+      }
+    
+  KN<K> work(n);
+
+  if(sym)
+    {
+      int ido=0;
+      char bmat= mode == 1 ? 'I' : 'G';
+      char which[3]= "LM";	// larger value
+      //      if(mode >2) which[0] ='S'; // smaller value
+      int ishift=1; // Auto Shift true by default
+      int iparam[12]= {0,ishift,0,(int)maxit,1,(int) nconv,0,mode,0,0,0,0};
+      int ipntr[12]={ 0,0,0, 0,0,0,  0,0,0, 0,0,0 };
+      KN<double> workd(3*n+1);
+      int lworkl = ncv*(ncv+9);
+      KN<double> workl(lworkl+1);
+      KN<double> vp(ncv*n+1);
+
+      int info= (residptr !=0);
+      KN<double> vresid(residptr? 1: n);
+      if(!residptr) residptr=&vresid[0];
+
+      while (1) {
+
+	saupp(ido,bmat,n,which,nbev,tol,  residptr,  ncv,  vp, n,
+	      iparam,  ipntr,  workd,   workl,  lworkl, info);
+	if(verbosity>99) 
+	  cout << "    saupp ido: " << ido << " info : " << info << endl;
+	if(info<0) {cerr << "  -- err arpack info = " << info << endl;}  
+	sauppError(info);
+
+	if(ido==99) break;
+
+	KN_<double>  xx(&workd[ipntr[1]],n);
+	KN_<double>  yy(&workd[ipntr[2]],n);
+	KN_<double>  zz(&workd[ipntr[3]],n);
+	DoIdoAction(ido,mode,xx,yy,zz,work,OP1,B);
+      }
+
+      nconv = iparam[5];
+      if(nconv==0) cerr << "  -- Strange: no eigens values ??? " << endl;
+      // Finding eigenvalues and eigenvectors.
+      if(nconv)
+	{
+	  int newdim = nbev;
+	  if(nconv>nbev) {
+	    cerr << "WARNING: nconv(saupp) > nbev: " << nconv << " > " << nbev << endl;
+	    newdim = nconv;
+	  }
+	  KN<double> evr(newdim);
+	  KNM<double> Z(n,newdim);
+	  int ldz=n;
+	  char HowMny ='A';
+	  int rvec=1;
+	  
+	  seupp( rvec, HowMny, evr,  Z, ldz, sigma, bmat, n,
+		 which,  nbev,  tol,  residptr, ncv, vp,  n, iparam,ipntr,  workd, workl,lworkl,info);
+	  
+	  if(verbosity>5)
+	    {
+	      
+	      cout << "Dimension of the system            : " << n              << endl;
+	      cout << "Number of 'requested' eigenvalues  : " << nbev  << endl;
+	      cout << "Number of 'converged' eigenvalues  : " << nconv          << endl;
+	      cout << "Number of Arnoldi vectors generated: " << ncv  << endl;
+	      cout << "Number of iterations taken         : " << iparam[3]  << endl;
+	      cout << endl;
+	      
+	      //if (prob.EigenvaluesFound()) {
+	      cout << "Eigenvalues:" << endl;
+	      for (int i=0; i<nconv; i++) {
+		cout << "  lambda[" << (i+1) << "]: " << evr(i) << endl;
+		  KN_<K> vi(Z(':',i)) ;
+		  if(verbosity>99)
+		    cout <<" Eigenvector: :" << vi << endl;
+	      }
+	      cout << endl;
+	    }
+	  
+	  if (evalue)
+	    {
+	      KN<double> & ev(*evalue);
+	      int m = Min(nconv,ev.N());
+	      for(int i=0;i<m;i++)
+		ev[i]=evr(i);
+	      }
+	  if(rawvector)
+	    {
+	      int m = Min(nconv,rawvector->M());
+	      ffassert(rawvector->N()==n);
+	      for(int i=0;i<m;i++)
+		{
+		  KN_<K> vi(Z(':',i)) ;
+		  
+		  //   cout << " ------ EV--raw " << vi.min() << " " << vi.max() << endl;
+		  (*rawvector)(':',i)=vi;
+		}
+	      
+	    }
+	  
+	  if (evector)
+	    {
+	      FEbaseArrayKn<K> & ev(*evector);
+	      int m = Min(nconv,(long) ev.N);
+	      for(int i=0;i<m;i++)
+		{
+		  //KN<K> & xx= *(ev(i));
+		    //if(xx.pVh->NbDoF != n)
+		    //ExecError("Wrong Type size of FEspace to store the eigen vector ");
+		    // if (xx.pVh != pOP1->pUh) 
+		    //    ExecError("Wrong Type of FEspace to store the eigen vector ");
+		    //xx.Vh = pOP1->Uh;
+		    KN_<K> vi(Z(':',i)) ;
+		    ev.set(i,vi);
+		  
+		}
+	    }
+	}
+    }
+  else 
+      { 
+	// cas non symetrique ,
+        // Finding an Arnoldi basis.                                                                                                               
+        //int mode=3; //  Shift invert                                                                                                               
+        int ido=0;
+        char bmat='G';
+        char which[]="LM";
+        int ishift=1; // Auto Shift true by default                                                                                                
+        int iparam[12]= {0,ishift,0,(int)maxit,1,(int)nconv,0,mode,0,0,0,0};
+        int ipntr[15]={ 0,0,0, 0,0,0,  0,0,0, 0,0,0 ,0,0,0};
+        KN<double> workd(3*n+1);
+        int lworkl = 3*ncv*(ncv+2);
+	KN<double> workl(lworkl+1);
+        KN<double> vp(ncv*n+1);
+        int info= (residptr !=0);
+	KN<double> vresid(residptr? 1: n);
+	if(!residptr) residptr=&vresid[0];
+	if(verbosity>9)
+	  cout << " n " << n << " nbev "<< nbev << " tol =" << tol << " maxit =" << maxit << " ncv = " <<ncv << endl;	
+	
+	while (1)
+	{
+	  naupp(ido,bmat,n,which,nbev,tol,  residptr,  ncv,  vp, n,
+		iparam,  ipntr,  workd,   workl,  lworkl, info);
+	  if(verbosity>99) {cout << "    naupp ido: " << ido << " info : " << info << endl;}
+	  if(info<0) {cerr << "  -- err arpack info = " << info << endl;}  
+	  sauppError(info);
+	  if(ido==99) break;
+	  KN_<double>  xx(&workd[ipntr[1]],n);
+	  KN_<double>  yy(&workd[ipntr[2]],n);
+	  KN_<double>  zz(&workd[ipntr[3]],n);
+	  DoIdoAction(ido,mode,xx,yy,zz,work,OP1,B);
+	}
+
+	nconv = iparam[5];
+	if(nconv)
+	  {
+	    int newdim = nbev;
+	    if(nconv>nbev) {
+	      cerr << "WARNING: nconv(naupp) > nbev: " << nconv << " > " << nbev << endl;
+	      newdim = nconv;
+	    }
+	    KN<double> evr(newdim+1), evi(newdim+1);
+	    KNM<double> Z(n,newdim+1);
+	    KN<double> workev(3*ncv);
+	    int ldz=n;
+	    char HowMny ='A';
+	    int rvec=1;
+	    double sigmai=0;
+	    neupp( rvec, HowMny, evr,evi, Z , ldz, sigma,sigmai, workev,
+		   bmat, n,   which,  nbev,  tol,  residptr, ncv,
+		     vp, n, iparam , ipntr, workd, workl,lworkl,info);
+	    
+	    
+	    if (verbosity)
+	      {
+		cout << "Real non-symmetric eigenvalue problem: A*x - B*x*lambda" << endl;
+		cout << "mode " << mode << " sigma=" << sigma <<  endl << endl;
+		
+		
+		cout << "Dimension of the system            : " << n              << endl;
+		cout << "Number of 'requested' eigenvalues  : " << nbev  << endl;
+		cout << "Number of 'converged' eigenvalues  : " << nconv          << endl;
+		cout << "Number of Arnoldi vectors generated: " << ncv  << endl;
+		cout << "Number of iterations taken         : " << iparam[3] << endl;
+		cout << endl;
+		  
+		cout << "Eigenvalues:" << endl;
+		for (int i=0; i<nconv; i++) {
+		  cout << "  lambda[" << (i+1) << "]: " ;
+		  ios::fmtflags oldflag= cout.flags();
+		  cout.setf(ios::showpos);
+		  cout << evr(i) 
+		       <<  evi(i) << "i"<<  endl;
+		  cout.flags(oldflag); // restore flags     
+		  KN_<double> vi(Z(':',i)) ;
+		  if(verbosity>99)
+		    {
+		      cout <<" Eigenvector: :" << vi << endl;
+		      cout << endl;	
+		    }    
+		  }
+	      }
+	    
+	    if (evalue)
+	      {
+		KN<double> & ev(*evalue);
+		int m = Min(nconv,ev.N());
+		for(int i=0;i<m;i++)
+		  ev[i]=evr(i);
+	      }
+	    
+	    if (evaluei)
+	      {
+		KN<double> & ev(*evaluei);
+		int m = Min(nconv,ev.N());
+		for(int i=0;i<m;i++)
+		  ev[i]=evi(i);
+	      }
+	    if(rawvector)
+	      {
+		//K*  rawev(prob.RawEigenvectors());
+		int m = Min(nconv,rawvector->M());
+	    ffassert(rawvector->N()==n);
+	    for(int i=0;i<m;i++)
+	      {
+		//int k=i;
+		KN_<K> vi(Z(':',i)) ;
+		cout << "   ------ EV--raw " << vi.min() << " " << vi.max() << endl;
+		(*rawvector)(':',i)=vi;
+	      }
+	    
+	      }
+	
+	    if (evector)
+	      {
+		// K*  rawev(prob.RawEigenvectors());
+		// rawev + n*k is
+		//  iev = prob.EigenvalueImag(k)
+		//  iev==0 => the eigen vector 
+		//  iev> 0 => real 
+		//      start real :  rawev + n*k 
+		//      start imag :  ramev +n*(k+1)
+		//  iev < 0 =>  complex  
+		//      start real :  rawev + n*(k-1) 
+		//      -start imag :  ramev +n*(k)
+		FEbaseArrayKn<K> & ev(*evector);
+		int m = Min(nconv,(long) ev.N);
+		for(int i=0;i<m;i++)
+		  {
+		    // K ev_i=
+		    //prob.EigenvalueImag(i);
+		    //KN<K> & xx= *(ev[i]);
+		    // if (xx.pVh != pOP1->pUh) 
+		    //    ExecError("Wrong Type of FEspace to store the eigen vector ");
+		    // xx.Vh = pOP1->Uh;
+		    // int  k=(ev_i < 0) ? i-1 : i;
+		    //int k=i;
+		     KN_<K> vi(Z(':',i));//rawev+n*k,n) ;
+		    //xx= new KN<K>(vi);
+		      ev.set(i,vi);//new KN<K>(vi));
+		  }
+	      }
+	    
+	  }
+	} 
+    if(pcOP1) delete pcOP1;
+    if(pcB) delete pcB;
+    
+	return (long) nconv;
+}
+  
+
+AnyType EigenValueC::E_EV::operator()(Stack stack)  const 
+{
+  dddd = (verbosity>=200);  
+  double tol=1e-6;
+  long nconv=0; 
+  long nbev=1;
+  long ncv =0;  // the number of Arnoldi vectors generated 
+  long maxit=0;  // the maximum number of Arnoldi iterations 
+  long mode=3;
+  K sigma=0;
+  KN<K> * evalue=0;
+  KN<K> * resid=0;
+  KNM<K> * rawvector=0;
+  
+ // pfecarray  evector2;
+  FEbaseArrayKn<Complex> *   evector=0;
+  tol=arg<double>(0,stack,0);
+  nbev=arg<long>(1,stack,0);
+  sigma=arg<K>(2,stack,0.0);
+  evalue=arg<KN<K> *>(3,stack,0);
+ // evector2 =arg<pfecarray>(4,stack,make_pair<pfecbasearray,int>(0,0));
+   evector= arg<FEbaseArrayKn<Complex> * >(4,stack,0);
+  ncv= arg<long>(5,stack,0);
+  maxit= arg<long>(6,stack,0);
+  rawvector=arg<KNM<K> *>(7,stack,0);
+  resid=arg<KN<K> *>(8,stack,0);
+  mode = arg<long>(9,stack,3);
+  K * residptr= resid ? (K*) *resid : 0;
+  //evector=evector2.first;
+  ffassert(mode>0 && mode <4) ; 
+ // Matrice_Creuse<K> *pOP1 =  GetAny<Matrice_Creuse<K> *>((*expOP1)(stack));
+//  Matrice_Creuse<K> *pB =  GetAny<Matrice_Creuse<K> *>((*expB)(stack));
+  
+  if(evalue) nbev=Max( (long)evalue->N(),nbev);
+  if(!maxit)  maxit = 100*nbev;    
+  
+  //const MatriceCreuse<K> & OP1 = pOP1->A;
+  //const MatriceCreuse<K> & B = pB->A;
+  
+  //long  n=OP1.n;
+    
+    
+    Matrice_Creuse<K> *pOP1=0, *pB=0;
+    if(expOP1)
+        pOP1 =  GetAny<Matrice_Creuse<K> *>((*expOP1)(stack));
+    if(expB)
+        pB =  GetAny<Matrice_Creuse<K> *>((*expB)(stack));
+   // double * residptr=resid? (double*) *resid : 0;
+   // cout << " residptr = " << residptr <<endl;
+    long  n=0;
+    if( pOP1)
+        n =pOP1->A->n;
+    else {
+        ffassert(expn);
+        n = GetAny<long>((*expn)(stack));
+    }
+    
+    if(evalue) nbev=Max( (long)evalue->N(),nbev);
+    
+    const VirtualMatrice<K> * ptOP1, *ptB;
+    if(pOP1)
+        ptOP1= & (const VirtualMatrice<K>&)(pOP1->A);
+    if(pB)
+        ptB = &  (const VirtualMatrice<K>&)(pB->A);
+    
+    FuncMat<K> *pcOP1=0,  *pcB=0;
+    if(codeOP1)
+        ptOP1=pcOP1= new FuncMat<K>(-1,n,stack,codeOP1);
+    if(codeB)
+        ptB=pcB= new FuncMat<K>(1,n,stack,codeB);
+    MatriceIdentite<K>  Id(n);
+    
+    if(!ptB) ptB = &Id;
+    const VirtualMatrice<K> &OP1= *ptOP1, &B=*ptB;
+    
+    
+    
+  nbev=min(nbev,n-2);
+  if(!ncv)     ncv = nbev*2+1;  
+  ncv = max(nbev+2,ncv);
+  ncv = min(ncv,n);
+  const char *serr[10];
+  int err=0;
+  if(nbev>= n-1)
+     serr[err++]="  Number of eigenvalues of OP to be computed <= n-2 ";
+   if( mode < 1 || mode > 3) 
+        serr[err++]="  the mode = 1 ,2 ,3  ";
+  // 2 <= NCV-NEV and NCV <= N
+   if( ! ( 2 <= nbev && ncv <= n)) 
+       serr[err++]="   ( 2 <= nbve && nvc <= n) ";
+  if (n != OP1.N)
+   serr[err++]=" the first matrix in EigneValue is not Hermitien.";
+  if (n != B.N )
+    serr[err++]="Sorry the row's number of the secand matrix in EigneValue is wrong.";
+  if (n != B.M )
+    serr[err++]="Sorry the colum's number of the secand matrix in EigneValue is wrong.";
+    if(verbosity)
+	cout << "Real complex eigenvalue problem: A*x - B*x*lambda" << endl;
+  if(verbosity>9 ||  err)
+	cout << "   n " << n << " nev "<< nbev << " tol =" << tol << " maxit =" << maxit << " ncv = " << ncv << " mode = " << mode << endl;	
+  if(err) 
+    {
+	cerr << " list of the error " << endl;
+	for (int i=0;i<err;++i)
+	    cerr << "\n-  " <<  serr[i] << endl;
+	ExecError("Fatal Error in EigenValue (complex) ");
+    }
+
+      
+  
+ 
+  KN<K> work(n);
+  //  ARrcSymGenEig is a class that requires the user to provide a
+  //   way to perform the matrix-vector products w = OP*Bv =
+  //   inv(A-sigma*B)*B*v and w = B*v, where sigma is the adopted shift.
+  // OP1 = (A-sigma*B)
+  // OP = inv(OP) 
+  /*
+  ffassert(0);
+
+
+    ARrcCompGenEig<R> prob( n, nbev, sigma,"LM",ncv,tol,maxit,residptr);
+
+
+    // OP = inv[A - sigma*I]
+
+
+    // Finding an Arnoldi basis.
+
+    while (!prob.ArnoldiBasisFound()) {
+
+      // Calling ARPACK FORTRAN code. Almost all work needed to
+
+      prob.TakeStep();
+  */
+
+  // cas non symetrique ,
+  // Finding an Arnoldi basis.                                                                                                              \
+                                                                                                                                                   
+ // int mode=3; //  Shift invert			\
+
+  int ido=0;
+  char bmat='G';
+  char which[]="LM";
+  int ishift=1; // Auto Shift true by default                                                                                               \
+
+  int iparam[12]= { 0, ishift, 0, (int) maxit, 1,(int)  nconv, 0,(int) mode, 0, 0, 0, 0 };
+  int ipntr[15]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+  KN<K> workd(3*n+1);
+  int lworkl = 3*ncv*ncv+5*ncv;
+  KN<K> workl(lworkl+1);
+  KN<K> vp(ncv*n+1);
+  int info= (residptr !=0);
+  KN<double> rwork(ncv+1);
+  KN<K> vresid(residptr? 1: n);
+  if(!residptr) residptr=&vresid[0];
+
+  
+  while(1)
+    {
+      
+      caupp(ido, bmat, n, which, nbev,
+	    tol, residptr, ncv,
+	    vp, n, iparam, ipntr, workd, workl,
+	    lworkl,rwork, info);
+      
+      if(verbosity>99) { cout << "    caupp ido: " << ido << " info : " << info << endl; }
+      if(info<0) {cerr << " -- err arpack info = " << info << endl;}
+      sauppError(info);
+      
+      if(ido==99) break;
+      
+      KN_<K>  xx(&workd[ipntr[1]],n);
+      KN_<K>  yy(&workd[ipntr[2]],n);
+      KN_<K>  zz(&workd[ipntr[3]],n);
+      
+      DoIdoAction(ido,mode,xx,yy,zz,work,OP1,B);
+    }
+ 
+  nconv = iparam[5];
+  if(nconv)
+    {
+      int newdim = nbev;
+      if(nconv>nbev) {
+ 	cerr << "WARNING: nconv(caupp) > nbev: " << nconv << " > " << nbev << endl;
+ 	newdim = nconv;
+      }
+      KN<K> evc(newdim);
+      KNM<K> Z(n,newdim);
+      KN<K> workev(3*ncv);
+      //int ldz=n;
+      char HowMny ='A';
+      int rvec=1;
+      ceupp( rvec, HowMny, evc, Z, n, sigma, workev,  bmat, n,  which, 
+ 	     nbev, tol, residptr, ncv,
+ 	     vp, n, iparam, ipntr, workd, workl,lworkl,rwork,info);
+
+      if (verbosity)
+	{
+	  cout << "Complex eigenvalue problem: A*x - B*x*lambda" << endl;
+	  cout << "mode =" << mode << "  sigma=" << sigma <<  endl << endl;
+	  
+	  cout << "Dimension of the system            : " << n              << endl;
+	  cout << "Number of 'requested' eigenvalues  : " << nbev  << endl;
+	  cout << "Number of 'converged' eigenvalues  : " << nconv          << endl;
+	  cout << "Number of Arnoldi vectors generated: " << ncv << endl;
+	  cout << "Number of iterations taken         : " << iparam[3]  << endl;
+	  cout << endl;
+	  
+	  cout << "Eigenvalues:" << endl;
+	  for (int i=0; i<nconv; i++) {
+	    cout << "  lambda[" << (i+1) << "]: " << evc(i) << endl;
+	    KN_<K> vi(Z(':',i)) ;
+	    if(verbosity>99)
+	      cout <<" Eigenvector: :" << vi << endl;
+	  }
+		       cout << endl;
+	}
+      
+      
+      if (evalue)
+	{
+	  KN<K> & ev(*evalue);
+	  int m = Min(nconv,ev.N());
+	  for(int i=0;i<m;i++)
+	    ev[i]=evc(i);
+	}
+      if (evector)
+	{
+	  //FEbaseArray<K,v_fes> & ev(*evector);
+	    FEbaseArrayKn<K>  & ev(*evector);
+	  int m = Min(nconv,(long) ev.N);
+	  for(int i=0;i<m;i++)
+	    {
+	      //FEbase<K,v_fes> & xx= **(ev[i]);
+	      //KN_<K> vi(Z(':',i)) ;
+	      //xx= new KN<K>(vi);
+		ev.set(i,Z(':',i));
+	      
+	    }
+	}
+       if(rawvector)
+	    {
+	      int m = Min(nconv,rawvector->M());
+	      ffassert(rawvector->N()==n);
+	      for(int i=0;i<m;i++)
+		{
+		  KN_<K> vi(Z(':',i)) ;
+		  (*rawvector)(':',i)=vi;
+		    cout << " raw " << vi.l2() << " == " << (*rawvector)(':',i).l2()<< endl;
+		}
+	      
+	    }
+	  
+	
+    }
+  
+return (long) nconv;
+}
+
+#ifndef DYNM_LOAD
+void init_eigenvalue()
+{
+  if(verbosity&& (mpirank==0) ) cout << "eigenvalue ";
+    Global.Add("EigenValue","(",new EigenValue());  //  j + dJ
+    Global.Add("EigenValue","(",new EigenValueC());  //  j + dJ
+    Global.Add("EigenValue","(",new EigenValue(1));  //  j + dJ
+    Global.Add("EigenValue","(",new EigenValue(1,1));  //  j + dJ
+   // Global.Add("EigenValue","(",new EigenValueC(1));  //  j + dJ
+   
+}
+#else
+class Init {
+public:
+  Init()
+  {
+    if(verbosity&&(mpirank==0) ) cout << "eigenvalue ";
+    Global.Add("EigenValue2","(",new EigenValue());  //  j + dJ
+    Global.Add("EigenValue2","(",new EigenValueC(1));  //  j + dJ
+  }
+};
+Init init; 
+#endif
diff --git a/src/FreeFem++-CoCoa b/src/FreeFem++-CoCoa
new file mode 100755
index 0000000..b5e6587
--- /dev/null
+++ b/src/FreeFem++-CoCoa
@@ -0,0 +1,50 @@
+#!/bin/sh
+#  
+# EXTENSIONS  : ".edp"				# Accepted file extentions
+# OSTYPES     : "****"				# Accepted file types
+# ROLE        : None				# Role (Editor, Viewer, None)
+# SERVICEMENU : FreeFem++     			# Name of Service menu item
+#
+dir=`dirname $0`;
+ff="/usr/local/bin/FreeFem++"
+q="'"
+end="exit;"
+begin="cd $PWD;"
+
+# begin the cmd generation ----------
+cmd=""
+# -----------------
+for i in "$@"; do
+ d=`dirname "$i"`;
+ f=`basename "$i"`;
+ cmd="$cmd cd $q$d$q; $ff $q$f$q;"
+done
+# ------------------ 
+if [ -z "$cmd" ]; then
+ cmd="$ff;"
+fi
+# ------------------
+cmd="$cmd"
+# ---- end of cmd generation ----
+echo 'do script "'$cmd'"'
+#
+#
+#  send the command $cmd to the apple terminal via osascript
+#
+# (echo $0;echo $*;echo "--$TERM--";printenv;set)  >/tmp/tutu
+
+if [ -z "$TERM_PROGRAM" ] ; then 
+echo '
+tell application "Terminal"
+	activate
+	try
+	  do script "'$begin$cmd$end'" 
+	end try
+end tell 
+' | osascript 	
+else
+set -e
+eval  $cmd
+fi;
+
+
diff --git a/src/Graphics/._ffglut.cpp b/src/Graphics/._ffglut.cpp
new file mode 100644
index 0000000..63e1130
Binary files /dev/null and b/src/Graphics/._ffglut.cpp differ
diff --git a/src/Graphics/._getprog-unix.hpp b/src/Graphics/._getprog-unix.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/Graphics/._getprog-unix.hpp differ
diff --git a/src/Graphics/DefColor.cpp b/src/Graphics/DefColor.cpp
new file mode 100644
index 0000000..e0f3aca
--- /dev/null
+++ b/src/Graphics/DefColor.cpp
@@ -0,0 +1,96 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <cmath>
+using namespace std;
+
+void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool grey,int nbcolors,float *colors);
+
+
+ void hsvToRgb (float h, float s, float v, float & r, float & g, float & b)
+{
+  int i;
+  float aa, bb, cc, f;
+
+  if (s == 0) /* Grayscale */
+    r = g = b = v;
+  else {
+    h = h - floor(h);
+    if (h == 1.0) h = 0;
+    h *= 6.0;
+    i =  int(h);
+    f = h - i;
+    aa = v * (1 - s);
+    bb = v * (1 - (s * f));
+    cc = v * (1 - (s * (1 - f)));
+    switch (i) {
+    case 0: r = v;  g = cc; b = aa; break;
+    case 1: r = bb; g = v;  b = aa; break;
+    case 2: r = aa; g = v;  b = cc; break;
+    case 3: r = aa; g = bb; b = v;  break;
+    case 4: r = cc; g = aa; b = v;  break;
+    case 5: r = v;  g = aa; b = bb; break;
+    }
+  }
+}
+//  def des couleurs de la tables 
+void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool grey,int nbcolors,float *colors)
+{
+  if(k<=0) {  r=g=b=1.;} //  white
+  else if (k==1)  { r=g=b=0.; } // black
+  else if (k >= nb)   {  r=g=b=0.;} // black
+  else if (grey) { float gg = 0.1+0.9*float(k-2)/(nb-3); r=g=b=gg;} 
+  else if (nbcolors<=1) {  
+     float h=float(k-2)/(nb-2),s=1.,v=1.;
+     hsvToRgb(h,s,v,r,g,b); 
+     return;}     
+  else   { //  interpolation dans la table hsv    
+      int i= (k-2); 
+      int j0= i*(nbcolors-1) / (nb-2);
+      int j1=j0+1;
+      int i0=  j0*(nb-2)/(nbcolors-1);
+      int i1=  j1*(nb-2)/(nbcolors-1);
+      int j03=j0*3,j13=j1*3;
+      float a=float(i1-i)/(i1-i0),a1=1-a;
+      if (hsv)
+       {
+        float h = colors[j03+0]*a + colors[j13+0]*a1;
+        float s = colors[j03+1]*a + colors[j13+1]*a1;
+        float v = colors[j03+2]*a + colors[j13+2]*a1;
+        hsvToRgb(h,s,v,r,g,b); }
+      else 
+      {
+       r = colors[j03+0]*a + colors[j13+0]*a1;
+       g = colors[j03+1]*a + colors[j13+1]*a1;
+       b = colors[j03+2]*a + colors[j13+2]*a1;
+      }
+    }     
+ 
+}
+
diff --git a/src/Graphics/Makefile.am b/src/Graphics/Makefile.am
new file mode 100644
index 0000000..5f0353e
--- /dev/null
+++ b/src/Graphics/Makefile.am
@@ -0,0 +1,11 @@
+EXTRA_DIST=glrgraph.hpp  macglrgraf.cpp	\
+macrgraf.cpp Pcrgraph.cpp  rgraph.hpp		\
+sansrgraph.cpp xglrgraf.cpp Xrgraph.cpp DefColor.cpp   \
+getprog-unix.hpp mode_open.hpp ffglut.hpp ff-win32.cpp
+
+# FFCS: no compilation here, so the tags file must be built by hand
+tags:TAGS
+TAGS:
+	etags *.?pp
+clean-local::
+	-rm TAGS
diff --git a/src/Graphics/Pcrgraph.cpp b/src/Graphics/Pcrgraph.cpp
new file mode 100644
index 0000000..237ace8
--- /dev/null
+++ b/src/Graphics/Pcrgraph.cpp
@@ -0,0 +1,1559 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : D. Bernardi, Y. Darmaillac F. Hecht,     */
+/*           O. Pironneau, K.Ohtsuka        */
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#define PCRGRAPH_CPP
+#define FF_GRAPH_SET_PTR
+#include <config-wrapper.h>
+
+#define TOSTRING1(i) #i
+#define TOSTRING(i) TOSTRING1(i)
+#include <ext/stdio_filebuf.h>
+#include <cstdlib>
+///#include <unistd.h>
+#include <cmath>
+#include <string>
+#include <setjmp.h>
+#include <cctype>
+#include <new>
+#include <iostream>
+#include <fstream>
+using namespace std;
+//#include "vect.h"
+#include "error.hpp"
+#include "strversionnumber.hpp"
+//#include <memory.h>
+
+/*
+** Windows includes
+*/
+#include <windows.h>
+#include <commdlg.h>
+///#include <direct.h>
+#include <time.h>
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <io.h>      //*OT  use for the console window
+///#include <stat.h>
+
+const char *  edpfilenamearg=0; 
+bool  waitatend=true;
+bool  consoleatend=true;
+
+#define fill thequikdrawfill
+
+#include "rgraph.hpp"
+
+//char *Version = "1.2.7";
+void out_of_memory ();
+void NEW_HANDLER (void);
+void myexit(int);
+void compile(char *fname);
+float scali(int i);
+float scalj(int j);
+//int pStrCopy (StringPtr p1, StringPtr p2);
+int execute(char* what);
+//int DoMouseDown (int windowPart, WindowPtr whichWindow, EventRecord *myEvent);
+char Getijc(int & x,int & y);
+void postexit();
+
+static int  cube6[7][3] ={ {255,0,0},{255,255,0},{0,255,0},
+      {0,255,255},{0,0,255}, {255,0,255},{255,0,0} }; 
+static  int grey6[2][3] ={ {255,255,255},{0,0,0} }; 
+static bool grey=false;      
+static int ncolortable=0;
+static int LastColor=2; // LastColor=1 => Noir et Blanc >2 =>couleur
+
+typedef struct rgb {
+  BYTE r;    // red component of color
+  BYTE g;  // green component of color
+  BYTE b;    // blue component of color
+}	rgb;
+
+static rgb * colortable=0;
+static HPEN*  hpen=0;
+static HBRUSH*  hbr=0;
+static  HFONT  hFont=0;
+static int fontH = 0;	// The height of font
+static int cstatic=1;
+
+int getcolor();
+void putpixel(int ix,int iy, int couleur);
+int scalx(float x);
+int scaly(float y);
+void compile (char *);
+
+void NEW_HANDLER (void){  set_new_handler (&out_of_memory);}
+
+#define ours(w)   (w==grafWindow0)
+
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+
+char errbuf[255];
+static int INITGRAPH=0;
+float rayon;
+static int width,height;
+
+static FILE *psfile = 0;
+static FILE *psfile_save = 0;
+static float aspx, aspy, echx,echy,ech,rxmin,rxmax,rymin,rymax;
+static int currx, curry;
+static int carre;
+
+static HWND        hWnd;
+static WNDCLASS    rClass;
+static HDC hdc;
+static HANDLE hConOut=0;
+const float fMinPixel = -32000; // to avoid int overflot 
+const float fMaxPixel = 32000;
+
+/* Function definitions */
+BOOL Init(HINSTANCE, HINSTANCE, LPSTR, int);
+int  DoMain(HINSTANCE hInstance);
+LONG WINAPI OpenWindowProc1(HWND, UINT, WPARAM, LPARAM);
+
+int getcolor();
+void putpixel(int ix,int iy, int couleur);
+int scalx(float x);
+int scaly(float y);
+void rattente (int);
+BOOL inittext(VOID);
+
+BOOL ShowOpenDialogBox(char *fileName);
+BOOL CreateProjetFile(char *fileName);
+char *ChangePdeToExt(char *fileName,char *ext);
+BOOL mainFreeFEM();
+int GetFileName(char *fullname, char  *shortname);
+DWORD GetOption(char lpszCmdLine[]);
+void SetConsole(HANDLE hConsole);
+FILE *GetConsoleHandle(DWORD Dev);
+BOOL GetConsoleBuff();
+BOOL EditLog();
+//void SaveMesh(Grid& t);
+//void SavePlot(int D,Grid& t, Real *f);
+BOOL FatalErr(char *s, int err);
+//BOOL CheckSameTrig(Grid& t);
+
+//*OT  flag for FreeFEM+/WinfFEM
+#define winf_VFFEM 1
+#define winf_NOWAIT 2
+#define winf_NOCOLOR 4
+#define winf_NOEDIT 8
+#define  winf_Usage   1024
+
+unsigned int winf_flg = 0;
+// end
+
+char FreeFemCache[256]="\0",
+     shortName[256]="\0",
+     fullName[256]="\0";          
+
+void fillpoly(int n, float *poly){
+   POINT *pt;
+   
+   pt = new POINT[n];
+   for (int i=0; i < n; i++) {
+      pt[i].x = scalx(poly[2*i]); pt[i].y = scaly(poly[2*i+1]);
+     }
+   
+   if (cstatic <0  || cstatic > ncolortable)  cstatic =1;
+   SelectObject(hdc,hbr[cstatic]);
+   int ret = Polygon(hdc,pt,n);
+   delete []  pt;
+   SelectObject(hdc,hpen[n]);
+    if (psfile) 
+    {
+     fprintf(psfile,"bF ");
+     for (int i=0;i<n;i++)
+      fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1]));
+     fprintf(psfile,"eF\n");
+    }
+} 
+
+void out_of_memory ()
+{
+  cout << " error: operator new failed; not enough memory" << endl;
+  myexit (1);
+}
+
+void erreur(char *s)
+{
+   ErrorExec(s,0);
+ 
+}
+void HandleWindowEvent()
+{  MSG msg;
+  
+//if ( PeekMessage(&msg,NULL,WM_PAINT,WM_PAINT,PM_NOREMOVE)) {
+if ( PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) {
+    	TranslateMessage(&msg);
+   		DispatchMessage(&msg);
+  	}
+  	
+}
+void SetColorTable(int n);
+void raffpoly(int n, float *poly){}
+#include "getprog-unix.hpp"
+    
+
+void penthickness(int pepais){
+  if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais);
+}
+void showgraphic(){ShowWindow(hWnd, SW_SHOW ); } // UpdateWindow(hWnd);}
+
+void thisexit(){ myexit(0);}
+
+    
+void plotstring(const char *s)
+{
+    static  HFONT  hOldFont;
+
+    if (s == 0) return;
+    hOldFont = (HFONT)::SelectObject(hdc,hFont);
+    //::GetTextMetrics(hdc, &tm);
+    ::TextOut(hdc, currx, curry-fontH, s, strlen(s));
+    ::DeleteObject(hOldFont);
+
+	  if(psfile) {
+	     fprintf(psfile,"%d %d M\n", currx,height-curry);
+	     fprintf(psfile,"(%s) S\n",s);
+	  }
+}
+
+void rmoveto(float x, float y)
+{
+	currx = scalx(x);
+	curry = scaly(y);
+}         
+
+void rlineto(float x, float y)
+{
+  HandleWindowEvent();
+  int newx = scalx(x), newy = scaly(y);
+  MoveToEx(hdc,currx,curry,NULL);
+  LineTo(hdc,newx,newy);
+  if (psfile) {
+    fprintf(psfile,"%d %d M\n", currx,height-curry);  
+    fprintf(psfile,"%d %d L\n", newx,height-newy);
+  }
+  currx = newx; curry = newy;
+}
+
+void cadre(float xmin,float xmax,float ymin,float ymax)
+{
+	rxmin = xmin;
+	rxmax = xmax;
+	rymin = ymin;
+	rymax = ymax;
+	echx=aspx/(xmax-xmin);
+	echy=aspy/(ymax-ymin); 
+}
+
+void getcadre(float &xmin,float &xmax,float &ymin,float &ymax)
+{
+  xmin = rxmin;
+  xmax = rxmax;
+  ymin = rymin;
+  ymax = rymax;
+}
+
+void cadreortho(float centrex, float centrey, float rayon)
+{
+	RECT rc;
+	GetClientRect(hWnd, &rc);
+
+	width = rc.right - rc.left;
+	height = rc.bottom - rc.top;
+
+  if (height < width)
+  {
+    rymin = centrey - rayon;
+    rymax = centrey + rayon;
+    echx = echy= height / (2 * rayon);
+    rxmin= centrex - width / (2 * echx);
+    rxmax= centrex + width / (2 * echx);
+  }
+  else
+  {
+    rxmin = centrex - rayon;
+    rxmax = centrex + rayon;
+    echx = echy = width / (2 * rayon);
+    rymin = centrey - height / (2 * echy);
+    rymax = centrey + height / (2 * echy);
+  }
+}
+
+int scalx(float x)
+{
+  return static_cast<int>((x - rxmin) * echx);
+}
+
+int scaly(float y)
+{
+  return static_cast<int>((rymax - y) * echy);
+}
+
+float scali(int i)
+{
+  return i/echx  + rxmin;
+}
+
+float scalj(int j)
+{
+  return -j/echy  + rymax;
+}
+
+void pointe(float x, float y)
+
+{
+//  putpixel(scalx(x), scaly(y), LastColor);
+}
+
+int InRecScreen(float x1, float y1,float x2, float y2)
+{  
+  float xi = Min(x1,x2),xa=Max(x1,x2);
+  float yi = Min(y1,y2),ya=Max(y1,y2);
+  return (xa >= rxmin) && (xi <= rxmax) && (ya >= rymin) && (yi <= rymax);
+}
+
+int InPtScreen( float x, float y)
+{
+  return (x >= rxmin) && (x <= rxmax) && (y >= rymin) && (y <= rymax);
+}
+
+void SetRGBpen(int n)
+{
+    SelectObject(hdc, hpen[n]);
+}
+
+static rgb DefColorWin32( int k,int nb, bool hsv,bool grey,int nbcolors,float *colors)
+{
+ rgb C;
+ float r,g,b;
+extern void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool grey,int nbcolors,float *colors);
+ DefColor(r,g,b,   k,nb,hsv,grey,nbcolors,colors);
+ C.r= (BYTE) (255*r);
+ C.g= (BYTE) (255*g);
+ C.b= (BYTE) (255*b);
+ return C;
+}              
+
+
+void SetColorTable1(int nb,bool hsv,int nbcolors,float *colors)
+{
+  static bool greyo = !grey;
+  static float * colorso =0;
+  if(!INITGRAPH) return;
+  if (ncolortable == nb && greyo == grey && colorso == colors ) return;// optim
+   greyo = grey;
+   colorso=colors;
+   { 
+     if (hpen) for(int i=0; i<ncolortable;i++)
+       DeleteObject(hpen[i]);
+     delete [] hpen;
+     if (hbr) for(int i=0; i<ncolortable;i++)
+       DeleteObject(hbr[i]);
+     delete [] hbr;
+     if (hFont) DeleteObject(hFont);
+     hpen=0;
+     hbr=0;
+     hFont=0;
+     
+     if(colortable) 
+       delete [] colortable;
+     colortable = new rgb[nb+1];
+     ncolortable = nb;
+     if(LastColor>1) LastColor=nb-1;
+     for (int i0=0;i0<nb;i0++)
+       {  
+	 colortable[i0]=DefColorWin32(i0,nb,hsv,grey,nbcolors,colors);           
+       }
+     
+   }
+   
+   {
+     
+     hpen = new HPEN[ncolortable];
+     hbr = new HBRUSH[ncolortable];
+     
+     for(int i=0; i<ncolortable;i++)
+       {
+	 hpen[i] = CreatePen(PS_INSIDEFRAME, 1,RGB(colortable[i].r, 
+						   colortable[i].g,
+						   colortable[i].b));
+	 hbr[i] = CreateSolidBrush(RGB(colortable[i].r, 
+				       colortable[i].g,
+				       colortable[i].b));
+	 }
+   }
+   
+}
+
+void SetColorTable(int nb)
+{
+  RECT rc;
+  GetClientRect(hWnd, &rc);
+  aspx = (float)(rc.right - rc.left);
+  aspy = (float)(rc.bottom - rc.top);
+  
+  if (winf_flg & winf_NOCOLOR) return;
+  nb=Max(nb,23);
+  if(nb<2) nb = 2;
+  if (ncolortable == nb) return;
+  if(LastColor>1) LastColor=nb-1;
+  
+  if (hpen) for(int i=0; i<ncolortable;i++)
+    DeleteObject(hpen[i]);
+  delete [] hpen;
+  if (hbr) for(int i=0; i<ncolortable;i++)
+    DeleteObject(hbr[i]);
+  delete [] hbr;
+  if (hFont) DeleteObject(hFont);
+  hpen=0;
+  hbr=0;
+  hFont=0;
+  
+  if(colortable) 
+    delete [] colortable;
+  colortable = new rgb[nb+1];
+  ncolortable = nb;
+  int k=0;
+  colortable[k].r = 255;
+  colortable[k].g = 255;
+  colortable[k++].b = 255;
+  colortable[k].r = 0;
+  colortable[k].g = 0;
+  colortable[k++].b = 0;
+  if (nb>2) 
+    { 
+      nb -= 2;
+      for (long i0=0;i0<nb;i0++,k++)
+        {  
+	  long  i6 = i0*6;
+	  long  j0 = i6/nb;// in 0..6
+	  long  j1 = j0+1;// in 1..6
+	  long  k0 = i0 - (nb*j0)/6L;
+	  long  k1 = (nb*j1)/6L-i0;
+	  long  kk = (k0+k1);
+	  
+	  if (! grey)
+	    {
+	      colortable[k].r  = ((cube6[j1][0]*k0+cube6[j0][0]*k1)/kk);
+	      colortable[k].g  = ((cube6[j1][1]*k0+cube6[j0][1]*k1)/kk);
+	      colortable[k].b  = ((cube6[j1][2]*k0+cube6[j0][2]*k1)/kk);
+	    }
+          else 
+	    {
+	      kk=nb-1;
+	      k1 =  i0;
+	      k0 = nb - i0 -1;
+	      colortable[k].r   = ((grey6[0][0]*k0+grey6[1][0]*k1)/kk);
+	      colortable[k].g   = ((grey6[0][1]*k0+grey6[1][1]*k1)/kk);
+	      colortable[k].b   = ((grey6[0][2]*k0+grey6[1][2]*k1)/kk);
+	    }
+	  
+	  /*
+	    colortable[k].r = ((cube6[j1][0]*k0+cube6[j0][0]*k1)/kk)%256;
+	    colortable[k].g = ((cube6[j1][1]*k0+cube6[j0][1]*k1)/kk)%256;
+	    colortable[k].b = ((cube6[j1][2]*k0+cube6[j0][2]*k1)/kk)%256;
+	  */
+        }         
+    }
+  else 
+    {	ncolortable  =2;}
+  
+  hpen = new HPEN[ncolortable];
+  hbr = new HBRUSH[ncolortable];
+  
+  for(int i=0; i<ncolortable;i++)
+    {
+      hpen[i] = CreatePen(PS_INSIDEFRAME, 1,RGB(colortable[i].r, 
+						colortable[i].g,
+						colortable[i].b));
+      hbr[i] = CreateSolidBrush(RGB(colortable[i].r, 
+				    colortable[i].g, 
+				    colortable[i].b));
+    }
+}
+
+void couleur(int c)
+{ 
+  if(c!=cstatic) 
+  { 
+    c= c > LastColor ? 1 : c; // c=Min(c,LastColor); pour noir et blanc
+
+    if (!(winf_flg&winf_NOCOLOR)) {
+    if (c>=0 && c < ncolortable)
+    	cstatic = c;
+    else cstatic = 1;  
+	SetRGBpen(cstatic);
+  	}
+  // else  SetRGBpen(1);
+  }
+  if (psfile)
+  {
+    float r=1,g=1,b=1;
+    if (colortable) {
+      if (c>0 && c < ncolortable)
+  {
+    r =  (float) colortable[c].r /255.;
+    g =  (float) colortable[c].g /255.;
+    b =  (float) colortable[c].b /255.;
+  }
+    }
+    else if (c!=0)
+      r=g=b=0;
+    
+    fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b);
+  }
+}
+int LaCouleur(){return cstatic;}
+
+//* Control on the graphic window
+void rattente(int waitm)
+{
+   int i=0, j=0;
+   char c;
+   if (waitm)
+     if(!(winf_flg&winf_NOWAIT)) c = Getijc(i,j);
+}
+
+char Getijc(int & x,int & y)
+{
+  char char1=' ';
+  if(!INITGRAPH) 
+    {
+      x = 0;
+      y = 0;   
+      return char1;
+    }
+   int  cont=1;
+   POINT xy;
+    xy.x =0;
+    xy.y =0;
+  MSG msg;      
+	SetWindowText(hWnd,"Click mouse to continue");
+  do
+   {   
+      GetMessage(&msg,hWnd,0,0);// all message
+      GetCursorPos(&xy);
+      switch (msg.message)
+       {
+         case WM_LBUTTONDOWN:char1=char(251), cont=0;
+         		break; 
+         // with shift 248                 
+         case WM_RBUTTONDOWN:char1=char(253), cont=0;
+         break;  
+         // with shit 250
+         // if the 2 buttom, 252, et shith 249;
+         case WM_CLOSE:	myexit(2);
+         case WM_DESTROY:   myexit(3);
+         case WM_CHAR: char1 = (TCHAR)msg.wParam; cont = 0; break;
+               //case WM_KEYDOWN: char1 = (TCHAR)msg.wParam;  cont=0; break;
+       default:
+  					TranslateMessage(&msg);
+     				DispatchMessage(&msg);
+       	break;
+       }
+    }
+    while (cont); 
+//    ScreenToClient(hWnd,&xy);
+ 	ShowWindow(hWnd, SW_SHOW );
+ // SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+    SetWindowText(hWnd,   PACKAGE_STRING  " works...");
+ 	RECT rc;
+    ScreenToClient(hWnd,&xy);
+ 	GetClientRect(hWnd, &rc);
+ 
+ 	x = xy.x-rc.left;
+ 	y = xy.y-rc.top;
+ //	cout << " x = " << x << " y = " << y  << " char = " << ((unsigned char)char1 > 127 ? '*': char1) << ")" << endl;
+ 	return char1;
+}
+
+char Getxyc(float &x,float &y)
+{ 
+  char c=' ';
+  int i=0,j=0;
+  if(!(winf_flg&winf_NOWAIT)) c = Getijc( i,j);
+  x = scali(i);
+  y = scalj(j);
+  //rattente(1);
+  return c;
+}
+
+//* clear the screen with white
+void reffecran(void)
+{     
+ HBRUSH hbr;
+ RECT rc;
+
+ GetClientRect(hWnd, &rc);
+ hbr = CreateSolidBrush(RGB(255, 255, 255));
+ FillRect(hdc,&rc,hbr);
+ DeleteObject(hbr);
+}
+
+BOOL ShowOpenDialogBox(char *fileName)
+{
+  OPENFILENAME ofn; 
+  char szDirName[256];   
+  char *strFilter="PCgFEM Files (*.edp)\0*.edp\0All Files (*.*)\0*.*\0\0"; 
+  
+  memset(&ofn, 0, sizeof(OPENFILENAME));
+  getcwd(szDirName,sizeof(szDirName));
+  ofn.lStructSize = sizeof(OPENFILENAME);
+  ofn.hwndOwner = NULL;
+  ofn.lpstrFilter = strFilter;
+  ofn.lpstrFileTitle = fileName;
+  ofn.nMaxFileTitle = 80;
+  ofn.lpstrInitialDir=szDirName;
+  ofn.lpstrTitle ="Choose you freefem '*.edp' File";
+  ofn.Flags=OFN_SHOWHELP|OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
+  
+  return GetOpenFileName(&ofn);
+} 
+
+void coutmode(short r) { ;}// will be done later
+   
+
+void initgraphique(void)       
+{ 
+  if (INITGRAPH) return;
+  hdc=GetDC(hWnd);
+  hpen=0;
+  SetColorTable(2+6);
+
+  RECT rc;
+  GetClientRect(hWnd, &rc);
+  aspx = (float)(rc.right - rc.left);
+  aspy = (float)(rc.bottom - rc.top);
+  width = rc.right - rc.left;
+  height = rc.bottom - rc.top;
+  carre = aspx == aspy;
+  // Define the font style
+    LOGFONT lf;
+    TEXTMETRIC tm;
+		HFONT hFont, hOldFont;
+
+    memset(&lf, 0, sizeof lf);
+    lf.lfHeight = -9;
+    lstrcpy(lf.lfFaceName,"Arial");
+    lf.lfOutPrecision = OUT_TT_PRECIS;
+    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+    lf.lfQuality = PROOF_QUALITY;
+    lf.lfPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
+    hFont = ::CreateFontIndirect(&lf);
+
+    hOldFont = (HFONT)::SelectObject(hdc,hFont);
+    ::GetTextMetrics(hdc, &tm);
+    ::DeleteObject(hOldFont);
+    fontH =  static_cast<int>((tm.tmHeight + tm.tmExternalLeading)*0.6);
+  // end of font style
+  INITGRAPH = 1;
+  // cout << flush << "end  inigraphique " << endl;
+}
+
+void closegraphique(void)
+{ 
+	if(INITGRAPH) {
+		if(hpen) 
+		   DeleteObject(hpen), delete [] colortable;
+		if (hbr)   DeleteObject(hbr), 
+    INITGRAPH =0; // before DestroyWindow to avoid loop 
+    ReleaseDC(hWnd,hdc); 
+//    DestroyWindow(hWnd);
+	}
+}
+
+void GetScreenSize(int & ix,int &iy)
+{
+  ix = width ;
+  iy = height;
+}
+
+void openPS(const char *filename )
+{ 
+  RECT rc;
+  GetClientRect(hWnd, &rc);
+  width = rc.right - rc.left;
+  height = rc.bottom - rc.top;
+
+  closePS();
+  time_t t_loc;
+  float s=0.5;
+    const int shiftx=50,shifty=50;
+
+  time(&t_loc);
+  printf(" Save Postscript in file '%s'\n",filename?filename:"freefem.ps"),
+  psfile=fopen(filename?filename:"freefem.ps","w");
+  if(psfile==0) {printf("Erreur %s \n",filename);exit(1);}
+    if(psfile) {
+  fprintf(psfile,"%%!PS-Adobe-2.0 EPSF-2.0\n%%%%Creator: %s\n%%%%Title: FreeFem++\n","user");
+  fprintf(psfile,"%%%%CreationDate: %s",ctime(&t_loc));
+  fprintf(psfile,"%%%%Pages: 1\n");
+  fprintf(psfile,"%%%%BoundingBox:       %d %d %d %d\n",shiftx,shifty,int(shiftx+width*s),int(shifty+height*s));
+  fprintf(psfile,"%%%%EndComments\n");
+  fprintf(psfile," /L {  lineto currentpoint stroke newpath moveto} def\n");
+  fprintf(psfile," /M {  moveto } def\n");
+  fprintf(psfile," /C {setrgbcolor} def\n");
+  fprintf(psfile," /rec {newpath 4 copy 8 1 roll moveto 3 -1 roll lineto 4 2 roll exch lineto lineto closepath} def\n");
+  fprintf(psfile," %d %d  translate \n",shiftx,shifty);
+  fprintf(psfile," %f %f  scale \n",s,s);
+  fprintf(psfile," 0 %d 0 %d rec clip newpath\n",int(width),int(height));
+  fprintf(psfile," /Helvetica findfont 10 scalefont setfont\n");
+  fprintf(psfile," /S { show} def\n");
+  fprintf(psfile," /bF  { mark} def \n");
+  fprintf(psfile," /eF {newpath moveto counttomark 2 idiv {lineto} repeat closepath fill cleartomark} def\n");
+  fprintf(psfile," /P { /yy exch def /xx exch def   xx xx 1 add yy yy 1 add  rec  fill } def\n");
+
+  fprintf(psfile," 1 setlinewidth\n");
+	  psfile_save=psfile;
+  }
+}
+void closePS(void)
+{
+  if(psfile_save)   {
+    fprintf(psfile_save,"showpage\n");//fprintf(psfile,"showpage\n");
+    fclose(psfile_save);//fclose(psfile);
+    }
+    
+  psfile=0;
+  psfile_save=0;
+  
+}
+
+  void Commentaire(const char * c)  
+  {
+  if(psfile)   {
+    fprintf(psfile,"%% %s\n",c);
+   }
+  };
+  void NoirEtBlanc(int NB)
+  {
+    if(NB) LastColor=1;
+    else LastColor=ncolortable?ncolortable:2;
+  }
+ 
+  void MettreDansPostScript(int in)
+   {
+     if(in)  psfile=psfile_save;     
+     else   psfile=0;
+   }
+
+// Various works when the program will end
+void myexit(int err)
+{
+ 	time_t ltime;         // write the time stump in console
+ 	struct tm *now;
+ 	time(&ltime);           // write the end time
+ 	now = localtime(&ltime);
+ 	cout << "\nEnd Time: " << asctime(now) << endl;
+
+  if (err==0) {  // normal end
+		cout << "end No Error " << endl << flush ;
+	}
+  else  
+  	cout << "end by Error (no.=" << err << ')' << endl;
+  rattente(1);
+	
+  if (GetConsoleBuff()==FALSE)
+ 		FatalErr("Log file creation error !",0);
+ 	if (!(winf_flg&winf_NOEDIT)) EditLog();
+
+  if (INITGRAPH)
+   closegraphique();
+ 
+ 	FreeConsole();
+	PostQuitMessage(0);
+ 	exit(err);
+}
+
+// initialize the console
+void SetcppIo()
+{
+  FILE *fp=NULL,*fin=NULL;
+  // Get the standard output
+   fin = GetConsoleHandle(STD_INPUT_HANDLE);   
+   if(fin!=NULL)
+     *stdin = *fin;
+   
+   // get the standard output
+   if((fp = GetConsoleHandle(STD_OUTPUT_HANDLE)) == NULL)
+     *stdout = *fp;
+   freopen("conin$", "r", stdin);
+   freopen("conout$", "w", stdout);
+   // freopen("conout$", "w", stderr);
+   
+   using namespace __gnu_cxx;
+   stdio_filebuf<char> * ccout = new stdio_filebuf<char>(stdout, std::ios_base::out);
+   //static  stdio_filebuf<char> ccerr(stderr, std::ios_base::out);
+   stdio_filebuf<char> *ccin= new stdio_filebuf<char>(stdin, std::ios_base::in);
+   
+   cout.rdbuf(ccout);
+   cin.rdbuf(ccin);
+   cerr.rdbuf(ccout);
+   ios::sync_with_stdio();
+}
+BOOL inittext(VOID)
+{
+
+  OSVERSIONINFO osVer; // for GetVersionEx()
+
+  osVer.dwOSVersionInfoSize = sizeof(osVer);
+  GetVersionEx(&osVer);
+  if (osVer.dwPlatformId == VER_PLATFORM_WIN32s) {
+    MessageBox(NULL, 
+        "This FreeFEM++ cannot run on Windows 3.1.\n"
+        "This application will now terminate.",
+        "Error: Windows NT or Windows 95 Required to Run",  MB_OK );
+        return FALSE;       // Console API is not able in Windows 3.1 
+    }
+
+  // FreeConsole();          // If the console is already used
+   AllocConsole();         // Use the console API
+   SetcppIo();
+
+   /*
+   freopen("conin$", "r", stdin);
+   freopen("conout$", "w", stdout);
+   freopen("conout$", "w", stderr);
+   */
+
+   SetConsoleTitle(PACKAGE_STRING  " console");
+   return TRUE;
+}
+
+//*------- Modules for MS-Windows
+//*OT  12/3/1999
+//* Get the buffer of the console
+//* The buffer is stored in the filename.log 
+BOOL GetConsoleBuff()
+{
+  CONSOLE_SCREEN_BUFFER_INFO csbi; //* to get buffer info
+  GetConsoleScreenBufferInfo(hConOut, &csbi);
+
+  COORD coordLine = {0,0};
+  CHAR *szLine;  //* buffer to read from the console (a line)
+  DWORD dwCharsRead;
+  char fname[255];
+  FILE *fp;
+  strcpy(fname,ChangePdeToExt(shortName,"log"));
+  if ((fp = fopen(fname,"w"))==NULL) {
+		perror(fname);
+     return FALSE;
+	}
+	
+  szLine = (CHAR *)malloc((csbi.dwSize.X+1) * sizeof(CHAR));
+  for (int i=0; i<csbi.dwCursorPosition.Y; i++) {
+  	if (ReadConsoleOutputCharacter(hConOut, szLine,
+              csbi.dwSize.X, coordLine, &dwCharsRead)== FALSE) {
+       				perror("ReadConsoleOutputCharacter");
+              return FALSE;
+    }
+    int j=csbi.dwSize.X-1;
+    while ((szLine[j] == ' ') && (j > 0)) szLine[j--] =0;
+    if (j < csbi.dwSize.X-1) szLine[j+1] = '\n'; 
+    fprintf(fp,"%s",szLine);
+    coordLine.Y++;
+  }
+  fclose(fp);
+  return TRUE;
+}
+
+//*OT  12/3/1999
+//* Open the filename.log by the editor
+//* default editor is notepad.exe
+//* Using variable "ffemEd", we can change the editor 
+BOOL EditLog()
+{
+  char *editor, fname[256], cmdLine[255];
+  
+  strcpy(fname,ChangePdeToExt(shortName,"log"));
+  editor = getenv("ffed");
+  if (editor == 0)
+  	sprintf(cmdLine,"notepad.exe %s",fname);
+	else
+	  sprintf(cmdLine,"%s %s",editor,fname);
+
+  if (WinExec(cmdLine,SW_SHOWNORMAL) < 31) {
+  	sprintf(errbuf,"Cannot execute [%s]",cmdLine);
+  	FatalErr(errbuf,99);
+  	return FALSE;
+  }
+  FreeConsole();
+  return true;
+}
+
+void Usage()
+{
+   cout << "Usage: freefem++ [options]" << endl;
+   cout << "Select a program file by the dialog box if option is omitted.\n[option]" << endl;
+   cout << "-f filename: Run the program file \"filename\"." << endl;
+   cout << "    In this mode, all plotted datas are stored in the \".\\cache\"." << endl;
+   cout << "    The stored datas are used in \"WinfFEM\" (IDE for freefem+)." << endl;
+   cout << "    You can get this from  <http://barnard.cs.hkg.ac.jp>." << endl;
+   cout << "-s    : No wait at end." << endl;
+   cout << "-b    : Do not use the color" << endl;
+   cout << "-n    : Do not open the log file at end. The editor is the notepad if you do not" << endl;
+   cout << "        set \"ffed=[name of editor]\" in environments." << endl;
+   cout << "-h    : Display the usage (this)." << endl;
+}
+
+// freefem+  arg1  arg2 arg3
+// Hack the args and analysis 
+int StoreFname(char Line[], int len)
+{
+  char msg[256]; char *ext;
+
+  // ALH - 2/6/04 - add treatments for names surrounded with quotes
+  // (but still breaks on names including quotes).
+  char stopchar = ' ';
+  bool skipone = false;
+  if(Line[0] == '"' || Line[0] == '\''){
+    stopchar = Line[0];
+    skipone = true;
+  }
+
+  // Copies the name string, including its surrounding quotes if
+  // necessary.
+  int i;
+  int j=0;
+  for (i=0; i<len; i++){
+    if (Line[i] != stopchar) fullName[j++] = Line[i];
+    else{
+      if(skipone) skipone = false;
+      else break;
+    }
+  }
+  fullName[j] = '\0';
+ 	
+  ofstream check(fullName,ios::in);
+  if (!check.is_open()) {
+    sprintf(msg,"\"%s\" does not exist!",fullName);
+    FatalErr(msg,-1);
+  }
+  else check.close();
+ 	   
+  ext = strrchr(fullName,'.'); ext++;
+  /*
+  if (toupper(*ext) != 'E'
+      || toupper(*(ext+1)) != 'D'
+      || toupper(*(ext+2)) != 'P') {
+    sprintf(msg,"\"%s\" is not a FreeFem++ script!",fullName);
+    FatalErr(msg,-1);
+  }
+*/	
+  GetFileName(fullName,shortName);
+  return i;
+}
+
+// freefem+  arg1  arg2 arg3
+// Hack the args and analysis 
+DWORD GetOption(char lpszCmdLine[])
+{
+  int i = 0;
+  int CmdLen = strlen(lpszCmdLine);
+  DWORD dwStyle = WS_OVERLAPPEDWINDOW;
+  cout << "getOp: " ;
+  while (i < CmdLen) { 
+    cout << lpszCmdLine[i] ;
+    while (lpszCmdLine[i] == ' ')
+      i++;
+    if (lpszCmdLine[i] == '-') {
+      i++;
+      switch(lpszCmdLine[i]) {
+      case 'f':
+      	i++;
+      	while (lpszCmdLine[i] == ' ')
+	  ++i;
+      	i += StoreFname(&lpszCmdLine[i],CmdLen-i);
+	winf_flg |= winf_VFFEM;
+      	break;
+      case 'v':
+      {  string vv;
+	  char c;
+	  while  (i < CmdLen &&( (isspace(c=lpszCmdLine[i++])&& vv.length()>0 )||isdigit(c) ))
+	    if(isdigit(c)) vv+= c;
+	  verbosity=atoi(vv.c_str());	  
+      }
+      case 's':  // not wait at end of execution
+	winf_flg |= winf_NOWAIT; ++i;
+	break;
+      case 'b':	// no color
+	winf_flg |= winf_NOCOLOR; ++i;
+	break;
+      case 'n':
+	winf_flg |= winf_NOEDIT; ++i;
+	break;
+      case 'h':
+	winf_flg |= winf_Usage; ++i;
+	break;
+      default:
+	while (lpszCmdLine[i]!=' ' && (i < CmdLen))
+	  i++;
+      }
+    }
+    else  {
+      i += StoreFname(&lpszCmdLine[i],CmdLen-i);
+      break;
+    }
+  }
+  cout << " v = " << verbosity << endl;
+  return 0;
+}
+
+/*
+ * Init     
+ *     Initialization for the program is done here:
+ *     1)  Register the window class (if this is the first instance)
+ *     2)  Create the desktop window for the app.
+ *     3)  Show the desktop window in the manner requested by the User.
+ *
+ */
+BOOL Init(HINSTANCE hInstance,   HINSTANCE hPrevInstance,
+    LPSTR  lpszCmdLine, int    nCmdShow) 
+{
+  DWORD dwStyle = WS_OVERLAPPEDWINDOW;
+
+  if (!hPrevInstance)
+  {
+    /*  Register Class for First Overlapped Window  */
+    rClass.lpszClassName = "FreeFem++" ;
+    rClass.hInstance     = hInstance;
+    rClass.lpfnWndProc   = OpenWindowProc1;
+    rClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
+    rClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
+    rClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+    rClass.style         = 0x4000;
+    rClass.cbClsExtra    = 0;
+    rClass.cbWndExtra    = 0;
+
+    if (!RegisterClass( &rClass))
+      return FALSE;
+    }
+  int dd=600;
+  int ddx0=200;
+  int ddy0=30;
+//  long dwFlags;
+/*  DEVMODE dev_mode = {0};
+  if(!EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dev_mode))
+	{
+	   cout  << " screen size ??  " << dev_mode.dmPelsWidth << " x " << dev_mode.dmPelsHeight << endl;
+	   dd = Min(dev_mode.dmPelsWidth*0.7,dev_mode.dmPelsHeight*0.9);
+	   ddx0 = dev_mode.dmPelsWidth*0.28;
+	   ddy0=dev_mode.dmPelsHeight*0.05;	   
+	}
+  else cout << " Error EnumDisplaySettings => no screen size " << endl;
+  
+  */
+  int sx = GetSystemMetrics(SM_CXSCREEN);
+  int sy = GetSystemMetrics(SM_CYSCREEN);
+  dd = static_cast<int>(Min(sx*0.7,sy*0.9));
+  ddx0 = static_cast<int>(sx*0.28);
+  ddy0 = static_cast<int>(sy*0.05);	   
+  
+  //cout << " Screen Size " << sx << " x " << sy << endl;
+ // Rectangle  ss=Get_VirtualScreen();
+ //  dd=(Abs(ss.get_Top-ss.get_Bottom())*90)/100;
+ 
+  GetOption(lpszCmdLine);
+  hWnd = CreateWindow("FreeFEM++",
+      PACKAGE_STRING " for Windows",
+      dwStyle,ddx0,ddy0,dd,dd,/*
+      CW_USEDEFAULT,
+      CW_USEDEFAULT,
+      CW_USEDEFAULT,
+      CW_USEDEFAULT,*/
+      NULL,
+      NULL,
+      hInstance,
+      NULL);
+
+  
+  if (*fullName == '\0' && (winf_flg != winf_Usage)) { // in command line, there is no filename
+    if (ShowOpenDialogBox(shortName)==FALSE) {
+       exit(0);
+    }
+    strcpy(fullName,shortName);
+  }
+  
+  if (inittext()==FALSE) 
+    myexit(1);
+  else if (winf_flg & winf_VFFEM ) { // create only cache, option "-f" is given
+   if (!getcwd(FreeFemCache,MAX_PATH)) {
+     FatalErr("Fail to get current path",-1);
+   }
+   strcat(FreeFemCache,"\\cache\\");
+
+   if (chdir(FreeFemCache)) {  // check the cache directory
+#ifndef __CYGWIN__
+     if (mkdir(FreeFemCache)) {
+#else
+     if (mkdir(FreeFemCache,0777)) {
+#endif
+       sprintf(errbuf,"Fail to create the directory %s",FreeFemCache); 
+       FatalErr(errbuf,-1);
+     }
+   }
+   else (chdir("..\\"));  // already created
+   return TRUE;
+  };
+  
+  return TRUE;
+}
+
+/* OpenWindowProc1 - Handles messages for the main window.
+ *     Parameters:
+ *         hWnd    - Handle to Window which message is delivered to.
+ *         msgID   - ID number of message
+ *         wParam  - 16-bit parameter
+ *         lParam  - 32-bit parameter
+ *
+ */
+LONG WINAPI OpenWindowProc1(
+    HWND    hWnd,
+    UINT    wMsgID,
+    WPARAM  wParam,
+    LPARAM  lParam)
+{
+  switch (wMsgID) {
+    case WM_DESTROY:
+      PostQuitMessage(0);
+ 			DestroyWindow(hWnd);
+      break;
+    default:
+      return DefWindowProc(hWnd, wMsgID, wParam, lParam);
+  }
+
+  return 0;
+}
+
+
+//*OT  29/12/98
+// Routines and functions for WinfFEM
+int  chkCacheDir();
+BOOL TestProjetPresence(char *shortName);
+BOOL CreateProjetFile(char *shortName);
+BOOL SaveLogFile(char *fileName);
+void GetOption(int argc, char *argv[]);
+FILE *projet=NULL;
+// end 
+
+
+int WINAPI WinMain(HINSTANCE  hInstance,
+        HINSTANCE hPrevInstance,
+        LPSTR  lpszCmdLine,  // int argc, char *argv[]
+        int    nCmdShow)
+{
+  MSG msg;
+  
+  LPTSTR cmd = GetCommandLine();
+  if (Init(hInstance, hPrevInstance,lpszCmdLine,nCmdShow)) {
+		// main after checking options
+		if (mainFreeFEM() == FALSE)
+		   myexit(99);	// exit with error
+		else myexit(0);
+
+   	while (GetMessage(&msg,NULL,0,0)) {
+    	TranslateMessage(&msg);
+   		DispatchMessage(&msg);
+  	}
+  	myexit(msg.wParam);  // exit(msg.wParam);
+	}
+	return -1;
+}
+// the real main 
+
+
+extern int mymain(int argc,char **argv);
+
+// main() in FreeFEM+ for PCs
+BOOL mainFreeFEM()
+{
+ char prjName[256]; 
+
+ if (winf_flg & winf_VFFEM) {	// given by "-f filename"
+  strcpy(prjName,ChangePdeToExt(shortName,"prj"));
+
+  if (strcmp(FreeFemCache,"")!=0)
+      if (CreateProjetFile(prjName)==FALSE)
+        FatalErr(prjName,-1);
+ }   
+ 
+ cout << "Welcome to freefem++ v " << StrVersionNumber() <<endl;
+ cout << "Program file [" << fullName <<']'<< endl;
+ time_t ltime;         // write the time stump in console
+ struct tm *now;
+ time(&ltime);
+ now = localtime(&ltime);
+ cout << "Start Time: " << asctime(now) << endl;
+ ShowWindow(hWnd,SW_SHOW);
+ initgraphique();
+ int argc;
+ char * argv [3];
+ argc = 2;
+ argv[0]= "FreeFem++";
+ argv[1]= fullName;
+// int main (int  argc, char **argv)
+ int ret=1;
+ try {
+ 	//compile(fullName);
+ 	ret=mymain(argc,argv);
+ 	cout << fullName << endl;
+ 	rattente(1);
+ 	
+ 	rattente(1);
+ 	} catch(Error &e){
+	  ret=e.errcode();
+	  cout<<" error "<<e.what(); myexit(1); };                   
+ 
+ if (projet!=NULL)
+  fclose(projet);
+
+ SetWindowText(hWnd,"End of FreeFEM++");
+ if (winf_flg & winf_NOWAIT) {	// option "-s" 
+   	myexit(ret);
+ };
+  return ret==0;
+}
+
+// error without console
+BOOL FatalErr(char *s, int err)
+{
+  int ret;
+  UINT Style = MB_SYSTEMMODAL|MB_ICONEXCLAMATION;
+
+  if (err==0) Style |= MB_YESNO;
+  else Style |= MB_OK;
+
+  ret = MessageBox(NULL,s,"Information from FreeFEM++",Style);
+
+  if (!err & (ret ==IDYES)) return TRUE;
+  else if (!err & (ret == IDNO)) return FALSE;
+  else if (err != 99) exit(err);
+  return TRUE;
+}
+
+
+//*OT
+// Modules for debug console and log
+void SetConsole(HANDLE hConsole)
+{
+	SMALL_RECT srctWindowRect;
+	COORD  coordScreen;
+
+	srctWindowRect.Left = 10;
+	srctWindowRect.Top = 10;   
+	srctWindowRect.Bottom = 500;
+	srctWindowRect.Right = 320;
+	SetConsoleWindowInfo(hConsole, TRUE, &srctWindowRect);
+	coordScreen.X = 80;		// buffer size 80x1000
+	coordScreen.Y = 1000;
+	SetConsoleScreenBufferSize(hConsole,coordScreen);
+}
+
+// the console handle to stdout 
+FILE *GetConsoleHandle(DWORD Device)
+{
+  int Crt;
+  FILE *Console = NULL;
+
+  if ((hConOut = GetStdHandle(Device)) != INVALID_HANDLE_VALUE) {
+
+    // _open_osfhandle() is not in cygwin
+
+#if !defined(__CYGWIN__)
+    Crt = _open_osfhandle((long)hConOut, _O_TEXT);
+    if (Device == STD_INPUT_HANDLE) Console = fdopen(Crt, "r");
+    else Console = fdopen(Crt, "w");
+#else
+    if (Device == STD_INPUT_HANDLE) Console = fdopen(0,"r");
+    else Console = fdopen(1,"w");
+#endif
+
+    setvbuf(Console, NULL, _IONBF, 0);
+    SetConsole(hConOut);
+  }
+
+  return Console;
+}
+
+
+int GetFileName( char *fullname,
+    char  *shortname)  // filename
+{
+    int   i, j, k;
+    int   tail=0;
+
+    ifstream test(fullname,ios::in);
+    if (!test.is_open()) {
+      cout << "File " << fullname << "do not exist !" << endl;
+         return FALSE;
+    }
+
+    strcpy( shortname , "\0" )  ;
+
+    tail = strlen( fullname ) ;
+
+    if  ( tail == 0 )   return -1 ; // return by nothing
+
+    for ( i = tail - 1 ; i >= 0 ; i-- ) { // loop 1
+       if  ( fullname[i] == '\\' ) {
+       for ( j = i+1, k=0 ; j < tail ; j++, k++ )
+          *(shortname + k) = *(fullname + j ) ;
+         *(shortname + k) = '\0';
+       break;
+      }
+  }
+  if (i == -1)
+    strcpy(shortname,fullname);
+
+   return 0  ; // OK!
+}
+
+
+void ShowHelp(const char * s,int k)
+{
+  if(k) {
+    MettreDansPostScript(0);
+    couleur(1);
+    float xmin,xmax,ymin,ymax;
+    getcadre(xmin,xmax,ymin,ymax);
+    rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+    plotstring(s);
+    MettreDansPostScript(1);
+       //  couleur(1);	
+  }
+}
+
+char *ChangePdeToExt(char *fileName,char *ext)
+{
+ int len;
+  
+ len=strlen(fileName);        
+ char *file = new char[len+1];
+ for(int i=0; i<len; i++) *(file+i) = *(fileName+i);
+ file[len-4]='.';
+ file[len-3]=ext[0];
+ file[len-2]=ext[1];
+ file[len-1]=ext[2];
+ file[len]='\0';
+ return file;
+} 
+
+BOOL CreateProjetFile(char *fileName)
+{
+ char chemin[256];
+
+ strcpy(chemin,FreeFemCache);
+ strcat(chemin,ChangePdeToExt(shortName,"prj"));
+ if (projet=fopen(chemin,"w"),!projet)
+     return FALSE;
+ fprintf(projet,"FFF at WinfFEM@FFF\n");                         
+ return TRUE;
+}
+
+//* the module for graph.cpp
+int NbMeshTotal=1, NbPlotTotal=1;
+
+float GetHeigthFont()
+{
+    return (float)fontH/echy;
+}
+
+//* store all data created in graph.cpp
+
+// Chack the mesh which will be stored in the cache
+// return TRUE  (if it is same)
+// else return FALSE  
+/*
+BOOL CheckSameTrig(Grid& t)
+{
+  static struct {  // store the information of the mesh
+    float x;  float y;  int w;
+  }  p[3] = { {0,0,0}, {0,0,0}, {0,0,0}};  // three virteces
+  static int nv = 0, nt = 0;  // numbers of the virteces and the triangles
+
+  if ((nv != t.nv) || (nt != t.nt))
+    goto SET;
+  if ((t.v[0].x != p[0].x) || (t.v[0].y != p[0].y) || (t.v[0].where != p[0].w))
+    goto SET;
+  if ((t.v[nv/2].x != p[1].x) || (t.v[nv/2].y != p[1].y) || (t.v[nv/2].where != p[1].w))
+    goto SET;
+  if ((t.v[nv-1].x != p[2].x) || (t.v[nv-1].y != p[2].y) || (t.v[nv-1].where != p[2].w))
+    goto SET;
+  else return TRUE;
+
+SET:
+ nv = t.nv;  nt = t.nt;
+ p[0].x = t.v[0].x; p[0].y = t.v[0].y; p[0].w = t.v[0].where; 
+ p[1].x = t.v[nv/2].x; p[1].y = t.v[nv/2].y; p[1].w = t.v[nv/2].where; 
+ p[2].x = t.v[nv-1].x; p[2].y = t.v[nv-1].y; p[2].w = t.v[nv-1].where; 
+ return FALSE;
+}
+
+
+// ohtsuka 8/23/98
+ void SaveMesh(Grid& t)
+{
+ char chemin[256],meshName[256];
+ int i,j=0;
+ 
+ if (!(winf_flg&winf_VFFEM)) return;
+ if (CheckSameTrig(t)==TRUE)
+   return;
+
+ strcpy(chemin,FreeFemCache);
+ sprintf(meshName,"%d-%s",NbMeshTotal++,ChangePdeToExt(shortName,"msh"));
+ strcat(chemin,meshName);
+ 
+ ofstream mesh(chemin,ios::out);
+ if (mesh.is_open())  {
+   mesh << "FFF at WinfFEM_MESH@FFF" << endl;
+   fprintf(projet,"%s\n",meshName);
+   mesh << t.nv << "	" << t.nt << endl;
+   for( i=0; i<t.nv; i++ ) {
+      mesh << t.v[i].x <<"	"<< t.v[i].y <<"	"
+           << t.v[i].where << endl;
+   }
+
+   for( i=0; i<t.nt; i++ ) {	
+       mesh << t.no(t.t[i].v[0]) <<"	"<< t.no(t.t[i].v[1]) <<"	"<< t.no(t.t[i].v[2]) <<"	"<< j<<endl;
+   }
+ } else {
+   cout << "Unable to SAVE MESH for WinfFEM !" << endl;
+   return;
+  }
+  NbPlotTotal=1;
+  mesh.close();
+} 
+
+void SavePlot(int D,Grid& t, Real *f)
+{                                    
+ char chemin[256],plotName[256];
+ int i;
+ 
+ if (!(winf_flg&winf_VFFEM)) return;
+ if (f == NULL) return;
+ strcpy(chemin,FreeFemCache);
+ sprintf(plotName,"%d-%d%s",NbMeshTotal-1,NbPlotTotal,ChangePdeToExt(shortName,"fnc"));
+ strcat(chemin,plotName);
+
+ ofstream plot(chemin,ios::out);
+ if (plot.is_open()) {
+   fprintf(projet,"%s\n",plotName);
+   plot << "FFF at WinfFEM_PLOT@FFF" << endl;          
+   plot << NbMeshTotal-1 << "-" << ChangePdeToExt(shortName,"msh") << endl;
+   plot << D << endl;
+   plot << t.nv << endl;
+   for (i=0; i<t.nv; i++) 
+     plot << t.v[i].where << "  " << f[i] << endl;
+ } else {
+   cerr << "Unable to SAVE PLOT for WinfFEM !" << endl;
+   return;
+ }
+ NbPlotTotal++;
+}                         
+*/
+void  viderbuff(){;}
+
+//*OT July 7 2000
+//This module is used in analyse.cpp "system"
+//
+#include <shellapi.h>
+#define MAXPATH  256
+char * getOp(const char *what)
+{
+    int   tail=0, len=0;
+    char  *p;
+
+    p = strrchr(what, '\\');
+    if (p == NULL) p = (char *)what;
+    while (*p && (*p != ' '))  p++;
+    if (*p) *p++ = '\0';
+    else return NULL;
+    while (*p && (*p == ' '))  p++;
+    if (*p) return p;
+    else return NULL;
+}
+
+#ifdef   WWWWWWWWWWWWWWWWWWWW
+int execute(const char* what)
+{
+  char szBuffer[MAXPATH + 1];
+  char *option;
+  int r=0; 
+  char *vide="";
+  option = getOp(what);
+  if(!option) 
+    option = vide;
+  cout << "excute :: " <<what << "  ## " << option << endl;
+  if (*what) {
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    ZeroMemory( &si, sizeof(STARTUPINFO) );
+    ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );
+    si.cb=sizeof( STARTUPINFO );
+    si.dwFlags = STARTF_USESHOWWINDOW;
+    si.wShowWindow = SW_SHOWNORMAL;
+    
+    CreateProcess(what,option,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi );
+    if( pi.hProcess )	{
+      WaitForInputIdle( GetCurrentProcess(), INFINITE );
+      DWORD dwExitCode = STILL_ACTIVE;
+      while(dwExitCode == STILL_ACTIVE)	{
+	WaitForSingleObject( pi.hProcess, 1000 );
+	GetExitCodeProcess( pi.hProcess, &dwExitCode );
+      }
+      CloseHandle(pi.hProcess);
+      CloseHandle(pi.hThread);
+    }
+    else {
+      sprintf(szBuffer,"%s: cannot execute",what);
+      if (option != NULL) sprintf(szBuffer,"%s  with option %s!",szBuffer, option); 
+      MessageBox(NULL, szBuffer, "Error in FreeFem++", MB_OK | MB_ICONINFORMATION);
+      r=1; 
+    }
+  }
+  else r=2,MessageBox(NULL, "Error in system()", "Error in FreeFem++", MB_OK | MB_ICONINFORMATION);
+  return r;
+}
+#else
+int  execute (const char * str)
+{ 
+ cout << "exec: " << str << endl;
+ return  system(str);
+}
+#endif
+
+
+void setgrey(bool gg ){grey=gg;}
+int getgrey(){ return grey;}
diff --git a/src/Graphics/Xrgraph.cpp b/src/Graphics/Xrgraph.cpp
new file mode 100644
index 0000000..9f23b27
--- /dev/null
+++ b/src/Graphics/Xrgraph.cpp
@@ -0,0 +1,1209 @@
+/********** DO NOT REMOVE THIS BANNER **********/
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR:   D. Bernardi, F. Hecht,  O. Pironneau ,    Y. Darmaillac                      
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/******************************************************************/
+const char * edpfilenamearg=0;	 	
+bool  waitatend=true;
+bool  consoleatend=true;
+
+#define FF_GRAPH_SET_PTR
+#include <math.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <cassert>
+#include "strversionnumber.hpp"
+using namespace std;
+
+#define MAXSHORT 0xFFFF
+
+#ifdef HPPA
+#ifndef __GNUC__
+typedef char *caddr_t;
+#endif
+#endif
+#ifdef __MWERKS__
+#include <Xlib.h>
+#include <Xutil.h>
+#include <Xos.h>
+#include <Xatom.h>
+#include <keysym.h>
+#include <cursorfont.h>
+#else
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+#endif
+#undef index 
+#include "rgraph.hpp"
+
+#ifdef macintoshxx
+#include <ConditionalMacros.h>
+#include <unix.h>
+#else
+#include <sys/stat.h>
+#endif
+
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+
+
+static  long  cube6[7][3] ={ { 65535,32000,32000},{ 65535, 65535,0},{0, 65535,0},{0, 65535, 65535},{0,0, 65535}
+     , { 65535,0, 65535},{ 32000,0,0} }; 
+static  long grey6[2][3] ={ {65534,65534,65534},{0,0,0} }; 
+
+static FILE *psfile = 0;
+static FILE *psfile_save = 0;
+static bool grey=false;
+static int LastColor=2;  //  pour est en couleur par defaut
+
+const float fMinPixel = -32000;
+const float fMaxPixel = +32000;
+#define reel float 
+static  Display *display;
+static  Window win;
+static  XSizeHints size_hints;
+// static  XEvent report;
+static int ncolortable,fcolor;
+static XColor *colortable;
+static  GC gc;
+static  XFontStruct *font_info;
+static int shift, control,shiftlock,alt;
+static reel echx,echy,rxmin,rxmax,rymin,rymax;
+static int  lacouleur,screen, width, height, currx, curry;
+static unsigned long  background,foreground;
+static Cursor cursor_watch,cursor_arrow;
+static long NbErrX11 =0;
+Colormap color_map,color_map_sys;
+#define call(i) i
+static  Visual *visual;
+static int INITGRAPH=0;
+void myend()
+{
+ if (INITGRAPH)
+   closegraphique();
+  cout << "the end" <<endl;
+//  ExitToShell();
+}
+void myexit(int err) { 
+  cout << " The End err=" << err << endl;
+  exit(err);}
+
+#ifdef FREEFEM
+#include <fstream.h>
+#include <new.h>
+
+void out_of_memory ();
+void myexit(int );
+void compile(char *fname);
+
+
+int main (int argc, char **argv)
+{
+  atexit(myend);
+  int OPTION = 0;
+  if (argc == 2)
+    {
+       printf ("PROGRAM  FreeFem 1.0 %s \n",argv[1]);
+       initgraphique();
+       compile (argv[1]);
+       closegraphique();
+    }
+  else
+    printf ("To launch freefem you must type freefem  and a file name\n");
+  return 0;
+}
+#else
+extern int mymain(int argc,char **argv);
+int main (int argc, char **argv)
+{
+ return mymain(argc,argv);
+}
+
+#endif
+
+void message(char *s)
+{  printf("%s	\n",s);}
+
+void erreur(char *s)
+{ message(s); exit(0);}
+
+void *safecalloc(size_t nb, size_t  size)
+{
+  void* p=NULL;
+  p = calloc(nb, size);
+  if (p == NULL) printf("Run out of Memory!\n");
+  return p;
+}
+
+void safefree(void** f)
+{
+  if(*f){ free((char*) *f); *f=NULL;}
+}
+
+void rflush()
+{
+  XEvent report;
+  XNextEvent(display, &report);
+  if (report.type == Expose)
+    while (XCheckTypedEvent(display, Expose, &report));
+  
+  XFlush(display);
+}
+
+int xerror  (Display *display,XErrorEvent * myerr)
+{
+  if (NbErrX11++<10) {
+  char msg[80];
+  XGetErrorText(display, myerr->error_code, msg, 80);
+  fprintf(stderr, "Error code %s\n", msg);}
+  return 0;
+}
+
+/*
+void xerror()
+{
+  fprintf(stderr, "Probleme avec X-Windows\n");
+  assert(0);
+}
+*/
+void xerrorio()
+{
+  
+  fprintf(stderr, "Fatal erreur avec X-Windows\n");
+  assert(0);
+  exit(2);
+}
+void  MyXSelectInput(Display * dpy,Window w,int  mask)
+
+{
+  XSetWindowAttributes attributes;
+  attributes.event_mask = mask;
+  XChangeWindowAttributes(dpy, w, CWEventMask, &attributes);
+}
+int LaCouleur() {return  lacouleur;}
+
+void couleur(int c)
+{ 
+  if ( lacouleur == c) // small optim
+    return;
+
+  c= c > LastColor ? 1 : c; // c=Min(c,LastColor); pour noir et blanc
+ lacouleur = c;
+ if (colortable)
+   { 
+     if (c>=0 && c < ncolortable)
+       XSetForeground(display,gc,colortable[c].pixel);
+     else 
+       XSetForeground(display,gc,foreground);
+   }
+else
+  if ( c == 0 )
+    XSetForeground(display,gc,background);
+  else
+    XSetForeground(display,gc,foreground);
+ if (psfile)
+  {
+    float r=1,g=1,b=1;
+    if (colortable) {
+      if (c>0 && c < ncolortable)
+	{
+	  r =  (float) colortable[c].red /65535.;
+	  g =  (float) colortable[c].green /65535.;
+	  b =  (float) colortable[c].blue /65535.;
+	}
+    }
+    else if (c!=0)
+      r=g=b=0;
+    
+    fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b);
+  }
+}
+
+
+static XColor DefColorX11( int k,int nb, bool hsv,bool grey,int nbcolors,float *colors)
+{
+ XColor C;
+ float r,g,b;
+extern void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool grey,int nbcolors,float *colors);
+ DefColor(r,g,b,   k,nb,hsv,grey,nbcolors,colors);
+ C.red=65535*r;
+ C.green=65535*g;
+ C.blue=65535*b;
+ C.flags = DoRed | DoGreen | DoBlue;
+ C.pixel=k;
+ // cout << " color : " << k << " " << C.red << " "<< C.green << " " << C.blue << " " << r << endl; 
+ return C;
+} 
+
+void SetColorTable1(int nb,bool hsv,int nbcolors,float *colors)
+{
+  static bool greyo = !grey;
+  static float * colorso =0;
+  if(!INITGRAPH) return;
+   if (ncolortable == nb && greyo == grey && colorso == colors ) return;// optim
+   greyo = grey;
+   colorso=colors;
+   if (fcolor  && nb>2 && nb < 256) 
+     { 
+       if(colortable) delete [] colortable;
+       colortable = new XColor[nb];
+       ncolortable = nb;
+       if(LastColor>1) LastColor=nb-1;
+        for (int i0=0;i0<nb;i0++)
+         {  
+           colortable[i0]=DefColorX11(i0,nb,hsv,grey,nbcolors,colors);           
+          }
+        background=0;
+        foreground=1; 
+       if (visual->c_class != TrueColor)
+	 {
+	   // cout << "XStoreColors( not TrueColor)" << ncolortable << " "  <<
+	     XStoreColors (display, color_map, colortable, ncolortable) ;
+	       //	<< endl;
+	 }
+       else 
+	 {
+	   // cout << "XAllocColor (TrueColor)" << endl; 
+	   for (int i=0;i<ncolortable;i++)
+	     XAllocColor(display, color_map, colortable+i );
+	   background =colortable[background].pixel;
+	   foreground =colortable[foreground].pixel;
+	 }
+       if (win) {
+	 XGCValues gcvalues;
+	 gcvalues.foreground = foreground;
+	 gcvalues.background = background;
+	 gc = XCreateGC(display, win, GCForeground | GCBackground , &gcvalues);
+       }
+       }
+}
+void SetColorTable(int nb)
+{
+  int i;
+   if (fcolor  && nb>2 && nb < 256) 
+     { 
+       nb = Max(nb,8);
+       if (ncolortable == nb) return;// optim
+       if(colortable) delete [] colortable;
+       colortable = new XColor[nb];
+       ncolortable = nb;
+       if(LastColor>1) LastColor=nb-1;
+       int k=0;
+       colortable[k].pixel=k;
+       colortable[k].red= 65535;
+       colortable[k].green= 65535;
+       colortable[k].blue= 65535;
+       colortable[k].flags = DoRed | DoGreen | DoBlue;
+       background=k;
+       k++;
+       colortable[k].pixel=k;
+       colortable[k].red=0;
+       colortable[k].green=0;
+       colortable[k].blue=0;
+       colortable[k].flags = DoRed | DoGreen | DoBlue;
+       foreground=k;
+       k++;
+       nb = nb -2;
+       for (long i0=0;i0<nb;i0++,k++)
+         {  
+	   //     long  i1 = nb - i0;
+	   long  i6 = i0*6;
+	   long  j0 = i6/nb;// in 0..6
+	   long  j1 = j0+1;// in 1..6
+	   long  k0 = i0 - (nb*j0)/6L;
+	   long  k1 = (nb*j1)/6L-i0;
+	   long  kk = k0+k1;
+	   //	     cout <<k << " " << i0 << " " << j0 << " " << j1 << " " << k0 << " " << k1  << endl;
+           if ( kk <= 0)
+	     { cerr << kk << " " << nb << " " << k0 << " " << k1 << " " << endl;
+	     assert(kk);
+             }
+	   colortable[k].pixel=  (unsigned long) k;
+	   colortable[k].flags = DoRed | DoGreen | DoBlue;
+	   if (! grey)
+         {
+           colortable[k].red   = (unsigned short) ((long) (cube6[j1][0]*k0+cube6[j0][0]*k1)/kk);
+           colortable[k].green = (unsigned short) ((long)  (cube6[j1][1]*k0+cube6[j0][1]*k1)/kk);
+           colortable[k].blue  = (unsigned short) ((long) (cube6[j1][2]*k0+cube6[j0][2]*k1)/kk);
+	   }
+          else 
+           {
+           kk=nb-1;
+           k1 =  i0;
+           k0 = nb - i0 -1;
+           j0=1;
+           j1=0;
+           colortable[k].red   = (unsigned short) ((long) (grey6[j1][0]*k0+grey6[j0][0]*k1)/kk);
+           colortable[k].green = (unsigned short) ((long)  (grey6[j1][1]*k0+grey6[j0][1]*k1)/kk);
+           colortable[k].blue  = (unsigned short) ((long) (grey6[j1][2]*k0+grey6[j0][2]*k1)/kk);
+           }
+	   
+           assert(k<ncolortable);
+	   //   cout <<colortable[k].pixel 
+	   //	<< " r=" <<  colortable[k].red 
+	   //	<< " g=" <<  colortable[k].green
+	   //	<< " b=" <<colortable[k].blue <<endl;
+          }
+       if (visual->c_class != TrueColor)
+	 {
+	   // cout << "XStoreColors( not TrueColor)" << ncolortable << " "  <<
+	     XStoreColors (display, color_map, colortable, ncolortable) ;
+	       //	<< endl;
+	 }
+       else 
+	 {
+	   // cout << "XAllocColor (TrueColor)" << endl; 
+	   for (i=0;i<ncolortable;i++)
+	     XAllocColor(display, color_map, colortable+i );
+	   background =colortable[background].pixel;
+	   foreground =colortable[foreground].pixel;
+	 }
+       if (win) {
+	 XGCValues gcvalues;
+	 gcvalues.foreground = foreground;
+	 gcvalues.background = background;
+	 gc = XCreateGC(display, win, GCForeground | GCBackground , &gcvalues);
+       }
+     }
+
+
+// a faire 
+}
+void FlushEvent()
+{
+  XEvent event;
+  while (XPending(display))
+   XNextEvent(display, &event);
+} 
+
+void initgraphique()
+{
+ int ddd;
+  atexit(myend);
+  win=0;
+  XSetWindowAttributes attributes;
+  NbErrX11=0;
+  XGCValues gcvalues;
+  XEvent report;
+  display = XOpenDisplay(NULL);
+  if (!display) 
+    {
+      cerr << " Erreur openning  display " << endl;
+      exit(2);
+    }
+  colortable=0;
+  ncolortable=0;
+  LastColor=2;// En couleur pas defaul
+  //  modif FH
+  Display *dpy=display;
+  // Colormap color_map,color_map_sys;
+  visual  = DefaultVisual(display, DefaultScreen(display));
+  fcolor=0;  /* pas couleur */
+  int fstereo=0; /* non */
+  int nbplans=visual->bits_per_rgb;
+  color_map_sys = DefaultColormap (display, DefaultScreen (display)); 
+  color_map = color_map_sys;
+  foreground= BlackPixel(display, screen);
+  background= WhitePixel(display, screen);
+
+  switch (visual->c_class)
+	 {
+	 case GrayScale:  {break;}
+	 case PseudoColor: 
+	   { 
+	     cout << " PseudoColor  nbcolor =" << visual->map_entries << endl;
+	     color_map= XCreateColormap (display, RootWindow (display, DefaultScreen (display)),
+					 visual,AllocAll);
+	     // copy the def color map 
+	     for (int i=0;i<visual->map_entries;i++)
+	       {  XColor colorcell_defs;
+	          colorcell_defs.pixel = (unsigned long) i;
+		  XQueryColor (display, color_map_sys, &colorcell_defs);
+		  XStoreColor (display, color_map, &colorcell_defs);
+	       }
+	     fcolor=1;
+	     
+	     SetColorTable(8); // set 
+	     break;
+	   }
+	 case DirectColor:
+	   {
+	     cout << " DirectColor " << endl;
+	     fcolor=1;
+	     SetColorTable(8); // set 
+	     break; 
+	   }
+	 case TrueColor  : 
+	   {
+	     cout << " TrueColor " << endl;
+	     fcolor=1;	     
+	     SetColorTable(8); // set 
+	     break;
+	   }
+	 } 
+  font_info = XLoadQueryFont(display, "6x9");
+  if (!font_info) font_info = XLoadQueryFont(display, "6x10");
+  if( !font_info) {cout << " erreur font 6x10 and 6x9 not found !\n";exit(2);};
+  XSetErrorHandler((XErrorHandler)xerror);
+  XSetIOErrorHandler((XIOErrorHandler)xerrorio);
+  screen = DefaultScreen(display);
+  width = DisplayWidth(display, screen);
+  height = DisplayHeight(display, screen);
+  ddd = width < height ?  width : height;
+  width = ddd*8/10;
+  height =  ddd*8/10;
+
+
+  attributes.background_pixel = background;
+  attributes.border_pixel     = foreground;
+  attributes.backing_store    = Always;
+  attributes.colormap         = color_map;
+
+  win = XCreateWindow(display, RootWindow(display, DefaultScreen(display)),
+		      50, 80, width, height,4,
+		      CopyFromParent, InputOutput, visual,
+		      CWBackPixel | CWBorderPixel | CWBackingStore | CWColormap,
+		      &attributes);
+   char   title[256];
+  sprintf(title,"%s%s","FreeFrem++ ",StrVersionNumber().c_str());
+  XChangeProperty(display, win, XA_WM_NAME, XA_STRING, 8
+                  , PropModeReplace,(const unsigned char *)  title , strlen(title)); 
+
+
+  
+         
+  gcvalues.foreground = foreground;
+  gcvalues.background = background;
+  gcvalues.function   = GXcopy    ;
+  gc = XCreateGC(display, win, GCForeground | GCBackground | GCFunction, &gcvalues);
+  
+  XSetFillRule(display,gc,WindingRule);
+  
+  
+  // win = XCreateSimpleWindow(display, RootWindow(display, screen), 50, 80, width, height, 4,
+  // foreground,background);
+  cursor_arrow = XCreateFontCursor(display,XC_arrow);
+  cursor_watch = XCreateFontCursor(display,XC_watch);
+    
+  size_hints.flags = PPosition | PSize;
+  size_hints.x = 0;
+  size_hints.y = 0;
+  size_hints.width = width;
+  size_hints.height = height;
+
+  XSetFont(display, gc, font_info->fid);
+  XSetForeground(display, gc, foreground); 
+  XMapWindow(display, win);
+  MyXSelectInput (display, win, (int) (ExposureMask
+				       | KeyPressMask
+				       | KeyReleaseMask
+				       | ButtonPressMask
+				       | ButtonReleaseMask
+				       /*                               | ResizeRedirectMask   */
+				       | StructureNotifyMask)
+		  ); 
+  
+  // do XNextEvent(display, &report); while (report.type != Expose);
+  XDefineCursor(display,win,cursor_watch);
+  XFlush(display); 
+  INITGRAPH = 1;
+
+}
+
+void closegraphique()
+{
+  if (INITGRAPH)
+    {
+      INITGRAPH = 0;
+      XUnloadFont(display, font_info->fid);
+      XFreeGC(display, gc);
+      XCloseDisplay(display);
+      closePS();
+    }
+}
+
+void cadre(reel xmin,reel xmax,reel ymin,reel ymax)
+{
+  rxmin = xmin;
+  rxmax = xmax;
+  rymin = ymin;
+  rymax = ymax;
+
+  echx = width / (xmax - xmin);
+  echy = height / (ymax - ymin);
+}
+
+void getcadre(reel &xmin,reel &xmax,reel &ymin,reel &ymax)
+{
+  xmin = rxmin;
+  xmax = rxmax;
+  ymin = rymin;
+  ymax = rymax;
+
+}
+
+
+int InRecScreen(reel x1, reel y1,reel x2, reel y2)
+{  
+
+  return (Max(x1,x2)>= rxmin) && (Min(x1,x2) <= rxmax) && (Max(y1,y2) >= rymin) && (Min(y1,y2)  <= rymax);
+}
+int InPtScreen( reel x, reel y)
+{
+  return (x >= rxmin) && (x <= rxmax) && (y >= rymin) && (y <= rymax);
+}
+
+
+
+
+float scali(int i)
+{
+  return i/echx  + rxmin;
+}
+float scalj(int j)
+{
+  return -j/echy  + rymax;
+}
+int scalx(reel x)
+{
+  return (int) Min(fMaxPixel,Max(fMinPixel,((x - rxmin) * echx)));
+} 
+int scaly(reel y)
+{
+  return (int)Min(fMaxPixel,Max(fMinPixel,((rymax - y) * echy)));
+}
+
+void pointe(reel x, reel y)
+{
+  XDrawPoint(display, win, gc, scalx(x), scaly(y));
+}
+
+void rmoveto(reel x, reel y)
+{
+  currx = scalx(x);
+  curry = scaly(y);
+}
+
+void rlineto(reel x, reel y)
+{
+  int newx = scalx(x), newy = scaly(y);
+  XDrawLine(display, win, gc, currx, curry, newx, newy);
+  if (psfile)
+    fprintf(psfile,"%d %d %d %d L\n",currx, height-curry, newx, height-newy);
+  currx = newx; curry = newy;
+/*   XFlush(display); */
+}
+
+void cadreortho(reel centrex, reel centrey, reel rayon)
+{
+  //  int xasp,yasp;
+
+  if (height < width)
+  {
+    rymin = centrey - rayon;
+    rymax = centrey + rayon;
+    echx = echy= height / (2 * rayon);
+    rxmin= centrex - width / (2 * echx);
+    rxmax= centrex + width / (2 * echx);
+  }
+  else
+  {
+    rxmin = centrex - rayon;
+    rxmax = centrex + rayon;
+    echx = echy = width / (2 * rayon);
+    rymin = centrey - height / (2 * echy);
+    rymax = centrey + height / (2 * echy);
+  }
+}
+
+void plotstring (const char *  string)
+{ int lx,l = strlen(string);
+  XDrawString(display, win, gc, currx, curry , string, l);
+ lx = XTextWidth( font_info,string,l);
+ if(psfile) fprintf(psfile,"(%s) %d %d  S\n",string,currx,height-curry);
+ currx += lx;
+}
+
+void showgraphic()
+{
+}
+
+void x11draw3(int * ptype)
+{
+  XGCValues gcvalues;
+  int type;
+
+  type=  *ptype;
+  switch (type)
+  {
+    case 0  : {gcvalues.line_style = LineSolid;     break;}
+    case 1  : {gcvalues.line_style = LineOnOffDash; break;}
+    default : {gcvalues.line_style = LineDoubleDash;break;}
+  }
+  XChangeGC(display, gc, GCLineStyle, &gcvalues);
+
+  if (psfile) 
+    switch (type) {
+    case 0  : {fprintf(psfile,"[] setdash\n");break;}
+    case 1  : {fprintf(psfile,"[3]  setdash\n");break;}
+    default : {fprintf(psfile,"[4 1] setdash\n");break;}
+    }
+
+}  
+
+void penthickness(int pepais)
+{
+  XGCValues gcvalues;
+  gcvalues.line_width = pepais;
+  XChangeGC(display, gc, GCLineWidth, &gcvalues);
+  if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais);
+}
+
+
+void x11linsrn(int * x1,int * x2,int * y1,int * y2)
+  //int *x1,*x2,*y1,*y2;
+{   
+  XDrawLine(display, win, gc, *x1, *x2, *y1, *y2); 
+/*  call(viderbuff)(); */
+}
+
+   
+void viderbuff()
+{
+  XRaiseWindow (display,win);
+  XFlush(display); 
+}
+
+
+
+void cercle(reel centrex, reel centrey, reel rayon)
+{
+  int r = (int) (rayon * echx);
+  XDrawArc(display, win, gc,
+	   scalx(centrex) - r, scaly(centrey) - r, width, height, 0, 360 * 64);
+  XFlush(display);
+}
+void reffecran()
+{
+ XClearWindow(display,win);
+}
+
+void fillpoly(int n, float *poly)
+{
+  int i;
+  XPoint *poly0,polyloc[10];
+  if(n<10)
+    poly0=polyloc;
+  else
+    if(poly0= (XPoint *) malloc(n*sizeof(XPoint)), !poly)
+  {
+    fprintf(stderr, "Erreur d'allocation dans raffpoly\n");
+    return;
+  }
+  for(i=0; i<n; i++)
+  {
+    poly0[i].x =scalx(poly[2*i]);
+    poly0[i].y =scaly(poly[2*i+1]);
+  }
+  
+  XFillPolygon(display, win, gc, poly0,n, Complex, CoordModeOrigin);
+
+  if( poly0!=polyloc) free((char*)poly0);
+   if (psfile) 
+    {
+     fprintf(psfile,"bF ");
+     for (i=0;i<n;i++)
+      fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1]));
+     fprintf(psfile,"eF\n"); 
+    }
+}
+
+#include "getprog-unix.hpp"
+
+
+int execute (const char * str)
+{ 
+  return system(str);
+}
+
+char Getijc(int *x1,int *y1)
+{ char char1;
+  XEvent event;
+  int flag,nb;
+  XComposeStatus status;
+  char buffer[20];
+  KeySym keysym;   /*  incidence */
+  XDefineCursor(display,win,cursor_arrow);
+  flag=0;
+  while (!flag)
+  { XNextEvent(display, &event);
+    if(event.type == ButtonRelease) 
+    { *x1 = event.xbutton.x;
+      *y1 = event.xbutton.y; 
+      if      (event.xbutton.button == Button1) char1=shift?248:251;
+      else if (event.xbutton.button == Button2) char1=shift?249:252;
+      else                                      char1=shift?250:253; 
+      //     printf(" mouse release %d\n",(int) char1);
+      flag=1;
+    }
+    else if(event.type == KeyPress)
+    { *x1 = event.xkey.x;
+      *y1 = event.xkey.y; 
+      char1= event.xkey.keycode ;
+       keysym=0;
+       nb=XLookupString(&event.xkey,buffer,20,&keysym,&status);
+
+/*        printf("nb= %d keysym= %d buffer=",nb,keysym);
+/*        for(i=0;i<20;i++)
+/*         printf(" %d ",(int)buffer[i]);
+/*        printf("\n");
+*/
+
+/*       voir    /usr/include/X11/keysymdef.h + ap_keysym */
+
+       if (nb != 0) 
+         {char1 = buffer[0];
+          flag= 1; 
+         }
+       else
+         {
+/*          if     (IsFunctionKey(keysym))     printf("function down\n");
+          else if(IsModifierKey(keysym))     printf("modifier down\n");
+          else if(IsKeypadKey(keysym))       printf(" keypad down\n");
+          else if(IsMiscFunctionKey(keysym)) printf(" misc function down\n");
+          else if(IsPFKey(keysym))           printf(" PF key down\n");
+*/
+
+          switch(keysym) 
+            {
+/* Cursor control & motion */
+	      /*
+            case XK_Left :
+              flag = 1;
+              char1 = call(keyboa).curs_left;
+              break;
+            case XK_Up :
+              flag = 1;
+              char1 = call(keyboa).curs_up;
+              break;
+            case XK_Right :
+              flag = 1;
+              char1 = call(keyboa).curs_right;
+              break;
+            case XK_Down :
+              flag = 1;
+              char1 = call(keyboa).curs_down;
+              break;
+            case XK_Next :
+              flag = 1;
+              char1 = call(keyboa).pad_down;
+              break;
+            case XK_Prior :
+              flag = 1;
+              char1 = call(keyboa).pad_up;
+              break;
+            case XK_End :
+              flag = 1;
+              char1 = call(keyboa).marg_right;
+              break;
+            case XK_Begin :
+              flag = 1;
+              char1 = call(keyboa).marg_left;
+              break;
+	      */
+/* Misc Functions */ 
+	      /* 
+
+            case XK_Select :
+              flag = 1;
+              char1 = call(keyboa).mark;
+              break; */
+/*
+            case XK_Print :
+              flag = 1;
+              char1 = ;
+              break;  
+            case XK_Execute :
+              flag = 1;
+              char1 = ;
+              break;  
+            case XK_Insert :
+              flag = 1;
+              char1 = ;
+              break;
+
+            case XK_Undo :
+              flag = 1;
+              char1 = call(keyboa).undo;
+              break;
+
+            case XK_Redo :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Menu :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Find :
+              flag = 1;
+              char1 = ;
+              break;
+
+
+            case XK_Cancel :
+              flag = 1;
+              char1 = call(keyboa).line_del;
+              break;
+            case XK_Help :
+              flag = 1;
+              char1 = call(keyboa).help;
+              break;
+
+            case XK_Break :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Mode_switch :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_script_switch :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Num_Lock :
+              flag = 1;
+              char1 = ;
+              break;
+
+            case XK_F1 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct1 : call(keyboa).funct1 ;
+              break;
+            case XK_F2 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct2 : call(keyboa).funct2 ;
+              break;
+            case XK_F3 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct3 : call(keyboa).funct3 ;
+              break;
+            case XK_F4 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct4 : call(keyboa).funct4 ;
+              break;
+            case XK_F5 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct5 : call(keyboa).funct5 ;
+              break;
+            case XK_F6 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct6 : call(keyboa).funct6 ;
+              break;
+            case XK_F7 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct7 : call(keyboa).funct7 ;
+              break;
+            case XK_F8 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct8 : call(keyboa).funct8 ;
+              break;
+            case XK_F9 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct9 : call(keyboa).funct9 ;
+              break;
+            case XK_F10 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct10 : call(keyboa).funct10 ;
+              break;
+            case XK_F11 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct11 : call(keyboa).funct11 ;
+              break;
+            case XK_F12 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct12 : call(keyboa).funct12 ;
+              break;
+	      */
+            case XK_Shift_L :
+              shift=1;
+              break;
+            case XK_Shift_R :
+              shift=1;
+              break;
+           case XK_Control_L :
+              control=1;
+              break;
+            case XK_Control_R :
+              control=1;
+              break;
+            case XK_Caps_Lock :
+              shiftlock = 1 ;
+              break;
+            case XK_Shift_Lock :
+              shiftlock = 1 ;
+              break;
+            case XK_Meta_L :
+              alt=1;
+              break;
+            case XK_Meta_R :
+              alt=1;
+              break;
+            case XK_Alt_L :
+              alt=1;
+              break;
+            case XK_Alt_R :
+              alt=1;
+              break;
+            } /* end switch */
+         }
+    }
+    else if(event.type == KeyRelease)
+    { *x1 = event.xkey.x;
+      *y1 = event.xkey.y; 
+      char1= event.xkey.keycode ;
+       keysym=0;
+       nb=XLookupString(&event.xkey,buffer,20,&keysym,&status);
+/*          if     (IsFunctionKey(keysym))     printf("function up\n");
+          else if(IsModifierKey(keysym))     printf("modifier up\n");
+          else if(IsKeypadKey(keysym))       printf(" keypad up\n");
+          else if(IsMiscFunctionKey(keysym)) printf(" misc function up\n");
+          else if(IsPFKey(keysym))           printf(" PF key up\n");
+*/
+       if (nb == 0) 
+         {
+          switch(keysym)
+            {
+            case XK_Shift_L :
+              shift=0;
+              break;
+            case XK_Shift_R :
+              shift=0;
+              break;
+           case XK_Control_L :
+              control=0;
+              break;
+            case XK_Control_R :
+              control=0;
+              break;
+            case XK_Caps_Lock :
+              shiftlock = 0 ;
+              break;
+            case XK_Shift_Lock :
+              shiftlock = 0 ;
+              break;
+            case XK_Meta_L :
+              alt=0;
+              break;
+            case XK_Meta_R :
+              alt=0;
+              break;
+            case XK_Alt_L :
+              alt=0;
+              break;
+            case XK_Alt_R :
+              alt=0;
+              break;
+            } /* end switch */
+
+         }
+    }
+  }
+  XDefineCursor(display,win,cursor_watch);
+  XFlush(display);
+  return char1;
+}
+   
+char Getxyc(float &x,float &y)
+{ 
+  //  cout << " in Getxyc" << endl;
+  char c;
+  int i,j;
+  c = Getijc( &i,&j);
+  x = scali(i);
+  y = scalj(j);
+  //  cout << " out  Getxyc" << x << " " << y << " " << c << endl;
+
+  return c;
+}
+void rattente(int waitm)
+{ int i,j;
+  XFlush(display);
+  if (waitm)
+      Getijc(&i,&j);
+}
+ void GetScreenSize(int &ix,int &iy)
+{
+  ix = width;
+  iy = height;
+}
+void openPS(const char *filename )
+{ 
+  char ffff[32];
+  int count=0;
+  if(psfile_save) closePS();
+  time_t t_loc;
+  float s=0.5;
+  char  username[10];
+  /*if (!cuserid(username)) */ strcpy(username,"inconnue");
+  time(&t_loc);
+  bool notfound;
+  if( !filename) 
+   do {
+      struct stat buf;
+      sprintf(ffff,"rgraph_%.3d.ps",count++);
+      volatile int r= stat(ffff,&buf) ;
+      notfound = r !=0;
+      if(count>1000) break;
+    } while ( !notfound );
+   
+
+  const char *fps (filename?filename:ffff);
+
+  
+  psfile=fopen(fps,"w");
+  if(psfile) {
+    psfile_save=psfile;
+    fprintf(psfile,"%%!PS-Adobe-2.0 EPSF-2.0\n%%%%Creator: %s\n%%%%Title: FreeFem++\n","user");
+    fprintf(psfile,"%%%%CreationDate: %s",ctime(&t_loc));
+    fprintf(psfile,"%%%%Pages: 1\n");
+    fprintf(psfile,"%%%%BoundingBox:       0 0 %d %d\n",int(width*s),int(height*s));
+    fprintf(psfile,"%%%%EndComments\n");
+    fprintf(psfile," /L {newpath moveto lineto stroke} def\n");
+    fprintf(psfile," /C {setrgbcolor} def\n");
+    fprintf(psfile," /rec {newpath 4 copy 8 1 roll moveto 3 -1 roll lineto 4 2 roll exch lineto lineto closepath} def\n");
+    fprintf(psfile," %f %f  scale \n",s,s);
+    fprintf(psfile," 0 %d 0 %d rec clip\n",int(width),int(height));
+    fprintf(psfile," /Helvetica findfont 10 scalefont setfont\n");
+    fprintf(psfile," /S {moveto show} def\n");
+    fprintf(psfile," /bF  { mark} def \n");
+    fprintf(psfile," /eF {newpath moveto counttomark 2 idiv {lineto} repeat closepath  fill cleartomark} def\n");
+    fprintf(psfile," /P { /yy exch def /xx exch def   xx xx 1 add yy yy 1 add  rec  fill } def\n");
+    fprintf(psfile," 1 setlinewidth\n");
+  }
+  else 
+    cerr << " Err openning postscript file " << fps << endl;
+}
+void closePS(void)
+{
+  if(psfile_save) {
+    fprintf(psfile_save,"showpage\n");
+    fclose(psfile_save);
+  }
+  psfile_save=0;
+  psfile=0;
+}
+
+ void coutmode(short i)  {}
+// bof bof --- 
+ float  GetHeigthFont()
+{ 
+  int dir,asc,desc,k;
+  XCharStruct overall;
+
+  XTextExtents(font_info,"gML",3,&dir,&asc,&desc,&overall); 
+  return (asc+desc)*(0.9/echy);
+}
+  void Commentaire(const char * c)  
+  {
+  if(psfile)   {
+    fprintf(psfile,"%% %s\n",c);
+   }
+  };
+  void NoirEtBlanc(int NB)
+  {
+    if(NB) LastColor=1;
+    else LastColor=ncolortable?ncolortable:2;
+  }
+ 
+  void MettreDansPostScript(int in)
+   {
+     if(in)  psfile=psfile_save;     
+     else   psfile=0;
+   }
+
+static void     FillRect(float x0,float y0, float x1, float y1)
+ {
+     float r[8];
+     r[0]=x0;r[1]=y0;
+     r[2]=x1;r[3]=y0;
+     r[4]=x1;r[5]=y1;
+     r[6]=x0;r[7]=y1;
+     fillpoly(4,r);
+ }
+
+int PutLevel(int lineno, float xf, int col)
+{
+  float xmin,xmax,ymin,ymax;
+  getcadre(xmin,xmax,ymin,ymax);
+  float xleft = xmax - (xmax-xmin)*0.1;
+  float ytop  = ymax;
+  float ydelta = (ymax-ymin)/40;
+  ydelta=GetHeigthFont();
+  xleft = xmax - 6*ydelta;  
+  ytop -= ydelta*(col+2);
+  couleur(col);
+  FillRect(xleft+ydelta/8.,ytop+ydelta/8.,xleft+ydelta*7./8.,ytop+ydelta*7./8.);
+  rmoveto(xleft+ydelta*1.4,ytop+ydelta/4);
+  char buf[30];
+  sprintf(buf,"%g",xf);
+  couleur(1);
+  plotstring(buf);
+
+   return lineno;
+}
+ void ShowHelp(const char * s,int k)
+{
+  if(k) {
+    MettreDansPostScript(0);
+    couleur(1);
+    float xmin,xmax,ymin,ymax;
+    getcadre(xmin,xmax,ymin,ymax);
+    rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+    plotstring(s);
+    MettreDansPostScript(1);
+       //  couleur(1);	
+  }
+}
+
+  void setgrey(bool gg ){grey=gg;}
+  int getgrey(){ return grey;}
+
+class Grid;
+
+void SaveMesh(Grid &t){}
+void SavePlot(int D, Grid& t, double *f){}
+void SavePlot(int D, Grid& t, float *f){}
+
diff --git a/src/Graphics/ff-win32.cpp b/src/Graphics/ff-win32.cpp
new file mode 100644
index 0000000..8f1e1d7
--- /dev/null
+++ b/src/Graphics/ff-win32.cpp
@@ -0,0 +1,79 @@
+
+#ifdef WIN32
+#include <string>
+using namespace std;
+#include <windows.h>
+#include <commdlg.h>
+#include <io.h>      //*OT  use for the console window
+
+BOOL ShowOpenDialogBox1(char *fileName)
+{
+  OPENFILENAME ofn; 
+  char szDirName[256];   
+  const char *strFilter="PCgFEM Files (*.edp)\0*.edp\0All Files (*.*)\0*.*\0\0"; 
+  
+  memset(&ofn, 0, sizeof(OPENFILENAME));
+  getcwd(szDirName,sizeof(szDirName));
+  ofn.lStructSize = sizeof(OPENFILENAME);
+  ofn.hwndOwner = NULL;
+  ofn.lpstrFilter = strFilter;
+  ofn.lpstrFileTitle = fileName;
+  ofn.nMaxFileTitle = 80;
+  ofn.lpstrInitialDir=szDirName;
+  ofn.lpstrTitle ="Choose you freefem '*.edp' File";
+  ofn.Flags=OFN_SHOWHELP|OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
+  
+  return GetOpenFileName(&ofn);
+} 
+
+
+
+string ChangeExt(const string & ff,const char * suff)
+{
+  int dot = ff.rfind(".edp");
+  assert(dot>0);
+  return ff.substr(0,dot)+suff;
+}
+
+bool GetConsoleBuff(const string &edpname)
+{
+  CONSOLE_SCREEN_BUFFER_INFO csbi; //* to get buffer info
+  HANDLE hConOut= GetStdHandle(STD_OUTPUT_HANDLE);
+  //cout << " handle " << hConOut << endl; 
+  if( hConOut == 0) return false ;  
+  if ( INVALID_HANDLE_VALUE == hConOut) return false; 
+  GetConsoleScreenBufferInfo(hConOut, &csbi);
+  
+  COORD coordLine = {0,0};
+  CHAR *szLine=0;  //* buffer to read from the console (a line)
+  DWORD dwCharsRead;
+  FILE *fp;
+  string  fname=ChangeExt(edpname,".log");
+  if ((fp = fopen(fname.c_str(),"w"))==NULL) {
+    perror(fname.c_str());
+    cout<< " err fopen logfile: "<< fname <<  endl;	  	
+    return false;
+  }
+  szLine = new CHAR [csbi.dwSize.X+1];
+  for (int i=0; i<csbi.dwCursorPosition.Y; i++) 
+	{
+       	 if (ReadConsoleOutputCharacter(hConOut, szLine,
+				   csbi.dwSize.X, coordLine,
+				   &dwCharsRead)== FALSE)
+      {
+	perror("ReadConsoleOutputCharacter");
+	cout << " err ReadConsoleOutputCharacter " <<i << " " << csbi.dwCursorPosition.Y <<  endl;
+	return false;
+      }
+    int j=csbi.dwSize.X-1;
+    while ((szLine[j] == ' ') && (j > 0)) szLine[j--] =0;
+    if (j < csbi.dwSize.X-1) szLine[j+1] = '\n'; 
+    fprintf(fp,"%s",szLine);
+    coordLine.Y++;
+  }
+  fclose(fp);
+  delete [] szLine;
+  cout << " save log in :  '"<< fname << "'\n"  ;
+  return true;
+}
+#endif
diff --git a/src/Graphics/ffglut.cpp b/src/Graphics/ffglut.cpp
new file mode 100644
index 0000000..8f098e6
--- /dev/null
+++ b/src/Graphics/ffglut.cpp
@@ -0,0 +1,3006 @@
+#ifdef __APPLE__
+#include <GLUT/glut.h>
+#else
+#include <GL/glut.h>
+#endif
+//#include <pthread.h>
+#include <limits>
+#include <cfloat>
+#include <cstdlib>
+#include <cstdio>
+#include <cmath>
+using namespace std;
+
+#include <fstream>
+#include <iostream>
+#include <cstring>
+#include <cstdio>
+#include <vector>
+#include <list>
+#include <map>
+#include <utility>
+#include <unistd.h>
+
+#include "rgraph.hpp"
+#include "fem.hpp"
+#include "RNM.hpp"
+#include "Mesh2dn.hpp"
+#include "Mesh3dn.hpp"
+
+#include "PlotStream.hpp"
+
+extern long verbosity;
+
+// add for the gestion of the endianness of the file.
+//PlotStream::fBytes PlotStream::zott; //0123;
+//PlotStream::hBytes PlotStream::zottffss; //012345678;
+// ---- FH
+
+using namespace Fem2D;
+using std::numeric_limits;
+const R pi=M_PI;//4*atan(1.); 
+using namespace std;
+
+int debug=1;
+int casemouse=0,keyact=0;
+double gwait=0;//  no wait in second
+#include "ffglut.hpp"
+
+#include "ffthreads.hpp"
+
+int version =0;
+
+//Mutex MutexNextPlot;
+Thread::Id tidRead=0;
+bool NoMorePlot=false;
+bool NoMorePlotTilte=false;
+ThePlot *currentPlot=0, *nextPlot=0;
+bool inThreadRead=false;
+FILE *datafile=0;
+
+static  bool TryNewPlot( void );
+
+
+void LauchNextRead();
+void WaitNextRead();
+THREADFUNC(ThreadRead,fd);
+//void * ThreadRead(void *fd);
+
+int kread=-1;
+
+
+map<int,OneWindow *> AllWindows;
+map<int,int>  Num2Windows;
+
+
+int Fin(int code)
+{
+  WaitNextRead();
+  if(!NoMorePlot && debug>2)
+    cout << " exit before end  " << endl;
+  if(NoMorePlot && !code) exit(NoMorePlot ? 0  : 1);
+  if(code) exit(NoMorePlot ? 0  : 1);
+  return 0;
+}
+
+int   ReadOnePlot(FILE *fp)
+{ 
+  int err=0;
+   if(!fp) return -4; 
+  err= feof(fp) ;
+  if(err) return -2;
+  err= ferror(fp) ;
+  if(err) return -3;
+
+  PlotStream f(fp);
+  f.set_binary_mode();
+  const char *  magic2="#!ffglutdata2..";
+  const char *  magic3="#!ffglutdata3..";
+  const char *  magic3_1="#!ffglutdata3.1";
+  const int lmagic=strlen(magic2);
+    char magicxx[32];
+  err=0;
+  // init ..
+  if(kread==-1)
+    {
+      for(int i=0;i<lmagic;i++)
+	{ int c=getc(fp);
+	    magicxx[i]=c;
+	  //err += c != magic[i];
+	  //if(err) break;
+	}
+	magicxx[lmagic]='\0';
+	if( strcmp(magicxx,magic2)==0)  version=2;
+	else if( strcmp(magicxx,magic3)==0)  version=3;
+	else if( strcmp(magicxx,magic3_1)==0)  version=3;
+	else err =1; 
+	
+      if(err) {
+	if(debug>2)
+	 cout << " Err read magic heading " << endl;
+	 goto Lreturn;
+	 //return err;
+	}
+      kread++;
+      if(debug>2) cout << " Read entete " << version << endl;
+	  int c1 =getc(fp);//
+      if(c1==13)	  
+        int c2 =getc(fp);//	
+
+
+    }
+  long cas; 
+  f >> cas;
+  err=-1;
+  if (feof(fp)) goto Lreturn ;
+  if((debug > 2)) cout << " ReadOnePlot " << kread+1<< " cas = " << cas << " " << nextPlot << endl;
+  if(cas==PlotStream::dt_newplot)  
+    {
+      assert(nextPlot==0);
+      nextPlot = new ThePlot(f,currentPlot,++kread);
+	if(debug>1)	
+      cout << " next is build " << nextPlot<< " wait :" << nextPlot->wait << " -> " << kread <<  " gwait = " << gwait << endl;
+      assert(nextPlot);
+      err=0;
+    }
+  else 
+    {
+      err=1;
+      cout << " Error Cas inconnue (skip) " << endl;
+    }
+ Lreturn:
+  f.set_text_mode();
+  return err;
+}
+
+
+void TimerNextPlot(int value)
+{
+  // the routine to  until the end of nextplot.
+  // we use gluttimerfunc functionnaly
+  //  remark, if we miss we retry.
+  // -----
+  //  if(debug) cout << " TimeNextPlot  " << endl;
+  value=min(1000,(value*3)/2);// try at leat every 1 second (not to heavy computation)
+  if(TryNewPlot())
+    glutPostRedisplay();
+  else 
+    glutTimerFunc(value,TimerNextPlot,value);
+}
+
+int SendForNextPlot()
+{
+  //  to send a event to plot the date sheet.
+  // and out a timer to wait to the end of read..
+  // every 25/ second..  = 1000/25 = 40 ms
+  if(NoMorePlot)
+    {
+    if(gwait )
+        {usleep((useconds_t)(1e6*gwait)); Fin(0); }
+
+    if((debug > 1)) cout << " send signal For Next plot, skip: No More Plot !  " << endl;
+    return 0;
+    }
+  if((debug > 1)) cout << " Try to read read  plot "<< endl;
+  //  put a timer for wait to the  end of read
+  glutTimerFunc(40,TimerNextPlot,40);
+  
+  return 1;
+}
+static  bool TryNewPlot( void );
+
+
+
+
+
+int  signep4(int i0,int i1,int i2,int i3)
+{ // calcul du signe dans la permutation 
+  int s =1;
+  if(i0>i1) s=-s,Exchange(i0,i1);
+  if(i1>i2) s=-s,Exchange(i1,i2);
+  if(i2>i3) s=-s,Exchange(i2,i3); // i3 max
+  if(i0>i1) s=-s,Exchange(i0,i1);
+  if(i1>i2) s=-s,Exchange(i1,i2); // i2 max < i
+  if(i0>i1) s=-s,Exchange(i0,i1);
+  return s;
+}
+inline R3 bary(const R3 K[4],R f[4],int i0,int i1,R v)
+{
+  R d=f[i0]-f[i1];
+  assert(fabs(d)>1e-20);
+  R l1= (f[i0] - v)/ d;  //  == 1 si v = f[i1]  
+  R l0 = 1. -l1;
+  assert(l0 >=-1e-10 && l1 >= -1e-10);
+  return K[i0]*l0 + K[i1]*l1; // == K[i1] si l1 ==1 => v = f[i1] 
+}
+void drawisoTet(const R3 K[4],R f[4],R v)
+{
+  static const int  nvfaceTet[4][3]  ={{3,2,1}, {0,2,3},{ 3,1,0},{ 0,1,2}}  ;//{ {2,1,3},{0,2,3},{1,0,3},{0,1,2} };
+
+  R3 P[4];
+  int nP=0;
+  int np[4],nm[4];
+  int km=0,kp=0;
+  for (int i=0;i<4;++i)
+    {
+      if(f[i]<=v) nm[km++]=i;
+      if(f[i]>=v) np[kp++]=i;
+    }
+  
+  //cout << "km kp "<< km << " " << kp << endl;
+  int h=-1,b[3];
+  if(kp==1 && km==3)
+    {
+      h = np[0];
+      b[0]=nvfaceTet[h][0];
+      b[1]=nvfaceTet[h][1];
+      b[2]=nvfaceTet[h][2];
+    }
+  if(km==1 && kp == 3)
+    {
+      h = nm[0];
+      b[0]=nvfaceTet[h][0];
+      b[2]=nvfaceTet[h][1];
+      b[1]=nvfaceTet[h][2];
+    }
+  if(kp==2 && km==2)
+    {//  cas quad 
+      if(signep4(nm[0],nm[1],np[0],np[1]) < 0)
+	Exchange(nm[0],nm[1]);
+      //  le tet m[0],nm[1],np[0],np[1] est positif
+      P[0]=bary(K,f,nm[0],np[0],v);
+      P[1]=bary(K,f,nm[0],np[1],v);
+      P[2]=bary(K,f,nm[1],np[1],v);
+      P[3]=bary(K,f,nm[1],np[0],v);
+      nP=4;      
+    }
+  else if (h>=0)
+    { // cas triangle 
+      P[0]=bary(K,f,h,b[0],v);
+      P[1]=bary(K,f,h,b[1],v);
+      P[2]=bary(K,f,h,b[2],v);
+      nP=3;
+    }
+  
+
+  /*
+    if(nP)
+    {
+    cout << "+ " << np[0] << " - " << nm[0] << endl;
+    cout << nP << " ;  ";
+    for(int i=0;i<nP;++i)
+    cout << P[i] << " ;  ";
+    cout << endl;
+    
+    }
+  */
+    if(nP)
+    {
+      if(nP>2)
+	{
+	  R3 N(R3(P[0],P[1])^R3(P[0],P[2]));
+	  N /= N.norme();
+	  glNormal3d(N.x,N.y,N.z);
+	}
+      glBegin(GL_POLYGON);
+      for(int i=0;i<nP;++i)
+	glVertex3f(P[i].x, P[i].y,P[i].z); // 
+      glEnd();
+    }
+
+  //  verification de l'orientation
+ // assert(nP < 3 || det(P[0],P[1],P[2],K[np[0]]) >=0)   ;
+ // assert(nP < 3 || det(P[0],P[1],P[2],K[nm[0]]) <=0)   ;
+  
+}
+
+
+int dichotomie(const KN_<double>  &viso,R v) 
+{
+    int i=0,j=viso.N(),k;
+    if  (v <viso[0] || v >viso[j-1]) 
+	return -1;  
+    while (i<j-1)    
+	if ( viso[k=(i+j)/2]> v) j=k;
+	else i=k;
+    return i;
+}
+
+
+
+int  ShowGlerror(const char *s)
+{
+    GLint error = glGetError();
+    if ( error != GL_NO_ERROR )
+	printf("Attention %s erreur : %x \n",s,error);   
+    return error;   
+}
+
+
+//  def des couleurs de la tables 
+void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool grey,KN<R> colors)
+{
+    int nbcolors = colors.N()/3;
+    if(k<=0) {  r=g=b=1.;} //  white
+    else if (k==1)  { r=g=b=0.; } // black
+    else if (k >= nb)   {  r=g=b=0.;} // black
+    else if (grey) { float gg = 0.1+0.9*float(k-2)/(nb-3); r=g=b=gg;} 
+    else if (nbcolors<=1) {  
+	float h=float(k-2)/(nb-2),s=1.,v=1.;
+	hsvToRgb(h,s,v,r,g,b); 
+    return;}     
+    else   { //  interpolation dans la table hsv    
+	int i= (k-2); 
+	int j0= i*(nbcolors-1) / (nb-2);
+	int j1=j0+1;
+	int i0=  j0*(nb-2)/(nbcolors-1);
+	int i1=  j1*(nb-2)/(nbcolors-1);
+	int j03=j0*3,j13=j1*3;
+	float a=float(i1-i)/(i1-i0),a1=1-a;
+	if (hsv)
+	  {
+	      float h = colors[j03+0]*a + colors[j13+0]*a1;
+	      float s = colors[j03+1]*a + colors[j13+1]*a1;
+	      float v = colors[j03+2]*a + colors[j13+2]*a1;
+	  hsvToRgb(h,s,v,r,g,b); }
+	else 
+	  {
+	      r = colors[j03+0]*a + colors[j13+0]*a1;
+	      g = colors[j03+1]*a + colors[j13+1]*a1;
+	      b = colors[j03+2]*a + colors[j13+2]*a1;
+	  }
+    }     
+    
+}
+
+template<class Mesh>
+void Plot(const Mesh & Th,bool fill,bool plotmesh,bool plotborder,ThePlot & plot,GLint gllists,int * lok)
+{
+    glDisable(GL_DEPTH_TEST);
+
+    ShowGlerror("begin Mesh plot");
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
+    R z1= plot.z0;
+    R z2= plot.z0;
+    
+    
+    double r=0,g=0,b=0;
+    if((debug > 3)) cout<< " OnePlotMesh::Draw " << plotmesh << " " << plotborder << " " <<  Th.nbBrdElmts() << " " << z1 << " "  << z2 << endl;
+    // plot.SetColorTable(16) ; 
+    bool cc[3]= { plotborder , plotmesh && fill , plotmesh };
+    int kk=0;
+    //for(int i=0;i<3;i++)
+    //  cout << cc[i] << " " << lok[i] << " , ";
+    //cout << endl;
+    if(cc[kk])
+      if(lok[kk])   glCallList(gllists+kk);
+      else 
+	{ 
+	  lok[kk]=1;
+	  glNewList(gllists+kk,GL_COMPILE_AND_EXECUTE ); // save  la list sans affichage
+	  glLineWidth(2); 
+	  glBegin(GL_LINES);    
+	  for (int i=0;i<Th.nbBrdElmts();i++)
+	    {
+		const typename  Mesh::BorderElement  & K(Th.be(i)); 
+	      plot.color(1+abs(K.lab));
+	      glVertex3d(K[0].x,K[0].y,z1);
+	      glVertex3d(K[1].x,K[1].y,z1);
+	      
+	      
+	    }
+	  glEnd(); 	  
+	  glLineWidth(1); 
+	  glEndList();  // fin de la list
+	}
+      else ;
+    
+    kk++;	
+    if(cc[kk])
+    {
+      if(lok[kk])   glCallList(gllists+kk);
+      else 
+	{ 
+	  lok[kk]=1;
+	  glNewList(gllists+kk,GL_COMPILE_AND_EXECUTE ); // save  la list sans affichage
+	  glPolygonMode(GL_FRONT,GL_FILL);//GL_FILL	
+	  glBegin(GL_TRIANGLES);
+	  for (int i=0;i<Th.nt;i++)
+	    {
+	      const typename  Mesh::Element & K(Th[i]);
+	      plot.color(K.lab?1+abs(K.lab):0);
+	      
+	      //glColor3d(r,g,b);
+	      int i0= Th(K[0]),  i1= Th(K[1]),   i2= Th(K[2]) ;    		
+	      glVertex3d(K[0].x,K[0].y,z2);
+	      glVertex3d(K[1].x,K[1].y,z2);
+	      glVertex3d(K[2].x,K[2].y,z2);
+	      
+	    }    
+	  glEnd();
+	  glEndList();  //
+	}
+    }
+    kk++;
+    if(cc[kk])
+    {
+      if(lok[kk])   glCallList(gllists+kk);
+      else 
+	{ 
+	  lok[kk]=1;
+	  glNewList(gllists+kk,GL_COMPILE_AND_EXECUTE ); // save  la list sans affichage
+	  glPolygonMode(GL_FRONT,GL_LINE);
+	  glBegin(GL_TRIANGLES);
+	  for (int i=0;i<Th.nt;i++)
+	    {
+		const  typename  Mesh::Element  & K(Th[i]);
+		plot.color(fill? 1 : 1+abs(K.lab));
+		int i0= Th(K[0]),  i1= Th(K[1]),   i2= Th(K[2]) ;    
+		glVertex3d(K[0].x,K[0].y,z1);
+		glVertex3d(K[1].x,K[1].y,z1);
+		glVertex3d(K[2].x,K[2].y,z1);
+		
+	    }    
+	  
+	  glEnd();
+	glEndList();  // fin de la list
+      }
+    }
+    ShowGlerror("end Mesh plot");
+
+}
+
+
+void Plot(const Mesh3 & Th,bool fill,bool plotmesh,bool plotborder,ThePlot & plot,GLint gllists,int * lok)
+{
+  typedef Mesh3::BorderElement BE;
+  typedef Mesh3::Element Tet;
+  glEnable(GL_DEPTH_TEST);
+  /*
+  if(fill)  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
+  else glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
+  */
+  ShowGlerror("begin Mesh plot");
+  
+  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
+  
+  R z1= plot.z0;
+  R z2= plot.z0;
+  
+  double r=0,g=0,b=0;
+  
+  bool cc[3]= { plotborder , plotborder && fill , plotmesh && fill };
+  double saturation =plotmesh ? 1 :  0.25;
+  int kk=0;
+  if(cc[kk])
+  {
+    if(lok[kk])   glCallList(gllists+kk);
+    else 
+      { 
+	lok[kk]=1;
+	glNewList(gllists+kk,GL_COMPILE_AND_EXECUTE ); // save  la list sans affichage
+	glLineWidth(1); 
+	glAlphaFunc ( GL_GREATER, 0.1 ) ;
+	glEnable(GL_ALPHA_TEST) ;
+	if(!plotmesh)
+	  {
+	    glLineStipple(1, 0x300C);
+	    glEnable(GL_LINE_STIPPLE);
+	  }
+	glBegin(GL_TRIANGLES);    
+	for (int i=0;i<Th.nbe;i++)
+	  {
+	    const BE & K(Th.be(i)); 
+	    plot.color(1+abs(K.lab),saturation);
+	    R3 N(R3(K[0],K[1])^R3(K[0],K[2]));
+	    N /= N.norme();
+	    glNormal3d(N.x,N.y,N.z);
+	    glVertex3d(K[0].x,K[0].y,K[0].z);
+	    glVertex3d(K[1].x,K[1].y,K[1].z);
+	    glVertex3d(K[2].x,K[2].y,K[2].z);
+	  }
+	glEnd(); 
+	glDisable(GL_LINE_STIPPLE);
+	glLineWidth(1); 
+	glDisable(GL_ALPHA_TEST) ;
+
+	glEndList();  // fin de la list	  
+      }
+  }
+    kk=2;
+    if(cc[kk])
+    {
+	if(lok[kk])   glCallList(gllists+kk);
+	else 
+	  { 
+	      lok[kk]=1;
+	      glNewList(gllists+kk,GL_COMPILE_AND_EXECUTE ); // save  la list sans affichage
+	      glLineWidth(1); 
+	      glPolygonMode(GL_FRONT,GL_FILL);//GL_FILL	
+	      glBegin(GL_TRIANGLES);    
+	      for (int i=0;i<Th.nbe;i++)
+		{
+		  const BE & K(Th.be(i)); 
+		  plot.color(0,saturation);
+		  R3 N(R3(K[0],K[1])^R3(K[0],K[2]));
+		  N /= N.norme();
+		  glNormal3d(N.x,N.y,N.z);
+		  glVertex3d(K[0].x,K[0].y,K[0].z);
+		  glVertex3d(K[1].x,K[1].y,K[1].z);
+		  glVertex3d(K[2].x,K[2].y,K[2].z);
+		}
+	      glEnd(); 
+	      glDisable(GL_LINE_STIPPLE);
+	      glLineWidth(1); 
+	      glDisable(GL_ALPHA_TEST) ;
+	      
+	      glEndList();  // fin de la list	  
+	  }
+    }
+  kk++;
+  ShowGlerror("end Mesh plot");
+  
+}
+
+
+
+void OnePlotError::Draw(OneWindow *win)
+{
+  initlist();
+  ThePlot & plot=*win->theplot;
+  win->SetScreenView() ;
+  glColor3d(0.,0.,0.);
+  cout << " Error plot item empty " << item <<  endl;
+  int i = 4;
+  char s[100];
+  sprintf(s,"Warning the item %ld fot the plot is empty",item);
+  win->Show(s,4+item*2);
+  win->SetView() ;
+}
+
+template<class Mesh>
+void OnePlotMesh<Mesh>::Draw(OneWindow *win)
+{
+  initlist();
+  ThePlot & plot=*win->theplot;
+  Plot(*Th,plot.fill,true,true,plot,gllists,oklist);
+  ShowGlerror("OnePlotMesh::Draw");
+}
+void OnePlotMesh3::Draw(OneWindow *win)
+{
+  initlist();
+    ThePlot & plot=*win->theplot;
+    Plot(*Th,plot.fill,true,true,plot,gllists,oklist);
+    ShowGlerror("OnePlotMesh3::Draw");
+}
+void OnePlotFE3::Draw(OneWindow *win)
+{
+  initlist();
+  
+  ThePlot & plot=*win->theplot;
+    ShowGlerror("begin OnePlotFE3 plot");
+    ///    plot.SetDefIsoV();
+    if(plot.fill && what%10==6)
+      glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    else
+      glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    bool  change=false;
+    if( (what%10==6) ) 
+      {
+	change = win->changeiso ;
+      }
+      
+    if(what%10==6)
+      glEnable(GL_DEPTH_TEST);
+    else 
+      glEnable(GL_DEPTH_TEST);
+    win->setLighting();
+    if(oklist[0] && !change)
+      glCallList(gllists+0);
+    else
+      { 
+	oklist[0]=1;
+        glNewList(gllists+0,GL_COMPILE_AND_EXECUTE); // save  la list sans affichage
+	int nsubV=Psub.N();
+	int nsubT=Ksub.N()/4;
+	KN<R3> Pn(nsubV);
+	int nK=v.N()/ Th->nt;
+	for(int k=0,o=0;k<Th->nt;++k, o+= nK)
+	  {
+	    const Mesh3::Element & K=(*Th)[k];
+	    int ii[4];// 
+	    R ff[4];
+	    R3 Pt[4];
+	    for(int i=0;i<nsubV;++i)
+	      Pn[i]=K(Psub[i]);
+	    int lK=0;
+	    if(what%10==6)
+	      for(int sk=0;sk<nsubT;++sk)
+		{
+		  
+		  for(int l=0;l<4;++l)
+		    {
+		      int iv= Ksub[lK++];
+		      ii[l]= iv;
+		      Pt[l]=Pn[iv];
+		      ff[l]=v[o+iv];
+		    }
+		  
+		  for(int i=0;i< plot.Viso.N();++i)
+		    {
+		      plot.color(i+4);			    
+		      drawisoTet( Pt,ff,plot.Viso[i]);
+		    }
+		  
+		}
+	  }
+        glEndList();  // fin de la list
+      }
+    win->unsetLighting();
+    ShowGlerror("b mesh  OnePlotFE plot");  
+    Plot(*Th,false,plot.drawmeshes,plot.drawborder,plot,gllists+2,&oklist[2]);
+    ShowGlerror("OnePlotFE::Draw");
+}    
+
+
+
+template<class Mesh>
+ OnePlotFE<Mesh>::OnePlotFE(const Mesh *T,long w,PlotStream & f)
+:OnePlot(w,2,5),Th(T)
+{
+    R2 P0,P1;
+    Th->BoundingBox(P0,P1);
+    Pmin=P0;
+    Pmax=P1;
+    if(version==2)
+      {
+	  long nsub;
+	  
+	  f>> nsub;
+	  int nsubT=NbOfSubTriangle(nsub);
+	  int nsubV=NbOfSubInternalVertices(nsub);
+	  
+	  Psub.resize(nsubV);
+	  Ksub.resize(nsubT*3);
+	  for(int i=0,j=0;i<nsubV;++i)
+	    Psub[i]=SubInternalVertex(nsub,i);
+	   
+	  for(int sk=0,p=0;sk<nsubT;++sk)
+	      for(int i=0;i<3;++i,++p)
+		  Ksub[p]=numSubTriangle(nsub,sk,i);
+	  
+	  
+      }
+    else
+      {	  f >> Psub ;
+	  f >> Ksub ;
+	  if(debug>2) {
+	  cout << " Psub " << Psub << endl;
+	  cout << " Ksub " << Ksub << endl;}
+
+      }
+    if(what<10)
+      f>> v;
+    else
+      {
+      f>> vc;
+      vc2v();
+      }
+    cas =2; 
+    vc2v();
+    if(debug>3) cout << "OnePlotFE" << Th <<" " << what<< " " << Psub.N() << " " << Ksub.N()/3 <<" " << v.N() << endl; 
+    ffassert(f.good());
+    
+}
+
+
+
+template<class Mesh>
+bool  OnePlotFE<Mesh>::vc2v() 
+{
+  bool ret=false;
+  if(what>=10)
+    {
+      ret=true;
+      int n = vc.N();
+      if(v.size() !=n) 
+	v.resize(n);
+      for(int i=0;i<n;++i)
+	if( cas%4== 0) v[i] = vc[i].real();
+	else if( cas%4== 1) v[i] = vc[i].imag();
+	else if( cas%4== 2) v[i] = abs(vc[i]);
+	else if( cas%4== 3) v[i] = arg(vc[i]);
+    }
+  
+  if(what%10==1)
+    {
+      fmin = min(fmin,v.min());
+      fmax = max(fmax,v.max());
+    }
+  else if (what%10==2)
+    {  
+      int n= v.N()/2;
+      for (int i=0,j=0;i<n;i++, j+=2)
+	{
+	  R2 u(v[j],v[j+1]);
+	  vmax2 = max(vmax2,u.norme2());
+	}
+    }
+  return ret;  
+}
+
+bool  OnePlotFE3::vc2v() 
+{
+  bool ret=false;
+  if(what>=10)
+    {
+      ret=true;
+      int n = vc.N();
+      if(v.size() !=n) 
+	v.resize(n);
+      for(int i=0;i<n;++i)
+	if( cas%4== 0) v[i] = vc[i].real();
+	else if( cas%4== 1) v[i] = vc[i].imag();
+	else if( cas%4== 2) v[i] = abs(vc[i]);
+	else if( cas%4== 3) v[i] = arg(vc[i]);
+    }
+  
+  
+  if(what%10==6)
+    {
+      fmin = min(fmin,v.min());
+      fmax = max(fmax,v.max());
+    }
+  else if (what%10==7)
+    {  
+      
+      int n= v.N()/3;
+      for (int i=0,j=0;i<n;i++, j+=2)
+	{
+	  R3 u(v[j],v[j+1],v[j+2]);
+	  vmax2 = max(vmax2,u.norme2());
+	}
+      //cout << " vmax = " << sqrt(vmax2) << endl; 
+    }
+  return ret;
+}
+
+template<class Mesh>
+void OnePlotFE<Mesh>::Draw(OneWindow *win)
+{
+  initlist();
+  ThePlot & plot=*win->theplot;
+  ShowGlerror("begin OnePlotFE plot");
+  //plot.SetDefIsoV();
+  win->setLighting();
+  //    OneWindow * win=plot.win;// bof bof  la struct est tres mauvaise . 
+  assert(win);
+  const Mesh & Th(*this->Th);
+    int nsubT= Ksub.N()/3;//NbOfSubTriangle(nsub);
+  int nsubV=Psub.N();//NbOfSubInternalVertices(nsub);
+  int nK=v.N()/ Th.nt;
+  if(debug>4)
+  cout << "\t\t\tOnePlotMesh::Draw  " <<v.N() << " ,nt " << Th.nt << " " << nK << " " 
+       << Psub.N() << " " << what << " ,nv " << Th.nv << " cas=" << cas << endl;
+  ffassert(v.N()== Th.nt*nK);
+  ffassert(nK == nsubV*(what%10));
+  int o=0;
+  KN<R2> Pn(Psub.N());
+  if((debug > 10)) cout << " " <<nsubV  << " " << nsubT << endl;
+  
+  if(plot.fill && what%10==1)
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+  else
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+  
+  if(what%10==2)
+    glDisable(GL_DEPTH_TEST);
+  else 
+    glEnable(GL_DEPTH_TEST);
+
+  R coef = plot.coeff;
+  double xmin,xmax,ymin,ymax;
+  win->getcadre(xmin,xmax,ymin,ymax);
+  double d= Max(ymax-ymin,xmax-xmin);
+  R kk = 4*win->hpixel;
+  R cc = win->hpixel*40;
+  
+  int klist=0;
+  bool  change=false;
+  if( (what%10==1) ) 
+    {
+      if ( plot.fill) klist=1;
+      change = win->changeiso ;
+    }
+  else if (what%10==2)
+    change  =  win->changearrow ;
+  if(debug>9)
+    cout << change << " " << klist << " ... " << oklist[klist] << "  fill = " 
+	 <<  plot.fill <<  " " <<  coef << endl;
+  if (oklist[klist] && ! change )
+    glCallList(gllists+klist);
+  else 
+    {
+      //      R fmn,fmx,vmn,vmx;
+            
+      // win->theplot->dyn_bfv(win,fmn,fmx,vmn,vmx) ;
+      //win->theplot->SetDefIsoV(0,0,fmn,fmx,vmn,vmx) ;
+      oklist[klist]=1;
+      glNewList(gllists+klist,GL_COMPILE_AND_EXECUTE); // save  la list aevc  affichage
+      if(debug>100)
+      cout << win->Bmin << ", Bmax:   " << win->Bmax << " Viso: "<< plot.Viso << endl;
+      for(int k=0;k<Th.nt;++k, o+= nK)
+	{
+	  const typename Mesh::Element & K=Th[k];
+	  for(int i=0;i<nsubV;++i)
+	    Pn[i]=K(Psub[i]);// local to global coord. 
+	  if(what%10==1)
+	    for(int sk=0;sk<nsubT;++sk)
+	      {
+		int i0= Ksub[sk*3+0];//numSubTriangle(nsub,sk,0);
+		int i1= Ksub[sk*3+1];//numSubTriangle(nsub,sk,1);
+		int i2= Ksub[sk*3+2];//numSubTriangle(nsub,sk,2);
+		
+		R ff[3]={v[o+i0],v[o+i1],v[o+i2]};
+		R2 Pt[3]={Pn[i0],Pn[i1],Pn[i2]};
+		if(plot.fill)
+		  plot.DrawIsoTfill( Pt, ff, plot.Viso,plot.Viso.N());
+		else
+		  plot.DrawIsoT( Pt, ff, plot.Viso,plot.Viso.N()); 
+	      }
+	  else // what ==2
+	    for (int i=0,j=0;i<nsubV;++i)
+	      {
+		R2 P=Pn[i];
+		R2 uv(v[o+j],v[o+j+1]);
+		j+=2;
+		R  l = Max(sqrt((uv,uv)),1e-30) ;
+		int col = 2+dichotomie(plot.Varrow,l);
+		if(debug>100) 
+		  cout << uv << " l= " << l << " " << coef << " " <<col <<  endl;
+		
+		plot.color(2+col);
+		uv = coef*uv;
+		l *= coef;
+		R2 dd = uv*(-kk/l);
+		R2 dn = dd.perp()*0.5;
+		if (l*10000.< kk) continue;
+		if (l < kk) 
+		  uv = uv*(kk/l);
+		else if (l> cc)
+		  uv = uv*(cc/l);	   
+		glBegin(GL_LINES);          
+		
+		win->Seg(P,P+uv);
+		
+		if (10*l>kk) {
+		  win->Seg(P+uv,P+uv+dd+dn);
+		  win->Seg(P+uv,P+uv+dd-dn);
+		}
+		glEnd();		
+	      }
+
+	}
+      glEndList();  // fin de la list
+    }
+  
+  // if(plot.drawmeshes)
+  //  if(what==2)
+  //  glEnable(GL_DEPTH_TEST);  
+  ShowGlerror("b mesh  OnePlotFE plot");  
+  win->unsetLighting();
+  Plot(Th,false,plot.drawmeshes,plot.drawborder,plot,gllists+2,&oklist[2]);
+  ShowGlerror("OnePlotFE::Draw");
+}
+
+template<class Mesh>
+ void OnePlotFE<Mesh>::dyn_bfv(OneWindow *win,R & fmn,R &fmx,R & vmn2,R & vmx2) const 
+{
+  const Mesh & Th(*this->Th);
+  int nsubT= Ksub.N()/3;//NbOfSubTriangle(nsub);
+  int nsubV=Psub.N();//NbOfSubInternalVertices(nsub);
+  int nK=v.N()/ Th.nt;
+  ffassert(v.N()== Th.nt*nK);
+  ffassert(nK == nsubV*(what%10));
+  int o=0;
+  KN<R2> Pn(Psub.N());
+  KN<R3> P3(Psub.N());
+  double xmin,xmax,ymin,ymax;
+  KN<int> inCadre(nsubV);
+  win->getcadre(xmin,xmax,ymin,ymax);
+  bool ccc=false;
+  bool ddd=false;
+  if(ddd)
+  cout << " dyn__ .. " << endl;
+  for(int k=0;k<Th.nt;++k, o+= nK)
+    {
+      const typename Mesh::Element & K=Th[k];
+      inCadre=0;
+      for(int i=0;i<nsubV;++i)
+	Pn[i]=K(Psub[i]);// local to global coord. 
+      for(int i=0;i<nsubV;++i)
+	{
+	  double f=0;
+	  if(what%10==1) f=v[o+i];
+	  gluProject(Pn[i].x,Pn[i].y,f,win->modelMatrix,win->projMatrix,win->viewport,
+		      &P3[i].x,&P3[i].y,&P3[i].z);
+	  if(ddd)
+	    cout  <<P3[i]  << ", " ;
+	  
+	}// local to global coord. 
+      if(ddd)
+	cout << endl;
+      for(int sk=0;sk<nsubT;++sk)
+	{
+	  int i1=Ksub[sk*3+0], i2=Ksub[sk*3+1], i3=Ksub[sk*3+2];
+	  R3 P0= Minc(Minc(P3[i1],P3[i2]),P3[i3]);
+	  R3 P1= Maxc(Maxc(P3[i1],P3[i2]),P3[i3]);
+	  if( win->InRecScreen(P0,P1))
+	      {
+		if(debug>100)
+		cout << " ???  " << P0 << " " << P1 << " ,  " << win->Bmin 
+		     << " , " << win->Bmax << endl;
+		inCadre[i1]=2;
+		inCadre[i2]=2;
+		inCadre[i3]=2;
+	      }
+	}
+      for (int i=0,j=0;i<nsubV;++i)
+	if(inCadre[i])
+	  {
+	    ccc=true;
+	    if(what%10==1)
+	      {
+		R f=v[o+i];
+		fmn=min(f,fmn);
+		fmx=max(f,fmx);
+		
+	      }		    
+	    else // what ==2
+	      
+	      {
+		R2 uv(v[o+j],v[o+j+1]);
+		j+=2;		
+		R  l =(uv,uv) ;
+		vmn2=min(l,vmn2);
+		vmx2=max(l,vmx2);
+	      }
+	  }
+      if(debug>100 && ccc)
+	cout << " dny_bfv :  "  << fmn << " " << fmx << " " << sqrt(vmn2) << " " << sqrt(vmx2) 
+	     <<  " : " << Pn[0] << endl;
+      
+    }
+}
+
+
+
+void OnePlotCurve::Draw(OneWindow *win)
+{
+  initlist();
+
+  ThePlot & plot= *win->theplot;
+  plot.SetColorTable(16) ;
+    double z = plot.z0;
+  
+  glBegin(GL_LINE_STRIP);    
+  plot.color(2);
+  // cout << "nePlotCurve::Draw " << xx << " " << yy << endl;
+  for (int i=0;i<xx.N();i++)
+    {
+      glVertex3d(xx[i],yy[i],z);
+      
+    }
+  glEnd(); 
+    
+}
+
+void OnePlotBorder::Draw(OneWindow *win)
+{
+  initlist();
+
+  glDisable(GL_DEPTH_TEST);
+  ThePlot & plot= *win->theplot;
+  R h = 8*win->hpixel;
+  
+  double z = plot.z0;
+  plot.SetColorTable(16) ; 
+  
+  // vector<vector<pair<long,R2> > > data;
+  for(int i=0;i<data.size() ;++i)
+    {
+      vector<pair<long,R2> > & v=data[i];
+      ShowGlerror("end OnePlotBorder::Draw  1");
+      
+      
+      for(int j=1;j<v.size();++j)
+	{
+	  //	  cout <<v[j].first << endl;
+	  plot.color(2+v[j].first);
+	  R2 Po(v[j-1].second), Pn(v[j].second);
+	  R2 uv(Po,Pn);
+          double l = Max(sqrt((uv,uv)),1e-20);
+          
+          R2 dd = uv*(-h/l);
+          R2 dn = dd.perp()*0.5;
+	  glLineWidth(2); 
+	  glBegin(GL_LINES);    
+	  win->Seg(Po,Pn);
+	  glEnd();
+	  
+	  glLineWidth(1);
+	  glBegin(GL_LINES);    	  
+	  if(j!=1)
+	    {
+	      win->Seg(Po,Po+dd+dn);
+	      win->Seg(Po,Po+dd-dn);
+	    }
+	  glEnd();
+	}
+      
+      ShowGlerror("end OnePlotBorder::Draw  2");
+      
+      glPointSize(7); 
+      glBegin(GL_POINTS);    
+      int l= v.size()-1;
+      plot.color(2+v[0].first);
+      glVertex3d(v[0].second.x,v[0].second.y,z);
+      plot.color(2+v[l].first);
+      glVertex3d(v[l].second.x,v[l].second.y,z);
+      glEnd();
+      glPointSize(1);
+      ShowGlerror("end OnePlotBorder::Draw  3");
+    }
+  ShowGlerror("end OnePlotBorder::Draw");
+  
+}
+
+OneWindow::OneWindow(int h,int w,ThePlot *p)
+  :
+  icurrentPlot(lplots.begin()), 
+  lplotssize(0),
+  height(h),width(w),theplot(0),hpixel(1),
+  Bmin(0,0),Bmax(1,1),oBmin(Bmin),oBmax(Bmax),zmin(0),zmax(1),
+  windowdump(false),help(false), rapz0(-1.),rapz(1),withlight(false),
+  changearrow(true),changeiso(true), keepPV(false),init(false)
+{
+  
+  add(p);
+}
+
+
+void OneWindow::set(ThePlot *p)
+{
+  //ffassert(p);
+    bool first = !theplot;
+    bool change = theplot != p;
+    theplot=p;
+    if(p)
+      {
+	plotdim=p->plotdim;
+      }
+    if(!init)
+    {
+    rapz0 =-1; // to recompute the defalut rapz
+    //    p->win=this;
+    //    if(first)
+    DefaultView(2) ;
+    }
+    
+}
+
+void OneWindow::add(ThePlot *p)
+{
+  if(p) {
+    lplots.push_back(p);
+    lplotssize++;
+    ++icurrentPlot;
+    if(icurrentPlot==lplots.end())
+      --icurrentPlot;// the previous
+    if(icurrentPlot != lplots.end())
+      set(*icurrentPlot);
+    if( lplotssize>10)
+      {
+	bool isfirst = theplot == *lplots.begin();  
+	if(debug >1)
+	cout << " delete a plot " << *lplots.begin() << endl;
+	delete *lplots.begin();
+	lplots.erase(lplots.begin());
+        lplotssize--;
+	if(isfirst) set(*lplots.begin()); // change to the next plot
+      }
+  }
+  else 
+    set(p);
+}
+
+void OneWindow::DefaultView(int state)
+{
+  if(debug>1)  cout << "DefaultView " << state << " " <<keepPV << " theplot " << theplot << endl;
+  if(keepPV)
+   {
+      if(state==0 && init) return;
+  }
+  else /*if(state==2)*/ rapz0=-1;
+    
+  if(theplot)
+    {
+      init =1;
+      plotdim=theplot->plotdim;
+      R3 A(theplot->Pmin),B(theplot->Pmax);
+      R3 D(A,B);
+      R dxy= max(D.x,D.y);
+      zmax = theplot->fmax;
+      zmin = theplot->fmin;
+      theta=theplot->theta;
+      phi=theplot->phi;
+      if(theplot->datadim==3) rapz0=1;
+      else   if(rapz0<=0)
+	{ //  ( zmax-zmin )*rapz0 =  0.3 dxyy
+	  rapz0  =  0.4* dxy/(zmax-zmin) ;
+	  if(debug>2)
+	    {
+	      cout << " rapz0 = " << rapz0 ;
+	      cout << " dz = " << zmax-zmin  << " dxy =" << dxy << endl;
+	    }
+	}
+        
+      rapz=rapz0;
+      coef_dist=theplot->dcoef;
+      focal=theplot->focal;      
+    
+      if(theplot->datadim==3)
+	{
+	  Bmin3=A;
+	  Bmax3=B;
+	}
+      else
+	{ // data plot 2d ou 1 d... 
+	  if(theplot->boundingbox.size() ==4)
+	    {
+	      Bmin3.x=theplot->boundingbox[0];
+	      Bmin3.y=theplot->boundingbox[1];
+	      Bmax3.x=theplot->boundingbox[2];
+	      Bmax3.y=theplot->boundingbox[3];	    
+	    }
+	  else 
+	    {
+	      Bmin3.x=A.x;
+	      Bmin3.y=A.y;
+	      Bmax3.x=B.x;
+	      Bmax3.y=B.y;
+	    }
+	  Bmin3.z=theplot->fmin;
+	  Bmax3.z=theplot->fmax;
+	}
+      Pvue3=(Bmin3+Bmax3)/2;
+      
+      
+      
+      D *=0.05;      
+      if(theplot->boundingbox.size() !=4)
+	{
+	  A -= D;
+	  B += D;
+	}
+      else
+	{
+	  R x1=theplot->boundingbox[0],y1=theplot->boundingbox[1];
+	  R x2=theplot->boundingbox[2],y2=theplot->boundingbox[3];
+	  A = R2(min(x1,x2),min(y1,y2));
+	  B = R2(max(x1,x2),max(y1,y2));
+	}
+      
+      if (theplot->aspectratio)
+	cadreortho(A.p2(),B.p2());
+      else 
+	cadre(A.p2(),B.p2());
+    }
+  hpixel = (Bmax.x-Bmin.x)/width;
+  
+  // SetView() ;
+}
+
+void  OneWindow::SetScreenView() const
+{
+
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_DEPTH_TEST);
+  glMatrixMode(GL_PROJECTION); 
+  glLoadIdentity(); 
+  glOrtho(0,width,0,height,-1,1);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+}
+
+void  OneWindow::SetView()
+{
+  if(plotdim==3 && theplot)
+    {
+      glViewport(0, 0,width, height);
+      
+      glMatrixMode(GL_PROJECTION); 
+      glLoadIdentity(); 
+      R ratio= (double) width / (double)  height; 
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity(); 
+      
+      
+      R aspect=ratio;
+      R3 DD(Bmin3,Bmax3);
+      DD.z *= rapz;
+      R dmax= DD.norme();;
+      R dist = 0.5*dmax/sin(focal/2)*coef_dist;
+       cam.x=Pvue3.x+cos(phi)*cos(theta)*dist;
+       cam.y=Pvue3.y+cos(phi)*sin(theta)*dist;
+       cam.z=Pvue3.z*rapz+dist*sin(phi);  
+      R znear=max(dist-dmax,1e-30);
+      R zfare=dist+dmax;
+      gluPerspective(focal*180./M_PI,aspect,znear,zfare);
+      /*      
+      if (eye)
+	{
+	  R dmm = -dmax*ceyes;
+	  R dx = -dmm*sin(theta);
+	  R dy = dmm*cos(theta);
+	  camx += dx*eye;
+	  camy += dy*eye;
+	  }
+      */
+      if(debug>2)
+	{
+	  cout <<" setview 3d: rapz " <<  rapz << " cam: ";
+	  cout << cam << " Pvue:" ;
+	  cout << Pvue3  << " theta " << theta << "  phi = "<<  phi << endl;
+	}
+      gluLookAt(cam.x,cam.y,cam.z,Pvue3.x,Pvue3.y,Pvue3.z*rapz,0.,0.,1.);
+      glScaled(1.,1.,rapz);   
+
+      glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
+      ShowGlerror(" Get PM");
+      glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
+      ShowGlerror(" Get MV");
+      glGetIntegerv(GL_VIEWPORT,viewport);
+      ShowGlerror(" Get VP");
+  
+
+      
+    }
+  else
+    {
+      ShowGlerror("Begin SetView");   
+      glDisable(GL_DEPTH_TEST);
+      glViewport(0, 0,width, height);
+      R dz0,dz1,zm=0;
+      if(plotdim==3)
+	{
+	    dz0=Bmin3.z;
+	    dz1=Bmax3.z;
+	}
+      else
+	{  
+	    R zzmin = Min(zmin,theplot->fminT);
+	    R zzmax = Max(zmax,theplot->fmaxT);    
+	    R dz = (zzmax-zzmin);
+	    zm=(zzmin+zzmax)*0.5;
+	    //  to be sur  the the z size is no zero . 
+	    dz = max(dz,(Bmax.x-Bmin.x)*0.1);
+	    dz = max(dz,(Bmax.y-Bmin.y)*0.1);
+	    dz0=-dz;
+	    dz1 = dz;
+	}
+	
+      if((debug>3 )) cout << "\t\t\t   SetView " << this << " " << Bmin  << " " 
+			  << Bmax  << " dz  " << dz0 << " " << dz1  
+			  << " theta " << theta << "  phi = "<<  phi << endl;
+      ShowGlerror("0 Set MV");
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+      ShowGlerror(" Set MV");
+      glMatrixMode(GL_PROJECTION); 
+      glLoadIdentity(); 
+      ShowGlerror(" Set PM 1");
+      glOrtho(Bmin.x,Bmax.x,Bmin.y,Bmax.y,dz0,dz1);
+      
+      ShowGlerror(" Set PM 2");
+      
+      R2 M=(Bmin+Bmax)/2.;
+      glTranslated(0,0,-zm);
+      
+      //glLineWidth(1);
+      //glColor3d(0.,0.,0.);
+
+      glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
+      ShowGlerror(" Get PM");
+      glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
+      ShowGlerror(" Get MV");
+      glGetIntegerv(GL_VIEWPORT,viewport);
+      ShowGlerror(" Get VP");
+  
+      
+      ShowGlerror("End SetView ");
+  }
+    
+}
+void  OneWindow::resize(int w,int h)
+{  double ww=width,hh=height;
+    width=w;
+    height=h;
+    if (theplot && theplot->aspectratio)
+      {	
+	  cadreortho(oBmin,oBmax);
+      }
+    
+}
+
+void OneWindow::zoom(R coef)
+{
+  coef_dist*=coef;
+  R2 M=(oBmin+oBmax)/2.;
+  R2 D=(oBmax-oBmin)/2.;
+  R2 A=  M - D*coef;
+  R2 B=  M + D*coef;
+  if (theplot->aspectratio)
+    cadreortho(A,B);
+  else 
+    cadre(A,B);
+
+}
+void  OneWindow::zoom(int w,int h,R coef)
+{
+    GLdouble x=w,y=height-h,z=(zmin+zmax)/2.;
+    GLdouble xx,yy,zz;
+    
+
+    GLint ok= gluUnProject( x,y,z,modelMatrix,projMatrix,viewport,&xx,&yy,&zz);
+    ShowGlerror(" UnPro .. ");
+    if(debug>2)
+      cout << " ok " << ok << " " << x << " " << y << " " << z 
+	   << " -> " << xx << " " << yy << " " << zz << endl;
+    R2  oD(oBmin,oBmax);
+    R2  D(Bmin,Bmax);
+    R2 O(xx,yy);// oBmin.x+D.x*xx/width,oBmin.y+D.y*yy/height); 
+    if((debug > 3)) cout<< " zoom : "  << this << " O " << O  
+			<< " " << coef << " D = "<<  D<< "as "
+			<< theplot->aspectratio <<  endl;
+    oD *= 0.5*coef;
+    R2 A = O - oD;
+    R2 B = O + oD;
+    if (theplot->aspectratio)
+	cadreortho(A,B);
+    else 
+	cadre(A,B);
+}
+void OneWindow::MoveXView(R dx,R dy) 
+{
+  R3 D(Bmin3,Bmax3);
+  R3 dd( dx*D.x*sin(theta),-dx*D.y*cos(theta), - dy*D.z);
+  if(debug>2)
+  cout << " MoveXView  "<< dx << " " << dy << " " << D << " mn: " << Bmin3 <<"  mx :" << Bmax3 << " d=" << dd << endl;
+  Pvue3 += dd/50.;
+  // 2d ...  add  FH   july 2009
+  R2 D2(-dx*5*hpixel,-dy*5*hpixel);
+  oBmin += D2;
+  oBmax += D2;
+  Bmin += D2;
+  Bmax += D2;
+
+
+  // cout << xm << " " << ym << " " << zm << endl;
+}
+
+void OneWindow::cadre(R2 A,R2 B)
+{
+      
+    oBmin=Bmin=A;
+    oBmax=Bmax=B;
+    hpixel = (Bmax.x-Bmin.x)/width;    
+    
+    
+}
+
+void OneWindow::getcadre(double &xmin,double &xmax,double &ymin,double &ymax)
+{
+    xmin =  Bmin.x;
+    xmax =  Bmax.x;
+    ymin = Bmin.y;
+    ymax = Bmax.y;
+    
+}
+void OneWindow::Display()
+{
+  if(!theplot) return;
+  ffassert(this && theplot);
+  SetScreenView() ;
+  glColor3d(0.,0.,0.);
+     
+  if(help)
+    {
+      theplot->DrawHelp(this);
+      help=false;
+    }
+  else
+    {
+  ShowGlerror("Begin Display");
+  
+  //  SetView();
+  if(theplot)
+    theplot->Draw(this);
+  ShowGlerror("After Display");
+    }
+}
+void OneWindow::cadreortho(R2 A, R2 B)
+{
+    R2 D(A,B);
+    oBmin=A;
+    oBmax=B;
+    
+    double cxy =  D.y*width/ (D.x*height);
+    
+    if ( D.y*width < D.x*height)  
+	// width -> infty => D.x la ref
+	D.y = D.x*(double) height/ width;
+    else // height -> infty => D.y la ref
+	D.x = D.y*(double) width/height;
+    R2 M=(A+B)/2., D2=D/2.;
+    
+    Bmin= M - D2;
+    Bmax= M + D2;
+    
+    if((debug > 10)) cout << " cadreortho: "<< " :: " << Bmin << " " << Bmax <<" oB " << oBmin << " " << oBmax << endl;
+    
+    // if((debug > 10)) cout << "cadreortho\n";
+}
+void OneWindow::setLighting()
+{
+  if(withlight)
+    {
+      if(plotdim==3)
+	{
+	  GLfloat lp0[4] = { (float) cam.x,(float)  cam.y, (float)  cam.z, 1.0F };
+	  glLightfv(GL_LIGHT0,GL_POSITION,lp0);	
+	  
+	  if(debug>1)  cout << " Light pos  3d:  " << cam << endl;
+	}
+      else
+	{
+	  GLfloat position[] = {(float) Pvue3.x,(float) Pvue3.y,(float) (Pvue3.z+(Bmax3.z-Bmin3.z)*3),1.f} ;
+	  glLightfv(GL_LIGHT0, GL_POSITION, position);
+	  
+	}
+      
+      float cca=0.3,ccd=1., ccs=0.8;
+      GLfloat ambient[] = {cca,cca,cca,1.0f};//diff�rents param�tres
+      GLfloat diffuse[] = {ccd,ccd,ccd,1.0f};
+      GLfloat specular_reflexion[] = {ccs,ccs,ccs,1.0f};
+      GLubyte shiny_obj = 128;
+      glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1);
+      glEnable(GL_LIGHTING);//positionnement de la lumi�re avec
+      glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);//les diff�rents param�tres
+      glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
+      
+      glEnable(GL_COLOR_MATERIAL);//sp�cification de la r�flexion sur les mat�riaux
+      glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuse);
+      // glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular_reflexion);// on peut le faire avant chaque objet
+      //glMateriali(GL_FRONT_AND_BACK,GL_SHININESS,shiny_obj);//si on veut qu'ils aient des caract�ristiques #
+      glShadeModel(GL_FLAT);  
+      glEnable(GL_LIGHTING);
+      glEnable(GL_LIGHT0); 
+    }
+  else
+    {
+      glDisable(GL_LIGHTING);
+      glDisable(GL_LIGHT0);
+    }
+
+}
+
+void OneWindow::unsetLighting()
+{
+  glDisable(GL_LIGHTING);
+  glDisable(GL_LIGHT0);
+  //g->lightning=false;
+}
+
+OnePlotBorder::OnePlotBorder(PlotStream & f) 
+  :OnePlot(4,2,1)
+{ 
+    long nbd;
+    f>> nbd;
+    data.resize(nbd);
+    for(int i=0;i<nbd;++i)
+      {
+	  long n; 
+	  f>> n;
+	  //cout << n << endl;
+	  data[i].resize(n+1);
+	  for(int j=0;j<=n;++j)
+	    {
+		long l; 
+		double x,y;
+		f >> l>> x >> y;
+		// cout << x << ' ' << y << ' ' <<  l << endl;
+		R2 P(x,y);
+		Pmin=Minc(Pmin,P);
+		Pmax=Maxc(Pmax,P);
+		data[i][j]=make_pair(l,P);
+	    }
+      }
+    ffassert(f.good());
+}
+
+void OnePlot::GLDraw(OneWindow *win)
+{
+  ThePlot & plot= *win->theplot; 
+  Draw(win);
+  
+  win->changeiso=0;
+  win->changearrow=0; 
+}
+
+void ThePlot::DrawHelp(OneWindow *win) 
+{
+  int i = 1;
+  win->Show("Enter a keyboard character in the FreeFem Graphics window in order to:",i++);
+  
+  i+=1;
+  win->Show("enter) wait next plot",i++);
+  win->Show("p)     previous plot (10 plots saved) ",i++);
+  win->Show("ESC)   exit from ffglut (if termined) ",i++);
+  win->Show("^c)    non-ignorable exit from ffglut  ",i++);
+  win->Show("?)  show this help window",i++);
+  win->Show("+) -)   zoom in/out  around the cursor 3/2 times ",i++);
+  win->Show("=)   reset vue ",i++);
+  win->Show("r)   refresh plot ",i++);
+  win->Show("up, down, left, right) special keys  to  tanslate   ",i++);
+  win->Show("3)   switch 3d/2d plot (in test)  keys : ",i++);
+  win->Show("        z) Z) (focal zoom unzoom)  ",i++);
+  win->Show("        H) h) switch increase or decrease the Z scale of the plot ",i++);
+  win->Show("mouse motion)    ",i++);
+  win->Show("   - left button)  rotate    ",i++);
+  win->Show("   - right button)       zoom        (ctrl+button on mac) ",i++);
+  win->Show("   - right button +alt)  tanslate    (alt+ctrl+button on mac)",i++);
+
+  win->Show("a) A) increase or decrease the arrow size",i++);
+  win->Show("B)  switch between show  border meshes or not",i++);
+  win->Show("i) I) update or not: the min/max bound of the functions to the window",i++);
+  win->Show("n) N) decrease or increase the number of iso value array ",i++);
+  win->Show("b)  switch between black and white or color plotting ",i++);
+  win->Show("g)  switch between grey or color plotting ",i++);
+  win->Show("f)  switch between filling iso or iso line  ",i++);
+  win->Show("l)  switch between lighting or not  ",i++);
+  win->Show("v)  switch between show or not the numerical value of colors ",i++);
+  win->Show("m)  switch between show or not  meshes  ",i++);
+  win->Show("w)  window dump in file ffglutXXXX.ppm ",i++);
+  win->Show("*)  keep/unkeep viewpoint for next plot",i++);
+  win->Show("k)  complex data / change view type ",i++);
+    
+  win->Show("any other key : nothing ",++i);
+}
+
+void ThePlot::dyn_bfv(OneWindow *win,R & fmn,R &fmx,R & vmn2,R & vmx2) const 
+{
+  fmn=+1e100;
+  fmx=-fmn;
+  vmx2=0;
+  vmn2=fmin;
+  for (list<OnePlot *>::const_iterator i= plots.begin();i != plots.end(); ++i)
+    {
+      if(*i)  (*i)->dyn_bfv(win,fmn,fmx,vmn2,vmx2) ;
+    }
+  if(debug>4)
+    cout << "dyn_bfv  " << fmn << " " << fmx << endl;
+  if(fmn>fmx) fmn=fmin,fmx=fmax;
+  if(vmn2>vmx2) vmn2=0,vmx2=vmax2;
+}
+
+bool ThePlot::NextCase() 
+{
+  bool ret=false;
+  for (list<OnePlot *>::iterator i= plots.begin();i != plots.end(); ++i)
+    ret =  (**i).NextCase() || ret; //  alway  run NextCase ..  
+  return  ret;
+}
+
+void ThePlot::Draw(OneWindow *win) 
+{
+    if((debug>1 )) 
+      { 
+	cout << "      ThePlot::Plot " << count << " " << this << " win " << win << " " << state ;
+	for (list<OnePlot *>::iterator i= plots.begin();i != plots.end(); ++i)
+	  cout << (**i).what;
+	cout << endl;
+	
+      }
+    if(state==0) {
+      state=1;
+      win->DefaultView(0);
+    }
+
+    win->SetView();
+    for (list<OnePlot *>::iterator i= plots.begin();i != plots.end(); ++i)
+	(*i)->Draw(win);
+    
+    if(cm || value)
+      { //  screen plot ...
+	win->SetScreenView();
+	if(cm)
+	  {
+	    color(1);
+	    win->DrawCommentaire(cm->c_str(),0.1,0.97);
+	  }
+	if(value)
+	  {  
+	    int k0=0;
+	    if(withiso)
+	      {
+		win->PlotValue(Viso,k0,"IsoValue");
+		k0=1+Viso.N();
+	      }
+	    if(witharrow)
+	      win->PlotValue(Varrow,k0,"Vec Value");
+	  }
+	// for picking..
+	win->SetView();
+      }
+    changeViso=false;
+    changeVarrow=false;
+    changeColor=false;
+    changeBorder=false;
+    changeFill=false;
+}
+
+void  ThePlot::SetColorTable(int nb)
+{
+    tbc.resize(nb);
+    for (int i=0;i<nb;++i)
+	tbc[i].set(i,nb,this);    
+}
+
+
+
+ThePlot::ThePlot(PlotStream & fin,ThePlot *old,int kcount)
+  :  count(kcount), state(0),
+     changeViso(true),changeVarrow(true),changeColor(true),
+     changeBorder(true),changeFill(true), withiso(false),witharrow(false),
+     plotdim(2),theta(30.*M_PI/180.),phi(20.*M_PI/180.),dcoef(1),focal(20.*M_PI/180.),
+     datadim(1), winnum(0)
+     
+{
+  
+  hsv=true; // hsv  type   
+  coeff=1;
+  wait=0;
+  value=false;
+  fill=false;
+  aspectratio=false;
+  clean=true;
+  uaspectratio=false;
+  pViso=false;
+  pVarrow=false;
+  Niso=0;
+  Narrow=20;
+  bw=false;
+  psfile=0;
+  cm=0;
+  grey=0;
+  if(old) {
+    grey=old->grey;
+  }
+  greyo=grey;
+  drawborder=true;
+  drawmeshes=false;
+  add=false; 
+  keepPV=false;
+  echelle=1.;
+    
+  Pmin=R3(+dinfty,+dinfty,+dinfty);
+  fmin = +dinfty;    
+  fmax = -dinfty;
+  Pmax=R3(-dinfty,-dinfty,-dinfty);
+  vmax2=0;
+  
+  coefr=1;
+  long dimpp=0;
+  long cas;
+#define READ_VTK_PARAM(index,type)					\
+case 20+index: {type dummy; fin >= dummy;} break;
+  
+  while(1)
+    {
+
+	fin >> cas;
+	if((debug > 4)) cout << " read cas: " << cas << "  " << PlotStream::dt_endarg << endl;
+	if(cas==PlotStream::dt_endarg) break;
+	if(version==2)
+	  switch (cas) {
+	  case  0: fin >> coeff; break;
+	  case 1: fin >> cm; break;
+	  case 2: fin >> psfile; break;
+	  case 3: fin >> wait; break;
+	  case 4: fin >> fill; break;
+	  case 5: fin >> value; break;
+	  case 6: fin >> clean; break;
+	  case 7: fin >> aspectratio;uaspectratio=true; break;
+	  case 8: fin >> boundingbox; break;
+	  case 9: fin >> Niso; break;
+	  case 10: fin >> Narrow; break;
+	  case 11: fin >> Viso;Niso=Viso.N();pViso=true; break;
+	  case 12: fin >> Varrow;Narrow=Varrow.N();pVarrow=true; break;
+	  case 13: fin >> bw; break;
+	  case 14: fin >> grey; break;
+	  case 15: fin >> colors; break;
+	  case 16: fin >> drawborder; break;
+	  case 17: fin >> dimpp; break;// ajout fevr 2008  v3.0.6
+	  case 18: fin >> add; break;
+	  case 19: fin >> keepPV; break;
+	  case 20: fin >> echelle;break;
+ 	  default: 
+	    cout << "Fatal error: Unknow  case  : " << cas <<endl;
+	    ffassert(0);
+	    break;
+	  }
+	else if(version ==3)
+	  switch (cas) {
+	  case  0: fin >= coeff; break;
+	  case 1: fin >= cm; break;
+	  case 2: fin >= psfile; break;
+	  case 3: fin >= wait; break;
+	  case 4: fin >= fill; break;
+	  case 5: fin >= value; break;
+	  case 6: fin >= clean; break;
+	  case 7: fin >= aspectratio;uaspectratio=true; break;
+	  case 8: fin >= boundingbox; break;
+	  case 9: fin >= Niso; break;
+	  case 10: fin >= Narrow; break;
+	  case 11: fin >= Viso;Niso=Viso.N();pViso=true; break;
+	  case 12: fin >= Varrow;Narrow=Varrow.N();pVarrow=true; break;
+	  case 13: fin >= bw; break;
+	  case 14: fin >= grey; break;
+	  case 15: fin >= colors; break;
+	  case 16: fin >= drawborder; break;
+	  case 17: fin >= dimpp; break;// ajout fevr 2008  v3.0.6
+	  case 18: fin >= add; break;
+	  case 19: fin >= keepPV; break;
+	  case 20: fin >= echelle;break;
+                  // unsed parameter ...
+                  READ_VTK_PARAM(1,double); // ZScale
+                  READ_VTK_PARAM(2,bool); // WhiteBackground
+                  READ_VTK_PARAM(3,bool); // OpaqueBorders
+                  READ_VTK_PARAM(4,bool); // BorderAsMesh
+                  READ_VTK_PARAM(5,bool); // ShowMeshes
+                  READ_VTK_PARAM(6,long); // ColorScheme
+                  READ_VTK_PARAM(7,long); // ArrowShape
+                  READ_VTK_PARAM(8,double); // ArrowSize
+                  READ_VTK_PARAM(9,long); // ComplexDisplay
+                  READ_VTK_PARAM(10,bool); // LabelColors
+                  READ_VTK_PARAM(11,bool); // ShowAxes
+                  READ_VTK_PARAM(12,bool); // CutPlane
+                  READ_VTK_PARAM(13,KN<double>); // CameraPosition
+                  READ_VTK_PARAM(14,KN<double>); // CameraFocalPoint
+                  READ_VTK_PARAM(15,KN<double>); // CameraViewUp
+                  READ_VTK_PARAM(16,double); // CameraViewAngle
+                  READ_VTK_PARAM(17,KN<double>); // CameraClippingRange
+                  READ_VTK_PARAM(18,KN<double>); // CutPlaneOrigin
+                  READ_VTK_PARAM(19,KN<double>); // CutPlaneNormal
+                  //  SEND_VTK_PARAM(20,long); // WindowIndex
+              case 40: fin >= winnum; break;
+	    
+	  default: 
+	    static int nccc=0;
+	    if(nccc++<5)
+	      cout << " Skip Unknow case " << cas <<" (ffglut is too old ?)\n";
+	    fin.SkipData();
+	    break;
+	  }   
+	else ffassert(0);
+	ffassert(fin.good() && ! fin.eof());
+    }
+  if(dimpp) plotdim=dimpp; 
+  //    if( !uaspectratio) aspectratio= true;
+  ffassert(cas==PlotStream::dt_endarg);
+  if((debug > 2))
+    {
+      cout << " Window num " << winnum << ", ";
+      cout << " coeff " << coeff <<", ";
+      if(cm)
+	cout << " cm " << *cm <<", ";
+      if(wait)	cout << " wait " ;
+      if(fill)	cout << " fill " ;
+      if(value)	cout << " value " ;
+      if(bw)	cout << " bw " ;
+      if(grey)	cout << " grey " ;
+      if(drawborder)	cout << " drawborder " ;
+      if(colors.N()) cout << "\n colors =" << colors;
+      if(boundingbox.N()) cout << "\n bb  =" << boundingbox;
+      
+      cout << endl;
+    } 
+  fin.GetMeshes();  
+  long nbmeshes;
+  fin >> nbmeshes;
+  if((debug > 2)) cout << " read nb : mesh " << nbmeshes << endl;
+  if(version==2)
+    {
+      Ths.resize(nbmeshes);    
+      for(int i=0;i<nbmeshes;++i)
+	Ths[i]=0;
+    }
+  else
+    {
+      Ths2.resize(nbmeshes);    
+      for(int i=0;i<nbmeshes;++i)
+	Ths2[i]=0;
+    }
+  
+  for(int i=0;i<nbmeshes;++i)
+    { 
+      long l;
+      fin >> l;
+      if(l>=0) 
+	{
+	  if((debug > 3)) cout << " read mesh " << i  << " -> " << l << "  " <<nbmeshes << endl;
+	  l--;
+	  ffassert(l>=0 && l < nbmeshes);
+	  if(version==2)
+	  {
+	    ffassert(Ths[l]==0);
+	    fin >>Ths[l] ;
+	  }
+	  else
+	    {
+	      ffassert(Ths2[l]==0);
+	      fin >>Ths2[l] ;
+	    }
+	  
+	  if((debug > 3))
+	    {
+	    if(version==2)
+	      cout << i << " nt/nv " << l << " "  <<Ths[l]->nt << " " << Ths[l]->nv << endl;
+	    else
+	      cout << i << " nt/nv " << l << " "  <<Ths2[l]->nt << " " << Ths2[l]->nv << endl;
+	    }
+	  ffassert(fin.good());
+	}
+      else // Add FH optimisation FH 11/12/2008 (not use to day)
+	{// the mesh is already in the previous plot with number ll
+	  ffassert(l==-1);
+	  long ll;
+	  fin >> l>> ll; // read l and ll
+	  ffassert(old);
+	  if(version==2)
+	    {
+	      Ths[l]=old->Ths[ll];
+	      Ths[l]->increment(); // 
+	    }
+	  else
+	    {
+	      Ths2[l]=old->Ths2[ll];
+	      Ths2[l]->increment(); // 
+	    }
+	  
+	}
+      
+    }
+  long nbmeshes3=0;
+  if(fin.GetMeshes3()) //  read GetPlots if false ...
+    { //  il y a des solution 3d; 
+      
+      fin >> nbmeshes3;
+      if((debug > 2)) cout << " read nb : mesh3 " << nbmeshes3 << endl;
+      Ths3.resize(nbmeshes3);
+      for(int i=0;i<nbmeshes3;++i)
+	Ths3[i]=0;
+      for(int i=0;i<nbmeshes3;++i)
+	{ 
+	  long l;
+	  fin >> l;
+	  if(l>=0) 
+	    {
+	      if((debug > 3)) cout << " read mesh3 " << i  << " -> " << l 
+				   << "  " <<nbmeshes3 << endl;
+		   l--;
+		   ffassert(l>=0 && l < nbmeshes3);
+		   ffassert(Ths3[l]==0);
+		   fin >>Ths3[l] ;
+		   if((debug > 3))
+		     cout << i << " nt/nv " << l << " "  <<Ths3[l]->nt << " " 
+			  << Ths3[l]->nv << endl;
+		   ffassert(fin.good());
+	    }
+	  else // Add FH optimisation FH 11/12/2008 (not use to day)
+		 {// the mesh is already in the previous plot with number ll
+		   ffassert(l==-1);
+		   long ll;
+		   fin >> l>> ll; // read l and ll
+		   ffassert(old);
+		   Ths3[l]=old->Ths3[ll];
+		   Ths3[l]->increment(); // 
+		 }
+	  
+	}	 
+      
+      fin.GetPlots(); 
+    }
+ 
+  long nbplot;
+  int iso3d=0;
+  fin >>nbplot;
+  if((debug > 2)) cout << " nb item plot " << nbplot << endl;
+  for(int i=0;i<nbplot;++i)
+    {
+      long what;
+      OnePlot *p=0;
+      fin >> what;
+      long imsh;
+      if((debug > 2)) cout << "    plot  " << i << " what " << what << endl;
+      if(what !=3 && !uaspectratio) aspectratio= true;
+      if(what==-1)  // gestion of error (empty plot)
+	p = new OnePlotError(fin);
+      else if(what==0) 
+	{ 
+	  
+	  fin >> imsh;
+	  if(version==2)
+	    p=new OnePlotMesh<Mesh>(Ths[imsh-1]);
+	  else
+	    p=new OnePlotMesh<Mesh2>(Ths2[imsh-1]);
+	  
+	}
+      else if (what==1 || what==2 || what==11 || what==12 )
+	{
+	  fin >> imsh;
+	  if(what%10==1) withiso=true;
+	  else if (what%10==2) witharrow=true;
+	  if((debug >= 10)) cout << " plot : mesh " << imsh << endl;
+	  ffassert(imsh>0 && imsh <=nbmeshes);
+	  if(version==2)
+	    p=new OnePlotFE<Mesh>(Ths[imsh-1],what,fin);
+	  else 
+	    p=new OnePlotFE<Mesh2>(Ths2[imsh-1],what,fin);
+	}
+      else if(what==3)
+	p=new OnePlotCurve(fin);
+      else if(what==4)
+	p=new OnePlotBorder(fin);
+      else if(what==5) 
+	{ 	    
+	  fin >> imsh;
+	    p=new OnePlotMesh3(Ths3[imsh-1]);
+	}
+      else if (what==6  || what==7|| what==16  || what==17)
+	{
+	  iso3d++;
+	  fin >> imsh;
+	  if(what==6||what==16 ) withiso=true;
+	  
+	  if((debug > 10)) cout << " plot : mesh3 " << imsh << endl;
+	  ffassert(imsh>0 && imsh <=nbmeshes3);
+	  p=new OnePlotFE3(Ths3[imsh-1],what,fin);
+	}
+      
+      else
+	{
+	  cout << "Bizarre unkown what :  " << what<< endl;
+	  ffassert(0);
+	}
+      ffassert(p);
+      plots.push_back(p);
+      p->bb(Pmin,Pmax);
+      p->bfv(fmin,fmax,vmax2);
+      plotdim=max(plotdim,p->dim);
+      ffassert(fin.good());		      
+      datadim=max(datadim,p->dim); 
+    }
+  if(Niso==0) 
+    Niso = iso3d ? 5 : 20;
+  
+  // cout << "\t\t\t\t  f min, max v max :" << fmin << " " << fmax << " " << vmax2 << endl;
+  
+  double ref_f = abs(fmax)+abs(fmin) ; 
+  if(fmax < fmin)
+    {
+      fmax = 1;
+      fmin = 0;
+    }
+  else if( (fmax-fmin) <= 1e-8*ref_f)
+    {
+      if(ref_f< 1e-20) ref_f=0.5;
+      fmax += ref_f/2;
+      fmin -= ref_f/2;
+    }
+  PminT=Pmin;
+  PmaxT=Pmax;
+  fminT=fmin;
+  fmaxT=fmax;
+  if(old && 0)
+    {
+      Pmin= Minc(Pmin,old->PminT);
+      Pmax= Maxc(Pmax,old->PmaxT);
+      fmax= Max(fmax,old->fmaxT);
+      fmin= Min(fmin,old->fminT);
+    }
+  
+  z0= fminT +(fmaxT-fminT)*0.01;
+  if((debug > 2)) cout << "               data bound: " << PminT << " " << PmaxT  
+		       << " fmin == " << fminT << "  " << fmaxT 
+		       << " z0 " << z0 <<  endl;
+  fin.GetEndPlot(); 
+  Viso.resize(Niso);
+  Varrow.resize(Narrow);
+  
+  SetColorTable(Max(Niso,Narrow)+4) ;           
+  SetDefIsoV() ;
+
+}
+
+
+void ThePlot::SetDefIsoV(int niso,int narr,double fmn,double fmx,double vmn,double vmx)
+{
+  bool dyn=false; 
+  R d,x;
+  
+  if( fmx>fmn)
+    {
+      if(debug>3)
+	cout << "Set Def dyn_bfv  " << fmn << " " << fmx << endl;
+
+      if(niso>2) 
+	Viso.resize(niso); 
+      Niso=Viso.N();
+      Narrow=narr;
+      d =  (fmx-fmn)/(Niso-2) ;
+      x =  (fmn+fmx)/2-d*0.5*(Niso-1);
+      dyn=true;
+    }
+  else
+    {
+      d = 1 ? (fmaxT-fminT)/(Niso-2)  : (fmaxT-fminT)/(Niso-1);       
+      x = 1 ? (fminT+fmaxT)/2-d*0.5*(Niso-1) :fminT+d/2;
+    }
+  if(!pViso || dyn)
+    {
+      for (int i = 0;i < Niso;i++)
+	{Viso[i]=x;x +=d; }
+      //if (fill ) {Viso[0]=fminT-d;Viso[Niso-1]=fmaxT+d;}    
+    }
+  dyn=false;
+
+  if(vmx>vmn)
+    {
+      if(narr>2) 
+	Varrow.resize(niso); 
+      Narrow=Varrow.N();
+      dyn=true;
+      x = sqrt(vmn);
+      d = (sqrt(vmx)-x)/(Narrow-1.1);
+    }
+  else
+    {
+      x=0; 
+      if(debug>10)
+	cout << "vmax2=  " << vmax2 << endl;
+      d= sqrt(vmax2)/(Narrow-1.1);
+    }   
+  if (!pVarrow || dyn)
+    for (int i = 0;i < Narrow;i++)
+      {
+	Varrow[i]=x;
+	x +=d; 
+      }
+  if(debug>100)
+    cout << " Viso ..; " << Viso <<endl;
+  SetColorTable(Max(Niso,Narrow)+4) ; 
+}
+
+void OneWindow::Show(const char *str,int i)
+{
+  int hx= 15;
+  int ix= width/20;
+  int iy= height-hx*i;
+  plot(ix,iy,str,3);
+}
+
+void  FillRectRasterPos(R x0,R y0,R x1,R y1)
+{
+  //  if((debug > 10)) cout << "FR Rp:   " << x0 << " " << y0 << " " << x1 << " " << y1 << endl;
+  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);//GL_FILL
+  glBegin(GL_POLYGON);
+  glVertex2d(x0, y0);
+  glVertex2d(x1, y0);
+  glVertex2d(x1, y1);
+  glVertex2d(x0, y1);
+  glEnd();
+  
+}
+
+void  OneWindow::FillRect(R x0,R y0,R x1,R y1)
+{
+  
+  double z1=  (zmin+zmax)/2; // line 
+  glPolygonMode(GL_FRONT,GL_FILL);//GL_FILL
+  glBegin(GL_POLYGON);
+  glVertex3d(x0, y0,z1);
+  glVertex3d(x1, y0,z1);
+  glVertex3d(x1, y1,z1);
+  glVertex3d(x0, y1,z1);
+  glEnd();
+}
+
+void OneWindow::PlotValue(const KN_<double> & Viso,int  k0,const char * cmm)
+{
+  
+  ShowGlerror("PlotValue b");
+  //  glRasterPos2f(x,y);
+  if((debug > 10)) cout << "PlotValue:" << cmm << " " << k0 << " " << width << " " <<height << endl;
+  R xmin=0,xmax=width,ymin=0,ymax=height;
+  if((debug > 10)) cout << "PlotValue " << Viso << endl;
+  // int ix,iy;
+  // GetSizeScreen(ix,iy);   
+  
+  R dx=(xmax-xmin);
+  R dy=(ymax-ymin);
+  //  10 points  
+  // int kk = Max(30,iy/10);
+  R h=10;
+  R ho=h*1.1;
+  R x0=xmin+dx*0.85;
+  R y= ymin+dy*0.97;
+  if((debug > 10)) cout << x0 << " " << y << " " << h <<  endl;
+  y -= k0* ho;
+  this->color(0);
+  FillRectRasterPos(x0-h*0.5,y-h*(1.4*Viso.N()+0.3),x0+h*9,y+h*1.5);
+  ShowGlerror("PlotValue m");
+  this->color(1);
+
+  plot(x0+ho,y,cmm);
+  y -=  ho;
+  for (int i=0;i<Viso.N();i++)
+    {
+      if((debug > 10)) cout << " x0 : " << x0<< " " << y << " " << h << " v = " << Viso[i] << endl;
+      this->color(i+4);
+      FillRectRasterPos(x0,y,x0+h,y+h);
+      plot(x0+ho,y+3*h/10,Viso[i]);
+      y -=  ho;
+      ;                 
+    }
+  ShowGlerror("PlotValue f");
+}
+
+
+void OneWindow::DrawCommentaire(const char * cm,R x,R y) 
+{
+  
+    R xmin=0,xmax=height,ymin=0,ymax=height;
+    float dx=(xmax-xmin);
+    float dy=(ymax-ymin);    
+    plot(xmin+dx*x,ymin+dy*y,cm);   
+}
+
+/*
+ void drwstr(R x,R y,char* format, ...) {
+ va_list  args;
+ char  *s,buffer[1024];
+ 
+ va_start(args,format);
+ vsnprintf(buffer,1024,format,args);
+ va_end(args);
+ }
+ */
+void  plot(double xx,double yy,const char *cmm,int font)
+{
+    glRasterPos2f(xx,yy);   
+    float x[4];
+    glGetFloatv(GL_CURRENT_RASTER_POSITION,x);
+    if((debug > 10)) cout<<"avant x : "<<x[0]<<" y : "<<x[1]<<" z : "<<x[2]<< " " << xx <<" " << yy << endl;
+    /*
+      #define GLUT_BITMAP_9_BY_15((void*)2)
+      #define GLUT_BITMAP_8_BY_13((void*)3)
+      #define GLUT_BITMAP_TIMES_ROMAN_10((void*)4)
+      #define GLUT_BITMAP_TIMES_ROMAN_24((void*)5)
+      #define GLUT_BITMAP_HELVETICA_10((void*)6)
+      #define GLUT_BITMAP_HELVETICA_12((void*)7)
+      #define GLUT_BITMAP_HELVETICA_18((void*)8)
+     */
+    void * glut_font=GLUT_BITMAP_TIMES_ROMAN_10;    
+    switch (font)
+      {
+      case  0: glut_font=GLUT_STROKE_ROMAN;break;
+      case  1: glut_font=GLUT_STROKE_MONO_ROMAN;break;
+      case  2: glut_font=GLUT_BITMAP_9_BY_15;break;
+      case  3: glut_font=GLUT_BITMAP_8_BY_13;break;
+      case  4: glut_font=GLUT_BITMAP_TIMES_ROMAN_10;break;
+      case  5: glut_font=GLUT_BITMAP_TIMES_ROMAN_24;break;
+      case  6: glut_font=GLUT_BITMAP_HELVETICA_10;break;
+      case  7: glut_font=GLUT_BITMAP_HELVETICA_12;break;
+      case  8: glut_font=GLUT_BITMAP_HELVETICA_18;break;
+
+
+	
+      }
+    for (const char *s=cmm; *s; s++)
+      {if((debug > 10)) cout << *s ;
+	glutBitmapCharacter(glut_font,*s);
+      }
+    if((debug > 10)) cout << " ;;; " <<endl;
+}
+void plot(double x,double y,double i,int font)
+{
+    char buf[24];
+    snprintf(buf,24,"%g",i);
+    plot(x,y,buf);
+}
+
+
+void hsvToRgb (float h, float s, float v, float & r, float & g, float & b)
+{
+    int i;
+    float aa, bb, cc, f;
+    
+    if (s == 0) /* Grayscale */
+	r = g = b = v;
+    else {
+	if (h == 1.0) h = 0;
+	h *= 6.0;
+	i =  int(h);
+	f = h - i;
+	aa = v * (1 - s);
+	bb = v * (1 - (s * f));
+	cc = v * (1 - (s * (1 - f)));
+	switch (i) {
+	    case 0: r = v;  g = cc; b = aa; break;
+	    case 1: r = bb; g = v;  b = aa; break;
+	    case 2: r = aa; g = v;  b = cc; break;
+	    case 3: r = aa; g = bb; b = v;  break;
+	    case 4: r = cc; g = aa; b = v;  break;
+	    case 5: r = v;  g = aa; b = bb; break;
+	}
+    }
+}
+
+void ThePlot::DrawIsoT(const R2 Pt[3],const R ff[3],const R * Viso,int NbIso, R rapz)
+{
+    glBegin(GL_LINES);
+    R2 PQ[5];
+    //int NbIso = Viso.N();
+    R  eps2= Min(R2(Pt[0],Pt[1]).norme2(),R2(Pt[0],Pt[2]).norme2(),R2(Pt[1],Pt[2]).norme2() )*1e-8;
+    for(int l=0;l< NbIso;l++)  /*    loop on the level curves */
+      {
+	  R xf = Viso[l];
+	  int im=0;
+	  for(int i=0;i<3;i++) // for the  3 edges 
+	    {
+		int j = (i+1)%3;
+		R fi=(ff[i]);
+		R fj=(ff[j]);
+		
+		if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+		  {
+		      if (Abs(fi-fj)<=0.1e-10) 	/* one side must be drawn */
+			{
+			    color(l+4);
+			    glVertex3f(Pt[i].x, Pt[i].y,xf*rapz);
+			    glVertex3f(Pt[j].x, Pt[j].y,xf*rapz);
+
+			    //MoveTo(Pt[i]);
+			    //LineTo(Pt[j]);
+			}
+		      else 
+			{
+			    R  xlam=(fi-xf)/(fi-fj);
+			     
+			    PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+			}
+		  }
+	    }
+	  
+	  if (im>=2) /*    draw one segment */
+	    {
+		color(l+4);
+		//MoveTo(PQ[0]);
+		//LineTo(PQ[1]);
+	      if( R2(PQ[0],PQ[1]).norme2() > eps2 )
+		{
+		glVertex3f(PQ[0].x, PQ[0].y,xf*rapz);
+		glVertex3f(PQ[1].x, PQ[1].y,xf*rapz);
+		}
+	    }
+      }
+    glEnd();
+    
+} 
+
+void ThePlot::DrawIsoTfill(const R2 Pt[3],const R ff[3],const R * Viso,int NbIso, R rapz)
+{
+    R2 PQ[10];
+    R z[10];
+    
+    R eps= (Viso[NbIso-1]-Viso[0])*1e-6;
+    for(int l=1;l< NbIso;l++)  //   loop on the level curves 
+      {
+	  R xfb = Viso[l-1];
+	  R xfh = Viso[l];
+	  assert(xfb < xfh);
+	  int im=0;
+	  for(int i=0;i<3;i++) // for the  3 edges 
+	    {
+		int j=(i+1)%3;
+		R fi=(ff[i]);
+		R fj=(ff[j]);
+		R xxfb =  xfb;
+		R xxfh =  xfh;
+		if (fj<fi ) Exchange(xxfb,xxfh);
+		R xf  = xxfb;
+		if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+		  {
+		      if (Abs(fi-fj)>=0.1e-20)
+			{
+			    R  xlam=(fi-xf)/(fi-fj);
+			    z[im] =  ff[i] * (1.F-xlam)  +  ff[j]* xlam;
+			    PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+			    
+			}
+		  }
+		xf = xxfh;  
+		if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+		  {
+		      if (Abs(fi-fj)>=0.1e-20)
+			{
+			    R  xlam=(fi-xf)/(fi-fj);
+			    z[im] =  ff[i] * (1.F-xlam)  +  ff[j]* xlam;
+			    PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+			}
+		  }
+		if (  xfb-eps <=fj  && fj <= xfh+eps) 
+		    z[im]=ff[j],PQ[im++] = Pt[j];
+		
+	    }
+	  if (im>2) 
+	    {
+	      color(l+4);
+	      R3 P[10];
+	      for(int i=0;i<im;++i)
+		P[i]= R3(PQ[i].x,PQ[i].y,z[i]*rapz);
+	      R3 N(R3(P[0],P[1])^R3(P[0],P[2]));
+	      N /= N.norme();
+	      if(N.z<0) N = -N;
+	      glNormal3d(N.x,N.y,N.z);
+	      
+	      glBegin(GL_POLYGON);
+	      //SetColor((xfb+xfh)/2); 
+	      for (int i=0;i<im;i++)
+		{// if((debug > 10)) cout << i << " \t : " << PQ[i].x << " " <<  PQ[i].y << " " << z[i]*rapz << endl;
+		  glVertex3f(P[i].x, P[i].y,P[i].z);
+		}
+	      glEnd();
+	      
+	    }
+      }
+} 
+
+
+bool WindowDump(int width,int height)
+{
+    int i,j;
+    FILE *fptr;
+    static int counter = 0;
+    char fname[32];
+    unsigned char *image;
+    
+    /* Allocate our buffer for the image */
+    if ((image = new unsigned char[3*width*height]) == NULL) {
+	fprintf(stderr,"WindowDump - Failed to allocate memory for image\n");
+	return(false);
+    }
+    
+    /* Open the file */
+    sprintf(fname,"ffglut_%04d.ppm",counter);
+    if ((fptr = fopen(fname, MODE_WRITE_BINARY)) == NULL) {
+	fprintf(stderr,"WindowDump - Failed to open file for window dump\n");
+	return(false);
+    }
+    if((debug > 10)) cout << " WindowDump in " << fname << endl;
+    /* Copy the image into our buffer */
+    glReadBuffer(GL_FRONT);
+    glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,image);
+    
+    /* Write the PPM file */
+    fprintf(fptr,"P6\n%d %d\n255\n",width,height);
+    for (j=height-1;j>=0;j--) {
+	for (i=0;i<width;i++) {
+	    fputc(image[3*j*width+3*i+0],fptr);
+	    fputc(image[3*j*width+3*i+1],fptr);
+	    fputc(image[3*j*width+3*i+2],fptr);
+	}
+    }
+    fclose(fptr);
+    
+    delete [] image;
+    counter++;
+    return(true);
+}
+
+
+void Clean() 
+{
+    glClearColor(1.0, 1.0, 1.0, 0.0);
+    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+}
+
+static void Reshape( int width, int height )
+{   
+    OneWindow * win=CurrentWin();
+    if(win)
+	win->resize(width,height);
+    glutPostRedisplay();
+}
+
+
+
+void Display(void)
+{ 
+    OneWindow * win=CurrentWin();
+    if(win) 
+      {
+	  /*    if (win->stereo)
+	   { ffassert(0); 
+	   
+	   glClearColor(1.0, 1.0, 1.0, 0.0);
+	   glDrawBuffer(GL_BACK_RIGHT);
+	   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	   global->SetView(-1);
+	   glCallList(TheDrawList);    
+	   glClearColor(1.0, 1.0, 1.0, 0.0);
+	   glDrawBuffer(GL_BACK_LEFT);
+	   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	   global->SetView(+1);
+	   glCallList(TheDrawList);    
+	   
+	   //win->Display();
+	   glFlush();
+	   glutSwapBuffers();
+	   }
+	   else */
+	{
+	    Clean();
+	    win->Display();
+	    glFlush();
+	    glutSwapBuffers();
+	    if ( win->windowdump)
+		WindowDump(win->width,win->height);
+	    win->windowdump=false;
+	}
+	  
+      }
+
+    if(!win->theplot || !win->theplot->wait || gwait )
+      SendForNextPlot();
+
+    if(!NoMorePlotTilte  &&NoMorePlot)
+      {
+	NoMorePlotTilte=true;
+	glutSetWindowTitle("FreeFem++ / Program ended; enter ESC to exit)");
+//          if(gwait) {usleep((useconds_t)(1e6*gwait)); Fin(0); }
+      }
+}
+
+static void Mouse( int button,int state,int x,int y )
+{
+    // state up or down 
+    OneWindow * win=CurrentWin();
+     keyact = glutGetModifiers();
+    switch(button)
+      {
+      case GLUT_LEFT_BUTTON:
+        casemouse=GLUT_LEFT_BUTTON;
+	if(win)
+	  {
+	    if(win && state == GLUT_DOWN) { win->xold=x,win->yold=y;return;}
+	    win->phi += (y-win->yold)/(2.*180.);
+	    win->theta -= (x-win->xold)/(2*180.);
+	    glutPostRedisplay();
+	  }
+	break;
+      case GLUT_RIGHT_BUTTON:
+        casemouse=GLUT_RIGHT_BUTTON;
+        if(win)
+          {
+            if(win && state == GLUT_DOWN) { win->xold=x,win->yold=y;return;}
+          }
+        break;
+
+
+
+      }
+}
+static void MotionMouse(int x,int y )
+{
+    OneWindow * win=CurrentWin();
+    switch(casemouse)
+      {
+      case GLUT_LEFT_BUTTON:
+	
+	if(win)
+	  {
+	    win->phi += (y-win->yold)/(2.*180.);
+	    win->theta -= (x-win->xold)/(2*180.);
+	    win->xold=x;
+	    win->yold=y;
+	    glutPostRedisplay();
+	  }
+	break;
+      case GLUT_RIGHT_BUTTON:
+        casemouse=GLUT_RIGHT_BUTTON;
+	
+        if(win)
+          {
+	    if(keyact & GLUT_ACTIVE_ALT)
+	      {
+                int dx = (x-win->xold);
+                int dy = (y-win->yold);
+		win->MoveXView(dx,-dy);
+		glutPostRedisplay();
+		{ win->xold=x,win->yold=y;}	      
+	      }
+	    else {
+	      //  zoom en y 
+	      R dd= (y-win->yold);
+	      
+	      { win->xold=x,win->yold=y;}
+	      win->zoom(pow(0.99,dd));
+	      glutPostRedisplay();
+
+	    }
+	  }
+        break;
+      }
+
+}
+
+static void Key( unsigned char key, int x, int y )
+{
+    OneWindow * win=CurrentWin();
+    if(!win->theplot)return;
+    if(debug>1) cout << "Key winnum:  " <<win->theplot->winnum << endl;
+    int ni=win->theplot->Viso.N();
+    int na=win->theplot->Varrow.N();
+    
+    switch (key)
+    {
+        case 27: // esc char
+            Fin(0);
+            break;
+        case 3: // esc char
+            Fin(9);
+            break;
+        case 'w':
+            if(win)
+		win->windowdump=true;
+            break;
+        case 'l':
+            win->withlight = !win->withlight;
+            break;
+        case '?' :
+            if(win)
+                win->help=true;
+            
+        case '+':
+            win->zoom(x,y,0.7);
+            win->coef_dist /= 1.2;
+            break;
+        case '-':
+            win->zoom(x,y,1./0.7);
+            win->coef_dist *= 1.2;
+            break;
+        case '3':
+            
+            win->plotdim=win->plotdim==2?3:2;
+            break;
+            /*
+             case '2':
+             win->plotdim=2;
+             break; */
+        case '=':
+            win->DefaultView(1);
+            break;
+        case 'f':
+            win->theplot->fill = ! win->theplot->fill  ;
+            break;
+        case '@':
+            win->dtheta = win->dtheta ? 0 : pi/1800.;
+            break;
+        case '*': // add FH  mars 2013 ..
+            win->keepPV = ! win->keepPV;
+            break;
+        case 'k':
+            if(win->theplot->NextCase())
+            {
+                R fmn,fmx,vmn,vmx;
+                win->theplot->dyn_bfv(win,fmn,fmx,vmn,vmx) ;
+                win->theplot->SetDefIsoV(ni,na,fmn,fmx,vmn,vmx) ;
+                win->changeiso=true;
+                win->changearrow=true;
+            }
+            break;
+            
+        case 'b':
+            win->theplot->grey = ! win->theplot->grey   ;
+            win->changeiso=true;
+            win->changearrow=true;
+            
+            break;
+        case 'g':
+            win->theplot->grey = !  win->theplot->grey   ;
+            win->changeiso=true;
+            win->changearrow=true;
+            
+            break;
+            
+        case 'v':
+            win->theplot->value = ! win->theplot->value  ;
+            break;
+        case 'm':
+            win->theplot->drawmeshes = ! win->theplot->drawmeshes  ;
+            break;
+        case 'B':
+            win->theplot->drawborder = ! win->theplot->drawborder  ;
+            break;
+        case 'H':
+            win->rapz *= 1.2;
+            break;
+        case 'h':
+            win->rapz /= 1.2;
+            break;
+        case 'p':
+            if(win->icurrentPlot != win->lplots.begin())
+                win->set(*--win->icurrentPlot);
+            break;
+        case 'a':
+            win->theplot->coeff/= 1.2;
+            win->changearrow=true;
+            break;
+        case 'A':
+            win->theplot->coeff*= 1.2;
+            win->changearrow=true;
+            break;
+            
+        case 'n':
+	{
+            na  -=  na < 10  ? 2 : 5;
+            ni  -=  ni <10 ? 2 : 5;
+            na = max(na,2);
+            ni = max(ni,2);
+            R fmn,fmx,vmn,vmx;
+            win->theplot->dyn_bfv(win,fmn,fmx,vmn,vmx) ;
+            win->theplot->SetDefIsoV(ni,na,fmn,fmx,vmn,vmx) ;
+            
+            win->changeiso=true;
+            win->changearrow=true;
+	}
+            break ;
+        case 'N':
+	{
+            na  += na < 10  ? 2 : 5;
+            ni  += ni < 10  ? 2 : 5;
+	}
+        case 'i':
+	{
+            R fmn,fmx,vmn,vmx;
+            win->theplot->dyn_bfv(win,fmn,fmx,vmn,vmx) ;
+            win->theplot->SetDefIsoV(ni,na,fmn,fmx,vmn,vmx) ;
+            
+            win->changeiso=true;
+            win->changearrow=true;
+	}
+            break;
+        case 'I':
+	{
+            R fmn,fmx,vmn,vmx;	  
+            win->theplot->SetDefIsoV(ni,na) ;	  
+            win->changeiso=true;
+            win->changearrow=true;
+	}
+            break;
+        case 'z':
+            if(win->focal < M_PI/1.2 ) 
+            {
+                win->coef_dist*=sin(win->focal*1.2/2)/sin(win->focal/2);
+                win->focal *=1.2;
+            }
+            break;
+        case 'Z':
+            if(win->focal > 1e-5)
+            {
+                win->coef_dist*=sin(win->focal/1.2/2)/sin(win->focal/2);
+                win->focal /=1.2;
+            }
+            break;
+        case '\r':
+        case '\n':
+	{
+            list<ThePlot*>::iterator ic = win->icurrentPlot;
+            if(++ic == win->lplots.end()) // last plot ->  try new one
+                SendForNextPlot();
+            else
+                win->set(*++win->icurrentPlot);
+            break;
+	}
+        default:
+            if((debug > 10)) cout << " Key Character " << (int) key << " " << key << endl;  
+            
+    }
+    glutPostRedisplay();
+}
+
+
+void SpecialKey(int key, int x, int y)
+{
+    OneWindow * win=CurrentWin();
+    if(win)
+      {
+    // if((debug > 10)) cout << " SpecialKey " << key << " " << x << " " << y << " : ";
+	R dx(0),dy(0);
+	switch (key) {
+	case  GLUT_KEY_LEFT:   dx = -1; break;
+	case  GLUT_KEY_RIGHT:  dx = +1; break;
+	case  GLUT_KEY_DOWN:   dy = -1; break;
+	case  GLUT_KEY_UP:     dy = +1; break;
+	}
+	// calcul du deplacement de xm,ym,zm;
+	// if((debug > 10)) cout << " " << dx << " " << dy << endl;
+	win->MoveXView(dx,dy);
+	glutPostRedisplay();
+      }
+}
+
+void LauchNextRead()
+{
+  if(!NoMorePlot)
+    {
+      inThreadRead=true;
+      tidRead = Thread::Start(&ThreadRead,(void *) datafile);
+    }
+}
+
+void WaitNextRead()
+{
+  if( inThreadRead )
+    {
+      assert(tidRead!=0);
+      Thread::Wait(tidRead);
+      tidRead =0;
+      inThreadRead=false;;
+    }
+}
+
+//void * ThreadRead(void *fd)
+THREADFUNC(ThreadRead,fd)
+{   
+  int err=0;
+  assert(nextPlot==0);
+  //  MutexNextPlot.WAIT();
+  if(gwait) usleep((useconds_t) (gwait*1.e6) );
+  err=ReadOnePlot((FILE*)fd);
+  // MutexNextPlot.Free(); 
+  if(debug>1)
+    cout << " We Read a plot  : " << kread << " " << nextPlot << " " << err << endl;
+  if(err<0)
+  {
+    NoMorePlot=true;
+
+   }
+  Thread::Exit();
+  return  0; 
+}
+
+
+static  bool TryNewPlot( void )
+{
+    // the routine to try to see if the next plot is read or not.
+    // -----------------------------------------------------------
+    bool ret=false;
+    if(debug>2)
+        cout << "  TryNewPlot   plot : " << currentPlot << " next = " << nextPlot << endl;;
+    if (nextPlot!=0)
+    {
+        
+        WaitNextRead();
+        int iwnp= nextPlot-> winnum;
+        if(debug>1) cout << " change current plot to: " << nextPlot << " et  Lock Plot . winnum  " << iwnp << endl;;
+        //cout << " winnum: " << iwnp << endl;
+        if(Num2Windows[iwnp]==0)
+          {
+            ostringstream titre;
+            titre <<  "W "<< iwnp << " /FreeFem++: type return key to proceed (or ? for help on other)";
+            int Height = 512;
+            int Width = 512*3/2;
+            
+            glutInitWindowSize(Width , Height);
+            glutInitWindowPosition(100+iwnp*50, 100+iwnp*50);
+            int iw0=glutCreateWindow(titre.str().c_str());
+            if(debug>1)  cout << " ** glutCreateWindow  " << iw0 << endl;
+            glDisable(GL_DEPTH_TEST);
+            glutReshapeFunc( Reshape ); // pour changement de fenetre
+            glutKeyboardFunc( Key );    // pour les evenements clavier
+            glutSpecialFunc(SpecialKey);
+            glutMouseFunc(Mouse);       // pour les evenements sourie
+            glutMotionFunc(MotionMouse); // les mouvements  de la sourie
+            glutDisplayFunc( Display ); // l'affichage
+            glutPushWindow();
+            glutShowWindow();
+            AllWindows[iw0]= new OneWindow(Width , Height,nextPlot);
+            Num2Windows[iwnp]=iw0;
+        }
+        else
+            AllWindows[Num2Windows[iwnp]]->add(nextPlot);
+        glutSetWindow(Num2Windows[iwnp]);
+        //if(currentPlot) delete currentPlot; //  a change fait dans add
+        // MutexNextPlot.WAIT();
+        currentPlot=nextPlot;
+        nextPlot=0;
+        // MutexNextPlot.Free();
+        LauchNextRead();
+        ret=true;
+    }
+    if(gwait &&  NoMorePlot )
+    {usleep((useconds_t)(1e6*gwait)); Fin(0); }
+    
+    return ret;    
+}
+const char * Index(const char * p, const char c)
+{
+    int k=0;
+    while(k++<1000000)
+        if(!*p) return 0;
+        else if(  *p==c) return p;
+        else ++p;
+    return 0; 
+}
+const char * rIndex(const char * p, const char c)
+{
+    int k=0;
+    const char *pp=0;
+    while(k++<1000000)
+        if(!*p) break;
+        else if(  *p==c) pp= p;
+        else ++p;
+    return pp; 
+}
+void 	SetDefWin(const char *p,int & iii0,int & jjj0,int & Width,int &Height)
+{
+  // syntax 
+  //   1024x1024+100+100
+  // or
+  //  1024x1024 
+  const char  *bx = p;
+  const char *by = Index(p,'x');
+  const char *ox = Index(p,'+');
+  const char *oy = rIndex(p,'+');
+  if(by ==0) return;
+  Width= atoi(bx);
+  Height= atoi(by+1);
+  if(ox && (ox != oy))
+    {
+      iii0= atoi(ox+1);
+      jjj0=atoi(oy+1);
+    }
+  if(debug>1)
+    cout << "  position = "<< Width << "x" << Height << "+"<< iii0 << "+" << jjj0 << endl;
+  assert(Width >0 &&  Width < 3000);
+  assert(Height >0 &&  Height < 3000);
+  assert(iii0 >0 &&  iii0 < 3000);
+  assert(jjj0 >0 &&  jjj0 < 3000);
+
+}
+int main(int argc,  char** argv)
+{
+    glutInit(&argc, argv);
+    bool stereo=false;
+    bool fullscreen = false;
+
+    if(stereo)
+	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STEREO);
+    else  
+	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
+     int i1=1;
+     int Height = 512,Width = 512*3/2, iii0=100,jjj0=100;
+     string titre = "W0/FreeFem++: type return key to proceed (or ? for help on other)";
+     int eerr=0; 
+    if(argc>1) 
+      {
+	if( (i1 < argc) &&strcmp(argv[i1],"-?")==0) i1++,eerr=-1; 
+	if (i1 < argc)
+	  {
+	    if( strcmp(argv[i1],"-nv")==0) i1++,debug=0;
+	    else if( strcmp(argv[i1],"-v")==0) i1++,debug=2,verbosity=2;
+	    else if( strcmp(argv[i1],"-vv")==0) i1++,debug=5,verbosity=2;
+	    else if( strcmp(argv[i1],"-vvv")==0) i1++,debug=10, verbosity=1000;
+	  }
+	  if( (i1+1 < argc) && (strcmp(argv[i1],"-wait")==0)) { i1++; gwait=atof(argv[i1++]); }
+	  if( (i1+1 < argc) && (strcmp(argv[i1],"-g")==0)) { 
+	    i1++; 
+	    SetDefWin(argv[i1++], iii0,jjj0,Width,Height);
+	  }
+	  if( (i1+1 < argc) && (strcmp(argv[i1],"-t")==0)) { 
+	    i1++; 
+	    titre = argv[i1++];
+	  }
+	  if( (i1 -  argc > 1) )
+	    { 
+	      eerr = 1;
+	      cout << " error ming args " << i1 -  argc  << endl; 
+	    }
+      }
+    datafile =0;
+     if(debug>1)
+    cout << "ffglut : " << (argc>i1) << eerr << endl;
+    if(argc>i1 && (eerr==0))// && *argv[argc-1] != '-' )
+      {	
+	datafile=fopen(argv[argc-1], "r");
+	if(debug >1)
+		cout << " fopen :" << argv[argc-1] << " " <<datafile << endl;
+	if(datafile==0)
+	  eerr=100;
+	
+      }
+    if(eerr)
+      {
+	cerr << " Erreur ffglut  [-nv|-v|-vv|-vvv] [-wait 0.5] [-g 512x300+10+10] [-t title] [file]" << endl; 
+	cerr << " err number " << eerr << endl; 
+	abort();
+      }
+    
+    
+    if(debug>1)		
+    cout <<  " mode read = " << MODE_READ_BINARY << endl;
+    if(datafile==0)
+	datafile=stdin;
+    if ( !datafile){
+	cerr<< " Erreur fdopen stdin in binary " << endl;
+	Fin(1);
+     }
+    int err=ReadOnePlot(datafile);
+    if(err) { //cout << "Err ReadOnePlot " << err << endl;
+      Fin(1);}
+   
+
+
+    if(kread==0) {
+      //cout << " Error: no graphic data " << endl;
+      Fin(1);
+    }
+    if(debug>1) 
+    cout << "on a lue le premier plot next plot: " << nextPlot << endl;
+
+
+    
+    glutInitWindowSize(Width , Height);
+    glutInitWindowPosition(iii0,jjj0);
+
+    int iw0=glutCreateWindow(titre.c_str());
+    //glutPushWindow();
+   // if (fullscreen)
+//	glutFullScreen();
+    Num2Windows[0]=iw0;
+    glDisable(GL_DEPTH_TEST);
+    glutReshapeFunc( Reshape ); // pour changement de fenetre
+    glutKeyboardFunc( Key );    // pour les evenements clavier
+    glutSpecialFunc(SpecialKey);
+    glutMouseFunc(Mouse);       // pour les evenements sourie
+    glutMotionFunc(MotionMouse); // les mouvements  de la sourie
+    glutDisplayFunc( Display ); // l'affichage
+    glutSetWindow(iw0);
+    AllWindows[iw0]=new OneWindow(Width , Height,currentPlot);
+    TryNewPlot();
+    
+ 
+    //cout << " Window  " << iw0 << endl;
+    glutMainLoop(); 
+
+  return 0;
+}
+
+
diff --git a/src/Graphics/ffglut.hpp b/src/Graphics/ffglut.hpp
new file mode 100644
index 0000000..b91c49c
--- /dev/null
+++ b/src/Graphics/ffglut.hpp
@@ -0,0 +1,373 @@
+/*
+ *  ffglut.hpp
+ *  ff
+ *
+ *  Created by FrÈdÈric Hecht on 04/11/08.
+ *  Copyright 2008 UPMC. All rights reserved.
+ *
+ */
+#include <complex>
+typedef std::complex<double> Complex; 
+extern int debug;
+static const double dinfty=numeric_limits<double>::max();
+void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool grey,KN<R> colors);
+void hsvToRgb (float h, float s, float v, float & r, float & g, float & b);
+
+
+class ThePlot;
+class OneWindow;
+
+struct OnePlot 
+{
+  int dim;
+  R3 Pmin,Pmax;
+  double fmin,fmax;
+  double vmax2;
+  long what;
+  GLsizei ngllists;
+  GLint gllists;
+  KN<int> oklist;
+  int setgllists;
+  virtual void Draw(OneWindow *win) =0;
+  virtual bool NextCase() {return false;}
+  void bb(R3 & Pmn,R3 &Pmx) const 
+  { 
+    Pmn=Minc(Pmin,Pmn);
+    Pmx=Maxc(Pmax,Pmx);
+    }
+
+  void bfv(R & fmn,R &fmx,R & vmx) const 
+  { 
+    // cout << "\t\t\t\t  f min, max v max :" << fmin << " " << fmax << " " << vmax2 << endl;
+    fmn=Min(fmin,fmn);
+    fmx=Max(fmax,fmx);
+    vmx=Max(vmax2,vmx);
+  }
+
+  virtual void dyn_bfv(OneWindow *win,R & fmn,R &fmx,R & vmn,R & vmx) const 
+  {//  compute the function bound and arrow bound view ....  
+  }
+  
+  OnePlot(long w,int ddim=2,int nbgllist=0) :
+    dim(ddim),
+    Pmin(dinfty,dinfty,dinfty),Pmax(-dinfty,-dinfty,-dinfty),
+    fmin(dinfty),fmax(-dinfty),vmax2(0),
+    what(w),ngllists(nbgllist),gllists(0),
+    oklist(nbgllist),setgllists(0){
+  }
+  
+  void initlist()
+  {
+    if(! setgllists)
+      if(ngllists>0) 
+	{
+	  oklist=0; //  
+	  gllists= glGenLists(ngllists);
+	  setgllists=1;
+	  assert(gllists);
+	}
+  }
+  
+  void GLDraw(OneWindow *win);
+  virtual ~OnePlot() {
+    if(setgllists) glDeleteLists(gllists,ngllists);
+  };
+private: // pas de copy  car il y a des destructeurs dans les classes derives
+  OnePlot(const OnePlot & );
+  OnePlot & operator=(const OnePlot & );
+};
+
+template<class Mesh>
+struct OnePlotMesh : public OnePlot
+{
+  const Mesh *Th;
+  OnePlotMesh(const Mesh *T)
+    : OnePlot(0,2,3),Th(T) 
+  {
+    R2 P0,P1;
+    Th->BoundingBox(P0,P1);
+    Pmin=P0;
+    Pmax=P1;
+  }
+  void Draw(OneWindow *win);
+  
+};
+
+struct OnePlotMesh3 : public OnePlot
+{
+    const Mesh3 *Th;
+    OnePlotMesh3(const Mesh3 *T)
+      : OnePlot(0,3,3),Th(T) 
+    {
+	Pmin=Th->Pmin;
+	Pmax=Th->Pmax;
+	//Th->BoundingBox(Pmin,Pmax);     
+    }
+    void Draw(OneWindow *win);
+};
+
+template<class Mesh>
+struct OnePlotFE: public OnePlot 
+{
+  const Mesh *Th;
+ // long nsub;
+  KN<double> v;
+  KN<Complex> vc;
+  KN<R2> Psub;
+  KN<int> Ksub;
+  int cas; // in cas of complex  chaage interpertation of complex value 
+  OnePlotFE(const Mesh *T,long w,PlotStream & f);
+  void Draw(OneWindow *win);
+  void dyn_bfv(OneWindow *win,R & fmn,R &fmx,R & vmn,R & vmx) const ;
+  bool  vc2v(); 
+  bool  NextCase() { cas++; return vc2v();}
+};
+
+struct OnePlotFE3: public OnePlot 
+{
+  const Mesh3 *Th;
+  long nsub;
+  KN<double> v;
+  KN<Complex> vc;
+  KN<R3> Psub;
+  KN<int> Ksub;
+  int cas; // in cas of complex  chaage interpertation of complex value 
+
+  OnePlotFE3(const Mesh3 *T,long w,PlotStream & f)
+    :OnePlot(w,3,5),Th(T),cas(2)
+    {
+	Pmin=Th->Pmin;
+	Pmax=Th->Pmax;
+
+	f >> Psub ;
+	f >> Ksub ;
+	if(what<10)
+	  f >>  v;
+	else
+	  f >> vc;
+	vc2v();
+	if(debug>3) cout << "OnePlotFE3" << Th <<" " << what<< " " << nsub <<" " << v.N() << endl
+			 << "       Pmin " << Pmin << " Pmax  " << Pmax << endl;
+	ffassert(f.good());
+	
+    }
+    void Draw(OneWindow *win);
+  bool  vc2v();     
+  bool  NextCase() { cas++; return vc2v();}
+};
+
+struct OnePlotCurve: public OnePlot {
+  KN<double> xx,yy;
+  OnePlotCurve(PlotStream & f)
+    :OnePlot(3,2,1)
+  {
+    f >> xx>>yy;
+    // cout << xx << " " << yy <<endl;
+    ffassert(f.good());
+    ffassert(xx.N() && yy.N() && xx.N() == yy.N());
+    Pmin=Minc(Pmin,R2(xx.min(),yy.min()));
+    Pmax=Maxc(Pmax,R2(xx.max(),yy.max()));
+    
+  }
+  void Draw(OneWindow *win);
+};
+
+struct OnePlotBorder: public OnePlot {
+  vector<vector<pair<long,R2> > > data;
+  OnePlotBorder(PlotStream & f);	  
+  void Draw(OneWindow *win);
+};
+
+// add 11/12/2008 for gestion of error FH  (what -1) 
+struct OnePlotError: public OnePlot {
+  long item;
+  OnePlotError(PlotStream & f) 
+    : OnePlot(-1)
+  {    f >> item; 
+     }	  
+  void Draw(OneWindow *win) ;
+  
+};
+
+
+
+class ThePlot 
+{
+public:
+  int count;
+  int state; // 0 new 
+  GLint gllist;
+  KN<R> colors;
+  bool hsv; // hsv  type 
+  KN<R> boundingbox;
+  double coeff;
+  bool wait;
+  bool value;
+  bool fill;
+  bool aspectratio;
+  bool clean;
+  bool uaspectratio;
+  bool pViso,pVarrow;
+  bool withiso;
+  bool witharrow;
+  
+  long  Niso,Narrow;
+  R3 Pmin,Pmax,PminT,PmaxT;//  with R -> true bound
+  R  fmin,fmax,fminT,fmaxT; // with  bound with previous plot. 
+  R  vmax2;
+  KN<R> Viso,Varrow;
+  bool bw;
+  string * psfile;
+  string * cm;
+  
+  bool grey;
+  bool greyo;
+  bool drawborder;
+  bool drawmeshes;
+  bool add,keepPV;
+  double echelle;
+  vector<Mesh *> Ths;
+  vector<Mesh2 *> Ths2;
+  vector<Mesh3 *> Ths3;
+  list<OnePlot *> plots;
+  bool changeViso,changeVarrow,changeColor,changeBorder,changeFill;
+  R3 Pvue,Peyes;
+  R alpha; 
+  R coefr; 
+  R z0; //  z pour les objets 2d. 
+  //  for 3d plot jan 2009
+  int  plotdim;
+  R theta, phi, dcoef, focal;
+  int datadim;
+  // 2D
+  long winnum;
+  bool NextCase();
+  
+  bool Change() const  { return changeViso||changeVarrow||changeColor||changeBorder||changeFill;}
+  ~ThePlot()
+  {
+    for (list<OnePlot *>::iterator i= plots.begin();i != plots.end(); ++i)
+      if(*i) delete *i;
+    for (vector<Mesh *>::iterator i= Ths.begin();i != Ths.end(); ++i)
+      if(*i) delete *i;
+    for (vector<Mesh2 *>::iterator i= Ths2.begin();i != Ths2.end(); ++i)
+      if(*i) delete *i;
+    for (vector<Mesh3 *>::iterator i= Ths3.begin();i != Ths3.end(); ++i)
+      if(*i) delete *i;
+    
+  }
+  ThePlot(PlotStream & fin,ThePlot *old , int kcount);
+  
+  void Draw(OneWindow *win) ;
+  void DrawHelp(OneWindow *win) ;
+  
+  struct RGB  { float r,g,b;
+    void set(int k,int nb,ThePlot *theplot ) 
+    {
+      DefColor(r,g,b, k,nb,theplot->hsv,theplot->grey,theplot->colors);
+    }
+  } ;
+  vector<RGB>  tbc;
+  void color(int i,R alpha=1.) { 
+    ffassert(tbc.size());
+    RGB c(tbc[min(max(0,i),(const int) tbc.size())]);
+    if(alpha<1) {
+      R a1=1.-alpha;
+      c.r=c.r*alpha+a1;
+	    c.g=c.g*alpha+a1;
+	    c.b=c.b*alpha+a1;
+	    
+	    // cout << " aaaa" << alpha << endl;
+    }
+    glColor4f(c.r,c.g,c.b,alpha);
+  }
+  void  SetColorTable(int nb); 
+  void SetDefIsoV(int niso=0,int narr=0,R fmn=1.,R fmx=-1.,R vmn=1.,R vmx=-1.); 
+  void DrawIsoT(const R2 Pt[3],const R ff[3],const R * Viso,int NbIso, R rapz=1);
+  void DrawIsoTfill(const R2 Pt[3],const R ff[3],const R * Viso,int NbIso, R rapz=1);
+  void dyn_bfv(OneWindow *win,R & fmn,R &fmx,R & vmn,R & vmx) const ;
+  
+}; 
+
+class OneWindow {
+public:
+  ThePlot *theplot;
+  list<ThePlot*> lplots;//  to store some plot 
+  list<ThePlot*>::iterator icurrentPlot;//=lplots.begin();
+  int lplotssize;
+
+  int height,width;
+  R2 Bmin,Bmax;
+  R2 oBmin,oBmax;// orign box 
+  R zmin,zmax;
+  R hpixel;// taille pixel en coordonne x,y,z 
+  int xold,yold;
+  bool windowdump,help;
+
+  GLdouble modelMatrix[16];
+  GLdouble projMatrix[16];
+  GLint viewport[4];  
+  
+  int  plotdim;
+  R theta, phi, coef_dist, focal, dtheta;
+  R  rapz,rapz0;     
+  R3 Bmin3,Bmax3,Pvue3;
+  R3 cam;
+  bool withlight;
+  bool changearrow,changeiso;// to rebuild de graphic list if neccessary
+  bool keepPV,init;
+  //double  aspx, aspy, echx,echy,ech,rxmin,rxmax,rymin,rymax;
+  OneWindow(int h,int w,ThePlot *p);
+  void DefaultView(int state) ;
+  bool  NextCase() ;
+  void  SetView() ;
+  void MoveXView(R dx,R dy) ;
+  void set(ThePlot *p);
+  void add(ThePlot *p);
+  void cadre(R2 A,R2 B);
+  void cadreortho(R2 A,R2 B);
+  void getcadre(double &xmin,double &xmax,double &ymin,double &ymax);
+  void Display();
+  void resize(int w,int h);
+  void zoom(int w,int h,R coef);
+  void zoom(R coef);
+  float GetHeigthFont(){return 10;}
+    void color(int i,R alpha=1) {theplot->color(i,alpha);}
+  void FillRect(R x0,R y0,R x1,R y1);
+  void PlotValue(const KN_<double> & Viso,int  k0,const char * cmm);
+  void DrawCommentaire(const char * cm,R x,R y); 
+  void SetScreenView() const ;
+  void Show(const char *str,int i);
+  void   setLighting();
+  void unsetLighting();
+  void Seg(R2 A, R2 B) const  { 
+    glVertex3d(A.x,A.y,theplot->z0);
+    glVertex3d(B.x,B.y,theplot->z0);
+  }
+ 
+  int InRecScreen(R2 P1,R2 P2) const 
+  {  
+    R2 Pmn=Minc(P1,P2),Pmx=Maxc(P1,P2);
+    return (Pmx.x >= Bmin.x) && (Pmn.x <= Bmax.x) && (Pmx.y >= Bmin.y) && (Pmn.y <= Bmax.y);
+  }
+  int InRecScreen(R3 P1,R3 P2) const 
+  {  
+    R3 Pmn=Minc(P1,P2),Pmx=Maxc(P1,P2);
+    return (Pmx.x >= viewport[0]) && (Pmn.x <= viewport[2]) && (Pmx.y >= viewport[1]) && (Pmn.y <= viewport[3]);
+  }
+    
+
+};
+
+void plot(double x,double y,const char *cmm,int font=-1);
+void plot(double x,double y,double i,int fint = -1);
+
+extern map<int,OneWindow*> AllWindows; 
+
+inline OneWindow* CurrentWin() 
+ {
+  OneWindow* w= AllWindows[glutGetWindow()];
+ ffassert(w);
+ return w;
+ }
diff --git a/src/Graphics/ffthreads.cpp b/src/Graphics/ffthreads.cpp
new file mode 100644
index 0000000..935407c
--- /dev/null
+++ b/src/Graphics/ffthreads.cpp
@@ -0,0 +1,92 @@
+// SUMMARY  : Threads for Linux and Microsoft Win32
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Antoine Le Hyaric / F. Hecht
+// E-MAIL   : lehyaric at ann.jussieu.fr
+
+// This file is part of Freefem++
+// 
+// Freefem++ is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+// 
+// Freefem++  is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public License
+// along with Freefem++; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+//  Frederic Hecht  .
+
+#include <cassert>
+#include <string>
+#include <cerrno>
+#include <cstring>
+#include <iostream>
+#include <cstdlib>
+using namespace std;
+
+#define ERROR_FF(msg) (cerr << msg<<endl, assert(0), exit(1)) 
+
+#include "ffthreads.hpp"
+
+#ifdef __MINGW32__
+#include <process.h>
+#else
+#include <signal.h>
+#endif
+
+
+Thread::Id Thread::Start(THREADFUNC(f,),Thread::Parm p){
+  Id tid;
+#ifdef __MINGW32__
+  unsigned ThreadId;
+  tid = (HANDLE) _beginthreadex(NULL,0,f,p,0,&ThreadId);
+  if(tid == NULL) ERROR_FF("Thread::Start: Thread could not be created");
+#else
+  int R = pthread_create(&tid,NULL,f,p);
+  if(R != 0) ERROR_FF("Thread::Start: Thread could not be created");
+#endif
+  return tid;
+}
+
+void Thread::Wait(Thread::Id tid){
+#ifdef __MINGW32__
+  DWORD R = WaitForSingleObject(tid,INFINITE);
+  if(R == WAIT_FAILED) ERROR_FF("Thread::Wait" " -- Wait failed");
+  CloseHandle(tid);
+#else
+  int R=pthread_join(tid,NULL);
+  if(R!=0) ERROR_FF("Thread::Wait: Wait failed");
+#endif
+}
+
+void Thread::Exit(){
+#ifdef __MINGW32__
+    _endthreadex(0);
+#else
+    pthread_exit(NULL); // No test: returns void.
+#endif
+}
+
+void Thread::Kill(Thread::Id tid){
+#ifdef __MINGW32__
+    if(TerminateThread(tid,0) == 0)
+      ERROR_FF("Thread::Kill: Thread not killed");
+#else
+    if(pthread_kill(tid,SIGINT)!=0)
+      ERROR_FF("Thread::Kill: Thread not killed");
+#endif
+}
+
+Thread::Id Thread::Current(){
+#ifdef __MINGW32__
+  return GetCurrentThread();
+#else
+  return pthread_self();
+#endif
+}
diff --git a/src/Graphics/ffthreads.hpp b/src/Graphics/ffthreads.hpp
new file mode 100644
index 0000000..f74af32
--- /dev/null
+++ b/src/Graphics/ffthreads.hpp
@@ -0,0 +1,65 @@
+// SUMMARY  : Threads for Linux and Microsoft Win32
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Antoine Le Hyaric, Modif F. hecht
+// E-MAIL   : lehyaric at ann.jussieu.fr
+
+// This file is part of Freefem++
+// 
+// Freefem++ is free software; you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation; either version 2.1 of the License, or
+// (at your option) any later version.
+// 
+// Freefem++  is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public License
+// along with Freefem++; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+// from:
+// Antoine Le Hyaric - LJLL Paris 6 - lehyaric at ann.jussieu.fr - 21/10/04
+//  simplify by F. Hecht
+// Antoine Le Hyaric - LJLL Paris 6 - hect at ann.jussieu.fr - 22/11/08
+
+#ifndef FFTHREADS_HPP
+#define FFTHREADS_HPP
+#include "mode_open.hpp"
+#include <string>
+using namespace std;
+#ifdef __MINGW32__
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+// Just check that we are in a known environment (otherwise it may be
+// difficult to recognise that the simple cause is an ifdef problem).
+
+class Thread{
+public:
+
+#ifdef __MINGW32__
+#define THREADFUNC(f,parm) unsigned int (__stdcall f)(Thread::Parm parm)
+  typedef LPVOID Parm;
+  typedef HANDLE Id;
+#else
+#define THREADFUNC(f,parm) void* f(Thread::Parm parm)
+  typedef void* Parm;
+  typedef pthread_t Id;
+#endif
+
+  // Mingw is a little puzzled if there are no brackets around
+  // __stdcall
+  static Id Start(THREADFUNC(f,),Parm p);
+  static void Wait(Id tid);
+  static void Exit(); // From inside the thread
+  static void Kill(Id tid);
+
+  static Id Current();
+};
+ 
+
+#endif // THREADS_HPP
diff --git a/src/Graphics/getprog-unix.hpp b/src/Graphics/getprog-unix.hpp
new file mode 100644
index 0000000..6304b59
--- /dev/null
+++ b/src/Graphics/getprog-unix.hpp
@@ -0,0 +1,274 @@
+#include "mode_open.hpp"
+#if WIN32
+#include  "ff-win32.cpp"
+#else
+#include <unistd.h>
+#endif
+
+// FFCS: required for chdir() when g++ 4.7 is used
+#include <unistd.h>
+
+// FFCS: redirecting visualization output
+#include "../fflib/ffapi.hpp"
+#include "../fflib/strversionnumber.hpp"
+#include <string>
+
+extern long mpirank;
+extern long verbosity;
+extern FILE *ThePlotStream; //  Add for new plot. FH oct 2008
+// for the environ variables ...
+extern const char *  prognamearg;
+extern const char *  edpfilenamearg;
+extern bool  waitatend;
+extern bool  consoleatend;
+extern bool echo_edp;
+extern bool 	  NoGraphicWindow;
+
+char * Shell_Space(const char * s);
+
+char * Shell_Space(const char * s)
+{
+    const char *c=s;
+    int nbspace;
+    int i;
+    for( i=0;i<100000;++i) 
+	if (! s[i]) break;
+ 	else if(isspace(s[i])) ++nbspace;
+    if (!(i<100000))
+      {
+	cerr << " Bug Shell_Space routine " <<endl;
+	exit(1);
+      }
+
+#ifdef WIN32
+    char * p= new char[i+1+nbspace];
+    char * q=p;
+    for( i=0;i<100000;++i) 
+	if (! s[i]) break;
+        else if(isspace(s[i])) *q++='^', *q++=s[i];
+	    else *q++=s[i];
+#else
+    char * p= new char[i+nbspace];
+    char * q=p;
+    for( i=0;i<100000;++i) 
+	if (! s[i]) break;
+        else if(isspace(s[i])) *q++='\\', *q++=s[i];
+	else *q++=s[i];
+#endif
+    *q++='\0';
+    assert( q-p <= i+nbspace);
+    return p;
+}
+int getprog(char* fn,int argc, char **argv)
+{
+  waitatend=true;  // attent 
+  consoleatend=false;  // bug with redirection FH 
+  int ret=0;
+  *fn='\0';
+#ifdef WIN32
+ const  int lsuffix= 4;
+#else 
+ const  int lsuffix= 0;
+#endif
+  
+#ifdef PROG_FFGLUT
+  const char * ffglut=PROG_FFGLUT;
+#else
+  const char *ffglut= "ffglut";
+#endif
+  const char *progffglut=0;
+  const char *fileglut=0;
+  bool noffglut=false;
+ 
+  // FFCS - remove the test for noffglut to be able to create pictures
+  // in any situation. Even FreeFem++-mpilang needs to send pictures
+  // (eg when called in a FreeFem++-server situation by EJS)
+  // is the name -nw or -nw.exe  -> no graphics 
+  noffglut=false;
+
+  bool ch2edpdir = false;
+  if(argc)
+    prognamearg=argv[0];
+
+   
+   if(prognamearg )      // FH add to remove ffglut in case of -nw or -nw.exe program. FH juin 2014..
+    {int l = strlen(prognamearg);
+        if( (( l>4 ) && (strcmp("-nw",prognamearg+l-3) ==0))
+           || (( l>8) &&(strcmp("-nw.exe",prognamearg+l-7) ==0)))
+        {
+            consoleatend=false;
+            noffglut=true;
+            NoGraphicWindow=true;
+            waitatend=false;
+        }
+    }
+   echo_edp=true;
+  if(argc)
+    for (int i=1; i<argc;i++)
+      if  (ret ==0 && strcmp(argv[i],"-f")==0 && i+1 < argc  ) 
+	{
+	  strcpy(fn,argv[i+1]);
+	  i++;	
+	  edpfilenamearg=argv[i];
+	  ret=1;
+	}
+      else if  (strcmp(argv[i],"-v")==0 && i+1 < argc) 
+	{
+	  verbosity = atoi(argv[i+1]);
+	  i++;	
+	  if(verbosity>10) printf(" verbosity : %ld\n",verbosity);
+	}
+      else if  (strcmp(argv[i],"-nw")==0 ) 
+	{
+	  consoleatend=false;
+	  noffglut=true;
+	  NoGraphicWindow=true;
+          waitatend=false; // add modif FH. juin 2014 ..
+	}
+      else if  (strcmp(argv[i],"-ne")==0 ) // no edp 
+	  echo_edp=false;
+      else if  (strcmp(argv[i],"-cd")==0 ) // 
+	  ch2edpdir=true;
+   
+      else if  (strcmp(argv[i],"-ns")==0 ) // no script  
+	  echo_edp=false;
+      else if  (strcmp(argv[i],"-nowait")==0 ) 
+	waitatend=false;
+      else if  (strcmp(argv[i],"-nc")==0 ) 
+	consoleatend=false;
+      else if  (strcmp(argv[i],"-log")==0 ) 
+	consoleatend=true;
+      else if  (strcmp(argv[i],"-wait")==0 ) 
+	  waitatend=true;
+      else if(strcmp(argv[i],"-fglut")==0 && i+1 < argc)
+	{ 
+	  fileglut=argv[++i];
+	  noffglut=true;
+	}
+      else if(strcmp(argv[i],"-glut")==0 && i+1 < argc)
+	{
+	  progffglut=argv[++i];
+	  noffglut=true;
+	  NoGraphicWindow=false;
+	}
+      else if(strcmp(argv[i],"-gff")==0 && i+1 < argc)
+	{
+	  progffglut=Shell_Space(argv[++i]);
+	  noffglut=true;
+	  NoGraphicWindow=false;
+	}    
+      else if(strcmp(argv[i],"-?")==0 )
+	ret=2;
+      else if( strcmp(argv[i],"-f")==0 && i+1 < argc) 
+	{
+	  strcpy(fn,argv[++i]);
+	  ret=1;
+	  edpfilenamearg=argv[i];	 
+	}
+      else if(ret==0)
+	{
+	  strcpy(fn,argv[i]);
+	  edpfilenamearg=argv[i];	 
+	  ret=1;
+	}
+if( ch2edpdir && edpfilenamearg)
+  {
+    int i=0;
+    int l= strlen(edpfilenamearg);
+#ifdef WIN32	
+    const char sepdir='\\';
+#else
+   const char sepdir='/';
+#endif    
+    
+    for(i=l-1;i>=0;i--)
+	if(edpfilenamearg[i]==sepdir) break;
+ 	
+    if(i>0) {
+	char *dir= new char [l+1];
+	strcpy(dir,edpfilenamearg);
+	dir[i]=0;
+	int err=0;
+	if(verbosity>1) 
+	    cout << " chdir '" << dir <<"'"<< endl;
+	// FFCS: mingw64 API change
+	err=chdir(dir);
+
+	//cout << err << endl;
+         if(err) {
+	     cerr << " error : chdir  " << dir << endl;
+	     exit(1);
+	 }
+	delete [] dir;
+	
+    }
+      
+    
+  }
+  if( ! progffglut && !noffglut)
+    progffglut=ffglut;
+  
+  if(progffglut && mpirank==0)
+    {
+      // FFCS: divert stream to FFCS
+      ThePlotStream = ffapi::ff_popen(progffglut,"w");		   
+
+      // FFCS: just forget the following message because it could be understood as an error during FFCS execution
+      // although ffglut is not used there.
+
+      //if(verbosity)
+      //  printf(" EXEC of the plot  : %s\n",progffglut);
+
+      if(!ThePlotStream) { cerr << "  Error popen  "<< progffglut << endl;exit(1);}
+      
+    }
+  else if (fileglut)
+    {// correction progffglut -> fileglut v3.0-2 FH.
+      ThePlotStream = fopen(fileglut, MODE_WRITE_BINARY );
+      if(verbosity)
+	printf(" save of the plot in file : %s\n",fileglut);
+      if(!ThePlotStream) 
+	{
+	  cerr << "  Error save file glut " << fileglut 
+	       << " mode " << MODE_WRITE_BINARY<< endl;
+	  exit(1);
+	}
+    }
+
+#ifdef WIN32
+  if(ret==0)
+    {
+      if ( ShowOpenDialogBox1(fn) )
+	ret=1;			    
+    }
+#endif
+
+  if(ret !=1) 
+    {
+      const char * ff = argc ? argv[0] : "FreeFem++" ;
+      cout << " Error parameter: "<< ff << " , version : " << StrVersionNumber() << endl;
+      cout << " Syntaxe = " << ff  << "   [ -v verbosity ] [ -fglut filepath ] [ -glut command ] [ -nw] [ -f] filename  [SCRIPT-arguments]\n"
+	   << "        -v      verbosity : 0 -- 1000000 level of freefem output \n"
+	   << "        -fglut  filepath  : the file name of save all plots (replot with ffglut command ) \n"
+	   << "        -glut    command  : change  command  compatible with ffglut  \n"
+           << "        -gff     command  : change  command  compatible with ffglut (with space quoting)\n"
+	   << "        -nowait           : nowait at the end on window   \n"
+	   << "        -wait             : wait at the end on window   \n"
+	   << "        -nw               : no ffglut, ffmedit  (=> no graphics windows) \n"
+	   << "        -ne               : no edp script output\n"
+           << "        -cd               : Change dir to script dir\n"
+           << endl ;
+
+	;
+
+      if(noffglut)  cout << " without     default ffglut : " << ffglut << endl;
+      else          cout << " with        default ffglut : " << ffglut << endl;
+      cout   << endl;
+      exit(1);
+      return ret; 
+    }
+  if(verbosity>10) 
+    cout << " file : " << fn << endl ; 
+
+    return 1;
+}
diff --git a/src/Graphics/gggg.cpp b/src/Graphics/gggg.cpp
new file mode 100644
index 0000000..0af6999
--- /dev/null
+++ b/src/Graphics/gggg.cpp
@@ -0,0 +1,55 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "config-wrapper.h"
+
+#include <cstdio>
+#include <complex>
+#include <queue>
+#include <error.hpp>
+#include "environment.hpp"
+
+#define  FF_GRAPH_PTR_DCL
+#include "rgraph.hpp"
+
+void ShowDebugStack(){}
+
+ long verbosity = 1;
+ long searchMethod=0; // = 9999; //pichon //PROBABLY BUG : can't compile without it
+ FILE *ThePlotStream=0; //  Add for new plot. FH oct 2008
+
+ 
+ int TheCurrentLine=-1; // unset: by default
+ long mpisize=0,mpirank=0;
+
+bool showCPU= false;
+
+
+//  add F. Hecht 
+EnvironmentData  ffenvironment;
+
+
diff --git a/src/Graphics/glrgraph.hpp b/src/Graphics/glrgraph.hpp
new file mode 100644
index 0000000..f6c9a13
--- /dev/null
+++ b/src/Graphics/glrgraph.hpp
@@ -0,0 +1,1637 @@
+/**************DO NOR REMOVE THIS BANNER***************/
+/*  FreeFEM : Language for a Finite Element Method    */
+/*  -------    Release 2.0:  June 2007.               */
+/*  Authors: D. Bernardi, Y. Darmaillac F. Hecht,     */
+/*           O. Pironneau                             */
+// ********** DO NOT REMOVE THIS BANNER **********
+/*
+ // SUMMARY  :      
+ // USAGE    :        
+ // ORG      : 
+ // AUTHOR   : Frederic Hecht
+ // E-MAIL   : hecht at ann.jussieu.fr
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/* (fax)    Olivier.Pironneau at ann.jussieu.fr          */
+/******************************************************/
+//#define FREEFEM
+//  AGL  apple 
+//  XGL   X11  
+//  WGL   window (a faire) 
+
+const char * edpfilenamearg=0;	 	
+bool  waitatend=true;
+bool  consoleatend=true;
+
+#ifdef AGL
+#define TARGET_API_MAC_CARBON 1
+#define CALL_IN_SPOCKETS_BUT_NOT_IN_CARBON 1
+#include <Carbon/Carbon.h>
+    
+#include <AGL/agl.h>
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+
+#endif
+#ifdef XGL
+#include <GL/glx.h>
+#include <X11/cursorfont.h>
+#include <X11/keysymdef.h>
+#endif
+#ifndef AGL
+#include <GL/gl.h>
+#include <GL/glu.h>
+#endif
+
+#include <sys/stat.h>
+
+#include "error.hpp"
+#include <fstream>
+#include <iostream>
+#include <stdlib.h>
+using namespace std;
+
+#include <errno.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include "rgraph.hpp"
+#include <time.h>
+#include <setjmp.h>
+#include <time.h>
+
+int currx=0,curry=0;
+static FILE *psfile = 0;
+static FILE *psfile_save = 0;
+
+#ifdef AGL
+static	AGLPixelFormat fmt;
+static	AGLContext ctx;
+
+int pStrCopy (StringPtr p1, char * p2);
+StringPtr c2p(const char * p,char *buf);
+#endif
+#ifdef XGL
+static  Display *dpy;
+static  Window win;
+static  XSizeHints size_hints;
+//static  GC gc;
+static  XFontStruct *font_info;
+GLXContext cx;
+int stensize;
+static Cursor cursor_watch,cursor_arrow;
+static int shift, control,shiftlock,alt;
+static GLuint basefont; 
+#endif
+
+
+extern long verbosity;  // level off printing
+
+
+#ifdef FREEFEM
+void myenviron ()
+{
+  cout << "FreeFEM error: operator new failed; not enough memory" << endl;
+  if (myenviron)
+   longjmp(myenvironj,1);
+  exit(2);
+}
+//  pour imprimer la version   FH 
+#define STRING(i) #i
+#include <new.h>
+
+jmp_buf myenvironj;
+static int  myenviron = 0;
+
+void out_of_memory ();
+void NEW_HANDLER (void);
+void compile(char *fname);
+float scali(int i);
+float scalj(int j);
+void execute(char* what);
+char Getijc(int & x,int & y);
+int DoMouseDown (int windowPart, WindowPtr whichWindow, EventRecord *myEvent);
+ void NEW_HANDLER (void){  set_new_handler (&myenvironj);}
+#endif
+
+static int nbcolor;
+static int ncolortable;
+static int LastColor; // LastColor=1 => Noir et Blanc 
+
+#ifdef AGL
+#define	ours(w)		(w==grafWindow0)
+static WindowPtr	 grafWindow0;
+static GrafPtr          grafPort0;
+static	Rect		boundsRect;
+static CursHandle  CrossCurseur ;
+static CursHandle  WatchCurseur ;
+static  Pattern  white,black;
+#else
+struct RGBColor {
+  unsigned short      red;                    /*magnitude of red component*/
+  unsigned short      green;                  /*magnitude of green component*/
+  unsigned short      blue;                   /*magnitude of blue component*/
+};
+#endif
+
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+
+static bool grey=false;
+static  int cube6[7][3] ={ {65534,0,0},{65534,65534,0},{0,65534,0},{0,65534,65534},{0,0,65534}
+     , {65534,0,65534},{65534,0,0} }; 
+static  int grey6[2][3] ={ {65534,65534,65534},{0,0,0} }; 
+
+char errbuf[255];
+static int INITGRAPH=0;
+static float aspx, aspy, echx,echy,ech,rxmin,rxmax,rymin,rymax;
+static int carre, lacouleur;
+static	GLuint fontList;
+
+
+
+static int width,height;
+
+static RGBColor * colortable;
+int getcolor();
+void putpixel(int ix,int iy, int couleur);
+int scalx(float x);
+int scaly(float y);
+void thisexit();
+
+
+void DrawCStringGL (const char * cstrOut, GLuint fontList)
+{
+	GLint i = 0;
+	glRasterPos3d(currx,height-curry,0);
+	while (cstrOut [i])
+		glCallList (fontList + cstrOut[i++]);
+}
+
+
+#ifdef AGL
+void InitMac();
+// --------------------------------------------------------------------------------------------------------------
+
+// --------------------------------------------------------------------------------------------------------------
+// APPLE EVENT SUPPORT ROUTINES
+// --------------------------------------------------------------------------------------------------------------
+
+StringPtr c2p(const char * p, unsigned char * buf)
+{
+  int l=strlen(p);
+  assert(l<255);
+
+  buf[0]=l;
+  memcpy(buf+1,p,l);
+  return buf; 
+}
+
+int pStrCopy (StringPtr p1, char * p2)
+/* copies a pascal string `p1 into a C string */
+{
+	int len,i;
+	
+	len = (*p1++) %256;
+	for(i=1;i<=len;i++) *p2++=*p1++;
+	*p2 = 0;
+	return 0;
+}
+
+void InitMac()
+{
+	BitMap	screenBitMap;
+	Rect	screenBits;
+	Cursor theArrow;
+	GetQDGlobalsScreenBits(&screenBitMap);
+	screenBits = screenBitMap.bounds;
+	SetCursor(GetQDGlobalsArrow(&theArrow));
+
+}
+class InitilisationMac {
+  static int init;
+  public:
+   InitilisationMac(){ InitMac();}
+};
+
+static InitilisationMac Initmac; // to call InitMac
+
+
+int getprog(char* fn,int  argc, char** argv)
+{ 
+ if (argc > 1) 
+  {
+     int ret=0;
+     for (int i=1; i<argc;i++)
+	 if  (ret ==0 && strcmp(argv[i],"-f")==0 && i+1 < argc  ) 
+	 {
+	     strcpy(fn,argv[i+1]);
+	     i++;	
+	     ret=1;
+	 }
+	     else if  (strcmp(argv[i],"-v")==0 && i+1 < argc) 
+	     {
+		 verbosity = atoi(argv[i+1]);
+		 i++;	
+	     }
+	     else if(ret==0)
+	     {
+		 strcpy(fn,argv[i]);
+		 ret=1;
+	     }
+	     if(ret==0) 
+	     {
+		 if(argc>0)
+		     cerr << " Syntaxe : " << argv[0] << "  -f filename  [-v verbosity] " << endl;
+		 else 
+		     cerr << " Syntaxe : FreeFem++-agl  -f filename  [-v verbosity] " << endl;
+		 
+		 return ret; 
+	     }
+     return 1;
+     
+  }
+ else 
+  {   OSErr anErr;
+
+
+  FSRef  fsRef;
+   NavDialogOptions dialogOptions;
+  NavReplyRecord reply;
+  
+  anErr=NavGetDefaultDialogOptions(&  dialogOptions);
+  if( anErr != noErr)  return -1;
+  anErr =NavChooseFile(0,&reply,&dialogOptions,0,0,0,0,0) ;  
+  if (anErr == noErr && reply.validRecord)
+   {
+                //  Deal with multiple file selection
+                long    count;
+                
+                anErr = AECountItems(&(reply.selection), &count);
+                // Set up index for file list
+                if (anErr == noErr)
+                {
+                    long index;
+                    
+                    for (index = 1; index <= count; index++)
+                    {
+                        AEKeyword   theKeyword;
+                        DescType    actualType;
+                        Size        actualSize;
+                        FSSpec      documentFSSpec;
+                        
+                        // Get a pointer to selected file
+                        anErr = AEGetNthPtr(&(reply.selection), index,
+                                            typeFSRef, &theKeyword,
+                                            &actualType,&fsRef,
+                                            sizeof(fsRef),
+                                            &actualSize);
+                        if (anErr == noErr)
+                         {  
+                          anErr=FSRefMakePath(&fsRef,(UInt8*)fn,256);
+                          if ( anErr == noErr )
+                           {
+                           cout <<  "Path : " << fn << endl;
+                           char * ff=fn,*fff=0;
+                           while ( *ff)
+                            { 
+                              if (*ff=='/') fff=ff;
+                              ff++;
+                            }
+                           if (fff) { 
+                             *fff=0;                              
+                             cout << "chdir to "<< fn << endl;
+                            chdir(fn);
+                             *fff='/';}
+                           }
+                           else cout << "Err: "<< anErr << endl;
+                           /*
+                        anErr = AEGetNthPtr(&(reply.selection), index,
+                                            typeFSS, &theKeyword,
+                                            &actualType,&documentFSSpec,
+                                            sizeof(documentFSSpec),
+                                            &actualSize);
+                           anErr = HSetVol(0,documentFSSpec.vRefNum,documentFSSpec.parID);
+                           pStrCopy(documentFSSpec.name, fn);*/
+                         }
+                    }
+                }
+                //  Dispose of NavReplyRecord, resources, descriptors
+                anErr = NavDisposeReply(&reply);
+     
+   }
+   else return 0; // erreur cancel
+	return (2);
+	}
+}
+
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+GLuint BuildFontGL (AGLContext ctx, GLint fontID, Style face, GLint size)
+{
+	GLuint listBase = glGenLists (256);
+	if (aglUseFont (ctx, fontID , face, size, 0, 256, (long) listBase))
+	{
+		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+		return listBase;
+	}
+	else
+	{
+		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+		glDeleteLists (listBase, 256);
+		return 0;
+	}
+}
+#else
+#include "getprog-unix.hpp"
+
+
+#endif
+
+#ifdef XGL
+void  MyXSelectInput(Display * dpy,Window w,int  mask)
+
+{
+  XSetWindowAttributes attributes;
+  attributes.event_mask = mask;
+  XChangeWindowAttributes(dpy, w, CWEventMask, &attributes);
+}
+#endif
+
+//-----------------------------------------------------------------------------------------------------------------------
+
+void DeleteFontGL (GLuint fontList)
+{
+	if (fontList)
+		glDeleteLists (fontList, 256);
+}
+
+void coutmode(short i) 
+{ 
+   cout <<  flush;
+   cerr <<  flush;
+;}
+
+#ifdef FREEFEM
+
+
+void myexit(int err)
+{
+ if (INITGRAPH)
+  {
+    rattente(0);
+    closegraphique();
+  }
+ if (err !=0)
+    cout << "Error: freefem+ has ended with error code " <<err<<endl;
+// else cout << "Normal exit 0" << endl;
+  if (myenviron)
+   longjmp(myenvironj,1);
+}
+void thisexit(){ myexit();}
+
+int main (int argc, char **argv)
+{
+  char       *prog;
+  char       fname[256];
+  argc = getprog (fname, argc, argv);
+  atexit(thisexit);
+  NEW_HANDLER (); // see dependent system files ({pc,x,mac}rgraph.{h,cpp})
+  
+
+  int OPTION = 0;
+  if (argc == 2)
+    {
+        initgraphique();
+        if(0==setjmp(myenvironj))
+         {  myenviron=1;
+	   compile (fname);
+	  // cout << "No Error" << endl;
+	 }
+	myenviron = 0;			
+    }
+  else
+    printf ("To launch freefem you must type the keyword freefem  and a file name\n");
+  
+  return 0;
+}
+#else
+extern int mymain(int argc,char **argv);
+string StrVersionNumber();
+
+int main (int argc, char **argv)
+{
+    char * wn = new  char [256];
+   for (int i=0;i<256;i++)
+     wn[i] = 0;
+   strcpy(wn,"   -- FreeFem++ ");
+   strcat(wn,StrVersionNumber().c_str());
+   
+   int ret=15;  
+   try {                  
+          ret=mymain(argc,argv);}
+   catch( Error & err) {
+     ret=err.errcode();
+     cerr  << err.what() << endl;                        
+                        }
+   catch( ...) { cerr << "catch exception ???";}
+                        
+
+ return ret;
+}
+
+void myexit(int err) { 
+  cout << " The End err=" << err << endl;
+  exit(err);}
+
+#endif
+
+void message(char *s)
+{ 
+   printf("%s	\n", s);
+}
+
+void erreur(char *s)
+{
+    cout  << endl;
+    cerr << "##Fatal error  :" << s << endl << "exit(1)" <<  endl;
+    exit(1);
+}
+
+void *safecalloc(long nb, long size)
+{
+  void* p=NULL;
+  p = calloc(nb, size);
+  if (p == NULL) 
+     erreur("Out of Memory!\n");
+  return p;
+}
+
+void safefree(void** f)
+{
+  if(*f)
+  { 
+    free(*f); 
+    *f=NULL;
+  }
+}
+
+void initgraphique(void)
+{
+    if(INITGRAPH) return;
+ //   cout <<"Initgraphique \n" ;
+    fontList=0;
+#ifdef AGL 
+    unsigned char buf40[40];
+    BitMap	screenBitMap;
+    Rect	screenBits;
+    Cursor theArrow;
+    GetQDGlobalsScreenBits(&screenBitMap);
+    screenBits = screenBitMap.bounds;
+    SetCursor(GetQDGlobalsArrow(&theArrow));
+    
+    boundsRect.top = 45;
+    boundsRect.left = (short) (15 +  (0.35 * screenBits.right));
+    boundsRect.bottom = screenBits.bottom -  25;
+    boundsRect.right =  screenBits.right-  25;
+    if((boundsRect.bottom - boundsRect.top) < (boundsRect.right - boundsRect.left))
+      boundsRect.right = boundsRect.left + boundsRect.bottom - boundsRect.top;
+    else
+      boundsRect.bottom = boundsRect.top + boundsRect.right - boundsRect.left;
+    grafWindow0=NewCWindow(0, &boundsRect, c2p("FreeFem Graphics",buf40),true, 8, (WindowPtr) -1L, true, 0);
+    
+    //ShowWindow(grafWindow0);
+    BringToFront(grafWindow0);
+    //SelectWindow(grafWindow0);
+    SetPortWindowPort(grafWindow0);
+    GetPort(&grafPort0);
+    
+    height = boundsRect.bottom - boundsRect.top - 10;
+    width = boundsRect.right - boundsRect.left -10;
+    aspx = boundsRect.right - boundsRect.left -10;
+    aspy = boundsRect.bottom - boundsRect.top - 10;
+    
+    
+    
+    GLint attrib[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_NONE };
+    
+    fmt = aglChoosePixelFormat(NULL, 0, attrib); /* Choose pixel format */
+    
+    ctx = aglCreateContext(fmt, NULL); 	/* Create an AGL context */
+    
+    aglDestroyPixelFormat(fmt); // pixel format is no longer needed
+    
+    aglSetDrawable(ctx, GetWindowPort (grafWindow0)); /* Attach the context to the window */
+    
+    {
+      EventRecord event;
+      WaitNextEvent (everyEvent, &event, 1, NULL);
+    }
+    
+    aglSetCurrentContext(ctx);
+    short int fNum;
+    // cout <<" GetFNum \n";
+    unsigned char buf10[10];
+    GetFNum(c2p("Geneva",buf10), &fNum);									// build font
+	fontList = BuildFontGL (ctx, fNum, normal, 9); 
+#endif
+#ifdef XGL
+ {
+    XVisualInfo* vi;
+    Colormap cmap;
+    XSetWindowAttributes swa;
+    static int attrib[] = { GLX_RGBA,
+			    GLX_DOUBLEBUFFER,
+			    GLX_RED_SIZE, 1,
+			    GLX_GREEN_SIZE, 1,
+			    GLX_BLUE_SIZE, 1,
+			    GLX_DEPTH_SIZE, 16,
+			    GLX_STENCIL_SIZE, 4,
+			    None };
+
+    /* get a connection */
+      dpy = XOpenDisplay(0);
+  if (!dpy) 
+    {
+      cerr << " Error openning  dpy " << endl;
+      exit(2);
+    }
+
+    /* get an appropriate visual */
+    vi = glXChooseVisual(dpy, DefaultScreen(dpy), attrib);
+    if (vi == NULL) {
+	fprintf(stderr, "Can't find a satisfactory visual.  Abort.\n");
+	exit(1);
+    }
+    glXGetConfig(dpy, vi, GLX_STENCIL_SIZE, &stensize);
+
+    /* create a GLX context */
+    cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+
+    /* create a color map */
+    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
+                           vi->visual, AllocNone);
+
+    /* create a window */
+    swa.colormap = cmap;
+    swa.border_pixel = 0;
+    swa.event_mask = StructureNotifyMask;
+    height = 512;
+    width = 512;
+	aspx = width;
+	aspy =height;
+    win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, width, height,
+                        0, vi->depth, InputOutput, vi->visual,
+                        CWBorderPixel|CWColormap|CWEventMask, &swa);
+    XMapWindow(dpy, win);
+	glXMakeCurrent(dpy, win, cx); 
+    cursor_arrow = XCreateFontCursor(dpy,XC_arrow);
+    cursor_watch = XCreateFontCursor(dpy,XC_watch);
+    XDefineCursor(dpy,win,cursor_watch);
+    MyXSelectInput (dpy, win, (int) (ExposureMask
+				       | KeyPressMask
+				       | KeyReleaseMask
+				       | ButtonPressMask
+				       | ButtonReleaseMask
+				       /*                               | ResizeRedirectMask   */
+				       | StructureNotifyMask)
+		  ); 
+  font_info = XLoadQueryFont(dpy, "6x9");
+  //XSetFont(dpy, gc, font_info->fid);
+  {unsigned int first, last; 	   
+  int id = font_info->fid;
+    first = font_info->min_char_or_byte2;
+    last = font_info->max_char_or_byte2;     
+    fontList = glGenLists(last+1);
+    if (fontList == 0) {
+        printf ("out of display lists\n");
+    exit (1);
+    }
+    glXUseXFont(id, first, last-first+1, fontList+first);     
+    }
+}    
+    
+#endif
+#ifdef WGL
+    a faire 
+#endif
+	carre = aspx == aspy;
+	lacouleur = getcolor();
+	nbcolor= 256; 
+	ncolortable =0;
+	LastColor=2;// En couleur pas defaul
+	colortable=0;
+	SetColorTable(2+6);
+
+	INITGRAPH = 1;
+    gluOrtho2D(0.0, height,0,width);
+    glLineWidth(1);
+	
+    // cout <<" End Initgraphique\n";
+}
+
+static RGBColor DefColorGL( int k,int nb, bool hsv,bool grey,int nbcolors,float *colors)
+{
+ RGBColor C;
+ float r,g,b;
+extern void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool grey,int nbcolors,float *colors);
+ DefColor(r,g,b,   k,nb,hsv,grey,nbcolors,colors);
+ C.red= (short unsigned int) (65535*r);
+ C.green=(short unsigned int)(65535*g);
+ C.blue= (short unsigned int) (65535*b);
+ return C;
+}              
+
+void SetColorTable1(int nb,bool hsv,int nbcolors,float *colors)
+{
+  static bool greyo = !grey;
+  static float * colorso=0;
+  if(!INITGRAPH) return;
+   if (ncolortable == nb && greyo == grey && colorso == colors ) return;// optim
+   greyo = grey;
+   colorso=colors;
+   if (nbcolor && nb>2) 
+     { 
+       if(colortable) delete [] colortable;
+       colortable = new RGBColor[nb];
+       ncolortable = nb;
+       if(LastColor>1) LastColor=nb-1;
+        for (int i0=0;i0<nb;i0++)
+         {  
+           colortable[i0]=DefColorGL(i0,nb,hsv,grey,nbcolors,colors);           
+          }
+  /*    for (k=0;k<ncolortable;k++)
+           cout << " color"  << k 
+                <<" r = " << colortable[k].red 
+                <<" g = " << colortable[k].green
+                <<" b = " << colortable[k].blue << endl;
+  */    
+         
+       }
+     else 
+      ncolortable  =0;
+}
+void SetColorTable(int nb)
+{
+  if(!INITGRAPH) return;
+   if (ncolortable == nb) return;// optim
+   if (nbcolor && nb>2) 
+     { 
+       if(colortable) delete [] colortable;
+       colortable = new RGBColor[nb];
+       ncolortable = nb;
+       if(LastColor>1) LastColor=nb-1;
+       int k=0;
+       colortable[k].red=65534;
+       colortable[k].green=65534;
+       colortable[k].blue=65534;
+       k++;
+       colortable[k].red=0;
+       colortable[k].green=0;
+       colortable[k].blue=0;
+       k++;
+       nb = nb -2;
+       for (long i0=0;i0<nb;i0++,k++)
+         {  
+      //     long  i1 = nb - i0;
+           long  i6 = i0*6;
+           long  j0 = i6/nb;// in 0..6
+           long  j1 = j0+1;// in 1..6
+           long  k0 = i0 - (nb*j0)/6L;
+           long  k1 = (nb*j1)/6L-i0;
+           long  kk = k0+k1;
+           //cout << "\t\t" << i0 << " " << j0 << " " << j1 << " " << k0 << " " << k1  << " "<<kk<<endl;
+         	if(kk<=0) kk=1;
+         // throwassert(kk);
+         
+          if (! grey)
+           {
+           colortable[k].red   = (cube6[j1][0]*k0+cube6[j0][0]*k1)/kk;
+           colortable[k].green = (cube6[j1][1]*k0+cube6[j0][1]*k1)/kk;
+           colortable[k].blue  = (cube6[j1][2]*k0+cube6[j0][2]*k1)/kk;
+           }
+          else 
+           {
+           kk=nb-1;
+           k1 =  i0;
+           k0 = nb - i0 -1;
+           colortable[k].red   = (grey6[0][0]*k0+grey6[1][0]*k1)/kk;
+           colortable[k].green = (grey6[0][1]*k0+grey6[1][1]*k1)/kk;
+           colortable[k].blue  = (grey6[0][2]*k0+grey6[1][2]*k1)/kk;
+           }
+         
+       /*    colortable[k].red   = (cube6[j1][0]*k0+cube6[j0][0]*k1)/kk;
+           colortable[k].green = (cube6[j1][1]*k0+cube6[j0][1]*k1)/kk;
+           colortable[k].blue  = (cube6[j1][2]*k0+cube6[j0][2]*k1)/kk;*/ 
+           throwassert(k<ncolortable);
+           
+          }
+  /*    for (k=0;k<ncolortable;k++)
+           cout << " color"  << k 
+                <<" r = " << colortable[k].red 
+                <<" g = " << colortable[k].green
+                <<" b = " << colortable[k].blue << endl;
+  */    
+         
+       }
+     else 
+      ncolortable  =0;
+}
+void closegraphique(void)
+{
+  if(INITGRAPH) 
+    {
+    
+ 	DeleteFontGL (fontList);
+#ifdef AGL 	
+	aglSetCurrentContext (NULL);
+	aglSetDrawable (ctx, NULL);
+	aglDestroyContext (ctx);
+    DisposeWindow(grafWindow0);
+#endif
+#ifdef XGL
+      XUnloadFont(dpy, font_info->fid);
+//      XFreeGC(dpy, gc);
+      XCloseDisplay(dpy);
+#endif
+#ifdef WGL
+  a faire 
+#endif
+      closePS();    
+     delete [] colortable;colortable=0;
+    }
+  INITGRAPH=0;
+}
+void showgraphic()
+{
+#ifdef AGL
+  if (grafWindow0 != FrontWindow())
+   { 
+	ShowWindow(grafWindow0);
+	BringToFront(grafWindow0);
+	SelectWindow(grafWindow0);
+	SetPortWindowPort(grafWindow0); }
+	GetPort(&grafPort0);
+#endif
+	
+}
+
+void reffecran(void)
+{
+  if(!INITGRAPH) return;
+  		glClearColor(1.f, 1.f, 1.f, 1.0f);
+		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* Clear buffer */
+
+ 
+}
+
+int getcolor(void)
+{ return lacouleur;
+}
+
+void putpixel(int ix,int iy, int couleur)
+{
+//  if (ncolortable>3 && couleur < ncolortable && couleur >=0 ) 
+//    SetCPixel(ix,iy,colortable+couleur);
+//  DrawCStringGL ((char*) glGetString (GL_VENDOR), fontList);
+  glBegin(GL_POINTS);
+  glVertex2i(ix, height-iy);
+  glEnd();
+
+}
+
+ void plotstring(const char *s)
+{ 
+// cout << "plotstring" << s << endl;
+int lx=0,l = strlen(s);
+ DrawCStringGL(s,fontList);
+#ifdef XGL
+  lx = XTextWidth( font_info,s,l);
+#endif
+ if(psfile) fprintf(psfile,"(%s) S\n",s);
+ currx += lx;
+} 
+
+int LaCouleur(){return lacouleur;}
+
+void couleur(int c)
+{ 
+  if ( lacouleur == c) // small optim
+    return;
+  c= c > LastColor ? 1 : c; // c=Min(c,LastColor); pour noir et blanc
+  lacouleur =c;
+    float r=1,g=1,b=1;
+      if (c>=0 && c < ncolortable)
+	{
+	  r =  (float) colortable[c].red /65535.F;
+	  g =  (float) colortable[c].green /65535.F;
+	  b =  (float) colortable[c].blue /65535.F;
+	 }
+     else if (c!=0)
+      r=g=b=0;
+ 	glColor4f (r,g,b,1.);
+    if (psfile)
+     fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b);
+   
+}
+
+int InRecScreen(float x1, float y1,float x2, float y2)
+{  
+  float xi = Min(x1,x2),xa=Max(x1,x2);
+  float yi = Min(y1,y2),ya=Max(y1,y2);
+  return (xa >= rxmin) && (xi <= rxmax) && (ya >= rymin) && (yi <= rymax);
+}
+int InPtScreen( float x, float y)
+{
+  return (x >= rxmin) && (x <= rxmax) && (y >= rymin) && (y <= rymax);
+}
+
+void penthickness(int pepais)
+{
+//  PenSize(pepais,pepais);
+  glLineWidth(pepais);
+  if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais);
+}
+void cadre(float xmin,float xmax,float ymin,float ymax)
+{
+  rxmin = xmin;
+  rxmax = xmax;
+  rymin = ymin;
+  rymax = ymax;
+  echx = aspx / (xmax - xmin);
+  echy = aspy / (ymax - ymin);
+}
+void getcadre(float &xmin,float &xmax,float &ymin,float &ymax)
+{
+  xmin = rxmin;
+  xmax = rxmax;
+  ymin = rymin;
+  ymax = rymax;
+
+}
+
+void cadreortho(float centrex, float centrey, float rayon)
+{
+  float xasp,yasp, getmaxx, getmaxy;
+  
+	getmaxx = xasp =aspx;	getmaxy = yasp = aspy;
+	
+  if (getmaxx * (float)xasp > getmaxy * (float)yasp)
+  {
+    rymin = centrey - rayon;
+    rymax = centrey + rayon;
+    echy= getmaxy / (2 * rayon);
+    echx= (echy * xasp) / yasp;
+    rxmin= centrex - getmaxx / (2 * echx);
+    rxmax= centrex + getmaxx / (2 * echx);
+  }
+  else
+  {
+    rxmin = centrex - rayon;
+    rxmax = centrex + rayon;
+    echx = getmaxx / (2 * rayon);
+    echy = (echx * yasp) / xasp;
+    rymin = centrey - getmaxy / (2 * echy);
+    rymax = centrey + getmaxy / (2 * echy);
+  }
+ // cout << "cadreortho\n";
+}
+
+int scalx(float x)
+{
+  return int((x - rxmin) * echx);
+}
+
+int scaly(float y)
+{
+  return int((rymax - y) * echy);
+}
+
+float scali(int i)
+{
+  return i/echx  + rxmin;
+}
+float scalj(int j)
+{
+  return -j/echy  + rymax;
+}
+
+void pointe(float x, float y)
+{
+  int newx = scalx(x), newy = scaly(y);
+  putpixel(newx, newy, lacouleur);
+  if (psfile) 
+   fprintf(psfile,"%d %d P\n", newx, height-newy);
+  
+}
+
+void rmoveto(float x, float y)
+{
+  int newx = scalx(x), newy = scaly(y);
+ // MoveTo(newx,newy);
+  if (psfile) 
+   fprintf(psfile,"%d %d M\n", newx, height-newy);
+  currx = newx; curry = newy;
+  
+}
+
+void rlineto(float x, float y)
+{
+  int newx = scalx(x), newy = scaly(y);
+  glBegin(GL_LINES);
+  glVertex2i(currx, height-curry);
+  glVertex2i(newx, height-newy);
+  glEnd();
+   if (psfile) 
+    fprintf(psfile,"%d %d L\n", newx,height-newy);
+  currx = newx; curry = newy;
+  
+}
+
+
+void fillpoly(int n, float *poly)
+{
+  glBegin(GL_POLYGON);
+  for (int i=0;i<n;i++)
+    glVertex2i(scalx(poly[2*i]),height-scaly( poly[2*i+1]));
+  glEnd();
+    if (psfile) 
+    {
+     fprintf(psfile,"bF ");
+     for (int i=0;i<n;i++)
+      fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1]));
+     fprintf(psfile,"eF\n");
+    }
+}
+
+
+
+
+
+
+int execute(const char* what)
+{
+  system(what);
+  return 1; // error
+}
+
+#ifdef AGL
+int DoMouseDown (int windowPart, WindowPtr whichWindow, EventRecord *myEvent)
+{
+  int wasactive;
+	switch (windowPart) {
+		case inGoAway:
+			if (ours(whichWindow))
+				if (TrackGoAway(whichWindow, myEvent->where))
+					{ 
+					   closegraphique();
+					   cout << "The end (closing the graphic window) " <<endl;
+					   exit(0);
+					   //HideWindow(whichWindow);  
+					} 
+			break;
+
+		case inZoomIn:
+			if (ours(whichWindow))
+				{
+					//SetCursor(&waitCursor);
+					 SetPortWindowPort(whichWindow);
+	                                 GetPort(&grafPort0);
+					 reffecran();
+					//EraseRect(&(whichWindow->portRect));
+					ZoomWindow(whichWindow, inZoomIn, true);
+					InitCursor();
+				}
+			break;
+
+		case inZoomOut:
+/*			if (ours(whichWindow))
+				{
+					SetCursor(&waitCursor); SetPort(whichWindow);
+					EraseRect(&(whichWindow->portRect));
+					ZoomWindow(whichWindow, inZoomOut, true);
+					if(whichWindow == editWindow) 
+						 MyZoomWindow(whichWindow);
+					InitCursor();
+				}*/
+			break;
+
+		case inMenuBar:
+//			return(DoCommand(MenuSelect(myEvent->where)));
+            break;
+
+		case inSysWindow:
+			//SystemClick(myEvent, whichWindow);
+			break;
+
+		case inDrag:
+			if (ours(whichWindow))
+				{
+					SetPortWindowPort(whichWindow);
+				        GetPort(&grafPort0);
+
+		//			DragWindow(whichWindow, myEvent->where, &dragRect);
+				}
+			break;
+
+		case inGrow:
+			//if (ours(whichWindow))
+			//	{MyGrowWindow(whichWindow, myEvent->where);}
+			break;
+
+		case inContent:
+			wasactive = (whichWindow == FrontWindow()); 
+	     if(!wasactive) { SelectWindow(whichWindow);
+	//	    if (ours(whichWindow) && MacReDraw ) (* MacReDraw)();
+		   }
+		  else if (ours(whichWindow))
+			{ SetPortWindowPort(whichWindow);	GetPort(&grafPort0);
+
+			   while (Button()) ;
+			   return 0;
+			}
+			break;
+	}
+return 1;
+}
+char HandleEvent(EventRecord	&	myEvent) 
+{
+  //  cout << "HandleEvent\n";
+	WindowPtr		whichWindow=NULL;
+	short			windowPart;
+     
+     char char1=0;
+	   switch (myEvent.what) {
+		case mouseDown:
+  		windowPart = FindWindow(myEvent.where, &whichWindow);
+	    if( DoMouseDown(windowPart, whichWindow, &myEvent) ==0) 
+	      char1=  251;
+	    break; 
+
+//
+//
+//		case keyDown:
+		case keyUp:
+		case autoKey: 
+			{
+
+			 windowPart = FindWindow(myEvent.where, &whichWindow);
+			if((whichWindow==grafWindow0) /* && (inContent == windowPart)*/)
+				{ if  (grafWindow0 !=  FrontWindow()) { 
+				     SelectWindow(whichWindow); 
+		             SetPortWindowPort(whichWindow);	GetPort(&grafPort0);
+
+		             }
+				   char1 = (myEvent.message & 127L);
+				  
+				}
+			break;}
+		
+	   case updateEvt:
+	   /* 
+	     if (ours((WindowPtr) myEvent.message)) {
+	       	BeginUpdate((WindowPtr) myEvent.message);
+		    EndUpdate((WindowPtr) myEvent.message);
+	     } */
+	    break;
+   // cout << "End HandleEvent" << int(char1) << endl;
+
+}
+  return char1;
+}
+
+
+#endif
+
+char Getijc(int & x,int & y)
+{   
+   char char1=0;
+
+#ifdef AGL 
+viderbuff();
+   showgraphic();
+    EventRecord		myEvent;
+	int flag=1;
+//	HLock( (Handle) WatchCurseur);
+//	SetCursor(*CrossCurseur);
+//	HUnlock( (Handle) WatchCurseur);
+   SelectWindow(grafWindow0);
+   while (char1==0) {
+	if (GetNextEvent(everyEvent, &myEvent) /* ,OxFFFFFFFF,h)*/) 
+	  char1=HandleEvent(myEvent);
+	 }
+   GlobalToLocal( & myEvent.where);
+   x = myEvent.where.h;
+   y = myEvent.where.v;
+#endif
+#ifdef XGL
+  XEvent event;
+  int flag,nb;
+  XComposeStatus status;
+  char buffer[20];
+  KeySym keysym;   /*  incidence */
+  XDefineCursor(dpy,win,cursor_arrow);
+  flag=0;
+  while (!flag)
+  { XNextEvent(dpy, &event);
+    if(event.type == ButtonRelease) 
+    { x = event.xbutton.x;
+      y = event.xbutton.y; 
+      if      (event.xbutton.button == Button1) char1=shift?248:251;
+      else if (event.xbutton.button == Button2) char1=shift?249:252;
+      else                                      char1=shift?250:253; 
+      //     printf(" mouse release %d\n",(int) char1);
+      flag=1;
+    }
+    else if(event.type == KeyPress)
+    { x = event.xkey.x;
+      y = event.xkey.y; 
+      char1= event.xkey.keycode ;
+       keysym=0;
+       nb=XLookupString(&event.xkey,buffer,20,&keysym,&status);
+
+/*        printf("nb= %d keysym= %d buffer=",nb,keysym);
+/*        for(i=0;i<20;i++)
+/*         printf(" %d ",(int)buffer[i]);
+/*        printf("\n");
+*/
+
+/*       voir    /usr/include/X11/keysymdef.h + ap_keysym */
+
+       if (nb != 0) 
+         {char1 = buffer[0];
+          flag= 1; 
+         }
+       else
+         {
+/*          if     (IsFunctionKey(keysym))     printf("function down\n");
+          else if(IsModifierKey(keysym))     printf("modifier down\n");
+          else if(IsKeypadKey(keysym))       printf(" keypad down\n");
+          else if(IsMiscFunctionKey(keysym)) printf(" misc function down\n");
+          else if(IsPFKey(keysym))           printf(" PF key down\n");
+*/
+#ifdef XK_MISCELLANY	      
+
+          switch(keysym) 
+            {
+/* Cursor control & motion */
+	      /*
+            case XK_Left :
+              flag = 1;
+              char1 = call(keyboa).curs_left;
+              break;
+            case XK_Up :
+              flag = 1;
+              char1 = call(keyboa).curs_up;
+              break;
+            case XK_Right :
+              flag = 1;
+              char1 = call(keyboa).curs_right;
+              break;
+            case XK_Down :
+              flag = 1;
+              char1 = call(keyboa).curs_down;
+              break;
+            case XK_Next :
+              flag = 1;
+              char1 = call(keyboa).pad_down;
+              break;
+            case XK_Prior :
+              flag = 1;
+              char1 = call(keyboa).pad_up;
+              break;
+            case XK_End :
+              flag = 1;
+              char1 = call(keyboa).marg_right;
+              break;
+            case XK_Begin :
+              flag = 1;
+              char1 = call(keyboa).marg_left;
+              break;
+	      */
+/* Misc Functions */ 
+	      /* 
+
+            case XK_Select :
+              flag = 1;
+              char1 = call(keyboa).mark;
+              break; */
+/*
+            case XK_Print :
+              flag = 1;
+              char1 = ;
+              break;  
+            case XK_Execute :
+              flag = 1;
+              char1 = ;
+              break;  
+            case XK_Insert :
+              flag = 1;
+              char1 = ;
+              break;
+
+            case XK_Undo :
+              flag = 1;
+              char1 = call(keyboa).undo;
+              break;
+
+            case XK_Redo :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Menu :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Find :
+              flag = 1;
+              char1 = ;
+              break;
+
+
+            case XK_Cancel :
+              flag = 1;
+              char1 = call(keyboa).line_del;
+              break;
+            case XK_Help :
+              flag = 1;
+              char1 = call(keyboa).help;
+              break;
+
+            case XK_Break :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Mode_switch :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_script_switch :
+              flag = 1;
+              char1 = ;
+              break;
+            case XK_Num_Lock :
+              flag = 1;
+              char1 = ;
+              break;
+
+            case XK_F1 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct1 : call(keyboa).funct1 ;
+              break;
+            case XK_F2 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct2 : call(keyboa).funct2 ;
+              break;
+            case XK_F3 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct3 : call(keyboa).funct3 ;
+              break;
+            case XK_F4 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct4 : call(keyboa).funct4 ;
+              break;
+            case XK_F5 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct5 : call(keyboa).funct5 ;
+              break;
+            case XK_F6 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct6 : call(keyboa).funct6 ;
+              break;
+            case XK_F7 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct7 : call(keyboa).funct7 ;
+              break;
+            case XK_F8 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct8 : call(keyboa).funct8 ;
+              break;
+            case XK_F9 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct9 : call(keyboa).funct9 ;
+              break;
+            case XK_F10 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct10 : call(keyboa).funct10 ;
+              break;
+            case XK_F11 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct11 : call(keyboa).funct11 ;
+              break;
+            case XK_F12 :
+              flag = 1;
+              char1 = shift ? call(keyboa).sfunct12 : call(keyboa).funct12 ;
+              break;
+	      */
+            case XK_Shift_L :
+              shift=1;
+              break;
+            case XK_Shift_R :
+              shift=1;
+              break;
+           case XK_Control_L :
+              control=1;
+              break;
+            case XK_Control_R :
+              control=1;
+              break;
+            case XK_Caps_Lock :
+              shiftlock = 1 ;
+              break;
+            case XK_Shift_Lock :
+              shiftlock = 1 ;
+              break;
+            case XK_Meta_L :
+              alt=1;
+              break;
+            case XK_Meta_R :
+              alt=1;
+              break;
+            case XK_Alt_L :
+              alt=1;
+              break;
+            case XK_Alt_R :
+              alt=1;
+              break;
+            } /* end switch */
+#endif              
+         }
+    }
+    else if(event.type == KeyRelease)
+    { x = event.xkey.x;
+      y = event.xkey.y; 
+      char1= event.xkey.keycode ;
+       keysym=0;
+       nb=XLookupString(&event.xkey,buffer,20,&keysym,&status);
+/*          if     (IsFunctionKey(keysym))     printf("function up\n");
+          else if(IsModifierKey(keysym))     printf("modifier up\n");
+          else if(IsKeypadKey(keysym))       printf(" keypad up\n");
+          else if(IsMiscFunctionKey(keysym)) printf(" misc function up\n");
+          else if(IsPFKey(keysym))           printf(" PF key up\n");
+*/
+       if (nb == 0) 
+         {
+#ifdef XK_MISCELLANY	      
+          switch(keysym)
+            {
+            
+            case XK_Shift_L :
+              shift=0;
+              break;
+            case XK_Shift_R :
+              shift=0;
+              break;
+           case XK_Control_L :
+              control=0;
+              break;
+            case XK_Control_R :
+              control=0;
+              break;
+            case XK_Caps_Lock :
+              shiftlock = 0 ;
+              break;
+            case XK_Shift_Lock :
+              shiftlock = 0 ;
+              break;
+            case XK_Meta_L :
+              alt=0;
+              break;
+            case XK_Meta_R :
+              alt=0;
+              break;
+            case XK_Alt_L :
+              alt=0;
+              break;
+            case XK_Alt_R :
+              alt=0;
+              break;
+              
+            } /* end switch */
+#endif	      
+
+         }
+    }
+  }
+  XDefineCursor(dpy,win,cursor_watch);
+  XFlush(dpy);
+#endif
+#ifdef WGL
+  a faire 
+#endif
+  return char1;
+    
+    
+
+}
+
+
+char Getxyc(float &x,float &y)
+{ 
+  char c;
+  int i,j;
+ // cout << "getxyc \n";
+  c = Getijc( i,j);
+  x = scali(i);
+  y = scalj(j);
+//  cout << "getxyc out \n";
+  return c;
+}
+
+void  viderbuff(){
+     glFinish();
+#ifdef AGL     
+     aglSwapBuffers (ctx); // send swap command
+#endif
+#ifdef XGL     
+     glXSwapBuffers (dpy,win); // send swap command
+#endif
+
+}
+
+
+void rattente(int waitm)
+{ int i,j;
+ char   c=0;
+ if(waitm)  c = Getijc( i,j);
+ if ( c == 3) {cout << "rattente: ^c => abort " << endl;closegraphique();exit(1);}// ^c  => exit
+/*    you may prefer to use carriage return to move to the next graph */
+/*	 getc(stdin);
+*/
+// if(waitm) while(!Button()){ };
+}
+
+//void GetSizeScreen(int & ix,int &iy);
+// GetScreenSize_
+void GetScreenSize(int & ix,int &iy)
+{
+  	ix = width ;
+  	iy = height;
+}
+
+
+
+void openPS(const char *filename )
+{ 
+  char ffff[32];
+  int count=0;
+  if(psfile_save) closePS();
+  time_t t_loc;
+  float s=0.5;
+  const int shiftx=50,shifty=50;
+ // char  username[10];
+  time(&t_loc);
+  bool notfound;
+  if( !filename) 
+   do {
+      struct stat buf;
+      sprintf(ffff,"rgraph_%.3d.ps",count++);
+      volatile int r= stat(ffff,&buf) ;
+      notfound = r !=0;
+      if(count>1000) break;
+    } while ( !notfound );
+   
+  psfile=fopen(filename?filename:ffff,"w");
+   
+  if(psfile==0) {printf("Erreur %s errno %d\n",filename?filename:ffff,errno);exit(1);}
+  if(psfile) {
+  fprintf(psfile,"%%!PS-Adobe-2.0 EPSF-2.0\n%%%%Creator: %s\n%%%%Title: FreeFem++\n","user");
+  fprintf(psfile,"%%%%CreationDate: %s",ctime(&t_loc));
+  fprintf(psfile,"%%%%Pages: 1\n");
+  fprintf(psfile,"%%%%BoundingBox:       %d %d %d %d\n",shiftx,shifty,int(shiftx+width*s),int(shifty+height*s));
+  fprintf(psfile,"%%%%EndComments\n");
+  fprintf(psfile," /L {  lineto currentpoint stroke newpath moveto} def\n");
+  fprintf(psfile," /M {  moveto } def\n");
+  fprintf(psfile," /C {setrgbcolor} def\n");
+  fprintf(psfile," /rec {newpath 4 copy 8 1 roll moveto 3 -1 roll lineto 4 2 roll exch lineto lineto closepath} def\n");
+  fprintf(psfile," %d %d  translate \n",shiftx,shifty);
+  fprintf(psfile," %f %f  scale \n",s,s);
+  fprintf(psfile," 0 %d 0 %d rec clip newpath\n",int(width),int(height));
+  fprintf(psfile," /Helvetica findfont 10 scalefont setfont\n");
+  fprintf(psfile," /S { show} def\n");
+  fprintf(psfile," /bF  { mark} def \n");
+  fprintf(psfile," /eF {newpath moveto counttomark 2 idiv {lineto} repeat closepath fill cleartomark} def\n");
+  fprintf(psfile," /P { /yy exch def /xx exch def   xx xx 1 add yy yy 1 add  rec  fill } def\n");
+
+  fprintf(psfile," 1 setlinewidth\n");
+  psfile_save=psfile;
+  }
+}
+void closePS(void)
+{
+  if(psfile_save)   {
+    fprintf(psfile_save,"showpage\n");
+    fclose(psfile_save);
+    }
+    
+  psfile=0;
+  psfile_save=0;
+  
+}
+
+  void Commentaire(const char * c)  
+  {
+  if(psfile)   {
+    fprintf(psfile,"%% %s\n",c);
+   }
+  };
+  void NoirEtBlanc(int NB)
+  {
+    if(NB) LastColor=1;
+    else LastColor=ncolortable?ncolortable:2;
+  }
+ 
+  void MettreDansPostScript(int in)
+   {
+     if(in)  psfile=psfile_save;     
+     else    psfile=0;
+   }
+
+static void     FillRect(float x0,float y0, float x1, float y1)
+ {
+     float r[8];
+     r[0]=x0;r[1]=y0;
+     r[2]=x1;r[3]=y0;
+     r[4]=x1;r[5]=y1;
+     r[6]=x0;r[7]=y1;
+     fillpoly(4,r);
+ }
+
+float  GetHeigthFont()
+{ 
+ // FontInfo 	MyFontInfo;
+ // GetFontInfo(&MyFontInfo);  
+#ifdef XGL   				
+  int dir,asc,desc,k;
+  XCharStruct overall;
+
+  XTextExtents(font_info,"gML",3,&dir,&asc,&desc,&overall); 
+  return (asc+desc)*(0.9/echy);
+#else  
+ int interligne = 9;// MyFontInfo.ascent + MyFontInfo.descent + MyFontInfo.leading;
+ return interligne/echy;
+#endif
+
+}
+
+
+
+int PutLevel(int lineno, float xf, int col)
+{
+  float xmin,xmax,ymin,ymax;
+  getcadre(xmin,xmax,ymin,ymax);
+  float xleft = xmax - (xmax-xmin)*0.1;
+  float ytop  = ymax;
+  float ydelta = (ymax-ymin)/40;
+  ydelta=GetHeigthFont();
+  xleft = xmax - 6*ydelta;  
+  ytop -= ydelta*(col+2);
+  couleur(col);
+  FillRect(xleft+ydelta/8.,ytop+ydelta/8.,xleft+ydelta*7./8.,ytop+ydelta*7./8.);
+  rmoveto(xleft+ydelta*1.4,ytop+ydelta/4);
+  char buf[30];
+  sprintf(buf,"%g",xf);
+  couleur(1);
+  plotstring(buf);
+
+   return lineno;
+}
+ void ShowHelp(const char * s,int k)
+{
+  if(k) {
+    MettreDansPostScript(0);
+    couleur(1);
+    float xmin,xmax,ymin,ymax;
+    getcadre(xmin,xmax,ymin,ymax);
+    rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+    plotstring(s);
+    MettreDansPostScript(1);
+       //  couleur(1);	
+  }
+}
+
+class Grid;
+  void setgrey(bool gg ){grey=gg;}
+  int getgrey(){ return grey;}
+
+void SaveMesh(Grid &t){}
+void SavePlot(int D, Grid& t, double *f){}
+void SavePlot(int D, Grid& t, float *f){}
+
diff --git a/src/Graphics/macglrgraf.cpp b/src/Graphics/macglrgraf.cpp
new file mode 100644
index 0000000..f865f98
--- /dev/null
+++ b/src/Graphics/macglrgraf.cpp
@@ -0,0 +1,29 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :           
+// ORG      : UPMC
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#define AGL 1
+#define FF_GRAPH_SET_PTR
+#include "glrgraph.hpp"
diff --git a/src/Graphics/macrgraf.cpp b/src/Graphics/macrgraf.cpp
new file mode 100644
index 0000000..f933c7b
--- /dev/null
+++ b/src/Graphics/macrgraf.cpp
@@ -0,0 +1,1180 @@
+//
+// SUMMARY  :           
+// ORG      : UPMC
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+/**************DO NOR REMOVE THIS BANNER***************/
+/*  FreeFEM++ : Language for a Finite Element Method    */
+/*  -------    Release 1.0:  June 1994.               */
+/*  Authors: D. Bernardi, Y. Darmaillac F. Hecht,     */
+/*           O. Pironneau                             */
+// -*- Mode : c++ -*-
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/* out our consent : fax (33)1 44 27 44 11            */
+/* (fax)    Olivier.Pironneau at ann.jussieu.fr          */
+/******************************************************/
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+/*  Authors: D. Bernardi, Y. Darmaillac F. Hecht,     */
+/*           O. Pironneau                             */
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+const char * edpfilenamearg=0;	 	
+bool  waitatend=true;
+
+//#define TARGET_API_MAC_CARBON 1
+#define FF_GRAPH_SET_PTR
+#include <MSLCarbonPrefix.h>
+#include <sioux.h>
+#include <SIOUXGlobals.h> //OP my hack
+#include "error.hpp"
+#include <fstream>
+#include <iostream>
+#include <stdlib.h>
+using namespace std;
+
+#include <errno.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#define fill thequikdrawfill
+#include "rgraph.hpp"
+#include <Windows.h>
+#include <Fonts.h>
+#include <SegLoad.h>
+#include <Quickdraw.h>
+//#include <StandardFile.h>
+#include <Navigation.h>
+#include <time.h>
+#include <setjmp.h>
+#include <time.h>
+#include <unix.h>
+#include <SIOUX.h> 
+#undef fill
+
+static FILE *psfile = 0;
+static FILE *psfile_save = 0;
+
+static bool grey=false;
+int pStrCopy (StringPtr p1, char * p2);
+
+#ifdef FREEFEM
+//  pour imprimer la version   FH 
+#define STRING(i) #i
+#include <new.h>
+
+jmp_buf environ;
+static int  myenviron = 0;
+
+TEHandle TESioux;
+
+void out_of_memory ();
+void NEW_HANDLER (void);
+void compile(char *fname);
+float scali(int i);
+float scalj(int j);
+void execute(char* what);
+int DoMouseDown (int windowPart, WindowPtr whichWindow, EventRecord *myEvent);
+char Getijc(int & x,int & y);
+ 
+
+void out_of_memory ()
+{
+  cout << "FreeFEM error: operator new failed; not enough memory" << endl;
+  if (myenviron)
+   longjmp(environ,1);
+  exit(2);
+}
+
+void NEW_HANDLER (void){  set_new_handler (&out_of_memory);}
+#endif
+
+#define	ours(w)		(w==grafWindow0)
+
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+
+static  int cube6[7][3] ={ {65534,0,0},{65534,65534,0},{0,65534,0},{0,65534,65534},{0,0,65534}
+     , {65534,0,65534},{65534,0,0} }; 
+static  int grey6[2][3] ={ {65534,65534,65534},{0,0,0} }; 
+
+char errbuf[255];
+static int INITGRAPH=0;
+static float aspx, aspy, echx,echy,ech,rxmin,rxmax,rymin,rymax;
+static int carre, lacouleur;
+// static CWindowRecord wgRecord0;
+static WindowPtr	 grafWindow0;
+static GrafPtr          grafPort0;
+static	Rect		boundsRect;
+static int nbcolor;
+static CursHandle  CrossCurseur ;
+static CursHandle  WatchCurseur ;
+static int ncolortable;
+static int LastColor; // LastColor=1 => Noir et Blanc 
+static  Pattern  white,black;
+
+static int width,height;
+static RGBColor * colortable;
+int getcolor();
+void putpixel(int ix,int iy, int couleur);
+int scalx(float x);
+int scaly(float y);
+void thisexit();
+void InitMac();
+// --------------------------------------------------------------------------------------------------------------
+
+// --------------------------------------------------------------------------------------------------------------
+// APPLE EVENT SUPPORT ROUTINES
+// --------------------------------------------------------------------------------------------------------------
+static OSStatus	MissingParameterCheck(
+	const AppleEvent 	*inputEvent)
+/*
+	This routine checks an input AppleEvent for the missing keyword.
+	If the missing keyword is found, that means that some required
+	parameters were missing (ie, an error). 
+	
+	However, if the missing keyword isn't found, that means that we aren't missing 
+	any required parameters (that is to say, all REQUIRED parameters were supplied
+	by the person who created the event).
+	
+	SOME DAY, THE ABOVE COMMENT WILL MAKE SENSE TO YOU.  IT STILL DOESN'T
+	TO ME AND I WAS THE ONE WHO WROTE IT.
+*/
+{
+	OSStatus		anErr;
+	AEKeyword	missingKeyword;
+	DescType	ignoredActualType;
+	Size		ignoredActualSize;
+	
+	anErr = AEGetAttributePtr(
+		inputEvent, 
+		keyMissedKeywordAttr,
+		typeWildCard,
+		&ignoredActualType,
+		(Ptr) &missingKeyword,
+		sizeof(AEKeyword),
+		&ignoredActualSize);
+			
+	if (anErr == noErr)
+		anErr = errAEParamMissed;
+	else
+		if (anErr == errAEDescNotFound)
+			anErr = noErr;
+		
+	return anErr;
+	
+} // MissingParameterCheck
+
+
+static pascal OSErr	DoOpenApp(
+	const AppleEvent 	*inputEvent,
+	AppleEvent 	*outputEvent,
+	SInt32		handlerRefCon)
+{
+/*
+ #pragma unused (outputEvent, handlerRefCon)
+
+	DoCommand(nil, cNew, 0, 0);
+	
+	// so that the initial document opens more quickly, we don't start
+	// the threads until we get an OpenApp or OpenDocument AppleEvent
+	if (gStarterThread != kNoThreadID)
+		SetThreadState(gStarterThread, kReadyThreadState, gStarterThread);
+*/	
+	return(MissingParameterCheck(inputEvent));
+	
+} // DoOpenApp
+
+// --------------------------------------------------------------------------------------------------------------
+static pascal OSErr	DoReopenApp(
+	const AppleEvent 	*inputEvent,
+	AppleEvent 	*outputEvent,
+	SInt32		handlerRefCon)
+{
+/*
+#pragma unused (outputEvent, handlerRefCon)
+
+	if (FrontWindow() == nil)
+		DoCommand(nil, cNew, 0, 0);
+*/	
+	return(MissingParameterCheck(inputEvent));
+	
+} // DoReopenApp
+
+// --------------------------------------------------------------------------------------------------------------
+// --------------------------------------------------------------------------------------------------------------
+static pascal OSStatus	DoOpenFile(
+	const AppleEvent 	*inputEvent
+	)	// nil == 0, zero length == print to default, other == printer name
+{
+
+	OSStatus		anErr, anErr2;
+	AEDescList	docList;				// list of docs passed in
+	long		index, itemsInList;
+	Boolean		wasAlreadyOpen;
+/*	
+	anErr = AEGetParamDesc( inputEvent, keyDirectObject, typeAEList, &docList);
+	nrequire(anErr, GetFileList);
+
+	anErr = AECountItems( &docList, &itemsInList);			// how many files passed in
+	nrequire(anErr, CountDocs);
+	for (index = 1; index <= itemsInList; index++)			// handle each file passed in
+	{	
+		AEKeyword	keywd;
+		DescType	returnedType;
+		Size		actualSize;
+		FSRef 		fileRef;
+		FSCatalogInfo	theCatInfo;
+		
+		anErr = AEGetNthPtr( &docList, index, typeFSRef, &keywd, &returnedType,
+						(Ptr)(&fileRef), sizeof( fileRef ), &actualSize );
+		nrequire(anErr, AEGetNthPtr);
+
+		anErr = FSGetCatalogInfo( &fileRef, kFSCatInfoFinderInfo, &theCatInfo, NULL, NULL, NULL );
+/*		
+		nrequire(anErr, FSGetCatalogInfo);
+
+		if (anErr == noErr)
+			anErr = DetermineWindowTypeOrOpen(&fileRef, ((FInfo*)&theCatInfo.finderInfo)->fdType, nil, nil, &wasAlreadyOpen);
+			
+			
+*/		
+
+//	}
+
+	return anErr;
+	
+} // DoOpenOrPrint
+
+// --------------------------------------------------------------------------------------------------------------
+static pascal OSErr	DoOpenDocument(
+	const AppleEvent 	*inputEvent,
+	AppleEvent 	*outputEvent,
+	SInt32		handlerRefCon)
+{
+
+#pragma unused (outputEvent, handlerRefCon)
+
+	OSStatus		anErr=0;
+	
+    anErr = DoOpenFile(inputEvent);
+
+	return anErr;
+	
+} // DoOpenDocument
+void InitMac()
+{
+#if TARGET_API_MAC_OS8
+	InitGraf(&qd.thePort);
+	InitFonts();
+	InitWindows();
+	InitMenus();
+	TEInit();
+	InitDialogs(0L);
+	FlushEvents(everyEvent, 0L);	
+	MaxApplZone();
+#endif /* TARGET_API_MAC_OS8 */
+	MoreMasters();
+	
+	InitCursor();
+#if TARGET_API_MAC_CARBON
+	BitMap	screenBitMap;
+	Rect	screenBits;
+	Cursor theArrow;
+	GetQDGlobalsScreenBits(&screenBitMap);
+	screenBits = screenBitMap.bounds;
+	SetCursor(GetQDGlobalsArrow(&theArrow));
+#else
+	Rect screenBits = qd.screenBits.bounds;
+	SetCursor(&qd.arrow);
+#endif /* TARGET_API_MAC_CARBON */
+	
+  SIOUXSettings.initializeTB = 0; // else SIOUX initialize the toolbox for us
+  SIOUXSettings.toppixel = 45;
+  SIOUXSettings.leftpixel = 15; 
+//  SIOUXSettings.fontface = bold + italic;// or normal
+  SIOUXSettings.asktosaveonclose = 0;
+  
+  short bas = screenBits.bottom;
+  short droit = screenBits.right;  
+  SIOUXSettings.columns = (short)(2.+(float)droit/8.);
+  SIOUXSettings.rows = (short)(10. + (float)bas/18.);
+  SIOUXSetTitle("\pfreefem+ line output"); //marche pas!!
+  SIOUXSettings.fontface = normal;
+  SIOUXSettings.fontid = 22;// courier;
+  SIOUXSettings.fontsize = 10;
+  cout << "Initmac" << endl;
+  
+	#define INSTALL(event, handler) \
+			AEInstallEventHandler(kCoreEventClass, event, handler, 0, false)
+	// AEC, changed to use the correct handler procs
+//	INSTALL (kAEOpenApplication, NewAEEventHandlerUPP(DoOpenApp));
+//	INSTALL (kAEReopenApplication, NewAEEventHandlerUPP(DoReopenApp));
+	INSTALL (kAEOpenDocuments,   NewAEEventHandlerUPP(DoOpenDocument));
+	#undef INSTALL
+
+}
+class InitilisationMac {
+  static int init;
+  public:
+   InitilisationMac(){ InitMac();}
+};
+
+static InitilisationMac Initmac; // to call InitMac
+
+int getprog(char* fn,int  argc, char** argvptr)
+{
+   OSErr anErr;
+
+  NavDialogOptions dialogOptions;
+  NavReplyRecord reply;
+  
+  anErr=NavGetDefaultDialogOptions(&  dialogOptions);
+  if( anErr != noErr)  return -1;
+  anErr =NavChooseFile(0,&reply,&dialogOptions,0,0,0,0,0) ;  
+  if (anErr == noErr && reply.validRecord)
+   {
+                //  Deal with multiple file selection
+                long    count;
+                
+                anErr = AECountItems(&(reply.selection), &count);
+                // Set up index for file list
+                if (anErr == noErr)
+                {
+                    long index;
+                    
+                    for (index = 1; index <= count; index++)
+                    {
+                        AEKeyword   theKeyword;
+                        DescType    actualType;
+                        Size        actualSize;
+                        FSSpec      documentFSSpec;
+                        
+                        // Get a pointer to selected file
+                        anErr = AEGetNthPtr(&(reply.selection), index,
+                                            typeFSS, &theKeyword,
+                                            &actualType,&documentFSSpec,
+                                            sizeof(documentFSSpec),
+                                            &actualSize);
+                        if (anErr == noErr)
+                         {  
+                           anErr = HSetVol(0,documentFSSpec.vRefNum,documentFSSpec.parID);
+                           pStrCopy(documentFSSpec.name, fn);
+                         }
+                    }
+                }
+                //  Dispose of NavReplyRecord, resources, descriptors
+                anErr = NavDisposeReply(&reply);
+     
+   }
+   else return 0; // erreur cancel
+	return (2);
+}
+#ifdef FREEFEM
+
+
+        void thisexit(){ myexit();}
+
+int main (int argc, char **argv)
+{
+  char       *prog;
+  char       fname[256];
+  SIOUXSettings.sleep=1;
+  argc = getprog (fname, argc, argv);
+  atexit(thisexit);
+  NEW_HANDLER (); // see dependent system files ({pc,x,mac}rgraph.{h,cpp})
+  
+
+  int OPTION = 0;
+  if (argc == 2)
+    {
+        initgraphique();
+        if(0==setjmp(environ))
+         {  myenviron=1;
+	   compile (fname);
+	  // cout << "No Error" << endl;
+	 }
+	myenviron = 0;			
+    }
+  else
+    printf ("To launch freefem you must type freefem  and a file name\n");
+  
+  return 0;
+}
+#else
+extern int mymain(int argc,char **argv);
+string StrVersionNumber();
+
+int main (int argc, char **argv)
+{
+   SIOUXUseWaitNextEvent = true;
+   SIOUXSettings.sleep=0;
+    char * wn = new  char [256];
+   for (int i=0;i<256;i++)
+     wn[i] = 0;
+   strcpy(wn,"   -- FreeFem++ ");
+   strcat(wn,StrVersionNumber().c_str());
+   
+   SIOUXSetTitle((unsigned char *) wn);
+   int ret=15;  
+                        try {                  
+                          ret=mymain(argc,argv);}
+                        catch( ...) { cerr << "catch exception ???";}
+                        catch( Error & err) {
+                          cerr  << err.what() << endl;                        
+                        }
+
+ return ret;
+}
+ void myexit(int i)
+  {
+    exit(i);
+   
+  }
+ 
+#endif
+
+void coutmode(short i) 
+{ 
+   cout <<  flush;
+   cerr <<  flush;
+ //  if(i)(**(SIOUXTextWindow->edit)).txFace = 0;
+ //  else (**(SIOUXTextWindow->edit)).txFace = 1;
+;}
+
+void message(char *s)
+{ 
+   printf("%s	\n", s);
+}
+
+void erreur(char *s)
+{
+    cout  << endl;
+    cerr << "##Fatal error  :" << s << endl << "exit(1)" <<  endl;
+    exit(1);
+}
+
+void *safecalloc(long nb, long size)
+{
+  void* p=NULL;
+  p = calloc(nb, size);
+  if (p == NULL) 
+     erreur("Out of Memory!\n");
+  return p;
+}
+
+void safefree(void** f)
+{
+  if(*f)
+  { 
+    free(*f); 
+    *f=NULL;
+  }
+}
+
+void initgraphique(void)
+{
+    if(INITGRAPH) return;
+#if TARGET_API_MAC_CARBON
+	BitMap	screenBitMap;
+	Rect	screenBits;
+	Cursor theArrow;
+	GetQDGlobalsScreenBits(&screenBitMap);
+	screenBits = screenBitMap.bounds;
+	SetCursor(GetQDGlobalsArrow(&theArrow));
+#else
+	Rect screenBits = qd.screenBits.bounds;
+	SetCursor(&qd.arrow);
+#endif /* TARGET_API_MAC_CARBON */
+
+	boundsRect.top = 45;
+	boundsRect.left = (short) (15 +  (0.35 * screenBits.right));
+	boundsRect.bottom = screenBits.bottom -  25;
+	boundsRect.right =  screenBits.right-  25;
+	if((boundsRect.bottom - boundsRect.top) < (boundsRect.right - boundsRect.left))
+		boundsRect.right = boundsRect.left + boundsRect.bottom - boundsRect.top;
+	else
+		boundsRect.bottom = boundsRect.top + boundsRect.right - boundsRect.left;
+	  grafWindow0=NewCWindow(0, &boundsRect, "\pFreeFem Graphics",true, 8, NULL, true, 0);
+	ShowWindow(grafWindow0);
+	BringToFront(grafWindow0);
+	SelectWindow(grafWindow0);
+	SetPortWindowPort(grafWindow0);
+	GetPort(&grafPort0);
+	height = boundsRect.bottom - boundsRect.top - 10;
+	width = boundsRect.right - boundsRect.left -10;
+	aspx = boundsRect.right - boundsRect.left -10;
+	aspy = boundsRect.bottom - boundsRect.top - 10;
+	carre = aspx == aspy;
+	lacouleur = getcolor();
+	CrossCurseur = GetCursor(crossCursor);
+	WatchCurseur = GetCursor(watchCursor);
+        GetQDGlobalsWhite(&white);
+        GetQDGlobalsBlack(&black);
+	
+	//if( (**(wgRecord0.port.portPixMap)).pixelSize>7)
+		nbcolor= 256; 
+	//else 
+	//	nbcolor= 2;
+
+
+	ncolortable =0;
+	LastColor=2;// En couleur pas defaul
+	colortable=0;
+	SetColorTable(2+6);
+  //    TextFont(fontNum);
+	TextSize(9); // small size 
+	INITGRAPH = 1;
+	
+
+}
+
+static RGBColor DefColorMacOs( int k,int nb,bool hsv, bool grey,int nbcolors,float *colors)
+{
+ RGBColor C;
+ float r,g,b;
+ extern void DefColor(float & r, float & g, float & b,
+              int k,int nb,bool hsv, bool grey,int nbcolors,float *colors);
+ DefColor(r,g,b,   k,nb,hsv,grey,nbcolors,colors);
+ C.red=65535*r;
+ C.green=65535*g;
+ C.blue=65535*b;
+ return C;
+}              
+
+void SetColorTable1(int nb,bool hsv,int nbcolors,float *colors)
+{
+  static bool greyo = !grey;
+  static float * colorso =0;
+  if(!INITGRAPH) return;
+   if (ncolortable == nb && greyo == grey && colorso == colors ) return;// optim
+   greyo = grey;
+   colorso=colors;
+   if (nbcolor && nb>2) 
+     { 
+       if(colortable) delete [] colortable;
+       colortable = new RGBColor[nb];
+       ncolortable = nb;
+       if(LastColor>1) LastColor=nb-1;
+        for (int i0=0;i0<nb;i0++)
+         {  
+           colortable[i0]=DefColorMacOs(i0,nb,hsv,grey,nbcolors,colors);           
+          }
+  /*    for (k=0;k<ncolortable;k++)
+           cout << " color"  << k 
+                <<" r = " << colortable[k].red 
+                <<" g = " << colortable[k].green
+                <<" b = " << colortable[k].blue << endl;
+  */    
+         
+       }
+     else 
+      ncolortable  =0;
+}
+void SetColorTable(int nb)
+{
+  SetColorTable1(nb,false,0,0);
+}
+
+void closegraphique(void)
+{
+  if(INITGRAPH) 
+    { 
+     DisposeWindow(grafWindow0);
+     delete [] colortable;colortable=0;
+    }
+  INITGRAPH=0;
+}
+void showgraphic()
+{
+  
+  if (grafWindow0 != FrontWindow())
+   { 
+	ShowWindow(grafWindow0);
+	BringToFront(grafWindow0);
+	SelectWindow(grafWindow0);
+	SetPortWindowPort(grafWindow0); }
+	GetPort(&grafPort0);
+	
+}
+
+void reffecran(void)
+{
+  if(!INITGRAPH) return;
+    Rect rect;
+    GetPortBounds(grafPort0,&rect);
+    EraseRect(&rect);
+ 
+}
+
+int getcolor(void)
+{ return 0;
+}
+
+void putpixel(int ix,int iy, int couleur)
+{
+  if (ncolortable>3 && couleur < ncolortable && couleur >=0 ) 
+    SetCPixel(ix,iy,colortable+couleur);
+}
+
+ void plotstring(const char *s)
+{  DrawText(s,0,strlen(s));
+ if(psfile) fprintf(psfile,"(%s) S\n",s);
+} 
+
+int LaCouleur(){return lacouleur;}
+
+void couleur(int c)
+{ 
+  if ( lacouleur == c) // small optim
+    return;
+  c= c > LastColor ? 1 : c; // c=Min(c,LastColor); pour noir et blanc
+  lacouleur =c;
+  if ( c == 0 )
+    ForeColor(30);
+  else if (ncolortable>3 && c < ncolortable && c >=0 ) 
+    RGBForeColor(colortable+c);
+  else 
+   ForeColor(33);
+ if (psfile)
+  {
+    float r=1,g=1,b=1;
+    if (colortable) {
+      if (c>0 && c < ncolortable)
+	{
+	  r =  (float) colortable[c].red /65535.F;
+	  g =  (float) colortable[c].green /65535.F;
+	  b =  (float) colortable[c].blue /65535.F;
+	}
+    }
+    else if (c!=0)
+      r=g=b=0;
+    
+    fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b);
+  }
+   
+}
+
+int InRecScreen(float x1, float y1,float x2, float y2)
+{  
+  float xi = Min(x1,x2),xa=Max(x1,x2);
+  float yi = Min(y1,y2),ya=Max(y1,y2);
+  return (xa >= rxmin) && (xi <= rxmax) && (ya >= rymin) && (yi <= rymax);
+}
+int InPtScreen( float x, float y)
+{
+  return (x >= rxmin) && (x <= rxmax) && (y >= rymin) && (y <= rymax);
+}
+
+void penthickness(int pepais)
+{
+  PenSize(pepais,pepais);
+  if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais);
+}
+void cadre(float xmin,float xmax,float ymin,float ymax)
+{
+  rxmin = xmin;
+  rxmax = xmax;
+  rymin = ymin;
+  rymax = ymax;
+  echx = aspx / (xmax - xmin);
+  echy = aspy / (ymax - ymin);
+}
+void getcadre(float &xmin,float &xmax,float &ymin,float &ymax)
+{
+  xmin = rxmin;
+  xmax = rxmax;
+  ymin = rymin;
+  ymax = rymax;
+
+}
+
+void cadreortho(float centrex, float centrey, float rayon)
+{
+  int xasp,yasp, getmaxx, getmaxy;
+  
+	getmaxx = xasp =aspx;	getmaxy = yasp = aspy;
+	
+  if (getmaxx * (float)xasp > getmaxy * (float)yasp)
+  {
+    rymin = centrey - rayon;
+    rymax = centrey + rayon;
+    echy= getmaxy / (2 * rayon);
+    echx= (echy * xasp) / yasp;
+    rxmin= centrex - getmaxx / (2 * echx);
+    rxmax= centrex + getmaxx / (2 * echx);
+  }
+  else
+  {
+    rxmin = centrex - rayon;
+    rxmax = centrex + rayon;
+    echx = getmaxx / (2 * rayon);
+    echy = (echx * yasp) / xasp;
+    rymin = centrey - getmaxy / (2 * echy);
+    rymax = centrey + getmaxy / (2 * echy);
+  }
+}
+
+int scalx(float x)
+{
+  return int((x - rxmin) * echx);
+}
+
+int scaly(float y)
+{
+  return int((rymax - y) * echy);
+}
+
+float scali(int i)
+{
+  return i/echx  + rxmin;
+}
+float scalj(int j)
+{
+  return -j/echy  + rymax;
+}
+
+void pointe(float x, float y)
+{
+  int newx = scalx(x), newy = scaly(y);
+  putpixel(newx, newy, lacouleur);
+  if (psfile) 
+   fprintf(psfile,"%d %d P\n", newx, height-newy);
+  
+}
+
+void rmoveto(float x, float y)
+{
+  int newx = scalx(x), newy = scaly(y);
+  MoveTo(newx,newy);
+  if (psfile) 
+   fprintf(psfile,"%d %d M\n", newx, height-newy);
+  
+}
+
+void rlineto(float x, float y)
+{
+  int newx = scalx(x), newy = scaly(y);
+  LineTo(newx,newy);
+   if (psfile) 
+    fprintf(psfile,"%d %d L\n", newx,height-newy);
+  
+}
+
+void raffpoly(int n, float *poly)
+{
+  PolyHandle thePoly;
+  int i;
+  thePoly =OpenPoly();
+   MoveTo(scalx(poly[0]),scaly( poly[1]));
+    for(i=1; i<n; i++)
+    LineTo(scalx(poly[2*i]),scaly( poly[2*i+1]));
+    ClosePoly();
+    FillPoly(thePoly,&white);
+    FramePoly(thePoly);
+    KillPoly(thePoly);
+}
+void fillpoly(int n, float *poly)
+{
+  PolyHandle thePoly;
+  int i;
+  thePoly =OpenPoly();
+   MoveTo(scalx(poly[0]),scaly( poly[1]));
+    for(i=1; i<n; i++)
+    LineTo(scalx(poly[2*i]),scaly( poly[2*i+1]));
+    ClosePoly();
+    FillPoly(thePoly,&black);
+    FramePoly(thePoly);
+    KillPoly(thePoly);
+    if (psfile) 
+    {
+     fprintf(psfile,"bF ");
+     for (i=0;i<n;i++)
+      fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1]));
+     fprintf(psfile,"eF\n");
+    }
+}
+
+int pStrCopy (StringPtr p1, char * p2)
+/* copies a pascal string `p1 into a C string */
+{
+	int len,i;
+	
+	len = (*p1++) %256;
+	for(i=1;i<=len;i++) *p2++=*p1++;
+	*p2 = 0;
+	return 0;
+}
+
+
+
+
+
+int execute(const char* what)
+{
+  cout << " sorry no execute on MacOs we skip "<< what<<endl;
+  system(what);
+  return 1; // error
+}
+
+int DoMouseDown (int windowPart, WindowPtr whichWindow, EventRecord *myEvent)
+{
+  int wasactive;
+	switch (windowPart) {
+		case inGoAway:
+			if (ours(whichWindow))
+				if (TrackGoAway(whichWindow, myEvent->where))
+					{ 
+					   closegraphique();
+					   cout << "Fin (fermeture fenetre graphique) " <<endl;
+					   exit(0);
+					   //HideWindow(whichWindow);  
+					} 
+			break;
+
+		case inZoomIn:
+			if (ours(whichWindow))
+				{
+					//SetCursor(&waitCursor);
+					 SetPortWindowPort(whichWindow);
+	                                 GetPort(&grafPort0);
+					 reffecran();
+					//EraseRect(&(whichWindow->portRect));
+					ZoomWindow(whichWindow, inZoomIn, true);
+					InitCursor();
+				}
+			break;
+
+		case inZoomOut:
+/*			if (ours(whichWindow))
+				{
+					SetCursor(&waitCursor); SetPort(whichWindow);
+					EraseRect(&(whichWindow->portRect));
+					ZoomWindow(whichWindow, inZoomOut, true);
+					if(whichWindow == editWindow) 
+						 MyZoomWindow(whichWindow);
+					InitCursor();
+				}*/
+			break;
+
+		case inMenuBar:
+//			return(DoCommand(MenuSelect(myEvent->where)));
+            break;
+
+		case inSysWindow:
+			//SystemClick(myEvent, whichWindow);
+			break;
+
+		case inDrag:
+			if (ours(whichWindow))
+				{
+					SetPortWindowPort(whichWindow);
+				        GetPort(&grafPort0);
+
+					DragWindow(whichWindow, myEvent->where, 0);
+				}
+			break;
+
+		case inGrow:
+			//if (ours(whichWindow))
+			//	{MyGrowWindow(whichWindow, myEvent->where);}
+			break;
+
+		case inContent:
+			wasactive = (whichWindow == FrontWindow()); 
+	     if(!wasactive) { SelectWindow(whichWindow);
+	//	    if (ours(whichWindow) && MacReDraw ) (* MacReDraw)();
+		   }
+		  else if (ours(whichWindow))
+			{ SetPortWindowPort(whichWindow);	GetPort(&grafPort0);
+
+			   while (Button()) ;
+			   return 0;
+			}
+			break;
+	}
+return 1;
+}
+char HandleEvent(EventRecord	&	myEvent) 
+{
+	WindowPtr		whichWindow=NULL;
+	short			windowPart;
+     
+     char char1=0;
+	   switch (myEvent.what) {
+		case mouseDown:
+  		windowPart = FindWindow(myEvent.where, &whichWindow);
+	    if( DoMouseDown(windowPart, whichWindow, &myEvent) ==0) 
+	      char1=  251;
+	    break; 
+
+//
+//
+//		case keyDown:
+		case keyUp:
+		case autoKey: 
+			{
+
+			 windowPart = FindWindow(myEvent.where, &whichWindow);
+			if((whichWindow==grafWindow0) /* && (inContent == windowPart)*/)
+				{ if  (grafWindow0 !=  FrontWindow()) { 
+				     SelectWindow(whichWindow); 
+		             SetPortWindowPort(whichWindow);	GetPort(&grafPort0);
+
+		             }
+				   char1 = (myEvent.message & 127L);
+				  
+				}
+			break;}
+	   case updateEvt: 
+	     if (ours((WindowPtr) myEvent.message)) {
+	       	BeginUpdate((WindowPtr) myEvent.message);
+		    EndUpdate((WindowPtr) myEvent.message);
+	     }
+	    break;
+
+}
+  return char1;
+}
+void  viderbuff(){
+   QDFlushPortBuffer(grafPort0,0);
+}
+
+char Getijc(int & x,int & y)
+{   
+   char char1=0;
+   showgraphic();
+    EventRecord		myEvent;
+	int flag=1;
+	HLock( (Handle) WatchCurseur);
+	SetCursor(*CrossCurseur);
+	HUnlock( (Handle) WatchCurseur);
+	SelectWindow(grafWindow0);
+   while (char1==0) {
+	if (GetNextEvent(everyEvent, &myEvent) /* ,OxFFFFFFFF,h)*/) 
+	  char1=HandleEvent(myEvent);
+	 }
+   GlobalToLocal( & myEvent.where);
+   x = myEvent.where.h;
+   y = myEvent.where.v;
+	HLock( (Handle) WatchCurseur);
+	SetCursor(*WatchCurseur);
+	HUnlock( (Handle) WatchCurseur);
+
+ //   printf("\t\t x = %d y = %d  c=%d\n", x,y,char1);
+  return char1;
+    
+    
+
+}
+
+char Getxyc(float &x,float &y)
+{ 
+  char c;
+  int i,j;
+  c = Getijc( i,j);
+  x = scali(i);
+  y = scalj(j);
+  return c;
+}
+
+
+void rattente(int waitm)
+{ int i,j;
+ char   c=0;
+ if(waitm)  c = Getijc( i,j);
+ if ( c == 3) {cout << "rattente: ^c => abort " << endl;closegraphique();exit(1);}// ^c  => exit
+/*    you may prefer to use carriage return to move to the next graph */
+/*	 getc(stdin);
+*/
+// if(waitm) while(!Button()){ };
+}
+
+void GetSizeScreen(int & ix,int &iy);
+void GetScreenSize(int & ix,int &iy)
+{
+  	ix = width ;
+  	iy = height;
+}
+
+
+
+void openPS(const char *filename )
+{ 
+  char ffff[32];
+  int count=0;
+  if(psfile_save) closePS();
+  time_t t_loc;
+  float s=0.5;
+  const int shiftx=50,shifty=50;
+ // char  username[10];
+  time(&t_loc);
+  bool notfound;
+  if( !filename) 
+   do {
+      struct stat buf;
+      sprintf(ffff,"rgraph_%.3d.ps",count++);
+      volatile int r= stat(ffff,&buf) ;
+      notfound = r !=0;
+      if(count>1000) break;
+    } while ( !notfound );
+   
+  psfile=fopen(filename?filename:ffff,"w");
+   
+  if(psfile==0) {printf("Erreur %s errno %d\d",filename?filename:ffff,errno);exit(1);}
+  if(psfile) {
+  fprintf(psfile,"%%!PS-Adobe-2.0 EPSF-2.0\n%%%%Creator: %s\n%%%%Title: FreeFem++\n","user");
+  fprintf(psfile,"%%%%CreationDate: %s",ctime(&t_loc));
+  fprintf(psfile,"%%%%Pages: 1\n");
+  fprintf(psfile,"%%%%BoundingBox:       %d %d %d %d\n",shiftx,shifty,int(shiftx+width*s),int(shifty+height*s));
+  fprintf(psfile,"%%%%EndComments\n");
+  fprintf(psfile," /L {  lineto currentpoint stroke newpath moveto} def\n");
+  fprintf(psfile," /M {  moveto } def\n");
+  fprintf(psfile," /C {setrgbcolor} def\n");
+  fprintf(psfile," /rec {newpath 4 copy 8 1 roll moveto 3 -1 roll lineto 4 2 roll exch lineto lineto closepath} def\n");
+  fprintf(psfile," %d %d  translate \n",shiftx,shifty);
+  fprintf(psfile," %f %f  scale \n",s,s);
+  fprintf(psfile," 0 %d 0 %d rec clip newpath\n",int(width),int(height));
+  fprintf(psfile," /Helvetica findfont 10 scalefont setfont\n");
+  fprintf(psfile," /S { show} def\n");
+  fprintf(psfile," /bF  { mark} def \n");
+  fprintf(psfile," /eF {newpath moveto counttomark 2 idiv {lineto} repeat closepath fill cleartomark} def\n");
+  fprintf(psfile," /P { /yy exch def /xx exch def   xx xx 1 add yy yy 1 add  rec  fill } def\n");
+
+  fprintf(psfile," 1 setlinewidth\n");
+  psfile_save=psfile;
+  }
+}
+void closePS(void)
+{
+  if(psfile_save)   {
+    fprintf(psfile_save,"showpage\n");
+    fclose(psfile_save);
+    }
+    
+  psfile=0;
+  psfile_save=0;
+  
+}
+
+  void Commentaire(const char * c)  
+  {
+  if(psfile)   {
+    fprintf(psfile,"%% %s\n",c);
+   }
+  };
+  void NoirEtBlanc(int NB)
+  {
+    if(NB) LastColor=1;
+    else LastColor=ncolortable?ncolortable:2;
+  }
+ 
+  void MettreDansPostScript(int in)
+   {
+     if(in)  psfile=psfile_save;     
+     else    psfile=0;
+   }
+
+static void     FillRect(float x0,float y0, float x1, float y1)
+ {
+     float r[8];
+     r[0]=x0;r[1]=y0;
+     r[2]=x1;r[3]=y0;
+     r[4]=x1;r[5]=y1;
+     r[6]=x0;r[7]=y1;
+     fillpoly(4,r);
+ }
+
+float  GetHeigthFont()
+{ 
+  FontInfo 	MyFontInfo;
+  GetFontInfo(&MyFontInfo);   				
+ int interligne = MyFontInfo.ascent + MyFontInfo.descent + MyFontInfo.leading;
+ return interligne*0.7/echy;
+}
+
+
+
+int PutLevel(int lineno, float xf, int col)
+{
+  float xmin,xmax,ymin,ymax;
+  getcadre(xmin,xmax,ymin,ymax);
+  float xleft = xmax - (xmax-xmin)*0.1;
+  float ytop  = ymax;
+  float ydelta = (ymax-ymin)/40;
+  ydelta=GetHeigthFont();
+  xleft = xmax - 6*ydelta;  
+  ytop -= ydelta*(col+2);
+  couleur(col);
+  FillRect(xleft+ydelta/8.,ytop+ydelta/8.,xleft+ydelta*7./8.,ytop+ydelta*7./8.);
+  rmoveto(xleft+ydelta*1.4,ytop+ydelta/4);
+  char buf[30];
+  sprintf(buf,"%g",xf);
+  couleur(1);
+  plotstring(buf);
+
+   return lineno;
+}
+ void ShowHelp(const char * s,int k)
+{
+  if(k) {
+    MettreDansPostScript(0);
+    couleur(1);
+    float xmin,xmax,ymin,ymax;
+    getcadre(xmin,xmax,ymin,ymax);
+    rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+    plotstring(s);
+    MettreDansPostScript(1);
+       //  couleur(1);	
+  }
+}
+  void setgrey(bool gg ){grey=gg;}
+  int getgrey(){ return grey;}
+
+class Grid;
+
+void SaveMesh(Grid &t){}
+void SavePlot(int D, Grid& t, double *f){}
+void SavePlot(int D, Grid& t, float *f){}
+
diff --git a/src/Graphics/mode_open.hpp b/src/Graphics/mode_open.hpp
new file mode 100644
index 0000000..a9abcf0
--- /dev/null
+++ b/src/Graphics/mode_open.hpp
@@ -0,0 +1,10 @@
+#ifndef  MODE_OPEN_HPP
+#define  MODE_OPEN_HPP
+#ifdef __WIN32__
+#define  MODE_READ_BINARY "rb"
+#define  MODE_WRITE_BINARY "wb"
+#else
+#define  MODE_READ_BINARY "r"
+#define  MODE_WRITE_BINARY "w"
+#endif
+#endif
diff --git a/src/Graphics/rgraph.hpp b/src/Graphics/rgraph.hpp
new file mode 100644
index 0000000..237e1d5
--- /dev/null
+++ b/src/Graphics/rgraph.hpp
@@ -0,0 +1,250 @@
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+/* -------------------                                */
+/* (e-mail)    Olivier.Pironneau at ann.jussieu.fr       */
+/* (e-mail)    hecht at ann.jussieu.fr                   */
+/******************************************************/
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+// ORIG-DATE:     Dec 97
+#ifndef RGRAPH_H_
+
+#define RGRAPH_H_
+
+// Modif F Hecht for dll on win32 
+// pass all the graphic function via pointeur
+//  now the real graphic function of a pointeur xxxx is call  xxxx_
+//   We just need to add FF_GRAPH_SET_PTR in all graphic.cpp version
+//  the dcl of xxxx pointeur is  done via GRAPH_PTR_DCL macro (set one time ) 
+//  
+// ----- 
+#ifdef FF_GRAPH_SET_PTR
+#define EXTERNFF(t,f,arg) t f##_ arg;  extern t (*f) arg 
+#else
+#ifdef FF_GRAPH_PTR_DCL
+#define EXTERNFF(t,f,arg)  t (*f) arg
+#else
+#define EXTERNFF(t,f,arg) extern t (*f) arg
+#endif
+#endif
+//#define EXTERN 
+#ifdef __cplusplus
+
+#include "config-wrapper.h"
+
+
+//extern "C" {
+EXTERNFF(	void ,getcadre,(float &xmin,float &xmax, float &ymin, float &ymax)) ;
+EXTERNFF(	void ,GetScreenSize,(int &ix,int &iy)) ;	// unused
+EXTERNFF(	char ,Getxyc,(float &x,float &y)) ;
+EXTERNFF(	void ,ShowHelp,(const char * s,int k)) ; // k=1 ??//tlr: deplace ici
+#endif
+EXTERNFF(	void ,erreur,(char *s)) ;
+EXTERNFF(	void ,initgraphique,()) ;	// only in main
+EXTERNFF(	void ,closegraphique,()) ;
+EXTERNFF(	void ,showgraphic,()) ;
+EXTERNFF(	void ,rattente,(int waitm)) ;
+EXTERNFF(	void ,cadre,(float xmin,float xmax, float ymin, float ymax)) ;
+EXTERNFF(	void ,cadreortho,(float centrex, float centrey, float rayon)) ;
+EXTERNFF(	void ,couleur,(int c)) ;
+EXTERNFF(	int  ,LaCouleur,()) ;
+EXTERNFF(	void ,pointe,(float x, float y)) ;
+EXTERNFF(	int ,InPtScreen,(float x, float y)) ;
+EXTERNFF(	int ,InRecScreen,(float x1, float y1,float x2, float y2)) ;
+EXTERNFF(	void ,plotstring,(const char *s)) ;
+EXTERNFF(	void ,rmoveto,(float x, float y)) ;
+EXTERNFF(	void ,rlineto,(float x, float y)) ;
+EXTERNFF(	void ,penthickness,(int )) ;
+EXTERNFF(	int ,execute,(const char* s)) ;
+EXTERNFF(	void ,reffecran,()) ;
+EXTERNFF(	void ,fillpoly,(int n, float *poly)) ;
+EXTERNFF(	void ,SetColorTable,(int nb)) ;
+EXTERNFF(	void ,SetColorTable1,(int nb,bool hsv,int nbcolors,float *colors)) ;
+EXTERNFF(	float ,GetHeigthFont,()) ; 
+//  old function for freefem+  
+//EXTERNFF(	void ,compile,(char *fname)) ;
+//EXTERNFF(	void ,compileString,(char *texte)) ;/*tlr: add a string stream */
+
+EXTERNFF(	void ,openPS,(const char * )) ;
+EXTERNFF(	void ,closePS,(void)) ;
+EXTERNFF(	void ,coutmode,(short i)) ;
+EXTERNFF(	void ,myexit,(int err)) ; // err=0 ??
+EXTERNFF(	void ,viderbuff,()) ;
+EXTERNFF(	void ,Commentaire,(const char *)) ;
+EXTERNFF(	void ,NoirEtBlanc,(int NB)) ;
+EXTERNFF(	void ,MettreDansPostScript,(int in)) ;//  oui=1 ou non=0 
+EXTERNFF(    int ,getprog,(char* fn,int , char** argvptr)) ;
+EXTERNFF(    void ,setgrey,(bool )) ;
+EXTERNFF(    int ,getgrey,(    )) ;
+
+
+// wrapping of function  -----
+#ifdef  FF_GRAPH_SET_PTR 
+static int init_ff_graph_ptr_func()
+{ //  a small function to set all pointeur
+	getcadre=getcadre_;
+	GetScreenSize=GetScreenSize_;
+	Getxyc=Getxyc_;
+	ShowHelp=ShowHelp_;
+	erreur=erreur_;
+	initgraphique=initgraphique_;
+	closegraphique=closegraphique_;
+	showgraphic=showgraphic_;
+	rattente=rattente_;
+	cadre=cadre_;
+	cadreortho=cadreortho_;
+	couleur=couleur_;
+	LaCouleur=LaCouleur_;
+	pointe=pointe_;
+	InPtScreen=InPtScreen_;
+	InRecScreen=InRecScreen_;
+	plotstring=plotstring_;
+	rmoveto=rmoveto_;
+	rlineto=rlineto_;
+	penthickness=penthickness_;
+	execute=execute_;
+	reffecran=reffecran_;
+	fillpoly=fillpoly_;
+	SetColorTable=SetColorTable_;
+	SetColorTable1=SetColorTable1_;
+	GetHeigthFont=GetHeigthFont_;
+	//compile=compile_;
+	//compileString=compileString_;
+	openPS=openPS_;
+	closePS=closePS_;
+	coutmode=coutmode_;
+	myexit=myexit_;
+	viderbuff=viderbuff_;
+	Commentaire=Commentaire_;
+	NoirEtBlanc=NoirEtBlanc_;
+	MettreDansPostScript=MettreDansPostScript_;
+	getprog=getprog_;
+	setgrey=setgrey_;
+	getgrey=getgrey_;
+  return 1;
+}
+//  to call the init function before main 
+static int init_ff_graph_ptr_func_call = init_ff_graph_ptr_func();
+
+#define getcadre getcadre_
+#define GetScreenSize GetScreenSize_
+#define Getxyc Getxyc_
+#define ShowHelp ShowHelp_
+#define erreur erreur_
+#define initgraphique initgraphique_
+#define closegraphique closegraphique_
+#define showgraphic showgraphic_
+#define rattente rattente_
+#define cadre cadre_
+#define cadreortho cadreortho_
+#define couleur couleur_
+#define LaCouleur LaCouleur_
+#define pointe pointe_
+#define InPtScreen InPtScreen_
+#define InRecScreen InRecScreen_
+#define plotstring plotstring_
+#define rmoveto rmoveto_
+#define rlineto rlineto_
+#define penthickness penthickness_
+#define execute execute_
+#define reffecran reffecran_
+#define fillpoly fillpoly_
+#define SetColorTable SetColorTable_
+#define SetColorTable1 SetColorTable1_
+#define GetHeigthFont GetHeigthFont_
+//#define compile compile_
+//#define compileString compileString_
+#define openPS openPS_
+#define closePS closePS_
+#define coutmode coutmode_
+#define myexit myexit_
+#define viderbuff viderbuff_
+#define Commentaire Commentaire_
+#define NoirEtBlanc NoirEtBlanc_
+#define MettreDansPostScript MettreDansPostScript_
+#define getprog getprog_
+#define setgrey setgrey_
+#define getgrey getgrey_
+#endif
+// end wrapping ----	    
+#ifdef __cplusplus
+
+//}
+
+
+
+#ifdef TERM_USED
+
+/** Ouput on the terminal window */	   
+
+class myostream {
+
+	int channel;
+
+	public:
+
+	myostream(int ch) { channel = ch; }
+
+	myostream& operator<<(char c);
+
+	myostream& operator<<(const char *s);
+
+	myostream& operator<<(const void *p);
+
+	myostream& operator<<(int n);
+
+	myostream& operator<<(unsigned int n) { return *this << (int)n; }
+
+	myostream& operator<<(long n);
+
+	myostream& operator<<(unsigned long n) { return *this << (long)n; }
+
+	myostream& operator<<(double n);
+
+	myostream& operator<<(float n) { return *this << (double)n; }
+
+	myostream& operator<<(__omanip func);
+
+};
+
+
+
+extern myostream termout; // could be cout, or another thing
+
+extern myostream termerr; // could be cerr, or another thing
+
+#define cout termout
+
+#define cerr termerr
+
+#endif /* TERM_USED */
+
+
+
+#endif /* __cplusplus */
+
+
+
+#endif /* RGRAPH_H_ */
+
diff --git a/src/Graphics/sansrgraph.cpp b/src/Graphics/sansrgraph.cpp
new file mode 100644
index 0000000..f045424
--- /dev/null
+++ b/src/Graphics/sansrgraph.cpp
@@ -0,0 +1,720 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#define FF_GRAPH_SET_PTR
+using namespace std;
+#include <ctime>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+#include <cassert>
+#include "rgraph.hpp"
+
+#include "error.hpp"
+#ifdef macintoshxx
+#include <ConditionalMacros.h>
+#include <unix.h>
+#else
+#include <sys/stat.h>
+#endif
+#ifdef xTARGET_CARBON
+#include <Navigation.h>
+int pStrCopy (StringPtr p1, char * p2)
+/* copies a pascal string `p1 into a C string */
+{
+	int len,i;
+	
+	len = (*p1++) %256;
+	for(i=1;i<=len;i++) *p2++=*p1++;
+	*p2 = 0;
+	return 0;
+}
+
+int getprog(char* fn,int argc, char** argvptr)
+{
+   OSErr anErr;
+
+  NavDialogOptions dialogOptions;
+  NavReplyRecord reply;
+  
+  anErr=NavGetDefaultDialogOptions(&  dialogOptions);
+  if( anErr != noErr)  return -1;
+  anErr =NavChooseFile(0,&reply,&dialogOptions,0,0,0,0,0) ;  
+  if (anErr == noErr && reply.validRecord)
+   {
+                //  Deal with multiple file selection
+                long    count;
+                
+                anErr = AECountItems(&(reply.selection), &count);
+                // Set up index for file list
+                if (anErr == noErr)
+                {
+                    long index;
+                    
+                    for (index = 1; index <= count; index++)
+                    {
+                        AEKeyword   theKeyword;
+                        DescType    actualType;
+                        Size        actualSize;
+                        FSSpec      documentFSSpec;
+                        
+                        // Get a pointer to selected file
+                        anErr = AEGetNthPtr(&(reply.selection), index,
+                                            typeFSS, &theKeyword,
+                                            &actualType,&documentFSSpec,
+                                            sizeof(documentFSSpec),
+                                            &actualSize);
+                        if (anErr == noErr)
+                         {  
+                           anErr = HSetVol(0,documentFSSpec.vRefNum,documentFSSpec.parID);
+                           pStrCopy(documentFSSpec.name, fn);
+                         }
+                    }
+                }
+                //  Dispose of NavReplyRecord, resources, descriptors
+                anErr = NavDisposeReply(&reply);
+     
+   }
+	return (2);
+}
+#else
+#include "getprog-unix.hpp"
+#endif
+
+
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+
+
+static  long  cube6[7][3] ={ { 65535,32000,32000},{ 65535, 65535,0},{0, 65535,0},{0, 65535, 65535},{0,0, 65535}
+     , { 65535,0, 65535},{ 32000,0,0} }; 
+static  long grey6[2][3] ={ {65534,65534,65534},{0,0,0} }; 
+
+static bool grey=false;
+static FILE *psfile = 0;
+static FILE *psfile_save = 0;
+static int LastColor=2;  //  pour est en couleur par defaut
+
+const float fMinPixel = -32000;
+const float fMaxPixel = +32000;
+#define reel float 
+ typedef struct XColor { 
+  unsigned short red,green,blue;
+} XColor;
+static XColor *colortable;
+static int ncolortable,fcolor;
+static reel echx,echy,rxmin,rxmax,rymin,rymax;
+static int  lacouleur=0, width, height, currx=0, curry=0;
+#define call(i) i
+static int INITGRAPH=0;
+void myend();
+void myend()
+{
+ if (INITGRAPH)
+   closegraphique();
+  cout << "the end" <<endl;
+//  ExitToShell();
+}
+void myexit(int err) { 
+  cout << " The End err=" << err << endl;
+  exit(err);}
+
+const char * edpfilenamearg=0;	 	
+bool  waitatend=false;
+bool  consoleatend=false;
+
+#ifdef FREEFEM
+#include <fstream.h>
+#include <new.h>
+
+void out_of_memory ();
+void myexit(int );
+void compile(char *fname);
+
+
+int main (int argc, char **argv)
+{
+  atexit(myend);
+  int OPTION = 0;
+  if (argc == 2)
+    {
+       printf ("PROGRAM  FreeFem 1.0 %s \n",argv[1]);
+       initgraphique();
+       compile (argv[1]);
+       closegraphique();
+    }
+  else
+    printf ("To launch freefem you must type freefem  and a file name\n");
+  return 0;
+}
+#else
+void doatexitff();
+void doatexitff()
+{
+#ifdef WIN32
+  bool err=true;
+  if(edpfilenamearg && consoleatend)
+	{
+	cout << " try getConsole " << edpfilenamearg << endl; 
+	string fn = edpfilenamearg;
+	err=GetConsoleBuff(fn);
+        }	
+  if( waitatend &&  err)
+    {
+      char c;  
+      cout << "wait enter ? ";
+      cin.get();
+    }
+#endif
+
+}
+extern int mymain(int argc,char **argv);
+int main (int argc, char **argv)
+{
+  atexit(doatexitff);
+  int ret=mymain(argc,argv);
+  return ret;
+}
+
+
+#endif
+void message(char *s);
+void message(char *s)
+{  printf("%s	\n",s);}
+
+void erreur(char *s)
+{ message(s); exit(0);}
+void *safecalloc(size_t nb, size_t  size);
+void *safecalloc(size_t nb, size_t  size)
+{
+  void* p=NULL;
+  p = calloc(nb, size);
+  if (p == NULL) printf("Run out of Memory!\n");
+  return p;
+}
+void safefree(void** f);
+void safefree(void** f)
+{
+  if(*f){ free((char*) *f); *f=NULL;}
+}
+void rflush();
+void rflush()
+{
+}
+
+
+int LaCouleur() {return  lacouleur;}
+
+void couleur(int c)
+{ 
+  if ( lacouleur == c) // small optim
+    return;
+
+  c= c > LastColor ? 1 : c; // c=Min(c,LastColor); pour noir et blanc
+ lacouleur = c;
+    float r=1,g=1,b=1;
+    if (colortable) {
+      if (c>0 && c < ncolortable)
+	{
+	  r =  (float) colortable[c].red /65535.;
+	  g =  (float) colortable[c].green /65535.;
+	  b =  (float) colortable[c].blue /65535.;
+	}
+    }
+    else if (c!=0)
+      r=g=b=0;
+    if(psfile)
+    fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b);
+  
+}
+
+static XColor DefColorSansG( int k,int nb, bool hsv,bool ggrey,int nbcolors,float *colors)
+{
+ XColor C;
+ float r,g,b;
+extern void DefColor(float & r, float & g, float & b,
+              int k,int nb, bool hsv,bool ggrey,int nbcolors,float *colors);
+ DefColor(r,g,b,   k,nb,hsv,ggrey,nbcolors,colors);
+ C.red= (short unsigned int) (65535*r);
+ C.green=(short unsigned int)(65535*g);
+ C.blue= (short unsigned int) (65535*b);
+ return C;
+} 
+void SetColorTable1(int nb,bool hsv,int nbcolors,float *colors)
+{
+  static bool greyo = !grey;
+  static float *colorso =0;
+  if(!INITGRAPH) return;
+   if (ncolortable == nb && greyo == grey && colorso == colors ) return;// optim
+   greyo = grey;
+   colorso=colors;
+   if (nbcolors && nb>2) 
+     { 
+       if(colortable) delete [] colortable;
+       colortable = new XColor[nb];
+       ncolortable = nb;
+       if(LastColor>1) LastColor=nb-1;
+        for (int i0=0;i0<nb;i0++)
+         {  
+           colortable[i0]=DefColorSansG(i0,nb,hsv,grey,nbcolors,colors);           
+          }
+        
+       }
+     else 
+      ncolortable  =0;
+}
+void SetColorTable(int nb)
+{
+   if (fcolor  && nb>2 && nb < 256) 
+     { 
+       nb = Max(nb,8);
+       if (ncolortable == nb) return;// optim
+       if(colortable) delete [] colortable;
+       colortable = new XColor[nb];
+       ncolortable = nb;
+       if(LastColor>1) LastColor=nb-1;
+      // cout << "SetColorTable "<< nb << endl;
+       int k=0;
+       colortable[k].red= 65535;
+       colortable[k].green= 65535;
+       colortable[k].blue= 65535;
+       k++;
+       colortable[k].red=0;
+       colortable[k].green=0;
+       colortable[k].blue=0;
+       k++;
+       nb = nb -2;
+       for (long i0=0;i0<nb;i0++,k++)
+         {  
+	   //     long  i1 = nb - i0;
+	   long  i6 = i0*6;
+	   long  j0 = i6/nb;// in 0..6
+	   long  j1 = j0+1;// in 1..6
+	   long  k0 = i0 - (nb*j0)/6L;
+	   long  k1 = (nb*j1)/6L-i0;
+	   long  kk = k0+k1;
+	   //	     cout <<k << " " << i0 << " " << j0 << " " << j1 << " " << k0 << " " << k1  << endl;
+           if ( kk <= 0)
+	     { cerr << kk << " " << nb << " " << k0 << " " << k1 << " " << endl;
+	     assert(kk);
+             }
+      /*     colortable[k].red   = (unsigned short) ((long) (cube6[j1][0]*k0+cube6[j0][0]*k1)/kk);
+           colortable[k].green = (unsigned short) ((long)  (cube6[j1][1]*k0+cube6[j0][1]*k1)/kk);
+           colortable[k].blue  = (unsigned short) ((long) (cube6[j1][2]*k0+cube6[j0][2]*k1)/kk);*/
+	   if (! grey)
+         {
+           colortable[k].red   = (unsigned short) ((long) (cube6[j1][0]*k0+cube6[j0][0]*k1)/kk);
+           colortable[k].green = (unsigned short) ((long)  (cube6[j1][1]*k0+cube6[j0][1]*k1)/kk);
+           colortable[k].blue  = (unsigned short) ((long) (cube6[j1][2]*k0+cube6[j0][2]*k1)/kk);
+	   }
+          else 
+           {
+           kk=nb-1;
+           k1 =  i0;
+           k0 = nb - i0 -1;
+           j0=1;
+           j1=0;
+           colortable[k].red   = (unsigned short) ((long) (grey6[j1][0]*k0+grey6[j0][0]*k1)/kk);
+           colortable[k].green = (unsigned short) ((long)  (grey6[j1][1]*k0+grey6[j0][1]*k1)/kk);
+           colortable[k].blue  = (unsigned short) ((long) (grey6[j1][2]*k0+grey6[j0][2]*k1)/kk);
+           }
+           
+           
+           assert(k<ncolortable);
+	   //   cout <<colortable[k].pixel 
+	   //	<< " r=" <<  colortable[k].red 
+	   //	<< " g=" <<  colortable[k].green
+	   //	<< " b=" <<colortable[k].blue <<endl;
+          }
+  }
+
+
+// a faire 
+}
+void FlushEvent()
+{
+} 
+
+void initgraphique()
+{
+  colortable=0;
+  ncolortable=0;
+  LastColor=2;// En couleur par default
+  fcolor=1;  /* des couleurs */
+  SetColorTable(8);
+  INITGRAPH = 1;
+  width = 10000;// change FH mai 2012 to have more precis graphic for F.  Ortegon 
+  height =  7071; // aspect ratio  \sqrt(2)
+}
+
+void closegraphique()
+{
+  if (INITGRAPH)
+    {
+      INITGRAPH = 0;
+      delete [] colortable;
+      closePS();
+    }
+}
+
+void cadre(reel xmin,reel xmax,reel ymin,reel ymax)
+{
+  rxmin = xmin;
+  rxmax = xmax;
+  rymin = ymin;
+  rymax = ymax;
+
+  echx = width / (xmax - xmin);
+  echy = height / (ymax - ymin);
+}
+
+void getcadre(reel &xmin,reel &xmax,reel &ymin,reel &ymax)
+{
+  xmin = rxmin;
+  xmax = rxmax;
+  ymin = rymin;
+  ymax = rymax;
+
+}
+
+
+int InRecScreen(reel x1, reel y1,reel x2, reel y2)
+{  
+
+  return (Max(x1,x2)>= rxmin) && (Min(x1,x2) <= rxmax) && (Max(y1,y2) >= rymin) && (Min(y1,y2)  <= rymax);
+}
+int InPtScreen( reel x, reel y)
+{
+  return (x >= rxmin) && (x <= rxmax) && (y >= rymin) && (y <= rymax);
+}
+
+
+float scali(int i);
+float scalj(int i);
+float scalx(int i);
+float scaly(int i);
+float scali(int i)
+{
+  return i/echx  + rxmin;
+}
+float scalj(int j)
+{
+  return -j/echy  + rymax;
+}
+int scalx(reel x)
+{
+  return (int) Min(fMaxPixel,Max(fMinPixel,((x - rxmin) * echx)));
+} 
+int scaly(reel y)
+{
+  return (int)Min(fMaxPixel,Max(fMinPixel,((rymax - y) * echy)));
+}
+
+void pointe(reel , reel )
+{
+}
+
+void rmoveto(reel x, reel y)
+{
+  currx = scalx(x);
+  curry = scaly(y);
+}
+
+void rlineto(reel x, reel y)
+{
+  int newx = scalx(x), newy = scaly(y);
+  if (psfile)
+    fprintf(psfile,"%d %d %d %d L\n",currx, height-curry, newx, height-newy);
+  currx = newx; curry = newy;
+}
+
+void cadreortho(reel centrex, reel centrey, reel rayon)
+{
+
+  if (height < width)
+  {
+    rymin = centrey - rayon;
+    rymax = centrey + rayon;
+    echx = echy= height / (2 * rayon);
+    rxmin= centrex - width / (2 * echx);
+    rxmax= centrex + width / (2 * echx);
+  }
+  else
+  {
+    rxmin = centrex - rayon;
+    rxmax = centrex + rayon;
+    echx = echy = width / (2 * rayon);
+    rymin = centrey - height / (2 * echy);
+    rymax = centrey + height / (2 * echy);
+  }
+}
+
+void plotstring (const char *  string)
+{ //int l = strlen(string);
+ if(psfile) fprintf(psfile,"(%s) %d %d  S\n",string,currx,height-curry);
+}
+
+void showgraphic()
+{
+}
+void x11draw3(int * ptype);
+
+void x11draw3(int * ptype)
+{
+  int type;
+
+  type=  *ptype;
+
+  if (psfile) 
+    switch (type) {
+    case 0  : {fprintf(psfile,"[] setdash\n");break;}
+    case 1  : {fprintf(psfile,"[3]  setdash\n");break;}
+    default : {fprintf(psfile,"[4 1] setdash\n");break;}
+    }
+
+}  
+
+void penthickness(int pepais)
+{
+  if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais*2);
+}
+
+void x11linsrn(int * ,int * ,int * ,int * );
+void x11linsrn(int * ,int * ,int * ,int * )
+  //int *x1,*x2,*y1,*y2;
+{   
+}
+
+   
+void viderbuff()
+{
+}
+
+
+void cercle(reel , reel , reel );
+void cercle(reel , reel , reel )
+{
+  //int r = (int) (rayon * echx);
+}
+void reffecran()
+{
+}
+
+void fillpoly(int n, float *poly)
+{
+  int i;
+   if (psfile) 
+    {
+     fprintf(psfile,"bF ");
+     for (i=0;i<n;i++)
+      fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1]));
+     fprintf(psfile,"eF\n");
+    }
+
+}
+
+
+int  execute (const char * str)
+{ 
+ cout << "exec: " << str << endl;
+ return  system(str);
+}
+
+char Getijc(int *x1,int *y1);
+char Getijc(int *x1,int *y1)
+{
+  //char char1;
+  *x1=0;
+  *y1=0;
+  //cout << "entre un caractere ? ";
+  //cin >>char1 ;
+  return 0;// char1;
+}
+   
+char Getxyc(float &x,float &y)
+{ 
+  //  cout << " in Getxyc" << endl;
+  char c;
+  int i,j;
+  c = Getijc( &i,&j);
+  x = scali(i);
+  y = scalj(j);
+  //  cout << " out  Getxyc" << x << " " << y << " " << c << endl;
+
+  return c;
+}
+
+/// <<rattente>>
+void rattente(int )
+{
+}
+ void GetScreenSize(int &ix,int &iy)
+{
+  ix = width;
+  iy = height;
+}
+void openPS(const char *filename )
+{ 
+  char ffff[32];
+  int count=0;
+  if(psfile_save) closePS();
+  time_t t_loc;
+  int  widthA4PS=596;
+  //int heightA4PS=842;
+  float s= (double)widthA4PS/width;
+  char  username[10];
+  /*if (!cuserid(username)) */ strcpy(username,"inconnue");
+  time(&t_loc);
+  bool notfound;
+  if( !filename) 
+   do {
+      struct stat buf;
+      sprintf(ffff,"rgraph_%.3d.ps",count++);
+      volatile int r= stat(ffff,&buf) ;
+      notfound = r !=0;
+      if(count>1000) break;
+    } while ( !notfound );
+   
+
+  const char *fps (filename?filename:ffff);
+
+
+  psfile=fopen(fps,"w");
+  if(psfile) {
+    psfile_save=psfile;
+    fprintf(psfile,"%%!PS-Adobe-2.0 EPSF-2.0\n%%%%Creator: %s\n%%%%Title: FreeFem++\n","user");
+    fprintf(psfile,"%%%%CreationDate: %s",ctime(&t_loc));
+    fprintf(psfile,"%%%%Pages: 1\n");
+    fprintf(psfile,"%%%%BoundingBox:       0 0 %d %d\n",int(width*s),int(height*s));
+    fprintf(psfile,"%%%%EndComments\n");
+    fprintf(psfile," /L {newpath moveto lineto stroke} def\n");
+    fprintf(psfile," /C {setrgbcolor} def\n");
+    fprintf(psfile," /rec {newpath 4 copy 8 1 roll moveto 3 -1 roll lineto 4 2 roll exch lineto lineto closepath} def\n");
+    fprintf(psfile," %f %f  scale \n",s,s);
+    fprintf(psfile," 0 %d 0 %d rec clip\n",int(width),int(height));
+    fprintf(psfile," /Helvetica findfont %d scalefont setfont\n",int(9/s));
+    fprintf(psfile," /S {moveto show} def\n");
+    fprintf(psfile," /bF  { mark} def \n");
+    fprintf(psfile," /eF {newpath moveto counttomark 2 idiv {lineto} repeat closepath fill cleartomark} def\n");
+    fprintf(psfile," /P { /yy exch def /xx exch def   xx xx 1 add yy yy 1 add  rec  fill } def\n");
+    fprintf(psfile," 2 setlinewidth\n");
+  }
+  else 
+    cerr << " Err openning postscript file " << fps << endl;
+}
+void closePS(void)
+{
+  if(psfile_save) {
+    fprintf(psfile_save,"showpage\n");
+    fclose(psfile_save);
+  }
+  psfile_save=0;
+  psfile=0;
+}
+ void coutmode(short )  {}
+// bof bof --- 
+ float  GetHeigthFont()
+{ 
+     double  widthA4PS=596;
+    float s=widthA4PS/width; 
+  return 5.5/s/echy;
+}
+  void Commentaire(const char * c)  
+  {
+  if(psfile)   {
+    fprintf(psfile,"%% %s\n",c);
+   }
+  }
+  void NoirEtBlanc(int NB)
+  {
+    if(NB) LastColor=1;
+    else LastColor=ncolortable?ncolortable:2;
+  }
+ 
+  void MettreDansPostScript(int in)
+   {
+     if(in)  psfile=psfile_save;     
+     else   psfile=0;
+   }
+
+static void     FillRect(float x0,float y0, float x1, float y1)
+ {
+     float r[8];
+     r[0]=x0;r[1]=y0;
+     r[2]=x1;r[3]=y0;
+     r[4]=x1;r[5]=y1;
+     r[6]=x0;r[7]=y1;
+     fillpoly(4,r);
+ }
+int PutLevel(int lineno, float xf, int col);
+int PutLevel(int lineno, float xf, int col)
+{
+  float xmin,xmax,ymin,ymax;
+  getcadre(xmin,xmax,ymin,ymax);
+  float xleft = xmax - (xmax-xmin)*0.1;
+  float ytop  = ymax;
+  float ydelta = (ymax-ymin)/40;
+  ydelta=GetHeigthFont();
+  xleft = xmax - 6*ydelta;  
+  ytop -= ydelta*(col+2);
+  couleur(col);
+  FillRect(xleft+ydelta/8.,ytop+ydelta/8.,xleft+ydelta*7./8.,ytop+ydelta*7./8.);
+  rmoveto(xleft+ydelta*1.4,ytop+ydelta/4);
+  char buf[30];
+  sprintf(buf,"%g",xf);
+  couleur(1);
+  plotstring(buf);
+
+   return lineno;
+}
+ void ShowHelp(const char * s,int k)
+{
+  if(k) {
+    MettreDansPostScript(0);
+    couleur(1);
+    float xmin,xmax,ymin,ymax;
+    getcadre(xmin,xmax,ymin,ymax);
+    rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+    plotstring(s);
+    MettreDansPostScript(1);
+       //  couleur(1);	
+  }
+}
+
+  void setgrey(bool gg ){grey=gg;}
+  int getgrey(){ return grey;}
+
+class Grid;
+void SaveMesh(Grid &);
+void SavePlot(int , Grid& , double *);
+void SavePlot(int , Grid& , float *);
+
+void SaveMesh(Grid &){}
+void SavePlot(int , Grid& , double *){}
+void SavePlot(int , Grid& , float *){}
+
diff --git a/src/Graphics/xglrgraf.cpp b/src/Graphics/xglrgraf.cpp
new file mode 100644
index 0000000..eb64a34
--- /dev/null
+++ b/src/Graphics/xglrgraf.cpp
@@ -0,0 +1,30 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#define XGL
+#define FF_GRAPH_SET_PTR
+#include "glrgraph.hpp"
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..4905eaf
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,27 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+
+SUBDIRS=libMesh  bamglib femlib  Graphics Algo lglib fflib 	\
+nw mpi  bamg medit bin-win32 
+
+EXTRA_DIST=FreeFem++-CoCoa Carbon.r  \
+solver/MUMPS_FreeFem.cpp \
+solver/README_COMPILE \
+solver/complex_SuperLU_DIST_FreeFem.cpp \
+solver/complex_pastix_FreeFem.cpp \
+solver/ffsuperludistoption.hpp \
+solver/hips_FreeFem.cpp \
+solver/hypre_FreeFem.cpp \
+solver/makefile \
+solver/makefile-common.inc \
+solver/makefile-sparsesolver.inc \
+solver/parms_FreeFem.cpp \
+solver/real_SuperLU_DIST_FreeFem.cpp \
+solver/real_pastix_FreeFem.cpp \
+solver/wrapper_dotblas.c \
+solver/wrapper_dotblas.f \
+solver/wrapper_dotblas1.c \
+solver/wrapper_dotblas1.f 
+
+
diff --git a/src/bamg/Makefile.am b/src/bamg/Makefile.am
new file mode 100644
index 0000000..a834730
--- /dev/null
+++ b/src/bamg/Makefile.am
@@ -0,0 +1,22 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+CXXLD=$(STATICTOOL) $(CXX)
+
+bin_PROGRAMS=$(BAMGPROG)
+EXTRA_PROGRAMS=bamg  cvmsh2 #drawbdmesh
+bamg_SOURCES=bamg.cpp global.cpp
+bamg_DEPENDENCIES=../fflib/Mesh2.o ../fflib/MeshDraw.o ../fflib/MeshGeom.o ../fflib/MeshQuad.o ../fflib/MeshRead.o ../fflib/MeshWrite.o  ../fflib/Meshio.o ../fflib/Metric.o ../fflib/QuadTree.o ../fflib/R2.o ../fflib/SetOfE4.o ../fflib/write_hdf5.o	../fflib/write_xdmf.o
+
+cvmsh2_SOURCES=cvmsh2.cpp global.cpp
+cvmsh2_DEPENDENCIES=../fflib/Mesh2.o ../fflib/MeshDraw.o ../fflib/MeshGeom.o ../fflib/MeshQuad.o ../fflib/MeshRead.o ../fflib/MeshWrite.o  ../fflib/Meshio.o ../fflib/Metric.o ../fflib/QuadTree.o ../fflib/R2.o ../fflib/SetOfE4.o ../fflib/write_hdf5.o	../fflib/write_xdmf.o
+
+#EXTRA_drawbdmesh_SOURCES= # ../Graphics/Xrgraph.cpp ../Graphics/Pcrgraph.cpp 
+#drawbdmesh_DEPENDENCIES=../fflib/libff.a  @STD_GRAPH_OBJ@
+#drawbdmesh_SOURCES= drawbdmesh.cpp 
+#drawbdmesh_LDADD = @STD_GRAPH_OBJ@ $(LDADD)  @STD_LIBS@ @LIBSNOCONSOLE@
+
+LDADD= ../fflib/Mesh2.o ../fflib/MeshDraw.o ../fflib/MeshGeom.o ../fflib/MeshQuad.o ../fflib/MeshRead.o ../fflib/MeshWrite.o  ../fflib/Meshio.o ../fflib/Metric.o ../fflib/QuadTree.o ../fflib/R2.o ../fflib/SetOfE4.o ../fflib/write_hdf5.o	../fflib/write_xdmf.o
+AM_CPPFLAGS=-I$(srcdir)/../fflib -I$(srcdir)/../bamglib -I$(srcdir)/../Graphics $(HDF5_CPPFLAGS)
+
+
diff --git a/src/bamg/bamg.cpp b/src/bamg/bamg.cpp
new file mode 100644
index 0000000..0ee8826
--- /dev/null
+++ b/src/bamg/bamg.cpp
@@ -0,0 +1,835 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+//
+// SUMMARY:  Bamg: Bidimensional Anisotrope Mesh Generator
+// RELEASE: 0 
+//
+// AUTHOR:   F. Hecht,    
+// ORG    :  UMPC
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+// ORIG-DATE:     Dec 97
+// Modif          March 98
+/*
+ 
+ This file is part of Bamg or FreeFEm++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+// ORIG-DATE:     Dec 97
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+#include <new>
+#include <cassert>
+#include "Meshio.h"
+#include <iomanip>
+#include "Mesh2.h"
+#include "QuadTree.h"
+using namespace bamg;
+using namespace std;
+#include <fstream>
+#ifdef __MWERKS__
+#define   NBVMAX 10000
+#else
+#define   NBVMAX 50000   
+#endif 
+//                       0         1         2         3
+//                       0123456789012345678901234567890
+const char whatbamg []= "@(#)LJLL, le 20 fevr 2006,  Bamg v1.02  ";
+const char *bamgversion = whatbamg + 28;
+int initgraph=0;
+//long verbosity=2;
+
+#ifdef __MWERKS__
+#define R_OK 0
+#define F_OK 0
+#define W_OK 0
+#include <unix.h>
+inline int access( char *fileName, int notUsed )
+{
+	struct stat		statRec;
+	return  stat( fileName, &statRec );
+}
+#endif
+#ifdef _MSC_VER
+#define R_OK 04
+#define F_OK 0
+#define W_OK 02
+#include <io.h>
+inline int access( char *fileName, int mode)
+{
+  return  _access( fileName, mode );
+}
+#endif
+
+void NewHandler();
+void NewHandler()
+{ cerr << " Not enought memory " << endl;
+  exit(1);
+}
+void forDebug();
+
+
+void  MeshErrorIO(ios& )
+{
+  MeshError(999);
+  exit(1);
+}
+
+#ifdef DRAWING 
+bool withrgraphique= initgraphique; 
+#else
+bool withrgraphique=false; 
+#endif
+
+void forDebug()
+{ 
+#ifdef DRAWING 
+if(initgraph) {
+  if (CurrentTh)     CurrentTh->inquire();
+  closegraphique();initgraph=0; }
+#endif
+}
+
+int main(int argc, char **argv)
+{  
+#ifdef __MWERKS__
+  cout << " version " << bamgversion << " for initialisation of the toolbox " << endl;
+#endif 
+  // JUST for HP CC bug 
+#ifdef LONGLONG
+  long long bidon=2;
+  if( (double) bidon != 2.0) {
+    cerr << "Compiler bug  Pb of cast of long long to a double => remove the LONGLONG define" << endl;
+    exit(10); }
+#endif
+  double time0, time1,time2,time3,time4;
+  //   2 way for uses ---
+  //   1 first mesh 
+  //   or adaptation 
+  MeshIstreamErrorHandler = MeshErrorIO;
+  //  double *sol=0;
+  //  int adaptation = 0 ;
+  Int4 i;
+  hinterpole=1; // by def interpolation a h 
+  //  int Err=0;
+  int fileout=0;
+  int nbvx = NBVMAX;
+  int iso =0,AbsError=0,nbjacoby=1,allquad=0;
+  int NoMeshReconstruction=0;
+  int Rescaling = 1;
+  double costheta=2;
+  Real8 cutoffradian=-1;
+  double anisomax = 1e6;
+  double err=0.01,errg=0.1,coef=1,hmin=1.e-100,hmax=1.e17,raison=0,CutOff=1e-5;
+  int KeepBackVertices=1;
+ double hminaniso=1e-100; 
+  const double  boundmaxsubdiv = 10;
+  double  maxsubdiv=boundmaxsubdiv;
+  double omega=1.8;
+  int NbSmooth=3;
+  double *solMbb =0,*solMBB=0;
+  int  *typesolsBB =0;
+  Int4 nbsolbb=0,lsolbb=0;
+  Int4 nbsolBB=0,lsolBB=0;
+  int SplitEdgeWith2Boundary=0;
+  int rbbeqMbb=0,rBBeqMBB=0;
+  int ChoiseHessien = 0;
+  double power=1;
+  Triangles *Thr=0,*Thb=0;
+
+  char * fgeom=0,*fmeshback=0,*fmeshout=0,*fmeshr=0,*fmetrix=0,*famfmt=0,*fmsh=0,
+    *fnopo=0,*fftq=0,*fam=0,*famdba=0,*rbb=0,*rBB=0,*wbb=0,*wBB=0,
+    *fMbb=0,*foM=0,*fMBB=0;
+  verbosity =2;
+  char *datargv[128] ;
+  int datargc=1;
+  datargv[0]= datargv[1]=0;// for create a error if no parameter 
+  const char * datafile = argc ==2 ? argv[1] : "DATA_bamg";
+  
+  atexit( forDebug);
+  set_new_handler( &NewHandler);
+
+  if (argc<3)  
+    { // for test on the mac
+      if (!access(datafile,R_OK))
+	{
+	  MeshIstream data(datafile);
+	  while(data.cm() && datargc <128)
+	    datargv[datargc++]=data.ReadStr();
+	  
+      if (argc==1)
+	datargv[0]=argv[0]; // copy of the program name 
+      argc=datargc;
+      argv=datargv;
+	}
+    };
+
+  for (i=1;i<argc;i++)
+    if (!strcmp(argv[i],"-v")  && ++i<argc)
+      verbosity = atoi(argv[i]);
+    else if (!strcmp(argv[i],"-NoRescaling") ) 
+       Rescaling = 0;
+    else if (!strcmp(argv[i],"-Rescaling") ) 
+       Rescaling = 1;
+    else if (!strcmp(argv[i],"-H")  && ++i<argc) 
+       ChoiseHessien = atoi(argv[i]);
+    else if (!strcmp(argv[i],"-power")  && ++i<argc) 
+       power = atof(argv[i]);
+    else if (!strcmp(argv[i],"-nbv")   && ++i<argc)
+      nbvx = atoi(argv[i]);
+    else if (!strcmp(argv[i],"-nbs")   && ++i<argc)
+       nbvx = atoi(argv[i]);
+    else if (!strcmp(argv[i],"-g")   && ++i<argc)
+      fgeom = argv[i];
+    else if ((!strcmp(argv[i],"-thetaquad") || (!strcmp(argv[i],"-ThetaQuad"))) && ++i<argc)
+      costheta  = 1-Abs(cos(Pi*atof(argv[i])/180.0));
+    else if (!strcmp(argv[i],"-b")  && ++i<argc)
+      fmeshback = argv[i];
+    else if (!strcmp(argv[i],"-r")  && ++i<argc)
+      fmeshr = argv[i];
+    else if (!strcmp(argv[i],"-M")  && ++i<argc) 
+      fmetrix = argv[i];
+    else if (!strcmp(argv[i],"-rbb") && ++i<argc) 
+      rbb = argv[i];
+    else if (!strcmp(argv[i],"-rBB") && ++i<argc) 
+      rBB = argv[i];
+    else if (!strcmp(argv[i],"-Mbb") && ++i<argc) 
+      fMbb = argv[i];
+    else if (!strcmp(argv[i],"-MBB") && ++i<argc) 
+      fMBB = argv[i];
+    else if (!strcmp(argv[i],"-wBB") && ++i<argc) 
+      wBB = argv[i];
+    else if (!strcmp(argv[i],"-wbb") && ++i<argc) 
+      wbb = argv[i];
+     else if (!strcmp(argv[i],"-o")  && ++i<argc) 
+       fmeshout= argv[i];
+    else if (!strcmp(argv[i],"-intm")  && i<argc)
+      hinterpole=0; 
+    else if (!strcmp(argv[i],"-oam_fmt") && ++i<argc)
+      famfmt = argv[i];
+    else if (!strcmp(argv[i],"-oam") && ++i<argc)
+      fam= argv[i];
+    else if (!strcmp(argv[i],"-omsh") && ++i<argc)
+      fmsh = argv[i];
+    else if (!strcmp(argv[i],"-oftq") && ++i<argc)
+      fftq = argv[i];
+    else if (!strcmp(argv[i],"-onopo") && ++i<argc)
+      fnopo = argv[i];
+    else if (!strcmp(argv[i],"-oamdba") && ++i<argc)
+      famdba= argv[i];
+    else if (!strcmp(argv[i],"-oM") && ++i<argc)
+      foM = argv[i];
+    else if (!strcmp(argv[i],"-coef")  && ++i<argc) 
+      coef = atof(argv[i]);
+    else if (!strcmp(argv[i],"-err")  && ++i<argc) 
+      err = atof(argv[i]);
+    else if (!strcmp(argv[i],"-errg")  && ++i<argc) 
+      errg = atof(argv[i]);
+    else if (!strcmp(argv[i],"-raison")  && ++i<argc) 
+      raison = atof(argv[i]);
+    else if (!strcmp(argv[i],"-ratio")  && ++i<argc) 
+      raison = atof(argv[i]);
+    else if (!strcmp(argv[i],"-hmin")  && ++i<argc) 
+      hmin= atof(argv[i]);
+     else if (!strcmp(argv[i],"-hminaniso")  && ++i<argc) 
+      hminaniso= atof(argv[i]);
+   else if (!strcmp(argv[i],"-hmax")  && ++i<argc) 
+       hmax = atof(argv[i]);
+    else if (!strcmp(argv[i],"-thetamax")  && ++i<argc) 
+      cutoffradian = atof(argv[i])*Pi/180.0;
+    else if (!strcmp(argv[i],"-anisomax")  && ++i<argc) 
+       anisomax =  atof(argv[i]);
+    else if (!strcmp(argv[i],"-maxsubdiv")  && ++i<argc) 
+       maxsubdiv = atof(argv[i]);
+    else if (!strcmp(argv[i],"-iso"))
+      iso = 1;
+    else if (!strcmp(argv[i],"-KeepBackVertices"))
+      KeepBackVertices = 1;
+    else if (!strcmp(argv[i],"-noKeepBackVertices"))
+      KeepBackVertices = 0;
+    else if (!strcmp(argv[i],"-KeepBackVertices"))
+	KeepBackVertices = 1;
+    else if (!strcmp(argv[i],"-noKeepBackVertices"))
+	KeepBackVertices = 0;
+    else if (!strcmp(argv[i],"-2q") || !strcmp(argv[i],"-2Q"))
+      allquad=1;
+    else if (!strcmp(argv[i],"-2") )
+      allquad=2;
+    else if (!strcmp(argv[i],"-aniso"))
+      iso = 0;
+    else if (!strcmp(argv[i],"-RelError"))
+      AbsError = 0;
+    else if (!strcmp(argv[i],"-AbsError"))
+      AbsError = 1;
+    else if (!strcmp(argv[i],"-splitpbedge") ) 
+      SplitEdgeWith2Boundary=1;
+    else if (!strcmp(argv[i],"-nosplitpbedge") ) 
+      SplitEdgeWith2Boundary=0;
+    else if (!strcmp(argv[i],"-NbJacobi")  && ++i<argc) 
+      nbjacoby = atoi(argv[i]);
+    else if (!strcmp(argv[i],"-CutOff")  && ++i<argc) 
+      CutOff =  atof(argv[i]), AbsError = 0;
+    else if (!strcmp(argv[i],"-NbSmooth")  && ++i<argc) 
+      NbSmooth = atoi(argv[i]);
+    else if (!strcmp(argv[i],"-omega")  && ++i<argc) 
+      omega =  atof(argv[i]);
+    else 
+      { 
+	cout << " Error in the arguments " << i << "  of " << bamgversion <<endl;
+	cout << "      argument [" << i << "]= `" << ((i< argc ) ?  argv[i] : " The Lastest ") 
+	     <<"`" << endl;
+	cout << " Usage :" << endl;
+	cout << "  Mesh INPUT: The 2 arguments are exclusives." << endl;
+	cout << "" << endl;
+	cout << "     -g  filename    Set the geometry for mesh generation. " << endl;
+	cout << "                     DB mesh file." << endl;
+	cout << "     -b  filename    Set the background mesh for mesh adaption " << endl;
+	cout << "                     (require {\tt -M} or {-Mbb} arguments). " << endl;
+	cout << "                     - am_fmt file if filename match  *.am_fmt " << endl;
+	cout << "                     - ambda file if filename match  *.amdba " << endl;
+	cout << "                     - nopo file if filename match  *.nopo " << endl;
+	cout << "                     - am file if filename match  *.am " << endl;
+	cout << "                     - ftq file if filename match  *.ftq " << endl;
+	cout << "                     - msh file if filename match  *.msh " << endl;
+	cout << "                     - otherwise the file is a BD mesh file " << endl;
+	cout << "                     Remark: the geometry is the background geometry." << endl;
+	cout << "                     DB mesh file." << endl;
+	cout << "     -r  filename    Set the  mesh for modification mesh  " << endl;
+	cout << "                     no reconstruction " << endl;
+	cout << "                     same as in the case of -b argument" << endl;
+	cout << "" << endl;
+	cout << "     -thetamax (double)   change the angular limit for a corner in degre " << endl;
+	cout << "                       the angle is defined from 2 normals of 2 concecutives edges " << endl;
+	cout << "                       if no geomtry cf reading an  am_fmt, amdba, nopo .. file " << endl;
+
+
+	cout << "" << endl;
+	cout << "  METRIC definition or mesh size definition, one of the" << endl;
+	cout << "  2 next arguments is need in case of  mesh adaption." << endl;
+	cout << "" << endl;
+	cout << "     -M filename     Set  the metric which is  defined on the background mesh " << endl;
+	cout << "                     or on the geometry. Metric file." << endl;
+	cout << "     -Mbb filename   Set the solution  defined on the background mesh for" << endl;
+	cout << "                     metric construction, the solutions was FE P1 defined on " << endl;
+	cout << "                     the background mesh. bb file. " << endl;
+	cout << "     -MBB filename   same with -Mbb but with BB file " << endl;
+	cout << "" << endl;
+	cout << "     -errg (double)  Set the level of error on geometry (0.1) by default" << endl;
+	cout << "     -coef (double)  Set the value of mutiplicative " << endl;
+        cout << "                     coef on the mesh size (1 by default)." << endl;
+	cout << "     -power (double) Set the power parameter of hessien to construct " << endl;
+	cout << "                     the metric  (1 by default)" << endl;
+	cout << "     -maxsubdiv  (double) Change the metric  such that  the maximal subdivision  " << endl;
+	cout << "                     of a background's edge is bound by the " <<endl;
+	cout << "                     given number (always limited by 10) " << endl;
+	cout << "     -ratio (double) Set the ratio for a smoothing of the metric." << endl;
+	cout << "                     If ratio is  0 then no smoothing" << endl;
+	cout << "	              and if ratio  is in  [1.1,10] then the smoothing " << endl;
+	cout << "                     change the metrix such that the greatest geometrical" << endl;
+	cout << "                     progression (speed of mesh size variation) " << endl;
+	cout << "                     in a mesh is bounded  by ratio (by default no smoothing)." << endl;
+	cout << "     -hmin (double)  Set the value of the minimal edge size." << endl;
+	cout << "     -hminaniso (double)  Set the value of the minimal edge size and save aniso." << endl;
+	cout << "     -hmax (double)  Set the value of the maximal edge size." << endl;
+	cout << "     -NbSmooth (int) Number of Smoothing iteration " << endl;
+	cout << "                     (3 by default if the metric is set otherwise 0)." << endl;
+	cout << "     -omega (double)  relaxation parameter for Smoothing " << endl;
+	cout << "     -splitpbedge     split in 2 all internal edges with 2 vertex on boundary" << endl;
+	cout << "     -nosplitpbedge   d'ont cut internal edges with 2 vertex on boundary (default)" << endl;
+	cout << "" << endl;
+	cout << "" << endl;
+	cout << "        the next arguments are used with the -Mbb argument" << endl;
+	cout << "" << endl;
+	cout << "     -KeepBackVertices  Try to Keep old vertices (default) " << endl;
+	cout << "     -noKeepBackVertices  all vertices are create from scratch  " << endl;
+	cout << "     -err   (double)    Set the level of error (default 0.01)"    << endl;
+	cout << "     -iso               The constructed metric must be isotropic" << endl;
+	cout << "     -aniso             The constructed metric can be anisotropic " << endl;
+	cout << "     -anisomax (double) Set  maximum ratio  of anisotropy " << endl;
+	cout << "                            1 =>  isotropic (1e6 by default) " << endl;
+	cout << "     -RelError          Construct metric with relative  error " << endl;
+	cout << "     -AbsError          Construct metric with with abs error " << endl;
+	cout << "     -CutOff (double)   Set the limit of the relative error  (1.e-5)" << endl;
+	cout << "     -NbJacobi (int)    Set the number of Jacobi iteration for smoothing " << endl;
+	cout << "                        the construction of metric  (1 by default)." << endl;
+	cout << "     -NoRescaling       Don't rescaling of all solution between [0..1] " 
+	     << "before metric computation " << endl; 
+	cout << "     -Rescaling       Do rescaling of all solution between [0..1] " 
+	     << "before metric computation ((default case)" << endl; 
+	cout << "     -H (int)           choices for computing the hessein (test)" << endl;
+	cout << "" << endl;
+	cout << "" << endl;
+	cout << "  Definition of some internal variable and limitation." << endl;
+	cout << "" << endl;
+	cout << "     -v   (int)       Set the level of impression (verbosity) " << endl;
+	cout << "                      between 0 and 10 (1 by default)." << endl;
+	cout << "     -nbv (int)       Set the maximal of  vertices (" << nbvx  << " by default)." << endl;
+	cout << "" << endl;
+	cout << "" << endl;
+	cout << "  To interpoled a solution form background mesh to generated " << endl;
+	cout << "  mesh (in case of adpatation)" << endl;
+	cout << "" << endl;
+	cout << "    -rbb filename    Read  solution  file defined on the background " << endl;
+	cout << "                      mesh for interpolation on created mesh." << endl;
+	cout << "                      bb file. (by default the  -Mbb filename)" << endl;
+	cout << "     -wbb filename    Write the file of interpolation of the solutions" << endl;
+	cout << "                      read with  -rbb argument. " << endl;
+	cout << "                      bb file." << endl;
+	cout << "     -rBB filename    same -rbb but with BB file ";
+	cout << "     -wBB filename    same -wbb but with BB file ";
+	cout << "" << endl;
+	cout << "  Output mesh file for adpation or generation." << endl;
+	cout << "    Remark: one of output mesh file is require " << endl;
+	cout << endl;
+	cout << "     -o       filename Create a DB Mesh file." << endl;
+	cout << "     -oamdba  filename Create a amdba file." << endl;
+	cout << "     -oftq    filename Create a ftq file." << endl;
+	cout << "     -omsh    filename Create a msh file (freefem3 file)." << endl;
+	cout << "     -oam_fmt filename Create a am_fmt file. " << endl;
+	cout << "     -oam     filename Create a am file. " << endl;
+	cout << "     -onopo   filename Create a nopo file. " << endl;
+	cout << "     -oM filename      Create a metric file. " << endl;
+
+	cout << endl;
+	cout << endl;
+	cout << "     -thetaquad (double)  minimal angle of a quadrangle " << endl;
+	cout << "     -2q                  split triangles in 3 quad and quad in 4 quad  " << endl;
+	cout << "     -2                   split triangles in 4 trai and quad in 4 quad  " << endl;
+
+	cout << endl;
+      
+	cout << " Remark: if no argument is given when the arguments are read in "<<datafile
+	     << " file" << endl;
+	exit(3);
+      }
+  // some verification
+  NoMeshReconstruction= fmeshr !=0;
+  if (!fmeshback) fmeshback=fmeshr;
+  fileout = fmeshout || fam || fnopo || fftq || fam || famdba ||famfmt || wbb || wBB  ;
+  if (!fileout && !foM )
+    {
+      cerr << " No Output file a given " << endl;
+      MeshError(1);
+    }
+  if ( maxsubdiv > boundmaxsubdiv || maxsubdiv <= 1.0)
+    {
+      cerr << " -maxsubdiv " << maxsubdiv << " is not in ]1,"<< boundmaxsubdiv << "]" << endl;
+      exit(3);
+    }
+  if (iso) 
+    anisomax=1;
+  if (!(fmetrix||fMbb))
+    NbSmooth=0; // no metric -> no smoothing 
+  if( ! rbb) // to set the rbb filename by default 
+    rbb=fMbb;
+  if( ! rBB) // to set the rbb filename by default 
+    rBB=fMBB;
+
+  if (fMbb && rbb) 
+    rbbeqMbb = !strcmp(rbb,fMbb);
+  if (fMBB && rBB) 
+    rBBeqMBB = !strcmp(rBB,fMBB);
+
+#ifdef DRAWING 
+  if(initgraphique)
+    {
+      initgraphique();
+      initgraph=1;
+      withrgraphique=0; 
+    }
+#endif
+  
+     if (verbosity) 
+       cout << bamgversion <<" : ";
+     if (verbosity)
+       if (fgeom && fileout)
+	 cout << " Construction of a mesh from the geometry : " << fgeom << endl
+	      << "     with less than " << nbvx << " vertices " << endl;
+       else if(fmeshback && fileout)
+	 if (NoMeshReconstruction)
+	   cout <<  " Modification of a adpated mesh " 
+		<< fmeshback 
+		<< "    with less than " << nbvx << " vertices" << endl;
+	 else
+	   cout <<  " Construction of a adpated mesh from the background mesh: " 
+		<< fmeshback 
+		<< "    with less than " << nbvx << " vertices" <<  endl;
+       else if (fmeshback && foM)
+	 cout << " Construction of the metric file on the background mesh: " 
+	      << fmeshback << endl;
+       
+
+     if (fgeom && fileout)
+       {
+	 if (verbosity) 
+	   cout << " Construction of a mesh from the geometry : " << fgeom << endl
+		<< "     with less than " << nbvx << " vertices " << endl;
+
+	 time0 = CPUtime();
+	 Geometry Gh(fgeom);
+	 hmin = Max(hmin,Gh.MinimalHmin());
+	 hmax = Min(hmax,Gh.MaximalHmax());
+	 if(fmetrix) 
+	   Gh.ReadMetric(fmetrix,hmin,hmax,coef);
+	 else
+	   {
+	     Int4 iv;
+	     for(iv=0;iv<Gh.nbv;iv++)
+	       {
+		 MetricAnIso M=Gh[iv];
+		 MatVVP2x2 Vp(M/coef);
+		 Vp.Maxh(hmin);
+		 Vp.Minh(hmax);
+		 Gh.vertices[iv].m = Vp;
+	       }
+	   }
+	 
+	 time1 = CPUtime();
+	 if(verbosity>3)
+	   cout << " Cpu for read the geometry " << time1-time0 << "s" << endl;
+	 Triangles Th(nbvx,Gh);
+	 if(costheta<=1)
+	   Th.MakeQuadrangles(costheta);
+	 if (allquad)
+	      Th.SplitElement(allquad==2);
+	   
+	 if(SplitEdgeWith2Boundary)
+	   Th.SplitInternalEdgeWithBorderVertices();
+	 Th.ReNumberingTheTriangleBySubDomain();
+	 time2 = CPUtime();
+	 if(verbosity>3) Th.ShowHistogram();
+	  if(NbSmooth>0) Th.SmoothingVertex(NbSmooth,omega);
+	  if(verbosity>3 && NbSmooth>0) Th.ShowHistogram();
+#ifdef DRAWING
+	  if(initgraph)
+	    {
+	      Th.InitDraw();
+	      Th.Draw();
+	      Th.inquire();
+	    }
+#endif
+	 time3 = CPUtime();
+	 if(verbosity> 1)
+	   cout << " Cpu for meshing         :" << setw(8) << time2-time1 
+		<< "s, for  Smoothing " <<  time3-time2 
+		<< "s  Nb Vertices/s = " <<  (Th.nbv) /(time2-time1)
+		<< setw(0) <<endl ;
+	 if (fmeshout) Th.Write(fmeshout  ,Triangles::BDMesh);
+	 if (famfmt)   Th.Write(famfmt    ,Triangles::am_fmtMesh);
+	 if (fam)      Th.Write(fam       ,Triangles::amMesh);
+	 if (famdba)   Th.Write(famdba    ,Triangles::amdbaMesh);
+	 if (fftq)     Th.Write(fftq      ,Triangles::ftqMesh);
+	 if (fmsh)     Th.Write(fmsh      ,Triangles::mshMesh);
+	 if (fnopo)    Th.Write(fnopo     ,Triangles::NOPOMesh);
+#ifdef DRAWING 
+	  if(initgraph)
+	    {
+	      
+	      reffecran();
+	      Th.InitDraw();
+	      Th.Draw();
+	      Th.inquire();
+	    }
+#endif
+
+	 time3 = CPUtime();
+	 if(verbosity>0) 
+	       {
+		 cout << " Cpu for meshing with io :" << setw(8) <<time3-time0 
+		      << "s  Nb Vertices/s = " <<  (Th.nbv) /(time3-time0)	 << setw(0)<< endl;
+		 cout << " Nb vertices = " << Th.nbv;
+	       if (Th.nbt-Th.NbOutT-Th.NbOfQuad*2) 
+		 cout  << " Nb Triangles = " << (Th.nbt-Th.NbOutT-Th.NbOfQuad*2);
+	       if (Th.NbOfQuad ) 
+		 cout  << " Nb Quadrilaterals = " << Th.NbOfQuad  ;
+	       cout   << endl;
+	       }	   
+
+       }
+     else if (fmeshback && (fmetrix||fMbb||fMBB||NoMeshReconstruction) && 
+	      (fileout || foM  || ( rbb && wbb)  ||( rBB && wBB) ) ) 
+       {
+	 // to be sure the value was not stupide
+	 
+	 time0 = CPUtime();
+	 Triangles BTh(fmeshback,cutoffradian); // read the background mesh 
+	 hmin = Max(hmin,BTh.MinimalHmin());
+	 hmax = Min(hmax,BTh.MaximalHmax());
+
+	 BTh.MakeQuadTree();
+	 time1 = CPUtime();
+	 if (fmetrix) 
+	   BTh.ReadMetric(fmetrix,hmin,hmax,coef);
+	 else
+	   { // init with hmax 
+	     Metric Mhmax(hmax);
+	     for (Int4 iv=0;iv<BTh.nbv;iv++)
+		 BTh[iv].m = Mhmax;
+	   }
+	 if (fMbb)
+	   {
+	     solMbb = ReadbbFile(fMbb,nbsolbb,lsolbb,2,2);
+	     if (lsolbb != BTh.nbv) 
+	       {
+	         cerr << "fatal error  nbsol " << nbsolbb << " " << lsolbb<< " =! " << BTh.nbv << endl;
+		 cerr << "  size of sol incorrect " << endl;
+		 MeshError(99);
+	       }
+	     assert(lsolbb==BTh.nbv);
+	     BTh.IntersectConsMetric(solMbb,nbsolbb,0,hmin,hmax,sqrt(err)*coef,1e30,AbsError?0.0:CutOff,
+				     nbjacoby,Rescaling,power,ChoiseHessien);
+	    if(!rbbeqMbb)
+	      delete [] solMbb,solMbb =0;
+
+	   }
+	 if (fMBB)
+	   {
+	     solMBB = ReadBBFile(fMBB,nbsolBB,lsolBB,typesolsBB,2,2);
+	     if (lsolBB != BTh.nbv) 
+	       {
+	         cerr << "fatal error  nbsol " << nbsolBB << " " << lsolBB << " =! " << BTh.nbv << endl;
+		 cerr << "  size of sol incorrect " << endl;
+		 MeshError(99);
+	       }
+	     assert(lsolBB==BTh.nbv);
+	     BTh.IntersectConsMetric(solMBB,nbsolBB,0,hmin,hmax,sqrt(err)*coef,1e30,AbsError?0.0:CutOff,
+				     nbjacoby,Rescaling,ChoiseHessien);
+	    if(!rBBeqMBB)
+	      delete [] solMBB,solMBB =0;
+
+	   }
+	 
+	 BTh.IntersectGeomMetric(errg,iso);
+	 if(raison) 
+	   BTh.SmoothMetric(raison);
+	 BTh.MaxSubDivision(maxsubdiv);
+	 //
+	 if (iso) 
+	   anisomax=1;
+	 BTh.BoundAnisotropy(anisomax,hminaniso);
+	 time2 = CPUtime();
+	 if(foM)
+	   {
+	     if(verbosity >2)
+	       cout << " -- write Metric  file " << foM <<endl;
+		 
+	     ofstream f(foM);
+	     if(f) BTh.WriteMetric(f,iso);
+	   }
+
+	 if ( fileout) 
+	   {
+	     if ( NoMeshReconstruction)
+               if (( fmeshback == fmeshr) || (!strcmp(fmeshback,fmeshr)))
+		 Thr=&BTh,Thb=0; // back and r mesh are the same 
+	       else
+                 Thr= new Triangles(fmeshr,cutoffradian),Thb=&BTh; // read the new 
+
+		
+	     
+	     Triangles & Th( *(NoMeshReconstruction 
+			     ?  new Triangles(*Thr,&Thr->Gh,Thb,nbvx) // copy the mesh + free space to modification  
+			     :  new Triangles(nbvx,BTh,KeepBackVertices)     // construct a new mesh 
+			     ));
+             if (Thr != &BTh) delete Thr;
+             
+	     if(costheta<=1.0)
+	       Th.MakeQuadrangles(costheta);
+	     if (allquad)
+	       Th.SplitElement(allquad==2);
+	     if(SplitEdgeWith2Boundary)
+	       Th.SplitInternalEdgeWithBorderVertices();
+	     Th.ReNumberingTheTriangleBySubDomain();
+	     time3 = CPUtime();
+	     
+	     if(verbosity>0) 
+	       cout << " Cpu time for meshing          : " << time3-time2 
+		    << "s  Nb Vertices/s = " <<  (Th.nbv) /(time3-time2)
+		    << endl;
+	     if(verbosity>3) Th.ShowHistogram();
+	     if(NbSmooth>0) Th.SmoothingVertex(NbSmooth,omega);
+	     if(verbosity>3 && NbSmooth>0) Th.ShowHistogram();
+#ifdef DRAWING
+	  if(initgraph)
+	    {
+	      Th.InitDraw();
+	      Th.Draw();
+	      Th.inquire();
+	    }
+#endif
+	 Th.BTh.ReMakeTriangleContainingTheVertex();
+
+	 if (fmeshout) Th.Write(fmeshout  ,Triangles::BDMesh);
+	 if (famfmt)   Th.Write(famfmt    ,Triangles::am_fmtMesh);
+	 if (fam)      Th.Write(fam       ,Triangles::amMesh);
+	 if (famdba)   Th.Write(famdba    ,Triangles::amdbaMesh);
+	 if (fftq)     Th.Write(fftq      ,Triangles::ftqMesh);
+	 if (fmsh)     Th.Write(fmsh      ,Triangles::mshMesh);
+	 if (fnopo)    Th.Write(fnopo     ,Triangles::NOPOMesh);
+	 
+	     if ( ( rbb && wbb)  ||( rBB && wBB))  // the code for interpolation 
+	       {
+		 if(verbosity >1)
+		   {
+		     if (rbb ) 
+		       cout << " -- interpolation P1  files : " << rbb << " -> " << wbb <<endl;
+		     if (rBB ) 
+		       cout << " -- interpolation P1  files : " << rBB<< " -> " << wBB <<endl;
+		   }
+		 double time00  = CPUtime();	   
+		 const int dim=2;
+		 // optimisation read only si rbb != fMbb
+		
+		 double *solbb=0;
+		 double *solBB=0;
+
+		 if (rbb) 
+		   solbb =  rbbeqMbb? solMbb : ReadbbFile(rbb,nbsolbb,lsolbb,2,2);
+		 if (rBB) 
+		   solBB =  rBBeqMBB? solMBB : ReadBBFile(rBB,nbsolBB,lsolBB,typesolsBB,2,2);
+
+		 // cout << " " << rbbeqMbb << " " <<  sol << " " << nbsol << " " << lsol << endl; 
+		 if (!solBB && !solbb ) 
+		   {
+		     cerr << " Fatal Error "  << "solBB =  " <<  solBB << " solbb= " << solbb << endl;
+		     exit(2);}
+		 
+		 ofstream *fbb = wbb ? new ofstream(wbb) :0;
+		 ofstream *fBB = wBB ? new ofstream(wBB) :0;
+		 Int4   nbfieldBB = 0, nbfieldbb = nbsolbb;
+		 if (fbb)
+		   *fbb  << dim << " " << nbsolbb << " " << Th.nbv <<" " << 2 << endl; 
+		 if (fBB)
+		   {
+		     int i;
+		     *fBB  << dim << " " << nbsolBB ;
+		     for ( i=0;i<nbsolBB;i++)
+		       *fBB << " " << (typesolsBB ?typesolsBB[i]+1:1) ;
+		     *fBB << " " << Th.nbv <<" " << 2 << endl; 
+		     assert(dim==2);
+		     for ( i=0;i<nbsolBB;i++)
+		     nbfieldBB += typesolsBB ? typesolsBB[i]+1 : 1;
+		     // this code is good only if dim == 2 
+		   }
+		 cout << "nb of field BB " << nbfieldBB << endl;
+		 //		 if(fBB) fBB->precision(15);
+		 //if(fbb) fbb->precision(15);
+		 for(i=0;i<Th.nbv;i++)
+		   {
+		     Int4 i0,i1,i2;
+		     double a[3];
+		     Icoor2 dete[3];
+		     I2 I = Th.BTh.toI2(Th.vertices[i].r);
+		     Triangle & tb = *Th.BTh.FindTriangleContening(I,dete);
+		     
+		     if (tb.det>0) { // internal point 
+		       a[0]= (Real8) dete[0]/ tb.det;
+		       a[1]= (Real8) dete[1] / tb.det;
+		       a[2] = (Real8) dete[2] / tb.det;
+		       i0=Th.BTh.Number(tb[0]);
+		       i1=Th.BTh.Number(tb[1]);
+		       i2=Th.BTh.Number(tb[2]);}
+		     else {
+		       double aa,bb;
+		       
+		       TriangleAdjacent  ta=CloseBoundaryEdge(I,&tb,aa,bb).Adj();
+		       
+		       int k = ta;
+		       Triangle & tc = *(Triangle *)ta;
+		       i0=Th.BTh.Number(tc[0]);
+		       i1=Th.BTh.Number(tc[1]);
+		       i2=Th.BTh.Number(tc[2]);
+		       a[VerticesOfTriangularEdge[k][1]] =aa;
+		       a[VerticesOfTriangularEdge[k][0]] = bb;
+		       a[OppositeVertex[k]] = 1- aa -bb;}
+		     
+		     Int4  ibb0 = nbfieldbb*i0;
+		     Int4  ibb1 = nbfieldbb*i1;
+		     Int4  ibb2 = nbfieldbb*i2;
+
+		     Int4  iBB0 = nbfieldBB*i0;
+		     Int4  iBB1 = nbfieldBB*i1;
+		     Int4  iBB2 = nbfieldBB*i2;
+		     Int4 j=0;
+
+		     for ( j=0;j<nbfieldbb;j++) 
+		       *fbb  << " " << ( a[0] * solbb[ibb0++] + a[1] * solbb[ibb1++] + a[2]* solbb[ibb2++]) ;
+
+		     for (j=0;j<nbfieldBB;j++) 
+		       *fBB  << " " << ( a[0] * solBB[iBB0++] + a[1] * solBB[iBB1++] + a[2]* solBB[iBB2++]) ;
+		     
+		     if (fbb) *fbb  << endl;
+		     if (fBB) *fBB  << endl;
+		   }
+		 if (fbb)
+		   delete fbb  ; // close
+		 if (fBB)
+		   delete fBB  ; // close
+		 if (solbb) 
+		   delete [] solbb;
+		 if (solBB) 
+		   delete [] solBB;
+		 double  time04 = CPUtime();
+		 if(verbosity>0) 
+		   cout << " Cpu time for interpolation " << time04-time00 << " s" <<endl;
+		 
+	       }
+	     time4 = CPUtime();
+	     if(verbosity>0) 
+	       {
+	       cout << " Cpu time for meshing with io  : " << time4-time0
+		    << "s  Nb Vertices/s = " << Th.nbv/(time4-time0)
+		    << endl
+		    << " Nb vertices = " << Th.nbv;
+	       if (Th.nbt-Th.NbOutT-Th.NbOfQuad*2) 
+		 cout  << " Nb Triangles = " << (Th.nbt-Th.NbOutT-Th.NbOfQuad*2);
+	       if (Th.NbOfQuad ) 
+		   cout  << " Nb Quadrilaterals = " << Th.NbOfQuad  ;
+		     cout   << endl;
+	       }
+	     
+#ifdef DRAWING
+	     if(initgraph)
+	       {
+		 reffecran();
+		 Th.InitDraw();
+		 Th.Draw();
+		 Th.inquire();
+	       }
+#endif
+	     
+	     // cout << "delete &Th " ;
+	     delete &Th;
+	     //cout << " end " << endl;
+	   }
+       }// if (fgeom && fmeshout)
+     // clean the 
+     for(i=1;i<datargc;i++)
+       delete [] datargv[i] ;
+
+#ifdef DRAWING 
+     if(initgraph)
+       closegraphique();
+     initgraph=0;
+#endif
+     cout << flush;
+     return(0);
+     } 
+ 
diff --git a/src/bamg/cvmsh2.cpp b/src/bamg/cvmsh2.cpp
new file mode 100644
index 0000000..09dad63
--- /dev/null
+++ b/src/bamg/cvmsh2.cpp
@@ -0,0 +1,152 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+//
+// SUMMARY: Bamg: Bidimensional Anisotrope Mesh Generator
+// RELEASE: 0 
+// AUTHOR:   F. Hecht,    
+// ORG    :  UPMC
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+/*
+ 
+ This file is part of Freefem++ or Bamg
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+// ORIG-DATE:     Dec 97
+// ORIG-DATE:     Dec 97
+#include "config-wrapper.h"
+#include <cstdlib>
+#include <cstdio>
+#include <string.h>
+#include <setjmp.h>
+#include <new>
+#include <cassert>
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+
+using namespace std;
+using namespace bamg;
+//long verbosity=2;
+#ifdef DRAWING 
+bool withrgraphique=  initgraphique;
+#else
+bool withrgraphique=false; 
+#endif
+#ifdef HAVE_UNISTD_H 
+#include <unistd.h>
+#else
+#ifdef __MWERKS__
+#define R_OK 0
+#define F_OK 0
+#define W_OK 0
+#include <unix.h>
+inline int access( char *fileName, int notUsed )
+{
+	struct stat		statRec;
+	return  stat( fileName, &statRec );
+}
+#endif
+
+#ifdef PURE_WIN32
+#define R_OK 0
+#define F_OK 0
+#define W_OK 0
+#define access(i,j) 1
+#endif
+#endif
+int initgraph=0;
+void NewHandler();
+void NewHandler()
+{ cerr << " Not enought memory " << endl;
+  exit(1);
+}
+
+
+void  MeshErrorIO(ios& )
+{
+  MeshError(999);
+  exit(1);
+}
+
+int main(int argc, char **argv)
+{ 
+  Real8 cutoffradian = 30.0*Pi/180.0;
+  char * fin=0,*fout=0,*fgeom=0;
+  verbosity = 2;
+  int ok=0,i=0;
+  if (argc >= 3)
+    {
+      fin=argv[1];
+      fout=argv[2];
+      ok= !access(fin,R_OK) && (access(fout,F_OK) || !access(fout,W_OK)) ;
+    }
+  
+  for (i=3;i<argc && ok ;i+=2)
+    if (!strcmp(argv[i],"-g")) 
+      {
+	fgeom=argv[i+1];
+	ok= ok &&  (access(fgeom,F_OK) || !access(fgeom,W_OK) );
+      }
+    else if (!strcmp(argv[i],"-thetamax"))
+      cutoffradian = atof(argv[i+1])*Pi/180.0;
+    else if (!strcmp(argv[i],"-v"))
+      verbosity = atoi(argv[i+1]);
+    else
+      ok=0;
+      
+  
+  
+  if (!ok)
+    {
+      cout << "2D mesh convertisor of type   .am_fmt .amdba .am .nopo .msh .ftq + bd mesh\n";
+      cout << "                    in type   .am_fmt .amdba .am .nopo .msh .ftq + bd mesh\n";
+      cout << endl;
+      cout << " usage: cnmsh2 InMesh OutMesh \n";
+      cout << " or   : cnmsh2 Inmeshfile  OutBdmeshfile  [-g OutGeomfile ] [ -thetamax theta ] [-v level]\n";
+      cout << endl;
+      cout << " where  theta is the angular limit for  smooth curve in  degre \n";
+      cout << "        level is level of verbosity in [0..99] 0 => no message, 99 to much \n";
+      cout << endl;
+      cout << " remark: ";
+      cout << "   the  type of OutMesh is defined with the suffix\n";
+      cout << "   si the suffixe is not in .am_fmt .amdba .am .nopo .msh .ftq, then \n";
+      cout << "   the mesh is a bd mesh (cf .mesh)" << endl;
+      return 1;
+    }
+  MeshIstreamErrorHandler = MeshErrorIO;
+  set_new_handler( &NewHandler);
+#ifdef DRAWING
+  if(initgraphique)
+    { 
+      initgraphique(); 
+      initgraph=1;
+    }
+#endif
+  //    cout << "open file in " << fin<< endl;
+  Triangles Th(fin,cutoffradian);
+  if (!fgeom)
+    ((void )  0); //    Th.Write( (const char *) fout);
+  else
+    {
+      //      cout << " geom " << fgeom << endl;
+      Th.Gh.Write(fgeom);
+      Th.Write(fout,Triangles::BDMesh);
+    }
+
+   return 0;
+}
diff --git a/src/bamg/global.cpp b/src/bamg/global.cpp
new file mode 100644
index 0000000..488102f
--- /dev/null
+++ b/src/bamg/global.cpp
@@ -0,0 +1,3 @@
+long verbosity=1;
+  long mpirank =0;
+void  ShowDebugStack(){}
diff --git a/src/bamglib/._Mesh2.h b/src/bamglib/._Mesh2.h
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/bamglib/._Mesh2.h differ
diff --git a/src/bamglib/._MeshWrite.cpp b/src/bamglib/._MeshWrite.cpp
new file mode 100644
index 0000000..63e1130
Binary files /dev/null and b/src/bamglib/._MeshWrite.cpp differ
diff --git a/src/bamglib/._Metric.cpp b/src/bamglib/._Metric.cpp
new file mode 100644
index 0000000..63e1130
Binary files /dev/null and b/src/bamglib/._Metric.cpp differ
diff --git a/src/bamglib/._QuadTree.cpp b/src/bamglib/._QuadTree.cpp
new file mode 100644
index 0000000..63e1130
Binary files /dev/null and b/src/bamglib/._QuadTree.cpp differ
diff --git a/src/bamglib/._meshtype.h b/src/bamglib/._meshtype.h
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/bamglib/._meshtype.h differ
diff --git a/src/bamglib/._write_hdf5.hpp b/src/bamglib/._write_hdf5.hpp
new file mode 100644
index 0000000..361d6a9
Binary files /dev/null and b/src/bamglib/._write_hdf5.hpp differ
diff --git a/src/bamglib/._write_xdmf.cpp b/src/bamglib/._write_xdmf.cpp
new file mode 100644
index 0000000..361d6a9
Binary files /dev/null and b/src/bamglib/._write_xdmf.cpp differ
diff --git a/src/bamglib/._write_xdmf.hpp b/src/bamglib/._write_xdmf.hpp
new file mode 100644
index 0000000..361d6a9
Binary files /dev/null and b/src/bamglib/._write_xdmf.hpp differ
diff --git a/src/bamglib/Makefile.am b/src/bamglib/Makefile.am
new file mode 100644
index 0000000..cd78546
--- /dev/null
+++ b/src/bamglib/Makefile.am
@@ -0,0 +1,11 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+
+# This is not compiled as a separate library because its
+# interconnections with other libraries have not been solved.
+
+EXTRA_DIST=Mesh2.cpp Mesh2.h MeshDraw.cpp MeshGeom.cpp Meshgibbs.cpp	\
+Meshio.cpp Meshio.h MeshQuad.cpp MeshRead.cpp meshtype.h MeshWrite.cpp	\
+Metric.cpp Metric.h QuadTree.cpp QuadTree.h R2.cpp R2.h SetOfE4.cpp	\
+SetOfE4.h write_hdf5.cpp write_hdf5.hpp write_xdmf.cpp write_xdmf.hpp
diff --git a/src/bamglib/Mesh2.cpp b/src/bamglib/Mesh2.cpp
new file mode 100644
index 0000000..c8bf3f2
--- /dev/null
+++ b/src/bamglib/Mesh2.cpp
@@ -0,0 +1,5197 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifdef __MWERKS__
+#ifdef __INTEL__
+//#pragma global_optimizer off
+//#pragma inline_depth(0)
+//#pragma optimization_level 2
+#endif
+//#pragma inline_depth 0
+#endif
+extern bool withrgraphique;
+#include <stdio.h>
+#include <string.h>
+#include <math.h> 
+#include <time.h>
+#include <iostream>
+using namespace std; 
+
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+
+namespace bamg {
+
+
+#ifdef DEBUG1
+extern int SHOW ; // for debugging 
+int SHOW = 0; // for debugging 
+
+#endif
+
+int  Triangles::counter = 0;
+
+Triangles * CurrentTh =0;
+
+int hinterpole=1;
+
+
+long NbUnSwap =0;
+int  ForDebugging = 0;
+const Direction NoDirOfSearch = Direction();
+#ifndef NDEBUG 
+inline void MyAssert(int i,char*ex,char * file,long line) 
+{
+  if( i) {
+    cerr << "Error Assert:" << ex << " in " << file << " line: " << line << endl;
+#ifdef  NOTFREEFEM
+    exit(1); 
+#else
+    throw(ErrorExec("exit",1000));
+#endif
+  }
+}
+#endif
+
+Int4 AGoodNumberPrimeWith(Int4 n)
+{
+  const Int4 BigPrimeNumber[] ={ 567890359L,
+				 567890431L,  567890437L,  567890461L,  567890471L,
+				 567890483L,  567890489L,  567890497L,  567890507L,
+				 567890591L,  567890599L,  567890621L,  567890629L , 0};
+  
+  Int4 o = 0;
+  Int4 pi = BigPrimeNumber[1];
+  for (int i=0; BigPrimeNumber[i]; i++) {
+    Int4 r = BigPrimeNumber[i] % n;
+    Int4 oo = Min(Min(r,n-r),Min(Abs(n-2*r),Abs(n-3*r)));
+    if ( o < oo) 
+      o=oo,pi=BigPrimeNumber[i];}
+  //  cout << " AGoodNumberPrimeWith " << n << " " <<pi << " "<< o << endl;
+  return pi; 
+}
+
+class Triangles;
+void MeshError(int Err,const Triangles *Th){
+ cerr << " Fatal error in the meshgenerator " << Err << endl ;
+#ifdef  NOTFREEFEM
+    exit(1); 
+#else
+  throw(ErrorMesh("Bamg",Err,Th));
+#endif
+}
+
+ ostream& operator <<(ostream& f, const  Triangle & ta)
+  {
+    if(CurrentTh)
+      f << "[" << CurrentTh->Number(ta) << "::" 
+     <<  CurrentTh->Number(ta.ns[0]) << "," 
+     <<  CurrentTh->Number(ta.ns[1]) << "," 
+     <<  CurrentTh->Number(ta.ns[2]) << "," 
+     << "{" <<  CurrentTh->Number(ta.at[0]) << " " << ta.aa[0] << "} " 
+     << "{" <<  CurrentTh->Number(ta.at[1]) << " " << ta.aa[1] << "} " 
+     << "{" <<  CurrentTh->Number(ta.at[2]) << " " << ta.aa[2] << "} " 
+     << "]" ;
+     else
+       f << "[" 
+     << ta.ns[0] << "," 
+     << ta.ns[1] << "," 
+     << ta.ns[2] << "," 
+     << "{" << ta.at[0] << " " << ta.aa[0] << "} " 
+     << "{" << ta.at[1] << " " << ta.aa[1] << "} " 
+     << "{" << ta.at[2] << " " << ta.aa[2] << "} " 
+     << "]" ;
+   return f;}
+
+void  swap(Triangle *t1,Int1 a1,
+                 Triangle *t2,Int1 a2,
+                 Vertex *s1,Vertex *s2,Icoor2 det1,Icoor2 det2)
+{ // swap 
+  // --------------------------------------------------------------
+  // Int1 a2=aa[a];// les 2 numero de l arete dans les 2 triangles
+  //                               
+  //               sb                     sb    
+  //             / | \                   /   \                      !
+  //         as1/  |  \                 /a2   \                     !
+  //           /   |   \               /    t2 \                    !
+  //       s1 /t1  | t2 \s2  -->   s1 /___as2___\s2                 !
+  //          \  a1|a2  /             \   as1   /  
+  //           \   |   /               \ t1    /   
+  //            \  |  / as2             \   a1/    
+  //             \ | /                   \   /     
+  //              sa                       sa   
+  //  -------------------------------------------------------------
+  int as1 = NextEdge[a1];
+  int as2 = NextEdge[a2];
+  int ap1 = PreviousEdge[a1];
+  int ap2 = PreviousEdge[a2];
+#ifdef DRAWING1
+  couleur(0);
+  t1->Draw();
+  t2->Draw();
+#endif
+#ifdef DEBUG1
+  t1->check();
+  t2->check();
+#endif
+  (*t1)(VerticesOfTriangularEdge[a1][1]) = s2 ; // avant sb
+  (*t2)(VerticesOfTriangularEdge[a2][1]) = s1  ; // avant sa
+  // mise a jour des 2 adjacences externes 
+  TriangleAdjacent taas1 = t1->Adj(as1),
+    taas2 = t2->Adj(as2),
+    tas1(t1,as1), tas2(t2,as2),
+    ta1(t1,a1),ta2(t2,a2);
+#ifdef DEBUG
+  assert( ! ta1.Locked());
+  assert( ! ta2.Locked());
+#endif
+  // externe haut gauche
+  taas1.SetAdj2(ta2, taas1.GetAllFlag_UnSwap());
+   // externe bas droite
+  taas2.SetAdj2(ta1, taas2.GetAllFlag_UnSwap());
+  // remove the Mark  UnMarkSwap 
+  t1->SetUnMarkUnSwap(ap1);
+  t2->SetUnMarkUnSwap(ap2);
+  // interne 
+  tas1.SetAdj2(tas2);
+
+  t1->det = det1;
+  t2->det = det2;
+
+  t1->SetTriangleContainingTheVertex();
+  t2->SetTriangleContainingTheVertex();
+#ifdef DEBUG1
+  t1->check();
+  t2->check();
+#endif
+#ifdef DRAWING1 
+  couleur(1);
+  t1->Draw();
+  t2->Draw();
+#endif 
+#ifdef DRAWING1
+  if(  CurrentTh)
+    CurrentTh->inquire();
+#endif
+
+} // end swap 
+
+
+
+
+
+Int4 FindTriangle(Triangles &Th, Real8 x, Real8 y, double* a,int & inside)
+ {
+   CurrentTh=&Th;
+   assert(&Th);
+   I2 I = Th.toI2(R2(Min(Max(Th.pmin.x,x),Th.pmax.x),Min(Max(Th.pmin.y,y),Th.pmax.y))); 
+   Icoor2 dete[3];
+   Triangle & tb = *Th.FindTriangleContening(I,dete);
+   
+   if  (tb.link) 
+     { // internal point in a true triangles
+       a[0]= (Real8) dete[0]/ tb.det;
+       a[1]= (Real8) dete[1] / tb.det;
+       a[2] = (Real8) dete[2] / tb.det;
+	 inside = 1;	 
+	 return Th.Number(tb);
+     } 
+   else 
+     {
+       inside = 0; 
+       double aa,bb;
+       TriangleAdjacent  ta=CloseBoundaryEdgeV2(I,&tb,aa,bb);	 
+       int k = ta;
+       Triangle * tc = ta;
+       if (!tc->link) 
+	 { ta = ta.Adj();
+	 tc=ta;
+	 k = ta;
+	 Exchange(aa,bb);
+	 assert(tc->link);
+	 }
+       a[VerticesOfTriangularEdge[k][0]] = aa;
+       a[VerticesOfTriangularEdge[k][1]] = bb;
+       a[OppositeVertex[k]] = 1- aa -bb;
+       return Th.Number(tc);
+     }
+ }
+
+
+TriangleAdjacent CloseBoundaryEdge(I2 A,Triangle *t, double &a,double &b) {
+// 
+  //  cout << " - ";   	 
+  int k=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+  int dir=0;
+  assert(k>=0);
+  int kkk=0;  
+  Icoor2 IJ_IA,IJ_AJ;
+  TriangleAdjacent edge(t,OppositeEdge[k]);          
+  for (;;edge = dir >0 ? Next(Adj(Next(edge))) : Previous(Adj(Previous(edge)))) 
+   {  
+   
+    assert(kkk++<1000);      
+    Vertex  &vI =  *edge.EdgeVertex(0);
+    Vertex  &vJ =  *edge.EdgeVertex(1);
+    I2 I=vI, J=vJ, IJ= J-I;
+    IJ_IA = (IJ ,(A-I));
+    //   cout << A << vI.i << vJ.i << edge << " " <<  IJ_IA << " dir " << dir <<endl;
+    if (IJ_IA<0) {
+     if (dir>0) {a=1;b=0;return edge;}// change of signe => I
+     else {dir=-1;
+        continue;}};// go in direction i 
+    IJ_AJ = (IJ ,(J-A));
+    if (IJ_AJ<0) {
+    if(dir<0)  {a=0;b=1;return edge;}            
+    else {dir = 1;
+       continue;}}// go in direction j
+    double IJ2 = IJ_IA + IJ_AJ;
+    assert(IJ2);
+    a= IJ_AJ/IJ2;
+    b= IJ_IA/IJ2;
+    //    cout<< "CloseBoundaryEdge a = " << a << " b= " << b << endl;
+    return edge;
+  } 
+}
+
+TriangleAdjacent Triangle::FindBoundaryEdge(int i) const
+{
+  // turn around  the vertex ns[i] also call  s
+#ifdef DEBUG
+   Vertex * s  =  ns[i];
+#endif
+  Triangle   *t = (Triangle *) this , *ttc;
+  int k=0,j = EdgesVertexTriangle[i][0],jc;
+  int exterieur  = !link  ;
+  
+  do 
+    {
+      int exterieurp = exterieur;
+      k++; 
+#ifdef DEBUG
+      assert( s == & (*t)[VerticesOfTriangularEdge[j][1]] );
+#endif
+      ttc =  t->at[j];
+      exterieur = !ttc->link;
+      if (exterieur+exterieurp == 1) 
+	return TriangleAdjacent(t,j);
+      jc = NextEdge[t->aa[j]&3];
+      t = ttc;
+      j = NextEdge[jc];
+      assert(k<2000);
+    } while ( (this!= t)); 
+  return TriangleAdjacent(0,0);
+ 
+}
+
+
+TriangleAdjacent CloseBoundaryEdgeV2(I2 C,Triangle *t, double &a,double &b) 
+{ 
+ // walk around the vertex 
+ // version 2 for remove the probleme if we fill the hole
+  //int bug=1;
+  //  Triangle *torigine = t;
+  // restart:
+  //   int dir=0;
+  assert(t->link == 0);
+  // to have a starting edges 
+  // try the 3 edge bourna-- in case of internal hole 
+  // and choice  the best 
+  // 
+  // 
+  // the probleme is in case of  the fine and long internal hole
+  // for exemple neart the training edge of a wing
+  // 
+  Vertex * s=0,*s1=0, *s0=0;
+  Icoor2 imax = MaxICoor22;
+  Icoor2 l0 = imax,l1 = imax;
+  double dd2 =  imax;// infinity
+  TriangleAdjacent er; 
+  int  cas=-2;
+  for (int j=0;j<3;j++)
+    { 
+      TriangleAdjacent ta=t->FindBoundaryEdge(j);
+      if  (! (Triangle *) ta) continue;
+      s0 = ta.EdgeVertex(0);
+      s1 = ta.EdgeVertex(1);
+      I2 A = * s0;
+      I2 B = *ta.EdgeVertex(1);
+      I2 AB = B-A,AC=C-A,BC=B-C;
+      Icoor2  ACAC = (AC,AC), BCBC = (BC,BC);
+      Icoor2  AB2  =   Norme2_2(AB); //  ||AB||^2
+      Icoor2  ABAC  =   (AB,AC);         //  AB.AC|
+      
+      double d2;
+      if ( ABAC < 0 )   // DIST A
+        {
+           if ( (d2=(double) ACAC)  <  dd2) 
+             {
+	       //  cout << " A "  << d2  << " " <<  dd2;
+               er = ta;
+               l0 = ACAC;
+               l1 = BCBC;
+               cas = 0;
+               s = s0;
+             }
+        }
+      else if (ABAC > AB2)  // DIST B
+        {
+           if ( (d2=(double) BCBC)  <  dd2) 
+             {
+	       // cout << " B "  << d2  << " " <<  dd2;
+               dd2 = d2;
+               er = Adj(ta); // other direction
+               l0 = BCBC;
+               l1 = ACAC;
+               cas = 1;
+               s = s1;
+             }
+        }
+      else  // DIST AB
+        { 
+
+          double det_2 =  (double) Det(AB,AC); 
+          det_2 *= det_2; // square of area*2 of triangle ABC
+          d2 = det_2/ (double) AB2; // hauteur^2 in C of of triangle ABC      
+	  //	  cout << " AB " << d2 << " " << dd2 
+	  //      << " " << CurrentTh->Number(ta.EdgeVertex(0)) 
+	  //     << " " << CurrentTh->Number(ta.EdgeVertex(1)) << " " ;
+
+          if (d2 < dd2) 
+	       {
+	         dd2 = d2;
+	         er = ta;
+	         l0 = (AC,AC);
+	         l1 = (BC,BC);
+	         s = 0;
+                 cas = -1;
+		 //	 cout << " ABAC " <<  ABAC << " ABAC " << ABAC
+		 //	      << " AB2 " << AB2 << endl;
+		 b = ((double) ABAC/(double) AB2);
+		 a = 1 - b;
+	       }
+        }
+     }
+   assert(cas !=-2);
+   // l1 = ||C s1||  , l0 = ||C s0||
+   // where s0,s1 are the vertex of the edge er
+
+   if ( s) 
+     { 
+       t=er;
+       TriangleAdjacent edge(er); 
+       
+       int kkk=0;  
+       int linkp = t->link == 0;
+       
+       Triangle * tt=t=edge=Adj(Previous(edge));
+       //  cout << CurrentTh->Number(t) << " " << linkp << endl;
+       do  {  // loop around vertex s
+	 
+	 assert(edge.EdgeVertex(0)==s && kkk++<10000);
+	 
+	 int link = tt->link == 0;
+	 //	 cout << CurrentTh->Number(tt) << " " << link << " " << CurrentTh->Number(s) 
+	 //	      << " " << CurrentTh->Number(er.EdgeVertex(0)) 
+	 //	      << " " << CurrentTh->Number(er.EdgeVertex(1)) 
+	 //	      << " " << CurrentTh->Number(edge.EdgeVertex(0)) 
+	 //	      << " " << CurrentTh->Number(edge.EdgeVertex(1)) 
+	 //	      <<  endl;
+	 if ((link + linkp) == 1) 
+	   { // a boundary edge 
+	     Vertex * st = edge.EdgeVertex(1);
+	     I2 I=*st;
+	     Icoor2  ll = Norme2_2 (C-I);
+	     if (ll < l1) {  // the other vertex is neart 
+	       s1=st;
+	       l1=ll;
+	       er = edge;
+	       if(ll<l0) { // change of direction --
+		 s1=s;
+		 l1=l0;
+		 s=st;
+		 l0=ll;
+		 t=tt;
+		 edge=Adj(edge);
+		 link=linkp;
+		 er = edge;
+	       }
+	     }
+	   }
+	 
+	 linkp=link;
+	 edge=Adj(Previous(edge));
+	 tt = edge;
+       } while (t!=tt);
+
+       assert((Triangle *) er);
+       I2 A((I2)*er.EdgeVertex(0));
+       I2 B((I2)*er.EdgeVertex(1));
+       I2 AB=B-A,AC=C-A,CB=B-C;
+       double aa =  (double) (AB,AC);
+       double bb =  (double) (AB,CB);
+       //  cout << " " << aa << " " << bb 
+       //    << " " << CurrentTh->Number(er.EdgeVertex(0)) 
+       //	    << " " << CurrentTh->Number(er.EdgeVertex(1)) ;
+       if (aa<0)       a=1,b=0;
+       else if(bb<0)   a=0,b=1;
+       else  
+	 {
+	   a  = bb/(aa+bb);
+	   b  = aa/(aa+bb);
+	 }
+     }
+   
+   //   cout <<" return= " <<  CurrentTh->Number(er.EdgeVertex(0)) << " " 
+   //	<<  CurrentTh->Number(er.EdgeVertex(1)) << " " << a 
+   //	<< " " << b <<" " << l0 << " " <<l1 <<endl;
+   return er;
+} 
+
+
+
+Metric Triangles::MetricAt  (const R2 & A) const
+  { //if ((vertices <= &v) && (vertices < v+nbv)) return v.m;
+    I2 a = toI2(A);
+    Icoor2 deta[3];
+    Triangle * t =FindTriangleContening(a,deta);
+    if (t->det <0) { // outside
+      double ba,bb;
+      TriangleAdjacent edge= CloseBoundaryEdge(a,t,ba,bb) ;
+      return Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));}
+     else { // inside
+      Real8   aa[3];
+      Real8 s = deta[0]+deta[1]+deta[2];
+      aa[0]=deta[0]/s;
+      aa[1]=deta[1]/s;
+      aa[2]=deta[2]/s;
+      return Metric(aa,(*t)[0],(*t)[1],(*t)[2]);
+     }
+  }
+
+
+void ListofIntersectionTriangles::SplitEdge(const Triangles & Bh,
+       const R2 &A,const R2  &B,int nbegin)
+{ //  SplitEdge
+  //  if(SHOW)  cout << " splitedge " << A << B << " " <<  nbegin << endl;
+  Triangle *tbegin, *t;
+
+  Icoor2 deta[3], deti,detj;
+  Real8 ba[3];
+  int nbt =0,ifirst=-1,ilast;
+  int i0,i1,i2;
+  int ocut,i,j,k=-1;
+  //  int OnAVertices =0;
+  Icoor2 dt[3];
+  I2 a = Bh.toI2(A) ,b= Bh.toI2(B);// compute  the Icoor a,b
+  I2 vi,vj;  
+  int iedge =-1;// not a edge
+
+  if(nbegin)  {// optimisation 
+    // we suppose  knowing the starting  triangle
+    t=tbegin=lIntTria[ilast=(Size-1)].t;
+    if (tbegin->det>=0) 
+    ifirst = ilast;}  
+  else {// not optimisation 
+    init();
+    t=tbegin = Bh.FindTriangleContening(a,deta);
+    //    if(SHOW) cout <<t << " " << Real8(deta[0])/t->det<< " " << Real8(deta[1])/t->det
+    //		  << " " << Real8(deta[2])/t->det << endl;
+    if( t->det>=0)
+      ilast=NewItem(t,Real8(deta[0])/t->det,Real8(deta[1])/t->det,Real8(deta[2])/t->det);
+    else 
+     {// find the nearest boundary edge  of the vertex A
+      // find a edge or such normal projection a the edge IJ is on the edge
+      //   <=> IJ.IA >=0 && IJ.AJ >=0
+      ilast=ifirst;
+      double ba,bb;
+      TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb);
+      Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+      NewItem(A,Metric(ba,v0,bb,v1));
+      t=edge;
+      // test if the point b is in the same side
+      if (det(v0.i,v1.i,b)>=0) {
+	//cout << " All the edge " << A << B << endl;
+	TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb);
+	Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+	NewItem(A,Metric(ba,v0,bb,v1));
+	return;
+      }
+     } // find the nearest boundary edge  of the vertex A
+   } // end not optimisation 
+  if (t->det<0) {  // outside departure
+    while (t->det <0) { // intersection boundary edge and a,b,
+      k=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+      assert(k>=0);
+      ocut = OppositeEdge[k];
+      i=VerticesOfTriangularEdge[ocut][0];
+      j=VerticesOfTriangularEdge[ocut][1];
+      vi=(*t)[i];
+      vj=(*t)[j];
+      deti = bamg::det(a,b,vi);
+      detj = bamg::det(a,b,vj);
+     //  if(SHOW) {  penthickness(3);
+// 	Move(vi);Line(vj);CurrentTh->inquire();penthickness(1);
+//         cout << Bh.Number(tbegin) << " " << Bh.Number(t) << " i= " << i <<" j= " <<  j << " k=" << k 
+//       	   << " deti= " << deti << " detj= " << detj 
+// 	     << " v = " << Bh.Number((*t)[i]) << (*t)[i].r <<  " " << Bh.Number((*t)[j]) << (*t)[j].r  << endl;}
+      if (deti>0) // go to  i direction on gamma
+	ocut = PreviousEdge[ocut];      
+      else if (detj<=0) // go to j direction on gamma
+	ocut = NextEdge[ocut];         
+      TriangleAdjacent tadj =t->Adj(ocut);
+      t = tadj;
+      iedge= tadj; 
+      if (t == tbegin) { // 
+	double ba,bb;
+	if (verbosity>7) 
+	  cout << "       SplitEdge: All the edge " << A << B << nbegin <<  det(vi,vj,b) 
+	       << " deti= " << deti <<  " detj=" <<detj << endl;
+	TriangleAdjacent edge=CloseBoundaryEdge(a,t,ba,bb);
+	Vertex & v0 = *edge.EdgeVertex(0), & v1 = *edge.EdgeVertex(1);
+	NewItem(A,Metric(ba,v0,bb,v1));
+	return;
+	/*
+	cerr << nbegin <<  det(vi,vj,b) << " deti= " << deti <<  " detj=" <<detj << endl;
+	cerr << "SplitEdge on boucle A" << A << " B = " << B << endl;
+
+#ifdef DRAWING
+	reffecran();
+	Bh.Draw();
+        penthickness(5);
+	Move(A);
+	Line(B);
+        penthickness(1);
+
+	Bh.inquire();
+        penthickness(5);
+	Move(A);
+	Line(B);
+        penthickness(1);
+	Bh.inquire();
+#endif	
+	MeshError(997);*/
+      }
+    } //  end while (t->det <0)
+    // theoriticaly we have: deti =<0 and detj>0
+  
+      // computation of barycentric coor
+    // test if the point b is on size on t
+    // we revert vi,vj because vi,vj is def in Adj triangle
+    if ( det(vi,vj,b)>=0) {
+      if (verbosity>7)
+      cout << "       SplitEdge: all AB outside " << A << B << endl;
+      t=tbegin;
+      Real8 ba,bb;
+      TriangleAdjacent edge=CloseBoundaryEdge(b,t,ba,bb);
+      NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1)));
+      return;
+    }
+    else
+      {
+	k = OppositeVertex[iedge];
+	i=VerticesOfTriangularEdge[iedge][0];
+	j=VerticesOfTriangularEdge[iedge][1];
+	Real8 dij = detj-deti;
+	assert(i+j+k == 0 + 1 +2);
+	ba[j] =  detj/dij;
+	ba[i] = -deti/dij;
+	ba[k] = 0;
+// 	if(SHOW) cout << i << " " << j << " " << k << " " << ba[i] << " " << ba[j] << endl;
+	ilast=NewItem(t,ba[0],ba[1],ba[2]); }
+  }  //  outside departure
+
+     
+   
+  // recherche the intersection of [a,b] with Bh Mesh.
+  // we know  a triangle ta contening the vertex a
+  // we have 2 case for intersection [a,b] with a edge [A,B] of Bh
+  // 1) the intersection point is in ]A,B[
+  // 2)                        is A or B
+  // first version --- 
+  for (;;) {
+    //    t->Draw();
+    if (iedge < 0) {
+      i0 =0;i1=1;i2=2;
+      dt[0] =bamg::det(a,b,(*t)[0]);
+      dt[1] =bamg::det(a,b,(*t)[1]);
+      dt[2] =bamg::det(a,b,(*t)[2]);}
+    else {
+      i2 = iedge;
+      i0 = NextEdge[i2];
+      i1 = NextEdge[i0]; 
+      dt[VerticesOfTriangularEdge[iedge][0]] = detj;// we revert i,j because
+      dt[VerticesOfTriangularEdge[iedge][1]] = deti;// we take the Triangle by the other side
+      dt[iedge] = det(a,b,(*t)[OppositeVertex[iedge]]);}
+    
+    // so we have just to see the transition from - to + of the det0..2 on edge of t
+    // because we are going from a to b
+    if       ((dt[i=VerticesOfTriangularEdge[i0][0]] <  0) &&
+              ( dt[j=VerticesOfTriangularEdge[i0][1]] > 0))
+      ocut =i0;
+    else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] <  0) &&
+              (dt[j=VerticesOfTriangularEdge[i1][1]] >  0))
+      ocut =i1;
+    else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] <  0) && 
+              (dt[j=VerticesOfTriangularEdge[i2][1]] >  0))
+      ocut =i2;
+    else if   ((dt[i=VerticesOfTriangularEdge[i0][0]] == 0) &&
+              ( dt[j=VerticesOfTriangularEdge[i0][1]] >  0))
+      ocut =i0;
+    else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] == 0) &&
+              (dt[j=VerticesOfTriangularEdge[i1][1]] >  0))
+      ocut =i1;
+    else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] == 0) && 
+              (dt[j=VerticesOfTriangularEdge[i2][1]] >  0))
+      ocut =i2;
+    else if   ((dt[i=VerticesOfTriangularEdge[i0][0]] <  0) &&
+              ( dt[j=VerticesOfTriangularEdge[i0][1]] == 0))
+      ocut =i0;
+    else  if ((dt[i=VerticesOfTriangularEdge[i1][0]] <  0) &&
+              (dt[j=VerticesOfTriangularEdge[i1][1]] == 0))
+      ocut =i1;
+    else  if ((dt[i=VerticesOfTriangularEdge[i2][0]] <  0) && 
+              (dt[j=VerticesOfTriangularEdge[i2][1]] == 0))
+      ocut =i2;
+    else { //  On a edge (2 zero)
+      k =0;
+      if (dt[0]) ocut=0,k++; 
+      if (dt[1]) ocut=1,k++; 
+      if (dt[2]) ocut=2,k++;
+      if(k == 1) {
+        if (dt[ocut] >0) // triangle upper AB
+          ocut = NextEdge[ocut];
+        i= VerticesOfTriangularEdge[ocut][0];
+        j= VerticesOfTriangularEdge[ocut][1];
+      }
+      else  {
+        cerr << " Bug Split Edge " << endl;
+        cerr << " dt[0]= " << dt[0] 
+             << " dt[1]= " << dt[1] 
+             << " dt[2]= "<< dt[2] << endl;
+        cerr << i0 << " " << i1 << " " << i2 << endl;
+        cerr << " A = " << A << " B= " << B << endl;
+        cerr << " Triangle t = " <<  *t << endl;
+        cerr << (*t)[0] << (*t)[1] << (*t)[0] << endl;
+        cerr << " nbt = " << nbt << endl;
+        MeshError(100);}}
+    
+    k = OppositeVertex[ocut];
+
+    Icoor2 detbij = bamg::det((*t)[i],(*t)[j],b);
+
+    
+    if (detbij >= 0) { //we find the triangle contening b
+      dt[0]=bamg::det((*t)[1],(*t)[2],b);
+      dt[1]=bamg::det((*t)[2],(*t)[0],b);
+      dt[2]=bamg::det((*t)[0],(*t)[1],b);
+#ifdef DEBUG 
+      assert(dt[0] >= 0);
+      assert(dt[1] >= 0);
+      assert(dt[2] >= 0);
+#endif
+      Real8 dd = t->det;
+      NewItem(t,dt[0]/dd,dt[1]/dd,dt[2]/dd);      
+      return ;}
+    else { // next triangle by  adjacent by edge ocut 
+      deti = dt[i];
+      detj = dt[j];
+      Real4 dij = detj-deti;
+      ba[i] =  detj/dij;
+      ba[j] = -deti/dij;
+      ba[3-i-j ] = 0;
+      ilast=NewItem(t, ba[0],ba[1],ba[2]);      
+      
+      TriangleAdjacent ta =t->Adj(ocut);
+      t = ta;
+      iedge= ta; 
+      if (t->det <= 0)  {
+        double ba,bb;
+        TriangleAdjacent edge=CloseBoundaryEdge(b,t,ba,bb);
+        NewItem(B,Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1)));
+	// 	cout << " return " << ba << " " << bb << endl;
+	// ajoute le 03 frev 1997 par F. hecht
+        return;
+        }
+     }// we  go outside of omega 
+  } // for(;;)
+ 
+   
+} // routine SplitEdge
+
+
+int  ListofIntersectionTriangles::NewItem(Triangle * tt,Real8 d0,Real8 d1,Real8 d2) { 
+   int n;
+  R2 x(0,0);
+  if ( d0) x =      (*tt)[0].r * d0;
+  if ( d1) x = x +  (*tt)[1].r * d1;
+  if ( d2) x = x +  (*tt)[2].r * d2;
+  // newer add same point 
+  if(!Size ||  Norme2_2(lIntTria[Size-1].x-x)) {
+    if (Size==MaxSize) ReShape();
+    lIntTria[Size].t=tt;
+    lIntTria[Size].bary[0]=d0;
+    lIntTria[Size].bary[1]=d1;
+    lIntTria[Size].bary[2]=d2;
+    lIntTria[Size].x = x;
+    Metric m0,m1,m2;
+     Vertex * v;
+    if ((v=(*tt)(0))) m0    = v->m;
+    if ((v=(*tt)(1))) m1    = v->m;
+    if ((v=(*tt)(2))) m2    = v->m;
+    lIntTria[Size].m =  Metric(lIntTria[Size].bary,m0,m1,m2);
+#ifdef DEBUG1
+    if(SHOW) { cout << "SHOW       ++ NewItem =" << Size << x ;
+    cout << " " << d0 << " " << d1 << " " << d2 <<endl;}
+#endif
+    n=Size++;}
+  else n=Size-1;
+  return n;
+}
+int ListofIntersectionTriangles::NewItem(R2 A,const Metric & mm) {  
+   int n;
+  if(!Size ||  Norme2_2(lIntTria[Size-1].x-A)) {
+    if (Size==MaxSize) ReShape();
+    lIntTria[Size].t=0;
+    lIntTria[Size].x=A;
+    lIntTria[Size].m=mm;
+#ifdef DEBUG1
+    if (SHOW)  cout << "SHOW       ++ NewItem A" << Size << A << endl;
+#endif
+    n=Size++;
+   }
+  else  n=Size-1;
+ return  n; 
+}
+
+Real8  ListofIntersectionTriangles::Length()
+{
+  //  cout << " n= " << Size << ":" ;
+  assert(Size>0);
+  // computation of the length      
+  R2 C;
+  Metric Mx,My;
+  int ii,jj;
+  R2 x,y,xy;
+  
+  SegInterpolation *SegI=lSegsI;
+  SegI=lSegsI;
+  lSegsI[NbSeg].last=Size;// improvement 
+  
+  int EndSeg=Size;
+     
+  y = lIntTria[0].x;
+  Real8 sxy, s = 0;
+  lIntTria[0].s =0;
+  SegI->lBegin=s;
+
+  for (jj=0,ii=1;ii<Size;jj=ii++) 
+    {  
+      // seg jj,ii
+      x=y;
+      y = lIntTria[ii].x;
+      xy = y-x;
+      Mx = lIntTria[ii].m;
+      My = lIntTria[jj].m;
+      //      Real8 &sx=  lIntTria[ii].sp; // previous seg
+      //  Real8 &sy=  lIntTria[jj].sn; // next seg
+      //      sx = Mx(xy);
+      //      sy = My(xy);
+      //   sxy = (Mx(xy)+ My(xy))/2.0;
+      sxy =  LengthInterpole(Mx,My,xy);
+      s += sxy;
+      lIntTria[ii].s = s;
+      if (ii == EndSeg) 
+	SegI->lEnd=s,
+	  SegI++,
+	  EndSeg=SegI->last,
+	  SegI->lBegin=s;
+      
+      //    cout << ii << " " << jj << x<< y <<xy << s <<  lIntTria[ii].m  ;
+    }
+  len = s;
+  SegI->lEnd=s;
+
+  //  cout << " len= " << s << endl;
+  return s;
+}
+
+Int4 ListofIntersectionTriangles::NewPoints(Vertex * vertices,Int4 & nbv,Int4  nbvx)
+{
+
+  const Int4 nbvold = nbv;
+  Real8 s = Length();
+  if (s <  1.5 ) return 0;
+  //////////////////////   
+  int ii = 1 ;
+  R2 y,x;
+  Metric My,Mx ;
+  Real8 sx =0,sy;
+  int nbi = Max(2,(int) (s+0.5));
+  Real8 sint = s/nbi;
+  Real8 si = sint;
+
+  int EndSeg=Size;
+  SegInterpolation *SegI=0;
+  if (NbSeg) 
+    SegI=lSegsI,EndSeg=SegI->last;
+  
+  for (int k=1;k<nbi;k++)
+    {
+      while ((ii < Size) && ( lIntTria[ii].s <= si )) 
+	if (ii++ == EndSeg) 
+	  SegI++,EndSeg=SegI->last;
+
+      int ii1=ii-1;
+      x  =lIntTria[ii1].x;
+      sx =lIntTria[ii1].s;
+      Metric Mx=lIntTria[ii1].m;
+#ifdef DEBUG    
+      double lx = lIntTria[ii-1].sn;
+#endif
+      y  =lIntTria[ii].x;
+      sy =lIntTria[ii].s;
+      Metric My=lIntTria[ii].m;
+#ifdef DEBUG    
+      double ly =lIntTria[ii].sp;  
+      assert( sx <= si);
+      assert( si <= sy);
+      assert( sy != sx);
+#endif 
+
+      Real8 lxy = sy-sx;
+      Real8 cy = abscisseInterpole(Mx,My,y-x,(si-sx)/lxy);
+      
+      R2 C;
+      Real8 cx = 1-cy;
+      C = SegI ? SegI->F(si): x * cx + y *cy;
+
+    si += sint;
+    if ( nbv<nbvx) {
+      vertices[nbv].r = C;
+      vertices[nbv++].m = Metric(cx,lIntTria[ii-1].m,cy,lIntTria[ii].m);
+      if((verbosity/100%10)==2)
+      cout << "   -- Add point " << nbv-1 << " " << vertices[nbv-1] << " " << vertices[nbv-1].m << endl;
+
+#ifdef DEBUG
+      if(k>1) {
+	R2 AB = vertices[nbv-2].r - vertices[nbv-1].r ;
+	Real8 dp = LengthInterpole(vertices[nbv-2].m,vertices[nbv-1].m,AB);
+	if (dp > 1.6) {
+	  cerr << "PB calcul new Int.  points trop loin l=" << dp << " v=" << nbv-1 << " " << nbv-2 <<Mx<<My<<y-x << endl;
+	}
+	}
+#endif
+    }
+    else return nbv-nbvold;
+  }
+  return nbv-nbvold;
+}
+
+int SwapForForcingEdge(Vertex   *  & pva ,Vertex  * &   pvb ,
+      TriangleAdjacent & tt1,Icoor2 & dets1, Icoor2 & detsa,Icoor2 & detsb, int & NbSwap)
+{ // l'arete ta coupe l'arete pva pvb
+  // de cas apres le swap sa coupe toujours
+  // on cherche l'arete suivante 
+  // on suppose que detsa >0 et detsb <0
+  // attention la routine echange pva et pvb 
+
+   if(tt1.Locked()) return 0; // frontiere croise 
+
+  TriangleAdjacent tt2 = Adj(tt1);
+  Triangle *t1=tt1,*t2=tt2;// les 2 triangles adjacent
+  Int1 a1=tt1,a2=tt2;// les 2 numero de l arete dans les 2 triangles
+  assert ( a1 >= 0 && a1 < 3 );
+   
+  Vertex & sa= (* t1)[VerticesOfTriangularEdge[a1][0]];
+  Vertex & s1= (*t1)[OppositeVertex[a1]];
+  Vertex & s2= (*t2)[OppositeVertex[a2]];
+  
+
+  Icoor2 dets2 = det(*pva,*pvb,s2);
+
+#ifdef DEBUG
+  Vertex & sb= (*t1)[VerticesOfTriangularEdge[a1][1]];
+  Icoor2 wdets1 = det(*pva,*pvb,s1);  
+  Icoor2 wdetsa = det(*pva,*pvb,sa);
+  Icoor2 wdetsb = det(*pva,*pvb,sb);
+  assert(wdets1 == dets1);
+  assert(wdetsa == detsa);
+  assert(wdetsb == detsb);
+#endif
+  
+  Icoor2 det1=t1->det , det2=t2->det ;
+#ifdef DEBUG  
+  assert(det1>0 && det2 >0);
+  Icoor2 ddet1 = det((*t1)[0],(*t1)[1],(*t1)[2]);
+  Icoor2 ddet2 = det((*t2)[0],(*t2)[1],(*t2)[2]);
+   if ((det1 != ddet1) || (det2 != ddet2) )
+    {
+      assert(det1 == ddet1);
+      assert(det2 == ddet2);
+     }
+   Icoor2 detvasasb = det(*pva,sa,sb);
+   Icoor2 detvbsasb = det(*pvb,sa,sb);
+   if (  CurrentTh && !  ( ( (detvasasb <= 0) && (detvbsasb >= 0)) || ( (detvasasb >= 0) && (detvbsasb <= 0)))) 
+     {
+       cout << " detvasasb =" <<  detvasasb << "detvbsasb = " <<  detvbsasb 
+	    << " " << pva << " " << pvb << " "  <<CurrentTh <<endl;
+#ifdef DRAWING1
+       reffecran();
+       CurrentTh->Draw();
+       penthickness(10);
+       pva->MoveTo();pvb->LineTo();
+       penthickness(1);
+       CurrentTh->inquire();
+#endif       
+   }
+     assert( ( (detvasasb <= 0) && (detvbsasb >= 0)) || ( (detvasasb >= 0) && (detvbsasb <= 0)));
+#endif
+
+  Icoor2 detT = det1+det2;
+  assert((det1>0 ) && (det2 > 0));
+  assert ( (detsa < 0) && (detsb >0) ); // [a,b] cut infinite line va,bb
+  Icoor2 ndet1 = bamg::det(s1,sa,s2);
+  Icoor2 ndet2 = detT - ndet1;
+
+  int ToSwap =0; //pas de swap
+  if ((ndet1 >0) && (ndet2 >0)) 
+    { // on peut swaper  
+      if ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0))
+        ToSwap =1; 
+      else // swap alleatoire 
+        if (BinaryRand()) 
+          ToSwap =2; 
+    }
+#ifdef DEBUG
+  if (ForDebugging) {
+    cerr << "swap = " << ToSwap << " ndet1 " << ndet1 << ", ndet2 " << ndet2 << "det1  " << det1 << " det2 " <<  det2  
+	 << " if1 = " << ((ndet1 >0) && (ndet2 >0)) 
+	 << " if2 = " << ((dets1 <=0 && dets2 <=0) || (dets2 >=0 && detsb >=0)) << endl;
+#ifdef DRAWING
+  couleur(0);
+  t1->Draw();
+  t2->Draw();
+#endif
+  }
+#endif
+  if (ToSwap) NbSwap++,
+     bamg::swap(t1,a1,t2,a2,&s1,&s2,ndet1,ndet2);
+  
+#ifdef DEBUG
+  if (ForDebugging) {
+#ifdef DRAWING
+  couleur(4);
+  t1->Draw();
+  t2->Draw();
+  rattente(1);
+#endif
+  }
+#endif
+  int ret=1;
+
+  if (dets2 < 0) {// haut
+    dets1 = ToSwap ? dets1 : detsa ;
+    detsa = dets2; 
+    tt1 =  Previous(tt2) ;}
+  else if (dets2 > 0){// bas 
+    dets1 = ToSwap ? dets1 : detsb ;
+    detsb = dets2;
+    //xxxx tt1 = ToSwap ? tt1 : Next(tt2);
+    if(!ToSwap) tt1 =  Next(tt2);
+    }
+  else { // changement de sens 
+     if (ForDebugging)  cout << "changement de sens" << endl;
+    ret = -1;
+    Exchange(pva,pvb);
+    Exchange(detsa,detsb);
+    Exchange(dets1,dets2);
+    Exchange(tt1,tt2);
+    dets1=-dets1;
+    dets2=-dets2;
+    detsa=-detsa;
+    detsb=-detsb;
+
+    if (ToSwap)
+    {
+      if (dets2 < 0) {// haut
+        dets1 = (ToSwap ? dets1 : detsa) ;
+        detsa = dets2; 
+        tt1 =  Previous(tt2) ;}
+      else if (dets2 > 0){// bas 
+        dets1 = (ToSwap ? dets1 : detsb) ;
+        detsb =  dets2;
+        if(!ToSwap) tt1 =  Next(tt2);
+       }
+      else {// on a fin ???
+        tt1 = Next(tt2);
+        ret =0;}
+    }
+  }
+  return ret;
+}
+
+int ForceEdge(Vertex &a, Vertex & b,TriangleAdjacent & taret)  
+{ 
+#ifdef DEBUG
+ restart: // for debug 
+#endif
+  int NbSwap =0;
+  assert(a.t && b.t); // the 2 vertex is in a mesh 
+  int k=0;
+  taret=TriangleAdjacent(0,0); // erreur 
+  
+  TriangleAdjacent tta(a.t,EdgesVertexTriangle[a.vint][0]);
+  Vertex   *v1, *v2 = tta.EdgeVertex(0),*vbegin =v2;
+  // we turn around a in the  direct sens  
+   
+  Icoor2 det2 = v2 ? det(*v2,a,b): -1 , det1;
+  if(v2) // normal case 
+    det2 = det(*v2,a,b);
+  else { // no chance infini vertex try the next
+    tta= Previous(Adj(tta));
+    v2 = tta.EdgeVertex(0);
+    vbegin =v2;
+    assert(v2);
+    det2 = det(*v2,a,b);
+ //   cout << " No Change try the next" << endl;
+  }
+
+#ifdef DRAWING1
+  a.MoveTo();b.LineTo();
+#endif
+
+  while (v2 != &b) {
+    TriangleAdjacent tc = Previous(Adj(tta));    
+    v1 = v2; 
+    v2 = tc.EdgeVertex(0);
+    det1 = det2;
+#ifdef DEBUG
+    assert( v1 ==  tta.EdgeVertex(0));
+    assert( &a ==  tc.EdgeVertex(1) );
+#endif
+    det2 =  v2 ? det(*v2,a,b): det2; 
+    
+    if((det1 < 0) && (det2 >0)) { 
+      // try to force the edge 
+      Vertex * va = &a, *vb = &b;
+      tc = Previous(tc);
+      assert ( v1 && v2);
+      Icoor2 detss = 0,l=0,ks;
+      // cout << "Real ForcingEdge " << *va << *vb << detss << endl;
+#ifdef DEBUG
+      Icoor2 dettt1 =  det(*v1,a,b);
+      Icoor2 dettt2 =  det(*v2,a,b);
+
+      if (!(dettt1==det1 && dettt2==det2))
+	{
+	  assert(ForDebugging==0);
+          ForDebugging=1;
+	  goto restart;
+	}
+	
+#endif 
+      while ((ks=SwapForForcingEdge(  va,  vb, tc, detss, det1,det2,NbSwap)))
+	if(l++ > 10000000) {
+	  cerr << " Loop in forcing Egde AB" 
+               <<"\n vertex A " << a 
+               <<"\n vertex B " <<  b 
+               <<"\n nb de swap " << NbSwap 
+               <<"\n nb of try  swap too big = " <<  l << " gearter than " <<  1000000 << endl;
+   
+         if ( CurrentTh ) 
+            cerr << " vertex number " << CurrentTh->Number(a) << " " <<  CurrentTh->Number(b) << endl;
+#ifdef DEBUG
+	  ForDebugging = 1;
+#endif
+#ifdef DRAWING1
+          if (  CurrentTh ) {
+	    reffecran();
+            couleur(6);
+	    CurrentTh->Draw();
+            couleur(1);
+	    penthickness(10);
+	    a.MoveTo();b.LineTo();
+	    penthickness(1);
+	    CurrentTh->inquire();
+            couleur(6);
+	    l=0;
+	    reffecran();
+            while (ks=SwapForForcingEdge(  va,  vb, tc, detss, det1,det2,NbSwap) && (l++ < 1000))
+             cerr << " " << CurrentTh->Number(tc.EdgeVertex(0))<<" " <<CurrentTh->Number(tc.EdgeVertex(1)) << " ";
+	  }
+#endif	  
+	  MeshError(990);
+	}
+      Vertex *aa = tc.EdgeVertex(0), *bb = tc.EdgeVertex(1);
+      if ((( aa == &a ) && (bb == &b)) ||  ((bb ==  &a ) && (aa == &b))) {
+	tc.SetLock();
+	a.Optim(1,0);
+	b.Optim(1,0);
+	taret = tc;
+	return NbSwap;
+      }
+      else 
+      {
+	  taret = tc;
+	  return -2; // error  boundary is crossing
+/*	  cerr << "Fatal Error  boundary is crossing  ";
+	  if(CurrentTh)
+	  {
+	      cerr << " edge:  [" << CurrentTh->Number(a) << ", " << CurrentTh->Number(b) <<  " ] and [ ";
+	      cerr    << CurrentTh->Number(aa) << " " << CurrentTh->Number(bb) << " ] " << endl;
+	  }
+	  MeshError(991);
+*/	  
+      }
+    }
+    tta = tc;
+    assert(k++<2000);
+    if ( vbegin == v2 ) return -1;// error 
+  }
+
+  tta.SetLock();
+  taret=tta;
+  a.Optim(1,0);
+  b.Optim(1,0);
+  return NbSwap; 
+}
+
+
+int Triangle::swap(Int2 a,int koption){
+#ifdef DEBUG
+  if(a &4 ) return 0;// arete lock 
+  int munswap1 = a/4;
+  a &=3;
+#else
+ if(a/4 !=0) return 0;// arete lock or MarkUnSwap
+#endif
+
+   Triangle *t1=this,*t2=at[a];// les 2 triangles adjacent
+   Int1 a1=a,a2=aa[a];// les 2 numero de l arete dans les 2 triangles
+#ifdef DEBUG
+  if(a2 & 4) return 0; // arete lock
+  int munswap2 = a2/4;
+  a2 &= 3;
+#else
+  if(a2/4 !=0) return 0; // arete lock or MarkUnSwap
+#endif
+  
+   Vertex  *sa=t1->ns[VerticesOfTriangularEdge[a1][0]];
+   Vertex  *sb=t1->ns[VerticesOfTriangularEdge[a1][1]];
+   Vertex  *s1=t1->ns[OppositeVertex[a1]];
+   Vertex  *s2=t2->ns[OppositeVertex[a2]];
+
+#ifdef DEBUG
+  assert ( a >= 0 && a < 3 );  
+#endif
+  
+   Icoor2 det1=t1->det , det2=t2->det ;
+   Icoor2 detT = det1+det2;
+   Icoor2 detA = Abs(det1) + Abs(det2);
+   Icoor2 detMin = Min(det1,det2);
+
+   int OnSwap = 0;       
+   // si 2 triangle infini (bord) => detT = -2;
+   if (sa == 0) {// les deux triangles sont frontieres
+     det2=bamg::det(s2->i,sb->i,s1->i);
+     OnSwap = det2 >0;}
+   else if (sb == 0) { // les deux triangles sont frontieres
+     det1=bamg::det(s1->i,sa->i,s2->i);
+     OnSwap = det1 >0;}
+   else if(( s1 != 0) && (s2 != 0) ) {
+     det1 = bamg::det(s1->i,sa->i,s2->i);
+     det2 = detT - det1;
+     OnSwap = (Abs(det1) + Abs(det2)) < detA;
+   
+     Icoor2 detMinNew=Min(det1,det2);
+     //     if (detMin<0 && (Abs(det1) + Abs(det2) == detA)) OnSwap=BinaryRand();// just for test   
+     if (! OnSwap &&(detMinNew>0)) {
+       OnSwap = detMin ==0;
+       if (! OnSwap) {
+	 int  kopt = koption;
+        while (1)
+	 if(kopt) {
+	 // critere de Delaunay pure isotrope
+	  Icoor2 xb1 = sb->i.x - s1->i.x,
+	   x21 = s2->i.x - s1->i.x,
+	   yb1 = sb->i.y - s1->i.y,
+	   y21 = s2->i.y - s1->i.y,
+	   xba = sb->i.x - sa->i.x, 
+	   x2a = s2->i.x - sa->i.x,
+	   yba = sb->i.y - sa->i.y,
+	   y2a = s2->i.y - sa->i.y;
+	  double
+	   cosb12 =  double(xb1*x21 + yb1*y21),
+	   cosba2 =  double(xba*x2a + yba*y2a) ,
+	   sinb12 = double(det2),
+	   sinba2 = double(t2->det);
+
+	 
+	 // angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2)
+	 OnSwap =  ((double) cosb12 * (double)  sinba2) <  ((double) cosba2 * (double) sinb12);
+//  	 if(CurrentTh) 
+//  	   cout << "swap " << CurrentTh->Number(sa) << " " << CurrentTh->Number(sb) << " " ;
+//  	 cout <<  cosb12 << " " <<  sinba2 << " "  <<  cosba2 << " " << sinb12 
+//  	      << " Onswap = " <<  OnSwap << endl;
+	  break;
+	 }
+	 else 
+	   {	
+	     // critere de Delaunay anisotrope 
+	     Real8 som;
+	     I2 AB=(I2) *sb - (I2) *sa;
+	     I2 MAB2=((I2) *sb + (I2) *sa);
+	     R2 MAB(MAB2.x*0.5,MAB2.y*0.5);
+	     I2 A1=(I2) *s1 - (I2) *sa;
+	     I2 D = (I2) * s1 - (I2) * sb ;
+	     R2 S2(s2->i.x,s2->i.y);
+	     R2 S1(s1->i.x,s1->i.y);
+	     {
+	       Metric M=s1->m;
+	       R2 ABo = M.Orthogonal(AB);
+	       R2 A1o = M.Orthogonal(A1);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       if (Abs(d) > dd*1.e-3) {
+		 R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 som  = M(C - S2)/M(C - S1);
+	       } else 
+		{kopt=1;continue;}
+		
+	     }
+	     {
+	       Metric M=s2->m;
+	       R2 ABo = M.Orthogonal(AB);
+	       R2 A1o = M.Orthogonal(A1);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       if(Abs(d) > dd*1.e-3) {
+		 R2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 som  += M(C - S2)/M(C -  S1);
+	       } else 
+		{kopt=1;continue;}
+	     }
+	     OnSwap = som < 2;
+	     break;
+	 }
+  
+       } // OnSwap 
+     } // (! OnSwap &&(det1 > 0) && (det2 > 0) )
+   }
+#ifdef  DEBUG1   
+   if (OnSwap &&  ( munswap1  || munswap2)) {
+     cout << " erreur Mark unswap T " << CurrentTh->Number(t1) << " " <<  CurrentTh->Number(t2) << endl
+	  << *t1 << endl
+          << *t2 << endl;
+     return 0;
+   }
+#endif 
+   if( OnSwap ) 
+       bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2);
+   else {
+     NbUnSwap ++;
+      t1->SetMarkUnSwap(a1);     
+   }
+   return OnSwap;
+}
+
+Real8  Vertex::Smoothing(Triangles & Th,const Triangles & BTh,Triangle  * & tstart ,Real8 omega)
+{
+#ifdef DEBUG  
+    Int4 NbSwap =0;
+#endif
+   Vertex * s  = this;
+  Vertex &vP = *s,vPsave=vP;
+  //  if (vP.on) return 0;// Don't move boundary vertex  
+  
+   Triangle * tbegin= t , *tria = t , *ttc;
+ 
+   int k=0,kk=0,j = EdgesVertexTriangle[vint][0],jc;
+  R2 P(s->r),PNew(0,0);
+  //  cout << BTh.quadtree << " " <<  BTh.quadtree->root << endl;
+  // assert(BTh.quadtree && BTh.quadtree->root);
+  do {
+	k++; 
+	
+#ifdef DEBUG
+    assert( s == & (*tria)[VerticesOfTriangularEdge[j][1]] );
+    assert( tria->det >0);
+#endif
+    if (!tria->Hidden(j))
+      {
+	Vertex &vQ = (*tria)[VerticesOfTriangularEdge[j][0]]; 
+	
+	R2 Q = vQ,QP(P-Q);
+	Real8 lQP = LengthInterpole(vP,vQ,QP);
+	PNew += Q+QP/Max(lQP,1e-20);
+	kk ++;
+      }
+     ttc =  tria->TriangleAdj(j);
+     jc = NextEdge[tria->NuEdgeTriangleAdj(j)];
+     tria = ttc;
+     j = NextEdge[jc];
+     assert(k<2000);
+  } while ( tbegin != tria); 
+  if (kk<4) return 0;
+  PNew = PNew/(Real8)kk;
+  R2 Xmove((PNew-P)*omega);
+  PNew = P+Xmove;
+  Real8 delta=Norme2_2(Xmove); 
+  
+  
+  // 
+  Icoor2 deta[3];
+  I2 IBTh  = BTh.toI2(PNew);
+  
+  tstart=BTh.FindTriangleContening(IBTh,deta,tstart);  
+  
+  if (tstart->det <0) 
+    { // outside
+      double ba,bb;
+      TriangleAdjacent edge= CloseBoundaryEdge(IBTh,tstart,ba,bb) ;
+      tstart = edge;
+      vP.m= Metric(ba,*edge.EdgeVertex(0),bb,*edge.EdgeVertex(1));
+    }
+  else 
+    { // inside
+      Real8   aa[3];
+      Real8 s = deta[0]+deta[1]+deta[2];
+      aa[0]=deta[0]/s;
+      aa[1]=deta[1]/s;
+      aa[2]=deta[2]/s;
+      vP.m = Metric(aa,(*tstart)[0],(*tstart)[1],(*tstart)[2]);
+    }
+  
+  // recompute the det of the triangle
+  vP.r = PNew;
+  
+  vP.i = Th.toI2(PNew);
+
+  Vertex vPnew = vP;
+  
+  int ok=1;
+  int loop=1;
+  k=0;
+  while (ok) 
+    {
+      ok =0;
+      do {
+	k++; 
+	double detold = tria->det;
+	tria->det =  bamg::det( (*tria)[0],(*tria)[1]  ,(*tria)[2]);
+	if (loop) 
+	  {
+	    Vertex *v0,*v1,*v2,*v3;
+	    if (tria->det<0) ok =1;			       
+	    else if (tria->Quadrangle(v0,v1,v2,v3))
+	      {
+		vP = vPsave;
+		Real8 qold =QuadQuality(*v0,*v1,*v2,*v3);
+		vP = vPnew;
+		Real8 qnew = QuadQuality(*v0,*v1,*v2,*v3);
+		if (qnew<qold) ok = 1;
+	      }
+	    else if ( (double)tria->det < detold/2 ) ok=1;
+	    
+	  }
+        tria->SetUnMarkUnSwap(0);
+        tria->SetUnMarkUnSwap(1);
+        tria->SetUnMarkUnSwap(2);
+	ttc =  tria->TriangleAdj(j);
+	jc = NextEdge[tria->NuEdgeTriangleAdj(j)];
+	tria = ttc;
+	j = NextEdge[jc];
+	assert(k<2000);
+      } while ( tbegin != tria); 
+      if (ok && loop) vP=vPsave; // no move 
+      loop=0;
+    }
+  return delta;
+}
+
+
+
+
+void Triangles::Add( Vertex & s,Triangle * t, Icoor2 * det3) 
+{
+  // -------------------------------------------
+  //             s2
+  //                                            !
+  //             /|\                            !
+  //            / | \                           !
+  //           /  |  \                          !
+  //    tt1   /   |   \ tt0                     !
+  //         /    |s   \                        !
+  //        /     .     \                       !
+  //       /  .      `   \                      !
+  //      / .           ` \                     !
+  //      ----------------                      !
+  //   s0       tt2       s1
+  //-------------------------------------------- 
+  
+  Triangle * tt[3]; // the 3 new Triangles
+  Vertex &s0 = (* t)[0], &s1=(* t)[1], &s2=(* t)[2];
+  Icoor2  det3local[3];
+  int infv = &s0 ?  ((  &s1 ? ( &s2  ? -1 : 2) : 1  )) : 0;
+  // infv = ordre of the infini vertex (null)
+   int nbd0 =0; // number of zero det3
+   int izerodet=-1,iedge; // izerodet = egde contening the vertex s
+  Icoor2 detOld = t->det;
+  
+  if ( (( infv <0 ) && (detOld <0)) ||  (( infv >=0  ) && (detOld >0)) ) 
+    {
+      cerr << "  infv " << infv << " det = " << detOld << endl;
+      cerr << Number(s) << " "<< Number(s0) << " "  
+	   << Number(s1) << " "  << Number(s2) << endl;
+      MeshError(3);
+    }
+  
+  // if det3 do not exist then constuct det3
+  if (!det3) { 
+    det3 = det3local; // alloc 
+    if ( infv<0 ) {
+      det3[0]=bamg::det(s ,s1,s2);
+      det3[1]=bamg::det(s0,s ,s2);
+      det3[2]=bamg::det(s0,s1,s );}
+    else { 
+      // one of &s1  &s2  &s0 is NULL so (&si || &sj) <=> !&sk
+      det3[0]=  &s0 ? -1  : bamg::det(s ,s1,s2) ;
+      det3[1]=  &s1 ? -1 : bamg::det(s0,s ,s2) ;
+      det3[2]=  &s2 ? -1 : bamg::det(s0,s1,s ) ;}}
+
+  
+  if (!det3[0]) izerodet=0,nbd0++;
+  if (!det3[1]) izerodet=1,nbd0++;
+  if (!det3[2]) izerodet=2,nbd0++;
+  
+  if  (nbd0 >0 ) // point s on a egde or on a vertex 
+  {
+    if (nbd0 == 1) {
+      iedge = OppositeEdge[izerodet];
+      TriangleAdjacent ta = t->Adj(iedge);
+
+#ifdef DEBUG1      
+      cout << " the point " << Number(s) << " is the edge " <<  izerodet 
+	   << " of " << Number(t)	   << " det3 = " 
+	   << det3[0] << " " <<  det3[1] << " " <<  det3[2] << " " <<  endl;
+      cout  << " ta = "  <<  ta << "ta->det =" << ((Triangle*) ta)->det  
+	    << " "<< t->det<< endl;
+#endif
+
+      // the point is on the edge 
+      // if the point is one the boundary 
+      // add the point in outside part 
+      if ( t->det >=0) { // inside triangle
+	if ((( Triangle *) ta)->det < 0 ) {
+	  // add in outside triangle 
+	  Add(s,( Triangle *) ta);
+	  return;}
+      }}
+    else {
+      cerr << " bug  " << nbd0 <<endl;
+      cerr << " Bug double points in " << endl ;
+      cerr << " s = " << Number(s) << " " <<  s << endl;
+      cerr << " s0 = "<< Number(s0) << " "  << s0 << endl;
+      cerr << " s1 = "<< Number(s1) << " "  << s1 << endl;
+      cerr << " s2 = "<< Number(s2) << " "  << s2 << endl;
+      MeshError(5,this);}
+  }
+  // remove de MarkUnSwap edge
+  t->SetUnMarkUnSwap(0);     
+  t->SetUnMarkUnSwap(1);     
+  t->SetUnMarkUnSwap(2);
+
+  tt[0]= t;
+  tt[1]= &triangles[nbt++];
+  tt[2]= &triangles[nbt++];
+  
+  if (nbt>nbtx) {
+    cerr << " No enougth triangles " << endl;
+    MeshError(999,this);
+  }
+
+  *tt[1]=   *tt[2]= *t;
+// gestion of the link
+   tt[0]->link=tt[1];
+   tt[1]->link=tt[2]; 
+  
+  (* tt[0])(OppositeVertex[0])=&s;
+  (* tt[1])(OppositeVertex[1])=&s;
+  (* tt[2])(OppositeVertex[2])=&s;
+
+  tt[0]->det=det3[0];
+  tt[1]->det=det3[1];
+  tt[2]->det=det3[2];         
+
+  //  update adj des triangles externe 
+  tt[0]->SetAdjAdj(0);
+  tt[1]->SetAdjAdj(1);
+  tt[2]->SetAdjAdj(2);
+  //  update des adj des 3 triangle interne
+  const int i0 = 0;
+  const int i1= NextEdge[i0];
+  const int i2 = PreviousEdge[i0];
+
+  tt[i0]->SetAdj2(i2,tt[i2],i0);
+  tt[i1]->SetAdj2(i0,tt[i0],i1);
+  tt[i2]->SetAdj2(i1,tt[i1],i2);
+  
+  tt[0]->SetTriangleContainingTheVertex();
+  tt[1]->SetTriangleContainingTheVertex();
+  tt[2]->SetTriangleContainingTheVertex();
+ 
+ 
+  // swap if the point s is on a edge
+  if(izerodet>=0) {
+    //  cout << " the point s is on a edge =>swap " << iedge << " "  << *tt[izerodet] << endl;
+    int rswap =tt[izerodet]->swap(iedge);
+    
+    if (!rswap) 
+     {
+       cout << " Pb swap the point s is on a edge =>swap " << iedge << " "  << *tt[izerodet] << endl;
+#ifdef DRAWING
+       if(  CurrentTh &&  withrgraphique) 
+        {
+       reffecran();
+       
+       DrawMark(s.r);
+          CurrentTh->inquire();
+       DrawMark(s.r);
+       rattente(1); 
+        }      
+#endif
+     }
+    assert(rswap);
+  }
+ 
+#ifdef DEBUG 
+  tt[0]->check();
+  tt[1]->check();
+  tt[2]->check();
+#endif
+#ifdef DRAWING1 
+  tt[0]->Draw();
+  tt[1]->Draw();
+  tt[2]->Draw();
+#endif
+  
+}
+
+
+Int4  Triangles::SplitInternalEdgeWithBorderVertices()
+{
+  Int4 NbSplitEdge=0;
+  SetVertexFieldOn();  
+  Int4 it;
+  Int4 nbvold=nbv;
+  for (it=0;it<nbt;it++)
+    {
+      Triangle &t=triangles[it];
+      if (t.link)
+	for (int j=0;j<3;j++)
+	  if(!t.Locked(j) && !t.Hidden(j)){
+	    Triangle &tt = *t.TriangleAdj(j);
+	    if ( &tt && tt.link && it < Number(tt)) 
+	      { // an internal edge 
+		Vertex &v0 = t[VerticesOfTriangularEdge[j][0]];
+		Vertex &v1 = t[VerticesOfTriangularEdge[j][1]];
+		if (v0.on && v1.on)
+		  {
+		    R2 P= ((R2) v0 + (R2) v1)*0.5;
+		    if ( nbv<nbvx) {
+		      vertices[nbv].r = P;
+		      vertices[nbv++].m = Metric(0.5,v0.m,0.5,v1.m);
+		      vertices[nbv].ReferenceNumber=0;
+		      vertices[nbv].DirOfSearch = NoDirOfSearch ;
+		    }
+		    NbSplitEdge++;
+		    if (verbosity>7)
+		      cout <<" Internal edge with two vertices on boundary" 
+			   << Number(v0) << " " << Number(v1) << " by " <<  endl;
+		  }
+	      }
+	  }
+    }
+  ReMakeTriangleContainingTheVertex();    
+  if (nbvold!=nbv) 
+    {
+      Int4  iv = nbvold;
+      Int4 NbSwap = 0;
+      Icoor2 dete[3];  
+      for (Int4 i=nbvold;i<nbv;i++) 
+	{// for all the new point
+	  Vertex & vi = vertices[i];
+	  vi.i = toI2(vi.r);
+      vi.r = toR2(vi.i);
+      //      if (!quadtree->ToClose(vi,seuil,hi,hj)) {
+      // a good new point 
+      vi.ReferenceNumber=0; 
+      vi.DirOfSearch =NoDirOfSearch;
+      //	cout << " Add " << Number(vi) << " " << vi 
+      // << "   " <<  Number(vi) << " <--> " << Number(vi) <<endl;
+      Triangle *tcvi = FindTriangleContening(vi.i,dete);
+      if (tcvi && !tcvi->link) {
+	cout << i <<  " PB insert point " << Number(vi) << vi << Number(vi) 
+	     << " tcvi = " << tcvi << " " << tcvi->link << endl;
+	cout << (*tcvi)[1] <<  (*tcvi)[2] << endl;
+	tcvi = FindTriangleContening(vi.i,dete);
+	cout << (*tcvi)[1] <<  (*tcvi)[2] << endl;
+#ifdef DRAWING1
+	inquire();
+	penthickness(5);
+	DrawMark(vi.r);
+	penthickness(1);
+	inquire();
+#endif
+	
+	MeshError(1001,this);
+      }
+      
+      
+      quadtree->Add(vi);
+#ifdef DRAWING1
+      DrawMark(vi.r);
+#endif
+      assert (tcvi && tcvi->det >= 0) ;// internal 
+      Add(vi,tcvi,dete);
+      NbSwap += vi.Optim(1);          
+      iv++;
+      //      }
+	}
+      if (verbosity>3) 
+	{
+	  cout << "    Nb Of New Point " << iv ;
+	  cout << " Nb swap = " << NbSwap << " to  split internal edges with border vertices" ;}
+      
+      nbv = iv;
+    }
+  if (NbSplitEdge >  nbv-nbvold)
+  {
+    cout << " Warning not enough vertices  to split all internal edges "  << endl
+	 << "    we lost " << NbSplitEdge - ( nbv-nbvold) << " Edges Sorry " << endl;
+      warning = 2;
+  }
+  if (verbosity>2)
+  cout << "SplitInternalEdgeWithBorderVertices: Number of splited edge " << NbSplitEdge << endl;
+  return  NbSplitEdge;
+}
+Int4 Triangles::InsertNewPoints(Int4 nbvold,Int4 & NbTSwap)
+ {
+  Real8 seuil= 1.414/2 ;// for two close point 
+  Int4 i;
+ // insertion part --- 
+
+  const Int4 nbvnew = nbv-nbvold;
+  if (verbosity>5) 
+    cout << "    Try to Insert the " <<nbvnew<< " new points " << endl;  
+  Int4 NbSwap=0;
+  Icoor2 dete[3];
+  
+  // construction d'un ordre aleatoire 
+  if (! nbvnew) 
+    return 0; 
+  if (nbvnew) {
+  const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv)  ;
+  Int4 k3 = rand()%nbvnew ; 
+  for (Int4 is3=0; is3<nbvnew; is3++) {
+     Int4 j = nbvold +(k3 = (k3 + PrimeNumber)% nbvnew);
+     Int4 i = nbvold+is3; 
+    ordre[i]= vertices + j;
+    ordre[i]->ReferenceNumber=i;
+  }
+  // be carefull 
+  Int4  iv = nbvold;
+  for (i=nbvold;i<nbv;i++) 
+    {// for all the new point
+      Vertex & vi = *ordre[i];
+      vi.i = toI2(vi.r);
+      vi.r = toR2(vi.i);
+      Real4 hx,hy;
+      vi.m.Box(hx,hy);
+      Icoor1 hi=(Icoor1) (hx*coefIcoor),hj=(Icoor1) (hy*coefIcoor);
+      if (!quadtree->ToClose(vi,seuil,hi,hj)) 
+        {
+			// a good new point 
+			Vertex & vj = vertices[iv];
+			Int4 j = vj.ReferenceNumber; 
+			assert( &vj== ordre[j]);
+			if(i!=j)
+			  { //  for valgring 
+			    Exchange(vi,vj);
+			    Exchange(ordre[j],ordre[i]);
+			  }
+		      vj.ReferenceNumber=0; 
+			//	cout << " Add " << Number(vj) << " " << vj 
+			// << "   " <<  Number(vi) << " <--> " << Number(vj) <<endl;
+			Triangle *tcvj = FindTriangleContening(vj.i,dete);
+			if (tcvj && !tcvj->link) 
+			 {
+			  cerr << i <<  " PB insert point " << Number(vj) << vj << Number(vi) 
+			       << " tcvj = " << tcvj << " " << tcvj->link << endl;
+			  cerr << (*tcvj)[1] <<  (*tcvj)[2] << endl;
+			  tcvj = FindTriangleContening(vj.i,dete);
+			  cout << (*tcvj)[1] <<  (*tcvj)[2] << endl;
+#ifdef DRAWING1
+		 	  inquire();
+			  penthickness(5);
+			  DrawMark(vj.r);
+			  penthickness(1);
+			  
+			  inquire();
+#endif
+	  
+	          MeshError(1001,this);
+	         }
+	
+	
+	        quadtree->Add(vj);
+#ifdef DRAWING1
+	        DrawMark(vj.r);
+#endif
+			assert (tcvj && tcvj->det >= 0) ;// internal 
+			Add(vj,tcvj,dete);
+			NbSwap += vj.Optim(1);          
+			iv++;
+         }
+    } 
+  if (verbosity>3) {
+    cout << "    Nb Of New Point " << iv << " Nb Of To close Points " << nbv-iv ;
+    cout << " Nb swap = " << NbSwap << " after " ;}
+
+    nbv = iv;
+  }
+
+#ifdef DRAWING1
+  inquire();
+#endif
+
+  for (i=nbvold;i<nbv;i++) 
+    NbSwap += vertices[i].Optim(1);  
+   if (verbosity>3) 
+     cout << " NbSwap = " <<  NbSwap << endl;
+
+
+  NbTSwap +=  NbSwap ;
+#ifdef DEBUG
+{  
+  Int4 NbErr=0;
+  Int4 i;
+  for (i=0;i<nbt;i++)
+    if (triangles[i].link) 
+      {
+      double dd =Det(triangles[i][1].r-triangles[i][0].r,triangles[i][2].r-triangles[i][0].r);
+      if(dd <=0) 
+	{
+	  NbErr++;
+	  cerr << " det triangle i " << i << " = " << triangles[i].det ;
+	  cerr << " det triangle  " << dd ;
+	    cerr << " Les trois sommets " ;
+	    cerr << Number(triangles[i][0]) << " "  << Number(triangles[i][1]) << " " 
+		 << Number(triangles[i][2]) << endl;
+	    cerr << "I2     " <<triangles[i][0].r << triangles[i][1].r << triangles[i][2].r << endl;
+	    cerr << "R2     " << triangles[i][0].i << triangles[i][1].i << triangles[i][2].i << endl;
+	    cerr << "I2-R2 =" <<toR2(triangles[i][0].i)-triangles[i][0].r 
+		 << toR2(triangles[i][1].i)-triangles[i][1].r
+		 << toR2(triangles[i][2].i)-triangles[i][2].r << endl;
+	}
+      }
+  if(NbErr) { 
+#ifdef DRAWING
+    Int4 kkk=0;
+    //  UnMarkUnSwapTriangle();
+    //  for (i=0;i<nbv;i++)
+    //  kkk += vertices[i].Optim(0);
+    if(verbosity>3)
+    cout << "    Nb of swap louche " << kkk << endl;
+    if(kkk) {
+  for (i=0;i<nbt;i++)
+    if (triangles[i].link) 
+      {
+      double dd =Det(triangles[i][1].r-triangles[i][0].r,triangles[i][2].r-triangles[i][0].r);
+      if(dd <=0) 
+	{
+	  NbErr++;
+	  cerr << " xxxdet triangle i " << i << " = " << triangles[i].det ;
+	  cerr << " xxxdet triangle  " << dd ;
+	    cerr << " xxxLes trois sommets " ;
+	    cerr << Number(triangles[i][0]) << " "  << Number(triangles[i][1]) << " " 
+		 << Number(triangles[i][2]) << endl;
+	    cerr << triangles[i][0].r << triangles[i][1].r << triangles[i][2].r << endl;
+	    cerr << triangles[i][0].i << triangles[i][1].i << triangles[i][2].i << endl;
+	}
+      } }
+   inquire();
+#endif
+    //   MeshError(11);
+  }
+  
+}
+#endif
+  return nbv-nbvold;
+ 
+ }
+void  Triangles::NewPoints(Triangles & Bh,int KeepBackVertex)
+{ // Triangles::NewPoints
+  Int4 nbtold(nbt),nbvold(nbv);
+  if (verbosity>2) 
+    cout << "  -- Triangles::NewPoints ";
+  if (verbosity>3)cout <<  " nbv (in)  on Boundary  = " << nbv  <<endl;
+  Int4 i,k;
+  int j;
+  Int4 *first_np_or_next_t = new Int4[nbtx];
+  Int4 NbTSwap =0;
+//    insert old point
+    nbtold = nbt;
+    
+  if (KeepBackVertex && (&Bh != this) && (nbv+Bh.nbv< nbvx)) 
+   {
+  //   Bh.SetVertexFieldOn();
+     for (i=0;i<Bh.nbv;i++)
+      { 
+        Vertex & bv = Bh[i];
+        if (!bv.on) {
+          vertices[nbv].r = bv.r;
+          vertices[nbv++].m = bv.m;}
+      }
+     int nbv1=nbv;
+     Bh.ReMakeTriangleContainingTheVertex();     
+     InsertNewPoints(nbvold,NbTSwap)   ;            
+     if (verbosity>2)
+        cout <<  "      (Nb of Points from background mesh  = " 
+             << nbv-nbvold  << " / " << nbv1-nbvold << ")" << endl;
+   }  
+  else 
+    Bh.ReMakeTriangleContainingTheVertex();     
+
+  Triangle *t;
+  // generation of the list of next Triangle 
+  // at 1 time we test all the triangles
+  Int4 Headt =0,next_t;
+  for(i=0;i<nbt;i++)
+    first_np_or_next_t[i]=-(i+1);
+  // end list i >= nbt 
+  // the list of test triangle is 
+  // the next traingle on i is  -first_np_or_next_t[i]
+  int iter=0;
+  // Big loop 
+  do {
+    iter++;
+    nbtold = nbt;
+    nbvold = nbv;
+#ifdef DRAWING1  
+  inquire();
+#endif  
+
+  // default size of  IntersectionTriangle
+
+  i=Headt;
+  next_t=-first_np_or_next_t[i];
+  for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]) 
+    { // for each triangle  t
+      // we can change first_np_or_next_t[i]
+      //      cout << " Do the triangle " << i << " Next_t=" << next_t << endl;
+      assert(i>=0 && i < nbt );
+      first_np_or_next_t[i] = iter; 
+      for(j=0;j<3;j++)
+	{ // for each edge 
+	  TriangleAdjacent tj(t,j);
+	  Vertex & vA = * tj.EdgeVertex(0);
+	  Vertex & vB = * tj.EdgeVertex(1);
+	  
+	  if (!t->link) continue;// boundary
+	  if (t->det <0) continue;
+	  if (t->Locked(j)) continue;
+
+	  TriangleAdjacent tadjj = t->Adj(j);	  
+	  Triangle * ta= tadjj;
+
+	  if (ta->det <0) continue;	  
+	  
+	  R2 A = vA;
+	  R2 B = vB;
+	  
+	  k=Number(ta);
+	  
+	  if(first_np_or_next_t[k]==iter)  // this edge is done before 
+	    continue; // next edge of the triangle 
+	  
+	  //const Int4 NbvOld = nbv;
+	  lIntTria.SplitEdge(Bh,A,B);
+	  lIntTria.NewPoints(vertices,nbv,nbvx);
+	} // end loop for each edge 
+      
+    }// for triangle   
+  
+#ifdef DRAWING1
+  cout << "  -------------------------------------------- " << endl;
+  inquire();
+  reffecran();
+  Draw();
+  penthickness(2);
+#endif
+
+   if (!InsertNewPoints(nbvold,NbTSwap)) 
+     break;
+     
+   for (i=nbtold;i<nbt;i++)
+     first_np_or_next_t[i]=iter;
+
+  Headt = nbt; // empty list 
+  for (i=nbvold;i<nbv;i++) 
+    { // for all the triangle contening the vertex i
+       Vertex * s  = vertices + i;
+       TriangleAdjacent ta(s->t, EdgesVertexTriangle[s->vint][1]);
+       Triangle * tbegin= (Triangle*) ta;
+       Int4 kt;
+       do { 
+	 kt = Number((Triangle*) ta);
+	 if (first_np_or_next_t[kt]>0) 
+	   first_np_or_next_t[kt]=-Headt,Headt=kt;
+	 assert( ta.EdgeVertex(0) == s);
+	 ta = Next(Adj(ta));
+       } while ( (tbegin != (Triangle*) ta)); 
+    }   
+   
+  } while (nbv!=nbvold);
+  
+  delete []  first_np_or_next_t;
+
+  Int4 NbSwapf =0,NbSwp;
+  
+  // bofbof 
+  
+  
+  NbSwp = NbSwapf;
+  for (i=0;i<nbv;i++)
+    NbSwapf += vertices[i].Optim(0);
+  /*
+  for (i=0;i<nbv;i++)
+    NbSwapf += vertices[i].Optim(0);
+  for (i=0;i<nbv;i++)
+    NbSwapf += vertices[i].Optim(0);
+  for (i=0;i<nbv;i++)
+    NbSwapf += vertices[i].Optim(0);
+  for (i=0;i<nbv;i++)
+    NbSwapf += vertices[i].Optim(0);
+    */
+  NbTSwap +=  NbSwapf ;
+  if (verbosity>3) cout << "   " ;
+  if (verbosity>2) 
+     cout << " Nb Of Vertices =" << nbv << " Nb of triangles = " << nbt-NbOutT 
+	  << " NbSwap final = " << NbSwapf << " Nb Total Of Swap = " << NbTSwap << endl;
+
+
+}
+
+void  Triangles::NewPointsOld(Triangles & Bh)
+{ // Triangles::NewPointsOld
+  Real8 seuil= 0.7 ;// for two neart point 
+  if (verbosity>1) 
+    cout << " begin :  Triangles::NewPointsOld " << endl;
+  Int4 i,k;
+  int j;
+  Int4 BeginNewPoint[3];
+  Int4 EndNewPoint[3];
+#ifdef TRACETRIANGLE
+  Int4 trace=0;
+#endif
+  int step[3];
+  Int4 *first_np_or_next_t = new Int4[nbtx];
+  Int4 ColorEdge[3];
+  Int4 color=-1;
+  Triangle *t;
+  // generation of the list of next Triangle 
+  // at 1 time we test all the triangles
+  Int4 Headt =0,next_t;
+  for(i=0;i<nbt;i++)
+    first_np_or_next_t[i]=-(i+1);
+  // end list i >= nbt 
+  // the list of test triangle is 
+  // the next Triangle on i is  -first_np_or_next_t[i]
+  Int4 nbtold,nbvold;
+
+  // Big loop 
+  do {
+    nbtold = nbt;
+    nbvold = nbv;
+#ifdef DRAWING1  
+  inquire();
+#endif  
+
+  // default size of  IntersectionTriangle
+
+  i=Headt;
+  next_t=-first_np_or_next_t[i];
+  for(t=&triangles[i];i<nbt;t=&triangles[i=next_t],next_t=-first_np_or_next_t[i]) 
+    { // for each triangle  t
+      // we can change first_np_or_next_t[i]
+#ifdef TRACETRIANGLE
+      trace =  TRACETRIANGLE <0 ? 1 : i == TRACETRIANGLE;
+#endif
+      //      cout << " Do the triangle " << i << " Next_t=" << next_t << endl;
+      assert(i>=0 && i < nbt );
+      first_np_or_next_t[i] = nbv; // to save the fist new point of triangle
+      for(j=0;j<3;j++)
+	{ // for each edge 
+	  TriangleAdjacent tj(t,j);
+	  // color++;// the color is 3i+j
+          color = 3*i + j ;;
+	  ColorEdge[j]=color;
+	  BeginNewPoint[j]=nbv;
+	  EndNewPoint[j]=nbv-1;
+	  step[j]=1;// right sens 
+	  Vertex & vA = * tj.EdgeVertex(0);
+	  Vertex & vB = * tj.EdgeVertex(1);
+	  
+#ifdef TRACETRIANGLE
+	  if(trace) {
+	    cout << " i " << Number(vA) <<" j "<<  Number(vB) 
+		 << " "  << t->Locked(j) ;
+	  }
+#endif
+	  if (!t->link) continue;// boundary
+	  if (t->det <0) continue;
+	  if (t->Locked(j)) continue;
+
+	  TriangleAdjacent tadjj = t->Adj(j);	  
+	  Triangle * ta= tadjj;
+
+	  if (ta->det <0) continue;	  
+	  
+	  R2 A = vA;
+	  R2 B = vB;
+	  
+	  k=Number(ta);
+	  // the 2 opposite vertices 
+	  const Vertex & vC1  =  *tj.OppositeVertex();
+	  const Vertex & vC2 = *tadjj.OppositeVertex();
+	  
+#ifdef TRACETRIANGLE
+	  trace = trace || k == TRACETRIANGLE;
+	  if(trace) {
+	    cout << "Test Arete " << i << " AB = " << A << B 
+		 << "i "  <<Number(vA)<< "j" <<Number(vB); 
+	    cout << " link" <<(int)t->link << " ta=" << Number( ta) 
+		 << " det " <<ta->det ;
+	    cout << " hA = " <<vA.m.h << " hB = " <<vB.m.h ;
+	    cout << " loc " << ta->Locked(j) << endl;
+	  }
+#endif
+	  
+	  if(first_np_or_next_t[k]>0) { // this edge is done before 
+	    // find the color of the edge and begin , end of newpoint
+	     int kk = t->NuEdgeTriangleAdj(j);
+	    assert ((*t)(VerticesOfTriangularEdge[j][0]) == (*ta)(VerticesOfTriangularEdge[kk][1]));
+	    assert ((*t)(VerticesOfTriangularEdge[j][1]) == (*ta)(VerticesOfTriangularEdge[kk][0]));
+	     Int4 kolor =3*k + kk;
+	    ColorEdge[j]=kolor;
+	     Int4 kkk= 1;
+	    step[j]=-1;// other sens 
+	    BeginNewPoint[j]=0;
+	    EndNewPoint[j]=-1; // empty list          
+	    for (Int4 iv=first_np_or_next_t[k];iv<nbv;iv++) 
+	      if (vertices[iv].color > kolor) 
+		break; // the color is passed            
+	      else if (vertices[iv].color == kolor) {
+		EndNewPoint[j]=iv; 
+		if (kkk) // one time test
+		  kkk=0,BeginNewPoint[j]=iv;}
+	    continue; // next edge of the triangle 
+	  } // end  if( k < i) 
+       
+	  
+#ifdef DRAWING1
+	  penthickness(2); Move(A);Line(B);   penthickness(1);
+#endif
+	  const Int4 NbvOld = nbv;
+	  lIntTria.SplitEdge(Bh,A,B);
+	  // Int4 NbvNp =
+	  lIntTria.NewPoints(vertices,nbv,nbvx);
+	  Int4 nbvNew=nbv;
+	  nbv = NbvOld;
+	  for (Int4 iv=NbvOld;iv<nbvNew;iv++) {
+	    vertices[nbv].color = color;
+	    vertices[nbv].ReferenceNumber=nbv;// circular link
+	    R2 C =  vertices[iv].r;
+	    vertices[nbv].r =  C;
+	    vertices[nbv].m =  vertices[iv].m ;
+	    // test if the new point is not to close to the 2 opposite vertex
+	    R2 CC1 = C-vC1 , CC2 = C-vC2;
+	    if (   (  (vC1.m(CC1) + vertices[nbv].m(CC1)) >  seuil)
+		&& (  (vC2.m(CC2) + vertices[nbv].m(CC2)) >  seuil) )
+	      nbv++;
+	  }
+	    
+	  EndNewPoint[j] = nbv-1;
+	} // end loop for each edge 
+
+#ifdef TRACETRIANGLE
+      if(trace) {
+	// verification des point cree 
+	cout << "\n ------------ " << t->link << " " << t->det 
+	     << " b " << BeginNewPoint[0] << " " << BeginNewPoint[1]
+	     << " " << BeginNewPoint[2] << " " 
+	     << " e " << EndNewPoint[0] << " " << EndNewPoint[1] 
+	     << " " << EndNewPoint[2] << " " 
+	     << " s " << step[0] << " " << step[1] << " " << step[2] << " " 
+	     <<  endl;
+      }
+#endif
+
+      if (!t->link) continue;// boundary
+      if (t->det<=0) continue;// outside 
+      //      continue;
+      for(int j0=0;j0<3;j0++)
+	for (Int4 i0= BeginNewPoint[j0]; i0 <= EndNewPoint[j0];i0++)
+	  {
+	   // find the neart  point one the opposite edge 
+           // to compute i1
+	    Vertex & vi0 = vertices[i0];
+	    int kstack = 0;
+	    Int4 stack[10];
+	 //   Int4 savRef[10];
+	    int j1 = j0; 
+	    while (j0 != (j1 = NextEdge[j1])) {//loop on the 2 other edge
+	      // computation of the intersection of edge j1 and DOrto
+	      // take the good sens 
+	      
+	      if (BeginNewPoint[j1]> EndNewPoint[j1])
+	        continue; // 
+              else if (EndNewPoint[j1] - BeginNewPoint[j1] <1) {
+                for (Int4 ii1= BeginNewPoint[j1];ii1<=EndNewPoint[j1];ii1++)
+                    stack[kstack++] = ii1;
+                 continue;}
+	      
+                
+	      int k0,k1;
+	      if (step[j1]<0) k0=1,k1=0; // reverse
+	      else k0=0,k1=1; 
+	      R2 V10 = (R2)(*t)[VerticesOfTriangularEdge[j1][k0]];
+	      R2 V11 = (R2)(*t)[VerticesOfTriangularEdge[j1][k1]];
+	      R2 D = V11-V10;
+	      Real8 c0 =  vi0.m(D,(R2) vi0);
+
+	      Real8 c10 =  vi0.m(D,V10);
+	      Real8 c11 =  vi0.m(D,V11);
+
+	      Real8 s;
+	      //cout << " --i0 = " << i0  << D  << V10 << V11 << endl ;
+	      //cout << "   c10 " <<  c10 << " c0 " << c0 << " c11 " << c11 << endl;
+	      if (( c10 < c0 ) && (c0 < c11)) 
+		s = (c11-c0)/(c11-c10);
+	      else if  (( c11 < c0 ) && (c0 < c10)) 
+		s = (c11-c0) /(c11-c10);
+	      else break;
+	      R2 VP = V10*s + V11*(1-s);
+	      int sss = (c11-c10) >0 ? 1 : -1;
+#ifdef DRAWING1
+	      penthickness(2);
+	      Move((R2) vi0);
+	      Line(VP);
+	      penthickness(1);
+#endif
+	      // find the 2 point by dichotomie
+	      //cout << "   t =" << Number(t) << " c0 " << c0  ;
+	      Int4 ii0 =  BeginNewPoint[j1];
+	      Int4 ii1 =  EndNewPoint[j1];	     
+              Real8 ciii=-1,cii0=-1,cii1=-1  ;
+ 	      if ( sss * ((cii0=vi0.m(D,(R2) vertices[ii0]))- c0) >0 )  
+		stack[kstack++] = ii0;//cout << " add+0 " << ii0;
+ 	      else if ( sss * ((cii1=  vi0.m(D ,(R2) vertices[ii1]))- c0) < 0 )  
+		stack[kstack++] = ii1;//cout << " add+1 " << ii1;
+              else {
+	        while ((ii1-ii0)> 1) {
+		  Int4 iii = (ii0+ii1)/2;
+	          ciii = vi0.m( D ,(R2) vertices[iii]);
+		  //cout << " (iii = " << iii << " " <<  ciii << ") ";
+		  if ( sss * (ciii - c0) <0 )  ii0 = iii;
+		  else ii1 = iii;}	        	      
+	        stack[kstack++] = ii0;// cout << " add0 " << ii0;
+	        if (ii1 != ii0)  stack[kstack++] = ii1;//cout << " add1 " << ii1;
+              }
+#ifdef DEBUG2
+	      cout << "ii1 = " << ii1 
+		   << " ii0 = " << ii0 << endl;
+              cout << "   cccc = " << cii0 << " " << ciii 
+		   << " " << cii1 << " sss=" << sss << endl;
+#endif
+	      if (kstack >5) // bug ?
+	    	cout << "NewPoints: bug????? " << kstack << " stack  " << stack[kstack]<< endl;
+	    }
+	    
+	    stack[kstack++] = -1; // to stop
+	    Int4 i1;
+	    kstack =0; 
+	    while( (i1=stack[kstack++]) >= 0) 
+	      { // the two parameter is i0 and i1 
+	      assert(i1 < nbv && i1 >= 0);
+	      assert(i0 < nbv && i0 >= 0);
+	      assert(i1 != i0);
+	      R2 v01 = (R2) vertices[i1]- (R2) vertices[i0];
+	      Real8 d01 = (vertices[i0].m(v01) + vertices[i1].m(v01));
+		
+
+#ifdef DRAWING1
+	      Move(vertices[i0].r);
+	      Line(vertices[i1].r);
+#endif
+#ifdef TRACETRIANGLE
+	      if(trace) {
+		cout << "\n test j" << j <<" "  << i0 
+		     << " " << i1 << " d01=" << d01 <<endl;}
+#endif
+	      assert (i0 >= nbvold);
+	      assert (i1 >= nbvold);
+	      assert(i0 != i1);
+	      if (d01 == 0) 
+		break; 
+	      if ( d01 < seuil)
+              {
+		if (i1<nbvold) {
+		  // remove all the points i0;
+		   Int4 ip,ipp;
+		  for  (ip=i0;i0 != (ipp = vertices[ip].ReferenceNumber);ip=ipp)
+		    vertices[ip].ReferenceNumber = -1;// mark remove
+		  vertices[ip].ReferenceNumber = -1;// mark remove
+		}
+	      else {
+		// remove on of two points
+		 Int4 ip0, ip1, ipp0,ipp1;
+		 int kk0=1,kk1=1;
+		// count the number of common points to compute weight w0,w1
+		for  (ip0=i0;i0 != (ipp0 = vertices[ip0].ReferenceNumber);ip0=ipp0) kk0++;
+		for  (ip1=i1;i1 != (ipp1 = vertices[ip1].ReferenceNumber);ip1=ipp1) kk1++;
+		
+		 Real8 w0 = ((Real8) kk0)/(kk0+kk1);
+		 Real8 w1 = ((Real8) kk1)/(kk0+kk1);
+
+		// make a circular link
+		Exchange(vertices[i0].ReferenceNumber,vertices[i1].ReferenceNumber);
+		// the new coordinate 
+		R2 C //= vertices[i0] ;
+		  =  vertices[i0].r *w0 + vertices[i1].r* w1;
+
+#ifdef TRACETRIANGLE
+		if(trace) {
+		  cout << "\n ref = "<< vertices[i0].ref << " " <<vertices[i1].ref <<endl;
+		}
+#endif    
+#ifdef DRAWING1  
+		Move(vertices[i0].r);
+		Line(vertices[i1].r);
+		DrawMark(C);
+#endif		
+		// update the new point points of the list 
+		for  (ip0=i0;i0 != (ipp0 = vertices[ip0].ReferenceNumber);ip0=ipp0)
+		  vertices[ip0].r = C;	      
+		vertices[ip0].r = C;
+	      }
+              }
+	    }
+	} // for (i0= ....
+  }// for triangle   
+
+#ifdef DRAWING1
+  cout << " -------------------------------------------- " << endl;
+  inquire();
+  reffecran();
+  Draw();
+  penthickness(2);
+#endif
+  
+  // remove of all the double points
+
+  Int4 ip,ipp,kkk=nbvold;
+  for (i=nbvold;i<nbv;i++) 
+     if (vertices[i].ReferenceNumber>=0) {// good points
+    //  cout <<" i = " << i ;
+      for  (ip=i;i != (ipp = vertices[ip].ReferenceNumber);ip=ipp)
+         vertices[ip].ReferenceNumber = -1;// mark remove
+      vertices[ip].ReferenceNumber = -1;// mark remove
+      // cout << i << " ---> " << kkk << endl;        
+      vertices[kkk] = vertices[i];
+      vertices[kkk].i = toI2(vertices[kkk].r);
+#ifdef DRAWING1
+      DrawMark(vertices[kkk]);
+#endif
+      vertices[kkk++].ReferenceNumber = 0;
+      
+     } 
+#ifdef DRAWING1  
+  penthickness(1);
+#endif
+    
+ // insertion part --- 
+
+  const Int4 nbvnew = kkk-nbvold;
+
+  cout << "    Remove " << nbv - kkk  << " to close  vertex " ;
+  cout << " and   Insert the " <<nbvnew<< " new points " << endl;  
+  nbv = kkk;
+  Int4 NbSwap=0;
+  Icoor2 dete[3];
+  
+  // construction d'un ordre aleatoire 
+  if (! nbvnew) 
+    break; 
+  if (nbvnew) {
+  const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv)  ;
+  Int4 k3 = rand()%nbvnew ; 
+  for (Int4 is3=0; is3<nbvnew; is3++) 
+    ordre[nbvold+is3]= &vertices[nbvold +(k3 = (k3 + PrimeNumber)% nbvnew)];
+
+  for (i=nbvold;i<nbv;i++) 
+    { Vertex * vi = ordre[i];
+      Triangle *tcvi = FindTriangleContening(vi->i,dete);
+      //     Vertex * nv =  quadtree->NearestVertex(vi->i.x,vi->i.y);
+      //      cout << " Neart Vertex of "  << Number(vi)<< vi->i << " is " 
+      //   << Number(nv) << nv->i  << endl;
+      // Int4  kt = Number(tcvi);
+      // 
+      
+      quadtree->Add(*vi); //
+#ifdef DRAWING1
+      DrawMark(vi->r);
+#endif
+      assert (tcvi->det >= 0) ;// internal 
+      Add(*vi,tcvi,dete),NbSwap += vi->Optim(1);          
+    }  
+  }
+  cout << " Nb swap = " << NbSwap << " after " ;
+#ifdef DRAWING1
+  inquire();
+#endif
+
+  for (i=nbvold;i<nbv;i++) 
+    NbSwap += vertices[i].Optim(1);  
+  cout << NbSwap << endl;
+
+  for (i=nbtold;i<nbt;i++)
+     first_np_or_next_t[i]=1;
+
+  Headt = nbt; // empty list 
+  for (i=nbvold;i<nbv;i++) 
+    { // for all the triangle contening the vertex i
+       Vertex * s  = vertices + i;
+       TriangleAdjacent ta(s->t, EdgesVertexTriangle[s->vint][1]);
+       Triangle * tbegin= (Triangle*) ta;
+       Int4 kt;
+       do { 
+	 kt = Number((Triangle*) ta);
+	 if (first_np_or_next_t[kt]>0) 
+	   first_np_or_next_t[kt]=-Headt,Headt=kt;
+	 assert( ta.EdgeVertex(0) == s);
+	 ta = Next(Adj(ta));
+       } while ( (tbegin != (Triangle*) ta)); 
+    }
+
+
+  } while (nbv!=nbvold);
+  delete []  first_np_or_next_t;
+#ifdef  DEBUG
+  int nberr=0;
+  for (int it=0;it<nbt;it++)
+    if(triangles[it].det==0) 
+      if(nberr++<10) cerr << "Bug Triangle nul" << it << triangles[it] << endl;
+  if(nberr) MeshError(992,this);
+#endif
+  cout << " end :  Triangles::NewPoints old  nbv=" << nbv << endl;
+
+}
+
+void Triangles::Insert() 
+{
+  if (verbosity>2) cout << "  -- Insert initial " << nbv << " vertices " << endl ;
+  Triangles * OldCurrentTh =CurrentTh;
+
+  CurrentTh=this;
+  double time0=CPUtime(),time1,time2,time3;
+  SetIntCoor();
+  Int4 i;
+  for (i=0;i<nbv;i++) 
+    ordre[i]= &vertices[i] ;
+
+  // construction d'un ordre aleatoire 
+  const Int4 PrimeNumber= AGoodNumberPrimeWith(nbv) ;
+  Int4 k3 = rand()%nbv ; 
+  for (int is3=0; is3<nbv; is3++) 
+    ordre[is3]= &vertices[k3 = (k3 + PrimeNumber)% nbv];
+
+
+
+
+  for (i=2 ; det( ordre[0]->i, ordre[1]->i, ordre[i]->i ) == 0;) 
+    if  ( ++i >= nbv) {
+      cerr << " All the vertices are aline " << endl;
+      MeshError(998,this); }
+          
+  // echange i et 2 dans ordre afin 
+  // que les 3 premiers ne soit pas aligne
+  Exchange( ordre[2], ordre[i]);
+  
+  // on ajoute un point a l'infini pour construire le maillage
+  // afin d'avoir une definition simple des aretes frontieres
+  nbt = 2;
+  
+  
+  // on construit un maillage trivale forme
+  // d'une arete et de 2 triangles
+  // construit avec le 2 aretes orientes et 
+  Vertex *  v0=ordre[0], *v1=ordre[1];
+  
+  triangles[0](0) = 0; // sommet pour infini 
+  triangles[0](1) = v0;
+  triangles[0](2) = v1;
+  
+  triangles[1](0) = 0;// sommet pour infini 
+  triangles[1](2) = v0;
+  triangles[1](1) = v1;
+  const int e0 = OppositeEdge[0];
+  const int e1 = NextEdge[e0];
+  const int e2 = PreviousEdge[e0];
+  triangles[0].SetAdj2(e0, &triangles[1] ,e0);
+  triangles[0].SetAdj2(e1, &triangles[1] ,e2);
+  triangles[0].SetAdj2(e2, &triangles[1] ,e1);
+  
+  triangles[0].det = -1;  // faux triangles
+  triangles[1].det = -1;  // faux triangles
+  
+  triangles[0].SetTriangleContainingTheVertex();
+  triangles[1].SetTriangleContainingTheVertex();
+  
+  triangles[0].link=&triangles[1];
+  triangles[1].link=&triangles[0];
+  
+#ifdef DEBUG 
+  triangles[0].check();
+  triangles[1].check();
+#endif  
+  //  nbtf = 2;
+   if (  !quadtree )  quadtree = new QuadTree(this,0);
+   quadtree->Add(*v0);
+   quadtree->Add(*v1);
+   
+  // on ajoute les sommets un � un 
+  Int4 NbSwap=0;
+
+  time1=CPUtime();
+
+    if (verbosity>3) cout << "  -- Begin of insertion process " << endl;
+
+  for (Int4 icount=2; icount<nbv; icount++) {
+    Vertex *vi  = ordre[icount];
+    //    cout << " Insert " << Number(vi) << endl;
+    Icoor2 dete[3];
+    Triangle *tcvi = FindTriangleContening(vi->i,dete);
+    quadtree->Add(*vi); 
+    Add(*vi,tcvi,dete);
+    NbSwap += vi->Optim(1,0);
+#ifdef DRAWING1
+    inquire();
+#endif
+    
+  }// fin de boucle en icount
+  time2=CPUtime();
+  if (verbosity>3) 
+    cout << "    NbSwap of insertion " <<    NbSwap 
+	 << " NbSwap/Nbv " <<  (float) NbSwap / (float) nbv 
+	 << " NbUnSwap " << NbUnSwap << " Nb UnSwap/Nbv " 
+	 << (float)NbUnSwap /(float) nbv 
+	 <<endl;
+  NbUnSwap = 0;
+  // construction d'un ordre aleatoire 
+  //  const int PrimeNumber= (nbv % 999983) ? 1000003: 999983 ;
+#ifdef NBLOOPOPTIM
+
+  k3 = rand()%nbv ; 
+  for (int is4=0; is4<nbv; is4++) 
+    ordre[is4]= &vertices[k3 = (k3 + PrimeNumber)% nbv];
+  
+  double timeloop = time2 ;
+  for(int Nbloop=0;Nbloop<NBLOOPOPTIM;Nbloop++) 
+    {
+      double time000 = timeloop;
+      Int4  NbSwap = 0;
+      for (int is1=0; is1<nbv; is1++) 
+	NbSwap += ordre[is1]->Optim(0,0);
+      timeloop = CPUtime();
+  if (verbosity>3) 
+      cout << "    Optim Loop "<<Nbloop<<" NbSwap: " <<  NbSwap 
+	   << " NbSwap/Nbv " 	   <<  (float) NbSwap / (float) nbv 
+	   << " CPU=" << timeloop - time000 << "  s, " 
+	   << " NbUnSwap/Nbv " << (float)NbUnSwap /(float) nbv  
+	   <<  endl;
+      NbUnSwap = 0;
+      if(!NbSwap) break;
+    }
+  ReMakeTriangleContainingTheVertex(); 
+  // because we break the TriangleContainingTheVertex
+#endif
+#ifdef  DEBUG
+  int nberr=0;
+  for (int it=0;it<nbt;it++)
+    if(triangles[it].det==0) 
+      if(nberr++<10) cerr << "Bug Triangle nul" << it << triangles[it] << endl;
+  if(nberr) MeshError(991,this);
+#endif
+  time3=CPUtime();
+  if (verbosity>4) 
+  cout << "    init " << time1 - time0 << " initialisation,  " 
+       << time2 - time1 << "s, insert point  " 
+       << time3 -time2 << "s, optim " << endl
+       << "     Init Total Cpu Time = " << time3 - time0 << "s " << endl;
+  
+#ifdef DRAWING1
+  inquire();
+#endif  
+  CurrentTh=OldCurrentTh;
+}
+
+
+void Triangles::ForceBoundary()
+{
+  if (verbosity > 2)
+    cout << "  -- ForceBoundary  nb of edge " << nbe << endl;
+  int k=0;
+  Int4  nbfe=0,nbswp=0,Nbswap=0;
+  for (Int4 t = 0; t < nbt; t++)  
+    if (!triangles[t].det)
+      k++,cerr << " det T" << t << " = " << 0 << endl;
+  if (k!=0) {
+    cerr << " ther is  " << k << "  triangles of mes = 0 " << endl;
+    MeshError(11,this);}
+  
+  TriangleAdjacent ta(0,0);
+  for (Int4 i = 0; i < nbe; i++) 
+    {
+      nbswp =  ForceEdge(edges[i][0],edges[i][1],ta);
+      
+      if ( nbswp < 0) 	k++;
+      else Nbswap += nbswp;
+      if (nbswp) nbfe++;
+      if ( nbswp < 0 && k < 5)
+      {
+         cerr << " Missing  Edge " << i << " v0 =  " << Number(edges[i][0]) << edges[i][0].r
+      	   <<" v1= " << Number(edges[i][1]) << edges[i][1].r << " " << edges[i].on->Cracked() << "  " << (Triangle *) ta ;
+	  if(ta.t)
+	  {
+	      Vertex *aa = ta.EdgeVertex(0), *bb = ta.EdgeVertex(1);  
+	      cerr << " crossing with  [" << Number(aa) << ", " << Number(bb) << "]\n";
+	  }
+	  else cerr << endl;
+	   
+      }
+      if ( nbswp >=0 && edges[i].on->Cracked())
+	  ta.SetCracked();
+    }
+		  
+  
+  if (k!=0) {
+    cerr << " they is " << k << " lost edges " << endl;
+    cerr << " The boundary is crossing may be!" << endl;
+    MeshError(10,this);
+  }
+  for (Int4 j=0;j<nbv;j++)
+    Nbswap +=  vertices[j].Optim(1,0);
+  if (verbosity > 3)
+    cout << "     Nb of inforced edge = " << nbfe << " Nb of Swap " << Nbswap << endl;
+
+}
+
+void Triangles::FindSubDomain(int OutSide=0)
+{
+    //#define DRAWING1
+    
+    if (verbosity >2)
+    {
+	if (OutSide)
+	    cout << "  -- Find all external sub-domain ";	
+	else
+	    cout << "  -- Find all internal sub-domain ";
+      if(verbosity>99)
+	{
+	  
+	  for(int i=0;i<nbt;++i)
+	      cout << i<< " " << triangles[i] << endl;
+	}
+	
+    }
+    // if (verbosity > 4) cout << " OutSide=" << OutSide << endl;
+    short * HeapArete = new short[nbt];
+    Triangle  **  HeapTriangle = new Triangle*  [nbt];
+    Triangle *t,*t1;
+    Int4 k,it;
+    
+    for (Int4 itt=0;itt<nbt;itt++) 
+	triangles[itt].link=0; // par defaut pas de couleur
+#ifdef DRAWING1
+    reffecran();
+#endif
+    
+    Int4  NbSubDomTot =0;
+    for ( it=0;it<nbt;it++)  { 
+	if ( ! triangles[it].link  ) {
+	    t = triangles + it;
+	    NbSubDomTot++;; // new composante connexe
+	    Int4 i = 0; // niveau de la pile 
+	    t->link = t ; // sd forme d'un triangle cicular link
+#ifdef DRAWING1
+	    t->Draw(NbSubDomTot-1);
+#endif
+	    
+	    
+	    HeapTriangle[i] =t ; 
+	    HeapArete[i] = 3;
+	    
+	    while (i >= 0) // boucle sur la pile
+	    { while ( HeapArete[i]--) // boucle sur les 3 aretes 
+	    { 
+		int na =  HeapArete[i];
+		Triangle * tc =  HeapTriangle[i]; // triangle courant
+		if( ! tc->Locked(na)) // arete non frontiere
+		{
+		    Triangle * ta = tc->TriangleAdj(na) ; // n� triangle adjacent
+		    if (ta->link == 0 ) // non deja chainer => on enpile
+		    { 
+			i++;
+#ifdef DRAWING1
+			ta->Draw(NbSubDomTot-1);
+#endif
+			ta->link = t->link ;  // on chaine les triangles
+			t->link = ta ;  // d'un meme sous domaine          
+			HeapArete[i] = 3; // pour les 3 triangles adjacents
+			HeapTriangle[i] = ta;
+		    }}
+	    } // deplie fin de boucle sur les 3 adjacences
+		i--;
+	    }          
+	}      
+    }
+    
+    // supression de tous les sous domaine infini <=>  contient le sommet NULL
+    it =0;
+    NbOutT = 0;
+    while (it<nbt) {
+	if (triangles[it].link) 
+	{ 
+	    if (!( triangles[it](0) &&  triangles[it](1) &&  triangles[it](2) )) 
+	    {
+		// infini triangle 
+		NbSubDomTot --;
+		//  cout << " triangle infini " << it << triangles[it] << endl;
+		t=&triangles[it];
+		NbOutT--;  // on fait un coup de trop. 
+		while  (t){ // cout << Number(t) << " " << endl;
+		    NbOutT++;
+		    t1=t;
+		    t=t->link;
+		    t1->link=0;}//while (t)
+	    }
+	}   
+	it++;} // end while (it<nbt)
+    if (nbt == NbOutT ||  !NbSubDomTot) 
+    {
+	cout << "\n error : " <<  NbOutT << " " << NbSubDomTot <<" " << nbt << endl;
+	cerr << "Error: The boundary is not close => All triangles are outside " << endl;
+	MeshError(888,this);
+    }
+    
+    delete [] HeapArete;
+    delete [] HeapTriangle;
+    
+    
+    if (OutSide|| !Gh.subdomains || !Gh.NbSubDomains ) 
+    { // No geom sub domain
+	Int4 i;
+	if (subdomains) delete [] subdomains;
+	subdomains = new SubDomain[ NbSubDomTot];
+	NbSubDomains=  NbSubDomTot;
+	for ( i=0;i<NbSubDomains;i++) {
+	    subdomains[i].head=NULL;
+	    subdomains[i].ref=i+1;
+	}
+	Int4 * mark = new Int4[nbt];
+	for (it=0;it<nbt;it++)
+	    mark[it]=triangles[it].link ? -1 : -2;
+	
+	it =0;
+	k = 0;
+	while (it<nbt) {
+	    if (mark[it] == -1) {
+		t1 = & triangles[it];
+		t = t1->link;
+		mark[it]=k;
+#ifdef DRAWING1  
+		t1->Draw(k);
+#endif
+		subdomains[k].head = t1;
+		// cout << " New -- " << Number(t1) << " " << it << endl;
+		do {// cout << " k " << k << " " << Number(t) << endl;
+		    mark[Number(t)]=k;
+#ifdef DRAWING1  
+		    t->Draw(k);
+#endif
+		    t=t->link;
+		} while (t!=t1);
+#ifdef DRAWING1  
+		t1->Draw(k);
+#endif
+		mark[it]=k++;}
+	    //    else if(mark[it] == -2 ) triangles[it].Draw(999);
+	    it++;} // end white (it<nbt)
+	assert(k== NbSubDomains);
+	if(OutSide) 
+	{
+	    //  to remove all the sub domain by parity adjacents
+	    //  because in this case we have only the true boundary edge
+	    // so teh boundary is manifold
+	    Int4 nbk = NbSubDomains;
+	    while (nbk)
+		for (it=0;it<nbt && nbk ;it++)
+		    for (int na=0;na<3 && nbk ;na++)
+		    {
+			Triangle *ta = triangles[it].TriangleAdj(na);
+			Int4 kl = ta ? mark[Number(ta)] : -2;
+			Int4 kr = mark[it];
+			if(kr !=kl) {
+			    //cout << kl << " " << kr << " rl "  << subdomains[kl].ref
+			    // << " rr " << subdomains[kr].ref ;
+			    if (kl >=0 && subdomains[kl].ref <0 && kr >=0 && subdomains[kr].ref>=0)
+				nbk--,subdomains[kr].ref=subdomains[kl].ref-1;
+			    if (kr >=0 && subdomains[kr].ref <0 && kl >=0 && subdomains[kl].ref>=0)
+				nbk--,subdomains[kl].ref=subdomains[kr].ref-1;
+			    if(kr<0 && kl >=0 && subdomains[kl].ref>=0)
+				nbk--,subdomains[kl].ref=-1;
+			    if(kl<0 && kr >=0 && subdomains[kr].ref>=0)
+				nbk--,subdomains[kr].ref=-1;
+			    //   cout << " after \t "   
+			    //	 << kl << subdomains[kl].ref << " rr " << kr 
+			    // << subdomains[kr].ref << endl;
+			}
+		    }
+			//  cout << subdomains[0].ref << subdomains[1].ref << endl;
+			Int4  j=0;
+	    for ( i=0;i<NbSubDomains;i++)
+		if((-subdomains[i].ref) %2) { // good 
+					      //cout << " sudom ok  = " << i << " " << subdomains[i].ref
+					      // << " " << (-subdomains[i].ref) %2 << endl;
+		    if(i != j) 
+			Exchange(subdomains[i],subdomains[j]);
+		    j++;}
+		    else
+		    { //cout << " remove sub domain " << i << endl;
+			t= subdomains[i].head;
+			while  (t){// cout << Number(t) << " " << endl;
+			    NbOutT++;
+			    t1=t;
+			    t=t->link;
+			    t1->link=0;}//while (t)
+		    }
+		    
+		    if(verbosity>4)
+			cout << " Number of remove sub domain (OutSideMesh) =" << NbSubDomains-j << endl;
+	    NbSubDomains=j;
+	}
+	
+	delete []  mark; 
+	
+    }
+    else
+    { // find the head for all sub domaine
+	if (Gh.NbSubDomains != NbSubDomains && subdomains)
+	    delete [] subdomains, subdomains=0;
+	if (! subdomains  ) 
+	    subdomains = new SubDomain[ Gh.NbSubDomains];
+	NbSubDomains =Gh.NbSubDomains;
+	if(verbosity>4)
+	    cout << "     find the " << NbSubDomains << " sub domain " << endl;
+	Int4 err=0;
+	ReMakeTriangleContainingTheVertex();
+	Int4 * mark = new Int4[nbt];
+	Edge **GeometricalEdgetoEdge = MakeGeometricalEdgeToEdge();
+        
+	for (it=0;it<nbt;it++)
+	    mark[it]=triangles[it].link ? -1 : -2;
+	Int4 inew =0;
+	for (Int4 i=0;i<NbSubDomains;i++) 
+	{
+	    GeometricalEdge &eg = *Gh.subdomains[i].edge;
+	    subdomains[i].ref = Gh.subdomains[i].ref;
+	    int ssdlab = subdomains[i].ref;
+	    // by carefull is not easy to find a edge create from a GeometricalEdge 
+	    // see routine MakeGeometricalEdgeToEdge
+	    Edge &e = *GeometricalEdgetoEdge[Gh.Number(eg)];
+	    assert(&e);
+	    Vertex * v0 =  e(0),*v1 = e(1);
+	    Triangle *t  = v0->t;
+	    int sens = Gh.subdomains[i].sens;
+	    // test if ge and e is in the same sens 
+	    //	cout << " geom edge = " <<  Gh.Number(eg) <<" @" << &eg << " ref = " << subdomains[i].ref 
+	    //     << " ref edge =" << eg.ref << " sens " << sens ;
+	    if (((eg[0].r-eg[1].r),(e[0].r-e[1].r))<0)
+		sens = -sens ;
+	    subdomains[i].sens = sens;
+	    subdomains[i].edge = &e;
+	    //	cout << " sens " << sens << " in geom " << eg[0].r << eg[1].r << " in mesh  " << e[0].r << e[1].r << endl;
+	    //	cout << "  v0 , v1 = " << Number(v0) << " "  << Number(v1) << endl;
+	    assert(t && sens);
+	    
+	    TriangleAdjacent  ta(t,EdgesVertexTriangle[v0->vint][0]);// previous edges
+		
+	    while (1) 
+	    {
+		assert( v0 == ta.EdgeVertex(1) );
+		//	 cout << " recherche " << Number( ta.EdgeVertex(0)) << endl;
+		if (ta.EdgeVertex(0) == v1) { // ok we find the edge
+		    if (sens>0)  
+			subdomains[i].head=t=Adj(ta);
+		    else 
+			subdomains[i].head=t=ta;
+		    //cout << "      triangle  =" << Number(t) << " = " << (*t)[0].r <<  (*t)[1].r <<  (*t)[2].r << endl;
+		    if(t<triangles || t >= triangles+nbt || t->det < 0 
+		        || t->link == 0) // Ajoute aout 200 
+		     {
+			cerr << " Error in the def of sub domain "<<i
+			     << " form border " << NbSubDomains - i  << "/" << NbSubDomains
+			     << ": Bad sens  " << Gh.Number(eg) <<" "<< sens <<  endl;  
+			err++;
+			break;}
+		    Int4 it = Number(t);
+		    if (mark[it] >=0) {
+                        
+			if(verbosity>10)
+			    cerr << "     Warning: the sub domain " << i << " ref = " << subdomains[i].ref 
+				<< " is previouly defined with "  <<mark[it] << " ref = " << subdomains[mark[it]].ref
+				<< " skip this def " << endl;
+			break;}
+		    if(i != inew) 
+			Exchange(subdomains[i],subdomains[inew]);
+		    inew++;
+		    Triangle *tt=t;
+		    Int4 kkk=0;
+		    do 
+		    {
+			kkk++;
+			assert(mark[Number(tt)]<0);
+#ifdef DRAWING1
+			tt->Draw(i);
+#endif
+			mark[Number(tt)]=i;
+			tt=tt->link;
+		    } while (tt!=t);
+		    if(verbosity>7)
+			cout << "     Nb de triangles dans le sous domaine " << i << " de ref " << subdomains[i].ref << " = " << kkk << endl;
+		    break;}
+		ta = Previous(Adj(ta));         
+		if(t == (Triangle *) ta) {
+		    err++;
+		    cerr << " Error in the def of sub domain " << i 
+			<< " edge=" << Gh.Number(eg) << " " << sens << endl;
+		    break;}
+		//         cout << " NB of remove subdomain " << NbSubDomTot-NbSubDomains<< endl;
+		
+	    }
+		
+	}
+	if (err) MeshError(777,this);
+	
+	if (inew < NbSubDomains) {
+	    if (verbosity>5) 
+		cout << "     Warning: We remove " << NbSubDomains-inew << " SubDomains " << endl;
+	    NbSubDomains=inew;}
+	
+	
+	for (it=0;it<nbt;it++)
+	    if ( mark[it] ==-1 ) 
+		NbOutT++,triangles[it].link =0;
+	delete [] GeometricalEdgetoEdge;
+	delete [] mark;
+	
+    }
+    
+#ifdef DRAWING1
+    inquire();
+#endif
+    NbOutT=0;
+    for (it=0;it<nbt;it++) 
+	if(!triangles[it].link)  NbOutT++;
+    if (verbosity> 4)
+	cout << "    " ;
+    if (verbosity> 2)
+	cout << " Nb of Sub borned Domain  = " <<  NbSubDomTot << " NbOutTriangles = " << NbOutT <<endl;
+#ifdef DRAWING1
+    inquire();
+#endif
+    
+    //#undef DRAWING1
+    
+    
+}
+void Triangles::ReNumberingVertex(Int4 * renu)
+{
+  // warning be carfull because pointeur
+  // from on mesh to over mesh 
+  //  --  so do ReNumbering a the beginning
+  Vertex * ve = vertices+nbv;
+  Int4 it,ie,i;
+  
+  for ( it=0;it<nbt;it++) 
+    triangles[it].ReNumbering(vertices,ve,renu);
+  
+  for ( ie=0;ie<nbe;ie++) 
+    edges[ie].ReNumbering(vertices,ve,renu);
+  
+  for (i=0;i< NbVerticesOnGeomVertex;i++)
+    {
+      Vertex *v = VerticesOnGeomVertex[i].mv;
+      if (v>=vertices && v < ve)
+	VerticesOnGeomVertex[i].mv=vertices+renu[Number(v)];
+    }
+  
+  for (i=0;i< NbVerticesOnGeomEdge;i++)
+    {
+      Vertex *v =VerticesOnGeomEdge[i].mv;
+      if (v>=vertices && v < ve)
+	 VerticesOnGeomEdge[i].mv=vertices+renu[Number(v)];
+    }
+
+  for (i=0;i< NbVertexOnBThVertex;i++)
+    {
+      Vertex *v=VertexOnBThVertex[i].v;
+      if (v>=vertices && v < ve)
+	VertexOnBThVertex[i].v=vertices+renu[Number(v)];
+    }
+  
+  for (i=0;i< NbVertexOnBThEdge;i++)
+    {
+      Vertex *v=VertexOnBThEdge[i].v;
+      if (v>=vertices && v < ve)
+	VertexOnBThEdge[i].v=vertices+renu[Number(v)];
+    }
+
+  // move the Vertices without a copy of the array 
+  // be carefull not trivial code 
+  Int4 j;
+  for ( it=0;it<nbv;it++) // for all sub cycles of the permutation renu
+    if (renu[it] >= 0) // a new sub cycle
+      { 
+        i=it;
+        Vertex ti=vertices[i],tj;
+        while ( (j=renu[i]) >= 0) 
+         { // i is old, and j is new 
+           renu[i] = -1-renu[i]; // mark 
+           tj = vertices[j]; // save new
+           vertices[j]= ti; // new <- old
+           i=j;     // next 
+           ti = tj;
+         }  
+     }
+  if (quadtree) 
+  {  delete quadtree;
+   quadtree = new QuadTree(this);
+  }
+ for ( it=0;it<nbv;it++)
+   renu[i]= -renu[i]-1;
+  
+}
+void Triangles::ReNumberingTheTriangleBySubDomain(bool justcompress)
+ {
+  Int4 *renu= new Int4[nbt];
+   Triangle *t0,*t,*te=triangles+nbt;
+   Int4 k=0,it,i,j;
+      
+  for ( it=0;it<nbt;it++) 
+    renu[it]=-1; // outside triangle 
+  for ( i=0;i<NbSubDomains;i++)
+   { 
+     t=t0=subdomains[i].head;
+     assert(t0); // no empty sub domain
+     do { 
+       Int4 kt = Number(t);
+       assert(kt>=0 && kt < nbt );
+       assert(renu[kt]==-1);
+       renu[kt]=k++;
+       }
+     while (t0 != (t=t->link));
+   }
+  if (verbosity>9)
+    cout << " number of inside triangles " << k << " nbt = " << nbt << endl;
+  // take is same numbering if possible    
+  if(justcompress)
+      for ( k=0,it=0;it<nbt;it++) 
+     if(renu[it] >=0 ) 
+       renu[it]=k++;
+   
+   // put the outside triangles at the end
+   for ( it=0;it<nbt;it++) 
+    if (renu[it]==-1) 
+      renu[it]=k++;
+      
+    assert(k == nbt);
+   // do the change on all the pointeur 
+   for ( it=0;it<nbt;it++)
+     triangles[it].ReNumbering(triangles,te,renu);
+     
+   for ( i=0;i<NbSubDomains;i++)
+     subdomains[i].head=triangles+renu[Number(subdomains[i].head)];
+   
+  // move the Triangles  without a copy of the array 
+  // be carefull not trivial code 
+  for ( it=0;it<nbt;it++) // for all sub cycles of the permutation renu
+    if (renu[it] >= 0) // a new sub cycle
+      { 
+        i=it;
+        Triangle ti=triangles[i],tj;
+        while ( (j=renu[i]) >= 0) 
+         { // i is old, and j is new 
+           renu[i] = -1; // mark 
+           tj = triangles[j]; // save new
+           triangles[j]= ti; // new <- old
+           i=j;     // next 
+           ti = tj;
+         }  
+     }
+   delete [] renu;
+   nt = nbt - NbOutT;
+
+#ifdef DEBUG
+// verif 
+     for ( it=0;it<nbt;it++)
+      triangles[it].check();
+#endif   
+ }
+Int4  Triangles::ConsRefTriangle(Int4 *reft) const
+{
+  assert(reft);
+   Triangle *t0,*t;
+   Int4 k=0, num;   
+  for (Int4 it=0;it<nbt;it++) 
+    reft[it]=-1; // outside triangle 
+  for (Int4 i=0;i<NbSubDomains;i++)
+   { 
+     t=t0=subdomains[i].head;
+     assert(t0); // no empty sub domain
+     //  Int4 color=i+1;// because the color 0 is outside triangle
+     do { k++;
+       num = Number(t);
+       assert(num>=0 &&num < nbt);
+       reft[num]=i;
+       //  cout << Number(t0) << " " <<Number(t)<< " "  << i << endl;
+       }
+     while (t0 != (t=t->link));
+   }
+  //  NbOutT = nbt - k;
+  if (verbosity>5) 
+    cout << " Nb of Sub Domain =" << NbSubDomains  << " Nb of In Triangles " << k 
+	 << " Nbt = " << nbt << " Out Triangles = " << nbt - k <<  endl;
+   
+  return k;   
+
+}
+
+/*
+void Triangles::ConsLinkTriangle()
+{
+  for (Int4 i=0;i<NbSubDomains;i++)
+    subdomains[i].head=0;
+   Triangle * t=triangles,*tend = triangles+nbt,*hst;
+  for (;t<tend;t++)
+   {  
+       if (t->link) 
+        {
+           Int4 color = t->color-1;
+          assert(color<NbSubDomains && color>=0);
+          if (hst=subdomains[color].head) {
+            t->link=hst->link;
+            hst->link=t; }
+          else {
+            subdomains[color].head = t;
+            t->link=t;}// circular link         
+        }
+     }
+ {
+   for (Int4 i=0;i<NbSubDomains;i++)
+     assert(subdomains[i].head);
+ }
+   
+}
+*/
+/* void Triangles::RandomInit() 
+{ 
+ //  Meshbegin = vertices;
+ //  Meshend  = vertices + nbvx;
+   nbv = nbvx;
+   for (int i = 0; i < nbv; i++)
+     {
+        vertices[i].r.x= rand();
+        vertices[i].r.y= rand();
+        vertices[i].ref = 0;
+     }
+}
+void Triangles::CubeInit(int n,int m) 
+{ 
+  //  nbvx = n*m;
+ //  Meshbegin = vertices;
+  // Meshend  = vertices + nbvx;
+   nbv = n*m;
+   assert(nbv <= nbvx);
+   int k =0;
+   for (int i = 0; i < n; i++)
+   for (int j = 0; j < m; j++)
+     {
+        vertices[k].r.x= i;
+        vertices[k].r.y= j;
+        vertices[k++].ref = 0;
+     }
+}
+*/
+Vertex * Triangles::NearestVertex(Icoor1 i,Icoor1 j) 
+   { return  quadtree->NearestVertex(i,j); } 
+
+
+void Triangles::PreInit(Int4 inbvx,char *fname)
+{
+  srand(19999999);
+  OnDisk =0;
+  NbRef=0;
+  //  allocGeometry=0;
+  identity=0;
+  NbOfTriangleSearchFind =0;
+  NbOfSwapTriangle =0;
+  nbiv=0;
+  nbv=0;
+  nbvx=inbvx;
+  nbt=0;
+  NbOfQuad = 0;
+  nbtx=2*inbvx-2;
+  NbSubDomains=0;
+  NbVertexOnBThVertex=0;
+  NbVertexOnBThEdge=0;
+  VertexOnBThVertex=0;
+  VertexOnBThEdge=0;
+  
+  NbCrackedVertices=0;
+  NbCrackedEdges =0;
+  CrackedEdges  =0;  
+  nbe = 0; 
+  name = fname ;
+  warning=0;
+  if (inbvx) {
+    vertices=new Vertex[nbvx];
+    assert(vertices);
+    ordre=new Vertex* [nbvx];
+    assert(ordre);
+    triangles=new Triangle[nbtx];
+    assert(triangles);}
+  else {
+    vertices=0;
+    ordre=0;
+    triangles=0;
+    nbtx=0;
+   }
+  if ( name || inbvx)
+    {
+      time_t timer =time(0);
+      char buf[70];     
+      strftime(buf ,70,", Date: %y/%m/%d %H:%M %Ss",localtime(&timer));
+      counter++; 
+      char countbuf[30];   
+      sprintf(countbuf,"%d",counter);
+      int lg =0 ;
+      if (&BTh != this && BTh.name)
+	lg = strlen(BTh.name)+4;
+      identity = new char[ lg + strlen(buf) + strlen(countbuf)+ 2  + 10 + ( Gh.name ? strlen(Gh.name) + 4 : 0)];
+      identity[0]=0;
+      if (lg)
+	strcat(strcat(strcat(identity,"B="),BTh.name),", ");
+
+      if (Gh.name)
+	strcat(strcat(identity,"G="),Gh.name);
+      strcat(strcat(identity,";"),countbuf);
+      strcat(identity,buf);
+      // cout << "New MAILLAGE "<< identity << endl;
+    } 
+  
+  quadtree=0;
+//  edgescomponante=0;
+  edges=0;
+  VerticesOnGeomVertex=0;
+  VerticesOnGeomEdge=0;
+  NbVerticesOnGeomVertex=0;
+  NbVerticesOnGeomEdge=0;
+//  nbMaxIntersectionTriangles=0;
+//  lIntTria;
+  subdomains=0;
+  NbSubDomains=0;
+//  Meshbegin = vertices;
+//  Meshend  = vertices + nbvx;
+  if (verbosity>98) 
+    cout << "Triangles::PreInit() " << nbvx << " " << nbtx 
+	 << " " << vertices 
+	 << " " << ordre << " " <<  triangles <<endl;
+
+}
+
+void Triangles::GeomToTriangles1(Int4 inbvx,int KeepBackVertices) 
+{ 
+//#define DRAWING1
+  Gh.NbRef++;// add a ref to Gh
+
+  
+/************************************************************************* 
+// methode in 2 step
+// 1 - compute the number of new edge to allocate
+// 2 - construct the edge
+ remark: 
+  in this part we suppose to have a background mesh with the same
+  geometry 
+  
+  To construct the discretisation of the new mesh we have to 
+  rediscretize the boundary of background Mesh 
+  because we have only the pointeur from the background mesh to the geometry.
+  We need the abcisse of the background mesh vertices on geometry
+  so a vertex is 
+  0 on GeometricalVertex ;
+  1 on GeometricalEdge + abcisse
+  2 internal 
+  
+  *************************************************************************/
+  assert(&BTh.Gh == &Gh);
+
+ // if(verbosity==100) Gh.Write("/tmp/gg.gmsh");
+  BTh.NbRef++; // add a ref to BackGround Mesh
+  PreInit(inbvx);
+  BTh.SetVertexFieldOn();
+#ifdef DRAWING
+  if (withrgraphique)
+   { BTh.InitDraw();
+  reffecran(); 
+  CurrentTh = this;}
+#endif
+  int * bcurve = new int[Gh.NbOfCurves]; // 
+  
+  // we have 2 ways to make the loop 
+  // 1) on the geometry 
+  // 2) on the background mesh
+  //  if you do the loop on geometry, we don't have the pointeur on background,
+  //  and if you do the loop in background we have the pointeur on geometry
+  // so do the walk on  background
+  //  Int4 NbVerticesOnGeomVertex;
+  //  VertexOnGeom * VerticesOnGeomVertex;  
+  //  Int4 NbVerticesOnGeomEdge;
+  //  VertexOnGeom * VerticesOnGeomEdge;
+  
+  
+  NbVerticesOnGeomVertex=0;
+  NbVerticesOnGeomEdge=0;
+  //1 copy of the  Required vertex
+  int i; 
+  for ( i=0;i<Gh.nbv;i++)
+    if (Gh[i].Required()) NbVerticesOnGeomVertex++;
+  
+  VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+  VertexOnBThVertex = new VertexOnVertex[NbVerticesOnGeomVertex];
+  //
+  if( NbVerticesOnGeomVertex >= nbvx) 
+    {
+      cerr << " Too much vertices on geometry " << NbVerticesOnGeomVertex << " >= " << nbvx << endl; 
+      MeshError(1,this);
+    }
+  assert(vertices);
+  for (i=0;i<Gh.nbv;i++)
+    if (Gh[i].Required()) {//Gh  vertices Required
+        vertices[nbv] =  Gh[i];
+        vertices[nbv].i = I2(0,0);
+        Gh[i].to = vertices + nbv;// save Geom -> Th
+        VerticesOnGeomVertex[nbv]= VertexOnGeom(vertices[nbv],Gh[i]);
+	// cout << "--------- "  <<Number(Gh[i].to) << " " << Gh[i].to << " " << i << endl;
+	nbv++;}
+    else Gh[i].to=0;
+  // 
+  for (i=0;i<BTh.NbVerticesOnGeomVertex;i++)
+    { 
+      VertexOnGeom & vog = BTh.VerticesOnGeomVertex[i];
+      if (vog.IsRequiredVertex()) {
+	 GeometricalVertex * gv = vog;
+	 Vertex *bv = vog;
+	 assert(gv->to);// use of Geom -> Th
+	 VertexOnBThVertex[NbVertexOnBThVertex++] = VertexOnVertex(gv->to,bv);
+	 gv->to->m = bv->m; // for taking the metrix of the background mesh
+	 ;}
+    }
+  assert(NbVertexOnBThVertex == NbVerticesOnGeomVertex);
+// new stuff FH with curve
+//  find the begin of the curve in BTh
+{
+  Gh.UnMarkEdges();	
+  int bfind=0;
+/*
+   cout << " nb curves = " << Gh.NbOfCurves << endl;
+   for(int i=0;i<Gh.NbOfCurves ;i++)
+     {
+        cout << " Curve " << i << " begin e=" << Gh.Number(Gh.curves[i].be) << " k=" << Gh.curves[i].kb 
+             << "  end e= " << Gh.Number(Gh.curves[i].ee) << " k=" << Gh.curves[i].ke << endl;
+     }*/
+  for (int i=0;i<Gh.NbOfCurves;i++)
+   {
+    bcurve[i]=-1; 
+   }
+  
+  for (int iedge=0;iedge<BTh.nbe;iedge++) 
+    {      
+      Edge & ei = BTh.edges[iedge];
+      for(int je=0;je<2;je++) // for the 2 extremites
+	 if (!ei.on->Mark() && ei[je].on->IsRequiredVertex() )
+	    {
+	      // a begin of curve 
+	      int nc = ei.on->CurveNumber;
+	      
+	      //cout << "curve " <<  nc << " v " << Gh.Number((GeometricalVertex *) *ei[je].on) << " "
+	      //     << " e "  << " " << Gh.Number(ei.on) << " vc " << Gh.Number((*Gh.curves[nc].be)[Gh.curves[nc].kb]) << endl;
+	      if(
+	         ei.on==Gh.curves[nc].be    && 
+	         (GeometricalVertex *) *ei[je].on == &(*Gh.curves[nc].be)[Gh.curves[nc].kb] //  same extremity 
+	         )     
+	        { 
+	        // cout << " find " << endl;
+	         bcurve[nc]=iedge*2+je;
+	         bfind++;	
+	        }      
+            }
+    } 
+   assert( bfind==Gh.NbOfCurves);
+}          
+// method in 2 + 1 step 
+//  0.0) compute the length and the number of vertex to do allocation
+//  1.0)  recompute the length
+//  1.1)   compute the  vertex 
+  Int4 nbex=0,NbVerticesOnGeomEdgex=0;
+  for (int step=0; step <2;step++)
+    {
+      Int4 NbOfNewPoints=0;
+      Int4 NbOfNewEdge=0;
+      Int4 iedge;
+      Gh.UnMarkEdges();	
+/*   add Curve loop  FH    
+      // find a starting back groud edges to walk 
+      for (iedge=0;iedge<BTh.nbe;iedge++) {      
+	    Edge & ei = BTh.edges[iedge];
+	    for(int jedge=0;jedge<2;jedge++) // for the 2 extremites
+	     if (!ei.on->Mark() && ei[jedge].on->IsRequiredVertex() )
+	    {
+*/  
+// new code FH 2004 
+       Real8 L=0;
+       for (int icurve=0;icurve<Gh.NbOfCurves;icurve++)
+            { 
+              iedge=bcurve[icurve]/2;
+              int jedge=bcurve[icurve]%2;
+              if( ! Gh.curves[icurve].master) continue; // we skip all equi curve
+	      Edge & ei = BTh.edges[iedge];
+	      // warning: ei.on->Mark() can be change in
+	      // loop for(jedge=0;jedge<2;jedge++) 
+	      // new curve  
+	      // good the find a starting edge 
+	      Real8 Lstep=0,Lcurve=0;// step between two points   (phase==1) 
+	      Int4 NbCreatePointOnCurve=0;// Nb of new points on curve     (phase==1) 
+
+	      
+	      //    cout.precision(16);
+	      for(int phase=0;phase<=step;phase++) 
+		{
+
+		  for(Curve * curve= Gh.curves+icurve;curve;curve= curve->next)
+		     {
+
+		    int icurveequi= Gh.Number(curve);
+  
+                   if( phase == 0 &&  icurveequi != icurve)  continue;
+
+                  int k0=jedge,k1;
+                  Edge * pe=  BTh.edges+iedge;
+		  //GeometricalEdge *ong = ei.on;
+                   int iedgeequi=bcurve[icurveequi]/2;
+                   int jedgeequi=bcurve[icurveequi]%2;
+
+                  int k0equi=jedgeequi,k1equi;		  
+                  Edge * peequi= BTh.edges+iedgeequi;
+		  GeometricalEdge *ongequi = peequi->on;
+		  
+                  Real8 sNew=Lstep;// abcisse of the new points (phase==1) 
+                  L=0;// length of the curve
+                  Int4 i=0;// index of new points on the curve
+                   GeometricalVertex * GA0 = *(*peequi)[k0equi].on;
+                  Vertex *A0;
+                  A0 = GA0->to;  // the vertex in new mesh
+                  Vertex *A1;
+		  VertexOnGeom *GA1;
+                  Edge * PreviousNewEdge = 0;
+		  //  cout << "  --------------New Curve phase " << phase 
+		  //       << "---------- A0=" << *A0 << ei[k0]  <<endl;
+                  assert (A0-vertices>=0 && A0-vertices <nbv);
+                  if(ongequi->Required() ) 
+                        {
+                         GeometricalVertex *GA1 = *(*peequi)[1-k0equi].on;
+                         A1 = GA1->to;  //
+                        }       
+                  else 
+                  for(;;) 
+		    {
+		      //   assert(pe && BTh.Number(pe)>=0 && BTh.Number(pe)<=BTh.nbe);
+		      Edge &ee=*pe; 
+		      Edge &eeequi=*peequi; 
+		      k1 = 1-k0; // next vertex of the edge 
+		      k1equi= 1 - k0equi;
+		      
+		      assert(pe  && ee.on);
+		      ee.on->SetMark();
+		      Vertex & v0=ee[0], & v1=ee[1];
+		      R2 AB= (R2) v1 - (R2) v0;
+		      Real8 L0=L,LAB;
+		      LAB =  LengthInterpole(v0.m,v1.m,AB);
+		      L+= LAB;    
+		      if (phase) {// computation of the new points
+			while ((i!=NbCreatePointOnCurve) && sNew <= L) { 
+			  //    cout  << " L0= " << L0 << " L " << L << " sN=" 
+			  //         << sNew << " LAB=" << LAB << " NBPC =" <<NbCreatePointOnCurve<< " i " << i  << endl;
+			  assert (sNew >= L0);
+			  assert(LAB);
+			  
+			  
+			  assert(vertices && nbv<nbvx);
+			  assert(edges && nbe < nbex);
+			  assert(VerticesOnGeomEdge && NbVerticesOnGeomEdge < NbVerticesOnGeomEdgex);
+			  // new vertex on edge
+			  A1=vertices+nbv++;
+			  GA1=VerticesOnGeomEdge+NbVerticesOnGeomEdge;
+			  Edge *e = edges + nbe++;
+			  Real8 se= (sNew-L0)/LAB;
+			  assert(se>=0 && se < 1.000000001);
+#ifdef DEBUG
+			  se =  abscisseInterpole(v0.m,v1.m,AB,se); // because code \ref(xxx)
+#else
+			  se =  abscisseInterpole(v0.m,v1.m,AB,se,1);
+#endif
+			  assert(se>=0 && se <= 1);
+			  //((k1==1) != (k1==k1equi))
+			  se = k1 ? se : 1. - se;
+			  se = k1==k1equi ? se : 1. - se;
+			  VertexOnBThEdge[NbVerticesOnGeomEdge++] = VertexOnEdge(A1,&eeequi,se); // save 
+			  ongequi = Gh.ProjectOnCurve(eeequi,se,*A1,*GA1); 
+			  A1->ReferenceNumber = eeequi.ref;
+			  A1->DirOfSearch =NoDirOfSearch;
+			  //cout << icurveequi << " " << i << " " <<  *A1 << endl;
+			  e->on = ongequi;
+			  e->v[0]=  A0;
+			  e->v[1]=  A1;
+			  if(verbosity>99)
+				cout << i << "+ New P "<< nbv-1 << " "  <<sNew<< " L0=" << L0 
+				<< " AB=" << LAB << " s=" << (sNew-L0)/LAB << " se= "  
+				<< se <<" B edge " << BTh.Number(ee) << " signe = " << k1 <<" " << A1->r <<endl;
+			    
+#ifdef DEBUG
+			  // code \label(xxx)
+			    R2  A1A0 = A1->r - A0->r;
+			    Real8 dp = LengthInterpole(A0->m,A1->m,A1A0);
+			    if (dp > 1.4) {
+			      cerr << " PB new Points "<< nbv-1 ;
+			      cerr << " AB=" << LAB << " s=" << (sNew-L0)/LAB << " se= "  ;
+			      cerr << se <<" B edge " << BTh.Number(ee) << " signe = " << k1 <<endl;	      
+			      cerr << " PB calcul new on cuver points trop loin l=" << dp 
+				   << " v=" << nbv-1 << " " << nbv-2 << " Lcurve = " << Lcurve << AB <<v0.m<< v1.m <<endl;
+			    }
+
+#endif
+			  e->ref = eeequi.ref;
+			  e->adj[0]=PreviousNewEdge;
+			  
+			  if (PreviousNewEdge)
+			    PreviousNewEdge->adj[1] =  e;
+			  PreviousNewEdge = e;
+#ifdef DRAWING1
+			  e->Draw();
+			  //         A0->Draw();
+			  A1->m.Draw(*A1);
+			  A1->Draw(Number(A1));
+#endif
+			  A0=A1;
+			  sNew += Lstep;
+			  //   cout << " sNew = " << sNew << " L = " << L 
+			  //        << "  ------" <<NbCreatePointOnCurve << " " << i <<  endl;
+			  if (++i== NbCreatePointOnCurve) break;
+			}
+			
+		      }               
+		      assert(ee.on->CurveNumber==ei.on->CurveNumber);
+		      if(verbosity>98) cout <<  BTh.Number(ee) << " " << " on=" << *ee[k1].on << " "<< ee[k1].on->IsRequiredVertex() <<  endl;
+		      if ( ee[k1].on->IsRequiredVertex()) {
+		         assert(eeequi[k1equi].on->IsRequiredVertex());
+			 GeometricalVertex * GA1 = *eeequi[k1equi].on;
+			A1=GA1->to;// the vertex in new mesh
+			assert (A1-vertices>=0 && A1-vertices <nbv);
+			break;}
+		      if (!ee.adj[k1])
+			{cerr << "Error adj edge " << BTh.Number(ee) << ", nbe = "  << nbe 
+			      << " Gh.vertices " << Gh.vertices 
+			      << " k1 = " << k1 << " on=" << *ee[k1].on << endl;
+			cerr << ee[k1].on->gv-Gh.vertices << endl;
+			}
+		      pe = ee.adj[k1]; // next edge
+		      k0 = pe->Intersection(ee); 
+		      peequi= eeequi.adj[k1equi];  // next edge
+		      k0equi=peequi->Intersection(eeequi);            
+		    }// for(;;) end of the curve
+		  
+
+		  if (phase) // construction of the last edge
+                    {
+		      Edge *e = edges + nbe++;
+		      if (verbosity>10) 
+			cout << " Fin curve A1" << *A1 << " " << icurve << " <=> " << icurveequi <<"-----" <<
+			  NbCreatePointOnCurve << " == " <<i<<endl;
+                      e->on  = ongequi;
+                      e->v[0]=  A0;
+                      e->v[1]=	A1;
+                      e->ref = peequi->ref;
+                      e->adj[0]=PreviousNewEdge;
+                      e->adj[1]=0;
+                      if (PreviousNewEdge)
+			PreviousNewEdge->adj[1] =  e;
+                      PreviousNewEdge = e;
+		      //		      cout << "Last new edge " << nbe << " " << " on " << Gh.Number(pe->on) 
+		      //   << " of curve =" <<pe->on->CurveNumber <<endl;
+	    
+
+#ifdef DRAWING1 
+                      e->Draw();
+                      A1->Draw();
+                      A0->Draw();
+		      //                      inquire();
+#endif
+                      assert(i==NbCreatePointOnCurve);
+  
+                    }
+		   } //  end loop on equi curve 
+                     
+		  if (!phase)  { // 
+		    Int4 NbSegOnCurve = Max((Int4)(L+0.5),(Int4) 1);// nb of seg
+		    Lstep = L/NbSegOnCurve; 
+		    Lcurve = L;
+		    NbCreatePointOnCurve = NbSegOnCurve-1;
+		    
+		    for(Curve * curve= Gh.curves+icurve;curve;curve= curve->next)
+		     {
+		       NbOfNewEdge += NbSegOnCurve;
+		       NbOfNewPoints += NbCreatePointOnCurve;
+		     }
+		    if(verbosity>5)
+		      cout << icurve << " NbSegOnCurve = " <<  NbSegOnCurve << " Lstep=" 
+			   << Lstep <<" " << NbOfNewPoints<< " NBPC= " << NbCreatePointOnCurve <<endl;
+		    // do'nt 
+		    //  if(NbCreatePointOnCurve<1) break;
+		  }
+		}//for(phase;;)
+/*  modif FH add Curve class  		  
+	    }}//for (iedge=0;iedge<BTh.nbe;iedge++) 
+*/
+// new code Curve class  	
+     } //  end of curve loop 
+// end new code	    
+       // do the allocation
+    if(step==0) 
+      {
+	//if(!NbOfNewPoints) break;// nothing ????? bug 
+	if(nbv+NbOfNewPoints > nbvx) 
+	  {
+	    cerr << " Too much vertices on geometry " << nbv+NbOfNewPoints  << " >= " << nbvx << endl;
+	    MeshError(3,this);
+	  }
+	//cout << " NbOfNewEdge" << NbOfNewEdge << " NbOfNewPoints " << NbOfNewPoints << endl;
+	edges = new Edge[NbOfNewEdge];
+	nbex = NbOfNewEdge;
+	if(NbOfNewPoints) { // 
+	   VerticesOnGeomEdge = new VertexOnGeom[NbOfNewPoints];
+	   NbVertexOnBThEdge =NbOfNewPoints;
+	   VertexOnBThEdge = new  VertexOnEdge[NbOfNewPoints];
+	   NbVerticesOnGeomEdgex = NbOfNewPoints; }
+	NbOfNewPoints =0;
+	NbOfNewEdge = 0;
+      }
+    } // for(step;;)
+  assert(nbe);
+
+ delete [] bcurve;
+ 
+  
+#ifdef DRAWING1
+  reffecran();
+  InitDraw();
+  Draw();
+  inquire();
+#endif
+  
+  Insert();
+  ForceBoundary();
+  FindSubDomain();
+  
+#ifdef DRAWING1
+  reffecran();
+  Draw();
+  inquire();
+#endif
+  // NewPointsOld(*this) ;
+//  BTh.ReMakeTriangleContainingTheVertex(); //  FH change => put in NewPoints
+  //  for (Int4 iv=0;iv<BTh.nbv;iv++)
+  //    BTh[iv].i = toI2(BTh[iv].r);
+  NewPoints(BTh,KeepBackVertices) ;
+  CurrentTh = 0;
+//#undef  DRAWING1 
+}
+
+void Triangles::GeomToTriangles0(Int4 inbvx) 
+{
+  Gh.NbRef++;// add a ref to GH
+
+
+  Int4 i,NbOfCurves=0,NbNewPoints,NbEdgeCurve;
+  Real8 lcurve, lstep,s;
+#ifdef DRAWING
+ if (withrgraphique)
+   {
+  Gh.InitDraw() ;
+  CurrentTh = this; }
+#endif
+  
+  R2 AB;
+  GeometricalVertex *a,*b;
+  Vertex *va,*vb;
+  GeometricalEdge * e;
+  PreInit(inbvx);
+  int  background = &BTh != this;
+  //  int  SameGeom = background && (&BTh.Gh == &Gh);
+  nbv = 0;
+  NbVerticesOnGeomVertex=0;
+  NbVerticesOnGeomEdge=0;
+  for (i=0;i<Gh.nbv;i++)
+    if (Gh[i].Required() && Gh[i].IsThe() ) NbVerticesOnGeomVertex++;
+  VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];  
+//
+  if( NbVerticesOnGeomVertex >= nbvx) 
+    {
+      cerr << " Too much vertices on geometry " << NbVerticesOnGeomVertex << " >= " << nbvx << endl;
+      MeshError(1,this);
+    }
+  for (i=0;i<Gh.nbv;i++)
+    if (Gh[i].Required()&& Gh[i].IsThe()  ) {//Gh  vertices Required
+      if (nbv < nbvx)
+	vertices[nbv] = Gh[i];
+      Gh[i].to = vertices + nbv;// save Geom -> Th
+      VerticesOnGeomVertex[nbv]= VertexOnGeom(*Gh[i].to,Gh[i]);
+    //  cout << "--------- "  <<Number(Gh[i].to) << " " << Gh[i].to << " " << i << endl;
+      nbv++;
+    }
+    if(verbosity>10) cout << " GeomToTriangles0: init nbv : " << nbv << endl;
+//  assert( Gh.nbv < nbvx);
+  
+  // Method in 2 step:  0 and 1 
+  // 1) compute de nb of edge 
+  // 2) construct the edge    
+  // generation of the curves
+  assert(! edges);
+#ifdef DRAWING1
+  reffecran();
+#endif
+// 2 step 
+// --step=0 to compute the number of edges + alloc at end
+// --step=1 to construct the edges
+  for (int step=0;step<2;step++) 
+    {//  for (int step=0;step<2;step++) 
+      Int4 nbex = 0;
+      nbe = 0;
+      Int4 NbVerticesOnGeomEdge0=NbVerticesOnGeomEdge;
+    //  cout <<  "  -------------- step =" << step << endl;
+      Gh.UnMarkEdges();	
+      NbOfCurves = 0;
+      for (i=0;i<Gh.nbe;i++) {
+	GeometricalEdge & ei = Gh.edges[i];   
+	if (!ei.Dup()) // a good curve (not dup )
+	for(int j=0;j<2;j++) 
+	  if (!ei.Mark() && ei[j].Required()) { 
+	    // warning ei.Mark() can be change in loop for(j=0;j<2;j++) 
+	    //  cout << " New curve = " << NbOfCurves << endl;
+	    Int4 nbvend  =0;
+	  
+           Edge * PreviousNewEdge=0;
+
+          lstep = -1;//to do not create points
+	  if(ei.Required())
+	    {
+	      if (j==0)
+              {if(step==0)
+		  nbe++;
+		else
+		  { 
+		    e = & ei;
+		    a=ei(0)->The();
+		    b=ei(1)->The();
+		    assert(edges);
+		    edges[nbe].v[0]=a->to;
+		    edges[nbe].v[1]=b->to;;
+		    edges[nbe].ref = e->ref;
+		    edges[nbe].on = e;
+		    edges[nbe].adj[0] = 0;
+		    edges[nbe].adj[1] = 0;
+#ifdef DRAWING1
+		    edges[nbe].Draw();
+#endif
+                      nbe++;}}
+	    }
+          else 
+	    { // on curve ------
+	      for ( int kstep=0;kstep<= step;kstep++)
+		{ // begin  for ( int kstep=0;kstep<= step;kstep++)
+		  // if 2nd step where 2 step
+		  // -- 1 compute le length of the curve
+		  // -- create the points and edge
+		  PreviousNewEdge=0;
+		  NbNewPoints=0;
+		  NbEdgeCurve=0;
+		  assert(nbvend < nbvx); 
+		  lcurve =0;
+		  s = lstep;
+		  int k=j;
+		  e = & ei;
+		  a=ei(k)->The();
+		  va = a->to;
+		  e->SetMark();
+		  //  cout << " New curve " ;
+		  
+		  // if SameGeo  We have go in the background geometry 
+		  // to find the discretisation of the curve
+		  
+		  for(;;) 
+		    { 
+		      k = 1-k;
+		      b= (*e)(k)->The();
+		      AB = b->r - a->r;
+		      Metric MA = background ? BTh.MetricAt(a->r) :a->m ;
+		      Metric MB =  background ? BTh.MetricAt(b->r) :b->m ;
+		      Real8 ledge = (MA(AB) + MB(AB))/2;
+		      // 
+		      const int MaxSubEdge = 10;
+		      int NbSubEdge = 1;
+		      Real8 lSubEdge[MaxSubEdge];
+		      R2 A,B;
+		      if (ledge < 1.5) 
+			lSubEdge[0] = ledge;
+		      else {
+			NbSubEdge = Min( MaxSubEdge, (int) (ledge +0.5));
+			A= a->r;
+			Metric MAs =MA,MBs;
+			// cout << " lSubEdge old=" << ledge 
+			//      << " new " << A << MA << endl;
+			ledge = 0; 
+			Real8 x =0, xstep= 1. /  NbSubEdge;
+			for (int kk=0; kk < NbSubEdge; kk++,A=B,MAs=MBs ) {
+			  x += xstep;
+			  B =  e->F(k ? x : 1-x);
+			  MBs= background ? BTh.MetricAt(B) :Metric(1-x, MA, x ,MB);
+			  AB = A-B;
+			  lSubEdge[kk]= (ledge += (MAs(AB)+MBs(AB))/2);
+			  // cout << "     " << lSubEdge[kk] << " x " << x  
+			  //      << " " << A << B << MA << MB<< endl ;
+			}
+			//  cout << endl;
+		      }
+		      
+		      Real8 lcurveb = lcurve+ ledge ;
+		      while (lcurve<=s && s <= lcurveb && nbv < nbvend)
+			{
+			  // New points
+			  
+			  // Real8 aa=(lcurveb-s)/ledge;
+			  // Real8 bb=(s-lcurve)/ledge;
+			  
+			  Real8 ss = s-lcurve;
+			  // 1) find the SubEdge containing ss by dichotomie
+			  int kk0=-1,kk1=NbSubEdge-1,kkk;
+			  Real8 ll0=0,ll1=ledge,llk;
+			  while (kk1-kk0>1)
+			    {
+			      if (ss < (llk=lSubEdge[kkk=(kk0+kk1)/2]))
+				kk1=kkk,ll1=llk;
+			      else
+				kk0=kkk,ll0=llk;}
+			  assert(kk1 != kk0);
+			  
+			  Real8 sbb = (ss-ll0  )/(ll1-ll0);
+			  Real8 bb = (kk1+sbb)/NbSubEdge, aa=1-bb;
+			  
+			  // new vertex on edge
+			  vb = &vertices[nbv++];
+			  vb->m = Metric(aa,a->m,bb,b->m);
+			  vb->ReferenceNumber = e->ref;
+			  vb->DirOfSearch =NoDirOfSearch;
+			  Real8 abcisse = k ? bb : aa;
+			  vb->r =  e->F( abcisse );
+			  VerticesOnGeomEdge[NbVerticesOnGeomEdge++]= VertexOnGeom(*vb,*e,abcisse);        
+			  
+			  // to take in account the sens of the edge
+			  
+			  s += lstep;
+			  edges[nbe].v[0]=va;
+			  edges[nbe].v[1]=vb;
+			  edges[nbe].ref = e->ref;
+			  edges[nbe].on = e;
+			  edges[nbe].adj[0] = PreviousNewEdge;
+			  if(PreviousNewEdge)
+			    PreviousNewEdge->adj[1] = &edges[nbe];
+#ifdef DRAWING1
+			  vb->Draw();
+			  edges[nbe].Draw();
+#endif
+			  PreviousNewEdge = edges + nbe;
+			  nbe++;
+                            //  remove DEBUG print to find a bug in examples++-tutorial/periodic4.edp
+                            // under windows
+                            //  after this the bug  disappear (version 3.30 on freefem++  23/04/2014  FH
+                            //  problem optimisation, bug in compiler, bug in freefem++
+                            
+ 
+                         if(verbosity>999)
+                            {
+			  cout << " new points " << nbv-1 << " " << vb->r ;
+			  cout << " new edge " << nbe-1 << " " ;
+			  cout << va << vb <<  " kk0 = " << kk0 
+			       << " " << kk1 << " ss=" << ss ;
+			  cout << " " << sbb << endl;
+			  cout << "      " << aa << va->r << bb << vb->r 
+			       <<" length=" << Norme2(va->r-vb->r) << endl;
+			  cout << "      s " << s << " lstep= " << lstep 
+			       << " ledge= " << ledge 
+			       << " lcurve= " << lcurve << endl;
+                            }
+                            //  end of modification ... DF. Hecht 23/04/2014  FH
+
+			  va = vb;
+			}
+		      lcurve = lcurveb;
+		      e->SetMark();
+		      // cout << e-Gh.edges << ", " << k << " " 
+		      //      <<(*e)[k].r <<" " <<(*e)[1-k].r <<" " 
+		      //      << lcurve<< ";; " ;                          
+		      a=b;
+		      if (b->Required() ) break;
+		      int kprev=k;
+		      k = e->SensAdj[kprev];// next vertices
+		      e = e->Adj[kprev];
+		      assert(e);
+		    }// for(;;)
+		  vb = b->to;
+		  //            cout << endl;
+		  NbEdgeCurve = Max((Int4) (lcurve +0.5), (Int4) 1);
+		  NbNewPoints = NbEdgeCurve-1;
+		  if(!kstep)
+		    { NbVerticesOnGeomEdge0 += NbNewPoints;
+		    NbOfCurves++;}
+		  
+		  nbvend=nbv+NbNewPoints; 
+		  
+		  lstep = lcurve / NbEdgeCurve;
+		  //   cout <<"lstep " << lstep << " lcurve " 
+		  //    << lcurve << " NbEdgeCurve " << NbEdgeCurve << " " <<NbVerticesOnGeomEdge0<<" " <<NbVerticesOnGeomEdge<<" step =" <<step<<  endl;
+		} 
+	      // end of curve --
+	      if (edges) { // last edges of the curves 
+		edges[nbe].v[0]=va;
+		edges[nbe].v[1]=vb;
+		edges[nbe].ref = e->ref;
+		edges[nbe].on = e;
+		edges[nbe].adj[0] = PreviousNewEdge;
+		edges[nbe].adj[1] = 0;
+		if(PreviousNewEdge)
+		  PreviousNewEdge->adj[1] = & edges[nbe];
+		
+		
+#ifdef DRAWING1
+		edges[nbe].Draw();
+#endif
+		nbe++;}
+	      else
+		nbe += NbEdgeCurve;
+	    } // end on  curve ---
+	} // if (edges[i][j].Corner())  
+    } // for (i=0;i<nbe;i++)
+    if(!step) {
+     // cout << "edges " << edges << " VerticesOnGeomEdge " <<VerticesOnGeomEdge << endl;
+      assert(!edges);
+      assert(!VerticesOnGeomEdge);
+      edges = new Edge[nbex=nbe];
+      if(NbVerticesOnGeomEdge0)
+	VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge0];
+      assert(edges);
+      assert(VerticesOnGeomEdge || NbVerticesOnGeomEdge0 ==0);
+        // do the vertex on a geometrical vertex
+       NbVerticesOnGeomEdge0 = NbVerticesOnGeomEdge;       
+     }
+     else 
+       assert(NbVerticesOnGeomEdge == NbVerticesOnGeomEdge0);
+    //     cout << " Nb of Curves = " << NbOfCurves << "nbe = " << nbe 
+    //	  << "== " << nbex << "  nbv = " << nbv <<  endl;
+    assert(nbex=nbe);
+   } // for (step=0;step<2;step++)
+
+#ifdef DRAWING1
+  reffecran();
+  InitDraw();
+  Draw();
+  inquire();
+#endif
+ 
+  Insert();
+  ForceBoundary();
+  FindSubDomain();
+
+#ifdef DRAWING1
+  reffecran();
+  Draw();
+  inquire();
+#endif
+   // NewPointsOld(*this) ;
+    NewPoints(*this,0) ;
+  CurrentTh = 0;
+}
+
+Edge** Triangles::MakeGeometricalEdgeToEdge()
+ {
+  assert(Gh.nbe);
+  Edge **e= new Edge* [Gh.nbe];
+  
+  Int4 i;
+  for ( i=0;i<Gh.nbe ; i++)
+    e[i]=NULL;
+  for ( i=0;i<nbe ; i++) 
+    { 
+      Edge * ei = edges+i;
+      GeometricalEdge *on = ei->on; 
+      e[Gh.Number(on)] = ei;    
+    }
+  for ( i=0;i<nbe ; i++) 
+    for (int ii=0;ii<2;ii++) { 
+       Edge * ei = edges+i;
+       GeometricalEdge *on = ei->on;
+      int j= ii;
+      while (!(*on)[j].Required()) { 
+	//	cout << i << " " << ii << " j= " << j << " curve = " 
+	//           <<  on->CurveNumber << "  " << Gh.Number(on) << " on " << j 
+	//   << " s0 " << Gh.Number( (*on)[0]) << " s1  " << Gh.Number( (*on)[1]) 
+	//   << " ->  " ;
+       Adj(on,j); // next geom edge
+       j=1-j;
+       //       cout << Gh.Number(on) << "  " << j  << " e[ON] =  " <<  e[Gh.Number(on)] 
+       //    << " s0 " << Gh.Number( (*on)[0]) << " s1  " << Gh.Number( (*on)[1]) << endl; 
+       if (e[Gh.Number(on)])  break; // optimisation     
+       e[Gh.Number(on)] = ei; 
+       }
+   }
+
+  int kk=0;
+     for ( i=0;i<Gh.nbe ; i++)
+       if (!e[i]) 
+	 if(kk++<10) {
+	   cerr << " Bug -- the geometrical edge " << i << " is on no edge curve = " << Gh.edges[i].CurveNumber 
+		<< " s0 " << Gh.Number( Gh.edges[i][0]) << " s1  " << Gh.Number( Gh.edges[i][1]) << endl; 
+	 //	 assert( e[i]);
+       }
+  if(kk) MeshError(997,this);
+
+  return e;
+ }
+
+void Triangles::clear()
+{
+  assert(NbRef<=0);
+  if (CurrentTh == this) CurrentTh=0;
+  if(verbosity>10)
+    cout << " ~Triangles "<< this  <<" "<< identity << endl;
+  if(vertices)  delete [] vertices;
+  if(edges)     delete [] edges;
+  if(triangles) delete [] triangles;
+  if(quadtree)  delete  quadtree;
+  if(ordre)     delete [] ordre;
+  if( subdomains) delete []  subdomains;
+  if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge;
+  if (VerticesOnGeomVertex) delete [] VerticesOnGeomVertex;
+  if (name) delete [] name;
+  if (identity) delete [] identity;
+  if (VertexOnBThVertex) delete [] VertexOnBThVertex;
+  if (VertexOnBThEdge) delete [] VertexOnBThEdge;
+  
+  if (&Gh) 
+    {
+      if (Gh.NbRef>0) Gh.NbRef--;
+      else if (Gh.NbRef==0) delete &Gh;
+    }
+  if (&BTh && (&BTh != this))
+    {
+      if (BTh.NbRef>0) BTh.NbRef--;
+      else if (BTh.NbRef==0) delete &BTh;
+    }
+  PreInit(0); // set all to zero 
+  
+}
+
+void Triangles::SetIntCoor(const char * strfrom)
+{
+    pmin =  vertices[0].r;
+    pmax =  vertices[0].r;
+
+    // recherche des extrema des vertices pmin,pmax
+    Int4 i;
+    for (i=0;i<nbv;i++) {
+      pmin.x = Min(pmin.x,vertices[i].r.x);
+      pmin.y = Min(pmin.y,vertices[i].r.y);
+      pmax.x = Max(pmax.x,vertices[i].r.x);
+      pmax.y = Max(pmax.y,vertices[i].r.y);
+    }
+    R2 DD = (pmax-pmin)*0.05;
+    pmin = pmin-DD;
+    pmax = pmax+DD; 
+    coefIcoor= (MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
+    assert(coefIcoor >0);
+
+    // generation of integer coord  
+    for (i=0;i<nbv;i++) {
+      vertices[i].i = toI2(vertices[i].r);    
+    }
+#ifdef DRAWING
+    xGrafCoef = coefIcoor;
+    yGrafCoef = coefIcoor;
+    xGrafOffSet = pmin.x;
+    yGrafOffSet = pmin.y;
+#ifdef DRAWING1
+    rattente(1);
+#endif
+#endif
+
+    // computation of the det 
+    int Nberr=0;
+    for (i=0;i<nbt;i++)
+      {
+	Vertex & v0 = triangles[i][0];
+	Vertex & v1 = triangles[i][1];
+	Vertex & v2 = triangles[i][2];
+      if ( &v0 && &v1 &&  &v2 ) // a good triangles;
+      {
+	triangles[i].det= det(v0,v1,v2);
+	if (triangles[i].det <=0 && Nberr++ <10)
+	  {
+	    if(Nberr==1)
+            { if (strfrom)
+		cerr << "+++ Fatal Error " << strfrom << "(SetInCoor)  Error :  area of Triangle < 0 " << endl; 
+	      else 
+                  cerr << "+++  Fatal Error Triangle (in SetInCoor) area of Triangle < 0" << endl;}
+	    cerr << " Triangle " << i << "  det  (I2) = " << triangles[i].det ;
+	    cerr << " (R2) " << Det(v1.r-v0.r,v2.r-v0.r);
+	    cerr << "; The 3  vertices " << endl;
+	    cerr << Number(v0) << " "  << Number(v1) << " " 
+		 << Number(v2) << " : " ;
+	    cerr << v0.r << v1.r << v2.r << " ; ";
+	    cerr << v0.i << v1.i << v2.i << endl;
+	  }
+      }
+    else
+      triangles[i].det= -1; // Null triangle; 
+      }
+    if (Nberr) MeshError(899,this);
+	
+}
+
+void Triangles::FillHoleInMesh() 
+{
+  Triangles * OldCurrentTh =CurrentTh;
+  CurrentTh=this;
+  //  Int4 NbTold = nbt;
+  // generation of the integer coor
+  {
+ 
+    //  double coef = coefIcoor;
+    // recherche des extrema des vertices pmin,pmax
+    Int4 i;
+    if(verbosity>2)
+      cout << "  -- FillHoleInMesh: Nb of vertices =" << nbv 
+	   << " Pmin = "<< pmin << " Pmax = "<< pmax << endl;
+    
+    assert(ordre);
+    for (i=0;i<nbv;i++) 
+      ordre[i]= 0 ;
+    
+
+    NbSubDomains =0;
+    
+  // generation of the adjacence of the triangles
+    SetOfEdges4 * edge4= new SetOfEdges4(nbt*3,nbv);
+    Int4 * st = new Int4[nbt*3];
+    for (i=0;i<nbt*3;i++)
+      st[i]=-1;
+    Int4 kk =0;
+    for (i=0;i<nbe;i++)
+      kk += (i == edge4->addtrie(Number(edges[i][0]),Number(edges[i][1])));
+    if (kk != nbe)
+      { 
+	cerr << " Some Double edge in the mesh, the number is " << kk-nbe << endl;
+	MeshError(1002,this);
+      }
+    for (i=0;i<nbt;i++)
+      for (int j=0;j<3;j++)
+	{
+	  // Int4 i0,i1;
+	  Int4 k =edge4->addtrie(Number(triangles[i][VerticesOfTriangularEdge[j][0]]),
+				 Number(triangles[i][VerticesOfTriangularEdge[j][1]]));
+	  Int4 invisible = triangles[i].Hidden(j);
+	  if(st[k]==-1)
+	    st[k]=3*i+j;
+	  else if(st[k]>=0) {
+	    assert( ! triangles[i].TriangleAdj(j) && !triangles[st[k] / 3].TriangleAdj((int) (st[k]%3)));
+	    
+	    triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3));
+	    if (invisible)  triangles[i].SetHidden(j);
+	    if (k<nbe) {
+	      triangles[i].SetLocked(j);
+	    }
+	    st[k]=-2-st[k]; }
+	  else {
+	    cerr << " The edge (" 
+	     << Number(triangles[i][VerticesOfTriangularEdge[j][0]])
+		 << " , " 
+		 << Number(triangles[i][VerticesOfTriangularEdge[j][1]])
+		 << " ) is in more than 2 triangles " <<k <<endl;
+	    cerr << " Edge " << j << " Of Triangle " << i << endl;
+	    cerr << " Edge " << (-st[k]+2)%3 << " Of Triangle " << (-st[k]+2)/3  << endl;
+	    cerr << " Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3))
+		 << " Of Triangle " <<  Number(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) << endl;
+	    MeshError(9999,this);}	
+
+
+	}
+    if(verbosity>5) {
+      cout << "    On Mesh " << name << endl;
+      cout << "    - The number of Vertices  = " << nbv << endl;
+      cout << "    - The number of Triangles = " << nbt << endl;
+      cout << "    - The number of given edge = " << nbe << endl;
+      cout << "    - The number of all edges = " << edge4->nb() << endl;
+      cout << "    - The Euler number = 1-Nb Of Hole = " << nbt-edge4->nb()+nbv << endl; }
+    
+    
+    // check the consistant of edge[].adj and the geometrical required  vertex
+     Int4 k=0;
+     for (i=0;i<edge4->nb();i++)
+       if (st[i] >=0) // edge alone 
+       {
+           if (i < nbe)
+	   {
+	     Int4 i0=edge4->i(i);ordre[i0] = vertices+i0;
+	     Int4 i1=edge4->j(i);ordre[i1] = vertices+i1;
+	   }
+     	 else {
+	   k++;
+	   if (verbosity>20 && k <20) 
+	     {
+	     Int4 i0=edge4->i(i);
+	     Int4 i1=edge4->j(i);
+	     cerr << " Lose boundary edges " << i << " : " << i0 << " " << i1 << endl;
+	     }
+	 }
+       }
+     	 
+      if(k != 0) {
+	if (verbosity>20)
+	  {
+	    cout << " The given edge are " << endl;
+	      for (int i=0;i< nbe;i++)
+		cout <<  " Edge " << i << " : " <<  Number(edges[i][0]) << " " <<  Number(edges[i][1]) 
+		     << " " << edges[i].ref << endl; 
+	  }
+	cerr << k << " boundary edges  are not defined as edges " << endl;
+	MeshError(9998,this);
+      }
+      // generation of the mesh with boundary points   
+      Int4 nbvb = 0;
+      for (i=0;i<nbv;i++)
+	{ 
+	  vertices[i].t=0;
+	  vertices[i].vint=0;
+	if (ordre[i]) 
+	  ordre[nbvb++] = ordre[i];
+	}
+
+      Triangle *savetriangles= triangles;
+      Int4 savenbt=nbt;
+      Int4 savenbtx=nbtx;
+      SubDomain * savesubdomains = subdomains;
+      subdomains = 0;
+
+      Int4  Nbtriafillhole = 2*nbvb;
+      Triangle * triafillhole =new Triangle[Nbtriafillhole];
+      if (verbosity>9)
+	cout << " Nbtriafillhole triafillhole*" << triafillhole << endl; 
+      triangles =  triafillhole;
+
+      nbt=2;
+      nbtx= Nbtriafillhole;
+      
+	for (i=2 ; det( ordre[0]->i, ordre[1]->i, ordre[i]->i ) == 0;) 
+	  if  ( ++i >= nbvb) {
+	    cerr << "FillHoleInMesh: All the vertices are aline " << nbvb << endl;
+	    MeshError(998,this); }
+	Exchange( ordre[2], ordre[i]);
+
+	Vertex *  v0=ordre[0], *v1=ordre[1];
+
+
+	triangles[0](0) = 0; // sommet pour infini 
+	triangles[0](1) = v0;
+	triangles[0](2) = v1;
+	
+	triangles[1](0) = 0;// sommet pour infini 
+	triangles[1](2) = v0;
+	triangles[1](1) = v1;
+	const int e0 = OppositeEdge[0];
+	const int e1 = NextEdge[e0];
+	const int e2 = PreviousEdge[e0];
+	triangles[0].SetAdj2(e0, &triangles[1] ,e0);
+	triangles[0].SetAdj2(e1, &triangles[1] ,e2);
+	triangles[0].SetAdj2(e2, &triangles[1] ,e1);
+	
+	triangles[0].det = -1;  // faux triangles
+	triangles[1].det = -1;  // faux triangles
+	
+	triangles[0].SetTriangleContainingTheVertex();
+	triangles[1].SetTriangleContainingTheVertex();
+	
+	triangles[0].link=&triangles[1];
+	triangles[1].link=&triangles[0];
+	
+#ifdef DEBUG 
+	triangles[0].check();
+	triangles[1].check();
+#endif  
+	//  nbtf = 2;
+	if (  !quadtree ) 
+	   delete  quadtree; // ->ReInitialise();
+	
+	  quadtree = new QuadTree(this,0);
+	quadtree->Add(*v0);
+	quadtree->Add(*v1);
+	
+	// on ajoute les sommets un a un 
+	Int4 NbSwap=0;
+	for (Int4 icount=2; icount<nbvb; icount++) {
+	  
+	  Vertex *vi  = ordre[icount];
+	  //	  cout << " Add vertex " <<  Number(vi) << endl;
+	  Icoor2 dete[3];
+	  Triangle *tcvi = FindTriangleContening(vi->i,dete);
+	  quadtree->Add(*vi); 
+	  Add(*vi,tcvi,dete);
+	  NbSwap += vi->Optim(1,1);
+	  
+#ifdef DRAWING2
+	  cout << Number(vi) << " " <<  NbSwap <<  endl;
+	reffecran();
+	Draw();
+	vi->Draw();
+	inquire();
+#endif
+	}// end loop on  icount	
+#ifdef DRAWING1
+	inquire();
+#endif
+	
+	//Int4 nbtfillhole = nbt;
+	 // inforce the boundary 
+	 TriangleAdjacent ta(0,0);
+	 Int4 nbloss = 0,knbe=0;
+	 for ( i = 0; i < nbe; i++) 
+	  if (st[i] >=0)  // edge alone => on border ...  FH oct 2009
+	   {
+	     Vertex & a=edges[i][0], & b =    edges[i][1];
+	     if (a.t && b.t) // le bug est la si maillage avec des bod non raffine 1.
+	       {
+		 knbe++;
+		 if (ForceEdge(a,b,ta)<0)
+		   nbloss++;
+	       }
+	   }
+	 if(nbloss)
+	   {
+	     cerr << " we loss some  " << nbloss << " "  << " edges other " << knbe << endl;
+	     MeshError(1100,this);
+	   }
+	 FindSubDomain(1);
+         // remove all the hole 
+	 // remove all the good sub domain
+	 Int4 krm =0;
+	 for (i=0;i<nbt;i++)
+	   if (triangles[i].link) // remove triangles
+	     {
+	       krm++;
+	       for (int j=0;j<3;j++)
+		 {
+		   TriangleAdjacent ta =  triangles[i].Adj(j);
+		   Triangle & tta = * (Triangle *) ta;
+		   if(! tta.link) // edge between remove and not remove 
+		     { // change the link of ta;
+		       int ja = ta;
+		       Vertex *v0= ta.EdgeVertex(0);
+		       Vertex *v1= ta.EdgeVertex(1);
+		       Int4 k =edge4->addtrie(v0?Number(v0):nbv,v1? Number(v1):nbv);
+		       assert(st[k] >=0); 
+		       tta.SetAdj2(ja,savetriangles + st[k] / 3,(int) (st[k]%3));
+		       ta.SetLock();
+		       st[k]=-2-st[k]; 
+		     }
+		 }
+	     }
+	 Int4 NbTfillHoll =0;
+	 for (i=0;i<nbt;i++)
+	   if (triangles[i].link) {
+	     triangles[i]=Triangle((Vertex *) NULL,(Vertex *) NULL,(Vertex *) NULL);
+	     triangles[i].color=-1;
+	   }
+	   else
+	     {
+	      triangles[i].color= savenbt+ NbTfillHoll++;
+#ifdef DEBUG 
+	     triangles[i].check();
+#endif
+      }
+	 // cout <<      savenbt+NbTfillHoll << " " <<  savenbtx  << endl;
+     assert(savenbt+NbTfillHoll <= savenbtx );
+     // copy of the outside triangles in saveTriangles 
+     for (i=0;i<nbt;i++)
+       if(triangles[i].color>=0) 
+	 {
+          savetriangles[savenbt]=triangles[i];
+	  savetriangles[savenbt].link=0;
+	  savenbt++;
+	 }
+     // gestion of the adj
+      k =0;
+      Triangle * tmax = triangles + nbt;
+      for (i=0;i<savenbt;i++)  
+	{ 
+	  Triangle & ti = savetriangles[i];
+	  for (int j=0;j<3;j++)
+	    {
+	      Triangle * ta = ti.TriangleAdj(j);
+	      int aa = ti.NuEdgeTriangleAdj(j);
+	      int lck = ti.Locked(j);
+	      if (!ta) k++; // bug 
+	      else if ( ta >= triangles && ta < tmax) 
+		{
+		  ta= savetriangles + ta->color;
+		  ti.SetAdj2(j,ta,aa);
+		  if(lck) ti.SetLocked(j);
+		}
+	    }
+	}
+     //	 OutSidesTriangles = triangles;
+      //	Int4 NbOutSidesTriangles = nbt;
+	 
+	 // restore triangles;
+	 nbt=savenbt;
+	 nbtx=savenbtx;
+	 delete [] triangles;
+	 delete [] subdomains;
+	 triangles = savetriangles;
+	 subdomains = savesubdomains;
+	 //	 cout <<  triangles << " <> " << OutSidesTriangles << endl; 
+	     /*	 k=0;
+	 for (i=0;i<nbt;i++)
+	   for (int j=0;j<3;j++)
+	     if (!triangles[i].TriangleAdj(j))
+	     k++;
+	     */
+	 if (k) {
+	   cerr << "Error Nb of triangles edge alone = " << k << endl;
+	   MeshError(9997,this);
+	 }
+	 FindSubDomain();
+	 // cout << " NbTOld = " << NbTold << " ==  " << nbt - NbOutT << " " << nbt << endl;
+  
+    // 
+
+    delete edge4;
+    delete [] st;
+    for (i=0;i<nbv;i++)
+      quadtree->Add(vertices[i]);
+    
+    SetVertexFieldOn();
+
+    for (i=0;i<nbe;i++)
+      if(edges[i].on) 
+	for(int j=0;j<2;j++)
+	  if (!edges[i].adj[j])
+	    if(!edges[i][j].on->IsRequiredVertex()) {
+	      cerr << " Erreur adj et sommet requis edges [" << i <<  "][ " << j << "]= "
+		   <<  Number(edges[i][j]) << " : "  << " on = " << Gh.Number(edges[i].on) ;
+	      if (edges[i][j].on->OnGeomVertex())
+		cerr << " vertex " << Gh.Number(edges[i][j].on->gv);
+	      else if (edges[i][j].on->OnGeomEdge())
+		cerr << "Edges " << Gh.Number(edges[i][j].on->ge);
+	      else
+		cerr << " = " << edges[i][j].on ;
+	      cerr << endl;
+	  }
+    
+#ifdef DRAWING1
+    InitDraw();
+#endif
+    
+  }
+  CurrentTh=OldCurrentTh;
+}
+
+Triangles::Triangles(Triangles & Th,Geometry * pGh,Triangles * pBth,Int4 nbvxx) // COPY OPERATOR
+: Gh(*(pGh?pGh:&Th.Gh)), BTh(*(pBth?pBth:this))
+{
+  Gh.NbRef++;
+  nbvxx = Max(nbvxx,Th.nbv); 
+  Int4 i;
+  // do all the allocation to be sure all the pointer existe
+  
+  char * cname = 0;
+  if (Th.name) 
+    {
+      cname = new char[strlen(Th.name)+1];
+      strcpy(cname,Th.name);
+    }
+  PreInit(nbvxx,cname);// to make the allocation 
+  // copy of triangles
+  nt=Th.nt;
+  nbv = Th.nbv;
+  nbt = Th.nbt;
+  nbiv = Th.nbiv;
+  nbe = Th.nbe;
+  NbSubDomains = Th.NbSubDomains;
+  NbOutT = Th.NbOutT;
+  NbOfQuad =  Th.NbOfQuad ;
+  NbOfSwapTriangle =0;
+  NbVerticesOnGeomVertex = Th.NbVerticesOnGeomVertex;
+  if(NbVerticesOnGeomVertex)
+    VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+  NbVerticesOnGeomEdge = Th.NbVerticesOnGeomEdge;
+  if (NbVerticesOnGeomEdge)
+     VerticesOnGeomEdge = new VertexOnGeom[NbVerticesOnGeomEdge] ;
+  if (& BTh == & Th.BTh) // same back ground 
+    {
+      BTh.NbRef++;
+      NbVertexOnBThVertex = Th.NbVertexOnBThVertex;
+      if(NbVertexOnBThVertex)
+	VertexOnBThVertex = new VertexOnVertex[NbVertexOnBThVertex];
+      NbVertexOnBThEdge = Th.NbVertexOnBThEdge;
+      if(NbVertexOnBThEdge)
+	VertexOnBThEdge = new VertexOnEdge[NbVertexOnBThEdge];
+    }
+   else 
+     { // no add on back ground mesh 
+       BTh.NbRef++;
+       NbVertexOnBThVertex=0;
+       VertexOnBThVertex=0;
+       NbVertexOnBThEdge=0;
+       VertexOnBThEdge=0;
+       //       assert (& BTh == this); // --- a voir 
+		     
+    }
+
+
+  if(nbe)
+    edges = new Edge[nbe];
+  if(NbSubDomains)
+    subdomains = new SubDomain[NbSubDomains];
+  pmin = Th.pmin;
+  pmax = Th.pmax;
+  coefIcoor = Th.coefIcoor;
+  for(i=0;i<nbt;i++)
+     triangles[i].Set(Th.triangles[i],Th,*this);
+  for(i=0;i<nbe;i++)
+     edges[i].Set(Th,i,*this);
+  for(i=0;i<nbv;i++)
+     vertices[i].Set(Th.vertices[i],Th,*this);
+  for(i=0;i<NbSubDomains;i++)  
+    subdomains[i].Set(Th,i,*this);
+  for (i=0;i<NbVerticesOnGeomVertex;i++)
+    VerticesOnGeomVertex[i].Set(Th.VerticesOnGeomVertex[i],Th,*this);
+  for (i=0;i<NbVerticesOnGeomEdge;i++)
+    VerticesOnGeomEdge[i].Set(Th.VerticesOnGeomEdge[i],Th,*this);
+  quadtree=0;
+
+
+  //  assert(!OutSidesTriangles);
+}
+
+/** -- old with a bug we loss some time last swap
+
+Int4  Triangle::Optim(Int2 i,int koption)
+{
+  // turn in the positif sens around vertex s  
+    Int4 NbSwap =0;
+   Vertex * s  = ns[i];
+   Triangle * tbegin=0 , *t = this , *ttc;
+   int k=0,j = EdgesVertexTriangle[i][0],jc;
+  tbegin=t;
+  do {
+    k++; 
+#ifdef DEBUG
+    assert( s == & (*t)[VerticesOfTriangularEdge[j][1]] );
+#endif
+#ifdef DRAWING1 
+    t->Draw();
+    DrawMark( s->r);
+#endif
+     ttc =  t->at[j];
+     jc = NextEdge[t->aa[j]&3];
+     cout << *t << " " <<  VerticesOfTriangularEdge[j][1] << "\n\t try swap " << * ttc << " " << jc ;
+    while ( ttc->swap(jc,koption)) {
+      NbSwap++,assert(k++<20000);
+      ttc =  t->at[j];
+      jc = NextEdge[t->aa[j]&3];
+      cout << "\n\t s  " <<  *ttc << " " << jc << endl;
+    }
+    cout << endl;
+    t = ttc;
+    j = NextEdge[jc];
+    assert(k<20000);
+  } while ( (tbegin != t)); 
+  
+  return NbSwap;
+}
+*/
+Int4  Triangle::Optim(Int2 i,int koption)
+{
+  // turne around in positif sens
+  Int4 NbSwap =0;
+#ifdef DEBUG
+   Vertex * s  = ns[i];
+#endif
+   Triangle  *t = this;
+   int k=0,j =OppositeEdge[i];
+   int jp = PreviousEdge[j];
+   // initialise   tp, jp the previous triangle & edge
+   Triangle *tp= at[jp];
+   jp = aa[jp]&3;
+#ifdef DEBUG
+   assert(tp->at[jp] == this);
+#endif
+   do {
+#ifdef DEBUG
+    assert(k++<20000);
+    assert( s == & (*t)[OppositeVertex[j]] );
+#endif
+    //    cout << *t << " " <<  j  << "\n\t try swap " ;
+    while (t->swap(j,koption))
+      {
+	NbSwap++;
+	assert(k++<20000);
+	t=  tp->at[jp];      // set unchange t qnd j for previous triangles
+	j=  NextEdge[tp->aa[jp]&3];
+	//   cout << "\n\t s  " <<  *t << " " << j << endl;
+#ifdef DEBUG
+	assert( s == & (*t)[OppositeVertex[j]] );
+#endif
+      }
+    // end on this  Triangle 
+    tp = t;
+    jp = NextEdge[j];
+
+    t=  tp->at[jp];      // set unchange t qnd j for previous triangles
+    j=  NextEdge[tp->aa[jp]&3];
+
+   } while( t != this);
+   return NbSwap;
+}
+
+ void Triangles::SmoothingVertex(int nbiter,Real8 omega )
+  { 
+  //  if quatree exist remove it end reconstruct
+    if (quadtree) delete quadtree;
+    quadtree=0;
+    ReMakeTriangleContainingTheVertex();
+    Triangle vide; // a triangle to mark the boundary vertex
+    Triangle   ** tstart= new Triangle* [nbv];
+    Int4 i,j,k;
+    //   attention si Background == Triangle alors on ne peut pas utiliser la rechech rapide 
+    if ( this == & BTh)
+     for ( i=0;i<nbv;i++)
+      tstart[i]=vertices[i].t;     
+    else 
+     for ( i=0;i<nbv;i++)
+      tstart[i]=0;
+    for ( j=0;j<NbVerticesOnGeomVertex;j++ ) 
+      tstart[ Number(VerticesOnGeomVertex[j].mv)]=&vide;
+    for ( k=0;k<NbVerticesOnGeomEdge;k++ ) 
+      tstart[ Number(VerticesOnGeomEdge[k].mv)]=&vide;
+    if(verbosity>2) 
+      cout << "  -- SmoothingVertex: nb Iteration = " << nbiter << " Omega = " << omega << endl;
+    for (k=0;k<nbiter;k++)
+     {
+      Int4 i,NbSwap =0;
+      Real8 delta =0;
+      for ( i=0;i<nbv;i++)
+        if (tstart[i] != &vide) // not a boundary vertex 
+	  delta=Max(delta,vertices[i].Smoothing(*this,BTh,tstart[i],omega));
+      if (!NbOfQuad)
+      for ( i=0;i<nbv;i++)
+        if (tstart[i] != &vide) // not a boundary vertex 
+	  NbSwap += vertices[i].Optim(1);
+       if (verbosity>3)
+	 cout << "    Move max = " <<  sqrt(delta) << " iteration = " 
+	      << k << " Nb of Swap = " << NbSwap << endl;
+       }
+
+    delete [] tstart;
+    if (quadtree) quadtree= new QuadTree(this);
+  }
+void Triangles::MakeQuadTree()
+{  
+  if(verbosity>8)
+    cout << "      MakeQuadTree" << endl;
+  if (  !quadtree )  quadtree = new QuadTree(this);
+
+  
+#ifdef DRAWING1
+  quadtree->Draw();
+  rattente(1);
+  reffecran();
+  quadtree->Draw();
+  rattente(1);
+#endif
+  
+}
+void  Triangles::ShowRegulaty() const// Add FH avril 2007 
+{
+   const  Real8  sqrt32=sqrt(3.)*0.5; 
+   const Real8  aireKh=sqrt32*0.5;
+   D2  Beq(1,0),Heq(0.5,sqrt32);
+   D2xD2 Br(D2xD2(Beq,Heq).t());
+   D2xD2 B1r(Br.inv());
+   /*   D2xD2 BB = Br.t()*Br;
+    cout << " BB = " << BB << " " << Br*B1r <<  endl; 
+    MetricAnIso MMM(BB.x.x,BB.x.y,BB.y.y);
+    MatVVP2x2 VMM(MMM);
+    cout << " " << VMM.lambda1 << " " << VMM.lambda2 <<  endl; 
+   */
+    double gammamn=1e100,hmin=1e100;
+    double gammamx=0,hmax=0;
+    double beta=1e100;
+    double beta0=0;
+    double  alpha2=0;
+    double area=0,Marea=0;
+   // Real8 cf= Real8(coefIcoor);
+   // Real8 cf2= 6.*cf*cf;
+    int nt=0;
+    for (int it=0;it<nbt;it++)
+      if ( triangles[it].link) 
+	{
+	  nt++;
+	  Triangle &K=triangles[it];
+	  Real8  area3= Area2((R2) K[0],(R2) K[1],(R2) K[2])/6.;
+	  area+= area3;
+	  D2xD2 B_Kt(K[0],K[1],K[2]);
+	  D2xD2 B_K(B_Kt.t());
+	  D2xD2 B1K = Br*B_K.inv();
+	  D2xD2 BK =  B_K*B1r;
+	  D2xD2 B1B1 = B1K.t()*B1K;
+	  MetricAnIso MK(B1B1.x.x,B1B1.x.y,B1B1.y.y);
+	  MatVVP2x2 VMK(MK);
+	  alpha2 = Max(alpha2,Max(VMK.lambda1/VMK.lambda2,VMK.lambda2/VMK.lambda1));
+	  // cout << B_K << " * " << B1r << " == " << BK << " " << B_K*B_K.inv() << endl;
+	  Real8 betaK=0;
+	  
+	  for (int j=0;j<3;j++)
+	    {
+	      Real8 he= Norme2(R2(K[j],K[(j+1)%3]));
+	      hmin=Min(hmin,he);
+	      hmax=Max(hmax,he);
+	      Vertex & v=K[j];
+	      D2xD2 M((MetricAnIso)v);
+	      betaK += sqrt(M.det());
+	      
+	      D2xD2 BMB = BK.t()*M*BK;
+	      MetricAnIso M1(BMB.x.x,BMB.x.y,BMB.y.y);
+	      MatVVP2x2 VM1(M1);
+	      //cout << B_K <<" " <<  M << " " <<  he << " " << BMB << " " << VM1.lambda1 << " " << VM1.lambda2<<   endl; 
+	      gammamn=Min3(gammamn,VM1.lambda1,VM1.lambda2);
+	      gammamx=Max3(gammamx,VM1.lambda1,VM1.lambda2);		
+	    }
+	  betaK *= area3;//  1/2 (somme sqrt(det))* area(K)
+	  Marea+= betaK;
+	  // cout << betaK << " " << area3 << " " << beta << " " << beta0 << " " << area3*3*3*3 <<endl;
+	  beta=min(beta,betaK);
+	  beta0=max(beta0,betaK);
+	}   
+    area*=3; 
+    gammamn=sqrt(gammamn);
+    gammamx=sqrt(gammamx);    
+    cout << "  -- adaptmesh Regulary:  Nb triangles " << nt <<  " , h  min " << hmin  << " , h max " << hmax << endl;  
+    cout << "     area =  " << area << " , M area = " << Marea << " , M area/( |Khat| nt) " << Marea/(aireKh*nt) << endl; 
+    cout << "     infiny-regulaty:  min " << gammamn << "  max " << gammamx << endl;  
+    cout << "     anisomax  "<< sqrt(alpha2) << ", beta max = " << 1./sqrt(beta/aireKh) 
+	 << " min  "<<  1./sqrt(beta0/aireKh)  << endl;
+}
+void  Triangles::ShowHistogram() const
+ {
+
+    const Int4 kmax=10;
+    const Real8 llmin = 0.5,llmax=2;
+     const Real8 lmin=log(llmin),lmax=log(llmax),delta= kmax/(lmax-lmin);
+    Int4 histo[kmax+1];
+    Int4 i,it,k, nbedges =0;
+    for (i=0;i<=kmax;i++) histo[i]=0;
+    for (it=0;it<nbt;it++)
+	if ( triangles[it].link) 
+	{
+	     
+	    for (int j=0;j<3;j++)
+	    {
+		Triangle *ta = triangles[it].TriangleAdj(j);
+		if ( !ta || !ta->link || Number(ta) >= it) 
+		{ 
+		    Vertex & vP = triangles[it][VerticesOfTriangularEdge[j][0]];
+		    Vertex & vQ = triangles[it][VerticesOfTriangularEdge[j][1]];
+		    if ( !& vP || !&vQ) continue;
+		    R2 PQ = vQ.r - vP.r;
+		    Real8 l = log(LengthInterpole(vP,vQ,PQ));
+#ifdef DRAWING2             
+		    if (l>1.4)  {
+			penthickness(3);
+			vP.MoveTo(),vQ.LineTo();
+			penthickness(1);
+			cout << "   l = " << l << Number(vP) << " edge = " << Number(vQ) << endl;
+		    }
+#endif             
+		    nbedges++;
+		    k = (int) ((l - lmin)*delta);
+		    k = Min(Max(k,0L),kmax);
+		    histo[k]++;
+		}
+	    }
+	}  
+	    cout << "  -- Histogram of the unit mesh,  nb of edges" << nbedges << endl <<endl;
+ 
+    cout << "        length of edge in   | % of edge  | Nb of edges " << endl;
+    cout << "        ------------------- | ---------- | ----------- " << endl;
+    for   (i=0;i<=kmax;i++)
+      { 
+       cout << "    " ;
+        cout.width(10);
+        if (i==0) cout  << " 0 " ;
+        else cout  << exp(lmin+i/delta) ;
+        cout.width(); cout << "," ;
+        cout.width(10);
+        if (i==kmax) cout << " +infty " ;
+        else cout  << exp(lmin+(i+1)/delta) ;
+        cout.width();cout << "   |   " ;
+        
+       cout.precision(4);
+       cout.width(6);
+       cout <<  ((long)  ((10000.0 * histo[i])/ nbedges))/100.0 ;
+       cout.width();
+       cout.precision();
+       cout <<  "   |   " << histo[i] <<endl;
+      }
+    cout << "        ------------------- | ---------- | ----------- " << endl <<endl;
+    
+ }
+
+int  Triangles::Crack()
+  { 
+    assert(NbCrackedEdges ==0 || NbCrackedVertices >0); 
+    for (int i=0;i<NbCrackedEdges;i++)
+       CrackedEdges[i].Crack();
+    return NbCrackedEdges;
+  }
+  
+int Triangles::UnCrack() 
+{ 
+  assert(NbCrackedEdges ==0 || NbCrackedVertices >0); 
+  for (int i=0;i<NbCrackedEdges;i++)
+    CrackedEdges[i].UnCrack();
+  return NbCrackedEdges;
+}
+
+int Triangles::CrackMesh()
+{
+    Triangles *CurrentThOld = CurrentTh;
+  //  computed the number of cracked edge
+  int i,k;
+  for (k=i=0;i<nbe;i++)
+    if(edges[i].on->Cracked()) k++;
+  if( k==0) return 0;
+    CurrentTh = this;
+  cout << " Nb of Cracked Edges = " << k << endl;
+  NbCrackedEdges =k;
+  CrackedEdges = new  CrackedEdge[k];
+  //  new edge
+  Edge * e = new Edge[ nbe + k];
+
+  // copy
+  for (i=0;i<nbe;i++) 
+    e[i] = edges[i];
+  delete edges;
+  edges = e;
+
+  const int  nbe0  = nbe;
+  for (k=i=0;i<nbe0;i++) // on double les arete cracked 
+    if(edges[i].on->Cracked())
+      {
+	e[nbe] = e[i];
+	//  return the edge 
+	e[nbe].v[0] =  e[i].v[1];
+	e[nbe].v[1] =  e[i].v[0];
+	e[nbe].on = e[i].on->link ; // fqux 
+	CrackedEdges[k++]=CrackedEdge(edges,i,nbe);
+	nbe++;
+      }
+  ReMakeTriangleContainingTheVertex() ; 
+  //  
+  int nbcrakev  =0;
+  Vertex *vlast = vertices + nbv;
+  Vertex *vend = vertices + nbvx; // end of array
+  for (int iv=0;iv<nbv;iv++) // vertex 
+    {
+      Vertex & v= vertices[iv];
+      Vertex * vv = & v;  
+      int kk=0; // nb cracked
+      int kc=0; 
+      int kkk =0; // nb triangle  with same number 
+      Triangle * tbegin = v.t;
+      int i  = v.vint;       
+      assert(tbegin && (i >= 0 ) && (i <3));
+      // turn around the vertex v
+      TriangleAdjacent ta(tbegin,EdgesVertexTriangle[i][0]);// previous edge
+      int k=0;
+      do {
+	int kv = VerticesOfTriangularEdge[ta][1];
+	k++; 
+	Triangle * tt (ta);
+	if ( ta.Cracked() ) 
+	  {   
+	    TriangleAdjacent tta=(ta.Adj());
+	    assert(tta.Cracked());
+	    if ( kk == 0) tbegin=ta,kkk=0;  //  begin by a cracked edge  => restart                
+	    if (  kkk ) { kc =1;vv = vlast++;  kkk = 0; } // new vertex if use 
+	    kk++;// number of cracked edge view                 
+	  }
+	if ( tt->link ) { // if good triangles store the value 
+	  int it = Number(tt);
+	  assert(it < nt);
+	  (*tt)(kv)= vv; //   Change the vertex of triangle 
+	  if(vv<vend) {*vv= v;vv->ReferenceNumber=iv;} // copy the vertex value + store the old vertex number in ref 
+	  //	  tt->SetTriangleContainingTheVertex();
+	  kkk++;
+	} else if (kk) { // crack + boundary 
+	  if (  kkk ) { kc =1;vv = vlast++;  kkk = 0; } // new vertex if use 
+	}
+	
+	ta = Next(ta).Adj(); 
+      } while ( (tbegin != ta)); 
+      assert(k);
+      if (kc)  nbcrakev++;
+    }
+  
+  if ( nbcrakev ) 
+      for (int iec =0;iec < NbCrackedEdges; iec ++)
+	  CrackedEdges[iec].Set();
+  
+  //  set the ref 
+  cout << " set the ref " <<  endl ;
+  NbCrackedVertices =   nbcrakev;
+  // int nbvo = nbv;
+  nbv = vlast - vertices;
+  int nbnewv =  nbv - nbv; // nb of new vrtices 
+  if (nbcrakev && verbosity > 1 )
+    cout << " Nb of craked vertices = " << nbcrakev << " Nb of created vertices " <<   nbnewv<< endl;
+  // all the new vertices are on geometry 
+  //  BOFBO--  A VOIR
+  if (nbnewv)
+    { // 
+      Int4 n = nbnewv+NbVerticesOnGeomVertex;
+      Int4 i,j,k;
+      VertexOnGeom * vog = new VertexOnGeom[n];
+      for ( i =0; i<NbVerticesOnGeomVertex;i++) 
+	vog[i]=VerticesOnGeomVertex[i];
+      delete [] VerticesOnGeomVertex;
+      VerticesOnGeomVertex = vog;
+      // loop on cracked edge 
+      Vertex * LastOld = vertices + nbv - nbnewv;
+      for (int iec =0;iec < NbCrackedEdges; iec ++)
+	for (k=0;k<2;k++)
+	  {
+	    Edge & e = *( k ? CrackedEdges[iec].a.edge : CrackedEdges[iec].b.edge);
+	    for (j=0;j<2;j++) 
+	      {
+		Vertex * v = e(j);
+		if ( v >=  LastOld)
+		  { // a new vertex 
+		    Int4 old = v->ReferenceNumber ; // the old same vertex 
+		    Int4 i  = ( v - LastOld);
+		    //  if the old is on vertex => warning
+		    // else the old is on edge => ok 
+		    vog[i] = vog[old];
+				//  		    vog[i].mv = v;
+				//g[i].ge = ;
+				//og[i].abcisse = ;
+		  }
+		
+	      }
+	  }
+
+	NbVerticesOnGeomVertex = n;
+  }
+  SetVertexFieldOn();
+
+ 
+  if (vlast >= vend)
+    {  
+      cerr << " Not enougth vertices to crack the mesh we need " << nbv << " vertices " << endl;
+      MeshError(555,this);
+    }
+  cout << "  NbCrackedVertices " <<  NbCrackedVertices << endl;
+  CurrentTh = CurrentThOld;
+  return  NbCrackedVertices;
+}
+      
+Triangles::Triangles(const Triangles & Tho,const int *flag ,const int *bb)
+  : Gh(*(new Geometry())), BTh(*this)
+{ // truncature
+  // 
+  
+  char cname[] = "trunc";
+
+  int i,k,itadj;
+  int kt=0;
+  int * kk    = new int [Tho.nbv];
+  Int4 * reft = new Int4[Tho.nbt];
+  Int4 nbInT =    Tho.ConsRefTriangle(reft);
+  Int4 * refv = new Int4[Tho.nbv];
+
+  for (i=0;i<Tho.nbv;i++)
+    kk[i]=-1;
+  for (i=0;i<Tho.nbv;i++)
+    refv[i]=0;
+  int nbNewBedge =0;
+  //  int nbOldBedge =0;  
+  for (i=0;i<Tho.nbt;i++)
+    if(  reft[i] >=0 && flag[i]) 
+      {
+        const Triangle & t = Tho.triangles[i];
+        kt++;
+        kk[Tho.Number(t[0])]=1;
+        kk[Tho.Number(t[1])]=1;
+        kk[Tho.Number(t[2])]=1;
+        itadj=Tho.Number(t.TriangleAdj(0));
+        if (  reft[itadj] >=0 && !flag[itadj])
+          { nbNewBedge++;
+          refv[Tho.Number(t[VerticesOfTriangularEdge[0][0]])]=bb[i];
+          refv[Tho.Number(t[VerticesOfTriangularEdge[0][1]])]=bb[i];
+          }
+        itadj=Tho.Number(t.TriangleAdj(1));
+        if (  reft[itadj] >=0 && !flag[itadj])
+          { nbNewBedge++;
+          refv[Tho.Number(t[VerticesOfTriangularEdge[1][0]])]=bb[i];
+          refv[Tho.Number(t[VerticesOfTriangularEdge[1][1]])]=bb[i];}
+        itadj=Tho.Number(t.TriangleAdj(2));
+        if (  reft[itadj] >=0 && !flag[itadj])
+          { nbNewBedge++;
+          refv[Tho.Number(t[VerticesOfTriangularEdge[2][0]])]=bb[i];
+          refv[Tho.Number(t[VerticesOfTriangularEdge[2][1]])]=bb[i];}
+      }
+  k=0;
+  for (i=0;i<Tho.nbv;i++)
+    if (kk[i]>=0) 
+      kk[i]=k++;
+  cout << " number of vertices " << k << " remove = " << Tho.nbv - k << endl;
+  cout << " number of triangles " << kt << " remove = " << nbInT-kt << endl;
+  cout << " number of New boundary edge " << nbNewBedge << endl;
+  Int4 inbvx =k;
+  PreInit(inbvx,cname);
+  for (i=0;i<Tho.nbv;i++)
+    if (kk[i]>=0) 
+      {
+        vertices[nbv] = Tho.vertices[i];
+        if (!vertices[nbv].ref())
+          vertices[nbv].ReferenceNumber = refv[i];
+        nbv++;
+      }
+  assert(inbvx == nbv);
+  for (i=0;i<Tho.nbt;i++)
+    if(  reft[i] >=0 && flag[i]) 
+      {
+        const Triangle & t = Tho.triangles[i];
+        int i0 = Tho.Number(t[0]);
+        int i1 = Tho.Number(t[1]);
+        int i2 = Tho.Number(t[2]);
+        assert(i0>=0 && i1 >= 0 && i2  >= 0);
+        assert(i0<Tho.nbv && i1 <Tho.nbv && i2  <Tho.nbv);
+        // cout <<i<< " F" <<  flag[i] << " T " << nbt << "   = " <<  kk[i0] << " " << kk[i1] << " " << kk[i2] ;
+        // cout << " OT  " <<  i0 << " "  << i1 << " " << i2  << " " << reft[i] << endl;
+        triangles[nbt] = Triangle(this,kk[i0],kk[i1],kk[i2]);
+        triangles[nbt].color = Tho.subdomains[reft[i]].ref; 
+        nbt++;           
+      }
+  assert(kt==nbt);
+  if (nbt ==0 && nbv ==0) {
+    cout << "Error all triangles was remove " << endl;
+    MeshError(999,this);
+  }
+  delete [] kk;
+  delete [] reft;
+  delete [] refv;
+  double cutoffradian = 10.0/180.0*Pi;
+  ConsGeometry(cutoffradian);
+  Gh.AfterRead(); 
+  SetIntCoor();
+  FillHoleInMesh();
+   
+  assert(NbSubDomains);
+  assert(subdomains[0].head && subdomains[0].head->link);
+             
+}
+  
+Triangle * Triangles::FindTriangleContening(const I2 & B,Icoor2 dete[3], Triangle *tstart) const
+{ // in: B 
+  // out: t
+  // out : dete[3]
+  // t the triangle and s0,s1,s2 the 3 vertices of t
+  // in dete[3] = { det(B,s1,s2) , det(s0,B,s2), det(s0,s1,B)}
+  // with det(a,b,c ) = -1 if one of 3 vertices a,b,c is NULL 
+  Triangle * t=0;	
+  int j,jp,jn,jj;
+  if (tstart) 
+    t=tstart;
+  else 
+   {
+   assert(quadtree);
+   Vertex *a = quadtree->NearestVertex(B.x,B.y) ;
+  
+  if (! a || !a->t ) {
+    if (a) 
+      {cerr << " Attention PB TriangleConteningTheVertex  vertex number=" << Number(a) << endl;
+       cerr  << "We forget a call to ReMakeTriangleContainingTheVertex" << endl;}
+    cerr << " Pb with " << B << toR2(B) << endl;
+    MeshError(7777);
+  }
+  assert(a>= vertices && a < vertices+nbv);
+#ifdef DRAWING1 
+  a->Draw();
+#endif 
+  //  int k=0;
+   t = a->t;
+  assert(t>= triangles && t < triangles+nbt);
+   
+   }
+  Icoor2  detop ;
+  int kkkk =0; // number of test triangle 
+
+  while ( t->det < 0) 
+    { // the initial triangles is outside  
+      int k0=(*t)(0) ?  ((  (*t)(1) ? ( (*t)(2) ? -1 : 2) : 1  )) : 0;
+      assert(k0>=0); // k0 the NULL  vertex 
+      int k1=NextVertex[k0],k2=PreviousVertex[k0];
+      dete[k0]=det(B,(*t)[k1],(*t)[k2]);
+      dete[k1]=dete[k2]=-1;     
+      if (dete[k0] > 0) // outside B 
+        return t; 
+      t = t->TriangleAdj(OppositeEdge[k0]);
+      assert(kkkk++ < 2);
+    }
+
+  jj=0;
+  detop = det(*(*t)(VerticesOfTriangularEdge[jj][0]),*(*t)(VerticesOfTriangularEdge[jj][1]),B);
+ 
+  while(t->det  > 0 ) 
+    { 
+      assert( kkkk++ < 2000 ); 
+      j= OppositeVertex[jj];
+      
+#ifdef DRAWING1
+      t->Draw();
+#endif 
+      dete[j] = detop;  //det(*b,*s1,*s2);
+      jn = NextVertex[j];
+      jp = PreviousVertex[j];
+      dete[jp]= det(*(*t)(j),*(*t)(jn),B);
+      dete[jn] = t->det-dete[j] -dete[jp];
+      
+#ifdef DEBUG
+      const Vertex * s0 = (*t)(0);
+      const Vertex * s1 = (*t)(1);
+      const Vertex * s2 = (*t)(2);
+      assert(dete[0] == det(B ,*s1,*s2));
+      assert(dete[1] == det(*s0,B ,*s2));
+      assert(dete[2] == det(*s0,*s1,B ));
+      assert(t->det== (dete[0] + dete[1] +dete[2]));
+#endif
+      // count the number k of  dete <0
+      int k=0,ii[3];
+      if (dete[0] < 0 ) ii[k++]=0; 
+      if (dete[1] < 0 ) ii[k++]=1;
+      if (dete[2] < 0 ) ii[k++]=2;
+      // 0 => ok
+      // 1 => go in way 1
+      // 2 => two way go in way 1 or 2 randomly
+      
+      if (k==0) 
+	break;
+      if (k == 2 && BinaryRand())
+	Exchange(ii[0],ii[1]);
+      assert ( k  < 3);
+      TriangleAdjacent t1 = t->Adj(jj=ii[0]);
+      if ((t1.det() < 0 ) && (k == 2))
+	t1 = t->Adj(jj=ii[1]);
+      t=t1;
+      j=t1;// for optimisation we now the -det[OppositeVertex[j]];
+      detop = -dete[OppositeVertex[jj]];
+      jj = j;
+    }
+  
+  if (t->det<0) // outside triangle 
+    dete[0]=dete[1]=dete[2]=-1,dete[OppositeVertex[jj]]=detop;
+  //  NbOfTriangleSearchFind += kkkk;  
+  return t;
+}
+
+}
+
diff --git a/src/bamglib/Mesh2.h b/src/bamglib/Mesh2.h
new file mode 100644
index 0000000..c842357
--- /dev/null
+++ b/src/bamglib/Mesh2.h
@@ -0,0 +1,1509 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <limits.h>
+#include <time.h>
+#if  (defined(unix) || defined(__unix)) && !defined(__AIX)
+#define SYSTIMES
+#include <sys/times.h>
+#include <unistd.h>
+#endif
+#ifdef  DRAWING
+#include "rgraph.hpp"
+#endif
+
+extern long verbosity;
+extern int SHOW;
+#include "meshtype.h"
+
+#include "error.hpp"
+
+
+#include "R2.h"
+
+namespace bamg {
+
+
+
+const  double Pi =  3.14159265358979323846264338328;
+const  float fPi =  3.14159265358979323846264338328;
+
+
+class MeshIstream;
+class OFortranUnFormattedFile;
+class IFortranUnFormattedFile;
+
+extern int hinterpole;
+
+
+typedef P2<Icoor1,Icoor2> I2;
+
+inline int BinaryRand(){
+#ifdef RAND_MAX
+ const long HalfRandMax = RAND_MAX/2;
+ return rand() <HalfRandMax;
+#else
+ return rand() & 16384; // 2^14 (for sun because RAND_MAX is not def in stdlib.h)
+#endif
+
+} 
+typedef P2<Real8,Real8> R2;
+typedef P2xP2<Int2,Int4> I2xI2;
+typedef P2<Real4,Real8> R2xR2;
+
+}
+
+#include "Metric.h"
+
+namespace bamg {
+inline float OppositeAngle(float a)
+ {return a<0 ? fPi + a :a - fPi ;}
+inline double OppositeAngle(double a)
+ {return a<0 ? Pi + a :a - Pi ;}
+ 
+#ifdef DRAWING
+extern Real4  xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet;
+extern R2 GrafPMin,GrafPMax;
+extern Real8 Grafh;
+#endif
+
+Icoor2 inline det(const I2 &a,const I2 & b,const I2 &c)
+{
+    Icoor2 bax = b.x - a.x ,bay = b.y - a.y; 
+    Icoor2 cax = c.x - a.x ,cay = c.y - a.y; 
+  return  bax*cay - bay*cax;}
+
+
+
+// def de numerotation dans un triangles 
+static const Int2 VerticesOfTriangularEdge[3][2] = {{1,2},{2,0},{0,1}};
+static const Int2 EdgesVertexTriangle[3][2] = {{1,2},{2,0},{0,1}};
+static const Int2 OppositeVertex[3] = {0,1,2};
+static const Int2 OppositeEdge[3] =  {0,1,2};
+static const Int2 NextEdge[3] = {1,2,0};
+static const Int2 PreviousEdge[3] = {2,0,1};
+static const Int2 NextVertex[3] = {1,2,0};
+static const Int2 PreviousVertex[3] = {2,0,1};
+
+Int4 AGoodNumberPrimeWith(Int4 n);
+
+// remark all the angle are in radian beetwen [-Pi,Pi]
+
+
+class Geometry;
+//static Geometry *NULLGeometry=0;
+class Triangles;
+class Triangle;
+class QuadTree;
+class GeometricalEdge;
+class VertexOnGeom;
+class VertexOnEdge;
+/////////////////////////////////////////////////////////////////////////////////////
+const int IsVertexOnGeom = 8;
+const int IsVertexOnVertex = 16;
+const int IsVertexOnEdge = 32;
+/////////////////////////////////////////////////////////////////////////////////////
+#ifndef  NOTFREEFEM
+class ErrorMesh : public Error
+{  
+public:
+    const Triangles *Th;
+    ErrorMesh(const char * Text,int l,const Triangles * TTh=0, const char *t2="") :
+	Error(MESH_ERROR,"Meshing error: ",Text,"\n number : ",l,", ",t2),Th(TTh)  {}
+};
+#endif
+
+class Direction { //   
+  private:
+  Icoor1 dir;
+  public:
+  Direction(): dir(MaxICoor){}; //  no direction set
+  Direction(Icoor1 i,Icoor1 j) { Icoor2  n2 = 2*(Abs(i)+Abs(j));  
+                                 Icoor2 r = MaxICoor* (Icoor2) i;
+                                 Icoor1 r1 = (Icoor1) (2*(r/ n2)); // odd number 
+                                 dir = (j>0) ? r1 : r1+1; //  odd -> j>0 even -> j<0
+                               }
+  int sens(    Icoor1 i,Icoor1 j) { int r =1; 
+                                   if (dir!= MaxICoor) {
+                                     Icoor2 x(dir/2),y1(MaxICoor/2-Abs(x)),y(dir%2?-y1:y1);
+                                     r = (x*i + y*j) >=0;}
+                                   return r;}
+#ifdef DRAWING
+ void  Draw() {
+                         if (dir!= MaxICoor) {
+                                     Icoor2 x(dir/2),y1(MaxICoor/2-Abs(x)),y(dir%2?-y1:y1);
+                                     R2 D(x,y);
+                                     double eps = Grafh/Norme2(D)/20;
+                                     D = D*eps;
+                                     rmoveto(D.x,D.y);
+                                    }
+  }
+#endif                                   
+                                   
+      
+                              
+  
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class Vertex {public:
+  I2 i;  // allow to use i.x, and i.y in long int (beware of scale and centering)
+  R2 r;  // allow to use r.x, and r.y in double
+  Metric m;
+  Int4 ReferenceNumber;
+  Direction DirOfSearch;
+  union {
+    Triangle * t; // one triangle which contained  the vertex
+    Int4 color;
+    Vertex * to;// use in geometry Vertex to now the Mesh Vertex associed 
+    VertexOnGeom * on;     // if vint 8; // set with Triangles::SetVertexFieldOn()
+    Vertex * onbv; // if vint == 16 on Background vertex Triangles::SetVertexFieldOnBTh()
+    VertexOnEdge * onbe;   // if vint == 32 on Background edge
+  };
+  Int1 vint;  // the vertex number in triangle; varies between 0 and 2 in t
+  operator  I2   () const {return i;} // operator de cast 
+  operator  const R2 & () const {return r;}// operator de cast 
+//  operator  R2 & () {return r;}// operator de cast 
+  Real8 operator()(R2 x) const { return m(x);}
+  operator Metric () const {return m;}// operator de cast 
+  Int4  Optim(int  = 1,int =0); 
+  //  Vertex(){}
+  //  ~Vertex(){}
+  Real8  Smoothing(Triangles & ,const Triangles & ,Triangle  * & ,Real8 =1);
+  int ref() const { return ReferenceNumber;}
+
+  friend ostream& operator <<(ostream& f, const  Vertex & v)
+  {f << "(" << v.i  << "," << v.r << MatVVP2x2(v.m) << ")" ;   return f;}
+  inline void Set(const Vertex & rec,const Triangles &,Triangles &);
+  
+#ifdef DRAWING
+  void  Draw(Int4 =-1) const ;
+  void MoveTo() const  {    rmoveto(r.x,r.y);  }
+  void LineTo() const {    rlineto(r.x,r.y);  }
+#endif  
+};
+
+double QuadQuality(const Vertex &,const Vertex &,const Vertex &,const Vertex &);
+
+// extern Vertex *Meshend , *Meshbegin;
+
+/////////////////////////////////////////////////////////////////////////////////////
+class TriangleAdjacent {
+  friend ostream& operator <<(ostream& f, const  TriangleAdjacent & ta)
+  {f << "{" << ta.t << "," << ((int) ta.a) << "}" ;
+   return f;}
+
+public:
+  Triangle * t; // le triangle 
+  int  a; // le numero de l arete
+  
+  TriangleAdjacent(Triangle  * tt,int  aa): t(tt),a(aa &3) {};
+  TriangleAdjacent() {};
+  
+  operator Triangle * () const {return t;}
+  operator Triangle & () const {return *t;}
+    operator int() const {return a;}
+  TriangleAdjacent & operator++() 
+  {
+    a= NextEdge[a];
+    return *this;}
+  TriangleAdjacent operator--()
+  { 
+    a= PreviousEdge[a];
+    return *this;}
+  inline  TriangleAdjacent  Adj() const ;
+  int swap();
+  inline void SetAdj2(const TriangleAdjacent& , int =0);
+  inline Vertex *  EdgeVertex(const int &) const ;
+  inline Vertex *  OppositeVertex() const ;
+  inline Icoor2 & det() const;
+  inline int Locked() const  ;
+  inline int GetAllFlag_UnSwap() const ;
+  inline void SetLock();
+  inline int MarkUnSwap()  const;
+  inline void SetMarkUnSwap();
+  inline void SetCracked();
+  inline int Cracked() const ;
+};// end of Vertex class  
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+class Edge { public:
+   Vertex * v[2];
+   Int4 ref;
+    GeometricalEdge * on;
+   Vertex & operator[](int i){return *v[i];};
+   Vertex * operator()(int i){return v[i];};
+
+  void ReNumbering(Vertex *vb,Vertex *ve, Int4 *renu) 
+   {
+    if (v[0] >=vb && v[0] <ve) v[0] = vb + renu[v[0]-vb];
+    if (v[1] >=vb && v[1] <ve) v[1] = vb + renu[v[1]-vb];
+   }
+
+  const Vertex & operator[](int i) const { return *v[i];};
+  R2 operator()(double t) const; // return the point 
+  //                                on the curve edge a t in [0:1]
+  Edge * adj[2]; // the 2 adj edges if on the same curve 
+  int Intersection(const  Edge & e) const { 
+    if (!(adj[0]==&e || adj[1]==&e)) 
+      cerr << "Bug : Intersection " << (void*) &e <<  "  " 
+	   << adj[0] << " " <<  adj[1] << endl;
+    assert(adj[0]==&e || adj[1]==&e);
+    return adj[0]==&e ? 0 : 1;}
+  Real8 MetricLength() const ;  
+  inline void Set(const Triangles &,Int4,Triangles &);
+  
+#ifdef DRAWING
+  void  Draw(Int4 = -1) const ;
+#endif
+}; // end of Edge class 
+
+/////////////////////////////////////////////////////////////////////////////////////
+class GeometricalVertex :public Vertex {
+public:
+    int cas;
+    friend class Geometry;
+    GeometricalVertex * link; //  link all the same GeometricalVertex circular (Crack)
+  int Corner() const {return cas&4;}
+  int Required()const {return cas&6;}// a corner is required
+  void  SetCorner(){ cas |= 4;}
+  void  SetRequired(){ cas |= 2;}
+  void  Set(){cas=0;}
+  void  Set(const Vertex & v)
+    { // add for bug in clang++ compile FH very strang and hard  ...
+        i=v.i;
+        r=v.r;
+        m=v.m;
+        t=v.t;
+        vint=v.vint;
+    }
+  GeometricalVertex() :cas(0), link(this) {};
+  GeometricalVertex * The() { assert(link); return link;}// return a unique vertices
+  int IsThe() const { return link == this;}  
+  
+inline void Set(const GeometricalVertex & rec,const Geometry & Gh ,const Geometry & GhNew);
+  inline friend ostream& operator <<(ostream& f, const  GeometricalVertex & s) 
+     { f << s.r << "," << s.cas << ".";return f; }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+class GeometricalEdge {
+  public:
+   GeometricalVertex * v[2];
+   Int4 ref;
+   Int4  CurveNumber;
+  R2 tg[2]; // the 2 tangente 
+  //   if tg[0] =0 => no continuite 
+  GeometricalEdge * Adj [2]; 
+  int SensAdj[2];
+//  private:
+  int flag ;
+  public: 
+  GeometricalEdge * link; // if   Cracked() or Equi()
+
+// end of data 
+  
+  GeometricalVertex & operator[](int i){return *v[i];};
+  const GeometricalVertex & operator[](int i) const { return *v[i];};
+  GeometricalVertex * operator()(int i){return v[i];};  
+ // inline void Set(const Geometry &,Int4,Geometry &);
+
+  R2 F(Real8 theta) const ; // parametrization of the curve edge
+  Real8 R1tg(Real8 theta,R2 &t) const ; // 1/radius of curvature + tangente
+  int Cracked() const {return flag & 1;}
+  int Dup() const { return flag & 32;}
+  int Equi()const {return flag & 2;}
+  int ReverseEqui()const {return flag & 128;}
+  int TgA()const {return flag &4;}
+  int TgB()const {return flag &8;}
+  int Tg(int i) const{return i==0 ? TgA() : TgB();}
+  int Mark()const {return flag &16;}
+  int Required() { return flag & 64;}
+  void SetCracked() { flag |= 1;}
+  void SetDup()     { flag |= 32;} // not a real edge 
+  void SetEqui()    { flag |= 2;}
+  void SetTgA()     { flag|=4;}
+  void SetTgB()     { flag|=8;}
+  void SetMark()    { flag|=16;}
+  void SetUnMark()  { flag &= 1007 /* 1023-16*/;}
+  void SetRequired() { flag |= 64;}
+  void SetReverseEqui() {flag |= 128;}
+  
+  inline void Set(const GeometricalEdge & rec,const Geometry & Th ,Geometry & ThNew);
+
+#ifdef DRAWING 
+  void Draw(Int4  =-1);
+#endif
+  
+};
+  
+class Curve {public:
+ GeometricalEdge * be,*ee; // begin et end edge
+ int kb,ke;  //  begin vetex and end vertex
+ Curve *next; // next curve equi to this
+ bool master; // true => of equi curve point on this curve  
+ inline void Set(const Curve & rec,const Geometry & Th ,Geometry & ThNew);
+ Curve() : be(0),ee(0),kb(0),ke(0),next(0),master(true) {} 
+ void Reverse() { Exchange(be,ee); Exchange(kb,ke);} //  revese the sens of the curse 
+};
+  
+   
+
+/////////////////////////////////////////////////////////////////////////////////////
+class Triangle {
+  friend class TriangleAdjacent;
+  friend ostream& operator <<(ostream& f, const  Triangle & ta);
+
+
+  private: // les arete sont opposes a un sommet
+  Vertex * ns [3]; // 3 vertices if t is triangle, t[i] allowed by access function, (*t)[i] if pointer
+  Triangle * at [3]; // nu triangle adjacent  
+  Int1  aa[3];  // les nu des arete dans le triangles (mod 4)
+  public: 
+  Icoor2 det; // determinant du triangle (2 fois l aire des vertices entieres)
+  union { 
+    Triangle * link ;
+    Int4 color;
+  };
+  void SetDet() {
+    if(ns[0] && ns[1] && ns[2])    det = bamg::det(*ns[0],*ns[1],*ns[2]);
+    else det = -1; }
+  Triangle() {}
+  Triangle(Triangles *Th,Int4 i,Int4 j,Int4 k);
+  Triangle(Vertex *v0,Vertex *v1,Vertex *v2);
+  inline void Set(const Triangle &,const Triangles &,Triangles &);
+  inline int In(Vertex *v) const { return ns[0]==v || ns[1]==v || ns[2]==v ;}
+  TriangleAdjacent FindBoundaryEdge(int ) const;
+
+  void ReNumbering(Triangle *tb,Triangle *te, Int4 *renu) 
+   {
+    if (link  >=tb && link  <te) link  = tb + renu[link -tb];
+    if (at[0] >=tb && at[0] <te) at[0] = tb + renu[at[0]-tb];
+    if (at[1] >=tb && at[1] <te) at[1] = tb + renu[at[1]-tb];
+    if (at[2] >=tb && at[2] <te) at[2] = tb + renu[at[2]-tb];    
+   }
+  void ReNumbering(Vertex *vb,Vertex *ve, Int4 *renu) 
+   {
+    if (ns[0] >=vb && ns[0] <ve) ns[0] = vb + renu[ns[0]-vb];
+    if (ns[1] >=vb && ns[1] <ve) ns[1] = vb + renu[ns[1]-vb];
+    if (ns[2] >=vb && ns[2] <ve) ns[2] = vb + renu[ns[2]-vb];    
+   }
+
+
+  const Vertex & operator[](int i) const {return *ns[i];};
+  Vertex & operator[](int i)  {return *ns[i];};
+  
+  const Vertex  *  operator()(int i) const {return ns[i];};
+  Vertex  * & operator()(int i)  {return ns[i];};
+  
+  TriangleAdjacent Adj(int  i) const  // triangle adjacent + arete 
+  { return TriangleAdjacent(at[i],aa[i]&3);};
+
+  Triangle * TriangleAdj(int  i) const 
+  {return at[i&3];} // triangle adjacent + arete 
+  Int1  NuEdgeTriangleAdj(int  i) const 
+  {return aa[i&3]&3;} // Number of the  adjacent edge in adj tria  
+
+  inline Real4 qualite() ;
+  
+
+  void SetAdjAdj(Int1 a) 
+  { a &= 3;
+     Triangle *tt=at[a];
+   aa [a] &= 55; // remove MarkUnSwap
+    Int1 aatt = aa[a] & 3;
+   if(tt){ 
+     tt->at[aatt]=this;
+     tt->aa[aatt]=a + (aa[a] & 60 ) ;}// Copy all the mark 
+  }
+  
+  void SetAdj2(Int1 a,Triangle *t,Int1 aat)
+    {  at[a]=t;aa[a]=aat;
+    if(t) {t->at[aat]=this;t->aa[aat]=a;}
+    }
+    
+  void SetTriangleContainingTheVertex()
+   { 
+     if (ns[0]) (ns[0]->t=this,ns[0]->vint=0);
+     if (ns[1]) (ns[1]->t=this,ns[1]->vint=1);
+     if (ns[2]) (ns[2]->t=this,ns[2]->vint=2);
+   }
+   
+  int swap(Int2 a1,int=0);
+  Int4  Optim(Int2 a,int =0);
+
+  int  Locked(int a)const { return aa[a]&4;} 
+  int  Hidden(int a)const { return aa[a]&16;} 
+  int  Cracked(int a) const { return aa[a] & 32;}
+  // for optimisation 
+  int  GetAllflag(int a){return aa[a] & 1020;}
+  void SetAllFlag(int a,int f){aa[a] = (aa[a] &3) + (1020 & f);}
+
+  void SetHidden(int a){
+    Triangle * t = at[a];
+    if(t) t->aa[aa[a] & 3] |=16;
+    aa[a] |= 16;}
+  void SetCracked(int a){
+    Triangle * t = at[a];
+    if(t) t->aa[aa[a] & 3] |=32;
+    aa[a] |= 32;}
+  
+  double   QualityQuad(int a,int option=1) const;
+  Triangle * Quadrangle(Vertex * & v0,Vertex * & v1,Vertex * & v2,Vertex * & v3) const ;
+
+  void SetLocked(int a){
+     Triangle * t = at[a];
+    t->aa[aa[a] & 3] |=4;
+    aa[a] |= 4;}
+
+  void SetMarkUnSwap(int a){
+     Triangle * t = at[a];
+    t->aa[aa[a] & 3] |=8;
+    aa[a] |=8 ;}
+
+
+  void SetUnMarkUnSwap(int a){ 
+     Triangle * t = at[a];
+    t->aa[aa[a] & 3] &=55; // 23 + 32 
+    aa[a] &=55 ;}
+  
+
+ 
+#ifdef DEBUG       
+  void inline checka(Int1 a); 
+  void inline check();
+#endif
+
+#ifdef DRAWING
+  void  Draw(Int4 i=-1) const;
+  int swapDRAW(Int2 a1);
+
+#endif
+
+};  // end of Triangle class 
+
+
+
+
+class ListofIntersectionTriangles {
+/////////////////////////////////////////////////////////////////////////////////////
+class IntersectionTriangles {
+public: 
+  Triangle *t;
+  Real8  bary[3];  // use if t != 0
+  R2 x;
+  Metric m;
+  Real8 s;// abscisse curviline
+  Real8 sp; // len of the previous seg in m
+  Real8 sn;// len of the  next seg in m
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class SegInterpolation {
+ public:
+  GeometricalEdge * e;
+  Real8 sBegin,sEnd; // abscisse of the seg on edge parameter
+  Real8 lBegin,lEnd; // length abscisse  set in ListofIntersectionTriangles::Length
+  int last;// last index  in ListofIntersectionTriangles for this Sub seg of edge
+  R2 F(Real8 s){ 
+    Real8 c01=lEnd-lBegin, c0=(lEnd-s)/c01, c1=(s-lBegin)/c01;
+    assert(lBegin<= s && s <=lEnd);
+    return e->F(sBegin*c0+sEnd*c1);}
+};
+ 
+ int MaxSize; // 
+ int Size; //
+ Real8 len; //
+ int state;
+ IntersectionTriangles * lIntTria;
+ int NbSeg;
+ int MaxNbSeg;
+ SegInterpolation * lSegsI;
+ public:
+ IntersectionTriangles & operator[](int i) {return lIntTria[i];}
+ operator int&() {return Size;}
+ ListofIntersectionTriangles(int n=256,int m=16)
+   :   MaxSize(n), Size(0), len(-1),state(-1),lIntTria(new IntersectionTriangles[n]) ,
+    NbSeg(0), MaxNbSeg(m), lSegsI(new SegInterpolation[m])  
+  { if (verbosity>9) 
+    cout << "      construct ListofIntersectionTriangles"
+			  << MaxSize << " " <<  MaxNbSeg<< endl;};
+  ~ListofIntersectionTriangles(){
+    if (lIntTria) delete [] lIntTria,lIntTria=0;
+    if (lSegsI) delete [] lSegsI,lSegsI=0;} 
+  void init(){state=0;len=0;Size=0;}
+  
+  int NewItem(Triangle * tt,Real8 d0,Real8 d1,Real8 d2);
+  int NewItem(R2,const Metric & );
+  void NewSubSeg(GeometricalEdge *e,Real8 s0,Real8 s1) 
+    { 
+      if (NbSeg>=MaxNbSeg) {
+           int mneo= MaxNbSeg;
+           MaxNbSeg *= 2;
+          if (verbosity>3) 
+	    cout <<" reshape lSegsI from " << mneo << " to " 
+		 << MaxNbSeg <<endl;
+           SegInterpolation * lEn =  new SegInterpolation[MaxNbSeg];
+           assert(lSegsI && NbSeg < MaxNbSeg);
+           for (int i=0;i< NbSeg;i++) 
+              lEn[i] = lSegsI[MaxNbSeg]; // copy old to new            
+           delete []  lSegsI; // remove old
+           lSegsI = lEn;        
+           }
+       if (NbSeg) 
+         lSegsI[NbSeg-1].last=Size;
+       lSegsI[NbSeg].e=e;
+       lSegsI[NbSeg].sBegin=s0;
+       lSegsI[NbSeg].sEnd=s1;     
+       NbSeg++;           
+    }
+    
+//  void CopyMetric(int i,int j){ lIntTria[j].m=lIntTria[i].m;}
+//  void CopyMetric(const Metric & mm,int j){ lIntTria[j].m=mm;}
+
+  void ReShape() { 
+     int newsize = MaxSize*2;
+    IntersectionTriangles * nw = new IntersectionTriangles[newsize];
+    assert(nw);
+    for (int i=0;i<MaxSize;i++) // recopy
+      nw[i] = lIntTria[i];       
+    if(verbosity>3)
+      cout << " ListofIntersectionTriangles  ReShape MaxSize " 
+	   << MaxSize << " -> " 
+	 <<  newsize << endl;
+    MaxSize = newsize; 
+    delete [] lIntTria;// remove old
+    lIntTria = nw; // copy pointer
+  }
+  
+  void SplitEdge(const Triangles & ,const R2 &,const R2  &,int nbegin=0); 
+  Real8 Length(); 
+  Int4 NewPoints(Vertex *,Int4 & nbv,Int4 nbvx);
+};
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+class GeometricalSubDomain {
+public:
+  GeometricalEdge *edge;
+  int sens; // -1 or 1
+  Int4 ref;
+  inline void Set(const GeometricalSubDomain &,const Geometry & ,const Geometry &);
+  
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class SubDomain {
+public:
+  Triangle * head;
+  Int4  ref;  
+  int sens; // -1 or 1
+  Edge * edge; // to  geometrical 	
+  inline void Set(const Triangles &,Int4,Triangles &);
+  	 
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class VertexOnGeom {  public:
+
+  Vertex * mv;
+  Real8 abscisse;  
+  union{ 
+    GeometricalVertex * gv; // if abscisse <0; 
+    GeometricalEdge * ge;  // if abscisse in [0..1]
+  };
+  inline void Set(const VertexOnGeom&,const Triangles &,Triangles &);  
+  int OnGeomVertex()const {return this? abscisse <0 :0;}
+  int OnGeomEdge() const {return this? abscisse >=0 :0;}
+  VertexOnGeom(): mv(0),abscisse(0){gv=0;} 
+  VertexOnGeom(Vertex & m,GeometricalVertex &g) : mv(&m),abscisse(-1){gv=&g;}
+   //  cout << "        mv = " <<mv << " gv = "  << gv << endl;} 
+  VertexOnGeom(Vertex & m,GeometricalEdge &g,Real8 s) : mv(&m),abscisse(s){ge=&g;}
+    //cout << &g << " "  << ge << endl;} 
+  operator Vertex * () const  {return mv;}
+  operator GeometricalVertex * () const  {return gv;}
+  operator GeometricalEdge * () const  {return ge;}
+//  operator Real8 & () {return abscisse;}
+  operator const Real8 & () const {return abscisse;}
+  int IsRequiredVertex(){ return this? (( abscisse<0 ? (gv?gv->Required():0):0 )) : 0;}
+  void SetOn(){mv->on=this;mv->vint=IsVertexOnGeom;}
+  friend ostream& operator <<(ostream& f, const  VertexOnGeom & vog){
+    f << vog.abscisse << " " << vog.mv << " " << vog.gv << " ; ";
+    if (vog.abscisse < 0) f << *vog.gv << " ;; " ;
+    //    else f << *vog.ge << " ;; " ;
+    return f;}
+  inline void Set(const Triangles &,Int4,Triangles &);
+    
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class VertexOnVertex {public:
+  Vertex * v, *bv;
+  VertexOnVertex(Vertex * w,Vertex *bw) :v(w),bv(bw){}
+  VertexOnVertex() {};
+  inline void Set(const Triangles &,Int4,Triangles &);
+  void SetOnBTh(){v->onbv=bv;v->vint=IsVertexOnVertex;}
+};
+/////////////////////////////////////////////////////////////////////////////////////
+class VertexOnEdge {public:
+  Vertex * v;
+  Edge * be;
+  Real8 abcisse;
+  VertexOnEdge( Vertex * w, Edge *bw,Real8 s) :v(w),be(bw),abcisse(s) {}
+  VertexOnEdge(){}
+  inline void Set(const Triangles &,Int4,Triangles &);  
+  void SetOnBTh(){v->onbe=this;v->vint=IsVertexOnEdge;}  
+  Vertex & operator[](int i) const { return (*be)[i];}
+  operator Real8 () const { return abcisse;}
+  operator  Vertex *  () const { return v;}  
+  operator  Edge *  () const { return be;}  
+};
+
+ inline TriangleAdjacent FindTriangleAdjacent(Edge &E);
+ inline Vertex * TheVertex(Vertex * a); // for remove crak in mesh 
+/////////////////////////////////////////////////////////////////////////////////////
+ 
+class CrackedEdge { // a small class to store on crack an uncrack information 
+  friend class Triangles;
+  friend ostream& operator <<(ostream& f, const   Triangles & Th) ;  
+ class CrackedTriangle {
+  friend class Triangles;
+  friend class CrackedEdge;
+  friend ostream& operator <<(ostream& f, const   Triangles & Th) ;  
+  Triangle * t; // edge of triangle t
+  int i; //  edge number of in triangle
+  Edge *edge; // the  2 edge 
+  Vertex *New[2]; // new vertex number 
+  CrackedTriangle() : t(0),i(0),edge(0) { New[0]=New[1]=0;} 
+  CrackedTriangle(Edge * a) : t(0),i(0),edge(a) { New[0]=New[1]=0;} 
+  void Crack(){ 
+    Triangle & T(*t); 
+    int i0=VerticesOfTriangularEdge[i][0];
+    int i1=VerticesOfTriangularEdge[i][0];
+    assert(New[0] && New[1]);
+    T(i0) = New[0];
+    T(i1) = New[1];}    
+  void UnCrack(){ 
+    Triangle & T(*t); 
+    int i0=VerticesOfTriangularEdge[i][0];
+    int i1=VerticesOfTriangularEdge[i][0];
+    assert(New[0] && New[1]);
+    T(i0) = TheVertex(T(i0));
+    T(i1) = TheVertex(T(i1));} 
+  void Set() {
+     TriangleAdjacent ta ( FindTriangleAdjacent(*edge));
+     t = ta;
+     i = ta;
+     
+     New[0] = ta.EdgeVertex(0);
+     New[1] = ta.EdgeVertex(1);
+     // warning the ref 
+     
+     }    
+     
+  }; // end of class CrackedTriangle
+ public:  
+  CrackedTriangle a,b; 
+  CrackedEdge() :a(),b() {}
+  CrackedEdge(Edge * start, Int4  i,Int4 j) : a(start+i),b(start+j) {};
+  CrackedEdge(Edge * e0, Edge * e1 ) : a(e0),b(e1) {};
+
+  void Crack() { a.Crack(); b.Crack();}
+  void UnCrack() { a.UnCrack(); b.UnCrack();}
+  void Set() { a.Set(), b.Set();}
+};
+
+/////////////////////////////////////////////////////////////////////////////////////
+
+class Triangles { 
+public:
+
+  enum TypeFileMesh {
+    AutoMesh=0,BDMesh=1,NOPOMesh=2,amMesh=3,am_fmtMesh=4,amdbaMesh=5,
+//-----------------------------ajout format hdf5-----------------------------//
+    //    ftqMesh=6,mshMesh=7};
+    ftqMesh=6,mshMesh=7,hdf5Mesh=8};
+//-----------------------------ajout format hdf5-----------------------------//
+
+  int static counter; // to kown the number of mesh in memory 
+  int OnDisk;       // true if on disk 
+  Geometry & Gh;   // Geometry
+  Triangles & BTh; // Background Mesh Bth==*this =>no  background 
+  
+  Int4 NbRef; // counter of ref on the this class if 0 we can delete
+  Int4 nbvx,nbtx;  // nombre max  de sommets , de  triangles
+  
+  Int4 nt,nbv,nbt,nbiv,nbe; // nb of legal triangles, nb of vertex, of triangles, 
+  // of initial vertices, of edges with reference,
+  Int4 NbOfQuad; // nb of quadrangle 
+
+  Int4 NbSubDomains; // 
+  Int4 NbOutT; // Nb of oudeside triangle
+  Int4 NbOfTriangleSearchFind;
+  Int4 NbOfSwapTriangle;
+  char * name, *identity;
+  Vertex * vertices;   // data of vertices des sommets
+  
+  Int4 NbVerticesOnGeomVertex;
+  VertexOnGeom * VerticesOnGeomVertex;
+  
+  Int4 NbVerticesOnGeomEdge;
+  VertexOnGeom * VerticesOnGeomEdge;
+
+  Int4 NbVertexOnBThVertex;
+  VertexOnVertex *VertexOnBThVertex;
+
+  Int4 NbVertexOnBThEdge;
+  VertexOnEdge *VertexOnBThEdge;
+
+  
+  Int4 NbCrackedVertices;
+  
+
+  Int4 NbCrackedEdges;
+  CrackedEdge *CrackedEdges;
+  
+  
+  R2 pmin,pmax; // extrema
+  Real8 coefIcoor;  // coef to integer Icoor1;
+
+  Triangle * triangles;
+  Edge * edges; 
+
+  QuadTree *quadtree;
+  Vertex ** ordre;
+  SubDomain * subdomains;
+  ListofIntersectionTriangles  lIntTria;
+  int warning ;
+// end of variable
+  
+  Triangles(Int4 i);//:BTh(*this),Gh(*new Geometry()){PreInit(i);}
+  void clear();
+    ~Triangles() {if(NbRef==0) {clear();NbRef=-1;}}
+  Triangles(const char * ,Real8=-1) ;
+  
+ 
+  Triangles(Int4 nbvx,Triangles & BT,int keepBackVertices=1)
+         :Gh(BT.Gh),BTh(BT) {
+	     try {GeomToTriangles1(nbvx,keepBackVertices);}
+	      catch(...) { this->clear(); throw; } }
+  
+  Triangles(Int4 nbvx,Geometry & G)
+         :Gh(G),BTh(*this){
+	     try { GeomToTriangles0(nbvx);}
+	     catch(...) { this->clear(); throw; } }
+  Triangles(Triangles &,Geometry * pGh=0,Triangles* pBTh=0,Int4 nbvxx=0 ); // COPY OPERATEUR
+  //  Triangles(Triangles &){ cerr << " BUG call copy opretor of Triangles" << endl;MeshError(111);}
+  Triangles(const Triangles &,const int *flag,const int *bb); // truncature
+  
+
+  void SetIntCoor(const char * from =0);
+
+ // void  RandomInit();
+ // void  CubeInit(int ,int);
+  
+  Real8 MinimalHmin() {return 2.0/coefIcoor;}
+  Real8 MaximalHmax() {return Max(pmax.x-pmin.x,pmax.y-pmin.y);}
+  const Vertex & operator[]  (Int4 i) const { return vertices[i];};
+  Vertex & operator[](Int4 i) { return vertices[i];};
+  const Triangle & operator()  (Int4 i) const { return triangles[i];};
+  Triangle & operator()(Int4 i) { return triangles[i];};
+  I2 toI2(const R2 & P) const {
+          return  I2( (Icoor1) (coefIcoor*(P.x-pmin.x))
+	                 ,(Icoor1) (coefIcoor*(P.y-pmin.y)) );}
+  R2 toR2(const I2 & P) const {
+          return  R2( (double) P.x/coefIcoor+pmin.x, (double) P.y/coefIcoor+pmin.y);}
+  void Add( Vertex & s,Triangle * t,Icoor2 *  =0) ;
+  void Insert();
+  //  void InsertOld();
+  void ForceBoundary();
+  void Heap();
+  void FindSubDomain(int );
+  Int4  ConsRefTriangle(Int4 *) const;
+  void ShowHistogram() const;
+  void  ShowRegulaty() const; // Add FH avril 2007 
+//  void ConsLinkTriangle();
+
+  void ReMakeTriangleContainingTheVertex();
+  void UnMarkUnSwapTriangle();
+  void SmoothMetric(Real8 raisonmax) ;
+  void BoundAnisotropy(Real8 anisomax,double hminaniso= 1e-100) ;
+  void MaxSubDivision(Real8 maxsubdiv);
+  void WriteMetric(ostream &,int iso) ;
+  Edge** MakeGeometricalEdgeToEdge();
+  void  SetVertexFieldOn();  
+  void  SetVertexFieldOnBTh();
+  Int4 SplitInternalEdgeWithBorderVertices();
+  void MakeQuadrangles(double costheta);
+  int SplitElement(int choice);
+  void MakeQuadTree();
+  void NewPoints( Triangles &,int KeepBackVertex =1 );
+  Int4 InsertNewPoints(Int4 nbvold,Int4 & NbTSwap) ; 
+  void NewPointsOld( Triangles & );
+  void NewPoints(int KeepBackVertex=1){ NewPoints(*this,KeepBackVertex);}
+  void ReNumberingTheTriangleBySubDomain(bool justcompress=false);
+  void ReNumberingVertex(Int4 * renu);
+  void SmoothingVertex(int =3,Real8=0.3);
+  Metric MetricAt (const R2 &) const;
+  GeometricalEdge * ProjectOnCurve( Edge & AB, Vertex &  A, Vertex & B,Real8 theta,
+                      Vertex & R,VertexOnEdge & BR,VertexOnGeom & GR);
+   
+  
+  void WriteElements(ostream& f,Int4 * reft ,Int4 nbInT) const;
+
+  
+  Int4 Number(const Triangle & t) const  { return &t - triangles;}
+  Int4 Number(const Triangle * t) const  { return t - triangles;}
+  Int4 Number(const Vertex & t) const  { return &t - vertices;}
+  Int4 Number(const Vertex * t) const  { return t - vertices;}
+  Int4 Number(const Edge & t) const  { return &t - edges;}
+  Int4 Number(const Edge * t) const  { return t - edges;}
+  Int4 Number2(const Triangle * t) const  {
+    //   if(t>= triangles && t < triangles + nbt )
+      return t - triangles;
+      //  else  return t - OutSidesTriangles;
+  }
+  
+  Vertex * NearestVertex(Icoor1 i,Icoor1 j) ;
+  Triangle * FindTriangleContening(const I2 & ,Icoor2 [3],Triangle *tstart=0) const;
+  void Write(const char * filename,const TypeFileMesh type = AutoMesh);
+  void Write_am_fmt(ostream &) const ;
+  void Write_am(ostream &) const ;
+  void Write_ftq(ostream &) const ;
+  void Write_nopo(ostream &) const ;
+  void Write_msh(ostream &) const ;
+//-----------------------------ajout format hdf5-----------------------------//
+  void Write_hdf5(const char * filename) const ;
+//-----------------------------ajout format hdf5-----------------------------//
+  void Write_amdba(ostream &) const ;
+
+  void Read(MeshIstream &,int version,Real8 cutoffradian);
+  void Read_am_fmt(MeshIstream &);
+  void Read_amdba(MeshIstream &);
+  void Read_am(MeshIstream &);
+  void Read_nopo(MeshIstream &);
+  void Read_ftq(MeshIstream &);
+  void Read_msh(MeshIstream &);
+
+  void ReadMetric(const char * fmetrix,const Real8 hmin,const Real8 hmax,const Real8 coef);
+  void IntersectConsMetric(const double * s,const Int4 nbsol,const int * typsols,
+			   const  Real8 hmin,const Real8 hmax, const Real8 coef,
+			   const Real8  anisomax,const Real8 CutOff=1.e-4,const int NbJacobi=1,
+			   const int DoNormalisation=1,
+			   const double power=1.0,
+			   const int choise=0);
+  void IntersectGeomMetric(const Real8 err,const int iso);
+  
+  
+  int  isCracked() const {return NbCrackedVertices != 0;}
+  int  Crack();
+  int UnCrack();
+  
+#ifdef DEBUG
+  void inline Check(); 
+#endif
+#ifdef DRAWING
+  void  Draw() const ;
+  void  InitDraw() const ;
+  void   inquire()  ;
+#endif
+ friend ostream& operator <<(ostream& f,  const  Triangles & Th); 
+  void  Write(const char * filename);
+  void ConsGeometry(Real8 =-1.0,int *equiedges=0); // construct a geometry if no geo 
+  void FillHoleInMesh() ;
+  int CrackMesh();
+ private:
+  void GeomToTriangles1(Int4 nbvx,int KeepBackVertices=1);// the  real constructor mesh adaption
+  void GeomToTriangles0(Int4 nbvx);// the  real constructor mesh generator
+  void PreInit(Int4,char * =0 );
+  //
+  void Write_nop5(OFortranUnFormattedFile * f,
+			     Int4 &lnop5,Int4 &nef,Int4 &lgpdn,Int4 ndsr) const ;
+
+  
+}; // End Class Triangles
+/////////////////////////////////////////////////////////////////////////////////////
+class Geometry { 
+public:
+  int OnDisk; 
+  Int4 NbRef; // counter of ref on the this class if 0 we can delete
+
+  char *name;
+  Int4 nbvx,nbtx; // nombre max  de sommets , de  Geometry
+  Int4 nbv,nbt,nbiv,nbe; // nombre de sommets, de Geometry, de sommets initiaux,
+  Int4 NbSubDomains; // 
+  Int4 NbEquiEdges;
+  Int4 NbCrackedEdges; 
+//  Int4 nbtf;//  de triangle frontiere
+  Int4 NbOfCurves;
+  int empty(){return (nbv ==0) && (nbt==0) && (nbe==0) && (NbSubDomains==0); }
+  GeometricalVertex * vertices;   // data of vertices des sommets 
+  Triangle * triangles; 
+  GeometricalEdge * edges;
+  QuadTree *quadtree;
+  GeometricalSubDomain *subdomains;
+  Curve *curves;
+  ~Geometry(); 
+  Geometry(const Geometry & Gh); //Copy  Operator 
+  Geometry(int nbg,const Geometry ** ag); // intersection operator 
+  
+  R2 pmin,pmax; // extrema
+  Real8 coefIcoor;  // coef to integer Icoor1;
+  Real8 MaximalAngleOfCorner;
+  
+//  end of data 
+
+  
+  I2 toI2(const R2 & P) const {
+          return  I2( (Icoor1) (coefIcoor*(P.x-pmin.x))
+	                 ,(Icoor1) (coefIcoor*(P.y-pmin.y)) );}
+  
+  Real8 MinimalHmin() {return 2.0/coefIcoor;}
+  Real8 MaximalHmax() {return Max(pmax.x-pmin.x,pmax.y-pmin.y);}
+  void ReadGeometry(const char * ) ;
+  void ReadGeometry(MeshIstream & ,const char *)  ;
+
+  void EmptyGeometry();
+  Geometry() {EmptyGeometry();}// empty Geometry
+  void AfterRead();
+  Geometry(const char * filename) {EmptyGeometry();OnDisk=1;ReadGeometry(filename);AfterRead();}
+
+  void ReadMetric(const char *,Real8 hmin,Real8 hmax,Real8 coef);
+  const GeometricalVertex & operator[]  (Int4 i) const { return vertices[i];};
+  GeometricalVertex & operator[](Int4 i) { return vertices[i];};
+  const  GeometricalEdge & operator()  (Int4 i) const { return edges[i];};
+  GeometricalEdge & operator()(Int4 i) { return edges[i];}; 
+  Int4 Number(const GeometricalVertex & t) const  { return &t - vertices;}
+  Int4 Number(const GeometricalVertex * t) const  { return t - vertices;}
+  Int4 Number(const GeometricalEdge & t) const  { return &t - edges;}
+  Int4 Number(const GeometricalEdge * t) const  { return t - edges;}
+  Int4 Number(const Curve * c) const  { return c - curves;}
+  
+  void UnMarkEdges() {
+    for (Int4 i=0;i<nbe;i++) edges[i].SetUnMark();}
+
+ GeometricalEdge *  ProjectOnCurve(const Edge & ,Real8,Vertex &,VertexOnGeom &) const ;
+  GeometricalEdge *  Contening(const R2 P,  GeometricalEdge * start) const;
+ friend ostream& operator <<(ostream& f, const   Geometry & Gh); 
+ void Write(const char * filename);
+ 
+#ifdef DEBUG
+  void inline Check();   
+#endif
+#ifdef DRAWING
+  void  Draw() const ;
+  void  InitDraw() const ;
+#endif
+  
+}; // End Class Geometry
+
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+///////////////////           END CLASS          ////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+
+inline Triangles::Triangles(Int4 i) :Gh(*new Geometry()),BTh(*this){PreInit(i);}
+
+extern Triangles * CurrentTh;
+
+TriangleAdjacent CloseBoundaryEdge(I2 ,Triangle *, double &,double &) ;
+TriangleAdjacent CloseBoundaryEdgeV2(I2 A,Triangle *t, double &a,double &b);
+
+Int4 FindTriangle(Triangles &Th, Real8 x, Real8 y, double* a,int & inside);
+
+
+
+inline Triangle *    Triangle::Quadrangle(Vertex * & v0,Vertex * & v1,Vertex * & v2,Vertex * & v3) const
+{
+// return the other triangle of the quad if a quad or 0 if not a quat
+  Triangle * t =0;
+  if (link) {
+    int a=-1;
+    if (aa[0] & 16 ) a=0;
+    if (aa[1] & 16 ) a=1;
+    if (aa[2] & 16 ) a=2;
+    if (a>=0) {
+      t = at[a];
+      //  if (t-this<0) return 0;
+      v2 = ns[VerticesOfTriangularEdge[a][0]];
+      v0 = ns[VerticesOfTriangularEdge[a][1]];
+      v1 = ns[OppositeEdge[a]];
+      v3 = t->ns[OppositeEdge[aa[a]&3]];
+    }
+  }
+  return t;
+}
+
+inline   double   Triangle::QualityQuad(int a,int option) const
+{ // first do the logique part 
+  double q;
+  if (!link || aa[a] &4)
+    q=  -1;
+  else {
+    Triangle * t = at[a];
+    if (t-this<0) q=  -1;// because we do 2 times 
+    else if (!t->link ) q=  -1;
+    else if (aa[0] & 16 || aa[1] & 16  || aa[2] & 16 || t->aa[0] & 16 || t->aa[1] & 16 || t->aa[2] & 16 )
+      q= -1;
+    else if(option) 
+      { 
+	const Vertex & v2 = *ns[VerticesOfTriangularEdge[a][0]];
+	const Vertex & v0 = *ns[VerticesOfTriangularEdge[a][1]];
+	const Vertex & v1 = *ns[OppositeEdge[a]];
+	const Vertex & v3 = * t->ns[OppositeEdge[aa[a]&3]];
+	q =  QuadQuality(v0,v1,v2,v3); // do the float part
+      }
+    else q= 1;
+  }
+  return  q;
+}
+
+
+inline void Vertex::Set(const Vertex & rec,const Triangles & ,Triangles & )
+ { 
+   *this  = rec;
+ }
+inline void GeometricalVertex::Set(const GeometricalVertex & rec,const Geometry & ,const Geometry & )
+ { 
+   *this  = rec;
+ }
+inline void Edge::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+ { 
+   *this = Th.edges[i];
+   v[0] = ThNew.vertices + Th.Number(v[0]);    
+   v[1] = ThNew.vertices + Th.Number(v[1]);
+   if (on) 
+     on =  ThNew.Gh.edges+Th.Gh.Number(on);
+   if (adj[0]) adj[0] =   ThNew.edges +   Th.Number(adj[0]);
+   if (adj[1]) adj[1] =   ThNew.edges +   Th.Number(adj[1]);
+
+ }
+inline void GeometricalEdge::Set(const GeometricalEdge & rec,const Geometry & Gh ,Geometry & GhNew)
+ { 
+   *this = rec;
+   v[0] = GhNew.vertices + Gh.Number(v[0]);    
+   v[1] = GhNew.vertices + Gh.Number(v[1]); 
+   if (Adj[0]) Adj[0] =  GhNew.edges + Gh.Number(Adj[0]);     
+   if (Adj[1]) Adj[1] =  GhNew.edges + Gh.Number(Adj[1]);     
+ }
+ 
+inline void Curve::Set(const Curve & rec,const Geometry & Gh ,Geometry & GhNew)
+{
+  *this = rec;
+   be = GhNew.edges + Gh.Number(be);    
+   ee = GhNew.edges + Gh.Number(ee); 
+   if(next) next= GhNew.curves + Gh.Number(next); 
+}
+
+inline void Triangle::Set(const Triangle & rec,const Triangles & Th ,Triangles & ThNew)
+ { 
+   *this = rec;
+   if ( ns[0] ) ns[0] = ThNew.vertices +  Th.Number(ns[0]);
+   if ( ns[1] ) ns[1] = ThNew.vertices +  Th.Number(ns[1]);
+   if ( ns[2] ) ns[2] = ThNew.vertices +  Th.Number(ns[2]);
+   if(at[0]) at[0] =  ThNew.triangles + Th.Number(at[0]);
+   if(at[1]) at[1] =  ThNew.triangles + Th.Number(at[1]);
+   if(at[2]) at[2] =  ThNew.triangles + Th.Number(at[2]);
+   if (link  >= Th.triangles && link  < Th.triangles + Th.nbt)
+     link = ThNew.triangles + Th.Number(link);
+ }
+inline void VertexOnVertex::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+{ 
+  *this = Th.VertexOnBThVertex[i];  
+  v = ThNew.vertices + Th.Number(v);
+
+}
+inline void SubDomain::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+{
+  *this = Th.subdomains[i];
+  assert( head - Th.triangles >=0 && head - Th.triangles < Th.nbt);
+  head = ThNew.triangles + Th.Number(head) ; 
+  assert(edge - Th.edges >=0 && edge - Th.edges < Th.nbe); 
+  edge = ThNew.edges+ Th.Number(edge);
+}
+ inline void GeometricalSubDomain::Set(const GeometricalSubDomain & rec,const Geometry & Gh ,const Geometry & GhNew)
+{
+   *this = rec;
+   edge = Gh.Number(edge) + GhNew.edges;
+}
+inline void VertexOnEdge::Set(const Triangles & Th ,Int4 i,Triangles & ThNew)
+{
+  *this = Th.VertexOnBThEdge[i];  
+  v = ThNew.vertices + Th.Number(v);
+}
+
+inline void VertexOnGeom::Set(const VertexOnGeom & rec,const Triangles & Th ,Triangles & ThNew)
+{
+  *this = rec;  
+  mv = ThNew.vertices + Th.Number(mv);
+  if (gv)
+  {
+    if (abscisse < 0 )
+      gv = ThNew.Gh.vertices + Th.Gh.Number(gv);
+    else
+      ge = ThNew.Gh.edges + Th.Gh.Number(ge);
+  }
+}
+inline Real8 Edge::MetricLength() const
+  { 
+    return LengthInterpole(v[0]->m,v[1]->m,v[1]->r - v[0]->r) ;
+  }
+
+inline  void  Triangles::ReMakeTriangleContainingTheVertex()
+ {
+   Int4 i;
+  for ( i=0;i<nbv;i++) 
+    {
+	vertices[i].vint = 0;
+	vertices[i].t=0;
+    }
+  for ( i=0;i<nbt;i++) 
+    triangles[i].SetTriangleContainingTheVertex();
+ }
+
+inline  void  Triangles::UnMarkUnSwapTriangle()
+ {
+   Int4 i;
+  for ( i=0;i<nbt;i++) 
+    for(int  j=0;j<3;j++)
+      triangles[i].SetUnMarkUnSwap(j);
+ }
+
+inline  void   Triangles::SetVertexFieldOn()
+  {
+    for (Int4 i=0;i<nbv;i++) 
+       vertices[i].on=0;
+    for (Int4 j=0;j<NbVerticesOnGeomVertex;j++ ) 
+       VerticesOnGeomVertex[j].SetOn();
+    for (Int4 k=0;k<NbVerticesOnGeomEdge;k++ ) 
+       VerticesOnGeomEdge[k].SetOn();
+    }	       
+inline  void   Triangles::SetVertexFieldOnBTh()
+  {
+    for (Int4 i=0;i<nbv;i++) 
+       vertices[i].on=0;
+    for (Int4 j=0;j<NbVertexOnBThVertex;j++ ) 
+       VertexOnBThVertex[j].SetOnBTh();
+    for (Int4 k=0;k<NbVertexOnBThEdge;k++ ) 
+       VertexOnBThEdge[k].SetOnBTh();
+       
+    }	       
+
+inline  void  TriangleAdjacent::SetAdj2(const TriangleAdjacent & ta, int l  )
+{ // set du triangle adjacent 
+  if(t) {
+    t->at[a]=ta.t;
+    t->aa[a]=ta.a|l;}
+  if(ta.t) {
+    ta.t->at[ta.a] = t ;
+    ta.t->aa[ta.a] = a| l ;
+  }
+}
+
+
+inline int  TriangleAdjacent::Locked() const
+{ return t->aa[a] &4;}
+inline int  TriangleAdjacent::Cracked() const
+{ return t->aa[a] &32;}
+inline int  TriangleAdjacent::GetAllFlag_UnSwap() const
+{ return t->aa[a] & 1012;} // take all flag except MarkUnSwap
+
+inline int  TriangleAdjacent::MarkUnSwap() const
+{ return t->aa[a] &8;}
+
+inline void  TriangleAdjacent::SetLock(){ t->SetLocked(a);}
+
+inline void  TriangleAdjacent::SetCracked() { t->SetCracked(a);}
+
+inline  TriangleAdjacent TriangleAdjacent::Adj() const
+{ return  t->Adj(a);}
+
+inline Vertex  * TriangleAdjacent::EdgeVertex(const int & i) const
+ {return t->ns[VerticesOfTriangularEdge[a][i]]; }
+inline Vertex  * TriangleAdjacent::OppositeVertex() const
+{return t->ns[bamg::OppositeVertex[a]]; }
+inline Icoor2 &  TriangleAdjacent::det() const
+{ return t->det;}
+inline  TriangleAdjacent Adj(const TriangleAdjacent & a)
+{ return  a.Adj();}
+
+inline TriangleAdjacent Next(const TriangleAdjacent & ta) 
+{ return TriangleAdjacent(ta.t,NextEdge[ta.a]);}
+
+inline TriangleAdjacent Previous(const TriangleAdjacent & ta) 
+{ return TriangleAdjacent(ta.t,PreviousEdge[ta.a]);}
+ 
+inline void Adj(GeometricalEdge * & on,int &i) 
+  {int j=i;i=on->SensAdj[i];on=on->Adj[j];}
+  
+inline Real4 qualite(const Vertex &va,const Vertex &vb,const Vertex &vc)
+{
+  Real4 ret; 
+  I2 ia=va,ib=vb,ic=vc;
+  I2 ab=ib-ia,bc=ic-ib,ac=ic-ia;
+  Icoor2 deta=Det(ab,ac);
+  if (deta <=0) ret = -1;
+   else {
+     Real8 a = sqrt((Real8) (ac,ac)),
+       b = sqrt((Real8) (bc,bc)),
+       c = sqrt((Real8) (ab,ab)),
+       p = a+b+c;
+     Real8 h= Max(Max(a,b),c),ro=deta/p;
+   ret = ro/h;}
+  return ret;
+}
+
+
+inline  Triangle::Triangle(Triangles *Th,Int4 i,Int4 j,Int4 k) {
+  Vertex *v=Th->vertices;
+  Int4 nbv = Th->nbv;
+  assert(i >=0 && j >=0 && k >=0);
+  assert(i < nbv && j < nbv && k < nbv);
+  ns[0]=v+i;
+  ns[1]=v+j;
+  ns[2]=v+k;
+  at[0]=at[1]=at[2]=0;
+  aa[0]=aa[1]=aa[2]=0;
+  det=0;
+}
+
+inline  Triangle::Triangle(Vertex *v0,Vertex *v1,Vertex *v2){
+  ns[0]=v0;
+  ns[1]=v1;
+  ns[2]=v2;
+  at[0]=at[1]=at[2]=0;
+  aa[0]=aa[1]=aa[2]=0;
+  if (v0) det=0;
+  else {
+    det=-1;
+    link=NULL;};  
+}
+
+inline    Real4 Triangle::qualite()
+{
+  return det < 0 ? -1 :  bamg::qualite(*ns[0],*ns[1],*ns[2]);
+}
+
+Int4 inline  Vertex::Optim(int i,int koption)
+{ 
+  Int4 ret=0;
+  if ( t && (vint >= 0 ) && (vint <3) )
+    {
+      ret = t->Optim(vint,koption);
+      if(!i) 
+	{
+	  t =0; // for no future optime 
+	  vint= 0; }
+    }
+  return ret;
+}
+
+Icoor2 inline det(const Vertex & a,const Vertex & b,const Vertex & c)
+{
+    Icoor2 bax = b.i.x - a.i.x ,bay = b.i.y - a.i.y; 
+    Icoor2 cax = c.i.x - a.i.x ,cay = c.i.y - a.i.y; 
+  return  bax*cay - bay*cax;}
+
+
+void  swap(Triangle *t1,Int1 a1,
+	   Triangle *t2,Int1 a2,
+	   Vertex *s1,Vertex *s2,Icoor2 det1,Icoor2 det2);
+
+
+
+int inline TriangleAdjacent::swap()
+{ return  t->swap(a);}
+
+
+
+int SwapForForcingEdge(Vertex   *  & pva ,Vertex  * &   pvb ,
+		       TriangleAdjacent & tt1,Icoor2 & dets1,
+		       Icoor2 & detsa,Icoor2 & detsb, int & nbswap);
+
+int ForceEdge(Vertex &a, Vertex & b,TriangleAdjacent & taret) ;
+
+// inline bofbof   FH 
+inline  TriangleAdjacent FindTriangleAdjacent(Edge &E)
+  {
+    Vertex * a = E.v[0];
+    Vertex * b = E.v[1];
+    
+    Triangle * t = a->t;
+    int i = a->vint;
+    TriangleAdjacent ta(t,EdgesVertexTriangle[i][0]); // Previous edge
+    assert(t && i>=0 && i < 3);
+    assert( a == (*t)(i));
+    int k=0;
+    do { // turn around vertex in direct sens (trigo)
+      k++;assert(k< 20000);
+      //  in no crack => ta.EdgeVertex(1) == a otherwise ??? 
+      if (ta.EdgeVertex(1) ==  a && ta.EdgeVertex(0) ==  b) return ta; // find 
+      ta = ta.Adj();
+      if (ta.EdgeVertex(0) ==  a && ta.EdgeVertex(1) ==  b) return ta; // find 
+      --ta;
+      } while (t != (Triangle *)ta);
+    assert(0);
+    return TriangleAdjacent(0,0);// error 
+  }
+  
+inline Vertex * TheVertex(Vertex * a) // give a unique vertex with smallest number
+{ // in case on crack in mesh 
+    Vertex * r(a), *rr;
+    Triangle * t = a->t;
+    int i = a->vint;
+    TriangleAdjacent ta(t,EdgesVertexTriangle[i][0]); // Previous edge
+    assert(t && i>=0 && i < 3);
+    assert( a == (*t)(i));
+    int k=0;
+    do { // turn around vertex in direct sens (trigo)
+      k++;assert(k< 20000);
+      //  in no crack => ta.EdgeVertex(1) == a
+      if ((rr=ta.EdgeVertex(0)) < r) r = rr;
+      ta = ta.Adj();
+      if ((rr=ta.EdgeVertex(1)) < r) r =rr;
+      --ta;
+     } while (t != (Triangle*) ta);  
+    return r;
+}
+
+inline double CPUtime(){
+#ifdef SYSTIMES
+  struct tms buf;
+  if (times(&buf)!=-1)
+    return ((double)buf.tms_utime+(double)buf.tms_stime)/(long) sysconf(_SC_CLK_TCK);
+  else
+#endif
+    return ((double) clock())/CLOCKS_PER_SEC;
+}
+
+#ifdef DEBUG
+void inline Triangle::checka(Int1 a) {
+  // verif de la coherence des adjacences de l arete a
+  a = a%4;
+  assert(a < 3 && a >= 0 );
+  Triangle *t1=this,*t2=at[a];
+  Int2 a1=a,a2=aa[a]%4;
+  
+  assert(a2 < 3 && a2 >= 0 );
+  if (t2 && ( ((*t1).ns[VerticesOfTriangularEdge[a1][0]] != (*t2).ns[VerticesOfTriangularEdge[a2][1]])
+	      || ((*t1).ns[VerticesOfTriangularEdge[a1][1]] != (*t2).ns[VerticesOfTriangularEdge[a2][0]])))
+    {
+      if (CurrentTh) cerr << " In Triangles beetween Triangle " << CurrentTh->Number(t1) << " and " 
+		     <<  CurrentTh->Number(t2) <<  endl;
+      cerr << "---- t1="<< t1 << " " << a1 <<",  t2="<< t2 << " " << a2 << endl;
+      cerr <<"t1="<< t1 << " " << a1 << " " << t1->ns[VerticesOfTriangularEdge[a1][0]] 
+	   << " " << t1->ns[VerticesOfTriangularEdge[a1][1]] <<endl;
+      if (CurrentTh)
+	cerr <<"t1="<< t1 << " " << a1 << " " << CurrentTh->Number(t1->ns[VerticesOfTriangularEdge[a1][0]])
+	   << " " << CurrentTh->Number(t1->ns[VerticesOfTriangularEdge[a1][1]]) <<endl;
+      if (t2) cerr <<"t2="<< t2 << " " << a2 << " " 
+		   <<  t2->ns[VerticesOfTriangularEdge[a2][0]] 
+		   << " " << t2->ns[VerticesOfTriangularEdge[a2][1]] <<endl;
+      if (t2 &&CurrentTh)
+	cerr <<"t2="<< t2 << " " << a2 << " " 
+	     <<  CurrentTh->Number(t2->ns[VerticesOfTriangularEdge[a2][0]])
+	     << " " << CurrentTh->Number(t2->ns[VerticesOfTriangularEdge[a2][1]]) <<endl;
+      assert(0); 
+    } 
+  if (t2)   assert(t1->aa[a1]/4 == t2->aa[a2]/4); // lock compatibite
+}
+
+
+void inline  Triangle::check() {
+  Icoor2 det2=0;
+  //  cout << " check " << this << endl;
+  int  infv=ns[0] ?  ((  ns[1] ? ( ns[2] ? -1 : 2) : 1  )) : 0;
+  if (det<0) {
+      if (infv<0 )
+	{  if (CurrentTh) cerr << " In Triangles " << CurrentTh->Number(this) << endl;
+	cerr << " det = " <<  det << " and " << infv << endl;
+	MeshError(5);
+	}}
+  else  if (infv>=0 )
+ 	{  if (CurrentTh) cerr << " In Triangles " << CurrentTh->Number(this) << endl;
+	cerr << " det = " << det << " and " << infv << endl;
+	MeshError(5);
+	}  
+  
+  if (det >=0) 
+    if( det != (det2=bamg::det(*ns[0],*ns[1],*ns[2])))
+	{ // penthickness(4);Draw();
+	  if (CurrentTh) cerr << " In Triangles" << CurrentTh->Number(this) 
+			 << endl;
+      cerr << *ns[0] << *ns[1] << " " << *ns[2]  << " " << endl;
+	   cerr << " Bug in triangle " << this 
+		<< ":" << det << " !=  " << det2 << endl;
+	   MeshError(5);
+	}
+  checka(0);
+  checka(1);
+  checka(2);
+//  if (ns[0]) assert( ns[0] - Meshbegin  >= 0 );
+//  if (ns[0]) assert( Meshend  - ns[0] >= 0 );
+//  if (ns[1]) assert( ns[1] - Meshbegin  >= 0 );
+//  if (ns[1]) assert( Meshend  - ns[1] >= 0 );
+//  if (ns[2]) assert( ns[2] - Meshbegin  >= 0 );
+//  if (ns[2]) assert( Meshend  - ns[2] >= 0 );
+  assert(ns[0] != ns[2]);
+  assert(ns[1] != ns[2]);
+  assert(ns[0] != ns[1]);
+}
+
+
+#endif
+
+
+
+
+#ifdef DRAWING 
+extern Real4 xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet; // R2 -> I2 transform
+extern R2 Gpmin,Gpmax;
+//extern Real8 Gh;
+// cf routine ILineTo IMoveto
+
+extern void  IMoveTo(long i,long j);
+extern void  ILineTo(long i,long j);
+extern char Getxyc(long &i,long &j);
+extern void Draw(float ,float );
+extern void Draw(long ,long );
+extern void DrawMark(R2 r);
+//inline void DrawMark(D2 r) {DrawMark(R2(r.x,r.y));}
+inline void Move(I2 x) {IMoveTo(x.x,x.y);}
+inline void Move(R2 x) {rmoveto(x.x,x.y);}
+//inline void Move(D2 x) {rmoveto(x.x,x.y);}
+inline void Line(I2 x){ILineTo(x.x,x.y);}
+inline void Line(R2 x) {rlineto(x.x,x.y);}
+//inline void Line(D2 x) {rlineto(x.x,x.y);}
+#endif
+
+}
+
+
+
+
+
+
diff --git a/src/bamglib/MeshDraw.cpp b/src/bamglib/MeshDraw.cpp
new file mode 100644
index 0000000..8a3cdce
--- /dev/null
+++ b/src/bamglib/MeshDraw.cpp
@@ -0,0 +1,808 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifdef DRAWING
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include <iostream>
+using namespace std;
+
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+extern bool withrgraphique;
+
+
+
+namespace bamg {
+Real4  xGrafCoef,yGrafCoef,xGrafOffSet,yGrafOffSet;
+R2 GrafPMin,GrafPMax;
+Real8 Grafh=0;
+
+
+
+void  IMoveTo(long i,long j)
+{  if (!withrgraphique) return;
+   rmoveto(float(i)/xGrafCoef+xGrafOffSet ,float(j)/yGrafCoef+yGrafOffSet );}
+
+void  ILineTo(long i,long j)
+{      if (!withrgraphique) return;
+  rlineto(float(i)/xGrafCoef+xGrafOffSet ,float(j)/yGrafCoef+yGrafOffSet );}
+
+
+void   Triangles::Draw(   ) const {
+    if (!withrgraphique) return;
+  showgraphic();
+//  if (!init) InitDraw();
+  Int4 i;
+//  for (i=0;i<nbv;i++)
+//    vertices[i].Draw(i);    
+  for (i=0;i<nbe;i++)
+    edges[i].Draw();
+  for (i=0;i<nbt;i++) 
+      if (triangles[i].link) 
+	triangles[i].Draw(-2);
+//  for (i=0;i<nbv;i++)
+//   ((Metric) vertices[i]).Draw(vertices[i]);    
+   
+  //  rattente(1);
+  
+}
+
+
+void    Edge::Draw(Int4  i) const 
+{
+      if (!withrgraphique) return;
+  if (InRecScreen(Min(v[0]->r.x,v[1]->r.x),
+		  Max(v[0]->r.y,v[1]->r.y),
+		  Min(v[0]->r.x,v[1]->r.x),
+		  Max(v[0]->r.y,v[1]->r.y))) {
+    v[0]->MoveTo();
+    v[1]->LineTo();
+    R2 M= ((R2) *v[0] + (R2) * v[1])*0.5;
+    Move(M);
+    char VertexDraw_i10[20];
+    if (i<0)
+      sprintf(VertexDraw_i10,"%p",this);
+    else 
+      sprintf(VertexDraw_i10,"%ld",i);
+    if (i>=0)
+      plotstring(&VertexDraw_i10[0]); 
+    
+  }
+}
+void    Vertex::Draw(Int4 i) const 
+{
+      if (!withrgraphique) return;
+  if (CurrentTh && i<0&& i != -2 )
+    {
+      if (CurrentTh->vertices <= this && this < CurrentTh->vertices + CurrentTh->nbv)
+	i = CurrentTh->Number(this);
+    }
+  if (InPtScreen(r.x,r.y)) {
+   char VertexDraw_i10[20];
+   if (i<0)
+     sprintf(VertexDraw_i10,"%p",this);
+   else 
+     sprintf(VertexDraw_i10,"%ld",i);
+  
+  showgraphic();
+  //  float eps = (MaxICoor/yGrafCoef)/100;
+  DrawMark(r);
+  
+  if (i>=0)
+    plotstring(&VertexDraw_i10[0]); }
+}
+
+void  DrawMark(R2 r) 
+{
+      if (!withrgraphique) return;
+  if (InPtScreen(r.x,r.y)) {
+  float eps = Grafh/100;
+  rmoveto(r.x+eps,r.y);
+  rlineto(r.x,r.y+eps);
+  rlineto(r.x-eps,r.y);
+  rlineto(r.x,r.y-eps);
+  rlineto(r.x+eps,r.y);}
+ 
+}
+void  Triangle::Draw(Int4 i ) const
+{
+      if (!withrgraphique) return;
+  //  int cc=LaCouleur();
+  if (CurrentTh && i<0 && i != -2)
+    {
+      if (CurrentTh->triangles <= this && this < CurrentTh->triangles + CurrentTh->nbt)
+	i = CurrentTh->Number(this);
+    }	
+  char i10[20];
+  if (i<0)   sprintf(i10,"%p",this);
+  else  sprintf(i10,"%ld",i);
+  showgraphic();
+
+  if (ns[0] == 0) {
+  if (InRecScreen(Min(ns[1]->r.x,ns[2]->r.x),
+		  Min(ns[1]->r.y,ns[2]->r.y),
+		  Max(ns[1]->r.x,ns[2]->r.x),
+		  Max(ns[1]->r.y,ns[2]->r.y)))
+    { rmoveto(ns[1]->r.x,ns[1]->r.y);
+      rlineto(ns[2]->r.x,ns[2]->r.y);
+      rmoveto( (ns[1]->r.x + ns[2]->r.x)/2.0 + (ns[1]->r.y - ns[2]->r.y)*0.1,
+              (ns[1]->r.y + ns[2]->r.y)/2.0 - (ns[1]->r.x - ns[2]->r.x)*0.1 );
+      if(i>=0)  plotstring(&i10[0]);    
+    }}
+  else
+  if (InRecScreen(Min3(ns[0]->r.x,ns[1]->r.x,ns[2]->r.x),
+		  Min3(ns[0]->r.y,ns[1]->r.y,ns[2]->r.y),
+		  Max3(ns[0]->r.x,ns[1]->r.x,ns[2]->r.x),
+		  Max3(ns[0]->r.y,ns[1]->r.y,ns[2]->r.y))) {
+    { 
+      const int i0=0                               , j01=EdgesVertexTriangle[i0][1];//     j01==2
+      const int i1=VerticesOfTriangularEdge[j01][1], j12=EdgesVertexTriangle[i1][1];//i1=1,j12=0
+      const int i2=VerticesOfTriangularEdge[j12][1], j20=EdgesVertexTriangle[i2][1];//i1=2,j20=1
+
+      rmoveto(ns[i0]->r.x,ns[i0]->r.y);
+      if(Hidden(j01)) rmoveto(ns[i1]->r.x,ns[i1]->r.y); else  rlineto(ns[i1]->r.x,ns[i1]->r.y);
+      if(Hidden(j12)) rmoveto(ns[i2]->r.x,ns[i2]->r.y); else  rlineto(ns[i2]->r.x,ns[i2]->r.y);
+      if(Hidden(j20)) rmoveto(ns[i0]->r.x,ns[i0]->r.y); else  rlineto(ns[i0]->r.x,ns[i0]->r.y);
+      
+    rmoveto( (ns[0]->r.x + ns[1]->r.x + ns[2]->r.x)/3.0 ,
+             (ns[0]->r.y + ns[1]->r.y + ns[2]->r.y)/3.0);
+    
+    }
+  
+  if(i>=0)  plotstring(&i10[0]);    
+  }
+  //  LaCouleur(cc);
+}
+
+void  Triangles::InitDraw() const
+{ 
+   if (!withrgraphique) return; 
+   couleur(1);
+   GrafPMin =  vertices[0].r;
+   GrafPMax =  vertices[0].r;
+  // recherche des extrema des vertices GrafPMin,GrafPMax
+  Int4 i;
+  for (i=0;i<nbv;i++) {
+    //    GrafPMax = Max2(GrafPMax,vertices[i].r);
+    //    GrafPMin = Min2(GrafPMin,vertices[i].r);
+    GrafPMin.x = Min(GrafPMin.x,vertices[i].r.x);
+    GrafPMin.y = Min(GrafPMin.y,vertices[i].r.y);
+    GrafPMax.x = Max(GrafPMax.x,vertices[i].r.x);
+    GrafPMax.y = Max(GrafPMax.y,vertices[i].r.y);
+  }
+  float hx = (GrafPMax.x-GrafPMin.x);
+  float hy = (GrafPMax.y-GrafPMin.y);
+  Grafh = Max(hx,hy)*0.55;
+  cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.5,Grafh);
+  
+}
+void Show(const char * s,int k=1)
+{
+  if (!withrgraphique) return;
+  if(k) {
+  couleur(1);
+  float xmin,xmax,ymin,ymax;
+       getcadre(xmin,xmax,ymin,ymax);
+       rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+       plotstring(s);
+       //  couleur(1);	
+  }
+}
+void Triangles::inquire() 
+{    
+  if (! withrgraphique) return;
+  int PS=0;
+  cout << flush;
+   Triangles *OldCurrentTh=CurrentTh;
+  CurrentTh = this;
+  if (! Grafh ) InitDraw();
+  unsigned  char c;
+  int rd;
+  float x,y;
+  int setv =0;
+  Int4 nbtrel=0;
+  Int4 * reft = new Int4 [Max(nbt,1L)];
+  if (NbSubDomains && subdomains[0].head)
+    nbtrel = ConsRefTriangle(reft);
+  else
+    for (Int4 kkk=0;kkk<nbt;kkk++) reft[kkk]=0;
+  // cout << "inquire **********************************************************************"<<endl ;
+      if (verbosity>2)
+	cout << "inquire: Nb de Triangle reel = " <<ConsRefTriangle(reft)<<endl;
+
+  while (Show("Enter ? for help",PS==0), c=::Getxyc(x,y), ( c && c != 'F'  && c != 'f')  && c < 250 )
+    { rd = 0;
+      couleur(1);
+    //  cout << " #"<< c << "# " << (int) c << " xy=" << x << " "<< y  <<endl ;
+      //     penthickness(2);
+      if (c=='?') { int i=3;
+        reffecran();
+	Show("enter a keyboard character in graphic window to do",i++);
+	i++;
+	Show("f or mouse click: to continue the process",i++);
+	Show("p: openPS file to save plot, P: close PS file ",i++);
+        Show("B: set backgound mesh has drawing mesh",i++);
+	Show("H: show histogramme",i++);
+	Show("i: initDraw",i++);
+	Show("+ or - : zoom + or -",i++);
+	Show("r: redraw  , =: reinit the viewport ",i++);
+	Show("q: quit / abort / stop ",i++);
+	Show("Q: show quadtree",i++);
+	Show("g: show geometry",i++);
+	Show("d: show triangle with det = 0",i++);
+	Show("m: show all the metric",i++);
+	Show("V: show all the vertices",i++);
+	Show("T: show all the sub domain ref number",i++);
+	Show("V: show all the vertices",i++);
+	Show("D: Inforce the mesh to be Delaunay",i++);
+	Show("b: show all the boundary edges ref number",i++);
+	Show("k: find the triangle contening the point",i++);
+	Show("v,o,s : print the nearest vertex  s=> draw metric o=> optim around (debug)",i++);
+	Show("t: find triangle contening the point  with brute force",i++);	
+	Show("e: find the nearest edge of triangle contening the point",i++);
+	Show("C: construct the in-circle in anistrope way",i++);
+	Show("n: show normal for find ",i++);
+      }
+      if (c=='p') openPS(0),PS=1;
+      if (c=='P') closePS(),PS=0;
+      if (c=='B') BTh.inquire();
+      if ( c=='D') {
+	for(int iter=0;iter < 50;iter++)
+	  { int k = 0;
+	  for (Int4 icount=0; icount<nbv; icount++) {
+	    k += vertices[icount].Optim(1,0);
+	  }
+	  if (k !=0) cout << " Bizarre le maillage n'est  pas delaunay  nbswap = " << k << endl;
+	  else break;
+	  }
+	rd =1;
+      }
+      
+      if (c=='H') ShowHistogram();
+      if (c=='i') {InitDraw();
+      }
+      if (c=='+') Grafh /= 2.,rd=1,cadreortho(x,y,Grafh);
+      if (c=='-') Grafh *= 2.,rd=1,cadreortho(x,y,Grafh);
+      if (c=='r') rd =1;
+      if (c=='Q') CurrentTh=0,MeshError(1);
+      if (c=='q' && quadtree) penthickness(2),
+				couleur(6), 
+				quadtree->Draw(),
+				couleur(1),
+				penthickness(1);
+      if (c=='g') couleur(6),Gh.Draw();
+      if (c=='n') {
+        for (int i=0;i<nbv;i++)
+         {
+           vertices[i].MoveTo();
+           vertices[1].DirOfSearch.Draw();;
+         }
+      }
+      if (c=='d')
+	{      
+          couleur(4);
+	  for(int i=0;i<nbt;i++)
+	    if(triangles[i].det == 0) {
+	      triangles[i].Draw();
+	      cout << " Bizzare " << i << endl;
+	    }
+          couleur(1);
+       
+	}
+      if (c=='m')  {Int4 i;
+        couleur(2);
+        for (i=0;i<nbv;i++)
+	((Metric) vertices[i]).Draw(vertices[i]); 
+        couleur(1);}
+      if (c=='V')  {Int4 i;
+        for (i=0;i<nbv;i++)
+	 vertices[i].Draw(); }
+      if (c=='T') {
+	Int4 i;
+	for( i=0;i<nbt;i++)
+	  if(reft[i]>=0)
+	    { couleur(2+(reft[i])%6);
+	      triangles[i].Draw(reft[i]);
+              couleur(1); 
+	    }
+      }
+	
+      if (c=='b') {
+	Int4 i;
+	reffecran();
+	for (i=0;i<nbe;i++)
+	  edges[i].Draw(edges[i].ref);
+	
+      }
+      if (c=='k') 
+	{ 
+	  if(!setv) ReMakeTriangleContainingTheVertex();
+	  R2 P(x,y);
+	  I2 I = toI2(P);
+	  Icoor2 dete[3];
+	  Triangle * tb = FindTriangleContening(I,dete);
+	  penthickness(1);
+	  tb->Draw(Number(tb));
+	  penthickness(1);
+	  if(tb->link==0) {
+	    double a,b;
+	    TriangleAdjacent ta=CloseBoundaryEdgeV2(I,tb,a,b);
+	    R2 A = *ta.EdgeVertex(0);
+	    R2 B = *ta.EdgeVertex(1);
+	    //Triangle * tt  = ta;
+	    //    tt->Draw(Number(tt));
+	    penthickness(5);
+	    //   ta.EdgeVertex(0)->MoveTo();
+	    //  ta.EdgeVertex(1)->LineTo();
+	    DrawMark(A*a+B*b);
+	    penthickness(1);
+	      }
+	}
+      if (c=='v' || c=='o' || c=='s' )
+	{ 
+	  couleur(3);
+	  if(!setv) ReMakeTriangleContainingTheVertex();
+	  setv=1;
+	  
+	  R2 XY(x,y),P;
+	  Real8 d;
+	  Int4 i,j=0;
+	  P  = XY - vertices[0].r;
+	  d = (P,P);
+	  for (i=0;i<nbv;i++) {
+	    P  = XY - vertices[i].r;
+	  Real8 dd = (P,P);
+	  if(dd < d) {
+	    j=i;
+	    d=dd;}}
+	  cout << " sommet " << j << "= " <<	vertices[j]  << ", d = " << d << " " << vertices[j].m << endl;
+	  vertices[j].Draw(j);
+	  DrawMark(vertices[j].r);
+	  if( c=='s')  vertices[j].m.Draw(vertices[j]);
+	  if (c=='o')   cout << " Nb Swap = " << vertices[j].Optim(1) << endl;
+	  couleur(1);
+      }
+      if (c=='t' || c=='c'||c=='e') {
+	    couleur(4);
+            R2 XY(x,y);
+	    Real8 a12,a02,a01;
+	    for (Int4 i=0;i<nbt;i++) {
+	      if(triangles[i].det<=0)  continue;
+	      //	      cout << " T = " << i << " " << triangles[i].det << " ";
+	      //	      cout << Number(triangles[i][0]) << " "
+	      //		   << Number(triangles[i][1]) << " "
+	      //		   << Number(triangles[i][2]) << " ";
+	      //    cout << area2(triangles[i][0].r,triangles[i][1].r,triangles[i][2].r) << " " ;
+	      //	      cout << area2(XY,triangles[i][1].r,triangles[i][2].r) << " " ;
+	      //      cout << area2(triangles[i][0].r,XY,triangles[i][2].r) << " " ;
+	      //     cout << area2(triangles[i][0].r,triangles[i][1].r,XY) << endl;
+			   
+	      if( (a12=Area2(XY,triangles[i][1].r,triangles[i][2].r)) < 0) continue;
+	      if( (a02=Area2(triangles[i][0].r,XY,triangles[i][2].r)) < 0) continue;
+	      if( (a01=Area2(triangles[i][0].r,triangles[i][1].r,XY)) < 0) continue;
+	      if(c=='e'|| c=='E') {
+		int ie =0;
+		Real8 am = a12;
+		if(a02 < am) am=a02,ie=1;
+		if(a01 < am) am=a01,ie=2;
+		TriangleAdjacent tta(triangles+i,ie);
+		Vertex *v0 =tta.EdgeVertex(0);
+		Vertex *v1 =tta.EdgeVertex(1);
+		tta.EdgeVertex(0)->MoveTo();
+		tta.EdgeVertex(1)->LineTo();
+		cout << " Edge " << Number(tta.EdgeVertex(0)) << " " <<  Number(tta.EdgeVertex(1)) << endl;
+		for (Int4 k=0;k<nbe;k++)
+		  if ( ( edges[k](0) == v0 &&  edges[k](1) == v1) ||
+		       ( edges[k](0) == v1 &&  edges[k](1) == v0)	)			
+		    cout << " Edge " << k << "  on Geo = " << Gh.Number(edges[k].on)<< endl;
+		
+		  
+		if(c=='e') {
+		  triangles[i].SetUnMarkUnSwap(ie);
+		  triangles[i].swapDRAW(ie);}
+		else if(c=='E')
+		  {
+		    ;
+		  }
+
+		break;
+	      }
+	      cout << " In triangle " << i << triangles[i];
+	      triangles[i].Draw(i);
+	      if(c=='c') {
+		Vertex *s1=&triangles[i][0];
+		Vertex *sa=&triangles[i][1];
+		Vertex *sb=&triangles[i][2];
+		D2 S1(s1->r.x,s1->r.y);
+		D2 SA(sa->r.x,sa->r.y);
+		D2 SB(sb->r.x,sb->r.y);
+		D2 AB= SB-SA;
+		D2 MAB2=SB + SA;
+		D2 M1A=(S1 + SA)*0.5;
+		D2 MAB(MAB2.x*0.5,MAB2.y*0.5);
+		D2 A1=S1-SA;
+		D2 D = S1 - SB ;
+		{
+		  Metric M=s1->m;
+		  D2 ABo = M.Orthogonal(AB);
+		  D2 A1o = M.Orthogonal(A1);
+		  penthickness(1);
+		  Move(MAB);
+		  Line(MAB+ABo);
+		  Line(MAB-ABo);
+		  Move(M1A);
+		  Line(M1A+A1o);
+		  Line(M1A-A1o);
+		  penthickness(3);
+		  
+		  // (A+B)+ x ABo = (S1+B)/2+ y A1 
+		  // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2
+		  double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+		  double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+		  cout << " d = " << d << " dd= " << dd << endl;
+		  if (Abs(d) > dd*1.e-10) {
+		    D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		    cout << C << s1->r <<sa->r  <<sb->r << endl;
+		    DrawMark(C);
+		    cout << M << " l = "<<  M(C-S1) << " lnew = 1 == " ;
+		    //M.Draw(R2(C.x,C.y));
+		    M=M/M(C-S1);	
+		    cout << M(C-S1) << M << endl;	 
+		    M.Draw(R2(C.x,C.y));
+		  }
+		  
+		}
+	      }
+	      break;
+	    }
+	    cout << " fin recherche triangle " << endl;
+	   couleur(1); 
+      }            
+      if (c=='='||c==249) {
+	rd=1;
+	float hx = (GrafPMax.x-GrafPMin.x);
+	float hy = (GrafPMax.y-GrafPMin.y);
+	Grafh = Max(hx,hy)*0.55;
+	cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.55,Grafh);
+      }
+       penthickness(1);
+      if (rd) 
+        reffecran(),Draw();
+
+    }
+  // cout << endl;
+  delete [] reft;
+  CurrentTh = OldCurrentTh;
+ }
+void Draw(float x,float y)
+{
+ if (!withrgraphique) return;
+
+  if (InPtScreen(x,y)) {
+  float eps = Max(GrafPMax.x-GrafPMin.x,GrafPMax.y-GrafPMin.y)/100;
+  rmoveto(x+eps,y);
+  rlineto(x,y+eps);
+  rlineto(x-eps,y);
+  rlineto(x,y-eps);
+  rlineto(x+eps,y);}
+}
+char Getxyc(long &i,long &j)
+{ 
+   if (!withrgraphique) return 0;
+ 
+   float x,y;
+   char c=::Getxyc(x,y);
+   i = (long)( (x - xGrafOffSet)*xGrafCoef);
+   j = (long)((y - yGrafOffSet)*yGrafCoef);
+   return c;
+}
+
+
+void Draw(long i,long j)
+{
+  if (!withrgraphique) return;
+  Draw(((float) i)/xGrafCoef+xGrafOffSet ,((float) j)/yGrafCoef+yGrafOffSet );
+}
+
+int Triangle::swapDRAW(Int2 a){
+  int NbUnSwap=0;
+  if(a/4 !=0)  {cout << a << "arete lock"<< a <<endl;return 0;}// arete lock or MarkUnSwap
+
+   Triangle *t1=this,*t2=at[a];// les 2 triangles adjacent
+   Int1 a1=a,a2=aa[a];// les 2 numero de l arete dans les 2 triangles
+  
+  if(a2/4 !=0) {cout << a2 << "arete lock adj"<< a2 << endl; return 0;} // arete lock
+  
+   Vertex  *sa=t1->ns[VerticesOfTriangularEdge[a1][0]];
+   Vertex  *sb=t1->ns[VerticesOfTriangularEdge[a1][1]];
+   Vertex  *s1=t1->ns[OppositeVertex[a1]];
+   Vertex  *s2=t2->ns[OppositeVertex[a2]];
+
+#ifdef DEBUG
+  assert ( a >= 0 && a < 3 );  
+#endif
+  
+   Icoor2 det1=t1->det , det2=t2->det ;
+   Icoor2 detT = det1+det2;
+   Icoor2 detA = Abs(det1) + Abs(det2);
+   Icoor2 detMin = Min(det1,det2);
+
+   int OnSwap = 0;       
+   // si 2 triangle infini (bord) => detT = -2;
+   if (sa == 0) {// les deux triangles sont frontieres
+     det2=bamg::det(s2->i,sb->i,s1->i);
+     OnSwap = det2 >0;}
+   else if (sb == 0) { // les deux triangles sont frontieres
+     det1=bamg::det(s1->i,sa->i,s2->i);
+     OnSwap = det1 >0;}
+   else if(( s1 != 0) && (s2 != 0) ) {
+     det1 = bamg::det(s1->i,sa->i,s2->i);
+     det2 = detT - det1;
+     OnSwap = (Abs(det1) + Abs(det2)) < detA;
+     Icoor2 detMinNew=Min(det1,det2);
+     cout << " detMin = " << detMin << "  detMinNew " <<  detMinNew << endl;
+     if (! OnSwap &&(detMinNew>0)) {
+       OnSwap = detMin ==0;
+       if (! OnSwap) {
+	 int  kopt = 1;
+        while (1)
+	 if(kopt) {
+	 // critere de Delaunay pure 
+	  Real8 xb1 = sb->i.x - s1->i.x,
+	   x21 = s2->i.x - s1->i.x,
+	   yb1 = sb->i.y - s1->i.y,
+	   y21 = s2->i.y - s1->i.y,
+	   xba = sb->i.x - sa->i.x, 
+	   x2a = s2->i.x - sa->i.x,
+	   yba = sb->i.y - sa->i.y,
+	   y2a = s2->i.y - sa->i.y,
+	   cosb12 =  xb1*x21 + yb1*y21 ,
+	   cosba2 =  xba*x2a + yba*y2a ,
+	   sinb12 = det2,
+	   sinba2 = t2->det,
+	   //zsinba2 = t2->det;
+	 
+	 // angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2)
+	 OnSwap =  (cosb12 *  sinba2) <  (cosba2 *  sinb12);
+	 if(CurrentTh) 
+	   cout << "swap s1=" << CurrentTh->Number(sa) << " s2=" << CurrentTh->Number(sb) 
+		<< " t1= " <<  CurrentTh->Number(t1) << " t2=" <<  CurrentTh->Number(t2) << " " ;
+
+
+	 cout <<  cosb12 << " " <<  sinba2 << " "  <<  cosba2 << " " << sinb12 
+	      << " Onswap = " <<  OnSwap << endl;
+
+	  break;
+	 }
+	 else 
+	   {	
+	     // critere de Delaunay pure 
+	     Real8 som;
+	     I2 AB=(I2) *sb - (I2) *sa;
+	     I2 MAB2=((I2) *sb + (I2) *sa);
+	     D2 MAB(MAB2.x*0.5,MAB2.y*0.5);
+	     I2 A1=(I2) *s1 - (I2) *sa;
+	     I2 D = (I2) * s1 - (I2) * sb ;
+	     D2 S2(s2->i.x,s2->i.y);
+	     D2 S1(s1->i.x,s1->i.y);
+	     D2 SA(sa->i.x,sa->i.y);
+	     D2 SB(sb->i.x,sb->i.y);
+	     DrawMark(s2->r);
+	     DrawMark(s1->r);
+	     DrawMark(sa->r);
+	     DrawMark(sb->r);
+	     {
+	       Metric M=s1->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       if (Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M1 r2 =" <<  M(C - S2) << " r1 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) ;
+		 som  = M(C - S2)/M(C - S1);
+		 cout << " r1/r2 = " << som << endl;
+	       } else 
+		{kopt=1;continue;}
+		
+	     }
+	     {
+	       Metric M=s2->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       cout << " d = " << Abs(d) << " dd " << dd << endl;
+	       if(Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M2 r1 =" <<  M(C - S2) << " r2 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) 
+		      << " r1/r2 =  " << M(C - S2)/M(C -  S1)  << endl;
+		 som  += M(C - S2)/M(C -  S1);
+	       } else 
+		{kopt=1;continue;}
+	     }
+	     {
+	       Metric M=sa->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       cout << " d = " << Abs(d) << " dd " << dd << endl;
+	       if(Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M2 r1 =" <<  M(C - S2) << " r2 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) 
+		      << " r1/r2 =  " << M(C - S2)/M(C -  S1)  << endl;
+		 som  += M(C - S2)/M(C -  S1);
+	       } else 
+		{kopt=1;continue;}
+	     }
+  	     {
+	       Metric M=sb->m;
+	       D2 ABo = M.Orthogonal(SB-SA);
+	       D2 A1o = M.Orthogonal(S1-SA);
+	       // (A+B)+ x ABo = (S1+B)/2+ y A1 
+	       // ABo x - A1o y =  (S1+B)/2-(A+B)/2 = (S1-B)/2 = D/2 
+	       double dd = Abs(ABo.x*A1o.y)+Abs(ABo.y*A1o.x);
+	       double d = (ABo.x*A1o.y - ABo.y*A1o.x)*2; // because D/2
+	       cout << " d = " << Abs(d) << " dd " << dd << endl;
+	       if(Abs(d) > dd*1.e-3) {
+		 D2 C(MAB+ABo*((D.x*A1o.y - D.y*A1o.x)/d));
+		 cout << "M2 r1 =" <<  M(C - S2) << " r2 = " << M(C - S1) 
+		      << "ra = " << M(C - SA) << " rb = " << M(C-SB) 
+		      << " r1/r2 =  " << M(C - S2)/M(C -  S1)  << endl;
+		 som  += M(C - S2)/M(C -  S1);
+	       } else 
+		{kopt=1;continue;}
+	     }
+	     cout <<  som  << endl;
+	     OnSwap = som < 4;
+	     break;
+	 }
+
+       } // OnSwap 
+     } // (! OnSwap &&(det1 > 0) && (det2 > 0) )
+   }
+   cout << OnSwap << endl;
+   if( OnSwap ) {
+     couleur(0);
+     t1->Draw();
+     t2->Draw();    
+     bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2);		
+     couleur(1);
+     t1->Draw();
+     t2->Draw();    
+   }
+   else {
+     NbUnSwap ++;
+     t1->SetMarkUnSwap(a1);     
+   }
+   return OnSwap;
+}
+
+
+	   
+
+void GeometricalEdge::Draw(Int4  i)
+{ 
+    if (!withrgraphique) return;
+
+  if (CurrentTh && i<0 && i != -2)
+    {
+      if (CurrentTh->Gh.edges <= this && this < CurrentTh->Gh.edges + CurrentTh->Gh.nbe)
+	i = CurrentTh->Gh.Number((this));
+    }	
+
+    v[0]->MoveTo();
+    R2 x,x50;
+    int k=0,k50=0;
+    for (int ii = 0;ii<100;ii++) {
+      x= F( Real4(ii)/100.0);
+      if(ii==50) x50=x,k50=1;
+      if (InPtScreen(x.x,x.y) )
+      {if(k) rlineto(x.x,x.y);
+          else k=1,rmoveto(x.x,x.y);}
+    }
+      if (InPtScreen(v[1]->r.x,v[1]->r.y))      
+	v[1]->LineTo();  
+
+      char VertexDraw_i10[20];
+      if( k50) {
+	if (i<0)
+	  sprintf(VertexDraw_i10,"Eg%p",this);
+	else 
+	  sprintf(VertexDraw_i10,"Eg%ld",i);
+	rmoveto(x50.x,x50.y);
+	plotstring(&VertexDraw_i10[0]); }  
+
+}
+
+void  Geometry::InitDraw() const
+{ 
+   GrafPMin =  vertices[0].r;
+   GrafPMax =  vertices[0].r;
+  // recherche des extrema des vertices GrafPMin,GrafPMax
+  Int4 i;
+  for (i=0;i<nbv;i++) {
+    //    GrafPMax = Max2(GrafPMax,vertices[i].r);
+    //    GrafPMin = Min2(GrafPMin,vertices[i].r);
+    GrafPMin.x = Min(GrafPMin.x,vertices[i].r.x);
+    GrafPMin.y = Min(GrafPMin.y,vertices[i].r.y);
+    GrafPMax.x = Max(GrafPMax.x,vertices[i].r.x);
+    GrafPMax.y = Max(GrafPMax.y,vertices[i].r.y);
+  }
+  float hx = (GrafPMax.x-GrafPMin.x);
+  float hy = (GrafPMax.y-GrafPMin.y);
+  Grafh = Max(hx,hy)*7/10;
+  if (withrgraphique)
+   cadreortho((GrafPMin.x+GrafPMax.x)*0.5,(GrafPMin.y+GrafPMax.y)*0.55,Grafh);
+
+  
+}
+
+void   Geometry::Draw() const {
+    if (!withrgraphique) return;
+
+  showgraphic();
+  //  InitDraw();
+  Int4 i;
+  for (i=0;i<nbv;i++)
+    vertices[i].Draw();    
+  for (i=0;i<nbe;i++)
+    {
+	if(edges[i].Cracked()) couleur(4);
+	else couleur(6);
+    edges[i].Draw(i);
+    }
+   couleur(6);
+  for (i=0;i<nbv;i++)
+    if (vertices[i].Required()) {
+      char i10[40];
+      sprintf(i10,"%ld:%d",i,vertices[i].Required());
+      Move(vertices[i].r);
+      if(vertices[i].Corner()) couleur(2);
+      plotstring(i10);  
+      if(vertices[i].Corner()) couleur(6);
+      }
+  // rattente(1);
+ }
+
+}
+#endif
diff --git a/src/bamglib/MeshGeom.cpp b/src/bamglib/MeshGeom.cpp
new file mode 100644
index 0000000..3c7edd7
--- /dev/null
+++ b/src/bamglib/MeshGeom.cpp
@@ -0,0 +1,1218 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// #define TRACETRIANGLE 3
+extern long verbosity ;
+//#define strcasecmp strcmp
+#include <cstdio>
+#include <string.h>
+#include <cmath>
+#include <time.h>
+#include <iostream>
+using namespace std;
+
+
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+namespace bamg {
+void Triangles::ConsGeometry(Real8 cutoffradian,int *equiedges) // construct a geometry if no geo 
+ {
+  //  if equiedges existe taille nbe 
+  //   equiedges[i]/2 == i  original
+  //   equiedges[i]/2 = j  =>   equivalence entre i et j => meme maillage
+  //   equiedges[i]%2   : 0 meme sens , 1 pas meme sens 
+  //       
+  // --------------------------
+  if (verbosity>1) 
+    cout << "  -- construction of the geometry from the 2d mesh " << endl;
+  if (nbt<=0 || nbv <=0 ) { MeshError(101);}
+
+  // construction of the edges 
+  //  Triangles * OldCurrentTh =CurrentTh;
+  CurrentTh=this;
+  //  Int4 NbTold = nbt;
+  // generation of the integer coor
+  // generation of the adjacence of the triangles
+  if (cutoffradian>=0)
+    Gh.MaximalAngleOfCorner = cutoffradian;
+  SetOfEdges4 * edge4= new SetOfEdges4(nbt*3,nbv);
+  Int4 * st = new Int4[nbt*3];
+  Int4 i,k;
+  int j; 
+  if (Gh.name) delete Gh.name;
+  Gh.name = new char [ name ? strlen(name) + 15 : 50 ];
+  Gh.name[0]=0;
+  strcat(Gh.name,"cons from: ");
+  if (name) strcat(Gh.name,name);
+  else strcat(Gh.name," a mesh with no name");
+  for (i=0;i<nbt*3;i++)
+    st[i]=-1;
+  Int4 kk =0;
+
+  Int4 nbeold = nbe;
+  for (i=0;i<nbe;i++)
+    {
+      //      cout << i << " " << Number(edges[i][0]) << " " << Number(edges[i][1]) << endl;
+      edge4->addtrie(Number(edges[i][0]),Number(edges[i][1]));
+    }
+  if (nbe !=  edge4->nb())
+      { 
+      cerr << " Some Double edge in the mesh, the number is " << nbe 
+	   << " nbe4=" << edge4->nb()  << endl;
+      MeshError(1002);
+    }
+  for (i=0;i<nbt;i++)
+    for  (j=0;j<3;j++)
+      {
+	// Int4 i0,i1;
+	Int4 k =edge4->addtrie(Number(triangles[i][VerticesOfTriangularEdge[j][0]]),
+			       Number(triangles[i][VerticesOfTriangularEdge[j][1]]));
+	Int4 invisible = triangles[i].Hidden(j);
+	if(st[k]==-1)
+	  st[k]=3*i+j;
+	else if(st[k]>=0) {
+	  assert( ! triangles[i].TriangleAdj(j) && !triangles[st[k] / 3].TriangleAdj((int) (st[k]%3)));
+	  
+	  triangles[i].SetAdj2(j,triangles + st[k] / 3,(int) (st[k]%3));
+	  if (invisible)  triangles[i].SetHidden(j);
+	  if (k<nbe) {
+	    triangles[i].SetLocked(j);
+	  }
+	  st[k]=-2-st[k]; }
+	else {
+	  cerr << " The edge (" 
+	       << Number(triangles[i][VerticesOfTriangularEdge[j][0]])
+	       << " , " 
+	       << Number(triangles[i][VerticesOfTriangularEdge[j][1]])
+	       << " ) is in more than 2 triangles " <<k <<endl;
+	  cerr << " Edge " << j << " Of Triangle " << i << endl;
+	  cerr << " Edge " << (-st[k]+2)%3 << " Of Triangle " << (-st[k]+2)/3  << endl;
+	  cerr << " Edge " << triangles[(-st[k]+2)/3].NuEdgeTriangleAdj((int)((-st[k]+2)%3))
+	       << " Of Triangle " <<  Number(triangles[(-st[k]+2)/3].TriangleAdj((int)((-st[k]+2)%3))) 
+	       << endl;
+	  MeshError(9999);}	
+	
+	
+      }
+  Int4 nbedges = edge4->nb(); // the total number of edges 
+    delete edge4;
+  edge4 =0;
+
+  if(verbosity>5) {
+    if (name)
+     cout << "    On Mesh " << name << endl;
+    cout << "    - The number of Vertices  = " << nbv << endl;
+    cout << "    - The number of Triangles = " << nbt << endl;
+    cout << "    - The number of given edge = " << nbe << endl;
+    cout << "    - The number of all edges = " << nbedges << endl;
+    cout << "    - The Euler number = 1-Nb Of Hole = " << nbt-nbedges+nbv << endl; }
+  
+  
+  // check the consistant of edge[].adj and the geometrical required  vertex
+  k=0;
+  kk=0;
+  Int4 it;
+
+  for (i=0;i<nbedges;i++)
+    if (st[i] <-1) // edge internal
+      { 
+	it =  (-2-st[i])/3;
+	j  =  (int) ((-2-st[i])%3);
+	Triangle & tt = * triangles[it].TriangleAdj(j);
+	//cout << it << " c="  << triangles[it].color <<  " " << Number(tt) << " c="  << tt.color << endl;
+	if (triangles[it].color != tt.color|| i < nbeold) // Modif FH 06122055 // between 2 sub domai
+	  k++;
+      }
+    else if (st[i] >=0) // edge alone 
+       // if (i >= nbeold) 
+	     kk++;
+  
+  if(verbosity>4 && (k+kk) )
+    cout << "    Nb of  ref edge " << kk+k << " (internal " << k << ")"
+	 << " in file " << nbe  << endl;
+  k += kk;
+  kk=0;
+    if (k)
+    {
+      
+      //      if (nbe) {
+      //	cerr << k << " boundary edges  are not defined as edges " << endl;
+      //	MeshError(9998);
+      // }
+      // construction of the edges 
+      nbe = k;
+      Edge * edgessave = edges;
+      edges = new Edge[nbe];
+      k =0;
+      // construction of the edges 
+      if(verbosity>4)
+	cout << "    Construction of the edges  " << nbe << endl;
+
+      for (i=0;i<nbedges;i++)
+	{ 
+	  Int4  add= -1;
+	  
+	  if (st[i] <-1) // edge internal
+	    { 
+	      it =  (-2-st[i])/3;
+	      j  =  (int) ((-2-st[i])%3);
+	      Triangle & tt = * triangles[it].TriangleAdj(j);
+	      if (triangles[it].color !=  tt.color || i < nbeold) // Modif FH 06122055
+		  add=k++;
+	    }
+	  else if (st[i] >=0) // edge alone 
+	    {
+	      it = st[i]/3;
+	      j  = (int) (st[i]%3);
+	      add=k++;
+	    }
+	  
+	  if (add>=0 && add < nbe)
+	    {
+	      
+	      edges[add].v[0] = &triangles[it][VerticesOfTriangularEdge[j][0]];
+	      edges[add].v[1] = &triangles[it][VerticesOfTriangularEdge[j][1]];
+	      edges[add].on=0; 
+	      if (i<nbeold) // in file edge // Modif FH 06122055 
+		{
+		  edges[add].ref = edgessave[i].ref; 		      
+		  edges[add].on = edgessave[i].on; //  HACK pour recuperer les aretes requise midf FH avril 2006 ???? 
+		}
+	      else
+		edges[add].ref = Min(edges[add].v[0]->ref(),edges[add].v[1]->ref()); // no a good choice
+	    }
+	}
+      assert(k==nbe);
+      if (edgessave) delete [] edgessave;
+    }
+    
+    // construction of edges[].adj 
+    for (i=0;i<nbv;i++) 
+      vertices[i].color =0;
+    for (i=0;i<nbe;i++)
+      for (j=0;j<2;j++) 
+	edges[i].v[j]->color++;
+    
+    for (i=0;i<nbv;i++) 
+      vertices[i].color = (vertices[i].color ==2) ? -1 : -2;
+    for (i=0;i<nbe;i++)
+      for (j=0;j<2;j++) 
+	{ 
+	  Vertex *v=edges[i].v[j];
+	  Int4 i0=v->color,j0;
+	  if(i0<0)
+	     edges[i ].adj[ j ]=0;  // Add FH Jan 2008   
+	  if(i0==-1)
+	    v->color=i*2+j;
+	  else if (i0>=0) {// i and i0 edge are adjacent by the vertex v
+	    j0 =  i0%2;
+	    i0 =  i0/2;
+	    assert( v ==  edges[i0 ].v[j0]);
+	    edges[i ].adj[ j ] =edges +i0;
+	    edges[i0].adj[ j0] =edges +i ;
+	    assert(edges[i0].v[j0] == v);
+	    //	    if(verbosity>8)
+	    //  cout << " edges adj " << i0 << " "<< j0 << " <-->  "  << i << " " << j << endl;
+	    v->color = -3;}
+	}
+    // now reconstruct the sub domain info 
+    assert(!NbSubDomains);
+  NbSubDomains=0;
+  
+  { 
+    Int4 it;
+    // find all the sub domain
+    Int4 *colorT = new Int4[nbt];
+    Triangle *tt,*t;
+    Int4 k;
+    for ( it=0;it<nbt;it++)
+      colorT[it]=-1;
+    for (it=0;it<nbt;it++)
+      {
+	if (colorT[it]<0) 
+	  {
+	    colorT[it]=NbSubDomains;
+	    Int4 level =1,j,jt,kolor=triangles[it].color;
+	    st[0]=it; // stack 
+	    st[1]=0;
+	    k=1;
+	    while (level>0)
+	      if( ( j=st[level]++) <3)
+		{ 
+		  t = &triangles[st[level-1]];
+		  tt=t->TriangleAdj((int)j);
+		  
+		  if ( ! t->Locked(j) && tt && (colorT[jt = Number(tt)] == -1) && ( tt->color==kolor))
+		    {
+		      colorT[jt]=NbSubDomains;
+		      st[++level]=jt;
+		      st[++level]=0;
+		      k++;
+		    }
+		}
+	      else 
+		level-=2;
+	    if (verbosity>5) 
+	      cout << "   Nb of triangles " << k << " of Subdomain "  
+		   <<  NbSubDomains << " " << kolor << endl;
+	    NbSubDomains++;
+	  }
+      }
+    if (verbosity> 3)
+      cout << "   The Number of sub domain = " << NbSubDomains << endl;
+    
+    Int4 isd;
+    subdomains = new SubDomain[NbSubDomains];
+    for (isd=0;isd<NbSubDomains;isd++)
+      {
+	subdomains[isd].head =0;
+      }
+    k=0;
+    for (it=0;it<nbt;it++)
+      for (int j=0;j<3;j++)
+	{
+	  tt=triangles[it].TriangleAdj(j);
+	  if ((!tt ||  triangles[it].Locked(j) || tt->color != triangles[it].color) && !subdomains[isd=colorT[it]].head)
+	    {
+	      subdomains[isd].head = triangles+it;
+	      subdomains[isd].ref =  triangles[it].color;
+	      subdomains[isd].sens = j; // hack
+	      subdomains[isd].edge = 0;
+	      k++;
+	    }
+	}  
+    assert(k== NbSubDomains);
+    
+    delete [] colorT;
+    
+    
+  }      
+  delete [] st;
+  // now make the geometry
+  // 1 compress the vertices 
+  Int4 * colorV = new Int4[nbv];
+  for (i=0;i<nbv;i++) 
+    colorV[i]=-1;
+  for (i=0;i<nbe;i++)
+    for ( j=0;j<2;j++)
+      colorV[Number(edges[i][j])]=0;
+  k=0;
+  for (i=0;i<nbv;i++) 
+    if(!colorV[i])
+      colorV[i]=k++;
+  
+  Gh.nbv=k;
+  Gh.nbe = nbe;
+  Gh.vertices = new GeometricalVertex[k];
+  Gh.edges = new GeometricalEdge[nbe];
+  Gh.NbSubDomains = NbSubDomains;
+  Gh.subdomains = new GeometricalSubDomain[NbSubDomains];
+  if (verbosity>3)
+    cout << "    Nb of  vertices  = " << Gh.nbv << " Nb of edges = " << Gh.nbe << endl;
+  NbVerticesOnGeomVertex = Gh.nbv;
+  VerticesOnGeomVertex = new VertexOnGeom[NbVerticesOnGeomVertex];
+  NbVerticesOnGeomEdge =0;
+  VerticesOnGeomEdge =0;
+  for (i=0;i<Gh.nbv;i++)
+      Gh.vertices[i].Set();// bug clang ???? FH 09/2012
+     if(verbosity>6){
+         int nbr=0;
+         for (i=0;i<Gh.nbv;i++)
+             if( Gh.vertices[i].Required()) nbr++;
+         cout << " --00 nb  require  v in Gh " << nbr << " on " << Gh.nbv << endl;
+     }
+     
+  {
+    Int4 j;
+    for (i=0;i<nbv;i++) 
+      if((j=colorV[i])>=0)
+	{
+            int k=Gh.vertices[j].cas;
+            Gh.vertices[j].Set(vertices[i]);
+	//  Vertex & v = Gh.vertices[j];
+	 // v = vertices[i];
+	   Gh.vertices[j].color =0;
+            assert(k==Gh.vertices[j].cas);
+	  VerticesOnGeomVertex[j] = VertexOnGeom(vertices[i], Gh.vertices[j]);
+	}
+    
+  }
+     
+  edge4= new SetOfEdges4(nbe,nbv);  
+  
+  Real4 * len = new Real4[Gh.nbv];
+  for(i=0;i<Gh.nbv;i++)
+    len[i]=0;
+     if(verbosity>6){
+         int nbr=0;
+         for (i=0;i<Gh.nbv;i++)
+             if( Gh.vertices[i].Required()) nbr++;
+         cout << " --bb nb  require  v in Gh " << nbr << " on " << Gh.nbv
+         <<endl;
+     }
+
+  Gh.pmin =  Gh.vertices[0].r;
+  Gh.pmax =  Gh.vertices[0].r;
+  // recherche des extrema des vertices pmin,pmax
+  for (i=0;i<Gh.nbv;i++) {
+    Gh.pmin.x = Min(Gh.pmin.x,Gh.vertices[i].r.x);
+    Gh.pmin.y = Min(Gh.pmin.y,Gh.vertices[i].r.y);
+    Gh.pmax.x = Max(Gh.pmax.x,Gh.vertices[i].r.x);
+    Gh.pmax.y = Max(Gh.pmax.y,Gh.vertices[i].r.y);
+  }
+  
+  R2 DD05 = (Gh.pmax-Gh.pmin)*0.05;
+  Gh.pmin -=  DD05;
+  Gh.pmax +=  DD05;
+  
+  Gh.coefIcoor= (MaxICoor)/(Max(Gh.pmax.x-Gh.pmin.x,Gh.pmax.y-Gh.pmin.y));
+  assert(Gh.coefIcoor >0);
+ 
+  Real8 hmin = HUGE_VAL;
+     int kreq=0,kkreq=0;
+  for (i=0;i<nbe;i++)
+    {
+      Int4 i0 = Number(edges[i][0]);
+      Int4 i1 = Number(edges[i][1]);
+      Int4 j0 =	 colorV[i0];
+      Int4 j1 =  colorV[i1];
+      
+      Gh.edges[i].v[0] = Gh.vertices +  j0;
+      Gh.edges[i].v[1] = Gh.vertices +  j1;
+      Gh.edges[i].flag = 0;
+      Gh.edges[i].tg[0]=R2();
+      Gh.edges[i].tg[1]=R2();
+      bool requis= edges[i].on; 
+	if(requis) kreq++;
+      edges[i].on =  Gh.edges + i;
+      if(equiedges && i < nbeold ) {
+        int j=equiedges[i]/2;
+        int sens=equiedges[i]%2;
+        if(i!=j && equiedges[i]>=0) {
+          if(verbosity>9)  
+             cout << " Edges Equi " << i << " <=> " << j << " sens = " << sens  << endl;
+           if( sens==0)
+           Gh.edges[i].SetEqui();
+           else 
+            Gh.edges[i].SetReverseEqui();
+           Gh.edges[i].link= & Gh.edges[j];
+           //assert(sens==0);//  meme sens pour l'instant
+        }
+	
+       }
+      if(requis)  {  // correction fevr 2009 JYU ...
+	Gh.edges[i].v[0]->SetRequired();
+	Gh.edges[i].v[1]->SetRequired();
+	Gh.edges[i].SetRequired(); // fin modif ...
+          kkreq++;
+      }
+      R2 x12 = Gh.vertices[j0].r-Gh.vertices[j1].r;
+      Real8 l12=Norme2(x12);
+      hmin = Min(hmin,l12);
+      
+      Gh.vertices[j1].color++;
+      Gh.vertices[j0].color++;
+      
+      len[j0]+= l12;
+      len[j1] += l12;
+      hmin = Min(hmin,l12);
+      
+      Gh.edges[i].ref  = edges[i].ref;
+      
+      k = edge4->addtrie(i0,i1);
+      
+      assert(k == i);
+      
+    }
+     if(verbosity>6){
+         int nbr=0;
+         for (i=0;i<Gh.nbv;i++)
+             if( Gh.vertices[i].Required()) nbr++;
+         cout << " --11 nb  require  v in Gh " << nbr << " on " << Gh.nbv
+              << " kreq =" << kreq<<" kkreq=" << kkreq <<endl;
+     }
+ 
+  
+  for (i=0;i<Gh.nbv;i++) 
+    if (Gh.vertices[i].color > 0) 
+      Gh.vertices[i].m=  Metric(len[i] /(Real4) Gh.vertices[i].color);
+    else 
+      Gh.vertices[i].m=  Metric(hmin);
+  delete [] len;
+  for (i=0;i<NbSubDomains;i++)
+    {
+      Int4 it = Number(subdomains[i].head);
+      int j = subdomains[i].sens;
+      Int4 i0 = Number(triangles[it][VerticesOfTriangularEdge[j][0]]);
+      Int4 i1 = Number(triangles[it][VerticesOfTriangularEdge[j][1]]);
+      k = edge4->findtrie(i0,i1);
+      if(k>=0)
+	{
+	  subdomains[i].sens = (vertices + i0 == edges[k].v[0]) ? 1 : -1;
+	  subdomains[i].edge = edges+k;
+	  Gh.subdomains[i].edge = Gh.edges + k;
+	  Gh.subdomains[i].sens  =  subdomains[i].sens;
+	  Gh.subdomains[i].ref =  subdomains[i].ref;
+	}
+      else
+	MeshError(103);
+    }
+  
+  delete edge4;
+  delete [] colorV;
+  //  -- unset adj
+  for (i=0;i<nbt;i++)
+    for ( j=0;j<3;j++)
+      triangles[i].SetAdj2(j,0,triangles[i].GetAllflag(j));
+     if(verbosity>6){
+         int nbr=0;
+         for (i=0;i<Gh.nbv;i++)
+             if( Gh.vertices[i].Required()) nbr++;
+         cout << " -- nb  required  v in Gh " << nbr << " on " << Gh.nbv << endl;
+     }
+ }
+
+
+void Geometry::EmptyGeometry()  // empty geometry
+  {
+  OnDisk=0;
+  NbRef=0;
+  name =0;
+  quadtree=0;
+  curves=0;
+ // edgescomponante=0;
+  triangles=0;
+  edges=0;
+  vertices=0;
+  NbSubDomains=0;
+  //  nbtf=0;
+//  BeginOfCurve=0;  
+  nbiv=nbv=nbvx=0;
+  nbe=nbt=nbtx=0;
+  NbOfCurves=0;
+//  BeginOfCurve=0;
+  subdomains=0;
+  MaximalAngleOfCorner = 10*Pi/180;
+  }
+
+
+
+Geometry::Geometry(const Geometry & Gh)
+ { Int4 i;
+   *this = Gh;
+   NbRef =0;
+   quadtree=0;
+   name = new char[strlen(Gh.name)+4];
+   strcpy(name,"cp:");
+   strcat(name,Gh.name);
+   vertices = nbv ? new GeometricalVertex[nbv] : NULL;
+   triangles = nbt ? new  Triangle[nbt]:NULL;
+   edges = nbe ? new GeometricalEdge[nbe]:NULL;
+   curves= NbOfCurves ? new Curve[NbOfCurves]:NULL;
+   subdomains = NbSubDomains ? new GeometricalSubDomain[NbSubDomains]:NULL;
+   for (i=0;i<nbv;i++)
+     vertices[i].Set(Gh.vertices[i],Gh,*this);
+   for (i=0;i<nbe;i++)
+     edges[i].Set(Gh.edges[i],Gh,*this);
+   for (i=0;i<NbOfCurves;i++)
+     curves[i].Set(Gh.curves[i],Gh,*this);
+   for (i=0;i<NbSubDomains;i++)
+     subdomains[i].Set(Gh.subdomains[i],Gh,*this);
+     
+   //    for (i=0;i<nbt;i++)
+   //      triangles[i].Set(Gh.triangles[i],Gh,*this);
+   assert(!nbt);   
+ }
+
+
+GeometricalEdge* Geometry::Contening(const R2 P,  GeometricalEdge * start) const
+{
+  GeometricalEdge* on =start,* pon=0;
+  // walk with the cos on geometry
+  //  cout << P ;
+  int k=0;
+   while(pon != on)
+     {  
+       pon = on;
+       assert(k++<100);
+       R2 A= (*on)[0];
+       R2 B= (*on)[1];
+       R2 AB = B-A;
+       R2 AP = P-A;
+       R2 BP = P-B;
+       //   cout << "::  " << on - edges << " "  <<  AB*AP  << " " <<  AB*BP << " " << A << B << endl;
+       if ( (AB,AP) < 0) 
+	 on = on->Adj[0];
+       else if ( (AB,BP)  > 0) 
+	 on = on->Adj[1];
+       else
+	 return on;
+     }
+   return on;
+}
+GeometricalEdge* Geometry::ProjectOnCurve(const Edge & e,Real8 s,Vertex &V,VertexOnGeom &GV ) const 
+ {  
+    Real8 save_s=s;
+    int NbTry=0;
+retry:    
+    s=save_s;
+    GeometricalEdge * on = e.on;
+    assert(on);
+    assert( e[0].on &&  e[1].on);
+    const Vertex &v0=e[0],&v1=e[1];
+    V.m = Metric(1.0-s, v0,s, v1);
+#define MXE__LINE  __LINE__+1
+    const int mxe =100;
+    GeometricalEdge *ge[mxe+1];
+    int    sensge[mxe+1];
+    Real8  lge[mxe+1];
+    int bge=mxe/2,tge=bge;
+    ge[bge] = e.on;
+    sensge[bge]=1;
+
+    R2 V0 = v0,V1=v1,V01=V1-V0;
+    VertexOnGeom  vg0= *v0.on,  vg1=*v1.on;
+    if(NbTry) cout << "bug: s==== " << s << " e=" <<  V0 << " " << V1 << endl;
+
+    //    GeometricalEdge * eg0 = e.on,* eg1 = e.on, *eg=NULL;
+    GeometricalEdge * eg0=on, *eg1=on;
+    R2 Ag=(R2) (*on)[0],Bg=(R2)(*on)[1],AB=Bg-Ag; 
+    if(NbTry) cout <<" G edge= " << Ag << Bg << endl << " v edge" << V01 << " v geom " << AB  <<  (V01,AB) <<endl; 
+    int OppositeSens = (V01,AB) < 0;
+    int sens0=0,sens1=1;
+    if (OppositeSens)
+      s=1-s,Exchange(vg0,vg1),Exchange(V0,V1);
+    // find all the discretisation of the egde 
+#ifdef DEBUG
+    // we supposee  edge on=[Ag,Bg]  intersect edge [V0,V1];
+    // =>   V0Ag.V0V1 > 0 ||  V0Bg.V0V1 >0
+    // =>   V1Ag.V0V1 < 0 ||  V0Bg.V0V1 <0
+    R2 V0V1 = V1-V0;
+    Real8 cos0A = ((Ag-V0),V0V1);
+    Real8 cos0B = ((Bg-V0),V0V1);
+    Real8 cos1A = ((Ag-V1),V0V1);
+    Real8 cos1B = ((Bg-V1),V0V1);
+    if ( (cos0A < 0 && cos0B <0) || (cos1A> 0 && cos1B >0))
+      {
+	cerr << "  Bug on pointer edge  [" << V0 << " , " << V1 << " ] "
+	     << "  on geometrical edge " << Number(on) << " = [" << Ag << " , " << Bg << " ] " << endl;
+	cerr << cos0A << "> 0  ||  " << cos0B <<  " >  0  and  ";
+	cerr << cos1A << "< 0  ||  " << cos1B <<  " <  0  " << endl;
+	
+	exit (1);
+	}
+    
+#endif    
+    if(NbTry) cout << "bug: edge = " << v0.r << " -> " << v1.r << endl 
+		   << "sg 0 = " << vg0 
+		   << " on = " << Number(on) << ":" << Ag << Bg << "; " 
+		   <<  " sg 1= " << vg1 
+		   << "--------------------------------------------" << endl;
+    while (eg0 != (GeometricalEdge*) vg0  &&  (*eg0)(sens0) != (GeometricalVertex*) vg0)
+      { 
+      if (bge<=0) {
+	//          int kkk;
+          // if (NbTry) cout <<"Read (int) to Show Sioux window", cin >> kkk ;
+	       if(NbTry) 
+	          {
+		    cerr << " -- Fatal Error: on the class triangles before call Geometry::ProjectOnCurve" << endl; 
+		    cerr << "   The mesh of the  Geometry is to fine: ";
+		    cerr << "     1)  a mesh edge  contening more than "<< mxe/2 << " geometrical edges." << endl;
+		    cerr << "     2)  code bug : be sure that we call   Triangles::SetVertexFieldOn() before " << endl;
+		    cerr << "   To solve the problem do a coarsening of the geometrical mesh " << endl;
+		    cerr << " or change the constant value of mxe in " << __FILE__ << " line " << MXE__LINE << "( dangerous way )" << endl;	  
+		    MeshError(222);
+		  }
+	    NbTry++;
+	    goto retry;}
+        GeometricalEdge* tmpge = eg0;
+	 if(NbTry)
+		cout << "bug: --Edge @" <<  Number(tmpge)  << " = "<< Number(eg0) << ":" <<Number(eg0->Adj[0]) << "," <<  
+			 Number(eg0->Adj[1]) <<"," ;
+	ge[--bge] =eg0 = eg0->Adj[sens0];
+	assert(bge>=0 && bge <= mxe);
+	sens0 = 1-( sensge[bge] = tmpge->SensAdj[sens0]);
+	if(NbTry)
+		cout << "bug: Edge "  <<  Number(eg0) << " "<< 1-sens0 <<  " S "
+		     << Number((*eg0)[1-sens0]) <<":" << Number(eg0->Adj[0]) << "," 
+		     <<  Number(eg0->Adj[1]) <<"," << endl
+	 	     <<Number(eg0)<< (*eg0)[sens0].r << "v = " << Number((*eg1)(sens0)) << " e = " << eg0 <<  endl;
+     }
+      if(NbTry) cout << Number((GeometricalEdge*) vg1) << " " << Number((GeometricalVertex*) vg1) << endl;
+    while (eg1 != (GeometricalEdge*) vg1  &&  (*eg1)(sens1) != (GeometricalVertex*) vg1)
+      { 
+        if(tge>=mxe ) { 
+	  cerr << " --Fatal Error: on the class triangles before call Geometry::ProjectOnCurve" << endl; 
+	  NbTry++;
+	  if (NbTry<2) goto retry;
+	  cerr << "   The mesh of the  Geometry is to fine:" ;
+	  cerr << "     1)  a mesh edge  contening more than "<< mxe/2 << " geometrical edges." << endl;
+	  cerr << "     2)  code bug : be sure that we call   Triangles::SetVertexFieldOn() before " << endl;
+	  cerr << "   To solve the problem do a coarsening of the geometrical mesh " << endl;
+	  cerr << " or change the constant value of mxe in " << __FILE__ << " line " << MXE__LINE << "( dangerous way )" << endl;	
+	  MeshError(223);
+	}
+
+	GeometricalEdge* tmpge = eg1;
+	if(NbTry)
+		cout << "++Edge @" << tmpge << " = " <<  Number(eg1) <<"%" << Number(eg1->Adj[0]) << "," 
+		 <<  Number(eg1->Adj[1]) <<"," ;
+	ge[++tge] =eg1 = eg1->Adj[sens1];
+	sensge[tge]= sens1 = 1-tmpge->SensAdj[sens1];
+	assert(tge>=0 && tge <= mxe);
+         if(NbTry)
+		cout << "  Edge "  <<  Number(eg1) << " " << sens1 << " S "
+		     <<Number((*eg1)[sens1]) <<"%"<< Number(eg1->Adj[0]) << "," <<  Number(eg1->Adj[1]) <<"," 
+	             <<Number(eg1)<< (*eg1)[sens1].r << "v = " << Number((*eg1)(sens1)) << " e = " << Number(eg1) <<  endl;
+      }
+
+    	if(NbTry)    cout << endl;
+        
+
+    if ( (*eg0)(sens0) == (GeometricalVertex*) vg0 )
+      vg0 = VertexOnGeom( *(Vertex *) vg0,*eg0,sens0);
+    
+    if ( (*eg1)(sens1) == (GeometricalVertex*) vg1)
+       vg1 = VertexOnGeom( *(Vertex *) vg1,*eg1,sens1);
+
+    Real8 sg;
+    //   cout << "           " << Number(on) << " " <<  Number(eg0) << " " <<  Number(eg1) << " "  ; 
+    if (eg0 == eg1) { 
+        Real8 s0= vg0,s1=vg1;
+       sg =  s0 * (1.0-s) +  s * s1;
+       //    cout <<"                s0=" << s0 << " s1=" << s1 
+       //             << " s = " << s << " sens= " << OppositeSens << "\t\t sg = " << sg << endl ;
+       on=eg0;}
+    else {
+       R2 AA=V0,BB;
+       Real8 s0,s1;
+       
+       //cout << endl << "s= " << s << Number(eg0) << " " << (Real8) vg0 << " " 
+       //	    << Number(eg1) << " " << (Real8) vg1 << V0 << V1 << "  Interpol = " 
+       // << V0*(1-s)+V1*s << ";;; " <<  endl;
+       int i=bge;
+       Real8 ll=0;
+       for(i=bge;i<tge;i++) 
+	 {
+	   assert( i>=0 && i <= mxe);
+	   BB =  (*ge[i])[sensge[i]];
+	   lge[i]=ll += Norme2(AA-BB);
+	   //   cout << " ll " << i << BB << ll << " " <<sensge[i] <<" on = " <<
+	   // Number(ge[i]) << " sens= " << sensge[i] ;
+	   AA=BB ;}
+       lge[tge]=ll+=Norme2(AA-V1); 
+       // cout << " ll " << tge << " " << ll <<  sensge[tge] 
+       //	     <<" on = " << Number(ge[tge]) <<  " sens= " << sensge[tge] << endl;
+    // search the geometrical edge
+      assert(s <= 1.0);
+      Real8 ls= s*ll;
+      on =0;
+      s0 = vg0;
+      s1= sensge[bge];
+      Real8 l0=0,l1;
+      i=bge;
+      while (  (l1=lge[i]) < ls ) {
+	assert(i >= 0 && i <= mxe);
+	i++,s0=1-(s1=sensge[i]),l0=l1;}
+      on=ge[i];
+      if (i==tge) 
+	s1=vg1;
+     
+      s=(ls-l0)/(l1-l0);
+      //  cout << "on =" << Number(on) << sens0 << sens1 <<  "s0  " << s0 << " s1 =" 
+      //	     << s1 << " l0 =" << l0 << " ls= " << ls << " l1= " << l1 << " s= " << s;
+       sg =  s0 * (1.0-s) +  s * s1;    
+       } 
+    assert(on);
+    // assert(sg && sg-1);
+    V.r= on->F(sg);
+    //  if (eg0 != eg1) 
+    //        cout << "----- sg = "<< sg << " Sens =" << OppositeSens << " Edge = " 
+    //     << Number(on) <<"  V=" << V << endl;
+    GV=VertexOnGeom(V,*on,sg);
+    return on;
+ }
+
+void Geometry::AfterRead()
+ {// -----------------
+    if (verbosity>20)
+    cout << "Geometry::AfterRead()" <<  nbv << " " << nbe << endl;
+    Int4 i,k=0;        ;
+    int jj; // jj in [0,1]
+    Int4 * hv = new Int4 [ nbv];
+    Int4 * ev = new Int4 [ 2 * nbe ];
+    float  * eangle = new float[ nbe ];
+    {
+      double eps = 1e-20;
+      QuadTree quadtree; // to find same vertices
+      Vertex * v0 = vertices; 
+      GeometricalVertex  * v0g = (GeometricalVertex  *) (void *) v0;   
+      int k=0;
+      for (i=0;i<nbv;i++) 
+        vertices[i].link = vertices +i;
+      for (i=0;i<nbv;i++) 
+	     {
+	      vertices[i].i = toI2(vertices[i].r); // set integer coordinate
+	      Vertex *v= quadtree.NearestVertex(vertices[i].i.x,vertices[i].i.y); 
+	      if( v && Norme1(v->r - vertices[i]) < eps )
+	       { // link v & vertices[i] 
+	         // vieille ruse pour recuperer j 
+	         GeometricalVertex * vg = (GeometricalVertex  *) (void *) v;
+	         int j = vg-v0g;
+	         assert( v ==  & (Vertex &) vertices[j]);
+	         vertices[i].link = vertices + j;
+            k++;	      
+	       }
+	      else  quadtree.Add(vertices[i]); 
+	     }
+      if (k) {
+	cout << " Number of distinte vertices " << nbv - k << " Over " << nbv << endl;
+	//if (verbosity>10) 
+	{
+	  cout << " The duplicate vertex " << endl;
+	  for (i=0;i<nbv;i++)
+	    if (!vertices[i].IsThe())
+	      cout << " " << i << " and " << Number(vertices[i].The()) << endl;
+	  MeshError(102);
+	  //throw(ErrorExec("exit",1));    
+	}
+      }
+      
+      //  verification of cracked edge
+      int err =0;
+      for (i=0;i<nbe;i++)
+	if (edges[i].Cracked() )
+	  {
+	    //    verification of crack
+	    GeometricalEdge & e1=edges[i];
+	    GeometricalEdge & e2=*e1.link;
+            cerr << i << " " << e1[0].The() << " " << e2[0].The() << " " <<  e1[1].The() << " " << e2[1].The() << endl;
+	    if ( e1[0].The() == e2[0].The() && e1[1].The() == e2[1].The() )
+	      {
+	      }
+	    else 
+	      if ( e1[0].The() == e2[1].The() && e1[1].The() == e2[0].The() )
+		{
+		}
+	      else
+		{
+		  err++;
+		  cerr << " Cracked edges with no same vertex " << &e1-edges << " " << &e2 -edges << endl;
+		}
+	  }
+	else
+	  {
+	    //  if (!edges[i][0].IsThe()) err++;
+	    // if (!edges[i][1].IsThe()) err++;
+	  }
+      if (err)
+	{
+	  cerr << " Some vertex was not distint and not on cracked edge " << err<< endl;
+	  MeshError(222);
+	}
+    }
+    if(verbosity>7) 
+      for (i=0;i<nbv;i++)
+	if (vertices[i].Required())
+	  cout << "     The geo vertices  " << i << " is required" << endl;
+
+    for (i=0;i<nbv;i++) 
+      hv[i]=-1;// empty list
+
+    for (i=0;i<nbe;i++) 
+      {
+        R2 v10  =  edges[i].v[1]->r -  edges[i].v[0]->r;
+        Real8 lv10 = Norme2(v10);
+        if(lv10 == 0) {
+          cerr << "The length  of " <<i<< "th Egde is 0 " << endl ;
+          MeshError(1);}
+        eangle[i] = atan2(v10.y,v10.x)  ; // angle in [ -Pi,Pi ]
+	if(verbosity>9) 
+	  cout << "     angle edge " << i <<" " << eangle[i]*180/Pi<< v10<<endl;
+        for (jj=0;jj<2;jj++)
+          { // generation of list
+            Int4 v =  Number(edges[i].v[jj]);
+            ev[k] = hv[v];
+            hv[v] = k++;
+          }
+      }
+    // bulle sort on the angle of edge  
+    for (i=0;i<nbv;i++) {
+      int exch = 1,ord =0;      
+      while (exch) {
+        exch = 0;
+        Int4  *p =  hv + i, *po = p;
+	Int4 n = *p;
+         float angleold = -1000 ; // angle = - infini 
+        ord = 0;
+        while (n >=0) 
+        {
+          ord++;
+           Int4 i1= n /2;
+           Int4  j1 = n % 2;
+           Int4 *pn = ev + n;
+          float angle = j1 ? OppositeAngle(eangle[i1]):  eangle[i1];
+          n = *pn;
+          if (angleold > angle) // exch to have : po -> pn -> p 
+            exch=1,*pn = *po,*po=*p,*p=n,po = pn;
+          else //  to have : po -> p -> pn 
+            angleold =  angle, po = p,p  = pn;
+        }
+      } // end while (exch)
+      
+      if (ord >= 1 ) 
+	{ /*
+	  Int4 n = hv[i];
+	  while ( n >=0) 
+	    { Int4 i1 = n/2,j1 = n%2;
+	    //float a = 180*(j1 ? OppositeAngle(eangle[i1]): eangle[i1])/Pi;
+	    n = ev[n];
+	    }
+	  */
+	} 
+      if(ord == 2) { // angulare test to find a corner 
+        Int4 n1 = hv[i];
+        Int4 n2 = ev[n1];
+        Int4 i1 = n1 /2, i2 = n2/2; // edge number
+        Int4  j1 = n1 %2, j2 = n2%2; // vertex in the edge 
+        float angle1= j1 ? OppositeAngle(eangle[i1]) :  eangle[i1];
+        float angle2= !j2 ? OppositeAngle(eangle[i2]) :  eangle[i2];
+	float da12 = Abs(angle2-angle1);
+	if(verbosity>9)
+	  cout <<"     check angle " << i << " " << i1 << " " << i2  << " " << 180*(da12)/Pi 
+	       << " " << 180*MaximalAngleOfCorner/Pi << vertices[i] << endl;
+
+        if (( da12 >= MaximalAngleOfCorner ) 
+            && (da12 <= 2*Pi -MaximalAngleOfCorner)) {
+	  vertices[i].SetCorner() ; 
+	  if(verbosity>7)
+	    cout << "     The vertex " << i << " is a corner (angle) " 
+		 << 180*(da12)/ Pi<< " " << 180*MaximalAngleOfCorner/Pi << endl;}
+	// if the ref a changing then is     SetRequired();
+	
+	if (edges[i1].flag != edges[i2].flag || edges[i1].Required()) 
+	 {
+	  vertices[i].SetRequired();
+	  if(verbosity>7)
+	    cout << "     The vertex " << i << " is Required the flag change (crack or equi, or require)" << endl;}
+	  
+	if (edges[i1].ref != edges[i2].ref) {
+	  vertices[i].SetRequired();
+	  if(verbosity>7)
+	    cout << "     The vertex " << i << " is Required ref" << endl;}
+      } ;
+      
+      if(ord != 2) {
+        vertices[i].SetCorner();
+	if(verbosity>7)
+	  cout << "     the vertex " << i << " is a corner ordre = " << ord << endl;
+      }
+      // close the liste around the vertex 
+      { Int4 no=-1, ne = hv[i];
+        while ( ne >=0) 
+                 ne = ev[no=ne];        
+            if(no>=0) 
+              ev[no] = hv[i];
+          } // now the list around the vertex is circular
+      
+    } // end for (i=0;i<nbv;i++)
+ 
+    k =0;
+    for (i=0;i<nbe;i++)
+      for (jj=0;jj<2;jj++){
+            Int4 n1 = ev[k++]; 
+            Int4 i1 = n1/2 ,j1=n1%2;
+            if( edges[i1].v[j1] != edges[i].v[jj]) 
+              { cerr << " Bug Adj edge " << i << " " << jj << 
+                  " et " << i1 << " " << j1 << " k=" << k;
+                cerr << Number(edges[i].v[jj]) <<" <> " 
+                     << Number(edges[i1].v[j1])  <<endl;
+                cerr << "edge " << Number(edges[i].v[0]) << " " 
+                     << Number(edges[i].v[1]) << endl; 
+            //    cerr << "in file " <<filename <<endl;
+                MeshError(1);
+              }
+            edges[i1].Adj[j1] = edges + i;
+            edges[i1].SensAdj[j1] = jj;
+	    if (verbosity>10)
+	      cout << " edges. Adj " << i1 << " " << j1 << " <--- " << i << " " << jj << endl;
+      }
+    
+    // generation of  all the tangente 
+    for (i=0;i<nbe;i++) {
+        R2 AB = edges[i].v[1]->r -edges[i].v[0]->r;        
+	Real8 lAB = Norme2(AB); // length of current edge AB
+        Real8 ltg2[2];
+        ltg2[0]=0;ltg2[1]=0;
+        for (jj=0;jj<2;jj++) {
+             R2 tg =  edges[i].tg[jj];
+             Real8 ltg = Norme2(tg); // length of tg
+             if(ltg == 0) {// no tg
+	       if( ! edges[i].v[jj]->Corner())   { // not a Corner       
+		 tg =  edges[i].v[1-jj]->r 
+		   - edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r;
+		 ltg =  Norme2(tg);
+		 tg =  tg *(lAB/ltg),ltg=lAB;
+		/*
+		   if(edges[i].ref >=4) 
+		   cout << " tg " << tg.x << " "<< tg.y  << " " << edges[i].v[1-jj]->r << edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r << " y-y = "
+		     << edges[i].v[1-jj]->r.y -edges[i].Adj[jj]->v[1-edges[i].SensAdj[jj]]->r.y <<  endl;
+		*/
+	       }
+	       
+	       //else ;// a Corner with no tangent => nothing to do    
+             } // a tg 
+             else 
+               tg = tg *(lAB/ltg),ltg=lAB;
+             ltg2[jj] = ltg;
+             if ( (tg,AB) < 0) 
+               tg = -tg;
+	    //if(edges[i].ref >=4) cout << " tg = " << tg << endl;
+             edges[i].tg[jj] = tg;
+	}     // for (jj=0;jj<2;jj++) 
+	
+	if (ltg2[0]!=0) edges[i].SetTgA();
+	if (ltg2[1]!=0) edges[i].SetTgB();
+    } // for (i=0;i<nbe;i++)
+
+    if(verbosity>7)
+      for (i=0;i<nbv;i++)
+	if (vertices[i].Required())
+	  cout << "     The  geo  vertices " << i << " is required " << endl;
+  
+   for (int step=0;step<2;step++)
+   {
+    for (i=0;i<nbe;i++) 
+      edges[i].SetUnMark();
+    
+    NbOfCurves = 0;
+    Int4  nbgem=0;
+    for (int level=0;level < 2 && nbgem != nbe;level++)
+      for (i=0;i<nbe;i++) {
+	GeometricalEdge & ei = edges[i];   
+	for(jj=0;jj<2;jj++) 
+	  if (!ei.Mark() && (level || ei[jj].Required())) { 
+	    // warning ei.Mark() can be change in loop for(jj=0;jj<2;jj++) 
+	    int k0=jj,k1;
+	    GeometricalEdge *e = & ei;
+	    GeometricalVertex *a=(*e)(k0); // begin 
+	    if(curves) {
+	      curves[NbOfCurves].be=e;
+	      curves[NbOfCurves].kb=k0;
+	    }
+	    int nee=0;
+	    for(;;) { 
+		nee++;
+	      k1 = 1-k0; // next vertex of the edge 
+	      e->SetMark();
+	      nbgem++;
+	      e->CurveNumber=NbOfCurves;
+	      if(curves) {
+	      curves[NbOfCurves].ee=e;
+	      curves[NbOfCurves].ke=k1;
+	      }
+	      
+	      GeometricalVertex *b=(*e)(k1);
+	      if (a == b ||  b->Required() ) break;
+	      k0 = e->SensAdj[k1];//  vertex in next edge
+	      e = e->Adj[k1]; // next edge
+	      
+	    }// for(;;)
+	      if(verbosity>10 && curves==0) cout << NbOfCurves <<" curve :  nb edges=  "<< nee<<  endl; 
+	    NbOfCurves++;
+	    if(level) {
+	      if(verbosity>4)
+		cout << "    Warning: Curve "<< NbOfCurves << " without required vertex " 
+		     << "so the vertex " << Number(a) << " become required " <<endl;
+	      a->SetRequired();
+	    }
+       
+	  }} 
+	  assert(nbgem && nbe);
+
+	  if(step==0) {
+	    curves = new Curve[NbOfCurves];
+	  }
+    	} 
+    for(int i=0;i<NbOfCurves ;i++)
+     {
+       GeometricalEdge * be=curves[i].be, *eqbe=be->link;
+       //GeometricalEdge * ee=curves[i].ee, *eqee=be->link;
+       curves[i].master=true;
+       if(be->Equi() || be->ReverseEqui() ) 
+        {
+          assert(eqbe);
+          int nc = eqbe->CurveNumber;
+          assert(i!=nc);
+          curves[i].next=curves[nc].next;
+          curves[i].master=false;
+          curves[nc].next=curves+i;
+          if(be->ReverseEqui())
+           curves[i].Reverse();           
+        }
+     }
+    	 
+    if(verbosity>3)
+      cout << "    End ReadGeometry: Number of curves in geometry is " << NbOfCurves <<endl; 
+    if(verbosity>4)
+    for(int i=0;i<NbOfCurves ;i++)
+     {
+        cout << " Curve " << i << " begin e=" << Number(curves[i].be) << " k=" << curves[i].kb 
+             << "  end e= " << Number(curves[i].ee) << " k=" << curves[i].ke << endl;
+     }
+    delete []ev;
+    delete []hv;
+    delete []eangle;
+    
+}
+Geometry::~Geometry() 
+{
+  assert(NbRef<=0);
+  if(verbosity>9)
+    cout << "DELETE      ~Geometry "<< this  << endl;
+  if(vertices)  delete [] vertices;vertices=0;
+  if(edges)     delete [] edges;edges=0;
+ // if(edgescomponante) delete [] edgescomponante; edgescomponante=0;
+  if(triangles) delete [] triangles;triangles=0;
+  if(quadtree)  delete  quadtree;quadtree=0;
+  if(curves)  delete  []curves;curves=0;NbOfCurves=0;
+  if(name) delete [] name;name=0;
+  if(subdomains) delete [] subdomains;subdomains=0;
+//  if(ordre)     delete [] ordre;
+  EmptyGeometry();
+
+}
+
+Real8 GeometricalEdge::R1tg(Real8 theta,R2 & t) const // 1/R of radius of cuvature
+{ R2 A=v[0]->r,B=v[1]->r;
+ Real8 dca,dcb,dcta,dctb;
+ Real8 ddca,ddcb,ddcta,ddctb;
+ // Real8 t1 = 1 -theta;
+ // Real8 t1t1 = t1*t1;
+ Real8 tt = theta*theta;
+ assert( theta >=0);
+ assert( theta <=1);
+ if (TgA()) 
+  if (TgB()) // interpolation d'hermite
+    { //cb =  theta*theta*(3-2*theta);
+     dcb = 6*theta*(1-theta);
+     ddcb = 6*(1-2*theta);
+     //ca =  1-cb;     
+     dca = -dcb;
+     ddca = -ddcb;
+
+       // cta = (1-theta)*(1-theta)*theta;
+     dcta =  (3*theta - 4)*theta + 1;
+     ddcta=6*theta-4;
+
+     //ctb = (theta-1)*theta*theta ;
+     dctb = 3*tt - 2*theta;
+     ddctb = 6*theta-2;
+    }
+  else { // 1-t*t, t-t*t, t*t
+    Real8 t = theta;
+    // cb = t*t;
+    dcb = 2*t;
+    ddcb = 2;
+    //ca = 1-cb;
+    dca = -dcb;
+    ddca = -2;
+    // cta= t-cb;
+    dcta = 1-dcb;
+    ddcta = -ddcb;
+    // ctb =0;
+    dctb=0;    
+    ddctb=0;    
+  }    
+ else
+  if (TgB()){
+    Real8 t = 1-theta;
+    //ca = t*t;
+    dca = -2*t;
+    ddca = 2;
+    //cb = 1-ca;
+    dcb = -dca;
+    ddcb = -2;
+    //ctb= -t+ca;
+    dctb = 1+dca;
+    ddctb= ddca;
+    //cta=0;    
+    dcta =0;
+    ddcta =0;
+   }
+  else {t=B-A;return 0;} // lagrange P1
+  R2 d =  A*dca + B*dcb + tg[0]* dcta + tg[1] * dctb;
+  
+  R2 dd =  A*ddca + B*ddcb + tg[0]* ddcta + tg[1] * ddctb;
+  Real8 d2=(d,d);
+  Real8 sd2 = sqrt(d2);
+  t=d;
+  if(d2>1.0e-20) {t/=sd2;return Abs(Det(d,dd))/(d2*sd2);}
+  else return 0;
+
+}
+
+
+R2 GeometricalEdge::F(Real8 theta) const // parametrization of the curve edge
+{ R2 A=v[0]->r,B=v[1]->r;
+ Real8 ca,cb,cta,ctb;
+ assert( theta >=-1e-12);
+ assert( theta <=1+1e-12);
+ if (TgA()) 
+  if (TgB()) // interpolation d'hermite
+   { cb =  theta*theta*(3-2*theta);
+     ca =  1-cb;     
+     cta = (1-theta)*(1-theta)*theta;
+     ctb = (theta-1)*theta*theta ;
+   //  if(ref==4 || ref==5)
+   //  cout << " FFF " << tg[0] << tg[1] << A << B << " => " << A*ca + B*cb + tg[0]* cta + tg[1] * ctb << endl;
+    }
+  else { // 1-t*t, t-t*t, t*t
+    Real8 t = theta;
+    cb = t*t;
+    ca = 1-cb;
+    cta= t-cb;
+    ctb=0;    
+  }    
+ else
+  if (TgB()){
+    Real8 t = 1-theta;
+    ca = t*t;
+    cb = 1-ca;
+    ctb= -t+ca;
+    cta=0;    
+   }
+  else {
+      ca =(1-theta),cb = theta,cta=ctb=0; // lagrange P1
+   }
+ return A*ca + B*cb + tg[0]* cta + tg[1] * ctb;
+
+}
+
+}
diff --git a/src/bamglib/MeshQuad.cpp b/src/bamglib/MeshQuad.cpp
new file mode 100644
index 0000000..a890a38
--- /dev/null
+++ b/src/bamglib/MeshQuad.cpp
@@ -0,0 +1,943 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+// ********** DO NOT REMOVE THIS BANNER **********
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// SUMMARY: Bamg: Bidimensional Anisotrope Mesh Generator
+// RELEASE: 0 
+// AUTHOR:   F. Hecht,    
+// ORG    :  UMPC
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+// ORIG-DATE:     frev 98
+//---------------------------------------------------------
+//  to make quad 
+// -------------------
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+
+namespace bamg {
+
+static const  Direction NoDirOfSearch=Direction();
+
+#ifdef __MWERKS__
+#pragma global_optimizer on
+#pragma optimization_level 1
+//#pragma inline_depth 0
+#endif
+
+class DoubleAndInt4 {
+public: double q; Int4 i3j;
+  int operator<(DoubleAndInt4 a){return q > a.q;}
+};// to sort by decroissant
+
+
+
+template<class T>  inline void  HeapSort(T *c,long n)
+{
+  long l,j,r,i;
+  T crit;
+  c--; // on decale de 1 pour que le tableau commence a 1
+  if( n <= 1) return;
+  l = n/2 + 1;
+  r = n;
+  while (1) { // label 2
+    if(l <= 1 ) { // label 20
+      crit = c[r];
+      c[r--] = c[1];
+    if ( r == 1 ) { c[1]=crit; return;}
+    } else  crit = c[--l]; 
+    j=l;
+    while (1) {// label 4
+      i=j;
+      j=2*j;
+      if  (j>r) {c[i]=crit;break;} // L8 -> G2
+      if ((j<r) && (c[j] < c[j+1])) j++; // L5
+      if (crit < c[j]) c[i]=c[j]; // L6+1 G4
+      else {c[i]=crit;break;} //L8 -> G2
+    }
+  }
+}
+
+Triangle * swapTest(Triangle *t1,Int2 a);
+// 
+
+
+double QuadQuality(const Vertex & a,const Vertex &b,const Vertex &c,const Vertex &d)
+{
+  // calcul de 4 angles --
+  R2 A((R2)a),B((R2)b),C((R2)c),D((R2)d);
+  R2 AB(B-A),BC(C-B),CD(D-C),DA(A-D);
+  //  Move(A),Line(B),Line(C),Line(D),Line(A);
+  const Metric & Ma  = a;
+  const Metric & Mb  = b;
+  const Metric & Mc  = c;
+  const Metric & Md  = d;
+    
+  double lAB=Norme2(AB);
+  double lBC=Norme2(BC);
+  double lCD=Norme2(CD);
+  double lDA=Norme2(DA);
+  AB /= lAB;  BC /= lBC;  CD /= lCD;  DA /= lDA;
+  // version aniso 
+  double cosDAB= Ma(DA,AB)/(Ma(DA)*Ma(AB)),sinDAB= Det(DA,AB);
+  double cosABC= Mb(AB,BC)/(Mb(AB)*Mb(BC)),sinABC= Det(AB,BC);
+  double cosBCD= Mc(BC,CD)/(Mc(BC)*Mc(CD)),sinBCD= Det(BC,CD);
+  double cosCDA= Md(CD,DA)/(Md(CD)*Md(DA)),sinCDA= Det(CD,DA);
+  double sinmin=Min(Min(sinDAB,sinABC),Min(sinBCD,sinCDA));
+  // cout << A << B << C << D ;
+  // cout << " sinmin " << sinmin << " " << cosDAB << " " << cosABC << " " << cosBCD << " " << cosCDA << endl;
+  // rattente(1);
+  if (sinmin<=0) return sinmin;
+  return 1.0-Max(Max(Abs(cosDAB),Abs(cosABC)),Max(Abs(cosBCD),Abs(cosCDA)));
+}
+
+ GeometricalEdge *   Triangles::ProjectOnCurve( Edge & BhAB, Vertex &  vA, Vertex & vB,
+						Real8 theta,
+						Vertex & R,VertexOnEdge &  BR,VertexOnGeom & GR) 
+                      
+{
+   void *pA=0,*pB=0;
+   Real8 tA=0,tB=0;
+   R2 A=vA,B=vB;
+    Vertex * pvA=&vA, * pvB=&vB;
+  if (vA.vint == IsVertexOnVertex)
+    {
+      //  cout << " Debut vertex = " << BTh.Number(vA.onbv) ;
+      pA=vA.onbv;
+    }
+  else if (vA.vint == IsVertexOnEdge)
+    {
+      pA=vA.onbe->be;
+      tA=vA.onbe->abcisse;
+      // cout << " Debut edge = " << BTh.Number(vA.onbv) << " " << tA ;
+
+    }
+  else
+    {cerr << "ProjectOnCurve On Vertex " << BTh.Number(vA) << " " << endl;
+     cerr << " forget call to SetVertexFieldOnBTh" << endl;
+     MeshError(-1);
+    } 
+    
+  if (vB.vint == IsVertexOnVertex)
+    {
+      // cout << " Fin vertex = " << BTh.Number(vB.onbv) << endl;
+      pB=vB.onbv;
+    }
+  else if(vB.vint == IsVertexOnEdge)
+    {
+      pB=vB.onbe->be;
+      tB=vB.onbe->abcisse;
+      // cout << " Fin edge = " << BTh.Number(vB.onbe->be) << " " <<  tB ;
+
+    }
+  else
+    {cerr << "ProjectOnCurve On Vertex " << BTh.Number(vB) << " " << endl;
+     cerr << " forget call to SetVertexFieldOnBTh" << endl;
+     MeshError(-1);
+    } 
+  Edge * e = &BhAB;
+ assert( pA && pB && e);
+ // be carefull the back ground edge e is on same geom edge 
+ // of the initiale edge def by the 2 vertex A B;
+ assert(e>=BTh.edges && e<BTh.edges+BTh.nbe);// Is a background Mesh;   
+// walk on BTh edge 
+ //assert(0 /* not finish ProjectOnCurve with BackGround Mesh*/);
+// 1 first find a back ground edge contening the vertex A
+// 2 walk n back gound boundary to find the final vertex B
+
+
+#ifdef DEBUG
+// we suppose if the vertex A is on a background edge and
+// the abcisse is 0 or 1 when the related point is not
+// a end of curve <=>  !IsRequiredVertex
+    if (vA.vint == IsVertexOnEdge)
+      if (tA<=0)
+	assert(! (*vA.onbe->be)[0].on->IsRequiredVertex());
+      else if (tA>=1) 
+      	assert(!(*vA.onbe->be)[1].on->IsRequiredVertex());
+#endif
+
+     if( vA.vint == IsVertexOnEdge) 
+       { // find the start edge 
+	     e = vA.onbe->be;	 
+
+       } 
+     else if (vB.vint == IsVertexOnEdge) 
+       {
+         theta = 1-theta;
+	 Exchange(tA,tB);
+	 Exchange(pA,pB);
+	 Exchange(pvA,pvB);
+	 Exchange(A,B);
+	 e =  vB.onbe->be;
+
+	 // cout << " EXCHANGE  A et B) " << endl;
+       } 
+     else
+       { // do the search by walking 
+	 assert(0 /* A FAIRE */);
+       }
+
+     // find the direction of walking with sens of edge and pA,PB;
+   R2 AB=B-A;
+
+   Real8 cosE01AB = (( (R2) (*e)[1] - (R2) (*e)[0] ) , AB);
+   int kkk=0;
+   int sens = (cosE01AB>0) ? 1 : 0;
+ 
+   //   Real8 l=0; // length of the edge AB
+   Real8 abscisse = -1;
+ 
+   for (int cas=0;cas<2;cas++)
+     {// 2 times algo:
+       //    1 for computing the length l
+       //    2 for find the vertex 
+       int  iii;
+        Vertex  *v0=pvA,*v1; 
+       Edge *neee,*eee;
+       Real8 lg =0; // length of the curve 
+       Real8 te0;
+       // we suppose take the curve's abcisse 
+       // cout << kkk << " e = " << BTh.Number(e) << "  v0=  " 
+       //    << BTh.Number(v0) << " v1 = " << BTh.Number((*e)[sens]) << endl;
+       for ( eee=e,iii=sens,te0=tA;
+             eee && ((( void*) eee) != pB) && (( void*) (v1=&((*eee)[iii]))) != pB ;
+             neee = eee->adj[iii],iii = 1-neee->Intersection(*eee),eee = neee,v0=v1,te0=1-iii )   
+	      { 
+		//	cout << kkk << " eee = " << BTh.Number(eee) << "  v0=  " 
+		//     << BTh.Number(v0) << " v1 = " << BTh.Number(v1) << endl;
+		
+		assert(kkk++<100);
+		assert(eee);
+		Real8 lg0 = lg;
+		Real8 dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
+	     	lg += dp;
+		if (cas && abscisse <= lg)
+		  { // ok we find the geom edge 
+		    Real8 sss  =   (abscisse-lg0)/dp;
+		    Real8 thetab = te0*(1-sss)+ sss*iii;
+		    assert(thetab>=0 && thetab<=1);
+		    BR = VertexOnEdge(&R,eee,thetab);
+
+		    // cout << Number(R) << " = " <<  thetab << " on  " <<  BTh.Number(eee)
+		    //	 << " = " << R << endl;
+
+		    return  Gh.ProjectOnCurve(*eee,thetab,R,GR);
+
+		  }
+	      }
+       // we find the end 
+       if (v1 != pvB) 
+	 {
+	   if (( void*) v1 == pB)
+	      tB = iii;
+	     
+	   Real8 lg0 = lg;
+	   assert(eee);
+	   v1 = pvB;
+	   Real8 dp = LengthInterpole(v0->m,v1->m,(R2) *v1 - (R2) *v0);
+	   lg += dp;	
+	   abscisse = lg*theta;
+	   if (abscisse <= lg && abscisse >= lg0 ) // small optimisation we know the lenght because end
+	     { // ok we find the geom edge 
+	       Real8 sss  =   (abscisse-lg0)/dp;
+	       Real8 thetab = te0*(1-sss)+ sss*tB;
+	       assert(thetab>=0 && thetab<=1);
+	       BR = VertexOnEdge(&R,eee,thetab);
+	      
+	       //	cout << kkk << " eee = " << BTh.Number(eee) << "  v0=  " 
+	       //     << BTh.Number(v0) << " " << te0
+	       //      << " v1 = " << BTh.Number(v1) <<  " " << tB  << endl;
+
+	       //out << Number(R) << " Opt  = " <<  thetab << " on  " <<  BTh.Number(eee) 
+	       //	    << " = " << R << endl;
+
+	       return  Gh.ProjectOnCurve(*eee,thetab,R,GR);
+	     }
+	 }
+       abscisse = lg*theta;
+       
+     }
+   cerr << " Big Bug" << endl;
+   MeshError(678);
+   return 0; // just for the compiler 
+      
+}                  
+
+
+void Triangles::MakeQuadrangles(double costheta)
+{
+  if (verbosity>2) 
+    cout << "  -- MakeQuadrangles costheta = " << costheta << endl;
+  if (verbosity>5)  
+    cout << "    (in)  Nb of Quadrilaterals = " << NbOfQuad 
+	 << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+         << " Nb of outside triangles = " << NbOutT << endl;
+
+  if (costheta >1) {
+    if (verbosity>5)
+      cout << "     do nothing costheta >1 "<< endl;
+    return;}
+
+  
+  Int4 nbqq = (nbt*3)/2;
+  DoubleAndInt4  *qq = new DoubleAndInt4[nbqq];
+
+  Int4 i,ij;
+  int j;
+  Int4 k=0;
+  for (i=0;i<nbt;i++)
+    for (j=0;j<3;j++)
+      if ((qq[k].q=triangles[i].QualityQuad(j))>=costheta)
+ 	   qq[k++].i3j=i*3+j;
+//  sort  qq
+  HeapSort(qq,k);
+  
+  Int4 kk=0;
+  for (ij=0;ij<k;ij++)
+    { 
+      //      cout << qq[ij].q << " " << endl;
+      i=qq[ij].i3j/3;
+      j=(int) (qq[ij].i3j%3);
+      // optisamition no float computation  
+      if (triangles[i].QualityQuad(j,0) >=costheta) 
+        triangles[i].SetHidden(j),kk++;
+    }
+  NbOfQuad = kk;
+  if (verbosity>2) 
+    {
+    cout << "    (out)  Nb of Quadrilaterals = " << NbOfQuad 
+	 << " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+         << " Nb of outside triangles = " << NbOutT << endl;
+    }
+  delete [] qq;
+#ifdef DRAWING2 
+  Draw();
+  inquire();
+#endif
+
+}
+/*
+Triangles::BThBoundary(Edge e,Real 8) const 
+{
+  // pointeur of the background must be on 
+  // 
+  Edge be = e.on;
+}
+*/
+int  Triangles::SplitElement(int choice)
+{
+  Direction NoDirOfSearch;
+  const  int withBackground = &BTh != this && &BTh;
+ if (verbosity>2) 
+   cout << "  -- SplitElement " << (choice? " Q->4Q and T->4T " : " Q->4Q or T->3Q " ) << endl;;
+ if (verbosity>5)
+   cout << endl << "    (in)  Nb of Quadrilaterals = " << NbOfQuad 
+	<< " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+	<< " Nb of outside triangles = " << NbOutT << endl;
+ 
+ ReNumberingTheTriangleBySubDomain();
+#ifdef DRAWING2 
+  Draw();
+ inquire();
+#endif
+ //int nswap =0;
+  const Int4 nfortria( choice ? 4 : 6);
+    if(withBackground) 
+    {
+      BTh.SetVertexFieldOn();
+      SetVertexFieldOnBTh();
+    }
+   else
+     BTh.SetVertexFieldOn();
+   
+  Int4 newnbt=0,newnbv=0;
+  Int4 * kedge = 0;
+ Int4 newNbOfQuad=NbOfQuad;
+  Int4 * ksplit= 0, * ksplitarray=0;
+  Int4 kkk=0;
+  int ret =0;
+  if (nbvx<nbv+nbe) return 1;//   
+  Triangles *  OCurrentTh= CurrentTh;
+  CurrentTh = this;
+  // 1) create  the new points by spliting the internal edges 
+  // set the 
+  Int4 nbvold = nbv;
+  Int4 nbtold = nbt;
+  Int4 NbOutTold  = NbOutT;
+  Int4  NbEdgeOnGeom=0;
+  Int4 i;
+  
+  nbt = nbt - NbOutT; // remove all the  the ouside triangles 
+  Int4 nbtsave = nbt;
+  Triangle * lastT = triangles + nbt;
+  for (i=0;i<nbe;i++)
+    if(edges[i].on) NbEdgeOnGeom++;
+  Int4 newnbe=nbe+nbe;
+  //  Int4 newNbVerticesOnGeomVertex=NbVerticesOnGeomVertex;
+  Int4 newNbVerticesOnGeomEdge=NbVerticesOnGeomEdge+NbEdgeOnGeom;
+  // Int4 newNbVertexOnBThVertex=NbVertexOnBThVertex;
+  Int4 newNbVertexOnBThEdge=withBackground ? NbVertexOnBThEdge+NbEdgeOnGeom:0;
+
+  // do allocation for pointeur to the geometry and background
+  VertexOnGeom * newVerticesOnGeomEdge = new VertexOnGeom[newNbVerticesOnGeomEdge];
+  VertexOnEdge *newVertexOnBThEdge = newNbVertexOnBThEdge ?  new VertexOnEdge[newNbVertexOnBThEdge]:0;
+  if (NbVerticesOnGeomEdge)
+    memcpy(newVerticesOnGeomEdge,VerticesOnGeomEdge,sizeof(VertexOnGeom)*NbVerticesOnGeomEdge);
+  if (NbVertexOnBThEdge)
+    memcpy(newVertexOnBThEdge,VertexOnBThEdge,sizeof(VertexOnEdge)*NbVertexOnBThEdge);
+  Edge *newedges = new Edge [newnbe];
+  //  memcpy(newedges,edges,sizeof(Edge)*nbe);
+  SetOfEdges4 * edge4= new SetOfEdges4(nbe,nbv);
+#ifdef DEBUG
+  for (i=0;i<nbt;i++)
+    triangles[i].check();
+#endif
+#ifdef DRAWING2  
+  reffecran();
+#endif  
+  Int4 k=nbv;
+  Int4 kk=0;
+  Int4 kvb = NbVertexOnBThEdge;
+  Int4 kvg = NbVerticesOnGeomEdge;
+  Int4 ie =0;
+  Edge ** edgesGtoB=0;
+  if (withBackground)
+   edgesGtoB= BTh.MakeGeometricalEdgeToEdge();
+  Int4 ferr=0;
+  for (i=0;i<nbe;i++)
+     newedges[ie].on=0;
+
+  for (i=0;i<nbe;i++)
+    {
+      GeometricalEdge *ong =  edges[i].on;
+
+      newedges[ie]=edges[i];
+      newedges[ie].adj[0]=newedges+(edges[i].adj[0]-edges) ;
+      newedges[ie].adj[1]=newedges + ie +1;
+      R2 A = edges[i][0],B = edges[i][1];
+      // cout << " ie = " << ie <<"  v0 = " <<  Number(newedges[ie][0]) << endl;
+
+
+      kk += (i == edge4->addtrie(Number(edges[i][0]),Number(edges[i][1])));
+      if (ong) // a geometrical edges 
+	{ 
+	  if (withBackground)
+	    {
+	      // walk on back ground mesh 
+	      //  newVertexOnBThEdge[ibe++] = VertexOnEdge(vertices[k],bedge,absicsseonBedge); 
+	      // a faire -- difficile 
+	      // the first PB is to now a background edge between the 2 vertices
+	      assert(edgesGtoB); 
+	      // cout << " ie = " << ie <<"  v0 = " <<  Number(newedges[ie][0]) << endl;
+             ong= ProjectOnCurve(*edgesGtoB[Gh.Number(edges[i].on)],
+			     edges[i][0],edges[i][1],0.5,vertices[k],
+                             newVertexOnBThEdge[kvb],
+                             newVerticesOnGeomEdge[kvg++]);
+	     vertices[k].ReferenceNumber= edges[i].ref;
+	     vertices[k].DirOfSearch =   NoDirOfSearch;        
+;
+	     // get the Info on background mesh 
+	     Real8 s =        newVertexOnBThEdge[kvb];
+	     Vertex &  bv0  = newVertexOnBThEdge[kvb][0];
+	     Vertex &  bv1  = newVertexOnBThEdge[kvb][1];
+	     // compute the metrix of the new points 
+	     vertices[k].m =  Metric(1-s,bv0,s,bv1); 
+	     kvb++;
+	     // cout << " ie = " << ie <<"  v0 = " <<  Number(newedges[ie][0]) << endl;
+	    }
+	  else 
+	    {
+	      ong=Gh.ProjectOnCurve(edges[i],
+				    0.5,vertices[k],newVerticesOnGeomEdge[kvg++]);
+	      // vertices[k].i = toI2( vertices[k].r);
+	      vertices[k].ReferenceNumber = edges[i].ref;
+	      vertices[k].DirOfSearch = NoDirOfSearch;
+	      vertices[k].m =  Metric(0.5,edges[i][0],0.5,edges[i][1]);	      
+	    }  
+	}
+      else // straigth line edge ---
+	{ 
+	  vertices[k].r = ((R2) edges[i][0] + (R2)  edges[i][1] )*0.5;
+	  vertices[k].m =  Metric(0.5,edges[i][0],0.5,edges[i][1]);
+	  vertices[k].on = 0;
+	}
+      //vertices[k].i = toI2( vertices[k].r);
+      R2 AB =  vertices[k].r;
+      R2 AA = (A+AB)*0.5;
+      R2 BB = (AB+B)*0.5;
+      vertices[k].ReferenceNumber = edges[i].ref;
+	    vertices[k].DirOfSearch = NoDirOfSearch;
+	    
+      newedges[ie].on = Gh.Contening(AA,ong);
+      newedges[ie++].v[1]=vertices+k;
+
+      newedges[ie]=edges[i];
+      newedges[ie].adj[0]=newedges + ie -1;
+      newedges[ie].adj[1]=newedges+(edges[i].adj[1]-edges) ;
+      newedges[ie].on =  Gh.Contening(BB,ong);
+      newedges[ie++].v[0]=vertices+k;
+      // cout << " ie = " << ie-2 << " vm " << k << " v0 = " <<  Number(newedges[ie-2][0])
+      //	   << " v1 = " << Number(newedges[ie-1][1])  
+      //	   << " ong =" << ong-Gh.edges 
+      //	   << " on 0 =" <<  newedges[ie-2].on -Gh.edges << AA
+      //	   << " on 1 =" <<  newedges[ie-1].on -Gh.edges << BB 
+      //	   << endl;
+      k++;
+    }
+#ifdef DEBUG
+  assert(kvb ==  newNbVertexOnBThEdge);
+  // verif edge 
+  { Vertex *v0 = vertices, *v1 = vertices+ k;
+    for (Int4  i=0;i<ie;i++)
+     {
+       assert( &newedges[i][0] >= v0 &&  &newedges[i][0] < v1);
+       assert( &newedges[i][1] >= v0 &&  &newedges[i][1] < v1);
+     }
+  }
+#endif
+  if (edgesGtoB) delete [] edgesGtoB;
+  edgesGtoB=0;
+
+  newnbv=k;
+  newNbVerticesOnGeomEdge=kvg;
+  if (newnbv> nbvx) goto Error;// bug 
+    
+  nbv = k;
+
+
+  kedge = new Int4[3*nbt+1];
+  ksplitarray = new Int4[nbt+1];
+  ksplit = ksplitarray +1; // because ksplit[-1] == ksplitarray[0]
+ 
+  for (i=0;i<3*nbt;i++)
+    kedge[i]=-1;
+
+  //  
+
+ for (i=0;i<nbt;i++)
+   {  
+
+     Triangle & t = triangles[i];
+     assert(t.link);
+     for(int j=0;j<3;j++)
+       {
+	 const TriangleAdjacent ta = t.Adj(j);
+	 const Triangle & tt = ta;
+	 if (&tt >= lastT)
+	   t.SetAdj2(j,0,0);// unset adj
+	 const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]];
+	 const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]];
+	 Int4  ke =edge4->findtrie(Number(v0),Number(v1));
+	 if (ke>0) 
+	   {
+	     Int4 ii = Number(tt);
+	     int  jj = ta;
+	     Int4 ks = ke + nbvold;
+	     kedge[3*i+j] = ks;
+	     if (ii<nbt) // good triangle
+	       kedge[3*ii+jj] = ks;
+	     Vertex &A=vertices[ks];
+	     Real8 aa,bb,cc,dd;
+	     if ((dd=Area2(v0.r,v1.r,A.r)) >=0)
+	       { // warning PB roundoff error 
+		 if (t.link && ( (aa=Area2( A.r    , t[1].r , t[2].r )) < 0.0 
+				||   (bb=Area2( t[0].r , A.r    , t[2].r )) < 0.0  
+				||   (cc=Area2( t[0].r , t[1].r , A.r    )) < 0.0))
+		   ferr++, cerr << " Error : " <<  ke + nbvold << " not in triangle " 
+				<< i << " In=" << !!t.link
+				<< " " <<  aa  << " " << bb << " " << cc << " " << dd << endl;
+		 
+	       }
+	     
+	     else
+	       {
+		 if (tt.link && ( (aa=Area2( A.r     , tt[1].r , tt[2].r )) < 0 
+				 ||   (bb=Area2( tt[0].r , A.r     , tt[2].r )) < 0 
+				 ||   (cc=Area2( tt[0].r , tt[1].r , A.r     )) < 0)) 
+		   ferr++, cerr << " Warning : " <<  ke + nbvold << " not in triangle " << ii 
+				<< " In=" << !!tt.link 
+				<< " " <<  aa  << " " << bb << " " << cc << " " << dd << endl;
+				
+	       } 
+	     
+	   }
+       }
+   }
+  if(ferr)
+    {
+      cerr << " Number of triangles with P2 interpolation Probleme " << ferr << endl;;
+      MeshError(9);
+    }
+
+  for (i=0;i<nbt;i++)
+    {
+      ksplit[i]=1; // no split by default
+      const Triangle & t = triangles[ i];
+      // cout << " Triangle " << i << " " << t  << !!t.link << ":: " ;
+      int nbsplitedge =0;
+      int nbinvisible =0;
+      int invisibleedge=0;
+      int kkk[3];      
+      for (int j=0;j<3;j++)
+	{
+	  if (t.Hidden(j)) invisibleedge=j,nbinvisible++;
+	  
+	  const TriangleAdjacent ta = t.Adj(j);
+	  const Triangle & tt = ta;
+
+	  
+	  const Vertex & v0 = t[VerticesOfTriangularEdge[j][0]];
+	  const Vertex & v1 = t[VerticesOfTriangularEdge[j][1]];
+	 //  cout << " ke = " << kedge[3*i+j]  << " " << Number(v0) << " " << Number(v1) << "/ ";
+	  if ( kedge[3*i+j] < 0) 
+	    {
+	      Int4  ke =edge4->findtrie(Number(v0),Number(v1));
+	      //  cout << ":" << ke << "," << !!t.link << " " <<  &tt ;
+	      if (ke<0) // new 
+		{
+		  if (&tt) // internal triangles all the boundary 
+		      { // new internal edges 
+			Int4 ii = Number(tt);
+			int  jj = ta;
+	      
+			kedge[3*i+j]=k;// save the vertex number 
+			kedge[3*ii+jj]=k;
+			if (k<nbvx) 
+			  {
+			    vertices[k].r = ((R2) v0+(R2) v1 )/2;
+			    //vertices[k].i = toI2( vertices[k].r);
+			    vertices[k].ReferenceNumber=0;
+	        vertices[k].DirOfSearch =NoDirOfSearch;
+			    vertices[k].m =  Metric(0.5,v0,0.5,v1);
+			  }
+			k++;
+			kkk[nbsplitedge++]=j;		      
+		    } // tt 
+		  else
+		    cerr <<endl <<  " Bug " <<i<< " " << j << " t=" << t << endl;
+		  
+		} // ke<0	       
+	      else
+		{ // ke >=0
+		  kedge[3*i+j]=nbvold+ke;
+		  kkk[nbsplitedge++]=j;// previously splited
+		}
+	    }
+	  else 
+	    kkk[nbsplitedge++]=j;// previously splited
+	  
+	} 
+      assert (nbinvisible<2);
+     // cout << " " <<  nbinvisible << " " <<  nbsplitedge << endl;
+      switch (nbsplitedge) {
+      case 0: ksplit[i]=10; newnbt++; break;   // nosplit
+      case 1: ksplit[i]=20+kkk[0];newnbt += 2; break; // split in 2 
+      case 2: ksplit[i]=30+3-kkk[0]-kkk[1];newnbt += 3; break; // split in 3 
+      case 3:
+	if (nbinvisible) ksplit[i]=40+invisibleedge,newnbt += 4;
+	else   ksplit[i]=10*nfortria,newnbt+=nfortria;
+	break;
+      } 
+    assert(ksplit[i]>=40);
+    }
+  //  now do the element split
+  newNbOfQuad = 4*NbOfQuad;
+  nbv = k;
+#ifdef DRAWING2  
+  inquire();
+#endif  
+//  cout << " Nbv = " << nbv << endl;
+  kkk = nbt;
+  ksplit[-1] = nbt;
+  // look on  old true  triangles 
+
+  for (i=0;i<nbtsave;i++)
+    {
+      //     cout << "Triangle " << i << " " << ksplit[i] << ":" << triangles[i]
+      //	   << "  ----------------------------------------------- " <<endl;
+      // Triangle * tc=0;
+      int  nbmkadj=0;
+      Int4 mkadj [100];
+      mkadj[0]=i;
+      Int4 kk=ksplit[i]/10;
+      int  ke=(int) (ksplit[i]%10);
+      assert(kk<7 && kk >0);
+      
+      // def the numbering   k (edge) i vertex 
+      int k0 = ke;
+      int k1 = NextEdge[k0];
+      int k2 = PreviousEdge[k0];
+      int i0 = OppositeVertex[k0];
+      int i1 = OppositeVertex[k1];
+      int i2 = OppositeVertex[k2];
+       
+       Triangle &t0=triangles[i];
+       Vertex * v0=t0(i0);           
+       Vertex * v1=t0(i1);           
+       Vertex * v2=t0(i2);
+
+       // cout << "nbmkadj " << nbmkadj << " it=" << i <<endl;
+       assert(nbmkadj< 10);
+       // --------------------------
+       TriangleAdjacent ta0(t0.Adj(i0)),ta1(t0.Adj(i1)),ta2(t0.Adj(i2));
+       // save the flag Hidden
+       int hid[]={t0.Hidden(0),t0.Hidden(1),t0.Hidden(2)};
+       // un set all adj -- save Hidden flag --
+       t0.SetAdj2(0,0,hid[0]);
+       t0.SetAdj2(1,0,hid[1]);
+       t0.SetAdj2(2,0,hid[2]);
+       // --  remake 
+       switch  (kk) {
+       case 1: break;// nothing 
+       case 2: // 
+	 {
+	   Triangle &t1=triangles[kkk++];
+	   t1=t0;
+	   assert (kedge[3*i+i0]>=0);
+	   Vertex * v3 = vertices + kedge[3*i+k0];
+	   
+	   t0(i2) = v3;
+	   t1(i1) = v3;
+	   t0.SetAllFlag(k2,0);
+	   t1.SetAllFlag(k1,0);
+	 } 
+	 break; 
+       case 3: //
+	 {
+	   Triangle &t1=triangles[kkk++];
+            Triangle &t2=triangles[kkk++];
+            t2=t1=t0;
+            assert (kedge[3*i+k1]>=0);
+            assert (kedge[3*i+k2]>=0);
+            
+            Vertex * v01 = vertices + kedge[3*i+k2];
+            Vertex * v02 = vertices + kedge[3*i+k1]; 
+            t0(i1) = v01; 
+            t0(i2) = v02; 
+            t1(i2) = v02;
+            t1(i0) = v01; 
+            t2(i0) = v02; 
+	    t0.SetAllFlag(k0,0);
+	    t1.SetAllFlag(k1,0);
+	    t1.SetAllFlag(k0,0);
+	    t2.SetAllFlag(k2,0);
+	 } 
+	 break;
+       case 4: // 
+       case 6: // split in 4 
+	 {
+	   Triangle &t1=triangles[kkk++];
+	   Triangle &t2=triangles[kkk++];
+	   Triangle &t3=triangles[kkk++];
+	   t3=t2=t1=t0;
+	   assert(kedge[3*i+k0] >=0 && kedge[3*i+k1] >=0 && kedge[3*i+k2] >=0);
+	   Vertex * v12 = vertices + kedge[3*i+k0];
+	   Vertex * v02 = vertices + kedge[3*i+k1]; 
+	   Vertex * v01 = vertices + kedge[3*i+k2];
+	   // cout << Number(t0(i0))  << " " << Number(t0(i1)) 
+	   //     << " " <<  Number(t0(i2)) 
+	   //     << " " <<  kedge[3*i+k0] 
+	   //     << " " <<  kedge[3*i+k1] 
+	   //     << " " <<  kedge[3*i+k2] << endl;
+	   t0(i1) = v01;
+	   t0(i2) = v02;
+	   t0.SetAllFlag(k0,hid[k0]);
+
+	   t1(i0) = v01;
+	   t1(i2) = v12;
+	   t0.SetAllFlag(k1,hid[k1]);
+	   
+	   t2(i0) = v02;
+	   t2(i1) = v12;
+	   t2.SetAllFlag(k2,hid[k2]);
+	   
+	   t3(i0) = v12;
+	   t3(i1) = v02;
+	   t3(i2) = v01;
+	   	   
+	   t3.SetAllFlag(0,hid[0]);	   
+	   t3.SetAllFlag(1,hid[1]);	   
+	   t3.SetAllFlag(2,hid[2]);
+
+	   if ( kk == 6)
+	     {
+	       
+	       Triangle &t4=triangles[kkk++];
+	       Triangle &t5=triangles[kkk++];
+	       
+	       t4 = t3;
+	       t5 = t3;
+
+	       t0.SetHidden(k0);
+	       t1.SetHidden(k1);
+	       t2.SetHidden(k2);
+	       t3.SetHidden(0);
+	       t4.SetHidden(1);
+	       t5.SetHidden(2);
+	       
+		if (nbv < nbvx ) 
+		  {
+		    vertices[nbv].r = ((R2) *v01 + (R2) *v12  + (R2) *v02 ) / 3.0;
+		    vertices[nbv].ReferenceNumber =0;
+	      vertices[nbv].DirOfSearch =NoDirOfSearch;
+		    //vertices[nbv].i = toI2(vertices[nbv].r);
+		    Real8 a3[]={1./3.,1./3.,1./3.};
+		    vertices[nbv].m = Metric(a3,v0->m,v1->m,v2->m);
+		    Vertex * vc =  vertices +nbv++;
+		    t3(i0) = vc;
+		    t4(i1) = vc;
+		    t5(i2) = vc;
+
+		  }
+		else
+		  goto Error; 
+	     }
+		    
+	 } 
+	 break;         
+       }
+ 
+       // cout << "  -- " << i << " " << nbmkadj << " " << kkk << " " << tc << endl;
+       //  t0.SetDetf();
+       // save all the new triangles
+       mkadj[nbmkadj++]=i;
+       Int4 jj;
+       if (t0.link) 
+	 for (jj=nbt;jj<kkk;jj++)
+	   {
+	     triangles[jj].link=t0.link;
+	     t0.link= triangles+jj;
+	     mkadj[nbmkadj++]=jj;
+	     // triangles[jj].SetDet();
+	   }
+       // cout << "  -- " << i << " " << nbmkadj << endl;
+       assert(nbmkadj<=13);// 13 = 6 + 4 + 3
+  
+       if (kk==6)  newNbOfQuad+=3;
+	 //	 triangles[i].Draw();       
+
+       for (jj=ksplit[i-1];jj<kkk;jj++)
+	 // triangles[jj].SetDet();
+       //	   triangles[jj].Draw();
+	 
+
+
+       nbt = kkk;
+       ksplit[i]= nbt; // save last adresse of the new triangles
+       kkk = nbt;
+       
+    }
+
+//  cout << " nv = " << nbv << " nbt = " << nbt << endl;
+  for (i=0;i<nbv;i++)
+    vertices[i].m = vertices[i].m*2.;
+  //
+  if(withBackground)
+    for (i=0;i<BTh.nbv;i++)
+      BTh.vertices[i].m =  BTh.vertices[i].m*2.;
+#ifdef DRAWING2
+  Draw();
+  inquire();
+#endif
+  
+  
+  ret = 2;
+  if (nbt>= nbtx) goto Error; // bug 
+  if (nbv>= nbvx) goto Error; // bug 
+  // generation of the new triangles 
+
+  SetIntCoor("In SplitElement"); 
+
+  ReMakeTriangleContainingTheVertex();
+  if(withBackground)
+    BTh.ReMakeTriangleContainingTheVertex();
+
+  delete [] edges;
+  edges = newedges;
+  nbe = newnbe;
+  NbOfQuad = newNbOfQuad;
+
+  for (i=0;i<NbSubDomains;i++)
+    { 
+      Int4 k = subdomains[i].edge- edges;
+      subdomains[i].edge =  edges+2*k; // spilt all edge in 2 
+    }
+    
+  if (ksplitarray) delete [] ksplitarray;
+  if (kedge) delete [] kedge;
+  if (edge4) delete edge4;
+  if (VerticesOnGeomEdge) delete [] VerticesOnGeomEdge;
+  VerticesOnGeomEdge= newVerticesOnGeomEdge;
+  if(VertexOnBThEdge) delete []  VertexOnBThEdge;
+  VertexOnBThEdge = newVertexOnBThEdge;
+  NbVerticesOnGeomEdge = newNbVerticesOnGeomEdge;
+  NbVertexOnBThEdge=newNbVertexOnBThEdge;
+  //  ReMakeTriangleContainingTheVertex();
+
+  FillHoleInMesh();
+
+#ifdef DEBUG
+  for (i=0;i<nbt;i++)
+    triangles[i].check();
+#endif
+  
+ if (verbosity>2)
+   cout << "    (out) Nb of Quadrilaterals = " << NbOfQuad 
+	<< " Nb Of Triangles = " << nbt-NbOutT- NbOfQuad*2 
+	<< " Nb of outside triangles = " << NbOutT << endl;
+
+ CurrentTh=OCurrentTh;
+ return 0; //ok
+
+ Error:
+  nbv = nbvold;
+  nbt = nbtold;
+  NbOutT = NbOutTold;
+  // cleaning memory ---
+  delete newedges;
+  if (ksplitarray) delete [] ksplitarray;
+  if (kedge) delete [] kedge;
+  if (newVerticesOnGeomEdge) delete [] newVerticesOnGeomEdge;
+  if (edge4) delete edge4;
+  if(newVertexOnBThEdge) delete []  newVertexOnBThEdge;
+  
+
+  CurrentTh= OCurrentTh;
+  return ret; // ok 
+}
+
+} //  end of namespcae bamg 
diff --git a/src/bamglib/MeshRead.cpp b/src/bamglib/MeshRead.cpp
new file mode 100644
index 0000000..cd790a0
--- /dev/null
+++ b/src/bamglib/MeshRead.cpp
@@ -0,0 +1,1227 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+#ifdef __MWERKS__
+#pragma optimization_level 2
+//#pragma inline_depth 1
+#endif
+
+#ifdef DRAWING1
+  extern bool withrgraphique ;
+#endif
+
+namespace bamg {
+
+static const  Direction NoDirOfSearch=Direction();
+
+void Triangles::Read(MeshIstream & f_in,int Version,Real8 cutoffradian)
+{
+  Real8 hmin = HUGE_VAL;// the infinie value 
+  //  Real8 MaximalAngleOfCorner = 10*Pi/180;// 
+  Int4 i;
+  Int4 dim=0;
+  Int4 hvertices =0;
+  Int4 ifgeom=0;
+  Metric M1(1);
+  if (verbosity>1)
+    cout << "  -- ReadMesh " << f_in.CurrentFile  << " Version = " << Version << endl;
+  int field=0;
+  int showfield=0;
+  while (f_in.cm()) 
+    {  
+      field=0;
+      char  fieldname[256];
+      if(f_in.eof()) break;
+      f_in.cm() >> fieldname ;;
+      if(f_in.eof()) break;
+      f_in.err() ;
+      if(verbosity>9)
+	cout <<  "    " << fieldname << endl;
+      if (!strcmp(fieldname,"MeshVersionFormatted") )
+         f_in >>   Version ;
+      else if(!strcmp(fieldname,"End"))
+         break;
+      else if (!strcmp(fieldname,"Dimension"))
+         {
+           f_in >>   dim ;
+           assert(dim ==2);
+         }
+      else if  (!strcmp(fieldname,"Geometry"))
+	{ 
+	  char * fgeom ;
+	  f_in >> fgeom;
+	  //	  if (cutoffradian>=0) => bug if change edit the file geometry 
+	  //  Gh.MaximalAngleOfCorner = cutoffradian;
+	  if (strlen(fgeom))
+	      Gh.ReadGeometry(fgeom);
+	  else 
+	    { 
+	      // include geometry 
+	      f_in.cm();
+	      Gh.ReadGeometry(f_in,fgeom);
+	    }
+
+	  Gh.AfterRead();
+	  ifgeom=1;
+	  delete [] fgeom;
+	}
+      else if (!strcmp(fieldname,"Identifier"))
+	{
+	  if (identity) delete [] identity;
+	  f_in >> identity;
+	}
+      else if (!strcmp(fieldname,"hVertices"))
+         { hvertices =1;
+	   Real4 h;
+           for (i=0;i< nbv;i++) {
+            f_in >>  h ;
+	    vertices[i].m = Metric(h);}
+         }
+      else if (!strcmp(fieldname,"Vertices"))
+         { 
+           assert(dim ==2);
+           f_in >>   nbv ;
+	   if(verbosity>3)
+	     cout << "   Nb of Vertices = " << nbv << endl;
+	   nbvx=nbv;
+	   vertices=new Vertex[nbvx];
+	   assert(vertices);
+	   ordre=new Vertex* [nbvx];
+	   assert(ordre);
+	   
+	   nbiv = nbv;
+           for (i=0;i<nbv;i++) {
+             f_in >> 
+	       	 	 vertices[i].r.x >>  
+	           vertices[i].r.y >> 
+             vertices[i].ReferenceNumber  ;
+             vertices[i].DirOfSearch =NoDirOfSearch;
+	           vertices[i].m=M1;
+	     vertices[i].color =0;}
+	   nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+	   triangles =new Triangle[nbtx];
+	   assert(triangles);
+	   nbt =0;
+         }
+      else if (!strcmp(fieldname,"Triangles"))
+	{ 
+	  if (dim !=2)
+	    cerr << "ReadMesh: Dimension <> 2" <<endl , f_in.ShowIoErr(0);
+	  if(! vertices || !triangles  || !nbv )
+	    cerr << "ReadMesh:Triangles before Vertices" <<endl,
+	      f_in.ShowIoErr(0);
+	  int NbOfTria;
+	  f_in >>  NbOfTria ;
+	  if(verbosity>3)
+	    cout << "   NbOfTria = " << NbOfTria << endl;
+	  if (nbt+NbOfTria >= nbtx)
+	    cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria  = "
+		 << nbt + NbOfTria<<"  < 2*nbv-2 ="  << nbtx << endl,
+	      f_in.ShowIoErr(0); 
+	  //	  begintria = nbt;
+	  for (i=0;i<NbOfTria;i++)  
+	    {
+	      Int4 i1,i2,i3,iref;
+	      Triangle & t = triangles[nbt++];
+	      f_in >>  i1 >>  i2 >>   i3 >>   iref ;
+	      t = Triangle(this,i1-1,i2-1,i3-1);
+	      t.color=iref;
+	    }
+	  // endtria=nbt;
+	}
+      else if (!strcmp(fieldname,"Quadrilaterals"))
+        { 
+
+	  if (dim !=2)
+	    cerr << "ReadMesh: Dimension <> 2" <<endl , f_in.ShowIoErr(0);
+	  if(! vertices || !triangles  || !nbv )
+	    cerr << "ReadMesh:Quadrilaterals before Vertices" <<endl,
+	      f_in.ShowIoErr(0);
+	  f_in >>   NbOfQuad ;
+	  if(verbosity>3)
+	    cout << "   NbOfQuad= " << NbOfQuad << endl;
+	  if (nbt+2*NbOfQuad >= nbtx)
+	    cerr << "ReadMesh: We must have 2*NbOfQuad + NbOfTria  = "
+		 << nbt + 2*NbOfQuad <<"  < 2*nbv-2 ="  << nbtx << endl,
+	      f_in.ShowIoErr(0);
+	  //  beginquad=nbt;
+	  for (i=0;i<NbOfQuad;i++)  
+	    { 
+	      Int4 i1,i2,i3,i4,iref;
+	      Triangle & t1 = triangles[nbt++];
+	      Triangle & t2 = triangles[nbt++];
+	      f_in >>  i1 >>  i2 >>   i3 >> i4 >>    iref ;
+	      t1 = Triangle(this,i1-1,i2-1,i3-1);
+	      t1.color=iref;
+	      t2 = Triangle(this,i3-1,i4-1,i1-1);
+	      t2.color=iref;
+	      t1.SetHidden(OppositeEdge[1]); // two time  because the adj was not created 
+	      t2.SetHidden(OppositeEdge[1]); 
+	    }
+	  // endquad=nbt;
+	}
+      else if (!strcmp(fieldname,"VertexOnGeometricVertex"))
+	{ 
+           f_in  >> NbVerticesOnGeomVertex ;
+ 	   if(verbosity>5)
+	     cout << "   NbVerticesOnGeomVertex = "   << NbVerticesOnGeomVertex << endl
+		  << " Gh.vertices " << Gh.vertices << endl;
+	   if( NbVerticesOnGeomVertex) 
+	     {
+	       VerticesOnGeomVertex= new  VertexOnGeom[NbVerticesOnGeomVertex] ;
+	       if(verbosity>7)
+		 cout << "   VerticesOnGeomVertex = " << VerticesOnGeomVertex << endl
+		      << "   Gh.vertices " << Gh.vertices << endl;
+	       assert(VerticesOnGeomVertex);
+	       for (Int4 i0=0;i0<NbVerticesOnGeomVertex;i0++)  
+		 { 
+		   Int4  i1,i2;
+		   //VertexOnGeom & v =VerticesOnGeomVertex[i0];
+		   f_in >>  i1 >> i2 ;
+		   VerticesOnGeomVertex[i0]=VertexOnGeom(vertices[i1-1],Gh.vertices[i2-1]);
+		 }
+	     }
+	 }
+      else if (!strcmp(fieldname,"VertexOnGeometricEdge"))
+         { 
+           f_in >>  NbVerticesOnGeomEdge ;
+ 	   if(verbosity>3)
+	     cout << "   NbVerticesOnGeomEdge = " << NbVerticesOnGeomEdge << endl;
+	   if(NbVerticesOnGeomEdge) 
+	     {
+	       VerticesOnGeomEdge= new  VertexOnGeom[NbVerticesOnGeomEdge] ;
+	       assert(VerticesOnGeomEdge);
+	       for (Int4 i0=0;i0<NbVerticesOnGeomEdge;i0++)  
+		 { 
+		   Int4  i1,i2;
+		   Real8 s;
+		   //VertexOnGeom & v =VerticesOnGeomVertex[i0];
+		   f_in >>  i1 >> i2  >> s;
+		   VerticesOnGeomEdge[i0]=VertexOnGeom(vertices[i1-1],Gh.edges[i2-1],s);
+		 }
+	     }
+         }
+      else if (!strcmp(fieldname,"Edges"))
+	{ 
+          Int4 i,j, i1,i2;
+          f_in >>  nbe ;
+          edges = new Edge[nbe];
+	  if(verbosity>5)
+	    cout << "     Record Edges: Nb of Edge " << nbe << " edges " <<  edges << endl;
+          assert(edges);
+	  Real4 *len =0;
+          if (!hvertices) 
+	    {
+	      len = new Real4[nbv];
+	      for(i=0;i<nbv;i++)
+		len[i]=0;
+	    }
+          for (i=0;i<nbe;i++) 
+	    {
+	      f_in  >> i1  >> i2  >> edges[i].ref ;
+                 
+	      assert(i1 >0 && i2 >0);
+	      assert(i1 <= nbv && i2 <= nbv);
+	      i1--;
+	      i2--;
+	      edges[i].v[0]= vertices +i1;
+	      edges[i].v[1]= vertices +i2;
+	      edges[i].adj[0]=0;
+	      edges[i].adj[1]=0;
+
+	      R2 x12 = vertices[i2].r-vertices[i1].r;
+	      Real8 l12=sqrt( (x12,x12));        
+	      if (!hvertices) {
+		vertices[i1].color++;
+		vertices[i2].color++;
+		len[i1]+= l12;
+		len[i2] += l12;}
+	      hmin = Min(hmin,l12);
+	    }
+	  // definition  the default of the given mesh size 
+          if (!hvertices) 
+	    {
+            for (i=0;i<nbv;i++) 
+	      if (vertices[i].color > 0) 
+		vertices[i].m=  Metric(len[i] /(Real4) vertices[i].color);
+	      else 
+		vertices[i].m=  Metric(hmin);
+	      delete [] len;
+	    }
+	  if(verbosity>5)
+	    cout << "     hmin " << hmin << endl;
+	  // construction of edges[].adj 
+	    for (i=0;i<nbv;i++) 
+	      vertices[i].color = (vertices[i].color ==2) ? -1 : -2;
+	    for (i=0;i<nbe;i++)
+	      for (j=0;j<2;j++) 
+		{ 
+		  Vertex *v=edges[i].v[j];
+		  Int4 i0=v->color,j0;
+		  if(i0==-1)
+		    v->color=i*2+j;
+		  else if (i0>=0) {// i and i0 edge are adjacent by the vertex v
+		    j0 =  i0%2;
+		    i0 =  i0/2;
+		    assert( v ==  edges[i0 ].v[j0]);
+		    edges[i ].adj[ j ] =edges +i0;
+		    edges[i0].adj[ j0] =edges +i ;
+		    assert(edges[i0].v[j0] == v);
+		    //	    if(verbosity>8)
+		    //  cout << " edges adj " << i0 << " "<< j0 << " <-->  "  << i << " " << j << endl;
+		      v->color = -3;}
+		}
+
+	}
+	
+/*   ne peut pas marche car il n'y a pas de flag dans les aretes du maillages
+       else if (!strcmp(fieldname,"RequiredEdges"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbe );
+            assert( j > 0 );
+            j--;
+            edges[j].SetRequired();  }
+      }
+*/	
+      else if (!strcmp(fieldname,"EdgeOnGeometricEdge"))
+	{ 
+	  assert(edges);
+	  int i1,i2,i,j;
+	  f_in >> i2 ;
+	  if(verbosity>3)
+	    cout << "     Record EdgeOnGeometricEdge: Nb " << i2 <<endl;
+	  for (i1=0;i1<i2;i1++)
+	    {
+	      f_in  >> i >> j ;
+	      if(!(i>0 && j >0 && i <= nbe && j <= Gh.nbe))
+		{
+		  cerr << "      Record EdgeOnGeometricEdge i=" << i << " j = " << j;
+		  cerr << " nbe = " << nbe << " Gh.nbe = " <<  Gh.nbe << endl;
+		  cerr << " We must have : (i>0 && j >0 && i <= nbe && j <= Gh.nbe) ";
+		  cerr << " Fatal error in file " << name << " line " << f_in.LineNumber << endl;
+		  MeshError(1);
+		}
+		
+		
+	      edges[i-1].on = Gh.edges + j-1;
+	    }
+	  //	  cout << "end EdgeOnGeometricEdge" << endl;
+	}
+      else if (!strcmp(fieldname,"SubDomain") || !strcmp(fieldname,"SubDomainFromMesh") )
+	{ 
+	  
+	  f_in >> NbSubDomains ;
+	  subdomains = new SubDomain [ NbSubDomains ];
+	    for (i=0;i< NbSubDomains;i++)
+	      { Int4 i3,head,sens;
+	      f_in  >>  i3 >>	head >> sens  >> subdomains[i].ref ;
+		assert (i3==3);
+		head --;
+		assert(head < nbt && head >=0);
+		subdomains[i].head = triangles+head;		
+	      }
+	}
+      else
+	{ // unkown field
+	  field = ++showfield;
+	  if(showfield==1) // just to show one time 
+	    if (verbosity>5)
+	      cout << "     Warning we skip the field " << fieldname << " at line " << f_in.LineNumber << endl;
+	}
+      showfield=field; // just to show one time 
+    }
+    
+    if (ifgeom==0)
+      {
+	if (verbosity)
+	  cout  << " ## Warning: Mesh without geometry we construct a geometry (theta =" 
+		<< cutoffradian*180/Pi << " degres )" << endl;
+	ConsGeometry(cutoffradian);	
+	Gh.AfterRead();
+      }	  
+}
+
+
+
+
+void Triangles::Read_am_fmt(MeshIstream & f_in)
+{
+  Metric M1(1);
+
+  if (verbosity>1)
+    cout << "  -- ReadMesh .am_fmt file " <<  f_in.CurrentFile  << endl;
+   	
+     Int4 i;
+     f_in.cm() >> nbv >> nbt ;
+     if (verbosity>3)
+       cout << "    nbv = " << nbv  << " nbt = " << nbt << endl;
+     f_in.eol() ;// 
+     nbvx = nbv;
+     nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+     triangles =new Triangle[nbtx];
+     assert(triangles);
+     vertices=new Vertex[nbvx];
+     ordre=new Vertex* [nbvx];
+     
+     for (     i=0;i<nbt;i++)
+       {
+	 Int4 i1,i2,i3;
+	 f_in >>  i1 >>  i2 >>   i3 ;
+	 triangles[i]  = Triangle(this,i1-1,i2-1,i3-1);	 
+       }
+      f_in.eol() ;// 
+      
+      for ( i=0;i<nbv;i++)
+	f_in >> vertices[i].r.x >>   vertices[i].r.y,
+	  vertices[i].m = M1,vertices[i].DirOfSearch =NoDirOfSearch;
+
+      f_in.eol() ;// 
+      
+      for ( i=0;i<nbt;i++)  
+	f_in >> triangles[i].color;
+      f_in.eol() ;// 
+      
+      for ( i=0;i<nbv;i++)  
+	     f_in >> vertices[i].ReferenceNumber;
+      
+      
+}
+
+////////////////////////
+
+void  Triangles::Read_am(MeshIstream &ff)
+{
+  if (verbosity>1)
+    cout << "  -- ReadMesh .am_fmt file " <<  ff.CurrentFile  << endl;
+    Metric M1(1);	
+  
+  IFortranUnFormattedFile f_in(ff);
+
+  Int4  l=f_in.Record();
+  assert(l==2*sizeof(Int4));
+  f_in >> nbv >> nbt ;
+  l=f_in.Record();
+  assert((size_t) l==nbt*sizeof(long)*4 + nbv*(2*sizeof(float)+sizeof(long)));
+  if (verbosity>3)
+    cout << "    nbv = " << nbv  << " nbt = " << nbt << endl;
+  
+  nbvx = nbv;
+  nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+  triangles =new Triangle[nbtx];
+  assert(triangles);
+  vertices=new Vertex[nbvx];
+  ordre=new Vertex* [nbvx];
+  
+
+  Int4 i;
+  for (     i=0;i<nbt;i++) {
+    long i1,i2,i3;
+    f_in >>  i1 >>  i2 >>   i3 ;
+    triangles[i]  = Triangle(this,i1-1,i2-1,i3-1); }
+  
+  for ( i=0;i<nbv;i++) {
+    float x,y;
+    f_in >> x >> y;
+    vertices[i].r.x =x;
+    vertices[i].r.y=y;
+    vertices[i].m=M1;}
+  
+  for ( i=0;i<nbt;i++) {
+    long i;
+    f_in >> i;
+    triangles[i].color=i;}
+  
+  for ( i=0;i<nbv;i++) {
+    long i;
+    f_in >> i;
+    vertices[i].ReferenceNumber=i;}
+}
+
+//////////////////////////////////
+
+void  Triangles::Read_nopo(MeshIstream & ff)
+{
+
+ if (verbosity>1)
+    cout << "  -- ReadMesh .nopo file " <<  ff.CurrentFile  << endl;
+ IFortranUnFormattedFile f_in(ff);
+ 
+ 
+ Int4  l,i,j;
+ l=f_in.Record(); 
+ l=f_in.Record();
+ f_in >> i;
+ assert(i==32);
+ Int4 niveau,netat,ntacm;
+
+ char titre[80+1],  date[2*4+1], nomcre[6*4+1], typesd[5];
+ f_in.read4(titre,20);
+ f_in.read4(date,2);
+ f_in.read4(nomcre,6);
+ f_in.read4(typesd,1);
+
+
+   f_in >> niveau>>netat>>ntacm;
+ if (strcmp("NOPO",typesd))
+   {
+     cout << " where in record  " << f_in.where() << " " << strcmp("NOPO",typesd) << endl;
+     cerr << " not a  nopo file but `" << typesd <<"`"<< " len = " << strlen(typesd) << endl;
+     cerr << (int) typesd[0] << (int) typesd[1] << (int) typesd[2] << (int) typesd[3] << (int) typesd[4] << endl;
+     cout << " nomcre :" << nomcre << endl;
+     cout << " date   :" << date << endl;
+     cout << " titre  :" << titre<< endl;
+     MeshError(112);
+   }
+ if(verbosity>2)
+   cout << "    nb de tableau associe : " << ntacm << " niveau =" << niveau << endl;
+ 
+ for (i=0;i<ntacm;i++)
+   f_in.Record();
+
+ f_in.Record();
+ f_in >> l;
+ assert(l == 27);
+ Int4 nop2[27];
+ for (i=0;i<27;i++)
+   f_in >> nop2[i];
+ Int4 ndim = nop2[0];
+ Int4 ncopnp = nop2[3];
+ Int4 ne = nop2[4];
+ Int4 ntria = nop2[7];
+ Int4 nquad = nop2[8];
+ Int4 np = nop2[21];
+ // Int4 nef = nop2[13];
+ Metric M1(1);
+ if(verbosity>2) 
+   cout << "    ndim = " << ndim << " ncopnp= " << ncopnp << " ne = " << ne 
+	<< "    ntri = " << ntria << " nquad = " << nquad << " np = " << np << endl;
+ nbv = np;
+ nbt = 2*nquad + ntria;
+ if (ne != nquad+ntria || ndim !=2 || ncopnp != 1 )
+   {
+     cerr << " not only tria & quad in nopo mesh on dim != 2 ou ncopnp != 1 " << endl;
+     MeshError(113);
+   }
+ if( nop2[24]>=0)  f_in.Record();
+  NbOfQuad = nquad;
+  nbvx = nbv;
+  nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+  triangles =new Triangle[nbtx];
+  assert(triangles);
+  vertices=new Vertex[nbvx];
+  ordre=new Vertex* [nbvx];
+
+
+ f_in >> l;
+
+  if(verbosity>9)
+    cout << " Read cnop4 nb of float  " << l << endl;
+  
+  assert(l==2*np);
+  for (i=0;i<np;i++)
+    {  float x,y;
+    f_in >>  x>> y;
+    vertices[i].r.x=x;
+    vertices[i].r.y=y;
+    vertices[i].m=M1;
+    vertices[i].DirOfSearch =NoDirOfSearch;
+
+    }
+  f_in.Record();
+  // lecture de nop5 bonjour les degats
+  f_in >> l;
+  if(verbosity>9)
+    cout << " Read nop5  nb of int4 " << l << endl;
+ Int4 k=0;
+ Int4 nbe4 =  3*ntria + 4*nquad;
+ // cout << " nbv = " << nbv << " nbe4 " << nbe4 << endl;
+ SetOfEdges4 * edge4= new SetOfEdges4(nbe4,nbv); 
+ Int4 * refe = new Int4[nbe4];
+ Int4 kr =0;
+ for (i=0;i<ne;i++)
+   {
+     // Int4 ng[4]={0,0,0,0};
+     Int4 np[4],rv[4],re[4];
+     Int4 ncge,nmae,ndsde,npo;
+     f_in >> ncge >> nmae >> ndsde >> npo ;
+     //cout << " element " << i << " " << ncge << " "  
+     // << nmae <<" " <<  npo << endl;
+     if (ncge != 3 && ncge != 4)
+       {
+	 cerr << " read nopo type element[" << i << "] =" 
+	      << ncge << " not 3 or 4 " << endl;
+	 MeshError(115);
+       }
+     if (npo != 3 && npo != 4)
+       {
+	 cerr << " read nopo element[" << i << "] npo = "  
+	      << npo << " not 3 or 4 " << endl;
+	 MeshError(115);
+       }
+     
+     for( j=0;j<npo;j++)
+       {f_in >>np[j];np[j]--;}
+     
+     if (ncopnp !=1) 
+       {
+	 f_in >> npo;
+	 if (npo != 3 || npo != 4)
+	   {
+	     cerr << " read nopo type element[" << i << "]= "  
+		  << ncge << " not 3 or 4 " << endl;
+	     MeshError(115);
+	   }
+	 
+	 for(j=0;j<npo;j++)
+	   {f_in >>np[j];np[j]--;}
+	 
+       }
+     if (nmae>0) 
+       {
+	 Int4  ining; // no ref 
+	 
+	 f_in>>ining;
+	 if (ining==1)
+	   MeshError(116);
+	 if (ining==2)
+	   for (j=0;j<npo;j++)
+	     f_in >>re[j];
+	 for (j=0;j<npo;j++)
+	   f_in >>rv[j];
+	 
+	 
+	 // set the ref on vertex and the shift np of -1 to start at 0
+	 for (j=0;j<npo;j++)
+	   vertices[np[j]].ReferenceNumber = rv[j];
+	 
+	 if (ining==2)
+	   for (j=0;j<npo;j++)
+	     if (re[j])
+	       {
+		 kr++;
+		 Int4 i0 = np[j];
+		 Int4 i1 = np[(j+1)%npo];
+		 // cout << kr << " ref  edge " << i0 << " " << i1 << " " << re[j] << endl;
+		 refe[edge4->addtrie(i0,i1)]=re[j];
+	       }
+       }
+     
+     if (npo==3) 
+       { // triangles 
+	 triangles[k]  = Triangle(this,np[0],np[1],np[2]); 
+	 triangles[k].color = ndsde;
+	 k++;
+       }
+     else if (npo==4)
+       { // quad 
+	 Triangle & t1 = triangles[k++];
+	 Triangle & t2 = triangles[k++];
+	 t1 = Triangle(this,np[0],np[1],np[2]);
+	 t2 = Triangle(this,np[2],np[3],np[0]);
+	 t1.SetHidden(OppositeEdge[1]); // two time  because the adj was not created 
+	 t2.SetHidden(OppositeEdge[1]); 
+	 t1.color = ndsde;
+	 t2.color = ndsde;
+       }
+     else
+       {
+	 cerr << " read nopo type element =" << npo << " not 3 or 4 " << endl;
+	 MeshError(114);
+       }
+     
+     
+   }
+ // cout << k << " == " << nbt << endl;
+ assert(k==nbt);
+
+ nbe = edge4->nb();
+ if (nbe)
+   {
+     if (verbosity>7)
+     cout << " Nb of ref edges = " << nbe << endl;
+     if (edges)
+       delete [] edges;
+     edges = new Edge[nbe];
+     for (i=0;i<nbe;i++)
+       {
+	 edges[i].v[0] = vertices + edge4->i(i);
+	 edges[i].v[1] = vertices + edge4->j(i);
+	 edges[i].ref = refe[i];
+	 //	 cout << i << " " <<  edge4->i(i) << " " <<  edge4->j(i) << endl;
+       }
+      if (verbosity>7)
+	cout << " Number of reference edge in the  mesh = " << nbe << endl;
+   }
+ delete [] refe;
+ delete edge4;
+}
+  void  Triangles::Read_ftq(MeshIstream & f_in)
+{
+  //  
+  if (verbosity>1)
+    cout << "  -- ReadMesh .ftq file " <<  f_in.CurrentFile  << endl;
+  
+  Int4 i,ne,nt,nq;
+  f_in.cm() >> nbv >> ne >> nt >> nq ;
+  if (verbosity>3)
+    cout << "    nbv = " << nbv  << " nbtra = " << nt << " nbquad = " << nq << endl;
+  nbt = nt+2*nq;
+  
+
+  nbvx = nbv;
+  nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+  triangles =new Triangle[nbtx];
+  assert(triangles);
+  vertices=new Vertex[nbvx];
+  ordre=new Vertex* [nbvx];
+  Int4 k=0;
+  
+  for ( i=0;i<ne;i++) 
+    {
+      long ii,i1,i2,i3,i4,ref;
+      f_in >>  ii;
+	if (ii==3) 
+	  { // triangles 
+	    f_in >> i1>>  i2 >>   i3 >> ref ;
+	    triangles[k]  = Triangle(this,i1-1,i2-1,i3-1); 
+	    triangles[k++].color = ref;
+	  }
+	else if (ii==4)
+	  { // quad 
+	    f_in >> i1>>  i2 >>   i3 >> i4 >> ref ;
+	    Triangle & t1 = triangles[k++];
+	    Triangle & t2 = triangles[k++];
+	    t1 = Triangle(this,i1-1,i2-1,i3-1);
+	    t1.color=ref;
+	    t2 = Triangle(this,i3-1,i4-1,i1-1);
+	    t2.color=ref;
+	    t1.SetHidden(OppositeEdge[1]); // two time  because the adj was not created 
+	    t2.SetHidden(OppositeEdge[1]); 	  
+	  }
+	else
+	  {
+	    cout << " read ftq type element =" << ii << " not 3 or 4 " << endl;
+	    MeshError(111);
+	  }
+    }
+  assert(k==nbt);
+  Metric M1(1);
+  for ( i=0;i<nbv;i++)
+    {
+      f_in >> vertices[i].r.x >>   vertices[i].r.y >> vertices[i].ReferenceNumber;
+       vertices[i].DirOfSearch =NoDirOfSearch;
+       vertices[i].m = M1;
+
+    }
+}
+
+///////////////////////////////////////////////
+
+void  Triangles::Read_msh(MeshIstream &f_in)
+{
+    Metric M1(1.);
+  if (verbosity>1)
+    cout << "  -- ReadMesh .msh file " <<  f_in.CurrentFile  << endl;
+   	
+     Int4 i;
+     f_in.cm() >> nbv >> nbt ;
+     while (f_in.in.peek()==' ')
+         f_in.in.get();
+     if(isdigit(f_in.in.peek())) 
+       f_in >> nbe;
+     if (verbosity>3)
+       cout << "    nbv = " << nbv  << " nbt = " << nbt << " nbe = " << nbe << endl;
+     nbvx = nbv;
+     nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+     triangles =new Triangle[nbtx];
+     assert(triangles);
+     vertices=new Vertex[nbvx];
+     ordre=new Vertex* [nbvx];
+      edges = new Edge[nbe];
+     for ( i=0;i<nbv;i++)
+	{
+	 f_in >> vertices[i].r.x >>   vertices[i].r.y >> vertices[i].ReferenceNumber;
+	    vertices[i].on=0;
+	    vertices[i].m=M1;
+         //if(vertices[i].ReferenceNumber>NbRef)	NbRef=vertices[i].ReferenceNumber;  
+  	}
+     for (     i=0;i<nbt;i++)
+       {
+	 Int4 i1,i2,i3,r;
+	 f_in >>  i1 >>  i2 >>   i3 >> r;
+	 triangles[i]  = Triangle(this,i1-1,i2-1,i3-1);
+	 triangles[i].color = r;	 
+       }
+     for (i=0;i<nbe;i++)
+       {
+	 Int4 i1,i2,r;
+	 f_in >>  i1 >>  i2 >> r;
+	      edges[i].v[0]= vertices +i1-1;
+	      edges[i].v[1]= vertices +i2-1;
+	      edges[i].adj[0]=0;
+	      edges[i].adj[1]=0;
+	      edges[i].ref = r;
+	      edges[i].on=0;
+       }
+      
+}
+
+//////////////////////////////////////////////////
+
+void  Triangles::Read_amdba(MeshIstream &f_in )
+{
+  Metric M1(1);
+  if (verbosity>1)
+    cout << "  -- ReadMesh .amdba file " <<  f_in.CurrentFile  << endl;
+   	
+     Int4 i;
+     f_in.cm() >> nbv >> nbt ;
+     //    if (verbosity>3)
+       cout << "    nbv = " << nbv  << " nbt = " << nbt << endl;
+     f_in.eol() ;// 
+     nbvx = nbv;
+     nbtx =  2*nbv-2; // for filling The Holes and quadrilaterals 
+     triangles =new Triangle[nbtx];
+     assert(triangles);
+     vertices=new Vertex[nbvx];
+     ordre=new Vertex* [nbvx];
+     Int4 j;
+      for ( i=0;i<nbv;i++)
+	{
+	  f_in >> j ;
+	  assert( j >0 && j <= nbv);
+	  j--;
+	  f_in >> vertices[j].r.x >>   vertices[j].r.y >> vertices[j].ReferenceNumber;
+	   vertices[j].m=M1;
+	   vertices[j].DirOfSearch=NoDirOfSearch;
+	}
+     
+      for (     i=0;i<nbt;i++)
+       {
+	 Int4 i1,i2,i3,ref;
+	   f_in >> j ;
+	   assert( j >0 && j <= nbt);
+	   j--;
+	   f_in >> i1 >>  i2 >>   i3 >> ref;
+	 triangles[j]  = Triangle(this,i1-1,i2-1,i3-1);
+	 triangles[j].color =ref;
+       }
+      f_in.eol() ;// 
+      
+  // cerr << " a faire " << endl;
+  //MeshError(888);
+}
+
+
+Triangles::Triangles(const char * filename,Real8 cutoffradian) 
+: Gh(*(new Geometry())), BTh(*this)
+{ 
+#ifdef DRAWING1
+   if (!withrgraphique) {initgraphique();withrgraphique=true;}   
+#endif
+
+  //  Int4 beginquad=0,begintria=0;
+  // Int4 endquad=0;endtria=0;
+  //int type_file=0;
+
+  int lll = strlen(filename);
+  int  am_fmt = !strcmp(filename + lll - 7,".am_fmt");
+  int  amdba = !strcmp(filename + lll - 6,".amdba");
+  int  am = !strcmp(filename + lll - 3,".am");
+  int  nopo = !strcmp(filename + lll - 5,".nopo");
+  int  msh = !strcmp(filename + lll - 4,".msh");
+  int  ftq = !strcmp(filename + lll - 4,".ftq");
+
+ // cout << " Lecture type  :" << filename + lll - 7 <<":" <<am_fmt<<  endl;
+
+  char * cname = new char[lll+1];
+  strcpy(cname,filename);
+  Int4 inbvx =0;
+  PreInit(inbvx,cname);
+  OnDisk = 1;
+  //  allocGeometry = &Gh; // after Preinit ; 
+
+  MeshIstream f_in (filename);
+  
+  if (f_in.IsString("MeshVersionFormatted"))
+    {
+      int version ;
+      f_in >> version ;
+      Read(f_in,version,cutoffradian);
+    }
+  else {     
+    if (am_fmt) Read_am_fmt(f_in);
+    else if (am) Read_am(f_in);
+    else if (amdba) Read_amdba(f_in);
+    else if (msh) Read_msh(f_in);
+    else if (nopo) Read_nopo(f_in);
+    else if (ftq) Read_ftq(f_in);
+    else 
+      { 
+	cerr << " Unkown type mesh " << filename << endl;
+	MeshError(2);
+      }
+      ConsGeometry(cutoffradian);
+      Gh.AfterRead();    
+  }
+
+  SetIntCoor();
+  FillHoleInMesh();
+  // Make the quad ---
+   
+}
+
+void Geometry::ReadGeometry(const char * filename)
+{
+  OnDisk = 1;
+  if(verbosity>1)
+      cout << "  -- ReadGeometry " << filename << endl;
+  MeshIstream f_in (filename);
+  ReadGeometry(f_in,filename);
+}
+
+
+
+void Geometry::ReadGeometry(MeshIstream & f_in,const char * filename)  
+{
+  if(verbosity>1)
+    cout << "  -- ReadGeometry " << filename << endl;
+  assert(empty());
+  nbiv=nbv=nbvx=0;
+  nbe=nbt=nbtx=0;
+  NbOfCurves=0;
+ // BeginOfCurve=0;
+  name=new char [strlen(filename)+1];
+  strcpy(name,filename);
+  Real8 Hmin = HUGE_VAL;// the infinie value 
+//  Real8 MaximalAngleOfCorner = 10*Pi/180; ; 
+  Int4 hvertices =0;
+  Int4 i;
+  Int4 Version,dim=0;
+  int field=0;
+  int showfield=0;
+  int NbErr=0;
+
+  while (f_in.cm()) 
+    { 
+      field=0;
+      // warning ruse for on allocate fiedname at each time 
+      char fieldname[256];
+      f_in.cm() >> fieldname ;
+      f_in.err();
+      if(f_in.eof()) break;
+//      cout <<  fieldname <<  " line " << LineNumber  <<endl;
+      if (!strcmp(fieldname,"MeshVersionFormatted") )
+        f_in  >> Version ;
+      else if (!strcmp(fieldname,"End"))
+	break;
+      else if (!strcmp(fieldname,"end"))
+	break;
+      else if (!strcmp(fieldname,"Dimension"))
+        {
+          f_in   >>  dim ;
+	  if(verbosity>5) 
+	    cout << "     Geom Record Dimension dim = " << dim << endl;        
+          assert(dim ==2);
+         }
+       else if (!strcmp(fieldname,"hVertices"))
+         { 
+	   if (nbv <=0) {
+	     cerr<<"Error: the field Vertex is not found before hVertices " << filename<<endl;
+	     NbErr++;}       
+	   if(verbosity>5) 
+	    cout << "     Geom Record hVertices nbv=" << nbv <<  endl;
+	   hvertices =1;
+           for (i=0;i< nbv;i++) 
+	     {
+	       Real4 h;
+	       f_in  >>  h ; 
+	       vertices[i].m = Metric(h);
+	     }
+	 }
+       else if (!strcmp(fieldname,"MetricVertices"))
+         { hvertices =1;
+	   if (nbv <=0) {
+	     cerr<<"Error: the field Vertex is not found before MetricVertices " << filename<<endl;
+	     NbErr++;}       
+           if(verbosity>5) 
+	     cout << "     Geom Record MetricVertices nbv =" << nbv <<  endl;
+           for (i=0;i< nbv;i++) 
+	     {
+	       Real4 a11,a21,a22;
+	       f_in  >>  a11 >> a21 >> a22  ; 
+	       vertices[i].m = Metric(a11,a21,a22);
+	     }
+	 }
+       else if (!strcmp(fieldname,"h1h2VpVertices"))
+         { hvertices =1;
+	   if (nbv <=0) {
+	     cerr<<"Error: the field Vertex is not found before h1h2VpVertices " << filename<<endl;
+	     NbErr++;}       
+           if(verbosity>5) 
+	     cout << "     Geom Record h1h2VpVertices nbv=" << nbv << endl;
+
+           for (i=0;i< nbv;i++) 
+	     {
+	       Real4 h1,h2,v1,v2;
+	       f_in  >> h1 >> h2 >>v1 >>v2 ; 
+	       vertices[i].m = Metric(MatVVP2x2(1/(h1*h1),1/(h2*h2),D2(v1,v2)));
+	     }
+	 }
+      else if (!strcmp(fieldname,"Vertices"))
+        { 
+          assert(dim ==2);
+          f_in   >>  nbv ;
+	  //          if(LineError) break;
+          nbvx = nbv;
+          
+          vertices = new GeometricalVertex[nbvx];
+	  if(verbosity>5) 
+	    cout << "     Geom Record Vertices nbv = " << nbv << "vertices = " << vertices<<endl;
+          assert(nbvx >= nbv);
+          nbiv = nbv;
+          for (i=0;i<nbv;i++) {
+            f_in  >> vertices[i].r.x  ;
+            // if(LineError) break;
+            f_in  >> vertices[i].r.y ;
+	    // if(LineError) break;
+            f_in >>   vertices[i].ReferenceNumber   ;
+            vertices[i].DirOfSearch=NoDirOfSearch;
+	    //            vertices[i].m.h = 0;
+            vertices[i].color =0;
+            vertices[i].Set();}
+	  // if(LineError) break;
+	    pmin =  vertices[0].r;
+	    pmax =  vertices[0].r;
+	    // recherche des extrema des vertices pmin,pmax
+	    for (i=0;i<nbv;i++) {
+	      pmin.x = Min(pmin.x,vertices[i].r.x);
+	      pmin.y = Min(pmin.y,vertices[i].r.y);
+	      pmax.x = Max(pmax.x,vertices[i].r.x);
+	      pmax.y = Max(pmax.y,vertices[i].r.y);
+	    }
+	    
+	      R2 DD05 = (pmax-pmin)*0.05;
+	      pmin -=  DD05;
+	      pmax +=  DD05;
+	    
+	    coefIcoor= (MaxICoor)/(Max(pmax.x-pmin.x,pmax.y-pmin.y));
+	    assert(coefIcoor >0);
+	    if (verbosity>5) {
+	      cout << "     Geom: min="<< pmin << "max ="<< pmax << " hmin = " << MinimalHmin() <<  endl;}
+        }
+      else if(!strcmp(fieldname,"MaximalAngleOfCorner")||!strcmp(fieldname,"AngleOfCornerBound"))
+        {         
+          f_in >> MaximalAngleOfCorner;
+              
+	  if(verbosity>5) 
+	    cout << "     Geom Record MaximalAngleOfCorner " << MaximalAngleOfCorner <<endl;
+          MaximalAngleOfCorner *= Pi/180;
+        }
+      else if (!strcmp(fieldname,"Edges"))
+        {
+	  if (nbv <=0) {
+	    cerr<<"Error: the field edges is not found before MetricVertices " << filename<<endl;
+	    NbErr++;}   
+	  else 
+	    {
+	      int i1,i2;
+	      R2 zero2(0,0);
+	      f_in   >>  nbe ;
+	      
+	      edges = new GeometricalEdge[nbe];
+	      if(verbosity>5) 
+		cout << "     Record Edges: Nb of Edge " << nbe <<endl;
+	      assert(edges);
+	      assert (nbv >0); 
+	      Real4 *len =0;
+	      if (!hvertices) 
+		{
+		  len = new Real4[nbv];
+		  for(i=0;i<nbv;i++)
+		    len[i]=0;
+		}
+	      
+	      for (i=0;i<nbe;i++) 
+		{
+		  f_in  >> i1   >> i2 >>  edges[i].ref  ;
+		  
+		  i1--;i2--; // for C index
+		  edges[i].v[0]=  vertices + i1;
+		  edges[i].v[1]=  vertices + i2;
+		  R2 x12 = vertices[i2].r-vertices[i1].r;
+		  Real8 l12=sqrt((x12,x12));
+		  edges[i].tg[0]=zero2;
+		  edges[i].tg[1]=zero2;
+		  edges[i].SensAdj[0] = edges[i].SensAdj[1] = -1;
+		  edges[i].Adj[0] = edges[i].Adj[1] = 0;
+		  edges[i].flag = 0;
+		  if (!hvertices) 
+		    {
+		      vertices[i1].color++;
+		      vertices[i2].color++;
+		      len[i1] += l12;
+		      len[i2] += l12;
+		    }
+		  
+		  Hmin = Min(Hmin,l12);
+		}
+	      // definition  the default of the given mesh size 
+	      if (!hvertices) 
+		{
+		  for (i=0;i<nbv;i++) 
+		    if (vertices[i].color > 0) 
+		      vertices[i].m=  Metric(len[i] /(Real4) vertices[i].color);
+		    else 
+		      vertices[i].m=  Metric(Hmin);
+		  delete [] len;
+		  
+		  if(verbosity>3) 
+		    cout << "     Geom Hmin " << Hmin << endl;
+		}
+	      
+	    }
+	}
+      else if (!strcmp(fieldname,"EdgesTangence") ||!strcmp(fieldname,"TangentAtEdges")  )
+        { 
+          int n,i,j,k;
+          R2 tg;
+          f_in  >> n ;
+          
+	  if(verbosity>5) 
+	    cout << "     Record TangentAtEdges: Nb of Edge " << n <<endl;
+          
+          for (k=0;k<n;k++)
+            {
+	      f_in  >>  i  >> j ;
+	      f_in >> tg.x  >> tg.y ;
+	      assert( i <= nbe );
+	      assert( i > 0 );
+	      assert ( j == 1 || j==2 );
+	      i--;j--;// for C index
+	      edges[i].tg[j] = tg;
+            }
+        }
+      else if (!strcmp(fieldname,"Corners"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+	  if(verbosity>5) 
+	    cout << "     Record Corner: Nb of Corner " << n <<endl;
+          
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbv );
+            assert( j > 0 );
+            j--;
+            vertices[j].SetCorner();
+            vertices[j].SetRequired();  }
+        }
+      else if (!strcmp(fieldname,"RequiredVertices"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbv );
+            assert( j > 0 );
+            j--;
+            vertices[j].SetRequired();  }
+      }
+      else if (!strcmp(fieldname,"RequiredEdges"))
+        { 
+          int i,j,n;
+          f_in  >> n ;
+
+          for (i=0;i<n;i++) {     
+            f_in  >>  j ;
+            assert( j <= nbe );
+            assert( j > 0 );
+            j--;
+            edges[j].SetRequired();  }
+      }
+    else if (!strcmp(fieldname,"SubDomain") || !strcmp(fieldname,"SubDomainFromGeom"))
+      { 
+	f_in   >>  NbSubDomains ;
+	if (NbSubDomains>0) 
+	  {
+	    subdomains = new GeometricalSubDomain[  NbSubDomains];
+	    Int4 i0,i1,i2,i3;
+	    for (i=0;i<NbSubDomains;i++) 
+	      {
+		f_in  >> i0  >>i1 
+		      >> i2  >>i3 ; 
+		
+		assert(i0 == 2);
+		assert(i1<=nbe && i1>0);
+		subdomains[i].edge=edges + (i1-1);
+		subdomains[i].sens = (int) i2;
+		subdomains[i].ref = i3;
+	      }
+	  }
+      }
+      else
+	{ // unkown field
+	  field = ++showfield;
+	  if(showfield==1) // just to show one time 
+	    if (verbosity>3)
+	      cout << "    Warning we skip the field " << fieldname << " at line " << f_in.LineNumber << endl;
+	}
+      showfield=field; // just to show one time 
+    } // while !eof()
+  // generation  de la geometrie 
+  // 1 construction des aretes 
+  // construire des aretes en chaque sommets 
+  
+  if (nbv <=0) {
+    cerr<<"Error: the field Vertex is not found in " << filename<<endl;
+    NbErr++;}
+  if(nbe <=0) {
+    cerr <<"Error: the field Edges is not found in "<< filename<<endl
+      ;NbErr++;}
+  if(NbErr) MeshError(1);
+
+ 
+}
+
+
+}  // end of namespace bamg 
diff --git a/src/bamglib/MeshWrite.cpp b/src/bamglib/MeshWrite.cpp
new file mode 100644
index 0000000..85fc101
--- /dev/null
+++ b/src/bamglib/MeshWrite.cpp
@@ -0,0 +1,1021 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "config.h"
+#include <cstdio>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+#ifdef HAVE_HDF5
+//-----------------------------ajout format hdf5-----------------------------//
+#include "write_xdmf.hpp"
+#include "write_hdf5.hpp"
+#ifndef H5_NO_NAMESPACE
+#ifndef H5_NO_STD
+using std::cout;
+using std::endl;
+#endif  // H5_NO_STD
+#endif
+
+#include "H5Cpp.h"
+
+#ifndef H5_NO_NAMESPACE
+using namespace H5;
+#endif
+#endif
+//-----------------------------ajout format hdf5-----------------------------//
+
+namespace bamg {
+  
+  void Triangles::Write(const char * filename,const TypeFileMesh typein )
+  {
+    TypeFileMesh type = typein;
+    const char * gsuffix=".gmsh";
+    int ls=0;
+    int lll = strlen(filename);
+    if (type==AutoMesh)
+      {
+	type = BDMesh;
+	if      (!strcmp(filename + lll - (ls=7),".am_fmt")) type = am_fmtMesh;
+	else if (!strcmp(filename + lll - (ls=6),".amdba"))  type = amdbaMesh;
+	else if (!strcmp(filename + lll - (ls=3),".am"))     type = amMesh;
+	else if (!strcmp(filename + lll - (ls=5),".nopo"))   type = NOPOMesh;
+	else if (!strcmp(filename + lll - (ls=4),".msh"))    type = mshMesh;
+//-----------------------------ajout format hdf5-----------------------------//
+	else if (!strcmp(filename + lll - (ls=3),".h5"))     type = hdf5Mesh;
+//-----------------------------ajout format hdf5-----------------------------//
+	else if (!strcmp(filename + lll - (ls=4),".ftq"))    type = ftqMesh;
+	else if (!strcmp(filename + lll - (ls=7),".AM_FMT")) type = am_fmtMesh;
+	else if (!strcmp(filename + lll - (ls=6),".AMDBA"))  type = amdbaMesh;
+	else if (!strcmp(filename + lll - (ls=3),".AM"))     type = amMesh;
+	else if (!strcmp(filename + lll - (ls=5),".NOPO"))   type = NOPOMesh;
+	else if (!strcmp(filename + lll - (ls=4),".MSH"))    type = mshMesh;
+	else if (!strcmp(filename + lll - (ls=4),".FTQ"))    type = ftqMesh;
+	else ls=0;
+      } 
+    if (verbosity>1)
+      {
+	cout << "  -- Writing the file " << filename << " of type " ;
+	switch (type) 
+	  {
+	  case BDMesh     :  cout << " BD Mesh "  ; break;
+	  case NOPOMesh   :  cout << " NOPO "     ; break;
+	  case amMesh     :  cout << " am "       ; break;
+	  case am_fmtMesh :  cout << " am_fmt "   ; break;
+	  case amdbaMesh  :  cout << " amdba "    ; break;
+	  case ftqMesh    :  cout << " ftq "      ; break;
+	  case mshMesh    :  cout << " msh "      ; break;
+//-----------------------------ajout format hdf5-----------------------------//
+	  case hdf5Mesh   :  cout << " h5  "      ; break;
+//-----------------------------ajout format hdf5-----------------------------//
+	  default: 
+	    cerr << endl 
+		 <<  " Unkown type mesh file " << (int) type << " for Writing " << filename <<endl;
+	    MeshError(1);
+	  }     
+	Int4 NbOfTria =  nbt-2*NbOfQuad-NbOutT ;
+	if (NbOfTria)      cout << " NbOfTria = " << NbOfTria;
+	if (NbOfQuad)      cout << " NbOfQuad = " << NbOfQuad;
+	if (nbe)   	cout << " NbOfRefEdge = " << nbe ;
+	cout    << endl;
+	
+      }
+    ofstream f(filename /*,ios::trunc*/);
+    f.precision(12);
+    
+    if (f)
+      switch (type) 
+	{
+	case BDMesh     : 
+	  {
+	    if ( ! Gh.OnDisk)
+	      {
+		delete [] Gh.name;
+		Gh.name = new char[lll+1+strlen(gsuffix)];
+		strcpy(Gh.name,filename);
+		if (Gh.name[lll-ls-1]=='.') strcpy(Gh.name+lll-ls, gsuffix+1);
+		else strcpy(Gh.name+lll-ls,gsuffix);
+		cout << " write geo in " << Gh.name << endl;
+		ofstream f(Gh.name) ;
+		f << Gh ;
+		Gh.OnDisk=true;
+	      }
+	    f << *this     ;
+	    break;
+	  }
+	case NOPOMesh   :  Write_nopo(f)  ; break;
+	case amMesh     :  Write_am(f)    ; break;
+	case am_fmtMesh :  Write_am_fmt(f); break;
+	case amdbaMesh  :  Write_amdba(f) ; break;
+	case ftqMesh    :  Write_ftq(f)   ; break;
+	case mshMesh    :  Write_msh(f)   ; break;
+//-----------------------------ajout format hdf5-----------------------------//
+	case hdf5Mesh   :  Write_hdf5(filename)  ; break;
+//-----------------------------ajout format hdf5-----------------------------//
+	default: 
+	  cerr << " Unkown type mesh file " << (int) type << " for Writing " << filename <<endl;
+	  MeshError(1);
+	}
+    else
+      {
+	cerr << " Error openning file " << filename << endl;
+	MeshError(1);
+      }
+    if(verbosity>5)
+      cout << "end write" << endl;
+    
+  }
+  void Triangles::Write_nop5(OFortranUnFormattedFile * f,
+			     Int4 &lnop5,Int4 &nef,Int4 &lgpdn,Int4 ndsr) const 
+  {
+    ndsr =0;
+    Int4 * reft = new Int4[nbt];
+    //Int4 nbInT = ;
+    ConsRefTriangle(reft);
+    Int4 no5l[20];
+    
+    Int4 i5 = 0;
+    Int4 i,j,k=0,l5;
+    //  Int4 ining=0;
+    Int4 imax,imin;
+    
+    lgpdn = 0;
+    nef=0;
+    // construction of a liste linked  of edge
+    Edge ** head  = new Edge *[nbv];
+    Edge  ** link = new Edge * [nbe];
+    for (i=0;i<nbv;i++)
+      head[i]=0; // empty liste
+    
+    for (i=0;i<nbe;i++)
+      { 
+	j = Min(Number(edges[i][0]),Number(edges[i][1]));
+	link[i]=head[j];
+	head[j]=edges +i;
+      }
+    for ( i=0;i<nbt;i++)
+      {
+	no5l[0]    = 0;
+	Int4 kining=0;
+	Int4 ining=0;
+	Int4 nmae =0;
+	Int4 np=0;
+	l5 = 2;
+	Triangle & t = triangles[i];
+	Triangle * ta; // 
+	Vertex *v0,*v1,*v2,*v3;
+	if (reft[i]<0) continue;
+	ta = t.Quadrangle(v0,v1,v2,v3);
+	if (!ta)
+	  { // a triangles
+	    no5l[l5++] = Max(subdomains[reft[i]].ref,(Int4) 1);
+	    np = 3;
+	    no5l[l5++] = np;
+	    no5l[0]    = np;
+	    no5l[l5++] = Number(triangles[i][0]) +1;
+	    no5l[l5++] = Number(triangles[i][1]) +1;
+	    no5l[l5++] = Number(triangles[i][2]) +1;
+	    imax = Max3(no5l[l5-1],no5l[l5-2],no5l[l5-3]);
+	    imin = Min3(no5l[l5-1],no5l[l5-2],no5l[l5-3]);
+	    lgpdn = Max(lgpdn,imax-imin);
+	    kining=l5++;
+	    // ref of 3 edges 
+	    for (j=0;j<3;j++)
+	      {
+		no5l[l5] = 0;
+		int i0 = (int) j;
+		int i1 = (i0+1) %3;
+		Int4 j1= no5l[4+i0];
+		Int4 j2= no5l[4+i1];
+		Int4 ji = Min(j1,j2)-1;
+		Int4 ja = j1+j2-2;
+		Edge * e=head[ji];
+		while (e)
+		  if(Number((*e)[0])+Number((*e)[1]) == ja) 
+		    {
+		      no5l[l5] = e->ref;
+		      break;
+		    }
+		  else
+		    e = link[Number(e)];
+		l5++;
+	      }
+	    if ( no5l[l5-1] || no5l[l5-2] || no5l[l5-3]  )
+	      ining=2;
+	    else 
+	      l5 -= 3;
+	    
+	    no5l[l5++] = triangles[i][0].ref();
+	    no5l[l5++] = triangles[i][1].ref();
+	    no5l[l5++] = triangles[i][2].ref();
+	    if (ining ||  no5l[l5-1] || no5l[l5-2] || no5l[l5-3]  )
+	      ining= ining ? ining : 3;
+	    else
+	      l5 -= 3,ining=0; 
+	  }
+	else if ( &t<ta)
+	  { 
+	    k++;
+	    no5l[l5++] = Max(subdomains[reft[i]].ref,(Int4) 1);
+	    np =4;
+	    no5l[l5++] = np;
+	    no5l[0]    = np;
+	    
+	    no5l[l5++] = Number(v0) +1;
+	    no5l[l5++] = Number(v1) +1;
+	    no5l[l5++] = Number(v2) +1;
+	    no5l[l5++] = Number(v3) +1;
+	    
+	    imax = Max(Max(no5l[l5-1],no5l[l5-2]),Max(no5l[l5-3],no5l[l5-4]));
+	    imin = Min(Min(no5l[l5-1],no5l[l5-2]),Min(no5l[l5-3],no5l[l5-4]));
+	    lgpdn = Max(lgpdn,imax-imin);
+	    
+	    
+	    kining=l5++;
+	    // ref of the 4 edges 
+	    // ref of 3 edges 
+	    for (j=0;j<4;j++)
+	      {
+		no5l[l5] = 0;
+		int i0 = (int) j;
+		int i1 = (i0+1) %4;
+		Int4 j1= no5l[4+i0];
+		Int4 j2= no5l[4+i1];
+		Int4 ji = Min(j1,j2)-1;
+		Int4 ja = j1+j2-2;
+		Edge *e=head[ji];
+		while (e)
+		  if(Number((*e)[0])+Number((*e)[1]) == ja) 
+		    {
+		      no5l[l5] = e->ref;
+		      break;
+		    }
+		  else
+		    e = link[Number(e)];
+		l5++;
+	      }
+	    if ( no5l[l5-1] || no5l[l5-2] || no5l[l5-3] || no5l[l5-4] )
+	      ining=2;
+	    else 
+	      l5 -= 4;
+	    
+	    no5l[l5++] = v0->ref();
+	    no5l[l5++] = v1->ref();
+	    no5l[l5++] = v2->ref();
+	    no5l[l5++] = v3->ref();
+	    if (ining || no5l[l5-1] || no5l[l5-2] || no5l[l5-3] || no5l[l5-4] )
+	      ining= ining ? ining : 3;
+	    else
+	      l5 -= 4;
+	    
+	  }
+	else l5=0;
+	
+	if (l5)
+	  {
+	    if (ining)
+	      {
+		nef ++;
+		nmae = l5-kining;
+		no5l[kining] = ining;
+	      }
+	    else l5--;
+	    no5l[1]=nmae;
+	    // for all ref  
+	    for (j=kining+1;j<l5;j++)
+	      {
+		no5l[j] = Abs(no5l[j]);
+		ndsr = Max(ndsr,no5l[j]);
+	      }
+	    
+	    if (f && i < 10 && verbosity > 10)
+	      { 
+		cout << " e[ " << i << " @" << i5 << "]=";
+		for (j=0;j<l5;j++)
+		  cout << " " << no5l[j]; 
+		cout << endl;
+	      }
+	    
+	    if (f)
+	      for (j=0;j<l5;j++)
+		*f << no5l[j]; 
+	    i5 += l5;
+	  }
+      }
+    if(verbosity>10)
+      cout << "   fin write nopo 5 i5=" << i5 << " " << i5*4 << endl;
+    lnop5=i5; 
+    lgpdn++; // add 1
+    delete [] reft;
+    delete [] head;
+    delete [] link;
+    
+  }
+
+  void Triangles::Write_nopo(ostream &ff) const
+    
+  {
+    Int4  nef=0;
+    Int4 lpgdn=0;
+    Int4 ndsr=0;
+    Int4 i;
+    Int4 ndsd=1;
+    Int4 lnop5=0;
+ 
+    OFortranUnFormattedFile f(ff);
+ 
+    for (i=0;i<NbSubDomains ;i++)
+      ndsd=Max(ndsd,subdomains[i].ref);
+ 
+    // to compute the lnop5,nef,lpgdn,ndsr parameter 
+    Write_nop5(0,lnop5,nef,lpgdn,ndsr);
+    
+    f.Record();
+    
+    f <<  Int4(13)<<Int4(6)<<Int4(32)<<Int4(0)<<Int4(27)<<Int4(0) ;
+    f << Int4(nbv+nbv) ;
+    f << lnop5;
+    f << Int4(1 )<<Int4(1)<<Int4(1 )<<Int4(1)<<Int4(2)<<Int4(1);
+    
+    f.Record(33*sizeof(Int4)); 
+    
+    f << Int4(32) ;
+    
+    //char *c=identity;
+    time_t timer =time(0);
+    char buf[10];
+    strftime(buf ,10,"%y/%m/%d",localtime(&timer));
+    f.write4(identity,20);
+    f.write4(buf,2);
+    f.write4("created with BAMG",6);
+    f.write4("NOPO",1);
+    
+    
+    f << Int4(0) << Int4(1) << Int4(0) ;
+    f.Record();
+    Int4 nbquad= NbOfQuad;
+    Int4 nbtria= nbt-NbOutT - 2*NbOfQuad;
+    
+    cout << " lnop5      = " << lnop5 << endl;
+    cout << " nbquad     = " << nbquad << endl;
+    cout << " nbtrai     = " << nbtria << endl;
+    cout << " lpgdn      = " << lpgdn << endl;
+    cout << " nef        = " << nef  << endl;
+    cout << " np         = " << nbv  << endl;
+    cout << " ndsr       = " << ndsr << endl;
+    f << Int4(27)  
+      << Int4(2)  << ndsr     << ndsd    << Int4(1) << nbtria+nbquad
+      << Int4(0)  << Int4(0)  << nbtria  << nbquad  << Int4(0)
+      << Int4(0)  << Int4(0)  << Int4(0) << nef     << Int4(nbv)
+      << Int4(0)  << Int4(0)  << Int4(0) << Int4(0) << Int4(0)
+      << Int4(0)  << nbv      << Int4(2) << lpgdn   << Int4(0)
+      << lnop5    << Int4(1) ;
+    f.Record();
+    f << (Int4) 2*nbv;
+    for (i=0;i<nbv;i++)
+      f << (float) vertices[i].r.x <<  (float) vertices[i].r.y;
+    f.Record();
+    f << lnop5;
+    Write_nop5(&f,lnop5,nef,lpgdn,ndsr);
+    // cout << "fin write nopo" << endl;
+  }
+
+  void Triangles::Write_am_fmt(ostream &f) const 
+  {
+    Int4 i,j;
+    assert(this && nbt);
+    Int4 * reft = new Int4[nbt];
+    Int4 nbInT =    ConsRefTriangle(reft);
+    f.precision(12);
+    f << nbv << " " << nbInT << endl;
+    for (i=0;i<nbt;i++)
+      if(reft[i]>=0)
+	{
+	  f << Number(triangles[i][0]) +1 << " " ;
+	  f << Number(triangles[i][1]) +1 << " " ;
+	  f << Number(triangles[i][2]) +1 << " " ;
+	  f << endl;
+	}
+    for (i=0;i<nbv;i++)
+      f << vertices[i].r.x << " " << vertices[i].r.y << endl;
+    for (j=i=0;i<nbt;i++) 
+      if (reft[i]>=0)
+	f << subdomains[reft[i]].ref  << (j++%10 == 9 ?  '\n' : ' ');
+    f << endl;
+    for (i=0;i<nbv;i++)
+      f << vertices[i].ref()  << (i%10 == 9 ?  '\n' : ' ');
+    f << endl;
+    delete [] reft;
+
+
+  }
+
+  void Triangles::Write_am(ostream &ff) const 
+  {
+    OFortranUnFormattedFile f(ff);  
+    Int4 i,j;
+    assert(this && nbt);
+    Int4 * reft = new Int4[nbt];
+    Int4 nbInT =    ConsRefTriangle(reft);
+    f.Record();
+    f << nbv << nbInT ;
+    f.Record();
+    for (i=0;i<nbt;i++)
+      if(reft[i]>=0)
+	{
+	  f << Number(triangles[i][0]) +1 ;
+	  f << Number(triangles[i][1]) +1 ;
+	  f << Number(triangles[i][2]) +1 ;
+	}
+    for (i=0;i<nbv;i++)
+      {
+	float x= vertices[i].r.x;
+	float y= vertices[i].r.y;
+	f << x << y ;
+      }
+    for (j=i=0;i<nbt;i++) 
+      if (reft[i]>=0)
+	f << subdomains[reft[i]].ref;
+    for (i=0;i<nbv;i++)
+      f << vertices[i].ref() ;
+    delete [] reft;
+  }
+
+  void Triangles::Write_ftq(ostream &f) const 
+  {
+
+    Int4 i;
+    assert(this && nbt);
+    Int4 * reft = new Int4[nbt];
+    Int4 nbInT =    ConsRefTriangle(reft);
+    f.precision(12);
+    Int4 nele = nbInT-NbOfQuad;
+    Int4 ntri =  nbInT-2*NbOfQuad;
+    Int4 nqua =  NbOfQuad;
+
+    f << nbv << " " << nele << " " << ntri <<  " " << nqua << endl;
+    Int4 k=0;
+    for( i=0;i<nbt;i++)
+      { 
+	Triangle & t = triangles[i];
+	Triangle * ta; // 
+	Vertex *v0,*v1,*v2,*v3;
+	if (reft[i]<0) continue;
+	ta = t.Quadrangle(v0,v1,v2,v3);
+	if (!ta)
+	  { // a triangles
+	    f << "3 " 
+	      << Number(triangles[i][0]) +1 << " " 
+	      << Number(triangles[i][1]) +1 << " " 
+	      << Number(triangles[i][2]) +1 << " " 
+	      << subdomains[reft[i]].ref << endl;
+	    k++;
+	  }
+	if ( &t<ta)
+	  { 
+	    k++;
+	    f << "4 " << Number(v0)+1 << " " << Number(v1)+1  << " "  
+	      << Number(v2)+1 << " "  << Number(v3)+1 << " "  
+	      << subdomains[reft[i]].ref << endl;
+	  }
+      }
+    assert(k == nele);
+  
+    for (i=0;i<nbv;i++)
+      f << vertices[i].r.x << " " << vertices[i].r.y 
+	<< " " <<  vertices[i].ref() << endl;
+    delete [] reft;
+  
+  
+  }
+  void Triangles::Write_msh(ostream &f) const 
+  {
+    Int4 i;
+    assert(this && nbt);
+    Int4 * reft = new Int4[nbt];
+    Int4 nbInT =    ConsRefTriangle(reft);
+    f.precision(12);
+    f << nbv << " " << nbInT << " " << nbe <<  endl;
+
+    for (i=0;i<nbv;i++)
+      f << vertices[i].r.x << " " << vertices[i].r.y << " " 
+	<< vertices[i].ref() <<   endl;
+
+    for (i=0;i<nbt;i++)
+      if(reft[i]>=0)
+	f << Number(triangles[i][0]) +1 << " " 
+	  << Number(triangles[i][1]) +1 << " " 
+	  << Number(triangles[i][2]) +1 << " " 
+	  << subdomains[reft[i]].ref << endl;
+  
+
+    for (i=0;i<nbe;i++)
+      f << Number(edges[i][0]) +1 << " "  << Number(edges[i][1]) +1 
+	<< " " << edges[i].ref << endl;
+      
+    delete [] reft;
+
+  }
+
+
+  //-----------------------------ajout format hdf5-----------------------------//
+  void Triangles::Write_hdf5(const char * f) const 
+  {
+#ifdef HAVE_HDF5
+    Int4 i;
+    assert(this && nbt);
+    Int4 * reft = new Int4[nbt];
+    Int4 nbInT = ConsRefTriangle(reft);
+    float coord[nbv][2];
+    int Connectivity[nbInT][3];
+
+    for (i=0;i<nbv;i++)
+      {
+	coord[i][0]=vertices[i].r.x;
+	coord[i][1]=vertices[i].r.y;
+      }
+
+    for (i=0;i<nbt;i++)
+      { 
+	if(reft[i]>=0)
+	  {
+	    Connectivity[i][0]=Number(triangles[i][0]);
+	    Connectivity[i][1]=Number(triangles[i][1]);
+	    Connectivity[i][2]=Number(triangles[i][2]);
+	  }
+      }
+
+    // write hdf5 file
+    WriteHdf5 * Hdf5MeshFile2D = new WriteHdf5(f,nbInT,nbv);
+    Hdf5MeshFile2D->WriteHdf5MeshFile2D(coord, Connectivity);
+    delete Hdf5MeshFile2D; 
+
+    // write xdmf file
+    WriteXdmf * XdmfMeshFile2D = new WriteXdmf(f,nbInT,nbv);
+    XdmfMeshFile2D->WriteXdmfMeshFile2D();
+    delete XdmfMeshFile2D; 
+
+    delete [] reft;
+#else
+      cerr << " Sorry no hdf5 on with computer= no Write_hdf5 of" << f << endl;
+      MeshError(9999,this);
+#endif
+  }
+  //-----------------------------ajout format hdf5-----------------------------//
+
+
+
+
+
+  void Triangles::Write_amdba(ostream &f) const 
+  {
+    assert(this && nbt);
+
+    Int4 i,j;
+    Int4 * reft = new Int4[nbt];
+    Int4 nbInT =    ConsRefTriangle(reft);
+    f << nbv << " " << nbInT << endl;
+    cout.precision(12);
+    for (i=0;i<nbv;i++)
+      f << i+1 << " " 
+	<< vertices[i].r.x 
+	<< " " << vertices[i].r.y 
+	<< " " << vertices[i].ref() << endl;
+    j=1;
+    for (i=0;i<nbt;i++)
+      if(reft[i]>=0)
+	f << j++ << " " 
+	  << Number(triangles[i][0]) +1 << " " 
+	  << Number(triangles[i][1]) +1 << " " 
+	  << Number(triangles[i][2]) +1 << " " 
+	  << subdomains[reft[i]].ref  << endl ;
+    f << endl;
+    delete [] reft;
+
+
+  }
+
+  void Triangles::Write(const char * filename)
+  {
+    ofstream f(filename);
+    if (f)
+      {
+	if (name) delete name;
+	name = new char[strlen(filename)+1];
+	strcpy(name,filename);
+	OnDisk =1;
+	f << *this;
+      }
+  }
+  void Triangles::WriteElements(ostream& f,Int4 * reft ,Int4 nbInT) const
+  { 
+    const Triangles & Th= *this;
+    // do triangle and quad 
+    if(verbosity>9) 
+      cout  << " In Triangles::WriteElements " << endl
+	    << "   Nb of In triangles " << nbInT-Th.NbOfQuad*2 << endl
+	    << "   Nb of Quadrilaterals " <<  Th.NbOfQuad << endl
+	    << "   Nb of in+out+quad  triangles " << Th.nbt << " " << nbInT << endl;
+	 
+    Int4 k=nbInT-Th.NbOfQuad*2;
+    Int4 num =0;
+    if (k>0) {
+      f << "\nTriangles\n"<< k << endl;
+      for(Int4 i=0;i<Th.nbt;i++)
+	{ 
+	  Triangle & t = Th.triangles[i];
+	  if (reft[i]>=0 && !( t.Hidden(0) || t.Hidden(1) || t.Hidden(2) ))
+	    { k--;
+	      f << Th.Number(t[0])+1 << " " << Th.Number(t[1])+1 
+		<< " "  << Th.Number(t[2])+1  << " " << Th.subdomains[reft[i]].ref << endl;
+	      reft[i] = ++num;
+	    }
+	}
+    } 
+    if (Th.NbOfQuad>0) {
+      f << "\nQuadrilaterals\n"<<Th.NbOfQuad << endl;
+      k = Th.NbOfQuad;
+      for(Int4 i=0;i<Th.nbt;i++)
+	{ 
+	  Triangle & t = Th.triangles[i];
+	  Triangle * ta; // 
+	  Vertex *v0,*v1,*v2,*v3;
+	  if (reft[i]<0) continue;
+	  if ((ta=t.Quadrangle(v0,v1,v2,v3)) !=0 && &t<ta)
+	    { 
+	      k--;
+	      f << Th.Number(v0)+1 << " " << Th.Number(v1)+1  << " "  
+		<< Th.Number(v2)+1 << " "  << Th.Number(v3)+1 << " "  
+		<< Th.subdomains[reft[i]].ref << endl;
+	      reft[i] = ++num;
+	      reft[Number(ta)] = num;
+	    }
+	}
+      assert(k==0);
+    }
+    // warning reft is now the element number 
+  }
+
+  ostream& operator <<(ostream& f, const   Triangles & Th) 
+  {
+    //  Th.FindSubDomain();
+    // warning just on say the class is on the disk
+    //  ((Triangles *) &Th)->OnDisk = 1;
+
+    Int4 * reft = new Int4[Th.nbt];
+    Int4 nbInT =    Th.ConsRefTriangle(reft);
+    {
+      f << "MeshVersionFormatted 0" <<endl;
+      f << "\nDimension\n"  << 2 << endl;
+      f << "\nIdentifier\n" ;
+      WriteStr(f,Th.identity);
+      f << "\n\nGeometry\n" ;
+      if( Th.Gh.OnDisk)
+	WriteStr(f,Th.Gh.name),     f <<endl;
+      else
+	{ // empty file name -> geom in same file
+	  f << "\"\"" << endl << endl;
+	  f << "# BEGIN of the include geometry file because geometry is not on the disk"
+	    << Th.Gh << endl;
+	  f << "End" << endl 
+	    << "# END of the include geometrie file because geometry is not on the disk"
+	    << endl ;
+	}
+    }
+    { 
+      f.precision(12);
+      f << "\nVertices\n" << Th.nbv <<endl;
+      for (Int4 i=0;i<Th.nbv;i++)
+	{
+	  Vertex & v =  Th.vertices[i];
+	  f << v.r.x << " " << v.r.y << " " << v.ref() << endl;
+	}
+    }
+    Int4 ie; 
+    {
+      f << "\nEdges\n"<< Th.nbe << endl;
+      for(ie=0;ie<Th.nbe;ie++)
+	{ 
+	  Edge & e = Th.edges[ie];
+	  f << Th.Number(e[0])+1 << " " << Th.Number(e[1])+1;
+	  f << " " << e.ref <<endl;
+	}
+      if(Th.NbCrackedEdges)
+	{
+	  f << "\nCrackedEdges\n"<< Th.NbCrackedEdges << endl;
+	  for( ie=0;ie<Th.NbCrackedEdges;ie++)
+	    { 
+	      Edge & e1 = *Th.CrackedEdges[ie].a.edge;
+	      Edge & e2 = *Th.CrackedEdges[ie].b.edge;
+	      f << Th.Number(e1)+1 << " " << Th.Number(e2)+1 <<endl;;
+	    }
+	}
+    }
+
+    Th.WriteElements(f,reft,nbInT);
+    {
+      f << "\nSubDomainFromMesh\n" << Th.NbSubDomains<< endl ;
+      for (Int4 i=0;i<Th.NbSubDomains;i++)
+	f << 3 << " " << reft[Th.Number(Th.subdomains[i].head)] << " " << 1 << " " 
+	  <<  Th.subdomains[i].ref << endl;
+     
+    }
+    if (Th.Gh.NbSubDomains)
+      {
+        f << "\nSubDomainFromGeom\n" << Th.Gh.NbSubDomains << endl ;
+	for (Int4 i=0;i<Th.NbSubDomains;i++)
+	  {  
+	    f << 2 << " " << Th.Number(Th.subdomains[i].edge)+1 << " " 
+	      <<  Th.subdomains[i].sens  << " " <<  Th.Gh.subdomains[i].ref << endl;
+	  } 
+      }
+    {
+      f << "\nVertexOnGeometricVertex\n"<<  Th.NbVerticesOnGeomVertex << endl;
+      for (Int4 i0=0;i0<Th.NbVerticesOnGeomVertex;i0++)
+	{
+	  VertexOnGeom & v =Th.VerticesOnGeomVertex[i0];
+	  assert(v.OnGeomVertex()) ;
+	  f << " " << Th.Number(( Vertex *)v)+1  
+	    << " " << Th.Gh.Number(( GeometricalVertex * )v)+1 
+	    << endl;
+	}
+    }
+    { 
+      f << "\nVertexOnGeometricEdge\n"<<  Th.NbVerticesOnGeomEdge << endl;
+      for (Int4 i0=0;i0<Th.NbVerticesOnGeomEdge;i0++)
+	{
+	  const VertexOnGeom & v =Th.VerticesOnGeomEdge[i0];
+	  assert(v.OnGeomEdge()) ;   
+	  f << " " << Th.Number((Vertex * )v)+1  ;
+	  f << " " << Th.Gh.Number((const  GeometricalEdge * )v)+1  ;
+	  f << " " << (Real8 ) v << endl;
+	}
+    }
+    {
+      Int4 i0,k=0;
+
+      for (i0=0;i0<Th.nbe;i0++)
+	if ( Th.edges[i0].on ) k++;
+     
+      f << "\nEdgeOnGeometricEdge\n"<< k << endl;
+      for (i0=0;i0<Th.nbe;i0++)
+	if ( Th.edges[i0].on ) 
+	  f << (i0+1) << " "  << (1+Th.Gh.Number(Th.edges[i0].on)) <<  endl;
+      if (Th.NbCrackedEdges)
+	{
+	  f << "\nCrackedEdges\n"<< Th.NbCrackedEdges << endl;	  
+	  for(i0=0;i0< Th.NbCrackedEdges; i0++) 
+	    {
+	      f << Th.Number(Th.CrackedEdges[i0].a.edge) << " " ;
+	      f  << Th.Number(Th.CrackedEdges[i0].b.edge) << endl;
+	    }
+	}
+    }  
+    if (&Th.BTh != &Th && Th.BTh.OnDisk && Th.BTh.name) 
+      {
+	int *mark=new int[Th.nbv];
+	Int4 i;
+	for (i=0;i<Th.nbv;i++)
+	  mark[i]=-1;
+	f << "\nMeshSupportOfVertices\n" <<endl;
+	WriteStr(f,Th.BTh.name);
+	f <<endl;
+	f << "\nIdentityOfMeshSupport" << endl;
+	WriteStr(f,Th.BTh.identity);
+	f<<endl;
+
+	f << "\nVertexOnSupportVertex" << endl;
+	f<< Th.NbVertexOnBThVertex << endl;
+	for(i=0;i<Th.NbVertexOnBThVertex;i++) {
+	  const VertexOnVertex & vov = Th.VertexOnBThVertex[i];
+	  Int4 iv = Th.Number(vov.v);
+	  mark[iv] =0;
+	  f << iv+1<< " " << Th.BTh.Number(vov.bv)+1 << endl;}
+
+	f << "\nVertexOnSupportEdge" << endl;
+	f << Th.NbVertexOnBThEdge << endl;
+	for(i=0;i<Th.NbVertexOnBThEdge;i++) {
+	  const VertexOnEdge & voe = Th.VertexOnBThEdge[i];
+	  Int4 iv = Th.Number(voe.v);
+	  //	 assert(mark[iv] == -1]);
+	  mark[iv] = 1;
+	  f << iv+1 << " " << Th.BTh.Number(voe.be)+1 << " " << voe.abcisse <<  endl;}
+       
+	f << "\nVertexOnSupportTriangle" << endl;   
+	Int4 k = Th.nbv -  Th.NbVertexOnBThEdge - Th.NbVertexOnBThVertex;
+	f << k << endl;
+	//       Int4 kkk=0;
+	CurrentTh=&Th.BTh;
+	for (i=0;i<Th.nbv;i++) 
+	  if (mark[i] == -1) {
+	    k--;
+	    Icoor2 dete[3];
+	    I2 I = Th.BTh.toI2(Th.vertices[i].r);
+	    Triangle * tb = Th.BTh.FindTriangleContening(I,dete);
+	    if (tb->link) // a true triangle
+	      {
+		Real8 aa= (Real8) dete[1]/ tb->det, bb= (Real8) dete[2] / tb->det;
+		f << i+1 << " " << Th.BTh.Number(tb)+1 << " " << aa << " " << bb << endl ;
+	      }
+	    else 
+	      {
+		double aa,bb,det[3];
+		TriangleAdjacent ta=CloseBoundaryEdgeV2(I,tb,aa,bb);
+		int k = ta;
+		det[VerticesOfTriangularEdge[k][1]] =aa;
+		det[VerticesOfTriangularEdge[k][0]] = bb;
+		det[OppositeVertex[k]] = 1- aa -bb;
+		Triangle * tb = ta;
+		f << i+1 << Th.BTh.Number(tb)+1 << " " << det[1] << " " << det[2] <<endl;
+	      }
+	  }
+	assert(!k);
+	delete [] mark;
+	 
+
+      }
+    f << "\nEnd" << endl;
+    //  Th.ConsLinkTriangle();
+    delete [] reft;
+    return f;
+   
+  }
+
+
+
+  void Geometry::Write(const char * filename)
+  {
+    ofstream f(filename);
+    if (f)
+      {
+	if(verbosity>1)
+	  cout << "  -- write geometry in file " << filename << endl;
+	if (name) delete name;
+	name = new char[strlen(filename)+1];
+	strcpy(name,filename);
+	OnDisk =1;
+	f << *this;
+      }
+  }
+
+  ostream& operator <<(ostream& f, const   Geometry & Gh) 
+  {
+    Int4  NbCorner=0;
+    {
+      f << "MeshVersionFormatted 0" <<endl;
+      f << "\nDimension\n"  << 2 << endl;
+      //     f << "\nIdentifier\n" ;
+      //     WriteStr(f,Gh.identity);
+      //     f <<endl;
+    }
+    int nbreqv=0;
+    { 
+     
+      f.precision(12);
+      f << "\nVertices\n" << Gh.nbv <<endl;
+      for (Int4 i=0;i<Gh.nbv;i++)
+	{
+	  GeometricalVertex & v =  Gh.vertices[i];
+	  if (v.Required()) nbreqv++;
+	  f << v.r.x << " " << v.r.y << " " << v.ref() << endl;
+	  if (v.Corner()) NbCorner++;
+	}
+    }
+   
+    int nbcracked=0;
+
+    {
+      int nbreq=0;
+      f << "\nEdges\n"<< Gh.nbe << endl;
+      for(Int4 ie=0;ie<Gh.nbe;ie++)
+	{ 
+	 
+	  GeometricalEdge & e = Gh.edges[ie];
+	  if (e.Required()) nbreq++;
+	  if (e.Cracked()) { 
+	    Int4 ie1 = Gh.Number(e.link);
+	    if (ie <= ie1)  ++nbcracked;}
+	  f << Gh.Number(e[0])+1 << " " << Gh.Number(e[1])+1;
+	  f << " " << e.ref <<endl;
+	}
+     
+      if (nbcracked)
+	{
+	  f << "\nCrackedEdges\n"<< nbcracked<< endl;
+	  for(Int4 ie=0;ie<Gh.nbe;ie++)
+	    {
+	      GeometricalEdge & e = Gh.edges[ie];
+	      if (e.Cracked()) { 
+		Int4  ie1 = Gh.Number(e.link);
+		if (ie <= ie1)  f << ie+1 << " " << ie1+1<< endl;
+	      }
+	    }
+	}
+      if(nbreq)
+	{
+	  f << "\nRequiredEdges\n"<< nbreq<< endl;
+	  for(Int4 ie=0;ie<Gh.nbe;ie++)
+	    {
+	      GeometricalEdge & e = Gh.edges[ie];
+	      if (e.Required()) 
+		f << ie+1 << endl;
+	    }
+	}
+     
+     
+     
+    }
+
+    f << "\nAngleOfCornerBound\n" 
+      << Gh.MaximalAngleOfCorner*180/Pi << endl;
+    if (NbCorner) 
+      {
+	f << "\nCorners\n" << NbCorner << endl;
+	for (Int4 i=0,j=0;i<Gh.nbv;i++)
+	  {
+	    GeometricalVertex & v =  Gh.vertices[i];
+	    if (v.Corner()) 
+	      j++,f << Gh.Number(v)+1 << (j % 5 ? ' ' : '\n');
+	  }
+        
+      
+      }
+
+    if(nbreqv)
+      {
+	f << "\nRequiredVertices\n"<< nbreqv<< endl;
+	for (Int4 j=0,i=0;i<Gh.nbv;i++)
+	  {
+	    GeometricalVertex & v =  Gh.vertices[i];
+	    
+	    if (v.Required()) 
+	      j++,f << i+1 << (j % 5 ? ' ' : '\n');
+	  }
+	f << endl;
+      }
+    
+    { 
+      Int4 i;
+      f << "\nSubDomainFromGeom\n" ;
+      f << Gh.NbSubDomains<< endl;
+      for (i=0;i<Gh.NbSubDomains;i++) 
+	f << "2 " << Gh.Number(Gh.subdomains[i].edge)+1 << " " << Gh.subdomains[i].sens 
+	  << " " << Gh.subdomains[i].ref << endl;        
+    }
+    {
+      Int4 n=0,i;
+
+      for(i=0;i< Gh.nbe;i++)
+	{
+	  if(Gh.edges[i].TgA() && Gh.edges[i][0].Corner() ) 
+	    n++;
+	  if(Gh.edges[i].TgB() && Gh.edges[i][1].Corner() ) 
+	    n++;
+	}
+      if (n) {
+	f << "TangentAtEdges " << n << endl;
+	for(i=0;i< Gh.nbe;i++)
+	  {
+	    if (Gh.edges[i].TgA() && Gh.edges[i][0].Corner() ) 
+	      f << i+1 << " 1 " << Gh.edges[i].tg[0].x 
+		<< " " << Gh.edges[i].tg[0].y << endl;
+	    if (Gh.edges[i].TgB() && Gh.edges[i][1].Corner() ) 
+	      f << i+1 << " 2 " << Gh.edges[i].tg[1].x 
+		<< " " << Gh.edges[i].tg[1].y << endl;
+	  }
+	 
+      }}
+    //  f << " Not Yet Implemented" << endl;
+     
+    return f;
+  }
+
+
+} // end of namespace bamg 
diff --git a/src/bamglib/Meshgibbs.cpp b/src/bamglib/Meshgibbs.cpp
new file mode 100644
index 0000000..8612abf
--- /dev/null
+++ b/src/bamglib/Meshgibbs.cpp
@@ -0,0 +1,1063 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "vect.h"
+
+#define mmax(a,b)(a>b?a:b)
+#define mmin(a,b)(a<b?a:b)
+#define ffalse 0
+#define ttrue 1
+
+/*  -- translated by f2c (version of 23 May 1992  14:18:33).
+   You must link the resulting object file with the libraries:
+	-lF77 -lI77 -lm -lc   (in that order)
+*/
+
+
+#define integer long
+#define logical long
+
+int gibbs1_(integer* n,integer*  record,integer*  ptvois);
+int gibbs2_(integer* n,integer*  record,integer*  criter);
+int gibbsa_(integer* n,integer*  ptvois,integer*  vois,integer*  r,integer*  m,
+             integer*  nv,integer*  nx,integer*  ny,integer*  nn,integer*  w1,integer*  w2, 
+	integer* pfold,integer*  pfnew,integer*  impre,integer*  nfout);
+int gibbsb_(integer* x,integer*  y,integer*  n,integer*  ptvois,
+						integer*  vois,integer*  nx,integer*  ny,integer*  nv,integer*  nn,integer*  m,
+						integer*  wh,integer*  wl,integer* r, integer* impre, integer* nfout);
+int gibbsc_(integer* nz,integer*  nv,integer*  niveau,integer*  n,integer* );
+int gibbsd_(integer* racine,integer*  n,integer*  ptvois,integer*  
+							vois,integer*  nv,integer*  r,integer*  niveau);
+int gibbst_(integer* n,integer*  p,integer*  nv,integer*  nn,integer*  ptvois,integer*  vois,
+						integer*  m,integer*  r,integer*  new_,integer*  option, 
+						integer* pfnew,integer*  impre,integer*  nfout);
+
+/* Subroutine */ int gibbs1_(integer* n,integer*  record,integer*  ptvois)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer crit, i, j, l, r, rec;
+
+/* -----------------------------------------------------------------------
+ */
+/*     routine appele par gibbs0 */
+/* -----------------------------------------------------------------------
+ */
+/*     but: trie record (ensemble de n sommet) telle que l'ordre des somm 
+*/
+/*     soit croissant (ordre du sommet i est ptvois(i+1)-ptvois(i)) */
+/* -----------------------------------------------------------------------
+ */
+
+    /* Parameter adjustments */
+    --ptvois;
+    --record;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    l = *n / 2 + 1;
+    r = *n;
+L2:
+    if (l <= 1) {
+	goto L20;
+    }
+    --l;
+    rec = record[l];
+    crit = ptvois[record[l] + 1] - ptvois[record[l]];
+    goto L3;
+L20:
+    rec = record[r];
+    crit = ptvois[record[r] + 1] - ptvois[record[r]];
+    record[r] = record[1];
+    --r;
+    if (r == 1) {
+	goto L999;
+    }
+L3:
+    j = l;
+L4:
+    i = j;
+    j <<= 1;
+    if ((i__1 = j - r) < 0) {
+	goto L5;
+    } else if (i__1 == 0) {
+	goto L6;
+    } else {
+	goto L8;
+    }
+L5:
+    if (ptvois[record[j] + 1] - ptvois[record[j]] < ptvois[record[j + 1] + 1] 
+	    - ptvois[record[j + 1]]) {
+	++j;
+    }
+L6:
+    if (crit >= ptvois[record[j] + 1] - ptvois[record[j]]) {
+	goto L8;
+    }
+    record[i] = record[j];
+    goto L4;
+L8:
+    record[i] = rec;
+    goto L2;
+L999:
+    record[1] = rec;
+    return 0;
+} /* gibbs1_ */
+
+/* Subroutine */ int gibbs2_(integer* n,integer*  record,integer*  criter)
+{
+    static integer crit, i, j, l, r, rec;
+
+
+/*     trie record selon les valeurs de criter(record(.)) croissantes */
+
+
+    /* Parameter adjustments */
+    --criter;
+    --record;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    l = *n / 2 + 1;
+    r = *n;
+L2:
+    if (l <= 1) {
+	goto L20;
+    }
+    --l;
+    rec = record[l];
+    crit = criter[rec];
+    goto L3;
+L20:
+    rec = record[r];
+    crit = criter[rec];
+    record[r] = record[1];
+    --r;
+    if (r == 1) {
+	goto L999;
+    }
+L3:
+    j = l;
+L4:
+    i = j;
+    j <<= 1;
+    if (j - r < 0) {
+	goto L5;
+    } else if (j == r) {
+	goto L6;
+    } else {
+	goto L8;
+    }
+L5:
+    if (criter[record[j]] < criter[record[j + 1]]) {
+	++j;
+    }
+L6:
+    if (crit >= criter[record[j]]) {
+	goto L8;
+    }
+    record[i] = record[j];
+    goto L4;
+L8:
+    record[i] = rec;
+    goto L2;
+L999:
+    record[1] = rec;
+    return 0;
+} /* gibbs2_ */
+
+/* Subroutine */ 
+int gibbsa_(integer* n,integer*  ptvois,integer*  vois,integer*  r,integer*  m,
+             integer*  nv,integer*  nx,integer*  ny,integer*  nn,integer*  w1,integer*  w2, 
+	integer* pfold,integer*  pfnew,integer*  impre,integer*  nfout)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4;
+
+    /* Builtin functions */
+    /* Subroutine */ int s_stop();
+
+    /* Local variables */
+    static integer nbcc, degi, bold, bnew, i, j, k, p, degre, x, y, p1, p2;
+/*    extern  Subroutine  int gibbs1_();*/
+    static integer pf;
+/*    extern  Subroutine int gibbsb_(), gibbsd_(), gibbst_();*/
+    static integer nbpass, niveau, pf1, option, old, new_, opt, new1;
+
+/* -----------------------------------------------------------------------
+ */
+/*  but: calculer une renumerotation des sommets d'un graphe defini par: 
+*/
+/*     par la methode de gibbs */
+/* -----------------------------------------------------------------------
+ */
+/*  entree */
+/* -------- */
+/*     n = nb de sommet du graphe */
+/*      les voisins d'un sommet i ont pour numero : */
+/*     ( vois(j) , j=ptvois(i),ptvois(i+1)-1 ) */
+
+/*     impre   parametre d'impression */
+/*     nfout   numero du fichier pour impression */
+
+/*  sortie */
+/*  ------ */
+/*     r(1:n) tableau donnant la nouvelle numerotation: */
+/*       r(i) = nouveau numero du sommet i */
+/*     pfolf = ancien  profile */
+/*     pfnew = nouveau profile */
+
+/*  tableau de travail : */
+/*  -------------------- */
+/*     m(n) */
+/*     nv(0:n+n) */
+/*     nx(n) */
+/*     ny(n) */
+/*     nn(0:n) */
+/*     w1(n) */
+/*     w2(n) */
+
+/* -----------------------------------------------------------------------
+ */
+/*     programmeur f. hecht  le 3/02/1987 */
+/* -----------------------------------------------------------------------
+ */
+
+/*     tri des voisins d'un sommet du graphe par degre croissant */
+/* --------------------------------------------------------------- */
+    /* Parameter adjustments */
+    --w2;
+    --w1;
+    --ny;
+    --nx;
+    --m;
+    --r;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    p2 = ptvois[1] - 1;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	p1 = p2 + 1;
+	p2 = ptvois[i + 1] - 1;
+	i__2 = p2 - p1 + 1;
+	gibbs1_(&i__2, &vois[p1], &ptvois[1]);
+/*       if(impre.le.-9) then */
+/*        write (nfout,*) 'les voisin de ',i,'sont: ', (vois(j),j=p1,p
+2) */
+/*       endif */
+/* L10: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	r[i] = 0;
+/* L20: */
+    }
+/*     boucle sur les composante connexe du graphe */
+    new_ = 0;
+    nbcc = 0;
+L30:
+    if (new_ < *n) {
+	++nbcc;
+/*       recherche d'une racine y (un sommet non numerote) de degree m
+ini */
+	y = 0;
+	degre = *n + 1;
+	i__1 = *n;
+	for (i = 1; i <= i__1; ++i) {
+	    if (r[i] <= 0) {
+		degi = ptvois[i + 1] - ptvois[i];
+		if (degi < degre) {
+		    degre = degi;
+		    y = i;
+		}
+	    }
+/* L40: */
+	}
+	if (y == 0) {
+	   return -3;/*  s_stop("fatal erreur  gibbs 2 : pb racine", 33L); */
+	}
+	gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+	nbpass = 0;
+L50:
+	++nbpass;
+	x = y;
+	p = niveau;
+	k = 0;
+	i__1 = nv[p + 1];
+	for (i = nv[p] + 1; i <= i__1; ++i) {
+	    ++k;
+	    m[k] = nv[i];
+/* L60: */
+	}
+	gibbs1_(&k, &m[1], &ptvois[1]);
+	i__1 = k;
+	for (i = 1; i <= i__1; ++i) {
+	    y = m[i];
+	    gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+	    if (niveau > p) {
+		goto L50;
+	    }
+/* L70: */
+	}
+	y = m[1];
+/*        if(impre.lt.0) then */
+/*          write(nfout,*) */
+/*     +  '    nb de pass pour trouver le pseudo diametre',nbpass */
+/*     +         ,' x=',x,',y=',y,' de la composante connexe ',nbcc */
+
+/*          write (nfout,*) ('-',i=1,78) */
+/*        endif */
+/*       optimisation de la descendance de la numerotation */
+/*       ------------------------------------------------- */
+	gibbsb_(&x, &y, n, &ptvois[1], &vois[1], &nx[1], &ny[1], nv, nn, &m[1]
+		, &w1[1], &w2[1], &r[1], impre, nfout);
+
+/*     renumerotation de cuthill mac kee avec la meilleur des 4 option
+s */
+/*     --------------------------------------------------------------
+--- */
+	pf = 1073741824;
+	option = -2;
+	new1 = new_;
+	for (opt = -2; opt <= 2; ++opt) {
+	    new_ = new1;
+	    if (opt != 0) {
+		gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], &
+			new_, &opt, &pf1, impre, nfout);
+		if (pf1 < pf) {
+		    pf = pf1;
+		    option = opt;
+		}
+	    }
+/* L80: */
+	}
+/*        if(impre.ne.0) write (nfout,*) '    on a choisi l''option ',
+ */
+/*     +             option,', new =',new */
+	new_ = new1;
+	gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], &new_, &
+		option, &pf1, impre, nfout);
+	goto L30;
+    }
+/*      if(impre.ne.0) write(nfout,*) */
+/*     +       '   nb de composante connexe du graphe =',nbcc */
+/*     calcul du profile */
+    *pfold = 0;
+    *pfnew = 0;
+    bnew = 0;
+    bold = 0;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	old = i;
+	new_ = r[i];
+	i__2 = ptvois[i + 1] - 1;
+	for (j = ptvois[i]; j <= i__2; ++j) {
+/* Computing MIN */
+	    i__3 = old, i__4 = vois[j];
+	    old = mmin(i__3,i__4);
+/* Computing MIN */
+	    i__3 = new_, i__4 = r[vois[j]];
+	    new_ = mmin(i__3,i__4);
+/* L100: */
+	}
+	*pfold = *pfold + i - old + 1;
+/* Computing MAX */
+	i__2 = bold, i__3 = i - old + 1;
+	bold = mmax(i__2,i__3);
+	*pfnew = *pfnew + r[i] - new_ + 1;
+/* Computing MAX */
+	i__2 = bnew, i__3 = r[i] - new_ + 1;
+	bnew = mmax(i__2,i__3);
+/* L110: */
+    }
+/*      if(impre.ne.0) then */
+/*        write(nfout,*)'profile  old  = ',pfold,', profile  new = ',pfnew
+ */
+/*        write(nfout,*)'1/2 bande old = ',bold ,', 1/2 band new = ',bnew 
+*/
+/*      endif */
+return 0;
+} /* gibbsa_ */
+
+/* Subroutine */ int gibbsb_(integer* x,integer*  y,integer*  n,integer*  ptvois,
+integer*  vois,integer*  nx,integer*  ny,integer*  nv,integer*  nn,integer*  m,
+integer*  wh,integer*  wl,integer* r, integer* impre, integer* nfout)
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static  flag_;
+    static integer i, j, k, p, s, h0, i1, l0, i2;
+/*    extern  Subroutine  int gibbs1_(); */
+    static integer lg;
+/*    extern  Subroutine  int gibbsd_(), gibbsc_();*/
+    static integer niveau, mxcanx, mxcany, nbc;
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ */
+/* ...................................................................... 
+*/
+/*     attention on met la descente optimiser dans r <0 ou nulle */
+/* .......................................................................
+ */
+    /* Parameter adjustments */
+    --r;
+    --m;
+    --ny;
+    --nx;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    gibbsd_(y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+    gibbsc_(&ny[1], nv, &niveau, n, &mxcany);
+    gibbsd_(x, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+    p = niveau;
+    gibbsc_(&nx[1], nv, &niveau, n, &mxcanx);
+    flag_ = ffalse;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nx[i] + ny[i] == p) {
+	    r[i] = -nx[i];
+	} else if (nx[i] >= 0) {
+	    flag_ = ttrue;
+	    r[i] = -1073741824;
+	} else {
+	    if (r[i] <= 0) {
+		r[i] = -1073741822;
+	    }
+	}
+/* L20: */
+    }
+    if (flag_) {
+/*       calcul des composantes connexe du graphe sans les sommets de 
+nn */
+/*       ------------------------------------------------------------
+--- */
+	j = *n;
+	k = 0;
+	nbc = 0;
+	nv[nbc] = j;
+L30:
+	++k;
+	if (k <= *n) {
+	    if (r[k] == -1073741824) {
+/*           recherche de la fermeture transitive partant de k
+ */
+		++nbc;
+		i = -1;
+		s = k;
+L40:
+		++i;
+		wl[i] = ptvois[s];
+		wh[i] = ptvois[s + 1];
+		++j;
+		nv[j] = s;
+		r[s] = -1073741823;
+L50:
+		if (i >= 0) {
+		    if (wl[i] < wh[i]) {
+			s = vois[wl[i]];
+			++wl[i];
+			if (r[s] == -1073741824) {
+			    goto L40;
+			}
+			goto L50;
+		    }
+		    --i;
+		    goto L50;
+		}
+		nv[nbc] = j;
+		m[nbc] = nbc;
+	    }
+	    goto L30;
+	}
+/*        if(impre.lt.0) write(nfout,*) */
+/*     +         ' nb de composante connexe du graphe reduit =',nbc */
+
+/* --------------- fin de construction des composantes connexes------
+--- */
+/*        nv(0)=n */
+/*        if(impre.le.-10) write(nfout,5555)'nv(0:n+n) = ',(nv(i),i=0,
+n+n) */
+	gibbs1_(&nbc, &m[1], nv);
+/*        if(impre.le.-10)write(nfout,5555)'trie m =',(m(i),i=1,nbc) 
+*/
+	i__1 = p;
+	for (i = 0; i <= i__1; ++i) {
+	    nn[i] = 0;
+/* L60: */
+	}
+	i__1 = *n;
+	for (i = 1; i <= i__1; ++i) {
+	    j = -r[i];
+	    if (j >= 0 && j <= p) {
+		++nn[j];
+	    }
+/* L70: */
+	}
+
+/*       boucle sur les composante connexes par ordre croissantes */
+/*       -------------------------------------------------------- */
+	for (k = nbc; k >= 1; --k) {
+	    i = m[k];
+	    i1 = nv[i - 1] + 1;
+	    i2 = nv[i];
+	    lg = i2 - i1 + 1;
+/*         if(impre.le.-7) */
+/*     +       write(nfout,*) k,' composante ',i,',lg=',lg,',i1,i2
+=',i1,i2 */
+/*         if(impre.le.-8) */
+/*     +       write (nfout,5555)' ',(nv(i),i=i1,i2) */
+	    h0 = 0;
+	    l0 = 0;
+	    i__1 = p;
+	    for (j = 0; j <= i__1; ++j) {
+		wh[j] = nn[j];
+		wl[j] = nn[j];
+/* L90: */
+	    }
+	    i__1 = i2;
+	    for (i = i1; i <= i__1; ++i) {
+		s = nv[i];
+		++wh[nx[s]];
+		++wl[p - ny[s]];
+/* L100: */
+	    }
+	    i__1 = p;
+	    for (j = 0; j <= i__1; ++j) {
+		if (wh[j] != nn[j]) {
+/* Computing MAX */
+		    i__2 = wh[j];
+		    h0 = mmax(i__2,h0);
+		}
+		if (wl[j] != nn[j]) {
+/* Computing MAX */
+		    i__2 = wl[j];
+		    l0 = mmax(i__2,l0);
+		}
+/* L110: */
+	    }
+	    if (h0 < l0 || h0 == l0 && mxcanx <= mxcany) {
+/*           if(impre.le.-2) write(nfout,*) */
+/*     +       '         h0 = ',h0,',l0 = ',l0,'  ------- XXXX
+ --------' */
+		i__1 = i2;
+		for (i = i1; i <= i__1; ++i) {
+		    s = nv[i];
+		    r[s] = -nx[s];
+		    ++nn[-r[s]];
+/* L120: */
+		}
+	    } else {
+/*           if (impre.le.-2) write(nfout,*) */
+/*     +       '         h0 = ',h0,',l0 = ',l0,'  ------- YYYY
+ --------' */
+		i__1 = i2;
+		for (i = i1; i <= i__1; ++i) {
+		    s = nv[i];
+		    r[s] = -p + ny[s];
+		    ++nn[-r[s]];
+/* L130: */
+		}
+	    }
+/* L140: */
+	}
+    }
+/*     on met les nouveaux niveaux de la descendance optimiser dans nn */
+/*     ----------------------------------------------------------------- 
+*/
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (r[i] > 0) {
+	    nn[i] = -1;
+	} else if (r[i] == -1073741822) {
+	    nn[i] = -2;
+	} else {
+	    nn[i] = -r[i];
+	}
+/* L150: */
+    }
+/*      if(impre.le.-10)write (nfout,5555)' nn(i)=',(nn(i),i=1,n) */
+/* 5555  format('            --------   ',a,/,5(15x,10(i5)/)) */
+return 0;} /* gibbsb_ */
+
+/* Subroutine */ int gibbsc_(integer* nz,integer*  nv,integer*  niveau,integer*  n,integer*  mxz)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer i, j;
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ */
+    /* Parameter adjustments */
+    --nz;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	nz[i] = -1;
+/* L10: */
+    }
+    *mxz = 0;
+    i__1 = *niveau;
+    for (i = 0; i <= i__1; ++i) {
+/* Computing MAX */
+	i__2 = *mxz, i__3 = nv[i + 1] - nv[i];
+	*mxz = mmax(i__2,i__3);
+	i__2 = nv[i + 1];
+	for (j = nv[i] + 1; j <= i__2; ++j) {
+	    nz[nv[j]] = i;
+/* L20: */
+	}
+    }
+return 0;} /* gibbsc_ */
+
+/* Subroutine */ int gibbsd_(integer* racine,integer*  n,integer*  ptvois,integer*  vois,integer*  nv,integer*  r,integer*  niveau)
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer i, k, s, sv, stk, stk1, stk2;
+
+/* -----------------------------------------------------------------------
+ */
+/*     but construire la structure des descendant de racine  du graphe */
+/* -----------------------------------------------------------------------
+ */
+/*     sortie : */
+/*     -------- */
+/*     nv est la structure des niveaux */
+/*     les sommets du niveau (i =0,niveau_ sont defini par : */
+/*        (nv(j),j=nv(i),nv(i+1)-1) */
+
+/*     le tableau r(i) n'est modifier que sur les sommets */
+/*       de la composante connexe du graphe contenant la racine */
+
+/* -----------------------------------------------------------------------
+ */
+
+/*     on demark tout les sommets non remuneroter */
+/* -------------------------------------------------- */
+    /* Parameter adjustments */
+    --r;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (r[i] < 0) {
+	    r[i] = 0;
+	}
+/* L10: */
+    }
+
+/*    initialisation */
+
+    stk = *n - 1;
+    nv[0] = stk;
+    stk2 = stk;
+    *niveau = 0;
+    ++stk;
+    nv[stk] = *racine;
+    r[*racine] = -1;
+L20:
+    if (stk2 < stk) {
+	++(*niveau);
+	stk1 = stk2 + 1;
+	nv[*niveau] = stk;
+	stk2 = stk;
+/*        print *,' ------- niveau =',niveau,' stk=',stk1,stk2 */
+	i__1 = stk2;
+	for (k = stk1; k <= i__1; ++k) {
+	    s = nv[k];
+/*         print *,'----------------- s=',s */
+	    i__2 = ptvois[s + 1] - 1;
+	    for (i = ptvois[s]; i <= i__2; ++i) {
+/*               pour tout les sommets (sv) voisin */
+/*                d'un sommet (s) du niveau precedent */
+		sv = vois[i];
+/*          print *,' voisin =',sv */
+/*               si le sommet n'est pas marque on le marque et
+ on l'ajout */
+		if (r[sv] == 0) {
+		    ++stk;
+		    nv[stk] = sv;
+		    r[sv] = -1;
+		}
+/* L30: */
+	    }
+/* L40: */
+	}
+	goto L20;
+    }
+    --(*niveau);
+/*      call pnv(' gibbsd ',n,nv,niveau) */
+return 0;} /* gibbsd_ */
+
+
+/* Subroutine */ int gibbst_(integer* n,integer*  p,integer*  nv,integer*  nn,integer*  ptvois,integer*  vois,integer*  m,integer*  r,integer*  new_,integer*  option, 
+	integer* pfnew,integer*  impre,integer*  nfout)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4, i__5;
+
+    /* Local variables */
+    static integer nbsc, bnew, knew, step, plus, i, j, k, s, debut, i1, i2;
+/*    extern Subroutine int gibbs2_();*/
+    static integer fin;
+
+
+/*     construction de la stucture de niveau dans nv a partir de nn */
+/*     ------------------------------------------------------------ */
+    /* Parameter adjustments */
+    --r;
+    --m;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    nv[0] = *n;
+    i__1 = *p + 1;
+    for (i = 1; i <= i__1; ++i) {
+	nv[i] = 0;
+/* L150: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nn[i] >= 0) {
+	    ++nv[nn[i] + 1];
+	}
+/* L160: */
+    }
+    i__1 = *p;
+    for (i = 0; i <= i__1; ++i) {
+	nv[i + 1] += nv[i];
+/* L170: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nn[i] >= 0) {
+	    j = nn[i];
+	    ++nv[j];
+	    nv[nv[j]] = i;
+	}
+/* L180: */
+    }
+    for (i = *p; i >= 0; --i) {
+	nv[i + 1] = nv[i];
+/* L190: */
+    }
+    nv[0] = *n;
+    nbsc = nv[*p + 1] - nv[0];
+/*     --- fin de la construction ------------------------------------ */
+    if (*option == -2) {
+	i__1 = *impre - 1;
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	m[i] = *n * 3 + ptvois[i + 1] - ptvois[i];
+/* L10: */
+    }
+    if ((((int)*option) == 1)||(((int)*option) == -1)) {
+	debut = 0;
+	fin = *p;
+	step = 1;
+    } else {
+	debut = *p;
+	fin = 0;
+	step = -1;
+    }
+    i__1 = fin;
+    i__2 = step;
+    for (i = debut; i__2 < 0 ? i >= i__1 : i <= i__1; i += i__2) {
+	i1 = nv[i] + 1;
+	i2 = nv[i + 1];
+	i__3 = i2 - i1 + 1;
+	gibbs2_(&i__3, &nv[i1], &m[1]);
+	i__3 = i2;
+	for (j = i1; j <= i__3; ++j) {
+	    s = nv[j];
+	    i__4 = ptvois[s + 1] - 1;
+	    for (k = ptvois[s]; k <= i__4; ++k) {
+/* Computing MIN */
+		i__5 = m[vois[k]];
+		m[vois[k]] = mmin(i__5,j);
+/* L20: */
+	    }
+/* L30: */
+	}
+/* L40: */
+    }
+    if (*option > 0) {
+	knew = *new_;
+	plus = 1;
+    } else {
+	knew = *new_ + nbsc + 1;
+	plus = -1;
+    }
+    *new_ += nbsc;
+/*      if(option.gt.0) then */
+/*        do 60 k = debut , fin , step */
+/*          do 60 j = nv(k+1),nv(k)+1,-1 */
+/*            knew = knew + plus */
+/*            r(nv(j)) = knew */
+/* 60      continue */
+/*      else */
+    i__2 = fin;
+    i__1 = step;
+    for (k = debut; i__1 < 0 ? k >= i__2 : k <= i__2; k += i__1) {
+	i__3 = nv[k + 1];
+	for (j = nv[k] + 1; j <= i__3; ++j) {
+	    knew += plus;
+	    r[nv[j]] = knew;
+/* L70: */
+	}
+    }
+/*      endif */
+    *pfnew = 0;
+    bnew = 0;
+    i__3 = *n;
+    for (i = 1; i <= i__3; ++i) {
+	k = r[i];
+	if (k > 0) {
+	    i__1 = ptvois[i + 1] - 1;
+	    for (j = ptvois[i]; j <= i__1; ++j) {
+		if (r[vois[j]] > 0) {
+/* Computing MIN */
+		    i__2 = k, i__4 = r[vois[j]];
+		    k = mmin(i__2,i__4);
+		}
+/* L100: */
+	    }
+	    *pfnew = *pfnew + r[i] - k + 1;
+/* Computing MAX */
+	    i__1 = bnew, i__2 = r[i] - k + 1;
+	    bnew = mmax(i__1,i__2);
+	}
+/* L110: */
+    }
+/*      if(impre.lt.0.or.impre.gt.2) then */
+/*        write(nfout,*) '      option =',option,', profile =',pfnew */
+/*     +       ,', 1/2 bande =',bnew,', new=',new,', nbss composante=',nbsc
+ */
+/*      endif */
+return 0;} /* gibbst_ */
+
+/* function */ 
+int Triangles::gibbsv (integer* ptvoi,
+		       integer* vois,integer* lvois,integer* w,integer* v)
+{
+  /* System generated locals */
+  integer  i__2;
+  
+  /* Local variables */
+  integer i, j, k, T, ss, iii, ptv, ptv1;
+  integer nbss = nbv; 
+  /*--- Prepare les donees pour gibbsa en construisant ptvoi, vois, lvois -
+    ------------*/
+  /*     in */
+  /*     ---   nbnt =3 pour des triangles 2D, */
+  /* 			nbt =  nb de triangle */
+  /*    		nbss = nb de sommets */
+  /*           nsea = numeros de 3 sommets de chaque triangle (me) */
+  /*     out */
+  /*     --- 	ptvoi, vois, lvois, err */
+  /*      tableaux de travail w, v */
+  /*-----------------------------------------------------------------------
+    ----------*/
+  /* Parameter adjustments */
+  --v;
+  --w;
+  --vois;
+  --ptvoi;
+  long nt = nbt-NbOutT;
+  /* Function Body */
+  for (i = 1; i <= nbss; ++i) {
+    w[i] = -1;
+    ptvoi[i] = 0; }
+  ptvoi[nbss + 1] = 0;
+  for (i = 0; i < nt; ++i) 
+    { 
+      assert(triangles[i].link);
+      for (j = 0; j < 3; ++j)
+	{
+	  ss = Number(triangles[i][j])+1;
+	  ++ptvoi[ss + 1];
+	  w[ss] = 0;
+	}
+    }
+  
+  for (i = 1; i <= nbss; ++i) 
+    ptvoi[i + 1] += ptvoi[i];
+  
+  for (i = 0; i < nt; ++i)
+    if (triangles[i].link) 
+      for (j = 0; j < 3; ++j) 
+	{
+	  ss = Number(triangles[i][j])+1;
+	  ++ptvoi[ss];
+	  v[ptvoi[ss]] = i;
+	}
+  
+    ptv1 = 0;
+    iii = 1;
+    for (i = 1; i <= nbss; ++i) {
+      ptv = ptv1 + 1;
+      ptv1 = ptvoi[i];
+      ptvoi[i] = iii;
+      i__2 = ptv1;
+      for (j = ptv; j <= i__2; ++j) {
+	T = v[j];
+	for (k = 0; k < 3; ++k) {
+	  ss = Number(triangles[T][k])+1;  /*  nsea[k + T * nsea_dim1]; */
+	  if (w[ss] != i) {
+	    w[ss] = i;
+	    if (iii > *lvois)  return 2 ;
+	    /* print*,'pas assez de place memoire' */
+	    
+	    vois[iii] = ss;
+	    ++iii;}
+	}
+      }
+    }
+    ptvoi[nbss + 1] = iii;
+    *lvois = iii - 1;
+    return 0; /* OK */
+    return 0;} /* gibbsv_ */
+
+int Triangles::gibbs()
+/* -------- 
+	renumber vertices by gibbs method; updates triangle and edge array
+	in:   mesh  
+	out:   mesh
+ 	auxiliary arrays: ptvois,vois,r,m,nv,nx,ny,nn,w1,w2,f 
+ 	all of size nv+1 except vois (10(nv+1)) and nv (2(nv+1))
+ 	err = -1 : memory alloc pb; err = -3: fatal erreur  gibbs 2 : pb racine
+*/
+{
+  long nv = nbv;
+  long nt = nbt-NbOutT;
+    long i, j, pfold, pfnew;
+    long* ptvois=NULL;
+    long* vois=NULL;
+    long* nn =NULL;
+    long* r =NULL;
+    long* m =NULL;
+    long* nnv =NULL;
+    long* nx =NULL;
+    long* ny =NULL;
+    long* w1 =NULL;
+    long* w2=NULL;
+    long nbvoisin =  10*nv;
+    long printint=0, iodev=6;
+    int err=0;
+    ptvois = new long[nv+1]; 		//(long*)calloc((long)(nv + 1) , sizeof(long));
+    nn = 	 new long[3*nt]; 			//(long*)calloc(3 * nt ,sizeof(long));
+    vois = 	 new long[nbvoisin+10];	//(long*)calloc((long)(nbvoisin + 10) , sizeof(long)); 
+    r = 	 new long[nv+1];				//(long*)calloc((long)(nv + 1) , sizeof(long));
+    if((!ptvois)||(!nn)||(!vois)||(!r)) return -1;
+    err = gibbsv(ptvois,vois,&nbvoisin,r,nn) ;
+    delete [] nn;					// free(nn);
+    if(err==0)
+      {
+	m = new long[nv+1];
+	nn = new long[nv+1];
+	nnv = new long[(nv+1)<<1];
+	nx = new long[nv+1];
+	ny = new long[nv+1];
+	w1 = new long[nv+1];
+	w2 = new long[nv+1];
+	long lnv = nv;
+	err = gibbsa_ (&lnv, ptvois, vois, r, m, nnv, nx, ny, nn, w1, w2, &pfold, &pfnew,
+		      &printint, &iodev);
+	delete [] m;
+	delete [] nnv;
+	delete [] nn;
+	delete [] nx;
+	delete [] ny;
+	delete [] w1;
+	delete [] w2;
+      }
+    
+    delete [] vois;
+  delete [] ptvois;
+  /*          
+	      if (err == 0 && (pfnew <= pfold))
+	      {
+	      A<bVertex> f(nv);
+	      for (i = 0; i < nv; ++i)
+	      {	f[i].x = v[i].x;
+	      f[i].y = v[i].y;
+	      f[i].where = v[i].where;
+	      }
+	      for (i = 0; i < nv; ++i)
+	      {	v[r[i] - 1].x = f[i].x;
+	 		v[r[i] - 1].y = f[i].y;
+	 		v[r[i] - 1].where = f[i].where;
+			}
+			
+       for (j = 0; j < nt; ++j)  // updates triangle array
+       for (i = 0; i < 3; i++)
+       t[j].v[i] = &v[r[no(t[j].v[i])] - 1];
+       
+       for (j = 0; j < ne; ++j)	// updates edge array
+       {
+	   		e[j].in = &v[r[no(e[j].in)] - 1];
+	   		e[j].out = &v[r[no(e[j].out)] - 1];
+			}
+			f.destroy();
+       if (!NumThinGrid) 
+       {  NumThinGrid= new int [nv];
+       for (i=0;i<nv;i++) NumThinGrid[i]=i;// Same numbering 
+       }
+       for (i=0;i<nv;i++) NumThinGrid[i]=r[NumThinGrid[i]]-1;  
+       
+       }
+  */
+  delete [] r;
+  return err;
+} 
+			
+/*  message d'erreur:         *err = 2;    print*,'pas assez de place memoire'   */
diff --git a/src/bamglib/Meshio.cpp b/src/bamglib/Meshio.cpp
new file mode 100644
index 0000000..6e7ac40
--- /dev/null
+++ b/src/bamglib/Meshio.cpp
@@ -0,0 +1,373 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "meshtype.h"
+#include "Meshio.h"
+namespace bamg {
+
+const char *OFortranUnFormattedFile::unkown("unkown file name");
+void (*MeshIstreamErrorHandler)(ios & ) =0;
+///////////////////////////////////////////////////////////
+ void WriteStr(ostream & out,char * str)
+{ 
+  int i=0;
+  char c;
+  out << '"' ;
+  while (i++,c=*str++) {
+   if (i==70) 
+      cout << " //\n",i=0;
+   if (c == '"') out << "\"\"" ;
+   else out << c ;}
+ out << '"' ;
+}
+///////////////////////////////////////////////////////////
+double * ReadbbFile(const char * file,long & nbsol,long & lsol,const int typesol,const int dim)
+{
+
+  MeshIstream frbb(file);
+  int dimlu,typesollu;
+  long i;
+ double *sol =0;
+  frbb >>    dimlu >> nbsol >> lsol >> typesollu ;
+  if(typesol != typesollu )
+    { 
+      cerr << " incorrect type of solution (read) " << typesollu << " != (wanted) " <<  typesol << endl;
+      cerr << "  or       dim  of solution (read) " << dimlu  << " != (wanted) " <<  dim << endl;
+      nbsol=0;
+      lsol=0;
+    }
+  else
+    {
+      sol = new double[lsol*nbsol];
+      double *s=sol;
+      for(  i=0;i<lsol;i++)
+	for (long j=0;j<nbsol;j++)
+	  frbb >>  *s++ ;
+      //      frbb.close();
+    }
+
+  
+  return sol;
+}
+
+///////////////////////////////////////////////////////////
+double * ReadBBFile(const char * file,long & nbsol,long & lsol,int *& typesols,
+  const int dim,const int typesol)
+{
+
+  MeshIstream frbb(file);
+  int dimlu,typesollu;
+  typesols = 0;
+  long i,n=0;
+  double *sol =0;
+  int sizeoftype[] = { 1, dim ,dim * (dim+1) / 2, dim * dim } ;
+  // char * charoftype[] = {  "Scalar" , "dim Vector" ,"dim x dim Sym-Matric","dim x dim Full-Matric" } ;
+  frbb >>    dimlu >> nbsol ;
+  typesols = new int [nbsol] ;
+  for (i=0;i<nbsol;i++)
+    {
+     frbb >> typesols[i];
+     typesols[i]--;
+     if (typesols[i]<0 || typesols[i]>= 4)
+       {
+	 cerr << " Error reading BBFile the type solution " << i+1 << " is " << typesols[i]+1 
+	      << " is not in [1..4] " << endl;
+	   frbb.ShowIoErr(998);
+	 nbsol=0;
+	 lsol=0;
+	 delete [] typesols;
+	 typesols=0;
+	 return 0; 
+       }
+     n += sizeoftype[ typesols[i]];
+    }
+  frbb >> lsol >> typesollu ;
+  if(typesol != typesollu )
+    { 
+      cerr << " incorrect type of solution (read) " << typesollu << " != (wanted) " <<  typesol << endl;
+      cerr << "  or       dim  of solution (read) " << dimlu  << " != (wanted) " <<  dim << endl;
+      frbb.ShowIoErr(999);
+      nbsol=0;
+      lsol=0;
+    }
+  else
+    {
+      if (verbosity> 5)
+	cout << "     read BB file " << file << "  with nbsol " << nbsol << " total nb of field = " << n << endl; 
+      if (verbosity>9) 
+	for (i=0;i<nbsol;i++)
+	  cout << "      the type of solution " << i+1 << " is " <<  sizeoftype[ typesols[i]]  
+	       << " and  the number of sub-field are " << sizeoftype[ typesols[i]] << endl; 
+      sol = new double[lsol*n];
+      double *s=sol;
+      for(  i=0;i<lsol;i++)
+	for (long j=0;j<n;j++)
+	  frbb >>  *s++ ;
+      //      frbb.close();
+    }
+
+  
+  return sol;
+}
+
+
+void MeshIstream::ShowIoErr(int s) {
+  LineError = 1;
+  if (CurrentFile)
+    cerr << " In  file " <<  CurrentFile ;
+  cerr << ", Erreur Lecture "  << s << 
+    ", good="  << (s & ios::goodbit) <<
+    ", bad=" << (s & ios::badbit) <<
+    ", fail=" << (s & ios::failbit) <<
+    ", eof=" << (s & ios::eofbit) << " Line " << LineNumber <<
+    endl;
+  if(!in.eof()) 
+    {
+      in.clear(ios::goodbit);
+      int i=0;
+      char c;
+      cerr << " the next character :" ;
+      while (i++<80 && in.get(c) && (c != '\n' || i < 30 ))
+	cerr.put(c);
+      cerr << endl; 
+    }
+  if (MeshIstreamErrorHandler)
+    MeshIstreamErrorHandler(in);
+  else 
+   { 
+    in.clear(ios::failbit);
+   }
+}
+int  MeshIstream::IsString(const char* s)
+{ 
+  int n=0;
+  char c;
+  const char * ss = s;
+  while (in.get(c) && c ==' ') n++; // eat whitespace 
+  if (in.good())
+    while ( *ss && c == *ss && in.get(c) )
+      ss++; 
+
+  if (*ss) { // no 
+    if (verbosity>9) 
+      cout << "IsString: not " << s << " " << n  << "  putback " << ss-s << " :" << c  ;
+    if (in.good())
+      in.putback(c),ss--;
+    while(ss-s>0)
+      {
+	cout << *ss ;
+	in.putback(*ss--);
+      };
+    if (verbosity>9) 
+      cout << ":"<< endl;
+    return 0;}
+  else return 1;
+}
+
+ char * MeshIstream::ReadStr()
+{ 
+  static char buf[1025];
+  int  instr=0,k=0;
+  char * b=buf, bb=0, *bend=buf+1023;
+  
+  for (b=buf;b<bend &&  in.get(*b);instr && b++)
+    {
+      int kold = k;
+      if(isspace(*b))
+	{
+	  if (*b == '\n') LineNumber++;
+	  if (instr && !bb) break;
+	}
+      else if (*b == bb) 
+	{
+	  if(++k%2) b--;
+	}
+      else if( !instr) 
+	{
+	  instr =1;
+	  if  ((*b == '"') ||  (*b == '\'' ) )
+	    bb=*b--,k=0;
+	}
+      else
+	instr =1;
+      
+      if( k%2 && kold==k ) // even and fin
+	break;
+    }
+  *b=0;
+  in.clear(ios::goodbit);
+  //  cout << " l = " << b-buf << " " ;
+  char * r = new char [b-buf+1];
+  strcpy(r,buf);
+  return r ;  
+}
+///////////////////////////////////////////////////////////
+OFortranUnFormattedFile::~OFortranUnFormattedFile()
+{
+  // save the last record 
+  if (l==0) { // l rec no set --
+    l=where();
+  if (verbosity>9)
+    cout << " size of last record  = " 
+	 << l << " n = " << nb_rec << " i= " << i << endl;
+   if (!f->good()) Error(3);
+    f->seekp(i-sizeof(long));
+   if (!f->good()) Error(3);
+    f->write((char*)&l,sizeof(l)); 
+    if (!f->good()) Error(3);
+   n=j;
+  }
+
+  f->seekp(n);
+  if (!f->good()) Error(3);
+   f->write((char*) &l,sizeof(l));
+  if (!f->good()) Error(3);
+   
+  if (f && to_close) {
+    if (verbosity>9)
+      cout << "delete OFortranUnFormattedFile " << file_name 
+	   << " @end  = " << n <<  endl;
+    delete f;} f=0;
+}
+
+IFortranUnFormattedFile::~IFortranUnFormattedFile()
+{
+  if (f && to_close) {
+    if (verbosity>9)
+      cout << " delete IFortranUnFormattedFile" << file_name 
+	   << "  @end = " << n <<  endl;
+    delete f;} f=0;
+}
+
+long IFortranUnFormattedFile::Record()
+{
+  nb_rec++;
+  n += sizeof(long);
+  f->seekg(n);
+  f->read((char*)&l,sizeof(l));
+  if (!f->good()) Error(3);
+  i=j= n+sizeof(l); 
+  n +=   l + sizeof(l) ; // end 
+  if (verbosity>9)
+  cout << " Read  rec end =" << n << " l=  " << l 
+       << " current= " << j << " begin= " << i << endl;
+  return l;
+}
+
+long OFortranUnFormattedFile::Record(long ll) //
+{
+  if (j==4 && l==0) 
+    { 
+      l=ll;
+      f->seekp(0);
+      f->write((char*)&ll,sizeof(l));
+      if (!f->good()) Error(3);
+      return 0;
+    }
+  if (n>=0) 
+    {
+      if (l==0) 
+	{ // l rec no set --
+	  l=where();
+	  if (verbosity>9)
+	    cout << " set len  of rec  " << nb_rec  << " = " << l 
+		 << " @ " << i-sizeof(long) << endl;
+
+	  f->seekp(i-sizeof(long));
+	  f->write((char*)&l,sizeof(l)); 
+	  n=j;
+	}
+      f->seekp(n);
+      f->write((char*)&l,sizeof(l)); 
+      if (!f->good()) Error(3);
+    }
+  else 
+    f->seekp(0);
+  n += sizeof(long);
+  nb_rec++;
+  f->write((char*)&ll,sizeof(l));
+  if (!f->good()) Error(3);
+  
+  l=ll;
+  n +=  sizeof(long);
+  j = n;
+  i = n;
+  n +=   l;
+  if (verbosity>9)
+    cout << " Write rec end =" << n << " l=  " << l 
+	 << " current= " << j << " begin= " << i << endl;
+  return l;
+}
+void OFortranUnFormattedFile::Error(int err)
+{
+  cerr << "Fatal Error Output FortranUnFormattedFile " << endl;
+  if (err==0) 
+    cerr << "-- Error openning ";
+  else if (err==1)
+    cerr<< "-- OverFlow write ";
+  else if (err==2)
+    cerr<< "-- Erreur  write " ;
+  else if (err==3)
+    cerr<< "-- Erreur  write record info " ;
+  else 
+    cerr << " unkown err " << err ;
+
+  cerr << " Record number = "    << nb_rec << endl
+       << " read position  in file " << j << " < " << n 
+       << " =  end on record " << endl;
+  cerr << " position in the record = " << where() 
+       << " length of record = " << l <<endl;
+  cerr 	<< " file = " << file_name<< endl ;
+  MeshError(900);
+  //  throw(ErrorMesh("exit",1));
+}
+void IFortranUnFormattedFile::Error(int err)
+{
+  cerr << "Fatal Error Input FortranUnFormattedFile " << endl;
+  if (err==0) 
+    cerr << " Error openning ";
+  else if (err==1)
+    cerr<< " OverFlow read";
+  else if (err==2)
+    cerr<< " Erreur  read" ;
+  else if (err==3)
+    cerr<< " Erreur  read record info " ;
+  else 
+    cerr << " unkown err " << err ;
+
+  cerr << " Record number = "    << nb_rec << endl
+       << " read position  in file " << j << " < " << n 
+       << " =  end on record " << endl;
+  cerr << " position in the record = " << where() 
+       << " length of record = " << l <<endl;
+  cerr 	<< " file = " << file_name<< endl ;
+    MeshError(900);
+    //  throw(ErrorMesh("exit",1));
+}
+
+}// end of namespace bamg 
diff --git a/src/bamglib/Meshio.h b/src/bamglib/Meshio.h
new file mode 100644
index 0000000..7c12651
--- /dev/null
+++ b/src/bamglib/Meshio.h
@@ -0,0 +1,245 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cstdio>
+#include <iostream>
+#include <fstream>
+#include "error.hpp"
+#include <cstring>
+#include <cstdlib>
+#include <cctype>
+using namespace std;
+//  PB compilo HP aCC 
+#if defined(__hpux) || defined(__SUNPRO_CC) 
+#define IOS_OPENMODE int
+#else
+#define IOS_OPENMODE ios::openmode
+#endif
+extern  long verbosity ;
+
+namespace bamg {
+
+
+extern  void (*MeshIstreamErrorHandler)(ios & );
+
+void WriteStr(ostream & out,char * str);
+
+double * ReadbbFile(const char * file,long & nbsol,long & lsol,const int dim=2,const int typesol=2);
+double * ReadBBFile(const char * file,long & nbsol,long & lsol,int *& typesols,const int dim=2,const int typesol=2);
+// solution at vertex (P1)
+
+union Char4orLong {  char c[4];    long l;} ;
+
+class  MeshIstream {
+public:
+  istream  & in ;
+  const char * CurrentFile;
+  //  ifstream  fin;
+  int LineNumber,LineError,opened;
+
+
+  istream & cm ()//  mange les blancs et les commentaire 
+  { 
+    char c;
+    int cmm=0;
+    while ( in.get(c) &&  
+	    ( isspace(c) ?
+	      (( ( c=='\n'|| c==char(12) || c==char(15)) && (LineNumber++,cmm=0)),1) 
+	      : (cmm || (c=='#' && (cmm=1) )) ) 
+	    ) ((void ) 0);
+	   if (in.good()) in.putback(c);
+    return in;
+  }
+
+  // void rewind(){ fin.clear();fin.seekg(0);}
+    
+  void eol()// go to end of line
+  { 
+    char c;
+    while ( in.get(c) &&  ( c!='\n') && ( c!='\r')) (void) 0;
+  }
+  void ShowIoErr(int );
+  MeshIstream  & err () 
+  { 
+    if ( ! in.good() ) ShowIoErr(in.rdstate());
+    return *this;
+  }
+  //  MeshIstream(istream & i): in(i),CurrentFile(0),LineNumber(1),LineError(0) {}
+
+  MeshIstream(const char * file_name)
+    : in(*new ifstream(file_name)),CurrentFile(file_name), LineNumber(1),LineError(0) 
+  {    if (!in) {cerr << " Error Opening file " << file_name,CurrentFile=0;ShowIoErr(1);}
+  if(verbosity>4) cout << "    Openfile : " << file_name << endl;err();  }
+
+  /*  //  void close()
+  {
+      if (CurrentFile) {
+        if(verbosity>5) cout << "    Closefile: " <<  CurrentFile << endl;
+	CurrentFile=0;in.close();}
+  } */
+  int eof(){return in.eof();}
+  ~MeshIstream(){delete ∈}
+  int IsString(const char* s);
+  char * ReadStr();
+  MeshIstream&   operator>>(short& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(long& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(int& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(float& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(double& i)   { cm() >> i ;return err();}
+  MeshIstream&   operator>>(char * & i ) { i=ReadStr();return err();}
+
+};
+// Fortran unformatted file  interface ----------
+
+class IFortranUnFormattedFile {
+//  template<class T> friend IFortranUnFormattedFile & operator>>(IFortranUnFormattedFile &f,T & l);
+  istream * f;
+  long i,l,n,j,nb_rec;
+  const char * file_name;
+  int to_close;
+ public:
+  IFortranUnFormattedFile(char *name)
+    : f(new ifstream(name)),i(0),l(0),n((long)-sizeof(long)),
+      nb_rec(0),file_name(name), to_close(1)
+    { if(!*f) Error(0);}
+
+  IFortranUnFormattedFile(MeshIstream & ff)
+    : f(&ff.in),i(0),l(0),n((long)-sizeof(long)),nb_rec(0),
+      file_name(ff.CurrentFile), to_close(0)
+    { if(! *f)  Error(0);}
+  
+ ~IFortranUnFormattedFile();
+  long Record();
+  long where(){return j-i;}
+  void  read4(char *c,int );// for the fortran 77 char4
+  void  read(char * p,const size_t lg);
+  void Error(int);
+};
+
+class OFortranUnFormattedFile {
+//  template<class T> friend OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const T & l);
+  ostream * f;
+  long i,l,n,j,nb_rec;
+  const static char * unkown;
+  const char * file_name;
+  int to_close;
+ public:
+  
+  OFortranUnFormattedFile(const char *name,IOS_OPENMODE  mm=ios::trunc)
+    : f(new ofstream(name,mm)),i(0),l(0),n((long) -sizeof(long)),nb_rec(0),file_name(name), to_close(1)
+    { if(!*f) Error(0);}
+  OFortranUnFormattedFile(ostream &ff)
+    : f(&ff),i(0),l(0),n((long) -sizeof(long)),nb_rec(0),file_name(unkown), to_close(0)
+    { if(!*f) Error(0);}
+  
+  ~OFortranUnFormattedFile();
+
+  long Record(long ll=0);
+  long where(){return j-i;} 
+  void write4(const char *c,int );// for the fortran 77 char4
+  void write(const char * p,const size_t lg);
+  void Error(int );
+};
+
+/// ---------- inline -------------------------
+
+inline void  IFortranUnFormattedFile::read(char * p,const size_t lg){  
+  f->read(p,lg);
+  j+=lg;
+  if (j>n) Error(1);
+  else if (!f->good()) Error(2) ;
+}
+
+inline void  OFortranUnFormattedFile::write(const char * p,const size_t lg){  
+   f->write(p,lg);
+   j+=lg;
+   if (l && j>n)  Error(1);
+   else if (!f->good()) Error(2);
+}
+
+template<class T> inline
+IFortranUnFormattedFile & operator>>(IFortranUnFormattedFile &f,T & l)
+{  
+  f.read((char *) &l,sizeof(l));return f;
+}
+/*  bug sur sun  
+template inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const T & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+on ex les template  */ 
+
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const int  & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const long  & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const double  & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+inline 
+ OFortranUnFormattedFile & operator<<(OFortranUnFormattedFile &f,const float & l)
+ { 
+   f.write((char *) &l,sizeof(l));return f;
+ }
+
+inline void OFortranUnFormattedFile::write4(const char *c,int ll)
+{
+  int i,j;
+  Char4orLong ch4;
+  for ( i=0;i<ll;i++)
+    {
+      ch4.l=0;
+      for (j=0;j<4;j++)
+	ch4.c[j]=*c? *c++:' ';
+      *this << ch4.l;
+    }
+}
+inline void IFortranUnFormattedFile::read4(char *c,int ll)
+{
+  int i,j;
+  Char4orLong ch4;
+
+  for ( i=0;i<ll;i++)
+    {
+      *this >> ch4.l;
+      for (j=0;j<4;j++)
+	*c++= ch4.c[j];
+    }
+  *c=0;// end of string 
+}
+
+}
diff --git a/src/bamglib/Metric.cpp b/src/bamglib/Metric.cpp
new file mode 100644
index 0000000..f81b23e
--- /dev/null
+++ b/src/bamglib/Metric.cpp
@@ -0,0 +1,1213 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdio.h>
+#include "Meshio.h"
+#include "Mesh2.h"
+
+
+namespace bamg {
+
+
+inline Real8 det3x3(Real8 A[3] ,Real8 B[3],Real8 C[3])
+{ return    A[0] * ( B[1]*C[2]-B[2]*C[1])
+          - A[1] * ( B[0]*C[2]-B[2]*C[0])
+          + A[2] * ( B[0]*C[1]-B[1]*C[0]);
+}
+
+SaveMetricInterpole  LastMetricInterpole;
+
+void ReductionSimultanee( MetricAnIso M1,  MetricAnIso M2,double & l1,double & l2, D2xD2 & V) 
+{
+  double a11=M1.a11,a21=M1.a21,a22=M1.a22;
+  double b11=M2.a11,b21=M2.a21,b22=M2.a22;
+  //  M1 v = l M2 v
+  // (M1 - l M2) v =0
+  // det (M1 - l M2) =0
+  // det (M1 - l M2) = a l^2 + b l + c;
+  // = (a11 - l * b11) * (a22 - l * b22) - (a21 - l * b21 ) ^2
+  //  const double eps = 1.e-5;
+  const double /*c11 = a11*a11,*/ c21= a21*a21;
+  const double /*d11 = b11*b11,*/ d21= b21*b21;
+  const double a=b11*b22 - d21;
+  const double b=-a11*b22-a22*b11+2*a21*b21;
+  const double c=-c21+a11*a22;
+  const double bb = b*b,ac= a*c;
+  const double delta = bb - 4 * ac;
+  //  const double kk=c11+c22+c21+d11+d21+d22;
+  // modif F Hecht feb 1998 
+  // cerr.precision(14);
+  //cerr  <<  bb << " " << ac << " " <<  bb <<  " " <<a << endl;
+  // cerr << a11 << " " << a21 << " " << a22 << endl;
+  //cerr << b11 << " " << b21 << " " << b22 << endl;
+  if (bb + Abs(ac) < 1.0e-20 || (delta< 1.0E-4 * bb ) )
+   {
+   // racine double;
+     // cerr << "double " << endl ;
+    if (Abs(a) < 1.e-30 )
+     l1 = l2 = 0;
+    else 
+     l1=l2=-b/(2*a); 
+    V= D2xD2(1,0,0,1);
+   }
+  else {
+    // cerr << "  -- " << a << endl ;
+    const double delta2 = sqrt(delta);
+    l1= (-b - delta2)/(2*a);
+    l2= (-b + delta2)/(2*a);
+    // M1 v = l M2 v
+    //  ( (M1 - I M2) x,y)  = (x,(M1 - I M2) y) \forall y
+    // so Ker((M1 - I M2)) = Im((M1 - I M2))^\perp
+      double v0 = a11-l1*b11, v1 = a21-l1*b21,v2 = a22 - l1*b22;
+      double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
+      double vp1x,vp1y,vp2x,vp2y;
+
+      if(s1 < s0)
+	s0=sqrt(s0),vp1x=v1/s0,vp1y=-v0/s0;
+      else
+	s1=sqrt(s1),vp1x=v2/s1,vp1y=-v1/s1;
+
+      v0 = a11-l2*b11, v1 = a21-l2*b21,v2 = a22 - l2*b22;
+      s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
+      if(s1 < s0)
+	s0=sqrt(s0),vp2x=v1/s0,vp2y=-v0/s0;
+      else
+	s1=sqrt(s1),vp2x=v2/s1,vp2y=-v1/s1;
+#ifdef DEBUG
+      assert(Abs(vp1y)+Abs(vp2y)>0);
+#endif
+      V=D2xD2(vp1x,vp2x,vp1y,vp2y);
+  }
+  return;
+
+}
+
+MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) ;
+MetricAnIso Intersection(const MetricAnIso M1,const MetricAnIso M2) 
+{
+      D2xD2 M;
+      double l1,l2;
+      ReductionSimultanee(M1,M2,l1,l2,M);
+      R2 v0(M.x.x,M.y.x);
+      R2 v1(M.x.y,M.y.y);
+      D2xD2 M_1(M.inv());
+      D2xD2 D(Max(M1(v0,v0),M2(v0,v0)),0,0,Max(M1(v1,v1),M2(v1,v1)));
+      D2xD2 Mi(M_1.t()*D*M_1);
+      return MetricAnIso(Mi.x.x,0.5*(Mi.x.y+Mi.y.x),Mi.y.y);
+}
+
+MetricAnIso::MetricAnIso(const Real8  a[3],const  MetricAnIso m0,
+	   const  MetricAnIso m1,const  MetricAnIso m2 )
+{
+  MetricAnIso mab(a[0]*m0.a11 + a[1]*m1.a11 + a[2]*m2.a11,
+		  a[0]*m0.a21 + a[1]*m1.a21 + a[2]*m2.a21,
+		  a[0]*m0.a22 + a[1]*m1.a22 + a[2]*m2.a22);
+  
+  MatVVP2x2 vab(mab);
+ 
+  R2 v1(vab.v.x,vab.v.y);
+  R2 v2(-v1.y,v1.x);
+  
+  Real8 h1 = a[0] / m0(v1) + a[1] / m1(v1) + a[2] / m2(v1);
+  Real8 h2 = a[0] / m0(v2) + a[1] / m1(v2) + a[2] / m2(v2);
+
+  vab.lambda1 =  1 / (h1*h1);
+  vab.lambda2 =  1 / (h2*h2);
+  *this = vab;
+}
+
+ MetricAnIso::MetricAnIso( Real8  a,const  MetricAnIso ma,
+	                   Real8  b,const  MetricAnIso mb)
+{ 
+  MetricAnIso mab(a*ma.a11+b*mb.a11,a*ma.a21+b*mb.a21,a*ma.a22+b*mb.a22);
+  MatVVP2x2 vab(mab);
+  
+  R2 v1(vab.v.x,vab.v.y);
+  R2 v2(-v1.y,v1.x);
+  
+
+  Real8 h1 = a / ma(v1) + b / mb(v1);
+  Real8 h2 = a / ma(v2) + b / mb(v2);
+  vab.lambda1 =  1 / (h1*h1);
+  vab.lambda2 =  1 / (h2*h2);
+  *this = vab;
+}
+
+
+
+ MatVVP2x2::MatVVP2x2(const MetricAnIso M) 
+{
+  double a11=M.a11,a21=M.a21,a22=M.a22;
+  const double eps = 1.e-5;
+  double c11 = a11*a11, c22 = a22*a22, c21= a21*a21;
+  double b=-a11-a22,c=-c21+a11*a22;
+  double   delta = b*b - 4 * c ;
+  double n2=(c11+c22+c21);
+  if ( n2 < 1e-30) 
+     lambda1=lambda2=0,v.x=1,v.y=0;
+  else if (delta < eps*n2)
+    { 
+      lambda1=lambda2=-b/2, v.x=1,v.y=0;
+    }
+  else 
+    {  //    ---  construction  de 2 vecteur dans (Im ( A - D(i) Id) ortogonal 
+      delta = sqrt(delta);
+      lambda1 = (-b-delta)/2.0,lambda2 = (-b+delta)/2.0;
+      double v0 = a11-lambda1, v1 = a21,v2 = a22 - lambda1;
+      double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
+ 
+      if(s1 < s0)
+	s0=sqrt(s0),v.x=v1/s0,v.y=-v0/s0;
+      else
+	s1=sqrt(s1),v.x=v2/s1,v.y=-v1/s1;
+    };
+}
+
+
+ int MetricAnIso::IntersectWith(const MetricAnIso M2) 
+{
+  //cerr << " - " << *this << M2 <<  endl;
+      int r=0;
+      MetricAnIso & M1 = *this;
+      D2xD2 M;
+      double l1,l2;
+      
+      ReductionSimultanee(*this,M2,l1,l2,M);
+      // cerr << M << endl;
+      R2 v1(M.x.x,M.y.x);
+      R2 v2(M.x.y,M.y.y);
+      double l11=M1(v1,v1);
+      double l12=M1(v2,v2);
+      double l21=M2(v1,v1);
+      double l22=M2(v2,v2);
+      if ( l11 < l21 )  r=1,l11=l21;
+      if ( l12 < l22 )  r=1,l12=l22; 
+      // cerr << r << endl;
+      if (r) { // change
+        D2xD2 M_1(M.inv());
+        D2xD2 D(l11,0,0,l12); 
+        D2xD2 Mi(M_1.t()*D*M_1);
+        a11=Mi.x.x;
+        a21=0.5*(Mi.x.y+Mi.y.x);
+        a22=Mi.y.y; }
+      return r;
+}
+void Triangles::IntersectGeomMetric(const Real8 err=1,const int iso=0)
+
+{
+  if(verbosity>1)
+    cout << "  -- IntersectGeomMetric geometric err=" << err << (iso ? " iso " : " aniso "  ) << endl;
+  Real8 ss[2]={0.00001,0.99999};
+  Real8 errC = 2*sqrt(2*err);
+  Real8 hmax = Gh.MaximalHmax();
+  Real8 hmin = Gh.MinimalHmin();
+  Real8 maxaniso = 1e6;
+  assert(hmax>0);
+  SetVertexFieldOn();
+  if (errC > 1) errC = 1;
+  for (Int4  i=0;i<nbe;i++)
+   for (int j=0;j<2;j++)
+    {
+      
+      Vertex V;
+      VertexOnGeom GV;
+      // cerr << Number(edges[i]) << " " << ss[j] << endl;
+      Gh.ProjectOnCurve(edges[i],ss[j],V,GV);
+	{
+	  GeometricalEdge * eg = GV;
+	  Real8 s = GV;
+	  R2 tg;
+	  //	   cerr << i << " " << j << " " << Number(V) << " on = " 
+	  //	<< Gh.Number(eg) << " at s = " << s << " " << endl;
+	  Real8  R1= eg->R1tg(s,tg);
+	  // cerr << " R = " << 1/Max(R1,1e-20) << tg << " on x " 
+	  //    << V.r << errC/ Max(R1,1e-20) <<  " hold=" <<V.m(tg) << " "  << endl;
+	  Real8 ht = hmax;
+          if (R1>1.0e-20) 
+	    {  // err relative to the length of the edge
+	      ht = Min(Max(errC/R1,hmin),hmax);
+	    }
+	  Real8 hn = iso? ht : Min(hmax,ht*maxaniso);
+	  //cerr << ht << " " << hn << "m=" << edges[i][j].m <<  endl;
+	  assert(ht>0 && hn>0);
+	  MatVVP2x2 Vp(1/(ht*ht),1/(hn*hn),tg);
+	  //cerr << " : " ;
+	  Metric MVp(Vp);
+	  // cerr << " : "  << MVp  << endl;
+	  edges[i][j].m.IntersectWith(MVp);
+	  //cerr << " . " << endl;
+	}
+
+    }
+  // the problem is for the vertex on vertex 
+     
+}
+/*
+void  Triangles::BoundAnisotropy(Real8 anisomax)
+{
+  if (verbosity > 1) 
+    cout << "  -- BoundAnisotropy by  " << anisomax << endl; 
+  Real8 h1=1.e30,h2=1e-30,rx=0;
+  Real8 coef = 1./(anisomax*anisomax);
+  Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30;  
+  for (Int4 i=0;i<nbv;i++)
+    {
+
+      MatVVP2x2 Vp(vertices[i]);
+      
+      h1=Min(h1,Vp.lmin());
+      h2=Max(h2,Vp.lmax());
+      rx = Max(rx,Vp.Aniso2());
+      
+      Vp.BoundAniso2(coef);
+      
+      hn1=Min(hn1,Vp.lmin());
+      hn2=Max(hn2,Vp.lmax());
+      rnx = Max(rnx,Vp.Aniso2());
+
+      
+      vertices[i].m = Vp;
+
+    }
+
+  if (verbosity>2)
+    {
+      cout << "     input :  Hmin = " << sqrt(1/h2)  << " Hmax = " << sqrt(1/h1) 
+	   << " factor of anisotropy max  = " << sqrt(rx) << endl;
+      cout << "     output:  Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) 
+	   << " factor of anisotropy max  = " << sqrt(rnx) << endl;
+    }
+}
+*/
+void  Triangles::BoundAnisotropy(Real8 anisomax,Real8 hminaniso)
+{
+  double lminaniso = 1/ (Max(hminaniso*hminaniso,1e-100));
+  if (verbosity > 1) 
+    cout << "  -- BoundAnisotropy by  " << anisomax << endl; 
+  Real8 h1=1.e30,h2=1e-30,rx=0;
+  Real8 coef = 1./(anisomax*anisomax);
+  Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30;  
+  for (Int4 i=0;i<nbv;i++)
+    {
+
+      MatVVP2x2 Vp(vertices[i]);
+      double lmax=Vp.lmax();
+      h1=Min(h1,Vp.lmin());
+      h2=Max(h2,Vp.lmax());
+      rx = Max(rx,Vp.Aniso2());
+
+      Vp *= Min(lminaniso,lmax)/lmax;
+      
+      Vp.BoundAniso2(coef);
+      
+      hn1=Min(hn1,Vp.lmin());
+      hn2=Max(hn2,Vp.lmax());
+      rnx = Max(rnx,Vp.Aniso2());
+
+      
+      vertices[i].m = Vp;
+
+    }
+
+  if (verbosity>2)
+    {
+      cout << "     input :  Hmin = " << sqrt(1/h2)  << " Hmax = " << sqrt(1/h1) 
+	   << " factor of anisotropy max  = " << sqrt(rx) << endl;
+      cout << "     output:  Hmin = " << sqrt(1/hn2) << " Hmax = " << sqrt(1/hn1) 
+	   << " factor of anisotropy max  = " << sqrt(rnx) << endl;
+    }
+}
+void Triangles::IntersectConsMetric(const double * s,const Int4 nbsol,const int * typsols,
+				    const  Real8 hmin1,const Real8 hmax1,const Real8 coef,
+				    const Real8 anisomax ,const Real8 CutOff,const int NbJacobi,
+				    const int DoNormalisation,const double power,const int choice)
+{ //  the array of solution s is store    
+  // sol0,sol1,...,soln    on vertex 0
+  //  sol0,sol1,...,soln   on vertex 1
+  //  etc.
+  //  choise = 0 =>  H is computed with green formule
+  //   otherwise  => H is computed from P2 on 4T 
+  const int dim = 2;
+  
+  int sizeoftype[] = { 1, dim ,dim * (dim+1) / 2, dim * dim } ; 
+
+  // computation of the nb of field 
+  Int4 ntmp = 0;
+  if (typsols)
+    {
+      for (Int4 i=0;i<nbsol;i++)
+	     ntmp += sizeoftype[typsols[i]];
+    }
+  else
+    ntmp = nbsol;
+
+  // n is the total number of fields
+
+  const Int4 n = ntmp;
+
+  Int4 i,k,iA,iB,iC,iv;
+  R2 O(0,0);
+  int RelativeMetric = CutOff>1e-30;
+  Real8 hmin = Max(hmin1,MinimalHmin());
+  Real8 hmax = Min(hmax1,MaximalHmax());
+  Real8 coef2 = 1/(coef*coef);
+
+  if(verbosity>1) 
+    {
+      cout << "  -- Construction of Metric: Nb of field. " << n << " nbt = " 
+	   << nbt << " nbv= " << nbv 
+	   << " coef = " << coef << endl
+	   << "     hmin = " << hmin << " hmax=" << hmax 
+	   << " anisomax = " << anisomax <<  " Nb Jacobi " << NbJacobi << " Power = " << power ;
+      if (RelativeMetric)
+	cout << " RelativeErr with CutOff= "  <<  CutOff << endl;
+      else
+	cout << " Absolute Err" <<endl;
+    }
+  double *ss=(double*)s;//, *ssiii = ss;
+
+  double sA,sB,sC;
+
+  Real8 *detT = new Real8[nbt];
+  Real8 *Mmass= new Real8[nbv];
+  Real8 *Mmassxx= new Real8[nbv];
+  Real8 *dxdx= new Real8[nbv];
+  Real8 *dxdy= new Real8[nbv];
+  Real8 *dydy= new Real8[nbv];
+  Real8 *workT= new Real8[nbt];
+  Real8 *workV= new Real8[nbv];
+  int *OnBoundary = new int[nbv];
+  for (iv=0;iv<nbv;iv++)
+    {
+      Mmass[iv]=0;
+      OnBoundary[iv]=0;
+      Mmassxx[iv]=0;
+    }
+
+  for (i=0;i<nbt;i++) 
+    if(triangles[i].link) // the real triangles 
+      {
+	const Triangle &t=triangles[i];
+	// coor of 3 vertices 
+	R2 A=t[0];
+	R2 B=t[1];
+	R2 C=t[2];
+
+
+	// number of the 3 vertices
+	iA = Number(t[0]);
+	iB = Number(t[1]);
+	iC = Number(t[2]);
+	
+	Real8 dett = bamg::Area2(A,B,C);
+	detT[i]=dett;
+	dett /= 6;
+
+	// construction of on boundary 
+	int nbb =0;
+	for(int j=0;j<3;j++)
+          {
+	    Triangle *ta=t.Adj(j);
+	    if ( ! ta || !ta->link) // no adj triangle => edge on boundary
+	      OnBoundary[Number(t[VerticesOfTriangularEdge[j][0]])]=1,
+		OnBoundary[Number(t[VerticesOfTriangularEdge[j][1]])]=1,
+		nbb++;
+	  }
+	
+	workT[i] = nbb;
+	Mmass[iA] += dett;
+	Mmass[iB] += dett;
+	Mmass[iC] += dett;
+	
+	if((nbb==0)|| !choice)
+	  {
+	    Mmassxx[iA] += dett;
+	    Mmassxx[iB] += dett;
+	    Mmassxx[iC] += dett;
+	  }
+      }
+  else
+    workT[i]=-1;
+
+//  for (Int4 kcount=0;kcount<n;kcount++,ss++)
+    for (Int4 nusol=0;nusol<nbsol;nusol++)
+    { //for all Solution  
+
+      Real8 smin=ss[0],smax=ss[0];
+      
+      Real8 h1=1.e30,h2=1e-30,rx=0;
+      Real8 coef = 1./(anisomax*anisomax);
+      Real8 hn1=1.e30,hn2=1e-30,rnx =1.e-30;  
+      int nbfield = typsols? sizeoftype[typsols[nusol]] : 1; 
+      if (nbfield == 1) 
+       for ( iv=0,k=0; iv<nbv; iv++,k+=n )
+				{
+				  dxdx[iv]=dxdy[iv]=dydy[iv]=0;
+				  smin=Min(smin,ss[k]);
+				  smax=Max(smax,ss[k]);
+				 }
+			  else
+			   {
+         //  cas vectoriel 
+          for ( iv=0,k=0; iv<nbv; iv++,k+=n )
+          {	
+           double v=0;		     
+			     for (int i=0;i<nbfield;i++) 
+			         v += ss[k+i]*ss[k+i];
+			     v = sqrt(v);
+				   smin=Min(smin,v);
+				   smax=Max(smax,v);
+			    }
+			   }
+      Real8 sdelta = smax-smin;
+      Real8 absmax=Max(Abs(smin),Abs(smax));
+      Real8 cnorm = DoNormalisation ? coef2/sdelta : coef2;
+      
+      if(verbosity>2) 
+	     cout << "    Solution " << nusol <<  " Min = " << smin << " Max = " 
+	       << smax << " Delta =" << sdelta << " cnorm = " << cnorm <<  " Nb of fields =" << nbfield << endl;
+
+      
+      if ( sdelta < 1.0e-10*Max(absmax,1e-20) && (nbfield ==1)) 
+				{
+				  if (verbosity>2)
+				    cout << "      Solution " << nusol << " is constant. We skip. " 
+					 << " Min = " << smin << " Max = " << smax << endl;
+				continue;
+				}
+				
+	 double *sf  = ss; 
+	 for (Int4 nufield=0;nufield<nbfield;nufield++,ss++) 
+	   {
+	     for ( iv=0,k=0; iv<nbv; iv++,k+=n )
+		       dxdx[iv]=dxdy[iv]=dydy[iv]=0;
+       for (i=0;i<nbt;i++) 
+	      if(triangles[i].link)
+	  {// for real all triangles 
+	    // coor of 3 vertices 
+	    R2 A=triangles[i][0];
+	    R2 B=triangles[i][1];
+	    R2 C=triangles[i][2];
+	    
+	    
+	    // warning the normal is internal and the 
+	    //   size is the length of the edge
+	    R2 nAB = Orthogonal(B-A);
+	    R2 nBC = Orthogonal(C-B);
+	    R2 nCA = Orthogonal(A-C);
+	    // remark :  nAB + nBC + nCA == 0 
+
+	    // number of the 3 vertices
+	    iA = Number(triangles[i][0]);
+	    iB = Number(triangles[i][1]);
+	    iC = Number(triangles[i][2]);
+	    
+	    // for the test of  boundary edge
+	    // the 3 adj triangles 
+	    Triangle *tBC = triangles[i].TriangleAdj(OppositeEdge[0]);
+	    Triangle *tCA = triangles[i].TriangleAdj(OppositeEdge[1]);
+	    Triangle *tAB = triangles[i].TriangleAdj(OppositeEdge[2]);
+
+	    // value of the P1 fonction on 3 vertices 
+	    sA = ss[iA*n];
+	    sB = ss[iB*n];
+	    sC = ss[iC*n];
+
+	    R2 Grads = (nAB * sC + nBC * sA + nCA * sB ) /detT[i] ;
+	    if(choice) 
+	      {
+		int nbb = 0;
+		Real8 dd = detT[i];
+		Real8 lla,llb,llc,llf;
+		Real8  taa[3][3],bb[3];
+		// construction of the trans of lin system
+		for (int j=0;j<3;j++)
+		  {
+		    int ie = OppositeEdge[j];
+		    TriangleAdjacent ta = triangles[i].Adj(ie);
+		    Triangle *tt = ta;
+		    if (tt && tt->link)
+		      {
+			Vertex &v = *ta.OppositeVertex();
+			R2 V = v;
+			Int4 iV = Number(v);
+			Real8 lA  = bamg::Area2(V,B,C)/dd;
+			Real8 lB  = bamg::Area2(A,V,C)/dd;
+			Real8 lC  = bamg::Area2(A,B,V)/dd;
+			taa[0][j] =  lB*lC;
+			taa[1][j] =  lC*lA;
+			taa[2][j] =  lA*lB;
+			//Real8 xx = V.x-V.y;
+			//Real8 yy = V.x + V.y;
+			//cout << " iv " << ss[iV*n] << " == " << (8*xx*xx+yy*yy)
+			//     << " l = " << lA << " " << lB << " " << lC 
+			//     << " = " << lA+lB+lC << " " <<  V << " == " << A*lA+B*lB+C*lC << endl;
+			
+			lla = lA,llb=lB,llc=lC,llf=ss[iV*n] ;
+
+			bb[j]     =  ss[iV*n] - ( sA*lA + sB*lB + sC*lC ) ;
+		      }
+		    else
+		      {
+			nbb++;
+			taa[0][j]=0;
+			taa[1][j]=0;
+			taa[2][j]=0;
+			taa[j][j]=1;
+			bb[j]=0;
+		      }
+		  }
+
+		// resolution of 3x3 lineaire system transpose
+		Real8 det33 =  det3x3(taa[0],taa[1],taa[2]);		
+		Real8 cBC   =  det3x3(bb,taa[1],taa[2]);
+		Real8 cCA   =  det3x3(taa[0],bb,taa[2]);
+		Real8 cAB   =  det3x3(taa[0],taa[1],bb);
+		
+		assert(det33);
+		//	det33=1;
+		// verif
+		//	cout << " " << (taa[0][0]*cBC +  taa[1][0]*cCA + taa[2][0] * cAB)/det33 << " == " << bb[0] ;
+		//	cout << " " << (taa[0][1]*cBC +  taa[1][1]*cCA + taa[2][1] * cAB)/det33 << " == " << bb[1];
+		//	cout << " " << (taa[0][2]*cBC +  taa[1][2]*cCA + taa[2][2] * cAB)/det33 << " == " << bb[2] 
+		//	     << "  -- " ;
+		//cout << lla*sA + llb*sB+llc*sC+ (lla*llb* cAB +  llb*llc* cBC + llc*lla*cCA)/det33 
+		//   << " == " << llf <<  endl;
+		// computation of the gradient in the element 
+		
+		// H( li*lj) = grad li grad lj + grad lj grad lj
+		// grad li = njk  / detT ; with i j k ={A,B,C)
+		Real8 Hxx = cAB * ( nBC.x*nCA.x) +  cBC * ( nCA.x*nAB.x) + cCA * (nAB.x*nBC.x);
+		Real8 Hyy = cAB * ( nBC.y*nCA.y) +  cBC * ( nCA.y*nAB.y) + cCA * (nAB.y*nBC.y);
+		Real8 Hxy = cAB * ( nBC.y*nCA.x) +  cBC * ( nCA.y*nAB.x) + cCA * (nAB.y*nBC.x) 
+		          + cAB * ( nBC.x*nCA.y) +  cBC * ( nCA.x*nAB.y) + cCA * (nAB.x*nBC.y);
+		Real8 coef = 1.0/(3*dd*det33);
+		Real8 coef2 = 2*coef;
+		//	cout << " H = " << Hxx << " " << Hyy << " " <<  Hxy/2 << " coef2 = " << coef2 << endl;
+		Hxx *= coef2;
+		Hyy *= coef2;
+		Hxy *= coef2;
+		//cout << i  << " H = " << 3*Hxx/dd << " " << 3*Hyy/dd << " " <<  3*Hxy/(dd*2) << " nbb = " << nbb << endl;
+		if(nbb==0)
+		  {
+		    dxdx[iA] += Hxx;
+		    dydy[iA] += Hyy;
+		    dxdy[iA] += Hxy;
+		    
+		    dxdx[iB] += Hxx;
+		    dydy[iB] += Hyy;
+		    dxdy[iB] += Hxy;
+		    
+		    dxdx[iC] += Hxx;
+		    dydy[iC] += Hyy;
+		    dxdy[iC] += Hxy;
+		  }
+		
+	      }
+	    else
+	      {
+		
+		// if edge on boundary no contribution  => normal = 0
+		if ( ! tBC || ! tBC->link ) nBC = O;
+		if ( ! tCA || ! tCA->link ) nCA = O;
+		if ( ! tAB || ! tAB->link ) nAB = O;
+	    
+		// remark we forgot a 1/2 because
+		//       $\\int_{edge} w_i = 1/2 $ if $i$ is in edge 
+		//                          0  if not
+		// if we don't take the  boundary 
+		// dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;
+		
+		dxdx[iA] += ( nCA.x + nAB.x ) *Grads.x;
+		dxdx[iB] += ( nAB.x + nBC.x ) *Grads.x;
+		dxdx[iC] += ( nBC.x + nCA.x ) *Grads.x;
+		
+		// warning optimization (1) the divide by 2 is done on the metrix construction
+		dxdy[iA] += (( nCA.y + nAB.y ) *Grads.x + ( nCA.x + nAB.x ) *Grads.y) ;
+		dxdy[iB] += (( nAB.y + nBC.y ) *Grads.x + ( nAB.x + nBC.x ) *Grads.y) ;
+		dxdy[iC] += (( nBC.y + nCA.y ) *Grads.x + ( nBC.x + nCA.x ) *Grads.y) ; 
+		
+		dydy[iA] += ( nCA.y + nAB.y ) *Grads.y;
+		dydy[iB] += ( nAB.y + nBC.y ) *Grads.y;
+		dydy[iC] += ( nBC.y + nCA.y ) *Grads.y;
+	      }
+	    
+	  } // for real all triangles 
+     Int4 kk=0;
+      for ( iv=0,k=0 ; iv<nbv; iv++,k+=n )
+	if(Mmassxx[iv]>0) 
+	  {
+	    dxdx[iv] /= 2*Mmassxx[iv];
+	    // warning optimization (1) on term dxdy[iv]*ci/2 
+	    dxdy[iv] /= 4*Mmassxx[iv];
+	    dydy[iv] /= 2*Mmassxx[iv];
+	    // Compute the matrix with abs(eigen value)
+	    Metric M(dxdx[iv], dxdy[iv], dydy[iv]);
+	    MatVVP2x2 Vp(M);
+	    //cout <<iv <<  "  M  = " <<  M <<  " aniso= " << Vp.Aniso() ;
+	    Vp.Abs();
+	    M = Vp;
+	      dxdx[iv] = M.a11;
+	      dxdy[iv] = M.a21;
+	      dydy[iv] = M.a22;
+	      //  cout << " (abs)  iv M  = " <<  M <<  " aniso= " << Vp.Aniso() <<endl;
+	  }
+	else kk++;
+      
+      
+      // correction of second derivate
+      // by a laplacien
+
+      Real8 *d2[3] = { dxdx, dxdy, dydy};
+      Real8 *dd;
+      for (int xy = 0;xy<3;xy++)
+	{
+	  dd = d2[xy];
+      // do leat 2 iteration for boundary problem
+	  for (int ijacobi=0;ijacobi<Max(NbJacobi,2);ijacobi++)
+	    {
+	      for (i=0;i<nbt;i++) 
+		if(triangles[i].link) // the real triangles 
+		  {
+		    // number of the 3 vertices
+		    iA = Number(triangles[i][0]);
+		    iB = Number(triangles[i][1]);
+		    iC = Number(triangles[i][2]);
+		    Real8 cc=3;
+		    if(ijacobi==0)
+		      cc = Max((Real8) ((Mmassxx[iA]>0)+(Mmassxx[iB]>0)+(Mmassxx[iC]>0)),1.);
+		    workT[i] = (dd[iA]+dd[iB]+dd[iC])/cc;
+		  }
+	      for (iv=0;iv<nbv;iv++)
+		workV[iv]=0;
+
+	      for (i=0;i<nbt;i++) 
+		if(triangles[i].link) // the real triangles 
+		  {
+		    // number of the 3 vertices
+		    iA = Number(triangles[i][0]);
+		    iB = Number(triangles[i][1]);
+		    iC = Number(triangles[i][2]);
+		    Real8 cc =  workT[i]*detT[i];
+		    workV[iA] += cc;
+		    workV[iB] += cc;
+		    workV[iC] += cc;
+		  }
+
+	      for (iv=0;iv<nbv;iv++)
+		if( ijacobi<NbJacobi || OnBoundary[iv])
+		  dd[iv] = workV[iv]/(Mmass[iv]*6);
+	      
+
+	    }
+
+	  
+	}
+
+      // constuction  of the metrix from the Hessian dxdx. dxdy,dydy
+
+      Real8 rCutOff=CutOff*absmax;// relative cut off 
+
+      for ( iv=0,k=0 ; iv<nbv; iv++,k+=n )
+	{ // for all vertices 
+	  //{
+	  //Metric M(dxdx[iv], dxdy[iv], dydy[iv]);
+	  // MatVVP2x2 Vp(M);	  
+	  //cout << " iv M="<<  M << "  Vp = " << Vp << " aniso  " << Vp.Aniso() << endl;
+	  //}
+	  MetricIso Miso;
+// new code to compute ci ---	  
+	  Real8 ci ;
+	  if (RelativeMetric)
+	    { //   compute the norm of the solution
+	       double xx =0,*sfk=sf+k; 
+	       for (int ifield=0;ifield<nbfield;ifield++,sfk++)
+	          xx += *sfk* *sfk;	       
+	       xx=sqrt(xx);
+	       ci = coef2/Max(xx,rCutOff);
+	    }
+	  else ci = cnorm;
+	  
+ // old 
+//	  Real8 ci = RelativeMetric ? coef2/(Max(Abs(ss[k]),rCutOff)) : cnorm ;
+ //   modif F Hecht 101099
+	  Metric Miv(dxdx[iv]*ci, dxdy[iv]*ci,  dydy[iv]*ci);
+	  MatVVP2x2 Vp(Miv);
+
+	  Vp.Abs();
+	 if(power!=1.0) 
+	      Vp.pow(power);
+	  
+
+
+	  h1=Min(h1,Vp.lmin());
+	  h2=Max(h2,Vp.lmax());
+
+	  Vp.Maxh(hmin);
+	  Vp.Minh(hmax);
+
+	  rx = Max(rx,Vp.Aniso2());
+
+	  Vp.BoundAniso2(coef);
+
+	  hn1=Min(hn1,Vp.lmin());
+	  hn2=Max(hn2,Vp.lmax());
+	  rnx = Max(rnx,Vp.Aniso2());
+
+	  Metric MVp(Vp);
+	  vertices[iv].m.IntersectWith(MVp);
+	}// for all vertices 
+      if (verbosity>2)
+	{ 
+	  cout << "              Field " << nufield << " of solution " << nusol  << endl;
+	  cout << "              before bounding :  Hmin = " << sqrt(1/h2) << " Hmax = " 
+	       << sqrt(1/h1)  << " factor of anisotropy max  = " << sqrt(rx) << endl;
+	  cout << "              after  bounding :  Hmin = " << sqrt(1/hn2) << " Hmax = " 
+	       << sqrt(1/hn1)  << " factor of anisotropy max  = " << sqrt(rnx) << endl;
+	}
+	 } //  end of for all field
+    }// end for all solution 
+
+  delete [] detT;
+  delete [] Mmass;
+  delete [] dxdx;
+  delete [] dxdy;
+  delete [] dydy;
+  delete []  workT;
+  delete [] workV;
+  delete [] Mmassxx;
+  delete []  OnBoundary;
+ 
+}
+
+
+void Triangles::ReadMetric(const char * fmetrix,const Real8 hmin1=1.0e-30,const Real8 hmax1=1.0e30,const Real8 coef=1)
+{
+  Real8 hmin = Max(hmin1,MinimalHmin());
+  Real8 hmax = Min(hmax1,MaximalHmax());
+  MeshIstream f_metrix(fmetrix);
+  Int4 k,j;
+  f_metrix >>  k >> j ;
+  if(verbosity>1)
+    cout << " metrix: open " << fmetrix 
+	 << ", le coef = " << coef
+	 << ", hmin = " << hmin 
+	 << ", hmax = " << hmax 
+	 << (  (j == 1)? " Iso " : " AnIso " )<< endl;
+  
+  if (k != nbv || !(j == 1 || j == 3)) 
+    {
+      cerr << " Error Pb metrix " << k << " <> " 
+	   <<  nbv << " or  1 or 3 <> " << j << endl;
+      MeshError(1002);
+    }
+  
+  cout << " j = " << j << endl;
+  //  Int4 nberr = 0;
+  for (Int4 iv=0;iv<nbv;iv++)
+    {
+      Real8 h;
+      if (j == 1) 
+	{
+	f_metrix >>  h ;
+	vertices[iv].m=Metric(Max(hmin,Min(hmax, h*coef)));
+	}
+      else if (j==3) 
+	{
+	  Real8 a,b,c;	     
+	  f_metrix >>  a >> b >> c  ;
+	  MetricAnIso M(a,b,c);
+	  MatVVP2x2 Vp(M/coef);
+	  
+	  Vp.Maxh(hmin);
+	  Vp.Minh(hmax);
+	  vertices[iv].m = Vp;
+	  
+	}
+    }
+ 
+}
+
+void Triangles::WriteMetric(ostream & f,int iso)
+{
+  if (iso)
+    {
+      f <<  nbv <<" " << 1 << endl ;
+      for (Int4 iv=0;iv<nbv;iv++)
+	{
+	  MatVVP2x2 V=vertices[iv].m;
+	  f <<  V.hmin()  << endl;
+	}
+    }
+else
+  {
+    f <<  nbv <<" " << 3 << endl ;
+    for (Int4 iv=0;iv<nbv;iv++)
+      f <<  vertices[iv].m.a11 << " " 
+	<<  vertices[iv].m.a21 << " " 
+	<<  vertices[iv].m.a22 << endl;
+  }
+}
+void  Triangles::MaxSubDivision(Real8 maxsubdiv)
+{
+const  Real8 maxsubdiv2 = maxsubdiv*maxsubdiv;
+#ifdef DRAWING2
+  inquire();
+#endif	    
+  if(verbosity>1)
+    cout << "  -- Limit the subdivision of a edges in the new mesh by " << maxsubdiv <<   endl  ;
+  // for all the edges 
+  // if the len of the edge is to long 
+  Int4 it,nbchange=0;    
+  Real8 lmax=0;
+  for (it=0;it<nbt;it++)
+    {
+      Triangle &t=triangles[it];
+      for (int j=0;j<3;j++)
+	{
+	  Triangle &tt = *t.TriangleAdj(j);
+	  if ( ! &tt || (( it < Number(tt) && ( tt.link || t.link)))) 
+	    {
+		Vertex &v0 = t[VerticesOfTriangularEdge[j][0]];
+		Vertex &v1 = t[VerticesOfTriangularEdge[j][1]];
+		R2 AB= (R2) v1-(R2) v0;
+		Metric M = v0;
+		Real8 l = M(AB,AB);
+		lmax = Max(lmax,l);
+		if(l> maxsubdiv2)
+		  { R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
+		    Real8 lc = M(AC,AC);
+		    D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
+		    D2xD2 Rt1(Rt.inv());
+		    D2xD2 D(maxsubdiv2,0,0,lc);
+		    D2xD2 MM = Rt1*D*Rt1.t();
+#ifdef DRAWING1
+		    v0.m.Draw(v0);
+#endif	    
+		    v0.m =  M = MetricAnIso(MM.x.x,MM.y.x,MM.y.y);
+#ifdef DRAWING1
+		    v0.m.Draw(v0);
+#endif	    
+		    //		    cout << " M(AB,AB) = " << M(AB,AB) << " == " << maxsubdiv 
+		    //	 << " M(AC,AC) = " << M(AC,AC) << " == " << lc << endl; 
+		    nbchange++;
+		  }
+		M = v1;
+		l = M(AB,AB);
+		lmax = Max(lmax,l);
+		if(l> maxsubdiv2)
+		  { R2 AC = M.Orthogonal(AB);// the ortogonal vector of AB in M
+		    Real8 lc = M(AC,AC);
+		    D2xD2 Rt(AB,AC);// Rt.x = AB , Rt.y = AC;
+		    D2xD2 Rt1(Rt.inv());
+		    D2xD2 D(maxsubdiv2,0,0,lc);
+		    D2xD2  MM = Rt1*D*Rt1.t();
+#ifdef DRAWING1
+		    v1.m.Draw(v1);
+#endif	    
+		    v1.m =  M = MetricAnIso(MM.x.x,MM.y.x,MM.y.y);
+#ifdef DRAWING1
+		    v1.m.Draw(v1);
+		    inquire();
+#endif	    
+		    // cout << " M(AB,AB) = " << M(AB,AB) << " == " << maxsubdiv 
+		    //	 << " M(AC,AC) = " << M(AC,AC) << " == " << lc << endl; 
+		    nbchange++;
+		  }
+		
+		
+	    }
+	}
+    }
+  if(verbosity>3)
+  cout << "    Nb of metric change = " << nbchange 
+       << " Max  of the subdivision of a edges before change  = " << sqrt(lmax) << endl;
+#ifdef DRAWING2
+  inquire();
+#endif	    
+
+}
+
+void Triangles::SmoothMetric(Real8 raisonmax) 
+{ 
+  if(raisonmax<1.1) return;
+  if(verbosity > 1)
+     cout << "  -- Triangles::SmoothMetric raisonmax = " << raisonmax << " " <<nbv <<endl;
+  ReMakeTriangleContainingTheVertex();
+  Int4 i,j,kch,kk,ip;
+  Int4 *first_np_or_next_t0 = new Int4[nbv];
+  Int4 *first_np_or_next_t1 = new Int4[nbv];
+  Int4 Head0 =0,Head1=-1;
+  Real8 logseuil= log(raisonmax);
+
+  for(i=0;i<nbv-1;i++)
+    first_np_or_next_t0[i]=i+1; 
+  first_np_or_next_t0[nbv-1]=-1;// end;
+  for(i=0;i<nbv;i++)
+    first_np_or_next_t1[i]=-1;
+  kk=0;
+  while (Head0>=0&& kk++<100) {
+    kch=0;
+    for (i=Head0;i>=0;i=first_np_or_next_t0[ip=i],first_np_or_next_t0[ip]=-1)
+      {  //  pour tous les triangles autour du sommet s
+	// 	cout << kk << " i = " << i << " " << ip << endl;
+	 Triangle * t= vertices[i].t;
+	assert(t);
+	Vertex & vi = vertices[i];
+	TriangleAdjacent ta(t,EdgesVertexTriangle[vertices[i].vint][0]);
+	Vertex *pvj0 = ta.EdgeVertex(0);
+	while (1) {
+	  //	  cout << i << " " <<  Number(ta.EdgeVertex(0)) << " "
+	  //      << Number(ta.EdgeVertex(1)) << "  ---> " ;
+	  ta=Previous(Adj(ta));
+	  // cout <<  Number(ta.EdgeVertex(0)) << " " << Number(ta.EdgeVertex(1)) << endl;
+	  assert(vertices+i == ta.EdgeVertex(1));
+	  Vertex & vj = *(ta.EdgeVertex(0));
+	  if ( &vj ) {
+	    j= &vj-vertices;
+	    assert(j>=0 && j < nbv);
+	    R2 Aij = (R2) vj - (R2) vi;
+	    Real8 ll =  Norme2(Aij);
+	    if (0) {  
+	      Real8 hi = ll/vi.m(Aij);
+	      Real8 hj = ll/vj.m(Aij);
+	      if(hi < hj)
+		{
+		  Real8 dh=(hj-hi)/ll;
+		  //cout << " dh = " << dh << endl;
+		  if (dh>logseuil) {
+		    vj.m.IntersectWith(vi.m/(1 +logseuil*ll/hi));
+		    if(first_np_or_next_t1[j]<0)
+		      kch++,first_np_or_next_t1[j]=Head1,Head1=j;
+		  }
+		}
+	    } 
+	    else
+	      {
+		Real8 li = vi.m(Aij);
+		//Real8 lj = vj.m(Aij);
+		//		if ( i == 2 || j == 2)
+		//  cout << " inter " << i << " " << j << " " << ((1 +logseuil*li)) <<  endl;
+	      	if( vj.m.IntersectWith(vi.m/(1 +logseuil*li)) )
+		  //if( vj.m.IntersectWith(vi.m*(lj/li/(1 +logseuil*lj))) )
+		  if(first_np_or_next_t1[j]<0) // if the metrix change 
+		    kch++,first_np_or_next_t1[j]=Head1,Head1=j;
+	      }
+	  }
+	  if  ( &vj ==  pvj0 ) break;
+	}
+      }
+    Head0 = Head1;
+    Head1 = -1;
+    Exchange(first_np_or_next_t0,first_np_or_next_t1);
+    if(verbosity>5)
+    cout << "     Iteration " << kk << " Nb de  vertices with change  " << kch << endl;
+  }
+  if(verbosity>2 && verbosity < 5) 
+    cout << "    Nb of Loop " << kch << endl;
+  delete [] first_np_or_next_t0;
+  delete [] first_np_or_next_t1;
+}
+
+void Geometry::ReadMetric(const char * fmetrix,Real8 hmin=1.0e-30,Real8 hmax=1.0e30,Real8 coef=1)
+{
+  hmin = Max(hmin,MinimalHmin());
+  MeshIstream f_metrix(fmetrix);
+  Int4 k,j;
+  f_metrix >>  k >> j ;
+  if(verbosity>1)
+    cout << "  -- ReadMetric  " << fmetrix 
+	 << ",  coef = " << coef
+	 << ", hmin = " << hmin 
+	 << ", hmax = " << hmax 
+	 << (  (j == 1)? " Iso " : " AnIso " ) << endl;
+  
+  if (k != nbv ||  !(j == 1 || j == 3)) {
+    cerr << " Error Pb metrix " << k << " <> " 
+	 <<  nbv << " or  1 or 3  <> " << j << endl;
+    MeshError(1003);}
+	 
+  
+  //  Int4 nberr = 0;
+  for (Int4 iv=0;iv<nbv;iv++)
+    {
+    Real8 h;
+    if (j == 1) 
+      {
+      f_metrix >>  h ;
+      vertices[iv].m=Metric(Max(hmin,Min(hmax, h*coef)));
+      }
+    else if (j==3) 
+      {
+	Real8 a,b,c;	     
+	f_metrix >>  a >> b >> c  ;
+	MetricAnIso M(a,b,c);
+	MatVVP2x2 Vp(M/coef);
+	Vp.Maxh(hmin);
+      Vp.Minh(hmax);
+      vertices[iv].m = Vp;
+      }
+    }
+  
+}
+
+
+Real8 LengthInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB)
+{
+  Real8 k=1./2.;
+  int level=0;
+  static int kkk=0;
+  static  Metric Ms1[32],Ms2[32];
+  static Real8 lMs1[32],lMs2[32];
+  static double K[32];
+  Real8 l=0,sss=0;
+  Ms1[level]=Ma;
+  Ms2[level]=Mb;
+  Real8 sa =  Ma(AB);
+  Real8 sb =  Mb(AB);
+  lMs1[level]=sa;
+  lMs2[level]=sb;
+  K[level]=k;
+  level++;
+  int i=0;
+  Real8 * L= LastMetricInterpole.L, *S = LastMetricInterpole.S;
+  Real8  sstop = 0.1; // Max(0.6,(sa+sb)/5000);
+  while (level) {
+    level--;
+    Metric M1=Ms1[level];
+    Metric M2=Ms2[level];
+    k=K[level];
+    Real8 s1=  lMs1[level];
+    Real8 s2=  lMs2[level];
+
+    Real8 s= (s1+s2)*k;
+//    if (level >20  && i < 2030-level)
+//    cout << "                  level " << level << " " << i << " " << s << " " << k <<endl;
+    if( s > sstop   && level < 30 && i < 500-level ) {
+      Metric Mi(0.5,M1,0.5,M2);
+      Real8 si = Mi(AB);
+      if( Abs((s1+s2)-(si+si)) > s1*0.001) 
+	{
+	  k=k/2;
+	  // we begin by the end to walk in the correct sens from a to b
+	       // due to the stack 
+	       Ms1[level]=Mi;
+	  Ms2[level]=M2;
+	  lMs1[level]=si;
+	  lMs2[level]=s2;
+	  K[level]=k;
+	  level++;
+	  Ms1[level]=M1;
+	  Ms2[level]=Mi;
+	  lMs1[level]=s1;
+	  lMs2[level]=si;
+	  K[level]=k;
+	  level++;
+	}
+      else
+	L[i]= l += s,S[i]=sss+=k,i++;
+    }
+    else 
+      L[i]= l += s,S[i]=sss+=k,i++;//cout << i << " l = " << l << " sss = " << sss << endl;
+  }
+  // warning for optimisation S is in [0:0.5] not in [0:1]
+  assert(i<512);
+  LastMetricInterpole.lab=l;
+  LastMetricInterpole.opt=i;
+  if (i>200 && kkk++<10)
+     cout << "Warning LengthInterpole: ( i = " << i << " l = " << l << " sss " << sss << " ) " << sstop <<endl;
+  return l;
+}
+
+Real8 abscisseInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB,Real8 s,int optim)
+{ 
+  if(!optim)  LengthInterpole(Ma,Mb,AB);
+  Real8 l  = s* LastMetricInterpole.lab,r;
+  int j=LastMetricInterpole.opt-1,i=0,k;
+  
+  Real8 * L= LastMetricInterpole.L, *S = LastMetricInterpole.S;
+  // warning for optimisation S is the abcisse in [0:0.5]
+  // and L is le lenght 
+  if(l<=L[0])
+    r=2*S[0]*l/L[0];
+  else if (l>=L[j])
+    r=1;
+  else 
+    {
+      while (j-i>1)
+	{
+	  k= (i+j)/2;
+	  if(l<=L[k])
+	    j=k;// l<=L[j] 
+	  else
+	    i=k; //  L[i]<l
+	};
+      //   cout  << i << " " << j  <<" " << L[i] << " " << L[j] << " " << S[i] << " " <<  S[j]  << " l=" << l << endl;
+      if (i==j)
+	r = 2*S[i];
+      else
+	r =  2*(S[i]*(L[j]-l)+ S[j]*(l-L[i]))/(L[j]-L[i]);
+    }
+  assert(r<=1 && r>=0);
+  return r ;
+    
+}
+
+
+#ifdef DRAWING 
+
+void MetricAnIso::Draw(R2 c) const 
+{ 
+  float x= c.x,y= c.y;
+  if (InPtScreen(x,y)) {
+  R2 X(cos(0.0),sin(0.0));
+  X = X / operator()(X);
+  rmoveto(x+X.x,y+X.y);
+  
+  for (int i=1;i<=100;i++)
+   { double t= 2*Pi*i/100.0;
+     R2 X(cos(t),sin(t));
+     X = X / Max(operator()(X),1.0e-5);
+     rlineto(x+X.x,y+X.y); } 
+  }
+}
+
+void MetricIso::Draw(R2 c) const 
+{ 
+  float x= c.x,y= c.y;
+  if (InPtScreen(x,y)) {
+  rmoveto(x+h,y);
+  for (int i=1;i<=40;i++)
+   { double t= Pi*i/20.0;
+     rlineto(x+h*cos(t),y+h*sin(t)); } 
+  }
+}
+
+
+#endif
+}   // end of namespace bamg 
diff --git a/src/bamglib/Metric.h b/src/bamglib/Metric.h
new file mode 100644
index 0000000..18bbf4d
--- /dev/null
+++ b/src/bamglib/Metric.h
@@ -0,0 +1,225 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef TYPEMETRIX
+#define TYPEMETRIX MetricAnIso
+#endif
+
+//#include "R2.h"
+namespace bamg {
+
+typedef P2<double,double> D2;
+typedef P2xP2<double,double> D2xD2;
+
+class  MetricAnIso;
+class MatVVP2x2;
+class MetricIso;
+
+typedef TYPEMETRIX Metric;
+
+
+class MetricIso{
+  friend class MatVVP2x2;
+   Real4 h;
+public:
+  MetricIso(Real4 a): h(a){}
+  MetricIso(const MetricAnIso M);// {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));}
+  MetricIso(Real8 a11,Real8 a21,Real8 a22);// {*this=MetricAnIso(a11,a21,a22));}
+  MetricIso(): h(1) {}; // 
+  MetricIso(const Real8  a[3],const  MetricIso m0,
+	   const  MetricIso m1,const  MetricIso m2 )
+    : h(hinterpole 
+	? (a[0]*m0.h+a[1]*m1.h+a[2]*m2.h)
+	: 1/sqrt(a[0]/(m0.h*m0.h)+a[1]/(m1.h*m1.h)+a[2]/(m2.h*m2.h))) {}
+    MetricIso(const Real8  a,const  MetricIso ma,
+	          const Real8  b,const  MetricIso mb)
+    : h(hinterpole
+	? a*ma.h+b*mb.h
+	:1/sqrt(a/(ma.h*ma.h)+b/(mb.h*mb.h))) {}
+  R2 Orthogonal(const R2 A)const {return R2(-h*A.y,h*A.x);}
+  R2 Orthogonal(const I2 A)const {return R2(-h*A.y,h*A.x);}
+//  D2 Orthogonal(const D2 A)const {return D2(-h*A.y,h*A.x);}
+  Real8 operator()(R2 x) const { return sqrt((x,x))/h;};
+  Real8 operator()(R2 x,R2 y) const { return ((x,y))/(h*h);};
+  int  IntersectWith(MetricIso M) {int r=0;if (M.h<h) r=1,h=M.h;return r;}
+  MetricIso operator*(Real8 c) const {return  MetricIso(h/c);} 
+  MetricIso operator/(Real8 c) const {return  MetricIso(h*c);}
+  Real8 det() const {return 1./(h*h*h*h);}    
+  operator D2xD2(){ return D2xD2(1/(h*h),0.,0.,1/(h*h));}
+  void     Box(Real4 & hx,Real4 & hy) { hx=h,hy=h;}
+  friend ostream& operator <<(ostream& f, const  MetricIso & M)
+  {f << " h=" << M.h<< ";" ;   return f;}
+
+#ifdef DRAWING
+  void Draw(R2 ) const;
+#endif
+};
+
+
+class MetricAnIso{ public:
+  friend class MatVVP2x2;
+  Real8 a11,a21,a22;
+  MetricAnIso(Real8 a): a11(1/(a*a)),a21(0),a22(1/(a*a)){}
+  MetricAnIso(Real8 a,Real8 b,Real8 c) :a11(a),a21(b),a22(c){}
+  MetricAnIso()  {}; // 
+  MetricAnIso(const Real8  a[3],const  MetricAnIso m0,
+	      const  MetricAnIso m1,const  MetricAnIso m2 );
+  R2 mul(const R2 x)const {return R2(a11*x.x+a21*x.y,a21*x.x+a22*x.y);}
+  Real8 det() const {return a11*a22-a21*a21;}  
+  R2 Orthogonal(const R2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}
+  R2 Orthogonal(const I2 x){return R2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}
+//  D2 Orthogonal(const D2 x){return D2(-(a21*x.x+a22*x.y),a11*x.x+a21*x.y);}
+  MetricAnIso( Real8  a,const  MetricAnIso ma,
+	       Real8  b,const  MetricAnIso mb);
+  int  IntersectWith(const MetricAnIso M);
+  MetricAnIso operator*(Real8 c) const {Real8 c2=c*c;return  MetricAnIso(a11*c2,a21*c2,a22*c2);} 
+  MetricAnIso operator/(Real8 c) const {Real8 c2=1/(c*c);return  MetricAnIso(a11*c2,a21*c2,a22*c2);} 
+  operator D2xD2(){ return D2xD2(a11,a21,a21,a22);}
+
+  Real8 operator()(R2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);};
+//  Real8 operator()(D2 x) const { return sqrt(x.x*x.x*a11+2*x.x*x.y*a21+x.y*x.y*a22);};
+  Real8 operator()(R2 x,R2 y) const { return x.x*y.x*a11+(x.x*x.y+x.y*y.x)*a21+x.y*y.y*a22;};
+  inline void  Box(Real4 &hx,Real4 &hy) const ;  
+ friend ostream& operator <<(ostream& f, const  MetricAnIso & M)
+  {f << " mtr a11=" << M.a11 << " a21=a12=" << M.a21 << " a22=" << M.a22 << ";" ;   return f;}
+#ifdef DRAWING
+  void Draw(R2 ) const;
+#endif
+  MetricAnIso(const MatVVP2x2);
+};
+
+
+class MatVVP2x2 
+{
+  friend  class MetricAnIso;
+  friend  class MetricIso;
+public:
+  double lambda1,lambda2;
+  D2 v;
+
+
+  MatVVP2x2(double r1,double r2,const D2 vp1): lambda1(r1),lambda2(r2),v(vp1){}
+  
+  void  Abs(){lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);}
+  void  pow(double p){lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);}
+  void  Min(double a) { lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;}
+  void  Max(double a) { lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;}
+
+  void Minh(double h) {Max(1.0/(h*h));}
+  void Maxh(double h) {Min(1.0/(h*h));}
+  void Isotrope() {lambda1=lambda2=bamg::Max(lambda1,lambda2);}
+  friend ostream& operator <<(ostream& f, const MatVVP2x2 & c)
+  { f << '{' << 1/sqrt(c.lambda1)<< ',' << 1/sqrt(c.lambda2) << ','<< c.v << '}' <<flush ; return f; }
+  friend istream& operator >>(istream& f,  MatVVP2x2 & c)
+  { f >> c.lambda1 >>c.lambda2 >> c.v.x >> c.v.y ;c.v /= Norme2(c.v); return f; }
+  MatVVP2x2(const MetricAnIso );
+  MatVVP2x2(const MetricIso M) :  lambda1(1/(M.h*M.h)),lambda2(1/(M.h*M.h)),v(1,0) {}
+  Real8 hmin() const {return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));}
+  Real8 hmax() const {return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));}
+  Real8 lmax() const {return bamg::Max3(lambda1,lambda2,1e-30);}
+  Real8 lmin() const {return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);}
+  Real8 Aniso2() const  { return lmax()/lmin();}
+  inline void BoundAniso2(const Real8 coef);
+  Real8 Aniso() const  { return sqrt( Aniso2());}
+  void BoundAniso(const Real8 c){ BoundAniso2(1/(c*c));}
+  void operator *=(double coef){ lambda1*=coef;lambda2*=coef;}
+};
+
+inline void  MatVVP2x2::BoundAniso2(const Real8 coef) 
+{
+  if (coef<=1.00000000001) 
+    if (lambda1 < lambda2)
+      lambda1 = bamg::Max(lambda1,lambda2*coef);
+    else
+      lambda2 = bamg::Max(lambda2,lambda1*coef);
+  else  // a verifier 
+    if (lambda1 > lambda2)
+      lambda1 = bamg::Min(lambda1,lambda2*coef);
+    else
+      lambda2 = bamg::Min(lambda2,lambda1*coef);
+}
+
+
+
+
+void ReductionSimultanee( MetricAnIso M1,  MetricAnIso M2,double & l1,double & l2, D2xD2 & V) ;
+
+inline MetricAnIso::MetricAnIso(const MatVVP2x2 M)  
+{
+ //     recompose M in: M = V^t lambda V 
+  //     V = ( v,v^\perp)
+  //  where v^\perp = (-v_1,v_0)
+  double v00=M.v.x*M.v.x;
+  double v11=M.v.y*M.v.y;
+  double v01=M.v.x*M.v.y;
+  a11=v00*M.lambda1+v11*M.lambda2;
+  a21=v01*(M.lambda1-M.lambda2);
+  a22=v00*M.lambda2+v11*M.lambda1;
+}
+
+
+inline   void  MetricAnIso::Box(Real4 &hx,Real4 &hy) const 
+{
+  Real8 d=  a11*a22-a21*a21;
+  hx = sqrt(a22/d);
+  hy = sqrt(a11/d);
+  //  cerr << " hx = " << hx << " hy =  " << hy << endl;
+}
+
+
+inline MetricIso::MetricIso(const MetricAnIso M) 
+  {MatVVP2x2 vp(M);h=1/sqrt(Max(vp.lambda1,vp.lambda2));}
+  
+inline  MetricIso::MetricIso(Real8 a11,Real8 a21,Real8 a22)
+  {MatVVP2x2 vp(MetricAnIso(a11,a21,a22));h=1/sqrt(Max(vp.lambda1,vp.lambda2));}
+
+
+
+class SaveMetricInterpole {
+  friend  Real8 LengthInterpole(const MetricAnIso ,const  MetricAnIso , R2 );
+  friend Real8 abscisseInterpole(const MetricAnIso ,const  MetricAnIso , R2 ,Real8 ,int );
+  int opt;
+  Real8 lab;
+  Real8 L[1024],S[1024];
+};
+
+extern SaveMetricInterpole  LastMetricInterpole; // for optimization 
+
+
+ Real8 LengthInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB);
+ Real8 abscisseInterpole(const MetricAnIso Ma,const  MetricAnIso Mb, R2 AB,Real8 s,int optim=0);
+
+
+
+inline Real8 LengthInterpole(Real8 la,Real8 lb) 
+{   return ( Abs(la - lb) < 1.0e-6*Max3(la,lb,1.0e-20) ) ?  (la+lb)/2  : la*lb*log(la/lb)/(la-lb);}
+
+inline Real8 abscisseInterpole(Real8 la,Real8 lb,Real8 lab,Real8 s)
+{ return ( Abs(la - lb) <1.0e-6*Max3(la,lb,1.0e-20))  ? s : (exp(s*lab*(la-lb)/(la*lb))-1)*lb/(la-lb);}
+
+}
diff --git a/src/bamglib/QuadTree.cpp b/src/bamglib/QuadTree.cpp
new file mode 100644
index 0000000..f001a1c
--- /dev/null
+++ b/src/bamglib/QuadTree.cpp
@@ -0,0 +1,542 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <limits.h>
+//#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+
+namespace bamg {
+
+#define INTER_SEG(a,b,x,y) (((y) > (a)) && ((x) <(b)))
+#define ABS(i) ((i)<0 ?-(i) :(i))
+#define MAX1(i,j) ((i)>(j) ?(i) :(j))
+#define NORM(i1,j1,i2,j2) MAX1(ABS((i1)-(j1)),ABS((i2)-(j2)))
+
+#define IJ(i,j,l) ( ( j & l) ? (( i & l) ? 3 : 2 ) :( ( i & l)? 1 : 0 ))
+#define I_IJ(k,l)  (( k&1) ? l : 0)
+#define J_IJ(k,l)  (( k&2) ? l : 0)
+
+
+#ifdef DRAWING
+
+void  QuadTree::Draw()
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+   int l=0; // level
+   QuadTreeBox * b;
+  IntQuad hb =  MaxISize;
+  if(!root) return;
+  //  Int4 kkk =0;
+  pb[0]=  root;
+  pi[0]= root->n>0 ?(int)  root->n : 4  ;
+  ii[0]=jj[0]=0;
+  do{    
+    b= pb[l];
+
+    while (pi[l]--)
+      { 
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	    { // 
+	      for (int k=0;k<b->n;k++)
+		{
+		  I2 i2 =  b->v[k]->i;
+		  IMoveTo(i2.x,i2.y+50);
+		  ILineTo(i2.x,i2.y-50);
+		  IMoveTo(i2.x+50,i2.y);
+		  ILineTo(i2.x-50,i2.y);
+
+		  assert(ii[l] <= i2.x);
+		  assert(jj[l] <= i2.y);
+		  assert(ii[l] +hb > i2.x);
+		  assert(jj[l] +hb > i2.y);
+
+		}
+	      break;
+	    }
+	else // Pointer QuadTreeBox 
+	    { 
+	       int lll = pi[l];
+	       QuadTreeBox *b0=b;
+	      
+	      if ((b=b->b[lll])) 
+		{ 
+		  hb >>=1 ; // div by 2
+		   Icoor1 iii = ii[l]+I_IJ(lll,hb);
+		   Icoor1 jjj = jj[l]+J_IJ(lll,hb);
+		  
+		  pb[++l]=  b;
+		  pi[l]= 4;
+		  ii[l]= iii;
+		  jj[l]= jjj;
+		  
+		  IMoveTo(ii[l],jj[l]);
+		  ILineTo(ii[l]+hb,jj[l]);
+		  ILineTo(ii[l]+hb,jj[l]+hb);
+		  ILineTo(ii[l]   ,jj[l]+hb);
+		  ILineTo(ii[l]   ,jj[l]);
+		  
+		  
+		}
+	      else
+		{
+		   Icoor1 iii = ii[l]+I_IJ(lll,hb/2);
+		   Icoor1 jjj = jj[l]+J_IJ(lll,hb/2);
+		  b=b0;
+
+		  IMoveTo(iii,     jjj);
+		  ILineTo(iii+hb/2,jjj+hb/2);
+		  IMoveTo(iii+hb/2,jjj);
+		  ILineTo(iii     ,jjj+hb/2);
+
+		}
+	    }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+
+}
+
+#endif
+
+Vertex *  QuadTree::NearestVertex(Icoor1 i,Icoor1 j)
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+   int l=0; // level
+   QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  Icoor1  i0=0,j0=0;
+  Icoor1  iplus( i<MaxISize?(i<0?0:i):MaxISize-1);
+  Icoor1  jplus( j<MaxISize?(j<0?0:j):MaxISize-1);
+  
+  Vertex *vn=0;
+  
+  // init for optimisation ---
+  b = root;
+   Int4  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+       Icoor1 hb2 = hb >> 1 ;
+        int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+       QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;	
+      i0 += I_IJ(k,hb2); // i orign of QuadTreeBox
+      j0 += J_IJ(k,hb2); // j orign of QuadTreeBox 
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for( int k=0;k<n0;k++)
+	{
+	  I2 i2 =  b->v[k]->i;
+	  h0 = NORM(iplus,i2.x,jplus,i2.y);
+	  if (h0 <h) {
+	    h = h0;
+	    vn = b->v[k];}
+	  NbVerticesSearch++;
+	}
+      return vn;
+    }
+  // general case -----
+  pb[0]= b;
+  pi[0]=b->n>0 ?(int)  b->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+	 int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  b->v[k]->i;
+	    h0 = NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) 
+	      {
+		h = h0;
+		vn = b->v[k];
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	     QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+		 Icoor1 iii = ii[l]+I_IJ(k,hb);
+		 Icoor1 jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return vn;
+}
+
+
+
+Vertex *   QuadTree::ToClose(Vertex & v,Real8 seuil,Icoor1 hx,Icoor1 hy)
+{
+  const Icoor1 i=v.i.x;
+  const Icoor1 j=v.i.y;
+  const R2 X(v.r);
+  const Metric  Mx(v.m);
+
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+   int l=0; // level
+   QuadTreeBox * b;
+  Icoor1 h=MaxISize;
+  Icoor1 hb =  MaxISize;
+  Icoor1 i0=0,j0=0;
+  
+  //  Vertex *vn=0;
+  
+  if (!root->n)
+    return 0; // empty tree 
+  
+  // general case -----
+  pb[0]=root;
+  pi[0]=root->n>0 ?(int)  root->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+	 int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  b->v[k]->i;
+	    if ( ABS(i-i2.x) <hx && ABS(j-i2.y) <hy )
+	      {
+		R2 XY(X,b->v[k]->r);
+		Real8 dd;
+	      // old code	        if( Mx(XY) + b->v[k]->m(XY) < seuil )
+	        if( (dd= LengthInterpole(Mx(XY), b->v[k]->m(XY)))  < seuil )
+		  {
+		    //  cout <<  CurrentTh->Number(v) << "is To Close " 
+		    // << CurrentTh->Number( b->v[k]) << " l=" <<dd<<endl;
+		    return b->v[k]; 
+		  }
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	     QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k]))
+	      {
+		hb >>=1 ; // div by 2
+		 long iii = ii[l]+I_IJ(k,hb);
+		 long jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,i-hx,i+hx) && INTER_SEG(jjj,jjj+hb,j-hy,j+hy)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return 0;
+}
+
+
+void  QuadTree::Add( Vertex & w)
+{
+  QuadTreeBox ** pb , *b;
+   long i=w.i.x, j=w.i.y,l=MaxISize;
+  pb = &root;
+  //    cout << pb << " " << &root << endl;
+  while( (b=*pb) && (b->n<0))
+    { 
+      b->n--;
+      l >>= 1;
+      pb = &b->b[IJ(i,j,l)];
+    }
+  if  (b) {      
+    if (b->n > 3 &&  b->v[3] == &w) return;
+    if (b->n > 2 &&  b->v[2] == &w) return;
+    if (b->n > 1 &&  b->v[1] == &w) return;
+    if (b->n > 0 &&  b->v[0] == &w) return;
+  }
+  assert(l);
+  while ((b= *pb) && (b->n == 4)) // the QuadTreeBox is full
+    { 
+      Vertex *v4[4]; // copy of the QuadTreeBox vertices
+      
+      v4[0]= b->v[0];
+      v4[1]= b->v[1];
+      v4[2]= b->v[2];
+      v4[3]= b->v[3];
+      b->n = -b->n; // mark is pointer QuadTreeBox
+      b->b[0]=b->b[1]=b->b[2]=b->b[3]=0; // set empty QuadTreeBox ptr
+      l >>= 1;    // div the size by 2
+      for ( int k=0;k<4;k++) // for the 4 vertices find the sub QuadTreeBox ij
+	{ 
+	   int ij;
+	   QuadTreeBox * bb =  b->b[ij=IJ(v4[k]->i.x,v4[k]->i.y,l)];
+	  if (!bb) 
+	    bb=b->b[ij]=NewQuadTreeBox(); // alloc the QuadTreeBox 
+	  //    cout << bb << " " << k << " "  << ij <<  endl;
+	  bb->v[bb->n++] = v4[k];
+	}
+      pb = &b->b[IJ(i,j,l)];
+    }
+  if (!(b = *pb))
+    b=*pb= NewQuadTreeBox(); //  alloc the QuadTreeBox 
+  //   cout << b << " " << b->n << endl;
+  b->v[b->n++]=&w; // we add the vertex 
+  NbVertices++;    
+}
+
+QuadTree::QuadTree(Triangles * t,long nbv) : 
+  lenStorageQuadTreeBox(t->nbvx/8+10),
+  th(t),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0)
+{ 
+  if (nbv == -1) nbv = t->nbv;
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+  assert( MaxISize > MaxICoor);
+  for (Int4 i=0;i<nbv;i++) 
+    Add(t->vertices[i]);
+#ifdef DRAWING1
+  Draw();
+#endif
+}
+
+QuadTree::QuadTree() : 
+  lenStorageQuadTreeBox(100),
+  th(0),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0)
+{
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+}
+QuadTree::StorageQuadTreeBox::StorageQuadTreeBox(long ll,StorageQuadTreeBox *nn)
+{
+  len = ll;
+  n = nn;
+  b = new QuadTreeBox[ll];
+  for (int i = 0; i <ll;i++)
+    b[i].n =0,b[i].b[0]=b[i].b[1]=b[i].b[2]=b[i].b[3]=0;
+  bc =b;
+  be = b +ll;
+  assert(b);
+}
+
+QuadTree::~QuadTree()
+{
+  delete sb; 
+  root=0;
+}
+
+ostream& operator <<(ostream& f, const  QuadTree & qt)
+{ 
+  f << " the quadtree "  << endl;
+  f << " NbQuadTreeBox = " << qt.NbQuadTreeBox 
+    << " Nb Vertices = " <<  qt.NbVertices << endl;
+  f << " NbQuadTreeBoxSearch " << qt.NbQuadTreeBoxSearch  
+    << " NbVerticesSearch " << qt.NbVerticesSearch << endl;
+  f << " SizeOf QuadTree" << qt.SizeOf() << endl;
+  //     return  dump(f,*qt.root);
+  return  f;
+}
+
+Vertex *  QuadTree::NearestVertexWithNormal(Icoor1 i,Icoor1 j)
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  Icoor1 ii[  MaxDeep ], jj [ MaxDeep];
+  int l; // level
+  QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  Icoor1  i0=0,j0=0;
+  Icoor1  iplus( i<MaxISize?(i<0?0:i):MaxISize-1);
+  Icoor1  jplus( j<MaxISize?(j<0?0:j):MaxISize-1);
+  
+  Vertex *vn=0;
+  
+  // init for optimisation ---
+  b = root;
+   Int4  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+       Icoor1 hb2 = hb >> 1 ;
+        int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+       QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;	
+      i0 += I_IJ(k,hb2); // i orign of QuadTreeBox
+      j0 += J_IJ(k,hb2); // j orign of QuadTreeBox 
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for( int k=0;k<n0;k++)
+	{
+	  I2 i2 =  b->v[k]->i;
+	  //   try if is in the right sens -- 
+	  h0 = NORM(iplus,i2.x,jplus,i2.y);
+	  if (h0 <h) {
+	    h = h0;
+	    vn = b->v[k];}
+	  NbVerticesSearch++;
+	}
+	if (vn) return vn; 
+    }
+  // general case -----
+  // INITIALISATION OF THE HEAP 
+  l =0; // level 
+  pb[0]= b;
+  pi[0]=b->n>0 ?(int)  b->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {   // walk on the tree  
+    b= pb[l];
+    while (pi[l]--) // loop on 4 element of the box
+      { 	      
+       int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  b->v[k]->i;
+	    // if good sens when try -- 
+	    
+	    h0 = NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) 
+	      {
+		h = h0;
+		vn = b->v[k];
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	     QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+		 Icoor1 iii = ii[l]+I_IJ(k,hb);
+		 Icoor1 jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return vn;
+}
+
+
+}  // end of namespace bamg
+
diff --git a/src/bamglib/QuadTree.h b/src/bamglib/QuadTree.h
new file mode 100644
index 0000000..0166981
--- /dev/null
+++ b/src/bamglib/QuadTree.h
@@ -0,0 +1,111 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+namespace bamg {
+
+const int MaxDeep = 30;
+typedef  long  IntQuad;
+const IntQuad MaxISize = ( 1L << MaxDeep);
+
+
+class Triangles;
+class Vertex;
+
+class QuadTree {
+ public:
+
+  class QuadTreeBox { 
+  public:
+
+    long n; // if n < 4 => Vertex else =>  QuadTreeBox;
+    union {
+      QuadTreeBox *b[4];
+      Vertex * v[4];
+    };
+    
+
+  }; // end class QuadTreeBox  /////////////////
+
+  class StorageQuadTreeBox {
+  public:
+    QuadTreeBox *b,*bc,*be;
+    long len;
+    StorageQuadTreeBox *n; // next StorageQuadTreeBox
+    StorageQuadTreeBox(long ,StorageQuadTreeBox * =0);
+    ~StorageQuadTreeBox()
+    { //cout <<  "~StorageQuadTreeBox " << this << " n " << n << " b " << b << endl;
+      if(n) delete n;
+      delete [] b;
+    }
+    long  SizeOf() const {
+      return len*sizeof(QuadTreeBox)+sizeof(StorageQuadTreeBox)+ (n?n->SizeOf():0);
+    }
+  }; // end class  StorageQuadTreeBox 
+  
+  StorageQuadTreeBox * sb;
+  
+  
+  long  lenStorageQuadTreeBox;
+
+public:
+  QuadTreeBox * root;
+  Triangles *th;
+  long NbQuadTreeBox,NbVertices;
+  long NbQuadTreeBoxSearch,NbVerticesSearch;
+  Vertex * NearestVertex(Icoor1 i,Icoor1 j);
+  Vertex *  NearestVertexWithNormal(Icoor1 i,Icoor1 j); // new version  
+  Vertex * ToClose(Vertex & ,Real8 ,Icoor1,Icoor1);
+  long SizeOf() const {return sizeof(QuadTree)+sb->SizeOf();}
+
+#ifdef DRAWING
+    void Draw();
+#endif
+
+  void  Add( Vertex & w);
+
+  QuadTreeBox* NewQuadTreeBox()
+  {
+    ///cout << "NewQuadTreeBox " << sb << " " << sb->bc << " " 
+    //<< sb->be << " " <<lenStorageQuadTreeBox <<endl;
+    if(! (sb->bc<sb->be)) 
+	sb=new StorageQuadTreeBox(lenStorageQuadTreeBox,sb);
+
+    assert(sb && (sb->bc->n == 0));
+    NbQuadTreeBox++;
+    return sb->bc++;
+  }
+  ~QuadTree();
+  QuadTree(Triangles * t,long nbv=-1);
+  QuadTree();
+  friend ostream& operator <<(ostream& f, const  QuadTree & qt);
+
+
+	
+};
+}
+//#undef IJ
diff --git a/src/bamglib/R2.cpp b/src/bamglib/R2.cpp
new file mode 100644
index 0000000..5e79e4b
--- /dev/null
+++ b/src/bamglib/R2.cpp
@@ -0,0 +1,31 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <iostream>
+using namespace std;
+#include "R2.h"
diff --git a/src/bamglib/R2.h b/src/bamglib/R2.h
new file mode 100644
index 0000000..cbb3df4
--- /dev/null
+++ b/src/bamglib/R2.h
@@ -0,0 +1,135 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+namespace bamg {
+template <class R,class RR> class P2xP2;
+
+template <class R,class RR>
+class P2 {
+  
+public:  
+  R x,y;
+  P2 () :x(0),y(0) {};
+  P2 (R a,R b)  :x(a),y(b)  {}
+  P2 (P2 A,P2 B) : x(B.x-A.x),y(B.y-A.y) {}
+  P2<R,RR>   operator+(const P2<R,RR> & cc) const {return P2<R,RR>(x+cc.x,y+cc.y);}
+  P2<R,RR>   operator-(const P2<R,RR> & cc) const {return P2<R,RR>(x-cc.x,y-cc.y);}
+  P2<R,RR>   operator-()  const{return P2<R,RR>(-x,-y);}
+//  RR   operator*(const P2<R,RR> & cc) const {return  (RR) x* (RR) cc.x+(RR) y* (RR) cc.y;} // produit scalaire
+  RR   operator,(const P2<R,RR> & cc) const {return  (RR) x* (RR) cc.x+(RR) y* (RR) cc.y;} // produit scalaire
+  P2<R,RR>   operator*(R  cc) const {return P2<R,RR>(x*cc,y*cc);}
+ // P2<R,RR>   operator*(RR  cc) const {return P2<R,RR>((R)(x*cc),(R)(y*cc));}
+  P2<R,RR>   operator/(R  cc) const {return P2<R,RR>(x/cc,y/cc);}
+  P2<R,RR>  operator+=(const  P2<R,RR> & cc) {x += cc.x;y += cc.y;return *this;}
+  P2<R,RR>  operator/=(const  R r) {x /= r;y /= r;return *this;}
+  P2<R,RR>  operator*=(const  R r) {x *= r;y *= r;return *this;}
+  P2<R,RR>  operator-=(const  P2<R,RR> & cc) {x -= cc.x;y -= cc.y;return *this;}
+//  P2<R,RR> Orthogonal(const   P2<R,RR> r) {return P2<R,RR>(-r.y,r.x);}
+ };
+
+template <class R,class RR>
+class P2xP2 { // x ligne 1 y ligne2 
+
+  friend ostream& operator <<(ostream& f, const P2xP2<R,RR> & c) 
+     { f << '[' << c.x << ',' << c.y << ']' <<flush ; return f; }
+     
+  friend P2<R,RR> operator*(P2<R,RR> c,P2xP2<R,RR> cc)
+     {return P2<R,RR>(c.x*cc.x.x + c.y*cc.y.x, c.x*cc.x.y + c.y*cc.y.y);} 
+
+
+ public:
+  P2<R,RR> x,y; 
+  P2xP2 (): x(),y()  {}
+  P2xP2 (P2<R,RR> a,P2<R,RR> b): x(a),y(b) {}
+  P2xP2 (P2<R,RR> a,P2<R,RR> b,P2<R,RR> c ): x(b-a),y(c-a) {}
+  P2xP2 (R xx,R xy,R yx,R yy) :x(xx,xy),y(yx,yy) {}
+  P2<R,RR> operator*(const P2<R,RR> c) const {return P2<R,RR>(x.x*c.x + x.y*c.y, y.x*c.x + y.y*c.y);}
+  P2xP2<R,RR>  operator*(P2xP2<R,RR> c) const 
+    { return  P2xP2<R,RR>(x.x*c.x.x + x.y*c.y.x,
+			  x.x*c.x.y + x.y*c.y.y,
+			  y.x*c.x.x + y.y*c.y.x,
+			  y.x*c.x.y + y.y*c.y.y);}
+  RR det() const {return (RR) x.x* (RR) y.y - (RR) x.y * (RR) y.x;}
+  P2xP2<R,RR> inv()  const
+     { RR d = (*this).det(); 
+       return P2xP2<R,RR>((R)( y.y /d) ,(R)(-x.y/d),(R)( -y.x/d) ,(R)( x.x/d) );
+     };
+   P2xP2<R,RR> t() {return P2xP2<R,RR>(x.x,y.x,x.y,y.y);} //transposer 
+   P2<R,RR>tx() {return P2<R,RR>(x.x,y.x);} 
+   P2<R,RR>ty() {return P2<R,RR>(x.y,y.y);} 
+
+};  
+
+
+
+//template  <class R,class RR>  // transposer
+//inline P2xP2<R,RR> t(P2xP2<R,RR> m) 
+//   {return P2xP2<R,RR>(m.x.x,m.y.x,m.x.y,m.y.y);} 
+
+template  <class R,class RR>  
+inline RR Det(const P2<R,RR> x,const P2<R,RR> y) {
+  return (RR) x.x * (RR) y.y - (RR) x.y * (RR) y.x ;} 
+
+template  <class R,class RR>  
+inline RR Area2 (const P2<R,RR> a,const P2<R,RR> b,const P2<R,RR> c) {
+  return Det(b-a,c-a) ;} 
+
+template  <class R,class RR>  
+inline R Norme1 (const P2<R,RR> x) {
+  return (Abs(x.x)+Abs(x.y)) ;} 
+
+template  <class R,class RR>  
+inline R NormeInfini (const P2<R,RR> x) {
+  return Max(Abs(x.x),Abs(x.y)) ;} 
+
+template  <class R,class RR>  
+inline RR Norme2_2 (const P2<R,RR> x) {
+  return (RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y ;} 
+
+template  <class R,class RR>  
+inline RR Norme2 (const P2<R,RR> x) {
+  return sqrt((RR)x.x*(RR)x.x + (RR)x.y*(RR)x.y) ;} 
+
+template  <class R,class RR>  
+inline P2<R,RR> Orthogonal (const P2<R,RR> x) {
+  return  P2<R,RR>(-x.y,x.x);} 
+
+template <class R,class RR>
+inline  ostream& operator <<(ostream& f, const P2<R,RR> & c)
+  { f << '[' << c.x << ',' << c.y <<']' <<flush ; return f; }
+
+   
+/*template  <class R,class RR>
+inline P2<R,RR> Min2(P2<R,RR> x,P2<R,RR> y) 
+   {return  P2<R,RR>(Min(x.x,y.x),Min(x.y,y.y) ;} 
+
+template  <class R,class RR>
+inline P2<R,RR> Max2(P2<R,RR> x,P2<R,RR> y) 
+   {return  P2<R,RR>(Max(x.x,y.x),Max(x.y,y.y) ;} 
+*/
+}
diff --git a/src/bamglib/SetOfE4.cpp b/src/bamglib/SetOfE4.cpp
new file mode 100644
index 0000000..c68b5ab
--- /dev/null
+++ b/src/bamglib/SetOfE4.cpp
@@ -0,0 +1,84 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <iostream> 
+using namespace std;
+#include "meshtype.h"
+#include "SetOfE4.h"
+
+namespace bamg {
+
+ SetOfEdges4::SetOfEdges4(Int4 mmx,Int4 nnx)
+   {nx=nnx;
+    nbax=mmx;
+    NbOfEdges = 0;
+    tete= new Int4 [nx];
+    Int4 i=nx;
+    while (i--)
+      tete[i] = -1;// vide 
+    Edges =new Int4Edge[nbax];
+   }
+    
+ Int4 SetOfEdges4::find(Int4 ii,Int4 jj)
+{ 
+  if (tete == 0 ) {
+    cerr <<"SetOfEdges4::find \nplus de tete de liste\n";
+    MeshError(888);}
+  Int4 n = tete[ Abs( ii ) % nx ];
+  
+  while (n >= 0) 
+    if (ii == Edges[n].i && jj == Edges[n].j)
+      return n;
+    else n = Edges[n].next;
+  return -1; // n'existe pas
+}
+
+ Int4 SetOfEdges4::add(Int4 ii,Int4 jj)
+{
+  if (tete == 0 ) {
+    cerr << "SetOfEdges4::add\n plus de tete de liste \n" << endl;
+    MeshError(888);}
+  
+  Int4 h;
+  Int4 n = tete[ h = Abs( ii ) % nx ];
+  while (n >= 0) 
+   if (ii == Edges[n].i && jj == Edges[n].j)
+            return n;
+   else n = Edges[n].next;
+  if (nbax <=NbOfEdges ) {
+    cerr << " SetOfEdges4::add\noverflow de la pile "  << nbax << " " << NbOfEdges << endl;
+    MeshError(888);}
+  
+   Edges[NbOfEdges].i=ii;
+   Edges[NbOfEdges].j=jj;
+   Edges[NbOfEdges].next= tete[h];
+   tete[h] = NbOfEdges;
+   return NbOfEdges ++;
+}
+
+
+}  // end of namespace bamg 
diff --git a/src/bamglib/SetOfE4.h b/src/bamglib/SetOfE4.h
new file mode 100644
index 0000000..5179ce9
--- /dev/null
+++ b/src/bamglib/SetOfE4.h
@@ -0,0 +1,64 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SetOfEdge4_h
+#define _SetOfEdge4_h
+
+namespace bamg {
+
+class SetOfEdges4 ;
+class Int4Edge{
+friend class SetOfEdges4;
+public:
+  Int4 i,j;
+  Int4 next; 
+};
+
+class SetOfEdges4 {
+  Int4 nx,nbax,NbOfEdges;
+  Int4 * tete; 
+  Int4Edge * Edges;
+
+public:
+  SetOfEdges4(Int4 ,Int4);// nb Edges mx , nb de sommet 
+  ~SetOfEdges4() {// cout << " delete SetofArete " << endl ;
+  delete [] tete; delete [] Edges;}
+   Int4 add (Int4 ii,Int4 jj);
+  Int4 addtrie (Int4 ii,Int4 jj) {return ii <=jj ? add (ii,jj)  : add (jj,ii) ;}
+  Int4  nb(){return NbOfEdges;}
+  Int4 find (Int4 ii,Int4 jj);
+  Int4 findtrie (Int4 ii,Int4 jj) {return ii <=jj ? find (ii,jj)  : find (jj,ii) ;}
+  // inline void close();
+  Int4 i(Int4 k){return Edges[k].i;}
+  Int4 j(Int4 k){return Edges[k].j;}
+  Int4 newarete(Int4 k){return NbOfEdges == k+1;}
+  Int4Edge & operator[](Int4 k){return  Edges[k];}
+};
+}
+
+#endif 
diff --git a/src/bamglib/meshtype.h b/src/bamglib/meshtype.h
new file mode 100644
index 0000000..e7b0ae8
--- /dev/null
+++ b/src/bamglib/meshtype.h
@@ -0,0 +1,71 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef MESHTYPE_H
+#define MESHTYPE_H
+#include <limits.h>
+namespace bamg {
+template<class T> inline T Square (const T &a) { return a*a;} 
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
+template<class T> inline double Norme (const T &a){return sqrt(a*a);}
+template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;}
+// for pb on microsoft compiler 
+template<class T> inline T Max3 (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
+template<class T> inline T Min3 (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
+
+typedef float  Real4;
+typedef double Real8;
+typedef short  Int1;
+typedef short  Int2;
+typedef long   Int4;
+
+#if LONG_BIT > 63
+// for alpha and silicon 
+ typedef int  Icoor1;  
+ typedef long   Icoor2;
+ const Icoor1 MaxICoor = 1073741823; // 2^30-1
+ const  Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ;
+
+#elif  defined(BAMG_LONG_LONG)
+ typedef long  Icoor1;
+ typedef long long   Icoor2;
+ const Icoor1 MaxICoor =   1073741823;// 2^30-1
+// not a const due to a bug in hp compiler
+#define  MaxICoor22 2305843004918726658LL
+//const  Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ;
+#else
+ typedef int  Icoor1;
+ typedef double   Icoor2;
+ const Icoor1 MaxICoor = 8388608; // 2^23
+ const  Icoor2 MaxICoor22 = Icoor2(2)*Icoor2(MaxICoor) * Icoor2(MaxICoor) ;
+#endif
+ class Triangles;
+extern void MeshError(int Err,const Triangles *Th=0) ;
+}
+#endif
diff --git a/src/bamglib/write_hdf5.cpp b/src/bamglib/write_hdf5.cpp
new file mode 100644
index 0000000..3592fb0
--- /dev/null
+++ b/src/bamglib/write_hdf5.cpp
@@ -0,0 +1,506 @@
+#include "config.h"
+extern long verbosity;
+#ifdef HAVE_HDF5
+#include "write_hdf5.hpp"
+using std::max;
+using std::min;
+
+ 
+WriteHdf5::WriteHdf5(const char *ffname, Int4 nbelem, Int4 nbvertex) : hdf5_filename(ffname),  nbofelem(nbelem), nbofvertex(nbvertex)
+{ 
+  //constructeur
+  //creation du fichier hdf5
+  file_id = H5Fcreate(hdf5_filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+  status=0;
+}
+
+WriteHdf5::~WriteHdf5()
+{
+}
+
+void WriteHdf5::WriteHdf5MeshFile2D(float coordinates[][2], int connec[][3])
+{
+  //ecriture du maillage 2D au format hdf5 pour paraview
+
+  hid_t group_id_connec;
+  hid_t group_id_coord;
+  
+  hid_t dataset_id_coord, dataspace_id_coord;
+  hid_t aid_max_x, aid_min_x, aid_max_y, aid_min_y;
+  hid_t attr_max_x, attr_min_x, attr_max_y, attr_min_y;
+  hid_t dataset_id_elem2node, dataspace_id_elem2node;
+  hid_t dataset_id_nelem, dataspace_id_nelem; 
+  hid_t dataset_id_nnode, dataspace_id_nnode; 
+  hid_t dataset_id_elemtype, dataspace_id_elemtype; 
+  hid_t dataset_id_meshtype, dataspace_id_meshtype;
+  hid_t type_id,type_mesh_id;
+  
+  hsize_t dims_coord[2];
+  hsize_t dims_x_max[1];
+  hsize_t dims_x_min[1];
+  hsize_t dims_y_max[1];
+  hsize_t dims_y_min[1];
+  hsize_t dims_elem2node[2];
+  hsize_t dims_nelem[1];
+  hsize_t dims_nnode[1];
+  
+  dims_coord[0] = nbofvertex; 
+  dims_coord[1] = 2; 
+  dims_x_max[0] = 1;
+  dims_x_min[0] = 1;
+  dims_y_max[0] = 1;
+  dims_y_min[0] = 1;
+  dims_elem2node[0] = nbofelem; 
+  dims_elem2node[1] = 3; 
+  dims_nelem[0] = 1; 
+  dims_nnode[0] = 1; 
+  
+  float x_max = coordinates[0][0];
+  float x_min = coordinates[0][0];
+  float y_max = coordinates[0][1];
+  float y_min = coordinates[0][1];
+  
+  for (int i=0;i<nbofvertex;i++) 
+    {
+      x_max= max(x_max,coordinates[i][0]);
+      y_max= max(y_max,coordinates[i][1]);
+      x_min= min(x_min,coordinates[i][0]);
+      y_min= min(y_min,coordinates[i][1]);
+    }
+   
+  //ecriture des coordonnees 2D X et Y des noeuds
+  group_id_coord = H5Gcreate2(file_id, "/Coordinates", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  dataspace_id_coord = H5Screate_simple(2, dims_coord, NULL);
+  dataset_id_coord = H5Dcreate2(file_id, "/Coordinates/XY", H5T_IEEE_F32LE, dataspace_id_coord, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_coord, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, coordinates);
+   
+  //ecriture des valeurs max des coordonnees
+  aid_max_x =  H5Screate_simple(1, dims_x_max, NULL);
+  attr_max_x = H5Acreate2(dataset_id_coord, "X_MAX",  H5T_IEEE_F32LE, aid_max_x, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_max_x, H5T_NATIVE_FLOAT, &x_max);
+  status = H5Aclose(attr_max_x);
+  status = H5Sclose(aid_max_x); 
+   
+  aid_min_x =  H5Screate_simple(1, dims_x_min, NULL);
+  attr_min_x = H5Acreate2(dataset_id_coord, "X_MIN",  H5T_IEEE_F32LE, aid_min_x, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_min_x, H5T_NATIVE_FLOAT, &x_min);
+  status = H5Aclose(attr_min_x);
+  status = H5Sclose(aid_min_x); 
+   
+  aid_max_y =  H5Screate_simple(1, dims_y_max, NULL);
+  attr_max_y = H5Acreate2(dataset_id_coord, "Y_MAX",  H5T_IEEE_F32LE, aid_max_y, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_max_y, H5T_NATIVE_FLOAT, &y_max);
+  status = H5Aclose(attr_max_y);
+  status = H5Sclose(aid_max_y); 
+   
+  aid_min_y =  H5Screate_simple(1, dims_y_min, NULL);
+  attr_min_y = H5Acreate2(dataset_id_coord, "Y_MIN",  H5T_IEEE_F32LE, aid_min_y, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_min_y, H5T_NATIVE_FLOAT, &y_min);
+  status = H5Aclose(attr_min_y);
+  status = H5Sclose(aid_min_y); 
+   
+  status = H5Dclose(dataset_id_coord);
+  status = H5Sclose(dataspace_id_coord); 
+  status = H5Gclose(group_id_coord);
+   
+  //ecriture du tableau de connectivite (3 numeros de noeud definissent 1 triangle)
+  group_id_connec = H5Gcreate2(file_id, "/Connectivity", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+
+  dataspace_id_elem2node = H5Screate_simple(2, dims_elem2node, NULL);
+  dataset_id_elem2node = H5Dcreate2(file_id, "/Connectivity/ELEM2NODE", H5T_STD_I32LE, 
+				   dataspace_id_elem2node, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_elem2node, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, connec);
+  status = H5Dclose(dataset_id_elem2node);
+  status = H5Sclose(dataspace_id_elem2node);
+
+  //ecriture du type d'elements = triangle, du nombre de triangles et du nombre de noeuds du maillage
+  char elemtype[9];
+  strcpy(elemtype,"Triangle");
+  type_id = H5Tcopy(H5T_C_S1);
+  status  = H5Tset_size(type_id, 8);
+  dataspace_id_elemtype = H5Screate(H5S_SCALAR); 
+  dataset_id_elemtype=H5Dcreate2(file_id, "/Connectivity/ELEMTYPE", type_id, 
+				dataspace_id_elemtype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_elemtype, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, elemtype);
+  status = H5Dclose(dataset_id_elemtype);
+  status = H5Sclose(dataspace_id_elemtype);
+   
+  dataspace_id_nelem = H5Screate_simple(1, dims_nelem, NULL);
+  dataset_id_nelem = H5Dcreate2(file_id, "/Connectivity/NELEM", H5T_STD_I32LE, 
+			       dataspace_id_nelem, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_nelem, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &nbofelem);
+  status = H5Dclose(dataset_id_nelem);
+  status = H5Sclose(dataspace_id_nelem);
+   
+  dataspace_id_nnode = H5Screate_simple(1, dims_nnode, NULL);
+  dataset_id_nnode = H5Dcreate2(file_id, "/Connectivity/NNODE", H5T_STD_I32LE, 
+			       dataspace_id_nnode, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_nnode, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, &nbofvertex);
+  status = H5Dclose(dataset_id_nnode);
+  status = H5Sclose(dataspace_id_nnode);
+
+  //ecriture du type de connectivite
+  char meshtype[8];
+  strcpy(meshtype,"UNIFORM");
+  type_mesh_id = H5Tcopy(H5T_C_S1);
+  status  = H5Tset_size(type_mesh_id, 7);
+  dataspace_id_meshtype = H5Screate(H5S_SCALAR);
+  dataset_id_meshtype=H5Dcreate2(file_id, "/Connectivity/TYPE", type_mesh_id, 
+				dataspace_id_meshtype, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_meshtype, type_mesh_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, meshtype);
+  status = H5Dclose(dataset_id_meshtype);
+  status = H5Sclose(dataspace_id_meshtype);
+  status = H5Tclose(type_mesh_id);
+   
+  status = H5Gclose(group_id_connec);
+   
+  status = H5Fclose(file_id);
+  if (status != 0) cout << "HDF5 error" << endl;
+  cout<<"save hdf5 file mesh : "<< hdf5_filename << endl;
+}
+
+void WriteHdf5::WriteHdf5MeshFile3D(float coordinates[][3], int connec[][4])
+{
+  //ecriture du maillage 3D au format hdf5 pour paraview
+
+  hid_t group_id_coord;
+  hid_t group_id_connec;
+  hid_t dataset_id_coord, dataspace_id_coord;
+  hid_t aid_max_x, aid_min_x, aid_max_y, aid_min_y, aid_max_z, aid_min_z;
+  hid_t attr_max_x, attr_min_x, attr_max_y, attr_min_y,  attr_max_z, attr_min_z;
+  hid_t dataset_id_elem2node, dataspace_id_elem2node;
+  hid_t dataset_id_elemtype, dataspace_id_elemtype; 
+  hid_t dataset_id_nelem, dataspace_id_nelem; 
+  hid_t dataset_id_nnode, dataspace_id_nnode; 
+  hid_t dataset_id_meshtype, dataspace_id_meshtype;
+  hid_t type_id,type_mesh_id;
+  
+  hsize_t dims_coord[2];
+  hsize_t dims_x_max[1];
+  hsize_t dims_x_min[1];
+  hsize_t dims_y_max[1];
+  hsize_t dims_y_min[1];
+  hsize_t dims_z_max[1];
+  hsize_t dims_z_min[1];
+  hsize_t dims_elem2node[2];
+  hsize_t dims_nelem[1];
+  hsize_t dims_nnode[1];
+
+  dims_coord[0] = nbofvertex;
+  dims_coord[1] = 3;
+  dims_x_max[0] = 1;
+  dims_x_min[0] = 1;
+  dims_y_max[0] = 1;
+  dims_y_min[0] = 1;
+  dims_z_max[0] = 1;
+  dims_z_min[0] = 1;
+  dims_elem2node[0] = nbofelem; 
+  dims_elem2node[1] = 4; 
+  dims_nelem[0] = 1; 
+  dims_nnode[0] = 1; 
+  
+  float x_max = 0 ;
+  float x_min = 0 ;
+  float y_max = 0 ;
+  float y_min = 0 ;
+  float z_max = 0 ;
+  float z_min = 0 ;
+
+  for (int i=0;i<nbofvertex;i++) 
+    {
+      x_max= max(x_max,coordinates[i][0]);
+      y_max= max(y_max,coordinates[i][1]);
+      z_max= max(z_max,coordinates[i][2]);
+      x_min= min(x_min,coordinates[i][0]);
+      y_min= min(y_min,coordinates[i][1]);
+      z_min= min(z_min,coordinates[i][2]);
+    }
+
+  //ecriture des coordonnees 3D X,Y,Z des noeuds
+  group_id_coord = H5Gcreate2(file_id, "/Coordinates", H5P_DEFAULT, H5P_DEFAULT, 
+			     H5P_DEFAULT);
+  dataspace_id_coord = H5Screate_simple(2, dims_coord, NULL);
+  dataset_id_coord = H5Dcreate2(file_id, "/Coordinates/XYZ", H5T_IEEE_F32LE, 
+			       dataspace_id_coord, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_coord, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, 
+		    H5P_DEFAULT, coordinates);
+
+  //ecriture des valeurs max des coordonnees
+  aid_max_x =  H5Screate_simple(1, dims_x_max, NULL);
+  attr_max_x = H5Acreate2(dataset_id_coord, "X_MAX",  H5T_IEEE_F32LE, aid_max_x, 
+			 H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_max_x, H5T_NATIVE_FLOAT, &x_max);
+  status = H5Aclose(attr_max_x);
+  status = H5Sclose(aid_max_x); 
+  
+  aid_min_x =  H5Screate_simple(1, dims_x_min, NULL);
+  attr_min_x = H5Acreate2(dataset_id_coord, "X_MIN",  H5T_IEEE_F32LE, aid_min_x, 
+			 H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_min_x, H5T_NATIVE_FLOAT, &x_min);
+  status = H5Aclose(attr_min_x);
+  status = H5Sclose(aid_min_x); 
+  
+  aid_max_y =  H5Screate_simple(1, dims_y_max, NULL);
+  attr_max_y = H5Acreate2(dataset_id_coord, "Y_MAX",  H5T_IEEE_F32LE, aid_max_y, 
+			 H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_max_y, H5T_NATIVE_FLOAT, &y_max);
+  status = H5Aclose(attr_max_y);
+  status = H5Sclose(aid_max_y); 
+  
+  aid_min_y =  H5Screate_simple(1, dims_y_min, NULL);
+  attr_min_y = H5Acreate2(dataset_id_coord, "Y_MIN",  H5T_IEEE_F32LE, aid_min_y, 
+			 H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_min_y, H5T_NATIVE_FLOAT, &y_min);
+  status = H5Aclose(attr_min_y);
+  status = H5Sclose(aid_min_y); 
+  
+  aid_max_z =  H5Screate_simple(1, dims_z_max, NULL);
+  attr_max_z = H5Acreate2(dataset_id_coord, "Z_MAX",  H5T_IEEE_F32LE, aid_max_z, 
+			 H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_max_z, H5T_NATIVE_FLOAT, &z_max);
+  status = H5Aclose(attr_max_z);
+  status = H5Sclose(aid_max_z); 
+  
+  aid_min_z =  H5Screate_simple(1, dims_z_min, NULL);
+  attr_min_z = H5Acreate2(dataset_id_coord, "Z_MIN",  H5T_IEEE_F32LE, aid_min_z, 
+			 H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_min_z, H5T_NATIVE_FLOAT, &z_min);
+  status = H5Aclose(attr_min_z);
+  status = H5Sclose(aid_min_z); 
+  
+  status = H5Dclose(dataset_id_coord);
+  status = H5Sclose(dataspace_id_coord); 
+  status = H5Gclose(group_id_coord);
+
+  //ecriture du tableau de connectivite (4 numeros de noeud definissent 1 tetraedre)
+  group_id_connec = H5Gcreate2(file_id, "/Connectivity", H5P_DEFAULT, H5P_DEFAULT, 
+			      H5P_DEFAULT);
+
+  dataspace_id_elem2node = H5Screate_simple(2, dims_elem2node, NULL);
+  dataset_id_elem2node = H5Dcreate2(file_id, "/Connectivity/ELEM2NODE", H5T_STD_I32LE, 
+				   dataspace_id_elem2node, H5P_DEFAULT, H5P_DEFAULT, 
+				   H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_elem2node, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, 
+		    H5P_DEFAULT, connec);
+  status = H5Dclose(dataset_id_elem2node);
+  status = H5Sclose(dataspace_id_elem2node);
+
+  //ecriture du type d'elements = tetraedre, du nombre de tetraedres et du nombre de noeuds du maillage
+  char elemtype[12];
+  strcpy(elemtype,"Tetrahedron");
+  type_id = H5Tcopy(H5T_C_S1);
+  status  = H5Tset_size(type_id, 11);
+  dataspace_id_elemtype = H5Screate(H5S_SCALAR);
+  dataset_id_elemtype=H5Dcreate2(file_id, "/Connectivity/ELEMTYPE", type_id, 
+				dataspace_id_elemtype, H5P_DEFAULT, H5P_DEFAULT, 
+				H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_elemtype, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, 
+		    elemtype);
+  status = H5Dclose(dataset_id_elemtype);
+  status = H5Sclose(dataspace_id_elemtype);
+  
+  dataspace_id_nelem = H5Screate_simple(1, dims_nelem, NULL);
+  dataset_id_nelem = H5Dcreate2(file_id, "/Connectivity/NELEM", H5T_STD_I32LE, 
+			       dataspace_id_nelem, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_nelem, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, 
+		    &nbofelem);
+  status = H5Dclose(dataset_id_nelem);
+  status = H5Sclose(dataspace_id_nelem);
+  
+  dataspace_id_nnode = H5Screate_simple(1, dims_nnode, NULL);
+  dataset_id_nnode = H5Dcreate2(file_id, "/Connectivity/NNODE", H5T_STD_I32LE, 
+			       dataspace_id_nnode, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_nnode, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, 
+		    &nbofvertex);
+  status = H5Dclose(dataset_id_nnode);
+  status = H5Sclose(dataspace_id_nnode);
+
+  //ecriture du type de connectivite
+  char meshtype[8];
+  strcpy(meshtype,"UNIFORM");
+  type_mesh_id = H5Tcopy(H5T_C_S1);
+  status  = H5Tset_size(type_mesh_id, 7);
+  dataspace_id_meshtype = H5Screate(H5S_SCALAR);
+  dataset_id_meshtype=H5Dcreate2(file_id, "/Connectivity/TYPE", type_mesh_id, 
+				dataspace_id_meshtype, H5P_DEFAULT, H5P_DEFAULT, 
+				H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_meshtype, type_mesh_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, 
+		    meshtype);
+  status = H5Dclose(dataset_id_meshtype);
+  status = H5Sclose(dataspace_id_meshtype);
+  status = H5Tclose(type_mesh_id);
+  
+  status = H5Gclose(group_id_connec);
+  
+  status = H5Fclose(file_id);
+
+  if (status != 0) cout << "HDF5 error" << endl;
+  cout <<"save hdf5 file mesh : "<< hdf5_filename << endl;
+}
+
+void WriteHdf5::WriteHdf5SolFile2DInit() 
+{  
+  //creation du groupe /Data contenant toutes les donnees solution
+  group_id_data = H5Gcreate2(file_id, "/Data", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+}
+
+void WriteHdf5::WriteHdf5SolFile2DAddField(string * fieldname, int result_order, int trans_dim, int what_type, float *field)
+{
+  //ajout des champs solution dans le groupe /Data
+
+  string str_data="/Data/";
+  size_t size_data = str_data.size() + 1;
+  string str_float="FLOAT_";
+  size_t size_str_float=str_float.size() + 1;
+  string str_underscore="_";
+  size_t size_str_underscore=str_underscore.size() + 1;
+  char data_type[17]; 
+  hid_t dataset_id_data, dataspace_id_data;
+  hid_t type_id;
+  hid_t attr_type;
+  hid_t aid_type;
+  hsize_t dims_data[2];// coorect FH.
+  vector<string> type_char(3);
+  vector<string> res_char(2);
+ 
+  type_char[0]= "Scalar"; 
+  type_char[1]= "Vector"; 
+  type_char[2]= "Vector"; 
+  res_char[0]= "Cell";  
+  res_char[1]= "Node";
+
+  size_t size_datafieldname = fieldname->size() + 1;
+  char * char_datafieldname = new char[size_datafieldname];
+  strncpy(char_datafieldname, fieldname->c_str(), size_datafieldname);
+  char * char_datafieldname_tot=new char[size_data+size_datafieldname];
+  strncpy(char_datafieldname_tot, str_data.c_str(), size_data);
+  strncat(char_datafieldname_tot,char_datafieldname,size_data+size_datafieldname);
+  strncpy(data_type, str_float.c_str(), size_str_float);
+
+  if(result_order==0) 
+    {
+      dims_data[0] = nbofelem;
+    }
+  else
+    {
+      dims_data[0] = nbofvertex;
+    }
+  dims_data[1] = trans_dim;
+   
+  //ajout des champs fonction de la dimension de l'element (triangle ou noeud) et du type
+  //de donnees (vecteur, ...) affectees a l'element
+  strncat(data_type,  res_char[result_order].c_str(), size_str_float + (res_char[result_order].size()+1));
+  strncat(data_type, str_underscore.c_str(), size_str_float 
+  	  + (res_char[result_order].size()+1) + size_str_underscore);
+  strncat(data_type, type_char[what_type].c_str(), 
+  	  size_str_float + (res_char[result_order].size()+1) 
+  	  + size_str_underscore + (type_char[what_type].size() + 1));
+  dataspace_id_data = H5Screate_simple(2, dims_data, NULL);
+  dataset_id_data = H5Dcreate2(file_id, char_datafieldname_tot, H5T_IEEE_F32LE, 
+  			      dataspace_id_data, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_data, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, field);
+  type_id = H5Tcopy(H5T_C_S1);
+  status  = H5Tset_size(type_id, 17);
+  aid_type =  H5Screate(H5S_SCALAR);
+  attr_type = H5Acreate2(dataset_id_data, "TYPE",  type_id, aid_type, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_type, type_id, data_type);
+  status = H5Aclose(attr_type);
+  status = H5Sclose(aid_type);
+  status = H5Dclose(dataset_id_data);
+  status = H5Sclose(dataspace_id_data);
+  delete [] char_datafieldname;
+  delete [] char_datafieldname_tot;
+}
+
+void WriteHdf5::WriteHdf5SolFile2DFinalize()
+{ 
+  //fermeture du groupe /Data et du fichier hdf5
+  status = H5Gclose(group_id_data);
+  status = H5Fclose(file_id); 
+  if (status != 0) cout << "HDF5 error" << endl;
+  if(verbosity>2) cout << "save hdf5 file solution : " << hdf5_filename <<endl;
+}
+
+void WriteHdf5::WriteHdf5SolFile3DInit()
+{
+  //creation du groupe /Data contenant toutes les donnees solution
+  group_id_data = H5Gcreate2(file_id, "/Data", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+}
+
+void WriteHdf5::WriteHdf5SolFile3DAddField(string * fieldname, int result_order, int trans_dim, int what_type, float *field)
+{
+  //ajout des champs solution dans le groupe /Data
+
+  string str_data="/Data/";
+  size_t size_data = str_data.size() + 1;
+  string str_float="FLOAT_";
+  size_t size_str_float=str_float.size() + 1;
+  string str_underscore="_";
+  size_t size_str_underscore=str_underscore.size() + 1;
+  char data_type[18]; 
+  hid_t dataset_id_data, dataspace_id_data;
+  hid_t type_id;
+  hid_t attr_type;
+  hid_t aid_type;
+  hsize_t dims_data[2];// correct FH. 1->2
+  vector<string> type_char(3);
+  vector<string> res_char(2);
+
+  type_char[0]= "Scalar"; 
+  type_char[1]= "Vector"; 
+  type_char[2]= "Tensor6"; 
+  res_char[0]= "Cell";  
+  res_char[1]= "Node";
+
+  size_t size_datafieldname = fieldname->size() + 1;
+  char * char_datafieldname = new char[size_datafieldname];
+  strncpy(char_datafieldname, fieldname->c_str(), size_datafieldname);
+  char * char_datafieldname_tot=new char[size_data+size_datafieldname];
+  strncpy(char_datafieldname_tot, str_data.c_str(), size_data);
+  strncat(char_datafieldname_tot,char_datafieldname,size_data+size_datafieldname);
+  strncpy(data_type, str_float.c_str(), size_str_float);
+
+  if(result_order==0) 
+    {
+      dims_data[0] = nbofelem;
+    }
+  else
+    {
+      dims_data[0] = nbofvertex;
+    }
+  dims_data[1] = trans_dim;
+
+  //ajout des champs fonction de la dimension de l'element (tetraedre ou noeud) et du type
+  //de donnees (tenseur de 6 composantes, ...) affectees a l'element
+  strncat(data_type,  res_char[result_order].c_str(), size_str_float + (res_char[result_order].size()+1));
+  strncat(data_type, str_underscore.c_str(), size_str_float 
+  	  + (res_char[result_order].size()+1) + size_str_underscore);
+  strncat(data_type, type_char[what_type].c_str(), 
+  	  size_str_float + (res_char[result_order].size()+1) 
+  	  + size_str_underscore + (type_char[what_type].size() + 1));
+  dataspace_id_data = H5Screate_simple(2, dims_data, NULL);
+  dataset_id_data = H5Dcreate2(file_id, char_datafieldname_tot, H5T_IEEE_F32LE, 
+  			      dataspace_id_data, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Dwrite(dataset_id_data, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, field);
+  type_id = H5Tcopy(H5T_C_S1);
+  status  = H5Tset_size(type_id, 18);
+  aid_type =  H5Screate(H5S_SCALAR);
+  attr_type = H5Acreate2(dataset_id_data, "TYPE",  type_id, aid_type, H5P_DEFAULT, H5P_DEFAULT);
+  status = H5Awrite(attr_type, type_id, data_type);
+  status = H5Aclose(attr_type);
+  status = H5Sclose(aid_type);
+  status = H5Dclose(dataset_id_data);
+  status = H5Sclose(dataspace_id_data);
+  delete [] char_datafieldname;
+  delete [] char_datafieldname_tot;
+}
+
+void WriteHdf5::WriteHdf5SolFile3DFinalize()
+{
+  //fermeture du groupe /Data et du fichier hdf5
+  status = H5Gclose(group_id_data);
+  status = H5Fclose(file_id); 
+  if (status != 0) cout << "HDF5 error" << endl;
+  if(verbosity>2) cout << "save hdf5 file solution : " << hdf5_filename <<endl;
+}
+#endif
diff --git a/src/bamglib/write_hdf5.hpp b/src/bamglib/write_hdf5.hpp
new file mode 100644
index 0000000..4609c9a
--- /dev/null
+++ b/src/bamglib/write_hdf5.hpp
@@ -0,0 +1,57 @@
+#ifndef write_hdf5_h_
+#define write_hdf5_h_
+ 
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <cmath>
+#include <algorithm>
+
+#ifndef H5_NO_NAMESPACE
+#ifndef H5_NO_STD
+    using std::cout;
+    using std::endl;
+#endif  // H5_NO_STD
+#endif
+
+#include "H5Cpp.h"
+
+#ifndef H5_NO_NAMESPACE
+    using namespace H5;
+#endif
+
+using namespace std;
+using std::string;
+using std::vector;
+typedef long   Int4;
+
+class WriteHdf5
+{ 
+private:
+  ofstream hdf5_file;
+  const char * hdf5_filename;
+  Int4 nbofelem;
+  Int4 nbofvertex;
+  Int4 nbvperelem;
+  hid_t file_id;
+  hid_t group_id_data;
+  herr_t status;
+  int dimension;
+ 
+public:
+
+  WriteHdf5(const char * ffname, Int4 nbelem, Int4 nbvertex);
+  virtual ~WriteHdf5();
+  void WriteHdf5MeshFile2D(float coordinates[][2], int connec[][3]);
+  void WriteHdf5MeshFile3D(float coordinates[][3], int connec[][4]);
+  void WriteHdf5SolFile2DInit();
+  void WriteHdf5SolFile2DAddField(string * fieldname, int result_order, int trans_dim, int what_type, float *field);
+  void WriteHdf5SolFile2DFinalize();
+  void WriteHdf5SolFile3DInit();
+  void WriteHdf5SolFile3DAddField(string * fieldname, int result_order, int trans_dim, int what_type, float *field);
+  void WriteHdf5SolFile3DFinalize();
+};
+
+#endif
diff --git a/src/bamglib/write_xdmf.cpp b/src/bamglib/write_xdmf.cpp
new file mode 100644
index 0000000..0007aff
--- /dev/null
+++ b/src/bamglib/write_xdmf.cpp
@@ -0,0 +1,265 @@
+#include "write_xdmf.hpp"
+#ifdef DEBUG
+int debug_w=1;
+#else
+int debug_w=0;
+#endif
+
+
+//La denomination, au niveau des fichiers d'input,
+//des fichiers de maillage ou solution sont en partie fixes :
+//Le nom des fichiers de maillage doit se finir par .mesh.h5
+//Le nom des fichiers solution doit se finir par .sol.h5
+//L'interface ne prend en compte que les elements de type triangle et tetraedre.
+
+WriteXdmf::WriteXdmf(const char *ffname, Int4 nbelem, Int4 nbvertex) : WXffname(ffname),  nbofelem(nbelem), nbofvertex(nbvertex)
+{
+  //constructeur
+  //recuperation du nom de fichier passe dans l'input
+  //pour creation du nom de fichier xdmf
+  int lll = strlen(WXffname);
+  string str_xdmf_filename=WXffname;
+  string str_xdmf="xmf";
+  str_xdmf_filename.replace(lll-2,3,str_xdmf);
+  size_t size_xdmf_filename = str_xdmf_filename.size() + 1;
+  xdmf_filename = new char[size_xdmf_filename];
+  strncpy(xdmf_filename, str_xdmf_filename.c_str(), size_xdmf_filename);
+}
+
+WriteXdmf::~WriteXdmf()
+{
+  delete [] xdmf_filename;  
+  delete [] Elemtype;
+}
+
+void WriteXdmf::WriteXdmfMeshFile2D()
+{
+  //initialisation du type d'element : triangle
+  Elemtype= new char[strlen("Triangle")+1];
+  strcpy(Elemtype,"Triangle");
+  dimension=2;
+  nbvperelem=3; 
+ 
+  //creation et ecriture du fichier de description
+  //du maillage 2D au format xdfm pour paraview
+  xdmf_file.open (xdmf_filename);
+  xdmf_file << "<?xml version=\"1.0\" ?>\n";
+  xdmf_file << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n";
+  xdmf_file << "<Xdmf Version=\"2.0\">\n"; 
+  xdmf_file << "  <Domain>\n"; 
+  // pour l'instant nom du maillage par defaut : full mesh
+  xdmf_file << "    <Grid Name=\"" << "full mesh" << "\" GridType=\"Uniform\">\n";
+  xdmf_file << "      <Topology TopologyType=\"" << Elemtype 
+	    << "\"  NumberOfElements=\"" << nbofelem << "\">\n";
+  // nb nodes per element, ici classe triangle donc =3
+  xdmf_file << "	<DataItem Format=\"HDF\" NumberType=\"Int\" Dimensions=\"" 
+	    << nbofelem << " " << nbvperelem << "\">\n";
+  xdmf_file << "           " << WXffname  << ":/Connectivity/ELEM2NODE\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Topology>\n";
+  xdmf_file << "      <Geometry GeometryType=\"XY\">\n";
+  xdmf_file << "	<DataItem NumberType=\"Float\" Precision=\"8\" Dimensions=\""
+	    << nbofvertex << " "<< dimension << "\" Format=\"HDF\">\n";
+  xdmf_file << "           " << WXffname << ":/Coordinates/XY\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Geometry>\n";
+  xdmf_file << "    </Grid>\n";
+  xdmf_file << "  </Domain>\n";
+  xdmf_file << "</Xdmf>\n";
+  xdmf_file.close();
+
+  cout<<"save xdmf file mesh : "<< xdmf_filename << endl;
+}
+
+void WriteXdmf::WriteXdmfMeshFile3D()
+{ 
+  //initialisation du type d'element : tetraedre
+  Elemtype= new char[strlen("Tetrahedron")+1];
+  strcpy(Elemtype,"Tetrahedron");
+  dimension=3;
+  nbvperelem=4; 
+
+  //creation et ecriture du fichier de description
+  //du maillage 3D au format xdfm pour paraview
+  xdmf_file.open (xdmf_filename);
+  xdmf_file << "<?xml version=\"1.0\" ?>\n";
+  xdmf_file << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n";
+  xdmf_file << "<Xdmf Version=\"2.0\">\n"; 
+  xdmf_file << "  <Domain>\n"; 
+  //pour l'instant nom du maillage par defaut : full mesh
+  xdmf_file << "    <Grid Name=\"" << "full mesh" << "\" GridType=\"Uniform\">\n";
+  xdmf_file << "      <Topology TopologyType=\"" << Elemtype 
+	    << "\"  NumberOfElements=\"" << nbofelem << "\">\n";
+  // nb nodes per element, ici classe Tetrahedra donc = 4
+  xdmf_file << "	<DataItem Format=\"HDF\" NumberType=\"Int\" Dimensions=\"" 
+	    << nbofelem << " " << nbvperelem << "\">\n";
+  xdmf_file << "           " << WXffname  << ":/Connectivity/ELEM2NODE\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Topology>\n";
+  xdmf_file << "      <Geometry GeometryType=\"XYZ\">\n";
+  xdmf_file << "	<DataItem NumberType=\"Float\" Precision=\"8\" Dimensions=\""
+	    << nbofvertex << " "<< dimension << "\" Format=\"HDF\">\n";
+  xdmf_file << "           " << WXffname << ":/Coordinates/XYZ\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Geometry>\n";
+  xdmf_file << "    </Grid>\n";
+  xdmf_file << "  </Domain>\n";
+  xdmf_file << "</Xdmf>\n";
+  xdmf_file.close();
+
+  cout <<"save xdmf file mesh : "<< xdmf_filename << endl;
+}
+
+void WriteXdmf::WriteXdmfSolFile2DInit() 
+{ 
+  //initialisation du type d'element : triangle
+  Elemtype= new char[strlen("Triangle")+1];
+  strcpy(Elemtype,"Triangle");
+  dimension=2;
+  nbvperelem=3;
+  string str_h5_mesh="mesh.h5";
+  string str_h5_mesh_filename=WXffname;
+  str_h5_mesh_filename.replace(strlen(WXffname)-6,7,str_h5_mesh);
+
+  //creation et debut d'ecriture du fichier de description
+  //du fichier solution 2D au format xdfm pour paraview
+  //avec le lien vers le fichier de maillage hdf5 correspondant
+  xdmf_file.open (xdmf_filename);
+  xdmf_file << "<?xml version=\"1.0\" ?>\n";
+  xdmf_file << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n";
+  xdmf_file << "<Xdmf Version=\"2.0\">\n"; 
+  xdmf_file << "  <Domain>\n"; 
+  //pour l'instant nom du maillage par defaut : full mesh
+  xdmf_file << "    <Grid Name=\"" << "full mesh" << "\" GridType=\"Uniform\">\n";
+  xdmf_file << "      <Topology TopologyType=\"" << Elemtype 
+	    << "\"  NumberOfElements=\"" << nbofelem << "\">\n";
+  // nb nodes per element, ici classe triangle donc =3
+  xdmf_file << "	<DataItem Format=\"HDF\" NumberType=\"Int\" Dimensions=\"" 
+	    << nbofelem << " " << nbvperelem << "\">\n";
+  xdmf_file << "           " << str_h5_mesh_filename.c_str()  << ":/Connectivity/ELEM2NODE\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Topology>\n";
+  xdmf_file << "      <Geometry GeometryType=\"XY\">\n";
+  xdmf_file << "	<DataItem NumberType=\"Float\" Precision=\"8\" Dimensions=\""
+	    << nbofvertex << " "<< dimension << "\" Format=\"HDF\">\n";
+  xdmf_file << "           " << str_h5_mesh_filename.c_str() << ":/Coordinates/XY\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Geometry>\n";
+}
+
+void WriteXdmf::WriteXdmfSolFile2DAddField(string * fieldname, int data_type, int result_order, int trans_dim)
+{
+  vector<string> type_char(3);
+  vector<string> res_char(2);
+ 
+
+  type_char[0]= "Scalar"; 
+  type_char[1]= "Vector"; 
+  type_char[2]= "Vector"; 
+  res_char[0]= "Cell";  
+  res_char[1]= "Node";
+
+  //ecriture des descriptions du ou des champs solution 2D
+  xdmf_file << "      <Attribute Name=\"" <<  fieldname->c_str() 
+	    << "\" AttributeType=\"" << type_char[data_type]
+	    << "\" Center=\"" << res_char[result_order]<<"\">\n";
+  if(result_order==0) 
+    {
+      xdmf_file << "        <DataItem Dimensions=\" " << nbofelem  << " " << trans_dim
+		<< " \" NumberType=\"" <<"Float" << "\" Format=\"HDF\">\n";
+    }
+  else
+    {
+      xdmf_file << "        <DataItem Dimensions=\" " << nbofvertex << " " << trans_dim
+		<< " \" NumberType=\"" <<"Float" << "\" Format=\"HDF\">\n";
+    }
+  xdmf_file << "          " << WXffname << ":/Data/" <<  fieldname->c_str() <<"\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Attribute>\n";
+}
+
+void WriteXdmf::WriteXdmfSolFile2DFinalize()
+{
+  //fin d'ecriture et fermeture du fichier des descriptions solution 2D
+  xdmf_file << "    </Grid>\n";
+  xdmf_file << "  </Domain>\n";
+  xdmf_file << "</Xdmf>\n";
+  xdmf_file.close();
+  cout << "save xdmf file solution : " << xdmf_filename <<endl;
+}
+
+void WriteXdmf::WriteXdmfSolFile3DInit()
+{ 
+  //initialisation du type d'element : tetraedre
+  Elemtype= new char[strlen("Tetrahedron")+1];
+  strcpy(Elemtype,"Tetrahedron");
+  dimension=3;
+  nbvperelem=4;
+  string str_h5_mesh="mesh.h5";
+  string str_h5_mesh_filename=WXffname;
+  str_h5_mesh_filename.replace(strlen(WXffname)-6,7,str_h5_mesh);
+
+  //creation et debut d'ecriture du fichier de description
+  //du fichier solution 3D au format xdfm pour paraview
+  //avec le lien vers le fichier de maillage hdf5 correspondant
+  xdmf_file.open (xdmf_filename);
+  xdmf_file << "<?xml version=\"1.0\" ?>\n";
+  xdmf_file << "<!DOCTYPE Xdmf SYSTEM \"Xdmf.dtd\" []>\n";
+  xdmf_file << "<Xdmf Version=\"2.0\">\n"; 
+  xdmf_file << "  <Domain>\n"; 
+  //pour l'instant nom du maillage par defaut : full mesh
+  xdmf_file << "    <Grid Name=\"" << "full mesh" << "\" GridType=\"Uniform\">\n";
+  xdmf_file << "      <Topology TopologyType=\"" << Elemtype 
+	    << "\"  NumberOfElements=\"" << nbofelem << "\">\n";
+  //nb nodes per element, ici classe tetrahedre donc =4
+  xdmf_file << "	<DataItem Format=\"HDF\" NumberType=\"Int\" Dimensions=\"" 
+	    << nbofelem << " " << nbvperelem << "\">\n";
+  xdmf_file << "           " << str_h5_mesh_filename.c_str()  << ":/Connectivity/ELEM2NODE\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Topology>\n";
+  xdmf_file << "      <Geometry GeometryType=\"XYZ\">\n";
+  xdmf_file << "	<DataItem NumberType=\"Float\" Precision=\"8\" Dimensions=\""
+	    << nbofvertex << " "<< dimension << "\" Format=\"HDF\">\n";
+  xdmf_file << "           " << str_h5_mesh_filename.c_str() << ":/Coordinates/XYZ\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Geometry>\n";
+}
+
+void WriteXdmf::WriteXdmfSolFile3DAddField(string * fieldname, int data_type, int result_order, int trans_dim)
+{
+  vector<string> type_char(3);
+  vector<string> res_char(2);
+  type_char[0]= "Scalar"; 
+  type_char[1]= "Vector"; 
+  type_char[2]= "Tensor6"; 
+  res_char[0]= "Cell";  
+  res_char[1]= "Node";
+
+  //ecriture des descriptions du ou des champs solution 3D
+  xdmf_file << "      <Attribute Name=\"" <<  fieldname->c_str() 
+	    << "\" AttributeType=\"" << type_char[data_type]
+	    << "\" Center=\"" << res_char[result_order]<<"\">\n";
+  if(result_order==0) 
+    {
+      xdmf_file << "        <DataItem Dimensions=\" " << nbofelem  << " " << trans_dim
+		<< " \" NumberType=\"" <<"Float" << "\" Format=\"HDF\">\n";
+    }
+  else
+    {
+      xdmf_file << "        <DataItem Dimensions=\" " << nbofvertex << " " << trans_dim
+		<< " \" NumberType=\"" <<"Float" << "\" Format=\"HDF\">\n";
+    }
+  xdmf_file << "          " << WXffname << ":/Data/" <<  fieldname->c_str() <<"\n";
+  xdmf_file << "        </DataItem>\n";
+  xdmf_file << "      </Attribute>\n";
+}
+
+void WriteXdmf::WriteXdmfSolFile3DFinalize()
+{ 
+  //fin d'ecriture et fermeture du fichier des descriptions solution 3D
+  xdmf_file << "    </Grid>\n";
+  xdmf_file << "  </Domain>\n";
+  xdmf_file << "</Xdmf>\n";
+  xdmf_file.close();
+  cout << "save xdmf file solution : " << xdmf_filename <<endl;
+}
diff --git a/src/bamglib/write_xdmf.hpp b/src/bamglib/write_xdmf.hpp
new file mode 100644
index 0000000..fdff88d
--- /dev/null
+++ b/src/bamglib/write_xdmf.hpp
@@ -0,0 +1,41 @@
+#ifndef write_xdmf_h_
+#define write_xdmf_h_
+ 
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+using namespace std;
+using std::string;
+using std::vector;
+typedef long   Int4;
+
+class WriteXdmf
+{ 
+private:
+  const char * WXffname;
+  ofstream xdmf_file;
+  char * Elemtype;
+  Int4 nbofelem;
+  Int4 nbofvertex;
+  Int4 nbvperelem;
+  char * xdmf_filename;
+  int dimension;
+ 
+public:
+
+  WriteXdmf(const char * ffname, Int4 nbelem, Int4 nbvertex);
+  virtual ~WriteXdmf();
+  void WriteXdmfMeshFile2D();
+  void WriteXdmfMeshFile3D();
+  void WriteXdmfSolFile2DInit();
+  void WriteXdmfSolFile2DAddField(string * fieldname, int data_type, int result_order, int trans_dim);
+  void WriteXdmfSolFile2DFinalize();
+  void WriteXdmfSolFile3DInit();
+  void WriteXdmfSolFile3DAddField(string * fieldname, int data_type, int result_order, int trans_dim);
+  void WriteXdmfSolFile3DFinalize();
+};
+
+#endif
diff --git a/src/bin-win32/Makefile.am b/src/bin-win32/Makefile.am
new file mode 100755
index 0000000..a7ae0ef
--- /dev/null
+++ b/src/bin-win32/Makefile.am
@@ -0,0 +1,78 @@
+EXTRA_DIST=launchff++.cpp
+LDADD2 = $(ARPACKLIBS) $(UMFPACKLIBS)  $(BLASLIBS) $(G2CLIB)
+# remark the libff.dll  was  splited in 6 because  ld trap
+#  to much routine => memory fault in ld
+#  but now I see thant the couple allocation/delete
+#  must be make in same .dll file under windows
+#  is impossible to manage with the template generation
+#  so one .dll (this work with gcc version 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125))
+#   change the entry points mymain to mainff 
+# to be compatibile with bamg. 
+# 
+
+FF_OBJ0 = CodeAlloc.o AFunction2.o  CheckPtr.o lex.o  global.o environment.o load.o 
+FF_OBJ_AC = array_complex.o
+FF_OBJ_AR = array_real.o
+FF_OBJ_AL = array_long.o
+FF_OBJ1 = AFunction.o   InitFunct.o strversionnumber.o  mt19937ar.o string_def.o 
+FF_OBJ2 = BamgFreeFem.o  Drawing.o Element_P2h.o Element_RT.o FESpace.o FQuadTree.o InitFunct.o Mesh2.o MeshDraw.o MeshGeom.o MeshQuad.o MeshRead.o MeshWrite.o Meshio.o Metric.o QuadTree.o QuadratureFormular.o R2.o SetOfE4.o eigenvalue.o fem.o gibbs.o  lgalgo.o lgfem.o lgmat.o lgmesh.o  mshptg.o problem.o DefColor.o lgmesh3.o  P012_2d.o P012_3d.o  FESpacen.o ../libMesh/chrono.o  ../libMesh/libmesh3.o  ../libMesh/memory.o ../libMesh/eigenv.o  ../libMesh/libmesh5.o  Mesh1dn.o Mesh2dn.o Mes [...]
+FF_OBJIDE = FreeFem___cs-cs.o FreeFem___cs-commands.o FreeFem___cs-draw.o FreeFem___cs-strversionnumber.o FreeFem___cs-socket.o FreeFem___cs-threads.o FreeFem___cs-hl_yacc.o FreeFem___cs-hl_lex.o FreeFem___cs-highlight.o FreeFem___cs-spawn.o FreeFem___cs-editor.o FreeFem___cs-server.o    windres.o
+
+FFD_OBJ0 = $(patsubst %.o,../fflib/%.o,$(FF_OBJ0))
+FFD_OBJ_AC = $(patsubst %.o,../fflib/%.o,$(FF_OBJ_AC))
+FFD_OBJ_AL = $(patsubst %.o,../fflib/%.o,$(FF_OBJ_AL))
+FFD_OBJ_AR = $(patsubst %.o,../fflib/%.o,$(FF_OBJ_AR))
+FFD_OBJ1 = $(patsubst %.o,../fflib/%.o,$(FF_OBJ1))
+FFD_OBJ2 = $(patsubst %.o,../fflib/%.o,$(FF_OBJ2))
+FFD_OBJIDE = $(patsubst %.o,../ide/%.o,$(FF_OBJIDE))
+FFD_OBJLMSH = $(patsubst %.o,../ide/%.o,$(FF_OBJLMSH))
+
+LIBS_FF = libff.dll FreeFem++-api.dll
+
+
+
+
+all-local: $(WIN32DLLTARGET) 
+	-for i in $(LDADD2) ; do case $$i in  *.dll) echo cp -p $$i .; cp -p $$i . ;;	  esac ; done
+	echo done
+win32-dll-target: FreeFem++.exe FreeFem++-nw.exe  bamg.exe cvmsh2.exe  launchff++.exe ff-c++ $(MPIPROG)
+	echo "on a fini"
+
+libff.dll: $(FFD_OBJ0) $(FFD_OBJ_AR) $(FFD_OBJ_AC) $(FFD_OBJ_AL) $(FFD_OBJ1) $(FFD_OBJ2) ../lglib/lg.tab.o	\
+		FreeFem++-api.dll
+	$(CXX) $(GCCNOCYGWIN)  -shared  -Wl,--enable-auto-import $^  -o $@ $(LDADD2)
+
+
+FreeFem++-nw.exe: ../nw/sansrgraph.o ../nw/parallelempi-empty.o ../lglib/mymain.o $(LIBS_FF)
+	$(CXX)   $(GCCNOCYGWIN) libff.dll $^ -o $@  -lcomdlg32
+FreeFem++.exe: ../nw/sansrgraph.o    ../nw/parallelempi-empty.o ../lglib/mymain.o $(LIBS_FF)
+	$(CXX)   $(GCCNOCYGWIN) libff.dll $^ -o $@  -lcomdlg32
+FreeFem++-mpi.exe:	../nw/sansrgraph.o ../mpi/parallelempi.o   ../lglib/mymain.o $(LIBS_FF)
+	$(MPICXX)   $(GCCNOCYGWIN) libff.dll $^ -o $@  -lcomdlg32 $(MPI_LIB)
+bamg.exe:  libff.dll $(LIBS_FF)
+	$(CXX)   $(GCCNOCYGWIN) ../bamg/bamg.o  -Wl,--enable-auto-import $^ -o $@ 
+cvmsh2.exe:  $(LIBS_FF)
+	$(CXX)   $(GCCNOCYGWIN)  -Wl,--enable-auto-import ../bamg/cvmsh2.o  $^ -o $@ 
+drawbdmesh.exe:../std/Pcrgraph.o  ../bamg/drawbdmesh.o $(LIBS_FF)
+	$(CXX)   $(GCCNOCYGWIN) -mwindows  -Wl,--enable-auto-import  $^ -o $@ 
+launchff++.exe:launchff++.cpp
+	$(CXX) $(GCCNOCYGWIN) launchff++.cpp -o launchff++.exe
+
+ff-c++:../../examples++-load/load.link.in
+	../../config.status  --file=ff-c++:$<
+	chmod a+x ff-c++
+install-exec-local:: install-exec-local--$(WIN32DLLTARGET)
+
+install-exec-local--win32-dll-target::
+	$(INSTALL_SCRIPT) launchff++.exe FreeFem++.exe FreeFem++-nw.exe  bamg.exe cvmsh2.exe  ff-c++ $(MPIPROG) $(DESTDIR)${bindir} 
+	$(INSTALL_SCRIPT) *.dll   $(DESTDIR)${bindir} 
+install-exec-local--::
+
+
+# FFCS: create a separate DLL for ffapi so that it can be changed when running FreeFem++ or FFCS
+FreeFem++-api.dll:../nw/ffapi.o
+	$(CXX) $(GCCNOCYGWIN) -shared -Wl,--enable-auto-import $< -o $@
+
+# FFCS: automake does not clean the exes automatically because they are not built automatically.
+clean-local::
+	-rm *.exe
diff --git a/src/bin-win32/launchff++.cpp b/src/bin-win32/launchff++.cpp
new file mode 100755
index 0000000..79ef300
--- /dev/null
+++ b/src/bin-win32/launchff++.cpp
@@ -0,0 +1,59 @@
+#include <direct.h>
+#include <string.h>
+#include <cstdlib>
+#include <string>
+#include <cstring>
+#include <iostream>
+using namespace std;
+
+
+const char C='"';
+
+int main(int argc,const char **argv)
+{
+  int debug=0; 
+  char *dir=0;
+  const char *pp=0; 
+  string cmd="freefem++.exe ";
+  if(argc <=1)
+  {
+      cerr << " Sorry no file name "<< endl;
+      cerr << " Drag and Drop the file icon on the application  icon or double clip on script file" << endl;
+      exit(1);
+  }
+  
+  for(int i=1;i<argc;++i)
+    {	
+	if(strcmp("++d",argv[i])==0) 
+	  debug=1;
+	else {
+    cmd += C;
+    cmd += argv[i];
+    if(!pp &&strlen(argv[i])>2) 
+	if( argv[i][1]==':')
+          pp= argv[i];
+    cmd += C;
+    cmd += " ";
+	if( debug) cout << "  ffl: arg " << i << argv[i] << endl;
+    }}
+  if(pp)
+   {
+   	if( debug ) cout << "  ffl: file:" << pp << endl;  
+    int i=0;
+    int l= strlen(pp);
+     for(i=l-1;i>=0;i--)
+       if(pp[i]=='\\') break;
+     dir= new char [l+1];
+     strcpy(dir,pp);
+     dir[i]=0;
+	 if(debug) 
+     cout << "  ffl:  chdir to " << dir << endl;
+     _chdir(dir);
+     delete [] dir;
+   }
+   cmd += " -wait -log";
+   if(debug) 
+   cout << "exec " << cmd << endl;
+   int ret= system(cmd.c_str());
+   return ret;
+}
diff --git a/src/femlib/._CGNL.hpp b/src/femlib/._CGNL.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/femlib/._CGNL.hpp differ
diff --git a/src/femlib/._Drawing.cpp b/src/femlib/._Drawing.cpp
new file mode 100644
index 0000000..63e1130
Binary files /dev/null and b/src/femlib/._Drawing.cpp differ
diff --git a/src/femlib/._Mesh3dn.cpp b/src/femlib/._Mesh3dn.cpp
new file mode 100644
index 0000000..e9604e8
Binary files /dev/null and b/src/femlib/._Mesh3dn.cpp differ
diff --git a/src/femlib/._QuadratureFormular.hpp b/src/femlib/._QuadratureFormular.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/femlib/._QuadratureFormular.hpp differ
diff --git a/src/femlib/._R1.hpp b/src/femlib/._R1.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/femlib/._R1.hpp differ
diff --git a/src/femlib/._R2.hpp b/src/femlib/._R2.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/femlib/._R2.hpp differ
diff --git a/src/femlib/._R3.hpp b/src/femlib/._R3.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/femlib/._R3.hpp differ
diff --git a/src/femlib/._RNM_op.hpp b/src/femlib/._RNM_op.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/femlib/._RNM_op.hpp differ
diff --git a/src/femlib/._gmres.hpp b/src/femlib/._gmres.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/femlib/._gmres.hpp differ
diff --git a/src/femlib/BamgFreeFem.cpp b/src/femlib/BamgFreeFem.cpp
new file mode 100644
index 0000000..a4f4d50
--- /dev/null
+++ b/src/femlib/BamgFreeFem.cpp
@@ -0,0 +1,967 @@
+// ORIG-DATE:     Dec 97
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// #define TRACETRIANGLE 3
+//#pragma dont_inline on
+//#pragma global_optimizer off
+//#pragma inline_depth(0)
+
+//#undef NDEBUG
+extern long verbosity ;
+//#define strcasecmp strcmp
+#include <cstdio>
+#include <string>
+#include <cmath>
+#include <ctime>
+#include <iomanip>
+#include <fstream>
+#include "RNM.hpp"
+
+using namespace std;
+
+#include "Meshio.h"
+#include "Mesh2.h"
+#include "QuadTree.h"
+#include "SetOfE4.h"
+
+#include "rgraph.hpp"
+#include "fem.hpp"
+#include "AFunction.hpp"
+#include "BamgFreeFem.hpp"
+#include "FESpace.hpp"
+#include "Mesh2dn.hpp"
+#include "Mesh3dn.hpp"
+#include "MeshPoint.hpp"
+#include "PlotStream.hpp"
+#include <set>
+Fem2D::Mesh *bamg2msh( bamg::Triangles* tTh,bool renumbering)
+{ 
+  using namespace bamg;
+  bamg::Triangles & th (*tTh);
+  tTh->ReNumberingTheTriangleBySubDomain(!renumbering);//  just compress 
+  //tTh->NbRef++;
+  Int4  i,j,k=0;
+  int nv  =  tTh->nbv;
+  int nt  =   tTh->nbt - tTh->NbOutT;
+  int neb =   tTh->nbe;
+  
+  int nbcrakev = 0;
+  tTh->ReMakeTriangleContainingTheVertex();
+  Fem2D::Triangle * t =  new Fem2D::Triangle[nt]  ;
+  Fem2D::BoundaryEdge * b_e = new Fem2D::BoundaryEdge[neb];
+  
+  Fem2D::Vertex vbase;        
+  Fem2D::Vertex *vb(&vbase);
+  if (verbosity>5)
+    cout << "  -- Before cracking mesh:  Nb Triangles = " << nt << " Nb of Vertices " << nv << endl;
+  for ( i=0;i<nt;i++) // unset all triangles 
+    for (j=0;j<3;j++)
+      t[i](j)=0;
+  //  nv=0;    
+  for (int iv=0;iv<th.nbv;iv++) // vertex 
+    {
+      // cout << iv << " : " ;
+      const Vertex & v(th[iv]); 
+      int kk=0; // nb cracked
+      int kc=0; 
+      int kkk =0; // nb triangle  with same number 
+      Triangle * tbegin = v.t;
+      Fem2D::Vertex * vv = vb+iv;
+      int i  = v.vint;       
+      throwassert(tbegin && (i >= 0 ) && (i <3));
+      // turn around the vertex v
+      TriangleAdjacent ta(tbegin,EdgesVertexTriangle[i][0]);// previous edge
+      int k=0;
+      do {
+        int kv = VerticesOfTriangularEdge[ta][1];
+        k++; 
+        Triangle * tt (ta);
+        throwassert( &v == & (*  tt)[kv] );            
+        if ( ta.Cracked() ) 
+          {   // cout << " || "    ;                    
+            if ( kk == 0) tbegin=ta,kkk=0;  //  begin by a cracked edge  => restart                
+            if (  kkk ) { kc =1;vv = vb +  nv++;  kkk = 0; } // new vertex if use 
+            kk++;
+            // number of cracked edge view                 
+          }
+        if ( tt->link ) { // if good triangles store the value 
+          int it = th.Number(tt);
+          throwassert(it < nt);
+          //int iiv=vv-vb;
+          t[it](kv) = vv;
+          /*
+          cout << it << " " << kv << " "<< iiv  << endl;
+          if (&th(it)[kv] != &th[iiv])
+             cout << it << " " << kv << " "<< iiv << " != " << th.Number(th(it)[kv]) << endl ;
+          */
+          kkk++;
+        } else if (kk) { // crack + boundary 
+          if (  kkk ) { kc =1;vv = vb +  nv++;  kkk = 0; } // new vertex if use 
+        }
+        
+        ta = Next(ta).Adj(); 
+      } while ( (tbegin != ta)); 
+      throwassert(k);
+      if (kc)  nbcrakev++;
+    }
+  Fem2D::Vertex * v = new Fem2D::Vertex[nv];
+  //  set the vertices --
+  for (i=0;i<nt;i++)
+    { 
+      for (j=0;j<3;j++)
+        {
+          throwassert( t[i](j) );             
+          int k = t[i](j) - vb;
+          t[i](j) = v+ k;
+          throwassert(k>=0 && k < nv);
+          Vertex & thv(th(i)[j]);
+          v[k].x    =  thv.r.x;
+          v[k].y    =  thv.r.y;
+          v[k].lab  =  thv.ref();        
+        }  
+    }
+  // warning in cracked edges 
+  // construction of the edges --
+  
+  if (nbcrakev && verbosity>2)
+    cout << "  -- Nb of craked vertices = " << nbcrakev << " Nb of created vertices " << nv - th.nbv << endl;
+  
+  
+  for (i=0;i<tTh->nbe;i++)
+    {
+      int i0=tTh->Number(tTh->edges[i][0]),i1=tTh->Number(tTh->edges[i][1]);
+      throwassert(i0>=0 && i0 <nv);
+      throwassert(i1>=0 && i1 <nv);      
+      b_e[i]=Fem2D::BoundaryEdge(v,i0,i1,tTh->edges[i].ref);
+    }      
+  Int4 *reft = new Int4[tTh->nbt];
+  //Int4 nbref =
+  tTh->ConsRefTriangle(reft);
+  for( i=0,k=0;i<tTh->nbt;i++)
+    if(tTh->triangles[i].link)
+      { 
+        
+        Fem2D::R2 A(t[k][0]),B(t[k][1]),C(t[k][2]);
+        t[k].area = (( B-A)^(C-A))*0.5 ;
+        t[k].lab = tTh->subdomains[reft[i]].ref;  // a faire
+        throwassert(k == i);
+        k++;
+      }
+  delete [] reft;
+  throwassert ( nt == k);
+  tTh->ReMakeTriangleContainingTheVertex();
+  
+  if (verbosity)
+    cout << "  --  mesh:  Nb of Triangles = "  << setw(6) <<  nt << ", Nb of Vertices " << nv << endl;
+  
+  {  
+    Fem2D::Mesh *m = new Fem2D::Mesh(nv,nt,neb,v,t,b_e);
+    if (renumbering) m->renum();
+    m->MakeQuadTree();
+    return m;
+  }
+}
+
+Fem2D::Mesh *bamg2msh(const bamg::Geometry &Gh)
+{ 
+  // ------------------
+  int nv=  Gh.nbv;
+  int neb=Gh.nbe;
+  Fem2D::Triangle * t = 0 ;
+  Fem2D::BoundaryEdge * b_e = new Fem2D::BoundaryEdge[neb];
+  Fem2D::Vertex *v = new Fem2D::Vertex[nv]  ;
+  for (int i=0;i<nv;i++)
+    {
+      const bamg::GeometricalVertex & vg( Gh[i]);
+      v[i].x=vg.r.x;
+      v[i].y=vg.r.y;
+      v[i].lab=vg.ref();
+      
+    }     
+  for (int ie=0;ie<neb;ie++)
+    {
+      const bamg::GeometricalEdge & e= Gh(ie);
+      int i0=Gh.Number(e[0]),i1=Gh.Number(e[0]);
+      b_e[ie]= Fem2D::BoundaryEdge(v,i0,i1,e.ref);
+    }   
+  
+  {  
+    Fem2D::Mesh *m = new Fem2D::Mesh(nv,0,neb,v,t,b_e);
+    m->MakeQuadTree();
+    return m;
+  }
+  // ------------------
+}
+
+
+
+
+
+bamg::Triangles * msh2bamg(const Fem2D::Mesh & Th,double cutoffradian,long * reqedgeslab,int nreqedgeslab)
+  
+{
+  using namespace bamg;
+  Triangles *Tn=new Triangles(Th.nv);
+  Tn->nbv = Th.nv;
+  Tn->nbt = Th.nt;
+  Tn->nbe = Th.neb;
+  Tn->name= new char[strlen("msh2bamg")+1];
+  strcpy(Tn->name,"msh2bamg");
+  //  Tn->triangles = new Triangle [Tn->nbtx];
+  throwassert(Tn->triangles);
+  //  Tn->vertices = new Vertex [Tn->nbvx];
+  //  Tn->ordre = new (Vertex* [Tn->nbvx]);
+  Tn->edges = new Edge [Th.neb];
+ 
+  Int4 i;
+  Metric Mid(1.);
+  for (i = 0; i < Th.nv; i++)
+    {
+      Tn->vertices[i].r.x = Th(i).x;
+      Tn->vertices[i].r.y = Th(i).y;
+	Tn->vertices[i].m=Mid;
+      Tn->vertices[i].ReferenceNumber = Th(i).lab;
+    }
+  
+  //  Int4 i1 [nbt],i2 [nbt],i3 [nbt];
+  for (i = 0; i < Th.nt; i++)
+    {
+      int i1 = Th(Th[i][0]);
+      int i2 = Th(Th[i][1]);
+      int i3 = Th(Th[i][2]);
+      Tn->triangles[i]= Triangle( Tn,i1 ,i2 ,i3 );
+      Tn->triangles[i].color = Th[i].lab;
+    }
+    //  Real8 cutoffradian = -1;    
+    // add code   un change boundary part ...  frev 2009 JYU FH
+    set<int> labreq;
+    if(nreqedgeslab && verbosity) cout << " label of required edges " ;
+    for (int i=0; i <nreqedgeslab;++i)
+      {
+	  if(verbosity)
+	      cout << " " << reqedgeslab[i];
+	  labreq.insert(reqedgeslab[i]);
+      }
+    bamg::GeometricalEdge paszero;  // add JYU    fevr 2009   for  required edge ....
+    if(nreqedgeslab && verbosity) cout << endl;
+    int k=0;  
+    for (i = 0; i < Th.neb; i++)
+    {
+      Tn->edges[i].v[0] = Tn->vertices + Th(Th.bedges[i][0]);
+      Tn->edges[i].v[1] = Tn->vertices + Th(Th.bedges[i][1]);
+      Tn->edges[i].ref = Th.bedges[i].lab;
+      Tn->edges[i].on = 0; 
+      if( labreq.find( Tn->edges[i].ref) != labreq.end())
+	{
+	    k++; 
+	    Tn->edges[i].on = &paszero; 
+	}
+
+    }
+  if(verbosity)cout << "  number of required edges : "<< k << endl;
+   
+    
+  Tn->ConsGeometry(cutoffradian);   
+  Tn->Gh.AfterRead();    
+  Tn->SetIntCoor();
+  Tn->FillHoleInMesh();
+  return Tn;
+}
+
+
+bamg::Triangles * msh2bamg(const Fem2D::Mesh & Th,double cutoffradian, 
+                           int  nbdfv, int * ndfv,int  nbdfe, int * ndfe,
+			   long * reqedgeslab,int nreqedgeslab)
+{
+  using namespace bamg;
+  Triangles *Tn=new Triangles(Th.nv);
+  KN<int> equiedges(Th.neb);
+  for(int i=0;i<Th.neb;i++)
+    equiedges[i]=2*i;
+  if(nbdfe !=0 )
+  {
+  KN<int>  kk(Th.neb),kn(Th.neb);
+   kk=0;
+    for(int i=0;i<Th.neb;i++)
+      {
+         int df=ndfe[i];
+         kk[df]++;
+         if(kk[df]==1) kn[df]=i;
+         else { 
+           int k=kn[df],sens=0;
+           int di0=ndfv[Th(Th.bedges[i][0])];
+           int di1=ndfv[Th(Th.bedges[i][1])];
+           int dk0=ndfv[Th(Th.bedges[k][0])];
+           int dk1=ndfv[Th(Th.bedges[k][1])];
+           if ((di0==dk0) &&(di1==dk1) ) sens=0;
+           else if ((di1==dk0) &&(di0==dk1) ) sens=1;
+           else  {
+              cout << "Error in periodic mesh " << di0 << " " << di1 << " <=> " << dk0 << " " << dk1 << endl;
+              ExecError("bug periodic mesh in ??? ");
+           }
+           equiedges[i]=2*k+sens;
+
+         }
+      }
+    
+  }; // a faire pour les maillages periodique 
+  
+  Tn->nbv = Th.nv;
+  Tn->nbt = Th.nt;
+  Tn->nbe = Th.neb;
+  Tn->name= new char[strlen("msh2bamg")+1];
+  strcpy(Tn->name,"msh2bamg");
+  //  Tn->triangles = new Triangle [Tn->nbtx];
+  throwassert(Tn->triangles);
+  //  Tn->vertices = new Vertex [Tn->nbvx];
+  //  Tn->ordre = new (Vertex* [Tn->nbvx]);
+  Tn->edges = new Edge [Th.neb];
+  
+  Int4 i;
+    Metric Mid(1.);  
+  for (i = 0; i < Th.nv; i++)
+    {
+      Tn->vertices[i].r.x = Th(i).x;
+      Tn->vertices[i].r.y = Th(i).y;
+      Tn->vertices[i].ReferenceNumber = Th(i).lab;
+      Tn->vertices[i].m=Mid;
+    }
+  
+  //  Int4 i1 [nbt],i2 [nbt],i3 [nbt];
+  for (i = 0; i < Th.nt; i++)
+    {
+      int i1 = Th(Th[i][0]);
+      int i2 = Th(Th[i][1]);
+      int i3 = Th(Th[i][2]);
+      Tn->triangles[i]= Triangle( Tn,i1 ,i2 ,i3 );
+      Tn->triangles[i].color = Th[i].lab;
+    }
+    
+    // add code   un change boundary part ...  frev 2009 JYU FH
+    set<int> labreq;
+    if(nreqedgeslab && verbosity) cout << " label of required edges " ;
+    for (int i=0; i <nreqedgeslab;++i)
+      {
+	  if(verbosity)
+	      cout << " " << reqedgeslab[i];
+	  labreq.insert(reqedgeslab[i]);
+      }
+    bamg::GeometricalEdge paszero;  // add JYU    fevr 2009   for  required edge ....
+    if(nreqedgeslab && verbosity) cout << endl;
+    int k=0;  
+    
+  for (i = 0; i < Th.neb; i++)
+    {
+      Tn->edges[i].v[0] = Tn->vertices + Th(Th.bedges[i][0]);
+      Tn->edges[i].v[1] = Tn->vertices + Th(Th.bedges[i][1]);
+      Tn->edges[i].ref = Th.bedges[i].lab;
+      Tn->edges[i].on = 0; 
+      if( labreq.find( Tn->edges[i].ref) != labreq.end())
+	  {
+	      k++; 
+	      Tn->edges[i].on = &paszero; 
+	  }
+    }
+  //  Real8 cutoffradian = -1;
+  Tn->ConsGeometry(cutoffradian,equiedges);
+  Tn->Gh.AfterRead();    
+  Tn->SetIntCoor();
+  Tn->FillHoleInMesh();
+  return Tn;
+}
+
+
+
+Fem2D::Mesh *  BuildMesh(Stack stack, E_BorderN const * const & b,bool justboundary,int nbvmax,bool Requiredboundary) 
+{
+  
+
+  using namespace bamg;
+  using bamg::Abs;
+  using bamg::Max;
+  using bamg::Min;
+  using bamg::Pi;
+  Fem2D::MeshPoint & mp (*Fem2D::MeshPointStack(stack)), mps = mp;
+  
+  int nbvx=0,nbe=0,nbsd=0;
+  for (E_BorderN const * k=b;k;k=k->next)
+  {
+      int nbd = k->NbBorder(stack);
+      for(int index=0; index<nbd; ++index )
+    {long n=  Max(1L,Abs(k->Nbseg(stack,index))); ;
+    nbvx += n+1;
+    nbe += n;
+    nbsd++;
+    }
+  }
+  Geometry * Gh =  new Geometry;
+  
+  if(verbosity>2)
+    cout <<"\t\t"  << "  Begin: ConstGeometry from nb Border  "  << nbsd <<endl;
+  //throwassert(empty());
+  const char * filename = "FREEFEM.gh";
+  Gh->name=new char [strlen(filename)+1];
+  strcpy(Gh->name,filename);
+  Real8 Hmin = HUGE_VAL;// the infinie value 
+  Int4 hvertices =0;
+  Int4 i,nn,n;
+  //Int4 dim=0;
+  Gh->MaximalAngleOfCorner =30.00*Pi/180.0;
+  Gh->nbv = 0;
+  Gh->nbvx = nbvx;
+  
+  Gh->nbe = nbe;
+  Gh->edges = new GeometricalEdge[Gh->nbe];
+  bamg::Vertex *vertices =  new Vertex[Gh->nbvx];// correction 2009/07/03 
+  double lmin= HUGE_VAL;
+  //  generation des points et des lignes 
+  i=0;
+  for (E_BorderN const * k=b;k;k=k->next)
+    {
+    int nbd = k->NbBorder(stack);
+    for(int index=0; index<nbd; ++index )
+    {
+      assert(k->b->xfrom); // a faire
+      double & t = *  k->var(stack);
+      double a(k->from(stack)),b(k->to(stack));
+      long * indx = k->index(stack);
+      if(indx) *indx = index;
+      else ffassert(index==0);
+      n=Max(Abs(k->Nbseg(stack,index)),1L);
+      t=a;
+      double delta = (b-a)/n;
+      for ( nn=0;nn<=n;nn++,i++, t += delta)
+        {
+          if (nn==n) t=b; // to remove roundoff error 
+          mp.label = k->label();
+          k->code(stack); // compute x,y, label
+          // cout << " ----- " << i << " " << mp.P.x << " " << mp.P.y << endl;
+          vertices[i].r.x=mp.P.x;
+          vertices[i].r.y=mp.P.y;
+          vertices[i].ReferenceNumber=  mp.label;
+          vertices[i].color = i;
+          if (nn>0) {
+            lmin=min(lmin,Norme2_2( vertices[i].r-vertices[i-1].r));
+          }     
+        }
+    }
+}
+  lmin = sqrt(lmin);
+  double eps = (lmin)/16.; 
+  int nbvprev = i;
+  long nbv=0;
+  Gh->pmin =  vertices[0].r;
+  Gh->pmax =  vertices[0].r;
+  // recherche des extrema des vertices pmin,pmax
+  for (i=0;i<nbvprev;i++) 
+    {
+      Gh->pmin.x = Min(Gh->pmin.x,vertices[i].r.x);
+      Gh->pmin.y = Min(Gh->pmin.y,vertices[i].r.y);
+      Gh->pmax.x = Max(Gh->pmax.x,vertices[i].r.x);
+      Gh->pmax.y = Max(Gh->pmax.y,vertices[i].r.y);
+    }
+    
+  double diameter=Max(Gh->pmax.x-Gh->pmin.x,Gh->pmax.y-Gh->pmin.y);
+  Gh->coefIcoor= (MaxICoor)/diameter;
+  Icoor1 epsI = (Icoor1) (Gh->coefIcoor*eps);
+  ffassert(Gh->coefIcoor >0);
+
+ if(lmin<diameter*1e-7) {
+    ExecError(" Error points  border points to close < diameter*1e-7 ");}
+  
+  if (verbosity>2) 
+    {
+      cout <<"\t\t"  << "     Geom: min="<< Gh->pmin << "max ="<< Gh->pmax 
+           << " hmin = " << Gh->MinimalHmin() <<  endl;
+    }
+  nbv = 0;        
+  {  // find common point 
+    QuadTree quadtree;
+    Metric Id(1.);
+    for ( i=0;i<nbvprev;i++) 
+      { 
+        vertices[i].i = Gh->toI2(vertices[i].r);
+        vertices[i].m = Id;
+        Vertex *v= quadtree.ToClose(vertices[i],eps,epsI,epsI) ;
+        // quadtree.NearestVertex(vertices[i].i.x,vertices[i].i.y); 
+        if( v && Norme1(v->r - vertices[i]) < eps )
+          { vertices[i].color=v->color; }
+        else  {quadtree.Add(vertices[i]);
+        vertices[i].color = nbv++;}
+      }
+    /*   
+         if (nbvprev-nbv==0)
+         {
+         reffecran();
+         bamg::R2 O((Gh->pmin+Gh->pmax)/2),D(Gh->pmax-Gh->pmin);
+         cadreortho(O.x,O.y,Max(D.x,D.y)*1.1);
+         xGrafCoef = Gh->coefIcoor;
+         yGrafCoef = Gh->coefIcoor;
+         xGrafOffSet = Gh->pmin.x;
+         yGrafOffSet = Gh->pmin.y;  
+         quadtree.Draw();
+         for (int i=0;i<nbvprev;i++)
+         {
+         rmoveto(vertices[i].r.x,vertices[i].r.y);
+         
+         char buf[100];
+         sprintf(buf,"%d",i);
+         plotstring(buf);
+         }
+         rattente(1);
+         }
+    */   
+  } // to delete quadtree
+  if (verbosity>1) 
+  cout << " Nb of common points " << nbvprev-nbv <<endl;
+  
+  Gh->nbvx = nbv;
+  Gh->nbv = nbv;
+  
+  Gh->vertices = new GeometricalVertex[nbv];
+  throwassert(Gh->nbvx >= Gh->nbv);
+  Gh->nbiv = Gh->nbv;
+  // Int4 k=0;
+  const Direction NoDirOfSearch;
+  //  compression of points    
+  int kkk;     
+  for ( i=0,kkk=0;kkk<nbvprev;kkk++) 
+    {
+      if (vertices[kkk].color == i) // if new points 
+        {
+          Gh->vertices[i].r.x = vertices[kkk].r.x ;
+          Gh->vertices[i].r.y = vertices[kkk].r.y;
+          //Gh->vertices[i].link = Gh->vertices + i;
+          throwassert(Gh->vertices[i].IsThe());
+          Gh->vertices[i].ReferenceNumber = vertices[kkk].ReferenceNumber  ;
+          Gh->vertices[i].DirOfSearch = NoDirOfSearch;
+          Gh->vertices[i].color =0;
+          Gh->vertices[i].Set();
+          //  vertices[i].SetCorner();
+	    if(Requiredboundary)
+           Gh->vertices[i].SetRequired();
+          i++;
+        }
+    }
+  throwassert(i==nbv);
+  R2 zero2(0,0);
+  if(verbosity>5) 
+    cout <<"\t\t"  << "     Record Edges: Nb of Edge " << Gh->nbe <<endl;
+  throwassert(Gh->edges);
+  throwassert (Gh->nbv >0); 
+  Real4 *len =0;
+  if (!hvertices) 
+    {
+      len = new Real4[Gh->nbv];
+      for(i=0;i<Gh->nbv;i++)
+        len[i]=0;
+    }
+  int nnn=0;
+  i=0;
+  for (E_BorderN const * k=b;k;k=k->next)
+      
+  {    int nbd = k->NbBorder(stack);
+      for(int index=0; index<nbd; ++index )
+      {
+      double & t = *  k->var(stack);
+      double a(k->from(stack)),b(k->to(stack));
+      n=Max(Abs(k->Nbseg(stack,index)),1L);
+      long * indx = (k->index(stack));
+      if(indx) *indx = index;
+      else ffassert(index==0);
+
+      double delta = (b-a)/n;
+      t=a+delta/2; 
+      for ( nn=0;nn<n;nn++,i++, t += delta)
+        {
+          
+          mp.label = k->label();
+          k->code(stack); 
+          Int4 i1 =  vertices[nnn].color, i2 =  vertices[++nnn].color;
+          throwassert(i1 >= 0 && i1 < nbv);
+          throwassert(i2 >= 0 && i2 < nbv);
+          Gh->edges[i].ref = mp.label;
+          Gh->edges[i].v[0]=  Gh->vertices + i1;
+          Gh->edges[i].v[1]=  Gh->vertices + i2;
+          R2 x12 = Gh->vertices[i2].r-Gh->vertices[i1].r;
+          Real8 l12=Norme2(x12);
+          Gh->edges[i].tg[0]=zero2;
+          Gh->edges[i].tg[1]=zero2;
+          Gh->edges[i].SensAdj[0] = Gh->edges[i].SensAdj[1] = -1;
+          Gh->edges[i].Adj[0] = Gh->edges[i].Adj[1] = 0;
+          Gh->edges[i].flag = 0;
+          Gh->edges[i].link=0;
+	  if(Requiredboundary)
+	  Gh->edges[i].SetRequired();
+	    
+          if (!hvertices) 
+            {
+              Gh->vertices[i1].color++;
+              Gh->vertices[i2].color++;
+              len[i1] += l12;
+              len[i2] += l12;
+            }
+          
+          Hmin = Min(Hmin,l12);
+        }
+      nnn++; 
+      }}
+  
+  delete [] vertices; vertices=0;
+  
+  throwassert(nnn==nbvprev);
+  throwassert(i==Gh->nbe);
+  // definition  the default of the given mesh size 
+  if (!hvertices) 
+    {
+      for (i=0;i<Gh->nbv;i++) 
+        if (Gh->vertices[i].color > 0) 
+          Gh->vertices[i].m=  Metric(len[i] /(Real4) Gh->vertices[i].color);
+        else 
+          Gh->vertices[i].m=  Metric(Hmin);
+      delete [] len;
+      
+      if(verbosity>3) 
+        cout <<"\t\t"  << "     Geom Hmin " << Hmin << endl;
+    }
+  
+  Gh->NbSubDomains=nbsd;
+  if (Gh->NbSubDomains>0)
+    {
+        Gh->subdomains = new GeometricalSubDomain[  Gh->NbSubDomains];
+        Int4 i1=0;
+        i=0;
+        for (E_BorderN const * k=b;k;k=k->next)
+        {
+            int nbd = k->NbBorder(stack);
+            for(int index=0; index<nbd; ++index,i++)
+            {
+                long Nbseg =k->Nbseg(stack,index);
+                long n=  Max(1L,Abs(Nbseg));
+                Gh->subdomains[i].sens = Nbseg >0 ? 1 : -1;
+                Gh->subdomains[i].edge=Gh->edges + i1;
+                Gh->subdomains[i].ref = i;
+                i1 += n;
+            }}
+    }
+  Gh->NbEquiEdges=0;
+  Gh->NbCrackedEdges=0;
+  Fem2D::Mesh * m=0;
+  if (justboundary)
+    m=bamg2msh(*Gh);
+  else 
+  {
+      Gh->AfterRead();  
+      int nbtx= nbvmax ? nbvmax :  (Gh->nbv*Gh->nbv)/9 +1000;
+      if(verbosity> 99) cout << " ** Gh = " << endl << *Gh << endl << " *** " <<endl; ;
+      Triangles *Th = 0;
+      try { 
+	  Th =new Triangles( nbtx ,*Gh);
+	  if(0)
+	    {
+	      
+	      
+	      Th->SetVertexFieldOn();
+	      for( int i=0;i<Th->nbv;++i)
+		{
+		  VertexOnGeom *on=0;
+		  if( (on =Th->vertices[i].on) ) // we are on geometrie
+		    {
+		      if(on->abscisse <0) {
+			  bamg::GeometricalVertex * gv= on->gv;
+			  int iold = Gh->Number(gv);
+		      }
+		      else {// erreur car un point est sur un arete en non un sommet
+			  bamg::GeometricalEdge * ge= on->ge;
+			  int eold = Gh->Number(ge); //
+			  int iold = Gh->Number( (*ge)[0] );
+			  int jold = Gh->Number( (*ge)[1] );
+			  int s = on->abscisse;
+			  
+			  // cout << " error bizarre " << ge << endl;
+		      }  
+		      
+		      
+		    }      
+		  
+		}
+	    }
+      }
+      catch(...)
+      {
+	  Gh->NbRef=0; 
+	  delete Gh;
+	  cout << " catch Err bamg "  << endl;
+	  throw ;
+     }
+      m=bamg2msh(Th,true);      
+      delete Th;
+  }
+  
+  delete Gh;
+  /* deja fait  dans bamg2msh
+     Fem2D::R2 Pn,Px;
+     m->BoundingBox(Pn,Px);
+     m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+  ---------- */
+  mp=mps;   
+ // m->decrement();
+ //   Add2StackOfPtr2FreeRC(stack,m);// fait au niveau d'apres  07/2008 FH 
+    
+   
+  return m;   
+}
+
+void E_BorderN::BoundingBox(Stack stack,double  &xmin,double & xmax, double & ymin,double & ymax) const
+{  
+  Fem2D::MeshPoint & mp (*Fem2D::MeshPointStack(stack)), mps = mp;
+  for (E_BorderN const * k=this;k;k=k->next)
+    {
+        int nbd = k->NbBorder(stack);
+        for(int index=0; index<nbd; ++index )
+        {
+      assert(k->b->xfrom); // a faire 
+      double & t = *  k->var(stack);
+      double a(k->from(stack)),b(k->to(stack));
+      long * indx = (k->index(stack));
+      if(indx) *indx = index;
+      else ffassert(index==0);
+
+      long n=Max(Abs(k->Nbseg(stack,index)),1L);
+      t=a;
+      double delta = (b-a)/n;
+      for (int  nn=0;nn<=n;nn++, t += delta)
+        {
+          if (nn==n) t=b; // to remove roundoff error 
+          mp.label = k->label();
+          k->code(stack); // compute x,y, label
+          xmin=Min(xmin,mp.P.x);
+          xmax=Max(xmax,mp.P.x);
+          ymin=Min(ymin,mp.P.y);
+          ymax=Max(ymax,mp.P.y);
+        }
+        }}
+  mp=mps; 
+}  
+void E_BorderN::Plot(Stack stack) const
+{  
+  using Fem2D::R2;
+  
+  Fem2D::MeshPoint & mp (*Fem2D::MeshPointStack(stack)), mps = mp;
+  float x0,x1,y0,y1;
+  getcadre(x0,x1,y0,y1);
+  float h= (x1-x0)*0.01;
+  int nbd=0;
+  for (E_BorderN const * k=this;k;k=k->next)
+    {
+      int nbdr = k->NbBorder(stack);
+      for(int index=0; index<nbdr; ++index )
+     {
+      nbd++;
+      assert(k->b->xfrom); // a faire 
+      double & t = *  k->var(stack);
+      double a(k->from(stack)),b(k->to(stack));
+      long n=Max(Abs(k->Nbseg(stack,index)),1L);
+      long * indx = (k->index(stack));
+      if(indx) *indx = index;
+      else ffassert(index==0);
+
+      t=a;
+      double delta = (b-a)/n;
+      R2 P,Po;
+      for (int  nn=0;nn<=n;nn++, t += delta)
+        {
+          if (nn==n) t=b; // to remove roundoff error 
+          mp.label = k->label();
+          mp.P.z=0;
+          k->code(stack); // compute x,y, label
+          P=mp.P.p2();
+          couleur(2+mp.label);
+          if(nn!=0) { LineTo(P);
+          R2 uv(Po,P);
+          double l = Max(sqrt((uv,uv)),1e-20);
+          
+          R2 dd = uv*(-h/l);
+          R2 dn = dd.perp()*0.5;
+          
+          LineTo(P+dd+dn);
+          MoveTo(P+dd-dn);
+          LineTo(P);}
+          else {
+            DrawMark(mp.P.p2(),0.01);
+            MoveTo(mp.P.p2());
+            
+          }
+          
+          
+          //  cout << k->label()<< " " << nn << ", x,y = " << mp.P.x  << " , " << mp.P.y << endl;
+          Po=P;
+        }
+      DrawMark(mp.P.p2(),0.01);
+      MoveTo(mp.P.p2());
+    }
+}
+  if(verbosity>9) cout << "  -- Plot size : " << nbd << " Border \n";
+  mp=mps; 
+}
+void E_BorderN::SavePlot(Stack stack,PlotStream & plot ) const
+{  
+    using Fem2D::R2;
+    
+    Fem2D::MeshPoint & mp (*Fem2D::MeshPointStack(stack)), mps = mp;
+    //float x0,x1,y0,y1;
+    //getcadre(x0,x1,y0,y1);
+    //float h= (x1-x0)*0.01;
+    
+    long nbd1=0;// nb of sub border
+    for (E_BorderN const * k=this;k;k=k->next)
+    {
+     int nbdr = k->NbBorder(stack);
+     for(int index=0; index<nbdr; ++index )
+	nbd1++;
+    }
+   plot << nbd1;
+   int nbd=0;
+    for (E_BorderN const * k=this;k;k=k->next)
+      {
+          int nbdr = k->NbBorder(stack);
+          for(int index=0; index<nbdr; ++index )
+          {
+	  nbd++;
+	  assert(k->b->xfrom); // a faire 
+	  double & t = *  k->var(stack);
+	  double a(k->from(stack)),b(k->to(stack));
+	  long n=Max(Abs(k->Nbseg(stack,index)),1L);
+          long * indx = (k->index(stack));
+          if(indx) *indx = index;
+          else ffassert(index==0);
+
+	  t=a;
+	  double delta = (b-a)/n;
+	  R2 P,Po;
+	  plot<< (long) n;
+	  for (int  nn=0;nn<=n;nn++, t += delta)
+	    {
+		if (nn==n) t=b; // to remove roundoff error 
+		mp.label = k->label();
+		mp.P.z=0;
+		k->code(stack); // compute x,y, label
+		P=mp.P.p2();
+		plot << (long) mp.label <<P.x << P.y;
+	    }
+	 
+          }}
+    assert(nbd==nbd1);
+    if(verbosity>9) cout << "  -- Plot size : " << nbd << " Border \n";
+    mp=mps; 
+}
+
+Fem2D::Mesh *  BuildMeshBorder(Stack stack, E_BorderN const * const & b) 
+{
+  return BuildMesh(stack,b,true,0,true);
+}
+Fem2D::Mesh *  BuildMesh(Stack stack, E_BorderN const * const & b,bool Requiredboundary) 
+{
+  return BuildMesh(stack,b,false,0,Requiredboundary);
+}
+
+Fem2D::Mesh *  ReadTriangulate( string  * const & s) {
+  using namespace Fem2D;
+  KN<R2> xy;
+  char c;
+  int nv;
+  for(int step=0;step<2;step++)
+    {
+      nv=0;
+      ifstream f(s->c_str());
+      if(!f) {cerr <<" Error openning file " << *s << endl;
+      ExecError("Openning file ");}
+      while (f.good())
+        {
+          R2 P;
+          f >> P ;
+          if (!f.good()) break;
+          if (step) xy[nv]=P;
+          nv++;
+          while (f.get(c) &&  (c!='\n' && c!='\r' ) ) (void) 0; // eat until control (new line
+        } 
+      if (!step && nv ) xy.init(nv); // alloc the array        
+    }
+  if(verbosity)
+    cout << " we read  " << nv << " coordinates  xy "<< endl;
+  
+  Mesh * m=new Mesh(nv,xy); 
+  m->MakeQuadTree();
+//  m->decrement(); //  07/2008 FH  auto del ptr
+ //  delete s;  modif mars 2006 auto del ptr
+  return m;
+  
+}
+Fem2D::Mesh *  Triangulate( const  KN_<double> & xx,const  KN_<double> & yy) 
+{
+    using namespace Fem2D;
+    ffassert(xx.N()==yy.N());
+    int nv=xx.N();
+    KN<R2> xy(nv);
+    for(int i=0;i<nv;++i)
+       xy[i]= R2(xx[i],yy[i]);
+    Mesh * m=new Mesh(nv,xy); 
+    m->MakeQuadTree();
+   // m->decrement();  07/2008 FH  auto del ptr
+    //  delete s;  modif mars 2006 auto del ptr
+    return m;
+    
+}
+Fem2D::Mesh *  ReadMeshbamg( string * const & s) {
+  using bamg::Triangles;
+  Triangles * bTh= new Triangles(s->c_str());
+  // bTh->inquire();
+  Fem2D::Mesh * m=bamg2msh(bTh,false);// no renum
+  delete bTh;
+  // delete s; modif mars 2006 auto del ptr
+ //  m->decrement();  07/2008 FH  auto del ptr
+  return m;
+}
+
+Fem2D::Mesh *  buildmeshbamg( string * const & s, int nbvxin) {
+
+  using bamg::Triangles;
+  using bamg::Geometry;
+  Geometry Gh(s->c_str());
+  //double	 hmin = Gh.MinimalHmin();
+  //double	 hmax = Gh.MaximalHmax();
+  int nbvx = nbvxin ? nbvxin : ((Gh.nbv*Gh.nbv)/9 +1000); 
+  Triangles * bTh=  new Triangles(nbvx,Gh);
+  // bTh->inquire();
+  Fem2D::Mesh * m=bamg2msh(bTh,false);// no renum
+  delete bTh;
+ //  delete s; modif mars 2006 auto del ptr
+ // m->decrement();
+  return m;
+}
diff --git a/src/femlib/BamgFreeFem.hpp b/src/femlib/BamgFreeFem.hpp
new file mode 100644
index 0000000..1f1cee9
--- /dev/null
+++ b/src/femlib/BamgFreeFem.hpp
@@ -0,0 +1,55 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Bamglib interface header  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#ifndef FREEFEMBAMG_H_
+#define FREEFEMBAMG_H_
+
+namespace bamg {
+extern  void (*MeshIstreamErrorHandler)(ios & );
+class Triangles;
+}
+
+
+  Fem2D::Mesh *  ReadMeshbamg( string * const & s) ;
+  Fem2D::Mesh *  ReadTriangulate( string * const & s) ;
+  Fem2D::Mesh *  Triangulate( const  KN_<double> & xx,const  KN_<double> & yy) ;
+  Fem2D::Mesh *bamg2msh( bamg::Triangles* tTh,bool renumbering=false); 
+  bamg::Triangles * msh2bamg(const Fem2D::Mesh & Th, double cutoffradian=-1.0,long * reqedgeslab=0,int nreqedgeslab =0) ;
+  bamg::Triangles * msh2bamg(const Fem2D::Mesh & Th,double cutoffradian,  int  nbdfv, int * ndfv,int  nbdfe, int * ndfe,
+     long * reqedgeslab=0,int nreqedgeslab=0);
+
+  Fem2D::Mesh *  BuildMesh(Stack stack, E_BorderN const * const & b,bool justboundary,int nbvmax=0,bool Requiredboundary=true);
+  Fem2D::Mesh *  BuildMesh(Stack stack  , E_BorderN const * const & b,bool Requiredboundary) ;
+  Fem2D::Mesh *  BuildMeshBorder(Stack stack  , E_BorderN const * const & b) ;
+  Fem2D::Mesh * MoveTheMesh(const Fem2D::Mesh &Th,const KN_<double> & u,const KN_<double> &v);
+  Fem2D::Mesh *  buildmeshbamg( string * const & s,int =0);
+#endif
diff --git a/src/femlib/CGNL.hpp b/src/femlib/CGNL.hpp
new file mode 100644
index 0000000..49e13cd
--- /dev/null
+++ b/src/femlib/CGNL.hpp
@@ -0,0 +1,114 @@
+
+template<class R,class DJ>
+R argmin(R  rho,const DJ & dJ, KN_<R> &x,KN_<R> &h,KN_<R> &g,KN_<R> &w)
+{
+  //  Find  ro such thah (dJ(x+ro h),h)  =0 
+  // remark input: dJ(x)=g 
+  int k=0;
+//  g=dJ*x; //  pour est sure
+  R ro0=0, ro=rho,ro1=rho,rold=0;
+  R p0= (g,h),p,p1;
+  if(p0>0) { h=-g; p0=(g,h);
+    cout << "Reset searching directions to gradient! (Wow! says F. hecht) \n";
+  } 
+  R ap0=fabs(p0)*0.01; // on arrete quand on a divise par 100.
+  
+  x += (ro-rold)* h; rold=ro; g=dJ*x;// dJ(x,g);
+  p= ( p1 = (g,h) );
+  if (  verbosity >=50 )      
+    cout << "        ro " <<  ro << " " << p 
+         << " rh0= 0 " << p0 << endl;
+  
+  
+  bool loop=true;
+  while (k++<100 && loop)
+    { //  calcul du  nouveau ro courant
+      
+      if (p0*p1 <0) { //  Ok changement de signe 
+        R lambda= (-p0/(-p0+p1));
+        if (lambda>0.8) lambda=0.8;
+        if (lambda<0.2) lambda=0.2;
+        ro = ro1*lambda + (1-lambda)*ro0 ;
+        x += (ro-rold)* h; rold=ro; g=dJ*x;// dJ(x,g);
+        assert(ro>1e-30 && ro < 1e+30);
+        p = (g,h);
+        if ( verbosity >=50 )
+	     cout << "         " << ", rho=" << ro << " gh= " << p
+             << "; ro0, gh0 = " << ro0 << " " << p0 
+             << "; ro1, gh1 = " << ro1 << " " << p1 << " " << lambda ; 
+        
+        if(fabs(p) <= ap0 || k>100  ) {
+          if (  verbosity >=50 )      
+            cout << endl << endl;
+          return ro; 
+        }
+        if(p0*p<0) { 
+          p1=p;
+          ro1=ro;
+          if (  verbosity >=50 ) cout << " +\n";} 
+        else {
+          p0=p;
+          ro0=ro;
+          if (  verbosity >=50 ) cout <<" -\n";}              
+      }
+      else 
+        { 
+          ro *=2; 
+          p0=p1;
+          x += (ro-rold)* h; rold=ro; g=dJ*x;//dJ(x,g);
+          p = (g,h);    
+           p1=p;
+           ro1=ro;    
+           if (  verbosity >=50 ) cout <<p<<" " << ro <<  " 2* " ;
+        }
+      
+    }  
+  ExecError("NLCG: ArgMin loop (convexe minimization? )");
+  return 0;
+}
+
+template<class R,class DJ,class P,class S >
+int NLCG(const DJ & dJ,const P & C,KN_<R> &x,const int nbitermax, double &eps,long kprint=1000000000,S *Stop=0)
+{
+  //  -------------
+  assert(&x && &dJ && &C);
+  typedef KN<R> Rn;
+  int n=x.N();
+  
+  R ro=1;
+  Rn g(n),h(n),Ah(n), & Cg(Ah);  // on utilise Ah pour stocke Cg  
+  g=dJ*x;// dJ(x,g);  
+  Cg = C*g; // gradient preconditionne 
+  h =-Cg; 
+  R g2 = (Cg,g);
+  if (g2 < 1e-30) 
+    { if(kprint>1)
+      cout << "GCNL  g^2 =" << g2 << " < 1.e-30  Nothing to do " << endl;
+    return 2;  }
+  if (kprint>5 ) 
+    cout << " 0 GCNL  g^2 =" << g2 << endl;
+  R reps2 =eps >0 ?  eps*eps*g2 : -eps; // epsilon relatif 
+  eps = reps2;
+  for (int iter=0;iter<=nbitermax;iter++)
+    { 
+      ro = argmin(ro,dJ,x,h,g,Ah);
+      
+      Cg = C*g;
+      R g2p=g2; 
+      g2 = (Cg,g);
+      bool stop = Stop && Stop->Stop(iter,x,g);
+      if (  kprint >1 )
+        cout << "CGNL:" <<iter <<  ",  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+      if (g2 < reps2 || stop) {
+        if (kprint )
+          cout << "CGNL converge: " << iter <<",  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+        return 1;// ok 
+      }
+      R gamma = g2/g2p;       
+      h *= gamma;
+      h -= Cg;  //  h = -Cg * gamma* h       
+    }
+  if(verbosity)
+  cout << " Non convergence of the NL cojugate gradient " <<endl;
+  return 0; 
+}
diff --git a/src/femlib/CheckPtr.cpp b/src/femlib/CheckPtr.cpp
new file mode 100644
index 0000000..2fee089
--- /dev/null
+++ b/src/femlib/CheckPtr.cpp
@@ -0,0 +1,516 @@
+//#define NCHECKPTR // BUg with MPI ??? FH
+
+#if __APPLE__
+#include <malloc/malloc.h>
+#else
+#include <malloc.h>
+#endif
+
+static long verbosity;
+
+static long StorageUsed()
+{
+#if MALLOC_ZONE_SPECIFIC_FLAGS
+    struct mstats mem1;
+    mem1 = mstats();
+    return mem1.bytes_used;
+#elif M_MMAP_THRESHOLD
+    struct mallinfo mem1;
+    mem1=mallinfo();
+    return mem1.uordblks;
+#else
+    return 0;
+#endif
+    
+}
+#ifndef NCHECKPTR
+#define DEBUGUNALLOC 1 
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <cstdlib>
+#include <cerrno>
+#include <cstdio>
+#include <new>
+
+void debugalloc()
+{ }
+
+void debugunalloc()
+{ static long count=0;
+  //  debugalloc();
+ count++;}
+
+
+void exitalloc(int i)
+{ static long count=0;
+ count++;
+ exit(1); 
+}
+
+// Modif:         Juin 2001  for debuging  missing  delete point
+//  --  THE MACRO 
+// TO SHOW ALL ALLOCATION
+// #define SHOWALLOC
+//  TO DEBUG ALL UN DELETE POINETUR
+
+
+int UnShowAlloc =1;
+
+int ShowAlloc(const char *s,size_t & lg); 
+        
+//inline void *operator new(size_t, void *place) { return place; }
+
+static int kerr=0;
+void * mymalloc(size_t l)
+{
+  char *p = (char*)malloc(l+16);
+  if (!p) return p;   
+  for( int i = 0; i < 8 ; i++)
+    p[i] = 'a'+i,p[i+l+8] = 'z'-i; // put a marque before 
+  return (void*) (p+8);
+}
+void myfree(char *p,size_t l=0,int nordre=0) 
+{
+  if(p) {
+    p -= 8;
+    int k =0;
+    for( int i = 0; i < 8 ; i++)
+      {
+	if (p[i] != 'a' +i)     k++;
+	if(l && (p[i+l+8] != 'z' -i)) k++;       
+      }
+    for (size_t i=0;i<l;i++)
+      p[i+8]=127;
+    if(!k) free(p);
+   else {
+     debugalloc();
+     if (kerr++<20) 
+       printf("@@@@@@@@@@@@@@@@@ Erreur myfree p= %p   l=%ul n=%d\n",p,(unsigned int) l,nordre);
+
+   }
+  }
+}
+
+void *operator new(std::size_t) throw (std::bad_alloc);
+void *operator  new[] (std::size_t) throw (std::bad_alloc);
+void operator delete(void *  ) throw ();
+
+
+
+const int N100 = 100;
+class  AllocData;
+
+class AllocExtern {
+  public:
+class OneAlloc {public:
+  void * p;
+  size_t l;
+  long n;
+  bool is_array ;
+  bool operator<(const OneAlloc & a) const { return n<a.n;}
+};
+  
+  void  HeapSort(OneAlloc **c,long n)
+  {
+    long l,j,r,i;
+    OneAlloc* crit;
+    c--; // on decale de 1 pour que le tableau commence a 1
+    if( n <= 1) return;
+    l = n/2 + 1;
+    r = n;
+    while (1) { // label 2
+      if(l <= 1 ) { // label 20
+	crit = c[r];
+	c[r--] = c[1];
+	if ( r == 1 ) { c[1]=crit; return;}
+      } else  crit = c[--l]; 
+      j=l;
+      while (1) {// label 4
+      i=j;
+      j=2*j;
+      if  (j>r) {c[i]=crit;break;} // L8 -> G2
+      if ((j<r) && (*c[j] < *c[j+1])) j++; // L5
+      if ( *crit < *c[j]) c[i]=c[j]; // L6+1 G4
+      else {c[i]=crit;break;} //L8 -> G2
+      }
+    }
+  }
+  
+  class AllocData {public:
+    OneAlloc *a;
+    AllocData * next;
+    AllocData();
+    ~AllocData();
+    private:
+    AllocData(const AllocExtern::AllocData&);
+    void operator=(const AllocExtern::AllocData&);
+  };
+
+private:
+    
+  static const long Maxundelptr = 2048;
+    static size_t StorageUsage;
+  static size_t AllocSize ;
+  static size_t MaxUsedSize;
+  static AllocData * AllocHead ;  
+  static long NbAlloc;
+  static long NbAllocShow;
+  static long NbPtr;
+  static void * NextFree;
+  static long NbuDelPtr;
+  static long uDelPtr[Maxundelptr];
+  static bool after_end; 
+  static char filename[128];
+  AllocData * NewAllocData();
+  OneAlloc *Alloc();
+public:
+  
+  void * MyNewOperator(size_t ll,bool is_array );
+  void MyDeleteOperator(void * pp,bool is_array);
+  AllocExtern();
+  ~AllocExtern();
+  void init();  
+  int ShowAlloc( const char *s,size_t & lg); 
+  bool IsUnDelPtr(long nn) { // dichotomic find 
+    long i=0;
+    long j=NbuDelPtr-1;
+    while (i<=j) {
+      long k = (i+j)/2, kn=uDelPtr[k];
+      if ( nn<kn) j=k-1;
+      else if ( nn > kn) i = k+1;
+      else
+        return  true;}
+    return false;
+  }
+};
+
+static AllocExtern AllocExternData;
+size_t AllocExtern::StorageUsage=0;
+size_t AllocExtern::AllocSize =0;
+size_t AllocExtern::MaxUsedSize =0;
+AllocExtern::AllocData * AllocExtern::AllocHead =0;  
+long AllocExtern::NbAlloc =0;
+long AllocExtern::NbAllocShow=0;
+long AllocExtern::NbPtr =0;
+void * AllocExtern::NextFree =0;
+long AllocExtern::NbuDelPtr =0;
+long AllocExtern::uDelPtr[Maxundelptr];
+bool AllocExtern::after_end =false;
+char AllocExtern::filename[128] ="ListOfUnAllocPtr.bin";
+
+AllocExtern::AllocData * AllocExtern::NewAllocData()
+{
+  
+  AllocExtern::AllocData * ad = (AllocData *) mymalloc(sizeof(AllocData));
+  ad->a = (OneAlloc*) mymalloc(sizeof(OneAlloc)*N100);
+  for (int i=0;i<N100;i++)
+    ad->a[i].l=0,ad->a[i].p=NextFree,NextFree = & ad->a[i];
+  ad->next = AllocHead;
+  AllocHead = ad;
+#ifdef SHOWALLOC    
+  printf("\t\tCheckPtr: OneAlloc[100] %lx\n",this);
+#endif    
+  return ad;
+}
+
+
+
+AllocExtern::OneAlloc * AllocExtern::Alloc()
+{
+  OneAlloc * f =  (OneAlloc *) NextFree;
+  if (!f) 
+    AllocHead = NewAllocData();
+  f =(OneAlloc *) NextFree;
+  if (!f) exitalloc(1);
+  NextFree =   f->p;
+  return f;
+}
+
+
+void * AllocExtern::MyNewOperator(size_t ll,bool is_array)
+{ 
+  if(after_end) return malloc(ll);
+  init();
+  AllocExtern::OneAlloc * a = Alloc();
+  a->p = mymalloc(ll);
+  a->l = ll+1; // pour les allocation null
+  a->n = ++NbAlloc;
+  a->is_array = is_array;
+  NbPtr++;
+  AllocSize += ll;
+#ifdef DEBUGUNALLOC
+  if ( (IsUnDelPtr(a->n) && (a->n >= DEBUGUNALLOC) )) 
+    debugunalloc();
+#endif
+#ifdef SHOWALLOC    
+  printf( "\t%d\tCheckPtr: New Alloc %ld %lx when %ld\n ",a->n, ll, a->p, a->n);
+#endif
+  MaxUsedSize = AllocSize < MaxUsedSize ? MaxUsedSize :  AllocSize;
+  if( !ll &&  !a->p)
+    {
+        if(verbosity>2) {
+      printf("\t\tCheckPtrMem Full Exit(10) New Alloc %ld %p when %ld\n ", ll, a->p, a->n);
+      printf ("\t\tCheckPtr:Max Memory used %10.3f kbytes " ,  MaxUsedSize/1024. );
+      printf (" Memory undelete %ld \n" , AllocSize);
+        }
+      exitalloc(1);
+    }
+  return (void*) ((char*)a->p);
+}
+
+void AllocExtern::MyDeleteOperator(void * pp,bool is_array)
+{
+  if(after_end) { /*free(pp)*/; return;}
+  init();
+  if (AllocHead)
+    {
+      AllocExtern::AllocData *p = AllocHead;
+      while (p)
+	{
+	  for (int i=0;i<N100;i++)
+	    if((p->a[i].l > 0) && (p->a[i].p == pp))
+	      {
+#ifdef SHOWALLOC    	  
+		printf("\t%d\tCheckPtr: delete  Alloc %ld %lx when %ld \n",p->a[i].n,p->a[i].l-1,  p->a[i].p, p->a[i].n);
+#endif
+		size_t ll = p->a[i].l-1;
+		for (size_t kkk=0;kkk<ll;kkk++) 
+		  ((char *) pp)[kkk]=18;
+		
+		myfree((char*)pp,ll,p->a[i].n);
+		
+		AllocSize -= ll;
+		NbPtr--;
+		p->a[i].l=0;
+		p->a[i].p = NextFree;
+		p->a[i].n =0;
+		if (p->a[i].is_array != is_array)
+		  printf("\t\tCheckPtr:  erreur delete [] ");
+		//if( p->a[i].n < NbAllocShow )		  debugalloc();      
+		NextFree = & p->a[i].p;
+		return;}
+	  p = p->next;
+	}
+      if(pp) 
+	{
+	  printf( "\t\tCheckPtr: delete of bad pointer %p  -----------\n",pp);
+	  debugalloc(); 
+	}
+      
+    } else 
+      myfree((char*)pp); 
+}
+void AllocExtern::init()
+{
+   static int count=0;
+   if(0== (count++)) 
+    {
+      sprintf(filename,"ListOfAllocPtr-%d.bin",(int) sizeof(void*));
+      StorageUsage=0;
+      AllocSize =0;
+      MaxUsedSize =0;
+      AllocHead =0;  
+      NbAlloc =0;
+      NbPtr =0;
+      NextFree =0;
+      NbuDelPtr =0;
+      NbuDelPtr = 0;
+        
+      after_end = false;
+      
+      FILE *file=fopen(filename,"rb");
+      
+      if (file) 
+	{
+	  fread(&NbuDelPtr,sizeof(long),1,file);
+	  fread(uDelPtr,sizeof(long),NbuDelPtr,file);
+	  if(NbuDelPtr> 100000000 && NbuDelPtr <0) 
+	    {
+	      printf("Fatal error in the file %s is wrong (please remove)",filename);
+	      exit(1);
+	    }
+	  fclose(file);
+	}  
+      else
+	{ // printf("fopen ListOfUnAllocPtr errno = %d\n",errno);
+	}   
+    }
+}
+AllocExtern::AllocExtern()
+{
+  init();
+  
+}
+
+AllocExtern::~AllocExtern()
+{
+    if(UnShowAlloc==0) return;
+     OneAlloc *  list[Maxundelptr];
+     
+     AllocData * p=AllocHead;
+     int k=0,kk=0;
+     int lln=0;
+     
+     while (p) {int i=N100;
+     while(i--)
+       if (p->a[i].l >0  )
+	 {
+	   if ( p->a[i].n >=  p->a[i].n) lln = p->a[i].n;
+	   if ( p->a[i].n <= NbAllocShow )
+	     k++;
+	   else
+	     if (kk<Maxundelptr)
+	       list[kk++]=p->a+i;
+	 }
+      p = p->next;
+     }
+     k+=kk;
+    kk=kk < Maxundelptr ? kk : Maxundelptr;
+    HeapSort(list,kk);
+    if(verbosity > 2)
+    for (int i= kk-10<0 ? 0 : kk-10 ;i<kk;i++)
+      {
+        printf ("\t\tCheckPtr:Undelete pointer  %p size %ld  when %ld\n", list[i]->p,list[i]->l,list[i]->n);        
+      }
+    if (kk)
+      {
+	FILE *file=fopen(filename,"wb");
+	if (file) 
+	  {
+	    NbuDelPtr=kk;
+	    for (int i=0;i<kk;i++)
+	      uDelPtr[i]=list[i]->n;
+	    fwrite(&NbuDelPtr,sizeof(long),1,file);
+	    fwrite(uDelPtr,sizeof(long),NbuDelPtr,file);
+	    fclose(file);
+	  }
+      }
+      else {}
+    
+      if(verbosity>2) {
+    if(k)  printf ("\t\tCheckPtr:Nb of undelete pointer is %d last %d\n",k,lln);
+    printf ("\t\tCheckPtr:Max Memory used %10.3f kbytes " ,  MaxUsedSize/1024. );
+    printf (" Memory undelete %ld \n" , AllocSize);
+      }
+    
+    //   clean store pointer      
+    p=AllocHead;    
+    while (p)
+      {
+	myfree((char*)p->a);
+	AllocData * pold = p;
+	p = p->next;
+	myfree((char*)pold);
+      }     
+    AllocHead=0;
+    after_end=true; 
+}
+// ------------------
+
+
+void *operator new(size_t ll ) throw (std::bad_alloc)
+{ void * p =  AllocExternData.MyNewOperator(ll,false);
+ if (ll && !p) { printf("EXIT BECAUSE MEMORY FULL \n");
+ exitalloc(1); };
+ return p;}
+void *operator new[](size_t ll ) throw (std::bad_alloc)
+{ void * p =  AllocExternData.MyNewOperator(ll,true);
+ if (ll && !p) { printf("EXIT BECAUSE MEMORY FULL \n");
+ exitalloc(1); };
+ return p;}
+
+  
+void operator delete(void * pp) throw ()
+{  AllocExternData.MyDeleteOperator(pp,false);}
+void operator delete[](void * pp) throw ()
+{  AllocExternData.MyDeleteOperator(pp,true);}
+
+int AllocExtern::ShowAlloc(const char *s,size_t & lg) {
+    size_t m =StorageUsage;
+    StorageUsage =StorageUsed();
+    if (!NbAllocShow) {NbAllocShow=NbAlloc;}
+    if(verbosity > 2)
+  printf ("----------CheckPtr:-----%s------ NbUndelPtr  %ld  Alloc: %ld  NbPtr %ld  Mem Usage: %zu diff: %ld\n",s,NbPtr,AllocSize,NbAlloc,StorageUsage,(long)(StorageUsage-m));
+  lg = AllocSize;
+  return NbPtr;
+}
+int ShowAlloc(const char *s,size_t & lg) 
+{  return  AllocExternData.ShowAlloc(s,lg);}
+#else
+#define XXXX
+#ifdef XXXX
+#include <cstdlib>
+#include <cerrno>
+#include <cstdio>
+#include <new>
+
+long  CheckPtr___nbptr=0;
+size_t CheckPtr___memoryusage =0;
+
+void* operator new( size_t size ) throw(std::bad_alloc) {
+    CheckPtr___nbptr++;
+    void *p = malloc( size );
+    
+    return p;
+}
+
+void* operator new[]( size_t size ) throw(std::bad_alloc) {  
+    void *p = malloc(size);
+     CheckPtr___nbptr++;
+    return p;
+}
+
+void operator delete( void *p ) throw() {  
+    free(p);
+    CheckPtr___nbptr--;
+
+}
+
+void operator delete[]( void *p ) throw() {
+    free(p);
+    CheckPtr___nbptr--;
+
+}
+
+int ShowAlloc(const char *s,size_t & lg)
+{
+    size_t m =StorageUsed();
+    long diff = m-CheckPtr___memoryusage;
+    if(verbosity > 0 && CheckPtr___memoryusage!=0 && m != CheckPtr___memoryusage)
+        printf("CheckPtr:  Warning memory leak with malloc = %ld \n ",diff);
+    CheckPtr___memoryusage=m;
+    lg = 0; return CheckPtr___nbptr;}
+int UnShowAlloc =0;
+#else
+#include <stdlib.h>
+
+int ShowAlloc(const char *s,size_t & lg)
+{lg=0; return 0;}
+int UnShowAlloc =0;
+#endif
+#endif
diff --git a/src/femlib/ConjuguedGradrientNL.cpp b/src/femlib/ConjuguedGradrientNL.cpp
new file mode 100644
index 0000000..8ffb4a7
--- /dev/null
+++ b/src/femlib/ConjuguedGradrientNL.cpp
@@ -0,0 +1,116 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:    29 fev 2000  
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : array modelisation 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ 
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ 
+ */
+
+template<class R,class DJ,class M>
+R argmin(R  rho,const M & dJ,const KN_<R> &x,KN_<R> &h,KN_<R> &g,KN_<R> &w)
+{
+  //  find  ro / (dJ(x+roh),h)  =0 
+  // remark input: dJ(x)=g 
+  int k=0;
+  
+  R ro0=0, ro=rho,ro1=rho;
+  R p0= (g,h),p,p1;
+  R ap0=Abs(p0)*0.1; // on arret quand on a divise par 10.
+  x += (ro-rold)* h; rold=ro; g =A(x);
+  p= ( p1 = (g,h) );
+  
+
+  bool loop=true;
+  while (k++<100 && loop)
+  { //  calcul du  nouveau ro courant
+    if (p0*p1 <0) { //  Ok changement de signe 
+      ro = (p0*ro1+p1*ro0)/ (p0+p1); 
+      x += (ro-rold)* h; rold=ro; g =A(x);
+      p = (g,h);
+      if (  verbosity >3 )      
+      cout << "         ro " << ro << " gh= " << p
+           << "; ro0, gh0 = " << ro0 << " " << p0 
+           << "; ro1, gh1 = " << ro1 << " " << p1 << endl; 
+      
+      if(Abs(p) <= ap0 || k>10  ) return ro; 
+      if(p0*p<0) { p1=p;ro1=ro;} 
+      else {p0=p;ro0=ro;}              
+    }
+    else { 
+      ro *=2; 
+      x += (ro-rold)* h; rold=ro; g =A(x);
+      p = (g,h);    
+      p1=p;
+      ro1=ro;    
+    }
+  }  
+}
+
+template<class R,class DJ,class M,class P> 
+int ConjuguedGradientNL(const M & dJ,const P & C,KN_<R> &x,const int nbitermax, double &eps,long kprint=1000000000)
+{
+//  -------------
+   throwassert(&x && &b && &A && &C);
+   typedef KN<R> Rn;
+   int n=b.N();
+   if (verbosity>99) kprint=1;
+   throwassert(n==x.N());
+   R ro=1;
+   Rn g(n),h(n),Ah(n), & Cg(Ah);  // on utilise Ah pour stocke Cg  
+   g = dJ(x);  
+   Cg = C*g; // gradient preconditionne 
+   h =-Cg; 
+   R g2 = (Cg,g);
+   if (g2 < 1e-30) 
+    { if(verbosity>1)
+       cout << "GCNL  g^2 =" << g2 << " < 1.e-30  Nothing to do " << endl;
+     return 2;  }
+   if (verbosity>5 ) 
+     cout << " 0 GCNL  g^2 =" << g2 << endl;
+   R reps2 =eps >0 ?  eps*eps*g2 : -eps; // epsilon relatif 
+   eps = reps2;
+   for (int iter=0;iter<=nbitermax;iter++)
+     { 
+       ro = argmin(J,x,h,g,Ah);
+       
+       Cg = C*g;
+       R g2p=g2; 
+       g2 = (Cg,g);
+       if (  verbosity >1 )
+         cout << "CGNL:" <<iter <<  "  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+       if (g2 < reps2) { 
+         if (verbosity )
+            cout << "CGNL converge: " << iter <<  "  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+          return 1;// ok 
+          }
+       R gamma = g2/g2p;       
+       h *= gamma;
+       h -= Cg;  //  h = -Cg * gamma* h       
+     }
+   cout << " CGNL: the method don't converge in " <<nbitermax <<" iterations \n" ;
+   return 0; 
+}
diff --git a/src/femlib/DOperator.hpp b/src/femlib/DOperator.hpp
new file mode 100644
index 0000000..4b84c23
--- /dev/null
+++ b/src/femlib/DOperator.hpp
@@ -0,0 +1,560 @@
+#include <queue>
+// class for 1 linear form
+// just copy a array 
+
+//  Warning this class are use at compilating time
+//  ----------------------------------------------
+using Fem2D::operatortype;
+using Fem2D::op_id;
+using Fem2D::op_dx;
+using Fem2D::op_dy;
+using Fem2D::op_dz;
+using Fem2D::last_operatortype;
+
+template<class T> 
+inline  T * NewCopy(const  T * const o,int n)
+{ 
+  int  m=n;
+  T * c = new T [n];
+  for (int i=0;i<m;i++)
+    c[i]=o[i];
+  return c;
+}
+template<class T> 
+inline  T * NewCopy(const  T * const o,int n,int m)
+{ 
+  throwassert(m<=n);
+  T * c = new T [n];
+  for (int i=0;i<m;i++) c[i]=o[i];
+  return c;
+}
+
+template <class T1, class T2, class T3>
+struct triplet
+{
+	typedef T1 first_type;
+	typedef T2 second_type;
+	typedef T3 third_type;
+	T1 first;
+	T2 second;
+	T3 third;
+	triplet() : first(),second(),third()   {}
+	triplet(const T1& x, const T2& y, const T3& z)  : first(x),second(y), third(z) {}
+	template<class U, class V,class W> inline
+	triplet(const triplet<U, V, W>& p) : first(p.first),second(p.second),third(p.third) {}
+};
+
+template <class T1, class T2,class T3>
+inline triplet<T1, T2, T3> make_triplet(T1 x, T2 y, T3 z)
+{
+	return triplet<T1, T2, T3>(x, y, z);
+}
+
+
+template<class I,class R>
+ class LinearComb : public E_F0mps { public: 
+   typedef I TI;
+   typedef R TR;
+   typedef size_t size_type;
+   typedef pair<I,R> K;
+   typedef vector<K> array;
+   typedef typename array::const_iterator const_iterator;
+   typedef typename array::iterator iterator;
+   array v;
+   vector<size_type> where_in_stack_opt;
+   vector<bool> mesh_indep_stack_opt;
+   const E_F0_Optimize * optiexp0,*optiexpK;
+   bool isoptimize;
+   
+   LinearComb(): v(),
+		 where_in_stack_opt(),mesh_indep_stack_opt(),
+		 optiexp0(0),optiexpK(0),isoptimize(false) {}
+   
+   LinearComb(const I& i,const R& r) :v(1),
+				      where_in_stack_opt(),mesh_indep_stack_opt(),
+				      optiexp0(),optiexpK(),isoptimize(false) 
+   {
+     v[0]=make_pair<I,R>((I)i,(R)r);
+   }
+   
+   LinearComb(const LinearComb &l) 
+      :v(l.v),
+        where_in_stack_opt(l.where_in_stack_opt),
+        mesh_indep_stack_opt(l.mesh_indep_stack_opt),
+        optiexp0(l.optiexp0),optiexpK(l.optiexpK),isoptimize(false){}  
+        
+   int nbtrue(bool *ok) const 
+     { 
+        int k=0; 
+        for (size_t i=0;i<v.size();i++) 
+          if (ok[i]) k++;
+         return k;
+     }
+     
+   //  copy just les parties ok   
+   LinearComb(const LinearComb &l,bool * ok) 
+     :v(l.nbtrue(ok) ),
+      where_in_stack_opt(v.size()),
+      mesh_indep_stack_opt(v.size()),
+      optiexp0(l.optiexp0),optiexpK(l.optiexpK),
+      isoptimize(l.isoptimize) 
+      {
+	// int k=0;
+        const_iterator lll= l.v.begin();
+        iterator ll=v.begin(); 
+        for (int i=0,k=0;lll!= l.v.end();++lll,++i) 
+          if (ok[i]) 
+            {
+            *ll++=*lll;
+            where_in_stack_opt[k]=l.where_in_stack_opt[i];
+            mesh_indep_stack_opt[k]=l.mesh_indep_stack_opt[i];
+            ++k;            
+            }
+         
+      }  
+        
+       
+   void operator=(const LinearComb<I,R> &l) {
+     v=l.v;
+     where_in_stack_opt=l.where_in_stack_opt;
+     mesh_indep_stack_opt=l.mesh_indep_stack_opt;
+     optiexp0=l.optiexp0;
+     optiexpK=l.optiexpK;
+     isoptimize=l.isoptimize; 
+     }
+   const I * simple() const { if (v.size()==1) return & v.begin()->first;else return  0;}     
+   void  add(const I& i,const R &r)  { 
+     for (iterator k=v.begin();k!=v.end();k++)
+       if (k->first == i) {k->second += r;return ;}
+     v.push_back(make_pair<I,R>((I)i,(R)r));     
+   }
+   
+   size_type size() const { return v.size();}   
+   
+   const K & operator[](size_type i) const { return v[i];}
+   
+   void operator+=(const LinearComb & l) {
+     for (const_iterator k=l.v.begin();k!=l.v.end();k++)
+       { const K & kk(*k);
+       add(kk.first,kk.second);}
+   }
+   
+   void operator*=(const R & r) {
+     for (iterator k=v.begin();k!=v.end();k++)
+       {K & kk(*k);
+       kk.second = kk.second*r;}
+   }     
+   
+   void operator/=(const R & r) {
+     for (iterator k=v.begin();k!=v.end();k++)
+       {K & kk(*k);
+       kk.second = kk.second/r; }
+   }     
+   
+  AnyType operator()(Stack )  const {
+    return SetAny<const LinearComb<I,R> * >(this);}
+  operator aType () const { return atype<const LinearComb >();}         
+    
+    
+  bool mappable(bool (*f)(const  R &)) const {
+     for (const_iterator k=v.begin();k!=v.end();k++)
+       if (!(*f)(k->second)) return false;
+      return true;}
+      
+  void mapping(R (*f)(const R &)) {
+     for (iterator k=v.begin();k!=v.end();k++)
+       k->second=(*f)(k->second) ;}
+  
+  int MaxOp() const {
+    int m=0;
+     for (const_iterator k=v.begin();k!=v.end();k++)
+       m= maxop(m,(k->first)) ;
+     return m;}
+    
+ void DiffOp(KN_<bool> &d) const {
+     assert(d.N() >= last_operatortype);
+     d=false;
+     for (const_iterator k=v.begin();k!=v.end();k++)
+       SetOp(d,k->first);
+       
+   
+ }  
+  unsigned int DiffOp(int & lastop) const
+ {
+   unsigned int d=0;
+   lastop=0;
+   for (const_iterator k=v.begin();k!=v.end();k++)
+     d |= GetDiffOp(k->first,lastop);
+     
+   assert(lastop<last_operatortype);
+   lastop++;
+   
+   return d;
+  }  
+  
+  ostream & dump(ostream &f) const {
+    int n = size();
+    for (int i=0; i<n; i++)
+      {
+        const K & ri=v[i];
+        Expression ee= ri.second.LeftValue();
+        f  << "\n\t\t"<< i << " " << ri.first << ": "  ;
+       f << " :  type exp: " << typeid(*ee).name() << " "<<endl;
+      }
+
+    return f;
+  } 
+ LinearComb * Optimize(Block * b)  
+  {
+    const bool kdump=(verbosity/1000)%10==1;
+    if (kdump)
+    cout << "\n\n Optimize " << endl;
+    LinearComb * r=new LinearComb(*this);
+    LinearComb  &rr= *r;
+    int n = rr.size();
+    
+    deque<pair<Expression,int> > ll;
+    MapOfE_F0 m;
+    rr.where_in_stack_opt.resize(n);
+    rr.mesh_indep_stack_opt.resize(n);
+    size_type top = b->OffSet(0), topbb=top; // FH. bofbof ??? 
+    for (int i=0; i<n; i++)
+      {
+      const K & ri=rr.v[i];
+       Expression ee= ri.second.LeftValue();
+       if (kdump)
+       cout << "Optimize :  type exp: " << typeid(*ee).name() << " "<<endl;
+        rr.mesh_indep_stack_opt[i]=ee->MeshIndependent(); 
+       rr.where_in_stack_opt[i]=ee->Optimize(ll, m, top);
+       if (kdump)
+       cout  << "\n\t\t"<< i << " " << ri.first << ": " << rr.where_in_stack_opt[i] << endl;
+      }
+      
+    b->OffSet(top-topbb);
+    //  
+    int k=ll.size(),k0=0,k1=0;
+    for (int i=0;i<k;i++)
+        if (ll[i].first->MeshIndependent()) k0++;
+    deque<pair<Expression,int> > l0(k0),l1(k-k0);
+    k0=0,k1=0;
+    for (int i=0;i<k;i++)
+       if (ll[i].first->MeshIndependent()) 
+         {
+          if (kdump)
+          cout << " mi " << ll[i].second << " " << *(ll[i].first) << endl;
+          l0[k0++]=ll[i];
+         }
+        else 
+         {
+          if (kdump)
+          cout << " md " << ll[i].second << " " << *(ll[i].first) << endl;
+          l1[k1++]=ll[i];
+         }
+    if (k0)      
+      rr.optiexp0 = new E_F0_Optimize(l0,m,0);  
+    if (k1) 
+      rr.optiexpK = new E_F0_Optimize(l1,m,0);
+    rr.isoptimize=true;
+    if (kdump) cout << "LinearCom Optimize k0(mi) = " << k0 << " k1 = " << k1 << "\n\n"<<endl;
+    return r;
+  }    
+   
+};
+
+
+
+template<class I,class R>
+LinearComb<I,R> operator+(const LinearComb<I,R> & a,const LinearComb<I,R> & b)
+ {LinearComb<I,R> r(a);r+=b;return r;}
+
+template<class I,class R>
+LinearComb<I,R> operator*(const LinearComb<I,R> & a,const R & b)
+ {LinearComb<I,R> r(a);r*=b;return r;}
+template<class I,class R>
+LinearComb<I,R> operator*(const R & b,const LinearComb<I,R> & a)
+ {LinearComb<I,R> r(a);r*=b;return r;}
+ 
+
+ 
+class MGauche :public pair<int,operatortype> {public:
+  MGauche() {}
+  MGauche(int i,operatortype j) {first = i;second= j;}
+  MGauche(const pair<int,operatortype> &p) : pair<int,operatortype>(p){}
+  bool operator==(const MGauche& a) const {
+    return static_cast<bool>(first == a.first && second == a.second);}
+  int maxop(int op) const { return Max(op,(int) second);}
+    
+};
+
+class MDroit :public pair<int,operatortype> {public:
+  MDroit(){}
+  MDroit(int i,operatortype j) {first = i;second =j;}
+  //   first : number of unknow 
+  // second  : number of operator ( 0 Id, 1 dx, 2 dy)
+  MDroit(const pair<int,operatortype> &p) : pair<int,operatortype>(p){}
+  bool operator==(const MDroit& a) const {
+    return static_cast<bool>(first == a.first && second == a.second);}
+};
+
+inline ostream & operator<<(ostream & f,const MDroit & p)
+{ f << p.first <<','<<p.second ;
+  return f;}
+inline ostream & operator<<(ostream & f,const MGauche & p)
+{ f << p.first <<';'<<p.second ;
+  return f;}
+  
+template<typename A,typename B>
+inline ostream & operator<<(ostream & f,const pair<A,B> &p)
+{ f << p.first <<" "<<p.second ;
+  return f;}
+  
+  
+//extern const C_F0 & One, &Zero;
+C_F0 operator*(const C_F0 &,const C_F0 &);
+C_F0 & operator+=(const C_F0 &,const C_F0 &);
+ 
+typedef LinearComb<MGauche,C_F0> LinearOperatorG;
+typedef LinearComb<MDroit ,C_F0> LinearOperatorD;
+
+typedef LinearComb<pair<MGauche,MDroit>,C_F0> BilinearOperator;
+
+inline  int maxop(int op,const MGauche & v) 
+    { return Max(op,(int) v.second);}
+inline  int maxop(int op,const MDroit & v) 
+    { return Max(op,(int) v.second);}
+inline  int maxop(int op,const pair<MGauche,MDroit> & b) 
+    { return Max(op,(int) b.first.second,(int) b.second.second );}
+ 
+inline BilinearOperator operator*(const LinearOperatorG & a,const LinearOperatorD & b) 
+ {
+   BilinearOperator r;
+   for (LinearOperatorG::const_iterator i=a.v.begin();i!=a.v.end();i++)
+     for (LinearOperatorD::const_iterator j=b.v.begin();j!=b.v.end();j++)
+       {
+	 const LinearOperatorG::K  vi(*i);
+	 const LinearOperatorD::K  vj(*j);
+	
+	 r.add(make_pair(vi.first,vj.first),vi.second*vj.second);
+	   
+       }
+    return r;
+ } 
+inline BilinearOperator operator*(const LinearOperatorD & b,const LinearOperatorG & a) 
+ {
+   BilinearOperator r;
+   for (LinearOperatorG::const_iterator i=a.v.begin();i!=a.v.end();i++)
+     for (LinearOperatorD::const_iterator j=b.v.begin();j!=b.v.end();j++)
+       {
+	 const LinearOperatorG::K  vi(*i);
+	 const LinearOperatorD::K  vj(*j);
+	
+	 r.add(make_pair(vi.first,vj.first),vi.second*vj.second);
+	   
+       }
+    return r;
+ } 
+ostream & operator<<(ostream & f,const  BilinearOperator & a); 
+ 
+inline ostream & operator<<(ostream & f,const  BilinearOperator & a)
+{
+  int k=0;
+  for (BilinearOperator::const_iterator i=a.v.begin();i!=a.v.end();i++)
+    {
+      const BilinearOperator::K  vi(*i);
+      const char * www[]={" ","_x ","_y "};
+      const  pair<pair<int,int>,pair<int,int> > i1(vi.first);
+      const  pair<int,int> ii(i1.first),jj(i1.second);
+      f << *(const E_F0 *) vi.second <<  char('u'+ii.first) << www[ii.second] << " " << char('u'+jj.first)<<"'" << www[jj.second] ;
+      if ( (++k%5)==0) f << endl ; else f << " ";
+    }
+  return f;
+}
+typedef LinearOperatorD LOperaD;
+typedef LinearOperatorG LOperaG;
+typedef BilinearOperator Opera;
+inline LOperaG DiffG(int i,operatortype j) { return LOperaG(make_pair(i,j),*pOne);}
+inline LOperaD DiffD(int i,operatortype j) { return LOperaD(make_pair(i,j),*pOne);}
+
+inline LOperaG *newU_(int i) {  LOperaG * r;
+  r= new LOperaG(make_pair(i,op_id),*pOne);
+ SHOWVERB( cout << "newU_ " << r << endl);
+  return r; }
+inline LOperaG *newU_x(int i) { return new LOperaG(make_pair(i,op_dx),*pOne);}
+inline LOperaG *newU_y(int i) { return new LOperaG(make_pair(i,op_dy),*pOne);}
+inline LOperaD *newV_(int i) { return new LOperaD(make_pair(i,op_id),*pOne);}
+inline LOperaD *newV_x(int i) { return new LOperaD(make_pair(i,op_dx),*pOne);}
+inline LOperaD *newV_y(int i) { return new LOperaD(make_pair(i,op_dy),*pOne);}
+
+template<class L>
+ L *  Diff(const L *   u,const  operatortype & d) { 
+     throwassert(u);
+     L * r= new  L(*u);
+    for (typename L::iterator i=r->v.begin();i!=r->v.end();i++)
+      {   
+	  operatortype & dd=i->first.second;
+	  if (dd != op_id)
+	    { ffassert(0); i->first.second = op_id;  } // a faire          
+	  else {
+	      ffassert(i->second.EvaluableWithOutStack());// a faire derivation des fonctions
+	      dd = d ; }
+          
+    }
+    return r;}
+
+template<class L>
+L *  CONJ_op(const L *   u) { 
+    throwassert(u);
+    L * r= new  L(*u);
+    for (typename L::iterator i=r->v.begin();i!=r->v.end();i++)
+      {   typename L::TR  & cc=i->second;
+	  if( cc.right()==atype<Complex>() ) 
+	      i->second= C_F0(TheOperators,"\'",cc);
+          
+      }
+    return r;}
+	    
+
+
+template<class L>
+int  MaxOp(const L *   u) { 
+     throwassert(u);
+     int op=0;
+    for (typename L::const_iterator i=u->v.begin();i!=u->v.end();i++)          
+          op = maxop(op,i->first);
+    return op;}
+    
+    
+    
+template<class L,class A,L* ff(const basicAC_F0 & args)>
+class CODE_L1 { public:
+  typedef L* Result;
+  typedef L* (*func)(const basicAC_F0 & args) ;
+  static L* f(const basicAC_F0 & args) { return ff(args);} //  ff :A-> L*
+  static ArrayOfaType  typeargs() {return ArrayOfaType(atype<A>);}
+};
+
+template<class L>
+class CODE_L_Add { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const L * a(dynamic_cast<const L*>((Expression) args[0]));
+    const L * b(dynamic_cast<const L*>((Expression) args[1]));
+    throwassert(a  && b );
+    return new L(*a+*b);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<const L*>(),atype<const L*>());}
+};
+template<class L>
+class CODE_L_Sub { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const L * a(dynamic_cast<const L*>((Expression) args[0]));
+    const L * b(dynamic_cast<const L*>((Expression) args[1]));
+    throwassert(a  && b );
+    L * bb = new L(*pminusOne * *b);
+    return new L(*a+*bb);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<const L*>(),atype<const L*>());}
+};
+
+template<class L>
+class CODE_L_Minus { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const L * a(dynamic_cast<const L*>((Expression) args[0]));
+    throwassert(a  && pminusOne );
+    return new L(*pminusOne * *a);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<const L*>());}
+};
+template<class L>
+class CODE_L_Plus { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const L * a(dynamic_cast<const L*>((Expression) args[0]));
+    throwassert(a );
+    return new L( *a);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<const L*>());}
+};
+
+template<class L,class A,class B>
+class CODE_L_Mul { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const A * a(dynamic_cast<const A*>((Expression) args[0]));
+    const B * b(dynamic_cast<const B*>((Expression) args[1]));
+    SHOWVERB(cout << " CODE_L_Mul " << a << " " << b << endl);
+    throwassert(a  && b );
+    return new L(*a * *b);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<const A*>(),atype<const B*>());}
+};
+
+template<class T,class L>
+class CODE_L_MulRL { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const L * b(dynamic_cast<const L*>((Expression) args[1]));
+    if (!b) {
+      
+      cout << " --- " << ((Expression) args[1]) << typeid((Expression) args[1]).name() << endl;
+    throwassert( b );
+    }
+    return new L(to<T>(args[0]) * *b);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<T>(),atype<const L*>());}
+};
+
+template<class L,class T>
+class CODE_L_MulLR { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const L * a(dynamic_cast<const L*>((Expression) args[0]));
+    throwassert( a );
+    return new L(to<T>(args[1]) * *a);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<Result>(),atype<T>());}
+};
+
+template<class L,class T>
+class CODE_L_DivLR { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    const L * a(dynamic_cast<const L*>((Expression) args[0]));
+    throwassert( a );
+    return new L(C_F0(TheOperators,"/",*pOne,args[1]) * *a);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<Result>(),atype<T>());}
+};
+
+template<class L,operatortype op>
+class CODE_Diff { public:
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+   const L * a=dynamic_cast<const L*>((Expression) args[0]) ;
+    throwassert( a );
+    return  Diff(a,op);}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<Result>());}
+};
+
+template<class L>
+class CODE_conj { public:
+    typedef const L* Result;
+    static  E_F0 * f(const basicAC_F0 & args) { 
+	const L * a=dynamic_cast<const L*>((Expression) args[0]) ;
+	throwassert( a );
+	return  CONJ_op(a);}
+    static ArrayOfaType  typeargs() {return ArrayOfaType(atype<Result>());}
+};
+
+enum TheCode_VF { Code_Jump=1, Code_Mean=2, Code_OtherSide=3};
+
+template<class L,TheCode_VF code>
+class Code_VF { public:  
+  typedef const L* Result;
+  static  E_F0 * f(const basicAC_F0 & args) { 
+   const L * u=dynamic_cast<const L*>((Expression) args[0]) ;
+    assert( u );
+     L * r= new  L(*u);
+    for (typename L::iterator i=r->v.begin();i!=r->v.end();i++)
+      {   operatortype & dd=i->first.second;
+          assert(dd<last_operatortype);
+          dd = (operatortype) ((int) dd+last_operatortype*code) ; 
+     }    
+    return r;}
+   static ArrayOfaType  typeargs() {return ArrayOfaType(atype<Result>());}
+};
+         
diff --git a/src/femlib/Drawing.cpp b/src/femlib/Drawing.cpp
new file mode 100644
index 0000000..508ca85
--- /dev/null
+++ b/src/femlib/Drawing.cpp
@@ -0,0 +1,788 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cmath>
+#include "error.hpp"
+#include <cstdio>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include "rgraph.hpp"
+
+
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpacen.hpp" 
+#include "FESpace.hpp" 
+
+namespace Fem2D {
+
+void NewSetColorTable(int nb,float *colors=0,int nbcolors=0,bool hsv=true)
+{
+  if(colors && nbcolors)
+    SetColorTable1(nb,hsv,nbcolors,colors);
+  else
+    SetColorTable(nb);
+}
+int dichotomie(const RN_ &viso,R v) 
+{
+  int i=0,j=viso.N(),k;
+  if  (v <viso[0] || v >viso[j-1]) 
+    return -1;  
+  while (i<j-1)    
+   if ( viso[k=(i+j)/2]> v) j=k;
+   else i=k;
+  return i;
+}
+
+void plot(long i)
+{
+  char buf[24];
+  snprintf(buf,24,"%ld",i);
+  plotstring(buf);
+}
+void plot(int i)
+{
+  char buf[24];
+  snprintf(buf,24,"%d",i);
+  plotstring(buf);
+}
+void plot(double i)
+{
+  char buf[24];
+  snprintf(buf,24,"%g",i);
+  plotstring(buf);
+}
+
+void DrawIsoT(const R2 Pt[3],const R ff[3],const RN_ & Viso);
+void DrawIsoTfill(const R2 Pt[3],const R ff[3],const RN_ & Viso,double rapz);
+
+void FillRect(float x0,float y0, float x1, float y1)
+ {
+     float r[8];
+     r[0]=x0;r[1]=y0;
+     r[2]=x1;r[3]=y0;
+     r[4]=x1;r[5]=y1;
+     r[6]=x0;r[7]=y1;
+     fillpoly(4,r);
+ }
+
+void PlotValue(const RN_ & Viso,int  k0,const char * cmm)
+{
+   float xmin,xmax,ymin,ymax;
+ //  cout << "PlotValue " << Viso << endl;
+   // int ix,iy;
+  // GetSizeScreen(ix,iy);   
+   getcadre(xmin,xmax,ymin,ymax);
+   float dx=(xmax-xmin);
+   float dy=(ymax-ymin);
+   //  10 points  
+  // int kk = Max(30,iy/10);
+   float h=GetHeigthFont();
+   float x0=xmin+dx*0.8;
+   float y= ymin+dy*0.95;
+  // cout << x0 << " " << y << " " << h <<  endl;
+   y -= k0* h*1.4;
+   couleur(0);
+   FillRect(x0-h*0.5,y-h*(1.4*Viso.N()+0.3),x0+h*9,y+h*1.5);
+   couleur(1);
+   rmoveto(x0+1.2*h,y);
+   plotstring(cmm);
+   y -=  h*1.4;
+   for (int i=0;i<Viso.N();i++)
+    {
+       couleur(i+4);
+       FillRect(x0,y,x0+h,y+h);
+       rmoveto(x0+1.2*h,y);
+       y -=  h*1.4;
+       plot(Viso[i]);                 
+    }
+}
+
+void DrawCommentaire(const char * cm,float x,float y) 
+{
+   float xmin,xmax,ymin,ymax;
+   getcadre(xmin,xmax,ymin,ymax);
+   float dx=(xmax-xmin);
+   float dy=(ymax-ymin);
+   
+   rmoveto(xmin+dx*x,ymin+dy*y);
+   plotstring(cm);   
+}
+
+void Mesh::DrawBoundary() const
+{  
+    for(int i=0;i<neb;i++)
+       bedges[i].Draw();
+}
+void Mesh::InitDraw() const 
+   {
+     R2 Pmin,Pmax;
+     BoundingBox(Pmin,Pmax);
+     R2 O((Pmin+Pmax)/2);
+     R r =  (Max(Pmax.x-Pmin.x,Pmax.y-Pmin.y)*0.55);
+     showgraphic();
+     cadreortho((float)O.x,(float)(O.y+r*0.05),(float) r);
+    }
+inline  R Square(R x){return x*x;}
+
+void  SetDefaultIsoValue(const RN_& U,RN_ & Viso)
+ {
+   R umn = U.min();
+   R umx = U.max();
+   int N = Viso.N();
+   R d = (umx-umn)/(N+1);
+   R x = umn+d/2;
+   for (int i = 0;i < N;i++)
+     {Viso[i]=x;x +=d; }
+   NewSetColorTable(N+4) ;  
+ }
+void  SetDefaultIsoValue(const RN_& u,const RN_& v,RN_ & Viso)
+ {
+   R s = (Square(u[0])+Square(v[0]));
+   R umn =s ;
+   R umx = s;    
+   int n(v.N());
+    for (int i=1;i<n;i++)
+     {   s = (Square(u[i])+Square(v[i]));
+        umn = Min(umn,s),umx=Max(umn,s);
+      }  
+   umx=sqrt(umx);
+   umn=sqrt(umn);
+   
+   int N = Viso.N();
+   R d = (umx-umn)/(N-1);
+   R x = umn;
+   for (int i = 0;i < N;i++)
+     {Viso[i]=x;x +=d; }
+   Viso[N-1]= umx; 
+   NewSetColorTable(N+4) ;  
+ }
+ 
+ void Mesh::Draw(int init,bool fill) const
+ {
+   
+   if (init>0)  InitDraw();
+   
+   SetColorTable(16) ;  
+   for (int i=0;i<nt;i++)
+    {
+      if (fill) 
+       {
+         triangles[i].Fill(2+Abs(triangles[i].lab));         
+         couleur(triangles[i].lab?1:0);
+         triangles[i].Draw();
+       }
+      else 
+       {
+       couleur(1+Abs(triangles[i].lab));
+       triangles[i].Draw();}
+    }
+     
+
+   couleur(1);
+   penthickness(2); 
+   for (int i=0;i<NbMortars;i++)
+    {     
+      mortars[i].Draw();
+    }
+   penthickness(3);
+   double l= 1e100;
+   for (int i=0;i<neb;i++)
+     {
+       couleur(1+Abs( bedges[i].lab));
+       bedges[i].Draw();
+       l=Min(l,bedges[i].length());
+     }
+   for (int i=0;i<nv;i++)
+     { 
+       R2 P=vertices[i], N=vertices[i].Ne();
+       if (Norme2_2(N) ) 
+         { MoveTo(P); LineTo(P+N*l/5);  }
+     }
+   penthickness(1); 
+   if(init%2)
+   for (int i=0;i<nv;i++)
+    {
+      couleur(1+Abs(vertices[i].lab));
+      MoveTo(vertices[i]);
+      plot(i);
+    }
+   couleur(1);
+//   rattente(0);
+ }
+
+void FElement::Draw(const RN_& U,const RN_ & Viso,int composante) const
+{   
+  int nsb = nbsubdivision();
+  int nsb2 = NbOfSubTriangle(nsb);
+  int nbdf=NbDoF();
+  RN fk(nbdf);
+  for (int i=0;i<nbdf;i++) // get the local value
+    fk[i] = U[operator()(i)];
+  RNMK fb(nbdf,N,3); //  the value for basic fonction
+  RN ff(3);
+  R2 Pt,P[3],A(T[0]),B(T[1]),C(T[2]);
+  bool whatd[last_operatortype];
+  initwhatd(whatd,0);
+  
+  for (int k=0;k<nsb2;k++)
+   {   
+   //  ff=0.0;
+     for (int j=0;j<3;j++)
+      { 
+     //   cout << nbdf << endl;
+        Pt=SubTriangle(nsb,k,j); //  current point 
+        BF(whatd,Pt,fb);
+        ff[j] = (fb('.',composante,0),fk);
+        P[j] = A*(1-Pt.x-Pt.y)+B*Pt.x + C*Pt.y;
+       }
+     DrawIsoT(P,ff,Viso);  
+   } 
+} 
+    
+void FElement::Drawfill(const RN_& U,const RN_ & Viso,int composante, double rapz) const
+{   
+  int nsb = nbsubdivision();
+  int nsb2 =  NbOfSubTriangle(nsb);
+  int nbdf=NbDoF();
+  RN fk(nbdf);
+  for (int i=0;i<nbdf;i++) // get the local value
+    fk[i] = U[operator()(i)];
+  RNMK fb(nbdf,N,3); //  the value for basic fonction
+  RN ff(3);
+  R2 Pt,P[3],A(T[0]),B(T[1]),C(T[2]);
+  bool whatd[last_operatortype];
+  initwhatd(whatd,0);
+  
+  for (int k=0;k<nsb2;k++)
+   {   
+   //  ff=0.0;
+     for (int j=0;j<3;j++)
+      { 
+     //   cout << nbdf << endl;
+        Pt=SubTriangle(nsb,k,j); //  current point 
+        BF(whatd,Pt,fb);
+        ff[j] = (fb('.',composante,0),fk);
+        P[j] = A*(1-Pt.x-Pt.y)+B*Pt.x + C*Pt.y;
+       }
+     DrawIsoTfill(P,ff,Viso,rapz);  
+   } 
+} 
+
+R2 FElement::MinMax(const RN_& U,const RN_& V,int i0,int i1) const
+{
+  R2 minmax(1e100,-1e100);
+  int nsb = nbsubdivision();
+  int nsb2 =  NbOfSubTriangle(nsb);
+  int nbdf=NbDoF();
+  RN fk(nbdf);
+  RN gk(nbdf);
+  RNMK fb(nbdf,N,3); //  the value for basic fonction
+  RN f0(3);
+  RN f1(3);
+  bool whatd[last_operatortype];
+  initwhatd(whatd,0);  
+  R2 Pt,A(T[0]),B(T[1]),C(T[2]);
+  for (int i=0;i<nbdf;i++) // get the local value
+    fk[i] = U[operator()(i)];
+  for (int i=0;i<nbdf;i++) // get the local value
+    gk[i] = V[operator()(i)];
+  for (int k=0;k<nsb2;k++)
+   {   
+   //  ff=0.0;
+     for (int j=0;j<3;j++)
+      { 
+     //   cout << nbdf << endl;
+        R2 Pt=SubTriangle(nsb,k,j); //  current point 
+        BF(whatd,Pt,fb);
+        f0[j] = (fb('.',i0,0),fk);
+        f1[j] = (fb('.',i1,0),gk);
+        R2 uv(f0[j],f1[j]);
+        R uv2 = (uv,uv);
+        minmax.x=Min(minmax.x,uv2);
+        minmax.y=Max(minmax.y,uv2);
+        
+       }
+    }
+   return minmax;
+}
+
+R2 FElement::MinMax(const RN_& U,int i0) const
+{
+  R2 minmax(1e100,-1e100);
+  int nsb = nbsubdivision();
+  int nsb2 =  NbOfSubTriangle(nsb);
+  int nbdf=NbDoF();
+  RN fk(nbdf);
+  RNMK fb(nbdf,N,3); //  the value for basic fonction
+  RN f0(3);
+  RN f1(3);
+  R2 Pt,A(T[0]),B(T[1]),C(T[2]);
+   bool whatd[last_operatortype];
+  initwhatd(whatd,0);
+ 
+  for (int i=0;i<nbdf;i++) // get the local value
+    fk[i] = U[operator()(i)];
+  for (int k=0;k<nsb2;k++)
+   {   
+   //  ff=0.0;
+     for (int j=0;j<3;j++)
+      { 
+     //   cout << nbdf << endl;
+        R2 Pt=SubTriangle(nsb,k,j); //  current point 
+        BF(whatd,Pt,fb);
+        f0[j] = (fb('.',i0,0),fk);
+        minmax.x=Min(minmax.x,f0[j]);
+        minmax.y=Max(minmax.y,f0[j]);        
+       }
+    }
+   return minmax;
+}
+void FElement::Draw(const RN_& U,const RN_& V,const RN_ & Viso,R coef,int i0,int i1) const
+{
+  bool whatd[last_operatortype];
+  initwhatd(whatd,0);
+   
+  float xmin,xmax,ymin,ymax;
+  getcadre(xmin,xmax,ymin,ymax);
+  float d= Max(ymax-ymin,xmax-xmin);
+  R kk = d*0.005;
+  R cc = d*0.05;
+  int nsb = nbsubdivision();
+  int nsb2 = NbOfSubTriangle(nsb);
+  int nbdf=NbDoF();
+  RN fk(nbdf);
+  RN gk(nbdf);
+  for (int i=0;i<nbdf;i++) // get the local value
+    fk[i] = U[operator()(i)];
+  for (int i=0;i<nbdf;i++) // get the local value
+    gk[i] = V[operator()(i)];
+    
+  RNMK fb(nbdf,N,3); //  the value for basic fonction
+  RN f0(3);
+  RN f1(3);
+  R2 Pt,P[3],A(T[0]),B(T[1]),C(T[2]);
+  for (int k=0;k<nsb2;k++)
+   {   
+   //  ff=0.0;
+     for (int j=0;j<3;j++)
+      { 
+     //   cout << nbdf << endl;
+        Pt=SubTriangle(nsb,k,j); //  current point 
+        BF(whatd,Pt,fb);
+        f0[j] = (fb('.',i0,0),fk);
+        f1[j] = (fb('.',i1,0),gk);
+     //   if(number<2) 
+     //   cout << number << " " << fk << " " << fb('.',0,0) << " :  " << f0[j] << " " <<  f1[j] << endl;
+        P[j] = A*(1-Pt.x-Pt.y)+B*Pt.x + C*Pt.y;
+        R2 uv(f0[j],f1[j]);
+        R  l = Max(sqrt((uv,uv)),1e-30) ;
+        
+         {
+          couleur(2+dichotomie(Viso,l));
+          uv = coef*uv;
+          l *= coef;
+          R2 dd = uv*(-kk/l);// modif F.H size of arraow 08/14 FH.l
+          R2 dn = dd.perp()*0.5;
+          if (l*10000.< kk) continue;
+          if (l < kk) 
+	        uv = uv*(kk/l);
+          else if (l> cc)
+	        uv = uv*(cc/l);	   
+          MoveTo(P[j]);       
+          LineTo(P[j]+uv);
+          if (l>kk) {
+            LineTo(P[j]+uv+dd+dn);
+            MoveTo(P[j]+uv+dd-dn);
+            LineTo(P[j]+uv);}
+          }
+      }
+   } 
+} 
+
+void DrawIsoT(const R2 Pt[3],const R ff[3],const RN_ & Viso)
+{
+  R2 PQ[5];
+  int NbIso = Viso.N();
+  for(int l=0;l< NbIso;l++)  /*    loop on the level curves */
+    {
+      R xf = Viso[l];
+      int im=0;
+      for(int i=0;i<3;i++) // for the  3 edges 
+	{
+	  int j = (i+1)%3;
+	  R fi=(ff[i]);
+	  R fj=(ff[j]);
+	  
+	  if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+	    {
+	      if (Abs(fi-fj)<=0.1e-10) 	/* one side must be drawn */
+		{
+		  couleur(l+4);
+		  MoveTo(Pt[i]);
+		  LineTo(Pt[j]);
+		}
+	      else
+		{
+		  R  xlam=(fi-xf)/(fi-fj);
+		  PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+		}
+	    }
+	}
+      
+      if (im>=2) /*    draw one segment */
+	{
+	  couleur(l+4);
+	  MoveTo(PQ[0]);
+	  LineTo(PQ[1]);
+	}
+    }
+  
+} 
+void DrawIsoTfill(const R2 Pt[3],const R ff[3],const RN_ & Viso,double rapz)
+{
+  R2 PQ[10];
+  int NbIso = Viso.N();
+  R eps= (Viso[NbIso-1]-Viso[0])*1e-6;
+  for(int l=1;l< NbIso;l++)  //   loop on the level curves 
+    {
+      R xfb = Viso[l-1];
+      R xfh = Viso[l];
+      int im=0;
+      for(int i=0;i<3;i++) // for the  3 edges 
+	{
+          int j=(i+1)%3;
+          R fi=(ff[i]);
+          R fj=(ff[j]);
+          R xxfb =  xfb;
+          R xxfh =  xfh;
+	  if (fj<fi ) Exchange(xxfb,xxfh);
+          R xf  = xxfb;
+	  if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+	    {
+	      if (Abs(fi-fj)>=0.1e-20)
+		{
+		  R  xlam=(fi-xf)/(fi-fj);
+		  PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+		}
+	    }
+          xf = xxfh;	  
+	  if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+	    {
+	      if (Abs(fi-fj)>=0.1e-20)
+		{
+		  R  xlam=(fi-xf)/(fi-fj);
+		  PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+		}
+	    }
+	   if (  xfb-eps <=fj  && fj <= xfh+eps) 
+	     PQ[im++] = Pt[j];
+	}
+       if (im>2) 
+         {
+           float f[20];
+           int k=0;
+           for (int i=0;i<im;i++)
+            f[k++]=PQ[i].x,f[k++]=PQ[i].y;
+           f[k++]=f[0];
+           f[k++]=f[1];
+           
+           couleur(3+l);
+           fillpoly(im,f);
+         }
+     }
+} 
+
+template<class R2>
+void TBoundaryEdge<R2>::Draw() const 
+{
+  couleur(2+(lab%6));
+  MoveTo(*vertices[0]);
+  LineTo(*vertices[1]);
+}
+
+    template<class R>   
+    void FElement::SaveDraw(const KN_<R> & U,int composante,R* Usave) const 
+    {
+	int nsb = nbsubdivision();
+	int nsbv = NbOfSubInternalVertices(nsb);
+	int nbdf=NbDoF();
+	KN<R> fk(nbdf);
+	for (int i=0;i<nbdf;i++) // get the local value
+	    fk[i] = U[operator()(i)];
+	R2 Pt;
+	bool whatd[last_operatortype];
+	initwhatd(whatd,0);
+	
+	RNMK fb(nbdf,N,3); //  the value for basic fonction
+	for (int k=0;k<nsbv;k++)
+	  {
+	      Pt=SubInternalVertex(nsb,k); 
+	      BF(whatd,Pt,fb);
+	    Usave[k] = R();// (fb('.',composante,0),fk);
+	    for( int i=0; i<nbdf;++i)
+		Usave[k]   +=  fb(i,composante,0)*fk[i];
+	    
+	  }
+	
+    }
+     template<class R> 
+    void FElement::SaveDraw(const KN_<R> & U,const KN_<R> & V,int iU,int iV,R * Usave) const 
+    {
+	int nsb = nbsubdivision();
+	int nsbv = NbOfSubInternalVertices(nsb);
+	int nbdf=NbDoF();
+	KN<R> fk(nbdf);
+	KN<R> gk(nbdf);
+	for (int i=0;i<nbdf;i++) // get the local valu
+	  {
+	      fk[i] = U[operator()(i)];
+	      gk[i] = V[operator()(i)];
+	  }
+	R2 Pt;
+	bool whatd[last_operatortype];
+	initwhatd(whatd,0);
+	
+	RNMK fb(nbdf,N,3); //  the value for basic fonction
+	for (int k=0,k2=0;k<nsbv;k++)
+	  {
+	      Pt=SubInternalVertex(nsb,k); 
+	      BF(whatd,Pt,fb);
+	    Usave[k2]=R();
+	    Usave[k2+1]=R();
+	    for( int i=0; i<nbdf;++i)
+	      {
+		Usave[k2]   +=  fb(i,iU,0)*fk[i];
+		Usave[k2+1] +=  fb(i,iV,0)*gk[i];
+	      }
+	    k2+=2;
+	  }
+	
+    } 
+    
+template<class R>    
+KN<R>  FESpace::newSaveDraw(const KN_<R> & U,int composante,int & lg,int & nsb) const 
+    {
+	nsb = TFE[0]->nbsubdivision;
+	int nsbv = NbOfSubInternalVertices(nsb);
+	lg = nsbv*Th.nt;
+	if(verbosity>99)
+	cout << "           ++ newSaveDraw what: nt " << Th.nt << " " << nsbv << " " << lg << endl;
+	KN<R> v(lg);
+	ffassert(v);
+        for (int k=0,i=0;k<Th.nt;k++)
+	  {
+	    (*this)[k].SaveDraw( U,composante,&v[i]);	
+	      i+=nsbv;
+	  }
+	return KN<R>(true,v);// to remove the copy.
+    }
+template<class R>      
+KN<R>  FESpace::newSaveDraw(const KN_<R> & U,const KN_<R> & V,int iU,int iV,int & lg,int & nsb) const 
+    {
+	nsb = TFE[0]->nbsubdivision;
+	int nsbv = NbOfSubInternalVertices(nsb)*2;
+	lg = nsbv*Th.nt;
+	
+	KN<R> v(lg);
+	
+        for (int k=0,i=0;k<Th.nt;k++)
+	  {
+	      (*this)[k].SaveDraw( U,V,iU,iV,&v[i]);	
+	      i+=nsbv;
+	  }
+	return  KN<R>(true,v);// to remove the copy.
+    }
+    
+typedef complex<double> Complex;   
+template     
+    KN<double>  FESpace::newSaveDraw<double>(const KN_<double> & U,const KN_<double> & V,int iU,int iV,int & lg,int & nsb) const ;
+template    
+    KN<double>  FESpace::newSaveDraw<double>(const KN_<double> & U,int composante,int & lg,int & nsb) const ;
+    template     
+    KN<Complex>  FESpace::newSaveDraw<Complex>(const KN_<Complex> & U,const KN_<Complex> & V,int iU,int iV,int & lg,int & nsb) const ;
+    template    
+    KN<Complex>  FESpace::newSaveDraw<Complex>(const KN_<Complex> & U,int composante,int & lg,int & nsb) const ;
+    
+   
+void  FESpace::Draw(const RN_& U,const RN_ & Viso,int j,float *colors,int nbcolors,bool hsv,bool drawborder) const 
+{
+  showgraphic();
+  NewSetColorTable(Viso.N()+4,colors,nbcolors,hsv);
+  for (int k=0;k<Th.nt;k++) 
+    (*this)[k].Draw( U,Viso,j);
+  NewSetColorTable(2+6,colors,nbcolors,hsv);
+  if(drawborder) Th.DrawBoundary();
+  NewSetColorTable(Viso.N()+4,colors,nbcolors,hsv);
+
+}
+
+void  FESpace::Drawfill(const RN_& U,const RN_ & Viso,int j,double rapz,float *colors,int nbcolors,bool hsv,bool drawborder) const 
+{
+  showgraphic();
+  NewSetColorTable(Viso.N()+4,colors,nbcolors,hsv);
+  for (int k=0;k<Th.nt;k++) 
+    (*this)[k].Drawfill( U,Viso,j,rapz);
+  NewSetColorTable(2+6,colors,nbcolors,hsv);
+  if(drawborder) Th.DrawBoundary();
+  NewSetColorTable(Viso.N()+4,colors,nbcolors,hsv);
+}
+
+
+
+R2 FESpace::MinMax(const KN_<R>& U,const KN_<R>& V,int j0,int j1,bool  bb) const 
+{
+  R2 Pminmax(1e100,-1e100);
+    for (int k=0;k<Th.nt;k++)
+     { 
+        const Triangle & K(Th[k]);
+        R2 A(K[0]),B(K[1]),C(K[2]);
+        if (bb  || InRecScreen(Min(A.x,B.x,C.x),Min(A.y,B.y,C.y),Max(A.x,B.x,C.x),Max(A.y,B.y,C.y))) 
+         Pminmax=minmax(Pminmax,(*this)[k].MinMax(U,V,j0,j1));
+     }
+   return Pminmax;
+}
+R2 FESpace::MinMax(const KN_<R>& U,int j0,bool bb) const 
+{
+  R2 Pminmax(1e100,-1e100);
+    for (int k=0;k<Th.nt;k++) 
+      {
+        const Triangle & K(Th[k]);
+        R2 A(K[0]),B(K[1]),C(K[2]);
+        if (bb  || InRecScreen(Min(A.x,B.x,C.x),Min(A.y,B.y,C.y),Max(A.x,B.x,C.x),Max(A.y,B.y,C.y))) 
+          Pminmax=minmax(Pminmax,(*this)[k].MinMax(U,j0));
+      }
+   return Pminmax;
+}
+void  FESpace::Draw(const KN_<R>& U,const RN_ & Viso, R coef,int j0,int j1,float *colors,int nbcolors,bool hsv,bool drawborder) const 
+{ 
+  showgraphic();
+  NewSetColorTable(Viso.N()+5,colors,nbcolors,hsv);
+  for (int k=0;k<Th.nt;k++) 
+    (*this)[k].Draw( U,U,Viso,coef,j0,j1);
+  NewSetColorTable(2+6,colors,nbcolors,hsv);
+  if(drawborder) Th.DrawBoundary();
+  NewSetColorTable(Viso.N()+5,colors,nbcolors,hsv);
+
+}
+
+void  FESpace::Draw(const KN_<R>& U,const KN_<R>& V,const RN_ & Viso, R coef,int iu,int iv,float *colors,int nbcolors,bool hsv,bool drawborder) const 
+{ 
+  showgraphic();
+  NewSetColorTable(Viso.N()+5,colors,nbcolors,hsv);
+  for (int k=0;k<Th.nt;k++) 
+    (*this)[k].Draw( U,V,Viso,coef,iu,iv);
+  NewSetColorTable(2+6,colors,nbcolors,hsv);
+  if(drawborder) Th.DrawBoundary();
+   NewSetColorTable(Viso.N()+5,colors,nbcolors,hsv);
+
+}
+
+
+template<class R2>
+void TTriangle<R2>::Draw(double skrink) const
+{
+  const TTriangle<R2> & K(*this);
+  R2 A(K[0]),B(K[1]),C(K[2]),G((A+B+C)/3.);
+  A = G + (A-G)*skrink;
+  B = G + (B-G)*skrink;
+  C = G + (C-G)*skrink;
+  MoveTo(A);
+  LineTo(B);
+  LineTo(C);
+  LineTo(A);
+}
+
+template<class R2>
+void TTriangle<R2>::Draw(int edge,double skrink) const 
+{
+  const TTriangle<R2> & K(*this);
+  R2 A(K[0]),B(K[1]),C(K[2]),G((A+B+C)/3.);
+  MoveTo(G+(*vertices[(edge+1)%3]-G)*skrink);
+  LineTo(G+(*vertices[(edge+2)%3]-G)*skrink);
+}
+
+
+template  void TTriangle<R2>::Draw(double skrink) const;
+template  void TTriangle<R2>::Draw(int edge,double skrink) const;
+
+template<class R2>
+void TTriangle<R2>::Fill(int color) const 
+{
+  const TTriangle<R2> & K(*this);
+  R2 A(K[0]),B(K[1]),C(K[2]);
+  float p[]={(float)A.x,(float)A.y,(float)B.x,(float)B.y,(float)C.x,(float)C.y};
+  int c=LaCouleur(); 
+  couleur(color); 
+  fillpoly(3,p);
+  couleur(c); 
+}
+
+void DrawMark(R2 P,R k)
+ {
+   float x0,x1,y0,y1;
+   getcadre(x0,x1,y0,y1);
+   float h= (x1-x0)*(float)k;
+   rmoveto((float)P.x+h,(float)P.y-h);
+   rlineto((float)P.x+h,(float)P.y+h);
+   rlineto((float)P.x-h,(float)P.y+h);
+   rlineto((float)P.x-h,(float)P.y-h);
+   rlineto((float)P.x+h,(float)P.y-h);
+ }
+ 
+ Triangle * Mesh::Find(const R2 & P) const 
+ {
+    // brute force
+    
+    for (int i=0;i<nt;i++)
+     {
+      kthrough++;
+      const Triangle & K(triangles[i]);
+      R2 A(K[0]),B(K[1]),C(K[2]);
+      R a=Area2(P,B,C);
+      R b=Area2(A,P,C);
+      R c=Area2(A,B,P);
+      R s=a+b+c;
+      R eps=s*1e-6;
+      if (a>-eps && b >-eps && c >-eps) return triangles + i;
+      
+     }
+   return 0; // outside 
+ }
+
+template<class R2>
+ void TMortar<R2>::Draw() const {
+   throwassert(Th);
+   for (int i=0;i<nleft;i++)
+     (*Th)[left[i]/3].Draw(left[i]%3,0.8);     
+   for (int i=0;i<nright;i++)
+     (*Th)[right[i]/3].Draw(right[i]%3,0.8);
+     
+ }
+}
diff --git a/src/femlib/Element_P2h.cpp b/src/femlib/Element_P2h.cpp
new file mode 100644
index 0000000..e9cc7d5
--- /dev/null
+++ b/src/femlib/Element_P2h.cpp
@@ -0,0 +1,134 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "error.hpp"
+#include "rgraph.hpp"
+using namespace std;  
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpace.hpp"
+
+namespace  Fem2D {
+
+ // ------ P2h  Hierarchical (just remove P1 node of the P2 finite element)  --------
+ class TypeOfFE_P2hLagrange : public  TypeOfFE { public:  
+  static int Data[];
+    static double Pi_h_coef[];
+
+   TypeOfFE_P2hLagrange(): TypeOfFE(0,1,0,1,Data,4,1,3,3,Pi_h_coef)
+    {  
+    
+       const R2 Pt[] = { R2(0.5,0.5), R2(0.0,0.5), R2(0.5,0.0) };
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+} ;
+//                     on what     nu df on node node of df    
+  int TypeOfFE_P2hLagrange::Data[]={3,4,5,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0, 0,3 };
+  double TypeOfFE_P2hLagrange::Pi_h_coef[]={1.,1.,1.};
+
+ void TypeOfFE_P2hLagrange::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  //  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+  throwassert( val.N()>=3);
+  throwassert(val.M()==1);
+  
+  val=0; 
+// --     
+ if (whatd[op_id])
+  {
+   RN_ f0(val('.',0,op_id)); 
+  f0[0] = 4*l1*l2; // oppose au sommet 0
+  f0[1] = 4*l0*l2; // oppose au sommet 1
+  f0[2] = 4*l1*l0; // oppose au sommet 3
+  }
+ if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+ {
+   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  if (whatd[op_dx])
+  {
+    RN_ f0x(val('.',0,op_dx)); 
+  f0x[0] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
+  f0x[1] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
+  f0x[2] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
+  }
+
+ if (whatd[op_dy])
+  {  
+    RN_ f0y(val('.',0,op_dy)); 
+  f0y[0] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
+  f0y[1] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
+  f0y[2] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
+  }
+ 
+ if (whatd[op_dxx])
+  {  
+    RN_ fxx(val('.',0,op_dxx)); 
+
+    fxx[0] =  8*Dl1.x*Dl2.x;
+    fxx[1] =  8*Dl0.x*Dl2.x;
+    fxx[2] =  8*Dl0.x*Dl1.x;
+  }
+
+ if (whatd[op_dyy])
+  {  
+    RN_ fyy(val('.',0,op_dyy)); 
+    fyy[0] =  8*Dl1.y*Dl2.y;
+    fyy[1] =  8*Dl0.y*Dl2.y;
+    fyy[2] =  8*Dl0.y*Dl1.y;
+  }
+ if (whatd[op_dxy])
+  {  
+    assert(val.K()>op_dxy);
+    RN_ fxy(val('.',0,op_dxy)); 
+  
+    fxy[0] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+    fxy[1] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+    fxy[2] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+  }
+ 
+ }
+ 
+}
+// link with FreeFem++  do not work with static library .a 
+//  FH so add a extern name to call in init_static_FE (see end of FESpace.cpp)
+void init_FE_P2h() { };
+
+extern  ListOfTFE typefem_P2h;
+
+static TypeOfFE_P2hLagrange P2LagrangeP2h;
+// given the name of the finite element in FreeFem++
+ ListOfTFE typefem_P2h("P2h", &P2LagrangeP2h);
+
+
+// --- fin -- 
+} // FEM2d namespace 
diff --git a/src/femlib/Element_RT.cpp b/src/femlib/Element_RT.cpp
new file mode 100644
index 0000000..fd7325d
--- /dev/null
+++ b/src/femlib/Element_RT.cpp
@@ -0,0 +1,831 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <cmath>
+#include <cstdlib>
+#include "error.hpp"
+#include <iostream>
+#include <fstream>
+#include <map>
+#include "rgraph.hpp"
+using namespace std;  
+
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpace.hpp"
+
+namespace  Fem2D {
+
+class TypeOfFE_RT : public  TypeOfFE { public:  
+  static int Data[];
+   TypeOfFE_RT(): TypeOfFE(0,1,0,2,Data,1,1,6,3) 
+     {const R2 Pt[] = { R2(0.5,0.5), R2(0.0,0.5), R2(0.5,0.0) };
+      for (int p=0,kk=0;p<3;p++)
+       { P_Pi_h[p]=Pt[p];   
+        for (int j=0;j<2;j++) 
+        pij_alpha[kk++]= IPJ(p,p,j);
+       }}
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * watdd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+//   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+   void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const ;
+} ; 
+//                     on what     nu df on node node of df    
+  int TypeOfFE_RT::Data[]={3,4,5,       0,0,0,       0,1,2,       0,0,0,        0,1,2,   0,0, 0,0,3,3};
+
+/* void TypeOfFE_RT::D2_FB(const Mesh & ,const Triangle & ,const R2 & ,RNMK_ & val) const
+{ //  
+  val=0;
+}*/
+/*
+ void TypeOfFE_RT::FB(const Mesh & Th,const Triangle & K,const R2 & PHat,RNMK_ & val) const
+{ //  
+//  const Triangle & K(FE.T);
+  R2 P(K(PHat));
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+ // R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==2 );
+  throwassert(val.K()==3 );
+  RN_ f0(val('.',0,0)); 
+  RN_ f1(val('.',1,0)); 
+  val=0;  
+//  RN_ df0(val(0,'.',0)); 
+//  RN_ fy(val('.','.',2)); 
+  //     a_i ([x,y]-c_i) , ou  c_i = A,B , C si i= 0,1,2 
+  //   int_T a_i div([x,y]-c_i) = 1
+  //    div div([x,y]-c_i) = 2 
+  //   donc a_i = 1/(2 area T)
+  
+  R a=1./(2*K.area);
+  R a0=   K.EdgeOrientation(0) * a ;
+  R a1=   K.EdgeOrientation(1) * a  ;
+  R a2=   K.EdgeOrientation(2) * a ;
+ // if (Th(K)< 2) cout << Th(K) << " " <<  A << " "  << B << " " << C << "; " <<  a0 << " " << a1 << " "<< a2 << endl;;
+
+  //  ------------
+  f0[0] = (P.x-A.x)*a0;
+  f1[0] = (P.y-A.y)*a0;
+  
+  f0[1] = (P.x-B.x)*a1;
+  f1[1] = (P.y-B.y)*a1;
+  
+  f0[2] = (P.x-C.x)*a2;
+  f1[2] = (P.y-C.y)*a2;
+  // ----------------
+  // ----------------
+  // BUG dans RT correct FH le 17 sept 2002 
+  //  dx [x,y] = [1,0] et non [1,1]
+  //  dy [x,y] = [0,1] et non [1,1] 
+  // -------------------------------------
+  
+  val(0,0,1) =  a0;  
+  val(1,0,1) =  a1;  
+  val(2,0,1) =  a2;  
+  val(0,1,2) =  a0;  
+  val(1,1,2) =  a1;  
+  val(2,1,2) =  a2;  
+  
+}
+*/
+ void TypeOfFE_RT::FB(const bool *whatd,const Mesh & Th,const Triangle & K,const R2 & PHat,RNMK_ & val) const
+{ //  
+//  const Triangle & K(FE.T);
+  R2 P(K(PHat));
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  // R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+ // R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==2 );
+//  throwassert(val.K()==3 );
+  val=0;     
+  R a=1./(2*K.area);
+  R a0=   K.EdgeOrientation(0) * a ;
+  R a1=   K.EdgeOrientation(1) * a  ;
+  R a2=   K.EdgeOrientation(2) * a ;
+ // if (Th(K)< 2) cout << Th(K) << " " <<  A << " "  << B << " " << C << "; " <<  a0 << " " << a1 << " "<< a2 << endl;;
+
+  //  ------------
+  if (whatd[op_id])
+   {
+   assert(val.K()>op_id);
+  RN_ f0(val('.',0,0)); 
+  RN_ f1(val('.',1,0)); 
+  f0[0] = (P.x-A.x)*a0;
+  f1[0] = (P.y-A.y)*a0;
+  
+  f0[1] = (P.x-B.x)*a1;
+  f1[1] = (P.y-B.y)*a1;
+  
+  f0[2] = (P.x-C.x)*a2;
+  f1[2] = (P.y-C.y)*a2;
+  }
+  // ----------------
+  // BUG dans RT correct FH le 17 sept 2002 
+  //  dx [x,y] = [1,0] et non [1,1]
+  //  dy [x,y] = [0,1] et non [1,1] 
+  // -------------------------------------
+    if (whatd[op_dx])
+   {
+   assert(val.K()>op_dx);
+   val(0,0,op_dx) =  a0;  
+   val(1,0,op_dx) =  a1;  
+   val(2,0,op_dx) =  a2; 
+  } 
+    if (whatd[op_dy])
+   {
+    assert(val.K()>op_dy);
+    val(0,1,op_dy) =  a0;  
+    val(1,1,op_dy) =  a1;  
+    val(2,1,op_dy) =  a2;  
+  }
+}
+/*
+ void TypeOfFE_RT::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j,  void * arg) const
+{
+  const R2 Pt[] = { R2(0.5,0.5), R2(0.0,0.5), R2(0.5,0.0) };
+  const Triangle & T(K.T);
+  //    if (K.number<2) cout << K.number << ": " ;
+   for (int i=0;i<3;i++)
+     {  
+       f(v,T(Pt[i]),K,i,Pt[i],arg);
+       R2 E(T.Edge(i));
+       R signe = T.EdgeOrientation(i) ;
+       val[i]= signe*(v[j]*E.y-v[j+1]*E.x); 
+    //   if (K.number<2) cout <<  val[i] << " " ;
+       }
+   //   if (K.number<2) cout << endl;
+}
+*/
+void TypeOfFE_RT::Pi_h_alpha(const baseFElement & K,KN_<double> & v) const 
+{
+  const Triangle & T(K.T);
+
+   for (int i=0,k=0;i<3;i++)
+     {  
+        R2 E(T.Edge(i));
+        R signe = T.EdgeOrientation(i) ;
+        v[k++]= signe*E.y;
+        v[k++]=-signe*E.x;
+     }   
+}
+// -------------------
+
+
+
+class TypeOfFE_RTmodif : public  TypeOfFE { public:  
+  static int Data[];
+   TypeOfFE_RTmodif(): TypeOfFE(0,1,0,2,Data,1,1,6,3) 
+     {const R2 Pt[] = { R2(0.5,0.5), R2(0.0,0.5), R2(0.5,0.0) };
+      for (int p=0,kk=0;p<3;p++)
+       { P_Pi_h[p]=Pt[p];   
+        for (int j=0;j<2;j++) 
+        pij_alpha[kk++]= IPJ(p,p,j);
+       }}
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ //  void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+   void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const ;
+} ; 
+//                     on what     nu df on node node of df    
+  int TypeOfFE_RTmodif::Data[]={3,4,5,       0,0,0,       0,1,2,       0,0,0,        0,1,2,   0,0,  0,0, 3,3};
+
+
+ void TypeOfFE_RTmodif::FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & PHat,RNMK_ & val) const
+{ //  
+//  const Triangle & K(FE.T);
+  R2 P(K(PHat));
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R la=1-PHat.x-PHat.y,lb=PHat.x,lc=PHat.y; 
+  R2 Dla(K.H(0)), Dlb(K.H(1)), Dlc(K.H(2));
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==2 );
+
+  R2 AB(A,B),AC(A,C),BA(B,A),BC(B,C),CA(C,A),CB(C,B);
+
+  R aa0= 1./(((AB,Dlb) + (AC,Dlc))*K.area);
+  R aa1= 1./(((BA,Dla) + (BC,Dlc))*K.area);
+  R aa2= 1./(((CA,Dla) + (CB,Dlb))*K.area);
+  int i=0;
+  R a0=   &K[ (i+1)%3] < &K[ (i+2)%3] ? aa0 : -aa0 ;
+  i=1;
+  R a1=   &K[ (i+1)%3] < &K[ (i+2)%3] ? aa1 : -aa1 ;
+  i=2;
+  R a2=   &K[ (i+1)%3] < &K[ (i+2)%3] ? aa2 : -aa2 ;
+ // if (Th(K)< 2) cout << Th(K) << " " <<  A << " "  << B << " " << C << "; " <<  a0 << " " << a1 << " "<< a2 << endl;;
+ 
+  R2 Va= AB*(lb*a0) + AC*(lc*a0);
+  R2 Vb= BA*(la*a1) + BC*(lc*a1);
+  R2 Vc= CA*(la*a2) + CB*(lb*a2);
+  R2 Va_x= AB*(Dlb.x*a0) + AC*(Dlc.x*a0);
+  R2 Vb_x= BA*(Dla.x*a1) + BC*(Dlc.x*a1);
+  R2 Vc_x= CA*(Dla.x*a2) + CB*(Dlb.x*a2);
+  R2 Va_y= AB*(Dlb.y*a0) + AC*(Dlc.y*a0);
+  R2 Vb_y= BA*(Dla.y*a1) + BC*(Dlc.y*a1);
+  R2 Vc_y= CA*(Dla.y*a2) + CB*(Dlb.y*a2);
+ 
+ if( whatd[op_id])
+  {
+    RN_ f0(val('.',0,0)); 
+    RN_ f1(val('.',1,0)); 
+    
+    f0[0] = Va.x;
+    f1[0] = Va.y;
+    
+    f0[1] = Vb.x;
+    f1[1] = Vb.y;
+    
+    f0[2] = Vc.x;
+    f1[2] = Vc.y;
+  }
+ // ----------------
+ if( whatd[op_dx])
+   {
+     val(0,0,1) =  Va_x.x;  
+     val(0,1,1) =  Va_x.y;  
+     
+     val(1,0,1) =  Vb_x.x;  
+     val(1,1,1) =  Vb_x.y;  
+     
+     val(2,0,1) =  Vc_x.x;  
+     val(2,1,1) =  Vc_x.y;
+   }
+ 
+ if( whatd[op_dy])
+   {
+     val(0,0,2) =  Va_y.x;  
+     val(0,1,2) =  Va_y.y;  
+
+     val(1,0,2) =  Vb_y.x;  
+     val(1,1,2) =  Vb_y.y;  
+     
+  val(2,0,2) =  Vc_y.x;  
+  val(2,1,2) =  Vc_y.y;  
+   }
+ 
+}
+
+void TypeOfFE_RTmodif::Pi_h_alpha(const baseFElement & K,KN_<double> & v) const 
+{
+  const Triangle & T(K.T);
+
+   for (int i=0,k=0;i<3;i++)
+     {  
+        R2 E(T.Edge(i));
+        R signe = &T[ (i+1)%3] < &T[ (i+2)%3] ? 1.0 : -1.0 ;
+        v[k++]= signe*E.y;
+        v[k++]=-signe*E.x;
+     }   
+}
+
+
+// ---------------------
+class TypeOfFE_P0 : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+
+   TypeOfFE_P0(): TypeOfFE(0,0,1,1,Data,1,1,1,1,Pi_h_coef){
+     pij_alpha[0]=IPJ(0,0,0);
+     P_Pi_h[0]=R2(1./3.,1./3.);
+     }
+   void FB(const bool * watdd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+
+};
+
+//                     on what     nu df on node node of df    
+  int TypeOfFE_P0::Data[]={6, 0, 0, 0 , 0 ,0, 0, 1 };
+double TypeOfFE_P0::Pi_h_coef[]={1.0};
+
+
+void TypeOfFE_P0::FB(const bool* whatd,const Mesh & ,const Triangle & K,const R2 & PHat,RNMK_ & val) const
+{ //  
+  //  const Triangle & K(FE.T);
+  R2 P(K(PHat));
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  //R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  throwassert(val.N() >=1);
+  throwassert(val.M()==1 );
+  // throwassert(val.K()==3 );
+  val=0;
+  if ( whatd[op_id])
+    val(0,0,0) =1;
+}
+
+// ------ P1 non conforme --------
+class TypeOfFE_P1ncLagrange : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+  TypeOfFE_P1ncLagrange(): TypeOfFE(0,1,0,1,Data,1,1,3,3,Pi_h_coef)
+  {
+    const R2 Pt[] = { R2(0.5,0.5), R2(0.0,0.5), R2(0.5,0.0) };
+    for (int i=0;i<NbDoF;i++) {
+      pij_alpha[i]= IPJ(i,i,0);
+      P_Pi_h[i]=Pt[i]; }
+  }
+
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+
+} ;
+    
+//                     on what     nu df on node node of df    
+  int TypeOfFE_P1ncLagrange::Data[]={3,4,5,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0, 0,3};
+double TypeOfFE_P1ncLagrange::Pi_h_coef[]={1.,1.,1.};
+
+
+class TypeOfFE_ConsEdge : public  TypeOfFE { public:  
+  static int Data[];
+    static double Pi_h_coef[];
+
+   TypeOfFE_ConsEdge(): TypeOfFE(0,1,0,1,Data,3,1,3,3,Pi_h_coef)
+    { const R2 Pt[] = { R2(0.5,0.5), R2(0.0,0.5), R2(0.5,0.0) };
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+
+   void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  
+} ;
+//                     on what     nu df on node node of df    
+  int TypeOfFE_ConsEdge::Data[]={3,4,5,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0, 0,3};
+double TypeOfFE_ConsEdge::Pi_h_coef[]={1.,1.,1.};
+void TypeOfFE_ConsEdge::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+  
+  val=0; 
+  if (whatd[op_id])
+   {
+     
+     RN_ f0(val('.',0,0)); 
+     //      
+    f0[0] =  double(l0 <= min(l1,l2) ); // arete  
+    f0[1] =  double(l1 <= min(l0,l2) );
+    f0[2] =  double(l2 <= min(l0,l1) );
+  }
+
+}
+/*    
+class TypeOfFE_P1Edge : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+	
+  TypeOfFE_P1Edge(): TypeOfFE(0,2,0,1,Data,3,1,12,6,Pi_h_coef)
+    {  R2 Pt[6] ;
+	
+	int kk=0;
+	for(int i=0;i<3;++i)
+	  for(int j=0;i<QF_GaussLegendre2.n;++j)
+	  { R2 A(TriangleHat[VerticesOfTriangularEdge[i][0]]);
+	    R2 B(TriangleHat[VerticesOfTriangularEdge[i][1]]);
+	     Pt[k++]=A*(QF_GaussLegendre2[j].x)+ B*(1-QF_GaussLegendre2[j].x)
+	  }
+	      
+        int other[6]= { 1,0, 3,2,5,4 };
+	k=0;
+	  for (int i=0;i<NbDoF;i++) {
+	    pij_alpha[i]= IPJ(i,i,0);
+	    if(other[i]>=0)
+		pij_alpha[kk++]= IPJ(i,other[i],0);
+	       P_Pi_h[i]=Pt[i]; }
+	}
+	
+	void FB(const bool * whatd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+	
+    } ;
+    //                     on what     nu df on node node of df    
+    int TypeOfFE_ConsEdge::Data[]={3,4,5,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0, 0,3};
+    double TypeOfFE_ConsEdge::Pi_h_coef[]={1.,1.,1.};
+    void TypeOfFE_ConsEdge::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+    {
+	//  const Triangle & K(FE.T);
+	R2 A(K[0]), B(K[1]),C(K[2]);
+	R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+	
+	if (val.N() <3) 
+	    throwassert(val.N() >=3);
+	throwassert(val.M()==1 );
+	
+	val=0; 
+	if (whatd[op_id])
+	{
+	    
+	    RN_ f0(val('.',0,0)); 
+	    //      
+	    f0[0] =  double(l0 <= min(l1,l2) ); // arete  
+	    f0[1] =  double(l1 <= min(l0,l2) );
+	    f0[2] =  double(l2 <= min(l0,l1) );
+	}
+	
+    }
+    
+*/
+    
+void TypeOfFE_P1ncLagrange::FB(const bool * whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  //  l1(  cshrink1*(cshrink*((1,0)-G)+G)-G)+G  = 1
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  
+  if (val.N() <3) 
+    throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+  // throwassert(val.K()==3 );
+  
+  val=0; 
+  if (whatd[op_id])
+   {
+  RN_ f0(val('.',0,0)); 
+  f0[0] = 1-l0*2;  
+  f0[1] = 1-l1*2;
+  f0[2] = 1-l2*2;
+  }
+  if (whatd[op_dx] || whatd[op_dy] )
+   {
+    R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+    if (whatd[op_dx]) 
+      {
+      RN_ f0x(val('.',0,op_dx)); 
+      f0x[0] = -Dl0.x*2;
+      f0x[1] = -Dl1.x*2;
+      f0x[2] = -Dl2.x*2;
+      }
+    if (whatd[op_dy]) 
+     {  
+     RN_ f0y(val('.',0,op_dy)); 
+     f0y[0] = -Dl0.y*2;
+     f0y[1] = -Dl1.y*2;
+     f0y[2] = -Dl2.y*2;
+     }
+   }
+}
+
+// The RT orthogonal FE
+
+class TypeOfFE_RTortho : public  TypeOfFE { public:  
+  static int Data[];
+   TypeOfFE_RTortho(): TypeOfFE(0,1,0,2,Data,1,1,6,3) 
+     {const R2 Pt[] = { R2(0.5,0.5), R2(0.0,0.5), R2(0.5,0.0) };
+      for (int p=0,kk=0;p<3;p++)
+       { P_Pi_h[p]=Pt[p];   
+        for (int j=0;j<2;j++) 
+        pij_alpha[kk++]= IPJ(p,p,j);
+       }}
+
+   void FB(const bool * watdd, const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const ;
+} ; 
+//                     on what     nu df on node node of df    
+  int TypeOfFE_RTortho::Data[]={3,4,5,       0,0,0,       0,1,2,       0,0,0,        0,1,2,   0,0, 0,0, 3,3};
+
+
+
+ void TypeOfFE_RTortho::FB(const bool *whatd,const Mesh & Th,const Triangle & K,const R2 & PHat,RNMK_ & val) const
+{ //  
+//  const Triangle & K(FE.T);
+  R2 P(K(PHat));
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  //R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+ // R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==2 );
+//  throwassert(val.K()==3 );
+  val=0;  
+  R a=1./(2*K.area);
+  R a0=   K.EdgeOrientation(0) * a ;
+  R a1=   K.EdgeOrientation(1) * a  ;
+  R a2=   K.EdgeOrientation(2) * a ;
+ // if (Th(K)< 2) cout << Th(K) << " " <<  A << " "  << B << " " << C << "; " <<  a0 << " " << a1 << " "<< a2 << endl;;
+
+  //  ------------
+  if (whatd[op_id])
+   {
+   assert(val.K()>op_id);
+  RN_ f0(val('.',0,0)); 
+  RN_ f1(val('.',1,0)); 
+  f1[0] =  (P.x-A.x)*a0;
+  f0[0] = -(P.y-A.y)*a0;
+  
+  f1[1] =  (P.x-B.x)*a1;
+  f0[1] = -(P.y-B.y)*a1;
+  
+  f1[2] =  (P.x-C.x)*a2;
+  f0[2] = -(P.y-C.y)*a2;
+  }
+  // ----------------
+    if (whatd[op_dx])
+   {
+   assert(val.K()>op_dx);
+   val(0,1,op_dx) =  a0;  
+   val(1,1,op_dx) =  a1;  
+   val(2,1,op_dx) =  a2; 
+  } 
+    if (whatd[op_dy])
+   {
+   assert(val.K()>op_dy);
+    val(0,0,op_dy) =  -a0;  
+    val(1,0,op_dy) =  -a1;  
+    val(2,0,op_dy) =  -a2;  
+  }
+}
+
+void TypeOfFE_RTortho::Pi_h_alpha(const baseFElement & K,KN_<double> & v) const 
+{
+  const Triangle & T(K.T);
+
+   for (int i=0,k=0;i<3;i++)
+     {  
+        R2 E(T.Edge(i));
+        R signe = &T[ (i+1)%3] < &T[ (i+2)%3] ? 1.0 : -1.0 ;
+        v[k++]= signe*E.x;
+        v[k++]= signe*E.y;
+     }   
+}
+// -------------------
+// ttdc finite element fully discontinue. 
+// -------------------
+class TypeOfFE_P1ttdc : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+    static const R2 G;
+    static const R cshrink;
+    static const R cshrink1;
+    //  (1 -1/3)*
+    
+    static R2 Shrink(const R2& P){ return (P-G)*cshrink+G;}
+    static R2 Shrink1(const R2& P){ return (P-G)*cshrink1+G;}
+    
+   TypeOfFE_P1ttdc(): TypeOfFE(0,0,3,1,Data,1,1,3,3,Pi_h_coef)
+    { const R2 Pt[] = { Shrink(R2(0,0)), Shrink(R2(1,0)), Shrink(R2(0,1)) }; 
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i];
+       // cout << Pt[i] << " " ;
+      }
+      //	cout <<" cshrink: " << cshrink << " cshrink1 : "<< cshrink1 <<endl;
+     }
+
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   
+  
+  virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
+   
+} ;
+    const R2 TypeOfFE_P1ttdc::G(1./3.,1./3.);   
+    const R TypeOfFE_P1ttdc::cshrink=1-1e-2;   
+    const R TypeOfFE_P1ttdc::cshrink1=1./TypeOfFE_P1ttdc::cshrink;   
+    
+class TypeOfFE_P2ttdc : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+    static const R2 G;
+    static const R cshrink;
+    static const R cshrink1;
+    
+    static R2 Shrink(const R2& P){ return (P-G)*cshrink+G;}
+    static R2 Shrink1(const R2& P){ return (P-G)*cshrink1+G;}
+    
+   TypeOfFE_P2ttdc(): TypeOfFE(0,0,6,1,Data,3,1,6,6,Pi_h_coef)
+    { const R2 Pt[] = { Shrink(R2(0,0)), Shrink(R2(1,0)), Shrink(R2(0,1)),
+	                Shrink(R2(0.5,0.5)),Shrink(R2(0,0.5)),Shrink(R2(0.5,0)) };
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+   
+  
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ 
+ 
+} ;
+//                          on what   nu df on node  node of df    
+  int TypeOfFE_P1ttdc::Data[]={6,6,6,       0,1,2,       0,0,0,       0,0,0,         0,1,2,       0, 0,3};
+  int TypeOfFE_P2ttdc::Data[]={6,6,6,6,6,6, 0,1,2,3,4,5, 0,0,0,0,0,0,  0,0,0,0,0,0,  0,1,2,3,4,5, 0, 0,6};
+double TypeOfFE_P1ttdc::Pi_h_coef[]={1.,1.,1.};
+double TypeOfFE_P2ttdc::Pi_h_coef[]={1.,1.,1.,1.,1.,1.};
+    
+const R2 TypeOfFE_P2ttdc::G(1./3.,1./3.);   
+const R TypeOfFE_P2ttdc::cshrink=1-1e-2;   
+const R TypeOfFE_P2ttdc::cshrink1=1./TypeOfFE_P2ttdc::cshrink;   
+    
+ 
+R TypeOfFE_P1ttdc::operator()(const FElement & K,const  R2 & P1Hat,const KN_<R> & u,int componante,int op) const 
+{ 
+
+  R2 PHat=Shrink1(P1Hat);  
+  R u0(u(K(0))), u1(u(K(1))), u2(u(K(2)));
+  R r=0;
+  if (op==0)
+    {
+      R l0=1-PHat.x-PHat.y,l1=PHat.x,l2=PHat.y; 
+      r = u0*l0+u1*l1+l2*u2;
+    }
+   else
+    { 
+       const Triangle & T=K.T;
+       R2 D0 = T.H(0)*cshrink1 , D1 = T.H(1)*cshrink1  , D2 = T.H(2)*cshrink1 ;
+       if (op==1)
+         r =  D0.x*u0 + D1.x*u1 + D2.x*u2 ;
+        else 
+         r =  D0.y*u0 + D1.y*u1 + D2.y*u2 ;
+    }
+ //  cout << r << "\t";
+   return r;
+}
+
+void TypeOfFE_P1ttdc::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P1,RNMK_ & val) const
+{
+  R2 P=Shrink1(P1);  
+   
+  //  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  
+  if (val.N() <3) 
+    throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+  //  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd[op_id]) 
+   {
+     f0[0] = l0;
+    f0[1] = l1;
+    f0[2] = l2;}
+ if (whatd[op_dx] || whatd[op_dy])
+  {
+  R2 Dl0(K.H(0)*cshrink1), Dl1(K.H(1)*cshrink1), Dl2(K.H(2)*cshrink1);
+  
+  if (whatd[op_dx]) 
+   {
+    RN_ f0x(val('.',0,op_dx)); 
+   f0x[0] = Dl0.x;
+   f0x[1] = Dl1.x;
+   f0x[2] = Dl2.x;
+  }
+  
+  if (whatd[op_dy]) {
+    RN_ f0y(val('.',0,op_dy)); 
+   f0y[0] = Dl0.y;
+   f0y[1] = Dl1.y;
+   f0y[2] = Dl2.y;
+  }
+  }
+}
+
+
+
+ void TypeOfFE_P2ttdc::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P1,RNMK_ & val) const
+{
+    R2 P=Shrink1(P1);  
+   
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+//  throwassert(FE.N == 1);  
+  throwassert( val.N()>=6);
+  throwassert(val.M()==1);
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+// --     
+ if (whatd[op_id])
+  {
+   RN_ f0(val('.',0,op_id)); 
+  f0[0] = l0*(2*l0-1);
+  f0[1] = l1*(2*l1-1);
+  f0[2] = l2*(2*l2-1);
+  f0[3] = 4*l1*l2; // oppose au sommet 0
+  f0[4] = 4*l0*l2; // oppose au sommet 1
+  f0[5] = 4*l1*l0; // oppose au sommet 3
+  }
+ if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+ {
+   R2 Dl0(K.H(0)*cshrink1), Dl1(K.H(1)*cshrink1), Dl2(K.H(2)*cshrink1);
+  if (whatd[op_dx])
+  {
+    RN_ f0x(val('.',0,op_dx)); 
+  f0x[0] = Dl0.x*l4_0;
+  f0x[1] = Dl1.x*l4_1;
+  f0x[2] = Dl2.x*l4_2;
+  f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
+  f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
+  f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
+  }
+
+ if (whatd[op_dy])
+  {  
+    RN_ f0y(val('.',0,op_dy)); 
+  f0y[0] = Dl0.y*l4_0;
+  f0y[1] = Dl1.y*l4_1;
+  f0y[2] = Dl2.y*l4_2;
+  f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
+  f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
+  f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
+  }
+ 
+ if (whatd[op_dxx])
+  {  
+    RN_ fxx(val('.',0,op_dxx)); 
+
+    fxx[0] = 4*Dl0.x*Dl0.x;
+    fxx[1] = 4*Dl1.x*Dl1.x;
+    fxx[2] = 4*Dl2.x*Dl2.x;
+    fxx[3] =  8*Dl1.x*Dl2.x;
+    fxx[4] =  8*Dl0.x*Dl2.x;
+    fxx[5] =  8*Dl0.x*Dl1.x;
+  }
+
+ if (whatd[op_dyy])
+  {  
+    RN_ fyy(val('.',0,op_dyy)); 
+    fyy[0] = 4*Dl0.y*Dl0.y;
+    fyy[1] = 4*Dl1.y*Dl1.y;
+    fyy[2] = 4*Dl2.y*Dl2.y;
+    fyy[3] =  8*Dl1.y*Dl2.y;
+    fyy[4] =  8*Dl0.y*Dl2.y;
+    fyy[5] =  8*Dl0.y*Dl1.y;
+  }
+ if (whatd[op_dxy])
+  {  
+    assert(val.K()>op_dxy);
+    RN_ fxy(val('.',0,op_dxy)); 
+  
+    fxy[0] = 4*Dl0.x*Dl0.y;
+    fxy[1] = 4*Dl1.x*Dl1.y;
+    fxy[2] = 4*Dl2.x*Dl2.y;
+    fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+    fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+    fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+  }
+ 
+ }
+ 
+}
+
+ 
+//
+// end ttdc
+// ------------------
+
+static TypeOfFE_RTortho The_TypeOfFE_RTortho;
+static TypeOfFE_RT The_TypeOfFE_RT;
+static TypeOfFE_P0 The_TypeOfFE_P0;
+static TypeOfFE_P1ttdc The_TypeOfFE_P1ttdc;
+static TypeOfFE_P2ttdc The_TypeOfFE_P2ttdc;
+static TypeOfFE_RTmodif The_TypeOfFE_RTmodif;
+static TypeOfFE_P1ncLagrange The_TypeOfFE_P1nc;
+static TypeOfFE_ConsEdge The_TypeOfFE_ConsEdge; // add FH 
+TypeOfFE  & RTLagrangeOrtho(The_TypeOfFE_RTortho);
+TypeOfFE  & RTLagrange(The_TypeOfFE_RT);
+TypeOfFE  & RTmodifLagrange(The_TypeOfFE_RTmodif);
+TypeOfFE  & P0Lagrange(The_TypeOfFE_P0);
+TypeOfFE  & P1ncLagrange(The_TypeOfFE_P1nc);
+TypeOfFE  & P1ttdc(The_TypeOfFE_P1ttdc);
+TypeOfFE  & P2ttdc(The_TypeOfFE_P2ttdc);
+TypeOfFE  & P0edge(The_TypeOfFE_ConsEdge);
+
+}
diff --git a/src/femlib/FESpace-v0.cpp b/src/femlib/FESpace-v0.cpp
new file mode 100644
index 0000000..1777630
--- /dev/null
+++ b/src/femlib/FESpace-v0.cpp
@@ -0,0 +1,1723 @@
+#include <cmath>
+#include <cstdlib>
+#include "error.hpp"
+#include <iostream>
+#include <fstream>
+#include <map>
+#include "rgraph.hpp"
+using namespace std;  
+
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpace.hpp"
+
+namespace  Fem2D {
+
+ int  Make(const TypeOfFE ** t,int k,KN<R2> & P,KN<int> & I)
+ {
+   typedef  TypeOfFE::IPJ IPJ;
+
+   int n=0,nn=0;
+
+   for (int i=0;i<k;i++)
+    {
+     const KN<R2> p(t[i]->P_Pi_h);
+     for (int j=0;j<p.N();j++,nn++)
+     {
+       P[n]=p[j]; // par defaut un nouveau => ajout
+       I[nn]=n++;       
+       for (int l=0;l<n-1;l++)
+        {
+          R2 QP(p[j],P[l]);
+          if ( (QP,QP) < 1.0e-12 ) { 
+            I[nn]=l;
+            n--; // on a retrouver =>  detruit
+            break;}
+        }
+       
+     }
+    }
+   return n; // nombre de point commun
+ }
+ 
+ KN<TypeOfFE::IPJ > Makepij_alpha(const TypeOfFE ** t,int k)
+ {
+ // Attention les df est numerote de facon croissant 
+ // en faisant une boucle sur les TypeOfFE
+ // comme dans la class TypeOfFESum
+  typedef TypeOfFE::IPJ IPJ;
+  int n=0,m=0;
+  for (int i=0;i< k;i++) {
+    n += t[i]->pij_alpha.N();
+    m += t[i]->P_Pi_h.N();
+    }
+  KN<TypeOfFE::IPJ > ij(n);
+  KN<int> I(m);
+  KN<R2> P(m);
+  Make(t,k,P,I);
+  int p0=0,i0=0,N0=0,nn=0;
+  for (int i=0;i< k;i++) {
+    const KN<IPJ > p(t[i]->pij_alpha);
+     for (int j=0;j<p.N();j++,nn++)  
+      {
+        ij[nn].i= p[j].i+i0; //  comme dans TypeOfFESum
+        ij[nn].j= N0+ p[j].j;
+        ij[nn].p= I[p[j].p+p0];
+       
+      //   cout << nn << "Makepij_alpha: " << ij[nn].i << " " << ij[nn].p << " " << ij[nn].j << endl;
+        
+      }
+    i0+=t[i]->NbDoF;
+    p0+=t[i]->P_Pi_h.N();
+    N0+=t[i]->N;}
+  return ij; 
+ }
+ KN<R2 > MakeP_Pi_h(const TypeOfFE **t,int k)
+ {
+  int np=0;
+  for (int i=0;i< k;i++) 
+    np += t[i]->P_Pi_h.N();
+    
+  KN< R2 >  yy(np);
+  KN<int> zz(np);
+  int kk=Make(t,k,yy,zz);
+ // cout << " MakeP_Pi_h: " << kk << " from " << np << endl; 
+  return yy(SubArray(kk));
+ 
+ }
+
+ListOfTFE * ListOfTFE::all ; // list of all object of this type 
+
+ListOfTFE::ListOfTFE (const char * n,TypeOfFE *t) : name(n),tfe(t) 
+{
+  if(!t)
+  assert(t);
+  static int count=0;
+  if (count++==0) 
+    all=0; // init of all in dependant of the ordre of the objet file   
+  next=all;
+  all=this;
+}
+
+const TypeOfFE ** Make(const FESpace **l,int k) {
+  const TypeOfFE** p=new const TypeOfFE*[k];
+  for (int i=0;i<k;i++)
+    p[i]=l[i]->TFE[0];
+  return p;
+}
+const TypeOfFE ** Make(const TypeOfFE **l,int k) {
+  const TypeOfFE** p=new const TypeOfFE*[k];
+  for (int i=0;i<k;i++)
+    p[i]=l[i];
+  return p;
+}
+
+  
+bool Same(const FESpace **l,int k)
+{
+   for (int i=1;i<k;i++)
+    if (l[0] != l[i] ) return false;
+   return true;
+}   
+
+class FESumConstruct { protected:
+   const TypeOfFE ** teb;
+   const int k;
+   int nbn; // nb of node 
+   int  *  data;
+   int  * const NN; //  NN[ i:i+1[ dimension de l'element i
+   int  * const DF; // DF[i:i+1[  df associe a l'element i
+   int  * const comp; //  
+   FESumConstruct(int kk,const TypeOfFE **t);   
+   virtual ~FESumConstruct(){
+     delete [] DF;
+     delete [] NN;
+     delete [] comp;
+     delete [] data;}   
+};
+
+  void FElement::Pi_h(RN_ val,InterpolFunction f,R *v, void * arg=0) const {
+   // routine: a  tester FH.
+    FElement::aIPJ ipj(Pi_h_ipj()); 
+    FElement::aR2  PtHat(Pi_h_R2()); 
+    KN<R>   Aipj(ipj.N());
+    KNM<R>  Vp(N,PtHat.N());
+        
+     Pi_h(Aipj);
+     for (int p=0;p<PtHat.N();p++)
+          { 
+            f(v,T(PtHat[p]),*this,T.lab,PtHat[p],arg);
+            KN_<double> Vpp(Vp('.',p));
+            for (int j=0;j<N;j++)          
+               Vpp[j]=v[j];              
+           }
+           
+         for (int i=0;i<Aipj.N();i++)
+          { 
+           const FElement::IPJ &ipj_i(ipj[i]);
+           val[ipj_i.i] += Aipj[i]*Vp(ipj_i.j,ipj_i.p);           
+          }
+ }
+
+class TypeOfFESum: public FESumConstruct, public  TypeOfFE { public:
+   TypeOfFESum(const FESpace **t,int kk): 
+     FESumConstruct(kk,Make(t,kk)),TypeOfFE(teb,kk,data) {}
+       TypeOfFESum(const TypeOfFE **t,int kk): 
+     FESumConstruct(kk,Make(t,kk)),TypeOfFE(teb,kk,data) {}
+
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+//   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+//  void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void * arg ) const; 
+   virtual void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+    { 
+      for (int i=0,k0=0;i<k;i++) {
+          int n=teb[i]->NbDoF;
+          KN_<R> sv(v(SubArray(n,k0)));
+          teb[i]->Pi_h_alpha(K,sv);
+          k0+= n;}
+    }
+   ~TypeOfFESum(){  delete []  teb;}
+} ;
+
+class FEProduitConstruct { protected:
+   const TypeOfFE & teb;
+   int k;
+   int * data;
+   FEProduitConstruct(int kk,const TypeOfFE &t)  ;   
+   ~FEProduitConstruct(){delete [] data;}   
+};
+
+class TypeOfFEProduit: protected FEProduitConstruct, public  TypeOfFE { public:  
+   TypeOfFEProduit(int kk,const TypeOfFE &t): 
+     FEProduitConstruct(kk,t),TypeOfFE(t,kk,data)  {}
+     
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+//   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+//   void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void * arg ) const;  
+   virtual void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+    { int nbof=teb.NbDoF;
+      for (int i=0,k0=0;i<k;i++,k0+=nbof)
+        {          
+          KN_<R> sv(v(SubArray(nbof,k0)));
+          teb.Pi_h_alpha(K,sv);
+        }
+    }
+ 
+   ~TypeOfFEProduit(){}
+} ;
+
+FEProduitConstruct::FEProduitConstruct(int kk,const TypeOfFE &t)
+ :k(kk),teb(t) 
+{  
+  int m= teb.NbDoF;
+  KN<int> nn(teb.NbNode);
+  nn=0; // nb de dl par noeud 
+  for (int i=0;i<m;i++)
+    nn[teb.NodeOfDF[i]]++;   
+    
+  int n= m*kk;
+  int N= teb.N*kk;
+  data = new int [n*5+N];
+  int c=0;
+  
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++)
+    data[c++] = teb.DFOnWhat[i];
+  
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) // num of df on node  for the df = j 
+      data[c++] = teb.DFOfNode[i]+j*nn[teb.NodeOfDF[i]];
+    
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) 
+    data[c++] = teb.NodeOfDF[i]; //  node of df
+
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) 
+    data[c++] = j; //  node from of FE
+    
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) 
+    data[c++] = i; //  node from of df in FE
+    
+   for (int j=0;j<kk;j++) 
+    for (int i=0;i<teb.N;i++) 
+      data[c++]= teb.dim_which_sub_fem[i] + teb.nb_sub_fem*j ;
+}
+
+FESumConstruct::FESumConstruct(int kk,const TypeOfFE **t)
+ :k(kk),teb(t),NN(new int[kk+1]),DF(new int[kk+1]) , comp(new int[kk])
+{  
+   map<const TypeOfFE *,int> m;
+   int i=k,j;    
+   while(i--) // on va a l'envert pour avoir comp[i] <=i 
+      m[teb[i]]=i;
+    // l'ordre comp est important comp est croissant  mais pas de pb. 
+   i=k;    
+   while(i--) 
+     comp[i]=m[teb[i]]; //  comp[i] <=i
+        
+  // reservatition des intervalles en espaces
+  int n=0,N=0;
+   for ( j=0;j<kk;j++)
+     {NN[j]=N;N+=teb[j]->N;}
+   NN[kk] = N;
+ //  reservation des interval en df   
+   n=0;
+   for ( j=0;j<kk;j++)
+    { DF[j]=n;n+=teb[j]->NbDoF;}
+   DF[kk] = n;
+//  n = nb de DF total   
+//  N the fem is in R^N 
+   
+  data = new int [n*5 + N];
+  int c=0;
+  int ki= 0; 
+// recherche des noeuds
+   KN<int> w(7),nn(7);
+   w=0;
+   nn=0; 
+   
+         
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+         nn[teb[j]->DFOnWhat[i]]++;
+   nbn=0;      
+   for( j=0;j<7;j++)
+     if (nn[j]) nn[j]=nbn++;
+     else nn[j]=-1;
+   KN<int> dln(7);
+   dln=0;
+  // nn donne numero de noeud sur what            
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = teb[j]->DFOnWhat[i];
+    
+   for ( j=0;j<kk;j++)
+    {
+     int  cc=c;
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = teb[j]->DFOfNode[i]+dln[teb[j]->DFOnWhat[i]];
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       dln[teb[j]->DFOnWhat[i]]=Max(dln[teb[j]->DFOnWhat[i]],data[cc++]+1);      
+    }
+        
+       
+   for ( j=0;j<kk;j++)
+    { 
+     //  w renumerotation des noeuds 
+     //  Ok si un noeud par what 
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = nn[teb[j]->DFOnWhat[i]];
+    }
+    
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = j; //  node from of FE
+
+    
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = i; //  node from of df in FE
+       
+   int xx=0;
+   for (j=0;j<kk;j++)
+     { 
+      int xxx=xx;
+      for (i=0;i<teb[j]->N;i++)
+       { 
+         data[c] = teb[j]->dim_which_sub_fem[i]+xx;
+         xxx=Max(xxx,data[c]+1);
+         c++;
+       }
+       xx=xxx;
+     }
+  
+  throwassert(c== 5*n+N);      
+/*  int cc=0;
+   cout << " Data : " << endl;
+  for ( i=0;i<5;i++)    {
+    for (j=0;j<n;j++)
+      cout << " " << data[cc++];
+     cout << endl;}
+ cout << " which " ;
+ for (i=0;i<N;i++)
+   cout << " " << data[cc++];
+  cout << endl;*/
+}
+
+class TypeOfFE_P1Lagrange : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+   TypeOfFE_P1Lagrange(): TypeOfFE(1,0,0,1,Data,1,1,3,3,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1) }; 
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   
+//   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
+   
+} ;
+
+///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// NEW ////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class TypeOfFE_P1Bubble : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+   TypeOfFE_P1Bubble(): TypeOfFE(1,0,1,1,Data,1,1,4,4,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1), R2(1./3.,1./3.) }; 
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   
+//   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ //  void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+  //virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
+   
+} ;
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class TypeOfFE_P2Lagrange : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+  
+   TypeOfFE_P2Lagrange(): TypeOfFE(1,1,0,1,Data,3,1,6,6,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0) };
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+   
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ //  void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+} ;
+
+int TypeOfFE_P1Lagrange::Data[]={0,1,2,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0};
+int TypeOfFE_P1Bubble::Data[]={0,1,2,6,     0,0,0,0,     0,1,2,3,     0,0,0,0,        0,1,2,3,     0};
+int TypeOfFE_P2Lagrange::Data[]={0,1,2,3,4,5, 0,0,0,0,0,0, 0,1,2,3,4,5, 0,0,0,0,0,0,  0,1,2,3,4,5, 0};
+double TypeOfFE_P1Lagrange::Pi_h_coef[]={1.,1.,1.};
+double TypeOfFE_P1Bubble::Pi_h_coef[]={1.,1.,1.,1.};
+double TypeOfFE_P2Lagrange::Pi_h_coef[]={1.,1.,1.,1.,1.,1.};
+
+inline void dump(char *m,int n,int * p)
+{
+  cout << m ;
+  for (int i=0;i<n;i++) cout << " " << p[i] ;
+  cout << endl;
+}
+
+
+
+ConstructDataFElement::~ConstructDataFElement()
+{
+  if(*counter==0) 
+   {
+    delete [] NodesOfElement;
+    delete []  FirstNodeOfElement;
+    delete [] FirstDfOfNode;
+  }
+ else counter--;
+}
+
+ ConstructDataFElement::ConstructDataFElement(const ConstructDataFElement * t,int k)
+  :thecounter(0), 
+   counter(t->counter),
+   MaxNbNodePerElement(t->MaxNbNodePerElement),
+   MaxNbDFPerElement(t->MaxNbDFPerElement*k),
+   NodesOfElement(t->NodesOfElement),
+   FirstNodeOfElement(t->FirstNodeOfElement),
+   FirstDfOfNode(0),
+   NbOfElements(t->NbOfElements),
+   NbOfDF(t->NbOfDF*k),
+   NbOfNode(t->NbOfNode),
+   Nproduit(t->Nproduit*k)
+ {
+   throwassert(t==0 || t->FirstDfOfNode==0);
+   *counter++;
+ }
+
+ConstructDataFElement::ConstructDataFElement (const Mesh &Th,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,const TypeOfMortar *tm,
+int nbdfv,const int *ndfv,int nbdfe,const int *ndfe)
+: counter(&thecounter),thecounter(0) 
+{ 
+ Make(Th,NbDfOnSommet,NbDfOnEdge,NbDfOnElement, tm,nbdfv,ndfv,nbdfe,ndfe);
+}
+
+ConstructDataFElement::ConstructDataFElement(const FESpace ** l,int k) 
+: thecounter(0),counter(&thecounter) 
+{
+ int NbDfOnSommet=0;
+ int NbDfOnEdge=0;
+ int NbDfOnElement=0;
+ const Mesh & Th(l[0]->Th);
+ for  (int i=0;i<k;i++)
+   {
+     NbDfOnSommet += l[i]->TFE[0]->NbDfOnVertex;
+     NbDfOnEdge += l[i]->TFE[0]->NbDfOnEdge;
+     NbDfOnElement += l[i]->TFE[0]->NbDfOnElement;
+     throwassert( &Th== &l[i]->Th); 
+     throwassert( l[i]->TFE.constant());
+   }
+   
+ Make(Th,NbDfOnSommet,NbDfOnEdge,NbDfOnElement,0);   
+}
+ 
+
+void ConstructDataFElement::Make(const Mesh &Th,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,const TypeOfMortar *tm,
+int nb_dfv,const int *ndfv,int nb_dfe,const int *ndfe)   
+{
+  *counter=0;
+  Nproduit =1;
+  int ndf=0,samendf=1;
+  
+  int nbdfe=3*NbDfOnSommet+3*NbDfOnEdge+NbDfOnElement;
+  int nbne = 0;
+  int nn=0;  
+  int firstmul=0;
+  throwassert( tm || Th.NbMortars==0);
+  NbOfElements = Th.nt; //  by default
+  // if mortars 
+  //
+  int NbOfNodeL=0;
+  NbOfElements += Th.NbMortars;  
+  FirstDfOfNode =0;
+  FirstNodeOfElement=0;
+  MaxNbDFPerElement=3*NbDfOnSommet+3*NbDfOnEdge+NbDfOnElement;
+
+  int ks=0,ke=0,kt=0;
+  if(NbDfOnSommet) { nbne+=3;
+     ks=1;
+     ndf=NbDfOnSommet;}
+
+  if(NbDfOnEdge) {  nbne+=3;
+     ke=1;
+     samendf &= !ndf || ndf == NbDfOnEdge;
+     ndf=NbDfOnEdge;}
+     
+  if(NbDfOnElement) {  nbne+=1;
+     kt=1;
+     samendf &= !ndf || ndf == NbDfOnElement;
+     ndf=NbDfOnElement;}
+
+  int NbDFonNode[7],NodeIsOn[7];
+   {
+     int j=0,k=0;
+     if(ks) { NbDFonNode[j++]=NbDfOnSommet; NbDFonNode[j++]=NbDfOnSommet; NbDFonNode[j++]=NbDfOnSommet;}
+     if(ke) { NbDFonNode[j++]=NbDfOnEdge; NbDFonNode[j++]=NbDfOnEdge; NbDFonNode[j++]=NbDfOnEdge;}
+     if(kt) { NbDFonNode[j++]=NbDfOnElement;}
+
+     if (ks) {NodeIsOn[k++]=0;NodeIsOn[k++]=1;NodeIsOn[k++]=2;}
+     if (ke) {NodeIsOn[k++]=3;NodeIsOn[k++]=4;NodeIsOn[k++]=5;}
+     if (kt) {NodeIsOn[k++]=6;}
+     
+     throwassert(j == nbne);
+  }
+     
+    MaxNbNodePerElement=nbne;
+
+//  
+   if ( ks && (!ke && ! kt) && (ndfv==0 && ndfe==0))
+     {nn=Th.nv;
+      NodesOfElement=0;
+      }
+   else {
+//    constuction du tableau  NodesOfElement  bofbof 
+
+//     computation of the length lne of array NodesOfElement        
+       int lne=  Th.nt*nbne;
+       if (Th.NbMortars)
+        {
+          samendf= false;
+          NbOfNodeL=Th.NbMortars;
+          throwassert(tm);
+          FirstNodeOfElement = new int[NbOfElements+1];
+          int k=0,kk=0;          
+          for (k=0;k<Th.nt;k++,kk+=nbne)
+            FirstNodeOfElement[k] = kk;
+           
+          for (int im=0;im<Th.NbMortars;im++) // (www) code 
+            {
+             FirstNodeOfElement[k++]=lne;           
+             lne += tm->NbOfNodes(Th,Th.mortars[im]);
+            }
+          FirstNodeOfElement[k++]=lne;           
+        }       
+        
+       NodesOfElement = new int[lne];
+       
+       for (int i=0;i<lne;i++) 
+         NodesOfElement[i]=-1;
+       int i=0;
+       int oe=0; 
+       if(ks) { oe=3;nn=ndfv ? nb_dfv : Th.nv;}
+       
+       if (ke && ndfe) { 
+        for (int be=0;be<Th.neb;be++)
+         {
+          int j,k=Th.BoundaryElement(be,j);
+          int jj=j;
+          int kk=Th.ElementAdj(k,jj);
+          if ( kk >=0 && jj>=0)   
+            NodesOfElement[kk*nbne+oe+jj] = nn + ndfe[be]   ; // adj
+          NodesOfElement[k*nbne+oe+j]   = nn + ndfe[be]   ; // new         
+         }
+         nn += nb_dfe;
+        }
+       for (int k=0;k<Th.nt;k++)
+        {
+          int iold=i;
+          if(ks) {
+            for (int j=0;j<3;j++)
+             NodesOfElement[i++]= ndfv ?  ndfv[Th(k,j)] : Th(k,j) ;
+          }
+          if(ke) {
+            for (int j=0;j<3;j++)
+             if (NodesOfElement[i]<0) {
+               int jj=j;
+               int kk=Th.ElementAdj(k,jj);
+               
+               NodesOfElement[kk*nbne+oe+jj] = nn   ; // adj   
+               NodesOfElement[i++]           = nn++ ; // new
+             }  else i++;
+          }
+          if(kt) 
+             NodesOfElement[i++]= nn++;
+         // cout << k ;
+         // dump(" ",i-iold, NodesOfElement+iold);
+        }
+       // cout << i << " " << Th.nt*nbne << endl;
+        firstmul=nn;
+        if (Th.NbMortars)
+          {  
+            //  construction of the mortars element 
+           int * color= new int [firstmul]; 
+           //  
+           int thecolor=0;
+           for (int j=0;j<firstmul;j++) 
+             color[j]=thecolor;
+             
+           for (int im=0;im<Th.NbMortars;im++)
+            {   
+             int iold=i;         
+             thecolor++; // get a new color
+             // tm->ConstructionOfNode(Th,im,NodesOfElement,FirstNodeOfElement,nn);  
+             Mortar & M(Th.mortars[im]);
+              NodesOfElement[i++] = nn++; // the first node is the lag. mul.
+             int n=M.NbT();
+             for (int kk=0;kk<n;kk++)
+             {
+              int K,e;
+               K=M.T_e(kk,e); 
+               int kb=FirstNodeOfElement[K];
+               int ke=FirstNodeOfElement[K+1];             
+               for (int j=kb,jj=0;j<ke;j++,jj++)
+                if (onWhatIsEdge[e][NodeIsOn[jj]])
+                 { // the node jj is on edge e
+                    int node=NodesOfElement[j];
+                   // cout << "." << jj << " K=" << K <<" "<<e << " n=" << node ;
+                    throwassert(node<firstmul);
+                    if (color[node] != thecolor) //  new node => adding
+                     { 
+                    //   cout << "a, ";
+                       color[node] = thecolor;
+                       NodesOfElement[i++] = node;
+                     }
+                   // else cout << ", ";
+                 }
+               }
+               //cout << endl;
+               
+               //cout << im ;
+               //dump(": ",i-iold, NodesOfElement+iold);
+               throwassert(i==FirstNodeOfElement[im+Th.nt+1]);
+              }
+             delete [] color;
+          } 
+        else
+          throwassert(i==Th.nt*nbne);
+        NbOfNode=nn;
+                
+        
+   }
+  NbOfNode=nn;  
+  int NbOfDFL=0;  
+   if (! samendf) 
+       { throwassert(NodesOfElement);
+         FirstDfOfNode= new int [nn+1];
+         for (int i=0;i<=nn;i++) FirstDfOfNode[i]=-1; 
+         int i=0;
+         //  the classical part (FEM)
+         for (int k=0;k<Th.nt;k++)
+           for (int j=0;j<nbne;j++) // thanks to student
+             FirstDfOfNode[ NodesOfElement[i++]+1]=NbDFonNode[j];
+         //  the mortars parts juste the mulplicator 
+         
+         for (int km=0,k=Th.nt;km<Th.NbMortars;km++,k++) 
+            {  //  the lag. mult. is the first node of the mortar --
+              throwassert(FirstNodeOfElement);
+              //  hack 
+              int fk=FirstNodeOfElement[k];
+              int lk=FirstNodeOfElement[k+1];
+              int ndlmul = tm->NbLagrangeMult(Th,Th.mortars[km]);  //  On node par 
+              int nodemul = NodesOfElement[fk]; // the first node is the lagr. mul.
+              throwassert(FirstDfOfNode[nodemul+1]==-1);      
+              FirstDfOfNode[nodemul+1]= ndlmul;
+              NbOfDFL += ndlmul;
+              int nbdle=0;
+              int nbnm=lk-fk;
+              for (int j=fk;j<lk;j++)
+               nbdle+=FirstDfOfNode[NodesOfElement[j]+1];
+              MaxNbDFPerElement = Max(MaxNbDFPerElement,nbdle);
+            }
+             
+         FirstDfOfNode[0]=0;
+         for (int i=0;i<=nn;i++) throwassert(FirstDfOfNode[i]!=-1); 
+
+         for (int i=0;i<nn;i++) 
+              FirstDfOfNode[i+1] += FirstDfOfNode[i] ;
+           NbOfDF=  FirstDfOfNode[nn];       
+        }
+    else
+       {
+         NbOfDF = nn*ndf; 
+         Nproduit = ndf;        
+       }
+   MaxNbNodePerElement=nbne;
+   
+   cout << " Nb Of Nodes = " << nn << endl;   
+   if(NbOfNodeL)        
+     cout << " Nb of Lagrange Mul Node = " << NbOfNodeL << endl;        
+   cout << " Nb of DF = " << NbOfDF << endl;   
+   if(NbOfDFL) {  
+     cout << " Nb of Lagrange Mul DF = "   << NbOfDFL << endl;  
+     cout << " MaxNbDFPerElement     =   " << MaxNbDFPerElement << endl;
+   };
+
+}
+
+FESpace::FESpace(const FESpace & Vh,int k )
+ :
+     ptrTFE(new TypeOfFEProduit(k,*Vh.TFE[0])),
+     TFE(1,0,ptrTFE),
+     cmesh(Vh.Th),
+     cdef(Vh.cdef?new ConstructDataFElement(Vh.cdef,k):0),
+     N(Vh.N*k),
+     Nproduit(Vh.Nproduit*k),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     
+     Th(Vh.Th),
+     NbOfDF(Vh.NbOfDF*k),
+     NbOfElements(Vh.NbOfElements),
+     NbOfNodes(Vh.NbOfNodes),
+     MaxNbNodePerElement(Vh.MaxNbNodePerElement),
+     MaxNbDFPerElement(Vh.MaxNbDFPerElement*k),
+     NodesOfElement(Vh.NodesOfElement),
+     FirstDfOfNodeData(cdef?cdef->FirstDfOfNode:0),
+     FirstNodeOfElement(Vh.FirstNodeOfElement),
+     tom(0) {
+     if(cdef) renum();}
+ 
+FESpace::FESpace(const FESpace ** Vh,int k )
+ :
+     ptrTFE(new TypeOfFESum(Vh,k)),
+     TFE(1,0,ptrTFE),
+     cmesh((**Vh).Th),
+     cdef(new ConstructDataFElement(Vh,k)),
+     N(sum(Vh,&FESpace::N,k)),
+     Nproduit(cdef->Nproduit),     
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+
+     Th((**Vh).Th),
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement),
+     NodesOfElement(cdef->NodesOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     tom(0) {
+     if(cdef) renum(); }
+     
+FESpace::FESpace(const Mesh & TTh,const TypeOfFE ** tef,int k,int nbdfv,const int *ndfv,int nbdfe,const int *ndfe )
+ :
+     ptrTFE(new TypeOfFESum(tef,k)),
+     TFE(1,0,ptrTFE),
+     cmesh(TTh),
+     cdef(new ConstructDataFElement(TTh,sum(tef,&TypeOfFE::NbDfOnVertex,k),
+                                        sum(tef,&TypeOfFE::NbDfOnEdge,k),
+                                        sum(tef,&TypeOfFE::NbDfOnElement,k),
+                                        0,nbdfv,ndfv,nbdfe,ndfe)),
+     N(sum(tef,&TypeOfFE::N,k)),
+     Nproduit(cdef->Nproduit),     
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+
+     Th(TTh),
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement),
+     NodesOfElement(cdef->NodesOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     tom(0) {
+     if(cdef) renum(); }
+
+
+ FESpace::FESpace(const Mesh & TTh,const TypeOfFE & tef,int nbdfv,const int *ndfv,int nbdfe,const int *ndfe)
+   :  
+     ptrTFE(0),
+     TFE(1,0,&tef),
+     cmesh(TTh),
+     cdef(new ConstructDataFElement(TTh,tef.NbDfOnVertex,tef.NbDfOnEdge,tef.NbDfOnElement,0,nbdfv,ndfv,nbdfe,ndfe)),
+     N(tef.N),
+     Nproduit(cdef->Nproduit),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     Th(TTh),
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement),
+     NodesOfElement(cdef->NodesOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     tom(0) {
+     if(tef.NbDfOnVertex || tef.NbDfOnEdge) renum();
+     }
+     
+ FESpace::~FESpace()
+   {
+     SHOWVERB(cout << " FESpace::~FESpace() " << endl);
+      delete  cdef;
+      if(ptrTFE) 
+        delete  ptrTFE;
+   }
+
+ FESpace::FESpace(const Mesh & TTh,const TypeOfFE & tef,const TypeOfMortar & tm)
+   :  
+     ptrTFE(0),
+     TFE(1,0,&tef),
+     cmesh(TTh),
+     cdef(new ConstructDataFElement(TTh,tef.NbDfOnVertex,tef.NbDfOnEdge,tef.NbDfOnElement,&tm)),
+     N(tef.N),
+     Nproduit(1),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),     
+     Th(TTh),
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement),
+     NodesOfElement(cdef->NodesOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     tom(&tm) { 
+     // cout << "avant renum ="<< *this <<endl;
+       renum();
+     // cout << "apres renum ="<< *this <<endl;
+     }
+     
+void ConstructDataFElement::renum(const long *r,int l)   
+ { 
+/*   cout << "renu=" << l << ":" << endl;
+   for (int i=0;i<NbOfNode;i++)
+      if (i%10) cout << r[i] << "\t";
+      else cout << "\n " << i << ":\t" << r[i] << "\t";
+      cout << endl; 
+*/
+   throwassert(this);
+   if (NodesOfElement) 
+     for (int i=0;i< l ; i++)
+       NodesOfElement[i]=r[NodesOfElement[i]];
+   if(FirstDfOfNode)  
+    { int k,i,*n=new int[NbOfNode];
+      for ( i=0;i<NbOfNode;i++)        
+         n[r[i]]=FirstDfOfNode[i+1]-FirstDfOfNode[i]; 
+      FirstDfOfNode[0]=k=0;
+      for(i=0;i< NbOfNode;)
+        {k+=n[i];
+         FirstDfOfNode[++i]=k;}
+       delete [] n;
+    }
+ }     
+ 
+ 
+/*
+ void TypeOfFEProduit::D2_FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   int n=teb.NbDoF;
+   int m=teb.N;   
+   val=0.0;
+   SubArray t(3);
+   RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
+   teb.D2_FB(Th,K,P,v);
+   for (int i=1;i<k;i++)
+     val(SubArray(n,i,k),SubArray(m,m*i),t)=v; 
+ } 
+*/ 
+/*
+ void TypeOfFEProduit::FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   int n=teb.NbDoF;
+   int m=teb.N;   
+   val=0.0;
+   SubArray t(3);
+   RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
+   teb.FB(Th,K,P,v);
+   for (int i=1;i<k;i++)
+     val(SubArray(n,i,k),SubArray(m,m*i),t)=v; 
+ }
+ */
+ void TypeOfFEProduit::FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   int n=teb.NbDoF;
+   int m=teb.N;   
+   val=0.0;
+   SubArray t(val.K());
+   RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
+   teb.FB(whatd,Th,K,P,v);
+   for (int i=1;i<k;i++)
+     val(SubArray(n,i,k),SubArray(m,m*i),t)=v; 
+ }
+ 
+/* 
+ void TypeOfFEProduit::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j, void * arg) const
+ {
+   const baseFElement  KK(K,teb);
+   int m=teb.N;   
+    for(int i=0;i<k;i++)
+     { RN_  vv(val(SubArray(m,m*i)));
+     teb.Pi_h(KK,vv,f,v,j+i*m,arg);}
+ }
+ 
+/* 
+ void TypeOfFESum::D2_FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   val=0.0;
+   SubArray t(3);
+   for (int i=0;i<k;i++)
+    {
+     int j=comp[i];
+     int ni=NN[i];
+     int di=DF[i];  
+     int i1=i+1; 
+     int nii=NN[i1];
+     int dii=DF[i1];
+     throwassert(ni<nii && di < dii);
+     RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));     
+     if (j<=i)
+       teb[i]->D2_FB(Th,K,P,v);       
+     else
+       v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);     
+    } }
+*/    
+/*
+ void TypeOfFESum::FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   val=0.0;
+   SubArray t(3);
+   for (int i=0;i<k;i++)
+    {
+     int j=comp[i];
+     int ni=NN[i];
+     int di=DF[i];  
+     int i1=i+1; 
+     int nii=NN[i1];
+     int dii=DF[i1];
+     throwassert(ni<nii && di < dii);
+     RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));     
+     if (j<=i)
+       teb[i]->FB(Th,K,P,v);       
+     else
+       v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);     
+    }
+ }
+*/ 
+  void TypeOfFESum::FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   val=0.0;
+   SubArray t(val.K());
+   for (int i=0;i<k;i++)
+    {
+     int j=comp[i];
+     int ni=NN[i];
+     int di=DF[i];  
+     int i1=i+1; 
+     int nii=NN[i1];
+     int dii=DF[i1];
+     throwassert(ni<nii && di < dii);
+     RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));     
+     if (j<=i)
+       teb[i]->FB(whatd,Th,K,P,v);       
+     else
+       v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);     
+    }
+ }
+/* 
+ void TypeOfFESum::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int jjj, void * arg) const
+ {
+    for(int i=0;i<k;i++)
+     { 
+       const baseFElement  KK(K,*teb[i]);
+       int dfii=DF[i+1],dfi=DF[i];
+       RN_  vv(val(SubArray(dfii-dfi,dfi)));
+       teb[i]->Pi_h(KK,vv,f,v,jjj+NN[i],arg);
+     }
+    // cout << val(SubArray(NbDoF)) << endl;
+     
+ }
+ /*
+ void TypeOfFE_P1Lagrange::D2_FB(const Mesh & ,const Triangle & ,const R2 & ,RNMK_ & val) const
+{ //  
+  val=0;
+}
+*/
+/*
+ void TypeOfFE_P2Lagrange::D2_FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{ // 2 times derivatives  for error indicator
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+  throwassert(val.N() >=6);
+  throwassert(val.M()==1 );
+  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ fxx(val('.',0,0)); 
+  RN_ fxy(val('.',0,1)); 
+  RN_ fyy(val('.',0,2)); 
+  
+  fxx[0] = 4*Dl0.x*Dl0.x;
+  fxx[1] = 4*Dl1.x*Dl1.x;
+  fxx[2] = 4*Dl2.x*Dl2.x;
+  fxx[3] =  8*Dl1.x*Dl2.x;
+  fxx[4] =  8*Dl0.x*Dl2.x;
+  fxx[5] =  8*Dl0.x*Dl1.x;
+
+  fyy[0] = 4*Dl0.y*Dl0.y;
+  fyy[1] = 4*Dl1.y*Dl1.y;
+  fyy[2] = 4*Dl2.y*Dl2.y;
+  fyy[3] =  8*Dl1.y*Dl2.y;
+  fyy[4] =  8*Dl0.y*Dl2.y;
+  fyy[5] =  8*Dl0.y*Dl1.y;
+
+  fxy[0] = 4*Dl0.y*Dl0.y;
+  fxy[1] = 4*Dl1.y*Dl1.y;
+  fxy[2] = 4*Dl2.y*Dl2.y;
+  fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+  fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+  fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+
+}
+*/
+ R TypeOfFE_P1Lagrange::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+   R u0(u(K(0))), u1(u(K(1))), u2(u(K(2)));
+   R r=0;
+   if (op==0)
+    {
+      R l0=1-PHat.x-PHat.y,l1=PHat.x,l2=PHat.y; 
+      r = u0*l0+u1*l1+l2*u2;
+    }
+   else
+    { 
+       const Triangle & T=K.T;
+       R2 D0 = T.H(0) , D1 = T.H(1)  , D2 = T.H(2) ;
+       if (op==1)
+         r =  D0.x*u0 + D1.x*u1 + D2.x*u2 ;
+        else 
+         r =  D0.y*u0 + D1.y*u1 + D2.y*u2 ;
+    }
+ //  cout << r << "\t";
+   return r;
+}
+
+
+void TypeOfFE_P1Lagrange::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd[op_id]) 
+   {
+    f0[0] = l0;
+    f0[1] = l1;
+    f0[2] = l2;}
+ if (whatd[op_dx] || whatd[op_dy])
+  {
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  
+  if (whatd[op_dx]) 
+   {
+    RN_ f0x(val('.',0,op_dx)); 
+   f0x[0] = Dl0.x;
+   f0x[1] = Dl1.x;
+   f0x[2] = Dl2.x;
+  }
+  
+  if (whatd[op_dy]) {
+    RN_ f0y(val('.',0,op_dy)); 
+   f0y[0] = Dl0.y;
+   f0y[1] = Dl1.y;
+   f0y[2] = Dl2.y;
+  }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// NEW /////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+/*
+void TypeOfFE_P1Bubble::FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const
+{
+  assert(0);
+}
+
+
+void TypeOfFE_P1Bubble::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const
+{
+  assert(0);
+}
+
+/*
+R TypeOfFE_P1Bubble::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const
+{
+  assert(0);
+}
+*/
+
+void TypeOfFE_P1Bubble::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y, l1=P.x, l2=P.y, lb=l0*l1*l2*9.; 
+  
+  if (val.N() <4) 
+   throwassert(val.N() >=4);
+  throwassert(val.M()==1 );
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd[op_id]) 
+   {
+    f0[0] = l0-lb;
+    f0[1] = l1-lb;
+    f0[2] = l2-lb;
+    f0[3] = 3.*lb;
+   }
+  if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+ {
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2)), 
+     Dlb((Dl0*l1*l2+Dl1*l0*l2+Dl2*l0*l1)*9.);
+  
+  if (whatd[op_dx]) 
+   {
+    RN_ f0x(val('.',0,op_dx)); 
+   f0x[0] = Dl0.x-Dlb.x;
+   f0x[1] = Dl1.x-Dlb.x;
+   f0x[2] = Dl2.x-Dlb.x;
+   f0x[3] = 3.*Dlb.x;
+  }
+  
+  if (whatd[op_dy]) {
+    RN_ f0y(val('.',0,op_dy)); 
+   f0y[0] = Dl0.y-Dlb.y;
+   f0y[1] = Dl1.y-Dlb.y;
+   f0y[2] = Dl2.y-Dlb.y;
+   f0y[3] = 3.*Dlb.y;
+  }
+ if (whatd[op_dxx])
+  {  
+    RN_ fxx(val('.',0,op_dxx)); 
+    R lbdxx= 2*((Dl0.x*Dl1.x)*l2+(Dl1.x*Dl2.x)*l0+(Dl2.x*Dl0.x)*l1);
+    fxx[0] = -lbdxx;
+    fxx[1] = -lbdxx;
+    fxx[2] = -lbdxx;
+    fxx[3] = 3*lbdxx;
+  }
+
+ if (whatd[op_dyy])
+  {  
+    RN_ fyy(val('.',0,op_dyy));
+    R lbdyy= 2*((Dl0.y*Dl1.y)*l2+(Dl1.y*Dl2.y)*l0+(Dl2.y*Dl0.y)*l1);
+     
+    fyy[0] =  -lbdyy;
+    fyy[1] =  -lbdyy;
+    fyy[2] =  -lbdyy;
+    fyy[3] =  3*lbdyy;
+  }
+ if (whatd[op_dxy])
+  {  
+    assert(val.K()>op_dxy);
+    RN_ fxy(val('.',0,op_dxy)); 
+    R lbdxy= (Dl0.x*Dl1.y+ Dl0.y*Dl1.x)*l2+(Dl1.x*Dl2.y+Dl1.y*Dl2.x)*l0+(Dl2.x*Dl0.y+Dl2.y*Dl0.x)*l1;  
+    fxy[0] = 4*Dl0.x*Dl0.y-9.*(l0-l1-l2);
+    fxy[1] = 4*Dl1.x*Dl1.y-9.*(l0-l1-l2);
+    fxy[2] = 4*Dl2.x*Dl2.y-9.*(l0-l1-l2);
+    fxy[3] = 27.*(l0-l1-l2);
+  }
+  }
+
+}
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+/* void TypeOfFE_P1Lagrange::FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,0)); 
+  RN_ f0x(val('.',0,1)); 
+  RN_ f0y(val('.',0,2)); 
+  
+  f0[0] = l0;
+  f0[1] = l1;
+  f0[2] = l2;
+  
+  f0x[0] = Dl0.x;
+  f0x[1] = Dl1.x;
+  f0x[2] = Dl2.x;
+  
+  f0y[0] = Dl0.y;
+  f0y[1] = Dl1.y;
+  f0y[2] = Dl2.y;
+}
+
+ void TypeOfFE_P2Lagrange::FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+//  throwassert(FE.N == 1);  
+  throwassert( val.N()>=6);
+  throwassert(val.M()==1);
+  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,0)); 
+  RN_ f0x(val('.',0,1)); 
+  RN_ f0y(val('.',0,2)); 
+// --     
+  f0[0] = l0*(2*l0-1);
+  f0[1] = l1*(2*l1-1);
+  f0[2] = l2*(2*l2-1);
+  f0[3] = 4*l1*l2; // oppose au sommet 0
+  f0[4] = 4*l0*l2; // oppose au sommet 1
+  f0[5] = 4*l1*l0; // oppose au sommet 3
+  
+  
+  f0x[0] = Dl0.x*l4_0;
+  f0x[1] = Dl1.x*l4_1;
+  f0x[2] = Dl2.x*l4_2;
+  f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
+  f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
+  f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
+  
+  
+  f0y[0] = Dl0.y*l4_0;
+  f0y[1] = Dl1.y*l4_1;
+  f0y[2] = Dl2.y*l4_2;
+  f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
+  f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
+  f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
+  
+}
+*/
+void TypeOfFE_P2Lagrange::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+//  throwassert(FE.N == 1);  
+  throwassert( val.N()>=6);
+  throwassert(val.M()==1);
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+// --     
+ if (whatd[op_id])
+  {
+   RN_ f0(val('.',0,op_id)); 
+  f0[0] = l0*(2*l0-1);
+  f0[1] = l1*(2*l1-1);
+  f0[2] = l2*(2*l2-1);
+  f0[3] = 4*l1*l2; // oppose au sommet 0
+  f0[4] = 4*l0*l2; // oppose au sommet 1
+  f0[5] = 4*l1*l0; // oppose au sommet 3
+  }
+ if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+ {
+   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  if (whatd[op_dx])
+  {
+    RN_ f0x(val('.',0,op_dx)); 
+  f0x[0] = Dl0.x*l4_0;
+  f0x[1] = Dl1.x*l4_1;
+  f0x[2] = Dl2.x*l4_2;
+  f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
+  f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
+  f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
+  }
+
+ if (whatd[op_dy])
+  {  
+    RN_ f0y(val('.',0,op_dy)); 
+  f0y[0] = Dl0.y*l4_0;
+  f0y[1] = Dl1.y*l4_1;
+  f0y[2] = Dl2.y*l4_2;
+  f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
+  f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
+  f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
+  }
+ 
+ if (whatd[op_dxx])
+  {  
+    RN_ fxx(val('.',0,op_dxx)); 
+
+    fxx[0] = 4*Dl0.x*Dl0.x;
+    fxx[1] = 4*Dl1.x*Dl1.x;
+    fxx[2] = 4*Dl2.x*Dl2.x;
+    fxx[3] =  8*Dl1.x*Dl2.x;
+    fxx[4] =  8*Dl0.x*Dl2.x;
+    fxx[5] =  8*Dl0.x*Dl1.x;
+  }
+
+ if (whatd[op_dyy])
+  {  
+    RN_ fyy(val('.',0,op_dyy)); 
+    fyy[0] = 4*Dl0.y*Dl0.y;
+    fyy[1] = 4*Dl1.y*Dl1.y;
+    fyy[2] = 4*Dl2.y*Dl2.y;
+    fyy[3] =  8*Dl1.y*Dl2.y;
+    fyy[4] =  8*Dl0.y*Dl2.y;
+    fyy[5] =  8*Dl0.y*Dl1.y;
+  }
+ if (whatd[op_dxy])
+  {  
+    assert(val.K()>op_dxy);
+    RN_ fxy(val('.',0,op_dxy)); 
+  
+    fxy[0] = 4*Dl0.x*Dl0.y;
+    fxy[1] = 4*Dl1.x*Dl1.y;
+    fxy[2] = 4*Dl2.x*Dl2.y;
+    fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+    fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+    fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+  }
+ 
+ }
+ 
+}
+/*
+ void TypeOfFE_P1Lagrange::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j,  void * arg) const
+{
+  const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1) };
+   for (int i=0;i<3;i++)
+     {  
+     f(v,K.T(Pt[i]),K,i,Pt[i],arg),val[i]=*(v+j);}
+ 
+}
+ void TypeOfFE_P2Lagrange::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j, void * arg) const
+{
+  const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0) };
+   for (int i=0;i<6;i++)
+     {
+     f(v,K.T(Pt[i]),K,i,Pt[i],arg),val[i]=*(v+j);}
+ 
+}
+*/
+ 
+ 
+//TypeOfFE  P1Lagrange(1,0,0,P1Functions,D2_P1Functions,P1Interpolant,DataP1Lagrange);
+//TypeOfFE  P2Lagrange(1,1,0,P2Functions,D2_P2Functions,P2Interpolant,DataP2Lagrange,3);
+
+//  case of   fine mesh   
+class TypeOfMortarCas1: public TypeOfMortar { 
+  friend class FESpace;
+  friend class FMortar;
+  friend class ConstructDataFElement;
+  protected:
+  int NbLagrangeMult(const Mesh &,const Mortar &M) const ;
+ 
+   int NbDoF(const Mesh &,const Mortar &M,int i) const 
+     { int l(M.NbLeft()),r(M.NbRight());
+       int n =Max(l,r);
+       int mn=Min(l,r);
+       return (l+r)*(NbDfOnVertex + NbDfOnEdge) + (n+1)*NbDfOnVertex + n*NbDfOnEdge -mn-1; 
+      }
+  int NbOfNodes(const Mesh &,const Mortar &M) const // call one time  
+     {int l(M.NbLeft()),r(M.NbRight()); return (l+r)*(vertex_is_node+edge_is_node)+1;}
+  int NbDoF(const Mesh &,const Mortar &M) const 
+     { int l(M.NbLeft()),r(M.NbRight());
+       int n =Max(l,r);
+       int mn=Min(l,r);
+       return (l+r)*(NbDfOnVertex + NbDfOnEdge) + (n+1)*NbDfOnVertex + n*NbDfOnEdge -mn-1; 
+      }
+  
+   int NodeOfDF(const FESpace &Vh,const Mortar &M,int i) const 
+     {throwassert(0);return 0;}
+   int DFOfNode(const FESpace &Vh,const Mortar &M,int i) const 
+     {throwassert(0);return 0;}
+   void ConstructionOfNode(const Mesh &Th,int im,int * NodesOfElement,int *FirstNodeOfElement,int &lastnodenumber) const;
+   void ConsTheSubMortar(FMortar & ) const; 
+     
+   const int vertex_is_node,edge_is_node;
+  public: 
+    TypeOfMortarCas1 (int i,int j): TypeOfMortar(i,j),
+      vertex_is_node(i?1:0),edge_is_node(j?1:0) {};
+     
+}  MortarCas1P2(1,1) ;
+
+ const TypeOfMortar & TheMortarCas1P2(MortarCas1P2); 
+ 
+
+void TypeOfMortarCas1::ConstructionOfNode(const Mesh &Th,int im,int * NodesOfElement,int *FirstNodeOfElement,int &lastnodenumber) const
+{  
+  // im   mortar number 
+ // trop complique on change 
+             const Mortar &M(Th.mortars[im]);
+             int k = Th.nt+im;
+             int  kk=FirstNodeOfElement[k]; //  begin   
+             // lagrange  multiplicator one new node 
+              NodesOfElement[kk++] = lastnodenumber++;
+/*                               
+             int il = M.NbLeft();
+             int ir = M.NbRight();
+             int ir1 = ir-1;
+             //  left
+             
+             for( int j=0;j<il;j++)  //  numbering vertex0 edge vertex1
+              { 
+                int K = M.TLeft(j);  // triangle
+                int e = M.ELeft(j);  //  edge
+                int nbneK = FirstNodeOfElement[K];
+                int oe = vertex_is_node ? 3 : 0;
+                int i0 = VerticesOfTriangularEdge[e][0];
+                int i1 = VerticesOfTriangularEdge[e][1];
+                if (vertex_is_node && !j)   //  just the first time 
+                   NodesOfElement[kk++]=NodesOfElement[nbneK +i0];
+                if (edge_is_node)
+                   NodesOfElement[kk++]=NodesOfElement[nbneK+oe+e];
+                if (vertex_is_node )  
+                   NodesOfElement[kk++]=NodesOfElement[nbneK +i1];
+              }
+
+             //  right 
+             for( int j=0;j<ir;j++)  //  numbering vertex0 edge vertex1
+              { 
+                int K = M.TRight(j);  // triangle
+                int e = M.ERight(j);  //  edge
+                int nbneK = FirstNodeOfElement[K];
+                int oe = vertex_is_node ? 3 : 0;
+                
+                int i0 = VerticesOfTriangularEdge[e][1]; //  change the sens because right side
+                int i1 = VerticesOfTriangularEdge[e][0];
+              //  if (vertex_is_node &&  !j)   // never 
+               //    NodesOfElement[kk++]=NodesOfElement[nbneK +i0];
+                if (edge_is_node) 
+                   NodesOfElement[kk++]=NodesOfElement[nbneK+oe+e];
+                if (vertex_is_node  && (j != ir1) )  //  skip the last 
+                   NodesOfElement[kk++]=NodesOfElement[nbneK +i1];
+              } */
+              
+              throwassert(FirstNodeOfElement[k+1]==kk);
+}
+
+ R  d1P1F0(const FESpace *,const aSubFMortar *,R x) {return 1-x;}// 1 on 0
+ R  d1P1F1 (const FESpace *,const aSubFMortar *,R x) {return x;}//  1 on 1
+ 
+ R  d1P2F0 (const FESpace *,const aSubFMortar *,R x) {return (1-x)*(1-2*x);}// 1 on x=0
+ R  d1P2F1(const FESpace *,const aSubFMortar *,R x) {return (1-x)*x*4;} // 1 on x=1/2
+ R  d1P2F2(const FESpace *,const aSubFMortar *,R x) {return x*(2*x-1);} // 1 on x=1
+ 
+ void  TypeOfMortarCas1::ConsTheSubMortar(FMortar & sm) const
+   { //  constuction of 
+   /* 
+     int nbsm; // nb of submortar
+  aSubFMortar * sm;
+  ~FMortar() { delete [] dataDfNumberOFmul; delete [] dataf;}
+  private:
+  
+  int *dataDfNumberOFmul;
+   R (**dataf)(const FESpace *,const aSubFMortar *,R);
+
+   */
+   //  typedef
+     const Mesh &Th(sm.Vh.Th);
+     const Mortar & M(sm.M);
+     int nl=M.NbLeft();
+     int nr=M.NbRight();
+     int nbsm= nl+nr-1;
+     sm.nbsm = nbsm;
+     int ldata = 6*nbsm;// 3 gauche+ 3 droite 
+     sm.sm = new aSubFMortar[nbsm];
+     sm.datai = new int [ldata];
+     sm.dataf = new (R (*[ldata])(const FESpace *,const aSubFMortar *,R))  ;
+     int *dataDfNumberOFmul=sm.datai;
+     
+     R (**dataf)(const FESpace *,const aSubFMortar *,R) ;
+     dataf=sm.dataf;
+     for (int i=0;i<ldata;i++) sm.dataf[i]=0;
+   //  int * data0=sm.data+ldata;
+   //  int * data1=data0+ldata;
+     
+     //  now the construction 
+     int l=0,g=0;
+     R2 A(M.VLeft(0));
+     R2 B(M.VLeft(nl));
+     throwassert(&M.VLeft(0) == &M.VRight(0));
+     throwassert(&M.VLeft(nl) == &M.VRight(nr));
+    
+     R2 AB(A,B);
+     R lg=Norme2(AB);
+    // cout << " Mortar from " << A << " to " << B << " = " <<lg << endl;
+     R2 AB1(AB/lg);
+     int il=0,ir=0;
+     int k=0;
+     R la=0.0;
+     R lb=0.0;
+     R2 AA(A),BB(A);
+   //  cout << "lg : " <<lg ;
+     do {
+       sm.sm[k].left  = M.left[il];
+       sm.sm[k].right =  M.right[ir];
+       R2 Bl(M.VLeft(il+1));
+       R2 Br(M.VRight(ir+1));
+       R ll=(AB1,Bl-A), lr=(AB1,Br-A);
+     //  throwassert ( ll >=0 && lr >= 0);
+     //  throwassert ( ll <=lg  && lr <= lg);
+       
+   //    cout << "AA , BB = " << AA << "," << BB << endl;
+    //   cout << " " << ll << " " << lr << " ll=" << sm.sm[k].left << ", ";
+       if (ll<lr) {BB=Bl,lb=ll,il++;} else {BB=Br, lb=lr,ir++;}
+  //     cout << k << " " << k << " " << la/lg << " " << lb/lg << endl;
+       sm.sm[k].a = la/lg;
+       sm.sm[k].b = lb/lg;
+       sm.sm[k].A=AA;
+       sm.sm[k].B=BB;       
+       la=lb;
+       AA=BB;
+       k++;
+       throwassert(k<=nbsm);
+     } while (il<nl && ir < nr);
+     
+  //   cout << "k=" << k <<endl;
+     throwassert(nbsm==Max(nl,nr)); 
+     //throwassert(nbsm<=k);
+    nbsm=k;
+    sm.nbsm=k;
+//   construction of interpolation 
+//  1) on a P1 on P2 
+//   P2  si les longueurs des aSubMortar precedende et suivant  sont les meme 
+//   sinon P1 
+   //  calcul de leps 
+     R leps=1.0/(1048576.0) ; // 1/2^20 
+     R lgp=0;
+     R lgc=0;
+     R lgs=sm.sm[0].lg1();
+    // cout << lgp << " " << lgc << " " << lgs << endl;
+     
+     int nmul=0;
+     for (int k=0;k<nbsm;k++) 
+       {
+         
+         lgp=lgc;
+         lgc=lgs;
+         lgs=  k+1 == nbsm  ? 0 : sm.sm[k+1].lg1();
+         sm.sm[k].DfNumberOFmul= dataDfNumberOFmul;
+         sm.sm[k].f=dataf;
+        // cout << lgp << " " << lgc << " " << lgs << " ";
+         if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
+          { // P2
+           sm.sm[k].Nbmul=3;
+           *dataDfNumberOFmul++=nmul++;
+           *dataDfNumberOFmul++=nmul++;
+           *dataDfNumberOFmul++=nmul;
+           *dataf++ = d1P2F0;
+           *dataf++ = d1P2F1;
+           *dataf++ = d1P2F2;
+          // cout << "P2 " << nmul << " " ;
+           
+          }
+         else 
+          { // P1
+                   sm.sm[k].Nbmul=2;
+           *dataDfNumberOFmul++=nmul++;
+           *dataDfNumberOFmul++=nmul;
+           *dataf++ = d1P1F0;
+           *dataf++ = d1P1F1;
+          // cout << "P1 " << nmul << " " ;
+           
+
+          }
+       }
+      nmul++;
+     // cout << " " << nmul << " " <<  sm.NbDoF(0) << endl;
+      throwassert(nmul==sm.NbDoF(0));
+     
+   }
+   
+  int TypeOfMortarCas1::NbLagrangeMult(const Mesh &,const Mortar &M) const 
+     { 
+       int nl = M.NbLeft();
+       int nr = M.NbRight();
+       R2 A(M.VLeft(0));
+       R2 B(M.VLeft(nl));
+       R2 AB(A,B);
+       R lg=Norme2(AB);
+       R leps = lg/1048576.0;
+       throwassert(nl==1 || nr==1);
+       R lgp=0,lgc=0,lgs=0;
+       int nbmul=3; 
+       if (nr==1) 
+        {
+        R2 AA(M.VLeft(0)),BB(M.VLeft(1));
+        lgp= Norme2(BB-AA); // preced
+        AA=BB;
+        BB=M.VLeft(2); 
+        lgc= Norme2(BB-AA); // courant 
+        
+        for (int i=1;i<nl-1;i++)
+         { 
+            AA=BB;
+            BB=M.VLeft(i+2); 
+            lgs=Norme2(AA-BB); // le suivant 
+            if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
+              nbmul+=2; // P2
+            else 
+              nbmul+=1;// P1;
+            lgp=lgc;
+            lgc=lgs;
+            
+         }
+        }
+        else
+        {
+        R2 AA(M.VRight(0)),BB(M.VRight(1));
+        lgp= Norme2(BB-AA); // preced
+        AA=BB;
+        BB=M.VRight(2); 
+        lgc= Norme2(BB-AA); // courant 
+        
+        for (int i=1;i<nr-1;i++)
+         { 
+            AA=BB;
+            BB=M.VRight(i+2); 
+            lgs=Norme2(AA-BB); // le suivant 
+            if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
+              nbmul+=2; // P2
+            else 
+              nbmul+=1;// P1;
+            lgp=lgc;
+            lgc=lgs;
+            
+         }
+        }
+       throwassert(nbmul>2);
+       return nbmul;
+      }  
+
+ 
+// --- 
+ FMortar::FMortar(const FESpace * VVh,int k)
+  : 
+    Vh(*VVh),
+    M(Vh.Th.mortars[k-Vh.Th.nt]),
+    N(VVh->N),
+    p(Vh.PtrFirstNodeOfElement(k)),
+    nbn(Vh.NbOfNodesInElement(k)),
+    tom(Vh.tom)
+    
+ { throwassert(k>=Vh.Th.nt && k <Vh.Th.nt + Vh.Th.NbMortars);
+   VVh->tom->ConsTheSubMortar(*this);}
+   
+ R TypeOfFE::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const 
+  {
+   R v[1000],vf[100];
+   assert(N*3*NbDoF<=1000 && NbDoF <100 );
+   KNMK_<R> fb(v,NbDoF,N,op+1); //  the value for basic fonction
+   KN_<R> fk(vf,NbDoF);
+   for (int i=0;i<NbDoF;i++) // get the local value
+    fk[i] = u[K(i)];
+    //  get value of basic function
+   bool whatd[last_operatortype];
+   for (int i=0;i<last_operatortype;i++) 
+     whatd[i]=false;
+   whatd[op]=true;
+   FB(whatd,K.Vh.Th,K.T,PHat,fb);  
+   R r = (fb('.',componante,op),fk);  
+   return r;
+  }
+ 
+static TypeOfFE_P1Lagrange P1LagrangeP1;
+static TypeOfFE_P1Bubble P1BubbleP1;
+static TypeOfFE_P2Lagrange P2LagrangeP2;
+
+TypeOfFE  & P2Lagrange(P2LagrangeP2);
+TypeOfFE  & P1Bubble(P1BubbleP1);
+TypeOfFE  & P1Lagrange(P1LagrangeP1);
+
+static ListOfTFE typefemP1("P1", &P1LagrangeP1);
+static ListOfTFE typefemP1b("P1b", &P1BubbleP1);
+static ListOfTFE typefemP2("P2", &P2LagrangeP2);
+static  ListOfTFE typefemRT("RT0", &RTLagrange);
+static  ListOfTFE typefemRTOrtho("RT0Ortho", &RTLagrangeOrtho);
+ 
+ extern  TypeOfFE & RTmodifLagrange, & P1ttdc, & P2ttdc;
+ static  ListOfTFE typefemRTmodif("RTmodif", &RTmodifLagrange);
+ static ListOfTFE typefemP0("P0", &P0Lagrange);
+ static ListOfTFE typefemP1nc("P1nc", &P1ncLagrange);
+ static ListOfTFE typefemP1ttdc("P1dc", &P1ttdc);
+ static ListOfTFE typefemP2ttdc("P2dc", &P2ttdc);
+ 
+} // fin de namespace Fem2D 
diff --git a/src/femlib/FESpace.cpp b/src/femlib/FESpace.cpp
new file mode 100644
index 0000000..9eba86a
--- /dev/null
+++ b/src/femlib/FESpace.cpp
@@ -0,0 +1,2030 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <cmath>
+#include <cstdlib>
+#include "error.hpp"
+#include <iostream>
+#include <fstream>
+#include <map>
+#include "rgraph.hpp"
+using namespace std;  
+
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpacen.hpp"
+#include "FESpace.hpp"
+extern long verbosity ;
+namespace  Fem2D {
+
+ int  Make(const TypeOfFE ** t,int k,KN<R2> & P,KN<int> & I)
+ {
+   typedef  TypeOfFE::IPJ IPJ;
+
+   int n=0,nn=0;
+
+   for (int i=0;i<k;i++)
+    {
+     const KN<R2> p(t[i]->P_Pi_h);
+     for (int j=0;j<p.N();j++,nn++)
+     {
+       P[n]=p[j]; // par defaut un nouveau => ajout
+       I[nn]=n++;       
+       for (int l=0;l<n-1;l++)
+        {
+          R2 QP(p[j],P[l]);
+          if ( (QP,QP) < 1.0e-12 ) { 
+            I[nn]=l;
+            n--; // on a retrouver =>  detruit
+            break;}
+        }
+       
+     }
+    }
+   return n; // nombre de point commun
+ }
+ 
+ KN<TypeOfFE::IPJ > Makepij_alpha(const TypeOfFE ** t,int k)
+ {
+ // Attention les df est numerote de facon croissant 
+ // en faisant une boucle sur les TypeOfFE
+ // comme dans la class TypeOfFESum
+  typedef TypeOfFE::IPJ IPJ;
+  int n=0,m=0;
+  for (int i=0;i< k;i++) {
+    n += t[i]->pij_alpha.N();
+    m += t[i]->P_Pi_h.N();
+    }
+  KN<TypeOfFE::IPJ > ij(n);
+  KN<int> I(m);
+  KN<R2> P(m);
+  Make(t,k,P,I);
+  int p0=0,i0=0,N0=0,nn=0;
+  for (int i=0;i< k;i++) {
+    const KN<IPJ > p(t[i]->pij_alpha);
+     for (int j=0;j<p.N();j++,nn++)  
+      {
+        ij[nn].i= p[j].i+i0; //  comme dans TypeOfFESum
+        ij[nn].j= N0+ p[j].j;
+        ij[nn].p= I[p[j].p+p0];
+       
+      //   cout << nn << "Makepij_alpha: " << ij[nn].i << " " << ij[nn].p << " " << ij[nn].j << endl;
+        
+      }
+    i0+=t[i]->NbDoF;
+    p0+=t[i]->P_Pi_h.N();
+    N0+=t[i]->N;}
+  return ij; 
+ }
+ KN<R2 > MakeP_Pi_h(const TypeOfFE **t,int k)
+ {
+  int np=0;
+  for (int i=0;i< k;i++) 
+    np += t[i]->P_Pi_h.N();
+    
+  KN< R2 >  yy(np);
+  KN<int> zz(np);
+  int kk=Make(t,k,yy,zz);
+ // cout << " MakeP_Pi_h: " << kk << " from " << np << endl; 
+  return yy(SubArray(kk));
+ 
+ }
+
+ListOfTFE * ListOfTFE::all ; // list of all object of this type 
+
+void init_static_FE(); //   to correct so probleme with static Library FH aout 2004
+//  the list of other FE file to force the link 
+
+ListOfTFE::ListOfTFE (const char * n,TypeOfFE *t) : name(n),tfe(t) 
+{
+  if(!t)
+  assert(t);
+  static int count=0;
+  if (count++==0) 
+    all=0; // init of all in dependant of the ordre of the objet file   
+  next=all;
+  all=this;
+ //  to correct so probleme with static Library FH aout 2004 
+ init_static_FE();
+}
+
+const TypeOfFE ** Make(const FESpace **l,int k) {
+  const TypeOfFE** p=new const TypeOfFE*[k];
+  for (int i=0;i<k;i++)
+    p[i]=l[i]->TFE[0];
+  return p;
+}
+const TypeOfFE ** Make(const TypeOfFE **l,int k) {
+  const TypeOfFE** p=new const TypeOfFE*[k];
+  for (int i=0;i<k;i++)
+    p[i]=l[i];
+  return p;
+}
+
+  
+bool Same(const FESpace **l,int k)
+{
+   for (int i=1;i<k;i++)
+    if (l[0] != l[i] ) return false;
+   return true;
+}   
+
+class FESumConstruct { protected:
+   const int k;
+   const TypeOfFE ** teb;
+   int nbn; // nb of node 
+   int  *  data;
+   int  * data1;
+   int  * const NN; //  NN[ i:i+1[ dimension de l'element i
+   int  * const DF; // DF[i:i+1[  df associe a l'element i
+   int  * const comp; //  
+   FESumConstruct(int kk,const TypeOfFE **t);   
+   virtual ~FESumConstruct(){
+     delete [] DF;
+     delete [] NN;
+     delete [] comp;
+     delete [] data;}   
+};
+
+  void FElement::Pi_h(RN_ val,InterpolFunction f,R *v, void * arg=0) const {
+   // routine: a  tester FH.
+    FElement::aIPJ ipj(Pi_h_ipj()); 
+    FElement::aR2  PtHat(Pi_h_R2()); 
+    KN<R>   Aipj(ipj.N());
+    KNM<R>  Vp(N,PtHat.N());
+        
+     Pi_h(Aipj);
+     for (int p=0;p<PtHat.N();p++)
+          { 
+            f(v,T(PtHat[p]),*this,T.lab,PtHat[p],arg);
+            KN_<double> Vpp(Vp('.',p));
+            for (int j=0;j<N;j++)          
+               Vpp[j]=v[j];              
+           }
+           
+         for (int i=0;i<Aipj.N();i++)
+          { 
+           const FElement::IPJ &ipj_i(ipj[i]);
+           val[ipj_i.i] += Aipj[i]*Vp(ipj_i.j,ipj_i.p);           
+          }
+ }
+
+class TypeOfFESum: public FESumConstruct, public  TypeOfFE { public:
+   TypeOfFESum(const FESpace **t,int kk): 
+     FESumConstruct(kk,Make(t,kk)),TypeOfFE(teb,kk,data,data1) {}
+       TypeOfFESum(const TypeOfFE **t,int kk): 
+     FESumConstruct(kk,Make(t,kk)),TypeOfFE(teb,kk,data,data1) {}
+
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+//   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+//  void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void * arg ) const; 
+   virtual void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+    {
+      int k0=0;
+      for (int i=0;i<k;i++) {
+         //  int n=teb[i]->NbDoF; // ici BUG 28/11/2006 FH 
+          int n=teb[i]->pij_alpha.N(); // ici BUG 
+          KN_<R> sv(v(SubArray(n,k0)));
+          teb[i]->Pi_h_alpha(K,sv);
+          k0+= n;}
+      assert(pij_alpha.N()==k0);
+    }
+   ~TypeOfFESum(){  delete []  teb;}
+} ;
+
+class FEProduitConstruct { protected:
+   int k;
+   const TypeOfFE & teb;
+   int * data;
+   int * data1;
+   FEProduitConstruct(int kk,const TypeOfFE &t)  ;   
+   ~FEProduitConstruct(){delete [] data;}   
+};
+
+class TypeOfFEProduit: protected FEProduitConstruct, public  TypeOfFE { public:  
+  TypeOfFEProduit(int kk,const TypeOfFE &t): 
+    FEProduitConstruct(kk,t),TypeOfFE(t,kk,data,data1)  {}
+  
+  
+  void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  virtual void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+  { int nbof=teb.NbDoF;
+  for (int i=0,k0=0;i<k;i++,k0+=nbof)
+    {          
+      KN_<R> sv(v(SubArray(nbof,k0)));
+      teb.Pi_h_alpha(K,sv);
+    }
+  }
+  
+  ~TypeOfFEProduit(){}
+} ;
+
+FEProduitConstruct::FEProduitConstruct(int kk,const TypeOfFE &t)
+ :k(kk),teb(t) 
+{  
+  int m= teb.NbDoF;
+  KN<int> nn(teb.NbNode);
+  nn=0; // nb de dl par noeud 
+  for (int i=0;i<m;i++)
+    nn[teb.NodeOfDF[i]]++;   
+    
+  int n= m*kk;
+  int No=teb.N;
+  int N= No*kk;
+  data = new int [n*(5+2)+3*N];
+  data1 = data + n*(5)+N; // april 2006  add 2 array ????
+  int c=0;
+  
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++)
+    data[c++] = teb.DFOnWhat[i];
+  
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) // num of df on node  for the df = j 
+      data[c++] = teb.DFOfNode[i]+j*nn[teb.NodeOfDF[i]];
+    
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) 
+    data[c++] = teb.NodeOfDF[i]; //  node of df
+
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) 
+    data[c++] = j; //  node from of FE
+    
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) 
+    data[c++] = i; //  node from of df in FE
+    
+   for (int j=0;j<kk;j++) 
+    for (int i=0;i<teb.N;i++) 
+      data[c++]= teb.dim_which_sub_fem[i] + teb.nb_sub_fem*j ;
+ 
+   int ci=n;
+   int cj=0;
+
+  //  ou dans la partie miminal element finite atomic 
+  for (int i=0;i<m;i++)
+   for (int j=0;j<kk;j++) 
+    {
+      int il= teb.fromASubDF[i];
+      int jl= teb.fromASubFE[i];
+      data1[ci++]=il;
+      data1[cj++]=j*teb.nb_sub_fem+jl;      
+    }
+  //  warning the numbering of  
+  for(int j=0;j<kk;++j)
+    for(int i=0;i<No;++i)
+      data1[ci++]=0;//j*m+teb.begin_dfcomp[i];
+  for(int j=0;j<kk;++j)
+    for(int i=0;i<No;++i)      
+      data1[ci++]=m*kk;//j*m+teb.end_dfcomp[i];
+  cout << " kk "<< kk << " " << m << " : ";
+  //  for(int i=0;i< N*2;++i)
+  //  cout << data1[2*n+i] << " " ;
+  // cout << endl;    
+}
+
+FESumConstruct::FESumConstruct(int kk,const TypeOfFE **t)
+ :k(kk),teb(t),NN(new int[kk+1]),DF(new int[kk+1]) , comp(new int[kk])
+{  
+   map<const TypeOfFE *,int> m;
+   int i=k,j;    
+   while(i--) // on va a l'envert pour avoir comp[i] <=i 
+      m[teb[i]]=i;
+    // l'ordre comp est important comp est croissant  mais pas de pb. 
+   i=k;    
+   while(i--) 
+     comp[i]=m[teb[i]]; //  comp[i] <=i
+        
+  // reservatition des intervalles en espaces
+  int n=0,N=0;
+   for ( j=0;j<kk;j++)
+     {NN[j]=N;N+=teb[j]->N;}
+   NN[kk] = N;
+ //  reservation des interval en df   
+   n=0;
+   for ( j=0;j<kk;j++)
+    { DF[j]=n;n+=teb[j]->NbDoF;}
+   DF[kk] = n;
+//  n = nb de DF total   
+//  N the fem is in R^N 
+   
+  data = new int [n*(5+2) + 3*N];
+  data1 = data + n*5+N; // april 2006  add 2 array ????
+  
+  int c=0;
+  //  int ki= 0; 
+// recherche des noeuds
+   KN<int> w(7),nn(7);
+   w=0;
+   nn=0; 
+   
+         
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+         nn[teb[j]->DFOnWhat[i]]++;
+   nbn=0;      
+   for( j=0;j<7;j++)
+     if (nn[j]) nn[j]=nbn++;
+     else nn[j]=-1;
+   KN<int> dln(7);
+   dln=0;
+  // nn donne numero de noeud sur what            
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = teb[j]->DFOnWhat[i];
+    
+   for ( j=0;j<kk;j++)
+    {
+     int  cc=c;
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = teb[j]->DFOfNode[i]+dln[teb[j]->DFOnWhat[i]];
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       dln[teb[j]->DFOnWhat[i]]=Max(dln[teb[j]->DFOnWhat[i]],data[cc++]+1);      
+    }
+        
+       
+   for ( j=0;j<kk;j++)
+    { 
+     //  w renumerotation des noeuds 
+     //  Ok si un noeud par what 
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = nn[teb[j]->DFOnWhat[i]];
+    }
+    
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = j; //  node from of FE
+
+    
+   for ( j=0;j<kk;j++)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       data[c++] = i; //  node from of df in FE
+  // error -- here 
+  //in case of [P2,P2],P1  
+   // we expect 0,0,1   and we get 0 1 2 
+   // => wrong BC ???? 
+   int xx=0;
+   for (j=0;j<kk;j++)
+     { 
+      int xxx=xx;
+      for (i=0;i<teb[j]->N;i++)
+       { 
+         data[c] = teb[j]->dim_which_sub_fem[i]+xx;
+         xxx=Max(xxx,data[c]+1);
+         c++;
+       }
+       xx=xxx;
+     }
+    
+
+  //  ou dans la partie miminal element finite atomic 
+ 
+   int ci=n;
+   int cf=2*n;
+   int cl=cf+N;;
+   int cj=0;
+   int ccc=0;
+   for ( j=0;j<kk;ccc+=teb[j++]->nb_sub_fem)
+     for ( i=0;i<teb[j]->NbDoF;i++)
+       {
+	 int il= teb[j]->fromASubDF[i];
+	 int jl= teb[j]->fromASubFE[i];
+	 data1[ci++]=il;
+	 data1[cj++]=ccc+jl;      
+       }
+
+   for (int  j=0,ccn=0 ; j<kk ; ccn += teb[j++]->NbDoF)     
+     for(int k=0;k<teb[j]->N;++k)
+       {
+	 data1[cf++] = ccn + teb[j]->begin_dfcomp[k];
+	 data1[cl++] = ccn + teb[j]->end_dfcomp[k];
+       }
+   ffassert(cl==2*n+2*N);    
+  
+  ffassert(c== 5*n+N);      
+/*  int cc=0;
+   cout << " Data : " << endl;
+  for ( i=0;i<5;i++)    {
+    for (j=0;j<n;j++)
+      cout << " " << data[cc++];
+     cout << endl;}
+ cout << " which " ;
+ for (i=0;i<N;i++)
+   cout << " " << data[cc++];
+  cout << endl;*/
+}
+
+class TypeOfFE_P1Lagrange : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+   TypeOfFE_P1Lagrange(): TypeOfFE(1,0,0,1,Data,1,1,3,3,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1) }; 
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   
+//   void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
+   
+} ;
+///////////////////////////////////////////////////////////////////////////////
+// FH pour tester des idee de schema ----  Juin 2005 ---
+///////////////////////////////////////////////////////////////////////////////
+
+//  un VF cell centre 
+class TypeOfFE_P0VF : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+   TypeOfFE_P0VF(): TypeOfFE(1,0,0,1,Data,1,1,3,3,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1) }; 
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
+   
+} ;
+int TypeOfFE_P0VF::Data[]={0,1,2,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0, 0,3};
+double TypeOfFE_P0VF::Pi_h_coef[]={1.,1.,1.}; //  bofbof a verifier ...
+
+ R TypeOfFE_P0VF::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+   R u0(u(K(0))), u1(u(K(1))), u2(u(K(2)));
+   R r=0;
+   if (op==0)
+    {
+      R l0=0,l1=PHat.x,l2=PHat.y;
+      l1 = l1 * 3. < 1;
+      l2 = l2 * 3. < 1;
+      l0 = 1 - l0 -l2;
+      
+      r = u0*l0+u1*l1+l2*u2;
+    }
+   else
+    { 
+      r =0; 
+    }
+ //  cout << r << "\t";
+   return r;
+}
+
+
+void TypeOfFE_P0VF::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  if (whatd[op_id]) 
+   {
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  l1 = l1 * 3. < 1;
+  l2 = l2 * 3. < 1;
+  l0 = 1 - l0 -l2;
+  
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+    f0[0] = l0;
+    f0[1] = l1;
+    f0[2] = l2;}
+ 
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////// NEW ////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class TypeOfFE_P1Bubble : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+   TypeOfFE_P1Bubble(): TypeOfFE(1,0,1,1,Data,1,1,4,4,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1), R2(1./3.,1./3.) }; 
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   
+//   void D2_FB(const Me�Seria�����sh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ //  void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+  //virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const ;
+   
+} ;
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class TypeOfFE_P2Lagrange : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+  
+   TypeOfFE_P2Lagrange(): TypeOfFE(1,1,0,1,Data,3,1,6,6,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0) };
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+   
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ //  void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+} ;
+
+
+class TypeOfFE_P2bLagrange : public  TypeOfFE { public:  
+  static int Data[];
+  static double Pi_h_coef[];
+  
+   TypeOfFE_P2bLagrange(): TypeOfFE(1,1,1,1,Data,3,1,7,7,Pi_h_coef)
+    { const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0), R2(1./3.,1./3.) };
+      for (int i=0;i<NbDoF;i++) {
+       pij_alpha[i]= IPJ(i,i,0);
+       P_Pi_h[i]=Pt[i]; }
+     }
+   
+  // void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+   void FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+ //  void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const;
+  // void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int, void *) const;
+} ;
+
+int TypeOfFE_P1Lagrange::Data[]={0,1,2,       0,0,0,       0,1,2,       0,0,0,        0,1,2,       0, 0,3};
+int TypeOfFE_P1Bubble::Data[]={0,1,2,6,     0,0,0,0,     0,1,2,3,     0,0,0,0,        0,1,2,3,     0, 0,4};
+int TypeOfFE_P2Lagrange::Data[]={0,1,2,3,4,5, 0,0,0,0,0,0, 0,1,2,3,4,5, 0,0,0,0,0,0,  0,1,2,3,4,5, 0 ,0,6};
+int TypeOfFE_P2bLagrange::Data[]={0,1,2,3,4,5,6, 0,0,0,0,0,0,0, 0,1,2,3,4,5,6, 0,0,0,0,0,0,0,  0,1,2,3,4,5,6, 0,0,7};
+double TypeOfFE_P1Lagrange::Pi_h_coef[]={1.,1.,1.};
+double TypeOfFE_P1Bubble::Pi_h_coef[]={1.,1.,1.,1.};
+double TypeOfFE_P2Lagrange::Pi_h_coef[]={1.,1.,1.,1.,1.,1.};
+double TypeOfFE_P2bLagrange::Pi_h_coef[]={1.,1.,1.,1.,1.,1.,1.};
+
+inline void dump(char *m,int n,int * p)
+{
+  cout << m ;
+  for (int i=0;i<n;i++) cout << " " << p[i] ;
+  cout << endl;
+}
+
+
+
+ConstructDataFElement::~ConstructDataFElement()
+{
+  if((*counter)--==0) 
+   {
+   // cout << " delete ConstructDataFElement " <<   NodesOfElement << " " <<  FirstNodeOfElement << " "<< FirstDfOfNode << "  " << counter << endl;
+    delete [] NodesOfElement;
+    delete []  FirstNodeOfElement;
+    delete [] FirstDfOfNode;
+    (*counter)--; // correct bug oct 2008
+    delete counter;
+  }
+//  else (*counter)--; // correct bug oct 2008
+  // else 
+     // cout << " no delete ConstructDataFElement " <<   NodesOfElement << " " <<  FirstNodeOfElement << " "<< FirstDfOfNode << "  " << counter << endl;
+// (*counter)--; // correction mai 2006 bug in counter incrementation 
+}
+
+ ConstructDataFElement::ConstructDataFElement(const ConstructDataFElement * t,int k)
+  ://thecounter(0), 
+   counter(t->counter),
+   MaxNbNodePerElement(t->MaxNbNodePerElement),
+   MaxNbDFPerElement(t->MaxNbDFPerElement*k),
+   NodesOfElement(t->NodesOfElement),
+   FirstNodeOfElement(t->FirstNodeOfElement),
+   FirstDfOfNode(0),
+   NbOfElements(t->NbOfElements),
+   NbOfDF(t->NbOfDF*k),
+   NbOfNode(t->NbOfNode),
+   Nproduit(t->Nproduit*k)
+ {
+   throwassert(t==0 || t->FirstDfOfNode==0);
+   (*counter)++;      // correction mai 2006 bug in counter incrementation  
+
+ }
+
+ConstructDataFElement::ConstructDataFElement (const Mesh &Th,/*int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement*/
+const  KN<const TypeOfFE *> & TFEs,const TypeOfMortar *tm,
+int nbdfv,const int *ndfv,int nbdfe,const int *ndfe)
+: counter(NewCounter())
+{ 
+ Make(Th,TFEs,/*NbDfOnSommet,NbDfOnEdge,NbDfOnElement,*/ tm,nbdfv,ndfv,nbdfe,ndfe);
+}
+
+ConstructDataFElement::ConstructDataFElement(const FESpace ** l,int k,const KN<const TypeOfFE *>  & TFEs) 
+: counter(NewCounter()) 
+{
+ int NbDfOnSommet=0;
+ int NbDfOnEdge=0;
+ int NbDfOnElement=0;
+ const Mesh & Th(l[0]->Th);
+ for  (int i=0;i<k;i++)
+   {
+     NbDfOnSommet += l[i]->TFE[0]->NbDfOnVertex;
+     NbDfOnEdge += l[i]->TFE[0]->NbDfOnEdge;
+     NbDfOnElement += l[i]->TFE[0]->NbDfOnElement;
+     ffassert( &Th== &l[i]->Th); 
+     ffassert( l[i]->TFE.constant());
+   }
+   
+ Make(Th,TFEs);//NbDfOnSommet,NbDfOnEdge,NbDfOnElement,0);   
+}
+ 
+
+void ConstructDataFElement::Make(const Mesh &Th,
+const  KN<const TypeOfFE *> & TFEs,
+
+/*int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,*/const TypeOfMortar *tm,
+int nb_dfv,const int *ndfv,int nb_dfe,const int *ndfe) 
+/* pour le condition de periodicit� ..
+  nb_dfv :  nombre de sommets recolle par periodicit�
+  ndfv:  numerotation des sommets pour CL de periodicite
+  ndfv[i] = numero du sommet i (i<Th.nv)  recolle par periodicit�
+  nb_dfe:  nombre de arete frontiere  recolle par periodicit�
+  ndfe[i]:  numero de l'arete frontiere (i < Th.neb) recoll�. 
+  F. H. 
+*/  
+{
+  *counter=0;
+  assert(TFEs.constant());
+  const TypeOfFE & TFE(*TFEs[0]);
+  int nbdfe=TFE.NbDoF; 
+  int NbDfOnSommet=TFE.NbDfOnVertex;
+  int NbDfOnEdge=TFE.NbDfOnEdge;
+  int NbDfOnElement=TFE.NbDfOnElement;
+  int NbNodeonVertex=0;
+  int NbNodeonEdge=0;
+  int NbNodeonElement=0;
+  int NbNodes=TFE.NbNode;
+
+
+   assert( nbdfe == 3*NbDfOnSommet+3*NbDfOnEdge+NbDfOnElement);
+/*  Vieux code 
+  { // construct du tableau NodeOn et calcul de NbNodeon.. 
+   KN<int>NodeOn(NbNodes);
+   NodeOn=-1;
+   int nb[7];
+   for (int i=0;i<7;i++)
+     nb[i]=0;
+   int kkk=0;
+   for (int df=0;df<TFE.NbDoF;df++)
+    {
+     int node=TFE.NodeOfDF[df];
+     int w=TFE.DFOnWhat[df];
+     if ( NodeOn[node] >=0)
+      assert( NodeOn[node] ==w); 
+     else {
+       NodeOn[node]=w;
+  	     ++kkk;
+  	     ++nb[w]; }// on vertex 0  	    
+  	 }
+   assert(nb[0]==nb[1] && nb[1] == nb[2]);
+   assert(nb[3]==nb[4] && nb[4] == nb[5]);
+   NbNodeonVertex=nb[0];
+   NbNodeonEdge=nb[3];
+   NbNodeonElement=nb[6]; 
+   assert(kkk==NbNodes);
+  }*/
+  
+   KN<int> NbDFonNode(NbNodes), NodeIsOn(NbNodes);
+   NbDFonNode=0;
+   for (int df=0;df<nbdfe;df++)
+    {
+     int node=TFE.NodeOfDF[df];
+     int what=TFE.DFOnWhat[df];
+     int ndfonnode = TFE.DFOfNode[df];
+     NbDFonNode[node]=Max(NbDFonNode[node],ndfonnode+1);
+     NodeIsOn[node]=what;
+    }
+   assert(NbDFonNode.sum() == nbdfe);
+   
+   NbNodeonVertex=TFE.NbNodeOnVertex;
+   NbNodeonEdge=TFE.NbNodeOnEdge;
+   NbNodeonElement=TFE.NbNodeOnElement; 
+  
+  assert(NbNodeonVertex<=1);
+  assert(NbNodeonEdge<=1);
+  assert(NbNodeonElement<=1);
+  Nproduit =1;
+  const int ndf=NbDFonNode[0];
+  int samendf=1;
+  
+  for (int i=1;i<NbNodes;i++)
+    if ( ndf != NbDFonNode[i]) 
+     { samendf = 0;
+       break;}
+  
+  int nbne = NbNodes;
+  int nn=0;  
+  int firstmul=0;
+  ffassert( tm || Th.NbMortars==0);
+  NbOfElements = Th.nt; //  by default
+  // if mortars 
+  //
+  int NbOfNodeL=0;
+  NbOfElements += Th.NbMortars;  
+  FirstDfOfNode =0;
+  FirstNodeOfElement=0;
+  MaxNbDFPerElement=nbdfe; 
+  assert(3*NbDfOnSommet+3*NbDfOnEdge+NbDfOnElement==MaxNbDFPerElement);
+
+  int ks=TFE.NbNodeOnVertex>0,
+      ke=TFE.NbNodeOnEdge>0,
+      kt=TFE.NbNodeOnElement>0;
+ /* Vieux code 
+   if(NbDfOnSommet) { nbne+=3;
+     ks=1;
+     ndf=NbDfOnSommet;}
+
+  if(NbDfOnEdge) {  nbne+=3;
+     ke=1;
+     samendf &= !ndf || ndf == NbDfOnEdge;
+     ndf=NbDfOnEdge;}
+     
+  if(NbDfOnElement) {  nbne+=1;
+     kt=1;
+     samendf &= !ndf || ndf == NbDfOnElement;
+     ndf=NbDfOnElement;}
+
+  int NbDFonNode[7],NodeIsOn[7];
+   {
+     int j=0,k=0;
+     if(ks) { NbDFonNode[j++]=NbDfOnSommet; NbDFonNode[j++]=NbDfOnSommet; NbDFonNode[j++]=NbDfOnSommet;}
+     if(ke) { NbDFonNode[j++]=NbDfOnEdge; NbDFonNode[j++]=NbDfOnEdge; NbDFonNode[j++]=NbDfOnEdge;}
+     if(kt) { NbDFonNode[j++]=NbDfOnElement;}
+
+     if (ks) {NodeIsOn[k++]=0;NodeIsOn[k++]=1;NodeIsOn[k++]=2;}
+     if (ke) {NodeIsOn[k++]=3;NodeIsOn[k++]=4;NodeIsOn[k++]=5;}
+     if (kt) {NodeIsOn[k++]=6;}
+     
+     throwassert(j == nbne);
+  }
+*/     
+    MaxNbNodePerElement=nbne;
+
+//  
+   if ( ks && (!ke && ! kt) && (ndfv==0 && ndfe==0))
+     {nn=Th.nv;
+      NodesOfElement=0;
+      }
+   else {
+//    constuction du tableau  NodesOfElement  bofbof 
+
+//     computation of the length lne of array NodesOfElement        
+       int lne=  Th.nt*nbne;
+       if (Th.NbMortars)
+        {
+          samendf= false;
+          NbOfNodeL=Th.NbMortars;
+          ffassert(tm);
+          FirstNodeOfElement = new int[NbOfElements+1];
+          int k=0,kk=0;          
+          for (k=0;k<Th.nt;k++,kk+=nbne)
+            FirstNodeOfElement[k] = kk;
+           
+          for (int im=0;im<Th.NbMortars;im++) // (www) code 
+            {
+             FirstNodeOfElement[k++]=lne;           
+             lne += tm->NbOfNodes(Th,Th.mortars[im]);
+            }
+          FirstNodeOfElement[k++]=lne;           
+        }       
+        
+       NodesOfElement = new int[lne];
+       
+       for (int i=0;i<lne;i++) 
+         NodesOfElement[i]=-1;
+       int i=0;
+       int oe=0; 
+       if(ks) { oe=3*NbNodeonVertex;nn= (ndfv ? nb_dfv : Th.nv)*NbNodeonVertex;}
+       
+       if (ke && ndfe) { // il y a des aretes avec cl de periodicite. 
+        for (int be=0;be<Th.neb;be++)
+         {
+          int j,k=Th.BoundaryElement(be,j);
+          int jj=j;
+          int kk=Th.ElementAdj(k,jj);
+          for (int kkk=0;kkk<NbNodeonEdge;kkk++)
+           {
+             int kj=kkk,kjj=-1;
+            // assert(kk != k);
+             if ( kk >= 0 && jj >=0  &&  !(( kk == k ) && ( jj=j ) ) ) 
+             {
+              if (k < kk ) kjj = NbNodeonEdge-kj-1; //
+              else   kj = NbNodeonEdge-kj-1, kjj = NbNodeonEdge-kj-1;
+             }
+          if (kjj >=0)   
+            NodesOfElement[kk*nbne+oe+jj] = nn + ndfe[be]*NbNodeonEdge+ kjj   ; // adj
+          NodesOfElement[k*nbne+oe+j]   = nn + ndfe[be]*NbNodeonEdge+ kj   ; // new  
+          }       
+         }
+         nn += nb_dfe;
+        }
+       for (int k=0;k<Th.nt;k++)
+        {
+          // int iold=i;
+          if(ks) {
+            for (int j=0;j<3;j++)
+             for (int jj=0;jj<NbNodeonVertex;jj++)
+              NodesOfElement[i++]= (ndfv ?  ndfv[Th(k,j)] : Th(k,j))*NbNodeonVertex+jj ;
+          }
+          if(ke) {
+            for (int j=0;j<3;j++)
+             for (int ll=0;ll<NbNodeonEdge;ll++)
+             if (NodesOfElement[i]<0) {
+               int jj=j;
+               int kk=Th.ElementAdj(k,jj);
+               int jjj=jj*NbNodeonEdge+NbNodeonEdge-ll-1; // autre sens  
+               assert(kk>=k && jjj == jj); 
+               NodesOfElement[kk*nbne+oe+jjj] = nn   ; // adj   
+               NodesOfElement[i++]           = nn++ ; // new
+             }  else i++;
+          }
+          for (int jj=0;jj<NbNodeonElement;jj++) 
+             NodesOfElement[i++]= nn++;
+         // cout << k ;
+         // dump(" ",i-iold, NodesOfElement+iold);
+        }
+       // cout << i << " " << Th.nt*nbne << endl;
+        firstmul=nn;
+        if (Th.NbMortars)
+          {  
+            //  construction of the mortars element 
+           int * color= new int [firstmul]; 
+           //  
+           int thecolor=0;
+           for (int j=0;j<firstmul;j++) 
+             color[j]=thecolor;
+             
+           for (int im=0;im<Th.NbMortars;im++)
+            {   
+	      //int iold=i;         
+             thecolor++; // get a new color
+             // tm->ConstructionOfNode(Th,im,NodesOfElement,FirstNodeOfElement,nn);  
+             Mortar & M(Th.mortars[im]);
+              NodesOfElement[i++] = nn++; // the first node is the lag. mul.
+             int n=M.NbT();
+             for (int kk=0;kk<n;kk++)
+             {
+              int K,e;
+               K=M.T_e(kk,e); 
+               int kb=FirstNodeOfElement[K];
+               int ke=FirstNodeOfElement[K+1];             
+               for (int j=kb,jj=0;j<ke;j++,jj++)
+                if (onWhatIsEdge[e][NodeIsOn[jj]])
+                 { // the node jj is on edge e
+                    int node=NodesOfElement[j];
+                   // cout << "." << jj << " K=" << K <<" "<<e << " n=" << node ;
+                    throwassert(node<firstmul);
+                    if (color[node] != thecolor) //  new node => adding
+                     { 
+                    //   cout << "a, ";
+                       color[node] = thecolor;
+                       NodesOfElement[i++] = node;
+                     }
+                   // else cout << ", ";
+                 }
+               }
+               //cout << endl;
+               
+               //cout << im ;
+               //dump(": ",i-iold, NodesOfElement+iold);
+               ffassert(i==FirstNodeOfElement[im+Th.nt+1]);
+              }
+             delete [] color;
+          } 
+        else
+          ffassert(i==Th.nt*nbne && i );
+        NbOfNode=nn;
+                
+        
+   }
+  NbOfNode=nn;  
+  int NbOfDFL=0;  
+   if (! samendf) 
+       {
+         
+         ffassert(NodesOfElement);
+         FirstDfOfNode= new int [nn+1];
+         for (int i=0;i<=nn;i++) FirstDfOfNode[i]=-1; 
+         int i=0;
+         //  the classical part (FEM)
+         for (int k=0;k<Th.nt;k++)
+           for (int j=0;j<nbne;j++) // thanks to student
+             FirstDfOfNode[ NodesOfElement[i++]+1]=NbDFonNode[j];
+         //  the mortars parts juste the mulplicator 
+         
+         for (int km=0,k=Th.nt;km<Th.NbMortars;km++,k++) 
+            {  //  the lag. mult. is the first node of the mortar --
+              throwassert(FirstNodeOfElement);
+              //  hack 
+              int fk=FirstNodeOfElement[k];
+              int lk=FirstNodeOfElement[k+1];
+              int ndlmul = tm->NbLagrangeMult(Th,Th.mortars[km]);  //  On node par 
+              int nodemul = NodesOfElement[fk]; // the first node is the lagr. mul.
+              throwassert(FirstDfOfNode[nodemul+1]==-1);      
+              FirstDfOfNode[nodemul+1]= ndlmul;
+              NbOfDFL += ndlmul;
+              int nbdle=0;
+              //int nbnm=lk-fk;
+              for (int j=fk;j<lk;j++)
+               nbdle+=FirstDfOfNode[NodesOfElement[j]+1];
+              MaxNbDFPerElement = Max(MaxNbDFPerElement,nbdle);
+            }
+             
+         FirstDfOfNode[0]=0;
+         for (int i=0;i<=nn;i++) throwassert(FirstDfOfNode[i]!=-1); 
+
+         for (int i=0;i<nn;i++) 
+              FirstDfOfNode[i+1] += FirstDfOfNode[i] ;
+           NbOfDF=  FirstDfOfNode[nn];       
+        }
+    else
+       {
+         NbOfDF = nn*ndf; 
+         Nproduit = ndf;        
+       }
+   MaxNbNodePerElement=nbne;
+   if(verbosity>2)
+   {
+     cout << "  FESpace: Nb Of Nodes = " << nn ;   
+     if(NbOfNodeL)        
+       cout << " Nb of Lagrange Mul Node = " << NbOfNodeL  ;        
+     cout << " Nb of DF = " << NbOfDF << endl;   
+     if(NbOfDFL) {  
+       cout << " Nb of Lagrange Mul DF = "   << NbOfDFL ;  
+       cout << " MaxNbDFPerElement     =   " << MaxNbDFPerElement ;
+     };
+       cout << endl;
+   }
+}
+
+FESpace::FESpace(const FESpace & Vh,int k )
+ :
+     Th(Vh.Th),
+     ptrTFE(new TypeOfFEProduit(k,*Vh.TFE[0])),
+     TFE(1,0,ptrTFE),
+     cdef(Vh.cdef?new ConstructDataFElement(Vh.cdef,k):0),
+     cmesh(Vh.Th),
+     N(Vh.N*k),
+     Nproduit(Vh.Nproduit*k),     
+     NbOfDF(Vh.NbOfDF*k),
+     NbOfElements(Vh.NbOfElements),
+     NbOfNodes(Vh.NbOfNodes),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     NodesOfElement(Vh.NodesOfElement),
+     FirstNodeOfElement(Vh.FirstNodeOfElement),
+     FirstDfOfNodeData(cdef?cdef->FirstDfOfNode:0),
+     tom(0),
+     MaxNbNodePerElement(Vh.MaxNbNodePerElement),
+     MaxNbDFPerElement(Vh.MaxNbDFPerElement*k)
+{
+      // correction mai 2006 no renumbering of existing cdef 
+     if(cdef && (Vh.cdef && Vh.cdef->counter != cdef->counter)) {
+       // cout << " remum " << cdef->counter << " != " << Vh.cdef->counter  <<endl; 
+       renum(); // correction mai 2006 no renumbering of existing cdef 
+       }
+    Show();
+     }
+ 
+FESpace::FESpace(const FESpace ** Vh,int k )
+ :
+     Th((**Vh).Th),
+     ptrTFE(new TypeOfFESum(Vh,k)),
+     TFE(1,0,ptrTFE),
+     cdef(new ConstructDataFElement(Vh,k,TFE)),
+     cmesh((**Vh).Th),
+     N(sum(Vh,&FESpace::N,k)),
+     Nproduit(cdef->Nproduit),     
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     NodesOfElement(cdef->NodesOfElement),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     tom(0) ,
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement) 
+{
+     if(cdef) renum();
+    Show();
+    // verification 
+    long snbdf=0;
+    for(int i=0;i<k;++i)
+        snbdf += Vh[i]->NbOfDF;
+    if( snbdf !=NbOfDF)
+        cerr << " Problem build of FEspace (2d) (may be : due to periodic Boundary condition missing ) FH " << endl
+             << " The number of DF must be " << snbdf << "  and it is " << NbOfDF <<endl; 
+    ffassert(snbdf == NbOfDF );
+}
+     
+FESpace::FESpace(const Mesh & TTh,const TypeOfFE ** tef,int k,int nbdfv,const int *ndfv,int nbdfe,const int *ndfe )
+ :
+     Th(TTh),
+     ptrTFE(new TypeOfFESum(tef,k)),
+     TFE(1,0,ptrTFE),
+     cdef(new ConstructDataFElement(TTh,TFE,//sum(tef,&TypeOfFE::NbDfOnVertex,k),
+                                       // sum(tef,&TypeOfFE::NbDfOnEdge,k),
+                                        //sum(tef,&TypeOfFE::NbDfOnElement,k),
+                                        0,nbdfv,ndfv,nbdfe,ndfe)),
+     cmesh(TTh),
+     N(sum(tef,&TypeOfFE::N,k)),
+     Nproduit(cdef->Nproduit),     
+
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     NodesOfElement(cdef->NodesOfElement),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     tom(0) ,
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement)
+{
+  if(cdef) renum();
+  Show();
+}
+
+
+ FESpace::FESpace(const Mesh & TTh,const TypeOfFE & tef,int nbdfv,const int *ndfv,int nbdfe,const int *ndfe)
+   :  
+     Th(TTh),
+     ptrTFE(0),
+     TFE(1,0,&tef),
+     cdef(new ConstructDataFElement(TTh,TFE,0,nbdfv,ndfv,nbdfe,ndfe)),
+     cmesh(TTh),
+     //tef.NbDfOnVertex,tef.NbDfOnEdge,tef.NbDfOnElement,0,nbdfv,ndfv,nbdfe,ndfe)),
+     N(tef.N),
+     Nproduit(cdef->Nproduit),
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     NodesOfElement(cdef->NodesOfElement),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     tom(0),
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement)
+{
+  if(tef.NbDfOnVertex || tef.NbDfOnEdge) renum();
+  Show();
+}
+     
+ FESpace::~FESpace()
+   {
+     SHOWVERB(cout << " FESpace::~FESpace() " << endl);
+     /*  cout << " del FESpace " << this << " " <<  cdef << " "  ;
+       if(cdef) cout << cdef->NodesOfElement << endl;
+       else cout << endl;*/
+      delete  cdef;
+      if(ptrTFE) 
+        delete  ptrTFE;
+   }
+
+ FESpace::FESpace(const Mesh & TTh,const TypeOfFE & tef,const TypeOfMortar & tm)
+   :  
+     Th(TTh),
+     ptrTFE(0),
+     TFE(1,0,&tef),
+     cdef(new ConstructDataFElement(TTh,TFE,&tm)),//tef.NbDfOnVertex,tef.NbDfOnEdge,tef.NbDfOnElement,&tm)),
+     cmesh(TTh),
+     N(tef.N),
+     Nproduit(1),
+     NbOfDF(cdef->NbOfDF),
+     NbOfElements(cdef->NbOfElements),
+     NbOfNodes(cdef->NbOfNode),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),     
+     NodesOfElement(cdef->NodesOfElement),
+     FirstNodeOfElement(cdef->FirstNodeOfElement),
+     FirstDfOfNodeData(cdef->FirstDfOfNode),
+     tom(&tm),
+     MaxNbNodePerElement(cdef->MaxNbNodePerElement),
+     MaxNbDFPerElement(cdef->MaxNbDFPerElement)
+{ 
+     // cout << "avant renum ="<< *this <<endl;
+       renum();
+     // cout << "apres renum ="<< *this <<endl;
+    Show();
+     }
+     
+void ConstructDataFElement::renum(const long *r,int l)   
+ { 
+/*   cout << "renu=" << l << ":" << endl;
+   for (int i=0;i<NbOfNode;i++)
+      if (i%10) cout << r[i] << "\t";
+      else cout << "\n " << i << ":\t" << r[i] << "\t";
+      cout << endl; 
+*/
+   ffassert(this);
+   if (NodesOfElement) 
+     for (int i=0;i< l ; i++)
+       NodesOfElement[i]=r[NodesOfElement[i]];
+   if(FirstDfOfNode)  
+    { int k,i,*n=new int[NbOfNode];
+      for ( i=0;i<NbOfNode;i++)        
+         n[r[i]]=FirstDfOfNode[i+1]-FirstDfOfNode[i]; 
+      FirstDfOfNode[0]=k=0;
+      for(i=0;i< NbOfNode;)
+        {k+=n[i];
+         FirstDfOfNode[++i]=k;}
+       delete [] n;
+    }
+ }     
+ 
+ 
+/*
+ void TypeOfFEProduit::D2_FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   int n=teb.NbDoF;
+   int m=teb.N;   
+   val=0.0;
+   SubArray t(3);
+   RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
+   teb.D2_FB(Th,K,P,v);
+   for (int i=1;i<k;i++)
+     val(SubArray(n,i,k),SubArray(m,m*i),t)=v; 
+ } 
+*/ 
+/*
+ void TypeOfFEProduit::FB(const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   int n=teb.NbDoF;
+   int m=teb.N;   
+   val=0.0;
+   SubArray t(3);
+   RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
+   teb.FB(Th,K,P,v);
+   for (int i=1;i<k;i++)
+     val(SubArray(n,i,k),SubArray(m,m*i),t)=v; 
+ }
+ */
+ void TypeOfFEProduit::FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   int n=teb.NbDoF;
+   int m=teb.N;   
+   val=0.0;
+   SubArray t(val.K());
+   RNMK_ v(val(SubArray(n,0,k),SubArray(m),t));
+   teb.FB(whatd,Th,K,P,v);
+   for (int i=1;i<k;i++)
+     val(SubArray(n,i,k),SubArray(m,m*i),t)=v; 
+ }
+ 
+  void TypeOfFESum::FB(const bool * whatd,const Mesh & Th,const Triangle & K,const R2 & P,RNMK_ & val) const
+ {
+   val=0.0;
+   SubArray t(val.K());
+   for (int i=0;i<k;i++)
+    {
+     int j=comp[i];
+     int ni=NN[i];
+     int di=DF[i];  
+     int i1=i+1; 
+     int nii=NN[i1];
+     int dii=DF[i1];
+     throwassert(ni<nii && di < dii);
+     RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));     
+     if (j<=i)
+       teb[i]->FB(whatd,Th,K,P,v);       
+     else
+       v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);     
+    }
+ }
+ R TypeOfFE_P1Lagrange::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+   R u0(u(K(0))), u1(u(K(1))), u2(u(K(2)));
+   R r=0;
+   if (op==op_id)
+    {
+      R l0=1-PHat.x-PHat.y,l1=PHat.x,l2=PHat.y; 
+      r = u0*l0+u1*l1+l2*u2;
+    }
+   else
+    { 
+       const Triangle & T=K.T;
+       R2 D0 = T.H(0) , D1 = T.H(1)  , D2 = T.H(2) ;
+       if (op==op_dx)
+         r =  D0.x*u0 + D1.x*u1 + D2.x*u2 ;
+        else if(op==op_dy)
+         r =  D0.y*u0 + D1.y*u1 + D2.y*u2 ;
+    }
+ //  cout << r << "\t";
+   return r;
+}
+
+
+void TypeOfFE_P1Lagrange::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd[op_id]) 
+   {
+    f0[0] = l0;
+    f0[1] = l1;
+    f0[2] = l2;}
+ if (whatd[op_dx] || whatd[op_dy])
+  {
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  
+  if (whatd[op_dx]) 
+   {
+    RN_ f0x(val('.',0,op_dx)); 
+   f0x[0] = Dl0.x;
+   f0x[1] = Dl1.x;
+   f0x[2] = Dl2.x;
+  }
+  
+  if (whatd[op_dy]) {
+    RN_ f0y(val('.',0,op_dy)); 
+   f0y[0] = Dl0.y;
+   f0y[1] = Dl1.y;
+   f0y[2] = Dl2.y;
+  }
+  }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////// NEW /////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+void TypeOfFE_P1Bubble::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y, l1=P.x, l2=P.y, lb=l0*l1*l2*9.; 
+  
+  if (val.N() <4) 
+   throwassert(val.N() >=4);
+  throwassert(val.M()==1 );
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd[op_id]) 
+   {
+    f0[0] = l0-lb;
+    f0[1] = l1-lb;
+    f0[2] = l2-lb;
+    f0[3] = 3.*lb;
+   }
+  if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+ {
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2)), 
+     Dlb((Dl0*l1*l2+Dl1*l0*l2+Dl2*l0*l1)*9.);
+  
+  if (whatd[op_dx]) 
+   {
+    RN_ f0x(val('.',0,op_dx)); 
+   f0x[0] = Dl0.x-Dlb.x;
+   f0x[1] = Dl1.x-Dlb.x;
+   f0x[2] = Dl2.x-Dlb.x;
+   f0x[3] = 3.*Dlb.x;
+  }
+  
+  if (whatd[op_dy]) {
+    RN_ f0y(val('.',0,op_dy)); 
+   f0y[0] = Dl0.y-Dlb.y;
+   f0y[1] = Dl1.y-Dlb.y;
+   f0y[2] = Dl2.y-Dlb.y;
+   f0y[3] = 3.*Dlb.y;
+  }
+ if (whatd[op_dxx])
+  {  
+    RN_ fxx(val('.',0,op_dxx)); 
+    R lbdxx= 18*((Dl0.x*Dl1.x)*l2+(Dl1.x*Dl2.x)*l0+(Dl2.x*Dl0.x)*l1);
+    fxx[0] = -lbdxx;
+    fxx[1] = -lbdxx;
+    fxx[2] = -lbdxx;
+    fxx[3] = 3*lbdxx;
+  }
+
+ if (whatd[op_dyy])
+  {  
+    RN_ fyy(val('.',0,op_dyy));
+    R lbdyy= 18*((Dl0.y*Dl1.y)*l2+(Dl1.y*Dl2.y)*l0+(Dl2.y*Dl0.y)*l1);
+     
+    fyy[0] =  -lbdyy;
+    fyy[1] =  -lbdyy;
+    fyy[2] =  -lbdyy;
+    fyy[3] =  3*lbdyy;
+  }
+ if (whatd[op_dxy])
+  {  
+    assert(val.K()>op_dxy);
+    RN_ fxy(val('.',0,op_dxy)); 
+    R lbdxy= 9*(Dl0.x*Dl1.y+ Dl0.y*Dl1.x)*l2+(Dl1.x*Dl2.y+Dl1.y*Dl2.x)*l0+(Dl2.x*Dl0.y+Dl2.y*Dl0.x)*l1;  
+    fxy[0] = 4*Dl0.x*Dl0.y-lbdxy;
+    fxy[1] = 4*Dl1.x*Dl1.y-lbdxy;
+    fxy[2] = 4*Dl2.x*Dl2.y-lbdxy;
+    fxy[3] = +3*lbdxy;
+  }
+  }
+
+}
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+/* void TypeOfFE_P1Lagrange::FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  
+  if (val.N() <3) 
+   throwassert(val.N() >=3);
+  throwassert(val.M()==1 );
+  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,0)); 
+  RN_ f0x(val('.',0,1)); 
+  RN_ f0y(val('.',0,2)); 
+  
+  f0[0] = l0;
+  f0[1] = l1;
+  f0[2] = l2;
+  
+  f0x[0] = Dl0.x;
+  f0x[1] = Dl1.x;
+  f0x[2] = Dl2.x;
+  
+  f0y[0] = Dl0.y;
+  f0y[1] = Dl1.y;
+  f0y[2] = Dl2.y;
+}
+
+ void TypeOfFE_P2Lagrange::FB(const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+//  throwassert(FE.N == 1);  
+  throwassert( val.N()>=6);
+  throwassert(val.M()==1);
+  throwassert(val.K()==3 );
+  
+  val=0; 
+  RN_ f0(val('.',0,0)); 
+  RN_ f0x(val('.',0,1)); 
+  RN_ f0y(val('.',0,2)); 
+// --     
+  f0[0] = l0*(2*l0-1);
+  f0[1] = l1*(2*l1-1);
+  f0[2] = l2*(2*l2-1);
+  f0[3] = 4*l1*l2; // oppose au sommet 0
+  f0[4] = 4*l0*l2; // oppose au sommet 1
+  f0[5] = 4*l1*l0; // oppose au sommet 3
+  
+  
+  f0x[0] = Dl0.x*l4_0;
+  f0x[1] = Dl1.x*l4_1;
+  f0x[2] = Dl2.x*l4_2;
+  f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
+  f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
+  f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
+  
+  
+  f0y[0] = Dl0.y*l4_0;
+  f0y[1] = Dl1.y*l4_1;
+  f0y[2] = Dl2.y*l4_2;
+  f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
+  f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
+  f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
+  
+}
+*/
+void TypeOfFE_P2Lagrange::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y; 
+  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+//  throwassert(FE.N == 1);  
+  throwassert( val.N()>=6);
+  throwassert(val.M()==1);
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+// --     
+ if (whatd[op_id])
+  {
+   RN_ f0(val('.',0,op_id)); 
+  f0[0] = l0*(2*l0-1);
+  f0[1] = l1*(2*l1-1);
+  f0[2] = l2*(2*l2-1);
+  f0[3] = 4*l1*l2; // oppose au sommet 0
+  f0[4] = 4*l0*l2; // oppose au sommet 1
+  f0[5] = 4*l1*l0; // oppose au sommet 3
+  }
+ if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+ {
+   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2));
+  if (whatd[op_dx])
+  {
+    RN_ f0x(val('.',0,op_dx)); 
+  f0x[0] = Dl0.x*l4_0;
+  f0x[1] = Dl1.x*l4_1;
+  f0x[2] = Dl2.x*l4_2;
+  f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) ;
+  f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) ;
+  f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) ;
+  }
+
+ if (whatd[op_dy])
+  {  
+    RN_ f0y(val('.',0,op_dy)); 
+  f0y[0] = Dl0.y*l4_0;
+  f0y[1] = Dl1.y*l4_1;
+  f0y[2] = Dl2.y*l4_2;
+  f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1) ;
+  f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2) ;
+  f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0) ;
+  }
+ 
+ if (whatd[op_dxx])
+  {  
+    RN_ fxx(val('.',0,op_dxx)); 
+
+    fxx[0] = 4*Dl0.x*Dl0.x;
+    fxx[1] = 4*Dl1.x*Dl1.x;
+    fxx[2] = 4*Dl2.x*Dl2.x;
+    fxx[3] =  8*Dl1.x*Dl2.x;
+    fxx[4] =  8*Dl0.x*Dl2.x;
+    fxx[5] =  8*Dl0.x*Dl1.x;
+  }
+
+ if (whatd[op_dyy])
+  {  
+    RN_ fyy(val('.',0,op_dyy)); 
+    fyy[0] = 4*Dl0.y*Dl0.y;
+    fyy[1] = 4*Dl1.y*Dl1.y;
+    fyy[2] = 4*Dl2.y*Dl2.y;
+    fyy[3] =  8*Dl1.y*Dl2.y;
+    fyy[4] =  8*Dl0.y*Dl2.y;
+    fyy[5] =  8*Dl0.y*Dl1.y;
+  }
+ if (whatd[op_dxy])
+  {  
+    assert(val.K()>op_dxy);
+    RN_ fxy(val('.',0,op_dxy)); 
+  
+    fxy[0] = 4*Dl0.x*Dl0.y;
+    fxy[1] = 4*Dl1.x*Dl1.y;
+    fxy[2] = 4*Dl2.x*Dl2.y;
+    fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+    fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+    fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+  }
+ 
+ }
+ 
+}
+
+
+void TypeOfFE_P2bLagrange::FB(const bool *whatd,const Mesh & ,const Triangle & K,const R2 & P,RNMK_ & val) const
+{
+//  const Triangle & K(FE.T);
+  R2 A(K[0]), B(K[1]),C(K[2]);
+  R l0=1-P.x-P.y,l1=P.x,l2=P.y,lb=l0*l1*l2*3.;  
+  R l4_0=(4*l0-1),l4_1=(4*l1-1),l4_2=(4*l2-1); 
+  
+//  throwassert(FE.N == 1);  
+  throwassert( val.N()>=7);
+  throwassert(val.M()==1);
+//  throwassert(val.K()==3 );
+  
+  val=0; 
+// --     
+ if (whatd[op_id])
+  {
+   R lb4=lb*4;
+   RN_ f0(val('.',0,op_id)); 
+  f0[0] = l0*(2*l0-1)+lb;
+  f0[1] = l1*(2*l1-1)+lb;
+  f0[2] = l2*(2*l2-1)+lb;
+  f0[3] = 4*l1*l2-lb4; // oppose au sommet 0
+  f0[4] = 4*l0*l2-lb4; // oppose au sommet 1
+  f0[5] = 4*l1*l0-lb4; // oppose au sommet 3
+  f0[6] = 9*lb;
+  
+  }
+ if(  whatd[op_dx] || whatd[op_dy] || whatd[op_dxx] || whatd[op_dyy] ||  whatd[op_dxy])
+ {
+   R2 Dl0(K.H(0)), Dl1(K.H(1)), Dl2(K.H(2)),     Dlb((Dl0*l1*l2+Dl1*l0*l2+Dl2*l0*l1)*3.),
+    Dlb4(Dlb*4.);
+
+  if (whatd[op_dx])
+  {
+    RN_ f0x(val('.',0,op_dx)); 
+  f0x[0] = Dl0.x*l4_0 +Dlb.x;
+  f0x[1] = Dl1.x*l4_1 +Dlb.x;
+  f0x[2] = Dl2.x*l4_2 +Dlb.x;
+  f0x[3] = 4*(Dl1.x*l2 + Dl2.x*l1) -Dlb4.x;
+  f0x[4] = 4*(Dl2.x*l0 + Dl0.x*l2) -Dlb4.x;
+  f0x[5] = 4*(Dl0.x*l1 + Dl1.x*l0) -Dlb4.x;
+  f0x[6] = 9.*Dlb.x;
+  }
+
+ if (whatd[op_dy])
+  {  
+   RN_ f0y(val('.',0,op_dy)); 
+  f0y[0] = Dl0.y*l4_0  +Dlb.y;
+  f0y[1] = Dl1.y*l4_1  +Dlb.y;
+  f0y[2] = Dl2.y*l4_2  +Dlb.y;
+  f0y[3] = 4*(Dl1.y*l2 + Dl2.y*l1)  -Dlb4.y;
+  f0y[4] = 4*(Dl2.y*l0 + Dl0.y*l2)  -Dlb4.y;
+  f0y[5] = 4*(Dl0.y*l1 + Dl1.y*l0)  -Dlb4.y;
+  f0y[6] = 9*Dlb.y;
+  
+  }
+ 
+ if (whatd[op_dxx])
+  {  
+    RN_ fxx(val('.',0,op_dxx)); 
+    R lbdxx= 6*((Dl0.x*Dl1.x)*l2+(Dl1.x*Dl2.x)*l0+(Dl2.x*Dl0.x)*l1);
+    R lbd4xx= 4*lbdxx;
+
+    fxx[0] = 4*Dl0.x*Dl0.x  + lbdxx;
+    fxx[1] = 4*Dl1.x*Dl1.x  + lbdxx;;
+    fxx[2] = 4*Dl2.x*Dl2.x  + lbdxx;;
+    fxx[3] = 8*Dl1.x*Dl2.x  - lbd4xx;
+    fxx[4] = 8*Dl0.x*Dl2.x  - lbd4xx;
+    fxx[5] = 8*Dl0.x*Dl1.x  - lbd4xx;
+    fxx[6] = 9*lbdxx;  
+      }
+
+ if (whatd[op_dyy])
+  {  
+    RN_ fyy(val('.',0,op_dyy)); 
+    R lbdyy= 6*((Dl0.y*Dl1.y)*l2+(Dl1.y*Dl2.y)*l0+(Dl2.y*Dl0.y)*l1);
+    R lbd4yy= lbdyy*4;  
+ 
+    fyy[0] = 4*Dl0.y*Dl0.y + lbdyy;
+    fyy[1] = 4*Dl1.y*Dl1.y + lbdyy;
+    fyy[2] = 4*Dl2.y*Dl2.y + lbdyy;
+    fyy[3] = 8*Dl1.y*Dl2.y - lbd4yy;
+    fyy[4] = 8*Dl0.y*Dl2.y - lbd4yy;
+    fyy[5] = 8*Dl0.y*Dl1.y - lbd4yy;
+    fyy[6] = 9*lbdyy;  
+    
+  }
+ if (whatd[op_dxy])
+  {  
+    assert(val.K()>op_dxy);
+    RN_ fxy(val('.',0,op_dxy)); 
+    R lbdxy= 3*(Dl0.x*Dl1.y+ Dl0.y*Dl1.x)*l2+(Dl1.x*Dl2.y+Dl1.y*Dl2.x)*l0+(Dl2.x*Dl0.y+Dl2.y*Dl0.x)*l1;  
+    R lbd4xy= lbdxy*4;  
+  
+    fxy[0] = 4*Dl0.x*Dl0.y + lbdxy;
+    fxy[1] = 4*Dl1.x*Dl1.y + lbdxy;
+    fxy[2] = 4*Dl2.x*Dl2.y + lbdxy;
+    fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x) - lbd4xy;
+    fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x) - lbd4xy;
+    fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x) - lbd4xy;
+    fxy[6] =  9.*lbdxy;
+  }
+ 
+ }
+ 
+}
+/*
+ void TypeOfFE_P1Lagrange::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j,  void * arg) const
+{
+  const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1) };
+   for (int i=0;i<3;i++)
+     {  
+     f(v,K.T(Pt[i]),K,i,Pt[i],arg),val[i]=*(v+j);}
+ 
+}
+ void TypeOfFE_P2Lagrange::Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int j, void * arg) const
+{
+  const R2 Pt[] = { R2(0,0), R2(1,0), R2(0,1),R2(0.5,0.5),R2(0,0.5),R2(0.5,0) };
+   for (int i=0;i<6;i++)
+     {
+     f(v,K.T(Pt[i]),K,i,Pt[i],arg),val[i]=*(v+j);}
+ 
+}
+*/
+ 
+ 
+//TypeOfFE  P1Lagrange(1,0,0,P1Functions,D2_P1Functions,P1Interpolant,DataP1Lagrange);
+//TypeOfFE  P2Lagrange(1,1,0,P2Functions,D2_P2Functions,P2Interpolant,DataP2Lagrange,3);
+
+//  case of   fine mesh   
+class TypeOfMortarCas1: public TypeOfMortar { 
+  friend class FESpace;
+  friend class FMortar;
+  friend class ConstructDataFElement;
+  protected:
+  int NbLagrangeMult(const Mesh &,const Mortar &M) const ;
+ 
+   int NbDoF(const Mesh &,const Mortar &M,int i) const 
+     { int l(M.NbLeft()),r(M.NbRight());
+       int n =Max(l,r);
+       int mn=Min(l,r);
+       return (l+r)*(NbDfOnVertex + NbDfOnEdge) + (n+1)*NbDfOnVertex + n*NbDfOnEdge -mn-1; 
+      }
+  int NbOfNodes(const Mesh &,const Mortar &M) const // call one time  
+     {int l(M.NbLeft()),r(M.NbRight()); return (l+r)*(vertex_is_node+edge_is_node)+1;}
+  int NbDoF(const Mesh &,const Mortar &M) const 
+     { int l(M.NbLeft()),r(M.NbRight());
+       int n =Max(l,r);
+       int mn=Min(l,r);
+       return (l+r)*(NbDfOnVertex + NbDfOnEdge) + (n+1)*NbDfOnVertex + n*NbDfOnEdge -mn-1; 
+      }
+  
+   int NodeOfDF(const FESpace &Vh,const Mortar &M,int i) const 
+     {ffassert(0);return 0;}
+   int DFOfNode(const FESpace &Vh,const Mortar &M,int i) const 
+     {ffassert(0);return 0;}
+   void ConstructionOfNode(const Mesh &Th,int im,int * NodesOfElement,int *FirstNodeOfElement,int &lastnodenumber) const;
+   void ConsTheSubMortar(FMortar & ) const; 
+     
+   const int vertex_is_node,edge_is_node;
+  public: 
+    TypeOfMortarCas1 (int i,int j): TypeOfMortar(i,j),
+      vertex_is_node(i?1:0),edge_is_node(j?1:0) {};
+     
+}  MortarCas1P2(1,1) ;
+
+ const TypeOfMortar & TheMortarCas1P2(MortarCas1P2); 
+ 
+
+void TypeOfMortarCas1::ConstructionOfNode(const Mesh &Th,int im,int * NodesOfElement,int *FirstNodeOfElement,int &lastnodenumber) const
+{  
+  // im   mortar number 
+ // trop complique on change 
+  //  const Mortar &M(Th.mortars[im]);
+             int k = Th.nt+im;
+             int  kk=FirstNodeOfElement[k]; //  begin   
+             // lagrange  multiplicator one new node 
+              NodesOfElement[kk++] = lastnodenumber++;
+/*                               
+             int il = M.NbLeft();
+             int ir = M.NbRight();
+             int ir1 = ir-1;
+             //  left
+             
+             for( int j=0;j<il;j++)  //  numbering vertex0 edge vertex1
+              { 
+                int K = M.TLeft(j);  // triangle
+                int e = M.ELeft(j);  //  edge
+                int nbneK = FirstNodeOfElement[K];
+                int oe = vertex_is_node ? 3 : 0;
+                int i0 = VerticesOfTriangularEdge[e][0];
+                int i1 = VerticesOfTriangularEdge[e][1];
+                if (vertex_is_node && !j)   //  just the first time 
+                   NodesOfElement[kk++]=NodesOfElement[nbneK +i0];
+                if (edge_is_node)
+                   NodesOfElement[kk++]=NodesOfElement[nbneK+oe+e];
+                if (vertex_is_node )  
+                   NodesOfElement[kk++]=NodesOfElement[nbneK +i1];
+              }
+
+             //  right 
+             for( int j=0;j<ir;j++)  //  numbering vertex0 edge vertex1
+              { 
+                int K = M.TRight(j);  // triangle
+                int e = M.ERight(j);  //  edge
+                int nbneK = FirstNodeOfElement[K];
+                int oe = vertex_is_node ? 3 : 0;
+                
+                int i0 = VerticesOfTriangularEdge[e][1]; //  change the sens because right side
+                int i1 = VerticesOfTriangularEdge[e][0];
+              //  if (vertex_is_node &&  !j)   // never 
+               //    NodesOfElement[kk++]=NodesOfElement[nbneK +i0];
+                if (edge_is_node) 
+                   NodesOfElement[kk++]=NodesOfElement[nbneK+oe+e];
+                if (vertex_is_node  && (j != ir1) )  //  skip the last 
+                   NodesOfElement[kk++]=NodesOfElement[nbneK +i1];
+              } */
+              
+              throwassert(FirstNodeOfElement[k+1]==kk);
+}
+
+ R  d1P1F0(const FESpace *,const aSubFMortar *,R x) {return 1-x;}// 1 on 0
+ R  d1P1F1 (const FESpace *,const aSubFMortar *,R x) {return x;}//  1 on 1
+ 
+ R  d1P2F0 (const FESpace *,const aSubFMortar *,R x) {return (1-x)*(1-2*x);}// 1 on x=0
+ R  d1P2F1(const FESpace *,const aSubFMortar *,R x) {return (1-x)*x*4;} // 1 on x=1/2
+ R  d1P2F2(const FESpace *,const aSubFMortar *,R x) {return x*(2*x-1);} // 1 on x=1
+ 
+ void  TypeOfMortarCas1::ConsTheSubMortar(FMortar & sm) const
+   { //  constuction of 
+   /* 
+     int nbsm; // nb of submortar
+  aSubFMortar * sm;
+  ~FMortar() { delete [] dataDfNumberOFmul; delete [] dataf;}
+  private:
+  
+  int *dataDfNumberOFmul;
+   R (**dataf)(const FESpace *,const aSubFMortar *,R);
+
+   */
+   //  typedef
+     //     const Mesh &Th(sm.Vh.Th);
+     const Mortar & M(sm.M);
+     int nl=M.NbLeft();
+     int nr=M.NbRight();
+     int nbsm= nl+nr-1;
+     sm.nbsm = nbsm;
+     int ldata = 6*nbsm;// 3 gauche+ 3 droite 
+     sm.sm = new aSubFMortar[nbsm];
+     sm.datai = new int [ldata];
+     typedef  R (* Fdataf)(const FESpace *,const aSubFMortar *,R);
+     sm.dataf =new Fdataf[ldata]; //  new (R (*[ldata])(const FESpace *,const aSubFMortar *,R))  ;
+     ffassert( sm.dataf ); //  remove previous line FH, PB comp
+     int *dataDfNumberOFmul=sm.datai;
+     
+     R (**dataf)(const FESpace *,const aSubFMortar *,R) ;
+     dataf=sm.dataf;
+     for (int i=0;i<ldata;i++) sm.dataf[i]=0;
+   //  int * data0=sm.data+ldata;
+   //  int * data1=data0+ldata;
+     
+     //  now the construction 
+     // int l=0,g=0;
+     R2 A(M.VLeft(0));
+     R2 B(M.VLeft(nl));
+     ffassert(&M.VLeft(0) == &M.VRight(0));
+     ffassert(&M.VLeft(nl) == &M.VRight(nr));
+    
+     R2 AB(A,B);
+     R lg=Norme2(AB);
+    // cout << " Mortar from " << A << " to " << B << " = " <<lg << endl;
+     R2 AB1(AB/lg);
+     int il=0,ir=0;
+     int k=0;
+     R la=0.0;
+     R lb=0.0;
+     R2 AA(A),BB(A);
+   //  cout << "lg : " <<lg ;
+     do {
+       sm.sm[k].left  = M.left[il];
+       sm.sm[k].right =  M.right[ir];
+       R2 Bl(M.VLeft(il+1));
+       R2 Br(M.VRight(ir+1));
+       R ll=(AB1,Bl-A), lr=(AB1,Br-A);
+     //  throwassert ( ll >=0 && lr >= 0);
+     //  throwassert ( ll <=lg  && lr <= lg);
+       
+   //    cout << "AA , BB = " << AA << "," << BB << endl;
+    //   cout << " " << ll << " " << lr << " ll=" << sm.sm[k].left << ", ";
+       if (ll<lr) {BB=Bl,lb=ll,il++;} else {BB=Br, lb=lr,ir++;}
+  //     cout << k << " " << k << " " << la/lg << " " << lb/lg << endl;
+       sm.sm[k].a = la/lg;
+       sm.sm[k].b = lb/lg;
+       sm.sm[k].A=AA;
+       sm.sm[k].B=BB;       
+       la=lb;
+       AA=BB;
+       k++;
+       throwassert(k<=nbsm);
+     } while (il<nl && ir < nr);
+     
+  //   cout << "k=" << k <<endl;
+     ffassert(nbsm==Max(nl,nr)); 
+     //throwassert(nbsm<=k);
+    nbsm=k;
+    sm.nbsm=k;
+//   construction of interpolation 
+//  1) on a P1 on P2 
+//   P2  si les longueurs des aSubMortar precedende et suivant  sont les meme 
+//   sinon P1 
+   //  calcul de leps 
+     R leps=1.0/(1048576.0) ; // 1/2^20 
+     R lgp=0;
+     R lgc=0;
+     R lgs=sm.sm[0].lg1();
+    // cout << lgp << " " << lgc << " " << lgs << endl;
+     
+     int nmul=0;
+     for (int k=0;k<nbsm;k++) 
+       {
+         
+         lgp=lgc;
+         lgc=lgs;
+         lgs=  k+1 == nbsm  ? 0 : sm.sm[k+1].lg1();
+         sm.sm[k].DfNumberOFmul= dataDfNumberOFmul;
+         sm.sm[k].f=dataf;
+        // cout << lgp << " " << lgc << " " << lgs << " ";
+         if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
+          { // P2
+           sm.sm[k].Nbmul=3;
+           *dataDfNumberOFmul++=nmul++;
+           *dataDfNumberOFmul++=nmul++;
+           *dataDfNumberOFmul++=nmul;
+           *dataf++ = d1P2F0;
+           *dataf++ = d1P2F1;
+           *dataf++ = d1P2F2;
+          // cout << "P2 " << nmul << " " ;
+           
+          }
+         else 
+          { // P1
+                   sm.sm[k].Nbmul=2;
+           *dataDfNumberOFmul++=nmul++;
+           *dataDfNumberOFmul++=nmul;
+           *dataf++ = d1P1F0;
+           *dataf++ = d1P1F1;
+          // cout << "P1 " << nmul << " " ;
+           
+
+          }
+       }
+      nmul++;
+     // cout << " " << nmul << " " <<  sm.NbDoF(0) << endl;
+      ffassert(nmul==sm.NbDoF(0));
+     
+   }
+   
+  int TypeOfMortarCas1::NbLagrangeMult(const Mesh &,const Mortar &M) const 
+     { 
+       int nl = M.NbLeft();
+       int nr = M.NbRight();
+       R2 A(M.VLeft(0));
+       R2 B(M.VLeft(nl));
+       R2 AB(A,B);
+       R lg=Norme2(AB);
+       R leps = lg/1048576.0;
+       ffassert(nl==1 || nr==1);
+       R lgp=0,lgc=0,lgs=0;
+       int nbmul=3; 
+       if (nr==1) 
+        {
+        R2 AA(M.VLeft(0)),BB(M.VLeft(1));
+        lgp= Norme2(BB-AA); // preced
+        AA=BB;
+        BB=M.VLeft(2); 
+        lgc= Norme2(BB-AA); // courant 
+        
+        for (int i=1;i<nl-1;i++)
+         { 
+            AA=BB;
+            BB=M.VLeft(i+2); 
+            lgs=Norme2(AA-BB); // le suivant 
+            if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
+              nbmul+=2; // P2
+            else 
+              nbmul+=1;// P1;
+            lgp=lgc;
+            lgc=lgs;
+            
+         }
+        }
+        else
+        {
+        R2 AA(M.VRight(0)),BB(M.VRight(1));
+        lgp= Norme2(BB-AA); // preced
+        AA=BB;
+        BB=M.VRight(2); 
+        lgc= Norme2(BB-AA); // courant 
+        
+        for (int i=1;i<nr-1;i++)
+         { 
+            AA=BB;
+            BB=M.VRight(i+2); 
+            lgs=Norme2(AA-BB); // le suivant 
+            if ( Abs(lgp-lgc) < leps && Abs(lgs-lgc) < leps )
+              nbmul+=2; // P2
+            else 
+              nbmul+=1;// P1;
+            lgp=lgc;
+            lgc=lgs;
+            
+         }
+        }
+       ffassert(nbmul>2);
+       return nbmul;
+      }  
+
+ 
+// --- 
+ FMortar::FMortar(const FESpace * VVh,int k)
+  : 
+    Vh(*VVh),
+    M(Vh.Th.mortars[k-Vh.Th.nt]),
+    p(Vh.PtrFirstNodeOfElement(k)),
+    nbn(Vh.NbOfNodesInElement(k)),
+    N(VVh->N),
+    tom(Vh.tom)
+    
+ { ffassert(k>=Vh.Th.nt && k <Vh.Th.nt + Vh.Th.NbMortars);
+   VVh->tom->ConsTheSubMortar(*this);}
+   
+ R TypeOfFE::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const 
+  {
+   R v[10000],vf[1000];
+   assert(N*3*NbDoF<=10000 && NbDoF <1000 );
+   KNMK_<R> fb(v,NbDoF,N,op+1); //  the value for basic fonction
+   KN_<R> fk(vf,NbDoF);
+   for (int i=0;i<NbDoF;i++) // get the local value
+    fk[i] = u[K(i)];
+    //  get value of basic function
+   bool whatd[last_operatortype];
+   for (int i=0;i<last_operatortype;i++) 
+     whatd[i]=false;
+   whatd[op]=true;
+   FB(whatd,K.Vh.Th,K.T,PHat,fb);  
+   R r = (fb('.',componante,op),fk);  
+   return r;
+  }
+ 
+static TypeOfFE_P1Lagrange P1LagrangeP1;
+static TypeOfFE_P0VF VFP0VF;
+static TypeOfFE_P1Bubble P1BubbleP1;
+static TypeOfFE_P2Lagrange P2LagrangeP2;
+static TypeOfFE_P2bLagrange P2bLagrangeP2;
+
+TypeOfFE  & P2Lagrange(P2LagrangeP2);
+TypeOfFE  & P2bLagrange(P2bLagrangeP2);
+TypeOfFE  & P1Bubble(P1BubbleP1);
+TypeOfFE  & P1Lagrange(P1LagrangeP1);
+TypeOfFE  & P0VF(VFP0VF);
+
+static ListOfTFE typefemP1("P1", &P1LagrangeP1);
+static ListOfTFE typefemP0VF("P0VF", &P0VF);  // 
+static ListOfTFE typefemP1b("P1b", &P1BubbleP1);
+static ListOfTFE typefemP2("P2", &P2LagrangeP2);
+static  ListOfTFE typefemRT("RT0", &RTLagrange);
+static  ListOfTFE typefemRTOrtho("RT0Ortho", &RTLagrangeOrtho);
+ 
+ extern  TypeOfFE & RTmodifLagrange, & P1ttdc, & P2ttdc,   & P0edge;
+ static  ListOfTFE typefemRTmodif("RTmodif", &RTmodifLagrange);
+ static ListOfTFE typefemP0("P0", &P0Lagrange);
+ static ListOfTFE typefemP1nc("P1nc", &P1ncLagrange);
+ static ListOfTFE typefemP1ttdc("P1dc", &P1ttdc);
+ static ListOfTFE typefemP2ttdc("P2dc", &P2ttdc);
+ static ListOfTFE typefemP2b("P2b", &P2bLagrangeP2);
+ 
+ static ListOfTFE typefemP0edge("P0edge", &P0edge);
+
+// correct Probleme of static library link with new make file 
+void init_static_FE()
+{ //  list of other FE file.o 
+   extern void init_FE_P2h() ;
+  init_FE_P2h() ;
+}
+ 
+} // fin de namespace Fem2D 
diff --git a/src/femlib/FESpace.hpp b/src/femlib/FESpace.hpp
new file mode 100644
index 0000000..5a585e5
--- /dev/null
+++ b/src/femlib/FESpace.hpp
@@ -0,0 +1,883 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef FESpace_h_
+#define FESpace_h_
+#include "FESpacen.hpp"
+
+#include <cstdarg>
+
+namespace  Fem2D {
+  class FESpace; 
+class TypeOfFE;
+  /*
+// numbering of derivative 
+enum operatortype { op_id=0,
+   op_dx=1,op_dy=2,
+   op_dxx=3,op_dyy=4,
+   op_dyx=5,op_dxy=5,   
+   op_dz=6,
+   op_dzz=7,     
+   op_dzx=8,op_dxz=8, 
+   op_dzy=9,op_dyz=9   
+   }; 
+    
+const int last_operatortype=10;
+ 
+
+inline void initwhatd(bool *whatd,int k)
+{
+  for (int i=0;i<last_operatortype;i++)
+    whatd[i]=false;    
+  whatd[k]=true;
+}
+  */
+typedef KN_<R> RN_;
+typedef KN<R>  RN;
+typedef KNM_<R> RNM_;
+//typedef KNM<R>  RNM;
+typedef KNMK_<R> RNMK_;
+typedef KNMK<R>  RNMK;
+
+inline int FindIn(int v,int *a,int n)
+{
+  for (int i=0;i<n;i++)
+    if( v==a[i]) return i;
+  return -1;
+};
+
+
+//  Methode boeuf 
+//    on suppose que pour chaque elment fini
+// on sait calculer 
+//   un tableau de point x,y 
+// les valeur de la fonction et des derives
+// FB(RN_<R2> 
+// i  =  df
+// j  = [0 N[  (ou N est la dim de l'espace d'arrive N=3 
+// k = 0,1,2   f,fx,fy 
+
+
+class FElement;
+class baseFElement;
+class FMortar;
+class TypeOfMortar;
+
+//  for FE
+//typedef void  (* basicFunction)(const FElement & FE,const R2 &P, RNMK_ & val);
+typedef void  (* InterpolFunction)(R* v, const R2 & P,const baseFElement &,int where,const R2 & Phat, void * arg);
+//typedef void (*InterpolantFunction)(const FElement & FE,RN_ & val, InterpolFunction f, R* v);
+//  for FM   ( Finite Mortar  Mortar + interpolation)
+typedef void  (* basicFunctionMortar)(const FMortar & FE,const R2 &P, RNMK_ & val);
+typedef void  (* InterpolFunctionMortar)(R* v, const R2 & P,const Mortar &,int where,const R2 & Phat);
+typedef void  (*InterpolantFunctionMortar)(const FMortar & FE,RN_ & val, InterpolFunctionMortar f, R* v);
+
+//void P1Functions(const FElement &FE,const R2 & P,RNMK_ & val);
+//void P2Functions(const FElement &FE,const R2 & P,RNMK_ & val);
+
+
+class VofScalarFE { 
+  R v[3];
+  public:
+  VofScalarFE() {v[0]=v[1]=v[2]=0;}
+  VofScalarFE(R f,R fx,R fy) {v[0]=f;v[1]=fx;v[2]=fy;}
+
+  R & operator[](int i){ return v[i];}
+  const R & operator[](int i) const { return v[i];}  
+  R f()  { return v[0];}
+  R fx() { return v[1];}
+  R fy() { return v[2];}
+ VofScalarFE &operator+=(const VofScalarFE & a) { v[0]+=a.v[0]; v[1]+=a.v[1]; v[2]+=a.v[2];return *this;}  
+};
+
+class ConstructDataFElement {
+  friend class FESpace;
+  //int thecounter; //  chang 09/2008 the counter is a pointer because 
+    //  if you remove before the master the counter become invalide. 
+  int * counter;
+  int MaxNbNodePerElement;
+  int MaxNbDFPerElement;
+  int *NodesOfElement;
+  int *FirstNodeOfElement;
+  int *FirstDfOfNode;
+  int NbOfElements;
+  int NbOfDF;
+  int NbOfNode;
+  int Nproduit;
+  ConstructDataFElement(const Mesh &Th,/*int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,*/
+  const  KN<const TypeOfFE *> & TFEs,const TypeOfMortar *tm=0,
+  int nbdfv=0,const int *ndfv=0,int nbdfe=0,const int *ndfe=0);
+  ConstructDataFElement(const ConstructDataFElement *,int k);
+  ConstructDataFElement(const FESpace ** l,int k,const  KN<const TypeOfFE *> & TFEs) ;
+  void renum(const long *r,int l)  ; 
+  ~ConstructDataFElement();
+ void Make(const Mesh &Th,/*int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement*/const  KN<const TypeOfFE *> & TFEs,const TypeOfMortar *tm=0,
+   int nbdfv=0,const int *ndfv=0,int nbdfe=0,const int *ndfe=0);
+private:
+    static int *NewCounter() { int * p=new int; *p=0;return p;}// add the build thecounter. 
+};
+
+template<class T>
+inline int sum(const T ** l,int const T::*p,int n)
+  {
+    int r=0;
+    for (int i=0;i<n;i++)
+     r += l[i]->*p;
+     return r;
+  }
+  
+template<class T>
+inline int max(const T ** l,int const T::*p,int n)
+  {
+    int r=0;
+    for (int i=0;i<n;i++)
+     r =Max( l[i]->*p,r);
+     return r;
+  }
+ 
+ 
+class TypeOfFE { public:
+//  The FEM is in R^N
+//  The FEM is compose from nb_sub_fem
+//  dim_which_sub_fem[N] give
+    typedef R2 RdHat;  // add avril 2009 FH
+    typedef R2 Rd;  // add avril 2009 FH
+
+
+  friend class FESpace;
+  friend class FElement;
+  friend class FEProduitConstruct;
+  const int NbDoF;
+  const int NbNodeOnVertex, NbNodeOnEdge, NbNodeOnElement;
+  const int NbDfOnVertex, NbDfOnEdge, NbDfOnElement, N,nb_sub_fem;
+  const  int NbNode;
+  //  remark 
+ // virtual void FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const =0;
+  virtual void FB(const bool *,const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const =0;
+//  virtual void D2_FB(const Mesh & Th,const Triangle & K,const R2 &P, RNMK_ & val) const=0;
+ // virtual void Pi_h(const baseFElement & K,RN_ & val, InterpolFunction f, R* v,int , void *) const=0;
+  
+  // soit 
+  //  $(U_pj)_{{j=0,N-1}; {p=0,nbpoint_Pi_h-1}}$ les valeurs de U au point Phat[i];
+  //   p est le numero du point d'integration
+  //   j est la composante 
+  //  l'interpole est  defini par
+  //  Pi_h u = \sum_k u_k w^k , et u_i = \sum_pj alpha_ipj U_pj
+  //  la matrice de alpha_ipj est tres creuse
+  struct IPJ { 
+    int i,p,j; // i is DoF, p is Point, j is componante 
+    IPJ(int ii=0,int pp=0,int jj=0):i(ii),p(pp),j(jj) {}
+  };
+  
+  friend KN<IPJ> Makepij_alpha(const TypeOfFE **,int );
+  friend KN<R2> MakeP_Pi_h(const TypeOfFE **,int );
+ 
+   const KN<IPJ > & Ph_ijalpha() const {return pij_alpha;} // la struct de la matrice
+   const KN<R2> & Pi_h_R2() const { return P_Pi_h;}   // les points
+   virtual void Pi_h_alpha(const baseFElement & K,KN_<double> & v) const
+     {  assert(coef_Pi_h_alpha);
+        v=KN_<double>(coef_Pi_h_alpha,pij_alpha.N());}
+
+   //  ----  
+  
+  const int nbsubdivision; // nb of subdivision for plot
+   int const * const DFOnWhat; //  0,1,2 vertex 3,4,5 edge 6  triangle
+   int const * const DFOfNode; // n\u00c9 du df on Node
+   int const * const NodeOfDF; // 
+   int const * const fromFE;   //  the df  come from df of FE
+   int const * const fromDF;   //  the df  come from with FE
+   int const * const dim_which_sub_fem; // from atomic sub FE for CL (size N)
+   KN<IPJ > pij_alpha ;
+   KN<R2 > P_Pi_h ;
+  double *coef_Pi_h_alpha;
+   KN<TypeOfFE *> Sub_ToFE; //  List of atomic sub TFE avril 2006 
+    //  form Atomic Sub FE 
+   int const * const fromASubFE; //  avril 2006 for CL
+   int const * const fromASubDF; //  avril 2006 for CL
+  int const * const  begin_dfcomp; //  mai 2008 for optimiation 
+  int const  * const end_dfcomp; // mai 2008 
+   
+  // if 0  no plot 
+  public: 
+  
+    TypeOfFE(const TypeOfFE & t,int k,const int * data,const int * data1) 
+    : 
+      NbDoF(t.NbDoF*k),
+      NbNodeOnVertex(t.NbNodeOnVertex),NbNodeOnEdge(t.NbNodeOnEdge),NbNodeOnElement(t.NbNodeOnElement),
+      NbDfOnVertex(t.NbDfOnVertex*k),NbDfOnEdge(t.NbDfOnEdge*k),NbDfOnElement(t.NbDfOnElement*k),
+      N(t.N*k),nb_sub_fem(t.nb_sub_fem*k),
+      NbNode(t.NbNode), 
+     nbsubdivision(t.nbsubdivision),
+    DFOnWhat(data),
+    DFOfNode(data+NbDoF),
+    NodeOfDF(data+2*NbDoF),
+    fromFE(data+3*NbDoF),
+    fromDF(data+4*NbDoF),
+    dim_which_sub_fem(data+5*NbDoF),
+    pij_alpha(t.pij_alpha.N()*k),P_Pi_h(t.P_Pi_h),
+    coef_Pi_h_alpha(0),
+    Sub_ToFE(nb_sub_fem),
+    fromASubFE(data1+0*NbDoF),
+      fromASubDF(data1+1*NbDoF),
+      begin_dfcomp(data1+2*NbDoF),
+      end_dfcomp(data1+2*NbDoF+N)
+
+    { 
+       for(int i=0,kk=0;i<k;i++)
+        for (int j=0;j<t.nb_sub_fem;j++)
+          Sub_ToFE[kk++]=t.Sub_ToFE[j];
+       assert(begin_dfcomp[0]==0 && end_dfcomp[N-1]==NbDoF);
+       
+      throwassert(dim_which_sub_fem[N-1]>=0 && dim_which_sub_fem[N-1]< nb_sub_fem);
+     // Warning the componant is moving first 
+        for (int j=0,l=0;j<t.pij_alpha.N();j++) // for all sub DF
+          for(int i=0; i<k; i++,l++) // for componate
+          {
+          pij_alpha[l].i=t.pij_alpha[j].i*k+i;   //  DoF number
+          pij_alpha[l].p=t.pij_alpha[j].p;       //  point of interpolation
+          pij_alpha[l].j=t.pij_alpha[j].j+i*t.N; //  componante of interpolation
+          }                         
+    } 
+       
+    TypeOfFE(const TypeOfFE ** t,int k,const int * data,const int * data1) 
+    : 
+      NbDoF(sum(t,&TypeOfFE::NbDoF,k)),
+      NbNodeOnVertex(NbNodebyWhat(data,NbDoF,0)),
+      NbNodeOnEdge(NbNodebyWhat(data,NbDoF,3)),
+      NbNodeOnElement(NbNodebyWhat(data,NbDoF,6)),
+      NbDfOnVertex(sum(t,&TypeOfFE::NbDfOnVertex,k)),
+      NbDfOnEdge(sum(t,&TypeOfFE::NbDfOnEdge,k)),
+      NbDfOnElement(sum(t,&TypeOfFE::NbDfOnElement,k)),
+      N(sum(t,&TypeOfFE::N,k)),nb_sub_fem(sum(t,&TypeOfFE::nb_sub_fem,k)),
+      NbNode( (NbDfOnVertex ? 3 :0) + (NbDfOnEdge ? 3 :0 ) +(NbDfOnElement? 1 :0) ),      
+      nbsubdivision(max(t,&TypeOfFE::nbsubdivision,k)),
+      
+    DFOnWhat(data),
+    DFOfNode(data+NbDoF),
+    NodeOfDF(data+2*NbDoF),
+    fromFE(data+3*NbDoF),
+    fromDF(data+4*NbDoF),
+    dim_which_sub_fem(data+5*NbDoF),
+    pij_alpha(Makepij_alpha(t,k)),
+    P_Pi_h(MakeP_Pi_h(t,k)),
+    coef_Pi_h_alpha(0),
+    Sub_ToFE(nb_sub_fem),
+    fromASubFE(data1+0*NbDoF),
+      fromASubDF(data1+1*NbDoF),
+      begin_dfcomp(data1+2*NbDoF),
+      end_dfcomp(data1+2*NbDoF+N)    
+  {
+    for(int i=0,kk=0;i<k;i++)
+      for (int j=0;j<t[i]->nb_sub_fem;j++)
+	Sub_ToFE[kk++]=t[i]->Sub_ToFE[j];
+    assert(begin_dfcomp[0]==0 && end_dfcomp[N-1]==NbDoF);
+       
+    Sub_ToFE= this;
+    throwassert(dim_which_sub_fem[N-1]>=0 && dim_which_sub_fem[N-1]< nb_sub_fem);} 
+
+  TypeOfFE(const int i,const int j,const int k,const int NN,const  int  *   data,int nsub,int nbsubfem,
+    int kPi,int npPi,double * coef_Pi_h_a=0) 
+   : NbDoF(3*(i+j)+k),
+     NbNodeOnVertex(NbNodebyWhat(data,NbDoF,0)),
+     NbNodeOnEdge(NbNodebyWhat(data,NbDoF,3)),
+     NbNodeOnElement(NbNodebyWhat(data,NbDoF,6)),     
+/*     NbDfOnVertex(Count(data,NbDoF,0)),
+     NbDfOnEdge(Count(data,NbDoF,3)),
+     NbDfOnElement(Count(data,NbDoF,6)),
+ */  
+     NbDfOnVertex(i),NbDfOnEdge(j),NbDfOnElement(k),N(NN),nb_sub_fem(nbsubfem),
+     NbNode( (NbDfOnVertex ? 3 :0) + (NbDfOnEdge ? 3 :0 ) +(NbDfOnElement? 1 :0) ),
+    nbsubdivision(nsub),
+    DFOnWhat(data),
+    DFOfNode(data+NbDoF),
+    NodeOfDF(data+2*NbDoF),
+    fromFE(data+3*NbDoF),
+    fromDF(data+4*NbDoF),
+    dim_which_sub_fem(data+5*NbDoF),
+    pij_alpha(kPi),P_Pi_h(npPi),
+    coef_Pi_h_alpha(coef_Pi_h_a),
+    Sub_ToFE(nb_sub_fem),
+     fromASubFE(data+3*NbDoF),
+     fromASubDF(data+4*NbDoF),
+     begin_dfcomp(data+5*NbDoF+N),
+     end_dfcomp(data+5*NbDoF+2*N)    
+     { 
+      Sub_ToFE= this;
+      assert(begin_dfcomp[0]==0 && end_dfcomp[N-1]==NbDoF);
+     // cout << "TypeOfFE " <<NbDoF << " : " << NbDfOnVertex << " " << NbDfOnEdge << " " << NbDfOnElement << 
+     // " : " << NbNodeOnVertex << " " << NbNodeOnEdge << " " << NbNodeOnElement << endl;
+      assert(NbDfOnVertex==Count(data,NbDoF,0));
+      assert(NbDfOnVertex==Count(data,NbDoF,1));
+      assert(NbDfOnVertex==Count(data,NbDoF,2));
+      assert(NbDfOnEdge==Count(data,NbDoF,3));
+      assert(NbDfOnEdge==Count(data,NbDoF,4));
+      assert(NbDfOnEdge==Count(data,NbDoF,5));
+      assert(NbDfOnElement==Count(data,NbDoF,6));
+      
+      throwassert(dim_which_sub_fem[N-1]>=0 && dim_which_sub_fem[N-1]< nb_sub_fem);} 
+      
+  TypeOfFE(const int nbdf,const int NN,const  int  *   data,int nsub,int nbsubfem,
+    int kPi,int npPi,double * coef_Pi_h_a=0) 
+   : 
+     NbDoF(nbdf),
+     NbNodeOnVertex(NbNodebyWhat(data,NbDoF,0)),
+     NbNodeOnEdge(NbNodebyWhat(data,NbDoF,3)),
+     NbNodeOnElement(NbNodebyWhat(data,NbDoF,6)),     
+     NbDfOnVertex(Count(data,NbDoF,0)),
+     NbDfOnEdge(Count(data,NbDoF,3)),
+     NbDfOnElement(Count(data,NbDoF,6)),
+     N(NN),
+     nb_sub_fem(nbsubfem),
+     NbNode( (NbDfOnVertex ? 3 :0) + (NbDfOnEdge ? 3 :0 ) +(NbDfOnElement? 1 :0) ),
+    nbsubdivision(nsub),
+    DFOnWhat(data),
+    DFOfNode(data+NbDoF),
+    NodeOfDF(data+2*NbDoF),
+    fromFE(data+3*NbDoF),
+    fromDF(data+4*NbDoF),
+    dim_which_sub_fem(data+5*NbDoF),
+    pij_alpha(kPi),P_Pi_h(npPi),
+    coef_Pi_h_alpha(coef_Pi_h_a),
+    Sub_ToFE(nb_sub_fem) ,   
+    fromASubFE(data+3*NbDoF),
+     fromASubDF(data+4*NbDoF),
+     begin_dfcomp(data+5*NbDoF+N),
+     end_dfcomp(data+5*NbDoF+2*N)    
+
+     { 
+      Sub_ToFE= this;
+      assert(begin_dfcomp[0]==0 && end_dfcomp[N-1]==NbDoF);
+      assert(NbDfOnVertex==Count(data,NbDoF,0));
+      assert(NbDfOnVertex==Count(data,NbDoF,1));
+      assert(NbDfOnVertex==Count(data,NbDoF,2));
+      assert(NbDfOnEdge==Count(data,NbDoF,3));
+      assert(NbDfOnEdge==Count(data,NbDoF,4));
+      assert(NbDfOnEdge==Count(data,NbDoF,5));
+      assert(NbDfOnElement==Count(data,NbDoF,6));
+      
+      throwassert(dim_which_sub_fem[N-1]>=0 && dim_which_sub_fem[N-1]< nb_sub_fem);} 
+
+  virtual ~TypeOfFE() { }
+  virtual R operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op)
+ const ;
+ 
+ private:
+ static int Count(const int *data,int n,int which) 
+   {
+      int kk=0;
+      for (int i=0;i<n;++i)
+        if (which == data[i]) ++kk;
+      return kk;}
+      
+ static int LastNode(const int *data,int n) 
+   {
+      int kk=0,i0=2*n;
+      for(int i=0;i<n;i++)
+        kk=Max(kk,data[i+i0]);
+      return kk;}
+      
+static int NbNodebyWhat(const int *data,int n,int on) 
+  { 
+      const int nmax=100;
+      int t[nmax];
+      for (int i=0;i<n;i++)
+      	t[i]=0;
+       int k=0,i0=2*n;
+       for(int i=0;i<n;i++)
+          if ( data[i]==on)
+           { int node= data[i+i0];
+           //  cout << " node " << node << endl;
+             assert(node < nmax);
+            if( ! t[node] )
+               t[node] = 1,++k;
+            } 
+           
+//     cout << " on " << on << " k = " << k << endl;
+     return k;
+  }      
+      
+} ; 
+
+
+
+class aSubFMortar;
+
+class TypeOfMortar { 
+  friend class FESpace;
+  friend class FMortar;
+  friend class ConstructDataFElement;
+  virtual int NbLagrangeMult(const Mesh &Th,const Mortar &M) const =0;
+  virtual int NbDoF(const Mesh &Th,const Mortar &M,int i) const =0;
+  virtual int NbOfNodes(const Mesh &Th,const Mortar &M) const =0;
+  virtual int NbDoF(const Mesh &Th,const Mortar &M) const =0;
+  virtual int NodeOfDF(const FESpace &,const Mortar &M,int i) const =0;
+  virtual int DFOfNode(const FESpace &,const Mortar &M,int i) const =0;
+  virtual void ConstructionOfNode(const Mesh &Th,int im,int * NodesOfElement,int *FirstNodeOfElement,int &lastnodenumber) const=0; 
+  virtual void ConsTheSubMortar(FMortar &) const =0; 
+  protected:
+  const int NbDfOnVertex, NbDfOnEdge , N;
+  public: 
+    TypeOfMortar (int i,int j): NbDfOnVertex(i),NbDfOnEdge(j),N(1){};
+   
+  virtual  ~TypeOfMortar(){}
+     
+} ;
+
+class FElement; 
+
+  class baseFElement { public:
+      typedef Fem2D::FESpace FESpace;
+    typedef Fem2D::Mesh Mesh;
+    typedef Fem2D::Triangle Element;
+    typedef Fem2D::TypeOfFE  TypeOfFE;
+
+  const FESpace &Vh;  
+  const Triangle &T;
+  const TypeOfFE * tfe; 
+  const int N;
+  const int number;  
+  baseFElement(  const FESpace &aVh, int k) ;
+  baseFElement(const   baseFElement & K,  const TypeOfFE & atfe) ;
+  R EdgeOrientation(int i) const {return T.EdgeOrientation(i);}
+  //  : Vh(aVh),T(Vh.Th[k]),tfe(aVh.TFE[k]),N(aVh.N),number(k){}
+
+};
+
+class FElement : public baseFElement { public:
+  typedef const KN<TypeOfFE::IPJ> &  aIPJ;
+  typedef  TypeOfFE::IPJ   IPJ;
+  typedef const KN<R2> &  aR2;
+  
+  
+  friend class Fem2D::FESpace;
+  const int *p;
+  const int nb;
+  FElement(const FESpace * VVh,int k) ;
+  public:
+  int NbOfNodes()const {return nb;}
+  int  operator[](int i) const ;//{ return  p ? p+i :  ((&T[i])-Vh.Th.vertices);}  N\u00c9 du noeud 
+  int  NbDoF(int i) const ;  // number of DF 
+  int  operator()(int i,int df) const ;// { N\u00c9 du DoF du noeud i de df local df 
+  int  operator()(int df) const { return operator()(NodeOfDF(df),DFOfNode(df));}
+  void Draw(const KN_<R> & U, const  KN_<R> & VIso,int j=0) const ;  
+ 
+  template<class R>   
+  void SaveDraw(const KN_<R> & U,int j,R* Usave) const ;  
+  template<class R> 
+  void SaveDraw(const KN_<R> & U,const KN_<R> & V,int iU,int iV,R* UVsave) const ;  
+
+  void Drawfill(const KN_<R> & U, const  KN_<R> & VIso,int j=0,double rapz=1) const ;  
+  void Draw(const RN_& U,const RN_& V, const  KN_<R> & Viso,R coef,int i0,int i1) const;
+  R2   MinMax(const RN_& U,const RN_& V,int i0,int i1) const  ;
+  R2   MinMax(const RN_& U,int i0) const  ;
+  void BF(const R2 & P,RNMK_ & val) const;// { tfe->FB(Vh.Th,T,P,val);}
+  void BF(const bool * whatd, const R2 & P,RNMK_ & val) const;// { tfe->FB(Vh.Th,T,P,val);}
+ // void D2_BF(const R2 & P,RNMK_ & val) const ; //{ tfe->D2_FB(Vh.Th,T,P,val);}
+  void Pi_h(RN_ val,InterpolFunction f,R *v,  void * arg) const;//  {tfe->Pi_h(Vh.Th,T,val,f,v);}
+  aIPJ Pi_h_ipj() const { return tfe->Ph_ijalpha();}
+  aR2 Pi_h_R2() const { return tfe->Pi_h_R2();}
+  void Pi_h(KN_<R> & v) const { return tfe->Pi_h_alpha(*this,v);}
+  
+  int NbDoF() const { return tfe->NbDoF;}
+  int DFOnWhat(int i) const { return tfe->DFOnWhat[i];}
+  int FromDF(int i) const { return tfe->fromDF[i];}
+  int FromFE(int i) const { return tfe->fromFE[i];}
+ // df is the df in element 
+  int NodeOfDF(int df) const { return tfe->NodeOfDF[df];} // a node
+  int FromASubFE(int i) const { return tfe->fromASubFE[i];}
+  int FromASubDF(int i) const { return tfe->fromASubDF[i];}
+   int DFOfNode(int df) const { return tfe->DFOfNode[df];} // the df number on the node 
+
+  //  add Mai 2008 for optimization 
+  int dfcbegin(int ic) const { return this->tfe->begin_dfcomp[ic];}
+  int dfcend(int ic) const { return this->tfe->end_dfcomp[ic];}
+ 
+  R operator()(const R2 & PHat,const KN_<R> & u,int i,int op)  const ;
+  complex<R> operator()(const R2 & PHat,const KN_<complex<R> > & u,int i,int op)  const ;
+  
+ // FElementGlobalToLocal operator()(const KN_<R> & u ) const { return FElementGlobalToLocal(*this,u);}
+  private:
+  int nbsubdivision() const { return tfe->nbsubdivision;} // for draw 
+  };
+  
+  
+class aSubFMortar { public:
+  R a,b; 
+  R2 A,B; 
+  int left,right; //
+  int TLeft() const { return left/3;}
+  int ELeft() const{ return left%3;}
+  
+  int TRight() const{ return right/3;}
+  int ERight()const{ return right%3;}
+  
+  int * DfNumberOFmul;
+  int  Nbmul; 
+ // int *whatnode[2];
+  R (**f)(const FESpace *,const aSubFMortar * ,R); // array of function of mul on aSubMortar 
+  R lg1(){throwassert(a<b);return b-a;}  
+  aSubFMortar():DfNumberOFmul(0),Nbmul(0),f(0){}
+ 
+  R2 operator()(const Mesh & Th,R x,int side) const
+   {
+      int kk = side==0 ? left : right;
+      int k=kk/3;
+      int e=kk%3;
+      const Triangle & K(Th[k]);
+      int c = VerticesOfTriangularEdge[e][0];
+      int d = VerticesOfTriangularEdge[e][1];
+      
+      const R2 &C=K[c];
+      const R2 &D=K[d];
+      // $ [AB] include in  [CD] $
+      R2 CD(C,D);
+      R  CD2=(CD,CD);
+      R la= (CD,A-C)/CD2;
+      R lb= (CD,B-C)/CD2;
+      //  A = C*(1-la)+ la*D
+      //  B = C*(1-lb)+ lb*D
+      //  X = (1-x)*A+x*B;
+      //  X = (1-x)*(C*(1-la)+ la*D) + x*(C*(1-lb)+ lb*D)
+      //  X = C*((1-x)*(1-la)+x*(1-lb))
+      R xx=((1-x)*(1-la)+x*(1-lb));
+      throwassert(xx>=0 && xx <= 1);
+      return TriangleHat[c]*(xx)+TriangleHat[d]*(1-xx);
+   }
+  
+};  
+
+
+
+class FMortar { public:
+  friend class FESpace;
+  const FESpace &Vh;  
+  const Mortar &M;
+  const int *p;
+  const int nbn; //  nb of node
+//  const int nbnl,nbnr; // nb of node left, right
+  
+  //   we supposse 
+  //  the node numbering in a mortar is
+  //  1   the lagrange mul.
+  //  2   the node of left side
+  //  3   the node of right side
+  
+  const int N;  
+   TypeOfMortar const *  const tom; 
+  FMortar(const FESpace * VVh,int k) ;
+  public:
+  int  operator[](int i) const ;
+  int  operator()(int i,int df) const ;// { N\u00c9 du DoF du noeud i de df local df 
+  int  operator()(int df) const { return operator()(NodeOfDF(df),DFOfNode(df));}
+  int NbDoF(int i) const ;//{return tom->NbDoF(Vh.Th,M,i);};  // number of DF 
+  int NbOfNodes()const {return nbn;}
+  int NbDoF() const ;
+  int NodeOfDF(int i) const ;
+  int DFOfNode(int i) const ;
+  
+  int nbsm; // nb of submortar
+  aSubFMortar * sm;
+  ~FMortar() { 
+    delete [] datai;
+    delete [] dataf;}
+  
+  int *datai;
+   R (**dataf)(const FESpace *,const aSubFMortar *,R);
+  private:
+   FMortar(const FMortar &);
+   void operator=(const FMortar &);
+
+};
+
+extern TypeOfFE & P1Lagrange;
+extern TypeOfFE & P2Lagrange;
+extern TypeOfFE & RTLagrange;
+extern TypeOfFE & RTLagrangeOrtho;
+extern TypeOfFE & P0Lagrange;
+extern TypeOfFE & P1ncLagrange;
+
+  class FESpace : public RefCounter , public UniqueffId
+{
+  public:
+  typedef Fem2D::Mesh Mesh;
+  typedef Fem2D::FElement FElement;
+  typedef Mesh::Element  Element;
+  typedef Mesh::Rd  Rd;
+  typedef Fem2D::TypeOfFE TypeOfFE;
+  typedef Fem2D::QuadratureFormular QFElement;
+  typedef Fem2D::QuadratureFormular1d QFBorderElement;
+
+
+  const Mesh &Th;
+  TypeOfFE const * const ptrTFE;
+  KN<const TypeOfFE *>  TFE; 
+  private:
+  ConstructDataFElement * cdef; //  juste pour les constantes 
+  public:
+  CountPointer<const Mesh> cmesh;
+  const int N; // dim espace d'arrive
+  const int Nproduit; // dim de l'espace produit generalement 1
+  const int NbOfDF;
+  const int NbOfElements;
+  const int NbOfNodes;
+  const int nb_sub_fem; // nb de sous elements finis tensorise (independe au niveau des composantes)
+  int const* const dim_which_sub_fem;// donne les dependant des composantes liee a un meme sous element fini
+   //   exemple si N=5,  
+   // dim_which_sub_fem[0]=0;
+   // dim_which_sub_fem[1] =1;
+   // dim_which_sub_fem[2]= 2
+   // dim_which_sub_fem[3] =2 
+   // dim_which_sub_fem[4] =3
+   //  =>
+   //  le  sous  elements fini 0 est lie a la composante 0 
+   //  le  sous  elements fini 1 est lie a la composante 1 
+   //  le  sous  elements fini 2 est lie aux composantes 2,3 
+   //  le  sous  elements fini 3 est lie a la composante 4 
+   //  donc pour les CL. les composante 2 et 3 sont lie car elle sont utiliser pour definir un
+   //  meme degre de libert\u00e9.
+  
+  int const*const NodesOfElement;
+  int const*const FirstNodeOfElement;
+  int const*const FirstDfOfNodeData;
+  const TypeOfMortar * tom; 
+  const int MaxNbNodePerElement;
+  const int MaxNbDFPerElement;
+
+//  par defaut P1                
+  FESpace(const Mesh & TTh) 
+    :
+    Th(TTh),
+    ptrTFE(0),
+    TFE(1,0,&P1Lagrange),
+    cdef(0),
+    cmesh(TTh),
+    N(1),
+    Nproduit(1),
+    NbOfDF(TTh.nv),
+    NbOfElements(TTh.nt),
+    NbOfNodes(TTh.nv),
+    nb_sub_fem(TFE[0]->nb_sub_fem),
+    dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+    NodesOfElement(0),
+    FirstNodeOfElement(0),
+    FirstDfOfNodeData(0),
+    tom(0),
+    MaxNbNodePerElement(3),
+    MaxNbDFPerElement(3*Nproduit)
+ {}
+
+
+  int FirstDFOfNode(int i) const {return FirstDfOfNodeData ? FirstDfOfNodeData[i] : i*Nproduit;}
+  int LastDFOfNode(int i)  const {return FirstDfOfNodeData ? FirstDfOfNodeData[i+1] : (i+1)*Nproduit;}
+  int NbDFOfNode(int i)  const {return FirstDfOfNodeData ? FirstDfOfNodeData[i+1]-FirstDfOfNodeData[i] : Nproduit;}
+  int MaximalNbOfNodes() const {return MaxNbNodePerElement;};
+  int MaximalNbOfDF() const {return MaxNbDFPerElement;};
+  const int * PtrFirstNodeOfElement(int k) const {
+      return NodesOfElement 
+               ? NodesOfElement + (FirstNodeOfElement ? FirstNodeOfElement[k] : k*MaxNbNodePerElement)                 
+               : 0;}   
+               
+  int SizeToStoreAllNodeofElement() const {  
+       return  FirstNodeOfElement 
+                ?  FirstNodeOfElement[NbOfElements] 
+                : MaxNbNodePerElement*NbOfElements;}   
+                      
+  int NbOfNodesInElement(int k)   const {             
+      return FirstNodeOfElement 
+               ?  FirstNodeOfElement[k+1] - FirstNodeOfElement[k] 
+               : MaxNbNodePerElement ;}
+  int  esize() const { return  MaxNbDFPerElement*N*last_operatortype;}   // size to store all value of B. function        
+      
+    FESpace(const FESpace &,int k );
+    FESpace(const FESpace **,int k ); 
+    FESpace(const Mesh & TTh,const TypeOfFE **,int k,int nbdfv=0,const int *ndfv=0,int nbdfe=0,const int *ndfe=0 );//int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,int NN=1); 
+ 
+    FESpace(const Mesh & TTh,const TypeOfFE & ,
+    int nbdfv=0,const int *ndfv=0,int nbdfe=0,const int *ndfe=0);//int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,int NN=1); 
+    
+    FESpace(const Mesh & TTh,const TypeOfFE &,const TypeOfMortar & );//int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,int NN=1); 
+  ~FESpace();    
+ // FESpace(Mesh & TTh,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,int NN=1); 
+  int  renum();
+      
+  FElement operator[](int k) const { return FElement(this,k);} 
+  FElement operator[](const Triangle & K) const { return FElement(this,Th.number(K));} 
+  int  operator()(int k)const {return NbOfNodesInElement(k);}
+  int  operator()(int k,int i) const { //  the node i of element k
+     return NodesOfElement ?  *(PtrFirstNodeOfElement(k) + i)  : Th(k,i)  ;}
+  
+  void Draw(const KN_<R>& U,const KN_<R>& Viso,int j=0,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const ; // Draw iso line
+  void Drawfill(const KN_<R>& U,const KN_<R>& Viso,int j=0,double rapz=1,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const ; // Draw iso line
+  
+  template<class R> 
+  KN<R>  newSaveDraw(const KN_<R> & U,int composante,int & lg,int & nsb) const   ; 
+  template<class R> 
+  KN<R>  newSaveDraw(const KN_<R> & U,const KN_<R> & V,int iU,int IV,int & lg,int & nsb) const   ; 
+  void Draw(const KN_<R>& U,const KN_<R> & Viso, R coef,int j0=0,int j1=1,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const  ; // Arrow
+  void Draw(const KN_<R>& U,const KN_<R>& V,const KN_<R> & Viso, R coef,int iu=0,int iv=0,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const  ; // Arrow
+  R2 MinMax(const KN_<R>& U,const KN_<R>& V,int j0,int j1,bool bb=true) const ;
+  R2 MinMax(const KN_<R>& U,int j0, bool bb=true) const ;
+ // void destroy() {RefCounter::destroy();}
+  bool isFEMesh() const { return !cdef && ( N==1) ;} // to make optim
+  void Show() const {  
+ // cout << " Show: FESpace " << this << " " <<  N << " ";  if(cdef) cout << cdef->NodesOfElement << endl;else cout << endl;
+  }
+
+ private: // for gibbs  
+  int gibbsv (long* ptvoi,long* vois,long* lvois,long* w,long* v);
+    
+};
+
+inline baseFElement::baseFElement(  const FESpace &aVh, int k) 
+    : Vh(aVh),T(Vh.Th[k]),tfe(aVh.TFE[k]),N(aVh.N),number(k){}
+    
+inline baseFElement::baseFElement(const   baseFElement & K,  const TypeOfFE & atfe) 
+    : Vh(K.Vh),T(K.T),tfe(&atfe),N(Vh.N),number(K.number){}
+
+
+inline FElement::FElement(const FESpace * VVh,int k) 
+  : baseFElement(*VVh,k) ,
+    p(Vh.PtrFirstNodeOfElement(k)),
+    nb(Vh.NbOfNodesInElement(k))
+    
+     {} 
+  
+inline   int  FElement::operator[](int i) const {
+   return  p ? p[i] :  ((&T[i])-Vh.Th.vertices);}  
+   
+inline   int  FElement::operator()(int i,int df) const {
+   return  Vh.FirstDFOfNode(p ? p[i] :  ((&T[i])-Vh.Th.vertices)) + df;}  
+   
+inline   int  FMortar::operator()(int i,int df) const {throwassert(p);
+   return  Vh.FirstDFOfNode(p[i]) + df;} 
+    
+inline   int  FMortar::operator[](int i) const {throwassert(p);
+   return  p[i];}  
+   
+inline   int  FElement::NbDoF(int i) const {
+   int node =p ? p[i] :  ((&T[i])-Vh.Th.vertices);
+   return  Vh.LastDFOfNode(node)-Vh.FirstDFOfNode(node);}  
+
+void  SetDefaultIsoValue(const KN_<R>& U,KN_<R> & Viso);
+void  SetDefaultIsoValue(const KN_<R>& u,const KN_<R>& v,KN_<R> & Viso);
+void MoveTo(R2 P); 
+void LineTo(R2 P) ;
+
+/*
+void operator=(  KN_<R> & u,const FElementGlobalToLocal & x) 
+{
+  int n=u.N();
+  throwassert(n==x.S.NbDoF());
+  for (int i=0;i<n;i++) // get the local value
+     v[i] = x.U[x.S(i)];
+}
+*/
+inline  int FMortar::NbDoF(int i) const {
+   int node = p[i];
+   return  Vh.LastDFOfNode(node)-Vh.FirstDFOfNode(node);
+};  // number of DF 
+inline  int FMortar::NbDoF() const { return tom->NbDoF(Vh.Th,M);}
+//inline  int FMortar::NbOfNodes()const {return }
+inline  int FMortar::NodeOfDF(int i) const { return tom->NodeOfDF(Vh,M,i);}
+inline  int FMortar::DFOfNode(int i) const { return tom->DFOfNode(Vh,M,i);}
+
+inline ostream & operator << (ostream & f,const FElement & FE)
+   {
+     f << FE.number << "," <<FE.nb << ":" ;
+     for (int i=0;i<FE.nb;i++) f << "\t"<<FE.p[i];
+   return f;
+     
+   }
+inline ostream & operator << (ostream & f,const FESpace & Vh)
+   {
+     cout << " list of nodes per element :" << endl;
+     for (int k=0;k< Vh.NbOfElements;k++)
+      { f <<setw(3) <<  k << ":";
+      for (int j=0;j<Vh(k);j++)
+        f << " " << setw(3) << Vh(k,j);
+        cout << endl;
+      }
+      
+      f << endl << " FirstDFOfNode :" ;       
+      for (int i=0;i<=Vh.NbOfNodes;i++)
+        {if (i%10==0)  cout << "\n" << setw(3) << i << " : ";
+        cout << setw(3) << Vh.FirstDFOfNode(i) << " ";}
+    
+   return f;
+     
+   }
+   
+inline void FElement::BF(const R2 & P,RNMK_ & val) const {
+ static bool whatdold[last_operatortype]={true,true,true,false,false,false,false,false,false,false};
+ tfe->FB(whatdold,Vh.Th,T,P,val);}
+inline void FElement::BF(const bool * whatd,const R2 & P,RNMK_ & val) const { tfe->FB(whatd,Vh.Th,T,P,val);}
+//inline  void FElement::D2_BF(const R2 & P,RNMK_ & val) const { tfe->D2_FB(Vh.Th,T,P,val);}
+
+
+//  -------
+ extern const TypeOfMortar & TheMortarCas1P2; 
+ 
+void PlotValue(const RN_ & Viso,int  k0,const char * cmm);
+ 
+// to store all the type of TFE
+// the problem is the TFE can be define on lot of file.cpp
+struct ListOfTFE { 
+  const char * name;
+  TypeOfFE * tfe;
+  ListOfTFE * next;
+
+  static ListOfTFE * all ; // list of all object of this type 
+  ListOfTFE (const char * n,TypeOfFE *t);
+};
+// to get a unique list of TypeOfFE 
+// local variable of TypeOfFE
+ListOfTFE & GetListOfTFE() ;
+
+
+inline   R FElement::operator()(const R2 & PHat,
+                                const KN_<R> & u,int i,int op)  const
+{
+ return (*tfe)(*this,PHat,u,i,op);
+}
+
+
+inline  complex<R> FElement::operator()(const R2 & PHat,const KN_<complex<R> > & u,int i,int op)  const 
+{
+ complex<double> * pu=u; // pointeur du tableau
+  double *pr = static_cast<double*>(static_cast<void*>(pu));
+
+  const KN_<R>  ur(pr,u.n,u.step*2);
+  const KN_<R>  ui(pr+1,u.n,u.step*2);
+  
+   return complex<R>((*tfe)(*this,PHat,ur,i,op),(*tfe)(*this,PHat,ui,i,op));
+}
+
+}
+
+
+#endif
diff --git a/src/femlib/FESpacen.cpp b/src/femlib/FESpacen.cpp
new file mode 100644
index 0000000..c3bccb6
--- /dev/null
+++ b/src/femlib/FESpacen.cpp
@@ -0,0 +1,624 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : Generic Fiinite Element   1d, 2d, 3d  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include <map>
+
+#include "ufunction.hpp"
+
+#include "error.hpp"
+#include "RNM.hpp"
+
+#include "Mesh3dn.hpp"
+#include "Mesh2dn.hpp"
+
+#include "FESpacen.hpp"
+
+#include "splitsimplex.hpp"
+ int UniqueffId::count=0;
+ namespace Fem2D {
+
+//template<class Element>
+int nbdf_d(const int ndfitem[4],const  int nd[4])
+{
+  const int ndf = ndfitem[0]*nd[0] + ndfitem[1]*nd[1]+  ndfitem[2]*nd[2]  + ndfitem[3]*nd[3];	
+  return ndf;
+}
+
+//template<class Element>
+int nbnode_d(const int ndfitem[4],const  int nd[4])
+{
+  //  const  int nd[]= {Element::nv, Element::ne,Element::nf,Element::nt};
+    const int ndf = nd[0]*(ndfitem[0]!=0) + nd[1]*(ndfitem[1]!=0)+  nd[2]*(ndfitem[2]!=0)  + nd[3]*(ndfitem[3]!=0);	
+    return ndf;
+}
+
+//template<class Element>
+int *builddata_d(const int ndfitem[4],const int nd[4],int N)
+{
+  //    const int d=Element::Rd::d;
+  //    const int nwhat=Element::nitem;
+  //    const  int nd[]= {Element::nv, Element::ne,Element::nf,Element::nt};
+  //    const int nitem=nd[0]+nd[1]+nd[2]+nd[3];
+  //    cout << " nitem="<< nitem<< endl;
+  const int ndf = nbdf_d(ndfitem,nd);
+  const int nnode=nbnode_d(ndfitem,nd);
+  int lgdata= ndf*5+N;
+  int * data = new int[lgdata];
+  int p=0;
+  for(int i=0,nw=0;i<=3;++i)
+    for(int j=0;j<nd[i];++j,nw++)// pour les what (support de node)
+      for(int k=0;k<ndfitem[i];++k)// 	    
+	data[p++] = nw;
+ // cout << p << " " <<ndfitem[0]<< ndfitem[1]<<ndfitem[2]<<ndfitem[3]<< " " << ndf  << endl;
+  assert(p==ndf);
+  for(int i=0,nw=0;i<=3;++i)
+    for(int j=0;j<nd[i];++j,nw++)// pour les what (support de node)
+      for(int k=0;k<ndfitem[i];++k)// 	    
+	data[p++] = k;
+  // cout << p << " " << 2*ndf << " " << nitem << endl;
+  int nn=0;
+  for(int i=0;i<=3;++i)
+    {
+      int in=ndfitem[i]?1:0;
+      for(int j=0;j<nd[i];++j,nn+=in )// pour les what (support de node)
+	for(int k=0;k<ndfitem[i];++k)// 	    
+	  data[p++] = nn;
+    }
+  // cout << p << " " << 3*ndf << " " << nitem << endl;
+  for(int i=0;i<ndf*2+N;++i)	    
+    data[p++] = 0;
+  
+ // data[p++] = 0;
+ // data[p++] = 0;
+  //cout << p << " == " << lgdata << endl;
+  assert(p== lgdata);
+  //cout << nn << " " << nnode << endl;
+  p =0;
+  
+  /*  
+      for(int j=0;j<4;j++)
+      {
+      for (int i=0;i<ndf;i++)
+      cout << data[p++] << " ";
+      cout << endl;
+      } 
+  */
+  assert(nn==nnode); 
+  return data;  
+}
+
+   dataTypeOfFE::dataTypeOfFE(const int nitemdim[4],const int dfon[4],int NN,int nbsubdivisionn,int nb_sub_femm,bool discon)
+     :
+     data(builddata_d(dfon,nitemdim,NN)),  
+     dataalloc(data),
+     ndfonVertex(dfon[0]),
+     ndfonEdge(dfon[1]),
+     ndfonFace(dfon[2]),
+     ndfonVolume(dfon[3]),
+     NbDoF(nbdf_d(dfon,nitemdim)),
+     NbNode(nbnode_d(dfon,nitemdim)),
+     N(NN),
+     nb_sub_fem(nb_sub_femm),
+     nbsubdivision(nbsubdivisionn),
+     discontinue(discon),
+     DFOnWhat(data+0*NbDoF),
+     DFOfNode(data+1*NbDoF),
+     NodeOfDF(data+2*NbDoF),
+     fromFE(data+3*NbDoF),
+     fromDF(data+4*NbDoF),
+     fromASubFE(data+3*NbDoF),
+     fromASubDF(data+4*NbDoF) ,
+     dim_which_sub_fem(data+5*NbDoF)
+   {}
+
+
+int *builddata_d(const int nitemdim[4],const KN< dataTypeOfFE const  *> &teb)
+{
+    const int k = teb.N(); 
+    KN<int> NN(k+1), DF(k+1) , comp(k+1);
+    map< dataTypeOfFE const  *,int> m;
+    int i=k,j;    
+    while(i--) // on va a l'envert pour avoir comp[i] <=i 
+	m[teb[i]]=i;
+    // l'ordre comp est important comp est croissant  mais pas de pb. 
+    i=k;    
+    while(i--) 
+	comp[i]=m[teb[i]]; //  comp[i] <=i
+    int n=0,N=0;
+    for ( j=0;j<k;j++)
+      {NN[j]=N;N+=teb[j]->N;}
+    NN[k] = N;
+    //  reservation des interval en df   
+    n=0;
+    for ( j=0;j<k;j++)
+      { DF[j]=n;n+=teb[j]->NbDoF;}
+    DF[k] = n;
+    
+    int NbDoF=0;
+    int dfon[4]={0,0,0,0};
+    int nbsubdivision=0;
+    int discon=0; 
+    for (int i=0;i<k;++i)
+      {
+	NbDoF += teb[i]->NbDoF;
+	  dfon[0] += teb[i]->ndfonVertex;
+	dfon[1] += teb[i]->ndfonEdge;
+	dfon[2] += teb[i]->ndfonFace;
+	dfon[3] += teb[i]->ndfonVolume;
+	nbsubdivision = max(nbsubdivision,teb[i]->nbsubdivision);
+	discon = discon || teb[i]->discontinue; // bof bof 1 FE discontinue => discontinue
+      }
+    int nwhat=15; // 15 = 4+6+1+1 (nb of  support item  (what) : vertex, edges, fqces, tet)
+    
+    int ostart=nwhat;
+    int * data0=new int[ostart+7*NbDoF+N];
+    int * data=data0+ostart;
+    int * data1=data+5*NbDoF;
+   
+      int c=0;
+    KN<int> w(nwhat),nn(nwhat); 
+    
+    w=0;
+    nn=0; 
+
+    
+    for ( j=0;j<k;j++)
+	for ( i=0;i<teb[j]->NbDoF;i++)
+	    nn[teb[j]->DFOnWhat[i]]++;
+    int nbn=0;      
+    for( j=0;j<nwhat;j++)
+	if (nn[j]) nn[j]=nbn++;
+	else nn[j]=-1;
+    KN<int> dln(nwhat);
+    dln=0;
+    // nn donne numero de noeud sur what            
+    for ( j=0;j<k;j++)
+	for ( i=0;i<teb[j]->NbDoF;i++)
+	    data[c++] = teb[j]->DFOnWhat[i];
+    
+    for ( j=0;j<k;j++)
+      {
+	  int  cc=c;
+	  for ( i=0;i<teb[j]->NbDoF;i++)
+	      data[c++] = teb[j]->DFOfNode[i]+dln[teb[j]->DFOnWhat[i]];
+	  for ( i=0;i<teb[j]->NbDoF;i++)
+	      dln[teb[j]->DFOnWhat[i]]=Max(dln[teb[j]->DFOnWhat[i]],data[cc++]+1);      
+      }
+    
+    
+    for ( j=0;j<k;j++)
+      { 
+	  //  w renumerotation des noeuds 
+	  //  Ok si un noeud par what 
+	  for ( i=0;i<teb[j]->NbDoF;i++)
+	      data[c++] = nn[teb[j]->DFOnWhat[i]];
+      }
+    
+    for ( j=0;j<k;j++)
+	for ( i=0;i<teb[j]->NbDoF;i++)
+	    data[c++] = j; //  node from of FE
+    
+    
+    for ( j=0;j<k;j++)
+	for ( i=0;i<teb[j]->NbDoF;i++)
+	    data[c++] = i; //  node from of df in FE
+    // error -- here 
+    //in case of [P2,P2],P1  
+    // we expect 0,0,1   and we get 0 1 2 
+    // => wrong BC ???? 
+    c+=2*n; // on saute le deux tableau en plus (cf data1.)
+    
+    
+    int xx=0;
+    for (j=0;j<k;j++)
+      { 
+	  int xxx=xx;
+	  for (i=0;i<teb[j]->N;i++)
+	    { 
+		data[c] = teb[j]->dim_which_sub_fem[i]+xx;
+		xxx=Max(xxx,data[c]+1);
+		c++;
+	    }
+	  xx=xxx;
+      }
+    
+    
+    //  ou dans la partie miminal element finite atomic 
+    
+    int ci=n;
+    int cj=0;
+    int ccc=0;
+    for ( j=0;j<k;ccc+=teb[j++]->nb_sub_fem)
+	
+	for ( i=0;i<teb[j]->NbDoF;i++)
+	  {
+	      int il= teb[j]->fromASubDF[i];
+	      int jl= teb[j]->fromASubFE[i];
+	      data1[ci++]=il;
+	      data1[cj++]=ccc+jl;      
+	  }
+    
+    int nb_sub_fem=ccc;
+    
+    ffassert(c== 7*n+N);      
+    /*  int cc=0;
+     cout << " Data : " << endl;
+     for ( i=0;i<5;i++)    {
+     for (j=0;j<n;j++)
+     cout << " " << data[cc++];
+     cout << endl;}
+     cout << " which " ;
+     for (i=0;i<N;i++)
+     cout << " " << data[cc++];
+     cout << endl;*/
+    
+    
+    for(int i=0;i<4;++i)
+	data0[i]=dfon[i];
+    
+    data0[4]=NbDoF;
+    data0[5]=nbn;// NbNode
+    data0[6]=N;
+    data0[7]=nb_sub_fem;
+    data0[8]=nbsubdivision;
+    data0[9]=discon;
+    
+    return data0;
+}
+
+  
+dataTypeOfFE::dataTypeOfFE(const int nitemdim[4],const KN< dataTypeOfFE const *>  &  tef)
+: 
+data(builddata_d(nitemdim,tef)),  
+dataalloc(data),
+ndfonVertex(data[0]),
+ndfonEdge(data[1]),
+ndfonFace(data[2]),
+ndfonVolume(data[3]),
+NbDoF(data[4]),
+NbNode(data[5]),
+N(data[6]),
+nb_sub_fem(data[7]),
+nbsubdivision(data[8]),
+discontinue(data[9]),
+DFOnWhat(data+15+0*NbDoF),
+DFOfNode(data+15+1*NbDoF),
+NodeOfDF(data+15+2*NbDoF),
+fromFE(data+15+3*NbDoF),
+fromDF(data+15+4*NbDoF),
+fromASubFE(data+15+5*NbDoF),
+fromASubDF(data+15+6*NbDoF) ,
+dim_which_sub_fem(data+15+7*NbDoF)
+{}
+
+template<class Mesh>
+void GTypeOfFESum<Mesh>::init(InterpolationMatrix<RdHat> & M,FElement * pK,int odf,int ocomp,int *pp) const
+{
+  // a faire ..... cas matrix invariante 
+  assert(0);
+}
+
+template<class Mesh>
+     GTypeOfFESum<Mesh>::GTypeOfFESum(const KN< GTypeOfFE<Mesh> const *> & t)
+     : 
+     GTypeOfFE<Mesh>(t),
+     k(t.N()),
+     teb(t),
+     NN(k+1),
+     DF(k+1) ,
+     comp(k+1) {Build();}
+     
+template<class Mesh> 
+static  KN< GTypeOfFE<Mesh> const *> kn(const GFESpace<Mesh> ** tt,int kk)
+     {
+	 KN< GTypeOfFE<Mesh> const *> r(kk);
+	 for(int i=0;i<kk;++i)
+	   { r[i]=tt[i]->TFE[0];ffassert(tt[i]->TFE.constant());}
+	 return r;
+     }
+template<class Mesh> 
+static     KN< GTypeOfFE<Mesh> const *> kn(const GFESpace<Mesh> & tt,int kk)
+     {
+	 return  KN< GTypeOfFE<Mesh> const *> (kk,tt.TFE[0]);
+     }
+     
+template<class Mesh>
+     GTypeOfFESum<Mesh>::GTypeOfFESum(const GFESpace<Mesh> ** tt,int kk)
+     :	
+     GTypeOfFE<Mesh>(kn(tt,kk)),
+     k(kk),
+     teb(kn(tt,kk)),
+     NN(k+1),
+     DF(k+1) ,
+     comp(k+1) {Build();}
+     
+template<class Mesh>
+     GTypeOfFESum<Mesh>::GTypeOfFESum(const GFESpace<Mesh> & tt,int kk)
+     :	
+     GTypeOfFE<Mesh>(kn(tt,kk)),
+     k(kk),
+     teb(kn(tt,kk)),
+     NN(k+1),
+     DF(k+1) ,
+     comp(k+1) {Build();}
+     
+template<class Mesh>
+void GTypeOfFESum<Mesh>::Build()
+{
+    bool debug=verbosity>5;;
+  {
+    const KN< GTypeOfFE<Mesh> const *> & t=teb;
+    map<const GTypeOfFE<Mesh> *,int> m;
+    int i=k,j;    
+    while(i--) // on va a l'envert pour avoir comp[i] <=i 
+      m[teb[i]]=i;
+    // l'ordre comp est important comp est croissant  mais pas de pb. 
+    i=k;    
+    while(i--) 
+      comp[i]=m[teb[i]]; //  comp[i] <=i
+    
+    // reservatition des intervalles en espaces
+    int n=0,N=0;
+    for ( j=0;j<k;j++)
+      {NN[j]=N;N+=teb[j]->N;}
+    NN[k] = N;
+    //  reservation des interval en df   
+    n=0;
+    for ( j=0;j<k;j++)
+      { DF[j]=n;n+=teb[j]->NbDoF;}
+    DF[k] = n;
+  }
+  int ii=0;
+  for (int i=0;i<k;++i)
+    {
+      for (int j=0;j<teb[i]->nb_sub_fem;++j)
+	this->Sub_ToFE[ii++]=teb[i]->Sub_ToFE[j];
+    }
+  assert(ii==this->nb_sub_fem );
+  
+  int c=0,c0=0, fcom=0;
+  for (int i=0;i<this->nb_sub_fem;i++) 
+    { 
+      int N=this->Sub_ToFE[i]->N;
+      int ndofi=this->Sub_ToFE[i]->NbDoF;
+      this->first_comp[i]= fcom;
+      this->last_comp[i]= fcom+N;
+      fcom += N;
+
+      for(int j=0;j<N;++j)
+	{
+	  this->begin_dfcomp[c] = c0 + this->Sub_ToFE[i]->begin_dfcomp[j] ; 
+	  this->end_dfcomp[c]   = c0 + this->Sub_ToFE[i]->end_dfcomp[j] ;
+	  c++;
+	}
+      c0+=ndofi;
+      
+    }
+  if(debug)
+    {
+      cout <<" NbDoF : " << this->NbDoF <<endl;
+      for(int i=0;i<this->N;++i)
+	cout << "      comp " << i << " ["<<this->begin_dfcomp[i]<<", "<< this->end_dfcomp[i]<< "[\n";
+    }
+  
+  // construction de l'interpolation .
+  
+  int npi=0;
+  int nci=0;
+  bool var=true;
+  for (int i=0;i<this->nb_sub_fem;i++)
+    {
+      npi +=this->Sub_ToFE[i]->NbPtforInterpolation;
+      nci +=this->Sub_ToFE[i]->NbcoefforInterpolation;
+      var = var && this->Sub_ToFE[i]->invariantinterpolationMatrix;
+    }
+  assert(this->NbcoefforInterpolation== nci);
+  this->invariantinterpolationMatrix=var;
+  // this->pInterpolation.init(nci);
+  // this->cInterpolation.init(nci);
+  // this->dofInterpolation.iniy(nci);
+  {
+    map<RdHat,int,lessRd> mpt;
+    numPtInterpolation.init(npi);
+    int npp=0,kkk=0;
+    KN<RdHat> Ptt(npi);
+    for (int i=0;i<this->nb_sub_fem;i++)
+      {
+	const GTypeOfFE<Mesh> &ti=*this->Sub_ToFE[i];
+	
+	for(int p=0;p<ti.NbPtforInterpolation;++p,++kkk)
+	  {
+	    Ptt[kkk]=ti.PtInterpolation[p];
+	    if(verbosity>5)
+	    cout << "    p= "<< p << " [ " << Ptt[kkk]<< "] ,  "<< kkk<< " "<< npp<<endl;;
+	    if( mpt.find(Ptt[kkk]) == mpt.end())
+	      mpt[Ptt[kkk]]=npp++;
+	    numPtInterpolation[kkk]=mpt[Ptt[kkk]];
+	  }
+      }
+    assert(this->NbPtforInterpolation==0);
+    if(verbosity>5)
+    cout << npp;
+    this->NbPtforInterpolation=npp;
+    this->PtInterpolation.init(npp);
+    for(int i=0;i<npp;++i)
+      this->PtInterpolation[numPtInterpolation[i]]=Ptt[i];
+  }
+  
+  int oc=0,odof=0;
+  for (int i=0,k=0;i<this->nb_sub_fem;i++)
+    {
+      const GTypeOfFE<Mesh> &ti=*this->Sub_ToFE[i];
+      for(int j=0;j<ti.NbcoefforInterpolation; ++j,++k)
+	{
+	  this->pInterpolation[k]   = numPtInterpolation[ti.pInterpolation[j]];
+	  this->cInterpolation[k]   = ti.cInterpolation[j]+oc;
+	  this->dofInterpolation[k] = ti.dofInterpolation[j]+odof;
+	  this->coefInterpolation[k]=ti.coefInterpolation[j];
+	}
+      oc += ti.N;
+      odof += ti.NbDoF; 
+    }
+  
+  assert(c==this->N);
+}
+
+     
+template<class Mesh> void GTypeOfFESum<Mesh>::set(const Mesh & Th,const Element & K,InterpolationMatrix<RdHat> & M,int oocoef,int oodf,int *nnump ) const
+     {
+	 int op=0,oc=0,odof=oodf,ocoef=oocoef;
+	 assert(nnump==0);
+	 for (int i=0,k=0;i<this->nb_sub_fem;i++)
+	   {
+	       const GTypeOfFE<Mesh> &ti=*this->Sub_ToFE[i];
+	       if(!ti.invariantinterpolationMatrix)
+		   ti.set(Th,K,M,ocoef,odof,&numPtInterpolation[op]);
+	       oc += ti.N;
+	       odof += ti.NbDoF; 
+	       ocoef += ti.NbcoefforInterpolation;
+	       op += ti.NbPtforInterpolation;
+	       
+	   }
+	 
+     }
+     
+template<class MMesh> 
+     GFESpace<MMesh>::GFESpace(const GFESpace & Vh,int kk,int nbequibe,int *equibe)
+     :
+     GFESpacePtrTFE<MMesh>(new GTypeOfFESum<MMesh>(Vh,kk)),
+     DataFENodeDF(Vh.Th.BuildDFNumbering(this->ptrTFE->ndfonVertex,this->ptrTFE->ndfonEdge,this->ptrTFE->ndfonFace,this->ptrTFE->ndfonVolume,nbequibe,equibe)),
+     Th(Vh.Th),
+     TFE(1,0,this->ptrTFE), 
+     cmesh(Th),
+     N(TFE[0]->N),
+     Nproduit(kk),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     maxNbPtforInterpolation(TFE[0]->NbPtforInterpolation),
+     maxNbcoefforInterpolation(TFE[0]->NbcoefforInterpolation)
+     
+     {
+     }
+    
+template<class MMesh> 
+     GFESpace<MMesh>::GFESpace(const GFESpace ** pVh,int kk,int nbequibe,int *equibe)
+     :
+     GFESpacePtrTFE<MMesh>(new GTypeOfFESum<MMesh>(pVh,kk)),
+     DataFENodeDF((**pVh).Th.BuildDFNumbering(this->ptrTFE->ndfonVertex,this->ptrTFE->ndfonEdge,this->ptrTFE->ndfonFace,this->ptrTFE->ndfonVolume,nbequibe,equibe)),
+     Th((**pVh).Th),
+     TFE(1,0,this->ptrTFE), 
+     cmesh(Th),
+     N(TFE[0]->N),
+     Nproduit(FirstDfOfNodeData ? 1 :MaxNbDFPerNode),
+     nb_sub_fem(TFE[0]->nb_sub_fem),
+     dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+     maxNbPtforInterpolation(TFE[0]->NbPtforInterpolation),
+     maxNbcoefforInterpolation(TFE[0]->NbcoefforInterpolation)
+     
+     {
+         long snbdf=0;
+         for(int i=0;i<kk;++i)
+             snbdf += pVh[i]->NbOfDF;
+         if( snbdf !=NbOfDF)
+             cerr << " Problem build of GFESpace (3d) (may be : due to periodic Boundary condition missing ) FH " << endl
+             << " The number of DF must be " << snbdf << "  and it is " << NbOfDF <<endl; 
+         ffassert(snbdf == NbOfDF );
+
+         
+	     for(int i=0;i<kk;++i)
+	     ffassert(&Th==&pVh[i]->Th);
+     }
+   
+template<class MMesh> 
+     template<class R> 
+KN<R>  GFESpace<MMesh>::newSaveDraw(const KN_<R> & U,int componante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U) const  
+{
+  const int d =  Rd::d;
+  Rd *Ps=0;
+  int *Ks=0;
+  int nsb = TFE[0]->nbsubdivision;        
+  int nvsub,nksub;
+  SplitSimplex<Rd>(nsb, nvsub,  Ps,  nksub ,  Ks);
+  ffassert( Psub.unset());
+  ffassert( Ksub.unset());
+  Psub.set(Ps,nvsub);
+  Ksub.set(Ks,nksub*(d+1));
+  lg= nvsub*Th.nt;
+  KN<R> v(lg);
+  for (int k=0,i=0;k<Th.nt;k++)
+    { 
+      FElement K=(*this)[k];
+      for(int l=0;l<nvsub;l++)
+	  v[i++] =   K(Psub[l], U, componante, op_U)  ;
+
+    }                                                                                                                                                                                                                            
+  return KN<R>(true,v);// to remove the copy.    
+}
+
+   /*
+template<class MMesh>
+KN<double>  GFESpace<MMesh>::newSaveDraw(const KN_<R> & U,int composante,int & lg,int & nsb) const 
+     {
+	 nsb = TFE[0]->nbsubdivision;
+	 int nsbv = NbOfSubInternalVertices(nsb,d);
+	 lg = nsbv*Th.nt;
+	 cout << "newSaveDraw what: nt " << Th.nt << " " << nsbv << " " << lg << endl;
+	 KN<double> v(lg);
+	 ffassert(v);
+	 for (int k=0,i=0;k<Th.nt;k++)
+	   {
+	       (*this)[k].SaveDraw( U,composante,&v[i]);	
+	       i+=nsbv;
+	   }
+	 return KN<double>(true,v);// to remove the copy.
+     }
+   */     
+// explicite instance..
+template class GTypeOfFESum<Mesh2>;
+template class GTypeOfFESum<Mesh3>;
+template class GFESpace<Mesh1>;
+template class GFESpace<Mesh2>;
+template class GFESpace<Mesh3>;
+     
+ template  KN<double>  GFESpace<Mesh3>::newSaveDraw<double>(const KN_<double> & U,int componante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U) const ; 
+ template  KN<double>  GFESpace<Mesh2>::newSaveDraw<double>(const KN_<double> & U,int componante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U) const ; 
+ template  KN<double>  GFESpace<Mesh1>::newSaveDraw<double>(const KN_<double> & U,int componante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U) const  ;
+
+ typedef std::complex<double> Complex; 
+ template  KN<Complex>  GFESpace<Mesh3>::newSaveDraw<Complex>(const KN_<Complex> & U,int componante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U) const ; 
+ template  KN<Complex>  GFESpace<Mesh2>::newSaveDraw<Complex>(const KN_<Complex> & U,int componante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U) const ; 
+ template  KN<Complex>  GFESpace<Mesh1>::newSaveDraw<Complex>(const KN_<Complex> & U,int componante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U) const  ;
+     
+    
+}
diff --git a/src/femlib/FESpacen.hpp b/src/femlib/FESpacen.hpp
new file mode 100644
index 0000000..3bccd04
--- /dev/null
+++ b/src/femlib/FESpacen.hpp
@@ -0,0 +1,811 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : Generic Fiinite Element header  1d, 2d, 3d  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#ifndef FESpacen_HPP_
+#define FESpacen_HPP_
+/*
+ *  FEspacen.hpp
+ *  EF23n
+ *
+ *  Created by Fr�d�ric Hecht on 04/12/07.
+ *  Copyright 2007 Universite Pierre et marie Curie  All rights reserved.
+ *
+ */
+#include <cassert>
+#include <cmath>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <complex>
+#include <map>
+using namespace std;
+#include "error.hpp"
+#include "ufunction.hpp"
+#include "Mesh3dn.hpp"
+#include "Mesh2dn.hpp"
+#include "Mesh1dn.hpp"
+
+#include "RNM.hpp"
+
+
+#include "QuadratureFormular.hpp"
+
+namespace Fem2D {
+
+template<class Mesh> class GFESpace;
+template<class Mesh> class GFElement;
+template<class Mesh> class GbaseFElement;
+template<class Mesh> class GTypeOfFE;
+ 
+// numbering of derivative 
+enum operatortype { 
+    op_id=0,
+    op_dx=1,op_dy=2,
+    op_dxx=3,op_dyy=4,
+    op_dyx=5,op_dxy=5,   
+    op_dz=6,
+    op_dzz=7,     
+    op_dzx=8,op_dxz=8, 
+    op_dzy=9,op_dyz=9   
+}; 
+
+typedef unsigned int What_d;
+ 
+const unsigned int Fop_id= 1<< op_id;
+
+const unsigned int Fop_dx= 1<< op_dx;
+const unsigned int Fop_dy= 1<< op_dy;
+const unsigned int Fop_dz= 1<< op_dz;
+
+const unsigned int Fop_dxx= 1<< op_dxx;
+const unsigned int Fop_dxy= 1<< op_dxy;
+const unsigned int Fop_dxz= 1<< op_dxz;
+
+const unsigned int Fop_dyx= 1<< op_dyx;
+const unsigned int Fop_dyy= 1<< op_dyy;
+const unsigned int Fop_dyz= 1<< op_dyz;
+
+const unsigned int Fop_dzx= 1<< op_dzx;
+const unsigned int Fop_dzy= 1<< op_dzy;
+const unsigned int Fop_dzz= 1<< op_dzz;
+
+const unsigned int Fop_D0 = Fop_id;
+const unsigned int Fop_D1 = Fop_dx | Fop_dy | Fop_dz;
+const unsigned int Fop_D2 = Fop_dxx | Fop_dyy | Fop_dzz | Fop_dxy | Fop_dxz | Fop_dyz;
+const unsigned int Fop_Dall = Fop_D0| Fop_D1| Fop_D2;
+
+inline What_d  Fwhatd(const operatortype op) { return 1<< op;}
+
+
+const int last_operatortype=10;
+const bool operatortypeValue[last_operatortype]= {true,false,false,false,false,false,false,false,false,false} ; 
+
+
+inline void initwhatd(bool *whatd,int k)
+{
+    for (int i=0;i<last_operatortype;i++)
+	whatd[i]=false;    
+    whatd[k]=true;
+}
+
+typedef double R;
+typedef KN_<R> RN_;
+typedef KN<R>  RN;
+typedef KNM_<R> RNM_;
+typedef KNMK_<R> RNMK_;
+typedef KNMK<R>  RNMK;
+
+template<class Mesh> class GFElement; 
+template<class Mesh> class GFESpace; 
+template<class Mesh>class GTypeOfFE ;
+
+class dataTypeOfFE {
+    
+
+private:
+  const int * data; 
+  const int * dataalloc; 
+    
+public:
+    const int ndfonVertex; 
+    const int ndfonEdge;
+    const int ndfonFace;
+    const int ndfonVolume;
+     const int NbDoF;
+    const int NbNode;
+    int  N,nb_sub_fem;  
+    const int nbsubdivision; // nb of subdivision for plot    
+    const bool discontinue;
+
+    int const * const DFOnWhat; 
+    int const * const DFOfNode; // nu  du df on Node
+    int const * const NodeOfDF; // nu du node du df
+    int const * const fromFE;   //  the df  come from df of FE
+    int const * const fromDF;   //  the df  come from with FE
+    int const * const fromASubFE; //  avril 2006 for CL
+    int const * const fromASubDF; //  avril 2006 for CL
+    int const * const dim_which_sub_fem; // from atomic sub FE for CL
+    const  int * ndfOn() const { return & ndfonVertex;}
+    
+  dataTypeOfFE(const int *nnitemdim,const int dfon[4],int NN,int nbsubdivisionn,int nb_sub_femm=1,bool discon=true);
+    // pour evite un template 
+    // nitemdim : nbitem : si d==2   3,3,1,0 , si d=3: 4,6,4,1 , si d==1 = 2,1,0,0 
+    // dfon : nombre de df par item 
+    // NN 
+    dataTypeOfFE(const int nitemdim[4],const KN< dataTypeOfFE const *>  & tef);
+    
+    virtual ~dataTypeOfFE(){ if(dataalloc) delete [] dataalloc;}
+ };
+
+template<class RdHat>
+class InterpolationMatrix {
+public:
+  const int N,np,ncoef; 
+  bool invariant;
+  int k; 
+  KN<RdHat> P; 
+  KN<R> coef;
+  KN<int> comp;
+  KN<int> p;
+  KN<int> dofe; 
+
+  template<class Mesh>
+  InterpolationMatrix(const GFESpace<Mesh> &Vh);
+
+  template<class Mesh>
+  InterpolationMatrix(const GTypeOfFE<Mesh> & tef);
+
+  template<class Mesh>
+  void set(const GFElement<Mesh> & FK);
+
+
+private: // copie interdit ...
+  InterpolationMatrix(const InterpolationMatrix &);
+  void operator=(const InterpolationMatrix &);
+};
+
+template <class RdHat>
+ostream & operator<<(ostream& f,const InterpolationMatrix<RdHat> &M)
+{ f<< M.N << " "<< M.k << " "<< M.np << " "<< M.ncoef << endl;
+  f<< " = " << M.P ;
+  f << "coef=" <<M.coef ;
+  f << "comp " << M.comp;
+  f << "p = " << M.p;
+  f << "dofe = " << M.dofe;
+  return f;
+}
+
+
+template<class Mesh>
+class GTypeOfFE : public  dataTypeOfFE
+{ 
+public:
+  typedef typename Mesh::Element Element;
+  typedef  Element E;
+  typedef typename Element::RdHat RdHat;
+  typedef typename Element::Rd Rd;
+  typedef GFElement<Mesh> FElement;
+
+  // generic data build interpolation
+  bool  invariantinterpolationMatrix;
+  int NbPtforInterpolation;
+  int NbcoefforInterpolation;
+  KN<RdHat> PtInterpolation; 
+  KN<int> pInterpolation,cInterpolation,dofInterpolation; 
+  KN<R>  coefInterpolation;
+  
+    // soit 
+    //  $(U_pj)_{{j=0,N-1}; {p=0,nbpoint_Pi_h-1}}$ les valeurs de U au point Phat[i];
+    //   p est le numero du point d'integration
+    //   j est la composante 
+    //  l'interpole est  defini par
+    //  Pi_h u = \sum_k u_k w^k , et u_i = \sum_pj alpha_ipj U_pj
+    //  la matrice de alpha_ipj est tres creuse
+ 
+
+
+  KN<GTypeOfFE<Mesh> *> Sub_ToFE; 
+  KN<int> begin_dfcomp, end_dfcomp;
+  KN<int> first_comp,last_comp; // for each SubFE 
+    
+  virtual void init(InterpolationMatrix<RdHat> & M,FElement * pK,int odf,int ocomp,int *pp) const
+  {
+    assert(pK==0);
+    assert(M.np==NbPtforInterpolation);
+    assert(M.ncoef==NbcoefforInterpolation);
+    M.P=PtInterpolation;
+    M.coef=coefInterpolation;
+    M.comp=cInterpolation;
+    M.p=pInterpolation;
+    M.dofe=dofInterpolation;
+  }
+
+  
+  // the full constructor ..
+  GTypeOfFE(const int dfon[4],const int NN,int  nsub,int kPi,int npPi,bool invar,bool discon) 
+    : 
+    dataTypeOfFE(Element::nitemdim,dfon, NN, nsub,1,discon),
+    invariantinterpolationMatrix(invar),
+    NbPtforInterpolation(npPi),
+    NbcoefforInterpolation(kPi),
+    PtInterpolation(NbPtforInterpolation), 
+    pInterpolation(NbcoefforInterpolation),
+    cInterpolation(NbcoefforInterpolation),
+    dofInterpolation(NbcoefforInterpolation),
+    coefInterpolation(NbcoefforInterpolation),
+
+    Sub_ToFE(this->nb_sub_fem),
+    begin_dfcomp(N,0),
+    end_dfcomp(N,this->NbDoF),
+    first_comp(this->nb_sub_fem,0),
+    last_comp(this->nb_sub_fem,N)
+
+    { 
+      Sub_ToFE=this;
+      assert(this->dim_which_sub_fem[this->N-1]>=0 && this->dim_which_sub_fem[this->N-1]< this->nb_sub_fem);
+    } 
+
+    //  simple constructeur of lagrange type Finite element   1 point par Node for interpolation
+  GTypeOfFE(const int dfon[4],const int NN,int  nsub,bool invar,bool discon)
+    : 
+    dataTypeOfFE(Element::nitemdim,dfon, NN, nsub,1,discon),
+    
+    invariantinterpolationMatrix(invar),
+    NbPtforInterpolation(this->NbDoF),
+    NbcoefforInterpolation(this->NbDoF),
+    PtInterpolation(NbPtforInterpolation),
+    pInterpolation(NbcoefforInterpolation),
+    cInterpolation(NbcoefforInterpolation),
+    dofInterpolation(NbcoefforInterpolation),
+    coefInterpolation(NbcoefforInterpolation),
+    
+    Sub_ToFE(this->nb_sub_fem),
+    begin_dfcomp(N,0),
+    end_dfcomp(N,this->NbDoF),
+    first_comp(this->nb_sub_fem,0),
+    last_comp(this->nb_sub_fem,N)    
+  { 
+    Sub_ToFE=this;
+    assert(this->dim_which_sub_fem[this->N-1]>=0 && this->dim_which_sub_fem[this->N-1]< this->nb_sub_fem);
+  } 
+
+  //  simple constructeur pour sum direct d'espace
+  GTypeOfFE(const KN<GTypeOfFE const  *>  & tef)
+    : 
+    dataTypeOfFE(Element::nitemdim,tef),
+
+    invariantinterpolationMatrix(0),
+    NbPtforInterpolation(0),
+    NbcoefforInterpolation(ncoeftef(tef)),
+    PtInterpolation(NbPtforInterpolation),
+    pInterpolation(NbcoefforInterpolation),
+    cInterpolation(NbcoefforInterpolation),
+    dofInterpolation(NbcoefforInterpolation),
+    coefInterpolation(NbcoefforInterpolation),
+
+
+    Sub_ToFE(this->nb_sub_fem),
+    begin_dfcomp(this->N,0),
+    end_dfcomp(this->N,this->NbDoF),
+    first_comp(this->nb_sub_fem,0),
+    last_comp(this->nb_sub_fem,N)        
+  { 
+    Sub_ToFE=this;
+    assert(this->dim_which_sub_fem[this->N-1]>=0 && this->dim_which_sub_fem[this->N-1]< this->nb_sub_fem);
+  } 
+  
+  
+  virtual R operator()(const GFElement<Mesh>  & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const  ;
+  virtual void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, KNMK_<R> & val) const =0;
+  virtual void set(const Mesh & Th,const Element & K,InterpolationMatrix<RdHat> & M,int ocoef,int odf,int *nump ) const {}; // no change by deflaut
+    // ocoef is the offset of the coef in M 
+    // odf is the offset in the df 
+    // nump  if exist give the numbering of p  . 0=> no change
+  
+  static KN<int> tefN(const KN<GTypeOfFE const  *>  & tef) {
+    int n=tef.N();
+    KN<int> ntef(n);
+    for(int i=0;i<n;++i) ntef[i]=tef[i]->N;
+    return ntef;}
+
+  static int ncoeftef(const KN<GTypeOfFE const  *>  & tef) {
+    int k=0,n=tef.N();
+    for(int i=0;i<n;++i)
+      k+= tef[i]->NbcoefforInterpolation;
+    return k;}
+
+
+private:
+  static int Count(const int *data,int n,int which) 
+  {
+    int kk=0;
+    for (int i=0;i<n;++i)
+      if (which == data[i]) ++kk;
+    return kk;
+  }
+  
+  static int LastNode(const int *data,int n) 
+  {
+    int kk=0,i0=2*n;
+    for(int i=0;i<n;i++)
+      kk=Max(kk,data[i+i0]);
+    return kk;}
+  
+  static int NbNodebyWhat(const int *data,int n,int on) 
+  { 
+    const int nmax=100;
+    int t[nmax];
+    for (int i=0;i<n;i++)
+      t[i]=0;
+    int k=0,i0=2*n;
+    for(int i=0;i<n;i++)
+      if ( data[i]==on)
+	{ int node= data[i+i0];
+	  //  cout << " node " << node << endl;
+	  assert(node < nmax);
+	  if( ! t[node] )
+	    t[node] = 1,++k;
+	} 
+    
+    //     cout << " on " << on << " k = " << k << endl;
+    return k;
+  }      
+  
+} ; 
+
+  template<class mesh>
+  struct DataFE
+  {
+    static GTypeOfFE<mesh> & P0; 
+    static GTypeOfFE<mesh> & P1; 
+    static GTypeOfFE<mesh> & P2; 
+  };
+  
+
+ 
+  template<class MMesh>
+  class GbaseFElement
+  {
+  public:
+    typedef MMesh  Mesh;
+    typedef GFESpace<Mesh>  FESpace;
+    typedef typename Mesh::Element Element;
+    typedef  Element E;
+    typedef typename E::Rd Rd;
+    typedef typename E::RdHat RdHat;
+    typedef Fem2D::GQuadratureFormular<RdHat>  QF;
+    
+  const GFESpace<Mesh> &Vh;  
+  const Element &T;
+  const GTypeOfFE<Mesh> * tfe; 
+  const int N;
+  const int number;  
+  GbaseFElement(const GFESpace<Mesh> &aVh, int k) ;
+  GbaseFElement(const   GbaseFElement & K,  const GTypeOfFE<Mesh> & atfe) ;
+  R EdgeOrientation(int i) const {return T.EdgeOrientation(i);}
+  
+};
+
+template<class Mesh>
+class GFElement : public GbaseFElement<Mesh> 
+{
+public:
+    
+  typedef typename Mesh::Element Element;
+  typedef  Element E;
+  typedef typename E::Rd Rd;
+  typedef typename E::RdHat RdHat;
+  typedef Fem2D::GQuadratureFormular<RdHat>  QF;
+  
+  
+  friend class GFESpace<Mesh>;
+  const int *p;
+  const int nb;
+  
+  GFElement(const GFESpace<Mesh> * VVh,int k) ;
+  
+  int NbOfNodes()const {return nb;}
+  int  operator[](int i) const ;//{ return  p ? p+i :  ((&T[i])-Vh.Th.vertices);}  N\u00c9 du noeud 
+  int  NbDoF(int i) const ;  // number of DF 
+  int  operator()(int i,int df) const ;// { N\u00c9 du DoF du noeud i de df local df 
+  int  operator()(int df) const { return operator()(NodeOfDF(df),DFOfNode(df));}
+  // void Draw(const KN_<R> & U, const  KN_<R> & VIso,int j=0) const ;  
+  //void Drawfill(const KN_<R> & U, const  KN_<R> & VIso,int j=0,double rapz=1) const ;  
+  //void Draw(const RN_& U,const RN_& V, const  KN_<R> & Viso,R coef,int i0,int i1) const;
+  //Rd   MinMax(const RN_& U,const RN_& V,int i0,int i1) const  ;
+  //Rd   MinMax(const RN_& U,int i0) const  ;
+  void BF(const Rd & P,RNMK_ & val) const;// { tfe->FB(Vh.Th,T,P,val);}
+  void BF(const What_d whatd, const Rd & P,RNMK_ & val) const;// { tfe->FB(Vh.Th,T,P,val);}
+  void set(InterpolationMatrix<RdHat> &M) const {this->tfe->set(this->Vh.Th,this->T,M,0,0,0);}
+  // add april 08   begin end number for df of the componante ic 
+  int dfcbegin(int ic) const { return this->tfe->begin_dfcomp[ic];}
+  int dfcend(int ic) const { return this->tfe->end_dfcomp[ic];}
+  // the fist and last composant of a sub finite element
+  //  int firstcomp(int isfe) const {return this->tfe->first_comp[isfe];}
+  // int lastcomp(int isfe)  const {return this->tfe->last_comp[isfe];}
+  int subFE(int df)       const {return this->tfe->fromASubFE[df] ;}
+
+  template<class RR>
+  KN_<RR> & Pi_h(KNM_<RR> vpt,KN_<RR> & vdf,InterpolationMatrix<RdHat> &M)    const 
+  { 
+    // compute  the interpolation  
+    // in : vpt  value of componant j at point p : vpt(p,j) 
+    // out: vdf  value du the degre of freedom
+    vdf=RR();
+    
+    if(M.k != this->number) 
+      M.set( (const GFElement &) *this); 
+    
+    for (int k=0;k<M.ncoef;++k)
+      vdf[M.dofe[k]] += M.coef[k]*vpt(M.p[k],M.comp[k]);            	
+    
+    return  vdf;     
+  }
+  
+  
+  int NbDoF() const { return this->tfe->NbDoF;}
+  int DFOnWhat(int i) const { return this->tfe->DFOnWhat[i];}
+  int FromDF(int i) const { return this->tfe->fromDF[i];}
+  int FromFE(int i) const { return this->tfe->fromFE[i];}
+  
+  // df is the df in element 
+  int NodeOfDF(int df) const { return this->tfe->NodeOfDF[df];} // a node
+  int FromASubFE(int i) const { return this->tfe->fromASubFE[i];}
+  int FromASubDF(int i) const { return this->tfe->fromASubDF[i];}
+  int DFOfNode(int df) const { return this->tfe->DFOfNode[df];} // the df number on the node 
+  
+  R operator()(const Rd & PHat,const KN_<R> & u,int i,int op)  const ;
+  complex<R> operator()(const RdHat & PHat,const KN_<complex<R> > & u,int i,int op)  const ;
+  
+  // GFElementGlobalToLocal operator()(const KN_<R> & u ) const { return GFElementGlobalToLocal(*this,u);}
+private:
+  int nbsubdivision() const { return this->tfe->nbsubdivision;} // for draw 
+};
+
+
+template<class MMesh> 
+    class BuildTFE { protected:
+	GTypeOfFE<MMesh> const * const tfe;
+    };
+
+template<class MMesh>
+struct GFESpacePtrTFE {
+    GTypeOfFE<MMesh> const * const ptrTFE;
+    GFESpacePtrTFE(GTypeOfFE<MMesh> const * const pptrTFE=0) : ptrTFE(pptrTFE) {}
+    virtual  ~GFESpacePtrTFE() { if(ptrTFE) delete ptrTFE;}
+};
+    
+template<class MMesh> 
+class GFESpace :  public RefCounter,protected GFESpacePtrTFE<MMesh>,  public DataFENodeDF, public UniqueffId  {
+public:
+  typedef MMesh Mesh;
+  typedef GFElement<Mesh> FElement;
+  typedef typename Mesh::Element  Element;
+  typedef typename Mesh::BorderElement  BorderElement;
+  typedef typename Mesh::Rd  Rd;
+  typedef GTypeOfFE<Mesh> TypeOfFE;
+  typedef GQuadratureFormular<typename Element::RdHat> QFElement;
+  typedef GQuadratureFormular<typename BorderElement::RdHat>  QFBorderElement;
+
+  const Mesh &Th;
+
+  KN<const GTypeOfFE<Mesh> *>  TFE; 
+private:
+  
+public:
+  CountPointer<const Mesh> cmesh;
+  const int N; // dim espace d'arrive
+  const int Nproduit; // 1 if non constant Max number df par node. else Max number df par node.. 
+  const int nb_sub_fem; // nb de sous elements finis tensorise (independe au niveau des composantes)
+  int const* const dim_which_sub_fem;// donne les dependant des composantes liee a un meme sous element fini
+  const int   maxNbPtforInterpolation;  
+  const int   maxNbcoefforInterpolation;  
+
+  //   exemple si N=5,  
+  // dim_which_sub_fem[0]=0;
+  // dim_which_sub_fem[1] =1;
+  // dim_which_sub_fem[2]= 2
+  // dim_which_sub_fem[3] =2 
+  // dim_which_sub_fem[4] =3
+  //  =>
+  //  le  sous  elements fini 0 est lie a la composante 0 
+  //  le  sous  elements fini 1 est lie a la composante 1 
+  //  le  sous  elements fini 2 est lie aux composantes 2,3 
+  //  le  sous  elements fini 3 est lie a la composante 4 
+  //  donc pour les CL. les composante 2 et 3 sont lie car elle sont utiliser pour definir un
+  //  meme degre de libert\u00e9.
+  
+  //  par defaut P1                
+  
+    GFESpace(const Mesh & TTh,const GTypeOfFE<Mesh> & tfe=DataFE<Mesh>::P1,int nbequibe=0,int *equibe=0)
+    :
+    GFESpacePtrTFE<MMesh>(0),
+    DataFENodeDF(TTh.BuildDFNumbering(tfe.ndfonVertex,tfe.ndfonEdge,tfe.ndfonFace,tfe.ndfonVolume,nbequibe,equibe)),
+    Th(TTh),
+    TFE(1,0,&tfe), 
+    cmesh(TTh),
+    N(TFE[0]->N),
+    Nproduit(FirstDfOfNodeData ? 1 :MaxNbDFPerNode ),
+    nb_sub_fem(TFE[0]->nb_sub_fem),
+    dim_which_sub_fem(TFE[0]->dim_which_sub_fem),
+    maxNbPtforInterpolation(TFE[0]->NbPtforInterpolation),
+    maxNbcoefforInterpolation(TFE[0]->NbcoefforInterpolation)
+    
+    {
+	if(verbosity) cout << "  -- FESpace: Nb of Nodes " << NbOfNodes 
+	    << " Nb of DoF " << NbOfDF << endl;
+    }
+    
+  GFESpace(const GFESpace & Vh,int kk,int nbequibe=0,int *equibe=0);
+  GFESpace(const GFESpace ** Vh,int kk,int nbequibe=0,int *equibe=0);
+    
+  int FirstDFOfNode(int i) const {return FirstDfOfNodeData ? FirstDfOfNodeData[i] : i*Nproduit;}
+  int LastDFOfNode(int i)  const {return FirstDfOfNodeData ? FirstDfOfNodeData[i+1] : (i+1)*Nproduit;}
+  int NbDFOfNode(int i)  const {return FirstDfOfNodeData ? FirstDfOfNodeData[i+1]-FirstDfOfNodeData[i] : Nproduit;}
+  int MaximalNbOfNodes() const {return MaxNbNodePerElement;};
+  int MaximalNbOfDF() const {return MaxNbDFPerElement;};
+    const int * PtrFirstNodeOfElement(int k) const {
+      return NodesOfElement 
+	  ? NodesOfElement + (FirstNodeOfElement ? FirstNodeOfElement[k] : k*MaxNbNodePerElement)                 
+	  : 0;}   
+  
+  int SizeToStoreAllNodeofElement() const {  
+      return  FirstNodeOfElement 
+	  ?  FirstNodeOfElement[NbOfElements] 
+	  : MaxNbNodePerElement*NbOfElements;}   
+    
+  int NbOfNodesInElement(int k)   const {             
+      return FirstNodeOfElement 
+	  ?  FirstNodeOfElement[k+1] - FirstNodeOfElement[k] 
+	  : MaxNbNodePerElement ;}
+  int  esize() const { return  MaxNbDFPerElement*N*last_operatortype;}   // size to store all value of B. function        
+
+  
+  ~GFESpace()
+  {
+  }
+  // GFESpace(Mesh & TTh,int NbDfOnSommet,int NbDfOnEdge,int NbDfOnElement,int NN=1); 
+  int  renum();
+  
+  FElement operator[](int k) const { return FElement(this,k);} 
+  FElement operator[](const Element & K) const { return FElement(this,Th(K));} 
+  int  operator()(int k)const {return NbOfNodesInElement(k);}
+  int  operator()(int k,int i) const { //  the node i of element k
+      return NodesOfElement ?  *(PtrFirstNodeOfElement(k) + i)  : Th(k,i)  ;}
+  
+    /*
+      void Draw(const KN_<R>& U,const KN_<R>& Viso,int j=0,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const ; // Draw iso line
+    void Drawfill(const KN_<R>& U,const KN_<R>& Viso,int j=0,double rapz=1,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const ; // Draw iso line
+    
+    void Draw(const KN_<R>& U,const KN_<R> & Viso, R coef,int j0=0,int j1=1,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const  ; // Arrow
+    void Draw(const KN_<R>& U,const KN_<R>& V,const KN_<R> & Viso, R coef,int iu=0,int iv=0,float *colors=0,int nbcolors=0,bool hsv=true,bool drawborder=true) const  ; // Arrow
+    Rd MinMax(const KN_<R>& U,const KN_<R>& V,int j0,int j1,bool bb=true) const ;
+    Rd MinMax(const KN_<R>& U,int j0, bool bb=true) const ;
+    // void destroy() {RefCounter::destroy();}
+    */
+    bool isFEMesh() const { return ! NodesOfElement  && ( N==1) ;} // to make optim
+  template <class R>  
+  KN<R>  newSaveDraw(const KN_<R> & U,int composante,int & lg,KN<Rd> &Psub,KN<int> &Ksub,int op_U=0) const  ; 
+
+
+private: // for gibbs  
+  int gibbsv (long* ptvoi,long* vois,long* lvois,long* w,long* v);
+};
+
+template<class Mesh>
+inline GbaseFElement<Mesh>::GbaseFElement(  const GFESpace<Mesh> &aVh, int k) 
+  : Vh(aVh),T(Vh.Th[k]),tfe(aVh.TFE[k]),N(aVh.N),number(k){}
+
+template<class Mesh>    
+inline GbaseFElement<Mesh>::GbaseFElement(const   GbaseFElement & K,  const GTypeOfFE<Mesh> & atfe) 
+  : Vh(K.Vh),T(K.T),tfe(&atfe),N(Vh.N),number(K.number){}
+
+template<class Mesh>
+GFElement<Mesh>::GFElement(const GFESpace<Mesh> * VVh,int k) 
+  : GbaseFElement<Mesh>(*VVh,k) ,
+    p(this->Vh.PtrFirstNodeOfElement(k)),
+    nb(this->Vh.NbOfNodesInElement(k))    
+{} 
+
+template<class Mesh>
+inline   int  GFElement<Mesh>::operator[](int i) const {
+  return  p ? p[i] :  ((&this->T[i])-this->Vh.Th.vertices);}  
+
+template<class Mesh>
+inline   int  GFElement<Mesh>::operator()(int i,int df) const {
+  return  this->Vh.FirstDFOfNode(p ? p[i] :  ((&this->T[i])-this->Vh.Th.vertices)) + df;}  
+
+template<class Mesh>
+inline   int  GFElement<Mesh>::NbDoF(int i) const {
+  int node =p ? p[i] :  ((&this->T[i])-this->Vh.Th.vertices);
+  return  this->Vh.LastDFOfNode(node)-this->Vh.FirstDFOfNode(node);}  
+
+template<class Mesh>
+inline void GFElement<Mesh>::BF(const Rd & P,RNMK_ & val) const {
+  this->tfe->FB(Fop_D0|Fop_D1,this->Vh.Th,this->T,P,val);}  
+
+ 
+template<class Mesh>
+    inline void GFElement<Mesh>::BF(const What_d whatd,const Rd & P,RNMK_ & val) const { this->tfe->FB(whatd,this->Vh.Th,this->T,P,val);}
+    
+//template<class Mesh>
+ //   inline void GFElement<Mesh>::set(InterpolationMatrix<typename Mesh::Element::RdHat> &M) const { this->tfe->set(this->Vh.Th,this->T,&M);}
+
+template<class Mesh>
+inline   R GFElement<Mesh>::operator()(const Rd & PHat,
+                                const KN_<R> & u,int i,int op)  const
+{
+    return (*this->tfe)(*this,PHat,u,i,op);
+}
+
+template<class Mesh>
+inline  complex<R> GFElement<Mesh>::operator()(const RdHat & PHat,const KN_<complex<R> > & u,int i,int op)  const 
+{
+    complex<double> * pu=u; // pointeur du tableau
+    double *pr = static_cast<double*>(static_cast<void*>(pu));
+    
+    const KN_<R>  ur(pr,u.n,u.step*2);
+    const KN_<R>  ui(pr+1,u.n,u.step*2);
+    
+    return complex<R>((*this->tfe)(*this,PHat,ur,i,op),(*this->tfe)(*this,PHat,ui,i,op));
+}
+
+
+
+template<class Mesh>
+R GTypeOfFE<Mesh>::operator()(const GFElement<Mesh> & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const 
+{
+    R v[10000],vf[500];
+    ffassert(N*last_operatortype*NbDoF<=10000 && NbDoF <500 );
+    KNMK_<R> fb(v,NbDoF,N,last_operatortype); //  the value for basic fonction
+    KN_<R> fk(vf,NbDoF);
+    for (int i=0;i<NbDoF;i++) // get the local value
+	fk[i] = u[K(i)];
+    //  get value of basic function
+    FB( 1 << op ,K.Vh.Th,K.T,PHat,fb);  
+    R r = (fb('.',componante,op),fk);  
+    return r;
+}
+
+int nbdf_d(const int ndfitem[4],const  int nd[4]);
+int nbnode_d(const int ndfitem[4],const  int nd[4]);
+int *builddata_d(const int ndfitem[4],const int nd[4]);
+
+
+    
+    
+template<class Mesh>
+class GTypeOfFESum:  public  GTypeOfFE<Mesh> {
+    
+public:
+  typedef GFElement<Mesh> FElement;
+  typedef typename Mesh::Element  Element;
+  typedef typename Element::RdHat  RdHat;
+  typedef typename Mesh::Rd  Rd;
+  const int k; 
+  KN<const  GTypeOfFE<Mesh> *> teb;
+  KN<int> NN,DF,comp,numPtInterpolation;
+ 
+  GTypeOfFESum(const KN< GTypeOfFE<Mesh> const *> & t);
+  GTypeOfFESum(const GFESpace<Mesh> **,int kk);
+  GTypeOfFESum(const GFESpace<Mesh> &,int kk);
+    
+  void Build();  // the true constructor 
+    
+  void init(InterpolationMatrix<RdHat> & M,FElement * pK=0,int odf=0,int ocomp=0,int *pp=0) const;
+  void set(const Mesh & Th,const Element & K,InterpolationMatrix<RdHat> & M,int ocoef,int odf,int *nump ) const; // no change by deflaut 
+  void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, KNMK_<R> & val) const ;
+  ~GTypeOfFESum(){}
+} ;
+
+
+template<class Mesh>
+void GTypeOfFESum<Mesh>::FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, KNMK_<R> & val) const  
+{
+    val=0.0;
+    SubArray t(val.K());
+    for (int i=0;i<k;i++)
+      {
+	  int j=comp[i];
+	  int ni=NN[i];
+	  int di=DF[i];  
+	  int i1=i+1; 
+	  int nii=NN[i1];
+	  int dii=DF[i1];
+	  assert(ni<nii && di < dii);
+	  RNMK_ v(val(SubArray(dii-di,di),SubArray(nii-ni,ni),t));     
+	  if (j<=i)
+	      teb[i]->FB(whatd,Th,K,P,v);       
+	  else
+	      v=val(SubArray(DF[j+1]-DF[j],DF[j]),SubArray(NN[j+1]-NN[j],NN[j]),t);     
+      }
+} 
+
+
+
+template<class RdHat>
+template<class Mesh>
+InterpolationMatrix<RdHat>::InterpolationMatrix(const GFESpace<Mesh> &Vh)
+  :
+  N(Vh.N),np(Vh.maxNbPtforInterpolation),ncoef(Vh.maxNbcoefforInterpolation),
+  invariant(Vh.TFE.constant() ? Vh.TFE[0]->invariantinterpolationMatrix: false),
+  k(-1),
+  P(np),
+  comp(ncoef),
+  p(ncoef),
+  dofe(ncoef)
+{ 
+  Vh.TFE[0]->GTypeOfFE<Mesh>::init(*this,0,0,0,0);    
+}
+
+template<class RdHat>
+template<class Mesh>
+InterpolationMatrix<RdHat>::InterpolationMatrix(const GTypeOfFE<Mesh> & tef)
+  :
+  N(tef.N),np(tef.NbPtforInterpolation),ncoef(tef.NbcoefforInterpolation),
+  invariant(tef.invariantinterpolationMatrix),
+  k(-1),
+  P(np),
+  comp(ncoef),
+  p(ncoef),
+  dofe(ncoef)  
+{
+  //  virtual void init(InterpolationMatrix<RdHat> & M,FElement * pK=0,int odf=0,int ocomp=0,int *pp=0) const
+  tef.GTypeOfFE<Mesh>::init(*this,0,0,0,0);
+}
+
+template<class RdHat> template<class Mesh>
+void InterpolationMatrix<RdHat>::set(const GFElement<Mesh> & FK) 
+{
+  if(k==FK.number) return;
+  k=FK.number;
+  if(invariant) return;
+    FK.set(*this);
+  //assert(invariant);
+  // a faire ...
+}
+
+typedef  GTypeOfFE<Mesh3> TypeOfFE3;
+typedef  GTypeOfFE<Mesh3> TypeOfFE3;
+typedef  GFESpace<Mesh3> FESpace3;
+typedef  GFESpace<Mesh2> FESpace2;
+typedef  GFElement<Mesh3> FElement3;
+typedef  GFElement<Mesh2> FElement2;
+typedef  GFElement<Mesh3> FElement3;
+typedef  GbaseFElement<Mesh2> baseFElement2;
+typedef  GbaseFElement<Mesh3> baseFElement3;
+
+}
+
+
+#endif
diff --git a/src/femlib/FQuadTree.cpp b/src/femlib/FQuadTree.cpp
new file mode 100644
index 0000000..eb186dc
--- /dev/null
+++ b/src/femlib/FQuadTree.cpp
@@ -0,0 +1,1125 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+// ORIG-DATE:     Dec 97
+#include <cmath>
+#include <cstdlib>
+#include "error.hpp"
+#include <iostream>
+
+#include <limits.h>
+//#include <stdio.h>
+#include <string.h>
+#include <cstdlib>
+using namespace std;
+
+#include "RNM.hpp"
+#include "rgraph.hpp"
+
+#include "fem.hpp"
+using namespace Fem2D;
+
+
+
+
+
+#ifndef NEWQUADTREE
+
+//  new version ----------
+//  ----------------------
+#ifdef DRAWING
+void FQuadTree::PlotQuad(I2 pp,long hb)
+{
+		  IMoveTo(pp.x,pp.y);
+		  ILineTo(pp.x+hb,pp.y);
+		  ILineTo(pp.x+hb,pp.y+hb);
+		  ILineTo(pp.x   ,pp.y+hb);
+		  ILineTo(pp.x   ,pp.y);
+}
+
+void FQuadTree::PlotX(I2 p,long hb)
+{	
+  IMoveTo(p.x,     p.y);
+  ILineTo(p.x+hb/2,p.y+hb/2);
+  IMoveTo(p.x+hb/2,p.y);
+  ILineTo(p.x     ,p.y+hb/2);
+}
+void  FQuadTree::Draw()
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  I2 pp[MaxDeep];
+  //long ii[  MaxDeep ], jj [ MaxDeep];
+  int l=0; // level
+  QuadTreeBox * b;
+  IntQuad hb =  MaxISize;
+  if (!root) return ;
+  // long kkk =0;
+  pb[0]=  root;
+  pi[0]= root->n>0 ?(int)  root->n : 4  ;;
+  pp[0].x=pp[0].y=0;//ii[0]=jj[0]=0;
+  do{    
+    b= pb[l];
+
+    while (pi[l]--)
+      { 
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	    { // 
+	      for (int k=0;k<b->n;k++)
+		{
+		  DrawMark(*b->v[k],0.002);
+
+		}
+	      break;
+	    }
+	else // Pointer QuadTreeBox 
+	    { 
+	      int lll = pi[l];
+	      QuadTreeBox *b0=b;
+	      
+	      if ((b=b->b[lll])) 
+		{ 
+		  hb >>=1 ; // div by 2
+		  I2 ppp(pp[l],lll,hb);
+		  
+		  pb[++l]=  b;
+		  pi[l]= 4;
+		  pp[l]=ppp;
+                  PlotQuad(pp[l],hb);
+		}
+	      else
+		{
+		  I2 ppp(pp[l],lll,hb/2);		 
+		  b=b0;
+                  PlotX(ppp,hb/2);
+		}
+	    }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+
+}
+
+#endif
+
+Vertex *  FQuadTree::NearestVertex(long xi,long yj)
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  I2 pp[  MaxDeep ];
+  int l=0; // level
+  QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  I2   p0(0,0);
+  I2  plus( xi<MaxISize?(xi<0?0:xi):MaxISize-1,yj<MaxISize?(yj<0?0:yj):MaxISize-1);
+  
+  Vertex *vn=0;
+  
+  // init for optimisation ---
+  b = root;
+  long  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+      long hb2 = hb >> 1 ;
+       int k = plus.Case(hb2);//(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+      QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;
+      p0.Add(k,hb2);	
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for( int k=0;k<n0;k++)
+	{
+	  I2 i2 =  R2ToI2(b->v[k]);
+	  h0 = I2(i2,plus).norm();//NORM(iplus,i2.x,jplus,i2.y);
+	  if (h0 <h) {
+	    h = h0;
+	    vn = b->v[k];}
+	  NbVerticesSearch++;
+	}
+      return vn;
+    }
+  // general case -----
+  pb[0]= b;
+  pi[0]=b->n>0 ?(int)  b->n : 4  ;
+  pp[0]=p0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+        int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  R2ToI2(b->v[k]);
+	    h0 = I2(i2,plus).norm();//  NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) 
+	      {
+		h = h0;
+		vn = b->v[k];
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k]))
+	      {
+		hb >>=1 ; // div by 2
+		I2 ppp(pp[l],k,hb);
+		
+		if  ( ppp.interseg(plus,hb,h) )//(INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    pp[l]=ppp;		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return vn;
+}
+
+
+
+Vertex *  FQuadTree::ToClose(const R2 & v,R seuil,long hx,long hy)
+{
+  I2 H(hx,hy);
+  const I2 p(XtoI(v.x),YtoJ(v.y));
+  const R2 X(v);
+  R seuil2 = seuil*seuil;
+ // const Metric  Mx(v.m);
+
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+    I2 pp[  MaxDeep ];
+
+//  long ii[  MaxDeep ], jj [ MaxDeep];
+  int l=0; // level
+  QuadTreeBox * b;
+  long h=MaxISize;
+  long hb =  MaxISize;
+  //long i0=0,j0=0;
+  I2 p0(0,0);
+  //  Vertex *vn=0;
+  
+  if (!root->n)
+    return 0; // empty tree 
+  
+  // general case -----
+  pb[0]= root;
+  pi[0]=  root->n>0 ?(int)  root->n : 4 ;
+  pp[0]=p0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+        int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    Vertex & V(*b->v[k]);
+	    I2 i2 =  R2ToI2(V);
+	    if ( I2(i2,p).less(H) )
+	      {
+		R2 XY(X,V);
+		R dd;
+	        if( (dd= (XY,XY) ) < seuil2 ) // LengthInterpole(Mx(XY), b->v[k]->m(XY)))  < seuil )
+	          {// cout << dd << " " << XY << " ";
+		    return &V; }
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+	        I2 ppp(pp[l],k,hb);
+		if (ppp.interseg(p,hb,H))
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    pp[l]=ppp;		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return 0;
+}
+
+
+void  FQuadTree::Add( Vertex & w)
+{
+  QuadTreeBox ** pb , *b;
+  I2 p(XtoI(w.x),YtoJ(w.y));
+  long l=MaxISize;
+  pb = &root;
+  //    cout << pb << " " << &root << endl;
+  while( (b=*pb) && (b->n<0))
+    { 
+      b->n--;
+      l >>= 1;
+      pb = &b->b[p.Case(l)];
+    }
+  if  (b) {      
+    if (b->n > 3 &&  b->v[3] == &w) return;
+    if (b->n > 2 &&  b->v[2] == &w) return;
+    if (b->n > 1 &&  b->v[1] == &w) return;
+    if (b->n > 0 &&  b->v[0] == &w) return;
+  }
+  throwassert(l);
+  while ((b= *pb) && (b->n == 4)) // the QuadTreeBox is full
+    { 
+      Vertex *v4[4]; // copy of the QuadTreeBox vertices
+      
+      v4[0]= b->v[0];
+      v4[1]= b->v[1];
+      v4[2]= b->v[2];
+      v4[3]= b->v[3];
+      b->n = -b->n; // mark is pointer QuadTreeBox
+      b->b[0]=b->b[1]=b->b[2]=b->b[3]=0; // set empty QuadTreeBox ptr
+      l >>= 1;    // div the size by 2
+      for (int k=0;k<4;k++) // for the 4 vertices find the sub QuadTreeBox ij
+	{ 
+	  int ij;
+	  QuadTreeBox * bb =  b->b[ij=R2ToI2(v4[k]).Case(l)];
+	  if (!bb) 
+	    bb=b->b[ij]=NewQuadTreeBox(); // alloc the QuadTreeBox 
+	  //    cout << bb << " " << k << " "  << ij <<  endl;
+	  bb->v[bb->n++] = v4[k];
+	}
+      pb = &b->b[p.Case(l)];
+    }
+  if (!(b = *pb))
+    b=*pb= NewQuadTreeBox(); //  alloc the QuadTreeBox 
+  //   cout << b << " " << b->n << endl;
+  b->v[b->n++]=&w; // we add the vertex 
+  NbVertices++;    
+}
+
+
+FQuadTree::FQuadTree(Vertex * v,R2 Pmin,R2 Pmax,long nbv)
+  :
+  th(0),
+  lenStorageQuadTreeBox(Max(abs(nbv),1000L)),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0),
+  cMin(Pmin-(Pmax-Pmin)/2),
+  cMax(Pmax+(Pmax-Pmin)/2),
+  coef( MaxISize/Norme_infty(cMax-cMin))
+  
+{ 
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+  for (long i=0;i<nbv;i++) 
+    Add(v[i]);
+#ifdef DRAWING1
+  Draw();
+#endif
+}
+
+FQuadTree::FQuadTree(Mesh * t,R2 Pmin,R2 Pmax,long nbv) : 
+ lenStorageQuadTreeBox(t->nv/8+100),
+  th(t),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  cMin(Pmin-(Pmax-Pmin)/2),
+  cMax(Pmax+(Pmax-Pmin)/2),
+  coef( MaxISize/Norme_infty(cMax-cMin))
+  
+{ 
+  if (nbv == -1) nbv = t->nv;
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+//  throwassert( MaxISize > MaxICoor);
+  if (t)
+  for (long i=0;i<nbv;i++) 
+    Add(t->vertices[i]);
+#ifdef DRAWING1
+  Draw();
+#endif
+}
+
+FQuadTree::FQuadTree(Mesh* t,long tnv,R2 Pmin,R2 Pmax,long nbv) : 
+ lenStorageQuadTreeBox(tnv/8+100),
+  th(t),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  cMin(Pmin-(Pmax-Pmin)/2),
+  cMax(Pmax+(Pmax-Pmin)/2),
+  coef( MaxISize/Norme_infty(cMax-cMin))
+  
+{ 
+  if (nbv == -1) nbv = tnv;
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+//  throwassert( MaxISize > MaxICoor);
+  if (t)
+  for (long i=0;i<nbv;i++) 
+    Add(t->vertices[i]);
+#ifdef DRAWING1
+  Draw();
+#endif
+}
+
+
+FQuadTree::FQuadTree() : 
+  lenStorageQuadTreeBox(100),
+  th(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  cMin(0,0),cMax(0,0),coef(0)
+{
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+}
+FQuadTree::StorageQuadTreeBox::StorageQuadTreeBox(long ll,StorageQuadTreeBox *nn)
+{
+  len = ll;
+  n = nn;
+  b = new QuadTreeBox[ll];
+  for (int i = 0; i <ll;i++)
+    b[i].n =0,b[i].b[0]=b[i].b[1]=b[i].b[2]=b[i].b[3]=0;
+  bc =b;
+  be = b +ll;
+  throwassert(b);
+}
+
+ FQuadTree::StorageQuadTreeBox::~StorageQuadTreeBox()
+    { //cout <<  "~StorageQuadTreeBox " << this << " n " << n << " b " << b << endl;
+      if(n) delete n;
+      delete [] b;
+    }
+
+FQuadTree::~FQuadTree()
+{
+  delete sb; 
+}
+
+ostream& operator <<(ostream& f, const  FQuadTree & qt)
+{ 
+  f << " the quadtree "  << endl;
+  f << " NbQuadTreeBox = " << qt.NbQuadTreeBox 
+    << " Nb Vertices = " <<  qt.NbVertices << endl;
+  f << " NbQuadTreeBoxSearch " << qt.NbQuadTreeBoxSearch  
+    << " NbVerticesSearch " << qt.NbVerticesSearch << endl;
+  f << " SizeOf QuadTree" << qt.SizeOf() << endl;
+  //     return  dump(f,*qt.root);
+  return  f;
+}
+
+Vertex *  FQuadTree::NearestVertexWithNormal(const R2 &P)//(long xi,long yj)
+{
+  long xi(XtoI(P.x)),yj(YtoJ(P.y));
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  //long ii[  MaxDeep ], jj [ MaxDeep];
+  I2 pp[ MaxDeep];
+  int l; // level
+  QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  I2   p0(0,0);
+  I2  plus( xi<MaxISize?(xi<0?0:xi):MaxISize-1,yj<MaxISize?(yj<0?0:yj):MaxISize-1);
+  
+  Vertex *vn=0;
+ // Vertex *vc;  // the current vertex
+  
+  // init for optimisation ---
+  b = root;
+  long  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+      long hb2 = hb >> 1 ;
+      int k = plus.Case(hb2);//(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+      QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;	
+      p0.Add(k,hb2);	
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for(int k=0;k<n0;k++)
+	{
+	  Vertex * v=b->v[k];
+	  if (v->ninside(P)) {
+	   I2 i2 =  R2ToI2(v);
+	  //   try if is in the right sens -- 
+	   h0 = I2(i2,plus).norm();// h0 = NORM(iplus,i2.x,jplus,i2.y);
+	   if (h0 <h) {
+	    h = h0;
+	    vn = v;}
+	   NbVerticesSearch++;}
+	}
+	if (vn) return vn; 
+    }
+  // general case -----
+  // INITIALISATION OF THE STACK 
+  l =0; // level 
+  pb[0]= b;
+  pi[0]= b->n>0 ?(int)  b->n : 4  ;
+  pp[0]=p0;
+  h=hb;
+  L1: 
+  do {   // walk on the tree  
+    b= pb[l];
+    while (pi[l]--) // loop on 4 element of the box
+      { 	      
+       int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+       Vertex * v=b->v[k];
+	   if (v->ninside(P) ) {	    
+	     NbVerticesSearch++;
+	     I2 i2 =  R2ToI2(v);
+	     // if good sens when try -- 
+	     h0 = I2(i2,plus).norm();//  NORM(iplus,i2.x,jplus,i2.y);
+	     if (h0 <h) 
+	      {
+		   h = h0;
+		   vn =v;
+	       }}
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+		I2 ppp(pp[l],k,hb);
+		
+		if  ( ppp.interseg(plus,hb,h) )//(INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    pp[l]=ppp;		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  if (!vn && b != root )
+   {// cas particulier on repart du sommet on avais rien trouver 
+    b=root;
+   hb =  MaxISize;
+   p0=I2(0,0);
+   l=0;
+   pb[0]= b;
+   pi[0]= b->n>0 ?(int)  b->n : 4  ;
+   pp[0]=I2(0,0);
+   
+     goto L1;
+   }
+  return vn;
+}
+
+#else
+
+
+//  nouvelle version a tester 
+
+
+
+#define INTER_SEG(a,b,x,y) (((y) > (a)) && ((x) <(b)))
+#define ABS(i) ((i)<0 ?-(i) :(i))
+#define MAX1(i,j) ((i)>(j) ?(i) :(j))
+#define NORM(i1,j1,i2,j2) MAX1(ABS((i1)-(j1)),ABS((i2)-(j2)))
+
+#define IJ(i,j,l) ( ( j & l) ? (( i & l) ? 3 : 2 ) :( ( i & l)? 1 : 0 ))
+#define I_IJ(k,l)  (( k&1) ? l : 0)
+#define J_IJ(k,l)  (( k&2) ? l : 0)
+
+
+#ifdef DRAWING
+// old version ----  
+
+void  FQuadTree::Draw()
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  long ii[  MaxDeep ], jj [ MaxDeep];
+  int l=0; // level
+  QuadTreeBox * b;
+  IntQuad hb =  MaxISize;
+  if (!root) return ;
+  long kkk =0;
+  pb[0]=  root;
+  pi[0]= root->n>0 ?(int)  root->n : 4  ;;
+  ii[0]=jj[0]=0;
+  do{    
+    b= pb[l];
+
+    while (pi[l]--)
+      { 
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	    { // 
+	      for (int k=0;k<b->n;k++)
+		{
+		  DrawMark(*b->v[k],0.002);
+
+		}
+	      break;
+	    }
+	else // Pointer QuadTreeBox 
+	    { 
+	      int lll = pi[l];
+	      QuadTreeBox *b0=b;
+	      
+	      if ((b=b->b[lll])) 
+		{ 
+		  hb >>=1 ; // div by 2
+		  long iii = ii[l]+I_IJ(lll,hb);
+		  long jjj = jj[l]+J_IJ(lll,hb);
+		  
+		  pb[++l]=  b;
+		  pi[l]= 4;
+		  ii[l]= iii;
+		  jj[l]= jjj;
+		  
+		  IMoveTo(ii[l],jj[l]);
+		  ILineTo(ii[l]+hb,jj[l]);
+		  ILineTo(ii[l]+hb,jj[l]+hb);
+		  ILineTo(ii[l]   ,jj[l]+hb);
+		  ILineTo(ii[l]   ,jj[l]);
+		  
+		  
+		}
+	      else
+		{
+		  long iii = ii[l]+I_IJ(lll,hb/2);
+		  long jjj = jj[l]+J_IJ(lll,hb/2);
+		  b=b0;
+
+		  IMoveTo(iii,     jjj);
+		  ILineTo(iii+hb/2,jjj+hb/2);
+		  IMoveTo(iii+hb/2,jjj);
+		  ILineTo(iii     ,jjj+hb/2);
+
+		}
+	    }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+
+}
+
+#endif
+
+Vertex *  FQuadTree::NearestVertex(long xi,long yj)
+{
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  long ii[  MaxDeep ], jj [ MaxDeep];
+  int l=0; // level
+  QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  long  i0=0,j0=0;
+  long  iplus( xi<MaxISize?(xi<0?0:xi):MaxISize-1);
+  long  jplus( yj<MaxISize?(yj<0?0:yj):MaxISize-1);
+  
+  Vertex *vn=0;
+  
+  // init for optimisation ---
+  b = root;
+  long  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+      long hb2 = hb >> 1 ;
+       int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+      QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;	
+      i0 += I_IJ(k,hb2); // i orign of QuadTreeBox
+      j0 += J_IJ(k,hb2); // j orign of QuadTreeBox 
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for( int k=0;k<n0;k++)
+	{
+	  I2 i2 =  R2ToI2(b->v[k]);
+	  h0 = NORM(iplus,i2.x,jplus,i2.y);
+	  if (h0 <h) {
+	    h = h0;
+	    vn = b->v[k];}
+	  NbVerticesSearch++;
+	}
+      return vn;
+    }
+  // general case -----
+  pb[0]= b;
+  pi[0]=b->n>0 ?(int)  b->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+        int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    I2 i2 =  R2ToI2(b->v[k]);
+	    h0 = NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) 
+	      {
+		h = h0;
+		vn = b->v[k];
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k]))
+	      {
+		hb >>=1 ; // div by 2
+	        long iii = ii[l]+I_IJ(k,hb);
+	        long jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return vn;
+}
+
+
+
+Vertex *  FQuadTree::ToClose(const R2 & v,R seuil,long hx,long hy)
+{
+  const long i=XtoI(v.x);
+  const long j=YtoJ(v.y);
+  const R2 X(v);
+  R seuil2 = seuil*seuil;
+ // const Metric  Mx(v.m);
+
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  long ii[  MaxDeep ], jj [ MaxDeep];
+  int l=0; // level
+  QuadTreeBox * b;
+  long h=MaxISize;
+  long hb =  MaxISize;
+  long i0=0,j0=0;
+  
+  //  Vertex *vn=0;
+  
+  if (!root->n)
+    return 0; // empty tree 
+  
+  // general case -----
+  pb[0]= root;
+  pi[0]=  root->n>0 ?(int)  root->n : 4 ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+        int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    Vertex & V(*b->v[k]);
+	    I2 i2 =  R2ToI2(V);
+	    if ( ABS(i-i2.x) <hx && ABS(j-i2.y) <hy )
+	      {
+		R2 XY(X,V);
+		R dd;
+	      // old code	        if( Mx(XY) + b->v[k]->m(XY) < seuil )
+	        if( (dd= (XY,XY) ) < seuil ) // LengthInterpole(Mx(XY), b->v[k]->m(XY)))  < seuil )
+		  {
+		    //  cout <<  CurrentTh->Number(v) << "is To Close " 
+		    // << CurrentTh->Number( b->v[k]) << " l=" <<dd<<endl;
+		    return &V; 
+		  }
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+	        long iii = ii[l]+I_IJ(k,hb);
+		long jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,i-hx,i+hx) && INTER_SEG(jjj,jjj+hb,j-hy,j+hy)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return 0;
+}
+
+
+void  FQuadTree::Add( Vertex & w)
+{
+  QuadTreeBox ** pb , *b;
+  long i= XtoI(w.x), j=YtoJ(w.y),l=MaxISize;
+  pb = &root;
+  //    cout << pb << " " << &root << endl;
+  while( (b=*pb) && (b->n<0))
+    { 
+      b->n--;
+      l >>= 1;
+      pb = &b->b[IJ(i,j,l)];
+    }
+  if  (b) {      
+    if (b->n > 3 &&  b->v[3] == &w) return;
+    if (b->n > 2 &&  b->v[2] == &w) return;
+    if (b->n > 1 &&  b->v[1] == &w) return;
+    if (b->n > 0 &&  b->v[0] == &w) return;
+  }
+  throwassert(l);
+  while ((b= *pb) && (b->n == 4)) // the QuadTreeBox is full
+    { 
+      Vertex *v4[4]; // copy of the QuadTreeBox vertices
+      
+      v4[0]= b->v[0];
+      v4[1]= b->v[1];
+      v4[2]= b->v[2];
+      v4[3]= b->v[3];
+      b->n = -b->n; // mark is pointer QuadTreeBox
+      b->b[0]=b->b[1]=b->b[2]=b->b[3]=0; // set empty QuadTreeBox ptr
+      l >>= 1;    // div the size by 2
+      for (int k=0;k<4;k++) // for the 4 vertices find the sub QuadTreeBox ij
+	{ 
+	  int ij;
+	  QuadTreeBox * bb =  b->b[ij=IJ(XtoI(v4[k]->x),YtoJ(v4[k]->y),l)];
+	  if (!bb) 
+	    bb=b->b[ij]=NewQuadTreeBox(); // alloc the QuadTreeBox 
+	  //    cout << bb << " " << k << " "  << ij <<  endl;
+	  bb->v[bb->n++] = v4[k];
+	}
+      pb = &b->b[IJ(i,j,l)];
+    }
+  if (!(b = *pb))
+    b=*pb= NewQuadTreeBox(); //  alloc the QuadTreeBox 
+  //   cout << b << " " << b->n << endl;
+  b->v[b->n++]=&w; // we add the vertex 
+  NbVertices++;    
+}
+
+FQuadTree::FQuadTree(Mesh * t,R2 Pmin,R2 Pmax,long nbv) : 
+  th(t),
+  lenStorageQuadTreeBox(t->nv/8+100),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0),
+  cMin(Pmin-(Pmax-Pmin)/2),
+  cMax(Pmax+(Pmax-Pmin)/2),
+  coef( MaxISize/Norme_infty(cMax-cMin))
+  
+{ 
+  if (nbv == -1) nbv = t->nv;
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+//  throwassert( MaxISize > MaxICoor);
+  if (t)
+  for (long i=0;i<nbv;i++) 
+    Add(t->vertices[i]);
+#ifdef DRAWING1
+  Draw();
+#endif
+}
+
+FQuadTree::FQuadTree() : 
+  th(0),
+  lenStorageQuadTreeBox(100),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0),
+  coef(0),cMin(0,0),cMax(0,0)
+{
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+}
+FQuadTree::StorageQuadTreeBox::StorageQuadTreeBox(long ll,StorageQuadTreeBox *nn)
+{
+  len = ll;
+  n = nn;
+  b = new QuadTreeBox[ll];
+  for (int i = 0; i <ll;i++)
+    b[i].n =0,b[i].b[0]=b[i].b[1]=b[i].b[2]=b[i].b[3]=0;
+  bc =b;
+  be = b +ll;
+  throwassert(b);
+}
+
+FQuadTree::~FQuadTree()
+{
+  delete sb; 
+}
+
+ostream& operator <<(ostream& f, const  FQuadTree & qt)
+{ 
+  f << " the quadtree "  << endl;
+  f << " NbQuadTreeBox = " << qt.NbQuadTreeBox 
+    << " Nb Vertices = " <<  qt.NbVertices << endl;
+  f << " NbQuadTreeBoxSearch " << qt.NbQuadTreeBoxSearch  
+    << " NbVerticesSearch " << qt.NbVerticesSearch << endl;
+  f << " SizeOf QuadTree" << qt.SizeOf() << endl;
+  //     return  dump(f,*qt.root);
+  return  f;
+}
+
+Vertex *  FQuadTree::NearestVertexWithNormal(const R2 &P)//(long xi,long yj)
+{
+  long xi(XtoI(P.x)),yj(YtoJ(P.y));
+  QuadTreeBox * pb[ MaxDeep ];
+  int  pi[ MaxDeep  ];
+  long ii[  MaxDeep ], jj [ MaxDeep];
+  int l; // level
+  QuadTreeBox * b;
+  IntQuad  h=MaxISize,h0;
+  IntQuad hb =  MaxISize;
+  long  i0=0,j0=0;
+  long  iplus( xi<MaxISize?(xi<0?0:xi):MaxISize-1);
+  long  jplus( yj<MaxISize?(yj<0?0:yj):MaxISize-1);
+  
+  Vertex *vn=0;
+ // Vertex *vc;  // the current vertex
+  
+  // init for optimisation ---
+  b = root;
+  long  n0;
+  if (!root->n)
+    return vn; // empty tree 
+  
+  while( (n0 = b->n) < 0) 
+    {
+      // search the non empty 
+      // QuadTreeBox containing  the point (i,j)
+      long hb2 = hb >> 1 ;
+      int k = IJ(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+      QuadTreeBox * b0= b->b[k];
+      if ( ( b0 == 0) || (b0->n == 0) ) 
+	break; // null box or empty   => break 	    
+      NbQuadTreeBoxSearch++;
+      b=b0;	
+      i0 += I_IJ(k,hb2); // i orign of QuadTreeBox
+      j0 += J_IJ(k,hb2); // j orign of QuadTreeBox 
+      hb = hb2; 
+    }
+  
+  
+  if ( n0 > 0) 
+    {  
+      for(int k=0;k<n0;k++)
+	{
+	  Vertex * v=b->v[k];
+	  if (v->ninside(P)) {
+	   I2 i2 =  R2ToI2(v);
+	  //   try if is in the right sens -- 
+	   h0 = NORM(iplus,i2.x,jplus,i2.y);
+	   if (h0 <h) {
+	    h = h0;
+	    vn = v;}
+	   NbVerticesSearch++;}
+	}
+	if (vn) return vn; 
+    }
+  // general case -----
+  // INITIALISATION OF THE STACK 
+  l =0; // level 
+  pb[0]= b;
+  pi[0]= b->n>0 ?(int)  b->n : 4  ;
+  ii[0]=i0;
+  jj[0]=j0;
+  h=hb;
+  L1: 
+  do {   // walk on the tree  
+    b= pb[l];
+    while (pi[l]--) // loop on 4 element of the box
+      { 	      
+       int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+       Vertex * v=b->v[k];
+	   if (v->ninside(P) ) {	    
+	     NbVerticesSearch++;
+	     I2 i2 =  R2ToI2(v);
+	     // if good sens when try -- 
+	     h0 = NORM(iplus,i2.x,jplus,i2.y);
+	     if (h0 <h) 
+	      {
+		   h = h0;
+		   vn =v;
+	       }}
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k])) 
+	      {
+		hb >>=1 ; // div by 2
+		long iii = ii[l]+I_IJ(k,hb);
+		long jjj = jj[l]+J_IJ(k,hb);
+		
+		if  (INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : 4  ;
+		    ii[l]= iii;
+		    jj[l]= jjj;
+		    
+		  }
+		else
+		 b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  if (!vn && b != root )
+   {// cas particulier on repart du sommet on avais rien trouver 
+    b=root;
+   hb =  MaxISize;
+   i0=0;
+   j0=0;
+   l=0;
+   pb[0]= b;
+   pi[0]= b->n>0 ?(int)  b->n : 4  ;
+   ii[0]=i0;
+   jj[0]=j0;
+   
+     goto L1;
+   }
+  return vn;
+}
+
+#endif
+
diff --git a/src/femlib/FQuadTree.hpp b/src/femlib/FQuadTree.hpp
new file mode 100644
index 0000000..0e2fb90
--- /dev/null
+++ b/src/femlib/FQuadTree.hpp
@@ -0,0 +1,155 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+// AUTHOR:   F. Hecht,    
+// ORG    :  UMPC
+// E-MAIL :   Frederic.Hecht at Inria.fr   
+//
+// ORIG-DATE:     Dec 97
+
+namespace Fem2D {
+const int MaxDeep = 30;
+typedef  long  IntQuad;
+const IntQuad MaxISize = ( 1L << MaxDeep);
+
+
+class Mesh;
+//typename Vertex;
+
+class FQuadTree {
+ public:
+  class I2 { public:
+     static bool INTER_SEG1d(long a,long b,long x,long y) { return (((y) > (a)) && ((x) <(b)));}
+     long x,y;
+     I2() {}
+     I2(long i,long j): x(i),y(j) {}
+     I2(const I2 &pp,long k,long l): x(pp.x+(( k&1) ? l : 0)),y(pp.y+(( k&2) ? l : 0)) {}
+     void Add(long k,long l) { x+= (( k&1) ? l : 0) ; y+= (( k&2) ? l : 0);}
+     I2(const I2 &A,const I2 &B) : x(B.x-A.x),y(B.y-A.y) {}
+
+     long Case(long l) const  { return ( ( y & l) ? (( x & l) ? 3 : 2 ) :( ( x & l)? 1 : 0 ));}
+     long norm() const { return Max(abs(x),abs(y));}
+     bool less(I2 h) const  { return abs(x) <h.x && abs(y) <h.y;}
+     bool interseg(I2 pp,long hb,long h) const { 
+        return INTER_SEG1d(x,x+hb,pp.x-h,pp.x+h) && INTER_SEG1d(y,y+hb,pp.y-h,pp.y+h);}
+     bool interseg(const I2 &pp,long hb,const I2 &h) const { 
+        return INTER_SEG1d(x,x+hb,pp.x-h.x,pp.x+h.x) && INTER_SEG1d(y,y+hb,pp.y-h.y,pp.y+h.y);}
+  };
+
+  class QuadTreeBox { 
+  public:
+
+    long n; // if n < 4 => Vertex else =>  QuadTreeBox;
+    union {
+      QuadTreeBox *b[4];
+      Vertex * v[4];
+    };
+    
+
+  }; // end class QuadTreeBox  /////////////////
+
+  class StorageQuadTreeBox {
+  public:
+    QuadTreeBox *b,*bc,*be;
+    long len;
+    StorageQuadTreeBox *n; // next StorageQuadTreeBox
+    StorageQuadTreeBox(long ,StorageQuadTreeBox * =0);
+    ~StorageQuadTreeBox();
+    long  SizeOf() const {
+      return len*sizeof(QuadTreeBox)+sizeof(StorageQuadTreeBox)+ (n?n->SizeOf():0);
+    }
+  }; // end class  StorageQuadTreeBox 
+  
+  StorageQuadTreeBox * sb;
+  
+  
+  long  lenStorageQuadTreeBox;
+
+public:
+  QuadTreeBox * root;
+  Mesh *th;
+
+  long NbQuadTreeBoxSearch,NbVerticesSearch;
+  long NbQuadTreeBox,NbVertices;
+  
+  R2 cMin,cMax; //  box of QuadTree
+  R coef; //	
+
+
+  long XtoI(R x) { return  (long) ((Max(Min(x,cMax.x),cMin.x)-cMin.x)*coef);}
+  long YtoJ(R y) { return  (long) ((Max(Min(y,cMax.y),cMin.y)-cMin.y)*coef);}
+  R ItoX(long i){ return double(i)*coef+cMin.x ;}
+  R ItoY(long j){ return double(j)*coef+cMin.y ;}
+  I2  R2ToI2(const R2 &P) { return I2(XtoI(P.x),YtoJ(P.y));}
+  I2  R2ToI2(const R2 *P) { return I2(XtoI(P->x),YtoJ(P->y));}
+
+  
+  Vertex * NearestVertex(const R2 & P) { return NearestVertex(XtoI(P.x),YtoJ(P.y));}
+  Vertex * NearestVertexWithNormal(const R2 & P);
+  // { return NearestVertexWithNormal(XtoI(P.x),YtoJ(P.y));}
+  
+  Vertex * NearestVertex(long i,long j);
+  
+//  Vertex *  NearestVertexWithNormal(long i,long j); // new version
+  Vertex *  ToClose(const R2 & ,R ,long,long);
+  Vertex *  ToClose(const R2 & P,R delta){
+      long hx = (long) (coef*delta);
+      return ToClose(P,delta,hx,hx);}
+  long SizeOf() const {return sizeof(FQuadTree)+sb->SizeOf();}
+
+#ifdef DRAWING
+  void  IMoveTo(long i,long j)
+{  rmoveto(float(i)/coef+cMin.x ,float(j)/coef+cMin.y  );}
+
+void  ILineTo(long i,long j)
+ {rlineto(float(i)/coef+cMin.x ,float(j)/coef+cMin.y  );}
+    void Draw();
+  void PlotQuad(I2 pp,long hb);
+  void PlotX(I2 pp,long hb);
+
+#endif
+
+  void  Add( Vertex & w);
+
+  QuadTreeBox* NewQuadTreeBox()
+  {
+    ///cout << "NewQuadTreeBox " << sb << " " << sb->bc << " " 
+    //<< sb->be << " " <<lenStorageQuadTreeBox <<endl;
+    if(! (sb->bc<sb->be)) 
+	sb=new StorageQuadTreeBox(lenStorageQuadTreeBox,sb);
+
+    throwassert(sb && (sb->bc->n == 0));
+    NbQuadTreeBox++;
+    return sb->bc++;
+  }
+  ~FQuadTree();
+  FQuadTree(Mesh* t,long tnv,R2 Pmin,R2 Pmax,long nbv=-1);
+  FQuadTree(Mesh * t,R2 Pmin,R2 Pmax,long nbv=-1);
+  FQuadTree(Vertex * v,R2 Pmin,R2 Pmax,long nbv);
+  FQuadTree();
+  friend ostream& operator <<(ostream& f, const  FQuadTree & qt);
+
+
+	
+};
+//#undef IJ
+
+
+} // name space 
+
diff --git a/src/femlib/GQuadTree.cpp b/src/femlib/GQuadTree.cpp
new file mode 100644
index 0000000..0a94bf9
--- /dev/null
+++ b/src/femlib/GQuadTree.cpp
@@ -0,0 +1,854 @@
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : Generic Tree (binairy, Quad, Oct)   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include <cmath>
+#include <cstdlib>
+#include "error.hpp"
+#include <iostream>
+#include <climits>
+#include  <cfloat>
+#include <cstring>
+#include "ufunction.hpp"
+#include "HeapSort.hpp"
+using namespace std;
+
+
+#include "GenericMesh.hpp"
+#include "Mesh1dn.hpp"
+#include "Mesh2dn.hpp"
+#include "Mesh3dn.hpp"
+
+
+
+
+
+namespace EF23 {
+  
+  //  new version ----------
+  //  ----------------------
+  template<class Rd>
+  void OrthoProject(const Rd &P,const Rd &A,const Rd & B,R * l)
+  {
+    Rd AB(A,B),AP(A,P),BP(B,P);
+    R pa=(AB,AP),pb=(AB,BP);
+    //  (l0 PA + l1 PB , AB)=0
+    //   l0 pa + l1 pb = 0
+    //   l0 + l1 =1
+    //   l0 (pa - pb) = - pb;
+    l[0] = - pb/(pa-pb);
+    l[1] = 1-l[0];
+  }
+  
+  template<class Rd>
+  void OrthoProject(const Rd &P,const Rd &A,const Rd &B,const Rd &C,R * l)
+  {
+  Rd AB(A,B),AC(A,C),AP(A,P),BP(B,P),CP(C,P);
+  R2 p0( (AB,AP) , (AC,AP) );
+  R2 p1( (AB,BP) , (AC,BP) );
+  R2 p2( (AB,CP) , (AC,CP) );
+  // sum  li pi = 0
+  //   l0    + l1    + l2     = 1
+  //  =>     
+  R2 O;
+  R d = det(p0,p1,p2);
+  l[0] = det(O ,p1,p2)/ d;
+  l[1] = det(p0,O ,p2)/ d;
+  l[2] = 1. -l[0] -l[1];
+  //  
+  //     
+  }
+  
+  template<class Vertex>    
+  Vertex *  GTree<Vertex>::NearestVertex(Zd xyi)//long xi,long yj)
+  {
+    // warning this function return the NearestVertex in the first
+    // none empty box contening the point xyi.
+    //   They do not return the true nearest point in classical norm.
+      
+    QuadTreeBox * pb[ MaxDeep ];
+    int  pi[ MaxDeep  ];
+    Zd pp[  MaxDeep ];
+    int l=0; // level
+    QuadTreeBox * b;
+    IntQuad  h=MaxISize,h0;
+    IntQuad hb =  MaxISize;
+    Zd   p0(0,0,0);
+    Zd  plus(xyi) ; plus.Bound();
+    
+    // xi<MaxISize?(xi<0?0:xi):MaxISize-1,yj<MaxISize?(yj<0?0:yj):MaxISize-1);
+    
+    Vertex *vn=0;
+    
+    // init for optimisation ---
+    b = root;
+    long  n0;
+    if (!root->n)
+      return vn; // empty tree 
+    
+    while( (n0 = b->n) < 0) 
+      {
+		// search the non empty 
+		// QuadTreeBox containing  the point (i,j)
+		long hb2 = hb >> 1 ;
+		int k = plus.Case(hb2);//(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+
+		QuadTreeBox * b0= b->b[k];
+ 
+		if ( ( b0 == 0) || (b0->n == 0) ){
+		  break; // null box or empty box   => break 
+		}   
+		NbQuadTreeBoxSearch++;
+		b=b0;
+		p0.Add(k,hb2);
+		hb = hb2; 
+		
+      }
+      // n0 number of boxes of in b ("b0")
+    if(verbosity>200)
+    cout << "n0=" << n0 << endl;
+    
+    if ( n0 > 0) 
+    {  
+      for( int k=0;k<n0;k++)
+	{
+	  Zd i2 =  VtoZd(b->v[k]);
+	  h0 = Zd(i2,plus).norm();  //NORM(iplus,i2.x,jplus,i2.y);
+	  if (h0 <h) {
+	    h = h0;
+	    vn = b->v[k];
+	  }
+	  NbVerticesSearch++;
+	}
+      
+      return vn;
+    }
+    
+if(verbosity>200)
+    cout << "general case : NearVertex" << endl; 
+    // general case -----
+  pb[0]= b;
+  pi[0]=b->n>0 ?(int)  b->n : N  ;
+  pp[0]=p0;
+  h=hb;
+  do {    
+    b= pb[l];
+    while (pi[l]--)
+      { 	      
+        int k = pi[l];
+	
+	if (b->n>0) // Vertex QuadTreeBox none empty
+	  { 
+	    NbVerticesSearch++;
+	    Zd i2 =  VtoZd(b->v[k]);
+	    h0 = Zd(i2,plus).norm();//  NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) 
+	      {
+		h = h0;
+		vn = b->v[k];
+	      }
+	  }
+	else // Pointer QuadTreeBox 
+	  { 
+	    QuadTreeBox *b0=b;
+	    NbQuadTreeBoxSearch++;
+	    if ((b=b->b[k]))
+	      {
+		hb >>=1 ; // div by 2
+		Zd ppp(pp[l],k,hb);
+		
+		if  ( ppp.interseg(plus,hb,h) )//(INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		  {
+		    pb[++l]=  b;
+		    pi[l]= b->n>0 ?(int)  b->n : N  ;
+		    pp[l]=ppp;
+		  }
+		else
+		  b=b0, hb <<=1 ;
+	      }
+	    else
+	      b=b0;
+	  }
+      }
+    hb <<= 1; // mul by 2 
+  } while (l--);
+  
+  return vn;
+  }
+  
+  
+  template<class Vertex>
+  Vertex *  GTree<Vertex>::ToClose(const Rd & v,R seuil,Zd H)
+  {
+    const Rd X(v);
+    const Zd p(RdtoZd(v));
+    R seuil2 = seuil*seuil;
+    // const Metric  Mx(v.m);
+    
+    QuadTreeBox * pb[ MaxDeep ];
+    int  pi[ MaxDeep  ];
+    Zd pp[  MaxDeep ];
+    
+    int l=0; // level
+    QuadTreeBox * b;
+    long h=MaxISize;
+    long hb =  MaxISize;
+    Zd p0( 0 );
+    
+    if (!root->n)
+      return 0; // empty tree 
+   
+    // general case -----
+    pb[0]= root;
+    pi[0]= root->n>0 ?(int)  root->n : N ;
+    pp[0]= p0;
+    h=hb;
+    do {    
+      b= pb[l];
+      while (pi[l]--)
+	{ 	      
+	  int k = pi[l];
+	  //cout << "b" << b << ", k= " << k << endl;
+	  //cout << " b->n " << b->n << endl;
+	  if (b->n>0) // Vertex QuadTreeBox none empty
+	    { 
+	      NbVerticesSearch++;
+	      Vertex & V(*b->v[k]);
+	      Zd i2 =  VtoZd(V);
+	   
+	      if ( Zd(i2,p).less(H) )
+		{
+		  
+		  Rd XY(X,V);
+		  R dd;
+		  if( (dd= (XY,XY) ) < seuil2 ) // LengthInterpole(Mx(XY), b->v[k]->m(XY)))  < seuil )
+		    { 
+		
+		      return &V; 
+		    }
+		}
+	    }
+	  else // Pointer QuadTreeBox 
+	    { 
+	      QuadTreeBox *b0=b;
+	      NbQuadTreeBoxSearch++;
+	      if( (b=b->b[k]) ) 
+		{
+			
+		  hb >>=1; // div by 2
+		  Zd ppp(pp[l],k,hb);
+		  	
+		  if( ppp.interseg(p,hb,H) )
+		    {
+		      	
+		      pb[++l]=  b;
+		      pi[l]= b->n>0 ?(int)  b->n : N;  
+		      pp[l]=ppp;
+		    }
+		  else
+		    b=b0, hb <<=1 ;
+		    	
+		}
+	      else
+		b=b0;
+	    }
+	} // fin: while(pi[l]--)
+      hb <<= 1; // mul by 2 
+    } while (l--);
+
+    return 0;
+    
+  }
+  
+  template<class Vertex>
+  void  GTree<Vertex>::Add( Vertex & w)
+  {
+    QuadTreeBox ** pb , *b;
+    Zd p(VtoZd(w));
+    long l=MaxISize;
+    pb = &root;
+   
+    while( (b=*pb) && (b->n<0))
+      { 
+	b->n--;
+	l >>= 1;
+	pb = &b->b[p.Case(l)];
+      }
+    if  (b) {
+      for(int i=N-1;i>=0;--i)
+	if (b->n > i &&  b->v[i] == &w)
+	  {
+	    //if( abs(w.x+0.5)<1e-10 ) cout << "if (b->n > i &&  b->v[i] == &w)" <<endl;
+	    return;
+	  }
+    }
+    assert(l);
+    while ((b= *pb) && (b->n == N)) // the QuadTreeBox is full
+      { 
+	//if(verbosity > 5) cout << " b = " << b << b->n << "  " << l << endl;
+	Vertex *v4[N]; // copy of the QuadTreeBox vertices      
+	for(int i=0;i<N;++i)
+	  { v4[i]= b->v[i];
+	  b->v[i]=0;}
+	
+	b->n = -b->n; // mark is pointer QuadTreeBox
+	
+	l >>= 1;    // div the size by 2
+	ffassert(l);
+	for (int k=0;k<N;k++) // for the 4 vertices find the sub QuadTreeBox ij
+	  { 
+	    int ij;
+	    QuadTreeBox * bb =  b->b[ij=VtoZd(v4[k]).Case(l)];
+	    //if(verbosity > 5)  cout << "ij= "<< ij <<  " " << VtoZd(v4[k])<< endl;
+	    if (!bb) 
+	      bb=b->b[ij]=NewQuadTreeBox(); // alloc the QuadTreeBox 
+	    //if(verbosity > 5)  cout << bb << " " << k << " "  << ij <<  endl;
+	    bb->v[bb->n++] = v4[k];
+	  }
+	pb = &b->b[p.Case(l)];
+      }
+    if (!(b = *pb))
+      { //if(verbosity > 5)  cout << "Qbox \n";
+	b=*pb= NewQuadTreeBox(); //  alloc the QuadTreeBox 
+      }
+    //if(verbosity > 5)  cout << b << " " << b->n << endl;
+    b->v[b->n++]=&w; // we add the vertex 
+    NbVertices++;    
+    
+  }
+
+    
+template<class Vertex>    
+GTree<Vertex>::GTree(Vertex * v,Rd Pmin,Rd Pmax,int nbv) : 
+ lenStorageQuadTreeBox(nbv/8+100),
+ // th(t),
+ NbQuadTreeBoxSearch(0),
+ NbVerticesSearch(0),
+ NbQuadTreeBox(0),
+ NbVertices(0),
+ cMin(Pmin-(Pmax-Pmin)/2),
+ cMax(Pmax+(Pmax-Pmin)/2),
+ coef( MaxISize/Norme_infty(cMax-cMin))
+ 
+{ 
+  if(verbosity>5){
+    cout << "  GTree: box: "<<  Pmin << " " << Pmax << " " << cMin << " "<< cMax << " nbv : " << nbv <<endl;
+    cout << "MaxISize " << MaxISize << endl; 
+    //cout << "  RdtoZd(cMin)" << RdtoZd(cMin) << " RdtoZd(cMax)" << RdtoZd(cMax) << endl;
+    //cout << "  RdtoZd(Pmin)" << RdtoZd(Pmin) << " RdtoZd(Pmax)" << RdtoZd(Pmax) << endl;
+    }
+  sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+  root=NewQuadTreeBox();
+  //  throwassert( MaxISize > MaxICoor);
+  if (v)
+    for (long i=0;i<nbv;i++) 
+      Add(v[i]);
+}
+  
+  template<class Vertex>
+  GTree<Vertex>::GTree() : 
+  lenStorageQuadTreeBox(100),
+  // th(0),
+  NbQuadTreeBoxSearch(0),
+  NbVerticesSearch(0),
+  NbQuadTreeBox(0),
+  NbVertices(0),
+  cMin(),cMax(),coef(0)
+  {
+    sb =new StorageQuadTreeBox(lenStorageQuadTreeBox);
+    root=NewQuadTreeBox();
+  }
+  
+  template<class Vertex>    
+  GTree<Vertex>::StorageQuadTreeBox::StorageQuadTreeBox(int ll,StorageQuadTreeBox *nn)
+  {
+    len = ll;
+    n = nn;
+    b = new QuadTreeBox[ll];
+    for (int i = 0; i <ll;i++)
+      {
+	b[i].n =0;
+	for(int j=0;j<N;++j)
+	  b[i].b[j]=0;
+      }
+    bc =b;
+    be = b +ll;
+    assert(b);
+  }
+  
+  template<class Vertex>    GTree<Vertex>::StorageQuadTreeBox::~StorageQuadTreeBox()
+  { //cout <<  "~StorageQuadTreeBox " << this << " n " << n << " b " << b << endl;
+    if(n) delete n;
+    delete [] b;
+  }
+  
+  template<class Vertex> GTree<Vertex>::~GTree()
+  {
+    delete sb; 
+  }
+  
+template<class Vertex> ostream& operator <<(ostream& f, const  GTree<Vertex> & qt)
+{ 
+  f << " the tree "  << endl;
+  f << " NbTreeBox = " << qt.NbQuadTreeBox 
+    << " Nb Vertices = " <<  qt.NbVertices << endl;
+  f << " NbTreeBoxSearch " << qt.NbQuadTreeBoxSearch  
+    << " NbVerticesSearch " << qt.NbVerticesSearch << endl;
+  f << " SizeOf QuadTree" << qt.SizeOf() << endl;
+  //     return  dump(f,*qt.root);
+  return  f;
+}
+  
+  template<class Vertex> Vertex *  GTree<Vertex>::NearestVertexWithNormal(const Rd &P)//(long xi,long yj)
+  {
+    QuadTreeBox * pb[ MaxDeep ];
+    int  pi[ MaxDeep  ];
+    Zd pp[ MaxDeep];
+    int l; // level
+    QuadTreeBox * b;
+    IntQuad  h=MaxISize,h0;
+    IntQuad hb =  MaxISize;
+    Zd   p0;
+    Zd  plus(RdtoZd(P) );//xi<MaxISize?(xi<0?0:xi):MaxISize-1,yj<MaxISize?(yj<0?0:yj):MaxISize-1);
+    
+    Vertex *vn=0;
+    // init for optimisation ---
+    b = root;
+    long  n0;
+    if (!root->n)
+      return vn; // empty tree 
+    
+    while( (n0 = b->n) < 0) 
+      {
+	// search the non empty 
+	// QuadTreeBox containing  the point (i,j)
+	long hb2 = hb >> 1 ;
+	int k = plus.Case(hb2);//(iplus,jplus,hb2);// QuadTreeBox number of size hb2 contening i;j
+	QuadTreeBox * b0= b->b[k];
+	if ( ( b0 == 0) || (b0->n == 0) ) 
+	  break; // null box or empty   => break 	    
+	NbQuadTreeBoxSearch++;
+	b=b0;	
+	p0.Add(k,hb2);	
+	hb = hb2; 
+      }
+    
+    
+    if ( n0 > 0) 
+    {  
+      for(int k=0;k<n0;k++)
+	{
+	  Vertex * v=b->v[k];
+	  if (v->ninside(P)) {
+	    Zd i2 =  VtoZd(v);
+	    //   try if is in the right sens -- 
+	    h0 = Zd(i2,plus).norm();// h0 = NORM(iplus,i2.x,jplus,i2.y);
+	    if (h0 <h) {
+	      h = h0;
+	      vn = v;}
+	    NbVerticesSearch++;}
+	}
+      if (vn) return vn; 
+    }
+    // general case -----
+    // INITIALISATION OF THE STACK 
+    l =0; // level 
+    pb[0]= b;
+    pi[0]= b->n>0 ?(int)  b->n : N  ;
+    pp[0]=p0;
+    h=hb;
+  L1: 
+    do {   // walk on the tree  
+      b= pb[l];
+      while (pi[l]--) // loop on 4 element of the box
+	{ 	      
+	  int k = pi[l];
+	  
+	  if (b->n>0) // Vertex QuadTreeBox none empty
+	    { 
+	      Vertex * v=b->v[k];
+	      if (v->ninside(P) ) {	    
+		NbVerticesSearch++;
+		Zd i2 =  VtoZd(v);
+		// if good sens when try -- 
+		h0 = Zd(i2,plus).norm();//  NORM(iplus,i2.x,jplus,i2.y);
+		if (h0 <h) 
+		{
+		  h = h0;
+		  vn =v;
+		}}
+	    }
+	  else // Pointer QuadTreeBox 
+	    { 
+	      QuadTreeBox *b0=b;
+	      NbQuadTreeBoxSearch++;
+	      if ((b=b->b[k])) 
+		{
+		  hb >>=1 ; // div by 2
+		  Zd ppp(pp[l],k,hb);
+		
+		  if  ( ppp.interseg(plus,hb,h) )//(INTER_SEG(iii,iii+hb,iplus-h,iplus+h) && INTER_SEG(jjj,jjj+hb,jplus-h,jplus+h)) 
+		    {
+		      pb[++l]=  b;
+		      pi[l]= b->n>0 ?(int)  b->n : N  ;
+		      pp[l]=ppp;		    
+		    }
+		  else
+		    b=b0, hb <<=1 ;
+		}
+	      else
+		b=b0;
+	    }
+	}
+      hb <<= 1; // mul by 2 
+    } while (l--);
+    if (!vn && b != root )
+   {// cas particulier on repart du sommet on avais rien trouver 
+     b=root;
+     hb =  MaxISize;
+     p0=Zd();
+     l=0;
+     pb[0]= b;
+     pi[0]= b->n>0 ?(int)  b->n : N  ;
+     pp[0]=Zd();
+     
+     goto L1;
+   }
+    return vn;
+}
+
+
+
+
+  //  static int kfind=0;
+  // static int kthrough=0;
+  
+  inline void CoorBary(const Triangle2 & K,const  R2  & P, R *l)
+  {
+    R detK = 2.*K.mesure() ;
+    l[1]=det(K[0],P,K[2])/detK;
+    l[2]=det(K[0],K[1],P)/detK;
+    l[0]=1-l[1]-l[2];
+  }
+  
+
+  inline void CoorBary(const Tet & K,const  R3  & P, R *l)
+  {
+    R detK = 6.*K.mesure() ;
+    l[1]=det(K[0],P,K[2],K[3])/detK;
+    l[2]=det(K[0],K[1],P,K[3])/detK;
+    l[3]=det(K[0],K[1],K[2],P)/detK;
+    l[0]=1-l[1]-l[2]-l[3];
+  }
+  
+  
+  inline    int nRand(int n) {
+    return  rand()%n; //avant random()%n;
+  }
+  
+  inline int find5(int i,int *k,int l)
+  {
+    if(l<5)
+      {
+	for(int j=0;j<l;++j)
+	  if(i==k[j]) return j;
+      }
+    else  if(i>=k[0] && i<=k[l-1])
+      {
+	int i0=0,i1=l-1;
+	while(i0<=i1)
+	  { int im=(i0+i1)/2;
+	    if(i<k[im]) i1=im-1;
+	    else 
+	      if(i>k[im]) i0=im+1;
+	      else
+		if(i==k[im]){
+		  return im;
+		}
+	  }
+      }
+    return -1;
+  } 
+  
+  template<class Mesh>
+  const typename  Mesh::Element * Find(const Mesh & Th,
+				       GTree<typename Mesh::Vertex> *quadtree,
+				       typename Mesh::Rd P,
+				       typename Mesh::RdHat & Phat,
+				       bool & outside,
+				       const typename  Mesh::Element * tstart)
+{
+  typedef  typename Mesh::Element Element;
+  typedef  typename Mesh::Vertex Vertex;
+  typedef  typename Mesh::Rd Rd;
+  const int nkv=Element::nv;
+  const int d=Rd::d;
+  R dP=DBL_MAX;
+  Rd PPhat;
+  int k=0;    
+
+  int it,j;
+  const int mxbord=100;
+  int kbord[mxbord];
+  int nbord=0;
+  if(searchMethod>1) goto PICHON;
+  if ( tstart )
+    it =  Th(tstart);
+  else  if(quadtree)
+    {  
+      const Vertex * v=quadtree->NearestVertexWithNormal(P);
+      if (!v) 
+	{ 
+	  v=quadtree->NearestVertex(P);
+	  assert(v);
+	}
+      it=Th.Contening(v);
+      if(verbosity>200)
+	cout <<  "  Close : "<<  *v << " " << Th(v) << " "; 
+      
+    }
+  else ffassert(0);
+  
+  if(verbosity>200)
+    cout << "tstart=" << tstart << " "<< "it=" << it << " P="<< P << endl; 
+  outside=true; 
+  Mesh::kfind++;
+  while (1)
+    { 
+      //if(verbosity>199) cout << "it " << it <<endl;
+      const Element & K(Th[it]);
+      Mesh::kthrough++;
+      assert(k++<1000);
+      int kk,n=0,nl[nkv];
+      R l[nkv];
+      for(int iii=0; iii<nkv; iii++)
+	l[iii]=0.;
+      
+      CoorBary(K,P,l);
+      
+      // CoorBary :: donner entre 0 et 1
+      // Pb si K.mesure*1.e-10 precision machine ==> bug
+      
+      // avant:
+      // R eps =  -K.mesure()*1e-10;
+      R eps = -1e-10;
+      for(int i=0;i<nkv;++i)
+	if( l[i] < eps){
+	  nl[n++]=i;
+	}
+      if(verbosity>200){
+	cout << "tet it=" << it ;
+	cout << "  K.mesure=" << K.mesure() ;
+	cout << " eps=" << eps << endl;
+	for(int i=0;i<nkv;++i)
+	  cout<< " l["<< i <<"]=" <<  l[i] ;
+	cout << " n=" << n << endl;
+      }
+      
+      if (n==0)
+	{  // interior => return
+	  outside=false; 
+	  Phat=Rd(l +1);
+	  // cout << Phat <<endl;
+#ifndef NDEBUG
+	  Rd pp=K(Phat)-P;
+	  if( pp.norme()>1e-5)
+	    {
+	      cout << " Bug find P " << P << " ==" << K(Phat)  << endl;
+	      cout << "Phat== " << Phat << " diff= " << pp << endl;
+	      assert(0);
+	    }
+	  
+#endif	  
+	  return &K;
+	}
+      
+      
+      
+      kk=n==1 ? 0 : nRand(n);
+      j= nl[ kk ];
+      int itt =  Th.ElementAdj(it,j);
+      if(itt!=it && itt >=0)  
+	{
+	  dP=DBL_MAX;
+	  it=itt;
+	  continue;
+	}  
+      int  inkbord=find5(it,kbord,nbord);
+      if(inkbord<0 )  
+	{
+	  assert(nbord < mxbord);
+	  kbord[nbord++]=it;
+	  if(nbord>=5)  HeapSort(kbord,nbord);
+	}
+      if(verbosity>101)
+	{
+	  cout << " bord "<< it<< "   nbf < 0 : " <<n << " (inb) " << inkbord << " nfb" << nbord<<endl;
+	  R ss=0; 
+	  for(int i=0;i<nkv;++i)
+	    {  ss += l[i];
+	      cout << l[i] << " ";}
+	  cout << " s=" << ss << endl;;
+	  
+	}
+      
+      if(verbosity>200)
+	cout << "GQuadTree::value of n " << n << endl;
+      
+      if ( n!=1 )  // on est sur le bord, mais plusieurs face <0 => on test les autre
+	{  // 1) existe t'il un adj interne
+	  int nn=0,ii;
+	  int nadj[d+1],ni[d+1];
+	  for(int i=0;i<nkv;++i)
+	    //avant :: if (l[i] < eps && (itt=Th.ElementAdj(it,ii=i)) != it && itt && find5(itt,kbord,nbord) < -1 ) 
+	    if (l[i] < eps && (itt=Th.ElementAdj(it,ii=i)) != it && (itt>=0) && find5(itt,kbord,nbord) < 0 ) 
+	      ni[nn++]=i,nadj[i]=itt;
+	  if(verbosity>100)
+	    cout << " nn : "<< nn << endl;
+	  if (nn>0)
+	    {
+	      //j=nadj[nRand(nn)];
+	      j=ni[nRand(nn)];
+	      it=nadj[j];
+	      dP=DBL_MAX;
+	      //cout << "new it= " << it << endl;
+	      continue;
+	    }
+	}
+      // toutes les faces <0  sont sur le bord.
+      //   pour l'instant on s'ar�te
+      // le point est externe. (mais trop cher pour faire mieux)
+      // on projet le points sur le bord via le coordonne 
+      //  barycentrique 
+      { // a ridge on border  (to hard to do the correct stuff) 
+	//  or a corner    just do the projection on lambda  
+	R s=0.;
+	for(int i=0;i<nkv;++i)
+	  s += (l[i]= max(l[i],0.));
+	for(int i=0;i<nkv;++i)
+	  l[i]/=s;
+	Phat=Rd(l +1);
+	if(verbosity>100)
+	  {
+	    cout << P << " " << n << " l: ";
+	    R ss=0; 
+	    for(int i=0;i<nkv;++i)
+	      {  ss += l[i];
+		cout << l[i] << " ";}
+	    cout << " s=" << ss <<" " << s <<" exit by bord " << it << " "  << Phat << endl;;
+          }
+	outside=true;
+	if(searchMethod) goto PICHON;
+	return &Th[it] ;
+      }		    
+    }
+  
+ PICHON:
+  {
+  /*==============================PICHON=================*/
+  // Brute force ** */    
+  R l[4], eps = -1e-6;  //pichon
+  double dist_baryC = 0.0, min_dist_baryC = 1e31;      
+  long closestTet = -1;
+  l[0]=l[1]=l[2]=l[3]=1; //  for d < 3
+  for(int tet=0;tet<Th.nt;tet++) // nkv=4
+    { 
+      const Element & K(Th[tet]);
+      CoorBary(K,P,l);
+      
+      // measure dist by sum ( |lambda_i| )
+      dist_baryC = 0.0;      
+      for(int i=0; i<nkv; i++)
+	dist_baryC += abs(l[i]);
+      
+      // define closest Tetrahedron !!! TO VERIFY THE HYPOTHESE !!! 
+      if( dist_baryC < min_dist_baryC )   
+	{
+	  min_dist_baryC = dist_baryC; 
+	  closestTet = tet; 
+	}
+      
+      
+      if  ( (l[0] >= eps) && (l[1] >= eps) && (l[2] >= eps) &&  (l[3] >= eps) )
+	{
+          outside=false;
+	  Phat=Rd(l+1);
+	  return &K;	
+	}
+    }
+  
+  const Element & K(Th[closestTet]);
+  outside=true;
+  CoorBary(K,P,l);
+  
+  Phat=Rd(l+1);
+  if(verbosity>2)
+    cout << "  --vertex:" << P << " NOT in DOMAIN. use closestTet. Phat:" << Phat << endl;
+  return &K;
+  }
+  /*==============================PICHON=================*/
+}
+
+
+// Instantiation  manuel des templates
+
+template class GTree<Vertex2>;
+template class GTree<Vertex3>;
+template class GTree<Vertex1>;
+typedef Mesh3::GMesh GMesh3;
+typedef Mesh2::GMesh GMesh2;
+typedef Mesh1::GMesh GMesh1;
+template
+const   GMesh3::Element * Find<GMesh3>(const GMesh3 & Th,
+				       GTree< GMesh3::Vertex> *quadtree,
+				       GMesh3::Rd P,
+				       GMesh3::RdHat & Phat,
+				       bool & outside,
+				       const   GMesh3::Element * tstart);
+template
+const   GMesh2::Element * Find<GMesh2>(const GMesh2 & Th,
+				       GTree< GMesh2::Vertex> *quadtree,
+				       GMesh2::Rd P,
+				       GMesh2::RdHat & Phat,
+				       bool & outside,
+				       const   GMesh2::Element * tstart);
+
+/*
+  template
+  const   GMesh1::Element * Find<GMesh1>(const GMesh1 & Th,
+				       GTree< GMesh1::Vertex> *quadtree,
+				       GMesh1::Rd P,
+				       GMesh1::RdHat & Phat,
+				       bool & outside,
+				       const   GMesh1::Element * tstart);
+*/
+}
diff --git a/src/femlib/GQuadTree.hpp b/src/femlib/GQuadTree.hpp
new file mode 100644
index 0000000..c510a50
--- /dev/null
+++ b/src/femlib/GQuadTree.hpp
@@ -0,0 +1,234 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : Generic Tree header  (binairy, Quad, Oct)   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+namespace Fem2D {
+#include "R3.hpp"
+}
+namespace EF23 {
+  using namespace Fem2D;
+  using Fem2D::R;
+
+  static const int MaxDeep = 30;
+  typedef  int  IntQuad;
+  static const IntQuad MaxISize = ( 1L << MaxDeep);
+  static const IntQuad MaxISize1 =   MaxISize-1;  
+  class Z1 { public:
+      static bool INTER_SEG1d(int a,int b,int x,int y) { return (((y) > (a)) && ((x) <(b)));}
+    int x;
+    Z1():x(0){}
+    Z1(R1 P) : x((int)P.x) {}
+    Z1( int i) : x(i){}
+    Z1(const Z1 &pp,int k,int l): x(pp.x+(( k&1) ? l : 0)) {}
+    void Add(int k,int l) { x+= (( k&1) ? l : 0) ;}
+    Z1(const Z1 &A,const Z1 &B) : x(B.x-A.x){}
+	
+    int Case(int l) const  { return  ( x & l)? 1 : 0 ;}
+    int norm() const { return abs(x);}
+    void Bound() {   x = max(min(x,MaxISize1),0);}
+    
+    bool less(Z1 h) const  { return abs(x) <h.x ;}
+    bool interseg(Z1 pp,int hb,int h) const { 
+      return INTER_SEG1d(x,x+hb,pp.x-h,pp.x+h) ;}
+    bool interseg(const Z1 &pp,int hb,const Z1 &h) const { 
+      return INTER_SEG1d(x,x+hb,pp.x-h.x,pp.x+h.x) ;}
+    operator R1 () const { return R1(x);} 
+  };
+  
+ 
+  
+  class Z2 { public:
+      static bool INTER_SEG1d(int a,int b,int x,int y) { return (((y) > (a)) && ((x) <(b)));}
+    int x,y;
+    Z2():x(0),y(0) {}
+    Z2(R2 P) : x((int)P.x),y((int)P.y) {}
+    Z2( int i) : x(i),y(i){}
+    //Z2( int i,int j) : x(i),y(j) {}
+    Z2(const Z2 &pp,int k,int l): x(pp.x+(( k&1) ? l : 0)),y(pp.y+(( k&2) ? l : 0)) {}
+    void Add(int k,int l) { x+= (( k&1) ? l : 0) ; y+= (( k&2) ? l : 0);}
+    Z2(const Z2 &A,const Z2 &B) : x(B.x-A.x),y(B.y-A.y) {}
+	
+    int Case(int l) const  { return ( ( y & l) ? (( x & l) ? 3 : 2 ) : ( ( x & l)? 1 : 0 )  ) ;}
+    int norm() const { return Max(abs(x),abs(y));}
+    void Bound() {   x = max(min(x,MaxISize1),0);
+      y = max(min(y,MaxISize1),0);}
+    
+    bool less(Z2 h) const  { return abs(x) <h.x && abs(y) <h.y;}
+    bool interseg(Z2 pp,int hb,int h) const { 
+      return INTER_SEG1d(x,x+hb,pp.x-h,pp.x+h) && INTER_SEG1d(y,y+hb,pp.y-h,pp.y+h);}
+    bool interseg(const Z2 &pp,int hb,const Z2 &h) const { 
+      return INTER_SEG1d(x,x+hb,pp.x-h.x,pp.x+h.x) && INTER_SEG1d(y,y+hb,pp.y-h.y,pp.y+h.y);}
+    operator R2 () const { return R2(x,y);} 
+  };
+  
+  class Z3 { public:
+      static bool INTER_SEG1d(int a,int b,int x,int y) { return (((y) > (a)) && ((x) <(b)));}
+    int x,y,z;
+    Z3():x(0),y(0),z(0) {}
+    
+    Z3(R3 P) : x((int)P.x),y((int)P.y),z((int) P.z) {}
+    Z3( int i) : x(i),y(i),z(i){}
+    
+    Z3(const Z3 &pp,int k,int l): x(pp.x+(( k&1) ? l : 0)),y(pp.y+(( k&2) ? l : 0)),z(pp.z+(( k&4) ? l : 0)) {}
+    void Add(int k,int l) { x+= (( k&1) ? l : 0) ; y+= (( k&2) ? l : 0); z+= (( k&4) ? l : 0);}
+    Z3(const Z3 &A,const Z3 &B) : x(B.x-A.x),y(B.y-A.y),z(B.z-A.z) {}
+    void Bound() {  x = max(min(x,MaxISize1),0);
+      y = max(min(y,MaxISize1),0);
+      z = max(min(z,MaxISize1),0);}
+    
+    int Case(int l) const  {// cout << " case = "<< int((x&l)!=0)+(int((y&l)!=0)<<1) + (int((z&l)!=0)<<2);
+      return int( (x&l)!=0) + ( int((y&l)!=0)<<1 ) + ( int( (z&l)!=0) <<2 ) ;}
+    int norm() const { return Max(abs(x),abs(y),abs(z));}
+    bool less(Z3 h) const  { return abs(x) <h.x && abs(y) <h.y && abs(z) < h.z ;}
+    bool interseg(Z3 pp,int hb,int h) const { 
+      return INTER_SEG1d(x,x+hb,pp.x-h,pp.x+h) && INTER_SEG1d(y,y+hb,pp.y-h,pp.y+h) && INTER_SEG1d(z,z+hb,pp.z-h,pp.z+h) ;
+      }
+    bool interseg(const Z3 &pp,int hb,const Z3 &h) const { 
+      return INTER_SEG1d(x,x+hb,pp.x-h.x,pp.x+h.x) && INTER_SEG1d(y,y+hb,pp.y-h.y,pp.y+h.y) && INTER_SEG1d(z,z+hb,pp.z-h.z,pp.z+h.z);
+      }
+    operator R3 () const { return R3(x,y,z);} 
+    
+  }; 
+
+  inline  ostream& operator <<(ostream& f, const Z3 & P )   { f << P.x << ' ' << P.y << ' ' << P.z   ; return f; }
+  inline  ostream& operator <<(ostream& f, const Z2 & P )   { f << P.x << ' ' << P.y   ; return f; }
+  inline  ostream& operator <<(ostream& f, const Z1 & P )   { f << P.x    ; return f; }
+  
+  template<class Rd>    struct Traits_Zd {  typedef void Zd;};
+  template<>    struct Traits_Zd<R1> {  typedef Z1 Zd;};
+  template<>    struct Traits_Zd<R2> {  typedef Z2 Zd;};
+  template<>    struct Traits_Zd<R3> {  typedef Z3 Zd;};
+  
+  template<class Vertex>    
+  class GTree {
+    typedef typename Vertex::Rd Rd;
+    typedef typename Traits_Zd<Rd>::Zd Zd;
+    
+    
+  public:
+  
+    static  const int d =Rd::d;
+    static const int N = 1 << d;  // N=2^(d-1)
+    
+    
+    class QuadTreeBox { 
+    public:
+      
+      int n; // if n < 4 => Vertex else =>  QuadTreeBox;
+      union {
+	QuadTreeBox *b[N];
+	Vertex * v[N];
+      };
+      // void init() { for(int i=0;i<N;++i) b[i]=0;}
+      
+    }; // end class QuadTreeBox  /////////////////
+    
+    class StorageQuadTreeBox {
+    public:
+      QuadTreeBox *b,*bc,*be;
+      int len;
+      StorageQuadTreeBox *n; // next StorageQuadTreeBox
+      StorageQuadTreeBox(int ,StorageQuadTreeBox * =0);
+      ~StorageQuadTreeBox();
+      int  SizeOf() const {
+	return len*sizeof(QuadTreeBox)+sizeof(StorageQuadTreeBox)+ (n?n->SizeOf():0);
+      }
+    }; // end class  StorageQuadTreeBox 
+    
+    StorageQuadTreeBox * sb;
+    
+    
+    int  lenStorageQuadTreeBox;
+    
+  public:
+    QuadTreeBox * root;
+    // Mesh *th;
+    
+    int NbQuadTreeBoxSearch,NbVerticesSearch;
+    int NbQuadTreeBox,NbVertices;
+    
+    Rd cMin,cMax; //  box of QuadTree
+    R coef; //	
+    
+    
+    Zd  RdtoZd(const Rd &P)  const {return Zd((Minc(Maxc(P,cMin),cMax)-cMin)*coef);} 
+    Zd  VtoZd(const Vertex * v) const {return RdtoZd( (const Rd&) *v);} 
+    Zd  VtoZd(const Vertex & v) const {return RdtoZd( (const Rd&) v);} 
+    
+    Rd  ZdtoRd(const Zd &I) const { return ( (Rd) I )/coef+cMin;}
+    
+    Vertex * NearestVertex(const Rd & P) {
+      return NearestVertex(RdtoZd(P));} //XtoI(P.x),YtoJ(P.y));}
+    Vertex * NearestVertexWithNormal(const Rd & P);
+    Vertex * NearestVertex(Zd i2);
+    
+    Vertex *  ToClose(const Rd & ,R ,Zd );
+    Vertex *  ToClose(const Rd & P,R delta){
+      int hx = (int) (coef*delta);
+      //if(verbosity > 5 ) cout << "hx=" << hx << " coef=" << coef << endl;
+      return ToClose(P,delta,Zd(hx));}
+    int SizeOf() const {return sizeof(GTree)+sb->SizeOf();}
+    
+    void  Add( Vertex & w);
+    
+    QuadTreeBox* NewQuadTreeBox()
+  {
+    ///cout << "NewQuadTreeBox " << sb << " " << sb->bc << " " 
+    //<< sb->be << " " <<lenStorageQuadTreeBox <<endl;
+    if(! (sb->bc<sb->be)) 
+      sb=new StorageQuadTreeBox(lenStorageQuadTreeBox,sb);
+    
+    assert(sb && (sb->bc->n == 0));
+    NbQuadTreeBox++;
+    return sb->bc++;
+  }
+    ~GTree();
+    GTree(Vertex * v,Rd Pmin,Rd Pmax,int nbv);
+    GTree();
+    template<class V>     
+    friend ostream& operator <<(ostream& f, const  GTree<V> & qt);
+    
+    
+    
+  };
+  
+  template<class Mesh>
+  const typename  Mesh::Element * Find(const Mesh & Th,
+				       GTree<typename Mesh::Vertex> *quadtree,
+				       typename Mesh::Rd P,
+				       typename Mesh::RdHat & Phat,
+				       bool & outside,
+				       const typename  Mesh::Element * tstart);
+  
+  
+} // name space 
+
diff --git a/src/femlib/GenericMesh.hpp b/src/femlib/GenericMesh.hpp
new file mode 100644
index 0000000..8a3de7f
--- /dev/null
+++ b/src/femlib/GenericMesh.hpp
@@ -0,0 +1,1578 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model of generic mesh 1d,2d,3d    
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+#ifndef GENERICMESH_HPP_
+#define GENERICMESH_HPP_
+
+// la regle de programmation 3  
+extern long verbosity;
+extern long searchMethod; //pichon
+#include <map>  // Add J. Morice
+
+#include "cassert" 
+#include "assertion.hpp" 
+#include <cstdlib>
+#include <utility>
+#include <limits>
+//#include <algorithm>
+//#include <Functional>
+
+#include "RefCounter.hpp"
+
+
+using namespace ::std;
+
+
+#include "Serialize.hpp"
+
+#include "GQuadTree.hpp"
+// definition R
+namespace Fem2D  {
+#include "R3.hpp"
+#include "Label.hpp"
+#include "HashTable.hpp"
+
+  const double UnSetMesure=-1e+200;
+
+inline int maxdfon(const int *dfon){ return max(max(dfon[0],dfon[1]),max(dfon[2],dfon[3]));}
+  // struct R {}; 
+template<int d> struct typeRd {typedef R0 Rd;};
+template<> struct typeRd<1> {typedef R1 Rd;};
+template<> struct typeRd<2> {typedef R2 Rd;};
+template<> struct typeRd<3> {typedef R3 Rd;};
+
+const int NbTypeItemElement = 4;
+
+const int TypeVertex =0;
+const int TypeEdge   =1;
+const int TypeFace   =2;
+const int TypeVolume =3;
+    //  add FH  ... april 2009  for peroidic Boundary Condition.
+    //  gestion of the permutation 1,2,3
+    // here just user order     
+    //  NumPerm  : number of the permutation  
+    //   p  permutation      n= NumPerm(p)
+    //   p1 permutation inv  n1 = NumPerm(p1)
+    //   p1[p[i]]=i 
+    //   =>  n1   number of the perm /  p[p1[i]]  increase <=> i
+    //  SetNumPerm: set the permutation form number 
+    
+    template<int d> inline int NumPerm(int *) {ffassert(0);}  
+    template<int d> inline int NumPerm1(int *) {ffassert(0);}  // num perm inverse 
+    template<> inline int NumPerm<1>(int *) { return 0;}
+    template<> inline int NumPerm1<1>(int *) { return 0;}
+    template<> inline int NumPerm<2>(int *p) { return p[0] > p[1] ;}
+    template<> inline int NumPerm1<2>(int *p) { return p[0] > p[1] ;}
+    
+    template<> inline int NumPerm1<3>(int *p) { 
+	// signe + depart*2
+	int k=0,i0=0,i1=1,i2=2,j[3];
+	if(p[i0]> p[i1]) swap(i0,i1),k +=1;
+	if(p[i1]> p[i2]) swap(i1,i2),k +=1;
+	if(p[i0]> p[i1]) swap(i0,i1),k +=1;
+	assert(p[i0] < p[i1] && p[i1] < p[i2]);
+	// j is inv of i1,i2,i3
+	j[i0]=0;j[i1]=1;j[i2]=2;
+	return (k%2)+i0*2; // signe + depart*2
+    }
+    
+    template<> inline int NumPerm<3>(int *p) { 
+	// signe + depart*2
+	int k=0,i0=0,i1=1,i2=2,j[3];
+	if(p[i0]> p[i1]) swap(i0,i1),k +=1;
+	if(p[i1]> p[i2]) swap(i1,i2),k +=1;
+	if(p[i0]> p[i1]) swap(i0,i1),k +=1;
+	assert(p[i0] < p[i1] && p[i1] < p[i2]);
+	// j is inv of i1,i2,i3
+	j[i0]=0;j[i1]=1;j[i2]=2; 
+	return (k%2)+ ((j[0]+3)%3)*2; // signe + depart*2
+    }    
+    // build de permutation     
+    template<int d> inline void SetNumPerm(int n,int *p) { ffassert(0); }// a error}    
+    template<int d> inline void SetNumPerm1(int n,int *p) { ffassert(0); }// a error}    
+    
+    template<> inline void SetNumPerm<1>(int ,int *p) { p[0]=0;} // a error}    
+    template<> inline void SetNumPerm<2>(int n,int *p) { p[0]=n;p[1]=1-n;} // a error}    
+    
+    // build perm inverse
+    template<> inline void SetNumPerm1<1>(int ,int *p) { p[0]=0;} // a error}    
+    template<> inline void SetNumPerm1<2>(int n,int *p) { p[0]=n;p[1]=1-n;} // a error} 
+    
+    template<> inline  void SetNumPerm1<3>(int n,int *p) { 
+	int i=n/2, j= n%2 ? 2:1;
+	p[i]=0;p[(i+j)%3]=1;p[(i+j+j)%3]=2;
+	assert( n == NumPerm1<3>(p));
+    }    
+    
+    template<> inline   void SetNumPerm<3>(int n,int *p) { 
+	int i=n/2, j= n%2 ? 2:1;
+	p[0]=i;p[1]=(i+j)%3;p[2]=(i+j+j)%3;
+	assert( n == NumPerm<3>(p));
+    } 
+    // ---  end add periodic 
+    
+class DataFENodeDF {
+    int  * nbref; // pointer  on common ref counter 
+public:
+  int ndfon[4];
+  const int NbOfElements;
+  const  int NbOfNodes;
+  const  int NbOfDF;  
+  const int * const NodesOfElement;
+  const int * const FirstDfOfNodeData;
+  const int * const FirstNodeOfElement; //  0 
+  const int MaxNbNodePerElement;
+  const int MaxNbDFPerElement;
+  const int MaxNbDFPerNode;
+  int ndfonVertex()const {return ndfon[0];}
+  int ndfonEdge()const {return ndfon[1];}
+  int ndfonFace()const {return ndfon[2];}
+  int ndfonTet()const {return ndfon[3];}
+
+  DataFENodeDF(const DataFENodeDF & m)
+    :
+    nbref( m.nbref ) ,
+    NbOfElements(m.NbOfElements),
+    NbOfNodes(m.NbOfNodes),
+    NbOfDF(m.NbOfDF),
+    NodesOfElement(m.NodesOfElement),
+    FirstDfOfNodeData(m.FirstDfOfNodeData),
+    FirstNodeOfElement(m.FirstNodeOfElement),
+    MaxNbNodePerElement(m.MaxNbNodePerElement),
+    MaxNbDFPerElement(m.MaxNbDFPerElement) ,
+    MaxNbDFPerNode(maxdfon(m.ndfon))
+    {
+      for(int i=0;i<NbTypeItemElement;++i)
+	    ndfon[i]=m.ndfon[i];
+	(*nbref)++; // add one to the ref counter 
+    }
+  DataFENodeDF( 
+	       int andfon[NbTypeItemElement],
+	       int aNbOfElements,
+	       int aNbOfNodes,
+	       int aNbOfDF,
+	       const int * aNodesOfElement,
+	       const int * aFirstDfOfNodeData,
+	       int aMaxNbNodePerElement,
+	       int aMaxNbDFPerElement)
+    :
+    nbref( new int(0)),// new ref counter 
+    NbOfElements(aNbOfElements),
+    NbOfNodes(aNbOfNodes),
+    NbOfDF(aNbOfDF),
+    NodesOfElement(aNodesOfElement),
+    FirstDfOfNodeData(aFirstDfOfNodeData),
+    FirstNodeOfElement(0),
+    MaxNbNodePerElement(aMaxNbNodePerElement),
+    MaxNbDFPerElement(aMaxNbDFPerElement) ,
+    MaxNbDFPerNode(maxdfon(andfon))    
+  {
+    for(int i=0;i<NbTypeItemElement;++i)
+      ndfon[i]=andfon[i];
+  }
+ ~DataFENodeDF()  
+  {
+    if ((*nbref)==0) // remove if nbref ==0
+       {
+	 delete nbref;
+         delete [] NodesOfElement;
+         delete [] FirstDfOfNodeData;
+         delete [] FirstNodeOfElement;
+       }
+	else  (*nbref)--;
+  }
+private:
+	void operator=(const DataFENodeDF &) ;    
+	
+};
+
+template<typename Rn>
+class GenericVertex : public Rn,public Label
+{
+    
+  template<typename T,typename B,typename V>
+        friend class GenericMesh;
+  friend inline ostream& operator <<(ostream& f, const GenericVertex & v )
+  { f << (const Rn &) v << ' ' << (const Label &) v   ; return f; }
+  friend inline istream& operator >> (istream& f,  GenericVertex & v )
+        { f >> (Rn &) v >> (Label &) v ; return f; }
+    
+  Rn *normal; // pointeur sur la normal exterieur pour filtre des points de departs
+   
+public:
+  typedef Rn Rd;
+  static const int d=Rd::d;  
+  GenericVertex() : Rd(),Label(),normal(0) {};
+  GenericVertex(const Rd & P,int r=0): Rd(P),Label(r),normal(0){}
+    
+  void SetNormal(Rd *&n,const Rd & N)
+  { if (normal) { 
+      Rd NN=*normal+N; 
+      *normal= NN/NN.norme(); }
+    else *(normal=n++)=N;}
+    
+  Rd Ne() const {return normal ? *normal: Rd();}
+  bool ninside(const Rd & P) const
+  {
+    return normal? (Rd(*this,P),*normal)<=0: true;
+  }
+    
+private: // pas de copie pour ne pas prendre l'adresse
+  GenericVertex(const GenericVertex &);
+  void operator=(const GenericVertex &); 
+  
+};
+  inline  R1 ExtNormal( GenericVertex<R1> *const v[2],int const f[1])  {   return f[0]==0 ? R1(-1):R1(1);  }
+  inline  R2 ExtNormal( GenericVertex<R2> *const v[3],int const f[2])  {   return R2(*v[f[1]],*v[f[0]]).perp();  }
+    // correct signe N in 3d mai 2009 (FH)
+  inline  R3 ExtNormal( GenericVertex<R3> *const v[4],int const f[3])  {   return R3(*v[f[0]],*v[f[2]])^R3(*v[f[0]],*v[f[1]]) ;  }
+    
+
+template<typename Data>  
+class GenericElement: public Label {
+public:
+  typedef typename Data::V Vertex;
+  typedef typename Data::V::Rd Rd;
+  typedef typename Data::RdHat RdHat;// for parametrization 
+  typedef typename Data::RdHatBord RdHatBord;// for parametrization 
+
+  typedef typename Rd::R R;
+
+  static const int nv=Data::NbOfVertices;  // nb  of vertices 
+  static const int ne=Data::NbOfEdges;  // nb  of edges
+  static const int nf=Data::NbOfFaces;  // nb of faces
+  static const int nt=Data::NT;  // nb of tets
+  static const int nitem=nv+ne+nf+nt;
+  static const int nva=Data::NbOfVertexOnHyperFace;  
+  static const int nea=Data::NbOfAdjElem;  
+  static const int d=Rd::d;  
+  static const int (* const nvedge)[2] ;//
+  static const int (* const nvface)[3] ;//
+  static const int (* const onWhatBorder)[nitem] ;//
+    
+  static const int (* const nvadj)[nva] ;//  
+  static const int nitemdim[4]; //  nv,ne,nf,nt 
+  // variable prive 
+private:
+  Vertex *vertices[nv]; // an array of 3 pointer to vertex
+  R mes; 
+public:
+  GenericElement() {}
+  const Vertex & operator[](int i) const  {
+    ASSERTION(i>=0 && i <nv);
+    return *vertices[i];} // to see triangle as a array of vertex
+
+  Vertex & operator[](int i)  {
+    ASSERTION(i>=0 && i <nv);
+    return *vertices[i];} // to see triangle as a array of vertex
+
+  const Vertex& at(int i) const   { return *vertices[i];} // to see triangle as a array of vert
+
+  Vertex& at(int i)    { return *vertices[i];} // to see triangle as a array of vert
+
+  GenericElement & set(Vertex * v0,int * iv,int r,double mss=UnSetMesure) 
+  { 
+    for(int i=0;i<nv;++i)	
+      vertices[i]=v0+iv[i];
+    mes=(mss!=UnSetMesure) ? mss : Data::mesure(vertices);
+    lab=r;
+    ASSERTION(mss==UnSetMesure && mes>0);
+    return *this;
+  }
+
+  
+  istream & Read1(istream & f,Vertex * v0,int n)
+  {
+    int iv[nv],ir,err=0;
+    for (int i=0;i<nv;++i) 
+      {
+	f >> iv[i];
+	iv[i]--;
+	if (  ! (iv[i]>=0 && iv[i]<n)) err++;
+      }
+    f >> ir;
+    if(err || ! f.good() )
+      {
+	cerr << " Erreur GenericElement::Read1 " << nv <<  " " << n << "  : " ;
+	for (int j=0;j<nv;++j) 
+	  cerr << iv[j] <<  " ";
+	cerr << " , " << ir <<  endl;
+	abort();
+      }
+
+    set(v0,iv,ir); 
+    return f;
+  }
+     	
+  Rd Edge(int i) const {ASSERTION(i>=0 && i <ne);
+    return Rd(at(nvedge[i][0]),at(nvedge[i][1]));}// opposite edge vertex i
+
+  Rd N(int i) const  { return ExtNormal(vertices,nvadj[i]);}
+  Rd PBord(int i,RdHatBord P) const   { return Data::PBord(nvadj[i],P);}  
+
+  Rd operator()(const RdHat & Phat) const {
+    Rd r= (1.-Phat.sum())*(*(Rd*) vertices[0]);    
+    for (int i=1;i<nv;++i)
+      r+=  Phat[i-1]*(*(Rd*) vertices[i]);
+    return r;
+  }
+
+ int faceOrient(int i) const 
+    {// def the permutatution of orient the face
+	int fo =1;
+	const Vertex * f[3]={&at(nvface[i][0]), &at(nvface[i][1]), &at(nvface[i][2])}; 
+	if(f[0]>f[1]) fo = -fo,Exchange(f[0],f[1]); 
+	if(f[1]>f[2]) { fo = -fo,Exchange(f[1],f[2]); 
+	if(f[0]>f[1]) fo = -fo,Exchange(f[0],f[1]); }
+	return fo;
+    }
+    
+  int facePermutation(int i) const 
+  {// def the permutatution of orient the face
+    int fo =0;
+    const Vertex * f[3]={&at(nvface[i][0]), &at(nvface[i][1]), &at(nvface[i][2])}; 
+    if(f[0]>f[1]) fo+=1,Exchange(f[0],f[1]); 
+    if(f[1]>f[2]) { fo+=2,Exchange(f[1],f[2]); 
+    if(f[0]>f[1]) fo+=4,Exchange(f[0],f[1]); }
+    return fo;
+  }
+
+  bool   EdgeOrientation(int i) const 
+    { return &at(nvedge[i][0]) < &at(nvedge[i][1]);}
+    
+  R lenEdge(int i) const {ASSERTION(i>=0 && i <3);
+    Rd E=Edge(i);return sqrt((E,E));}
+
+  R  mesure() const {return mes;}
+
+
+    
+  static  int NbNodes(int c)  // use the bit i of c to say if node in objet of dim  i existe
+  { int c0=(c&1)!=0, c1=(c&2)!=0, c2=(c&4)!=0, c3=(c&8)!=0;  
+    return nv*c0 +ne*c1 +nf*c2 + nt*c3 ;}
+
+    static  int NbNodes(const int c[4])  // use the bit i of c to say if node in objet of dim  i existe
+  { int c0=(c[0])!=0, c1=(c[1])!=0, c2=(c[2])!=0, c3=(c[3])!=0;  
+    return nv*c0 +ne*c1 +nf*c2 + nt*c3 ;}
+
+  void Renum(Vertex   *v0, int * r)  
+  { 
+    for (int i=0;i<nv;i++) 
+      vertices[i]=v0+r[vertices[i]-v0];
+  }
+
+  void Change(Vertex   *vold, Vertex *vnew) 
+  { 
+    for (int i=0;i<nv;i++) 
+      vertices[i]=vnew+vertices[i]-vold;
+  }
+
+  //Rd n(int i) const //  unit exterior normal
+  //  {Rd E=Edge(i);return Rd(E.y,-E.x)/Norme2(E);} 
+   
+    
+private:
+  // pas de copie
+  GenericElement(const  GenericElement &);
+  GenericElement &operator = (const  GenericElement &);
+};
+
+ 
+    template<int N> inline void PermI2J(const void **I,const void **J,int *S)
+    {
+	ffassert(0);
+    }
+    template<> inline void PermI2J<1>(const void **I,const void **J,int *S)
+    {
+	S[0]=0;
+    }
+    template<> inline void PermI2J<2>(const void **I,const void **J,int *S)
+    {
+	if(I[0]==J[0])
+	  { assert(I[1]==J[1]);
+	    S[0]=0;S[1]=1;}
+	else 
+	  { assert(I[1]==J[0]&&I[0]==J[1]);
+	    S[0]=1;S[1]=0;}	
+    }
+    template<> inline void PermI2J<3>(const void **I,const void **J,int *S)
+    {
+	if(I[0]==J[0]) S[0]=0;
+	else if(I[0]==J[1]) S[0]=1;
+	else {S[0]=2; assert(I[0]==J[2]) ;}
+	if(I[1]==J[0]) S[1]=0;
+	else if(I[1]==J[1]) S[1]=1;
+	else {S[1]=2; assert(I[1]==J[2]) ; }
+	S[2]=3-S[0]-S[1];
+	assert(I[2]==J[3-S[0]-S[1]]);
+    }
+    
+template<typename T,typename B,typename V>
+class GenericMesh : public RefCounter
+{ 
+public:
+  typedef GenericMesh GMesh;
+  typedef T Element;   
+  typedef typename V::Rd Rd;
+  typedef typename Rd::R R;
+  typedef V  Vertex;
+  typedef B BorderElement;
+  typedef  EF23::GTree<V> GTree;
+  typedef typename Element::RdHat RdHat;// for parametrization                                        
+
+  int nt,nv,nbe;
+  R mes,mesb;
+  //private:
+  V *vertices;
+  T *elements;
+  B *borderelements;
+  Rd  * bnormalv; //  boundary vertex normal 
+  Rd Pmin,Pmax; // // the bound  of the domain  see BuildBound 
+  static const int nea=T::nea; //  numbering of adj (4 in Tet,  3 in Tria, 2 in seg) 
+  static const int nva=T::nva; //  numbering of vertex in Adj element 
+  static int kfind,kthrough; //  number of search and number of throught element. 
+  int *TheAdjacencesLink; // to store the adj link  k*nea+i -> k'*nea+i' 
+  int *BoundaryElementHeadLink; //
+  int *ElementConteningVertex;  
+  GTree *gtree;
+public:
+    int nbElmts() const {return nt;}
+    int nbBrdElmts() const {return nbe;}
+    int nbVertices() const {return nv;}
+    const T & operator[](int i) const {return elements[CheckT(i)];}
+  const V& operator()(int i) const {return vertices[CheckV(i)];}
+  const B& be(int i) const {return borderelements[CheckBE(i)];}
+  void  BoundingBox(Rd &pmin,Rd &pmax) const {pmin=Pmin;pmax=Pmax;} 
+  T & t(int i)  {return elements[CheckT(i)];}
+  V & v(int i)  {return vertices[CheckV(i)];}
+  B & be(int i) {return borderelements[CheckBE(i)];}
+    
+    
+  GenericMesh()
+    : nt(0),nv(0),nbe(0),  mes(0.),mesb(0.) ,
+      vertices(0),elements(0),borderelements(0),bnormalv(0),
+      TheAdjacencesLink(0),BoundaryElementHeadLink(0),
+      ElementConteningVertex(0), gtree(0)
+  {} 
+ 
+  GenericMesh(const  Serialize &serialized) ;
+    
+  void set(int mv,int mt,int mbe) 
+  {
+    assert(nt==0 && nv==0 && nbe ==0);
+    nt=mt;
+    nv=mv;
+    nbe=mbe;
+    vertices=new V[nv];
+    elements= new T[nt];
+    borderelements = new B[nbe]; 
+    assert( nt >=0 && elements);
+    assert( nv >0 && vertices);
+    
+  }
+ 
+ 
+  int operator()(const T & tt) const {return CheckT(&tt - elements);}
+  int operator()(const T * tt) const {return CheckT(tt - elements);}
+  int operator()(const V & vv) const {return CheckV(&vv - vertices);}
+  int operator()(const V  * vv) const{return CheckV(vv - vertices);}
+  int operator()(const B & k) const {return CheckBE(&k - borderelements);}
+  int operator()(const B  * k) const{return CheckBE(k - borderelements);}
+  int operator()(int it,int j) const {return operator()(elements[it][j]);}// Nu vertex j of triangle it
+  int be(int it,int j) const {return operator()(borderelements[it][j]);}// Nu vertex j of triangle it
+  
+  int CheckV(int i) const { ASSERTION(i>=0 && i < nv); return i;} 
+  int CheckT(int i) const { ASSERTION(i>=0 && i < nt); return i;}
+  int CheckBE(int i) const { ASSERTION(i>=0 && i < nbe); return i;}
+  
+   
+  int Contening(const Vertex * vv) const{ return ElementConteningVertex[ vv  - vertices];} 
+  void BuildAdj();
+  void BuildBoundaryElementAdj();  // Add J. Morice function that give the TheAdjacencesSurfaceLink :: Version avec un manifold
+  void BuildBoundaryElementAdj(const int &nbsurf, int* firstDefSurface, int* labelDefSurface, int* senslabelDefSurface); // version avec plusieurs vari�t�s
+  // void BuildBoundaryElementAdj_V2(const int &nbsurf, int* firstDefSurface, int* labelDefSurface, int* senslabelDefSurface); // bug inside a retoucher
+  void Buildbnormalv();
+  void BuildBound();
+  void BuildjElementConteningVertex();
+  void BuildGTree() {if(gtree==0)  gtree=new GTree(vertices,Pmin,Pmax,nv);}    
+  DataFENodeDF BuildDFNumbering(int dfon[NbTypeItemElement],int nbequibe=0,int *equibe=0) const ;
+    DataFENodeDF BuildDFNumbering(int ndfv,int ndfe,int ndff,int ndft,int nbequibe=0,int *equibe=0) const 
+  { int dfon[NbTypeItemElement]={ndfv,ndfe,ndff,ndft};
+    return  BuildDFNumbering(dfon,nbequibe,equibe);
+  }
+  
+  int ElementAdj(int k,int &j) const  {
+    int p=TheAdjacencesLink[nea*k+j];
+    if(p>=0) j=p%nea;
+    return p>=0 ? p/nea: -1-j;}// modif FH. to change the code of copule k,kadj on border element..
+    //  correct bug of 23/05/2013 : 1  dof on RT0 3d... 
+    
+
+
+  int ElementAdj(int k,int &j,Rd& PHat) const  
+    {
+    //   return the kk the number of adj element k  to hyperface j (opposite to vertex j)
+    //   out j: is the new hyperface number in element kk.
+    // and 
+    // in : Pt is the point  on hyperface j on element k on ref element K hat.
+    //  remark   lb[j]==0  at enter
+    // you get the new 	point Pt (in  on hyperface j on element kk
+    //  and lb[j] ==0 at return (j have change).
+    int p=TheAdjacencesLink[nea*k+j];
+    if(p>=0) 
+      {
+	
+	  R lb[Rd::d+1];//{1.-PHat.sum(),PHat}; 
+	  R lbb[Rd::d+1];//{1.-PHat.sum(),PHat}; 
+	  PHat.toBary(lb); // R1 R2 R3 
+	  if(Abs(lb[j])>1e-10)
+	   assert(Abs(lb[j])<1e-10);
+	int sigma[T::nva];	  
+	const void * nvkj[T::nva], *nvkkjj[T::nva];
+	int jj=p%nea;
+	int kk=p/nea;
+
+	Element & K(elements[CheckT(k)]);
+	Element & KK(elements[CheckT(kk)]);
+	Rd Pin=K(PHat);  
+	for (int l=0;l<T::nva;++l)
+	    nvkj[l] =&K[T::nvadj[j][l]];
+	for (int l=0;l<T::nva;++l)
+	    nvkkjj[l] = &KK[T::nvadj[jj][l]];
+	//  il faut permute ll.
+	PermI2J<nva>(nvkj,nvkkjj,sigma);
+	for (int l=0;l<T::nva;++l)
+	    lbb[T::nvadj[jj][l]]=lb[T::nvadj[j][sigma[l]]];
+	lbb[jj]=0;
+#ifdef DEBUG	  
+	Rd PH=PHat;  
+#endif
+	PHat=Rd(lbb+1);
+#ifdef DEBUG	  
+	Rd Pout=KK(PHat);
+	if( (Pin-Pout).norme2() > 1e-10 )
+	    {
+		for (int l=0;l<=T::nva;++l)
+		    cout << lbb[l] <<" < -- " << lb[l] << endl;
+		for (int l=0;l<T::nva;++l)
+		    cout <<l << " :    o=  " << nvkkjj[l]  << "   i= " << nvkj[l] << " " <<  sigma[l] 
+		         << " -- " << &KK[T::nvadj[jj][l]]  << " == " << &K[T::nvadj[j][sigma[l]]] 
+		    << " -- " << &K[T::nvadj[j][l]]  << " == " << &KK[T::nvadj[jj][sigma[l]]] 
+		    << " -- " << lbb[T::nvadj[jj][l]] << " == " << lb[T::nvadj[j][sigma[l]]]
+		    << " ++ " << T::nvadj[jj][l] << " <-- " << T::nvadj[j][sigma[l]] 
+		    << endl;
+		cout << "Adj:  j= " << j << " ," << Pin << " != " << Pout << " , " << PH << " -> " << PHat << "  jj = " << jj <<  endl;
+		assert(0);
+	    }
+#endif	  
+	j=jj;
+	return kk;
+      }
+    return -1;//  on border 
+  }
+    
+  int GetAllElementAdj(int it,int *tabk) const
+  { //  get the tab of all adj element (max ne)
+    //  and return the size of the tab 
+    int i=0;
+    for(int j=0;j<nea;++j)
+      {
+	tabk[i]=TheAdjacencesLink[3*it+j]/3;
+	if(tabk[i] >=0 && tabk[i]!=it) i++; 
+      }
+    return i;
+  }
+
+  int BoundaryElement(int bbe,int & ItemInK) const {
+    int i= BoundaryElementHeadLink[bbe]; 
+    ItemInK = i%nea; 
+    return i/nea;}
+  
+  // Add J. Morice 
+  template<int N,int M>
+  SortArray<int,N> itemadjs(const int (* const  nu )[N],int k,int i, int *sens) 
+  {
+    int nnv[N];
+    B & K(borderelements[CheckBE(k)]);
+    ASSERTION(i>=0 && i <M);
+    for (int j=0;j<N;++j){
+      nnv[j] = operator()(K[nu[i][j]]);
+    }
+    if(nnv[0] > nnv[1] )
+      *sens = 1;
+    else
+      *sens =-1;
+    return SortArray<int,N>(nnv);
+  }
+
+  SortArray<int,B::nva> items(int k,int i,int *sens) 
+  {
+    return itemadjs<B::nva,B::nv>(B::nvadj,k,i,sens);
+  }
+
+  
+  template<int N,int M>
+  SortArray<int,N> iteme(const int (* const  nu )[N],int k,int i) 
+  {
+    int nnv[N];
+    Element & K(elements[CheckT(k)]);
+    ASSERTION(i>=0 && i <M);
+    for (int j=0;j<N;++j){
+      nnv[j] = operator()(K[nu[i][j]]);
+    }
+
+    return SortArray<int,N>(nnv);
+  }
+
+  SortArray<int,B::nv> itemadj(int k,int i) 
+  {
+    return iteme<B::nv,T::nea>(T::nvadj,k,i);
+  }
+  
+  SortArray<int,B::nv> itembe(int k) 
+  {
+    int nnv[B::nv];
+    B & K(borderelements[CheckBE(k)]);
+    
+    for (int j=0;j<B::nv;++j){
+      nnv[j] = operator()(K[j]);
+    }
+
+    return SortArray<int,B::nv>(nnv);
+  }
+
+  //  const Element * Find(const Rd & P) const ;
+  const Element * Find(Rd P, RdHat & Phat,bool & outside,const Element * tstart=0) const  
+  {return EF23::Find<GMesh>(*this,this->gtree,P,Phat,outside,tstart);}
+  
+  R mesure(){ return mes;}
+  R bordermesure(){ return mesb;}
+  virtual ~GenericMesh() { 
+    //cout << "~GenericMesh\n";
+   
+    delete [] ElementConteningVertex;
+    delete [] TheAdjacencesLink;
+    delete [] BoundaryElementHeadLink;
+    delete [] borderelements;
+    if(nt>0) delete [] elements;
+    delete [] vertices;
+    delete [] bnormalv;
+    if(gtree) delete gtree;
+      ElementConteningVertex=0;
+      TheAdjacencesLink=0;
+      BoundaryElementHeadLink=0;
+      borderelements=0;
+      elements=0;
+      vertices=0;
+      bnormalv=0;
+      gtree=0;
+      nt=(0);
+      nv=(0);
+      nbe=(0);
+      mes=(0.);
+      mesb=(0.);
+  }
+
+  Serialize serialize() const;
+  
+private:
+  GenericMesh(const GenericMesh &); // pas de construction par copie
+   void operator=(const GenericMesh &);// pas affectation par copy 
+};
+
+template<typename T,typename B,typename V>
+void GenericMesh<T,B,V>::BuildjElementConteningVertex()
+{
+  const int nkv= T::nv;
+    int lerr[10];
+  if(!ElementConteningVertex) ElementConteningVertex = new int[nv];
+
+    for(int i=0;i<nv;++i)
+	ElementConteningVertex[i]=-1; 
+    
+    for (int k=0;k<nt;++k)
+	for (int i=0;i<nkv;++i)
+	    ElementConteningVertex[operator()(elements[k][i])]=k ;
+    int kerr=0;
+    for(int i=0;i<nv;++i)
+	if (ElementConteningVertex[i]<0) 
+	    if(kerr<10) lerr[kerr++]=i; 
+    if(kerr)
+      {
+	cerr << " Fatal error: some vertex are not at least in one element  \n       :   " ;
+	for(int i=0;i<kerr;++i)
+	    cerr << " " << lerr[i];
+	cerr << endl;
+      }
+    ffassert(kerr==0);//  Sure Error.
+
+} 
+template<typename T,typename B,typename V>
+void GenericMesh<T,B,V>::BuildAdj()
+{
+ // const int nva   = T::nva;
+ // const int nea   = T::nea;
+  if(TheAdjacencesLink!=0) return ;//  already build ... 
+  TheAdjacencesLink = new int[nea*nt];
+  BoundaryElementHeadLink = new int[nbe];
+  HashTable<SortArray<int,nva>,int> h(nea*nt,nv);
+  int nk=0,nba=0;
+  int err=0;
+if(verbosity>5) 
+  cout << "   -- BuildAdj:nva=// nea=" << nva << " " << nea << " "<< nbe << endl;
+  for (int k=0;k<nt;++k)
+    for (int i=0;i<nea;++i)
+      {
+        SortArray<int,nva> a(itemadj(k,i));
+	//cout << " ### "   << " item(k,i)= " << itemadj(k,i) << " a= " << a << " k " << k << " i " << i << endl;
+	typename HashTable<SortArray<int,nva>,int>::iterator p= h.find(a);
+	if(!p) 
+	  { 
+	    h.add(a,nk);
+	    TheAdjacencesLink[nk]=-1;
+	    nba++;
+	  }
+	else 
+	  {	  
+	    ASSERTION(p->v>=0);
+	    TheAdjacencesLink[nk]=p->v;
+	    TheAdjacencesLink[p->v]=nk;
+	    p->v=-1-nk;
+	    nba--;
+	  }
+	++nk;
+      }
+    
+  for (int k=0;k<nbe;++k)
+     {
+	SortArray<int,nva> a(itembe(k));
+
+	typename HashTable<SortArray<int,nva>,int>::iterator p= h.find(a);
+	//cout << k << " ### "   << " item(k,i)= " << itembe(k) << " a= " << a << endl;
+	if(!p) { err++;
+	  if(err==1) cerr << "Err  Border element not in mesh \n";
+	  if (err<10)  cerr << " \t " << k << " " << a << endl;
+	}
+	 else
+	   {
+	     BoundaryElementHeadLink[k] = p->v <0 ? -p->v-1 : p->v;
+	     #ifndef NDEBUG
+	     int tt=BoundaryElementHeadLink[k]/nea;
+	     int ee=BoundaryElementHeadLink[k]%nea;
+	     //cout << k << " ### "   << a << " = " << itemadj(t,e) << " t " << t << " e " << e << endl;
+	     assert(itemadj(tt,ee)==a);
+	     #endif
+	   }
+     }
+
+    
+  assert(err==0);
+  int na= h.n;
+  if(verbosity>1) 
+    {
+	cout << "  -- BuildAdj: nb Elememt " << nt << " nb vertices " << nv << endl;
+	cout << "             : nb adj  = "<< na << " on border " << nba << " nea = " << nea << " nva = " << nva ;
+      if(nea==2)
+        cout << " Const d'Euler: " << nt - na + nv << endl;
+      else
+        cout << endl;	
+    }	
+}
+/*
+template<typename T,typename B,typename V>
+void GenericMesh<T,B,V>::BuildSurface(const int &nb, KN<int> SurfaceDef)
+{
+  int nbsurf;
+  nbsurf = nb;
+  KN<int> surfa
+  
+}
+*/
+
+
+template<typename T,typename B,typename V>
+void GenericMesh<T,B,V>::BuildBoundaryElementAdj()
+{
+  // Return in TheBorderElementAjacencesLink
+  //  if exist a link :: sign(nk_link)*(nk_link+1)
+  //  else            :: sign(nk)*(nk)
+
+  // assert(TheBoundaryElementAdjacencesLink==0); plus tard
+  int *TheBoundaryElementAdjacencesLink = new int[B::nea*nbe];
+  HashTable<SortArray<int,B::nva>,int> h(B::nea*nbe,nv);
+  int nk=0;
+  int err=0;
+  int sens;
+
+  cout << "nea/nva" << B::nea << " "  << B::nva << endl;
+  for (int k=0;k<nbe;++k)
+    for (int i=0;i<B::nea;++i)
+      {
+        SortArray<int,B::nva> a(items(k,i,&sens));
+
+	typename HashTable<SortArray<int,B::nva>,int>::iterator p= h.find(a);
+	if(!p) 
+	  { 
+	    h.add(a,nk);
+	    TheBoundaryElementAdjacencesLink[nk] = sens*(nk+1)   ;  // sens;
+	  } 
+	else 
+	  {	    
+	    ASSERTION(p->v>=0);
+	    if( sens*TheBoundaryElementAdjacencesLink[p->v] > 0 ){
+	      
+	      B & K(borderelements[CheckBE(k)]);
+	      int firstVertex  =  operator()(K[B::nvadj[i][0]])+1;
+	      int secondVertex =  operator()(K[B::nvadj[i][1]])+1;
+	      cout << " The edges defined by vertex is " << firstVertex << "-" << secondVertex << ", is oriented in the same direction in element " << k+1 << 
+		" and in element "<<  1+(p->v/B::nea) << endl;
+	      err++;
+	      assert(err==0);
+	    }
+	    if( abs(TheBoundaryElementAdjacencesLink[p->v]) != 1+p->v ){
+	      
+	      B & K(borderelements[CheckBE(k)]);
+	      int firstVertex  =  operator()(K[B::nvadj[i][0]])+1;
+	      int secondVertex =  operator()(K[B::nvadj[i][1]])+1;
+	      cout << " The edges defined by vertex is " << firstVertex << "-" << secondVertex << "belong to the three border elements ::" 
+		   << 1+(p->v)/B::nea <<", "<< k+1 <<" and "<< 1+(abs(TheBoundaryElementAdjacencesLink[p->v])-1)/B::nea << endl;
+	      cout << " The Surface contains these edges is not a manifold" << endl;
+	      err++;
+	    }
+
+	    TheBoundaryElementAdjacencesLink[nk]= TheBoundaryElementAdjacencesLink[p->v];
+	    TheBoundaryElementAdjacencesLink[p->v]= sens*(nk+1);  
+	   
+	  }
+	if( err > 10 ) 
+	  exit(1); 
+	nk++;
+      }
+    
+  assert(err==0);
+  delete [ ] TheBoundaryElementAdjacencesLink; 
+  if(verbosity) cout << "number of adjacents edges " << nk << endl; 
+}
+
+
+template<typename T,typename B,typename V>
+void GenericMesh<T,B,V>::BuildBoundaryElementAdj(const int &nbsurf, int* firstDefSurface, int* labelDefSurface, int* senslabelDefSurface)
+{
+
+   // Return in TheBoundaryElementAdjacences
+  //  if exist a link :: sign(nk_link)*(nk_link+1)
+  //  else            :: sign(nk)*(nk)
+
+
+  for(int isurf=0; isurf < nbsurf; isurf++){
+   
+    //###################################### 
+    // Trop operations if ===> a changer 
+
+    int nbe_surf=0; // number in the surface
+
+    for(int k=0; k<nbe; k++){
+      B & K(borderelements[CheckBE(k)]);
+      int label = K.lab;
+      for(int iii=firstDefSurface[isurf]; iii< firstDefSurface[isurf+1];iii++) 
+	if( label == labelDefSurface[iii] ) nbe_surf++;  	  
+    }
+
+    int facek=0;
+    int *surf_be=new int[nbe_surf];
+    int *orientation_surf_be=new int[nbe_surf];
+    for(int k=0; k<nbe; k++){
+      B & K(borderelements[CheckBE(k)]);
+      int label = K.lab;
+      for(int iii=firstDefSurface[isurf]; iii< firstDefSurface[isurf+1];iii++) 
+	if( label == labelDefSurface[iii] ) {
+	  surf_be[facek]=k ; 
+	  orientation_surf_be[facek]=senslabelDefSurface[iii];
+	  facek++;
+	}
+    }
+    
+    //######################################
+   
+    // assert(TheBoundaryElementAdjacencesLink==0); plus tard
+    int *TheBoundaryElementAdjacencesLink = new int[B::nea*nbe_surf];
+    HashTable<SortArray<int,B::nva>,int> h(B::nea*nbe_surf,nv);
+    int nk=0;
+    int err=0;
+    int sens;
+
+    cout << "nea/nva" << B::nea << " "  << B::nva << endl;
+    for (int k=0;k<nbe_surf;++k)
+      for (int i=0;i<B::nea;++i)
+	{
+	  SortArray<int,B::nva> a(items( surf_be[k],i,&sens));
+	  sens=sens*orientation_surf_be[k];
+	  typename HashTable<SortArray<int,B::nva>,int>::iterator p= h.find(a);
+	  if(!p) 
+	    { 
+	      h.add(a,nk);
+	      TheBoundaryElementAdjacencesLink[nk]=sens*(nk+1);   
+	      // nk est un nombre locale depend de la surfaces choisie
+	      // element du bord est donn�e par ::  surf_be[nk/3];
+	      // arrete corespondante locale de l'element :: nk%3; 
+	    }
+	  else 
+	    {
+	      
+	      ASSERTION(p->v>=0);
+	      if( sens*TheBoundaryElementAdjacencesLink[p->v] > 0 ){
+		
+		B & K(borderelements[CheckBE(surf_be[k])]);
+		int firstVertex  =  operator()(K[B::nvadj[i][0]])+1;
+		int secondVertex =  operator()(K[B::nvadj[i][1]])+1;
+		cout << " The edges, defined by vertex is " << firstVertex << "-" << secondVertex <<  ", is oriented in the same direction in element " << surf_be[k]+1 << 
+		  " and in element "<<  1+surf_be[(p->v/B::nea)] << endl;
+	
+		err++;
+	      }
+	     
+	      if( abs(TheBoundaryElementAdjacencesLink[p->v]) != 1+p->v ){
+		
+		B & K(borderelements[CheckBE(k)]);
+		int firstVertex  =  operator()(K[B::nvadj[i][0]])+1;
+		int secondVertex =  operator()(K[B::nvadj[i][1]])+1;
+		cout << " The edges defined by vertex is " << firstVertex << "-" << secondVertex << "belong to the three border elements ::" 
+		     << 1+surf_be[(p->v)/B::nea] <<", "<< surf_be[k]+1 <<" and  "<< 1+surf_be[(abs(TheBoundaryElementAdjacencesLink[p->v])-1)/B::nea] << endl;
+		cout << " The "<< isurf+1 << " Surface contains these edges is not a manifold" << endl;
+		err++;
+		assert(err==0);
+	      }
+	      
+
+	      TheBoundaryElementAdjacencesLink[nk]   = TheBoundaryElementAdjacencesLink[p->v];;
+	      TheBoundaryElementAdjacencesLink[p->v] = sens*(nk+1);  
+	      
+	    }
+	  if( err > 10 ) 
+	    exit(1); 
+	  nk++;
+	}
+	
+    assert(err==0);
+    delete [] surf_be;
+    delete [] orientation_surf_be;
+    delete [ ] TheBoundaryElementAdjacencesLink; 
+    if(verbosity) cout << "number of adjacents edges " << nk << endl; 
+  } 
+}
+
+
+
+
+// template<typename T,typename B,typename V>
+// void GenericMesh<T,B,V>::BuildBoundaryElementAdj_V2(const int &nbsurf,int *firstDefSurface, int *labelDefSurface, int *senslabelDefSurface)
+// {
+// //   assert(firstDefSurface.N() == nbsurf+1);
+// //   assert(labelDefSurface.N() == firstDefSurface[nbsurf]);
+// //   assert(senslabelDefSurface.N() == firstDefSurface[nbsurf]);
+
+//   // determination des labels des surfaces
+//   map<int, int> maplabel; 
+//   int numero_label=0;
+//   for(int ii=0; ii< firstDefSurface[nbsurf]; ii++){
+//     map<int,int>::const_iterator imap=maplabel.find( abs(labelDefSurface[ii]) );
+//     //cout << "K.lab= " << K.lab << endl; 
+//     if(imap == maplabel.end()){
+//       maplabel[ abs(labelDefSurface[ii]) ] = numero_label;
+//       numero_label = numero_label+1;
+//     }
+//   }
+
+//   int *nbe_label=new int[numero_label];
+//   for(int ii=0; ii< numero_label; ii++) nbe_label[ii] = 0;
+//   for(int k=0; k<nbe; k++){
+//     B & K(borderelements[CheckBE(k)]);
+//     map<int,int>::const_iterator imap=maplabel.find( K.lab );
+    
+// //  if(imap == maplabel.end()){
+// //       printf("The label %d given for Definition of different surface is not in the border element mesh\n",K.lab); 
+// //       exit(1);
+// //     }
+// //     else{
+//     nbe_label[(*imap).second]++;
+//     //    }
+//   }
+
+//   int all_nbe_label=0;
+//   for(int k=0; k<numero_label; k++){
+//     all_nbe_label=all_nbe_label+nbe_label[k];
+//   }
+//   /*
+//     if(all_nbe_label != nbe){
+//     cerr << "some element in the border element are not references in the Surface description" << endl;
+//     exit(1);
+//     }
+//     assert(all_nbe_label == nbe);  // autrement cela veut dire que certain element du bord n'ont pas �t� mis dans le descriptif
+//   */
+//   int *organisation_be_label;
+//   organisation_be_label = new int[all_nbe_label];
+  
+//   int *count_nbe_label =new int[numero_label];
+//   int *debut_nbe_label =new int[numero_label+1];
+
+//   for(int ii=0; ii< numero_label; ii++)
+//     count_nbe_label[ii] =0; 
+
+//   debut_nbe_label[0]=0;
+//   for(int ii=1; ii< numero_label; ii++) 
+//     debut_nbe_label[ii] = debut_nbe_label[ii-1]+nbe_label[ii-1]; 
+//   debut_nbe_label[numero_label] = all_nbe_label;
+
+//   for(int k=0; k<nbe; k++){
+//     B & K(borderelements[CheckBE(k)]);
+//     map<int,int>::const_iterator imap=maplabel.find( K.lab );
+//     assert(imap != maplabel.end());
+//     organisation_be_label[ debut_nbe_label[(*imap).second] + count_nbe_label[(*imap).second] ] = k ;
+//     count_nbe_label[(*imap).second ]++;
+//   }
+
+//   for(int ii=0; ii< numero_label; ii++) 
+//     assert( count_nbe_label[ii] == nbe_label[ii] );
+  
+//   delete [] count_nbe_label;
+
+//   for(int isurf=0; isurf < nbsurf; isurf++){
+  
+//     int nbe_surf=0; // number in the surface
+//     for( int iii=firstDefSurface[isurf]; iii< firstDefSurface[isurf+1];iii++ ){
+//       map<int,int>::const_iterator imap=maplabel.find( abs(labelDefSurface[iii]) );
+//       nbe_surf=nbe_surf+nbe_label[ (*imap).second ];
+//     }
+  
+//     // assert(TheBoundaryElementAdjacencesLink==0); plus tard
+//     int *TheBoundaryElementAdjacencesLink = new int[B::nea*nbe_surf];
+//     HashTable<SortArray<int,B::nva>,int> h(B::nea*nbe_surf,nv);
+//     int nk=0;
+//     int err=0;
+//     int sens;
+   
+//     int count_sbe; 
+//     int *surf_be = new int[nbe_surf]; 
+    
+//     count_sbe=0; 
+//     for( int iii=firstDefSurface[isurf]; iii< firstDefSurface[isurf+1];iii++ ){
+//       map<int,int>::const_iterator imap=maplabel.find( abs(labelDefSurface[iii]) );
+      
+//       for( int jjj= debut_nbe_label[(*imap).second]; jjj < debut_nbe_label[(*imap).second+1]; jjj++ ){
+// 	int k=organisation_be_label[jjj];
+// 	surf_be[count_sbe] = k; 
+// 	count_sbe++;
+
+// 	for (int i=0;i<B::nea;++i)
+// 	  {
+// 	    SortArray<int,B::nva> a(items( k,i,&sens));
+// 	    sens=sens*senslabelDefSurface[iii];
+// 	    typename HashTable<SortArray<int,B::nva>,int>::iterator p= h.find(a);
+// 	    if(!p) 
+// 	      { 
+// 		h.add(a,nk);
+// 		TheBoundaryElementAdjacencesLink[nk] = sens*(nk+1);
+//  	      }
+// 	    else 
+// 	      {
+		
+// 		ASSERTION(p->v>=0);
+// 		if( sens*TheBoundaryElementAdjacencesLink[p->v] > 0){
+		  
+// 		  B & K(borderelements[CheckBE(k)]);
+// 		  int firstVertex  =  operator()(K[B::nvadj[i][0]])+1;
+// 		  int secondVertex =  operator()(K[B::nvadj[i][1]])+1;
+// 		  cout << " The edges, defined by vertex is " << firstVertex << "-" << secondVertex << ", is oriented in the same direction in element " << k+1 << 
+// 		    " and in element "<<  1+surf_be[(p->v/B::nea)] << endl;
+// 		  err++;
+// 		}
+		
+// 		if( abs(TheBoundaryElementAdjacencesLink[p->v]) != 1+p->v ){
+		
+// 		  B & K(borderelements[CheckBE(k)]);
+// 		  int firstVertex  =  operator()(K[B::nvadj[i][0]])+1;
+// 		  int secondVertex =  operator()(K[B::nvadj[i][1]])+1;
+// 		  cout << " The edges defined by vertex is " << firstVertex << "-" << secondVertex << "belong to the three border elements ::" 
+// 		       << 1+surf_be[(p->v)/B::nea] <<", "<< surf_be[k]+1 <<" and  "<< 1+surf_be[(abs(TheBoundaryElementAdjacencesLink[p->v])-1)/B::nea] << endl;
+// 		  cout << " The "<< isurf+1 << " Surface contains these edges is not a manifold" << endl;
+// 		  err++;
+// 		  assert(err==0);
+// 		}
+				
+// 		TheBoundaryElementAdjacencesLink[nk]=TheBoundaryElementAdjacencesLink[p->v];
+// 		TheBoundaryElementAdjacencesLink[p->v]=sens*(nk+1);  		
+// 	      }
+
+// 	    if( err > 10 ) 
+// 	      exit(1); 
+// 	    nk++;
+// 	  }
+//       }
+//     }
+    
+//     assert(err==0);
+//     delete [ ] TheBoundaryElementAdjacencesLink;
+//     delete [ ] surf_be;
+//     if(verbosity) cout << "number of adjacents edges " << nk << endl; 
+//   }
+
+//   delete [] organisation_be_label;
+//   delete [] debut_nbe_label;
+//   delete [] nbe_label;
+// }
+
+
+template<typename T,typename B,typename V>
+DataFENodeDF GenericMesh<T,B,V>::BuildDFNumbering(int ndfon[NbTypeItemElement],int nbequibe,int *equibe) const
+{
+/*
+   nbequibe nb of  borderelement with equi boundary condition
+  for i =0, 2*nbequibe, i+= 2)
+    
+     be0= equibe[i]/8 <=>  be1=equibe[i+1] /8
+     equibe[i]%8    given the permuation  p0 compare to sort array. 
+     equibe[i+1]%8 given the permuation   p1 compare to sort array.
+    the  numbering of perumation 
+     SetNumPerm<nkf>(p0,equibe[i+1]%8);
+     SetNumPerm<nkf>(p1,equibe[i+1]%8);
+    
+    so a level of point with always have:
+      be0[p0[j]] <==>  be1[p1[j]]
+ 
+ 
+ */
+  const GenericMesh & Th(*this);
+  int nnodeK = T::NbNodes(ndfon);
+  int *p = 0, *pp=0; 
+    unsigned int tinfty=std::numeric_limits<unsigned int>::max()   ; 
+    
+  const int nkv= T::nv;
+  const int nkf= T::nf;
+  const int nke= T::ne;
+  const int nkt= T::nt;
+  const int nbev= B::nv;
+  const int nbef= B::nf;
+  const int nbee= B::ne;
+  const int nk[]={nkv,nke,nkf,nkt};
+  int MaxNbNodePerElement=0;
+  int MaxNbDFPerElement=0;
+  int nbNodes=0;
+  int NbOfDF=0;
+  int n=0;
+  int minndf=100000000;
+  int maxndf=0;
+  int nbnzero=0;
+  for (int dd=0;dd<NbTypeItemElement;++dd)
+    if(ndfon[dd])
+      {
+	
+        nbnzero++;
+	minndf=Min(minndf,ndfon[dd]);
+	maxndf=Max(maxndf,ndfon[dd]);
+	MaxNbDFPerElement   += ndfon[dd]*nk[dd];
+	MaxNbNodePerElement += nk[dd];
+      }
+  bool constndfpernode = minndf == maxndf;
+  bool nodearevertices = ( nbnzero ==1  && ndfon[0]) && nbequibe==0 ;
+ 
+  assert(maxndf>0);
+  const int nkeys=4+6+4+1;
+  assert(nnodeK<= nkeys);
+  
+  if(nodearevertices)
+    {
+      nbNodes=nv;
+      NbOfDF=nbNodes*ndfon[0];
+    }
+  else
+    { 
+      p =  new int[nnodeK*nt];
+      typedef SortArray<unsigned int,2> Key;
+	
+      Key keys[nkeys*2];
+      int keysdim[nkeys*2];
+      
+      int of = Th.nv+10;// Modif FH 28/05/2013 
+      int ndim[NbTypeItemElement]={0,0,0,0};
+      NbOfDF=0;
+      {
+	HashTable<Key,int> h(nnodeK*nt,of+nt);
+	int  nbmaxeq = 1+nnodeK*nbequibe;
+	int  nbhasheq = nbequibe ? of+nt : 1;
+	HashTable<Key,Key> equi(nbmaxeq,nbhasheq); 
+	  //  constuction of item translation for 
+	  if(verbosity>2)
+	  cout << " nb equi be :  " << nbequibe << endl;
+	  for(int ieq=0,keq=0;keq<nbequibe;++keq)
+	    {
+		int p1[nbev],p2[nbev];
+		int v1[nbev],v2[nbev];
+		int be1=equibe[ieq]/8,pe1=equibe[ieq++]%8;
+		int be2=equibe[ieq]/8,pe2=equibe[ieq++]%8;
+		int itemb1,k1=BoundaryElement(be1,itemb1);
+		int itemb2,k2=BoundaryElement(be2,itemb2);
+		const B& b1(Th.be(be1));
+	        const B& b2(Th.be(be2));
+		SetNumPerm<nbev>(pe1,p1);
+		SetNumPerm<nbev>(pe2,p2);
+		int m=0;
+		for(int i=0;i<nbev;++i)
+		  {
+		      v1[i]=Th(b1[p1[i]]);
+		      v2[i]=Th(b2[p2[i]]);
+		  }
+		
+		int dimb= B::RdHat::d;
+		if(ndfon[dimb])
+		  { //  simple border element
+		  }
+                if( ndfon[0] )
+		    for(int i=0;i<nbev;++i)
+		  {
+		    keysdim[m]=0,keys[m++]=Key(v1[i],tinfty);
+		    keysdim[m]=0,keys[m++]=Key(v2[i],tinfty);
+		      if(verbosity >100) cout << be1<< " " << be2 << "  " <<  v1[i] << " <--> " << v2[i] 
+			                 << " /  " << Th(v1[i]) << " <=> " << Th(v2[i]) << endl;
+		  }
+		if( ndfon[1] )
+		  for(int i=0;i<nbee;++i)
+		  {
+		      keysdim[m]=1,keys[m++]=Key(v1[B::nvedge[i][0]],v1[B::nvedge[i][1]]);
+		      keysdim[m]=1,keys[m++]=Key(v2[B::nvedge[i][0]],v2[B::nvedge[i][1]]);
+		  }
+		if( ndfon[2] && dimb ==2)
+		  {
+		      assert(nbef==1 && nkf != 1);
+		      int ii;
+		      keysdim[m]=2,keys[m++]=Key(k1+of,ElementAdj(k1,ii=itemb1) +of);
+		      keysdim[m]=2,keys[m++]=Key(k2+of,ElementAdj(k2,ii=itemb2) +of);		     
+		  }
+		        
+		for(int j=0;j<m;)
+		  {
+		      int i0=j++,i1=j++; 
+		      if(keys[i1]<keys[i0]) swap( keys[i0],keys[i1]);
+		      //typename HashTable<Key,Key>::iterator pe =
+                      if(keys[i0]< keys[i1] ) // not equal ... Add nov. 2014 
+		        equi.add(keys[i0],keys[i1]);
+		     // if(pe) assert(pe->k == keys[i0]);
+		  }
+		
+	    }
+	  
+	  //  to find the final equivalent  key ... 
+	  //  in change of chaibe of equi key
+	  for (int it=0,change=1;change;it++)
+	    { 
+	    change=0;
+	    ffassert(it++<100);
+	    for (typename HashTable<Key,Key>::iterator qe,pe=equi.begin() ; pe != equi.end(); ++pe)
+	      { 
+                  if( verbosity>9999) cout << pe->k << " " << pe->v << endl;
+		  ffassert( pe->k < pe->v);
+		  qe=equi.find(pe->v);
+		  if(qe) 
+                  {
+                      if( verbosity>9999) cout << pe->k << " " << pe->v << " <=> " << qe->k <<endl;
+
+                     change++;
+		     ffassert( qe->k < qe->v);
+		      pe->v = qe->v;
+		  }
+	    
+		  
+	      }
+	     if(verbosity>5)
+	      cout << "     -- BuildDF: iteration in final equivalent " << it << " nb change " << change << endl;
+	    }
+	    
+	
+	  //  construction of nodes numbering 
+	  
+	  // ------------
+	  
+	for(int k=0;k<nt;++k)
+	  {
+	    const T & K(Th[k]);
+	    int m=0;
+	    if( ndfon[0] )//  node on vertex
+	      for(int i=0;i<nkv;++i)
+		keysdim[m]=0,keys[m++]=Key(Th(K[i]),tinfty);
+	    if(  ndfon[1] )//  node on Edge
+	      for(int i=0;i<nke;++i)
+		keysdim[m]=1,keys[m++]=Key(Th(K[T::nvedge[i][0]]),Th(K[T::nvedge[i][1]]));
+	    if(  ndfon[2])//  node on Face
+	      {
+	      if (nkf==1) 
+		keysdim[m]=2,keys[m++]=Key(k+of,tinfty);
+	      else
+		for(int ii,i=0;i<nkf;++i)
+		  keysdim[m]=2,keys[m++]=Key(k+of,ElementAdj(k,ii=i) +of);
+	      }
+	    if(  ndfon[3] )//  node on Tet
+	      if(nkt==1)
+		keysdim[m]=3,keys[m++]=Key(k+of,tinfty);
+	    
+	    if(k<0)
+	    {
+	      for(int i=0;i<nke;++i)
+		cout << " e= " << T::nvedge[i][0] << " " << T::nvedge[i][1] << endl;
+	      cout << ndfon[0] << " " << ndfon[1] << " " << ndfon[2] << " " << ndfon[3] << ": "
+		   <<  " m = "<< m << "  " <<nnodeK
+		   << " " << T::nv
+		   << " " << T::ne 
+		   << " " << T::nf 
+		   << " " << T::nt  
+		   << endl;
+	    }
+	    assert(m==nnodeK);
+	    for(int i=0;i<m;i++)
+	      {
+		Key ki=keys[i],kio=ki; 
+		typename HashTable<Key,Key>::iterator pe= equi.find(ki);
+		  if(pe) {   ki= pe->v;  }
+		typename HashTable<Key,int>::iterator pk= h.find(ki);
+		if(!pk)
+		 {
+		  pk = h.add(ki,nbNodes++);
+		  NbOfDF += ndfon[keysdim[i]];
+		 }
+		if(verbosity>100 && pe ) cout << kio << " -> " << pe->k  << " :: " <<  pk->v << endl;   
+		p[n++] = pk->v;
+		ndim[keysdim[i]]++;
+			  
+	      }
+	  }
+      }
+       if(verbosity)
+	 {   cout << "  -- Build Nodes/DF on mesh :   n.v. " << nv <<  ", n. elmt. " << nt << ", n b. elmt. " <<nbe << endl;
+	     cout << "     nb of Nodes " << nbNodes << "    nb of DoF   " << NbOfDF <<"  DFon="
+	          << ndfon[0]<<ndfon[1]<<ndfon[2]<<ndfon[3]<<endl ;	     
+	 }
+      if( ! constndfpernode) 
+	{ 
+	  pp=new int[nbNodes+1];
+	  int kk=0,nn=0;
+	  for(int k=0;k<nt;++k)
+	    for(int i=0;i<nnodeK;i++)
+		pp[p[nn++]]=ndfon[keysdim[i]];;
+	  for(int n=0;n<nbNodes;++n)	
+	    {  
+	      int ndfn=pp[n];
+	      pp[n]=kk;
+	      kk+=ndfn;
+	    }
+	  pp[nbNodes]=NbOfDF;//  add last 
+	  assert(kk==NbOfDF);
+	}
+    }
+  return DataFENodeDF(ndfon,nt,nbNodes,NbOfDF,p,pp,MaxNbNodePerElement,MaxNbDFPerElement);
+}
+template<typename T,typename B,typename V>
+void GenericMesh<T,B,V>::BuildBound()
+{
+    mes=0.;
+    mesb=0.;
+    
+    for (int i=0;i<nt;i++)  
+	mes += this->elements[i].mesure();
+    
+    for (int i=0;i<nbe;i++)  
+	mesb += this->be(i).mesure();  
+    
+    if(vertices && (nv>0))
+    {
+	Pmin=vertices[0];
+	Pmax=vertices[0];
+	 for(int i=1;i<nv;++i)
+	 {
+	     Pmin=Minc(Pmin,vertices[i]);
+	     Pmax=Maxc(Pmax,vertices[i]);
+
+	 }
+    }
+  if(verbosity>3)
+      cout << "  -- GMesh" << V::d << " , n V: " << nv << " , n Elm: " << nt << " , n B Elm: " << nbe 
+	 << " , bb: (" << Pmin << ") , (" << Pmax << ")\n"; 
+}
+
+template<typename T,typename B,typename V>
+void GenericMesh<T,B,V>::Buildbnormalv()
+{
+    const int nkv= T::nv;
+   // const int nkf= T::nf;
+   // const int nke= T::ne;
+   // const int nkt= T::nt;
+    
+    if (bnormalv) 
+      {return;}
+    int nb=0;
+    for (int k=0;k<nt;k++)
+	for (int i=0;i<nkv;i++)
+	{  
+	    int ii(i),kk;
+	    kk=ElementAdj(k,ii);
+	    if (kk<0 || kk==k) nb++;
+	}
+    if(verbosity>2)
+	cout << " number of real boundary  " << nb << endl;
+    bnormalv= new Rd[nb];
+    Rd *n=bnormalv;
+    for (int k=0;k<nt;k++)
+	for (int i=0;i<nea;i++)
+	{  
+	    int ii,kk=ElementAdj(k,ii=i);
+	    if (kk<0 || kk==k) {
+		Element & K(elements[k]);
+		Rd N;//=K.n(i);
+		for(int j=0;j<nva;++j)
+		{
+		    K[Element::nvadj[i][j]].SetNormal(n,N);
+		}
+		    
+	    }
+	}
+    // cout << nb << " == " << n-bnormalv << endl;
+    assert(n - bnormalv <= nb );
+}
+
+static const char * GenericMesh_magicmesh="GenericMesh v0";
+template<typename T,typename B,typename V>
+Serialize GenericMesh<T,B,V>::serialize() const
+{
+    const int nve = T::nv;
+    const int nvbe = B::nv;
+    const int d = Rd::d;
+    long long  l=0;
+    l += sizeof(long long);
+    l += 6*sizeof(int);
+    l += nt*(sizeof(int)*(nve + 1));
+    l += nv*( sizeof(int) + sizeof(double)*d);
+    l += nbe*(sizeof(int)*(nvbe+1));
+    if(verbosity>1)
+       cout << "Serialize gmesh " << l << " " << nve << " " << nvbe << endl;
+    Serialize  serialized(l,GenericMesh_magicmesh);
+    // cout << l << magicmesh << endl;
+    size_t pp=0;
+    serialized.put(pp, l); 
+    serialized.put( pp,d);
+    serialized.put( pp,nve);
+    serialized.put( pp,nvbe);
+    serialized.put( pp,nt);
+    serialized.put( pp,nv);
+    serialized.put( pp,nbe);
+    if (verbosity>2) 
+	cout << " GenericMesh Serialized : " << l << " "  << nt << " " << nv << " " << nbe << endl;
+    for (int i=0;i<nv;i++)
+      {
+	  for(int j=0;j<d;++j)
+	  serialized.put(pp,vertices[i][j]);
+	  serialized.put(pp,vertices[i].lab);
+      }
+    for (int i=0;i<nt;i++)
+      {
+	  
+	  const Element & K(elements[i]);
+	  for(int j=0;j<nve;++j)
+	      serialized.put(pp,(int) operator()(K[j]));
+	  serialized.put(pp, K.lab);
+      }
+    for (int i=0;i<nbe;i++)
+      {
+	  const BorderElement & K(borderelements[i]);
+	  for(int j=0;j<nvbe;++j)
+	      serialized.put(pp,(int) operator()(K[j]));
+	  serialized.put(pp, K.lab);
+      }
+    assert(pp==serialized.size());
+    return serialized;  
+}
+    
+/*    GenericMesh()
+    : nt(0),nv(0),nbe(0),  mes(0.),mesb(0.) ,
+    vertices(0),elements(0),borderelements(0),bnormalv(0),
+    TheAdjacencesLink(0),BoundaryElementHeadLink(0),
+    ElementConteningVertex(0), gtree(0)
+    {} 
+ */  
+    template<typename T,typename B,typename V>
+    GenericMesh<T,B,V>::GenericMesh(const  Serialize &serialized) 
+    : nt(0),nv(0),nbe(0),  mes(0.),mesb(0.) ,
+    vertices(0),elements(0),borderelements(0),bnormalv(0),
+    TheAdjacencesLink(0),BoundaryElementHeadLink(0),
+    ElementConteningVertex(0), gtree(0)
+    {
+	const int nve = T::nv;
+	const int nvbe = B::nv;
+	const int d = Rd::d;
+	int dd,nnve,nnvbe,nnt,nnv,nnbe;
+	long long  l=0;
+	size_t pp=0;	
+	serialized.get(pp, l); 
+	serialized.get( pp,dd);
+	serialized.get( pp,nnve);
+	serialized.get( pp,nnvbe);
+	serialized.get( pp,nnt);
+	serialized.get( pp,nnv);
+	serialized.get( pp,nnbe);
+	ffassert(d==dd && nve == nnve && nvbe == nnvbe);
+	set(nnv,nnt,nnbe);
+	for (int i=0;i<nv;i++)
+	  {
+	      //double r[d];
+	      for(int j=0;j<d;++j)
+		  serialized.get(pp,vertices[i][j]);
+	      serialized.get(pp,vertices[i].lab);
+	  }
+	mes=0.;
+	for (int i=0;i<nt;i++)
+	  {
+	      int ii[nve],lab;
+	      for(int j=0;j<nve;++j)
+		  serialized.get(pp,ii[j]);
+	      serialized.get(pp,lab);
+	     mes += elements[i].set(vertices,ii,lab).mesure();
+	      
+	  }
+	mesb=0;
+	for (int i=0;i<nbe;i++)
+	  {
+	      int ii[nvbe],lab;
+	      for(int j=0;j<nvbe;++j)
+		  serialized.get(pp,ii[j]);
+	      serialized.get(pp, lab);
+	      mesb += borderelements[i].set(vertices,ii,lab).mesure();
+	  }
+       assert(pp==serialized.size());	
+    }
+    
+}
+#endif
diff --git a/src/femlib/HashTable.hpp b/src/femlib/HashTable.hpp
new file mode 100644
index 0000000..2e38b55
--- /dev/null
+++ b/src/femlib/HashTable.hpp
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+template<typename T,int N>
+struct SortArray {
+};
+
+template<typename T>
+struct SortArray<T,1> {
+  T v[1];
+  SortArray(T *a)
+  { 
+    v[0]=a[0];
+  }
+  SortArray(const T& a0)
+  { 
+    v[0]=a0;
+  }
+  SortArray(){}
+  bool operator == (const SortArray<T,1> & t)  const
+  {  return v[0] == t.v[0]  ;}
+  bool operator<(const SortArray<T,1> & t)  const 
+  {  return v[0] < t.v[0]  ;}  
+  size_t hash() const {return (size_t) v[0];}
+};
+
+
+template<typename T>
+struct SortArray<T,2> {
+  //  using std::swap;
+  T v[2];
+  SortArray(T *a)
+  { 
+    v[0]=a[0];
+    v[1]=a[1];
+    if(v[0]>v[1]) swap(v[0],v[1]);
+  }
+  SortArray(const T& a0,const T &a1)
+  { 
+    v[0]=a0;
+    v[1]=a1;
+    if(v[0]>v[1]) swap(v[0],v[1]);
+  }
+  SortArray(){}
+  bool operator == (const SortArray<T,2> & t)  const
+  {  return v[0] == t.v[0] && v[1] == t.v[1] ;}
+    bool operator<(const SortArray<T,2> & t)  const 
+    {  return v[0] != t.v[0] ? v[0] < t.v[0] : v[1] < t.v[1] ;}  
+  size_t hash() const {return (size_t) v[0];}
+};
+
+
+template<typename T>
+struct SortArray<T,3> {
+  T v[3];
+  SortArray(T *a)
+  { 
+    v[0]=a[0];
+    v[1]=a[1];
+    v[2]=a[2];
+    if(v[0]>v[1]) swap(v[0],v[1]);
+    if(v[1]>v[2]) { 
+      swap(v[1],v[2]);
+      if(v[0]>v[1]) swap(v[0],v[1]);
+    ASSERTION(v[0] <= v[1] && v[1] <= v[2] );
+    }
+  }
+  
+  SortArray(){}
+  bool operator == (const SortArray<T,3> & t)  const
+  {  return v[0] == t.v[0] && v[1] == t.v[1]  && v[2] == t.v[2] ;}
+    
+  bool operator<(const SortArray<T,3> & t)  const 
+    {  return v[0] != t.v[0] ? v[0] < t.v[0] :
+           ( v[1] != t.v[1] ? v[1] < t.v[1] :  v[2] < t.v[2] );}  
+  
+  size_t hash() const {return (size_t) v[0];}
+};
+
+template<typename T,int N>
+ostream & operator<<(ostream & f,const SortArray<T,N> & item)
+{ 
+    for (int i=0;i<N;++i) f << " " << item.v[i];
+    return f;
+}
+
+template<class K,class V>
+class HashTable {
+public:
+  struct   nKV { size_t next; K k; V v;
+    nKV(){} };
+  typedef nKV *iterator;
+  size_t n,nx,nk,ncol,nfind;
+  size_t * head;
+  nKV * t;
+  static const  size_t endhash= (size_t) -1; 
+  
+  HashTable(size_t nnx,size_t nnk)
+    :    n(0),nx(nnx),nk(nnk),ncol(0),nfind(0),
+	 head(new size_t[nk]),t(new nKV[nx])
+  {  reset();}
+  
+  void reset() 
+  {
+    n=0;
+    ncol=0;
+    for (size_t j=0;j<nk;++j) 
+      head[j]=endhash;
+  }
+  
+  nKV *  find(const K & key)
+  { 
+    nfind++;
+    for (size_t k=head[key.hash() %nk];k!=endhash;k=t[k].next)
+      {
+	++ncol;
+	if(key == t[k].k) return t+k;
+      }
+    return 0;
+  } 
+    // add FH  21 avril 2009
+  size_t  operator()(nKV * p) { return p ? p-t : n;}
+    
+  iterator end(){ return t+n;}
+  iterator begin(){ return t;}
+    
+  nKV *add(const K & key,const V & v)
+  {
+    size_t k =key.hash()%nk;
+    assert(n<nx);
+    t[n].v = v;
+    t[n].k = key;
+    t[n].next=head[k];
+    head[k]=n;    
+    return t+ n++;
+  }    
+  
+  V & operator[](const K & key) 
+  {
+    nKV *p = find(key);
+    if(p) return p->v;
+    else return t[add(key,V())].v;
+  }
+  ~HashTable()
+  {
+    if(nfind && verbosity>4)
+      cout << "    ~HashTable:   Cas moyen : " << (double) ncol/ nfind << endl;
+    delete [] head;
+    delete [] t;
+  }
+
+  //  pas de copie ....
+private:
+  HashTable(const HashTable&);
+  void operator=(const HashTable&);
+};
diff --git a/src/femlib/HeapSort.hpp b/src/femlib/HeapSort.hpp
new file mode 100755
index 0000000..da0307b
--- /dev/null
+++ b/src/femlib/HeapSort.hpp
@@ -0,0 +1,56 @@
+template<class T>
+void  HeapSort(T *c,long n)
+{
+  long l,j,r,i;
+  T crit;
+  c--; // on decale de 1 pour que le tableau commence a 1
+  if( n <= 1) return;
+  l = n/2 + 1;
+  r = n;
+  while (1) { // label 2
+    if(l <= 1 ) { // label 20
+      crit = c[r];
+      c[r--] = c[1];
+    if ( r == 1 ) { c[1]=crit; return;}
+    } else  crit = c[--l]; 
+    j=l;
+    while (1) {// label 4
+      i=j;
+      j=2*j;
+      if  (j>r) {c[i]=crit;break;} // L8 -> G2
+      if ((j<r) && (c[j] < c[j+1])) j++; // L5
+      if (crit < c[j]) c[i]=c[j]; // L6+1 G4
+      else {c[i]=crit;break;} //L8 -> G2
+    }
+  }
+}
+
+template<class K,class T>
+void  HeapSort(K *k,T *t,long n)
+{
+    long l,j,r,i;
+    K kk;
+    T tt;
+    k--;t--; // on decale de 1 pour que les tableau commence a 1
+    if( n <= 1) return;
+    l = n/2 + 1;
+    r = n;
+    while (1) { // label 2
+	if(l <= 1 ) { // label 20
+	    kk = k[r];
+	    tt = t[r];
+	    t[r]=t[1];
+	    k[r--] = k[1];	    
+	    if ( r == 1 ) { k[1]=kk;t[1]=tt; return;}
+	} else  {kk = k[--l];tt=t[l]; }
+	j=l;
+	while (1) {// label 4
+	    i=j;
+	    j=2*j;
+	    if  (j>r) {k[i]=kk;t[i]=tt;break;} // L8 -> G2
+	    if ((j<r) && (k[j] < k[j+1])) j++; // L5
+	    if (kk < k[j]) {k[i]=k[j];t[i]=t[j];} // L6+1 G4
+	    else {k[i]=kk;t[i]=tt;break;} //L8 -> G2
+	}
+    }
+}
diff --git a/src/femlib/InvIntFunc.cpp b/src/femlib/InvIntFunc.cpp
new file mode 100644
index 0000000..4261964
--- /dev/null
+++ b/src/femlib/InvIntFunc.cpp
@@ -0,0 +1,59 @@
+// used by splitsimplex.cpp 
+//  to inverse numering ... 
+//   F. Hecht 
+// ORIG-DATE:     fev 2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 2d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01  */
+
+inline int InvIntFunction(int l)
+// calcul de inverse de la fonction F 
+{
+  // inverse la function F 
+  int i=0,j,k=l;
+  int Fi=F(i),Fj,Fk=F(k);
+  while (1)
+    {
+      j = (i+k)/2;
+      if(j==i) break;
+      Fj=F(j);      
+      // cout << i<< j << k << " " << (l < Fj)  << " : "; 
+      if( l < Fj ) { k=j; Fk=Fj;}
+      else if ( l > Fj  ) { i=j; Fi=Fj;}
+      else { i=j;}      
+      // cout <<  "                ** " << l << " : " << i<< " "<< j << " "<< k << " : Fi  " << Fi << " " << Fj << " "<< Fk << endl;
+      
+    }
+
+
+  if( Fk==l) i=k;
+  //  cout << "           i =" << i << " l=  " << l << " in  [  " << F(i) << ", " << F(i+1) << "[ " << endl;
+  assert( (F(i) <= l)  && (l < F(i+1)  )  ); 
+  return i; 
+}
diff --git a/src/femlib/Label.hpp b/src/femlib/Label.hpp
new file mode 100644
index 0000000..92203f3
--- /dev/null
+++ b/src/femlib/Label.hpp
@@ -0,0 +1,19 @@
+#ifndef LABEL_HPP
+#define LABEL_HPP
+ 
+class Label {  // reference number for the physics
+  friend inline ostream& operator <<(ostream& f,const Label & r  )
+    { f <<  r.lab ; return f; }
+  friend inline istream& operator >>(istream& f, Label & r  )
+    { f >>  r.lab ; return f; }
+  public: 
+  int lab;
+  Label(int r=0):lab(r){}
+  bool onGamma() const { return lab;} 
+  int operator!() const{return !lab;} 
+  bool operator<(const Label & r) const {return lab < r.lab;} 
+  bool operator==(const Label & r) const {return lab == r.lab;} 
+  bool operator>(const Label & r) const { return lab > r.lab;} 
+
+  };
+#endif
diff --git a/src/femlib/Makefile.am b/src/femlib/Makefile.am
new file mode 100644
index 0000000..fd16af1
--- /dev/null
+++ b/src/femlib/Makefile.am
@@ -0,0 +1,38 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+
+# This is not compiled as a separate library because its
+# interconnections with other libraries have not been solved.
+
+EXTRA_DIST=BamgFreeFem.cpp BamgFreeFem.hpp CGNL.hpp CheckPtr.cpp	\
+ConjuguedGradrientNL.cpp DOperator.hpp Drawing.cpp Element_P2h.cpp	\
+Element_RT.cpp fem3.hpp fem.cpp fem.hpp FESpace.cpp	\
+FESpace.hpp FESpace-v0.cpp FQuadTree.cpp FQuadTree.hpp gibbs.cpp	\
+glutdraw.cpp gmres.hpp MatriceCreuse.hpp MatriceCreuse_tpl.hpp		\
+MeshPoint.hpp mortar.cpp mshptg.cpp QuadratureFormular.cpp		\
+QuadratureFormular.hpp RefCounter.hpp RNM.hpp RNM_opc.hpp RNM_op.hpp	\
+RNM_tpl.hpp R1.hpp R2.hpp R3.hpp \
+FESpacen.cpp \
+FESpacen.hpp \
+P012_1d.cpp \
+P012_2d.cpp \
+P012_3d.cpp \
+PkLagrange.hpp \
+Mesh1dn.cpp \
+Mesh1dn.hpp \
+Mesh2dn.cpp \
+Mesh2dn.hpp \
+Mesh3dn.cpp \
+Mesh3dn.hpp \
+HashTable.hpp \
+Label.hpp \
+assertion.hpp \
+GenericMesh.hpp \
+GQuadTree.hpp \
+GQuadTree.cpp \
+HeapSort.hpp \
+libmesh5.c \
+libmesh5.h  \
+ufunction.hpp  \
+splitsimplex.cpp InvIntFunc.cpp splitsimplex.hpp
diff --git a/src/femlib/MatriceCreuse.hpp b/src/femlib/MatriceCreuse.hpp
new file mode 100644
index 0000000..1562079
--- /dev/null
+++ b/src/femlib/MatriceCreuse.hpp
@@ -0,0 +1,1039 @@
+#ifndef MatriceCreuse_h_
+#define MatriceCreuse_h_
+
+template<class T>
+ T Square(const T & r){return r*r;}
+
+ 
+#ifdef HAVE_LIBUMFPACK_XXXXXXXXXXXXX
+extern "C" {
+#ifdef HAVE_UMFPACK_H
+#include <umfpack.h>
+#else
+#ifdef HAVE_UMFPACK_UMFPACK_H
+#include <umfpack/umfpack.h>
+#else
+#ifdef HAVE_BIG_UMFPACK_UMFPACK_H
+#include <UMFPACK/umfpack.h>
+#else
+#ifdef HAVE_UFSPARSE_UMFPACK_H
+#include <ufsparse/umfpack.h>
+#else
+#ifdef HAVE_SUITESPARSE_UMFPACK_H
+#include <suitesparse/umfpack.h>
+#else
+
+  // Defaults to a local version of the UMFPACK headers
+#include "../../download/include/umfpack.h"
+
+#endif // HAVE_SUITESPARSE_UMFPACK_H
+#endif // HAVE_UFSPARSE_UMFPACK_H
+#endif // HAVE_BIG_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_H
+}
+#endif
+
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpace.hpp" 
+#include "DOperator.hpp"
+#include "QuadratureFormular.hpp" 
+
+using  Fem2D::Mesh;
+using  Fem2D::FESpace;
+using Fem2D::FElement;
+using Fem2D::baseFElement;
+using Fem2D::FMortar;
+using Fem2D::TypeOfMortar;
+using Fem2D::QuadratureFormular;
+using Fem2D::QuadratureFormular1d;
+using Fem2D::QuadratureFormular_T_5;
+using Fem2D::QF_GaussLegendre3;
+const double  EPSILON=1e-20;
+using Fem2D::onWhatIsEdge;
+
+//#define APROGRAMMER(a) {cerr << "A PROGRAMMER "  #a << endl; exit (1) ;}
+#define ERREUR(a,b) {cerr << "ERREUR " #a<< b <<endl; throw(ErrorExec("FATAL ERREUR dans " __FILE__  "\n" #a  " line: ",__LINE__)) ;}
+
+template <class R> class MatriceCreuse; 
+template <class R> class MatriceElementaire; 
+template <class R,class FESpace> class MatriceElementaireSymetrique;
+template <class R,class FESpace> class MatriceElementairePleine;
+template <class R> class MatriceMorse;
+template <class R> class MatriceProdTensoriel;
+
+//template <class R> R Square(R x){ return x*x;}
+
+template <class T> T* docpyornot(bool nocpy,T* p,int n)
+{ 
+  T * r=p;
+   if( !nocpy) { // do copy 
+      r= new T[n]; ffassert(r);
+      if(p) 
+       for(int i=0;i<n;i++) 
+        r[i]=p[i];
+      }
+    else if( r==0) // always do allocation  July 2009 for mpi matrice  
+      { r= new T[n]; ffassert(r);}
+   return r;
+ }
+ template <class T,class TT> T* docpy(TT* p,int n)
+{ 
+   T * r=0;
+   if(p && n) { // do copy 
+      r= new T[n]; ffassert(r);
+      for(int i=0;i<n;i++) 
+        r[i]=T(p[i]); // pour cadna ???? FH 
+      }
+   return r;
+ }
+
+
+
+template <class R> 
+class MatriceElementaire {
+
+public:
+  enum TypeOfMatriceElementaire {Full=1,Symmetric=2};
+
+
+       
+  int lga;  // size of array a    
+  R* a;          // array  coef --
+  int *ni,*nj;   //  list of df   
+  // to build matrice on face or edge -----
+
+  
+  int n,m;       // n,m number of df
+  const TypeOfMatriceElementaire mtype;
+  KN<double> data; // to store value of basic function 
+
+  const bool onFace ; //  true if do int on face or edge with jump (VF or GD : Galerkin Discontinus)
+  // in with case  add ... 
+  const int lnki,lnkj; // size of the 4 next array
+  int *nik,*nikk;  //  number of df in element   k,kk for VF and GD methode 
+  int *njk,*njkk;  //  number of df in element   k,kk  for VF and GD methode
+
+
+  MatriceElementaire(int datasize,int llga
+                     ,int *nnj,int * nni,TypeOfMatriceElementaire t=Full)
+    
+    :   lga(llga),a(new R[lga]),
+        ni(nni),nj(nnj),n(0),m(0),mtype(t),data(datasize),
+        onFace(false),lnki(0),lnkj(0),nik(0),nikk(0),njk(0),njkk(0)
+        {}
+       
+
+ //  for discontinous Galerkine method
+  MatriceElementaire(int datasize,int llga,int *nni,
+                     int lk,
+                     TypeOfMatriceElementaire t=Symmetric
+                     ) 
+    :
+    lga(llga),a(new R[lga]),
+    ni(nni),nj(nni),n(0),m(0),mtype(t),data(datasize*(lk?2:1)) ,
+       onFace(lk!=0),
+       lnki(lk),lnkj(lk),
+       nik(lk? new int[lk*2]:0),
+       nikk(nik+lk),
+       njk(nik),
+       njkk(nik+lk)
+       { ffassert(lk>=0);}
+
+    //  for discontinous Galerkine method
+    MatriceElementaire(int datasize,int llga,int *nni,int lki,int *nnj,int lkj,
+                       TypeOfMatriceElementaire t=Full
+                       )
+    :
+    lga(llga),a(new R[lga]),
+    ni(nni),nj(nnj),n(0),m(0),mtype(t),data(datasize*(lki+lkj?2:1)) ,
+    onFace(lki+lkj),
+    lnki(lki),lnkj(lkj),
+    nik(lki? new int[lki*2]:0),
+    nikk(nik+lki),
+    njk(lkj? new int[lkj*2]:0),
+    njkk(njk+lkj)
+    {  ffassert(lki>=0);}// non teste ??? .... F. hecht ...
+
+  virtual ~MatriceElementaire() {
+    if(ni != nj) 
+      delete [] nj;
+         
+    delete [] ni;
+    delete [] a;
+    if ( nik) delete[] nik;
+     }
+      
+  virtual R & operator() (int i,int j) =0;
+    virtual void call(int ,int ie,int label,void * data,void *Q=0) =0;  //
+  const LinearComb<pair<MGauche,MDroit>,C_F0> * bilinearform;
+  
+  MatriceElementaire & operator()(int k,int ie,int label,void * s=0,void *B=0) {
+    call(k,ie,label,s,B);
+    return *this;}
+};
+
+template <class FES> 
+class MatDataFES { 
+public:
+  typedef FES FESpace;
+  typedef typename FESpace::FElement FElement;
+
+  typedef typename  FESpace::QFElement QFElement; 
+  typedef typename  FESpace::QFBorderElement QFBorderElement; 
+  CountPointer<const FESpace> cUh,cVh;
+  const FESpace &Uh;
+  const FESpace &Vh;
+  const QFElement & FIT;
+  const QFBorderElement & FIE;
+  MatDataFES(const FESpace & UUh,const QFElement & fit, const QFBorderElement & fie)
+    :Uh(UUh),Vh(UUh),FIT(fit),FIE(fie) {}
+  MatDataFES(const FESpace & UUh,const FESpace & VVh,const QFElement & fit, const QFBorderElement & fie)
+    :Uh(UUh),Vh(VVh),FIT(fit),FIE(fie) {}
+    
+
+};
+
+template <class R,class FES> 
+class MatriceElementaireFES :   public MatDataFES<FES> ,   public MatriceElementaire<R> 
+{  
+public:
+  typedef MatriceElementaire<R> MElm ;
+  using MElm::Full;
+  using MElm::Symmetric;
+
+  typedef typename MElm::TypeOfMatriceElementaire TypeOfMatriceElementaire;
+  typedef FES FESpace;
+
+  typedef typename  FESpace::FElement FElement; 
+  typedef typename  FESpace::QFElement QFElement; 
+  typedef typename  FESpace::QFBorderElement QFBorderElement; 
+
+  MatriceElementaireFES(const FESpace & UUh,const FESpace & VVh,int llga
+			,int *nnj,int * nni,TypeOfMatriceElementaire t=Full,
+			const QFElement & fit=*QFElement::Default,
+			const QFBorderElement & fie =*QFBorderElement::Default) 
+                     
+    :
+    MatDataFES<FES>(UUh,VVh,fit,fie),
+    MatriceElementaire<R>(UUh.esize()+VVh.esize(),llga,nnj,nni,t)
+  {}
+       
+  MatriceElementaireFES(const FESpace & UUh,int llga,int *nni,
+			TypeOfMatriceElementaire t=Symmetric,
+			const QFElement & fit=*QFElement::Default,
+			const QFBorderElement & fie =*QFBorderElement::Default)
+    :
+    MatDataFES<FES>(UUh,UUh,fit,fie),
+    MatriceElementaire<R>(UUh.esize(),llga,nni,nni,t)
+  {}
+
+  //  for discontinous Galerkine method
+  MatriceElementaireFES(const FESpace & UUh,int llga,int *nni,
+			int lk,
+			TypeOfMatriceElementaire t=Symmetric,
+			const QFElement & fit=*QFElement::Default,
+			const QFBorderElement & fie =*QFBorderElement::Default) 
+    :
+    MatDataFES<FES>(UUh,UUh,fit,fie),
+    MatriceElementaire<R>(UUh.esize(),llga,nni,lk,t)
+  {}
+    
+    MatriceElementaireFES(const FESpace & UUh,const FESpace & VVh,int llga
+                          ,int *nnj,int lkj,int * nni,int lki,TypeOfMatriceElementaire t=Full,
+                          const QFElement & fit=*QFElement::Default,
+                          const QFBorderElement & fie =*QFBorderElement::Default)
+    
+    :
+    MatDataFES<FES>(UUh,VVh,fit,fie),
+    MatriceElementaire<R>(UUh.esize()+VVh.esize(),llga,nnj,lkj,nni,lki,t)
+    {}
+    
+  ~MatriceElementaireFES() {}
+  const LinearComb<pair<MGauche,MDroit>,C_F0> * bilinearform;
+  
+  MatriceElementaireFES & operator()(int k,int ie,int label,void * s=0,void *Q=0) {
+    this->call(k,ie,label,s,Q);
+    return *this;}
+};
+
+template <class R,class FES=FESpace> 
+class MatriceElementairePleine:public MatriceElementaireFES<R,FES> {
+
+  /* --- stockage --
+     //  n = 4 m = 5
+     //  0  1  2  3  4
+     //  5  6  7  8  9
+     // 10 11 12 13 14
+     // 15 16 17 18 19
+     ------------------*/
+public:
+  typedef FES FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::QFElement QFElement;
+  typedef typename  FESpace::QFBorderElement QFBorderElement;
+  typedef typename  FESpace::FElement FElement;
+  typedef typename  FESpace::Mesh::Rd Rd;
+    
+
+  R & operator() (int i,int j) {return this->a[i*this->m+j];}
+  // MatPleineElementFunc element;
+  void  (* element)(MatriceElementairePleine &,const FElement &,const FElement &, double*,int ie,int label,void *,Rd *) ;
+  void  (* faceelement)(MatriceElementairePleine &,const FElement &,const FElement &,const FElement &,const FElement &, double*,int ie,int iee, int label,void *,Rd *) ;
+    void call(int k,int ie,int label,void *,void *B);
+  
+  MatriceElementairePleine & operator()(int k,int ie,int label,void * stack=0,Rd *Q=0)
+  {call(k,ie,label,stack,Q);return *this;}
+  MatriceElementairePleine(const FESpace & VVh,
+                           const QFElement & fit=*QFElement::Default,
+                           const QFBorderElement & fie =*QFBorderElement::Default)  
+    :MatriceElementaireFES<R,FES>(VVh,
+			Square(VVh.MaximalNbOfDF()),
+			new int[VVh.MaximalNbOfDF()],this->Full,fit,fie),
+    element(0),faceelement(0) {}
+ 
+   //  matrice for VF or Galerkin Discontinus
+   MatriceElementairePleine(const FESpace & VVh,bool VF,
+                           const QFElement & fit=*QFElement::Default,
+                           const QFBorderElement & fie =*QFBorderElement::Default)  
+     :MatriceElementaireFES<R,FES>(VVh,
+			Square(VVh.MaximalNbOfDF()*2),
+			new int[VVh.MaximalNbOfDF()*2],
+			VF?VVh.MaximalNbOfDF()*2:0,
+			this->Full,fit,fie),			
+    element(0),faceelement(0) {}
+
+  MatriceElementairePleine(const FESpace & UUh,const FESpace & VVh,
+                               const QFElement & fit=*QFElement::Default,
+                               const QFBorderElement & fie =*QFBorderElement::Default) 
+    :MatriceElementaireFES<R,FES>(UUh,VVh,
+				  UUh.MaximalNbOfDF()*VVh.MaximalNbOfDF(),
+				  new int[UUh.MaximalNbOfDF()],
+				  new int[VVh.MaximalNbOfDF()],this->Full,fit,fie),
+     element(0),faceelement(0) {}
+
+    MatriceElementairePleine(const FESpace & UUh,const FESpace & VVh,bool VF,
+                             const QFElement & fit=*QFElement::Default,
+                             const QFBorderElement & fie =*QFBorderElement::Default)
+    :MatriceElementaireFES<R,FES>(UUh,VVh,
+                                  UUh.MaximalNbOfDF()*VVh.MaximalNbOfDF()*4,
+                                  new int[UUh.MaximalNbOfDF()*2],VF?UUh.MaximalNbOfDF()*2:0,
+                                  new int[VVh.MaximalNbOfDF()*2],VF?VVh.MaximalNbOfDF()*2:0,this->Full,fit,fie),
+    element(0),faceelement(0) {}
+
+}; 
+
+template <class R,class FES=FESpace> 
+class MatriceElementaireSymetrique:public MatriceElementaireFES<R,FES> {
+
+
+
+  // --- stockage --
+  //   0
+  //   1 2
+  //   3 4 5
+  //   6 7 8 9
+  //  10 . . . .
+  //
+
+public:
+  typedef FES FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::QFElement QFElement;
+  typedef typename  FESpace::QFBorderElement QFBorderElement;
+  typedef typename  FESpace::FElement FElement; 
+  typedef typename  FESpace::Mesh::Rd Rd;
+  R & operator()(int i,int j) 
+  {return j < i ? this->a[(i*(i+1))/2 + j] : this->a[(j*(j+1))/2 + i] ;}
+  void (* element)(MatriceElementaireSymetrique &,const FElement &, double*,int ie,int label,void *,Rd *) ;
+  void (* mortar)(MatriceElementaireSymetrique &,const FMortar &,void *) ;
+  void call(int k,int ie,int label,void * stack,void *B);
+  MatriceElementaireSymetrique(const FESpace & VVh,
+                               const QFElement & fit=*QFElement::Default,
+                               const QFBorderElement & fie =*QFBorderElement::Default) 
+    :MatriceElementaireFES<R,FES>(
+           VVh,
+	   int(VVh.MaximalNbOfDF()*(VVh.MaximalNbOfDF()+1)/2),
+	   new int[VVh.MaximalNbOfDF()],this->Symmetric,
+       fit,fie),
+       element(0),mortar(0) {}
+  MatriceElementaireSymetrique & operator()(int k,int ie,int label,void * stack=0,Rd *B=0)
+  {this->call(k,ie,label,stack,B);return *this;};
+};
+
+
+template <class R>  class MatriceProfile;
+
+//  classe modele pour matrice creuse
+//  ---------------------------------
+template <class R> 
+class MatriceCreuse : public RefCounter,public VirtualMatrice<R> {
+public:
+  MatriceCreuse(int NbOfDF,int mm,int ddummy)
+         : VirtualMatrice<R>(NbOfDF,mm),n(NbOfDF),m(mm),dummy(ddummy){}
+  MatriceCreuse(int NbOfDF)
+         : VirtualMatrice<R>(NbOfDF),n(NbOfDF),m(NbOfDF),dummy(1){}
+  int n,m,dummy;
+  virtual int size() const =0;
+
+  virtual MatriceCreuse & operator +=(MatriceElementaire<R> & )=0;
+  virtual void operator=(const R & v) =0; // Mise a zero 
+  KN_<R> & MatMul(KN_<R> &ax,const KN_<R> &x) const { 
+    ax= R();
+    addMatMul(x,ax);
+    return ax;}
+  virtual ostream& dump (ostream&)  const =0;
+  virtual void Solve(KN_<R> & x,const KN_<R> & b) const =0;
+  virtual ~MatriceCreuse(){}
+  virtual R & diag(int i)=0;
+  virtual void SetBC(int i,double tgv)=0; 
+  virtual R & operator()(int i,int j)=0;
+  virtual R * pij(int i,int j) const =0; // Add FH 
+  virtual  void  resize(int n,int m)  {AFAIRE("MatriceCreuse::resize");}  // a faire dans les classe derive ... // add march 2009  FH 
+  virtual MatriceMorse<R> *toMatriceMorse(bool transpose=false,bool copy=false) const {return 0;} // not 
+  virtual bool addMatTo(R coef,std::map< pair<int,int>, R> &mij,bool trans=false,int ii00=0,int jj00=0,bool cnj=false,double threshold=0.)=0;
+  // Add FH april 2005
+  virtual R pscal(const KN_<R> & x,const KN_<R> & y) =0 ; // produit scalaire  
+  virtual double psor(KN_<R> & x,const  KN_<R> & gmin,const  KN_<R> & gmax , double omega) =0;
+  virtual void setdiag(const KN_<R> & x)=0 ;
+  virtual void getdiag( KN_<R> & x) const =0 ;
+  // end add
+  virtual int NbCoef() const {return 0;};
+  virtual void setcoef(const KN_<R> & x)=0 ;
+  virtual void getcoef( KN_<R> & x) const =0 ;
+  // Add FH oct 2005
+   bool ChecknbLine(int nn) const { return n==nn;}  
+   bool ChecknbColumn(int mm) const { return m==mm;} 
+
+  // end ADD
+
+};
+
+template <class R> 
+inline ostream& operator <<(ostream& f,const MatriceCreuse<R> & m) 
+    {return m.dump(f);}
+
+template <class R> 
+KN_<R> & operator/=(KN_<R> & x ,const MatriceProfile<R> & a) ;
+
+
+enum FactorizationType {
+    FactorizationNO=0,
+    FactorizationCholeski=1,
+    FactorizationCrout=2,
+    FactorizationLU=3};
+
+template <class R> 
+class MatriceProfile:public MatriceCreuse<R> {
+public:
+  mutable R *L;  // lower 
+  mutable R *U;  // upper
+  mutable R *D;  // diagonal 
+  int *pL; // profile L 
+  int *pU; // profile U 
+  mutable  FactorizationType typefac;
+  FactorizationType typesolver; 
+  ostream& dump (ostream&) const ;
+  MatriceProfile(const int  n,const R *a);
+  
+  template<class FESpace>
+  MatriceProfile(const FESpace &,bool VF=false);
+  MatriceProfile(int NbOfDF,R* d,
+		 R* u, int * pu,
+		 R* l, int * pl,
+		 FactorizationType tf=FactorizationNO) 
+    : MatriceCreuse<R>(NbOfDF),L(l),U(u),D(d),pL(pl),pU(pu),
+      typefac(tf),typesolver(FactorizationNO){}
+
+  const MatriceProfile t() const   
+     {return MatriceProfile(this->n,D,L,pL,U,pU,typefac);}
+  const MatriceProfile lt() const  
+ 
+  
+     {return MatriceProfile(this->n,0,L,pL,0,0);}
+  const MatriceProfile l() const  
+     {return MatriceProfile(this->n,0,0,0,L,pL);}
+  const MatriceProfile d() const   
+     {return MatriceProfile(this->n,D,0,0,0,0);}
+  const MatriceProfile ld() const  
+     {return MatriceProfile(this->n,D,0,0,L,pL);}
+  const MatriceProfile ldt() const 
+     {return MatriceProfile(this->n,D,L,pL,0,0);}
+  const MatriceProfile du() const  
+     {return MatriceProfile(this->n,D,U,pU,0,0);}
+  const MatriceProfile u() const   
+     {return MatriceProfile(this->n,0,U,pU,0,0);}
+  const MatriceProfile ut() const  
+    
+    
+    {return MatriceProfile(this->n,0,0,0,U,pU);}
+
+  void Solve(KN_<R> &x,const KN_<R> &b) const {
+    /*if (typefac==0)  code faux // FH   nov 2006
+      switch(typefac) 
+	{
+	FactorizationCholeski: cholesky() ; break;
+	FactorizationCrout:   crout(); break;
+	FactorizationLU:      LU(); break; 
+	}*/ 
+    if (&x != &b) x=b;x/=*this;} 
+  
+  int size() const ;
+  void  resize(int n,int m)  { AFAIRE("MatriceProfile::resize");}  // a faire ...  add march 2009  FH 
+  ~MatriceProfile();
+  //  KN_<R>         operator* (const KN_<R> & ) const ;
+  void addMatMul(const KN_<R> &x,KN_<R> &ax) const;
+  void addMatTransMul(const KN_<R> &x,KN_<R> &ax) const 
+    { this->t().addMatMul(x,ax);}
+  MatriceCreuse<R> & operator +=(MatriceElementaire<R> &);
+  void operator=(const R & v); // Mise a zero 
+  void cholesky(double = EPSILON/8.) const ; //
+  void crout(double = EPSILON/8.) const ; //
+  void LU(double = EPSILON/8.) const ; //
+  R & diag(int i) { return D[i];}
+  void SetBC (int i,double tgv) {
+      if( tgv>=0) D[i]=tgv;
+      else  { ffassert(tgv<0); }  // to hard ..
+  }
+  R & operator()(int i,int j) { if(i!=j) ffassert(0); return D[i];} // a faire 
+  R * pij(int i,int j) const { if(i!=j) ffassert(0); return &D[i];} // a faire  Modif FH 31102005
+  MatriceMorse<R> *toMatriceMorse(bool transpose=false,bool copy=false) const ;
+  
+  template<class F> void map(const  F & f)
+  {
+    for(int i=0;i<this->n;++i)
+      D[i]=f(D[i]);
+    if (L)
+    for(int i=0;i<pL[this->n];++i)
+      L[i]=f(L[i]);
+    if (L && (L != U) )
+    for(int i=0;i<pL[this->m];++i)
+      U[i]=f(U[i]);
+  }
+  
+  template<class RR> MatriceProfile(const MatriceProfile<RR> & A)
+    : MatriceCreuse<R>(A.n,A.m,0)
+  {
+    
+    typefac=A.typefac;
+    pL=  docpy<int,int>(A.pL,this->n+1);
+    D = docpy<R,RR>(A.D,this->n);
+    if ( A.pL == A.pU ) pU=pL;
+    else pU=  docpy<int,int>(A.pU,this->m+1);
+    
+      L= docpy<R,RR>(A.L,pL[this->n]);
+      
+    if ( A.L == A.U ) U=L;
+    else  U= docpy<R,RR>(A.U,pU[this->m]);
+    
+  
+  }
+
+  
+  bool addMatTo(R coef,std::map< pair<int,int>, R> &mij,bool trans=false,int ii00=0,int jj00=0,bool cnj=false,double threshold=0.);
+
+  // Add FH april 2005
+  R pscal(const KN_<R> & x,const KN_<R> & y); // produit scalaire  
+  double psor(KN_<R> & x,const  KN_<R> & gmin,const  KN_<R> & gmax , double omega);
+  void setdiag(const KN_<R> & x) ;
+  void getdiag( KN_<R> & x) const ;
+    // end add
+  // Add FH oct 2005
+   int NbCoef() const ;
+   void setcoef(const KN_<R> & x);
+   void getcoef( KN_<R> & x) const ;
+  // end add
+  
+  /*----------------------------------------------------------------
+    D[i] = A[ii]
+    L[k] = A[ij]  j < i avec:   pL[i]<= k < pL[i+1] et j = pL[i+1]-k
+    U[k] = A[ij]  i < j avec:   pU[j]<= k < pU[j+1] et i = pU[i+1]-k 
+    remarque pL = pU generalement 
+    si L = U => la matrice est symetrique 
+    -------------------------------------------------------------------
+  */ 
+  private:
+   void operator=(const MatriceProfile & A);
+};
+
+
+                                          
+template <class R> 
+class MatriceMorse:public MatriceCreuse<R> {
+//  numebering  is no-symmetric
+//  the all line  i :  
+//     k=   lg[i] .. lg[i+1]+1
+//        j = cl[k]
+//        aij=a[k]
+// otherwise  symmetric  case
+// same but just the  LOWER part is store     (j <= i) 
+// and aii exist always in symmetric case
+//  -----------------------------------------
+
+public:
+  int nbcoef;
+  bool symetrique;  
+  R * a;
+  int * lg; 
+ 
+  int * cl;  
+public:
+
+    
+ class VirtualSolver :public RefCounter { 
+   friend class MatriceMorse;
+   virtual void Solver(const MatriceMorse<R> &a,KN_<R> &x,const KN_<R> &b) const  =0;
+};
+
+  MatriceMorse():MatriceCreuse<R>(0),nbcoef(0),symetrique(true),a(0),lg(0),cl(0),solver(0) {};
+  MatriceMorse(KNM_<R> & A, double tol) ;
+  MatriceMorse(const int  n,const R *a);
+//    :MatriceCreuse<R>(n),solver(0) {}
+  MatriceMorse(istream & f);
+
+  template<class FESpace>   explicit 
+  MatriceMorse(const FESpace & Uh,bool sym,bool VF=false)
+    :MatriceCreuse<R>(Uh.NbOfDF),solver(0) {Build(Uh,Uh,sym,VF);}
+
+  template<class FESpace>   explicit 
+  MatriceMorse(const FESpace & Uh,const FESpace & Vh,bool VF=false)
+    :MatriceCreuse<R>(Uh.NbOfDF,Vh.NbOfDF,0),solver(0) 
+  {Build(Uh,Vh,false,VF);}
+
+  template<class FESpace>   explicit 
+  MatriceMorse(const FESpace & Uh,const FESpace & Vh,
+               void (*build)(MatriceMorse *,const FESpace & Uh,const FESpace & Vh,void *data),void *data=0
+	       )
+    :MatriceCreuse<R>(Uh.NbOfDF,Vh.NbOfDF,0),solver(0) 
+  {build(this,Uh,Vh,data);           
+  }
+ 
+MatriceMorse(int nn,int mm,int nbc,bool sym,R *aa=0,int *ll=0,int *cc=0,bool dd=false, const VirtualSolver * s=0,bool transpose=false )
+    :MatriceCreuse<R>(nn,mm,dd && !transpose),
+     nbcoef(nbc),
+     symetrique(sym), // transpose = true => dummy false (new matrix)
+     a(docpyornot(this->dummy,aa,nbc)),
+     lg(docpyornot(this->dummy,ll,nn+1)),
+     cl(docpyornot(this->dummy,cc,nbc)),
+     solver(s)
+  { if(transpose) dotransposition(); };
+  void Solve(KN_<R> &x,const KN_<R> &b) const;
+  int size() const ;
+  void addMatMul(const KN_<R> &x,KN_<R> &ax) const;
+  void addMatTransMul(const KN_<R> &x,KN_<R> &ax) const;
+  MatriceMorse & operator +=(MatriceElementaire<R> &);
+  void operator=(const R & v) 
+    { for (int i=0;i< nbcoef;i++) a[i]=v;}
+  virtual ~MatriceMorse(){ if (!this->dummy) { delete [] a; delete [] cl;delete [] lg;}}
+  ostream&  dump(ostream & f) const ;
+  R * pij(int i,int j) const ;
+  R  operator()(int i,int j) const {R * p= pij(i,j) ;throwassert(p); return *p;}
+  R & operator()(int i,int j)  {R * p= pij(i,j) ;throwassert(p); return *p;}
+  R & diag(int i)  {R * p= pij(i,i) ;throwassert(p); return *p;}
+  void SetBC (int i,double tgv) {
+	R * p= pij(i,i) ;
+	ffassert(p);
+	if( tgv>=0) *p=tgv;
+	else  {
+	    ffassert(!symetrique); 
+	    for (int k=lg[i];k<lg[i+1]; ++k) a[k]=0;// put the line to Zero.
+	    *p = 1. ; // and the diag coef to 1.
+	}  
+    }
+    
+  void SetSolver(const VirtualSolver & s){solver=&s;}
+  void SetSolverMaster(const VirtualSolver * s){solver.master(s);}
+  bool sym() const {return symetrique;}
+  // Add FH april 2005
+  R pscal(const KN_<R> & x,const KN_<R> & y); // produit scalaire  
+  double psor(KN_<R> & x,const  KN_<R> & gmin,const  KN_<R> & gmax , double omega);
+  void setdiag(const KN_<R> & x) ;
+  void getdiag( KN_<R> & x) const ;
+  // end add
+  
+  // Add FH oct 2005
+   int NbCoef() const ;
+   void setcoef(const KN_<R> & x);
+   void getcoef( KN_<R> & x) const ;
+  // end add
+void  resize(int n,int m) ; // add march 2009 ...
+template<class K>
+  MatriceMorse(int nn,int mm, std::map< pair<int,int>, K> & m, bool sym);
+  
+ template<class RB,class RAB>
+ void  prod(const MatriceMorse<RB> & B, MatriceMorse<RAB> & AB);
+ 
+ MatriceMorse<R> *toMatriceMorse(bool transpose=false,bool copy=false) const {
+     return new MatriceMorse(this->n,this->m,nbcoef,symetrique,a,lg,cl,copy, solver,transpose);}
+  bool  addMatTo(R coef,std::map< pair<int,int>, R> &mij,bool trans=false,int ii00=0,int jj00=0,bool cnj=false,double threshold=0.);
+  
+  template<typename RR,typename K> static  RR CastTo(K  b){return b;}
+                                                  
+  template<class K>
+    MatriceMorse(const MatriceMorse<K> & , R (*f)(K) );
+  template<class K>
+    MatriceMorse(const MatriceMorse<K> & );
+
+  private:
+  void dotransposition ()  ;  // do the transposition 
+  CountPointer<const VirtualSolver> solver;
+  
+  void operator=(const MatriceMorse & );
+
+  template<class FESpace>
+  void  Build(const FESpace & Uh,const FESpace & Vh,bool sym,bool VF=false);
+  
+};
+
+
+template<class R> class StopGC { public: virtual  bool Stop(int iter, R *, R * ){cout << " Stop !!!!!\n"; return false;} };
+template<class R,class M,class P,class S >// S=StopGC<Real>
+int ConjuguedGradient(const M & A,const P & C,const KN_<R> &b,KN_<R> &x,const int nbitermax, double &eps,long kprint=1000000000,S *Stop=0)
+{
+   
+//  ConjuguedGradient lineare   A*x est appele avec des conditions au limites 
+//  non-homogene puis homogene  pour calculer le gradient  
+   if (verbosity>50) 
+     kprint=2;
+   if (verbosity>99)  cout << A << endl;
+   throwassert(&x && &b && &A && &C);
+   typedef KN<R> Rn;
+   int n=b.N();   
+   throwassert(n==x.N());
+   Rn g(n), h(n), Ah(n), & Cg(Ah);  // on utilise Ah pour stocke Cg  
+   g = A*x;  
+   double xx= RNM::real((x,conj(x)));
+   double epsold=eps;
+   g -= b;// g = Ax-b
+   Cg = C*g; // gradient preconditionne 
+   h =-Cg; 
+   double g2 = RNM::real((Cg,conj(g)));
+   if (g2 < 1e-30) 
+    { if(verbosity>1 || (kprint<100000))
+       cout << "GC  g^2 =" << g2 << " < 1.e-30  Nothing to do " << endl;
+     return 2;  }
+   double reps2 =eps >0 ?  eps*eps*g2 : -eps; // epsilon relatif 
+   eps = reps2;
+   for (int iter=0;iter<=nbitermax;iter++)
+     {      
+       Ah = A*h;
+       double hAh =RNM::real((h,conj(Ah)));
+      // if (Abs(hAh)<1e-30) ExecError("CG2: Matrix non defined, sorry ");
+       R ro =  - RNM::real((g,conj(h)))/ hAh; // ro optimal (produit scalaire usuel)
+       x += ro *h;
+       g += ro *Ah; // plus besoin de Ah, on utilise avec Cg optimisation
+       Cg = C*g;
+       double g2p=g2; 
+       g2 = RNM::real((Cg,conj(g)));
+       bool stop = Stop && Stop->Stop(iter,x,g);
+    
+       if ( !(iter%kprint) && iter && (verbosity>3) )
+         cout << "CG:" <<iter <<  "  ro = " << ro << " ||g||^2 = " << g2 << " " << stop << endl;
+         
+       if (g2 < reps2 || stop) {
+         if ( !iter && !xx && g2 && epsold >0 ) {  
+             // change fo eps converge to fast due to the 
+             // penalization of boundary condition.
+             eps =  epsold*epsold*g2; 
+             if (verbosity>3 || (kprint<3))
+             cout << "CG converge to fast (pb of BC)  restart: " << iter <<  "  ro = " 
+                  << ro << " ||g||^2 = " << g2 << " <= " << reps2 << "  new eps2 =" <<  eps <<endl; 
+              reps2=eps;
+           } 
+         else 
+          { 
+           if (verbosity>1 || (kprint<100000) )
+            cout << "CG converge: " << iter <<  "  ro = " << ro << " ||g||^2 = " << g2 << endl; 
+           return 1;// ok 
+          }
+          }
+       double gamma = g2/g2p;       
+       h *= gamma;
+       h -= Cg;  //  h = -Cg * gamma* h       
+     }
+   if(verbosity)
+   cout << " GC: method doesn't converge in " << nbitermax 
+        <<  " iteration , xx= "  << xx<< endl;
+   return 0; 
+}
+
+template<class R,class M,class P,class S>// S=StopGC<Real>
+int ConjuguedGradient2(const M & A,const P & C,KN_<R> &x,const KN_<R> &b,const int nbitermax, double &eps,long kprint=1000000000,S *Stop=0)
+{
+//  ConjuguedGradient2 affine A*x = 0 est toujours appele avec les condition aux limites 
+//  -------------
+    
+   throwassert(&x  && &A && &C);
+   typedef KN<R> Rn;
+   int n=x.N();
+  // if (verbosity>99) kprint=1;
+   R ro=1;
+   Rn g(n),h(n),Ah(n), & Cg(Ah);  // on utilise Ah pour stocke Cg  
+   g = A*x;
+   g -= b;  
+   Cg = C*g; // gradient preconditionne 
+   h =-Cg; 
+   R g2 = (Cg,g);
+   if (g2 < 1e-30) 
+    { if(verbosity>1 || kprint< 1000000)
+       cout << "GC  g^2 =" << g2 << " < 1.e-30  Nothing to do " << endl;
+     return 2;  }
+   if (verbosity>5 || (kprint<2))
+     cout << " 0 GC  g^2 =" << g2 << endl;
+   R reps2 =eps >0 ?  eps*eps*g2 : -eps; // epsilon relatif 
+   eps = reps2;
+   for (int iter=0;iter<=nbitermax;iter++)
+     { 
+       R rop = ro; 
+       x += rop*h;      //   x+ rop*h  , g=Ax   (x old)
+       //       ((Ah = A*x - b) - g);
+       // Ah -= b;        //   Ax + rop*Ah = rop*Ah + g  =
+       // Ah -= g;         //   Ah*rop  
+       Ah = A*x;
+       Ah -= b;        //   Ax + rop*Ah = rop*Ah + g  =
+       Ah -= g;         //   Ah*rop  
+       R hAh =(h,Ah);
+         if (RNM::norm2(hAh)<1e-60) ExecError("CG2: Matrix is not defined (/0), sorry ");
+       ro =  - (g,h)*rop/hAh ; // ro optimal (produit scalaire usuel)
+       x += (ro-rop) *h;
+       g += (ro/rop) *Ah; // plus besoin de Ah, on utilise avec Cg optimisation
+       Cg = C*g;
+       R g2p=g2; 
+       g2 = (Cg,g);
+         bool stop = Stop && Stop->Stop(iter,x,g);
+       if ( ( (iter%kprint) == kprint-1)  /*&&  verbosity >1*/ )
+         cout << "CG:" <<iter <<  "  ro = " << ro << " ||g||^2 = " << g2 << " " << stop <<  endl;
+       if (stop || g2 < reps2 ) {
+         if (kprint <= nbitermax )
+            cout << "CG converges " << iter <<  "  ro = " << ro << " ||g||^2 = " << g2
+                 << " stop=" << stop << " /Stop= " << Stop <<  endl;
+          return 1;// ok 
+          }
+       R gamma = g2/g2p;       
+       h *= gamma;
+       h -= Cg;  //  h = -Cg * gamma* h       
+     }
+     //if (nbitermax <= nbitermax )
+      cout << "CG does'nt converge: " << nbitermax <<   " ||g||^2 = " << g2 << " reps2= " << reps2 << endl; 
+   return 0; 
+}
+
+template <class R> 
+class MatriceIdentite:public  VirtualMatrice<R> { public:
+ typedef typename VirtualMatrice<R>::plusAx plusAx;
+    MatriceIdentite(int n) :VirtualMatrice<R>(n) {}; 
+ void addMatMul(const  KN_<R>  & x, KN_<R> & Ax) const { 
+     ffassert(x.N()==Ax.N());
+   Ax+=x; } 
+ plusAx operator*(const KN<R> &  x) const {return plusAx(this,x);} 
+  bool ChecknbLine(int n) const { return true;}  
+  bool ChecknbColumn(int m) const { return true;} 
+
+};  
+
+template<class R>
+class SolveGCDiag :   public MatriceMorse<R>::VirtualSolver , public VirtualMatrice<R>{
+  int n;
+  int nbitermax;
+  double eps;
+  mutable double  epsr;
+  KN<R> D1;
+  public:
+  typedef typename VirtualMatrice<R>::plusAx plusAx;
+  SolveGCDiag(const MatriceMorse<R> &A,int itmax,double epsilon=1e-6) : 
+    VirtualMatrice<R>(A.n),
+    n(A.n),nbitermax(itmax?itmax: Max(100,n)),eps(epsilon),epsr(0),D1(n)
+  { //throwassert(A.sym());
+    for (int i=0;i<n;i++)
+      D1[i] = 1./A(i,i);}
+   void Solver(const MatriceMorse<R> &a,KN_<R> &x,const KN_<R> &b) const  {
+     epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+     ConjuguedGradient<R,MatriceMorse<R>,SolveGCDiag<R>,StopGC<R> >(a,*this,b,x,nbitermax,epsr  );
+   }
+plusAx operator*(const KN_<R> &  x) const {return plusAx(this,x);} 
+
+
+ void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  ffassert(x.N()==Ax.N());
+     for (int i=0;i<n;i++) 
+     Ax[i]+= D1[i]*x[i];}
+     
+   bool ChecknbLine(int nn) const { return n==nn;}  
+   bool ChecknbColumn(int mm) const { return n==mm;} 
+
+};
+
+struct TypeSolveMat {
+    enum TSolveMat { NONESQUARE=0, LU=1, CROUT=2, CHOLESKY=3, GC = 4 , GMRES = 5, SparseSolver=6, SparseSolverSym=7 };
+    TSolveMat t;
+    bool sym;
+    bool profile;
+    TypeSolveMat(TSolveMat tt=LU) :t(tt),
+    sym(t == CROUT || t ==CHOLESKY  ||  t==GC || t==SparseSolverSym ),
+    profile(t == CROUT || t ==CHOLESKY  || t ==LU ) {}
+    bool operator==(const TypeSolveMat & a) const { return t == a.t;}                               
+    bool operator!=(const TypeSolveMat & a) const { return t != a.t;}
+    static TSolveMat defaultvalue;
+};
+
+// add FH , JM  avril 2009 
+template<class K,class V> class MyMap;
+class String; 
+typedef void *    pcommworld; // to get the pointeur to the comm word ... in mpi
+//  to build 
+#define VDATASPARSESOLVER  1
+int Data_Sparse_Solver_version() ; //{ return VDATASPARSESOLVER;}
+struct Data_Sparse_Solver {
+  bool initmat;
+  TypeSolveMat* typemat;
+  double epsilon;
+  const void * precon;
+  int NbSpace;
+  int strategy;
+  double tgv;
+  bool factorize;
+  double tol_pivot;
+  double tol_pivot_sym;
+  int itmax ;
+  string data_filename;  
+  KN<long> lparams;  //  copy arry more secure ...
+  KN<double> dparams;   
+  
+  MyMap<String,String> * smap;   
+  
+  KN<long> perm_r; 
+  KN<long> perm_c;     
+  KN<double> scale_r; 
+  KN<double> scale_c; 
+  string sparams;  
+  pcommworld commworld;  // pointeur sur le commworld
+    int master; //  master rank in comm add FH 02/2013 for MUMPS ... => VDATASPARSESOLVER exist 
+ /*   
+  int *param_int;
+  double *param_double;
+  string *param_char;
+  int *perm_r;
+  int *perm_c;
+  string *file_param_int;
+  string *file_param_double;
+  string *file_param_char;
+  string *file_param_perm_r;
+  string *file_param_perm_c;
+  */
+    
+    Data_Sparse_Solver()
+	:
+    initmat(1),
+    typemat(0),
+    strategy(0),
+    tgv(1e30),
+    factorize(0),
+    epsilon(1e-6),
+    precon(0),
+    tol_pivot(-1),
+    tol_pivot_sym(-1),
+    NbSpace(50),
+    itmax(0),
+ //   lparams(0,0),
+ //   dparams(0,0),
+    smap(0) ,
+//    perm_r(0,0),
+//    perm_c(0,0),
+//    scale_r(0,0),
+ //   scale_c(0,0)
+    
+    /*
+    param_int(0),
+    param_double(0),
+    param_char(0),
+    perm_r(0),
+    perm_c(0),
+    file_param_int(0),
+    file_param_double(0),
+    file_param_perm_r(0),
+    file_param_perm_c(0),
+     */
+    //sparams, 
+    commworld(0),
+    master(0)
+    {}
+    
+private:
+    Data_Sparse_Solver(const Data_Sparse_Solver& ); // pas de copie 
+};
+
+// add Sep 2007 for generic Space solver
+#define DCL_ARG_SPARSE_SOLVER(T,A)  Stack stack,const MatriceMorse<T> *A, Data_Sparse_Solver & ds
+#define ARG_SPARSE_SOLVER(A) stack,A, ds					
+
+typedef MatriceMorse<double>::VirtualSolver *
+(*SparseRMatSolve)(DCL_ARG_SPARSE_SOLVER(double,A) );
+
+
+typedef MatriceMorse<Complex>::VirtualSolver *
+(*SparseCMatSolve)(DCL_ARG_SPARSE_SOLVER(Complex,A) );
+
+
+template<class R> struct DefSparseSolver {
+  typedef typename MatriceMorse<R>::VirtualSolver * 
+  (*SparseMatSolver)(DCL_ARG_SPARSE_SOLVER(R,A) );
+
+  static SparseMatSolver solver;
+    
+  static  typename MatriceMorse<R>::VirtualSolver * 
+
+  Build( DCL_ARG_SPARSE_SOLVER(R,A) )
+    
+  {
+    typename MatriceMorse<R>::VirtualSolver *ret=0;
+    if(solver)
+      ret =(solver)(ARG_SPARSE_SOLVER(A));
+    return ret;	
+  }
+};
+
+// add Dec 2012 F.H. for optimisation .. 
+template<class R> struct DefSparseSolverSym {
+    typedef typename MatriceMorse<R>::VirtualSolver *
+    (*SparseMatSolver)(DCL_ARG_SPARSE_SOLVER(R,A) );
+    
+    static SparseMatSolver solver;
+    
+    static  typename MatriceMorse<R>::VirtualSolver *
+    
+    Build( DCL_ARG_SPARSE_SOLVER(R,A) )
+    
+    {
+        typename MatriceMorse<R>::VirtualSolver *ret=0;
+        if(solver)
+            ret =(solver)(ARG_SPARSE_SOLVER(A));
+        return ret;	
+    }
+};
+
+// End Sep 2007 for generic Space solver
+
+
+
+inline void C2RR(int n,Complex *c,double *cr,double *ci)
+{
+ for (int i=0;i<n;i++)
+  {
+   cr[i]=real(c[i]);
+   ci[i]=imag(c[i]);
+  }
+}
+
+inline void RR2C(int n,double *cr,double *ci,Complex *c)
+{
+ for (int i=0;i<n;i++)
+  {
+    c[i]=Complex(cr[i],ci[i]);   
+  }
+}
+
+
+
+#endif
diff --git a/src/femlib/MatriceCreuse_tpl.hpp b/src/femlib/MatriceCreuse_tpl.hpp
new file mode 100644
index 0000000..31eecbf
--- /dev/null
+++ b/src/femlib/MatriceCreuse_tpl.hpp
@@ -0,0 +1,1947 @@
+#ifndef  MatriceCreuse_tpl_
+#ifndef  MatriceCreuse_h_
+#include "MatriceCreuse.hpp"
+#include <limits>
+#include <set>
+#include <list>
+#include <map>
+#endif
+
+#ifndef __MWERKS__
+// test blas 
+//  on MacOS9 under MWERKS
+//  cblas_ddot macos-9 is not 
+#ifdef HAVE_CBLAS_H
+extern "C" {
+#define FF_VERSION VERSION
+#undef VERSION
+#include <cblas.h>
+#undef VERSION   
+#define VERSION VERSION    
+}
+#define WITHBLAS 1
+#elif HAVE_VECLIB_CBLAS_H
+#include <vecLib/cblas.h> 
+#define WITHBLAS 1
+#endif  
+#endif  
+#ifdef WITHBLAS 
+template<class R> inline R blas_sdot(const int n,const R *sx,const int incx,const R *sy,const int  incy)
+{
+  R s=R();
+  
+  if(incx == 1 && incy == 1)
+   for (int k = 0; k< n; k++)
+    s += *sx++ * * sy++;
+  else
+   for (int k = 0; k< n; k++, sx += incx, sy += incy)
+    s += *sx * *sy;   
+   return  s;
+}
+
+template<class R> inline R blas_sdot( int n, R *sx, int incx, R *sy, int  incy)
+{
+    R s=R();
+    
+    if(incx == 1 && incy == 1)
+        for (int k = 0; k< n; k++)
+            s += *sx++ * * sy++;
+    else
+        for (int k = 0; k< n; k++, sx += incx, sy += incy)
+            s += *sx * *sy;
+    return  s;
+}
+// OpenBlas PB with constant  remove const ....
+template<> inline float blas_sdot(const int n,  float *sx, int incx, float *sy, int  incy)
+{
+    return cblas_sdot(n,sx,incx,sy,incy);
+}
+template<> inline double blas_sdot( int n,  double *sx, int incx, double *sy, int  incy)
+{
+    return cblas_ddot(n,sx,incx,sy,incy);
+}
+
+#ifdef OPENBLAS_CONFIG_H
+typedef  openblas_complex_double *BLAS_ptr_complex16;
+#else
+typedef void *BLAS_ptr_complex16;
+
+#endif
+template<> inline  complex<double> blas_sdot( int n,  complex<double> *sx, int incx, complex<double> *sy, int  incy)
+{
+    complex<double> s;
+    cblas_zdotu_sub(n,( double *)sx,incx,( double *)sy,incy,(BLAS_ptr_complex16)&s);
+    return s;
+}
+//template<> inline  complex<float> blas_sdot( int n,  complex<float> *sx, int incx, complex<float> *sy, int  incy)
+//{
+//    complex<float> s;
+//    cblas_cdotu_sub(n,( void *)sx,incx,( void *)sy,incy,(BLAS_ptr_complex8)&s);
+//    return s;
+//}
+
+#endif
+//  end modif FH
+using Fem2D::HeapSort;
+using std::numeric_limits;
+
+//  -----------
+template<class FElement>
+inline int  BuildMEK_KK(const int l,int *p,int *pk,int *pkk,const FElement * pKE,const FElement*pKKE)
+{
+  // routine which find common  dof on to adjacent element pKE and pKKE and make the link ..
+  // if pKKE== 0   then no  adj element
+  // the idea is find common dof, but this work only if all dot a different
+  // in on elemnt, so we can have a bug
+  //  in case of periodic boundary condition ..
+  // not correct ... F.Hecht ...
+
+  // -----
+  // routine  build  les array p, pk,pkk 
+  // which return number of df int 2 element pKE an pKKE
+  // max l size of array p, pk, pkk
+  // p[i] is the global number of freedom
+  // pk[i] is is the local number in pKE ( -1 if not in pKE element)
+  // pkk[i] is is the local number in pKKE ( -1 if not in pKKE element)
+     const FElement (*pK[2])={pKE,pKKE};
+
+     int ndf=0; // number of dl
+     int * qk=pk, *qkk=pkk;
+     for (int k=0;k<2;k++)
+      if(pK[k]) 
+       {
+         if(k) Exchange(qk,qkk);
+         const FElement& FEK=*pK[k];
+         int nbdf =FEK.NbDoF();
+         
+         for (int ii=0;ii<nbdf;ii++)
+          {
+           p[ndf] = 2*FEK(ii)+k; // copy the numbering
+           qk[ndf] = ii;
+           qkk[ndf++] = -1;
+          } // end for ii
+         } 
+      ffassert(ndf <=l);
+    int bug=0;
+   // compression suppression des doublons
+    // attention un df peu aparaitre 2 fois (CL period) dans un element ..
+       Fem2D::HeapSort(p,pk,pkk,ndf);
+       int k=0;  
+        for(int ii=1;ii<ndf;++ii)
+          if (p[k]/2==p[ii]/2) // doublons k,kk
+            { 
+              if (pkk[ii]>=0) pkk[k]=pkk[ii];
+              if (pk[ii]>=0) pk[k]=pk[ii];
+              assert(pk[k] >=0 && pkk[k]>=0);
+            }
+           else { // copy
+              if(p[k]==p[ii]) bug++;
+              p[++k] =p[ii];
+              pk[k]=pk[ii];
+              pkk[k]=pkk[ii];
+             }
+        ndf=k+1; 
+  for(int ii=0;ii<ndf;++ii)
+      p[ii]= p[ii]/2;// clean pp to revome bug(CL period)
+    if( bug && pKKE) {
+        static int count =0;
+        if( count++ < 2 && verbosity )
+        {
+        cerr << "  May be a Bug in BuildMEK_KK , the code is not safe , periodic boundary condition  on 1 element . " << bug <<  endl;
+        cerr << "  They is a problem   in this case (I am not sure) F.H.  ????" << endl;
+            cerr << "   exempt if the associed  matrix voefficient is 0. "<< endl;
+        }
+        //ffassert(0); // bof bof ... remove of case of jump in internal edge ...
+    }
+   return ndf;
+} //  BuildMEK_KK
+
+template<class R,class FES>
+void MatriceElementairePleine<R,FES>::call(int k,int ie,int label,void * stack,void *B) {
+  for (int i=0;i<this->lga;i++) 
+     this->a[i]=0;
+  if(this->onFace)
+    { 
+     throwassert(faceelement);
+     const Mesh &Th(this->Vh.Th);
+     
+     int iie=ie,kk=Th.ElementAdj(k,iie);
+     if(kk==k|| kk<0) kk=-1;
+     if ( &this->Vh == &this->Uh)
+      {
+       FElement Kv(this->Vh[k]);
+       if(kk<0)
+        { // return ; // on saute ????  bof bof 
+	  this->n=this->m=BuildMEK_KK<FElement>(this->lnki,this->ni,this->nik,this->nikk,&Kv,0);
+         int n2 =this->m*this->n; 
+         for (int i=0;i<n2;i++) this->a[i]=0;
+         faceelement(*this,Kv,Kv,Kv,Kv,this->data,ie,iie,label,stack,reinterpret_cast<Rd*>(B));
+        }
+        else
+        {
+         FElement KKv(this->Vh[kk]);
+         this->n=this->m=BuildMEK_KK<FElement>(this->lnki,this->ni,this->nik,this->nikk,&Kv,&KKv);
+        
+         
+         faceelement(*this,Kv,KKv,Kv,KKv,this->data,ie,iie,label,stack,reinterpret_cast<Rd*>(B));
+
+        }
+      }
+     else 
+      {
+          throwassert(faceelement);
+          const Mesh &Th(this->Vh.Th);
+          
+          int iie=ie,kk=Th.ElementAdj(k,iie);
+          if(kk==k|| kk<0) kk=-1;
+          if ( &this->Vh == &this->Uh)
+          {
+              FElement Kv(this->Vh[k]);
+              FElement Ku(this->Uh[k]);
+              if(kk<0)
+              { // return ; // on saute ????  bof bof
+                  this->n=BuildMEK_KK<FElement>(this->lnki,this->ni,this->nik,this->nikk,&Kv,0);
+                  this->m=BuildMEK_KK<FElement>(this->lnkj,this->nj,this->njk,this->njkk,&Ku,0);
+                  int n2 =this->m*this->n;
+                  for (int i=0;i<n2;i++) this->a[i]=0;
+                  faceelement(*this,Kv,Kv,Kv,Kv,this->data,ie,iie,label,stack,reinterpret_cast<Rd*>(B));
+              }
+              else
+              {
+                  FElement KKv(this->Vh[kk]);
+                  FElement KKu(this->Uh[kk]);
+                  this->n=BuildMEK_KK<FElement>(this->lnki,this->ni,this->nik,this->nikk,&Kv,&KKv);
+                  this->m=BuildMEK_KK<FElement>(this->lnkj,this->nj,this->njk,this->njkk,&Ku,&KKu);
+                  
+                  faceelement(*this,Ku,KKu,Kv,KKv,this->data,ie,iie,label,stack,reinterpret_cast<Rd*>(B));
+                  
+              }
+          }
+          ERREUR("BUG ???? A FAIRE/ TO DO  (see F. hecht) ", 0);
+        ffassert(0); // a faire F. Hecht desole
+       
+      }
+   }
+  else {
+  throwassert(element);
+  const FElement&Kv(this->Vh[k]);
+  int nbdf =Kv.NbDoF();
+  for (int i=0;i<nbdf;i++)
+     this->ni[i] = Kv(i); // copy the numbering 
+  this->m=this->n=nbdf;  
+
+  if(this->ni != this->nj) { // 
+    const FElement&Ku(this->Uh[k]);
+    int nbdf =Ku.NbDoF();
+    for (int i=0;i<nbdf;i++)
+      this->nj[i] = Ku(i); // copy the numbering 
+     this->m=nbdf;
+     int n2 =this->m*this->n; 
+     for (int i=0;i<n2;i++) this->a[i]=0;
+     element(*this,Ku,Kv,this->data,ie,label,stack,reinterpret_cast<Rd*>(B));
+  }
+  else 
+    {
+     int n2 =this->m*this->n;
+     for (int i=0;i<n2;i++) this->a[i]=0;
+     element(*this,Kv,Kv,this->data,ie,label,stack,reinterpret_cast<Rd*>(B));
+   // call the elementary mat 
+    }  
+  }  
+}
+
+template<class R,class FES>
+void MatriceElementaireSymetrique<R,FES>::call(int k,int ie,int label,void * stack,void  *B) {
+  // mise a zero de la matrice elementaire, plus sur
+  for (int i=0;i<this->lga;i++) 
+    this->a[i]=0;
+  if(this->onFace)
+    { 
+      ffassert(0); // a faire 
+    }
+  else {
+    
+    if (k< this->Uh.Th.nt)
+      {
+	throwassert(element);
+	const FElement K(this->Uh[k]);
+	int nbdf =K.NbDoF();
+	for (int i=0;i<nbdf;i++)
+	  this->ni[i] = K(i); // copy the numbering 
+	this->m=this->n = nbdf; 
+	
+	element(*this,K,this->data,ie,label,stack,static_cast<Rd*>(B));
+      }// call the elementary mat 
+    else
+      {
+	ffassert(0); // remove code for the 3d 
+	/*
+	throwassert(mortar);
+	{
+	  const FMortar K(&(this->Uh),k);
+	  int nbdf = K.NbDoF();
+	  for (int i=0;i<nbdf;i++)
+	    this->ni[i] = K(i); // copy the numbering 
+	  this->m=this->n = nbdf; 
+	  // mise a zero de la matrice elementaire, plus sur
+	  
+	  mortar(*this,K,stack);}
+	*/
+      }
+  }
+}
+  
+template<class R>
+MatriceProfile<R>::~MatriceProfile() {
+  if(!this->dummy) 
+    { //cout << " del mat profile " << endl ;
+    if (U && (U !=L))  delete [] U;
+    if (D)  delete [] D;
+    if (L)  delete [] L;
+    if (pU && (pU != pL)) delete [] pU;
+    if (pL) delete [] pL;
+    //cout << " dl de MatriceProfile " << this << endl;
+    }
+}
+template<class R>
+int MatriceProfile<R>::size() const {
+  int s = sizeof(MatriceProfile<R>);
+  if (D) s += this->n*sizeof(R);
+  if (pL) s += this->n*sizeof(int);
+  if (pU && (pU != pL)) s += this->n*sizeof(int);
+  if (L) s += pL[this->n]*sizeof(int);
+  if (U && (U != L)) s += pU[this->n]*sizeof(int);
+  return s;
+}
+/*
+template<class R>
+int MatriceProfile<R>::MatriceProfile(const MatriceProfile<RR> & A )
+  : MatriceCreuse<R>(A.n,A.m,0)
+  {
+    
+    typefac=A.typefac;
+    pL=  docpy<int,int>(A.pL,n+1);
+    D = docpy<R,RR>(A.D,n);
+    if ( A.pL == A.pU ) pU=pL;
+    else pU=  docpy<int,int>(A.pU,m+1);
+    
+      L= docpy<R,RR>(A.L,pL[n]);
+      
+    if ( A.L == A.U ) U=L;
+    else  U= docpy<R,RR>(A.U,pU[m]);
+    
+  
+  }*/
+template<class R>
+  MatriceMorse<R> *MatriceProfile<R>::toMatriceMorse(bool transpose,bool copy) const 
+  {
+  // A FAIRE;
+    ffassert(0); // TODO
+   return 0;
+  }
+  
+ inline pair<int,int> ij_mat(bool trans,int ii00,int jj00,int i,int j) {
+  // warning trans sub  matrix and not the block. 
+  return trans ? make_pair<int,int>(j+ii00,i+jj00)
+                :  make_pair<int,int>(i+ii00,j+jj00) ; }
+ 
+template<class R>
+bool MatriceProfile<R>::addMatTo(R coef,std::map< pair<int,int>, R> &mij,bool trans,int ii00,int jj00,bool cnj,double threshold)
+{
+    double eps0=max(numeric_limits<double>::min(), threshold);
+    if( RNM::norm2(coef)<eps0) return  L == U ;
+    int i,j,kf,k;
+    if(D)
+    {
+        for( i=0;i<this->n;i++)
+            if( RNM::norm2(D[i])>eps0)
+                mij[ij_mat(trans,ii00,jj00,i,i)] += coef*(cnj? RNM::conj(D[i]) : D[i]);
+    }
+    else
+    {
+        for(int i=0;i<this->n;i++) // no dia => identity dai
+            mij[ij_mat(trans,ii00,jj00,i,i)] += coef;
+    }
+    if (L && pL )
+        for (kf=pL[0],i=0;  i<this->n;   i++  )
+	  { 
+	    k=kf;
+	    kf=pL[i+1];
+	    for ( j=i-kf+k;   k<kf; j++,  k++  )
+                if(RNM::norm2(L[k])>eps0)
+		  mij[ij_mat(trans,ii00,jj00,i,j)]= coef*(cnj? RNM::conj(L[k]) : L[k]);
+	  }
+    if (U && pU)
+        for (kf=pU[0],j=0;  j<this->m;  j++)
+	  {
+	    k=kf;
+	    kf=pU[j+1];
+	    for ( i=j-kf+k;   k<kf; i++,  k++  )
+	      if(RNM::norm2(U[k])>eps0)
+		mij[ij_mat(trans,ii00,jj00,i,j)]= coef*(cnj? RNM::conj(U[k]) : U[k]);
+	  }
+    return L == U ; // symetrique
+}
+template<class R>
+MatriceProfile<R>::MatriceProfile(const int nn,const R *a)
+  :MatriceCreuse<R>(nn,nn,0),typefac(FactorizationNO)
+{
+  int *pf = new int [this->n+1];
+  int i,j,k;
+  k=0;
+  for (i=0;i<=this->n;k+=i++)
+    {
+      pf[i]=k;
+      //  cout << " pf " << i<< " = " << k  << endl;
+    }
+  ffassert( pf[this->n]*2 == this->n*(this->n-1));
+  pU = pf; // pointeur profile U
+  pL = pf; // pointeur profile L
+  U = new R[pf[this->n]];
+  L = new R[pf[this->n]];
+  D = new R[this->n];  
+  const R *aij=a;
+  for (i=0;i<this->n;i++)
+    for (j=0;j<this->n;j++)
+      if      (j<i)   L[pL[i+1]-i+j] = *aij++;
+      else if (j>i)   U[pU[j+1]-j+i] = *aij++;
+      else            D[i] = *aij++;
+}
+
+template<class R>
+template<class FESpace>
+MatriceProfile<R>::MatriceProfile(const FESpace & Vh,bool VF) 
+  :MatriceCreuse<R>(Vh.NbOfDF,Vh.NbOfDF,0),typefac(FactorizationNO)
+{
+   // for galerkine discontinue ....
+   // VF : true=> Finite Volume matrices (change the stencil) 
+   // VF = false => Finite element 
+   // F. Hecht nov 2003
+   // -----
+  this->dummy=0;
+  this->n = this->m = Vh.NbOfDF;
+  int i,j,k,ke,ie,mn,jl,iVhk;
+  int itab,tabk[5]; 
+  int *pf = new int [this->n+1];
+  for (i=0;i<this->n;i++)  pf[i]=0;
+  for (ke=0;ke<Vh.NbOfElements;ke++)
+    { 
+      itab=0;
+      tabk[itab++]=ke;
+      if(VF) itab += Vh.Th.GetAllElementAdj(ke,tabk+itab);
+      tabk[itab]=-1;    
+      mn = this->n;
+      for( k=tabk[ie=0]; ie <itab; k=tabk[++ie])
+	{ iVhk=(int) Vh(k);
+        for (jl=0;jl<iVhk;jl++) // modif Oct 2008 valgrind
+	  { 
+	    j=Vh(k,jl) ;
+	    mn = Min ( mn , Vh.FirstDFOfNode(j) ) ;}
+        }
+       //for( k=tabk[ie=0]; ie <itab; k=tabk[++ie])
+        { 
+	  k=ke; // bof bof a verifier finement .... FH
+	  iVhk=(int) Vh(k);  
+        //for (j=Vh(k,jl=0);jl<(int) Vh(k);j=Vh(k,++jl)) 
+	for (jl=0;jl<iVhk;jl++) // modif Oct 2008 valgrind
+	     {
+		 j=Vh(k,jl);
+	      int df1 = Vh.LastDFOfNode(j);
+	      for (int df= Vh.FirstDFOfNode(j);  df < df1; df++  )
+	       pf[df] = Max(pf[df],df-mn);
+	     }
+	     }
+    }
+  int l =0;
+  for (i=0;i<this->n;i++)  {int tmp=l;l += pf[i]; pf[i]=tmp;}
+  pf[this->n] = l;
+  if(verbosity >3) 
+    cout << "  -- SizeOfSkyline =" <<l << endl;
+
+  pU = pf; // pointeur profile U
+  pL = pf; // pointeur profile L
+  D = 0; // diagonal
+  U = 0; // upper part
+  L = 0; // lower part 
+}
+
+template<class R>
+void MatriceProfile<R>::addMatMul(const KN_<R> &x,KN_<R> &ax) const 
+{if (x.n!= this->n ) ERREUR(MatriceProfile MatMut(xa,x) ," longueur incompatible x (in) ") ;
+ if (ax.n!= this->n ) ERREUR(MatriceProfile MatMut(xa,x) ," longueur incompatible ax (out)") ;
+ int i,j,k,kf;
+ ffassert(this->n == this->m);
+ if (D) 
+   for (i=0;i<this->n;i++) 
+     ax[i] += D[i]*x[i];
+ else
+   for (i=0;i<this->n;i++) // no dia => identyty dai
+     ax[i] +=x[i];
+      
+ if (L && pL )    
+   for (kf=pL[0],i=0;  i<this->n;   i++  )  
+     { 
+       k=kf;
+       kf=pL[i+1];
+       for ( j=i-kf+k;   k<kf; j++,  k++  )
+	 ax[i] += L[k]*x[j],throwassert(i>=0 && i <this->n && j >=0 && j < this->m && k>=0 && k < pL[this->n]);
+     }
+ 
+ if (U && pU)     
+   for (kf=pU[0],j=0;  j<this->m;  j++)  
+     {
+       k=kf;
+       kf=pU[j+1];
+       for ( i=j-kf+k;   k<kf; i++,  k++  )
+	 ax[i] += U[k]*x[j],throwassert(i>=0 && i <this->n && j >=0 && j < this->m &&  k>=0 && k < pU[this->n]);
+     }
+ 
+ 
+}
+
+
+template<class R>
+void MatriceProfile<R>::operator=(const R & v) {
+  if(v!=R())
+    { cerr << " Mise a zero d'une matrice MatriceProfile<R>::operator=(R v) uniquement v=" << v << endl;
+    throw(ErrorExec("exit",1));
+    }
+  typefac = FactorizationNO;
+  delete [] U;
+  delete [] L;
+  delete [] D;
+  U=L=D=0;
+}
+template<class R>
+MatriceCreuse<R>  & MatriceProfile<R>::operator +=(MatriceElementaire<R> & me) {
+  int il,jl,i,j,k;
+  int * mi=me.ni, *mj=me.nj;
+  if (!D)  // matrice vide 
+    { D  = new R[this->n];
+    L  = pL[this->n] ? new R[pL[this->n]] :0 ;
+    for (i =0;i<this->n;i++) D[i] =0;
+    for (k =0;k<pL[this->n];k++) L[k] =0;
+    switch (me.mtype) {
+    case MatriceElementaire<R>::Full :     
+      U  = pU[this->n] ? new R[pU[this->n]] : 0;
+      for (k =0;k<pU[this->n];k++) U[k] =0;
+      break;
+    case MatriceElementaire<R>::Symmetric :     
+      U = L; 
+      break;
+    default:
+      cerr << "Big bug type MatriceElementaire unknown" << (int) me.mtype << endl;
+      throw(ErrorExec("exit",1));
+      break; 
+    }
+    }
+  R * al = me.a; 
+  switch (me.mtype) {
+  case MatriceElementaire<R>::Full : //throwassert(L !=U);
+    for (il=0; il<me.n; ++il) // modif overflow FH win32  oct 2005
+     { i=mi[il];
+      for ( jl=0; jl< me.m ; ++jl,++al)  // modif overflow FH
+        { j=mj[jl] ;
+	  if      (j<i)  L[ pL[i+1] - (i-j) ] += *al;
+	  else if (j>i)  U[ pU[j+1] - (j-i) ] += *al;
+	  else           D[i] += *al;}}
+    break;
+     
+  case MatriceElementaire<R>::Symmetric : //throwassert(L ==U);   
+    for (il=0; il<me.n; ++il) // modif overflow FH win32
+      { i=mi[il];
+      for (jl=0;jl<= il;++jl)
+       { j=mj[jl]  ;
+	 if      (j<i)  L[ pL[i+1] - (i-j) ] += *al++;
+	 else if (j>i)  U[ pU[j+1] - (j-i) ] += *al++;
+	 else           D[i] += *al++;}}
+    break;
+  default:
+    cerr << "Big bug type MatriceElementaire unknown" << (int) me.mtype << endl;
+    exit(1);
+    break; 
+  }      
+  return *this;
+} 
+
+template<class R>
+ostream& MatriceProfile<R>::dump (ostream& f) const 
+{f<< " matrix skyline " << this->n << '\t' << this->m << '\t' ;
+ f <<  "  this " << endl;
+ f << " pL = " << pL << " L ="  << L << endl
+   << " pU = " << pU << " U ="  << U << endl
+   << " D = " << D << endl;
+ if ( (pL == pU) &&  (U == L) )
+   if (pL && L) 
+     {f << " skyline symmetric " <<endl;
+     int i,j,k;
+     for (i = 0;i<this->n;i++) 
+       { f << i << " {" << pL[i+1]-pL[i] << "}" <<'\t' ;
+       for (k=pL[i];k<pL[i+1];k++)
+	 { j=i-(pL[i+1]-k);
+	 f << j << " " << L[k] << "; "; 
+	 }
+       f <<  i  << ":" << D[i] << endl  ;
+       }
+     }
+   else f << "Skyline: pointeur null " <<endl; 
+ else 
+   { 
+     f << " Skyline  non symmetric " << endl;
+     int i,k;
+     for (i = 0;i<this->n;i++) 
+       {
+	 f << i ;
+	 if (pL && L) 
+	   {
+	     f << " jO=" << i-pL[i+1]+pL[i] << " L= " <<'\t' ;
+	     for (k=pL[i];k<pL[i+1];k++)
+	       { 
+		 f <<  " " << L[k] ; 
+	       }
+	   }
+	 if (D)
+	   f  << " D= " << D[i]  << '\t' ;
+	 else 
+	   f  << " D=0 => 1 ; ";
+	 if (pU && U) 
+	   {
+	     f << " i0=" << i-pU[i+1]+pU[i] << " U= " <<'\t' ;
+	     for (k=pU[i];k<pU[i+1];k++)
+	       f << " " << U[k] ; 
+
+	   }
+	 f << endl;  
+       }
+    
+   }
+ return f;
+}
+template<class R>
+void MatriceProfile<R>::cholesky(double eps) const {
+  double eps2=eps*eps;
+  R  *ij , *ii  , *ik , *jk , xii;
+  int i,j,k;
+  if (L != U) ERREUR(factorise,"Skyline matrix non symmetric");
+  U = 0; // 
+  typefac = FactorizationCholeski;
+  if ( RNM::norm2(D[0]) <= 1.0e-60)
+      ERREUR(cholesky,"pivot (" << 0 << ")= " << D[0] )
+  
+  D[0] = sqrt(D[0]); 
+  ij = L ; // pointeur sur le terme ij de la matrice avec j<i 
+  for (i=1;i<this->n;i++) // boucle sur les lignes 
+    { ii = L+pL[i+1]; // pointeur sur le terme fin de la ligne +1 =>  ij < ii;
+    xii = D[i] ; 
+    for ( ; ij < ii ; ij++) // pour les j la ligne i
+      { j = i -(ii - ij); 
+      k = Max( j - (pL[j+1]-pL[j]) ,  i-(pL[i+1]-pL[i]) ); 
+      ik =  ii - (i - k); 
+      jk =  L + pL[j+1] -(j - k); 
+      k = j - k ;
+      R s= -*ij; 
+#ifdef WITHBLAS
+      s += blas_sdot(k,ik,1,jk,1);
+#else
+      while(k--) s += *ik++ * *jk++;  
+#endif
+      *ij =  -s/D[j] ;
+      xii -= *ij * *ij ;
+      }
+    // cout << RNM::norm2(xii) << " " << Max(eps2*RNM::norm2(D[i]),1.0e-60) << " " << sqrt(xii) <<endl;
+    if ( RNM::norm2(xii) <= Max(eps2*RNM::norm2(D[i]),1.0e-60)) 
+      ERREUR(cholesky,"pivot (" << i << ")= " << xii << " < " << eps*abs(D[i]))
+    D[i] = sqrt(xii);
+    }
+}
+template<class R>
+void MatriceProfile<R>::crout(double eps) const  {
+  R  *ij , *ii  , *ik , *jk , xii, *dkk;
+  int i,j,k;
+  double eps2=eps*eps;
+  if (L != U) ERREUR(factorise,"Skyline matrix  non symmetric");
+  U = 0; // 
+  typefac = FactorizationCrout;
+   
+  ij = L ; // pointeur sur le terme ij de la matrice avec j<i 
+  for (i=1;i<this->n;i++) // boucle sur les lignes 
+    { ii = L+pL[i+1]; // pointeur sur le terme fin de la ligne +1 =>  ij < ii;
+    xii = D[i] ; 
+    for ( ; ij < ii ; ij++) // pour les j la ligne i
+      { j = i -(ii - ij); 
+      k = Max( j - (pL[j+1]-pL[j]) ,  i-(pL[i+1]-pL[i]) ); 
+      ik =  ii - (i - k); 
+      jk =  L + pL[j+1] -(j - k); 
+      dkk = D + k;
+      k = j - k ; 
+      R s=-*ij;
+      while ( k-- ) s += *ik++ * *jk++ * *dkk++;  
+      *ij = -s/ *dkk ; // k = j ici 
+
+      xii -= *ij * *ij * *dkk;
+      }
+    if (RNM::norm2(xii) <= Max(eps2*RNM::norm2(D[i]),1.0e-60))
+      ERREUR(crout,"pivot (" << i << " )= " << abs(xii)<< " <= " << eps*abs(D[i]) << " eps = " << eps)
+	D[i] = xii;
+    }
+}
+template<class R>
+void MatriceProfile<R>::LU(double eps) const  {
+  R s,uii;
+  double eps2=eps*eps;
+  int i,j;
+  if (L == U && ( pL[this->n]  || pU[this->n] ) ) ERREUR(LU,"matrix LU  symmetric");
+  if(verbosity>3)
+  cout << "  -- LU " << endl;
+  typefac=FactorizationLU;
+
+  for (i=1;i<this->n;i++) // boucle sur les sous matrice de rang i 
+    { 
+      // for L(i,j)  j=j0,i-1
+      int j0 = i-(pL[i+1]-pL[i]);
+      for ( j = j0; j<i;j++)
+        {           
+          int k0 = Max(j0,j-(pU[j+1]-pU[j]));
+          R *Lik = L + pL[i+1]-i+k0; // lower
+          R *Ukj = U + pU[j+1]-j+k0; // upper
+          s =0;
+#ifdef WITHBLAS
+	  s = blas_sdot(j-k0,Lik,1,Ukj,1);
+	  Lik += j-k0;
+#else
+          for (int k=k0;k<j;k++) // k < j < i ;
+	    s += *Lik++ * *Ukj++ ;     // a(i,k)*a(k,j);
+#endif
+	  *Lik -= s;
+	  *Lik /= D[j]; //  k == j here
+        }
+      // for U(j,i) j=0,i-1        
+      j0=i-pU[i+1]+pU[i];
+      for (j=j0;j<i;j++) 
+	{
+	  s = 0;
+	  int k0 = Max(j0,j-pL[j+1]+pL[j]);
+	  R *Ljk = L + pL[j+1]-j+k0;   
+	  R *Uki = U + pU[i+1]-i+k0;   
+#ifdef WITHBLAS
+	  s = blas_sdot(j-k0,Ljk,1,Uki,1);
+          Uki += j-k0;
+#else
+	  for (int k=k0  ;k<j;k++)    // 
+	    s +=  *Ljk++ * *Uki++ ;
+#endif
+	  *Uki -= s;  // k = j here 
+	}
+      // for D (i,i) in last because we need L(i,k) and U(k,i) for k<j
+      int k0 = i-Min(pL[i+1]-pL[i],pU[i+1]-pU[i]);
+      R *Lik = L + pL[i+1]-i+k0; // lower
+      R *Uki = U + pU[i+1]-i+k0; // upper
+      s =0;
+#ifdef WITHBLAS
+       s = blas_sdot(i-k0,Lik,1,Uki,1);
+#else
+      for (int k=k0;k<i;k++) // k < i < i ;
+	s += *Lik++ * *Uki++ ;     // a(i,k)*a(k,i);
+#endif
+      // cout << " k0 " << k0 << " i = " << i << " " <<  s << endl;
+      uii = D[i] -s;
+      
+      if (RNM::norm2(uii) <= Max(eps2*RNM::norm2(D[i]),1.0e-30))
+	ERREUR(LU,"pivot (" << i << " )= " << abs(uii) << " <= " << eps*abs(D[i]) << " eps = " << eps);     
+      
+      D[i] = uii;
+      
+    }
+}
+
+
+template<class R>
+KN_<R> & operator/=(KN_<R> & x ,const MatriceProfile<R> & a) 
+{
+  // --------------------------------------------------------------------
+  //   si La diagonal D n'existe pas alors on suppose 1 dessus (cf crout)
+  // --------------------------------------------------------------------
+  R * v = &x[0];
+  int n = a.n;  
+  if (x.n != n ) 
+    ERREUR (KN_<R> operator/(MatriceProfile<R>),"  matrice et KN_<R> incompatible");
+  const R *ij ,*ii, *ik, *ki;
+  R *xk,*xi;
+  int i;
+  switch (a.typefac) {
+  case FactorizationNO:
+    if (a.U && a.L) {cerr << "APROGRAMMER (KN_<R><R>::operator/MatriceProfile)";throw(ErrorExec("exit",2));}
+   
+    if ( a.U && !a.L ) 
+      { // matrice triangulaire superieure
+	// cout << " remonter " << (a.D ? "DU" : "U") << endl;
+	ki = a.U + a.pU[n]; 
+	i = n;
+	while ( i-- )
+	  { ii = a.U + a.pU[i];
+          xi= xk  = v +  i ;
+          if (a.D) *xi /= a.D[i];// pour crout ou LU
+          while ( ki > ii) 
+	    *--xk  -=  *--ki *  *xi ; 
+	  }
+      }
+    else if  ( !a.U && a.L ) 
+      { // matrice triangulaire inferieure
+	// cout << " descente "  <<( a.D ? "LD" : "L" ) <<endl;
+	ii = a.L;
+	for (i=0; i<n; i++)
+	  { ij = ik = (a.L + a.pL[i+1]) ;  // ii =debut,ij=fin+1 de la ligne 
+          xk = v + i;
+          R ss = v[i]; 
+          while ( ik > ii) 
+	    ss -= *--ik * *--xk ; 
+          if ( a.D) ss /= a.D[i];// pour crout ou LU
+          v[i] = ss ;
+          ii = ij;
+	  }
+      }
+    else if (a.D) 
+      { // matrice diagonale
+	// cout << " diagonal D" <<endl;
+	for (i=0;i<n;i++) 
+	  v[i]=v[i]/a.D[i];
+      }
+    break;
+  case FactorizationCholeski:  
+    //     cout << " FactorizationChosleski" << endl;
+    x /= a.ld();
+    x /= a.ldt();   
+    break;
+  case FactorizationCrout:
+    //   cout << " FactorizationCrout" << endl;
+    x /= a.l();
+    x /= a.d();
+    x /= a.lt();
+    break;
+  case FactorizationLU:
+    //  cout << " FactorizationLU" << endl;
+    x  /= a.l();
+    x  /= a.du();
+    break;
+    /*   default:
+	 ERREUR  (operator /=(MatriceProfile," Error unkown type of Factorization  =" << typefac);
+    */
+  }
+  return x;
+}
+
+template <class R> 
+ MatriceMorse<R>::MatriceMorse(KNM_<R> & A,double tol)
+    :MatriceCreuse<R>(A.N(),A.M(),false),solver(0) 
+      {
+  double tol2=tol*tol;    
+  symetrique = false;
+  this->dummy=false;
+  int nbcoeff=0;
+  for(int i=0;i<this->n;i++)
+    for(int j=0;j<this->m;j++)
+      if(RNM::norm2(A(i,j))>tol2) nbcoeff++;
+
+  nbcoef=nbcoeff;
+  nbcoeff=Max(nbcoeff,1); // pour toujours alloue quelque chose FH Bug dans CheckPtr
+  a=new R[nbcoeff] ;
+  lg=new int [this->n+1];
+  cl=new int [nbcoeff];
+  nbcoeff=0;
+  R aij;
+  for(int i=0;i<this->n;i++)
+   { 
+    lg[i]=nbcoeff;
+    for(int j=0;j<this->m;j++)
+     
+      if(RNM::norm2(aij=A(i,j))>tol2)
+       {
+         cl[nbcoeff]=j;
+         a[nbcoeff]=aij;
+         nbcoeff++;
+       }
+    }
+   lg[this->n]=nbcoeff;
+
+  
+}
+template <class R> 
+ MatriceMorse<R>::MatriceMorse(const int  nn,const R *aa)
+    :MatriceCreuse<R>(nn),solver(0) 
+      {
+  symetrique = true;
+  this->dummy=false;
+  this->n=nn;
+  nbcoef=this->n;
+  a=new R[this->n] ;
+  lg=new int [this->n+1];
+  cl=new int [this->n];
+  for(int i=0;i<this->n;i++)
+   {
+    lg[i]=i;
+    cl[i]=i;
+    a[i]=aa[i];      
+      }
+lg[this->n]=this->n;
+}
+
+template<class R>
+template<class K>
+ MatriceMorse<R>::MatriceMorse(const MatriceMorse<K> & A,R (*f)(K ))
+   : MatriceCreuse<R>(A.n,A.m,A.dummy),nbcoef(A.nbcoef),      
+     symetrique(A.symetrique),       
+     a(new R[nbcoef]),
+     lg(new int [this->n+1]),
+     cl(new int[nbcoef]),
+     solver(0)
+{
+  ffassert(a && lg &&  cl);
+  for (int i=0;i<=this->n;i++)
+    lg[i]=A.lg[i];
+  for (int k=0;k<nbcoef;k++)
+    {
+      cl[k]=A.cl[k];
+      a[k]=f(A.a[k]);
+    }
+  
+}
+
+template<class R>
+template<class K>
+MatriceMorse<R>::MatriceMorse(const MatriceMorse<K> & A)
+: MatriceCreuse<R>(A.n,A.m,A.dummy),nbcoef(A.nbcoef),      
+symetrique(A.symetrique),       
+a(new R[nbcoef]),
+lg(new int [this->n+1]),
+cl(new int[nbcoef]),
+solver(0)
+{
+    ffassert(a && lg &&  cl);
+    for (int i=0;i<=this->n;i++)
+        lg[i]=A.lg[i];
+    for (int k=0;k<nbcoef;k++)
+    {
+        cl[k]=A.cl[k];
+        a[k]=A.a[k];
+    }
+    
+}
+
+
+
+template <class R> 
+int MatriceMorse<R>::size() const 
+{
+  return nbcoef*(sizeof(int)+sizeof(R))+ sizeof(int)*(this->n+1);
+}
+
+inline int WhichMatrix(istream & f)
+{
+    string line;
+    while ( isspace(f.peek()))
+	f.get(); 
+    if  ( f.peek() =='#' )
+    {
+	line="";
+	while ( f.good()  )
+	{
+	    char c=f.get();
+	    if(c=='\n' || c=='\r') { break;}
+	    line += c;
+	}
+	if( line.find("(Morse)")) 
+	    return 2; // morse 
+	else 
+	    return 0; 
+    }
+  return 0;   
+}
+template <class R>
+  MatriceMorse<R>::MatriceMorse(istream & f)
+:  MatriceCreuse<R>(0,0,0),nbcoef(0),
+a(0),
+lg(0),
+cl(0),
+
+solver(0)
+{
+      string line;
+      int k=0;
+      while ( isspace(f.peek()))
+	      f.get(); 
+      while ( f.peek() =='#' )
+      {
+	line="";
+	while ( f.good()  )
+	{
+	    char c=f.get();
+	    if(c=='\n' || c=='\r') { break;}
+	    line += c;
+	}
+	if( f.peek()=='\n' || f.peek()=='\r') f.get();
+	if(verbosity>9)
+	 cout << "Read matrice: "<< k << " :"   << line << endl;
+	k++;    
+      }
+      
+      f >> this->n >> this->m >> symetrique >>nbcoef;
+      if(verbosity>3)
+      cout << " read mat: " <<  this->n << " " <<  this->m << " " << symetrique << " " << nbcoef <<endl;
+      lg= new int [this->n+1];
+      cl= new int[nbcoef];
+      a= new R[nbcoef];
+      ffassert(f.good() && lg && a && cl );
+      int i,j,i0,j0;
+      i0=-1;j0=2000000000;
+      R aij;
+      int imx=-2000000000, jmx=-2000000000;
+      int imn= 2000000000, jmn= 2000000000;
+      
+      for (int k =0;k<nbcoef; ++k)
+      {
+	  f >> i >> j >> aij;
+	  ffassert(f.good() );
+	  i--;j--;
+	  imx=max(imx,i);
+	  jmx=max(jmx,j);
+	  imn=min(imn,i);
+	  jmn=min(jmn,j);
+	  //cout << i << " " << j << " " << aij << endl;
+	  if(i0!=i) {j0=-1;lg[i]=k;}
+	  ffassert(i0<=i && j0<j);
+	  lg[i+1]=k+1;
+	  cl[k]=j;
+	  a[k]=aij;
+	  j0=j;i0=i;
+      }
+      ffassert( imx < this->n && jmx < this->m );
+      ffassert( imn >=0 && jmn >=0);
+      
+}
+
+template <class R> 
+ostream& MatriceMorse<R>::dump(ostream & f) const 
+{
+  f << "# Sparse Matrix (Morse)  " << endl;
+  f << "# first line: n m (is symmetic) nbcoef \n";
+  f << "# after for each nonzero coefficient:   i j a_ij where (i,j) \\in  {1,...,n}x{1,...,m} \n";  
+ 
+  f << this->n << " " << this->m << " " << symetrique << "  " << nbcoef <<endl;
+  int k=lg[0];
+  int pold= f.precision();
+  for (int i=0;i<this->n;i++)
+   { 
+    
+//    f << i << " : " << lg[i] <<","<< lg[i+1]-1 << " : " ;
+    int ke=lg[i+1];
+    for (;k<ke;k++)
+      f << setw(9) << i+1 << ' ' << setw(9) << cl[k]+1 << ' ' << setprecision( 20) << a[k]<< '\n' ;
+     // if (RNM::norm2(a[k])) f  << cl[k] << " " << a[k]<< ", ";
+     // else f  << cl[k] << " 0., " ;
+   // f << endl;    
+   }
+   f.precision(pold);
+  return f;
+}
+template <class R> 
+inline R*  MatriceMorse<R>::pij(int i,int j) const 
+ {
+   if (! (i<this->n && j< this->m)) 
+   throwassert(i<this->n && j< this->m);
+   int i0=lg[i];
+   int i1=lg[i+1]-1;
+   while (i0<=i1) // dichotomie
+    { 
+      int im=(i0+i1)/2;
+      if (j<cl[im]) i1=im-1;
+      else if (j>cl[im]) i0=im+1;
+      else return a+im;      
+    }
+   return 0;     
+ }
+template <class R>
+template <class FESpace> 
+void MatriceMorse<R>::Build(const FESpace & Uh,const FESpace & Vh,bool sym,bool VF)
+{
+  typedef typename FESpace::Mesh Mesh;
+  
+  // for galerkine discontinue ....
+  // VF : true=> Finite Volume matrices (change the stencil) 
+  // VF = false => Finite element 
+  // F. Hecht nov 2003
+  // -----
+  symetrique = sym;
+  this->dummy=false;
+  a=0;
+  lg=0;
+  cl=0;
+  //  bool same  = &Uh == & Vh;
+  ffassert( &Uh.Th == &Vh.Th);  // same Mesh
+  const Mesh & Th(Uh.Th);
+  //int nbt = Th.nt;
+  //int nbv = Th.nv;
+  //int nbm = Th.NbMortars;
+  int nbe = Uh.NbOfElements;
+  int nbn_u = Uh.NbOfNodes;
+  int nbn_v = Vh.NbOfNodes;
+  
+  KN<int> mark(nbn_v);
+  KN<int> pe_u(nbn_u+1+Uh.SizeToStoreAllNodeofElement());
+  //  les element du node i 
+  // sont dans pe_u[k] pour k \in [ pe_u[i] , pe_u[i+1] [
+  pe_u=0;
+  for (int k=0;k<nbe;k++)
+    { 
+      int nbne=Uh(k);
+      for (int in=0;in<nbne;in++)
+        pe_u[(Uh(k,in)+1)]++;
+   }
+  int kk= nbn_u+1,kkk=kk;
+  pe_u[0]=kk;
+  for (int in1=1;in1<=nbn_u;in1++)
+    { // in1 = in + 1
+      kk += pe_u[in1];
+      pe_u[in1] = kkk; // store the last of in 
+      kkk=kk;
+    } 
+  if(verbosity>4) 
+    cout <<"  -- MatriceMorse<R>::Build " << kk << " " << nbn_u << " " << Uh.SizeToStoreAllNodeofElement() 
+	 << " " <<  nbn_u+1+Uh.SizeToStoreAllNodeofElement() << endl;
+  ffassert(kk== nbn_u+1+Uh.SizeToStoreAllNodeofElement());
+  for (int k=0;k<nbe;k++)
+    { 
+      int nbne=Uh(k);
+      for (int in=0;in<nbne;in++)
+        pe_u[pe_u[(Uh(k,in)+1)]++] = k;
+    }
+  
+  
+  int color=0;
+  mark=color++;
+  lg = new int [this->n+1];
+  ffassert(lg);
+  for (int step=0;step<2;step++) 
+    { 
+      int ilg=0;
+      lg[0]=ilg;
+      int kij=0;
+    for (int in=0;in<nbn_u;in++)
+      {
+	int nbj=0; // number of j
+	int kijs=kij;
+	// for all triangle contening node in
+	for (int kk= pe_u[in];kk<pe_u[in+1];kk++)
+	  {
+	    int ke=pe_u[kk];// element of 
+	    int tabk[10];
+	    int ltab=0;
+	    tabk[ltab++]=ke;
+	    if( VF) // if Finite volume then add Triangle adj in stencil ...
+	      ltab+= Th.GetAllElementAdj(ke,tabk+ltab);
+	    tabk[ltab]=-1;
+	    for(int ik=0,k=tabk[ik];ik<ltab;k=tabk[++ik])
+	      {
+		throwassert(k>=0 && k < nbe);
+		int njloc = Vh(k);
+		for (int jloc=0;jloc<njloc;jloc++)
+		  { 
+		    int  jn = Vh(k,jloc);
+		    if (mark[jn] != color && (!sym ||  jn < in) ) 
+		      {
+			mark[jn] = color;
+			int fdf=Vh.FirstDFOfNode(jn);
+			int ldf=Vh.LastDFOfNode(jn);
+			if (step)
+			  for (int j=fdf;j<ldf;j++)
+			    cl[kij++] = j;
+			nbj += ldf-fdf;
+		      }            
+		  }} 
+	  }
+	int fdf=Uh.FirstDFOfNode(in);
+	int ldf=Uh.LastDFOfNode(in);
+	int kijl=kij;
+	if (step)
+	  {
+	    HeapSort(cl+kijs,kij-kijs);
+	    for (int i=fdf;i<ldf;i++)
+	      { 
+		if (i!=fdf) //  copy the ligne if not the first 
+		  for (int k=kijs;k<kijl;k++)
+		    cl[kij++]=cl[k]; 
+		if (sym) // add block diag
+		  for(int j=fdf;j<=i;j++)
+		    cl[kij++]=j;            
+		throwassert(kij==lg[i+1]);// verif           
+	      }
+	  }
+	else
+	  for (int i=fdf;i<ldf;i++)
+	    { 
+	      if (sym) ilg += ++nbj; // for the diag block
+	      else ilg += nbj;             
+	      lg[i+1]=ilg;
+	    }
+	color++; // change the color
+      }
+    if (step==0) { // do allocation 
+      nbcoef=ilg;
+      if (verbosity >3)
+        cout << "  -- MorseMatrix: Nb coef !=0 " << nbcoef << "  n =" << this->n << " m = " << this->m << endl;
+      a = new R[nbcoef];
+      cl = new int [nbcoef];}
+    ffassert( a && cl);
+    for (int i=0;i<nbcoef;i++) 
+      a[i]=0;
+   }
+    if( verbosity > 999)
+    {
+        cout << "  -- MorseMatrix: " << endl;
+        for(int i=0; i< this->n; ++i)
+        { cout << i << " : " ;
+            for(int k=lg[i];k<lg[i+1]; ++k)
+                cout << cl[k] << ' ';
+            cout << endl;
+        }
+    }
+    
+}
+template<class R> inline void ConjArray( R  *v, int n)
+{
+  for (int i=0;i<n;++i)
+    v[i] = RNM::conj(v[i]);
+}
+template<> inline void ConjArray<double>(double *v, int n) {}
+template<> inline void ConjArray<float>(float *v, int n) {}
+
+template<class R>
+ void  MatriceMorse<R>::dotransposition()
+ {
+   if(symetrique) return; 
+   
+   ffassert(this->dummy==false);  
+   int *llg= new int[nbcoef];
+   int *clg= new int[this->m+1];
+   
+   for (int i=0;i<this->n;i++)
+     for (int k=lg[i];k<lg[i+1];k++)
+        llg[k]=i;
+ 
+  HeapSort(cl,llg,a,nbcoef);
+  for(int k=0;k<this->m;k++)
+    clg[k]=-1;
+
+  // build new line end (old column)
+  for(int k=0;k<nbcoef;k++)
+    clg[cl[k]+1]=k+1;
+      
+   for(int kk=0, k=0;k<=this->m;k++)
+   if (clg[k]==-1)
+      clg[k]=kk;
+    else kk=clg[k];
+    
+  clg[this->m]=nbcoef;
+  // sort the new column (old line)
+  for(int i=0;i<this->m;i++)  
+    HeapSort(llg+clg[i],cl+clg[i],a+clg[i],clg[i+1]-clg[i]); 
+  delete[] cl;
+  delete[] lg;
+  Exchange(this->n,this->m);       
+  cl=llg;
+  lg=clg;
+  ConjArray(a,nbcoef);    
+ }
+
+template<class R>
+ triplet<int,int,bool> BuildCombMat(std::map< pair<int,int>, R> & mij,const list<triplet<R,MatriceCreuse<R> *,bool> >  &lM,bool trans,int ii00,int jj00,bool cnj=false)
+  {
+    // modif FH feb 2010  cnj =>  transpose ->  conj &  trans 
+    typedef typename list<triplet<R,MatriceCreuse<R> *,bool> >::const_iterator lconst_iterator;
+    
+    lconst_iterator begin=lM.begin();
+    lconst_iterator end=lM.end();
+    lconst_iterator i;
+    
+   // std::map< pair<int,int>, R> mij;
+    
+    int n=0,m=0;
+    bool sym=true;
+    for(i=begin;i!=end;i++++)
+     {
+	if(i->second) // M == 0 => zero matrix 
+	{
+	    MatriceCreuse<R> & M=*i->second;
+	    bool transpose = i->third !=  trans;
+	    ffassert( &M);
+	    R coef=i->first;
+	    if(verbosity>3)
+		cout << "                BuildCombMat + " << coef << "*" << &M << " " << sym << "  t = " << transpose << " " <<  i->third << endl;
+	    //  change to max FH dec 2007 to hard to satisfy
+	   /* if (n==0)*/ { if(transpose) {m=max(m,M.n); n=max(n,M.m);} else{n=max(M.n,n); m=max(M.m,m);}}// Modif mars 2007 FH
+	   /* else { if(transpose)  ffassert(n== M.m && m==M.n); else ffassert(n== M.n && m==M.m);}*/
+	    sym = M.addMatTo(coef,mij,transpose,ii00,jj00,transpose&&cnj) && sym;  
+	}
+     } 
+    int nbcoef=mij.size();
+    if(sym) nbcoef = (nbcoef+n)/2;
+
+  // return new   MatriceMorse<R>(n,m,mij,sym);   
+    return make_triplet(n,m,sym);
+  }
+  
+template<class R>
+  MatriceMorse<R> * BuildCombMat(const list<triplet<R,MatriceCreuse<R> *,bool> >  &lM,bool trans,int ii00,int jj00)
+  {
+   
+    std::map< pair<int,int>, R> mij;
+    triplet<int,int,bool> nmsym=BuildCombMat(mij,lM,trans,ii00,jj00);
+
+   return new   MatriceMorse<R>(nmsym.first,nmsym.second,mij,nmsym.third);   
+     
+  }
+template<class R>
+bool MatriceMorse<R>::addMatTo(R coef,std::map< pair<int,int>, R> &mij,bool trans,int ii00,int jj00,bool cnj,double threshold)
+{
+  double eps0=max(numeric_limits<double>::min(),threshold);
+  int i,j,k;
+  if (symetrique)
+   {
+     for ( i=0;i<this->n;i++)
+       for ( k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           R cij =  coef* ( cnj ? RNM::conj(a[k]) : a[k]);
+           if(RNM::norm2(cij)>eps0)
+           {
+            mij[ij_mat(trans,ii00,jj00,i,j)] += cij ;
+           if (i!=j)
+             mij[ij_mat(trans,ii00,jj00,j,i)] += cij;
+           }
+         }
+           
+   }
+  else
+   {
+     for ( i=0;i<this->n;i++)
+       for ( k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           R cij =  coef* ( cnj ? RNM::conj(a[k]) : a[k]);
+
+           if(RNM::norm2(cij)>eps0)
+           mij[ij_mat(trans,ii00,jj00,i,j)] += cij;
+         }
+   }
+
+return symetrique;
+}
+
+ 
+template<class R> 
+template<class K>
+MatriceMorse<R>::MatriceMorse(int nn,int mm, std::map< pair<int,int>, K> & m, bool sym):
+  MatriceCreuse<R>(nn,mm,0),
+  nbcoef(m.size()),symetrique(sym),
+  a(new R[nbcoef]),
+  lg(new int[nn+1]),
+  cl(new int[nbcoef]),     
+  solver(0)
+{
+     int k=0;
+     bool nosym=!sym;
+     typename std::map< pair<int,int>, R>::iterator iter=m.begin(), mend=m.end();
+     //  remarque lg est croissant Bug trouver par 
+     for(int i=0;i<=nn;i++) lg[i]=0; 
+     while(iter!=mend)
+      { 
+        int i=iter->first.first;
+        int j=iter->first.second;
+        K & aij=iter->second;
+        assert( i < nn && j < mm);
+        if(j<=i || nosym)
+        {
+         cl[k]=j;
+         a[k]=aij;
+         lg[i+1]=++k;
+        }
+        ++iter;
+       }
+    // lg est croissant  on bouche les trou   
+   for(int i=1;i<=nn;i++) lg[i]=Max(lg[i-1],lg[i]); 
+      
+   ffassert(nbcoef==k);  
+  }
+// FH  mars 2009 ... 
+template<class R>
+ void  MatriceMorse<R>::resize(int nn,int mm) 
+{
+    int nc=0;   
+    int *nlg=new int[nn+1],*ncl=0;
+    int nm=min(nn,this->n);
+    nc =0;
+    nlg[0]=nc; 
+    if (symetrique)
+      {   if( nn != mm) AFAIRE("MatriceMorse<R>::resize symetric  n!=m");
+	  for (int i=0;i<nm;i++)
+	    {
+	      for (int k=lg[i];k<lg[i+1];k++)
+		{   int j=cl[k];
+		    if( j<this->m && RNM::norm2(a[k]))		    
+			++nc;		   
+		}
+		nlg[i+1]=nc;
+	    }
+	  
+      }
+    else
+      {
+	  for (int i=0;i<nm;i++)
+	    {
+	      for (int k=lg[i];k<lg[i+1];k++)
+		{
+		    int j=cl[k];
+		    if(i<this->n && j<this->m && RNM::norm2(a[k]))
+			++nc ;
+		}
+		nlg[i+1]=nc;
+	    }
+      }
+    for(int i=nm+1;i<=nn;++i)
+	nlg[i]=nc;
+    ncl = new int[nc];
+    R *na=new R[nc];
+    nc=0;
+
+    if (symetrique)
+      {   if( nn != mm) AFAIRE("MatriceMorse<R>::resize symetric  n!=m");
+	  for (int i=0;i<nm;i++)
+	      for (int k=lg[i];k<lg[i+1];k++)
+		{   int j=cl[k];
+		    if( j<this->m && RNM::norm2(a[k]))		    
+		      {na[nc]=a[k];
+		       ncl[nc++]=j;}
+		}
+	  
+      }
+    else
+      {
+	  for (int i=0;i<nm;i++)
+	      for (int k=lg[i];k<lg[i+1];k++)
+		{
+		    int j=cl[k];
+		    if( j<this->m && RNM::norm2(a[k]))
+		      {na[nc]=a[k];
+		       ncl[nc++]=j;}
+		}
+      }
+    
+    delete [] cl;
+    delete [] lg;
+    delete [] a;
+    cl=ncl;
+    lg=nlg;
+    a=na;
+    this->n=nn;
+    this->m=mm;
+    this->N=nn;
+    this->M=mm;
+    this->nbcoef=nc;
+ //   cout << nn << " " << mm << "  " <<  KN_<int>(lg,nn+1) << endl;
+    
+}
+template<class RA>
+ template<class RB,class RAB>
+ void  MatriceMorse<RA>::prod(const MatriceMorse<RB> & B, MatriceMorse<RAB> & AB)
+ {
+   //  compute the s
+  bool sym=this == & B &&symetrique;
+  int *blg=B.lg;
+  int *bcl=B.cl;
+  ffassert(this->m==B.n); 
+  bool delbl= B.symetrique;
+  if (delbl)
+    {
+     int nn=B.n;
+      blg = new int[nn+1];
+     for (int i=0;i<B.n;i++)
+         blg[i]=B.lg[i+1]-B.lg[i];
+      blg[nn]=0;   
+      
+      for (int i=0;i<nn;i++)
+        for (int k= B.lg[i];k<B.lg[i+1];k++)
+          {  int j=B.cl[k];
+              assert(j <= i);
+             if (j!=i)  
+               blg[j]++;
+             }
+             
+      for (int i=1;i<=nn;i++)
+       blg[i]+=blg[i-1];
+      int nbnz = blg[nn];
+      bcl= new int[nbnz];
+      
+      for (int i=0;i<B.n;i++)
+        for (int k= B.lg[i];k<B.lg[i+1];k++)
+          {  int j=B.cl[k];
+             assert(j <= i);
+             bcl[--blg[i] ]=j;
+             if(i !=j)
+               bcl[--blg[j]]=i;
+          }
+    }
+   
+   set<pair<int,int> > sij;
+   double eps0=numeric_limits<double>::min();
+
+     for (int i=0;i<this->n;i++)
+       for (int k=lg[i];k<lg[i+1];k++)
+         {    
+           int j=cl[k];
+           if(RNM::norm2(a[k])<eps0) continue;
+           int ii[2],jj[2];
+           ii[0]=i;ii[1]=j;
+           jj[0]=j;jj[1]=i;
+           int kk=1;
+           if(symetrique && i != j) kk=2;
+           for (int ll=0;ll<kk;ll++)
+            {
+                int i=ii[ll];
+                int j=jj[ll];
+		if(j>=B.n) continue; // in case of not equal size A.m != B.n 
+                for (int kkb=blg[j];kkb<blg[j+1];kkb++)
+                  { 
+                   int kz= bcl[kkb];
+                   RB bjk;
+                   if (B.symetrique && kz > j)
+                     bjk=B(kz,j);
+                   else
+                      bjk=B(j,kz);
+                   if( RNM::norm2(bjk)>eps0 && (!sym || kz<=i))
+                     sij.insert(make_pair(i,kz));
+                  }
+            }
+           
+         }
+    int nn=this->n;
+    int mm=B.m;
+    int * llg=new int[nn+1];
+    int * lcl=new int[sij.size()];  
+    RAB * aa = new RAB[sij.size()];
+    for(int i=0;i<=nn;i++)
+        llg[i]=0;
+        
+    for (set<pair<int,int> >::iterator iter=sij.begin();iter!=sij.end();++iter)
+      { 
+        int i=iter->first;
+	// int j=iter->second;
+        llg[i]++;
+       }
+     for (int i=1;i<=nn;i++)
+       llg[i]+=llg[i-1];
+     ffassert(llg[this->n]==(long) sij.size());
+     for (set<pair<int,int> >::iterator iter=sij.begin();iter!=sij.end();++iter)
+      { 
+        int i=iter->first;
+        int j=iter->second;
+       // cout << i << " , " << j << endl;
+        lcl[--llg[i]]=j;
+       }
+     for(int i=0;i<nn;i++)  
+       HeapSort(lcl+llg[i],llg[i+1]-llg[i]); 
+       
+     AB.n=nn;
+     AB.m=mm;
+     AB.N=nn;  // add missing jan 2008 FH
+     AB.M=mm;  // add missing jan 2008 FH
+
+     AB.lg=llg;
+     AB.cl=lcl;
+     AB.a=aa;        
+     AB.nbcoef=sij.size();
+     AB.symetrique=sym;
+     AB.dummy=false;
+     AB = RAB();
+     for (int i=0;i<this->n;i++)
+       for (int k=lg[i];k<lg[i+1];k++)
+         {    
+           int j=cl[k];
+           RAB aij = a[k];
+           if(RNM::norm2(aij) <eps0 ) continue;
+           int ii[2],jj[2];
+           ii[0]=i;ii[1]=j;
+           jj[0]=j;jj[1]=i;
+           int kk=1;
+           if(symetrique && i != j) kk=2;
+           for (int ll=0;ll<kk;ll++)
+            {
+                int i=ii[ll];
+                int j=jj[ll];
+		if(j>=B.n) continue; // in case of not equal size A.m != B.n 
+                for (int kb=blg[j];kb<blg[j+1];kb++)
+                  { 
+                   int k= bcl[kb];
+                   RB bjk;
+                   if (B.symetrique && k > j)
+                     bjk=B(k,j);
+                   else
+                      bjk=B(j,k);
+                //   cout << i << "," << "," << j << "," << k << " " << aij << " " << bjk << endl;
+                   if( RNM::norm2( bjk)> eps0  && (!sym || k<=i))
+                       AB(i,k) += aij*bjk;
+                  }
+            }
+           
+         }
+
+    if (delbl) {
+      delete [] blg;
+      delete [] bcl;
+    }
+     
+     
+ }
+
+template<class R>
+  void  MatriceMorse<R>::addMatMul(const KN_<R> &  x, KN_<R> & ax) const   
+{
+  int i,j,k;
+  if( ! (this->n==ax.N() && this->m==x.N()))
+    {cerr << " Err MatriceMorse<R>:  ax += A x" <<endl;
+      cerr << " A.n " << this->n<< " !=  "<< ax.N() << " ax.n \n";
+      cerr << " A.m " << this->m<< " != " <<x.N() << " x.n \n" ;
+      ffassert(0); 
+      abort();
+    }
+  if (symetrique)
+   {
+     for (i=0;i<this->n;i++)
+       for (k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           ax[i] += a[k]*x[j];
+           if (i!=j)
+             ax[j] += a[k]*x[i];
+         }
+           
+   }
+  else
+   {
+     for (i=0;i<this->n;i++)
+       for (k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           ax[i] += a[k]*x[j];
+         }
+   }
+}
+
+template<class R>
+  void  MatriceMorse<R>::addMatTransMul(const KN_<R> &  x, KN_<R> & ax) const   
+{
+  int i,j,k;
+  ffassert(this->m==ax.N());
+  ffassert(this->n==x.N());  
+  if (symetrique)
+   {
+     for (i=0;i<this->n;i++)
+       for (k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           ax[j] += a[k]*x[i];
+           if (i!=j)
+             ax[i] += a[k]*x[j];
+         }
+           
+   }
+  else
+   {
+     for (i=0;i<this->n;i++)
+       for (k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           ax[j] += a[k]*x[i];
+         }
+   }
+}
+
+
+template<class R>
+MatriceMorse<R>  & MatriceMorse<R>::operator +=(MatriceElementaire<R> & me) {
+  //  R zero=R();
+  int il,jl,i,j;
+  int * mi=me.ni, *mj=me.nj;
+  if ((this->n==0) && (this->m==0))
+   {
+   
+    //    if(verbosity>3)
+    cout << "  -- Morse Matrice is empt: let's build it" << endl;
+    ffassert(0); 
+    /*
+    this->n=me.Uh.NbOfDF;
+    this->m=me.Vh.NbOfDF;
+    switch (me.mtype) {
+    case MatriceElementaire<R>::Full : 
+      Build(me.Uh,me.Vh,false);    
+      break;
+    case MatriceElementaire<R>::Symmetric :     
+      Build(me.Uh,me.Vh,true);    
+      break;
+     default:
+      cerr << "Big bug type MatriceElementaire is unknown" << (int) me.mtype << endl;
+      throw(ErrorExec("exit",1));
+      break; }     
+    */
+   }
+  R * al = me.a; 
+  R * aij;
+  switch (me.mtype) { // modif FH overfloat in array mi and mj => trap on win32
+  case MatriceElementaire<R>::Full : ffassert(!symetrique);
+    for (il=0; il<me.n; ++il)  { i=mi[il]; 
+      for ( jl=0; jl< me.m ; ++jl,++al)  {j=mj[jl];
+        aij = pij(i,j);
+      //  if( *al!=zero )
+        {
+        throwassert(aij);
+            *aij += *al;}}}
+    break;
+     
+  case MatriceElementaire<R>::Symmetric : ffassert(symetrique);   
+    for (il=0; il<me.n; ++il) {  i=mi[il] ;
+      for (jl=0;jl< il+1 ; ++jl) { j=mj[jl];
+	 aij =    (j<i) ? pij(i,j) : pij(j,i);
+         throwassert(aij);
+         *aij += *al++;}}
+    break;
+  default:
+    cerr << "Big bug type MatriceElementaire unknown" << (int) me.mtype << endl;
+    exit(1);
+    break; 
+  }      
+  return *this;
+} 
+
+template<class R>
+  void MatriceMorse<R>::Solve(KN_<R> &x,const KN_<R> &b) const{
+    if (solver)    
+      solver->Solver(*this,x,b);
+    else
+  {  cerr << "No Solver defined  for this Morse matrix " << endl;
+    throw(ErrorExec("exit",1));}
+  }
+
+
+template<class R>
+double MatriceMorse<R>::psor(KN_<R> & x,const  KN_<R> & gmin,const  KN_<R> & gmax , double omega) 
+{
+  double err=0;
+  int n=this->n;
+  ffassert(n==this->m);
+  ffassert(n==x.N());
+  ffassert(n==gmin.N());
+  ffassert(n==gmax.N());
+  if (symetrique)
+   {
+     ErrorExec("Error:sorry psor just for no symmetric Morse matrices",1);
+   }
+  else
+   {
+     for (int i=0;i<this->n;i++)
+      {
+       R xnew =x[i];
+       R aii=R();
+       for (int k=lg[i];k<lg[i+1];k++)
+         {
+           int j=cl[k];
+           if(j!= i) 
+             xnew -= a[k]*x[j];
+            else aii=a[k];
+         }
+        if(aii != R())
+           xnew /= aii;
+         else ErrorExec("Error: psor diagonal coef = 0 ",1);
+        R dx  = (xnew - x[i])*omega ;
+        R xi = RNM::Min(RNM::Max(x[i]+dx,gmin[i]),gmax[i]);
+        dx = x[i]- xi;
+        err = Max(err, RNM::norm2(dx));
+        x[i] = xi;
+        }
+   }  return sqrt(err);
+  
+}
+
+template<class R>
+double MatriceProfile<R>::psor(KN_<R> & x,const  KN_<R> & gmin,const  KN_<R> & gmax , double omega) 
+{
+  double rr=0;
+  ErrorExec("Error:sorry psor just for no symmetric Morse matrices (will do in future FH??? )",2);
+  return rr;
+  
+}
+
+template<class R>
+void MatriceProfile<R>::setdiag(const KN_<R> & x) 
+{
+  ffassert(D);
+ ffassert( this->n == x.N());
+  KN_<R> d(D,this->n) ;
+  d=x;
+}
+template<class R>
+void MatriceProfile<R>::getdiag(KN_<R> & x) const 
+{
+  ffassert(D);
+  ffassert( this->n == x.N());
+  KN_<R> d(D,this->n) ;
+  x=d;  
+}
+template<class R>
+void MatriceMorse<R>::setdiag(const KN_<R> & x) 
+{
+ ffassert( this->n == this->m&& this->n == x.N());
+ for (int i=0;i<this->n;++i)
+    {
+      R * p= pij(i,i);
+      if(p)     *p = x[i];
+      else ffassert( RNM::norm2(x[i]) < 1e-30);}
+}
+template<class R>
+void MatriceMorse<R>::getdiag(KN_<R> & x) const 
+{
+ ffassert( this->n == this->m && this->n == x.N());
+ for (int i=0;i<this->n;++i)
+    {
+      R * p= pij(i,i);
+      x[i]=  p ?  *p : R() ;
+    }
+  
+}
+template<class R>
+R MatriceMorse<R>::pscal(const KN_<R> & x,const KN_<R> & y)
+{ // (x, Ay)
+  R sum=R();
+  int i,j,k;
+  ffassert(this->n==x.N());
+  ffassert(this->m==y.N());  
+  if (symetrique)
+   {
+     for (i=0;i<this->n;i++)
+       for (k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           sum += a[k]*x[i]*y[j];
+           if (i!=j)
+             sum += a[k]*x[j]*y[i];
+         }
+           
+   }
+  else
+   {
+     for (i=0;i<this->n;i++)
+       for (k=lg[i];k<lg[i+1];k++)
+         {
+           j=cl[k];
+           sum += a[k]*x[i]*y[j];
+         }
+   }
+  return sum;
+}
+template<class R>
+R MatriceProfile<R>::pscal(const KN_<R> & x,const KN_<R> & y)
+{
+ if (y.n != this->n || x.n != this->n ) ERREUR(MatriceProfile pscal(xa,x) ," longueur incompatible c (out)") ;
+ int i,j,k,kf;
+ R sum = R();
+ ffassert(this->n == this->m);
+ if (D) 
+   for (i=0;i<this->n;i++) 
+     sum += D[i]*x[i]*y[i];
+ else
+   for (i=0;i<this->n;i++) // no dia => identyty dai
+     sum +=x[i]*y[i];
+      
+ if (L && pL )    
+   for (kf=pL[0],i=0;  i<this->n;   i++  )  
+     { 
+       k=kf;
+       kf=pL[i+1];
+       for ( j=i-kf+k;   k<kf; j++,  k++  )
+	 sum += L[k]*x[i]*y[j],throwassert(i>=0 && i <this->n && j >=0 && j < this->m && k>=0 && k < pL[this->n]);
+     }
+ if (U && pU)     
+   for (kf=pU[0],j=0;  j<this->m;  j++)  
+     {
+       k=kf;
+       kf=pU[j+1];
+       for ( i=j-kf+k;   k<kf; i++,  k++  )
+	 sum += U[k]*x[i]*y[j],throwassert(i>=0 && i <this->n && j >=0 && j < this->m &&  k>=0 && k < pU[this->n]);
+     }
+ return sum;
+}
+
+template<class R>
+void MatriceMorse<R>::getcoef(KN_<R> & x) const 
+{
+ ffassert(x.N()==this->nbcoef);
+ x = KN_<R>(this->a,nbcoef);  
+}
+template<class R>
+void MatriceMorse<R>::setcoef(const KN_<R> & x)  
+{
+ ffassert(x.N()==nbcoef);
+  KN_<R>(this->a,nbcoef) = x;
+}
+template<class R>
+int MatriceMorse<R>::NbCoef() const  
+{
+  return this->nbcoef;
+}
+
+template<class R>
+void MatriceProfile<R>::getcoef(KN_<R> & x) const 
+{
+ ffassert(x.N()==this->NbCoef());
+ int k=0,kk;
+ if (D)
+  {  kk=this->n;
+     x(SubArray(kk,k))  = KN_<R>(D,kk);
+     k += kk; }
+ if (L)
+  {  kk= pL[this->n];
+     x(SubArray(kk,k))  = KN_<R>(L,kk);
+     k += kk; }
+  if (U && (U != L)) 
+  {  kk=  pU[this->n];
+     x(SubArray(kk,k))  = KN_<R>(U,kk);
+     k += kk; }
+   
+}
+template<class R>
+void MatriceProfile<R>::setcoef(const KN_<R> & x)  
+{
+ ffassert(x.N()==this->NbCoef());
+   int k=0,kk;
+ if (D)
+  {  kk=this->n;
+     KN_<R>(D,kk)=x(SubArray(kk,k))   ;
+     k += kk; }
+ if (L)
+  {  kk= pL[this->n];
+     KN_<R>(L,kk)=x(SubArray(kk,k))   ;
+     k += kk; }
+  if (U && (U != L)) 
+  {  kk=  pU[this->n];
+     KN_<R>(U,kk)=x(SubArray(kk,k)) ;
+     k += kk; }
+
+}
+template<class R>
+int MatriceProfile<R>::NbCoef() const  
+{
+  int s=0;
+  if (D) s += this->n;
+  if (L) s += pL[this->n];
+  if (U && (U != L)) s += pU[this->n];
+  return s;
+}
+#endif
+
diff --git a/src/femlib/Mesh1dn.cpp b/src/femlib/Mesh1dn.cpp
new file mode 100644
index 0000000..d8cb9d6
--- /dev/null
+++ b/src/femlib/Mesh1dn.cpp
@@ -0,0 +1,125 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 1d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+#include <fstream>
+#include <iostream>
+#include "ufunction.hpp"
+#include "error.hpp"
+#include "RNM.hpp"
+#include "libmesh5.h"
+
+#include "Mesh1dn.hpp"
+
+   //long verbosity=1;
+
+namespace Fem2D {
+
+  const R1 R1::KHat[2]={R1(0),R1(1)};
+  const R2 R2::KHat[3]={R2(0,0),R2(1,0),R2(0,1)};
+  const  R3 R3::KHat[4]={R3(0,0,0),R3(1,0,0),R3(0,1,0),R3(0,0,1)};
+  
+  static const int  nvfaceTet[4][3]  = { {2,1,3},{0,2,3},{1,0,3},{0,1,2} };
+  static const int  nvedgeTet[6][2] = { {0,1},{0,2},{0,3},{0,1},{1,2},{2,3} };
+  
+  static const int  nvfaceTria[1][3]  = { {0,1,2} };
+  static const int  nvedgeTria[3][2] = { {1,2},{2,0},{0,1}}; 
+  
+  static const int   nvfaceSeg[1][3]  = {{-1,-1,-1}};
+  static const int  nvedgeSeg[1][2] = { {0,1} };
+  static const int  nvadjSeg[2][1] = { {0},{1} };
+  
+  template<> const int (* const GenericElement<DataPoint1>::nvface)[3] = 0 ;
+  template<> const int (* const GenericElement<DataPoint1>::nvedge)[2] = 0 ;
+  template<> const int (* const GenericElement<DataPoint1>::nvadj)[1] = 0 ;
+    
+  template<> const int (* const GenericElement<DataSeg1>::nvface)[3] = 0 ;
+  template<> const int (* const GenericElement<DataSeg1>::nvedge)[2] = nvedgeSeg; //nvedgeTria ;
+  template<> const int (* const GenericElement<DataSeg1>::nvadj)[1] = nvadjSeg ;
+    
+  template<> const int  GenericElement<DataSeg1>::nitemdim[4] = {2,1,0,0 }  ;
+  
+  template<> int   GenericMesh<Seg1,BoundaryPoint1,Vertex1>::kfind=0;
+  template<> int   GenericMesh<Seg1,BoundaryPoint1,Vertex1>::kthrough=0;
+  
+  static const int onWhatIsVertex[2][3] = {  {1,0,0}, // sommet  0 
+					     {0,1,0}}; // sommet 1 
+  
+  
+  template<>
+  const int (* const GenericElement<DataSeg1>::onWhatBorder)[3] = onWhatIsVertex ;
+  
+  
+  Mesh1::Mesh1(const char * filename)
+  { // read the mesh  
+    
+    int nt,nv,nbe;
+    int ok=0;//load(filename);
+    if(ok)
+      {
+	ifstream f(filename);
+	if(!f) {cerr << "Mesh1::Mesh1 Erreur openning " << filename<<endl;exit(1);}
+	if(verbosity)
+	  cout << " Read On file \"" <<filename<<"\""<<  endl;
+	f >> nv >> nt >> nbe ;
+	this->set(nv,nt,nbe);
+	if(verbosity)
+	  cout << "  -- Nb of Vertex " << nv << " " << " Nb of Seg " << nt 
+	       << " , Nb of border Vertex " << nbe <<  endl;
+	assert(f.good() && nt && nv) ;
+	for (int i=0;i<nv;i++)    
+	  {
+	    f >> this->vertices[i];
+	    assert(f.good());
+	  }
+	mes=0;
+	for (int i=0;i<nt;i++) 
+	  { 
+	    this->t(i).Read1(f,this->vertices,nv);
+	    mes += t(i).mesure();
+	  }
+	mesb=0.;
+	for (int i=0;i<nbe;i++) 
+	  { 
+	    this->be(i).Read1(f,this->vertices,nv);
+	    mesb += be(i).mesure();
+	  }
+      }
+    BuildBound();
+    BuildAdj();
+    Buildbnormalv();  
+    BuildjElementConteningVertex();  
+    
+    if(verbosity)  
+      cout << "   - mesh mesure = " << mes << " border mesure: " << mesb << endl;  
+  }
+}
+
+ 
diff --git a/src/femlib/Mesh1dn.hpp b/src/femlib/Mesh1dn.hpp
new file mode 100644
index 0000000..584c60c
--- /dev/null
+++ b/src/femlib/Mesh1dn.hpp
@@ -0,0 +1,126 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 1d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#ifndef MESH1DN_HPP_
+#define MESH1DN_HPP_
+
+namespace Fem2D {
+#include "R1.hpp"
+}
+
+#include "GenericMesh.hpp" 
+#include <cstdlib>
+using namespace std;
+
+namespace Fem2D {
+  
+typedef GenericVertex<R1> Vertex1;
+
+struct DataSeg1  {
+  static const int NbOfVertices =2;
+  static const int NbOfFaces =0;
+  static const int NbOfEdges =1;
+  static const int NT =0;
+  static const int NbOfAdjElem =NbOfVertices;
+  static const int NbOfVertexOnHyperFace =NbOfVertices-1;
+  typedef Vertex1 V;
+  typedef  V::Rd Rd ;
+  static R mesure(  V *  pv[NbOfVertices]) {    
+    return pv[1]->x-pv[0]->x;
+  } 
+  typedef R0 RdHatBord;
+  typedef R1 RdHat;
+  static RdHat PBord(const int * nvb,const RdHatBord & P)  { return R1(*nvb) ;}  
+  //  static const int (* const nvface)[3];// = nvfaceTria  ;
+  //static const int (* const nvedge)[2];// = nvedgeTrai;
+
+};
+
+
+struct DataPoint1  {
+  static const int NbOfVertices =1;
+  static const int NbOfEdges =0;
+  static const int NbOfFaces =0;
+  static const int NT =0;
+  static const int NbOfAdjElem =1;
+  static const int NbOfVertexOnHyperFace =1;
+  typedef Vertex1 V;
+  typedef  V::Rd Rd;
+  static R mesure(  V * pv[NbOfVertices]  ) {    
+    return 1.;
+  }
+  typedef R0 RdHatBord;
+  typedef R0 RdHat;
+  static RdHat PBord(const int * nvb,const RdHatBord & P)  { return R0() ;}  
+
+};
+
+
+
+class Seg1: public GenericElement<DataSeg1>  {
+public: 
+  Seg1() {}; // constructor empty for array
+
+
+  R1 H(int i) const { ASSERTION(i>=0 && i <1);
+    return (2-i)/mesure();} // heigth 
+  
+  void Gradlambda(R1 * GradL) const
+  {
+    GradL[1]= H(1);
+    GradL[0]=-GradL[1];
+  }
+  
+  
+
+};
+
+class BoundaryPoint1: public GenericElement<DataPoint1>  {
+public: 
+  BoundaryPoint1() {}; // constructor empty for array
+
+
+};
+
+
+class Mesh1 : public GenericMesh<Seg1,BoundaryPoint1,Vertex1> { 
+public:
+  Mesh1(const char *); // 
+  const Element * Find( R1 P, R1 & Phat,bool & outside,const Element * tstart) const;
+ private:
+  int load(const string & filename); 
+   Mesh1(const Mesh1 &); // pas de construction par copie
+   void operator=(const Mesh1 &);// pas affectation par copy 
+};
+}
+#endif
+ 
diff --git a/src/femlib/Mesh2dn.cpp b/src/femlib/Mesh2dn.cpp
new file mode 100644
index 0000000..743cc68
--- /dev/null
+++ b/src/femlib/Mesh2dn.cpp
@@ -0,0 +1,455 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 2d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#include <fstream>
+#include <iostream>
+#include "ufunction.hpp"
+#include "error.hpp"
+#include "RNM.hpp"
+#include "libmesh5.h"
+
+
+#include "Mesh2dn.hpp"
+//  for plotStream (a change)
+#include "Mesh3dn.hpp"
+#include "rgraph.hpp"
+#include "fem.hpp"
+#include "PlotStream.hpp"
+
+namespace Fem2D {
+  long verbosity=1;
+  
+  //  const R1 R1::KHat[2]={R1(0),R1(1)};
+  // const R2 R2::KHat[3]={R2(0,0),R2(1,0),R2(0,1)};
+  // const  R3 R3::KHat[4]={R3(0,0,0),R3(1,0,0),R3(0,1,0),R3(0,0,1)};
+  
+  static const int  nvfaceTet[4][3]  = { {2,1,3},{0,2,3},{1,0,3},{0,1,2} };
+  static const int  nvedgeTet[6][2] = { {0,1},{0,2},{0,3},{0,1},{1,2},{2,3} };
+  
+  static const int  nvfaceTria[1][3]  = { {0,1,2} };
+  static const int  nvedgeTria[3][2] = { {1,2},{2,0},{0,1}}; //  tourne de le sens trigo  donc Normal ext   vect(1,0) ^ perp  
+  
+  static const int   nvfaceSeg[1][3]  = {{-1,-1,1}};
+  static const int  nvedgeSeg[1][2] = { {0,1} };
+    
+  static const int  nvadjSeg[2][1] = { {0},{1} };
+    
+ 
+  template<> const int (* const GenericElement<DataSeg2>::nvface)[3] = 0 ;
+  template<> const int (* const GenericElement<DataSeg2>::nvedge)[2] = nvedgeSeg; //nvedgeTria ;
+  template<> const int (* const GenericElement<DataSeg2>::nvadj)[1] = nvadjSeg ;
+    
+  
+  template<> const int (* const GenericElement<DataTriangle2>::nvface)[3] = nvfaceTria ;
+  template<>  const int (* const GenericElement<DataTriangle2>::nvedge)[2] = nvedgeTria ;
+  template<>  const int (* const GenericElement<DataTriangle2>::nvadj)[2] = nvedgeTria ;
+  template<> const int  GenericElement<DataTriangle2>::nitemdim[4] = {3,3,1,0 }  ;
+  
+  
+  static const int onWhatIsEdge2d[3][7] = {  {0,1,3, 2,0,0, 0}, // edge 0 
+					   {3,0,1, 0,2,0, 0},
+					   {1,3,0, 0,0,2, 0}};
+  
+  template<>
+  const int (* const GenericElement<DataTriangle2>::onWhatBorder)[7] = onWhatIsEdge2d ;
+  
+  template<> int   GenericMesh<Triangle2,BoundaryEdge2,Vertex2>::kfind=0;
+  template<> int   GenericMesh<Triangle2,BoundaryEdge2,Vertex2>::kthrough=0;
+  
+
+Mesh2::Mesh2(const char * filename)
+{ // read the mesh  
+
+  int nt,nv,nbe;
+  int ok=load(filename);
+  if(ok)
+    {
+      ifstream f(filename);
+      if(!f) {cerr << "Mesh2::Mesh2 Erreur openning " << filename<<endl;exit(1);}
+      if(verbosity)
+      cout << " Read On file \"" <<filename<<"\""<<  endl;
+      f >> nv >> nt >> nbe ;
+      this->set(nv,nt,nbe);
+      if(verbosity)
+      cout << "  -- Nb of Vertex " << nv << " " << " Nb of Triangles " << nt 
+	   << " , Nb of border edges " << nbe <<  endl;
+      assert(f.good() && nt && nv) ;
+      for (int i=0;i<nv;i++)    
+	{
+	  f >> this->vertices[i];
+	  assert(f.good());
+	}
+      mes=0;
+      for (int i=0;i<nt;i++) 
+	{ 
+	  this->t(i).Read1(f,this->vertices,nv);
+	  mes += t(i).mesure();
+	}
+      mesb=0.;
+      for (int i=0;i<nbe;i++) 
+	{ 
+	  this->be(i).Read1(f,this->vertices,nv);
+	  mesb += be(i).mesure();
+	}
+    }
+  BuildBound();
+  BuildAdj();
+  Buildbnormalv();  
+  BuildjElementConteningVertex();  
+
+  if(verbosity)  
+  cout << "   - mesh mesure = " << mes << " border mesure: " << mesb << endl;  
+}
+
+int Mesh2::load(const string & filename)
+{
+  
+  int bin;
+  int ver,inm,dim;
+  int lf=filename.size()+20;
+  KN<char>  fileb(lf),filef(lf);
+  char * pfile;
+  strcpy(filef,filename.c_str());
+  strcpy(fileb,filef);
+  strcat(filef,".mesh");
+  strcat(fileb,".meshb");
+  if( (inm=GmfOpenMesh(pfile=fileb, GmfRead,&ver,&dim)) ) 
+    bin=true;
+  else if( (inm=GmfOpenMesh(pfile=filef, GmfRead,&ver,&dim)) ) 
+    bin=false;
+  else
+    { cerr << " Erreur ouverture file " << (char *) fileb << " " << (char *) filef << endl;
+      return   1;
+    }
+  int nv,nt,neb;
+  nv = GmfStatKwd(inm,GmfVertices);
+  nt = GmfStatKwd(inm,GmfTriangles);
+  neb=GmfStatKwd(inm,GmfEdges);
+  this->set(nv,nt,neb);
+
+  if(verbosity)  
+  cout << pfile <<": ver " << ver << ", d "<< dim  << ", nt " << nt << ", nv " << nv << " nbe:  = " << nbe << endl;
+  if(dim  != Rd::d) { 
+    cerr << "Err dim == " << dim << " != " << Rd::d << endl;
+    return 2; }
+  if( nv<=0 && nt <=0 ) {
+    cerr << " missing data "<< endl;
+    return 3;
+  }
+  int iv[4],lab;
+  float cr[3];
+  // read vertices 
+  GmfGotoKwd(inm,GmfVertices);
+  int mxlab=0;
+  int mnlab=0;
+  for(int i=0;i<nv;++i)
+    {  
+      if(ver<2) {
+	GmfGetLin(inm,GmfVertices,&cr[0],&cr[1],&cr[2],&lab);
+	vertices[i].x=cr[0];
+	vertices[i].y=cr[1];
+	//	vertices[i].z=cr[2];
+    }
+      else
+	GmfGetLin(inm,GmfVertices,&vertices[i].x,&vertices[i].y,&lab);	    
+      vertices[i].lab=lab;
+      
+      mxlab= max(mxlab,lab);
+      mnlab= min(mnlab,lab);
+    }
+  
+  
+  //    /* read mesh triangles */
+  if(mnlab==0 &&mxlab==0 )
+    {
+      mes=0;
+      GmfGotoKwd(inm,GmfTriangles);
+      for(int i=0;i<nbe;++i)
+	{  
+	  GmfGetLin(inm,GmfTriangles,&iv[0],&iv[1],&iv[2],&lab);
+	  for (int j=0;j<3;++j)  
+	    iv[j]--;
+	  this->elements[i].set(this->vertices,iv,lab);
+	  mes += this->elements[i].mesure();
+	}
+      
+    }
+  
+  
+  /* read mesh segement */
+  mesb=0;
+  GmfGotoKwd(inm,GmfEdges);
+  for(int i=0;i<nbe;++i)
+    {
+      GmfGetLin(inm,GmfEdges,&iv[0],&iv[1],&lab);
+      assert( iv[0]>0 && iv[0]<=nv && iv[1]>0 && iv[1]<=nv);
+      for (int j=0;j<2;j++) iv[j]--;
+      this->borderelements[i].set(vertices,iv,lab); 
+      mesb += this->borderelements[i].mesure();	    
+    }
+  
+  GmfCloseMesh(inm);    
+  return(0); // OK
+  
+}
+
+int Mesh2::Save(const string & filename)
+{
+  int ver = GmfFloat, outm;
+  if ( !(outm = GmfOpenMesh(filename.c_str(),GmfWrite,ver,2)) ) {
+    cerr <<"  -- Mesh2::Save  UNABLE TO OPEN  :"<< filename << endl;
+    return(1);
+  }
+  float fx,fy;
+  GmfSetKwd(outm,GmfVertices,this->nv);
+  for (int k=0; k<nv; k++) {
+    const  Vertex & P = this->vertices[k];
+    GmfSetLin(outm,GmfVertices,fx=P.x,fy=P.y,P.lab);
+  }
+
+  GmfSetKwd(outm,GmfTriangles,nt);
+  for (int k=0; k<nt; k++) {
+    const Element & K(this->elements[k]);
+    int i0=this->operator()(K[0])+1;
+    int i1=this->operator()(K[1])+1;
+    int i2=this->operator()(K[2])+1;
+    int lab=K.lab;
+    GmfSetLin(outm,GmfTriangles,i0,i1,i2,lab);
+  }
+
+  GmfSetKwd(outm,GmfEdges,nbe);
+  for (int k=0; k<nbe; k++) {
+    const BorderElement & K(this->borderelements[k]);
+    int i0=this->operator()(K[0])+1;
+    int i1=this->operator()(K[1])+1;
+    int lab=K.lab;
+    GmfSetLin(outm,GmfEdges,i0,i1,lab);
+  }
+
+  GmfCloseMesh(outm);
+  return (0);
+
+}
+
+const     string Gsbegin="Mesh2::GSave v0",Gsend="end"; 
+
+template<class Mesh>
+void GSave2(FILE * ff,const Mesh & Th) 
+    {  
+	PlotStream f(ff);
+	
+	f <<  Gsbegin ;
+	int nbe=Th.nbBrdElmts();
+	f << Th.nv << Th.nt << nbe;
+	for (int k=0; k<Th.nv; k++) {
+	    const  typename Mesh::Vertex & P = Th(k);		
+	    f << P.x <<P.y  << P.lab ;
+	}
+	
+	    for (int k=0; k<Th.nt; k++) {
+		const typename Mesh::Element & K(Th[k]);
+		int i0=Th(K[0]);
+		int i1=Th(K[1]);
+		int i2=Th(K[2]);
+		
+		int lab=K.lab;
+		f << i0 << i1 << i2  << lab;
+	    }
+	
+	
+	
+	for (int k=0; k<nbe; k++) {
+	    const typename Mesh::BorderElement & K(Th.be(k));
+	    int i0=Th(K[0]);
+	    int i1=Th(K[1]);	   
+	    int lab=K.lab;
+	    f << i0 << i1  << lab;
+	}
+	f << Gsend;
+    }
+
+ //template   void GSave2<Mesh2>(FILE * ff,const Mesh2 & Th) ;
+ template   void GSave2<Mesh>(FILE * ff,const Mesh & Th) ;
+   
+    
+    Mesh2::Mesh2(FILE *f)
+    {
+	
+	GRead(f);
+	assert( (nt >= 0 || nbe>=0)  && nv>0) ;
+	BuildBound();
+	if(verbosity>1)
+	    cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+	
+	if(nt > 0){ 
+	    BuildAdj();
+	    Buildbnormalv();  
+	    BuildjElementConteningVertex();  
+	}
+	
+	if(verbosity>1)
+	    cout << "  -- Mesh2  (File *), d "<< 2  << ", n Tet " << nt << ", n Vtx "
+	    << nv << " n Bord " << nbe << endl;
+	
+    }
+    
+    void Mesh2::GRead(FILE * ff)
+    {  
+	PlotStream f(ff);
+	string s;
+	f >> s;
+	ffassert( s== Gsbegin);
+	f >> nv >> nt >> nbe;
+	if(verbosity>1)
+	    cout << " GRead : nv " << nv << " " << nt << " " << nbe << endl;
+	this->vertices = new Vertex[nv];
+	this->elements = new Element [nt];
+	this->borderelements = new BorderElement[nbe];		
+	for (int k=0; k<nv; k++) {
+	    Vertex & P = this->vertices[k];
+	    f >> P.x >>P.y >> P.lab ;
+	}
+	mes=0.;
+	mesb=0.;
+	
+	if(nt != 0)
+	  {
+	      
+	      for (int k=0; k<nt; k++) {
+		  int i[4],lab;
+		  Element & K(this->elements[k]);
+		  f >> i[0] >> i[1] >> i[2] >> lab;
+		  K.set(this->vertices,i,lab);
+		  mes += K.mesure();	    
+		  
+	      }
+	  }
+	
+	
+	for (int k=0; k<nbe; k++) {
+	    int i[4],lab;
+	    BorderElement & K(this->borderelements[k]);
+	    f >> i[0] >> i[1]   >> lab;
+	    K.set(this->vertices,i,lab);
+	    mesb += K.mesure();	    
+	    
+	}
+	f >> s;
+	ffassert( s== Gsend);
+    }
+    
+    
+    
+    
+/*
+int Mesh2::Popen(const FILE *namestream)
+{
+  
+  int ver = GmfFloat;
+  int dimp =2;
+  float fx,fy;
+
+  FILE *popenstream;
+  popenstream = namestream;
+
+  fprintf(popenstream,"MeshVersionFormatted\n");
+  fprintf(popenstream,"%i\n",ver);
+  fprintf(popenstream,"Dimension\n");
+  fprintf(popenstream,"%i\n",dimp);
+  fprintf(popenstream,"Vertices\n");
+  fprintf(popenstream,"%i\n",this->nv);
+
+  for (int k=0; k<nv; k++) {
+    const  Vertex & P = this->vertices[k];
+    fx=P.x; fy=P.y;
+    fprintf(popenstream,"%f %f %i\n",fx,fy,P.lab);
+  }
+  
+  fprintf(popenstream,"Triangles\n");
+  fprintf(popenstream,"%i\n",this->nt);
+  for (int k=0; k<nt; k++) {
+    const Element & K(this->elements[k]);
+    int i0=this->operator()(K[0])+1;
+    int i1=this->operator()(K[1])+1;
+    int i2=this->operator()(K[2])+1;
+    int lab=K.lab;
+    fprintf(popenstream,"%i %i %i %i\n",i0,i1,i2,lab);
+  }
+
+  fprintf(popenstream,"Edges\n");
+  for (int k=0; k<nbe; k++) {
+    const BorderElement & K(this->borderelements[k]);
+    int i0=this->operator()(K[0])+1;
+    int i1=this->operator()(K[1])+1;
+    int lab=K.lab;
+    fprintf(popenstream,"%i %i %i\n",i0,i1,lab);
+  }
+
+  return (0);
+}
+*/
+Mesh2::Mesh2(int nnv, int nnt, int nnbe, Vertex2 *vv, Triangle2 *tt, BoundaryEdge2 *bb)
+{
+	
+	nv = nnv;
+	nt = nnt;
+	nbe =nnbe;
+	
+	vertices = vv;
+	elements = tt;
+	borderelements = bb;
+	
+	mes=0.;
+	mesb=0.;
+	
+	for (int i=0;i<nt;i++)  
+	  mes += this->elements[i].mesure();
+	
+	for (int i=0;i<nbe;i++)  
+	  mesb += this->be(i).mesure();  
+	
+
+//if(nnt !=0){
+  //BuildBound();
+  //BuildAdj();
+  //Buildbnormalv();  
+  //BuildjElementConteningVertex();
+  //BuildGTree();
+  //decrement();    
+//}
+    
+  if(verbosity>1)
+  cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+	
+} 
+
+}
diff --git a/src/femlib/Mesh2dn.hpp b/src/femlib/Mesh2dn.hpp
new file mode 100644
index 0000000..4de9d25
--- /dev/null
+++ b/src/femlib/Mesh2dn.hpp
@@ -0,0 +1,147 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 2d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#ifndef MESH2DN_HPP_
+#define MESH2DN_HPP_
+
+namespace Fem2D {
+#include "R2.hpp"
+}
+
+#include "GenericMesh.hpp" 
+#include <cstdio>
+#include <cstdlib>
+using namespace std;
+
+namespace Fem2D {
+    
+    
+    
+    typedef GenericVertex<R2> Vertex2;
+    
+    struct DataTriangle2  {
+	static const int NbOfVertices =3;
+	static const int NbOfFaces =1;
+	static const int NbOfEdges =3;
+	static const int NT =0;
+	static const int NbOfAdjElem =NbOfVertices;
+	static const int NbOfVertexOnHyperFace =NbOfVertices-1;
+	typedef Vertex2 V;
+	typedef  V::Rd Rd ;
+	static R mesure(  V *  pv[NbOfVertices]) {    
+	    return det(*pv[0],*pv[1],*pv[2])*0.5;
+	} 
+	typedef R2 RdHat;
+	typedef R1 RdHatBord;
+	static RdHat PBord(const int * nvb,const RdHatBord & P)  { return RdHat::KHat[nvb[0]]*(1-P.x)+R2::KHat[nvb[1]]*(P.x) ;}  
+	
+	//  static const int (* const nvface)[3];// = nvfaceTria  ;
+	//static const int (* const nvedge)[2];// = nvedgeTrai;
+	
+    };
+    
+    
+    struct DataSeg2  {
+	static const int NbOfVertices =2;
+	static const int NbOfEdges =1;
+	static const int NbOfFaces =0;
+	static const int NT =0;
+	static const int NbOfAdjElem =NbOfVertices;
+	static const int NbOfVertexOnHyperFace =NbOfVertices-1;
+	typedef Vertex2 V;
+	typedef  V::Rd Rd;
+	static R mesure(  V *  pv[NbOfVertices]) {    
+	    return R2(*pv[0],*pv[1]).norme();
+	}
+	typedef R1 RdHat;
+	typedef R0 RdHatBord;
+	static RdHat PBord(const int * nvb,const RdHatBord &P)  { return RdHat(*nvb) ;}  
+	
+	//static const int (* const nvface)[3];// = nvfaceSeg ;
+	//static const int (* const nvedge)[2];//  = nvedgeSeg;
+	
+    };
+    
+    
+    
+    class Triangle2: public GenericElement<DataTriangle2>  
+  {
+  public: 
+      Triangle2() {}; // constructor empty for array
+      
+      
+      R2 H(int i) const { ASSERTION(i>=0 && i <3);
+      R2 E=Edge(i);return E.perp()/(2.*this->mesure());} // heigth 
+      
+      void Gradlambda(R2 * GradL) const
+      {
+	  GradL[1]= H(1);
+	  GradL[2]= H(2);
+	  GradL[0]=-GradL[1]-GradL[2];
+      }
+      
+      
+      
+  };
+    
+    class BoundaryEdge2: public GenericElement<DataSeg2>  
+  {
+  public: 
+      BoundaryEdge2() {}; // constructor empty for array
+      
+      
+  };
+    
+    template<typename Mesh> void GSave2(FILE * ff,const Mesh & Th) ;
+    
+    class Mesh2 : public GenericMesh<Triangle2,BoundaryEdge2,Vertex2> 
+    { 
+    public:
+	Mesh2(const char *); // 
+	Mesh2(int nnv, int nnt, int nnbe, Vertex2 *vv, Triangle2 *tt, BoundaryEdge2 *bb); 
+	const Element * Find( R2 P, R2 & Phat,bool & outside,const Element * tstart) const;
+	int Save(const string & filename);
+	//int Popen(const FILE *namestream);
+	Mesh2(FILE *f);     
+	void GSave(FILE * f) const { return GSave2<Mesh2>(f,*this);}
+	void GRead(FILE * f);
+	
+    private:
+	int load(const string & filename); 
+	Mesh2(const Mesh2 &); // pas de construction par copie
+	void operator=(const Mesh2 &);// pas affectation par copy 
+    };
+    
+}
+
+#endif
+
diff --git a/src/femlib/Mesh3dn.cpp b/src/femlib/Mesh3dn.cpp
new file mode 100644
index 0000000..ee451e5
--- /dev/null
+++ b/src/femlib/Mesh3dn.cpp
@@ -0,0 +1,1414 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 3d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include <fstream>
+#include <iostream>
+#include <cstring>
+#include "libmesh5.h"
+#include "ufunction.hpp"
+#include "error.hpp"
+#include "RNM.hpp"
+namespace Fem2D 
+{
+}
+#include "Mesh2dn.hpp"
+#include "Mesh3dn.hpp"
+#include "rgraph.hpp"
+#include "fem.hpp"
+#include "PlotStream.hpp"
+
+namespace Fem2D 
+{
+  
+  
+  
+  
+  /*
+    const short int v_tet_face[4][3]=  {{3,2,1},{0,2,3},{ 3,1,0},{ 0,1,2}};
+    const short int a_tet_face[4][3]=  {{ 0,1,0},{ 0,2,0},{ 0,3,1},{ 1,2,1}};
+    const bool  sig_tet_face[4][3]=  {{ 0,1,0},{ 1,0,1},{ 0,1,0},{ 1,0,1}};
+    const short int v_tet_edge[6][2]= {{ 1,2},{1,3},{1,4},{2,3},{2,4},{3,4}}; 
+    const short int fadj_tet_edge[6][2]= {{4,3},{2,4},{3,2},{4,1},{1,3},{2,1}};
+    const short int op_tet_edge[6]={ 6, 5, 4, 3, 2, 1};  
+  */
+  
+  //  Attention  nvfaceTet  donnne les faces  les 4 faces de tet telle que la
+  // tel que  le tet forme des trois sommet  + l'autre sommet soit positif.
+  //  donc  le  produit vectoriel des 2 aretes  (0,1) (0,2)  donne une  normale interieur.
+  //  Ok pour les gradients des $\lambda_i$  
+  static const int  nvfaceTet[4][3]  ={{3,2,1}, {0,2,3},{ 3,1,0},{ 0,1,2}}  ;//{ {2,1,3},{0,2,3},{1,0,3},{0,1,2} };
+  static const int  nvedgeTet[6][2] = { {0,1},{0,2},{0,3},{1,2},{1,3},{2,3} };
+  
+  static const int  nvfaceTria[1][3]  = { {0,1,2} };
+  static const int  nvedgeTria[3][2] = { {1,2},{2,0},{0,1}}; 
+  
+  static const int   nvfaceSeg[1][3]  = {{-1,-1,1}};
+  static const int  nvedgeSeg[1][2] = { {0,1} };
+  
+  
+  template<>
+  const int (* const GenericElement<DataTriangle3>::nvface)[3] = nvfaceTria ;
+  template<>
+  const int (* const GenericElement<DataTriangle3>::nvedge)[2] = nvedgeTria ;
+  template<>
+  const int (* const GenericElement<DataTriangle3>::nvadj)[2] = nvedgeTria ;
+  template<> const int  GenericElement<DataTriangle3>::nitemdim[4] = {3,3,1,0 }  ;
+  static const int onWhatIsEdge3[3][7] = {
+    {0,1,3, 2,0,0, 0}, // edge 0 
+    {3,0,1, 0,2,0, 0},
+    {1,3,0, 0,0,2, 0} };
+  
+  template<>
+  const int (* const GenericElement<DataTriangle3>::onWhatBorder)[7] = onWhatIsEdge3 ;
+  
+  
+  template<>
+  const int (* const GenericElement<DataTet>::nvface)[3] = nvfaceTet ;
+  template<>
+  const int (* const GenericElement<DataTet>::nvedge)[2] = nvedgeTet ;
+  template<>
+  const int (* const GenericElement<DataTet>::nvadj)[3] = nvfaceTet ;
+  template<> const int  GenericElement<DataTet>::nitemdim[4] = {4,6,4,1 }  ;
+  
+  int onWhatIsFace[4][15] ; 
+    typedef const int   (*const PtrConst15int) [15]; //  a pointeur on  const arry of 15 int. (to help xcode) 
+ // static const int (* const SetonWhatIsFace(int  onWhatIsFace[4][15] ,const int  nvfaceTet[4][3],const int nvedgeTet[6][2]))[15];
+    static PtrConst15int SetonWhatIsFace(int  onWhatIsFace[4][15] ,const int  nvfaceTet[4][3],const int nvedgeTet[6][2]);
+    
+  template<>
+  const int (* const GenericElement<DataTet>::onWhatBorder)[15] = SetonWhatIsFace(onWhatIsFace,nvfaceTet,nvedgeTet) ;
+  
+  template<> int   GenericMesh<Tet,Triangle3,Vertex3>::kfind=0;
+  template<> int   GenericMesh<Tet,Triangle3,Vertex3>::kthrough=0;
+  
+
+//  const int (* const SetonWhatIsFace(int  onWhatIsFace[4][15] ,const int  nvfaceTet[4][3],const int nvedgeTet[6][2]))[15]
+  PtrConst15int  SetonWhatIsFace(int  onWhatIsFace[4][15] ,const int  nvfaceTet[4][3],const int nvedgeTet[6][2])
+  {
+    for(int i=0;i<15;++i)
+      for(int j=0;j<4;++j)
+	onWhatIsFace[j][i]=0;
+    for(int j=0;j<4;++j)
+      for(int i=0;i<3;++i)
+	onWhatIsFace[j][nvfaceTet[j][i]]=1;
+    for(int j=0;j<4;++j)
+      { 
+	onWhatIsFace[j][j+4+6]=3;
+	int ff[]={0,0,0,0};
+	int jo=1+2+3-nvfaceTet[j][0]-nvfaceTet[j][1]-nvfaceTet[j][2];
+	ff[jo]=1;
+	for(int i=0;i<6;++i)
+	  if(ff[nvedgeTet[i][0]]+ff[nvedgeTet[i][1]]==0)
+	    onWhatIsFace[j][i+4]=2;	
+      }
+    if(0)
+      for(int j=0;j<4;++j)
+	{
+	  for(int i=0;i<15;++i)
+	    cout << onWhatIsFace[j][i] << " ";
+	  cout << endl;
+	}
+    
+    return onWhatIsFace;
+  }
+  void Add(int *p,int n,int o)
+    {
+        for(int i=0;i<n;++i)
+            p[i] += o;
+    }
+  Mesh3::Mesh3(const string  filename)
+  {
+    int ok=load(filename);
+    cout << "read mesh ok " << ok  << endl;
+    cout << ", nt " << nt << ", nv " << nv << " nbe:  = " << nbe << endl;
+    if(ok)
+      {
+	ifstream f(filename.c_str());
+	if(!f) {	
+	  cerr << "  --  Mesh3::Mesh3 Erreur openning " << filename<<endl;ffassert(0);exit(1);}	
+	if(verbosity>2)
+	  cout << "  -- Mesh3:  Read On file \"" <<filename<<"\""<<  endl;
+	if(filename.rfind(".msh")==filename.length()-4) 
+	    readmsh(f,-1);
+        else 
+	    read(f);
+      }
+    
+    BuildBound();
+    if(nt > 0){ 
+      BuildAdj();
+      Buildbnormalv();  
+      BuildjElementConteningVertex();  
+    }
+
+    
+    if(verbosity>2)
+      cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+    if(verbosity)
+      cout << "  -- Mesh3 : "<<filename  << ", d "<< 3  << ", n Tet " << nt << ", n Vtx "
+	   << nv << " n Bord " << nbe << endl;
+      ffassert(mes>=0); // add F. Hecht sep 2009.
+  }
+
+  // Add by J. Morice 11/10
+  // compute the hmin in a 3d mesh 
+  // Remark: on peut le mettre dans generic mesh
+  //         (attention aux boucles sur les arr�tes)
+  double Mesh3::hmin() const{
+    R3 Pinf(1e100,1e100,1e100),Psup(-1e100,-1e100,-1e100);   // Extremit� de la bo�te englobante
+    double hmin=1e10;
+    
+    for (int ii=0;ii< this->nv;ii++){ 
+      R3 P( vertices[ii].x, vertices[ii].y, vertices[ii].z);
+      Pinf=Minc(P,Pinf);
+      Psup=Maxc(P,Psup);     
+    }
+
+    for (int k=0;k<this->nt;k++){
+      for (int e=0;e<6;e++){
+	if( this->elements[k].lenEdge(e) < Norme2(Psup-Pinf)/1e9 )
+	  {
+	    const Tet & K(this->elements[k]);
+	    int iv[4];
+	    for(int jj=0; jj <4; jj++){
+	      iv[jj] = this->operator()(K[jj]);
+	    }
+	    for (int eh=0;eh<6;eh++){
+	      if(verbosity>2) cout << "tetrahedra: " << k << " edge : " << eh << " lenght "<<  this->elements[k].lenEdge(eh) << endl;
+	    }
+	    if(verbosity>2) cout << " A tetrahedra with a very small edge was created " << endl;
+	    
+	    return 1;
+	  }
+	hmin=min(hmin,this->elements[k].lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+      }
+      
+    }
+    
+    for (int k=0;k<this->nbe;k++){
+      for (int e=0;e<3;e++){
+	if( this->be(k).lenEdge(e) < Norme2(Psup-Pinf)/1e9 )
+	  {
+	    for (int eh=0;eh<3;e++){
+	      cout << "triangles: " << k << " edge : " << eh << " lenght "<<  this->be(k).lenEdge(e) << endl;
+	    }
+	      cout << " A triangle with a very small edges was created " << endl;
+	      return 1;
+	  }
+	hmin=min(hmin,this->be(k).lenEdge(e));   // calcul de .lenEdge pour un Mesh3
+      }
+    }
+    ffassert(hmin>Norme2(Psup-Pinf)/1e9);
+    return hmin;
+  } 
+
+
+  // Read a mesh with correct the mesh : 
+  // 1) delete multiple points defined
+  // 2) delete points which is not in element or in border element
+  Mesh3::Mesh3(const string  filename, const long change)
+  {
+   
+    int ok=load(filename);
+    cout << "read mesh ok " << ok  << endl;
+    cout << ", nt " << nt << ", nv " << nv << " nbe:  = " << nbe << endl;
+    if(ok)
+      {
+	ifstream f(filename.c_str());
+	if(!f) {	
+	  cerr << "  --  Mesh3::Mesh3 Erreur openning " << filename<<endl;ffassert(0);exit(1);}	
+	if(verbosity>2)
+	  cout << "  -- Mesh3:  Read On file \"" <<filename<<"\""<<  endl;
+	if(filename.rfind(".msh")==filename.length()-4) 
+	    readmsh(f,-1);
+        else 
+	    read(f);
+      }
+
+    if(change){
+      // verification multiple points
+      double hseuil=hmin();
+      hseuil = hseuil/10;
+      cout << " hseuil = " << hseuil << endl;
+      KN<int> Numero_Som(this->nv);
+      Vertex *vv=new Vertex[this->nv];
+      int nv_t=0;
+      {	
+	R3 Pinf(1e100,1e100,1e100),Psup(-1e100,-1e100,-1e100);
+	for (int ii=0;ii< this->nv;ii++){ 
+	  R3 P( vertices[ii].x, vertices[ii].y, vertices[ii].z);
+	  Pinf=Minc(P,Pinf);
+	  Psup=Maxc(P,Psup);     
+	}
+
+	EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(vv,Pinf,Psup,0);
+	// creation of octree
+	for (int ii=0;ii<this->nv;ii++){
+	  const R3 r3vi( this->vertices[ii].x, this->vertices[ii].y, this->vertices[ii].z );
+	  const Vertex3 &vi(r3vi);
+	  
+	  Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+	  
+	  if(!pvi){
+	    vv[nv_t].x = vi.x;
+	    vv[nv_t].y = vi.y;
+	    vv[nv_t].z = vi.z;
+	    vv[nv_t].lab = this->vertices[ii].lab; // lab mis a zero par default
+	    Numero_Som[ii] = nv_t; 
+	    gtree->Add( vv[nv_t] );
+	    nv_t=nv_t+1;
+	  }
+	  else{
+	    Numero_Som[ii] = pvi-vv;
+	  }
+	}
+	
+	delete gtree;
+	//delete [] vv;
+      }
+
+      // general case
+
+      KN<int> takevertex(nv_t,0);
+      for (int k=0; k<nbe; k++) {
+	const BorderElement & K(this->borderelements[k]);     
+	for(int jj=0; jj<3; jj++){
+	  takevertex[ Numero_Som[this->operator()(K[jj])] ] = 1;
+	}
+      }
+      for(int k=0; k< this->nt; k++){
+	const Element & K(this->elements[k]);
+	for(int jj=0; jj<4; jj++){
+	  takevertex[ Numero_Som[this->operator()(K[jj])] ] = 1;
+	}
+      }
+
+      int newvertex=0;
+      for(int iv=0; iv<nv_t; iv++){
+	newvertex+=takevertex[iv];
+      }
+
+      if( newvertex != this->nv){
+	
+	// determination of vertex
+	Vertex *vvv = new Vertex[ newvertex ];
+	KN<int> newNumero_Som(nv_t);
+	int iii=0;
+	for(int iv=0;  iv< nv_t; iv++){
+	  if( takevertex[iv ] == 1  ){
+	     vvv[iii].x = vv[iv].x;
+	     vvv[iii].y = vv[iv].y;
+	     vvv[iii].z = vv[iv].z;
+	     vvv[iii].lab = vv[iv].lab; // lab mis a zero par default
+	     newNumero_Som[iv] = iii;
+	     iii++;
+	  }
+	}
+	ffassert( newvertex== iii );
+	
+	Element *tt;
+	if(this->nt !=0) tt=new Element[this->nt];
+	BorderElement *bb = new BorderElement[this->nbe];
+
+	Element *ttt=tt;
+	BorderElement *bbb=bb;
+
+	for (int k=0; k<this->nbe; k++) {
+	  const BorderElement & K(this->borderelements[k]);    
+	  int iv[3];
+	  for(int jj=0; jj<3; jj++){
+	    iv[jj] = Numero_Som[this->operator()(K[jj])];
+	    iv[jj] = newNumero_Som[iv[jj]];
+	  }
+	  (bbb++)->set(vvv,iv,K.lab);
+	}
+
+	for(int k=0; k< this->nt; k++){
+	  const Element & K(this->elements[k]);
+	  int iv[4];
+	  for(int jj=0; jj<4; jj++){
+	    iv[jj] = Numero_Som[this->operator()(K[jj])];
+	    iv[jj] = newNumero_Som[iv[jj]];
+	  }
+	  (ttt++)->set(vvv,iv,K.lab);
+	}
+	cout << " delete vertices + autre " << endl;
+	delete [] vertices;
+	delete [] elements;
+	delete [] borderelements;
+	
+	nv = newvertex;
+
+       	vertices = vvv;
+	elements = tt;
+	borderelements = bb;
+
+        //&this = new Mesh3(newvertex,this->nt,this-nbe,vvv,tt,bb);
+	
+	delete [] newNumero_Som;
+      }
+      else{
+	cout << " no need to change the mesh " << endl;
+      }
+      delete [] Numero_Som;
+    }
+    
+    BuildBound();
+    if(nt > 0){ 
+      BuildAdj();
+      Buildbnormalv();  
+      BuildjElementConteningVertex();  
+    }
+      
+    if(verbosity>2)
+      cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+    if(verbosity)
+      cout << "  -- Mesh3 : "<<filename  << ", d "<< 3  << ", n Tet " << nt << ", n Vtx "
+	   << nv << " n Bord " << nbe << endl;
+      ffassert(mes>=0); // add F. Hecht sep 2009.
+  }
+   // Fin Add by J. Morice nov 2010
+   // Add J. Morice 12/2010
+   void Mesh3::TrueVertex() 
+	{
+			// verification multiple points
+		double hseuil=hmin();
+		hseuil =hseuil/10;
+		cout << " hseuil = " << hseuil << endl;
+		KN<int> Numero_Som(this->nv);
+		Vertex *vv=new Vertex[this->nv];
+		int nv_t=0;
+		{	
+			R3 Pinf(1e100,1e100,1e100),Psup(-1e100,-1e100,-1e100);
+			for (int ii=0;ii< this->nv;ii++){ 
+				R3 P( vertices[ii].x, vertices[ii].y, vertices[ii].z);
+				Pinf=Minc(P,Pinf);
+				Psup=Maxc(P,Psup);     
+			}
+			
+			EF23::GTree<Vertex3> *gtree = new EF23::GTree<Vertex3>(vv,Pinf,Psup,0);
+			// creation of octree
+			for (int ii=0;ii<this->nv;ii++){
+				const R3 r3vi( this->vertices[ii].x, this->vertices[ii].y, this->vertices[ii].z );
+				const Vertex3 &vi(r3vi);
+				
+				Vertex3 * pvi=gtree->ToClose(vi,hseuil);
+				
+				if(!pvi){
+					vv[nv_t].x = vi.x;
+					vv[nv_t].y = vi.y;
+					vv[nv_t].z = vi.z;
+					vv[nv_t].lab = this->vertices[ii].lab; // lab mis a zero par default
+					Numero_Som[ii] = nv_t; 
+					gtree->Add( vv[nv_t] );
+					nv_t=nv_t+1;
+				}
+				else{
+					Numero_Som[ii] = pvi-vv;
+				}
+			}
+			
+			delete gtree;
+			//delete [] vv;
+		}
+		
+		// general case
+		
+		KN<int> takevertex(nv_t,0);
+		for (int k=0; k<nbe; k++) {
+			const BorderElement & K(this->borderelements[k]);     
+			for(int jj=0; jj<3; jj++){
+				takevertex[ Numero_Som[this->operator()(K[jj])] ] = 1;
+			}
+		}
+		for(int k=0; k< this->nt; k++){
+			const Element & K(this->elements[k]);
+			for(int jj=0; jj<4; jj++){
+				takevertex[ Numero_Som[this->operator()(K[jj])] ] = 1;
+			}
+		}
+		
+		int newvertex=0;
+		for(int iv=0; iv<nv_t; iv++){
+			newvertex+=takevertex[iv];
+		}
+		
+		if( newvertex != this->nv){
+			
+			// determination of vertex
+			Vertex *vvv = new Vertex[ newvertex ];
+			KN<int> newNumero_Som(nv_t);
+			int iii=0;
+			for(int iv=0;  iv< nv_t; iv++){
+				if( takevertex[iv ] == 1  ){
+					vvv[iii].x = vv[iv].x;
+					vvv[iii].y = vv[iv].y;
+					vvv[iii].z = vv[iv].z;
+					vvv[iii].lab = vv[iv].lab; // lab mis a zero par default
+					newNumero_Som[iv] = iii;
+					iii++;
+				}
+			}
+			ffassert( newvertex== iii );
+			
+			Element *tt;
+			if(this->nt !=0) tt=new Element[this->nt];
+			BorderElement *bb = new BorderElement[this->nbe];
+			
+			Element *ttt=tt;
+			BorderElement *bbb=bb;
+			
+			for (int k=0; k<this->nbe; k++) {
+				const BorderElement & K(this->borderelements[k]);    
+				int iv[3];
+				for(int jj=0; jj<3; jj++){
+					iv[jj] = Numero_Som[this->operator()(K[jj])];
+					iv[jj] = newNumero_Som[iv[jj]];
+				}
+				(bbb++)->set(vvv,iv,K.lab);
+			}
+			
+			for(int k=0; k< this->nt; k++){
+				const Element & K(this->elements[k]);
+				int iv[4];
+				for(int jj=0; jj<4; jj++){
+					iv[jj] = Numero_Som[this->operator()(K[jj])];
+					iv[jj] = newNumero_Som[iv[jj]];
+				}
+				(ttt++)->set(vvv,iv,K.lab);
+			}
+			cout << " delete vertices + autre " << endl;
+			delete [] vertices;
+			delete [] elements;
+			delete [] borderelements;
+			
+			nv = newvertex;
+			
+			vertices = vvv;
+			elements = tt;
+			borderelements = bb;
+			
+			//&this = new Mesh3(newvertex,this->nt,this-nbe,vvv,tt,bb);
+			
+			delete [] newNumero_Som;
+		}
+		else{
+			cout << " no need to change the mesh " << endl;
+		}
+		delete [] Numero_Som;
+    
+    
+		BuildBound();
+		if(nt > 0){ 
+			BuildAdj();
+			Buildbnormalv();  
+			BuildjElementConteningVertex();  
+		}
+	
+		if(verbosity>2)
+			cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+			if(verbosity)
+				cout << "  -- Mesh3 :  d "<< 3  << ", n Tet " << nt << ", n Vtx "
+				<< nv << " n Bord " << nbe << endl;
+			ffassert(mes>=0); // add F. Hecht sep 2009.
+	}
+	
+  // Fin Add J. Morice 12/2010
+	
+  void  Mesh3::read(istream &f)
+  { // read the mesh
+    int i;
+    //	f >> nv >> nt >> neb ;
+    string str;
+    int err=0;
+    while(!f.eof())
+      {
+	f >> str;
+	//cout << str << endl;
+	if( str== "Vertices") 
+	  {
+	    f >> nv;
+	    assert(!this->vertices );
+	    if(verbosity>2)
+	      cout << "  -- Nb of Vertex " << nv << endl;
+	    this->vertices = new Vertex[nv];
+	    for (i=0;i<nv;i++)    
+	      {
+		f >> this->vertices[i];
+		assert(f.good());
+	      }
+	  }
+	else if (str=="Tetrahedra")
+	  {
+	    f >> nt;
+	    assert(this->vertices && !this->elements);
+	    this->elements = new Element [nt];
+	    mes=0;
+	    assert(this->elements);
+	    if(verbosity>2)
+	      cout <<   "  -- Nb of Elements " << nt << endl;
+	    for (int i=0;i<nt;i++) 
+	      { 
+		this->t(i).Read1(f,this->vertices,this->nv);
+                if(this->t(i).mesure()<=0) err++; // Modif FH nov 2014
+		mes += this->t(i).mesure();
+                }
+	  }
+	else if (str=="Triangles")
+	  {
+	    mesb=0;
+	    int kmv=0,ij;
+	    f >> nbe;
+	    assert(vertices);
+	    this->borderelements = new BorderElement[nbe];
+	    if(verbosity>2)
+	      cout <<   "  -- Nb of border Triangles " << nbe << endl;
+	    for (i=0;i<nbe;i++) 
+	      { 
+		this->be(i).Read1(f,this->vertices,this->nv); 
+		mesb += this->be(i).mesure();
+		for(int j=0;j<3;++j)
+		  if(!vertices[ij=this->be(i,j)].lab)
+		    {
+		      vertices[ij].lab=1;
+		      kmv++;
+		    }
+	      }
+	  }
+	else if(str[0]=='#')
+	  {// on mange la ligne 
+	    int c; 
+	    while ( (c=f.get()) != '\n' &&  c != EOF) 
+	      //cout << c << endl;
+	      ;
+	  }
+      }
+    assert( (nt >= 0 || nbe>=0)  && nv>0) ;
+    /*   done at up level ... 
+	 BuildBound();
+	 
+	 if(nt > 0){ 
+	 BuildAdj();
+	 Buildbnormalv();  
+	 BuildjElementConteningVertex();  
+	 }
+    */
+    if(err!=0)
+    {
+        cerr << " Mesh3::read: sorry bad mesh. Number of negative Tet " << err << endl;
+        this->~Mesh3();
+        ffassert(0);
+    }
+  }
+  
+  int Mesh3::load(const string & filename)
+  {
+    
+    int bin;
+    int ver,inm,dim;
+    int lf=filename.size()+20;
+    KN<char>  fileb(lf),filef(lf);
+    char *data = new char[filename.size()+1];
+    size_t ssize = filename.size()+1;
+    char *ptr;
+    char *pfile;
+
+    strncpy( data, filename.c_str(),ssize);
+    
+    ptr = strstr(data,".mesh");
+    if( !ptr ){
+      strcpy(filef,filename.c_str());
+      strcpy(fileb,filef);
+      strcat(filef,".mesh");
+      strcat(fileb,".meshb");
+      if( (inm=GmfOpenMesh(pfile=fileb, GmfRead,&ver,&dim)) ) 
+	bin=true;
+      else if( (inm=GmfOpenMesh(pfile=filef, GmfRead,&ver,&dim)) ) 
+	bin=false;
+      else 
+	if(verbosity>5){
+	  cerr << " Erreur ouverture file " << (char *) fileb  << " " << (char *) filef  <<endl;
+	  return   1;
+	}
+    }
+    else{
+      if( !(inm=GmfOpenMesh(data, GmfRead,&ver,&dim)) ){
+	if(verbosity>5)
+	  cerr << " Erreur ouverture file " << (char *) data  << endl;
+	return   1;
+      }
+    }
+    
+    int nv=-1,nt=-1,neb=-1;
+    nv = GmfStatKwd(inm,GmfVertices);
+    nt = GmfStatKwd(inm,GmfTetrahedra);
+    neb= GmfStatKwd(inm,GmfTriangles);
+    this->set(nv,nt,neb);
+    if(verbosity>1)
+      cout << "  -- Mesh3(load): "<< (char *) data <<", ver " << ver << ", d "<< dim  
+	   << ", nt " << nt << ", nv " << nv << " nbe:  = " << nbe << endl;
+    if(dim  != 3) { 
+      cerr << "Err dim == " << dim << " !=3 " <<endl;
+      return 2; }
+    if( nv<=0 && (nt <0 || nbe <=0)  ) {
+      cerr << " missing data "<< endl;
+      return 3;
+    }
+    int iv[4],lab;
+    float cr[3];
+    // read vertices 
+    GmfGotoKwd(inm,GmfVertices);
+    int mxlab=0;
+    int mnlab=0;
+    for(int i=0;i<nv;++i)
+      {  
+	if(ver<2) {
+	  GmfGetLin(inm,GmfVertices,&cr[0],&cr[1],&cr[2],&lab);
+	  vertices[i].x=cr[0];
+	  vertices[i].y=cr[1];
+	  vertices[i].z=cr[2];}
+	else
+	  GmfGetLin(inm,GmfVertices,&vertices[i].x,&vertices[i].y,&vertices[i].z,&lab);	    
+	vertices[i].lab=lab;
+	
+	mxlab= max(mxlab,lab);
+	mnlab= min(mnlab,lab);
+      }
+    
+    
+    //    /* read mesh triangles */
+    if(nbe > 0) {
+      if(mnlab==0 && mxlab==0 )
+	{
+	  int kmv=0;
+	  mesb=0;
+	  GmfGotoKwd(inm,GmfTriangles);
+	  for(int i=0;i<nbe;++i)
+	    {  
+	      GmfGetLin(inm,GmfTriangles,&iv[0],&iv[1],&iv[2],&lab);
+	      for(int j=0;j<3;++j)
+		if(!vertices[iv[j]-1].lab)
+		  {
+		    vertices[iv[j]-1].lab=1;
+		    kmv++;
+		  }
+	      for (int j=0;j<3;++j)  
+		iv[j]--;
+	      this->be(i).set(this->vertices,iv,lab);
+	      mesb += this->be(i).mesure();
+	    }
+	  
+	  if(kmv&& verbosity>1)
+	    cout << "    Aucun label Hack (FH)  ??? => 1 sur les triangle frontiere "<<endl;
+	}
+      else
+	{
+	  mesb=0;
+	  GmfGotoKwd(inm,GmfTriangles);
+	  for(int i=0;i<nbe;++i)
+	    {  
+	      GmfGetLin(inm,GmfTriangles,&iv[0],&iv[1],&iv[2],&lab);
+	      for (int j=0;j<3;++j)  
+		iv[j]--;
+	      this->be(i).set(this->vertices,iv,lab);
+	      mesb += this->be(i).mesure();
+	    }
+	}
+    }
+    
+    if(nt>0)
+      {
+	/* read mesh tetrahedra */
+	GmfGotoKwd(inm,GmfTetrahedra);
+	for(int i=0;i<nt;++i)
+	  {  
+	    GmfGetLin(inm,GmfTetrahedra,&iv[0],&iv[1],&iv[2],&iv[3],&lab);
+	    assert( iv[0]>0 && iv[0]<=nv && iv[1]>0 && iv[1]<=nv && iv[2]>0 && iv[2]<=nv && iv[3]>0 && iv[3]<=nv);
+	    for (int j=0;j<4;j++) iv[j]--;
+	    this->elements[i].set(vertices,iv,lab); 
+	    mes += this->elements[i].mesure();	    
+	  }
+      }
+    GmfCloseMesh(inm);  
+    return 0; // OK
+  }
+  
+const     string Gsbegin="Mesh3::GSave v0",Gsend="end";  
+  void Mesh3::GSave(FILE * ff,int offset) const
+  {  
+    PlotStream f(ff);
+    
+    f <<  Gsbegin ;
+    f << nv << nt << nbe;
+    for (int k=0; k<nv; k++) {
+      const  Vertex & P = this->vertices[k];		
+      f << P.x <<P.y << P.z << P.lab ;
+    }
+    
+    if(nt != 0){
+      
+      for (int k=0; k<nt; k++) {
+	const Element & K(this->elements[k]);
+	int i0=this->operator()(K[0])+offset;
+	int i1=this->operator()(K[1])+offset;
+	int i2=this->operator()(K[2])+offset;
+	int i3=this->operator()(K[3])+offset;
+    
+	int lab=K.lab;
+	f << i0 << i1 << i2 << i3 << lab;
+      }
+    }
+    
+    
+    for (int k=0; k<nbe; k++) {
+      const BorderElement & K(this->borderelements[k]);
+      int i0=this->operator()(K[0])+offset;
+      int i1=this->operator()(K[1])+offset;
+      int i2=this->operator()(K[2])+offset;
+      int lab=K.lab;
+      f << i0 << i1 << i2  << lab;
+    }
+    f << Gsend;
+  }
+	      
+   Mesh3::Mesh3(const  Serialize &serialized)
+   :GenericMesh<Tet,Triangle3,Vertex3> (serialized) 
+    {
+	BuildBound();
+	if(verbosity>1)
+	    cout << "  -- End of serialized: mesure = " << mes << " border mesure " << mesb << endl;  
+	
+	if(nt > 0){ 
+	    BuildAdj();
+	    Buildbnormalv();  
+	    BuildjElementConteningVertex();  
+	}
+	
+	if(verbosity>1)
+	    cout << "  -- Mesh3  (serialized), d "<< 3  << ", n Tet " << nt << ", n Vtx "
+	    << nv << " n Bord " << nbe << endl;
+	ffassert(mes>=0); // add F. Hecht sep 2009.
+
+    }
+  Mesh3::Mesh3(FILE *f,int offset)
+  {
+    
+    GRead(f,offset);// remove 1 
+    assert( (nt >= 0 || nbe>=0)  && nv>0) ;
+    BuildBound();
+    if(verbosity>2)
+      cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+    
+    if(nt > 0){ 
+      BuildAdj();
+      Buildbnormalv();  
+      BuildjElementConteningVertex();  
+    }
+    if(verbosity>2)
+	  cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+    
+    if(verbosity>1)
+      cout << "  -- Mesh3  (File *), d "<< 3  << ", n Tet " << nt << ", n Vtx "
+	   << nv << " n Bord " << nbe << endl;
+      ffassert(mes>=0); // add F. Hecht sep 2009.
+  }
+  
+  void Mesh3::GRead(FILE * ff,int offset)
+  {  
+    PlotStream f(ff);
+    string s;
+    f >> s;
+    ffassert( s== Gsbegin);
+    f >> nv >> nt >> nbe;
+    if(verbosity>2)
+    cout << " GRead : nv " << nv << " " << nt << " " << nbe << endl;
+    this->vertices = new Vertex[nv];
+    this->elements = new Element [nt];
+    this->borderelements = new BorderElement[nbe];		
+    for (int k=0; k<nv; k++) {
+      Vertex & P = this->vertices[k];
+      f >> P.x >>P.y >> P.z >> P.lab ;
+    }
+    mes=0.;
+    mesb=0.;
+    
+    if(nt != 0)
+      {
+	
+	for (int k=0; k<nt; k++) {
+	  int i[4],lab;
+	  Element & K(this->elements[k]);
+	  f >> i[0] >> i[1] >> i[2] >> i[3] >> lab;
+      Add(i,4,offset);  
+	  K.set(this->vertices,i,lab);
+	  mes += K.mesure();	    
+	  
+	}
+      }
+    
+    
+    for (int k=0; k<nbe; k++) {
+      int i[4],lab;
+      BorderElement & K(this->borderelements[k]);
+      f >> i[0] >> i[1] >> i[2]  >> lab;
+      Add(i,3,offset);  
+      K.set(this->vertices,i,lab);
+      mesb += K.mesure();	    
+      
+    }
+    f >> s;
+    ffassert( s== Gsend);
+  }
+    void Mesh3::readmsh(ifstream & f,int offset)
+    {  
+        int err=0;
+	f >> nv >> nt >> nbe;
+	if(verbosity>2)
+	    cout << " GRead : nv " << nv << " " << nt << " " << nbe << endl;
+	this->vertices = new Vertex[nv];
+	this->elements = new Element [nt];
+	this->borderelements = new BorderElement[nbe];		
+	for (int k=0; k<nv; k++) {
+	    Vertex & P = this->vertices[k];
+	    f >> P.x >>P.y >> P.z >> P.lab ;
+	}
+	mes=0.;
+	mesb=0.;
+	
+	if(nt != 0)
+	  {
+	      
+	      for (int k=0; k<nt; k++) {
+		  int i[4],lab;
+		  Element & K(this->elements[k]);
+		  f >> i[0] >> i[1] >> i[2] >> i[3] >> lab;
+                  Add(i,4,offset);
+		  K.set(this->vertices,i,lab);
+		  mes += K.mesure();
+                  err += K.mesure() <0;
+		  
+	      }
+	  }
+	
+	
+	for (int k=0; k<nbe; k++) {
+	    int i[4],lab;
+	    BorderElement & K(this->borderelements[k]);
+	    f >> i[0] >> i[1] >> i[2]  >> lab;
+            Add(i,3,offset);
+	    K.set(this->vertices,i,lab);
+	    mesb += K.mesure();	    
+	    
+	}
+        if(err!=0)
+        {
+            cerr << " Mesh3::readmsh : sorry bad mesh. Number of negative Tet " << err << endl;
+            this->~Mesh3();
+            ffassert(0);
+        }
+
+    }
+    
+  
+  
+  int Mesh3::Save(const string & filename) const
+  {
+    int ver = GmfFloat, outm;
+    if ( !(outm = GmfOpenMesh(filename.c_str(),GmfWrite,ver,3)) ) {
+      cerr <<"  -- Mesh3::Save  UNABLE TO OPEN  :"<< filename << endl;
+      return(1);
+    }
+    
+    float fx,fy,fz;
+    GmfSetKwd(outm,GmfVertices,this->nv);
+    for (int k=0; k<nv; k++) {
+      const  Vertex & P = this->vertices[k];
+      GmfSetLin(outm,GmfVertices,fx=P.x,fy=P.y,fz=P.z,P.lab);
+    }
+    
+    if(nt != 0){
+      GmfSetKwd(outm,GmfTetrahedra,nt);
+      for (int k=0; k<nt; k++) {
+	const Element & K(this->elements[k]);
+	int i0=this->operator()(K[0])+1;
+	int i1=this->operator()(K[1])+1;
+	int i2=this->operator()(K[2])+1;
+	int i3=this->operator()(K[3])+1;
+	int lab=K.lab;
+	GmfSetLin(outm,GmfTetrahedra,i0,i1,i2,i3,lab);
+      }
+    }
+    
+    GmfSetKwd(outm,GmfTriangles,nbe);
+    for (int k=0; k<nbe; k++) {
+      const BorderElement & K(this->borderelements[k]);
+      int i0=this->operator()(K[0])+1;
+      int i1=this->operator()(K[1])+1;
+      int i2=this->operator()(K[2])+1;
+      int lab=K.lab;
+      GmfSetLin(outm,GmfTriangles,i0,i1,i2,lab);
+    }
+    
+    GmfCloseMesh(outm);
+    return (0);
+    
+  }
+
+   int Mesh3::SaveSurface(const string & filename) const
+  {
+    int ver = GmfFloat, outm;
+    if ( !(outm = GmfOpenMesh(filename.c_str(),GmfWrite,ver,3)) ) {
+      cerr <<"  -- Mesh3::Save  UNABLE TO OPEN  :"<< filename << endl;
+      return(1);
+    }
+
+    // Number of Vertex in the surface
+    int *v_num_surf=new int[nv];
+    int *liste_v_num_surf=new int[nv];
+    for (int k=0; k<nv; k++){ 
+      v_num_surf[k]=-1;
+      liste_v_num_surf[k]=0;
+    }
+    // Search Vertex on the surface
+    int nbv_surf=0;
+    for (int k=0; k<nbe; k++) {
+      const BorderElement & K(this->borderelements[k]);     
+      for(int jj=0; jj<3; jj++){
+	int i0=this->operator()(K[jj]);
+	if( v_num_surf[i0] == -1 ){
+	  v_num_surf[i0] = nbv_surf;
+	  liste_v_num_surf[nbv_surf]= i0;
+	  nbv_surf++;
+	}
+      }
+    }
+
+    float fx,fy,fz;
+    GmfSetKwd(outm,GmfVertices,nbv_surf);
+    for (int k=0; k<nbv_surf; k++) {
+      int k0 = liste_v_num_surf[k];
+      const  Vertex & P = this->vertices[k0];
+      GmfSetLin(outm,GmfVertices,fx=P.x,fy=P.y,fz=P.z,P.lab);
+    }
+    
+    GmfSetKwd(outm,GmfTriangles,nbe);
+    for (int k=0; k<nbe; k++) {
+      const BorderElement & K(this->borderelements[k]);
+      int i0=v_num_surf[this->operator()(K[0])]+1;
+      int i1=v_num_surf[this->operator()(K[1])]+1;
+      int i2=v_num_surf[this->operator()(K[2])]+1;
+      int lab=K.lab;
+
+      assert( i0-1 < nbv_surf &&  i1-1 < nbv_surf &&  i2-1 < nbv_surf );
+      assert( 0<i0 && 0<i1 && 0<i2 );
+
+      GmfSetLin(outm,GmfTriangles,i0,i1,i2,lab);
+    }
+    
+    GmfCloseMesh(outm);
+
+    delete [ ] v_num_surf;
+    delete [ ] liste_v_num_surf;
+
+    return (0); 
+  }
+
+
+  int Mesh3::SaveSurface(const string & filename1,const string & filename2) const
+  {    
+    // Number of Vertex in the surface
+    int *v_num_surf=new int[nv];
+    int *liste_v_num_surf=new int[nv];
+    for (int k=0; k<nv; k++){ 
+      v_num_surf[k]=-1;
+      liste_v_num_surf[k]=0;
+    }
+    // Search Vertex on the surface
+    int nbv_surf=0;
+    for (int k=0; k<nbe; k++) {
+      const BorderElement & K(this->borderelements[k]);     
+      for(int jj=0; jj<3; jj++){
+	int i0=this->operator()(K[jj]);
+	if( v_num_surf[i0] == -1){
+	  v_num_surf[i0] = nbv_surf;
+	  nbv_surf++;
+	}
+      }
+    }
+
+    // file .points
+    FILE *fpoints = fopen(filename1.c_str(),"w");
+    fprintf(fpoints,"%i\n",nbv_surf);
+    
+    for (int k=0; k<nbv_surf; k++) {
+      //int k0 = liste_v_num_surf[k];
+      const  Vertex & P = this->vertices[k];
+      fprintf(fpoints,"%f %f %f %i\n",P.x,P.y,P.z,P.lab);
+    }
+    fclose(fpoints);
+    
+    // file .faces
+    FILE *ffaces = fopen(filename2.c_str(),"w");
+    fprintf(ffaces,"%i\n",nbe);
+    for (int k=0; k<nbe; k++) {
+      const BorderElement & K(this->borderelements[k]);
+      int i0=this->operator()(K[0]);
+      int i1=this->operator()(K[1]);
+      int i2=this->operator()(K[2]);
+      int lab=K.lab;
+      int label0= this->vertices[i0].lab; 
+      int label1= this->vertices[i1].lab; 
+      int label2= this->vertices[i2].lab;
+      //GmfSetLin(outm,GmfTriangles,i0,i1,i2,lab);
+      int nature=3;
+      int i0v=v_num_surf[i0]+1;
+      int i1v=v_num_surf[i1]+1;
+      int i2v=v_num_surf[i2]+1;
+      assert( i0v-1 < nbv_surf &&  i1v-1 < nbv_surf &&  i2v-1 < nbv_surf );
+      assert( 0<i0v && 0<i1v && 0<i2v );
+
+      fprintf(ffaces,"%i %i %i %i %i %i %i %i\n", nature, i0v, i1v, i2v, lab, label0, label1, label2);
+    }
+    fclose(ffaces);
+    
+    delete [ ] v_num_surf;
+    delete [ ] liste_v_num_surf;
+    return (0);  
+  }
+
+
+  Mesh3::Mesh3(int nnv, int nnt, int nnbe, Vertex3 *vv, Tet *tt, Triangle3 *bb)
+  {
+  
+    nv = nnv;
+    nt = nnt;
+    nbe =nnbe;
+    
+    vertices = vv;
+    elements = tt;
+    borderelements = bb;
+    
+    mes=0.;
+    mesb=0.;
+    
+    for (int i=0;i<nt;i++)  
+      mes += this->elements[i].mesure();
+    
+    for (int i=0;i<nbe;i++)  
+      mesb += this->be(i).mesure();  
+    
+//  Add FH to be consitant we all constructor ...  July 09
+      BuildBound();
+      if(nt > 0){ 
+	  BuildAdj();
+	  Buildbnormalv();  
+	  BuildjElementConteningVertex();  
+      }
+//  end add       
+      if(verbosity>1)
+	  cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+          
+//    if(verbosity>1)
+//      cout << "  -- End of read: mesure = " << mes << " border mesure " << mesb << endl;  
+      assert(mes>=0.);
+  }
+  
+  Mesh3::Mesh3(int nnv, int nnbe, Vertex3 *vv, Triangle3 *bb)
+  {
+  
+    nv = nnv;
+    nbe =nnbe;
+    
+    vertices = vv;
+    borderelements = bb;
+    
+    mes=0.;
+    mesb=0.;
+    
+    for (int i=0;i<nbe;i++)  
+      mesb += this->be(i).mesure();  
+
+//  Add FH to be consitant we all constructor ...  July 09
+      BuildBound();
+      if(nt > 0){ 
+	  BuildAdj();
+	  Buildbnormalv();  
+	  BuildjElementConteningVertex();  
+      }
+//  end add       
+      
+    if(verbosity>1)
+      cout << "  -- End of Construct  mesh3: mesure = " << mes << " border mesure " << mesb <<  endl;  
+      ffassert(mes>=0); // add F. Hecht sep 2009.
+  }
+
+  void Mesh3::flipSurfaceMesh3(int surface_orientation)
+  {
+    /* inverse the orientation of the surface if necessary*/
+    /* and control that all surfaces are oriented in the same way*/
+    int nbflip=0;
+    for (int i=0;i<this->nbe;i++)
+      { 
+	double mes_triangle3= this->be(i).mesure();
+	
+	if( surface_orientation*mes_triangle3 < 0){
+	  const Triangle3 &K( this->be(i) );
+	  int iv[3];       
+	  
+	  iv[0] = this->operator()(K[0]);
+	  iv[1] = this->operator()(K[1]);
+	  iv[2] = this->operator()(K[2]);
+	  
+	  int iv_temp=iv[1];
+	  iv[1]=iv[2];
+	  iv[2]=iv_temp;
+	  this->be(i).set( this->vertices, iv, K.lab ) ;
+	  nbflip++;
+	}
+      }
+    assert(nbflip==0 || nbflip== this->nbe); 
+  }
+
+
+  int  signe_permutation(int i0,int i1,int i2,int i3)
+  {
+    int p=1;
+    if(i0>i1) Exchange(i0,i1), p = -p;
+    if(i0>i2) Exchange(i0,i2), p = -p;
+    if(i0>i3) Exchange(i0,i3), p = -p;
+    if(i1>i2) Exchange(i1,i2), p = -p;
+    if(i1>i3) Exchange(i1,i3), p = -p;
+    if(i2>i3) Exchange(i2,i3), p = -p;
+    return p;
+  }
+
+
+  int  WalkInTet(const Mesh3 & Th,int it, R3 & Phat,const R3 & U, R & dt)
+  {
+    bool ddd=verbosity>200;
+      bool nomove=true;
+    R lambda[4];
+    Phat.toBary(lambda);
+    if(ddd) cout << "\n\n\n   WT: "  << Phat << " :  "  << lambda[0] << " " <<lambda[1] <<" " <<lambda[2] << " " <<lambda[3] << " u = "<< U << " dt " << dt <<endl;
+#ifndef NDEBUG      
+      for(int i=0;i<4;++i)
+      assert(lambda[i]<1.000001 && lambda[i]>-0.0000001);
+#endif
+    typedef R3 Rd;
+    const Mesh3::Element & T(Th[it]);
+    const int nve = 4;
+    const Rd  Q[nve]={(const R3) T[0],(const R3) T[1],(const R3) T[2],(const R3) T[3]};
+    
+    Rd P  =T(Phat);
+    
+    //  cout << " " << u << " " << v ;
+    Rd PF = P + U*dt;
+    
+    //  couleur(15);MoveTo( P); LineTo( PF);
+    R l[nve];
+    double Det=T.mesure()*6;
+    l[0] = det(PF  ,Q[1],Q[2],Q[3]);
+    l[1] = det(Q[0],PF  ,Q[2],Q[3]); 
+    l[2] = det(Q[0],Q[1],PF  ,Q[3]); 
+    l[3] = Det - l[0]-l[1]-l[2];
+    l[0] /= Det;
+    l[1] /= Det;
+    l[2] /= Det;
+    l[3] /= Det;
+     if(ddd)  cout << "\t\t\tWT " << it << ", " << Phat << ",  PF=" << PF
+		   << " :  "  << l[0] << " " <<l[1] <<" " <<l[2] << " " <<l[3] 
+	           << " == " << det(Q[0],Q[1],Q[2],PF)/Det
+		   << " : l (in) "  << lambda[0] << " " <<lambda[1] <<" " <<lambda[2] << " " <<lambda[3] 
+		   << " PF= K(l) = " << Th[it](R3(l+1)) 
+		   <<endl ;
+		  
+    const R eps = 1e-8;
+    int neg[nve],k=0;
+    int kk=-1;
+    if (l[0]>-eps && l[1]>-eps && l[2]>-eps && l[3]>-eps) 
+      {
+	dt =0;
+	Phat=R3(l+1);
+	nomove=false;
+	return -1;
+      }
+    else 
+      {
+	// on regarde de les reelement negatif 
+        // on ne veut pas des points sur les faces.
+        // car sinon il va y avoir un probleme ans on va projete sur la face
+	//  et remettre le point dans le tetraedre.
+	if (l[0]<=-eps ) neg[k++]=0;
+	if (l[1]<=-eps ) neg[k++]=1;
+	if (l[2]<=-eps ) neg[k++]=2;
+	if (l[3]<=-eps ) neg[k++]=3;
+	
+	//R eps1 = T.mesure()   * 1.e-5;
+	   if(ddd)  cout << " k= " << k << endl;
+    
+	if (k==3) //  3 face de sortie possible 
+	  {
+	    // let j be the vertex beetween the 3 faces 
+	    int j = 6-neg[0]-neg[1]-neg[2]; //  sommet intersection des 3 faces.
+	    int i0 = Tet::nvface[j][0];
+	    int i1 = Tet::nvface[j][1];
+	    int i2 = Tet::nvface[j][2];
+	     if(ddd)  cout << "  -------- " << j << " " << i0 << " " << i1 << " " << i2  << endl;
+	    //  le tet i0,i1,i2,j est positif. 
+	    assert(signe_permutation(i0,i1,i2,j)==1);
+	    // 
+	    R v0= det(Q[i0],Q[j],P,PF); 
+	    R v1= det(Q[i1],Q[j],P,PF); 
+	    R v2= det(Q[i2],Q[j],P,PF); 
+	     if(ddd)   cout << "\t\t\t " << j << " v0123 =" << v0 << " "<< v1 << " " << v2 << endl;
+	    if( v0 > eps && v1 < -eps ) 
+	      kk= i1 ;// on sort par la face j i0, j1
+	    else if( v1 > eps && v2 < -eps ) 
+	      kk= i0 ;
+	    else if( v2 > eps && v0 < -eps ) 
+	      kk= i1 ;
+	    else 
+	      {  // on ne sort pas par une face 
+		int nul[3], nn=0, mm=3;
+		  if (Abs(v0) <=eps) nul[nn++]=i0; else nul[--mm]=i0;
+		  if (Abs(v1) <=eps) nul[nn++]=i1; else nul[--mm]=i1;
+		  if (Abs(v2) <=eps) nul[nn++]=i2; else nul[--mm]=i2;
+		assert(nn>0); 
+		if(nn == 1) // on sort par l'arete nul[0] entre le face   nul[1] et nul[2]
+		  kk =  nul[1+(rand()/(RAND_MAX/2))%2];		  
+		else // on sort par le sommet j.  on choisi la face alleatoirement 
+		  kk = nul[(rand()/(RAND_MAX/3))%3];
+		  
+	      }
+	  }
+	else if (k==2)
+	  {
+	    //  numero des l'arete entre les 2 faces
+	    int i0=neg[0],i1=neg[1];
+	    int e = i0 + i1 - (i0==0); 
+	    // on a:
+	    //   e      =     0        1       2      3        4      5
+	    //  (i0,i1) =   (0,1)  , (0,2), (0,3) , (1,2)  , (1,3), (2,3) 
+	    // avec i0,i1 sont les sommets qui ne sont pas dans l'arete
+	    int   jj0[6] = {2,3,1,0,2,0};
+	    int   jj1[6] = {3,1,2,3,0,1};
+	    int j0 = jj0[e];
+	    int j1 = jj1[e];
+	     if(ddd)   cout << " e " << e << " i0 " << i0 << " " << i1 << " j0 =" << j0 << " " << j1 << endl;
+	    // le tet  j0,j1,i0,i1  doit est positif (ie. la pemutation est positive)
+	    // de meme  i0,i1,j0,j1
+	    assert(signe_permutation(j0,j1,i0,i1)==1);
+	    R v0= det(Q[j0],Q[j1],P,PF); 
+            if(ddd) cout << " v0 =" << v0 <<endl;
+	    if( Abs(v0) < eps  ) 
+	      {
+	      // on sort par l'arete  j0,j1
+	      // on choisi aleatoirement la face de sortie 
+	      kk = (rand()/(RAND_MAX/2)) ? i0 : i1; 
+	      if(ddd)
+		  cout << " rand choose  2 :  " << kk << endl;
+	      }
+	    else 
+	      kk= v0 >0 ? i0 : i1; // Attention dyslexie ici durdur FH....
+	    
+	  }
+	else if (k==1) //  une face possible de sortie (cas simple)
+	  kk = neg[0];
+	
+	if(kk>=0)
+	  {
+	    R d=lambda[kk]-l[kk];
+	    if ( l[kk] )
+	     {
+	    throwassert(d);
+	    R coef =  lambda[kk]/d;
+	    R coef1 = 1-coef;
+	    nomove= (coef<1.e-6);
+	    dt        = dt*coef1;
+	    lambda[0] = lambda[0]*coef1 + coef *l[0];
+	    lambda[1] = lambda[1]*coef1 + coef *l[1];
+	    lambda[2] = lambda[2]*coef1 + coef *l[2];
+	    lambda[3] = lambda[3]*coef1 + coef *l[3];
+            if(ddd) cout << "   \t\t -> kk=" << kk << " d=" << d << " , l= "<< lambda[0]  << " " 
+			 <<lambda[1] << " " <<lambda[2] << " " << lambda[3] << endl;
+	    lambda[kk] =0;
+	     }
+	      
+	 
+	  
+	  }
+	 
+      }
+    if(nomove )
+	// on ne bouge pas on utilse Find ... 
+	  {
+	      R dx2= (U,U)*dt*dt;
+	      R ddt=dt, dc=1;
+	      // if Udt < h/2 => recherche un point final  
+	      if(dx2*dx2*dx2 > Det*Det/4)
+		  dt=0;       
+	      else 
+		{ 
+		    dc=0.25;
+		    ddt=dt*dc;
+		    PF= P + U*ddt; // on avance que d'un 1/4
+		    dt -= ddt;
+		}
+	      bool outside;
+	      const Mesh3::Element  *K=Th.Find(PF, Phat,outside,&Th[it]);
+	      if(outside) dt=0; // on a fini 
+	      if(ddd) cout << "   \t ***** WT :  Lock -> Find P+U*ddt*c "<< it<< " " << " -> "<< Th(K) 
+		  << " dt = " << dt << " c = " << dc << " outside: "<< outside <<" , PF " << PF << endl;
+	      return 4+Th(K);
+     }
+      
+    //  on remet le point dans le tet. 
+    int jj=0;
+    R lmx=lambda[0];
+    if (lmx<lambda[1])  jj=1, lmx=lambda[1];
+    if (lmx<lambda[2])  jj=2, lmx=lambda[2];
+    if (lmx<lambda[3])  jj=3, lmx=lambda[3];
+    if(lambda[0]<0) lambda[jj] += lambda[0],lambda[0]=0;
+    if(lambda[1]<0) lambda[jj] += lambda[1],lambda[1]=0;
+    if(lambda[2]<0) lambda[jj] += lambda[2],lambda[2]=0;
+    if(lambda[3]<0) lambda[jj] += lambda[3],lambda[3]=0;
+    Phat=R3(lambda+1);
+    if(ddd) cout  << "\t\t\t -> "<< dt << " : "  << Phat << " K(Phat) ="<< Th[it](Phat) <<  ", " << kk << " jj= "<< jj << " "<< lmx << endl; 
+    assert(kk<0 || lambda[kk]==0);
+    return kk;
+  }        
+	      
+    
+} //   End  namespace Fem2D
+  
+	      
diff --git a/src/femlib/Mesh3dn.hpp b/src/femlib/Mesh3dn.hpp
new file mode 100644
index 0000000..8c381a8
--- /dev/null
+++ b/src/femlib/Mesh3dn.hpp
@@ -0,0 +1,188 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 1d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#ifndef MESH3DN_HPP_
+#define MESH3DN_HPP_
+
+
+#include <cstdio>
+
+// definition R
+#include <cstdlib>
+namespace Fem2D {
+
+#include "R3.hpp"
+}
+ 
+ using namespace ::std;
+#include "GenericMesh.hpp" 
+
+namespace Fem2D {
+  
+typedef GenericVertex<R3> Vertex3;
+
+struct DataTriangle3  {
+  static const int NbOfVertices =3;
+  static const int NbOfEdges =3;
+  static const int NbOfFaces =1;
+  static const int NT =0;
+  static const int NbOfAdjElem =NbOfVertices;
+  static const int NbOfVertexOnHyperFace =NbOfVertices-1;
+  typedef Vertex3 V;
+  typedef  V::Rd Rd ;
+  typedef R2 RdHat;
+  typedef R1 RdHatBord;
+  static RdHat PBord(const int * nvb,const RdHatBord &P)  { 
+  return RdHat::KHat[nvb[0]]*(1-P.x)+R2::KHat[nvb[1]]*(P.x) ;}  
+
+  static R mesure(  V *  pv[NbOfVertices]) {    
+    return (R3(*pv[0],*pv[1])^R3(*pv[0],*pv[2])).norme()*0.5;
+  }
+};
+
+struct DataTet  {
+  static const int NbOfVertices =4;
+  static const int NbOfEdges =6;
+  static const int NbOfFaces =4;
+  static const int NT =1;
+  static const int NbOfAdjElem =NbOfVertices;
+  static const int NbOfVertexOnHyperFace =NbOfVertices-1;
+  typedef Vertex3 V;
+  typedef  V::Rd Rd ;
+  static R mesure(  V *  pv[NbOfVertices]) 
+  {    
+    R3 AB(*pv[0],*pv[1]);
+    R3 AC(*pv[0],*pv[2]);
+    R3 AD(*pv[0],*pv[3]);
+    return det(AB,AC,AD)/6.;
+  }
+  static const int (* const nvface)[3];// = nvfaceTet;
+  static const int (* const nvedge)[2];//  = nvedgeTet;
+  typedef R3 RdHat;
+  typedef R2 RdHatBord;
+  static RdHat PBord(const int * nvb,const RdHatBord& P)  { 
+ //     cout << "PBORD : " << nvb[0] << " " <<  nvb[1] <<  nvb[2] << " " << P<< " -> " <<  RdHat::KHat[nvb[0]]*(1-P.x-P.y)+RdHat::KHat[nvb[1]]*(P.x)+RdHat::KHat[nvb[2]]*(P.y) 
+//	<< "," <<  RdHat::KHat[nvb[0]] << "," <<  RdHat::KHat[nvb[1]] << "," << RdHat::KHat[nvb[2]] <<endl;
+  return RdHat::KHat[nvb[0]]*(1-P.x-P.y)+RdHat::KHat[nvb[1]]*(P.x)+RdHat::KHat[nvb[2]]*(P.y) ;}  
+
+};
+
+class Tet: public GenericElement<DataTet>  {
+public: 
+  Tet() {}; // constructor empty for array
+
+  
+  R3 H(int i) const 
+  { ASSERTION(i>=0 && i <4);
+    int nvface[4][3]=  {{3,2,1}, {0,2,3},{ 3,1,0},{ 0,1,2}};
+    R3 AB(at(nvface[i][0]),at(nvface[i][1]));
+    R3 AC(at(nvface[i][0]),at(nvface[i][2]));
+    return AB^AC/(6.*this->mesure());} // heigth 
+ 
+    R3 n(int i) const 
+    { ASSERTION(i>=0 && i <4);
+    int nvface[4][3]=  {{3,2,1}, {0,2,3},{ 3,1,0},{ 0,1,2}};
+	R3 AB(at(nvface[i][0]),at(nvface[i][1]));
+	R3 AC(at(nvface[i][0]),at(nvface[i][2]));
+	R3 N=AB^AC;
+    return N/N.norme();} //  exterior normal  
+    
+  void Gradlambda(R3 * GradL) const
+  {
+    R3 V1(at(0),at(1));
+    R3 V2(at(0),at(2));
+    R3 V3(at(0),at(3));
+    R det1=1./(6.*mesure());
+    GradL[1]= (V2^V3)*det1;
+    GradL[2]= (V3^V1)*det1;
+    GradL[3]= (V1^V2)*det1;
+    GradL[0]=-GradL[1]-GradL[2]-GradL[3];
+  }
+
+};
+
+class Triangle3: public GenericElement<DataTriangle3>  {
+public: 
+  Triangle3() {}; // constructor empty for array
+
+  Rd Edge(int i) const {ASSERTION(i>=0 && i <3);
+    return Rd(this->at((i+1)%3),this->at((i+2)%3));}// opposite edge vertex i
+  /*
+  Rd H(int i) const { ASSERTION(i>=0 && i <3);
+    Rd E=Edge(i);return E.perp()/(2.*this->mesure());} // heigth 
+  
+  void Gradlambda(Rd * GradL) const
+  {
+    GradL[1]= H(1);
+    GradL[2]= H(2);
+    GradL[0]=-GradL[1]-GradL[2];
+  }
+  */ 
+
+};
+
+
+class Mesh3 : public GenericMesh<Tet,Triangle3,Vertex3> { 
+public:
+  Mesh3(){}
+  Mesh3(const string); 
+  Mesh3(const string, const long); // Add J. Morice 11/10
+  Mesh3(FILE *f,int offset=0);     
+  Mesh3(const  Serialize &);     
+  Mesh3(int nnv, int nnt, int nnbe, Vertex3 *vv, Tet *tt, Triangle3 *bb); 
+  Mesh3(int nnv, int nnbe, Vertex3 *vv, Triangle3 *bb);  // surface mesh 
+  
+  double hmin() const; // Add J. Morice 11/10
+
+  void GSave(FILE * f,int offset=0) const ;
+  void GRead(FILE * f,int offset);
+    
+  int Save(const string & filename) const ;  
+    
+  int SaveSurface(const string & filename) const ;  
+  int SaveSurface(const string & filename1, const string & filename2) const ;  
+  void flipSurfaceMesh3(int surface_orientation);
+  void read(istream &);
+  void readmsh(ifstream & f,int offset);
+  void TrueVertex();
+	
+private:
+  int load(const string & filename); 
+  Mesh3(const Mesh3 &); // pas de construction par copie
+  void operator=(const Mesh3 &);// pas affectation par copy 
+};
+// for the caracteristic method.
+  int  WalkInTet(const Mesh3 & Th,int it, R3 & Phat,const R3 & U, R & dt);
+
+} 
+#endif
diff --git a/src/femlib/MeshPoint.hpp b/src/femlib/MeshPoint.hpp
new file mode 100644
index 0000000..c222235
--- /dev/null
+++ b/src/femlib/MeshPoint.hpp
@@ -0,0 +1,464 @@
+
+//typedef double R;
+namespace  Fem2D {
+class MeshPointBase { public:
+  R3 P;
+  R3 PHat;
+  union {
+  const Mesh * Th;  
+  const Mesh3 * Th3;  
+  };
+  union{
+  const Triangle * T;
+  const Tet * T3;
+  };
+  long region, t,v,f,e,gsens; // triangle,vertex, face or edge
+  long  label;
+  R3 N; //  if on boundary 
+  bool outside;
+  int VF; 
+  int d;
+  void set(const R2 &P2,const R2 & P_Hat,const  baseFElement & K,int ll,const R2 &NN,int iedge)
+   { 
+     P.x=P2.x;
+     P.y=P2.y;
+     P.z=0;
+     PHat.x=P_Hat.x;
+     PHat.y=P_Hat.y;
+     PHat.z=0.;
+     T=&K.T;
+     Th=&K.Vh.Th; 
+     region = T->lab;
+     label = ll;
+     v=f=-1; 
+     e=iedge;
+     t=(*Th)(T); 
+     throwassert( Abs( (NN,NN) -1.0) < 1e-5 );
+     N.x=NN.x;   
+     N.y=NN.y;   
+     N.z=0; 
+     VF=0;
+     d=2;
+   }
+  void set(const Mesh & aTh,const R2 &P2,const R2 & P_Hat,const  Triangle & aK,int ll,const R2 &NN,int iedge,int VFF=0)
+   { 
+     P.x=P2.x;
+     P.y=P2.y;
+     P.z=0;
+     PHat.x=P_Hat.x;
+     PHat.y=P_Hat.y;
+     PHat.z=0.;
+     T=&aK;
+     Th=&aTh; 
+     region = T->lab;
+     label = ll;
+     v=f=-1;
+     t=(*Th)(T); 
+     e=iedge; 
+     throwassert( Abs( (NN,NN) -1.0) < 1e-5 );
+     N.x=NN.x;   
+     N.y=NN.y;   
+     N.z=0;   
+     VF=VFF;
+     d=2;
+   }
+   
+  void set(const R2 &P2,const R2 & P_Hat,const  baseFElement & K,int ll)
+   { 
+     P.x=P2.x;
+     P.y=P2.y;
+     P.z=0;
+     PHat.x=P_Hat.x;
+     PHat.y=P_Hat.y;
+     PHat.z=0.;
+     T=&K.T;
+     Th=&K.Vh.Th; 
+     region = T->lab;
+     label = ll;
+     t=(*Th)(T);
+     v=f=e=-1;  
+     N.x=0;   
+     N.y=0;   
+     N.z=0;   
+     VF=0;  
+     d=2;
+   }
+   
+     void set(const R2 &P2,const R2 & P_Hat,const  baseFElement & K)
+   { 
+     P.x=P2.x;
+     P.y=P2.y;
+     P.z=0;
+     PHat.x=P_Hat.x;
+     PHat.y=P_Hat.y;
+     PHat.z=0.;
+     T=&K.T;
+     Th=&K.Vh.Th; 
+     region = T->lab;
+     v=f=e=-1;  
+     N.x=0;   
+     N.y=0;   
+     N.z=0;   
+     VF=0;  
+     int ll[3],kk(0);
+     if ( P_Hat.x<1.e-6) ll[kk++]=1;
+     if ( P_Hat.y<1.e-6) ll[kk++]=2;
+     if ( P_Hat.y+P_Hat.x>0.999999) ll[kk++]=0;    
+     if (kk==0) label=0;
+     else if (kk==2)
+      { 
+	 v = 3-ll[0]-ll[1];// 3 = 0+1+2 sommet oppose
+        label=(*T)[v].lab;
+      } 
+     else  {
+       e = ll[0]; 
+       int i1,i2;
+       Th->VerticesNumberOfEdge(K.T,e,i1,i2);
+       const BoundaryEdge * be=Th->TheBoundaryEdge(i1,i2);
+       label= be ? be->lab : 0;
+      // R2 E(K.T.Edge(ke));
+      // (R2 &) N = E.perp()/Norme2(E);
+       
+   
+      //cout << "lab =" <<  label << " " << e << " " <<  kk << " " << P_Hat 
+       //    << ": " <<  K.number << " , " << (R2) P << " " << N << endl;
+      }
+   
+     t=(*Th)(T);
+     d=2;
+   }
+
+  void set(const  Mesh &aTh, const R2 &P2,const R2 & P_Hat,const  Triangle & aK,const int ll,bool coutside=false)
+   { 
+     P.x=P2.x;
+     P.y=P2.y;
+     P.z=0;
+     PHat.x=P_Hat.x;
+     PHat.y=P_Hat.y;
+     PHat.z=0.;
+     T=&aK;
+     Th=&aTh; 
+     region = T->lab;
+     label = ll;
+       t= aTh(aK); // Miss correct Nov. 2012 ...
+      v=f=e=-1;
+     N.x=0;   
+     N.y=0;   
+     N.z=0;   
+     outside=coutside;
+     VF=0;  
+     d=2;
+   }
+   
+  void setP(const Mesh * pTh,int tt,int ss)
+   { 
+     T=&(*pTh)[tt];
+     Vertex & V=(*T)[ss];
+     (R2 &) P= V ;
+     P.z=0;
+     (R2 &) PHat = TriangleHat[ss];
+     PHat.z=0;
+     Th=pTh; 
+     region = T->lab;
+     label = V.lab;
+     t=tt;
+     v=f=e=-1;
+     v=ss;
+     VF=0;
+     d=2;  
+   }
+   
+  void change(const R2 & PH,const Triangle & tt,int ll)
+   { 
+     T= &tt;
+     (R2 &) PHat = PH;
+     (R2 &) P = (*T)(PH);
+     region = T->lab;
+     label = ll;
+     
+     t=(*Th)(T);
+     v=f=e=-1;
+     VF=0;
+     d=2;  
+     
+   }
+    void change(const R3 & PH,const Tet & tt,int ll)
+    { 
+	T3= &tt;
+	(R3 &) PHat = PH;
+	(R3 &) P = (*T3)(PH);
+	region = T3->lab;
+	label = ll;
+        
+         t=(*Th)(T);
+	v=f=e=-1;
+	VF=0;
+	d=2;  
+	
+    }
+    
+   void unset() 
+   {
+     P.x=-1e30;
+     P.y=-1e30;
+     P.z=-1e30;
+     T=0;
+     Th=0;
+      label =0;
+     VF=0;  
+      d=0;
+   }
+   bool isUnset() const { return P.x == -1e30;} // BofBof   
+   void set(R x=0.0,R y=0.0,R z=0.0) 
+   {
+     P.x=x;
+     P.y=y;
+     P.z=z;
+     T=0;
+     Th=0;
+      label =0;
+      t=f=e=v=-1; 
+      VF=0;  
+      d=0;
+   }
+
+
+
+  // ------- 3D
+  void set(const R3 &P2,const R3 & P_Hat,const  baseFElement3 & K,int ll,const R3 &NN,int iface)
+   { 
+     P=P2;
+     PHat=P_Hat;
+     T3=&K.T;
+     Th3=&K.Vh.Th; 
+     region = T3->lab;
+     label = ll;
+     e=v=-1; 
+     f=iface;
+     t=(*Th3)(T3); 
+     assert( Abs( (NN,NN) -1.0) < 1e-5 );
+     N=NN;   
+     VF=0;
+     d=3;
+   }
+  void set(const Mesh3 & aTh,const R3 &P2,const R3 & P_Hat,const  Tet & aK,int ll,const R3 &NN,int iface,int VFF=0)
+   { 
+     P=P2;
+     PHat=P_Hat;
+     T3=&aK;
+     Th3=&aTh; 
+     region = T3->lab;
+     label = ll;
+     v=f=-1;
+     t=(*Th3)(T3); 
+     v=e=-1;
+     f=iface; 
+     assert( Abs( (NN,NN) -1.0) < 1e-5 );
+     N=NN;   
+     VF=VFF;
+     d=3;
+   }
+   
+  void set(const R3 &P2,const R3 & P_Hat,const  baseFElement3 & K,int ll)
+   { 
+     P=P2;
+     PHat=P_Hat;
+     T3=&K.T;
+     Th3=&K.Vh.Th; 
+     region = T3->lab;
+     label = ll;
+     t=(*Th)(T);
+     v=f=e=-1;  
+     N.x=0;   
+     N.y=0;   
+     N.z=0;   
+     VF=0;  
+     d=3;
+   }
+   
+     void set(const R3 &P2,const R3 & P_Hat,const  baseFElement3 & K)
+   { 
+     P=P2;
+     PHat=P_Hat;
+     T3=&K.T;
+     Th3=&K.Vh.Th; 
+     region = T3->lab;
+     v=f=e=-1;  
+     N.x=0;   
+     N.y=0;   
+     N.z=0;   
+     VF=0;  
+     int ll[4],kk(0);
+     if ( P_Hat.x<1.e-6) ll[kk++]=1;
+     if ( P_Hat.y<1.e-6) ll[kk++]=2;
+     if ( P_Hat.z<1.e-6) ll[kk++]=3;
+     if ( P_Hat.x+P_Hat.y+P_Hat.z>0.999999) ll[kk++]=0;    
+     if (kk==0) label=0;
+     else if (kk==3)
+      { 
+	 v = 6-ll[0]-ll[1]-ll[2];// 3 = 0+1+2 sommet oppose
+	 label=(*T)[v].lab;
+      } 
+     else  {
+       //  on edge
+       //ffassert(0); // a faire 
+       /*
+       e = ll[0]; 
+       int i1,i2,I3;
+       
+       Th3->VerticesNumberOfEdge(K.T,e,i1,i2);
+       const BoundaryEdge * be=Th3->TheBoundaryEdge(i1,i2);
+       label= be ? be->lab : 0;
+       */
+       label=-1;// to say 
+      }
+   
+     t=(*Th3)(T3);
+     d=3;
+   }
+
+  void set(const  Mesh3 &aTh, const R3 &P2,const R3 & P_Hat,const  Tet & aK,const int ll,bool coutside=false)
+   { 
+     P=P2;
+     PHat=P_Hat;
+     T3=&aK;
+     Th3=&aTh; 
+     region = T3->lab;
+     label = ll;
+     t=(*Th3)(T3);
+     v=f=e=-1;  
+     N.x=0;   
+     N.y=0;   
+     N.z=0;   
+    // area=mes;
+     outside=coutside;
+     VF=0;  
+     d=3;
+   }
+   
+  void setP(const Mesh3 * pTh,int tt,int ss)
+   { 
+     T3=&(*pTh)[tt];
+     const Mesh3::Vertex & V=(*T3)[ss];
+     P= V ;
+     PHat = TetHat[ss];
+     Th3=pTh; 
+     region = T3->lab;
+     label = V.lab;
+     t=tt;
+     v=f=e=-1;
+     v=ss;
+     VF=0;
+     d=3;  
+   }
+   
+
+  // --------  
+};
+class MeshPoint : public MeshPointBase { public:
+  MeshPointBase other;
+  void unset() {  MeshPointBase::unset(); other.unset();}
+  void set(const R2 &P2,const R2 & P_Hat,const  baseFElement & K,int ll,const R2 &NN,int iedge) {
+     MeshPointBase::set(P2,P_Hat,K,ll,NN,iedge);
+     other.unset();}   
+  void set(const Mesh & aTh,const R2 &P2,const R2 & P_Hat,const  Triangle & aK,int ll,const R2 &NN,int iedge) {
+    MeshPointBase::set(aTh,P2,P_Hat,aK,ll,NN,iedge);
+    other.unset();}
+  void set(const Mesh & aTh,const R2 &P2,const R2 & P_Hat,const  Triangle & aK,int ll,const R2 &NN,int iedge,int VFF) {
+    MeshPointBase::set(aTh,P2,P_Hat,aK,ll,NN,iedge,VFF);
+    other.unset();}
+  void set(const R2 &P2,const R2 & P_Hat,const  baseFElement & K) {
+     MeshPointBase::set(P2,P_Hat,K);
+     other.unset();
+    }
+  void set(const  Mesh &aTh, const R2 &P2,const R2 & P_Hat,const  Triangle & aK,
+           const int ll,bool coutside=false) {
+      MeshPointBase::set(aTh,P2,P_Hat,aK,ll,coutside);
+      other.unset();
+           }
+
+  // 3d
+  void set(const R3 &P2,const R3 & P_Hat,const  baseFElement3 & K,int ll,const R3 &NN,int iedge) {
+     MeshPointBase::set(P2,P_Hat,K,ll,NN,iedge);
+     other.unset();}   
+  void set(const Mesh3 & aTh,const R3 &P2,const R3 & P_Hat,const  Tet & aK,int ll,const R3 &NN,int iedge) {
+    MeshPointBase::set(aTh,P2,P_Hat,aK,ll,NN,iedge);
+    other.unset();}
+  void set(const Mesh3 & aTh,const R3 &P2,const R3 & P_Hat,const  Tet & aK,int ll,const R3 &NN,int iedge,int VFF) {
+    MeshPointBase::set(aTh,P2,P_Hat,aK,ll,NN,iedge,VFF);
+    other.unset();}
+  void set(const R3 &P2,const R3 & P_Hat,const  baseFElement3 & K) {
+     MeshPointBase::set(P2,P_Hat,K);
+     other.unset();
+    }
+  void set(const  Mesh3 &aTh, const R3 &P2,const R3 & P_Hat,const  Tet & aK,
+           const int ll,bool coutside=false) {
+    MeshPointBase::set(aTh,P2,P_Hat,aK,ll,coutside);
+    other.unset();
+  }
+  // fin 3d
+  void set(R x=0.0,R y=0.0,R z=0.0) {  
+     MeshPointBase::set(x,y,z);
+     other.unset();} 
+  void change(const R2 & PH,const Triangle & tt,int ll) {
+     MeshPointBase::change(PH,tt,ll);
+     other.unset(); }
+    void change(const R3 & PH,const Tet & tt,int ll) {
+	MeshPointBase::change(PH,tt,ll);
+    other.unset(); }
+  void setP(const Mesh * pTh,int tt,int ss) { 
+      MeshPointBase::setP(pTh,tt,ss); 
+      other.unset(); } 
+  void setP(const Mesh3 * pTh,int tt,int ss) {  // 3d
+      MeshPointBase::setP(pTh,tt,ss); 
+      other.unset(); } 
+
+   bool operator==(const MeshPoint & mp) const {
+      return T == mp.T &&  P.x == mp.P.x && P.y == mp.P.y 
+          && P.z == mp.P.z ;}
+  bool  SetAdj() {
+     if (!(Th && T && t >=0 && e>=0)) return false;//  modif 
+     if(VF==0)
+     {
+     int ieo=e,to=t,ie=e;
+     
+     t=Th->ElementAdj(t,ie);
+     e=ie;
+     if ( t == to && t >= 0 ) return false;
+     int io0=VerticesOfTriangularEdge[ieo][0];
+     //     int io1=VerticesOfTriangularEdge[ieo][1];
+     int i0=VerticesOfTriangularEdge[e][0];
+     int i1=VerticesOfTriangularEdge[e][1];
+     T= &(*Th)[t];
+     region = T->lab;    
+     R l[3];
+     l[1]=PHat.x;
+     l[2]=PHat.y;
+     l[0]=1-PHat.x-PHat.y;
+     R le=l[io0]; 
+     l[i1]=le;
+     l[i0]=1-le;
+     l[3-i1-i0]=0;
+     PHat.x=l[1];
+     PHat.y=l[2];
+     gsens = -gsens;   
+     } 
+     else
+     { //  
+       VF = 1 + VF%2; 
+       ffassert(0); // a faire 
+     }  
+     return true;         
+   }
+  };
+
+ostream & operator << ( ostream &,const  MeshPoint & )  ;    
+inline static MeshPoint* MeshPointStack(Stack s) {void * p= static_cast<void **>(s)[MeshPointStackOffset];throwassert(p); return static_cast<MeshPoint*>( p);}
+inline static void MeshPointStack(Stack s,MeshPoint* mp) {*static_cast<MeshPoint**>(static_cast<void *>(s)) = mp;}
+#ifdef NEWFFSTACK
+inline static MeshPoint* MeshPointStack(void * s) {void * p= static_cast<void **>(s)[MeshPointStackOffset];throwassert(p); return static_cast<MeshPoint*>( p);}
+inline static void MeshPointStack( void *s,MeshPoint* mp) {*static_cast<MeshPoint**>(static_cast<void *>(s)) = mp;}
+
+#endif
+
+}
diff --git a/src/femlib/P012_1d.cpp b/src/femlib/P012_1d.cpp
new file mode 100644
index 0000000..eab913d
--- /dev/null
+++ b/src/femlib/P012_1d.cpp
@@ -0,0 +1,236 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : P0,P1,P2 lagrange 1D 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN   FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include "PkLagrange.hpp"
+
+ namespace Fem2D {
+// P0 
+
+
+class TypeOfFE_P0Lagrange1d : public  TypeOfFE_Lagrange<Mesh1> { 
+public:  
+  TypeOfFE_P0Lagrange1d(): TypeOfFE_Lagrange<Mesh1>(0) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, RNMK_ & val) const;
+  virtual R operator()(const FElement & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const ;
+  
+} ;
+
+
+
+R TypeOfFE_P0Lagrange1d::operator()(const FElement & K,const  R1 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+  R u0(u(K(0)));
+  R r=0;
+  if (op==0)
+    r = u0;
+  else  r=0;
+  return r;
+}
+
+void TypeOfFE_P0Lagrange1d::FB(const What_d whatd,const Mesh & ,const Element & K,const R1 & P,RNMK_ & val) const
+{
+  assert(val.N() >=1);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd & Fop_D0) 
+    {
+      f0[0] = 1;
+    }
+}
+
+
+// P1 
+class TypeOfFE_P1Lagrange1d : public  TypeOfFE_Lagrange<Mesh1> { 
+public:  
+  TypeOfFE_P1Lagrange1d(): TypeOfFE_Lagrange<Mesh1>(1) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, RNMK_ & val) const;
+  virtual R operator()(const FElement & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const ;
+  
+} ;
+
+
+
+R TypeOfFE_P1Lagrange1d::operator()(const FElement & K,const  R1 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+  R u0(u(K(0))), u1(u(K(1)));
+  R r=0;
+  if (op==0)
+    {
+      R l0=1-PHat.x,l1=PHat.x; 
+      r = u0*l0+u1*l1;
+    }
+  else if(op==op_dx  )
+    { 
+      const Element & T=K.T;
+      R1 D[2];
+      T.Gradlambda(D);
+	r =  D[0].x*u0 + D[1].x*u1 ;
+    }
+  //  cout << r << "\t";
+  return r;
+}
+
+void TypeOfFE_P1Lagrange1d::FB(const What_d whatd,const Mesh & ,const Element & K,const R1 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  
+  R l[]={1.-P.sum(),P.x}; 
+  
+  assert(val.N() >=Element::nv);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd & Fop_D0) 
+    {
+      f0[0] = l[0];
+      f0[1] = l[1];
+    }
+  if (whatd & Fop_D1)
+    {
+      R1 Dl[3];
+      K.Gradlambda(Dl);
+      if (whatd & Fop_dx) 
+	{
+	  RN_ f0x(val('.',0,op_dx)); 
+	  f0x[0] = Dl[0].x;
+	  f0x[1] = Dl[1].x;
+	  
+	}
+      
+
+    }
+}
+
+
+
+
+class TypeOfFE_P2Lagrange1d : public  TypeOfFE_Lagrange<Mesh1>  { 
+public:  
+  typedef Mesh1 Mesh;
+  typedef GFElement<Mesh1> FElement;
+  TypeOfFE_P2Lagrange1d(): TypeOfFE_Lagrange<Mesh1>(2) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Mesh1::Element & K,const Rd &P, RNMK_ & val) const;
+  
+} ;
+
+
+
+void TypeOfFE_P2Lagrange1d::FB(const What_d whatd,const Mesh & ,const Element & K,const R1 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  
+  R l[]={1.-P.sum(),P.x}; 
+  
+  assert(val.N() >=E::nv+E::ne);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  //  
+  if (whatd & Fop_D0) 
+    {
+	int k=0;
+	for(int i=0;i<E::nv;++i)
+          f0[k++] = l[i]*(2*l[i]-1.);
+ 	for(int i=0;i<E::ne;++i)
+	  f0[k++] = 4.*l[E::nvedge[i][0]]*l[E::nvedge[i][1]];  
+    }
+  
+  if (whatd & (Fop_D1|Fop_D2))
+  {
+      R1 Dl[2];
+      R l4[2]={ (4*l[0]-1),(4*l[1]-1)}; 
+      
+      K.Gradlambda(Dl);
+      RN_ f0x(val('.',0,op_dx));
+      int k=0;
+      for(int i=0;i<E::nv;++i,++k)
+      {
+	  f0x[k] = Dl[i].x*l4[i];
+      }
+      for(int i=0;i<E::ne;++i,++k)
+      {
+	  int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	  f0x[k] = 4*(Dl[i1].x*l[i0] + Dl[i0].x*l[i1]) ;
+      }
+      assert(k==1);
+      
+      //cout << " D2 " << whatd <<  endl;
+      if (whatd & Fop_D2)
+      {
+	  //cout << " D2 " << endl;
+	  RN_ f0xx(val('.',0,op_dxx));
+	  
+	   k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	  {
+	      f0xx[k] = 4.*Dl[i].x*Dl[i].x;
+	  }
+	  for(int i=0;i<E::ne;++i,++k)
+	  {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0xx[k] = 8.*Dl[i0].x*Dl[i1].x;
+	  } 
+      }
+      
+  } 
+    
+}
+
+
+
+static TypeOfFE_P0Lagrange1d  P0_1d;
+GTypeOfFE<Mesh1> & P0Lagrange1d(P0_1d);
+
+static TypeOfFE_P1Lagrange1d  P1_1d;
+GTypeOfFE<Mesh1> & P1Lagrange1d(P1_1d);
+
+static TypeOfFE_P2Lagrange1d  P2_1d;
+GTypeOfFE<Mesh1> & P2Lagrange1d(P2_1d);
+
+
+
+
+template<> GTypeOfFE<Mesh1> & DataFE<Mesh1>::P0=P0_1d; 
+template<> GTypeOfFE<Mesh1> & DataFE<Mesh1>::P1=P1_1d; 
+template<> GTypeOfFE<Mesh1> & DataFE<Mesh1>::P2=P2_1d; 
+
+
+ }
+
diff --git a/src/femlib/P012_2d.cpp b/src/femlib/P012_2d.cpp
new file mode 100644
index 0000000..356cb63
--- /dev/null
+++ b/src/femlib/P012_2d.cpp
@@ -0,0 +1,256 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : P0,P1,P2 lagrange 2D 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN   FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include "PkLagrange.hpp"
+
+// P0 
+
+ namespace Fem2D {
+class TypeOfFE_P0Lagrange2d : public  TypeOfFE_Lagrange<Mesh2> { 
+public:  
+  TypeOfFE_P0Lagrange2d(): TypeOfFE_Lagrange<Mesh2>(0) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, RNMK_ & val) const;
+  virtual R operator()(const FElement & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const ;
+  
+} ;
+
+
+
+R TypeOfFE_P0Lagrange2d::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+  R u0(u(K(0)));
+  R r=0;
+  if (op==0)
+    r = u0;
+  else  r=0;
+  return r;
+}
+
+void TypeOfFE_P0Lagrange2d::FB(const What_d whatd,const Mesh & ,const Element & K,const R2 & P,RNMK_ & val) const
+{
+  assert(val.N() >=1);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd & Fop_D0) 
+    {
+      f0[0] = 1;
+    }
+}
+
+
+// P1 
+class TypeOfFE_P1Lagrange2d : public  TypeOfFE_Lagrange<Mesh2> { 
+public:  
+  TypeOfFE_P1Lagrange2d(): TypeOfFE_Lagrange<Mesh2>(1) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, RNMK_ & val) const;
+  virtual R operator()(const FElement & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const ;
+  
+} ;
+
+
+
+R TypeOfFE_P1Lagrange2d::operator()(const FElement & K,const  R2 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+  R u0(u(K(0))), u1(u(K(1))), u2(u(K(2)));
+  R r=0;
+  if (op==0)
+    {
+      R l0=1-PHat.x-PHat.y,l1=PHat.x,l2=PHat.y; 
+      r = u0*l0+u1*l1+l2*u2;
+    }
+  else if(op==op_dx || op==op_dy )
+    { 
+      const Element & T=K.T;
+      R2 D[3];
+      T.Gradlambda(D);
+      if (op==op_dx)
+	r =  D[0].x*u0 + D[1].x*u1 + D[2].x*u2;
+      else 
+	r =  D[0].y*u0 + D[1].y*u1 + D[2].y*u2 ;
+    }
+  //  cout << r << "\t";
+  return r;
+}
+
+void TypeOfFE_P1Lagrange2d::FB(const What_d whatd,const Mesh & ,const Element & K,const R2 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  
+  R l[]={1.-P.sum(),P.x,P.y}; 
+  
+  assert(val.N() >=Element::nv);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd & Fop_D0) 
+    {
+      f0[0] = l[0];
+      f0[1] = l[1];
+      f0[2] = l[2];
+    }
+  if (whatd & Fop_D1)
+    {
+      R2 Dl[3];
+      K.Gradlambda(Dl);
+      if (whatd & Fop_dx) 
+	{
+	  RN_ f0x(val('.',0,op_dx)); 
+	  f0x[0] = Dl[0].x;
+	  f0x[1] = Dl[1].x;
+	  f0x[2] = Dl[2].x;
+	  
+	}
+      
+      if (whatd & Fop_dy) {
+	RN_ f0y(val('.',0,op_dy)); 
+	f0y[0] = Dl[0].y;
+	f0y[1] = Dl[1].y;
+	f0y[2] = Dl[2].y;
+      }
+
+    }
+}
+
+
+
+
+class TypeOfFE_P2Lagrange2d : public  TypeOfFE_Lagrange<Mesh2>  { 
+public:  
+  typedef Mesh2 Mesh;
+  typedef GFElement<Mesh2> FElement;
+  TypeOfFE_P2Lagrange2d(): TypeOfFE_Lagrange<Mesh2>(2) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Mesh2::Element & K,const Rd &P, RNMK_ & val) const;
+  
+} ;
+
+
+
+void TypeOfFE_P2Lagrange2d::FB(const What_d whatd,const Mesh & ,const Element & K,const R2 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  
+  R l[]={1.-P.sum(),P.x,P.y}; 
+  
+  assert(val.N() >=E::nv+E::ne);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  //  
+  if (whatd & Fop_D0) 
+    {
+	int k=0;
+	for(int i=0;i<E::nv;++i)
+          f0[k++] = l[i]*(2*l[i]-1.);
+ 	for(int i=0;i<E::ne;++i)
+	  f0[k++] = 4.*l[E::nvedge[i][0]]*l[E::nvedge[i][1]];  
+    }
+  
+  if (whatd & (Fop_D1|Fop_D2))
+  {
+      R2 Dl[3];
+      R l4[3]={ (4*l[0]-1),(4*l[1]-1),(4*l[2]-1)}; 
+    
+      K.Gradlambda(Dl);
+      RN_ f0x(val('.',0,op_dx));
+      RN_ f0y(val('.',0,op_dy)); 
+      RN_ f0z(val('.',0,op_dz)); 
+      int k=0;
+      for(int i=0;i<E::nv;++i,++k)
+      {
+	  f0x[k] = Dl[i].x*l4[i];
+	  f0y[k] = Dl[i].y*l4[i];
+      }
+      for(int i=0;i<E::ne;++i,++k)
+      {
+	  int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	  f0x[k] = 4*(Dl[i1].x*l[i0] + Dl[i0].x*l[i1]) ;
+	  f0y[k] = 4*(Dl[i1].y*l[i0] + Dl[i0].y*l[i1]) ;
+      }
+      assert(k==6);
+      
+      //cout << " D2 " << whatd <<  endl;
+      if (whatd & Fop_D2)
+      {
+	  //cout << " D2 " << endl;
+	  RN_ f0xx(val('.',0,op_dxx));
+	  RN_ f0yy(val('.',0,op_dyy)); 
+	  RN_ f0xy(val('.',0,op_dxy));
+	  
+	   k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	  {
+	      f0xx[k] = 4.*Dl[i].x*Dl[i].x;
+	      f0yy[k] = 4.*Dl[i].y*Dl[i].y;
+	      f0xy[k] = 4.*Dl[i].x*Dl[i].y;
+	  }
+	  for(int i=0;i<E::ne;++i,++k)
+	  {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0xx[k] = 8.*Dl[i0].x*Dl[i1].x;
+	      f0yy[k] = 8.*Dl[i0].y*Dl[i1].y;
+	      f0xy[k] = 4.*(Dl[i0].x*Dl[i1].y+ Dl[i1].x*Dl[i0].y);
+	  } 
+	  assert(k==6);
+      }
+      
+  } 
+    
+}
+
+
+
+static TypeOfFE_P0Lagrange2d  P0_2d;
+GTypeOfFE<Mesh2> & P0Lagrange2d(P0_2d);
+
+static TypeOfFE_P1Lagrange2d  P1_2d;
+GTypeOfFE<Mesh2> & P1Lagrange2d(P1_2d);
+
+static TypeOfFE_P2Lagrange2d  P2_2d;
+GTypeOfFE<Mesh2> & P2Lagrange2d(P2_2d);
+
+
+
+
+template<> GTypeOfFE<Mesh2> & DataFE<Mesh2>::P0=P0_2d; 
+template<> GTypeOfFE<Mesh2> & DataFE<Mesh2>::P1=P1_2d; 
+template<> GTypeOfFE<Mesh2> & DataFE<Mesh2>::P2=P2_2d; 
+
+
+ }
diff --git a/src/femlib/P012_3d.cpp b/src/femlib/P012_3d.cpp
new file mode 100644
index 0000000..f8a1dac
--- /dev/null
+++ b/src/femlib/P012_3d.cpp
@@ -0,0 +1,855 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : P0,P1,P2 lagrange 3D 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN   FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+
+#include "PkLagrange.hpp"
+
+ namespace Fem2D {
+// P0 
+
+
+class TypeOfFE_P0Lagrange3d : public  TypeOfFE_Lagrange<Mesh3> { 
+public:  
+  TypeOfFE_P0Lagrange3d(): TypeOfFE_Lagrange<Mesh3>(0) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, RNMK_ & val) const;
+  virtual R operator()(const FElement & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const ;
+  
+} ;
+
+     
+
+
+R TypeOfFE_P0Lagrange3d::operator()(const FElement & K,const  R3 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+  R u0(u(K(0)));
+  R r=0;
+  if (op==0)
+    r = u0;
+  else  r=0;
+  return r;
+}
+
+void TypeOfFE_P0Lagrange3d::FB(const What_d whatd,const Mesh & ,const Element & K,const R3 & P,RNMK_ & val) const
+{
+  assert(val.N() >=1);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd & Fop_D0) 
+    {
+      f0[0] = 1;
+    }
+}
+
+
+// P1 
+class TypeOfFE_P1Lagrange3d : public  TypeOfFE_Lagrange<Mesh3> { 
+public:  
+  TypeOfFE_P1Lagrange3d(): TypeOfFE_Lagrange<Mesh3>(1) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Element & K,const Rd &P, RNMK_ & val) const;
+  virtual R operator()(const FElement & K,const  RdHat & PHat,const KN_<R> & u,int componante,int op) const ;
+  
+} ;
+
+
+
+R TypeOfFE_P1Lagrange3d::operator()(const FElement & K,const  R3 & PHat,const KN_<R> & u,int componante,int op) const 
+{ 
+  R u0(u(K(0))), u1(u(K(1))), u2(u(K(2))),u3(u(K(3)));
+  R r=0;
+  if (op==0)
+    {
+      R l0=1-PHat.x-PHat.y-PHat.z,l1=PHat.x,l2=PHat.y,l3=PHat.z; 
+      r = u0*l0+u1*l1+l2*u2+l3*u3;
+    }
+  else if(op==op_dx || op==op_dy || op==op_dz) // dx => dy thank to Pichon 27/01/2008 (FH)
+    { 
+      const Element & T=K.T;
+      R3 D[4];
+      T.Gradlambda(D);
+      if (op==op_dx)
+	r =  D[0].x*u0 + D[1].x*u1 + D[2].x*u2+ D[3].x*u3 ;
+      else if (op==op_dy) 
+	r =  D[0].y*u0 + D[1].y*u1 + D[2].y*u2+ D[3].y*u3 ;
+      else 
+	r =  D[0].z*u0 + D[1].z*u1 + D[2].z*u2+ D[3].z*u3 ;
+    }
+  //  cout << r << "\t";
+  return r;
+}
+
+void TypeOfFE_P1Lagrange3d::FB(const What_d whatd,const Mesh & ,const Element & K,const R3 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  
+  R l[]={1.-P.sum(),P.x,P.y,P.z}; 
+  
+  assert(val.N() >=Element::nv);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  
+  if (whatd & Fop_D0) 
+    {
+      f0[0] = l[0];
+      f0[1] = l[1];
+      f0[2] = l[2];
+      f0[3] = l[3];
+    }
+  if (whatd & Fop_D1)
+    {
+      R3 Dl[4];
+      K.Gradlambda(Dl);
+      //for(int i=0;i<4;++i)
+	//      cout << Dl[i] << endl;
+      if (whatd & Fop_dx) 
+	{
+	  RN_ f0x(val('.',0,op_dx)); 
+	  f0x[0] = Dl[0].x;
+	  f0x[1] = Dl[1].x;
+	  f0x[2] = Dl[2].x;
+	  f0x[3] = Dl[3].x;
+	  
+	}
+      
+      if (whatd & Fop_dy) {
+	RN_ f0y(val('.',0,op_dy)); 
+	f0y[0] = Dl[0].y;
+	f0y[1] = Dl[1].y;
+	f0y[2] = Dl[2].y;
+	f0y[3] = Dl[3].y;
+      }
+
+      if (whatd & Fop_dz) {
+	RN_ f0z(val('.',0,op_dz)); 
+	f0z[0] = Dl[0].z;
+	f0z[1] = Dl[1].z;
+	f0z[2] = Dl[2].z;
+	f0z[3] = Dl[3].z;
+      }
+    }
+  //  cout << val << endl;
+}
+
+
+
+
+class TypeOfFE_P2Lagrange3d : public TypeOfFE_Lagrange<Mesh3>  { 
+public:  
+  typedef Mesh3 Mesh;
+  typedef GFElement<Mesh3> FElement;
+  TypeOfFE_P2Lagrange3d(): TypeOfFE_Lagrange<Mesh3>(2) {  }
+  void FB(const What_d whatd,const Mesh & Th,const Mesh3::Element & K,const Rd &P, RNMK_ & val) const;
+} ;
+
+class TypeOfFE_P1bLagrange3d : public TypeOfFE_Lagrange<Mesh3>  { 
+    public:  
+	 typedef Mesh3 Mesh;
+	 typedef GFElement<Mesh3> FElement;
+	 TypeOfFE_P1bLagrange3d(): TypeOfFE_Lagrange<Mesh3>(-1) {  }
+	 void FB(const What_d whatd,const Mesh & Th,const Mesh3::Element & K,const Rd &P, RNMK_ & val) const;
+} ;
+     
+
+     
+
+void TypeOfFE_P2Lagrange3d::FB(const What_d whatd,const Mesh & ,const Element & K,const R3 & P,RNMK_ & val) const
+{
+  //  const Triangle & K(FE.T);
+  
+  R l[]={1.-P.sum(),P.x,P.y,P.z}; 
+  
+  assert(val.N() >=E::nv+E::ne);
+  assert(val.M()==1 );
+  
+  val=0; 
+  RN_ f0(val('.',0,op_id)); 
+  //  
+  if (whatd & Fop_D0) 
+    {
+	int k=0;
+	for(int i=0;i<E::nv;++i)
+          f0[k++] = l[i]*(2*l[i]-1.);
+ 	for(int i=0;i<E::ne;++i)
+	  f0[k++] = 4.*l[E::nvedge[i][0]]*l[E::nvedge[i][1]];  
+    }
+  
+  if (whatd & (Fop_D1|Fop_D2))
+  {
+   
+    R3 Dl[4];
+    R l4[4]={ (4*l[0]-1),(4*l[1]-1),(4*l[2]-1),(4*l[3]-1)}; 
+      
+    K.Gradlambda(Dl);
+
+    if( whatd & Fop_dx)
+      {
+	RN_ f0x(val('.',0,op_dx));
+ 
+	int k=0;
+	for(int i=0;i<E::nv;++i,++k)
+	  {
+	    f0x[k] = Dl[i].x*l4[i];
+	  }
+	for(int i=0;i<E::ne;++i,++k)
+	  {
+	    int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	    f0x[k] = 4*(Dl[i1].x*l[i0] + Dl[i0].x*l[i1]) ;
+	  }
+	assert(k==10);
+      }
+
+    if( whatd & Fop_dy)
+      {
+	RN_ f0y(val('.',0,op_dy));
+ 
+	int k=0;
+	for(int i=0;i<E::nv;++i,++k)
+	  {
+	    f0y[k] = Dl[i].y*l4[i];
+	  }
+	for(int i=0;i<E::ne;++i,++k)
+	  {
+	    int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	    f0y[k] = 4*(Dl[i1].y*l[i0] + Dl[i0].y*l[i1]) ;
+	  }
+	assert(k==10);
+      }
+
+    if( whatd & Fop_dz)
+      {
+	RN_ f0z(val('.',0,op_dz));
+ 
+	int k=0;
+	for(int i=0;i<E::nv;++i,++k)
+	  {
+	    f0z[k] = Dl[i].z*l4[i];
+	  }
+	for(int i=0;i<E::ne;++i,++k)
+	  {
+	    int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	    f0z[k] = 4*(Dl[i1].z*l[i0] + Dl[i0].z*l[i1]) ;
+	  }
+	assert(k==10);
+      }
+
+    /* avant
+      RN_ f0x(val('.',0,op_dx));
+      RN_ f0y(val('.',0,op_dy)); 
+      RN_ f0z(val('.',0,op_dz)); 
+      
+      int k=0;
+      for(int i=0;i<E::nv;++i,++k)
+      {
+      f0x[k] = Dl[i].x*l4[i];
+      f0y[k] = Dl[i].y*l4[i];
+      f0z[k] = Dl[i].z*l4[i];
+      }
+      for(int i=0;i<E::ne;++i,++k)
+      {
+      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+      f0x[k] = 4*(Dl[i1].x*l[i0] + Dl[i0].x*l[i1]) ;
+      f0y[k] = 4*(Dl[i1].y*l[i0] + Dl[i0].y*l[i1]) ;
+      f0z[k] = 4*(Dl[i1].z*l[i0] + Dl[i0].z*l[i1]) ;
+      }
+      assert(k==10);
+    */
+    //cout << " D2 " << whatd <<  endl;
+    if (whatd & Fop_D2)
+      {
+	
+	//cout << " D2 " << endl;
+	if (whatd & Fop_dxx){
+	  RN_ f0xx(val('.',0,op_dxx));
+	
+	  int k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	    {
+	      f0xx[k] = 4.*Dl[i].x*Dl[i].x;
+	    }
+	  for(int i=0;i<E::ne;++i,++k)
+	    {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0xx[k] = 8.*Dl[i0].x*Dl[i1].x;
+	    } 
+	  assert(k==10);
+	}
+	//cout << " D2 " << endl;
+	if (whatd & Fop_dyy){
+	  RN_ f0yy(val('.',0,op_dyy)); 
+	
+	  int k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	    {	
+	      f0yy[k] = 4.*Dl[i].y*Dl[i].y;
+	    }
+	  for(int i=0;i<E::ne;++i,++k)
+	    {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0yy[k] = 8.*Dl[i0].y*Dl[i1].y;
+	    }
+	  assert(k==10);
+	}
+	//cout << " D2 " << endl;
+	if (whatd & Fop_dzz){	 
+	  RN_ f0zz(val('.',0,op_dzz)); 
+      
+	  int k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	    {
+	      f0zz[k] = 4.*Dl[i].z*Dl[i].z;
+	    }
+	  for(int i=0;i<E::ne;++i,++k)
+	    {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0zz[k] = 8.*Dl[i0].z*Dl[i1].z;
+	      
+	    }
+	  assert(k==10);
+	}
+	//cout << " D2 " << endl;
+	if (whatd & Fop_dxy){		  
+	  RN_ f0xy(val('.',0,op_dxy));
+	 
+	  int k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	    {
+	      f0xy[k] = 4.*Dl[i].x*Dl[i].y;
+	    }
+	  for(int i=0;i<E::ne;++i,++k)
+	    {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0xy[k] = 4.*(Dl[i0].x*Dl[i1].y+ Dl[i1].x*Dl[i0].y);
+	    } 
+	  assert(k==10);
+	}
+
+	//cout << " D2 " << endl;
+	if (whatd & Fop_dxz){
+	  RN_ f0xz(val('.',0,op_dxz));
+	 
+	  int k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	    {
+	      f0xz[k] = 4.*Dl[i].x*Dl[i].z;
+	    }
+	  for(int i=0;i<E::ne;++i,++k)
+	    {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0xz[k] = 4.*(Dl[i0].x*Dl[i1].z+ Dl[i1].x*Dl[i0].z);
+	    } 
+	  assert(k==10);
+	}
+	//cout << " D2 " << endl;
+	if (whatd & Fop_dyz){
+
+	  RN_ f0yz(val('.',0,op_dyz));
+	  
+	  int k=0;
+	  for(int i=0;i<E::nv;++i,++k)
+	    {
+	      f0yz[k] = 4.*Dl[i].y*Dl[i].z;
+	    }
+	  for(int i=0;i<E::ne;++i,++k)
+	    {
+	      int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	      f0yz[k] = 4.*(Dl[i0].y*Dl[i1].z+ Dl[i1].y*Dl[i0].z);
+	    } 
+	  assert(k==10);
+	}
+	/*
+	//cout << " D2 " << endl;
+	RN_ f0xx(val('.',0,op_dxx));
+	RN_ f0yy(val('.',0,op_dyy)); 
+	RN_ f0zz(val('.',0,op_dzz)); 
+	RN_ f0xy(val('.',0,op_dxy));
+	RN_ f0xz(val('.',0,op_dxz));
+	RN_ f0yz(val('.',0,op_dyz));
+	
+	k=0;
+	for(int i=0;i<E::nv;++i,++k)
+	{
+	f0xx[k] = 4.*Dl[i].x*Dl[i].x;
+	f0yy[k] = 4.*Dl[i].y*Dl[i].y;
+	f0zz[k] = 4.*Dl[i].z*Dl[i].z;
+	f0xy[k] = 4.*Dl[i].x*Dl[i].y;
+	f0xz[k] = 4.*Dl[i].x*Dl[i].z;
+	f0yz[k] = 4.*Dl[i].y*Dl[i].z;
+	}
+	for(int i=0;i<E::ne;++i,++k)
+	{
+	int i0=E::nvedge[i][0],i1=E::nvedge[i][1];
+	f0xx[k] = 8.*Dl[i0].x*Dl[i1].x;
+	f0yy[k] = 8.*Dl[i0].y*Dl[i1].y;
+	f0zz[k] = 8.*Dl[i0].z*Dl[i1].z;
+	f0xy[k] = 4.*(Dl[i0].x*Dl[i1].y+ Dl[i1].x*Dl[i0].y);
+	f0xz[k] = 4.*(Dl[i0].x*Dl[i1].z+ Dl[i1].x*Dl[i0].z);
+	f0yz[k] = 4.*(Dl[i0].y*Dl[i1].z+ Dl[i1].y*Dl[i0].z);
+	} 
+	assert(k==10);
+      
+	*/
+      }
+  }
+/* 
+ if (whatd[op_dxx])
+ {  
+ RN_ fxx(val('.',0,op_dxx)); 
+ 
+ fxx[0] = 4*Dl0.x*Dl0.x;
+ fxx[1] = 4*Dl1.x*Dl1.x;
+ fxx[2] = 4*Dl2.x*Dl2.x;
+ fxx[3] =  8*Dl1.x*Dl2.x;
+ fxx[4] =  8*Dl0.x*Dl2.x;
+ fxx[5] =  8*Dl0.x*Dl1.x;
+ }
+ 
+ if (whatd[op_dyy])
+ {  
+ RN_ fyy(val('.',0,op_dyy)); 
+ fyy[0] = 4*Dl0.y*Dl0.y;
+ fyy[1] = 4*Dl1.y*Dl1.y;
+ fyy[2] = 4*Dl2.y*Dl2.y;
+ fyy[3] =  8*Dl1.y*Dl2.y;
+ fyy[4] =  8*Dl0.y*Dl2.y;
+ fyy[5] =  8*Dl0.y*Dl1.y;
+ }
+ if (whatd[op_dxy])
+ {  
+ assert(val.K()>op_dxy);
+ RN_ fxy(val('.',0,op_dxy)); 
+ 
+ fxy[0] = 4*Dl0.x*Dl0.y;
+ fxy[1] = 4*Dl1.x*Dl1.y;
+ fxy[2] = 4*Dl2.x*Dl2.y;
+ fxy[3] =  4*(Dl1.x*Dl2.y + Dl1.y*Dl2.x);
+ fxy[4] =  4*(Dl0.x*Dl2.y + Dl0.y*Dl2.x);
+ fxy[5] =  4*(Dl0.x*Dl1.y + Dl0.y*Dl1.x);
+ }
+ */
+    
+}
+
+     /*
+ R TypeOfFE_P1bLagrange3d::operator()(const FElement & K,const  R3 & PHat,const KN_<R> & u,int componante,int op) const 
+     { 
+	 R u0(u(K(0))), u1(u(K(1))), u2(u(K(2))),u3(u(K(3))),u4(u(K(4)));
+	 R r=0;
+	 if (op==0)
+	   {
+	       R l0=1-PHat.x-PHat.y-PHat.z,l1=PHat.x,l2=PHat.y,l3=PHat.z; 
+	       R l0123=
+	       r = u0*l0+u1*l1+l2*u2+l3*u3;
+	   }
+	 else if(op==op_dx || op==op_dy || op==op_dz) // dx => dy thank to Pichon 27/01/2008 (FH)
+	   { 
+	       const Element & T=K.T;
+	       R3 D[4];
+	       T.Gradlambda(D);
+	       if (op==op_dx)
+		   r =  D[0].x*u0 + D[1].x*u1 + D[2].x*u2+ D[3].x*u3 ;
+	       else if (op==op_dy) 
+		   r =  D[0].y*u0 + D[1].y*u1 + D[2].y*u2+ D[3].y*u3 ;
+	       else 
+		   r =  D[0].z*u0 + D[1].z*u1 + D[2].z*u2+ D[3].z*u3 ;
+	   }
+	 //  cout << r << "\t";
+	 return r;
+     }
+ */    
+     void TypeOfFE_P1bLagrange3d::FB(const What_d whatd,const Mesh & ,const Element & K,const R3 & P,RNMK_ & val) const
+     {
+	 //  const Triangle & K(FE.T);
+	 const R d1=d+1.;
+	 const R d13=d1*d1*d1;
+	 const R d14=d13*d1;
+	 R ll[]={1.-P.sum(),P.x,P.y,P.z}; 
+	 R lb4= (ll[0]*ll[1]*ll[2]*ll[3])*d13; // d1^-4 d1^3 = 1/d1 in G
+	 R lb=lb4*d1; // 1  in G     
+	 R l[5];
+	 for(int i=0;i<4;i++)
+	    l[i]=ll[i]-lb4;  //  1/d1 in G - 1/d1 G =0 
+	 l[4]=lb;
+	 
+	 assert(val.N() >=Element::nv);
+	 assert(val.M()==1 );
+	 
+	 val=0; 
+	 RN_ f0(val('.',0,op_id)); 
+	 
+	 if (whatd & Fop_D0) 
+	   {
+	       f0[0] = l[0];
+	       f0[1] = l[1];
+	       f0[2] = l[2];
+	       f0[3] = l[3];
+	       f0[4] = l[4];
+	   }
+	 if (whatd & Fop_D1)
+	   {
+	       R3 Dl[4];
+	       K.Gradlambda(Dl);
+	       R3 Dlb4 = (
+			 + Dl[0]*(ll[1]*ll[2]*ll[3])
+			 + Dl[1]*(ll[0]*ll[2]*ll[3])
+			 + Dl[2]*(ll[0]*ll[1]*ll[3])
+			 + Dl[3]*(ll[0]*ll[1]*ll[2]) )*d13;
+	       
+	       //for(int i=0;i<4;++i)
+	       //      cout << Dl[i] << endl;
+	      
+	       if (whatd & Fop_dx) 
+		 {
+		     RN_ f0x(val('.',0,op_dx)); 
+		     f0x[0] = Dl[0].x-Dlb4.x;
+		     f0x[1] = Dl[1].x-Dlb4.x;
+		     f0x[2] = Dl[2].x-Dlb4.x;
+		     f0x[3] = Dl[3].x-Dlb4.x;
+		     f0x[4] = Dlb4.x*d1;
+		     
+		 }
+	       
+	       if (whatd & Fop_dy) {
+		   RN_ f0y(val('.',0,op_dy)); 
+		   f0y[0] = Dl[0].y-Dlb4.y;
+		   f0y[1] = Dl[1].y-Dlb4.y;
+		   f0y[2] = Dl[2].y-Dlb4.y;
+		   f0y[3] = Dl[3].y-Dlb4.y;
+		   f0y[4] = Dlb4.y*d1;
+	       }
+	       
+	       if (whatd & Fop_dz) {
+		   RN_ f0z(val('.',0,op_dz)); 
+		   f0z[0] = Dl[0].z-Dlb4.z;
+		   f0z[1] = Dl[1].z-Dlb4.z;
+		   f0z[2] = Dl[2].z-Dlb4.z;
+		   f0z[3] = Dl[3].z-Dlb4.z;
+		   f0z[4] = Dlb4.z*d1;
+		   
+	       }
+	   }
+	 else if (whatd & Fop_D2)
+	     ffassert(0); // a faire ...
+	 //  cout << val << endl;
+     }
+
+     
+     
+     class TypeOfFE_RT0_3d : public    GTypeOfFE<Mesh3>  { 
+     public:  
+	 typedef Mesh3 Mesh;
+	 typedef  Mesh3::Element  Element;
+	 
+	 typedef GFElement<Mesh3> FElement;
+	 static int dfon[];
+	 static const int d=Mesh::Rd::d;
+	 TypeOfFE_RT0_3d();
+	 int edgeface[4][3] ;
+	void FB(const What_d whatd,const Mesh & Th,const Mesh3::Element & K,const Rd &P, RNMK_ & val) const;
+	void  set(const Mesh & Th,const Element & K,InterpolationMatrix<RdHat> & M,int ocoef,int odf,int *nump  ) const;
+     } ;
+     int TypeOfFE_RT0_3d::dfon[]={0,0,1,0}; 
+     
+
+     TypeOfFE_RT0_3d::TypeOfFE_RT0_3d(): GTypeOfFE<Mesh3>(dfon,d,1,3*3*4,6,false,true)
+     { 	
+       //  integration on middle of edge (light ) on  each face .. 
+	R3 Pt[]= {R3(0.,0.,0.), R3(1.,0.,0.),R3(0.,1.,0.),R3(0.,0.,1.)};
+	for (int i=0;i<Element::ne;++i)
+          this->PtInterpolation[i]=(Pt[Element::nvedge[i][0]]+Pt[Element::nvedge[i][1]])*0.5;
+	 
+	 
+//	 static const int  nvfaceTet[4][3]  ={{3,2,1}, {0,2,3},{ 3,1,0},{ 0,1,2}}  ;//{ {2,1,3},{0,2,3},{1,0,3},{0,1,2} };
+//	    { {0,1},{0,2},{0,3},{1,2},{1,3},{2,3} };
+	 //     0     1     2     3     4     5
+       {
+	   int i=0;
+	   for (int f=0;f<4;f++)
+	       for (int e=0,i=0;e<6;e++)
+		   if ((Element::nvedge[e][0] !=f)  && (Element::nvedge[e][1]!=f))
+		       edgeface[f][i++]=e; 
+      }
+       {
+	 int i=0;
+	 for (int f=0;f<4;f++) 
+	   {
+	     //  cout << " face : " << f << endl;
+	     for (int p=0;p<3;p++) 
+	     {
+		 int e= edgeface[f][p] ; 
+		// cout << "  , "  << this->PtInterpolation[e];
+		 for (int c=0;c<3;c++,i++) 
+
+	           {
+	             this->pInterpolation[i]=e;
+	             this->cInterpolation[i]=c;
+		     this->dofInterpolation[i]=f;
+	             this->coefInterpolation[i]=0.;	       
+	           }
+	     }
+	   //cout <<  endl;
+	   }
+       }
+       
+     }
+     void  TypeOfFE_RT0_3d::set(const Mesh & Th,const Element & K,InterpolationMatrix<RdHat> & M ,int ocoef,int odf,int *nump) const
+     {
+	 //   compute de coef d'interpolation
+	// M.coef 
+	 int i=ocoef;
+	 for (int f=0;f<4;f++) 
+	   {
+	       R3 N=K.N(f);//  exterior and  ||N|| = 2* area f
+	       N *= K.faceOrient(f)/6.;
+	       for (int p=0;p<3;p++) 
+		 {
+		     int e= edgeface[f][p] ; 
+		     for (int c=0;c<3;c++,i++) 
+			 
+		       {
+			   //this->pInterpolation[i]=e;
+			   //this->cInterpolation[i]=c;
+			   //this->dofInterpolation[i]=f;
+			   M.coef[i]=N[c];	       
+		       }
+		 }}
+		// cout << " M.coef :" << M.coef << endl;
+	 //ffassert(i==M.ncoef && M.np == 6 );
+ 	 
+     }
+     void  TypeOfFE_RT0_3d::FB(const What_d whatd,const Mesh & Th,const Mesh3::Element & K,const Rd &P, RNMK_ & val) const
+     {
+	 assert(val.N() >=4);
+	 assert(val.M()==3 );
+	 // wi = signe * (x - qi)/ (volume*d)   
+	 val=0; 
+	 
+	 R cc =1./(d*K.mesure());
+	 R ci[4]={ cc*K.faceOrient(0),cc*K.faceOrient(1),cc*K.faceOrient(2),cc*K.faceOrient(3)};
+	 
+	 if (whatd & Fop_D0) 
+	   {
+	       R3 X=K(P);
+	       int k=0;
+	       for(int i=0;i<4;++i)
+		 { R3 wi=(X-K[i])*ci[i];
+		     val(i,0,op_id) = wi.x ;
+		     val(i,1,op_id) = wi.y ;
+		     val(i,2,op_id) = wi.z ;
+		     //cout  << "RT 3d  "<<i << " "<< X << " " <<wi << " fo: " << K.faceOrient(i) <<endl;
+		 }
+	   }
+	 
+	 if (whatd & Fop_D1)
+	   {
+	       RN_ Ci(ci,4);
+	       if (whatd & Fop_dx) 
+		   val('.',0,op_dx) = Ci;
+	       if (whatd & Fop_dy) 
+		   val('.',1,op_dy) = Ci;	       
+	       if (whatd & Fop_dz) 
+		   val('.',2,op_dz) = Ci;
+	        //cout  << "RT 3d  "<< val('.','.',op_dz) << endl;
+	   }	 
+	 
+     }     
+     
+
+     class TypeOfFE_Edge0_3d  :public   GTypeOfFE<Mesh3>  { 
+     public:  
+	 typedef Mesh3 Mesh;
+	 typedef  Mesh3::Element  Element;
+	 
+	 typedef GFElement<Mesh3> FElement;
+	 static int dfon[];
+	 static const int d=Mesh::Rd::d;
+	 static const GQuadratureFormular<R1> QFe;
+	 int edgeface[4][3] ;
+	 TypeOfFE_Edge0_3d();
+	 void FB(const What_d whatd,const Mesh & Th,const Mesh3::Element & K,const Rd &P, RNMK_ & val) const;
+	 void  set(const Mesh & Th,const Element & K,InterpolationMatrix<RdHat> & M ,int ocoef,int odf,int *nump  ) const;
+     } ;
+     int TypeOfFE_Edge0_3d::dfon[]={0,1,0,0}; 
+     
+     const  GQuadratureFormular<R1> TypeOfFE_Edge0_3d::QFe(-1+2*2,2,GaussLegendre(2),true);
+     
+     TypeOfFE_Edge0_3d::TypeOfFE_Edge0_3d(): GTypeOfFE<Mesh3>(TypeOfFE_Edge0_3d::dfon,d,1,Element::ne*3*QFe.n,Element::ne*QFe.n,false,true)
+     { 	
+	 assert(QFe.n);
+	 //  integration on edge use QFe
+	 R3 Pt[]= {R3(0.,0.,0.), R3(1.,0.,0.),R3(0.,1.,0.),R3(0.,0.,1.)};
+	 for (int e=0,i=0;e<Element::ne;++e)
+	     for(int q=0;q<QFe.n;++q,++i)
+	       {
+		   double x=QFe[q].x;
+		   this->PtInterpolation[i]=Pt[Element::nvedge[e][0]]*x+Pt[Element::nvedge[e][1]]*(1-x);
+	       }
+       {
+	   int i=0,p=0;
+	   for (int e=0;e<Element::ne;e++) 
+	     {
+		 for(int q=0;q<QFe.n;++q,++p) 
+		     for (int c=0;c<3;c++,i++) 
+		       {
+			   this->pInterpolation[i]=p;
+			   this->cInterpolation[i]=c;
+			   this->dofInterpolation[i]=e;
+			   this->coefInterpolation[i]=0.;	       
+		       }
+		 
+		 
+	     }
+       }
+	// cout <<  " ++ TypeOfFE_Edge0_3d():"<< this->PtInterpolation << endl;
+     }
+     void  TypeOfFE_Edge0_3d::set(const Mesh & Th,const Element & K,InterpolationMatrix<RdHat> & M ,int ocoef,int odf,int *nump ) const
+     {
+	 // compute de coef d'interpolation
+	 // M.coef 
+	 int i=ocoef,p=0;
+	 for (int e=0;e<Element::ne;++e) 
+	   {
+	       R3 E=K.Edge(e);//  exterior and  ||N|| = 2* area f
+	       if(! K.EdgeOrientation(e)) E=-E;
+	       for(int q=0;q<QFe.n;++q,++p)  
+		    for (int c=0;c<3;c++,i++) 
+			     
+			   {
+			      // this->pInterpolation[i]=p;
+			       //this->cInterpolation[i]=c;
+			       //this->dofInterpolation[i]=e;
+			       M.coef[i]=E[c]*QFe[q].a;	       
+			   }
+		 }
+	 
+	// ffassert(i==M.ncoef && M.np == p );
+ 	 
+     }
+     void  TypeOfFE_Edge0_3d::FB(const What_d whatd,const Mesh & Th,const Mesh3::Element & K,const Rd &P, RNMK_ & val) const
+     {
+	 assert(val.N() >=6);
+	 assert(val.M()==3 );
+         R l[]={1.-P.sum(),P.x,P.y,P.z}; 
+	 R3 D[4];
+	 K.Gradlambda(D);
+	 
+	 // wi = signe * (x - qi)/ (volume*d)   
+	 val=0; 
+	 //  i,j : l1 grad lj - lj grad lj
+	 // int_i^j  grad lj . t_ij = 1
+	 
+	 
+	 bool  se[]={ K.EdgeOrientation(0), K.EdgeOrientation(1), K.EdgeOrientation(2), 
+	 K.EdgeOrientation(3), K.EdgeOrientation(4), K.EdgeOrientation(5)};
+	 
+	 if (whatd & Fop_D0) 
+	   {
+	       R3 X=K(P);
+	       int k=0;
+	       for(int i=0;i<6;++i)
+		 { 
+		     int i0=Element::nvedge[i][0],i1=Element::nvedge[i][1];
+		     if( !se[i]) Exchange(i0,i1);
+		     R3 wi = l[i0]*D[i1]-l[i1]*D[i0];
+		     val(i,0,op_id) = wi.x ;
+		     val(i,1,op_id) = wi.y ;
+		     val(i,2,op_id) = wi.z ;
+		    // cout  << "Edge0 3d  "<<i << " "<< X << " " <<wi << " fo: " <<se[i] <<endl;
+		 }
+	   }
+	 
+	 if (whatd & Fop_D1)
+	     
+	     for(int i=0;i<6;++i)
+	       { 
+		   int i0=Element::nvedge[i][0],i1=Element::nvedge[i][1];
+		   if( !se[i]) Exchange(i0,i1);
+		   if (whatd & Fop_dx) 
+		     {
+			 R3 wi = D[i0].x*D[i1]-D[i1].x*D[i0];		    
+			 val(i,0,op_dx) = wi.x ;
+			 val(i,1,op_dx) = wi.y ;
+			 val(i,2,op_dx) = wi.z ;
+		     }
+		   if (whatd & Fop_dy) 
+		     {
+			 R3 wi = D[i0].y*D[i1]-D[i1].y*D[i0];		    
+			 val(i,0,op_dy) = wi.x ;
+			 val(i,1,op_dy) = wi.y ;
+			 val(i,2,op_dy) = wi.z ;
+		     }
+		   if (whatd & Fop_dz) 
+		     {
+			 R3 wi = D[i0].z*D[i1]-D[i1].z*D[i0];		    
+			 val(i,0,op_dz) = wi.x ;
+			 val(i,1,op_dz) = wi.y ;
+			 val(i,2,op_dz) = wi.z ;
+		     }
+		   
+	       }	 
+	 
+     }     
+     
+static TypeOfFE_P0Lagrange3d  P0_3d;
+GTypeOfFE<Mesh3> & P0Lagrange3d(P0_3d);
+
+static TypeOfFE_P1Lagrange3d  P1_3d;
+GTypeOfFE<Mesh3> & P1Lagrange3d(P1_3d);
+
+static TypeOfFE_P2Lagrange3d  P2_3d;
+GTypeOfFE<Mesh3> & P2Lagrange3d(P2_3d);
+
+static TypeOfFE_P1bLagrange3d  P1b_3d;
+GTypeOfFE<Mesh3> & P1bLagrange3d(P1b_3d);
+
+static TypeOfFE_RT0_3d  RT0_3d;
+GTypeOfFE<Mesh3> & RT03d(RT0_3d);
+
+static TypeOfFE_Edge0_3d  Edge0_3d;
+GTypeOfFE<Mesh3> & Edge03d(Edge0_3d);
+
+     
+
+
+
+template<> GTypeOfFE<Mesh3> & DataFE<Mesh3>::P0=P0_3d; 
+template<> GTypeOfFE<Mesh3> & DataFE<Mesh3>::P1=P1_3d; 
+template<> GTypeOfFE<Mesh3> & DataFE<Mesh3>::P2=P2_3d; 
+
+
+ }
+
diff --git a/src/femlib/PkLagrange.hpp b/src/femlib/PkLagrange.hpp
new file mode 100644
index 0000000..1449da6
--- /dev/null
+++ b/src/femlib/PkLagrange.hpp
@@ -0,0 +1,132 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :Generic Pk Lagrange finite element class
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN   FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#include "FESpacen.hpp"
+
+namespace Fem2D {
+
+template<class Rd,class E>
+static void SetPtPk(Rd *Pt,const int *dfon,int nn)
+{  // P0 P1 et P2 , P1b 
+    const int d= E::Rd::d;
+    int k=0;
+    
+    if(dfon[0])
+      {
+	for(int i=0;i<=d;++i)
+	  Pt[k++]=Rd();
+	
+	for(int i=0;i<d;++i)
+	  Pt[i+1][i]=1.;
+      }
+
+    if(dfon[1]&& d !=1)
+	for(int i=0;i<E::ne;++i)
+	    Pt[k++] = (Pt[E::nvedge[i][0]]+Pt[E::nvedge[i][1]])*0.5;
+    
+    if(dfon[d]==1) 
+	Pt[k++]=Rd::diag(1./(d+1));
+    if(nn != k)
+      { 
+	cout << nn << " == " << k << " d = "<< d << " " << dfon[0]<< dfon[1]<<dfon[2]<<dfon[3]<<" "<< E::ne << endl;
+	assert(nn==k); 
+      }  
+    if(verbosity>9)
+      cout << " Pk = " << KN_<Rd>(Pt,nn)<<"\n";
+    
+}
+
+//  a class of Lagrange Pk finite element 
+template<class MMesh>
+class TypeOfFE_Lagrange: public  GTypeOfFE<MMesh>
+{
+  //typedef typename  MMesh Mesh;
+public:
+  typedef   MMesh Mesh;
+  typedef typename  Mesh::Element Element;
+  typedef typename  Element::Rd Rd;
+  typedef typename  Element::RdHat RdHat;
+  static const int d=Rd::d;
+  struct A4 {
+    int dfon[4];
+    
+    A4(int k) {
+      if(k==0) 
+	{// P0
+	  dfon[0]=dfon[1]=dfon[2]=dfon[3]=0;
+	  dfon[d]=1;
+	}
+      else if(k==-1) //  P1b. add  FH   March 2009 
+	  {
+	      dfon[0]=1;
+	      dfon[1]=dfon[2]=dfon[3]=0;
+	      dfon[d]=1;
+	  }	
+      else
+	{
+	  dfon[0]=1;
+	  dfon[1]=max(k-1,0);
+	  dfon[2]=d>1?max(k-2,0):0;
+	  dfon[3]=d>2?max(k-3,0):0;}
+    if(verbosity>9)      
+      cout << "A4 "<<   k<< " "   <<dfon[0]<< dfon[1]<<dfon[2]<<dfon[3]<<endl;
+    }
+    operator const  int  * () const {return dfon;}
+  };
+  
+  RdHat *Pt;
+  TypeOfFE_Lagrange(int k):
+    //              dfon ,N,nsub(graphique) ,  const mat interpolation , discontinuous 
+    GTypeOfFE<Mesh>(A4(k),1,k==-1?-1:Max(k,1),k<=2,k==0)
+  {
+    int n=this->NbDoF;
+    if(verbosity>9)    
+    cout << "\n +++ P"<<k<<" : ndof : "<< n <<endl;
+    SetPtPk<RdHat,Element> (this->PtInterpolation,this->ndfOn(),this->NbDoF);
+    if(verbosity>9)    cout << this->PtInterpolation<< endl;
+    for (int i=0;i<n;i++) 
+      {
+	this->pInterpolation[i]=i;
+	this->cInterpolation[i]=0;
+	this->dofInterpolation[i]=i;
+	this->coefInterpolation[i]=1.;
+      }
+  }
+  ~TypeOfFE_Lagrange(){ } //cout << "TypeOfFE_Lagrange"<< this->NbDoF<<endl;}
+private:
+  TypeOfFE_Lagrange( const TypeOfFE_Lagrange &) ;
+  void operator=( const TypeOfFE_Lagrange &) ;
+};
+
+
+ }
diff --git a/src/femlib/QuadratureFormular.cpp b/src/femlib/QuadratureFormular.cpp
new file mode 100644
index 0000000..2ff98ef
--- /dev/null
+++ b/src/femlib/QuadratureFormular.cpp
@@ -0,0 +1,751 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN   FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ 
+For 2d hight order formula: 
+ Thanks to http://xyz.lanl.gov/format/math.NA/0501496
+  Mathematics, abstract
+  math.NA/0501496
+  From: Mark Taylor [view email]
+  Date: Thu, 27 Jan 2005 19:17:37 GMT   (27kb)
+
+    Several new quadrature formulas for polynomial integration in the  triangle
+    Authors:  Mark A. Taylor,  Beth A. Wingate,  Len P. Bos
+    Comments: 14 pages, 14 figures, 5 pages of tabulated quadrature points
+    Report-no: SAND2005-0034J
+
+For 3d  order formula:
+
+  from: http://www.cs.kuleuven.be/~nines/research/ecf/mtables.html
+
+---------------------------------------------------------------------------
+| Name   : Ronald  Cools               |                                  |
+|          Prof. Dr. ir.               |        Address:                  |
+| Email  : Ronald.Cools at cs.kuleuven.be | Katholieke Universiteit Leuven   |
+|                                      | Department of Computer Science   |
+| http://www.cs.kuleuven.be/~ronald/   | Celestijnenlaan 200 A            |
+| Fax    : +(32) 16 32 79 96           | B-3001 HEVERLEE                  |
+| Phone  : +(32) 16 32 75 62           | BELGIUM                          |
+---------------------------------------------------------------------------
+ */
+
+
+
+#include <cstdlib>
+#include <cmath>
+#include <iostream>
+#include <fstream>
+using namespace std;
+#include "error.hpp"
+
+#include "ufunction.hpp"
+
+#include "QuadratureFormular.hpp"
+
+namespace Fem2D {
+  
+template<class QF,int ON> 
+  QF  * QF_exact(int exact,QF * p=0)
+  {
+    exact=max(0,exact);
+    const int N=100;
+    assert(exact<N&& exact>=0);
+    static QF ** a=0;
+    if(a==0)
+      { //    
+	a = new  QF*[N];
+	assert(a);
+	for(int i=0;i<N;++i)
+	  a[i]=0;
+      }
+    assert(a && exact >=0 && exact < N);
+    if ( p  )
+      {
+	//cout << endl << " QF " << exact << " " << p->exact << " " << p->n << endl;;
+	for( int i=0;i<=exact;++i)
+	  {
+	    if( a[i]== 0 || a[i]->n > p->n)
+	      a[i]= p;
+	    //  cout << " QF: on " << ON << " exact P_" << i << " : "<< a[i]->n << endl;
+	  }
+      }
+    else
+      p=a[exact];
+    return p;
+  }
+
+
+
+template<class Rd>
+GQuadratureFormular<Rd> * QF_Simplex(int exact)
+ {
+   return  QF_exact<GQuadratureFormular<Rd>,Rd::d+1>(exact);
+ }
+
+// explict instantiation 
+template  GQuadratureFormular<R1> * QF_Simplex<R1>(int exact);
+template  GQuadratureFormular<R2> * QF_Simplex<R2>(int exact);
+template  GQuadratureFormular<R3> * QF_Simplex<R3>(int exact);
+
+
+
+
+template<class Rd>    
+ostream& operator <<(ostream& f,const  GQuadraturePoint<Rd> & p) 
+      { f << '{' << (const R) p << '\t' << (const Rd &) p << '}' ; 
+        return f;}
+
+template<class Rd>    
+ostream& operator <<(ostream& f, const GQuadratureFormular<Rd>  & fi) 
+      { f << "nb de point integration " << fi.n << ", adr = " << &f << endl;
+        for (int i=0;i<fi.n;i++) f << '\t' << fi[i] << endl; 
+        return f;}
+
+// ----------------------------------------------------------------------
+
+
+static  GQuadraturePoint<R2>  P_QuadratureFormular_T_1[1] = {
+  GQuadraturePoint<R2>(1.,R2(1./3.,1./3.)) };
+
+const GQuadratureFormular<R2> QuadratureFormular_T_1(1,1,P_QuadratureFormular_T_1);
+// ----------------------------------------------------------------------
+static  GQuadraturePoint<R2> P_QuadratureFormular_T_1lump[3] = {
+  GQuadraturePoint<R2>(1./3.,R2(0.,0.)) ,
+  GQuadraturePoint<R2>(1./3.,R2(1.,0.)) ,
+  GQuadraturePoint<R2>(1./3.,R2(0.,1.)) };
+
+GQuadratureFormular<R2> const QuadratureFormular_T_1lump(1,3,P_QuadratureFormular_T_1lump);
+// ----------------------------------------------------------------------
+
+static GQuadraturePoint<R2> P_QuadratureFormular_T_2[3] = {
+  GQuadraturePoint<R2>(1./3.,R2(0.5,0.5)) ,
+  GQuadraturePoint<R2>(1./3.,R2(0.0,0.5)) ,
+  GQuadraturePoint<R2>(1./3.,R2(0.5,0.0)) };
+
+GQuadratureFormular<R2> const QuadratureFormular_T_2(2,3,P_QuadratureFormular_T_2);
+// ----------------------------------------------------------------------
+static  GQuadraturePoint<R2> P_QuadratureFormular_T_2_4P1[9] = {
+  GQuadraturePoint<R2>(1./12.,R2(0.25,0.75)) ,
+      GQuadraturePoint<R2>(1./12.,R2(0.75,0.25)) ,
+      GQuadraturePoint<R2>(1./12.,R2(0.0,0.25)) ,
+      GQuadraturePoint<R2>(1./12.,R2(0.0,0.75)) ,
+      GQuadraturePoint<R2>(1./12.,R2(0.25,0.0)) ,
+      GQuadraturePoint<R2>(1./12.,R2(0.75,0.0)) ,
+      GQuadraturePoint<R2>(1./6.,R2(0.25,0.25)) ,
+      GQuadraturePoint<R2>(1./6.,R2(0.25,0.50)) ,
+      GQuadraturePoint<R2>(1./6.,R2(0.50,0.25))       
+      };
+
+GQuadratureFormular<R2> const QuadratureFormular_T_2_4P1(2,9,P_QuadratureFormular_T_2_4P1);
+// ----------------------------------------------------------------------
+// STROUD page  314 
+// -----------------------------
+const R sqrt15 = 3.87298334620741688517926539978;
+const R t_T5 =1.E0/3.E0        ,                           A_T5 = 0.225E0;
+const R r_T5 = (6-sqrt15)/21   ,  s_T5 = (9+2*sqrt15)/21 , B_T5 = (155-sqrt15)/1200;
+const R u_T5 = (6+sqrt15)/21   ,  v_T5 = (9-2*sqrt15)/21 , C_T5 = (155+sqrt15)/1200;
+// OK cette  formule  est OK 
+static  GQuadraturePoint<R2> P_QuadratureFormular_T_5[] = {
+  GQuadraturePoint<R2>(A_T5,R2(t_T5,t_T5)),
+  GQuadraturePoint<R2>(B_T5,R2(r_T5,r_T5)),
+  GQuadraturePoint<R2>(B_T5,R2(r_T5,s_T5)),
+  GQuadraturePoint<R2>(B_T5,R2(s_T5,r_T5)),
+  GQuadraturePoint<R2>(C_T5,R2(u_T5,u_T5)),
+  GQuadraturePoint<R2>(C_T5,R2(u_T5,v_T5)),
+  GQuadraturePoint<R2>(C_T5,R2(v_T5,u_T5))
+};
+const GQuadratureFormular<R2> QuadratureFormular_T_5(5,7,P_QuadratureFormular_T_5);
+// ------------------
+//----
+
+ 
+// Thanks to http://xyz.lanl.gov/format/math.NA/0501496
+/*
+Mathematics, abstract
+math.NA/0501496
+From: Mark Taylor [view email]
+Date: Thu, 27 Jan 2005 19:17:37 GMT   (27kb)
+
+Several new quadrature formulas for polynomial integration in the  triangle
+Authors:  Mark A. Taylor,  Beth A. Wingate,  Len P. Bos
+Comments: 14 pages, 14 figures, 5 pages of tabulated quadrature points
+Report-no: SAND2005-0034J
+
+*/
+// ----------------------------------------------------------------------
+// awk '/15:/,/21:/ {print "GQuadraturePoint<R2>(" $3 "/2," $1"," $2"),"}' coords.txt   
+static  GQuadraturePoint<R2> P_QuadratureFormular_T_7[] = {  
+GQuadraturePoint<R2>(0.0102558174092/2,R2(1.0000000000000,0.0000000000000)),
+GQuadraturePoint<R2>(0.0102558174092/2,R2(0.0000000000000,0.0000000000000)),
+GQuadraturePoint<R2>(0.0102558174092/2,R2(0.0000000000000,1.0000000000000)),
+GQuadraturePoint<R2>(0.1116047046647/2,R2(0.7839656651012,0.0421382841642)),
+GQuadraturePoint<R2>(0.1116047046647/2,R2(0.1738960507345,0.7839656651012)),
+GQuadraturePoint<R2>(0.1116047046647/2,R2(0.1738960507345,0.0421382841642)),
+GQuadraturePoint<R2>(0.1116047046647/2,R2(0.0421382841642,0.1738960507345)),
+GQuadraturePoint<R2>(0.1116047046647/2,R2(0.7839656651012,0.1738960507345)),
+GQuadraturePoint<R2>(0.1116047046647/2,R2(0.0421382841642,0.7839656651012)),
+GQuadraturePoint<R2>(0.1679775595335/2,R2(0.4743880861752,0.4743880861752)),
+GQuadraturePoint<R2>(0.1679775595335/2,R2(0.4743880861752,0.0512238276497)),
+GQuadraturePoint<R2>(0.1679775595335/2,R2(0.0512238276497,0.4743880861752)),
+GQuadraturePoint<R2>(0.2652238803946/2,R2(0.2385615300181,0.5228769399639)),
+GQuadraturePoint<R2>(0.2652238803946/2,R2(0.5228769399639,0.2385615300181)),
+GQuadraturePoint<R2>(0.2652238803946/2,R2(0.2385615300181,0.2385615300181))
+};
+const GQuadratureFormular<R2> QuadratureFormular_T_7(7,15,P_QuadratureFormular_T_7);
+
+// awk '/21:/,/28:/ {print "GQuadraturePoint<R2>(" $3 "/2," $1"," $2"),"}' coords.txt
+static GQuadraturePoint<R2> P_QuadratureFormular_T_9[] = {  
+GQuadraturePoint<R2>(0.0519871420646/2,R2(0.0451890097844,0.0451890097844)),
+GQuadraturePoint<R2>(0.0519871420646/2,R2(0.0451890097844,0.9096219804312)),
+GQuadraturePoint<R2>(0.0519871420646/2,R2(0.9096219804312,0.0451890097844)),
+GQuadraturePoint<R2>(0.0707034101784/2,R2(0.7475124727339,0.0304243617288)),
+GQuadraturePoint<R2>(0.0707034101784/2,R2(0.2220631655373,0.0304243617288)),
+GQuadraturePoint<R2>(0.0707034101784/2,R2(0.7475124727339,0.2220631655373)),
+GQuadraturePoint<R2>(0.0707034101784/2,R2(0.2220631655373,0.7475124727339)),
+GQuadraturePoint<R2>(0.0707034101784/2,R2(0.0304243617288,0.7475124727339)),
+GQuadraturePoint<R2>(0.0707034101784/2,R2(0.0304243617288,0.2220631655373)),
+GQuadraturePoint<R2>(0.0909390760952/2,R2(0.1369912012649,0.2182900709714)),
+GQuadraturePoint<R2>(0.0909390760952/2,R2(0.6447187277637,0.2182900709714)),
+GQuadraturePoint<R2>(0.0909390760952/2,R2(0.1369912012649,0.6447187277637)),
+GQuadraturePoint<R2>(0.0909390760952/2,R2(0.2182900709714,0.6447187277637)),
+GQuadraturePoint<R2>(0.0909390760952/2,R2(0.2182900709714,0.1369912012649)),
+GQuadraturePoint<R2>(0.0909390760952/2,R2(0.6447187277637,0.1369912012649)),
+GQuadraturePoint<R2>(0.1032344051380/2,R2(0.0369603304334,0.4815198347833)),
+GQuadraturePoint<R2>(0.1032344051380/2,R2(0.4815198347833,0.0369603304334)),
+GQuadraturePoint<R2>(0.1032344051380/2,R2(0.4815198347833,0.4815198347833)),
+GQuadraturePoint<R2>(0.1881601469167/2,R2(0.4036039798179,0.1927920403641)),
+GQuadraturePoint<R2>(0.1881601469167/2,R2(0.4036039798179,0.4036039798179)),
+GQuadraturePoint<R2>(0.1881601469167/2,R2(0.1927920403641,0.4036039798179))
+};
+const GQuadratureFormular<R2> QuadratureFormular_T_9(9,21,P_QuadratureFormular_T_9);
+
+
+
+
+
+  // Computation of nodes and weights for a Gauss-Legendre quadrature formula
+  // on  [0,1] seg.
+typedef GQuadraturePoint<R1> QP1;
+QP1 *  GaussLegendre(int nn)
+// : exact(nn*2-1),n(nn),p(new Point[nn])
+  {
+    QP1 *p=new QP1[nn];
+    int n=nn;
+    double r, r1, p1, p2, p3, dp3;
+    double eps=1e-16;
+    const double pi=M_PI;
+    
+    for(int i = 0,ii=n; i <= (n+1)/2-1; i++)
+      { 
+	ii-=1;
+	r = cos(pi*(4*i+3)/(4*n+2));
+        do
+	  {
+            p2 = 0;
+            p3 = 1;
+            for(int j = 0; j <= n-1; j++)
+	      {
+                p1 = p2;
+                p2 = p3;
+                p3 = ((2*j+1)*r*p2-j*p1)/(j+1);
+	      }
+	    
+            dp3 = n*(r*p3-p2)/(r*r-1);
+            r1 = r;
+            r = r-p3/dp3;
+	  }
+        while(fabs(r-r1)>=eps*(1+fabs(r))*100);
+        p[i].x = 0.5 +r/2;
+        p[ii].x =0.5  -r/2;
+        p[i].a=p[ii].a= 1./((1.-r*r)*dp3*dp3);
+	
+      }
+    
+    //    Check();
+    return p;
+  }
+/*
+void QuadratureFormular1d::Check()
+{
+    QF_exact<QuadratureFormular1d,2>(exact,this);
+    int err=0;
+    for(int m=0;m<=exact;++m)
+    {
+	R ve = 1./ ( m+1), v=0.;
+	for (int i=0;i<n;++i)
+	    v += p[i].a*pow(p[i].x,m);
+	if (abs( ve-v)/ve > 1.e-8)
+	{
+	    cout << " erreur QuadratureFormular1d  n= " << n  << " exact = " << exact << endl;
+	    cout << " int x^" <<m << " == " << ve << " ! = " << v  << endl; 
+	    err++;
+	}
+    }
+    assert(err==0);	
+}
+*/
+static const R gauss_n2_1=  (1-sqrt(1./3.))/2;
+static const R gauss_n2_2=  1 - gauss_n2_1;
+
+const R gauss_n3_0=  0.5 ;
+const R gauss_n3_1=  (1-sqrt(3./5.)) /2  ;
+const R gauss_n3_2 =  1 - gauss_n3_1 ;
+
+const R pgauss_n3_0=  8./18.;
+const R pgauss_n3_1=  5./18.;
+const R pgauss_n3_2=  5./18.;
+
+const R pgauss1_n4_a= (18.+sqrt(30.))/36.;
+const R pgauss1_n4_b= (18.-sqrt(30.))/36.;
+const R gauss1_n4_a=  sqrt( 525. - 70.* sqrt(30.))/35.;
+const R gauss1_n4_b=  sqrt( 525. + 70.* sqrt(30.))/35.;
+
+const R pgauss1_n5_0 = 128./225.;
+const R pgauss1_n5_a= (322+13.*sqrt(70.))/900.;
+const R pgauss1_n5_b= (322-13.*sqrt(70.))/900.;
+const R gauss1_n5_a=  sqrt(245.-14.*sqrt(70.))/21.;
+const R gauss1_n5_b=  sqrt(245.+14.*sqrt(70.))/21.;
+
+const QuadratureFormular1d QF_GaussLegendre3(5,
+                  QuadratureFormular1d::QP(pgauss_n3_0,gauss_n3_0),
+                  QuadratureFormular1d::QP(pgauss_n3_1,gauss_n3_1),
+                  QuadratureFormular1d::QP(pgauss_n3_2,gauss_n3_2)); 
+                    
+const QuadratureFormular1d QF_GaussLegendre2(3,
+                  QuadratureFormular1d::QP(0.5,gauss_n2_1),
+                  QuadratureFormular1d::QP(0.5,gauss_n2_2)); 
+
+const QuadratureFormular1d QF_GaussLegendre1(1,QuadratureFormular1d::QP(1,0.5)); 
+
+const QuadratureFormular1d QF_LumpP1_1D(1,
+                  QuadratureFormular1d::QP(0.5,0.),
+                  QuadratureFormular1d::QP(0.5,1.)); 
+
+
+const QuadratureFormular1d QF_GaussLegendre4(7,
+					     QuadratureFormular1d::QP(pgauss1_n4_a/2.,(1.+gauss1_n4_a)/2.),
+					     QuadratureFormular1d::QP(pgauss1_n4_a/2.,(1.-gauss1_n4_a)/2.),
+					     QuadratureFormular1d::QP(pgauss1_n4_b/2.,(1.+gauss1_n4_b)/2.),
+					     QuadratureFormular1d::QP(pgauss1_n4_b/2.,(1.-gauss1_n4_b)/2.)
+					     ); 
+
+const QuadratureFormular1d QF_GaussLegendre5(-1+2*5,5,GaussLegendre(5),true);
+const QuadratureFormular1d QF_GaussLegendre6(-1+2*6,6,GaussLegendre(6),true);
+const QuadratureFormular1d QF_GaussLegendre7(-1+2*7,7,GaussLegendre(7),true);
+const QuadratureFormular1d QF_GaussLegendre8(-1+2*8,8,GaussLegendre(8),true);
+const QuadratureFormular1d QF_GaussLegendre9(-1+2*9,9,GaussLegendre(9),true);
+const QuadratureFormular1d QF_GaussLegendre10(-1+2*10,10,GaussLegendre(10),true);
+
+
+
+/*
+Region: Simplex 
+Dimension: 3 
+Degree: 3 
+Points: 5 
+Structure: Fully symmetric 
+Rule struct: 0 0 0 0 0 0 1 1 0 0 0 
+Generator: [ Fully symmetric ] 
+( 0.25, 0.25, 0.25, ) 
+Corresponding weight: 
+-0.133333333333333333333333333333333,
+Generator: [ Fully symmetric ] 
+( 0.166666666666666666666666666666666, 
+0.166666666666666666666666666666666, 
+0.166666666666666666666666666666666, 
+) 
+Corresponding weight: 
+0.075,
+
+Region: Simplex 
+Dimension: 3 
+Degree: 4 
+Points: 11 
+Structure: Fully symmetric 
+Rule struct: 0 0 0 0 0 0 1 1 1 0 0 
+Generator: [ Fully symmetric ] 
+( 0.25, 0.25, 0.25, ) 
+Corresponding weight: 
+-0.0131555555555555555555555555555555,
+Generator: [ Fully symmetric ] 
+( 0.0714285714285714285714285714285714, 
+0.0714285714285714285714285714285714, 
+0.0714285714285714285714285714285714, 
+) 
+Corresponding weight: 
+10 ^ -3 x 7.62222222222222222222222222222222,
+
+Generator: [ Fully symmetric ] 
+( 0.399403576166799204996102147461640, 
+0.399403576166799204996102147461640, 
+0.100596423833200795003897852538359, 
+) 
+Corresponding weight: 
+0.0248888888888888888888888888888888,
+
+
+Region: Simplex 
+Dimension: 3 
+Degree: 6 
+Points: 24 
+Structure: Fully symmetric 
+Rule struct: 0 0 0 0 0 0 0 3 0 1 0 
+Generator: [ Fully symmetric ] 
+( 0.214602871259152029288839219386284, 
+0.214602871259152029288839219386284, 
+0.214602871259152029288839219386284, 
+) 
+Corresponding weight: 
+10 ^ -3 x 6.65379170969458201661510459291332,
+Generator: [ Fully symmetric ] 
+( 0.0406739585346113531155794489564100, 
+0.0406739585346113531155794489564100, 
+0.0406739585346113531155794489564100, 
+) 
+Corresponding weight: 
+10 ^ -3 x 1.67953517588677382466887290765614,
+
+Generator: [ Fully symmetric ] 
+( 0.322337890142275510343994470762492, 
+0.322337890142275510343994470762492, 
+0.322337890142275510343994470762492, 
+) 
+Corresponding weight: 
+10 ^ -3 x 9.22619692394245368252554630895433,
+
+Generator: [ Fully symmetric ] 
+( 0.0636610018750175252992355276057269, 
+0.0636610018750175252992355276057269, 
+0.269672331458315808034097805727606, 
+) 
+Corresponding weight: 
+10 ^ -3 x 8.03571428571428571428571428571428,
+
+
+
+Region: Simplex 
+Dimension: 3 
+Degree: 7 
+Points: 31 
+Structure: Fully symmetric 
+Rule struct: 0 1 0 0 0 0 1 3 0 1 0 
+Generator: [ Fully symmetric ] 
+( 0.5, 0.5, 0., ) 
+Corresponding weight: 
+10 ^ -4 x 9.70017636684303350970017636684303,
+Generator: [ Fully symmetric ] 
+( 0.25, 0.25, 0.25, ) 
+Corresponding weight: 
+0.0182642234661088202912015685649462,
+
+Generator: [ Fully symmetric ] 
+( 0.0782131923303180643739942508375545, 
+0.0782131923303180643739942508375545, 
+0.0782131923303180643739942508375545, 
+) 
+Corresponding weight: 
+0.0105999415244136869164138748545257,
+
+Generator: [ Fully symmetric ] 
+( 0.121843216663905174652156372684818, 
+0.121843216663905174652156372684818, 
+0.121843216663905174652156372684818, 
+) 
+Corresponding weight: 
+-0.0625177401143318516914703474927900,
+
+Generator: [ Fully symmetric ] 
+( 0.332539164446420624152923823157707, 
+0.332539164446420624152923823157707, 
+0.332539164446420624152923823157707, 
+) 
+Corresponding weight: 
+10 ^ -3 x 4.89142526307349938479576303671027,
+
+Generator: [ Fully symmetric ] 
+( 0.1, 0.1, 0.2, ) 
+Corresponding weight: 
+0.0275573192239858906525573192239858,
+
+
+
+Region: Simplex 
+Dimension: 3 
+Degree: 8 
+Points: 43 
+Structure: Fully symmetric 
+Rule struct: 0 0 0 0 0 0 1 3 1 2 0 
+Generator: [ Fully symmetric ] 
+( 0.25, 0.25, 0.25, ) 
+Corresponding weight: 
+-0.0205001886586399158405865177642941,
+Generator: [ Fully symmetric ] 
+( 0.206829931610673204083980900024961, 
+0.206829931610673204083980900024961, 
+0.206829931610673204083980900024961, 
+) 
+Corresponding weight: 
+0.0142503058228669012484397415358704,
+
+Generator: [ Fully symmetric ] 
+( 0.0821035883105467230906058078714215, 
+0.0821035883105467230906058078714215, 
+0.0821035883105467230906058078714215, 
+) 
+Corresponding weight: 
+10 ^ -3 x 1.96703331313390098756280342445466,
+
+Generator: [ Fully symmetric ] 
+( 10 ^ -3 x 5.78195050519799725317663886414270, 
+10 ^ -3 x 5.78195050519799725317663886414270, 
+10 ^ -3 x 5.78195050519799725317663886414270, 
+) 
+Corresponding weight: 
+10 ^ -4 x 1.69834109092887379837744566704016,
+
+Generator: [ Fully symmetric ] 
+( 0.0505327400188942244256245285579071, 
+0.0505327400188942244256245285579071, 
+0.449467259981105775574375471442092, 
+) 
+Corresponding weight: 
+10 ^ -3 x 4.57968382446728180074351446297276,
+
+Generator: [ Fully symmetric ] 
+( 0.229066536116811139600408854554753, 
+0.229066536116811139600408854554753, 
+0.0356395827885340437169173969506114, 
+) 
+Corresponding weight: 
+10 ^ -3 x 5.70448580868191850680255862783040,
+
+Generator: [ Fully symmetric ] 
+( 0.0366077495531974236787738546327104, 
+0.0366077495531974236787738546327104, 
+0.190486041934633455699433285315099, 
+) 
+Corresponding weight: 
+10 ^ -3 x 2.14051914116209259648335300092023,
+
+Region: Simplex 
+Dimension: 3 
+Degree: 9 
+Points: 53 
+Structure: Fully symmetric 
+Rule struct: 0 0 0 0 0 0 1 4 0 3 0 
+Generator: [ Fully symmetric ] 
+( 0.25, 0.25, 0.25, ) 
+Corresponding weight: 
+-0.137799038326108641245781827743502,
+Generator: [ Fully symmetric ] 
+( 0.0483510385497367408791638973335652, 
+0.0483510385497367408791638973335652, 
+0.0483510385497367408791638973335652, 
+) 
+Corresponding weight: 
+10 ^ -3 x 1.86533656908528954751732956352791,
+
+Generator: [ Fully symmetric ] 
+( 0.324579280117882365858796772348839, 
+0.324579280117882365858796772348839, 
+0.324579280117882365858796772348839, 
+) 
+Corresponding weight: 
+10 ^ -3 x 4.30942396949340069685481460143672,
+
+Generator: [ Fully symmetric ] 
+( 0.114616540223995219683790300317451, 
+0.114616540223995219683790300317451, 
+0.114616540223995219683790300317451, 
+) 
+Corresponding weight: 
+-0.0901847664812015251273931145424214,
+
+Generator: [ Fully symmetric ] 
+( 0.225489951911513918847703826550363, 
+0.225489951911513918847703826550363, 
+0.225489951911513918847703826550363, 
+) 
+Corresponding weight: 
+0.0446725762025114446937850368088403,
+
+Generator: [ Fully symmetric ] 
+( 0.131627809246869809838976179197822, 
+0.131627809246869809838976179197822, 
+0.0836647016171849679665385541714202, 
+) 
+Corresponding weight: 
+0.0347004058845507618227002576570271,
+
+Generator: [ Fully symmetric ] 
+( 0.433951461411406772411426685800524, 
+0.433951461411406772411426685800524, 
+0.107769859549428611825218473500043, 
+) 
+Corresponding weight: 
+10 ^ -3 x 3.35258390266064697010720483063291,
+
+Generator: [ Fully symmetric ] 
+( 10 ^ -3 x -1.37627731813820071002030321419028, 
+10 ^ -3 x -1.37627731813820071002030321419028, 
+0.276553472636807342120192082186261, 
+) 
+Corresponding weight: 
+10 ^ -4 x 4.31628875556996929641889902726182,
+
+
+ */
+template<class Rd>
+void GQuadratureFormular<Rd>::Verification()
+{
+  QF_exact<GQuadratureFormular<Rd>,Rd::d+1>(exact,this);
+  const int d=Rd::d;
+  const double tol=1.e-12;
+  R err=0;
+  R a[d+1],h;
+  
+  for (int k=0;k<=exact;  k++)
+    {
+
+      //  formule magic: int_K  \lamda^k =   d! k! / ( d+k)! 
+      
+      R sa[d+1];
+      for(int l=0;l<=d;++l)	      
+	sa[l]=0.;
+     
+      for (int j=0;j<n;j++)
+	{
+	  h = p[j];
+	  Rd P = p[j];
+	  
+	  for(int l=0;l<d;++l)	      
+	    a[l]=p[j][l];
+	  a[d] = 1.-p[j].sum();
+	  
+	  for(int l=0;l<=d;++l)	      	  
+	    sa[l]+=h*pow(a[l],k);  
+	}
+      
+      R se(1),see(1);
+      for (int i=1;i<=k;i++) 
+	se *= (R) i / (R) (i+d);
+      see=se;
+      
+      for(int l=0;l<=d;++l)
+	err = Max(err,Abs(se-sa[l]));
+      
+      if (err>tol)
+	{
+	  cerr << " d= " << d << "T Ordre= " << k << " d!k!/(d+k)!= " << se << " " ;
+	  for(int l=0;l<=d;++l)
+	    cerr << sa[l] << " ";
+	  cerr << " err= " << err << endl;
+	}
+    }
+  
+  if(err>tol)
+    {
+      cerr << "Erreur dans la formule d'integration d=" <<d  << " exact = " << exact 
+	   << " Nb Point = " << n << endl;
+      assert(0);
+    }
+    
+}
+/*
+  from:
+http://www.cs.kuleuven.be/~nines/research/ecf/mtables.html
+ */
+typedef GQuadraturePoint<R3>  PQP3;
+typedef GQuadratureFormular<R3>  PQF3;
+// 2 4 (formule 2)
+// A.H. Stroud, Approximate calculation of multiple integrals, Prentice-Hall, Englewood Cliffs, N.J., 1971.
+// JavaScript:formule('t3-2-4b')
+    
+    PQP3  QF_TET_1[]=
+    { 
+    PQP3(R3(0.25,0.25,0.25), 1)
+    };
+    PQF3 const QuadratureFormular_Tet_1(1,1,QF_TET_1);
+ 
+    
+    PQP3  QF_TET_1lump[]=
+    { 
+    PQP3(R3(0,0,0),0.25),
+    PQP3(R3(1.,0,0),0.25),
+    PQP3(R3(0,1.,0),0.25),
+    PQP3(R3(0,0,1.),0.25),
+    };
+    PQF3 const QuadratureFormular_Tet_1lump(1,4,QF_TET_1lump);
+    
+    
+PQP3  QF_TET_2[]=
+  { 
+     PQP3(R3(0.58541019662496845446137605030968, 0.138196601125010515179541316563436, 0.138196601125010515179541316563436), 0.25),
+     PQP3(R3(0.138196601125010515179541316563436,  0.58541019662496845446137605030968, 0.138196601125010515179541316563436), 0.25),
+     PQP3(R3(0.138196601125010515179541316563436, 0.138196601125010515179541316563436,  0.58541019662496845446137605030968),0.25),
+     PQP3(R3(0.138196601125010515179541316563436, 0.138196601125010515179541316563436, 0.138196601125010515179541316563436),0.25)
+  };
+  PQF3 const QuadratureFormular_Tet_2(2,4,QF_TET_2);
+// 5  14  (formule 1)
+/*
+GM78
+A. Grundmann and H.M. M�ller, Invariant integration formulas for the n-simplex by combinatorial methods, SIAM J. Numer. Anal. 15 (1978), 282--290.
+ */
+PQP3  QF_TET_5[]=
+   { 
+     PQP3(R3(0.7217942490673263207930282587889082 , 0.0927352503108912264023239137370306 , 0.0927352503108912264023239137370306) , 0.0122488405193936582572850342477212*6.),
+     PQP3(R3(0.0927352503108912264023239137370306 , 0.7217942490673263207930282587889082 , 0.0927352503108912264023239137370306) , 0.0122488405193936582572850342477212*6.),
+     PQP3(R3(0.0927352503108912264023239137370306 , 0.0927352503108912264023239137370306 , 0.7217942490673263207930282587889082) , 0.0122488405193936582572850342477212*6.),
+     PQP3(R3(0.0927352503108912264023239137370306 , 0.0927352503108912264023239137370306 , 0.0927352503108912264023239137370306) , 0.0122488405193936582572850342477212*6),
+     PQP3(R3(0.067342242210098170607962798709629 , 0.310885919263300609797345733763457 , 0.310885919263300609797345733763457) , 0.0187813209530026417998642753888810*6.),
+     PQP3(R3(0.310885919263300609797345733763457 , 0.067342242210098170607962798709629 , 0.310885919263300609797345733763457) , 0.0187813209530026417998642753888810*6.),
+     PQP3(R3(0.310885919263300609797345733763457 , 0.310885919263300609797345733763457 , 0.067342242210098170607962798709629) , 0.0187813209530026417998642753888810*6.),
+     PQP3(R3(0.310885919263300609797345733763457 , 0.310885919263300609797345733763457 , 0.310885919263300609797345733763457) , 0.0187813209530026417998642753888810*6.),
+     PQP3(R3(0.454496295874350350508119473720660,  0.454496295874350350508119473720660, 0.045503704125649649491880526279339),  7.09100346284691107301157135337624E-3*6.),
+     PQP3(R3(00.454496295874350350508119473720660,  0.045503704125649649491880526279339, 0.454496295874350350508119473720660), 7.09100346284691107301157135337624E-3*6.),
+     PQP3(R3(00.045503704125649649491880526279339,  0.454496295874350350508119473720660, 0.454496295874350350508119473720660), 7.09100346284691107301157135337624E-3*6.),
+     PQP3(R3(00.045503704125649649491880526279339,  0.045503704125649649491880526279339, 0.454496295874350350508119473720660), 7.09100346284691107301157135337624E-3*6.),
+     PQP3(R3(00.045503704125649649491880526279339,  0.454496295874350350508119473720660, 0.045503704125649649491880526279339), 7.09100346284691107301157135337624E-3*6.),
+     PQP3(R3(00.454496295874350350508119473720660,  0.045503704125649649491880526279339, 0.045503704125649649491880526279339), 7.09100346284691107301157135337624E-3*6.)
+   };
+
+  PQF3 const QuadratureFormular_Tet_5(5,14,QF_TET_5);
+
+  template<> const GQuadratureFormular<R1> * GQuadratureFormular<R1>::Default= & QF_GaussLegendre3;
+  template<> const GQuadratureFormular<R2> * GQuadratureFormular<R2>::Default= & QuadratureFormular_T_5;
+  template<> const GQuadratureFormular<R3> * GQuadratureFormular<R3>::Default= & QuadratureFormular_Tet_5;
+
+    // Instanciation explicite of icpc   compiler  Version 11.1   (FH  oct 2010) 
+    template void  GQuadratureFormular<R1>::Verification();
+    template void  GQuadratureFormular<R2>::Verification();
+    template void  GQuadratureFormular<R3>::Verification();
+    
+   
+    
+} // end namespace Fem2D
diff --git a/src/femlib/QuadratureFormular.hpp b/src/femlib/QuadratureFormular.hpp
new file mode 100644
index 0000000..6db8607
--- /dev/null
+++ b/src/femlib/QuadratureFormular.hpp
@@ -0,0 +1,213 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:     Jan 2008
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : Generic  Quadrature Formular 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN   FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#ifndef _QuadratureFormular_h
+#define _QuadratureFormular_h
+
+#include <iostream>
+
+namespace Fem2D {
+  using namespace std;
+#include "R3.hpp"
+
+
+
+  //class QuadratureFormular;
+struct  QuadratureWeight {
+  R a;
+  QuadratureWeight(R aa): a(aa){}
+};
+
+template<class Rd>
+class GQuadraturePoint: public QuadratureWeight,public Rd {
+ public:
+  typedef GQuadraturePoint QP ;
+  GQuadraturePoint(): QuadratureWeight(0),Rd() {}
+  GQuadraturePoint(R aa, const Rd &xx): QuadratureWeight(aa),Rd(xx) {}
+  GQuadraturePoint(const Rd & xx,R aa): QuadratureWeight(aa),Rd(xx) {}
+  operator R() const {return a;}
+  GQuadraturePoint(R aa,R xx):QuadratureWeight(aa),Rd(xx) {}
+  GQuadraturePoint(R aa,R x,R y):QuadratureWeight(aa),Rd(x,y) {}
+  GQuadraturePoint(R aa,R x,R y,R z):QuadratureWeight(aa),Rd(x,y,z) {}
+  template<class RD >
+  GQuadraturePoint<RD>
+    Bary(RD * K, double mes) { return GQuadraturePoint<RD>(this->Rd::Bary(K),a*mes);}
+};
+
+template<class Rdd>
+class GQuadratureFormular {
+
+public:
+  typedef Rdd Rd;
+  typedef  GQuadraturePoint<Rd> QuadraturePoint;
+  typedef  GQuadraturePoint<Rd> QP;
+  int exact;            // exact
+  int n;                // nombre de point d'integration
+  const int size;             //  size of the array
+private:
+  QP *p;  // les point d'integration 
+  const bool clean;
+public:
+// -- les fonctions ------------------
+  void Verification(); // for verification 
+  GQuadratureFormular (int e,int NbOfNodes,QuadraturePoint *pp,bool c=false)
+ :exact(e), n(NbOfNodes),size(n),p(pp),clean(c)  {Verification();}
+  GQuadratureFormular (int e,int NbOfNodes,const QuadraturePoint *pp,bool c=false)
+ :exact(e),n(NbOfNodes),p(pp),clean(c)   {Verification();}
+  
+  GQuadratureFormular(int ex,QP p0,QP p1,QP p2,QP p3,QP p4) 
+    : exact(ex),n(5),size(n),p(new QP[5]),clean(true) { p[0]=p0;p[1]=p1;p[2]=p2;p[3]=p3;p[4]=p4;Verification();}
+  GQuadratureFormular(int ex,QP p0,QP p1,QP p2,QP p3) 
+    : exact(ex),n(4),size(n),p(new QP[4]) ,clean(true){ p[0]=p0,p[1]=p1,p[2]=p2;p[3]=p3;Verification();}
+  GQuadratureFormular(int ex,QP p0,QP p1,QP p2) 
+    : exact(ex),n(3),size(n),p(new QP[3]),clean(true) { p[0]=p0,p[1]=p1,p[2]=p2;Verification();}
+  GQuadratureFormular(int ex,QP p0,QP p1) 
+    : exact(ex),n(2),size(n),p(new QP[2]),clean(true) { p[0]=p0,p[1]=p1;Verification();}
+  GQuadratureFormular(int ex,QP p0) 
+    : exact(ex),n(1),size(n),p(new QP[1]),clean(true) { p[0]=p0;Verification();}
+  // bluid a empty GQuadratureFormular
+  GQuadratureFormular(int ssize):exact(0),n(0),size(ssize),p(new QP[size]),clean(true) {}
+
+  const QP & operator [](int i) const  {return p[i];} 
+  const QP  & operator ()(int i) const {return p[i];}
+  ~GQuadratureFormular() {if(clean) delete [] p;}
+    
+    GQuadratureFormular(const GQuadratureFormular & QF, int mul=1)
+    :exact(QF.exact),n(QF.n),size(QF.size*mul),p(new QP[size]),clean(true){ operator=(QF);}
+  void operator=(const GQuadratureFormular &QF)
+    {
+      assert(size>=QF.n);
+      n = QF.n;
+      for(int i=0;i<n;++i)
+           p[i]=QF.p[i];
+    }
+  void operator*=( double c)
+    {
+      for(int i=0;i<n;++i)
+          p[i].a *=c;
+    }
+  //  Add new GQuadratureFormular on element K to the current Quadarture formular ..
+    // FH   april 2014 ..
+    // to compute int under levelset ..
+    void reset() { n =0;exact=0;}
+  template<class RD >
+  void AddQFK(const GQuadratureFormular<RD> &QF ,Rd *K,double mes,int n0=0)
+    {
+        
+        assert( size >=  n0  + QF.n );
+        n0 += n;
+        n = n0 + QF.n;
+        for(int i=0;i<QF.n;++i)
+          p[i+n0]=QF.p[i].Bary(K,mes);
+        
+    }
+private:
+ /* GQuadratureFormular(const GQuadratureFormular &)
+    :exact(0),n(0),p(0){assert(0);}
+  void operator=(const GQuadratureFormular &)
+  {assert(0);}
+  GQuadratureFormular()
+    :exact(0),n(0),p(0){assert(0);}*/
+  static const GQuadratureFormular * Default;
+};
+
+
+
+template<class Rd>
+ostream& operator <<(ostream& , const GQuadratureFormular<Rd> & ) ;
+template<class Rd>
+ostream& operator <<(ostream& , GQuadraturePoint<Rd> & );
+
+typedef GQuadratureFormular<R1> QuadratureFormular1d;
+
+
+  extern const QuadratureFormular1d QF_GaussLegendre1; 
+  extern const QuadratureFormular1d QF_GaussLegendre2; 
+  extern const QuadratureFormular1d QF_GaussLegendre3; 
+  extern const QuadratureFormular1d QF_GaussLegendre4; 
+  extern const QuadratureFormular1d QF_GaussLegendre5; 
+  extern const QuadratureFormular1d QF_LumpP1_1D; 
+  
+  
+  extern const GQuadratureFormular<R2> QuadratureFormular_T_1;
+  extern const GQuadratureFormular<R2> QuadratureFormular_T_1lump;
+  extern const GQuadratureFormular<R2> QuadratureFormular_T_2;
+  extern const GQuadratureFormular<R2> QuadratureFormular_T_5;
+  extern const GQuadratureFormular<R2> QuadratureFormular_T_2_4P1;
+  extern const GQuadratureFormular<R2> QuadratureFormular_T_7;
+  extern const GQuadratureFormular<R2>  QuadratureFormular_T_9;
+
+  extern const GQuadratureFormular<R3> QuadratureFormular_Tet_1;
+  extern const GQuadratureFormular<R3> QuadratureFormular_Tet_1lump;
+  extern const GQuadratureFormular<R3> QuadratureFormular_Tet_2;
+  extern const GQuadratureFormular<R3> QuadratureFormular_Tet_5;
+  
+
+
+template<class Rd>
+GQuadratureFormular<Rd> * QF_Simplex(int exact);
+//  { return  QF_exact<GQuadratureFormular<Rd>,Rd::d+1>(exact);}
+
+template<class Rd>
+void  setQF( GQuadratureFormular<Rd> &FI,
+             const GQuadratureFormular<Rd> & FI1 ,
+             const GQuadratureFormular<Rd> & FI0 ,
+             Rd Q[Rd::d][Rd::d+1],
+             double *cmes,
+             int n)
+    {
+        FI.reset();
+        for(int i=0; i< n; ++i)
+            if(cmes[i]==1)
+                FI=FI1;
+            else if(cmes[i] > 1e-4)
+              FI.AddQFK(FI1,Q[i],cmes[i]);
+            else if ( cmes[i]> 1e-8 )
+              FI.AddQFK(FI0,Q[i],cmes[i]);
+
+    }
+
+
+    
+}
+
+namespace Fem2D {
+  typedef  GQuadratureFormular<R2> QuadratureFormular;
+  typedef  GQuadraturePoint<R2>    QuadraturePoint;
+  typedef  GQuadratureFormular<R1> QuadratureFormular1d;
+  typedef  GQuadraturePoint<R1>   QuadratureFormular1dPoint;
+  GQuadraturePoint<R1>  *  GaussLegendre(int nn);
+
+}
+#endif
diff --git a/src/femlib/R1.hpp b/src/femlib/R1.hpp
new file mode 100644
index 0000000..bcf1659
--- /dev/null
+++ b/src/femlib/R1.hpp
@@ -0,0 +1,117 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model of $\mathbb{R}^1$    
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#ifndef R1_HPP
+#define  R1_HPP
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+
+typedef double R;
+
+//  R0 R1, R2 , R3 to be uniforme. 
+// The class R1
+class R0 {
+public:  
+  typedef double R;
+  static const int d=0;
+  R0(){}
+};
+class R2;
+class R3;
+
+class R1 {
+public:  
+  typedef double R;
+  static const int d=1;
+
+  R x;  // declaration de membre 
+  // les 3 constructeurs ---
+  R1 () :x(0.){} // rappel : x(0)  sont initialiser via le constructeur de double 
+  R1 (R a):x(a)  {}
+  R1 (const R1 & a,const R1 & b):x(b.x-a.x)  {}
+  static  R1 diag(R a){ return R1(a);}
+
+  // rappel les operator definis dans une class on un parametre
+  // cache qui est la classe elle meme (*this)
+
+  // les operateurs affectation
+  //  operateur affection (*this) = P est inutil par defaut il fait le travail correctement
+  // les autre operoteur affectations
+  R1 &  operator+=(const R1 & P)  {x += P.x;return *this;}
+  R1 &  operator-=(const R1 & P) {x -= P.x;return *this;}
+  R1 &  operator*=(R a) {x *= a;return *this;}
+  R1 &  operator/=(R a) {x /= a;return *this;}
+  // operateur binaire + - * , ^ /
+  R1   operator+(const R1 & P)const   {return R1(x+P.x);}
+  R1   operator-(const R1 & P)const   {return R1(x-P.x);}
+  R    operator,(const R1 & P)const  {return  x*P.x;} // produit scalaire
+  R1   operator*(R c)const {return R1(x*c);}
+  R1   operator/(R c)const {return R1(x/c);}
+  // operateur unaire 
+  R1   operator-()const  {return R1(-x);} 
+  R1   operator+()const  {return *this;}
+  // un methode
+  R sum() const { return x;}
+  R * toBary(R * b) const { b[0]=1-x;b[1]=x;return b;}
+  // les operators  tableaux
+  // version qui peut modifie la class  via l'adresse de x
+  R  &  operator[](int i){ return (&x)[i];}
+  const R  &  operator[](int i) const { return (&x)[i];}
+
+
+  R norme() const { return std::sqrt(x*x);}
+  R norme2() const { return (x*x);}
+  R1 Bary(R1 P[d+1]) const { return (1-x)*P[0]+x*P[1];}  // add FH 
+  R1 Bary(const R1 *const *const P ) const { return (1-x)*(*P[0])+x*(*P[1]);}  // add FH 
+  R2 Bary(R2 P[d+1]) const;// { return (1-x)*P[0]+x*P[1];}  // add FH
+  R2 Bary(const R2 *const *const P ) const ;//{ return (1-x)*(*P[0])+x*(*P[1]);}  // add FH
+    R3 Bary(R3 P[d+1]) const ;//{ return (1-x)*P[0]+x*P[1];}  // add FH
+    R3 Bary(const R3 *const *const P ) const ;//{ return (1-x)*(*P[0])+x*(*P[1]);}  // add FH
+friend  R1 operator*(R c,const R1 & P) {return P*c;}
+
+friend  std::ostream& operator <<(std::ostream& f, const R1 & P )
+       { f << P.x   ; return f; }
+friend  std::istream& operator >>(std::istream& f,  R1 & P)
+       { f >>  P.x  ; return f; }
+  static const R1 KHat[d+1];
+};
+
+inline R1 Minc(const R1 & A,const R1 &B){ return R1(min(A.x,B.x));}
+inline R1 Maxc(const R1 & A,const R1 &B){ return R1(max(A.x,B.x));}
+inline double Norme_infty(const R1 & A){return std::fabs(A.x);}
+inline double Norme2_2(const R1 & A){ return A.x*A.x;}
+inline double Norme2(const R1 & A){ return std::fabs(A.x);}
+
+
+#endif
diff --git a/src/femlib/R2.hpp b/src/femlib/R2.hpp
new file mode 100644
index 0000000..dc24bda
--- /dev/null
+++ b/src/femlib/R2.hpp
@@ -0,0 +1,127 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model of $\mathbb{R}^2$    
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+#ifndef R2_HPP
+#define  R2_HPP
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+// Definition de la class R2 
+//  sans compilation separe toute les fonctions 
+// sous defini dans ce R2.hpp avec des inline 
+//  
+// definition R (les nombres reals)
+// remarque la fonction abort est defini dans 
+// #include <cstdlib> 
+
+// The class R2
+class R3;
+class R2 {
+public:  
+  typedef double R;
+  static const int d=2;
+
+  R x,y;  // declaration de membre 
+  // les 3 constructeurs ---
+  R2 () :x(0.),y(0.) {} // rappel : x(0), y(0)  sont initialiser via le constructeur de double 
+  R2 (R a,R b):x(a),y(b)  {}
+  R2 (const R * a):x(a[0]),y(a[1])  {}
+  R2 ( R * a):x(a[0]),y(a[1])  {}
+
+  R2 (const R2 & a,const R2 & b):x(b.x-a.x),y(b.y-a.y)  {}
+  static  R2 diag(R a){ return R2(a,a);}
+  // le constucteur par defaut est inutile
+  //R2 (const R2 & a) :x(a.x),y(a.y) {} 
+
+  // rappel les operator definis dans une class on un parametre
+  // cache qui est la classe elle meme (*this)
+
+  // les operateurs affectation
+  //  operateur affection (*this) = P est inutil par defaut il fait le travail correctement
+  //R2 &  operator=(const R2 & P)  {x = P.x;y = P.y;return *this;}
+  // les autre operoteur affectations
+  R2 &  operator+=(const R2 & P)  {x += P.x;y += P.y;return *this;}
+  R2 &  operator-=(const R2 & P) {x -= P.x;y -= P.y;return *this;}
+  R2 &  operator*=(R a) {x *= a;y *= a;return *this;}
+  R2 &  operator/=(R a) {x /= a;y /= a;return *this;}
+
+  // operateur binaire + - * , ^ /
+  R2   operator+(const R2 & P)const   {return R2(x+P.x,y+P.y);}
+  R2   operator-(const R2 & P)const   {return R2(x-P.x,y-P.y);}
+  R    operator,(const R2 & P)const  {return  x*P.x+y*P.y;} // produit scalaire
+  R    operator^(const R2 & P)const {return  x*P.y-y*P.x;} // produit mixte
+  R2   operator*(R c)const {return R2(x*c,y*c);}
+  R2   operator/(R c)const {return R2(x/c,y/c);}
+  // operateur unaire 
+  R2   operator-()const  {return R2(-x,-y);} 
+  R2   operator+()const  {return *this;}
+  // un methode
+  R2   perp() const {return R2(-y,x);} // la perpendiculaire
+  R sum() const { return x+y;}
+  R * toBary(R * b) const  { b[0]=1.-x-y;b[1]=x;b[2]=y;return b;}
+
+  // les operators  tableau
+  // version qui peut modifie la class  via l'adresse de x ou y 
+  R  &  operator[](int i){ return (&x)[i];}
+  const R  &  operator[](int i) const { return (&x)[i];}
+
+  R  X() const {return x;}
+  R  Y() const {return y;}
+  R  Z() const {return 0.;}
+
+  R norme() const { return std::sqrt(x*x+y*y);}
+  R norme2() const { return (x*x+y*y);}
+  R2 Bary(R2 P[d+1]) const { return (1-x-y)*P[0]+x*P[1]+y*P[2];}  // add FH 
+  R2 Bary(const R2 *const *const P ) const { return (1-x-y)*(*P[0])+x*(*P[1])+y*(*P[2]);}  // add FH
+  R3 Bary(R3 P[d+1]) const ; //{ return (1-x-y)*P[0]+x*P[1]+y*P[2];}  // add FH
+  R3 Bary(const R3 *const *const P ) const; // { return (1-x-y)*(*P[0])+x*(*P[1])+y*(*P[2]);}  // add FH
+   
+    
+friend  R2 operator*(R c,const R2 & P) {return P*c;} 
+friend  R2 perp(const R2 & P) { return R2(-P.y,P.x) ; }
+//inline R2 Perp(const R2 & P) { return P.perp(); }  // autre ecriture  de la fonction perp
+friend R  det(const R2 & A,const R2 & B,const R2 &C) { return R2(A,B)^R2(A,C);}
+
+friend  std::ostream& operator <<(std::ostream& f, const R2 & P )
+       { f << P.x << ' ' << P.y   ; return f; }
+friend  std::istream& operator >>(std::istream& f,  R2 & P)
+       { f >>  P.x >>  P.y  ; return f; }
+  static const R2 KHat[d+1];
+};
+
+inline R2 Minc(const R2 & A,const R2 &B){ return R2(min(A.x,B.x),min(A.y,B.y));}
+inline R2 Maxc(const R2 & A,const R2 &B){ return R2(max(A.x,B.x),max(A.y,B.y));}
+inline double Norme_infty(const R2 & A){return max(std::fabs(A.x),std::fabs(A.y));}
+inline double Norme2_2(const R2 & A){ return (A,A);}
+inline double  Norme2(const R2 & A){ return sqrt((A,A));}
+
+#endif
+
diff --git a/src/femlib/R3.hpp b/src/femlib/R3.hpp
new file mode 100644
index 0000000..aa29128
--- /dev/null
+++ b/src/femlib/R3.hpp
@@ -0,0 +1,136 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model of $\mathbb{R}^3$    
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#ifndef R3_HPP
+#define  R3_HPP
+#include "R1.hpp" 
+#include "R2.hpp" 
+
+class R3  {
+
+public:  
+  typedef double R;
+
+  static const int d=3;
+  
+  R x,y,z;
+ 
+  R3 () :x(0),y(0),z(0) {};
+  R3 (R a,R b,R c):x(a),y(b),z(c)  {}
+  R3 (const R * a):x(a[0]),y(a[1]) ,z(a[2]) {}
+
+  R3 (R2 P2):x(P2.x),y(P2.y),z(0)  {}
+  R3 (R2 P2,R zz):x(P2.x),y(P2.y),z(zz)  {}
+  R3 (const R3 & A,const R3 & B) :x(B.x-A.x),y(B.y-A.y),z(B.z-A.z)  {}
+  static  R3 diag(R a){ return R3(a,a,a);}
+  R3 & operator=(const R2 &P2) {x=P2.x;y=P2.y;z=0;return *this;}
+  R3   operator+(const R3 &P)const   {return R3(x+P.x,y+P.y,z+P.z);}
+  R3 & operator+=(const R3 &P)  {x += P.x;y += P.y;z += P.z;return *this;}
+  R3   operator-(const R3 &P)const   {return R3(x-P.x,y-P.y,z-P.z);}
+  R3 & operator-=(const R3 &P) {x -= P.x;y -= P.y;z -= P.z;return *this;}
+  R3 & operator*=(R c) {x *= c;y *= c;z *= c;return *this;}
+  R3 & operator/=(R c) {x /= c;y /= c;z /= c;return *this;}
+  R3   operator-()const  {return R3(-x,-y,-z);}
+  R3   operator+()const  {return *this;}
+  R    operator,(const R3 &P)const  {return  x*P.x+y*P.y+z*P.z;} // produit scalaire
+  R3  operator^(const R3 &P)const {return R3(y*P.z-z*P.y ,P.x*z-x*P.z, x*P.y-y*P.x);} // produit vectoreil
+  R3   operator*(R c)const {return R3(x*c,y*c,z*c);}
+  R3   operator/(R c)const {return R3(x/c,y/c,z/c);}
+  R  &  operator[](int i){ return (&x)[i];}
+  const R  &  operator[](int i) const { return (&x)[i];}
+  friend R3 operator*(R c,const R3 &P) {return P*c;}
+  friend R3 operator/(R c,const R3 &P) {return P/c;}
+  R norme() const { return std::sqrt(x*x+y*y+z*z);}
+  R norme2() const { return (x*x+y*y+z*z);}
+  R sum() const { return x+y+z;}
+  R * toBary(R * b) const  { b[0]=1.-x-y-z;b[1]=x;b[2]=y;b[3]=z;return b;}    
+  R  X() const {return x;}
+  R  Y() const {return y;}
+  R  Z() const {return z;}
+
+  R3 Bary(const R3 P[d+1]) const { return (1-x-y-z)*P[0]+x*P[1]+y*P[2]+z*P[3];}  // add FH 
+  R3 Bary(const R3 **P ) const { return (1-x-y-z)*(*P[0])+x*(*P[1])+y*(*P[2])+z*(*P[3]);}  // add FH 
+  friend ostream& operator <<(ostream& f, const R3 & P )
+  { f << P.x << ' ' << P.y << ' ' << P.z   ; return f; }
+  friend istream& operator >>(istream& f,  R3 & P)
+  { f >>  P.x >>  P.y >>  P.z  ; return f; }
+
+  friend R det( R3 A, R3 B,  R3 C) 
+  {
+    R  s=1.;
+    if(abs(A.x)<abs(B.x)) Exchange(A,B),s = -s;
+    if(abs(A.x)<abs(C.x)) Exchange(A,C),s = -s;
+    if(abs(A.x)>1e-50)
+      {
+	s *= A.x;
+	A.y /= A.x; A.z /= A.x;
+	B.y  -=  A.y*B.x  ;   B.z  -=  A.z*B.x ;
+	C.y  -=  A.y*C.x  ;   C.z  -=  A.z*C.x ;
+	return s* ( B.y*C.z - B.z*C.y) ;
+      }
+    else return 0.   ;
+  }
+  
+  friend R  det(const R3 &A,const R3 &B, const R3 &C, const R3 &D) { return det(R3(A,B),R3(A,C),R3(A,D));}
+  static const R3 KHat[d+1];
+  
+  R2 p2() const { return R2(x,y);}
+};
+
+inline R3 Minc(const R3 & A,const R3 &B){ return R3(min(A.x,B.x),min(A.y,B.y),min(A.z,B.z));}
+inline R3 Maxc(const R3 & A,const R3 &B){ return R3(max(A.x,B.x),max(A.y,B.y),max(A.z,B.z));}
+inline R Norme_infty(const R3 & A){return Max(std::fabs(A.x),std::fabs(A.y),std::fabs(A.z));}
+inline R Norme2_2(const R3 & A){ return (A,A);}
+inline R Norme2(const R3 & A){ return sqrt((A,A));}
+
+inline R3 R2::Bary(R3 P[d+1]) const { return (1-x-y)*P[0]+x*P[1]+y*P[2];}  // add FH
+inline R3 R2::Bary(const R3 *const *const P ) const { return (1-x-y)*(*P[0])+x*(*P[1])+y*(*P[2]);}  // add FH
+inline R3 R1::Bary(R3 P[d+1]) const { return (1-x)*P[0]+x*P[1];}  // add FH
+inline R3 R1::Bary(const R3 *const *const P ) const { return (1-x)*(*P[0])+x*(*P[1]);}  // add FH
+inline R2 R1::Bary(R2 P[d+1]) const { return (1-x)*P[0]+x*P[1];}  // add FH
+inline R2 R1::Bary(const R2 *const *const P ) const { return (1-x)*(*P[0])+x*(*P[1]);}  // add FH
+
+
+struct lessRd
+{
+  bool operator()(const R1 &s1, const R1 & s2) const
+  {    return s1.x < s2.x ;  }
+  bool operator()(const R2 &s1, const R2 & s2) const
+  {    return s1.x == s2.x ? (s1.y < s2.y)  :s1.x < s2.x;  }
+  bool operator()(const R3 &s1, const R3 & s2) const
+  {    return s1.x == s2.x ? (s1.y == s2.y ? (s1.z < s2.z)  :s1.y < s2.y )  :s1.x < s2.x;  }
+};
+
+
+
+#endif
+
diff --git a/src/femlib/RNM.hpp b/src/femlib/RNM.hpp
new file mode 100644
index 0000000..9bc707a
--- /dev/null
+++ b/src/femlib/RNM.hpp
@@ -0,0 +1,1601 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:    29 fev 2000  
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : array modelisation 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+
+ */
+#ifndef KNM_H_
+#define KNM_H_
+// version sept 2008 FH.
+// ----------------------
+// une tentative qui ne marche pas 
+// de tableau constant 
+#include <complex>
+#include <iostream>
+#include <iomanip>
+#include <cmath>
+#include <cassert>
+
+
+using namespace std;
+#define const_R   R
+#include <cstdlib>
+inline void Check_Kn(const char * str,const char * file,int line)
+{
+ cerr << "CHECK_KN: " << str << " in file: " << file << ", line " << line <<endl;
+#ifdef VersionFreeFempp
+    ffassert(0); 
+#else
+    assert(0);
+#endif
+    
+  abort();
+}
+
+#define K_bigassert(i)  if (!(i)) Check_Kn(#i,__FILE__,__LINE__);
+#define RNM_FATAL_ERROR(i) Check_Kn(i,__FILE__,__LINE__);
+#ifdef CHECK_KN
+
+#define K_throwassert(i)  if (!(i)) Check_Kn(#i,__FILE__,__LINE__);
+
+#else
+#define K_throwassert(i) 
+#endif
+// version du 29 fev 2000  
+//  correction   for (... lj++,ui++  qui apelle le produit scalaire
+//  petite correction  throwassert 
+// ajoute de operateur /= et *= sur des vecteurs
+//   suppression de constructeur qui pose de probleme   
+//   correction oper +=  ...  dans RNM_op.h ligne 56  change = en oper
+// version de 25 nov 99  sans const R
+// ajoute de '.' pour extraire une colonne, ou ligne  , ...
+//  version du 22 nov 1999   cast to KN_<const R> 
+//   version du 21 nov 1999  correction delete 
+//  version du 13 nov 1999
+//  version du 18 mars 99
+//  F. Hecht 
+// attention les indexations les indexations peuvent changer
+//  puisque que l'on peut prendre la transposer d'une matrice
+// tableau 
+// mais ils partent de 0 
+// version corrigee du 15/11/98
+// version avec sous tableau  ---  mars 99 
+// -------
+//  remarque du 8 mars 99 FH
+// class pour prendre des sous-tableau
+// attention aux PB de continute dans les tableaux
+// on a supposer que les tableaux multi indices pouvait est vue comme 
+// un tableau continue ce qui est generalement faux quand l'on en 
+// prend un sous tableau
+//   exemple: un tableau 3,5 est numerote comme:
+//    0  3  6  9 12
+//    1  4  7 10 13
+//    2  5  8 11 14
+//             step
+//   indexi  n 1
+//   indexj  m n
+//   est le sous tableau  3,3  n'est pas numeroter consecutivement 
+//  
+//    Donc la fonction  IsVector1() nous dit si un tableau 
+//    a un 2 ou 3 indices est ou non consecutif en memoire
+//    
+//  --  ajoute d'une classe VirtualMatrice
+// pour modeliser le produit matrice vecteur 
+//  x = A*v; via des fonctions virtuelle 
+//  ---------------------------------- 
+//   version du 6 mars 2001 FH
+//   ---  initialisation --
+//   --------------------------------
+//   version du 9 oct 2001 FH
+//   ajoute de constructeur par defaut d'une vecteur
+//   +  set , pour definir le vecteur 
+//   ou l'affectation (bof bof) 
+// ---------------------
+//  version sep 2002
+//  ajoute  operateur >> pour  KN<R> et KN_<R>
+//  --------------------  
+//  version  april 2003
+//  ajoute un gestion auto de 
+//  la fonction InternalError pour les matriceVirtuel
+//  --------------------  
+//   version jan 2004
+//   correction pour go ++ 
+//   des operateur  #=  pour les matrices et tenseurs
+//  ----------------------
+//   version  feb 2004 
+//   v(i(:)) =  w   //  i(1:10) 
+//   w=u(i(:))  //  
+//   version mars 2004 make small correction
+//   in  ITAB operator problem if non type R a defi 
+//   -------------------
+//   Modif pour version avec les Complex   mai 2004                                                                                                 
+//   (u,v)  donne le produit complex utiliser dans le produit matrice vecteur
+//   (u,conj(v))  donne le produit hermitiene pour le gradient conjugue
+//
+//   -- de fonction dans le cas real                                                                                                                 
+// modif for g++ 4.0 and xlc++   mai 2005
+//  adding some this-> 
+//   mars 2007
+// correction in operator operation:b -1*c 
+// aout 2007, 
+//  correct y = A*x ; when y is unset 
+//  correct y += A*x ; when y is unset 
+//  re-correct += sep 2007
+//  add size of the matrix in VirtualMatrix class.
+//   mars 2010 add  unset KNM case ...
+//  sept 2014  add 1/v operator  ... 
+// ----------------
+
+namespace RNM {
+inline double  conj(const double & x){return x;}
+inline float  conj(const float &x){return x;}
+inline long  conj(const long &x){return x;}
+inline double  real(const double &x){return x;}
+inline float  real(const float &x){return x;}
+    template<class T> T  real(const complex<T>& v){ return std::real(v);}
+inline double  norm2(const double x){return x*x;}
+inline float  norm2(const float x){return x*x;}
+template<class T> T  norm2(const complex<T>& v){ return std::norm(v);}
+    
+template<class T> inline complex<T>  conj(const complex<T>& v){ return std::conj<T>(v);}
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
+
+template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;}
+template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
+template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
+// specialisation cas complex ---
+template<class T> 
+inline complex<T> Min(const complex<T> &a,complex<T> &b)
+{ return complex<T>(min(a.real(),b.real()),min(a.imag(),b.imag()));}
+template<class T> 
+inline complex<T> Max(const complex<T> &a,const complex<T> &b)
+{ return complex<T>(max(a.real(),b.real()),max(a.imag(),b.imag()));}
+
+/*inline complex<double> Min(const complex<double> &a,complex<double> &b)
+{ return complex<double>(Min(real(a),real(b)),Min(imag(a),imag(b)));}
+inline complex<double> Max(const complex<double> &a,const complex<double> &b)
+{ return complex<double>(Max(real(a),real(b)),Max(imag(a),imag(b)));}
+*/ }
+//  ----                                                                                                                                             
+
+template<class R> class KNMK_ ;
+template<class R> class KNM_ ;
+template<class R> class KN_ ;
+template<class R> class TKN_ ; // KN_ Hermitain 
+template<class R> class ConjKNM_ ;//  take the conj of the matrix.
+template<class R> class notKN_ ; // KN_ not 
+template<class R> class notnotKN_ ; // KN_ not not 
+
+template<class R> class KNMK ;
+template<class R> class KNM ;
+template<class R> class KN ;
+
+template<class R> class conj_KN_ ;
+template<class R> class Add_KN_;
+template<class R> class Sub_KN_;
+template<class R> class Mulc_KN_; // vector b*a_i
+template<class R> class Divc_KN_;// vector b/a_i
+template<class R> class Add_Mulc_KN_;
+template<class R> class Mul_KNM_KN_; 
+template<class R> class DotStar_KN_;
+template<class R> class DotSlash_KN_;
+
+template<class R> class outProduct_KN_;
+template<class R> class if_KN_;
+template<class R> class if_arth_KN_;
+template<class R> class ifnot_KN_;
+template<class R,class I> class KN_ITAB; 
+
+template<class R,typename A,typename B> class F_KN_;
+
+
+#ifndef ffassert
+#define ffassert assert
+#endif
+
+// gestion des erreur interne --
+#ifndef InternalError
+typedef void (* TypeofInternalErrorRoutine)(const char *) ;
+static TypeofInternalErrorRoutine &InternalErrorRoutinePtr()
+{ 
+  static TypeofInternalErrorRoutine routine=0;
+  return routine;
+}
+
+static void InternalError(const char * str) {
+  if (InternalErrorRoutinePtr() ) (*InternalErrorRoutinePtr())(str);
+  cerr << str; 
+  exit(1);
+}
+inline void  SetInternalErrorRoutine(TypeofInternalErrorRoutine f) 
+{
+  InternalErrorRoutinePtr()=f;
+}
+#endif
+//  -- 
+template<class P,class Q> 
+   struct PplusQ { const P & p;const Q & q;
+    PplusQ(const P & pp,const Q & qq) : p(pp),q(qq){}
+    };
+
+template<class R> 
+struct  VirtualMatrice { public:
+    int N,M;
+    VirtualMatrice(int nn,int mm): N(nn),M(mm) {}
+    VirtualMatrice(int nn): N(nn),M(nn) {}
+  //  y += A x
+  virtual void addMatMul(const KN_<R> &  x, KN_<R> & y) const =0; 
+  virtual void addMatTransMul(const KN_<R> &  , KN_<R> & ) const 
+    { InternalError("VirtualMatrice::addMatTransMul not implemented "); }
+  virtual bool WithSolver() const {return false;} // by default no solver          
+  virtual void Solve( KN_<R> &  ,const KN_<R> & ) const 
+    { InternalError("VirtualMatrice::solve not implemented "); } 
+
+#ifdef VersionFreeFempp
+  virtual bool ChecknbLine  (int n) const= 0; 
+  virtual bool ChecknbColumn  (int m) const =0; 
+#else
+  virtual bool ChecknbLine  (int n) const {return true;} 
+  virtual bool ChecknbColumn  (int m) const {return true;}
+#endif
+  struct  plusAx { const VirtualMatrice * A; const KN_<R>   x;
+   plusAx( const VirtualMatrice * B,const KN_<R> &  y) :A(B),x(y) 
+      { ffassert(B->ChecknbColumn(y.N())); }
+    };
+    
+   plusAx operator*(const KN_<R> &  x) const {return plusAx(this,x);}
+   
+  struct  plusAtx { const VirtualMatrice * A; const KN_<R>   x;
+   plusAtx( const VirtualMatrice * B,const KN_<R> &  y) :A(B),x(y) 
+    {ffassert(B->ChecknbLine(y.N()));} };
+    
+  struct  solveAxeqb { const VirtualMatrice * A; const KN_<R>   b;
+   solveAxeqb( const VirtualMatrice * B,const KN_<R> &  y) :A(B),b(y) 
+    {ffassert(B->ChecknbColumn(y.N()));} };
+  
+  virtual ~VirtualMatrice(){} 
+};
+
+    
+
+//template <class R> class MatriceCreuseMulKN_;
+//template <class R> class MatriceCreuseDivKN_;
+
+class ShapeOfArray;
+
+class FromTo{ public:
+  long from,to;
+  FromTo(long i,long j):from(i),to(j) {K_throwassert(i<j);} 
+ };
+ 
+class SubArray{ public:
+  const long n,step,start;
+//  SubArray(char  nn): n(-1),step(1),start(0) {}  
+ explicit SubArray(long nn,long sta=0,long s=1): n(nn),step(s),start(sta) {}
+  SubArray(const FromTo& ft) : n(ft.to-ft.from+1),step(1),start(ft.from) {}
+  SubArray(const ShapeOfArray & ); // all 
+  long end()  const  { return start+ step*n;}
+  long last() const  { return start+ step*(n-1);}
+  long len1() const  { return step*(n-1);}  
+};
+
+
+class ShapeOfArray{ protected:
+  public:
+
+    long n;     //   n  nb of item
+    long step;  //   step  nb of between 2 item
+    long next;  //  the   next array of same type in matrix for subarray  
+              // by default  no next ( in case of KN, and KNM  -next is
+              // a counter of destruction  (use in frefem++)
+  ShapeOfArray(const ShapeOfArray & s,long nn): n(s.n),step(s.n),next(nn) {}              
+  ShapeOfArray(long nn): n(nn),step(1),next(-1) {}
+  
+  ShapeOfArray(long nn,long s): n(nn),step(s),next(-1) {}
+  
+  ShapeOfArray(long nn,long s,long nextt): n(nn),step(s),next(nextt) {}
+  
+  ShapeOfArray(const ShapeOfArray &old,const SubArray &sub) 
+         : n(sub.n),step(old.step*sub.step),next(old.next)
+          { K_throwassert((sub.last())*old.step <= old.last());} // a constructor 
+          
+  ShapeOfArray(const ShapeOfArray &old,long stepo,long start) 
+         : n(old.n-start),step(old.step*stepo),next(old.next) 
+          { K_throwassert(n>=0);}        
+          
+  long end()  const      { return n*step;}
+  long last()      const      { return (n-1)*step;}
+  long constant()  const { return step==0;}
+  long index(long k) const { K_throwassert( (k>=0) && ( (k <n) || !step) );
+           return step*k;}
+  ShapeOfArray operator*(long stepp) const {return  ShapeOfArray(n,step*stepp,next);}  
+  bool SameShape(const ShapeOfArray & a) const 
+          { return  !step || !a.step || a.n == n ;} 
+  long  N(const ShapeOfArray & a) { return step ? n : a.n;} // size of 2 shape 
+
+  
+// protected:
+  long operator[](long k) const {  
+    //if( k<0 || ( k<n && !step) )
+    //  cout << "k,n,step=" << k << " " << n << " " << step << endl;
+    K_throwassert( (k>=0) && ( (k <n) || !step) );
+           return step*k;}     
+  void init(long nn,long s=1,long nextt=-1) { n=nn; step=s; next=nextt;}         
+};
+
+ostream & operator<<(ostream & f,const ShapeOfArray & s);
+
+inline bool  SameShape(const ShapeOfArray & a,const ShapeOfArray & b) 
+           { return  !a.step || !b.step || a.n == b.n ;} 
+   
+inline long N(const ShapeOfArray & a,const ShapeOfArray & b) 
+           { K_throwassert(SameShape(a,b)); return  a.step ? a.n :  b.n ;}
+
+inline SubArray::SubArray(const ShapeOfArray & s) 
+           :n(s.n),step(s.step),start(0) {}
+           
+   
+
+template<class R> 
+ostream & operator<<(ostream & f,const KN_<const_R> & v) ;
+
+template<class R> istream & operator>>(istream & f, KN_<R> & v);
+template<class R> istream & operator>>(istream & f, KN<R> & v);
+
+template<class R>
+class SetArray { public:
+    R o,step;
+    long n;
+    explicit SetArray(long nn,R oo=R(),R sstep=R(1)): o(oo),n(nn),step(sstep) {}
+    template<class K>   SetArray(SetArray<K> sa): o(sa.o),n(sa.n),step(sa.step) {}
+    
+  R operator[](long i) const { return i <= n ? o + R(i)*step : R();}
+    long size() const {return n;}
+};
+
+/// <<KN_>>
+template<class R>
+class KN_: public  ShapeOfArray {
+protected:
+  R *v;
+public:
+  typedef R K; // type of data 
+  long N() const {return n;}
+  bool unset() const { return !v;}
+  void set(R * vv,int nn,int st=1,int nx=-1) {v=vv;n=nn;step=st;next=nx;}
+  long size() const{return step?n*step:n;}
+  operator R *() const {return v;}
+  KN_(const KN_<R> & u) :ShapeOfArray(u),v(u.v){} 
+  KN_(const KN_<R> & U,const SubArray & sa)  : ShapeOfArray(U,sa),v(U.v + U.index(sa.start)) {}
+
+  KN_ operator()(const SubArray & sa) const { return KN_(*this,sa);} // sub array 
+  
+  R & operator[](long i) const {return v[index(i)];}
+  R & operator()(long i) const {return v[index(i)];}
+  R & operator[](int i) const {return v[index(i)];}
+  R & operator()(int i) const {return v[index(i)];}
+
+  R operator,(const KN_<const_R> & v) const; // dot  product 
+
+   KN_& operator  =(const SetArray<R> & u)  ;
+   KN_& operator +=(const SetArray<R> & u)  ;
+   KN_& operator -=(const SetArray<R> & u)  ;  
+   KN_& operator *=(const SetArray<R> & u)  ;
+   KN_& operator /=(const SetArray<R> & u)  ;
+
+    KN_& operator  =(const KN_<const_R> & u)  ;
+    KN_& operator +=(const KN_<const_R> & u)  ;
+    KN_& operator -=(const KN_<const_R> & u)  ;
+    
+    KN_& operator *=(const KN_<const_R> & u)  ;
+    KN_& operator /=(const KN_<const_R> & u)  ;
+    
+  
+   KN_& operator = (const_R  a) ;  
+   KN_& operator +=(const_R  a) ;
+   KN_& operator -=(const_R  a) ;  
+   KN_& operator /=(const_R  a) ;
+   KN_& operator *=(const_R  a) ;
+  
+   KN_& operator  = (R*  a) { return operator =(KN_<R>(a,n));}
+   KN_& operator += (R*  a) { return operator+=(KN_<R>(a,n));}  
+   KN_& operator -= (R*  a) { return operator-=(KN_<R>(a,n));}  
+   KN_& operator *= (R*  a) { return operator*=(KN_<R>(a,n));}  
+   KN_& operator /= (R*  a) { return operator/=(KN_<R>(a,n));}  
+
+
+  
+  R min() const ;
+  R max() const ;
+  R sum() const ;
+  double norm() const ;
+  double l2() const ;
+  double l1() const ;
+  double linfty() const ;
+  double lp(double p) const ;
+  
+  template<class T> long last(const T &) const;
+  template<class T> long first(const T &) const;
+  
+  void map(R (*f)(R )); // apply the f fonction a all element of the array
+  void map(R (*f)(const  R& )); // apply the f fonction a all element of the array
+
+ template<class T>
+   void set(R (*f)(const  T& ),KN_<T> & u); // apply the f fonction a all element of the array u
+  
+   KN_& operator =(const DotStar_KN_<R> & u) ;
+   KN_& operator+=(const DotStar_KN_<R> & u) ;
+   KN_& operator-=(const DotStar_KN_<R> & u) ;
+   KN_& operator*=(const DotStar_KN_<R> & u) ;
+   KN_& operator/=(const DotStar_KN_<R> & u) ;
+
+   KN_& operator =(const DotSlash_KN_<R> & u) ;
+   KN_& operator+=(const DotSlash_KN_<R> & u) ;
+   KN_& operator-=(const DotSlash_KN_<R> & u) ;
+   KN_& operator*=(const DotSlash_KN_<R> & u) ;
+   KN_& operator/=(const DotSlash_KN_<R> & u) ;
+
+   KN_& operator =(const if_KN_<R> & u) ;
+   KN_& operator+=(const if_KN_<R> & u) ;
+   KN_& operator-=(const if_KN_<R> & u) ;
+   KN_& operator*=(const if_KN_<R> & u) ;
+   KN_& operator/=(const if_KN_<R> & u) ;
+
+   KN_& operator =(const ifnot_KN_<R> & u) ;
+   KN_& operator+=(const ifnot_KN_<R> & u) ;
+   KN_& operator-=(const ifnot_KN_<R> & u) ;
+   KN_& operator*=(const ifnot_KN_<R> & u) ;
+   KN_& operator/=(const ifnot_KN_<R> & u) ;
+
+   KN_& operator =(const Add_KN_<R> & u) ;
+   KN_& operator+=(const Add_KN_<R> & u) ;
+   KN_& operator-=(const Add_KN_<R> & u) ;
+   KN_& operator*=(const Add_KN_<R> & u) ;
+   KN_& operator/=(const Add_KN_<R> & u) ;
+  
+   template<class I,class T> KN_& operator =  (const KN_ITAB<T,I> & u);
+   template<class I,class T> KN_& operator +=  (const KN_ITAB<T,I> & u);
+   template<class I,class T> KN_& operator -=  (const KN_ITAB<T,I> & u);
+   template<class I,class T> KN_& operator *=  (const KN_ITAB<T,I> & u);
+   template<class I,class T> KN_& operator /=  (const KN_ITAB<T,I> & u);
+
+
+   KN_ITAB< KN_<R>,const KN_<int> >  operator()(const KN_<int> &itab) ;
+   KN_ITAB< KN_<R>,const KN_<long> >  operator()(const KN_<long> &itab) ;
+   KN_ITAB<const KN_<R>,const KN_<int> > operator()(const KN_<int> &itab) const ;
+   KN_ITAB<const KN_<R>,const KN_<long> >  operator()(const KN_<long> &itab) const ;
+
+
+    
+
+  
+   KN_& operator =(const Sub_KN_<R> & u) ;
+   KN_& operator-=(const Sub_KN_<R> & u) ;
+   KN_& operator+=(const Sub_KN_<R> & u) ;
+   KN_& operator*=(const Sub_KN_<R> & u) ;
+   KN_& operator/=(const Sub_KN_<R> & u) ;
+  
+   KN_& operator =(const Mulc_KN_<R> & u) ;
+   KN_& operator+=(const Mulc_KN_<R> & u) ;
+   KN_& operator-=(const Mulc_KN_<R> & u) ;
+   KN_& operator*=(const Mulc_KN_<R> & u) ;
+   KN_& operator/=(const Mulc_KN_<R> & u) ;
+ 
+    KN_& operator =(const Divc_KN_<R> & u) ;
+    KN_& operator+=(const Divc_KN_<R> & u) ;
+    KN_& operator-=(const Divc_KN_<R> & u) ;
+    KN_& operator*=(const Divc_KN_<R> & u) ;
+    KN_& operator/=(const Divc_KN_<R> & u) ;
+    
+   KN_& operator =(const Add_Mulc_KN_<R> & u) ;
+   KN_& operator+=(const Add_Mulc_KN_<R> & u) ;
+   KN_& operator-=(const Add_Mulc_KN_<R> & u) ;
+   KN_& operator*=(const Add_Mulc_KN_<R> & u) ;
+   KN_& operator/=(const Add_Mulc_KN_<R> & u) ;
+
+   KN_& operator =(const if_arth_KN_<R> & u) ;
+   KN_& operator+=(const if_arth_KN_<R> & u) ;
+   KN_& operator-=(const if_arth_KN_<R> & u) ;
+   KN_& operator*=(const if_arth_KN_<R> & u) ;
+   KN_& operator/=(const if_arth_KN_<R> & u) ;
+
+  
+   KN_& operator =(const Mul_KNM_KN_<R> & u) ; 
+   KN_& operator+=(const Mul_KNM_KN_<R> & u) ; 
+   KN_& operator-=(const Mul_KNM_KN_<R> & u) ; 
+   KN_& operator*=(const Mul_KNM_KN_<R> & u) ; 
+   KN_& operator/=(const Mul_KNM_KN_<R> & u) ; 
+  
+ //  KN_& operator =(const MatriceCreuseMulKN_<R> & ) ;
+ //  KN_& operator +=(const MatriceCreuseMulKN_<R> & ) ;
+   KN_& operator =(const typename VirtualMatrice<R>::plusAx & Ax)  
+    {*this=R(); Ax.A->addMatMul(Ax.x,*this);return *this;}
+   KN_& operator =(const typename VirtualMatrice<R>::plusAtx & Ax)  
+    {*this=R(); Ax.A->addMatTransMul(Ax.x,*this);return *this;}
+   KN_& operator +=(const typename VirtualMatrice<R>::plusAx & Ax)  
+    {  Ax.A->addMatMul(Ax.x,*this);return *this;}
+   KN_& operator +=(const typename VirtualMatrice<R>::plusAtx & Ax)  
+    {  Ax.A->addMatTransMul(Ax.x,*this);return *this;}
+   KN_& operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab)  
+    {*this=R(); Ab.A->Solve(*this,Ab.b);return *this;}
+    
+  template<class  A,class B,class C> KN_&  operator =  (const F_KN_<A,B,C>  & u) ;
+  template<class  A,class B,class C> KN_&  operator +=  (const F_KN_<A,B,C>  & u) ;
+  template<class  A,class B,class C> KN_&  operator -=  (const F_KN_<A,B,C>  & u) ;
+  template<class  A,class B,class C> KN_&  operator /=  (const F_KN_<A,B,C>  & u) ;
+  template<class  A,class B,class C> KN_&  operator *=  (const F_KN_<A,B,C>  & u) ;
+    
+   
+//   KN_& operator =(const MatriceCreuseDivKN_<R> &)  ;
+
+ friend   ostream & operator<< <R>(ostream & f,const KN_<const_R> & v)  ;
+ 
+  KN_(R *u,const ShapeOfArray & s):ShapeOfArray(s),v(u){}
+  KN_(R *u,long nn,long s):ShapeOfArray(nn,s),v(u){}
+  KN_(R *u,long nn,long s,long nextt):ShapeOfArray(nn,s,nextt),v(u){}
+  KN_(R *u,long nn):ShapeOfArray(nn),v(u){}
+
+
+  TKN_<R>  t() ; // transpose
+  const TKN_<R>  t() const ; // transpose
+  notKN_<R>  operator!()  ; //  not
+  const  notKN_<R>  operator!() const ; // not
+
+  //  operator KN<R> &();
+  // operator const KN<R> &() const;
+
+ private:
+ 
+  KN_&  operator++(){K_throwassert(next>=0);v += next;return *this;} //    ++U
+  KN_&  operator--(){K_throwassert(next>=0);v -= next;return *this;} //    --U
+  KN_   operator++(int ){K_throwassert(next>=0); KN_ old=*this;v = v +next;return old;} // U++
+  KN_   operator--(int ){K_throwassert(next>=0); KN_ old=*this;v = v -next;return old;} // U++
+ 
+  KN_(const KN_<R> & u,long offset) :ShapeOfArray(u),v(&u[offset]){} 
+  KN_(const KN_<R> & u,const ShapeOfArray &sh,long startv=0)
+         :ShapeOfArray(sh*u.step),v(&u[startv]){}
+  KN_(const KN_<R> & u,long nnext,const ShapeOfArray &sh,long startv=0)
+         :ShapeOfArray(sh.n,sh.step*u.step,nnext),v(&u[startv]){ }
+
+  
+// friend class KN_<R>;   
+ friend class KNM_<R>;   
+ friend class KNMK_<R>;   
+ friend class KN<R>;   
+ friend class KNM<R>;   
+ friend class KNMK<R>;   
+  
+};
+
+template<class R>
+class KNM_: public KN_<R> {
+  public:
+  ShapeOfArray shapei;
+  ShapeOfArray shapej;
+  public:
+  long IsVector1() const  {  return (shapei.n*shapej.n) ==  this->n ;} 
+  long N() const {return shapei.n;}
+  long M() const {return shapej.n;}  
+  long size() const { return shapei.n*shapej.n;}
+    
+  ConjKNM_<R>  h() ; // take the conj for hermian operator
+  const ConjKNM_<R>  h() const ; // take the conj for hermian operator
+  
+  KNM_(R* u,const ShapeOfArray & s,
+            const ShapeOfArray & si,
+            const ShapeOfArray & sj)
+             : KN_<R>(u,s),shapei(si),shapej(sj){} 
+  KNM_(R* u,long nn,long mm)
+             : KN_<R>(u,ShapeOfArray(nn*mm)),shapei(nn,1,nn),shapej(mm,nn,1){}
+  KNM_(R* u,long nn,long mm,long s)
+             : KN_<R>(u,ShapeOfArray(nn*mm,s)),shapei(nn,1,nn),shapej(mm,nn,1){}                     
+  KNM_(KN_<R> u,long n,long m) 
+             : KN_<R>(u,ShapeOfArray(m*n)),shapei(n,1,n),shapej(m,n,1){ }
+             
+  KNM_(const KN_<R> &u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset=0) 
+             : KN_<R>(&u[offset],si.last()+sj.last()+1,u.step),shapei(si),shapej(sj) 
+             {K_throwassert( offset>=0 && this->n+ (this->v-(R*)u) <= u.n);}
+  KNM_(const KN_<R> &u,const ShapeOfArray & si,const ShapeOfArray & sj,long offset,long nnext) 
+             : KN_<R>(&u[offset],si.last()+sj.last()+1,u.step,nnext),shapei(si),shapej(sj) 
+             {K_throwassert( offset>=0 && this->n+ (this->v-(R*)u) <= u.n);}
+  
+  KNM_(KNM_<R> U,const SubArray & si,const SubArray & sj)  
+             :KN_<R>(U,SubArray(U.ij(si.len1(),sj.len1())+1,U.ij(si.start,sj.start))),
+                     shapei(U.shapei,si),shapej(U.shapej,sj){} 
+
+  KNM_(KNM_<R> U,const SubArray & sa,const SubArray & si,const SubArray & sj)  
+             :KN_<R>(U,SubArray(sa)),shapei(U.shapei,si),shapej(U.shapej,sj){} 
+
+  KNM_(const KNM_<R> & u) 
+             :KN_<R>(u),shapei(u.shapei),shapej(u.shapej) {}
+
+  KNM_ operator()(const SubArray & sa,const SubArray & sb) const 
+            { return KNM_(*this,sa,sb);} // sub array 
+  
+  long ij(long i,long j) const   
+            { return shapei.index(i)+shapej.index(j);}
+  long indexij(long i,long j)        const   
+            { return this->index(shapei.index(i)+shapej.index(j));}
+  R & operator()(long i,long j)     const   
+            { return this->v[indexij(i,j)];}
+  R & operator()(int i,int j)     const   
+            { return this->v[indexij(i,j)];}
+            
+   KN_<R> operator()(const SubArray & sa,long j) const 
+    { return this->operator()(':',j)(sa);}  // sub array 
+   
+  KN_<R> operator()(long i,const SubArray & sb) const 
+    { return  this->operator()(i,':')(sb);} 
+    
+  KN_<R> operator()(const char,long j    )  const   // une colonne j  ('.',j)
+            { return KN_<R>(&this->v[this->index(shapej.index(j))],shapei*this->step);} 
+  KN_<R> operator()(long i    ,const char)  const   // une ligne i  (i,'.')
+            { return KN_<R>(&this->v[this->index(shapei.index(i))],shapej*this->step);}  
+  KN_<R> operator()(const char,int j    )  const   // une colonne j  ('.',j)
+            { return KN_<R>(&this->v[this->index(shapej.index(j))],shapei*this->step);} 
+  KN_<R> operator()(int i    ,const char)  const   // une ligne i  (i,'.')
+            { return KN_<R>(&this->v[this->index(shapei.index(i))],shapej*this->step);}  
+  KN_<R> operator()(const char,const char)  const   // tous 
+            { return *this;}
+  KNM_<R> t() const
+    { return KNM_<R>(this->v,*this,shapej,shapei);} //  before  { return KNM_<R>(*this,shapej,shapei,v);}
+  
+   KNM_& operator =(const KNM_<const_R> & u) ;
+   KNM_& operator =(const_R a)               ;
+   KNM_& operator+=(const_R a)               ;
+   KNM_& operator-=(const_R a)               ; 
+   KNM_& operator/=(const_R a)               ;
+   KNM_& operator*=(const_R a)               ; 
+   KNM_& operator+=(const KNM_<const_R> & u) ;
+   KNM_& operator-=(const KNM_<const_R> & u) ;
+   KNM_& operator*=(const KNM_<const_R> & u) ;
+   KNM_& operator/=(const KNM_<const_R> & u) ;
+   
+   KNM_ &operator =(const outProduct_KN_<R> &);
+   KNM_ &operator +=(const outProduct_KN_<R> &);
+   KNM_ &operator -=(const outProduct_KN_<R> &);
+   KNM_ &operator /=(const outProduct_KN_<R> &); // bofbof
+   KNM_ &operator *=(const outProduct_KN_<R> &); // bofbof
+
+    KNM_ &operator  =(const ConjKNM_<R> &);
+    KNM_ &operator +=(const ConjKNM_<R> &);
+    KNM_ &operator -=(const ConjKNM_<R> &);
+    KNM_ &operator /=(const ConjKNM_<R> &); // bofbof
+    KNM_ &operator *=(const ConjKNM_<R> &); // bofbof
+    
+private:  
+  KNM_& operator++() {this->v += this->next;return *this;} // ++U
+  KNM_& operator--() {this->v -= this->next;return *this;} // ++U
+  KNM_  operator++(int ){KNM_<R> old=*this;this->v = this->v +this->next;return old;} // U++
+  KNM_  operator--(int ){KNM_<R> old=*this;this->v = this->v -this->next;return old;} // U--
+
+
+ friend class KN_<R>;   
+// friend class KNM_<R>;   
+ friend class KNMK_<R>;   
+ friend class KN<R>;   
+ friend class KNM<R>;   
+ friend class KNMK<R>;   
+};
+
+template<class T,class I> 
+struct KN_ITAB
+{
+  KN_ITAB(const T &vv,const I &iindex) : v(vv),index(iindex) {}
+  T  v;
+  I  index;
+  KN_ITAB & operator=(const T & t);
+  KN_ITAB & operator+=(const T & t);
+  KN_ITAB & operator-=(const T & t);
+  KN_ITAB & operator*=(const T & t);
+  KN_ITAB & operator/=(const T & t);
+  typename T::R & operator[](long i){ return v[index[i]];}
+  const typename T::R &  operator[](long i) const { return v[index[i]];}
+  long N() const { return index.N();}    
+};
+
+template<class R>  KN_ITAB<const KN_<R>,const KN_<int> >  KN_<R>::operator()(const KN_<int>  &itab) const { return KN_ITAB<const KN_<R>,const KN_<int> > (*this,itab);}
+template<class R>  KN_ITAB<const KN_<R>,const KN_<long> >  KN_<R>::operator()(const KN_<long>  &itab) const { return KN_ITAB<const KN_<R>,const KN_<long> > (*this,itab);}
+template<class R>  KN_ITAB< KN_<R>,const KN_<int> >  KN_<R>::operator()(const KN_<int>  &itab) { return KN_ITAB<KN_<R>,const KN_<int> > (*this,itab);}
+template<class R>  KN_ITAB< KN_<R>,const KN_<long> >  KN_<R>::operator()(const KN_<long>  &itab) { return KN_ITAB<KN_<R>,const KN_<long> > (*this,itab);}
+
+
+template<class R>
+struct TKN_:public KN_<R> {
+    TKN_(const KN_<R> &x) : KN_<R>(x) {}
+};
+
+template<class R>
+struct ConjKNM_:public KNM_<R> {
+    ConjKNM_(const KNM_<R> &x) : KNM_<R>(x) {}
+};
+
+template<class R>
+struct notKN_:public KN_<R> {
+    notKN_(const KN_<R> &x) : KN_<R>(x) {}
+    notnotKN_<R>  operator!()  ; //  not
+    const  notnotKN_<R>  operator!() const ; // not
+};
+
+template<class R>
+struct notnotKN_:public KN_<R> {
+    notnotKN_(const notKN_<R> &x) : KN_<R>(x) {}
+    notKN_<R>  operator!()  ; //  notnot
+    const  notKN_<R>  operator!() const ; // notnot
+};
+
+template<class R>
+TKN_<R>  KN_<R>::t() { return *this;} // transpose
+template<class R>
+ConjKNM_<R>  KNM_<R>::h() { return *this;} // conj of the matrix
+
+template<class R>
+const TKN_<R>  KN_<R>::t() const { return *this;} // transpose
+template<class R>
+const ConjKNM_<R>  KNM_<R>::h() const { return *this;} //  conj of the matrix
+
+template<class R>
+notKN_<R>  KN_<R>::operator!() { return *this;} // not
+
+template<class R>
+const notKN_<R>  KN_<R>::operator!() const { return *this;} // not
+
+template<class R>
+notnotKN_<R>  notKN_<R>::operator!() { return *this;} // not
+
+template<class R>
+const notnotKN_<R>  notKN_<R>::operator!() const { return *this;} // not
+
+
+template<class R>
+struct outProduct_KN_ {
+    const KN_<R>  a,b;
+    R c;
+    long N() const {return a.N();    }
+    long M() const {return b.N();    }
+    outProduct_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=(R)1) : a(aa),b(bb),c(cc) {}
+    outProduct_KN_(const KN_<R> * aa, const KN_<R> &bb,R cc=(R)1) : a(*aa),b(bb),c(cc) {}
+    outProduct_KN_(const KN_<R> * aa, const KN_<R> *bb,R cc=(R)1) : a(*aa),b(*bb),c(cc) {}
+    outProduct_KN_(const Mulc_KN_<R> & aa,const KN_<R> & bb) : a(aa.a),b(bb),c(aa.b) {}    
+    outProduct_KN_ operator * (R cc) { return outProduct_KN_(a,b,c*cc);}    
+};
+
+template<class R>
+struct if_KN_ {
+    const KN_<R> & a,&b;
+    R c;
+    if_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=1.) : a(aa),b(bb),c(cc) {}
+    if_KN_ operator * (R cc) { return if_KN_(a,b,c*cc);}    
+};
+
+template<class R>
+struct ifnot_KN_ {
+    const KN_<R> & a,&b;
+    R c;
+    ifnot_KN_(const KN_<R> & aa, const KN_<R> &bb,R cc=1.) : a(aa),b(bb),c(cc) {}
+    ifnot_KN_ operator * (R cc) { return ifnot_KN_(a,b,c*cc);}    
+};
+
+
+template<class R> 
+outProduct_KN_<R> operator*(const KN_<R> &a,const TKN_<R> &b) 
+{ return outProduct_KN_<R>(a,b);}
+
+template<class R> 
+ifnot_KN_<R> operator*(const KN_<R> &a,const notKN_<R> &b) 
+{ return ifnot_KN_<R>(b,a);}
+
+template<class R> 
+ifnot_KN_<R> operator*(const KN_<R> &a,const notnotKN_<R> &b) 
+{ return if_KN_<R>(b,a);}
+
+template<class R> 
+ifnot_KN_<R> operator*(const notKN_<R> &b,const KN_<R> &a) 
+{ return ifnot_KN_<R>(b,a);}
+
+template<class R> 
+ifnot_KN_<R> operator*(const notnotKN_<R> &b,const KN_<R> & a) 
+{ return if_KN_<R>(b,a);}
+
+
+template<class R> 
+R operator*(const TKN_<R> &a,const KN_<R> &b) 
+{ return (a,b);}
+
+template<class R>
+class KNMK_: public KN_<R> {
+  friend class KNMK<R>;
+  public:
+  ShapeOfArray shapei;
+  ShapeOfArray shapej;
+  ShapeOfArray shapek;
+  public:
+  long IsVector1() const {  return (shapei.n*shapej.n*shapek.n) == this->n ;} 
+  long N() const {return shapei.n;}
+  long M() const {return shapej.n;}
+  long K() const {return shapek.n;}
+  long size() const { return shapei.n*shapej.n*shapek.n;}
+  KNMK_(const ShapeOfArray & s,
+        const ShapeOfArray & si,
+        const ShapeOfArray & sj,
+        const ShapeOfArray & sk,
+	    R * u)
+    : KN_<R>(u,s),shapei(si),shapej(sj),shapek(sk){} 
+    
+  KNMK_(R* u,long n,long m,long k)
+    : KN_<R>(u, ShapeOfArray(n*m*k)),shapei(n,1,n),shapej(m,n,1),shapek(k,n*m,n*m){};
+    
+//  KNMK_(const KN_<R> & u,long n,long m,long k)
+//   : KN_<R>(ShapeOfArray(n*m*k)),shapei(n,1,n),shapekj(m,n,1),u),
+//     shapek(k,n*m,n*m){};
+
+  KNMK_(const KNMK_<R> &U,const SubArray & si,const SubArray & sj,const SubArray & sk)  :
+    KN_<R>(U,SubArray(U.ijk(si.len1(),sj.len1(),sk.len1())+1,
+                       U.ijk(si.start,sj.start,sk.start))),
+                       shapei(U.shapei,si),
+                       shapej(U.shapej,sj),
+                       shapek(U.shapek,sk){} 
+
+  KNMK_(const KNMK_<R> & u) :KN_<R>(u),shapei(u.shapei),shapej(u.shapej),shapek(u.shapek) {}
+
+    
+  long ijk(long i,long j,long k) const 
+              { return shapei.index(i)+shapej.index(j)+shapek.index(k);}
+  long indexijk(long i,long j,long k) const 
+              {return this->index(shapei.index(i)+shapej.index(j)+shapek.index(k));} 
+                           
+  R & operator()(long i,long j,long k)   const   {return this->v[indexijk(i,j,k)];}
+  R & operator()(int i,int j,int k)   const   {return this->v[indexijk(i,j,k)];}
+  
+//  pas de tableau suivant
+ KN_<R>  operator()(const char ,long j,long k)  const  { // le tableau (.,j,k) 
+        return KN_<R>(*this,-1,shapei,shapej[j]+shapek[k]);}
+ KN_<R>  operator()(long i,const char ,long k)  const  { // le tableau (i,.,k) 
+        return KN_<R>(*this,-1,shapej,shapei[i]+shapek[k]);}
+ KN_<R>  operator()(long i,long j,const char )  const  { // le tableau (i,j,.) 
+        return KN_<R>(*this,-1,shapek,shapei[i]+shapej[j]);}
+
+ KN_<R>  operator()(const char ,int j,int k)  const  { // le tableau (.,j,k) 
+        return KN_<R>(*this,-1,shapei,shapej[j]+shapek[k]);}
+ KN_<R>  operator()(int i,const char ,int k)  const  { // le tableau (i,.,k) 
+        return KN_<R>(*this,-1,shapej,shapei[i]+shapek[k]);}
+ KN_<R>  operator()(int i,int j,const char )  const  { // le tableau (i,j,.) 
+        return KN_<R>(*this,-1,shapek,shapei[i]+shapej[j]);}
+//                                              
+ KNM_<R>  operator()(const char ,const char ,long k)  const  { // le tableau (.,.,k) 
+        return KNM_<R>(*this,shapei,shapej,shapek[k],shapek.next);} // step = n*m
+ //attention les suivants ne marche pas
+ KNM_<R>  operator()(const char ,long j,const char )  const  { // le tableau (.,j,.) 
+        return KNM_<R>(*this,shapei,shapek,shapej[j],-1/*shapej.next*/);} // step = n
+        
+ KNM_<R>  operator()(long i,const char ,const char )  const  { // le tableau (i,.,.) 
+        return KNM_<R>(*this,shapej,shapek,shapei[i],-1/*shapei.next*/);}  // step = 1
+
+ KNM_<R>  operator()(const char ,const char ,int k)  const  { // le tableau (.,.,k) 
+        return KNM_<R>(*this,shapei,shapej,shapek[k],shapek.next);} // step = n*m
+ //attention les suivants ne marche pas
+ KNM_<R>  operator()(const char ,int j,const char )  const  { // le tableau (.,j,.) 
+        return KNM_<R>(*this,shapei,shapek,shapej[j],-1/*shapej.next*/);} // step = n
+        
+ KNM_<R>  operator()(int i,const char ,const char )  const  { // le tableau (i,.,.) 
+        return KNM_<R>(*this,shapej,shapek,shapei[i],-1/*shapei.next*/);}  // step = 1
+
+   KNMK_& operator =(const KNMK_<const_R> & u) ;
+   KNMK_& operator+=(const KNMK_<const_R> & u)  ;
+   KNMK_& operator-=(const KNMK_<const_R> & u)  ;
+   KNMK_& operator/=(const KNMK_<const_R> & u)  ;
+   KNMK_& operator*=(const KNMK_<const_R> & u)  ;
+   KNMK_& operator =(const_R a)  ; 
+   KNMK_& operator+=(const_R a)  ;
+   KNMK_& operator-=(const_R a)  ;
+   KNMK_& operator/=(const_R a)  ;
+   KNMK_& operator*=(const_R a)  ;
+
+  KNMK_  operator()(SubArray si,SubArray sj,SubArray sk) const 
+        {return KNMK_(*this,si,sj,sk);}
+
+  private:
+//  KNMK_&  operator++(){v += next;return *this;} // ++U
+//  KNMK_&  operator--(){v -= next;return *this;} // --U
+//  KNMK_  operator++(long ){KNMK_ old=*this;v = v +next;return old;} // U++ 
+//  KNMK_  operator--(long ){KNMK_ old=*this;v = v -next;return old;} // U--
+ 
+        
+friend class KNM_<R>;   
+friend class KN_<R>;   
+
+};
+
+
+
+template<class R>
+class KN :public KN_<R> { public:
+
+  typedef R K;
+
+ // explicit  KN(const R & u):KN_<R>(new R(uu),1,0) {}
+  KN() : KN_<R>(0,0) {}
+  KN(long nn) : KN_<R>(new R[nn],nn)         {} 
+  KN(long nn, R * p) : KN_<R>(new R[nn],nn)  
+    { KN_<R>::operator=(KN_<R>(p,nn));}
+  KN(long nn,R (*f)(long i) ) : KN_<R>(new R[nn],nn) 
+        {for(long i=0;i<this->n;i++) this->v[i]=f(i);}  
+  KN(long nn,const  R & a) : KN_<R>(new R[nn],nn) 
+        { KN_<R>::operator=(a);} 
+  KN(long nn,long s,const  R  a) : KN_<R>(new R[nn],nn,s) 
+        { KN_<R>::operator=(a);} 
+  template<class S>   KN(const KN_<S> & s):KN_<R>(new R[s.n],s.n) 
+        {for (long i=0;i<this->n;i++) this->v[i] = s[i];}
+  template<class S>  KN(const KN_<S> & s,R (*f)(S )):KN_<R>(new R[s.n],s.n) 
+        {for (long i=0;i<this->n;i++) this->v[i] = f(s[i]);}
+  KN(const KN<R> & u):KN_<R>(new R[u.n],u.n)
+        { KN_<R>::operator=(u);}
+  KN(bool ,KN<R> & u):KN_<R>(u) {u.v=0;u.n=0;}// remove copy for return of local KN. 
+    
+  //  explicit KN(const KN_<R> & u):KN_<R>(new R[u.n],u.n) 
+  //      { KN_<R>::operator=(u);}
+        
+  ~KN(){delete [] this->v;}
+   
+  void CheckSet() { if(!(this->n)) {cerr << "Error RNM set array\n";K_throwassert(0); exit(1);}}
+   KN& operator  = (R*  a) { CheckSet(); return operator =(KN_<R>(a,this->n));}
+   KN& operator += (R*  a) { CheckSet(); return operator+=(KN_<R>(a,this->n));}  
+   KN& operator -= (R*  a) { CheckSet(); return operator-=(KN_<R>(a,this->n));}  
+   KN& operator *= (R*  a) { CheckSet(); return operator*=(KN_<R>(a,this->n));}  
+   KN& operator /= (R*  a) { CheckSet(); return operator/=(KN_<R>(a,this->n));}  
+  
+   KN& operator  =(const SetArray<R> & u)  
+     { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator= (u);return *this;}
+   KN& operator +=(const SetArray<R> & u)  
+     { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator+= (u);return *this;}
+   KN& operator -=(const SetArray<R> & u)    
+     { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator-= (u);return *this;}
+   KN& operator *=(const SetArray<R> & u)  
+     { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator*= (u);return *this;}
+   KN& operator /=(const SetArray<R> & u)  
+     { if(this->unset()) this->set(new R[u.size()],u.size(),0,0); KN_<R>::operator/= (u);return *this;}
+
+   KN& operator =(const_R a)  
+        { if(this->unset()) this->set(new R[1],1,0,0); KN_<R>::operator= (a);return *this;}
+   KN& operator =(const KN_<R>& a)  
+        { if(this->unset()) this->set(new R[a.N()],a.N()); KN_<R>::operator= (a);return *this;}                
+   KN& operator =(const KN<R>& a)  
+        { if(this->unset()) this->set(new R[a.N()],a.N()); KN_<R>::operator= (a);return *this;}                
+   KN& operator =(const Add_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const DotStar_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const if_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const ifnot_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const DotSlash_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const Sub_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const Mulc_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const Divc_KN_<R> & u)
+    { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const Add_Mulc_KN_<R> & u)
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+   KN& operator =(const if_arth_KN_<R> & u)  
+        { if(this->unset()) this->set(new R[u.a.N()],u.a.N());KN_<R>::operator=(u);return *this;}
+        
+        
+   KN& operator =(const Mul_KNM_KN_<R> & u) 
+        { if(this->unset()) this->set(new R[u.b.N()],u.b.N());KN_<R>::operator=(u);return *this;}
+//   KN& operator =(const MatriceCreuseMulKN_<R> & Ax) 
+//       {if(this->unset()) set(new R[Ax.v.N()],Ax.v.N()); KN_<R>::operator=(Ax);return *this;}
+//   KN& operator +=(const MatriceCreuseMulKN_<R> & Ax) 
+//       {if(this->unset()) set(new R[Ax.v.N()],Ax.v.N()); KN_<R>::operator+=(Ax);return *this;}
+//   KN& operator =(const MatriceCreuseDivKN_<R> & A1x)  
+//       { if(this->unset()) set(new R[A1x.v.N()],A1x.v.N());KN_<R>::operator=(A1x);return *this;}
+  // correcton aout 2007 FH  add N,M flied in VirtualMatrice
+   KN& operator =(const typename VirtualMatrice<R>::plusAx & Ax)  
+        { if(this->unset() && Ax.A->N ) this->set(new R[Ax.A->N],Ax.A->N);KN_<R>::operator=(Ax);return *this;}
+   KN& operator =(const typename VirtualMatrice<R>::solveAxeqb & Ab)  
+        { if(this->unset()) this->set(new R[Ab.b.N()],Ab.b.N());KN_<R>::operator=(Ab);return *this;}
+   KN& operator +=(const typename  VirtualMatrice<R>::plusAx & Ax)  
+  { if(this->unset()  && Ax.A->N) {
+        this->set(new R[Ax.A->N],Ax.A->N);
+        KN_<R>::operator=(R());}
+    KN_<R>::operator+=(Ax);
+    return *this;}
+   KN& operator =(const typename VirtualMatrice<R>::plusAtx & Ax)  
+        { if(this->unset()&&Ax.A->M) this->set(new R[Ax.A->M],Ax.A->M);KN_<R>::operator=(Ax);return *this;}
+   KN& operator +=(const typename VirtualMatrice<R>::plusAtx & Ax)  
+  { if(this->unset()&&Ax.A->M) {
+       this->set(new R[Ax.A->M],Ax.A->M);
+      KN_<R>::operator=(R());}
+      KN_<R>::operator+=(Ax);
+     return *this;}
+// end correcton FH
+   template<class P,class Q> 
+     KN& operator =(const  PplusQ<P,Q> & PQ)  
+      { *this=PQ.p; *this+=PQ.q;return *this; } 
+   template<class P,class Q> 
+     KN& operator +=(const  PplusQ<P,Q> & PQ)  
+      { *this+=PQ.p; *this+=PQ.q;return *this; } 
+           
+   KN& operator -=(const_R a)  
+        { KN_<R>::operator-=(a);return *this;}
+   KN& operator -=(const KN_<R>& a)  
+        { KN_<R>::operator-= (a);return *this;}
+   KN& operator -=(const Add_KN_<R> & u)  
+        { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const DotStar_KN_<R> & u)  
+        { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const DotSlash_KN_<R> & u)  
+        { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const Sub_KN_<R> & u)  
+        { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const Mulc_KN_<R> & u)  
+        { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const Divc_KN_<R> & u)
+    { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const Add_Mulc_KN_<R> & u)
+        { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const if_arth_KN_<R> & u)  
+        { KN_<R>::operator-=(u);return *this;}
+   KN& operator -=(const Mul_KNM_KN_<R> & u) 
+        { KN_<R>::operator-=(u);return *this;}
+ 
+   KN& operator +=(const_R a)  
+        { KN_<R>::operator += (a);return *this;}
+   KN& operator += (const KN_<R>& a)  
+        { KN_<R>::operator+= (a);return *this;}
+   KN& operator +=(const Add_KN_<R> & u)  
+        { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const DotStar_KN_<R> & u)  
+        { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const DotSlash_KN_<R> & u)  
+        { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const Sub_KN_<R> & u)  
+        { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const Mulc_KN_<R> & u)  
+        { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const Divc_KN_<R> & u)
+    { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const Add_Mulc_KN_<R> & u)
+        { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const if_arth_KN_<R> & u)  
+        { KN_<R>::operator+=(u);return *this;}
+   KN& operator +=(const Mul_KNM_KN_<R> & u) 
+        { KN_<R>::operator+=(u);return *this;}
+        
+
+   KN& operator/=(const_R a)  
+        { KN_<R>::operator/=(a);return *this;}
+   KN& operator /= (const KN_<R>& a)  
+        { KN_<R>::operator/= (a);return *this;}
+   KN& operator /=(const Add_KN_<R> & u)  
+        { KN_<R>::operator/=(u);return *this;}
+   KN& operator /=(const Sub_KN_<R> & u)  
+        { KN_<R>::operator/=(u);return *this;}
+   KN& operator /=(const Mulc_KN_<R> & u)  
+        { KN_<R>::operator/=(u);return *this;}
+   KN& operator /=(const Divc_KN_<R> & u)
+    { KN_<R>::operator/=(u);return *this;}
+    
+   KN& operator /=(const Add_Mulc_KN_<R> & u)  
+        { KN_<R>::operator/=(u);return *this;}
+   KN& operator /=(const if_arth_KN_<R> & u)  
+        { KN_<R>::operator/=(u);return *this;}
+        
+   KN& operator /=(const Mul_KNM_KN_<R> & u) 
+        { KN_<R>::operator/=(u);return *this;}
+        
+   KN& operator*=(const_R a)  
+        { KN_<R>::operator*=(a);return *this;}
+   KN& operator*=(const KN_<const_R>& a)  
+        { KN_<R>::operator*= (a);return *this;}
+   KN& operator *=(const Add_KN_<R> & u)  
+        { KN_<R>::operator*=(u);return *this;}
+   KN& operator *=(const Sub_KN_<R> & u)  
+        { KN_<R>::operator*=(u);return *this;}
+   KN& operator *=(const Mulc_KN_<R> & u)  
+        { KN_<R>::operator*=(u);return *this;}
+   KN& operator *=(const Divc_KN_<R> & u)
+    { KN_<R>::operator*=(u);return *this;}
+   KN& operator *=(const Add_Mulc_KN_<R> & u)
+        { KN_<R>::operator*=(u);return *this;}
+   KN& operator *=(const if_arth_KN_<R> & u)  
+        { KN_<R>::operator*=(u);return *this;}
+   KN& operator *=(const Mul_KNM_KN_<R> & u) 
+        { KN_<R>::operator*=(u);return *this;}
+        
+  
+  template<class I,class T> KN& operator =   (const KN_ITAB<T ,I> & ui)
+     {  KN_<R>::operator =(ui);  return *this;}
+  template<class I,class T> KN& operator +=   (const KN_ITAB<T ,I> & ui)
+     {  KN_<R>::operator +=(ui);  return *this;}
+  template<class I,class T> KN& operator -=   (const KN_ITAB<T ,I> & ui)
+     {  KN_<R>::operator -=(ui);  return *this;}
+  template<class I,class T> KN& operator *=   (const KN_ITAB<T ,I> & ui)
+     {  KN_<R>::operator *=(ui);  return *this;}
+  template<class I,class T> KN& operator /=   (const KN_ITAB<T ,I> & ui)
+     {  KN_<R>::operator /=(ui);  return *this;}
+        
+        
+  //  two opertor to cast to an array of constant      
+//    operator KN_<const_R> & ()  
+//          { return *  (KN_<const_R>*) this;}
+//    operator KN_<const_R> const & ()  const 
+//          { return *(const KN_<const_R>*) this;}
+//    operator KN<const_R> & () 
+//          { return   (KN<const_R> &) *this;}
+//    operator KN<const_R> const & ()  const 
+//          { return (const KN<const_R>& ) *this;}
+    static void fill0(R *v,int n) { if(n && v) for(int i=0;i<n;++i) v[i]=R();} 
+    void init(long nn) {this->n=nn;this->step=1;this->next=-1;this->v=new R[nn];fill0(this->v,this->n) ;}
+  void init() {this->n=0;this->step=1;this->next=-1;this->v=0;}
+  void init(const KN_<R> & a){init(a.N()); operator=(a);}
+  void resize(long nn) {
+    if ( nn != this->n) 
+     {
+       R *vo=this->v;
+       long no=std::min(this->n,nn), so=this->step;
+       ShapeOfArray::init(nn);
+       this->v=new R[this->n];
+       // copy
+       if(this->v && vo) 
+         for(long i=0,j=0;j<no;i++,j+=so) 
+           this->v[i]=vo[j]; 
+        delete [] vo;} }//  mars 2010
+  void destroy(){/*assert(this->next<0);*/  if(this->next++ ==-1) {delete [] this->v; this->v=0;this->n=0;}}//  mars 2010
+  void increment() {/*assert(this->next<0);*/  this->next--;}
+};
+
+//  Array with 2 indices
+//  ---------------------
+
+template<class R>
+class KNM: public KNM_<R>{ public:
+  KNM() :KNM_<R>(0,0,0){}
+  KNM(long nn,long mm) 
+        :KNM_<R>(new R[nn*mm],nn,mm){}
+   KNM(const KNM<R> & u)  // PB si stepi ou stepj nulle
+        :KNM_<R>(new R[u.size()],u.N(),u.M()) 
+       { KN_<R>::operator=(u);}
+  explicit KNM(const KNM_<R> & u)
+        :KNM_<R>(new R[u.size()],u.N(),u.M()) 
+        { KNM_<R>::operator=(u);}
+        
+  ~KNM(){delete [] this->v;}
+  
+   KNM& operator=(const KNM_<const_R> & u)   
+    { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator=(u);return *this;}
+   KNM& operator=(const_R a)                 
+    { if(this->unset()) RNM_FATAL_ERROR(" KNM operator=(double)"); KNM_<R>::operator=(a);return *this;}
+   KNM& operator+=(const_R  a)               
+        { if(this->unset()) RNM_FATAL_ERROR(" KNM operator+=(double)"); KNM_<R>::operator+=(a);return *this;}
+   KNM& operator-=(const_R  a)               
+        {if(this->unset()) RNM_FATAL_ERROR(" KNM operator-=(double)"); KNM_<R>::operator-=(a);return *this;}
+   KNM& operator/=(const_R  a)               
+        {if(this->unset()) RNM_FATAL_ERROR(" KNM operator/=(double)"); KNM_<R>::operator/=(a);return *this;}
+   KNM& operator*=(const_R  a)               
+        {if(this->unset()) RNM_FATAL_ERROR(" KNM operator*=(double)"); KNM_<R>::operator*=(a);return *this;}
+   KNM& operator+=(const KNM_<const_R> & u)  
+        { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator+=(u);return *this;}
+   KNM& operator-=(const KNM_<const_R> & u)  
+        {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator-=(u);return *this;}
+
+   KNM& operator/=(const KNM_<const_R> & u)  
+        {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator/=(u);return *this;}
+   KNM& operator*=(const KNM_<const_R> & u)  
+        { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator*=(u);return *this;}
+
+
+   KNM &operator  =(const outProduct_KN_<R> & u)
+        { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator =(u);return *this;}
+   KNM &operator +=(const outProduct_KN_<R> & u)
+        { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator+=(u);return *this;}
+   KNM &operator -=(const outProduct_KN_<R> & u)
+        { if(this->unset()) this->init(u.N(),u.M()) ; KNM_<R>::operator-=(u);return *this;}
+   KNM &operator /=(const outProduct_KN_<R> & u) 
+        {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator/=(u);return *this;}
+   KNM &operator *=(const outProduct_KN_<R> & u)
+        {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator*=(u);return *this;}
+ 
+    
+    KNM &operator  =(const ConjKNM_<R> &u)  {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator=(u);return *this;}
+    KNM &operator +=(const ConjKNM_<R> &u)  {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator+=(u);return *this;}
+    KNM &operator -=(const ConjKNM_<R> &u)  {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator-=(u);return *this;}
+    KNM &operator /=(const ConjKNM_<R> &u)  {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator/=(u);return *this;}
+    KNM &operator *=(const ConjKNM_<R> &u)  {  if(this->unset()) this->init(u.N(),u.M()) ;KNM_<R>::operator*=(u);return *this;}
+ // bofbof
+
+        
+  //  two opertors to cast to un array of constant        
+//    operator KNM_<const_R> & ()  
+//          { return *  (KNM_<const_R>*) this;}
+//    operator KNM_<const_R> const & ()  const 
+//          { return *(const KNM_<const_R>*) this;}
+
+//    operator KNM<const_R> & ()  
+//          { return *  (KNM<const_R>*) this;}
+//    operator KNM<const_R> const & ()  const 
+//          { return *(const KNM<const_R>*) this;}
+ 
+    void init() { //  add mars 2010 ...
+	this->n=0;this->step=1;this->next=-1;this->v=0;
+	this->shapei.init(0);
+	this->shapej.init(0);}
+    
+  void init(long nn,long mm) {
+    ShapeOfArray::init(nn*mm);
+    this->shapei.init(nn,1,nn);
+    this->shapej.init(mm,nn,1),
+    this->v=new R[nn*mm];}
+    
+  void resize(long nn,long mm) {     
+    long kk=nn*mm;
+      
+    long lso = this->size();
+    long n = this->shapei.n;
+    long m = this->shapej.n;
+    
+    if( (n !=nn) || ( m != mm))  // correct FH Jav 2012 ..
+     {
+       KNM_ <R> old(*this); 
+       long no=std::min(n,nn);
+       long mo=std::min(m,mm);
+       R *vo=this->v;
+       
+       // new mat 
+       ShapeOfArray::init(kk);
+       this->v=new R[this->n];
+       this->shapei.init(nn,1,nn);
+       this->shapej.init(mm,nn,1);
+       
+       if(this->v && vo)  // copy
+	 (*this)(SubArray(no),SubArray(mo)) = old(SubArray(no),SubArray(mo));
+       
+       delete []vo;
+     }
+    
+  }
+  void destroy(){assert(this->next<0);  if(this->next++ ==-1) {delete [] this->v; this->v=0;this->n=0;}} 
+  void increment() {assert(this->next<0);  this->next--;}
+    
+//  void destroy(){delete [] this->v;this->n=0 ;}
+
+};
+
+//  Array with 3 indices
+//  ---------------------
+template<class R>
+class KNMK: public KNMK_<R>{ public:
+
+  KNMK(long n,long m,long k) 
+     :KNMK_<R>(new R[n*m*k],n,m,k){}
+  explicit KNMK(const KNMK_<R> & u)
+     :KNMK_<R>(new R[u.size()],u.N(),u.M(),u.K()) 
+     { KNMK_<R>::operator=(u);}
+   KNMK(const KNMK<R> & u)
+     :KNMK_<R>(new R[u.size()],u.N(),u.M(),u.K()) 
+     { KNMK_<R>::operator=(u);}
+     
+  ~KNMK(){delete [] this->v;}
+  
+  KNMK& operator=(const KNMK_<const_R> & u)   
+     { KNMK_<R>::operator=(u);return *this;}
+  KNMK& operator=(const_R a)                  
+     { KNMK_<R>::operator=(a);return *this;}
+  KNMK& operator+=(const_R  a)                
+     { KNMK_<R>::operator+=(a);return *this;}
+  KNMK& operator-=(const_R  a)                
+     { KNMK_<R>::operator-=(a);return *this;}
+  KNMK& operator/=(const_R  a)                
+     { KNMK_<R>::operator/=(a);return *this;}
+  KNMK& operator*=(const_R  a)                
+     { KNMK_<R>::operator*=(a);return *this;}
+  KNMK& operator+=(const KNMK_<const_R> & u)  
+     { KNMK_<R>::operator+=(u);return *this;}
+  // ici jd 
+  KNMK& operator-=(const KNMK_<const_R> & u)  
+     { KNMK_<R>::operator-=(u);return *this;}
+  KNMK& operator*=(const KNMK_<const_R> & u)   
+     { KNMK_<R>::operator*=(u);return *this;}
+  KNMK& operator/=(const KNMK_<const_R> & u)   
+     { KNMK_<R>::operator/=(u);return *this;}
+     
+//  two opertor to cast to un array of constant          
+//    operator KNMK_<const_R> & ()  
+//       { return *  (KNMK_<const_R>*) this;}
+//    operator KNMK_<const_R> const & ()  const 
+//       { return *(const KNMK_<const_R>*) this;}  
+
+//    operator KNMK<const_R> & ()  
+//       { return *  (KNMK<const_R>*) this;}
+//    operator KNMK<const_R> const & ()  const 
+//       { return *(const KNMK<const_R>*) this;}  
+};
+
+//  -------------  optimization ---------------------
+template<class R> 
+class conj_KN_{public:
+  const KN_<const_R> & a;
+  conj_KN_(const KN_<const_R> & aa) : a(aa){}
+};
+
+
+inline const KN_<long> conj(const KN_<long> &a){ return a;}
+inline const KN_<double> conj(const KN_<double> &a){ return a;}
+inline const KN_<float> conj(const KN_<float> &a){ return a;}
+
+//template<class R> conj_KN_<R> conj(const KN<R> &a){ return a;}
+template<class R> conj_KN_<R> conj(const KN_<R> &a){ return a;}
+
+template<class R> 
+class DotStar_KN_{public: 
+  const KN_<const_R>  a; const KN_<const_R>  b;
+  DotStar_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) : a(aa),b(bb)  {}
+ }; 
+
+ 
+template<class R> 
+class DotSlash_KN_{public: 
+  const KN_<const_R>  a; const KN_<const_R>  b;
+  DotSlash_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) : a(aa),b(bb)  {}
+ }; 
+
+template<class R> 
+class Add_KN_{public: 
+  const KN_<const_R>  a; const KN_<const_R>  b;
+  Add_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) 
+     : a(aa),b(bb)  { K_throwassert(SameShape(a,b));}
+ };  
+ 
+template<class R> 
+class Sub_KN_{public: 
+  const KN_<const_R>  a; const KN_<const_R>  b;
+  Sub_KN_(const KN_<const_R> & aa,const KN_<const_R> & bb) 
+    : a(aa),b(bb) { K_throwassert(SameShape(a,b));}
+ };
+ 
+template<class R> 
+class Mulc_KN_ { public: 
+  const KN_<const_R>  a;  const_R  b;
+  Mulc_KN_(const KN_<const_R> & aa,const_R  bb) : a(aa),b(bb) {}
+  Mulc_KN_(const Mulc_KN_<R> & aa,const_R  bb) : a(aa.a),b(aa.b*bb) {}
+  Mulc_KN_ operator-() const {return Mulc_KN_(a,-b);}
+  outProduct_KN_<R> operator*(const  TKN_<double> & bb)
+{  return outProduct_KN_<R>(a,bb,b);} 
+
+ };  
+template<class R>
+class Divc_KN_ {
+    // // vector b/a_i ..
+public:
+    const KN_<const_R>  a;  const_R  b;
+    Divc_KN_(const_R  bb,const KN_<const_R> & aa) : a(aa),b(bb) {}
+  //  Divc_KN_(const Divc_KN_<R> & aa,const_R  bb) : a(aa.a),b(aa.b*bb) {}
+    Divc_KN_ operator-() const {return Divc_KN_(a,-b);}
+};  
+
+template<class R> 
+class Add_Mulc_KN_ { public:
+  const KN_<const_R> a,b;
+  const R ca,cb; 
+  Add_Mulc_KN_(const Mulc_KN_<R> & aa,const Mulc_KN_<R> & bb)  
+        : a(aa.a),b(bb.a),ca(aa.b),cb(bb.b) { K_throwassert(SameShape(a,b));}
+  Add_Mulc_KN_(const Mulc_KN_<R> & aa,const KN_<const_R> & bb,const R cbb) 
+        : a(aa.a),b(bb),ca(aa.b),cb(cbb)  { K_throwassert(SameShape(a,b));}
+  Add_Mulc_KN_(const KN_<const_R> & aa,const R caa,const KN_<const_R> & bb,const R cbb) 
+        : a(aa),b(bb),ca(caa),cb(cbb) { K_throwassert(SameShape(a,b));}
+ };  
+
+template<class R> 
+class if_arth_KN_ { public:
+  const KN_<const_R> a,b,c;
+  if_arth_KN_(const KN_<R> & aa,const KN_<R> & bb,const KN_<R> & cc)  
+        : a(aa),b(bb),c(cc){ K_throwassert(SameShape(a,b)&&SameShape(a,c));}
+ };  
+
+
+
+template<class R> 
+class Mul_KNM_KN_ { public:
+  const KNM_<const_R> &A;
+  const KN_<const_R> &b;
+  Mul_KNM_KN_(const  KNM_<const_R>  &aa,const KN_<const_R>  &bb)  
+        : A(aa),b(bb) {K_throwassert(SameShape(A.shapej,b));} 
+};
+
+
+ostream & operator<<(ostream & f,const ShapeOfArray & s);
+
+template<class R> ostream & operator<<(ostream & f,const KN_<const_R>   & v);
+template<class R> ostream & operator<<(ostream & f,const KNM_<const_R>  & v);
+template<class R> ostream & operator<<(ostream & f,const KNMK_<const_R> & v);
+template<class R> inline ostream & operator<<(ostream & f,const KN<const_R>   & v) 
+    { return f << (const KN_<const_R> &) v;}
+template<class R> inline ostream & operator<<(ostream & f,const KNM<const_R>  & v) 
+    { return f << (const KNM_<const_R> &) v;}
+template<class R> inline ostream & operator<<(ostream & f,const KNMK<const_R> & v) 
+    { return f << (const KNMK_<const_R> &) v;}
+
+
+template<class R> inline Add_KN_<R> operator+(const KN_<const_R> &a,const KN_<const_R> &b) 
+    { return Add_KN_<R>(a,b);}
+template<class R> inline Sub_KN_<R> operator-(const KN_<const_R> &a,const KN_<const_R> &b) 
+    { return Sub_KN_<R>(a,b);}
+template<class R> inline Mulc_KN_<R> operator*(const KN_<const_R> &a,const R &b) 
+    { return Mulc_KN_<R>(a,b);}
+template<class R> inline Mulc_KN_<R> operator/(const KN_<const_R> &a,const R &b) 
+    { return Mulc_KN_<R>(a,R(1)/b);}
+template<class R> inline Mulc_KN_<R> operator*(const R &b,const KN_<const_R> &a) 
+    { return Mulc_KN_<R>(a,b);}
+template<class R> inline Divc_KN_<R> operator/(const R &b,const KN_<const_R> &a)
+{ return Divc_KN_<R>(b,a);}
+template<class R> inline Mulc_KN_<R> operator-(const KN_<const_R> &a)
+    { return Mulc_KN_<R>(a,R(-1));}
+
+
+
+template<class R> inline Add_Mulc_KN_<R> operator+(const  Mulc_KN_<R>& a,const Mulc_KN_<R> &b) 
+    { return Add_Mulc_KN_<R>(a,b);}
+template<class R> inline Add_Mulc_KN_<R> operator-(const  Mulc_KN_<R>& a,const Mulc_KN_<R> &b) 
+    { return Add_Mulc_KN_<R>(a,b.a,-b.b);}
+
+template<class R> inline Add_Mulc_KN_<R> operator+(const  Mulc_KN_<R>& a,const KN_<const_R> &b) 
+   { return Add_Mulc_KN_<R>(a,b,R(1));}
+template<class R> inline Add_Mulc_KN_<R> operator-(const  Mulc_KN_<R>& a,const KN_<const_R> &b) 
+   { return Add_Mulc_KN_<R>(a,b,R(-1));}
+
+template<class R> inline Add_Mulc_KN_<R> operator+(const KN_<const_R> & b,const  Mulc_KN_<R>& a) 
+   { return Add_Mulc_KN_<R>(a,b,R(1));}
+
+// modif FH mars 2007 
+template<class R> inline Add_Mulc_KN_<R> operator-(const KN_<const_R> & a,const  Mulc_KN_<R>& b) 
+   { return Add_Mulc_KN_<R>(a,R(1),b.a,-b.b);}// modif FH mars 2007  
+
+template<class R> inline Mul_KNM_KN_<R> operator*(const  KNM_<const_R> & A,const  KN_<const_R> & b) 
+    { return Mul_KNM_KN_<R>(A,b);}
+
+
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const Add_Mulc_KN_<R> & b) 
+           { return SameShape(a,b.a) ;} 
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const if_arth_KN_<R> & b) 
+           { return SameShape(a,b.a) ;} 
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const Add_KN_<R> & b) 
+           { return SameShape(a,b.a) ;} 
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const Sub_KN_<R> & b) 
+           { return SameShape(a,b.a) ;} 
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const Mulc_KN_<R> & b) 
+           { return SameShape(a,b.a) ;}
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const Divc_KN_<R> & b)
+{ return SameShape(a,b.a) ;}
+
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const DotStar_KN_<R> & b)
+           { return SameShape(a,b.a) ;} 
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const DotSlash_KN_<R> & b) 
+           { return SameShape(a,b.a) ;} 
+template<class R> inline bool  SameShape(const ShapeOfArray & a,const Mul_KNM_KN_<R> & b) 
+           { return a.n==b.A.N() ;} 
+ inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<double>::plusAx & ) 
+           { return true ;} //  pas de test car la matrice peut etre rectangulaire
+ inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<double>::plusAtx & ) 
+           { return true ;} //  pas de test car la matrice peut etre rectangulaire
+ inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<complex<double> >::plusAx & ) 
+           { return true ;} //  pas de test car la matrice peut etre rectangulaire
+ inline bool  SameShape(const ShapeOfArray & ,const VirtualMatrice<complex<double> >::plusAtx & ) 
+           { return true ;} //  pas de test car la matrice peut etre rectangulaire
+
+ inline bool  SameShape(const ShapeOfArray & ,const double) 
+           { return true;} 
+ inline bool  SameShape(const ShapeOfArray & ,const complex<double>) 
+           { return true;} 
+ inline bool  SameShape(const ShapeOfArray & ,const complex<float>) 
+           { return true;}            
+
+template<class R>
+ inline bool SameShape(KNM<R>& m, const outProduct_KN_<R>& p)
+ { return p.a.N()>=m.N() && m.M()>=p.b.N(); } 
+
+template<class R> inline long SameAdress(const KN_<R> &a, const KN_<R> &b) { return &a[0]==&b[0];}
+// bof -bof 
+//template<class R> inline
+//  KN_<R>::operator KN<R> &() { return *(KN<R> *) (void *) this;}
+//template<class R> inline
+//  KN_<R>::operator const KN<R> &() const { return *(const KN<R> *) ( const void *) this;}
+
+//  operateur y=Ax-b ou y=Ax + b pour le GC
+template<class R> 
+   PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >  operator-(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B)  
+    { return PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >(A,Mulc_KN_<R>(B,R(-1.)));}
+
+template<class R> 
+   PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >  operator+(const typename VirtualMatrice<R>::plusAx & A,const KN_<R> & B)  
+    { return PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >(A,B);}
+
+template<class R> 
+   PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >  operator-(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B)  
+    { return PplusQ< typename VirtualMatrice<R>::plusAx, Mulc_KN_<R> >(A,Mulc_KN_<R>(B,R(-1.)));}
+
+template<class R> 
+   PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >  operator+(const typename VirtualMatrice<R>::plusAx & A,const KN<R> & B)  
+    { return PplusQ< typename VirtualMatrice<R>::plusAx, KN_<R> >(A,B);}
+    
+
+template<class R>
+KN_<R> diagonal(const KNM<R> & A) { 
+  K_throwassert(A.N() == A.M()); 
+  return KN_<R>(A,SubArray(A.N(),0,A.N()+1));}
+
+// to def  inv permutation FH mars 2006 
+class Inv_KN_long{ public:
+  KN_<long>  t;
+  Inv_KN_long(const KN_<long> & v)
+   : t(v) {}
+  Inv_KN_long( KN_<long> const  * & v)
+   : t(*v) {}
+  operator const KN_<long> & () const {return t;}
+};
+
+// For  sparce solve to set array to be consecutif (step==1) if neccessarly 
+template<class R>
+class KN_2Ptr { public:
+    // transfo de KN_ peut etre non concecutif (a.step != 1) en 
+    // un tableau concecutif en memoire si necessaire 
+    //  avec recopie du tableau dans le tableau d'origne a la destruction. 
+    KN_<R>   a;
+    const KN_<R>   ca;
+    KN<R> c; // tableau copie si non vide  
+    KN_2Ptr(KN_<R> & vv) : a(vv),ca(vv),c() { assert(a.N()); if (ca.step !=1 ) c=ca;} // copy if non consecutif
+    KN_2Ptr(const KN_<R> & vv) : a(0,0),ca(vv),c() { assert(ca.N()); if (ca.step !=1 ) c=ca; }// copy if non consecutif
+    operator R *() { return c.unset() ? (R *) ca:(R *) c ;}
+    operator const R *() const  { return c.unset() ? (R *) ca:(R *) c ;}
+    ~KN_2Ptr() { if(!a.unset() && !c.unset() ) {a=c; } } // recopy 	
+}; 
+
+template<class R,typename A,typename B=R> class  F_KN_ 
+{ 
+  public: 
+  A (*f)(B);
+  KN_<R> a;
+  long N() const {return a.N();}
+  F_KN_( A (*ff)(B),const KN_<R> & aa): f(ff),a(aa) {}
+  A operator[](long i) const { return f(a[i]);}
+  bool check(long n)  const { return  n <= a.N() || a.constant(); }
+  bool constant() const {return a.constant();}
+}; 
+
+template<class R,typename A,typename B>
+inline bool  SameShape(const ShapeOfArray & a,const F_KN_<R,A,B>  & b) 
+           { return  !a.step || b.constant()  || a.n == b.N() ;} 
+           
+#include "RNM_tpl.hpp"
+#ifdef K_throwassert
+#undef K_throwassert
+#endif
+#endif
diff --git a/src/femlib/RNM_op.hpp b/src/femlib/RNM_op.hpp
new file mode 100644
index 0000000..fcfbedc
--- /dev/null
+++ b/src/femlib/RNM_op.hpp
@@ -0,0 +1,175 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:    29 fev 2000  
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : array modelisation 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ 
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ 
+ */
+
+template<class R>  
+KNM_<R> & KNM_<R>::operator oper (const outProduct_KN_<R> & u)  
+{
+  //   *this  oper  A* t B 
+    K_throwassert (shapei.SameShape(u.a) && shapej.SameShape(u.b) );
+    long n= N(), m= M();
+    
+    R * ai(u.a),cc, c= u.c;
+    long stepi=u.a.step;
+    R * bj, *bb(u.b);
+    long stepj=u.b.step;
+    KN_<const_R>  li((*this)(0,'.')); //  first line
+    int stepij= li.step;
+    for (long i=0;i<n;i++,ai += stepi,++li)
+      {
+        cc= c * *ai;
+        R * mij = li;
+        bj = bb;
+        for (long j=0;   j<m; j++, bj += stepj, mij += stepij )         
+          *mij oper cc * RNM::conj(*bj) ; 
+       }
+    return *this;
+ }
+template<class R>  
+KNM_<R> & KNM_<R>::operator oper (const ConjKNM_<R> & u)  
+{
+    K_throwassert( N() == u.N() && M() == u.M() ); 
+  for(int i=0;i<N();++i)
+    for(int j=0;j<M();++j)
+        KNM_<R>::operator () (i,j) oper RNM::conj( u(i,j));
+    return *this;
+}
+
+
+template<class R>
+template<class  A,class B,class C>
+ KN_<R>& KN_<R>::operator oper (const F_KN_<A,B,C> & u)  {
+    K_throwassert ( u.check(this->N()) );
+    R * l(v);  //  first line   
+    for (long i=0;i<n;i++,l += step)  
+      *l oper  u[i]; 
+    return *this;}
+
+template<class R>
+KN_<R>& KN_<R>::operator oper (const SetArray<R> & u)  {
+    R * l(v);  //  first line   
+    for (long i=0;i<n;i++,l += step)  
+	*l oper  u[i]; 
+return *this;}
+
+
+
+template<class R>
+ KN_<R>& KN_<R>::operator oper (const Mul_KNM_KN_<R> & u)  {
+    K_throwassert (SameShape(u.A.shapei) && !constant());
+    R * l(v); KN_<const_R>  li(u.A(0,'.')); //  first line   
+    for (long i=0;i<n;i++,l += step,++li)  
+      *l oper (li,u.b); 
+    return *this;}
+
+
+template<class R>
+ KN_<R>&  KN_<R>::operator oper (const DotStar_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    long stepa(u.a.step),stepb(u.b.step);
+    R * l(v); const_R  *aa(u.a), *bb(u.b);    
+    for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb)
+      *l oper *aa * *bb;
+    return *this;
+  }
+template<class R>
+ KN_<R>&  KN_<R>::operator oper (const DotSlash_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    long stepa(u.a.step),stepb(u.b.step);
+    R * l(v); const_R  *aa(u.a), *bb(u.b);    
+    for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb)
+      *l oper *aa / *bb;
+    return *this;
+  }
+
+  
+template<class R>
+ KN_<R>&  KN_<R>::operator oper (const Add_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    long stepa(u.a.step),stepb(u.b.step);
+    R * l(v); const_R  *aa(u.a), *bb(u.b);    
+    for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb)
+      *l oper *aa+*bb;
+    return *this;
+  }
+
+template<class R>
+ KN_<R>&  KN_<R>::operator oper (const Sub_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    long stepa(u.a.step),stepb(u.b.step);
+    R * l(v); const_R  *aa(u.a), *bb(u.b);    
+    for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb)
+      *l oper  *aa-*bb;
+    return *this;
+  }
+  
+template<class R>
+ KN_<R>&  KN_<R>::operator oper (const Mulc_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    long stepa(u.a.step);
+    R * l(v); const_R  *aa(u.a),bb(u.b)  ;
+    for (long i=0;i<n;i++,l += step, aa +=stepa)
+      *l oper *aa * bb;
+    return *this;
+  }
+template<class R>
+KN_<R>&  KN_<R>::operator oper (const Divc_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    long stepa(u.a.step);
+    R * l(v); const_R  *aa(u.a),bb(u.b)  ;
+    for (long i=0;i<n;i++,l += step, aa +=stepa)
+        *l oper bb / *aa ;
+    return *this;
+}
+
+template<class R>
+ KN_<R>&  KN_<R>::operator oper (const Add_Mulc_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    const long stepa(u.a.step),stepb(u.b.step);
+    const R ca(u.ca),cb(u.cb);    
+    R * l(v);
+    const R *aa(u.a),*bb(u.b);    
+    for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb)
+      *l oper *aa*ca + *bb*cb;
+    return *this;
+  }
+
+template<class R>
+ KN_<R>&  KN_<R>::operator oper (const if_arth_KN_<R> & u) {
+    K_throwassert(u.a.N() == N()  );
+    R zero=R();
+    const long stepa(u.a.step),stepb(u.b.step),stepc(u.c.step);
+    R * l(v);
+    const R *aa(u.a),*bb(u.b),*cc(u.c);    
+    for (long i=0;i<n;i++,l += step, aa +=stepa, bb += stepb ,  cc += stepc)
+      *l oper ( (*aa != zero) ?  *bb : *cc);
+    return *this;
+  }
diff --git a/src/femlib/RNM_opc.hpp b/src/femlib/RNM_opc.hpp
new file mode 100644
index 0000000..942072a
--- /dev/null
+++ b/src/femlib/RNM_opc.hpp
@@ -0,0 +1,111 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:    29 fev 2000  
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : array modelisation 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ 
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ 
+ */
+
+template<class R>
+inline KN_<R>&  KN_<R>::operator oper (const_R a)  {
+    R * l(v);    
+    for (long i=0;i<n;i++,l += step) 
+      *l oper a;
+    return *this;
+  }
+    
+template<class R> 
+inline    KNM_<R> & KNM_<R>::operator oper (const_R a)    
+{ 
+  if(IsVector1() ) 
+        KN_<R>::operator oper (a);
+  else {  
+          KN_<R>  lj(operator()('.',0)); //  (.,.,O)
+          for (long  j=0;j<M();++j,++lj) 
+             lj oper a;}       
+  return *this;
+}
+
+template<class R> 
+inline    KNMK_<R> & KNMK_<R>::operator oper (const_R a)    
+{ 
+  if(IsVector1() ) 
+        KN_<R>::operator oper (a);
+  else {  
+          KNM_<R>  lj(operator()('.','.',0)); //  (.,.,O)
+          long j=K();
+           while(j--)
+            {lj oper a;++lj;}
+       }
+  return *this;
+}
+
+template<class R>
+inline KN_<R>&  KN_<R>::operator oper (const KN_<const_R> & u)   {
+    K_throwassert(u.n == n);
+    R * l(v);
+    const R *r(u);    
+    for (long i=0;i<n;i++,l += step, r += u.step) *l oper *r;
+    return *this;
+  }
+  
+template<class R> 
+inline    KNM_<R> & KNM_<R>::operator oper (const KNM_<const_R> & u)    
+{ 
+  K_throwassert( N() == u.N() && M() == u.M() );   
+  if(IsVector1() && u.IsVector1() && shapei.step == u.shapei.step ) // modif 2011 (thank to Oka) 
+        KN_<R>::operator oper(u); // modif FH jan 2004
+  else {  
+          KN_<R>  lj(operator()('.',0)); //  (.,O)
+          KN_<const_R>  uj(u('.',0));
+          long  j=M();
+          while ( j--)
+            { lj oper uj;++lj;++uj;} 
+        }      
+  return *this;
+}
+
+
+template<class R> 
+inline  KNMK_<R> & KNMK_<R>::operator oper (const KNMK_<const_R> & u)    
+{ 
+  K_throwassert( N() == u.N() && M() == u.M() &&   K() == u.K() ); 
+
+  if(IsVector1() && u.IsVector1() && u.N() == N() &&  shapei.step == u.shapei.step) // modif 2011 (thank to Oka) 
+        KN_<R>::operator oper(u); // modif FH 2004
+  else {  
+          K_throwassert( K() == u.K());
+          KNM_<R>  lj(operator()('.','.',0)); //  (.,O)
+          KNM_<const_R>  uj(u('.','.',0));
+          long j=K();
+          while (j--)
+           { lj oper uj;++lj;++uj;}
+       }
+  return *this;
+}
+
+#undef oper
diff --git a/src/femlib/RNM_tpl.hpp b/src/femlib/RNM_tpl.hpp
new file mode 100644
index 0000000..f957609
--- /dev/null
+++ b/src/femlib/RNM_tpl.hpp
@@ -0,0 +1,344 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:    29 fev 2000  
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : array modelisation 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ 
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ 
+ */
+
+#ifndef  RNM_tpl_
+#define  RNM_tpl_
+
+#include "RNM.hpp"
+
+//   version du 22 nov 1999
+//   Voila une debut de class vecteur + matrice 
+//   les class avec termine avec un _ ne travail que sur 
+//   un pointeur existant => pas de new et delete de pointeur
+//   la class correspondant sans de _ genere les pointeurs
+//  
+//   avec ses classes on peut prendre une ligne 
+//   ou une colonne d'une matrice
+// -----------------------
+
+namespace RNM  {
+
+template <class T> inline double norm(const T & x){return std::norm(x);}
+inline double norm(double x){return x*x;} 
+inline double norm(float x){return x*x;}
+inline long norm(long x){return x*x;}
+inline int norm(int x){return x*x;}
+
+}
+
+template<class R>
+void MatMul(KNM_<R> & ab, KNM_<R> &  a, KNM_<R> & b){
+  // attention ne marche que si les adresses ne sont pas les memes
+  long N= a.shapei.n;
+  long M= a.shapej.n;
+  K_throwassert(a.shapej.n == a.shapei.n);
+  K_throwassert(a.shapei.n == ab.shapei.n);
+  K_throwassert(b.shapej.n == ab.shapej.n);
+  K_throwassert(b.v != ab.v);
+  K_throwassert(a.v != ab.v);
+  KN_<R> ai =a(0);
+  for(long i=0;i<N;i++,++ai){
+    KN_<R> bj=b[0];
+    for(long j=0;j<M;j++,++bj)
+      ab(i,j) = (ai , bj)  ;}
+}
+
+
+
+inline ostream & operator<<(ostream & f,const ShapeOfArray & s)
+  { f << s.n ; 
+     const int i10=10; 
+     int prec=f.precision();
+     if(prec<i10) f.precision(i10);
+     if(s.step != 1)
+       f << ":" << s.step ;
+     if (s.step*s.n  !=  s.next ) 
+       f << " n: " << setw(3) << s.next ;
+     f << ",";
+     if(prec<i10) f.precision(prec);
+     return f;
+  };
+
+
+template<class R> ostream & operator<<(ostream & f,const KN_<const_R> & v)
+  { //f <<  " KN_ : " << (ShapeOfArray) v << " "   <<  (const_R *) v << " :\n\t"  ;
+    f << v.N() << "\t\n\t" ; 
+    const int i10=10; 
+    int prec=f.precision();
+    if(prec<i10) f.precision(i10);    
+    for (long i=0;i<v.N();i++)
+      f   << setw(3) << v[i] << ((i % 5) == 4 ? "\n\t" : "\t");
+    if(prec<i10) f.precision(prec); 
+    return f;
+  };
+
+template<class R> istream & operator>>(istream & f, KN_<R> & v)
+ {
+     int n;char c;
+     f >> n;
+     ffassert(f.good());
+     ffassert(n==v.N());
+     while (f.get(c) &&  (c!='\n' && c!='\r' ) ) ; // eat until control (new line
+
+     for (int i=0;i<n;i++)
+      {  f >> v[i] ;
+       ffassert(f.good());} // modif FH  main 2006
+     return f;
+}
+
+template<class R> istream & operator>>(istream & f, KN<R> & v)
+ {
+     int n;char c;
+     f >> n;
+     if (v.unset()) v.init(n);
+     cout << n << " == " << v.N() << endl;
+     ffassert(n==v.N());
+     while (f.get(c) &&  (c!='\n' && c!='\r' ) ) ; // eat until control (new line
+
+     for (int i=0;i<n;i++)
+       {
+       f >> v[i] ;
+       ffassert(f.good());}// modif FH  main 2006
+     return f;
+}
+
+
+template<class R> ostream & operator<<(ostream & f,const KNM_<const_R> & v)
+  {  //f << " KNM_ "<<v.N()<<"x"<<v.M()<< ": " << (ShapeOfArray) v  
+     //<< " i "  << v.shapei
+     // << " j "  << v.shapej
+     // << " " << &v(0,0) << " :\n\t";
+    const int i10=10; 
+    int prec=f.precision();
+    if(prec<i10) f.precision(i10);    
+     f << v.N()<<' '<<v.M() /*<< "  n" << v.next<<" :"<< v.shapei.next << "," << v.shapej.next */<< "\t\n\t" ;
+    for (long i=0;i<v.N();i++) {
+      for (long j=0;j<v.M();j++) 
+        f << " " << setw(3) << v(i,j);
+       f << "\n\t";}
+    if(prec<i10) f.precision(prec);
+  return f;
+    
+   };
+
+template<class R> ostream & operator<<(ostream & f,const KNMK_<const_R> & v)
+  { //f << " KNM_" <<v.N()<<"x"<<v.M()<<"x"<<v.K()<< " : " << (ShapeOfArray) v  
+    // << " i "  << v.shapei
+    // << " j "  << v.shapej
+    // << " k "  << v.shapek << endl;
+    // << " " << (void *) & v(0,0,0) << "\n\t" ;
+    f << v.N()<< 'x' <<v.M()<< 'x'<<v.K() << "\t:\n\t" ;    
+    const int i10=10; 
+    int prec=f.precision();
+    if(prec<i10) f.precision(i10);    
+    for (long i=0;i<v.shapei.n;i++){
+      for (long j=0;j<v.shapej.n;j++){
+	for (long k=0;k<v.shapek.n;k++)
+	  f << " " << setw(3) << v(i,j,k);
+	f << "\n\t";}
+      f << "\n\t";}
+    if(prec<i10) f.precision(prec);
+    return f;
+    
+  };
+
+template<class R>
+ R  KN_<R>::operator,(const KN_<const_R> & u) const {
+    K_throwassert(u.n == n);
+    R  s=0; 
+    R * l(v);
+    R  *r(u.v);    
+    for (long i=0;i<n;i++,l += step, r += u.step) s += *l * *r;
+    return s;
+  }
+
+template<class R>
+ R  operator,(const KN_<const_R> & u,const conj_KN_<const_R> & vc) {
+  int n=u.n;
+    K_throwassert(n == vc.a.n);
+    R  s=0; 
+    R * l(u);
+    R  *r(vc.a);
+    int stepl= u.step, stepr=vc.a.step;    
+    for (long i=0;i<n;i++,l += stepl, r += stepr) s += *l * RNM::conj(*r);
+    return s;
+  }
+
+template<class R>
+ R  operator,(const conj_KN_<const_R> & u,const KN_<const_R> & vc) {
+  int n=u.a.n;
+    K_throwassert(n == vc.n);
+    R  s=0; 
+    R * l(u.a);
+    R  *r(vc);
+    int stepl= u.a.step, stepr=vc.step;    
+    for (long i=0;i<n;i++,l += stepl, r += stepr) s += RNM::conj(*l) * (*r);
+    return s;
+  }
+
+template<class R>
+ R  operator,(const KN<const_R> & u,const conj_KN_<const_R> & vc) {  return ( (KN_<R>) u,vc);}
+template<class R>
+ R  operator,(const conj_KN_<const_R> & u,const KN<const_R> & vc) {  return (  u, (KN_<R>) vc);}
+
+
+template<class R>
+R  KN_<R>::min() const {
+    R minv = v[index(0)];
+    for (long i=1;i<n;i++)
+      minv = RNM::Min(minv, v[index(i)]) ;
+    return minv;
+  }
+template<class R>
+R  KN_<R>::max() const {
+    R maxv = v[index(0)];
+    for (long i=1;i<n;i++)
+      maxv = RNM::Max(maxv ,v[index(i)]);
+    return maxv;
+  }
+
+
+  
+template<class R>
+R  KN_<R>::sum() const {
+    R s = v[index(0)];
+    for (long i=1;i<n;i++)
+      s +=  v[index(i)];
+    //    cout << " sum = " << s << endl;
+    return s;
+  }
+
+template<class R>
+double  KN_<R>::norm() const {
+  double s = 0.;
+    for (long i=0;i<n;i++)
+      s +=  RNM::norm(v[index(i)]);
+    return s;
+  }
+
+template<class R>
+double  KN_<R>::l2() const {
+  double s = 0.;
+    for (long i=0;i<n;i++)
+      s +=  RNM::norm(v[index(i)]);
+    return sqrt(s);
+  }
+template<class R>
+double  KN_<R>::l1() const {
+  double s = 0.;
+    for (long i=0;i<n;i++)
+      s +=  std::abs(v[index(i)]);
+    return (s);
+  }
+template<class R>
+double  KN_<R>::linfty() const {
+  double s = 0.;
+    for (long i=0;i<n;i++)
+      s = std::max( (double) std::abs(v[index(i)]),s);
+    return (s);
+  }
+template<class R>
+double  KN_<R>::lp(double p) const {
+  if( p==1.) return l1();
+  else if (p==2.) return l2();
+  else if(p>1.e10) return linfty();
+  else
+  {
+  double s = 0.;
+    for (long i=0;i<n;i++)
+      s += pow(std::max( (double) std::abs(v[index(i)]),s),p);
+    return pow(s,1./p);
+   }
+  }
+
+template<class R> template<class T>
+long  KN_<R>::last(const T & a) const {
+    for (long i=n;i-- >0;)
+      if  (a(v[index(i)])) 
+        return i;
+    return -1;
+ }
+ 
+template<class R> template<class T>
+long  KN_<R>::first(const T & a) const {
+    for (long i=0;i<n;i++)
+      if  (a(v[index(i)])) return i;
+    return n;
+ }
+
+
+template<class R>
+ void  KN_<R>::map(R (*f)(R )) {
+    for (long i=0;i<n;i++)
+      {  R & x(v[index(i)]);
+          x =  f(x);}
+   
+  }
+
+template<class R>
+ void  KN_<R>::map(R (*f)(const R& )) {
+    for (long i=0;i<n;i++)
+      {  R & x(v[index(i)]);
+          x =  f(x);}
+   
+  }
+  
+template<class R>
+template<class T>
+ void  KN_<R>::set(R (*f)(const  T& ),KN_<T> & u)
+ { 
+   K_throwassert(N() == u.N());
+   for (long i=0;i<n;i++)
+      {  R & x(v[index(i)]);
+          v[index(i)]= f(u[i]);}
+ } 
+  
+
+
+///////////////// definition des operateurs d'affectation /////////////////////////
+#define oper =
+#include "RNM_op.hpp"
+#include "RNM_opc.hpp"
+#define oper +=
+#include "RNM_op.hpp"
+#include "RNM_opc.hpp"
+#define oper -=
+#include "RNM_op.hpp"
+#include "RNM_opc.hpp"
+#define oper *=
+#include "RNM_op.hpp"
+#include "RNM_opc.hpp"
+#define oper /=
+#include "RNM_op.hpp"
+#include "RNM_opc.hpp"
+
+#endif
diff --git a/src/femlib/RefCounter.hpp b/src/femlib/RefCounter.hpp
new file mode 100644
index 0000000..957e0cd
--- /dev/null
+++ b/src/femlib/RefCounter.hpp
@@ -0,0 +1,117 @@
+// ********** DO NOT REMOVE THIS BANNER **********
+// ORIG-DATE:    29 fev 2005  
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : array modelisation 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ 
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ 
+ */
+
+#ifndef REFCOUNTER_HPP
+#define REFCOUNTER_HPP
+
+#include "showverb.hpp" 
+#include "error.hpp" 
+
+class RefCounter; 
+class baseCountPointer;
+
+
+// ruse pour utiliser le prive c RefCounter de 
+//  pas de syntaxe pour des friends template 
+class baseCountPointer { protected:
+ void  add(const  RefCounter * c)  const; 
+ void  destroyPtr(const RefCounter *  c)  const;
+};
+
+class RefCounter {
+
+  mutable int count;
+  protected:
+  virtual ~RefCounter() {}
+  RefCounter() : count(0) {}
+  public:
+  int destroy() const { 
+   if(this) {throwassert(count>=0);
+        if ( count--==0) {
+	            SHOWVERB( cout << "True  destruction of " << this <<  endl);
+             delete this;
+             return true;} 
+        else{ SHOWVERB(cout << " no destruction count=" << count+1 << " " << this <<  endl);
+              return false;}}
+   else return false;} 
+   void increment() const {count++;} 
+   void decrement() const {count--;}
+ friend   class baseCountPointer;
+// private:
+  RefCounter(const RefCounter &) : count(0) {} 
+  void operator=(const RefCounter &) { count=0;}
+ 
+
+};
+
+inline void baseCountPointer::add(const RefCounter * c)  const 
+   { if (c) c->count++;}    
+inline void baseCountPointer::destroyPtr(const RefCounter *   c)  const 
+   { if (c) c->destroy();}    
+ 
+template<class T>
+class CountPointer: private baseCountPointer {
+ T * c;
+ public: 
+ CountPointer() : c(0) {}
+ CountPointer( T * a,bool mmaster=false) :c(a) { if(!mmaster) add(c);} 
+ CountPointer(  T & a) :c(&a) { add(c);}
+ CountPointer(const CountPointer & a) :c(a.c) { add(c);}
+ ~CountPointer()  { destroyPtr(c);c=0;}
+ //void destroy() const { destroyPtr(c);}
+ void destroy()  { destroyPtr(c);c=0;}
+ operator  T * ()   const { return c;}
+ operator   T & () const  {return *c;}
+  T& operator*() const {return *c;}
+  T* operator->() const {return c;}
+ bool operator==(const  CountPointer & n) const {return  n.c ==c;}
+ bool operator!=(const  CountPointer & n) const {return  n.c !=c;}
+ bool operator!() const { return !c;}
+ void operator=(const  CountPointer & n) {
+  if(*this != n) { destroyPtr(c); 
+                c=n.c;
+                add(c);               
+              }}
+                           
+ void operator=( T * t) {
+  if( c != t) { if(c) destroyPtr(c); 
+                c=t;
+                add(c);               
+              }} 
+//  for the compile time               
+ void init() {c=0;} // 
+ void master(T *t) {
+     destroyPtr(c); 
+     c=t;}
+};
+
+#endif
diff --git a/src/femlib/assertion.hpp b/src/femlib/assertion.hpp
new file mode 100755
index 0000000..9894ab5
--- /dev/null
+++ b/src/femlib/assertion.hpp
@@ -0,0 +1,14 @@
+#ifndef ASSERTION_HPP_
+#define ASSERTION_HPP_
+//  to compile all assertion
+//#define ASSERTION
+// to remove all the assert  
+//#define NDEBUG
+#ifndef ASSERTION
+#define ASSERTION(i)  ((void )  0)
+#else
+#include <cassert>
+#undef ASSERTION
+#define ASSERTION(i) assert(i)
+#endif
+#endif
diff --git a/src/femlib/fem.cpp b/src/femlib/fem.cpp
new file mode 100644
index 0000000..ad752af
--- /dev/null
+++ b/src/femlib/fem.cpp
@@ -0,0 +1,2083 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+extern long verbosity ;
+extern long searchMethod; //pichon
+
+#include <cmath>
+#include  <cfloat>
+#include <cstdlib>
+#include "error.hpp"
+#include <iostream>
+#include <fstream>
+//#include <strstream.h>
+//using namespace std;  //introduces namespace std
+#include "RNM.hpp"
+#include "rgraph.hpp"
+#include "Serialize.hpp"
+#include "fem.hpp"
+#include <set>
+namespace Fem2D {
+    
+    
+class SubMortar { 
+	friend class Mesh;
+	friend ostream & operator<<(ostream & f,const SubMortar & m);
+	R  alpha; // angle in radian 
+	R2 from,to;
+	int k; //  triangle number
+	int i; //  edge on triangle
+	int sens; //       
+		  //  int head;
+public:
+	    SubMortar() :alpha(0),k(0),i(0),sens(0){}
+	SubMortar(const Vertex & s,const Vertex & ss,int kk,int ii,int se) 
+	    : alpha(Theta((R2) ss - s)),from(s),to(ss),k(kk),i(ii),sens(se) {}
+	R len2() const { return Norme2_2(to-from);}
+	R len2(const R2 & A) const{ return (to-from,(A-from));}
+	
+	
+	bool operator<(const SubMortar &  b){ return alpha < b.alpha ;}  // to sort
+									 //  bool side(const Triangle &K) {}
+    };
+    
+    ostream & operator<<(ostream & f,const SubMortar & m)
+    { f << " a=" << m.alpha << " " << m.k << " " << m.i << " " << m.sens << " l^2=" <<m.len2() <<  ";" ;
+	return f;}
+    
+    void Mesh::BuildBoundaryAdjacences()
+    {
+	if(!BoundaryAdjacencesHead)
+	{
+	    BoundaryAdjacencesHead = new int[nv];
+	    BoundaryAdjacencesLink = new int[neb+neb];
+	    for (int i=0;i<nv;i++) 
+		BoundaryAdjacencesHead[i]=-1;
+	    int j2=0;
+	    for (int j=0;j<neb;j++)
+		for (int k=0;k<2;k++,j2++)
+		{  
+		    int v = number(bedges[j][k]);
+		    assert(v >=0 && v < nv);
+		    BoundaryAdjacencesLink[j2]=BoundaryAdjacencesHead[v];
+		    BoundaryAdjacencesHead[v]=j2;
+		}
+		    
+	}
+    }  
+	void Mesh::ConsAdjacence()
+    {
+	    //  warning in the paper a mortar is the whole edge of the coarse triangle
+	    //  here a mortar is a connected componand of he whole edge of the coarse triangle 
+	    //   minus  the extremite of mortar
+	    //  -----------
+	    int NbCollision=0,NbOfEdges=0,NbOfBEdges=0,NbOfMEdges=0;
+	    const char MaskEdge[]={1,2,4};
+	    const char AddMortar[]={8,16,32};
+	    //    reffecran();
+	    //    cadreortho(0.22,0.22,.1);
+	    if (neb) BuildBoundaryAdjacences();
+            area=0;  // FH add nov 2010
+            lenbord=0; // FH add nov 2010
+	    if(TheAdjacencesLink) return; //
+	    TheAdjacencesLink = new int[3*nt];
+	    const int NbCode = 2*nv;
+	    char * TonBoundary = new char [nt]; // the edge is 1 2 4   AddMortar = 8
+	    
+	    { int * Head = new int[NbCode];
+		
+		//  make the list
+		int i,j,k,n,j0,j1;
+		for ( i=0; i<NbCode; i++ )
+		    Head[i]=-1; // empty list
+		n=0; // make all the link
+		for (i=0;i<nt;i++)
+		{ 
+		    Triangle & T=triangles[i];
+		    area += T.area; // add FH nov 2010 
+		    for( j=0; j<3; j++,n++ )
+		    { 
+			VerticesNumberOfEdge(T,j,j0,j1);
+			k = j0+j1;
+			TheAdjacencesLink[n]=Head[k]; 
+			Head[k]=n; //            
+		    }
+		    
+		}
+		//
+		if (neb==0) { // build boundary
+		    for(int step=0;step<2;step++)
+		    {
+			neb=0;
+			for (i=0;i<nt;i++)
+			{ 
+			    Triangle & T=triangles[i];
+			    for( j=0; j<3; j++,n++ )
+			    { 
+				VerticesNumberOfEdge(T,j,j0,j1);
+				int kk = 0,im=Min(j0,j1);             
+				for (int n=Head[j0+j1]; n>=0; n=TheAdjacencesLink[n])
+				{ int jj=n%3,ii=n/3, jj0,jj1;
+				    VerticesNumberOfEdge(triangles[ii],jj,jj0,jj1);
+				    if(im==Min(jj0,jj1)) // same edge 
+					kk++;
+				}
+				if (kk==1) { 
+				    if(step) bedges[neb].set(vertices,j0,j1,1);
+				    neb++;
+				}
+				
+			    }
+			}
+			if (step==0) {
+			    if (verbosity) cout << " we build " << neb << " boundary edges" << endl;
+			    bedges = new BoundaryEdge[neb];
+			}
+		    }
+		    BuildBoundaryAdjacences(); 
+		}
+		for (int k=0;k<nt;k++) TonBoundary[k]=0;
+		
+		BoundaryEdgeHeadLink = new int[neb];       
+		for (i=0;i<neb;i++)
+		{  
+		    BoundaryEdge & be(bedges[i]);
+		    lenbord +=   be.length() ; // add Now 2010 FH 
+		    int n;
+		    int i0=number(be.vertices[0]);
+		    int i1=number(be.vertices[1]);
+		    throwassert(i0 >=0 && i0 < nv);
+		    throwassert(i1 >=0 && i1 < nv);
+		    throwassert(i1 != i0) ;
+		    int im=Min(i0,i1);
+		    BoundaryEdgeHeadLink[i]=-1; 
+		    for ( n=Head[i0+i1]; n>=0; n=TheAdjacencesLink[n])
+		    {
+			int jj=n%3,ii=n/3, jj0,jj1;
+			VerticesNumberOfEdge(triangles[ii],jj,jj0,jj1);
+			if(im==Min(jj0,jj1)) // same edge 
+			{
+			    TonBoundary[n/3] += MaskEdge[n%3];
+			    BoundaryEdgeHeadLink[i]=n;                  
+			    if(i0==jj0) break; // FH 01072005 bon cote de l'arete 
+					       // sinon on regard si cela existe?
+			}
+		    } 
+		    if ( BoundaryEdgeHeadLink[i] <0 && verbosity) 
+			cout << "   Attention l'arete frontiere " << i 
+			    << " n'est pas dans le maillage " <<i0 << " " << i1 <<  endl;
+		}
+		
+		//  find adj
+		// reffecran();    
+		
+		for (i=0;i<nt;i++)
+		{ 
+		    Triangle & T=triangles[i];
+		    for( j=0; j<3; j++,n++ )
+		    { 
+			VerticesNumberOfEdge(T,j,j0,j1);
+			k = j0+j1; // code of current edge 
+			int jm = Min(j0,j1), NbAdj=0, He=-1;
+			int *pm=Head+k;
+			while (*pm>=0) // be carefull  
+			{                                 
+			    int m=*pm,jj=m%3,ii=m/3, jj0,jj1;
+			    VerticesNumberOfEdge(triangles[ii],jj,jj0,jj1);
+			    if(jm==Min(jj0,jj1)) // same edge 
+			    {                  
+				NbAdj++;   
+				// remove from  the liste 
+				*pm=TheAdjacencesLink[m];
+				TheAdjacencesLink[m]=He;  // link to He
+				He = m;                  
+			    }
+			    else 
+			    {
+				NbCollision++;
+				pm=TheAdjacencesLink+*pm; // next 
+			    }
+			}
+			//  make a circular link 
+			if (NbAdj>0) 
+			{ 
+			    int m=He;
+			    while(TheAdjacencesLink[m]>=0)
+				m=TheAdjacencesLink[m]; // find end of list     
+							// close the List of common edges               
+			    TheAdjacencesLink[m] = He;               
+			}
+			if (NbAdj >2) 
+			{
+			    int m=He;
+			    do { 
+				m=TheAdjacencesLink[m];
+			    } while(TheAdjacencesLink[m]!=He);
+			}
+			
+			if (NbAdj) NbOfEdges++;
+			if(NbAdj==1)
+                        {
+                            if (! (TonBoundary[i]& MaskEdge[j]))
+			    { NbOfMEdges++;
+				if(verbosity>99) 
+				    cout << " Edge (" << j0 << " "<< j1 << ") : "  << j  << " of Triangle " << &T-triangles << " on mortar \n"
+				    <<" --- > " << number(T[0]) << " " << number(T[1]) << " " << number(T[2]) << " /" << int(TonBoundary[i])<< "\n" ;
+				TonBoundary[i]+= AddMortar[j];
+			    }
+				else { NbOfBEdges++; }
+                        }
+		    }
+		}
+		    
+		    if (verbosity>1 ) {
+			cout << "    Nb of Vertices " << nv <<  " ,  Nb of Triangles " 
+			<< nt << endl ;
+			cout << "    Nb of edge on user boundary  " << neb 
+			<< " ,  Nb of edges on true boundary  " << NbOfBEdges << endl;
+			if(NbOfMEdges) cout << "    Nb of edges on Mortars  = " << NbOfMEdges << endl;
+
+		    }
+		    delete [] Head; // cleanning memory
+		    NbMortars =0;
+		    NbMortarsPaper=0;
+	    }
+		{
+		    //  construct the mortar 
+		    int * linkg = new int [nv]; //  to link
+		    int * linkd = new int [nv]; //  to link
+		    int * NextT3= new int[3*nt];
+		    int * headT3= new int[nv];
+		    ffassert( linkg && linkd);
+		    for (int i=0;i<nv;i++) 
+			headT3[i]=linkg[i]=linkd[i]=-1; // empty
+							//   create the 2 link 
+							//  reffecran();
+							//  Draw(0);
+		    for (int k=0;k<nt;k++)
+			for (int j=0;j<3;j++)
+			    if (TonBoundary[k] & AddMortar[j]) 
+			    { 
+				//   triangles[k].Draw(j,0.8);
+				int s0,s1;
+				VerticesNumberOfEdge(triangles[k],j,s0,s1);
+				linkg[s0] = (linkg[s0] == -1) ? s1 : -2 ;
+				linkd[s1] = (linkd[s1] == -1) ? s0 : -2 ; 
+				//              throwassert(linkg[s0] != -1 && linkg[s1] != -1 );
+				//   cout << "On Mortar " << s0 << " " << s1 << " link " <<  linkg[s0]  << " " << linkd[s1] <<endl  ;                              
+			    } 
+				//  we remove the  boundary link       
+				for (int k=0;k<nt;k++)
+				    for (int j=0;j<3;j++)
+					if (TonBoundary[k] & MaskEdge[j]) 
+					{ 
+					    int s0,s1;
+					    VerticesNumberOfEdge(triangles[k],j,s0,s1);
+					    // cout << s0 << " " << s1 << " ld " << linkd[s0]  << " " << linkd[s1] << " lg " << linkg[s0]  << " " << linkg[s1] << " apres " ;              
+					    linkg[s0] = linkg[s0] != -1 ?  -2 : -1;
+					    linkg[s1] = linkg[s1] != -1 ?  -2 : -1;
+					    
+					    linkd[s1] = linkd[s1] != -1 ?  -2 : -1;                                                 
+					    linkd[s0] = linkd[s0] != -1 ?  -2 : -1; 
+					    // cout  << " ld " << linkd[s0]  << " " << linkd[s1] << " lg" << linkg[s0]  << " " << linkg[s1] << endl;
+					    
+					} 
+					    
+					    //    remark if   linkd[i]  == -2  extremities of mortars (more than 2 mortars)
+					    //    if  ((linkd[i] != -1) || (linkd[i] != -1))   =>   i is on mortars 
+					    //    make a link for all triangles contening a  mortars
+					    const int k100=100;
+		    SubMortar  bmortars[k100];
+		    int k3j=0;
+		    for (int k=0;k<nt;k++) {
+			const  Triangle & T=triangles[k];
+			for (int j=0;j<3;j++,k3j++) 
+			{ 
+			    NextT3[k3j]=-2; 
+			    
+			    int is= number(T[j]);
+			    // if (linkg[is]<-1 || linkd[is]<-1) // extremite of bmortars
+			    int j0 =EdgesVertexTriangle[j][0];  //  the 2 edges contening j 
+			    int j1 =EdgesVertexTriangle[j][1];
+			    if  (TonBoundary[k] & (AddMortar[j0]|AddMortar[j1]))  // (linkg[is]!=-1) 
+			    { 
+				throwassert(linkd[is]!=-1 || linkg[is]!=-1);
+				NextT3[k3j]=headT3[is];
+				headT3[is] =  k3j; 
+			    }}
+		    }
+		    //    loop on extremite of bmortars 
+		    // calcule du nombre de joint 
+		    /*      rattente(1);      
+		    for (int is=0;is<nv;is++)
+			if ( (linkg[is]<-1 || linkd[is]<-1) )
+		    {MoveTo( vertices[is]);
+			    ostringstream ss;
+			    ss << is ;
+			    plotstring(ss.str().c_str());
+		    }  */  
+		    datamortars=0;
+		    int kdmg = 0,kdmd=0; 
+		    int kdmgaa = 0,kdmdaa=0; 
+		    int step=0;
+		    mortars=0;
+		    NbMortars = 0;
+		    NbMortarsPaper=0;
+		    do { // two step  
+			 // one to compute the NbMortars
+			 // one to store in mortars and kdm 
+			int * datag=0,*datad=0;
+			ffassert(step++<2);
+			if (NbMortars)
+			{ // do allocation 
+			    int kdm=kdmgaa+kdmdaa;
+			    if (verbosity>2)
+				cout << "   sizeof datamortars" << kdm << " NbMortars=" << NbMortars << endl;
+			    mortars     = new Mortar [NbMortars];
+			    datamortars = new int [kdm];
+			    for (int i=0;i<kdm;i++)
+				datamortars[i]=0;
+			    datag=datamortars;
+			    datad=datamortars+kdmgaa;
+			    ffassert(kdmg && kdmd);
+			}
+			int onbm=NbMortars;
+			// cout << "begin " << NbMortars << " g " << kdmg << " d " <<kdmd << endl;
+			int kdmgo=kdmgaa;
+			int kdmdo=kdmdaa;
+			int kdm=kdmdaa+kdmgaa;
+			//  reset 
+			NbMortars =0;
+			kdmg =0;
+			kdmd =0;
+			
+			
+			for (int is=0;is<nv;is++)
+			    if (linkg[is] == -2) 
+			    { // for all extremity of mortars 
+				if(linkd[is] != -2)
+				{
+				  cout <<" Bug in mortar constrution : close to vertex "<< is << endl; 
+				  ffassert(linkd[is] == -2);
+				}
+				const Vertex & S = vertices[is];
+				R2  A(S);
+				int km=0;
+				int p;
+				for ( p=headT3[is] ;p>=0; p=NextT3[p])
+				{  //  for all nonconformitie around sm            
+				    int k=p/3;
+				    int i=p%3;
+				    const Triangle & T(triangles[k]);
+				    //throwassert( vertices + sm == &T[i]);
+				    // for the 2 egdes contening the vertex j of the triangle k
+				    
+				    for (int jj=0;jj<2;jj++)   // 2 edge j contening i              
+				    { 
+					int j = EdgesVertexTriangle[i][jj];                     
+					int s0,s1;
+					VerticesNumberOfEdge(T,j,s0,s1);
+					throwassert (s0  == is || s1 == is);
+					if ( TonBoundary[k] & AddMortar[j])
+					{
+					    int ss,sens;
+					    if ( s0 == is)
+					    { ss=s1;sens=1;}
+					    else
+					    { ss=s0;sens=-1;}
+					    const Vertex & vss( vertices[ss]);
+					    bmortars[km++] = SubMortar(S,vss,k,i,sens);
+					    throwassert(km<k100);
+					} 
+				    }
+				}
+				ffassert(p!=-2);
+				
+				// throwassert(km % 2 == 0);
+				HeapSort(bmortars,km); 
+				// cout <<" Nb of mortars around vertex "<< is << " = " << km<< endl;
+				//  searh the same mortar (left and right)
+				//  with same angle
+				int im=km-1; // the last
+				
+				double eps = 1e-6;
+				double thetai=bmortars[im].alpha-2*Pi;
+				
+				for (int jm=0;jm<km;im=jm++) 
+				{ //  for all break of vertex 
+				    
+				    double theta= (bmortars[jm].alpha-thetai);
+				    thetai=bmortars[jm].alpha;
+				    if (theta < eps  || theta+eps > 2*Pi)
+				    {//  same angle mod 2 * Pi
+				     //  beginning of a mortars 
+					if(mortars)  { //  set the pointeur
+					    ffassert(NbMortars< onbm);
+					    ffassert(datag && datad);
+					    ffassert(datag< datamortars+ kdm);
+					    mortars[NbMortars].left  = datag;
+					    mortars[NbMortars].right = datad;
+					    mortars[NbMortars].Th = this;
+					}
+					// cout << "   Begin mortar " << is << " " << im << " " << jm << " theta =" << thetai << endl; 
+					R2 AM(A,bmortars[im].to);
+					AM = AM/Norme2(AM);
+					int ig(im),id(jm);
+					if ( bmortars[im].sens <0) ig=jm,id=im;
+					//SubMortar & mg(bmortars[ig]);
+					//SubMortar & md(bmortars[id]);
+					//  loop sur droite gauche
+					//  meme sommet
+					//   0 = gauche 1=droite 
+					int sgd[2]={0,0};
+					int *link[2];                   
+					int nm[2]={0,0}; 
+					R  ll[2]={0.0,0.0}; 
+					// 
+					sgd[0]=sgd[1]=is; 
+					link[0] = linkg;
+					link[1] = linkd;
+					int gd=0; //  gd = 0 => left side  an gd=1 => right side
+					
+					
+					int kkkk=0;
+					do { //   for all 
+					    
+					    
+					    int sm = sgd[gd]; 
+					    int  dg = 1-gd;
+					    // cout << " sm = " << sm << " h=" << headT3[sm] << " gb=" << gd << " autre " << sgd[dg ] << " " << kkkk << endl;
+					    
+					    R lAV,avam;
+					    Vertex *pV=0;
+					    int p,k,i,j;
+					    //  search the the first start ( sens = gd )
+					    throwassert(headT3[sm]>=0);// on a mortar ?? 
+						for ( p=headT3[sm] ;p>=0; p=NextT3[p])
+						{                
+						    k=p/3;
+						    i=p%3;
+						    const Triangle & T(triangles[k]);
+						    // couleur(1);T.Draw(0.3);
+						    throwassert( vertices + sm == &T[i]);
+						    // for the 2 egdes contening the vertex j of the triangle k
+						    j = EdgesVertexTriangle[i][dg];
+						    Vertex &V = T[VerticesOfTriangularEdge[j][dg]];
+						    throwassert( &T[VerticesOfTriangularEdge[j][gd]] == vertices + sm);                
+						    if ( TonBoundary[k] & AddMortar[j])
+						    {  // check the sens and the direction
+							
+							//  cout << number(T[VerticesOfTriangularEdge[j][gd]])  << " pv=" 
+							//      << number(V)  << " sm=" << sm << " " << headT3[number(V)] << endl; 
+							
+							R2 AV(A,V);
+							lAV = Norme2(AV);
+							avam = (AV,AM);
+							// cout << " ---  " << avam << " > " << ll[gd] <<  " " << Abs((AM.perp(),AV) )
+							//     << " " << ( avam > ll[gd] && Abs((AM.perp(),AV)) < lAV * 1e-6 ) << endl;
+							// go ahead in direction AM 
+							if ( (avam > ll[gd])  && Abs((AM.perp(),AV)) < lAV * 1e-6 )  
+							{pV = &V;break;} //  ok good                         
+						    }
+						}
+						if ( ! (p>=0 && pV))
+						    throwassert(p>=0 && pV); //  PB reach the end without founding 
+						if ( ! ( Abs((AM.perp(),A-*pV)) < 1e-5) )
+						    // cout << Abs((AM.perp(),A-*pV)) <<*pV << endl, 
+						    throwassert( Abs((AM.perp(),A-*pV)) < 1e-5);
+						
+						throwassert(sm != number(pV));
+						int kkgd= 3*k + j;   
+						ll[gd] = avam;
+						//   find the SubMortar m of vertex  sm
+						//   with same sens and direction 
+						//   
+						
+						for (int s= number(pV);s>=0;s=link[gd][s],nm[gd]++) 
+						{
+						    //  on est sur l'arete kkgd
+						    
+						    throwassert( s == number(triangles[kkgd/3][VerticesOfTriangularEdge[kkgd%3][dg]]));
+						    sgd[gd]=s;// save the last
+							if ( ! ( Abs((AM.perp(),A-vertices[s])) < 1e-5) )
+							    // cout << Abs((AM.perp(),A-vertices[s])) << vertices[s] << endl, 
+							    throwassert( Abs((AM.perp(),A-vertices[s])) < 1e-5);
+							//cout << " s=" << s << " h=" << headT3[s] << " " << link[gd][s] << " " <<  link[dg][s] << endl; ;
+							throwassert(kkgd>=0 && kkgd < 3*nt);
+							if (datamortars) 
+							{
+							    throwassert(datag - datamortars == nm[0] + kdmg);
+							    throwassert(datad - datamortars == nm[1] + kdmd + kdmgo );
+							    
+							    if (gd == 0)  *datag++ = kkgd; // store 
+							    else          *datad++ = kkgd; //
+							    
+							}  
+							
+							//                            cout  << " ++++ "<<  ll[gd] << " > " << ll[dg]  << " " << headT3[sgd[dg]] << " " <<sgd[dg] << endl;    
+							
+							int kk=kkgd,kkk=0,kkkk=0;
+							if ( link[gd][s] >=0) { 
+							    for (int pp=headT3[s] ;pp>=0; pp=NextT3[pp],kkk++)
+							    {  throwassert(number(triangles[pp/3][pp%3]) == s);
+								
+								if( (pp/3)!= (kk/3))
+								{
+								    kkkk++,kkgd=pp - (pp%3) + EdgesVertexTriangle[pp%3][dg];                                  
+								}
+							    }
+							    throwassert( kkgd/3 != kk/3);
+							    throwassert(kkk==2 && kkkk==1);}  
+						} 
+						
+						if (ll[gd]>ll[dg] &&  headT3[sgd[dg]]>=0) //changement de cote 
+						    gd = dg; 
+						throwassert(kkkk++<100);
+						//cout <<" kkkk=" << kkkk << " " << sgd[0] << " " << sgd[1] << endl;
+					} while (sgd[0] != sgd[1]); 
+					
+					kdmgaa = Max(kdmgaa,kdmg  + nm[0]);
+					kdmdaa = Max(kdmdaa,kdmd  + nm[1]);                                                                    
+					
+					if (is < sgd[0]  &&  headT3[sgd[0]] >=0) {
+					    //cout << "    Mortars from (on saute) " << is << " to " << sgd[0] << " " << nm[0] << " " << nm[1]<< " " <<  kdmg <<  " " << kdmd << endl;
+					    if( mortars ) { //  restore 
+						datag -= nm[0];
+						datad -= nm[1];   } 
+					    
+					} 
+					else {
+					    // cout << "    Mortars from " << is << " to " << sgd[0] << " " << nm[0] << " " << nm[1]<< " " <<  kdmg <<  " " << kdmd << endl;
+					    
+					    if(mortars ) {
+						ffassert(NbMortars< onbm);
+						mortars[NbMortars].nleft  = nm[0];
+						mortars[NbMortars].nright = nm[1];
+						
+						//  check
+						for (int i=0;i<mortars[NbMortars].nleft;++i)
+						    if ( mortars[NbMortars].left[i] <0 ||  mortars[NbMortars].left[i] < 3*nt)
+							ffassert(0);
+						for (int i=0;i<mortars[NbMortars].nright;++i)
+						    if ( mortars[NbMortars].right[i] <0 ||  mortars[NbMortars].right[i] < 3*nt)
+							ffassert(0);                             
+						ffassert(datag <= datamortars + kdmgo + kdmdo); 
+						ffassert(datad <= datamortars + kdmgo + kdmdo); 
+					    }
+					    kdmg += nm[0];
+					    kdmd += nm[1]; 
+					    NbMortars++;
+					}
+				    } // same angle 
+				}//  for all break of vertex                  
+			    } // for all extremity of mortars 
+				if (verbosity>1 && NbMortars) 
+				    cout << "    Nb Mortars " << NbMortars << /*" " << kdmg << " "<<  kdmd <<*/ endl;
+			if (mortars) 
+			{
+			    // cout << "end " << NbMortars << " g " << kdmg << " d " <<kdmd << endl;
+			    // cout << kdmgo << " " << kdmg << " " << kdmdo << " " << kdmd << endl;
+			    ffassert(kdmgo == kdmgaa && kdmdo == kdmdaa);}
+		    }  while (NbMortars && !mortars) ;
+		    
+		    //   rattente(1);
+		    //   reffecran();
+		    //    compute the NbMortarsPaper
+		    int t3,nt3 = nt*3;
+		    NbMortarsPaper=0;
+		    for (int i=0;i<nt3;i++) 
+			NextT3[i]=0;
+		    for (int i=0;i<NbMortars;i++)
+		    {
+			
+			if (mortars[i].nleft==1)
+			{ t3=mortars[i].left[0];}
+			else  if (mortars[i].nright==1)
+			{ t3=mortars[i].right[0];}
+			else { cout << "   -- Bizarre " << mortars[i].nleft << " " << mortars[i].nright << endl;
+			}
+			if (NextT3[t3]==0) NbMortarsPaper++;
+			NextT3[t3]++;
+		    }
+		    delete [] linkg;
+		    delete [] linkd;
+		    delete [] NextT3;
+		    delete [] headT3;
+		    
+		}//  end of mortar construction   
+		
+		
+		
+		delete [] TonBoundary;
+		
+		//  construction of TriangleConteningVertex
+		TriangleConteningVertex = new int[nv];
+		for (int it=0;it<nt;it++)
+		    for (int j=0;j<3;j++)
+			TriangleConteningVertex[(*this)(it,j)]=it;
+		
+		Buildbnormalv();
+		if (verbosity>4) 
+		{ 
+		    cout << "    Number of Edges                 = " << NbOfEdges << endl;
+		    cout << "    Number of Boundary Edges        = " << NbOfBEdges << " neb = " << neb << endl;
+		    cout << "    Number of Mortars  Edges        = " << NbOfMEdges << endl;
+		    cout << "    Nb Of Mortars with Paper Def    = " <<  NbMortarsPaper << " Nb Of Mortars = " << NbMortars;             
+		    cout << "    Euler Number nt- NbOfEdges + nv = " 
+			<< nt + NbMortars - NbOfEdges + nv << "= Nb of Connected Componant - Nb Of Hole " 
+			<<endl;}
+		
+    }
+	    void  Mesh::BoundingBox(R2 &Pmin,R2 &Pmax) const 
+	    {
+		ffassert(nv);
+		Pmin=Pmax=vertices[0];
+		for (int i=0;i<nv;i++)
+		{ 
+		    const R2 & P=vertices[i];
+		    Pmin.x = Min(Pmin.x,P.x);
+		    Pmin.y = Min(Pmin.y,P.y);
+		    Pmax.x = Max(Pmax.x,P.x);
+		    Pmax.y = Max(Pmax.y,P.y);
+		} 
+		//  cout << " Bounding Box = " << Pmin <<" " <<  Pmax << endl;       
+	    }
+    void Mesh::read(const char * filename)
+    {
+	ifstream f(filename);
+	if (!f) {
+	    cerr << "Erreur ouverture du fichier " << filename << endl;
+	throw(ErrorExec("exit",1));}
+	// ffassert(f);
+	if(verbosity)
+	    cout << "  -- Mesh::read On file \"" <<filename<<"\""<<  endl;
+	read(f);
+    }
+    void Mesh::read(ifstream & f , bool bin )
+    { // read the mesh
+	dim=2;
+	ne=0;
+	ntet=0;
+	volume=0;
+	TriangleConteningVertex =0;
+	BoundaryAdjacencesHead=0;
+	BoundaryAdjacencesLink=0;
+	BoundaryEdgeHeadLink=0;
+	quadtree =0;
+	NbMortars=0;
+	tet=0;
+	edges=0;    
+	mortars=0;
+	TheAdjacencesLink =0;
+	area=0;
+	bnormalv=0;
+	
+	int i,i0,i1,i2,ir;
+	
+	
+	f >> nv >> nt >> neb ;
+	if(verbosity>10)
+	    cout << "    Nb of Vertex " << nv << " " << " Nb of Triangles " 
+	    << nt << " Nb of boundary edge " << neb <<  endl;
+	ffassert(f.good() && nt && nv) ;
+	triangles = new Triangle [nt];
+	vertices  = new Vertex[nv];
+	bedges    = new BoundaryEdge[neb];
+	area=0;
+	ffassert(triangles && vertices && bedges);
+	
+	for (i=0;i<nv;i++)    
+	    f >> vertices[i],ffassert(f.good());
+	
+	for (i=0;i<nt;i++) { 
+	    f >> i0 >> i1 >> i2 >> ir;
+	    ffassert(f.good() && i0>0 && i0<=nv && i1>0 && i1<=nv && i2>0 && i2<=nv);
+	    triangles[i].set(vertices,i0-1,i1-1,i2-1,ir); 
+	area += triangles[i].area;}
+	
+	for (i=0;i<neb;i++) { 
+	    f >> i0 >> i1 >> ir;
+	bedges[i] = BoundaryEdge(vertices,i0-1,i1-1,ir); }
+	
+	if(verbosity)
+	    cout << "   End of read: area on mesh = " << area <<endl;  
+	ConsAdjacence();
+	//   BoundingBox(cMin,cMax);//  Set of cMin,Cmax
+    }
+    
+	    Mesh::Mesh(int nbv,int nbt,int nbeb,Vertex *v,Triangle *t,BoundaryEdge  *b)
+	    {
+		TriangleConteningVertex =0;
+		BoundaryAdjacencesHead=0;
+		BoundaryAdjacencesLink=0;
+		BoundaryEdgeHeadLink=0;
+		quadtree =0;
+		NbMortars=0;
+		mortars=0;
+		dim=2;
+		tet=0;
+		volume=0;
+		edges=0;
+		ntet=0;
+		ne=0;    
+		TheAdjacencesLink =0;
+		nv=nbv;
+		nt =nbt;
+		neb=nbeb;
+		triangles=t;
+		vertices=v;
+		bedges=b;
+		area=0;
+		bnormalv=0;
+		if (t && nt >0) 
+		{
+		    for (int i=0;i<nt;i++)  
+			area += triangles[i].area;
+		    ConsAdjacence();  
+		}  
+		else
+		{
+		    bool removeouside=nbt>=0;
+		    nt=0;
+		    BuilTriangles(true,removeouside);
+		    /*    if( ! removeouside)
+		    {
+			neb=0; // remove the edge
+			delete [] bedges;
+			bedges=0;        
+			
+		    } */
+		    ConsAdjacence();
+		}
+		// cout << " build: Mesh : " << this << endl;
+	    }  
+	    
+	    inline int BinaryRand(){
+#ifdef RAND_MAX
+		const long HalfRandMax = RAND_MAX/2;
+		return rand() <HalfRandMax;
+#else
+		return rand() & 16384; // 2^14 (
+#endif
+		
+} 
+int  WalkInTriangle(const Mesh & Th,int it, double *lambda,
+                    const  KN_<R> & U,const  KN_<R> & V, R & dt)
+{
+    const Triangle & T(Th[it]);
+    const R2 Q[3]={(const R2) T[0],(const R2) T[1],(const R2) T[2]};
+    int i0=Th.number(T[0]);
+    int i1=Th.number(T[1]);
+    int i2=Th.number(T[2]);
+    
+    R u   = lambda[0]*U[i0] + lambda[1]*U[i1] + lambda[2]*U[i2];
+    R v   = lambda[0]*V[i0] + lambda[1]*V[i1] + lambda[2]*V[i2];
+    R2 P  = lambda[0]*Q[0]  + lambda[1]*Q[1]  + lambda[2]*Q[2];
+    
+    //  cout << " " << u << " " << v ;
+    R2 PF = P + R2(u,v)*dt;
+    
+    //  couleur(15);MoveTo( P); LineTo( PF);
+    R l[3];
+    l[0] = Area2(PF  ,Q[1],Q[2]);
+    l[1] = Area2(Q[0],PF  ,Q[2]);
+    l[2] = Area2(Q[0],Q[1],PF  );
+    R Det = l[0]+l[1]+l[2];
+    l[0] /= Det;
+    l[1] /= Det;
+    l[2] /= Det;
+    const R eps = 1e-5;
+    int neg[3],k=0;
+    int kk=-1;
+    if (l[0]>-eps && l[1]>-eps && l[2]>-eps) 
+    {
+	dt =0;
+	lambda[0] = l[0];
+	lambda[1] = l[1];
+	lambda[2] = l[2];
+    }
+    else 
+    {
+	
+	if (l[0]<eps && lambda[0] != l[0]) neg[k++]=0;
+	if (l[1]<eps && lambda[1] != l[1]) neg[k++]=1;
+	if (l[2]<eps && lambda[2] != l[2]) neg[k++]=2;
+	R eps1 = T.area     * 1.e-5;
+	
+	if (k==2) // 2  
+	{
+	    // let j be the vertex beetween the 2 edges 
+	    int j = 3-neg[0]-neg[1];
+	    // 
+	    R S = Area2(P,PF,Q[j]);
+	    
+	    if (S>eps1)
+		kk = (j+1)%3;
+	    else if (S<-eps1)
+		kk = (j+2)%3;
+	    else if (BinaryRand())
+		kk = (j+1)%3;
+	    else
+		kk = (j+2)%3;
+	    
+	} 
+	else if (k==1)
+	    kk = neg[0];
+	if(kk>=0)
+	{
+	    R d=lambda[kk]-l[kk];
+	    
+	    throwassert(d);
+	    R coef =  lambda[kk]/d;
+	    R coef1 = 1-coef;
+	    dt        = dt*coef1;
+	    lambda[0] = lambda[0]*coef1 + coef *l[0];
+	    lambda[1] = lambda[1]*coef1 + coef *l[1];
+	    lambda[2] = lambda[2]*coef1 + coef *l[2];
+	    lambda[kk] =0;
+	}
+    }
+    int jj=0;
+    R lmx=lambda[0];
+    if (lmx<lambda[1])  jj=1, lmx=lambda[1];
+    if (lmx<lambda[2])  jj=2, lmx=lambda[2];
+    if(lambda[0]<0) lambda[jj] += lambda[0],lambda[0]=0;
+    if(lambda[1]<0) lambda[jj] += lambda[1],lambda[1]=0;
+    if(lambda[2]<0) lambda[jj] += lambda[2],lambda[2]=0;
+    return kk;
+}
+R2  SubInternalVertex(int N,int k)
+    {
+	if(N<0)
+	  {
+	      R eps = 1e-08;
+	      R2 p[3][3]= { 
+		  { R2(1-eps,+eps),R2(eps,1-eps),R2(1./3.+eps,1./3.+eps) },
+		  { R2(0,1-eps)  ,R2(0,+eps),R2(1./3.-eps,1./3.) },
+		  { R2(eps,0),R2(1-eps,0),R2(1./3.,1./3.-eps) } };
+	      
+	      int j=k%3;
+	      R2 P=SubInternalVertex(-N,k/3);
+	      R l0=1.-P.x-P.y,l1=P.x,l2=P.y;
+	      return p[j][0]*l0+ p[j][1]*l1+ p[j][2]*l2;
+	  }
+	int i,j;
+	num1SubTVertex(N,k,i,j);
+	return R2( (double) i/ (double)N,(double) j/(double)N);
+    }
+    
+R2 SubTriangle(const int N,const int n,const int l)
+{
+    // compute the subdivision of a triangle in N*N
+    // N number of sub division
+    // n number of the sub triangle
+    // l vertex of the sub triangle
+    if(N<0)
+    {
+	R eps = 1e-08;
+	R2 p[3][3]= { 
+	    { R2(1-eps,+eps),R2(eps,1-eps),R2(1./3.+eps,1./3.+eps) },
+	    { R2(0,1-eps)  ,R2(0,+eps),R2(1./3.-eps,1./3.) },
+	    { R2(eps,0),R2(1-eps,0),R2(1./3.,1./3.-eps) } };
+	    
+	int j=n%3;
+	R2 P=SubTriangle(-N,n/3,l);
+	R l0=1.-P.x-P.y,l1=P.x,l2=P.y;
+	return p[j][0]*l0+ p[j][1]*l1+ p[j][2]*l2;
+    }
+    throwassert(n < N*N);
+    int i = n % N;
+    int j = n / N;
+    int k = N - i - j;
+    if(k<=0)
+      {
+	if(l==1) i++;
+	else if(l==2) j++;
+      }
+    else
+      if(l==1) j++;
+      else if(l==2) i++;
+    // if(l==1) i++;
+    // if(l==2) j++;
+    // if ( k <= 0 )cout << " - " << endl;
+    return k >0 
+	? R2( (double) i/ (double)N,(double) j/(double)N)
+	: R2( (double) (N-j)/ (double)N,(double) (N-i)/(double)N);
+    
+} 
+
+int numSubTriangle(const int N,const int n,const int l)
+    {
+	// compute the subdivision of a triangle in N*N
+	// N number of sub division
+	// n number of the sub triangle
+	// l vertex of the sub triangle
+	if(N<0)
+	  {
+	    int j=n%3;
+	    return numSubTriangle(-N,n/3,l)*3+j;
+	  }
+	throwassert(n < N*N);
+	int i = n % N;
+	int j = n / N;
+	int k = N - i - j;
+	if(k<=0)
+	  {
+	    if(l==1) i++;
+	    else if(l==2) j++;
+	  }
+	else
+	  if(l==1) j++;
+	  else if(l==2) i++;
+
+	// if ( k <= 0 )cout << " - " << endl;
+	return k >0 
+	? numSubTVertex(N,i, j)
+	: numSubTVertex(N,N-j,N-i);
+	
+} 
+    
+
+int Walk(const Mesh & Th,int& it, R *l,
+         const KN_<R>  & U,const KN_<R>  & V, R dt) 
+{
+    
+    int k=0;
+    int j; 
+    while ( (j=WalkInTriangle(Th,it,l,U,V,dt))>=0) 
+    { 
+	//int jj  = j;
+	throwassert( l[j] == 0);
+	R a= l[(j+1)%3], b= l[(j+2)%3];
+	int itt =  Th.ElementAdj(it,j);
+	if(itt==it || itt <0)  return -1;
+	it = itt;
+	l[j]=0;
+	l[(j+1)%3] = b;
+	l[(j+2)%3] = a;
+	ffassert(k++<1000);
+    }
+    return it;
+}
+const Triangle *  Mesh::Find( R2 P, R2 & Phat,bool & outside,const Triangle * tstart) const
+{
+    int it,j;
+    const Triangle *  rett=0;
+    if ( tstart )
+	it =  (*this)(tstart);
+    else  
+    {  
+	const Vertex * v=quadtree->NearestVertexWithNormal(P);
+	if (!v) 
+	{ 
+	    v=quadtree->NearestVertex(P);
+	    assert(v);
+	}
+	/*
+	 if (verbosity>100) 
+	 cout << endl << (*this)(v) << *v << " " << Norme2(P-*v) << endl; 
+	 */
+	it=Contening(v);
+    }
+    
+    //     int itdeb=it;     
+    //     int count=0;
+    //     L1: 
+    outside=true; 
+    //int its=it;
+    int iib=-1;//,iit=-1;
+	R dP=DBL_MAX;
+	R2 PPhat;
+	const Triangle * tt;
+	int k=0,kout=0;    
+	kfind++;
+	while (1)
+	{ 
+	    const Triangle & K(triangles[it]);
+	    kthrough++;
+	    if (k++>=10000) 
+	    {
+		/* cout << P << endl;
+		reffecran();
+		Draw(0);
+		triangles[its].Fill(2);
+		DrawMark(P,0.01);
+		rattente(1);  */
+		ffassert(k++<10000);
+	    }
+	    int kk,n=0,nl[3];
+	    
+	    
+	    
+	    R2 & A(K[0]), & B(K[1]), & C(K[2]);
+	    R l[3]={0,0,0};
+	    R area2= K.area*2;
+	    R eps =  -area2*1e-6;
+	    l[0] = Area2(P,B,C);
+	    l[1] = Area2(A,P,C);
+	    l[2] = area2-l[0]-l[1];
+	    if (l[0] < eps) nl[n++]=0;
+	    if (l[1] < eps) nl[n++]=1;
+	    if (l[2] < eps) nl[n++]=2;
+	    
+	    if (n==0)
+	    {  // interior => return
+		outside=false; 
+		Phat=R2(l[1]/area2,l[2]/area2);
+		return &K;
+	    }
+	    else if (n==1) 
+		kk=0;
+	    else  
+		kk=BinaryRand() ? 1 : 0;
+	    
+	    j= nl[ kk ];
+	    
+	    int itt =  ElementAdj(it,j);
+	    if(itt!=it && itt >=0)  
+	    {
+		dP=DBL_MAX;
+		it=itt;
+		continue;
+	    }  
+	    
+	    //  edge j on border
+	    l[j]=0;
+	    
+	    if ( n==2 ) 
+	    {
+		kk = 1-kk;
+		j= nl[ kk ];
+		itt =  ElementAdj(it,j);                  
+		if (itt >=0 && itt != it) // correction FH oct 2009
+		{
+		    dP=DBL_MAX;
+		    it=itt;
+		    continue;
+		}
+		//  on a corner of the mesh 
+		l[j]=0;
+		l[3-nl[0]+nl[1]]=1;
+		Phat=R2(l[1],l[2]);
+	        rett=triangles +it;
+	        if(searchMethod && outside) goto PICHON;
+	      return rett;
+	    }
+	    //   on the border 
+	    //   projection Ortho
+	    
+	    kout++;
+	    
+	    int j0=(j+1)%3,i0= &K[j0]-vertices;
+	    int j1=(j+2)%3,i1= &K[j1]-vertices;
+	    int ii,jj,iii;
+	    bool ret=false;
+	    
+	    R2 AB=R2(K[j0],K[j1]),  AP(K[j0],P), BP(K[j1],P);
+	    R la=  (AB,AP);
+	    R lb= -(AB,BP);
+	    if(la<0)     
+		ii= i0, jj = j0,iii=i1;
+	    else if ( lb <0)
+		ii= i1, jj = j1,iii=i0;
+	    else // PROJECTION between A,B
+		ret = true;
+	    if( ! ret)
+	    { //  VERIF THE DISTANCE**2 Dicrease
+		R2 Pjj(P,K[jj]);
+		R dd = (Pjj,Pjj);
+		if (dd >= dP ) {
+		    Phat=PPhat;
+		    // if(kout>1) cout << "        @ " << tt-triangles  << " " << Phat << " " << outside << endl;
+		    rett=tt;
+		    if(searchMethod && outside) goto PICHON;
+		    return tt;
+		}
+		else
+		{ 
+		    l[0]=l[1]=l[2]=0;
+		    l[jj]=1;
+		    PPhat.x=l[1];
+		    PPhat.y=l[2];                
+		    dP=dd;
+		    tt = triangles + it ;
+		}
+	    }  
+	    /*
+	     if(kout>1)
+	     cout << "Find --- "<< P << " :  k=" << k << "  la lb " << la << " " << lb 
+	     << " ii =" << ii << " iii= " << iii << " " << it << " dP= " 
+	     << dP << " ret = " << ret <<endl;
+	     */
+	    if (ret || ii == iib) 
+	    {  
+		l[j]=0;
+		
+		l[j0]= Max(0.,Min(+lb/(la+lb),1.));
+		l[j1]= 1-l[j0];
+		Phat=R2(l[1],l[2]);
+		//if(kout>1) cout << "        # " << it << " " << Phat << " " << outside << endl; 
+		rett=triangles +it;
+		if(searchMethod && outside) goto PICHON;
+		return rett;
+	    }
+	    bool ok=false;
+	    // next edge on true boundary 
+	    for (int p=BoundaryAdjacencesHead[ii];p>=0;p=BoundaryAdjacencesLink[p])
+	    { int e=p/2, ie=p%2;// je=2-ie;
+				// cout << number(bedges[e][0]) << " " << number(bedges[e][1]) << endl;
+		if (!bedges[e].in( vertices+iii)) //  edge not equal  to i0 i1 
+		{  
+		    ok=true;
+		    iib = ii;
+		    it= BoundaryElement(e,ie);  //  next triangle                      
+						 // cout << "  ------ " << it << " " << Phatt <<  endl;
+		    break;
+		}
+	    }
+	    ffassert(ok); 
+	}
+PICHON:	// Add dec 2010 ... 
+	// Brute force .... bof bof ...
+    double ddp=1e100;
+    int pk=-1;
+    
+    for(int k=0;k<nt;++k)
+      {
+	int n=0,nl[3];
+	Triangle & K=triangles[k];
+	R2 & A(K[0]), & B(K[1]), & C(K[2]), G((A+B+C)/3.);
+	R l[3]={0,0,0};
+	R area2= K.area*2;
+	R eps =  -area2*1e-6;
+	l[0] = Area2(P,B,C);
+	l[1] = Area2(A,P,C);
+	l[2] = area2-l[0]-l[1];
+	if (l[0] < eps) nl[n++]=0;
+	if (l[1] < eps) nl[n++]=1;
+	if (l[2] < eps) nl[n++]=2;
+	if (n==0)
+	  {  // interior => return
+	      outside=false; 
+	      Phat=R2(l[1]/area2,l[2]/area2);
+	      return &K;
+	  }
+	R2 GP(G,P);
+	double lgp2=(GP,GP);
+	if(ddp > lgp2) {
+	    ddp=lgp2;
+	    pk=k;
+	    
+	}
+      }
+    
+    return rett; 
+}
+
+
+int  WalkInTriangle(const Mesh & Th,int it, double *lambda,
+		    R u, R v, R & dt)
+{
+    const Triangle & T(Th[it]);
+    const R2 Q[3]={(const R2) T[0],(const R2) T[1],(const R2) T[2]};
+    // int i0=Th.number(T[0]);
+    // int i1=Th.number(T[1]);
+    // int i2=Th.number(T[2]);
+    
+    R2 P  = lambda[0]*Q[0]  + lambda[1]*Q[1]  + lambda[2]*Q[2];
+    
+    //  cout << " " << u << " " << v ;
+    R2 PF = P + R2(u,v)*dt;
+    
+    //  couleur(15);MoveTo( P); LineTo( PF);
+    R l[3];
+    l[0] = Area2(PF  ,Q[1],Q[2]);
+    l[1] = Area2(Q[0],PF  ,Q[2]);
+    l[2] = Area2(Q[0],Q[1],PF  );
+    R Det = l[0]+l[1]+l[2];
+    l[0] /= Det;
+    l[1] /= Det;
+    l[2] /= Det;
+    const R eps = 1e-5;
+    int neg[3],k=0;
+    int kk=-1;
+    if (l[0]>-eps && l[1]>-eps && l[2]>-eps) 
+    {
+	dt =0;
+	lambda[0] = l[0];
+	lambda[1] = l[1];
+	lambda[2] = l[2];
+    }
+    else 
+    {
+	
+	if (l[0]<eps && lambda[0] != l[0]) neg[k++]=0;
+	if (l[1]<eps && lambda[1] != l[1]) neg[k++]=1;
+	if (l[2]<eps && lambda[2] != l[2]) neg[k++]=2;
+	R eps1 = T.area     * 1.e-5;
+	
+	if (k==2) // 2  
+	{
+	    // let j be the vertex beetween the 2 edges 
+	    int j = 3-neg[0]-neg[1];
+	    // 
+	    R S = Area2(P,PF,Q[j]);
+	    
+	    if (S>eps1)
+		kk = (j+1)%3;
+	    else if (S<-eps1)
+		kk = (j+2)%3;
+	    else if (BinaryRand())
+		kk = (j+1)%3;
+	    else
+		kk = (j+2)%3;
+	    
+	} 
+	else if (k==1)
+	    kk = neg[0];
+	if(kk>=0)
+	{
+	    R d=lambda[kk]-l[kk];
+	    
+	    throwassert(d);
+	    R coef =  lambda[kk]/d;
+	    R coef1 = 1-coef;
+	    dt        = dt*coef1;
+	    lambda[0] = lambda[0]*coef1 + coef *l[0];
+	    lambda[1] = lambda[1]*coef1 + coef *l[1];
+	    lambda[2] = lambda[2]*coef1 + coef *l[2];
+	    lambda[kk] =0;
+	}
+    }
+    int jj=0;
+    R lmx=lambda[0];
+    if (lmx<lambda[1])  jj=1, lmx=lambda[1];
+    if (lmx<lambda[2])  jj=2, lmx=lambda[2];
+    if(lambda[0]<0) lambda[jj] += lambda[0],lambda[0]=0;
+    if(lambda[1]<0) lambda[jj] += lambda[1],lambda[1]=0;
+    if(lambda[2]<0) lambda[jj] += lambda[2],lambda[2]=0;
+    return kk;
+}        
+Mesh::~Mesh()
+{
+    //(cout << "   -- delete mesh " << this << endl);
+    delete  quadtree;
+    delete [] triangles;
+    delete [] vertices;
+    delete [] bedges;
+    delete [] mortars;
+    delete [] datamortars;
+    // delete [] adj;
+    delete [] TheAdjacencesLink;
+    delete [] BoundaryEdgeHeadLink;
+    delete [] BoundaryAdjacencesHead;
+    delete [] BoundaryAdjacencesLink;
+    delete []  TriangleConteningVertex;
+    delete [] bnormalv;
+    delete [] tet;
+    delete [] edges;
+}
+//  for the  mortar elements
+ int NbOfSubTriangle(int k)
+{  
+    if(k>0) return  k*k;
+    else if(k<0) return 3*(k*k);
+    ffassert(0);
+    return 0;
+}
+    
+
+ int NbOfSubInternalVertices(int kk)
+{ 
+    assert(kk);
+    int k=Abs(kk);
+    int  r= (k+2)*(k+1)/2;
+    assert(r>=0);
+    
+    return kk<0 ? 3*r : r;
+}
+
+
+
+Mesh::Mesh(int nbv,R2 * P)
+{
+    
+    TheAdjacencesLink=0;
+    BoundaryEdgeHeadLink=0;
+    BoundaryAdjacencesHead=0;
+    BoundaryAdjacencesLink=0; 
+    TriangleConteningVertex=0;              
+    TriangleConteningVertex=0;
+    dim=2;
+    tet=0;
+    edges=0;
+    ntet=0;
+    ne=0;
+    volume=0;
+    
+    quadtree =0;
+    NbMortars=0;
+    NbMortarsPaper=0;
+    nt=0;
+    mortars=0;
+    TheAdjacencesLink =0;
+    datamortars=0;
+    quadtree =0;
+    bedges=0;
+    neb =0;
+    bnormalv=0;
+    nv=nbv;
+    vertices  = new Vertex[nv];
+    triangles=0;
+    area=0;
+    for (int i=0;i<nv;i++)
+	vertices[i]=P[i];
+    bedges    =  0; 
+    area=0;
+    
+    
+    BuilTriangles(false) ;  
+    
+    ConsAdjacence();    
+    
+}
+void Mesh::BuilTriangles(bool empty,bool removeouside)
+{
+    long nba = neb;
+    // 
+    long nbsd = 0; // bofbof 
+    if(!removeouside) nbsd=1;
+    // faux just pour un test 
+    long  *sd;
+    sd=new long[2];
+    sd[0]=-1;
+    sd[1]=0;        
+    nbsd=removeouside?0:-1;
+    
+    long nbs=nv;
+    long nbsmax=nv;
+    long            err = 0;//, nbsold = nbs;       
+	long           *c = 0;
+	long           *tri = 0;
+	long           *nu = 0;
+	long           *reft = 0;
+	typedef double Rmesh;
+	Rmesh          *cr = 0;
+	Rmesh          *h = 0;
+	long nbtmax = 2 * nbsmax;
+	long * arete  = nba ? new long[2*nba] : 0; 
+	nu = new long[6*nbtmax];
+	c = new long[2*nbsmax];
+	tri = new long[(4 * nbsmax + 2 * nbsd)];
+	reft = new long[nbtmax];
+	cr = new Rmesh[(2 * nbsmax + 2)];
+	h = new Rmesh[nbsmax];
+	for(int i=0,k=0; i<nv; i++)
+	{ 
+	    cr[k++]  =vertices[i].x;
+	    cr[k++]=vertices[i].y;
+	    h[i]=1; 
+	}
+	for (int i=0,k=0 ;i<neb;i++)
+	{
+	    arete[k++] =number(bedges[i][0])+1;
+	    arete[k++] =number(bedges[i][1])+1;
+	}
+	
+	
+	extern int 
+	    mshptg8_ (Rmesh *cr, Rmesh *h, long *c, long *nu, long *nbs, long nbsmx, long *tri,
+		      long *arete, long nba, long *sd,
+		      long nbsd, long *reft, long *nbt, Rmesh coef, Rmesh puis, long *err);
+	
+	long nbt=0;
+	mshptg8_ (cr, h, c, nu, &nbs, nbs, tri, arete, nba, (long *) sd, nbsd, reft, &nbt, .25, .75, &err);
+	if(err) {
+	    cerr << " Sorry Error build delaunay triangle   error = " << err << endl;
+	    delete [] arete;
+	    delete [] nu;
+	    delete [] c;
+	    delete [] tri;
+	    delete [] reft;
+	    delete [] cr;
+	    delete [] h;
+	    delete [] sd;	   
+	    throw(ErrorExec("Error mshptg8_",1));
+	   	}
+	assert(err==0 && nbt !=0);
+	delete [] triangles;
+	nt = nbt;
+	if(verbosity>1)
+	    
+	    cout << " Nb Triangles = " << nbt << endl;
+	triangles = new Triangle[nt];
+	for(int i=0,k=0;i<nt;i++,k+=3)
+        {
+	  if( verbosity>1000)
+	    {
+	      cout << vertices[nu[k]-1]<< "  " << endl;
+	      cout << vertices[nu[k+1]-1]<< "  " << endl;
+	      cout << vertices[nu[k+2]-1]<< "  " << endl;
+	      cout << vertices[nu[k]-1]<< "  \n\n" << endl;
+	    }
+	    triangles[i].set(vertices,nu[k]-1,nu[k+1]-1,nu[k+2]-1,reft[i]);
+	    area += triangles[i].area;
+        }  
+	
+	delete [] arete;
+	delete [] nu;
+	delete [] c;
+	delete [] tri;
+	delete [] reft;
+	delete [] cr;
+	delete [] h;
+	delete [] sd;
+}
+Mesh::Mesh(const Mesh & Th,int * split,bool WithMortar,int label)
+{ //  routine complique 
+  //  count the number of elements
+    area=0; //Th.area;
+    lenbord=0;
+    volume=0;
+    BoundaryAdjacencesHead=0;
+    BoundaryAdjacencesLink=0;
+    BoundaryEdgeHeadLink=0;
+    quadtree =0;
+    NbMortars=0;
+    ntet=0;
+    ne=0;
+    dim=2;
+    tet=0;
+    edges=0;
+    mortars=0;
+    TheAdjacencesLink =0;
+    quadtree =0;
+    bedges=0;
+    neb =0;
+    bnormalv=0;
+    R2 Pmin,Pmax;
+    Th.BoundingBox(Pmin,Pmax);
+    nt=0;
+    int nebi=0; // nb arete interne 
+    int nbsdd =0;
+    int splitmin=100,splitmax=0;
+    for (int i=0;i<Th.nt;i++)
+	if(split[i]) 
+	{
+	    splitmin=Min(splitmin, split[i]);
+	    splitmax=Max(splitmax, split[i]);	    
+	    nt += NbOfSubTriangle(split[i]);
+	    area+= Th[i].area; // error Nov 2010 FH ..
+	}
+    
+    bool constsplit=splitmin==splitmax;
+    bool noregenereration = constsplit || WithMortar;
+
+    if(verbosity>2) 
+	cout << "  -  Mesh construct : from " << &Th << " split min " << splitmin 
+	    << "  max " << splitmax << ", recreate " << !noregenereration 
+	    << " label =" << label << endl;
+    
+    triangles = new Triangle[nt];
+    assert(triangles);
+    //  computation of thee numbers of vertices
+    //  on decoupe tous betement
+    // et on recolle le points ensuite 
+    // avec le quadtree qui sont sur les aretes ou les sommets 
+    //  calcul du magorant du nombre de sommets 
+    int nvmax= 0;// Th.nv;
+    { //int v;
+	KN<bool> setofv(Th.nv,false);
+	for (int i=0;i<Th.nt;i++)
+	    if ( split[i] ) 
+	    {   nbsdd++;
+		for (int j=0;j<3;j++)
+		{
+		    int jt=j,it=Th.ElementAdj(i,jt);
+		    if(it==i || it <0) neb += split[i];  //on est sur la frontiere
+		    else if  (!split[it]) neb += split[i];//le voisin ne doit pas etre decoupe
+		    else  //on est dans le domaine et le voisin doit etre decoupe
+		    {
+			int ie0,ie1;
+			Th.VerticesNumberOfEdge(Th[i],j,ie0,ie1);
+			BoundaryEdge * pbe = Th.TheBoundaryEdge(ie0,ie1);
+			if(pbe && &(*pbe)[0] == &Th(ie0))   
+			    neb += max(split[i],split[it]); // aretes frontiere (FH juillet 2005)
+			if (!pbe && (ie0 < ie1))
+			{
+			    nebi += max(split[i],split[it]); // arete interne a force ...  (FH jan 2007) 
+			   // cout << nebi << " zzzz  t" << i << " a=" << j << " taj=" << it << " sa =" <<    ie0 << " " << ie1 << " + = " << max(split[i],split[it]) << endl;
+			}
+		    }
+		}
+		for (int j=0;j<3;j++)
+		    //   if ( setofv.insert(Th(i,j) ).second ) 
+		    if ( !setofv[Th(i,j)]) 
+		    { 
+			setofv[Th(i,j)]=true;
+			//  cout << Th(i,j)  << " " ;
+			nvmax++; 
+		    }
+	    }
+		if(verbosity>4)
+		    cout << "  - nv old " << nvmax << endl;
+    }
+		
+	int nebmax=neb;
+	int nebimax=nebi;   
+	int nbsddmax=nbsdd;
+	for (int i=0;i<Th.nt;i++)
+	    if(split[i])
+		nvmax += NbOfSubInternalVertices(split[i]) -3;
+	
+	//  compute the minimal Hsize of the new mesh  
+	R hm = Th[0].h_min();
+	//  cout << " hm " << hm << endl;
+	// change h() in h_min() bug correct  july 2005 FH  ----
+	for (int it=0;it<Th.nt;it++)
+	{ 
+	    assert(split[it]>=0 && split[it]<=64);
+	    //      cout << " it = " <<it << " h " <<  Th[it].h() << " " << split[it] << " hm = " << hm <<  endl;
+	    if (split[it]) 
+		hm=Min(hm,Th[it].h_min()/(R) split[it]);
+	}
+	R seuil=hm/400.0;
+	if(verbosity>5)   
+	    cout << " seuil = " <<  seuil << " hmin = " << hm <<  endl; 
+	assert(seuil>1e-15);
+	vertices = new Vertex[nvmax];
+	assert( vertices );
+	
+	nv =0;
+	quadtree = new FQuadTree(this,Pmin,Pmax,nv); //  put all the old vertices in the quadtree 
+						     //  copy of the old vertices 
+	for (int i=0;i<Th.nt;i++)
+	    if (split[i]) 
+		for (int j=0;j<3;j++)
+		{
+		    
+		    Vertex * pV=quadtree->ToClose(Th[i][j],seuil);
+		    if (pV ==0) { 
+			// cout << Th(i,j) << " " ;
+			vertices[nv] = Th[i][j];
+			vertices[nv].normal=0;
+			quadtree->Add(vertices[nv]);
+			nv++;}
+		}
+		    // nv = Th.nv;
+		    if(verbosity>3) 
+		    {
+			cout << "  -- number of old vertices use: " << nv << endl;      
+			cout << "  -- number of  neb : " << nebmax << endl;
+		    }
+	bedges = new BoundaryEdge[nebmax];
+	BoundaryEdge * bedgesi= new BoundaryEdge[nebimax];  // jan 2007 FH
+	int * sdd= new int[Th.nt]; 
+	for (int i=0;i<Th.nt;++i)
+		sdd[i]= 0; 
+	/*   
+	    for (int i=0;i<Th.neb;i++)
+	{
+		cout << i << " " << " " << Th(Th.bedges[i][0]) << " " << Th(Th.bedges[i][1]) << endl;
+	} */
+	assert(bedges && bedgesi);
+	//  generation of the boundary edges
+	neb =0;
+	nebi=0;   //   generaztion des arete interne pour les force ...   
+	nbsdd=0;
+	//   for (int ieb=0,jj;ieb<Th.neb;ieb++)
+	for (int it=0;it<Th.nt;it++)
+	    if (  split[it] ) 
+	    {
+		// sdd[it]=-1;
+		for (int jt=0;jt<3;jt++)
+		{
+		    int jtt=jt,itt=Th.ElementAdj(it,jtt);
+		    //  cout << it <<  " " << jt << " " << jt << " " << itt << !split[itt] << endl;
+		    int ie0,ie1;
+		    Label  re(label); 
+		    Th.VerticesNumberOfEdge(Th[it],jt,ie0,ie1);
+		    //  cout << "++ ";
+		    BoundaryEdge * pbe = Th.TheBoundaryEdge(ie0,ie1);
+		    bool bbe= ( itt == it || itt <0 || !split[itt] || (pbe && &(*pbe)[0] == &Th(ie0))) ;
+		    
+		    BoundaryEdge * bbedges = bbe ? bedges : bedgesi;
+		    int &  nneb = bbe ? neb : nebi;
+		    int nnebmax = bbe ? nebmax : nebimax;
+		    int offset= bbe ? 0 : nebmax;
+		    if (bbe ||  (!pbe && (ie0 < ie1) ) ) // arete interne ou frontiere 
+		    {
+			int sens = 1; // par defaul le bon sens 
+			int kold = it;   //Th.BoundaryElement(ieb,jj);
+			int n=split[kold];
+			if( itt>=0) n = max(n,split[itt]); //  pour les aretes internes (FH juillet 2005)
+			if (!n) continue; 
+			if (pbe ) {
+			    re = *pbe;
+			    if( & (*pbe)[0] == &Th(ie1) ) sens = -sens; // pour les aretes non decoupe avril 2007
+			   // cout << " ### " << ie0 << " " << ie1 << " " <<  sens << endl;
+			}
+			// cout << " lab = " <<  re.lab << endl;
+			Vertex *pva= quadtree->NearestVertex(Th(ie0));
+			Vertex *pvb= quadtree->NearestVertex(Th(ie1));
+			Vertex *pv0=pva;
+			R2 A(*pva),B(*pvb);
+			R la = 1,lb=0, delta=1.0/n;
+			
+			for (int j=1;j<n;j++) 
+			{ 
+			    sens = 1; //  arete decoupe => le sens change avril 2007
+			    la-=delta;
+			    lb+=delta;
+			    assert(nv<nvmax);
+			    Vertex *pv1= vertices + nv;
+			    
+			    (R2 &) *pv1 = A*la + B*lb;
+			    (Label &) *pv1 = re ; //= (Label) be;
+			    quadtree->Add(*pv1);
+			    nv++;
+			    
+			    assert(nneb<nnebmax);
+			    bbedges[nneb].vertices[0]=pv0;
+			    bbedges[nneb].vertices[1]=pv1;
+			    (Label &)  bbedges[nneb] = re;
+			    nneb++;
+			    
+			    pv0=pv1;
+			}
+			//if (bbe)
+			 //   cout << nneb+1 << " yyyy  t" << it << " a=" << jt << " taj=" << itt << " sa =" <<    ie0 << " " << ie1 << " + = " << n << endl;
+
+			assert(nneb<nnebmax);
+			bbedges[nneb].vertices[0]=pv0;
+			bbedges[nneb].vertices[1]=pvb;
+			(Label &) bbedges[nneb]= re ;		         			    
+			sdd[it]= (1+ (nneb++ + offset))*sens; // numero de la derniere arete attention au sens si pas decoupe avril 2007
+			//cout << " ### " << pv0 - vertices << " " << pvb - vertices << " " <<  sens << " it = " << it << " " <<  sdd[it] << " itt " << itt  << " -- " << sdd[406] << endl;
+
+			if(  ( itt !=it || itt <0)  ) // interne 
+			   sdd[itt]= -sdd[it]; 
+		    }
+		} 
+		nbsdd++; 
+	    }
+
+		//   cout << "          (debug)  nb vertices on egdes " << nv << endl;  
+		    //  cout << " " <<  nebmax << " " << neb << endl;
+	assert(neb==nebmax);
+	assert(nebi==nebimax);
+	assert(nbsdd==nbsddmax);
+	
+	//   create the new vertices and the new triangle 
+	int   kt=0;
+	for (int K=0;K<Th.nt;K++)
+	{ // cout << K << endl;
+	    Triangle &T(Th[K]);
+	    R2 A(T[0]);
+	    R2 B(T[1]);
+	    R2 C(T[2]);
+	    long N=split[K];
+	    if (!N) continue;
+	    long N2=N*N;
+	    int vt[3];
+	    for (int n=0;n<N2;n++,kt++) //  loop on all sub triangle
+	    {
+		//(Label&) triangles[kt] = (Label&) T; 
+		for(int j=0;j<3;j++) //  Loop on the 3 vertices
+		{ 
+		    R2 PTj=SubTriangle(N,n,j);
+		    R la=1-PTj.x-PTj.y,lb=PTj.x,lc=PTj.y;
+		    R lmin = Min(la,lb,lc);
+		    R2 Pj= A*la+B*lb+C*lc; 
+		    Vertex *pV;
+		    pV=quadtree->ToClose(Pj,seuil);
+		    // if !noregenereration => point du bord du triangle deja genere 
+		    bool addv = !pV;
+		    if(!noregenereration && pV==0) addv = lmin > 1e-5;
+		    if ( addv )			
+		    { // new vertex
+		      // cout << "    -- " << nv << "  New Vertices " << Pj << " n=" << n << " j=" << j << " " << PTj << endl;
+			assert(nv<nvmax);
+			vertices[nv]=Pj;
+			(Label&) vertices[nv]=0; //  Internal vertices 
+			pV = vertices + nv;
+			quadtree->Add(*pV);
+			nv++;                  
+		    }  //  end of new vertex
+		    if(noregenereration)
+		    {
+		      assert(pV);
+		    //cout << j <<  "  " << *pV << " " << Pj << " " << number(pV) << " " << Norme2(Pj-*pV) << " " << nv << endl;
+		      vt[j]=number(pV);
+		    }
+		}
+		   
+		    //  triangles[kt].SetVertex(j,pV);
+		 // for(int j=0;j<3;j++)
+		  // cout << kt << " " << n << endl;
+		if(noregenereration)
+		{
+		    R2 A=vertices[vt[0]];
+		    R2 B=vertices[vt[1]];
+		    R2 C=vertices[vt[2]]; 
+		    R a = (( B-A)^(C-A))*0.5;
+		    
+		    if (a>0) 
+			triangles[kt].set(vertices,vt[0],vt[1],vt[2],T.lab);
+		    else 
+			triangles[kt].set(vertices,vt[0],vt[2],vt[1],T.lab);
+		}
+	    }   // end loop on all sub triangle
+	    
+	} //  end 
+	if (verbosity>3 ) 
+	{ 
+	    cout << "  - regeneration = " << ! noregenereration <<endl; 
+	    cout << "  - Nb of vertices       " << nv << endl; 
+	    cout << "  - Nb of triangle       " << nt << endl; 
+	    cout << "  - Nb of boundary edges " << neb << endl; 
+	
+	}
+	//  
+	if (!noregenereration )   // REGENRATION DU MAILLAGE 
+	{ // 
+	   // nebi=0;
+	    long nba = neb+nebi;
+	    // 
+	    long nbsd = nbsdd; // bofbof 
+			   //ok,  with correction of mshptg 
+	    long  *sd;
+	    sd=new long[2*nbsd+2];
+	    
+	    sd[0]=-1;
+	    sd[1]=Th[0].lab;         
+
+	    
+	    long nbs=nv;
+	    long nbsmax=nv;
+	    long            err = 0;//, nbsold = nbs;       
+		long           *c = 0;
+		long           *tri = 0;
+		long           *nu = 0;
+		long           *reft = 0;
+		typedef double Rmesh ;
+		Rmesh          *cr = 0;
+		Rmesh          *h = 0;
+		long nbtmax = 2 * nbsmax;
+		long * arete  = new long[2*nba]; 
+		nu = new long[6*nbtmax];
+		c = new long[2*nbsmax];
+		tri = new long[Max((4 * nbsmax + 2 * nbsd),nba)];
+		reft = new long[nbtmax];
+		cr = new Rmesh[(2 * nbsmax + 2)];
+		h = new Rmesh[nbsmax];
+		for(int i=0,k=0; i<nv; i++)
+		{ 
+		    cr[k++]  =vertices[i].x;
+		    cr[k++]=vertices[i].y;
+		    h[i]=1; 
+		}
+		{
+		    int k=0;
+		for (int i=0 ;i<neb;i++)
+		{
+		    arete[k++] =number(bedges[i][0])+1;
+		    arete[k++] =number(bedges[i][1])+1;
+		}
+		//  ajoute des aretes interne pour les forces ..  FH 
+		for (int i=0 ;i<nebi;i++)
+		{
+		    arete[k++] =number(bedgesi[i][0])+1;
+		    arete[k++] =number(bedgesi[i][1])+1;
+		}
+		}
+		// construction du tableau sd
+		
+		for (int it=0,j=0;it<Th.nt;it++)
+		    if (  split[it]) // un ssd par vieux triangle 
+		    {
+			assert(sdd[it]);
+			sd[j++]=sdd[it];
+			sd[j++] = Th[it].lab; 
+		    }
+			
+		extern int 
+		    mshptg8_ (Rmesh *cr, Rmesh *h, long *c, long *nu, long *nbs, long nbsmx, long *tri,
+			      long *arete, long nba, long *sd,
+			      long nbsd, long *reft, long *nbt, Rmesh coef, Rmesh puis, long *err);
+		
+		long nbt=0;
+		if(verbosity>10)
+		{
+		    cout << " mshptg8_ " << endl;
+		    cout << "    nbs =" << nbs << endl;
+		    cout << "    nba =" << nba << endl;
+		    cout << "    nbt =" << nbt << endl;
+		    cout << "    nbsd =" << nbsd << endl;
+		    cout << " sommets : " << endl;
+		    for(int i=0;i<nbs; ++i)
+			cout << " " << i+1 << " -- " << cr[2*i] << " " << cr[2*i+1] << endl;
+		    cout << " aretes : " << endl;
+		    for(int i=0;i<nba; ++i)
+			cout << " " << i+1 << " -- " << arete[2*i] << " " << arete[2*i+1] << endl;
+		    cout << " Sd : " << endl;
+		    for(int i=0;i<nbsd; ++i)
+			cout << " " << i+1 << " -- " << sd[2*i] << "  lab " << sd[2*i+1] << endl;
+		    //nbsd=0;
+		}
+		mshptg8_ (cr, h, c, nu, &nbs, nbs, tri, arete, nba, (long *) sd, nbsd, reft, &nbt, .25, .75, &err);
+		if( !(err==0 && nbt !=0))
+		{
+		    cerr << " Error mesh generation in mshptg : err = " << err << " nb triangles = " << nbt << endl;
+		    ffassert(err==0 && nbt !=0);
+		}
+		// 
+		
+		delete [] triangles;
+		// Correction FH bug  trunc  mesh with hole 25032005 +july 2005 
+		int kt=0;
+		R dmin=1e100;
+		for(int i=0,k=0;i<nbt;i++,k+=3)
+		{
+		    //int ir = reft[i]; 
+		    reft[i]=-1;
+		    R2 A=vertices[nu[k]-1],B=vertices[nu[k+1]-1],C=vertices[nu[k+2]-1];
+		    R2 G=(A+B+C)/3.,PHat;
+		    double d=Area2(A,B,C);
+		    dmin=min(d,dmin);
+		    //cout << A << "\n" << B << "\n" << C << "\n" << A << "\n\n";
+		    if(d<=1e-5 && 0)
+		    {
+			cout<< " T = "<<  i << " det= " << d << "  ::  " << A << " " << B << " " << C  << endl;
+			
+		    }
+		    bool outside;
+		    const Triangle * t=Th.Find(G,PHat,outside,0);
+		    if(!outside ) { 
+			int k=Th(t);
+			if( split[k] )
+			{
+			    reft[i] = k;
+			    kt++;
+			}
+		    }
+		}
+		nt=kt;
+		// cout << " " << dmin << endl;
+		if(verbosity>3)      
+		    cout << "  - Nb Triangles = " << nt <<  " remove triangle in hole :" <<  nbt - nt 
+			<<endl;
+		triangles = new Triangle[nt];
+		kt=0;
+		for(int i=0,k=0;i<nbt;i++,k+=3)
+		    if(reft[i]>=0) 
+			triangles[kt++].set(vertices,nu[k]-1,nu[k+1]-1,nu[k+2]-1,Th[reft[i]].lab);
+		assert(kt==nt);
+		// END  Correction FH bug  trunc  mesh with hole 25032005 + july 2005 
+		
+		delete [] arete;
+		delete [] nu;
+		delete [] c;
+		delete [] tri;
+		delete [] reft;
+		delete [] cr;
+		delete [] h;
+		delete [] sd;
+		
+	}
+	delete [] bedgesi;   
+	delete [] sdd;   
+	ConsAdjacence();
+}
+
+
+const char Mesh::magicmesh[8]="Mesh 2D";
+int  Mesh::kthrough =0;
+int  Mesh::kfind=0;
+
+Mesh::Mesh(const  Serialize &serialized) 
+{
+    TriangleConteningVertex =0;
+    BoundaryAdjacencesHead=0;
+    BoundaryAdjacencesLink=0;
+    BoundaryEdgeHeadLink=0;
+    quadtree =0;
+    volume=0;
+    NbMortars=0;
+    dim=0;
+    tet=0;
+    edges=0;
+    ntet=0;
+    ne=0;
+    
+    mortars=0;
+    TheAdjacencesLink =0;
+    nv=0;
+    nt =0;
+    neb=0;
+    triangles=0;
+    vertices=0;
+    bedges=0;
+    area=0;
+    lenbord=0;
+    bnormalv=0;
+    //  ---  assert(serialized.samewhat(magicmesh));
+    size_t  pp=0;;
+    long long l;
+    serialized.get(pp,l);
+    serialized.get( pp,nt);
+    serialized.get( pp,nv);
+    serialized.get( pp,neb);
+    if (verbosity>2) 
+	cout << " mesh serialized : " << l << " " << nt << " " << nv << " " << neb << endl;
+    assert ( nt > 0 && nv >0 && neb >=0);
+    triangles = new Triangle [nt];
+    vertices  = new Vertex[nv];
+    bedges    = new BoundaryEdge[neb];
+    area=0;
+    ffassert(triangles && vertices && bedges);
+    
+    for (int i=0;i<nv;i++)    
+    {
+        serialized.get(pp,vertices[i].x);
+        serialized.get(pp,vertices[i].y);
+        serialized.get(pp,vertices[i].lab);
+    }
+    for (int i=0;i<nt;i++) { 
+        int i0,i1,i2,ir;
+        serialized.get(pp,i0);
+        serialized.get(pp,i1);
+        serialized.get(pp,i2);
+        serialized.get(pp,ir);
+	
+        triangles[i].set(vertices,i0,i1,i2,ir); 
+        area += triangles[i].area;}
+    
+    for (int i=0;i<neb;i++) { 
+        int i0,i1,ir;
+        serialized.get(pp,i0);
+        serialized.get(pp,i1);
+        serialized.get(pp,ir);
+        bedges[i] = BoundaryEdge(vertices,i0,i1,ir);
+	lenbord += bedges[i].length(); }
+    assert( pp ==  serialized.size() );   
+    if(verbosity>2) 
+	cout << "   End of un serialize: area on mesh = " << area <<endl;  
+    ConsAdjacence();	
+    
+}
+
+Serialize  Mesh::serialize() const
+{
+    
+    long long  l=0;
+    l += sizeof(long long);
+    l += 3*sizeof(int);
+    l += nt*(sizeof(int)*4);
+    l += nv*( sizeof(int) + sizeof(double)*2);
+    l += neb*(sizeof(int)*3);
+    
+    // cout << l << magicmesh << endl;
+    Serialize  serialized(l,magicmesh);
+    // cout << l << magicmesh << endl;
+    size_t pp=0;
+    serialized.put(pp, l); 
+    serialized.put( pp,nt);
+    serialized.put( pp,nv);
+    serialized.put( pp,neb);
+    if (verbosity>2) 
+      cout << " mesh Serialized : " << l << " "  << nt << " " << nv << " " << neb << endl;
+    for (int i=0;i<nv;i++)
+    {
+	serialized.put(pp, vertices[i].x);
+	serialized.put(pp, vertices[i].y);
+	serialized.put(pp, vertices[i].lab);
+    }
+    //cout << " ---  " << endl;
+    for (int i=0;i<nt;i++)
+    {
+	const Triangle & K(triangles[i]);
+	int i0= &K[0]-vertices;
+	int i1= &K[1]-vertices;
+	int i2= &K[2]-vertices;
+	serialized.put(pp, i0);
+	serialized.put(pp, i1);
+	serialized.put(pp, i2);
+	serialized.put(pp, K.lab);
+    }
+    // cout << " ---  " << endl;
+    for (int i=0;i<neb;i++)
+    {
+	const BoundaryEdge & K(bedges[i]);
+	int i0= &K[0]-vertices;
+	int i1= &K[1]-vertices;
+	serialized.put(pp, i0);
+	serialized.put(pp, i1);
+	serialized.put(pp, K.lab);
+    }
+    //  cout << " ---  " << endl;
+    // cout << pp << " == " << serialized.size() << endl;
+    assert(pp==serialized.size());
+    return serialized; 
+}
+
+void Mesh::Buildbnormalv()
+{
+    if (bnormalv) 
+    {assert(0);return;}
+    int nb=0;
+    for (int k=0;k<nt;k++)
+	for (int i=0;i<3;i++)
+	{  
+	    int ii(i),kk;
+	    kk=ElementAdj(k,ii);
+	    if (kk<0 || kk==k) nb++;
+	}
+	    if(verbosity>2)
+		cout << " number of real boundary edges " << nb << endl;
+    bnormalv= new R2[nb];
+    R2 *n=bnormalv;
+    for (int k=0;k<nt;k++)
+	for (int i=0;i<3;i++)
+	{  
+	    int ii(i),kk;
+	    kk=ElementAdj(k,ii);
+	    if (kk<0 || kk==k) {
+		Triangle & K(triangles[k]);
+		R2 N=K.n(i);
+		Vertex & v0= K.Edge(0,i);
+		Vertex & v1= K.Edge(1,i);
+		v0.SetNormal(n,N);
+		v1.SetNormal(n,N);         
+	    }
+	}
+	    // cout << nb << " == " << n-bnormalv << endl;
+	    assert(n - bnormalv <= nb );
+}
+}
+//  static const R2 Triangle::Hat[3]= {R2(0,0),R2(1,0),R2(0,1)} ; 
diff --git a/src/femlib/fem.hpp b/src/femlib/fem.hpp
new file mode 100644
index 0000000..f8abe95
--- /dev/null
+++ b/src/femlib/fem.hpp
@@ -0,0 +1,708 @@
+#ifndef FEM2_H_
+#define FEM2_H_
+#include <string> 
+#include <cstring> 
+#include "RefCounter.hpp"
+#include "Serialize.hpp"
+// some usefull function 
+
+//typedef double R;
+
+
+template<class K> class KN_;
+
+const  double Pi =  3.14159265358979323846264338328;
+/*
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
+
+template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;}
+template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
+template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
+*/
+
+//#include "ufunction.hpp" 
+#include "ufunction.hpp" 
+
+#include <utility>
+#include <algorithm>
+#include <complex>
+
+// ALH - 21/10/13 - R1.hpp needs cmath and it does include it, but since R1.hpp is only included as part of namespace
+// Fem2D, we need to make sure that cmath is called as part of the default namespace, otherwise we will get "error:
+// ‘::acos’ has not been declared" and such.
+
+#include <cmath>
+
+// definition R
+namespace Fem2D 
+{
+
+inline double norm(double x){return x*x;} 
+inline float norm(float x){return x*x;}
+template<class T> T  norm(const complex<T> &x){return std::norm(x);}
+
+  // ALH - These include files are located inside the namespace definition on purpose?
+
+#include "R1.hpp"
+#include "R2.hpp"
+#include "R3.hpp"
+
+
+inline void MoveTo(R2 P) { rmoveto((float) P.x,(float)P.y);}
+inline void LineTo(R2 P) { rlineto((float)P.x,(float)P.y);}
+
+inline R Area2(const R2 A,const R2 B,const R2 C){return (B-A)^(C-A);} 
+inline R Theta(R2 P){ return atan2(P.y,P.x);}
+  /*
+inline R2 Minc(const R2 & A,const R2& B) { return R2(Min(A.x,B.x),Min(A.y,B.y));}
+inline R2 Maxc(const R2 & A,const R2& B) { return R2(Max(A.x,B.x),Max(A.y,B.y));}
+inline R3 Minc(const R3 & A,const R3& B) { return R3(Min(A.x,B.x),Min(A.y,B.y),Min(A.z,B.z));}
+inline R3 Maxc(const R3 & A,const R3& B) { return R3(Max(A.x,B.x),Max(A.y,B.y),Max(A.z,B.z));}
+inline R2 Minc(const R2 & A,const R2& B,const R2& C) { return R2(Min(A.x,B.x,C.x),Min(A.y,B.y,C.y));}
+inline R2 Maxc(const R2 & A,const R2& B,const R2& C) { return R2(Max(A.x,B.x,C.x),Max(A.y,B.y,C.y));}
+inline R3 Minc(const R3 & A,const R3& B,const R3& C) { return R3(Min(A.x,B.x,C.x),Min(A.y,B.y,C.y),Min(A.z,B.z,C.z));}
+inline R3 Maxc(const R3 & A,const R3& B,const R3& C) { return R3(Max(A.x,B.x,C.x),Max(A.y,B.y,C.y),Max(A.z,B.z,C.z));}
+  */
+// def de numerotation dans un triangles direct sens (trigo)
+// the edge is oposite of the vertex
+////  [3] is a edge
+//#include <Functional>
+struct SortedTriplet {
+    static const int  empty = -1;
+    int i1,i2,i3;
+    SortedTriplet(int j1,int j2=empty, int j3=empty) : i1(j1), i2(j2),i3(j3) {
+	if(i1<i2) Exchange(i1,i2);
+	if(i2<i3) Exchange(i2,i3);
+	if(i1<i2) Exchange(i1,i2);
+    }
+    bool operator < (const SortedTriplet & t)  const
+    {  return  i1==t.i1 ? (  i2== t.i2 ? i3 <t.i3 : i2 < t.i2 ) : i1 < t.i1; }
+    bool operator == (const SortedTriplet & t)  const
+    {  return  i1==t.i1  &&   i2== t.i2 &&  i3 == t.i3;}
+    bool operator != (const SortedTriplet & t)  const
+    {  return  i1!=t.i1  ||   i2!= t.i2 ||  i3 != t.i3; }
+    
+    size_t hash() const {
+	size_t res=0, i=1;
+	res += i1*i;
+	if( i2 !=empty)
+	    res += i2*(i<<8);
+	if( i3 !=empty)
+	    res += i3*( i <<16) ;
+	return res;
+    }
+};
+
+
+ const short VerticesOfTriangularEdge[3][2] = {{1,2},{2,0},{0,1}};
+ //  [3] is a vertices 
+ const short EdgesVertexTriangle[3][2] = {{1,2},{2,0},{0,1}};
+ const short OppositeVertex[3] = {0,1,2};
+ const short OppositeEdge[3] =  {0,1,2};
+ const short NextEdge[3] = {1,2,0};
+ const short PreviousEdge[3] = {2,0,1};
+ const short NextVertex[3] = {1,2,0};
+ const short PreviousVertex[3] = {2,0,1};
+ //  array to same is some onwhat is on edge for boundary condition
+ // is on a edge i  onwhat is in [0,7[ 
+ // 2  on edge 1 and   
+ const int onWhatIsEdge[3][7] = {  {0,1,3, 2,0,0, 0}, // edge 0 
+                                   {3,0,1, 0,2,0, 0},
+                                   {1,3,0, 0,0,2, 0}};
+                                  
+static   R2 TriangleHat[3]= { R2(0.,0.),R2(1.,0.),R2(0.,1.) } ;
+
+
+
+
+ const short int v_tet_face[4][3]=  {{3,2,1},{0,2,3},{ 3,1,0},{ 0,1,2}};
+ const short int a_tet_face[4][3]=  {{ 0,1,0},{ 0,2,0},{ 0,3,1},{ 1,2,1}};
+ const bool  sig_tet_face[4][3]=  {{ 0,1,0},{ 1,0,1},{ 0,1,0},{ 1,0,1}};
+ const short int v_tet_edge[6][2]= {{ 1,2},{1,3},{1,4},{2,3},{2,4},{3,4}}; 
+ const short int fadj_tet_edge[6][2]= {{4,3},{2,4},{3,2},{4,1},{1,3},{2,1}};
+ const short int op_tet_edge[6]={ 6, 5, 4, 3, 2, 1}; 
+ 
+const   R3 TetHat[4]= { R3(0.,0.,0.),R3(1.,0.,0.),R3(0.,1.,0.),R3(0.,0.,1.) } ; 
+
+ class Mesh;                                  
+// --------
+#include "Label.hpp"
+
+  
+template<class Rd>
+class TVertex : public Rd,public Label {
+ friend class Mesh;
+   Rd *normal; // pointeur sur la normal exterieur pour filtre les
+   // point de depart 
+public:
+  TVertex() : Rd(),Label(),normal(0){};
+  TVertex(Rd P,int r=0): Rd(P),Label(r),normal(0){}
+  bool ninside(const Rd & P) const { return normal? (Rd(*this,P),*normal)<=0: true;}
+  void SetNormal(Rd *&n,const Rd & N)
+     { if (normal) { 
+         Rd NN=*normal+N; 
+         *normal= NN/Norme2(NN); }
+       else *(normal=n++)=N;}
+  Rd Ne() const {return normal ? *normal: Rd();}
+//  void operator=(const TVertex & v) { x=v.x;y=v.y;lab=v.lab;normal=0;}
+};
+
+typedef TVertex<R2> Vertex;
+
+template<class Rd>
+inline ostream& operator <<(ostream& f, const TVertex<Rd> & v )
+  { f << (Rd) v << ' ' << (Label) v   ; return f; }
+template<class Rd>
+inline istream& operator >> (istream& f,  TVertex<Rd> & v )
+  { f >> (Rd&) v >> (Label&) v ; return f; }
+
+
+
+class Tetraedre: public Label {
+ 
+ public:
+ typedef TVertex<R3> Vertex;
+ private:
+  Vertex *vertices[4]; // an array of 3 pointer to vertex
+public:
+  R volume;
+  Tetraedre(){};              // constructor empty for array
+  static const int NbWhat = 15; // 4+6+4+1 
+  static const int NbV =4;
+  static const int NbE =6;
+  static const int NbF =4;
+  
+  Vertex & operator[](int i) const// to see triangle as a array of vertex
+       {return *vertices[i];} 
+       
+  Vertex *& operator()(int i) // to see triangle as a array of vertex
+       {return vertices[i];} 
+  
+  Tetraedre(Vertex * v0,int i0,int i1,int i2,int i3,int r,R a=0.0): Label(r) 
+     { set(v0,i0,i1,i2,i3,r,a);  }
+
+  void set(Vertex * v0,int i0,int i1,int i2,int i3,int r,R a=0.0)
+     { R3 A=*(vertices[0]=v0+i0);
+       R3 B=*(vertices[1]=v0+i1);
+       R3 C=*(vertices[2]=v0+i2); 
+       R3 D=*(vertices[3]=v0+i3); 
+	 lab = r;
+       volume = a ==0 ? det(R3(A,B),R3(A,C),R3(A,D))/6. : a;
+       throwassert(volume>0);}
+            
+  Vertex & Face(int j,int i) const // Vertex j of ace i
+     {assert(j<=0   && j < 3 && i <=0 && i < 4) ;return  *vertices[v_tet_face[i][j] ];}
+  
+  R3 N2areaInternal(int i) const { return R3(*vertices[v_tet_face[i][0]],*vertices[v_tet_face[i][1]]) 
+                                 ^R3(*vertices[v_tet_face[i][0]],*vertices[v_tet_face[i][2]]) ; }
+  R3 n(int i) const //  unit exterior normal
+     {R3 Ni=N2areaInternal(i);return Ni/-Norme2(Ni);} 
+  
+  R3 H(int i)  const  // heigth ($\nabla \lambda_i$ 
+     {R3 Ni=N2areaInternal(i);return Ni/(3.*volume);} 
+     
+  R3 Edge(int i) const //  edge  i
+     { return (R3) *vertices[v_tet_edge[i][1]]-(R3) *vertices[v_tet_edge[i][0]];}
+     
+  Vertex & Edge(int j,int i) const // Vertex j of edge i
+     {assert(j<=0   && j < 2 && i <=0 && i < 4) ;return  *vertices[v_tet_edge[i][j]];}
+  R lenEdge(int i) const {R3 E=Edge(i);return sqrt((E,E));}
+  R h() const { return Max( Max(lenEdge(0),lenEdge(1),lenEdge(2)),
+                            Max(lenEdge(3),lenEdge(4),lenEdge(5)) );}
+  
+  void Renum(Vertex   *v0, long * r)  { 
+    for (int i=0;i<4;i++) 
+      vertices[i]=v0+r[vertices[i]-v0];}
+      
+  Vertex & VerticeOfEdge(int i,int j) const  // vertex j of edge i 
+    {return  *vertices[v_tet_edge[i][j]];}  // vertex j of edge i 
+ 
+    R EdgeOrientation(int i) const { // return +1 or -1 
+     R Orient[2]={-1.,1.};
+    return  Orient[vertices[v_tet_edge[i][0]] < vertices[v_tet_edge[i][1]] ] ;}
+    
+  void SetVertex(int j,Vertex *v){vertices[j]=v;}
+
+  R3 operator() (const R3 & P) const{ // local to Global in triangle 
+      return    (const R3 &) *vertices[0] * (1-P.x-P.y-P.z) 
+             +  (const R3 &) *vertices[1] * (P.x) 
+             +  (const R3 &) *vertices[2] * (P.y) ;
+             +  (const R3 &) *vertices[3] * (P.z) ;}
+  
+  SortedTriplet what(int i,Vertex *v0,Tetraedre * t0) { 
+      if (i<0) ffassert(i>=0);
+      else if  (i<4) return SortedTriplet(vertices[i]-v0);
+      else if( (i-=4)<6) return SortedTriplet( &Edge(0,i)-v0, &Edge(1,i)-v0);
+      else if( (i-=6)<4) return SortedTriplet( &Face(0,i)-v0, &Face(1,i)-v0, &Face(2,i)-v0) ;
+      else if(i==0) return SortedTriplet(vertices[0]-v0,this-t0,-2);
+      else ffassert(0);
+      return 0;
+  }
+private:
+  Tetraedre(const Tetraedre &);  //  no copy of triangle
+  void operator=(const Tetraedre &);             
+
+};
+
+
+template<class Rd>
+class TTriangle: public Label {
+ public:
+ typedef TVertex<Rd> Vertex;
+ private:
+  Vertex *vertices[3]; // an array of 3 pointer to vertex
+public:
+  static const int NbWhat = 7; // 3+3+1 
+  static const int NbV = 3; // 3+3+1 
+  static const int NbE = 3; //
+  R area;
+  TTriangle(){};              // constructor empty for array
+  Vertex & operator[](int i) const// to see triangle as a array of vertex
+       {return *vertices[i];} 
+       
+  Vertex *& operator()(int i) // to see triangle as a array of vertex
+       {return vertices[i];} 
+  
+  TTriangle(Vertex * v0,int i0,int i1,int i2,int r,R a=0.0): Label(r) 
+     { Rd A=*(vertices[0]=v0+i0);
+       Rd B=*(vertices[1]=v0+i1);
+       Rd C=*(vertices[2]=v0+i2); 
+       area = a ==0 ? (( B-A)^(C-A))*0.5 : a;
+       throwassert(area>0);}
+
+  void set(Vertex * v0,int i0,int i1,int i2,int r,R a=0.0)
+     { lab=r; 
+       Rd A=*(vertices[0]=v0+i0);
+       Rd B=*(vertices[1]=v0+i1);
+       Rd C=*(vertices[2]=v0+i2); 
+       area = a ==0 ? (( B-A)^(C-A))*0.5 : a;
+       ffassert(area>0);}
+       
+  Rd Edge(int i) const // opposite edge vertex i
+     {return (Rd) *vertices[(i+2)%3]-(Rd) *vertices[(i+1)%3];}
+     
+  Vertex & Edge(int j,int i) const // Vertex j of edge i
+     {throwassert(j==0 || j==1 );return  *vertices[(i+j+1)%3];}
+
+// il y a un problem sur d=3 ici ----  
+  Rd n(int i) const //  unit exterior normal
+     {Rd E=Edge(i);return Rd(E.y,-E.x)/Norme2(E);} 
+  
+  Rd H(int i)  const  // heigth ($\nabla \lambda_i$ 
+     {Rd E=Edge(i);return Rd(-E.y,E.x)/(2*area);} 
+// ------     
+  R lenEdge(int i) const {Rd E=Edge(i);return sqrt((E,E));}
+  R lenEdge2(int i) const {Rd E=Edge(i);return ((E,E));}
+  R h() const { return sqrt(Max(lenEdge2(0),lenEdge2(1),lenEdge2(2)));}
+  R h_min() const { return sqrt(Min(lenEdge2(0),lenEdge2(1),lenEdge2(2)));}
+
+  SortedTriplet what(int i,Vertex *v0,TTriangle * t0) { 
+      if (i<0) ffassert(i>=0);
+      else if  (i<3) return SortedTriplet(vertices[i]-v0);
+      else if( (i-=3)<3) return SortedTriplet( &Edge(i,0)-v0, &Edge(i,1)-v0);
+      else if( i==0 ) return SortedTriplet( vertices[0]-v0, vertices[1]-v0, vertices[2]-v0) ;
+      else ffassert(0);
+  }
+  
+  void Renum(Vertex   *v0, long * r)  { 
+    for (int i=0;i<3;i++) 
+      vertices[i]=v0+r[vertices[i]-v0];}
+      
+  Vertex & VerticeOfEdge(int i,int j) const  // vertex j of edge i 
+    {return  *vertices[(i+1+j)%3];}  // vertex j of edge i 
+
+    R EdgeOrientation(int i) const { // return +1 or -1 
+     R Orient[2]={-1.,1.};
+    return  Orient[vertices[ (i+1)%3] < vertices[ (i+2)%3] ] ;}
+    
+  bool intersect(Rd P,Rd Q) const 
+   { 
+     const Rd &A(*vertices[0]);
+     const Rd &B(*vertices[1]);
+     const Rd &C(*vertices[2]);
+     Rd mn(Minc(A,B,C)),  mx(Maxc(A,B,C));
+     assert(P.x < Q.x && P.y < Q.y ); 
+     return (mx.x >= P.x) && (mn.x <= Q.x) &&  (mx.y >= P.y) && (mn.y <= Q.y)  ;
+
+   }
+     
+//  const Vertex & VerticeOfEdge(int i,int j) const {return  *vertices[(i+1+j)%3];}      
+  void Draw(double shink=1) const;
+  void Fill(int color) const;
+  void Draw(int edge,double shink=1) const;
+  void SetVertex(int j,Vertex *v){vertices[j]=v;}
+  Rd operator() (const Rd & P) const{ // local to Global in triangle 
+      return    (const Rd &) *vertices[0] * (1-P.x-P.y) 
+             +  (const Rd &) *vertices[1] * (P.x) 
+             +  (const Rd &) *vertices[2] * (P.y) ;}
+private:
+  TTriangle(const TTriangle &);  //  no copy of triangle
+  void operator=(const TTriangle &);             
+
+};
+
+typedef TTriangle<R2> Triangle;
+
+template<class Rd>
+class TBoundaryEdge: public Label {
+public:
+ typedef TVertex<Rd> Vertex;
+    static const int NbWhat = 3; // 3+3+1 
+    static const int NbV = 2; // 3+3+1 
+    static const int NbE = 1; //
+    
+  Vertex *vertices[2];
+  TBoundaryEdge(Vertex * v0,int i0,int i1,int r): Label(r) 
+  { vertices[0]=v0+i0; vertices[1]=v0+i1; }
+  void set(Vertex * v0,int i0,int i1,int r)
+  { lab=r,vertices[0]=v0+i0; vertices[1]=v0+i1; }
+  bool in(const Vertex * pv) const {return pv == vertices[0] || pv == vertices[1];}
+  TBoundaryEdge(){}; // constructor empty for array 
+  void Draw() const;
+  Vertex & operator[](int i) const {return *vertices[i];}
+  R length() const { return Norme2(R2(*vertices[0],*vertices[1]));}
+  void Renum(Vertex   *v0, long * r) { 
+    for (int i=0;i<2;i++) 
+      vertices[i]=v0+r[vertices[i]-v0];}
+  
+  SortedTriplet what(int i,Vertex *v0,TBoundaryEdge * t0) { 
+      if (i<0) ffassert(i>=0);
+      else if  (i<2) return SortedTriplet(vertices[i]-v0);
+      else if( i==0 ) return SortedTriplet( vertices[0]-v0, vertices[1]-v0) ;
+      else ffassert(0);
+  }
+  
+};
+
+typedef TBoundaryEdge<R2> BoundaryEdge;
+typedef BoundaryEdge Edge;
+  // typedef Tetraedre Tet;  // just to play
+
+template<class Rd>
+class TMortar { 
+  public:
+ typedef TVertex<Rd> Vertex;  
+  friend class Mesh;
+  friend class ConstructDataFElement;
+   Mesh * Th;
+   int nleft,nright;
+   int *left,*right;
+   TMortar(): Th(0),nleft(0),nright(0),left(0),right(0){}
+   void Draw() const;
+   public:
+     int NbLeft() const{return nleft;} 
+     int NbRight() const{return nright;} 
+     int TLeft(int i) const { return left[i]/3;}
+     //   
+     int NbT() const {return nleft+nright;} 
+     int T_e(int i,int & e)  const { // return the triangle number + the edge number 
+        throwassert(i>=0 && i < nleft+nright);
+        int k= (i<nleft ? left[i]: right[i-nleft]);
+        e=k%3;
+        return k/3;}
+     int ELeft(int i) const { return left[i]%3;}
+     int TRight(int i) const { return right[i]/3;}
+     int ERight(int i) const { return right[i]%3;}
+     
+     //  warning  i is in [0, nleft]
+     Vertex & VLeft(int i) const ;
+     Vertex & VRight(int i) const;
+     
+     
+};
+typedef TMortar<R2> Mortar;
+
+ 
+class FQuadTree;
+
+  // <<class Mesh>>
+
+class Mesh: public RefCounter { 
+public:
+  
+  typedef TTriangle<R2> Triangle;
+  typedef TTriangle<R2> Element;
+  typedef BoundaryEdge  BorderElement; 
+  typedef TVertex<R2>  Vertex;
+  typedef  R2 Rd;
+  typedef R2  RdHat;// for parametrization 
+  typedef Rd::R R;
+  typedef FQuadTree GTree;
+  
+
+  static const char magicmesh[8]  ;
+  int dim; 
+  int nt,nv,neb,ne,ntet;
+  R area;
+  R volume;
+  R lenbord;
+  static int kthrough,kfind;
+  FQuadTree *quadtree; 
+  Vertex *vertices;
+  Triangle *triangles;
+  BoundaryEdge  *bedges;
+  Edge  *edges;  // edge element 
+  Tetraedre * tet; // 
+
+    int nbElmts() const {return nt;}
+    int nbBrdElmts() const {return neb;}
+    int nbVertices() const {return nv;}
+    
+  int NbMortars,NbMortarsPaper;
+  Mortar *mortars; //  list of mortar
+  int    *datamortars;
+  R2  * bnormalv; //  boundary vertex normal 
+  //Triangle * adj;
+  Triangle & operator[](int i) const {throwassert(i>=0 && i<nt);return triangles[i];}
+ // const Triangle & operator[](int i) const {return triangles[i];}
+  Vertex & operator()(int i) const {throwassert(i>=0 && i<nv);return vertices[i];}
+  Mesh(const char * filename) {read(filename);} // read on a file
+  Mesh(const string s) {read(s.c_str());}
+  Mesh( const Serialize & ) ;
+  Mesh(int nbv,R2 * P);
+
+  R mesure(){ return area;}
+  R bordermesure(){ return lenbord;}
+  
+  Serialize serialize() const;
+  Mesh(int nbv,int nbt,int nbeb,Vertex *v,Triangle *t,BoundaryEdge  *b);  
+  Mesh(const Mesh & Thold,int *split,bool WithMortar=true,int label=1);
+  ~Mesh();
+  int number(const Triangle & tt) const {return &tt - triangles;}
+  int number(const Triangle * tt) const {return tt- triangles;}
+  int number(const Vertex & vv)   const {return &vv - vertices;}
+  int number(const Vertex * vv)   const {return vv  - vertices;}
+  int operator()(const Triangle & tt) const {return &tt - triangles;}
+  int operator()(const Triangle * tt) const {return tt  - triangles;}
+  int operator()(const Vertex & vv)   const {return &vv - vertices;}
+  int operator()(const Vertex * vv)   const {return vv  - vertices;}
+  int operator()(const BoundaryEdge & be)   const {return &be- bedges;}//  add FH 04/07/09
+  int operator()(const BoundaryEdge * be)   const {return be  - bedges;}//  add FH 04/07/09
+    
+  int operator()(int it,int j) const {return number(triangles[it][j]);}
+  BoundaryEdge &  be(int i) const { return bedges[i];}
+  Element &  t(int i) const { return triangles[i];}
+  Vertex &  v(int i) const { return vertices[i];}
+
+        // Nu vertex j of triangle it
+  void BoundingBox(R2 & Pmin,R2 &Pmax) const;
+  void InitDraw() const ;
+  void Draw(int init=2,bool fill=false) const;
+  void DrawBoundary() const; 
+  int Contening(const Vertex * vv) const{ return TriangleConteningVertex[ vv  - vertices];}
+  int renum();
+  int gibbsv (long* ptvoi,long* vois,long* lvois,long* w,long* v);
+  int ElementAdj(int it,int &j) const 
+      {int i=TheAdjacencesLink[3*it+j];j=i%3;return i/3;}
+  int BorderElementAdj(int i, int j) const 
+      {
+	// be: border index, i and j index of vertex of be, i index of common vertex
+	int p2=-1;
+	for (int p=BoundaryAdjacencesHead[i];p>=0;p=BoundaryAdjacencesLink[p])
+	  { 
+	    if ( !bedges[p2=p/2].in(vertices+j) )   return p2;
+	  }
+      return -1;} // Add J. Morice
+  int nTonEdge(int it,int e) const { int k=3*it+e;return k==TheAdjacencesLink[k] ? 1 : 2;}
+      
+  void VerticesNumberOfEdge(const Triangle & T,int j,int & j0,int & j1) const 
+      {j0 =  number(T[(j+1)%3]),j1=  number(T[(j+ 2)%3]);}
+  bool SensOfEdge(const Triangle & T,int j) const 
+      { return  number(T[(j+1)%3]) <number(T[(j+ 2)%3]);}
+      
+  int GetAllElementAdj(int it,int *tabk) const
+   { //  get the tab of all adj triangle to a traingle (max 3)
+     //  and return the size of the tab 
+      int i=0;
+      tabk[i]=TheAdjacencesLink[3*it+0]/3;
+      if(tabk[i] >=0 && tabk[i]!=it) i++; 
+      tabk[i]=TheAdjacencesLink[3*it+1]/3;
+      if(tabk[i] >=0 && tabk[i]!=it) i++; 
+      tabk[i]=TheAdjacencesLink[3*it+2]/3;
+      if(tabk[i] >=0 && tabk[i]!=it) i++; 
+      return i;
+   }
+      
+  int BoundaryElement(int bbe,int & edgeInT) const {
+     int i= BoundaryEdgeHeadLink[bbe]; edgeInT = i%3; 
+     return i/3;}
+
+     
+  Triangle * Find(const R2 & P) const ;
+  const Triangle * Find(R2 P, R2 & Phat,bool & outside,const Triangle * tstart=0) const  ;
+  
+  BoundaryEdge * TheBoundaryEdge(int i,int j)  const
+   {  
+    int p2;
+    for (int p=BoundaryAdjacencesHead[i];p>=0;p=BoundaryAdjacencesLink[p])
+     { 
+     if ( bedges[p2=p/2].in(vertices+j) )   return bedges+p2;
+     }
+     
+    return 0;}
+
+  int NumberOfTheBoundaryEdge(int i,int j)  const
+   {  
+    int p2;
+    for (int p=BoundaryAdjacencesHead[i];p>=0;p=BoundaryAdjacencesLink[p])
+     { 
+     if ( bedges[p2=p/2].in(vertices+j) )   return p2;
+     }
+     
+    return -1;}// Add J. Morice
+
+ void destroy() {RefCounter::destroy();}
+ void MakeQuadTree() ;
+      
+private:
+  void read(const char * filename); 
+  void read(ifstream & f,bool bin=false); 
+  void BuildBoundaryAdjacences();
+  void ConsAdjacence();
+  void Buildbnormalv(); 
+  void BuilTriangles(bool empty,bool removeoutside=true);
+  // to construct the adj triangle               
+  int *TheAdjacencesLink;
+  int *BoundaryEdgeHeadLink;
+  int *BoundaryAdjacencesHead;
+  int *BoundaryAdjacencesLink; 
+  int *TriangleConteningVertex;       
+
+  // <<no_mesh_copy>> the copy constructor for Mesh is kept private on purpose
+  Mesh(const Mesh &);
+
+  void operator=(const Mesh &);       
+};
+
+
+//  2 routines to compute the caracteristic
+int WalkInTriangle(const Mesh & Th,int it, double *lambda,
+                   const  KN_<R> & U,const  KN_<R> & V, R & dt);
+int  WalkInTriangle(const Mesh & Th,int it, double *lambda,
+                     R u, R v, R & dt); 
+                   
+int Walk(const Mesh & Th,int & it, R *l,
+         const KN_<R>  & U,const KN_<R>  & V, R dt) ;
+ 
+void DrawMark(R2 P,R k=0.02);
+
+         
+template<class T>
+void  HeapSort(T *c,long n)
+{
+  long l,j,r,i;
+  T crit;
+  c--; // on decale de 1 pour que le tableau commence a 1
+  if( n <= 1) return;
+  l = n/2 + 1;
+  r = n;
+  while (1) { // label 2
+    if(l <= 1 ) { // label 20
+      crit = c[r];
+      c[r--] = c[1];
+    if ( r == 1 ) { c[1]=crit; return;}
+    } else  crit = c[--l]; 
+    j=l;
+    while (1) {// label 4
+      i=j;
+      j=2*j;
+      if  (j>r) {c[i]=crit;break;} // L8 -> G2
+      if ((j<r) && (c[j] < c[j+1])) j++; // L5
+      if (crit < c[j]) c[i]=c[j]; // L6+1 G4
+      else {c[i]=crit;break;} //L8 -> G2
+    }
+  }
+}
+
+template<class T,class T1,class T2>
+void  HeapSort(T *c,T1 *c1,T2 *c2,long n)
+{
+  long l,j,r,i;
+  T crit;  T1 crit1;  T2 crit2;
+  c--;c1--;c2--; // on decale de 1 pour que le tableau commence a 1
+  if( n <= 1) return;
+  l = n/2 + 1;
+  r = n;
+  while (1) { // label 2
+    if(l <= 1 ) { // label 20
+      crit = c[r];     crit1 = c1[r];  crit2 = c2[r];
+      c2[r] = c2[1];   c1[r] = c1[1];  c[r--] = c[1];
+    if ( r == 1 ) { c2[1] = crit2,   c1[1] = crit1; c[1]=crit; return;}
+    } else  {crit = c[--l];crit1=c1[l];crit2=c2[l]; }
+    j=l;
+    while (1) {// label 4
+      i=j;
+      j=2*j;
+      if  (j>r) {c[i]=crit;c1[i]=crit1;c2[i]=crit2;break;} // L8 -> G2
+      if ((j<r) && (c[j] < c[j+1])) j++; // L5
+      if (crit < c[j]) {c[i]=c[j];c1[i]=c1[j];c2[i]=c2[j];} // L6+1 G4
+      else {c[i]=crit;c1[i]=crit1;c2[i]=crit2;break;} //L8 -> G2
+    }
+  }
+}
+
+ inline   int numSubTVertex(int N,int i,int j)
+    {  //  i,j  coordonne barycentre * N dans l'eleùent de reference.
+	i=i+j; // numerotation / diag  
+	// i,j 
+	assert(j<=i && 0<= j); 
+	return j+i*(i+1)/2;
+    }
+    
+ inline    void  num1SubTVertex(int N,int l,int & i,int & j)
+    {
+	
+      i= (int) ((-1 + sqrt(1.+8*l))/2); //  modif gcc 3.3.3  FH 100109
+	j = l - i*(i+1)/2;
+        // io=in+j;
+	// in = io-j
+	i=i-j;
+	assert( l == numSubTVertex(N,i,j)); 
+    }
+    
+  R2 SubTriangle(const int N,const int n,const int l);
+    int numSubTriangle(const int N,const int n,const int l);
+  int  NbOfSubTriangle(const int N);
+  int NbOfSubInternalVertices(int kk);
+  R2  SubInternalVertex(int N,int k);
+    
+      //  warning  i is in [0, nleft]
+template<class Rd>
+ inline     TVertex<Rd> & TMortar<Rd>::VLeft(int i) const 
+  { throwassert(i>=0 && i <= nleft);
+    return i< nleft ? (*Th)[TLeft( i  )][VerticesOfTriangularEdge[ELeft(i)][0]]
+                    : (*Th)[TLeft( i-1)][VerticesOfTriangularEdge[ELeft(i-1)][1]];}
+template<class Rd>
+ inline TVertex<Rd> & TMortar<Rd>::VRight(int i) const 
+  { throwassert(i>=0 && i <= nright);
+    return i< nright ? (*Th)[TRight( i  )][VerticesOfTriangularEdge[ERight(i)][1]]
+                     : (*Th)[TRight( i-1)][VerticesOfTriangularEdge[ERight(i-1)][0]];}
+
+ void DrawCommentaire(const char *cm,float x=0.1,float y=0.97) ;
+ 
+inline R2 minmax(const R2 & a,const R2 & b) 
+  {return R2(Min(a.x,b.x),Max(a.y,b.y));}
+
+
+}
+
+using Fem2D::R; 
+
+#include "FQuadTree.hpp"
+
+namespace Fem2D {
+
+inline void Mesh::MakeQuadTree() 
+  {
+    if (!quadtree) {
+        R2 Pn,Px;
+        BoundingBox(Pn,Px);
+        quadtree=new FQuadTree(this,Pn,Px,nv);
+    } 
+ }
+
+}
+
+#endif
diff --git a/src/femlib/fem3.hpp b/src/femlib/fem3.hpp
new file mode 100644
index 0000000..38f6e4f
--- /dev/null
+++ b/src/femlib/fem3.hpp
@@ -0,0 +1 @@
+to remove
\ No newline at end of file
diff --git a/src/femlib/gibbs.cpp b/src/femlib/gibbs.cpp
new file mode 100644
index 0000000..e898a24
--- /dev/null
+++ b/src/femlib/gibbs.cpp
@@ -0,0 +1,1253 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <cmath>
+#include "error.hpp"
+#include <iostream>
+#include <fstream>
+#include "RNM.hpp"
+#include "rgraph.hpp"
+#include "fem.hpp"
+using namespace Fem2D;
+#include "FESpacen.hpp"
+#include "FESpace.hpp"
+
+#define mmax(a,b)(a>b?a:b)
+#define mmin(a,b)(a<b?a:b)
+#define ffalse 0
+#define ttrue 1
+extern long verbosity;
+/*  -- translated by f2c (version of 23 May 1992  14:18:33).
+   You must link the resulting object file with the libraries:
+	-lF77 -lI77 -lm -lc   (in that order)
+*/
+
+
+#define integer long
+#define logical long
+
+int gibbs1_(integer* n,integer*  record,integer*  ptvois);
+int gibbs2_(integer* n,integer*  record,integer*  criter);
+int gibbsa_(integer* n,integer*  ptvois,integer*  vois,integer*  r,integer*  m,
+             integer*  nv,integer*  nx,integer*  ny,integer*  nn,integer*  w1,integer*  w2, 
+	integer* pfold,integer*  pfnew,integer*  impre,integer*  nfout);
+int gibbsb_(integer* x,integer*  y,integer*  n,integer*  ptvois,
+						integer*  vois,integer*  nx,integer*  ny,integer*  nv,integer*  nn,integer*  m,
+						integer*  wh,integer*  wl,integer* r, integer* impre, integer* nfout);
+int gibbsc_(integer* nz,integer*  nv,integer*  niveau,integer*  n,integer* );
+int gibbsd_(integer* racine,integer*  n,integer*  ptvois,integer*  
+							vois,integer*  nv,integer*  r,integer*  niveau);
+int gibbst_(integer* n,integer*  p,integer*  nv,integer*  nn,integer*  ptvois,integer*  vois,
+						integer*  m,integer*  r,integer*  new_,integer*  option, 
+						integer* pfnew,integer*  impre,integer*  nfout);
+
+/* Subroutine */ int gibbs1_(integer* n,integer*  record,integer*  ptvois)
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer crit, i, j, l, r, rec;
+
+/* -----------------------------------------------------------------------
+ */
+/*     routine appele par gibbs0 */
+/* -----------------------------------------------------------------------
+ */
+/*     but: trie record (ensemble de n sommet) telle que l'ordre des somm 
+*/
+/*     soit croissant (ordre du sommet i est ptvois(i+1)-ptvois(i)) */
+/* -----------------------------------------------------------------------
+ */
+
+    /* Parameter adjustments */
+    --ptvois;
+    --record;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    l = *n / 2 + 1;
+    r = *n;
+L2:
+    if (l <= 1) {
+	goto L20;
+    }
+    --l;
+    rec = record[l];
+    crit = ptvois[record[l] + 1] - ptvois[record[l]];
+    goto L3;
+L20:
+    rec = record[r];
+    crit = ptvois[record[r] + 1] - ptvois[record[r]];
+    record[r] = record[1];
+    --r;
+    if (r == 1) {
+	goto L999;
+    }
+L3:
+    j = l;
+L4:
+    i = j;
+    j <<= 1;
+    if ((i__1 = j - r) < 0) {
+	goto L5;
+    } else if (i__1 == 0) {
+	goto L6;
+    } else {
+	goto L8;
+    }
+L5:
+    if (ptvois[record[j] + 1] - ptvois[record[j]] < ptvois[record[j + 1] + 1] 
+	    - ptvois[record[j + 1]]) {
+	++j;
+    }
+L6:
+    if (crit >= ptvois[record[j] + 1] - ptvois[record[j]]) {
+	goto L8;
+    }
+    record[i] = record[j];
+    goto L4;
+L8:
+    record[i] = rec;
+    goto L2;
+L999:
+    record[1] = rec;
+    return 0;
+} /* gibbs1_ */
+
+/* Subroutine */ int gibbs2_(integer* n,integer*  record,integer*  criter)
+{
+    static integer crit, i, j, l, r, rec;
+
+
+/*     trie record selon les valeurs de criter(record(.)) croissantes */
+
+
+    /* Parameter adjustments */
+    --criter;
+    --record;
+
+    /* Function Body */
+    if (*n <= 1) {
+	return 0;
+    }
+    l = *n / 2 + 1;
+    r = *n;
+L2:
+    if (l <= 1) {
+	goto L20;
+    }
+    --l;
+    rec = record[l];
+    crit = criter[rec];
+    goto L3;
+L20:
+    rec = record[r];
+    crit = criter[rec];
+    record[r] = record[1];
+    --r;
+    if (r == 1) {
+	goto L999;
+    }
+L3:
+    j = l;
+L4:
+    i = j;
+    j <<= 1;
+    if (j - r < 0) {
+	goto L5;
+    } else if (j == r) {
+	goto L6;
+    } else {
+	goto L8;
+    }
+L5:
+    if (criter[record[j]] < criter[record[j + 1]]) {
+	++j;
+    }
+L6:
+    if (crit >= criter[record[j]]) {
+	goto L8;
+    }
+    record[i] = record[j];
+    goto L4;
+L8:
+    record[i] = rec;
+    goto L2;
+L999:
+    record[1] = rec;
+    return 0;
+} /* gibbs2_ */
+
+/* Subroutine */ 
+int gibbsa_(integer* n,integer*  ptvois,integer*  vois,integer*  r,integer*  m,
+             integer*  nv,integer*  nx,integer*  ny,integer*  nn,integer*  w1,integer*  w2, 
+	integer* pfold,integer*  pfnew,integer*  impre,integer*  nfout)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4;
+
+    /* Builtin functions */
+
+    /* Local variables */
+    static integer nbcc, degi, bold, bnew, i, j, k, p, degre, x, y, p1, p2;
+/*    extern  Subroutine  int gibbs1_();*/
+    static integer pf;
+/*    extern  Subroutine int gibbsb_(), gibbsd_(), gibbst_();*/
+    static integer nbpass, niveau, pf1, option, old, new_, opt, new1;
+    long pfn1,pfo1,m1e9;
+    m1e9 = 1000000000;
+
+/* -----------------------------------------------------------------------
+ */
+/*  but: calculer une renumerotation des sommets d'un graphe defini par: 
+*/
+/*     par la methode de gibbs */
+/* -----------------------------------------------------------------------
+ */
+/*  entree */
+/* -------- */
+/*     n = nb de sommet du graphe */
+/*      les voisins d'un sommet i ont pour numero : */
+/*     ( vois(j) , j=ptvois(i),ptvois(i+1)-1 ) */
+
+/*     impre   parametre d'impression */
+/*     nfout   numero du fichier pour impression */
+
+/*  sortie */
+/*  ------ */
+/*     r(1:n) tableau donnant la nouvelle numerotation: */
+/*       r(i) = nouveau numero du sommet i */
+/*     pfolf = ancien  profile */
+/*     pfnew = nouveau profile */
+
+/*  tableau de travail : */
+/*  -------------------- */
+/*     m(n) */
+/*     nv(0:n+n) */
+/*     nx(n) */
+/*     ny(n) */
+/*     nn(0:n) */
+/*     w1(n) */
+/*     w2(n) */
+
+/* -----------------------------------------------------------------------
+ */
+/*     programmeur f. hecht  le 3/02/1987 */
+/* -----------------------------------------------------------------------
+ */
+
+/*     tri des voisins d'un sommet du graphe par degre croissant */
+/* --------------------------------------------------------------- */
+    /* Parameter adjustments */
+    --w2;
+    --w1;
+    --ny;
+    --nx;
+    --m;
+    --r;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    p2 = ptvois[1] - 1;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	p1 = p2 + 1;
+	p2 = ptvois[i + 1] - 1;
+	i__2 = p2 - p1 + 1;
+	gibbs1_(&i__2, &vois[p1], &ptvois[1]);
+/*       if(impre.le.-9) then */
+/*        write (nfout,*) 'les voisin de ',i,'sont: ', (vois(j),j=p1,p
+2) */
+/*       endif */
+/* L10: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	r[i] = 0;
+/* L20: */
+    }
+/*     boucle sur les composante connexe du graphe */
+    new_ = 0;
+    nbcc = 0;
+L30:
+    if (new_ < *n) {
+	++nbcc;
+/*       recherche d'une racine y (un sommet non numerote) de degree m
+ini */
+	y = 0;
+	degre = *n + 1;
+	i__1 = *n;
+	for (i = 1; i <= i__1; ++i) {
+	    if (r[i] <= 0) {
+		degi = ptvois[i + 1] - ptvois[i];
+		if (degi < degre) {
+		    degre = degi;
+		    y = i;
+		}
+	    }
+/* L40: */
+	}
+	if (y == 0) {
+	   return -3;/*  s_stop("fatal erreur  gibbs 2 : pb racine", 33L); */
+	}
+	gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+	nbpass = 0;
+L50:
+	++nbpass;
+	x = y;
+	p = niveau;
+	k = 0;
+	i__1 = nv[p + 1];
+	for (i = nv[p] + 1; i <= i__1; ++i) {
+	    ++k;
+	    m[k] = nv[i];
+/* L60: */
+	}
+	gibbs1_(&k, &m[1], &ptvois[1]);
+	i__1 = k;
+	for (i = 1; i <= i__1; ++i) {
+	    y = m[i];
+	    gibbsd_(&y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+	    if (niveau > p) {
+		goto L50;
+	    }
+/* L70: */
+	}
+	y = m[1];
+/*        if(impre.lt.0) then */
+/*          write(nfout,*) */
+/*     +  '    nb de pass pour trouver le pseudo diametre',nbpass */
+/*     +         ,' x=',x,',y=',y,' de la composante connexe ',nbcc */
+
+/*          write (nfout,*) ('-',i=1,78) */
+/*        endif */
+/*       optimisation de la descendance de la numerotation */
+/*       ------------------------------------------------- */
+	gibbsb_(&x, &y, n, &ptvois[1], &vois[1], &nx[1], &ny[1], nv, nn, &m[1]
+		, &w1[1], &w2[1], &r[1], impre, nfout);
+
+/*     renumerotation de cuthill mac kee avec la meilleur des 4 option
+s */
+/*     --------------------------------------------------------------
+--- */
+	pf = 1073741824;
+	option = -2;
+	new1 = new_;
+	for (opt = -2; opt <= 2; ++opt) {
+	    new_ = new1;
+	    if (opt != 0) {
+		gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], &
+			new_, &opt, &pf1, impre, nfout);
+		if (pf1 < pf) {
+		    pf = pf1;
+		    option = opt;
+		}
+	    }
+/* L80: */
+	}
+/*        if(impre.ne.0) write (nfout,*) '    on a choisi l''option ',
+ */
+/*     +             option,', new =',new */
+	new_ = new1;
+	gibbst_(n, &p, nv, nn, &ptvois[1], &vois[1], &m[1], &r[1], &new_, &
+		option, &pf1, impre, nfout);
+	goto L30;
+    }
+/*      if(impre.ne.0) write(nfout,*) */
+/*     +       '   nb de composante connexe du graphe =',nbcc */
+/*     calcul du profile */
+    *pfold = 0;
+    *pfnew = 0;
+    pfo1=0;
+    pfn1=0;
+    bnew = 0;
+    bold = 0;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	old = i;
+	new_ = r[i];
+	i__2 = ptvois[i + 1] - 1;
+	for (j = ptvois[i]; j <= i__2; ++j) {
+/* Computing MIN */
+	    i__3 = old, i__4 = vois[j];
+	    old = mmin(i__3,i__4);
+/* Computing MIN */
+	    i__3 = new_, i__4 = r[vois[j]];
+	    new_ = mmin(i__3,i__4);
+/* L100: */
+	}
+	*pfold = *pfold + i - old + 1;
+/* Computing MAX */
+	i__2 = bold, i__3 = i - old + 1;
+	bold = mmax(i__2,i__3);
+	*pfnew = *pfnew + r[i] - new_ + 1;
+/* Computing MAX */
+	i__2 = bnew, i__3 = r[i] - new_ + 1;
+	bnew = mmax(i__2,i__3);
+        if(*pfold>m1e9) { pfo1+=*pfold/m1e9; *pfold = *pfold%m1e9;}
+        if(*pfnew>m1e9) { pfn1+=*pfnew/m1e9; *pfnew = *pfnew%m1e9;}
+        
+/* L110: */
+    }
+    if(pfo1 || pfn1)
+    { // change unit of pf
+        if(pfo1==pfn1)
+        {
+            *pfnew= pfn1*10 + (*pfnew >= *pfold) ;
+            *pfold= pfo1*10 + (*pfnew <= *pfold) ;
+        }
+        else
+        {
+           *pfnew= pfn1 ;
+           *pfold= pfo1;
+        }
+
+    }
+/*      if(impre.ne.0) then */
+/*        write(nfout,*)'profile  old  = ',pfold,', profile  new = ',pfnew
+ */
+/*        write(nfout,*)'1/2 bande old = ',bold ,', 1/2 band new = ',bnew 
+*/
+/*      endif */
+return 0;
+} /* gibbsa_ */
+
+/* Subroutine */ int gibbsb_(integer* x,integer*  y,integer*  n,integer*  ptvois,
+integer*  vois,integer*  nx,integer*  ny,integer*  nv,integer*  nn,integer*  m,
+integer*  wh,integer*  wl,integer* r, integer* , integer* )
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static int flag_;
+    static integer i, j, k, p, s, h0, i1, l0, i2;
+/*    extern  Subroutine  int gibbs1_(); */
+    static integer lg;
+/*    extern  Subroutine  int gibbsd_(), gibbsc_();*/
+    static integer niveau, mxcanx, mxcany, nbc;
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ */
+/* ...................................................................... 
+*/
+/*     attention on met la descente optimiser dans r <0 ou nulle */
+/* .......................................................................
+ */
+    /* Parameter adjustments */
+    --r;
+    --m;
+    --ny;
+    --nx;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    gibbsd_(y, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+    gibbsc_(&ny[1], nv, &niveau, n, &mxcany);
+    gibbsd_(x, n, &ptvois[1], &vois[1], nv, &r[1], &niveau);
+    p = niveau;
+    gibbsc_(&nx[1], nv, &niveau, n, &mxcanx);
+    flag_ = ffalse;
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nx[i] + ny[i] == p) {
+	    r[i] = -nx[i];
+	} else if (nx[i] >= 0) {
+	    flag_ = ttrue;
+	    r[i] = -1073741824;
+	} else {
+	    if (r[i] <= 0) {
+		r[i] = -1073741822;
+	    }
+	}
+/* L20: */
+    }
+    if (flag_) {
+/*       calcul des composantes connexe du graphe sans les sommets de 
+nn */
+/*       ------------------------------------------------------------
+--- */
+	j = *n;
+	k = 0;
+	nbc = 0;
+	nv[nbc] = j;
+L30:
+	++k;
+	if (k <= *n) {
+	    if (r[k] == -1073741824) {
+/*           recherche de la fermeture transitive partant de k
+ */
+		++nbc;
+		i = -1;
+		s = k;
+L40:
+		++i;
+		wl[i] = ptvois[s];
+		wh[i] = ptvois[s + 1];
+		++j;
+		nv[j] = s;
+		r[s] = -1073741823;
+L50:
+		if (i >= 0) {
+		    if (wl[i] < wh[i]) {
+			s = vois[wl[i]];
+			++wl[i];
+			if (r[s] == -1073741824) {
+			    goto L40;
+			}
+			goto L50;
+		    }
+		    --i;
+		    goto L50;
+		}
+		nv[nbc] = j;
+		m[nbc] = nbc;
+	    }
+	    goto L30;
+	}
+/*        if(impre.lt.0) write(nfout,*) */
+/*     +         ' nb de composante connexe du graphe reduit =',nbc */
+
+/* --------------- fin de construction des composantes connexes------
+--- */
+/*        nv(0)=n */
+/*        if(impre.le.-10) write(nfout,5555)'nv(0:n+n) = ',(nv(i),i=0,
+n+n) */
+	gibbs1_(&nbc, &m[1], nv);
+/*        if(impre.le.-10)write(nfout,5555)'trie m =',(m(i),i=1,nbc) 
+*/
+	i__1 = p;
+	for (i = 0; i <= i__1; ++i) {
+	    nn[i] = 0;
+/* L60: */
+	}
+	i__1 = *n;
+	for (i = 1; i <= i__1; ++i) {
+	    j = -r[i];
+	    if (j >= 0 && j <= p) {
+		++nn[j];
+	    }
+/* L70: */
+	}
+
+/*       boucle sur les composante connexes par ordre croissantes */
+/*       -------------------------------------------------------- */
+	for (k = nbc; k >= 1; --k) {
+	    i = m[k];
+	    i1 = nv[i - 1] + 1;
+	    i2 = nv[i];
+	    lg = i2 - i1 + 1;
+/*         if(impre.le.-7) */
+/*     +       write(nfout,*) k,' composante ',i,',lg=',lg,',i1,i2
+=',i1,i2 */
+/*         if(impre.le.-8) */
+/*     +       write (nfout,5555)' ',(nv(i),i=i1,i2) */
+	    h0 = 0;
+	    l0 = 0;
+	    i__1 = p;
+	    for (j = 0; j <= i__1; ++j) {
+		wh[j] = nn[j];
+		wl[j] = nn[j];
+/* L90: */
+	    }
+	    i__1 = i2;
+	    for (i = i1; i <= i__1; ++i) {
+		s = nv[i];
+		++wh[nx[s]];
+		++wl[p - ny[s]];
+/* L100: */
+	    }
+	    i__1 = p;
+	    for (j = 0; j <= i__1; ++j) {
+		if (wh[j] != nn[j]) {
+/* Computing MAX */
+		    i__2 = wh[j];
+		    h0 = mmax(i__2,h0);
+		}
+		if (wl[j] != nn[j]) {
+/* Computing MAX */
+		    i__2 = wl[j];
+		    l0 = mmax(i__2,l0);
+		}
+/* L110: */
+	    }
+	    if (h0 < l0 || (h0 == l0 && mxcanx <= mxcany)) {
+/*           if(impre.le.-2) write(nfout,*) */
+/*     +       '         h0 = ',h0,',l0 = ',l0,'  ------- XXXX
+ --------' */
+		i__1 = i2;
+		for (i = i1; i <= i__1; ++i) {
+		    s = nv[i];
+		    r[s] = -nx[s];
+		    ++nn[-r[s]];
+/* L120: */
+		}
+	    } else {
+/*           if (impre.le.-2) write(nfout,*) */
+/*     +       '         h0 = ',h0,',l0 = ',l0,'  ------- YYYY
+ --------' */
+		i__1 = i2;
+		for (i = i1; i <= i__1; ++i) {
+		    s = nv[i];
+		    r[s] = -p + ny[s];
+		    ++nn[-r[s]];
+/* L130: */
+		}
+	    }
+/* L140: */
+	}
+    }
+/*     on met les nouveaux niveaux de la descendance optimiser dans nn */
+/*     ----------------------------------------------------------------- 
+*/
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (r[i] > 0) {
+	    nn[i] = -1;
+	} else if (r[i] == -1073741822) {
+	    nn[i] = -2;
+	} else {
+	    nn[i] = -r[i];
+	}
+/* L150: */
+    }
+/*      if(impre.le.-10)write (nfout,5555)' nn(i)=',(nn(i),i=1,n) */
+/* 5555  format('            --------   ',a,/,5(15x,10(i5)/)) */
+return 0;} /* gibbsb_ */
+
+/* Subroutine */ int gibbsc_(integer* nz,integer*  nv,integer*  niveau,integer*  n,integer*  mxz)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer i, j;
+
+/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ */
+    /* Parameter adjustments */
+    --nz;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	nz[i] = -1;
+/* L10: */
+    }
+    *mxz = 0;
+    i__1 = *niveau;
+    for (i = 0; i <= i__1; ++i) {
+/* Computing MAX */
+	i__2 = *mxz, i__3 = nv[i + 1] - nv[i];
+	*mxz = mmax(i__2,i__3);
+	i__2 = nv[i + 1];
+	for (j = nv[i] + 1; j <= i__2; ++j) {
+	    if(nv[j] > *n) 
+	     printf(" bug in gibbsc_ ##### %ld %ld %ld %ld \n",j,nv[j],i,*niveau );
+	    if(nv[j] <= *n) 
+	    nz[nv[j]] = i;
+/* L20: */
+	}
+    }
+return 0;} /* gibbsc_ */
+
+/* Subroutine */ int gibbsd_(integer* racine,integer*  n,integer*  ptvois,integer*  vois,integer*  nv,integer*  r,integer*  niveau)
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer i, k, s, sv, stk, stk1, stk2, nvni=-1;
+
+/* -----------------------------------------------------------------------
+ */
+/*     but construire la structure des descendant de racine  du graphe */
+/* -----------------------------------------------------------------------
+ */
+/*     sortie : */
+/*     -------- */
+/*     nv est la structure des niveaux */
+/*     les sommets du niveau (i =0,niveau_ sont defini par : */
+/*        (nv(j),j=nv(i),nv(i+1)-1) */
+
+/*     le tableau r(i) n'est modifier que sur les sommets */
+/*       de la composante connexe du graphe contenant la racine */
+
+/* -----------------------------------------------------------------------
+ */
+
+/*     on demark tout les sommets non remuneroter */
+/* -------------------------------------------------- */
+    /* Parameter adjustments */
+    --r;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (r[i] < 0) {
+	    r[i] = 0;
+	}
+/* L10: */
+    }
+
+/*    initialisation */
+
+    stk = *n ;// correct bug FH june 2011 ....
+    nv[0] = stk;
+    stk2 = stk;
+    *niveau = 0;
+    ++stk;
+    nv[stk] = *racine;
+    r[*racine] = -1;
+L20:
+    if (stk2 < stk) {
+	++(*niveau);
+	stk1 = stk2 + 1;
+	nvni=nv[*niveau];/* save value */
+	nv[*niveau] = stk;
+	stk2 = stk;
+/*        print *,' ------- niveau =',niveau,' stk=',stk1,stk2 */
+	i__1 = stk2;
+	for (k = stk1; k <= i__1; ++k) {
+	    s = nv[k];
+/*         print *,'----------------- s=',s */
+	    i__2 = ptvois[s + 1] - 1;
+	    for (i = ptvois[s]; i <= i__2; ++i) {
+/*               pour tout les sommets (sv) voisin */
+/*                d'un sommet (s) du niveau precedent */
+		sv = vois[i];
+/*          print *,' voisin =',sv */
+/*               si le sommet n'est pas marque on le marque et
+ on l'ajout */
+		if (r[sv] == 0) {
+		    ++stk;
+		    nv[stk] = sv;
+		    r[sv] = -1;
+		}
+/* L30: */
+	    }
+/* L40: */
+	}
+	goto L20;
+    }
+ // if(nvni>0)  nv[*niveau]=nvni;
+    --(*niveau);
+/*      call pnv(' gibbsd ',n,nv,niveau) */
+return 0;} /* gibbsd_ */
+
+
+/* Subroutine */ int gibbst_(integer* n,integer*  p,integer*  nv,integer*  nn,integer*  ptvois,integer*  vois,integer*  m,integer*  r,integer*  new_,integer*  option, 
+	integer* pfnew,integer*  impre,integer*  )
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4, i__5;
+
+    /* Local variables */
+    static integer nbsc, bnew, knew, step, plus, i, j, k, s, debut, i1, i2;
+/*    extern Subroutine int gibbs2_();*/
+    static integer fin;
+
+
+/*     construction de la stucture de niveau dans nv a partir de nn */
+/*     ------------------------------------------------------------ */
+    /* Parameter adjustments */
+    --r;
+    --m;
+    --vois;
+    --ptvois;
+
+    /* Function Body */
+    nv[0] = *n;
+    i__1 = *p + 1;
+    for (i = 1; i <= i__1; ++i) {
+	nv[i] = 0;
+/* L150: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nn[i] >= 0) {
+	    ++nv[nn[i] + 1];
+	}
+/* L160: */
+    }
+    i__1 = *p;
+    for (i = 0; i <= i__1; ++i) {
+	nv[i + 1] += nv[i];
+/* L170: */
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	if (nn[i] >= 0) {
+	    j = nn[i];
+	    ++nv[j];
+	    nv[nv[j]] = i;
+	}
+/* L180: */
+    }
+    for (i = *p; i >= 0; --i) {
+	nv[i + 1] = nv[i];
+/* L190: */
+    }
+    nv[0] = *n;
+    nbsc = nv[*p + 1] - nv[0];
+/*     --- fin de la construction ------------------------------------ */
+    if (*option == -2) {
+	i__1 = *impre - 1;
+    }
+    i__1 = *n;
+    for (i = 1; i <= i__1; ++i) {
+	m[i] = *n * 3 + ptvois[i + 1] - ptvois[i];
+/* L10: */
+    }
+    if ((((int)*option) == 1)||(((int)*option) == -1)) {
+	debut = 0;
+	fin = *p;
+	step = 1;
+    } else {
+	debut = *p;
+	fin = 0;
+	step = -1;
+    }
+    i__1 = fin;
+    i__2 = step;
+    for (i = debut; i__2 < 0 ? i >= i__1 : i <= i__1; i += i__2) {
+	i1 = nv[i] + 1;
+	i2 = nv[i + 1];
+	i__3 = i2 - i1 + 1;
+	gibbs2_(&i__3, &nv[i1], &m[1]);
+	i__3 = i2;
+	for (j = i1; j <= i__3; ++j) {
+	    s = nv[j];
+	    i__4 = ptvois[s + 1] - 1;
+	    for (k = ptvois[s]; k <= i__4; ++k) {
+/* Computing MIN */
+		i__5 = m[vois[k]];
+		m[vois[k]] = mmin(i__5,j);
+/* L20: */
+	    }
+/* L30: */
+	}
+/* L40: */
+    }
+    if (*option > 0) {
+	knew = *new_;
+	plus = 1;
+    } else {
+	knew = *new_ + nbsc + 1;
+	plus = -1;
+    }
+    *new_ += nbsc;
+/*      if(option.gt.0) then */
+/*        do 60 k = debut , fin , step */
+/*          do 60 j = nv(k+1),nv(k)+1,-1 */
+/*            knew = knew + plus */
+/*            r(nv(j)) = knew */
+/* 60      continue */
+/*      else */
+    i__2 = fin;
+    i__1 = step;
+    for (k = debut; i__1 < 0 ? k >= i__2 : k <= i__2; k += i__1) {
+	i__3 = nv[k + 1];
+	for (j = nv[k] + 1; j <= i__3; ++j) {
+	    knew += plus;
+	    r[nv[j]] = knew;
+/* L70: */
+	}
+    }
+/*      endif */
+    *pfnew = 0;
+    bnew = 0;
+    i__3 = *n;
+    for (i = 1; i <= i__3; ++i) {
+	k = r[i];
+	if (k > 0) {
+	    i__1 = ptvois[i + 1] - 1;
+	    for (j = ptvois[i]; j <= i__1; ++j) {
+		if (r[vois[j]] > 0) {
+/* Computing MIN */
+		    i__2 = k, i__4 = r[vois[j]];
+		    k = mmin(i__2,i__4);
+		}
+/* L100: */
+	    }
+	    *pfnew = *pfnew + r[i] - k + 1;
+/* Computing MAX */
+	    i__1 = bnew, i__2 = r[i] - k + 1;
+	    bnew = mmax(i__1,i__2);
+	}
+/* L110: */
+    }
+/*      if(impre.lt.0.or.impre.gt.2) then */
+/*        write(nfout,*) '      option =',option,', profile =',pfnew */
+/*     +       ,', 1/2 bande =',bnew,', new=',new,', nbss composante=',nbsc
+ */
+/*      endif */
+return 0;} /* gibbst_ */
+
+/* function */ int Mesh::gibbsv (integer* ptvoi,
+integer* vois,integer* lvois,integer* w,integer* v)
+{
+    /* System generated locals */
+    integer  i__2;
+
+    /* Local variables */
+     integer i, j, k, T, ss, iii, ptv, ptv1;
+     integer nbss = nv , nbt = nt;
+/*--- Prepare les donees pour gibbsa en construisant ptvoi, vois, lvois -
+------------*/
+/*     in */
+/*     ---   nbnt =3 pour des triangles 2D, */
+/* 			nbt =  nb de triangle */
+/*    		nbss = nb de sommets */
+/*           nsea = numeros de 3 sommets de chaque triangle (me) */
+/*     out */
+/*     --- 	ptvoi, vois, lvois, err */
+/*      tableaux de travail w, v */
+/*-----------------------------------------------------------------------
+----------*/
+    /* Parameter adjustments */
+     --v;
+     --w;
+     --vois;
+     --ptvoi;
+     
+     /* Function Body */
+     for (i = 1; i <= nbss; ++i) {
+       w[i] = -1;
+       ptvoi[i] = 0; }
+     ptvoi[nbss + 1] = 0;
+     for (i = 0; i < nbt; ++i) {
+       for (j = 0; j < 3; ++j) {
+	 ss = number(triangles[i][j])+1;
+	 ++ptvoi[ss + 1];
+	 w[ss] = 0;}
+     }
+     
+     for (i = 1; i <= nbss; ++i) 
+       ptvoi[i + 1] += ptvoi[i];
+     
+     for (i = 0; i < nbt; ++i) {
+       for (j = 0; j < 3; ++j) {
+	 ss = number(triangles[i][j])+1;
+	 ++ptvoi[ss];
+	 v[ptvoi[ss]] = i;
+       }
+     }
+     ptv1 = 0;
+     iii = 1;
+     for (i = 1; i <= nbss; ++i) {
+       ptv = ptv1 + 1;
+       ptv1 = ptvoi[i];
+       ptvoi[i] = iii;
+       i__2 = ptv1;
+       for (j = ptv; j <= i__2; ++j) {
+	 T = v[j];
+	 for (k = 0; k < 3; ++k) {
+	   ss = number(triangles[T][k])+1;  /*  nsea[k + T * nsea_dim1]; */
+	   if (w[ss] != i) {
+	     w[ss] = i;
+	     if (iii > *lvois)  return 2 ;
+	     /* print*,'pas assez de place memoire' */
+	     
+	     vois[iii] = ss;
+	     ++iii;}
+	 }
+       }
+     }
+     ptvoi[nbss + 1] = iii;
+     *lvois = iii - 1;
+     return 0; /* OK */
+     return 0;} /* gibbsv_ */
+
+int Mesh::renum()
+/* -------- 
+	renumber vertices by gibbs method; updates triangle and edge array
+	in:   mesh  
+	out:   mesh
+ 	auxiliary arrays: ptvois,vois,r,m,nv,nx,ny,nn,w1,w2,f 
+ 	all of size nv+1 except vois (10(nv+1)) and nv (2(nv+1))
+ 	err = -1 : memory alloc pb; err = -3: fatal erreur  gibbs 2 : pb racine
+*/
+{
+    long   pfold, pfnew;
+    long* ptvois=NULL;
+    long* vois=NULL;
+    long* nn =NULL;
+    long* r =NULL;
+    long* m =NULL;
+    long* nnv =NULL;
+    long* nx =NULL;
+    long* ny =NULL;
+    long* w1 =NULL;
+    long* w2=NULL;
+    long nbvoisin =  10*nv;
+    long printint=0, iodev=6;
+    int err=0;
+  	ptvois = new long[nv+1]; 		//(long*)calloc((long)(nv + 1) , sizeof(long));
+	nn = 	 new long[3*nt]; 			//(long*)calloc(3 * nt ,sizeof(long));
+	vois = 	 new long[nbvoisin+10];	//(long*)calloc((long)(nbvoisin + 10) , sizeof(long)); 
+	r = 	 new long[nv+1];				//(long*)calloc((long)(nv + 1) , sizeof(long));
+	if((!ptvois)||(!nn)||(!vois)||(!r)) return -1;
+	err = gibbsv(ptvois,vois,&nbvoisin,r,nn) ;
+	delete [] nn;					// free(nn);
+	if(err==0)
+	{
+       m = new long[nv+1];
+       nn = new long[nv+1];
+       nnv = new long[(nv+1)<<1];
+       nx = new long[nv+1];
+       ny = new long[nv+1];
+       w1 = new long[nv+1];
+       w2 = new long[nv+1];
+	   long lnv = nv;
+       err = gibbsa_ (&lnv, ptvois, vois, r, m, nnv, nx, ny, nn, w1, w2, &pfold, &pfnew,
+		      &printint, &iodev);
+       delete [] m;
+       delete [] nnv;
+       delete [] nn;
+       delete [] nx;
+       delete [] ny;
+       delete [] w1;
+       delete [] w2;
+     }
+
+  delete [] vois;
+  delete [] ptvois;
+     if(verbosity>1)
+  cout << "  -- Mesh: Gibbs: old skyline = " << pfold << "  new skyline = " << pfnew << endl;
+  if (err == 0 && (pfnew <= pfold))
+     {
+       int i,j;
+       for ( i=0;i<nv;i++)
+	 r[i] -= 1; 
+       Vertex  * f= new Vertex[nv];
+       for (i = 0; i < nv; ++i)
+	 f[i] = vertices[i];
+       for (i = 0; i < nv; ++i)
+	 vertices[r[i]]  = f[i];
+       delete [] f;       
+       
+       for (j = 0; j < nt; ++j)  // updates triangle array
+	  triangles[j].Renum(vertices,r);
+       
+       for (j = 0; j < neb; ++j)	// updates edge array
+	    bedges[j].Renum(vertices,r);
+	  
+	  if (BoundaryAdjacencesHead )
+	   {
+          for (int i=0;i<nv;i++) 
+            BoundaryAdjacencesHead[i]=-1;
+          int j2=0;
+          for (int j=0;j<neb;j++)
+           for (int k=0;k<2;k++,j2++)
+             {  
+              int v = number(bedges[j][k]);
+              ffassert(v >=0 && v < nv);
+              BoundaryAdjacencesLink[j2]=BoundaryAdjacencesHead[v];
+              BoundaryAdjacencesHead[v]=j2;
+            }
+        }
+      for (int it=0;it<nt;it++)
+       for (int j=0;j<3;j++)
+         TriangleConteningVertex[(*this)(it,j)]=it;
+        
+       if (quadtree) {
+         delete quadtree;quadtree=0;
+         MakeQuadTree(); }
+
+      
+     }
+  delete [] r;
+  return err;
+} 
+int FESpace::renum()
+/* -------- 
+	renumber vertices by gibbs method; updates triangle and edge array
+	in:   mesh  
+	out:   mesh
+ 	auxiliary arrays: ptvois,vois,r,m,nv,nx,ny,nn,w1,w2,f 
+ 	all of size nv+1 except vois (10(nv+1)) and nv (2(nv+1))
+ 	err = -1 : memory alloc pb; err = -3: fatal erreur  gibbs 2 : pb racine
+*/
+{
+  if (cdef==0) return -2;
+  if (cdef->NodesOfElement==0) return -2;
+    int nv = NbOfNodes;
+    int nt = NbOfElements;// ;Th.nt;
+    long  pfold =0, pfnew=0;
+    long* ptvois=NULL;
+    long* vois=NULL;
+    long* nn =NULL;
+    long* r =NULL;
+    long* m =NULL;
+    long* nnv =NULL;
+    long* nx =NULL;
+    long* ny =NULL;
+    long* w1 =NULL;
+    long* w2=NULL;
+    long nbvperelem = 20; // pour le P1
+  //  cout << "gibbs: nbvperelem =" << nbvperelem << endl;
+    long nbvoisin =  (nbvperelem)*nv; 
+    long printint=0, iodev=6;
+    int err=0;
+    int nnx= SizeToStoreAllNodeofElement();
+  	ptvois = new long[nv+1]; 		
+	nn = 	 new long[nnx]; 		
+	vois = 	 new long[nbvoisin+100];	
+	r = 	 new long[nv+1];			
+	if((!ptvois)||(!nn)||(!vois)||(!r)) return -1;
+	err = gibbsv(ptvois,vois,&nbvoisin,r,nn) ;
+	delete [] nn;					
+	if(err==0)
+	{
+       m = new long[nv+1];
+       nn = new long[nv+1];
+       nnv = new long[(nv+1)<<1];
+       nx = new long[nv+1];
+       ny = new long[nv+1];
+       w1 = new long[nv+1];
+       w2 = new long[nv+1];
+	   long lnv = nv;
+       err = gibbsa_ (&lnv, ptvois, vois, r, m, nnv, nx, ny, nn, w1, w2, &pfold, &pfnew,
+		      &printint, &iodev);
+       delete [] m;
+       delete [] nnv;
+       delete [] nn;
+       delete [] nx;
+       delete [] ny;
+       delete [] w1;
+       delete [] w2;
+     }
+    else 
+      cerr << " Not enought memory (bug)" <<  nbvoisin << " " << nbvoisin/NbOfElements <<  endl;
+  delete [] vois;
+  delete [] ptvois;
+  if (err==0 && verbosity>1) 
+  cout << " FESpace:Gibbs: old skyline = " << pfold << "  new skyline = " << pfnew << endl;
+  if (err == 0 && (pfnew <= pfold))
+     {
+       int i;
+      // cout << *this << endl;
+       for ( i=0;i<nv;i++)
+	     r[i] -= 1; 
+	    cdef->renum(r,nnx);  
+        }
+     
+  delete [] r;
+  return err;
+} 
+/* function */ int FESpace::gibbsv (integer* ptvoi,
+integer* vois,integer* lvois,integer* w,integer* v)
+{
+    /* System generated locals */
+    integer  i__2;
+
+    /* Local variables */
+     
+     integer i, j, k, T, ss, iii, ptv, ptv1;
+     integer nbss = NbOfNodes , nbt = NbOfElements;
+     integer jj,kk;
+/*--- Prepare les donees pour gibbsa en construisant ptvoi, vois, lvois -
+------------*/
+/*     in */
+/*     ---   nbnt =3 pour des triangles 2D, */
+/* 			nbt =  nb de triangle */
+/*    		nbss = nb de sommets */
+/*           nsea = numeros de 3 sommets de chaque triangle (me) */
+/*     out */
+/*     --- 	ptvoi, vois, lvois, err */
+/*      tableaux de travail w, v */
+/*-----------------------------------------------------------------------
+----------*/
+    /* Parameter adjustments */
+     --v;
+     --w;
+     --vois;
+     --ptvoi;
+     
+     /* Function Body */
+     for (i = 1; i <= nbss; ++i) {
+       w[i] = -1;
+       ptvoi[i] = 0; }
+     ptvoi[nbss + 1] = 0;
+     for (i = 0; i < nbt; ++i) {
+       for (j = 0; j < NbOfNodesInElement(i) ; ++j) {
+	     ss =  (*this)(i,j) +1;
+	 ++ptvoi[ss + 1];
+	 w[ss] = 0;}
+     }
+     
+     for (i = 1; i <= nbss; ++i) 
+       ptvoi[i + 1] += ptvoi[i];
+     
+     for (i = 0; i < nbt; ++i) {
+       for (j = 0,jj= NbOfNodesInElement(i); j <jj  ; ++j) {
+	     ss = (*this)(i,j) +1;//number(triangles[i][j])+1;
+	     if ( ! ( ss>0 && ss <= nbss)) 
+	       {
+	          cout << "bug " << ss << " " <<  i << " " << j << endl;
+	          exit(1);
+	       }
+	     ++ptvoi[ss];
+	     v[ptvoi[ss]] = i;
+       }
+     }
+     ptv1 = 0;
+     iii = 1;
+     for (i = 1; i <= nbss; ++i) {
+       ptv = ptv1 + 1;
+       ptv1 = ptvoi[i];
+       ptvoi[i] = iii;
+       i__2 = ptv1;
+       for (j = ptv; j <= i__2; ++j) {
+	 T = v[j];
+	 for (k = 0,kk=NbOfNodesInElement(T); k < kk; ++k) {
+	   ss = (*this)(T,k) +1;//number(triangles[T][k])+1;  /*  nsea[k + T * nsea_dim1]; */
+	   if (w[ss] != i) {
+	     w[ss] = i;
+	     if (iii > *lvois)  return 2 ;
+	     /* print*,'pas assez de place memoire' */
+	     
+	     vois[iii] = ss;
+	     ++iii;}
+	 }
+       }
+     }
+     ptvoi[nbss + 1] = iii;
+     *lvois = iii - 1;
+     return 0; /* OK */
+     return 0;} /* gibbsv_ */						
+/*  message d'erreur:         *err = 2;    print*,'pas assez de place memoire'   */
+			
+/*  message d'erreur:         *err = 2;    print*,'pas assez de place memoire'   */
diff --git a/src/femlib/glutdraw.cpp b/src/femlib/glutdraw.cpp
new file mode 100644
index 0000000..284a99a
--- /dev/null
+++ b/src/femlib/glutdraw.cpp
@@ -0,0 +1,518 @@
+#ifdef __APPLE__
+#include <GLUT/glut.h>
+#else
+#include <GL/glut.h>
+#endif
+
+//  
+#include <pthread.h>
+pthread_mutex_t mutex, mutexclose;
+
+#include <cstdlib>
+#include <cstdio>
+#include <cmath>
+using namespace std;
+
+#include <cmath>
+#include "error.hpp"
+#include <cstdio>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include "rgraph.hpp"
+
+
+#include "RNM.hpp"
+#include "fem.hpp"
+#include "FESpace.hpp" 
+#include <vector>
+const R pi=4*atan(1.); 
+using namespace std;
+using namespace Fem2D;
+
+typedef  KN<R> Rn;
+
+class Global {    
+// une petite classe pour stoker toutes les variables globales
+public:
+  int Width , Height;              // taille de l'�cran en pixel
+  R rapz;
+  int count;
+  vector<const Mesh **>  lppTh;
+  vector<const Mesh **>  lisoTh;
+  vector<const Rn **>   lu0;
+  vector<const Rn **>   lu1;
+          
+  R theta,phi,coef_dist;           // coordonn�e polaire de la camera
+  R dtheta;                        // vitesse de rotation de la camera 
+  R xmin,xmax,ymin,ymax,zmin,zmax; // borne de la sc�ne
+  R xm,ym,zm; // point regarde
+  
+  Global(int height,int width) ;
+  void SetView() const;           // define le point de vue
+  void DefaultView();
+  void MoveXView(R dx,R dx);
+  void MakeListDraw() const  ;    // construit la list d'affichage
+  void reset() { count++;}
+  
+} *global ;  // la variable global
+
+  static int xold,yold;
+
+void * return_value=0;
+
+
+Global::Global(Mesh & TTh,Rn &ff,int height,int width,R rpz,int nbisovalue) 
+  : Th(TTh), f(ff)
+{
+  nbiso = nbisovalue;
+  Width= width ;
+  Height=height;
+  rapz=rpz;
+  count =0;
+  
+/*  // first compute the mesh bound
+  const  Vertex & v0=Th(0);
+  xmin=xmax=v0.x;
+  ymin=ymax=v0.y;
+  zmin = f[0], zmax=f[0];
+  for (int i=0;i<Th.nv;i++)
+    {
+      const  Vertex & v=Th(i);
+      xmin= Min(xmin,v.x);
+      ymin= Min(ymin,v.y);
+      xmax= Max(xmax,v.x);
+      ymax= Max(ymax,v.y); 
+      zmin= Min(zmin,f[i]);
+      zmax= Max(zmax,f[i]);                   
+    }
+  if(nbiso>2)
+    {
+      viso = new R[nbiso];
+      R diso=(zmax-zmin)/(nbiso-1);
+      for (int i=0;i<nbiso;i++)
+	viso[i]=zmin+i*diso;
+    }
+  else 
+    viso=0;
+  
+   DefaultView();
+  */
+}
+
+void Global::DefaultView() 
+{
+  coef_dist =1;
+  theta=45*pi/180.;
+  dtheta=0;
+  coef_dist=1;
+  phi = 20*pi/180.;
+   xm = (xmin+xmax)*0.5;
+   ym = (ymin+ymax)*0.5;
+   zm = rapz*(zmin+zmax)*0.5;    
+}
+void Global::SetView() const
+{
+  glViewport( 0, 0, Width, Height );
+  
+  glMatrixMode(GL_PROJECTION); 
+  glLoadIdentity(); 
+  R ratio= (double) Width / (double)  Height; 
+  R dx =(xmax-xmin), dy= (ymax-ymin), dz=(zmax-zmin)*rapz;
+  
+  R hx= (  ratio*dy < dx  ) ? dx : dy*ratio ;
+  R hy= hx/ratio ;
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity(); 
+  R focal=10;
+  R znear=0.1;
+  R zfare=100;
+  R aspect=ratio;
+  gluPerspective(focal,aspect,znear,zfare);
+  R dist = Max(dx,dy,dz)/atan(focal*pi/180.)*coef_dist;
+  R camx=xm+cos(phi)*cos(theta)*dist;
+  R camy=ym+cos(phi)*sin(theta)*dist;
+  R camz=zm+dist*sin(phi);     
+  gluLookAt(camx,camy,camz,xm,ym,zm,0.,0.,1.);
+  
+  
+}
+  void Global::MoveXView(R dx,R dy)
+  {
+  // cout << xm << " " << ym << " " << zm << " apres " ;
+   zm -= dy*(zmax-zmin)*rapz/50.;
+   xm += dx*(xmax-xmin)*sin(theta)/50;
+   ym -= dx*(ymax-ymin)*cos(theta)/50;   
+  // cout << xm << " " << ym << " " << zm << endl;
+  }
+
+
+void hsvToRgb (float h, float s, float v, float & r, float & g, float & b)
+{
+  int i;
+  float aa, bb, cc, f;
+  
+  if (s == 0) /* Grayscale */
+    r = g = b = v;
+  else {
+    if (h == 1.0) h = 0;
+    h *= 6.0;
+    i =  int(h);
+    f = h - i;
+    aa = v * (1 - s);
+    bb = v * (1 - (s * f));
+    cc = v * (1 - (s * (1 - f)));
+    switch (i) {
+    case 0: r = v;  g = cc; b = aa; break;
+    case 1: r = bb; g = v;  b = aa; break;
+    case 2: r = aa; g = v;  b = cc; break;
+    case 3: r = aa; g = bb; b = v;  break;
+    case 4: r = cc; g = aa; b = v;  break;
+    case 5: r = v;  g = aa; b = bb; break;
+    }
+  }
+}
+
+void   SetColor(R f)
+{
+  float r,g,b; 
+  assert(global);
+  R fmin=global->zmin; // borne de la fonction
+  R fmax=global->zmax;
+  
+  hsvToRgb(0.99*(f-fmin)/(fmax-fmin),1,1,r,g,b);
+  glColor3f(r,g,b);
+}
+
+void DrawVertex(const  R2 & v,R z=0,R rapz=1) 
+{  
+  SetColor(z);             // la couleur
+  glVertex3f(v.x, v.y, z*rapz); // le sommet
+}
+
+void DrawIsoTfill(const R2 Pt[3],const R ff[3],const R * Viso,int NbIso, R rapz=1)
+{
+  R2 PQ[10];
+  R z[10];
+  
+  R eps= (Viso[NbIso-1]-Viso[0])*1e-6;
+  for(int l=1;l< NbIso;l++)  //   loop on the level curves 
+    {
+      R xfb = Viso[l-1];
+      R xfh = Viso[l];
+      assert(xfb < xfh);
+      int im=0;
+      for(int i=0;i<3;i++) // for the  3 edges 
+	{
+          int j=(i+1)%3;
+          R fi=(ff[i]);
+          R fj=(ff[j]);
+          R xxfb =  xfb;
+          R xxfh =  xfh;
+	  if (fj<fi ) Exchange(xxfb,xxfh);
+          R xf  = xxfb;
+	  if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+	    {
+	      if (Abs(fi-fj)>=0.1e-20)
+		{
+		  R  xlam=(fi-xf)/(fi-fj);
+		  z[im] =  ff[i] * (1.F-xlam)  +  ff[j]* xlam;
+		  PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+		  
+		}
+	    }
+          xf = xxfh;  
+	  if(((fi<=xf)&&(fj>=xf))||((fi>=xf)&&(fj<=xf)))
+	    {
+	      if (Abs(fi-fj)>=0.1e-20)
+		{
+		  R  xlam=(fi-xf)/(fi-fj);
+		  z[im] =  ff[i] * (1.F-xlam)  +  ff[j]* xlam;
+		  PQ[im++]   = Pt[i] * (1.F-xlam)  +  Pt[j]* xlam;
+		}
+	    }
+	  if (  xfb-eps <=fj  && fj <= xfh+eps) 
+	    z[im]=ff[j],PQ[im++] = Pt[j];
+	  
+	}
+      if (im>2) 
+	{
+          glBegin(GL_POLYGON);
+          SetColor((xfb+xfh)/2); 
+	  for (int i=0;i<im;i++)
+	    {// cout << i << " \t : " << PQ[i].x << " " <<  PQ[i].y << " " << z[i]*rapz << endl;
+	      glVertex3f(PQ[i].x, PQ[i].y,z[i]*rapz);
+	    }
+          glEnd();
+	  
+	}
+    }
+} 
+
+
+void Global::MakeListDraw() const
+{
+/*  
+  Mesh &Th =
+  glNewList(TheDrawList,GL_COMPILE); // save  la list sans affichage
+  R fmn=zmin, fmx=zmax; 
+  
+  glPolygonMode(GL_FRONT,GL_FILL); // mode affichage des polygones  
+  // constructions des triangles color�s
+  if (nbiso)
+    {
+      for (int i=0;i<Th.nt;i++)
+        {
+          const Triangle & K(Th[i]);
+	  R2 Pt[3]={K[0],K[1],K[2]};
+	  R ff[3]={f[Th(K[0])],f[Th(K[1])],f[Th(K[2])]};
+	  DrawIsoTfill(Pt,ff,viso,nbiso,rapz);
+	}
+    }
+  else
+    {
+      for (int i=0;i<Th.nt;i++)
+	{
+	  const Triangle & K(Th[i]); 
+	  int i0= Th(K[0]),  i1= Th(K[1]),   i2= Th(K[2]) ;    
+	  glBegin(GL_TRIANGLES);
+	  DrawVertex(K[0],f[i0],rapz);
+	  DrawVertex(K[1],f[i1],rapz);
+	  DrawVertex(K[2],f[i2],rapz);
+	  glEnd();
+	}
+    }
+  glEndList();  // fin de la list
+  */
+}
+
+void Clean() 
+{
+  glClearColor(1.0, 1.0, 1.0, 0.0);
+  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+}
+
+static void Reshape( int width, int height )
+{   
+  global->Width  = width;
+  global->Height = height;  
+  global->SetView();
+  glutPostRedisplay();
+}
+
+
+static void Key( unsigned char key, int x, int y )
+{
+  switch (key) {
+  case 27: // esc char
+    pthread_mutex_unlock(&mutexclose);
+    pthread_exit(&return_value);
+    break;
+  case '+':  
+    global->coef_dist /= 1.2;
+    break;
+  case '-':  
+    global->coef_dist *= 1.2;
+    break;
+  case 'g':  
+    global->theta += pi/180.;
+    break;
+  case 'd':  
+    global->theta -= pi/180.;
+    break;
+  case 'h':  
+    global->phi += pi/180.;
+    break;
+  case 'b':  
+    global->phi -= pi/180.;
+    break;
+  case 'a':
+    global->dtheta = pi/180.;
+    break;	
+  case 's':
+    global->dtheta = 0;
+    break;	
+  case '=':
+    global->DefaultView();
+    break;
+  default:
+    cout << " Key Character " << (int) key << " " << key << endl;  
+    
+  }
+  global->SetView();  
+  glutPostRedisplay();
+}
+
+void Display(void)
+{ 
+  Clean();
+  int n=global->nblist;
+  for (int i=1;i<=n;i++)
+     glCallList(i); 
+        
+  glFlush();    
+  glutSwapBuffers();
+}
+
+static void Idle( void )
+{
+  if (global->dtheta)
+    {
+      global->theta += pi/180.;
+      global->SetView();
+      glutPostRedisplay();
+    }
+  
+}
+static void Mouse( int button,int state,int x,int y )
+{
+  // state up or down 
+  if (state == GLUT_DOWN) { xold=x,yold=y;return;}
+  // cout << "Mouse " << button<< " " << state << " " << x-xold << " " << y-yold << endl;
+  //  x gauche -> droitre
+  //  y  haut -> bas`
+  global->phi += (y-yold)/(2.*180.);
+  global->theta -= (x-xold)/(2*180.);
+  global->SetView();  
+  glutPostRedisplay();
+  
+}
+static void MotionMouse(int x,int y )
+{
+ // cout << " MotionMouse " << " " << x << " " << y << endl;
+  GLuint gtime = glutGet(GLUT_ELAPSED_TIME); //   
+  global->phi += (y-yold)/(2.*180.);
+  global->theta -= (x-xold)/(2*180.);
+   xold=x;
+   yold=y;
+  global->SetView();  
+  glutPostRedisplay();
+}
+void SpecialKey(int key, int x, int y)
+{
+ // cout << " SpecialKey " << key << " " << x << " " << y << " : ";
+  R dx(0),dy(0);
+    switch (key) {
+        case  GLUT_KEY_LEFT:   dx = -1; break;
+        case  GLUT_KEY_RIGHT:  dx = +1; break;
+        case  GLUT_KEY_DOWN:   dy = -1; break;
+        case  GLUT_KEY_UP:     dy = +1; break;
+}
+   // calcul du deplacement de xm,ym,zm;
+  // cout << " " << dx << " " << dy << endl;
+    global->MoveXView(dx,dy);
+    global->SetView();  
+  glutPostRedisplay();
+
+}
+void * glutthread(void *argu)
+{
+    char ** argv =   (char **) ((void**) argu)[1];
+    int &  argc =  * (int *) ((void**) argu )[0]  ;
+
+    glutInit(&argc , argv);
+    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
+     int Height = 512;
+     int Width = 512; 
+     glutInitWindowSize(Width , Height);
+     glutInitWindowPosition(100, 100);
+     string titre = "vue de ";
+     titre += argv[1] ;
+     titre += ", ";
+     titre += argv[2];
+     glutCreateWindow(titre.c_str());
+     glutPushWindow();
+     cout << "mutex lock in  glut " << endl;
+     
+     pthread_mutex_lock(&mutex);
+     cout << " .. continue in glut " << endl;
+       assert(global);
+
+     global->Height=Height;
+     global->Width=Width;
+     
+     global->MakeListDraw();    
+     global->SetView(); 
+     pthread_mutex_unlock(&mutex);
+
+     glEnable(GL_DEPTH_TEST); 
+     glutReshapeFunc( Reshape ); // pour changement de fenetre 
+     glutKeyboardFunc( Key );    // pour les evenements clavier
+     glutSpecialFunc(SpecialKey);
+     glutMouseFunc(Mouse);       // pour les evenements sourie
+     glutMotionFunc(MotionMouse); // les mouvements  de la sourie 
+     glutDisplayFunc( Display ); // l'affichage
+     glutIdleFunc( Idle );       // l'animation automatique     
+     glutMainLoop(); 
+     return return_value;     
+}
+/*
+void * main1(void *argu)
+{
+    pthread_mutex_lock(&mutex);
+
+    char ** argv =   (char **) ((void**) argu)[1];
+    int &  argc =  * (int *) ((void**) argu )[0]  ;
+
+    if (argc <3)
+     {
+	cerr << " utilisation : " << argv[0] << " meshfile  solfile [rap in z ] [nbisovalue] " << endl;
+	return return_value;
+     }
+    global=0;
+
+    assert(argc>2);
+  R rapz=1; 
+  int nbiso=20;
+  if (argc>3) rapz=atof(argv[3]);
+  if (argc>4) nbiso=atoi(argv[4]);
+  cout << " Rap z " << rapz << endl;
+  Mesh Th(argv[1]);
+  Rn f(Th.nv); 
+  {
+    ifstream fdat(argv[2]);
+    assert(fdat.good());
+    fdat >> f;
+  } // pour ferme le fichier (la variable fdat est detruite)
+    // 
+  global=new Global(Th,f,100,100,rapz,nbiso);  
+  pthread_mutex_unlock(&mutex);
+  cout << " un lock in main " << endl;
+  
+
+  cout << " wait close " << endl;
+  pthread_mutex_lock(&mutexclose);
+  pthread_mutex_unlock(&mutexclose);
+  cout << "  close " << endl;
+   
+   return return_value;
+}
+
+int main(int argc, char** argv)
+{
+    global=0;
+    pthread_mutex_init(&mutex,NULL);
+    pthread_mutex_init(&mutexclose,NULL);
+    pthread_mutex_lock(&mutex);
+    pthread_mutex_lock(&mutexclose);
+     pthread_t tid;
+    void * argu[2]={ (void *) & argc, (void*) argv};
+    
+    
+    pthread_create(&tid,NULL,main1,(void *) argu);
+    pthread_mutex_unlock(&mutex);
+
+    glutthread(argu);
+    
+
+   
+   
+   void **value_ptr;
+  
+   pthread_join(tid,value_ptr );
+  
+   return 0;
+}
+
+*/
+
diff --git a/src/femlib/gmres.hpp b/src/femlib/gmres.hpp
new file mode 100644
index 0000000..f735ca9
--- /dev/null
+++ b/src/femlib/gmres.hpp
@@ -0,0 +1,183 @@
+//*****************************************************************
+// Iterative template routine -- GMRES
+//
+// GMRES solves the unsymmetric linear system Ax = b using the 
+// Generalized Minimum Residual method
+//
+// GMRES follows the algorithm described on p. 20 of the 
+// SIAM Templates book.
+//
+// The return value indicates convergence within max_iter (input)
+// iterations (0), or no convergence within max_iter iterations (1).
+//
+// Upon successful return, output arguments have the following values:
+//  
+//        x  --  approximate solution to Ax = b
+// max_iter  --  the number of iterations performed before the
+//               tolerance was reached
+//      tol  --  the residual after the final iteration
+//  
+//*****************************************************************
+// modif F. hecht to by compatible with RNM.hpp 
+// no dummy vector result 
+//  M.solve(xx)  => M*(xx) 
+//  dot(u,v) => (u,v)
+//  norm(u) => sqrt( (u,u) ) 
+
+#include <math.h> 
+
+
+template<class Real> 
+void GeneratePlaneRotation(Real &dx, Real &dy, Real &cs, Real &sn)
+{
+    if (dy == 0.0) {
+        cs = 1.0;
+        sn = 0.0;
+    } else if (abs(dy) > abs(dx)) {
+        Real temp = dx / dy;
+        sn = 1.0 / sqrt( 1.0 + temp*temp );
+        cs = temp * sn;
+    } else {
+        Real temp = dy / dx;
+        cs = 1.0 / sqrt( 1.0 + temp*temp );
+        sn = temp * cs;
+    }
+}
+
+
+template<class Real> 
+void ApplyPlaneRotation(Real &dx, Real &dy, Real &cs, Real &sn)
+{
+    Real temp  =  cs * dx + sn * dy;
+    dy = -sn * dx + cs * dy;
+    dx = temp;
+}
+
+template < class Matrix, class Vector >
+void 
+Update(Vector &x, int k, Matrix &h, Vector &s, Vector v[])
+{
+  Vector y(s);
+
+  // Backsolve:  
+  for (int i = k; i >= 0; i--) {
+    y(i) /= h(i,i);
+    for (int j = i - 1; j >= 0; j--)
+      y(j) -= h(j,i) * y(i);
+  }
+
+  for (int j = 0; j <= k; j++)
+    x += v[j] * y(j);
+}
+
+
+template < class Real >
+Real 
+abs(Real x)
+{
+  return (x > 0 ? x : -x);
+}
+
+
+template < class Operator, class Vector, class Preconditioner,
+           class Matrix, class Real, class CStop  >
+int 
+GMRES(const Operator &A, Vector &x, const Vector &b,
+      const Preconditioner &M, Matrix &H, int &m, int &max_iter,
+      Real &tol,long verbosity, CStop * Stop )
+{
+  Real resid;
+  int i, j = 1, k;
+  Vector s(m+1), cs(m+1), sn(m+1), w,r,Ax;
+  r=M*b;
+  Real normb = sqrt((r,r));
+  
+  Ax=A * x;
+  Ax=b-Ax;
+  r = M*(Ax);
+  Real beta = sqrt((r,r));
+  
+  if ( abs(normb) < 1.e-30)
+    normb = 1;
+  
+  if ((resid = beta / normb) <= tol) {
+    tol = resid;
+    max_iter = 0;
+    return 0;
+  }
+
+  Vector *v = new Vector[m+1];
+
+  while (j <= max_iter) {
+    v[0] = r / beta;    
+    s = 0.0;
+    s(0) = beta;
+    
+    for (i = 0; i < m && j <= max_iter; i++, j++) {
+      w = M*(Ax=A * v[i]);
+      for (k = 0; k <= i; k++) {
+        H(k, i) = (w, v[k]);
+        w -= H(k, i) * v[k];
+      }
+      H(i+1, i) = sqrt((w,w));
+      v[i+1] = w  / H(i+1, i) ; 
+
+      for (k = 0; k < i; k++)
+        ApplyPlaneRotation(H(k,i), H(k+1,i), cs(k), sn(k));
+      
+      GeneratePlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
+      ApplyPlaneRotation(H(i,i), H(i+1,i), cs(i), sn(i));
+      ApplyPlaneRotation(s(i), s(i+1), cs(i), sn(i));
+      if(verbosity>5 || (verbosity>2 && j%100==0) )
+       cout << "GMRES: " << j << " " << abs(s(i+1)) << " " <<  normb << " " 
+           <<  abs(s(i+1)) / normb << " < " << tol << endl;
+      bool stop = Stop && Stop->Stop(i,x,r);// bof ???? 
+      if (((resid = abs(s(i+1)) / normb) < tol )|| stop ) {
+	if(verbosity)
+	  cout << "GMRES converges: " << j << " " << abs(s(i+1)) << " " <<  normb << " " 
+           <<  abs(s(i+1)) / normb << " < " << tol << endl;
+      
+        Update(x, i, H, s, v);
+        tol = resid;
+        max_iter = j;
+        delete [] v;
+        return 0;
+      }
+    }
+    Update(x, i - 1, H, s, v);// chanhe FH oct 2010  m -1 -> i -1 (bug max_iter < m)
+    Ax = A*x;
+    Ax = b-Ax;
+    
+    r = M*(Ax);
+    beta = sqrt((r,r));
+    if(verbosity>4)
+      cout << "GMRES: restart" << j << " " << beta << " " <<  normb << " " 
+           <<  beta / normb << " < " << tol << endl;
+    if ((resid = beta / normb) < tol) {
+      tol = resid;
+      max_iter = j;
+      delete [] v;
+      return 0;
+    }
+  }
+  
+ if(verbosity)
+    cout << "WARNING: GMRES do not converges: " << j <<"/" << max_iter << ",  resid = " << resid 
+         << ", tol=  " << tol << ", normb "<< normb << endl;
+  tol = resid;
+  delete [] v;
+    
+  return 1;
+}
+
+template < class Operator, class Vector, class Preconditioner,
+class Matrix, class Real >
+int
+GMRES(const Operator &A, Vector &x, const Vector &b,
+      const Preconditioner &M, Matrix &H, int &m, int &max_iter,
+      Real &tol,long verbosity)
+{  
+    return
+    GMRES(A,x,b,M,H,m,max_iter,tol,verbosity,(StopGC<Real> *)0); }
+
+
diff --git a/src/femlib/libmesh5.c b/src/femlib/libmesh5.c
new file mode 100644
index 0000000..5c40784
--- /dev/null
+++ b/src/femlib/libmesh5.c
@@ -0,0 +1,1224 @@
+
+
+/*----------------------------------------------------------*/
+/*                                                          */
+/*                       LIBMESH V 5.0                      */
+/*                                                          */
+/*----------------------------------------------------------*/
+/*                                                          */
+/*    Description:        handle .meshb file format I/O     */
+/*    Author:                Loic MARECHAL                  */
+/*    Creation date:        feb 16 2007                     */
+/*    Last modification:    feb 23 2007                     */
+/*                                                          */
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Includes                                                 */
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <ctype.h>
+#include "libmesh5.h"
+
+
+/*----------------------------------------------------------*/
+/* Structures                                               */
+/*----------------------------------------------------------*/
+
+typedef struct
+{
+    int pos, typ, SolSiz, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ];
+    char fmt[ GmfMaxTyp ];
+}KwdSct;
+
+typedef struct
+{
+    int dim, ver, iter, mod, typ, cod, NexKwdPos;
+    double angle, bbox[3][2], time;
+    KwdSct KwdTab[ GmfMaxKwd + 1 ];
+    FILE *hdl;
+    char FilNam[ GmfStrSiz ];
+}GmfMshSct;
+
+
+/*----------------------------------------------------------*/
+/* Defines                                                    */
+/*----------------------------------------------------------*/
+
+#define Asc 1
+#define Bin 2
+#define MshFil 4
+#define SolFil 8
+#define MaxMsh 100
+#define InfKwd 1
+#define RegKwd 2
+#define SolKwd 3
+#define WrdSiz 4
+
+
+/*----------------------------------------------------------*/
+/* Global variables                                         */
+/*----------------------------------------------------------*/
+
+int NmbMsh=0;
+GmfMshSct *MshTab[ MaxMsh + 1 ];
+char *KwdFmt[ GmfMaxKwd + 1 ][3] = 
+{    {"Reserved", "", ""},
+    {"MeshVersionFormatted", "", "i"},
+    {"Reserved", "", ""},
+    {"Dimension", "", "i"},
+    {"Vertices", "i", "dri"},
+    {"Edges", "i", "iii"},
+    {"Triangles", "i", "iiii"},
+    {"Quadrilaterals", "i", "iiiii"},
+    {"Tetrahedra", "i", "iiiii"},
+    {"Pentahedra", "i", "iiiiiii"},
+    {"Hexahedra", "i", "iiiiiiiii"},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Corners", "i", "i"},
+    {"Ridges", "i", "i"},
+    {"RequiredVertices", "i", "i"},
+    {"RequiredEdges", "i", "i"},
+    {"RequiredTriangles", "i", "i"},
+    {"RequiredQuadrilaterals", "i", "i"},
+    {"TangentAtEdgeVertices", "i", "iii"},
+    {"NormalAtVertices", "i", "ii"},
+    {"NormalAtTriangleVertices", "i", "iii"},
+    {"NormalAtQuadrilateralVertices", "i", "iiii"},
+    {"AngleOfCornerBound", "", "r"},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"BoundingBox", "", "drdr"},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"End", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Reserved", "", ""},
+    {"Tangents", "i", "dr"},
+    {"Normals", "i", "dr"},
+    {"TangentAtVertices", "i", "ii"},
+    {"SolAtVertices", "i", "sr"},
+    {"SolAtEdges", "i", "sr"},
+    {"SolAtTriangles", "i", "sr"},
+    {"SolAtQuadrilaterals", "i", "sr"},
+    {"SolAtTetrahedra", "i", "sr"},
+    {"SolAtPentahedra", "i", "sr"},
+    {"SolAtHexahedra", "i", "sr"},
+    {"DSolAtVertices", "i", "sr"},
+    {"ISolAtVertices", "i", "i"},
+    {"ISolAtEdges", "i", "ii"},
+    {"ISolAtTriangles", "i", "iii"},
+    {"ISolAtQuadrilaterals", "i", "iiii"},
+    {"ISolAtTetrahedra", "i", "iiii"},
+    {"ISolAtPentahedra", "i", "iiiiii"},
+    {"ISolAtHexahedra", "i", "iiiiiiii"},
+    {"Iterations","","i"},
+    {"Time","","r"},
+    {"Reserved","",""}
+ };
+
+
+/*----------------------------------------------------------*/
+/* Prototypes of local procedures                            */
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *, unsigned char *);
+static void ScaDblWrd(GmfMshSct *, unsigned char *);
+static void RecWrd(GmfMshSct *, unsigned char *);
+static void RecDblWrd(GmfMshSct *, unsigned char *);
+static int ScaKwdTab(GmfMshSct *);
+static void ExpFmt(GmfMshSct *, int);
+static void ScaKwdHdr(GmfMshSct *, int);
+
+
+/*----------------------------------------------------------*/
+/* Open a mesh file in read or write mod                    */
+/*----------------------------------------------------------*/
+
+int GmfOpenMesh(const char *FilNam, int mod, ...)
+{
+    int KwdCod, res, *PtrVer, *PtrDim;
+    char str[ GmfStrSiz ];
+    va_list par;
+    GmfMshSct *msh;
+
+    /*---------------------*/
+    /* MESH STRUCTURE INIT */
+    /*---------------------*/
+
+    if( NmbMsh == MaxMsh) NmbMsh=0;  // Add J. Morice allow to read/write more than 100 mesh/sol 
+    if( !(msh = calloc(1, sizeof(GmfMshSct))) || (NmbMsh >= MaxMsh) )
+        return(0);
+
+    MshTab[ ++NmbMsh ] = msh;
+
+    /* Copy the FilNam into the structure */
+
+    if(strlen(FilNam) + 7 >= GmfStrSiz)
+        return(0);
+
+    strcpy(msh->FilNam, FilNam);
+
+    /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
+
+    msh->mod = mod;
+
+    if(strstr(msh->FilNam, ".meshb"))
+        msh->typ |= (Bin | MshFil);
+    else if(strstr(msh->FilNam, ".mesh"))
+        msh->typ |= (Asc | MshFil);
+    else if(strstr(msh->FilNam, ".solb"))
+        msh->typ |= (Bin | SolFil);
+    else if(strstr(msh->FilNam, ".sol"))
+        msh->typ |= (Asc | SolFil);
+    else
+        return(0);
+
+    /* Open the file in the required mod and initialyse the mesh structure */
+
+    if(msh->mod == GmfRead)
+    {
+
+        /*-----------------------*/
+        /* OPEN FILE FOR READING */
+        /*-----------------------*/
+
+        va_start(par, mod);
+        PtrVer = va_arg(par, int *);
+        PtrDim = va_arg(par, int *);
+        va_end(par);
+
+        /* Create the name string and open the file */
+
+        if(!(msh->hdl = fopen(msh->FilNam, "rb")))
+            return(0);
+        /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
+
+        if(msh->typ & Bin)
+        {
+            fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl);
+
+            if( (msh->cod != 1) && (msh->cod != 16777216) )
+                return(0);
+
+            ScaWrd(msh, (unsigned char *)&msh->ver);
+            ScaWrd(msh, (unsigned char *)&KwdCod);
+
+            if(KwdCod != GmfDimension)
+                return(0);
+
+            ScaWrd(msh, (unsigned char *)&KwdCod);
+            ScaWrd(msh, (unsigned char *)&msh->dim);
+        }
+        else
+        {
+            do
+            {
+                res = fscanf(msh->hdl, "%s", str);
+            }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
+
+            if(res == EOF)
+                return(0);
+
+            fscanf(msh->hdl, "%d", &msh->ver);
+
+            do
+            {
+                res = fscanf(msh->hdl, "%s", str);
+            }while( (res != EOF) && strcmp(str, "Dimension") );
+
+            if(res == EOF)
+                return(0);
+
+            fscanf(msh->hdl, "%d", &msh->dim);
+        }
+
+        if( (msh->dim != 2) && (msh->dim != 3) )
+            return(0);
+
+        (*PtrVer) = msh->ver;
+        (*PtrDim) = msh->dim;
+
+        /*------------*/
+        /* KW READING */
+        /*------------*/
+
+        /* Read the list of kw present in the file */
+
+        if(!ScaKwdTab(msh))
+            return(0);
+    }
+    else if(msh->mod == GmfWrite)
+    {
+
+        /*-----------------------*/
+        /* OPEN FILE FOR WRITING */
+        /*-----------------------*/
+
+        msh->cod = 1;
+
+        /* Check if the user provided a valid version number and dimension */
+
+        va_start(par, mod);
+        msh->ver = va_arg(par, int);
+        msh->dim = va_arg(par, int);
+        va_end(par);
+
+        if( (msh->ver != 1) && (msh->ver != 2) )
+            return(0);
+        if( (msh->dim != 2) && (msh->dim != 3) )
+            return(0);
+
+        /* Create the mesh file */
+
+        if(!(msh->hdl = fopen(msh->FilNam, "wb")))
+            return(0);
+
+
+        /*------------*/
+        /* KW WRITING */
+        /*------------*/
+
+        /* Write the mesh version and dimension */
+
+        if(msh->typ & Asc)
+        {
+            fprintf(msh->hdl, "%s %d\n\n", KwdFmt[ GmfVersionFormatted ][0], msh->ver);
+            fprintf(msh->hdl, "%s %d\n", KwdFmt[ GmfDimension ][0], msh->dim);
+        }
+        else
+        {
+            RecWrd(msh, (unsigned char *)&msh->cod);
+            RecWrd(msh, (unsigned char *)&msh->ver);
+            GmfSetKwd(NmbMsh, GmfDimension, 0);
+            RecWrd(msh, (unsigned char *)&msh->dim);
+        }
+    }
+    else
+        return(0);
+
+    return(NmbMsh);
+}
+
+
+/*----------------------------------------------------------*/
+/* Close a meshfile in the right way                        */
+/*----------------------------------------------------------*/
+
+int GmfCloseMesh(int MshIdx)
+{
+    int ret;
+    GmfMshSct *msh;
+
+    if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+        return(0);
+
+    msh = MshTab[ MshIdx ];
+
+    /* In write down the "End" kw in write mode */
+
+    if(msh->mod == GmfWrite)
+        {
+          if(msh->typ & Asc)
+            fprintf(msh->hdl, "\n%s\n", KwdFmt[ GmfEnd ][0]);
+          else
+            GmfSetKwd(MshIdx, GmfEnd, 0);
+        }
+
+    /* Close the file and free the mesh structure */
+    /* modif FH */
+    ret=fclose(msh->hdl);
+
+    free(msh);
+    fprintf(stdout,"NmbMsh=%d",NmbMsh);
+    return ret!=0;
+}
+
+
+/*----------------------------------------------------------*/
+/* Read the number of lines and set the position to this kwd*/
+/*----------------------------------------------------------*/
+
+int GmfStatKwd(int MshIdx, int KwdCod, ...)
+{
+    int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
+    GmfMshSct *msh;
+    KwdSct *kwd;
+    va_list par;
+
+    if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+        return(0);
+
+    msh = MshTab[ MshIdx ];
+
+    if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+        return(0);
+
+    kwd = &msh->KwdTab[ KwdCod ];
+
+    if(!kwd->NmbLin)
+        return(0);
+
+    /* Read further arguments if this kw is a sol */
+
+    if(kwd->typ == SolKwd)
+    {
+        va_start(par, KwdCod);
+
+        PtrNmbTyp = va_arg(par, int *);
+        *PtrNmbTyp = kwd->NmbTyp;
+
+        PtrSolSiz = va_arg(par, int *);
+        *PtrSolSiz = kwd->SolSiz;
+
+        TypTab = va_arg(par, int *);
+
+        for(i=0;i<kwd->NmbTyp;i++)
+            TypTab[i] = kwd->TypTab[i];
+
+        va_end(par);
+    }
+
+    return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Set the current file position to a given kwd                */
+/*----------------------------------------------------------*/
+
+int GmfGotoKwd(int MshIdx, int KwdCod)
+{
+    GmfMshSct *msh;
+    KwdSct *kwd;
+
+    if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+        return(0);
+
+    msh = MshTab[ MshIdx ];
+
+    if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+        return(0);
+
+    kwd = &msh->KwdTab[ KwdCod ];
+
+    if(!kwd->NmbLin)
+        return(0);
+
+    fseek(msh->hdl, kwd->pos, SEEK_SET);
+    return 0;
+}
+
+
+/*----------------------------------------------------------*/
+/* Write the kwd and set the number of lines                */
+/*----------------------------------------------------------*/
+
+int GmfSetKwd(int MshIdx, int KwdCod, ...)
+{
+    int i, CurPos, NmbLin=0, NulPos=0,  *TypTab;
+    va_list par;
+    GmfMshSct *msh;
+    KwdSct *kwd;
+
+    if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+        return(0);
+
+    msh = MshTab[ MshIdx ];
+
+    if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+        return(0);
+
+    kwd = &msh->KwdTab[ KwdCod ];
+
+    /* Read further arguments if this kw has a header */
+
+    if(strlen(KwdFmt[ KwdCod ][1]))
+    {
+        va_start(par, KwdCod);
+        NmbLin = va_arg(par, int);
+
+        if(!strcmp(KwdFmt[ KwdCod ][2], "sr"))
+        {
+            kwd->NmbTyp = va_arg(par, int);
+            TypTab = va_arg(par, int *);
+
+            for(i=0;i<kwd->NmbTyp;i++)
+                kwd->TypTab[i] = TypTab[i];
+        }
+
+        va_end(par);
+    }
+
+    /* Setup the kwd info */
+
+    ExpFmt(msh, KwdCod);
+
+    if(!kwd->typ)
+        return(0);
+    else if(kwd->typ == InfKwd)
+        kwd->NmbLin = 1;
+    else
+        kwd->NmbLin = NmbLin;
+
+    /* Store the next kwd position in binary file */
+
+    if( (msh->typ & Bin) && msh->NexKwdPos )
+    {
+        CurPos = ftell(msh->hdl);
+        fseek(msh->hdl, msh->NexKwdPos, SEEK_SET);
+        RecWrd(msh, (unsigned char *)&CurPos);
+        fseek(msh->hdl, CurPos, SEEK_SET);
+    }
+
+    /* Write the header */
+
+    if(msh->typ & Asc)
+    {
+        fprintf(msh->hdl, "\n%s\n", KwdFmt[ KwdCod ][0]);
+
+        if(kwd->typ != InfKwd)
+            fprintf(msh->hdl, "%d\n", kwd->NmbLin);
+
+        /* In case of solution field, write the extended header */
+
+        if(kwd->typ == SolKwd)
+        {
+            fprintf(msh->hdl, "%d ", kwd->NmbTyp);
+
+            for(i=0;i<kwd->NmbTyp;i++)
+                fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
+
+            fprintf(msh->hdl, "\n\n");
+        }
+    }
+    else
+    {
+        RecWrd(msh, (unsigned char *)&KwdCod);
+        msh->NexKwdPos = ftell(msh->hdl);
+        RecWrd(msh, (unsigned char *)&NulPos);
+
+        if(kwd->typ != InfKwd)
+            RecWrd(msh, (unsigned char *)&kwd->NmbLin);
+
+        /* In case of solution field, write the extended header at once */
+
+        if(kwd->typ == SolKwd)
+        {
+            RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+            for(i=0;i<kwd->NmbTyp;i++)
+                RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+        }
+    }
+
+    return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a full line from the current kwd                    */
+/*----------------------------------------------------------*/
+
+int GmfGetLin(int MshIdx, int KwdCod, ...)
+{
+    double *DblPtr, *DblSolTab;
+    float *FltPtr, *FltSolTab;
+    int i, j, *IntPtr;
+    va_list par;
+    GmfMshSct *msh = MshTab[ MshIdx ];
+    KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+    /* Start decoding the arguments */
+
+    va_start(par, KwdCod);
+
+    if(kwd->typ != SolKwd)
+    {
+        if(msh->ver == 1)
+        {
+            if(msh->typ & Asc)
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        FltPtr = va_arg(par, float *);
+                        fscanf(msh->hdl, "%f", FltPtr);
+                    }
+                    else
+                    {
+                        IntPtr = va_arg(par, int *);
+                        fscanf(msh->hdl, "%d", IntPtr);
+                    }
+                }
+            }
+            else
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        FltPtr = va_arg(par, float *);
+                        ScaWrd(msh, (unsigned char *)FltPtr);
+                    }
+                    else
+                    {
+                        IntPtr = va_arg(par, int *);
+                        ScaWrd(msh, (unsigned char *)IntPtr);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(msh->typ & Asc)
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        DblPtr = va_arg(par, double *);
+                        fscanf(msh->hdl, "%lf", DblPtr);
+                    }
+                    else
+                    {
+                        IntPtr = va_arg(par, int *);
+                        fscanf(msh->hdl, "%d", IntPtr);
+                    }
+                }
+            }
+            else
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        DblPtr = va_arg(par, double *);
+                        ScaDblWrd(msh, (unsigned char *)DblPtr);
+                    }
+                    else
+                    {
+                        IntPtr = va_arg(par, int *);
+                        ScaWrd(msh, (unsigned char *)IntPtr);
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        if(msh->ver == 1)
+        {
+            FltSolTab = va_arg(par, float *);
+
+            if(msh->typ & Asc)
+                for(j=0;j<kwd->SolSiz;j++)
+                    fscanf(msh->hdl, "%f", &FltSolTab[j]);
+            else
+                for(j=0;j<kwd->SolSiz;j++)
+                    ScaWrd(msh, (unsigned char *)&FltSolTab[j]);
+        }
+        else if(msh->ver == 2)
+        {
+            DblSolTab = va_arg(par, double *);
+
+            if(msh->typ & Asc)
+                for(j=0;j<kwd->SolSiz;j++)
+                    fscanf(msh->hdl, "%lf", &DblSolTab[j]);
+            else
+                for(j=0;j<kwd->SolSiz;j++)
+                    ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
+        }
+    }
+
+    va_end(par);
+
+    /* return the number of arguments filled */
+
+    return(kwd->SolSiz);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a full line from the current kwd                    */
+/*----------------------------------------------------------*/
+
+int GmfSetLin(int MshIdx, int KwdCod, ...)
+{
+    double d, *DblSolTab;
+    float f, *FltSolTab;
+    int i, j;
+    va_list par;
+    GmfMshSct *msh = MshTab[ MshIdx ];
+    KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+    /* Start decoding the arguments */
+
+    va_start(par, KwdCod);
+
+    if(kwd->typ != SolKwd)
+    {
+        if(msh->ver == 1)
+        {
+            if(msh->typ & Asc)
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        d = va_arg(par, double);
+                        fprintf(msh->hdl, "%g ", (float)d);
+                    }
+                    else
+                    {
+                        j = va_arg(par, int);
+                        fprintf(msh->hdl, "%d ", j);
+                    }
+                }
+            }
+            else
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        d = va_arg(par, double);
+                        f = d;
+                        RecWrd(msh, (unsigned char *)&f);
+                    }
+                    else
+                    {
+                        j = va_arg(par, int);
+                        RecWrd(msh, (unsigned char *)&j);
+                    }
+                }
+            }
+        }
+        else
+        {
+            if(msh->typ & Asc)
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        d = va_arg(par, double);
+                        fprintf(msh->hdl, "%.15lg ", d);
+                    }
+                    else
+                    {
+                        j = va_arg(par, int);
+                        fprintf(msh->hdl, "%d ", j);
+                    }
+                }
+            }
+            else
+            {
+                for(i=0;i<kwd->SolSiz;i++)
+                {
+                    if(kwd->fmt[i] == 'r')
+                    {
+                        d = va_arg(par, double);
+                        RecDblWrd(msh, (unsigned char *)&d);
+                    }
+                    else
+                    {
+                        j = va_arg(par, int);
+                        RecWrd(msh, (unsigned char *)&j);
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        if(msh->ver == 1)
+        {
+            FltSolTab = va_arg(par, float *);
+
+            if(msh->typ & Asc)
+                for(j=0;j<kwd->SolSiz;j++)
+                    fprintf(msh->hdl, "%g ", FltSolTab[j]);
+            else
+                for(j=0;j<kwd->SolSiz;j++)
+                    RecWrd(msh, (unsigned char *)&FltSolTab[j]);
+        }
+        else if(msh->ver == 2)
+        {
+            DblSolTab = va_arg(par, double *);
+
+            if(msh->typ & Asc)
+                for(j=0;j<kwd->SolSiz;j++)
+                    fprintf(msh->hdl, "%.15lg ", DblSolTab[j]);
+            else
+                for(j=0;j<kwd->SolSiz;j++)
+                    RecDblWrd(msh, (unsigned char *)&DblSolTab[j]);
+        }
+    }
+
+    va_end(par);
+
+    if(msh->typ & Asc)
+        fprintf(msh->hdl, "\n");
+
+    /* return the number of arguments filled */
+
+    return(kwd->SolSiz);
+}
+
+
+/*----------------------------------------------------------*/
+/*----------------------------------------------------------*/
+
+int GmfCpyLin(int InpIdx, int OutIdx, int KwdCod)
+{
+    double d;
+    float f;
+    int i, a;
+    GmfMshSct *InpMsh = MshTab[ InpIdx ], *OutMsh = MshTab[ OutIdx ];
+    KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
+
+    for(i=0;i<kwd->SolSiz;i++)
+    {
+        if(kwd->fmt[i] == 'r')
+        {
+            if(InpMsh->ver == 1)
+            {
+                if(InpMsh->typ & Asc)
+                    fscanf(InpMsh->hdl, "%f", &f);
+                else
+                    ScaWrd(InpMsh, (unsigned char *)&f);
+
+                d = f;
+            }
+            else
+            {
+                if(InpMsh->typ & Asc)
+                    fscanf(InpMsh->hdl, "%lf", &d);
+                else
+                    ScaDblWrd(InpMsh, (unsigned char *)&d);
+
+                f = (float)d;
+            }
+
+            if(OutMsh->ver == 1)
+                if(OutMsh->typ & Asc)
+                    fprintf(OutMsh->hdl, "%g ", f);
+                else
+                    RecWrd(OutMsh, (unsigned char *)&f);
+            else
+                if(OutMsh->typ & Asc)
+                    fprintf(OutMsh->hdl, "%.15g ", d);
+                else
+                    RecDblWrd(OutMsh, (unsigned char *)&d);
+        }
+        else
+        {
+            if(InpMsh->typ & Asc)
+                fscanf(InpMsh->hdl, "%d", &a);
+            else
+                ScaWrd(InpMsh, (unsigned char *)&a);
+
+            if(OutMsh->typ & Asc)
+                fprintf(OutMsh->hdl, "%d ", a);
+            else
+                RecWrd(OutMsh, (unsigned char *)&a);
+        }
+    }
+
+    if(OutMsh->typ & Asc)
+        fprintf(OutMsh->hdl, "\n");
+    return 0; 
+}
+
+
+/*----------------------------------------------------------*/
+/* Find every kw present in a meshfile                        */
+/*----------------------------------------------------------*/
+
+static int ScaKwdTab(GmfMshSct *msh)
+{
+    int KwdCod, NexPos, CurPos, EndPos;
+    char str[ GmfStrSiz ];
+
+    if(msh->typ & Asc)
+    {
+        /* Scan each string in the file until the end */
+
+        while(fscanf(msh->hdl, "%s", str) != EOF)
+        {
+            /* Fast test in order to reject quickly the numeric values */
+
+            if(isalpha(str[0]))
+            {
+                /* Search which kwd code this string is associated with, 
+                    then get its header and save the curent position in file (just before the data) */
+
+                for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
+                    if(!strcmp(str, KwdFmt[ KwdCod ][0]))
+                    {
+                        ScaKwdHdr(msh, KwdCod);
+                        break;
+                    }
+            }
+            else if(str[0] == '#')
+                while(fgetc(msh->hdl) != '\n');
+        }
+    }
+    else
+    {
+        /* Get file size */
+
+        CurPos = ftell(msh->hdl);
+        fseek(msh->hdl, 0, SEEK_END);
+        EndPos = ftell(msh->hdl);
+        fseek(msh->hdl, CurPos, SEEK_SET);
+
+        /* Jump through kwd positions in the file */
+
+        do
+        {
+            /* Get the kwd code and the next kwd position */
+
+            ScaWrd(msh, (unsigned char *)&KwdCod);
+            ScaWrd(msh, (unsigned char *)&NexPos);
+
+            if(NexPos > EndPos)
+                return(0);
+
+            /* Check if this kwd belongs to this mesh version */
+
+            if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
+                ScaKwdHdr(msh, KwdCod);
+
+            /* Go to the next kwd */
+
+            if(NexPos)
+                fseek(msh->hdl, NexPos, SEEK_SET);
+        }while(NexPos && (KwdCod != GmfEnd));
+    }
+
+    return(1);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read and setup the keyword's header                        */
+/*----------------------------------------------------------*/
+
+static void ScaKwdHdr(GmfMshSct *msh, int KwdCod)
+{
+    int i;
+    KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+    if(!strcmp("i", KwdFmt[ KwdCod ][1]))
+    {
+        if(msh->typ & Asc)
+            fscanf(msh->hdl, "%d", &kwd->NmbLin);
+        else
+            ScaWrd(msh, (unsigned char *)&kwd->NmbLin);
+    }
+    else
+        kwd->NmbLin = 1;
+
+    if(!strcmp("sr", KwdFmt[ KwdCod ][2]))
+    {
+        if(msh->typ & Asc)
+        {
+            fscanf(msh->hdl, "%d", &kwd->NmbTyp);
+
+            for(i=0;i<kwd->NmbTyp;i++)
+                fscanf(msh->hdl, "%d", &kwd->TypTab[i]);
+        }
+        else
+        {
+            ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+            for(i=0;i<kwd->NmbTyp;i++)
+                ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+        }
+    }
+
+    ExpFmt(msh, KwdCod);
+    kwd->pos = ftell(msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Expand the compacted format and compute the line size    */
+/*----------------------------------------------------------*/
+
+static void ExpFmt(GmfMshSct *msh, int KwdCod)
+{
+    int i, j, TmpSiz=0;
+    char chr, *InpFmt = KwdFmt[ KwdCod ][2];
+    KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+    /* Set the kwd's type */
+
+    if(!strlen(KwdFmt[ KwdCod ][1]))
+        kwd->typ = InfKwd;
+    else if(!strcmp(InpFmt, "sr"))
+        kwd->typ = SolKwd;
+    else
+        kwd->typ = RegKwd;
+
+    /* Get the solution-field's size */
+
+    if(kwd->typ == SolKwd)
+        for(i=0;i<kwd->NmbTyp;i++)
+            switch(kwd->TypTab[i])
+            {
+                case GmfSca    : TmpSiz += 1; break;
+                case GmfVec    : TmpSiz += msh->dim; break;
+                case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break;
+                case GmfMat    : TmpSiz += msh->dim * msh->dim; break;
+            }
+
+    /* Scan each character from the format string */
+
+    i = 0;
+
+    while(i < strlen(InpFmt))
+    {
+        chr = InpFmt[ i++ ];
+
+        if(chr == 'd')
+        {
+            chr = InpFmt[i++];
+
+            for(j=0;j<msh->dim;j++)
+                kwd->fmt[ kwd->SolSiz++ ] = chr;
+        }
+        else if(chr == 's')
+        {
+            chr = InpFmt[i++];
+
+            for(j=0;j<TmpSiz;j++)
+                kwd->fmt[ kwd->SolSiz++ ] = chr;
+        }
+        else
+            kwd->fmt[ kwd->SolSiz++ ] = chr;
+    }
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a four bytes word in a mesh file                    */
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+    unsigned char swp;
+
+    fread(wrd, WrdSiz, 1, msh->hdl);
+
+    if(msh->cod == 1)
+        return;
+
+    swp = wrd[3];
+    wrd[3] = wrd[0];
+    wrd[0] = swp;
+
+    swp = wrd[2];
+    wrd[2] = wrd[1];
+    wrd[1] = swp;
+}
+
+
+/*----------------------------------------------------------*/
+/* Read an eight bytes word in a mesh file                    */
+/*----------------------------------------------------------*/
+
+static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+    int i;
+    unsigned char swp;
+
+    fread(wrd, WrdSiz, 2, msh->hdl);
+
+    if(msh->cod == 1)
+        return;
+
+    for(i=0;i<4;i++)
+    {
+        swp = wrd[7-i];
+        wrd[7-i] = wrd[i];
+        wrd[i] = swp;
+    }
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a four bytes word in a mesh file                    */
+/*----------------------------------------------------------*/
+
+static void RecWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+    fwrite(wrd, WrdSiz, 1, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write an eight bytes word in a mesh file                    */
+/*----------------------------------------------------------*/
+
+static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+    fwrite(wrd, WrdSiz, 2, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Fortran 77 API                                            */
+/*----------------------------------------------------------*/
+
+int call(gmfopenmeshf77)(char *FilNam, int *mod, int *ver, int *dim, int StrSiz)
+{
+    int  i;
+    char TmpNam[ GmfStrSiz ];
+
+    for(i=0;i<StrSiz;i++)
+        TmpNam[i] = FilNam[i];
+
+    TmpNam[ StrSiz ] = 0;
+
+    if(*mod == GmfRead)
+        return(GmfOpenMesh(TmpNam, *mod, ver, dim));
+    else
+        return(GmfOpenMesh(TmpNam, *mod, *ver, *dim));
+}
+
+int call(gmfclosemeshf77)(int *idx)
+{
+    return(GmfCloseMesh(*idx));
+}
+
+int call(gmfstatkwdf77)(int *MshIdx, int *KwdIdx, int *NmbTyp, int *SolSiz, int *TypTab)
+{
+    if(!strcmp(KwdFmt[ *KwdIdx ][2], "sr"))
+        return(GmfStatKwd(*MshIdx, *KwdIdx, NmbTyp, SolSiz, TypTab));
+    else
+        return(GmfStatKwd(*MshIdx, *KwdIdx));
+}
+
+int call(gmfgotokwdf77)(int *MshIdx, int *KwdIdx)
+{
+    return(GmfGotoKwd(*MshIdx, *KwdIdx));
+}
+
+int call(gmfsetkwdf77)(int *MshIdx, int *KwdIdx, int *NmbLin, int *NmbTyp, int *TypTab)
+{
+    if(!strcmp(KwdFmt[ *KwdIdx ][2], "sr"))
+        return(GmfSetKwd(*MshIdx, *KwdIdx, *NmbLin, *NmbTyp, TypTab));
+    else if(strlen(KwdFmt[ *KwdIdx ][1]))
+        return(GmfSetKwd(*MshIdx, *KwdIdx, *NmbLin));
+    else
+        return(GmfSetKwd(*MshIdx, *KwdIdx));
+}
+
+int call(gmfgetvertex2df77)(int *MshIdx, float *x, float *y, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfVertices, x, y, ref));
+}
+
+int call(gmfgetvertex3df77)(int *MshIdx, float *x, float *y, float *z, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfVertices, x, y, z, ref));
+}
+
+int call(gmfsetvertex2df77)(int *MshIdx, float *x, float *y, int *ref)
+{
+    return(GmfSetLin(*MshIdx, GmfVertices, *x, *y, *ref));
+}
+
+int call(gmfsetvertex3df77)(int *MshIdx, float *x, float *y, float *z, int *ref)
+{
+    return(GmfSetLin(*MshIdx, GmfVertices, *x, *y, *z, *ref));
+}
+
+int call(gmfgettrianglef77)(int *MshIdx, int *p1, int *p2, int *p3, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfTriangles, p1, p2, p3, ref));
+}
+
+int call(gmfsettrianglef77)(int *MshIdx, int *p1, int *p2, int *p3, int *ref)
+{
+    return(GmfSetLin(*MshIdx, GmfTriangles, *p1, *p2, *p3, *ref));
+}
+
+int call(gmfgettetrahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfTetrahedra, p1, p2, p3, p4, ref));
+}
+
+int call(gmfsettetrahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+    return(GmfSetLin(*MshIdx, GmfTetrahedra, *p1, *p2, *p3, *p4, *ref));
+}
+
+int call(gmfgetedgef77)(int *MshIdx, int *p1, int *p2, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfEdges, p1, p2, ref));
+}
+
+int call(gmfsetedgef77)(int *MshIdx, int *p1, int *p2, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfEdges, *p1, *p2, *ref));
+}
+
+int call(gmfgetquadrilateralf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfQuadrilaterals, p1, p2, p3, p4, ref));
+}
+
+int call(gmfsetquadrilateralf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfQuadrilaterals, *p1, *p2, *p3, *p4, *ref));
+}
+
+int call(gmfgethexahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *p5, int *p6, int *p7, int *p8, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfHexahedra, p1, p2, p3, p4, p5, p6, p7, p8, ref));
+}
+
+int call(gmfsethexahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *p5, int *p6, int *p7, int *p8, int *ref)
+{
+    return(GmfGetLin(*MshIdx, GmfHexahedra, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *ref));
+}
diff --git a/src/femlib/libmesh5.h b/src/femlib/libmesh5.h
new file mode 100644
index 0000000..eb8d569
--- /dev/null
+++ b/src/femlib/libmesh5.h
@@ -0,0 +1,178 @@
+
+
+/*----------------------------------------------------------*/
+/*															*/
+/*						LIBMESH V 5.0						*/
+/*															*/
+/*----------------------------------------------------------*/
+/*															*/
+/*	Description:		handle .meshb file format I/O		*/
+/*	Author:				Loic MARECHAL						*/
+/*	Creation date:		feb 16 2007							*/
+/*	Last modification:	feb 23 2007							*/
+/*															*/
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Defines													*/
+/*----------------------------------------------------------*/
+
+#define GmfStrSiz 1024
+#define GmfMaxTyp 20
+#define GmfMaxKwd 79
+#define GmfMshVer 1
+#define GmfRead 1
+#define GmfWrite 2
+#define GmfSca 1
+#define GmfVec 2
+#define GmfSymMat 3
+#define GmfMat 4
+#define GmfFloat 1
+#define GmfDouble 2
+
+enum GmfKwdCod
+{
+	GmfReserved1, \
+	GmfVersionFormatted, \
+	GmfReserved2, \
+	GmfDimension, \
+	GmfVertices, \
+	GmfEdges, \
+	GmfTriangles, \
+	GmfQuadrilaterals, \
+	GmfTetrahedra, \
+	GmfPentahedra, \
+	GmfHexahedra, \
+	GmfReserved3, \
+	GmfReserved4, \
+	GmfCorners, \
+	GmfRidges, \
+	GmfRequiredVertices, \
+	GmfRequiredEdges, \
+	GmfRequiredTriangles, \
+	GmfRequiredQuadrilaterals, \
+	GmfTangentAtEdgeVertices, \
+	GmfNormalAtVertices, \
+	GmfNormalAtTriangleVertices, \
+	GmfNormalAtQuadrilateralVertices, \
+	GmfAngleOfCornerBound, \
+	GmfReserved5, \
+	GmfReserved6, \
+	GmfReserved7, \
+	GmfReserved8, \
+	GmfReserved9, \
+	GmfReserved10, \
+	GmfReserved11, \
+	GmfReserved12, \
+	GmfReserved13, \
+	GmfReserved14, \
+	GmfReserved15, \
+	GmfReserved16, \
+	GmfReserved17, \
+	GmfReserved18, \
+	GmfReserved19, \
+	GmfReserved20, \
+	GmfReserved21, \
+	GmfReserved22, \
+	GmfReserved23, \
+	GmfReserved24, \
+	GmfReserved25, \
+	GmfReserved26, \
+	GmfReserved27, \
+	GmfReserved28, \
+	GmfReserved29, \
+	GmfReserved30, \
+	GmfBoundingBox, \
+	GmfReserved31, \
+	GmfReserved32, \
+	GmfReserved33, \
+	GmfEnd, \
+	GmfReserved34, \
+	GmfReserved35, \
+	GmfReserved36, \
+	GmfReserved37, \
+	GmfTangents, \
+	GmfNormals, \
+	GmfTangentAtVertices, \
+	GmfSolAtVertices, \
+	GmfSolAtEdges, \
+	GmfSolAtTriangles, \
+	GmfSolAtQuadrilaterals, \
+	GmfSolAtTetrahedra, \
+	GmfSolAtPentahedra, \
+	GmfSolAtHexahedra, \
+	GmfDSolAtVertices, \
+	GmfISolAtVertices, \
+	GmfISolAtEdges, \
+	GmfISolAtTriangles, \
+	GmfISolAtQuadrilaterals, \
+	GmfISolAtTetrahedra, \
+	GmfISolAtPentahedra, \
+	GmfISolAtHexahedra, \
+	GmfIterations, \
+	GmfTime, \
+	GmfReserved38
+};
+
+
+/*----------------------------------------------------------*/
+/* External procedures										*/
+/*----------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+extern int GmfOpenMesh(const char *, int, ...);
+extern int GmfCloseMesh(int);
+extern int GmfStatKwd(int, int, ...);
+extern int GmfGotoKwd(int, int);
+extern int GmfSetKwd(int, int, ...);
+extern int GmfGetLin(int, int, ...);
+extern int GmfSetLin(int, int, ...);
+
+
+/*----------------------------------------------------------*/
+/* Fortran 77 API											*/
+/*----------------------------------------------------------*/
+
+#if defined(F77_NO_UNDER_SCORE)
+#define call(x) x
+#else
+#define call(x) x ## _
+#endif
+
+int call(gmfopenmeshf77)(char *, int *, int *, int *, int);
+int call(gmfclosemeshf77)(int *);
+int call(gmfstatkwdf77)(int *, int *, int *, int *, int *);
+int call(gmfgotokwdf77)(int *, int *);
+int call(gmfsetkwdf77)(int *, int *, int *, int *, int *);
+int call(gmfgetvertex2df77)(int *, float *, float *, int *);
+int call(gmfgetvertex3df77)(int *, float *, float *, float *, int *);
+int call(gmfsetvertex2df77)(int *, float *, float *, int *);
+int call(gmfsetvertex3df77)(int *, float *, float *, float *, int *);
+int call(gmfgettrianglef77)(int *, int *, int *, int *, int *);
+int call(gmfsettrianglef77)(int *, int *, int *, int *, int *);
+int call(gmfgettetrahedronf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfsettetrahedronf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfgetedgef77)(int *, int *, int *, int *);
+int call(gmfsetedgef77)(int *, int *, int *, int *);
+int call(gmfgetquadrilateralf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfsetquadrilateralf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfgethexahedronf77)(int *, int *, int *, int *, int *, int *, int *, int *, int *, int *);
+int call(gmfsethexahedronf77)(int *, int *, int *, int *, int *, int *, int *, int *, int *, int *);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------*/
+/* Transmesh private API									*/
+/*----------------------------------------------------------*/
+
+#ifdef TRANSMESH
+
+extern char *KwdFmt[ GmfMaxKwd + 1 ][3];
+extern int GmfCpyLin(int, int, int);
+
+#endif
diff --git a/src/femlib/mortar.cpp b/src/femlib/mortar.cpp
new file mode 100644
index 0000000..3a39d60
--- /dev/null
+++ b/src/femlib/mortar.cpp
@@ -0,0 +1,281 @@
+// ORIG-DATE:     Dec 2002 
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Mortar  model ( not used)
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#include <cmath>
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <fstream>
+//#include <strstream.h>
+//using namespace std;  //introduces namespace std
+#include "RNM.hpp"
+#include "rgraph.hpp"
+#include "fem.hpp"
+#include "FQuadTree.hpp"
+
+inline int NbOfSubTriangle(int k)
+{  
+   assert(k>0);
+   return  k*k;
+}
+
+
+inline int NbOfSubInternalVertices(int k)
+{ 
+   assert(k>0);
+   int  r= (k+2)*(k+1)/2;
+   assert(r>=0);
+   return r;
+}
+
+
+//  for the  mortar elements
+ Mesh::Mesh(const Mesh & Th,int * split,bool WithMortar)
+ { //  routine complique 
+   //  count the number of elements
+   
+    area=Th.area;
+    BoundaryAdjacencesHead=0;
+    BoundaryAdjacencesLink=0;
+    BoundaryEdgeHeadLink=0;
+    quadtree =0;
+    NbMortars=0;
+    mortars=0;
+    TheAdjacencesLink =0;
+    quadtree =0;
+    bedges=0;
+    neb =0;
+   R2 Pmin,Pmax;
+   Th.BoundingBox(Pmin,Pmax);
+   nt=0;
+   for (int i=0;i<Th.nt;i++)
+     nt += NbOfSubTriangle(split[i]);
+   triangles = new Triangle[nt];
+   assert(triangles);
+   //  computation of thee numbers of vertices
+   //  on decoupe tous betement
+   // et on recolle le points ensuite 
+   // avec le quadtree qui sont sur les aretes ou les sommets 
+   //  calcul du magorant du nombre de sommets 
+   int nvmax=Th.nv;
+//  attention il faut supprime les aretes frontiere  interne    
+   for (int ieb=0,jj;ieb<Th.neb;ieb++)
+       neb += split[Th.BoundaryElement(ieb,jj)];
+   int nebmax=neb;
+   
+   for (int i=0;i<Th.nt;i++)
+     nvmax += NbOfSubInternalVertices(split[i]) -3;
+
+  //  compute the minimal Hsize of the new mesh  
+  R hm = Th[0].h();
+//  cout << " hm " << hm << endl;
+  for (int it=0;it<Th.nt;it++)
+    { 
+      assert(split[it]>0 && split[it]<=64);
+//      cout << " it = " <<it << " h " <<  Th[it].h() << " " << split[it] << " hm = " << hm <<  endl;
+      hm=Min(hm,Th[it].h()/(R) split[it]);
+    }
+   R seuil=hm/4.0;
+   cout << " seuil = " <<  seuil << " hmin = " << hm <<  endl; 
+   assert(seuil>1e-15);
+   vertices = new Vertex[nvmax];
+   assert( vertices && Th.nv <= nvmax);
+   
+   //  copy of the old vertices 
+   for (int i=0;i<Th.nv;i++)
+     vertices[i] = Th(i);
+     
+   nv = Th.nv;
+   
+   quadtree = new FQuadTree(this,Pmin,Pmax,nv); //  put all the old vertices in the quadtree 
+   bedges = new BoundaryEdge[nebmax];
+   assert(bedges);
+//  generation of the boundary edges
+   neb =0;
+   for (int ieb=0,jj;ieb<Th.neb;ieb++)
+       {  
+          int kold = Th.BoundaryElement(ieb,jj);
+          int n=split[kold];
+          
+          int n1=n+1;
+          BoundaryEdge & be(Th.bedges[ieb]);
+          Vertex *pva= vertices + (&be[0]-Th.vertices);
+          Vertex *pvb= vertices + (&be[1]-Th.vertices);
+          Vertex *pv0=pva;
+          R2 A(*pva),B(*pvb);
+          R la = 1,lb=0, delta=1.0/n;
+          
+          for (int j=1;j<n;j++) 
+           { 
+             la-=delta;
+             lb+=delta;
+             assert(nv<nvmax);
+             Vertex *pv1= vertices + nv;
+             
+             (R2 &) *pv1 = A*la + B*lb;
+             (Reference &) *pv1 = (Reference) be;
+             quadtree->Add(*pv1);
+             nv++;
+             assert(neb<nebmax);
+             bedges[neb].vertices[0]=pv0;
+             bedges[neb].vertices[1]=pv1;
+             (Reference &) bedges[neb]= be;
+             neb++;
+             pv0=pv1;
+           }
+         assert(neb<nebmax);
+         bedges[neb].vertices[0]=pv0;
+         bedges[neb].vertices[1]=pvb;
+         (Reference &) bedges[neb]= be;
+         neb++;
+       }    
+    assert(neb==nebmax);
+    
+//   create the new vertices and the new triangle 
+   int kerr=0,kt=0;
+   for (int K=0;K<Th.nt;K++)
+    { // cout << K << endl;
+      Triangle &T(Th[K]);
+      R2 A(T[0]);
+      R2 B(T[1]);
+      R2 C(T[2]);
+      long N=split[K];
+      long N2=N*N;
+      int vt[3];
+      for (int n=0;n<N2;n++,kt++) //  loop on all sub triangle
+        {
+          //(Reference&) triangles[kt] = (Reference&) T; 
+          for(int j=0;j<3;j++) //  Loop on the 3 vertices
+           { R2 PTj=SubTriangle(N,n,j);
+             R la=1-PTj.x-PTj.y,lb=PTj.x,lc=PTj.y;
+             R2 Pj= A*la+B*lb+C*lc; 
+             Vertex *pV;
+             pV=quadtree->ToClose(Pj,seuil);
+             if(!pV)
+             { // new vertex
+               //  cout << "    -- " << nv << "  New Vertices " << Pj << " n=" << n << " j=" << j << " " << PTj << endl;
+                 assert(nv<nvmax);
+                 vertices[nv]=Pj;
+                 (Reference&) vertices[nv]=0; //  Internal vertices 
+                 pV = vertices + nv;
+                 quadtree->Add(*pV);
+                 nv++;                  
+               }  //  end of new vertex
+               vt[j]=number(pV); 
+           //  triangles[kt].SetVertex(j,pV);
+           } // for(int j=0;j<3;j++)
+          // cout << kt << " " << n << endl;
+           R2 A=vertices[vt[0]];
+           R2 B=vertices[vt[1]];
+           R2 C=vertices[vt[2]]; 
+           R a = (( B-A)^(C-A))*0.5;
+           if (a>0) 
+             triangles[kt] = Triangle(vertices,vt[0],vt[1],vt[2],T.ref);
+           else 
+             triangles[kt] = Triangle(vertices,vt[0],vt[2],vt[1],T.ref);
+           
+        }   // end loop on all sub triangle
+   
+     } //  end 
+    
+   cout << " -- Nb of vertices       " << nv << endl; 
+   cout << " -- Nb of triangle       " << nt << endl; 
+   cout << " -- Nb of boundary edges " << neb << endl; 
+//  
+   if (!WithMortar)   
+    { // 
+      long nba = neb;
+     // 
+     long nbsd = 1; // bofbof 
+      // faux just pour un test 
+      long  *sd;
+      nbsd=1;
+      sd=new long[2*nbsd];
+      sd[0]=-1;
+      sd[1]=Th[0].ref;         
+       
+      long nbs=nv;
+      long nbsmax=nv;
+      long            err = 0, nbsold = nbs;       
+      long           *c = 0;
+      long           *tri = 0;
+      long           *nu = 0;
+      long           *reft = 0;
+      float          *cr = 0;
+      float          *h = 0;
+      long nbtmax = 2 * nbsmax;
+      long * arete  = new long[2*nba]; 
+      nu = new long[6*nbtmax];
+      c = new long[2*nbsmax];
+      tri = new long[(4 * nbsmax + 2 * nbsd)];
+      reft = new long[nbtmax];
+      cr = new float[(2 * nbsmax + 2)];
+      h = new float[nbsmax];
+      for(int i=0,k=0; i<nv; i++)
+       { 
+          cr[k++]  =vertices[i].x;
+          cr[k++]=vertices[i].y;
+          h[i]=1; 
+       }
+      for (int i=0,k=0 ;i<neb;i++)
+       {
+          arete[k++] =number(bedges[i][0])+1;
+          arete[k++] =number(bedges[i][1])+1;
+       }
+       
+       
+extern int 
+mshptg_ (float *cr, float *h, long *c, long *nu, long *nbs, long nbsmx, long *tri,
+	 long *arete, long nba, long *sd,
+	 long nbsd, long *reft, long *nbt, float coef, float puis, long *err);
+      
+      long nbt=0;
+      mshptg_ (cr, h, c, nu, &nbs, nbs, tri, arete, nba, (long *) sd, nbsd, reft, &nbt, .25, .75, &err);
+      assert(err==0 && nbt !=0);
+      delete [] triangles;
+      nt = nbt;
+      cout << " Nb Triangles = " << nbt << endl;
+      triangles = new Triangle[nt];
+      for(int i=0,k=0;i<nt;i++,k+=3)
+         triangles[i]=Triangle(vertices,nu[k]-1,nu[k+1]-1,nu[k+2]-1,reft[i]);
+      delete [] arete;
+      delete [] nu;
+      delete [] c;
+      delete [] tri;
+      delete [] reft;
+      delete [] cr;
+      delete [] h;
+      delete [] sd;
+      
+    }
+   ConsAdjacence();
+}
diff --git a/src/femlib/mshptg.cpp b/src/femlib/mshptg.cpp
new file mode 100644
index 0000000..a69cf49
--- /dev/null
+++ b/src/femlib/mshptg.cpp
@@ -0,0 +1,2238 @@
+// -*- Mode : c++ -*-
+//
+// -*- Mode : c++ -*-
+//
+// SUMMARY  : mshptg mesh generator ( form mshptg.f / inria / emc2 software) 
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+ 
+
+// bof bof FH je ne sais pas pourquoi nnnBAMG_LONG_LONG
+// nov 2005 j'ai corrige les problemes 
+// il y avait un gros bug de le trie
+// overflow long  car on calculais   x*x + y*y 
+// pour que cela tienne dans un  long long  
+//  x*x + y*y  < 2^63-1 =>  x et y  < 2^31-1 
+// --- 
+#include <iostream> 
+using namespace std;
+
+#ifdef BAMG_LONG_LONG
+#define LONG8 long long
+#define DLONG8LONG8 1.e17
+#define MAXCOOR ((double) 1073741823)// 2^30-1=1073741823. )
+#else
+#define LONG8 long 
+#define DLONG8LONG8 1e9
+#define MAXCOOR ((double) 32767. )
+#endif
+#define DET8(a11,a12,a21,a22) ( (LONG8) (a11) * (LONG8) (a22) - (LONG8) (a21)* (LONG8) (a12))
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+namespace Fem2D {
+#define i_nint(x) ((long) x >= 0 ? x + 0.5 : x - 0.5)
+#define amin(a, b) ((a) < (b) ? (a) : (b))
+#define amax(a, b) ((a) < (b) ? (b) : (a))
+#define aabs(a) ((a) < 0 ? -(a) : (a))
+
+static long     nothing = -1073741824L;
+
+
+
+/*****************************************************************************
+I. Fabrique une triangulation (de nbsmax sommets maxi.) a partir de:
+--------------------------------------------------------------------
+    -cr: tableau de taille 2*nbs (abscisse & ordonnees des points en entree)
+    -arete: tableau de taille 2*nba (depart & arrivee des aretes)
+      (decrire le contour dans le sens direct: domaine a
+            gauche des aretes exterieures)
+    -h: tableau de taille nbs (precision relative aux points en entree)
+
+
+II. Alloue et affecte une structure t de type triangulation:
+------------------------------------------------------------
+     -t.np: nombre de sommets en sortie
+     -t.nt: nombre de triangles en sortie
+     -t.rp[i].x:} abscisse
+      t.rp[i].y:} & ordonnee du ieme point du maillage
+     -t.tr[i][j]: numero du jeme point du ieme triangle du maillage
+
+
+III. Renvoie le type d'erreur:
+------------------------------
+     -  0 : pas d'erreur
+     -(-1): pas assez de memoire
+     - >0 : erreur mshptg8_
+  mshptg erreurs
+1: mshptg := 'le nb de point est < 3 or > que le nb max de point';
+2: mshptg := 'il y des points confondus ';
+3: mshptg := 'tout les points sont align�s ';
+7: mshptg := 'bug dans l''algorithme pour retrouver la fronti�re (Internal Bug mshfrt)';
+8: mshptg := 'Une ar�te a forcer traverse trop de triangles (Internal Bug : mshfr1)';
+9: mshptg := 'la fronti�re est crois�e ';
+10: mshptg := 'il y a un point qui est sur une ar�te fronti�re';
+11: mshptg := 'Un sous domaine est reference par aucun triangle ';
+20: mshptg := 'mshopt: 3 points confondus (Internal Bug) ';
+21: mshptg := 'la pile de mshopt est trop petit (Internal Bug)';
+
+
+
+    Remarque: penser a liberer les pointeurs t.rp et t.tr!!!
+    --------- un tableau de taille N est indexe de 0 a N-1
+        les numeros affectes aux points et aux triangles commencent a 0
+******************************************************************************/
+/*
+long 
+MakeTriangulation (triangulation * t, long nbs, long nbsmax, long nba,
+		   double *crbdy, double *hbdy, long *arete, int *ngbdy, long *sd, long nbsd, int* flag, int fflag)
+{
+  int             i, j;
+  long            err = 0, nbt, nbsold = nbs;
+  long           *c = NULL;
+  long           *tri = NULL;
+  long           *nu = NULL;
+  long           *reft = NULL;
+  int            *ngg = NULL;
+  double          *cr = NULL;
+  double          *h = NULL;
+
+  nbt = 2 * nbsmax;
+  nu = new long[6*nbt];
+  c = new long[2*nbsmax];
+  ngg = new int[nbsmax];
+  tri = new long[(4 * nbsmax + 2 * nbsd)];
+  reft = new long[nbt];
+  cr = new double[(2 * nbsmax + 2)];
+  h = new double[nbsmax];
+
+  for (i = 0; i < 2 * nba; i++)
+    arete[i]++;
+  for (i = 0; i < nbs; i++)
+     {
+       ngg[i] = ngbdy[i];
+       cr[2 * i] = crbdy[2 * i];
+       cr[2 * i + 1] = crbdy[2 * i + 1];
+       h[i] = hbdy[i];
+     }
+  for (i = nbs; i < nbsmax; i++)
+    ngg[i] = 0;
+
+  mshptg8_ (cr, h, c, nu, &nbs, nbsmax, tri, arete, nba, (long *) sd, nbsd, reft, &nbt, .25, .75, &err);
+  for (i = 0; i < 2 * nba; i++)
+    arete[i]--;
+  if (err)
+    goto L1;
+  if (*flag)
+     {
+       delete [] t->rp;t->rp = NULL;
+       delete [] t->tr;t->tr = NULL;
+       delete [] t->ng;t->ng = NULL;
+       delete [] t->ngt;t->ngt = NULL;
+     }
+  t->rp =new rpoint[nbs];
+  t->tr = new triangle[nbt];
+  t->ng = new int[nbs];
+  t->ngt = new int[nbt];
+
+  *flag = 1;
+  t->np = nbs;
+  t->nt = nbt;
+  for (i = 0; i < nbt; i++)
+     {
+       for (j = 0; j < 3; j++)
+	 t->tr[i][j] = nu[3 * i + j] - 1;
+       t->ngt[i] = reft[i] - 1;
+     }
+  for (i = 0; i < nbs; i++)
+     {
+       t->rp[i].x = cr[2 * i];
+       t->rp[i].y = cr[2 * i + 1];
+       if (i < nbsold)
+	 t->ng[i] = ngg[i];
+       else
+	 t->ng[i] = 0;
+     }
+  renum (t);
+  if(!fflag) removeBdyT (t);
+L1:
+  delete [] nu;nu = NULL;
+  delete [] cr;cr = NULL;
+  delete [] c;c = NULL;
+  delete [] tri;tri = NULL;
+  delete [] reft;reft = NULL;
+  delete [] ngg;ngg  = NULL;
+  delete [] h;h = NULL;
+  return err;
+}
+
+
+
+int 
+verifietr (double *cr, int ns)
+{
+  int             i;
+  double           xh, diameter = 1.F;
+
+  if (ns == 0)
+    return -1;
+  if (ns > 1)
+     {
+       diameter = 0.F;
+       for (i = 0; i < ns; i++)
+	 diameter = amax (diameter, aabs (cr[2 * i] - cr[0]) + aabs (cr[2 * i + 1] - cr[1]));
+     }
+  else
+    diameter = 0.001F;
+  for (i = 0; i < ns; i++)
+     {
+       xh = aabs (cr[2 * i] - cr[2 * ns]) + aabs (cr[2 * i + 1] - cr[2 * ns + 1]);
+       if (xh < 1e-5 * diameter)
+	 return i;
+     }
+  return -1;
+}
+
+*/
+
+int             mshrgl_ (double *c, long *nrfs, long *nbs, long *nu, long *w1,
+			 long *w, double omega, long itermx, double eps);
+int             mshopt_ (long *c, long *nu, long *t, long a, long *err);
+void            mshvoi_ (long *nu, long *w1, long *w, long *nbt, long *nbs);
+int             msha1p_ (long *t, long *s, long *c, long *nu, long *reft, long *tete, long *nbt,
+			 long *err);
+int             mshtri_ (double *cr, long *c, long *nbs, long *tri, LONG8 *nu, double *trfri, long *err);
+int             mshcxi_ (long *c, long *nu, long *tri, long *nbs, long *tete, long *err);
+int             mshfrt_ (long *c, long *nu, long *nbs, long *arete, long nba, long *sd,
+			 long nbsd, long *reft, long *w, long *err);
+int             mshgpt_ (long *c, double *cr, long *nu, double *h, long *reft, long *nbs,
+    long nbsmx, long *nbt, double coef, double puis, double *trfri, long *err);
+long            mshlcl_ (long *c, long *nu, long *tete, long *s);
+int             mshtr1_ (LONG8 *criter, long *record, long *n);
+int             mshcvx_ (long direct, long *c, long *nu, long *pfold, long *err);
+int             mshfr1_ (long *c, long *nu, long *it1, long *ita, long *is1, long *s2, long *err);
+int             mshfr2_ (long *c, long *nu, long *lst, long *nbac, long *t, long *ta,
+			 long *ss1, long *ss2, long *err);
+
+int 
+mshptg8_ (double *cr, double *h, long *c, long *nu, long *nbs, long nbsmx, long *tri,
+	 long *arete, long nba, long *sd,
+	 long nbsd, long *reft, long *nbt, double coef, double puis, long *err)
+{
+  /* System generated locals */
+  long            i_1;
+
+  /* Local variables */
+  static long     tete, i, j, k, t;
+  static double    trfri[4];
+  static long     nbsgrn, nbtgrn;
+
+/* ----------------------------------------------------------------------- */
+/*      but:  construire une triangulation a partir d'un ensemble de */
+/*             points et d'un maillage frontalier */
+/* ----------------------------------------------------------------------- */
+/*     entre : */
+/*     ------- */
+/*           cr(2,nbsmx)  tableau des coordonnees des nbs points donnes */
+
+
+/*           h (nbsmx)    tableau du h local voulu autour de chaque point */
+/*                          donnes */
+/*           nbs          nombre de points donnes */
+/*           nbsmx        nombre de points maximal a cree */
+/*                        si nbs  = nbsmx ont ne cree pas de points */
+/*                        si nbs  < nbsmx => erreur */
+/*           arete(2,nba) tableau des aretes du maillage a forcer */
+/*                          exemple :la frontiere */
+/*           nba          le nombre d'aretes du maillage */
+/*           sd(2,nbsd)   tableau definisant les nbsd  sous domaine */
+/*                          (reference des triangles gerener) */
+/*                          abs(sd(1,i)) =  numero d'une l'arete */
+/*                          si sd(1,i) est positive alors le sous domaine */
+/*                          est a gauche de l'arete sinon il est a droite */
+/*                          sd(2,i) donne le numero du sous doimaine */
+
+/*           puis         coefficient de generation des points */
+/*                        .1  => on propage plus loin les rafinement */
+/*                               donnes par h */
+/*                        .25 => valeur conseillee */
+/*           coef         coefficient sur le test arret */
+/*                          le valeur conseillee est .75 */
+/*                          remarque le nombre de point genere est en */
+/*                          O(coef**2) */
+
+/*        tableaux de travail: */
+/*        -------------------- */
+/*           c(2,nbsmx)    tableau d'entiers (copie de coordonnees) */
+/*           tri(ltri)     tableau d'entiers */
+/*        out : */
+/*        ----- */
+/*         nbs         nombre de points   donnes + generes */
+/*         nbt         nombre de triangles generes */
+/*         cr(1:2,nbs) coordonnees des sommets donnes + generes */
+/*         nu(1:3,nbt) sommets des triangles (tableau des connections) */
+/*                       telle que les sommets tourne dans le sens direct */
+/*         reft(1:nbt) numero de sous domaine de chaque triangle */
+/*         err    si err = 0 alors pas de probleme */
+/*                sinon nbt = 0 et pas de triangulation */
+/*     dimension des tableaux */
+/*     ---------------------- */
+/*     definition des parameters */
+/*     nbtmx = 2*(nbs-1) ,  ltri = max(4*nbs+2*nbsd,nba) */
+/*     long : nu(6*nbtmx) , reft(nbtmx) , c(2*nbsmx) , tri(ltri) */
+/*     long : arete(2,nba), sd(2,nbsd) */
+/*     double    : cr(2*nbsmx) , h(nbsmx) */
+
+/* ---------------------------------------------------------------------- */
+/*     programmeur F.Hecht, France */
+/*           version 1.0  mars 1986 */
+/* ----------------------------------------------------------------------- */
+
+  /* Parameter adjustments */
+  --reft;
+  sd -= 3;
+  arete -= 3;
+  --tri;
+  --nu;
+  c -= 3;
+  --h;
+  cr -= 3;
+
+  /* Function Body */
+  *err = 0;
+  *nbt = 0;
+  if (*nbs < 3 || nbsmx < *nbs)
+     {
+       *err = 1;
+       printf("mshptg bug in number of points %ld > %ld == max nb points \n",*nbs,nbsmx);
+       return 0;
+     }
+/* ------------------------- */
+/* preparation des donnees */
+/* ------------------------- */
+  mshtri_ (&cr[3], &c[3], nbs, &tri[1], (LONG8*) (void *) &tri[*nbs + 1], trfri, err);
+  if (*err != 0)
+     {
+       return 0;
+     }
+/* -------------------------------- */
+/* maillage de l enveloppe convexe */
+/* -------------------------------- */
+  mshcxi_ (&c[3], &nu[1], &tri[1], nbs, &tete, err);
+/* ----------------------------------------------------------------------- */
+/*     definition de tableau nu(1:6,2*nbs-2) */
+/* ----------------------------------------------------------------------- */
+/*     nu(*,ie) definit soit un element ,soit un sommet frontiere */
+/*     si nu(5:6,ie) = (0,0) alors ie est un sommet frontiere */
+/*     avec nu(1,ie) = numero du sommet */
+/*          nu(2,ie) = 8*t + a */
+/*                     ou t est le numero du triangle ayant l'arete */
+/*                     frontiere (a) dont le premier sommet est nu(1,ie) */
+/*          nu(3,ie) = pointeur dans nu sur sommet frontiere precedent */
+/*          nu(4,ie) = pointeur dans nu sur sommet frontiere suivant */
+/*     sinon ie est un element : */
+/*          nu(1:3,ie) numero des 3 sommets du triangle ie tournant dans */
+/*                     le sens direct */
+/*          nu(4:6,ie) = (d4,d5,d6) donnee des 3 aretes ai */
+/*           ai est forme des sommets nu(i-3,ie),nu(mod(i,3)+1,ie) */
+/*           si di < 0 alors arete i est frontiere et -di est pointeur */
+/*             sur 1er sommet frontiere de i */
+/*           sinon arete est interne et di = 8*ta + ata */
+/*              ou ta est le numero du triangle adjacent a l'arete */
+/*              et ata est le numero de l'arete dans ta */
+/* ------------------------------------------------------------------------ */
+  if (*err != 0)
+     {
+       return 0;
+     }
+
+  i_1 = *nbs;
+  for (i = 1; i <= i_1; ++i)
+     {
+       tri[i] = 0;
+     }
+  i = tete;
+L20:
+  j = nu[(i - 1) * 6 + 4];
+  tri[nu[(i - 1) * 6 + 1]] = nu[(j - 1) * 6 + 1];
+  i = j;
+  if (i != tete)
+     {
+       goto L20;
+     }
+/* ----------------------------- */
+/* traitement frontiere */
+/* ----------------------------- */
+  k = 0;
+  mshfrt_ (&c[3], &nu[1], nbs, &arete[3], nba, &sd[3], nbsd, &reft[1], &tri[
+								   1], err);
+  if (*err != 0)
+     {
+       return 0;
+     }
+/* ------------------------------------------------------------------- */
+/*       on a modifie nu les sommets frontiere n'ont plus de sens */
+/*       ainsi que les pointeurs sur ces elements */
+/* ------------------------------------------------------------------- */
+  nbsgrn = *nbs;
+  mshgpt_ (&c[3], &cr[3], &nu[1], &h[1], &reft[1], &nbsgrn, nbsmx, &nbtgrn,
+	   coef, puis, trfri, err);
+  if (*err != 0)
+     {
+       return 0;
+     }
+/*     construction du tableau nu(1:3,1:nbt) */
+/* ------------------------------------------ */
+  *nbt = 0;
+  k = 0;
+  j = 1;
+  i_1 = nbtgrn;
+  for (t = 1; t <= i_1; ++t)
+     {
+       if (nu[j + 5] != 0)
+	  {
+	    ++(*nbt);
+	    reft[*nbt] = reft[t];
+	    for (i = 0; i <= 2; ++i)
+	       {
+		 ++k;
+		 nu[k] = nu[j + i];
+	       }
+	  }
+       j += 6;
+     }
+/*     dans nu il y a (s1(t),s2(t),s3(t),t=1,nbt) */
+/*     ou s1 s2 s3 sont les 3 sommets de t */
+/* ------------------------------------------------ */
+  i_1 = *nbs;
+  for (i = 1; i <= i_1; ++i)
+     {
+       tri[i] = 1;
+     }
+  i_1 = nbsgrn;
+  for (i = *nbs + 1; i <= i_1; ++i)
+     {
+       tri[i] = 0;
+     }
+  mshvoi_ (&nu[1], &tri[nbsgrn + 1], &nu[*nbt * 3 + 1], nbt, &nbsgrn);
+  mshrgl_ (&cr[3], &tri[1], &nbsgrn, &nu[1], &tri[nbsgrn + 1], &nu[*nbt * 3
+						      + 1], 1.4F, 20L, .005F);
+  *nbs = nbsgrn;
+  return 1;
+}				/* mshptg_ */
+
+/* ********************************************************************** */
+void 
+mshvoi_ (long *nu, long *w1, long *w, long *nbt, long *nbs)
+{
+  /* System generated locals */
+  long            i_1;
+
+  /* Local variables */
+  static long     i, is;
+
+
+/* RECHERCHE DU VOISINAGE */
+/* ----------------------- */
+  /* Parameter adjustments */
+  --w;
+  --nu;
+
+  /* Function Body */
+  i_1 = *nbs;
+  for (i = 1; i <= i_1; ++i)
+     {
+       w1[i] = 0;
+     }
+  i_1 = *nbt * 3;
+  for (i = 1; i <= i_1; ++i)
+     {
+       ++w1[nu[i]];
+     }
+  w1[0] = 0;
+  i_1 = *nbs;
+  for (i = 1; i <= i_1; ++i)
+     {
+       w1[i] = w1[i - 1] + w1[i];
+     }
+  i_1 = *nbt * 3;
+  for (i = 1; i <= i_1; ++i)
+     {
+       is = nu[i] - 1;
+       ++w1[is];
+       w[w1[is]] = i;
+     }
+  for (i = *nbs; i >= 1; --i)
+     {
+       w1[i] = w1[i - 1];
+     }
+  w1[0] = 0;
+}				/* mshvoi_ */
+
+/* ********************************************************************** */
+int 
+mshrgl_ (double *c, long *nrfs, long *nbs, long *nu, long *w1,
+	 long *w, double omega, long itermx, double eps)
+{
+  /* System generated locals */
+  long            i_1, i_2, i_3;
+  double           r_1, r_2;
+
+  /* Local variables */
+  static double    depx, depy;
+  static long     iter;
+  static double    xmin, ymin, xmax, ymax;
+  static long     i, k, i1, i2, ic;
+  static double    bx, by, dx;
+  static long     is;
+  static double    err;
+
+
+/* REGULARISATION PAR MOYENNE BARYCENTRIQUE */
+/* ----------------------------------------- */
+  /* Parameter adjustments */
+  --w;
+  --nu;
+  --nrfs;
+  c -= 3;
+
+  /* Function Body */
+  xmin = c[3];
+  ymin = c[4];
+  xmax = c[3];
+  ymax = c[4];
+  i_1 = *nbs;
+  for (ic = 1; ic <= i_1; ++ic)
+     {
+/* Computing MIN */
+       r_1 = c[(ic << 1) + 1];
+       xmin = amin (r_1, xmin);
+/* Computing MIN */
+       r_1 = c[(ic << 1) + 2];
+       ymin = amin (r_1, ymin);
+/* Computing MAX */
+       r_1 = c[(ic << 1) + 1];
+       xmax = amax (r_1, xmax);
+/* Computing MAX */
+       r_1 = c[(ic << 1) + 2];
+       ymax = amax (r_1, ymax);
+     }
+/* Computing MAX */
+  r_1 = xmax - xmin, r_2 = ymax - ymin;
+  dx = amax (r_1, r_2);
+  i_1 = itermx;
+  for (iter = 1; iter <= i_1; ++iter)
+     {
+       err = (double) 0.;
+       i2 = w1[0];
+       i_2 = *nbs;
+       for (is = 1; is <= i_2; ++is)
+	  {
+	    i1 = i2 + 1;
+	    i2 = w1[is];
+	    if (i2 >= i1 && nrfs[is] == 0)
+	       {
+		 bx = (double) 0.;
+		 by = (double) 0.;
+		 i_3 = i2;
+		 for (i = i1; i <= i_3; ++i)
+		    {
+		      if (w[i] % 3 == 0)
+			 {
+			   k = w[i] - 2;
+			 }
+		      else
+			 {
+			   k = w[i] + 1;
+			 }
+		      bx += c[(nu[k] << 1) + 1];
+		      by += c[(nu[k] << 1) + 2];
+		    }
+		 bx /= i2 - i1 + 1;
+		 by /= i2 - i1 + 1;
+		 depx = omega * (c[(is << 1) + 1] - bx);
+		 depy = omega * (c[(is << 1) + 2] - by);
+		 c[(is << 1) + 1] -= depx;
+		 c[(is << 1) + 2] -= depy;
+/* Computing MAX */
+		 r_1 = err, r_2 = aabs (depx), r_1 = amax (r_1, r_2), r_2 = aabs (depy);
+		 err = amax (r_1, r_2);
+	       }
+	  }
+/* -------------------------------- */
+       if (err <= eps * dx)
+	  {
+	    return 0;
+	  }
+     }
+  return 1;
+}				/* mshrgl_ */
+
+/* ********************************************************************** */
+int 
+mshgpt_ (long *c, double *cr, long *nu, double *h, long *reft, long *nbs,
+     long nbsmx, long *nbt, double coef, double puis, double *trfri, long *err)
+{
+  /* System generated locals */
+  long            i_1;
+  double           r_1, r_2, r_3;
+  double          d_1, d_2, d_3, d_4, d_5, d_6, d_7, d_8;
+
+  /* Local variables */
+  static double    aire;
+  static long     tete;
+  static long     t;
+  static double    x, y;
+  static long     itera;
+  static double    h1, h2, h3;
+  static long     s1, s2, s3;
+  static double    hs;
+  static long     ix, iy, nbsold;
+  static double    det, pui;
+
+  /* Parameter adjustments */
+  --trfri;
+  --reft;
+  --h;
+  nu -= 7;
+  cr -= 3;
+  c -= 3;
+
+  /* Function Body */
+  pui = puis;
+  *nbt = (*nbs << 1) - 2;
+  if (*nbs >= nbsmx)
+     { /*  ADD FH  avril 2007 */
+      i_1 = *nbt;
+      for (t = 1; t <= i_1; ++t)
+        if (nu[t * 6 + 6] != 0)
+        { 
+	  mshopt_ (&c[3], &nu[7], &t, 4L, err);
+	  mshopt_ (&c[3], &nu[7], &t, 5L, err);
+	  mshopt_ (&c[3], &nu[7], &t, 6L, err);
+        }	
+	/* FIN  ADD FH  vril 2007 */    
+       return 0;
+     }
+  tete = 0;
+/*     initialisation de la liste des triangles libre */
+  i_1 = *nbt;
+  for (t = 1; t <= i_1; ++t)
+     {
+       if (nu[t * 6 + 6] == 0)
+	  {
+	    nu[t * 6 + 1] = tete;
+	    tete = t;
+	  }
+     }
+  itera = 0;
+L20:
+  ++itera;
+  nbsold = *nbs;
+  i_1 = *nbt;
+  for (t = 1; t <= i_1; ++t)
+     {
+       if (nu[t * 6 + 6] != 0)
+	  {
+	    s1 = nu[t * 6 + 1];
+	    s2 = nu[t * 6 + 2];
+	    s3 = nu[t * 6 + 3];
+/*        calcul de 2 fois l'aire du triangle */
+	    det = (cr[(s2 << 1) + 1] - cr[(s1 << 1) + 1]) 
+	        * (cr[(s3 << 1) + 2] - cr[(s1 << 1) + 2]) 
+	        - (cr[(s2 << 1) + 2] - cr[(s1 << 1) + 2]) 
+	        * (cr[(s3 << 1) + 1] - cr[(s1 << 1) + 1]);
+	    aire = det * coef;
+	    if (puis > (double) 0.)
+	       {
+		 d_2 = (double) h[s1];
+		 d_3 = (double) pui;
+		 d_4 = (double) h[s2];
+		 d_5 = (double) pui;
+		 d_6 = (double) h[s3];
+		 d_7 = (double) pui;
+		 d_1 = (pow (d_2, d_3) + pow (d_4, d_5) + pow (d_6, d_7)) / (double) 3.;
+		 d_8 = (double) (1.F / pui);
+		 hs = (double)pow (d_1, d_8);
+	       }
+	    else if (puis > (double) -1.)
+	       {
+		 d_1 = (double) (h[s1] * h[s2] * h[s3]);
+		 hs = (double)pow (d_1, 1. / 3);
+	       }
+	    else if (puis > (double) -2.)
+	       {
+		 hs = h[s1] * (double) 3. *h[s2] * h[s3] / (h[s1] * h[s2] + h[
+					       s1] * h[s3] + h[s2] * h[s3]);
+	       }
+	    else
+	       {
+/* Computing 2nd power */
+		 r_1 = (double)sqrt (h[s1] * h[s2]);
+/* Computing 2nd power */
+		 r_2 = h[s1] * h[s3];
+/* Computing 2nd power */
+		 r_3 = h[s2] * h[s3];
+		 hs = (double)sqrt (3.0) * (h[s1] * h[s2] * h[s3]
+			 / (r_1 * r_1) + r_2 * r_2 + r_3 * r_3);
+	       }
+	    if (aire > hs * hs)
+	       {
+		 h1 = (double) 1.;
+		 h2 = (double) 1.;
+		 h3 = (double) 1.;
+		 x = (cr[(s1 << 1) + 1] * h1 + cr[(s2 << 1) + 1] * h2 + cr[(s3
+					  << 1) + 1] * h3) / (h1 + h2 + h3);
+		 y = (cr[(s1 << 1) + 2] * h1 + cr[(s2 << 1) + 2] * h2 + cr[(s3
+					  << 1) + 2] * h3) / (h1 + h2 + h3);
+		 r_1 = trfri[1] * (x - trfri[2]);
+		 ix = (long) i_nint (r_1);
+		 r_1 = trfri[1] * (y - trfri[3]) - trfri[4];
+		 iy = (long) i_nint (r_1);
+		 if ((c[(s2 << 1) + 1] - ix) * (c[(s3 << 1) + 2] - iy) - (c[(
+		       s2 << 1) + 2] - iy) * (c[(s3 << 1) + 1] - ix) <= 0 ||
+		     (ix - c[(s1 << 1) + 1]) * (c[(s3 << 1) + 2] - c[(s1 <<
+			 1) + 2]) - (iy - c[(s1 << 1) + 2]) * (c[(s3 << 1) +
+		      1] - c[(s1 << 1) + 1]) <= 0 || (c[(s2 << 1) + 1] - c[(
+			s1 << 1) + 1]) * (iy - c[(s1 << 1) + 2]) - (c[(s2 <<
+		       1) + 2] - c[(s1 << 1) + 2]) * (ix - c[(s1 << 1) + 1])
+		     <= 0)
+		    {
+		    }
+		 else
+		    {
+		      if (*nbs >= nbsmx)
+			 {
+			   return 0;
+			 }
+		      ++(*nbs);
+		      c[(*nbs << 1) + 1] = ix;
+		      c[(*nbs << 1) + 2] = iy;
+		      cr[(*nbs << 1) + 1] = ix / trfri[1] + trfri[2];
+		      cr[(*nbs << 1) + 2] = (iy + trfri[4]) / trfri[1] + trfri[
+									 3];
+		      h[*nbs] = hs;
+		      msha1p_ (&t, nbs, &c[3], &nu[7], &reft[1], &tete, nbt, err);
+		      if (*err != 0)
+			 {
+			   return 0;
+			 }
+		    }
+	       }
+	  }
+     }
+  if (nbsold != *nbs)
+     {
+       goto L20;
+     }
+  return 1;
+}				/* mshgpt_ */
+
+/* ********************************************************************** */
+int 
+msha1p_ (long *t, long *s, long *c, long *nu, long *reft, long *tete, long *nbt,
+	 long *err)
+{
+  static long     t1, t2, t3, ia2, ia3;
+  static long     ta2, ta3;
+
+//    extern int mshopt_();
+  static long     tta;
+
+  /* Parameter adjustments */
+  --reft;
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  t1 = *t;
+  if (*tete == 0)
+     {
+       ++(*nbt);
+       t2 = *nbt;
+     }
+  else
+     {
+       t2 = *tete;
+       *tete = nu[*tete * 6 + 1];
+     }
+  if (*tete == 0)
+     {
+       ++(*nbt);
+       t3 = *nbt;
+     }
+  else
+     {
+       t3 = *tete;
+       *tete = nu[*tete * 6 + 1];
+     }
+  nu[t2 * 6 + 1] = *s;
+  nu[t2 * 6 + 2] = nu[*t * 6 + 2];
+  nu[t2 * 6 + 3] = nu[*t * 6 + 3];
+  nu[t2 * 6 + 4] = (t1 << 3) + 5;
+  nu[t2 * 6 + 5] = nu[*t * 6 + 5];
+  nu[t2 * 6 + 6] = (t3 << 3) + 5;
+  nu[t3 * 6 + 1] = nu[*t * 6 + 1];
+  nu[t3 * 6 + 2] = *s;
+  nu[t3 * 6 + 3] = nu[*t * 6 + 3];
+  nu[t3 * 6 + 4] = (t1 << 3) + 6;
+  nu[t3 * 6 + 5] = (t2 << 3) + 6;
+  nu[t3 * 6 + 6] = nu[*t * 6 + 6];
+  tta = nu[*t * 6 + 5];
+  if (tta > 0)
+     {
+       ta2 = tta / 8;
+       ia2 = tta - (ta2 << 3);
+       nu[ia2 + ta2 * 6] = (t2 << 3) + 5;
+     }
+  tta = nu[*t * 6 + 6];
+  if (tta > 0)
+     {
+       ta3 = tta / 8;
+       ia3 = tta - (ta3 << 3);
+       nu[ia3 + ta3 * 6] = (t3 << 3) + 6;
+     }
+  nu[t1 * 6 + 3] = *s;
+  nu[t1 * 6 + 5] = (t2 << 3) + 4;
+  nu[t1 * 6 + 6] = (t3 << 3) + 4;
+  reft[t2] = reft[*t];
+  reft[t3] = reft[*t];
+  mshopt_ (&c[3], &nu[7], &t1, 4L, err);
+  if (*err != 0)
+     {
+       return 0;
+     }
+  mshopt_ (&c[3], &nu[7], &t2, 5L, err);
+  if (*err != 0)
+     {
+       return 0;
+     }
+  mshopt_ (&c[3], &nu[7], &t3, 6L, err);
+  if (*err != 0)
+     {
+       return 0;
+     }
+  return 1;
+}				/* msha1p_ */
+
+/* ********************************************************************** */
+long 
+mshlcl_ (long *c, long *nu, long *tete, long *s)
+{
+  /* System generated locals */
+  long            ret_val;
+
+  /* Local variables */
+  static long     init;
+  static long     x, y, pt, ppt;
+  LONG8 det;
+
+  /* Parameter adjustments */
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  x = c[(*s << 1) + 1];
+  y = c[(*s << 1) + 2];
+  init = 1;
+  pt = *tete;
+L10:
+  ppt = pt;
+  pt = nu[pt * 6 + 4];
+  if (pt != *tete)
+     {
+       det = (LONG8) x * (LONG8) c[(nu[pt * 6 + 1] << 1) + 2] 
+           - (LONG8) y * (LONG8) c[(nu[pt * 6 + 1] << 1) + 1];
+       if (det < 0)
+	  {
+	    init = 0;
+	    goto L10;
+	  }
+       else if (init && det == 0)
+	  {
+	    goto L10;
+	  }
+     }
+  ret_val = ppt;
+  return ret_val;
+}				/* mshlcl_ */
+
+/* ********************************************************************** */
+int 
+mshtri_ (double *cr, long *c, long *nbs, long *tri, LONG8  *nu, double *trfri, long *err)
+{
+  /* System generated locals */
+  long            i_1, i_2, i_3;
+  double           r_1;
+
+  /* Local variables */
+  static long     ierr, trik;
+  static double    xmin, ymin, xmax, ymax;
+  static long     i, j, k, ic, jc;
+
+//    extern int mshtr1_();
+  static long     ip, xx;
+  static double    aa1, aa2;
+  static long     iii, tri3;
+  LONG8 det;
+
+  /* Parameter adjustments */
+  --trfri;
+  --nu;
+  --tri;
+  c -= 3;
+  cr -= 3;
+
+  /* Function Body */
+  ierr = 0;
+  iii = 1;
+  xmin = cr[3];
+  ymin = cr[4];
+  xmax = cr[3];
+  ymax = cr[4];
+  i_1 = *nbs;
+  for (ic = 1; ic <= i_1; ++ic)
+     {
+/* Computing MIN */
+       r_1 = cr[(ic << 1) + 1];
+       xmin = amin (r_1, xmin);
+/* Computing MIN */
+       r_1 = cr[(ic << 1) + 2];
+       ymin = amin (r_1, ymin);
+/* Computing MAX */
+       r_1 = cr[(ic << 1) + 1];
+       xmax = amax (r_1, xmax);
+/* Computing MAX */
+       r_1 = cr[(ic << 1) + 2];
+       ymax = amax (r_1, ymax);
+       tri[ic] = ic;
+       if (cr[(ic << 1) + 1] < cr[(iii << 1) + 1])
+	  {
+	    iii = ic;
+	  }
+     }
+  aa1 = MAXCOOR  / (xmax - xmin);
+  aa2 = MAXCOOR / (ymax - ymin);
+  aa1 = amin (aa1, aa2);
+  aa2 = aa1 * (cr[(iii << 1) + 2] - ymin);
+  trfri[1] = aa1;
+  trfri[2] = cr[(iii << 1) + 1];
+  trfri[3] = ymin;
+  trfri[4] = aa2;
+  i_1 = *nbs;
+  for (ic = 1; ic <= i_1; ++ic)
+     {
+       r_1 = aa1 * (cr[(ic << 1) + 1] - cr[(iii << 1) + 1]);
+       c[(ic << 1) + 1] = (long) i_nint (r_1);
+       r_1 = aa1 * (cr[(ic << 1) + 2] - ymin) - aa2;
+       c[(ic << 1) + 2] = (long) i_nint (r_1);
+/* Computing 2nd power */
+       i_2 = c[(ic << 1) + 1];
+/* Computing 2nd power */
+       i_3 = c[(ic << 1) + 2];
+       nu[ic] = (LONG8) i_2 * (LONG8) i_2 + (LONG8) i_3 * (LONG8) i_3;
+     }
+/* ---------------------------------------------------------- */
+  mshtr1_ (&nu[1], &tri[1], nbs);
+  ip = 1;
+  xx = nu[ip];
+  i_1 = *nbs;
+  for (jc = 1; jc <= i_1; ++jc)
+     {
+       if (nu[jc] > xx)
+	  {
+	    i_2 = jc - ip;
+	    mshtr1_ (&nu[ip], &tri[ip], &i_2);
+	    i_2 = jc - 2;
+	    for (i = ip; i <= i_2; ++i)
+	       {
+		 if (nu[i] == nu[i + 1])
+		    {
+		      ++ierr;
+	             if (ierr <10) 
+	             printf(" The points %ld and %ld are too close \n",tri[i],tri[i+1]);
+		    }
+	       }
+	    xx = nu[jc];
+	    ip = jc;
+	  }
+       ic = tri[jc];
+       nu[jc] = c[(ic << 1) + 2];
+     }
+  i_1 = *nbs - ip;
+  mshtr1_ (&nu[ip], &tri[ip], &i_1);
+  i_1 = jc - 2;
+  for (i = ip; i <= i_1; ++i)
+     {
+       if (nu[i] == nu[i + 1])
+	  {
+	    if (ierr <10) 
+	      printf(" The points %ld and %ld are to close \n",tri[i],tri[i+1]);
+	    ++ierr;
+	  }
+     }
+  if (ierr != 0)
+     {
+       *err = 2;
+       printf("mshptg bug 2 \n");
+
+       return 0;
+     }
+  k = 2;
+L50:
+  if (k <= *nbs)
+     {
+       ++k;
+       det = (LONG8) c[(tri[2] << 1) + 1] * (LONG8) c[(tri[k] << 1) + 2] 
+           - (LONG8) c[(tri[2] << 1) + 2] * (LONG8) c[(tri[k] << 1) + 1];
+       if (det == 0)
+	  {
+	    goto L50;
+	  }
+     }
+  else
+     {
+       *err = 3;
+       return 0;
+     }
+/*     k est le premier point non aligne */
+  trik = tri[k];
+  for (j = k - 1; j >= 3; --j)
+     {
+       tri[j + 1] = tri[j];
+     }
+  tri[3] = trik;
+  if (det < 0)
+     {
+/*       on inverse les  points 2 3 tries */
+       tri3 = tri[3];
+       tri[3] = tri[2];
+       tri[2] = tri3;
+     }
+  return 1;
+}				/* mshtri_ */
+
+/* ********************************************************************** */
+int 
+mshtr1_ (LONG8 *criter, long *record, long *n)
+{
+  /* System generated locals */
+  long            i_1;
+
+  /* Local variables */
+  long     i, j, l, r, rec;
+  LONG8 crit;
+/*     trie selon les valeurs de criter croissantes */
+/*     record suit le reordonnancement */
+
+
+  /* Parameter adjustments */
+  --record;
+  --criter;
+
+  /* Function Body */
+  if (*n <= 1)
+     {
+       return 0;
+     }
+  l = *n / 2 + 1;
+  r = *n;
+L2:
+  if (l <= 1)
+     {
+       goto L20;
+     }
+  --l;
+  rec = record[l];
+  crit = criter[l];
+  goto L3;
+L20:
+  rec = record[r];
+  crit = criter[r];
+  record[r] = record[1];
+  criter[r] = criter[1];
+  --r;
+  if (r == 1)
+     {
+       goto L999;
+     }
+L3:
+  j = l;
+L4:
+  i = j;
+  j <<= 1;
+  if ((i_1 = j - r) < 0)
+     {
+       goto L5;
+     }
+  else if (i_1 == 0)
+     {
+       goto L6;
+     }
+  else
+     {
+       goto L8;
+     }
+L5:
+  if (criter[j] < criter[j + 1])
+     {
+       ++j;
+     }
+L6:
+  if (crit >= criter[j])
+     {
+       goto L8;
+     }
+  record[i] = record[j];
+  criter[i] = criter[j];
+  goto L4;
+L8:
+  record[i] = rec;
+  criter[i] = crit;
+  goto L2;
+L999:
+  record[1] = rec;
+  criter[1] = crit;
+  return 0;
+}				/* mshtr1_ */
+
+/* ********************************************************************** */
+int 
+mshcvx_ (long direct, long *c, long *nu, long *pfold, long *err)
+{
+  static long     t, a4, a5, i1, i2, i3, i4, i5, i6, s1, s2, s3, t4, t5,
+                  pf, pp, ps;
+
+//    extern int mshopt_();
+  static long     tt4, tt5,  ppf, psf;
+  LONG8 det;
+
+  /* Parameter adjustments */
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  if (direct)
+     {
+       pp = 3;
+       ps = 4;
+       i1 = 1;
+       i2 = 3;
+       i3 = 2;
+       i4 = 6;
+       i5 = 5;
+       i6 = 4;
+     }
+  else
+     {
+       pp = 4;
+       ps = 3;
+       i1 = 1;
+       i2 = 2;
+       i3 = 3;
+       i4 = 4;
+       i5 = 5;
+       i6 = 6;
+     }
+L10:
+  ppf = *pfold;
+  pf = nu[ps + *pfold * 6];
+  psf = nu[ps + pf * 6];
+  s1 = nu[ppf * 6 + 1];
+  s2 = nu[pf * 6 + 1];
+  s3 = nu[psf * 6 + 1];
+  det =    (LONG8) (c[(s2 << 1) + 1] - c[(s1 << 1) + 1]) 
+         * (LONG8) (c[(s3 << 1) + 2] - c[(s1 << 1) + 2]) 
+         - (LONG8) (c[(s2 << 1) + 2] - c[(s1 << 1) + 2]) 
+         * (LONG8) (c[(s3 << 1) + 1] - c[(s1 << 1) + 1]);
+         
+  if ((!(direct) && det > 0) || (direct && det < 0))
+     {
+/*       on ajoute un triangle t et on detruit une arete */
+/*       ----------------------------------------------- */
+       if (direct)
+	  {
+	    tt4 = nu[ppf * 6 + 2];
+	    tt5 = nu[pf * 6 + 2];
+	  }
+       else
+	  {
+	    tt4 = nu[pf * 6 + 2];
+	    tt5 = nu[psf * 6 + 2];
+	  }
+       t4 = tt4 / 8;
+       t5 = tt5 / 8;
+       a4 = tt4 - (t4 << 3);
+       a5 = tt5 - (t5 << 3);
+/*       destruction de l'arete frontiere en pf */
+/*       -------------------------------------- */
+       nu[ps + ppf * 6] = psf;
+       nu[pp + psf * 6] = ppf;
+/*       on remplace l'arete frontiere par l'element genere */
+/*       --------------------------------------------------- */
+       t = pf;
+/*       update de l'arete non detruite */
+/*       ------------------------------ */
+       if (direct)
+	  {
+	    nu[ppf * 6 + 2] = (t << 3) + i6;
+	  }
+       else
+	  {
+	    nu[psf * 6 + 2] = (t << 3) + i6;
+	  }
+/*       on cree l'element */
+/*       ----------------- */
+       nu[i1 + t * 6] = s1;
+       nu[i2 + t * 6] = s2;
+       nu[i3 + t * 6] = s3;
+       nu[i4 + t * 6] = (t4 << 3) + a4;
+       nu[i5 + t * 6] = (t5 << 3) + a5;
+       if (direct)
+	  {
+	    nu[i6 + t * 6] = -ppf;
+	  }
+       else
+	  {
+	    nu[i6 + t * 6] = -psf;
+	  }
+       nu[a4 + t4 * 6] = (t << 3) + i4;
+       nu[a5 + t5 * 6] = (t << 3) + i5;
+       mshopt_ (&c[3], &nu[7], &t5, a5, err);
+       if (*err != 0)
+	  {
+	    return 0;
+	  }
+       goto L10;
+     }
+  return 1;
+}				/* mshcvx_ */
+
+/* ********************************************************************** */
+int 
+mshcxi_ (long *c, long *nu, long *tri, long *nbs, long *tete, long *err)
+{
+  /* System generated locals */
+  long            i_1;
+
+  /* Local variables */
+  static long     sfree, ttaf, i, j, s, t, pf;
+
+//    extern long mshlcl_();
+  //    extern int mshcvx_(), mshopt_();
+  static long     iaf, taf, npf, ppf, psf;
+
+/*     initialisation de la sfree liste dans nu */
+  /* Parameter adjustments */
+  --tri;
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  i_1 = *nbs + *nbs - 2;
+  for (i = 1; i <= i_1; ++i)
+     {
+       nu[i * 6 + 1] = i + 1;
+       for (j = 2; j <= 6; ++j)
+	  {
+	    nu[j + i * 6] = 0;
+	  }
+     }
+  nu[(*nbs + *nbs - 2) * 6 + 1] = 0;
+  sfree = 1;
+/*     initialisation du premier triangle */
+  t = sfree;
+  sfree = nu[sfree * 6 + 1];
+/*     initialisation de la liste frontiere */
+  *tete = sfree;
+  pf = sfree;
+  for (i = 1; i <= 3; ++i)
+     {
+       nu[i + t * 6] = tri[i];
+       nu[i + 3 + t * 6] = -pf;
+       ppf = pf;
+       sfree = nu[pf * 6 + 1];
+       pf = sfree;
+       if (i == 3)
+	  {
+	    pf = *tete;
+	  }
+       nu[ppf * 6 + 1] = tri[i];
+       nu[ppf * 6 + 2] = i + 3 + (t << 3);
+       nu[ppf * 6 + 4] = pf;
+       nu[pf * 6 + 3] = ppf;
+     }
+  i_1 = *nbs;
+  for (i = 4; i <= i_1; ++i)
+     {
+       s = tri[i];
+       pf = mshlcl_ (&c[3], &nu[7], tete, &s);
+/*      creation d'un nouveau triangle et modification de la
+   frontiere */
+/*      
+   --------------------------------------------------------------
+ */
+       t = sfree;
+       sfree = nu[sfree * 6 + 1];
+       npf = sfree;
+       sfree = nu[sfree * 6 + 1];
+       ppf = nu[pf * 6 + 3];
+       psf = nu[pf * 6 + 4];
+       ttaf = nu[pf * 6 + 2];
+       taf = ttaf / 8;
+       iaf = ttaf - (taf << 3);
+
+/*                  npf */
+/*               1  x s               --- */
+/*                 / \                --- */
+/*              4 /   \ 6        ---  vide --- */
+/*               /  t  \              --- */
+/*            2 /   5   \ 3           --- */
+/* ------ --<---x---------x---------x- frontiere--<--- */
+/*          psf \  iaf  /  pf         --- */
+/*               \ taf /         --- omega --- */
+/*                \   /               --- */
+/*                 \ /                --- */
+/*                  x                 --- */
+/*                                    --- */
+/*     generation  de l'element t */
+       nu[t * 6 + 1] = s;
+       nu[t * 6 + 2] = nu[psf * 6 + 1];
+       nu[t * 6 + 3] = nu[pf * 6 + 1];
+       nu[t * 6 + 4] = -npf;
+       nu[t * 6 + 5] = (taf << 3) + iaf;
+       nu[t * 6 + 6] = -pf;
+       nu[iaf + taf * 6] = (t << 3) + 5;
+/*      update de la liste frontiere */
+       nu[npf * 6 + 4] = psf;
+       nu[pf * 6 + 4] = npf;
+       nu[npf * 6 + 3] = pf;
+       nu[psf * 6 + 3] = npf;
+       nu[npf * 6 + 1] = s;
+       nu[npf * 6 + 2] = (t << 3) + 4;
+       nu[pf * 6 + 2] = (t << 3) + 6;
+       mshopt_ (&c[3], &nu[7], &t, 5L, err);
+       if (*err != 0)
+	  {
+	    return 0;
+	  }
+       mshcvx_ (1, &c[3], &nu[7], &npf, err);
+       if (*err != 0)
+	  {
+	    return 0;
+	  }
+       mshcvx_ (0, &c[3], &nu[7], &npf, err);
+       if (*err != 0)
+	  {
+	    return 0;
+	  }
+     }
+  return 1;
+}				/* mshcxi_ */
+
+/* ********************************************************************** */
+int 
+mshopt_ (long *c, long *nu, long *t, long a, long *err)
+{
+  /* Initialized data */
+
+  static long     mod3[3] =
+  {2, 3, 1};
+
+  /* System generated locals */
+  long            i_1;
+  double          d_1;
+
+  /* Local variables */
+  static long     pile[4096] /* was [2][256] */ ;
+  static double    reel1, reel2;
+  static double   reel8;
+  static long     i, a1, a2, s1, t1, t2, s2, s3, s4, aa, i11, i12, i13,
+                  i21, i22, i23, tt;
+  static long     tt1;
+  LONG8  cos1, cos2, sin1, sin2, sgn;
+  int kerr21=0;
+  /* Parameter adjustments */
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  i = 1;
+  pile[(i << 1) - 2] = *t;
+  pile[(i << 1) - 1] = a;
+L10:
+  if (i > 0)
+     {
+       t1 = pile[(i << 1) - 2];
+       a1 = pile[(i << 1) - 1];
+       --i;
+       if (t1 <= 0)
+	  {
+	    goto L10;
+	  }
+       tt1 = nu[a1 + t1 * 6];
+       if (tt1 <= 0)
+	  {
+	    goto L10;
+	  }
+       t2 = tt1 / 8;
+       a2 = tt1 - (t2 << 3);
+       i11 = a1 - 3;
+       i12 = mod3[i11 - 1];
+       i13 = mod3[i12 - 1];
+       i21 = a2 - 3;
+       i22 = mod3[i21 - 1];
+       i23 = mod3[i22 - 1];
+       s1 = nu[i13 + t1 * 6];
+       s2 = nu[i11 + t1 * 6];
+       s3 = nu[i12 + t1 * 6];
+       s4 = nu[i23 + t2 * 6];
+       sin1 =     (LONG8) (c[(s3 << 1) + 2] - c[(s1 << 1) + 2]) 
+                * (LONG8) (c[(s2 << 1) + 1] - c[(s1 << 1) + 1]) 
+              -   (LONG8) (c[(s3 << 1) + 1] - c[(s1 << 1) + 1]) 
+                * (LONG8) (c[(s2 << 1) + 2] - c[(s1 << 1) + 2]);
+                
+       cos1 =     (LONG8) (c[(s3 << 1) + 1] - c[(s1 << 1) + 1]) 
+                * (LONG8) (c[(s3 << 1) + 1] - c[(s2 << 1) + 1]) 
+              +   (LONG8) (c[(s3 << 1) + 2] - c[(s1 << 1) + 2]) 
+                * (LONG8) (c[(s3 << 1) + 2] - c[(s2 << 1) + 2]);
+       if (sin1 == 0 && cos1 == 0)
+	  {
+	    *err = 20;
+	    return 0;
+	  }
+/*       b est la cotangente de angle (s1,s3,s2) */
+
+       sin2 =   (LONG8) (c[(s4 << 1) + 1] - c[(s1 << 1) + 1]) 
+              * (LONG8) (c[(s2 << 1) + 2] - c[(s1 << 1) + 2]) 
+              - (LONG8) (c[(s4 << 1) + 2] - c[(s1 << 1) + 2]) 
+              * (LONG8) (c[(s2 << 1) + 1] - c[(s1 << 1) + 1]);
+     // FH correct 6/11/2005 forgotted cast          
+       cos2 =   (LONG8) (c[(s4 << 1) + 1] - c[(s2 << 1) + 1]) 
+              * (LONG8) (c[(s4 << 1) + 1] - c[(s1 << 1) + 1]) 
+              + (LONG8) (c[(s4 << 1) + 2] - c[(s2 << 1) + 2]) 
+              * (LONG8) (c[(s4 << 1) + 2] - c[(s1 << 1) + 2]);
+              
+       reel1 = (double) cos2 *(double) sin1;
+       reel2 = (double) cos1 *(double) sin2;
+
+       if (aabs (reel1) + aabs (reel2) >= (double ) DLONG8LONG8)
+	  {
+	    reel8 = (double) cos2 *(double) sin1 + (double) cos1 *(double) sin2;
+
+/* Computing MIN */
+	    d_1 = amax (reel8, -1.);
+	    reel8 = amin (d_1, 1.);
+	    sgn = (LONG8) reel8;
+	  }
+       else
+	  {
+	    sgn = cos2 * sin1 + cos1 * sin2;
+	  }
+/* Computing MIN */
+       i_1 = amin(amax (sgn, -1),1);
+      // cout << sgn << " " << i_1 << endl;
+       if ( i_1 * sin1 >= 0)
+	  {
+	    goto L10;
+	  }
+/*       on inverse le quadrilatere */
+/*       update des sommets */
+/* ------------------------- */
+       nu[i12 + t1 * 6] = s4;
+       nu[i22 + t2 * 6] = s1;
+/*       update des aretes a1,a2 */
+/* ------------------------------- */
+       tt1 = nu[i22 + 3 + t2 * 6];
+       nu[a1 + t1 * 6] = tt1;
+       if (tt1 > 0)
+	  {
+	    tt = tt1 / 8;
+	    aa = tt1 - (tt << 3);
+	    nu[aa + tt * 6] = a1 + (t1 << 3);
+	  }
+       else if (tt1 != nothing)
+	  {
+	    nu[-tt1 * 6 + 2] = a1 + (t1 << 3);
+	  }
+       tt1 = nu[i12 + 3 + t1 * 6];
+       nu[a2 + t2 * 6] = tt1;
+       if (tt1 > 0)
+	  {
+	    tt = tt1 / 8;
+	    aa = tt1 - (tt << 3);
+	    nu[aa + tt * 6] = a2 + (t2 << 3);
+	  }
+       else if (tt1 != nothing)
+	  {
+	    nu[-tt1 * 6 + 2] = a2 + (t2 << 3);
+	  }
+       nu[i12 + 3 + t1 * 6] = i22 + 3 + (t2 << 3);
+       nu[i22 + 3 + t2 * 6] = i12 + 3 + (t1 << 3);
+       if (i + 4 > 1024)
+	  {
+	    if(kerr21)
+	      cout << " Bizarre mshptg err 21 pile too small (continue)  "<< endl;
+	    if(kerr21++<10000)
+		    goto L10; 
+	    *err = 21;
+	    return 0;
+	  }
+       ++i;
+       pile[(i << 1) - 2] = t1;
+       pile[(i << 1) - 1] = a1;
+       ++i;
+       pile[(i << 1) - 2] = t2;
+       pile[(i << 1) - 1] = a2;
+       ++i;
+       pile[(i << 1) - 2] = t1;
+       pile[(i << 1) - 1] = i13 + 3;
+       ++i;
+       pile[(i << 1) - 2] = t2;
+       pile[(i << 1) - 1] = i23 + 3;
+       goto L10;
+     }
+  return 1;
+}				/* mshopt_ */
+
+/* ********************************************************************** */
+int 
+mshfrt_ (long *c, long *nu, long *nbs, long *arete, long nba, long *sd,
+	 long nbsd, long *reft, long *w, long *err)
+{
+  /* Initialized data */
+
+  static long     p3[3] =
+  {2, 3, 1};
+
+  /* System generated locals */
+  long            i_1, i_2, i_3;
+
+  /* Local variables */
+  static long     nbac, ifrt, a, i, t, itera, s1, s2;
+
+//    extern int mshfr1_();
+  static long     ie, ap, ta, is, nbacpp;
+  static long     is1, ss1, s2t, s3t, isd, jsd, nbt, err1;
+  LONG8 det2, det3;
+
+  /* Parameter adjustments */
+  --w;
+  --reft;
+  sd -= 3;
+  arete -= 3;
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  if (nba == 0)
+     {
+       return 0;
+     }
+  ifrt = 0;
+  nbt = *nbs + *nbs - 2;
+  i_1 = *nbs;
+  for (i = 1; i <= i_1; ++i)
+     {
+       reft[i] = 0;
+     }
+  i_1 = nba;
+  for (i = 1; i <= i_1; ++i)
+     {
+       reft[arete[(i << 1) + 1]] = nothing;
+       reft[arete[(i << 1) + 2]] = nothing;
+     }
+  nbac = 0;
+  i_1 = nba;
+  for (a = 1; a <= i_1; ++a)
+     {
+/* Computing MIN */
+       i_2 = arete[(a << 1) + 1], i_3 = arete[(a << 1) + 2];
+       s1 = amin (i_2, i_3);
+/* Computing MAX */
+       i_2 = arete[(a << 1) + 1], i_3 = arete[(a << 1) + 2];
+       s2 = amax (i_2, i_3);
+       if (s1 == s2)
+	  {
+	    ++nbac;
+	  }
+       else
+	  {
+	    i = reft[s1];
+	  L25:
+	    if (i != nothing)
+	       {
+/* Computing MAX */
+		 i_2 = arete[(i << 1) + 1], i_3 = arete[(i << 1) + 2];
+		 if (s2 == amax (i_2, i_3))
+		    {
+		      ++nbac;
+		    }
+		 else
+		    {
+		      i = w[i];
+		      goto L25;
+		    }
+	       }
+	    else
+	       {
+		 w[a] = reft[s1];
+		 reft[s1] = a;
+	       }
+	  }
+     }
+  nbacpp = 1;
+  itera = 0;
+  err1 = 0;
+L50:
+  ++itera;
+  if (err1 != 0)
+     {
+       *err = err1;
+       return 0;
+     }
+  if (nbac < nba)
+     {
+       if (nbacpp == 0)
+	  {
+	    i_1 = *nbs;
+	    for (i = 1; i <= i_1; ++i)
+	       {
+		 a = reft[i];
+	       L60:
+		 if (a > 0)
+		    {
+		      s1 = arete[(i << 1) + 1];
+		      s2 = arete[(i << 1) + 2];
+		      a = w[a];
+		      goto L60;
+		    }
+	       }
+	    *err = 7;
+	    return 0;
+	  }
+/* --------------------------------------------------------------------- */
+/*     on s'occupe des aretes a forcer */
+/* --------------------------------------------------------------------- */
+       nbacpp = 0;
+       i_1 = nbt;
+       for (ie = 1; ie <= i_1; ++ie)
+	  {
+	    if (nu[ie * 6 + 5] != 0)
+	       {
+		 for (is = 1; is <= 3; ++is)
+		    {
+		      s1 = nu[is + ie * 6];
+		      s2t = nu[p3[is - 1] + ie * 6];
+		      ss1 = amin (s1, s2t);
+		      ap = 0;
+		      a = reft[ss1];
+		    L80:
+		      if (a > 0)
+			 {
+/* Computing MAX */
+			   i_2 = arete[(a << 1) + 1], i_3 = arete[(a << 1) + 2];
+			   s2 = amax (i_2, i_3);
+			   t = ie;
+			   ta = 0;
+			   if (s2 == amax (s1, s2t))
+			      {
+				if (nu[is + 3 + ie * 6] > 0)
+				   {
+				     ta = nu[is + 3 + ie * 6] / 8;
+				     i = nu[is + 3 + ie * 6] - (ta << 3);
+				     nu[i + ta * 6] = nothing;
+				   }
+				nu[is + 3 + ie * 6] = nothing;
+				goto L100;
+			      }
+			   ap = a;
+			   a = w[a];
+			   goto L80;
+			 }
+		      if (itera == 1)
+			 {
+			   goto L110;
+			 }
+		      ss1 = s1;
+		      ap = 0;
+		      a = reft[ss1];
+		    L90:
+		      if (a > 0)
+			 {
+/* Computing MAX */
+			   i_2 = arete[(a << 1) + 1], i_3 = arete[(a << 1) + 2];
+			   s2 = amax (i_2, i_3);
+			   t = ie;
+			   ta = 0;
+/*             recherche si l' element coupe l''arete a */
+			   is1 = is;
+			   s3t = nu[p3[p3[is - 1] - 1] + t * 6];
+			   det2 = (LONG8) (c[(s2t << 1) + 1] - c[(s1 << 1) + 1]) * (LONG8) (c[( s2 << 1) + 2] - c[(s1 << 1) + 2]) 
+			        - (LONG8) (c[(s2t << 1) + 2] - c[(s1 << 1) + 2]) * (LONG8) (c[( s2 << 1) + 1] - c[(s1 << 1) + 1]);
+			   det3 = (LONG8) (c[(s3t << 1) + 1] - c[(s1 << 1) + 1]) * (LONG8) (c[( s2 << 1) + 2] - c[(s1 << 1) + 2]) 
+			        - (LONG8) (c[(s3t << 1) + 2] - c[(s1 << 1) + 2]) * (LONG8) (c[( s2 << 1) + 1] - c[(s1 << 1) + 1]);
+			   if (det2 > 0 && det3 < 0)
+			      {
+				mshfr1_ (&c[3], &nu[7], &t, &ta, &is1, &s2, err);
+				if (*err != 0)
+				   {
+				     return 0;
+				   }
+				goto L100;
+			      }
+			   else if (det2 == 0 && det3 < 0 && reft[s2t] == 0)
+			      {
+				err1 = 10;
+				printf(" det = %ld %ld %ld %ld %ld == %ld \n ",
+				   (c[(s2t << 1) + 1] - c[(s1 << 1) + 1]), (c[( s2 << 1) + 2] - c[(s1 << 1) + 2]) ,
+				   (c[(s2t << 1) + 2] - c[(s1 << 1) + 2]), (c[( s2 << 1) + 1] - c[(s1 << 1) + 1]) ,
+				   (c[(s2t << 1) + 1] - c[(s1 << 1) + 1]) * (c[( s2 << 1) + 2] - c[(s1 << 1) + 2]) ,
+				   (c[(s2t << 1) + 2] - c[(s1 << 1) + 2]) * (c[( s2 << 1) + 1] - c[(s1 << 1) + 1])
+				   );
+				   
+				 
+				printf("bug 2, mshptg: point %ld is on boundary edge %ld %ld  \n",s2t,i_2,i_3);
+			      }
+			   else if (det2 > 0 && det3 == 0 && reft[s3t] == 0)
+			      {
+				err1 = 10;
+				printf(" det = %ld %ld %ld %ld  %ld %ld \n ",
+				    (c[(s3t << 1) + 1] - c[(s1 << 1) + 1]),  (c[( s2 << 1) + 2] - c[(s1 << 1) + 2]) ,
+				    (c[(s3t << 1) + 2] - c[(s1 << 1) + 2]),  (c[( s2 << 1) + 1] - c[(s1 << 1) + 1]) ,
+				    (c[(s3t << 1) + 1] - c[(s1 << 1) + 1]) * (c[( s2 << 1) + 2] - c[(s1 << 1) + 2]) ,
+				    (c[(s3t << 1) + 2] - c[(s1 << 1) + 2]) *  (c[( s2 << 1) + 1] - c[(s1 << 1) + 1])
+				    );
+				printf("bug 2, mshptg: point %ld is on  boundary %ld %ld\n",s3t,i_2,i_3);
+			      }
+			   ap = a;
+			   a = w[a];
+			   goto L90;
+			 }
+		      goto L110;
+		    L100:
+		      ++nbacpp;
+		      if (ap == 0)
+			 {
+			   reft[ss1] = w[a];
+			 }
+		      else
+			 {
+			   w[ap] = w[a];
+			 }
+		      if (nbac + nbacpp == nba)
+			 {
+			   goto L130;
+			 }
+		    L110:
+		      ;
+		    }
+	       }
+	  }
+       nbac += nbacpp;
+       goto L50;
+     }
+L130:
+/* ----------------------------------------------------------------------- */
+/*     prise en compte des sous domaines */
+/* ----------------------------------------------------------------------- */
+/*  add FH   si pas de nbsd ---  jan 2004 */
+    
+    if (nbsd<0) {
+     i_1 = nbt;
+    for (ie = 1; ie <= i_1; ++ie)
+     { 
+       if (nu[ie * 6 + 1] > 0)
+	     {
+	    nu[ie * 6 + 1] = -nu[ie * 6 + 1];
+	     }
+	 reft[ie]=1;
+     }
+     
+      goto L205; //  pas triangle retire
+      }    
+     if (nbsd == 0) {
+	 long i__1 = nbt,nbssd,exter,i__,headt,nst,j;
+	for (t = 1; t <= i__1; ++t) {
+	    reft[t] = -1073741824;
+	}
+	nbssd = 0;
+/*         if(impre.gt.1) print *,'nbsd .eq. 0 =>  recherche de ssd' */
+	i__1 = nbt;
+	for (t = 1; t <= i__1; ++t) {
+	    if (nu[t * 6 + 1] > 0 && nu[t * 6 + 5] != 0) {
+		++nbssd;
+		exter = 0;
+		i__ = 2;
+		w[i__ - 1] = t;
+		w[i__] = 3;
+		reft[t] = 0;
+		headt = t;
+		nu[t * 6 + 1] = -nu[t * 6 + 1];
+		nst = 1;
+/*              print *,' ssd ',nbssd */
+L131:
+		if (i__ > 0) {
+		    ++w[i__];
+		    if (w[i__] <= 6) {
+			ta = nu[w[i__] + w[i__ - 1] * 6];
+			if (ta <= 0) {
+			    if (ta != -1073741824) {
+				exter = 1;
+			    }
+			} else if (ta > 0) {
+			    ta /= 8;
+			    if (nu[ta * 6 + 1] > 0) {
+/*                           print *,ta */
+				nu[ta * 6 + 1] = -nu[ta * 6 + 1];
+				++nst;
+				reft[ta] = headt;
+				headt = ta;
+				w[i__ + 1] = ta;
+				w[i__ + 2] = 3;
+				i__ += 2;
+			    }
+			}
+		    } else {
+			i__ += -2;
+		    }
+		    goto L131;
+		}
+
+		if (exter) {
+		    --nbssd;
+		    i__ = headt;
+L133:
+		    if (i__ > 0) {
+			j = reft[i__];
+/*                     print *,i */
+			reft[i__] = 0;
+			nu[i__ * 6 + 1] = 0;
+			i__ = j;
+			goto L133;
+		    }
+		} else {
+		    i__ = headt;
+L136:
+		    if (i__ > 0) {
+			j = reft[i__];
+			reft[i__] = nbssd;
+			i__ = j;
+			goto L136;
+		    }
+		}
+	    }
+	}
+	goto L205;
+    }
+/*  fin ajoute FH jan 2004  */
+
+
+  i_1 = *nbs + nbsd + nbsd;
+  for (i = 1; i <= i_1; ++i)
+     {
+       w[i] = 0;
+     }
+  i_1 = nbsd;
+  for (i = 1; i <= i_1; ++i)
+     {
+       a = (i_2 = sd[(i << 1) + 1], aabs (i_2));
+/* Computing MIN */
+       i_2 = arete[(a << 1) + 1], i_3 = arete[(a << 1) + 2];
+       s1 = amin (i_2, i_3);
+       w[i + i] = w[s1 + nbsd + nbsd];
+       w[s1 + nbsd + nbsd] = i;
+     }
+  i_1 = nbt;
+  for (t = 1; t <= i_1; ++t)
+     {
+       reft[t] = nothing;
+       if (nu[t * 6 + 6] != 0)
+	  {
+	    for (i = 1; i <= 3; ++i)
+	       {
+/* Computing MIN */
+		 i_2 = nu[i + t * 6], i_3 = nu[p3[i - 1] + t * 6];
+		 ss1 = amin (i_2, i_3);
+		 jsd = nbsd + nbsd + ss1;
+	       L160:
+		 isd = w[jsd];
+		 if (isd > 0)
+		    {
+		      a = sd[(isd << 1) + 1];
+		      if (a > 0)
+			 {
+			   if (nu[i + t * 6] == arete[(a << 1) + 1] && nu[p3[i -
+					 1] + t * 6] == arete[(a << 1) + 2])
+			      {
+				reft[t] = sd[(isd << 1) + 2];
+				w[isd + isd - 1] = t;
+				w[jsd] = w[isd + isd];
+				goto L170;
+			      }
+			 }
+		      else if (a < 0)
+			 {
+			   if (nu[i + t * 6] == arete[(-a << 1) + 2] && nu[p3[i
+				      - 1] + t * 6] == arete[(-a << 1) + 1])
+			      {
+				reft[t] = sd[(isd << 1) + 2];
+				w[isd + isd - 1] = t;
+				w[jsd] = w[isd + isd];
+				goto L170;
+			      }
+			 }
+		      else
+			 {
+			    cout << " Err sous domaine " << isd << "ref par  d'arete +/-  = " << a  << " n'est dans aucun triangle " << endl;
+			   *err = 11;
+			 }
+		      jsd = isd + isd;
+		      goto L160;
+		    }
+	       L170:
+		 ;
+	       }
+	  }
+     }
+  i_1 = nbsd;
+  for (isd = 1; isd <= i_1; ++isd)
+     {
+       if (w[isd + isd - 1] == 0)
+	  {
+	   cout << " Err sous domaine " << isd << "ref par  d'arete +/-  = " << sd[(isd << 1) + 1]  << " n'est dans aucun triangle " << endl;
+	    *err = 11;
+	  }
+       else
+	  {
+	    w[isd + isd] = 3;
+	  }
+     }
+  if (*err != 0)
+     {
+       return 0;
+     }
+  i = nbsd + nbsd;
+L200:
+  if (i > 0)
+     {
+       ++w[i];
+       if (w[i] <= 6)
+	  {
+	    ta = nu[w[i] + w[i - 1] * 6];
+	    if (ta > 0)
+	       {
+		 ta /= 8;
+		 if (nu[ta * 6 + 1] > 0)
+		    {
+		      nu[ta * 6 + 1] = -nu[ta * 6 + 1];
+		      if (reft[ta] != reft[w[i - 1]])
+			 {
+			   if (reft[ta] != nothing)
+			      {
+			      }
+			   else
+			      {
+				reft[ta] = reft[w[i - 1]];
+			      }
+			   w[i + 1] = ta;
+			   w[i + 2] = 3;
+			   i += 2;
+			 }
+		    }
+	       }
+	  }
+       else
+	  {
+	    ta = w[i-1] ; 
+	    if( nu[ta * 6 + 1]>=0)    nu[ta * 6 + 1]= -nu[ta * 6 + 1]; // pour etre sur que le traingle est bien marque 
+
+	    i += -2;
+	  }
+       goto L200;
+     }
+L205:     
+  i_1 = nbt;
+  for (ie = 1; ie <= i_1; ++ie)
+     {
+       if (nu[ie * 6 + 1] < 0)
+	  {
+	    nu[ie * 6 + 1] = -nu[ie * 6 + 1];
+	  }
+       else
+	  {
+	    for (i = 1; i <= 6; ++i)
+	       {
+		 nu[i + ie * 6] = 0;
+	       }
+	  }
+     }
+  return 1;
+}				/* mshfrt_ */
+
+/* ********************************************************************** */
+int 
+mshfr1_ (long *c, long *nu, long *it1, long *ita, long *is1, long *s2, long *err)
+{
+  /* Initialized data */
+
+  static long     p3[5] =
+  {2, 3, 1, 2, 3};
+
+  static long     nbac, t, x, y, l1, l2, l3, s1, s3;
+
+//    extern int mshfr2_();
+  static long     la, ta;
+  static long     s2t, s3t,  lst[768] /* was [3][256] */ ;
+  LONG8 det;
+
+  /* Parameter adjustments */
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  t = *it1;
+  s1 = nu[*is1 + t * 6];
+  x = c[(*s2 << 1) + 1] - c[(s1 << 1) + 1];
+  y = c[(*s2 << 1) + 2] - c[(s1 << 1) + 2];
+  nbac = 0;
+  l1 = *is1;
+  l2 = p3[l1 - 1];
+  l3 = p3[l2 - 1];
+  s2t = nu[l2 + t * 6];
+  s3t = nu[l3 + t * 6];
+  la = l2 + 3;
+L20:
+  ++nbac;
+  if (nbac > 256)
+     {
+       *err = 8;
+       return 0;
+     }
+  lst[nbac * 3 - 2] = t;
+  lst[nbac * 3 - 1] = la;
+  ta = nu[la + t * 6];
+  if (ta <= 0)
+     {
+       *err = 9;
+       return 0;
+     }
+  t = ta / 8;
+  la = ta - (t << 3);
+  s3 = nu[p3[la - 3] + t * 6];
+  if (s3 != *s2)
+     {
+       det =   (LONG8) x * (LONG8) (c[(s3 << 1) + 2] - c[(s1 << 1) + 2]) 
+             - (LONG8) y * (LONG8) (c[(s3 << 1) + 1] - c[(s1 << 1) + 1]);
+       if (det > 0)
+	  {
+	    la = p3[la - 4] + 3;
+	  }
+       else if (det < 0)
+	  {
+	    la = p3[la - 3] + 3;
+	  }
+       else
+	  {
+	    printf("mshptg: bug the point %ld  is on boundary \n", s3 ); 
+	    *err = 10+s3*10;
+	    return 0;
+	  }
+       goto L20;
+     }
+  mshfr2_ (&c[3], &nu[7], lst, &nbac, it1, ita, &s1, s2, err);
+  return 0;
+}				/* mshfr1_ */
+
+/* ********************************************************************** */
+int 
+mshfr2_ (long *c, long *nu, long *lst, long *nbac, long *t, long *ta,
+	 long *ss1, long *ss2, long *err)
+{
+  /* Initialized data */
+
+  static long     mod3[3] =
+  {2, 3, 1};
+
+  /* System generated locals */
+  long            i_1;
+
+  /* Local variables */
+  static long     i, x, y, a1, a2, pplst, s1, pslst, ptlst, s2, s3, s4,
+                  ttlst, t1, t2, aa, i11, i12, i13, i21, i22, i23, x41,
+                  y41, tt;
+
+//    extern int mshopt_();
+  static long     tt1, aas;
+LONG8  det1, det2, det3, det4;
+
+  /* Parameter adjustments */
+  lst -= 4;
+  nu -= 7;
+  c -= 3;
+
+  /* Function Body */
+  x = c[(*ss1 << 1) + 1] - c[(*ss2 << 1) + 1];
+  y = c[(*ss1 << 1) + 2] - c[(*ss2 << 1) + 2];
+  i_1 = *nbac - 1;
+  for (i = 1; i <= i_1; ++i)
+     {
+       lst[i * 3 + 1] = i + 1;
+     }
+  lst[*nbac * 3 + 1] = 0;
+  ttlst = 1;
+L20:
+  ptlst = ttlst;
+  pplst = 0;
+L30:
+  if (ptlst > 0)
+     {
+       t1 = lst[ptlst * 3 + 2];
+       a1 = lst[ptlst * 3 + 3];
+       tt1 = nu[a1 + t1 * 6];
+       t2 = tt1 / 8;
+       a2 = tt1 - (t2 << 3);
+       i11 = a1 - 3;
+       i12 = mod3[i11 - 1];
+       i13 = mod3[i12 - 1];
+       i21 = a2 - 3;
+       i22 = mod3[i21 - 1];
+       i23 = mod3[i22 - 1];
+       s1 = nu[i13 + t1 * 6];
+       s2 = nu[i11 + t1 * 6];
+       s3 = nu[i12 + t1 * 6];
+       s4 = nu[i23 + t2 * 6];
+       x41 = c[(s4 << 1) + 1] - c[(s1 << 1) + 1];
+       y41 = c[(s4 << 1) + 2] - c[(s1 << 1) + 2];
+       det2 = (LONG8) (c[(s2 << 1) + 1] - c[(s1 << 1) + 1]) * (LONG8) y41 
+            - (LONG8) (c[(s2 << 1) + 2] - c[(s1 << 1) + 2]) * (LONG8) x41;
+            
+       det3 = (LONG8) (c[(s3 << 1) + 1] - c[(s1 << 1) + 1]) * (LONG8)  y41 
+            - (LONG8) (c[(s3 << 1) + 2] - c[(s1 << 1) + 2]) * (LONG8)  x41;
+       if (det2 > 0 && det3 < 0)
+	  {
+/*         le quadrilataire est convexe on le retourne */
+/*         update des sommets */
+/* ------------------------- */
+	    nu[i12 + t1 * 6] = s4;
+	    nu[i22 + t2 * 6] = s1;
+/*         update du pointeur suivant */
+/* ----------------------------------- */
+	    pslst = lst[ptlst * 3 + 1];
+	    if (pslst > 0)
+	       {
+		 aas = lst[pslst * 3 + 3];
+		 if (aas == i22 + 3)
+		    {
+		      lst[pslst * 3 + 2] = t1;
+		      lst[pslst * 3 + 3] = i11 + 3;
+		    }
+	       }
+/*         update des aretes a1,a2 */
+/* ------------------------------- */
+	    tt1 = nu[i22 + 3 + t2 * 6];
+	    nu[a1 + t1 * 6] = tt1;
+	    if (tt1 > 0)
+	       {
+		 tt = tt1 / 8;
+		 aa = tt1 - (tt << 3);
+		 nu[aa + tt * 6] = a1 + (t1 << 3);
+	       }
+	    else if (tt1 != nothing)
+	       {
+		 nu[-tt1 * 6 + 2] = a1 + (t1 << 3);
+	       }
+	    tt1 = nu[i12 + 3 + t1 * 6];
+	    nu[a2 + t2 * 6] = tt1;
+	    if (tt1 > 0)
+	       {
+		 tt = tt1 / 8;
+		 aa = tt1 - (tt << 3);
+		 nu[aa + tt * 6] = a2 + (t2 << 3);
+	       }
+	    else if (tt1 != nothing)
+	       {
+		 nu[-tt1 * 6 + 2] = a2 + (t2 << 3);
+	       }
+	    nu[i12 + 3 + t1 * 6] = i22 + 3 + (t2 << 3);
+	    nu[i22 + 3 + t2 * 6] = i12 + 3 + (t1 << 3);
+	    
+	    det1 = (LONG8) (c[(s1 << 1) + 1] - c[(*ss1 << 1) + 1]) * (LONG8) y 
+	         - (LONG8) (c[(s1 << 1) + 2] - c[(*ss1 << 1) + 2]) * (LONG8) x;
+	         
+	    det4 = (LONG8) (c[(s4 << 1) + 1] - c[(*ss1 << 1) + 1]) * (LONG8) y 
+	         - (LONG8) (c[(s4 << 1) + 2] - c[(*ss1 << 1) + 2]) * (LONG8) x;
+	    if (det1 < 0 && det4 > 0)
+	       {
+/*           le sommets s4 est dans omega */
+		 lst[ptlst * 3 + 2] = t2;
+		 lst[ptlst * 3 + 3] = i22 + 3;
+	       }
+	    else if (det1 > 0 && det4 < 0)
+	       {
+/*           le sommets s1 est dans omega */
+		 lst[ptlst * 3 + 2] = t1;
+		 lst[ptlst * 3 + 3] = i12 + 3;
+	       }
+	    else
+	       {
+		 if (pplst == 0)
+		    {
+		      ttlst = lst[ptlst * 3 + 1];
+		      ptlst = ttlst;
+		    }
+		 else
+		    {
+		      ptlst = lst[ptlst * 3 + 1];
+		      lst[pplst * 3 + 1] = ptlst;
+		    }
+		 goto L30;
+	       }
+	  }
+       pplst = ptlst;
+       ptlst = lst[ptlst * 3 + 1];
+       goto L30;
+     }
+  if (ttlst != 0)
+     {
+       goto L20;
+     }
+  nu[i12 + 3 + t1 * 6] = nothing;
+  nu[i22 + 3 + t2 * 6] = nothing;
+  *t = t2;
+  *ta = t1;
+  i_1 = *nbac;
+  for (i = 1; i <= i_1; ++i)
+     {
+       mshopt_ (&c[3], &nu[7], &lst[i * 3 + 2], 4L, err);
+       mshopt_ (&c[3], &nu[7], &lst[i * 3 + 2], 5L, err);
+       mshopt_ (&c[3], &nu[7], &lst[i * 3 + 2], 6L, err);
+     }
+  return 1;
+}				/* mshfr2_ */
+
+
+}
diff --git a/src/femlib/splitsimplex.cpp b/src/femlib/splitsimplex.cpp
new file mode 100644
index 0000000..8ba28c1
--- /dev/null
+++ b/src/femlib/splitsimplex.cpp
@@ -0,0 +1,471 @@
+// used by splitsimplex.cpp 
+// ----   build a the simplex decomposition 
+/*
+template void  SplitSimplex<R1>(int N,int & nv, R1 *& P, int & nk , int *& K);
+template void  SplitSimplex<R2>(int N,int & nv, R2 *& P, int & nk , int *& K);
+template void  SplitSimplex<R3>(int N,int & nv, R3 *& P, int & nk , int *& K);
+$:
+*/
+//
+//   
+// ORIG-DATE:     fev 2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model  mesh 2d   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01  */
+
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <cassert>
+#include <fstream>
+#include "ufunction.hpp"
+using namespace std;
+namespace Fem2D  {
+#include "R3.hpp"
+};
+using Fem2D::R1;
+using Fem2D::R2;
+using Fem2D::R3;
+extern  long verbosity ;
+
+#include "splitsimplex.hpp"
+
+/*
+  construction an array of sub simplex for plot ... 
+  see last template function 
+     SplitSimplex(N,nv,P,nk,K);
+  N > 1 -> classical split un N^d sub simplex
+  nv : number of point on    
+*/
+//  d = 1   trivial
+void SplitSimplex(int N,R1 *P,int *K,int op=0,R1 *AB=0)
+{
+  assert(N>0);
+  double h = 1./ N;
+  for(int i=0;i<=N;++i)
+    if(AB)
+      P[i+op] = R1(i*h).Bary(AB);
+    else
+      P[i+op] = R1(i*h);
+  for(int i=0;i<N;++i)
+    {
+      K[i]=i+op;
+      K[i]=i+1+op;
+    }
+}
+/*
+0124 1234 1345 3456 2346 3567 1 solutions de taille 6  trouvees.
+0124 1245 1235 2356 2456 3567 Solution courte numero 7:
+0124 1246 1236 1356 1456 3567 Solution courte numero 12:
+*/
+
+
+
+typedef int int4 [4] ;
+
+// InvIntFunc
+
+inline int NumSimplex2(int i) {return ((i)*(i+1))/2;}
+inline int NumSimplex3(int i) {return ((i)*(i+1)*(i+2))/6;}
+#define InvIntFunction  invNumSimplex2
+#define F(i) NumSimplex2(i)
+#include "InvIntFunc.cpp"
+#undef F
+#undef InvIntFunction
+
+#define InvIntFunction invNumSimplex3
+#define F(i) NumSimplex3(i)
+#include "InvIntFunc.cpp"
+#undef F
+#undef InvIntFunction
+
+inline int NumSimplex1(int i) { return i;}
+inline int NumSimplex2(int i,int j) { return j+NumSimplex2(i+j);}
+inline int NumSimplex3(int i,int j,int k) { return NumSimplex3(i+j+k)+NumSimplex2(j+k)+k;}
+
+
+inline void  invNumSimplex2(int n,int &i,int &j) 
+{
+  int k= invNumSimplex2(n); //( i+j) 
+  j=n-NumSimplex2(k);
+  i= k-j;
+  //  cout << n << " " << k << " -> " << i << " " << j << endl;
+  assert( n == NumSimplex2(i,j));
+}
+inline void  invNumSimplex3(int n,int &i,int &j,int &k) 
+{
+  int l= invNumSimplex3(n); //=( i+j+k) 
+  invNumSimplex2(n-NumSimplex3(l),j,k);
+  i=l-k-j; 
+  // cout << n << "   " << l << "-> " << i << " " << j << " " << k <<endl;
+  assert( n == NumSimplex3(i,j,k)) ;
+}
+
+
+// d = 2
+void SplitSimplex(int N,R2 *P,int *K,int op=0,R2 *ABC=0)
+{
+  assert(N>0);
+  int nv = (N+1)*(N+2)/2;
+  double h=1./N;
+  //   loop sur les diag   i+j = k 
+  //   num  ( i+j,j) lexico croissant  
+  for(int l=0;l<nv;l++)
+    {
+      int i,j;
+      invNumSimplex2(l,i,j);
+      if(ABC)
+	P[l+op]= R2(i*h,j*h).Bary(ABC);
+      else 
+	P[l+op]= R2(i*h,j*h);
+      assert(l<nv);
+    }
+  //    generation des trianges
+  // --------
+  int l=0;
+  for (int i=0;i<N;++i)
+    for (int j=0;j<N;++j)
+      if(i+j<N) 
+	{
+	  K[l++]= op+NumSimplex2(i,j);
+	  K[l++]= op+NumSimplex2(i+1,j);
+	  K[l++]= op+NumSimplex2(i,j+1);
+	}
+      else
+	{
+	  K[l++]= op+NumSimplex2(N-i,N-j);
+	  K[l++]= op+NumSimplex2(N-i,N-j-1);
+	  K[l++]= op+NumSimplex2(N-i-1,N-j);
+	}
+}
+
+
+
+void SplitSimplex(int N,R3 *P,int *tet,int op=0,R3* Khat=0)
+{
+  const int n=N;
+  const int n2=n*n;
+  const int n3=n2*n;
+  const int ntc=6;
+  int nv = (N+1)*(N+2)*(N+3)/6;
+  
+  int d1[6][4] = { {0,1,2,4} , {1,2,4,3},{1,3,4,5},{3,4,5,6},{ 2,3,6,4}, {3,5,7,6} };
+  int ntt=0;
+  int n8[8];
+  int ptet=0;
+  double h=1./N;
+  for(int l=0;l<nv;l++)
+    {
+      int i,j,k;
+      invNumSimplex3(l,i,j,k);
+      if(Khat)
+	P[l+op]= R3(i*h,j*h,k*h).Bary(Khat);
+      else 
+	P[l+op]= R3(i*h,j*h,k*h);
+      assert(l<nv);
+    }
+  // comment n3  i=m[n]
+  //  m = i+j*n+k*n2 
+  for (int m=0;m<n3;m++)
+    {
+      int i = m % n;
+      int j = (m / n) % n;
+      int k = m /( n2);
+      for (int l=0;l<8;++l)
+	{
+	  int ii = ( i + ( (l & 1) != 0) );
+	  int jj = ( j + ( (l & 2) != 0) );
+	  int kk = ( k + ( (l & 4) != 0) );
+	  int ll= NumSimplex3(ii,jj,kk);
+	  n8[l]=ll;
+	  if(ii+jj+kk>n) n8[l]=-1;
+	}
+      for (int l=0;l<ntc;++l)
+	if(ntt<n3)
+	  {
+	    int out =0;
+	    for(int m=0;m<4;++m)
+	      if( (tet[ptet++]= n8[d1[l][m]]+op) < op) out++;
+	    if(out == 0 )  ntt++;
+	    else ptet -= 4; // remove tet
+	  }
+      
+    }
+  if(verbosity>199)
+    {
+      
+      cout <<   "  SplitSimplex   " << endl;
+      for (int i=0,l=0;i<n3;i++)
+       for(int m=0;m<4;++m)
+         cout << tet[l++] << (m==3 ? '\n' : ' ' );
+       cout << ptet << "   " << tet << endl;
+    }
+  assert(ntt==n3);
+}
+
+// Add J. Morice (trunc functions)
+
+void SplitSurfaceSimplex(int N,int &ntri2,int *&tri)
+{
+  const int n=N;
+  const int n2=n*n;
+  
+  int ntri=3*ntri2;
+  int op=0;
+  
+  tri = new int[ntri];
+  //    generation des trianges
+  // --------
+  
+  // face i=0
+  int l=0;
+  if(verbosity>200)
+    cout << "face i=0" << endl;
+  for (int i=0;i<N;++i)
+    for (int j=0;j<N;++j){
+      if(i+j<N) 
+	{
+	  tri[l++]= op+NumSimplex3(0,i,j);
+	  tri[l++]= op+NumSimplex3(0,i+1,j);
+	  tri[l++]= op+NumSimplex3(0,i,j+1); 
+	}
+      else
+	{
+	  tri[l++]= op+NumSimplex3(0,N-i,N-j);
+	  tri[l++]= op+NumSimplex3(0,N-i,N-j-1);
+	  tri[l++]= op+NumSimplex3(0,N-i-1,N-j); 
+	}
+      //cout << "i,j " << i << "," << j << endl;
+      if(verbosity>200)
+      cout << "l="<< l/3 <<  " "<< tri[l-3] <<" "<< tri[l-2] <<" "<<  tri[l-1] <<" "<<  endl;
+    }
+  // face j=0
+  if(verbosity>200)
+  cout << "face j=0" << endl;
+  for (int i=0;i<N;++i)
+    for (int j=0;j<N;++j){
+      if(i+j<N) 
+	{
+	  tri[l++]= op+NumSimplex3(i,0,j);
+	  tri[l++]= op+NumSimplex3(i,0,j+1); // inverser les deux lignes
+	  tri[l++]= op+NumSimplex3(i+1,0,j);
+	}
+      else
+	{
+	  tri[l++]= op+NumSimplex3(N-i,0,N-j);
+	  tri[l++]= op+NumSimplex3(N-i-1,0,N-j); // inverser les deux lignes
+	  tri[l++]= op+NumSimplex3(N-i,0,N-j-1);
+	}
+      //cout << "i,j " << i << "," << j << endl;
+      if(verbosity>200)
+	cout << "l="<< l/3 <<  " "<< tri[l-3] <<" "<< tri[l-2] <<" "<<  tri[l-1] <<" "<<  endl;
+    }
+  // face k=0
+  if(verbosity>200)
+    cout << "face k=0" << endl;
+  for (int i=0;i<N;++i)
+    for (int j=0;j<N;++j){
+      if(i+j<N) 
+	{
+	  tri[l++]= op+NumSimplex3(i,j,0);
+	  tri[l++]= op+NumSimplex3(i+1,j,0);
+	  tri[l++]= op+NumSimplex3(i,j+1,0);
+	  //tri[l++]= op+NumSimplex3(i+1,j,0);
+	}
+      else
+	{
+	  tri[l++]= op+NumSimplex3(N-i,N-j,0);
+	  tri[l++]= op+NumSimplex3(N-i,N-j-1,0);
+	  tri[l++]= op+NumSimplex3(N-i-1,N-j,0); 
+	  //tri[l++]= op+NumSimplex3(N-i,N-j-1,0);
+	}
+      //cout << "i,j " << i << "," << j << endl;
+      if(verbosity>200)
+	cout << "l="<< l/3 <<  " "<< tri[l-3] <<" "<< tri[l-2] <<" "<<  tri[l-1] <<" "<<  endl;
+    }
+  // face i+j+k=1
+  if(verbosity>200)
+    cout << "dernier face " << endl;
+  for (int k=0;k<N;++k)
+    for (int j=0;j<N;++j){
+      if(k+j<N) 
+	{
+	  int i=N-j-k;
+	  tri[l++]= op+NumSimplex3(   i,   j,   k);
+	  tri[l++]= op+NumSimplex3( i-1,   j, k+1); 
+	  tri[l++]= op+NumSimplex3( i-1, j+1,   k);
+	}
+      else
+	{
+	  int i=N-(N-j-1)-(N-k);
+	  tri[l++]= op+NumSimplex3(   i, N-j-1, N-k);
+	  tri[l++]= op+NumSimplex3( i-1, N-j,   N-k); 
+	  tri[l++]= op+NumSimplex3(   i, N-j, N-k-1); 
+	}
+      if(verbosity>200)
+	cout << "l="<< l/3 <<  " "<< tri[l-3] <<" "<< tri[l-2] <<" "<<  tri[l-1] <<" "<<  endl;
+    }
+  if(verbosity>200)
+    cout << "l= " << l << " ntri=" << ntri << endl;
+  assert( l == ntri); 
+}
+
+/*
+void  SplitSimplex(int N,int & nv, R1 *& P, int & nk , int *& K)
+{
+  typedef R1 Rd;
+  const int d = Rd::d;
+  int cas = (N>0) ? 1 : d+1;
+  N=abs(N);
+  assert(N);
+  int nv1=(N+1);
+  int nk1= N;
+  nv = cas*nv1;
+  nk = cas*nk1;
+  
+  P = new Rd[nv];
+  K = new int [nk*(d+1)];
+  if( cas ==1) 
+    SplitSimplex( N, P,K) ;
+    else 
+      {
+	Rd AB1[2]= { Rd(0),Rd(0.5)};
+	SplitSimplex( N, P,K,0,AB1)      ;
+	Rd AB2[2]= { Rd(0.5),Rd(1)};
+	SplitSimplex( N, P,K+nk1,nv1,AB2);      
+      }
+}
+
+
+void  SplitSimplex(int N,int & nv, R2 *& P, int & nk , int *& K)
+{
+  typedef R2 Rd;
+  const int d = Rd::d;
+  int cas = (N>0) ? 1 : d+1;
+  assert(N);
+  N=abs(N);
+  int nv1=N*(N+1)/2;
+  int nk1= N*N;
+  nv = cas*nv1;
+  nk = cas*nk1;
+  P = new Rd[nv];
+  K = new int [nk*(d+1)];
+  if( cas ==1) 
+    SplitSimplex( N, P,K);
+  else 
+    { 
+      Rd G=Rd::diag(1./(d+1));
+      R2 Khat[d+1];
+      for (int i=0;i<d;++i)
+	Khat[i+1][i]=1; //  modit  25/2/2009
+      for(int i=0;i<=d;++i)
+	{
+	  Rd S=Khat[i];
+	  Khat[i]=G;
+	  SplitSimplex( N, P,K+nk1*i,nv1*i,Khat);
+	  Khat[i]=S;
+	}     
+    }
+}
+
+*/
+
+template<class Rd>
+void  SplitSimplex(int N,int & nv, Rd *& P, int & nk , int *& K)
+{
+  const int d = Rd::d,d1 =d+1;
+  int cas = (N>0) ? 1 : d+1;
+  assert(N);
+  N=abs(N);
+  int nv1=N+1; // nb simplexe
+  int nk1=N; // nb vertices
+  for(int i=2;i<=d;++i)
+    {
+      nk1 *=N;
+      nv1 = (nv1)*(N+i)/i;
+    }
+  nv = cas*nv1;
+  nk = cas*nk1;
+  P = new Rd[nv]; // no bug correct jan 2024 FH (thank to OP)
+  K = new int[nk*d1]; // no  bug correct jan 2024 FH (thank to OP)
+  if( cas ==1) 
+    SplitSimplex( N, P,K);
+  else 
+    { 
+      Rd G=Rd::diag(1./(d1));
+      for(int i=0;i<=d;++i)
+	{
+	  Rd Khat[d+1];
+	  for (int j=1;j<=d;++j)
+	    Khat[j][j-1]=1;// bug correct jan 2024 FH (thank to OP) 
+	  Khat[i]=G;
+	  SplitSimplex( N, P,K+(nk1*d1)*i,nv1*i,Khat); // FH  no recursion here ...
+	}     
+    }
+  if(verbosity>99)
+     {
+         cout << "SplitSimplex : nv ="  << nv << " nk :" << nk << " " << N <<  endl ;
+         for(int i=0; i< nv ; ++i)
+             cout << i << " / " << P[i] <<  endl;
+         
+         for(int k=0,kk=0; k < nk; ++k)
+         {
+            cout << k << " " << kk << " : ";
+             for(int m=0;m<d+1;++m)
+                 cout << K[kk++] << " " ;
+             cout << endl;
+         }
+         
+     }
+}
+
+template void  SplitSimplex<R1>(int N,int & nv, R1 *& P, int & nk , int *& K);
+template void  SplitSimplex<R2>(int N,int & nv, R2 *& P, int & nk , int *& K);
+template void  SplitSimplex<R3>(int N,int & nv, R3 *& P, int & nk , int *& K);
+/*
+int main(int argc,const char ** argv)
+{
+  R3 *P;
+  int *K,nv,nk;
+  int N=2;
+  if(argc>1) N=atoi(argv[1]);
+  SplitSimplex(N,nv,P,nk,K);
+  cout << P << " " << K << endl;
+  cout << N << " nv " << nv << " nk =" << nk << endl;
+  for(int i=0;i<nv;++i) cout << P[i] << endl;
+  for(int i=0,l=0;i<nk;i++) 
+    {
+      for(int j=0;j<4;j++) 
+	cout << K[l++] << " ";
+      cout << endl;
+    }
+
+  
+}
+*/
diff --git a/src/femlib/splitsimplex.hpp b/src/femlib/splitsimplex.hpp
new file mode 100644
index 0000000..4a4fb76
--- /dev/null
+++ b/src/femlib/splitsimplex.hpp
@@ -0,0 +1,4 @@
+
+template<class Rd>  void  SplitSimplex(int N,int & nv, Rd *& P, int & nk , int *& K);
+// Add J. Morice for function trunc.
+void SplitSurfaceSimplex(int N,int &ntri2, int *&tri);
diff --git a/src/femlib/ufunction.hpp b/src/femlib/ufunction.hpp
new file mode 100644
index 0000000..e1dfbfe
--- /dev/null
+++ b/src/femlib/ufunction.hpp
@@ -0,0 +1,104 @@
+// ORIG-DATE:     Dec 2007
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  Model of usefull function generic function   
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curi, Paris,  FRANCE 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : frederic.hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#ifndef UFUNCTION_HPP_
+#define UFUNCTION_HPP_
+// some usefull function
+template<class T> inline T Min (const T &a,const T &b){return a < b ? a : b;}
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
+template<class T> inline double Norme (const T &a){return sqrt(a*a);}
+template<class T> inline void Exchange (T& a,T& b) {T c=a;a=b;b=c;}
+template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
+template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
+
+
+template<int d,typename A,typename B>
+struct Copy {
+static A * copy(A a[d],B * const b)
+{
+  for (int i=0;i<d;++i)
+    a[i]=b[i];
+  return a;
+}};
+
+template<typename A,typename B>
+struct Copy<1,A,B> {
+static A * copy(A a[1],B * const b  )
+{
+    a[0]=b[0];
+  return a;
+}};
+
+template<typename A,typename B>
+struct Copy<2,A,B> {
+static A * copy(A a[2],B * const b)
+{
+    a[0]=b[0];
+    a[1]=b[1];
+
+  return a;
+}};
+
+template<typename A,typename B>
+struct Copy<3,A,B> {
+static A * copy(A a[3],B * const b)
+{
+    a[0]=b[0];
+    a[1]=b[1];
+    a[2]=b[2];
+  return a;
+}};
+
+template<typename A,typename B>
+struct Copy<4,A,B> {
+static A * copy(A a[4],B * const b)
+{
+    a[0]=b[0];
+    a[1]=b[1];
+    a[2]=b[2];
+    a[3]=b[3];
+  return a;
+}};
+
+struct UniqueffId {
+private:
+  static int count ;
+  int id;
+public:
+  UniqueffId() : id(++count) {}
+  bool operator==(UniqueffId u) const {return id==u.id;}
+  bool operator!=(UniqueffId u) const {return id!=u.id;}
+  void init(){id=++count;}
+};
+
+#endif
diff --git a/src/fflib/._AFunction.hpp b/src/fflib/._AFunction.hpp
new file mode 100644
index 0000000..63e1130
Binary files /dev/null and b/src/fflib/._AFunction.hpp differ
diff --git a/src/fflib/._AFunction2.cpp b/src/fflib/._AFunction2.cpp
new file mode 100644
index 0000000..e9604e8
Binary files /dev/null and b/src/fflib/._AFunction2.cpp differ
diff --git a/src/fflib/._array_tlp.hpp b/src/fflib/._array_tlp.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/fflib/._array_tlp.hpp differ
diff --git a/src/fflib/._ffapi.cpp b/src/fflib/._ffapi.cpp
new file mode 100755
index 0000000..14f037e
Binary files /dev/null and b/src/fflib/._ffapi.cpp differ
diff --git a/src/fflib/._ffapi.hpp b/src/fflib/._ffapi.hpp
new file mode 100755
index 0000000..14f037e
Binary files /dev/null and b/src/fflib/._ffapi.hpp differ
diff --git a/src/fflib/._lgfem.cpp b/src/fflib/._lgfem.cpp
new file mode 100644
index 0000000..e9604e8
Binary files /dev/null and b/src/fflib/._lgfem.cpp differ
diff --git a/src/fflib/._lgsolver.hpp b/src/fflib/._lgsolver.hpp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/fflib/._lgsolver.hpp differ
diff --git a/src/fflib/AFunction.cpp b/src/fflib/AFunction.cpp
new file mode 100644
index 0000000..6e6d861
--- /dev/null
+++ b/src/fflib/AFunction.cpp
@@ -0,0 +1,1964 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//#pragma dont_inline on
+//#pragma inline_depth(1)
+
+#include "config-wrapper.h"
+
+#include <cmath>
+#include <complex>
+//  put here some def dur to c++11 
+// problem with mixed with using namespace std; 
+// to correct bug in g++ v 4.8.1 add std
+long isNaN(double x){return isnan(x);}
+long isInf(double x){return isinf(x);}
+long isNormal(double x){return std::isnormal(x);}
+#ifdef HAVE_JN
+double myyn(long n, double x){ return yn((int)n,x);}
+double myjn(long n, double x){ return jn((int) n,x);}
+#endif
+//int  ShowAlloc(const char *s, size_t lg);
+
+// F. Hecht fev. 2015 ...
+#include "AFunction.hpp"
+#include <cstdarg>
+#include <cstring>
+#include "error.hpp"
+#include "lex.hpp"
+
+#include "RNM.hpp"
+
+#include "Operator.hpp"
+// for exec routine 
+#include "rgraph.hpp"
+#include "InitFunct.hpp"
+#include <queue>
+
+#include "array_init.hpp"
+
+// Add FH to get memroy used in test .. march 2014
+#if __APPLE__
+#include <malloc/malloc.h>
+#elif HAVE_MALLOC_H
+#include <malloc.h> 
+#endif
+#ifdef HAVE_TIMES
+#include <time.h>
+#endif
+long storageused()
+{
+#if HAVE_MSTATS
+    struct mstats mem1;
+    mem1 = mstats();
+    return mem1.bytes_used;
+#elif HAVE_MALLINFO
+    struct mallinfo mem1;
+    mem1=mallinfo();
+    return mem1.uordblks;
+#else
+    return 0;
+#endif
+
+}
+long storagetotal()
+{
+#if HAVE_MSTATS
+    struct mstats mem1;
+    mem1 = mstats();
+    return mem1.bytes_total;
+#elif HAVE_MALLINFO
+    struct mallinfo mem1;
+    mem1=mallinfo();
+    return mem1.keepcost;
+#else
+    return 0;
+#endif
+}
+// end add mach 2014 ...
+extern Map_type_of_map map_type_of_map ; //  to store te type 
+extern Map_type_of_map map_pair_of_type ; //  to store te type 
+
+extern basicForEachType *  typevarreal,  * typevarcomplex;  //  type of real and complex variable
+
+extern int TheCurrentLine; // unset: by default
+extern long mpisize,mpirank;
+// FH  for g++ 3.4  the prototypage  have change
+double  VersionNumber(); 
+double Imag(const  complex<double> & z){ return imag(z);}
+double Real(const  complex<double> & z){ return real(z);}
+const  basicForEachType * basicForEachType::type_C_F0 =0; //  for any type un formal operation .... FH add 09/2012
+
+// FH
+
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+template<class T> inline T Min (const T &a,const T & b){return a < b ? a : b;}
+template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
+template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
+template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
+template<class T> inline T Square (const T &a){return a*a;}
+
+struct SubArray2: public binary_function<long,long,SubArray> { 
+  static SubArray f(const long & a,const long & b)  { 
+   // cout << "SubArray: " << a << " " << b << endl;
+    return SubArray(b-a+1,a);} }; 
+struct SubArray3: public ternary_function<long,long,long,SubArray> { 
+  static SubArray f(Stack s,const long & a,const long & b,const long & c)  {  
+  // cout << "SubArray: " << a << " " << b << " " <<  c << endl;
+   return SubArray((b-a+1)/c,a,c);} }; 
+
+#ifdef OLDCPP
+template<class T> inline
+complex<T> polar(const T& r, const T& theta)
+{
+	return complex<T>(r * cos(theta), r * sin(theta));
+}
+#endif
+
+
+double preal( Complex * const& p){return real(*p);}
+
+ 
+template<class A,class B>  A Build(B b) {  return A(b);}
+  
+  
+
+
+long Exit(long i) {throw(ErrorExit("Exit",i));return 0;}
+bool Assert(bool b) {if (!b) throw(ErrorExec("exec assert",1));return true;}
+  
+inline void MyAssert(int i,char * ex,char * file,long line)
+{if (i) {
+    cout << "CompileError assertion :  " << ex << " in file " << file << "  line = " << line << endl; 
+     CompileError();}
+ }
+
+
+/*  
+template<class R>
+class  OneOperator0 : public OneOperator {
+ class E_F0_F :public  E_F0 { public:
+  typedef  R (*func)( ) ; 
+  func f;
+  E_F0_F(func ff)  : f(ff) {}
+  AnyType operator()(Stack )  const  {return SetAny<R>( f()) ;}  
+     operator aType () const { return atype<R>();} 
+
+};
+
+  //  aType r; //  return type
+    typedef  R (*func)() ; 
+    func  f;
+    public: 
+    E_F0 * code(const basicAC_F0 & ) const 
+     { return  new E_F0_F(f);} 
+    OneOperator0(func  ff): OneOperator(map_type[typeid(R).name()]),f(ff){}
+};
+*/
+template<class R>
+class  OneOperatorConst : public OneOperator {
+    E_F0 * e;
+    public: 
+    E_F0 * code(const basicAC_F0 & ) const  { return  e;} 
+    OneOperatorConst(E_F0 * ee):  OneOperator(map_type[typeid(R).name()]),e(ee){}
+};
+
+class  OneOperator_array : public OneOperator {public:
+    E_F0 * code(const basicAC_F0 & a) const 
+     { return  new E_Array(a);} 
+    OneOperator_array(): OneOperator(atype<E_Array>(),true) {}
+};
+class  OneOperator_border : public OneOperator {public:
+    E_F0 * code(const basicAC_F0 & a) const 
+     { if (a.size()==1 && a[0].left()==atype<E_Array>() ) 
+        return new E_Border(dynamic_cast<const E_Array*>(a[0].LeftValue()));
+        else     
+        return  new E_Border(a);} 
+    OneOperator_border(): OneOperator(atype<const E_Border *>(),true) {}
+};
+
+class  OneOperator_border_label : public OneOperator {public:
+  class Op : public E_F0 {public:
+   const  E_Border *b;
+      Op( const  E_Border *bb) : b(bb) {}
+      AnyType operator()(Stack)  const { return SetAny<long>(b->label);}
+   };
+    E_F0 * code(const basicAC_F0 & a) const 
+     {  const  E_Border * b = dynamic_cast<const E_Border *>(a[0].LeftValue());
+        return new Op(b);} 
+    OneOperator_border_label(): OneOperator(atype<long>(),atype<const E_Border *>()) {}
+};
+
+
+
+template<class RR> RR LIncremantation(RR* a){ return ++(*a);}
+template<class RR> RR RIncremantation(RR* a){ return (*a)++;}
+template<class RR> RR LDecremantation(RR* a){ return --(*a);}
+template<class RR> RR RDecremantation(RR* a){ return (*a)--;}
+
+template<class RR,class B>
+ RR * New_form_string(string * s) {B * r=  new B(s);delete s;return r;}// correct Mars 2011 remove * if delete
+ 
+ 
+
+
+inline   string ** get_elements( MyMap<String,String> *  const  &  a,string*  const   & b)
+ { String* Sret=  &((*a)[*b]); // correction FH feb 2004
+   // delete b; la chaine est detruire automatiquement en fin d'instruction  FH jan 2010
+    return Sret->getap();}
+
+template<class RR> RR Abs(RR a) { return a<0?-a:a;}
+
+template<class R,class A,class B>
+R *MakePtrWithDel( A  const & a)
+{ R *r= new B(a->c_str());
+  delete a;
+  return r;}
+
+template<class R,class RR> 
+struct Op1_new_pstring: public unary_function<string*,R> { 
+  static R f(string * const & a)  {R r =  new RR(a->c_str());
+    // delete a;  (stack ptr) FH mars 2006
+    return r;} }; 
+
+template<class R,class RR> 
+struct Op2_set_pstring: public binary_function<R,string*,R> { 
+  static R  f(R const & p,string * const & a)  {*p =  new RR(a->c_str());
+   if ( !*p || !**p) { 
+       cerr << " Error openning file " << *a << endl; 
+       ExecError("Error openning file");}
+  //  delete a; modif mars 2006 FH
+   return p;} }; 
+
+template<class R,class RR> 
+struct Op2_set_pstringiomode: public ternary_function<R,string*,ios::openmode,R> { 
+  static R  f(Stack s,R const & p,string * const & a,const ios::openmode & mode) 
+   {*p =  new RR(a->c_str(),mode);
+     // delete a;   modif mars 2006 FH
+    return p;} }; 
+
+AnyType FWhile(Stack s ,Expression test,Expression ins)
+{ 
+  bool sptrclean=true;
+  AnyType a;
+  StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
+  while ( GetAny<bool>((*test)(s)))
+     try  { 
+        a=(*ins)(s);
+        if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+       }
+     catch ( E_exception & e) { 
+        if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+       if (e.code == E_exception::e_break) break;
+       else if  (e.code == E_exception::e_continue) continue;
+       else throw e;
+       }
+  return a;
+}
+    
+AnyType FFor(Stack s ,Expression i0,Expression i1,Expression i2,Expression ins)
+{ 
+  bool sptrclean=true;
+  AnyType a;
+     StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
+  for ( (*i0)(s);GetAny<bool>((*i1)(s));(*i2)(s))
+   {
+     try  {
+        a=(*ins)(s);
+        if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+       }
+     catch ( E_exception & e) { 
+        if (verbosity>50)
+          cerr << "FFor " << e.what() << e.code << endl; 
+        if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+       if (e.code == E_exception::e_break) break;
+       else if  (e.code == E_exception::e_continue) continue;
+       else throw e;
+       }
+   }
+  return a;
+}
+
+AnyType TTry(Stack s ,Expression ins,Expression ccatch,Expression fin,Expression notused)
+{ 
+  assert(notused == 0);
+  AnyType a;
+     try  {a=(*ins)(s);}
+     catch ( E_exception & e) { 
+        throw e; 
+       }
+     catch(...) {
+        if(verbosity> 2) cerr << "Try:: catch (...) exception " << endl;
+        a=(*ccatch)(s);         
+     }
+   
+   a=(*fin)(s);
+  return a;
+}
+
+AnyType FIf(Stack s ,Expression test,Expression i1,Expression i2,Expression )
+ {  AnyType a;
+   if (GetAny<bool>((*test)(s))) 
+     {
+       if(i1) a=(*i1)(s);//Add if FH oct 2010
+     }
+      else if (i2) 
+    {
+     if(i2) a=(*i2)(s); //Add if FH oct 2010
+    }
+   	     	
+  return a;
+ }
+
+
+
+aType TypeArray(aType b,aType a)
+{ // type of  b[a]
+   aType r=map_type_of_map[make_pair(a->right(),b->right())];
+   if (!r) {
+      cerr << "Sorry is not possible to make a map "<< *b->right() << " [" << *a->right() << "]" << endl;
+      cerr << " list: " << endl;
+      Map_type_of_map::const_iterator i;
+      for(i=map_type_of_map.begin();i!=map_type_of_map.end();i++)
+        cerr << "\t " << *i->first.second << " [" << *i->first.first << "]" << "=" << *i->second << endl;        
+      CompileError();
+   }
+   return r;
+}
+
+aType TypeTemplate(aType b,aType a)
+{ // type of  b[a]
+   aType r=map_type_of_map[make_pair(b,a)];
+   if (!r) {
+      cerr << "Sorry is not possible to make a map "<< *b << "<" << *a << ">" << endl;
+      cerr << " list: " << endl;
+      Map_type_of_map::const_iterator i;
+      for(i=map_type_of_map.begin();i!=map_type_of_map.end();i++)
+        cerr << "\t " << *i->first.second << " <" << *i->first.first << ">" << "=" << *i->second << endl;        
+      CompileError();
+   }
+   return r;
+}
+aType TypeArray(aType c,aType b,aType a)
+{
+   // type of  c[ b, a] 
+   aType ba=map_pair_of_type[make_pair(b->right(),a->right())];
+   if (!ba) {
+      cerr << "Sorry is not possible to make a type of pair  "<< *b->right() << ", " << *c->right() << " " << endl;
+      cerr << " list: " << endl;
+      Map_type_of_map::const_iterator i;
+      for(i=map_pair_of_type.begin();i!=map_pair_of_type.end();i++)
+        cerr << "\t (" << *i->first.second << " , " << *i->first.first << ") " << "=" << *i->second << endl;        
+      CompileError();
+   }
+   return TypeArray(c,ba);
+}
+
+
+inline  void ShowOn_cerr(const pair<const char * ,const OneOperator *> & i)
+{ 
+   cerr << "\t" <<  *i.first << ":" <<  endl;
+   i.second->Show(cerr);
+}
+
+
+
+void ShowKeyWord(ostream & f ) 
+ {
+   zzzfff->dump(f);
+ 
+ }
+
+ostream* dumptable(ostream* f)
+{
+
+  *f << " the keywords " << endl;
+  ShowKeyWord(*f);
+  *f << " the types " << endl; 
+  ShowType(*f);
+   ListOfTOfId::const_iterator i=tables_of_identifier.begin();
+   for(;i!=tables_of_identifier.end();++i)
+    { 
+      cout << "  --------- table of identifier ---------\n";
+      TableOfIdentifier * ti=*i;
+      TableOfIdentifier::const_iterator mc=ti->m.begin();
+      TableOfIdentifier::const_iterator end=ti->m.end();
+      for (;mc != end;mc++)
+       {
+         *f  << "  - " << mc->first << ",  type :" <<  *mc->second.first << endl;
+         const Polymorphic * op =dynamic_cast<const Polymorphic *>(mc->second.second) ;
+         if ( op )  *f << *op << endl;
+       }
+      
+     }
+  
+  return f;
+}
+
+
+long exec(string *s)
+    {
+      int r=execute(s->c_str());
+    //  delete s;    modif mars 2006 FH
+      return r;}
+      
+
+
+ 
+ class ostream_precis { public:
+ ostream_precis(ostream * ff) :f(ff) {}
+  ostream * f;
+   operator long () const {return f->precision();}
+ };
+
+ ostream_precis ostream_precision(ostream **f){ return ostream_precis(*f);}
+  ostream_precis ostream_precision(ostream *f){ return ostream_precis(f);}
+ long get_precis( ostream_precis  pf) { return pf.f->precision();}
+ long set_precis( ostream_precis  pf, long  l) { return pf.f->precision(l);}
+
+class ostream_seekp { public:
+    ostream_seekp(ostream * ff) :f(ff) {}
+    ostream * f;
+    operator long () const {return f->tellp();}
+};
+
+
+class istream_seekg { public:
+    istream_seekg(istream * ff) :f(ff) {}
+    istream * f;
+    operator long () const {return f->tellg();}
+};
+
+ostream_seekp ff_oseekp(ostream **f){ return ostream_seekp(*f);}
+ostream_seekp ff_oseekp(ostream *f){ return ostream_seekp(f);}
+istream_seekg ff_iseekg(istream **f){ return istream_seekg(*f);}
+istream_seekg ff_iseekg(istream *f){ return istream_seekg(f);}
+
+long ffseekp( ostream_seekp  pf, long  l) {  pf.f->clear();long ll= pf.f->tellp(); return pf.f->seekp(l),ll;}
+long fftellp( ostream_seekp  pf) { pf.f->clear(); return pf.f->tellp() ;}
+long ffseekg( istream_seekg  pf, long  l) { pf.f->clear(); return pf.f->seekg(l),l;}
+long fftellg( istream_seekg  pf) { return pf.f->tellg() ;}
+
+ class istream_good { public:
+  istream_good(istream * ff) :f(ff) {}
+  istream * f;
+  operator bool () const {return f->good();}
+ };
+ inline istream_good to_istream_good(istream **f){ return istream_good(*f);}
+ inline istream_good to_istream_good(istream *f){ return istream_good(f);}
+  
+  inline long get_good( istream_good  pf) { return pf.f->good();}
+  inline bool get_eof(istream ** p){ return (**p).eof();}
+ 
+typedef ios_base& ( * ostream_manipulateur )(ios_base&);
+
+ios_base&  default1(ios_base& f)
+{
+    f.flags( (ios_base::fmtflags) 0 ) ; // (/*ios_base::scientific | */ios_base::fixed) );
+    return f;
+}
+
+
+template< ostream_manipulateur pf> 
+inline ostream **set_os(ostream **f)
+{ 
+    **f << pf  ; return f;
+}
+
+inline ostream **set_os_flush(ostream **f)
+{ 
+    (**f).flush()  ; return f;
+}
+inline ostream *set_os_flush(ostream *f)
+{ 
+    (*f).flush()  ; return f;
+}
+template< ostream_manipulateur pf> 
+inline ostream *set_os1(ostream *f)
+{ 
+    *f << pf  ; return f;
+}
+
+
+template<class R>
+class  OneOperator_0 : public OneOperator {
+  class E_F0_F :public  E_F0mps { public:
+    typedef  R (*func)( ) ; 
+    func f;
+    E_F0_F(func ff)  : f(ff) {}
+    AnyType operator()(Stack )  const {return SetAny<R>( f()) ;}  
+    operator aType () const { return atype<R>();} 
+
+  };
+
+  typedef  R (*func)() ; 
+  func  f;
+public: 
+  E_F0 * code(const basicAC_F0 & ) const 
+  { return  new E_F0_F(f);} 
+  OneOperator_0(func  ff): OneOperator(map_type[typeid(R).name()]),f(ff){}
+};
+
+
+void init_by_array(unsigned long init_key[], int key_length);
+long genrand_int32(void);
+void init_genrand(unsigned long);
+long genrandint (long  s) { init_genrand( (unsigned long ) s); return 0;}
+long genrandint32 () {return (long)  genrand_int32();}
+
+template<class A,class B,bool RO=true>
+struct  MIMul {
+  static bool MeshIndependent(Expression a,Expression b)   
+   { 
+    bool mia= a->MeshIndependent() ;
+    bool mib= b->MeshIndependent();
+    if ( mia && mib) return true;
+    else
+      {
+        if (mia && a->EvaluableWithOutStack() )
+          {
+            A va = GetAny<A>((*a)(NullStack));
+           // cout << " va = " << va << endl;
+            if ( va == A() )
+             { 
+             //  cout << " va = " << va << endl; 
+               return true;
+             }
+          }
+        if (mib && b->EvaluableWithOutStack() )
+          {
+            B vb = GetAny<B>((*b)(NullStack));
+            // cout << " vb = " << vb << endl;
+            if ( vb == B() ) 
+            { //cout << " vb = " << vb << endl;
+             return true; }
+           }
+         return false;
+        }
+      
+    }
+  static bool ReadOnly() { return RO;}
+    
+};
+// add frev 2007
+class TransE_Array:  public E_F0 {  public:  
+     const E_Array * v;
+    int size() const {return v->size();}
+    size_t nbitem() const {return v->size();}
+    bool MeshIndependent(){return v->MeshIndependent();}
+    TransE_Array(const E_Array * e): v(e) {ffassert(e);}
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+};
+
+
+// add frev 2007 
+class opTrans : public OneOperator{
+public:
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    opTrans():   OneOperator(atype<TransE_Array>(),atype<E_Array>()  ) {}
+    E_F0 * code(const basicAC_F0 & args) const {
+	  return new TransE_Array(dynamic_cast<const E_Array*>((Expression) args[0])); } 
+};
+
+/*
+class opTTrans : public OneOperator{
+public:
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    opTTrans():   OneOperator(atype<E_Array>(),atype<TransE_Array>()  ) {}
+    E_F0 * code(const basicAC_F0 & args) const {
+	return dynamic_cast<const TransE_Array*>((Expression) args[0])->v; } 
+};
+*/ 
+
+class opDot : public OneOperator{
+public:
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    bool MeshIndependent() const { return false;}
+    
+    opDot(aType A, aType B): OneOperator(atype<C_F0>(),A,B) {}
+    opDot(): OneOperator(atype<C_F0>(),atype<TransE_Array >(),atype<E_Array>()  ) {}
+    
+    E_F0 *  code(const basicAC_F0 & ) const {ffassert(0);}
+    C_F0  code2(const basicAC_F0 &args) const;       
+};
+
+
+class opColumn : public OneOperator{
+public:
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    bool MeshIndependent() const { return false;}
+    
+    opColumn(aType A, aType B): OneOperator(atype<C_F0>(),A,B) {if( A== basicForEachType::type_C_F0)pref=-100;}
+    opColumn(aType A): OneOperator(atype<C_F0>(),ArrayOfaType(A,true)) {pref=-100;}
+    
+  //  opColumn(): OneOperator(atype<C_F0>(),atype<TransE_Array >(),atype<E_Array>()  ) {}
+    
+    E_F0 *  code(const basicAC_F0 & ) const {ffassert(0);}
+    C_F0  code2(const basicAC_F0 &args) const;
+};
+
+class opSum : public OneOperator{
+public:
+    const char * op;
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    bool MeshIndependent() const { return false;}
+    
+    opSum(const char *opp,aType A, aType B): OneOperator(atype<C_F0>(),A,B),op(opp) {}
+    
+    E_F0 *  code(const basicAC_F0 & ) const {ffassert(0);}
+    C_F0  code2(const basicAC_F0 &args) const;       
+};
+
+
+/*
+class opArray : public OneOperator{
+public:
+    const char * op;
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    bool MeshIndependent() const { return false;}
+    
+    opSum(const char *opp,aType A, aType B): OneOperator(atype<C_F0>(),A,B),op(opp) {}
+    
+    E_F0 *  code(const basicAC_F0 & ) const {ffassert(0);}
+    C_F0  code2(const basicAC_F0 &args) const;       
+};
+*/
+
+class opFormal : public OneOperator{
+public:
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    bool MeshIndependent() const { return false;}
+    C_F0  (*thecode2)(const basicAC_F0 &args);     
+    opFormal(aType A,C_F0  (c2)(const basicAC_F0 &args) ): OneOperator(atype<C_F0>(),A),thecode2(c2) {}       
+    E_F0 *  code(const basicAC_F0 & ) const {ffassert(0);}
+    C_F0  code2(const basicAC_F0 &args) const { return (*thecode2)(args);}    
+};
+// fin frev 2007
+// nov 2007   v[i]
+class opVI : public OneOperator{
+public:
+    AnyType operator()(Stack s)  const {ffassert(0);return 0L;}
+    bool MeshIndependent() const { return false;}
+    
+    opVI(aType A): OneOperator(atype<C_F0>(),A,atype<long>()) {}
+    
+    E_F0 *  code(const basicAC_F0 & ) const {ffassert(0);}
+    C_F0  code2(const basicAC_F0 &args) const;       
+};
+// fin nov 2007
+//  add 2010 feb.  FH
+C_F0 TryConj(const C_F0 & c) {
+    //   here put the conj   operator ... 
+    ArrayOfaType at(c.left()); 
+    basicAC_F0_wa p(c);
+    const  OneOperator *  ff=TheOperators->Find("\'",at);
+	if (ff) { 
+	    if(verbosity>10) 
+	    cout << " ( do Conj) "  ;
+	     return ff->code2(p);
+	}
+	
+    return c; }
+// fin add 2010 feb.	  
+// avril 2007
+
+C_F0  formalMatCofactor(const basicAC_F0 &args)
+{
+    bool ta =args[0].left()==atype<TransE_Array>();
+    const TransE_Array * tea=0;
+    const E_Array * ea=0;
+    if( ta)  tea = dynamic_cast<const TransE_Array*>((Expression) args[0]);
+    else ea = dynamic_cast<const E_Array*>((Expression) args[0]);
+    assert( ea || tea );
+    const E_Array & a=  ta ? *tea->v : *ea;
+    int ma =1;
+    int na=a.size();
+    if(na <1 ) CompileError(" Cofactor  ([ ...])  ");
+    bool maa= a[0].left()==atype<E_Array>();
+    if(maa) {
+	ma= a[0].LeftValue()->nbitem();
+	for (int i=1;i<na;i++)
+	    if( ma != (int) a[i].LeftValue()->nbitem())
+		CompileError(" a matrix with variable number of columm");
+        
+    }
+    
+    int na1=na,ma1=ma;
+    if(ta) RNM::Exchange(na1,ma1);
+    if(na1 != ma1) CompileError(" CoFactor:  no square matrix ");
+    if(na1 > 3 || ( na1 <1) ) CompileError(" CoFactor:   square matrix size is more then 3   ");
+    KNM<CC_F0> A(na1,na1);
+    KNM<CC_F0> C(na1,na1);
+    if(maa)
+	for (int i=0;i<na;++i)
+	{
+	    const E_Array * li=  dynamic_cast<const E_Array *>(a[i].LeftValue());
+	    ffassert(li);
+	    for (int j=0; j<ma;++j)
+		if(!ta)  A(i,j) = (*li)[j];
+		else     A(j,i) = TryConj((*li)[j]);
+	}
+    else
+        for (int i=0;i<na;++i)
+            if(!ta)  A(i,0) = a[i];
+            else     A(0,i) = TryConj(a[i]);
+    
+    
+    AC_F0  v,cc;
+    if(na1==2)
+    {
+      for(int i=0;i<na1;++i)
+        for(int j=0;j<na1;++j)
+          if( (i+j) %2 == 0)
+            C(i,j) = A(1-i,1-j);
+          else
+            C(i,j) = C_F0(TheOperators,"-",A(1-i,1-j));
+    }
+    else if( na1 ==3)
+    {
+        int i1,i2,j1,j2;
+        for(int i=0;i<3;++i)
+          for(int j=0;j<3;++j)
+          {
+              i1 = (i+1)%3;
+              i2 = (i+2)%3;
+              j1 = (j+1)%3;
+              j2 = (j+2)%3;
+              
+            C(i,j) = A(i1,j1)*A(i2,i2)-A(i1,j2)*A(i2,j1);
+          }
+    }
+    v=C(0,0);
+    
+    for (int i=0;i<na1;++i)
+    {  cc = C(i,0);
+        for (int j=1;j<ma1;++j)
+            cc+= C(i,j);
+        C_F0  vi(TheOperators,"[]",cc);
+        if(i==0) v=vi;
+        else v+= vi;
+    }
+    return C_F0(TheOperators,"[]",v);
+
+    
+}
+
+C_F0  formalMatTrace(const basicAC_F0 &args)       
+{
+    bool ta =args[0].left()==atype<TransE_Array>();
+    const TransE_Array * tea=0;
+    const E_Array * ea=0;
+	if( ta)  tea = dynamic_cast<const TransE_Array*>((Expression) args[0]);
+    else ea = dynamic_cast<const E_Array*>((Expression) args[0]);
+    assert( ea || tea );
+    const E_Array & a=  ta ? *tea->v : *ea;
+    int ma =1;
+    int na=a.size();
+    if(na <1 ) CompileError(" trace  [ ...]  ");
+    bool maa= a[0].left()==atype<E_Array>();
+    if(maa) {
+	ma= a[0].LeftValue()->nbitem();
+	for (int i=1;i<na;i++)
+	    if( ma != (int) a[i].LeftValue()->nbitem()) 
+		CompileError(" first matrix with variable number of columm");
+        
+    }
+
+    int na1=na,ma1=ma;
+    if(ta) RNM::Exchange(na1,ma1);
+    if(na1 != ma1) CompileError(" trace:  no square matrix ");
+    KNM<CC_F0> A(na1,ma1);
+    
+    if(maa)
+	for (int i=0;i<na;++i)
+	{
+	    const E_Array * li=  dynamic_cast<const E_Array *>(a[i].LeftValue());
+	    ffassert(li);
+	    for (int j=0; j<ma;++j)
+		if(!ta)  A(i,j) = (*li)[j];
+		else     A(j,i) = TryConj((*li)[j]);
+	} 
+	    else
+		for (int i=0;i<na;++i)
+		    if(!ta)  A(i,0) = a[i];
+		    else     A(0,i) = TryConj(a[i]);
+    
+    
+    CC_F0 s;
+    s= A(0,0);
+    for (int i=0;i<na1;++i)
+	s = C_F0(TheOperators,"+",s,A(i,i));
+    return  s;
+     
+}
+
+
+C_F0  formalMatDet(const basicAC_F0 &args)
+{
+    bool ta =args[0].left()==atype<TransE_Array>();
+    const TransE_Array * tea=0;
+    const E_Array * ea=0;
+    if( ta)  tea = dynamic_cast<const TransE_Array*>((Expression) args[0]);
+    else ea = dynamic_cast<const E_Array*>((Expression) args[0]);
+    assert( ea || tea );
+    const E_Array & a=  ta ? *tea->v : *ea;
+    int ma =1;
+    int na=a.size();
+    if(na <1 ) CompileError(" trace  [ ...]  ");
+    bool maa= a[0].left()==atype<E_Array>();
+    if(maa) {
+	ma= a[0].LeftValue()->nbitem();
+	for (int i=1;i<na;i++)
+	    if( ma != (int) a[i].LeftValue()->nbitem()) 
+		CompileError("  matrix with variable number of columm");
+        
+    }
+    
+    int na1=na,ma1=ma;
+    if(ta) RNM::Exchange(na1,ma1);
+    if(na1 != ma1) CompileError(" trace:  no square matrix ");
+    KNM<CC_F0> A(na1,ma1);
+    
+    if(maa)
+	for (int i=0;i<na;++i)
+	{
+	    const E_Array * li=  dynamic_cast<const E_Array *>(a[i].LeftValue());
+	    ffassert(li);
+	    for (int j=0; j<ma;++j)
+		if(!ta)  A(i,j) = (*li)[j];
+		else     A(j,i) = TryConj((*li)[j]);
+	} 
+	    else
+		for (int i=0;i<na;++i)
+		    if(!ta)  A(i,0) = a[i];
+		    else     A(0,i) = TryConj(a[i]);
+    
+    
+    if(na1==1)
+      return  A(0,0);
+    else if( na1==2 )
+    {
+	C_F0 s1(TheOperators,"*",A(0,0),A(1,1));
+	C_F0 s2(TheOperators,"*",A(0,1),A(1,0));
+	return C_F0(TheOperators,"-",s1,s2);
+    }
+    else if( na1==3 )
+    {
+        int i=0,ii=(i+1)%3,iii=(i+2)%3;
+        A(i,0)*A(i,0);
+        C_F0 det = A(i,0)*A(ii,1)*A(iii,2) - A(i,0)*A(ii,2)*A(iii,1);
+        i++;ii=(i+1)%3,iii=(i+2)%3;
+        det +=  A(i,0)*A(ii,1)*A(iii,2) - A(i,0)*A(ii,2)*A(iii,1);
+        i++;ii=(i+1)%3,iii=(i+2)%3;
+        det +=  A(i,0)*A(ii,1)*A(iii,2) - A(i,0)*A(ii,2)*A(iii,1);
+        return det;
+    }
+    else
+    {
+	CompileError("FH: sorry only det of 1x1 and 2x2 matrix ");
+    }
+    return  C_F0(); 
+    
+}
+
+//  Add juin  2007 
+template<class A,class B=A,class R=A>
+struct evalE_mul {
+    static AnyType eval(Stack s,const E_F0 * ab,const E_F0 * a,const E_F0 * b, bool & meshidenp) 
+    {
+	A aa = GetAny<A>((*a)(s)) ;
+	B bb = GetAny<B>((*b)(s)) ;
+	R rr(aa*bb);
+	bool mia=a->MeshIndependent();
+	bool mib=b->MeshIndependent();
+	
+	if (( aa == A()) && mia ) meshidenp=true;
+	else if(( bb == B()) && mib ) meshidenp=true;
+        else meshidenp = mib && mia;
+	cout << " meshidenp ??? " << meshidenp << " " << rr << endl;
+	return SetAny<R>(static_cast<R>(rr)); 
+    }
+};
+istream *Getline(istream * f, string ** s)
+{
+    if( *s==0) *s=new string;
+    getline(*f,**s);
+    size_t l = (**s).length();
+    if( l > 0 && ((**s)[l-1]=='\r')) (**s).resize(l-1); //
+       return f;    
+}
+// Fin Add ne marche pas ....
+// fiun avril 2007
+//  Hack to Bypass a bug in freefem FH  ... 
+template<> 
+class ForEachType<void *>:  public basicForEachType{public:// correction july 2009..... FH  Hoooo....  (Il y a un bug DUR DUR FH  ...) 
+    ForEachType(Function1 iv=0,Function1 id=0,Function1 OOnReturn=0):basicForEachType(typeid(void *),sizeof(void *),0,0,iv,id,OOnReturn) { }
+};
+
+inline double walltime(){
+#ifdef HAVE_GETTIMEOFDAY
+
+    
+    struct              timeval currentWallTime;
+    double             msecTime;
+    
+    gettimeofday(&currentWallTime, NULL);
+    
+    //time with milliseconds
+    msecTime = ( currentWallTime.tv_sec*1000. + currentWallTime.tv_usec/1000. )/1000.0;
+    
+    // return time with milliseconds
+    return msecTime;
+
+    
+#else
+
+    // add for Pichon mars 2010 
+    time_t currentWallTime;
+    time(&currentWallTime);
+    return (double)currentWallTime;
+#endif
+}
+
+inline long fftime()
+{
+#ifdef HAVE_GETTIMEOFDAY
+    time_t tloc;
+    return time(&tloc);
+#endif
+    return -1;
+}
+
+long atoi(string* p) {return atoi(p->c_str());}// add march 2010
+double atof(string* p) {return atof(p->c_str());}// add march 2010
+double NaN(string* p) {
+return nan(p->c_str());}// add march 2012
+double NaN() {return nan("");}// add march 2012
+int ShowAlloc(const char *s,size_t & lg); 
+long ShowAlloc1(string *  s,long * np) { size_t lg; long  n= ShowAlloc(s->c_str(),lg); *np=lg; return n;}
+long ShowAlloc1(string *  s) { size_t lg; long  n= ShowAlloc(s->c_str(),lg); return n;}
+void Init_map_type()
+{
+   TheOperators=new Polymorphic(), 
+   TheRightOperators=new Polymorphic();
+  //  cout << sizeof(string) << endl;
+    map_type[typeid(AnyType).name()] = new ForTypeAnyType();
+    map_type[typeid(void).name()] = new ForTypeVoid();
+
+    Dcl_Type<Expression>(0);    
+    Dcl_TypeandPtr<double>(0,0,::InitializeDef<double>,0);
+    Dcl_TypeandPtr<long>(0,0,::InitializeDef<long>,0);
+    Dcl_TypeandPtr<bool>(0,0,::InitializeDef<bool>,0);
+    Dcl_TypeandPtr<Complex>(0,0,::InitializeDef<Complex>,0);
+    Dcl_Type<void*>(); // add FH ...  for mpi comm world
+    Dcl_Type<char*>();
+    Dcl_Type<const char *>();
+    Dcl_Type<char>();
+    Dcl_TypeandPtr<string*>(0,0,::InitializePtr<string*>,::DeletePtr<string*>);
+    Dcl_TypeandPtr<ostream*>(0,0,::InitializePtr<ostream*>,::DeletePtr<ostream*>);
+    Dcl_TypeandPtr<istream*>(0,0,::InitializePtr<istream*>,::DeletePtr<istream*>);
+    Dcl_Type< ostream_precis > ();
+    Dcl_Type< ostream_seekp > ();
+    Dcl_Type< istream_seekg > ();
+    Dcl_Type< istream_good > ();
+    Dcl_Type< NothingType > ();
+    
+    Dcl_Type<Polymorphic*>();
+    
+//    Dcl_Type<C_F0>();
+    basicForEachType::type_C_F0 = map_type[typeid(C_F0).name()] =  new TypeLineFunction;
+    Dcl_Type<E_Array>();
+    Dcl_Type<TransE_Array >();// add
+    Dcl_Type<const E_Border *>();
+    Dcl_Type<const E_BorderN *>();
+
+    
+    
+    Dcl_Type<SubArray>();
+    Dcl_Type<pair<long,long> >();
+    
+    initArrayDCLlong();
+    initArrayDCLdouble();
+    initArrayDCLComplex();
+        
+    Dcl_Type<ios::openmode>();
+    
+//  les types des variables 
+    
+  zzzfff->Add("real",typevarreal=atype<double*>());
+  zzzfff->Add("int",atype<long*>());
+  zzzfff->Add("complex",typevarcomplex=atype<Complex*>());
+  zzzfff->Add("bool",atype<bool*>());
+  zzzfff->Add("string",atype<string**>());
+  zzzfff->Add("ifstream",atype<istream**>());
+  zzzfff->Add("ofstream",atype<ostream**>());
+  zzzfff->AddF("func",atype<C_F0>());
+  
+  
+    
+//  end of know types
+
+     map_type[typeid(bool).name()]->AddCast(
+       new E_F1_funcT<bool,bool*>(UnRef<bool>),
+       new E_F1_funcT<bool,long>(Cast<bool,long>),
+       new E_F1_funcT<bool,double>(Cast<bool,double>)
+       );                                         
+                        
+
+     map_type[typeid(long).name()]->AddCast(
+       new E_F1_funcT<long,long*>(UnRef<long>),
+       new E_F1_funcT<long,double>(Cast<long,double>),
+       new E_F1_funcT<long,bool>(Cast<long,bool>),
+       new E_F1_funcT<long,ostream_precis>(Cast<long,ostream_precis>),
+       new E_F1_funcT<long,ostream_seekp>(Cast<long,ostream_seekp>),
+       new E_F1_funcT<long,istream_seekg>(Cast<long,istream_seekg>)
+       );
+       
+       
+     map_type[typeid(double).name()]->AddCast(
+       new E_F1_funcT<double,double*>(UnRef<double>),
+       new E_F1_funcT<double,long>(Cast<double,long>),
+       new E_F1_funcT<double,bool>(Cast<double,bool>)
+       
+       ); 
+                                               
+     map_type[typeid(Complex).name()]->AddCast(
+       new E_F1_funcT<Complex,Complex*>(UnRef<Complex>),
+       new E_F1_funcT<Complex,long>(Cast<Complex,long>),
+       new E_F1_funcT<Complex,double>(Cast<Complex,double>)
+       );                                         
+
+     map_type[typeid(string*).name()]->AddCast(
+       new E_F1_funcT<string*,string**>(UnRefCopyPtr<string>),
+       new E_F1_funcT<string*,long>(FCast<string*,long,toString>),
+       new E_F1_funcT<string*,double>(FCast<string*,double,toString>),
+       new E_F1_funcT<string*,bool>(FCast<string*,bool,toString>),
+       new E_F1_funcT<string*,Complex>(FCast<string*,Complex,toString>)
+        ); 
+     //   a changer ---------------  modif                                         
+        map_type[typeid(string*).name()]->AddCast(					       
+          new E_F1_funcT<string*,char *>(FCast<string*,char *,toStringC>),
+          new E_F1_funcT<string*,const char *>(FCast<string* ,const char *,toStringCconst>)
+       );
+       
+     map_type[typeid(long).name()]->AddCast(new OneOperator_border_label);
+      
+     Global.New("verbosity",CPValue<long>(verbosity));
+     Global.New("searchMethod",CPValue<long>(searchMethod)); //pichon
+     
+     Global.New("cout",CConstant<ostream*>(&cout));
+     Global.New("cerr",CConstant<ostream*>(&cerr));// add jan 2014 FH.
+     Global.New("cin",CConstant<istream*>(&cin));
+     Global.New("append",CConstant<ios::openmode>(ios::app));
+     Global.New("binary",CConstant<ios::openmode>(ios::binary)); // add FH april 2014
+     TheOperators->Add("|",new OneBinaryOperator<Op2_pipe<ios::openmode> >); // add FH april 2014
+     Global.New("endl",CConstant<const char*>("\n"));
+     Global.New("true",CConstant<bool>(true));
+     Global.New("false",CConstant<bool>(false));
+     Global.New("pi",CConstant<double>(3.14159265358979323846264338328));
+     Global.New("version",CConstant<double>(VersionNumber()));
+      
+     Global.New("CPUTime",CConstant<bool*>(&showCPU));
+     // def de Zero et One
+     pZero = new  C_F0(CConstant<double>(0.0));
+     pOne = new  C_F0(CConstant<double>(1.0));
+     pminusOne = new  C_F0(CConstant<double>(-1.0));
+     
+     TheOperators->Add(":",
+       new OneOperatorConst<char>(new EConstant<char>(':')),
+       new OneBinaryOperator<SubArray2>,
+       new OneTernaryOperator3<SubArray3>);
+     
+       
+     TheOperators->Add("+",
+       new OneBinaryOperator<Op2_add<long,long,long> >,
+       new OneBinaryOperator<Op2_add<double,double,double> >,
+       new OneBinaryOperator<Op2_add<double,double,long> >,
+       new OneBinaryOperator<Op2_add<double,long,double> >,
+       new OneBinaryOperator<Op2_add<long,bool,bool> >,       
+       new OneBinaryOperator<Op2_add<long,long,bool> >,       
+       new OneBinaryOperator<Op2_add<long,bool,long> >,       
+       new OneBinaryOperator<Op2_add<Complex,Complex,Complex> >,
+       new OneBinaryOperator<Op2_add<Complex,Complex,double> >,
+       new OneBinaryOperator<Op2_add<Complex,double,Complex> >,
+       new OneBinaryOperator<Op2_add<Complex,Complex,long> >,
+       new OneBinaryOperator<Op2_add<Complex,long,Complex> > ,      
+       new OneBinaryOperator_st<Op2_padd<string,string*,string*> >  // a changer to do FH string * mars 2006    
+       );
+     TheOperators->Add("-",
+       new OneBinaryOperator<Op2_sub<long,long,long> >,
+       new OneBinaryOperator<Op2_sub<double,double,double> >,
+       new OneBinaryOperator<Op2_sub<double,double,long> >,
+       new OneBinaryOperator<Op2_sub<double,long,double> >,
+       new OneBinaryOperator<Op2_sub<long,bool,bool> >,              
+       new OneBinaryOperator<Op2_sub<Complex,Complex,Complex> >,
+       new OneBinaryOperator<Op2_sub<Complex,Complex,double> >,
+       new OneBinaryOperator<Op2_sub<Complex,double,Complex> >,
+       new OneBinaryOperator<Op2_sub<Complex,Complex,long> >,
+       new OneBinaryOperator<Op2_sub<Complex,long,Complex> >       
+       );
+       
+     TheOperators->Add("*",
+       new OneBinaryOperator<Op2_mul<long,long,long>,OneBinaryOperatorMI,evalE_mul<long> >,
+       new OneBinaryOperator<Op2_mul<double,double,double>,MIMul<double,double>,evalE_mul<double> >,
+       new OneBinaryOperator<Op2_mul<double,double,long>, MIMul<double,long>,evalE_mul<double,long,double> >,
+       new OneBinaryOperator<Op2_mul<double,long,double>,MIMul<long,double>,evalE_mul<long,double,double>  >,
+       new OneBinaryOperator<Op2_mul<Complex,Complex,Complex> >,
+       new OneBinaryOperator<Op2_mul<Complex,Complex,double> >,
+       new OneBinaryOperator<Op2_mul<Complex,double,Complex> >,
+       new OneBinaryOperator<Op2_mul<Complex,Complex,long> >,
+       new OneBinaryOperator<Op2_mul<Complex,long,Complex> >       
+       );
+     TheOperators->Add("/",
+       new OneBinaryOperator<Op2_div<long,long,long> >,
+       new OneBinaryOperator<Op2_div<double,double,double> >,
+       new OneBinaryOperator<Op2_div<double,double,long> >,
+       new OneBinaryOperator<Op2_div<double,long,double> >,
+       new OneBinaryOperator<Op2_div<Complex,Complex,Complex> >,
+       new OneBinaryOperator<Op2_div<Complex,Complex,double> >,
+       new OneBinaryOperator<Op2_div<Complex,double,Complex> >,
+       new OneBinaryOperator<Op2_div<Complex,Complex,long> >,
+       new OneBinaryOperator<Op2_div<Complex,long,Complex> >       
+       );
+
+     TheOperators->Add("%",
+       new OneBinaryOperator<Op2_mod<long,long,long> >
+       );
+
+
+    TheOperators->Add("+",
+       new OneUnaryOperator<Op1_plus<double> >,
+       new OneUnaryOperator<Op1_plus<long> >,
+       new OneUnaryOperator<Op1_plus<Complex> >);
+     
+    TheOperators->Add("-",
+       new OneUnaryOperator<Op1_neg<double> >,
+       new OneUnaryOperator<Op1_neg<long> >,
+       new OneUnaryOperator<Op1_neg<Complex> >);
+              
+     TheOperators->Add("^",
+		       new OneBinaryOperator<Op2_pow<long,long,long> >,
+    //   new OneBinaryOperator<Op2_pow<double,long,double> >,
+		       new OneBinaryOperator<Op2_pow<double,double,double> >,
+		       new OneBinaryOperator<Op2_pow<double,double,long> >,
+    //   new OneBinaryOperator<Op2_pow<Complex,Complex,double> >,
+    //  new OneBinaryOperator<Op2_pow<Complex,double,Complex> >,
+		       new OneBinaryOperator<Op2_pow<Complex,Complex,Complex> >
+     );
+     
+     TheOperators->Add("<",
+       new OneBinaryOperator<Op2_lt<long,long> >,
+       new OneBinaryOperator<Op2_lt<double,double> >,
+       new OneBinaryOperator<Op2_plt<string*,string*> >  //  FH string * mars 2006 
+     );
+     TheOperators->Add("<=",
+       new OneBinaryOperator<Op2_le<long,long> >,
+       new OneBinaryOperator<Op2_le<double,double> >,
+       new OneBinaryOperator<Op2_ple<string*,string*> >  //  FH string * mars 2006 
+     );
+     TheOperators->Add(">",
+       new OneBinaryOperator<Op2_gt<long,long> >,
+       new OneBinaryOperator<Op2_gt<double,double> >,
+       new OneBinaryOperator<Op2_pgt<string*,string*> >  //  string * mars 2006 
+     );
+     TheOperators->Add(">=",
+       new OneBinaryOperator<Op2_ge<long,long> >,
+       new OneBinaryOperator<Op2_ge<double,double> >,
+       new OneBinaryOperator<Op2_pge<string*,string*> >  //  FH string * mars 2006 
+     );
+     TheOperators->Add("==",
+       new OneBinaryOperator<Op2_eq<long,long> >,
+       new OneBinaryOperator<Op2_eq<double,double> >,
+       new OneBinaryOperator<Op2_eq<Complex,Complex> >,
+       new OneBinaryOperator<Op2_peq<string*,string*> >  //   FH string * mars 2006 
+     );
+
+     TheOperators->Add("!=",
+       new OneBinaryOperator<Op2_ne<long,long> >,
+       new OneBinaryOperator<Op2_ne<double,double> >,
+       new OneBinaryOperator<Op2_ne<Complex,Complex> >,
+       new OneBinaryOperator<Op2_pne<string*,string*> >  //  FH string * mars 2006 
+     );
+     
+     TheOperators->Add("!",
+       new OneUnaryOperator<Op1_not<bool > >
+     );
+     
+     TheOperators->Add("&&", new OneBinaryOperator<Op2_and > );
+     TheOperators->Add("&", new OneBinaryOperator<Op2_and > );
+     TheOperators->Add("||", new OneBinaryOperator<Op2_or> );
+     TheOperators->Add("|", new OneBinaryOperator<Op2_or> );
+       
+      // Unary_Op_Comparaision
+     
+     TheOperators->Add("=",
+       new OneBinaryOperator<set_eq<bool> ,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq<long> ,OneBinaryOperatorMIWO>,
+       new OneBinaryOperator<set_eq<double> ,OneBinaryOperatorMIWO>,
+       new OneBinaryOperator<set_eq<Complex> ,OneBinaryOperatorMIWO>,
+       new OneBinaryOperator<set_peq<string> ,OneBinaryOperatorMIWO>  // FH string * mars 2006 
+       ); 
+
+     TheOperators->Add("?:",
+       new Operator_Aritm_If<bool >,
+       new Operator_Aritm_If<long >,
+       new Operator_Aritm_If<double >,
+       new Operator_Aritm_If<Complex >,
+       new Operator_Aritm_If<string* >  // (OK???)  to do FH string * mars 2006 
+       ); 
+       
+/*
+     ArrayOperator<double>();
+     ArrayOperator<Complex>();
+     ArrayOperator<long>();
+*/
+//      initArrayOperators()   ;  
+     initArrayOperatorlong();
+     initArrayOperatordouble();
+     initArrayOperatorComplex();
+     initStringOperator();
+
+
+     TheOperators->Add("+=",
+       new OneBinaryOperator<set_eq_add<long>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq_add<double>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq_add<Complex>,OneBinaryOperatorMIWO >
+      );
+
+
+     TheOperators->Add("-=",
+       new OneBinaryOperator<set_eq_sub<long>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq_sub<double>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq_sub<Complex>,OneBinaryOperatorMIWO >
+      );
+
+
+
+     TheOperators->Add("*=",
+       new OneBinaryOperator<set_eq_mul<long> ,OneBinaryOperatorMIWO>,
+       new OneBinaryOperator<set_eq_mul<double>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq_mul<Complex>,OneBinaryOperatorMIWO >     
+      );
+
+
+     TheOperators->Add("/=",
+       new OneBinaryOperator<set_eq_div<long>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq_div<double>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<set_eq_div<Complex>,OneBinaryOperatorMIWO >     
+     );
+
+     TheOperators->Add("+",
+    //   new OneBinaryOperator<Op2_addp<const E_BorderN *,const E_BorderN *,const E_BorderN * > >,  
+       new AddBorderOperator
+       );
+
+      // add frev 2007
+      TheOperators->Add("\'", new opTrans); 
+      
+     // TheOperators->Add("\'", new opTTrans); 
+      TheOperators->Add("*",new opDot(atype<TransE_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("*",new opDot(atype<E_Array >(),atype<E_Array>() )   );  // a faire mais dur
+      TheOperators->Add("*",new opColumn(atype<E_Array >() )   );  //  [ ]* C_F0 (all)
+      TheOperators->Add("*",new opColumn(basicForEachType::type_C_F0,atype<E_Array >() )   );  //  [ ]* C_F0 (all)
+      TheOperators->Add("*",new opColumn(basicForEachType::type_C_F0,atype<TransE_Array >() )   );  //  [ ]* C_F0 (all)
+//    type_C_F0
+      TheOperators->Add("::",new opColumn(atype<E_Array >(),atype<E_Array>() )   );  // a faire mais dur
+      TheOperators->Add("*",new opDot(atype<E_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("*",new opDot(atype<TransE_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+ 
+     // car le type de retour depent des objets du tableau
+      atype<E_Array >()->Add("[","",new opVI(atype<E_Array >())   );  
+      atype<TransE_Array >()->Add("[","",new opVI(atype<TransE_Array >())   );  
+      TheOperators->Add("+",new opSum("+",atype<TransE_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("+",new opSum("+",atype<E_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("+",new opSum("+",atype<E_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("+",new opSum("+",atype<TransE_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("-",new opSum("-",atype<TransE_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("-",new opSum("-",atype<E_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("-",new opSum("-",atype<E_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("-",new opSum("-",atype<TransE_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+      TheOperators->Add(".*",new opSum("*",atype<TransE_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add(".*",new opSum("*",atype<E_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add(".*",new opSum("*",atype<E_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+      TheOperators->Add(".*",new opSum("*",atype<TransE_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("./",new opSum("/",atype<TransE_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("./",new opSum("/",atype<E_Array >(),atype<E_Array>() )   );  // a faire mais dur 
+      TheOperators->Add("./",new opSum("/",atype<E_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+    // correct in sept. 2009
+      TheOperators->Add("./",new opSum("/",atype<TransE_Array >(),atype<TransE_Array>() )   );  // a faire mais dur 
+    
+      
+     // il faut refechir  .....  FH 
+     // il faut definir le type d'un tableau bof, bof (atype<C_F0>())
+     TheOperators->Add(">>",
+       new OneBinaryOperator<Op_Read<bool>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<Op_Read<long>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<Op_Read<double>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<Op_Read<Complex>,OneBinaryOperatorMIWO >,
+       new OneBinaryOperator<Op_ReadP<string>,OneBinaryOperatorMIWO >
+		       
+       );
+     
+     TheOperators->Add("<<",
+       new OneBinaryOperator<Print<bool> >,
+       new OneBinaryOperator<Print<long> >,
+       new OneBinaryOperator<Print<double> >,
+       new OneBinaryOperator<Print<Complex> >,
+       new OneBinaryOperator<PrintP<string*> >  //  FH string * mars 2006 
+       );
+
+     
+     TheRightOperators->Add("++",       
+       new OneOperator1<long,long*, E_F_F0<long,long*,false> >(&RIncremantation<long>));
+     TheRightOperators->Add("--",       
+       new OneOperator1<long,long*, E_F_F0<long,long*,false> >(&RDecremantation<long>));
+     TheOperators->Add("++",       
+       new OneOperator1<long,long*, E_F_F0<long,long*,false> >(&LIncremantation<long>));
+     TheOperators->Add("--",       
+       new OneOperator1<long,long*, E_F_F0<long,long*,false> >(&LDecremantation<long>));
+//   init        
+     TheOperators->Add("<-", 
+       new OneOperator2<string**,string**,string*>(&set_copyp_new<string>),  //  FH string * mars 2006 
+       new OneOperator2_<double*,double*,double>(&set_copyp),  // 
+       new OneOperator2_<long*,long*,long>(&set_copyp),
+       new OneOperator2_<bool*,bool*,bool>(&set_copyp), //  mars 2006
+       new OneOperator2_<Complex*,Complex*,Complex>(&set_copy),
+  //     new OneOperator2_<istream**,istream**,istream*>(&set_copy_new<istream>),
+   //    new OneOperator2_<ostream**,ostream**,ostream*>(&set_copy_new<ostream>),
+//       new OneUnaryOperator<Op1_new_pstring<istream*,ifstream> >,
+//       new OneUnaryOperator<Op1_new_pstring<ostream*,ofstream> >,
+       new OneBinaryOperator<Op2_set_pstring<istream**,ifstream> >,  //  FH string * mars 2006 
+       new OneBinaryOperator<Op2_set_pstring<ostream**,ofstream> >,  //  FH string * mars 2006 
+       new OneTernaryOperator3<Op2_set_pstringiomode<ostream**,ofstream> >  ,    //  FH string * mars 2006
+       new OneTernaryOperator3<Op2_set_pstringiomode<istream**,ifstream> >   //  FH string * april  2014
+       );
+       
+     atype<istream* >()->AddCast( new E_F1_funcT<istream*,istream**>(UnRef<istream* >)); 
+     atype<ostream* >()->AddCast( new E_F1_funcT<ostream*,ostream**>(UnRef<ostream* >)); 
+   
+//     Add<istream**>("<-","(", new OneUnaryOperator<Op1_new_pstring<istream*,ifstream> >);
+     Add<ostream**>("<-","(", new OneUnaryOperator<Op1_new_pstring<ostream*,ofstream> >);  //  FH string * mars 2006 
+     
+    // Polymorphic * precis =new Polymorphic();
+    //  Add<ostream*>("precision",".",precis);
+     Add<ostream**>("precision",".",new OneOperator1<ostream_precis,ostream**>(ostream_precision));
+     Add<ostream*>("precision",".",new OneOperator1<ostream_precis,ostream*>(ostream_precision));
+    
+    // add FH jan 2010 ...
+    Add<ostream**>("seekp",".",new OneOperator1<ostream_seekp,ostream**>(ff_oseekp));
+    Add<ostream*>("seekp",".",new OneOperator1<ostream_seekp,ostream*>(ff_oseekp));
+    
+    Add<istream**>("seekg",".",new OneOperator1<istream_seekg,istream**>(ff_iseekg));
+    Add<istream*>("seekg",".",new OneOperator1<istream_seekg,istream*>(ff_iseekg));
+    Add<ostream**>("tellp",".",new OneOperator1<ostream_seekp,ostream**>(ff_oseekp));
+    Add<ostream*>("tellp",".",new OneOperator1<ostream_seekp,ostream*>(ff_oseekp));
+    
+    Add<istream**>("tellg",".",new OneOperator1<istream_seekg,istream**>(ff_iseekg));
+    Add<istream*>("tellg",".",new OneOperator1<istream_seekg,istream*>(ff_iseekg));
+    
+ //   Add<istream_seekp>("(","",new OneOperator1<long,istream_seekp>(fftellp),
+//			new OneOperator2<long,istream_seekp,long>(ffseekp));    
+    Add<ostream_seekp>("(","",new OneOperator1<long,ostream_seekp>(fftellp),
+		       new OneOperator2<long,ostream_seekp,long>(ffseekp));
+    Add<istream_seekg>("(","",new OneOperator1<long,istream_seekg>(fftellg),
+		       new OneOperator2<long,istream_seekg,long>(ffseekg));
+    // end add  jan 2010 .. 
+    Add<ostream_precis>("(","",new OneOperator1<long,ostream_precis>(get_precis),
+                                new OneOperator2<long,ostream_precis,long>(set_precis));
+//  add v 1.41   
+     Add<istream**>("good",".",new OneOperator1<istream_good,istream**>(to_istream_good));
+     Add<istream*>("good",".",new OneOperator1<istream_good,istream*>(to_istream_good));
+     Add<istream*>("good",".",new OneOperator1<istream_good,istream*>(to_istream_good));    
+     Add<istream_good>("(","",new OneOperator1<long,istream_good>(get_good));
+
+     Add<istream**>("eof",".",new OneOperator1<bool,istream**>(get_eof));
+// add v 2.8 
+     Add<ostream**>("scientific",".",new OneOperator1<ostream**,ostream**>(set_os<scientific>));
+     Add<ostream**>("fixed",".",new OneOperator1<ostream**,ostream**>(set_os<fixed>));
+     Add<ostream**>("showbase",".",new OneOperator1<ostream**,ostream**>(set_os<showbase>));
+     Add<ostream**>("noshowbase",".",new OneOperator1<ostream**,ostream**>(set_os<noshowbase>));
+     Add<ostream**>("showpos",".",new OneOperator1<ostream**,ostream**>(set_os<showpos>));
+     Add<ostream**>("noshowpos",".",new OneOperator1<ostream**,ostream**>(set_os<noshowpos>));
+     Add<ostream**>("default",".",new OneOperator1<ostream**,ostream**>(set_os<default1>));
+     Add<ostream**>("flush",".",new OneOperator1<ostream**,ostream**>(set_os_flush));// ADD may 2010
+     
+     Add<ostream*>("scientific",".",new OneOperator1<ostream*,ostream*>(set_os1<scientific>));
+     Add<ostream*>("fixed",".",new OneOperator1<ostream*,ostream*>(set_os1<fixed>));
+     Add<ostream*>("showbase",".",new OneOperator1<ostream*,ostream*>(set_os1<showbase>));
+     Add<ostream*>("noshowbase",".",new OneOperator1<ostream*,ostream*>(set_os1<noshowbase>));
+     Add<ostream*>("showpos",".",new OneOperator1<ostream*,ostream*>(set_os1<showpos>));
+     Add<ostream*>("noshowpos",".",new OneOperator1<ostream*,ostream*>(set_os1<noshowpos>));
+     Add<ostream*>("default",".",new OneOperator1<ostream*,ostream*>(set_os1<default1>));
+     Add<ostream*>("flush",".",new OneOperator1<ostream*,ostream*>(set_os_flush));// ADD may 2010
+     
+    Global.Add("getline","(",new OneOperator2<istream*,istream*,string **>(Getline));
+// add 2.16
+     Global.Add("trace","(",new opFormal(atype<E_Array>(),formalMatTrace ));
+     Global.Add("det","(",new opFormal(atype<E_Array>(),formalMatDet ));
+// end add
+                                
+    // add 3.20
+    Global.Add("Cofactor","(",new opFormal(atype<E_Array>(),formalMatCofactor ));
+      
+     TheOperators->Add("[]",new OneOperator_array );
+     TheOperators->Add("[border]",new OneOperator_border );
+     
+      
+     Global.Add("cos","(",new OneOperator1<double>(cos));
+//     Global.Add("square","(",new OneOperator1_<double>(Square));
+    Global.Add("square","(",new OneOperator1<long,long,E_F_F0<long,const long &> >(Square));// add FH Mai 2011
+    Global.Add("square","(",new OneOperator1<double,double,E_F_F0<double,const double &> >(Square));
+    Global.Add("square","(",new OneOperator1<Complex,Complex,E_F_F0<Complex,const Complex &> >(Square));// add FH Mai 2011
+ //add for Olivier FH July 2014
+    Global.Add("sqr","(",new OneOperator1<long,long,E_F_F0<long,const long &> >(Square));//
+    Global.Add("sqr","(",new OneOperator1<double,double,E_F_F0<double,const double &> >(Square));
+    Global.Add("sqr","(",new OneOperator1<Complex,Complex,E_F_F0<Complex,const Complex &> >(Square));//
+
+     Global.Add("round","(",new OneOperator1<double>(round)); // add june 2007
+     Global.Add("lround","(",new OneOperator1<long,double>(lround)); // add june 2007
+     Global.Add("floor","(",new OneOperator1<double>(floor)); // add march 2006
+     Global.Add("ceil","(",new OneOperator1<double>(ceil));  // add march 2006
+     Global.Add("rint","(",new OneOperator1<double>(rint));  // add june 2006
+     Global.Add("lrint","(",new OneOperator1<long,double>(lrint));  // add mars  2014
+    
+     Global.Add("sin","(",new OneOperator1<double>(sin));
+     Global.Add("tan","(",new OneOperator1<double>(tan));
+     Global.Add("atan","(",new OneOperator1<double>(atan));
+     Global.Add("sinh","(",new OneOperator1<double>(sinh));
+     Global.Add("cosh","(",new OneOperator1<double>(cosh));
+     Global.Add("tanh","(",new OneOperator1<double>(tanh));
+
+    Global.Add("atoi","(",new OneOperator1<long,string*>(atoi));// add march 2010
+    Global.Add("atof","(",new OneOperator1<double,string*>(atof));// add march 2010
+    
+#ifdef HAVE_ATANH
+     Global.Add("atanh","(",new OneOperator1<double>(atanh));
+#endif
+     Global.Add("asin","(",new OneOperator1<double>(asin));
+     Global.Add("acos","(",new OneOperator1<double>(acos));
+#ifdef HAVE_ASINH
+     Global.Add("asinh","(",new OneOperator1<double>(asinh));
+#endif
+#ifdef HAVE_ACOSH
+     Global.Add("acosh","(",new OneOperator1<double>(acosh));
+#endif
+#ifdef HAVE_ERFC
+     Global.Add("erf","(",new OneOperator1<double>(erf));
+     Global.Add("erfc","(",new OneOperator1<double>(erfc));
+#endif
+#ifdef HAVE_TGAMMA
+     Global.Add("tgamma","(",new OneOperator1<double>(tgamma));
+     Global.Add("lgamma","(",new OneOperator1<double>(lgamma));
+#endif
+     //  function de bessel j0, j1, jn, y0, y1, yn -- bessel functions of first and second kind     
+#ifdef HAVE_JN
+      Global.Add("j0","(",new OneOperator1<double>(j0));
+      Global.Add("j1","(",new OneOperator1<double>(j1));
+      Global.Add("jn","(",new OneOperator2<double,long,double>(myjn));
+      Global.Add("y0","(",new OneOperator1<double>(y0));
+      Global.Add("y1","(",new OneOperator1<double>(y1));
+      Global.Add("yn","(",new OneOperator2<double,long,double>(myyn));      
+#endif
+     Global.Add("exp","(",new OneOperator1<double>(exp));
+     Global.Add("log","(",new OneOperator1<double>(log));
+     Global.Add("log10","(",new OneOperator1<double>(log10));
+     Global.Add("pow","(",new OneOperator2<double,double>(pow));
+//     Global.Add("pow","(",new OneOperator2<double,double,long>(pow));
+     Global.Add("max","(",new OneOperator2_<double,double>(Max<double> ));
+     Global.Add("min","(",new OneOperator2_<double,double>(Min<double> ));
+     Global.Add("max","(",new OneOperator2_<long,long>(Max));
+     Global.Add("min","(",new OneOperator2_<long,long>(Min));
+     Global.Add("atan2","(",new OneOperator2<double>(atan2));
+     Global.Add("hypot","(",new OneOperator2<double>(hypot));// add Jan 2014
+    
+     Global.Add("atan","(",new OneOperator2<double>(atan2));
+     Global.Add("sqrt","(",new OneOperator1<double>(sqrt,2));
+     Global.Add("abs","(",new OneOperator1<double>(Abs));
+     Global.Add("abs","(",new OneOperator1<long>(Abs));
+     Global.Add("cos","(",new OneOperator1_<Complex>(cos));
+     Global.Add("sin","(",new OneOperator1_<Complex>(sin));
+     Global.Add("sinh","(",new OneOperator1_<Complex>(sinh));
+     Global.Add("cosh","(",new OneOperator1_<Complex>(cosh));
+     Global.Add("log","(",new OneOperator1_<Complex>(log));
+     //     Global.Add("log10","(",new OneOperator1_<Complex>(log10));
+     Global.Add("tan","(",new OneOperator1_<Complex>(tan));
+     Global.Add("exp","(",new OneOperator1_<Complex>(exp));
+     //Complex (* powcc  )( const  Complex &, const Complex &) =pow;
+    
+    Global.Add("pow","(",new OneBinaryOperator<Op2_pow<Complex,Complex,Complex> >);
+                //new OneOperator2_<Complex,Complex>(pow ));
+     Global.Add("sqrt","(",new OneOperator1_<Complex>(sqrt,0));
+     Global.Add("conj","(",new OneOperator1_<Complex>(conj,0));
+     Global.Add("conj","(",new OneOperator1_<double>(RNM::conj,1));
+     TheOperators->Add("\'",new OneOperator1_<Complex>(conj,0));       
+     TheOperators->Add("\'",new OneOperator1_<double>(RNM::conj,1));       //  add F.  Feb 2010  of conj of varf.. 
+     
+     
+     Global.Add("imag","(",new OneOperator1_<double,Complex>(Imag));
+     //  Big probleme  real is a type
+     Add<double>("<--","(",new OneOperator1_<double,Complex>(Real));
+    // Global.Add("real","(",new OneOperator1_<double,Complex>(Real));
+    // Add<double>(typevarreal->right()->name(),".",new OneOperator1_<double,Complex>(Real));
+    // Global.Add(typevarreal->right()->name(),".",new OneOperator1_<double,Complex>(Real));
+    // Add<double*>(typevarreal->left()->name(),".",new OneOperator1_<double,Complex*>(preal));
+    
+     Global.Add("abs","(",new OneOperator1_<double,Complex>(abs));
+
+     Global.Add("arg","(",new OneOperator1_<double,Complex>(arg));
+     Global.Add("norm","(",new OneOperator1_<double,Complex>(norm));
+     Global.Add("exit","(",new OneOperator1<long>(Exit));     
+     Global.Add("assert","(",new OneOperator1<bool>(Assert));     
+     
+     Global.Add("clock","(",new OneOperator0<double>(CPUtime));
+    Global.Add("time","(",new OneOperator0<double>(walltime));// add mars 2010 for Pichon.
+    Global.Add("ltime","(",new OneOperator0<long>(fftime));// add mars 2014 ( the times unix fonction)
+    Global.Add("storageused","(",new OneOperator0<long>(storageused));
+    Global.Add("storagetotal","(",new OneOperator0<long>(storagetotal));
+    
+     Global.Add("dumptable","(",new OneOperator1<ostream*,ostream*>(dumptable));
+     Global.Add("exec","(",new OneOperator1<long,string* >(exec));  //FH string * mars 2006 
+     Global.Add("system","(",new OneOperator1<long,string* >(exec));  //FH string fevr 2011 
+    
+     Global.Add("polar","(",new OneOperator2_<Complex,double,double>(polar));
+ // rand generator ---
+  unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4;                                                            
+  init_by_array(init, length);
+  extern long genrand_int31(void);   
+  extern double genrand_real1(void);
+  extern double genrand_real2(void);
+  extern double genrand_real3(void);
+  extern double  genrand_res53(void) ;
+  
+  Global.Add("randint32","(",new OneOperator_0<long>(genrandint32));
+  Global.Add("randint31","(",new OneOperator_0<long>(genrand_int31));
+  Global.Add("randreal1","(",new OneOperator_0<double>(genrand_real1));
+  Global.Add("randreal2","(",new OneOperator_0<double>(genrand_real2));
+  Global.Add("randreal3","(",new OneOperator_0<double>(genrand_real3));
+  Global.Add("randres53","(",new OneOperator_0<double>(genrand_res53));
+  Global.Add("randinit","(",new OneOperator1<long>(genrandint));
+  
+   //  NaN and Inf 
+  Global.Add("ShowAlloc","(",new OneOperator1<long,string*>(ShowAlloc1));// debuging 
+  Global.Add("ShowAlloc","(",new OneOperator2<long,string*,long*>(ShowAlloc1));// debuging 
+  Global.Add("NaN","(",new OneOperator0<double>(NaN));
+  Global.Add("NaN","(",new OneOperator1<double,string*   >(NaN));
+    Global.Add("isNaN","(",new OneOperator1<long,double>(isNaN));
+    Global.Add("isInf","(",new OneOperator1<long,double>(isInf));
+    Global.Add("isNormal","(",new OneOperator1<long,double>(isNormal));
+ 
+  
+
+typedef MyMap<String,String> MyMapSS;
+    
+     map_type[typeid(MyMapSS*).name()] = new ForEachType<MyMapSS*>(Initialize<MyMapSS >,Delete<MyMapSS >) ; 
+//Dcl_TypeandPtr_<KN_<string*> ,KN<string*>*  > (0,0,0,::Destroy<KN<K> >, ::ClearReturnKK_<K,KN<K>,KN_<K> >,::ClearReturnpKK<K,KN<K> >);
+    
+  //  map_type[typeid(KN2String*).name()] = new ForEachType<MyMapIS*>(Initialize<KN2String >,Delete<MyMapIS >) ;         
+     map_type_of_map[make_pair(atype<string*>(),atype<string*>())]=atype<MyMapSS*>();      
+     atype<MyMapSS*>()->Add("[","",new OneOperator2_<string**,MyMapSS*,string*>(get_elements));
+
+    
+          
+     tables_of_identifier.push_back(&Global);
+  
+
+}
+//int ShowAlloc(const char *s,size_t & lg); 
+
+
+
+
+ void ClearMem()
+ {
+     size_t lg;
+     ShowAlloc("ClearMem: begin" , lg);
+     delete pZero;
+     delete pOne;
+     delete pminusOne;
+      
+     tables_of_identifier.clear();
+     for (map<const string,basicForEachType *>::iterator i=map_type.begin();i!=map_type.end();++i)
+        delete i->second;
+        
+     map_type.clear();
+     map_type_of_map.clear();
+     map_pair_of_type.clear();
+     Global.clear();
+     if(TheOperators) 
+       TheOperators->clear();
+     if(TheRightOperators)
+       TheRightOperators->clear();
+        
+     CodeAlloc::clear();
+     ShowAlloc("ClearMem: end" , lg); 
+
+ } 
+static addingInitFunct TheaddingInitFunct(-10000,Init_map_type); 
+
+C_F0  opVI::code2(const basicAC_F0 &args) const      
+{
+    Expression p=args[1];
+    if ( ! p->EvaluableWithOutStack() ) 
+    { 
+	bool bb=p->EvaluableWithOutStack();
+	//cout << bb << " " <<  * p <<  endl;
+	CompileError(" [...][p], The p must be a constant , sorry");}
+        long pv = GetAny<long>((*p)(NullStack));
+    bool ta =args[0].left()==atype<TransE_Array>();
+    const TransE_Array * tea=0;
+    const E_Array * ea=0;
+	if( ta)  tea = dynamic_cast<const TransE_Array*>((Expression) args[0]);
+    else ea = dynamic_cast<const E_Array*>((Expression) args[0]);
+    assert( ea || tea );
+    const E_Array & a=  ta ? *tea->v : *ea;
+   // cout << " pv =" << pv << " size = "<< a.size() << endl;
+    if(!(pv >=0 && pv <a.size()))
+    {
+      cerr << "\n\nerror [ ... ][" << pv <<" ] " << " the  size of [ ...]  is "<< a.size() << endl;
+      lgerror(" bound of  [ .., .. , ..][ . ] operation  ");
+    }
+    
+    //ffassert(pv >=0 && pv <a.size());
+    return (* a.v)[pv];
+}
+
+C_F0  opDot::code2(const basicAC_F0 &args) const      
+{
+    bool ta =args[0].left()==atype<TransE_Array>();
+    bool tb = args[1].left()==atype<TransE_Array>();
+    const TransE_Array * tea=0;
+    const TransE_Array * teb=0;
+    const E_Array * ea=0;
+    const E_Array * eb=0;// E_F0
+	if( ta)  tea = dynamic_cast<const TransE_Array*>((Expression) args[0]);
+    else ea = dynamic_cast<const E_Array*>((Expression) args[0]);
+    if( tb)  teb = dynamic_cast<const TransE_Array*>((Expression) args[1]);
+    else eb = dynamic_cast<const E_Array*>((Expression) args[1]);
+    assert( ea || tea );
+    assert( eb || teb );
+    const E_Array & a=  ta ? *tea->v : *ea;
+    const E_Array & b=  tb ? *teb->v : *eb;
+    int ma =1;
+    int mb =1;
+    int na=a.size();
+    int nb=b.size();
+    if(na <1 && nb < 1) CompileError(" empty array  [ ...]'*[ ...  ]  ");
+    bool mab= b[0].left()==atype<E_Array>();
+    bool maa= a[0].left()==atype<E_Array>();
+    if(maa) {
+	ma= a[0].LeftValue()->nbitem();
+	for (int i=1;i<na;i++)
+	    if( ma != (int) a[i].LeftValue()->nbitem()) 
+		CompileError(" first matrix with variable number of columm");
+        
+    }
+    if(mab) {
+	mb= b[1].LeftValue()->nbitem();
+	for (int i=1;i<nb;i++)
+	    if( mb != (int) b[i].LeftValue()->nbitem()) 
+		CompileError(" second matrix with variable number of columm");
+    }
+    int na1=na,ma1=ma,nb1=nb,mb1=mb;
+    if(ta) RNM::Exchange(na1,ma1);
+    if(tb) RNM::Exchange(nb1,mb1);
+    
+    KNM<CC_F0> A(na1,ma1), B(nb1,mb1);
+    if ( A.M() != B.N())
+    {
+	cout << "   formal prod array or matrix : [ .. ] * [ .. ]   " << endl;
+	cout << " first  array :  matrix " << maa << " trans " << ta << " " << na << "x" << ma <<endl;
+	cout << " second array :  matrix " << mab << " trans " << tb << " " << nb << "x" << mb <<endl;	
+	CompileError(" no same size  [ ...]'*[ ...  ] sorry ");
+    }
+    
+    if(maa)
+	for (int i=0;i<na;++i)
+	{
+	    const E_Array * li=  dynamic_cast<const E_Array *>(a[i].LeftValue());
+	    ffassert(li);
+	    for (int j=0; j<ma;++j)
+		if(!ta)  A(i,j) = (*li)[j];
+		else     A(j,i) = TryConj((*li)[j]);
+	} 
+    else
+	for (int i=0;i<na;++i)
+	    if(!ta)  A(i,0) = a[i];
+	    else     A(0,i) = TryConj(a[i]);
+	 
+    if(mab)
+	for (int i=0;i<nb;++i)
+	{
+	    const E_Array * li=  dynamic_cast<const E_Array *>(b[i].LeftValue());
+	    ffassert(li);
+	    for (int j=0; j<mb;++j)
+		if(!tb)  B(i,j) = (*li)[j];
+		else     B(j,i) = TryConj((*li)[j]);
+	} 
+    else
+	for (int i=0;i<nb;++i)
+	    if(!tb)  B(i,0) = b[i];
+	    else     B(0,i) = TryConj(b[i]);
+    
+    KNM<CC_F0> C(na1,mb1);
+    CC_F0 s,abi;
+    for (int i=0;i<na1;++i)
+	for (int j=0;j<mb1;++j)
+	{
+	    s= C_F0(TheOperators,"*",A(i,0),B(0,j));
+	    for (int k=1;k<ma1;++k) {
+		abi = C_F0(TheOperators,"*",A(i,k),B(k,j));
+		s = C_F0(TheOperators,"+",s,abi);}
+	    C(i,j)=s;
+	};
+   // cout << "\n ***na1 nb1 == = "<< na1 << " " << nb1 << endl;
+    if( na1==1 && mb1 ==1)
+	return C(0,0);
+    else if ( mb1 ==1 ) // || (na1==1)) // correct du car ' on conj encore r . mars 2010 
+    {
+	AC_F0  v;
+	v=C(0,0);
+	int i0=na1!=1,j0=mb1!=1, nn= mb1*na1;
+	for (int i=1;i<nn;++i)
+	    v+=C(i0*i,j0*i);
+	C_F0  r(TheOperators,"[]",v);
+	if(mb1==1) return r;                                                                                                                                                                                         
+	else return C_F0(TheOperators,"\'",r);// Bug car on conj encore r . mars 2010 
+    }
+    else
+    {
+	AC_F0  v,cc;
+	v=C(0,0);
+	for (int i=0;i<na1;++i)	
+	{  cc = C(i,0);
+	    for (int j=1;j<mb1;++j)
+		cc+= C(i,j);
+	    C_F0  vi(TheOperators,"[]",cc);
+	    if(i==0) v=vi;
+	    else v+= vi;
+	}
+	return C_F0(TheOperators,"[]",v);
+    }
+/*	  
+    if ( !mab && ! maa)
+    {
+	
+	if( na != nb)
+	    CompileError(" no same size  [ ...]'*[ ...  ] sorry ");
+	
+	if( ta && ! tb)
+	{
+	    s= C_F0(TheOperators,"*",a[0],b[0]);
+	    for (int i=1;i<na;++i)
+	    {
+		abi = C_F0(TheOperators,"*",a[i],b[i]);
+		s = C_F0(TheOperators,"+",s,abi);
+	    }
+	    return s;//Type_Expr(s); //new C_F0(s);   ATTENTION le type est variable ici   FH
+	}
+	
+	if(!ma && mb)
+	{  
+	}
+	
+    }*/
+    
+    cout << "   formal prod array or matrix : [ .. ] * [ .. ]   " << na << "x" << nb << endl;
+    cout << "   formal prod array or matrix : [ .. ] * [ .. ]   " <<  endl;
+    cout << " first  array :  matrix " << maa << " trans " << ta << " " << na << "x" << ma <<endl;
+    cout << " second array :  matrix " << mab << " trans " << tb << " " << nb << "x" << mb <<endl;
+    CompileError("  not implemented sorry ..... (FH) to do ???? ");	
+    return C_F0();
+
+}
+C_F0  opColumn::code2(const basicAC_F0 &args) const
+{
+    bool ta =args[0].left()==atype<TransE_Array>();
+    bool tb = args[1].left()==atype<TransE_Array>();
+    const TransE_Array * tea=0;
+    const TransE_Array * teb=0;
+    const E_Array * ea=0;
+    const E_Array * eb=0;// E_F0
+    if( ta)  tea = dynamic_cast<const TransE_Array*>((Expression) args[0]);
+    else ea = dynamic_cast<const E_Array*>((Expression) args[0]);
+    if( tb)  teb = dynamic_cast<const TransE_Array*>((Expression) args[1]);
+    else eb = dynamic_cast<const E_Array*>((Expression) args[1]);
+    
+    // ffassert( ea || tea );
+    
+    if( (eb || teb) && ( ea || tea ) )
+    {
+        const E_Array & a=  ta ? *tea->v : *ea;
+        const E_Array & b=  tb ? *teb->v : *eb;
+        int ma =1;
+        int mb =1;
+        int na=a.size();
+        int nb=b.size();
+        if(na <1 && nb < 1) CompileError(" empty array  [ ...]':[ ...  ]  ");
+        bool mab= b[0].left()==atype<E_Array>();
+        bool maa= a[0].left()==atype<E_Array>();
+        if(maa) {
+            ma= a[0].LeftValue()->nbitem();
+            for (int i=1;i<na;i++)
+                if( ma != (int) a[i].LeftValue()->nbitem())
+                    CompileError(" first matrix with variable number of columm");
+            
+        }
+        if(mab) {
+            mb= b[1].LeftValue()->nbitem();
+            for (int i=1;i<nb;i++)
+                if( mb != (int) b[i].LeftValue()->nbitem())
+                    CompileError(" second matrix with variable number of columm");
+        }
+        int na1=na,ma1=ma,nb1=nb,mb1=mb;
+        if(ta) RNM::Exchange(na1,ma1);
+        if(tb) RNM::Exchange(nb1,mb1);
+        
+        KNM<CC_F0> A(na1,ma1), B(nb1,mb1);
+        if ( (na1!=nb1 ) || (ma1 != mb1) || (na1 * ma1 ==0)  )
+        {
+            cout << "\n   formal  array or matrix : [ .. ] : [ .. ]   " << endl;
+            cout << " first  array :  matrix " << maa << " trans " << ta << " " << na << "x" << ma <<endl;
+            cout << " second array :  matrix " << mab << " trans " << tb << " " << nb << "x" << mb <<endl;
+            CompileError(" no same size  [ ...] : [ ...  ] sorry ");
+        }
+        
+        if(maa)
+            for (int i=0;i<na;++i)
+            {
+                const E_Array * li=  dynamic_cast<const E_Array *>(a[i].LeftValue());
+                ffassert(li);
+                for (int j=0; j<ma;++j)
+                    if(!ta)  A(i,j) = (*li)[j];
+                    else     A(j,i) = TryConj((*li)[j]);
+            }
+        else
+            for (int i=0;i<na;++i)
+                if(!ta)  A(i,0) = a[i];
+                else     A(0,i) = TryConj(a[i]);
+        
+        if(mab)
+            for (int i=0;i<nb;++i)
+            {
+                const E_Array * li=  dynamic_cast<const E_Array *>(b[i].LeftValue());
+                ffassert(li);
+                for (int j=0; j<mb;++j)
+                    if(!tb)  B(i,j) = (*li)[j];
+                    else     B(j,i) = TryConj((*li)[j]);
+            }
+        else
+            for (int i=0;i<nb;++i)
+                if(!tb)  B(i,0) = b[i];
+                else     B(0,i) = TryConj(b[i]);
+        
+        //KNM<CC_F0> C(na1,mb1);
+        CC_F0 s,aibi;
+        
+        for (int i=0;i<na1;++i)
+            for (int j=0;j<ma1;++j)
+            {
+                aibi = C_F0(TheOperators,"*",A(i,j),B(i,j));
+                if( (i==0) && (j==0))
+                    s = aibi; 
+                else 
+                    s = C_F0(TheOperators,"+",s,aibi);
+            };
+        //   if( na1==1 && mb1 ==1)
+        return s;
+    }
+    else if ( ea || tea )
+    { // modif 2 /08/  2013  FH .. bug in [ a0,a1,... ]'*b 
+        //  [a0,a1,... ]*b  or [ a0,a1,... ]'*b  => [ a0*b',a1*b',
+        const E_Array & a=  ta ? *tea->v : *ea;
+        int na=a.size();
+        AC_F0  v;
+        v = 0; // empty
+        C_F0 b =ta ? TryConj(args[1]) :args[1]; 
+        for (int i=0;i<na;++i)
+        v += C_F0(TheOperators,"*",a[i],b)  ;            
+        return ta ? C_F0(TheOperators,"\'",C_F0(TheOperators,"[]",v)) :   C_F0(TheOperators,"[]",v);
+        
+    }
+    else if(eb || teb)
+    {  // modif 2 /08/  2013  FH .. bug in a*[ b0,b1,... ]'
+        const E_Array & b=  tb ? *teb->v : *eb;
+        int nb=b.size();
+        C_F0 a =tb ? TryConj(args[0]) :args[0]; 
+        AC_F0  v;
+        v = 0; // empty
+        for (int i=0;i<nb;++i)
+            v += C_F0(TheOperators,"*",a,b[i]) ;
+        return tb ? C_F0(TheOperators,"\'",C_F0(TheOperators,"[]",v)) :   C_F0(TheOperators,"[]",v);
+        
+    }
+    else ffassert(0); 
+    /*
+     cout << "   formal : array or matrix : [ .. ] : [ .. ]   " << na << "x" << nb << endl;
+     cout << "   formal : array or matrix : [ .. ] : [ .. ]   " <<  endl;
+     cout << " first  array :  matrix " << maa << " trans " << ta << " " << na << "x" << ma <<endl;
+     cout << " second array :  matrix " << mab << " trans " << tb << " " << nb << "x" << mb <<endl;
+     CompileError("  not implemented sorry ..... (FH) to do ???? ");
+     
+     */
+    return C_F0();
+}
+
+
+C_F0  opSum::code2(const basicAC_F0 &args) const
+{
+    
+    bool ta =args[0].left()==atype<TransE_Array>();
+    bool tb = args[1].left()==atype<TransE_Array>();
+    const TransE_Array * tea=0;
+    const TransE_Array * teb=0;
+    const E_Array * ea=0;
+    const E_Array * eb=0;// E_F0
+    if( ta)  tea = dynamic_cast<const TransE_Array*>((Expression) args[0]);
+    else ea = dynamic_cast<const E_Array*>((Expression) args[0]);
+    if( tb)  teb = dynamic_cast<const TransE_Array*>((Expression) args[1]);
+    else eb = dynamic_cast<const E_Array*>((Expression) args[1]);
+    assert( ea || tea );
+    assert( eb || teb );
+    const E_Array & a=  ta ? *tea->v : *ea;
+    const E_Array & b=  tb ? *teb->v : *eb;
+    int na=a.size();
+    int nb=b.size();
+    if(na != nb) CompileError(" formal   [ [...] [] ] : [ [..], [..] , ... ]  ");
+    
+
+    AC_F0  v;
+    v = 0; // empty
+	for (int i=0;i<na;++i)	
+	    v += C_F0(TheOperators,op,ta ? TryConj(a[i]) : a[i],tb ? TryConj(b[i]): b[i]) ;
+	return C_F0(TheOperators,"[]",v);
+    
+}
+
+
+
+
+
+
diff --git a/src/fflib/AFunction.hpp b/src/fflib/AFunction.hpp
new file mode 100644
index 0000000..07becb4
--- /dev/null
+++ b/src/fflib/AFunction.hpp
@@ -0,0 +1,3256 @@
+/// \file
+
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//file afonction.h
+#ifndef __AFONCTION__
+#define __AFONCTION__
+#include "showverb.hpp" 
+#include "InitFunct.hpp"
+
+#include <typeinfo>
+#include <cstddef>
+#include <iostream>
+#include <fstream>
+#include <cstring>
+#include "error.hpp"
+#include <map>
+#include <deque>
+#include <list>
+#include <vector>
+#include <queue>
+#include <complex>
+#include <string>
+#include <cstdlib>
+#include <algorithm>
+extern bool showCPU;
+#include "RNM.hpp" 
+
+#ifdef TIME_WITH_SYS_TIME 
+# include <sys/time.h> 
+# include <time.h> 
+#else
+# ifdef HAVE_SYS_TIME_H 
+# include <sys/time.h> 
+# else 
+# include <time.h>
+# endif 
+#endif
+
+// #include <time.h> 
+#include "CodeAlloc.hpp"
+
+inline double CPUtime(){
+#ifdef SYSTIMES
+  struct tms buf;
+  if (times(&buf)!=-1)
+    return ((double)buf.tms_utime+(double)buf.tms_stime)/(long) sysconf(_SC_CLK_TCK);
+  else
+#endif
+    return ((double) clock())/CLOCKS_PER_SEC;
+}
+
+extern long verbosity;  // level off printing
+extern long searchMethod; //pichon
+
+extern bool  withrgraphique;
+
+
+
+using namespace std;
+#include "ffstack.hpp"
+
+#include "AnyType.hpp"
+#include "String.hpp"
+
+
+class basicForEachType;
+class E_F1_funcT_Type;
+class E_F0;  //  une instruction exec time 
+class C_F0;  //  une instruction  complie time
+class ListOfInst;
+class Polymorphic;
+class OneOperator;
+
+/// <<Expression>> is used as the type of the local list contained in ListOfInst
+
+typedef  E_F0  *  Expression;
+
+class AC_F0;
+class basicAC_F0;
+typedef complex<double> Complex;
+
+/// <<Type_Expr>> [[file:AnyType.hpp::aType]] [[E_F0]]
+typedef pair<aType,  E_F0  *>  Type_Expr ;// to store the type and the expression  29042005 FH
+
+ int  FindType(const char * name) ; 
+  void lgerror (const char* s) ;  
+ void CompileError(string msg="",aType r=0);
+ void ExecError(string msg="");
+ 
+struct UnId {
+  const char * id;
+  aType r;
+  Expression  e; 
+  deque<UnId> * array; //  to store a array 
+  aType re; 
+  bool ref; // a ref or non 
+  UnId() :id(0),r(0),e(0),array(0),re(0),ref(false) {}
+  UnId(const char * idd) :id(idd),r(0),e(0),array(0),re(0),ref(false) {}
+  UnId(const char * idd,const C_F0 & ee,aType rr,bool reff) ;  
+  UnId(deque<UnId>  * d) : id(0),r(0),e(0),array(d?new deque<UnId>(*d):0),re(0),ref(false) {}
+  UnId(const UnId & u) : 
+    id(u.id),r(u.r),e(u.e),
+    array(u.array?new deque<UnId>(*u.array):0),
+    re(u.re),ref(u.ref) {}
+   // Modif 24032005  
+  void  operator= (const UnId & u) {
+    id=u.id;
+    r=u.r;
+    e=u.e;
+    re=u.re;
+    ref=u.ref;
+    if(array) delete array;
+    array=0;
+    if(u.array) array= new deque<UnId>(*u.array);
+  }
+    
+  ~UnId(){ if( array) delete array;} // Modif 24032005  
+  
+};
+
+/// <<ListOfId>>
+
+typedef deque<UnId> ListOfId;
+
+//  xxx is a type so xxx can't be a parameter 
+#define ATYPE(xxx) map_type[typeid(xxx).name()]
+/* #define NEW_TYPE(type) map_type[typeid(type).name()] = new ForEachType<type >(0,0)
+//#define NEW_TYPE(type) map_type[typeid(type).name()] = new ForEachType<type >()
+#define NEW_TYPE_I(type,i,d) map_type[typeid(type).name()] = new ForEachType<type>(i,d)   
+#define NEW_TYPE_Ptr(type) map_type[typeid(type*).name()] = new ForEachTypePtr<type  >()
+#define NEW_TYPE_PtrND(type) map_type[typeid(type*).name()] = new  ForEachTypePtr<type >(0)
+#define NEW_TYPE_PtrNIND(type) map_type[typeid(type*).name()] = new ForEachTypePtr<type >(0,0)
+//#define NEW_TYPE_PtrI(type) map_type[typeid(type*).name()] = new ForEachTypePtr<type*>(Initialize<type>)
+*/
+
+/// Doxygen doc
+extern Polymorphic * TheOperators, * TheRightOperators;
+
+//  -------------
+extern  C_F0 *pOne,*pZero,*pminusOne;
+
+
+typedef   AnyType (* Function1)(Stack, const AnyType &);
+typedef   AnyType (* Function2)(Stack, const AnyType &,const AnyType &);
+typedef   AnyType (* CFunction2)(Stack,  E_F0 *, E_F0  *);
+typedef   AnyType (* CFunction4)(Stack,  E_F0 *, E_F0 *, E_F0 *, E_F0 *);
+
+
+Expression NewExpression(Function1,Expression);
+Expression NewExpression(Function2,Expression,Expression);
+
+
+inline Type_Expr make_Type_Expr(aType t, E_F0  * e) {return make_pair(t,e);}
+inline Type_Expr make_Type_Expr( E_F0  * e,aType t) {return make_pair(t,e);}
+
+struct Keyless : binary_function<const char *,const char *, bool>
+   { 
+    typedef const char * Key;
+    bool operator()(const Key& x, const Key& y) const { return strcmp(x,y)<0;} };
+    
+
+// <<TableOfIdentifier>>
+class TableOfIdentifier: public CodeAlloc {
+  public:
+  struct Value;
+  typedef const char * Key;
+  typedef map<Key,Value,Keyless> maptype;
+  typedef pair<const Key,Value> pKV;
+  typedef maptype::iterator iterator;
+  typedef maptype::const_iterator const_iterator;
+  
+  struct  Value :public Type_Expr {
+    pKV *  next; // link all the variable in reverse order to call delete on each variable 
+    bool del; 
+    Value(const Type_Expr & vv,pKV * n,bool dd=true) : Type_Expr(vv),next(n),del(dd) {}
+    Value(aType t,E_F0  *f,pKV *n,bool dd=true): Type_Expr(t,f),next(n),del(dd) {}
+  };//  to store the type and the expression 
+  pKV *   listofvar;
+  
+// struct Keyless : binary_function<Key,Key, bool>
+//   { bool operator()(const Key& x, const Key& y) const{ return strcmp(x,y)<0;} };
+
+
+  maptype m;
+  C_F0 Find(Key) const ; 
+  C_F0 Find(Key,const basicAC_F0 &) const ; 
+  
+  const Type_Expr & New(Key k,const Type_Expr &  v,bool del=true);
+  void Add(Key k,Key op,OneOperator *p0,OneOperator *p1=0,
+      OneOperator *p2=0,OneOperator *p3=0,OneOperator *p4=0,
+      OneOperator *p5=0,OneOperator *p6=0)  ;
+  void clear(); 
+template<class T>         
+  C_F0 NewVar(Key k,aType t,size_t & top,const C_F0 &i) ;
+template<class T>         
+  C_F0 NewVar(Key k,aType t,size_t & top,const basicAC_F0 &args) ;
+template<class T,class U>         
+  C_F0 NewVar(Key k,aType t,size_t & top,const basicAC_F0 &args,const U & data) ;
+//  C_F0 NewVar(Key k,aType t,size_t & top,const basicAC_F0 &args,const C_F0& f) ;
+template<class T>         
+  C_F0 NewVar(Key k,aType t,size_t & top) ;
+  C_F0 NewID(aType t,Key k, C_F0 & c,size_t & top,bool del=true);   
+  C_F0 NewID(aType t,Key k, C_F0 & c,const ListOfId & l,size_t & top,bool del=true);   
+template<class T>   
+  C_F0 NewFESpace(Key k,aType t,size_t & top,const basicAC_F0 &args);
+  friend   ostream & operator<<(ostream & f,const TableOfIdentifier & );
+  C_F0 destroy();
+  TableOfIdentifier() ; //: listofvar(0) {};
+  ~TableOfIdentifier(); //
+};
+
+
+// <<basicForEachType>> for all the type of the language 
+class basicForEachType : public CodeAlloc {
+    const type_info  * ktype;  // the real type_info
+  //  const type_info *ktypefunc;// the type of code 
+    public:
+     const size_t size;
+
+    
+    typedef OneOperator * CastFunc;
+    typedef map<aType,CastFunc>::const_iterator const_cast_iterator;
+
+    typedef const char * Key;
+
+   // virtual  void print(ostream &f,const void *p) const =0;
+                            
+    friend ostream & operator<<(ostream & f,const basicForEachType & e) 
+      { f << '<' << e.name() << '>' ;return f;}
+     void Show(ostream & f) const ;
+     const char * name() const  { return this  ?  ktype->name() :"NULL" ;}
+     virtual bool CastingFrom(const basicForEachType * t) const ;
+     //  modif FH -----  A TESTER  // 
+     virtual bool SametypeRight(const basicForEachType * t) const {return  (this == t) || (t == un_ptr_type) || (t == type_C_F0);}
+//     virtual Type_Expr init(const Type_Expr & te) const { return Type_Expr(0,0);}
+     virtual int TYPEOFID() const  {return 0;}
+//     bool SametypeLeft(const basicForEachType * t) const {return  t == this;}
+   //  bool To(const basicForEachType * t) const { throwassert(t && this);return un_ptr_type == this ? t->un_ptr_type == this :  t == this;}
+     virtual C_F0 CastTo(const C_F0 & e) const ; 
+     virtual void SetArgs(const ListOfId *lid) const ;// { cout << "SetArgs::\n " ;throwassert(lid==0 || lid->size()==0);}
+     aType right() const {return un_ptr_type;};
+     Expression RightValueExpr(Expression f) const; 
+ //    Type_Expr NewVar(Key k,aType t,size_t & top,const C_F0 &i);
+     virtual  C_F0 Initialization(const Type_Expr & e) const ;
+     virtual Expression Destroy(const C_F0 &) const ;
+     virtual bool ExistDestroy() const {return destroy;} 
+     virtual Type_Expr SetParam(const C_F0 & c,const ListOfId * l,size_t & top) const;
+     virtual Expression OnReturn(Expression f) const; 
+     // { return make_pair<aType,const E_F0  *>(this,c.left());}
+
+   protected: 
+     basicForEachType(const type_info  & k ,const size_t ,
+                            const E_F1_funcT_Type * p=0,basicForEachType *rr=0,
+                            Function1 iv=0,Function1 id=0, Function1 dreturn=0) ;
+/*    inline basicForEachType(const type_info  & k ,const type_info  & kf ,const size_t ,
+                            const E_F1_funcT_Type * p=0,basicForEachType *rr=0,
+                            Function1 iv=0,Function1 id=0) ;*/
+
+public:
+    static  const  basicForEachType * type_C_F0; //  for any type un formal operation .... FH add 09/2012
+    
+    const basicForEachType * un_ptr_type;  // type of right exp
+   private:
+ //   map<aType,CastFunc> mapofcast;
+    OneOperator * casting; // list of operator for casting to this type 
+    
+    const E_F1_funcT_Type * un_ptr;        //  is ptr -> get value function
+    Function1 DoOnReturn;        //  to call some thing on return. 
+    
+    
+    Function1 InitExp;       //  to init the ptr value 
+    Function1  destroy;//  the destroy function 
+    TableOfIdentifier ti; //  all polymorphisme of the Identifier   
+   public:
+  // basicForEachType * FunctionType() const;// { return funct_type ? funct_type : (funct_type= new FuncForEachType(this));}
+   C_F0  Find(const char * k) const; // {return ti->Find(k);}
+   C_F0  Find(const char * k,const basicAC_F0 & args) const; // {return ti->Find(k);}
+   void  New(Key k,Type_Expr  v,bool del=true){ti.New(k,v,del);}
+  
+  void Add(Key k,Key op,OneOperator *p0,OneOperator *p1=0,
+      OneOperator *p2=0,OneOperator *p3=0,OneOperator *p4=0,
+      OneOperator *p5=0,OneOperator *p6=0)  
+     {ti.Add(k,op,p0,p1,p2,p3,p4,p5,p6);}     
+ 
+ 	void AddCast(CastFunc f1,CastFunc f2=0,CastFunc f3=0,CastFunc f4=0,
+ 	             CastFunc f5=0,CastFunc f6=0,CastFunc f7=0,CastFunc f8=0);
+    ostream & ShowTable(ostream & f) const { f << ti; return f;}
+    
+  //  basicForEachType * funct_type;
+  virtual ~basicForEachType();
+    
+};
+
+
+template<typename T> 
+inline basicForEachType * atype() { 
+  map<const string,basicForEachType *>::iterator ir=map_type.find(typeid(T).name());
+ // basicForEachType * r=map_type[];
+  if (ir == map_type.end()) { cerr << "Error: aType  '" << typeid(T).name() << "', doesn't exist\n";
+             ShowType(cerr);
+            throw(ErrorExec("exit",1));}
+  return ir->second;}
+
+
+//  --------
+//typedef basicForEachType TheType;
+
+//  const basicForEachType * ktype; // compilation time 
+
+//  class for all   exp 
+// a left exp is a pointer expression 
+//  -------
+//  --  exec times le code is just E_F0*(fonction without args)
+class C_LF2;
+class C_LF1;
+
+//  3 types of function/expression  0,1,2 args  
+
+/// <<E_F0>> is the base class for all expressions built by parsing an EDP script in the grammar of the FreeFem++
+/// language (see lg.ypp). E_F0 pointers are typed as #Expression, stored as a list in [[ListOfInst]], and evaluated
+/// when CListOfInst::eval() [[file:AFunction.hpp::CListOfInst::eval]] is called (see \ref index).
+
+class E_F0 :public CodeAlloc 
+   {
+   public:
+
+  struct kless : binary_function<Expression,Expression, bool>
+   { bool operator()(const Expression& x, const Expression& y) const{ 
+     //cout << x << " " << y << x->compare(y) << " ::: ";
+      int r1 = x->compare(y);// , r2 = y->compare(x);
+     //assert(r1+r2==0);
+     return r1<0;} };  
+   typedef map< E_F0 *,int,kless> MapOfE_F0;
+
+    virtual AnyType operator()(Stack)  const =0;
+    virtual bool Empty() const {return !this; }
+   // virtual E_F0 * destroy(Stack ) const {return 0;}
+  //  virtual const E_F0 * Parameter(Stack ) const {return this;}
+    virtual size_t nbitem() const {return 1;}
+    virtual bool EvaluableWithOutStack() const {return false;} // 
+    virtual bool MeshIndependent() const {return true;} // 
+    virtual bool Zero() const {return false;} //
+    virtual E_F0 * right_E_F0() const { return 0;}
+    virtual bool ReadOnly() const { return true;} // the expression do not change the memory     
+    virtual ~E_F0() {}
+    virtual int compare (const E_F0 *t) const { int r= (t==this) ? 0 : ( ( this<t) ?-1 : 1);
+     //cout << "cmp " <<  typeid(*this).name() << r << endl; 
+     return r;} // to give a order in instuction 
+    virtual int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) ;  // build optimisation
+    virtual AnyType operator()(Stack stack,AnyType *)  const { return operator()(stack);}  // call optim code
+    virtual  operator aType ()  const { assert(0);return 0;}   // the type of the expression
+    virtual ostream & dump(ostream &f) const  { f << ' ' << typeid(*this).name() << ' ' << this << ' '  ;return f; }
+    // for OPTIMIZATION
+    
+    int find(const MapOfE_F0 & m) ;
+    int insert(Expression  opt,deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) ;
+    // ajoute for optimisation to say if a expression in meshindep a exec time
+    // to solve   0*x // question 
+    // juin 2007 FH
+    virtual AnyType eval(Stack stack, bool & meshindep ) const  
+    { meshindep=MeshIndependent();return operator()(stack);}
+     
+ };  
+ 
+inline ostream & operator<<(ostream & f,const E_F0 &e) { if(&e) e.dump(f); else f << " --0-- " ;return f;}
+
+/// <<E_F0mps>> Specialization of [[E_F0]] where MeshIndependent() always returns false instead of true.  
+
+class E_F0mps : public E_F0 { public:
+  virtual bool MeshIndependent() const {return false;} // 
+};
+
+class E_F0info : public E_F0 { public:
+  // not a real expression just to pass information 
+    virtual bool EvaluableWithOutStack() const {return true;} // 
+    virtual bool MeshIndependent() const {return true;} // 
+    virtual AnyType operator()(Stack )  const {  
+    return SetAny<const E_F0 *>(this);}
+    operator aType () const { return atype<Expression>();} 
+
+  
+};
+
+class E_F1 : public CodeAlloc{ public: virtual AnyType operator()(Stack,AnyType &)  const =0;}; 
+class E_F2 : public CodeAlloc{ public: virtual AnyType operator()(Stack,AnyType &,AnyType &)  const =0;};
+class E_FN : public CodeAlloc{ public: virtual AnyType operator()(Stack,size_t N,...)  const =0;};
+
+//   class to play with  polymorphisme 
+//   ---------------------------------
+class basicAC_F0;
+class  ArrayOfaType : public CodeAlloc{ 
+  //  class for the type of parameter
+   aType tt[11]; 
+   protected:
+
+   int n;
+   aType * t; // array of type  
+   bool ellipse; 
+   void operator=(const ArrayOfaType &); // no set  operator
+   public:
+ //  ArrayOfaType() :n(0),t(0),ellipse(false) {}
+   explicit ArrayOfaType(bool ell=false) 
+       :n(0),t(0),ellipse(ell) {}
+   
+   explicit ArrayOfaType(const aType & a,bool ell=false) 
+       :n(1),t(tt),ellipse(ell)  {t[0]=a;}
+       
+   explicit ArrayOfaType(const aType & a,const aType & b,bool ell=false) 
+       :n(2),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;}
+       
+   explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,bool ell=false) 
+       :n(3),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;}
+       
+   explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d,bool ell=false) 
+       :n(4),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d;
+       /* cout << * a << *b << * c << * d << " ---------" << endl; */}
+   explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d,const aType & e,bool ell=false) 
+       :n(5),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d; t[4]=e; }
+   explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d,const aType & e,const aType & f,bool ell=false) 
+       :n(6),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d; t[4]=e; t[5]=f; }
+
+  explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d,const aType & e,
+			const aType & f,const aType & g,
+			bool ell=false) 
+    :n(7),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d; t[4]=e; t[5]=f; t[6]=g; }  // (6 args) Added by Fabian Dortu
+
+  explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d,const aType & e,
+			const aType & f,const aType & g,const aType & h,
+			bool ell=false) 
+    :n(8),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d; t[4]=e; t[5]=f; t[6]=g; t[7]=h; }  // (7 args) Added by Fabian Dortu
+
+  explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d,const aType & e,
+  			const aType & f,const aType & g,const aType & h, const aType & i,
+			bool ell=false) 
+    :n(9),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d; t[4]=e; t[5]=f; t[6]=g; t[7]=h; t[8]=i; }  // (8 args) Added by Fabian Dortu
+
+  explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d, const aType & e,
+  		const aType & f,const aType & g,const aType & h, const aType & i, const aType & j,
+  		bool ell=false) 
+    :n(10),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d; t[4]=e; t[5]=f; t[6]=g; t[7]=h; t[8]=i;  t[9]=j; }  // (10 args) Added by Fabian Dortu
+  
+   explicit ArrayOfaType(const aType & a,const aType & b,const aType & c,const aType & d,const aType & e,const aType & f,const aType & g,const aType & h, const aType & i, const aType & j, const aType & k,bool ell=false) 
+    :n(11),t(tt),ellipse(ell)  {t[0]=a,t[1]=b;t[2]=c;t[3]=d; t[4]=e; t[5]=f; t[6]=g; t[7]=h; t[8]=i;  t[9]=j; t[10]=k; }  // (10 args) Added by Fabian Dortu
+  
+       
+   ArrayOfaType(const basicAC_F0 & ) ;
+   ArrayOfaType(const ArrayOfaType & ); // 
+   ArrayOfaType(const ListOfId * l);
+   ~ArrayOfaType() { if(t && t != tt) delete [] t;t=0;n=0;}
+   bool WithOutCast( const ArrayOfaType & a) const ;  
+   bool WithCast( const ArrayOfaType & a,int nbcast=100000) const ;  // return the number of cast 
+   // exactly comparaison 
+   bool operator==( const ArrayOfaType & a) const { 
+     if (a.n != n || a.ellipse !=ellipse) return false;
+     for (int i=0;i<n;i++)  
+       if (t[i] != a.t[i]) 
+         return false; 
+     return true;}
+   
+   friend ostream & operator<<(ostream & f,const ArrayOfaType & a);
+};
+
+
+/// <<OneOperator>> Base class for all language operators. Daughter classes have the same name with several extensions:
+/// "[1-9]" represent the number of operator arguments, "_" designates operators that take a reference instead of a
+/// copied argument, "s" designates operators that require a stack argument.
+
+class  OneOperator : public ArrayOfaType {
+    friend class MakeVectSpaceN;
+    friend class basicForEachType;
+    const basicForEachType * r; //  return type 
+    OneOperator *next; // to make a list of OneOperator
+    public: 
+    int pref; //  to try to solve ambiguity for binary operator
+    //  10 for bool, 20 for int , 30 for long , 40, for float, 50 double, 60 for complex, 70 string
+    //  string+ 1 => string 
+    // 1+string => string 
+    OneOperator(aType rr) ;// : r(rr),ArrayOfaType(),next(0),pref(0) {throwassert(r);}
+    OneOperator(aType rr,aType  a) ;//: r(rr),ArrayOfaType(a,false),next(0),pref(0) {throwassert(rr && a );}
+    OneOperator(aType rr,aType  a,aType  b);// : r(rr),ArrayOfaType(a,b,false),next(0),pref(0) {
+    // throwassert(rr && a && b);} 
+    OneOperator(aType rr,aType  a,aType  b,aType c) ;
+    //: r(rr),ArrayOfaType(a,b,c,false),next(0),pref(0) {throwassert(rr && a && b && c);} 
+    OneOperator(aType rr,aType  a,aType  b,aType c,aType d) ;
+    //: r(rr),ArrayOfaType(a,b,c,d,false),next(0),pref(0) {throwassert(rr && a && b && c);} 
+    
+    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e) ;
+     //: r(rr),ArrayOfaType(a,b,c,d,e,false),next(0),pref(0) {throwassert(rr && a && b && c && d);} // Added by Fabian Dortu (5 parameters)
+    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f) ;
+     //: r(rr),ArrayOfaType(a,b,c,d,e,f,false),next(0),pref(0) {throwassert(rr && a && b && c && d && e && f);} // Added by Fabian Dortu (6 parameters) 
+    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g);
+     // : r(rr),ArrayOfaType(a,b,c,d,e,f,g,false),next(0),pref(0) {throwassert(rr && a && b && c && d && e && f && g);} // Added by Fabian Dortu (7 parameters) 
+    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g, aType h);
+     // : r(rr),ArrayOfaType(a,b,c,d,e,f,g,h,false),next(0),pref(0) {throwassert(rr && a && b && c && d && e && f && g && h);} // Added by Fabian Dortu (8 parameters) 
+    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g, aType h, aType i) ;
+     //: r(rr),ArrayOfaType(a,b,c,d,e,f,g,h,i,false),next(0),pref(0) {throwassert(rr && a && b && c && d && e && f && g && h && i);} // Added by Fabian Dortu (9 parameters) 
+    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g, aType h, aType i, aType j);
+      // : r(rr),ArrayOfaType(a,b,c,d,e,f,g,h,i,j,false),next(0),pref(0) {throwassert(rr && a && b && c && d && e && f && g && h && i && j);} // Added by Fabian Dortu (10 parameters) 
+    
+    
+    
+    OneOperator(aType rr,const ArrayOfaType &ta) ;
+      //: r(rr),ArrayOfaType(ta),next(0),pref(0) {throwassert(rr);} 
+    OneOperator(aType rr,bool ellipse) ;
+    //: r(rr),ArrayOfaType(ellipse),next(0),pref(0) {throwassert(rr );} 
+    OneOperator(aType rr,const ListOfId *l) ;
+    //: r(rr),ArrayOfaType(l),next(0),pref(0) {throwassert(rr );} 
+    
+    typedef pair<const OneOperator *,int> pair_find;
+    void operator+=(OneOperator &a){throwassert(a.next==0);a.next=next;next=&a;} 
+    //  a way to make none recurve delete  good   
+    virtual ~OneOperator();
+    pair_find Find(const ArrayOfaType & at) const ;
+    pair_find FindWithOutCast(const ArrayOfaType & at) const ; // for 
+    OneOperator * FindSameR(const ArrayOfaType & at)  ; 
+       
+    void Show(const ArrayOfaType & at,ostream &f=cerr) const;
+    void Show(ostream &f=cerr) const;
+    operator aType () const { return r;}
+
+    // <<OneOperator_code_decl>>
+    virtual E_F0 * code(const basicAC_F0 &) const =0; 
+    virtual C_F0  code2(const basicAC_F0 &a) const ; // {return code(code(a),r);}	
+    const OneOperator * Simple() const { return next||n?0:this;}
+    friend ostream & operator<<(ostream & f,const OneOperator & a);
+    
+};
+
+/// <<Polymorphic>>
+
+class Polymorphic:  
+  public E_F0mps // [[E_F0mps]]
+{
+   //  a list of type 
+   //  simple, array or function
+private: 
+   typedef const char * Key;
+   typedef OneOperator * Value;
+ //  struct Keyless : binary_function<Key,Key, bool>
+ //  { bool operator()(const Key& x, const Key& y) const{ return strcmp(x,y)<0;} };
+   
+   typedef map<Key,Value,Keyless> maptype;          //  
+   typedef maptype::const_iterator const_iterator;  // 
+   typedef maptype::iterator iterator;              // 
+   //  remark the map is mutable because 
+   //  a expression is const E_F0 *
+   // So There is a incompatibility between 
+   //   we save an  expression in a variable 
+   //   we have to add thing to a polymorphisme expression
+   mutable maptype m; //  all polymorphisme of the Identifier
+   Expression e; // default expression
+public:    
+  Polymorphic() : m(),e(0) {}
+  
+//  by default Empty and do nothing      
+ virtual AnyType operator()(Stack ) const  { return Nothing;}
+ virtual bool Empty() const {return true;} //  by default Empty 
+ void clear() { m.clear();}
+ const  OneOperator * Find(const char *op, const ArrayOfaType &at) const;
+ const  OneOperator * FindWithOutCast(const char *op,const  ArrayOfaType &at) const;
+ void Show(const char *op,const ArrayOfaType & at,ostream &f=cerr)const ; 
+ void  Add(const char * op,OneOperator * p0  ,OneOperator * p1=0,OneOperator * p2=0,
+                           OneOperator * p3=0,OneOperator * p4=0,OneOperator * p5=0,
+                           OneOperator * p6=0,OneOperator * p7=0,OneOperator * p8=0,
+                           OneOperator * p9=0,OneOperator * pa=0,OneOperator * pb=0,
+                           OneOperator * pc=0,OneOperator * pd=0,OneOperator * pe=0
+                           ) const
+      {Addp(op,p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,pa,pb,pc,pd,pe,0);}
+ void Add(const char * op,OneOperator ** pp) const ;      
+private:
+  void Addp(const char * op,OneOperator * pp,...) const ;
+  friend ostream & operator<<(ostream & f,const Polymorphic & a);
+};
+
+///   the type for polymorphisme of id 
+
+/// <<C_F0>> compile time expressions
+
+class basicAC_F0;
+class C_F0 {
+  friend class CC_F0; // cf [[CC_F0]]
+protected: 
+  Expression  f; //  the expression code, cf [[Expression]]
+  aType r;   // the expression type, cf  [[file:../fflib/AnyType.hpp::aType]]
+  
+public: 
+  //  the constructeur 
+  C_F0() :f(0),r(0) {}
+  C_F0(const C_F0 & c):f(c.f),r(c.r)   {}
+  C_F0(const C_F0 & a,const C_F0 & b); // concatenation 
+
+  /// cf [[Type_Expr]]
+  C_F0(const Type_Expr & a):f(a.second),r(a.first)   {}
+
+  /// <<C_F0_constructor_pop_char_basicAC_F0_decl>>
+  /// [[file:AFunction2.cpp::C_F0_constructor_pop_char_basicAC_F0_impl]]
+  /// cf [[Polymorphic]]
+  C_F0(const Polymorphic *,const char *,const basicAC_F0 & );
+
+  C_F0(const Polymorphic *,const char *, AC_F0 & );
+
+  //  function, array ..  
+  C_F0(const C_F0 & e,const char *op,const basicAC_F0 & p)  ;
+  C_F0(const C_F0 & e,const char *op, AC_F0 & p) ;	  
+
+  // <<C_F0_constructor_char_C_F0_decl>> [[C_F0_constructor_char_C_F0_impl]]
+  C_F0(const C_F0 & e,const char *op,const C_F0 & ee);
+
+  C_F0(const C_F0 & e,const char *op,const C_F0 & a,const C_F0 & b) ; 	  
+  C_F0(const C_F0 & e,const char *nm) ; 
+
+  //  without parameter ex f(). cf [[Polymorphic]]
+  C_F0(const Polymorphic * pop,const char *op); 
+
+  // unary operator  
+  C_F0(const Polymorphic * pop,const char *op,const C_F0 & a); 
+
+  // <<C_F0_constructor_binary_decl>> binary operator [[file:AFunction2.cpp::C_F0_constructor_binary]]
+  C_F0(const Polymorphic * pop,const char *op,const C_F0 & a,const  C_F0  & b); 
+
+  // ternary operator  
+  C_F0(const Polymorphic * pop,const char *op,const  C_F0 & a,const  C_F0 & b,const  C_F0 & c); 
+	  
+  C_F0( Expression ff,aType rr ): f(ff),r(rr) { 
+    //   cout << "C_F0: " <<  * rr << endl;//  dec 2007 FH
+    // if (!rr && ff)  cerr << "Type Null" << endl;
+  }
+
+  // operator Expression() const {return f;}
+  AnyType eval(Stack s) const {return (*f)(s);}
+  
+  Expression RightValue() const { return r->RightValueExpr(f);}	  
+  Expression LeftValue() const;
+	  
+  aType left() const {return r;}
+  aType right() const {return r->right();}
+  C_F0  RightExp() const { return C_F0(RightValue(),right());} // FH add 07/2005
+  operator    E_F0 *  () const {return f;}
+  bool Empty() const {return !f || f->Empty();}
+  bool NotNull() const {return  f;}
+  int  TYPEOFID() const { return r ? r->TYPEOFID(): 0;}
+  int  nbitem() const { return f ? f->nbitem() : 0;}
+  bool EvaluableWithOutStack() const { return f && f->EvaluableWithOutStack();}
+  bool Zero() const { return !f || f->Zero();}
+  Expression Destroy() {  return r->Destroy(*this);}
+    
+  operator const Polymorphic * () const {return  dynamic_cast<const Polymorphic *>(f);}
+  bool operator==(const C_F0 & a) const {return f==a.f && r == a.r;}
+  bool operator!=(const C_F0 & a) const {return f!=a.f || r != a.r;}
+  //          Type_Expr SetParam(const ListOfId * l,size_t & top) const ;
+  bool MeshIndependent() const { return f ==0 ? f->MeshIndependent() : false;}
+  C_F0 OnReturn() {	 f=r->OnReturn(f); return *this;  } // Add mai 2009 (for return statment.
+private:
+  friend class Block;	 
+  friend class TableOfIdentifier; 
+  C_F0( Expression ff ): f(ff),r(0) {}
+};
+
+
+
+// for bison [[CListOfInst]]
+class CListOfInst;
+
+ //  a => b
+ //  f => t||f
+ //  t => t
+ //  (a =>b)  <=>  (!a || b )
+ 
+//  warning ------------------
+class ForTypeVoid:  public basicForEachType{public:
+    ForTypeVoid():basicForEachType(typeid(void),0,0,0,0,0) {}
+};
+
+template<class T> 
+class ForEachType:  public basicForEachType{public:
+    ForEachType(Function1 iv=0,Function1 id=0,Function1 OOnReturn=0):basicForEachType(typeid(T),sizeof(T),0,0,iv,id,OOnReturn) {
+     if (sizeof(T) > sizeof(AnyTypeWithOutCheck) )
+      {
+        cout << " Sorry the " <<typeid(T).name() << " is too large  ( " << sizeof(T) 
+             << " > " << sizeof(AnyTypeWithOutCheck) << " ) " << endl;
+	throwassert(sizeof(T) <= sizeof(AnyTypeWithOutCheck) );
+      }
+    }
+};
+template<class T> 
+class ForEachType<T*>:  public basicForEachType{public:// coorection july 2009..... FH  Hoooo....  (Il y a un bug DUR DUR FH  ...) 
+    ForEachType(Function1 iv=0,Function1 id=0,Function1 OOnReturn=0):basicForEachType(typeid(T),sizeof(T),0,0,iv,id,OOnReturn) {
+	//T i= 0.0;
+    }
+};
+
+template<class A,class B>  AnyType UnRef(Stack,const AnyType &a) ; 
+template<class A>  AnyType Initialize(Stack,const AnyType &a) ; 
+template<class A>  AnyType Destroy(Stack,const AnyType &a) ; 
+
+//  the type of variable is pointer because we need to write in 
+template<class T,class PT=T*> 
+class ForEachTypePtr:  public basicForEachType { public:
+    ForEachTypePtr();
+    ForEachTypePtr(Function1 init,Function1 dl,Function1 onreturn=0);         
+    ForEachTypePtr(Function1 dl);
+};
+
+template<class T> 
+class ForEachTypePtr<T*,T**>:  public basicForEachType { public:
+    ForEachTypePtr(T* bb=0,Function1 onreturn=0);
+    ForEachTypePtr(Function1 init,Function1 dl,Function1 onreturn=0);         
+    ForEachTypePtr(Function1 dl);
+};
+
+
+template<class T,int RTYPE> 
+class ForEachTypePtrfspace:  public ForEachTypePtr<T> { public:
+    ForEachTypePtrfspace():ForEachTypePtr<T>() {} 
+    int TYPEOFID() const {return RTYPE;} 
+};
+
+
+class ForTypeAnyType:  public basicForEachType{public:
+    ForTypeAnyType(): basicForEachType(typeid(AnyType),sizeof(AnyType)) {}
+      bool CastingFrom(const basicForEachType * ) const {return true;}
+	  C_F0 CastTo(const C_F0 & e) const {return e;}     
+};
+
+
+//  for  cast and get value associed to a pointer  
+
+    
+template<class A,class B> 
+  AnyType Cast(Stack,const AnyType &b) { 
+    return   SetAny<A>(static_cast<A>(GetAny<B>(b)));}
+    
+template<class A,class B,A F(const  B &)> 
+  AnyType FCast(Stack s,const AnyType &b) { 
+    return   SetAny<A>(Add2StackOfPtr2Free(s,F(GetAny<B>(b))));}
+    
+template<class A> 
+  AnyType UnRef(Stack,const AnyType &a) { 
+    return   SetAny<A>(*PGetAny<A>(a));}
+
+template<class A,class B> 
+  AnyType UnRef(Stack,const AnyType &a) { 
+    return   SetAny<A>(*GetAny<B>(a));}
+    
+    
+template<class A> 
+  AnyType UnRefCopyPtr(Stack s,const AnyType &a) { 
+    A ** ppa=PGetAny<A*>(a);
+    A * pc = new A(**ppa);
+    return   SetAny<A*>(Add2StackOfPtr2Free(s,pc)) ;} 
+       
+    
+template<class A> AnyType Initialize(Stack,const AnyType &x){
+  A * a=PGetAny<A>(x);
+  A *b=new A;// 
+  memcpy(a,b,sizeof(A));// bitcopy
+  ::operator delete(b); // delete with no destruction 
+  return  SetAny<A*>(a);
+}
+
+template<class A> AnyType InitializePtr(Stack stack,const AnyType &x){
+  A * a=PGetAny<A>(x);
+  SHOWVERB( cout << " init ptr " << typeid(A*).name() <<  (char *) a  - (char*) stack<< endl);
+  *a=0;
+  return  x;
+}
+
+template<class A> AnyType InitializeDef(Stack stack,const AnyType &x){
+    A * a=PGetAny<A>(x);
+    SHOWVERB( cout << " init ptr " << typeid(A*).name() <<  (char *) a  - (char*) stack<< endl);
+    *a=A();
+    return  x;
+}
+
+
+template<class A> inline AnyType Delete(Stack,const AnyType &x){
+  A * a=PGetAny<A>(x);
+  SHOWVERB(cout << "DESTROY " <<typeid(A).name() << " " << a <<  endl); 
+  (*a).~A(); 
+  return  Nothing;
+}
+
+template<class A> inline AnyType Destroy(Stack,const AnyType &x){
+  A * a=PGetAny<A>(x);
+  SHOWVERB(cout << "DESTROY " <<typeid(A).name() << " " << a <<  endl); 
+  a->destroy(); 
+  return  Nothing;
+}
+
+template<class A> inline AnyType DestroyS(Stack,const AnyType &x){
+  A a=GetAny<A>(x);
+  SHOWVERB(cout << "DESTROY " <<typeid(A).name() << " " << a <<  endl); 
+  a.destroy(); 
+  return  Nothing;
+}
+
+template<class A> inline AnyType InitS(Stack,const AnyType &x){
+  A  a=GetAny<A>(x);
+  SHOWVERB(cout << "InitS " <<typeid(A).name() << " " << a <<  endl); 
+  a.init(); 
+  return  Nothing;
+}
+template<class A> inline AnyType InitP(Stack,const AnyType &x){
+  A  *a=PGetAny<A>(x);
+  SHOWVERB(cout << "InitP " <<typeid(A).name() << " " << a <<  endl); 
+  a->init(); 
+  return  Nothing;
+}
+
+
+template<class A> inline AnyType  DestroyPtr(Stack,const AnyType &x) {
+  const A *  a=PGetAny<A>(x);
+  SHOWVERB(cout << "DestroyPtr " << typeid(A).name() << *a  << endl);
+   (*a)->destroy(); 
+   //  delete *a; 
+
+  return  Nothing; 
+};
+template<class A> inline AnyType DeletePtr(Stack,const AnyType &x) {
+  const A *  a=PGetAny<A>(x);
+  SHOWVERB(cout << "DeletePtr " << typeid(A).name() << *a  << endl);
+  // (*a)->destroy(); 
+    delete *a; 
+
+  return  Nothing; 
+};
+
+template<> AnyType inline DestroyPtr<string *>(Stack,const AnyType &x) {
+  string **  a=PGetAny<string*>(x);
+ SHOWVERB( cout << "DestroyPtr " << typeid(string*).name() << *a  << endl);
+  delete *a; 
+  return  Nothing; 
+};
+
+
+
+template<class A> AnyType Initialize(Stack,const AnyType &x,const AnyType &y){
+ A * a=PGetAny<A>(x);
+ A *b=new A(GetAny<A>(x));// 
+  memcpy(a,b,sizeof(A));// bitcopy
+  ::operator delete(b); // delete with no destruction 
+  return  SetAny<A*>(a);
+}
+ 
+
+  
+class E_F0_CFunc2 :public  E_F0mps { public:
+   CFunction2  f2;
+   E_F0 *a,*b;
+   AnyType operator()(Stack s)  const {return f2(s,a,b);}
+   E_F0_CFunc2( CFunction2 ff,E_F0 *aa,E_F0 *bb) : f2(ff),a(aa),b(bb){}
+   bool EvaluableWithOutStack() const 
+      {return a->EvaluableWithOutStack() && b->EvaluableWithOutStack();} // 
+    operator aType () const { return atype<void>();}         
+
+};
+
+class E_F0_CFunc4 :public  E_F0mps { public:
+   CFunction4  f4;
+   E_F0 *a,*b,*c,*d;
+   AnyType operator()(Stack s)  const {return f4(s,a,b,c,d);}
+   E_F0_CFunc4( CFunction4 ff,E_F0 *aa,E_F0 *bb,E_F0 *cc,E_F0 *dd) 
+   : f4(ff),a(aa),b(bb),c(cc),d(dd){}
+    operator aType () const { return atype<void>();}         
+
+};
+
+
+
+template<class R,class A>
+ class E_F1_F :public  E_F1 { public:
+  typedef  R (*func)(A) ; 
+  func f;
+  E_F1_F(func ff) : f(ff) {}
+  AnyType operator()(Stack s,AnyType & a)  const 
+    {return SetAny<R>(f(GetAny<A>(a)));}  
+};
+
+template<class R,class A0,class A1>
+ class E_F2_F :public  E_F2 { public:
+  typedef  R (*func)(const  A0 &,const  A1&) ; 
+  func f;
+  E_F2_F(func ff) : f(ff) {}
+  AnyType operator()(Stack s,AnyType & a0,AnyType & a1)  const 
+    {return SetAny<R>(f(GetAny<A0>(a0),GetAny<A1>(a1)));}  
+};
+
+template<class R,class TA0,bool RO=true>
+ class E_F_F0 :public  E_F0 { public:
+   template <class T> struct remove_reference     {typedef T type;};
+//   template <class T> struct remove_reference<T&> {typedef T type;};
+   template <class T> struct remove_reference<const T&> {typedef T type;};
+   typedef typename remove_reference<TA0>::type A0;
+   
+ 
+  typedef  R (*func)(  TA0 ) ; 
+  func f;
+  Expression a;
+  E_F_F0(func ff,Expression aa) : f(ff),a(aa) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>(f(GetAny<A0>( (*a)(s) )));}  
+  bool EvaluableWithOutStack() const 
+      {return a->EvaluableWithOutStack();} // 
+  bool MeshIndependent() const {return a->MeshIndependent();} // 
+  bool ReadOnly() const { return RO  ;}     
+  int compare (const E_F0 *t) const { 
+     int rr;
+    // cout << "cmp " << typeid(*this).name() << " and " << typeid(t).name() << endl;
+     const  E_F_F0* tt=dynamic_cast<const E_F_F0 *>(t);
+     if (tt && f == tt->f) rr = a->compare(tt->a);
+     else rr = E_F0::compare(t);
+     return rr;
+     } // to give a order in instuction 
+
+   int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) ;
+   virtual ostream & dump(ostream &ff) const  { ff << typeid(*this).name() <<" f= " << f << " a= "<< *a << ' '  ;return ff; }
+
+};
+
+// modif for xlc++ FH 
+template<class R,class TA0,bool RO=true>
+class E_F_F0_Opt: public E_F_F0<R,TA0,RO>  { public :
+  size_t ia;  
+  E_F_F0_Opt(const  E_F_F0<R,TA0,RO>  &t,size_t iaa) 
+    : E_F_F0<R,TA0,RO>(t) , ia(iaa) {assert(iaa<2000000 && iaa >0);}
+  AnyType operator()(Stack s)  const 
+  {
+    // A0 x =  *static_cast<A0 *>(static_cast<void*>(static_cast<char *>(s)+ia));
+    // cout << " opt f (" << x << " ) = "   << ": " << ia << endl; 
+    return SetAny<R>( this->f( *static_cast<typename E_F_F0<R,TA0>::A0 *>(static_cast<void*>(static_cast<char *>(s)+ia))  ) );}  
+  
+};   
+
+template<class R,class TA0,bool RO>   
+   int  E_F_F0<R,TA0,RO>::Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) 
+    {
+       int rr = find(m);
+       if (rr) return rr;
+       return insert(new E_F_F0_Opt<R,TA0,RO>(*this,a->Optimize(l,m,n)),l,m,n);       
+    } 
+// fin modif xlc++ 
+
+template<class A0>
+ class E_VF_F0 :public  E_F0 { public:
+  typedef  void (*func)(  A0 ) ; 
+  func f;
+  Expression a;
+  E_VF_F0(func ff,Expression aa) : f(ff),a(aa) {}
+  AnyType operator()(Stack s)  const 
+    {f(GetAny<A0>( (*a)(s) ));return Nothing;}  
+  bool EvaluableWithOutStack() const 
+      {return a->EvaluableWithOutStack();} // 
+      
+ bool MeshIndependent() const { return a->MeshIndependent();  }    
+
+};
+
+inline int clexico(int i,int j) { return i==0 ? j : i;}
+inline int clexico(int i,int j,int k) { int ll=clexico(i,j);  return  ll==0 ? k : ll;}
+
+template<class R,class TA0,class TA1>
+ class E_F_F0F0 :public  E_F0 { public:
+   template <class T> struct remove_reference     {typedef T type;};
+   template <class T> struct remove_reference<T&> {typedef T type;};
+   typedef typename remove_reference<TA0>::type A0;
+   typedef typename remove_reference<TA1>::type A1;
+   typedef  R (*func)( A0 , A1 ) ;
+    
+  func f;
+  Expression a0,a1;
+  E_F_F0F0(func ff,Expression aa0,Expression aa1) 
+    : f(ff),a0(aa0),a1(aa1) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)) , GetAny<A1>((*a1)(s)) ) );}  
+   bool EvaluableWithOutStack() const 
+      {return a0->EvaluableWithOutStack() && a1->EvaluableWithOutStack();} // 
+   bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent();} // 
+  int compare (const E_F0 *t) const { 
+     int rr;
+    // cout << "cmp " << typeid(*this).name() << " and " << typeid(t).name() << endl;
+     const  E_F_F0F0* tt=dynamic_cast<const E_F_F0F0 *>(t);
+     if (tt && f == tt->f) rr= clexico(a0->compare(tt->a0),a1->compare(tt->a1));
+     else rr = E_F0::compare(t);
+     return rr;
+     } // to give a order in instuction 
+      
+   int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) ;
+    
+};
+
+// modif for xlc++
+template<class R,class TA0,class TA1>
+class E_F_F0F0_Opt: public E_F_F0F0<R,TA0,TA1>  { public :
+  size_t ia,ib;  
+  E_F_F0F0_Opt(const  E_F_F0F0<R,TA0,TA1> &t,size_t iaa,size_t ibb) 
+    : E_F_F0F0<R,TA0,TA1>(t) ,
+      ia(iaa),ib(ibb) {}
+  AnyType operator()(Stack s)  const 
+  {
+    //A0 aa =*static_cast<A0 *>(static_cast<void*>(static_cast<char *>(s)+ia));
+    //A1 bb=*static_cast<A1 *>(static_cast<void*>(static_cast<char *>(s)+ib)) ;
+    //cout << ia << " " << ib <<  "f( " << aa << "," << bb  << " )   = "<< f(aa,bb) << endl;
+    return SetAny<R>( this->f( *static_cast<typename E_F_F0F0<R,TA0,TA1>::A0 *>(static_cast<void*>(static_cast<char *>(s)+ia)) , 
+			 *static_cast<typename E_F_F0F0<R,TA0,TA1>::A1 *>(static_cast<void*>(static_cast<char *>(s)+ib)) ) );}  
+  
+};     
+       
+
+template<class R,class TA0,class TA1>
+   int E_F_F0F0<R,TA0,TA1>::Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) 
+    {
+
+       int rr = find(m);
+       if (rr) return rr;
+
+       return insert(new E_F_F0F0_Opt<R,TA0,TA1>(*this,a0->Optimize(l,m,n),a1->Optimize(l,m,n)),l,m,n);
+    }
+// add modif for xlc++
+
+
+
+template<class R,class A0>
+ class E_F_F0_ :public  E_F0 { public:
+  typedef  R (*func)(const   A0& ) ; 
+  func f;
+  Expression a;
+  E_F_F0_(func ff,Expression aa) : f(ff),a(aa) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>(f(GetAny<A0>( (*a)(s) )));}  
+   bool EvaluableWithOutStack() const 
+      {return a->EvaluableWithOutStack() ;} // 
+   bool MeshIndependent() const 
+      {return a->MeshIndependent();} // 
+    
+};
+// add FH 07/2008  for pmesh clean 
+template<class R,class A0>
+class E_F_F0_Add2RC :public  E_F0 { public:
+    typedef  R (*func)(const   A0& ) ; 
+    func f;
+    Expression a;
+    E_F_F0_Add2RC(func ff,Expression aa) : f(ff),a(aa) {}
+    AnyType operator()(Stack s)  const 
+    {return SetAny<R>(Add2StackOfPtr2FreeRC(s,f(GetAny<A0>( (*a)(s) ))));}  
+    bool EvaluableWithOutStack() const 
+    {return a->EvaluableWithOutStack() ;} // 
+    bool MeshIndependent() const 
+    {return a->MeshIndependent();} // 
+    
+};
+// end add. 
+template<class R,class A0,class E=E_F0>
+ class E_F_F0s_ :public  E { public:
+  typedef  R (*func)(Stack stack,const   A0& ) ; 
+  func f;
+  Expression a;
+  E_F_F0s_(func ff,Expression aa) : f(ff),a(aa) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>(f(s,GetAny<A0>( (*a)(s) )));}  
+//  bool MeshIndependent() const {return true;} // def in E
+
+    operator aType () const { return atype<R>();}         
+    
+};
+
+template<class R,class A0,class A1,class E=E_F0>
+ class E_F_F0F0_ :public  E { public:
+  typedef  R (*func)(const  A0 &,const  A1 & ) ; 
+  func f;
+  Expression a0,a1;
+  E_F_F0F0_(func ff,Expression aa0,Expression aa1) 
+    : f(ff),a0(aa0),a1(aa1) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)) , GetAny<A1>((*a1)(s)) ) );} 
+    bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent();} // 
+ 
+};
+// FH Add 07/2008 
+//   class with add 1 to the refcounter  for  mesh . 
+template<class R,class A0,class A1,class E=E_F0>
+class E_F_F0F0_Add2RC :public  E { public:
+typedef  R (*func)(const  A0 &,const  A1 & ) ; 
+func f;
+Expression a0,a1;
+E_F_F0F0_Add2RC(func ff,Expression aa0,Expression aa1) 
+: f(ff),a0(aa0),a1(aa1) {}
+AnyType operator()(Stack s)  const 
+{return SetAny<R>(Add2StackOfPtr2FreeRC(s, f( GetAny<A0>((*a0)(s)) , GetAny<A1>((*a1)(s)) ) ));} 
+bool MeshIndependent() const 
+{return a0->MeshIndependent() && a1->MeshIndependent();} // 
+
+};
+// FH end 07/2008 
+template<class R,class A0,class A1,class A2,class E=E_F0>
+ class E_F_F0F0F0_ :public  E { public:
+  typedef  R (*func)(const  A0 &,const  A1 & , const A2 &) ; 
+  func f;
+  Expression a0,a1,a2;
+  E_F_F0F0F0_(func ff,Expression aa0,Expression aa1,Expression aa2) 
+    : f(ff),a0(aa0),a1(aa1),a2(aa2) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)) , GetAny<A1>((*a1)(s)),GetAny<A2>((*a2)(s))  ) );}  
+    virtual size_t nbitem() const {return a2->nbitem(); } 
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent();} // 
+
+};
+
+template<class R,class A0,class A1,class A2,class E=E_F0>
+ class E_F_stackF0F0F0_ :public  E_F0mps { public:
+  typedef  R (*func)(Stack, const  A0 &,const  A1 & , const A2 &) ; 
+  func f;
+  Expression a0,a1,a2;
+  E_F_stackF0F0F0_(func ff,Expression aa0,Expression aa1,Expression aa2) 
+    : f(ff),a0(aa0),a1(aa1),a2(aa2) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f(s, GetAny<A0>((*a0)(s)) , GetAny<A1>((*a1)(s)),GetAny<A2>((*a2)(s))  ) );}  
+    virtual size_t nbitem() const {return a2->nbitem(); } 
+   bool MeshIndependent() const { return true;}
+};
+
+template<class R,class A0,class A1>
+ class E_F_F0F0_NC :public  E_F0 { public:
+  typedef  R (*func)(  A0 &,const  A1 & ) ; 
+  func f;
+  Expression a0,a1;
+  E_F_F0F0_NC(func ff,Expression aa0,Expression aa1) 
+    : f(ff),a0(aa0),a1(aa1) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)) , GetAny<A1>((*a1)(s)) ) );}  
+   bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent() ; } // 
+
+};
+
+
+
+
+ class E_F_StackF0F0 :public  E_F0mps { public:
+  typedef   AnyType (*func)(Stack,Expression ,Expression ) ; 
+  func f;
+  Expression a0,a1;
+  E_F_StackF0F0(func ff,Expression aa0,Expression aa1) 
+    : f(ff),a0(aa0),a1(aa1) { }
+  AnyType operator()(Stack s)  const 
+    {return  (*f)(s, a0 , a1) ;}  
+
+};
+
+
+/*
+ class E_F_F0F0_<AnyType,AnyType,AnyType> :public  E_F0 { public:
+  typedef  AnyType (*func)(const  AnyType &,const  AnyType & ) ; 
+  func f;
+  Expression a0,a1;
+  E_F_F0F0_(func ff,Expression aa0,Expression aa1) 
+    : f(ff),a0(aa0),a1(aa1) {}
+  AnyType operator()(Stack s)  const 
+    {return  f( (*a0)(s) , (*a1)(s) );}  
+   bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent() ; } // 
+
+};
+*/
+
+class E_F2_func :public  E_F2 { public:
+   Function2 f;
+   AnyType operator()(Stack s,AnyType & a,AnyType & b)  const {return f(s,a,b);}
+   E_F2_func( Function2 ff) : f(ff) {}
+};
+
+class E_F0_Func1 :public  E_F0 { public:
+   Function1  f;
+   E_F0 *a;
+   AnyType operator()(Stack s)  const {return f(s,(*a)(s));}
+   E_F0_Func1( Function1 f1,E_F0 *aa) : f(f1),a(aa){}
+   bool EvaluableWithOutStack() const {return a->EvaluableWithOutStack();} // 
+   bool MeshIndependent() const {return a->MeshIndependent();} // 
+   int compare (const E_F0 *t) const { 
+     int rr;
+     const  E_F0_Func1* tt=dynamic_cast<const E_F0_Func1 *>(t);
+     if (tt && f == tt->f) rr = a->compare(tt->a);
+     else rr = E_F0::compare(t);
+     if(tt && 0)
+      {
+       cout << "\n\t\t\t -------- " << (void *) f << " " << (void *) tt->f << " rr=" << a->compare(tt->a) << endl;
+       cout << "\t\t\tcmp E_F0_Func1 " << rr <<" << " << *this << " cmp " << *t << " " << tt << ">>\n";
+      }
+     return rr;
+     } // to give a order in instuction 
+  // int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) const;  // build optimisation
+
+    virtual ostream & dump(ostream &ff) const  { ff << "E_F0_Func1 f= " << f << " a= "<< *a << ' '  ;return ff; }
+
+};
+class E_F0_Func2 :public  E_F0 { public:
+   Function2  f;
+   E_F0 *a,*b;
+   AnyType operator()(Stack s)  const {return f(s,(*a)(s),(*b)(s));}
+   E_F0_Func2( Function2 f1,E_F0 *aa,E_F0 *bb) : f(f1),a(aa),b(bb){}
+   bool EvaluableWithOutStack() const 
+     {return a->EvaluableWithOutStack() &&b->EvaluableWithOutStack();} // 
+   bool MeshIndependent() const {return a->MeshIndependent() && b->MeshIndependent();} // 
+
+};
+
+
+
+//  the variable offset / stack (local variable)
+template<class R> class Value1:public E_F0
+ { 
+  size_t offset;
+  public:
+  AnyType operator()(Stack s) const { return SetAny<R*>(static_cast<R *>(static_cast<void *>(  static_cast<char *>(s)+offset)));}
+  Value1(size_t o):offset(o) {}
+};
+
+//  the variable globale
+template<class R> class GValue:public E_F0
+ { 
+  mutable R v;
+  public:
+  AnyType operator()(Stack ) const { return SetAny<R*>(static_cast<R *>(static_cast<void *>(&v)));}
+  GValue(R o):v(o) {}
+  bool EvaluableWithOutStack() const {return true;} // 
+  
+};
+
+//  a constante value 
+template<class R> int ccompare(const R & a,const R& b){ return a==b ?  0 :( a<b ? -1 : +1);}
+template<class R> int ccompare(const complex<R> & a,const complex<R>& b){ 
+  int c=ccompare(a.real(),b.real()); 
+  return c==0 ? ccompare(a.imag(),b.imag()): c ;}
+  
+template<class R> class EConstant:public E_F0
+ { 
+  const R v;
+  public:
+  AnyType operator()(Stack ) const { /*cout << " ()" << v << endl*/;return SetAny<R>(v);}
+  EConstant(const R & o):v(o) { /*cout << "New constant " << o << endl;*/}
+  bool EvaluableWithOutStack() const {return true;} //   
+  operator aType () const { return atype<R>();}
+     bool Zero()const  { return v == R();}
+  int compare (const E_F0 *t) const { 
+        int rr;
+        const  EConstant * tt=dynamic_cast<const EConstant *>(t);
+            if (tt) rr = ccompare(v,tt->v);
+             else rr = E_F0::compare(t);
+         return rr;
+       } 
+   ostream & dump(ostream &f) const { f << " ((" <<typeid(R).name()  << ") " << v << ") " ;return f;}  
+};
+
+
+
+
+
+//  the variable offset / stack (local variable)
+
+ class LocalVariable:public E_F0
+ { 
+  size_t offset;
+  aType t; //  type of the variable just for check  
+  public:
+  AnyType operator()(Stack s) const { 
+    SHOWVERB( cout << "\n\tget var " << offset << " " <<  t->name() << endl);  
+//   return PtrtoAny(static_cast<void *>(static_cast<char *>(s)+offset),t);}
+   return PtrtoAny(Stack_offset<void>(s,offset),t);}
+
+  LocalVariable(size_t o,aType tt):offset(o),t(tt) {throwassert(tt);     
+     SHOWVERB(cout << "\n--------new var " << offset << " " <<  t->name() << endl);
+    }
+};
+
+
+class LocalVariableFES : public LocalVariable { public:
+  size_t data;
+  LocalVariableFES(size_t o,aType tt,const  size_t & d) 
+   : LocalVariable(o,tt),data(d) {}
+  size_t nbitem() const { return data;}
+};
+
+template <class U>
+class LocalVariablePlus : public LocalVariable { public:
+  U data;
+  LocalVariablePlus(size_t o,aType tt,const  U & d) 
+   : LocalVariable(o,tt),data(d) {}
+};
+
+//  global variable bof bof 
+template<class T> class PValue:public E_F0
+ { 
+  T * p;
+  public:
+  AnyType operator()(Stack  ) const { return p;}
+  PValue(T * pp):p(pp) {}
+};
+
+
+//  global variable bof bof
+//  value througth  a pointeur   add F.H  july 2014
+template<class T> class dPValue:public E_F0
+{
+    T * p;
+public:
+    AnyType operator()(Stack  ) const { return SetAny<T>(*p);}
+    dPValue(T * pp):p(pp) {}
+};
+
+template<class R> class PPValue:public E_F0
+ { 
+  R ** p;
+  public:
+  AnyType operator()(Stack ) const { return SetAny<R*>(*p);}
+  PPValue(R ** pp):p(pp) {}
+};
+
+
+template<class R>
+Type_Expr CPValue(R & v)
+ {
+   throwassert(map_type[typeid(R*).name()]);
+  return make_pair(map_type[typeid(R*).name()],new PValue<R>(&v));
+ }
+
+template<class R>
+Type_Expr dCPValue(R * v)
+{
+    throwassert(map_type[typeid(R).name()]);
+    return make_pair(map_type[typeid(R).name()],new dPValue<R>(v));
+}
+template<class R>
+Type_Expr CPPValue(R *& v)
+ {
+   throwassert(map_type[typeid(R*).name()]);
+  return make_pair(map_type[typeid(R*).name()],new PPValue<R>(&v));
+ }
+ 
+template<class R >
+Type_Expr CConstant(const R & v)
+ {
+  throwassert(map_type[typeid(R).name()]);
+  return make_pair(map_type[typeid(R).name()],new  EConstant<R>(v));
+ }
+
+
+/// <<CC_F0>> used in [[file:../lglib/lg.ypp::YYSTYPE]]
+
+class CC_F0 {
+  Expression f;
+  aType r;
+public:
+  void operator=(const C_F0& c) { f=c.f;r=c.r;;} 
+  void operator=(const AC_F0& a) ; //{ f=new E_Array(a); f= atype<E_Array>();};
+  void operator=(long ) {f=0;r=0;}
+  void operator=(const CListOfInst& c);//{ C_FO cc=c;f=cc.f;r=cc.r}
+  operator C_F0 () const {return C_F0(f,r);}
+  bool Empty() const {return !f || f->Empty();}
+  aType left() const {return r;}
+ // operator const C_F0 &() const {return  *this;}
+};
+
+/// <<ListOfInst>>
+
+class ListOfInst :
+  public E_F0mps /*[[E_F0mps]]*/
+{ 
+  int n;
+  Expression   *   list;
+  int   *   linenumber;
+  const int nx;
+public:
+  ListOfInst():n(0),list(0),linenumber(0),nx(10){}
+  ListOfInst(int nn):n(0),list(0),linenumber(0),nx(nn?nn:10){}
+  void Add(const C_F0 & ins); 
+
+  /// <<ListOfInst::operator()>> implemented at [[file:AFunction2.cpp::ListOfInst::operator()]]
+
+  AnyType operator()(Stack s) const; 
+
+  operator aType () const { return n ? (aType) * (list[n-1]) : atype<void>();} 
+   
+  Expression &operator[](int i){return list[i];}
+  bool empty() const {return n==0;}
+  int size() const {return n;}
+  Expression * ptr() const {return list;}
+  int * nlines() const {return linenumber;}
+
+  ~ListOfInst(){
+    cout << " ----- ~ListOfInst " << endl;
+    if(list) delete [] list;
+    list=0;
+    if(linenumber)  delete[] linenumber;
+    linenumber=0;
+  }
+};
+
+/// <<CListOfInst>> used in [[file:../lglib/lg.ypp::YYSTYPE]]
+
+class CListOfInst{
+private:
+
+    /// class [[ListOfInst]]
+    ListOfInst * f;
+
+  const basicForEachType *r;
+
+public:
+  void operator=(const CC_F0 &a){
+    f=new ListOfInst();     
+    if( !a.Empty() ) {
+      f->Add(a);
+      r=a.left(); }}
+  CListOfInst & operator+=(const CC_F0 & a);//{ if( !a.Empty()){ f->Add(a);r=a.left();};return *this;} 
+  operator C_F0 () const  { return C_F0(f,r);}
+
+  /// <<CListOfInst::eval>> Called by yyparse() at [[file:../lglib/lg.ypp::start_symbol]] to evaluate the
+  /// complete expression tree when reaching the end of its "start" symbol. It calls ListOfInst::operator()() at
+  /// [[ListOfInst::operator()]] for its private [[ListOfInst]] pointer #f.
+
+  void eval(Stack s) {(*f)(s);}
+
+  int size() const {return f->size();}
+  Expression * ptr() const {return f->ptr();}
+  int * nlines() const { return f->nlines();}
+};
+
+
+AnyType FWhile(Stack ,E_F0 * test,E_F0 * ins);
+AnyType FFor(Stack s ,E_F0 * i0,E_F0 * i1,E_F0 * i2,E_F0 * ins);
+AnyType FIf(Stack s ,E_F0 * test,E_F0 * i1,E_F0 * i2,E_F0 * notuse);
+AnyType TTry(Stack s ,E_F0 * i0,E_F0 * i1,E_F0 * i2,E_F0 * notuse);
+
+
+/// <<Global>> Contains all FreeFem++ language keywords. Definition in [[file:global.cpp::Global]], uses
+/// [[TableOfIdentifier]]
+
+extern TableOfIdentifier Global;
+
+void ShowType(ostream & );
+
+template<class T> 
+inline C_F0 to(const C_F0 & a) { return map_type[typeid(T).name()]->CastTo(a);}
+
+
+/*
+inline C_F0 toBool(const C_F0 & a)    {return ATYPE(bool)->CastTo(a);}
+inline C_F0 toInt(const C_F0 & a)     {return ATYPE(int)->CastTo(a);}
+inline C_F0 toLong(const C_F0 & a)    {return ATYPE(long)->CastTo(a);}
+inline C_F0 toDouble(const C_F0 & a)  {return ATYPE(double)->CastTo(a);}
+inline C_F0 toComplex(const C_F0 & a)  {return ATYPE(Complex)->CastTo(a);}
+*/
+inline C_F0 While(C_F0 test,C_F0 ins) {return C_F0(new E_F0_CFunc2(FWhile,to<bool>(test),ins),0);}
+inline C_F0 For(C_F0 i0,C_F0 i1,C_F0 i2,C_F0 ins) {return C_F0(new E_F0_CFunc4(FFor,i0,to<bool>(i1),i2,ins),0);}
+inline C_F0 Try(C_F0 i0,C_F0 i1,C_F0 i2)  {return C_F0(new E_F0_CFunc4(TTry,i0,i1,i2,0),0);}
+inline C_F0 FIf(C_F0 i0,C_F0 i1,C_F0 i2) {return C_F0(new E_F0_CFunc4(FIf,to<bool>(i0),i1,i2,0),0);}
+inline C_F0 FIf(C_F0 i0,C_F0 i1) {return C_F0(new E_F0_CFunc4(FIf,to<bool>(i0),i1,0,0),0);}
+//inline  C_F0 C_F0::PtrValue() const{ 
+//   if (!(r && r->un_ptr)) { cerr << "PtrValue: Not a Left value " << *r << endl;CompileError();} 
+//   return C_F0(new  E_F0_Func1(r->un_ptr->f,f),r->un_ptr->r);}
+
+/// <<basicAC_F0>>
+
+class basicAC_F0 {
+//  version de base d'un tableau d'un parametres  
+//   pour les operateurs unaire, binaire, , 
+//   pas d'allocation 
+  friend class E_Array; // for mapping fonction 
+  protected:
+  typedef const C_F0 const_C_F0;
+ int nb;
+ C_F0 *a;
+ public:
+  typedef map<const char *,C_F0,Keyless> maptype ;
+  typedef maptype::iterator iterator;
+  typedef maptype::const_iterator const_iterator;
+  maptype * named_parameter;
+ basicAC_F0 & operator=(int i) {throwassert(i==0);named_parameter=0,nb=0;return *this;} // pas de parametres
+ basicAC_F0 & operator=(C_F0 & c) {named_parameter=0;nb=1;a=&c;return *this;}
+ basicAC_F0 & operator=(pair<int,C_F0*> p)  {named_parameter=0;nb=p.first;a=p.second;return *this;} 
+ const C_F0 & operator [] (int i) const {throwassert(a && i<nb);return a[i];}
+ int size() const {return nb;}
+ C_F0 * ptr() const  {return a;}
+ C_F0  find(const char * k) const  { 
+    assert(k);  
+   if (named_parameter) { const_iterator i=named_parameter->find(k) ;
+    if (i == named_parameter->end() ) return C_F0();
+    else  return i->second;}
+   else return C_F0();} 
+   
+ struct name_and_type{ 
+  const char * name;
+  const type_info * type;
+ } ;
+ 
+  void SetNameParam(int n=0,name_and_type *l=0 , Expression * e=0) const ;
+};
+
+/// <<AC_F0>> array of parameters for FF language operators. uses [[basicAC_F0]]
+
+class AC_F0: public basicAC_F0 { //  a Array of C_F0
+//    tableau d'un parametres  max 1024 parametres 
+//    avec allocation  
+ const static  int MaxSize;
+ //  no constructor in this class (this class is in a union )
+  public:
+  AC_F0 & operator=(pair<const char *,const C_F0> p) {
+    named_parameter=0; a=new C_F0[MaxSize]; nb=0;Add(p.first,p.second);return *this;}
+  AC_F0 & operator+=(pair<const char *,const C_F0> p) {Add(p.first,p.second);return *this;} 
+
+  AC_F0 & operator=(long k) {throwassert(k==0);named_parameter=0;a=new C_F0[MaxSize]; nb=0;return *this;}     
+  AC_F0 & operator=(const C_F0& c) {named_parameter=0; a=new C_F0[MaxSize]; nb=0;a[nb++]=c;return *this;} 
+  AC_F0 & operator+=(const C_F0& c) { 
+       if ( ! (a&& nb<MaxSize))
+         CompileError("Sorry  number of parameters > 1024");
+       a[nb++]=c;return *this;} 
+  AC_F0 & Add(const char * nm,const C_F0 &c)  {
+     if (!named_parameter) named_parameter=new maptype();
+    iterator i=named_parameter->find(nm);
+    if(i==named_parameter->end()) named_parameter->insert(make_pair(nm,c));
+    else {cerr << " the named in the list already exists "<< nm <<endl; CompileError();}
+    return *this;}
+  int size() const {return nb;}
+  const C_F0 & operator [] (int i) const {throwassert(a && i<nb);return a[i];}
+  void destroy() {
+      
+        nb=0;       
+        if(named_parameter) 
+          delete named_parameter;
+        if (a)
+           delete []  a;
+        a=0;named_parameter=0;}
+  
+}; 
+
+class  basicAC_F0_wa : public basicAC_F0 { public:
+ basicAC_F0_wa(const C_F0 & e) {
+   named_parameter=0;
+   nb=1;
+   a= new C_F0[nb];
+   a[0]=e;
+ }
+ basicAC_F0_wa(const C_F0 & e,const C_F0 & ee) {
+   named_parameter=0;
+   nb=2;
+   a= new C_F0[nb];
+   a[0]=e;
+   a[1]=ee;
+ }
+ 
+
+ basicAC_F0_wa(C_F0 e,const basicAC_F0 & b) { 
+   named_parameter=0;
+   if (b.named_parameter) named_parameter = new maptype(*b.named_parameter);
+   nb=1+b.size();
+   a= new C_F0[nb];
+   a[0]=e;
+   for (int i=1;i<nb;i++) a[i]=b[i-1];}
+    ~basicAC_F0_wa(){delete [] a;
+        a=0;
+        delete named_parameter;
+        named_parameter=0;}
+ 
+
+ basicAC_F0_wa(const basicAC_F0 & b) { 
+   named_parameter=0;
+   if (b.named_parameter) named_parameter = new maptype(*b.named_parameter);
+   nb=b.size();
+   a= new C_F0[nb];
+   for (int i=0;i<nb;i++) a[i]=b[i];}
+   
+  private: 
+   void operator=(const basicAC_F0 & b);
+};
+
+
+
+class E_Array  :public E_F0 {  public: 
+  basicAC_F0_wa *v;// the value
+  E_Array(const basicAC_F0 & aa) : v(new basicAC_F0_wa(aa))  {throwassert(v);}
+  AnyType operator()(Stack)  const {
+     cerr << " No evaluation of an E_array" << endl;
+     throwassert(0);
+     return  Nothing;}
+ const C_F0 & operator [] (int i) const {throwassert(v );return (*v)[i];}
+ int size() const {return v->size();}
+ size_t nbitem() const {return v->size();}
+ void map(C_F0 (*mapping)(const C_F0 & )) const 
+   { for (int i=0;i<v->size();i++) 
+      v->a[i]=(*mapping)(v->a[i]);}
+  virtual bool MeshIndependent() const {
+    for (int i=0;i<v->size();i++) 
+      if (v->a[i].MeshIndependent()) return false;
+     return false;
+   
+  } // 
+  operator aType () const { return atype<void>();} 
+ 
+  };
+class PlotStream;  
+class E_Border ;
+class E_BorderN :public E_F0mps { public: 
+   const E_Border * b;
+   int cas;// 0 long , 1, KN_ , 2 : Array // FH april 14 ..
+   Expression  n;
+   const E_BorderN * next;
+    
+    static   int Cas(C_F0  nn)
+    {
+        if( atype<long>()->CastingFrom(nn.left())) return 0;
+        else if(atype<KN_<long> >()->CastingFrom(nn.left())) return 1;
+        else if( atype< const E_Array * >()->CastingFrom(nn.left())  )
+        {
+            E_Array & a =  *dynamic_cast< E_Array *>((Expression) nn);
+            ffassert(a);
+            a.map(::to<long>);
+            //   a[i]=CastTo<long>(a[i]);
+            return 2;
+        }
+        else CompileError(" Number of element of a border ( longn , int array, [ ] array ");
+        return -1; // bug
+    }
+    E_BorderN(const E_Border *  bb, C_F0  nn,const E_BorderN * nx=0) ;
+    E_BorderN(const E_BorderN & bb,const E_BorderN * nx)
+    : b(bb.b),n(bb.n),cas(bb.cas),next(nx)
+    {
+      int kk=1;
+	if(bb.next) {// modif FH. 13/02/2008
+	       
+	    const E_BorderN ** pnext = &next;
+	    E_BorderN  *pp;
+	    next = bb.next;  // copy bb;       
+	    for(int step=0;step<2;++step)
+	    {
+	      while (*pnext)
+	       {
+		 kk++;
+		 pp = new E_BorderN(**pnext); // copy 
+		 *pnext = pp;
+		 pnext = & pp->next;
+	       }
+	      if(step==0)
+	       *pnext= nx;  // copy de nx
+	    }
+	   // cout << "  BorderN : nb item : " << kk << " == " << size()<< endl;  
+	}
+    }   
+    AnyType operator()(Stack)  const {
+     return  SetAny<const  E_BorderN *>(this);}  
+  operator aType () const { return atype<const  E_BorderN *>();}         
+    int size() const { int k=0;for(const E_BorderN  *pp=this;pp; pp=pp->next) k++; return k;}  
+   E_BorderN * operator+( const E_BorderN & bb)  const 
+   { throwassert(bb.next==0);
+     return new E_BorderN(bb,this);}
+
+static C_F0 to(int cas, C_F0 nn)
+    {
+        if(cas==0) return ::to<long>(nn);
+        else if(cas ==1) return ::to<KN_<long> >(nn);
+        else if(cas == 2) return ::to<E_Array> (nn);
+        else ffassert(0); // Big bug .. FH ..
+    }
+  long Nbseg(Stack stack,int index) const {
+      if(cas==0) {assert(index==0);  return GetAny<long>((*n)(stack));}
+      else if (cas==1 ) return  (GetAny<KN_<long> >((*n)(stack)))(index);
+      else if (cas==2)  {E_Array & a =  *dynamic_cast< E_Array *>((Expression) n);assert(a); Expression nn= a[index]; return  GetAny<long>((*nn)(stack));}
+      else return 0;
+  }
+  long NbBorder(Stack stack) const {
+       if(cas==0) return 1;
+      else if (cas==1 ) return  GetAny<KN_<long> >((*n)(stack)).N();
+      else if (cas==2)  return dynamic_cast<const E_Array *>(n)->size();
+      else return 0;
+  } //GetAny<long>((*n)(stack));}
+    
+  double from(Stack stack) const ;//{ return GetAny<double>((*n)(stack));}
+  double to(Stack stack) const ;//{ return GetAny<double>((*b)(stack));}
+  long * index(Stack stack) const ;//{ return GetAny<double>((*b)(stack));}
+  double * var(Stack stack) const ;//{ return GetAny<double*>((*n)(stack));}
+  void code(Stack stack) const ;
+  long label()const  ;
+  void Plot(Stack stack) const ;
+  void SavePlot(Stack stack,PlotStream & plot ) const;
+    
+  void BoundingBox(Stack stack,double  &xmin,double & xmax, double & ymin,double & ymax) const ;
+};
+
+class AddBorderOperator: public  OneOperator{
+  typedef const E_BorderN * A;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     {
+       A a0=dynamic_cast<A>((Expression) args[0]);
+       A a1=dynamic_cast<A>((Expression) args[1]);
+       ffassert( a0 && a1);
+       //ffassert(a1->next==0);  // change FH 13/02/2008
+       return  new E_BorderN(*a1,a0);} 
+    AddBorderOperator(): 
+      OneOperator(map_type[typeid(A).name()],map_type[typeid(A).name()],map_type[typeid(A).name()])
+      {pref = 0;}
+
+};
+
+
+class  OneOperator_borderN : public OneOperator {public:
+    const  E_Border * theborder;int cas;
+    E_F0 * code(const basicAC_F0 & a) const 
+     { return  new E_BorderN(theborder,a[0]);} 
+    OneOperator_borderN(const  E_Border * b)
+      : OneOperator(atype<const E_BorderN *>(),atype<long>()),
+      theborder(b),cas(0){}
+    OneOperator_borderN(const  E_Border * b,int )
+    : OneOperator(atype<const E_BorderN *>(),atype<KN_<long> >()),
+    theborder(b),cas(1){}
+    OneOperator_borderN(const  E_Border * b,int,int )
+    : OneOperator(atype<const E_BorderN *>(),atype<E_Array >()),
+    theborder(b),cas(2){}
+    
+};
+
+class E_Border  :public Polymorphic  {  public: 
+  static basicAC_F0::name_and_type name_param[] ;
+  static const int n_name_param =0;
+  static long Count;
+  Expression xvar,xfrom,xto,xcode,xindex;
+  basicAC_F0_wa * tab;
+  long label;
+  E_Border(const E_Array * a) : 
+    xvar(0),xfrom(0),xto(0),xcode(0),xindex(0), tab(a? a->v:0) ,label(++Count)
+  {
+    assert(tab); 
+    Add("(",new OneOperator_borderN(this));
+    Add("(",new OneOperator_borderN(this,1));
+    Add("(",new OneOperator_borderN(this,1,1));
+      /* A FAIRE pour multy border ****/
+  }
+  
+  E_Border(const basicAC_F0 & aa) :    
+    xvar(to<double*>(aa[0])),
+    xfrom(to<double>(aa[1])),
+    xto(to<double>(aa[2])),
+    xcode(aa[aa.size()-1].LeftValue()),
+    xindex( (aa.size() > 4) ? (Expression) to<long*>(aa[3]) : 0 ),
+    //xindex( to<long*>(aa[3])  ),
+    tab(0),
+    label(++Count)
+  {
+    Add("(",new OneOperator_borderN(this));
+    Add("(",new OneOperator_borderN(this,1));
+    Add("(",new OneOperator_borderN(this,1,1));
+  }
+
+  AnyType operator()(Stack)  const {
+    return  SetAny<const  E_Border *>(this);}
+  double length(Stack ) const { ffassert(0);return 0.0; /* a faire */ }
+};
+  
+inline  E_BorderN::E_BorderN(const E_Border *bb, C_F0  nn,const E_BorderN * nx)
+:b(bb),cas(Cas(nn)),n(to(cas,nn) ),next(nx) { /* cout << "  -- E_BorderN  : cas " << cas << endl; */ throwassert(b);}
+
+inline  double E_BorderN::from(Stack stack) const { return b->xfrom ? GetAny<double>((*b->xfrom)(stack)): double(0.0);}
+inline  double  E_BorderN::to(Stack stack) const { return b->xto? GetAny<double>((*b->xto)(stack)): b->length(stack) ;}
+inline  double *  E_BorderN::var(Stack stack) const { return b->xvar ? GetAny<double*>((*b->xvar)(stack)): (double*) 0 ;}
+inline  long *  E_BorderN::index(Stack stack) const { return b->xindex ? GetAny<long*>((*b->xindex)(stack)): (long*) 0 ;}
+inline  void  E_BorderN::code(Stack stack)const { (*b->xcode)(stack);}
+inline  long  E_BorderN::label()const { return b->label;}
+
+inline ArrayOfaType::ArrayOfaType(const basicAC_F0 & aa) : n(aa.size()),t(n ? (n<=4 ? tt : new aType[n]):0),ellipse(false) { 
+   for (int i=0;i<n;i++) t[i]=aa[i].left();}
+   
+inline ArrayOfaType::ArrayOfaType(const ArrayOfaType & aa) : n(aa.n),t(n<=4?tt:new aType[n]),ellipse(aa.ellipse) { 
+   for (int i=0;i<n;i++) t[i]=aa.t[i];}   
+
+
+inline C_F0 TableOfIdentifier::Find(const char * name) const  {
+    const_iterator i=m.find(name); 
+    if ( i == m.end()) { return C_F0();}
+    else return C_F0(i->second);}
+
+inline C_F0 TableOfIdentifier::Find(const char * name,const basicAC_F0 & args) const  {
+    const_iterator i=m.find(name); 
+    if ( i == m.end()) {cerr<<"No operator " << name<<endl;
+    cerr <<*this << endl;CompileError("TableOfIdentifier::Find");return C_F0();}
+    else {return C_F0(C_F0(i->second),"(",args);}}
+//  Attention il y a moralement un bug
+//  les initialisation   x = y   ( passe par l'operateur binaire <-  dans TheOperators
+//   les initialisation   x(y)   ( passe par l'operateur unaire <-  du type de x
+//   -------
+
+inline size_t align8(size_t &off) 
+{ 
+  size_t o= off %8 ;
+  off += o ? 8-o : 0;
+ return off;
+}
+
+
+template<class T>
+inline Type_Expr  NewVariable(aType t,size_t &off) 
+{ 
+   size_t o= align8(off);//  align    
+ //  off += t->un_ptr_type->size;
+ // bug    off += t->size;
+   off += t->un_ptr_type->size; // correction 16/09/2003 merci � Richard MICHEL
+   return  Type_Expr(t,new T(o,t));
+} 
+
+template<class T>
+inline Type_Expr  NewVariable(aType t,size_t &off,const basicAC_F0 &args) 
+{ 
+   size_t o= align8(off);//  align    
+   off += t->un_ptr_type->size;
+   return  Type_Expr(t,new T(o,t,args));
+}
+
+template<class T,class U>
+inline Type_Expr  NewVariable(aType t,size_t &off,const U & data) 
+{ 
+   size_t o= align8(off);//  align    
+   off += t->un_ptr_type->size;
+   return  Type_Expr(t,new T(o,t,data));
+}
+
+template<class T>   
+inline  C_F0 TableOfIdentifier::NewVar(Key k,aType t,size_t & top,const C_F0 &i) 
+   { 
+     return C_F0(TheOperators,"<-",New(k,NewVariable<T>(t,top)),i);}
+
+template<class T>   
+inline  C_F0 TableOfIdentifier::NewVar(Key k,aType t,size_t & top,const basicAC_F0 &args) 
+   {  
+ //      return C_F0(TheOperators,"<-",New(k,NewVariable(t,top)),t->Find("<-",args));}
+        return C_F0(TheOperators,"<-",basicAC_F0_wa(New(k,NewVariable<T>(t,top)),args));}
+        
+template<class T>   
+inline  C_F0 TableOfIdentifier::NewFESpace(Key k,aType t,size_t & top,const basicAC_F0 &args) 
+   {  
+        return C_F0(TheOperators,"<-",basicAC_F0_wa(New(k,NewFESpace<T>(t,top,args)),args));}
+        
+
+template<class T,class U>   
+inline  C_F0 TableOfIdentifier::NewVar(Key k,aType t,size_t & top,const basicAC_F0 &args,const U & data) 
+   {  
+ //      return C_F0(TheOperators,"<-",New(k,t->NewVar(top)),t->Find("<-",args));}
+        return C_F0(TheOperators,"<-",basicAC_F0_wa(New(k,NewVariable<T,U>(t,top,data)),args));}
+   
+//inline  C_F0 TableOfIdentifier::NewVar(Key k,aType t,size_t & top,const AC_F0 &args,const C_F0& ) 
+//   {   throwassert(0); return C_F0(TheOperators,"<-",New(k,NewVariable(t,top)),t->Find("<-",args));}
+
+template<class T>   
+inline  C_F0 TableOfIdentifier::NewVar(Key k,aType t,size_t & top) 
+   {  return t->Initialization(New(k,NewVariable<T>(t,top))); }
+
+// save a expression 
+inline  C_F0 TableOfIdentifier::NewID(aType r,Key k, C_F0 & c,size_t &top, bool del ) 
+   {  New(k,(make_pair<aType, E_F0  *>(c.left(),c.LeftValue())),del);return 0; }
+ //  { return r->Initialization(New(k,r->SetParam(c,ListOfId(),top),del));}
+
+inline  C_F0 TableOfIdentifier::NewID(aType r,Key k, C_F0 & c,const ListOfId & l,size_t & top,bool del) 
+   { return r->Initialization(New(k,r->SetParam(c,&l,top),del));}
+   
+/// <<tables_of_identifier>> allocated at [[file:global.cpp::tables_of_identifier]]
+
+typedef list<TableOfIdentifier *> ListOfTOfId;    
+extern list<TableOfIdentifier *> tables_of_identifier;
+
+/// [[file:AFunction2.cpp::Find]]
+
+C_F0 Find(const char * name);
+  
+inline  C_F0 basicForEachType::Find(const char * k) const
+  {  C_F0 r( ti.Find(k));
+     //if (r.Empty()) {cerr << " no member " <<k << " in type " << name() << endl; CompileError("  ");}
+     return r; }
+inline C_F0  basicForEachType::Find(const char * k,const basicAC_F0 & args) const {return ti.Find(k,args);}
+inline  C_F0 basicForEachType::Initialization(const Type_Expr & e) const 
+  {
+     if(!InitExp) 
+       { 
+          cerr << "Internal Error: No Way to m Initialize this var type " << *this << endl;
+          CompileError();
+       }
+   return C_F0(new  E_F0_Func1(InitExp,e.second),this);        
+  }
+  
+
+    
+//inline  AnyType Args2(const AnyType &,const  AnyType & b) {return b;}
+class E_comma : public E_F0 {public:
+   Expression a,b;
+   E_comma(Expression aa,Expression bb) : a(aa),b(bb) {}
+   AnyType operator()(Stack s) const  { (*a)(s); return (*b)(s);}
+   bool MeshIndependent() const {
+    return a->MeshIndependent() && b->MeshIndependent();}
+} ;
+
+inline	  C_F0::C_F0(const C_F0 & a,const C_F0 & b)  
+  { // the concatenation 
+      if (a.Empty())
+         {r=b.r,f=b.f;}
+      else if (b.Empty())
+         {r=a.r,f=b.f;}
+      else 
+        {r=b.r;
+        f= new E_comma(a.f,b.f);}
+  }
+
+inline	  C_F0::C_F0(const C_F0 & e,const char *op, AC_F0 & p)  
+   {    *this=C_F0(e,op,(const basicAC_F0 &) p);
+        p.destroy();
+   }          
+inline	  C_F0::C_F0(const Polymorphic * poly,const char *op, AC_F0 & p)
+   {    *this=C_F0(poly,op,(const basicAC_F0 &) p);
+        p.destroy();
+   }          
+
+inline	  C_F0::C_F0(const C_F0 & e,const char *op,const basicAC_F0 & p)  
+	   { 
+	     const Polymorphic * pop=e;
+	     if (pop) 
+	      {
+	      //cerr << "poly: " <<  *pop << endl;
+	      *this=C_F0(pop,op,p);
+	      }
+	     else { 
+	      // cerr << *e.r << " : table  " << endl;
+	      // e.r->ShowTable(cerr);
+	       C_F0 x=e.r->Find(op);
+	       
+	       pop=x;
+	       if(pop) 
+	       	 {  
+	       	   basicAC_F0_wa ep(e,p);       
+	           *this=C_F0(pop,"",ep); 
+	         } 
+	       else
+	        {
+	           cerr << " unknown operator " << op << " on type " << *e.r << endl;
+	           CompileError();
+	        }}	       
+	   }
+
+inline	  C_F0::C_F0(const C_F0 & e,const char *op,const C_F0 & a,const C_F0 & b)  
+{
+    C_F0 tab[2]={a,b};
+    basicAC_F0  p;
+    p=make_pair(2,tab);
+    *this= C_F0(e,op,p);
+}
+	   
+/// <<C_F0_constructor_char_C_F0_impl>>
+inline	  C_F0::C_F0(const C_F0 & e,const char *op,const C_F0 & ee)  
+{
+  const Polymorphic * pop=e;
+  if (pop) 
+    {
+      // calls [[C_F0_constructor_binary_decl]]
+      *this=C_F0(pop,op,e,ee);
+    }
+  else { 
+    // cerr << *e.r << " : table  " << endl;
+    // e.r->ShowTable(cerr);
+    C_F0 x=e.r->Find(op);       
+    pop=x;
+    if(pop) 	         
+      *this=C_F0(pop,"",e,ee);  
+    else
+      {
+	cerr << " unknown operator " << op << " on type " << *e.r << " " << *ee.r<<  endl;
+	CompileError();
+      }
+  }	       
+}
+	   
+inline	  C_F0::C_F0(const C_F0 & e,const char *nm)  
+	   { 
+	    // cerr << "  C_F0(const C_F0 & e,const char *item) : "   <<  " " << nm << endl;
+	     C_F0 x=e.r->Find(nm); 
+	     const Polymorphic * pop=x;
+	     // cerr << "Find " << *pop << endl;
+	     if (pop) 
+	       *this=C_F0(pop,".",e); //  unary oper . 
+	     else 
+	       {
+	           cerr << " No operator ." << nm << " for type " << *e.r  <<  endl;
+	          lgerror("");	          	        
+	       }
+	       
+	   }
+inline  E_F0 * C_F0::LeftValue() const {
+    return f;
+}
+
+/*inline Type_Expr C_F0::SetParam(const ListOfId * l,size_t & top) const {
+    return r->SetParam(*this,l,top);
+}*/
+
+
+/// Declaration of TypeArray
+aType TypeArray(aType,aType);
+aType TypeArray(aType c,aType b,aType a);
+
+/// Declaration of TypeTemplate
+aType TypeTemplate(aType,aType);
+
+void Init_map_type();
+
+/// <<Block>>
+
+class Block { //
+   static size_t Max(size_t a,size_t b){ return a < b ? b :a;}
+   typedef const char *  Key;
+   Block * fatherblock;
+   size_t  top,topmax;
+   TableOfIdentifier table;
+   ListOfTOfId::iterator itabl;    
+public:
+   //  list of variable
+   size_t OffSet(size_t ssize) {
+      top=align8(top);
+     size_t r=top;  top+=ssize ;topmax=Max(topmax,top);
+     return r;}
+   Block(Block * f=0);
+/*   :fatherblock(f),top(f?f->top:BeginOffset*sizeof(void*)),topmax(top)
+    {     
+      itabl=tables_of_identifier.insert(tables_of_identifier.begin(),&table);
+    }*/ 
+   size_t size() const { return Max(topmax,top);}
+  void Add(Key k,Key op,OneOperator *p0)  
+    { table.Add(k,op,p0);}
+   
+template<class T>   
+   C_F0 NewVar(Key k,aType t,const C_F0 &i) 
+     {return table.NewVar<T>(k, t,top,i);}
+template<class T>   
+   C_F0 NewFESpace(Key k,aType t,const basicAC_F0 &args) 
+     {return table.NewFESpace<T>(k, t,top,args);}
+template<class T>   
+   C_F0 NewVar(Key k,aType t, AC_F0 &args) 
+     {C_F0 r= table.NewVar<T>(k, t,top,args);
+      args.destroy();
+      topmax=Max(topmax,top);
+      return r;}
+template<class T>   
+   C_F0 NewVar(Key k,aType t,const basicAC_F0 &args) 
+     {C_F0 r= table.NewVar<T>(k, t,top,args);
+      topmax=Max(topmax,top);
+      return r;}
+template<class T,class U>   
+   C_F0 NewVar(Key k,aType t,const basicAC_F0 &args,const U & data) 
+     {C_F0 r= table.NewVar<T,U>(k, t,top,args,data);
+      topmax=Max(topmax,top);
+      return r;}
+//   C_F0 NewVar(Key k,aType t,const AC_F0 &args,const C_F0 & f) 
+//     {return table.NewVar(k, t,top,args,f);}
+template<class T>   
+   C_F0 NewVar(Key k,aType t) 
+     {C_F0 r= table.NewVar<T>(k, t,top);
+      topmax=Max(topmax,top);
+      return r;
+      }
+
+  // C_F0 NewVar(aType t,Key k,C_F0 f) 
+  //   {return table.NewVar(t,k, f);}
+  C_F0 NewID(aType t,Key k,C_F0 f,bool del=true) 
+     {C_F0 r= table.NewID(t,k, f,top,del);
+      topmax=Max(topmax,top);
+      return r;}
+  C_F0 NewID(aType t,Key k,C_F0 f,const ListOfId & l,bool del=true) 
+     {C_F0 r= table.NewID(t,k,f,l,top,del);
+      topmax=Max(topmax,top);
+      return r;}
+
+ static   Block * open(Block *& c); 
+   CC_F0  close(Block *& c); /* {
+     tables_of_identifier.erase(itabl);      
+     c=fatherblock;
+     if (fatherblock) {fatherblock->topmax=topmax;
+                       fatherblock->top=top;}
+        
+     CC_F0 r;
+     r = table.destroy();
+     delete this;
+     return r;}*/
+   C_F0 Find(const char * k) const  {return table.Find(k);}
+   
+   ~Block(); //{} 
+}; 
+
+
+
+/// <<OneOperator1>> To know the meaning of OneOperator name extensions, see [[OneOperator]]. The template arguments to
+/// OneOperator classes are identical to the types of the arguments of the C++ function that is called from the
+/// class. The matrices are of type KNM<double>* or KNM<double>** (for left-side expressions, but this is "more
+/// tricky") which correspond to a real[int,int] in the edp script.
+
+template<class R,class A=R,class CODE=E_F_F0<R,A> >
+class  OneOperator1 : public OneOperator {
+    aType r,t0; //  return type
+    typedef typename CODE::func func; // R (*func)(A) ; 
+    func  f;
+    public: 
+
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new CODE(f,t0->CastTo(args[0]));} 
+     
+    OneOperator1(func  ff,int ppref=0): 
+      OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()]),
+    t0( map_type[typeid(A).name()] ), f(ff) {pref=ppref;}
+      
+    OneOperator1(func  ff,aType tt0,int ppref=0): 
+      OneOperator(map_type[typeid(R).name()],tt0),
+      t0( map_type[typeid(A).name()] ), f(ff) {pref=ppref;}
+};
+
+
+template<class R,class A=R,class B=A,class CODE=E_F_F0F0<R,A,B> >
+class  OneOperator2 : public OneOperator {
+    aType r,t0,t1; //  return type 
+    typedef typename CODE::func func;
+    func f;
+    public: 
+
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new CODE(f,t0->CastTo(args[0]),t1->CastTo(args[1]));} 
+
+    OneOperator2(func  ff): 
+      OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()],map_type[typeid(B).name()]),
+      t0( map_type[typeid(A).name()] ),t1(map_type[typeid(B).name()] ), f(ff) {}
+      
+    OneOperator2(func  ff,aType tt0,aType tt1): 
+      OneOperator(map_type[typeid(R).name()],tt0,tt1),
+      t0( map_type[typeid(A).name()] ),t1(map_type[typeid(B).name()] ), f(ff) {}
+      
+};
+
+/*template<typename C>
+struct OneBinaryOperator_Traits {
+  typedef C::result_type R;
+  typedef C::first_argument_type A;
+  typedef C::second_argument_type B;
+};*/
+
+template<class A,class B>  struct SameType { static const int OK=0;};
+template<class A>  struct SameType<A,A> { static const int OK=1;};
+template<>  struct SameType<bool,bool> { static const int OK=10;};
+template<>  struct SameType<long,long> { static const int OK=20;};
+template<>  struct SameType<double,double> { static const int OK=30;};
+template<>  struct SameType<Complex,Complex> { static const int OK=40;};
+template<>  struct SameType<string*,string*> { static const int OK=50;};
+
+template <typename Arg1, typename Arg2,typename Arg3, class Result>
+struct ternary_function
+{
+	typedef Arg1   first_argument_type;
+	typedef Arg2   second_argument_type;
+	typedef Arg3   third_argument_type;
+	typedef Result result_type;
+};
+
+template <typename Arg1, typename Arg2,typename Arg3,typename Arg4 , class Result>
+struct quad_function
+{
+	typedef Arg1   first_argument_type;
+	typedef Arg2   second_argument_type;
+	typedef Arg3   third_argument_type;
+	typedef Arg4   fourth_argument_type;
+	typedef Result result_type;
+};
+
+template<typename T,class CODE >
+class  OneTernaryOperator : public OneOperator{
+  typedef typename T::result_type R;
+  typedef typename T::first_argument_type A;
+  typedef typename T::second_argument_type B;
+  typedef typename T::third_argument_type C;
+
+    class Op : public E_F0 {
+      typedef  typename C::result_type Result;
+         Expression a,b,c;
+       public:
+       AnyType operator()(Stack s)  const 
+        {return  SetAny<R>(static_cast<R>(C::f( GetAny<A>((*a)(s)) ,
+                                                GetAny<B>((*b)(s)) ,
+                                                GetAny<C>((*c)(s)))));}
+       Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc) {} 
+       bool MeshIndependent() const {
+       return a->MeshIndependent() && b->MeshIndependent() && c->MeshIndependent();}
+    };
+
+   public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new CODE(t[0]->CastTo(args[0]),t[1]->CastTo(args[1]),t[2]->CastTo(args[2]));} 
+    OneTernaryOperator(): 
+      OneOperator(map_type[typeid(R).name()],
+                  map_type[typeid(A).name()],
+                  map_type[typeid(B).name()],
+                  map_type[typeid(C).name()]) {}
+};
+
+template<typename T,class CODE >
+class  OneQuadOperator : public OneOperator{
+  typedef typename T::result_type R;
+  typedef typename T::first_argument_type A;
+  typedef typename T::second_argument_type B;
+  typedef typename T::third_argument_type C;
+  typedef typename T::fourth_argument_type D;
+
+  class Op : public E_F0 {
+    typedef  typename C::result_type Result;
+    Expression a,b,c,d;
+  public:
+    AnyType operator()(Stack s)  const 
+    {return  SetAny<R>(static_cast<R>(T::f( GetAny<A>((*a)(s)) ,
+					    GetAny<B>((*b)(s)) ,
+					    GetAny<C>((*c)(s)),
+					    GetAny<D>((*d)(s))
+					    )));}
+    Op(Expression aa,Expression bb,Expression cc,Expression dd) : a(aa),b(bb),c(cc),d(dd) {} 
+    bool MeshIndependent() const {
+      return a->MeshIndependent() && b->MeshIndependent() && c->MeshIndependent()  && d->MeshIndependent();}
+  };
+  
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+  { return  new CODE(t[0]->CastTo(args[0]),t[1]->CastTo(args[1]),t[2]->CastTo(args[2]),t[3]->CastTo(args[3]));} 
+  OneQuadOperator(): 
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()]
+		) {}
+};
+
+
+template<typename T >
+class  OneTernaryOperator3 : public OneOperator{
+  typedef typename T::result_type R;
+  typedef typename T::first_argument_type A;
+  typedef typename T::second_argument_type B;
+  typedef typename T::third_argument_type C;
+
+    class Op : public E_F0 {
+     // typedef  typename C::result_type Result;
+         Expression a,b,c;
+       public:
+       AnyType operator()(Stack s)  const 
+        {return  SetAny<R>(static_cast<R>(T::f( s, GetAny<A>((*a)(s)) ,
+                                                GetAny<B>((*b)(s)) ,
+                                                GetAny<C>((*c)(s)))));}
+       Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc) {} 
+       bool MeshIndependent() const { return a->MeshIndependent() && b->MeshIndependent() &&  c->MeshIndependent();}
+       
+    };
+
+   public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new Op(t[0]->CastTo(args[0]),t[1]->CastTo(args[1]),t[2]->CastTo(args[2]));} 
+    OneTernaryOperator3(): 
+      OneOperator(map_type[typeid(R).name()],
+                  map_type[typeid(A).name()],
+                  map_type[typeid(B).name()],
+                  map_type[typeid(C).name()]) {}
+};
+
+
+
+
+struct OneBinaryOperatorMI {
+  static bool MeshIndependent(Expression a,Expression b)   { return a->MeshIndependent() && b->MeshIndependent();}
+  static bool ReadOnly() { return true;}
+};
+struct OneBinaryOperatorMIWO {
+  static bool MeshIndependent(Expression a,Expression b)   { return a->MeshIndependent() && b->MeshIndependent();}
+  static bool ReadOnly() { return false;}
+};
+// ----------  operator with stack ??? for auto delete
+template<typename C,class MI=OneBinaryOperatorMI>
+class  OneBinaryOperator_st : public OneOperator{
+  typedef  typename C::result_type R;
+  typedef typename C::first_argument_type A;
+  typedef typename C::second_argument_type B;
+  aType t0,t1; // type of template modif FH mars 2006 
+  class Op : public E_F0 {
+    typedef  typename C::result_type Result;
+    Expression a,b;
+  public:
+    AnyType operator()(Stack s)  const 
+    {return  SetAny<R>(static_cast<R>(C::f(s, GetAny<A>((*a)(s)) , GetAny<B>((*b)(s)))));}
+    Op(Expression aa,Expression bb) : a(aa),b(bb) {} 
+    bool MeshIndependent() const { return MI::MeshIndependent(a,b);}
+    bool ReadOnly() const { return MI::ReadOnly()  ;} 
+    int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) 
+    {
+      int rr = find(m);
+      if (rr) return rr;          
+      int Opa = a->Optimize(l,m,n);          
+      int Opb =b->Optimize(l,m,n);
+      return insert(new Opt(*this,Opa,Opb),l,m,n);       
+    } 
+    int compare (const E_F0 *t) const { 
+      int rr;
+      const  Op * tt=dynamic_cast<const Op *>(t);
+      if (tt ) rr =   clexico(a->compare(tt->a),b->compare(tt->b));
+      else rr = E_F0::compare(t);
+      // cout << "cmp E_F0_Func1 " << rr << endl;
+      return rr;
+    } // to give a order in instuction 
+    // int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) const;  // build optimisation
+    
+    virtual ostream & dump(ostream &f) const  { 
+      f << "Op<" << typeid(C).name() 
+	<< ">   \n\t\t\t( a= "<< *a<< ")  \n\t\t\t(b= "<< *b << ") "  ;
+      return f; }
+  };
+    // build optimisation
+  class Opt: public Op  { public :
+    size_t ia,ib;  
+    Opt(const  Op &t,size_t iaa,size_t ibb) 
+      : Op(t) ,
+	ia(iaa),ib(ibb) {}
+    AnyType operator()(Stack s)  const 
+    {
+      // cout <<  "Opt2 ::: " << ia << " "<< ib << " f = " 
+      //      <<  GetAny<double>(SetAny<R>(C::f( *static_cast<A *>(static_cast<void*>(static_cast<char *>(s)+ia)) , 
+      //                     *static_cast<B *>(static_cast<void*>(static_cast<char *>(s)+ib))))) << endl;
+      
+      
+      return SetAny<R>( C::f(s, *static_cast<A *>(static_cast<void*>(static_cast<char *>(s)+ia)) , 
+			        *static_cast<B *>(static_cast<void*>(static_cast<char *>(s)+ib)) ) );}  
+    
+    
+  };     
+  //   aType r; //  return type 
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+  { //cout << "A op B \n" ;
+    return  new Op(t0->CastTo(args[0]),t1->CastTo(args[1]));} 
+  OneBinaryOperator_st(): 
+    OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()],map_type[typeid(B).name()]), 
+    t0(t[0]),
+    t1(t[1]) 
+  {pref = SameType<A,B>::OK ;}
+  
+  OneBinaryOperator_st(aType tt0,aType tt1):  
+    OneOperator(map_type[typeid(R).name()],
+                tt0 ? tt0  : map_type[typeid(A).name()] ,
+                tt1 ? tt1  : map_type[typeid(B).name()]), 
+    t0(map_type[typeid(A).name()]),
+    t1(map_type[typeid(B).name()])
+   {pref = SameType<A,B>::OK ;}
+
+};
+
+struct evalE_F2 {
+   static AnyType eval(Stack s,const E_F0 * ab,const E_F0 * a,const E_F0 * b, bool & meshidenp) 
+   {
+       return ab->E_F0::eval(s,meshidenp); 
+   }
+};
+
+//
+template<typename C,class MI=OneBinaryOperatorMI,class MIx=evalE_F2 >
+class  OneBinaryOperator : public OneOperator{
+  typedef  typename C::result_type R;
+  typedef typename C::first_argument_type A;
+  typedef typename C::second_argument_type B;
+  aType t0,t1; // type of template modif FH mars 2006 
+  class Op : public E_F0 {
+      typedef typename C::first_argument_type A;
+      typedef typename C::second_argument_type B;
+      typedef  typename C::result_type Result;
+    Expression a,b;
+  public:
+    AnyType operator()(Stack s)  const 
+    {return  SetAny<R>(static_cast<R>(C::f( GetAny<A>((*a)(s)) , GetAny<B>((*b)(s)))));}
+    //   optim  eval MI ...  juin 2007 FH ...
+    AnyType eval(Stack s, bool & meshidenp)  const 
+    {return  MIx::eval(s,this,a,b,meshidenp);}
+    // fi optime 
+    Op(Expression aa,Expression bb) : a(aa),b(bb) {} 
+    bool MeshIndependent() const { return MI::MeshIndependent(a,b);}
+    bool ReadOnly() const { return MI::ReadOnly()  ;} 
+    int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) 
+    {
+      int rr = find(m);
+      if (rr) return rr;          
+      int Opa = a->Optimize(l,m,n);          
+      int Opb =b->Optimize(l,m,n);
+      return insert(new Opt(*this,Opa,Opb),l,m,n);       
+    } 
+    int compare (const E_F0 *t) const { 
+      int rr;
+      const  Op * tt=dynamic_cast<const Op *>(t);
+      if (tt ) rr =   clexico(a->compare(tt->a),b->compare(tt->b));
+      else rr = E_F0::compare(t);
+      // cout << "cmp E_F0_Func1 " << rr << endl;
+      return rr;
+    } // to give a order in instuction 
+    // int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) const;  // build optimisation
+    
+    virtual ostream & dump(ostream &f) const  { 
+      f << "Op<" << typeid(C).name() 
+	<< ">   \n\t\t\t( a= "<< *a<< ")  \n\t\t\t(b= "<< *b << ") "  ;
+      return f; }
+  };
+    // build optimisation
+  class Opt: public Op  { public :
+    size_t ia,ib;  
+    Opt(const  Op &t,size_t iaa,size_t ibb) 
+      : Op(t) ,
+	ia(iaa),ib(ibb) {}
+    AnyType operator()(Stack s)  const 
+    {
+      // cout <<  "Opt2 ::: " << ia << " "<< ib << " f = " 
+      //      <<  GetAny<double>(SetAny<R>(C::f( *static_cast<A *>(static_cast<void*>(static_cast<char *>(s)+ia)) , 
+      //                     *static_cast<B *>(static_cast<void*>(static_cast<char *>(s)+ib))))) << endl;
+      
+      
+      return SetAny<R>( C::f( *static_cast<A *>(static_cast<void*>(static_cast<char *>(s)+ia)) , 
+			      *static_cast<B *>(static_cast<void*>(static_cast<char *>(s)+ib)) ) );}  
+    
+    
+  };     
+  //   aType r; //  return type 
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+  { //cout << "A op B \n" ;
+    if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	CompileError( " They are used Named parameter ");
+ 
+    return  new Op(t0->CastTo(args[0]),t1->CastTo(args[1]));} 
+  OneBinaryOperator(): 
+    OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()],map_type[typeid(B).name()]), 
+    t0(t[0]),
+    t1(t[1]) 
+  {pref = SameType<A,B>::OK ;}
+  
+  OneBinaryOperator(aType tt0,aType tt1):  
+    OneOperator(map_type[typeid(R).name()],
+                tt0 ? tt0  : map_type[typeid(A).name()] ,
+                tt1 ? tt1  : map_type[typeid(B).name()]), 
+    t0(map_type[typeid(A).name()]),
+    t1(map_type[typeid(B).name()])
+   {pref = SameType<A,B>::OK ;}
+
+};
+//-------------
+template<typename R>
+class  Operator_Aritm_If : public OneOperator{
+  typedef bool A; 
+  typedef R B; 
+  typedef R C; 
+  class Op : public E_F0 {
+    typedef  R Result;
+    Expression a,b,c;
+  public:
+    AnyType operator()(Stack s)  const 
+         {
+             bool ok = GetAny<bool>((*a)(s)) ;
+             R r ;
+             if( ok) r=GetAny<B>((*b)(s)) ;
+             else r =GetAny<C>((*c)(s)) ;
+             return  SetAny<R>(r);// static_cast<R>( ? GetAny<B>((*b)(s))  : GetAny<C>((*c)(s))  ));
+          }
+    Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc){} 
+    bool MeshIndependent() const { return a->MeshIndependent() && b->MeshIndependent() &&b->MeshIndependent() ;}
+    int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) 
+    {
+      int rr = find(m);
+      if (rr) return rr;          
+      int Opa = a->Optimize(l,m,n);          
+      int Opb =b->Optimize(l,m,n);
+      int Opc =c->Optimize(l,m,n);
+      return insert(new Opt(*this,Opa,Opb,Opc),l,m,n);       
+    } 
+    int compare (const E_F0 *t) const { 
+      int rr;
+      const  Op * tt=dynamic_cast<const Op *>(t);
+      if (tt ) rr =   clexico(a->compare(tt->a),b->compare(tt->b),c->compare(tt->c));
+      else rr = E_F0::compare(t);
+      // cout << "cmp E_F0_Func1 " << rr << endl;
+      return rr;
+    } // to give a order in instuction 
+    // int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) const;  // build optimisation
+    
+    virtual ostream & dump(ostream &f) const  { 
+      f << "Op<" << typeid(C).name() 
+	<< ">   \n\t\t\t( a= "<< *a<< ")  \n\t\t\t(b= "<< *b << ") "  ;
+      return f; }
+  };
+    // build optimisation
+  class Opt: public Op  { public :
+    size_t ia,ib,ic;  
+    Opt(const  Op &t,size_t iaa,size_t ibb,size_t icc) 
+      : Op(t) ,
+	ia(iaa),ib(ibb),ic(icc) {}
+    AnyType operator()(Stack s)  const 
+    {
+      // cout <<  "Opt2 ::: " << ia << " "<< ib << " f = " 
+      //      <<  GetAny<double>(SetAny<R>(C::f( *static_cast<A *>(static_cast<void*>(static_cast<char *>(s)+ia)) , 
+      //                     *static_cast<B *>(static_cast<void*>(static_cast<char *>(s)+ib))))) << endl;
+      
+      
+      return SetAny<R>(
+               static_cast<R> (
+                              *static_cast<bool *>(static_cast<void*>(static_cast<char *>(s)+ia)) ? 
+			      *static_cast<B    *>(static_cast<void*>(static_cast<char *>(s)+ib))    :
+			      *static_cast<C    *>(static_cast<void*>(static_cast<char *>(s)+ic)) ) );}  
+    
+    
+  };     
+  //   aType r; //  return type 
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+  { //cout << "A op B \n" ;
+      if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	  CompileError( " They are used Named parameter "); 
+    return  new Op(t[0]->CastTo(args[0]),t[1]->CastTo(args[1]),t[2]->CastTo(args[2]));} 
+  Operator_Aritm_If(): 
+    OneOperator(map_type[typeid(R).name()],map_type[typeid(bool).name()],map_type[typeid(B).name()],map_type[typeid(B).name()])
+  {pref = SameType<B,B>::OK ;}
+};
+
+/* essai d'unification des classes 
+
+template<class R,class A,R ff(A),class AA=A> 
+struct F_1 : unary_function<AA,R>,public E_F0 {
+       AnyType operator()(Stack s)  const 
+        { return  SetAny<R>( ff(GetAny<A>((*a)(s)))) ;}
+
+};
+
+
+template<class C>
+class bUnary_Op : public C { public:
+
+         Expression a;
+       public:
+        
+       bUnary_Op(Expression aa) : a(aa) {} 
+      
+       int compare (const E_F0 *t) const { 
+           int rr;
+            const  bUnary_Op * tt=dynamic_cast<const bUnary_Op *>(t);
+            if (tt) rr = a->compare(tt->a);
+             else rr = E_F0::compare(t);
+             // cout << "cmp E_F0_Func1 " << rr << endl;
+         return rr;
+       } // to give a order in instuction 
+      bool EvaluableWithOutStack() const {return a->EvaluableWithOutStack();} // 
+     bool MeshIndependent() const {return a->MeshIndependent();} // 
+       
+  // int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) const;  // build optimisation
+
+    virtual ostream & dump(ostream &f) const  { 
+       f << "Op1<" << typeid(C).name() 
+         << ">   \n\t\t\t( a= "<< *a<< ") "  ;
+      return f; }       
+       
+    };
+*/ 
+template<class C>
+class Unary_Op : public E_F0 { public:
+
+
+  typedef typename C::result_type R;
+  typedef typename C::argument_type A; 
+  
+       Expression a;
+       public:
+       AnyType operator()(Stack s)  const 
+        { return  SetAny<R>( C::f(GetAny<A>((*a)(s)))) ;}
+        
+       Unary_Op(Expression aa) : a(aa) {} 
+      
+       int compare (const E_F0 *t) const { 
+           int rr;
+            const  Unary_Op * tt=dynamic_cast<const Unary_Op *>(t);
+            if (tt) rr = a->compare(tt->a);
+             else rr = E_F0::compare(t);
+             // cout << "cmp E_F0_Func1 " << rr << endl;
+         return rr;
+       } // to give a order in instuction 
+      bool EvaluableWithOutStack() const {return a->EvaluableWithOutStack();} // 
+     bool MeshIndependent() const {return a->MeshIndependent();} // 
+       
+  // int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) const;  // build optimisation
+
+    virtual ostream & dump(ostream &f) const  { 
+       f << "Op1<" << typeid(C).name() 
+         << ">   \n\t\t\t( a= "<< *a<< ") "  ;
+      return f; }
+       
+       
+    };
+
+
+
+template<class C,class Op=Unary_Op<C> > 
+class  OneUnaryOperator : public OneOperator{
+  typedef typename C::result_type R;
+  typedef typename C::argument_type A; 
+   // aType r; //  return type 
+    aType tA;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+    {     if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	CompileError( " They are used Named parameter ");
+	 return  new Op(tA->CastTo(args[0]));} 
+    OneUnaryOperator(aType tt0=map_type[typeid(A).name()]): 
+      OneOperator(map_type[typeid(R).name()],tt0), 
+      tA(map_type[typeid(A).name()])
+      {}
+};
+
+template<class R,class A=R,class E=E_F0>
+class  OneOperator1s_ : public OneOperator {
+    aType r; //  return type
+    typedef  R (*func)(Stack stack, const A &) ; 
+    func  f;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+    {     if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	CompileError( " They are used Named parameter ");
+	 return  new E_F_F0s_<R,A,E>(f,t[0]->CastTo(args[0]));}
+    OneOperator1s_(func  ff): 
+      OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()]),f(ff){}
+};
+
+template<class R,class A=R,class CODE=E_F_F0_<R,A> >
+class  OneOperator1_ : public OneOperator {
+    aType r,t0; //  return type
+    typedef  R (*func)(const A &) ; 
+    func  f;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { 
+	 if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	     CompileError( " They are used Named parameter ");
+
+	 return  new CODE(f,t[0]->CastTo(args[0]));} 
+    OneOperator1_(func  ff,int ppref=0): 
+    OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()]),t0( map_type[typeid(A).name()] ),f(ff){pref=ppref;}
+    OneOperator1_(func  ff,aType tt0,int ppref=0): 
+	OneOperator(map_type[typeid(R).name()],tt0),
+	t0( map_type[typeid(A).name()]), f(ff) {pref=ppref;}
+    
+};
+
+template<class R,class A,class B,class E> class E_F_F0F0_;
+
+
+
+
+template<class R,class A=R,class B=A,class CODE=E_F_F0F0_<R,A,B,E_F0> >
+class  OneOperator2_ : public OneOperator {
+    aType r,t0,t1; //  return type  type de f,  f(t1, t2) 
+    typedef typename  CODE::func  func;
+    func f;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { 
+	 if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	     CompileError( " They are used Named parameter ");
+
+	 return  new CODE(f,t0->CastTo(args[0]),t1->CastTo(args[1]));} 
+    OneOperator2_(func  ff): 
+      OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()],map_type[typeid(B).name()]),
+      t0( map_type[typeid(A).name()] ),t1(map_type[typeid(B).name()] ), f(ff) {}
+     OneOperator2_(int ppref,func  ff): 
+       OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()],map_type[typeid(B).name()]),
+       t0( map_type[typeid(A).name()] ),t1(map_type[typeid(B).name()] ), f(ff) {pref=ppref;}
+
+    OneOperator2_(func  ff,aType tt0,aType tt1): 
+      OneOperator(map_type[typeid(R).name()],tt0,tt1),
+      t0( map_type[typeid(A).name()] ),t1(map_type[typeid(B).name()] ), f(ff) {}
+      
+};
+
+template<class R,class A=R,class B=A,class C=B,class CODE=E_F_F0F0F0_<R,A,B,C,E_F0> >
+class  OneOperator3_ : public OneOperator {
+   // aType r; //  return type 
+    aType tA,tB,tC; // type of template modif FH mars 2007 
+    typedef typename  CODE::func  func;
+    func f;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { 
+	 if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	     CompileError( " They are used Named parameter ");
+
+	 return  new CODE(f,tA->CastTo(args[0]),tB->CastTo(args[1]),tC->CastTo(args[2]));} 
+    OneOperator3_(func  ff,
+		  aType tt0=map_type[typeid(A).name()],
+		  aType tt1=map_type[typeid(B).name()],
+		  aType tt2=map_type[typeid(C).name()])
+	: OneOperator(map_type[typeid(R).name()],tt0,tt1,tt2),
+      tA(map_type[typeid(A).name()]),
+      tB(map_type[typeid(B).name()]),
+      tC(map_type[typeid(C).name()]),
+      f(ff){}
+};
+
+// <<OneOperatorCode>> utilise [[E_F0]]. la class code doit contenir
+/*
+  class CODE: public E_F0 {
+    typedef  ...  func .. ;
+    typedef .. R;
+     static ArrayOfaType  typeargs(); // the list of type de l'operateur of the args 
+    typedef  ... R;  // return type 
+}
+*/
+
+template<class CODE,int ppref=0>
+class  OneOperatorCode : public OneOperator {
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const  { return CODE::f(args);} 
+    OneOperatorCode():  OneOperator(atype<typename CODE::Result>(),CODE::typeargs()) {pref=ppref;}
+    OneOperatorCode(aType rr,const ArrayOfaType & l):  OneOperator(rr,l)  {pref=ppref;}
+    OneOperatorCode(aType rr,aType a):  OneOperator(rr,a)  {pref=ppref;}
+    OneOperatorCode(aType rr,aType a,aType b):  OneOperator(rr,a,b)  {pref=ppref;}
+    OneOperatorCode(aType rr,aType a,aType b,aType c):  OneOperator(rr,a,b,c)  {pref=ppref;}
+    
+};
+
+template<class A,class B> struct binary_trait{ typedef  A R  ;}; 
+template<>  struct binary_trait<int,double> { typedef  double R;}; 
+template<>  struct binary_trait<long,double> { typedef  double R;}; 
+template<>  struct binary_trait<int,complex<double> > { typedef  complex<double> R;}; 
+template<>  struct binary_trait<long,complex<double> > { typedef  complex<double> R;}; 
+template<>  struct binary_trait<double,complex<double> > { typedef  complex<double> R ;}; 
+template<class A>  struct binary_trait<A,string* > { typedef  string*  R ;}; 
+
+//  1 variable pour les operation de cast 
+class E_F1_funcT_Type: public OneOperator{ public:
+    //  const basicForEachType *r,*a;
+    Function1 f;
+    E_F0 * code(const basicAC_F0 & args) const   { 
+        if ( args.named_parameter && !args.named_parameter->empty()  ) 
+            CompileError( " They are used Named parameter ");
+        
+        return  new  E_F0_Func1(f,args[0]);} 
+    
+    E_F1_funcT_Type(const basicForEachType *rr,const basicForEachType *aa,Function1 ff)
+    : OneOperator(rr,aa), f(ff) {}
+    
+    //: r(rr),a(aa),f(ff) {}
+    //  friend ostream & operator<<(ostream & f,const E_F1_funcT_Type & e) { f << *e.a << " -> " << *e.r ;return f;}
+};
+
+template<class R,class A>
+class E_F1_funcT :public  E_F1_funcT_Type{ public:   
+    E_F1_funcT(Function1 ff) : E_F1_funcT_Type(map_type[typeid(R).name()],map_type[typeid(A).name()],ff){}
+    E_F1_funcT(aType rr,aType a,Function1 ff) : E_F1_funcT_Type(rr,a,ff){}
+};
+
+
+template<class T,class PT> 
+ ForEachTypePtr<T,PT>::ForEachTypePtr(): 
+         basicForEachType(typeid(PT),sizeof(PT),
+//         new E_F1_funcT<T,T*>(UnRef<T>),atype<T>(),
+         new E_F1_funcT_Type(atype<T>(),this,UnRef<T,PT>),atype<T>(),
+
+         ::Initialize<T>,::Delete<T>){}
+         
+template<class T,class PT> 
+ ForEachTypePtr<T,PT>::ForEachTypePtr(Function1 init,Function1 dl,Function1 onreturn): 
+         basicForEachType(typeid(PT),sizeof(PT),
+//         new E_F1_funcT<T,T*>(UnRef<T>),atype<T>(),
+         new E_F1_funcT_Type(atype<T>(),this,UnRef<T,PT>),atype<T>(),
+			  init,
+			  dl , onreturn ){}
+         
+template<class T,class PT> 
+ ForEachTypePtr<T,PT>::ForEachTypePtr(Function1 dl): 
+         basicForEachType(typeid(PT),sizeof(PT),
+         new E_F1_funcT_Type(atype<T>(),this,UnRef<T,PT>),atype<T>(),
+         ::Initialize<T>,dl){}
+         
+
+template<class T> 
+ ForEachTypePtr<T*,T**>::ForEachTypePtr(T* unused,Function1 OOnReturn): 
+         basicForEachType(typeid(T**),sizeof(T**),
+//         new E_F1_funcT<T*,T**>(UnRef<T*>),atype<T*>(),
+         new E_F1_funcT_Type(atype<T*>(),this,UnRef<T*>),atype<T*>(),
+
+         ::InitializePtr<T*>,::DestroyPtr<T*>,OOnReturn){}
+      
+template<class T> 
+ ForEachTypePtr<T*,T**>::ForEachTypePtr(Function1 init,Function1 dl,Function1 onreturn): 
+         basicForEachType(typeid(T**),sizeof(T**),
+        // new E_F1_funcT<T*,T**>(UnRef<T*>),atype<T*>(),
+         new E_F1_funcT_Type(atype<T*>(),this,UnRef<T*>),atype<T*>(),
+			  init  ,
+			  dl ,
+			  onreturn){}
+        
+template<class T> 
+ ForEachTypePtr<T*,T**>::ForEachTypePtr(Function1 dl): 
+         basicForEachType(typeid(T**),sizeof(T**),
+//         new E_F1_funcT<T*,T**>(UnRef<T*>),atype<T*>(),
+         new E_F1_funcT_Type(atype<T*>(),this,UnRef<T*>),atype<T*>(),
+         ::InitializePtr<T*>,dl){}
+         
+/* class  FuncForEachType : public basicForEachType {public:
+  FuncForEachType(const basicForEachType * t);
+  const basicForEachType *  rtype;  
+ };        
+*/
+  
+
+
+/*
+inline basicForEachType::basicForEachType(const type_info  & k, const type_info  & kf,
+                                          const size_t s,
+                                          const E_F1_funcT_Type * p,
+                                          basicForEachType *rr,
+                                          Function1 iv,Function1 id) 
+      : ktype(&k),ktypefunc(&kf),
+        size(s),
+        un_ptr(p),
+        un_ptr_type(rr?rr:this), 
+        InitExp(iv),        
+        destroy(id) ,
+        funct_type(new FuncForEachType(this)){} 
+        
+        
+*/
+
+inline C_F0 & operator+=(C_F0 & a,C_F0 &b)
+{
+   C_F0 r = C_F0(TheOperators,"+",a,b);
+   a=r;
+   return a;
+}
+
+
+template<typename T,typename PT>
+void Dcl_TypeandPtr_ (Function1 i,Function1 d,Function1 pi,Function1 pd,Function1 OnReturn=0,Function1 pOnReturn=0)
+   {
+      map_type[typeid(T).name()] = new ForEachType<T>(i,d,OnReturn); 
+      map_type[typeid(PT).name()] = new ForEachTypePtr<T,PT>(pi,pd,pOnReturn); 
+   }
+template<class T>
+void Dcl_TypeandPtr (Function1 i,Function1 d,Function1 pi,Function1 pd,Function1 OnReturn=0,Function1 pOnReturn=0)
+{
+map_type[typeid(T).name()] = new ForEachType<T>(i,d,OnReturn); 
+map_type[typeid(T*).name()] = new ForEachTypePtr<T>(pi,pd,pOnReturn); 
+}
+
+
+template<class T>
+  void Dcl_TypeandPtr (Function1 pi,Function1 pd)
+   {
+      map_type[typeid(T).name()] = new ForEachType<T>(); 
+      map_type[typeid(T*).name()] = new ForEachTypePtr<T>(pi,pd); 
+   }
+   
+template<class T>
+  void Dcl_TypeandPtr (Function1 pd)
+   {
+      map_type[typeid(T).name()] = new ForEachType<T>(); 
+      map_type[typeid(T*).name()] = new ForEachTypePtr<T>(pd); 
+   }
+   
+template<class T>
+  void Dcl_TypeandPtr ()
+   {
+      map_type[typeid(T).name()] = new ForEachType<T>(); 
+      map_type[typeid(T*).name()] = new ForEachTypePtr<T>(); 
+   }
+   
+template<class T>
+  aType Dcl_Type (Function1 iv=0,Function1 id=0,Function1 Onreturn=0)
+   {
+     if (sizeof(T) >sizeof(AnyData)) {
+       cerr << " the type   " << typeid(T).name() << " is too large " << sizeof(AnyData) <<  endl;
+       throwassert(sizeof(T) <=sizeof(AnyData));}
+     return map_type[typeid(T).name()] = new ForEachType<T>(iv,id,Onreturn); 
+    
+   }
+
+template<class T>
+  void Add(const char * k,const char * op,OneOperator *p0,OneOperator *p1=0,
+      OneOperator *p2=0,OneOperator *p3=0,OneOperator *p4=0,
+      OneOperator *p5=0,OneOperator *p6=0)  
+     {atype<T>()->Add(k,op,p0,p1,p2,p3,p4,p5,p6);}     
+
+inline C_F0 operator *(const C_F0 &a,const C_F0 &b)
+{    
+  return a==*pOne ? b : ( b ==*pOne ? a : C_F0(TheOperators,"*",a,b)) ;}
+inline C_F0 operator+(const C_F0 &a,const C_F0 &b){ return C_F0(TheOperators,"+",a,b);}
+inline C_F0 operator-(const C_F0 &a,const C_F0 &b){ return C_F0(TheOperators,"-",a,b);}
+  
+/// <<C_F0_operator_plusequals>>
+inline C_F0 &operator +=(C_F0 &a,const C_F0 &b)
+{  
+   C_F0 r=C_F0(TheOperators,"+",a,b);
+   a=r;
+   return a;}
+   
+//inline  bool CC_F0::Empty() const {return !f || f->Empty();}
+inline  void CC_F0::operator=(const CListOfInst& c) 
+  { C_F0 cc=c;f=cc.f;r=cc.r;}
+inline   CListOfInst &  CListOfInst::operator+=(const CC_F0 & a)
+  { if( !a.Empty()){ f->Add(a);r=a.left();};return *this;} 
+  
+inline Type_Expr basicForEachType::SetParam(const C_F0 & ,const ListOfId * ,size_t & ) const
+     { cerr << " int basicForEachType " << name() << endl; 
+       InternalError("basicForEachType::SetParam non defined");  }//return make_pair<aType,const E_F0  *>(c.left(),c.LeftValue());}
+     
+
+
+/*
+
+//  ---  pour les cast ------
+class  OneOpCast: public OneOperator { 
+    typedef const E_F1_funcT_Type *  CastFunc;
+    CastFunc  f;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const   { return  new  E_F0_Func1(f->f,args[0]);} 
+    OneOpCast(CastFunc  ff): OneOperator(ff->r,ff->a),f(ff){}
+};
+*/
+
+// 
+inline  bool  basicForEachType::CastingFrom(aType t) const  {
+     throwassert(this && t);
+     if ( t == this) return true;
+     else if( t ==  type_C_F0 ) return true; // FH do work .... 09 / 2012 (use of ellispe ...)
+     return casting->FindSameR(ArrayOfaType(t,false));
+  }
+
+inline  void CerrCast(const pair<const basicForEachType*,const E_F1_funcT_Type *> & i)
+{ 
+   cerr << "\t" <<  *i.first << ":" << i.second << endl;
+}
+
+inline 	 C_F0 basicForEachType::CastTo(const C_F0 & e) const 
+{
+ throwassert(this);
+ aType t = e.left();
+ if (this== t) return e;
+  
+ 
+  C_F0 ce=e;
+  basicAC_F0 at;
+  at=ce;
+  OneOperator * opcast =casting->FindSameR(ArrayOfaType(t,false));  
+  if ( opcast )  
+    if ( *opcast == at ) // left value
+      return C_F0(opcast->code(at),this);
+    else  { // rigth value 
+     aType tr = e.right();
+     ce = C_F0(e.RightValue(),tr);
+     at = ce;
+     return C_F0(opcast->code(at),this); }
+  else    
+      { cerr << "Impossible to cast " << *e.left() << " in " << *this << endl;
+           if (casting)  casting->Show(cerr)  ;
+           CompileError();} 
+ return C_F0();
+}
+inline Expression  basicForEachType::RightValueExpr(Expression f) const 
+{
+  if (un_ptr) return new  E_F0_Func1(un_ptr->f,f);
+   else return f;        
+}
+
+inline void CompileError(string msg,aType r){ 
+ string m= r ? msg + "  type: " + r->name() : msg ;
+   lgerror(m.c_str());
+ }
+ 
+ inline void ExecError(string msg){ 
+  // cerr << "Fatal ExecError: " << msg << endl;
+   throw(ErrorExec(msg.c_str(),1));
+ }
+ 
+const  Function1 NotReturnOfthisType = reinterpret_cast<Function1>(1); 
+
+inline Expression basicForEachType::OnReturn(Expression f) const {
+    if(!DoOnReturn) return f;
+    else if(DoOnReturn== NotReturnOfthisType )
+	CompileError("Problem when returning this type (sorry work in progress FH!) ", this);
+    else return new  E_F0_Func1(DoOnReturn,f);
+    return 0; 
+}
+
+
+inline  void CC_F0::operator=(const AC_F0& a) {  f=new E_Array(a); r= atype<E_Array>();};
+
+inline  UnId::UnId(const char * idd,const C_F0 & ee,aType rr=0,bool reff=false) 
+  :id(idd),r(rr),e(ee),array(0),re(ee.left()) ,ref(reff){}
+
+
+class E_exception : public exception { public:
+  enum CODE_exception { UNKNOWN,e_break,e_continue,e_return} ;
+  CODE_exception code;  
+  AnyType r; // for return 
+  public:
+  E_exception(CODE_exception c,AnyType rr=Nothing) : code(c),r(rr)  {}
+  const int type() {return code;}
+  virtual const char *  what() const throw() { return "E_exception (break,continue or return) "; }
+  ~E_exception() throw() {}
+};
+
+
+class E_throw : public E_F0mps { public:
+   E_exception::CODE_exception kind;    
+   Expression ret; // return value
+   E_throw(E_exception::CODE_exception c,Expression e=0) :kind(c),ret(e) {}
+   AnyType operator()(Stack s)  const { 
+     (ret ? throw(E_exception(kind,(*ret)(s)))
+          : throw(E_exception(kind)));
+       return Nothing; }
+   operator aType () const { return atype<void>();} 
+      
+ } ;
+
+class E_block :  public E_F0mps { public:
+  const int n;
+  Expression  * code;
+  int * linenumber;
+  Expression clean;
+   E_block(CListOfInst l,C_F0   c)
+     : n(l.size()),code(l.ptr()),linenumber(l.nlines()),clean(c) {}
+   E_block( C_F0  l,C_F0  c)
+     : n(1),code(new Expression),clean(c) { code[0]=l;}
+   AnyType operator()(Stack s)  const ;
+    operator aType () const { return atype<void>();}         
+   
+};
+
+class Routine;
+class E_Routine :  public E_F0mps { public:
+  Expression code;
+  Expression clean;
+  aType rt;
+  int nbparam;
+  Expression * param;
+  const char * name;
+  E_Routine(const Routine * routine,const basicAC_F0 & args);
+   AnyType operator()(Stack s)  const;
+  ~E_Routine() ;//{ delete [] param;}  modif del for windows
+  private:
+  E_Routine(const E_Routine &);
+  void operator=(const E_Routine &);
+  operator aType ()  const{ return rt;}         
+
+};
+
+/// <<Routine>> used in [[file:../lglib/lg.ypp::YYSTYPE]]
+
+class Routine: public OneOperator{  public:
+   size_t offset;
+   aType tfunc,tret;
+   const char * name;
+   const ListOfId param;
+   Block * currentblock;
+   Expression  ins;   
+   Expression  clean;
+   
+    E_F0 * code(const basicAC_F0 & args) const  ;
+   Routine(aType tf,aType tr,const char * iden,  ListOfId *l,Block * & cb);
+   Block * Set(C_F0   instr) ;
+};
+
+
+class TypeLineFunction: public ForEachType<C_F0> {
+  public:
+  TypeLineFunction() : ForEachType<C_F0>(0,0) {}
+  
+  void SetArgs(const ListOfId *lid) const {
+     if (lid) CompileError("No Argument in line function");
+      } 
+     
+  Type_Expr SetParam(const C_F0 & c,const ListOfId *l,size_t & top) const 
+    {  return Type_Expr(c.left(),c.LeftValue());  } 
+    
+  C_F0 Initialization(const Type_Expr & ) const 
+    {  return C_F0(); }  // nothing to initialize 
+    
+};
+
+
+class E_F0_Optimize : public E_F0 { 
+  deque<pair<Expression,int> > l;
+  // mutable deque<bool> var;
+  MapOfE_F0 m;
+  int NBbitem;
+  int ret;
+public:
+  E_F0_Optimize(deque<pair<Expression,int> > &ll,MapOfE_F0 & mm,int rett) :
+    l(ll),m(mm),NBbitem(1),ret(rett)  {}
+  int sizevar() const {return l.size();}
+  AnyType eval(Stack s,int notinit,bool * unvar)  const {
+    int k= l.size(),kk=0;
+    if(notinit ==0)
+      {
+	//var.resize(k);
+	for (int i=0;i<k;i++)
+	  {  size_t offset = l[i].second;
+	  unvar[i]=true;  
+	  *Stack_offset<AnyType>(s,offset) = l[i].first->eval(s, unvar[i]);
+	  if( unvar[i]) kk++;
+	  }          
+	if (verbosity/100 && verbosity % 10 == 2) 
+	     cout << "E_F0_Optimize  nb MI exp: " << kk << " /  " << k << endl;
+      }
+    else
+      for (int i=0;i<k;i++)
+        {  size_t offset = l[i].second;
+	if(!unvar[i]) 
+	  *Stack_offset<AnyType>(s,offset) = (*l[i].first)(s);
+	//*static_cast<AnyType *>(static_cast<void *>((char*)s+offset))= (*l[i].first)(s); // FH NEWSTACK
+	// cout << " E_F0_Optimize   " << offset << " " <<  *static_cast<double *>(static_cast<void *>((char*)s+offset)) << endl; ;
+        }
+    // return *static_cast<AnyType *>(static_cast<void *>((char*)s+ret));          
+    return *Stack_offset<AnyType>(s,ret); // FH NEWSTACK       
+  }
+  
+  virtual AnyType operator()(Stack s)  const {
+    int k= l.size();
+    for (int i=0;i<k;i++)
+      {  size_t offset = l[i].second;
+      *Stack_offset<AnyType>(s,offset) = (*l[i].first)(s);
+      //*static_cast<AnyType *>(static_cast<void *>((char*)s+offset))= (*l[i].first)(s); // FH NEWSTACK
+      // cout << " E_F0_Optimize   " << offset << " " <<  *static_cast<double *>(static_cast<void *>((char*)s+offset)) << endl; ;
+      }
+    // return *static_cast<AnyType *>(static_cast<void *>((char*)s+ret));          
+    return *Stack_offset<AnyType>(s,ret); // FH NEWSTACK       
+  }
+  virtual bool Empty() const {return l.size(); }
+  // virtual E_F0 * destroy(Stack ) const {return 0;}
+  //  virtual const E_F0 * Parameter(Stack ) const {return this;}
+  virtual size_t nbitem() const {  return NBbitem;}
+  virtual bool EvaluableWithOutStack() const {return false;} // 
+  virtual bool MeshIndependent() const {return false;} // 
+  virtual E_F0 * right_E_F0() const { return 0;}
+  virtual ~E_F0_Optimize() {}
+  // virtual int compare (const E_F0 *t) const { return t-this;} // to give a order in instuction 
+  virtual  operator aType ()  const { return  *(l.back().first);}   // the type of the expression  
+}; 
+ 
+ 
+inline    int E_F0::find(const MapOfE_F0 & m)  {  //  exp
+       // cout << " ffff :" ;
+        MapOfE_F0::const_iterator i= m.find(this); 
+        if(i != m.end()) {
+            if( (verbosity / 100)% 10 == 1) 
+              {
+                 cout << "\n    find : ";
+                 cout  <<  i->second << " mi=" ;
+                 cout << MeshIndependent() << " " ;
+                 cout << typeid(*this).name()  ;
+                 cout << " cmp = " << compare(i->first) ;
+                 cout  << " " << i->first->compare(this) << " ";
+                 dump(cout);
+               }
+             assert( compare(i->first) == 0);
+           }     
+        return i == m.end() ? 0 : i->second ;
+    }
+ inline   int E_F0::insert(Expression  opt,deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) 
+    {
+     int rr=align8(n);
+     pair<Expression,int> p(this,rr);
+     if( (verbosity / 100)% 10 == 1) 
+       cout << "  --  insert opt " << n << " " << *this << endl;     
+       n += sizeof(AnyType);         
+       l.push_back(make_pair<Expression,int>((Expression)opt,(int)rr)); 
+       m.insert(p); 
+       return rr;
+     }
+
+extern queue<pair<const E_Routine*,int> > * debugstack;
+
+struct NothingType {  // a type to do nothing 
+ NothingType() {};
+};
+
+extern basicForEachType *  typevarreal,  * typevarcomplex;  //  type of real and complex variable
+  
+void initArrayOperators();   
+void  initArrayDCL();
+
+void ClearMem(); 
+
+// <<OneOperator_code2>>
+inline C_F0  OneOperator::code2(const basicAC_F0 &a) const  {return C_F0(code(a),r);}	
+
+template<class R>
+class  OneOperator0 : public OneOperator {public:
+    class E_F0_F :public  E_F0 { public:
+	typedef  R (*func)( ) ; 
+	func f;
+	E_F0_F(func ff)  : f(ff) {}
+	AnyType operator()(Stack )  const  {return SetAny<R>( f()) ;}  
+	operator aType () const { return atype<R>();} 
+	
+    };
+    
+    //  aType r; //  return type
+    typedef  R (*func)() ; 
+    func  f;
+public: 
+	E_F0 * code(const basicAC_F0 & args) const 
+    { 
+	if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	    CompileError( " They are used Named parameter ");
+
+	return  new E_F0_F(f);} 
+    OneOperator0(func  ff): OneOperator(map_type[typeid(R).name()]),f(ff){}
+};
+
+template<class R >
+Type_Expr CVariable(R  (*ff)() )
+{
+    throwassert(map_type[typeid(R).name()]);
+    return make_pair(map_type[typeid(R).name()],new  typename OneOperator0<R>::E_F0_F(ff));
+}
+
+#endif
+
+
diff --git a/src/fflib/AFunction2.cpp b/src/fflib/AFunction2.cpp
new file mode 100644
index 0000000..5aebc32
--- /dev/null
+++ b/src/fflib/AFunction2.cpp
@@ -0,0 +1,985 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//#pragma dont_inline on
+//#pragma inline_depth(1)
+
+#include "config-wrapper.h"
+
+#include <complex>
+#include "AFunction.hpp"
+#include <cstdarg>
+#include <cstring>
+#include "error.hpp"
+#include "lex.hpp"
+
+#include "RNM.hpp"
+
+#include "Operator.hpp"
+// for exec routine 
+#include "rgraph.hpp"
+#include "InitFunct.hpp"
+
+queue<pair<const E_Routine*,int> > *debugstack=0;
+
+
+class vectorOfInst : public  E_F0mps { public:
+    int n;
+    Expression * v;
+    vectorOfInst(int k): n(k),v(new Expression[k]) {ffassert(v);
+      for(int i=0;i<n;++i) v[i]=0; }
+    ~vectorOfInst(){ delete [] v;}
+    bool empty() const {return n;}
+
+   AnyType operator()(Stack s)  const {
+     for (int i=0;i<n;++i)
+      {
+       ffassert(v[i]);
+       (*(v[i]))(s);
+      }
+      return Nothing;
+   }
+  private: 
+  vectorOfInst(const vectorOfInst &);
+  void operator=(const vectorOfInst &);  
+};
+
+double  VersionNumber(); 
+
+OneOperator::pair_find OneOperator::Find(const ArrayOfaType & at)const
+ { 
+      const OneOperator *w=0,*oo;
+      int nn=0,p=-10000;
+ /*     for (oo=this;oo;oo=oo->next)
+        if (oo->pref>=p && oo->WithOutCast(at)) 
+          {
+           if(p<oo->pref) {nn=0;p=oo->pref;}
+           nn++;
+           w=oo;}
+      if (nn) return make_pair(w,nn);*/
+      for (int ncast=0;ncast<=n;ncast++) // loop on the number of cast 
+       {
+         p=-10000;
+         for (oo=this;oo;oo=oo->next)
+          if (oo->pref>=p && oo->WithCast(at,ncast)) 
+          { 
+           if(p<oo->pref) {nn=0;p=oo->pref;}
+            nn++;
+            w=oo;}
+         if (nn) return make_pair(w,nn);
+       }
+      for (oo=this;oo;oo=oo->next)
+        if (oo->WithCast(at)) 
+          {nn++;
+           w=oo;}
+       return make_pair(w,nn);       
+}
+
+OneOperator::pair_find OneOperator::FindWithOutCast(const ArrayOfaType & at)const
+ { 
+      const OneOperator *w=0,*oo;
+      int n=0;
+      for (oo=this;oo;oo=oo->next)
+        if (oo->WithOutCast(at)) 
+          {n++;
+           w=oo;}
+      return make_pair(w,n);
+}
+
+OneOperator* OneOperator::FindSameR(const ArrayOfaType & at)
+ { 
+     if (!this) return 0;
+      OneOperator *oo,*r;
+      int n=0;
+      for (oo=this;oo;oo=oo->next)
+        { 
+        //if (oo->WithOutCast(at)) 
+        if  (at==*oo)  n++,r=oo;        
+        else if (oo->WithOutCast(at)) n++,r=oo;
+      //  if (n) cout << " \t " << oo << " " << *oo  << " <-----> " << at << " n =" << n << endl;
+        }
+     // if (n>1) cout << "FindSameR " << n << endl;
+     // if (n)       cout << *r << " <-----> " << at << " n =" << n << endl;
+      return n==1 ? r : 0;
+}
+      
+void OneOperator::Show(ostream &f) const
+{         
+   const OneOperator *oo;
+   for (oo=this;oo;oo=oo->next)
+     f << "\t (" <<  *oo << ")\n";
+ }   
+
+void OneOperator::Show(const ArrayOfaType & at,ostream &f) const
+{         
+         const OneOperator *oo;
+         int n=0,np=0;
+         for (oo=this;oo;oo=oo->next)
+           if (oo->WithOutCast(at)) {n++;f << "\t (" <<  *oo << ")\n";}
+         if(n==0) 
+          for (oo=this;oo;oo=oo->next)
+           if (oo->WithCast(at)) {
+              n++;
+              if (oo->pref) np++;
+              if (oo->pref) 
+                f <<   " c(" << oo->pref << ") \t (" <<  *oo << ")\n" ;
+                else f <<  " \t c(" <<  *oo << ")\n";
+              }
+         if (n==0) 
+          {
+           f << " List of choices "<< endl;
+           Show(f);            
+          }
+         else if (np != 1) 
+           f << " We have ambiguity " << n << endl; 
+ }   
+       
+const  OneOperator * Polymorphic::Find(const char *op, const  ArrayOfaType &at) const
+  {
+    const_iterator i=m.find(op);
+    if (i!=m.end())  
+      { 
+       OneOperator::pair_find r=i->second->Find(at);
+       if (r.second==1) return r.first;
+       }    
+    return 0;
+  }
+const  OneOperator * Polymorphic::FindWithOutCast(const char *op, const  ArrayOfaType &at) const
+  {
+    const_iterator i=m.find(op);
+    if (i!=m.end())  
+      { 
+       OneOperator::pair_find r=i->second->FindWithOutCast(at);
+       if (r.second==1) return r.first;
+       }    
+    return 0;
+  }
+ 
+  
+void Polymorphic::Show(const char *op,const ArrayOfaType & at,ostream &f)  const
+    {
+    const_iterator i=m.find(op);
+    if (i==m.end()) f << " unknow " << op << " operator " << endl;
+    else i->second->Show(at,f);
+  }
+
+// <<C_F0_constructor_pop_char_basicAC_F0_impl>> cf [[file:AFunction.hpp::C_F0_constructor_pop_char_basicAC_F0_decl]]
+C_F0::C_F0(const Polymorphic * poly,const char *op,const basicAC_F0 & p)
+{
+    ArrayOfaType at(p); 
+    if (poly) { // a Polymorphic => polymorphisme
+	const  OneOperator *  ff=poly->Find(op,at);
+	if (ff) { 
+	    /* cout << endl;
+	     poly->Show(op,at,cout);
+	     cout << op << ": (in " << at << ") => " << " " << *ff<< "\n\n";*/
+
+	  // [[file:AFunction.hpp::OneOperator_code2]]
+	  *this= ff->code2(p);
+	}
+	else
+	  { if(mpirank==0)
+	    {
+		cerr << " error operator " << op << " " << at << endl;
+		poly->Show(op,at,cerr);
+		// const  OneOperator *  ff=
+		poly->Find(op,at);
+	    }
+	      CompileError();
+	  }
+    }
+    else { 
+	//  no polymorphisme
+	if(mpirank==0){
+	    cerr << " const Polymorphic * poly,const char *op,const basicAC_F0 & p)   " << endl;
+	    cerr  << op << " " << at << endl;
+	}
+	    CompileError();          
+	}
+    }
+       
+
+
+
+//  operator without parameter
+C_F0::C_F0(const Polymorphic * pop,const char *op) 
+{
+  basicAC_F0  p;
+  p=0;
+  *this= C_F0(pop,op,p);
+}
+//  operator unaire
+C_F0::C_F0(const Polymorphic * pop,const char *op,const C_F0 & aa) 
+{
+  basicAC_F0  p;
+  C_F0 a(aa);
+  p=a;
+  *this= C_F0(pop,op,p);
+}
+
+// <<C_F0_constructor_binary_operator>> operator binaire
+C_F0::C_F0(const Polymorphic * pop,const char *op,const  C_F0 & a,const  C_F0 & b) 
+{
+  C_F0 tab[2]={a,b};
+  basicAC_F0 p;
+  p=make_pair<int,C_F0*>(2,tab);
+
+  // [[file:AFunction.hpp::C_F0_constructor_pop_char_basicAC_F0_decl]]
+  *this=C_F0(pop,op,p);
+}
+
+//  operator trinaire
+C_F0::C_F0(const Polymorphic * pop,const char *op,const  C_F0 & a,const  C_F0 & b,const  C_F0 & c) 
+{
+  C_F0 tab[3]={a,b,c};
+  basicAC_F0  p;
+  p=make_pair<int,C_F0*>(3,tab);
+  *this= C_F0(pop,op,p);
+}
+
+
+ OneOperator::~OneOperator(){ 
+       OneOperator * d=next;
+       next=0; 
+       if(! CodeAlloc::cleanning) // hash FH (pour les fuite de m�moire)
+         while(d) 
+        { 
+         OneOperator * dd=d->next;
+         d->next=0;
+         delete d;
+         d=dd;
+        }
+  }
+
+    OneOperator::OneOperator(aType rr) 
+      : ArrayOfaType(),r(rr),next(0),pref(0) {throwassert(r);}
+    OneOperator::OneOperator(aType rr,aType  a) 
+      : ArrayOfaType(a,false),r(rr),next(0),pref(0) {throwassert(rr && a );}
+    OneOperator::OneOperator(aType rr,aType  a,aType  b)
+      : ArrayOfaType(a,b,false),r(rr),next(0),pref(0) {
+     throwassert(rr && a && b);} 
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c) 
+      : ArrayOfaType(a,b,c,false),r(rr),next(0),pref(0)
+        {throwassert(rr && a && b && c);} 
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c,aType d)
+      : ArrayOfaType(a,b,c,d,false),r(rr),next(0),pref(0) 
+      {throwassert(rr && a && b && c);} 
+    
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e) 
+      : ArrayOfaType(a,b,c,d,e,false),r(rr),next(0),pref(0)
+       {throwassert(rr && a && b && c && d);} // Added by Fabian Dortu (5 parameters)
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f) 
+      : ArrayOfaType(a,b,c,d,e,f,false),r(rr),next(0),pref(0) 
+      {throwassert(rr && a && b && c && d && e && f);} // Added by Fabian Dortu (6 parameters) 
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g) 
+      : ArrayOfaType(a,b,c,d,e,f,g,false),r(rr),next(0),pref(0) 
+       {throwassert(rr && a && b && c && d && e && f && g);} // Added by Fabian Dortu (7 parameters) 
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g, aType h) 
+     : ArrayOfaType(a,b,c,d,e,f,g,h,false),r(rr),next(0),pref(0) 
+       {throwassert(rr && a && b && c && d && e && f && g && h);} // Added by Fabian Dortu (8 parameters) 
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g, aType h, aType i) 
+      : ArrayOfaType(a,b,c,d,e,f,g,h,i,false),r(rr),next(0),pref(0) 
+      {throwassert(rr && a && b && c && d && e && f && g && h && i);} // Added by Fabian Dortu (9 parameters) 
+    OneOperator::OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f, aType g, aType h, aType i, aType j) 
+      : ArrayOfaType(a,b,c,d,e,f,g,h,i,j,false),r(rr),next(0),pref(0) 
+     {throwassert(rr && a && b && c && d && e && f && g && h && i && j);} // Added by Fabian Dortu (10 parameters) 
+    
+    
+    
+    OneOperator::OneOperator(aType rr,const ArrayOfaType &ta) 
+      : ArrayOfaType(ta),r(rr),next(0),pref(0) 
+       {throwassert(rr);} 
+    OneOperator::OneOperator(aType rr,bool ellipse) 
+      : ArrayOfaType(ellipse),r(rr),next(0),pref(0) 
+        {throwassert(rr );} 
+    OneOperator::OneOperator(aType rr,const ListOfId *l) 
+      : ArrayOfaType(l),r(rr),next(0),pref(0) 
+      {throwassert(rr );} 
+
+void Polymorphic::Addp(const char * op,Value pp,...) const 
+{
+  pair<iterator,bool>  p=m.insert(pair<const Key,Value>(op,pp));
+  Value f= p.first->second;	
+  if (!p.second)  // not insert => old 
+    *f += *pp;
+  va_list ap;
+  va_start(ap,pp);
+  for(pp=va_arg(ap,OneOperator * );pp;pp=va_arg(ap,OneOperator * ))
+    *f += *pp;
+/*  if ( ! strlen(op) )  
+   { // no polymorphisme
+     if(m.size() !=1 ||  !f->Simple()) {
+       cerr << " no polymorphisme and polymorphisme are mixed " << endl;
+    //   for_each(m.begin,m.end(),ShowOn_cerr);
+       CompileError();       
+     }   
+   } */
+}
+
+void Polymorphic::Add(const char * op,Value *pp) const
+{
+  if (*pp)
+   {
+    pair<iterator,bool>  p=m.insert(pair<const Key,Value>(op,*pp));
+    Value f= p.first->second;	
+    if (!p.second)  // not insert => old 
+      *f += **pp;
+    pp++;
+    for(;*pp;pp++)
+     *f += **pp;
+   /*if ( ! strlen(op) )  
+     { // no polymorphisme
+      if(m.size() !=1 ||  !f->Simple()) {
+       cerr << " no polymorphisme and polymorphisme are mixed " << endl;
+      //   for_each(m.begin,m.end(),ShowOn_cerr);
+       CompileError();       
+     }  } */ }
+     
+}
+
+
+ int  FindType(const char * name)  
+   {
+   C_F0 r;
+
+     ListOfTOfId::const_iterator i=tables_of_identifier.begin();
+      for(;i!=tables_of_identifier.end();++i)
+      { 
+      TableOfIdentifier * ti=*i;     
+      r = ti->Find(name);
+      if (r.NotNull()) return r.TYPEOFID();
+    }
+     return 0;
+   } 
+
+/// <<Find>> uses [[file:global.cpp::tables_of_identifier]]
+
+C_F0 Find(const char * name)   
+{
+   C_F0 r;
+   ListOfTOfId::const_iterator i=tables_of_identifier.begin();
+   for(;i!=tables_of_identifier.end();++i)
+    { 
+      TableOfIdentifier * ti=*i;     
+      r = ti->Find(name);
+      if (r.NotNull()) return r;
+    }
+    if(mpirank==0)
+    cerr << " The Identifier " << name << " does not exist " << endl;
+    CompileError();
+    return r;
+}
+
+C_F0 TableOfIdentifier::destroy()
+{
+ int k=0;
+// cout << "\n\t List of destroy variables " << m.size() << " : " ; 
+ for (pKV * i=listofvar;i;i=i->second.next)
+   {
+     if  (i->second.del && i->second.first->ExistDestroy() )
+    // cout  << i->first << ", " ;
+     assert(i->second.first);
+     if (i->second.del && i->second.first->ExistDestroy() ) k++;
+   }
+// cout << endl;
+/*  old code 
+ ListOfInst *l=new ListOfInst(k);
+ for (pKV * i=listofvar;i;i=i->second.next)
+     if (i->second.del && i->second.first->ExistDestroy()) 
+       l->Add(i->second.first->Destroy(i->second) );
+*/
+// new code 
+  vectorOfInst * l= new vectorOfInst(k);
+  int j=0;
+ for (pKV * i=listofvar;i;i=i->second.next)
+     if (i->second.del && i->second.first->ExistDestroy()) 
+       l->v[j++]=i->second.first->Destroy(i->second) ;
+  ffassert(j==k);
+ return C_F0(l);     
+}
+
+   void TableOfIdentifier::clear()
+   {
+     for (iterator i=m.begin();i!=m.end();++i)
+       {
+        
+   //     delete i->first;
+        }
+     m.clear();
+   } 
+
+Expression basicForEachType::Destroy(const C_F0 & e) const 
+{
+    return destroy ? NewExpression(destroy,e) : (Expression)  e;
+} 
+
+basicForEachType::~basicForEachType()
+  {
+   if(casting) delete casting;
+   ti.clear();
+  }
+
+basicForEachType::basicForEachType(const type_info  & k,
+                                          const size_t s,
+                                          const E_F1_funcT_Type * p,
+                                          basicForEachType *rr,
+                                          Function1 iv,Function1 id, Function1  dreturn) 
+      : ktype(&k),//ktypefunc(0),
+        size(s),
+        un_ptr_type(rr?rr:this), 
+        casting(0), // no casting to 
+        un_ptr(p),
+        InitExp(iv),
+        DoOnReturn(dreturn),
+        //funct_type(0),
+        destroy(id) {} 
+ void basicForEachType::SetArgs(const ListOfId *lid) const
+{ SHOWVERB(cout << "SetArgs::\n ") ;ffassert(lid==0 || lid->size()==0);}
+
+
+
+ TableOfIdentifier::TableOfIdentifier() : listofvar(0) {}
+ TableOfIdentifier:: ~TableOfIdentifier() {}
+
+
+Block::Block(Block * f):fatherblock(f),top(f?f->top:BeginOffset*sizeof(void*)),topmax(top)
+    {     
+      itabl=tables_of_identifier.insert(tables_of_identifier.begin(),&table);
+    }
+Block::~Block(){} 
+
+ CC_F0  Block::close(Block *& c) {
+     tables_of_identifier.erase(itabl);      
+     c=fatherblock;
+     if (fatherblock) {fatherblock->topmax=topmax;
+                       fatherblock->top=top;}
+        
+     CC_F0 r;
+     r = table.destroy();
+     delete this;
+     return r;}
+ 
+   Block * Block::open(Block *& cb)
+   {
+     return  cb = new Block(cb); 
+   }
+  
+    
+const  Type_Expr &   TableOfIdentifier::New(Key k,const Type_Expr & v,bool del)
+  {
+    if( this != &Global) {
+	if ( Global.m.find(k) != Global.m.end() )
+	  {
+	    if(mpirank==0) 
+	      cerr << "\n *** Warning  The identifier " << k << " hide a Global identifier  \n";
+	    
+	  }
+    }
+      pair<iterator,bool>  p=m.insert(pKV(k,Value(v,listofvar,del)));
+      listofvar = &*m.find(k);
+      if (!p.second) 
+	{
+	    if(mpirank==0) {
+		cerr << " The identifier " << k << " exists \n";
+		cerr << " \t  the existing type is " << *p.first->second.first << endl;
+		cerr << " \t  the new  type is " << *v.first << endl;
+	    }
+	    CompileError();
+	}
+      return v;
+  }
+ void  TableOfIdentifier::Add(Key k,Key op,OneOperator *p0,OneOperator *p1,
+      OneOperator *p2,OneOperator *p3,OneOperator *p4,OneOperator *p5,OneOperator *p6)
+  {
+      iterator i= m.find(k);
+      if (i==m.end()) // new
+	{
+	    Value poly0=Value(atype<Polymorphic*>(),new Polymorphic(),listofvar);     
+	    i=m.insert(pair<const Key,Value>(k,poly0)).first;
+	    listofvar= &*i;
+	}
+      const Polymorphic * p= dynamic_cast<const Polymorphic *>(i->second.second);
+      if ( !p) { 
+	  if(mpirank==0)
+	      cerr << k << " is not a Polymorphic id " << endl;
+	  CompileError();
+      }
+      p->Add(op,p0,p1,p2,p3,p4,p5,p6);
+  }
+
+ ArrayOfaType::ArrayOfaType(const ListOfId * l)
+  : n(l->size()),t(new aType[n]),ellipse(false)
+ {
+    for (int i=0;i<n;i++) 
+      {
+      t[i]=(*l)[i].r;  
+       if ( ! t[i])
+        {
+	   if(mpirank==0) 
+           cerr << " Argument " << i << " '"<< (*l)[i].id << "' without type\n";
+           CompileError("DCL routine: Argument without type ");
+         }
+      }
+ }
+
+bool ArrayOfaType::WithOutCast( const ArrayOfaType & a) const 
+ {
+   if ( ( !ellipse && (a.n != n))  || (ellipse && n > a.n) ) return false;
+   for (int i=0;i<n;i++)
+       if (! a.t[i]->SametypeRight(t[i])) 
+        return false;       
+ // cerr << " TRUE " << endl;    
+   return true;
+ }
+
+  
+bool ArrayOfaType::WithCast( const ArrayOfaType & a,int nbcast) const 
+ {  
+   if (  ( !ellipse && (a.n != n))  || (ellipse && n > a.n) ) return false;
+   for (int i=0;i<n;i++)
+     if ( a.t[i]->SametypeRight(t[i])) ;
+     else if (! t[i]->CastingFrom(a.t[i])) return false; 
+     else if ( --nbcast <0) return false;
+   return true;
+ }    
+ 
+void basicForEachType::AddCast(CastFunc f1,CastFunc f2,CastFunc f3,CastFunc f4,
+  CastFunc f5,CastFunc f6,CastFunc f7,CastFunc f8)
+  {
+      CastFunc ff[]={f1,f2,f3,f4,f5,f6,f7,f8,0};
+      for (int i=0;ff[i];i++)
+	{
+	    ffassert(this == *ff[i] );
+	    if (casting->FindSameR(*ff[i]))
+	      {
+		  if(mpirank==0)
+		    {
+			cerr << " The casting to " << *ff[i] << " exists " << endl;
+			cerr << " List of cast " << endl;
+			casting->Show(cerr);
+		    }
+		  CompileError();
+	      }
+	    if (casting)  *casting += *ff[i];
+	    else casting = ff[i];
+	    /*      
+	     if( ! mapofcast.insert(make_pair<const aType,CastFunc>(ff[i]->a,ff[i])).second) 
+	     {
+	     cerr << " The casting to "<< *this << " from " << ff[i]->a << " exists " << endl;
+	     cerr << " List of cast " << endl;
+	     for_each(mapofcast.begin(),mapofcast.end(),CerrCast);
+	     CompileError();
+	     } */
+	}
+  }
+
+ ostream & operator<<(ostream & f,const OneOperator & a)     
+{
+//   for(const OneOperator * tt=&a;tt;tt=tt->next)
+     f << "\t  " << * (a.r) << " :  "  <<(const ArrayOfaType &) a;
+   return f;   
+}
+
+ ostream & operator<<(ostream & f,const Polymorphic & a)
+{
+  Polymorphic::const_iterator i;
+  if(!&a) return f << "Null " << endl;
+  for (i=a.m.begin();i!=a.m.end();i++)
+   {
+    f << "   operator" << i->first << " : " << endl;
+    i->second->Show(f);
+   }
+  return f;
+}  
+ ostream & operator<<(ostream & f,const ArrayOfaType & a)
+   { 
+     for (int i=0;i<a.n;i++) 
+       f <<  (i ? ", " : " ") << *a.t[i];
+       if (a.ellipse ) f << "... ";
+       else            f << " "; 
+      return f;}
+    ostream & operator<<(ostream & f,const TableOfIdentifier & t )
+ {
+   TableOfIdentifier::const_iterator i;
+   for(i=t.m.begin();i!=t.m.end();i++)
+    {
+      TableOfIdentifier::Value v=i->second;
+      f << i->first << ":  " << *v.first << " <- " ; 
+      const Polymorphic * p=dynamic_cast<const Polymorphic *>(v.second);
+      if(p) f << "Polymorphic " << *p << endl;
+      else  f << " Simple @" <<  v.second << endl;
+    }
+    return f;
+ }
+ 
+Expression NewExpression(Function1 f,Expression a)
+{
+  ffassert(f);
+  return new E_F0_Func1(f,a);
+}
+Expression NewExpression(Function2 f,Expression a,Expression b)
+{
+  ffassert(f);
+  return new E_F0_Func2(f,a,b);
+ 
+}
+ 
+ void ShowType(ostream & f)
+ {
+ 
+   map<const string,basicForEachType *>::const_iterator i;
+   for(i=map_type.begin();i!=map_type.end();i++)
+     {
+       f << " --"<< i->first <<" = " ; 
+       i->second->Show(f) ;
+       f << endl;
+     }
+
+ }
+
+ void basicForEachType::Show(ostream & f) const {
+       f << " " <<* this << endl;
+       if (casting) casting->Show(f) ;
+       if (ti.m.size())
+        { 
+          TableOfIdentifier::const_iterator mc=ti.m.begin();
+          TableOfIdentifier::const_iterator end=ti.m.end();
+          for (;mc != end;mc++)
+          {
+            f  << "    " << mc->first << ",  type :" <<  *mc->second.first << endl;
+            const Polymorphic * op =dynamic_cast<const Polymorphic *>(mc->second.second) ;
+            if ( op )  f << *op << endl;
+          }
+        }
+   }
+ 
+
+
+
+
+E_Routine::E_Routine(const Routine * routine,const basicAC_F0 & args)
+  :    code(routine->ins),
+       clean(routine->clean),
+       rt(routine->tret),      
+       nbparam(args.size()),
+       param(new Expression[nbparam]),
+       name(routine->name)
+{    
+   assert(routine->ins); 
+   for (int i=0;i<args.size();i++)  //  bug pb copie des string   dec 2007  FH  ???????????????
+   {
+      // cout << "E_Routine " << *routine->param[i].r << " <- " << *args[i].left() << endl;
+        param[i]=routine->param[i].r->CastTo(args[i]);
+   }
+};
+
+E_Routine::~E_Routine() { delete [] param;}
+
+struct CleanE_Routine {
+  const E_Routine * er; 
+    Stack s;
+    AnyType * l;
+    CleanE_Routine(const  E_Routine * r,Stack ss,AnyType *ll): er(r),s(ss),l(ll) {}
+    ~CleanE_Routine() {
+   // cout << " Clean E_routine " << er <<endl;	
+    (*er->clean)(s);
+    delete [] l; 
+    }
+};
+
+AnyType E_Routine::operator()(Stack s)  const  {
+   debugstack->push(pair<const E_Routine*,int>(this,TheCurrentLine));
+   const int lgsave=BeginOffset*sizeof(void*);
+   char  save[lgsave];
+   AnyType ret=Nothing;
+   memcpy(save,s,lgsave); // save  
+    AnyType *listparam;
+ //  Add2StackOfPtr2Free(s,new CleanE_Routine(this,s,listparam=new AnyType[nbparam]));
+    Add2StackOfPtr2FreeA(s,listparam=new AnyType[nbparam]);
+    
+    //   AnyType *listparam =Add2StackOfPtr2FreeA(s,new AnyType[nbparam]);
+   // 
+ //  WhereStackOfPtr2Free(s)->Add2StackOfPtr2Free(s,listparam);
+//  to day the memory gestion of the local variable are static,   
+   for (int i=0;i<nbparam;i++)
+     listparam[i]= (*param[i])(s); // set of the parameter 
+   Stack_Ptr<AnyType>(s,ParamPtrOffset) = listparam;
+   WhereStackOfPtr2Free(s)=new StackOfPtr2Free(s);// FH mars 2006 
+ 
+   try {  
+      ret=(*code)(s);  }
+   catch( E_exception & e) { 
+          // cout << " catch " << e.what() << " clean & throw " << endl;
+            if (e.type() == E_exception::e_return)
+              ret = e.r;
+           else 
+              ErrorExec("E_exception: break or contine not in loop ",1);
+  }
+  catch(...) { // clean and rethrow the exception 
+      //::delete [] listparam; 
+       (*clean)(s); 
+      WhereStackOfPtr2Free(s)->clean(); // FH mars 2005 
+      memcpy(s,save,lgsave);  // restore 
+      TheCurrentLine=debugstack->front().second;
+      debugstack->pop();
+      throw ;             
+     }
+  
+    (*clean)(s); //  the clean is done in CleanE_Routine delete .         
+   //  delete [] listparam; after return 
+    memcpy(s,save,lgsave);  // restore 
+    TheCurrentLine=debugstack->front().second;
+    debugstack->pop();
+   // il faudrait que les variable locale soit detruire apres le return 
+   // cf routine clean, pour le cas ou l'on retourne un tableau local.
+   // plus safe ?????  FH.  (fait 2008)
+   // mais pb si   a = f()+g()   OK les pointeurs des instruction sont detruit
+    //  en fin d'instruction programme de l'appelant  FH 2007 
+   // ... ou alors changer le return ???? qui doit copie le resultat.. (voir)
+   return ret;
+}
+
+void ListOfInst::Add(const C_F0 & ins) { 
+       if( (!ins.Empty()) ) {
+      if (n%nx==0){ 
+                Expression   *  l = new Expression [n+nx];
+                int * ln =  new int [n+nx];
+      			for (int i=0;i<n;i++) {
+      			  l[i]=list[i];
+      			  ln[i]=linenumber[i];}
+      			delete [] list;
+      			delete [] linenumber;
+      			list =l;
+      			linenumber=ln;
+      		    }
+      throwassert(list);
+      linenumber[n]= TheCurrentLine;		    
+      list[n++] = ins;
+      }}
+      
+/// <<ListOfInst::operator()>> Iteratively calls each item in the local array #list of type #Expression
+
+AnyType ListOfInst::operator()(Stack s) const {     
+    AnyType r; 
+    double s0=CPUtime(),s1=s0,ss0=s0;
+    StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
+    try { // modif FH oct 2006 
+	for (int i=0;i<n;i++) 
+	{
+	    TheCurrentLine=linenumber[i];
+	    r=(*list[i])(s);
+	    sptr->clean(); // modif FH mars 2006  clean Ptr
+	    s1=CPUtime();
+	    if (showCPU)  
+		cout << " CPU: "<< i << " " << s1-s0 << "s" << " " << s1-ss0 << "s" << endl;
+	    s0=CPUtime();
+	}
+    }
+    catch( E_exception & e) 	
+    {
+	if (e.type() != E_exception::e_return)  
+	    sptr->clean(); // pour ne pas detruire la valeur retourne  ...  FH  jan 2007
+	throw; // rethow  
+    }
+    catch(...)
+    {
+	sptr->clean();
+	throw; 
+    }
+    return r;}
+
+AnyType E_block::operator()(Stack s)  const {
+    StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
+    if (clean) 
+    {
+	try { 
+	    for (int i=0;i<n;i++) {
+		TheCurrentLine=linenumber[i];
+		(*code[i])(s); 
+		sptr->clean();
+		
+            }}
+	catch( E_exception & e) { 
+	    (*clean)(s); 
+	    if (e.type() != E_exception::e_return)  
+		sptr->clean();
+	    throw; // rethow  
+	}
+	catch(/* E_exception & e*/...) { // catch all for cleanning 
+	    (*clean)(s); 
+	    sptr->clean();
+	    // if(verbosity>50)
+	    //  cout << " catch " << e.what() << " clean & throw " << endl;
+	    // throw(e);
+            throw; // rethow 
+	}
+	
+	(*clean)(s); 
+	sptr->clean();
+	
+    }
+    else  // not catch  exception if no clean (optimization} 
+	for (int i=0;i<n;i++) 
+	{
+	    (*code[i])(s); 
+	    sptr->clean(); // mars 2006 FH clean Ptr
+	}
+	    return Nothing;
+   }
+
+
+void ShowDebugStack()
+ {
+   if (mpisize)
+   cerr << "  current line = " << TheCurrentLine  
+        << " mpirank " << mpirank << " / " << mpisize <<endl; 
+   else
+   cerr << "  current line = " << TheCurrentLine  << endl;
+  if(debugstack)
+   while ( debugstack->size() )
+     {
+        
+        cerr << " call " << debugstack->front().first->name<< "  at  line "
+             <<debugstack->front().second << endl;
+        debugstack->pop();
+     }
+ }
+ 
+
+  int  E_F0::Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n)  
+     {
+      int rr = find(m);
+      if (rr) return rr;
+      if( (verbosity / 10)% 10 == 1) 
+      	 cout << "\n new expression : " << n  << " mi=" << MeshIndependent()<< " " << typeid(*this).name()  
+      	      << " :" << *this << endl;        
+       return insert(this,l,m,n);
+     }   
+     
+
+class E_F0para :public E_F0 { public:
+  const int i;
+  AnyType operator()(Stack s)  const  {
+  //  return  (* Stack_Ptr<Expression>(s,ParamPtrOffset)[i])(s);
+    return Stack_Ptr<AnyType>(s,ParamPtrOffset)[i];
+  }
+   E_F0para(int ii) : i(ii){}
+};        
+     
+Routine::Routine(aType tf,aType tr,const char * iden,  ListOfId *l,Block * & cb)
+    : OneOperator(tr,l),offset(cb->OffSet(sizeof(void*))),
+     tfunc(tf),tret(tr),name(iden),param(*l),
+      currentblock(new Block(cb)),ins(0),clean(0) 
+     {
+       delete l;  // add  FH 24032005 (trap ) 
+       cb = currentblock; 
+	// cout <<"Routine: tf = " << *tf << "  " <<  *tr << endl;
+       for (size_t i=0;i<param.size();i++)
+       {
+	//   cout << "Routine " << i << " ref=  " << param[i].ref << " " << *param[i].r << " " << *param[i].r->right() << endl;
+           currentblock->NewID(param[i].r,param[i].id,C_F0(new E_F0para(i),// modif FH 2007 
+							   param[i].r), 
+							  // (param[i].ref ? param[i].r :  param[i].r->right() ),
+							   !param[i].ref);
+       }
+     }
+   Block * Routine::Set(C_F0 instrs) 
+       { 
+         ins=instrs;
+         clean = (C_F0) currentblock->close(currentblock);
+         return    currentblock;} 
+         
+ 
+E_F0 * Routine::code(const basicAC_F0 & args) const 
+{
+   
+   return new E_Routine(this,args);
+}
+
+void basicAC_F0::SetNameParam(int n,name_and_type *l , Expression * e) const 
+{
+ int k=0;
+ if ( !n && !named_parameter)  return;
+ 
+  for (int i=0;i<n;i++)
+  {
+     C_F0  ce=find(l[i].name) ;
+     if (ce.LeftValue()==0)
+       e[i]=0;
+     else  {
+       if(!map_type[l[i].type->name()] )
+	 {
+	     if(mpirank==0)
+	       {
+		   cerr << " missing ff type: '" <<l[i].type->name() << "'   "<< map_type.size()  <<  "\n";
+		   cerr << "i= " << i << "\n";
+	       }
+	   InternalError(" missing type ");
+	   assert(map_type[l[i].type->name()]);
+	 }
+       e[i]= map_type[l[i].type->name()]->CastTo(ce);
+       k++;
+       }
+  }
+  
+ if (!named_parameter) return;
+  
+  if ((size_t) k!=  named_parameter->size()) 
+   {
+      cout << " Sorry some name parameter are not used!  found" <<  k << " == " << named_parameter->size() <<endl;
+      for(const_iterator ii=named_parameter->begin(); ii != named_parameter->end();ii++)
+       {
+        for (int i=0;i<n;i++)
+          if (!strcmp(l[i].name,ii->first)) 
+            goto L1;
+         cout << "\t the parameter is '" << ii->first << "' is unused " << endl;
+        L1:;
+       }
+    if ( n && mpirank==0) {
+    cerr << " The named parameter can be " << endl;
+    for (int i=0;i<n;i++)
+       cerr << "\t" << l[i].name << " =  <" << l[i].type->name() << ">\n";
+    }
+    CompileError("Unused named parameter");  
+   }
+}
+
+
+//  change FH to bluid .dll 
+
+void lgerror (const char* s) 
+  {
+      if(mpirank==0)
+	{
+	    cerr << endl;
+	    cerr <<" Error line number " << zzzfff->lineno() << ", in file " << zzzfff->filename() 
+	    <<", before  token " <<zzzfff->YYText() << endl
+	    << s << endl;
+	}
+      throw(ErrorCompile(s,zzzfff->lineno(),zzzfff->YYText() ));
+  }
+
diff --git a/src/fflib/AFunction_ext.hpp b/src/fflib/AFunction_ext.hpp
new file mode 100644
index 0000000..00c7ece
--- /dev/null
+++ b/src/fflib/AFunction_ext.hpp
@@ -0,0 +1,622 @@
+// In order to use functions with the stack and 2 parameters , and more  new classes (OneOperator2s_, OneOperator3s_, etc.) must
+// In order to use functions with more than 3 parameters, new classes (OneOperator4_, OneOperator5_, etc.) must
+// be defined. See example code in include/AFunction.hpp
+// Two classes must be defined (here we show an example for a function accepting 4 arguments):
+//
+//  class OneOperator4_ 
+//  class E_F_F0F0F0F0_
+//
+// Note: in file includeAFunction.hpp, the class "OneOperator" (around line 400) mut be modified.
+// ************************************************
+// Add F. Hecht  oct 2009
+// ****  2 paramters with the stack
+//  class OneOperator2s_
+//  class E_F_F0F0s_                                                                                                                                                      
+#ifndef AFUNCTION_EXT_HPP__
+#define  AFUNCTION_EXT_HPP__
+template<class R,class A0,class A1, class E=E_F0>   // extend (4th arg.)
+class E_F_F0F0s_ :public  E { public:                               // extend 
+    typedef  R (*func)(Stack s,const  A0 &,const  A1 & ) ; // extend (statck +2th arg.)
+  func f;
+  Expression a0,a1;          // extend
+  E_F_F0F0s_(func ff,
+	     Expression aa0,
+	     Expression aa1)
+    : f(ff), a0(aa0), a1(aa1) {}  // extend (2th arg.)
+  AnyType operator()(Stack s)  const 
+  {return SetAny<R>( f( s,
+			GetAny<A0>((*a0)(s)),
+			GetAny<A1>((*a1)(s))  ) );}   // extend (2th arg.)
+  virtual size_t nbitem() const {return a1->nbitem(); } // modif ??? 
+  bool MeshIndependent() const 
+  {return a0->MeshIndependent() && a1->MeshIndependent() ;} // extend (2th arg.)
+  
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class CODE=E_F_F0F0s_<R,A,B,E_F0> >    // extend (4th arg.)
+class  OneOperator2s_ : public OneOperator {     // 
+  aType r; //  return type 
+  typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+    {     if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	CompileError( " They are used Named parameter ");
+
+      return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]));}     // extend
+  OneOperator2s_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()]),      // extens
+    f(ff){}
+};
+
+
+
+// ****  2 paramters with the stack
+//  class OneOperator2s_
+//  class E_F_F0F0s_                                                                                                                                                      
+
+template<class R,class A0,class A1,class A2, class E=E_F0>   // extend (4th arg.)
+class E_F_F0F0F0s_ :public  E { public:                               // extend 
+    typedef  R (*func)(Stack s,const  A0 &,const  A1 &,const A2 & ) ; // extend (statck +2th arg.)
+  func f;
+  Expression a0,a1,a2;          // extend
+  E_F_F0F0F0s_(func ff,
+	     Expression aa0,
+	     Expression aa1,
+	     Expression aa2)
+    : f(ff), a0(aa0), a1(aa1), a2(aa2) {}  // extend (2th arg.)
+  AnyType operator()(Stack s)  const 
+  {return SetAny<R>( f( s,
+			GetAny<A0>((*a0)(s)),
+			GetAny<A0>((*a1)(s)),
+			GetAny<A1>((*a2)(s))  ) );}   // extend (3th arg.)
+  virtual size_t nbitem() const {return a2->nbitem(); } // modif ??? 
+  bool MeshIndependent() const 
+  {return a0->MeshIndependent() && a1->MeshIndependent() && a2->MeshIndependent() ;} // extend (2th arg.)
+  
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class CODE=E_F_F0F0F0s_<R,A,B,C,E_F0> >    // extend (3th arg.)
+class  OneOperator3s_ : public OneOperator {     // 
+  aType r; //  return type 
+  typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+      if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	  CompileError( " They are used Named parameter ");
+
+      return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[0]->CastTo(args[1]),
+		     t[1]->CastTo(args[2]));}     // extend
+  OneOperator3s_(func  ff):                        // 2->
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()]),      // extend
+    f(ff){}
+};
+// ***********************************************
+
+// ***********************************************
+// **** 4 parameters
+// ***********************
+template<class R,class A0,class A1,class A2, class A3, class E=E_F0>   // extend (4th arg.)
+class E_F_F0F0F0F0_ :public  E { public:                               // extend 
+   typedef  R (*func)(const  A0 &,const  A1 & , const A2 &, const A3 & ) ; // extend (4th arg.)
+  func f;
+  Expression a0,a1,a2,a3;          // extend
+  E_F_F0F0F0F0_(func ff,
+		Expression aa0,
+		Expression aa1,
+		Expression aa2,
+		Expression aa3)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3) {}  // extend (4th arg.)
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s))  ) );}   // extend (4th arg.)
+  virtual size_t nbitem() const {return a3->nbitem(); } // modif
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()&& a3->MeshIndependent();} // extend (4th arg.)
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class CODE=E_F_F0F0F0F0_<R,A,B,C,D,E_F0> >    // extend (4th arg.)
+class  OneOperator4_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+    {  
+	if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	    CompileError( " They are used Named parameter ");
+	
+	return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]));}     // extend
+  OneOperator4_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()]),      // extens
+    f(ff){}
+};
+
+
+
+template<class R,class A0,class A1,class A2, class A3, class E=E_F0>   // extend (4th arg.)
+class E_F_F0F0F0F0s_ :public  E { public:                               // extend 
+    typedef  R (*func)(Stack, const  A0 &,const  A1 & , const A2 &, const A3 & ) ; // extend (4th arg.)
+  func f;
+  Expression a0,a1,a2,a3;          // extend
+  E_F_F0F0F0F0s_(func ff,
+		Expression aa0,
+		Expression aa1,
+		Expression aa2,
+		Expression aa3)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3) {}  // extend (4th arg.)
+  AnyType operator()(Stack s)  const 
+  {return SetAny<R>( f( s, GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s))  ) );}   // extend (4th arg.)
+  virtual size_t nbitem() const {return a3->nbitem(); } // modif
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()&& a3->MeshIndependent();} // extend (4th arg.)
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class CODE=E_F_F0F0F0F0s_<R,A,B,C,D,E_F0> >    // extend (4th arg.)
+class  OneOperator4s_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+    {  
+	if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	    CompileError( " They are used Named parameter ");
+	
+	return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]));}     // extend
+  OneOperator4s_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()]),      // extens
+    f(ff){}
+};
+
+
+// ***********************************************
+// **** 5 parameters
+// ***********************
+//
+//  NOTE: add the following line in AFunction.hpp
+//
+//    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e) 
+//      : r(rr),ArrayOfaType(a,b,c,d,e,false),next(0),pref(0) {throwassert(rr && a && b && c && d);} 
+
+template<class R,class A0,class A1,class A2, class A3, class A4, class E=E_F0>   // extend AX
+class E_F_F0F0F0F0F0_ :public  E { public:                               // extend 
+   typedef  R (*func)(const  A0 &,const  A1 & , const A2 &, const A3 &, const A4 & ) ; // extend AX
+  func f;
+  Expression a0,a1,a2,a3,a4;          // extend aX
+  E_F_F0F0F0F0F0_(func ff,            // extend F0
+		  Expression aa0,
+		  Expression aa1,
+		  Expression aa2,
+		  Expression aa3,
+		  Expression aa4)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3), a4(aa4) {}  // extend aX
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s)),
+			  GetAny<A4>((*a4)(s))  ) );}   // extend aX
+    virtual size_t nbitem() const {return a4->nbitem(); } 
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()
+	 && a3->MeshIndependent()&& a4->MeshIndependent();} // extend aX
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class E=D ,class CODE=E_F_F0F0F0F0F0_<R,A,B,C,D,E,E_F0> >    // extend  
+class  OneOperator5_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+    {  
+	if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	    CompileError( " They are used Named parameter ");
+	
+	return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]),
+		     t[4]->CastTo(args[4]));}     // extend
+  OneOperator5_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()],
+		map_type[typeid(E).name()]),      // extend
+    f(ff){}
+};
+
+// ***********************************************
+// **** 6 parameters
+// ***********************
+//
+//  NOTE: add the following line in AFunction.hpp
+//    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f) 
+//       : r(rr),ArrayOfaType(a,b,c,d,e,f,false),next(0),pref(0) {throwassert(rr && a && b && c && d && f);} 
+
+template<class R,class A0,class A1,class A2, class A3, class A4, class A5, class E=E_F0>   // extend AX
+class E_F_F0F0F0F0F0F0_ :public  E { public:                               // extend 
+   typedef  R (*func)(const  A0 &,const  A1 & , const A2 &, const A3 &, const A4 &, const A5 & ) ; // extend AX
+  func f;
+  Expression a0,a1,a2,a3,a4,a5;          // extend aX
+  E_F_F0F0F0F0F0F0_(func ff,            // extend F0
+		    Expression aa0,
+		    Expression aa1,
+		    Expression aa2,
+		    Expression aa3,
+		    Expression aa4,
+		    Expression aa5)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3), a4(aa4), a5(aa5) {}  // extend aX
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s)),
+			  GetAny<A4>((*a4)(s)),
+			  GetAny<A5>((*a5)(s)) ) );}   // extend aX
+    virtual size_t nbitem() const {return a5->nbitem(); } 
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()
+	 && a3->MeshIndependent()&& a4->MeshIndependent()&& a5->MeshIndependent();} // extend aX
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class E=D ,class F=E ,class CODE=E_F_F0F0F0F0F0F0_<R,A,B,C,D,E,F,E_F0> >    // extend  
+class  OneOperator6_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+    {  
+	if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	    CompileError( " They are used Named parameter ");
+	
+	return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]),
+		     t[4]->CastTo(args[4]),
+		     t[5]->CastTo(args[5]));}     // extend
+  OneOperator6_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()],
+		map_type[typeid(E).name()],
+		map_type[typeid(F).name()]),      // extend
+    f(ff){}
+};
+
+
+// ***********************************************
+// **** 7 parameters
+// ***********************
+//
+//  NOTE: add the following line in AFunction.hpp
+//    OneOperator(aType rr,aType  a,aType  b,aType c,aType d,aType e,aType f) 
+//       : r(rr),ArrayOfaType(a,b,c,d,e,f,false),next(0),pref(0) {throwassert(rr && a && b && c && d && f);} 
+
+template<class R,class A0,class A1,class A2, class A3, class A4, class A5, class A6, class E=E_F0>   // extend AX
+class E_F_F0F0F0F0F0F0F0_ :public  E { public:                               // extend 
+   typedef  R (*func)(const  A0 &,const  A1 & , const A2 &, const A3 &, const A4 &, const A5 &, const A6 & ) ; // extend AX
+  func f;
+  Expression a0,a1,a2,a3,a4,a5,a6;          // extend aX
+  E_F_F0F0F0F0F0F0F0_(func ff,            // extend F0
+		      Expression aa0,
+		      Expression aa1,
+		      Expression aa2,
+		      Expression aa3,
+		      Expression aa4,
+		      Expression aa5,
+		      Expression aa6)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3), a4(aa4), a5(aa5), a6(aa6) {}  // extend aX
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s)),
+			  GetAny<A4>((*a4)(s)),
+			  GetAny<A5>((*a5)(s)),
+			  GetAny<A6>((*a6)(s)) ) );}   // extend aX
+  virtual size_t nbitem() const {return a6->nbitem(); } // modif
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()
+	 && a3->MeshIndependent()&& a4->MeshIndependent()&& a5->MeshIndependent()&& a6->MeshIndependent();} // extend aX
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class E=D ,class F=E ,class G=F ,class CODE=E_F_F0F0F0F0F0F0F0_<R,A,B,C,D,E,F,G,E_F0> >    // extend  
+class  OneOperator7_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+    {  
+	if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	    CompileError( " They are used Named parameter ");
+	
+	return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]),
+		     t[4]->CastTo(args[4]),
+		     t[5]->CastTo(args[5]),
+		     t[6]->CastTo(args[6]));}     // extend
+  OneOperator7_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()],
+		map_type[typeid(E).name()],
+		map_type[typeid(F).name()],
+		map_type[typeid(G).name()]),      // extend
+    f(ff){}
+};
+
+
+
+// ***********************************************
+// **** 8 parameters
+// ***********************
+//
+
+template<class R,class A0,class A1,class A2, class A3, class A4, class A5, class A6, class A7, class E=E_F0>   // extend AX
+class E_F_F0F0F0F0F0F0F0F0_ :public  E { public:                               // extend 
+   typedef  R (*func)(const  A0 &,const  A1 & , const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 & ) ; // extend AX
+  func f;
+  Expression a0,a1,a2,a3,a4,a5,a6,a7;          // extend aX
+  E_F_F0F0F0F0F0F0F0F0_(func ff,            // extend F0
+			Expression aa0,
+			Expression aa1,
+			Expression aa2,
+			Expression aa3,
+			Expression aa4,
+			Expression aa5,
+			Expression aa6,
+			Expression aa7)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3), a4(aa4), a5(aa5), a6(aa6), a7(aa7) {}  // extend aX
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s)),
+			  GetAny<A4>((*a4)(s)),
+			  GetAny<A5>((*a5)(s)),
+			  GetAny<A6>((*a6)(s)),
+			  GetAny<A7>((*a7)(s)) ) );}   // extend aX
+  virtual size_t nbitem() const {return a7->nbitem(); } // modif
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()
+	 && a3->MeshIndependent()&& a4->MeshIndependent()&& a5->MeshIndependent()&& a6->MeshIndependent()&& a7->MeshIndependent();} // extend aX
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class E=D ,class F=E ,class G=F ,class H=G , class CODE=E_F_F0F0F0F0F0F0F0F0_<R,A,B,C,D,E,F,G,H,E_F0> >    // extend  
+class  OneOperator8_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+    {  
+	if ( args.named_parameter && !args.named_parameter->empty()  ) 
+	    CompileError( " They are used Named parameter ");
+	
+	return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]),
+		     t[4]->CastTo(args[4]),
+		     t[5]->CastTo(args[5]),
+		     t[6]->CastTo(args[6]),
+		     t[7]->CastTo(args[7]));}     // extend
+  OneOperator8_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()],
+		map_type[typeid(E).name()],
+		map_type[typeid(F).name()],
+		map_type[typeid(G).name()],
+		map_type[typeid(H).name()]),      // extend
+    f(ff){}
+};
+
+
+// ***********************************************
+// **** 9 parameters
+// ***********************
+//
+
+/*
+template<class R,class A0,class A1,class A2, class A3, class A4, class A5, class A6, class A7, class A8, class E=E_F0>   // extend AX
+class E_F_F0F0F0F0F0F0F0F0F0_ :public  E { public:                               // extend 
+   typedef  R (*func)(const  A0 &,const  A1 & , const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 & ) ; // extend AX
+  func f;
+  Expression a0,a1,a2,a3,a4,a5,a6,a7,a8;          // extend aX
+  E_F_F0F0F0F0F0F0F0F0F0_(func ff,            // extend F0
+			  Expression aa0,
+			  Expression aa1,
+			  Expression aa2,
+			  Expression aa3,
+			  Expression aa4,
+			  Expression aa5,
+			  Expression aa6,
+			  Expression aa7,
+			  Expression aa8)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3), a4(aa4), a5(aa5), a6(aa6), a7(aa7), a8(aa8) {}  // extend aX
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s)),
+			  GetAny<A4>((*a4)(s)),
+			  GetAny<A5>((*a5)(s)),
+			  GetAny<A6>((*a6)(s)),
+			  GetAny<A7>((*a7)(s)),
+			  GetAny<A8>((*a8)(s)) ) );}   // extend aX
+  virtual size_t nbitem() const {return a8->nbitem(); } // modif
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()
+	 && a3->MeshIndependent()&& a4->MeshIndependent()&& a5->MeshIndependent()&& a6->MeshIndependent()&& a7->MeshIndependent()&& a8->MeshIndependent();} // extend aX
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class E=D ,class F=E ,class G=F ,class H=G ,class I=H , class CODE=E_F_F0F0F0F0F0F0F0F0F0_<R,A,B,C,D,E,F,G,H,I,E_F0> >    // extend  
+class  OneOperator9_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+  { return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]),
+		     t[4]->CastTo(args[4]),
+		     t[5]->CastTo(args[5]),
+		     t[6]->CastTo(args[6]),
+		     t[7]->CastTo(args[7]),
+		     t[8]->CastTo(args[8]));}     // extend
+  OneOperator9_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()],
+		map_type[typeid(E).name()],
+		map_type[typeid(F).name()],
+		map_type[typeid(G).name()],
+		map_type[typeid(H).name()],
+		map_type[typeid(I).name()]),      // extend
+    f(ff){}
+};
+*/
+
+/*
+
+//
+// ***********************************************
+// **** 10 parameters
+// ***********************
+//
+
+template<class R,class A0,class A1,class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9, class E=E_F0>   // extend AX
+class E_F_F0F0F0F0F0F0F0F0F0F0_ :public  E { public:                               // extend 
+   typedef  R (*func)(const  A0 &,const  A1 & , const A2 &, const A3 &, const A4 &, const A5 &, const A6 &, const A7 &, const A8 &, const A9 & ) ; // extend AX
+  func f;
+  Expression a0,a1,a2,a3,a4,a5,a6,a7,a8,a9;          // extend aX
+  E_F_F0F0F0F0F0F0F0F0F0F0_(func ff,            // extend F0
+			    Expression aa0,
+			    Expression aa1,
+			    Expression aa2,
+			    Expression aa3,
+			    Expression aa4,
+			    Expression aa5,
+			    Expression aa6,
+			    Expression aa7,
+			    Expression aa8,
+			    Expression aa9)   // extend 
+    : f(ff), a0(aa0), a1(aa1), a2(aa2), a3(aa3), a4(aa4), a5(aa5), a6(aa6), a7(aa7), a8(aa8), a9(aa9) {}  // extend aX
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)),
+			  GetAny<A1>((*a1)(s)),
+			  GetAny<A2>((*a2)(s)),
+			  GetAny<A3>((*a3)(s)),
+			  GetAny<A4>((*a4)(s)),
+			  GetAny<A5>((*a5)(s)),
+			  GetAny<A6>((*a6)(s)),
+			  GetAny<A7>((*a7)(s)),
+			  GetAny<A8>((*a8)(s)),
+			  GetAny<A9>((*a9)(s)) ) );}   // extend aX
+  virtual size_t nbitem() const {return a9->nbitem(); } // modif 
+      bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent()&& a2->MeshIndependent()
+	 && a3->MeshIndependent()&& a4->MeshIndependent()&& a5->MeshIndependent()&& a6->MeshIndependent()
+	 && a7->MeshIndependent()&& a8->MeshIndependent()&& a9->MeshIndependent();} // extend aX
+
+};
+
+template<class R,class A=R,class B=A,class C=B, class D=C ,class E=D ,class F=E ,class G=F ,class H=G ,class I=H , class J=I , class CODE=E_F_F0F0F0F0F0F0F0F0F0F0_<R,A,B,C,D,E,F,G,H,I,J,E_F0> >    // extend  
+class  OneOperator10_ : public OneOperator {     // 3->4
+  aType r; //  return type 
+    typedef typename  CODE::func  func;
+  func f;
+public: 
+  E_F0 * code(const basicAC_F0 & args) const 
+  { return  new CODE(f,
+		     t[0]->CastTo(args[0]),
+		     t[1]->CastTo(args[1]),
+		     t[2]->CastTo(args[2]),
+		     t[3]->CastTo(args[3]),
+		     t[4]->CastTo(args[4]),
+		     t[5]->CastTo(args[5]),
+		     t[6]->CastTo(args[6]),
+		     t[7]->CastTo(args[7]),
+		     t[8]->CastTo(args[8]),
+		     t[9]->CastTo(args[9]));}     // extend
+  OneOperator10_(func  ff):                        // 3->4
+    OneOperator(map_type[typeid(R).name()],
+		map_type[typeid(A).name()],
+		map_type[typeid(B).name()],
+		map_type[typeid(C).name()],
+		map_type[typeid(D).name()],
+		map_type[typeid(E).name()],
+		map_type[typeid(F).name()],
+		map_type[typeid(G).name()],
+		map_type[typeid(H).name()],
+		map_type[typeid(I).name()],
+		map_type[typeid(J).name()]),      // extend
+    f(ff){}
+};
+
+*/
+#endif
diff --git a/src/fflib/AddNewFE.h b/src/fflib/AddNewFE.h
new file mode 100644
index 0000000..3f6eec8
--- /dev/null
+++ b/src/fflib/AddNewFE.h
@@ -0,0 +1,104 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+// to add Finite Element to ff++
+class EConstantTypeOfFE :public E_F0
+{ 
+//  using namespace   Fem2D;
+  Fem2D::TypeOfFE * v;
+  size_t N;
+  bool isconst;
+public:
+  AnyType operator()(Stack ) const { /*cout << " ()" << v << endl*/;return SetAny<Fem2D::TypeOfFE*>(v);}
+    EConstantTypeOfFE( Fem2D::TypeOfFE * o,bool ic=true):v(o),N(v->N),isconst(ic) {assert(v); /*cout << "New constant " << o << endl;*/}
+  size_t nbitem() const { return N ;} 
+  EConstantTypeOfFE & operator=(Fem2D::TypeOfFE * vv) {
+      ffassert( !isconst  && vv && (vv->N == N)); //  same type 
+      v = vv;       
+      return  *this;
+  }
+   operator aType () const { assert(v);return atype<Fem2D::TypeOfFE*>();} 
+};
+
+
+struct AddNewFE {  
+  AddNewFE (const char * FEname,Fem2D::TypeOfFE* tfe) 
+  {
+    ffassert(tfe); // check 
+    Global.New(FEname, Type_Expr(atype<Fem2D::TypeOfFE*>() ,new  EConstantTypeOfFE(tfe)));
+  }
+};
+
+// 3d case 
+
+
+class EConstantTypeOfFE3 :public E_F0
+{ public:
+    //  using namespace   Fem2D;
+    typedef Fem2D::TypeOfFE3 * T;
+    T  v;
+public:
+    AnyType operator()(Stack ) const { /*cout << " ()" << v << endl*/;return SetAny<T>(v);}
+    EConstantTypeOfFE3( T o):v(o) { /*cout << "New constant " << o << endl;*/}
+    size_t nbitem() const { assert(v);
+	cout << " nb item = " << v->N << endl;
+	return v->N ;} 
+    operator aType () const { return atype<T>();} 
+};
+
+
+Type_Expr CConstantTFE3(const EConstantTypeOfFE3::T & v);
+
+/*
+class EConstantTypeOfFE3 :public E_F0
+{ 
+    //  using namespace   Fem2D;
+    Fem2D::TypeOfFE3 * v;
+    size_t N;
+    bool isconst;
+public:
+    AnyType operator()(Stack ) const { return SetAny<Fem2D::TypeOfFE3*>(v);}
+    EConstantTypeOfFE3( Fem2D::TypeOfFE3 * o,bool ic=true):v(o),N(v->N),isconst(ic) {assert(v); //cout << "New constant " << o << endl;}
+    size_t nbitem() const { return N ;} 
+    EConstantTypeOfFE3 & operator=(Fem2D::TypeOfFE3 * vv) {
+	ffassert( !isconst  && vv && (vv->N == N)); //  same type 
+	v = vv;       
+    }
+    operator aType () const { assert(v);return atype<Fem2D::TypeOfFE3*>();} 
+};
+*/
+extern map<TypeOfFE *,TypeOfFE3 *> TEF2dto3d;
+TypeOfFE * FindFE2(const char * s);
+struct AddNewFE3 {  
+    AddNewFE3 (const char * FEname,Fem2D::TypeOfFE3* tfe,const char * FEname2=0) 
+    {
+      ffassert(tfe); // check 
+      Global.New(FEname, Type_Expr(atype<Fem2D::TypeOfFE3*>() ,new  EConstantTypeOfFE3(tfe)));
+      if(FEname2 && strlen(FEname2))
+	  TEF2dto3d[FindFE2(FEname2)]=tfe;
+    }
+};
diff --git a/src/fflib/AnyType.hpp b/src/fflib/AnyType.hpp
new file mode 100644
index 0000000..ac2b94f
--- /dev/null
+++ b/src/fflib/AnyType.hpp
@@ -0,0 +1,202 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//   definition of the a type to store any bacis type
+//   void *, long, double, complex, all bigger type 
+//   are pointer 
+//#define WITHCHECK
+
+/// cf [[file:AFunction.hpp::basicForEachType]]
+
+class basicForEachType;
+
+/// <<aType>> uses [[file:AFunction.hpp::basicForEachType]]
+
+typedef const  basicForEachType * aType;
+
+ostream & operator<<(ostream & f,const basicForEachType & e);
+
+//typedef  unsigned char  AnyData[24]; 
+
+//typedef  unsigned char  AnyData[2*(sizeof(void*)+2*sizeof(double))];
+//  change for 64 architecture must containt 2*(1 ptr + 3 long))
+//  and for 32    2( ptr + 2 double) 
+//  so 2( 3ptr + double ) sims Ok FH MAI 2006
+//typedef  unsigned char  AnyData[2*(3*sizeof(void*)+sizeof(double))];
+typedef  unsigned char  AnyData[2*(5*sizeof(void*))]; //  change . 
+
+
+extern map<const string,basicForEachType *> map_type;
+
+template <class T,bool ok>
+  class CheckSize { } ;
+template <class T>
+class CheckSize<T,false> {
+  CheckSize() { } // private constructor to see the error
+} ;
+class AnyTypeWithCheck  { 
+
+ private:  
+    union { 
+      AnyData data;
+      void * p;
+      double r;  
+      long l;
+      bool b;
+//      complex<double> c;
+    };
+ public:
+    const basicForEachType *ktype; 
+//    friend ostream & operator<<(ostream &f,const AnyTypeWithCheck &p);  
+    AnyTypeWithCheck(): ktype(0){}
+    AnyTypeWithCheck(long ll)   {l=ll;ktype=map_type[typeid(long).name()];}
+    AnyTypeWithCheck(double dd) {r=dd;ktype=map_type[typeid(double).name()];}
+    AnyTypeWithCheck(bool bb ) {b=bb;ktype=map_type[typeid(bool).name()];}
+    
+    void operator =(void *pp){p=pp;}
+};
+
+class AnyTypeWithOutCheck  { 
+    
+ public: 
+    union { 
+      AnyData data;
+      void * p;
+      double r;  
+      long l;
+      bool b;
+//      complex<double> c;
+    };
+ public:
+    AnyTypeWithOutCheck(){}
+    AnyTypeWithOutCheck(long ll)   {l=ll;}
+    AnyTypeWithOutCheck(double dd) {r=dd;}
+    AnyTypeWithOutCheck(void *pp ) {p=pp;}
+    AnyTypeWithOutCheck(bool bb ) {b=bb;}
+  
+    void operator =(void *pp){p=pp;}
+};
+
+#ifdef WITHCHECK
+typedef   AnyTypeWithCheck AnyType; 
+#else
+typedef   AnyTypeWithOutCheck AnyType; 
+#endif
+static AnyType Nothing;
+
+  
+#ifdef WITHCHECK  
+
+template<typename T>   AnyTypeWithCheck SetAny(const T & x)
+  { 
+	AnyTypeWithCheck any;
+    CheckSize<T,sizeof(T)<= sizeof(AnyData) >();
+	throwassert( (any.ktype=map_type[typeid(T).name()]));
+	throwassert (sizeof(T) <= sizeof(AnyData));
+	//a.t=x;
+	memcpy(&any,&x,sizeof(x));
+	return any;
+  }
+  
+inline AnyTypeWithCheck PtrtoAny(void * p,aType r)
+  {
+	AnyTypeWithCheck any;
+    any=p;
+	throwassert(any.ktype=r);    
+	return any;
+  }
+
+  
+#else
+
+ template<typename T>   AnyTypeWithOutCheck inline SetAny(const T & x)
+  { 
+   AnyTypeWithOutCheck any;
+   CheckSize<T,sizeof(T)<= sizeof(AnyData) >();
+   // plus stable ???  F avril 2006 FH. 
+   memcpy(&any,&x,sizeof(x));
+   // plante  de temps en temps sous wind32 .  FH 
+    //any = *(  (AnyTypeWithOutCheck *) (void *) &x); 
+   return any;
+  }
+  
+inline AnyTypeWithOutCheck PtrtoAny(void * p,aType )
+  {
+    return p;
+  }
+ template<>  inline AnyTypeWithOutCheck SetAny<double>(const double & x)
+  { return x;}
+ template<> inline  AnyTypeWithOutCheck SetAny<long>(const long & x)
+  { return x;}
+ template<> inline  AnyTypeWithOutCheck SetAny<bool>(const bool & x)
+  { return x;}
+
+ template<typename T>  inline  AnyTypeWithOutCheck SetAny( T *  x)
+ { return reinterpret_cast<void *>( x);}
+ template<typename T>  inline  AnyTypeWithOutCheck SetAny( const T * x)
+ { return reinterpret_cast<void *>( x);}
+
+  
+  
+#endif
+ template<class T> inline const T& GetAny(const AnyTypeWithCheck & x);
+ 
+ template<class T> inline  const T& GetAny(const AnyTypeWithCheck & x)
+{ 
+ CheckSize<T,sizeof(T)<= sizeof(AnyData) >();
+ if (x.ktype!=map_type[typeid(T).name()])
+   { cerr<< "GetAny: PB type <";
+   cerr <<typeid(T).name();
+   cerr << "> <=" << *(x.ktype) << endl;
+   throw(ErrorExec("exit",1));}
+ return *static_cast<const T*>(static_cast<const void*>(&x));
+}
+
+
+
+
+
+ template<typename T> inline  const T& GetAny(const AnyTypeWithOutCheck & x)
+{ 
+ CheckSize<T,sizeof(T)<= sizeof(AnyData) >();
+ return *static_cast<const T*>(static_cast<const void*>(&x));
+}
+
+ template<> inline const double& GetAny<double>(const AnyTypeWithOutCheck & x)
+ { return x.r;} 
+ template<>  inline const long& GetAny<long>(const AnyTypeWithOutCheck & x)
+ { return x.l;} 
+ template<>  inline const bool& GetAny<bool>(const AnyTypeWithOutCheck & x)
+ { return x.b;} 
+
+ template<class T>  inline T * PGetAny(const AnyTypeWithOutCheck & x)
+ { return static_cast< T*>(x.p);} 
+ 
+ //template<class T>  inline   T * const & GetAny<T*>(const AnyTypeWithOutCheck & x)
+ //  { return  x.p;}
+
+
diff --git a/src/fflib/CodeAlloc.cpp b/src/fflib/CodeAlloc.cpp
new file mode 100644
index 0000000..d832222
--- /dev/null
+++ b/src/fflib/CodeAlloc.cpp
@@ -0,0 +1,161 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <iostream>
+#include <typeinfo>
+#include <cstddef>
+#include <cstdlib>
+#include <cassert>
+#include "error.hpp"
+using namespace std;
+
+#include "CodeAlloc.hpp"
+
+/* now in global.cpp 
+size_t CodeAlloc::nb=0, CodeAlloc::lg=0,CodeAlloc::nbpx=0,CodeAlloc::chunk=2048; 
+size_t CodeAlloc::nbt,CodeAlloc::nbdl=0;
+CodeAlloc ** CodeAlloc::mem=0;
+bool CodeAlloc::sort=true;
+bool  CodeAlloc::cleanning=false;
+*/
+static long kerr=0;
+static long nbsort =0;
+template<class T>
+static void  HeapSort(T *c,long n)
+  {
+    long l,j,r,i;
+    T crit;
+    c--; // on decale de 1 pour que le tableau commence a 1
+    if( n <= 1) return;
+    l = n/2 + 1;
+    r = n;
+    while (1) { // label 2
+      if(l <= 1 ) { // label 20
+	crit = c[r];
+	c[r--] = c[1];
+	if ( r == 1 ) { c[1]=crit; return;}
+      } else  crit = c[--l]; 
+      j=l;
+      while (1) {// label 4
+	i=j;
+	j=2*j;
+	if  (j>r) {c[i]=crit;break;} // L8 -> G2
+	if ((j<r) && (c[j] < c[j+1])) j++; // L5
+	if (crit < c[j]) c[i]=c[j]; // L6+1 G4
+	else {c[i]=crit;break;} //L8 -> G2
+      }
+    }
+  }
+
+ void CodeAlloc::resize() 
+{
+  Sort_mem();
+  if( nbt*1.5 +10 >= nbpx )
+    {
+      nbpx = chunk;
+      mem=(CodeAlloc **)realloc(mem,chunk*sizeof(void*));
+      if(mem)  nbpx=chunk;
+      else ErrorExec("Alloc problem",0);
+      chunk *= 3; 
+      chunk /= 2;
+      assert(chunk > nbpx);
+    }
+}
+
+     
+     
+   void CodeAlloc::Sort_mem()
+  { 
+    size_t i,j;
+    if(nbt ==0) return;
+    nbsort++; 
+    HeapSort(mem,nbt);
+    
+    for( i=0,j=0;i<nbt;i++)
+      if ( ! isdel(i) )
+        mem[j++]=mem[i];
+    nbt=j;
+    if(nbt != nb) 
+      assert(nbt==nb);
+  }
+    void CodeAlloc::clear()
+  {
+     return ;
+
+    cleanning=true;
+    Sort_mem();
+    cout << " Clear Alloc Mem: "<< nb << endl; ;
+    for(size_t i=0;i<nbt;i++)
+      {
+        if( ! isdel(i)) 
+	  delete mem[i];	
+      }
+    cout << " nb " << nb <<  " ==  " << 0 << " , nbsort: " << nbsort <<endl;
+    nb=0;
+    lg=0;
+    nbpx=0;
+    chunk=2048; 
+    sort=true;
+    free(mem);
+    mem=0;
+    nbdl=0;
+    if(kerr)
+    cout << " CodeAlloc: nb err delete  " << kerr << endl;
+    kerr =0; 
+     cleanning=false;
+  }
+   void CodeAlloc::ErrorDel(void *pp)
+  {
+//    cerr << " Alloc:: Sorry the pointeur " << pp << " is not allocated \n";    
+     kerr++;  
+  }
+  void CodeAlloc::operator delete(void * pp) {
+    //  return ; // FH 
+    if( ! sort  &&  (nb*2 > nbt)  )  Sort_mem();
+    int ib=0,ie=nbt-1,im;
+    if(pp< mem[ib]) ErrorDel(pp);
+    if(pp> mem[ie]) ErrorDel(pp);
+    int p=-1;
+    while( ib < ie )
+      {
+	im = (ib + ie)/2;
+	  {
+	    if(  pp < mem[im]) ie=im-1; // in [ib , im-1] 
+	    else if (mem[im] == pp) { p=im;break;}
+	    else ib =im+1;// in [im+1 , ie]
+	  }
+      }
+    if( p <0 && mem[ib] == pp) p=ib;
+    
+    if(p<0) 
+      ErrorDel(pp);
+    else {
+      setdel(p); //le tableau est detruit   
+      nbdl++;nb--; 
+      ::operator delete(pp);
+    }
+  }
diff --git a/src/fflib/CodeAlloc.hpp b/src/fflib/CodeAlloc.hpp
new file mode 100644
index 0000000..7467916
--- /dev/null
+++ b/src/fflib/CodeAlloc.hpp
@@ -0,0 +1,77 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+class CodeAlloc { public:
+
+  static size_t nb,nbt,lg, nbdl,nbpx, chunk ;   
+  static CodeAlloc ** mem;
+  static bool cleanning;
+  static void * lgmax;
+  static bool sort;
+  static size_t memoryusage; // add FH mach 2014 ..
+  static bool isdel(int i)
+  {
+    return  ((char *) (void *)  mem[i] - (char *) 0) % 2 == 1;
+  }
+      
+  static void setdel(int i)
+  {
+    mem[i] = (CodeAlloc *) (void *) (((char *) mem[i] - (char *) 0)+ 1);
+  }
+  static void resize(); 
+  
+ static  void * Add2CleanAtEnd(void * p)
+  {
+    if(p) {
+      if(nbt>=nbpx) resize();
+      if(nbt>0) sort = sort && mem[nbt-1] < p;
+      nb++; 
+      mem[nbt++]=(CodeAlloc*)p;  }
+    return p;
+  }
+  
+  void *operator new(size_t ll ) {
+    lg+=ll;
+    return Add2CleanAtEnd(::operator new(ll));} 
+
+  
+  static void Sort_mem();
+  static  void clear();
+  static void ErrorDel(void *pp);
+  void operator delete(void * pp);
+  virtual ~CodeAlloc() {}
+  
+};
+
+template<class T> class CodeAllocT: public CodeAlloc{
+  T * p;
+  public: 
+  CodeAllocT(int n): p(new T[n]) { assert(p);}
+  static T * New(int n) { return (new CodeAllocT(n))->p;}
+  ~CodeAllocT(){ delete [] p;}
+};
diff --git a/src/fflib/InitFunct.cpp b/src/fflib/InitFunct.cpp
new file mode 100644
index 0000000..68d1d35
--- /dev/null
+++ b/src/fflib/InitFunct.cpp
@@ -0,0 +1,83 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "InitFunct.hpp"
+#include <algorithm>
+#include <deque>
+#include <iostream>
+#include <set> 
+#include "ffapi.hpp"  
+using namespace std;
+typedef void  (* afunc)(); 
+typedef pair<int,afunc> InitFunct;
+
+deque<InitFunct> * getInitFunctlist()
+{
+  static deque<InitFunct> * data = new deque<InitFunct>();
+  return data;
+}
+
+extern long verbosity;
+set<string> & ff_SetofInitFunct() { static set<string> sset; return sset;}
+void call(const InitFunct & a) { 
+  if(verbosity>5) 
+    cout << "\n addInitFunct : " << a.first << " call : " <<a.second  << " ( " ; 
+  (*a.second)();  
+  if(verbosity>5)
+    cout <<  " ) " ;
+}
+bool comp(const InitFunct a,const InitFunct b)
+ { 
+   return a.first < b.first;
+ }
+ 
+ void  callInitsFunct() 
+ {
+   deque<InitFunct> *  l(getInitFunctlist()); 
+   sort(l->begin(),l->end(),comp);
+   if(verbosity>5) cout << " callInitsFunct : " << l->size() << endl;
+   //   for_each(l->begin(),l->end(),show);   
+   for_each(l->begin(),l->end(),call);
+    l->clear();
+ }
+ 
+void  addInitFunct(int i,void  (* f)(),const char *name) 
+{
+
+  if(!name || (! *name ) ||  ff_SetofInitFunct().insert(name).second)
+    { 
+    getInitFunctlist()->push_back(make_pair(i,f));
+    if(verbosity>9)   cout << " -- addInitFunct: " << i << " " << f 
+			   << " " <<  (name ? name : "" ) <<endl; 
+    }
+  else 
+    cout << " ********  addInitFunct "<< name << " is always load (skip) !" << endl; 
+
+}
+
+
+
diff --git a/src/fflib/InitFunct.hpp b/src/fflib/InitFunct.hpp
new file mode 100644
index 0000000..291b75c
--- /dev/null
+++ b/src/fflib/InitFunct.hpp
@@ -0,0 +1,80 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef INITSFUNCT_HPP_
+#define INITSFUNCT_HPP_
+#include "ffapi.hpp"
+ 
+void  addInitFunct(int i,void  (* f)(),const char *name) ;
+void  callInitsFunct() ;
+
+class  addingInitFunct {  public:
+  addingInitFunct(int i,void  (* f)(),const char *name="") { addInitFunct(i,f,name);}
+} ;
+
+//
+#if WIN32
+#define LOADINITIO {					\
+    streambuf * so =ffapi::cout()->rdbuf() ;		\
+    streambuf * si =ffapi::cin()->rdbuf() ;		\
+    streambuf * se =ffapi::cerr()->rdbuf() ;		\
+    if( so &&  cout.rdbuf() != so ) cout.rdbuf(so);	\
+    if( si &&  cin.rdbuf() != si ) cin.rdbuf(si);	\
+    if( se &&  cerr.rdbuf() != se ) cerr.rdbuf(se);	\
+} 
+#else
+#define LOADINITIO {					\
+    streambuf * so =ffapi::cout()->rdbuf() ;		\
+    streambuf * si =ffapi::cin()->rdbuf() ;		\
+    streambuf * se =ffapi::cerr()->rdbuf() ;		\
+    if( so &&  cout.rdbuf() != so ) cout.rdbuf(so);	\
+    if( si &&  cin.rdbuf() != si ) cin.rdbuf(si);	\
+    if( se &&  cerr.rdbuf() != se ) cerr.rdbuf(se);	\
+    stdout = ffapi::ffstdout();\
+    stderr = ffapi::ffstderr();\
+    stdin = ffapi::ffstdin();\
+} 
+#endif
+
+  
+#define LOADINITNM(EXEC,NM)						\
+  static  void  AutoLoadInit() { LOADINITIO ;				\
+    if(verbosity>9) cout << "\n loadfile " NM  "\n" ;			\
+    EXEC; }								\
+  int DoLoadInit() {							\
+    if(verbosity>9)							\
+      cout << " ****  " << NM  <<  " ****\n" ;				\
+    addInitFunct(10000,&AutoLoadInit,NM);				\
+    return 2;}								\
+									\
+  static int callDoLoadInit=DoLoadInit();				
+
+#define LOADINIT(TI) LOADINITNM(TI init obsolete,__FILE__)			     
+#define LOADFUNC(FC) LOADINITNM(FC() ,__FILE__)			     
+
+
+#endif
diff --git a/src/fflib/Makefile.am b/src/fflib/Makefile.am
new file mode 100644
index 0000000..0626f37
--- /dev/null
+++ b/src/fflib/Makefile.am
@@ -0,0 +1,68 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+
+noinst_LIBRARIES=libff.a
+
+# FFCS - 28/11/11 - ffapi.cpp cannot be part of libff.a because it
+# needs to be compiled with different options depending on the
+# executable it is included in (eg with/without MPI)
+
+libff_a_SOURCES2=  UMFPack_Solver.cpp \
+AFunction.cpp AFunction2.cpp  \
+ array_long.cpp          array_real.cpp        array_complex.cpp \
+lex.cpp lgmesh.cpp	lgmesh3.cpp 	\
+CodeAlloc.cpp lgmat.cpp global.cpp 					\
+../femlib/Drawing.cpp ../femlib/gibbs.cpp				\
+../femlib/CheckPtr.cpp ../femlib/fem.cpp				\
+../femlib/QuadratureFormular.cpp ../femlib/FESpace.cpp			\
+../femlib/Element_RT.cpp ../femlib/mshptg.cpp ../femlib/FQuadTree.cpp	\
+../bamglib/QuadTree.cpp ../bamglib/R2.cpp ../bamglib/Meshio.cpp		\
+../bamglib/Mesh2.cpp ../bamglib/Metric.cpp ../femlib/BamgFreeFem.cpp	\
+../bamglib/MeshDraw.cpp ../bamglib/MeshGeom.cpp				\
+../bamglib/MeshQuad.cpp ../bamglib/SetOfE4.cpp ../bamglib/MeshRead.cpp	\
+../bamglib/write_hdf5.cpp ../bamglib/write_hdf5.hpp ../bamglib/write_xdmf.cpp \
+../bamglib/MeshWrite.cpp problem.cpp mt19937ar.cpp \
+../Graphics/DefColor.cpp \
+ InitFunct.cpp ../Algo/lgalgo.cpp			\
+../femlib/Element_P2h.cpp load.cpp lgfem.cpp AFunction.hpp AnyType.hpp	\
+error.hpp ../femlib/gmres.hpp InitFunct.hpp lex.hpp lgfem.hpp lgmesh3.hpp \
+lgmesh.hpp lgsolver.hpp	\
+Operator.hpp problem.hpp Serialize.hpp showverb.hpp String.hpp		\
+throwassert.hpp versionnumber.hpp  CodeAlloc.hpp \
+array_init.hpp  array_tlp.hpp array_resize.hpp \
+strversionnumber.hpp ffstack.hpp AddNewFE.h \
+environment.cpp environment.hpp string_def.cpp \
+../femlib/FESpacen.cpp \
+../femlib/P012_1d.cpp \
+../femlib/P012_2d.cpp \
+../femlib/P012_3d.cpp \
+../femlib/Mesh1dn.cpp \
+../femlib/Mesh2dn.cpp \
+../femlib/Mesh3dn.cpp \
+../femlib/GQuadTree.cpp \
+../femlib/libmesh5.c \
+glumesh2D.cpp \
+PlotStream.hpp \
+endian.hpp \
+ff++.hpp \
+../Eigen/arpackff.hpp \
+../femlib/splitsimplex.cpp AFunction_ext.hpp \
+ffapi.hpp P1IsoValue.cpp	P1IsoValue.hpp
+
+libff_a_SOURCES=$(libff_a_SOURCES2)  strversionnumber.cpp 
+
+# eigenvalue.cpp is optional (see configure.ac)
+EXTRA_libff_a_SOURCES=../Eigen/eigenvalue.cpp
+libff_a_LIBADD=@EIGENOBJ@
+libff_a_DEPENDENCIES=@EIGENOBJ@
+
+AM_CPPFLAGS=-I$(srcdir)/../lglib -I$(srcdir)/../bamglib -I$(srcdir)/../Graphics -I$(srcdir)/../femlib $(HDF5_CPPFLAGS)
+# -I$(top_srcdir)/arpack/arpack++/include
+
+# Build date changes at every change
+EXTRA_DIST=strversionnumber.m4
+BUILT_SOURCES=strversionnumber.cpp
+strversionnumber.cpp: $(libff_a_SOURCES2) ../../configure
+	m4 -DVersionFreeFemDate="`date`" strversionnumber.m4 > $@
+FORCE:
diff --git a/src/fflib/Operator.hpp b/src/fflib/Operator.hpp
new file mode 100644
index 0000000..a9d9c1d
--- /dev/null
+++ b/src/fflib/Operator.hpp
@@ -0,0 +1,782 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#if defined(__GNUC__) && __GNUC__+0 >= 3
+inline double pow(double x,long l) { return pow(x,(double)l);}
+#endif
+
+
+template<class R,class A=R> 
+struct Op1_neg: public unary_function<A,R> { 
+  static R f(const A & a)  { return - (R)a;} }; 
+  
+template<class R,class A=R> 
+struct Op1_plus: public unary_function<A,R> { 
+  static R f(const A & a)  { return + (R)a;} }; 
+  
+template<class A> 
+struct Op1_not: public unary_function<A,bool> { 
+  static bool f(const A & a)  { return ! (bool)a;} }; 
+  
+template<class R,class A=R,class B=A> 
+struct Op2_add: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return ((R)a + (R)b);} }; 
+
+template<class R,class A=R,class B=A> 
+struct Op2_sub: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return ((R)a - (R)b);} }; 
+
+template<class R,class A=R,class B=A> 
+struct Op2_mul: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { 
+  // cout << a << " * " << b <<" => "  << ((R)a * (R)b) << endl;
+  return ((R)a * (R)b);} }; 
+
+template<class R,class A=R,class B=A> 
+struct Op2_div: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  {
+     if (b == B()) 
+       {cerr <<  a << "/" << b << " : " <<  typeid(A).name()  << " " << typeid(B).name() 
+             << " " << typeid(R).name() << endl;ExecError(" Div by 0");}
+     return ((R)a / (R)b);} }; 
+
+template<class R>
+struct Op2_pipe: public binary_function<R,R,R> {
+    static R f(const R & a,const R & b)  {   return (a | b);} };
+
+template<class R,class A=R,class B=A> 
+struct Op2_mod: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return ((R)a % (R)b);} }; 
+
+template<class A,class B=A> 
+struct Op2_lt: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { 
+//    cout << a << " < " << b << " = " << ( a<b) << endl;
+    return a  < b;} }; 
+
+template<class A,class B=A> 
+struct Op2_le: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { return a  <= b;} }; 
+
+
+template<class A,class B=A> 
+struct Op2_gt: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { return a  > b;} }; 
+
+
+template<class A,class B=A> 
+struct Op2_ge: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { return a  >= b;} }; 
+
+template<class A,class B=A> 
+struct Op2_eq: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b) 
+   { //cout << a << " == " << b << " => " <<( a  == b) << endl;
+   return a  == b;} }; 
+
+template<class A,class B=A> 
+struct Op2_ne: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { return a  != b;} }; 
+
+struct Op2_and: public binary_function<bool,bool,bool> { 
+  static bool f(const bool & a,const bool & b)  { return a  && b;} }; 
+  
+struct Op2_or: public binary_function<bool,bool,bool> { 
+  static bool f(const bool & a,const bool & b)  { return a  || b;} }; 
+
+
+template<class R,class A,class B> 
+struct Op2_padd: public binary_function<A,B,R*> { 
+  static R * f(Stack s,const A & a,const B & b)  { 
+   R* r= Add2StackOfPtr2Free(s,new R (*a  + *b));
+  // delete a,delete b;
+  return r;} }; 
+
+
+template<class A,class B=A> 
+struct Op2_plt: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { bool r= *a  < *b;
+  //delete a,delete b;
+  return r;} }; 
+
+template<class A,class B=A> 
+struct Op2_ple: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { bool r= *a  <= *b;
+  // delete a,delete b;
+  return r;} }; 
+
+
+template<class A,class B=A> 
+struct Op2_pgt: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { bool r= *a  > *b;
+ // delete a,delete b;
+  return r;} }; 
+
+
+template<class A,class B=A> 
+struct Op2_pge: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { bool r= *a  >= *b;
+  // delete a,delete b;
+  return r;} }; 
+
+template<class A,class B=A> 
+struct Op2_peq: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  { bool r= *a  == *b;
+ //  delete a,delete b;
+  return r;} }; 
+
+template<class A,class B=A> 
+struct Op2_pne: public binary_function<A,B,bool> { 
+  static bool f(const A & a,const B & b)  {  bool r=*a  != *b;
+  // delete a,delete b;
+  return r;} }; 
+
+
+template<class R,class A=R,class B=A>
+struct Op2_pow: public binary_function<A,B,R> {
+  static R f(const A & a,const B & b)  { return R(pow(a,b));}};
+  
+
+
+template<class A>
+struct Op_Read : public binary_function<istream*,A*,istream*> {
+  static istream *  f(istream  * const  & f,A  * const  &  a)  
+   { 
+     *f >> *a;
+     return f;
+   }
+};
+
+template<class A>
+struct Op_ReadP : public binary_function<istream*,A**,istream*> {
+  static istream *  f(istream  * const  & f,A  ** const  &  a)  
+   {
+     assert(a);
+     if( ! *a)  *a= new A ; 
+     *f >> **a;
+     return f;
+   }
+};
+
+template<class A>
+struct Op_ReadKN : public binary_function<istream*,KN<A>*,istream*> {
+  static istream *  f(istream  * const  & f,KN<A>* const  &  a)  
+   { 
+     if( !f || !*f) ExecError("Fatal Error: file not open in read array (Op_ReadKN)");
+     int n;char c;
+     *f >> n;
+     if(!f->good()) ExecError("Fatal Error: file  not good in read array (Op_ReadKN)");
+     
+     if(n !=a->N()) {
+        cerr << " length on the array " << a->N() << " != " << n << " length in file " << endl;
+        ExecError("Fatal Error: incompatible length in read array (Op_ReadKN)");
+       assert(n==a->N());
+       }
+     while (f->get(c) &&  (c!='\n' && c!='\r' ) ) ((void) 0); // eat until control (new line
+
+     for (int i=0;i<n;i++)
+       *f >> (*a)[i] ;
+     return f;
+   }
+};
+
+
+
+template<class A>
+struct Print: public binary_function<ostream*,A,ostream*> {
+  static ostream* f(ostream* const  & a,const A & b)  { *a << b;  return a;}
+};
+//  ---------------------------------------------
+template<class A>
+struct set_eq: public binary_function<A*,A,A*> {
+  static A* f(A* const  & a,const A & b)  { *a = b; return a;}
+};
+
+template<class A,class B>
+struct set_eqq: public binary_function<A,B,A> {
+  static A f(const A & a,const B & b)  {A aa(a); aa = b; return aa;}
+};
+
+template<class A,class B>
+struct set_eqq_add: public binary_function<A,B,A> {
+  static A f(const A & a,const B & b)  {A aa(a); aa += b; return aa;}
+};
+
+template<class A>
+struct set_eq_add: public binary_function<A*,A,A*> {
+  static A* f(A* const  & a,const A & b)  { *a += b; return a;}
+};
+
+template<class A>
+struct set_eq_sub: public binary_function<A*,A,A*> {
+  static A* f(A* const  & a,const A & b)  { *a -= b; return a;}
+};
+
+template<class A>
+struct set_eq_mul: public binary_function<A*,A,A*> {
+  static A* f(A* const  & a,const A & b)  { *a *= b; return a;}
+};
+
+template<class A>
+struct set_eq_div: public binary_function<A*,A,A*> {
+  static A* f(A* const  & a,const A & b)  { *a /= b; return a;}
+};
+
+template<class A>
+struct set_peq: public binary_function<A**,A*,A**> {
+  static A** f(A** const  & a, A * const & b)  { 
+    if(*a != b )
+    { 
+	//cerr << " set_peq " << *a << endl;
+	delete *a;
+	//cerr << " set_peq " << *a << " " << " = " << b << " " <<  endl;
+	*a = new A(*b); //(stack ptr) FH mars 2006
+	//cerr << " set_peq " << *a << " " << **a << " = " << *b << " " << b <<  endl;
+    }
+     return a;}
+};
+
+//  ---------------------------------------------
+template<class A,class B>
+struct set_eqarrayp: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {  *a = *b; return a;}
+};
+
+template<class A,class B>
+struct set_eqarrayp_add: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  { assert(SameShape(*a,*b)); *a += *b; return a;}
+};
+
+template<class A,class B>
+struct set_eqarrayp_sub: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  { assert(SameShape(*a,*b)); *a -= *b; return a;}
+};
+
+template<class A,class B>
+struct set_eqarrayp_mul: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  { assert(SameShape(*a,*b)); *a *= *b; return a;}
+};
+
+
+template<class A,class B>
+struct set_eqarrayp_div: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  { assert(SameShape(*a,*b)); *a /= *b; return a;}
+};
+
+//  ---------------------------------------------
+template<class A,class B>
+struct set_eqarraypd: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,*b));  *a = *b;
+   delete b;
+   return a;}
+};
+
+
+template<class A,class B>
+struct set_eqarraypd_add: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,*b));  *a += *b; 
+  delete b;
+  return a;}
+};
+
+template<class A,class B>
+struct set_eqarraypd_sub: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,*b));  *a -= *b; 
+  delete b;
+  return a;}
+};
+
+template<class A,class B>
+struct set_eqarraypd_mul: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,*b));  *a *= *b;
+   delete b;
+   return a;}
+};
+
+template<class A,class B>
+struct set_eqarraypd_div: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,*b));  *a /= *b;
+   delete b;
+   return a;}
+};
+
+//  ---------------------------------------------
+template<class A,class B>
+struct set_eqarray: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  
+  {  *a = b;
+     return a;}
+};
+
+//  --------------------------------------------- august 2007 FH 
+template<class A,class B>
+struct init_eqarray: public binary_function<A*,B,A*> {
+    static A* f(A* const  & a, B const & b)  
+    {  a->init(); *a = b;
+	return a;}
+};
+//  ---------------------------------------------
+template<class A,class B>
+struct init_eqarraypd: public binary_function<A*,B,A*> {
+    static A* f(A* const  & a, B const & b)  {a->init();  *a = *b;
+    delete b;
+    return a;}
+};
+
+//  ---------------------------------------------
+template<class A,class B>
+struct init_eqarrayp: public binary_function<A*,B,A*> {
+    static A* f(A* const  & a, B const & b)  {  a->init(); *a = *b; return a;}
+};
+
+// ----------------------------------------  fin modif august 2007
+
+template<class A,class B>
+struct set_eqarray_add: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,b));  *a += b; return a;}
+};
+
+template<class A,class B>
+struct set_eqarray_sub: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,b));  *a -= b; return a;}
+};
+
+template<class A,class B>
+struct set_eqarray_mul: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,b));  *a *= b; return a;}
+};
+
+template<class A,class B>
+struct set_eqarray_div: public binary_function<A*,B,A*> {
+  static A* f(A* const  & a, B const & b)  {assert(SameShape(*a,b));  *a /= b; return a;}
+};
+
+template<class A,class B>
+struct set_eq_array: public binary_function<A,B,A> {
+  static A f(const A & a, B const & b)  
+  {  A aa=a;aa = b;
+     return a;}
+};
+template<class A,class B>
+struct set_eq_array_add: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,b));  A aa(a);  aa += b; return a;}
+};
+
+template<class A,class B>
+struct set_eq_array_sub: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,b));  A aa(a);  aa -= b; return a;}
+};
+
+template<class A,class B>
+struct set_eq_array_mul: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,b));  A aa(a);  aa *= b; return a;}
+};
+
+template<class A,class B>
+struct set_eq_array_div: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,b));  A aa(a);  aa /= b; return a;}
+};
+template<class A,class B>
+struct set_eq_arrayp: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {  A aa(a);  aa = *b; return a;}
+};
+//  ---------------------------------------------
+template<class A,class B>
+struct set_eq_arraypd: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,*b));A aa(a);  aa = *b;
+  delete b;
+  return a;}
+};
+
+template<class A,class B>
+struct set_eq_arrayp_sub: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  { assert(SameShape(a,*b));  A aa(a);  aa -= *b; return a;}
+};
+
+template<class A,class B>
+struct set_eq_arrayp_mul: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  { assert(SameShape(a,*b));  A aa(a);  aa *= *b; return a;}
+};
+
+template<class A,class B>
+struct set_eq_arrayp_div: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  { assert(SameShape(a,*b));  A aa(a);  aa /= *b; return a;}
+};
+
+template<class A,class B>
+struct set_eq_arrayp_add: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  { assert(SameShape(a,*b));  A aa(a);  aa += *b; return a;}
+};
+template<class A,class B>
+struct set_eq_arraypd_add: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,*b)); A aa(a);  aa += *b;
+   delete b;
+   return a;}
+};
+template<class A,class B>
+struct set_eq_arraypd_sub: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,*b)); A aa(a);  aa -= *b;
+   delete b;
+   return a;}
+};
+
+template<class A,class B>
+struct set_eq_arraypd_mul: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,*b)); A aa(a);  aa *= *b;
+   delete b;
+   return a;}
+};
+
+template<class A,class B>
+struct set_eq_arraypd_div: public binary_function<A,B,A> {
+  static A f(A const  & a, B const & b)  {assert(SameShape(a,*b)); A aa(a);  aa /= *b;
+   delete b;
+   return a;}
+};
+
+template<class A>
+struct PrintP: public binary_function<ostream*,A,ostream*> {
+    static ostream* f(ostream* const  & a,const A & b)  {  *a << *b; 
+	// a->flush();// ADD FH MAi 2010 to empty the buffer  baf idea  add flush of ostream 
+  //delete b; mars 2006 FH 
+   return a;}
+};
+template<class A>
+struct PrintPnd: public binary_function<ostream*,A,ostream*> {
+  static ostream* f(ostream* const  & a,const A & b)  
+  {  *a << *b; return a;}
+};
+
+
+
+
+template<class R,class A>  R * set_eqP(R* a,A b){ 
+   if (*a != b) delete (*a) ;
+  ( *a =b); return a;}
+template<class R,class A>  R * set_eqdestroy(R* a,A b){ 
+   if (*a != b)  (**a).destroy() ;//  le cas debile Th=Th doit marcher
+   // cout << " set_eqdestroy " << a << " " << b << endl;
+  ( *a =b); return a;}
+  
+template<class R,class A>  R * set_eqdestroy_incr(R* a,A b){
+  if(b) (*b).increment() ;
+  if(*a) (**a).destroy() ;//  le cas debile Th=Th doit marcher
+   // cout << " set_eqdestroy " << a << " " << b << endl;
+  ( *a =b); return a;}
+  
+template<class R>  R * set_copy( R* const & a,const R & b){ 
+ SHOWVERB( cout << " set_copy " << typeid(R).name() << " " << &b << endl);
+  memcpy(a,&b,sizeof(R)); return a;}
+
+template<class R>  R ** set_copy_new( R** const & a,const R * & b){ 
+    SHOWVERB( cout << " set_copy_new " << typeid(R).name() << " " << &b << endl);
+    *a= new R(*b);
+   return a;}
+
+template<class R>  R * set_copyp( R* const & a,const R & b){ 
+ SHOWVERB( cout << " set_copy " << typeid(R).name() << " " << &b << endl);
+  // memcpy(a,&b,sizeof(R));
+   *a = b;
+   return a;}
+
+template<class R>  R ** set_copyp_new( R**  a,R*  b){ 
+ SHOWVERB( cout << " set_copy " << typeid(R).name() << " " << &b << endl);
+  //memcpy(a,&b,sizeof(R)); return a;  FH 2007
+   // cerr << " set_copyp_new " << typeid(R).name() << " " << b <<  " " << *b ;
+  *a = new R(*b);
+
+  //  cerr << "  -> " << *a << endl; 
+  return a;
+  }
+
+template<class R>  R ** set_copy_incr( R** const & a, R * const & b){ 
+   *a=b;
+   if(b) b->increment();
+   return a;}
+
+template<class R,class A>  R * set_init2( R* const & a,const A & b,const A & c){ 
+ SHOWVERB( cout << " set_init2 " << typeid(R).name() << " " << &b << " " << &c << endl);
+  a->init(b,c); return a;}
+template<class R,class A>  R * set_init( R* const & a,const A & b){ 
+ SHOWVERB( cout << " set_init " << typeid(R).name() << " " << &b << endl);
+  a->init(b); return a;}
+template<class R,class A>  R * set_initp( R* const & a,const A & b){ 
+    SHOWVERB( cout << " set_init " << typeid(R).name() << " " << &b << endl);
+    a->init(*b); return a;}
+
+template<class R,class A=R,class B=A> 
+struct Op2_add0: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return (a + b);} };  
+
+template<class R,class A=R,class B=A> 
+struct Op2_build: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return R(a,b);} };  
+template<class R,class A=R,class B=A> 
+
+struct Op2_pbuild: public binary_function<A,B,R*> { 
+  static R *f(const A & a,const B & b)  { return new R(a,b);} };  
+  
+template<class R,class A=R,class B=A> 
+struct Op2_add__n: public binary_function<A,B,R*> { 
+  static R * f(const A & a,const B & b)  { return new R(a + b);} };    
+template<class R,class A=R,class B=A> 
+struct Op2_addp_n: public binary_function<A,B,R*> { 
+  static R* f(const A & a,const B & b)  { return new R(*a + b);} };   
+template<class R,class A=R,class B=A> 
+struct Op2_add_pn: public binary_function<A,B,R*> { 
+  static R* f(const A & a,const B & b)  { return new R(a + *b);} };   
+
+
+template<class R,class A=R,class B=A> 
+struct Op2_sub0: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return (a - b);} }; 
+  
+template<class R,class A=R> 
+struct Op1_subp: public unary_function<A,R> { 
+  static R f(const A & a)  { return (- *a );} };   
+template<class R,class A=R> 
+struct Op1_sub: public unary_function<A,R> { 
+static R f(const A & a)  { return (- a );} };   
+
+template<class R,class A=R,class B=A> 
+struct Op2_mulcp: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return (a * *b);} }; 
+
+template<class R,class A=R,class B=A> 
+struct Op2_mulc: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return (a * b);} };
+
+template<class R,class A=R,class B=A>
+struct Op2_divc: public binary_function<A,B,R> {
+    static R f(const A & a,const B & b)  { return (a / b);} };
+
+template<class R,class A=R,class B=A> 
+struct Op2_mulpc: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return (b * *a);} }; 
+
+template<class R,class A=R,class B=A> 
+struct Op2_mulpcp: public binary_function<A,B,R> { 
+  static R f(const A & a,const B & b)  { return (*a * *b);} }; 
+
+template<class R,class A=R,class B=A> 
+struct Op2_sub__n: public binary_function<A,B,R*> { 
+  static R * f(const A & a,const B & b)  { return new R(a - b);} };    
+template<class R,class A=R,class B=A> 
+struct Op2_subp_n: public binary_function<A,B,R*> { 
+  static R* f(const A & a,const B & b)  { return new R(*a - b);} };   
+template<class R,class A=R,class B=A> 
+struct Op2_sub_pn: public binary_function<A,B,R*> { 
+  static R* f(const A & a,const B & b)  { return new R(a - *b);} };   
+
+
+template<class R,class A=R,class B=A,class C=A> 
+struct Op3_p: public ternary_function<A,B,C,R*> { 
+  static R* f(Stack s,const A & a,const B & b,const  C & c )  { return new R(a,b,c);} };   
+
+template<class R,class A=R,class B=A> 
+struct Op2_p: public binary_function<A,B,R*> { 
+  static R* f(const A & a,const B & b)  { return new R(a,b);} };   
+
+
+
+
+template<class T>
+class Transpose{ public:
+  T  t;
+  Transpose( T  v)
+   : t(v) {}
+  template<class TT> Transpose( TT  v) : t(v) {}  
+  template<class TT> Transpose( TT * v) : t(*v) {}  
+  operator const T & () const {return t;}
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+  
diff --git a/src/fflib/P1IsoValue.cpp b/src/fflib/P1IsoValue.cpp
new file mode 100644
index 0000000..8d27ce6
--- /dev/null
+++ b/src/fflib/P1IsoValue.cpp
@@ -0,0 +1,434 @@
+//
+//  P1IsoValue.cpp
+//  ff
+//
+//  Created by Frédéric Hecht on 07/03/2014.
+//
+//
+#include <cassert>
+#include <cmath>
+using namespace std;
+#include "P1IsoValue.hpp"
+using namespace Fem2D;
+extern long verbosity;
+//typedef double R;
+
+inline R3 bary(const R3 K[4],R f[4],int i0,int i1,R v)
+{
+    R d=f[i0]-f[i1];
+    assert(fabs(d)>1e-20);
+    R l1= (f[i0] - v)/ d;  //  == 1 si v = f[i1]
+    R l0 = 1. -l1;
+    assert(l0 >=-1e-10 && l1 >= -1e-10);
+    return K[i0]*l0 + K[i1]*l1; // == K[i1] si l1 ==1 => v = f[i1]
+}
+
+inline R2 bary(const R2 K[3],R f[3],int i0,int i1,R v)
+{
+    R d=f[i0]-f[i1];
+    assert(fabs(d)>1e-20);
+    R l1= (f[i0] - v)/ d;  //  == 1 si v = f[i1]
+    R l0 = 1. -l1;
+    assert(l0 >=-1e-10 && l1 >= -1e-10);
+    return K[i0]*l0 + K[i1]*l1; // == K[i1] si l1 ==1 => v = f[i1]
+}
+
+static inline int  signep4(int i0,int i1,int i2,int i3)
+{ // calcul du signe dans la permutation
+    int s =1;
+    if(i0>i1) s=-s,Exchange(i0,i1);
+    if(i1>i2) s=-s,Exchange(i1,i2);
+    if(i2>i3) s=-s,Exchange(i2,i3); // i3 max
+    if(i0>i1) s=-s,Exchange(i0,i1);
+    if(i1>i2) s=-s,Exchange(i1,i2); // i2 max < i
+    if(i0>i1) s=-s,Exchange(i0,i1);
+    return s;
+}
+inline int  signe_permutation(int i0,int i1,int i2,int i3)
+{
+    int p=1;
+    if(i0>i1) Exchange(i0,i1), p = -p;
+    if(i0>i2) Exchange(i0,i2), p = -p;
+    if(i0>i3) Exchange(i0,i3), p = -p;
+    if(i1>i2) Exchange(i1,i2), p = -p;
+    if(i1>i3) Exchange(i1,i3), p = -p;
+    if(i2>i3) Exchange(i2,i3), p = -p;
+    return p;
+}
+inline void pen23tet(R3 P[6],R3 Q[3][4])
+{
+  //int d1[3][4]= { {1,6,2,3},    {1,5,2,6},    {1,6,4,5}};
+    int d0[3][4]= { {0,5,1,2},    {0,4,1,5},    {0,5,3,4}};
+   /* the 6 way to spilt  a pent en tet ...
+     DATA PDD /1,0,2,3,4,5,0,6/
+     DATA (MU(I, 1),I=1,12) /1,6,2,3,    1,5,2,6,    1,6,4,5/
+     DATA (MU(I, 2),I=1,12) /1,6,2,3,    1,4,2,6,    2,6,4,5/
+     DATA (MU(I, 3),I=1,12) /1,4,2,3,    2,6,3,4,    2,6,4,5/
+     DATA (MU(I, 4),I=1,12) /1,5,2,3,    1,5,3,6,    1,6,4,5/
+     DATA (MU(I, 5),I=1,12) /1,5,2,3,    1,5,3,4,    3,6,4,5/
+     DATA (MU(I, 6),I=1,12) /1,4,2,3,    2,5,3,4,    3,6,4,5/
+     */
+    for(int k=0; k<3; ++k)
+     for(int i=0; i<4;++i)
+        Q[k][i]=P[d0[k][i]];
+}
+int UnderIso(double *f,R2 Q[2][3] ,double area2[2],  double eps)
+{
+ 
+    const R2 *K = R2::KHat;
+    const  int p1[]= {1,2,0};
+    const  int p2[]= {2,0,1};
+    R v=0;
+    //  build  the negative tetra under zero iso value of f ..
+    double fmx=f[0], fmn=f[0];
+    fmx = std::max(fmx,f[1]);
+    fmn = std::min(fmn,f[1]);
+    fmx = std::max(fmx,f[2]);
+    fmn = std::min(fmn,f[2]);
+    if( fmn >= v - eps)
+    {
+        area2[0]=1;
+        return 0; // no intersection ..
+    }
+    if( fmx <= v+ eps)
+    {
+        area2[0]=1;
+        return 1;
+    }; //  full triz ..
+
+    int np[4],nm[4];
+    int km=0,kp=0;
+    
+    int ntria=0;
+    for (int i=0;i<3;++i)
+    {
+        if(f[i]<=v+eps) nm[km++]=i;
+        else np[kp++] = i;
+    }
+    if(km == 0)
+    {
+        area2[0]=0;
+        return 0;
+    }
+    else if( km == 1)
+    { //  1 tet  j, j+1, j+2, j+3
+        int j0=nm[0];
+        int j1=p1[j0], j2=p2[j0];
+        Q[0][0]=K[j0];
+        Q[0][1]=bary(K,f,j0,j1,v);
+        Q[0][2]=bary(K,f,j0,j2,v);
+        ntria=1;
+    }
+    else if( km == 2)
+    {// 1 prisme
+        ntria=2;
+        int j0 = np[0];
+        int j1=p1[j0], j2=p2[j0];
+        R2 Q1=bary(K,f,j0,j1,v);
+        R2 Q2=bary(K,f,j0,j2,v);
+        Q[0][0]=K[j1];
+        Q[0][1]=K[j2];
+        Q[0][2]=Q2;
+        Q[1][0]=K[j1];
+        Q[1][1]=Q2;
+        Q[1][2]=Q1;
+    }
+    else if( km == 3)
+    {
+        area2[0]=1;
+        return 1;
+    }
+    // vol computation
+    for(int k=0; k< ntria; ++k)
+    {
+        area2[k]=det(Q[k][0],Q[k][1],Q[k][2]);
+        //cout <<area2[k] << endl;
+        assert(area2[k] >= - eps);
+    }
+    
+    return ntria;
+   
+}
+int UnderIso(double *f,R3 Q[3][4] ,double vol6[3],  double eps)
+{
+    const R3 *K = R3::KHat;
+    const  int p1[]= {1,2,3,0};
+    const  int p2[]= {2,0,0,2};
+    const  int p3[]= {3,3,1,1};
+    R v=0;
+  //  build  the negative tetra under zero iso value of f ..
+    double fmx=f[0], fmn=f[0];
+    fmx = std::max(fmx,f[1]);
+    fmn = std::min(fmn,f[1]);
+    fmx = std::max(fmx,f[2]);
+    fmn = std::min(fmn,f[2]);
+    fmx = std::max(fmx,f[3]);
+    fmn = std::min(fmn,f[3]);
+    if( fmn >= v - eps)
+    {
+        vol6[0]=1;
+        return 0; // no intersection ..
+    }
+    if( fmx <= v+ eps)
+    {
+        vol6[0]=1;
+        return 1;
+    }; //  full tet ..
+    
+  // hard case ..
+// count number
+    vol6[0]=1;
+   
+    int np[4],nm[4];
+    int km=0,kp=0;
+    
+    int ntet=0;
+    for (int i=0;i<4;++i)
+    {
+        if(f[i]<=v+eps) nm[km++]=i;
+        else np[kp++] = i;
+    }
+    if(km == 0)
+    {
+        vol6[0]=0;
+        return 0;
+    }
+    else if( km == 1)
+    { //  1 tet  j, j+1, j+2, j+3
+        int j0=nm[0];
+        int j1=p1[j0], j2=p2[j0], j3=p3[j0];
+        Q[0][0]=K[j0];
+        Q[0][1]=bary(K,f,j0,j1,v);
+        Q[0][2]=bary(K,f,j0,j2,v);
+        Q[0][3]=bary(K,f,j0,j3,v);
+        ntet=1;
+    }
+    else if( km == 2)
+    {// 1 prisme i0,i1, j0,j1, k0, k0
+        ntet=3;
+        int i0=nm[0];
+        int i1=nm[1];
+        int k0=np[0];
+        int k1=np[1];
+        if(signe_permutation(i0,i1,k0,k1)<0)
+            std::swap(k0,k1);
+            
+        R3 P[6];
+        P[0]=K[i0];
+        P[1]=bary(K,f,i0,k0,v);
+        P[2]=bary(K,f,i0,k1,v);
+        P[3]=K[i1];
+        P[4]=bary(K,f,i1,k0,v);
+        P[5]=bary(K,f,i1,k1,v);
+        pen23tet(P,Q);
+        
+    }
+    else if( km == 3)
+    { // prisme
+        ntet=3;
+        int k0=np[0];
+        int i1=p1[k0];
+        int i2=p2[k0];
+        int i3=p3[k0];
+        assert(signe_permutation(k0,i1,i2,i3)>0);
+        R3 P[6];
+        P[3]=K[i1];
+        P[4]=K[i2];
+        P[5]=K[i3];
+        P[0]=bary(K,f,i1,k0,v);
+        P[1]=bary(K,f,i2,k0,v);
+        P[2]=bary(K,f,i3,k0,v);
+        pen23tet(P,Q);
+        
+
+    }
+    else if( km == 4)
+    {
+      vol6[0]=1;
+      return 1;
+    }
+// vol computation
+    for(int k=0; k< ntet; ++k)
+    {
+        vol6[k]=det(Q[k][0],Q[k][1],Q[k][2],Q[k][3]);
+        assert(vol6[k] >= - eps);
+        if( vol6[k]  <eps && verbosity> 99 )
+            cout <<k << " bizarre " << km << " "
+                 << Q[k][0]<< " "
+                << Q[k][1]<< " "
+                <<Q[k][2]<< " "
+                << Q[k][3]<< endl;
+    }
+
+    return ntet;
+}
+
+int IsoLineK(double *f,Fem2D::R3 *Q, double eps)
+{
+    
+    static const int  nvfaceTet[4][3]  ={{3,2,1}, {0,2,3},{ 3,1,0},{ 0,1,2}}  ;
+    
+    const R3 *K=R3::KHat;
+    int kv=0,vk[4],tv[4],kf;
+    for(int i=0;i<4;++i)
+    {
+      if( abs(f[i]) <= eps)
+        {
+            tv[kv++]=i;
+            vk[i]=1;
+        }
+        else
+         vk[kf=i]=0;
+    }
+    if(kv==3)
+    {
+        // cout << " full face " << kf << endl;
+        // a face complete kf..
+      //  warning
+        int i1=1,i2=2;
+        if(f[kf] <0) i1=2,i2=1;
+        Q[0]=K[nvfaceTet[kf][0]];
+        Q[1]=K[nvfaceTet[kf][i1]];
+        Q[2]=K[nvfaceTet[kf][i2]];
+        
+        return (f[kf] >0) ? 3:0;// to take one fulL face not to times ...
+    }
+
+    R v=0;
+    int nP=0;
+    int np[4],nm[4],nps[4],nms[4];;
+    int km=0,kp=0,kms=0,kps=0;
+    
+    for (int i=0;i<4;++i)
+    {
+        if(f[i]<=v+eps) nm[km++]=i;
+        if(f[i]>=v-eps) np[kp++]=i;
+        // strict ..
+        if(f[i]<v-eps) nms[kms++]=i;
+        if(f[i]>v+eps) nps[kps++]=i;
+    }
+    
+    //  cout << "IsoLineK: km kp "<< km << " " << kp << endl;
+    int h=-1,b[3];
+    if(kps==1 && km==3)
+    {
+        h = nps[0];
+        b[0]=nvfaceTet[h][0];
+        b[1]=nvfaceTet[h][1];
+        b[2]=nvfaceTet[h][2];
+    }
+    if(kms==1 && kp == 3)
+    {
+        h = nms[0];
+        b[0]=nvfaceTet[h][0];
+        b[2]=nvfaceTet[h][1];
+        b[1]=nvfaceTet[h][2];
+    }
+    if(kp==2 && km==2)
+    {//  cas quad
+        if(signep4(nm[0],nm[1],np[0],np[1]) < 0)
+            Exchange(nm[0],nm[1]);
+        Q[0]=bary(K,f,nm[0],np[0],v);
+        Q[1]=bary(K,f,nm[0],np[1],v);
+        Q[2]=bary(K,f,nm[1],np[1],v);
+        Q[3]=bary(K,f,nm[1],np[0],v);
+        nP=4;
+    }
+    else if (h>=0)
+    { // cas triangle
+        Q[0]=bary(K,f,h,b[0],v);
+        Q[1]=bary(K,f,h,b[1],v);
+        Q[2]=bary(K,f,h,b[2],v);
+        nP=3;
+    }
+    
+    return nP;
+}
+
+int IsoLineK(double *f,Fem2D::R2 *Q, double eps)
+{
+    int debug=0;
+    R2 P[3]={ R2(0.,0.),R2(1.,0.),R2(0.,1.)};
+    int kv=0,ke=0,e=3;
+    int tv[3],te[3],vk[3],i0[3],i1[3];
+    for(int i=0;i<3;++i)
+    {
+        if( abs(f[i]) <= eps) {
+            e -= tv[kv++]=i;
+            vk[i]=1;
+        }
+        else
+            vk[i]=0;
+    }
+    if(debug) cout << " ** " <<     kv << endl;
+    if(kv>1) //  on 2  vertex on the isoline ....
+    {
+        if(kv==2)
+        {
+            if(f[e] > 0.)
+            {
+                int j0=(e+1)%3;
+                int j1=(e+2)%3;
+                te[ke]=e+3,i0[ke]=j0,i1[ke]=j0,++ke;
+                te[ke]=e,i0[ke]=j1,i1[ke]=j1,++ke;
+                // pb d'unicity, need to see the adj triangle ...
+                //return 10+e ; // edge number + 10
+            }
+            else return 0; // skip edge ...
+            
+        }
+        else return 0; //  const funct...
+    }
+    else // see internal edge ..
+        for(int ee=0;ee<3;++ee)
+        {
+            int j0=(ee+1)%3;
+            int j1=(ee+2)%3;
+            if( vk[j0]) //  the intial  point on iso line
+            {
+                if(0. < f[j1])
+                    te[ke]=ee,i0[ke]=j0,i1[ke]=j0,++ke;
+                else
+                    te[ke]=ee+3,i0[ke]=j0,i1[ke]=j0,++ke;
+            }
+            else if (vk[j1]); // skip the final point on iso line
+            else if( f[j0] < 0. && 0. < f[j1])  // good  sens
+                te[ke]=ee,i0[ke]=j0,i1[ke]=j1,++ke;
+            else if ( f[j0] > 0. && 0. > f[j1]) // inverse  sens
+                te[ke]=ee+3,i0[ke]=j1,i1[ke]=j0,++ke;
+        }
+    if( ke==2)
+    {
+        // the  K[i1[0]] , Q[0], Q[1] must be direct ...
+        // the  K[i0[1]] , Q[0], Q[1] must be direct ...
+        // Warning   no trivail case ..  make a plot to see
+        //  with is good
+        // the first edge must be
+        
+        if(te[0]<3)  // oriente the line
+        {
+            assert(te[1] >=3);
+            std::swap(te[0],te[1]);
+            std::swap(i0[0],i0[1]);
+            std::swap(i1[0],i1[1]);
+            if(debug) cout << " swap " << endl;
+        }
+        for(int i=0;i<2;++i)
+        {
+            int j0=i0[i],j1=i1[i];
+            if( j0== j1)
+                Q[i] = P[j0];
+            else
+                Q[i] = (P[j0]*(f[j1]) -  P[j1]*(f[j0]) ) /(f[j1]-f[j0]);
+            if(debug) cout << i << " " << j0 << " " << j1 << " : "
+                << Q[i] << "***" << endl;
+        }
+        if(!vk[i1[0]])
+            assert( det(P[i1[0]],Q[0],Q[1]) > 0);
+        if(!vk[i0[1]])
+            assert( det(P[i0[1]],Q[1],Q[0]) > 0);
+        return 2;
+    }
+    // remark, the left of the line is upper .
+    return 0;
+}
diff --git a/src/fflib/P1IsoValue.hpp b/src/fflib/P1IsoValue.hpp
new file mode 100644
index 0000000..76ce7c0
--- /dev/null
+++ b/src/fflib/P1IsoValue.hpp
@@ -0,0 +1,49 @@
+//
+//  P1IsoValue.h
+//  ff
+//
+//  Created by Frédéric Hecht on 07/03/2014.
+//
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#ifndef __ff__P1IsoValue__
+#define __ff__P1IsoValue__
+
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+
+
+#include "ufunction.hpp"
+namespace Fem2D
+{
+#include "R3.hpp"
+}
+int IsoLineK(double *f,Fem2D::R3 *Q, double eps);
+int IsoLineK(double *f,Fem2D::R2 *Q, double eps);
+int UnderIso(double *f,Fem2D::R3 Q[3][4] ,double vol[3],  double eps);
+int UnderIso(double *f,Fem2D::R2 Q[2][3] ,double area[2],  double eps);
+
+
+
+#endif /* defined(__ff__P1IsoValue__) */
diff --git a/src/fflib/PlotStream.hpp b/src/fflib/PlotStream.hpp
new file mode 100644
index 0000000..71cfe11
--- /dev/null
+++ b/src/fflib/PlotStream.hpp
@@ -0,0 +1,257 @@
+/*
+ *  PlotStream.hpp
+ *
+ *  Created by Frederic Hecht on 27/10/08.
+ *  Copyright 2008 UPMC.
+ *
+ */
+
+#include <cstdio>
+#ifdef WIN32
+#include <fcntl.h>
+#endif
+#include "endian.hpp"
+
+//FFCS visualization stream redirection
+#include "ffapi.hpp"
+
+using  Fem2D::Mesh;
+using  Fem2D::Mesh3;
+namespace Fem2D {
+    
+}
+
+
+class PlotStream 
+{
+public:
+    
+  FILE * TheStream;
+
+  PlotStream(FILE *Stream) :TheStream(Stream) { }
+  operator bool() const { return TheStream;}
+  // datatype mush be < 0 to have no collistion with arg number. 
+  // FFCS: <<PlotStream::datatype>>
+    enum datatype { dt_meshes=-1,dt_plots=-2,dt_endplot=-3,dt_meshes3=-10,dt_plots3=-11,dt_endarg=99999,dt_newplot=-5  };
+  
+  //FFCS:need to send control data to FFCS at least once per plot
+  void SendNewPlot() {  ffapi::newplot();write((long )dt_newplot); set_binary_mode(); }
+  void SendEndArgPlot() {write((long )dt_endarg); }
+  //FFCS:redirect visualization stream
+  void SendEndPlot() { write((long )dt_endplot);ffapi::ff_fflush(TheStream); set_text_mode() ;}
+  void SendPlots() { write((long )dt_plots); }
+  void SendMeshes() { write((long )dt_meshes);}
+  void SendMeshes3() { write((long )dt_meshes3);}
+  //FFCS: divert stream to FFCS
+  void write(const void *data,size_t l) {ffapi::ff_fwrite(data,1,l,TheStream);}
+
+  PlotStream& write(const bool& bb) {bool b=w_endian(bb);write(reinterpret_cast<const void *> (&b),sizeof(bool));return *this;}
+  PlotStream& write(const long long& bb) {long long  b=w_endian(bb);write(reinterpret_cast<const void *> (&b),sizeof(long long));return *this;}
+  PlotStream& write(const long& bb) { // always write 8 bits for  a long FH. 
+    long long ll=bb;ll=w_endian(ll);write(reinterpret_cast<const void *> (&ll),sizeof(long long));
+    return *this;}
+  PlotStream& write(const int& bb) {int b=w_endian(bb);write(reinterpret_cast<const void *> (&b),sizeof(int));return *this;}
+  PlotStream& write(const double& bb) {double b=w_endian(bb);write(reinterpret_cast<const void *> (&b),sizeof(double));return *this;}
+  PlotStream& write(const complex<double>& bb) {return write(bb.real()),write(bb.imag());}
+  PlotStream &write(const Fem2D::R1 & P) { return write(P.x);}
+  PlotStream &write(const Fem2D::R2 & P) { return write(P.x),write(P.y);}
+  PlotStream &write(const Fem2D::R3 & P) { return write(P.x),write(P.y),write(P.z);}
+
+  PlotStream& write(const string& b) {  
+    int l=b.size();
+    write(l);
+    write(b.data(),l);
+    return *this;
+  }
+  
+  void set_text_mode() 
+  {    
+  //FFCS:visualization stream redirection
+    ffapi::wintextmode(TheStream);
+  }
+  void set_binary_mode()
+  {    
+  //FFCS:visualization stream redirection
+    ffapi::winbinmode(TheStream);
+  }
+ 
+  PlotStream & operator << (const bool& b)    { return write(b); }
+  PlotStream & operator << (const long& b)    { return write(b); }        
+  PlotStream & operator << (const long long & b)   { return write(b); }        
+  PlotStream & operator << (const int& b)      { return write(b); }        
+  PlotStream & operator << (const double& b)   { return write(b); }
+  PlotStream & operator << (const complex<double>& b)   { return write(b); }
+  PlotStream & operator << (const string& s)   { return write(s); }
+  PlotStream & operator << (const string* s)   { ffassert(s); return write(*s); }
+    template<class T>    
+    PlotStream & operator << (const KN_<T>& b)
+    {
+	long n=b.N();
+	write(n);
+	// cout << "PlotStream :<<  n " << n << endl;
+
+	for (int i=0;i<n;++i)
+	    write(b[i]);
+	return *this;
+    }
+
+
+  PlotStream & operator << (const Mesh& Th) {
+      /*
+    Serialize s=Th.serialize();
+    long  n=s.size();
+    write( n );
+    write(s,s.size());*/
+    GSave2(TheStream , Th) ; 
+    return *this;}
+
+  PlotStream & operator << (const Fem2D::Mesh2& Th) { Th.GSave(TheStream); return *this;}
+  PlotStream & operator << (const Fem2D::Mesh3& Th) { Th.GSave(TheStream); return *this;}
+
+    
+    
+  void read( void *data,size_t l) {
+	char * p= (char*)data;
+	for(int i=0;i<l;++i)	
+	  *p++ = (char) getc(TheStream);
+	//	fread(  p++,1,1,TheStream);
+	//       read(data,l);
+}
+  //FFCS:visualization stream redirection
+  bool good() const {return ffapi::ff_ferror(TheStream)==0;}
+  void GetNewPlot() { get(dt_newplot) ; set_binary_mode();}
+  void GetEndArgPlot() {get(dt_endarg); }
+  void GetEndPlot() {get(dt_endplot); set_text_mode();}
+  void GetPlots() { get(dt_plots); }
+  void GetMeshes() { get(dt_meshes);}
+  bool GetMeshes3() { long tt; read(tt);
+      if(tt== dt_meshes3) return true;
+      else if (tt== dt_plots) return false;
+      cout << " Error Check :  get " << tt << " == wait for  "<< dt_meshes3 << " or "<< dt_plots << endl;
+      ffassert(0);
+     }
+    
+  void get(datatype t) { long tt; read(tt);
+    if( tt !=(long) t) 
+      cout << " Error Check :  get " << tt << " == wait for  "<< t << endl; 
+    ffassert(tt==(long) t);}
+  //FFCS:visualization stream redirection
+    bool eof() {return ffapi::ff_feof(TheStream);}
+  PlotStream& read( bool& b) {read(reinterpret_cast< void *> (&b),sizeof(bool));  b=r_endian(b);return *this;}
+  PlotStream& read( long long& b) {read(reinterpret_cast< void *> (&b),sizeof(long long)); b=r_endian(b);return *this;}
+  PlotStream& read( long& b) { long long l;
+    read(reinterpret_cast< void *> (&l),sizeof(long long));
+    l=r_endian(l);
+    b=(long) l;
+    if(( b-(long) l) !=0)
+      { cout << " err err read long : error " << b << " !=  " << l << endl;
+	assert( (b-(long) l)==0);}
+    return *this;}
+  PlotStream& read( int& b) {read(reinterpret_cast< void *> (&b),sizeof(int)); b=r_endian(b);return *this;}
+  PlotStream& read( double& b) {read(reinterpret_cast< void *> (&b),sizeof(double)); b=r_endian(b);return *this;}
+  PlotStream &read( complex<double> &C) { double  re,im; read(re); read(im); C=complex<double>(re,im); return 
+ *this;}
+  PlotStream &read( Fem2D::R1 & P) { return read(P.x);}
+  PlotStream &read( Fem2D::R2 & P) { return read(P.x),read(P.y);}
+  PlotStream &read( Fem2D::R3 & P) { return read(P.x),read(P.y),read(P.z);}
+  PlotStream& read( string& b) {  	
+    int l;
+    read(l);
+    b.resize(l);
+    read(& (b[0]),l);
+    return *this;
+  }
+  
+  
+  
+  PlotStream & operator >> ( bool& b)      { return read(b); }
+  PlotStream & operator >> ( long& b)      { return read(b); }        
+  PlotStream & operator >> ( long long& b) { return read(b); }        
+  PlotStream & operator >> ( int& b)       { return read(b); }        
+  PlotStream & operator >> ( double& b)    { return read(b); }
+  PlotStream & operator >> ( complex<double>& b)    { return read(b); }
+  PlotStream & operator >> ( string& s)    { return read(s); }
+  PlotStream & operator >> ( string *& s) 
+  { if(!s) s= new string; return read(*s);
+    // cout << " fread string " << s <<endl;
+  }
+  
+  PlotStream & operator >> ( Mesh *& Th)
+  {
+    long n;
+    read(n);
+    Serialize s(n,Mesh::magicmesh);
+    read(s,n );
+    Th= new Mesh(s);
+    return *this;
+  }
+ 
+ 
+  template<class T>  
+  PlotStream & operator >> ( KN<T>& b)
+  {
+    long n;
+    read(n);
+   // cout << "PlotStream >>  : n " << n << endl;
+      
+    if( ! b.N() ) b.init(n);
+    ffassert( b.N()==n); 
+    for (int i=0;i<n;++i)
+      read(b[i]);
+    return *this;
+  }
+  //  PlotStream & operator << (const Mesh3& Th);   
+  //  PlotStream & operator >> ( Mesh3 *& Th);
+    PlotStream &  operator >> ( Fem2D::Mesh3 *& Th) {	Th= new Fem2D::Mesh3(TheStream); return *this;}
+    PlotStream &  operator >> ( Fem2D::Mesh2 *& Th) {	Th= new Fem2D::Mesh2(TheStream); return *this;}
+    
+    
+    // ---   I also write the type .. to skip data if we  need  to skip data 
+    // just change   >> and <<  by :  <= and >= 
+    PlotStream & operator <= (const bool& b)    { return write(1),write(b); }
+    PlotStream & operator <= (const long& b)    { return write(2),write(b); }        
+    PlotStream & operator <= (const long long & b)   { return write(3),write(b); }        
+    PlotStream & operator <= (const int& b)      { return write(4),write(b); }        
+    PlotStream & operator <= (const double& b)   { return write(5),write(b); }
+    PlotStream & operator <= (const string& s)   { return write(6),write(s); }
+    PlotStream & operator <= (const string* s)   { return write(6),write(*s); }
+    template<class T>    
+    PlotStream & operator <= (const KN_<T>& b)   { return write(10),write((int) sizeof(T)),operator<<(b);}
+    
+    PlotStream & operator >= ( bool& b)       { return readc(1)>>b; }
+    PlotStream & operator >= ( long& b)       { return readc(2)>>b; }        
+    PlotStream & operator >= ( long long & b) {return  readc(3)>>b; }        
+    PlotStream & operator >= ( int& b)        { return readc(4)>>b; }        
+    PlotStream & operator >= ( double& b)     { return readc(5)>>b; }
+    PlotStream & operator >= ( string& s)     { return readc(6)>>s; }
+    PlotStream & operator >= ( string*& s)     { return readc(6)>>s; }
+    template<class T>    
+    PlotStream & operator >= ( KN<T>& b)   { return readc(10), readc(sizeof(T)), operator>>(b);}
+    PlotStream & readc(int cc) { int c; read(c); assert(c==cc); return *this;}
+    
+    void SkipData() { int c; read(c); 
+	bool b;
+	int i;
+	long l,n;
+	long long ll;
+	string s;
+	double d;
+	char buf[100];
+	switch (c) {
+	    case 1: read(b);break;
+	    case 2: read(l);break;
+	    case 3: read(ll);break;
+	    case 4: read(i);break;
+	    case 5: read(d);break;
+	    case 6: read(s);break;
+            case 10: read(l); assert(l>0 && l <100);
+		read(n);
+		for(int i=0;i<n;++n) read(buf,l);
+	    default:
+		break;
+	}
+	
+    }    
+    
+};
+
diff --git a/src/fflib/Serialize.hpp b/src/fflib/Serialize.hpp
new file mode 100644
index 0000000..2b35448
--- /dev/null
+++ b/src/fflib/Serialize.hpp
@@ -0,0 +1,99 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef SERIALEZE_HPP_
+#define SERIALEZE_HPP_
+#include <cstring>
+#include "endian.hpp"
+struct MPIrank;
+ class Serialize {  
+   // we store a refcounter in the pointer p a adresse p-sizeof(long)
+   // so we can use the copy constructor
+   protected: 
+   
+  size_t lg;
+  const char *what;
+  char * p; 
+  public: 
+  Serialize(size_t lgg,const char * wht): 
+    lg(lgg), what(wht) , p((new char[lg+sizeof(long)])+sizeof(long)) 
+   { //cout << " begin count()=0 " << endl;
+    count()=0; }
+     void resize(size_t lgn) { // Add nov 2010 FH of asyncrone recv MPI ... 
+	 if (lgn>lg) 
+	   {
+	     char *p0= new char[lgn+sizeof(long)];
+	     memcpy(p0,p-sizeof(long),lg+sizeof(long));
+	     delete [] (p-sizeof(long));
+	     p= p0+sizeof(long);
+	   }
+	 lg=lgn;
+     }
+  ~Serialize(){ if(count()--==0) delete [] (p-sizeof(long));}
+  size_t size() const { return lg;}
+  //  mpi routine
+  void mpisend(const MPIrank &,long tag,const void * comm);
+  Serialize(const MPIrank &,const char * wht,long tag,const void * comm); 
+  //  end mpi routine 
+  operator void *() { return p;} 
+  operator char *() { return p;} 
+  bool samewhat(const char * w) const { return strncmp(what,w,8)==0; }
+
+  Serialize(const Serialize & s) :
+    lg(s.lg),
+    what(s.what) ,  
+    p(s.p)
+   { count()++; } 
+  
+ template<typename T>  inline void get(size_t & k,T & x) const
+   { 
+     T xx;//= r_endian(x);
+     assert(k<=lg+sizeof(T));
+     memcpy(&xx,p+ k,sizeof(T));
+     k +=  sizeof(T);
+     x=r_endian(xx);
+   }
+   template<typename T>  inline void put(size_t & k,const T & x) 
+   { 
+     if ( !(k<=lg+sizeof(T)) )
+       {
+	 cout << " assert put " << k << " <=" << lg + sizeof(T) << endl;
+	 assert((k<=lg+sizeof(T)));
+       }
+     T xx= w_endian(x);
+     memcpy( p + k,&xx,sizeof(T));
+     k += sizeof(T);
+   }
+   
+ protected:
+   long & count() const  { return * (long*) (void*) (p-sizeof(long));}
+ private:
+   void operator=(Serialize & s) ; // no affectation
+
+
+ };
+#endif
diff --git a/src/fflib/String.hpp b/src/fflib/String.hpp
new file mode 100644
index 0000000..367328f
--- /dev/null
+++ b/src/fflib/String.hpp
@@ -0,0 +1,170 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef STRING_HPP_
+#define STRING_HPP_
+
+
+#include <map>
+#include <cstdio>
+
+// BUG option compilation -fast 
+/*
+template<class T>
+string * toString(const T& a)
+{ ostringstream r;
+  r << a  ENDS ;
+  return new string(r.str());
+}
+
+*/
+// 
+inline string * toString(const double& a)
+{
+  char buf[30];
+  sprintf(buf,"%g",a);
+ return new string(buf);
+}
+inline string * toString(const long& a)
+{
+  char buf[30];
+  sprintf(buf,"%ld",a);
+  return new string(buf);
+}
+inline string * toString(const bool& a)
+{
+  return new string(a?"T":"F");
+}
+inline string * toString(const complex<double> & a)
+{
+  char buf[60];
+  sprintf(buf,"%g%+gi",a.real(),a.imag());
+  return new string(buf);
+}
+
+
+inline string * toStringCconst(const char * const &a)
+{ return new string(a);
+}
+inline string * toStringC( char * const &a)
+{ return new string(a);
+}
+
+template<class T>
+string * PtoString(const  T * a)
+{ ostringstream r;
+  r << *a ENDS;
+  return new string(r.str());
+}
+
+template<class T>
+AnyType PtoStringA(void *, const AnyType &a)
+{ 
+  ostringstream r;
+  r << *GetAny<T*>(a) ENDS ;
+  return SetAny<string *>(new string(r.str()));
+}
+template<class T>
+AnyType toStringA(void *, const AnyType &a)
+{ 
+  ostringstream r;
+  r << GetAny<T>(a) ENDS ;
+  return SetAny<string *>(new string(r.str()));
+}
+
+class String {  
+  string  * p;
+  public: 
+//  String( string & pp) : p(&pp) {}
+  String() : p(new string()) {/*cout << "String" << p <<","<<  *p << endl;*/}
+  void init() { p= new string();} // Add FH march 2010 
+void destroy() { delete p;p=0;} // Add FH march 2010 
+//  String( string * c) : p(c) {cout << "String" << p <<","<< *p << endl;} 
+  String(const String & c) : p(new string(c)) {/*cout << "String" << p <<","<< *p << endl;*/} 
+  String(const string & c) : p(new string(c)) {/*cout << "String" << p <<","<< *p << endl;*/} 
+  String(const char *  c) : p(new string(c)) {/*cout << "String" << p <<","<< *p << endl;*/} 
+  String(const long & c) : p(toString(c)){/*cout << "String" << p <<","<< *p << endl;*/} 
+  String(const double & c) : p(toString(c)){/*cout << "String" << p <<","<< *p << endl;*/} 
+  String(const bool & c) : p(toString(c)){/*cout << "String" << p <<","<< *p << endl;*/} 
+  String(const  long * c) : p(PtoString(c)){/*cout << "String" << p <<","<< *p << endl;*/} 
+  String(const double * c) : p(PtoString(c)){/*cout << "String" << p <<","<< *p << endl;*/} 
+  String & operator=(const String & s){delete p;p=new string(s);return *this;}
+  String  operator+(const String & s)const {return String(new string(*p+*s.p));} 
+  ~String(){/* cout << "~String" << p << *p << endl;*/ delete p; p=0;}
+   operator const string & () const {return *p;}
+   operator  string & ()  {return *p;}
+   string **  getap()  {return &p;}
+  friend inline  ostream & operator<<(ostream & f,const String & s) {throwassert(s.p); f << *s.p ; return f;}
+  bool operator<(const String &t) const {assert(p && t.p);return *p<*t.p;} // correction FH feb 2004
+  bool operator>(const String &t) const {assert(p && t.p);return *p>*t.p;} // correction FH feb 2004
+};
+
+
+template<class K,class V>
+class MyMap {
+  public:
+  map<K,V> *m;
+  
+  MyMap() : m(new map<K,V>) {/*cout << "new MyMap:: " << m << endl;*/} 
+  MyMap &operator=(MyMap &M){ 
+  //   cout << " MyMap::= " << m << " = " << M.m << endl;
+     delete m;m=new map<K,V>(M);
+    }
+  V &operator[](const K & k) {
+  throwassert(m);
+  typename map<K,V>::iterator i=m->find(k);
+//  cout << k << " "  << " end? "  << (i==m->end())  << endl;
+//  for(  map<K,V>::iterator ii=m->begin(); ii != m->end();ii++)
+ //    cout << " MyMap ::   m="<< m << ": " <<  ii->first  << "  -> " <<  ii->second <<endl;
+ // map<K,V>::iterator j=m->find(k);
+  
+ // cout << " m->find(k)->second   " <<  i->second  << ";" <<  j->second <<endl;
+  typedef typename map<K,V>::value_type   value_type;
+  if  (i==m->end())
+     i=m->insert(value_type(k,V())).first;
+  V &  v= i->second ;  
+  return v;
+}
+  ~MyMap(){delete m;/*cout << "MyMap:: delete "<< m << endl;*/m=0;} 
+  private:
+    MyMap(const MyMap &M):m(new map<K,V>(*M.m)) {}
+ 
+};
+template<class A,class B>
+struct pairless : binary_function<pair<A,B>,const char *, bool>
+   { 
+    typedef pair<A,B> Key;
+    bool operator()(const Key& x, const Key& y) const { return  x.first<y.first ? true
+       :  (  (x.first == y.first)  ? (x.second < y.second) : false );} };
+       
+typedef   map<pair<aType,aType>,aType,pairless<aType,aType> > Map_type_of_map; 
+    
+extern  Map_type_of_map map_type_of_map ; //  to store te type 
+//  of a map  of  A[B] 
+
+
+#endif
diff --git a/src/fflib/UMFPack_Solver.cpp b/src/fflib/UMFPack_Solver.cpp
new file mode 100644
index 0000000..2d5063f
--- /dev/null
+++ b/src/fflib/UMFPack_Solver.cpp
@@ -0,0 +1,366 @@
+//  file to add UMFPACK solver with dynamic load.
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "lgsolver.hpp"
+
+ 
+#ifdef HAVE_LIBUMFPACK
+extern "C" {
+#ifdef HAVE_UMFPACK_H
+#include <umfpack.h>
+#else
+#ifdef HAVE_UMFPACK_UMFPACK_H
+#include <umfpack/umfpack.h>
+#else
+#ifdef HAVE_BIG_UMFPACK_UMFPACK_H
+#include <UMFPACK/umfpack.h>
+#else
+#ifdef HAVE_UFSPARSE_UMFPACK_H
+#include <ufsparse/umfpack.h>
+#else
+#ifdef HAVE_SUITESPARSE_UMFPACK_H
+#include <suitesparse/umfpack.h>
+#else
+
+  // Defaults to a local version of the UMFPACK headers
+#include "../../download/include/umfpack.h"
+
+#endif // HAVE_SUITESPARSE_UMFPACK_H
+#endif // HAVE_UFSPARSE_UMFPACK_H
+#endif // HAVE_BIG_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_UMFPACK_H
+#endif // HAVE_UMFPACK_H
+}
+
+template<class R>
+class SolveUMFPACK :   public MatriceMorse<R>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  void *Symbolic, *Numeric ;
+  int umfpackstrategy;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+public:
+  SolveUMFPACK(const MatriceMorse<R> &A,int strategy,double ttgv, double epsilon=1e-6,
+	       double pivot=-1.,double pivot_sym=-1.  ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),
+    Symbolic(0),Numeric(0)  ,
+    umfpackstrategy(strategy),
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+    
+    int status;
+    throwassert( !A.sym() && Numeric == 0 && Symbolic==0 );
+    int n=A.n;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    
+    for(int i=0;i<UMFPACK_CONTROL;i++) Control[i]=0;
+    for(int i=0;i<UMFPACK_INFO;i++) Info[i]=0;
+    
+    umfpack_di_defaults (Control) ;
+    Control[UMFPACK_PRL]=1;
+   // Control[UMFPACK_PIVOT_TOLERANCE]=1E-10;
+    
+    if(verbosity>4) Control[UMFPACK_PRL]=2;
+    if(tol_pivot_sym>0) Control[UMFPACK_SYM_PIVOT_TOLERANCE]=pivot_sym;
+    if(tol_pivot>0) Control[UMFPACK_PIVOT_TOLERANCE]=pivot;
+    if(umfpackstrategy>=0)   Control[UMFPACK_STRATEGY]=umfpackstrategy;
+    if(verbosity>3) { 
+      cout << "  UMFPACK real  Solver Control :" ;
+      cout << "\n\t SYM_PIVOT_TOLERANCE "<< Control[UMFPACK_SYM_PIVOT_TOLERANCE];
+      cout << "\n\t PIVOT_TOLERANCE     "<< Control[UMFPACK_PIVOT_TOLERANCE];
+      cout << "\n\t PRL                 "<< Control[UMFPACK_PRL];
+      cout << "\n";      
+    }
+    
+    status = umfpack_di_symbolic (n, n, A.lg, A.cl, A.a, &Symbolic,Control,Info) ;
+    if (status !=  0)
+    {
+      (void) umfpack_di_report_matrix (n, n, A.lg, A.cl, A.a, 1, Control) ;
+
+	umfpack_di_report_info (Control, Info) ;
+	umfpack_di_report_status (Control, status) ;
+	cerr << "umfpack_di_symbolic failed" << endl;
+	ExecError("umfpack_di_symbolic failed");
+	//ffassert(0);
+    }
+
+    status = umfpack_di_numeric (A.lg, A.cl, A.a, Symbolic, &Numeric,Control,Info) ;
+    if (status !=  0)
+    {
+	umfpack_di_report_info (Control, Info) ;
+	umfpack_di_report_status (Control, status) ;
+	cerr << "umfpack_di_numeric failed" << endl;
+	ExecError("umfpack_di_numeric failed");
+	ffassert(0);
+    }
+
+    if (Symbolic) umfpack_di_free_symbolic (&Symbolic),Symbolic=0; 
+    if(verbosity>3)
+    cout << "  -- umfpack_di_build LU " << n <<  endl;
+    if(verbosity>5)     (void)  umfpack_di_report_info(Control,Info);
+
+  }
+  void Solver(const MatriceMorse<R> &A,KN_<R> &x,const KN_<R> &b) const  {
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    for(int i=0;i<UMFPACK_CONTROL;i++) Control[i]=0;
+    for(int i=0;i<UMFPACK_INFO;i++) Info[i]=0;
+    int n= b.N(); 
+     ffassert(A.ChecknbLine( n) && n == x.N() && A.ChecknbColumn(n) );
+    
+     umfpack_di_defaults (Control) ;
+     // change UMFPACK_At to UMFPACK_Aat in complex 
+    int status = umfpack_di_solve (UMFPACK_Aat, A.lg, A.cl, A.a, KN_2Ptr<R>(x), KN_2Ptr<R>(b), Numeric,Control,Info) ;
+    if (status != 0)
+    {
+	umfpack_di_report_info (Control, Info) ;
+	umfpack_di_report_status (Control, status) ;
+	cerr << "umfpack_di_solve failed" << endl;
+	ExecError("umfpack_di_solve failed");
+	
+	ffassert(0);
+    }
+     if(verbosity>2)
+    cout << "  -- umfpack_di_solve,  peak Mem: " << long(Info[UMFPACK_PEAK_MEMORY])/(1024*1024)*Info[UMFPACK_SIZE_OF_UNIT] << "Mbytes " << endl;
+    if(verbosity>3)
+    cout << "   b min max " << b.min() << " " <<b.max() << endl;
+    if(verbosity>3)     (void)  umfpack_di_report_info(Control,Info);
+     if(verbosity>1) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+  }
+
+  ~SolveUMFPACK() { 
+   if(verbosity>3)
+    cout << "~SolveUMFPACK S:" << Symbolic << " N:" << Numeric <<endl;
+    if (Symbolic)   umfpack_di_free_symbolic  (&Symbolic),Symbolic=0; 
+    if (Numeric)    umfpack_di_free_numeric (&Numeric),Numeric=0;
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+template<>
+class SolveUMFPACK<Complex> :   public MatriceMorse<Complex>::VirtualSolver  {
+  double eps;
+  mutable double  epsr;
+  int umfpackstrategy;
+  double tgv;
+  void *Symbolic, *Numeric ;
+  double *ar,*ai;
+
+
+    double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+
+public:
+  SolveUMFPACK(const MatriceMorse<Complex> &A,int strategy,double ttgv, double epsilon=1e-6,
+     double pivot=-1.,double pivot_sym=-1.
+) : 
+    eps(epsilon),epsr(0),umfpackstrategy(strategy),tgv(ttgv),
+    Symbolic(0),Numeric(0),
+    ar(0),ai(0),
+    tol_pivot_sym(pivot_sym), 
+    tol_pivot(pivot)
+   { 
+    int status;
+    throwassert( !A.sym());
+    int n=A.n;
+    //  copy the coef of the matrice ---
+     ar= new double[A.nbcoef];
+     ai= new double[A.nbcoef];
+     ffassert(ar && ai);
+     C2RR(A.nbcoef,A.a,ar,ai);
+        
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+    umfpack_zi_defaults (Control) ;
+    Control[UMFPACK_PRL]=1;
+    if(verbosity>4) Control[UMFPACK_PRL]=2;
+   //    Control[UMFPACK_SYM_PIVOT_TOLERANCE]=1E-10;
+  //  Control[UMFPACK_PIVOT_TOLERANCE]=1E-10;
+    if(tol_pivot_sym>0) Control[UMFPACK_SYM_PIVOT_TOLERANCE]=pivot_sym;
+    if(tol_pivot>0) Control[UMFPACK_PIVOT_TOLERANCE]=pivot;
+    if(umfpackstrategy>=0) Control[UMFPACK_STRATEGY]=umfpackstrategy;
+    if(verbosity>3) { 
+      cout << "  UMFPACK complex Solver Control :" ;
+      cout << "\n\t SYM_PIVOT_TOLERANCE "<< Control[UMFPACK_SYM_PIVOT_TOLERANCE];
+      cout << "\n\t PIVOT_TOLERANCE     "<< Control[UMFPACK_PIVOT_TOLERANCE];
+      cout << "\n\t PRL                 "<< Control[UMFPACK_PRL];
+      cout << "\n";      
+    }
+    status = umfpack_zi_symbolic (n, n, A.lg, A.cl, ar,ai, &Symbolic,Control,Info) ;
+    if (status < 0)
+    {
+      (void) umfpack_zi_report_matrix (n, n, A.lg, A.cl, ar,ai, 1, Control) ;
+
+	umfpack_zi_report_info (Control, Info) ;
+	umfpack_zi_report_status (Control, status) ;
+	cerr << "umfpack_zi_symbolic failed" << endl;
+	ExecError("umfpack_zi_symbolic failed");
+	ffassert(0);
+	exit(2);
+    }
+
+    status = umfpack_zi_numeric (A.lg, A.cl, ar,ai, Symbolic, &Numeric,Control,Info) ;
+    if (status < 0)
+    {
+	umfpack_zi_report_info (Control, Info) ;
+	umfpack_zi_report_status (Control, status) ;
+	cerr << "umfpack_zi_numeric failed" << endl;
+	ExecError("umfpack_zi_numeric failed");
+	ffassert(0);
+	exit(2);
+    }
+
+    if (Symbolic) umfpack_zi_free_symbolic (&Symbolic),Symbolic=0; 
+    if(verbosity>3)
+    cout << "umfpack_zi_build LU " << n <<  endl;
+    if(verbosity>5)     (void)  umfpack_zi_report_info(Control,Info);
+
+  }
+  void Solver(const MatriceMorse<Complex> &A,KN_<Complex> &x,const KN_<Complex> &b) const  {
+        ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+    double Control[UMFPACK_CONTROL];
+    double Info[UMFPACK_INFO];
+     umfpack_zi_defaults (Control) ;
+     int n = b.N();
+     ffassert(A.ChecknbLine( n) && n == x.N() && A.ChecknbColumn(n) );
+     KN<double> xr(n),xi(n),br(n),bi(n);
+     C2RR(n,b,br,bi);
+     // change UMFPACK_At to UMFPACK_Aat in complex  oct 2005 
+    int status = umfpack_zi_solve (UMFPACK_Aat, A.lg, A.cl, ar,ai, xr, xi, br,bi, Numeric,Control,Info) ;
+    if (status < 0)
+    {
+	umfpack_zi_report_info (Control, Info) ;
+	umfpack_zi_report_status (Control, status) ;
+	cerr << "umfpack_zi_solve failed" << endl;
+	ExecError("umfpack_zi_numeric failed");
+	ffassert(0);
+	exit(2);
+    }
+    RR2C(n,xr,xi,x);
+    if(verbosity>1)
+    {
+      cout << "  -- umfpack_zi_solve, peak Mem : " <<  long(Info[UMFPACK_PEAK_MEMORY])/(1024*1024)*Info[UMFPACK_SIZE_OF_UNIT] << "Mbytes " << endl;
+      
+     if(verbosity>3)     (void)  umfpack_zi_report_info(Control,Info);
+    
+      cout << "   b min max " << b.min() << " " <<b.max() << endl;
+      cout << "   x min max " << x.min() << " " <<x.max() << endl;
+    }
+  }
+
+  ~SolveUMFPACK() { 
+    if(verbosity>5)
+    cout << "~SolveUMFPACK " << endl;
+    if (Symbolic)   umfpack_zi_free_symbolic  (&Symbolic),Symbolic=0; 
+    if (Numeric)    umfpack_zi_free_numeric (&Numeric),Numeric=0;
+    delete [] ar;
+    delete [] ai;   
+  }
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+     
+
+}; 
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildSolverIUMFPack(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+  //cout << " BuildSolverUMFPack<double>" << endl;
+    return new SolveUMFPACK<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+inline MatriceMorse<Complex>::VirtualSolver *
+BuildSolverIUMFPack(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  //cout << " BuildSolverUMFPack<Complex>" << endl;
+    return new SolveUMFPACK<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym);
+}
+
+
+
+
+//  the 2 default sparse solver double and complex
+//DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+extern TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue;//=TypeSolveMat::defaultvalue;
+
+template <>
+DefSparseSolver<double>::SparseMatSolver  DefSparseSolver<double>::solver =BuildSolverIUMFPack;
+template <>
+DefSparseSolver<Complex>::SparseMatSolver  DefSparseSolver<Complex>::solver =BuildSolverIUMFPack;
+
+static bool SetUMFPACK()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to UMFPack" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverIUMFPack;
+    DefSparseSolver<Complex>::solver =BuildSolverIUMFPack;    
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+    return 1;
+}
+
+void init_UMFPack_solver()
+{
+  if(verbosity>2) 
+  cout << " UMFPACK ";
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  
+  DefSparseSolver<double>::solver =BuildSolverIUMFPack;
+  DefSparseSolver<Complex>::solver =BuildSolverIUMFPack;
+  Global.Add("defaulttoUMFPACK","(",new OneOperator0<bool>(SetUMFPACK));  
+  Global.Add("defaultoUMFPACK","(",new OneOperator0<bool>(SetUMFPACK));
+  Global.New("HaveUMFPACK",CConstant<bool>(true)); 
+
+}
+
+
+#ifdef LOAD_LINK_
+class Init { public:
+    Init();
+};
+Init init;
+Init::Init(){    
+  init_UMFPack_solver();
+}
+
+#endif
+
+#else
+  using namespace Fem2D;
+
+bool SetGMRES();
+void init_UMFPack_solver() {
+  if(verbosity) 
+  cout << " no UMFPACK -> replace by LU or GMRES  "; 
+  Global.Add("defaultoUMFPACK","(",new OneOperator0<bool>(SetGMRES));
+  Global.New("HaveUMFPACK",CConstant<bool>(false)); 
+}
+
+template <>
+DefSparseSolver<double>::SparseMatSolver  DefSparseSolver<double>::solver =BuildSolverGMRES;
+template <>
+DefSparseSolver<Complex>::SparseMatSolver  DefSparseSolver<Complex>::solver =BuildSolverGMRES;
+
+#endif
diff --git a/src/fflib/array_complex.cpp b/src/fflib/array_complex.cpp
new file mode 100644
index 0000000..7f8a64e
--- /dev/null
+++ b/src/fflib/array_complex.cpp
@@ -0,0 +1,91 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "array_tlp.hpp"
+#include "array_init.hpp"
+
+
+KN_<double> Get_C2R(KN_<complex<double> >  vc)
+{
+  ffassert(vc.step==1);
+  complex<double> * pc=vc; // pointeur du tableau                                                                            
+  double *pr = static_cast<double*>(static_cast<void*>(pc));
+  return KN_<double>(pr,vc.N()*2);
+}
+
+template<int offset>
+KN_<double> Get_C2R_(KN_<complex<double> >  vc)
+{
+  complex<double> * pc=vc; // pointeur du tableau                                                                            
+  double *pr = static_cast<double*>(static_cast<void*>(pc));
+  return KN_<double>(pr+offset,vc.N(),vc.step*2);
+}
+template<int offset>
+KNM_<double> Get_C2R_(KNM_<complex<double> >  vc)
+{
+    complex<double> * pc=vc; // pointeur du tableau                                                                            
+    double *pr = static_cast<double*>(static_cast<void*>(pc));
+    return KNM_<double>(pr+offset,ShapeOfArray(vc.N(),vc.step*2),vc.shapei,vc.shapej);
+}
+
+
+void initArrayDCLComplex()
+{
+     ArrayDCL<Complex>();
+}
+
+Complex square(const Complex & x){return x*x;}
+
+void initArrayOperatorComplex()
+{
+    typedef Complex K;
+    typedef const K & KK;
+    ArrayOperator<Complex,long>();
+    ArrayOperatorF<Complex,const Complex&>();
+     // take the real or imag part of complex array
+    Add<KN<Complex> *>("im",".",new OneOperator1<KN_<double>,KN_<Complex> >(Get_C2R_<1>,atype<KN<Complex> * >()));
+    Add<KN_<Complex> >("im",".",new OneOperator1<KN_<double>,KN_<Complex> >(Get_C2R_<1>,atype<KN_<Complex>  >()));
+    Add<KN<Complex> *>("re",".",new OneOperator1<KN_<double>,KN_<Complex> >(Get_C2R_<0>,atype<KN<Complex> * >()));
+    Add<KN_<Complex> >("re",".",new OneOperator1<KN_<double>,KN_<Complex> >(Get_C2R_<0>,atype<KN_<Complex>  >()));
+
+    Add<KNM<Complex> *>("im",".",new OneOperator1<KNM_<double>,KNM_<Complex> >(Get_C2R_<1>,atype<KNM<Complex> * >()));
+    Add<KNM_<Complex> >("im",".",new OneOperator1<KNM_<double>,KNM_<Complex> >(Get_C2R_<1>,atype<KNM_<Complex>  >()));
+    Add<KNM<Complex> *>("re",".",new OneOperator1<KNM_<double>,KNM_<Complex> >(Get_C2R_<0>,atype<KNM<Complex> * >()));
+    Add<KNM_<Complex> >("re",".",new OneOperator1<KNM_<double>,KNM_<Complex> >(Get_C2R_<0>,atype<KNM_<Complex>  >()));
+    
+    Global.Add("square","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(square));
+    Global.Add("conj","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(conj));
+
+    map_type[typeid(SetArray<K>).name()]->AddCast(					     
+						  new E_F1_funcT<SetArray<K>,SetArray<long> >(Cast<SetArray<K>,SetArray<long> >),
+						  new E_F1_funcT<SetArray<K>,SetArray<double> >(Cast<SetArray<K>,SetArray<double> >)
+	  					      
+					      );
+    Global.Add("toCarray","(",new OneOperator_2KN_<Complex>);
+    
+}
diff --git a/src/fflib/array_init.hpp b/src/fflib/array_init.hpp
new file mode 100644
index 0000000..2439ae2
--- /dev/null
+++ b/src/fflib/array_init.hpp
@@ -0,0 +1,37 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+void initArrayDCLComplex();
+void initArrayOperatorComplex();
+//
+void initArrayDCLdouble();
+void initArrayOperatordouble();
+//
+void initArrayDCLlong();
+void initArrayOperatorlong();
+//
+void     initStringOperator();
diff --git a/src/fflib/array_long.cpp b/src/fflib/array_long.cpp
new file mode 100644
index 0000000..6048c36
--- /dev/null
+++ b/src/fflib/array_long.cpp
@@ -0,0 +1,169 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "array_tlp.hpp"
+#include "array_init.hpp"
+const basicForEachType *aatypeknlongp;
+/*
+void initArrayOperators()
+{
+     ArrayOperator<double>();
+     ArrayOperator<Complex>();
+     ArrayOperator<long>();
+
+}
+void  initArrayDCL()
+{
+    ArrayDCL<double>();
+    ArrayDCL<Complex>();
+    ArrayDCL<long>();
+}
+*/
+
+ aType aaaa_knlp;
+void initArrayDCLlong()
+{
+//     ArrayOperator<long>();
+     Dcl_Type<Inv_KN_long>(); // Add FH mars 2005
+     ArrayDCL<long>();
+     aaaa_knlp = atype<KN<long>*>();
+
+}
+
+
+class OneBinaryOperatorInv_KN_long : public OneOperator { public:  
+  OneBinaryOperatorInv_KN_long(basicForEachType * ti) : OneOperator(atype<Inv_KN_long >(), ti ,atype<long>()) {}
+    E_F0 * code(const basicAC_F0 & args) const 
+     { Expression p=args[1];
+       if ( ! p->EvaluableWithOutStack() ) 
+        { 
+          bool bb=p->EvaluableWithOutStack();
+          cout << bb << " " <<  * p <<  endl;
+          CompileError("Inverse:  int[int] I,  array, with  I^p, The p must be a constant == -1, sorry");}
+       long pv = GetAny<long>((*p)(NullStack));
+        if (pv !=-1)   
+         { char buf[100];
+           sprintf(buf,"Inverse:  int[int] I,  array, I^%ld, The pow must be  == -1, sorry",pv);
+           CompileError(buf);}     
+       return  new E_F_F0<Inv_KN_long,KN_<long> >(Build<Inv_KN_long,KN_<long> >,to< KN_<long> >(args[0])); 
+    }
+};
+// end Hack 
+// Add mars 2010 
+template<class R>  R * set_init_init( R* const & a,const long & n){ 
+    SHOWVERB( cout << " set_init " << typeid(R).name() << " " << n << endl);
+    a->init(n);
+    for (int i=0;i<n;i++)
+	(*a)[i].init();
+    return a;}
+inline   string ** get_elements( KN<String> *  const  &  a,long  const   & b)
+{   ffassert( a && b >=0 && b < a->size());
+    String & Sret =  (*a)[b]; // correction FH feb 2004
+    // delete b; la chaine est detruire automatiquement en fin d'instruction  FH jan 2010
+    return Sret.getap();}
+
+template<class A> inline AnyType Destroy_KN(Stack,const AnyType &x){
+    KN<A> * a=GetAny<KN<A>*>(x);
+    for (int i=0;i<a->N(); i++)
+	(a)[i].destroy();
+    a->destroy(); 
+    return  Nothing;
+}
+// fin add
+
+
+template<class A,class B>
+struct set_Inv_KN_long: public binary_function<A,B,A> {
+    static A f(const A & a, B const & b)  
+    {  
+	int n=a.N();
+	KN_<long> I(b.t);
+	for(int i=0;i<I.N();++i)
+	  {
+	    int j=I[i];
+	    if(j>=0 && j<n)
+	    a[j]=i;
+	  }
+
+    return a;}
+};
+template<class A,class B>
+struct set_Inv_pKN_longI: public binary_function<A,B,A> {
+    static A f(const A & a, B const & b)  
+    {  
+	KN_<long> I(b.t);
+	int n=I.max()+1;
+	a->init(n);
+	(*a)=-1;
+	for(int i=0;i<I.N();++i)
+	  {
+	    int j=I[i];
+	    if(j>=0 && j<n)
+	    (*a)[j]=i;
+	  }
+	return a;}
+};
+
+
+void initArrayOperatorlong()
+{
+    typedef long K;
+     ArrayOperator<long,long>();
+     // to def inverse permutation // Add FH mars 2005
+     TheOperators->Add("^", new OneBinaryOperatorInv_KN_long(atype<KN_<long> >() ));
+    //- TheOperators->Add("^", new OneBinaryOperatorInv_KN_long(atype<KN<long> *>() )) ;
+     aatypeknlongp= atype<KN<long>*>(); // for  compilation error with g++ 3.2.2
+
+     Add<KN_<long> >("sort",".",new OneOperator1_<KN_<K>,KN_<K> >(SortKn<K, KN_<K> >));
+    // Add<KN<long> >("sort",".",new OneOperator1_<KN<K>,KN<K> >(SortKn<K, KN<K> >));
+     Add<KN<long> *>("sort",".",new OneOperator1_<KN<K>*,KN<K>* >(SortpKn<K>));
+     
+     
+//     ArrayDCL<long>();
+    
+    Dcl_TypeandPtr_<KN_<String>,KN<String> *>(0,0,0,::Destroy<KN<String> >, ::ClearReturnKK_<K,KN<String>,KN_<String> >,::ClearReturnpKK<String,KN<String> >);
+    atype<KN<String>* >()->Add("[","",new OneOperator2_<string**,KN<String>*,long >(get_elements));
+    TheOperators->Add("<-", 
+		      new OneOperator2_<KN<String> *,KN<String> *,long>(&set_init_init));
+    map_type_of_map[make_pair(atype<long>(),atype<string*>())]=atype<KN<String>*>(); // vector
+    Add<KN<String> *>("n",".",new OneOperator1<long,KN<String> *>(get_n));  
+    extern   KN<String> *pkarg;
+    Global.New("ARGV",CPValue<KN<String> >(*pkarg));// add FH mars 2010
+    Global.Add("toZarray","(",new OneOperator_2KN_<long>);
+    TheOperators->Add("=",
+		      new OneBinaryOperator<set_Inv_KN_long<KN_<long> ,Inv_KN_long > > );
+    TheOperators->Add("<-",
+		      new OneBinaryOperator<set_Inv_pKN_longI<KN<long>*,Inv_KN_long > > );
+
+    Add<KN<K> *>("imin",".",new OneOperator1<long,KN<K> *>(get_imin));
+    Add<KN<K> *>("imax",".",new OneOperator1<long,KN<K> *>(get_imax));
+  
+    
+}
+
+ void xxxx() {
+}
diff --git a/src/fflib/array_real.cpp b/src/fflib/array_real.cpp
new file mode 100644
index 0000000..a7fd9c3
--- /dev/null
+++ b/src/fflib/array_real.cpp
@@ -0,0 +1,81 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "array_tlp.hpp"
+#include "array_init.hpp"
+
+
+double square(double x){return x*x;}
+
+void initArrayDCLdouble()
+{
+//     ArrayOperator<long>();
+     ArrayDCL<double>();
+}
+
+//template<class A,class B>  A Build(B b) {  return A(b);}
+void initArrayOperatordouble()
+{
+
+    ArrayOperator<double,long>();
+    ArrayOperatorF<double,double>();
+    typedef double K;
+    typedef double KK;
+     Dcl_Type< QuantileKN<K> > (); 
+     Global.Add("abs","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(fabs));
+     Global.Add("acos","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(acos));
+     Global.Add("asin","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(asin));
+     Global.Add("atan","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(atan));
+     Global.Add("floor","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(floor));
+     Global.Add("ceil","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(ceil));
+
+    Global.Add("square","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(square));
+    Add<KN_<double> >("sort",".",new OneOperator1_<KN_<K>,KN_<K> >(SortKn<K, KN_<K> >));
+   // Add<KN<double> >("sort",".",new OneOperator1_<KN<K>,KN<K> >(SortKn<K, KN<K> >));
+    Add<KN<double> *>("sort",".",new OneOperator1_<KN<K>*,KN<K>* >(SortpKn<K>));
+    
+  //  Add<KN_<double> >("sort",".",new OneOperator2_<KN_<K>,KN_<K>,KN_<long> >(SortKn<K,long, KN_<K>,KN_<long>  >));
+  //  Add<KN<double> >("sort",".",new OneOperator2_<KN<K>,KN<K>,KN_<long> >(SortKn<K,long, KN<K>,KN_<long> >));
+    Global.Add("sort","(",new OneOperator2_<KN<K>*,KN<K>*,KN<long>* >(SortpKn2<K,long>));
+    
+    Add<KN_<double> >("quantile",".",new OneOperator1<QuantileKN<K>,KN_<K> >(Build<QuantileKN<K>,KN_<K> >));
+ //   Add<KN<double> >("quantile",".",new OneOperator1<QuantileKN<K>,KN_<K> >(Build<QuantileKN<K>,KN_<K> >, atype<KN<K> >()));
+   // Add<KN_<double> * >("quantile",".",new OneOperator1<QuantileKN<K>,KN_<K> >(Build<QuantileKN<K>,KN_<K> >, atype<KN<K> >()));
+    Add<KN<double> * >("quantile",".",new OneOperator1<QuantileKN<K>,KN_<K> >(Build<QuantileKN<K>,KN_<K> >, atype<KN<K> *>() ));
+    Add<QuantileKN<K> >("(","",new OneOperator2_<K,QuantileKN<K>,double>(Quantile<K>));
+
+    map_type[typeid(SetArray<K>).name()]->AddCast(					     
+						  new E_F1_funcT<SetArray<K>,SetArray<long> >(Cast<SetArray<K>,SetArray<long> >)
+												  
+						  );
+    Global.Add("toRarray","(",new OneOperator_2KN_<double>);
+    Add<KN<K> *>("imin",".",new OneOperator1<long,KN<K> *>(get_imin));
+    Add<KN<K> *>("imax",".",new OneOperator1<long,KN<K> *>(get_imax));
+
+    
+//     ArrayDCL<long>();
+}
diff --git a/src/fflib/array_resize.hpp b/src/fflib/array_resize.hpp
new file mode 100644
index 0000000..2bb6bec
--- /dev/null
+++ b/src/fflib/array_resize.hpp
@@ -0,0 +1,32 @@
+template<class T> struct  Resize{ T *v;
+  Resize( T * vv) : v(vv) {}
+ }; 
+
+template<class T> T *resize1(const Resize<T> & t,const long &n)
+ {  
+  t.v->resize(n);
+  return  t.v;
+ }
+
+template<class T> T *resizeandclean1(const Resize<T> & t,const long &n)
+ {  
+  int nn= t.v->N(); // old size 
+  
+  for (int i=n;i<nn;i++)  {delete (*t.v)[i];} // clean
+  t.v->resize(n);
+  for (int i=nn;i<n;i++)  {(*t.v)[i]=0;}  
+  return  t.v;
+ }
+ 
+template<class T> T *resize2(const Resize<T> & t,const long &n, const long & m)
+ {  
+  t.v->resize(n,m);
+  return  t.v;
+ }
+
+template<class T> Resize<T> to_Resize( T *v){ return Resize<T>(v);}
+
+template<class T> struct  Resize1{ T v;
+    Resize1( T  vv) : v(vv) {}
+};
+template<class T> Resize1<T> to_Resize1( T v){ return Resize1<T>(v);}
diff --git a/src/fflib/array_tlp.hpp b/src/fflib/array_tlp.hpp
new file mode 100644
index 0000000..01f6d79
--- /dev/null
+++ b/src/fflib/array_tlp.hpp
@@ -0,0 +1,1451 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//#pragma dont_inline on
+//#pragma inline_depth(1)
+
+#include "config-wrapper.h"
+
+#include <complex>
+#include "AFunction.hpp"
+#include <cstdarg>
+#include <cstring>
+#include "error.hpp"
+#include "lex.hpp"
+
+#include "RNM.hpp"
+
+#include "Operator.hpp"
+// for exec routine 
+#include "rgraph.hpp"
+#include "InitFunct.hpp"
+#include <queue>
+#include "array_resize.hpp"
+#include "HeapSort.hpp"
+
+template <class T>
+struct affectation: binary_function<T, T, T>
+{
+	T& operator()(T& x, const T& y) const {return (x=y);}
+};
+
+template <class T>
+struct affectation_add: binary_function<T, T, T>
+{
+	T& operator()(T& x, const T& y) const {return (x+=y);}// correct FH 25/10/2013
+};
+
+template <class T>
+struct affectation_sub: binary_function<T, T, T>
+{
+	T& operator()(T& x, const T& y) const {return (x-=y);}// correct FH 25/10/2013
+};
+
+
+
+extern Map_type_of_map map_type_of_map ; //  to store te type 
+extern Map_type_of_map map_pair_of_type ; //  to store te type 
+
+extern basicForEachType *  typevarreal,  * typevarcomplex;  //  type of real and complex variable
+
+extern int TheCurrentLine; // unset: by default
+extern long mpisize,mpirank;
+
+template<class T> inline T Max (const T &a,const T & b){return a > b ? a : b;}
+template<class T> inline T Min (const T &a,const T & b){return a < b ? a : b;}
+template<class T> inline T Abs (const T &a){return a <0 ? -a : a;}
+template<class T> inline T Max (const T &a,const T & b,const T & c){return Max(Max(a,b),c);}
+template<class T> inline T Min (const T &a,const T & b,const T & c){return Min(Min(a,b),c);}
+template<class T> inline T Square (const T &a){return a*a;}
+
+
+ 
+template<class K> 
+struct Op2_dotproduct: public binary_function<Transpose<KN_<K> >,KN<K> *,K> { 
+  static K f( Transpose<KN_<K> > const & a, KN<K> * const& b)  
+   { return (conj(a.t),*b);} }; 
+
+template<class K> 
+struct Op2_dotproduct_: public binary_function<Transpose<KN_<K> >,KN_<K> ,K> { 
+  static K f( Transpose<KN_<K> > const & a, KN_<K>  const& b)  
+   { return (conj(a.t),b);} }; 
+   
+template<class A,class B>  A Build(B b) {  return A(b);}
+
+template<class T>
+void  HeapSort(T *c,long n,long o)
+{ // trie un tableau c de n valeur avec un decalage de o.
+   //  le tableau: c[i*o] , pour i = 0 a n-1  
+    long l,j,r,i;
+    T crit;
+    c-=o; // on decale de o pour que le tableau commence a o
+    if( n <= 1) return;
+    l = (n/2 + 1)*o;
+    r = n*o;
+    while (1) { // label 2
+	if(l <= o ) { // label 20
+	    crit = c[r];
+	    c[r] = c[o];
+	    r-=o;
+	    if ( r == o ) { c[o]=crit; return;}
+	} else  crit = c[l-=o]; 
+	j=l;
+	while (1) {// label 4
+	    i=j;
+	    j=2*j;
+	    if  (j>r) {c[i]=crit;break;} // L8 -> G2
+	    if ((j<r) && (c[j] < c[j+o])) j+=o; // L5
+	    if (crit < c[j]) c[i]=c[j]; // L6+1 G4
+	    else {c[i]=crit;break;} //L8 -> G2
+	}
+    }
+}
+
+template<class R,class A> A  SortKn(const A  & ca)
+{ 
+    A a(ca);
+    HeapSort<R>(&a[0],a.n,a.step);
+    return a;}
+
+template<class R,class RR,class A,class B> A  SortKn(const A  & ca,const B  & cb)
+{ 
+    cout << "SortKn  " << endl;
+    const A &a(ca);
+    const B &b(cb);
+    ffassert(a.n == b.n);
+    ffassert(a.step == b.step && b.step ==1);
+    HeapSort<R,RR>(&a[0],&b[0],a.n);
+    cout << b << endl;
+return a;}
+
+template<class R,class RR> KN<R> *  SortpKn2( KN<R> * const & pa,KN<RR> * const & pb){ 
+  //  cout << " SortpKn2 " << endl;
+    KN<R> &a(*pa);
+    KN<RR> &b(*pb);
+    ffassert(a.n == b.n);
+    ffassert(a.step == b.step && b.step ==1);
+    HeapSort<R,RR>(&a[0],&b[0],a.n);
+   return pa;}
+
+template<class R> KN<R> *  SortpKn( KN<R> * const & pa){ 
+    KN<R> &a(*pa);
+    HeapSort<R>(&a[0],a.n,a.step);
+    return pa;}
+
+template<class R>
+class QuantileKN:  public KN_<R> { public:
+    QuantileKN(const KN_<R> &a): KN_<R>(a) {}
+    QuantileKN(KN<R>  * p): KN_<R>(*p) {}
+    operator R *() const {return this->KN_<R>::operator R *() ;}    
+};
+
+
+template<class R> R   Quantile(QuantileKN<R>  const & a,const double & q){ 
+    KN<R> b(a); 
+    HeapSort<R>(b,b.n,b.step);
+    long m=lrint(b.n*q);
+    if( m >= b.n) m=b.n-1;
+    if( m < 0) m=0;   
+    R qq=b[m];
+   // cout <<  "Quantile: m = " << m << " " << b <<endl;
+    return qq;}
+
+
+  
+inline void MyAssert(int i,char * ex,char * file,long line)
+{if (i) {
+    cout << "CompileError assertion :  " << ex << " in file " << file << "  line = " << line << endl; 
+     CompileError();}
+ }
+
+
+template<class K>
+inline   K * get_element( MyMap<String,K> *  const  &  a,string*  const   & b)
+ { K * ret=  &((*a)[*b]); // correction FH feb 2004
+  //  cout << "get_element " << *b << " : " << ret << " = "<< * ret << endl;
+   // delete b;  modif mars 2006 auto del ptr
+    return ret;}
+    
+template<>
+inline   string ** get_element<string*>( MyMap<String,string*> *  const  &  a,string*  const   & b)
+ { string** ret=  &((*a)[*b]); // correction FH feb 2004
+    if( *ret ==0) *ret = new string(""); //  string vide ???
+     // cout << "get_element " << *b << " : " << ret << " = "<< * ret << endl;
+    // delete b;  modif mars 2006 auto del ptr
+    return ret;}
+
+inline   string ** get_elements( MyMap<String,String> *  const  &  a,string*  const   & b)
+ { String* Sret=  &((*a)[*b]); // correction FH feb 2004
+   //  delete b;  modif mars 2006 auto del ptr
+    return Sret->getap();}
+
+template<class RR,class A,class B>  
+RR * get_element_(const A & a,const B & b){ 
+  if( b<0 || a.N() <= b) 
+   { cerr << " Out of bound  0 <=" << b << " < "  << a.N() << " array type = " << typeid(A).name() << endl;
+     ExecError("Out of bound in operator []");}
+    return  &((a)[b]);}
+    
+
+template<class RR,class A,class B>  
+RR * get_elementp_(const A & a,const B & b){ 
+  if( b<0 || a->N() <= b) 
+   { cerr << " Out of bound  0 <=" << b << " < "  << a->N() << " array type = " << typeid(A).name() << endl;
+     ExecError("Out of bound in operator []");}
+    return  &((*a)[b]);}
+
+template<class K>  
+KN_<K> fSubArray(const KN_<K> & a,const SubArray & b)
+ { return a(b);}
+template<class K>  
+KN_<K> fSubArrayp( KN<K>  * const & a,const SubArray & b)
+ { return (*a)(b);}
+
+template<class K>  
+KNM_<K> fSubArraybb(const KNM_<K> & a,const SubArray & b,const SubArray & c)
+{ return a(b,c);}
+template<class K>  
+KNM_<K> fSubArraypbb( KNM<K> * const & a,const SubArray & b,const SubArray & c)
+{ return (*a)(b,c);}
+
+template<class K>  
+KN_<K> fSubArrayib(const KNM_<K> & a,const long &i,const SubArray & b)
+{ return a(i,b);}
+template<class K>  
+KN_<K> fSubArraybi(const KNM_<K> & a,const SubArray & b,const long &i)
+{ return a(b,i);}
+
+template<class K>  
+KN_<K> fSubArraypib( KNM<K> *const & a,const long &i,const SubArray & b)
+{ return (*a)(i,b);}
+template<class K>  
+KN_<K> fSubArraypbi( KNM<K> *const & a,const SubArray & b,const long &i)
+{ return (*a)(b,i);}
+
+
+template<class A>  
+A fSubArrayc(const A & a,const char & b)
+ { return a;}
+ 
+template<class RR,class A,class B,class C>  
+RR * get_elementp2_(const A & a,const B & b,const C & c){ 
+  if( b<0 || a->N() <= b || c<0 || a->M() <= c  ) 
+   { cerr << " Out of bound  0 <=" << b << " < "  << a->N() << " " << c << " < "  << a->M() 
+           << " array type = " << typeid(A).name() << endl;
+     ExecError("Out of bound in operator (,)");}
+    return  &((*a)(b,c));}
+
+template<class RR,class A,class B,class C>  
+RR get_element_is(const A &  a,const B & b,const C & c){ 
+ //  cout << b << " .... " << ((*a)(SubArray(1,b),c)) << endl;;
+    return  ((*a)(b,'.')(c));}
+
+template<class RR,class A,class B,class C>  
+RR get_element_si(const A &  a,const B & b,const C & c){ 
+ //  cout << c << " .... " << ((*a)(b,SubArray(1,c) )) << endl;;
+     return  ((*a)('.',c)(b));}
+     
+template<class RR,class A,class B,class C>  
+RR get_element_lineorcol(const A &  a,const B & b,const C & c){ 
+ //  cout << b << " .... " << ((*a)(SubArray(1,b),c)) << endl;;
+    if(c == ':' && (b<0 || a->N() <= b))
+            ExecError("Out of bound");
+    if(b == ':' && (c<0 || a->M() <= c))
+            ExecError("Out of bound");
+    return  ((*a)(b,c));
+    }
+
+template<class RR,class A,class B,class C>  
+RR get_element_is_(const A &  a,const B & b,const C & c){ 
+    //  cout << b << " .... " << ((*a)(SubArray(1,b),c)) << endl;;
+return  ((a)(b,'.')(c));}
+
+template<class RR,class A,class B,class C>  
+RR get_element_si_(const A &  a,const B & b,const C & c){ 
+    //  cout << c << " .... " << ((*a)(b,SubArray(1,c) )) << endl;;
+return  ((a)('.',c)(b));}
+
+template<class RR,class A,class B,class C>  
+RR get_element_lineorcol_(const A &  a,const B & b,const C & c){ 
+    //  cout << b << " .... " << ((*a)(SubArray(1,b),c)) << endl;;
+return  ((a)(b,c));}
+
+template<class RR,class A,class B,class C>  
+RR * get_elementp2__(const A & a,const B & b,const C & c){ 
+    if( b<0 || a.N() <= b || c<0 || a.M() <= c  ) 
+      { cerr << " Out of bound  0 <=" << b << " < "  << a.N() << " " << c << " < "  << a.M() 
+	  << " array type = " << typeid(A).name() << endl;
+      ExecError("Out of bound in operator (,)");}
+return  &((a)(b,c));}
+
+
+    
+
+template<class RR,bool isinit>
+class  InitArrayfromArray : public OneOperator { 
+public:
+    typedef KN<RR> * A;
+    typedef KN<RR> * R;
+    typedef E_Array B;
+    
+    class CODE : public  E_F0 { public:
+       Expression a0;
+       int N;
+       Expression * tab;
+    int * what;//  0  RR, 1 KN<RR>, 
+       const  bool mi;
+
+    CODE(Expression a,const E_Array & tt)  
+      : a0(a),N(tt.size()),
+	tab(new Expression [N]),
+	what(new int[N])  ,
+	mi(tt.MeshIndependent())
+
+      {
+        assert(&tt);
+	//      int err=0;
+        for (int i=0;i<N;i++)
+	if(atype<RR>()->CastingFrom(tt[i].right() ) ) 
+	  {
+          tab[i]=atype<RR>()->CastTo(tt[i]);
+	    what[i]=0;
+	  }
+	else if(atype<KN_<RR> >()->CastingFrom(tt[i].right() ) ) 
+	  {
+	    tab[i]=atype<KN_<RR> >()->CastTo(tt[i].RightExp());
+	    what[i]=1;
+	  }      
+	else 
+	  CompileError(" InitArrayfromArray: we are waiting for scalar or vector of scalar");
+    }
+    
+    AnyType operator()(Stack stack)  const 
+    {
+	//extern void xxxx();
+	//xxxx();
+      A  a=GetAny<A>((*a0)(stack));
+      KN<AnyType> v(N);
+      KN<int>  nn(N+1);
+      for (int i=0;i<N;i++)
+        v[i]= (*(tab[i]))(stack);
+      
+      int n=0;
+      for (int i=0;i<N;i++)
+	{
+	  if (what[i]==0) nn[i]=1;
+	  else if (what[i]==1) nn[i]=GetAny<KN_<RR> >(v[i]).size();
+          n += nn[i];
+	}
+      if (isinit) 
+        a->init(n);
+      else
+	a->resize(n);
+      
+      for (int i=0,j=0 ;i<N; j += nn[i++])
+	
+        if (what[i]==0)
+          (*a)[j]= GetAny<RR>(v[i]);
+        else if (what[i]==1) 
+          (*a)(SubArray(nn[i],j)) = GetAny<KN_<RR> >((*(tab[i]))(stack));// correct bug nov 2014
+        //  (due to resize=> pointer  change Fh
+      return SetAny<R>(a);
+    } 
+    bool MeshIndependent() const     {return  mi;} // 
+    ~CODE() { delete [] tab; delete[] what;}
+    operator aType () const { return atype<R>();}    
+  }; // end sub class CODE
+  
+  
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new CODE(t[0]->CastTo(args[0]),*dynamic_cast<const E_Array*>( t[1]->CastTo(args[1]).LeftValue()));} 
+    InitArrayfromArray():   OneOperator(atype<R>(),atype<A>(),atype<B>())  {}
+  
+};
+
+template<class RR,bool isinit>
+class  InitMatfromAArray : public OneOperator { 
+public:
+    typedef KNM<RR> * A;
+    typedef KNM<RR> * R;
+    typedef E_Array B;
+    
+    class CODE : public  E_F0 { public:
+       Expression a0;
+       int N;
+       int M;
+       Expression ** tab;
+       const  bool mi;
+
+    CODE(Expression a,const E_Array & tt)  
+      : a0(a),N(tt.size()),M(0),
+	tab(new Expression* [N]),
+	mi(tt.MeshIndependent())
+
+      {
+        assert(&tt);
+	//       int err=0;
+        for (int i=0;i<N;i++)
+         {
+          const E_Array  *li =  dynamic_cast<const E_Array *>(tt[i].LeftValue());
+          if (li)
+	  {
+	     const E_Array & lli = *li;
+	     // -- check ---
+	     if( i == 0) { 
+	         M = lli.size(); ffassert( M>0 );
+	        for (int i=0;i<N;i++) tab[i] = new Expression [M];
+	       }
+	     else {  
+	        if ( M != li->size() ) { 
+	        cout << " line " << i << " the size of the column change " << M << " to " << li->size() << endl;
+	        CompileError(" Is not a matrix,  M is not constant" ); } } 
+	        
+	    for (int j=0;j<M;j++)
+              tab[i][j]=atype<RR>()->CastTo(  lli[j]);
+	   }
+	 else  // li == 0 
+	  CompileError(" we are waiting for  vector of scalar [  , , ,  ] ");
+	 }
+	 
+    }
+    
+    AnyType operator()(Stack stack)  const 
+    {
+      A  a=GetAny<A>((*a0)(stack));
+      if (isinit) 
+        a->init(N,M);
+      else
+	a->resize(N,M);
+      
+       for (int i =0;i<N;++i)
+       for (int j =0;j<M;++j)
+          (*a)(i,j)=   GetAny< RR >( (*(tab[i][j]))(stack)) ; 
+      return SetAny<R>(a);
+    } 
+    bool MeshIndependent() const     {return  mi;} // 
+    ~CODE() { for (int i=0;i<N;i++) delete [] tab[i]; delete [] tab; }
+    operator aType () const { return atype<R>();}    
+  }; // end sub class CODE
+  
+  
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new CODE(t[0]->CastTo(args[0]),*dynamic_cast<const E_Array*>( t[1]->CastTo(args[1]).LeftValue()));} 
+    InitMatfromAArray():   OneOperator(atype<R>(),atype<A>(),atype<B>())  {}
+  
+};
+
+template<typename RR>
+class  SetArrayofKNfromKN : public OneOperator { 
+public:
+    typedef KN_<RR>  A; // Warning  B type of  1 parameter 
+    typedef KN_<RR>  R;
+    typedef E_Array B; //   A type of 2 parameter
+    
+    class CODE : public  E_F0 { public:
+       Expression a0;
+       int N;
+       Expression * tab;
+       int * what;//  0  RR, 1 KN<RR>, 
+       const  bool mi;
+
+    CODE(Expression a,const E_Array & tt)  
+      : a0(a),N(tt.size()),
+	tab(new Expression [N]),
+	what(new int[N])  ,
+	mi(tt.MeshIndependent())
+      {
+        assert(&tt);
+	//      int err=0;
+        for (int i=0;i<N;i++)
+	if(atype<RR*>()->CastingFrom(tt[i].left() ) ) 
+	  {
+          tab[i]=atype<RR*>()->CastTo(tt[i]);
+	    what[i]=0;
+	  }
+	else if(atype<KN_<RR> >()->CastingFrom(tt[i].right() ) ) 
+	  {
+	    tab[i]=atype<KN_<RR> >()->CastTo(tt[i].RightExp());
+	    what[i]=1;
+	  }      
+	else 
+	  CompileError(" we are waiting for scalar or vector of scalar");
+    }
+    
+    AnyType operator()(Stack stack)  const 
+    {
+      A  a=GetAny<A>((*a0)(stack));
+      KN<AnyType> v(N);
+      KN<int>  nn(N+1);
+      for (int i=0;i<N;i++)
+        v[i]= (*(tab[i]))(stack);
+      
+      int n=0; 
+      for (int i=0;i<N;i++)
+	{
+	  if (what[i]==0) nn[i]=1;
+	  else if (what[i]==1) nn[i]=GetAny<KN_<RR> >(v[i]).size();
+          n += nn[i];
+	}
+      ffassert(n == a.size()); 
+      for (int i=0,j=0 ;i<N; j += nn[i++])
+	
+        if (what[i]==0)
+         * GetAny<RR*>(v[i]) = a[j];
+        else if (what[i]==1) { // hack FH 
+           KN_<RR> tab(GetAny<KN_<RR> >(v[i])); 
+           tab  =a(SubArray(nn[i],j));
+           }
+      return SetAny<R>(a);
+    } 
+    bool MeshIndependent() const     {return  mi;} // 
+    ~CODE() { delete [] tab; delete[] what;}
+    operator aType () const { return atype<R>();}    
+  }; // end sub class CODE
+  
+  
+    public: // warning hack  A and B 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new CODE(t[1]->CastTo(args[1]),*dynamic_cast<const E_Array*>( t[0]->CastTo(args[0]).RightValue()));} 
+    SetArrayofKNfromKN():   OneOperator(atype<R>(),atype<B>(),atype<A>())  {} // warning with A and B 
+  
+};
+   
+
+
+template<class K> long get_n(KN<K> * p){ return p->N();}
+template<class K> long get_n(KNM<K> * p){ return p->N();}
+template<class K> long get_m(KNM<K> * p){ return p->M();}
+template<class K> K get_max(KN<K> * p){ return p->max();}
+template<class K> K get_min(KN<K> * p){ return p->min();}
+template<class K> long get_imax(KN<K> * p){ long  i =0; for(long k=1;k< p->N(); ++k) if(  (*p)[k]>(*p)[i] ) i=k;  return i ;}
+template<class K> long get_imin(KN<K> * p){ long  i =0; for(long k=1;k< p->N(); ++k) if(  (*p)[k]<(*p)[i] ) i=k;  return i ;}
+
+template<class K> K get_sum(KN<K> * p){ return p->sum();}
+template<class K> double get_l2(KN<K> * p){ return p->l2();}
+template<class K> double get_l1(KN<K> * p){ return p->l1();}
+template<class K> double get_linfty(KN<K> * p){ return p->linfty();}
+
+template<class K> K get_max(KNM<K> * p){ return p->max();}
+template<class K> K get_min(KNM<K> * p){ return p->min();}
+template<class K> K get_sum(KNM<K> * p){ return p->sum();}
+template<class K> double get_l2(KNM<K> * p){ return p->l2();}
+template<class K> double get_l1(KNM<K> * p){ return p->l1();}
+template<class K> double get_linfty(KNM<K> * p){ return p->linfty();}
+
+template<class K,class T > K get_sum0(const T & p){ return p.sum();}
+template<class K,class T > K get_max0(const T &p){ return p.max();}
+template<class K,class T > K get_min0(const T &p){ return p.min();}
+template<class K,class T> K  get_l2_0(const T &p){ return p.l2();}
+template<class K,class T> K  get_l1_0(const T &p){ return p.l1();}
+template<class K,class T> K  get_linfty_0(const T &p){ return p.linfty();}
+
+
+ 
+ class ostream_precis { public:
+ ostream_precis(ostream * ff) :f(ff) {}
+  ostream * f;
+   operator long () const {return f->precision();}
+ };
+
+template<class A,class B> B castto(const A & a){ return a;}
+
+/*
+template<class K>
+AnyType ClearReturnpKN(Stack stack, const AnyType & a)
+{
+    KN<K> * m = GetAny<K>(a);
+    Add2StackOfPtr2FreeRC(stack, (K*) (*m) );
+    if(verbosity>1)
+	cout << "AddIncrement:: increment + Add2StackOfPtr2FreeRC " << endl;
+    return new KN<K>(true, *m);
+}*/
+
+template<typename K,typename KK>
+AnyType ClearReturnpKK(Stack stack, const AnyType & a)
+{
+    // a ne faire que pour les variables local au return...
+    //  pour l'instant on copie pour fqire mqrche 
+    // a repense  FH  mqi 2009....
+    KK * m = GetAny<KK * >(a);
+  //   KN<K> *cm=new KN<K>(true, *m); bug quant KN est une variable global
+   // KN<K> *cm=new KN<K>( *m); // on duplique le tableau comme en C++  (dur dur ?????? FH)
+    m->increment();
+    Add2StackOfPtr2FreeRC(stack,m);
+    if(verbosity>400)
+	cout << "ClearReturnpKK:: increment + Add2StackOfPtr2FreeRC nb ref  " <<  -m->next  << endl;
+    return m;
+}
+template<typename K,typename KK,typename KK_>
+AnyType ClearReturnpKK_(Stack stack, const AnyType & a)
+{
+   // il faut faire un copie du tableau 
+    KK_ * m = GetAny<KK_ * >(a);
+    KK *cm=new KK(*m); 
+   
+    Add2StackOfPtr2Free(stack,cm);// detruire la copie 
+    if(verbosity>400)
+	cout << "ClearReturnpKK_:: copie  Add2StackOfPtr2Free "  << endl;
+    return (KK_ *) cm;
+}
+template<typename K,typename KK,typename KK_>
+AnyType ClearReturnKK_(Stack stack, const AnyType & a)
+{
+    // il faut faire un copie du tableau 
+    KK_  m = GetAny<KK_>(a);
+    KK *cm=new KK(m); 
+    
+    Add2StackOfPtr2Free(stack,cm);// detruire la copie 
+    if(verbosity>400)
+	cout << "ClearReturnKK_:: copie  Add2StackOfPtr2Free   "  << endl;
+    return SetAny<KK_>(*cm);
+}
+template<typename K,typename KK_,typename KK>
+AnyType CopieKK_pKK(Stack stack,const AnyType &a) {
+    KK_  m = GetAny<KK_>(a);
+    KK *cm=new KK(m);     
+    if(verbosity>400)
+	cout << "CopieKK_pKK:: copie  Add2StackOfPtr2Free   "<< cm   << endl;
+    Add2StackOfPtr2Free(stack,cm);// detruire la copie 
+return cm;}
+
+
+template<typename KK,typename KK_> 
+AnyType UnRefpKN(Stack,const AnyType &a) {
+    KK_ a_(*PGetAny<KK >(a));
+    return  SetAny<KK_ >(a_);}
+
+template<class A> inline AnyType DestroyKN(Stack,const AnyType &x){
+    KN<A> * a=PGetAny<KN<A> >(x);
+    SHOWVERB(cout << "DESTROY " <<typeid(A).name() << " " << a <<  endl); 
+    for(int i=0;i<a->N(); ++i)
+        (*a)[i].destroy(); 
+    a->destroy(); 
+    return  Nothing;
+}
+
+template<class K>
+void ArrayDCL()
+{
+  //  Dcl_TypeandPtr<KN<K> >(0,0,0,::Destroy<KN<K> >, 0 ,  ::ClearReturnKN<K> );
+ 
+    //Dcl_Type<KN<K> *>(0,::Destroy<KN<K> >,   ::ClearReturnpKK<K,KN<K> > );
+    //Dcl_TypeandPtr<KN_<K> >(0,0,0,0,::ClearReturnKK_<K,KN<K>,KN_<K> >,::ClearReturnpKK_<K,KN<K>,KN_<K> >);
+    Dcl_TypeandPtr_<KN_<K> ,KN<K>*  > (0,0,::InitP<KN<K> >,::Destroy<KN<K> >, ::ClearReturnKK_<K,KN<K>,KN_<K> >,::ClearReturnpKK<K,KN<K> >); // add init 0
+    
+    //  Dcl_Type<KN<Complex> *>(0,::Destroy<KN<Complex> >);
+   // Dcl_Type<KN<K> *>(0,::Destroy<KN<K> >); // Modif 17102005 
+   // attention un exp KN<> * right est un KN<> et non un KN<> *
+
+  //  Dcl_Type<KNM<K> *>(0,::Destroy<KNM<K> > ,::ClearReturnpKK<K,KNM<K> >);
+    Dcl_TypeandPtr_<KNM_<K> ,KNM<K>*  > (0,0,0,::Destroy<KNM<K> >, ::ClearReturnKK_<K,KNM<K>,KNM_<K> >,::ClearReturnpKK<K,KNM<K> >);
+    Dcl_Type<  KN<KNM<K> >* >(0,::DestroyKN<KNM<K> >,::ClearReturnpKK<KNM<K>,KN<KNM<K> > >);
+    Dcl_Type<  KN<KN<K> >* >(0,::DestroyKN<KN<K> >,::ClearReturnpKK<KN<K>,KN<KN<K> > >);
+    
+    Dcl_Type< outProduct_KN_<K>* >();
+    Dcl_Type< Transpose<KN_<K> > > ();
+    Dcl_Type< Transpose< KNM<K> *> >();
+ 
+    Dcl_Type<Add_KN_<K> >();
+    
+    Dcl_Type<DotStar_KN_<K> >();
+    Dcl_Type<DotSlash_KN_<K> >();
+    Dcl_Type<Sub_KN_<K> >();
+    Dcl_Type<Mulc_KN_<K> >();
+    Dcl_Type<Divc_KN_<K> >();
+    Dcl_Type<Mul_KNM_KN_<K> >();
+    Dcl_Type<Add_Mulc_KN_<K> *>();
+    Dcl_Type<if_arth_KN_<K> *>();
+    // for    B(I) and B(I^-1)
+    Dcl_Type<pair<KN_<K>,Inv_KN_long> *>();
+    Dcl_Type<pair<KN_<K>,KN_<long> > *>();
+    
+    map_type[typeid(KN<K> * ).name()]->AddCast(
+    new E_F1_funcT<KN<K>*,KN_<K> >(CopieKK_pKK<K,KN_<K>,KN<K> > )
+	 );
+// add  august 2009 FH  to see full  matrix as a array
+    map_type[typeid(KN_<K>  ).name()]->AddCast(
+						     new E_F1_funcT<KN_<K>,KNM<K>* >(UnRef<KN_<K>,KNM<K> *> ));					     
+						 
+    
+     map_type[typeid(KN_<K> ).name()]->AddCast(
+    //   new E_F1_funcT<KN_<K>,KN_<K>*>(UnRefpKN_<K> ),
+       new E_F1_funcT<KN_<K>,KN<K>*>(UnRefpKN<KN<K>,KN_<K> >  )
+	//  inutil cas KN<K> est right expression de KN<K>* 
+//       new E_F1_funcT<KN_<K>,KN<K> >(Cast<KN_<K>,KN<K> >)
+       
+       ); 
+    map_type[typeid(KNM_<K> ).name()]->AddCast(
+					      new E_F1_funcT<KNM_<K>,KNM<K>*>(UnRefpKN<KNM<K>,KNM_<K> >  )
+					      ); 
+    
+    //   ,new E_F1_funcT<KN_<K>,K>(ValueToKN_<K>),
+    //   new E_F1_funcT<KN_<K>,K*>(PtrToKN_<K>)       
+/*       
+     // Ajoute FH   
+     map_type[typeid(KN<K> ).name()]->AddCast(
+       new E_F1_funcT<KN<K>,KN<K>*>(UnRef<KN<K> >)
+    //   ,new E_F1_funcT<KN_<K>,K>(ValueToKN_<K>),
+    //   new E_F1_funcT<KN_<K>,K*>(PtrToKN_<K>)       
+       ); */
+    map_type_of_map[make_pair(atype<long>(),atype<K>())]=atype<KN<K>*>(); // vector
+    map_pair_of_type[make_pair(atype<long>(),atype<long>())] =atype<pair<long,long> >();   
+    map_type_of_map[make_pair(atype<pair<long,long> >(),atype<K>())]=atype<KNM<K>*>(); // matrix 
+    map_type_of_map[make_pair(atype<long>(),atype<KN_<K> >())]=atype<KN<KN<K> >*>();// tableau de tableau
+    map_type_of_map[make_pair(atype<long>(),atype<KNM_<K> >())]=atype<KN<KNM<K> >*>();// tableau de matrix 
+
+}
+
+
+
+template<class A,class B> pair<A,B> * pBuild(const A & a,const B & b)
+  { return new pair<A,B>(a,b);}
+
+// add mars 2006
+template<class K,class L,class OP>
+struct set_A_BI: public binary_function<KN_<K>,pair<KN_<K>, KN_<L> > *,KN_<K> > {
+  static KN_<K> f(const KN_<K>   & a, pair<KN_<K>, KN_<L> > * const & b)  {
+    KN_<K> x(a);
+    OP op;
+     const KN_<K> & y(b->first);
+    const KN_<L> & I(b->second);
+    L  N = x.N();
+    L n = y.N();
+    
+    L maxI=I(SubArray(N)).max() ;
+    L minI=I(SubArray(N)).min() ;
+    
+    if( maxI >= n || I.N()  < N) 
+       { cerr << " Out of Bound x=y(I)  :  0 <= " << minI << " < "<< maxI << "< " << n  << endl;
+         cerr << " or I.N() " << I.N() << " > " << N << endl;
+         ExecError("Out of Bound error");
+       }
+       
+    for(int i=0;i<N;i++)
+      if(I[i]>=0) 
+      op(x(i),y(I[i]));
+    delete b;
+    return a;
+  
+  }
+};  
+
+template<class K,class L,class OP>
+struct set_AI_B: public binary_function<pair<KN_<K>, KN_<L> > * ,KN_<K>, NothingType > {
+  static NothingType  f( pair<KN_<K>, KN_<L> > * const & b,const KN_<K>   & a)  {
+    KN_<K> x(a);
+    OP op;
+     const KN_<K> & y(b->first);
+    const KN_<L> & I(b->second);
+    L  N = I.N();
+    L n = y.N();
+    
+    L maxI=I(SubArray(N)).max() ;
+    L minI=I(SubArray(N)).min() ;
+    
+    if(  maxI >= n || x.N()  < N ) 
+       { cerr << " Out of Bound x(I)=y  :  0 <= " << minI << " < "<< maxI << "< " << n  << endl;
+         cerr << " or x.N() " << I.N() << " > " << N << endl;
+         ExecError("Out of Bound error");
+       }
+       
+    for(int i=0;i<N;i++)
+      if(I[i] >=0) 
+      op(y(I[i]),x[i]);
+    delete b;   
+    return  NothingType();
+  
+  }
+};  
+
+template<class K> 
+struct Op3_paac: public ternary_function<KN_<K>,KN_<K>,K,if_arth_KN_<K>*> { 
+static if_arth_KN_<K>* f(Stack s,const KN_<K> & a,const KN_<K> & b,const  K & c )  {
+    //K cc(c);
+    KN_<K> kc(new(NewAllocTmp(s,sizeof(c))) K(c),1,0);
+  return new if_arth_KN_<K>(a,b,kc);}
+};   
+template<class K> 
+struct Op3_paca: public ternary_function<KN_<K>,K,KN_<K>,if_arth_KN_<K>*> { 
+    static if_arth_KN_<K>* f(Stack s,const KN_<K> & a,const  K & b,const KN_<K> & c )  {
+	//K bb(b);
+	KN_<K> kb(new(NewAllocTmp(s,sizeof(b))) K(b),1,0);
+    return new if_arth_KN_<K>(a,kb,c);}
+};   
+
+template<class K> 
+struct Op3_pacc: public ternary_function<KN_<K>,K,K,if_arth_KN_<K>*> { 
+    static if_arth_KN_<K>* f(Stack s,const KN_<K> & a,const K & b,const  K & c )  {
+	K cc(c),bb(b);
+	KN_<K> kc(new(NewAllocTmp(s,sizeof(c))) K(c),1,0),
+	       kb(new(NewAllocTmp(s,sizeof(b))) K(b),1,0);    
+    return new if_arth_KN_<K>(a,kb,kc);}
+};   
+
+template<class K>
+struct SetArray2: public binary_function<K,K,SetArray<K> > { 
+  static SetArray<K> f(const K & a,const K & b)  { 
+    // cout << "SubArray: " << a << " " << b << endl;
+    //     SetArray(long nn,R oo=R(),R sstep=R(1)): o(oo),n(nn),step(sstep) {}
+    long  n= long(abs((b-a)));
+    ffassert(n);
+    K s= (b-a)/K(n);
+    n++;
+    if(verbosity>100)
+      cout << "    SetArray " << n << " " << a << " " << s << endl;
+    return SetArray<K>(n,a,s);} }; 
+
+template<class K>
+struct SetArray3: public ternary_function<K,K,K,SetArray<K> > { 
+  static SetArray<K> f(Stack s,const K & a,const K &b,const K & c)  {  
+    // cout << "SubArray: " << a << " " << b << " " <<  c << endl;
+    long n= long(1+abs((c-a)/b));
+    if(verbosity>100)
+      cout << "    SetArray " << n << " :  "  << " " << a << " " << b << " " << c << endl;	
+    return SetArray<K>(n,a,b);} }; 
+
+template<class R,class A>  R * set_init_array( R* const & a,const A & b){ 
+    SHOWVERB( cout << " set_init " << typeid(R).name() << " " << &b << endl);
+    a->init(b.size());
+    *a=b;
+return a;}
+template<class R,class A>  R * set_array( R* const & a,const A & b){ 
+    SHOWVERB( cout << " set_init " << typeid(R).name() << " " << &b << endl);
+    a->resize(b.size());
+    *a=b;
+return a;}
+// missing FH august 2009 
+template<class R,class A>  R * set_arrayp( R* const & a,const A & b){ 
+    SHOWVERB( cout << " set_init " << typeid(R).name() << " " << &b << endl);
+    a->resize(b->size());
+    *a=*b;
+return a;}
+template<class R,class A>  R  set_array_( R const & a,const A & b){ 
+    SHOWVERB( cout << " set_array_ " << typeid(R).name() << " " << &b << endl);
+    ffassert(a.N()==b.size());
+    R aa=a;
+    aa=b;
+return a;}
+// xxxxxxxxxxx
+template<class K>  KNM<K> * set_initmat_t(KNM<K> * a,Transpose<KNM<K> * > b ){ 
+    ConjKNM_<K>  tb=b.t->t(); ;
+     a->init(tb.N(),tb.M());
+    *a=tb;
+    return a;}
+template<class K>  KNM<K> * set_initmat(KNM<K> * a,KNM<K> *  b ){ 
+    
+    a->init(b->N(),b->M());
+    *a=*b;
+    return a;}
+template<class K>  KNM<K> * set_mat_t(KNM<K> * a,Transpose<KNM<K> * > b ){ 
+    ConjKNM_<K>  tb=b.t->t(); ;
+    a->resize(tb.N(),tb.M());// correction mars 2013 
+    *a=tb;
+    return a;}
+template<class K>  KNM<K> * addto_mat_t(KNM<K> * a,Transpose<KNM<K> * > b ){ 
+    ConjKNM_<K>  tb=b.t->t(); ;
+    *a+=tb;
+    return a;}
+template<class K>  KNM<K> * subto_mat_t(KNM<K> * a,Transpose<KNM<K> * > b ){ 
+    ConjKNM_<K>  tb=b.t->t(); ;
+    *a-=tb;
+    return a;}
+template<class K>  KNM<K> * set_mat(KNM<K> * a,KNM<K> *  b ){ 
+    
+    a->resize(b->N(),b->M());
+    *a=*b;
+    return a;}
+
+template<class K>  
+class  OneOperator_2KN_ : public OneOperator {public:
+    class Op : public E_F0 {
+       public:
+	int N;
+	Expression *tab;
+	
+	Op( const  E_Array &bb) : N(bb.size()), tab(new Expression[N])
+	{
+	  for(int i=0;i<N;++i)	
+	    tab[i]=atype<K>()->CastTo( bb[i]);
+	}
+	AnyType operator()(Stack s)  const { 
+	    K * p = Add2StackOfPtr2FreeA<K>(s,new K[N]); //   mark to be delete .. 
+	    KN<K> A(N, p);
+	    for(int i=0;i<N;++i)
+		A[i]= GetAny<K>( (*tab[i])(s));
+	    return SetAny<KN_<K> >(A);}
+    };
+    E_F0 * code(const basicAC_F0 & a) const 
+    {  const  E_Array * b = dynamic_cast<const E_Array *>(a[0].LeftValue());
+	ffassert(b);
+        return new Op(*b);} 
+    OneOperator_2KN_<K>(): OneOperator(atype<KN_<K> >(),atype<E_Array>()) { pref=-1;}
+};
+
+extern aType aaaa_knlp;
+template<class K,class Z>
+void ArrayOperator()
+{
+    //  juin 2009  remove type KN_< > *
+    // and set  KN<> * 9left expression) qnd KN_<> is the associated expression..
+    // =>  lot of change because  KN<>* and KN_< > can generqte ambuguity.
+    // so remove all to code with KN<>* type. 
+    // the remove cqde are in comment :
+    //  the comment begin //- 
+    // and the if(0) in comment /* */ 
+    
+    
+     Dcl_Type< Resize<KN<K> > > ();
+     Dcl_Type< Resize<KNM<K> > > ();
+     aType knrp = atype<KN<K> *>();
+     aType knr_ = atype<KN_<K> >();
+   //-  typedef KN<Z> ZN;
+      
+    // add  dec 2009.  ne marche pas ( incompatible  avec MatrixBlock) a comprendre ????? FH. 
+    //  //   xxxxxxxxxx  2010 feb.   retest .. FH 
+    //   il y a plusieurs problems
+    //    1)   [1,2,3.] ->  tableau de quel type  int, real , complex ????
+    //
+     //   map_type[typeid(KN_<K>).name()]->AddCast(new OneOperator_2KN_<K>);
+    // fin add 
+    // ----
+     aType knlp=  aaaa_knlp ;
+     
+     atype<KN<K>* >()->Add("[","",new OneOperator2_<K*,KN<K>*,Z >(get_elementp_<K,KN<K>*,Z>));
+     atype<KN<K>* >()->Add("(","",new OneOperator2_<K*,KN<K>*,Z >(get_elementp_<K,KN<K>*,Z>));
+     atype<KN_<K> >()->Add("(","",new OneOperator2_<KN_<K>,KN_<K>,char >(fSubArrayc<KN_<K> >));
+     atype<KN_<K> >()->Add("(","",new OneOperator2_<KN_<K>,KN_<K>,SubArray>(fSubArray<K> ));
+     atype<KN<K>*>()->Add("(","",new OneOperator2_<KN_<K>,KN<K>*,SubArray>(fSubArrayp<K> ));
+     atype<KN<K>* >()->Add("(","",new OneOperator2_<KN<K>*,KN<K>*,char >(fSubArrayc<KN<K>* >));
+// 
+    
+     atype<KNM_<K> >()->Add("(","",new OneOperator3_<KNM_<K>,KNM_<K>,SubArray,SubArray>(fSubArraybb<K> ));
+     atype<KNM<K>* >()->Add("(","",new OneOperator3_<KNM_<K>,KNM<K>*,SubArray,SubArray>(fSubArraypbb<K> ));
+    /*
+     atype<KN_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM_<K>,SubArray,long>(fSubArraybi<K> ));
+     atype<KN_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM_<K>,long,SubArray>(fSubArrayib<K> ));
+     atype<KN_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM<K>*,SubArray,long>(fSubArraypbi<K> ));
+     atype<KN_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM<K>*,long,SubArray>(fSubArraypib<K> ));
+     */
+//
+    
+    atype<KN_<K> >()->Add("[","",new OneOperator2_<K*,KN_<K>,Z >(get_element_<K,KN_<K>,Z>));
+    atype<KN_<K> >()->Add("(","",new OneOperator2_<K*,KN_<K>,Z >(get_element_<K,KN_<K>,Z>));
+    
+    
+     atype<KNM<K>* >()->Add("(","",new OneOperator3_<KN_<K>,KNM<K>*,Z,SubArray >(get_element_is<KN_<K>,KNM<K>*,Z,SubArray>));
+     atype<KNM<K>* >()->Add("(","",new OneOperator3_<KN_<K>,KNM<K>*,SubArray,Z >(get_element_si<KN_<K>,KNM<K>*,SubArray,Z>));
+     atype<KNM<K>* >()->Add("(","",new OneOperator3_<KN_<K>,KNM<K>*,Z,char >(get_element_lineorcol<KN_<K>,KNM<K>*,Z,char>));
+     atype<KNM<K>* >()->Add("(","",new OneOperator3_<KN_<K>,KNM<K>*,char,Z >(get_element_lineorcol<KN_<K>,KNM<K>*,char,Z>));
+     atype<KNM<K>* >()->Add("(","",new OneOperator3_<K*,KNM<K>*,Z,Z >(get_elementp2_<K,KNM<K>*,Z,Z>));
+
+    atype<KNM_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM_<K>,Z,SubArray >(get_element_is_<KN_<K>,KNM_<K>,Z,SubArray>));
+    atype<KNM_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM_<K>,SubArray,Z >(get_element_si_<KN_<K>,KNM_<K>,SubArray,Z>));
+    atype<KNM_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM_<K>,Z,char >(get_element_lineorcol_<KN_<K>,KNM_<K>,Z,char>));
+    atype<KNM_<K> >()->Add("(","",new OneOperator3_<KN_<K>,KNM_<K>,char,Z >(get_element_lineorcol_<KN_<K>,KNM_<K>,char,Z>));
+    atype<KNM_<K> >()->Add("(","",new OneOperator3_<K*,KNM_<K>,Z,Z >(get_elementp2__<K,KNM_<K>,Z,Z>));
+    
+    
+     Add<KN<K> *>("sum",".",new OneOperator1<K,KN<K> *>(get_sum));
+     Add<KN<K> *>("min",".",new OneOperator1<K,KN<K> *>(get_min));
+     Add<KN<K> *>("max",".",new OneOperator1<K,KN<K> *>(get_max));
+
+     Add<KN<K> *>("l2",".",new OneOperator1<double,KN<K> *>(get_l2));
+     Add<KN<K> *>("l1",".",new OneOperator1<double,KN<K> *>(get_l1));
+     Add<KN<K> *>("linfty",".",new OneOperator1<double,KN<K> *>(get_linfty));
+// add july 2009 
+    Add<KNM<K> *>("sum",".",new OneOperator1<K,KNM<K> *>(get_sum));
+    Add<KNM<K> *>("min",".",new OneOperator1<K,KNM<K> *>(get_min));
+    Add<KNM<K> *>("max",".",new OneOperator1<K,KNM<K> *>(get_max));
+    Add<KNM<K> *>("l2",".",new OneOperator1<double,KNM<K> *>(get_l2));
+    Add<KNM<K> *>("l1",".",new OneOperator1<double,KNM<K> *>(get_l1));
+    Add<KNM<K> *>("linfty",".",new OneOperator1<double,KNM<K> *>(get_linfty));
+// end add     
+     
+     Add<KN_<K> >("sum",".",new OneOperator1_<K,KN_<K> >(get_sum0<K,KN_<K> >));
+     Add<KN_<K> >("min",".",new OneOperator1_<K,KN_<K> >(get_min0<K,KN_<K> >));
+     Add<KN_<K> >("max",".",new OneOperator1_<K,KN_<K> >(get_max0<K,KN_<K> >));
+     Add<KN_<K> >("l2",".",new OneOperator1_<double,KN_<K> >(get_l2_0<double,KN_<K> >));
+     Add<KN_<K> >("l1",".",new OneOperator1_<double,KN_<K> >(get_l1_0<double,KN_<K> >));
+     Add<KN_<K> >("linfty",".",new OneOperator1_<double,KN_<K> >(get_linfty_0<double,KN_<K> >));
+    
+// add july 2009    
+    Add<KNM_<K> >("sum",".",new OneOperator1_<K,KNM_<K> >(get_sum0<K,KNM_<K> >));
+    Add<KNM_<K> >("min",".",new OneOperator1_<K,KNM_<K> >(get_min0<K,KNM_<K> >));
+    Add<KNM_<K> >("max",".",new OneOperator1_<K,KNM_<K> >(get_max0<K,KNM_<K> >));
+    Add<KNM_<K> >("l2",".",new OneOperator1_<double,KNM_<K> >(get_l2_0<double,KNM_<K> >));
+    Add<KNM_<K> >("l1",".",new OneOperator1_<double,KNM_<K> >(get_l1_0<double,KNM_<K> >));
+    Add<KNM_<K> >("linfty",".",new OneOperator1_<double,KNM_<K> >(get_linfty_0<double,KNM_<K> >));
+// end add     
+    
+    
+/*    
+     Add<KN<K> >("sum",".",   new OneOperator1_<K,KN<K> >(get_sum0<K,KN<K> >));
+     Add<KN<K> >("min",".",   new OneOperator1_<K,KN<K> >(get_min0<K,KN<K> >));
+     Add<KN<K> >("max",".",   new OneOperator1_<K,KN<K> >(get_max0<K,KN<K> >));
+     Add<KN<K> >("l2",".",    new OneOperator1_<double,KN<K> >(get_l2_0<double,KN<K> >));
+     Add<KN<K> >("l1",".",    new OneOperator1_<double,KN<K> >(get_l1_0<double,KN<K> >));
+     Add<KN<K> >("linfty",".",new OneOperator1_<double,KN<K> >(get_linfty_0<double,KN<K> >));
+*/     
+
+     Add<KN<K> *>("resize",".",new OneOperator1< Resize<KN<K> >,KN<K> *>(to_Resize));
+     Add<KNM<K> *>("resize",".",new OneOperator1< Resize<KNM<K> >,KNM<K> *>(to_Resize));
+     
+     Add<Resize<KN<K> > >("(","",new OneOperator2_<KN<K> *,Resize<KN<K> > , Z   >(resize1));
+     Add<Resize<KNM<K> > >("(","",new OneOperator3_<KNM<K> *,Resize<KNM<K> > , Z, Z  >(resize2));
+
+    
+     TheOperators->Add("<-", 
+       new OneOperator2_<KN<K> *,KN<K> *,Z>(&set_init),
+       new InitArrayfromArray<K,true>
+    //   new OneOperator2_<KN<K> *,KN<K> *,KN<K> >(&set_init),
+    //   new OneOperator2_<KN<K> *,KN<K> *,KN_<K> >(&set_init)		????       
+     //  new OneOperator2_<KN<K> *,KN<K> *,KN<K> * >(&set_initp)
+       );
+    TheOperators->Add("<-", 
+                      new OneOperator2_<KN< KN<K> > *,KN< KN<K> > * ,Z  >(&set_init));
+    TheOperators->Add("<-", 
+                      new OneOperator2_<KN< KNM<K> > *,KN< KNM<K> > * ,Z  >(&set_init));
+    
+     TheOperators->Add("<-", 
+        new OneOperator3_<KNM<K> *,KNM<K> *,Z,Z>(&set_init2),
+        new InitMatfromAArray<K,true>
+       );
+       
+     Add<KN<K> *>("<-","(",new OneOperator2_<KN<K> *,KN<K> *,Z>(&set_init));
+   //  Add<KN<K> *>("<-","(",new OneOperator2_<KN<K> *,KN<K> *,KN<K> >(&set_init));
+     //Add<KN<K> *>("<-","(",new OneOperator2_<KN<K> *,KN<K> *,KN_<K> >(&set_init));
+    // Add<KN<K> *>("<-","(",new OneOperator2_<KN<K> *,KN<K> *,KN<K> * >(&set_initp));
+     Add<KNM<K> *>("<-","(",new OneOperator3_<KNM<K> *,KNM<K> *,Z,Z>(&set_init2));
+     TheOperators->Add("<-",new OneOperator2<KNM<K> *,KNM<K> *,Transpose<KNM<K> * > >(&set_initmat_t));// may 2011 FH..
+    TheOperators->Add("=",new OneOperator2<KNM<K> *,KNM<K> *,Transpose<KNM<K> * > >(&set_mat_t));// may 2011 FH..
+    TheOperators->Add("+=",new OneOperator2<KNM<K> *,KNM<K> *,Transpose<KNM<K> * > >(&addto_mat_t));// oct 2011 FH..
+    TheOperators->Add("-=",new OneOperator2<KNM<K> *,KNM<K> *,Transpose<KNM<K> * > >(&subto_mat_t));// oct 2011 FH..
+//     TheOperators->Add("-=",new OneOperator2<KNM<K> *,KNM<K> *,Transpose<KNM<K> * > >(&subto_mat_t<-1>));// oct 2011 FH..
+   //  Add<KNM<K> *>("<-","(",new OneOperator2<KNM<K> *,KNM<K> *,KNM<K> *  >(&set_initmat));// may 2011 FH..
+   //  Add<KNM<K> *>("=","(",new OneOperator2<KNM<K> *,KNM<K> *,Transpose<KNM<K> * > >(&set_mat_t));// may 2011 FH..
+  //   Add<KNM<K> *>("=","(",new OneOperator2<KNM<K> *,KNM<K> *,KNM<K> *  >(&set_mat));// may 2011 FH..
+
+    // Add<KNM<K> *>("=","(",new OneOperator2_<KNM<K> *,KNM<K> *,Transpose<KNM<K> * > >(&set_tt));
+    
+     Add<KN<K> *>("<-","(",new InitArrayfromArray<K,true>);
+     Add<KNM<K> *>("<-","(",new InitMatfromAArray<K,true>);
+     Add<KN<K> *>("n",".",new OneOperator1<Z,KN<K> *>(get_n));
+     Add<KNM<K> *>("n",".",new OneOperator1<Z,KNM<K> *>(get_n));
+     Add<KNM<K> *>("m",".",new OneOperator1<Z,KNM<K> *>(get_m));
+ //ajout ars 2012 FH    
+     Add<KN<KN<K> > *>("n",".",new OneOperator1<long,KN<KN<K> > *>(get_n));     
+     Add<KN<KNM<K> > *>("n",".",new OneOperator1<long,KN<KNM<K> > *>(get_n));  
+     atype<KN<KN<K> > * >()->Add("[","",new OneOperator2_<KN<K>*,KN<KN<K> >*,Z >(get_elementp_<KN<K>,KN<KN<K> >*,Z>));
+    atype<KN<KNM<K> > * >()->Add("[","",new OneOperator2_<KNM<K>*,KN<KNM<K> >*,Z >(get_elementp_<KNM<K>,KN<KNM<K> >*,Z>));
+    Dcl_Type< Resize<KN<KN<K> > > > ();
+    Dcl_Type< Resize<KN<KNM<K> > > >();
+    Add<KN<KN<K> > * >("resize",".",new OneOperator1< Resize<KN<KN<K> > >,KN<KN<K> > *>(to_Resize));
+    Add<KN<KNM<K> > * >("resize",".",new OneOperator1< Resize<KN<KNM<K> > >,KN<KNM<K> > *>(to_Resize));
+    Add<Resize<KN<KN<K> > > >("(","",new OneOperator2_<KN<KN<K> >  *,Resize<KN<KN<K> > > , long   >(resize1));
+    Add<Resize<KN<KNM<K> > > >("(","",new OneOperator2_<KN<KNM<K> >  *,Resize<KN<KNM<K> > > , long   >(resize1));
+    
+    
+//     AddOpeqarray<set_eqarray,KN,K>("=");
+
+     TheOperators->Add("=", new InitArrayfromArray<K,false>
+       );
+     TheOperators->Add("=", new InitMatfromAArray<K,false>
+       );
+     TheOperators->Add("=", new SetArrayofKNfromKN<K>
+       );
+ if(0) //  a  change il faut regle un PB ambiguite ...  
+     TheOperators->Add("=",
+        new OneBinaryOperator<set_eqarray<KN<K> ,K > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,DotStar_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,DotSlash_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,Divc_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray<KN<K> ,KN_<K> > > , // Add FH juin 2005         
+        new OneBinaryOperator<set_eqarraypd<KN<K> ,Add_Mulc_KN_<K>* > > , // Add FH aug 2005     
+        new OneBinaryOperator<set_eqarraypd<KN<K> ,if_arth_KN_<K>* > > 
+      //  new OneBinaryOperator<set_eqarrayp<KN<K> ,KN<K>* > >   // test aug 2009    
+      );
+  // add august 2007 
+    
+     TheOperators->Add("<-",
+		      // new OneBinaryOperator<set_eqarray<KN<K> ,K > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,Add_KN_<K> > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,DotStar_KN_<K> > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,DotSlash_KN_<K> > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,Sub_KN_<K> > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,Mulc_KN_<K> > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,Divc_KN_<K> > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,Mul_KNM_KN_<K> > > ,
+		       new OneBinaryOperator<init_eqarray<KN<K> ,KN_<K> > > , // Add FH juin 2005         
+		       new OneBinaryOperator<init_eqarraypd<KN<K> ,Add_Mulc_KN_<K>* > > , // Add FH aug 2005     
+		       new OneBinaryOperator<init_eqarraypd<KN<K> ,if_arth_KN_<K>* > > 
+		      // new OneBinaryOperator<init_eqarrayp<KN<K> ,KN<K>* > >       
+		       );
+
+    
+     TheOperators->Add("=",
+        new OneBinaryOperator<set_eqarray<KNM<K>  ,K > > ,
+         new OneBinaryOperator<set_eqarrayp<KNM<K>  , KNM<K> *  > > 
+        
+       );
+  
+     TheOperators->Add("=",
+        new OneBinaryOperator<set_eq_array<KN_<K> ,K > > ,
+        new OneBinaryOperator<set_eq_array<KN_<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array<KN_<K> ,DotStar_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array<KN_<K> ,DotSlash_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array<KN_<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array<KN_<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array<KN_<K> ,Divc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array<KN_<K> ,Mul_KNM_KN_<K> > > ,
+	new OneBinaryOperator<set_eq_arraypd<KN_<K> ,if_arth_KN_<K>* > > ,
+        new OneBinaryOperator<set_eq_arraypd<KN_<K> ,Add_Mulc_KN_<K>* > >  , // Add FH aug 2005    
+	new OneBinaryOperator<set_eq_array<KN_<K> ,KN_<K> > >, // add FH juin 2005		       
+        new OneBinaryOperator<set_eq_arraypd<KN_<K> ,KN<K>* > >
+		       
+      //-  new OneBinaryOperator<set_eq_arrayp<KN_<K> ,KN<K>* > >       
+      );
+//  ajoute mars 2010  FH    
+    TheOperators->Add("<-",
+		      new OneBinaryOperator<init_eqarray<KNM<K> ,KNM_<K> > >        
+		      );
+    
+    TheOperators->Add("=",
+		      new OneBinaryOperator<set_eqarray<KNM<K>  ,KNM_<K> > > 
+
+		    //  new OneBinaryOperator<set_eq_array<KNM_<K> ,K > > ,
+		    //  new OneBinaryOperator<set_eq_array<KNM_<K> ,KNM_<K> > >, 		       
+		    //  new OneBinaryOperator<set_eq_arraypd<KNM_<K> ,KNM<K>* > >
+		      );
+ 
+//  end add ...     
+/*if(0)
+     TheOperators->Add("+=",
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,K > > ,
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,DotStar_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,DotSlash_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarraypd_add<KN<K> ,Add_Mulc_KN_<K>* > > ,
+        new OneBinaryOperator<set_eqarraypd_add<KN<K> ,if_arth_KN_<K>* > > ,
+        new OneBinaryOperator<set_eqarray_add<KN<K> ,KN_<K> > > , // Add FH juin 2005         
+        new OneBinaryOperator<set_eqarrayp_add<KN<K> ,KN<K>* > >  
+              
+      );
+*/    
+     TheOperators->Add("+=",
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,K > > ,
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,DotStar_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,DotSlash_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,Divc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_add<KN_<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_arraypd_add<KN_<K> ,Add_Mulc_KN_<K>* > > ,
+        new OneBinaryOperator<set_eq_arraypd_add<KN_<K> ,if_arth_KN_<K>* > > ,
+	new OneBinaryOperator<set_eq_array_add<KN_<K> ,KN_<K> > >  // add FH juin 2005
+		       
+       // new OneBinaryOperator<set_eq_arrayp_add<KN_<K> ,KN<K>* > >        
+      );
+/*    if(0)  
+     TheOperators->Add("-=",
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,K > > ,
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,DotStar_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,DotSlash_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarraypd_sub<KN<K> ,Add_Mulc_KN_<K>* > > ,
+        new OneBinaryOperator<set_eqarraypd_sub<KN<K> ,if_arth_KN_<K>* > > ,
+        new OneBinaryOperator<set_eqarray_sub<KN<K> ,KN_<K> > > , // Add FH juin 2005                 
+        new OneBinaryOperator<set_eqarrayp_sub<KN<K> ,KN<K>* > >        
+      );*/
+    
+     TheOperators->Add("-=",
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,K > > ,
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,DotStar_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,DotSlash_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,Divc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_sub<KN_<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_arraypd_sub<KN_<K> ,Add_Mulc_KN_<K>* > > ,
+        new OneBinaryOperator<set_eq_arraypd_sub<KN_<K> ,if_arth_KN_<K>* > > ,
+       //- new OneBinaryOperator<set_eq_arrayp_sub<KN_<K> ,KN<K>* > >        
+	new OneBinaryOperator<set_eq_array_sub<KN_<K> ,KN_<K> > >   // Add FH juin 2005        
+      );
+      
+/*    if(0)
+    TheOperators->Add("*=",
+        new OneBinaryOperator<set_eqarray_mul<KN<K> ,K > >  ,
+        new OneBinaryOperator<set_eqarray_mul<KN<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_mul<KN<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_mul<KN<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_mul<KN<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarraypd_mul<KN<K> ,Add_Mulc_KN_<K>* > > ,
+        new OneBinaryOperator<set_eqarrayp_mul<KN<K> ,KN<K>* > >       
+      );*/
+ 
+      TheOperators->Add("*=",
+                        new OneBinaryOperator<set_eq_array_mul<KN_<K> ,K > >  );
+     TheOperators->Add(".*=",
+        new OneBinaryOperator<set_eq_array_mul<KN_<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_mul<KN_<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_mul<KN_<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_mul<KN_<K> ,Divc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_mul<KN_<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_arraypd_mul<KN_<K> ,Add_Mulc_KN_<K>* > > ,
+       //- new OneBinaryOperator<set_eq_arrayp_mul<KN_<K> ,KN<K>* > >       
+	new OneBinaryOperator<set_eq_array_mul<KN_<K> ,KN_<K> > >       
+      );
+// FH correction  01 nov 2005 FH  copy paste mistake eq_ exchange  ok  v2.0-3 
+/*    if(0)
+     TheOperators->Add("/=",
+        new OneBinaryOperator<set_eqarray_div<KN<K> ,K > > ,
+        new OneBinaryOperator<set_eqarray_div<KN<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_div<KN<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_div<KN<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarray_div<KN<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eqarraypd_div<KN<K> ,Add_Mulc_KN_<K>* > > ,
+        new OneBinaryOperator<set_eqarray_div<KN<K> ,KN_<K> > >        
+     );*/
+
+     TheOperators->Add("/=",
+                       new OneBinaryOperator<set_eq_array_div<KN_<K> ,K > > );
+    TheOperators->Add("./=",
+        new OneBinaryOperator<set_eq_array_div<KN_<K> ,Add_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_div<KN_<K> ,Sub_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_div<KN_<K> ,Mulc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_div<KN_<K> ,Divc_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_array_div<KN_<K> ,Mul_KNM_KN_<K> > > ,
+        new OneBinaryOperator<set_eq_arraypd_div<KN_<K> ,Add_Mulc_KN_<K>* > > ,
+        new OneBinaryOperator<set_eq_array_div<KN_<K> ,KN_<K> > >        
+     );
+// end correction 
+     TheOperators->Add("+",
+       new OneBinaryOperator<Op2_add0<Add_KN_<K>,KN_<K>,KN_<K> > >,
+     //-  new OneBinaryOperator<Op2_add0<Add_KN_<K>,KN_<K>,KN_<K> > >(knrp,knrp),
+       new OneBinaryOperator<Op2_add__n<Add_Mulc_KN_<K>,Mulc_KN_<K>,Mulc_KN_<K> > >,
+       new OneBinaryOperator<Op2_add__n<Add_Mulc_KN_<K>,KN_<K>,Mulc_KN_<K> > >,
+       new OneBinaryOperator<Op2_add__n<Add_Mulc_KN_<K>,Mulc_KN_<K> ,KN_<K> > >
+       );
+
+     TheOperators->Add("-",
+       new OneBinaryOperator<Op2_sub0<Sub_KN_<K>,KN_<K> ,KN_<K> > >,
+     //-  new OneBinaryOperator<Op2_sub0<Sub_KN_<K>,KN_<K> ,KN_<K> > >(knrp,knrp),
+       new OneUnaryOperator<Op1_sub<Mulc_KN_<K>,KN_<K> > >,
+       new OneBinaryOperator<Op2_sub__n<Add_Mulc_KN_<K>,Mulc_KN_<K>,Mulc_KN_<K> > >,
+       new OneBinaryOperator<Op2_sub__n<Add_Mulc_KN_<K>,KN_<K>,Mulc_KN_<K> > >,
+       new OneBinaryOperator<Op2_sub__n<Add_Mulc_KN_<K>,Mulc_KN_<K> ,KN_<K> > >
+       );
+    
+     TheOperators->Add("*",
+     //-  new OneBinaryOperator<Op2_mulpc<Mulc_KN_<K>,KN<K>*,K> >,
+     //-  new OneBinaryOperator<Op2_mulcp<Mulc_KN_<K>,K,KN<K>*> >,
+       new OneBinaryOperator<Op2_mulc<Mulc_KN_<K>,KN_<K>,K> >,
+       new OneBinaryOperator<Op2_mulc<Mulc_KN_<K>,K,KN_<K> > >,
+       new OneBinaryOperator<Op2_mulpcp<Mul_KNM_KN_<K>,KNM<K>*,KN<K>*> >,
+      // new OneBinaryOperator<Op2_mulp<Mul_KNM_KN_<K>,KNM_<K>,KN_<K>> >, // - add #1 mqi 2009 
+      // new OneBinaryOperator<Op2_dotproduct<K> >,
+       new OneBinaryOperator<Op2_dotproduct_<K> > 
+     //-  ,new OneBinaryOperator<Op2_pbuild<outProduct_KN_<K>,KN<K>*,Transpose<KN_<K> > > >
+       ,new OneBinaryOperator<Op2_pbuild<outProduct_KN_<K>,KN_<K>,Transpose<KN_<K> > > > 
+       ,new OneBinaryOperator<Op2_pbuild<outProduct_KN_<K>,Mulc_KN_<K>,Transpose<KN_<K> > > > 
+             
+       );
+
+    TheOperators->Add("/",
+                      new OneBinaryOperator<Op2_divc<Divc_KN_<K>,K,KN_<K> > >,
+                      new OneBinaryOperator<Op2_divc<Mulc_KN_<K>,KN_<K>,K > >
+                      
+                      );
+
+//  nouvel operateur       
+     TheOperators->Add("+=",
+        new OneBinaryOperator<set_eqarraypd_add<KNM<K> ,outProduct_KN_<K>* > > 
+       );
+       
+     TheOperators->Add("-=",
+        new OneBinaryOperator<set_eqarraypd_sub<KNM<K> ,outProduct_KN_<K>* > > 
+       );
+       
+     TheOperators->Add("=",
+        new OneBinaryOperator<set_eqarraypd<KNM<K> ,outProduct_KN_<K>* > > 
+       );
+//   tested ok ...  FH 
+     TheOperators->Add("?:",
+       new OneTernaryOperator3<Op3_p<if_arth_KN_<K>, KN_<K> > > ,
+       new OneTernaryOperator3<Op3_paac<K > > ,      
+       new OneTernaryOperator3<Op3_pacc<K > > ,      
+       new OneTernaryOperator3<Op3_paca<K > >   
+
+       );
+// end ...
+
+// add mars 2006 
+// atype<KN_<K> >()->Add("(","",new OneOperator2_< pair<KN_<K>,KN_<long> > * ,KN_<K>  , KN_<long>  >(pBuild< KN_<K>   , KN_<long>  >));
+ atype<KN_<K> >()->Add("(","",new OneOperator2_< pair<KN_<K>,KN_<long> > * ,KN_<K>  , KN_<long>  >(pBuild< KN_<K>   , KN_<long>  >,atype<KN_<K>  >(), atype<KN_<long> >() ));
+ atype<KN<K> *>()->Add("(","",new OneOperator2_< pair<KN_<K>,KN_<long> > * ,KN_<K>  , KN_<long>  >(pBuild< KN_<K>   , KN_<long>  >,atype<KN<K> * >(), atype<KN_<long> >() ));
+ //atype<KN_<K> >()->Add("(","",new OneOperator2_< pair<KN_<K>,KN_<long> > * ,KN_<K>  , KN_<long>  >(pBuild< KN_<K>   , KN_<long>  >,atype<KN_<K>  >(), knlp ));
+ //atype<KN<K> *>()->Add("(","",new OneOperator2_< pair<KN_<K>,KN_<long> > * ,KN_<K>  , KN_<long>  >(pBuild< KN_<K>   , KN_<long>  >,atype<KN<K> * >(), knlp ));
+ 
+ TheOperators->Add("=",
+        new OneBinaryOperator<set_A_BI< K,Z,affectation<K>  > > ,
+        new OneBinaryOperator<set_AI_B< K,Z,affectation<K>  > > 
+ );
+ TheOperators->Add("+=",
+        new OneBinaryOperator<set_A_BI< K,Z,affectation_add<K>  > > ,
+        new OneBinaryOperator<set_AI_B< K,Z,affectation_add<K>  > > 
+ );
+ TheOperators->Add("-=",
+        new OneBinaryOperator<set_A_BI< K,Z,affectation_sub<K>  > > ,
+        new OneBinaryOperator<set_AI_B< K,Z,affectation_sub<K>  > > 
+ );
+// fin 
+  TheOperators->Add("\'",       
+      // new OneOperator1<Transpose<KN_<K> >,KN<K> *>(&Build<Transpose<KN_<K> >,KN<K> *>),
+       new OneOperator1<Transpose<KN_<K> >,KN_<K> >(&Build<Transpose<KN_<K> >,KN_<K> >),
+       new OneOperator1<Transpose<KNM<K> * >, KNM<K> * >(&Build<Transpose<KNM<K> * >,KNM<K> * >)            
+  );
+       
+     TheOperators->Add(".*",
+       new OneBinaryOperator<Op2_build<DotStar_KN_<K>,KN_<K>,KN_<K> > > //-,
+     //-  new OneBinaryOperator<Op2_build<DotStar_KN_<K>,KN_<K>,KN_<K> > >(knrp,knrp),
+     //-  new OneBinaryOperator<Op2_build<DotStar_KN_<K>,KN_<K>,KN_<K> > >(knr_,knrp),
+      //- new OneBinaryOperator<Op2_build<DotStar_KN_<K>,KN_<K>,KN_<K> > >(knrp,knr_)
+       
+      );
+
+      
+     TheOperators->Add("./",
+       new OneBinaryOperator<Op2_build<DotSlash_KN_<K>,KN_<K>,KN_<K> > > //-,
+     //- new OneBinaryOperator<Op2_build<DotSlash_KN_<K>,KN_<K>,KN_<K> > >(knrp,knrp),
+     //-  new OneBinaryOperator<Op2_build<DotSlash_KN_<K>,KN_<K>,KN_<K> > >(knr_,knrp),
+     //-  new OneBinaryOperator<Op2_build<DotSlash_KN_<K>,KN_<K>,KN_<K> > >(knrp,knr_)
+      );
+      
+     TheOperators->Add("<<",
+    //   new OneBinaryOperator<PrintPnd<KN<K>*> >,
+       new OneBinaryOperator<Print<KNM_<K> > >,
+       new OneBinaryOperator<Print<KN_<K> > >
+       ); 
+    TheOperators->Add("<<",
+                      new OneBinaryOperator< PrintPnd< KN< KNM<K> >* > >,
+                      new OneBinaryOperator< PrintPnd< KN< KN<K> >* > >
+                      ); 
+    
+       
+     TheOperators->Add(">>",
+        new OneBinaryOperator<Op_ReadKN<K> >
+      );            
+
+     map_type[typeid(MyMap<String,K>*).name()] = new ForEachType<MyMap<String,K>*>(Initialize<MyMap<String,K> >,Delete<MyMap<String,K> >) ;
+         
+     map_type_of_map[make_pair(atype<string*>(),atype<K>())]=atype<MyMap<String,K>*>(); 
+     
+     atype<MyMap<String,K>*>()->Add("[","",new OneOperator2_<K*,MyMap<String,K>*,string*>(get_element<K>));
+    
+    // Add Mai 2009
+    Dcl_Type<SetArray<K> >();
+    TheOperators->Add("::",
+		    
+		      new OneBinaryOperator<SetArray2<K> >,
+		      new OneTernaryOperator3<SetArray3<K> >);
+    TheOperators->Add("<-", 
+		      new OneOperator2_<KN<K> *,KN<K> *,SetArray<K> >(&set_init_array));
+ 
+    TheOperators->Add("=", 
+		      new OneOperator2_<KN<K> *,KN<K> *,SetArray<K> >(&set_array),
+		      new OneOperator2_<KN<K> *,KN<K> *,KN<K> * >(&set_arrayp),  //  to reomve ambiguity aug 2009
+		      new OneOperator2_<KN_<K> ,KN_<K> ,SetArray<K> >(-1,&set_array_) // missing aug 2009 a(:)=1:3 less prioritaire
+    );
+    
+
+}
+
+template<class R,class A,class B=A,class BB=B>
+class  OneOperator1F_KN_ : public OneOperator {
+    aType r; //  return type
+    typedef  A (*func)( B ) ; 
+    func  f;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new Op(f,t[0]->CastTo(args[0]));} 
+    OneOperator1F_KN_(func  ff): 
+      OneOperator(map_type[typeid(R).name()],map_type[typeid(BB).name()]),f(ff){}
+
+ class Op :public  E_F0 { public:
+  typedef  A (*func)(B ) ; 
+  func f;
+  Expression a;
+  Op(func ff,Expression aa) : f(ff),a(aa) {}
+  AnyType operator()(Stack s)  const  {return SetAny<R>( R(f, GetAny<BB>( (*a)(s)) ) );}  
+   bool EvaluableWithOutStack() const 
+      {return a->EvaluableWithOutStack() ;} // 
+   bool MeshIndependent() const 
+      {return a->MeshIndependent();} // 
+    
+};      
+      
+};
+template<class K,class KK>
+void ArrayOperatorF()
+{
+     Dcl_Type<F_KN_<K,K,KK> >();
+
+
+     Global.Add("exp","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(exp));
+     Global.Add("log","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(log));
+     Global.Add("log10","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(log10));
+     Global.Add("sqrt","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(sqrt));
+     Global.Add("sin","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(sin));
+     Global.Add("cos","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(cos));
+     Global.Add("tan","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(tan));
+     Global.Add("cosh","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(cosh));
+     Global.Add("sinh","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(sinh));
+     Global.Add("tanh","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(tanh));
+    // Global.Add("acos","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(acos));
+    // Global.Add("asin","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(asin));
+    // Global.Add("atan","(",new OneOperator1F_KN_<F_KN_<K,K,KK>,K,KK,KN_<K> >(atan));
+
+     TheOperators->Add("=",new OneBinaryOperator<set_eq_array<KN_<K> ,F_KN_<K,K,KK> > > ); // add FH juin 2005
+     TheOperators->Add("+=",new OneBinaryOperator<set_eq_array_add<KN_<K> ,F_KN_<K,K,KK> > > ); // add FH juin 2005
+     TheOperators->Add("-=",new OneBinaryOperator<set_eq_array_sub<KN_<K> ,F_KN_<K,K,KK> > > ); // add FH juin 2005
+     TheOperators->Add("/=",new OneBinaryOperator<set_eq_array_div<KN_<K> ,F_KN_<K,K,KK> > > ); // add FH juin 2005
+     TheOperators->Add("*=",new OneBinaryOperator<set_eq_array_mul<KN_<K> ,F_KN_<K,K,KK> > > ); // add FH juin 2005
+  
+}
diff --git a/src/fflib/endian.hpp b/src/fflib/endian.hpp
new file mode 100644
index 0000000..cbfcb3d
--- /dev/null
+++ b/src/fflib/endian.hpp
@@ -0,0 +1,144 @@
+#ifndef ENDIAN_HPP__
+#define  ENDIAN_HPP__
+//  --------------------------------------------
+//  read and write without endianess problem.
+//  the choise is little endian , such than the 
+//  the order of the bytes is the same order of
+//  a shift operator <<  in a integer.   
+//  F. Hecht.
+//  --------------------------------------------
+template<int L>
+inline void w_endian(const unsigned char * c,unsigned char * k)
+{cerr<< " L = "<< L  << endl; assert(0); }
+template<int L>
+inline void r_endian(const unsigned char *c,unsigned char * k)
+{assert(0); }
+
+template<>
+inline  void w_endian<1>(const unsigned char *c,unsigned char* k)
+{*k=*c;}
+
+template<>
+inline  void w_endian<8>(const unsigned char *c,unsigned char* k)
+{
+  static  const unsigned long long  ull =( 0ULL + (1ULL << 8) + (2ULL << 16) + (3ULL << 24)
+					   + (4ULL << 32) + (5ULL << 40) + (6ULL << 48 ) + (7ULL << 56 ));
+  static  const unsigned char *o = reinterpret_cast<const unsigned char *>(&ull);
+  //  cout << " ++++ " << ull << " .. "   ;
+  // for(int i=0;i<8;++i) cout <<(int) o[i] ;
+  assert(8==sizeof(ull));
+  k[o[0]]=c[0];
+  k[o[1]]=c[1];
+  k[o[2]]=c[2];
+  k[o[3]]=c[3];  
+  k[o[4]]=c[4];
+  k[o[5]]=c[5];
+  k[o[6]]=c[6];
+  k[o[7]]=c[7];  
+  // cout << " ---  " ;
+  //  for (int i=0;i<8;++i) 
+  //  cout << k[i] ;
+  // cout << k << endl;
+}
+
+/*
+template<class T> std::ostream &dump(std::ostream & f, const T &t)
+{
+  const unsigned char *o = reinterpret_cast<const unsigned char *>(&t);
+  //  f << " " << t <<  " " << & t << " == " << (void *) o << " -> ";
+  for( int i=0;i< sizeof(t); ++i)
+    f  << (unsigned int) o[i] ;
+  return f;
+}
+*/
+
+template<>
+inline  void w_endian<4>(const unsigned char *c,unsigned char * k)
+{
+  static  const unsigned int u0123 = 0U + (1U << 8) + (2U << 16) + (3U << 24);
+  static  const unsigned char *o = reinterpret_cast<const unsigned char *>(&u0123);
+  //   ordre   c[o^-1] :   si o:   0123 -> 2130  
+  //   si  c == 1U + (2U << 8) + (3U << 16) + (4U << 24);   
+  //   alors  k[0] = 1, k[1]=2, k[2] = 3, k[3]=4 
+  //  ------------------
+  assert(4==sizeof(u0123));
+  k[o[0]]=c[0];
+  k[o[1]]=c[1];
+  k[o[2]]=c[2];
+  k[o[3]]=c[3];  
+}
+
+template<>
+inline  void w_endian<2>(const unsigned char *c,unsigned char *k)
+{
+  static  const unsigned short int  u01 = 0U + (1U << 8);
+  static  const unsigned char *o = reinterpret_cast<const unsigned char *>(&u01);
+  assert(2==sizeof(u01));
+  k[o[0]]=c[0];
+  k[o[1]]=c[1];
+}
+
+template<>
+inline  void r_endian<1>(const unsigned char *c,unsigned char *k)
+{  *k=*c; }
+
+template<>
+inline  void r_endian<8>(const unsigned char *c,unsigned char *k)
+{
+  static  const unsigned long long  ull =( 0ULL + (1ULL << 8) + (2ULL << 16) + (3ULL << 24)
+					   + (4ULL << 32) + (5ULL << 40) + (6ULL << 48 ) + (7ULL << 56 ));
+  static  const unsigned char *o = reinterpret_cast<const unsigned char *>(&ull);
+  assert(8==sizeof(ull));
+  
+  k[0]=c[o[0]];
+  k[1]=c[o[1]];
+  k[2]=c[o[2]];
+  k[3]=c[o[3]];  
+  k[4]=c[o[4]];
+  k[5]=c[o[5]];
+  k[6]=c[o[6]];
+  k[7]=c[o[7]];  
+  
+}
+
+
+template<>
+inline  void r_endian<4>(const unsigned char c[4],unsigned char k[4])
+{
+  static  const unsigned int u0123 = 0U + (1U << 8) + (2U << 16) + (3U << 24);
+  static  const unsigned char *o = reinterpret_cast<const unsigned char *>(&u0123);
+  assert(4==sizeof(u0123));
+  
+  k[0]=c[o[0]];
+  k[1]=c[o[1]];
+  k[2]=c[o[2]];
+  k[3]=c[o[3]];  
+}
+
+template<>
+inline  void r_endian<2>(const unsigned char c[2],unsigned char k[2])
+{
+  static  const unsigned short u01 = 0U + (1U << 8) ;
+  static  const unsigned char *o = reinterpret_cast<const unsigned char *>(&u01);
+  assert(2==sizeof(u01));
+  k[0]=c[o[0]];
+  k[1]=c[o[1]];
+}
+
+
+template<class T>
+inline  T r_endian(const T & t )
+{
+  T r;
+  r_endian<sizeof(t)>(reinterpret_cast<const unsigned char *>(&t),reinterpret_cast<unsigned char *>(&r));
+  return r;
+}
+
+template<class T>
+inline  T w_endian(const T & t )
+{
+  T r;
+  w_endian<sizeof(t)>(reinterpret_cast<const unsigned char *>(&t),reinterpret_cast<unsigned char *>(&r));
+  return r;
+}
+#endif
diff --git a/src/fflib/environment.cpp b/src/fflib/environment.cpp
new file mode 100644
index 0000000..4bc04f3
--- /dev/null
+++ b/src/fflib/environment.cpp
@@ -0,0 +1,407 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+ 
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "environment.hpp"
+#include "iostream"
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstring>
+#include <algorithm>
+
+// set in getprog-unix.hpp in Graphic dir..
+const char *  prognamearg=0;
+extern  void (*initparallele)(int &, char **&); // to know if mpiversion ... 
+
+#ifdef PURE_WIN32
+#include <windows.h>
+#endif
+
+
+#ifdef HAVE_GETENV
+#include <stdlib.h>
+#endif
+using namespace std;
+bool load(string s);
+
+const char SLACH='/';
+const char BACKSLACH='\\';
+#ifdef PURE_WIN32
+ const  char dirsep=BACKSLACH, dirnsep=SLACH;
+#else
+ const  char dirnsep=BACKSLACH, dirsep=SLACH;
+#endif
+
+string DirName(const char * f)
+{
+  const char *c= strrchr(f,dirsep);
+  if(!c) return string("");
+  else return string(f,strlen(f)-strlen(c));
+}
+string TransDir(string dir)
+{
+  for (size_t i=0; i<dir.size(); ++i)
+    if(dir[i]==dirnsep) dir[i]=dirsep;
+  if(dir.size()>1 && dir[dir.size()-1] != dirsep) 
+    dir += dirsep;
+  return  dir;    
+}
+
+
+
+template<typename T> 
+void  show(const char * s,const T & l,const char * separateur="\n")
+{
+  cout << s << * separateur;
+  for (typename T::const_iterator i=l.begin(); i != l.end(); i++)
+    cout  << * i << * separateur;
+  //cout << endl; 
+}
+
+
+
+
+
+bool  EnvironmentFind(string key,string item)
+ {
+   EnvironmentData::iterator ekey=ffenvironment.find(key);
+   if( ekey != ffenvironment.end()) 
+    {
+     OneEnvironmentData * pl= &ekey->second;
+     OneEnvironmentData::iterator i=find(pl->begin(),pl->end(),item);
+       return i != pl->end();
+     }
+    
+   return false;
+ }
+
+
+bool  EnvironmentClean(string key)
+{
+   EnvironmentData::iterator ekey=ffenvironment.find(key);
+   if( ekey != ffenvironment.end()) 
+    {
+      OneEnvironmentData * pl= &ekey->second;
+      pl->clear();
+      return true;
+     }
+    
+   return false;
+ }
+ 
+bool EnvironmentInsert(string key,string item,string before)
+{
+   bool ret=true;
+   OneEnvironmentData  & l = ffenvironment[key];
+   char  sufmpi[] = {'m','p','i',dirsep,'\0'};
+   string suf= ((key== "loadpath") && initparallele ) ? sufmpi  : ""; 
+   if( ! suf.empty() )
+     if((item.find("mpi") == string::npos ) && (item.find("MPI") == string::npos ) && item != "."  && item != "./" && item !="") 
+       {
+	 if(verbosity>=100)  cout << " EnvironmentInsert: Add suf " << suf << " to " << item << " in GetEnvironment "<< key << endl; 
+	 item  += suf;
+       }
+   
+   OneEnvironmentData::iterator i=find(l.begin(),l.end(),item);
+   
+   if(i!=l.end()) {ret=false; l.erase(i);} // if existe remove
+   i=find(l.begin(),l.end(),before);
+   if(verbosity>=100) cout << " insert " << key << " " << item << " " << before << endl;
+   if(i == l.end() && before!="$")
+       l.insert(l.begin(),item); // insert in front 
+   else
+       l.insert(i,item); // insert before i
+    
+  return ret;  
+}
+
+int GetEnvironment(const string & key, string items)
+{
+  if(verbosity>=100)  cout << key << " -> " << items <<  endl;
+  bool path=key.find("path")!= string::npos;
+  int d=0, k=0;
+  if(path)
+    items+=";;";
+  for (size_t  i=0;i<items.size();i++)
+   if(  items[i]==';')
+    { 
+
+      string item =items.substr(d,i-d);
+      if(path) item=TransDir(item);
+      if(verbosity>=100) cout << " + " << item << endl;
+      if(!EnvironmentFind(key,item)) 
+	{
+	  EnvironmentInsert(key,item,"$");
+	  k++; 
+	}
+      d=i+1;          
+    }
+    
+ return k;   
+}
+int  readinitfile(const string & file)
+{
+	string line="";
+	string key;
+	string value;
+	bool add=false;
+	ifstream f(file.c_str());
+	if( ! f) {
+		if(verbosity>=20) cout << "error opening init  file: " << file << endl;
+		return 0;}
+	
+	char c,c1,bv=0;
+	int linenumber = 1;
+	bool inkey=false,invalue=false,cmm=false;
+	while (f)
+	{
+		c= f.get();
+		c1=f.peek();
+		//cout << c ;
+		//      if(bv)
+		//cerr << bv ;
+		//else cerr << '.';
+		if(c == EOF)
+		  break;
+		if(c =='\n' || c=='\r' )
+		  {
+		    linenumber++;
+		    line="";
+		    cmm = false;
+		  }
+		else 
+		  line+= c;
+		if(c=='#') cmm=true;
+		if(!cmm)
+                {
+		  if(invalue) // get value  key [=|+= value ]
+		    { 
+		      if (bv) //  store the value
+			{	  
+			  if (! (c == bv || ( bv==' ' && isspace(c)) ) )
+			    {
+			      value+= c; // add to value
+			    }
+			  else  // end of value
+			    {
+			      bv =0; invalue=0; // fin de la value 
+			      if(verbosity >= 50) 
+				cout <<file <<":" << key << " = " << value <<endl;
+			      if(key=="verbosity")
+				verbosity=atoi(value.c_str());
+			      else 
+				{
+				  if( !add) 
+				    {EnvironmentClean(key);   
+				    GetEnvironment(key,value);}
+				  else 
+				    {
+				      bool path=key.find("path")!= string::npos;
+				      if(path)
+					EnvironmentInsert(key,TransDir(value),"$");		      
+				      else 
+					EnvironmentInsert(key,value,"$");		      
+				    }
+				  
+				}
+
+			      key="";
+			      value="";
+			    }
+			}
+		      else // find begin of value
+			{ 
+			  if(c=='\'' || c == '"' ) {bv = c;value="";}
+			  else if (! isspace(c)) {value=c;bv=' ';}
+			  
+			}
+		    }
+		  else if( inkey) 
+		    {
+		      if ( isalnum(c) ) key += c;
+		      else if ( c == '=') 
+			{ 
+			  inkey=false;
+			  invalue=true;
+			  add=false;
+			}
+		      else if ( c == '+' && c1=='=') 
+			{
+			  inkey=false;
+			  invalue=true;
+			  add=true;
+			  c1=f.get();
+			}
+		      else if (! isspace(c) ) 
+			break;      
+		    }
+		  else if(isalpha(c) ) 
+		    { inkey=1; key= c;}
+                }
+	}
+	if( inkey || invalue || bv )
+	  {
+	    cout << " error read init file : " << file << " " <<  linenumber << endl;
+	    cout << " line : " << line << endl;	    
+	    return -11;
+	  }
+	return 1;
+}
+
+
+void GetEnvironment()
+ {
+ char  * ff_verbosity=0,* ff_loadpath=0,* ff_incpath=0,* home=0;
+
+ // FFCS: we must make sure that FFCS does not reuse the same freefem++.pref as FF because some shared libraries must be
+ // recompiled.
+
+#ifdef ENABLE_FFCS
+ string  ffpref="freefem++-cs.pref";
+#else
+  string  ffpref="freefem++.pref";
+#endif
+
+#ifdef HAVE_GETENV
+  ff_verbosity = getenv("FF_VERBOSITY");
+  ff_loadpath = getenv("FF_LOADPATH");
+  ff_incpath = getenv("FF_INCLUDEPATH");
+  home    = getenv("HOME");
+#endif
+
+#ifdef PURE_WIN32 
+ 
+  const int LEN = 4096;
+  char envv[LEN];
+  char envl[LEN];
+  char envi[LEN];
+  char envh[LEN];
+  
+
+  if (GetEnvironmentVariable("FF_VERBOSITY", envv, LEN) > 0) 
+   ff_verbosity=envv;
+   
+  if (GetEnvironmentVariable("FF_LOADPATH", envl, LEN) > 0) 
+   ff_loadpath=envl;
+   
+  if (GetEnvironmentVariable("FF_INCLUDEPATH", envi, LEN) > 0) 
+   ff_incpath=envi;
+  
+  if (GetEnvironmentVariable("HOMEPATH", envh, LEN) > 0) 
+    home=envh;
+#endif 
+  if ( ff_verbosity ) { 
+    verbosity = atoi(ff_verbosity);
+  }
+
+#ifdef PURE_WIN32 
+#else
+  EnvironmentInsert("init-files","/etc/"+ffpref,"$");
+#ifdef FF_PREFIX_DIR_APPLE
+  EnvironmentInsert("init-files",string(FF_PREFIX_DIR_APPLE) + "/etc/" + ffpref ,"$");
+#endif
+#ifdef FF_PREFIX_DIR
+  EnvironmentInsert("init-files",string(FF_PREFIX_DIR) + "/etc/" + ffpref  ,"$");
+#endif
+
+  if(prognamearg)
+    {
+    if( strchr(prognamearg,dirsep) )
+      {
+	EnvironmentInsert("init-files",TransDir(DirName(prognamearg))+"/../etc/"+ffpref,"$");
+      }
+    }
+#endif
+
+  if(home) 
+	EnvironmentInsert("init-files",TransDir(home)+"."+ffpref,"$");
+
+  EnvironmentInsert("init-files",ffpref,"$");
+	
+  { 
+    OneEnvironmentData  & l = ffenvironment["init-files"];
+    OneEnvironmentData::iterator i=l.begin();	
+    while( i != l.end())
+      {
+	if(verbosity>2) cout << " try initfile : " <<*i << endl; 
+	readinitfile(*i++);	   
+      }
+  }
+  
+  
+  
+  if ( ff_verbosity ) { 
+    verbosity = atoi(ff_verbosity);
+  }
+  if(ff_loadpath)
+    GetEnvironment("loadpath",ff_loadpath);
+  if(ff_incpath)
+    GetEnvironment("includepath",ff_incpath);
+
+   EnvironmentInsert("includepath","","");//    always add "" the first include path  
+  if( verbosity >2) 
+    {
+      EnvironmentData::iterator loadpath=ffenvironment.find("loadpath");
+      EnvironmentData::iterator inc=ffenvironment.find("includepath");    
+      if(  loadpath != ffenvironment.end()) {
+	show("\nload path : ",loadpath->second, "\n \t ");
+	cout <<"(.)"<<endl;
+      }
+      if(  inc != ffenvironment.end()) {
+	show("\ninclude path : ",inc->second, "\n \t ");
+	cout <<"(.)"<<endl;}
+    }
+  if ( ff_verbosity ) { 
+    verbosity = atoi(ff_verbosity);
+    if(verbosity>2) cout << " --  verbosity is set to " << verbosity << endl;
+  }
+  
+ }
+void EnvironmentLoad()
+{
+    EnvironmentData::iterator toload=ffenvironment.find("load");
+    if(  toload != ffenvironment.end()) 
+	
+	for (OneEnvironmentData::iterator i=toload->second.begin(); i != toload->second.end(); ++i)
+	{
+	    if(verbosity) cout << "PreEnv load :"<< *i << endl;
+	    load(*i);
+	}
+	    
+}
+
+ 
+#ifdef TESTMAIN
+long verbosity=50;
+ EnvironmentData  environment;
+int main()
+{
+  GetEnvironment();
+  return 0; 
+}
+
+#endif
diff --git a/src/fflib/environment.hpp b/src/fflib/environment.hpp
new file mode 100644
index 0000000..4f4e1b8
--- /dev/null
+++ b/src/fflib/environment.hpp
@@ -0,0 +1,41 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "config-wrapper.h"
+#include <string>
+#include <list>
+#include <map>
+typedef std::list<std::string>  OneEnvironmentData;
+typedef std::map<std::string,OneEnvironmentData > EnvironmentData;
+
+extern EnvironmentData  ffenvironment;
+extern long verbosity;
+
+bool EnvironmentInsert(std::string key,std::string item,std::string before);
+
+void GetEnvironment();
+void EnvironmentLoad();  
diff --git a/src/fflib/error.hpp b/src/fflib/error.hpp
new file mode 100644
index 0000000..4cbf545
--- /dev/null
+++ b/src/fflib/error.hpp
@@ -0,0 +1,135 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef ERROR_H
+#define ERROR_H
+#include <cassert>
+#include <string>
+#include "throwassert.hpp"
+#include <exception>
+
+extern int TheCurrentLine; 
+
+#if defined(__GNUC__) && __GNUC__+0 < 3
+#include <strstream.h>
+ typedef  istrstream istringstream   ;
+ typedef  ostrstream ostringstream   ;
+#define ENDS << '\0'
+#define OLDCPP 1 
+#else
+// car ostringstream n'est pas encore defin sous g++
+//  
+#include <sstream>
+#define ENDS 
+
+#endif
+
+  using std::exception;
+
+extern long mpirank;
+
+class Error : public exception
+{ public:
+  enum CODE_ERROR { NONE, COMPILE_ERROR,EXEC_ERROR, MEM_ERROR,MESH_ERROR,ASSERT_ERROR,INTERNAL_ERROR, UNKNOWN };
+  
+  
+private: 
+  std::string  message;
+  const CODE_ERROR code;
+protected:
+  Error(CODE_ERROR c,const char * t1,const char * t2,const char * t3=0,
+	int n=0,const char * t4=0,const char * t5=0,const char * t6=0,
+	const char * t7=0,const char * t8=0,const char * t9=0)     
+    : message(),code(c)
+  {
+    using namespace std;
+    ostringstream mess;
+    if(t1)  mess << t1;
+    if(t2)  mess << t2;
+    if(t3)  mess << t3 << n ;
+    if(t4)  mess << t4;
+    if(t5)  mess << t5;
+    if(t6)  mess << t6;
+    if(t7)  mess << t7;
+    if(t8)  mess << t8;
+    if(t9)  mess << t9;
+    message = mess.str();
+    extern void ShowDebugStack();
+    ShowDebugStack();
+    if (c!=NONE && mpirank==0) cerr  << message << endl; // cerr << " at exec line  " << TheCurrentLine << endl; 
+    }
+public:
+  virtual int errcode() const {return code;} 
+  virtual const char *  what() const   throw () { return message.c_str(); } 
+  virtual  ~Error() throw () {}      
+};
+
+class ErrorCompile : public Error
+{
+ public:
+  ErrorCompile(const char * Text,int l,const char * t2="") : 
+    Error(COMPILE_ERROR,"Compile error : ",Text,"\n\tline number :",l,", ", t2) {}
+};
+
+class ErrorExec : public Error
+{  
+ public:
+  ErrorExec(const char * Text,int l) :
+    Error(UNKNOWN,"Exec error : ",Text, "\n   -- number :", l)  {}
+};
+
+class ErrorInternal : public Error
+{  
+ public:
+  ErrorInternal(const char * Text,int l,const char * t2="") :
+    Error(INTERNAL_ERROR,"Internal error : ",Text, "\n\tline  :",l,", in file ", t2)  {}
+};
+class ErrorAssert : public Error
+{  
+ public:
+  ErrorAssert(const char * Text,const char *file,const int line) :
+    Error(ASSERT_ERROR,"Assertion fail : (",Text, ")\n\tline :", line,", in file ",file)  {}
+};
+
+
+class ErrorMemory : public Error
+{ public:
+  ErrorMemory(const char * Text,int l=0) : 
+    Error(MEM_ERROR,"Memory Error : ",Text," number: ",l)  {}
+};
+
+class ErrorExit : public Error
+{
+  int codeexit;
+public:
+  ErrorExit(const char * ,int l) :
+    Error(NONE,"exit","(","",l,")"), codeexit(l)   {}
+    // the exit code fo freefem++ is given by l 
+  int errcode() const{return codeexit;}
+};
+
+#endif
diff --git a/src/fflib/ff++.hpp b/src/fflib/ff++.hpp
new file mode 100644
index 0000000..b984436
--- /dev/null
+++ b/src/fflib/ff++.hpp
@@ -0,0 +1,47 @@
+#ifndef FF___HPP_
+#define FF___HPP_
+// a not to bad list of freefem++ include 
+// to simplify like of programmer.
+// FH. 
+#include <fstream>
+#include <iostream>
+#include <cfloat>
+#include <cmath>
+#include <cstring>
+#include <complex>
+#include<stdlib.h>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "ufunction.hpp"
+using namespace std;  
+#include "rgraph.hpp"
+#include "RNM.hpp"
+// after RNM   otherwise 
+// trouble with index in RNM (I do no understander FH)
+#include <set>
+#include <vector>
+#include <map>
+
+#include "fem.hpp"
+
+
+#include "FESpacen.hpp" 
+#include "FESpace.hpp" 
+
+#include "MatriceCreuse_tpl.hpp"
+#include "MeshPoint.hpp"
+#include "Mesh2dn.hpp"
+#include "Mesh3dn.hpp"
+#include "Operator.hpp" 
+#include "lex.hpp"
+#include "libmesh5.h"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+
+#include "Mesh2.h"
+#include "BamgFreeFem.hpp"
+#include "ffapi.hpp" 
+#endif
diff --git a/src/fflib/ffapi.cpp b/src/fflib/ffapi.cpp
new file mode 100755
index 0000000..da6bcbb
--- /dev/null
+++ b/src/fflib/ffapi.cpp
@@ -0,0 +1,312 @@
+#ifdef WITH_PETSC
+#include <petsc.h>
+#endif
+
+/// \file
+/// ======================================================================
+/// Written by Antoine Le Hyaric
+/// Laboratoire Jacques-Louis Lions
+/// Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+/// http://www.ljll.math.upmc.fr/lehyaric
+/// ======================================================================
+/// This file is part of Freefem++
+/// 
+/// Freefem++ is free software; you can redistribute it and/or modify
+/// it under the terms of the GNU Lesser General Public License as
+/// published by the Free Software Foundation; either version 2.1 of
+/// the License, or (at your option) any later version.
+/// 
+/// Freefem++  is distributed in the hope that it will be useful,
+/// but WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+/// GNU Lesser General Public License for more details.
+/// 
+/// You should have received a copy of the GNU Lesser General Public
+/// License along with Freefem++; if not, write to the Free Software
+/// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+/// 02110-1301 USA
+/// ======================================================================
+/// headeralh cpp freefem start=21/01/10 upmc
+
+// Proposed FreeFem++ Application Programming Interface
+// ----------------------------------------------------
+
+// headerfilter
+#include "ffapi.hpp"
+#ifdef FFLANG
+#include "socket.hpp"
+#include "spawn.hpp"
+#include "buffer.hpp"
+#endif
+#include <iostream>
+#include <cstdio>
+#ifndef FFLANG
+#include <cstdio>
+#endif
+#ifdef FFLANG
+#include "options.hpp"
+#include <stdlib.h>
+#endif
+#ifndef FFLANG
+#ifdef WIN32
+#include <fcntl.h>
+#endif
+#endif
+#ifndef FFLANG
+#ifdef PARALLELE
+#include "mpi.h"
+#endif
+#endif
+// Add dec 2014
+#include <vector>
+typedef void (*AtEnd)();
+vector<AtEnd> AtFFEnd;
+void ff_finalize()
+{
+    for (vector<AtEnd>::const_reverse_iterator i=AtFFEnd.rbegin(); i !=AtFFEnd.rend(); ++ i)
+        (**i)();
+    AtFFEnd.clear(); 
+}
+void ff_atend(AtEnd f)
+{
+    AtFFEnd.push_back(f);
+}
+
+// FFCS-specific implementations for the FF API
+// --------------------------------------------
+
+/// FFLANG defined means that FFCS is being compiled. I am fairly confident that FFCS will not be defined while
+/// compiling the original FF.
+
+/// Need to choose a non-zero stream number because FF will check it (as global variable ThePlotStream)
+#define FFAPISTREAM 1
+
+/// if FFCS is around, we need to bufferize all communications to avoid mixing up CMD_FFG and CMD_STDOUT messages
+#ifdef FFLANG
+void bufferwrite(const char *b,const int l){
+  Socket::dialoglock->WAIT(); // need #include "socket.hpp"
+
+  // thank to the buffering, there is only one CMD_FFG tag for multiple visualization data items.
+  onlyffsock()<<CMD_FFG; // need #include "spawn.hpp"
+  onlyffsock()<<l;
+
+  // this call contains the socket MAGIC number
+  onlyffsock().bufferedwrite(static_cast<const char*>(b),l);
+
+  Socket::dialoglock->Free();
+}
+
+Buffer buffer(NULL,bufferwrite); // need #include "buffer.hpp"
+#endif
+
+namespace ffapi{
+
+  // Get a pointer to the local cin/cout (which is distinct from ffcs's stdin/stdout under Windows because each DLL owns
+  // separate cin/cout objects).
+
+  // need #include <iostream>
+  std::istream *cin(){return &std::cin;}
+  std::ostream *cout(){return &std::cout;}
+  std::ostream *cerr(){return &std::cerr;}
+
+  // FFCS - ::stdout not accepted under mingw32
+  // need #include <cstdio>
+  FILE *ffstdout(){return stdout;}
+  FILE *ffstderr(){return stderr;}
+  FILE *ffstdin(){return stdin;}
+
+  void newplot(){}
+
+  FILE *ff_popen(const char *command, const char *type){
+#ifdef FFLANG
+
+    // this happens right at the begining of FF, so the socket
+    // communication must not be started yet (only when actual
+    // visualization data needs to be transfered).
+
+    PROGRESS;
+    return (FILE*)FFAPISTREAM;
+#else
+
+    // need #include <cstdio>
+    return popen(command,type);
+#endif
+  }
+
+  int ff_pclose(FILE *stream){
+#ifdef FFLANG
+    // nothing to close in FFCS
+    return 0;
+#else
+    return pclose(stream);
+#endif
+  }
+
+  size_t fwriteinit(const void *ptr, size_t size, size_t nmemb,FILE *stream){
+
+    // printf() is useful for debug because it is not redirected through
+    // the FFCS socket. But it is asynchronous with cout so it may end up
+    // in the middle of the lines checked by test/compare. So deactivate
+    // it by default.
+#ifdef DEBUG_FFAPI
+#ifdef FFLANG
+    printf("debug: ffapi: using TCP sockets\n");
+#else
+    printf("debug: ffapi: using an anonymous pipe\n");
+#endif // FFLANG
+#endif // DEBUG_FFAPI
+
+#ifdef FFLANG
+
+    // Ask FFCS to analyze the visualization flux header. I could just skip this stage, but it will be useful to check
+    // the coherency between FFCS and FF when FF evolves in the future.
+
+    Socket::dialoglock->WAIT();
+    onlyffsock()<<CMD_FFGINIT;
+    Socket::dialoglock->Free();
+#endif
+    return ff_fwrite(ptr,size,nmemb,stream);
+  }
+
+  size_t ff_fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream){
+#ifdef FFLANG
+
+    // if the ffsock pointer is null here, it means that the pointer exported from the FFCS shared library is not a
+    // valid one (this has been the case with Windows DLLs in the past).
+
+    // we won't make use of the stream, but make sure that the call from
+    // FF is coherent with what we know.
+    assert(stream==(FILE*)FFAPISTREAM);
+
+    buffer.write(static_cast<const char*>(ptr),size*nmemb);
+
+    // stops the server flux at one precise point (point value expressed during a previous crash while reading server
+    // data in the client in visudata.cpp). Use abort() to call the debugger (which can display the call stack and show
+    // where the problematic pipe value came from).
+
+    // need #include "options.hpp"
+    if(options->AbortFFGraphicsDataAt==buffer.getpoint())abort(); // need #include <stdlib.h>
+
+#else
+    fwrite(ptr,size,nmemb,stream);
+#endif
+    return 0;
+  }
+
+  int ff_fflush(FILE *stream){
+#ifdef FFLANG
+    assert(stream==(FILE*)FFAPISTREAM);
+
+    // we need to flush both the buffer and the socket to avoid a separate callback for flush in the buffer
+    buffer.flush();
+
+    // ff_fflush() is used by FF only at the end of a plot, so we can use this location to send a marker for the
+    // sequential java client to deal with one complete plot at a time.
+    Socket::dialoglock->WAIT();
+    onlyffsock()<<CMD_FFGEND;
+    onlyffsock().writeflush();
+    Socket::dialoglock->Free();
+
+#else
+    fflush(stream);
+#endif
+    return 0;
+  }
+
+  int ff_ferror(FILE *stream){
+#ifndef FFLANG
+    return ferror(stream);
+#else
+    return 0;
+#endif
+  }
+
+  int ff_feof(FILE *stream){
+#ifndef FFLANG
+    return feof(stream);
+#else
+    return 0;
+#endif
+  }
+
+  void wintextmode(FILE *f){
+#ifndef FFLANG
+#ifdef WIN32
+    // need #include <fcntl.h>
+    _setmode(fileno(f),O_TEXT);	
+#endif
+#endif
+  }
+
+  void winbinmode(FILE *f){
+#ifndef FFLANG
+#ifdef WIN32
+    _setmode(fileno(f),O_BINARY);	
+#endif
+#endif
+  }
+
+  void mpi_init(int &argc, char** &argv){
+    /// only call MPI_Init() if this has not already been done in ffcs/src/server.cpp
+#ifndef FFLANG
+#ifdef PARALLELE
+    // need #include "mpi.h"
+    int provided;
+    MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
+    if(provided < MPI_THREAD_SERIALIZED) {
+        MPI_Comm_rank(MPI_COMM_WORLD, &provided);
+        if(provided == 0)
+            std::cout << "MPI_THREAD_SERIALIZED not supported !" << std::endl;
+    }
+#ifdef WITH_PETSCxxxxx
+    PetscInitialize(&argc, &argv, 0, "");
+#endif
+
+#endif
+#endif
+  }
+
+  void mpi_finalize(){
+#ifndef FFLANG
+#ifdef PARALLELE
+#ifdef WITH_PETSCxxxxxxxx
+    PetscFinalize();
+#endif
+    MPI_Finalize();
+#endif
+#endif
+  }
+
+  bool protectedservermode(){
+#ifdef FFLANG
+    return !options->LocalClient;
+#else
+    return false;
+#endif
+  }
+
+  void init(){
+    ffapi::fwriteinit;
+    ffapi::winbinmode;
+    ffapi::wintextmode;
+    ffapi::mpi_finalize;
+    ffapi::cin;
+    ffapi::cerr;
+    ffapi::cout;
+    ffapi::ff_feof;
+    ffapi::newplot;
+    ffapi::ff_popen;
+    ffapi::mpi_init;
+    ffapi::ff_ferror;
+    ffapi::ff_fflush;
+    ffapi::ff_fwrite;
+    ffapi::ff_pclose;
+    ffapi::protectedservermode;
+  }
+}
+
+/// Local Variables:
+/// mode:c++
+/// ispell-local-dictionary:"british"
+/// coding:utf-8
+/// End:
diff --git a/src/fflib/ffapi.hpp b/src/fflib/ffapi.hpp
new file mode 100755
index 0000000..26bc4c2
--- /dev/null
+++ b/src/fflib/ffapi.hpp
@@ -0,0 +1,115 @@
+/// \file
+/// ======================================================================
+/// Written by Antoine Le Hyaric
+/// Laboratoire Jacques-Louis Lions
+/// Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+/// http://www.ljll.math.upmc.fr/lehyaric
+/// ======================================================================
+/// This file is part of Freefem++
+/// 
+/// Freefem++ is free software; you can redistribute it and/or modify
+/// it under the terms of the GNU Lesser General Public License as
+/// published by the Free Software Foundation; either version 2.1 of
+/// the License, or (at your option) any later version.
+/// 
+/// Freefem++  is distributed in the hope that it will be useful,
+/// but WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+/// GNU Lesser General Public License for more details.
+/// 
+/// You should have received a copy of the GNU Lesser General Public
+/// License along with Freefem++; if not, write to the Free Software
+/// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+/// 02110-1301 USA
+/// ======================================================================
+/// headeralh cpp freefem start=21/01/10 upmc
+
+// Proposed FreeFem++ Application Programming Interface
+// ----------------------------------------------------
+
+// headerfilter
+#ifndef FFAPI_HPP
+#include <iostream>
+#include <sstream>
+#include <cstdio>
+using namespace std;
+#endif //FFAPI_HPP
+
+#ifndef FFAPI_HPP
+#define FFAPI_HPP
+  void ff_finalize();
+  void ff_atend( void (*atendff)());
+
+namespace ffapi{
+
+  // Redirecting the FF data stream
+  // ------------------------------
+
+  // Getting a pointer to FF stdin and stdout enables extra DLLs to use standard IO even when they are redirected (eg
+  // through FFCS).
+  
+  void init(); 
+  // need #include <iostream>
+  // need #include <sstream>
+  // need using namespace std;
+  std::istream *cin();
+  std::ostream *cout();
+  std::ostream *cerr();
+
+  // <<mingw32_stdout>> Cannot name these functions identically to the original file pointers under MingW32 (compile
+  // error). Impacts [[file:InitFunct.hpp::LOADINITIO]]. Changed from stdxxx_ptr() to ffstdxxx() according to the way FF
+  // itself was changed.
+
+  FILE *ffstdout();
+  FILE *ffstderr();
+  FILE *ffstdin();
+
+  /// Initiate graphical pipe output. I need a separate function for this to warn ffcs to check the corresponding ffglut
+  /// magic number
+
+  size_t fwriteinit(const void *ptr, size_t size, size_t nmemb,FILE *stream);
+
+  /// Indicates the begining of a new plot to avoid sending socket control data with each plot item.
+
+  void newplot();
+
+  /// Redefinition of standard system calls
+
+  FILE *ff_popen(const char *command, const char *type);
+  int ff_pclose(FILE *stream);
+  size_t ff_fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
+  int ff_fflush(FILE *stream);
+  int ff_ferror(FILE *stream);
+  int ff_feof(FILE *stream);
+
+  // Windows file mode
+  // -----------------
+
+  /// Changing file mode needs to be disabled when the file is a TCP socket to FFCS. Since the treatment is different in
+  /// FF and in FFLANG executables, they have to be stored in a DLL that changes between these two programs.
+
+  void wintextmode(FILE *f);
+  void winbinmode(FILE *f);
+
+  // Transfer basic MPI control
+  // --------------------------
+
+  void mpi_init(int &argc, char **& argv);
+  void mpi_finalize();
+
+  // Permanent server control
+  // ------------------------
+
+  /// if true, FF is considered to be accessible from remote anonymous connections and some commands (like shell
+  /// commands) are not allowed.
+
+  bool protectedservermode();
+}
+
+#endif // FFAPI_HPP
+
+/// Local Variables:
+/// mode:c++
+/// ispell-local-dictionary:"british"
+/// coding:utf-8
+/// End:
diff --git a/src/fflib/ffstack.hpp b/src/fflib/ffstack.hpp
new file mode 100644
index 0000000..7894111
--- /dev/null
+++ b/src/fflib/ffstack.hpp
@@ -0,0 +1,384 @@
+/// \file
+
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+//-----------------------------------  
+//  to manage the freefem stack 
+
+#include "throwassert.hpp"
+
+//   in the stack we save all the variable 
+//   a adresse 0 we have the MeshPointStack to defineP,N, ....
+//   a adresse sizeof(void *) 
+// 
+//
+//  Offset in (void *)
+const int MeshPointStackOffset =0;
+const int ParamPtrOffset = 1;
+const int ElemMatPtrOffset = 2;
+const int ExprPtrs = 4;
+const int NbPtrs = 5;
+
+
+
+const int BeginOffset = 6;
+//  0 : MeshPoint pointeur 
+//  1 : ParamPtrOffset
+//  2 : Truc les matrice elementaire
+
+#define NEWFFSTACKxxx
+
+#ifndef NEWFFSTACK
+typedef void StackType;
+
+/// <<Stack>>
+typedef void *Stack;
+
+
+ const Stack  NullStack=0;
+//typedef StackType& Stack;
+inline Stack pvoid2Stack(void * pv) { return pv;}
+
+template<class T>
+T * Stack_offset (Stack stack,size_t offset)  
+{  //cout << "Stack_offset" << stack << " " << offset << endl;
+    return   (T *) (void *) (((char *) stack)+offset);}
+
+template<class T>
+T * & Stack_Ptr (Stack stack,size_t offset)  
+  {return   (T * &)  (((void **) stack)[offset]);}
+
+void ShowType(ostream & f);
+
+
+struct VOIDPtrType {
+  virtual ~VOIDPtrType();
+};
+
+template<class T> 
+struct PtrType: public VOIDPtrType {
+ T * p;
+ PtrType(T* pp):p(pp) {}
+ ~PtrType() {delete p;}
+};
+
+template<class T> 
+struct PtrArrayType: public VOIDPtrType {
+ T * p;
+ PtrArrayType(T* pp):p(pp) {}
+ PtrArrayType() {delete [] p;}
+};
+
+
+#else
+
+struct StackType;
+
+//typedef void *Stack;
+
+/// Stack used by CListOfInst::eval()
+typedef StackType & Stack;
+
+struct StackType {
+ size_t lg;
+ char * stack; 
+ char * MeshPointStack;
+ operator char *() { return stack;}
+ operator void *() { return stack;}
+ operator long *() { return (long *)(void *)stack;}
+ operator void **() {return (void **) (void *) stack;}
+ operator StackType *() { return this;}
+ template<class T> 
+ T * Offset(size_t offset){ return (T*) (void*) (stack+offset);}
+ template<class T> 
+ T *& ptr(size_t offset){ return (T* &) ((void**) (void *) stack)[offset];}
+ StackType(size_t ll) :lg(ll),stack(new char[ll]),MeshPointStack(new char[1000]) 
+  {
+  long * p= ptr<long>(0);
+  long l4=lg/sizeof(long);
+  for (int i = 0;i< l4;i++) p[i]=0;
+
+  ptr<char>(MeshPointStackOffset)=MeshPointStack;
+  }
+ void clean() { delete []stack; delete [] MeshPointStack; }
+};
+
+inline Stack pvoid2Stack(void * pv) { return *static_cast<StackType *>(pv) ;}
+static  StackType * NullStackPtr= 0;
+static StackType & NullStack(*NullStackPtr);
+//typedef StackType& Stack;
+
+
+template<class T>
+T * Stack_offset (Stack stack,size_t offset)  
+  {return   stack.Offset<T>(offset);}
+
+template<class T>
+T * & Stack_Ptr (Stack stack,size_t offset)  
+  {return   (T * &)  (((void **) (void *) stack.stack)[offset]);}
+
+void ShowType(ostream & f);
+
+
+struct VOIDPtrType {
+  virtual ~VOIDPtrType();
+};
+
+template<class T> 
+struct PtrType: public VOIDPtrType {
+ T * p;
+ PtrType(T* pp):p(pp) {}
+ ~PtrType() {delete p;}
+};
+
+template<class T> 
+struct PtrArrayType: public VOIDPtrType {
+ T * p;
+ PtrArrayType(T* pp):p(pp) {}
+ PtrArrayType() {delete [] p;}
+};
+
+
+
+#endif
+//------------------------------------
+ 
+ // Add FH mars 2006 
+ // clean pointeur ceated by the language 
+ // ----
+ struct BaseNewInStack {
+  virtual ~BaseNewInStack() {};
+};
+
+ struct BaseNewInStack ;
+ struct StackOfPtr2Free;
+
+inline StackOfPtr2Free  * & WhereStackOfPtr2Free(Stack s) { return  Stack_Ptr<StackOfPtr2Free>(s,ExprPtrs) ;} // fait  
+
+
+struct StackOfPtr2Free {
+	typedef vector<BaseNewInStack *>::iterator iterator;
+	StackOfPtr2Free  ** where; // where is store the ptr to the stack 
+	StackOfPtr2Free *prev; // previous stack 
+
+	vector<BaseNewInStack *> stackptr;
+         static const int sizeofmemory4tmp=1024;
+        int topmemory4tmp;
+        char *memory4tmp ;  //
+	void add(BaseNewInStack *p) { 
+	   // cout << "\n\t\t ### ptr/lg add  " << p << "  at " << stackptr.size() << "  \n";	   
+	   stackptr.push_back(p);}
+	
+public: 
+	StackOfPtr2Free(Stack s):
+		where(&WhereStackOfPtr2Free(s)),
+		prev(*where),
+		topmemory4tmp(0),  // add FH oct 2008 of tmp allocation clean after each instruction 
+                memory4tmp(new char[sizeofmemory4tmp])  // add FH oct 2008 of tmp allocation  clean after each instruction
+	       { 
+			stackptr.reserve(20); 	
+			if(prev) Add2StackOfPtr2Free(s,this);
+	       }
+	
+	bool clean() 
+	 { bool ret= !stackptr.empty();
+	    if(ret)
+	      { 
+		topmemory4tmp=0;// clean the tmp allocation 
+	        if(stackptr.size()>=20 && verbosity>2) 
+		  // FFCS: nothing on following line for tests/compare
+	           cout << "\n\t\t ### big?? ptr/lg clean " << stackptr.size() << " ptr's\n";
+		
+		for (iterator i=stackptr.end(); i != stackptr.begin();)
+		{
+		   
+			delete  (* (--i) ); 
+		     //cout << "StackOfPtr2Free: clean " << (* (i) ) << endl;
+		}
+		stackptr.resize(0);// clean the
+		
+	     }
+	   return ret;
+	}
+    void * alloc(int lg) 
+       { 
+	int lg8=lg%8; 
+	if(lg8) lg += 8-lg8; 
+	if(topmemory4tmp + lg>= sizeofmemory4tmp) {ffassert(0);}
+	void *   p=static_cast<void*> (memory4tmp+topmemory4tmp);// correct FH Oct 2009
+	topmemory4tmp+= lg;
+	return p;
+	}
+    ~StackOfPtr2Free() {clean();delete [] memory4tmp;  *where=prev;} // restore the previous stack
+private:// no copy ....
+ 	StackOfPtr2Free(const StackOfPtr2Free&);
+	void operator =(const StackOfPtr2Free&);
+
+ template<class T>
+    friend  T * NewTmp(Stack s);
+ template<class T>
+  friend  T * Add2StackOfPtr2Free(Stack s,T * p);
+	
+};	
+
+ 
+inline void * NewAllocTmp(Stack s,size_t l)
+{
+  return WhereStackOfPtr2Free(s)->alloc(l);
+}
+
+template<class T>
+struct NewInStack: public BaseNewInStack   {	
+   T * p;
+   bool array;
+  ~NewInStack() { 
+     // cout << "~NewInStack " << typeid(T).name() << " " << p << "  array " << array << " " << this << "\n";
+      if(p) 
+        delete p;}  
+private: 
+   NewInStack(T * pp,bool aa=false) : p(pp),array(aa) {
+      //  cout << "NewInStack " << typeid(T).name() << " "  << p << "  array " << aa << " " << this << "\n";
+   } 
+   
+   
+ template<class TT> 
+ friend  TT * Add2StackOfPtr2FreeA(Stack s,TT * p);
+ template<class TT> 
+ friend  TT * Add2StackOfPtr2Free(Stack s,TT * p);
+   
+};
+// ajout of 2 class NewRefCountInStack and NewArrayInStack
+//  for clean of meshes 
+
+template<class T>
+struct NewRefCountInStack: public BaseNewInStack   {	
+    T * p;
+    bool array;
+    ~NewRefCountInStack() { 
+	// cout << "~NewInStack " << typeid(T).name() << " " << p << "  array " << array << " " << this << "\n";
+	if(p) p->destroy();}  
+private: 
+    NewRefCountInStack(T * pp,bool aa=false) : p(pp),array(aa) {
+	//  cout << "NewInStack " << typeid(T).name() << " "  << p << "  array " << aa << " " << this << "\n";
+    } 
+    
+    template<class TT> 
+    friend  TT * Add2StackOfPtr2FreeRC(Stack s,TT * p);
+    
+};
+
+template<class T>
+struct NewArrayInStack: public BaseNewInStack   {	
+    T * p;
+    bool array;
+    ~NewArrayInStack() { 
+	// cout << "~NewInStack " << typeid(T).name() << " " << p << "  array " << array << " " << this << "\n";
+	if(p)  delete [] p;
+   }  
+private: 
+    NewArrayInStack(T * pp,bool aa=false) : p(pp),array(aa) {
+	//  cout << "NewInStack " << typeid(T).name() << " "  << p << "  array " << aa << " " << this << "\n";
+    } 
+    
+    
+    template<class TT> 
+    friend  TT * Add2StackOfPtr2FreeA(Stack s,TT * p);
+    template<class TT> 
+    friend  TT * Add2StackOfPtr2Free(Stack s,TT * p);
+    
+};
+
+template<class T>
+T * Add2StackOfPtr2FreeRC(Stack s,T * p)
+{
+    if(p)	
+	WhereStackOfPtr2Free(s)->add(new NewRefCountInStack<T>(p));
+    return p;
+}	
+
+template<class T>
+T * Add2StackOfPtr2Free(Stack s,T * p)
+{
+   if(p)	
+     WhereStackOfPtr2Free(s)->add(new NewInStack<T>(p));
+   return p;
+}	
+template<class T>
+T * Add2StackOfPtr2FreeA(Stack s,T * p)
+{
+   if(p)	
+     WhereStackOfPtr2Free(s)->add(new NewArrayInStack<T>(p));
+   return p;
+}	
+//  fin modif gestion of allocation of Ptr in Language 
+//  ---------------------------------------------------
+#ifndef NEWFFSTACK
+
+/// <<newStack>>
+inline Stack newStack(size_t l)
+ {
+   char *  mps;
+  Stack thestack = new char[l];
+  for (size_t i = 0;i< l/sizeof(long);i++) ((long*) thestack)[i]=0;
+  ((char **) thestack)[MeshPointStackOffset] = mps = new char [1000]; 
+  for(int i=0;i<1000;++i) mps[i]=0;
+  WhereStackOfPtr2Free(thestack)=new StackOfPtr2Free(thestack); 
+  
+  return thestack;
+ // return *new StackType(l);}
+}
+
+inline void deleteStack(Stack s) 
+ {
+    delete  WhereStackOfPtr2Free(s); // add gestion of the Ptr
+    delete [] (((char **)  s)[MeshPointStackOffset]);
+    delete [] (char *) s;
+ // s.clean();
+ }
+#else
+//  a faire ....
+
+/// Called to create a new #Stack used to evaluate a FreeFem++ script in CListOfInst::eval()
+inline Stack newStack(size_t l)
+ {
+/*  Stack thestack = new char[l];
+  for (int i = 0;i< l/sizeof(long);i++) ((long*) thestack)[i]=0;
+  ((char **) thestack)[MeshPointStackOffset] = new char [1000]; 
+  
+  return thestack;*/
+  return *new StackType(l);
+  }
+
+
+inline void deleteStack(Stack s) 
+ {
+   // delete [] (((char **)  s)[MeshPointStackOffset]);
+  //  delete [] (char *) s;
+ s.clean();
+ }  
+#endif  
diff --git a/src/fflib/global.cpp b/src/fflib/global.cpp
new file mode 100644
index 0000000..15b782c
--- /dev/null
+++ b/src/fflib/global.cpp
@@ -0,0 +1,106 @@
+/// \file
+
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "config-wrapper.h"
+
+#include <complex>
+#include "AFunction.hpp"
+#include "error.hpp"
+#include "lex.hpp"
+#include "RNM.hpp"
+#include <queue>
+#include "environment.hpp"
+
+#define  FF_GRAPH_PTR_DCL
+#include "rgraph.hpp"
+//#include "PlotStream.hpp"
+
+ bool  NoGraphicWindow=false;
+
+/// <<verbosity>>
+long verbosity = 1;
+
+ long searchMethod = 0; //pichon
+ FILE *ThePlotStream=0; //  Add for new plot. FH oct 2008
+
+  KN<String> *pkarg;//  for the list of argument  mars 2010 
+ Map_type_of_map map_type_of_map ; //  to store te type 
+Map_type_of_map map_pair_of_type ; //  to store te type 
+
+ basicForEachType *  typevarreal,  * typevarcomplex;  //  type of real and complex variable
+
+/// <<zzzfff>> see [[file:lex.hpp::mylex]]
+mylex *zzzfff;
+bool lexdebug;
+
+/// <<plglval>> see [[file:../lglib/lg.ypp::YYSTYPE]] and [[file:../lglib/lg.ypp::yylval]]
+#include "lg.tab.hpp"
+YYSTYPE *plglval;
+
+ int TheCurrentLine=-1; // unset: by default
+ long mpisize=0,mpirank=0;
+
+ 
+   C_F0 *pOne=0,*pZero=0,*pminusOne=0;
+// const C_F0 & One(*pOne), &Zero(*pZero);
+ 
+ Polymorphic * TheOperators=0, //=new Polymorphic(), 
+             * TheRightOperators=0; //=new Polymorphic();
+
+/// <<Global>> Contains all FreeFem++ language keywords. Declaration in [[file:AFunction.hpp::Global]]
+
+TableOfIdentifier Global;
+
+ long E_Border::Count =0;
+
+/// <<tables_of_identifier>> declared at [[file:AFunction.hpp::tables_of_identifier]]
+typedef list<TableOfIdentifier *> ListOfTOfId;
+ListOfTOfId tables_of_identifier;
+
+const int AC_F0::MaxSize=1024; // maximal number of parameters
+
+
+
+map<const string,basicForEachType *> map_type;
+bool showCPU= false;
+
+
+size_t CodeAlloc::nb=0, CodeAlloc::lg=0,CodeAlloc::nbpx=0,CodeAlloc::chunk=2048; 
+size_t CodeAlloc::nbt,CodeAlloc::nbdl=0;
+CodeAlloc ** CodeAlloc::mem=0;
+size_t CodeAlloc::memoryusage=0; 
+bool CodeAlloc::sort=true;
+bool  CodeAlloc::cleanning=false;
+bool echo_edp=true; // add F.H of remove script dump 
+
+//  add F. Hecht 
+EnvironmentData  ffenvironment;
+
+
diff --git a/src/fflib/glumesh2D.cpp b/src/fflib/glumesh2D.cpp
new file mode 100755
index 0000000..357d17c
--- /dev/null
+++ b/src/fflib/glumesh2D.cpp
@@ -0,0 +1,431 @@
+// $Id$
+
+#include <iostream>
+#include <cfloat>
+#include <cmath>
+#include <complex>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+using namespace std;  
+#include "rgraph.hpp"
+#include "RNM.hpp"
+#include "fem.hpp"
+
+
+#include "FESpacen.hpp" 
+#include "FESpace.hpp" 
+
+#include "MatriceCreuse_tpl.hpp"
+#include "MeshPoint.hpp"
+#include "Operator.hpp" 
+#include "lex.hpp"
+
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+
+#include <set>
+#include <vector>
+#include <fstream>
+
+
+using namespace  Fem2D;
+
+class listMesh { 
+public:
+  list<Mesh *> *lth;
+  void init()  { lth=new list<Mesh *>;}
+  void destroy() { delete lth;}
+  listMesh(Stack s,Mesh *th) : lth(Add2StackOfPtr2Free(s,new list<Mesh*>)) { lth->push_back(th);}
+  listMesh(Stack s,Mesh *tha,Mesh *thb) : lth(Add2StackOfPtr2Free(s,new list<Mesh*>)) { lth->push_back(tha);lth->push_back(thb);}
+  listMesh(Stack s,const listMesh &l,Mesh *th) : lth(Add2StackOfPtr2Free(s,new list<Mesh*>(*l.lth))) { lth->push_back(th);}
+
+};
+
+
+Mesh * GluMesh(listMesh const & lst)
+{
+  int nbt=0;
+  int neb=0;
+  int nebx=0;
+  int nbv=0;
+  int nbvx=0;
+  double hmin=1e100;
+  R2 Pn(1e100,1e100),Px(-1e100,-1e100);
+  const list<Mesh *> lth(*lst.lth);
+   Mesh * th0=0;
+    int kk=0;
+  for(list<Mesh *>::const_iterator i=lth.begin();i != lth.end();++i)
+    {
+       if(! *i ) continue; //
+        ++kk;
+       Mesh &Th(**i);
+      th0=&Th;
+      if(verbosity>1)  cout << " GluMesh + "<< Th.nv << " " << Th.nt << endl;
+      nbt+= Th.nt;
+      nbvx += Th.nv;
+      nebx += Th.neb;
+      for (int k=0;k<Th.nt;k++)
+	for (int e=0;e<3;e++)
+	  hmin=min(hmin,Th[k].lenEdge(e));
+      
+      for (int i=0;i<Th.nv;i++)
+	{ 	  
+	  R2 P(Th(i));
+	  Pn=Minc(P,Pn);
+	  Px=Maxc(P,Px);     
+	}
+    }
+    if(kk==0) return 0; //  no mesh ...
+  if(verbosity>2)
+    cout << "      - hmin =" <<  hmin << " ,  Bounding Box: " << Pn 
+	 << " "<< Px << endl;
+  
+  Vertex * v= new Vertex[nbvx];
+  Triangle *t= new Triangle[nbt];
+  Triangle *tt=t;
+  BoundaryEdge *b= new BoundaryEdge[nebx];
+  BoundaryEdge *bb= b;
+  
+  ffassert(hmin>Norme2(Pn-Px)/1e9);
+  double hseuil =hmin/10.; 
+  
+  
+  FQuadTree *quadtree=new Fem2D::FQuadTree(th0,Pn,Px,0);
+  {
+    map<pair<int,int>,int> bbe;
+    for(list<Mesh *>::const_iterator i=lth.begin();i != lth.end();++i)
+      {
+          if(! *i ) continue; //
+	const Mesh &Th(**i);
+	if(!*i) continue;
+	if(verbosity>1)  cout << " GluMesh + "<< Th.nv << " " << Th.nt << endl;
+	int nbv0 = nbv;
+	
+	for (int ii=0;ii<Th.nv;ii++)
+	{
+	  const Vertex &vi(Th(ii));
+	  Vertex * pvi=quadtree->ToClose(vi,hseuil);
+	  if(!pvi) { 
+	    v[nbv].x = vi.x;
+	    v[nbv].y = vi.y;
+	    v[nbv].lab = vi.lab;
+	    quadtree->Add(v[nbv++]);
+	  }
+	}
+      
+	for (int k=0;k<Th.nt;k++)
+	  {
+	    const Triangle  &K(Th[k]);
+	    int i0=quadtree->ToClose(K[0],hseuil)-v; //NearestVertex(K[0])-v;
+	    int i1=quadtree->ToClose(K[1],hseuil)-v; //NearestVertex(K[1])-v;
+	    int i2=quadtree->ToClose(K[2],hseuil)-v; //NearestVertex(K[2])-v;
+	    (*tt++).set(v,i0,i1,i2,K.lab);
+	  }
+	
+      
+	for (int k=0;k<Th.neb;k++)
+	  {
+	    const BoundaryEdge & be(Th.bedges[k]);
+	    int i0=quadtree->ToClose(be[0],hseuil)-v;
+	    int i1=quadtree->ToClose(be[1],hseuil)-v;
+	    int ii0=i0,ii1=i1;
+	    if(ii1<ii0) Exchange(ii0,ii1);
+	    pair<int,int> i01(ii0,ii1);
+	    if( bbe.find(i01) == bbe.end())
+	    {	    
+	      (*bb++).set(v,i0,i1,be.lab);
+	      bbe[i01]=	  neb++;
+	    }
+	    
+	  }
+	
+      } 
+  }
+
+  delete quadtree;
+
+   
+  if(verbosity>1)
+    {
+      cout << "     Nb points : "<< nbv << " , nb edges : " << neb << endl;
+      cout << "     Nb of glu point " << nbvx -nbv;
+      cout << "     Nb of glu  Boundary edge " << nebx-neb;
+    }
+  
+  {
+    Mesh * m = new Mesh(nbv,nbt,neb,v,t,b);
+    R2 Pn,Px;
+    m->BoundingBox(Pn,Px);
+    m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+    //    m->decrement();
+    return m;
+  }
+  
+}
+
+template<class RR,class AA=RR,class BB=AA> 
+struct Op2_addmesh: public binary_function<AA,BB,RR> { 
+  static RR f(Stack s,const AA & a,const BB & b)  
+  { return RR(s, a, b );} 
+};
+
+template<bool INIT,class RR,class AA=RR,class BB=AA> 
+struct Op2_setmesh: public binary_function<AA,BB,RR> { 
+  static RR f(Stack stack, const AA & a,const BB & b)  
+  {    
+    ffassert(a );
+    pmesh  p=GluMesh(b);
+    
+      if(!INIT &&  *a) (**a).destroy() ;
+    //  Add2StackOfPtr2FreeRC(stack,p); //  the pointer is use to set variable so no remove. 
+    return *a=p,a;
+  } 
+};
+
+class SetMesh_Op : public E_F0mps 
+{
+public:
+  Expression a; 
+   
+  static const int n_name_param =2+2+2+2+2; //  add nbiter FH 30/01/2007 11 -> 12
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+    
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const{ return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+  long  arg(int i,Stack stack, long  a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+  bool   arg(int i,Stack stack, bool   a ) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+
+  
+public:
+  SetMesh_Op(const basicAC_F0 &  args,Expression aa) : a(aa) {
+    args.SetNameParam(n_name_param,name_param,nargs);
+      if( nargs[0] && nargs[2] ) 
+	  CompileError("uncompatible change (Th, label= , refe=  ");
+      if( nargs[1] && nargs[3] ) 
+	  CompileError("uncompatible change (Th, region= , reft=  ");
+      
+  } 
+  
+  AnyType operator()(Stack stack)  const ;
+};
+
+basicAC_F0::name_and_type SetMesh_Op::name_param[]= {
+  {  "refe", &typeid(KN_<long> )},
+  {  "reft", &typeid(KN_<long> )},
+  {  "label", &typeid(KN_<long> )},
+  {  "region", &typeid(KN_<long> )},
+  {  "renumv",&typeid(KN_<long>)},
+  {  "renumt",&typeid(KN_<long>)},
+  {  "flabel", &typeid(long)},
+  {  "fregion", &typeid(long)},
+  {  "rmledges", &typeid(long)},
+  {  "rmInternalEdges", &typeid(bool)}
+
+        
+    
+};
+
+int  ChangeLab(const map<int,int> & m,int lab)
+{
+  map<int,int>::const_iterator i=m.find(lab);
+  if(i != m.end())
+    lab=i->second;
+  return lab;
+}
+
+AnyType SetMesh_Op::operator()(Stack stack)  const 
+{
+    MeshPoint *mp=MeshPointStack(stack),smp=*mp; 
+  Mesh * pTh= GetAny<Mesh *>((*a)(stack));
+  Mesh & Th=*pTh;
+  Mesh *m= pTh;
+  int nbv=Th.nv; // nombre de sommet 
+  int nbt=Th.nt; // nombre de triangles
+  int neb=Th.neb; // nombre d'aretes fontiere
+  KN<long> zz;
+  KN<long> nre (arg(0,stack,arg(2,stack,zz)));  
+  KN<long> nrt (arg(1,stack,arg(3,stack,zz)));  
+  KN<long> rv (arg(4,stack,zz));  
+  KN<long> rt (arg(5,stack,zz));  
+  Expression flab = nargs[6] ;
+  Expression freg = nargs[7] ;
+  bool  rm_edge = nargs[8];
+  long  rmlabedges (arg(8,stack,0L));
+  bool  rm_i_edges = (arg(9,stack,false));
+
+  bool rV =  (rv.size()== nbv);
+  bool rT =  (rt.size()== nbt);
+    if(verbosity>1)
+	cout << "  -- SetMesh_Op: nb vertices" << nbv<< " nb Trai "<< nbt << " nb b. edges  "
+	     << neb << "renum V " << rV << " , renum T "<< rT << " rm internal edges " << rm_i_edges<< endl;
+    
+  if(nre.N() <=0 && nrt.N()<=0  && !rV && ! rT  && ! flab && ! freg && !rm_i_edges &&   !rm_edge ) return m;
+  ffassert( nre.N() %2 ==0);
+  ffassert( nrt.N() %2 ==0);
+  map<int,int> mape,mapt;
+  int z00 = false;
+  for(int i=0;i<nre.N();i+=2)
+    { z00 = z00 || ( nre[i]==0 && nre[i+1]==0);
+      if(nre[i] != nre[i+1])
+	mape[nre[i]]=nre[i+1];
+    }
+  for(int i=0;i<nrt.N();i+=2)
+    mapt[nrt[i]]=nrt[i+1];
+  int nebn =0;
+    for(int i=0;i<neb;++i)
+      {
+	int l0,l1=ChangeLab(mape,l0=m->bedges[i].lab) ;
+	 nebn++;
+      }
+
+  Vertex * v= new Vertex[nbv];
+  Triangle *t= new Triangle[nbt];
+  BoundaryEdge *b= new BoundaryEdge[nebn];
+  // generation des nouveaux sommets 
+  Vertex *vv=v;
+  // copie des anciens sommets (remarque il n'y a pas operateur de copy des sommets)
+  for (int i=0;i<nbv;i++)
+    {
+      int ii=rV? rv(i): i;
+      vv = v + ii;
+     Vertex & V=Th(i);
+     vv->x=V.x;
+     vv->y=V.y;
+     vv->lab = V.lab;
+	
+   }
+
+  //  generation des triangles 
+  int nberr=0;
+  R2 PtHat(1./3.,1./3.);
+  for (int i=0;i<nbt;i++)
+    {
+      int ii= rT ? rt(i) : i;
+      int i0=Th(i,0), i1=Th(i,1),i2=Th(i,2);
+      if(rV) {
+	  i0=rv(i0);
+	  i1=rv(i1);
+	  i2=rv(i2);
+      }
+      // les 3 triangles par triangles origines 
+      t[ii].set(v,i0,i1,i2,ChangeLab(mapt,Th[i].lab));
+      if(freg)
+	{
+	  mp->set(Th,Th[i](PtHat),PtHat,Th[i],Th[i].lab);
+	  t[ii].lab =GetAny<long>( (* freg)(stack)) ;  
+	}
+	
+    }  
+  int  nrmedge=0;
+  // les arete frontieres qui n'ont pas change
+  BoundaryEdge * bb=b;
+  for (int i=0;i<neb;i++)
+    {
+      int ke,k =Th.BoundaryElement(i,ke);
+      int kke,kk= Th.ElementAdj(k,kke=ke);
+      int intern = ! (( kk == k )|| ( kk < 0)) ;
+      const   Triangle &K(Th[k]);
+      int i1=Th(Th.bedges[i][0]);
+      int i2=Th(Th.bedges[i][1]);
+ 
+	if(rV) {
+	    i1=rv(i1);
+	    i2=rv(i2);
+	}
+	
+      int l0,l1=ChangeLab(mape,l0=m->bedges[i].lab) ;
+      mp->set(Th,Th[k](PtHat),PtHat,Th[k],l1);
+      if(flab)
+      {
+          R2 E=K.Edge(ke);
+          double le = sqrt((E,E));
+          double sa=0.5,sb=1-sa;
+          R2 PA(TriangleHat[VerticesOfTriangularEdge[ke][0]]),
+          PB(TriangleHat[VerticesOfTriangularEdge[ke][1]]);
+          R2 Pt(PA*sa+PB*sb ); //
+          //  void set(const Mesh & aTh,const R2 &P2,const R2 & P_Hat,const  Triangle & aK,int ll,const R2 &NN,int iedge,int VFF=0)
+          MeshPointStack(stack)->set(Th,K(Pt),Pt,K,l1,R2(E.y,-E.x)/le,ke);
+	  l1 =GetAny<long>( (*flab)(stack)) ;
+      }
+     if( !( intern && ( rm_i_edges || (rmlabedges && (l1 == rmlabedges)) )   ))
+      *bb++ = BoundaryEdge(v,i1,i2,l1);
+     else ++nrmedge;
+    }
+    nebn -= nrmedge;
+    if(nrmedge && verbosity > 2) cout << "   change  mesh2 : number of removed  internal edges " << nrmedge << endl;
+  assert(nebn==bb-b);
+  m =  new Mesh(nbv,nbt,nebn,v,t,b);
+
+  R2 Pn,Px;                                                                                                                               
+  m->BoundingBox(Pn,Px);
+  m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);   
+  //  m->decrement();
+  Add2StackOfPtr2FreeRC(stack,m);
+    *mp=smp;
+  return m;
+}
+
+
+class SetMesh : public OneOperator { public:  
+typedef Mesh *pmesh;
+    SetMesh() : OneOperator(atype<pmesh>(),atype<pmesh>() ) {}
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    return  new SetMesh_Op(args,t[0]->CastTo(args[0])); 
+  }
+};
+
+
+//  truc pour que la fonction 
+// Init::Init() soit appele a moment du chargement dynamique
+// du fichier 
+//
+#ifndef  DYNAMICS_LIBS
+void init_glumesh2D()
+{
+  Dcl_Type<listMesh>();
+  typedef Mesh *pmesh;
+  
+  //Dcl_Type<listMesh3>();
+  //typedef Mesh3 *pmesh3;
+  if(verbosity>2)
+    cout << " glumesh2D " ;
+  //cout << " je suis dans Init " << endl; 
+  TheOperators->Add("+",new OneBinaryOperator_st< Op2_addmesh<listMesh,pmesh,pmesh>  >      );
+  TheOperators->Add("+",new OneBinaryOperator_st< Op2_addmesh<listMesh,listMesh,pmesh>  >      );
+  TheOperators->Add("=",new OneBinaryOperator_st< Op2_setmesh<false,pmesh*,pmesh*,listMesh>  >     );
+  TheOperators->Add("<-",new OneBinaryOperator_st< Op2_setmesh<true,pmesh*,pmesh*,listMesh>  >     );
+  
+  Global.Add("change","(",new SetMesh);
+
+}
+#else  
+class Init { public:
+  Init();
+};
+
+static Init init;  //  une variable globale qui serat construite  au chargement dynamique 
+
+Init::Init(){  // le constructeur qui ajoute la fonction "splitmesh3"  a freefem++ 
+  Dcl_Type<listMesh>();
+  typedef Mesh *pmesh;
+  
+  //Dcl_Type<listMesh3>();
+  //typedef Mesh3 *pmesh3;
+  
+  if (verbosity)
+    cout << "  glumesh2D " ;
+  //cout << " je suis dans Init " << endl; 
+  TheOperators->Add("+",new OneBinaryOperator_st< Op2_addmesh<listMesh,pmesh,pmesh>  >      );
+  TheOperators->Add("+",new OneBinaryOperator_st< Op2_addmesh<listMesh,listMesh,pmesh>  >      );
+  TheOperators->Add("=",new OneBinaryOperator_st< Op2_setmesh<false,pmesh*,pmesh*,listMesh>  >     );
+  TheOperators->Add("<-",new OneBinaryOperator_st< Op2_setmesh<true,pmesh*,pmesh*,listMesh>  >     );
+  
+  Global.Add("change","(",new SetMesh);
+
+}
+#endif
diff --git a/src/fflib/lex.cpp b/src/fflib/lex.cpp
new file mode 100644
index 0000000..4c831e0
--- /dev/null
+++ b/src/fflib/lex.cpp
@@ -0,0 +1,860 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include  <complex>
+#include  <string>
+#include  <iostream>
+#include  "error.hpp"
+#include  <ctype.h>
+#include  <stdlib.h>
+#include  <map>
+#include "AFunction.hpp"
+//class pfes;
+#include  <iomanip>                                                                                                        
+#include "lg.tab.hpp"
+#include "lex.hpp"
+
+
+extern YYSTYPE *plglval;
+
+//  New version of macro expantion more classical
+//  and more  simple
+// FH Jan. 2005
+
+static const bool debugmacro = false;
+
+/*inline char * newcopy(const char * s)
+{
+  char *r(new char  [strlen(s)+1]);
+  strcpy(r, s);return r;
+}
+*/
+void  mylex::Add(Key k,int i)   
+{
+  Check(!i,k,"mot clef");
+  Add(k,i,0); 
+}
+
+void  mylex::Add(Key k,aType t)   
+{
+  Check(!t,k,"type");
+
+  // TYPE defined at [[file:../lglib/lg.ypp::token type TYPE]]
+  Add(k,TYPE,t);
+}
+
+void  mylex::AddF(Key k,aType t)  
+{
+  Check(!t,k,"FUNCTION");
+  Add(k,FUNCTION,t); 
+}
+void  mylex::AddSpace(Key k,aType t)  
+{
+  Check(!t,k,"FESPACE");
+  Add(k,FESPACE,t); 
+}
+
+bool mylex::InMotClef  (aType & t, int & r) const {
+  const_iterator i= MotClef.find(buf);
+  if (i== MotClef.end()) {
+    t=0;r=ID;
+    return false;}
+  else {
+    r=i->second.first;
+    t=i->second.second;
+    ffassert(r);
+    return true;}}
+
+void  mylex::Add(Key k,int r,aType t){ 
+  iterator ii= MotClef.find(k);
+  ffassert(ii==MotClef.end());
+  MotClef.insert(pair<const Key,Value>(k,Value(r,t))); }
+
+void mylex::dump(ostream & f ) 
+{
+  const_iterator i=MotClef.begin(),e=MotClef.end();
+  for (;i != e;i++)
+    {
+      f << "      " << i->first << " " << i->second.first << " " <<  i->second.second->name() << endl;
+    }
+}   
+
+inline bool isNLCR(istream & f,int c)
+{
+    // eat  CR NL or NL CR paire  
+    int cc= f.peek();
+    bool ret=(c == 10 || c == 13) ;
+    if(ret && ( cc != c) && (cc == 10 || cc == 13) )
+     f.get();
+    return ret;
+}
+
+int mylex::EatCommentAndSpace(string *data)
+{
+ // if data is !0 then add reading char in data
+ // return the last read char c
+ //  --------------------
+  int c,caux,sep=0;
+    const int space=(int) ' ';
+  int incomment =0;
+  do {
+    incomment = 0;
+    c = source().peek();
+    
+    // eat spaces 
+    while (isspace(c) || c == 10 || c == 13 )
+      {sep=space;
+      c = source().get();
+      if(isNLCR(source(),c)) c='\n';
+      if (echo) cout << (char) c;
+      if(c=='\n') { linenumber++; if (echo) cout << setw(5) <<linenumber << " : " ;};             
+       if(data) *data+=char(c);
+       c=source().peek();
+      } 
+     
+    // eat comment  
+    if(c=='/') 
+      { c = source().get();
+        caux=source().peek(); 
+        if(caux =='/') incomment = 1;
+        else if (caux == '*' ) incomment = 2;
+        if(!incomment) source().putback(c);
+      }
+      
+      
+    if(incomment==1) 
+      { sep=space;
+        if (echo) cout << "//" ;source().get();
+        if(data) *data+="//";
+
+        do {c=source().get();            
+        if(isNLCR(source(),c)) c='\n';
+        if (echo) cout << (char) c;
+        if(data) *data+=char(c);
+        if(c=='\n') { linenumber++; if (echo) cout << setw(5) <<linenumber << " : " ;};             
+        }
+      while( (c!= '\n') && (c!= 10)  && (c!= 13)  &&  ( c != EOF) );
+      }
+    else if(incomment==2) 
+      { sep=space;
+        if (echo) cout << "/*" ;
+        if(data) *data+="/*";
+
+        source().get();
+        do {    
+          c=source().get(); 
+          if(isNLCR(source(),c)) c='\n';
+          if (echo) cout << (char) c ;
+          if(data) *data+=char(c);
+          if(c=='\n') { linenumber++; if (echo) cout << setw(5) <<linenumber << " : " ;};             
+          caux = source().peek();
+        } while(c != EOF && !(c=='*' && caux=='/') ) ;
+        
+        if(c != EOF)  
+          {     c = source().get();
+          if (echo) cout << (char) c ;
+          if(data) *data+=char(c);          
+          }
+        else erreur( " Unterminated comment");
+      }
+  } while (incomment);
+    return (c==EOF) ? c : sep;
+}
+int mylex::basescan()
+{
+  //  extern long mpirank;
+   
+  int c;
+  buf[0]=0;
+  buf[1]=0;
+  buf[2]=0;
+  buf[3]=0; //
+ debut:
+  TheCurrentLine=linenumber;
+  // modif FH 
+  if (firsttime) 
+  {
+      firsttime=false;
+    if(echo) cout << setw(5) <<linenumber << " : " ; 
+  }
+  EatCommentAndSpace(); 
+  c =source().get(); // the current char 
+  char nc = source().peek(); // next char
+  buf[0]=c;
+  buf[1]=nc;
+  buf[2]=0;
+  int ret = c;
+  if (c == EOF) 
+    { 
+      //if (echo) cout << "ENDOFFILE "<< endl;
+      if (close() )  goto debut; 
+      buf[0]=0;
+      return ENDOFFILE;}
+  else if (isdigit(c) || (c=='.' && isdigit(nc))) {
+    //  a number
+    int i=1;
+    buf[0]=c;
+    bool real= (c=='.');
+    
+    
+    while ( isdigit(nc) && i< 50 ) buf[i++]=source().get(),nc=source().peek();
+    if (!real && (nc == '.')) real=true,buf[i++]=source().get(),nc=source().peek();
+    while ( isdigit(nc) && i< 50 ) buf[i++]=source().get(),nc=source().peek();
+    if (nc =='E' || nc =='e' || nc =='D' || nc =='d') {real=true;
+    buf[i++]=source().get(),nc=source().peek();
+    if (nc =='+' || nc =='-' || isdigit(nc))  buf[i++]=source().get(),nc=source().peek();
+    while ( isdigit(nc) && i< 50 ) buf[i++]=source().get(),nc=source().peek();
+    }
+    if (i>= 50)  erreur("Number to long");
+    
+    buf[i]=0;
+    if (nc=='i' ) 
+      { buf[i++]=source().get(),buf[i]=0,plglval->dnum = atof(buf),ret=CNUM;}
+    else 
+      if (real)
+        plglval->dnum = atof(buf),ret=DNUM;
+      else
+        plglval->lnum = atoi(buf),ret=LNUM;
+    
+    if(lexdebug) cout << " NUM : " << buf  << " "<<endl;
+  }
+  else if (isalpha(c) || c=='\\')
+    {
+      ret =  ID;
+      int i; 
+      for (i = 1; i < 256 && isalnum(source().peek()); i++) 
+        buf[i]=source().get();
+      if (i == 256) 
+        erreur ("Identifyier too long");
+      buf[i] = 0;
+      
+    }
+  else  if (c=='"')
+    {
+      int i;
+      char cc,ccc;
+      for (     i = 0,cc=source().peek(); 
+                i < 256 &&  ( (isprint(cc)|isspace(cc)) && cc !='\n'  && cc !='"');
+                cc=source().peek(),++i
+                ) 
+        {       
+          if ( cc == '\\')  //   escape 
+            {
+              cc= source().get();
+              cc= source().get(); 
+	      ccc= source().peek(); 
+              switch (cc) {
+              case 'n': buf[i]='\n';break;
+              case 'r': buf[i]='\r';break;
+              case 'f': buf[i]='\f';break;
+              case 't': buf[i]='\t';break;
+              case 'a': buf[i]='\a';break;
+              case 10:
+              case 13:
+		cc='\n';
+		if(ccc!=cc && (ccc==10 || ccc==13)) source().get();// NL CR eat ...
+		linenumber++;
+		//if (echo) cout << setw(5) <<linenumber << " : " ;		
+              default : buf[i]=cc  ;break;              
+              }
+            }
+          else 
+            buf[i] = source().get();
+        }
+      if (i == 256) erreur ("String too long");
+      buf[i] = 0;
+      if(source().get() != '"') erreur("End of String could not be found");
+      plglval->str = newcopy(buf);
+      if(lexdebug)  cout << "STRING=" << '"' << buf << '"' << endl;
+      
+      ret= STRING;
+    }
+  else 
+    {
+      ret = c;
+      switch(c) {
+        
+      case '{': 
+      case '%': 
+      case '}': 
+      case '(': 
+      case ')': 
+      case '[': 
+      case ']': 
+      case ',': 
+      case ';': 
+      case '#': 
+        break;
+      case '*': 
+        if (nc == '=') ret=MULEQ;       
+        break;
+      case '/': 
+        if (nc == '=') ret=DIVEQ;
+        break;  
+      case '^': 
+      case '~': 
+      case '\'': 
+      case '_': 
+      case '?':
+        break;
+      case '.': 
+        if (nc == '*') ret = DOTSTAR;
+        else if (nc == '/') ret = DOTSLASH;
+        break;
+      case ':': 
+        if (nc == '=') ret= SET;
+        break;
+      case '&':
+        if (nc == '&') ret= AND;
+        break;
+      case '|':
+        if (nc == '|') ret= OR;
+        break;
+      case '!': 
+        if (nc == '=') ret=NE;
+        break;          
+      case '<':
+        if (nc == '=') ret=LE;
+        if (nc == '<') ret=LTLT;
+        if (nc == '>') ret= NE;
+        break;
+      case '>':
+        if (nc == '=') ret=GE;  
+        if (nc == '>') ret=GTGT;
+        break;  
+      case '=': 
+        if (nc == '=') 
+          ret=EQ;
+        break;
+      case '-': 
+        if (nc == '>') ret=ARROW;       
+        if (nc == '-') ret=MOINSMOINS;  
+        if (nc == '=') ret=MOINSEQ;     
+        break;
+      case '+': 
+        if (nc == '+') ret=PLUSPLUS;    
+        if (nc == '=') ret=PLUSEQ;      
+        break;
+      default: 
+        cerr << "'" << (char) c << (char) nc << "' <=> " << (int) c << " is " ;
+        erreur (" Unexpected character");
+      }
+      if( (ret == DOTSTAR) || (ret==DOTSLASH))
+      {
+          source().get();
+          nc = source().peek();
+          if(nc == '=' )
+          {
+              buf[2]='=';// ad FH 19 april 2012 (bug in macro ) 
+              buf[3]=0; 
+              source().get();
+              ret = (ret == DOTSTAR) ?DOTMULEQ : DOTDIVEQ;
+          }
+      }
+      else if (ret!=c) source().get();
+      else buf[1] = 0;
+      strcpy(plglval->oper,buf);
+      if(lexdebug)  cout << "Special '" <<  plglval->oper << "' " << ret << " ";
+    }
+  typetoken=ret; 
+  return ret;
+}
+
+int mylex::scan1()
+{
+
+  // extern long mpirank;
+ // bool echo = mpirank == 0; 
+
+  int ret= basescan();
+  if(debugmacro)  cout << " scan1 " << ret << " " << token() << " " << ID << endl;
+    while ( ret == ID &&SetMacro(ret)); // correction mars 2014 FH
+    while ( ret == ID && CallMacro(ret)) ; // correction mars 2014 FH
+    
+  return ret;
+}    
+
+// <<mylex_scan>>
+int mylex::scan(int lvl)
+{
+ 
+  int ret= scan1(); 
+  
+  // ID defined at [[file:../lglib/lg.ypp::token str ID]]
+  if ( ret == ID) {
+    if (! InMotClef(plglval->type,ret))  {
+      int ft = FindType(buf);
+
+      // FESPACE, FESPACE1, FESPACE3 defined at [[file:../lglib/lg.ypp::token str FESPACE]]
+      int feid3[4]  ={ ID,FESPACE1,FESPACE,FESPACE3};
+
+      assert ( ft >= 0 && ft <= 3)  ;
+      ret =  feid3[ft];      
+      plglval->str = newcopy(buf);
+    }}
+  
+  if ( ret =='{') { //cout << " listMacroDef->push_back"<< endl; 
+    listMacroDef->push_back( MapMacroDef() );}
+  else if (ret == '}') {//cout << " listMacroDef->pop_back"<< endl;
+    listMacroDef->pop_back( );}
+  
+  if (! lexdebug && echo && lvl==0 ) print(cout);
+  
+  return ret;
+}
+
+string mylex::token() const
+  {
+   int i=-1;
+   string f;
+    if (typetoken == STRING) 
+      {
+        f += '"';
+        while (buf[++i]) 
+          if (buf[i]=='\n') f +=  "\\n"; 
+          else if (buf[i]=='"') f += "\\\""; 
+          else f +=  buf[i] ;
+        f+= '"';
+      }
+    else 
+      while (buf[++i]) 
+        if (buf[i]=='\n') f += "\\n"; 
+        else f += buf[i] ;
+    return f;
+  }
+  
+  void mylex::print(ostream &f) const
+  {
+   int i=-1;
+   int k=0;
+    if (typetoken == STRING) 
+      {
+	
+        f <<'"';
+        while (buf[++i]) { k++;
+	if (buf[i]=='\n') k++, f << "\\n"; 
+	else if (buf[i]=='"') k++,f << "\\\""; 
+	else f << buf[i] ;
+	if ( k%50==49) f << "\n  ... : ";  
+	}
+        f << '"';
+      }
+    else 
+      while (buf[++i]) 
+        if (buf[i]=='\n') f << "\\n"; 
+        else f << buf[i] ;
+  
+  } 
+
+char * mylex::match(int i) 
+{ if ( i != basescan() ) {// basescan -> scan1 change 2/2/2007  (non pas des substitution de parametres FH)
+  cerr << " we waiting for a '" << char(i) <<"'" << endl;
+  ErrorScan(" err macro ");};
+ return buf; }
+
+
+bool mylex::SetMacro(int &ret)
+{ 
+  char endmacro[]="EndMacro";
+  char newmacro[]="NewMacro";
+    
+  bool rt=false;
+  int oldmacro=1;
+  if (strcmp(buf,"macro")==0 || (oldmacro=strcmp(buf,newmacro))==0 )
+    {
+      char *macroname=newcopy(match(ID));
+      int nbparam =0;
+      deque<string> macroparm;
+      int rr=basescan(); 
+      string def;                          
+      if (rr!='(') 
+	def += buf;
+      else
+	{ // a '(' after macro name
+	  rr =  basescan();
+	  
+	  if (rr != ')' ) 
+	    do { 
+	      if (nbparam++>= 100) 
+		{ cerr << "in macro " <<macroname << endl;
+		ErrorScan(" Too much (more than 100) parameters"); }  
+	      
+	      //cout << " \t\t " << ID << " " << rr << " " << buf << endl;
+	      if (rr != ID) {
+		cerr <<" Erreur waiting of an ID: " << buf << " " << rr <<  endl;
+		erreur("in macro def: waiting for a ID"); }
+	      macroparm.push_back(buf);
+	      rr =  basescan(); 
+	      if (rr  == ')') break;          
+	      if ( rr != ',') erreur("in macro def: waiting  , or  ) "); 
+	      rr =  basescan();
+	      
+	    } while(1); 
+	}
+      int kmacro=0;
+      
+
+      do {
+	int lk=0;
+	string item;
+	int i = source().get();
+	if (i == EOF) {  cerr << "in macro " <<macroname <<  endl;
+	ErrorScan(" ENDOFFILE in macro definition. remark:a macro end with // ");}
+	int ii = source().peek();
+	if(isspace(i) && isalpha(ii) ) {
+	    def +=char(i);
+	    i = source().get();
+	    item = "";
+	    while(isalpha(i))
+	      {
+		item += char(i);
+		i = source().get();
+	      }
+	    if( item == newmacro)  kmacro++;
+	    if( item == endmacro)  {
+		if (kmacro==0)  
+		    { source().putback(i); break;}
+		kmacro--;
+	    }
+	    def += item;
+	    item ="";
+	    ii = source().peek();
+	}
+	
+	if(oldmacro)
+	  {
+	    if (i == '/' && ii == '/') { source().putback('/'); break;} 
+	  }
+
+	def +=char(i);        
+      } while(1);
+      macroparm.push_back(def);
+      if(echo) cout << "macro " << macroname  ;
+      for (size_t i=0;i<macroparm.size()-1;i++)
+	if(echo) cout << ( (i == 0) ? '(' : ',') << macroparm[i];
+      if (nbparam)
+	if(echo) cout << " )  " ;
+      for (size_t i=0;i<def.size();i++)
+	if (def[i] == 10 || (def[i] == 13 ) ) 
+	  {
+	    def[i]='\n';         
+	    linenumber++; if(echo) cout << '\n' << setw(5) <<linenumber << " : " ;
+	  }                  
+	else 
+	  if(echo) cout << def[i]   ;
+         // cout << macroparm.back() ;
+      MapMacroDef & MacroDef =listMacroDef->back();
+      MapMacroDef::const_iterator i=MacroDef.find(macroname);
+      if ( i == MacroDef.end() )
+	MacroDef[macroname]=macroparm;
+      else { 
+	cerr << "ERREUR in macro name:" <<macroname << endl;
+	ErrorScan(" The macro already exists, sorry");}
+      rt=true;
+      ret= basescan();
+    }
+  return rt;
+}
+
+
+bool mylex::CallMacro(int &ret)
+{
+  // New Version with direct macro expansion
+  // FH  jan 2005 
+  // -----------------------------------------
+//  add Stringification,FILE, LINE  march 2014 FH..
+  if(strcmp(buf,"Stringification")==0)
+  {
+      if(debugmacro) cout <<"call Stringification : " << buf << endl;
+
+      if(echo) cout << buf << "(" ;
+      string p,cmm;
+      int lvll=0;
+           match('(');
+      
+      int kend=')';
+      while (1) {
+          cmm="";
+          int sep =  EatCommentAndSpace(&cmm);
+          p += cmm;
+          int rr = scan1();// do macro expantion
+          if(lvll && rr==')') lvll--; //   if ( then  we eat next )
+          else if (rr=='(') lvll++ ;  //  eat next
+          else if (lvll<=0)
+              {
+                  if (rr==kend ) break;
+                  else if  (rr==')' || rr==',')  {
+                      cerr << "Error in Stringification  "
+                      << ", we wait for "<< char(kend) << " and we get  " << char(rr)<< endl;
+                      ErrorScan(" Wrong number of parameter in  Stringification call");
+                  }}
+          if(debugmacro)cout << " ..." << rr << " " << token()<< " " << level << endl;
+          if (rr==ENDOFFILE) ErrorScan(" Stringification in macro ");
+          if(echo) cout << token();
+          p += token();
+          //if(echo) cout <<buf;
+      }
+      
+      plglval->str = newcopy(p.c_str());
+      ret = STRING;
+
+      return false;
+  }
+  else if(strcmp(buf,"FILE")==0)
+  {
+      plglval->str = newcopy(filename() );
+      ret = STRING;
+     return false;
+  }
+  else if(strcmp(buf,"LINE")==0)
+  {
+    plglval->lnum = linenumber;
+    ret=LNUM;
+    return false;
+  }
+  else
+  for (list<MapMacroDef>::const_iterator i=listMacroDef->begin(); i != listMacroDef->end(); i++)
+    {
+      MapMacroDef::const_iterator j= i->find(buf);
+      
+      if (j != i->end()) {
+	// int inmacroold=withmacropara;
+	  if(debugmacro) cout <<"call macro : " << buf << endl;
+	  string * macronn= new string(" macro: ");
+	  *macronn+= buf;
+	  
+	const deque<string>  & macroparm= j->second;
+	int nbparam= macroparm.size()-1;
+	MapMacroParam  lp;
+	if (nbparam > 0 ) { 
+	  match('(');
+	    for (int k=0;k<nbparam;k++)
+	      { 
+		  string p;
+		  int kend= ( k+1 == nbparam) ? ')' : ',';
+		  int lvl=0;
+		  int lvll=0;
+		  while (1) {
+		      int sep =  EatCommentAndSpace();
+		      int rr = basescan();// basescan -> scan1 change 2/2/2007  ( not change to pass macro name as a parameter)
+		      if ( (rr=='}') && (--lvll==0) ) 
+			   continue; // remove first {
+		      else if ( (rr=='{') && (++lvll==1) )
+			  continue; // remove last }	
+		      else if(lvll==0) //  count the open close () [] 
+			{  
+			if(lvl && rr==')') lvl--; //   if ( then  we eat next ) 
+			else if(lvl && rr==']') lvl--; //   if ( then  we eat next ) 
+			else if (rr=='(') lvl++ ;  //  eat next 
+			else if (rr=='[') lvl++ ;  //  eat next 
+			else if (lvl<=0) 
+			  {
+			    if (rr==kend ) break;
+			    else if  (rr==')' || rr==',')  {// Correction FH 2/06/2004
+				cerr << "Error in macro expansion "<< j->first
+				<< ", we wait for "<< char(kend) << " and we get  " << char(rr)<< endl;
+				cerr << " number of macro parameter in definition is " << nbparam << endl;
+				ErrorScan(" Wrong number of parameter in  macro call");
+			    }}}
+		      
+		      if (rr==ENDOFFILE) ErrorScan(" ENDOFFILE in macro usage");
+		      if(sep==' ') p+=' ';
+		      p += token(); // Correction FH 2/06/2004 of string parameter
+		      
+		  }
+		  if(debugmacro)
+		cout << "macro arg "<< k << " :" << macroparm[k] << " -> " <<  p << endl;
+	      lp.insert(pair<string,string>(macroparm[k],p));
+	      //lp[macroparm[k]] = p; 
+	    }
+	}
+	if(debugmacro)
+	  cout <<   " input in : -> " << macroparm[nbparam]  << " <-> " << nbparam << endl;
+	input(macroparm[nbparam]);
+	// ici il faut faire la substitution  de parameter 
+	// -----------------------------------------------
+	string expandtxt;
+	bool echosave=echo;
+	while(1) {
+	  int c= EatCommentAndSpace(&expandtxt); // eat comment to save it;
+	  if (c == EOF) break;
+	  ret = basescan();
+          if(debugmacro)  cout << " ret = " << ret << token() << endl;
+	  if(ret== ENDOFFILE) break; 
+	  if (nbparam && ret == ID) 
+	    {  
+	      MapMacroParam::const_iterator j=lp.find(buf);
+	      if ( j !=  lp.end()) 
+		expandtxt+=j->second;
+	      else 
+		expandtxt+=token();
+	    }
+	  else if (ret!='#')  //  macro concatenation operator 
+	    expandtxt+=token();
+	}
+	echo=echosave;
+	if(debugmacro) cout <<" (macro) eadin : " << expandtxt << endl;
+	input(expandtxt,macronn);
+	ret =  scan1(); // Correction FH 6/06/2004 of string parameter
+	return true;        
+      }
+    }
+  return false;
+}
+
+void  mylex::xxxx::open(mylex *lex,const char * ff) 
+{
+  //filename=ff;
+  l=0;
+  nf=f=0;
+  if(lex->ffincludedir.empty()) // if no liste 
+      nf=f= new ifstream(ff,ios_base::binary); //  modif of win32
+  if (!f || !*f)
+   {
+   if ( f)  { delete f; f=0; }
+   for (ICffincludedir k=lex->ffincludedir.begin();
+        k!=lex->ffincludedir.end();
+        ++k)
+   {
+    string dif_ff(*k+ff);
+    if (verbosity>=50) lex->cout  << "  --lex open :" << dif_ff << endl;
+    nf=f= new ifstream(dif_ff.c_str(),ios_base::binary); 
+    if ( f)  {
+      if ( f->good()) {  
+        filename = new string(dif_ff);
+        break;
+      }
+      delete f; f=0;
+     }     
+   } 
+   } 
+   else
+      filename=new  string(ff);
+  if (!f || !*f) {
+    lex->cout << " Error openning file " <<ff<< " in: " <<endl;
+      for (ICffincludedir k=lex->ffincludedir.begin();
+	   k!=lex->ffincludedir.end();
+	   ++k)
+	  lex->cout  << "  -- try  :\"" << *k+ff  << "\"\n";
+
+    lgerror("lex: Error input openning file ");};
+}
+void  mylex::xxxx::readin(mylex *lex,const string & s,const string *name, int macroargs)//,int nbparam,int bstackparam)
+{
+  filename=name;
+  macroarg=macroargs;
+  l=0;
+  nf=f= new istringstream(s.c_str()); 
+  
+  if (!f || !*f) {
+    lex->cout << " Error readin string  :" <<s<< endl;
+    lgerror("lex: Error readin macro ");};
+}
+
+void mylex::xxxx::close() 
+{ 
+  if( nf)  delete nf;
+  if (filename && (macroarg==0) ) delete filename;
+  
+}
+void mylex::input(const char *  filename) 
+{
+  ffassert(level<99 && level >= -1);
+  if (level>=0) 
+    pilesource[level].l =linenumber;
+  
+  pilesource[level+1].open(this,filename);
+  pilesource[level+1].l =0;
+  // cout << "\n ++include " << filename << ";" << level+1 << endl;
+  linenumber = 1;     
+  level++;      
+}
+
+void mylex::input(const string & str,const string * name) 
+{
+  
+  ffassert(level<99 && level >= -1);
+  if (level>=0) 
+    { pilesource[level].l =linenumber;
+    }
+  
+  pilesource[level+1].readin(this,str,name);
+  linenumber = 0;     
+  level++;
+  
+}
+  
+bool mylex::close() { 
+  if(debugmacro )
+    cout << "\n close " << level ;
+  ffassert(level >=0 && level < 100);
+  // cout << "\n-- close " << level << endl;
+  pilesource[level].close(); 
+  // cout << "\n ++   " << level << endl;
+  if (--level<0)
+    return false;
+  linenumber = pilesource[level].l;
+  return true;
+}
+  
+ mylex::~mylex()
+{
+  delete listMacroDef;
+  while( ! strdata.empty()) 
+   {  //  commente july 2005 FH ???. a test plus finement. 
+      delete [] strdata.top(); // bug  ????? FH  25032005 
+      strdata.pop();
+   }
+}
+
+ mylex::mylex(ostream & out,bool eecho):
+    linenumber(1),
+    charnumber(0),
+    ffincludedir(ffenvironment["includepath"]),
+    firsttime(true),
+    level(-1),
+    echo(eecho && (mpirank == 0) && verbosity),
+    cout(out),
+    listMacroDef(new list<MapMacroDef>),
+    listMacroParam(0)
+ {    
+    listMacroDef->push_front(MapMacroDef());
+   };
+   
+mylex * Newlex(  ostream & out,bool eecho)
+  {
+    return new mylex(out,eecho);
+  }
+void Destroylex(mylex * m)
+ {
+   delete m;
+ }
+ostream & mylex::ShowStack(ostream & f){
+    for (int i=0;i<level;++i)
+	if(  pilesource[i].filename ) f << " \t"<<i<<"\t"<<" in " << *pilesource[i].filename<< " line : " <<  pilesource[i].l << endl;
+    return f;     
+}
diff --git a/src/fflib/lex.hpp b/src/fflib/lex.hpp
new file mode 100644
index 0000000..fde24a0
--- /dev/null
+++ b/src/fflib/lex.hpp
@@ -0,0 +1,161 @@
+/// \file
+
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef MY_LEX_HPP_
+#define MY_LEX_HPP_
+// with New version of macro expansion more simple and more stable 
+// FH jan 2005
+#include <stack> 
+#include "environment.hpp"
+extern bool lexdebug;
+extern long mpisize,mpirank;
+
+/// <<mylex>>
+class mylex : public CodeAlloc { 
+  public:
+  typedef const char * Key;
+  typedef pair<int,aType> Value;
+  struct Keyless : binary_function<Key,Key, bool>
+   { bool operator()(const Key& x, const Key& y) const{ return strcmp(x,y)<0;} };  
+  typedef   map<const char *,Value,Keyless> MapMotClef;
+  typedef   map<const char *, deque<string> ,Keyless >  MapMacroDef;
+  typedef   map<string, string  >  MapMacroParam;
+  typedef   MapMotClef::const_iterator const_iterator;
+  typedef   MapMotClef::iterator iterator;
+
+  public: 
+  int linenumber,charnumber;
+  list<string> ffincludedir;
+  typedef  list<string>::iterator Iffincludedir;
+  typedef  list<string>::const_iterator ICffincludedir;
+  
+  private:
+  bool firsttime;
+  int level;
+
+  char buf[1024];
+  int typetoken;
+  bool echo;
+  stack<char *> strdata;
+
+  struct xxxx { 
+    int l;
+    istream * f;
+    const string * filename;
+    int macroarg;
+    istream * nf;
+
+    xxxx() : l(0), f(0) , filename(0),macroarg(0),nf(0)   {}
+    void  open(mylex *lexx,const char * ff) ;
+    void  readin(mylex *lexx,const string & s,const string *name=0,int macroargg=0);
+    void close() ;
+  };
+  
+  friend struct mylex::xxxx;
+  
+  xxxx pilesource[100];
+  istream & source() const {return  * pilesource[level].f;} 
+  ostream & cout ;
+
+  MapMotClef  MotClef;
+  list<MapMacroDef> *listMacroDef;
+  list<MapMacroParam> *listMacroParam;
+  public:
+  
+  mylex(ostream & out,bool eecho=true);
+  string token() const;
+  void print(ostream &f) const; 
+
+  /// This is the main [[file:../lglib/lg.ypp::yylex]] entry point from the grammar. Implemented in
+  /// [[file:lex.cpp::mylex_scan]]
+
+  int scan(int lvl=0);
+
+  int lineno(){return linenumber;}
+  char * YYText() { return buf;}
+  void dump(ostream & f ) ;
+  
+  void erreur(const char * s) {
+    cerr << " Error line number" <<linenumber << ": " << s << endl;
+    throw(ErrorCompile("lex:",linenumber)); }
+  
+  bool InMotClef  (aType & t, int & r) const ;
+  void  Add(Key k,int r,aType t);
+  
+  void Check(bool b,Key k,const char * s) {
+    if(b) {cout <<"Add " << s << "  null: " << k << endl;
+    CompileError();}}
+  
+  void Add(Key k,int i) ;//    {Check(!i,k,"mot clef");Add(k,i,0); }
+  void Add(Key k,aType t);//   {Check(!t,k,"type");Add(k,TYPE,t); }
+  void AddF(Key k,aType t);//  {Check(!t,k,"type");Add(k,FUNCTION,t); }
+  void AddSpace(Key k,aType t);//  {Check(!t,k,"type");Add(k,FUNCTION,t); }
+
+  const char * filename() const { 
+    if ( level >=0 ) 
+      return  pilesource[level].filename ? pilesource[level].filename->c_str() : " -- in macro -- ";
+    return "-- unkown --";}
+    
+  void input(const char *  filename) ;
+  void input(const string &str,const string *name=0);
+  bool close() ;
+
+  char * newcopy(const char * s)
+   {
+    char *r(new char  [strlen(s)+1]);
+    strcpy(r, s);
+    strdata.push(r);
+    return r;
+  }
+ ostream & ShowStack(ostream & f); 
+~mylex();
+private: 
+  int basescan();  
+  int EatCommentAndSpace(string *data=0);
+  int scan1();
+  bool SetMacro(int &ret);
+  bool CallMacro(int &ret);
+  char * match(int i);
+  void ErrorScan(const char * s) {
+      cerr  << "\n" ;
+      ShowStack(cerr);
+    throw(ErrorCompile(s,lineno(),YYText() ) );}    
+  
+  
+} ;
+
+mylex * Newlex(  ostream & out,bool =true);
+ void Destroylex(mylex * m);
+
+/// <<zzzfff>> This pointer is allocated in [[file:global.cpp::zzzfff]] and initialized in
+/// [[file:../lglib/lg.ypp::zzzfff]]
+
+extern mylex *zzzfff;
+
+#endif
diff --git a/src/fflib/lgfem.cpp b/src/fflib/lgfem.cpp
new file mode 100644
index 0000000..371d53d
--- /dev/null
+++ b/src/fflib/lgfem.cpp
@@ -0,0 +1,6011 @@
+/// \file
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifdef __MWERKS__
+#pragma optimization_level 0
+//#pragma inline_depth(0)
+#endif
+
+#include  <cmath>
+#include  <iostream>
+#include <cfloat>
+
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include <cstdio>
+#include "fem.hpp"
+#include "Mesh3dn.hpp"
+
+
+#include "MatriceCreuse_tpl.hpp"
+
+
+#include "MeshPoint.hpp"
+#include <complex>
+#include "Operator.hpp" 
+
+#include <set>
+#include <map>
+#include <vector>
+
+#include "lex.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+#include "CGNL.hpp"
+#include "AddNewFE.h"
+#include "array_resize.hpp"
+#include "PlotStream.hpp"
+
+// add for the gestion of the endianness of the file.
+//PlotStream::fBytes PlotStream::zott; //0123;
+//PlotStream::hBytes PlotStream::zottffss; //012345678;
+// ---- FH
+namespace bamg { class Triangles; }
+namespace Fem2D { void DrawIsoT(const R2 Pt[3],const R ff[3],const RN_ & Viso);
+   extern GTypeOfFE<Mesh3> &P1bLagrange3d;
+   extern GTypeOfFE<Mesh3> &RT03d;
+    extern GTypeOfFE<Mesh3> &Edge03d;
+void  Expandsetoflab(Stack stack,const CDomainOfIntegration & di,set<int> & setoflab,bool &all);
+}
+
+#include "BamgFreeFem.hpp"
+
+static bool TheWait=false;
+bool  NoWait=false;
+extern bool  NoGraphicWindow;
+
+extern long verbosity;
+extern FILE *ThePlotStream; //  Add for new plot. FH oct 2008
+void init_lgmesh() ;
+
+namespace FreeFempp {
+template<class R>
+ TypeVarForm<R> * TypeVarForm<R>::Global;
+}
+
+const int nTypeSolveMat=10;
+int kTypeSolveMat;
+TypeSolveMat *dTypeSolveMat[nTypeSolveMat];
+
+ AnyType Long2TypeSolveMat(Stack, const AnyType &ll) {
+      long l=GetAny<long>(ll);
+    ffassert( l>=0 && l <kTypeSolveMat);
+    return dTypeSolveMat[l];
+}
+ AnyType  TypeSolveMat2Long(Stack,const AnyType  &tt ) {
+     const TypeSolveMat *t = GetAny<TypeSolveMat *>(tt);
+    for(long l=0;  l <kTypeSolveMat; ++l)
+	if( t==dTypeSolveMat[l]) return l;
+    return long (kTypeSolveMat-1); // sparse solver case 
+}
+
+
+basicAC_F0::name_and_type  OpCall_FormBilinear_np::name_param[]= {
+{   "bmat",&typeid(Matrice_Creuse<R>* )},
+     LIST_NAME_PARM_MAT
+/*
+  {   "init", &typeid(bool)},
+  {   "solver", &typeid(TypeSolveMat*)},
+  {   "eps", &typeid(double) } ,
+  {   "precon",&typeid(Polymorphic*)}, 
+  {   "dimKrylov",&typeid(long)},
+  {   "bmat",&typeid(Matrice_Creuse<R>* )},
+  {   "tgv",&typeid(double )},
+  {   "factorize",&typeid(bool)},
+  {   "strategy",&typeid(long )},
+  {   "tolpivot", &typeid(double)},
+  {   "tolpivotsym", &typeid(double) },
+  {   "nbiter", &typeid(long)}, // 12   
+  {   "paramint",&typeid(KN_<long>)}, // Add J. Morice 02/09 
+  {   "paramdouble",&typeid(KN_<double>)},
+  {   "paramstring",&typeid(string*)},
+  {   "permrow",&typeid(KN_<long>)},
+  {   "permcol",&typeid(KN_<long>)},
+  {   "fileparamint",&typeid(string*)}, // Add J. Morice 02/09 
+  {   "fileparamdouble",&typeid(string*)},
+  {   "fileparamstring",&typeid(string* )},
+  {   "filepermrow",&typeid(string*)},
+  {   "filepermcol",&typeid(string*)} //22
+ */
+};
+
+
+basicAC_F0::name_and_type  OpCall_FormLinear_np::name_param[]= {
+  "tgv",&typeid(double )
+};
+
+
+/*
+template<class R,class TA0,class TA1,class TA2>
+ class E_F_F0F0F0 :public  E_F0 { public:
+   template <class T> struct remove_reference     {typedef T type;};
+   template <class T> struct remove_reference<T&> {typedef T type;};
+   typedef typename remove_reference<TA0>::type A0;
+   typedef typename remove_reference<TA1>::type A1;
+   typedef typename remove_reference<TA2>::type A2;
+   typedef  R (*func)( A0 , A1, A2 ) ;
+    
+  func f;
+  Expression a0,a1,a2;
+  E_F_F0F0F0(func ff,Expression aa0,Expression aa1,Expression aa2) 
+    : f(ff),a0(aa0),a1(aa1),a2(aa2) {}
+  AnyType operator()(Stack s)  const 
+    {return SetAny<R>( f( GetAny<A0>((*a0)(s)) , GetAny<A1>((*a1)(s)),  GetAny<A2>((*a2)(s)) ) );}  
+   bool EvaluableWithOutStack() const 
+      {return a0->EvaluableWithOutStack() && a1->EvaluableWithOutStack() && a2->EvaluableWithOutStack() ;} // 
+   bool MeshIndependent() const 
+      {return a0->MeshIndependent() && a1->MeshIndependent() && a2->MeshIndependent();} // 
+  int compare (const E_F0 *t) const { 
+     int rr;
+    // cout << "cmp " << typeid(*this).name() << " and " << typeid(t).name() << endl;
+     const  E_F_F0F0F0* tt=dynamic_cast<const E_F_F0F0F0 *>(t);
+     if (tt && f == tt->f) rr= clexico(a0->compare(tt->a0),a1->compare(tt->a1),a2->compare(tt->a2));
+     else rr = E_F0::compare(t);
+     return rr;
+     } // to give a order in instuction 
+
+      
+   int Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n) const
+    {
+
+       int rr = find(m);
+       if (rr) return rr;
+
+       return insert(new Opt(*this,a0->Optimize(l,m,n),a1->Optimize(l,m,n),a2->Optimize(l,m,n)),l,m,n);
+    }
+     // build optimisation
+
+     class Opt: public E_F_F0F0F0  { public :
+       size_t ia,ib,ic;  
+       Opt(const  E_F_F0F0F0 &t,size_t iaa,size_t ibb,size_t icc) 
+         : E_F_F0F0F0(t) ,
+         ia(iaa),ib(ibb),ic(icc) {}
+      AnyType operator()(Stack s)  const 
+       {
+         //A0 aa =*static_cast<A0 *>(static_cast<void*>(static_cast<char *>(s)+ia));
+         //A1 bb=*static_cast<A1 *>(static_cast<void*>(static_cast<char *>(s)+ib)) ;
+         //cout << ia << " " << ib <<  "f( " << aa << "," << bb  << " )   = "<< f(aa,bb) << endl;
+         return SetAny<R>( f( *static_cast<A0 *>(static_cast<void*>(static_cast<char *>(s)+ia)) , 
+                             *static_cast<A1 *>(static_cast<void*>(static_cast<char *>(s)+ib)) ,
+                             *static_cast<A2 *>(static_cast<void*>(static_cast<char *>(s)+ic)) 
+                             ) );}  
+         
+      };     
+       
+    
+};
+template<class R,class A=R,class B=A,class C=A,class CODE=E_F_F0F0F0<R,A,B,C> >
+class  OneOperator3 : public OneOperator {
+    aType r; //  return type 
+    typedef typename CODE::func func;
+    //typedef  R (*func)(A,B) ;
+    func f;
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new CODE(f,t[0]->CastTo(args[0]),t[1]->CastTo(args[1]),t[2]->CastTo(args[3]));} 
+    OneOperator3(func  ff): 
+      OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()],map_type[typeid(B).name()],map_type[typeid(C).name()]),
+      f(ff){}
+};
+*/
+const E_Array * Array(const C_F0 & a) { 
+  if (a.left() == atype<E_Array>() )
+    return dynamic_cast<const E_Array *>(a.LeftValue());
+  else 
+    return 0;
+}
+bool Box2(const C_F0 & bb, Expression * box)
+{
+  const E_Array * a= Array(bb);
+  if(a && a->size() == 2)
+   {
+    box[0] = to<double>((*a)[0]);
+    box[1] = to<double>((*a)[1]);
+    return true;
+    }
+  else 
+    return false;
+  
+}
+bool Box2x2(Expression  bb, Expression * box)
+{
+  const E_Array * a= dynamic_cast<const E_Array *>(bb);
+  if(a && a->size() == 2)
+     return Box2((*a)[0],box)  &&  Box2((*a)[1],box+2) ;
+  else 
+    return false;
+}
+void dump_table()
+{
+   cout << " dump the table of the language " << endl;
+   cout << " ------------------------------ " <<endl <<endl;
+	map<const string,basicForEachType *>::const_iterator i; ;
+	       
+	for (i= map_type.begin();i !=map_type.end();i++)
+	  {
+	   cout << " type : " << i->first << endl;
+	   if( i->second )
+	     i->second->ShowTable(cout);
+	   else cout << " Null \n";
+	   cout << "\n\n";     
+	  }
+
+	for (i= map_type.begin();i !=map_type.end();i++)
+	  {
+	   cout << " type : " << i->first << endl;
+	   if( i->second )
+	     i->second->ShowTable(cout);
+	   else cout << " Null \n";
+	   cout << "\n\n";    
+	   
+	  }
+	  
+	 cout << "--------------------- " << endl;
+	 cout << *TheOperators << endl;
+	 cout << "--------------------- " << endl;
+
+}
+/*
+ class LocalArrayVariable:public E_F0
+ { 
+  size_t offset;
+  aType t; //  type of the variable just for check  
+  Expression  n; // expression of the size 
+  public:
+  AnyType operator()(Stack s) const { 
+    SHOWVERB( cout << "\n\tget var " << offset << " " <<  t->name() << endl);  
+   return PtrtoAny(static_cast<void *>(static_cast<char *>(s)+offset),t);}
+  LocalArrayVariable(size_t o,aType tt,Expression nn):offset(o),t(tt),n(nn) {ffassert(tt);
+    SHOWVERB(cout << "\n--------new var " << offset << " " <<  t->name() << endl);
+    }
+};
+*/
+
+
+
+
+
+
+bool In(long *viso,int n,long v) 
+{
+  int i=0,j=n,k;
+  if  (v <viso[0] || v >viso[j-1]) 
+    return false;  
+  while (i<j-1)    
+   if ( viso[k=(i+j)/2]> v) j=k;
+   else i=k;
+  return (viso[i]=v);
+}
+
+
+
+class  LinkToInterpreter { public:
+ Type_Expr   P,N,x,y,z,label,region,nu_triangle,nu_edge,lenEdge,hTriangle,area,inside,volume;
+  LinkToInterpreter() ; 
+};
+
+LinkToInterpreter * l2interpreter;
+
+
+  using namespace Fem2D;
+  using namespace EF23;
+/*
+inline pmesh  ReadMesh( string * const & s) {
+  Mesh * m=new Mesh(*s);
+  R2 Pn,Px;
+  m->BoundingBox(Pn,Px);
+  m->quadtree=new FQuadTree(m,Pn,Px,m->nv);
+ //  delete s; modif FH 2006 (stack ptr)
+  return m;
+ }
+
+inline pmesh3  ReadMesh3( string * const & s) {
+  Mesh3 * m=new Mesh3(s->c_str());
+  R3 Pn,Px;
+  // m->BoundingBox(Pn,Px);
+  m->gtree=new Mesh3::GTree(m->vertices,m->Pmin,m->Pmax,m->nv);
+ //  delete s; modif FH 2006 (stack ptr)
+  return m;
+ }
+*/
+ 
+
+template<class Result,class A>
+class E_F_A_Ptr_o_R :public  E_F0 { public:
+  typedef Result A::* ptr;
+  Expression a0;
+  ptr p; 
+  E_F_A_Ptr_o_R(Expression aa0,ptr pp) 
+    : a0(aa0),p(pp) {}
+  AnyType operator()(Stack s)  const {
+    return SetAny<Result*>(&(GetAny<A*>((*a0)(s))->*p));}
+  bool MeshIndependent() const {return a0->MeshIndependent();} // 
+  
+};
+//  ----
+//  remarque pas de template, cela ne marche pas encore ......
+ class E_P_Stack_P   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<R3*>(&MeshPointStack(s)->P);} 
+    operator aType () const { return atype<R3*>();}         
+    
+}; 
+ class E_P_Stack_Px   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<R*>(&MeshPointStack(s)->P.x);} 
+    operator aType () const { return atype<R*>();}         
+    
+}; 
+ class E_P_Stack_Py   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const {throwassert(* (long *) s);
+    return SetAny<R*>(&MeshPointStack(s)->P.y);} 
+    operator aType () const { return atype<R*>();}         
+    
+}; 
+ class E_P_Stack_Pz   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<R*>(&MeshPointStack(s)->P.z);} 
+    operator aType () const { return atype<R*>();}         
+    
+}; 
+
+ class E_P_Stack_N   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<R3*>(&MeshPointStack(s)->N);} 
+        operator aType () const { return atype<R3*>();}         
+
+}; 
+ class E_P_Stack_Nx   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<R*>(&MeshPointStack(s)->N.x);} 
+    operator aType () const { return atype<R*>();}         
+    
+}; 
+ class E_P_Stack_Ny   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<R*>(&MeshPointStack(s)->N.y);} 
+    operator aType () const { return atype<R*>();}             
+}; 
+ class E_P_Stack_Nz   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<R*>(&MeshPointStack(s)->N.z);} 
+    operator aType () const { return atype<R*>();}         
+    
+}; 
+
+ class E_P_Stack_Region   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<long*>(&MeshPointStack(s)->region);} 
+    operator aType () const { return atype<long*>();}         
+    
+}; 
+ class E_P_Stack_Label   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<long*>(&MeshPointStack(s)->label);} 
+    operator aType () const { return atype<long *>();}         
+    
+}; 
+ class E_P_Stack_Mesh   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<pmesh >(const_cast<pmesh>(MeshPointStack(s)->Th));} 
+  operator aType () const { return atype<pmesh>();}         
+
+}; 
+ class E_P_Stack_Nu_Triangle   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<long>(MeshPointStack(s)->t);} 
+    operator aType () const { return atype<long>();}         
+    
+}; 
+ class E_P_Stack_Nu_Vertex   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<long>(MeshPointStack(s)->v);} 
+    operator aType () const { return atype<long>();}         
+    
+}; 
+ class E_P_Stack_Nu_Face   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<long>(MeshPointStack(s)->f);} 
+    operator aType () const { return atype<long>();}         
+    
+}; 
+ class E_P_Stack_Nu_Edge   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<long>(MeshPointStack(s)->e);} 
+    operator aType () const { return atype<long>();}         
+    
+}; 
+ class E_P_Stack_inside   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    return SetAny<double>(MeshPointStack(s)->outside? 0.0 : 1.0 );} 
+    operator aType () const { return atype<double>();}         
+    
+}; 
+
+class E_P_Stack_lenEdge   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    MeshPoint * mp=MeshPointStack(s);      
+    ffassert(mp->T && mp ->e >=0 && mp->d==2);
+    double l= mp->T->lenEdge(mp->e);
+    return SetAny<double>(l);} 
+    operator aType () const { return atype<double>();}         
+    
+}; 
+
+class E_P_Stack_hTriangle   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    MeshPoint * mp=MeshPointStack(s);
+    assert(mp->T) ;
+    double l= mp->T->h();
+    return SetAny<double>(l);} 
+    operator aType () const  { return atype<double>();}         
+    
+};
+
+class E_P_Stack_nTonEdge   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    MeshPoint * mp=MeshPointStack(s);
+    assert(mp->T && mp->e > -1 && mp->d==2 ) ;
+    long l=mp->Th->nTonEdge(mp->t,mp->e);
+    // cout << " nTonEdge " << l << endl;
+    return SetAny<long>( l) ;} 
+    operator aType () const  { return atype<long>();}         
+    
+}; 
+
+class E_P_Stack_areaTriangle   :public  E_F0mps { public: 
+  AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+    MeshPoint * mp=MeshPointStack(s);
+    assert(mp->T) ;
+      double l=-1; // unset ...
+    if(mp->d==2)	
+      l= mp->T->area;	
+    else if (mp->d==3 && mp->f >=0)
+      {	
+	  R3 NN = mp->T3->N(mp->f);
+	  l= NN.norme()/2.;
+      }
+    else 
+      {
+	  cout << "erreur : E_P_Stack_areaTriangle" << mp->d << " " << mp->f << endl;
+	  ffassert(0); // undef 
+      }
+    return SetAny<double>(l);} 
+    operator aType () const { return atype<double>();}         
+    
+}; 
+
+// add FH
+class E_P_Stack_VolumeTet   :public  E_F0mps { public: 
+    AnyType operator()(Stack s)  const { throwassert(* (long *) s);
+	MeshPoint * mp=MeshPointStack(s);
+	assert(mp->T) ;
+	double l=-1; // unset ...
+	if (mp->d==3 && mp->T3 )
+	  {	
+	      l= mp->T3->mesure();
+	  }
+	else 
+	  {
+	    cout << "erreur : E_P_Stack_VolumeTet" << mp->d << " " << mp->f << endl;
+	    ffassert(0); // undef 
+	  }
+	return SetAny<double>(l);} 
+    operator aType () const { return atype<double>();}         
+    
+}; 
+
+/*
+class New_MeshPoint : public E_F0mps {
+
+};*/
+
+
+ 
+
+ 
+//inline pfes MakePtr(pmesh * const &  a, TypeOfFE * const & tef){ return pfes(new pfes_tef(a,tef)) ;}
+//inline pfes MakePtr(pmesh * const &  a){ return pfes(new pfes_tef(a,&P1Lagrange)) ;}
+//inline pfes MakePtr(pfes * const &  a,long const & n){ return pfes(new pfes_fes(a,n)) ;}
+/*
+class E_pfes : public E_F0 {
+  const int N;
+  Expression *Th,*tef; 
+  E_pfes(Expression *TTh,*ttef) : Th(TTh),tef(ttef),N(ttef?ttef->nbitem():0) {}
+   virtual AnyType operator()(Stack)  const {
+   return AnyType<pfes*>
+  }
+  
+  virtual size_t nbitem() const {return 1;}  
+};
+  OneOperator_pfes():OneOperator(atype<void>(),atype<E_Array>(),atype<E_Array>()) {}
+    E_F0 * code(const basicAC_F0 & args) const ; 
+  
+};*/
+template<class R>
+class  E_StopGC: public StopGC<R> {
+public:
+    typedef KN<R> Kn;
+    typedef KN_<R> Kn_;
+
+    Stack s;
+    long n;
+    long iter;
+    Kn_ xx,gg;
+    C_F0 citer,cxx,cgg;
+    C_F0 stop;
+    
+    E_StopGC(Stack ss,long nn,const  Polymorphic * op): s(ss),n(nn),iter(-1),
+    xx(0,0),gg(0,0),
+    citer(CConstant<long*>(&iter)),
+    cxx(dCPValue(&xx)),
+    cgg(dCPValue(&gg)),
+    stop(op,"(",citer,cxx,cgg)
+    {
+        
+    }
+    ~E_StopGC()
+    {//  a verifier ???? FH....
+        delete (E_F0 *) cxx; // ???
+        delete (E_F0 *) cgg; // ???
+        delete (E_F0 *) citer; // ???
+        delete (E_F0 *) stop; // ???
+    }
+    // template<class R> class StopGC { public: virtual  bool Stop(int iter, R *, R * ){return false;} };
+    bool Stop(int iterr, R *x, R * g)
+    {
+        // cout << " Stop " << iterr << endl;
+        iter=iterr;
+        xx.set(x,n);
+        gg.set(g,n);
+        return GetAny<bool>(stop.eval(s));
+    }
+};
+
+
+template<class R>
+class LinearCG : public OneOperator
+{ public:
+  typedef KN<R> Kn;
+  typedef KN_<R> Kn_;
+  const int cas;
+
+ class MatF_O: VirtualMatrice<R> { public:
+   Stack stack;
+   mutable  Kn x;
+   C_F0 c_x;
+  
+   Expression  mat1,mat;
+   typedef  typename VirtualMatrice<R>::plusAx plusAx;
+   MatF_O(int n,Stack stk,const OneOperator * op) 
+     : VirtualMatrice<R>(n),stack(stk),
+       x(n),c_x(CPValue(x)),
+       mat1(op->code(basicAC_F0_wa(c_x))),
+       mat( CastTo<Kn_>(C_F0(mat1,(aType)*op))) {
+         //ffassert(atype<Kn_ >() ==(aType) *op);
+         // WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+         
+         }
+   ~MatF_O() { 
+     // cout << " del MatF_O mat " << endl;
+     if(mat1 != mat) 
+       delete mat;
+      delete mat1;
+     // cout << " del MatF_Ocx ..." <<  endl;
+      Expression zzz = c_x;
+     // cout << " zzz "<< zzz << endl;
+     delete zzz;
+    // WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+     
+     }
+   void addMatMul(const  Kn_  & xx, Kn_ & Ax) const { 
+      ffassert(xx.N()==Ax.N());
+      x =xx;
+      Ax  += GetAny<Kn_>((*mat)(stack));
+      WhereStackOfPtr2Free(stack)->clean();
+       } 
+    plusAx operator*(const Kn &  x) const {return plusAx(this,x);} 
+  virtual bool ChecknbLine(int n) const { return true;}  
+  virtual bool ChecknbColumn(int m) const { return true;} 
+    
+};  
+
+  class E_LCG: public E_F0mps { public:
+      
+      
+   const int cas;// <0 => Nolinear
+   static const int n_name_param=6;
+
+   static basicAC_F0::name_and_type name_param[] ;
+
+
+  Expression nargs[n_name_param];
+   
+  const OneOperator *A, *C; 
+  Expression X,B;
+
+      
+  E_LCG(const basicAC_F0 & args,int cc) :cas(cc)
+   {
+      args.SetNameParam(n_name_param,name_param,nargs);
+      {  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+         ffassert(op);
+         A = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); }
+      if (nargs[2]) 
+      {  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(nargs[2]);
+         ffassert(op); 
+         C = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); }
+       else  C =0;
+      X = to<Kn*>(args[1]);
+      if (args.size()>2)
+        B = to<Kn*>(args[2]);
+      else 
+        B=0;
+   }
+     
+     virtual AnyType operator()(Stack stack)  const {
+       int ret=-1;
+       E_StopGC<R> *stop=0;
+      // WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+      try {
+      Kn &x = *GetAny<Kn *>((*X)(stack));
+      int n=x.N();
+      MatF_O AA(n,stack,A);
+      double eps = 1.0e-6;
+	  double *veps=0;
+      int nbitermax=  100;
+      long verb = verbosity;
+      
+      if (nargs[0]) eps= GetAny<double>((*nargs[0])(stack));
+      if (nargs[1]) nbitermax = GetAny<long>((*nargs[1])(stack));
+      if (nargs[3]) veps=GetAny<double*>((*nargs[3])(stack));
+      if (nargs[4]) verb=Abs(GetAny<long>((*nargs[4])(stack)));
+      if (nargs[5]) stop= new E_StopGC<R>(stack,n,dynamic_cast<const  Polymorphic *>(nargs[5]));
+//          cout << " E_LCG: Stop = " << stop << " " << verb << endl;
+      long gcverb=51L-Min(Abs(verb),50L);
+      if(verb==0) gcverb = 1000000000;// no print 
+      if(veps) eps= *veps;
+      KN<R>  bzero(B?1:n); // const array zero
+      bzero=R(); 
+      KN<R> *bb=&bzero; 
+      if (B) {
+        Kn &b = *GetAny<Kn *>((*B)(stack));
+        R p = (b,b);
+       if (p== R()) 
+         {
+          // ExecError("Sorry LinearCG work only with nul right hand side, so put the right hand in the function");
+          }
+         bb = &b;
+      }
+      if (cas<0) {
+       if (C) 
+         { MatF_O CC(n,stack,C);
+           ret = NLCG(AA,CC,x,nbitermax,eps, gcverb,stop );}
+        else 
+           ret = NLCG(AA,MatriceIdentite<R>(n),x,nbitermax,eps, gcverb,stop);
+        }
+      else 
+      if (C) 
+       { MatF_O CC(n,stack,C);
+         ret = ConjuguedGradient2(AA,CC,x,*bb,nbitermax,eps, gcverb, stop );}
+      else 
+         ret = ConjuguedGradient2(AA,MatriceIdentite<R>(n),x,*bb,nbitermax,eps, gcverb, stop );
+      if(veps) *veps = -(eps);
+      }
+      catch(...)
+      {
+       if( stop) delete stop;
+       // WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+        throw;
+      }
+     // WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005 
+     if( stop) delete stop;
+         
+      return SetAny<long>(ret);
+       
+     }  
+    operator aType () const { return atype<long>();}         
+     
+  };
+  
+  E_F0 * code(const basicAC_F0 & args) const {
+    return new E_LCG(args,cas);}
+  LinearCG() :   OneOperator(atype<long>(),
+                             atype<Polymorphic*>(),
+                             atype<KN<R> *>(),atype<KN<R> *>()),cas(2){}
+  LinearCG(int cc) :   OneOperator(atype<long>(),
+                             atype<Polymorphic*>(),
+                             atype<KN<R> *>()),cas(cc){}
+   
+};
+
+
+template<class R>
+basicAC_F0::name_and_type  LinearCG<R>::E_LCG::name_param[]= {
+  {   "eps", &typeid(double)  },
+  {   "nbiter",&typeid(long) },
+  {   "precon",&typeid(Polymorphic*)},
+  {   "veps" ,  &typeid(double*) },
+  {   "verbosity" ,  &typeid(long)},
+  {   "stop" ,  &typeid(Polymorphic*)}
+};
+
+
+template<class R>
+class LinearGMRES : public OneOperator 
+{ public:
+  typedef KN<R> Kn;
+  typedef KN_<R> Kn_;
+  const int cas;
+
+ class MatF_O: VirtualMatrice<R> { public:
+   Stack stack;
+   mutable  Kn x;
+   C_F0 c_x;
+   Kn *b;
+   Expression  mat1,mat;
+   typedef  typename VirtualMatrice<R>::plusAx plusAx;
+   MatF_O(int n,Stack stk,const OneOperator * op,Kn *bb) 
+     : VirtualMatrice<R>(n),
+       stack(stk),
+       x(n),c_x(CPValue(x)),b(bb),
+       mat1(op->code(basicAC_F0_wa(c_x))), 
+       mat( CastTo<Kn_>(C_F0(mat1,(aType)*op))  /*op->code(basicAC_F0_wa(c_x))*/) {
+      // ffassert(atype<Kn_ >() ==(aType) *op);
+       }
+     ~MatF_O() { if(mat1!=mat) delete mat; delete mat1; delete c_x.LeftValue();}
+   void addMatMul(const  Kn_  & xx, Kn_ & Ax) const { 
+      ffassert(xx.N()==Ax.N());
+      x =xx;
+      Ax  += GetAny<Kn_>((*mat)(stack));
+      if(b && &Ax!=b) Ax += *b; // Ax -b => add b (not in cas of init. b c.a.d  &Ax == b
+      WhereStackOfPtr2Free(stack)->clean(); //  add dec 2008
+   } 
+    plusAx operator*(const Kn &  x) const {return plusAx(this,x);} 
+  virtual bool ChecknbLine(int n) const { return true;}  
+  virtual bool ChecknbColumn(int m) const { return true;} 
+    
+};  
+ 
+
+  class E_LGMRES: public E_F0mps { public:
+   const int cas;// <0 => Nolinear
+   static basicAC_F0::name_and_type name_param[] ;
+   static const int n_name_param =7;
+   Expression nargs[n_name_param];
+  const OneOperator *A, *C; 
+  Expression X,B;
+
+  E_LGMRES(const basicAC_F0 & args,int cc) :cas(cc)
+   {
+      args.SetNameParam(n_name_param,name_param,nargs);
+      {  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(args[0].LeftValue());
+         ffassert(op);
+         A = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); }
+      if (nargs[2]) 
+      {  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(nargs[2]);
+         ffassert(op); 
+         C = op->Find("(",ArrayOfaType(atype<Kn* >(),false)); }
+       else  C =0;
+      X = to<Kn*>(args[1]);
+      if (args.size()>2)
+        B = to<Kn*>(args[2]);
+      else 
+        B=0;
+   }
+     
+     virtual AnyType operator()(Stack stack)  const {
+      Kn &x = *GetAny<Kn *>((*X)(stack));
+      Kn b(x.n);
+       E_StopGC<R> *stop=0;
+      if (B)   b = *GetAny<Kn *>((*B)(stack));
+      else     b= R();
+      int n=x.N();
+      int dKrylov=50;
+      double eps = 1.0e-6;
+      int nbitermax=  100;
+      long verb = verbosity;
+      if (nargs[0]) eps= GetAny<double>((*nargs[0])(stack));
+      if (nargs[1]) nbitermax = GetAny<long>((*nargs[1])(stack));
+      if (nargs[3]) eps= *GetAny<double*>((*nargs[3])(stack));
+      if (nargs[4]) dKrylov= GetAny<long>((*nargs[4])(stack));
+      if (nargs[5]) verb=Abs(GetAny<long>((*nargs[5])(stack)));
+      if (nargs[6]) stop= new E_StopGC<R>(stack,n,dynamic_cast<const  Polymorphic *>(nargs[6]));
+
+	 long gcverb=51L-Min(Abs(verb),50L);
+	 
+     
+      int ret;
+      if(verbosity>4)
+        cout << "  ..GMRES: eps= " << eps << " max iter " << nbitermax 
+             << " dim of Krylov space " << dKrylov << endl;
+        KNM<R> H(dKrylov+1,dKrylov+1);
+	int k=dKrylov;//,nn=n;
+       double epsr=eps;
+ 
+         KN<R>  bzero(B?1:n); // const array zero
+         bzero=R();
+         KN<R> *bb=&bzero;
+         if (B) {
+             Kn &b = *GetAny<Kn *>((*B)(stack));
+             R p = (b,b);
+             if (p)
+             {
+                 // ExecError("Sorry MPILinearCG work only with nul right hand side, so put the right hand in the function");
+             }
+             bb = &b;
+         }
+         KN<R> * bbgmres =0;
+         if ( !B ) bbgmres=bb; // none zero if gmres without B
+         MatF_O AA(n,stack,A,bbgmres);
+         if(bbgmres ){
+             *bbgmres= AA* *bbgmres; // Ok Ax == b -> not translation of b .
+             *bbgmres = - *bbgmres;
+             if(verbosity>1) cout << "  ** GMRES set b =  -A(0);  : max=" << bbgmres->max() << " " << bbgmres->min()<<endl;
+         }
+
+
+      //cout << " ** GMRES  bb max=" << bb->max() << " " << bb->min()<<endl;
+      if (cas<0) {
+        ErrorExec("NL GMRES:  to do! sorry ",1);
+/*       if (C) 
+         { MatF_O CC(n,stack,C);
+           ret = NLGMRES(AA,CC,x,nbitermax,eps, 51L-Min(Abs(verbosity),50L) );}
+        else 
+           ret = NLGMRES(AA,MatriceIdentite<R>(n),x,nbitermax,eps, 51L-Min(Abs(verbosity),50L));
+         ConjuguedGradient  */
+        }
+      else 
+       {
+       if (C)
+        { MatF_O CC(n,stack,C,0);
+         ret=GMRES(AA,(KN<R> &)x, *bb,CC,H,k,nbitermax,epsr,verb,stop);}
+       else
+         ret=GMRES(AA,(KN<R> &)x, *bb,MatriceIdentite<R>(n),H,k,nbitermax,epsr,verb,stop);
+       }
+      if(verbosity>99)    cout << " Sol GMRES :" << x << endl;
+         if(stop) delete stop;
+      return SetAny<long>(ret);
+       
+     }  
+    operator aType () const { return atype<long>();}         
+     
+  };
+  
+  E_F0 * code(const basicAC_F0 & args) const {
+    return new E_LGMRES(args,cas);}
+  LinearGMRES() :   OneOperator(atype<long>(),
+                             atype<Polymorphic*>(),
+                             atype<KN<R> *>(),atype<KN<R> *>()),cas(2){}
+  LinearGMRES(int cc) :   OneOperator(atype<long>(),
+                             atype<Polymorphic*>(),
+                             atype<KN<R> *>()),cas(cc){}
+   
+};
+
+
+template<class R>
+basicAC_F0::name_and_type  LinearGMRES<R>::E_LGMRES::name_param[]= {
+  {   "eps", &typeid(double)  },
+  {   "nbiter",&typeid(long) },
+  {   "precon",&typeid(Polymorphic*)},
+  {   "veps" ,  &typeid(double*) },
+  {   "dimKrylov", &typeid(long) },
+  {   "verbosity", &typeid(long) },
+  {   "stop" ,  &typeid(Polymorphic*)}
+};
+
+template<typename int2>
+typename map<int,int2>::iterator closeto(map<int,int2> & m, int k)
+ {
+  typename map<int,int2>::iterator i=  m.find(k);
+   if (i==m.end()) 
+    {
+     i=  m.find(k+1);
+     if (i==m.end()) 
+      i=  m.find(k-1);
+    }
+   return i;
+ }
+
+
+
+template<class T,int N>
+class Smallvect { public: 
+ T v[N];
+ T & operator[](int i){return v[i];}
+ const T & operator[](int i) const {return v[i];}
+};
+template<class T,int N>
+ostream & operator<<(ostream & f,const Smallvect<T,N> & v)
+{
+    for(int i=0;i<N;++i)  f << v[i] << ' ';
+    return f;
+}
+
+template<class T> 
+int numeroteclink(KN_<T> & ndfv) 
+{
+         int nbdfv =0;
+         for (int i=0;i<ndfv.N();i++)
+           if (ndfv[i]>=i)
+           {
+             int j=i,ii,kkk=0;
+             
+             do {
+               ii=ndfv[j];
+		 ffassert(kkk++<10);
+	       assert(nbdfv <= j);
+             //  assert(ii>=nbdfv);
+               ndfv[j]=nbdfv ;
+               j=ii;
+               }             
+             while (j!=nbdfv);
+             if (verbosity > 100) 
+             cout << "    ndf: " <<  j << " " <<  ii  << " <- " << nbdfv << " " <<  kkk <<  endl;
+              nbdfv++;
+           }
+       return nbdfv;
+}
+
+bool  InCircularList(const int *p,int i,int k)
+//  find k in circular list:  i , p[i], p[p[i]], ... 
+{ 
+    int j=i,l=0;    
+    do {
+	if (j==k) return true;
+	ffassert(l++<10);
+        j=p[j];
+    } while (j!=i);    
+    return false;
+}
+
+bool BuildPeriodic( 
+  int nbcperiodic,
+  Expression *periodic,
+  const Mesh &Th,Stack stack,
+  int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe) { 
+  
+/*
+  build numbering of vertex form 0 to nbdfv-1
+  and build numbering  of  edge form 0 to nbdfe-1
+  we removing common vextex or common edge    
+  --  we suppose one df by vertex 
+      nbdfv number of df on vertex 
+      ndfv[i]  given the numero of the df of the vertex 
+  -- we suppose 1 df
+*/  
+   typedef Smallvect<int,2> int2;    
+    if (nbcperiodic ) {
+      
+   //    KN<int> ndfv(Th.nv);
+    //   KN<int> ndfe(Th.neb);
+       ffassert(ndfv.N()==Th.nv);
+       ffassert(ndfe.N()==Th.neb);
+        
+       MeshPoint *mp=MeshPointStack(stack),smp=*mp;   
+       int n= nbcperiodic;
+       if (verbosity >2)
+         cout << " Nb of pair of periodic conditions: = " << n <<  endl;
+       int * link1=0;
+       int * link2=0;
+       KN<int*> plk1(n),plk2(n);
+       KN<int> nlk1(n),nlk2(n);
+       KN<int> lab1(n),lab2(n);
+#ifndef  HUGE_VAL      
+       const double infty= numeric_limits<double>::infinity();
+#else
+       const double infty= HUGE_VAL;
+#endif       
+       int nblink1, nblink2;
+       int *plink1 , *plink2;
+        for (int step=0;step<2;step++)
+         {
+           nblink1=0,     nblink2=0;
+           plink1=link1,  plink2=link2;
+           for (int ip=0, k=0;ip<n;ip++,k+=4)
+            {
+               int label1=GetAny<long>((*periodic[k+0])(stack));
+               int label2=GetAny<long>((*periodic[k+2])(stack));
+               lab1[ip]=label1;
+               lab2[ip]=label2;
+               
+               int l1=nblink1;
+               int l2=nblink2;
+               plk1[ip]= plink1;
+               plk2[ip]= plink2;
+               
+               for (int ke=0;ke<Th.neb;ke++)
+                {
+                 if (Th.bedges[ke].lab==label1)
+                  {
+                    if (plink1) *plink1++=ke;
+                    nblink1++;
+                  }
+                 else if (Th.bedges[ke].lab==label2)
+                  {
+                    if (plink2) *plink2++=ke;
+                    nblink2++;
+                   }
+                 }
+               nlk1[ip]= nblink1-l1;
+               nlk2[ip]= nblink2-l2;              
+            }
+            if(step) break; // no reallocl 
+            if (verbosity >3)
+            cout << "  Periodic = " << nblink1 << " " << nblink2 << " step=" << step << endl;
+            link1 = new int[nblink1];
+            link2 = new int[nblink2];
+            if(nblink1 != nblink2)
+            {
+             ExecError("Periodic:  the both number of edges is not the same ");
+            }
+         }
+        if ( nblink1 >0) 
+        {
+        for (int ip=0, k=0;ip<n;ip++,k+=4)
+          {
+            map<int,int2> m;
+            const int kk1=1,kk2=3;
+            int label1=lab1[ip],label2=lab2[ip];
+            int n1=nlk1[ip],n2=nlk2[ip];
+            int *pke1=plk1[ip], *pke2=plk2[ip];
+            double xmn=infty,xmx=-infty,hmn=infty;
+            if (verbosity >1)
+            cout << "  --Update: periodic  couple label1= " << label1 << ", n edges= " << n1 << "; "
+                                          << ", label2= " << label2<<  ", n edges= " << n2 <<endl; 
+            if (n1 != n2) ExecError("periodic BC:  the number of edges is not the same");
+            for (int i1=0;i1<n1;i1++)
+             {
+              const BoundaryEdge & e =Th.bedges[pke1[i1]];
+              if (e.lab==label1) 
+                {           
+                 mp->set(e[0].x,e[0].y);
+                 double x0=GetAny<double>((*periodic[k+kk1])(stack));
+                 mp->set(e[1].x,e[1].y);
+                 double x1=GetAny<double>((*periodic[k+kk1])(stack));
+		 if(verbosity>5)
+			cout << "lab1:  e[" << pke1[i1] << "]  v0:   " <<  e[0].x << " " << e[0].y << "  s = " << x0
+			<< "\t v1 " <<  e[0].x << " " << e[0].y << "  s = " << x1 << endl;
+		    xmn=Min(x1,x0,xmn);
+                 xmx=Max(x1,x0,xmx); 
+                 hmn=Min(hmn,Abs(x1-x0));
+               }                                
+             }
+            ffassert(hmn>1.0e-20);
+            double coef = 8/hmn;
+            double x0 = xmn;
+            if (verbosity > 2)
+            cout << "  --Update: periodic " << xmn << " " << xmx << " " << " h=" << hmn << endl;
+            ffassert(coef>1e-10 && (xmx-xmn)*coef < 1.e7 );
+             
+           //  map construction ----
+           for (int i1=0;i1<n1;i1++)
+             {
+              int ie=pke1[i1];
+              const BoundaryEdge & e =Th.bedges[pke1[i1]];
+              if (e.lab==label1)
+                 for (int ne=0;ne<2;ne++)
+                  {
+                   int2 i2;
+                   i2[0]=ie;
+                   i2[1]=-1;
+                   mp->set(e[ne].x,e[ne].y);
+                   double xx=GetAny<double>((*periodic[k+kk1])(stack));
+                   int i0= (int) ((xx-x0)*coef);
+                   map<int,int2>::iterator im=closeto(m,i0);
+                   if (im==m.end())
+                    {
+                     if (verbosity >50)
+                      cout << xx << " " << i0 << " " << ie << endl;
+                     im=m.insert(pair<int,int2>(i0,i2)).first;
+                    }
+                   else {
+                     if (verbosity >50)
+                     cout << xx << " " << i0 << " " << ie << " :  " << im->second[0] << " " << im->second[1] << endl;
+                    assert( (im->second[1] < 0) && (im->second[0] >=0) );
+                    im->second[1]=ie;}
+                   
+               }                                
+             }
+            
+            for (int i2=0;i2<n2;i2++)
+             {
+              int ie2=pke2[i2];
+              const BoundaryEdge & e =Th.bedges[ie2];
+              if (e.lab==label2)
+                {
+		if (verbosity >50)
+                    cout << i2 << " : " <<Th(e[0]) << " " << Th(e[1]) << ":: ";
+                 mp->set(e[0].x,e[0].y);
+                 double xx0=GetAny<double>((*periodic[k+kk2])(stack));
+                 mp->set(e[1].x,e[1].y);
+                 double xx1=GetAny<double>((*periodic[k+kk2])(stack));
+		 if(verbosity>5 && !(verbosity >50))
+		      cout << "lab2:  e[" << pke2[i2] << "]  v0:   " <<  e[0].x << " " << e[0].y << "  s = " << xx0
+		      << "\t v1 " <<  e[0].x << " " << e[0].y << "  s = " << xx1 << endl;
+		    
+                 int i0= int((xx0-x0)*coef);
+                 int i1= int((xx1-x0)*coef);
+                 map<int,int2>::iterator im0=closeto(m,i0);
+                 map<int,int2>::iterator im1=closeto(m,i1);
+                 if(im0 == m.end() || im1 == m.end() )
+                 	{ 
+			
+			  cout << "Abscisse: s0 = "<< xx0 << " <==> s1 " << xx1  <<endl; 
+			  ExecError("periodic: Sorry one vertex of edge is losted "); }
+                  int ie1=-1;
+                 if      (((ie1=im0->second[0])==im1->second[1]) && (ie1>=0)) ;
+                 else if (((ie1=im0->second[0])==im1->second[1]) && (ie1>=0)) ;
+                 else if (((ie1=im0->second[1])==im1->second[1]) && (ie1>=0)) ;
+                 else if (((ie1=im0->second[1])==im1->second[0]) && (ie1>=0)) ;
+                 else if (((ie1=im0->second[0])==im1->second[0]) && (ie1>=0)) ;
+                 else
+                  {
+                   cout << ie2 << " ~ " << im0->second[0] << " " << im0->second[1] << ", " 
+                                        << im1->second[0] << " " << im1->second[1] << endl;
+                   ExecError("periodic: Sorry one egde is losted "); }
+		 if(verbosity>50)
+		   cout << " ( " << im0->second << " , " << im1->second << " ) .. ";
+		 ffassert(ie1>=0 && ie1 < Th.neb );
+                 const BoundaryEdge & ep =Th.bedges[ie1];
+                 mp->set(ep[0].x,ep[0].y);
+                 double yy0=GetAny<double>((*periodic[k+kk1])(stack));
+                 mp->set(ep[1].x,ep[1].y);
+                 double yy1=GetAny<double>((*periodic[k+kk1])(stack));
+		if(verbosity>50)
+			cout << " e0: s  "<< xx0 << " " << xx1 << "e1 s "<< yy0 << " " << yy1  ; 
+                 
+                 pke1[i2]=ie1*2+ ( ( (yy1-yy0) < 0)  == ( (xx1-xx0) < 0) ) ;
+		    
+                 if (verbosity >50)
+                 cout << " \t  edge " << ie1 << " <=> " << ie2 << " " 
+                      << ( ( (yy1-yy0) < 0)  == ( (xx1-xx0) < 0) ) << "; "
+                      << xx0 << " " <<xx1<<" <=> "  << yy0 << " " <<yy1<< 
+                      "  ::  " <<  Th(ep[0]) << " " << Th(ep[1]) << endl ;
+
+                }
+              }
+              
+             
+          }
+          
+        *mp = smp;
+        for (int i=0;i<Th.neb;i++)
+            ndfe[i]=i;// circular link
+        for (int i=0;i<Th.nv;i++)
+          ndfv[i]=i;// circular link
+        for (int i=0;i<nblink1;i++)
+         {
+           int ie1=link1[i]/2;
+           int sens = link1[i]%2;
+           int ie2=link2[i];
+           assert(ie1!=ie2);
+	   if(!InCircularList(ndfe,ie1,ie2))   // merge of two list 
+	      Exchange(ndfe[ie1],ndfe[ie2]);
+	   for (int ke2=0;ke2<2;ke2++)
+             {
+                int ke1=ke2;
+                if(!sens) ke1=1-ke1; 
+                int iv1=Th(Th.bedges[ie1][ke1]);
+                int iv2=Th(Th.bedges[ie2][ke2]);
+                if (!InCircularList(ndfv,iv1,iv2)) {  // merge of two list 
+		   Exchange(ndfv[iv2],ndfv[iv1]);
+                   if (verbosity >50)
+		   { 
+		     cout << "  vertex " << iv1 <<  "<==> " << iv2 << " list : " << iv1;
+		     int i=iv1,k=0;
+		     while ( (i=ndfv[i]) != iv1 && k++<10)
+			 cout << ", "<< i ; 
+		       cout << endl;
+		   }}                  
+             }
+            
+         } 
+         // generation de numero de dlt
+         
+          nbdfv = numeroteclink(ndfv) ; 
+          nbdfe = numeroteclink(ndfe) ; 
+          if (verbosity>2) 
+            cout << "  -- nb df on vertices " << nbdfv << endl;
+        delete [] link1;
+        delete [] link2;
+        return true; //new FESpace(**ppTh,*tef,nbdfv,ndfv,nbdfe,ndfe);
+      }
+   }
+   return false;   
+}
+
+
+bool  v_fes::buildperiodic(Stack stack,int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe) { 
+  return BuildPeriodic(nbcperiodic,periodic,**ppTh,stack,nbdfv,ndfv,nbdfe,ndfe);
+
+}
+#ifdef ZZZZZZZZ
+FESpace * pfes_tef::update() { 
+   typedef Smallvect<int,2> int2; 
+    
+    if (nbcperiodic ) {
+       const Mesh &Th(**ppTh);
+       KN<int> ndfv(Th.nv);
+       KN<int> ndfe(Th.neb);
+       int nbdfv,nbdfe;
+        return  new FESpace(**ppTh,*tef,nbdfv,ndfv,nbdfe,ndfe);
+      }
+     else 
+       return  new FESpace(**ppTh,*tef);
+}
+#endif
+
+struct OpMake_pfes_np {
+  static const int n_name_param =1;
+  static basicAC_F0::name_and_type name_param[] ;
+};
+
+basicAC_F0::name_and_type  OpMake_pfes_np::name_param[]= {
+  "periodic", &typeid(E_Array) 
+};
+
+map<TypeOfFE *,TypeOfFE3 *> TEF2dto3d;
+AnyType TypeOfFE3to2(Stack,const AnyType &b) { 
+    TypeOfFE3 *t3=0;
+    TypeOfFE  *t2=GetAny<TypeOfFE *>(b);
+    map<TypeOfFE *,TypeOfFE3 *>::const_iterator i=TEF2dto3d.find(t2);
+    if(i != TEF2dto3d.end())
+	t3=i->second;
+    
+    if(t3==0)
+      {
+	  cerr << " sorry no cast to this 3d finite element " <<endl;
+	  ExecError( " sorry no cast to this 3d finite element ");
+      }
+    return t3;
+}
+
+/*
+ for (ListOfTFE * i=ListOfTFE::all;i;i=i->next)
+ {
+ ffassert(i->tfe); // check 
+ AddNewFE(i->name,i->tfe);
+ // Global.New(i->name, Type_Expr(atype<TypeOfFE*>(),new  EConstantTypeOfFE(i->tfe)));
+ }
+ 
+ */
+TypeOfFE * FindFE2(const char * s)
+{
+    for (ListOfTFE * i=ListOfTFE::all;i;i=i->next)
+	if(strcmp(i->name,s)==0)
+	    return i->tfe;
+    cout << " s =" << s << endl;
+    lgerror("FindFE2 ");
+    return 0;
+}
+
+
+typedef TypeOfFE TypeOfFE2;
+template<class pfes,class Mesh,class TypeOfFE,class pfes_tefk>
+struct OpMake_pfes: public OneOperator , public OpMake_pfes_np { 
+  
+  struct Op: public E_F0mps { 
+  public:
+    
+    Expression eppTh;
+    Expression eppfes;
+    const E_Array & atef;
+    int nb;
+    int nbcperiodic;
+    Expression *periodic;
+    KN<int>  tedim;
+    Op(Expression ppfes,Expression ppTh, const E_Array & aatef,int nbp,Expression * pr,KN<int> &ttedim) 
+      : eppTh(ppTh),eppfes(ppfes),atef(aatef),nbcperiodic(nbp),periodic(pr),tedim(ttedim) {       
+    }
+    ~Op() { if(periodic) delete []periodic;}
+    AnyType operator()(Stack s)  const {  
+      const int d = Mesh::Rd::d;
+      Mesh ** ppTh = GetAny<Mesh  **>( (*eppTh)(s) );
+      AnyType r = (*eppfes)(s) ;
+      const TypeOfFE ** tef= new  const TypeOfFE * [ atef.size()];
+      for (int i=0;i<atef.size();i++)
+	if(tedim[i]==d)
+	  tef[i]= GetAny<TypeOfFE *>(atef[i].eval(s));
+	else if(tedim[i]==2 && d ==3)
+	    tef[i]= GetAny<TypeOfFE *>(TypeOfFE3to2(s,atef[i].eval(s)));
+	else ffassert(0);
+	  
+      pfes * ppfes = GetAny<pfes *>(r);
+      bool same = true;
+      for (int i=1;i<atef.size();i++)
+	same &= atef[i].LeftValue() == atef[1].LeftValue();
+      *ppfes = new pfes_tefk(ppTh,tef,atef.size(),s    ,nbcperiodic,periodic);
+      (**ppfes).decrement();  //07/2008 FH
+	// Add2StackOfPtr2FreeRC(s,*ppfes);  //  bug????  a verifier 06/07/2008
+      //  delete [] tef;
+      return r;}
+  } ;
+  
+  E_F0 * code(const basicAC_F0 & args)  const
+  { 
+    int nbcperiodic=0;
+    Expression *periodic=0;
+    Expression nargs[n_name_param];
+    
+    args.SetNameParam(n_name_param,name_param,nargs);
+      GetPeriodic(Mesh::Rd::d,nargs[0],nbcperiodic,periodic);
+    aType t_tfe= atype<TypeOfFE*>();
+    aType t_tfe2= atype<TypeOfFE2*>();  
+    int d=  TypeOfFE::Rd::d;
+    string sdim= d ?  " 2d : " : " 3d : " ; 
+    const E_Array * a2(dynamic_cast<const E_Array *>(args[2].LeftValue()));
+    ffassert(a2);
+    int N = a2->size(); ;
+    if (!N) CompileError(sdim+" We wait an array of Type of Element ");
+      KN<int> tedim(N);
+    for (int i=0;i< N; i++) 
+      if ((*a2)[i].left() == t_tfe)
+	  tedim[i]=d;
+      else if ((*a2)[i].left() ==t_tfe2)
+	  tedim[i]=2;
+      else
+	    CompileError(sdim+" We wait an array of  Type of Element ");
+    //    ffassert(0);
+    return  new Op(args[0],args[1],*a2,nbcperiodic,periodic,tedim);
+  } 
+  OpMake_pfes() : 
+    OneOperator(atype<pfes*>(),atype<pfes*>(),atype<Mesh **>(),atype<E_Array>()) {}
+};
+
+inline pfes* MakePtr2(pfes * const &p,pmesh * const &  a, TypeOfFE * const & tef)
+{ *p=new pfes_tef(a,tef) ;
+  (**p).decrement();
+  return p;}
+
+inline pfes3* MakePtr3(pfes3 * const &p,pmesh3 * const &  a, TypeOfFE3 * const & tef)
+{ *p=new pfes3_tef(a,tef) ;
+  (**p).decrement();
+  return p;}
+
+
+
+class OP_MakePtr2 { public:
+    class Op : public E_F0mps  { public:
+	//  static int GetPeriodic(Expression  bb, Expression & b,Expression & f);
+	static const int n_name_param =1;
+      static basicAC_F0::name_and_type name_param[] ;
+      Expression nargs[n_name_param];
+      typedef pfes * R;
+      typedef pfes * A;
+      typedef pmesh * B;
+      typedef TypeOfFE * C;
+      Expression a,b,c;
+      int nbcperiodic ;
+      Expression *periodic;
+      Op(const basicAC_F0 & args);
+      
+      AnyType operator()(Stack s) const  {
+	A p= GetAny<A>( (*a)(s) );
+	B th= GetAny<B>( (*b)(s) );
+	C tef= GetAny<C>( (*c)(s) );   
+	//  cout << "  ----------- " << endl;  
+	*p=new pfes_tef(th,tef,s,nbcperiodic,periodic) ;
+	(**p).decrement();
+	return  SetAny<R>(p);
+      } 
+    }; // end Op class 
+  
+  typedef Op::R Result;
+  static  E_F0 * f(const basicAC_F0 & args) { return  new Op(args);}
+  static ArrayOfaType  typeargs() {
+    return ArrayOfaType(       
+			atype<Op::A>(),
+			atype<Op::B>(),
+			atype<Op::C>(),false ) ;}
+};  
+
+
+class OP_MakePtr3 { public:
+    class Op : public E_F0mps  { public:
+	//  static int GetPeriodic(Expression  bb, Expression & b,Expression & f);
+	static const int n_name_param =1;
+      static basicAC_F0::name_and_type name_param[] ;
+      Expression nargs[n_name_param];
+      typedef pfes3 * R;
+      typedef pfes3 * A;
+      typedef pmesh3 * B;
+      typedef TypeOfFE3 * C;
+      Expression a,b,c;
+      int nbcperiodic ;
+      Expression *periodic;
+      Op(const basicAC_F0 & args);
+      
+      AnyType operator()(Stack s) const  {
+	A p= GetAny<A>( (*a)(s) );
+	B th= GetAny<B>( (*b)(s) );
+	C tef= GetAny<C>( (*c)(s) );   
+	//  cout << "  ----------- " << endl;  
+	*p=new pfes3_tef(th,tef,s,nbcperiodic,periodic) ;
+	(**p).decrement();
+	return  SetAny<R>(p);
+      } 
+    }; // end Op class 
+  
+  typedef Op::R Result;
+  static  E_F0 * f(const basicAC_F0 & args) { return  new Op(args);}
+  static ArrayOfaType  typeargs() {
+    return ArrayOfaType(       
+			atype<Op::A>(),
+			atype<Op::B>(),
+			atype<Op::C>(),false ) ;}
+};  
+
+void GetPeriodic(const int d,Expression perio,    int & nbcperiodic ,    Expression * &periodic)
+{
+    ffassert(d==2 || d ==3);
+      if ( perio) 
+       {
+         if( verbosity>1) 
+         cout << "  -- Periodical Condition to do" << endl;
+         const E_Array * a= dynamic_cast<const  E_Array *>(perio);
+         ffassert(a);
+         int n = a->size();
+        nbcperiodic= n/2;
+        if( verbosity>1) 
+        cout << "    the number of periodicBC " << n << endl;
+        if ( 2*nbcperiodic != n ) CompileError(" Sorry the number of periodicBC must by even"); 
+        periodic = new Expression[n*d]; 
+        for (int i=0,j=0;i<n;i++,j+=d)
+	  if(d==2)
+	    { if (GetPeriodic((*a)[i],periodic[j],periodic[j+1])==0)
+            CompileError(" a sub array of periodic BC must be [label, realfunction ]");
+	    }
+	  else if (d==3)
+	    { if (GetPeriodic((*a)[i],periodic[j],periodic[j+1],periodic[j+2])==0)
+		CompileError(" a sub array of periodic BC must be [label, realfunction , realfunction]");
+	    }
+	  else ffassert(0); 
+        }
+
+
+}
+
+    
+OP_MakePtr2::Op::Op(const basicAC_F0 & args)
+  : a(to<A>(args[0])),b(to<B>(args[1])),c(to<C>(args[2]))
+     {
+      nbcperiodic=0;
+      periodic=0;
+      args.SetNameParam(n_name_param,name_param,nargs);
+      GetPeriodic(2,nargs[0],nbcperiodic,periodic);
+     }
+    
+OP_MakePtr3::Op::Op(const basicAC_F0 & args)
+  : a(to<A>(args[0])),b(to<B>(args[1])),c(to<C>(args[2]))
+{
+  nbcperiodic=0;
+  periodic=0;
+  args.SetNameParam(n_name_param,name_param,nargs);
+  GetPeriodic(3,nargs[0],nbcperiodic,periodic);
+}
+
+int GetPeriodic(Expression  bb, Expression & b,Expression & f)
+    {
+      const E_Array * a= dynamic_cast<const E_Array *>(bb);
+      if(a && a->size() == 2)
+	{
+	  b= to<long>((*a)[0]);
+	  f= to<double>((*a)[1]);
+	  return 1;
+	}
+      else 
+	return 0;
+    }
+int GetPeriodic(Expression  bb, Expression & b,Expression & f1,Expression & f2)
+{
+    const E_Array * a= dynamic_cast<const E_Array *>(bb);
+    if(a && a->size() == 3)
+      {
+	  b= to<long>((*a)[0]);
+	  f1= to<double>((*a)[1]);
+	  f2= to<double>((*a)[2]);
+	  return 1;
+      }
+    else 
+	return 0;
+}
+
+basicAC_F0::name_and_type  OP_MakePtr2::Op::name_param[]= {
+  "periodic", &typeid(E_Array) 
+};
+
+basicAC_F0::name_and_type  OP_MakePtr3::Op::name_param[]= {
+  "periodic", &typeid(E_Array) 
+};
+
+inline pfes* MakePtr2(pfes * const &p,pmesh * const &  a){ 
+      *p=new pfes_tef(a,&P1Lagrange);
+      (**p).decrement();
+       return p ;}
+       
+inline pfes* MakePtr2(pfes * const &p,pfes * const &  a,long const & n){
+       *p= new pfes_fes(a,n);
+      (**p).decrement();
+       return p ;}
+       
+ long FindTxy(Stack s,pmesh * const &  ppTh,const double & x,const double & y)
+{
+   R2 P(x,y),PHat;
+   bool outside;
+     MeshPoint & mp = *MeshPointStack(s);  
+   const Mesh * pTh= *ppTh;
+   if(pTh == 0) return 0;  
+   const Triangle * K=pTh->Find(mp.P.p2(),PHat,outside);
+   if (!outside)
+     mp.set(*pTh,P,PHat,*K,K->lab);
+   else return 0;
+   return 1;
+}
+
+ 
+
+
+ 
+
+template<class K>    
+KN<K> * pfer2vect( pair<FEbase<K,v_fes> *,int> p)
+ {  
+    KN<K> * x=p.first->x();
+    if ( !x) {  // defined 
+      FESpace * Vh= p.first->newVh();     
+      throwassert( Vh);
+      *p.first = x = new KN<K>(Vh->NbOfDF);
+      *x=K(); 
+    }
+    return x;}
+
+template<class K>        
+long pfer_nbdf(pair<FEbase<K,v_fes> *,int> p)
+ {  
+   if (!p.first->Vh) p.first->Vh= p.first->newVh();
+   throwassert( !!p.first->Vh);
+   return p.first->Vh->NbOfDF;
+ }
+ 
+double pmesh_area(pmesh * p)
+ { throwassert(p && *p) ;  return (**p).area ;}
+long pmesh_nt(pmesh * p)
+ { throwassert(p && *p) ;  return (**p).nt ;}
+long pmesh_nbe(pmesh * p)
+{ throwassert(p && *p) ;  return (**p).neb ;}
+long pmesh_nv(pmesh * p)
+ { throwassert(p && *p) ;  return (**p).nv ;}
+long pVh_ndof(pfes * p)
+ { throwassert(p && *p);
+   FESpace *fes=**p; ;  return fes->NbOfDF ;}
+long pVh_nt(pfes * p)
+ { throwassert(p && *p);
+   FESpace *fes=**p; ;  return fes->NbOfElements ;}
+long pVh_ndofK(pfes * p)
+ { throwassert(p && *p);
+   FESpace *fes=**p;   return (*fes)[0].NbDoF() ;}
+
+long mp_nuTriangle(MeshPoint * p)
+ { throwassert(p  && p->Th && p->T);
+   long nu=0;
+   if(p->d==2)
+     nu=(*p->Th)(p->T);
+   else if  (p->d==3)
+     nu=(*p->Th3)(p->T3);
+   else ffassert(0);
+   delete p;
+   return nu ;}
+   
+long mp_region(MeshPoint * p)
+ { throwassert(p && p->Th);
+   long  nu(p->region);
+   delete p;
+   return nu ;}
+
+
+class pVh_ndf : public ternary_function<pfes *,long,long,long> { public:
+
+
+  class Op : public E_F0mps { public:
+      Expression a,b,c;
+       Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc) {}       
+       AnyType operator()(Stack s)  const 
+        { 
+           pfes * p(GetAny<pfes *>((*a)(s)));
+           long  k(GetAny<long>((*b)(s)));
+           long  i(GetAny<long>((*c)(s)));
+           throwassert(p && *p);
+           FESpace *fes=**p;
+           throwassert(fes && k >=0 && k < fes->NbOfElements );
+           FElement K=(*fes)[k];
+           throwassert(i>=0 && i <K.NbDoF() );
+           long ret(K(i));
+           return  ret;
+         }
+   
+  };
+};
+//plus
+
+class Op_CopyArray : public OneOperator { public:
+    Op_CopyArray():OneOperator(atype<void>(),atype<E_Array>(),atype<E_Array>()) {}
+    E_F0 * code(const basicAC_F0 & args) const ; 
+};  
+                       
+template<class R,int dd>
+AnyType pfer2R(Stack s,const AnyType &a)
+{
+  pair< FEbase<R,v_fes> *  ,int> ppfe=GetAny<pair< FEbase<R,v_fes> *,int> >(a);
+  FEbase<R,v_fes> & fe( *ppfe.first);
+  int componante=ppfe.second;
+  if ( !fe.x()) {
+   if ( !fe.x()){
+    // CompileError(" Sorry unset fem array ");
+     return   SetAny<R>(0.0);
+    }
+  }
+   
+  const FESpace & Vh(*fe.Vh);
+  const Mesh & Th(Vh.Th);
+  assert(Th.ntet==0 && Th.volume==0 && Th.triangles != 0);
+  MeshPoint & mp = *MeshPointStack(s);
+  const Triangle *K;
+  R2 PHat;
+  bool outside=false;
+  bool qnu=true;
+  if ( mp.Th == &Th && mp.T) 
+   {
+    qnu=false;
+    K=mp.T;
+    PHat=mp.PHat.p2();
+   }
+  else if ( mp.other.Th == & Th && mp.other.P.x == mp.P.x && mp.other.P.y == mp.P.y )
+   {
+    K=mp.other.T;
+    PHat=mp.other.PHat.p2();
+    outside = mp.other.outside;
+   } 
+  else {
+    if (mp.isUnset()) ExecError("Try to get unset x,y, ...");
+    K=Th.Find(mp.P.p2(),PHat,outside);
+    mp.other.set(Th,mp.P.p2(),PHat,*K,0,outside);
+    }
+  // cout << "  ---  " << qnu << "  " << mp.P << " " << mp.outside <<  " " << outside << endl;
+  const FElement KK(Vh[Th(K)]);
+  if (outside && !KK.tfe->NbDfOnVertex && !KK.tfe->NbDfOnEdge) 
+    return   SetAny<R>(0.0); 
+/*  if (!outside) 
+    {
+      if ( Norme2_2( (*K)(PHat) - mp.P ) > 1e-12 )
+        cout << "bug ??  " << Norme2_2( (*K)(PHat) - mp.P ) << " " << mp.P << " " << (*K)(PHat) << endl;
+    } */
+/*  int nbdf=KK.NbDoF();
+  
+  int N= KK.N;
+  KN_<R> U(*fe.x());
+  KNMK<R> fb(nbdf,N,3); //  the value for basic fonction
+  KN<R> fk(nbdf);
+  for (int i=0;i<nbdf;i++) // get the local value
+    fk[i] = U[KK(i)];
+    //  get value of basic function
+  KK.BF(PHat,fb);  
+  
+  R r = (fb('.',componante,dd),fk);  
+*/
+  
+ const R rr = KK(PHat,*fe.x(),componante,dd);
+//  cout << " " << rr << endl;
+//  R2 B(mp.P);
+/*   if ( r < 0.08001 &&  Norme2_2(mp.P) > 0.05  && Norme2_2(mp.P) < 0.4*0.4  ) 
+     {
+     int vv=verbosity;
+      cout << " f()  triangle  " << Th(K) << " " << mp.P << " " << PHat << " =  " << r << " " <<outside ;
+      if (outside) {  verbosity = 200;
+         K=Th.Find(mp.P,PHat,outside);
+          cout << Th(K) << " " << outside << endl;}
+       cout << endl; verbosity=vv;
+     } */
+//  if ( qnu )   
+ //  cout << " f()  triangle       " << Th(K) << " " << mp.P << " " << PHat << " =  " << r <<  endl;
+  return SetAny<R>(rr);
+}
+
+ 
+template<class R>
+AnyType set_fe (Stack s,Expression ppfe, Expression e)
+  { 
+   long kkff = Mesh::kfind,  kkth = Mesh::kthrough;
+      StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
+
+   
+    MeshPoint *mps=MeshPointStack(s),mp=*mps;  
+    pair<FEbase<R,v_fes> *,int>  pp=GetAny<pair<FEbase<R,v_fes> *,int> >((*ppfe)(s));
+    FEbase<R,v_fes> & fe(*pp.first);
+    const  FESpace & Vh(*fe.newVh());
+    if(!&Vh ) ExecError("Unset FEspace (Null mesh ? ) on  uh= ");
+ 
+    KN<R> gg(Vh.MaximalNbOfDF());
+    const  Mesh & Th(Vh.Th);
+ //   R F[100]; // buffer 
+    TabFuncArg tabexp(s,Vh.N);
+    tabexp[0]=e;
+    
+    if(Vh.N!=1)
+    {  cerr << " Try to set a  vectorial  FE function  (nb  componant=" <<  Vh.N << ") with one scalar " << endl;
+       ExecError(" Error interploation (set)  FE function (vectorial) with a scalar");
+    }
+    KN<R> * y=new  KN<R>(Vh.NbOfDF);
+    KN<R> & yy(*y);
+    KN<R> Viso(100);
+    // R2 Ptt[3];
+    for (int i=0;i<Viso.N();i++)
+      Viso[i]=0.01*i; 
+      
+    FElement::aIPJ ipj(Vh[0].Pi_h_ipj()); 
+    FElement::aR2  PtHat(Vh[0].Pi_h_R2()); 
+    KN<double>   Aipj(ipj.N());
+    KN<R>   Vp(PtHat.N());
+    const E_F0 & ff(* (const  E_F0 *) e ) ;
+
+   if (Vh.isFEMesh() )
+    {
+      
+      ffassert(Vh.NbOfDF == Th.nv && Vh.N == 1 );
+      for (int iv=0;iv<Th.nv;iv++)
+       {
+         const Vertex & v(Th(iv));
+         int ik=Th.Contening(&v);
+         const Triangle & K(Th[ik]);
+         int il=-1;
+         if  ( &K[0] == &v) il=0;
+         if  ( &K[1] == &v) il=1;
+         if  ( &K[2] == &v) il=2;
+         assert(il>=0);
+         mps->set(Th,v,TriangleHat[il],K,v.lab);
+         yy[iv] = GetAny<R>( ff(s) );
+          sptr->clean(); // modif FH mars 2006  clean Ptr
+       }
+      
+    }
+   else     
+    
+     for (int t=0;t<Th.nt;t++)
+      {
+         FElement K(Vh[t]);
+         int nbdf=K.NbDoF();
+         gg=R();   
+#ifdef OLDPih    
+// old method          
+         K.Pi_h(gg,F_Pi_h,F,&tabexp);
+#else               
+         K.Pi_h(Aipj);
+         for (int p=0;p<PtHat.N();p++)
+          { 
+            mps->set(K.T(PtHat[p]),PtHat[p],K);
+            Vp[p]=GetAny<R>( ff(s) );
+           }
+         for (int i=0;i<Aipj.N();i++)
+          { 
+           const FElement::IPJ &ipj_i(ipj[i]);
+           assert(ipj_i.j==0); // car  Vh.N=0
+           gg[ipj_i.i] += Aipj[i]*Vp[ipj_i.p];            
+          }
+#endif          
+         for (int df=0;df<nbdf;df++)         
+            (*y)[K(df)] =  gg[df] ;
+           sptr->clean(); // modif FH mars 2006  clean Ptr
+                       
+      }
+    *mps=mp;
+    fe=y;
+     kkff = Mesh::kfind - kkff;
+     kkth = Mesh::kthrough -kkth;
+
+    if(verbosity>1)
+      ShowBound(*y,cout)  
+           << " " << kkth << "/" << kkff << " =  " << double(kkth)/Max<double>(1.,kkff) << endl;
+    return SetAny<FEbase<R,v_fes>*>(&fe); 
+  }
+AnyType set_feoX_1 (Stack s,Expression ppfeX_1, Expression e)
+  { // inutile 
+    // m�me chose que  v(X1,X2);
+      StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
+    typedef const interpolate_f_X_1<R>::CODE * code;
+    MeshPoint mp= *MeshPointStack(s); 
+    code ipp = dynamic_cast<code>(ppfeX_1);
+    
+    pair<FEbase<R,v_fes> *,int>  pp=GetAny<pair<FEbase<R,v_fes> *,int> >((*ipp->f)(s));
+    FEbase<R,v_fes> & fe(*pp.first);
+    const  FESpace & Vh(*fe.newVh());
+    KN<R> gg(Vh.MaximalNbOfDF()); 
+    const  Mesh & Th(Vh.Th);
+    R F[100]; // buffer 
+    TabFuncArg tabexp(s,Vh.N+2);
+    tabexp[0]=e;
+    tabexp[1]=ipp->x;
+    tabexp[2]=ipp->y;
+    
+    throwassert(Vh.N==1); 
+    KN<R> * y=new  KN<R>(Vh.NbOfDF); 
+     for (int t=0;t<Th.nt;t++)
+      {
+         FElement K(Vh[t]);
+         int nbdf=K.NbDoF();
+        
+         gg=R();
+         
+         K.Pi_h(gg,FoX_1_Pi_h,F,&tabexp);
+         for (int df=0;df<nbdf;df++)
+          (*y)[K(df)] =  gg[df] ;
+          sptr->clean(); // modif FH mars 2006  clean Ptr          
+      }
+    *MeshPointStack(s)=mp;
+    fe=y;
+    if(verbosity>1)
+    cout << "  -- interpole f= g*X^-1, function's bound:  " << y->min() << " " << y->max() << endl; 
+    return SetAny<FEbase<R,v_fes>*>(&fe); 
+  }
+
+template<class K>
+E_set_fev<K>::E_set_fev(const E_Array * a,Expression pp,int ddim) 
+  :dim(ddim), aa(*a),ppfe(pp),optimize(true),
+   where_in_stack_opt(),optiexp0(),optiexpK() 
+{ 
+  aa.map(to<K>) ;
+  bool kdump=false;
+  if(optimize)
+    { // new code Optimized  -------
+      int n=aa.size();
+      deque<pair<Expression,int> > ll;
+      MapOfE_F0 m;
+      where_in_stack_opt.resize(n);
+      size_t top = currentblock->OffSet(0), topbb=top; // FH. bofbof ??? 
+      for (int i=0; i<n; i++)
+	{
+	  Expression ee= aa[i].LeftValue();
+	  if (kdump)
+	    cout << "Optimize OneOperatorMakePtrFE:  type exp: " << typeid(*ee).name() << " "<<endl;
+	  where_in_stack_opt[i]=ee->Optimize(ll, m, top);
+	  if (kdump)
+	    cout  << "\n\t\t"<< i  << ": " << where_in_stack_opt[i] << endl;
+	}
+      
+      currentblock->OffSet(top-topbb);
+      //  
+      int k=ll.size(),k0=0,k1=0;
+      for (int i=0;i<k;i++)
+	if (ll[i].first->MeshIndependent()) k0++;
+      deque<pair<Expression,int> > l0(k0),l1(k-k0);
+      k0=0,k1=0;
+      for (int i=0;i<k;i++)
+	if (ll[i].first->MeshIndependent()) 
+	  {
+	    if (kdump)
+	      cout << " mi " << ll[i].second << " " << *(ll[i].first) << endl;
+	    l0[k0++]=ll[i];
+	  }
+	else 
+	  {
+	    if (kdump)
+	      cout << " md " << ll[i].second << " " << *(ll[i].first) << endl;
+	    l1[k1++]=ll[i];
+	  }
+      if (k0)      
+	optiexp0 = new E_F0_Optimize(l0,m,0);  // constant part
+      if (k1) 
+	optiexpK = new E_F0_Optimize(l1,m,0);  // none constant part
+      
+    }
+  
+  
+}
+
+
+template<class K>   
+AnyType E_set_fev<K>::operator()(Stack s)  const
+{
+  if(dim== 2)  return  Op2d(s);
+  else if(dim == 3)  return Op3d(s);
+  return Nothing;
+}
+
+
+template<class K>   
+AnyType E_set_fev<K>::Op3d(Stack s)  const
+{
+  //  voir E_set_fev3  ( pb de consitance a revoir FH) 
+  ffassert(0); // a faire   
+}
+template<class K>   
+AnyType E_set_fev<K>::Op2d(Stack s)  const
+{  
+  StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);     
+  MeshPoint *mps=MeshPointStack(s), mp=*mps;   
+  FEbase<K,v_fes> ** pp=GetAny< FEbase<K,v_fes> **>((*ppfe)(s));
+  FEbase<K,v_fes> & fe(**pp);
+  const  FESpace & Vh(*fe.newVh());
+  KN<K> gg(Vh.MaximalNbOfDF()); 
+  
+  
+  const  Mesh & Th(Vh.Th);
+  const int dim=Vh.N;
+  K ** copt=0;
+  if (optimize)   copt= new K *[dim];
+  if(copt) {
+    assert((size_t) dim== where_in_stack_opt.size());
+    for (int i=0;i<dim;i++)
+      {
+        int offset=where_in_stack_opt[i];
+        assert(offset>10);
+        copt[i]= static_cast<K *>(static_cast<void *>((char*)s+offset));
+        *(copt[i])=0;
+       }
+    if (optiexp0) (*optiexp0)(s); // init 
+  }
+  
+  ffassert(dim<100);
+  //   R F[100]; // buffer 
+  
+  TabFuncArg tabexp(s,Vh.N);
+  //   const E_Array * aa = dynamic_cast<const E_Array *>(e);
+  ffassert( aa.size() == Vh.N);
+  for (int i=0;i<dim;i++)
+    tabexp[i]=aa[i]; 
+  
+  KN<K> * y=new  KN<K>(Vh.NbOfDF);
+  KN<K> & yy(*y);
+  
+  FElement::aIPJ ipj(Vh[0].Pi_h_ipj()); 
+  FElement::aR2  PtHat(Vh[0].Pi_h_R2()); 
+  
+  KN<double>   Aipj(ipj.N());
+  
+  
+  //   KNM<K>  Vp(dim,PtHat.N());// bug 
+  // g++ error: too many initializers for `const __class_type_info_pseudo
+  
+  KN<K>  Vp1(dim*PtHat.N());
+  
+  
+  if (Vh.isFEMesh() )
+    {
+      
+      ffassert(Vh.NbOfDF == Th.nv && dim == 1 );
+      for (int iv=0;iv<Th.nv;iv++)
+	{
+	  const E_F0 & ff(* (const  E_F0 *) aa[0]  ) ;
+	  const Vertex & v(Th(iv));
+	  int ik=Th.Contening(&v);
+	  const Triangle & Kt(Th[ik]);
+	  int il=-1;
+	  if  ( &Kt[0] == &v) il=0;
+	  if  ( &Kt[1] == &v) il=1;
+	  if  ( &Kt[2] == &v) il=2;
+	  assert(il>=0);
+	  mps->set(Th,v,TriangleHat[il],Kt,v.lab);
+	  if (copt) {
+	    if (optiexpK) (*optiexpK)(s); 
+            yy[iv] =  *(copt[0]);
+          }
+          else 
+	    yy[iv] = GetAny<K>( ff(s) );
+	  sptr->clean(); // modif FH mars 2006  clean Ptr
+	}
+      
+    }
+  else
+    for (int t=0;t<Th.nt;t++)
+      {
+	FElement Kt(Vh[t]);
+	int nbdf=Kt.NbDoF();
+        
+	gg=K();
+        
+#ifdef OLDPih    
+	// old method          
+	Kt.Pi_h(gg,F_Pi_h,F,&tabexp);
+#else               
+	Kt.Pi_h(Aipj);
+	
+	for (int p=0;p<PtHat.N();p++)
+          { 
+            mps->set(Kt.T(PtHat[p]),PtHat[p],Kt);
+
+      //      KN_<K> Vpp(Vp('.',p));
+            KN_<K> Vpp(Vp1,SubArray(dim,p*dim)); // a Change FHHHHHHHH
+            if (copt) { // optimize  version 
+             if (optiexpK) (*optiexpK)(s);
+             for (int j=0;j<dim;j++)
+               Vpp[j] = *(copt[j]);
+            }
+            else  // old version 
+            for (int j=0;j<dim;j++)
+             if (tabexp[j]) 
+               Vpp[j]=GetAny<K>( (*tabexp[j])(s) );
+              else Vpp[j]=0;
+              
+           }
+           
+         for (int i=0;i<Aipj.N();i++)
+          { 
+           const FElement::IPJ &ipj_i(ipj[i]);
+         //  gg[ipj_i.i] += Aipj[i]*Vp(ipj_i.j,ipj_i.p);           
+             gg[ipj_i.i] += Aipj[i]*Vp1(ipj_i.j+ipj_i.p*dim); // index a la main  
+            sptr->clean(); // modif FH mars 2006  clean Ptr          
+          } 
+#endif          
+
+         for (int df=0;df<nbdf;df++)         
+           yy[Kt(df)] =  gg[df] ;
+      }
+   //  MeshPointStack(s)->unset();
+    fe=y;
+    if (copt) delete [] copt;
+    *MeshPointStack(s) = mp;
+    if(verbosity>1)
+        ShowBound(*y,cout) << endl ;
+   //HHHH*/       
+    return Nothing;
+  }
+
+
+template<class K>
+inline FEbase<K,v_fes> * MakePtrFE(pfes * const &  a){ 
+  FEbase<K,v_fes> * p=new FEbase<K,v_fes>(a);
+  //cout << "MakePtrFE " << p<< endl; 
+  return p ;}
+  
+template<class K>
+inline FEbase<K,v_fes> ** MakePtrFE2(FEbase<K,v_fes> * * const &  p,pfes * const &  a){ 
+  *p=new FEbase<K,v_fes>(a);
+  //cout << "MakePtrFE2 " << *p<< endl; 
+  return p ;}
+
+template<class K>  
+inline FEbaseArray<K,v_fes> ** MakePtrFE3(FEbaseArray<K,v_fes> * * const &  p,pfes * const &  a,const long & N){ 
+  *p=new FEbaseArray<K,v_fes>(a,N);
+  //cout << "MakePtrFE2 " << *p<< endl; 
+  return p ;}
+  
+/*
+inline pmesharray*  MakePtr(pmesharray*  const &  p,long   const &  a){ 
+  p->first=new pmesh [a];
+  p->second=a;
+  for (int i=0;i<a;i++) 
+     p->first[i]=0; // nuset 
+  return p ;}
+*/  
+template<class K>
+class  OneOperatorMakePtrFE : public OneOperator 
+{
+public:
+  // il faut Optimize 
+  // typedef double K;
+  typedef  FEbase<K,v_fes> ** R;
+  typedef pfes* B;
+  class CODE : public E_F0mps  
+  {
+  public:
+    Expression fer,fes;
+    E_set_fev<K> * e_set_fev;
+    const E_Array * v;
+    CODE(const basicAC_F0 & args) 
+      : 
+      fer(to<R>(args[0])),
+      fes(to<B>(args[1])),
+      e_set_fev(0) 
+    {
+      if (BCastTo<K>(args[2]) )
+	v = new E_Array(basicAC_F0_wa(to<K>(args[2]))); 
+      else 
+	v = dynamic_cast<const E_Array *>( args[2].LeftValue() );
+      if (!v) {
+	cout << "Error: type of arg :" << *args[2].left()  << " in " << typeid(K).name() << " case " << endl;
+	ErrorCompile(" We wait  a double/complex expression or a array expression",1);
+      }
+      //v->map(to<K>);
+      e_set_fev=  new   E_set_fev<K>(v,fer,v_fes::d);
+      
+    }
+    
+    AnyType operator()(Stack stack)  const {
+      R  p = GetAny<R>( (*fer)(stack));
+      B  a = GetAny<B>( (*fes)(stack)); 
+      *p=new FEbase<K,v_fes>(a);
+      (*e_set_fev)(stack); 
+      //  cout << "MakePtrFE: build p " << p << " " << *p << endl;         
+      return SetAny<R>(p);
+    }
+    operator aType () const { return atype<R>();}         
+    
+    
+  };
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { return  new CODE(args);}
+  OneOperatorMakePtrFE(aType tt):  // tt= aType<double>() or aType<E_Array>()  
+    OneOperator(map_type[typeid(R).name()],map_type[typeid(R).name()],map_type[typeid(B).name()],tt)
+  {}
+};
+
+
+// ---  
+
+template<class Result,class A>
+class  OneOperator_Ptr_o_R: public OneOperator {
+  //  aType r; //  return type 
+    typedef Result A::* ptr;
+    ptr p;   
+    public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return  new E_F_A_Ptr_o_R<Result,A>(t[0]->CastTo(args[0]),p);} 
+    OneOperator_Ptr_o_R(ptr pp):
+       OneOperator(atype<Result*>(),atype<A*>()),p(pp) {}     
+};
+
+template<class K>  K  *PAddition(const K * a,const K *  b)  {return  new K(*a+*b);}
+
+
+
+
+
+// 
+class fCLD { public:
+  typedef pair<int,Label> Key;
+  typedef  map<Key,Expression>::iterator iterator;
+  map<Key,Expression> *l;
+  fCLD (){ l=new  map<Key,Expression>;}
+  void operator=(const fCLD & a){ *l=*a.l;}
+  void destroy() { delete l;l=0;}
+  ~fCLD(){ delete l;l=0;}
+  void Add(finconnue *v,int lab,C_F0 f) { 
+    const MGauche *pn= v->simple();
+     Check(pn,"Def CL Dirichet ");
+    
+    Label r(lab);
+    Key k(make_pair(pn->first,r));
+    iterator i=l->find(k);
+    Check( i != l->end() ,"Def CL Dirichet already exists");
+    l->insert(make_pair(k,CastTo<double>(f)));        
+  }
+};
+
+//  pour stocker des expression de compilation 
+
+
+class Convect : public E_F0mps  { public:
+    typedef double  Result; // return type 
+    Expression u,v,w,ff,dt;
+    int d;
+    Convect(const basicAC_F0 & args)  : u(0),v(0),w(0),ff(0),dt(0)
+    {
+      args.SetNameParam(); 
+      const E_Array * a = dynamic_cast<const E_Array *>(args[0].LeftValue());
+            ffassert(a);
+	d= a->size();
+       if (d == 3) 
+	   w= CastTo<double>((*a)[2]);
+       else if (d != 2) 
+          { CompileError("convect vector have only 2 or 3 componant");}
+       u= CastTo<double>((*a)[0]);
+       v= CastTo<double>((*a)[1]);
+       
+       dt=CastTo<double>(args[1]);
+       ff=CastTo<double>(args[2]);
+     }
+    
+    static ArrayOfaType  typeargs() 
+      { return  ArrayOfaType(atype<E_Array>(),atype<double>(),atype<double>());}
+      
+    static  E_F0 * f(const basicAC_F0 & args) { return new Convect(args);} 
+    AnyType operator()(Stack s) const ; 
+    AnyType eval2(Stack s) const ; 
+    AnyType eval3(Stack s) const ; 
+    operator aType () const { return atype<Result>();}         
+    
+};
+
+/// <<Plot>> used for the [[plot_keyword]]
+
+class Plot :  public E_F0mps /* [[file:AFunction.hpp::E_F0mps]] */ {
+public:
+    typedef KN_<R>  tab;
+    typedef pferbase sol;
+    typedef pferbasearray asol;
+    typedef pf3rbase sol3;
+    typedef pf3rbasearray asol3;
+    typedef pfecbase solc;
+    typedef pfecbasearray asolc;
+    typedef pf3cbase solc3;
+    typedef pf3cbasearray asolc3;
+    
+    typedef long  Result;
+    struct ListWhat {
+	int what,i;
+	int cmp[3];
+	int n;	
+	void * v[3];//  for 
+	pmesh th() { assert(v[0] && what==0); return static_cast<pmesh>(v[0]);}
+	pmesh3 th3() { assert(v[0] && what==5); return static_cast<pmesh3>(v[0]);}
+	
+	void Set(int nn=0,void **vv=0,int *c=0) {
+	    cmp[0]=cmp[1]=cmp[2]=-1;
+	    v[0]=v[1]=v[2]=0;
+	    n=nn;
+	    for(int i=0;i<nn;++i)
+	      {   
+		  if(c) cmp[i]=c[i];
+		  if(vv) v[i]=vv[i];
+	      }		   
+	}	
+	
+	ListWhat(int w=-1,int ii=-1 )
+	: what(w),i(ii) {Set();}
+	ListWhat(int what,int ii,int n,void ** f0,int *c)
+	: what(what),i(ii){ Set(n,f0,c);}
+	ListWhat(int what,int ii,void * f0)
+	: what(what),i(ii){ Set(1,&f0,0);}
+	
+	template<typename S>
+	void eval(S *f,int *c)
+	{ for(int i=0;i<3;++i) {
+	    f[i]= static_cast<S>(v[i]);
+	    c[i]= cmp[i]; }
+	}
+	
+	template<typename M>
+	M eval()
+	{ assert(v[0]);
+	    return static_cast<M>(v[0]);	    
+	}
+	void eval(sol & f0,int & cmp0, sol &f1,int &cmp1)
+	{
+	  f0=static_cast<sol>(v[0]);
+	  f1=static_cast<sol>(v[1]);
+	  cmp0=cmp[0];
+	  cmp1=cmp[1];
+	}
+
+    };
+
+  /// <<Expression2>>
+    struct Expression2 
+     {
+	long what; // 0 mesh, 1 iso, 2 vector, 3 curve , 4 border , 5  mesh3, 6 iso 3d, 
+	// 7: vector 3d  ( +10 -> complex visu ???? ) 
+	// 101 array of iso 2d  , 106 array of iso 3d  , 100  array of meshes 
+	bool composant;
+	Expression e[3];
+	Expression2() {e[0]=0;e[1]=0;e[2]=0;composant=false;what=0;}
+	Expression &operator[](int i){return e[i];}
+	
+	template<class S>
+	int EvalandPush(Stack s,int ii,vector<ListWhat> & ll ) const  
+	{ 
+	    int n=-1;
+	    S f[3]={0,0,0};		
+	    int cmp[3]={-1,-1,-1};
+
+	    for(int i=0;i<3;++i)
+		if (e[i]) {
+		    if (!composant) 
+		      { pair<S,int> p= GetAny< pair<S,int> >((*e[i])(s));
+			  n=i;cmp[i]=p.second;
+			  f[i]= p.first;}
+		    else { cmp[i]=0;
+			f[i]=GetAny< S >((*e[i])(s));
+			n=i;}
+		}
+	    ll.push_back(ListWhat(what,ii,n+1,f,cmp));
+	    return n;}
+	
+	template<class A,class S> // ok of mesh too because composant=true; 
+ 	int AEvalandPush(Stack s,int ii,vector<ListWhat> & ll ) const  
+	{  typedef pair<A,int> PA;
+	    int nn=-1;
+	    A f[3];
+	    union {
+		S fj[3];
+		void *fv[3];
+	    };
+	    f[0]=f[1]=f[2]=0;		
+	    int cmp[3]={-1,-1,-1};
+	    
+	    for(int i=0;i<3;++i)
+		if (e[i]) 
+		  {
+		    if (!composant) 
+		     { PA p= GetAny< PA >((*e[i])(s)); cmp[i]=p.second;f[i]=p.first; nn=i;}
+	            else 
+		     { f[i]= GetAny< A >((*e[i])(s)); cmp[i]=0; nn=i;}
+		  }
+	    	else break;
+	    nn++;
+	    int n = f[0]->N;
+	    if(verbosity>50) // add 01/2011 FH ????
+	      cout << "add  N = " << n << " " << nn  << " "<< what << endl;
+	    for(int j=0;j<n;++j)
+	      {
+		
+		int m=-1;
+		fj[0]=fj[1]=fj[2]=0;// clean 
+		for (int i=0;i<nn;++i)
+		  {
+		    fj[i]=  *f[i]->operator[](j);
+		    if(fj[i] && fj[i]->x()) m=i;
+		    else break;
+		}
+		if(m>=0)  {
+		    ll.push_back(ListWhat(what%100,ii,m+1,fv,cmp));
+		    if(verbosity>100)
+		    cout << ".";
+		}
+		
+	      }	
+	    if(verbosity>100)
+	    cout << endl;
+	    return nn;
+	}
+     template<class S> 
+       int MEvalandPush(Stack s,int ii,vector<ListWhat> & ll ) const  
+       {  typedef KN<S> * A; 
+	  
+	   A ath;		
+	   
+	   ath= GetAny< A >((*e[0])(s));
+	   int n=0;
+	   if(ath) n = ath->N();
+	    S th;
+	   
+	   for(int j=0;j<n;++j)
+	     {
+	       th= ath->operator[](j);
+	       if(th) 		    
+		ll.push_back(ListWhat(what%100,ii,static_cast<void *>(th)));
+       
+	     }
+	   return n;
+       }
+       
+	sol eval(int i,Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) {
+		if (!composant) {pfer p= GetAny< pfer >((*e[i])(s)); cmp=p.second;return p.first;}
+		else {return GetAny< pferbase >((*e[i])(s));}
+	    }
+	    else return 0;}
+	sol3 eval3(int i,Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) {
+		if (!composant) {pf3r p= GetAny< pf3r >((*e[i])(s)); cmp=p.second;return p.first;}
+		else {return GetAny< pf3rbase >((*e[i])(s));}
+	    }
+	    else return 0;}
+	// add FH Japon 2010 ..	for complex visu ...  to complex ....  try to uniformize ...
+	solc evalc(int i,Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) {
+		if (!composant) {pfec p= GetAny< pfec >((*e[i])(s)); cmp=p.second;return p.first;}
+		else {return GetAny< pfecbase >((*e[i])(s));}
+	    }
+	    else return 0;}
+	solc3 evalc3(int i,Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) {
+		if (!composant) {pf3c p= GetAny< pf3c >((*e[i])(s)); cmp=p.second;return p.first;}
+		else {return GetAny< pf3cbase >((*e[i])(s));}
+	    }
+	    else return 0;}
+	
+	
+	asol evala(int i, Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) 
+	      {pferarray p= GetAny< pferarray >((*e[i])(s)); cmp=p.second;return p.first;}
+	    else return 0;}
+	asol3 evala3(int i, Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) 
+	      {pf3rarray p= GetAny< pf3rarray >((*e[i])(s)); cmp=p.second;return p.first;}
+	    else return 0;}
+	
+	asolc evalca(int i, Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) 
+	      {pfecarray p= GetAny< pfecarray >((*e[i])(s)); cmp=p.second;return p.first;}
+	    else return 0;}
+	asolc3 evalca3(int i, Stack s,int & cmp) const  {  cmp=-1;
+	    if (e[i]) 
+	      {pf3carray p= GetAny< pf3carray >((*e[i])(s)); cmp=p.second;return p.first;}
+	    else return 0;}
+	
+	Mesh & evalm(int i,Stack s) const  { throwassert(e[i]);return  * GetAny< pmesh >((*e[i])(s)) ;}
+	KN<pmesh> * evalma(int i,Stack s) const  { throwassert(e[i]);return   GetAny< KN<pmesh> * >((*e[i])(s)) ;}
+	const Mesh3 & evalm3(int i,Stack s) const  { throwassert(e[i]);return  * GetAny< pmesh3 >((*e[i])(s)) ;}
+	const E_BorderN * evalb(int i,Stack s) const  { throwassert(e[i]);return   GetAny< const E_BorderN *>((*e[i])(s)) ;}
+	tab  evalt(int i,Stack s) const  { throwassert(e[i]);return  GetAny<tab>((*e[i])(s)) ;}
+    };
+
+  // see [[Plot_name_param]]
+  static basicAC_F0::name_and_type name_param[] ;
+
+  /// FFCS: added new parameters for VTK graphics. See [[Plot_name_param]] for new parameter names
+  static const int n_name_param=42;
+
+  Expression bb[4];
+
+  /// see [[Expression2]]
+  vector<Expression2> l;
+
+    Expression nargs[n_name_param];
+    Plot(const basicAC_F0 & args) : l(args.size()) 
+    {
+      
+      args.SetNameParam(n_name_param,name_param,nargs);
+      if ( nargs[8] )
+	  Box2x2( nargs[8] , bb);   
+      
+      for (size_t i=0;i<l.size();i++)
+	  
+	  if (args[i].left()==atype<E_Array>())
+	    {
+	      //cout << "args[i].left()==atype<E_Array>()" << endl;
+	      l[i].composant=false;
+	      const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+	      ffassert(a);
+	      int asizea=a->size();
+	      if(asizea==0) CompileError("plot of vector with 0 of components(!= 2 or 3) ");
+	      bool bpfer=  BCastTo<pfer>((*a)[0]);
+	      bool bpf3r=  BCastTo<pf3r>((*a)[0]);
+	      bool bpfec=  BCastTo<pfec>((*a)[0]);
+	      bool bpf3c=  BCastTo<pf3c>((*a)[0]);
+	      
+	      if ( bpfer && asizea <3) 
+		{
+		  l[i].what=asizea;
+		  for (int j=0;j<a->size();j++)             
+		      l[i][j]= CastTo<pfer>((*a)[j]);
+		}
+	      else if ( bpfec && asizea <3) 
+		{
+		  l[i].what=10+asizea;
+		  for (int j=0;j<a->size();j++)             
+		      l[i][j]= CastTo<pfec>((*a)[j]);
+		}
+	      else if (asizea==2)
+		{
+		  l[i].what=3;
+		  for (int j=0;j<a->size();j++)             
+		      l[i][j]= CastTo<tab>((*a)[j]);
+		}
+	      else if (asizea == 3 && bpf3r ) // 3d vector ...
+		{
+		  l[i].what=7; // new 3d vector 
+		  for (int j=0;j<a->size();j++)             
+		      l[i][j]= CastTo<pf3r>((*a)[j]);
+		  
+		}
+	      else if (asizea == 3 && bpf3c ) // 3d vector ...
+		{
+		  l[i].what=17; // new 3d vector 
+		  for (int j=0;j<a->size();j++)             
+		      l[i][j]= CastTo<pf3c>((*a)[j]);
+		  
+		}
+	      
+	      else { CompileError("plot of array with wrong  number of components (!= 2 or 3) ");}
+	    }
+	  else if (BCastTo<pferbase>(args[i])) {
+	      l[i].what=1; //  iso value 2d
+	      // cout << "BCastTo<pferbase>(args[i])" << endl;
+	      l[i].composant=true;
+	      l[i][0]=CastTo<pferbase>(args[i]); }
+	  else if (BCastTo<pfer>(args[i])) {
+	      // cout << "BCastTo<pfer>(args[i])" << endl;
+	      l[i].composant=false;
+	      l[i].what=1; //  iso value 2d
+	      l[i][0]=CastTo<pfer>(args[i]);}
+	  else if (BCastTo<pfecbase>(args[i])) {
+	      l[i].what=11; //  iso value 2d
+	      // cout << "BCastTo<pferbase>(args[i])" << endl;
+	      l[i].composant=true;
+	      l[i][0]=CastTo<pfecbase>(args[i]); }
+	  else if (BCastTo<pfec>(args[i])) {
+	      // cout << "BCastTo<pfer>(args[i])" << endl;
+	      l[i].composant=false;
+	      l[i].what=11; //  iso value 2d
+	      l[i][0]=CastTo<pfec>(args[i]);}
+	  else if (BCastTo<pf3r>(args[i])) {
+	      // cout << "BCastTo<pfer>(args[i])" << endl;
+	      l[i].composant=false;
+	      l[i].what=6; //  iso value 3d
+	      l[i][0]=CastTo<pf3r>(args[i]);}
+	  else if (BCastTo<pf3c>(args[i])) {
+	      // cout << "BCastTo<pfer>(args[i])" << endl;
+	      l[i].composant=false;
+	      l[i].what=16; //  iso value 3d
+	      l[i][0]=CastTo<pf3c>(args[i]);}
+          else if (BCastTo<pferarray>(args[i])) {
+              // cout << "BCastTo<pfer>(args[i])" << endl;
+              l[i].composant=false;
+              l[i].what=101; //  iso value array iso value 2d
+              l[i][0]=CastTo<pferarray>(args[i]);}
+          else if (BCastTo<pfecarray>(args[i])) {
+              // cout << "BCastTo<pfer>(args[i])" << endl;
+              l[i].composant=false;
+              l[i].what=111; //  iso value array iso value 2d
+              l[i][0]=CastTo<pfecarray>(args[i]);}
+          else if (BCastTo<pf3rarray>(args[i])) {
+              // cout << "BCastTo<pfer>(args[i])" << endl;
+              l[i].composant=false;
+              l[i].what=106; //arry iso value array iso value 3d
+              l[i][0]=CastTo<pf3rarray>(args[i]);}
+          else if (BCastTo<pf3carray>(args[i])) {
+              // cout << "BCastTo<pfer>(args[i])" << endl;
+              l[i].composant=false;
+              l[i].what=116; //arry iso value array iso value 3d
+              l[i][0]=CastTo<pf3carray>(args[i]);}
+	  else if (BCastTo<pmesh>(args[i])){
+	      l[i].composant=true;
+	      l[i].what=0; // mesh ... 
+	      l[i][0]=CastTo<pmesh>(args[i]);}
+	  else if (BCastTo<pmesh3>(args[i])){
+	      l[i].composant=true;
+	      l[i].what=5;// 3d mesh ...
+	      l[i][0]=CastTo<pmesh3>(args[i]);}
+	  else if (BCastTo<const E_BorderN *>(args[i])){
+	      // cout << "BCastTo<const E_BorderN*>(args[i])" << endl;
+	      l[i].what=4; // border 2d
+	      l[i].composant=true;
+	      l[i][0]=CastTo<const E_BorderN *>(args[i]);}
+	  else if (BCastTo<KN<pmesh> *>(args[i])){
+	      l[i].composant=true;
+	      // cout << "BCastTo<const E_BorderN*>(args[i])" << endl;
+	      l[i].what=100; //  mesh 2d array 
+	      l[i][0]=CastTo<KN<pmesh> *>(args[i]);}
+	  else {
+	      CompileError("Sorry no way to plot this kind of data");
+	  }
+    }
+    
+  static ArrayOfaType  typeargs() { return  ArrayOfaType(true);}// all type
+
+  /// <<Plot_f>> Creates a Plot object with the list of arguments obtained from the script during the grammatical
+  /// analysis of the script (in lg.ypp)
+
+  static  E_F0 * f(const basicAC_F0 & args) { return new Plot(args);} 
+
+  /// Evaluates the contents of the Plot object during script evaluation. Implemented at [[Plot_operator_brackets]]
+
+  AnyType operator()(Stack s) const ;
+}; 
+
+/// <<Plot_name_param>>
+
+basicAC_F0::name_and_type Plot::name_param[Plot::n_name_param] = {
+  {   "coef", &typeid(double)},
+  {   "cmm", &typeid(string*)},
+  {   "ps", &typeid(string*)  },
+  {   "wait", &typeid(bool) },
+  {   "fill", &typeid(bool) },
+  {   "value", &typeid(bool) },
+  {   "clean", &typeid(bool) },     
+  {   "aspectratio", &typeid(bool)},  
+  {   "bb",&typeid(E_Array) },
+  {   "nbiso", &typeid(long)}, 
+  {   "nbarrow", &typeid(long)}, 
+  {   "viso", &typeid(KN_<double>)},       
+  {   "varrow", &typeid(KN_<double>)},
+  {   "bw",&typeid(bool)},
+  {   "grey", &typeid(bool)},
+  {   "hsv", &typeid(KN_<double>)},
+  {   "boundary", &typeid(bool)}, // 16
+  {   "dim", &typeid(long)}, // 2 or 3 
+  {   "add", &typeid(bool)}, // add to previous plot
+  {   "prev", &typeid(bool)}, // keep previou  view point  
+  {   "ech", &typeid(double)}, // keep previou  view point 
+     
+  // FFCS: more options for VTK graphics (numbers are required for processing)
+
+  {"ZScale",&typeid(double)}, // #1
+  {"WhiteBackground",&typeid(bool)}, // #2
+  {"OpaqueBorders",&typeid(bool)}, // #3
+  {"BorderAsMesh",&typeid(bool)}, // #4
+  {"ShowMeshes",&typeid(bool)}, // #5
+  {"ColorScheme",&typeid(long)}, // #6
+  {"ArrowShape",&typeid(long)}, // #7
+  {"ArrowSize",&typeid(double)}, // #8
+  {"ComplexDisplay",&typeid(long)}, // #9
+  {"LabelColors",&typeid(bool)}, // #10
+  {"ShowAxes",&typeid(bool)}, // #11
+  {"CutPlane",&typeid(bool)}, // #12
+  {"CameraPosition",&typeid(KN_<double>)}, // #13
+  {"CameraFocalPoint",&typeid(KN_<double>)}, // #14
+  {"CameraViewUp",&typeid(KN_<double>)}, // #15
+  {"CameraViewAngle",&typeid(double)}, // #16
+  {"CameraClippingRange",&typeid(KN_<double>)}, // #17
+  {"CutPlaneOrigin",&typeid(KN_<double>)}, // #18
+  {"CutPlaneNormal",&typeid(KN_<double>)}, // #19
+  {"WindowIndex",&typeid(long)}, // #20
+  {"NbColorTicks",&typeid(long)}, // #21
+
+};
+
+
+
+template<class K>
+class pb2mat : public E_F0 { public:
+  typedef Matrice_Creuse<K> *  Result;
+  const Problem * pb;
+  pb2mat(const basicAC_F0 & args) : pb(dynamic_cast<const Problem *>(args[0].left()))  
+  {ffassert(pb);}
+  static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<const Problem *>());}
+  
+  static  E_F0 * f(const basicAC_F0 & args) { return new Plot(args);} 
+  
+  AnyType operator()(Stack s) const 
+  {
+    Problem::Data<FESpace> *data= pb->dataptr(this->stack); 
+    if ( SameType<K,double>::OK )
+      {
+	ffassert( !!data->AR);  
+	return  SetAny<Matrice_Creuse<K> * >(&data->AR) ;
+      }
+    else 
+      {
+	ffassert( !!data->AC);  
+	return SetAny<Matrice_Creuse<K> * >(&data->AC) ;
+      }
+  }
+  
+  
+};  
+
+
+//template<class RR,class A>  void PrintP(RR* a, A  b){  *a <<*b;}
+LinkToInterpreter::LinkToInterpreter()
+{
+   //P,N,x,y,z,label,region,nu_triangle;
+   P=make_Type_Expr(atype<R3*>(),new E_P_Stack_P);
+   x=make_Type_Expr(atype<R*>(),new E_P_Stack_Px);
+   y=make_Type_Expr(atype<R*>(),new E_P_Stack_Py);
+   z=make_Type_Expr(atype<R*>(),new E_P_Stack_Pz);
+   N=make_Type_Expr(atype<R3*>(),new E_P_Stack_N);
+   
+   region=make_Type_Expr(new E_P_Stack_Region,atype<long*>());
+   label=make_Type_Expr(new E_P_Stack_Label,atype<long*>());
+   nu_triangle= make_Type_Expr(atype<long>(),new E_P_Stack_Nu_Triangle);
+   nu_edge= make_Type_Expr(atype<long>(),new E_P_Stack_Nu_Edge);
+   lenEdge    = make_Type_Expr(atype<R>(),new E_P_Stack_lenEdge);
+   hTriangle  = make_Type_Expr(atype<R>(),new E_P_Stack_hTriangle);
+   area       = make_Type_Expr(atype<R>(),new E_P_Stack_areaTriangle);
+   volume       = make_Type_Expr(atype<R>(),new E_P_Stack_VolumeTet);
+   inside     = make_Type_Expr(atype<R>(),new E_P_Stack_inside);
+  Global.New("x",x);
+  Global.New("y",y);
+  Global.New("z",z);
+  Global.New("label",label);
+  Global.New("region",region);
+  Global.New("nuTriangle",nu_triangle);   
+  Global.New("nuEdge",nu_edge);   
+  Global.New("P",P);   
+  Global.New("N",N);   
+  
+  Global.New("lenEdge",lenEdge);   
+  Global.New("area",area);   
+  Global.New("volume",volume);   
+  Global.New("hTriangle",hTriangle);
+  Global.New("inside",inside);   
+  Global.New("nTonEdge",make_Type_Expr(atype<long>(),new E_P_Stack_nTonEdge));   
+  
+}
+
+
+
+
+template<class K>
+struct set_eqmatrice_creuse_fbl: public binary_function<Matrice_Creuse<K>*,const Matrice_Creuse<K>  *,const  C_args * > {
+  static Matrice_Creuse<K>* f(Matrice_Creuse<K>* const  & a,const  C_args * const & b)  {
+  // 1  verif the FESpace 
+  
+  // 2 set = or += 
+    
+    ffassert(0);
+    return a;}
+};
+
+template<class K>
+struct set_eqvect_fl: public binary_function<KN<K>*,const  FormLinear *,KN<K>*> {
+  static KN<K>* f(KN<K>* const  & a,const  FormLinear * const & b)  {
+    ffassert(0);
+    return a;}
+};
+  
+ template<class R> 
+  AnyType IntFunction<R>::operator()(Stack stack) const  { 
+  MeshPoint mp=* MeshPointStack(stack);
+ R r=0;
+ 
+ SHOWVERB(cout << " int " << endl);
+ const vector<Expression>  & what(di->what);
+ const int dim =di->d; 
+
+ const GQuadratureFormular<R1>& FIE = di->FIE(stack);
+ const GQuadratureFormular<R2> & FIT = di->FIT(stack);
+ const GQuadratureFormular<R3> & FIV = di->FIV(stack);
+
+ CDomainOfIntegration::typeofkind kind = di->kind;
+ set<int> setoflab;
+ bool all=true;
+      
+  if (verbosity>3)
+  {
+      if(dim==2)
+      {
+          if (CDomainOfIntegration::int1d==kind) cout << "  -- boundary int border ( nQP: "<< FIE.n << ") levelset: "<< di->islevelset() << " ,"  ;
+          else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges ( nQP: "<< FIE.n << "),"  ;
+          else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIE.n << ")," ;
+          else cout << "  --  int    (nQP: "<< FIT.n << " ) in "  ;
+      }
+      else if(dim==3)
+      {
+          if (CDomainOfIntegration::int2d==kind) cout << "  -- boundary int border ( nQP: "<< FIT.n << ") ,"  ;
+          else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all faces ( nQP: "<< FIT.n << "),"  ;
+          else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF face nQP: ("<< FIT.n << ")," ;
+          else cout << "  --  int    (nQP: "<< FIV.n << " ) in "  ;
+      }
+  }
+ /*
+   if ( verbosity>3) 
+   if (kind==CDomainOfIntegration::int1d) cout << "  -- boundary int border " ;
+   else if (kind==CDomainOfIntegration::intalledges) cout << "  -- boundary int all edges " ;
+   else if (kind==CDomainOfIntegration::intallVFedges) cout << "  -- boundary int all VF  edges " ;
+   else cout << "  -- boundary int  " ;*/
+      
+ Expandsetoflab(stack,*di, setoflab,all); 
+/*
+ for (size_t i=0;i<what.size();i++)
+   {
+     long  lab  = GetAny<long>( (*what[i])(stack));
+     setoflab.insert(lab);
+     if ( verbosity>3) cout << lab << " ";
+     all=false;
+   }
+ */
+      
+ if(dim==2)
+   {
+     if(di->islevelset() && (CDomainOfIntegration::int1d!=kind) &&  (CDomainOfIntegration::int2d!=kind) ) InternalError("So no levelset integration type  case (10 2d)");
+     const Mesh  & Th = * GetAny<pmesh>( (*di->Th)(stack) );
+     ffassert(&Th);
+     
+     if (verbosity >3) 
+     {
+       if (all) cout << " all " << endl ;
+       else cout << endl;
+     }
+     if (kind==CDomainOfIntegration::int1d)
+       {
+	 const QuadratureFormular1d & FI = FIE;
+           if(di->islevelset())
+           {
+               double llevelset = 0;
+               double uset = HUGE_VAL;
+               R2 Q[3];
+               KN<double> phi(Th.nv);phi=uset;
+               double f[3];
+               for(int t=0; t< Th.nt;++t)
+               {
+                   double umx=-HUGE_VAL,umn=HUGE_VAL;
+                   for(int i=0;i<3;++i)
+                   {
+                       int j= Th(t,i);
+                       if( phi[j]==uset)
+                       {
+                           MeshPointStack(stack)->setP(&Th,t,i);
+                           phi[j]= di->levelset(stack);//zzzz
+                       }
+                       f[i]=phi[j];
+                       umx = std::max(umx,phi[j]);
+                       umn = std::min(umn,phi[j]);
+                       
+                   }
+                   if( umn <=0 && umx >= 0)
+                   {
+                      
+                       int np= IsoLineK(f,Q,1e-10);
+                       if(np==2)
+                       {
+                           const Triangle & K(Th[t]);
+                           R2 PA(K(Q[0])),PB(K(Q[1]));
+                           R2 NAB(PA,PB);
+                           double  lAB=sqrt((NAB,NAB));
+                           NAB = NAB.perp()/lAB;
+                           llevelset += lAB;
+                           for (int npi=0;npi<FI.n;npi++) // loop on the integration point
+                           {
+                               QuadratureFormular1dPoint pi( FI[npi]);
+                               double sa=pi.x,sb=1.-sa;
+                               R2 Pt(Q[0]*sa+Q[1]*sb ); //
+                               MeshPointStack(stack)->set(Th,K(Pt),Pt,K,-1,NAB,-1);
+                               r += lAB*pi.a*GetAny<R>( (*fonc)(stack));
+                           }
+                       }
+                       
+                   }
+               }
+               if(verbosity > 5) cout << " Lenght level set = " << llevelset << endl;
+               
+           }
+
+        else
+	 for( int e=0;e<Th.neb;e++)
+	   {
+	     if (all || setoflab.find(Th.bedges[e].lab) != setoflab.end())   
+	       {     
+		 
+		 int ie,i =Th.BoundaryElement(e,ie);
+		 const Triangle & K(Th[i]);   
+		 R2 E=K.Edge(ie);
+		 double le = sqrt((E,E)); 
+		 R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+		   PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]);
+		 
+		 for (int npi=0;npi<FI.n;npi++) // loop on the integration point
+		   {
+		     QuadratureFormular1dPoint pi( FI[npi]);
+		     double sa=pi.x,sb=1.-sa;
+		     R2 Pt(PA*sa+PB*sb ); //  
+		     MeshPointStack(stack)->set(Th,K(Pt),Pt,K,Th.bedges[e].lab,R2(E.y,-E.x)/le,ie);
+		     r += le*pi.a*GetAny<R>( (*fonc)(stack));
+		   }
+	       }
+	   }
+       }
+     else if (kind==CDomainOfIntegration::int2d)
+     {
+         const QuadratureFormular & FI =FIT;
+
+         if(di->islevelset())
+         { // add FH mars 2014 compute int2d  on phi < 0 ..
+             double llevelset = 0;
+             double uset = HUGE_VAL;
+             R2 Q[3];
+             KN<double> phi(Th.nv);phi=uset;
+             double f[3],umx,umn;
+             for(int t=0; t< Th.nt;++t)
+             {
+                if (all || setoflab.find(Th[t].lab) != setoflab.end())
+                {
+                const Triangle & K(Th[t]);
+
+                 double umx=-HUGE_VAL,umn=HUGE_VAL;
+                 for(int i=0;i<3;++i)
+                 {
+                     int j= Th(t,i);
+                     if( phi[j]==uset)
+                     {
+                         MeshPointStack(stack)->setP(&Th,t,i);
+                         phi[j]= di->levelset(stack);//zzzz
+                     }
+                     f[i]=phi[j];
+                     umx = std::max(umx,phi[j]);
+                     umn = std::min(umn,phi[j]);
+                     
+                 }
+                 double area =K.area;
+                 if( umn >=0 ) continue; //  all positif => nothing
+                 if( umx >0 )
+                    { // coupe ..
+                        int i0 = 0, i1 = 1, i2 =2;
+                        
+                        if( f[i0] > f[i1] ) swap(i0,i1) ;
+                        if( f[i0] > f[i2] ) swap(i0,i2) ;
+                        if( f[i1] > f[i2] ) swap(i1,i2) ;
+                        
+                        double c = (f[i2]-f[i1])/(f[i2]-f[i0]); // coef Up Traing
+                        if( f[i1] < 0 ) {double y=f[i2]/(f[i2]-f[i1]); c *=y*y; }
+                        else {double y=f[i0]/(f[i0]-f[i1]) ; c = 1.- (1.-c)*y*y; };
+                        assert( c > 0 && c < 1);
+                        area *= 1-c;
+                    }
+                 //  warning  quadrature  wrong just ok for constante FH, we must also change the quadaturer points ..
+                 // just order 1  here ???
+                 for (int npi=0; npi<FI.n;npi++)
+                    {
+                        QuadraturePoint pi(FI[npi]);
+                        MeshPointStack(stack)->set(Th,K(pi),pi,K,K.lab);
+                        r += area*pi.a*GetAny<R>( (*fonc)(stack));
+                    }
+                    
+                }
+             }
+             
+         }
+      else
+       for (int i=0;i< Th.nt; i++)
+	 {
+	   const Triangle & K(Th[i]);
+	   if (all || setoflab.find(Th[i].lab) != setoflab.end()) 
+	     for (int npi=0; npi<FI.n;npi++)
+	       {
+		 QuadraturePoint pi(FI[npi]);
+		 MeshPointStack(stack)->set(Th,K(pi),pi,K,K.lab);                       
+		 r += K.area*pi.a*GetAny<R>( (*fonc)(stack)); 
+	       }
+	 }
+     }
+     else   if (kind==CDomainOfIntegration::intalledges)
+       {
+	 const QuadratureFormular1d & FI = FIE;
+	 for (int i=0;i< Th.nt; i++) 
+	   if (all || setoflab.find(Th[i].lab) != setoflab.end()) 
+	     for( int ie=0;ie<3;ie++)
+	       {                                
+		 const Triangle & K(Th[i]);   
+		 R2 E=K.Edge(ie);
+		 double le = sqrt((E,E)); 
+		 R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+		   PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]);
+                 
+		 for (int npi=0;npi<FI.n;npi++) // loop on the integration point
+		   {
+		     QuadratureFormular1dPoint pi( FI[npi]);
+		     double sa=pi.x,sb=1-sa;
+		     R2 Pt(PA*sa+PB*sb ); //  
+		     MeshPointStack(stack)->set(Th,K(Pt),Pt,K,K.lab,R2(E.y,-E.x)/le,ie);// correction FH 6/2/2014 
+		     r += le*pi.a*GetAny<R>( (*fonc)(stack));
+		   }
+	       }
+       }
+     else   if (kind==CDomainOfIntegration::intallVFedges)
+       {
+	 double untier(1./3.);
+	 cerr << " a faire CDomainOfIntegration::intallVFedges " << endl; //%%%%%%%%%
+	 ffassert(0);
+	 const QuadratureFormular1d & FI = FIE;
+	 for (int i=0;i< Th.nt; i++) 
+	   if (all || setoflab.find(Th[i].lab) != setoflab.end()) 
+	     {
+	       const Triangle & K(Th[i]);
+	       const R2 GH(untier,untier);
+	       const R2 G=K(GH);
+	       for( int ie=0;ie<3;ie++)
+		 { 
+		   int ie0=VerticesOfTriangularEdge[ie][0] ;
+		   int ie1=VerticesOfTriangularEdge[ie][1] ;
+		   const R2 MH=(TriangleHat[ie0]+TriangleHat[ie1])*0.5;
+		   const R2 M(K(MH)); 
+		   R2 E(G,M);
+		   double le = sqrt((E,E)); 
+                   
+		   for (int npi=0;npi<FI.n;npi++) // loop on the integration point
+		     {
+		       QuadratureFormular1dPoint pi( FI[npi]);
+		       double sa=pi.x,sb=1-sa;
+		       R2 Pt(GH*sa+MH*sb ); //  
+		       MeshPointStack(stack)->set(Th,K(Pt),Pt,K,Th[ie].lab,R2(E.y,-E.x)/le,ie,1);
+		       r += le*pi.a*GetAny<R>( (*fonc)(stack));
+		     }
+		 }
+	     }
+       }
+     else
+       {
+	 InternalError("CDomainOfIntegration kind unkown");
+       }            
+   }
+ else if(dim==3)
+   {
+     if(di->islevelset() &&  (CDomainOfIntegration::int2d!=kind) && (CDomainOfIntegration::int3d!=kind) )
+         InternalError("So no levelset integration type on no int2d / int3d case (10 3d)");
+      
+     const Mesh3  & Th = * GetAny<pmesh3>( (*di->Th)(stack) );
+     ffassert(&Th);
+     
+     if (verbosity >3) 
+       {
+	 if (all) cout << " all " << endl ;
+	 else cout << endl;
+       }
+       if (kind==CDomainOfIntegration::int2d)
+           if(di->islevelset())
+           {
+               const GQuadratureFormular<R2> & FI = FIT;
+               double llevelset = 0;
+               const double uset = std::numeric_limits<double>::max();
+              // cout << " uset ="<<uset << endl;
+               R3 Q[4];
+               KN<double> phi(Th.nv);
+               phi=uset;
+               double f[4];
+               
+               for(int t=0; t< Th.nt;++t)
+               {
+                   double umx=std::numeric_limits<double>::min(),umn=std::numeric_limits<double>::max();
+                   for(int i=0;i<4;++i)
+                   {
+                       int j= Th(t,i);
+                       if( phi[j]==uset)
+                       {
+                           MeshPointStack(stack)->setP(&Th,t,i);
+                           phi[j]= di->levelset(stack);//zzzz
+                       }
+                       f[i]=phi[j];
+                       umx = std::max(umx,f[i]);
+                       umn = std::min(umn,f[i]);
+                       
+                   }
+                   if( umn <=0 && umx >= 0)
+                   {
+                       
+                       int np= IsoLineK(f,Q,1e-10);
+
+                       double l[3];
+                       if(np>2)
+                       {
+                        if(verbosity>999)  cout << t << " int levelset : " << umn << " .. " << umx << " np " << np <<" "
+                         << f[0] << " " << f[1] << " "<< f[2] << " "<< f[3] << " "<<endl;
+                          
+                           const Mesh3::Element & K(Th[t]);
+                           double epsmes3=K.mesure()*K.mesure()*1e-18;
+                           R3 PP[4];
+                           for(int i=0; i< np; ++i)
+                               PP[i]= K(Q[i]);
+                           for( int i =0; i+1 < np; i+=2)
+                           { // 0,1,, a and 2,3,0.
+                               int i0=i,i1=i+1,i2=(i+2)%np;
+                               R3 NN= R3(PP[i0],PP[i1])^R3(PP[i0],PP[i2]);
+                               double mes2 = (NN,NN);
+                               double mes = sqrt(mes2);
+                               if(mes2*mes <epsmes3) continue; //  too small
+                               NN /= mes;
+                               mes *= 0.5; //   warning correct FH 050109
+                             //  cout <<i << " / "  << NN << " / " << mes <<" / "<< i0<< i1<< i2 <<" " << llevelset <<endl;
+                               llevelset += mes;
+                               for (int npi=0;npi<FI.n;npi++) // loop on the integration point
+                               {
+                                   GQuadraturePoint<R2>  pi( FI[npi]);
+                                   pi.toBary(l);
+                                   R3 Pt( l[0]*Q[i0]+l[1]*Q[i1]+l[2]*Q[i2]); //
+                                   MeshPointStack(stack)->set(Th,K(Pt),Pt,K,-1,NN,-1);
+                                   r += mes*pi.a*GetAny<R>( (*fonc)(stack));
+                               }
+                           }
+                       }
+                       
+                   }
+               }
+               if(verbosity > 5) cout << " Area level set = " << llevelset << endl;
+              // if(verbosity > 50) cout << "phi " << phi << endl;
+               
+           }
+       
+         else
+        
+       {
+	 const GQuadratureFormular<R2> & FI = FIT;
+         int lab;
+	 for( int e=0;e<Th.nbe;e++)
+	   {
+	     if (all || setoflab.find(lab=Th.be(e).lab) != setoflab.end())   
+	       {     
+		 
+		 int ie,i =Th.BoundaryElement(e,ie);
+		 const Mesh3::Element & K(Th[i]);   
+		 R3 NN=K.N(ie);
+		 double mes = sqrt((NN,NN)); 
+		 NN /= mes; 
+		 mes *= 0.5; //   warning correct FH 050109
+		 for (int npi=0;npi<FI.n;npi++) // loop on the integration point
+		   {
+		     GQuadraturePoint<R2> pi( FI[npi]);
+		     R3 Pt(K.PBord(ie,pi)); //  
+		     MeshPointStack(stack)->set(Th,K(Pt),Pt,K,lab,NN,ie);
+		     r += mes*pi.a*GetAny<R>( (*fonc)(stack));
+		   }
+	       }
+	   }
+       }
+     else if (kind==CDomainOfIntegration::int3d)
+     {
+       
+         if(di->islevelset())
+         {   // int3d levelset < 0
+             GQuadratureFormular<R3> FI(FIV.n*3);
+             double llevelset = 0;
+             const double uset = std::numeric_limits<double>::max();
+             // cout << " uset ="<<uset << endl;
+             R3 Q[3][4];
+             double vol6[3];
+             KN<double> phi(Th.nv);
+             phi=uset;
+             double f[4];
+             
+             for (int t=0;t< Th.nt; t++)
+             {
+                 
+		 const Mesh3::Element & K(Th[t]);
+		 if (all || setoflab.find(K.lab) != setoflab.end())
+                 {
+                     double umx=std::numeric_limits<double>::min(),umn=std::numeric_limits<double>::max();
+                     for(int i=0;i<4;++i)
+                     {
+                         int j= Th(t,i);
+                         if( phi[j]==uset)
+                         {
+                             MeshPointStack(stack)->setP(&Th,t,i);
+                             phi[j]= di->levelset(stack);//zzzz
+                         }
+                         f[i]=phi[j];
+                     }
+                     int ntets= UnderIso(f,Q, vol6,1e-14);
+                     setQF<R3>(FI,FIV,QuadratureFormular_Tet_1, Q,vol6,ntets);
+                     for (int npi=0; npi<FI.n;npi++)
+                     {
+                         GQuadraturePoint<R3> pi(FI[npi]);
+                         MeshPointStack(stack)->set(Th,K(pi),pi,K,K.lab);
+                         r += K.mesure()*pi.a*GetAny<R>( (*fonc)(stack));
+                     }
+                 }
+             }
+
+            
+         }
+        else
+         {
+       const GQuadratureFormular<R3> & FI =FIV;
+             for (int i=0;i< Th.nt; i++) 
+	       {
+		 const Mesh3::Element & K(Th[i]);
+		 if (all || setoflab.find(K.lab) != setoflab.end()) 
+		   for (int npi=0; npi<FI.n;npi++)
+                     {
+                       GQuadraturePoint<R3> pi(FI[npi]);
+                       MeshPointStack(stack)->set(Th,K(pi),pi,K,K.lab);                       
+                       r += K.mesure()*pi.a*GetAny<R>( (*fonc)(stack)); 
+                     }
+               }
+         }
+     }
+     else   if (kind==CDomainOfIntegration::intalledges)
+       {
+         const GQuadratureFormular<R2> & FI = FIT;
+         int lab;
+	 for (int i=0;i< Th.nt; i++) 
+	   if (all || setoflab.find(Th[i].lab) != setoflab.end()) 
+	     for( int ie=0;ie<3;ie++)
+	       {                                
+		 const Mesh3::Element  & K(Th[i]);   
+		 R3 NN=K.N(ie);
+		 double mes = NN.norme(); 
+		   NN /= mes;
+		   mes*=0.5;//  correction 05/01/09 FH 
+		 for (int npi=0;npi<FI.n;npi++) // loop on the integration point
+		   {
+		     GQuadraturePoint<R2> pi( FI[npi]);
+		     R3 Pt(K.PBord(ie,pi)); //  
+		     MeshPointStack(stack)->set(Th,K(Pt),Pt,K,lab,NN,ie);
+		     r += mes*pi.a*GetAny<R>( (*fonc)(stack));
+		   }
+	       }
+       }
+
+   }
+ else {  InternalError("CDomainOfIntegration dim unkown");}
+ 
+ *MeshPointStack(stack)=mp;
+     return SetAny<R>(r);
+  }
+  
+void Show(const char * s,int k=1)
+{
+  if(k) {
+  couleur(1);
+  float xmin,xmax,ymin,ymax;
+       getcadre(xmin,xmax,ymin,ymax);
+       rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30);
+       plotstring(s);
+       //  couleur(1);	
+  }
+}
+template<class K,class v_fes>
+int Send2d(PlotStream & theplot,Plot::ListWhat & lli,map<const typename v_fes::FESpace::Mesh *,long> & mapth)
+{
+    typedef FEbase<K,v_fes> * pfek ;
+    pfek fe[3]={0,0,0};
+    int cmp[3]={-1,-1,-1};
+    int err=1;
+    long what=lli.what;
+    int lg,nsb;
+    lli.eval(fe,cmp);		    
+    if (fe[0]->x() && what %10 ==1) 
+	{		 
+	      err=0;
+	      theplot << what ;
+	      theplot <<mapth[ &(fe[0]->Vh->Th)];// numero du maillage
+	      KN<K> V1=fe[0]->Vh->newSaveDraw(*fe[0]->x(),cmp[0],lg,nsb);
+	      
+	      // construction of the sub division ... 
+	      int nsubT=NbOfSubTriangle(nsb);
+	      int nsubV=NbOfSubInternalVertices(nsb);
+	      KN<R2> Psub(nsubV);
+	      KN<int> Ksub(nsubT*3);
+	      for(int i=0;i<nsubV;++i)
+	      Psub[i]=SubInternalVertex(nsb,i);
+	      //cout << " Psub " << Psub <<endl;
+	      for(int sk=0,p=0;sk<nsubT;++sk)
+	      for(int i=0;i<3;++i,++p)
+	      Ksub[p]=numSubTriangle(nsb,sk,i);
+	      
+	      if(verbosity>9)
+	      cout << " Send plot:what: " << what << " " << nsb << " "<< V1.N() 
+	      << " Max "  << V1.max() << " min " << V1.min() << endl;
+	      theplot << Psub ;
+	      theplot << Ksub ;
+	      theplot << V1;
+	      // theplot << (long) nsb<< V1;
+	      
+	      }
+    else if (fe[0]->x() && fe[1]->x() &&what %10 ==2)   
+      {
+	
+	{
+	  err=0;
+	  theplot << what ;
+	  
+	  
+	  KN<K> V1=fe[0]->Vh->newSaveDraw(*fe[0]->x(),*fe[1]->x(),cmp[0],cmp[1],lg,nsb);
+	  // construction of the sub division ... 
+	  int nsubT=NbOfSubTriangle(nsb);
+	  int nsubV=NbOfSubInternalVertices(nsb);
+	  KN<R2> Psub(nsubV);
+	  KN<int> Ksub(nsubT*3);
+	  for(int i=0;i<nsubV;++i)
+	      Psub[i]=SubInternalVertex(nsb,i);
+	  for(int sk=0,p=0;sk<nsubT;++sk)
+	      for(int i=0;i<3;++i,++p)
+		  Ksub[p]=numSubTriangle(nsb,sk,i);
+	  
+	  theplot <<mapth[ &(fe[0]->Vh->Th)];// numero du maillage
+	  theplot << Psub ;
+	  theplot << Ksub ;
+	  theplot <<  V1;
+	  
+	  // theplot << (long) nsb<< V1;
+	}
+	
+      }
+    return err;
+	      
+}
+
+template<class K,class v_fes>
+int Send3d(PlotStream & theplot,Plot::ListWhat &lli,map<const typename v_fes::FESpace::Mesh *,long> &mapth3)
+{
+    typedef FEbase<K,v_fes> * pfek3 ;
+    pfek3 fe3[3]={0,0,0};
+    int cmp[3]={-1,-1,-1};
+    int err=1;
+    long what=lli.what;
+    int lg,nsb;
+    if (what%10==6)
+    {    
+	int lg,nsb;
+	lli.eval(fe3,cmp);
+	// FFCS is able to display 3d complex data
+	//if(what==6)
+	  {
+	    if (fe3[0]->x()) 
+	      {		 
+		  err=0;
+		  theplot << what ;
+		  theplot <<mapth3[ &(fe3[0]->Vh->Th)];// numero du maillage
+		  // KN<R>  GFESpace<MMesh>::newSaveDraw(const KN_<R> & U,int composante,int & lg,
+		  //   KN<Rd> &Psub,KN<int> &Ksub,int op_U) const
+		  KN<R3> Psub;
+		  KN<int> Ksub;
+		  KN<K> V1=fe3[0]->Vh->newSaveDraw(*fe3[0]->x(),cmp[0],lg,Psub,Ksub,0);
+		  if(verbosity>9)
+		      cout << " Send plot:what: " << what << " " << nsb << " "<< V1.N() 
+		      << " "  << V1.max() << " " << V1.min() << endl;
+		  theplot << Psub ;
+		  theplot << Ksub ;
+		  theplot << V1;
+	      }
+	  }
+    }
+    else  if (what%10==7)
+      {    
+	  int lg,nsb;
+	  lli.eval(fe3,cmp);
+	  // FFCS is able to display 3d complex data
+	  //if(what==7) // ve
+	    {
+	      if (fe3[0]->x()&& fe3[1]->x() && fe3[2]->x()) 
+		{		 
+		    err=0;
+		    theplot << what ;
+		    theplot <<mapth3[ &(fe3[0]->Vh->Th)];// numero du maillage
+		    // KN<R>  GFESpace<MMesh>::newSaveDraw(const KN_<R> & U,int composante,int & lg,
+		    //   KN<Rd> &Psub,KN<int> &Ksub,int op_U) const
+		    KN<R3> Psub1,Psub2,Psub3; // bf Bof ...
+		    KN<int> Ksub1,Ksub2,Ksub3;
+		    KN<K> V1=fe3[0]->Vh->newSaveDraw(*fe3[0]->x(),cmp[0],lg,Psub1,Ksub1,0);
+		    KN<K> V2=fe3[1]->Vh->newSaveDraw(*fe3[1]->x(),cmp[1],lg,Psub2,Ksub2,0);
+		    KN<K> V3=fe3[2]->Vh->newSaveDraw(*fe3[2]->x(),cmp[2],lg,Psub3,Ksub3,0);
+		    if(verbosity>9)
+			cout << " Send plot:what: " << what << " " << nsb << " "<< V1.N() 
+			<< " "  << V1.max() << " " << V1.min() << endl;
+		    theplot << Psub1 ;
+		    theplot << Ksub1 ;
+		    ffassert( V1.N() == V2.N()  &&V1.N() == V3.N()); 
+		    KNM<K> V123(3,V1.N()); // warning fortran numbering ...
+		    V123(0,'.')=V1;
+		    V123(1,'.')=V2;
+		    V123(2,'.')=V3;
+		    // FFCS: should be able to deal with complex as well
+		    theplot << (KN_<K>&) V123;
+		    
+		}
+	    }
+      }
+    return err;
+}
+   
+/// <<Plot_operator_brackets>> from class [[Plot]]
+
+AnyType Plot::operator()(Stack s) const{ 
+    
+   // remap  case 107 and 108 , 109  for array of FE. 
+  vector<ListWhat> ll;
+  ll.reserve(l.size());
+  // generation de la list de plot ...
+    for (size_t i=0;i<l.size();i++)
+      {
+	  //KN<pmesh > * ath;
+	  //pmesh th;
+	  //int cmp0=0,cmp1=1,cmp2=2;
+	  switch (l[i].what) {
+	      case 0:
+	      case 5:  
+	        l[i].EvalandPush<void *>(s,i,ll);		
+		break;
+	      case 1:
+	      case 2:
+	      case 6 :
+	      case 7 :		  
+	      case 11:
+	      case 12:
+	      case 16 :
+	      case 17 :		  
+	       l[i].EvalandPush<void *>(s,i,ll);break;
+			      		  
+	      case  100 : l[i].MEvalandPush< pmesh>(s,i,ll);break;
+	      case  105 : l[i].MEvalandPush< pmesh3>(s,i,ll);break;
+	      case  101 : l[i].AEvalandPush<asol, sol>(s,i,ll);break;
+	      case  106 : l[i].AEvalandPush<asol3, sol3>(s,i,ll);break;
+              case  111:  l[i].AEvalandPush<asolc, solc>(s,i,ll);break;  
+              case  116:  l[i].AEvalandPush<asolc3, solc3>(s,i,ll);break; 
+	        
+
+		  
+	      default:
+		  ffassert(l[i].what<100) ; // missing piece of code FH (jan 2010) ...
+		  ll.push_back(ListWhat(l[i].what,i));
+		  break;
+	  }
+	  
+      }
+    
+  if(ThePlotStream)
+    { 
+	/*
+	 les different item of the plot are given by the number what:
+	 what = 0 -> mesh
+	 what = 1 -> scalar field (FE function  2d) 
+	 what = 2 -> 2d vector field (two FE function  2d) 
+	 what = 3 -> curve def by 2 plot
+	 what = 4 -> border 
+	 what = 5 3d meshes
+	 what = 6  FE function 3d
+	 what = 100,101,106 //  remap ...
+	 what = 7 => 3d vector field (tree FE function  3d) 
+	 what = 8 ???
+	 what = -1 -> error, item empty 
+	 */
+	PlotStream theplot(ThePlotStream);
+	pferbase  fe[3]={0,0,0};
+	pf3rbase  fe3[3]={0,0,0};
+	double echelle=1;
+	int cmp[3]={-1,-1,-1};
+	theplot.SendNewPlot();
+	if (nargs[0]) (theplot<< 0L) <=  GetAny<double>((*nargs[0])(s));
+	if (nargs[1]) (theplot<< 1L) <=  GetAny<string *>((*nargs[1])(s));
+	if (nargs[2]) (theplot<< 2L) <=  GetAny<string*>((*nargs[2])(s));
+	if (nargs[3]) (theplot<< 3L)  <= (bool) (!NoWait &&  GetAny<bool>((*nargs[3])(s)));
+	else (theplot<< 3L)  <=  (bool)  (TheWait&& !NoWait);
+	if (nargs[4]) (theplot<< 4L)  <= GetAny<bool>((*nargs[4])(s));
+	if (nargs[5]) (theplot<< 5L) <=  GetAny<bool>((*nargs[5])(s));
+	if (nargs[6]) (theplot<< 6L) <=  GetAny<bool>((*nargs[6])(s));
+	if (nargs[7]) (theplot<< 7L)  <= GetAny<bool>((*nargs[7])(s));
+	if (nargs[8])  
+	  {  KN<double> bbox(4);
+	      for (int i=0;i<4;i++)
+		  bbox[i]= GetAny<double>((*bb[i])(s));
+	      
+	      (theplot<< 8L) <= bbox ;
+	  }
+	if (nargs[9])  (theplot<< 9L)   <=  GetAny<long>((*nargs[9])(s));
+	if (nargs[10])  (theplot<< 10L) <= GetAny<long>((*nargs[10])(s));
+	if (nargs[11]) { 
+	    KN_<double> v =GetAny<KN_<double> >((*nargs[11])(s)) ;
+	(theplot<< 11L)  <= v   ;}
+	
+	if (nargs[12]) 
+	    (theplot<< 12L) <=  GetAny<KN_<double> >((*nargs[12])(s)) ;
+	
+	
+	
+	if (nargs[13]) (theplot<< 13L)  <= GetAny<bool>((*nargs[13])(s));
+	if (nargs[14]) (theplot<< 14L) <= GetAny<bool>((*nargs[14])(s));
+	if (nargs[15]) 
+	    (theplot<< 15L)  <= GetAny<KN_<double> >((*nargs[15])(s));
+	if (nargs[16]) (theplot<< 16L)  <= GetAny<bool>((*nargs[16])(s));
+	// add frev 2008 FH for 3d plot ...
+	if (nargs[17]) (theplot<< 17L)  <= GetAny<long>((*nargs[17])(s));
+	if (nargs[18]) (theplot<< 18L)  <= GetAny<bool>((*nargs[18])(s));
+	if (nargs[19]) (theplot<< 19L)  <= GetAny<bool>((*nargs[19])(s));
+	if (nargs[20]) (theplot<< 20L)  <= (echelle=GetAny<double>((*nargs[20])(s)));
+
+	// FFCS: extra plot options for VTK (indexed from 1 to keep these lines unchanged even if the number of standard
+	// FF parameters above changes) received in [[file:../../../../src/visudata.cpp::receiving_plot_parameters]]
+
+#define VTK_START 20
+#define SEND_VTK_PARAM(index,type)					\
+	  if(nargs[VTK_START+index])					\
+	    (theplot<<(long)(VTK_START+index))				\
+	      <=GetAny<type>((*nargs[VTK_START+index])(s));
+
+	SEND_VTK_PARAM(1,double); // ZScale
+	SEND_VTK_PARAM(2,bool); // WhiteBackground
+	SEND_VTK_PARAM(3,bool); // OpaqueBorders
+	SEND_VTK_PARAM(4,bool); // BorderAsMesh
+	SEND_VTK_PARAM(5,bool); // ShowMeshes
+	SEND_VTK_PARAM(6,long); // ColorScheme
+	SEND_VTK_PARAM(7,long); // ArrowShape
+	SEND_VTK_PARAM(8,double); // ArrowSize
+	SEND_VTK_PARAM(9,long); // ComplexDisplay
+	SEND_VTK_PARAM(10,bool); // LabelColors
+	SEND_VTK_PARAM(11,bool); // ShowAxes
+	SEND_VTK_PARAM(12,bool); // CutPlane
+	SEND_VTK_PARAM(13,KN_<double>); // CameraPosition
+	SEND_VTK_PARAM(14,KN_<double>); // CameraFocalPoint
+	SEND_VTK_PARAM(15,KN_<double>); // CameraViewUp
+	SEND_VTK_PARAM(16,double); // CameraViewAngle
+	SEND_VTK_PARAM(17,KN_<double>); // CameraClippingRange
+	SEND_VTK_PARAM(18,KN_<double>); // CutPlaneOrigin
+	SEND_VTK_PARAM(19,KN_<double>); // CutPlaneNormal
+	SEND_VTK_PARAM(20,long); // WindowIndex
+	SEND_VTK_PARAM(21,long); // NbColorTicks
+
+	theplot.SendEndArgPlot();
+	map<const Mesh *,long> mapth;
+	map<const Mesh3 *,long> mapth3;
+	long kth=0,kth3=0;
+	//  send all the mesh: 
+	for (size_t ii=0;ii<ll.size();ii++)
+	  {
+	      int i=ll[ii].i;
+	      long what = ll[i].what;
+	      const Mesh *th=0;
+	      const Mesh3 *th3=0;
+	      if(what ==0)
+		  th= ll[ii].th();
+	      if( what ==5 )
+		  th3= & (l[i].evalm3(0,s));	      
+	      else if (what==1 || what==2|| what==11 || what==12)
+		{   
+		    
+		    ll[ii].eval(fe,cmp);		    
+		    if (fe[0]->x()) th=&fe[0]->Vh->Th;
+		    if(fe[1] && fe[1]->x()) {
+			ffassert(th == &fe[1]->Vh->Th);			
+			//    assert(th);
+		    };
+		}
+	      else if (what==6 || what==7|| what==16 || what==17)
+		{   
+		    ll[ii].eval(fe3,cmp);
+		    if (fe3[0]->x()) th3=&fe3[0]->Vh->Th;
+		    if (fe3[1]) ffassert(th3 == &fe3[1]->Vh->Th);
+		    if (fe3[2]) ffassert(th3 == &fe3[2]->Vh->Th);
+		    
+		}
+	      
+	      if(th && mapth.find(th)==mapth.end()) 
+		  mapth[th]=++kth;
+	      
+	      if(th3 && (mapth3.find(th3)==mapth3.end()))
+		  mapth3[th3]=++kth3;
+	      
+	  }
+	theplot.SendMeshes();
+	theplot << kth ;
+	for (map<const Mesh *,long>::const_iterator i=mapth.begin();i != mapth.end(); ++i)
+	  {
+	      theplot << i->second << *  i->first ;
+	  }
+	//  3d meshes 	
+	if(kth3)
+	  {
+	      theplot.SendMeshes3();
+	      theplot << kth3 ;
+	      for (map<const Mesh3 *,long>::const_iterator i=mapth3.begin();i != mapth3.end(); ++i)
+		{
+		    theplot << i->second << *  i->first ;
+		}
+	      
+	  }
+	theplot.SendPlots();	
+	theplot <<(long) ll.size(); 
+	for (size_t ii=0;ii<ll.size();ii++)
+	  {
+	      int i=ll[ii].i;
+	      long what = ll[ii].what;
+	      int err =1;//  by default we are in error
+	      const Mesh *pTh=0;
+	      const Mesh3 *pTh3=0;
+	      // long what = l[i].what;
+	      if(what ==0)
+		{
+		    pTh=ll[ii].th();
+		    if(pTh) {
+			err=0;
+			theplot << what ; 
+			theplot <<mapth[ ll[ii].th() ];// numero du maillage
+		    }
+		}
+	    
+	      else if (what==1 || what==2 )
+		  err = Send2d<R,v_fes>( theplot,ll[ii] ,mapth);
+	      else if (what==11 || what==12 )
+		  err = Send2d<Complex,v_fes>( theplot,ll[ii] ,mapth);
+		  
+		  
+		  /*
+		{    
+		    int lg,nsb;
+		    ll[ii].eval(fe,cmp);		    
+		    if(what==1)
+		      {
+			  if (fe[0]->x()) 
+			    {		 
+				err=0;
+				theplot << what ;
+				theplot <<mapth[ &(fe[0]->Vh->Th)];// numero du maillage
+				KN<double> V1=fe[0]->Vh->newSaveDraw(*fe[0]->x(),cmp[0],lg,nsb);
+				
+				// construction of the sub division ... 
+				int nsubT=NbOfSubTriangle(nsb);
+				int nsubV=NbOfSubInternalVertices(nsb);
+				KN<R2> Psub(nsubV);
+				KN<int> Ksub(nsubT*3);
+				for(int i=0;i<nsubV;++i)
+				    Psub[i]=SubInternalVertex(nsb,i);
+				//cout << " Psub " << Psub <<endl;
+				for(int sk=0,p=0;sk<nsubT;++sk)
+				    for(int i=0;i<3;++i,++p)
+					Ksub[p]=numSubTriangle(nsb,sk,i);
+				
+				if(verbosity>9)
+				    cout << " Send plot:what: " << what << " " << nsb << " "<< V1.N() 
+				    << " "  << V1.max() << " " << V1.min() << endl;
+				theplot << Psub ;
+				theplot << Ksub ;
+				theplot << V1;
+				// theplot << (long) nsb<< V1;
+				
+			    }
+		      }
+		    else
+		      {
+			  if ( fe[0]->x() && fe[1]->x())
+			    {
+				err=0;
+				theplot << what ;
+				
+				
+				KN<double> V1=fe[0]->Vh->newSaveDraw(*fe[0]->x(),*fe[1]->x(),cmp[0],cmp[1],lg,nsb);
+				// construction of the sub division ... 
+				int nsubT=NbOfSubTriangle(nsb);
+				int nsubV=NbOfSubInternalVertices(nsb);
+				KN<R2> Psub(nsubV);
+				KN<int> Ksub(nsubT*3);
+				for(int i=0;i<nsubV;++i)
+				    Psub[i]=SubInternalVertex(nsb,i);
+				for(int sk=0,p=0;sk<nsubT;++sk)
+				    for(int i=0;i<3;++i,++p)
+					Ksub[p]=numSubTriangle(nsb,sk,i);
+				
+				theplot <<mapth[ &(fe[0]->Vh->Th)];// numero du maillage
+				theplot << Psub ;
+				theplot << Ksub ;
+				theplot <<  V1;
+				
+				// theplot << (long) nsb<< V1;
+			    }
+		      }
+		}*/	    
+		  else if (l[i].what==3 )
+		{
+		    tab x=l[i].evalt(0,s);
+		    tab y=l[i].evalt(1,s);
+		    if( x.N() >0 && y.N() == x.N())
+		      {
+			  err=0; // correction dec 2008 FH 
+			  theplot << what ;
+			  theplot << x << y ;
+		      }
+		    else  
+		      {
+			  if(verbosity)
+			      cerr << "Warning:  Plot of array with wrong size (item "<< i + 1 
+			      << ") sizes = " << x.size()<< " , " << y.size()  << endl;
+		      }
+		    
+		}
+	      else if (l[i].what==4 )
+		{
+		    err=0;
+		    theplot << what ;
+		    const  E_BorderN * Bh= l[i].evalb(0,s);
+		    Bh->SavePlot(s,theplot);
+		}
+	      else if(what ==5)
+		{
+		    pTh3=&l[i].evalm3(0,s);
+		    if(pTh3) {
+			err=0;
+			theplot << what ; 
+			theplot <<mapth3[ &l[i].evalm3(0,s)];// numero du maillage
+		    }
+		}
+	      else  if (what==6 ||what==7 ) 
+		  err = Send3d<R,v_fes3>( theplot,ll[ii] ,mapth3);
+	      else if (what==16 || what==17 )
+		  err = Send3d<Complex,v_fes3>( theplot,ll[ii] ,mapth3);
+	    
+		/*
+		{    
+		    int lg,nsb;
+		    ll[ii].eval(fe3,cmp);
+		    if(what==6)
+		      {
+			  if (fe3[0]->x()) 
+			    {		 
+				err=0;
+				theplot << what ;
+				theplot <<mapth3[ &(fe3[0]->Vh->Th)];// numero du maillage
+				// KN<R>  GFESpace<MMesh>::newSaveDraw(const KN_<R> & U,int composante,int & lg,
+				//   KN<Rd> &Psub,KN<int> &Ksub,int op_U) const
+				KN<R3> Psub;
+				KN<int> Ksub;
+				KN<double> V1=fe3[0]->Vh->newSaveDraw(*fe3[0]->x(),cmp[0],lg,Psub,Ksub,0);
+				if(verbosity>9)
+				    cout << " Send plot:what: " << what << " " << nsb << " "<< V1.N() 
+				    << " "  << V1.max() << " " << V1.min() << endl;
+				theplot << Psub ;
+				theplot << Ksub ;
+				theplot << V1;
+			    }
+		      }
+		}
+	      else  if (what==7)
+		{    
+		    int lg,nsb;
+		    ll[ii].eval(fe3,cmp);
+		    if(what==7) // ve
+		      {
+			if (fe3[0]->x()&& fe3[1]->x() && fe3[2]->x()) 
+			  {		 
+			      err=0;
+			      theplot << what ;
+			      theplot <<mapth3[ &(fe3[0]->Vh->Th)];// numero du maillage
+			      // KN<R>  GFESpace<MMesh>::newSaveDraw(const KN_<R> & U,int composante,int & lg,
+			      //   KN<Rd> &Psub,KN<int> &Ksub,int op_U) const
+			      KN<R3> Psub1,Psub2,Psub3; // bf Bof ...
+			      KN<int> Ksub1,Ksub2,Ksub3;
+			      KN<double> V1=fe3[0]->Vh->newSaveDraw(*fe3[0]->x(),cmp[0],lg,Psub1,Ksub1,0);
+			      KN<double> V2=fe3[1]->Vh->newSaveDraw(*fe3[1]->x(),cmp[1],lg,Psub2,Ksub2,0);
+			      KN<double> V3=fe3[2]->Vh->newSaveDraw(*fe3[2]->x(),cmp[2],lg,Psub3,Ksub3,0);
+			      if(verbosity>9)
+				  cout << " Send plot:what: " << what << " " << nsb << " "<< V1.N() 
+				  << " "  << V1.max() << " " << V1.min() << endl;
+			      theplot << Psub1 ;
+			      theplot << Ksub1 ;
+			      ffassert( V1.N() == V2.N()  &&V1.N() == V3.N()); 
+			      KNM<double> V123(3,V1.N()); // warning fortran numbering ...
+			      V123(0,'.')=V1;
+			      V123(1,'.')=V2;
+			      V123(2,'.')=V3;
+			      theplot << (KN_<double>&) V123;
+			     
+			  }
+		      }
+		}*/
+	    
+	      else 
+		  ffassert(0);// erreur type theplot inconnue
+	      if(err==1)
+		{ if(verbosity) 
+		    cerr << "Warning: May be a bug in your script, \n" 
+		    << " a part of the plot is wrong t (mesh or FE function, curve)  => skip the item  " << i+1 
+		    << " in plot command " << endl;
+		    theplot << -1L << (long) i ;
+		}
+	      
+	      
+	  }
+	theplot.SendEndPlot();
+    } 
+  if (!withrgraphique) {initgraphique();withrgraphique=true;}
+  viderbuff();
+  MeshPoint *mps=MeshPointStack(s),mp=*mps ;
+  int nbcolors=0;
+  float *colors=0;
+  bool hsv=true; // hsv  type 
+  R boundingbox[4];
+  double coeff=1;
+  bool wait=TheWait;
+  bool value=false;
+  bool fill=false;
+  bool aspectratio=false;
+  bool clean=true;
+  bool uaspectratio=false;
+  bool pViso=false,pVarrow=false;
+  int Niso=20,Narrow=20;
+    
+  KN<R> Viso,Varrow;
+        
+  bool bw=false;
+  string * psfile=0;
+  string * cm=0;
+  pferbase  fe=0,fe1=0;
+  int cmp0,cmp1;
+  bool grey=getgrey();
+  bool greyo=grey;
+  bool drawborder=true;
+  if (nargs[0]) coeff= GetAny<double>((*nargs[0])(s));
+  if (nargs[1]) cm = GetAny<string *>((*nargs[1])(s));
+  if (nargs[2]) psfile= GetAny<string*>((*nargs[2])(s));
+  if (nargs[3]) wait= GetAny<bool>((*nargs[3])(s));
+  if (nargs[4]) fill= GetAny<bool>((*nargs[4])(s));
+  if (nargs[5]) value= GetAny<bool>((*nargs[5])(s));
+  if (nargs[6]) clean= GetAny<bool>((*nargs[6])(s));
+  if (nargs[7]) uaspectratio=true,uaspectratio= GetAny<bool>((*nargs[7])(s));
+  if (nargs[8])  
+    for (int i=0;i<4;i++)
+      boundingbox[i]= GetAny<double>((*bb[i])(s));
+  if (nargs[9]) Niso=  GetAny<long>((*nargs[9])(s));
+  if (nargs[10]) Narrow=  GetAny<long>((*nargs[10])(s));
+  if (nargs[11]) { 
+    KN_<double> v =GetAny<KN_<double> >((*nargs[11])(s)) ;
+    Niso=v.N();
+    Viso.init(Niso);
+    Viso=v;
+    pViso=true;}
+          
+  if (nargs[12]) {
+    KN_<double> v =GetAny<KN_<double> >((*nargs[12])(s)) ;
+    Niso=v.N();
+    Varrow.init(Niso);
+    Varrow=v;
+    pVarrow=true;
+  }
+                 
+  if (nargs[13]) bw= GetAny<bool>((*nargs[13])(s));
+  if (nargs[14]) grey= GetAny<bool>((*nargs[14])(s));
+  if (nargs[15]) {  
+    KN_<double> cc= GetAny<KN_<double> >((*nargs[15])(s));
+    nbcolors= cc.N()/3;
+    if ( nbcolors > 1&& nbcolors < 100)
+      {
+	colors = new float [nbcolors*3];
+	for (int i=0; i<3*nbcolors; i++) colors[i]=cc[i];
+      }
+    else nbcolors = 0;
+  }
+  if (nargs[16]) drawborder= GetAny<bool>((*nargs[16])(s));
+  int   dimplot=2;
+  if (nargs[17]) dimplot= GetAny<long>((*nargs[17])(s));
+  bool addtoplot=false, keepPV=false;
+  if (nargs[18]) addtoplot= GetAny<bool>((*nargs[18])(s));
+  if (nargs[19]) keepPV= GetAny<bool>((*nargs[19])(s));
+
+  //  for the gestion of the PTR. 
+  WhereStackOfPtr2Free(s)=new StackOfPtr2Free(s);// FH aout 2007 
+	
+  setgrey(grey);
+  if (Viso.unset()) Viso.init(Niso);
+  if (Varrow.unset()) Varrow.init(Narrow);
+    
+  // KN<R> Viso(Niso);
+  // KN<R> Varrow(Narrow);
+  // if (pViso) Viso=*pViso;
+  // if (pVarrow) Varrow=*pVarrow;
+  const Mesh * cTh=0;
+  bool vecvalue=false,isovalue=false;
+  bool ops=psfile;
+  bool drawmeshes=false;
+  if ( clean ) {
+    reffecran(); 
+
+    if (psfile) {
+      openPS(psfile->c_str());
+    }
+    if (bw) NoirEtBlanc(1);
+    R2 Pmin,Pmax;
+    R2 uminmax(1e100,-1e100);
+    R2 Vminmax(1e100,-1e100);
+    bool first=true;
+    for (size_t ii=0;ii<ll.size();ii++)
+	{
+	    int i=ll[ii].i;
+	    long what = ll[ii].what;
+	    R2  P1,P2;
+      if (what==1 || what==2) 
+	{
+         
+	  if( !uaspectratio)   aspectratio= true;
+          ll[ii].eval(fe,cmp0,fe1,cmp1);
+         
+	  if (!fe->x()) continue; 
+         
+	  //int nb=fe->x()->N();
+
+	  fe->Vh->cmesh->BoundingBox(P1,P2);
+          cTh=fe->Vh->cmesh;
+	  if (fe1==0)
+            uminmax = minmax(uminmax,fe->Vh->MinMax(*fe->x(),cmp0));
+	  else
+	    {
+	      if (fe1) 
+		{
+		  if (fe->Vh == fe1->Vh) 
+		    {  
+		      KN_<R> u( *fe->x()),v(*fe1->x());     
+		      Vminmax = minmax(Vminmax,fe->Vh->MinMax(u,v,cmp0,cmp1));
+		    }  
+		  else
+		    cerr << " On ne sait tracer que de vecteur sur un meme type element finite. " << endl;
+		}      
+           
+	    }
+	}
+      else if (l[i].what==0) 
+	{
+	  if( !uaspectratio) aspectratio= true;
+	    const  Mesh & Th= *ll[ii].th();
+	  Th.BoundingBox(P1,P2);
+	  cTh=&Th;
+	}
+      else if (l[i].what==4) 
+	{
+	  if( !uaspectratio) aspectratio= true;
+	  const  E_BorderN * Bh= l[i].evalb(0,s);
+	  Bh->BoundingBox(s,P1.x,P2.x,P1.y,P2.y);
+          
+	}
+      else if (l[i].what==3) 
+	{
+	  tab  ttx=l[i].evalt(0,s);
+	  tab  tty=l[i].evalt(1,s);
+	  tab *tx=&ttx,*ty=&tty;
+	  P1=R2(tx->min(),ty->min());
+	  P2=R2(tx->max(),ty->max());   
+	  if(verbosity>2)  
+	    cout << "Plot: bound  Pmin=" <<  P1 << ",  Pmax=" << P2 << endl;  
+	}
+      else continue;
+      
+      if (first)
+	{first=false; Pmin=P1;Pmax=P2;}
+      else {
+	Pmin.x = Min(Pmin.x,P1.x);
+	Pmin.y = Min(Pmin.y,P1.y);
+	Pmax.x = Max(Pmax.x,P2.x);
+	Pmax.y = Max(Pmax.y,P2.y);
+      }
+       
+      }
+      
+    {
+      R umx=uminmax.y,umn=uminmax.x;
+      if (verbosity>5) 
+        cout << " u bound " <<  uminmax << "  V : " << Vminmax <<endl;
+
+      if (verbosity>1)
+	cout << "Plot bound [x,y] " <<  Pmin << " max [x,y] " << Pmax << endl;  
+      int N=Viso.N();
+      int Na=Varrow.N();
+      R2 O((Pmin+Pmax)/2);
+      R rx(Pmax.x-Pmin.x),ry(Pmax.y-Pmin.y);
+      // bug   version 1.41 correct FH to remove div by zero.
+      rx = Max(rx,1e-30);
+      ry = Max(ry,1e-30);
+      // -- end correction
+      R r =  (Max(rx,ry)*0.55);
+      showgraphic();
+      if (aspectratio)
+	cadreortho((float)O.x,(float)(O.y+r*0.05),(float) r);
+      else 
+	cadre( (float)(O.x-rx*.55),(float)(O.x+rx*0.55),(float)(O.y-ry*.55),(float)(O.y+ry*.55));
+      R d = fill ? (umx-umn)/(N-1)  : (umx-umn)/(N);       
+      R x = fill ? umn-d/2 :umn+d/2;
+      if (!pViso) 
+        for (int i = 0;i < N;i++)
+	  {Viso[i]=x;x +=d; }
+      if (fill && !pViso) {Viso[0]=umn-d;Viso[N-1]=umx+d;}
+      x=0; d= sqrt(Vminmax.y)/(Na-1.001);
+      if (!pVarrow)
+        for (int i = 0;i < Na;i++)
+          {Varrow[i]=x;x +=d; }
+   
+      SetColorTable(Max(N,Na)+4) ;           
+    }
+  }  // clean
+  float xx0,xx1,yy0,yy1;
+  if (nargs[8])
+    {
+      xx0=min(boundingbox[0],boundingbox[2]);
+      xx1=max(boundingbox[0],boundingbox[2]);
+      yy0=min(boundingbox[1],boundingbox[3]);
+      yy1=max(boundingbox[1],boundingbox[3]);
+      if (verbosity>2) 
+	cout << "bb=  xmin =" << xx0 << ", max =" << xx1 << ", ymin = " << yy0 << ", ymax = " << yy1 << endl;
+      if (aspectratio)
+	cadreortho((xx0+xx1)*0.5,(yy0+yy1)*0.5, max(xx1-xx0,yy1-yy0)*0.5);
+      else 
+        cadre(xx0,xx1,yy0,yy1);
+
+     }
+   getcadre(xx0,xx1,yy0,yy1);
+   const R ccoeff=coeff;
+   bool plotting = true;   
+     //  drawing part  ------------------------------
+   while (plotting)
+     {
+	 if(verbosity>99) cout << "plot::operator() Drawing part \n";
+	 plotting = false; 
+	 bool thfill=fill;
+	 for (size_t ii=0;ii<ll.size();ii++)
+	   {
+	       int i=ll[ii].i;
+	       long what = ll[i].what;
+	       
+	       if (l[i].what==0) 
+		   if (fill)
+		       ll[ii].th()->Draw(0,thfill);
+		   else 
+		       ll[ii].th()->Draw(0,thfill);
+		   else  if (what==1 || what==2)
+		     {   
+			 
+			 ll[ii].eval(fe,cmp0,fe1,cmp1);
+			 // fe=  l[i].eval(0,s,cmp0);
+			 // fe1= l[i].eval(1,s,cmp1);;
+			 if (!fe->x()) continue;
+#ifdef VVVVVVV      
+			 cout << "   Min = " << fe->x->min() << " max = " << fe->x->max() ;
+			 if(fe1 && verbosity > 1)
+			     cout << " Min = " << fe1->x->min() << " max = " << fe1->x->max() ;   
+			 cout << endl;   
+#endif
+			 if (fe1) 
+			   {
+			       if (fe->Vh == fe1->Vh)           
+				   vecvalue=true,fe->Vh->Draw(*fe->x(),*fe1->x(),Varrow,coeff,cmp0,cmp1,colors,nbcolors,hsv,drawborder);
+			       else
+				   cerr << " On ne sait tracer que de vecteur sur un meme interpolation " << endl;
+			       if (drawmeshes) fe->Vh->Th.Draw(0,fill);
+			   }      
+			 else 
+			     
+			     
+			     if (fill)
+				 isovalue=true,fe->Vh->Drawfill(*fe->x(),Viso,cmp0,1.,colors,nbcolors,hsv,drawborder);
+			     else 
+				 isovalue=true,fe->Vh->Draw(*fe->x(),Viso,cmp0,colors,nbcolors,hsv,drawborder);
+			 
+			 if (drawmeshes) fe->Vh->Th.Draw(0,fill);
+			 
+		     }
+		   else if (l[i].what==4) 
+		     {
+			 const  E_BorderN * Bh= l[i].evalb(0,s);
+			 Bh->Plot(s);          
+		     }
+	       
+		   else if(l[i].what==3)
+		     {
+			 
+			 tab x=l[i].evalt(0,s);
+			 tab y=l[i].evalt(1,s);
+			 long k= Min(x.N(),y.N());
+			 // cout << " a faire " << endl;
+			 // cout << " plot :\n" << * l[i].evalt(0,s) << endl << * l[i].evalt(1,s) << endl;
+			 rmoveto(x[0],y[0]);
+			 couleur(2+i);
+			 for (int i= 1;i<k;i++)
+			     rlineto(x[i],y[i]);
+		     }
+	       thfill=false;
+	   }
+	 if (value) {
+	     int k=0; 
+	     if (isovalue) {PlotValue(Viso,k,"IsoValue");k+= Viso.N()+3;}
+	     if (vecvalue) {PlotValue(Varrow,k,"Vec Value");k+= Varrow.N()+3;}
+	 } 
+	 // value=false;
+	 
+	 if (cm) {       
+	     couleur(1);
+	     DrawCommentaire(cm->c_str(),0.1,0.97);
+	 }
+	 if (ops ) {
+	     ops=false;
+	     closePS();
+	 }
+	 if (wait && ! NoWait) 
+	   {  
+	   next:
+	       float x,y,x0,y0,x1,y1,dx,dy,coef=1.5;
+	       getcadre(x0,x1,y0,y1);
+	       char c=Getxyc(x,y);
+	       dx=(x1-x0)/2.;dy=(y1-y0)/2.;
+	       
+	       switch (c) 
+	       { 
+		   case '+' :  plotting=true; 
+		       cadre(x-dx/coef,x+dx/coef,y-dy/coef,y+dy/coef);reffecran();
+		       break;
+		   case '-' :  plotting=true; 
+		       cadre(x-dx*coef,x+dx*coef,y-dy*coef,y+dy*coef);;reffecran();
+		       break;
+		   case '=' :  plotting=true; 
+		       coeff=ccoeff;
+		       cadre(xx0,xx1,yy0,yy1);;reffecran();
+		       break;
+		   case 'r' :  plotting=true; 
+		       reffecran();
+		       break;
+		   case 'a' : 
+		   case 'c' : coeff /= 1.5; plotting=true;reffecran(); 
+		       reffecran();
+		       break;
+		   case 'A' : 
+		   case 'C' : coeff *= 1.5;
+		       plotting=true;
+		       reffecran();
+		       break;
+		   case 'b' : bw= !bw;NoirEtBlanc(bw)  ;
+		       plotting=true;
+		       reffecran();
+		       break;
+		   case 'v' : value = !value ; plotting=true;
+		       reffecran();
+		       break;
+		   case 'f' : fill = !fill ; plotting=true;
+		       reffecran();
+		       break;
+		   case 'g' : setgrey(grey=!getgrey()); plotting=true;
+		       reffecran();
+		       break;
+		       
+		   case 'm' : 
+		       reffecran();
+		       drawmeshes= !drawmeshes;
+		       plotting=true;
+		       break;
+		   case 'p' : 
+		       plotting=true;
+		       reffecran();
+		       ops=true;
+		       openPS(0);
+		       plotting=true;
+		       break;
+		   case 'q' :
+		       couleur(8);
+#ifdef DRAWING		      
+		       if (cTh) cTh->quadtree->Draw();
+#endif		       
+		       couleur(1);
+		       goto next;
+		   case 's' :
+		       if(cTh)
+			 {
+			     R2 P(x,y),PF(P),Phat;
+			     bool outside;
+			     const Vertex * v=cTh->quadtree->NearestVertexWithNormal(P);
+			     if (!v)  v=cTh->quadtree->NearestVertex(P);
+			     else {
+				 couleur(2);
+				 const Triangle * t= cTh->Find( PF,  Phat,outside,&(*cTh)[cTh->Contening(v)]) ;
+				 t->Draw(0.8);
+				 couleur(2);
+				 PF=(*t)(Phat);
+				 DrawMark(PF,0.003);
+				 
+			     }
+			     couleur(5);
+			     DrawMark(P,0.0015);
+			     
+			     couleur(1);
+			     if (v)
+				 DrawMark(*v,0.005);
+			     
+			 goto next;}
+		   case '?':
+		       int i=2;
+		       reffecran();               
+		       //Show("Enter a keyboard character in graphic window to do :",i++);
+		       Show("Enter a keyboard character in the FreeFem Graphics window in order to:",i++);
+		       
+		       i+=2;
+		       //Show("+)  zomm around the cursor 3/2 times ",i++);
+		       Show("+)  zoom in around the cursor 3/2 times ",i++);
+		       Show("-)  zoom out around the cursor 3/2 times  ",i++);
+		       //Show("-)  unzomm around the cursor 3/2 times  ",i++)	;
+		       Show("=)  reset zooming  ",i++);
+		       Show("r)  refresh plot ",i++);
+		       Show("ac) increase   the size arrow ",i++);
+		       Show("AC) decrease the size arrow  ",i++);
+		       Show("b)  switch between black and white or color plotting ",i++);
+		       Show("g)  switch between grey or color plotting ",i++);
+		       Show("f)  switch between filling iso or not  ",i++);
+		       Show("v)  switch between show  the numerical value of iso or not",i++);
+		       Show("p)   save  plot in a Postscprit file",i++);
+		       Show("m)  switch between show  meshes or not",i++);
+		       Show("p)  switch between show  quadtree or not (for debuging)",i++);
+		       Show("t)  find  Triangle ",i++);
+		       Show("?)  show this help window",i++);
+		       Show("any other key : continue ",++i);
+		       goto next;
+	       }   
+	       if (!pViso || !pVarrow)
+		 { //  recompute the iso bound
+		     R2 uminmax(1e100,-1e100);
+		     R2 Vminmax(1e100,-1e100);
+		     for (size_t i=0;i<l.size();i++)
+		       { R2  P1,P2;
+			   if (l[i].what==1 || l[i].what==2) 
+			     {
+				 fe   = l[i].eval(0,s,cmp0);
+				 fe1  = l[i].eval(1,s,cmp1);
+				 
+				 if (!fe->x()) continue; 
+				 
+				 // int nb=fe->x()->N();
+				 
+				 
+				 if (fe1==0)
+				     uminmax = minmax(uminmax,fe->Vh->MinMax(*fe->x(),cmp0,false));
+				 else
+				   {
+				       if (fe1) 
+					   if (fe->Vh == fe1->Vh) 
+					     {  
+						 KN_<R> u( *fe->x()),v(*fe1->x());     
+						 Vminmax = minmax(uminmax,fe->Vh->MinMax(u,v,cmp0,cmp1,false));
+					     }  
+				   }
+			     }
+			   else continue;
+			   
+			   
+		       }
+		     if (verbosity>5)   cout << " u bound " <<  uminmax << endl;
+		     R umx=uminmax.y,umn=uminmax.x;
+		     int N=Viso.N();
+		     int Na=Varrow.N();
+		     R d = fill ? (umx-umn)/(N-1)  : (umx-umn)/(N);       
+		     R x = fill ? umn-d/2 :umn+d/2;
+		     if (!pViso) 
+			 for (int i = 0;i < N;i++)
+			   {Viso[i]=x;x +=d; }
+		     if (fill && !pViso) {Viso[0]=umn-d;Viso[N-1]=umx+d;}
+		     x=0; d= sqrt(Vminmax.y)/Na;
+		     if (!pVarrow)
+			 for (int i = 0;i < Na;i++)
+			   {Varrow[i]=x;x +=d; }
+		     
+		     
+		     
+		 }
+	   }  
+	 *mps=mp;
+     } //  end plotting 
+  NoirEtBlanc(0)  ;
+  setgrey(greyo);
+  if (colors) delete[] colors;
+  // modif mars 2006  auto stack ptr
+  // if (cm)        delete cm;
+  // if (psfile)        delete psfile;
+  viderbuff();
+     
+  return 0L;
+}
+ 
+AnyType Convect::operator()(Stack s) const 
+{  
+    if(d==2)  return eval2(s);
+    else  return eval3(s);    
+}
+
+AnyType Convect::eval2(Stack s) const
+{
+  MeshPoint* mp(MeshPointStack(s));
+  static MeshPoint mpp,mps;
+  static R ddts;
+  R ddt = GetAny<double>((*dt)(s));
+  if (ddt) 
+    {
+      MeshPoint mpc(*mp);
+      MeshPointStack(s,&mpc);
+      if(*mp==mpp && ddt == ddts) 
+	mpc=mps;
+      else 
+	{
+
+	  const Mesh & Th(*mp->Th);
+	  ffassert(mp->Th && mp->T);
+	  R l[3];
+	  l[1]=mpc.PHat.x;
+	  l[2]=mpc.PHat.y;
+	  l[0]=1-l[1]-l[2];
+
+	  int k=0;
+	  int j; 
+	  int it=Th(mpc.T);
+	  while ( (j=WalkInTriangle(Th,it,l,GetAny<double>((*u)(s)),GetAny<double>((*v)(s)),ddt))>=0) 
+	    { 
+	      ffassert( l[j] == 0);
+	      //int jj  = j;            
+	      R a= l[(j+1)%3], b= l[(j+2)%3];
+	      int itt =  Th.ElementAdj(it,j);
+	      if(itt==it || itt <0)  break; // le bord 
+	      it = itt;
+	      l[j]=0;
+	      l[(j+1)%3] = b;
+	      l[(j+2)%3] = a;
+	      mpc.change(R2(l[1],l[2]),Th[it],0);             
+	      if(k++>1000)
+		{
+		  cerr << "Fatal  error  in Convect (R2) operator: loop  => velocity too high ???? or NaN F. Hecht  " << endl;
+		  ffassert(0);
+		}
+	    }
+
+	  mpc.change(R2(l[1],l[2]),Th[it],0);
+	  mpp=*mp; 
+	  mps=mpc;         
+	}
+    }
+  ddts=ddt;
+  AnyType r= (*ff)(s);
+  MeshPointStack(s,mp);
+  
+  return r;
+}
+
+AnyType Convect::eval3(Stack s) const 
+{
+MeshPoint* mp(MeshPointStack(s));
+static MeshPoint mpp,mps;
+static R ddts;
+R ddt = GetAny<double>((*dt)(s));
+if (ddt) 
+{
+    bool ddd=verbosity>100;
+    MeshPoint mpc(*mp);
+    MeshPointStack(s,&mpc);
+    if(*mp==mpp && ddt == ddts) 
+	mpc=mps;
+	else 
+	  {
+	      
+	      const Mesh3 & Th3(*mp->Th3);
+	      ffassert(mp->Th3 && mp->T3);
+	      R3 PHat=mpc.PHat;
+	      	      
+	      int k=0;
+	      int j; 
+	      int it=Th3(mpc.T3);
+	      if(ddd) cout << " IN: " <<  (*mpc.T3)(PHat) << " ; " << mpc.P <<" : " << ddt << endl;
+	      while ( (j=WalkInTet(Th3,it,PHat,R3(GetAny<double>((*u)(s)),GetAny<double>((*v)(s)),GetAny<double>((*w)(s))),ddt))>=0) 
+		  if(j>3)  { 
+		      it=j-4;
+		  mpc.change(PHat,Th3[it],0);
+	          if(ddd) cout << "   **P= "<< (*mpc.T3)(PHat) << " ,  Ph " << PHat << " : j = " << j  <<  " it:  " << it ;
+		  }
+		else
+                { 
+		  if(ddd) cout << "P= "<< (*mpc.T3)(PHat) << " ,  Ph " << PHat << " : j = " << j  <<  " it:  " << it ;
+#ifdef DEBUG		    
+		    R3  Po=(*mpc.T3)(PHat),Pho=PHat; int ito=it;
+#endif
+                    int itt =  Th3.ElementAdj(it,j,PHat);
+		   if(ddd && itt>=0) cout << "  -> " << itt << " " << j  << "  : Pn " <<  Th3[itt](PHat) << " PHn " << PHat << " , " << ddt << endl;	
+		    if(itt<0) break;
+		    it=itt;
+		    mpc.change(PHat,Th3[it],0);  
+#ifdef DEBUG		    
+		    if(((Po-mpc.P).norme2() > 1e-10))
+		      {   cout << ito << " " << &Th3[ito][0] << " " << &Th3[ito][1] << " " << &Th3[ito][2] << " " << &Th3[ito][3] << " "  << endl;
+			   cout << it << " " <<  &Th3[it][0] << " " <<  &Th3[it][1] << " " <<  &Th3[it][2] << " " <<  &Th3[it][3] << endl;
+			  cout << Pho  << "o Hat " << PHat << endl;
+			  cout << Po << " o != " << mpc.P << " diff= "<< (Po-mpc.P).norme2() <<endl;
+			  assert(0);
+			  
+		      }
+#endif			  
+		   ffassert(k++<2000);
+                }
+	      	      
+	      mpc.change(PHat,Th3[it],0);
+	      mpp=*mp; 
+	      mps=mpc;         
+	  }
+}
+ddts=ddt;
+AnyType r= (*ff)(s);
+MeshPointStack(s,mp);
+
+return r;
+}
+
+
+
+
+
+template<class K>
+class Op3_pfe2K : public ternary_function<pair<FEbase<K,v_fes> *,int>,R,R,K> { public:
+
+
+  class Op : public E_F0mps { public:
+    Expression a,b,c;
+    Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc) {/*cout << "Op3_pfe2K" << endl;*/}       
+    AnyType operator()(Stack s)  const 
+    { 
+      R xx(GetAny<R>((*b)(s)));
+      R yy(GetAny<R>((*c)(s)));
+      MeshPoint & mp = *MeshPointStack(s),mps=mp;
+      mp.set(xx,yy,0.0);
+      AnyType ret = pfer2R<K,0>(s,(*a)(s));
+      mp=mps;
+      return  ret;
+    }
+  };
+};
+
+
+//Add  FH 16032005
+class Op3_Mesh2mp : public ternary_function<pmesh*,R,R,MeshPoint *> { public:
+  class Op : public E_F0mps { public:
+      Expression a,b,c;
+       Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc) {}       
+       AnyType operator()(Stack s)  const 
+        { 
+           R xx(GetAny<R>((*b)(s)));
+           R yy(GetAny<R>((*c)(s)));
+           pmesh *ppTh(GetAny<pmesh*>((*a)(s)));
+           if( !ppTh || !*ppTh) ExecError("Op3_Mesh2mp unset mesh ??");
+           pmesh pTh(*ppTh);
+           MeshPoint * mp = new MeshPoint();
+           mp->set(xx,yy,0.0);
+           R2 PHat;
+           bool outside;
+           const Triangle * K=pTh->Find(mp->P.p2(),PHat,outside);
+           mp->set(*pTh,(R2) mp->P.p2(),PHat,*K,0,outside);
+           return mp;}
+   
+  };
+};
+
+template<class RR,class AA=RR>
+class JumpOp : public E_F0mps  { public:
+  typedef RR  R;
+  typedef AA A; 
+  typedef RR result_type;
+  typedef AA argument_type; 
+
+       Expression a;
+       public:
+       AnyType operator()(Stack stack)  const 
+        { // a faire 
+           A rd,rg;       
+           MeshPoint *mp=MeshPointStack(stack),smp=*mp;              
+           rg = GetAny<A>((*a)(stack));
+           rd = 0. ;// to be compatible with varf def... FH april 2014 ... v 3.31. 
+           if ( mp->SetAdj() )
+             rd = GetAny<A>((*a)(stack));  
+           *mp=smp;         
+           return  SetAny<R>(rd-rg);//  external - internal 
+        }
+       JumpOp(Expression aa) : a(aa) {} 
+    };
+
+template<class RR,class AA=RR>
+class MeanOp : public E_F0mps  { public:
+  typedef RR  R;
+  typedef AA A; 
+  typedef RR result_type;
+  typedef AA argument_type; 
+
+       Expression a;
+       public:
+       AnyType operator()(Stack stack)  const 
+        { // a faire 
+           A rd,rg;       
+           MeshPoint *mp=MeshPointStack(stack),smp=*mp;              
+           rg = GetAny<A>((*a)(stack));
+           rd = rg;
+           if ( mp->SetAdj() )
+             rd = GetAny<A>((*a)(stack));  
+           *mp=smp;         
+           return  SetAny<R>((rg+rd)*0.5);
+        }
+       MeanOp(Expression aa) : a(aa) {} 
+    };
+
+long get_size(pferarray const & a)
+{
+  return a.first->N;
+}
+long get_size(pfecarray const & a)
+{
+    return a.first->N;
+}
+long get_size(pferbasearray *const & a)
+{
+    return (**a).N;
+}
+long get_size(pfecbasearray *const & a)
+{
+    return (**a).N;
+}
+long get_size(pf3rarray const & a)
+{
+  return a.first->N;
+}
+long get_size(pf3rbasearray *const & a)
+{
+    return (**a).N;
+}
+long resize(pferbasearray *const & a, long const & n)
+{
+    (**a).resize(n);
+    return n; 
+}
+
+long resize(pfecbasearray *const & a, long const & n)
+{
+    (**a).resize(n);
+    return n;
+}
+
+pferbase* get_element(pferbasearray *const & a, long const & n)
+{
+  return (**a)[n];
+}
+
+pfer get_element(pferarray const & a, long const & n)
+{
+  return pfer( *(*a.first)[n],a.second);
+}
+
+//  complex case 
+pfecbase* get_element(pfecbasearray *const & a, long const & n)
+{
+  return (**a)[n];
+}
+pfec get_element(pfecarray const & a, long const & n)
+{
+  return pfec( *(*a.first)[n],a.second);
+}
+//  end complex case 
+
+lgElement get_element(pmesh const & a, long const & n)
+{
+  return lgElement(a,n);
+}
+lgElement get_element(pmesh *const & a, long const & n)
+{
+  return lgElement(*a,n);
+}
+
+
+
+lgBoundaryEdge get_belement(lgBoundaryEdge::BE const & a, long const & n)
+{
+    return lgBoundaryEdge(a,n);
+}
+
+lgElement get_adj(lgElement::Adj const & a, long  * const & n)
+{
+    return  a.adj(*n);
+}
+
+lgVertex get_vertex(pmesh const & a, long const & n)
+{
+    return lgVertex(a,n);
+}
+lgVertex get_vertex(pmesh *const & a, long const & n)
+{
+    return lgVertex(*a,n);
+}
+lgVertex get_element(lgElement const & a, long const & n)
+{
+  return a[n];
+}
+lgVertex get_belement(lgBoundaryEdge const & a, long const & n)
+{
+    return a[n];
+}
+
+R getx(lgVertex const & a)
+{
+  return a.x();
+}
+
+R gety(lgVertex const & a)
+{
+  return a.y();
+}
+long getlab(lgVertex const & a)
+{
+  return a.lab();
+}
+long getlab(lgElement const & a)
+{
+  return a.lab();
+}
+long getlab(lgBoundaryEdge const & a)
+{
+    return a.lab();
+}
+
+double getarea(lgElement const & a)
+{
+    return a.area();
+}
+double getlength(lgBoundaryEdge const & a)
+{
+    return a.length();
+}
+lgElement getElement(lgBoundaryEdge const & a)
+{
+    return a.Element();
+}
+long EdgeElement(lgBoundaryEdge const & a)
+{
+    return a.EdgeElement();
+}
+
+/*
+pmesh* get_element(pmesharray *const & a, long const & n)
+{
+  assert(n>=0 && n <=a->second);
+  return a->first +n;
+}
+*/
+template<class A> inline AnyType DestroyKN(Stack,const AnyType &x){
+  KN<A> * a=GetAny<KN<A>*>(x);
+  for (int i=0;i<a->N(); i++)
+    (*a)[i]->destroy();
+  a->destroy(); 
+  return  Nothing;
+}
+template<class RR,class A,class B>  
+RR * get_elementp_(const A & a,const B & b){ 
+  if( b<0 || a->N() <= b) 
+   { cerr << " Out of bound  0 <=" << b << " < "  << a->N() << " array type = " << typeid(A).name() << endl;
+     ExecError("Out of bound in operator []");}
+    return  &((*a)[b]);}
+    
+template<class R>  R * set_initinit( R* const & a,const long & n){ 
+ SHOWVERB( cout << " set_init " << typeid(R).name() << " " << n << endl);
+  a->init(n);
+  for (int i=0;i<n;i++)
+    (*a)[i]=0;
+   return a;}
+
+template<class A> inline AnyType DestroyKNmat(Stack,const AnyType &x){
+  KN<A> * a=GetAny<KN<A>*>(x);
+  for (int i=0;i<a->N(); i++)
+    (*a)[i].destroy();
+  a->destroy(); 
+  return  Nothing;
+}
+
+template<class R>  R * set_initmat( R* const & a,const long & n){ 
+ SHOWVERB( cout << " set_init " << typeid(R).name() << " " << n << endl);
+  a->init(n);
+  for (int i=0;i<n;i++)
+    (*a)[i].init();
+   return a;}
+    
+void init_mesh_array()
+ {
+  Dcl_Type<KN<pmesh> *>(0,::DestroyKN<pmesh> );
+  atype<KN<pmesh>* >()->Add("[","",new OneOperator2_<pmesh*,KN<pmesh>*,long >(get_elementp_<pmesh,KN<pmesh>*,long>));
+    TheOperators->Add("<-", 
+       new OneOperator2_<KN<pmesh> *,KN<pmesh> *,long>(&set_initinit));
+  map_type_of_map[make_pair(atype<long>(),atype<pmesh>())]=atype<KN<pmesh>*>(); // vector
+
+  // resize mars 2006 v2.4-1
+  Dcl_Type< Resize<KN<pmesh> > > ();
+  Add<KN<pmesh>*>("resize",".",new OneOperator1< Resize<KN<pmesh> >,KN<pmesh>*>(to_Resize));
+  Add<Resize<KN<pmesh> > >("(","",new OneOperator2_<KN<pmesh> *,Resize<KN<pmesh> > , long   >(resizeandclean1));
+   
+
+ }
+template<class RR,class A,class B>  
+RR  get_elementp(const A & a,const B & b){ 
+  if( b<0 || a->N() <= b) 
+   { cerr << " Out of bound  0 <=" << b << " < "  << a->N() << " array type = " << typeid(A).name() << endl;
+     ExecError("Out of bound in operator []");}
+    return  ((*a)[b]);}
+
+template<class T> T *resizeandclean2(const Resize<T> & t,const long &n)
+ {  // resizeandclean1
+  int nn= t.v->N(); // old size 
+  
+  for (int i=n;i<nn;i++)  {(*t.v)[i].destroy();;} // clean
+  t.v->resize(n);
+  for (int i=nn;i<n;i++)  {(*t.v)[i].init();}  
+  return  t.v;
+ }
+
+template<class PMat>
+AnyType ClearReturn(Stack stack, const AnyType & a)
+{
+    // a ne faire que pour les variables local au return...
+    //  pour l'instant on copie pour fqire mqrche
+    // a repense  FH  mqi 20014....
+    PMat * m = GetAny<PMat * >(a);
+    //   KN<K> *cm=new KN<K>(true, *m); bug quant KN est une variable global
+    // KN<K> *cm=new KN<K>( *m); // on duplique le tableau comme en C++  (dur dur ?????? FH)
+    m->increment();
+    Add2StackOfPtr2FreeRC(stack,m);
+    return m;
+}
+
+
+template <class R>
+void DclTypeMatrix()
+{
+ 
+  Dcl_Type<Matrice_Creuse<R>* >(InitP<Matrice_Creuse<R> >,Destroy<Matrice_Creuse<R> >, ClearReturn<Matrice_Creuse<R> >);
+  Dcl_Type<Matrice_Creuse_Transpose<R> >();      // matrice^t   (A')                             
+  Dcl_Type<Matrice_Creuse_inv<R> >();      // matrice^-1   A^{-1}                          
+  Dcl_Type<typename VirtualMatrice<R>::plusAx >();       // A*x (A'*x)
+  Dcl_Type<typename VirtualMatrice<R>::plusAtx >();       // A^t*x (A'*x)
+  Dcl_Type<typename VirtualMatrice<R>::solveAxeqb >();       // A^t*x (A'*x)
+  Dcl_Type<Matrix_Prod<R,R> >();
+  Dcl_Type<list<triplet<R,MatriceCreuse<R> *,bool> >*>();
+  
+   // resize mars 2006 v2.4-1
+ 
+  // array of matrix   matrix[int] A(n);
+  typedef  Matrice_Creuse<R> Mat;
+  typedef  Mat * PMat;
+  typedef  KN<Mat> AMat;
+  Dcl_Type<AMat *>(0,::DestroyKNmat<Mat> );  
+  
+  // init array
+    TheOperators->Add("<-", 
+       new OneOperator2_<AMat *,AMat *,long>(&set_initmat));
+  //  A[i] 
+  atype<AMat* >()->Add("[","",new OneOperator2_<PMat,AMat*,long >(get_elementp_<Mat,AMat*,long>));
+  
+  // resize
+  Dcl_Type< Resize<AMat> > ();
+  Add<AMat*>("resize",".",new OneOperator1< Resize<AMat >,AMat*>(to_Resize));
+  Add<Resize<AMat> >("(","",new OneOperator2_<AMat *,Resize<AMat> , long   >(resizeandclean2));
+   
+  // to declare matrix[int]     
+  map_type_of_map[make_pair(atype<long>(),atype<PMat>())]=atype<AMat*>(); 
+  
+}
+
+
+template<class A,class B> 
+AnyType First(Stack,const AnyType &b) { 
+return   SetAny<A>(GetAny<B>(b).first);}
+
+template<class K>
+AnyType AddIncrement(Stack stack, const AnyType & a)
+{
+    K m = GetAny<K>(a);
+    m->increment();
+    Add2StackOfPtr2FreeRC(stack,m);
+    if(verbosity>1)
+    cout << "AddIncrement:: increment + Add2StackOfPtr2FreeRC " << endl;
+    return a;
+}
+/* 
+class EConstantTypeOfFE3 :public E_F0
+    { public:
+	//  using namespace   Fem2D;
+	typedef Fem2D::TypeOfFE3 * T;
+	T  v;
+    public:
+	AnyType operator()(Stack ) const { ;return SetAny<T>(v);}
+	EConstantTypeOfFE3( T o):v(o) {}
+	size_t nbitem() const { assert(v);
+	cout << " nb item = " << v->N << endl;
+	return v->N ;} 
+	operator aType () const { return atype<T>();} 
+    };
+
+*/ 
+Type_Expr CConstantTFE3(const EConstantTypeOfFE3::T & v)
+{
+    throwassert(map_type[typeid( EConstantTypeOfFE3::T).name()]);
+    return make_pair(map_type[typeid( EConstantTypeOfFE3::T).name()],new EConstantTypeOfFE3(v));
+}
+
+//  end --- call meth be ..
+// 2013 resize of array of fe function..
+template<typename  T> T fepresize(const Resize1<T> & rt,const long &n) {
+    (**(rt.v)).resize(n);
+    return rt.v;}
+template<typename  T> T feresize(const Resize1<T> & rt,const long &n) {
+    rt.v.first->resize(n);
+    return rt.v;}
+
+R3 * set_eqp(R3 *a,R3 *b) { *a=*b; return a;}
+void  init_lgfem() 
+{
+ // ThePlotStream = new ofstream("ttttt.plot");
+  if(verbosity&& (mpirank==0)) cout <<"lg_fem ";
+#ifdef HAVE_CADNA
+  cout << "cadna ";
+  cadna_init(-1); // pas de fichier 
+#endif  
+//Dcl_Type<const C_args*>(); // to store compilation expression
+ 
+ Dcl_Type<MeshPoint*>();
+ Dcl_Type<R3*>(::Initialize<R3>);
+ Dcl_Type<R2*>(::Initialize<R2>);
+
+ map_type[typeid(R3*).name()] = new ForEachType<R3*>(Initialize<R3>);   
+  Dcl_TypeandPtr<pmesh>(0,0, ::InitializePtr<pmesh>,::DestroyPtr<pmesh>,AddIncrement<pmesh>,NotReturnOfthisType); 
+  Dcl_TypeandPtr<pmesh3>(0,0,::InitializePtr<pmesh3>,::DestroyPtr<pmesh3>,AddIncrement<pmesh3>,NotReturnOfthisType); 
+  Dcl_Type<lgVertex>(); 
+  Dcl_Type<lgElement>( ); 
+  Dcl_Type<lgElement::Adj>( ); 
+    
+  Dcl_Type<lgBoundaryEdge::BE >( ); 
+  Dcl_Type<lgBoundaryEdge>( ); 
+
+  atype<long>()->AddCast( 
+    new E_F1_funcT<long,lgVertex>(Cast<long,lgVertex>),
+    new E_F1_funcT<long,lgElement>(Cast<long,lgElement>),
+    new E_F1_funcT<long,lgBoundaryEdge>(Cast<long,lgBoundaryEdge>)
+  );
+
+
+ Dcl_Type<TypeOfFE*>(); 
+ Dcl_Type<TypeOfFE3*>(); // 3d
+    map_type[typeid(TypeOfFE3*).name()]->AddCast(
+						 new E_F1_funcT<TypeOfFE3*,TypeOfFE*>(TypeOfFE3to2)	);				 
+
+ Dcl_Type<TypeSolveMat*>();
+ DclTypeMatrix<R>();
+ DclTypeMatrix<Complex>();
+ 
+//  Dcl_Type<MatriceCreuseDivKN_<double> >();      //  A^(-1)  x
+                                    
+                                    
+ Dcl_TypeandPtr<pferbase>(); // il faut le 2 pour pourvoir initialiser 
+ Dcl_TypeandPtr<pferbasearray>(); // il faut le 2 pour pourvoir initialiser 
+ Dcl_Type< pfer >(); 
+ Dcl_Type< pferarray >(); 
+ Dcl_Type< pferarray >(); 
+
+
+
+    
+//  pour des Func FE complex   // FH  v 1.43
+    Dcl_TypeandPtr<pfecbase>(); // il faut le 2 pour pourvoir initialiser 
+    Dcl_TypeandPtr<pfecbasearray>(); // il faut le 2 pour pourvoir initialiser 
+    Dcl_Type< pfec >(); 
+    Dcl_Type< pfecarray >(); 
+    //  FH v 1.43
+    // add  mai 2009 FH for 3d eigen value.
+    Dcl_Type<FEbaseArrayKn<double> *>();
+    Dcl_Type<FEbaseArrayKn<Complex> *>();
+ 
+ 							      							   				 
+    
+    // Dcl_Type< pmesharray *>(); // il faut le 2 pour pourvoir initialiser 
+    
+    map_type[typeid(pfes).name()] = new ForEachType<pfes>(); 
+    map_type[typeid(pfes*).name()] = new ForEachTypePtrfspace<pfes,2>();
+
+
+ Dcl_TypeandPtr<pf3rbase>(); // il faut le 2 pour pourvoir initialiser 
+ Dcl_TypeandPtr<pf3rbasearray>(); // il faut le 2 pour pourvoir initialiser 
+ Dcl_Type< pf3r >(); 
+ Dcl_Type< pf3rarray >(); 
+
+//  pour des Func FE complex   // FH  v 1.43
+ Dcl_TypeandPtr<pf3cbase>(); // il faut le 2 pour pourvoir initialiser 
+ Dcl_TypeandPtr<pf3cbasearray>(); // il faut le 2 pour pourvoir initialiser 
+ Dcl_Type< pf3c >(); 
+ Dcl_Type< pf3carray >(); 
+
+    
+    //  cast of eigen value  mai 2009 ...
+    map_type[typeid(FEbaseArrayKn<double> *).name()]->AddCast(
+							      new E_F1_funcT<FEbaseArrayKn<double> *,pferbasearray>(Cast<FEbaseArrayKn<double> *,pferbasearray> ),
+							      new E_F1_funcT<FEbaseArrayKn<double> *,pferarray>(First<FEbaseArrayKn<double> *,pferarray> ),
+							      new E_F1_funcT<FEbaseArrayKn<double> *,pf3rbasearray>(Cast<FEbaseArrayKn<double> *,pf3rbasearray> ),
+							      new E_F1_funcT<FEbaseArrayKn<double> *,pf3rarray>(First<FEbaseArrayKn<double> *,pf3rarray> )
+							      
+							      );				 
+    map_type[typeid(FEbaseArrayKn<Complex> *).name()]->AddCast(
+							       new E_F1_funcT<FEbaseArrayKn<Complex> *,pfecbasearray>(Cast<FEbaseArrayKn<Complex> *,pfecbasearray> ),
+							       new E_F1_funcT<FEbaseArrayKn<Complex> *,pfecarray>(First<FEbaseArrayKn<Complex> *,pfecarray> ),
+							       new E_F1_funcT<FEbaseArrayKn<Complex> *,pf3cbasearray>(Cast<FEbaseArrayKn<Complex> *,pf3cbasearray> ),
+							       new E_F1_funcT<FEbaseArrayKn<Complex> *,pf3carray>(First<FEbaseArrayKn<Complex> *,pf3carray> )
+							       
+							       );				 
+    
+ map_type[typeid(pfes3).name()] = new ForEachType<pfes3>();  // 3d 
+ map_type[typeid(pfes3*).name()] = new ForEachTypePtrfspace<pfes3,3>(); // 3d
+
+ //   
+ Dcl_Type<const QuadratureFormular *>();
+ Dcl_Type<const QuadratureFormular1d *>();
+ Dcl_Type<const GQuadratureFormular<R3> *>();
+
+
+ Global.New("qf1pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_1));
+ Global.New("qf1pTlump",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_1lump));
+ Global.New("qf2pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_2));
+ Global.New("qf2pT4P1",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_2_4P1));
+ Global.New("qf5pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_5));
+ 
+ Global.New("qf7pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_7));
+ Global.New("qf9pT",CConstant<const QuadratureFormular *>(&QuadratureFormular_T_9));
+ 
+ Global.New("qf1pE",CConstant<const QuadratureFormular1d *>(&QF_GaussLegendre1));
+ Global.New("qf2pE",CConstant<const QuadratureFormular1d *>(&QF_GaussLegendre2));
+ Global.New("qf3pE",CConstant<const QuadratureFormular1d *>(&QF_GaussLegendre3));
+ Global.New("qf4pE",CConstant<const QuadratureFormular1d *>(&QF_GaussLegendre4));
+ Global.New("qf5pE",CConstant<const QuadratureFormular1d *>(&QF_GaussLegendre5));
+ Global.New("qf1pElump",CConstant<const QuadratureFormular1d *>(&QF_LumpP1_1D));
+ 
+  Global.New("qfV1",CConstant<const GQuadratureFormular<R3>  *>(&QuadratureFormular_Tet_1));
+  Global.New("qfV2",CConstant<const GQuadratureFormular<R3>  *>(&QuadratureFormular_Tet_2));
+  Global.New("qfV5",CConstant<const GQuadratureFormular<R3>  *>(&QuadratureFormular_Tet_5));
+  Global.New("qfV1lump",CConstant<const GQuadratureFormular<R3>  *>(&QuadratureFormular_Tet_1lump));
+     
+    
+ //  juste du code genere 
+ 
+ Global.New("wait",CConstant<bool*>(&TheWait));
+ Global.New("NoUseOfWait",CConstant<bool*>(&NoWait));
+ Global.New("NoGraphicWindow",CConstant<bool*>(&NoGraphicWindow));
+
+ Dcl_Type<MeshPoint *>();
+ Dcl_Type<finconnue *>();
+ Dcl_Type<ftest *>();
+ Dcl_Type<foperator *>();
+ Dcl_Type<foperator *>();
+ Dcl_Type<const BC_set *>();  // a set of boundary condition 
+ Dcl_Type<const Call_FormLinear<v_fes> *>();    //   to set Vector
+ Dcl_Type<const Call_FormBilinear<v_fes> *>();  // to set Matrix
+ Dcl_Type<const Call_FormLinear<v_fes3> *>();    //   to set Vector 3d
+ Dcl_Type<const Call_FormBilinear<v_fes3> *>();  // to set Matrix 3d
+ Dcl_Type<interpolate_f_X_1<double>::type>();  // to make  interpolation x=f o X^1 ;
+ 
+ map_type[typeid(const FormBilinear*).name()] = new TypeFormBilinear;
+ map_type[typeid(const FormLinear*).name()] = new TypeFormLinear;
+ aType t_C_args = map_type[typeid(const C_args*).name()] = new TypeFormOperator;
+ map_type[typeid(const Problem*).name()] = new TypeSolve<false,Problem>;
+ map_type[typeid(const Solve*).name()] = new TypeSolve<true,Solve>;
+ Dcl_Type<const IntFunction<double>*>(); 
+ Dcl_Type<const IntFunction<complex<double> >*>(); 
+ basicForEachType * t_solve=atype<const  Solve *>();
+ basicForEachType * t_problem=atype<const  Problem *>();
+ basicForEachType * t_fbilin=atype<const  FormBilinear *>();
+ basicForEachType * t_flin=atype<const  FormLinear *>();
+ basicForEachType * t_BC=atype<const BC_set *>();
+
+ /// Doxygen doc
+ basicForEachType * t_form=atype<const C_args*>();
+
+  Dcl_Type<const CDomainOfIntegration *>();
+  
+ 
+
+ atype<pmesh >()->AddCast( new E_F1_funcT<pmesh,pmesh*>(UnRef<pmesh >)); 
+ //  in mesh3  atype<pmesh3>()->AddCast( new E_F1_funcT<pmesh3,pmesh3*>(UnRef<pmesh3 >)); 
+ atype<pfes >()->AddCast(  new E_F1_funcT<pfes,pfes*>(UnRef<pfes>));
+ 
+ atype<pferbase>()->AddCast(  new E_F1_funcT<pferbase,pferbase>(UnRef<pferbase>));
+ atype<pfecbase>()->AddCast(  new E_F1_funcT<pfecbase,pfecbase>(UnRef<pfecbase>));
+ 
+ Add<pfer>("[]",".",new OneOperator1<KN<double> *,pfer>(pfer2vect<R>));
+ Add<pfec>("[]",".",new OneOperator1<KN<Complex> *,pfec>(pfer2vect<Complex>));
+ Add<pfer>("(","",new OneTernaryOperator<Op3_pfe2K<R>,Op3_pfe2K<R>::Op> );
+ Add<pfec>("(","",new OneTernaryOperator<Op3_pfe2K<Complex>,Op3_pfe2K<Complex>::Op> );
+ Add<double>("(","",new OneTernaryOperator<Op3_K2R<R>,Op3_K2R<R>::Op> );
+// Add<long>("(","",new OneTernaryOperator<Op3_K2R<long>,Op3_K2R<long>::Op> ); // FH stupide 
+ Add<Complex>("(","",new OneTernaryOperator<Op3_K2R<Complex>,Op3_K2R<Complex>::Op> );
+ Add<pmesh *>("(","",new OneTernaryOperator<Op3_Mesh2mp,Op3_Mesh2mp::Op> );
+ 
+ 
+ Add<MeshPoint *>("nuTriangle",".",new OneOperator1<long,MeshPoint *>(mp_nuTriangle));
+ Add<MeshPoint *>("region",".",new OneOperator1<long,MeshPoint *>(mp_region));
+ 
+ 
+ Add<pfer>("n",".",new OneOperator1<long,pfer>(pfer_nbdf<R>));
+ Add<pfec>("n",".",new OneOperator1<long,pfec>(pfer_nbdf<Complex>));
+ Add<pmesh*>("area",".",new OneOperator1<double,pmesh*>(pmesh_area));
+ Add<pmesh*>("mesure",".",new OneOperator1<double,pmesh*>(pmesh_area));
+ Add<pmesh*>("nt",".",new OneOperator1<long,pmesh*>(pmesh_nt));
+ Add<pmesh*>("nbe",".",new OneOperator1<long,pmesh*>(pmesh_nbe));
+    
+ Add<pmesh*>("nv",".",new OneOperator1<long,pmesh*>(pmesh_nv));
+ Add<pfes*>("ndof",".",new OneOperator1<long,pfes*>(pVh_ndof));
+ Add<pfes*>("nt",".",new OneOperator1<long,pfes*>(pVh_nt));
+ Add<pfes*>("ndofK",".",new OneOperator1<long,pfes*>(pVh_ndofK));
+ Add<pfes*>("(","", new OneTernaryOperator<pVh_ndf,pVh_ndf::Op>  );
+ //new OneOperator3<long,pfes*,long,long>(pVh_ndf));
+ 
+ atype<Matrice_Creuse<R> * >()->AddCast(new OneOperatorCode<pb2mat<R> >);
+ atype<Matrice_Creuse<Complex> * >()->AddCast(new OneOperatorCode<pb2mat<Complex> >);
+/*
+TheOperators->Add("*", 
+        new OneBinaryOperator<Op2_mulvirtAv<VirtualMatrice<R>::plusAx,Matrice_Creuse<R>*,KN<R>* > >,
+        new OneBinaryOperator<Op2_mulvirtAv<VirtualMatrice<R>::plusAtx,Matrice_Creuse_Transpose<R>,KN<R>* > >,
+        new OneBinaryOperator<Op2_mulvirtAv<VirtualMatrice<R>::solveAxeqb,Matrice_Creuse_inv<R>,KN<R>* > >     
+        );
+TheOperators->Add("^", new OneBinaryOperatorA_inv<R>());
+*/
+//   Add all Finite Element "P0","P1","P2","RT0", ... 
+  for (ListOfTFE * i=ListOfTFE::all;i;i=i->next)
+    {
+     ffassert(i->tfe); // check 
+     AddNewFE(i->name,i->tfe);
+    // Global.New(i->name, Type_Expr(atype<TypeOfFE*>(),new  EConstantTypeOfFE(i->tfe)));
+     }
+// Global.New("P1",CConstant<TypeOfFE*>(&P1Lagrange))
+// Global.New("P2",CConstant<TypeOfFE*>(&P2Lagrange));
+ kTypeSolveMat=0; 
+ Global.New("LU",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::LU))); 
+ Global.New("CG",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::GC)));
+ Global.New("Crout",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::CROUT)));
+ Global.New("Cholesky",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::CHOLESKY)));
+ Global.New("GMRES",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::GMRES)));
+ Global.New("UMFPACK",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::SparseSolver)));
+ Global.New("sparsesolver",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::SparseSolver)));
+
+ Global.New("sparsesolverSym",CConstant<TypeSolveMat*>(dTypeSolveMat[kTypeSolveMat++]=new TypeSolveMat(TypeSolveMat::SparseSolverSym)));
+
+ ffassert(kTypeSolveMat<nTypeSolveMat);
+ map_type[typeid(TypeSolveMat*).name()]->AddCast(new E_F1_funcT<TypeSolveMat*,long>(Long2TypeSolveMat) );    
+ map_type[typeid(long).name()]->AddCast(  new E_F1_funcT<long,TypeSolveMat*>(TypeSolveMat2Long) );                                     
+    
+//  init pmesh  
+/*
+
+ Add<pmesh*>("<-","(",
+             new OneOperator1_<pmesh,string*>(ReadMesh),
+             new OneOperator3_<long,pmesh*,double,double,
+                      E_F_stackF0F0F0_<long,pmesh*,double,double> >(& FindTxy )
+
+ );
+
+ Add<pmesh3*>("<-","(",
+             new OneOperator1_<pmesh3,string*>(ReadMesh3)
+ );
+*/
+/*TheOperators->Add("<-",);
+
+ );*/
+ 
+//old --   
+//  init FESpace 
+ TheOperators->Add("<-",
+		   new OneOperator2_<pfes*,pfes*,pmesh* >(& MakePtr2 ),
+		   // new OneOperator2_<pfes*,pfes*,pmesh3* >(& MakePtr3 ),
+		   //    new OneOperator3_<pfes*,pfes*,pmesh*,long >(& MakePtr2 ),
+		   //    new OneOperator3_<pfes*,pfes*,pmesh*,TypeOfFE* >(& MakePtr2 ),
+		   new OneOperatorCode<OP_MakePtr2>,
+		   new OneOperatorCode<OP_MakePtr3>,
+		   new OpMake_pfes<pfes,Mesh,TypeOfFE,pfes_tefk>,
+		   new OpMake_pfes<pfes3,Mesh3,TypeOfFE3,pfes3_tefk>
+        );
+    TheOperators->Add("=",new OneOperator2<R3*,R3*,R3* >(&set_eqp));
+ 
+ Add<MeshPoint*>("P",".", new OneOperator_Ptr_o_R<R3,MeshPoint>(  & MeshPoint::P));
+ Add<MeshPoint*>("N",".", new OneOperator_Ptr_o_R<R3,MeshPoint>(  & MeshPoint::N));
+ Add<R3*>("x",".", new OneOperator_Ptr_o_R<R,R3>(  & R3::x));
+ Add<R3*>("y",".", new OneOperator_Ptr_o_R<R,R3>(  & R3::y));
+ Add<R3*>("z",".", new OneOperator_Ptr_o_R<R,R3>(  & R3::z));
+ Add<R2*>("x",".", new OneOperator_Ptr_o_R<R,R2>(  & R2::x));
+ Add<R2*>("y",".", new OneOperator_Ptr_o_R<R,R2>(  & R2::y));
+ 
+ Add<pmesh>("[","",new OneOperator2_<lgElement,pmesh,long>(get_element));
+    
+ Add<pmesh*>("be",".",new OneOperator1_<lgBoundaryEdge::BE,pmesh*>(Build));
+ Add<lgElement>("adj",".",new OneOperator1_<lgElement::Adj,lgElement>(Build));
+ Add<lgBoundaryEdge::BE>("(","",new OneOperator2_<lgBoundaryEdge,lgBoundaryEdge::BE,long>(get_belement));
+ Add<lgElement::Adj>("(","",new OneOperator2_<lgElement,lgElement::Adj,long*>(get_adj));
+ TheOperators->Add("==", new OneBinaryOperator<Op2_eq<lgElement,lgElement> >);
+ TheOperators->Add("!=", new OneBinaryOperator<Op2_ne<lgElement,lgElement> >);
+ TheOperators->Add("<", new OneBinaryOperator<Op2_lt<lgElement,lgElement> >);
+ TheOperators->Add("<=", new OneBinaryOperator<Op2_le<lgElement,lgElement> >);
+		      
+    
+ Add<pmesh*>("[","",new OneOperator2_<lgElement,pmesh*,long>(get_element));
+ Add<pmesh>("(","",new OneOperator2_<lgVertex,pmesh,long>(get_vertex));
+ Add<pmesh*>("(","",new OneOperator2_<lgVertex,pmesh*,long>(get_vertex));
+
+ Add<lgElement>("[","",new OneOperator2_<lgVertex,lgElement,long>(get_element));
+ Add<lgBoundaryEdge>("[","",new OneOperator2_<lgVertex,lgBoundaryEdge,long>(get_belement));
+
+ Add<lgVertex>("x",".",new OneOperator1_<R,lgVertex>(getx));
+ Add<lgVertex>("y",".",new OneOperator1_<R,lgVertex>(gety));
+ Add<lgVertex>("label",".",new OneOperator1_<long,lgVertex>(getlab));
+ Add<lgElement>("label",".",new OneOperator1_<long,lgElement>(getlab));
+ Add<lgElement>("region",".",new OneOperator1_<long,lgElement>(getlab));
+ Add<lgElement>("area",".",new OneOperator1_<double,lgElement>(getarea));
+ Add<lgElement>("mesure",".",new OneOperator1_<double,lgElement>(getarea));
+ Add<lgBoundaryEdge>("length",".",new OneOperator1_<double,lgBoundaryEdge>(getlength));
+ Add<lgBoundaryEdge>("label",".",new OneOperator1_<long,lgBoundaryEdge>(getlab));
+ Add<lgBoundaryEdge>("Element",".",new OneOperator1_<lgElement,lgBoundaryEdge>(getElement));
+ Add<lgBoundaryEdge>("whoinElement",".",new OneOperator1_<long,lgBoundaryEdge>(EdgeElement));
+ 
+ 
+ // New FF language types. zzzfff is defined at [[file:lex.hpp::zzzfff]] as a pointer to an object of class mylex
+ // [[file:lex.hpp::class mylex]]. zzzfff->Add() is at [[file:lex.cpp::void mylex Add Key k aType t]]. The lexer will
+ // then be called from the parser via [[file:../lglib/lg.ypp::yylex]]
+
+ zzzfff->Add("R3",atype<R3*>());
+
+ // <<mesh_keyword>> pmesh is a pointer to Mesh [[file:../femlib/fem.hpp::class Mesh]] defined at
+ // [[file:lgfem.hpp::typedef Mesh pmesh]]
+
+ zzzfff->Add("mesh",atype<pmesh*>());
+
+ // pmesh3 is a pointer to Mesh3 defined at [[file:lgfem.hpp::typedef Mesh3 pmesh3]]
+
+ zzzfff->Add("mesh3",atype<pmesh3*>());
+
+ zzzfff->Add("element",atype<lgElement>());
+ zzzfff->Add("vertex",atype<lgVertex>());
+// zzzfff->Add("fespace",atype<pfes*>());
+ zzzfff->Add("matrix",atype<Matrice_Creuse<R> *>());
+ zzzfff->Add("Cmatrix",atype<Matrice_Creuse<Complex> *>()); // a voir
+
+ 
+
+ Global.Add("LinearCG","(",new LinearCG<R>()); // old form  with rhs (must be zer
+ Global.Add("LinearGMRES","(",new LinearGMRES<R>()); // old form
+ Global.Add("LinearGMRES","(",new LinearGMRES<R>(1)); // old form  without rhs
+ Global.Add("AffineGMRES","(",new LinearGMRES<R>(1)); // New  better
+ Global.Add("LinearCG","(",new LinearCG<R>(1)); //  without right handsize
+ Global.Add("AffineCG","(",new LinearCG<R>(1)); //  without right handsize
+ Global.Add("NLCG","(",new LinearCG<R>(-1)); //  without right handsize
+
+ //   Global.Add("LinearCG","(",new LinearCG<Complex>()); // old form  with rhs (must be zer
+ //   Global.Add("LinearGMRES","(",new LinearGMRES<Complex>()); // old form  with rhs (must be zer
+ //   Global.Add("LinearGMRES","(",new LinearGMRES<Complex>(1)); // old form  without rhs 
+//    Global.Add("LinearCG","(",new LinearCG<Complex>(1)); //  without right handsize
+//    Global.Add("NLCG","(",new LinearCG<Complex>(-1)); //  without right handsize
+   
+ zzzfff->AddF("varf",t_form);    //  var. form ~  <<varf>>
+ zzzfff->AddF("solve",t_solve);
+ zzzfff->AddF("problem",t_problem);
+ 
+
+ Global.Add("jump","(",new OneOperatorCode<Code_VF<Ftest,Code_Jump> >);
+ Global.Add("jump","(",new OneOperatorCode<Code_VF<Finconnue,Code_Jump> >);
+ Global.Add("average","(",new OneOperatorCode<Code_VF<Ftest,Code_Mean> >);
+ Global.Add("average","(",new OneOperatorCode<Code_VF<Finconnue,Code_Mean> >);
+ Global.Add("mean","(",new OneOperatorCode<Code_VF<Ftest,Code_Mean> >);
+ Global.Add("mean","(",new OneOperatorCode<Code_VF<Finconnue,Code_Mean> >);
+ Global.Add("otherside","(",new OneOperatorCode<Code_VF<Ftest,Code_OtherSide> >);
+ Global.Add("otherside","(",new OneOperatorCode<Code_VF<Finconnue,Code_OtherSide> >);
+
+ Global.Add("conj","(",new OneOperatorCode<CODE_conj<Finconnue> >);
+ Global.Add("conj","(",new OneOperatorCode<CODE_conj<Ftest> >);
+ Global.Add("conj","(",new OneOperatorCode<CODE_conj<Foperator> >);
+ TheOperators->Add("\'", new OneOperatorCode<CODE_conj<Finconnue> >); 
+ TheOperators->Add("\'", new OneOperatorCode<CODE_conj<Ftest> >);   
+ TheOperators->Add("\'", new OneOperatorCode<CODE_conj<Foperator> >);   
+    
+ Global.Add("dx","(",new OneOperatorCode<CODE_Diff<Ftest,op_dx> >);
+ Global.Add("dy","(",new OneOperatorCode<CODE_Diff<Ftest,op_dy> >);
+ Global.Add("dx","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dx> >);
+ Global.Add("dy","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dy> >);
+ 
+ Global.Add("dxx","(",new OneOperatorCode<CODE_Diff<Ftest,op_dxx> >);
+ Global.Add("dxy","(",new OneOperatorCode<CODE_Diff<Ftest,op_dxy> >);
+ Global.Add("dyx","(",new OneOperatorCode<CODE_Diff<Ftest,op_dyx> >);
+ Global.Add("dyy","(",new OneOperatorCode<CODE_Diff<Ftest,op_dyy> >);
+ 
+ Global.Add("dxx","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dxx> >);
+ Global.Add("dyy","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dyy> >);
+ Global.Add("dxy","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dxy> >);
+ Global.Add("dyx","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dyx> >);
+ 
+ Global.Add("on","(",new OneOperatorCode<BC_set > );
+
+ /// <<plot_keyword>> uses [[Plot]] and [[file:AFunction.hpp::OneOperatorCode]] and [[file:AFunction.hpp::Global]]
+ Global.Add("plot","(",new OneOperatorCode<Plot> );
+ Global.Add("convect","(",new OneOperatorCode<Convect> );
+
+
+ TheOperators->Add("+",
+    new OneOperatorCode<CODE_L_Add<Foperator> > ,
+    new OneOperatorCode<CODE_L_Add<Ftest> > ,
+    new OneOperatorCode<CODE_L_Add<Finconnue> > ,
+    new OneOperatorCode<C_args>(t_C_args,t_C_args,t_C_args) // ,
+  //  new OperatorIdentity<FormBilinear>(), // add FH 13042005
+  //  new OperatorIdentity<FormLinear>()       // add FH 13042005  + int2d ( ..)
+  );
+ TheOperators->Add("-",
+    new OneOperatorCode<CODE_L_Minus<Foperator> > ,
+    new OneOperatorCode<CODE_L_Minus<Ftest> > ,
+    new OneOperatorCode<CODE_L_Minus<Finconnue> >,
+    new OneOperatorCode<CODE_L_Sub<Foperator> > ,    
+    new OneOperatorCode<CODE_L_Sub<Ftest> > ,
+    new OneOperatorCode<CODE_L_Sub<Finconnue> >,
+    new OneOperatorCode<C_args_minus>(t_C_args,t_C_args,t_fbilin) ,       
+    new OneOperatorCode<C_args_minus>(t_C_args,t_C_args,t_flin) ,
+    new OneOperatorCode<Minus_Form<FormBilinear > >,
+    new OneOperatorCode<Minus_Form<FormLinear > > 
+           
+  );
+  
+  
+  atype<const C_args*>()->AddCast( 
+      new OneOperatorCode<C_args>(t_C_args,t_fbilin) ,       
+      new OneOperatorCode<C_args>(t_C_args,t_flin)  ,     
+      new OneOperatorCode<C_args>(t_C_args,t_BC)       
+    );
+    
+  atype<const C_args*>()->AddCast( 
+      new OneOperatorCode<C_args>(t_C_args,atype<DotSlash_KN_<R> >()) ,
+      new OneOperatorCode<C_args>(t_C_args,atype<KN<R>*>())  ,
+      new OneOperatorCode<C_args>(t_C_args,atype<DotStar_KN_<R> >())  ,           
+      new OneOperatorCode<C_args>(t_C_args,atype<Matrice_Creuse<R>*>()) ,
+      new OneOperatorCode<C_args>(t_C_args,atype<VirtualMatrice<R>::plusAx >()),
+      new OneOperatorCode<C_args>(t_C_args,atype<VirtualMatrice<R>::plusAtx >())   
+       
+    );         
+
+  atype<const C_args*>()->AddCast( 
+      new OneOperatorCode<C_args>(t_C_args,atype<DotSlash_KN_<Complex> >()) ,
+      new OneOperatorCode<C_args>(t_C_args,atype<KN<Complex>*>())  ,
+      new OneOperatorCode<C_args>(t_C_args,atype<DotStar_KN_<Complex> >())  ,           
+      new OneOperatorCode<C_args>(t_C_args,atype<Matrice_Creuse<Complex>*>()) ,
+      new OneOperatorCode<C_args>(t_C_args,atype<VirtualMatrice<Complex>::plusAx >()),
+      new OneOperatorCode<C_args>(t_C_args,atype<VirtualMatrice<Complex>::plusAtx >())   
+       
+    );         
+    
+ TheOperators->Add("*",  
+    new OneOperatorCode<CODE_L_Mul<Foperator,Ftest,Finconnue> > ,
+    new OneOperatorCode<CODE_L_Mul<Foperator,Finconnue,Ftest> > );
+    
+// Warning just double or complex in following operator 
+// ----------------------------------------------------    
+//   in case of  ambiguity we take the double version  
+//   case    long -> double
+//           long -> complex
+ TheOperators->Add("*",      
+    new OneOperatorCode<CODE_L_MulLR<Finconnue,double>, 20> ,
+    new OneOperatorCode<CODE_L_MulLR<Foperator,double>, 20 > ,
+    new OneOperatorCode<CODE_L_MulLR<Ftest,double>, 20 > ,
+    new OneOperatorCode<CODE_L_MulRL<double,Finconnue>, 20 > ,
+    new OneOperatorCode<CODE_L_MulRL<double,Foperator>, 20 > ,
+    new OneOperatorCode<CODE_L_MulRL<double,Ftest>, 20 > 
+  );
+ TheOperators->Add("*",       
+    new OneOperatorCode<CODE_L_MulLR<Finconnue,Complex>, 10 > ,
+    new OneOperatorCode<CODE_L_MulLR<Foperator,Complex>, 10 > ,
+    new OneOperatorCode<CODE_L_MulLR<Ftest,Complex>, 10 > ,
+    new OneOperatorCode<CODE_L_MulRL<Complex,Finconnue>, 10 > ,
+    new OneOperatorCode<CODE_L_MulRL<Complex,Foperator>, 10 > ,
+    new OneOperatorCode<CODE_L_MulRL<Complex,Ftest>, 10 > 
+  );
+  
+ TheOperators->Add("/",  
+    new OneOperatorCode<CODE_L_DivLR<Finconnue,double>, 20 > ,
+    new OneOperatorCode<CODE_L_DivLR<Foperator,double>, 20 > ,
+    new OneOperatorCode<CODE_L_DivLR<Ftest,double>, 20 > );
+
+ TheOperators->Add("/",  
+    new OneOperatorCode<CODE_L_DivLR<Finconnue,Complex>, 10 > ,
+    new OneOperatorCode<CODE_L_DivLR<Foperator,Complex>, 10 > ,
+    new OneOperatorCode<CODE_L_DivLR<Ftest,Complex>, 10 > );
+    
+// Warning just double or complex in previous operator 
+// ----------------------------------------------------    
+  
+// TheOperators->Add("=",new OneOperatorCode<BC_set1<double> >);
+
+  
+ TheOperators->Add("=",
+		   new OneOperator2<pmesh*,pmesh*,pmesh >(&set_eqdestroy_incr),
+		//-   new OneBinaryOperator<set_eqarray<KN<double> ,VirtualMatrice<R>::plusAx > > ,       
+		//-   new OneBinaryOperator<set_eqarray<KN<double> ,VirtualMatrice<R>::plusAtx > >  ,      
+		//-   new OneBinaryOperator<set_eqarray<KN<double> ,VirtualMatrice<R>::solveAxeqb > >  ,      
+		   
+		   new OneBinaryOperator<set_eq_array<KN_<double> ,VirtualMatrice<R>::plusAx > > ,       
+		   new OneBinaryOperator<set_eq_array<KN_<double> ,VirtualMatrice<R>::plusAtx > >  ,      
+		   new OneBinaryOperator<set_eq_array<KN_<double> ,VirtualMatrice<R>::solveAxeqb > >  ,      
+		   
+		//-   new OpArraytoLinearForm<double,v_fes>(atype< KN<double>* >(),true,false)  ,
+		   new OpArraytoLinearForm<double,v_fes>(atype< KN_<double> >(),false,false)  ,
+		   new OpMatrixtoBilinearForm<double,v_fes >);
+ 
+ TheOperators->Add("=",
+		 //-  new OpArraytoLinearForm<double,v_fes3>(atype< KN<double>* >(),true,false)  ,// 3d
+		   new OpArraytoLinearForm<double,v_fes3>(atype< KN_<double> >(),false,false)  ,//3d
+		   new OpMatrixtoBilinearForm<double,v_fes3 >);//3d
+
+
+ TheOperators->Add("<-",
+		   new OpArraytoLinearForm<double,v_fes>(atype< KN<double>* >(),true,true) ,
+		   new OpArraytoLinearForm<Complex,v_fes>(atype< KN<Complex>* >(),true,true) , 
+		   new OpArraytoLinearForm<double,v_fes3>(atype< KN<double>* >(),true,true) , //3d
+		   new OpArraytoLinearForm<Complex,v_fes3>(atype< KN<Complex>* >(),true,true) //3d
+        
+        );
+
+
+ TheOperators->Add("=",
+		   new OneBinaryOperator<set_eqarray<KN<Complex> ,VirtualMatrice<Complex>::plusAx > > ,       
+		   new OneBinaryOperator<set_eqarray<KN<Complex> ,VirtualMatrice<Complex>::plusAtx > >  ,      
+		   new OneBinaryOperator<set_eqarray<KN<Complex> ,VirtualMatrice<Complex>::solveAxeqb > >  ,  
+		   
+		   //- new OneBinaryOperator<set_eq_array<KN_<Complex> ,VirtualMatrice<Complex>::plusAx > > ,       
+		   //- new OneBinaryOperator<set_eq_array<KN_<Complex> ,VirtualMatrice<Complex>::plusAtx > >  ,      
+		   //- new OneBinaryOperator<set_eq_array<KN_<Complex> ,VirtualMatrice<Complex>::solveAxeqb > >  ,      
+		   
+		   new OpArraytoLinearForm<Complex,v_fes>(atype< KN<Complex>* >(),true,false)  ,
+		   //- new OpArraytoLinearForm<Complex,v_fes>(atype< KN_<Complex> >(),false,false)   ,
+		   new OpMatrixtoBilinearForm<Complex,v_fes >);
+ 
+ TheOperators->Add("=",
+		  //-  new OpArraytoLinearForm<Complex,v_fes3>(atype< KN<Complex>* >(),true,false)  , // 3d
+		   new OpArraytoLinearForm<Complex,v_fes3>(atype< KN_<Complex> >(),false,false)   , //3d
+		   new OpMatrixtoBilinearForm<Complex,v_fes3 >);// 3d
+
+ // add august 2007 
+ TheOperators->Add("<-",
+		   new OneBinaryOperator<init_eqarray<KN<double> ,VirtualMatrice<double>::plusAx > > ,       
+		   new OneBinaryOperator<init_eqarray<KN<double> ,VirtualMatrice<double>::plusAtx > >  ,      
+		   new OneBinaryOperator<init_eqarray<KN<double> ,VirtualMatrice<double>::solveAxeqb > >  ,  
+		   
+		   new OneBinaryOperator<init_eqarray<KN<Complex> ,VirtualMatrice<Complex>::plusAx > > ,
+		   new OneBinaryOperator<init_eqarray<KN<Complex> ,VirtualMatrice<Complex>::plusAtx > >  ,      
+		   new OneBinaryOperator<init_eqarray<KN<Complex> ,VirtualMatrice<Complex>::solveAxeqb > >    
+		   
+		);
+ 
+     
+ TheOperators->Add("+=",
+		 //-   new OneBinaryOperator<set_eqarray_add<KN<double> ,VirtualMatrice<R>::plusAx > > ,       
+		  //-  new OneBinaryOperator<set_eqarray_add<KN<double> ,VirtualMatrice<R>::plusAtx > > ,
+		   
+		   new OneBinaryOperator<set_eq_array_add<KN_<double> ,VirtualMatrice<double>::plusAx > > ,       
+		   new OneBinaryOperator<set_eq_array_add<KN_<double> ,VirtualMatrice<double>::plusAtx > >,        
+		   
+		 //-   new OpArraytoLinearForm<double,v_fes>(atype< KN<double>* >(),true,false,false)  ,
+		   new OpArraytoLinearForm<double,v_fes>(atype< KN_<double> >(),false,false,false)  , 
+		 //-   new OpArraytoLinearForm<double,v_fes3>(atype< KN<double>* >(),true,false,false)  , // 3d
+		   new OpArraytoLinearForm<double,v_fes3>(atype< KN_<double> >(),false,false,false)   // 3d
+		   
+       );
+
+ TheOperators->Add("+=",
+		  //-  new OneBinaryOperator<set_eqarray_add<KN<Complex> ,VirtualMatrice<Complex>::plusAx > > ,       
+		  //-  new OneBinaryOperator<set_eqarray_add<KN<Complex> ,VirtualMatrice<Complex>::plusAtx > > ,       
+		   
+		   new OneBinaryOperator<set_eq_array_add<KN_<Complex> ,VirtualMatrice<Complex>::plusAx > > ,       
+		   new OneBinaryOperator<set_eq_array_add<KN_<Complex> ,VirtualMatrice<Complex>::plusAtx > >,
+		   
+		  //-  new OpArraytoLinearForm<Complex,v_fes>(atype< KN<Complex>* >(),true,false,false)  ,
+		   new OpArraytoLinearForm<Complex,v_fes>(atype< KN_<Complex> >(),false,false,false)  , 
+
+		  //-  new OpArraytoLinearForm<Complex,v_fes3>(atype< KN<Complex>* >(),true,false,false)  ,
+		   new OpArraytoLinearForm<Complex,v_fes3>(atype< KN_<Complex> >(),false,false,false)   
+              
+       );
+
+
+       
+ TheOperators->Add("<-",new OpMatrixtoBilinearForm<double,v_fes >(1) );
+ TheOperators->Add("<-",new OpMatrixtoBilinearForm<Complex,v_fes >(1) );
+
+ TheOperators->Add("<-",new OpMatrixtoBilinearForm<double,v_fes3 >(1) ); // 3d
+ TheOperators->Add("<-",new OpMatrixtoBilinearForm<Complex,v_fes3 >(1) );// 3d
+       
+ Add<const  FormLinear   *>("(","",new OpCall_FormLinear<FormLinear,v_fes> );
+ Add<const  FormBilinear *>("(","",new OpCall_FormBilinear<FormBilinear,v_fes> );
+ Add<const  FormBilinear *>("(","",new OpCall_FormLinear2<FormBilinear,v_fes> );
+ Add<const C_args*>("(","",new OpCall_FormLinear2<C_args,v_fes>);
+ Add<const C_args*>("(","",new OpCall_FormBilinear<C_args,v_fes> );
+
+ Add<const  FormLinear   *>("(","",new OpCall_FormLinear<FormLinear,v_fes3> );
+ Add<const  FormBilinear *>("(","",new OpCall_FormBilinear<FormBilinear,v_fes3> );
+ Add<const  FormBilinear *>("(","",new OpCall_FormLinear2<FormBilinear,v_fes3> );
+ Add<const C_args*>("(","",new OpCall_FormLinear2<C_args,v_fes3>);
+ Add<const C_args*>("(","",new OpCall_FormBilinear<C_args,v_fes3> );
+
+//  correction du bug morale 
+//  Attention il y a moralement un bug
+//  les initialisation   x = y   ( passe par l'operateur binaire <-  dans TheOperators
+//   les initialisation   x(y)   ( passe par l'operateur unaire <-  de typedebase de x (inutile 2007).
+//  x(y1,..,yn) est un operator n+1   (x,y1,..,yn)
+// on passe toujours par x(y) maintenant.
+//   -------
+       
+       
+ TheOperators->Add("<-",
+       new OneOperator2_<pferbase*,pferbase*,pfes* >(MakePtrFE2),
+       new OneOperator3_<pferbasearray*,pferbasearray*,pfes*,long >(MakePtrFE3),  
+
+
+       new OneOperator2_<pfecbase*,pfecbase*,pfes* >(MakePtrFE2),
+       new OneOperator3_<pfecbasearray*,pfecbasearray*,pfes*,long >(MakePtrFE3) //,
+     //  new OneOperator2_<pmesharray*,pmesharray*,long >(MakePtr)
+       
+       
+       );
+ TheOperators->Add("<-",
+       new OneOperatorMakePtrFE<double>(atype<double>()),  //  scalar case
+       new OneOperatorMakePtrFE<double>(atype<E_Array>()),  //  vect case
+       new OneOperatorMakePtrFE<Complex>(atype<Complex>()),  //  scalar complex  case
+       new OneOperatorMakePtrFE<Complex>(atype<E_Array>())  //  vect complex case
+       );
+//  interpolation   operator 
+ TheOperators->Add("=",
+       new OneOperator2_<pfer,pfer,double,E_F_StackF0F0opt2<double> >(set_fe<double>) ,
+       new OneOperator2_<pfec,pfec,Complex,E_F_StackF0F0opt2<Complex> >(set_fe<Complex>) 
+       
+       ) ;     
+     //  new OneOperator2_<pferbase,pferbase,E_Array,E_F_StackF0F0 >(set_fev));
+       
+//  Attention il y a moralement un bug
+//  les initialisation   x = y   ( passe par l'operateur binaire <-  dans TheOperators
+//   les initialisation   x(y)   ( passe par l'operateur unaire <-  de typedebase de x
+//   -------  corrige 
+
+     
+ TheOperators->Add("=",
+       new OneOperator2<pfes*,pfes*,pfes>(&set_eqdestroy_incr),
+       new Op_CopyArray()
+       );
+       
+ TheOperators->Add("<-",
+       new OneOperator2_<pfes*,pfes*,pfes>(&set_copy_incr));
+ 
+ TheOperators->Add("<<",
+       new OneBinaryOperator<PrintPnd<R3*>  >,
+       new OneBinaryOperator<PrintPnd<Matrice_Creuse<R>*> >,
+       new OneBinaryOperator<PrintPnd<Matrice_Creuse<Complex>*> >
+
+       );   
+
+ TheOperators->Add(">>",
+		   new OneBinaryOperator<Op_Read<Matrice_Creuse<R> > >,
+		   new OneBinaryOperator<Op_Read<Matrice_Creuse<Complex> > >
+		   
+		   );   
+ 
+ 
+ Global.Add("int2d","(",new OneOperatorCode<CDomainOfIntegration>);
+ Global.Add("int1d","(",new OneOperatorCode<CDomainOfIntegrationBorder>);
+ Global.Add("intalledges","(",new OneOperatorCode<CDomainOfIntegrationAllEdges>);
+ Global.Add("intallVFedges","(",new OneOperatorCode<CDomainOfIntegrationVFEdges>);
+ Global.Add("jump","(",new OneUnaryOperator<JumpOp<R>,JumpOp<R> >);
+ Global.Add("mean","(",new OneUnaryOperator<MeanOp<R>,MeanOp<R> >);
+ Global.Add("average","(",new OneUnaryOperator<MeanOp<R>,MeanOp<R> >);
+ 
+ Global.Add("jump","(",new OneUnaryOperator<JumpOp<Complex>,JumpOp<Complex> >);
+ Global.Add("mean","(",new OneUnaryOperator<MeanOp<Complex>,MeanOp<Complex> >);
+ Global.Add("average","(",new OneUnaryOperator<MeanOp<Complex>,MeanOp<Complex> >);
+
+  
+ Add<const CDomainOfIntegration*>("(","",new OneOperatorCode<FormBilinear> );
+ Add<const CDomainOfIntegration *>("(","",new OneOperatorCode<FormLinear> );
+ 
+ Add<const CDomainOfIntegration *>("(","",new OneOperatorCode<IntFunction<double> >);
+ Add<const CDomainOfIntegration *>("(","",new OneOperatorCode<IntFunction<complex<double> > >);
+ 
+
+
+ map_type[typeid(double).name()]->AddCast(
+   new E_F1_funcT<double,pfer>(pfer2R<R,0>)
+   );
+   
+ map_type[typeid(Complex).name()]->AddCast(
+   new E_F1_funcT<Complex,pfec>(pfer2R<Complex,0>)
+   );
+ 
+// bof  
+ Global.Add("dx","(",new E_F1_funcT<double,pfer>(pfer2R<R,op_dx>));
+ Global.Add("dy","(",new E_F1_funcT<double,pfer>(pfer2R<R,op_dy>));
+ Global.Add("dxx","(",new E_F1_funcT<double,pfer>(pfer2R<R,op_dxx>));
+ Global.Add("dyy","(",new E_F1_funcT<double,pfer>(pfer2R<R,op_dyy>));
+ Global.Add("dxy","(",new E_F1_funcT<double,pfer>(pfer2R<R,op_dxy>));
+ Global.Add("dyx","(",new E_F1_funcT<double,pfer>(pfer2R<R,op_dyx>));
+
+ Global.Add("dx","(",new E_F1_funcT<Complex,pfec>(pfer2R<Complex,op_dx>));
+ Global.Add("dy","(",new E_F1_funcT<Complex,pfec>(pfer2R<Complex,op_dy>));
+ Global.Add("dxx","(",new E_F1_funcT<Complex,pfec>(pfer2R<Complex,op_dxx>));
+ Global.Add("dyy","(",new E_F1_funcT<Complex,pfec>(pfer2R<Complex,op_dyy>));
+ Global.Add("dxy","(",new E_F1_funcT<Complex,pfec>(pfer2R<Complex,op_dxy>));
+ Global.Add("dyx","(",new E_F1_funcT<Complex,pfec>(pfer2R<Complex,op_dyx>));
+
+ 
+ // Add<pferbasearray*>("[","",new OneOperator2_FEcomp<double,v_fes>(get_element)); 
+  Add<pfecbasearray*>("[","",new OneOperator2_<pfecbase*,pfecbasearray*,long>(get_element));  // use FH sep. 2009 
+  Add<pferbasearray*>("[","",new OneOperator2_<pferbase*,pferbasearray*,long>(get_element));  //  use ???? FH sep. 2009
+    // bof bof ..
+    // resize of array of Finite element ..  a little hard 2013 FH
+    Dcl_Type< Resize1<pfecbasearray* > > ();
+    Dcl_Type< Resize1<pferbasearray* > > ();
+    Dcl_Type< Resize1<pfecarray > > ();
+    Dcl_Type< Resize1<pferarray > > ();
+    Add<pfecbasearray*>("resize",".",new OneOperator1<Resize1<pfecbasearray* >,pfecbasearray*>(to_Resize1));  //  FH fev 2013
+    Add<pferbasearray*>("resize",".",new OneOperator1<Resize1<pferbasearray* >,pferbasearray*>(to_Resize1));  //   FH fev. 2013
+    Add<pferarray>("resize",".",new OneOperator1<Resize1<pferarray >,pferarray>(to_Resize1));  //  FH fev 2013
+    Add<pfecarray>("resize",".",new OneOperator1<Resize1<pfecarray >,pfecarray>(to_Resize1));  //   FH fev. 2013
+    new OneOperator2_<pferbasearray*,Resize1<pferbasearray* > , long  >(fepresize<pferbasearray*>);
+    Add<Resize1<pferbasearray* > >("(","",new  OneOperator2_<pferbasearray*,Resize1<pferbasearray* > , long  >(fepresize));
+    Add<Resize1<pfecbasearray* > >("(","",new OneOperator2_<pfecbasearray*,Resize1<pfecbasearray* > , long  >(fepresize));
+    Add<Resize1<pferarray > >("(","",new OneOperator2_<pferarray,Resize1<pferarray > , long  >(feresize));
+    Add<Resize1<pfecarray > >("(","",new OneOperator2_<pfecarray,Resize1<pfecarray > , long  >(feresize));
+
+    Dcl_Type< Resize1<pf3rbasearray* > > ();
+    Dcl_Type< Resize1<pf3rarray > > ();
+    Add<pf3rbasearray*>("resize",".",new OneOperator1<Resize1<pf3rbasearray* >,pf3rbasearray*>(to_Resize1));  //   FH fev. 2013
+    Add<pf3rarray>("resize",".",new OneOperator1<Resize1<pf3rarray >,pf3rarray>(to_Resize1));  //  FH fev 2013
+    new OneOperator2_<pf3rbasearray*,Resize1<pf3rbasearray* > , long  >(fepresize<pf3rbasearray*>);
+    Add<Resize1<pf3rbasearray* > >("(","",new  OneOperator2_<pf3rbasearray*,Resize1<pf3rbasearray* > , long  >(fepresize));
+    Add<Resize1<pf3rarray > >("(","",new OneOperator2_<pf3rarray,Resize1<pf3rarray > , long  >(feresize));
+
+// end of resize ...
+   
+  Add<pfecbasearray*>("n",".",new OneOperator1_<long,pfecbasearray*>(get_size));  //  FH fev 2013
+  Add<pferbasearray*>("n",".",new OneOperator1_<long,pferbasearray*>(get_size));  //   FH fev. 2013
+  Add<pferarray>("n",".",new OneOperator1_<long,pferarray>(get_size));  //  FH fev 2013
+  Add<pfecarray>("n",".",new OneOperator1_<long,pfecarray>(get_size));  //   FH fev. 2013
+
+  Add<pf3rbasearray*>("n",".",new OneOperator1_<long,pf3rbasearray*>(get_size));  //   FH fev. 2013
+  Add<pf3rarray>("n",".",new OneOperator1_<long,pf3rarray>(get_size));  //  FH fev 2013
+    
+    
+  Add<pferarray>("[","",new OneOperator2_FE_get_elmnt<double,v_fes>());// new version FH sep 2009
+  Add<pfecarray>("[","",new OneOperator2_FE_get_elmnt<Complex,v_fes>());
+   
+  Add<pf3rarray>("[","",new OneOperator2_FE_get_elmnt<double,v_fes>());// new version FH sep 2009
+
+//    Add<pferarray>("[","",new OneOperator2_<pfer,pferarray,long>(get_element));
+//    Add<pfecarray>("[","",new OneOperator2_<pfec,pfecarray,long>(get_element));
+  
+ // Add<pmesharray>("[","",new OneOperator2_<pmesh*,pmesharray*,long>(get_element));
+
+  TheOperators->Add("\'",       
+       new OneOperator1<Matrice_Creuse_Transpose<R>,Matrice_Creuse<R> *>(&Build<Matrice_Creuse_Transpose<R>,Matrice_Creuse<R> *>),
+       new OneOperator1<Matrice_Creuse_Transpose<Complex>,Matrice_Creuse<Complex> *>(&Build<Matrice_Creuse_Transpose<Complex>,Matrice_Creuse<Complex> *>)
+  );
+  
+ Add<pfer>("(","",new interpolate_f_X_1<R> ); 
+  TheOperators->Add("=", new OneOperator2_<void,interpolate_f_X_1<R>::type,double,E_F_StackF0F0 >(set_feoX_1) ) ; 
+// init_lgmesh() ;
+  init_lgmat();
+  init_mesh_array();
+
+ l2interpreter = new LinkToInterpreter;
+ using namespace FreeFempp; 
+ FreeFempp::TypeVarForm<double>::Global = new TypeVarForm<double>();       
+ FreeFempp::TypeVarForm<Complex>::Global = new TypeVarForm<Complex>();       
+    
+ 
+ Global.New("P13d",CConstantTFE3(&DataFE<Mesh3>::P1));   
+ Global.New("P23d",CConstantTFE3(&DataFE<Mesh3>::P2));   
+ Global.New("P03d",CConstantTFE3(&DataFE<Mesh3>::P0)); 
+ Global.New("RT03d",CConstantTFE3(&RT03d));   
+ Global.New("Edge03d",CConstantTFE3(&Edge03d));   
+ Global.New("P1b3d",CConstantTFE3(&P1bLagrange3d));   
+    /*
+     for (ListOfTFE * i=ListOfTFE::all;i;i=i->next)
+     {
+     ffassert(i->tfe); // check 
+     AddNewFE(i->name,i->tfe);
+     // Global.New(i->name, Type_Expr(atype<TypeOfFE*>(),new  EConstantTypeOfFE(i->tfe)));
+     }
+     
+     */
+  TEF2dto3d[FindFE2("P1")]=&DataFE<Mesh3>::P1;
+  TEF2dto3d[FindFE2("P2")]=&DataFE<Mesh3>::P2;
+  TEF2dto3d[FindFE2("P0")]=&DataFE<Mesh3>::P0;
+  TEF2dto3d[FindFE2("P1b")]=&P1bLagrange3d;
+  TEF2dto3d[FindFE2("RT0")]=&RT03d;
+ /*
+// add may 2011 F. HEcHt   
+  //    in progress ?????  to set varaible to store FinitELEMEnt type.  
+    zzzfff->Add("FiniteElement",atype<TypeOfFE*>());
+    zzzfff->Add("FiniteElement3",atype<TypeOfFE3*>());
+
+    TheOperators->Add("=",new OneOperator2<TypeOfFE*,TypeOfFE*,TypeOfFE*>(&setFE<1>) );    
+    TheOperators->Add("<-",new OneOperator2_<pfes*,pfes*,pfes>(&setFE<0>));
+  
+  */
+}
+
+/*   in progress ?????  to set varaible to store FinitELEMEnt type.  
+template<int init>
+TypeOfFE* setFE(TypeOfFE* a,TypeOfFE* b) 
+{
+    if(init) 
+    return a;    
+}
+*/
+void clean_lgfem()
+{
+  for (int i=0;i<kTypeSolveMat;++i)
+    delete dTypeSolveMat[i];
+   
+  delete l2interpreter;
+  delete  FreeFempp::TypeVarForm<double>::Global;
+  delete  FreeFempp::TypeVarForm<Complex>::Global;
+}
+template<class K,class v_fes>
+Expression IsFEcomp(const C_F0 &c,int i, Expression & rrr,Expression &iii)
+{
+    Expression r=0;
+    if(!i) rrr=0,iii=0;
+    //  typedef double K;
+    if(atype<typename E_FEcomp<K,v_fes>::Result>() == c.left())
+      {
+	  const E_FEcomp<K,v_fes> * e= dynamic_cast<const E_FEcomp<K,v_fes>*>(c.LeftValue() );
+	  if( !e) 	
+	    { 
+		const E_FEcomp_get_elmnt_array<K,v_fes> * ee= dynamic_cast<const E_FEcomp_get_elmnt_array<K,v_fes>*>(c.LeftValue() );
+		
+		if( !ee) 	
+		  { 
+		      cerr <<" Fatal error Copy array .." << *c.left()<< " composante : " << i << endl;
+		      ffassert(ee);
+		  }
+		else 
+		  { 
+		      if (ee->comp ==i) {
+			  if (i && ee->a00->a0 != rrr) cerr << " error composante arry vect. incompatible " << ee->comp << " "<< ee->a00->a0 << " != " << rrr << endl;
+			  else {
+			   r= ee->a0;
+			    rrr= ee->a00->a0;
+			    iii= ee->a1;
+			  }
+			 
+		      }
+		      else cerr << " erreur composante " << ee->comp << " != " << i << endl; 
+		    
+			
+		  }
+	    } 
+	  else 
+	    {
+	    	
+		if (e->comp ==i) {
+		      if (i && e->a0 != rrr) cerr << " error composante incompatible " << e->comp  << endl;
+		      else  rrr=r=e->a0;
+		}
+	      else cerr << " erreur composante " << e->comp << " != " << endl;		
+	  }
+      }
+    return r;
+}
+
+/*
+Expression IsCFEcomp(const C_F0 &c,int i)
+{
+  typedef Complex K;
+  if(atype<E_FEcomp<K,v_fes>::Result>() == c.left())
+   {
+     const E_FEcomp<K,v_fes> * e= dynamic_cast<const E_FEcomp<K,v_fes>*>(c.LeftValue() );
+     ffassert(e);
+     if (e->comp !=i) return 0;
+     else return e->a0;
+   }
+  else return 0;
+}
+*/
+
+template<class K,class v_fes>
+Expression Op_CopyArrayT(const E_Array & a,const E_Array & b)
+{
+    typedef FEbaseArray<K,v_fes>  FEba;
+
+    //int na=a.size();
+    int nb=b.size();
+    Expression r=0,rr=0,rrr,iii;
+    //  try real voctor value FE interpolation 
+    rr=IsFEcomp<K,v_fes>(a[0],0,rrr,iii) ;
+    if (rr !=0) 
+      {
+          for (int i=1;i<nb;i++)
+	      if (!IsFEcomp<K,v_fes>(a[i],i,rrr,iii))  
+		  CompileError("Copy of Array with incompatible K  vector value FE function () !");;
+	  if(iii) {// ffassert(0); //  moralement il : rrr[iii]
+	      C_F0 aa(rrr,atype<FEba**>()),ii(iii,atype<long>());
+	      C_F0 aa_ii(aa,"[",ii);
+	      rr=aa_ii.LeftValue();
+	  }
+	  if(v_fes::d==2) r=new E_set_fev<K>(&b,rr,2);
+	  else if(v_fes::d==3) r=new  E_set_fev3<K,v_fes3>(&b,rr);
+      }
+    //  try complex vector value FE interpolation 
+    return r;
+}
+ 
+ E_F0 * Op_CopyArray::code(const basicAC_F0 & args) const  {
+       E_F0 * ret=0;
+      const E_Array & a= *dynamic_cast<const E_Array*>(args[0].LeftValue());
+      const E_Array & b= *dynamic_cast<const E_Array*>(args[1].LeftValue());
+      int na=a.size();
+      int nb=b.size();
+      if (na != nb ) 
+        CompileError("Copy of Array with incompatible size!");
+      if(0)
+	{ // old code !!!!!!! before removing FH sept. 2009 
+       Expression rr=0,rrr,iii;
+       //  try real voctor value FE interpolation 
+       rr=IsFEcomp<double,v_fes>(a[0],0,rrr,iii) ;
+       if (rr !=0) 
+        {
+          for (int i=1;i<nb;i++)
+	    if (!IsFEcomp<double,v_fes>(a[i],i,rrr,iii))  
+                CompileError("Copy of Array with incompatible real vector value FE function () !");;           
+	  return  new E_set_fev<double>(&b,rr,2);
+         }
+       //  try complex vector value FE interpolation 
+
+       rr=IsFEcomp<Complex,v_fes>(a[0],0,rrr,iii) ;
+       if (rr !=0) 
+        {
+          for (int i=1;i<nb;i++)
+	    if (!IsFEcomp<Complex,v_fes>(a[i],i,rrr,iii))  
+	      CompileError("Copy of Array with incompatible complex vector value FE function () !");;           
+	  return  new E_set_fev<Complex>(&b,rr,2);
+	}
+       
+       rr=IsFEcomp<double,v_fes3>(a[0],0,rrr,iii) ;
+       if (rr !=0) 
+        {
+          for (int i=1;i<nb;i++)
+	    if (!IsFEcomp<double,v_fes3>(a[i],i,rrr,iii))  
+                CompileError("Copy of Array with incompatible real vector value FE function () !");;           
+	  return  new E_set_fev3<double,v_fes3>(&b,rr);
+         }
+       //  try complex vector value FE interpolation 
+
+       rr=IsFEcomp<Complex,v_fes3>(a[0],0,rrr,iii) ;
+       if (rr !=0) 
+        {
+          for (int i=1;i<nb;i++)
+	    if (!IsFEcomp<Complex,v_fes3>(a[i],i,rrr,iii))  
+                CompileError("Copy of Array with incompatible complex vector value FE function () !");;           
+	  return  new E_set_fev3<Complex,v_fes3>(&b,rr);
+         }
+	}
+       else
+	 {  Expression r=0; // new code FH sep 2009.
+	     if(!r)  r=Op_CopyArrayT<double,v_fes>(a,b);
+	     if(!r)  r=Op_CopyArrayT<Complex,v_fes>(a,b);
+	     if(!r)  r=Op_CopyArrayT<double,v_fes3>(a,b);
+	     if(!r)  r=Op_CopyArrayT<Complex,v_fes3>(a,b);
+	     if(r) return r;
+	 }
+        CompileError("Internal Error: General Copy of Array : to do ");
+      return ret;}
+
+template<class v_fes,int DIM>
+C_F0 NewFEvariableT(ListOfId * pids,Block *currentblock,C_F0 & fespacetype,CC_F0 init,bool cplx,int dim)
+{
+  ffassert(dim==DIM);
+  //   if (cplx)
+//   cout << "NewFEvariable  cplx=" << cplx << endl;
+  typedef FEbase<double,v_fes> FE;
+  typedef E_FEcomp<R,v_fes> FEi;
+  typedef typename FEi::Result FEiR;
+  
+  typedef FEbase<Complex,v_fes> CFE;
+  typedef E_FEcomp<Complex,v_fes> CFEi;
+  typedef typename  CFEi::Result CFEiR;
+  
+  Expression fes =fespacetype;
+  
+  aType dcltype=atype<FE **>();
+  aType cf0type=atype<C_F0>();
+  aType rtype=atype<FEiR>();
+  
+  if(cplx)
+    {
+      dcltype=atype<CFE **>();
+      rtype=atype<CFEiR>();
+      
+    }
+  ffassert(pids);
+  ListOfId &ids(*pids);
+  
+  string str("[");
+  
+  const int n=ids.size();
+  ffassert(n>0);
+  if ( fes->nbitem() != (size_t) n) {
+    cerr << " the array size must be " << fes->nbitem()  << " not " <<  n << endl;
+    CompileError("Invalide array size  for  vectorial fespace function");
+  }
+  for (int i=0;i<n;i++)
+    { 
+      str += ids[i].id;
+      if(i<n-1) str +=",";
+    }
+  str += "]";
+     bool binit= !init.Empty(); 
+     char * name = strcpy(CodeAllocT<char>::New(str.size()+1),str.c_str());
+     C_F0 ret; 
+     // modif  100109 (add Block::  before NewVar for g++ 3.3.3 on Suse 9)
+    ret= binit ? currentblock->Block::NewVar<LocalVariable>(name,dcltype,basicAC_F0_wa(fespacetype,init)) 
+      : currentblock->Block::NewVar<LocalVariable>(name,dcltype,basicAC_F0_wa(fespacetype));
+     C_F0 base = currentblock->Find(name);
+     if (cplx)
+       for (int i=0;i<n;i++) 
+         currentblock->NewID(cf0type,ids[i].id, C_F0(new CFEi(base,i,n), rtype) ); 
+     else
+       for (int i=0;i<n;i++) 
+         currentblock->NewID(cf0type,ids[i].id, C_F0(new FEi(base,i,n), rtype) ); 
+     delete pids; // add FH 25032005 
+     
+      return ret ; 
+}
+
+
+C_F0 NewFEvariable(ListOfId * pids,Block *currentblock,C_F0 & fespacetype,CC_F0 init,bool cplx,int dim)
+{
+  if(dim==2)
+    return NewFEvariableT<v_fes,2>(pids,currentblock,fespacetype,init,cplx,dim);
+  else if  (dim==3) 
+    return NewFEvariableT<v_fes3,3>(pids,currentblock,fespacetype,init,cplx,dim);
+  else
+    CompileError("Invalide fespace on Rd  ( d != 2 or 3) ");
+    return C_F0();
+}
+C_F0 NewFEvariable(const char * id,Block *currentblock,C_F0 & fespacetype,CC_F0 init,bool cplx,int dim)
+{
+  ListOfId * lid =new ListOfId;
+  lid->push_back(UnId(id));
+  return NewFEvariable(lid,currentblock,fespacetype,init,cplx,dim);
+}
+
+
+size_t dimFESpaceImage(const basicAC_F0 &args) 
+{
+  //aType t_m2= atype<pmesh*>();
+  // aType t_m3= atype<pmesh3*>();
+  aType t_tfe= atype<TypeOfFE*>();
+  aType t_tfe3= atype<TypeOfFE3*>();
+  aType t_a= atype<E_Array>();
+  size_t dim23=0; 
+  
+  for (int i=0;i<args.size();i++)
+    if (args[i].left() == t_tfe || args[i].left() == t_tfe3 )
+      dim23 += args[i].LeftValue()->nbitem();
+    else if (args[i].left() == t_a)
+      {
+	const E_Array & ea= *dynamic_cast<const E_Array *>(args[i].LeftValue());
+	ffassert(&ea);
+	for (int i=0;i<ea.size();i++)
+	  if (ea[i].left() == t_tfe || ea[i].left() == t_tfe3)
+            dim23 += ea[i].nbitem();
+	  else ffassert(0); // bug 
+      }
+  dim23 = dim23 ? dim23 : 1;
+  // cout << "dimFESpaceImage:  FESpace in R^"<< dim << endl;
+  return dim23;
+}
+
+aType  typeFESpace(const basicAC_F0 &args) 
+{
+  
+  aType t_m2= atype<pmesh*>();
+  aType t_m3= atype<pmesh3*>();
+  aType t_tfe= atype<TypeOfFE*>();
+  aType t_tfe3= atype<TypeOfFE3*>();
+  //aType t_a= atype<E_Array>();
+  size_t d=0;
+    // 20 avril 2009 add brak 
+  for (int i=0;i<args.size();i++)
+    
+    if (args[i].left() == t_tfe || args[i].left() == t_m2)
+      {   ffassert(d==0 || d==2) ;d=2;break;}
+    else if (args[i].left() == t_tfe3 || args[i].left() == t_m3)
+      {   ffassert(d==0 || d==3) ;d=3;break;}
+  
+  if(!(d == 2 || d == 3))
+    {
+      cerr << " bug " << d << " != 2 ror 3 \n";
+      ffassert(0);
+    }
+ //  cout<< " d= " << d << endl;
+  return d == 2 ? atype<pfes *>() : atype<pfes3 *>();
+}
+
+
+template<class v_fes,int DIM>   
+C_F0 NewFEarrayT(ListOfId * pids,Block *currentblock,C_F0 & fespacetype,CC_F0 sizeofarray,bool cplx,int dim)
+{
+  ffassert(dim==DIM);
+  // ffassert(!cplx);
+  typedef FEbaseArray<double,v_fes>  FE;
+  typedef  E_FEcomp<R,v_fes,FE > FEi;
+   typedef typename FEi::Result FEiR;
+
+   typedef FEbaseArray<Complex,v_fes>  CFE;
+   typedef  E_FEcomp<Complex,v_fes,CFE > CFEi;
+   typedef typename CFEi::Result CFEiR;
+   
+   Expression fes =fespacetype;
+    aType dcltype=atype<FE **>();
+    aType cf0type=atype<C_F0>();
+    aType rtype=atype<FEiR>();
+    ffassert(pids);
+    ListOfId &ids(*pids);
+    if(cplx)
+      {
+        dcltype=atype<CFE **>();
+        rtype=atype<CFEiR>();
+        
+      }
+    
+    string str("[");
+    
+    const int n=ids.size();
+     ffassert(n>0);
+   if ( fes->nbitem() != (size_t) n) {
+      cerr << " the array size must be " << fes->nbitem()  << " not " <<  n << endl;
+      CompileError("Invalid array size  for  vectorial fespace function");
+   }
+   for (int i=0;i<n;i++)
+    { 
+     str += ids[i].id;
+     if(i<n-1) str +=",";
+    }
+     str += "]";
+     char * name = strcpy(CodeAllocT<char>::New(str.size()+1),str.c_str());
+     C_F0 ret=  currentblock->Block::NewVar<LocalVariable>(name,dcltype,basicAC_F0_wa(fespacetype,sizeofarray)); 
+     C_F0 base = currentblock->Find(name);
+     if(cplx)
+      for (int i=0;i<n;i++) 
+         currentblock->NewID(cf0type,ids[i].id, C_F0(new CFEi(base,i,n), rtype) ); 
+     else
+      for (int i=0;i<n;i++) 
+         currentblock->NewID(cf0type,ids[i].id, C_F0(new FEi(base,i,n), rtype) );
+         
+     delete pids ; // add FH 25032005 
+      return ret ; 
+
+}
+
+   
+C_F0 NewFEarray(ListOfId * pids,Block *currentblock,C_F0 & fespacetype,CC_F0 sizeofarray,bool cplx,int dim)
+{
+  if(dim==2)
+    return NewFEarrayT<v_fes,2>(pids,currentblock,fespacetype,sizeofarray,cplx,dim);
+  else if  (dim==3) 
+    return NewFEarrayT<v_fes3,3>(pids,currentblock,fespacetype,sizeofarray,cplx,dim);
+  else
+    CompileError("Invalid vectorial fespace on Rd  ( d != 2 or 3) ");
+    return C_F0();
+}
+C_F0 NewFEarray(const char * id,Block *currentblock,C_F0 & fespacetype,CC_F0 sizeofarray,bool cplx,int dim)
+{ 
+  ListOfId *lid= new ListOfId;
+  lid->push_back(UnId(id));
+  return NewFEarray(lid,currentblock,fespacetype,sizeofarray,cplx,dim);
+}
+
+namespace Fem2D {
+void  Expandsetoflab(Stack stack,const BC_set & bc,set<long> & setoflab)
+{
+    for (size_t i=0;i<bc.on.size();i++)
+        if(bc.onis[i] ==0)
+	    {
+            long  lab  = GetAny<long>( (*bc.on[i])(stack));
+            setoflab.insert(lab);
+            if ( verbosity>99) cout << lab << " ";
+            
+	    }
+        else 
+	    {
+            KN<long>  labs( GetAny<KN_<long> >( (*bc.on[i])(stack)));
+            for (long j=0; j<labs.N(); ++j) {	      
+                setoflab.insert(labs[j]);
+                if ( verbosity>99) cout << labs[j] << " ";
+            }	  
+            
+	    }
+    if(verbosity>99) 
+        cout << endl;
+    
+}
+
+void  Expandsetoflab(Stack stack,const CDomainOfIntegration & di,set<int> & setoflab,bool &all)
+{
+    for (size_t i=0;i<di.what.size();i++)
+        if(di.whatis[i] ==0)
+	    {
+            long  lab  = GetAny<long>( (*di.what[i])(stack));
+            setoflab.insert(lab);
+            if ( verbosity>3) cout << lab << " ";
+            all=false;
+	    }
+        else 
+	    {
+            KN<long>  labs( GetAny<KN_<long> >( (*di.what[i])(stack)));
+            for (long j=0; j<labs.N(); ++j) {	      
+                setoflab.insert(labs[j]);
+                if ( verbosity>3) cout << labs[j] << " ";
+            }	  
+            all=false;	  
+	    }
+    
+}
+}
+
+
+#include "InitFunct.hpp"
+
+
+static addingInitFunct TheaddingInitFunct(-20,init_lgfem);
diff --git a/src/fflib/lgfem.hpp b/src/fflib/lgfem.hpp
new file mode 100644
index 0000000..2f57df6
--- /dev/null
+++ b/src/fflib/lgfem.hpp
@@ -0,0 +1,814 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+// ATTENTION pfes est la classe qui modelise un pointeur
+// sur un FESpace (donc un espace d'element fini 
+//  mais si la maillage change alors 
+//  l'espace change 
+//   cf la fonction set qui reconstruit FESpace
+
+
+extern Block *currentblock;
+
+void init_lgmat(); // initialisation for sparse mat functionnallity
+
+class v_fes; 
+class v_fes3; 
+typedef v_fes *pfes;
+typedef v_fes3 *pfes3;
+
+namespace  Fem2D {
+  class Mesh3;
+
+}
+using Fem2D::Mesh;
+using Fem2D::Mesh3;
+
+typedef Mesh * pmesh;
+typedef Mesh3 * pmesh3;
+
+using  Fem2D::FESpace;
+using  Fem2D::TypeOfFE;
+using  Fem2D::R;
+//  typedef double R;
+namespace {
+  using namespace Fem2D;
+  using  Fem2D::Vertex;
+  
+  class lgVertex {
+  public:
+    typedef double R;
+    CountPointer<Mesh> pTh;
+    Vertex *v;
+    void Check() const {   if (!v || !pTh) { ExecError("Too bad! Unset Vertex!"); } }
+    void init() { v=0;pTh.init();}
+    lgVertex(Mesh * Th,long kk): pTh(Th),v( &(*pTh)(kk)) {}
+    lgVertex(Mesh * Th,Vertex * kk): pTh(Th),v(kk) {}
+    operator int() const { Check(); return (* pTh)(v);} 
+    operator R2*(){ Check(); return v;} 
+    R x() const {Check() ; return v->x;}
+    R y() const {Check() ; return v->y;}
+    //  R z() const {Check() ; return v->z;}
+    long lab() const {Check() ; return v->lab;}
+    void destroy()  {pTh.destroy();}
+  };
+  
+  class lgElement { public:
+   struct Adj {// 
+	  Mesh *pTh;
+          Triangle *k;
+	  Adj(const lgElement & pp) : pTh(pp.pTh),k(pp.k) {}
+       lgElement adj(long & e) const  {
+         int ee;
+	   ffassert(pTh && k && e >=0 && e < 3 );
+         long kk=pTh->ElementAdj((*pTh)(k),ee=e); 
+         e=ee;
+	return  lgElement(pTh,kk);}
+      }; 
+  CountPointer<Mesh> pTh; 
+  Triangle *k;
+
+  lgElement():  k(0) {}
+  void  Check() const  {   if (!k || !pTh) { ExecError("Unset Triangle,Sorry!"); } }
+  void init() { k=0;pTh.init();}
+  void destroy() {pTh.destroy();}
+  lgElement(Mesh * Th,long kk): pTh(Th),k( &(*Th)[kk]) {}
+  lgElement(Mesh * Th,Triangle * kk): pTh(Th),k(kk) {}
+  operator int() const { Check(); return (* pTh)(k);} 
+  lgVertex operator [](const long & i) const { Check(); return lgVertex(pTh,&(*k)[i]);}   
+  long lab() const {Check() ; return k ? k->lab : 0;}
+  double area() const {Check() ; return k->area ;}
+  long n() const { return k ? 3: 0 ;}
+  bool operator==(const lgElement & l) const { return pTh==l.pTh && k == l.k;}
+  bool operator!=(const lgElement & l) const { return pTh!=l.pTh || k != l.k;}
+  bool operator<(const lgElement & l) const { return pTh==l.pTh && k <l.k;}
+  bool operator<=(const lgElement & l) const { return pTh==l.pTh && k <=l.k;}
+      
+
+};
+    // add FH  August 2009 ...   
+
+class lgBoundaryEdge { public:
+    struct BE {
+	Mesh * p;
+	BE(Mesh *pp) : p(pp) {}
+	BE(Mesh **pp) : p(*pp) {}
+	 operator Mesh * () const {return p;}
+    };
+    
+	CountPointer<Mesh> pTh;
+	BoundaryEdge *k;
+	
+	lgBoundaryEdge():  k(0) {}
+	void  Check() const  {   if (!k || !pTh) { ExecError("Unset BoundaryEdge,Sorry!"); } }
+	void init() { k=0;pTh.init();}
+	void destroy() {pTh.destroy();}
+	lgBoundaryEdge(Mesh * Th,long kk): pTh(Th),k( &(*pTh).be(kk)) {}
+	lgBoundaryEdge(Mesh * Th,BoundaryEdge * kk): pTh(Th),k(kk) {}
+        lgBoundaryEdge(const BE & be,long kk): pTh(be.p),k( &(*pTh).be(kk)) {}
+        lgBoundaryEdge(const BE & be,BoundaryEdge * kk): pTh(be.p),k(kk) {}
+	operator int() const { Check(); return (* pTh)(k);} 
+	lgVertex operator [](const long & i) const { Check(); return lgVertex(pTh,&(*k)[i]);}   
+	long lab() const {Check() ; return k ? k->lab : 0;}
+	double length() const {Check() ; return k->length()  ;}
+	long n() const { return k ? 2: 0 ;}
+       lgElement Element() const {Check() ;int ee; return lgElement(pTh,(*pTh).BoundaryElement((*pTh)(k),ee));}
+       long EdgeElement() const {Check() ;int ee;  (*pTh).BoundaryElement((*pTh)(k),ee);return ee;}
+
+    };
+    
+    
+
+ } // end namespace blanc
+
+void GetPeriodic(const int d,Expression perio,    int & nbcperiodic ,    Expression * &periodic);
+
+bool BuildPeriodic( 
+  int nbcperiodic,
+  Expression *periodic,
+  const Mesh &Th,Stack stack,
+  int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe);
+
+  
+class v_fes : public RefCounter { 
+public:
+  typedef ::pfes pfes;
+  typedef ::FESpace FESpace;
+  
+  static const int d=2;
+  const int N;
+  const pmesh* ppTh; // adr du maillage
+  CountPointer<FESpace>  pVh;
+  Stack stack; // the stack is use whith periodique expression
+  
+  int nbcperiodic;
+  Expression *periodic;
+  
+  
+  operator FESpace * ()  { 
+    throwassert(this && d==2);
+    if  ( !pVh || *ppTh !=  &pVh->Th )
+      pVh=CountPointer<FESpace>(update(),true);
+    return  pVh   ;} 
+  
+  FESpace * update() ;
+
+  v_fes(int NN,const pmesh* t,Stack s, int n,Expression *p)
+    : N(NN), ppTh(t),pVh(0),stack(s), nbcperiodic(n),periodic(p) {}
+  v_fes(int NN,const v_fes *f,Stack s,int n,Expression *p) 
+    :  N(NN),ppTh(f->ppTh),pVh(0),stack(s), nbcperiodic(n),periodic(p)
+    {}
+
+  void destroy(){ ppTh=0;pVh=0; delete this;}
+  virtual ~v_fes() {}
+  bool buildperiodic(Stack stack,int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe)  ;
+  virtual  FESpace * buildupdate(int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe) =0;
+  virtual  FESpace * buildupdate() =0;
+  
+};  
+
+  
+class v_fes3 : public RefCounter { public:
+    typedef pfes3 pfes;
+  typedef FESpace3 FESpace;
+
+  static const int d=3;
+  const int N;
+  const pmesh3* ppTh; // adr du maillage
+  CountPointer<FESpace3> pVh;
+  
+  Stack stack; // the stack is use whith periodique expression
+  
+  int nbcperiodic;
+  Expression *periodic;
+  
+  
+  operator FESpace3 * ()  { 
+    throwassert(this && d==3);
+    if  ( !pVh || *ppTh !=  &pVh->Th )
+      pVh=CountPointer<FESpace3>(update(),true);
+    return  pVh   ;} 
+  FESpace3 * update() ;
+  
+  v_fes3(int NN,const pmesh3* t,Stack s, int n,Expression *p)
+    : N(NN), ppTh(t),pVh(0),stack(s), nbcperiodic(n),periodic(p) {}
+  v_fes3(int NN,const v_fes3 *f,Stack s,int n,Expression *p) 
+    :  N(NN),ppTh(f->ppTh),pVh(0),stack(s), nbcperiodic(n),periodic(p)
+  {}
+  
+  void destroy(){ ppTh=0;pVh=0; delete this;}
+  virtual ~v_fes3() {}
+  bool buildperiodic(Stack stack, KN<int> & ndfe)  ;
+  virtual  FESpace3 * buildupdate( KN<int> & ndfe) {  return 0;}
+  virtual  FESpace3 * buildupdate() {return 0;};
+  
+};  
+  
+
+class pfes_tef : public v_fes { public:
+    
+    const TypeOfFE * tef ;  
+  pfes_tef(const pmesh* t,const TypeOfFE * tt,Stack s=NullStack, int n=0,Expression *p=0 ) 
+    : v_fes(tt->N,t,s,n,p),tef(tt) { operator FESpace * ();} 
+  FESpace * buildupdate(int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe) 
+    { return  *ppTh ? new FESpace(**ppTh,*tef,nbdfv,(int *) ndfv,nbdfe,(int*)ndfe): 0;}
+    FESpace * buildupdate()   {  return *ppTh ? new FESpace(**ppTh,*tef):0 ;}
+  
+};
+
+class pfes_tefk : public v_fes { public:
+    
+    const TypeOfFE ** tef ;
+  const int k;  
+  pfes_tefk(const pmesh* t,const TypeOfFE ** tt,int kk,Stack s=NullStack,int n=0,Expression *p=0 ) 
+    : v_fes(sum(tt,&Fem2D::TypeOfFE::N,kk),t,s,n,p),tef(tt),k(kk)  { 
+    // cout << "pfes_tefk const" << tef << " " << this << endl; 
+    operator FESpace * ();} 
+  FESpace * buildupdate() { 
+    // cout << "pfes_tefk upd:" << tef << " " << this <<  endl; 
+    assert(tef);
+      return  *ppTh? new FESpace(**ppTh,tef,k):0;}
+  virtual ~pfes_tefk() { delete [] tef;}
+  FESpace * buildupdate(int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe) 
+  {
+    assert(tef);
+    return  *ppTh? new FESpace(**ppTh,tef,k,nbdfv,ndfv,nbdfe,ndfe):0 ;}
+  
+  
+}; 
+
+class pfes3_tef : public v_fes3 { public:
+    
+    const TypeOfFE3 * tef ;  
+  pfes3_tef(const pmesh3* t,const TypeOfFE3 * tt,Stack s=NullStack, int n=0,Expression *p=0 ) 
+    : v_fes3(tt->N,t,s,n,p),tef(tt) { operator FESpace3 * ();} 
+    FESpace3 * buildupdate( KN<int> & ndfe)   { return  *ppTh ? new FESpace3(**ppTh,*tef,ndfe.size()/2,ndfe):0;   }
+    FESpace3 * buildupdate()   {  return  *ppTh? new FESpace3(**ppTh,*tef):0;}
+  
+};
+
+
+class pfes3_tefk : public v_fes3 { 
+public:
+  
+  const TypeOfFE3 ** tef ;
+  const int k;  
+  KN< GTypeOfFE<Mesh3> const *> atef;
+  GTypeOfFESum<Mesh3> tefs;
+  
+   static int sum(const Fem2D::TypeOfFE3 ** l,int const Fem2D::TypeOfFE3::*p,int n)
+    {
+        int r=0;
+        for (int i=0;i<n;i++)
+            r += l[i]->*p;
+        return r;
+    }
+    
+  pfes3_tefk(const pmesh3* t,const Fem2D::TypeOfFE3 ** tt,int kk,Stack s=NullStack,int n=0,Expression *p=0 ) 
+    : v_fes3(sum((const Fem2D::TypeOfFE3 **)tt,&Fem2D::TypeOfFE3::N,kk),t,s,n,p),
+      tef(tt),k(kk),
+      atef(kk,tt),tefs(atef)
+      
+  { 
+    // cout << "pfes_tefk const" << tef << " " << this << endl; 
+    operator FESpace3 * ();
+  } 
+  FESpace3 * buildupdate() { 
+    // cout << "pfes_tefk upd:" << tef << " " << this <<  endl; 
+    //assert(tef);
+      return  *ppTh? new FESpace3(**ppTh,tefs):0;}
+  virtual ~pfes3_tefk() { delete [] tef;}
+  FESpace3 * buildupdate(KN<int> & ndfe) 
+  {
+      return  *ppTh? new FESpace3(**ppTh,tefs,ndfe.size()/2,ndfe):0;
+  }
+    
+}; 
+ 
+class pfes_fes : public v_fes {
+public:
+  
+  pfes * Vh;
+  int n;
+  pfes_fes( pfes * Vhh, int nn,Stack s=NullStack,int n=0,Expression *p=0) 
+    :v_fes((**Vhh).N*nn,static_cast<const v_fes *>(*Vhh),s,n,p),
+     Vh(Vhh),n(nn)  
+  { operator FESpace * () ;}; 
+  FESpace * buildupdate() {  return  new FESpace(*(FESpace *)**Vh,n);  }
+  FESpace * buildupdate(int & nbdfv, KN<int> & ndfv,int & nbdfe, KN<int> & ndfe) 
+  {
+    InternalError(" No way to define a periodic BC in this case: tensorisation of FEspace ");
+    //  return  new FESpace(***Vh,n,nbdfv,ndfv,nbdfe,ndfe);
+  }
+};
+ 
+template<class K,class v_fes> class FEbase;
+template<class K,class v_fes> 
+class FEcomp {
+public:
+  typedef typename v_fes::pfes pfes;
+  typedef typename v_fes::FESpace FESpace;
+  
+  friend class FEbase<K,v_fes>;
+  FEbase<K,v_fes> * base;
+  int comp;
+  FEcomp(FEbase<K,v_fes> * b,int c) :base(b),comp(c) {};
+private: // rule of programming 
+  FEcomp(const FEcomp &);
+  void operator= (const FEcomp &); 
+};
+
+template<class K,class v_fes>
+class FEbase { 
+public:
+  typedef typename v_fes::pfes pfes;
+  typedef typename v_fes::FESpace FESpace;
+  
+  v_fes *const*pVh; // pointeur sur la variable stockant FESpace;
+  KN<K> * xx; // value
+  CountPointer<FESpace> Vh; // espace courant 
+  
+  KN<K> *x() {return xx;}
+  
+  FEbase(const pfes  *ppVh) :pVh(ppVh), xx(0),Vh(0) {}
+  
+  ~FEbase() { delete xx;}  
+  void destroy() { // cout << "~FEbase  destroy " << this << endl; 
+    delete this;}
+  
+  void operator=( KN<K> *y) { 
+    Vh=**pVh; 
+    throwassert((bool) Vh);
+    if (xx) delete xx;xx=y;
+    ffassert( y->N() == Vh->NbOfDF);
+  }
+    
+    void operator=(KN_<K> & y) { 
+	Vh=**pVh; 
+	throwassert((bool) Vh);
+	if (xx) 
+	  { // resize if need
+	  if(xx->N() != Vh->NbOfDF)
+	       delete xx;xx=0;
+	  }
+	if(!xx) xx= new KN<K>(Vh->NbOfDF) ; 
+	ffassert(SameShape(y,*xx));
+	*xx=y;
+    }
+    
+  FESpace * newVh() { 
+    throwassert(pVh  );
+    const pfes pp= *pVh;
+    // cout << pVh << " " << *pVh << endl;
+    return *pp;
+  }  
+  
+  operator  FESpace &() { throwassert(Vh); return *Vh;}
+
+private: // rule of programming 
+  FEbase(const FEbase &);
+  void operator= (const FEbase &); 
+};
+
+template<class K>
+class FEbaseArrayKn { public:// for eigen value 
+    int N;
+    FEbaseArrayKn(int NN):N(NN){}
+  virtual  void  set(int i,KN_<K> ) =0;
+virtual KN<K>* get (int i) const = 0; // for P. Jolivet 
+virtual void resize(int i) = 0; // for P. Jolivet 
+};
+
+template<class K,class v_fes>
+class FEbaseArray :public FEbaseArrayKn<K> {
+public:
+  typedef typename v_fes::pfes pfes;
+  typedef typename v_fes::FESpace FESpace;
+  
+ // int N;
+  FEbase<K,v_fes>  **xx;
+  FEbaseArray(const pfes  *ppVh,int NN) :FEbaseArrayKn<K>(NN),xx(new FEbase<K,v_fes> * [std::max(NN, 1)])
+  {
+    for (int i=0;i<std::max(this->N, 1);i++)
+      xx[i]=new FEbase<K,v_fes>(ppVh);
+  }
+  ~FEbaseArray() { 
+    //  cout << " ~FEbaseArray " << endl;
+    for (int i=0;i<std::max(this->N, 1);i++)
+      xx[i]->destroy();
+    delete [] xx;} 
+  void destroy() { //cout << " destroy ~FEbaseArray " << endl; 
+    delete this;}         
+  FEbase<K,v_fes>** operator[](int i) const  {
+    if(xx==0 || i <0 || i>=this->N) 
+      ExecError("Out of bound in FEbaseArray");
+    return xx+i;}  
+    
+    void resize(int i) {
+        if(xx != 0 && i > 0 && i != this->N) {
+            FEbase<K,v_fes>** yy = new FEbase<K,v_fes>*[i];
+            if(i > this->N) {
+                for(unsigned int j = 0; j < std::max(this->N, 1); ++j)
+                    yy[j] = xx[j];
+                for(unsigned int j = std::max(this->N, 1); j < i; ++j)
+                    yy[j] = new FEbase<K,v_fes>(xx[0]->pVh);
+            }
+            else {
+                for(unsigned int j = 0; j < i; ++j)
+                    yy[j] = xx[j];
+                for(unsigned int j = i; j < this->N; ++j)
+                    xx[j]->destroy();
+            }
+             FEbase<K,v_fes>  **oldXx = this->xx;
+             this->xx = yy;
+             delete [] oldXx;
+             this->N = i;
+        }
+    }
+
+    void  set(int i,KN_<K>  v){  **(operator[](i))=v;} 
+    
+    KN<K>* get(int i)const { return (**(operator[](i))).xx; }
+    
+private: // rule of programming 
+  FEbaseArray(const FEbaseArray &);
+  void operator= (const FEbaseArray &); 
+};
+
+void GetPeriodic(const int d,Expression perio,    int & nbcperiodic ,    Expression * &periodic);
+int GetPeriodic(Expression  bb, Expression & b,Expression & f);
+int GetPeriodic(Expression  bb, Expression & b,Expression & f1,Expression & f2);
+
+
+C_F0 NewFEarray(const char * id,Block *currentblock,C_F0 & fespacetype,CC_F0 init,bool cplx,int dim);
+C_F0 NewFEarray(ListOfId * ids,Block *currentblock,C_F0 & fespacetype,CC_F0 init,bool cplx,int dim);
+C_F0 NewFEvariable(const char * id,Block *currentblock,C_F0 & fespacetype,CC_F0 init,bool cplx,int dim);
+C_F0 NewFEvariable(ListOfId * ids,Block *currentblock,C_F0 & fespacetype,CC_F0 init,bool cplx,int dim);
+inline C_F0 NewFEvariable(const char * id,Block *currentblock,C_F0 & fespacetype,bool cplx,int dim)
+{ CC_F0 init;init=0;return NewFEvariable( id,currentblock,fespacetype, init, cplx,dim);}
+    
+inline C_F0 NewFEvariable(ListOfId * ids,Block *currentblock,C_F0 & fespacetype,bool cplx,int dim)
+{ CC_F0 init;init=0;return NewFEvariable( ids,currentblock,fespacetype, init,cplx,dim);}
+ 
+size_t dimFESpaceImage(const basicAC_F0 &args) ;
+aType  typeFESpace(const basicAC_F0 &args) ;
+
+template<class K,class vv_fes,class FE=FEbase<K,vv_fes> >
+class E_FEcomp : public E_F0mps { 
+public:
+  //  typedef FEbase<K,vv_fes> FE;
+  typedef vv_fes v_fes;
+  typedef pair< FE * ,int> Result;
+  Expression a0;
+  const int comp, N;
+
+  AnyType operator()(Stack s)  const {
+    return SetAny<Result>( Result( *GetAny<FE **>((*a0)(s)),comp) );}  
+  E_FEcomp(const C_F0 & x,const int cc,int NN) : a0(x.LeftValue()),comp(cc),N(NN)
+      {if(x.left()!=atype<FE **>() ) 
+        cout << "E_FEcomp: Bug " << *x.left() << " != " << *atype<FE **>() << "  case " <<typeid(K).name() << endl;
+        //CompileError("E_FEcomp: Bug ?");
+       throwassert(x.left()==atype<FE **>() &&a0);} 
+    operator aType () const { return atype<Result>();}         
+         
+};
+
+//typedef double R;
+typedef  pair< FEbase<double,v_fes> * ,int> aFEvarR;   
+typedef  pair< FEbaseArray<double,v_fes> * ,int> aFEArrayR;   
+typedef  pair< FEbase<Complex,v_fes> * ,int> aFEvarC;   
+
+template<class K>
+class interpolate_f_X_1 : public OneOperator  { public:
+ //  to interpolate f o X^{-1} 
+    typedef FEbase<K,v_fes> * pferbase ;
+typedef FEbaseArray<K,v_fes> * pferbasearray ;
+typedef pair<pferbase,int> pfer ;
+typedef pair<pferbasearray,int> pferarray ;
+  class type {};
+  class CODE : public E_F0mps { public:
+    Expression f;
+    Expression x,y;
+
+    CODE(const basicAC_F0 & args) : f(args[0].LeftValue())  
+      { const E_Array * X(dynamic_cast<const E_Array*>(args[1].LeftValue()));
+        if ( ! X || X->size() != 2) 
+           {
+             CompileError("array of 2 double x,y   f([xx,yy]) = ... ");
+           }
+        x=to<double>((*X)[0]);
+        y=to<double>((*X)[1]);
+        assert(f && x && y ); 
+      }
+    AnyType operator()(Stack)  const  { ExecError("No evaluation"); return Nothing;} 
+          operator aType () const { return atype<void>();}         
+
+   }; //  end class CODE 
+   
+   E_F0 * code(const basicAC_F0 & args) const  
+     { return  new CODE(args);}
+     
+   interpolate_f_X_1(): 
+      OneOperator(map_type[typeid(type).name()],map_type[typeid(pfer).name()],map_type[typeid(E_Array).name()])
+      {}
+};
+
+inline FESpace * v_fes::update() {     
+    assert(d==2);
+    if(!*ppTh) return 0; 
+    if (nbcperiodic ) {
+       assert(periodic);
+       const Mesh &Th(**ppTh);
+       KN<int> ndfv(Th.nv);
+       KN<int> ndfe(Th.neb);
+       int nbdfv,nbdfe;    
+       buildperiodic(stack,nbdfv,ndfv,nbdfe,ndfe);
+       return   buildupdate(nbdfv,ndfv,nbdfe,ndfe);
+      }
+     else 
+       return  buildupdate();
+}
+
+
+inline FESpace3 * v_fes3::update() {     
+  assert(d==3);
+  if(!*ppTh) return 0;
+  if (nbcperiodic ) {
+    assert(periodic);
+    //const Mesh3 &Th(**ppTh);
+   //    KN<int> ndfv(Th.nv);
+       KN<int> ndfe;
+     //  int nbdfv,nbdfe;    
+	  buildperiodic(stack,ndfe);
+       return   buildupdate(ndfe);
+      }
+     else 
+       return  buildupdate();
+}
+
+template<class A,class B>  A Build(B b) {  return A(b);}
+
+
+class TabFuncArg { public:
+  typedef double R;  
+  typedef  Fem2D::R2 R2;
+  Stack s;
+  int nb;
+  Expression * e;
+  void  eval(R *v) const 
+  { for (int i=0;i<nb;i++)
+    if (e[i])
+      { 
+        v[i] = GetAny<R>( (*e[i])(s));
+        //    cout <<" (" << i << " " << *v << ") ";
+      }
+    else 
+      v[i] = 0;
+  }
+  R2 eval_X() const {
+    return R2(GetAny<R>( (*e[nb-2])(s)),GetAny<R>( (*e[nb-1])(s)));
+  }
+  void  eval_2(R *v) const 
+  { 
+    for (int i=0;i<nb-2;i++)
+      if (e[i])
+        v[i] = GetAny<R>( (*e[i])(s));
+      else 
+        v[i] = 0;
+  }
+  TabFuncArg(Stack ss,int n) : s(ss),nb(n),e(new Expression[n]) {}
+  void operator=(int j) { ffassert(j==0); for (int i=0;i<nb;i++) e[i]=0;} // resert
+  Expression  & operator[](int i){return e[i];}
+  ~TabFuncArg() {delete [] e;}
+private: // no copy 
+  TabFuncArg(const TabFuncArg & );
+  void operator=(const TabFuncArg & );  
+};
+
+
+template<class K> 
+ class E_F_StackF0F0opt2 :public  E_F0mps { public:
+  typedef   AnyType (*func)(Stack,Expression ,Expression ) ; 
+  func f;
+  Expression a0,a1;
+  E_F_StackF0F0opt2(func ff,Expression aa0,Expression aa1) 
+    : f(ff),a0(aa0),a1(aa1) {
+    
+    const E_FEcomp<K,v_fes> * e= dynamic_cast<const E_FEcomp<K,v_fes>*>(a0);
+     if ( e  && e->N != 1)
+      { 
+        cerr << " err interpolation of  no scalar FE function componant ("<<  e->comp<< " in  0.." << e->N<< ") <<  with scalar function \n" ;
+        CompileError("interpolation of  no scalar FE function componant with scalar function ");
+      } 
+       
+/*  //  inutil car a0 est un composante d'un vecteur ???? 
+   // pour l'instant on a juste une erreur a l'execution
+   // et non a la compilation.
+   
+     if (a0->nbitem() != a1->nbitem() ) 
+      { // bofbof 
+        cerr << " err interpolation of  no scalar FE function ("<<  a0->nbitem() << " != "  <<  a1->nbitem()  << ") <<  with scalar function \n" ;
+        CompileError("interpolation of  no scalar FE function  with scalar function ");
+      } */
+     deque<pair<Expression,int> > ll;
+     MapOfE_F0 m;
+     size_t top =  currentblock->OffSet(0), topbb=top; // FH. bofbof ??? 
+     int ret =aa1->Optimize(ll, m, top);
+     a1 =   new E_F0_Optimize(ll,m,ret); 
+    currentblock->OffSet(top-topbb);
+  }
+  AnyType operator()(Stack s)  const 
+    {return  (*f)(s, a0 , a1) ;}  
+
+};
+
+template<class R>
+inline  ostream & ShowBound(const KN<R> & y,ostream & f)
+ {
+  f << "  -- vector function's bound  " << y.min() << " " << y.max() ;
+  return f;
+ }
+template<>
+inline   ostream & ShowBound<Complex>(const KN<Complex> & y,ostream & f)
+ {
+  f << "  -- vector function's bound : (no complex Value) " ;
+  return f;
+ }
+
+template<class K>
+class Op3_K2R : public ternary_function<K,R,R,K> { public:
+
+  class Op : public E_F0mps { public:
+      Expression a,b,c;
+    Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc) {}       
+       AnyType operator()(Stack s)  const 
+        { 
+           R xx(GetAny<R>((*b)(s)));
+           R yy(GetAny<R>((*c)(s)));
+           MeshPoint & mp = *MeshPointStack(s),mps=mp;
+           mp.set(xx,yy,0.0);
+           AnyType ret = (*a)(s);
+           mp=mps;
+           return  ret;}
+   
+  };
+};
+template<class K>
+class Op4_K2R : public quad_function<K,R,R,R,K> { public:
+    
+    class Op : public E_F0mps { public:
+	Expression a,b,c,d;
+      Op(Expression aa,Expression bb,Expression cc,Expression dd) 
+	: a(aa),b(bb),c(cc),d(dd) {}       
+      AnyType operator()(Stack s)  const 
+      { 
+	//cout <<"class Op4_K2R : public quad_function<K,R,R,R,K>" << endl;
+	R xx(GetAny<R>((*b)(s)));
+	R yy(GetAny<R>((*c)(s)));
+	R zz(GetAny<R>((*d)(s)));
+	MeshPoint & mp = *MeshPointStack(s),mps=mp;
+	mp.set(xx,yy,zz);
+	AnyType ret = (*a)(s);
+	mp=mps;
+	return  ret;}
+      
+    };
+};
+
+template<class K,class  v_fes>
+class E_set_fev3: public E_F0mps {
+public:
+  typedef typename  v_fes::pfes pfes;
+  typedef typename  v_fes::FESpace FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::FElement FElement;
+  typedef typename  Mesh::Element Element;
+  typedef typename  Mesh::Vertex Vertex;  
+  typedef typename  Mesh::RdHat RdHat;  
+  typedef typename  Mesh::Rd Rd;  
+
+
+  E_Array  aa;
+  Expression   ppfe;
+  bool optimize;
+  vector<size_t>  where_in_stack_opt;
+  Expression optiexp0,optiexpK;
+
+  E_set_fev3(const E_Array * a,Expression pp) ;
+  
+  AnyType operator()(Stack)  const ;
+  operator aType () const { return atype<void>();} 
+             
+};
+
+template<class K>
+class E_set_fev: public E_F0mps {public:
+    const int dim;
+  E_Array  aa;
+  Expression   ppfe;
+  bool optimize;
+  vector<size_t>  where_in_stack_opt;
+  Expression optiexp0,optiexpK;
+  
+  E_set_fev(const E_Array * a,Expression pp,int ddim=2) ;
+  
+  AnyType operator()(Stack)  const ;
+   AnyType Op2d(Stack)  const ;
+  AnyType Op3d(Stack)  const ;
+  
+  operator aType () const { return atype<void>();} 
+  
+};
+
+bool  InCircularList(const int *p,int i,int k);
+template<class T> int numeroteclink(KN_<T> & ndfv) ;
+
+//  for ...   vectorial FE array ..
+
+template<class K,class v_fes>
+class E_FEcomp_get_elmnt_array :public  E_F0 { public:
+    typedef FEbaseArray<K,v_fes> * pfekbasearray ;
+    typedef FEbase<K,v_fes> * pfekbase ;
+    typedef pair<pfekbase,int> pfek ;
+    typedef pair<pfekbasearray,int> pfekarray ;
+    typedef pfek  R;
+    typedef pfekarray A;
+    typedef long B;
+    typedef FEbaseArray<K,v_fes>  CFE;
+    typedef  E_FEcomp<K,v_fes,CFE > E_KFEArray;
+    
+    Expression a0,a1;
+    const  E_KFEArray * a00;
+    const int comp, N;        
+    
+    E_FEcomp_get_elmnt_array(Expression aa0,Expression aa1,int compp,int NN,const E_KFEArray * aa00) 
+    : a0(aa0),a1(aa1),a00(aa00),comp(compp),N(NN) {}
+    AnyType operator()(Stack s)  const 
+    {return SetAny<R>( get_element( GetAny<A>((*a0)(s)) , GetAny<B>((*a1)(s)) ) );} 
+    bool MeshIndependent() const {return a0->MeshIndependent() && a1->MeshIndependent();} // 
+    
+};
+
+template<class K,class v_fes>
+class  OneOperator2_FE_get_elmnt : public OneOperator {
+    // ///  Add<pferbasearray*>("[","",new OneOperator2_FEcomp<pferbase*,pferbasearray*,long>(get_element)); // not used ...
+    //    Add<pferarray>("[","",new OneOperator2_<pfer,pferarray,long>(get_element));
+    typedef FEbase<K,v_fes> * pfekbase ;
+    typedef FEbaseArray<K,v_fes> * pfekbasearray ;
+    typedef pair<pfekbase,int> pfek ;
+    typedef pair<pfekbasearray,int> pfekarray ;
+    
+    
+    
+    typedef pfek  R;
+    typedef pfekarray A;
+    typedef long B;
+    typedef E_FEcomp_get_elmnt_array<K,v_fes>  CODE;
+    typedef FEbaseArray<K,v_fes>  CFE;
+    typedef  E_FEcomp<K,v_fes,CFE > E_KFEArray;
+    typedef  E_FEcomp<K,v_fes > E_KFEi;
+    
+    
+    
+    
+    
+    aType t0,t1; //  return type  type de f,  f(t1, t2) 
+public: 
+    E_F0 * code(const basicAC_F0 & args) const 
+    { 
+	const E_KFEArray * afe=dynamic_cast<const E_KFEArray *> (args[0].LeftValue());
+	//  cout << " build xxx  " << afe <<  " " << *args[0].left() <<  endl;
+	//afe=0;// E_KFEi n'est pas le bon type on mame le vieux code ?????
+	ffassert(afe);
+	return new   CODE(t0->CastTo(args[0]),t1->CastTo(args[1]),afe->comp,afe->N,afe);
+    } 
+    OneOperator2_FE_get_elmnt(): 
+    OneOperator(map_type[typeid(R).name()],map_type[typeid(A).name()],map_type[typeid(B).name()]),
+    t0( map_type[typeid(A).name()] ),t1(map_type[typeid(B).name()] ){}
+};
+
+    
diff --git a/src/fflib/lgmat.cpp b/src/fflib/lgmat.cpp
new file mode 100644
index 0000000..1d73bdc
--- /dev/null
+++ b/src/fflib/lgmat.cpp
@@ -0,0 +1,3024 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifdef __MWERKS__
+#pragma optimization_level 0
+//#pragma inline_depth(0) 
+#endif
+/*
+#include "error.hpp"
+#include "RNM.hpp"
+#include <set>
+#include <vector>
+#include <cstdio>
+#include <cstring>
+#include <complex>
+
+#include  <cmath>
+#include  <iostream>
+using namespace std;
+#include "FESpacen.hpp"
+
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+//#include "fem3.hpp"
+#include "MeshPoint.hpp"
+#include "Operator.hpp" 
+
+#include "lex.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+*/
+#include "ff++.hpp" 
+#include "array_resize.hpp" 
+
+#include "CGNL.hpp"
+
+namespace bamg { class Triangles; }
+namespace Fem2D { void DrawIsoT(const R2 Pt[3],const R ff[3],const RN_ & Viso); }
+
+extern const basicForEachType *aatypeknlongp; //// for  compilation error with g++ 3.2.2
+#include "BamgFreeFem.hpp"
+
+
+
+// Debut FH Houston -------- avril 2004 ---------
+//  class for operator on sparse matrix 
+//   ------------------------------------
+//  pour le addition de matrice ----matrice creuse in french)
+//  MatriceCreuse    real class for matrix sparse
+//  Matrice_Creuse   class for matrix sparse +  poiteur on FE space def 
+//         to recompute matrice in case of mesh change
+//  list<triplet<R,MatriceCreuse<R> *,bool> > * is liste of 
+//  \sum_i a_i*A_i  where a_i is a scalare and A_i is a sparse matrix
+//
+ 
+
+
+template<class R> 
+list<triplet<R,MatriceCreuse<R> *, bool > > * to(Matrice_Creuse<R> * M)
+{
+  list<triplet<R,MatriceCreuse<R> *,bool> >  * l=new list<triplet<R,MatriceCreuse<R> *,bool> >;
+   l ->push_back(make_triplet<R,MatriceCreuse<R> *,bool>(1,M->A,false));
+  return  l;
+}
+template<class R> 
+list<triplet<R,MatriceCreuse<R> *, bool > > * to(Matrice_Creuse_Transpose<R>  M)
+{
+  list<triplet<R,MatriceCreuse<R> *,bool> >  * l=new list<triplet<R,MatriceCreuse<R> *,bool> >;
+   l ->push_back(make_triplet<R,MatriceCreuse<R> *,bool>(1,M.A->A,true));
+  return  l;
+}
+
+template<class R>
+AnyType M2L3 (Stack , const AnyType & pp)
+{
+    return to(GetAny<Matrice_Creuse<R> *>(pp));
+}
+
+
+template<class R>
+AnyType tM2L3 (Stack , const AnyType & pp)
+{
+    return to(GetAny<Matrice_Creuse_Transpose<R> >(pp));
+}
+
+
+template<class R> 
+struct Op2_ListCM: public binary_function<R,Matrice_Creuse<R> *,list<triplet<R,MatriceCreuse<R> *,bool> > *> 
+ { 
+   typedef triplet<R,MatriceCreuse<R> *,bool>  P;
+   typedef list<P> L;
+   typedef L * RR;
+   typedef R  AA;
+   typedef Matrice_Creuse<R> * BB;
+   
+ static  RR f(const   AA & a,const   BB & b)  
+  {
+    RR r=  new list<P> ;
+    r ->push_back(make_triplet<R,MatriceCreuse<R> *>(a,b->A,false));
+    return r;}
+};
+
+template<class R> 
+struct Op2_ListMC: public binary_function<Matrice_Creuse<R> *,R,list<triplet<R,MatriceCreuse<R> *,bool> > *> 
+ { 
+   typedef triplet<R,MatriceCreuse<R> *,bool>  P;
+   typedef list<P> L;
+   typedef L * RR;
+   typedef R  AA;
+   typedef Matrice_Creuse<R> * BB;
+   
+ static  RR f(const   BB & b,const   AA & a)  
+  {
+    RR r=  new list<P> ;
+    r ->push_back(make_triplet<R,MatriceCreuse<R> *>(a,b->A,false));
+    return r;}
+};
+//  ADD FH 16/02/2007
+
+template<class R> 
+struct Op2_ListCMt: public binary_function<R,Matrice_Creuse_Transpose<R> ,list<triplet<R,MatriceCreuse<R> *,bool> > *> 
+{ 
+    typedef triplet<R,MatriceCreuse<R> *,bool>  P;
+    typedef list<P> L;
+    typedef L * RR;
+    typedef R  AA;
+    typedef Matrice_Creuse_Transpose<R>  BB;
+    
+    static  RR f(const   AA & a,const   BB & b)  
+    {
+	RR r=  new list<P> ;
+	r ->push_back(make_triplet<R,MatriceCreuse<R> *>(a,b.A->A,true));
+	return r;}
+};
+
+template<class R> 
+struct Op2_ListMtC: public binary_function<Matrice_Creuse_Transpose<R> ,R,list<triplet<R,MatriceCreuse<R> *,bool> > *> 
+{ 
+    typedef triplet<R,MatriceCreuse<R> *,bool>  P;
+    typedef list<P> L;
+    typedef L * RR;
+    typedef R  AA;
+    typedef Matrice_Creuse_Transpose<R> BB;
+    
+    static  RR f(const   BB & b,const   AA & a)  
+    {
+	RR r=  new list<P> ;
+	r ->push_back(make_triplet<R,MatriceCreuse<R> *>(a,b.A->A,true));
+	return r;}
+};
+// FIN ADD 16/02/2007
+
+
+
+template<class R> 
+struct Op1_LCMd: public unary_function<list<triplet<R,MatriceCreuse<R> *,bool> > *,
+list<triplet<R,MatriceCreuse<R> *,bool> > *  >
+{  //  - ...
+    typedef triplet<R,MatriceCreuse<R> *,bool>  P;
+    typedef list<P> L;
+    typedef L * RR;
+    
+    static   RR f(const RR & l)  
+    { 
+	typedef typename list<triplet<R,MatriceCreuse<R> *,bool> >::iterator lci;
+	for (lci i= l->begin();i !=l->end();++i)
+	    i->first *= R(-1);
+	return l;
+    }    
+    
+};
+
+template<class R> 
+struct Op2_ListCMCMadd: public binary_function<list<triplet<R,MatriceCreuse<R> *,bool> > *,
+                                               list<triplet<R,MatriceCreuse<R> *,bool> > *,
+                                               list<triplet<R,MatriceCreuse<R> *,bool> > *  >
+{  //  ... + ...
+   typedef triplet<R,MatriceCreuse<R> *,bool>  P;
+   typedef list<P> L;
+   typedef L * RR;
+
+  static   RR f(const RR & a,const RR & b)  
+  { 
+    a->insert(a->end(),b->begin(),b->end());
+      
+    delete b;
+    return a;
+  }    
+    
+};
+
+template<class R> 
+struct Op2_ListMCMadd: public binary_function<Matrice_Creuse<R> *,
+                                              list<triplet<R,MatriceCreuse<R> *,bool> > *,                                               
+                                               list<triplet<R,MatriceCreuse<R> *,bool> > *  >
+{  //  M + ....
+   typedef triplet<R,MatriceCreuse<R> *,bool> P;
+   typedef list<P> L;
+   typedef L * RR;
+   typedef Matrice_Creuse<R> * MM;
+
+  static   RR f(const MM & a,const RR & b)  
+  { 
+    
+    b->push_front(make_triplet<R,MatriceCreuse<R> *>(R(1.),a->A,false));
+    return b;
+  }
+    
+    
+};
+
+template<class R> 
+struct Op2_ListCMMadd: public binary_function< list<triplet<R,MatriceCreuse<R> *,bool> > *,                                                                                              
+                                               Matrice_Creuse<R> * ,
+                                               list<triplet<R,MatriceCreuse<R> *,bool> > *>
+{  //   .... + M
+   typedef triplet<R,MatriceCreuse<R> *,bool> P;
+   typedef list<P> L;
+   typedef L * RR;
+   typedef Matrice_Creuse<R> * MM;
+
+  static   RR f(const RR & a,const MM & b)  
+  { 
+    
+    a->push_back(make_triplet<R,MatriceCreuse<R> *,bool>(R(1.),b->A,false));
+    return a;
+  }
+    
+    
+};
+
+template<class R> 
+struct Op2_ListMMadd: public binary_function< Matrice_Creuse<R> *,
+                                              Matrice_Creuse<R> * ,
+                                              list<triplet<R,MatriceCreuse<R> *,bool> > *>
+{  //  M + M
+   typedef triplet<R,MatriceCreuse<R> *,bool> P;
+   typedef list<P> L;
+   typedef L * RR;
+   typedef Matrice_Creuse<R> * MM;
+
+  static   RR f(const MM & a,const MM & b)  
+  { 
+    L * l=to(a);
+    l->push_back(make_triplet<R,MatriceCreuse<R> *>(R(1.),b->A,false));
+    return l;
+  }
+    
+    
+};
+// Fin Add FH Houston --------
+
+// for Jolivet  to build restriction  jan 2014
+// t[int] I= restrict(VCh,VGh,IPG); //  ou
+template<class pfes>
+class RestrictArray : public OneOperator { public:
+    template< typename T > struct Base { typedef  T B; };
+    template< typename T > struct Base< T* >{ typedef T B;};
+
+    typedef  typename Base<pfes>::B::FESpace FESpace;
+    typedef typename FESpace::FElement FElement;
+  //  typedef  FESpace FESpace;
+    
+    class Op : public E_F0info { public:  // passe de l'info ..
+        typedef pfes * A;
+        Expression a,b,c,d;
+        // if c = 0 => a,b FESpace
+        // if c != a FESpace et b,c KN_<double>
+        static const int n_name_param =0;
+     //   static basicAC_F0::name_and_type name_param[] ;
+        Expression nargs[n_name_param];
+        bool arg(int i,Stack stack,bool a) const{ return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+        long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+        KN_<long>  arg(int i,Stack stack,KN_<long> a ) const{ return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+        
+    public:
+        Op(const basicAC_F0 &  args,Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc),d(0) {
+          args.SetNameParam(n_name_param,0,nargs);
+          
+        }
+        /*
+        AnyType operator()(Stack stack)  const
+          {
+              if( verbosity>9) cout << " -- RestrictArray  "<< endl;
+              pfes * pCUh = GetAny< pfes * >((* a)(stack));
+              pfes * pFVh = GetAny<  pfes * >((* b)(stack));
+              // verif same  FE.
+              KN_<long> ncf=  GetAny<  KN_<long>  >((* c)(stack));
+              FESpace * pVCh = **pCUh;
+              FESpace * pVFh = **pFVh;
+              FESpace  VCh = *pVCh;
+              FESpace  VFh = *pVFh;
+              long neC = VCh.NbOfElements   ;
+              long neF = VFh.NbOfElements   ;
+              long ndfC = VCh.NbOfDF   ;
+              long ndfF = VFh.NbOfDF   ;
+              
+              KN_<long> nc2f= ncf;
+              
+              KN<long> *pnum=new KN<long>(ndfC);
+              KN<long> inj=*pnum;
+              inj = -1; // un set ..
+              if( verbosity>9) cout<< " ne =" << neC << " " << neF << endl;
+              
+              for(int kc=0; kc <VCh.NbOfElements; kc++)
+              {
+                  
+                  int kf = nc2f(kc);
+                  FElement KC(pVCh,kc);
+                  FElement KF(pVFh,kf);
+                  
+                  int ndofKC = KC.NbDoF() ;
+                  int ndofKF =  KF.NbDoF() ;
+                  if( verbosity>99) cout << kc << " " << kf << " : " <<ndofKC << " " << ndofKF << endl;
+                  ffassert(ndofKC== ndofKF );
+                  ffassert( kf >= 0 && kf < neF);
+                  ffassert( kc >= 0 && kc< neC);
+ 
+                  for(int df=0; df<ndofKC; df++)
+                  {
+                      int dfC =KC(df), dfF=KF(df);
+                      if( verbosity>99) cout << dfC <<" ->  "<< dfF << endl;
+                      assert(dfC >= 0 && dfC < ndfC);
+                      inj[dfC] = dfF;
+                  }
+                 
+              }
+              
+              if( verbosity>9) cout << " restrict:  Inject= " << inj << endl;
+               ffassert(inj.min() != -1);
+            //Add2StackOfPtr2FreeRC(stack,pnum);
+              
+            return pnum;
+          }
+	*/
+    };
+    RestrictArray() : OneOperator(  atype<const typename RestrictArray<pfes>::Op *>(),//atype<KN<long>* >(),
+                                        atype<pfes *>(),
+                                        atype<pfes *>(),
+                                        atype<KN_<long> >()) {}
+    
+    E_F0 * code(const basicAC_F0 & args) const
+    {
+        if(args.size()!=3)CompileError("Bug in RestrictArray code nb of args !=  3 ????? bizarre" );
+      return  new Op(args,t[0]->CastTo(args[0]),
+                           t[1]->CastTo(args[1]),
+                           t[2]->CastTo(args[2]));
+    }
+};
+// end restrict ...
+template< typename T > struct Base { typedef  T B; };
+template< typename T > struct Base< T* >{ typedef T B;};
+
+template<class pfes, int INIT>
+AnyType SetRestrict(Stack stack,Expression einj,Expression erest)
+{
+    
+    typedef  typename Base<pfes>::B::FESpace FESpace;
+    typedef typename FESpace::FElement FElement;
+
+   KN<long>  * pinj =GetAny<KN<long>*>((*einj)(stack));
+   const typename RestrictArray<pfes>::Op * ar(dynamic_cast<const typename RestrictArray<pfes>::Op *>(erest));
+    ffassert(ar);
+    if( verbosity>9) cout << " -- RestrictArray  "<< endl;
+    pfes * pCUh = GetAny< pfes * >((* ar->a)(stack));
+    pfes * pFVh = GetAny<  pfes * >((* ar->b)(stack));
+    // verif same  FE.
+    KN_<long> ncf=  GetAny<  KN_<long>  >((* ar->c)(stack));
+    FESpace * pVCh = **pCUh;
+    FESpace * pVFh = **pFVh;
+    FESpace & VCh = *pVCh;
+    FESpace & VFh = *pVFh;
+    long neC = VCh.NbOfElements   ;
+    long neF = VFh.NbOfElements   ;
+    long ndfC = VCh.NbOfDF   ;
+    long ndfF = VFh.NbOfDF   ;
+    
+    KN_<long> nc2f= ncf;
+    if(INIT==0)
+        pinj->init(ndfC);
+    else pinj->resize(ndfC);
+  //  KN<long> *pnum= INIT ==0 ? new KN<long>(ndfC): pnum;
+    KN<long> & inj=*pinj;
+    inj = -1; // un set ..
+    if( verbosity>9) cout<< " ne =" << neC << " " << neF << endl;
+    
+    for(int kc=0; kc <VCh.NbOfElements; kc++)
+    {
+        
+        int kf = nc2f(kc);
+        FElement KC(pVCh,kc);
+        FElement KF(pVFh,kf);
+        
+        int ndofKC = KC.NbDoF() ;
+        int ndofKF =  KF.NbDoF() ;
+        if( verbosity>99) cout << kc << " " << kf << " : " <<ndofKC << " " << ndofKF << endl;
+        ffassert(ndofKC== ndofKF );
+        ffassert( kf >= 0 && kf < neF);
+        ffassert( kc >= 0 && kc< neC);
+        
+        for(int df=0; df<ndofKC; df++)
+        {
+            int dfC =KC(df), dfF=KF(df);
+            if( verbosity>99) cout << dfC <<" ->  "<< dfF << endl;
+            assert(dfC >= 0 && dfC < ndfC);
+            inj[dfC] = dfF;
+        }
+        
+    }
+    if( verbosity>9) cout << " restrict:  Inject= " << inj << endl;
+    ffassert(inj.min() != -1);
+   
+  return pinj;
+}
+
+// Fin Add FH Houston --------
+template<class pfes>
+class MatrixInterpolation : public OneOperator { public:
+
+    class Op : public E_F0info { public:
+       typedef pfes * A;
+       Expression a,b,c,d;
+       // if c = 0 => a,b FESpace
+       // if c != a FESpace et b,c KN_<double>
+       static const int n_name_param =5;
+       static basicAC_F0::name_and_type name_param[] ;
+        Expression nargs[n_name_param];
+     bool arg(int i,Stack stack,bool a) const{ return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+     long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+     KN_<long>  arg(int i,Stack stack,KN_<long> a ) const{ return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+
+       public:
+       Op(const basicAC_F0 &  args,Expression aa,Expression bb) : a(aa),b(bb),c(0),d(0) {
+         args.SetNameParam(n_name_param,name_param,nargs);  }
+       Op(const basicAC_F0 &  args,Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc),d(0) {
+         args.SetNameParam(n_name_param,name_param,nargs); } 
+	Op(const basicAC_F0 &  args,Expression aa,Expression bb,Expression cc,Expression dd) : a(aa),b(bb),c(cc),d(dd) {
+	    args.SetNameParam(n_name_param,name_param,nargs); } 
+	
+	
+    };
+    // interpolation(Vh,Vh)
+   MatrixInterpolation() : OneOperator(atype<const typename MatrixInterpolation<pfes>::Op *>(),
+                                       atype<pfes *>(),
+                                       atype<pfes *>()) {}
+   // interpolation(Vh,xx,yy) // 2d 
+   MatrixInterpolation(int bidon) : OneOperator(atype<const typename MatrixInterpolation<pfes>::Op *>(),
+                                                atype<pfes *>(),atype<KN_<double> >(),atype<KN_<double> >()) {}
+ 
+    // interpolation(Vh,xx,yy,zz) // 3d 
+    MatrixInterpolation(int bidon,int bidon2) : OneOperator(atype<const typename MatrixInterpolation<pfes>::Op *>(),
+						 atype<pfes *>(),atype<KN_<double> >(),atype<KN_<double> >(),atype<KN_<double> >()) {}
+    
+  
+    E_F0 * code(const basicAC_F0 & args) const 
+     { 
+       if(args.size()==2)
+       return  new Op(args,t[0]->CastTo(args[0]),
+                           t[1]->CastTo(args[1]));
+       else if(args.size()==3)
+       return  new Op(args,t[0]->CastTo(args[0]),
+                           t[1]->CastTo(args[1]),
+                           t[2]->CastTo(args[2]));
+       else if(args.size()==4)
+	   return  new Op(args,t[0]->CastTo(args[0]),
+			  t[1]->CastTo(args[1]),
+			  t[2]->CastTo(args[2]),
+			  t[2]->CastTo(args[3])
+			  );
+       else CompileError("Bug in MatrixInterpolation code nb != 2 or 3 ????? bizarre" );
+       return 0;
+     }
+};
+template<>
+basicAC_F0::name_and_type  MatrixInterpolation<pfes>::Op::name_param[]= {
+   {  "t", &typeid(bool)}, 
+   {  "op", &typeid(long)},
+   {  "inside",&typeid(bool)},
+   {  "composante",&typeid(long)},
+   {  "U2Vc",&typeid(KN_<long>)}
+
+};
+
+template<>
+basicAC_F0::name_and_type  MatrixInterpolation<pfes3>::Op::name_param[]= {
+    {  "t", &typeid(bool)}, 
+    {  "op", &typeid(long)},
+    {  "inside",&typeid(bool)},
+    {  "composante",&typeid(long)},
+    {  "U2Vc",&typeid(KN_<long>)}
+    
+};
+
+
+
+
+template<class R>
+   class SetMatrix_Op : public E_F0mps { public:
+       Expression a; 
+       
+       static  aType btype;
+       static const int n_name_param =NB_NAME_PARM_MAT; //  add nbiter FH 30/01/2007 11 -> 12  //add var MUMPS+autre
+       static basicAC_F0::name_and_type name_param[] ;
+       Expression nargs[n_name_param];
+       const OneOperator * precon;
+       bool arg(int i,Stack stack,bool a) const{ return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+       long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+
+       public:
+       SetMatrix_Op(const basicAC_F0 &  args,Expression aa) : a(aa) {
+         args.SetNameParam(n_name_param,name_param,nargs);
+         precon = 0; //  a changer 
+         if ( nargs[3])
+          {
+           const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(nargs[3]);
+           assert(op);
+           precon = op->Find("(",ArrayOfaType(atype<KN<R>* >(),false)); // strange bug in g++ is R become a double
+          }
+         
+       } 
+       AnyType operator()(Stack stack)  const ;
+    };
+
+
+template<class R>
+class SetMatrix : public OneOperator { public:  
+
+ 
+  // SetMatrix() : OneOperator(atype<const typename SetMatrix<R>::Op *>(),atype<Matrice_Creuse<R> *>() ) {}
+   SetMatrix() : OneOperator(SetMatrix_Op<R>::btype,atype<Matrice_Creuse<R> *>() ) {}
+  
+    E_F0 * code(const basicAC_F0 & args) const 
+     { 
+       return  new SetMatrix_Op<R>(args,t[0]->CastTo(args[0])); 
+     }
+};
+
+template<class R>
+       aType  SetMatrix_Op<R>::btype=0;
+
+template <class R> 
+basicAC_F0::name_and_type  SetMatrix_Op<R>::name_param[]= {
+ LIST_NAME_PARM_MAT
+
+
+
+/*
+   {   "paramint",&typeid(KN<int>)}, // Add J. Morice 02/09 
+   {   "paramdouble",&typeid(KN<double>)},
+
+   {   "paramstring",&typeid(string*)},
+   {   "permrow",&typeid(KN_<long>)},
+   {   "permcol",&typeid(KN_<long>)},
+   {   "fileparamint",&typeid(string*)}, // Add J. Morice 02/09 
+   {   "fileparamdouble",&typeid(string*)},
+   {   "fileparamstring",&typeid(string* )},
+   {   "filepermrow",&typeid(string*)},
+   {   "filepermcol",&typeid(string*)} //22
+ */
+};
+
+template<class R>
+AnyType SetMatrix_Op<R>::operator()(Stack stack)  const 
+{
+   Matrice_Creuse<R> *  A= GetAny<Matrice_Creuse<R> *>((*a)(stack));
+   
+    ffassert(A);
+    if( !A->A) A->A.master(new MatriceMorse<R>());//  set to empty matrix .. mars 2014 FH ..
+    Data_Sparse_Solver ds;
+    bool VF=false;
+   // bool factorize=false;
+    ds.factorize=false;
+    /*
+  long NbSpace = 50; 
+  long itmax=0; 
+  double epsilon=1e-6;
+//  bool VF=false;
+//  VF=isVF(op->largs);
+ // assert(!VF); 
+  double tgv = 1e30;
+  double tol_pivot=-1;
+  double tol_pivot_sym=-1;
+  
+  KN<int>  param_int;
+  KN<double> param_double; 
+  string *param_char=NULL;
+  KN<int> perm_r; 
+  KN<int> perm_c;
+  string *file_param_int;  // Add J. Morice 02/09 
+  string *file_param_double; 
+  string* file_param_char;
+  string* file_param_perm_r;
+  string* file_param_perm_c;  
+*/
+// type de matrice par default 
+  TypeSolveMat tmat= TypeSolveMat::defaultvalue; 
+  if(   tmat !=  TypeSolveMat::SparseSolver  )    
+    tmat=TypeSolveMat::GMRES;
+ ds.typemat=&tmat; 
+ SetEnd_Data_Sparse_Solver<R>(stack,ds,nargs,n_name_param);  
+/*     
+  TypeSolveMat    *typemat=&tmat;
+  bool initmat=true;
+  int strategy=0; 
+   
+  if (nargs[0]) ds.initmat= ! GetAny<bool>((*nargs[0])(stack));
+  if (nargs[1]) ds.typemat= GetAny<TypeSolveMat *>((*nargs[1])(stack));
+  if (nargs[2]) ds.epsilon= GetAny<double>((*nargs[2])(stack));
+  // 3 precon 
+  if (nargs[4]) ds.NbSpace= GetAny<long>((*nargs[4])(stack));
+  if (nargs[6]) ds.tgv= GetAny<double>((*nargs[6])(stack));
+  if (nargs[7]) ds.factorize= GetAny<bool>((*nargs[7])(stack));
+  
+  if (nargs[8]) ds.strategy = GetAny<long>((*nargs[8])(stack)); 
+  if (nargs[9]) ds.tol_pivot = GetAny<double>((*nargs[9])(stack)); 
+  if (nargs[10]) ds.tol_pivot_sym = GetAny<double>((*nargs[10])(stack)); 
+  if (nargs[11]) ds.itmax = GetAny<long>((*nargs[11])(stack)); //  frev 2007 OK
+   
+
+  if (nargs[12]) ds.param_int= GetAny< KN<int> >((*nargs[12])(stack));  // Add J. Morice 02/09 
+  if (nargs[13]) ds.param_double= GetAny< KN<double> >((*nargs[13])(stack));
+  if (nargs[14]) ds.param_char= GetAny< string * >((*nargs[14])(stack));  //
+  if (nargs[15]) ds.perm_r = GetAny< KN<int > >((*nargs[15])(stack));
+  if (nargs[16]) ds.perm_c = GetAny< KN<int> >((*nargs[16])(stack));  //
+  if (nargs[17]) ds.file_param_int= GetAny< string* >((*nargs[17])(stack));  // Add J. Morice 02/09 
+  if (nargs[18]) ds.file_param_double= GetAny< string* >((*nargs[18])(stack));
+  if (nargs[19]) ds.file_param_char= GetAny< string* >((*nargs[19])(stack));  //
+  if (nargs[20]) ds.file_param_perm_r = GetAny< string* >((*nargs[20])(stack));
+  if (nargs[21]) ds.file_param_perm_c = GetAny< string* >((*nargs[21])(stack));  //
+*/
+
+
+   if(A->typemat.profile != ds.typemat->profile) 
+   {
+     cerr << " type of matrix " << A->typemat<<endl;
+     cerr << " type of matrix for solver " <<*ds.typemat<<endl;
+     
+     ExecError(" Set incompatibility between solver and type of matrix");
+   }
+  if( ds.factorize ) {
+    MatriceProfile<R> * pf = dynamic_cast<MatriceProfile<R> *>((MatriceCreuse<R> *) A->A);
+    assert(pf);
+    switch (ds.typemat->t) {
+    case TypeSolveMat::LU: pf->LU(Abs(ds.epsilon));break;
+    case TypeSolveMat::CROUT: pf->crout(Abs(ds.epsilon));break;
+    case TypeSolveMat::CHOLESKY: pf->cholesky(Abs(ds.epsilon));break;
+    default: ExecError("Sorry no factorization for this type for matrix"); 
+    }
+    
+  }    
+  SetSolver<R>(stack,VF,*A->A,ds) ;/*stack,*A->A,typemat,VF,epsilon,NbSpace,itmax,precon,strategy,tgv,tol_pivot,tol_pivot_sym, 
+	       param_int, param_double, param_char, perm_r, perm_c, file_param_int, file_param_double, 
+	       file_param_char, file_param_perm_r, file_param_perm_c);*/
+
+  return Nothing; 
+}
+
+
+
+bool SetDefaultSolver()
+{
+
+#ifdef HAVE_LIBUMFPACKXXXXXX
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to UMFPACK" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverUMFPack;
+    DefSparseSolver<Complex>::solver =BuildSolverUMFPack;
+    DefSparseSolverSym<double>::solver  =BuildSolverGMRES<double>;
+    DefSparseSolverSym<Complex>::solver =BuildSolverGMRES<Complex>;
+    
+#else
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to GMRES (no UMFPACK)" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverGMRES<double>;
+    DefSparseSolver<Complex>::solver =BuildSolverGMRES<Complex>;
+    DefSparseSolverSym<double>::solver  =BuildSolverGMRES<double>;
+    DefSparseSolverSym<Complex>::solver =BuildSolverGMRES<Complex>;
+    
+#endif
+    return true;
+
+}
+
+template<int init>
+AnyType SetMatrixInterpolation(Stack,Expression ,Expression);
+template<int init>
+AnyType SetMatrixInterpolation3(Stack,Expression ,Expression);
+
+//------
+
+template<class R>
+void BuildCombMat(map< pair<int,int>, R> & mij,const KNM_<R> & A, int ii00=0,int jj00=0,R coef=R(1.),bool cnj=false)
+{
+  double eps0=numeric_limits<double>::min();
+  int i,j;
+  int n = A.N(),m=A.M();
+  for ( i=0;i<n;i++)
+   for ( j=0;j<m;j++)
+          {
+           R cij=coef*A(i,j);
+           if (cnj)  cij = RNM::conj(cij); 
+           if(Fem2D::norm(cij) >eps0)
+             mij[ij_mat(false,ii00,jj00,i,j)] += cij;
+         
+   }
+
+}
+
+void buildInterpolationMatrix(MatriceMorse<R> * m,const FESpace & Uh,const FESpace & Vh,void *data)
+{  //  Uh = Vh 
+
+  int op=op_id; //  value of the function
+  bool transpose=false;
+  bool inside=false;
+   int * iU2V=0;  
+  if (data)
+   {
+     int * idata=static_cast<int*>(data);
+     transpose=idata[0];
+     op=idata[1];
+     inside=idata[2];
+       iU2V= idata + 5;
+     ffassert(op>=0 && op < 4);
+   }
+  if(verbosity>2) 
+    {
+      cout << "  -- buildInterpolationMatrix   transpose =" << transpose << endl
+           << "              value, dx , dy          op = " << op << endl
+           << "                            just  inside = " << inside << endl;
+    }
+  using namespace Fem2D;
+  int n=Uh.NbOfDF;
+  int mm=Vh.NbOfDF;
+  if(transpose) Exchange(n,mm);
+  m->symetrique = false;
+  m->dummy=false;
+  m->a=0;
+  m->lg=0;
+  m->cl=0;
+  m->nbcoef=0;
+  m->n=n;
+  m->m=mm;
+  int n1=n+1;
+  const  Mesh & ThU =Uh.Th; // line 
+  const  Mesh & ThV =Vh.Th; // colunm
+  bool samemesh =  &Uh.Th == &Vh.Th;  // same Mesh
+  int thecolor =0;
+  //  int nbn_u = Uh.NbOfNodes;
+  //int nbn_v = Vh.NbOfNodes;
+  
+  int nbcoef =0;
+  
+  KN<int> color(ThV.nt);
+  KN<int> mark(n);
+  mark=0;
+  
+  int *lg = new int [n1];
+  int * cl = 0;
+  double *a=0;
+  
+  color=thecolor++;
+  FElement Uh0 = Uh[0];
+  FElement Vh0 = Vh[0];
+  
+  FElement::aIPJ ipjU(Uh0.Pi_h_ipj()); 
+  FElement::aR2  PtHatU(Uh0.Pi_h_R2()); 
+  
+  //  FElement::aIPJ ipjV(Vh0.Pi_h_ipj()); 
+  // FElement::aR2  PtHatV(Vh0.Pi_h_R2()); 
+  
+  int nbdfVK= Vh0.NbDoF();
+  //  int nbdfUK= Uh0.NbDoF();
+  int NVh= Vh0.N;
+  //int NUh= Uh0.N;
+  
+  //ffassert(NVh==NUh); 
+  
+  
+  int nbp= PtHatU.N(); // 
+  //  int nbc= ipjU.N(); // 
+  KN<R2> PV(nbp);   //  the PtHat in ThV mesh
+  KN<int> itV(nbp); // the Triangle number
+  KN<bool> intV(nbp); // ouside or not 
+  KN<R>   AipjU(ipjU.N());
+  
+  KNM<R> aaa(nbp,nbdfVK); 
+
+
+   const R eps = 1.0e-10;
+   const int sfb1=Vh0.N*last_operatortype*Vh0.NbDoF();
+   KN<R> kv(sfb1*nbp);
+   R * v = kv;
+    KN<int> ik(nbp); // the Triangle number
+//   KNMK_<R> fb(v+ik[i],VhV0.NbDoF,VhV0.N,1); //  the value for basic fonction
+
+   bool whatd[last_operatortype];
+   for (int i=0;i<last_operatortype;i++) 
+     whatd[i]=false;
+   whatd[op]=true; // the value of function
+   KN<bool> fait(Uh.NbOfDF);
+   fait=false;
+  map< pair<int,int> , double > sij; 
+  
+  for (int step=0;step<2;step++) 
+   {
+      
+	  for (int it=0;it<ThU.nt;it++)
+	    {
+	      thecolor++; //  change the current color
+	      const Triangle & TU(ThU[it]);
+	      FElement KU(Uh[it]);
+	      KU.Pi_h(AipjU);
+	      int nbkU = 0;
+	      if (samemesh)
+	        {
+	          nbkU = 1; 
+	          PV = PtHatU;
+	          itV = it;
+		  intV= false;// add July 2009 (unset varaible FH)
+	        }
+	      else 
+	       {  
+	          const Triangle *ts=0;
+	          for (int i=0;i<nbp;i++)
+	            {
+	              bool outside;
+	              ts=ThV.Find(TU(PtHatU[i]),PV[i],outside,ts); 
+		      if(outside && verbosity>9 ) 
+		        cout << it << " " << i << " :: " << TU(PtHatU[i]) << "  -- "<< outside << PV[i] << " " << ThV(ts) << " ->  " <<  (*ts)(PV[i]) <<endl;
+	              itV[i]= ThV(ts);
+	              intV[i]=outside && inside; //  ouside and inside flag 
+	            }
+	       }
+	       
+	      
+	      for (int p=0;p<nbp;p++)
+	         { 
+
+	              KNMK_<R> fb(v+p*sfb1,nbdfVK,NVh,last_operatortype); // valeur de fonction de base de Vh 
+	              // ou:   fb(idf,j,0) valeur de la j composante de la fonction idf 
+	              Vh0.tfe->FB(whatd,ThV,ThV[itV[p]],PV[p],fb);  
+	          }
+
+	      for (int i=0;i<ipjU.N();i++) 
+	          { // pour tous le terme 
+	           const FElement::IPJ &ipj_i(ipjU[i]);
+	          // assert(ipj_i.j==0); // car  Vh.N=0
+	           int dfu = KU(ipj_i.i); // le numero de df global 
+	           if(fait[dfu]) continue;
+	           int jU = ipj_i.j; // la composante dans U
+	           int p=ipj_i.p;  //  le points
+	           if (intV[p]) continue; //  ouside and inside flag => next 
+	           R aipj = AipjU[i];
+	           FElement KV(Vh[itV[p]]);
+		      int jV=jU;
+		      if(iU2V) jV=iU2V[jU];
+		    
+		    if(jV>=0 && jV<NVh)
+			{
+			    KNMK_<R> fb(v+p*sfb1,nbdfVK,NVh,last_operatortype); 
+			    KN_<R> fbj(fb('.',jV,op)); 
+			    
+			    for (int idfv=0;idfv<nbdfVK;idfv++) 
+				if (Abs(fbj[idfv])>eps) 
+				  {
+				      int dfv=KV(idfv);
+				      int ii=dfu, jj=dfv;
+				      if(transpose) Exchange(ii,jj);
+				      // le term dfu,dfv existe dans la matrice
+				      R c= fbj[idfv]*aipj;
+				      //  cout << " Mat inter " << i << " , "<< j << " = " << c << " " <<step << " " << it << " " <<  endl; 
+				      if(Abs(c)>eps)
+					  //
+					  sij[make_pair(ii,jj)] += c;// correct du to periodic BC. June 2011
+				      /*   
+				       if(step==0)
+				       sij.insert(make_pair(i,j));
+				       else	                  
+				       (*m)(i,j)=c;
+				       */
+				  }
+			}
+	                      
+	          }
+	          
+	      for (int df=0;df<KU.NbDoF();df++) 
+	          {  
+	           int dfu = KU(df); // le numero de df global 
+	           fait[dfu]=true;
+	           }
+	       
+	       
+	    }
+	    if (step==0)
+	     {
+	         nbcoef = sij.size();
+	         cl = new int[nbcoef];
+	         a = new double[nbcoef];
+	         int k=0;
+	         for(int i=0;i<n1;i++)
+	           lg[i]=0;
+	          
+	         for (map<pair<int,int>, double >::iterator kk=sij.begin();kk!=sij.end();++kk)
+	          { 
+	            int i= kk->first.first;
+	            int j= kk->first.second;
+	           // cout << " Mat inter " << i << " , "<< j  << endl;
+	            cl[k]=j;
+	            a[k]= kk->second;	            
+	            lg[i+1]=++k;
+	          }
+	         assert(k==nbcoef);
+	         //  on bouche les ligne vide   lg[i]=0; 
+	         //  lg est un tableau croissant  =>
+	         for(int i=1;i<n1;i++)
+	              lg[i]=max(lg[i-1],lg[i]) ;
+	         m->lg=lg;
+             m->cl=cl;
+             m->a=a;
+             m->nbcoef=nbcoef;
+             fait=false;
+	     }
+    }
+    sij.clear();
+  //assert(0); // a faire to do
+}
+
+void buildInterpolationMatrix(MatriceMorse<R> * m,const FESpace3 & Uh,const FESpace3 & Vh,void *data)
+{  //  Uh = Vh 
+    typedef FESpace3::Mesh Mesh;
+    typedef FESpace3::FElement  FElement;
+    typedef Mesh::Element  Element;
+    typedef FESpace3::Rd  Rd;
+    typedef Element::RdHat  RdHat;
+    
+    int op=op_id; //  value of the function
+    bool transpose=false;
+    bool inside=false;
+    int * iU2V=0;  
+    if (data)
+      {
+	int * idata=static_cast<int*>(data);
+	transpose=idata[0];
+	op=idata[1];
+	inside=idata[2];
+	iU2V= idata + 5;
+	ffassert(op>=0 && op < 4);
+      }
+    if(verbosity>2) 
+      {
+	cout << "  -- buildInterpolationMatrix   transpose =" << transpose << endl
+	<< "              value, dx , dy          op = " << op << endl
+	<< "                            just  inside = " << inside << endl;
+      }
+    using namespace Fem2D;
+    int n=Uh.NbOfDF;
+    int mm=Vh.NbOfDF;
+    if(transpose) Exchange(n,mm);
+    m->symetrique = false;
+    m->dummy=false;
+    m->a=0;
+    m->lg=0;
+    m->cl=0;
+    m->nbcoef=0;
+    m->n=n;
+    m->m=mm;
+    int n1=n+1;
+    const  Mesh & ThU =Uh.Th; // line 
+    const  Mesh & ThV =Vh.Th; // colunm
+    bool samemesh =  &Uh.Th == &Vh.Th;  // same Mesh
+    int thecolor =0;
+    //  int nbn_u = Uh.NbOfNodes;
+    //int nbn_v = Vh.NbOfNodes;
+    
+    int nbcoef =0;
+    
+    KN<int> color(ThV.nt);
+    KN<int> mark(n);
+    mark=0;
+    
+    int *lg = new int [n1];
+    int * cl = 0;
+    double *a=0;
+    
+    color=thecolor++;
+    FElement Uh0 = Uh[0];
+    FElement Vh0 = Vh[0];
+    
+   // FElement::aIPJ ipjU(Uh0.Pi_h_ipj()); 
+   // FElement::aR2  PtHatU(Uh0.Pi_h_R2()); 
+    
+    //  FElement::aIPJ ipjV(Vh0.Pi_h_ipj()); 
+    // FElement::aR2  PtHatV(Vh0.Pi_h_R2()); 
+    
+    int nbdfVK= Vh0.NbDoF();
+    //  int nbdfUK= Uh0.NbDoF();
+    int NVh= Vh0.N;
+   // int NUh= Uh0.N;
+    
+    //ffassert(NVh==NUh); 
+    
+    InterpolationMatrix<RdHat> ipmat(Uh);    
+  
+    int nbp=ipmat.np; // 
+    //  int nbc= ipjU.N(); // 
+    KN<RdHat> PV(nbp);   //  the PtHat in ThV mesh
+    KN<int> itV(nbp); // the Triangle number
+    KN<bool> intV(nbp); // ouside or not 
+   // KN<R>   AipjU(ipjU.N());
+    
+    KNM<R> aaa(nbp,nbdfVK); 
+    
+    
+    const R eps = 1.0e-10;
+    const int sfb1=Vh0.N*last_operatortype*Vh0.NbDoF();
+    KN<R> kv(sfb1*nbp);
+    R * v = kv;
+    KN<int> ik(nbp); // the Triangle number
+    //   KNMK_<R> fb(v+ik[i],VhV0.NbDoF,VhV0.N,1); //  the value for basic fonction
+    op= op==3 ? op_dz : op; //   renumber op ????  dec 2010 FH. 
+    What_d whatd= 1<< op;
+    KN<bool> fait(Uh.NbOfDF);
+    fait=false;
+    map< pair<int,int> , double > sij; 
+    for (int step=0;step<2;step++) 
+      {
+	
+	for (int it=0;it<ThU.nt;it++)
+	  {
+	    thecolor++; //  change the current color
+	    const Element & TU(ThU[it]);
+	    FElement KU(Uh[it]);
+	    ipmat.set(KU);
+	    //KU.Pi_h(AipjU);
+	    int nbkU = 0;
+	    if (samemesh)
+	      {
+		nbkU = 1; 
+		PV = ipmat.P;
+		itV = it;
+		intV= false;// add July 2009 (unset varaible FH)
+	      }
+	    else 
+	      {  
+	          const Element *ts=0;
+	          for (int i=0;i<nbp;i++)
+	            {
+	              bool outside;
+	              ts=ThV.Find(TU(ipmat.P[i]),PV[i],outside,ts); 
+		      if(outside && verbosity>9 ) 
+			  cout << it << " " << i << " :: " << TU(ipmat.P[i]) << "  -- "<< outside << PV[i] << " " << ThV(ts) << " ->  " <<  (*ts)(PV[i]) <<endl;
+	              itV[i]= ThV(ts);
+	              intV[i]=outside && inside; //  ouside and inside flag 
+	            }
+	      }
+	    
+	    
+	    for (int p=0;p<nbp;p++)
+	      { 
+		  
+		  KNMK_<R> fb(v+p*sfb1,nbdfVK,NVh,last_operatortype); // valeur de fonction de base de Vh 
+		  // ou:   fb(idf,j,0) valeur de la j composante de la fonction idf 
+		  Vh0.tfe->FB(whatd,ThV,ThV[itV[p]],PV[p],fb);  
+	      }
+	    
+	    for (int i=0;i<ipmat.ncoef;i++) 
+	      { // pour tous le terme 
+		  
+	          // assert(ipj_i.j==0); // car  Vh.N=0
+		  int dfu = KU(ipmat.dofe[i]); // le numero de df global 
+		  if(fait[dfu]) continue;
+		  int jU = ipmat.comp[i]; // la composante dans U
+		  int p=ipmat.p[i];  //  le point
+		  if (intV[p]) continue; //  ouside and inside flag => next 
+		  R aipj = ipmat.coef[i];
+		  FElement KV(Vh[itV[p]]);
+		  int jV=jU;
+		  if(iU2V) jV=iU2V[jU];
+		  
+		  if(jV>=0 && jV<NVh)
+		    {
+		      KNMK_<R> fb(v+p*sfb1,nbdfVK,NVh,last_operatortype); 
+		      KN_<R> fbj(fb('.',jV,op)); 
+		      
+		      for (int idfv=0;idfv<nbdfVK;idfv++) 
+			  if (Abs(fbj[idfv])>eps) 
+			    {
+			      int dfv=KV(idfv);
+			      int ii=dfu, jj=dfv;
+			      if(transpose) Exchange(ii,jj);
+			      // le term dfu,dfv existe dans la matrice
+			      R c= fbj[idfv]*aipj;
+			      //  cout << " Mat inter " << i << " , "<< j << " = " << c << " " <<step << " " << it << " " <<  endl; 
+			      if(Abs(c)>eps)
+				  //
+				  sij[make_pair(ii,jj)] += c;// correct du to periodic BC. June 2011
+			      /*   
+			       if(step==0)
+			       sij.insert(make_pair(i,j));
+			       else	                  
+			       (*m)(i,j)=c;
+			       */
+			    }
+		    }
+		  
+	      }
+	    
+	    for (int df=0;df<KU.NbDoF();df++) 
+	      {  
+		  int dfu = KU(df); // le numero de df global 
+		  fait[dfu]=true;
+	      }
+	    
+	    
+	  }
+	if (step==0)
+	  {
+	    nbcoef = sij.size();
+	    cl = new int[nbcoef];
+	    a = new double[nbcoef];
+	    int k=0;
+	    for(int i=0;i<n1;i++)
+		lg[i]=0;
+	    
+	    for (map<pair<int,int>, double >::iterator kk=sij.begin();kk!=sij.end();++kk)
+	      { 
+		  int i= kk->first.first;
+		  int j= kk->first.second;
+		  // cout << " Mat inter " << i << " , "<< j  << endl;
+		  cl[k]=j;
+		  a[k]= kk->second;	            
+		  lg[i+1]=++k;
+	      }
+	    assert(k==nbcoef);
+	    //  on bouche les ligne vide   lg[i]=0; 
+	    //  lg est un tableau croissant  =>
+	    for(int i=1;i<n1;i++)
+		lg[i]=max(lg[i-1],lg[i]) ;
+	    m->lg=lg;
+	    m->cl=cl;
+	    m->a=a;
+	    m->nbcoef=nbcoef;
+	    fait=false;
+	  }
+      }
+    sij.clear();
+    //assert(0); // a faire to do
+}
+
+
+MatriceMorse<R> *  buildInterpolationMatrix1(const FESpace & Uh,const KN_<double> & xx,const KN_<double> & yy ,int *data)
+{  //  Uh = Vh 
+
+  int op=op_id; //  value of the function
+  int icomp=0;
+  bool transpose=false;
+  bool inside=false;
+  if (data)
+   {
+     transpose=data[0];
+     op=data[1];
+     inside=data[2];
+     icomp = data[3];
+     ffassert(op>=0 && op < 4);
+     
+   }
+  if(verbosity>2) 
+    {
+      cout << "  -- buildInterpolationMatrix   transpose =" << transpose << endl
+           << "              value, dx , dy          op = " << op << endl
+           << "              composante                 = " << icomp << endl
+           << "                            just  inside = " << inside << endl;
+    }
+  using namespace Fem2D;
+  int n=Uh.NbOfDF;
+  int mm=xx.N();
+  int nbxx= mm;
+  if(transpose) Exchange(n,mm);
+  const  Mesh & ThU =Uh.Th; // line 
+  
+   
+  FElement Uh0 = Uh[0];
+  
+   
+   
+ int nbdfUK= Uh0.NbDoF();
+ int NUh= Uh0.N;
+ 
+ ffassert(icomp < NUh && icomp >=0); 
+    
+
+   const int sfb1=Uh0.N*last_operatortype*Uh0.NbDoF();
+   KN<R> kv(sfb1);
+   R * v = kv;
+   const R eps = 1.0e-10;
+
+   bool whatd[last_operatortype];
+   for (int i=0;i<last_operatortype;i++) 
+     whatd[i]=false;
+   whatd[op]=true; // the value of function
+   KN<bool> fait(Uh.NbOfDF);
+   fait=false;
+   map< pair<int,int> , double > sij; 
+   R2 Phat;
+   bool outside;
+   
+   for(int ii=0;ii<nbxx;ii++)
+   {
+     const Triangle *ts=ThU.Find(R2(xx[ii],yy[ii]),Phat,outside); 
+     if(outside && !inside) continue;
+     int it = ThU(ts); 
+     FElement KU(Uh[it]);
+     KNMK_<R> fb(v,nbdfUK,NUh,last_operatortype);
+     Uh0.tfe->FB(whatd,ThU,ThU[it],Phat,fb);  
+     KN_<R> Fwi(fb('.',icomp,op));
+     for (int idfu=0;idfu<nbdfUK;idfu++) 
+       {
+        int  j = ii;
+        int  i = KU(idfu);
+        if(transpose) Exchange(i,j);
+        R c = Fwi(idfu);
+	if(Abs(c)>eps)
+	  sij[make_pair(i,j)] += c;// correct du to periodic BC. June 2011
+      }
+      }
+  
+   MatriceMorse<R> * m = new MatriceMorse<R>(n,mm,sij,false);
+    sij.clear();
+   return m;
+  //assert(0); // a faire to do
+}
+
+MatriceMorse<R> *  buildInterpolationMatrix1(const FESpace3 & Uh,const KN_<double> & xx,const KN_<double> & yy ,const KN_<double> & zz,int *data)
+{  //  Uh = Vh 
+    typedef FESpace3::Mesh Mesh;
+    typedef FESpace3::FElement  FElement;
+    typedef Mesh::Element  Element;
+    typedef FESpace3::Rd  Rd;
+    
+    
+    int op=op_id; //  value of the function
+    int icomp=0;
+    bool transpose=false;
+    bool inside=false;
+    if (data)
+      {
+	transpose=data[0];
+	op=data[1];
+	inside=data[2];
+	icomp = data[3];
+	ffassert(op>=0 && op < 4);
+	
+      }
+    if(verbosity>2) 
+      {
+	cout << "  -- buildInterpolationMatrix   transpose =" << transpose << endl
+	<< "              value, dx , dy          op = " << op << endl
+	<< "              composante                 = " << icomp << endl
+	<< "                            just  inside = " << inside << endl;
+      }
+    using namespace Fem2D;
+    int n=Uh.NbOfDF;
+    int mm=xx.N();
+    int nbxx= mm;
+    if(transpose) Exchange(n,mm);
+    const  Mesh & ThU =Uh.Th; // line 
+    
+    
+    FElement Uh0 = Uh[0];
+    
+    
+    
+    int nbdfUK= Uh0.NbDoF();
+    int NUh= Uh0.N;
+    
+    ffassert(icomp < NUh && icomp >=0); 
+    
+    
+    const int sfb1=Uh0.N*last_operatortype*Uh0.NbDoF();
+    KN<R> kv(sfb1);
+    R * v = kv;
+    const R eps = 1.0e-10;
+    
+    What_d whatd= 1 <<op;
+    KN<bool> fait(Uh.NbOfDF);
+    fait=false;
+    map< pair<int,int> , double > sij; 
+    Rd Phat;
+    bool outside;
+    
+    for(int ii=0;ii<nbxx;ii++)
+      {
+	const Element *ts=ThU.Find(Rd(xx[ii],yy[ii],zz[ii]),Phat,outside); 
+	if(outside && !inside) continue;
+	int it = ThU(ts); 
+	FElement KU(Uh[it]);
+	KNMK_<R> fb(v,nbdfUK,NUh,last_operatortype);
+	Uh0.tfe->FB(whatd,ThU,ThU[it],Phat,fb);  
+	KN_<R> Fwi(fb('.',icomp,op));
+	for (int idfu=0;idfu<nbdfUK;idfu++) 
+	  {
+	    int  j = ii;
+	    int  i = KU(idfu);
+	    if(transpose) Exchange(i,j);
+	    R c = Fwi(idfu);
+	    if(Abs(c)>eps)
+		sij[make_pair(i,j)] += c;// correct du to periodic BC. June 2011
+	  }
+      }
+    
+    MatriceMorse<R> * m = new MatriceMorse<R>(n,mm,sij,false);
+    sij.clear();
+    return m;
+    //assert(0); // a faire to do
+}
+
+
+AnyType SetMatrixInterpolation1(Stack stack,Expression emat,Expression einter,int init)
+{
+  using namespace Fem2D;
+  
+  Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+  const MatrixInterpolation<pfes>::Op * mi(dynamic_cast<const MatrixInterpolation<pfes>::Op *>(einter));
+  ffassert(einter);
+  int data[ MatrixInterpolation<pfes>::Op::n_name_param+100];
+  data[0]=mi->arg(0,stack,false); // transpose not
+  data[1]=mi->arg(1,stack,(long) op_id); ; // get just value
+  data[2]=mi->arg(2,stack,false); ; // get just value
+  data[3]=mi->arg(3,stack,0L); ; // get just value
+  KN<long> U2Vc;
+  U2Vc= mi->arg(4,stack,U2Vc); ;
+  if( mi->c==0)
+  { // old cas 
+  pfes * pUh = GetAny< pfes * >((* mi->a)(stack));
+  pfes * pVh = GetAny<  pfes * >((* mi->b)(stack));
+  FESpace * Uh = **pUh;
+  FESpace * Vh = **pVh;
+  int NVh =Vh->N;
+  int NUh =Uh->N;
+  ffassert(NUh< 100-MatrixInterpolation<pfes>::Op::n_name_param);
+
+      for(int i=0;i<NUh;++i)    
+        data[5+i]=i;// 
+      for(int i=0;i<min(NUh,(int) U2Vc.size());++i)    
+	  data[5+i]= U2Vc[i];//
+  if(verbosity>3)
+	for(int i=0;i<NUh;++i)
+	  {
+	    cout << "The Uh componante " << i << " -> " << data[5+i] << "  Componante of Vh  " <<endl;
+	  }
+	  for(int i=0;i<NUh;++i)    
+	if(data[5+i]>=NVh)
+	  {
+	      cout << "The Uh componante " << i << " -> " << data[5+i] << " >= " << NVh << " number of Vh Componante " <<endl;
+	      ExecError("Interpolation incompability beetween componante ");
+	  }
+      
+  ffassert(Vh);
+  ffassert(Uh);
+  
+  //  sparse_mat->pUh=pUh;
+  //sparse_mat->pVh=pVh;
+  if(!init) sparse_mat->init();
+  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+  sparse_mat->A.master(new MatriceMorse<R>(*Uh,*Vh,buildInterpolationMatrix,data));
+  //  sparse_mat->A.master(new MatriceMorse<R>(*Uh,*Vh,buildInterpolationMatrix,data));
+  }
+  else 
+  {  // new cas mars 2006
+  pfes * pUh = GetAny< pfes * >((* mi->a)(stack));
+  KN_<double>  xx = GetAny<  KN_<double>  >((* mi->b)(stack));
+  KN_<double>  yy = GetAny<  KN_<double>  >((* mi->c)(stack));
+  ffassert( xx.N() == yy.N()); 
+  FESpace * Uh = **pUh;
+  ffassert(Uh);
+  
+  //  sparse_mat->pUh=0;
+  //  sparse_mat->pVh=0;
+  if(!init) sparse_mat->init();
+  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+  sparse_mat->A.master(buildInterpolationMatrix1(*Uh,xx,yy,data));
+  }
+   return sparse_mat; // Warning .. no correct gestion of temp ptr ..
+ // return Add2StackOfPtr2Free(stack,sparse_mat);
+}
+
+AnyType SetMatrixInterpolation31(Stack stack,Expression emat,Expression einter,int init)
+{
+    using namespace Fem2D;
+    
+    Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+    const MatrixInterpolation<pfes3>::Op * mi(dynamic_cast<const MatrixInterpolation<pfes3>::Op *>(einter));
+    ffassert(einter);
+    int data[ MatrixInterpolation<pfes3>::Op::n_name_param+100];
+    data[0]=mi->arg(0,stack,false); // transpose not
+    data[1]=mi->arg(1,stack,(long) op_id); ; // get just value
+    data[2]=mi->arg(2,stack,false); ; // get just value
+    data[3]=mi->arg(3,stack,0L); ; // get just value
+    KN<long> U2Vc;
+    U2Vc= mi->arg(4,stack,U2Vc); ;
+    if( mi->c==0)
+      { // old cas 
+	  pfes3 * pUh = GetAny< pfes3 * >((* mi->a)(stack));
+	  pfes3 * pVh = GetAny<  pfes3 * >((* mi->b)(stack));
+	  FESpace3 * Uh = **pUh;
+	  FESpace3 * Vh = **pVh;
+	  int NVh =Vh->N;
+	  int NUh =Uh->N;
+	  ffassert(NUh< 100-MatrixInterpolation<pfes3>::Op::n_name_param);
+	  
+	  for(int i=0;i<NUh;++i)    
+	      data[5+i]=i;// 
+	  for(int i=0;i<min(NUh,(int) U2Vc.size());++i)    
+	      data[5+i]= U2Vc[i];//
+	  if(verbosity>3)
+	      for(int i=0;i<NUh;++i)
+		{
+		  cout << "The Uh componante " << i << " -> " << data[5+i] << "  Componante of Vh  " <<endl;
+		}
+	  for(int i=0;i<NUh;++i)    
+	      if(data[5+i]>=NVh)
+		{
+		  cout << "The Uh componante " << i << " -> " << data[5+i] << " >= " << NVh << " number of Vh Componante " <<endl;
+		  ExecError("Interpolation incompability beetween componante ");
+		}
+	  
+	  ffassert(Vh);
+	  ffassert(Uh);
+	  if(!init) sparse_mat->init();
+	  //  sparse_mat->pUh=pUh;
+	  //sparse_mat->pVh=pVh;
+	  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+	  sparse_mat->A.master(new MatriceMorse<R>(*Uh,*Vh,buildInterpolationMatrix,data));
+	  //  sparse_mat->A.master(new MatriceMorse<R>(*Uh,*Vh,buildInterpolationMatrix,data));
+      }
+    else 
+      {  // new cas mars 2006
+	  pfes3 * pUh = GetAny< pfes3 * >((* mi->a)(stack));
+	  KN_<double>  xx = GetAny<  KN_<double>  >((* mi->b)(stack));
+	  KN_<double>  yy = GetAny<  KN_<double>  >((* mi->c)(stack));
+	  KN_<double>  zz = GetAny<  KN_<double>  >((* mi->d)(stack));
+	  ffassert( xx.N() == yy.N()); 
+	  ffassert( xx.N() == zz.N()); 
+	  FESpace3 * Uh = **pUh;
+	  ffassert(Uh);
+	  if(!init) sparse_mat->init();
+	  //  sparse_mat->pUh=0;
+	  //  sparse_mat->pVh=0;
+	  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+	  sparse_mat->A.master(buildInterpolationMatrix1(*Uh,xx,yy,zz,data));
+      }
+    return sparse_mat;
+}
+
+template<int init>
+AnyType SetMatrixInterpolation(Stack stack,Expression emat,Expression einter)
+{ return SetMatrixInterpolation1(stack,emat,einter,init);}
+template<int init>
+AnyType SetMatrixInterpolation3(Stack stack,Expression emat,Expression einter)
+{ return SetMatrixInterpolation31(stack,emat,einter,init);}
+
+
+template<class RA,class RB,class RAB,int init>
+AnyType ProdMat(Stack stack,Expression emat,Expression prodmat)
+{
+  using namespace Fem2D;
+  
+  Matrice_Creuse<RAB> * sparse_mat =GetAny<Matrice_Creuse<RA>* >((*emat)(stack));
+  const Matrix_Prod<RA,RB>  AB = GetAny<Matrix_Prod<RA,RB> >((*prodmat)(stack));
+  //  sparse_mat->pUh=AB.A->pUh;
+  //sparse_mat->pVh=AB.B->pVh;
+  MatriceMorse<RA> *mA= AB.A->A->toMatriceMorse(AB.ta);
+  MatriceMorse<RB> *mB= AB.B->A->toMatriceMorse(AB.tb);
+  if( !mA && ! mB) ExecError(" Sorry error: in MatProd,  pb trans in MorseMat");
+  if( mA->m != mB->n) {
+    cerr << "  -- Error dim ProdMat A*B : tA =" << AB.ta << " = tB " << AB.tb << endl;
+    cerr << "  --MatProd " << mA->n<< " "<< mA->m << " x " << mB->n<< " "<< mB->m <<  endl;
+    ExecError(" Wrong mat dim in MatProd");
+  }
+  MatriceMorse<RAB> *mAB=new MatriceMorse<RA>();
+  mA->prod(*mB,*mAB);
+  if(!init) sparse_mat->init();
+  sparse_mat->typemat=(mA->n == mB->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+  sparse_mat->A.master(mAB);
+  delete mA;
+  delete mB;
+  return sparse_mat;
+}
+
+template<class R,int init>
+AnyType CombMat(Stack stack,Expression emat,Expression combMat)
+{
+  using namespace Fem2D;
+  
+  Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+  list<triplet<R,MatriceCreuse<R> *,bool> > *  lcB = GetAny<list<triplet<R,MatriceCreuse<R> *,bool> >*>((*combMat)(stack));
+  //  sparse_mat->pUh=0;
+  // sparse_mat->pVh=0;
+   MatriceCreuse<R> * AA=BuildCombMat<R>(*lcB,false,0,0);
+   if(!init) sparse_mat->init();
+  sparse_mat->A.master(AA);
+  sparse_mat->typemat=(AA->n == AA->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+  delete lcB;
+  return sparse_mat;
+}
+
+
+template<class R>
+AnyType MatriceCreuse2map(Stack , const AnyType & mat)
+{
+
+  using namespace Fem2D;
+
+  Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >(mat);
+  ffassert(sparse_mat);
+  int n=sparse_mat->N(),m=sparse_mat->M();
+  map<pair<int,int>,R> *M=new map<pair<int,int>,R>;
+  if (n >0 && m>0 && sparse_mat->A) 
+    {
+      sparse_mat->A->addMatTo(R(1.),*M);
+      // hack 
+      (*M)[make_pair(n-1,m-1)]+=R();
+    }
+  return M;
+}
+
+
+template<class R,int init>
+AnyType DiagMat(Stack stack,Expression emat,Expression edia)
+{
+  using namespace Fem2D;
+  KN<R> * diag=GetAny<KN<R>* >((*edia)(stack));
+  Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+  //  sparse_mat->pUh=0;
+  // sparse_mat->pVh=0;
+  if(!init) sparse_mat->init();
+  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::GC); //  none square matrice (morse)
+  sparse_mat->A.master(new MatriceMorse<R>((int) diag->N(),(const R*) *diag));
+  return sparse_mat;
+}
+
+
+
+template<class Rin,class Rout>
+ struct  ChangeMatriceMorse {
+ static  MatriceMorse<Rout> *f(MatriceMorse<Rin> *mr)
+ {
+    MatriceMorse<Rout>*  mrr=new MatriceMorse<Rout>(*mr);
+    delete mr;
+    return mrr;
+ }
+ };
+
+template<class R> 
+ struct  ChangeMatriceMorse<R,R> {
+ static MatriceMorse<R>* f(MatriceMorse<R>* mr)
+ {
+   return mr;
+ }
+ };
+template<class R,class RR,int init>
+AnyType CopyMat_tt(Stack stack,Expression emat,Expression eA,bool transp)
+{
+  using namespace Fem2D;
+  Matrice_Creuse<R> * Mat;
+ 
+  if(transp)
+   {
+    Matrice_Creuse_Transpose<R>  tMat=GetAny<Matrice_Creuse_Transpose<R> >((*eA)(stack));
+    Mat=tMat; 
+   }
+  else   Mat =GetAny<Matrice_Creuse<R>*>((*eA)(stack));
+  MatriceMorse<R> * mr=Mat->A->toMatriceMorse(transp,false);
+  MatriceMorse<RR> * mrr = ChangeMatriceMorse<R,RR>::f(mr);
+  
+  Matrice_Creuse<RR> * sparse_mat =GetAny<Matrice_Creuse<RR>* >((*emat)(stack));
+  //  sparse_mat->pUh=Mat->pUh;
+  // sparse_mat->pVh=Mat->pUh;;
+  //  cout << " CopyMat_tt " << init << " "<<transp << " " << sparse_mat << endl;
+  if(!init) sparse_mat->init() ;
+  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::GC); //  none square matrice (morse)
+  sparse_mat->A.master(mrr);
+  //delete mr;
+  return sparse_mat;
+}
+
+template<class R,class RR,int init>
+AnyType CopyTrans(Stack stack,Expression emat,Expression eA)
+{
+ return CopyMat_tt<R,RR,init>(stack,emat,eA,true);
+}
+template<class R,class RR,int init>
+AnyType CopyMat(Stack stack,Expression emat,Expression eA)
+{
+ return CopyMat_tt<R,RR,init>(stack,emat,eA,false);
+}
+
+
+template<class R,int init>
+AnyType MatFull2Sparse(Stack stack,Expression emat,Expression eA)
+{
+  KNM<R> * A=GetAny<KNM<R>* >((*eA)(stack));
+  Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+  //  sparse_mat->pUh=0;
+  // sparse_mat->pVh=0;
+  if(!init) sparse_mat->init() ;
+  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::GMRES); //  none square matrice (morse)
+  sparse_mat->A.master(new MatriceMorse<R>((KNM_<R> &)*A,0.0));
+  
+ return sparse_mat;
+}
+
+template<class R,int init>
+AnyType MatMap2Sparse(Stack stack,Expression emat,Expression eA)
+{
+   map< pair<int,int>, R> * A=GetAny< map< pair<int,int>, R> * >((*eA)(stack));
+   int n=0,m=0;
+   // hack:  the last element must exist in the map  to set matrix size 
+
+   typename map< pair<int,int>, R>::const_iterator last= --A->end(); // le last element
+   
+   if( last != A->end() )
+   
+        { 
+                n = last->first.first+1; 
+                m=last->first.second+1;
+        } 
+    
+  Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+     if(!init) sparse_mat->init() ;
+  //  sparse_mat->pUh=0;
+  // sparse_mat->pVh=0;
+  sparse_mat->typemat=TypeSolveMat(TypeSolveMat::GMRES); //  none square matrice (morse)  
+  sparse_mat->A.master(new MatriceMorse<R>(n,m,*A,false));
+  delete A; 
+ return sparse_mat;
+}
+
+template<class RR,class AA=RR,class BB=AA> 
+struct Op2_pair: public binary_function<AA,BB,RR> { 
+  static RR f(const AA & a,const BB & b)  
+  { return RR( a, b);} 
+};
+
+
+template<class R>
+long get_mat_n(Matrice_Creuse<R> * p)
+ { ffassert(p ) ;  return p->A ?p->A->n: 0  ;}
+
+template<class R>
+long get_mat_m(Matrice_Creuse<R> * p)
+ { ffassert(p ) ;  return p->A ?p->A->m: 0  ;}
+
+template<class R>
+long get_mat_nbcoef(Matrice_Creuse<R> * p)
+ { ffassert(p ) ;  return p->A ?p->A->NbCoef(): 0  ;}
+
+template<class R>
+pair<long,long> get_NM(const list<triplet<R,MatriceCreuse<R> *,bool> > & lM)
+{
+      typedef typename list<triplet<R,MatriceCreuse<R> *,bool> >::const_iterator lconst_iterator;
+    
+    lconst_iterator begin=lM.begin();
+    lconst_iterator end=lM.end();
+    lconst_iterator i;
+    
+    long n=0,m=0;
+    for(i=begin;i!=end;i++++)
+     {
+       ffassert(i->second);
+       MatriceCreuse<R> & M=*i->second;
+       bool t=i->third;
+       int nn= M.n,mm=M.m;
+       if (t) swap(nn,mm);
+       if ( n==0) n =  nn;
+       if ( m==0) m = mm;
+       if (n != 0) ffassert(nn == n);
+       if (m != 0) ffassert(mm == m);
+      }
+   return make_pair(n,m);    
+}
+
+template<class R>
+long get_diag(Matrice_Creuse<R> * p, KN<R> * x)
+ { ffassert(p && x ) ;  return p->A ?p->A->getdiag(*x): 0  ;}
+template<class R>
+long set_diag(Matrice_Creuse<R> * p, KN<R> * x)
+ { ffassert(p && x ) ;  return p->A ?p->A->setdiag(*x): 0  ;}
+
+ 
+template<class R>  
+R * get_elementp2mc(Matrice_Creuse<R> * const  & ac,const long & b,const long & c){ 
+   MatriceCreuse<R> * a= ac ? ac->A:0 ;
+  if(  !a || a->n <= b || c<0 || a->m <= c  ) 
+   { cerr << " Out of bound  0 <=" << b << " < "  << a->n << ",  0 <= " << c << " < "  << a->m
+           << " Matrix type = " << typeid(ac).name() << endl;
+     cerr << ac << " " << a << endl;
+     ExecError("Out of bound in operator Matrice_Creuse<R> (,)");}
+   R *  p =a->pij(b,c);
+   if( !p) { if(verbosity) cerr << "Error: the coef a(" << b << ","   << c << ")  do'nt exist in sparse matrix "
+           << " Matrix  type = " << typeid(ac).name() << endl;
+       ExecError("Use of unexisting coef in sparse matrix operator a(i,j) ");}
+    return  p;}
+
+
+template<class RR,class AA=RR,class BB=AA> 
+struct Op2_mulAv: public binary_function<AA,BB,RR> { 
+  static RR f(const AA & a,const BB & b)  
+  { return (*a->A * *b );} 
+};
+
+template<class RR,class AA=RR,class BB=AA> 
+struct Op2_mulvirtAv: public binary_function<AA,BB,RR> { 
+  static RR f(const AA & a,const BB & b)  
+  { return RR( (*a).A, b );} 
+};
+
+class Matrice_Creuse_C2R  { public:
+    typedef Complex K;  
+    Matrice_Creuse<K> * A;
+    int cas; //  0 re , 1 im 
+    Matrice_Creuse_C2R(Matrice_Creuse<K> * AA,int cass) : A(AA),cas(cass) {assert(A);}
+    operator MatriceCreuse<K> & () const {return *A->A;}
+    operator Matrice_Creuse<K> * () const {return A;}
+};
+
+template<int cas> 
+Matrice_Creuse_C2R Build_Matrice_Creuse_C2R(Matrice_Creuse<Complex> * pAA)
+{
+    
+  return Matrice_Creuse_C2R(pAA,cas);
+}
+ 
+template<class K>
+class OneBinaryOperatorA_inv : public OneOperator { public:  
+  OneBinaryOperatorA_inv() : OneOperator(atype<Matrice_Creuse_inv<K> >(),atype<Matrice_Creuse<K> *>(),atype<long>()) {}
+    E_F0 * code(const basicAC_F0 & args) const 
+     { Expression p=args[1];
+       if ( ! p->EvaluableWithOutStack() ) 
+        { 
+          bool bb=p->EvaluableWithOutStack();
+          cout << bb << " " <<  * p <<  endl;
+          CompileError(" A^p, The p must be a constant == -1, sorry");}
+       long pv = GetAny<long>((*p)(NullStack));
+        if (pv !=-1)   
+         { char buf[100];
+           sprintf(buf," A^%ld, The pow must be  == -1, sorry",pv);
+           CompileError(buf);}     
+       return  new E_F_F0<Matrice_Creuse_inv<K>,Matrice_Creuse<K> *>(Build<Matrice_Creuse_inv<K>,Matrice_Creuse<K> *>,t[0]->CastTo(args[0])); 
+    }
+};
+
+
+
+
+template<class K>
+class Psor :  public E_F0 { public:  
+ 
+   typedef double  Result;
+   Expression mat;
+   Expression xx,gmn,gmx,oomega;  
+   Psor(const basicAC_F0 & args) 
+    {   
+      args.SetNameParam();
+      mat=to<Matrice_Creuse<K> *>(args[0]); 
+      gmn=to<KN<K>*>(args[1]); 
+      gmx=to<KN<K>*>(args[2]); 
+      xx=to<KN<K>*>(args[3]); 
+      oomega=to<double>(args[4]); 
+      
+   }   
+    static ArrayOfaType  typeargs() { 
+      return  ArrayOfaType( atype<double>(),
+                            atype<Matrice_Creuse<K> *>(),
+                            atype<KN<K>*>(),
+                            atype<KN<K>*>(),
+                            atype<KN<K>*>(),
+                            atype<double>(),false);}
+                            
+    static  E_F0 * f(const basicAC_F0 & args){ return new Psor(args);} 
+    
+    AnyType operator()(Stack s) const {
+      Matrice_Creuse<K>* A= GetAny<Matrice_Creuse<K>* >( (*mat)(s) );
+      KN<K>* gmin = GetAny<KN<K>* >( (*gmn)(s) );
+      KN<K>* gmax = GetAny<KN<K>* >( (*gmx)(s) );
+      KN<K>* x = GetAny<KN<K>* >( (*xx)(s) );
+      double omega = GetAny<double>((*oomega)(s));
+      return A->A->psor(*gmin,*gmax,*x,omega);
+    }
+  
+};
+template <class R>
+ struct TheDiagMat {
+  Matrice_Creuse<R> * A; 
+  TheDiagMat(Matrice_Creuse<R> * AA) :A(AA) {ffassert(A);}
+  void   get_mat_daig( KN_<R> & x) { ffassert(A && A->A && x.N() == A->A->n  && A->A->n == A->A->m );
+     A->A->getdiag(x);}
+  void   set_mat_daig(const  KN_<R> & x) { ffassert(A && A->A && x.N() == A->A->n  && A->A->n == A->A->m );
+     A->A->setdiag(x);}
+ };
+ 
+ template <class R>
+ struct TheCoefMat {
+  Matrice_Creuse<R> * A; 
+  TheCoefMat(Matrice_Creuse<R> * AA) :A(AA) {ffassert(A);}
+  void   get_mat_coef( KN_<R> & x) { ffassert(A && A->A && x.N() == A->A->NbCoef()  );
+     A->A->getcoef(x);}
+  void   set_mat_coef(const  KN_<R> & x) { ffassert(A && A->A && x.N() == A->A->NbCoef() );
+     A->A->setcoef(x);}
+ };
+ 
+template<class R>
+TheDiagMat<R> thediag(Matrice_Creuse<R> * p)
+ {  return  TheDiagMat<R>(p);}
+
+template<class R>
+TheCoefMat<R> thecoef(Matrice_Creuse<R> * p)
+ {  return  TheCoefMat<R>(p);}
+ 
+template<class R>
+TheDiagMat<R> set_mat_daig(TheDiagMat<R> dm,KN<R> * x)
+{
+  dm.set_mat_daig(*x);
+  return dm;
+}
+template<class R>
+KN<R> * get_mat_daig(KN<R> * x,TheDiagMat<R> dm)
+{
+  dm.get_mat_daig(*x);
+  return x;
+}
+
+template<class R>
+TheCoefMat<R> set_mat_coef(TheCoefMat<R> dm,KN<R> * x)
+{
+  dm.set_mat_coef(*x);
+  return dm;
+}
+template<class R>
+KN<R> * get_mat_coef(KN<R> * x,TheCoefMat<R> dm)
+{
+  dm.get_mat_coef(*x);
+  return x;
+}
+
+template<class R> 
+bool IsRawMat(const basicAC_F0 & args) 
+{   
+    
+    const E_Array & ee= *dynamic_cast<const E_Array*>((Expression) args[1]);
+    if (!&ee) return 0;
+    
+    int N=ee.size();
+    if (N==1)
+    {
+	C_F0 c0(ee[0]);
+	return 
+	    atype<KN_<R> >()->CastingFrom(ee[0].left());
+	    
+    }
+    else if (N==3)
+    {
+	C_F0 c0(ee[0]),c1(ee[1]),c2(ee[2]);
+	return 
+	    atype<KN_<long> >()->CastingFrom(ee[0].left())
+	    && 	    atype<KN_<long> >()->CastingFrom(ee[1].left())
+	    &&      atype<KN_<R> >()->CastingFrom(ee[2].left());
+	    
+    }
+    return 0;
+}
+
+
+template<typename R>
+class RawMatrix :  public E_F0 { public:
+    int init;
+    typedef Matrice_Creuse<R> * Result;
+    Expression emat; 
+    Expression coef,col,lig;
+    RawMatrix(const basicAC_F0 & args,int initt) ;
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<Matrice_Creuse<R>*>(),atype<E_Array>());}
+    AnyType operator()(Stack s) const ;    
+};
+
+ template<typename R>
+ class BlockMatrix :  public E_F0 { public: 
+   typedef Matrice_Creuse<R> * Result;
+   int N,M;
+   int init;
+   Expression emat; 
+   Expression ** e_Mij;
+   int ** t_Mij;
+   BlockMatrix(const basicAC_F0 & args,int iinit=0) ;
+   ~BlockMatrix() ;
+      
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<Matrice_Creuse<R>*>(),atype<E_Array>());}
+    static  E_F0 * f(const basicAC_F0 & args){
+	if(IsRawMat<R>(args)) return new RawMatrix<R>(args,0);
+	else return new BlockMatrix(args,0);
+    }  
+    AnyType operator()(Stack s) const ;
+    
+};
+template<typename R>
+class BlockMatrix1 :  public BlockMatrix<R> { public:
+    BlockMatrix1(const basicAC_F0 & args): BlockMatrix<R>(args,1) {}
+    static  E_F0 * f(const basicAC_F0 & args){
+        if(IsRawMat<R>(args)) return new RawMatrix<R>(args,1);
+        else return new BlockMatrix<R>(args,1);
+    }  
+
+};
+
+template<typename R>  
+map< pair<int,int>, R> *Matrixfull2mapIJ_inv (KNM<R>   * const & pa,const Inv_KN_long & iii,const Inv_KN_long & jjj)
+{
+   const  KN_<long> &ii(iii), &jj(jjj);
+   const KNM<R> & a(*pa);
+   int N=a.N(),M=a.M();
+   long n = ii(SubArray(N)).max()+1;
+   long m= jj(SubArray(M)).max()+1;
+   
+/*
+  long minn = ii(SubArray(N)).min()+1;
+  long minm= jj(SubArray(M)).min()+1;
+  if ( !(0 <= minn && 0 <=  minm) ) 
+  {
+  cerr << " Out of Bound  in A(I^-1,J^1) :  "<< minn << " " << minm <<" =>  negative value!! " << endl;
+  ExecError("Out of Bound Error");
+  }
+*/
+   
+  // cout << "  ### n m " << n << " " << m << endl; 
+   map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+   map< pair<int,int>, R> & A(*pA);
+   A[make_pair(n-1,m-1)] = R(); // Hack to be sure that the last term existe 
+  
+   for (long i=0;i<N;++i)
+    for (long j=0;j<M;++j)
+     { R aij=a(i,j);
+       //cout << i << " " << j << " :: " << ii[i] << " " << jj[j] << " = " << aij << endl;
+       if(ii[i]>=0 && jj[j]>=0 && Fem2D::norm(aij)>1e-40) 
+         A[make_pair(ii[i],jj[j])] += aij;
+     }
+      
+  return pA;
+}
+
+template<typename R>  
+map< pair<int,int>, R> *Matrixfull2mapIJ (KNM<R>   * const & pa,const KN_<long> & ii,const  KN_<long> & jj)
+{
+   const KNM<R> & a(*pa);
+   int N=a.N(),M=a.M();
+   long n = ii.N();
+   long m= jj.N();
+  // cout << "  ### n m " << n << " " << m << endl; 
+   map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+   map< pair<int,int>, R> & A(*pA);
+   A[make_pair(n-1,m-1)] += R(); // Hack to be sure that the last term existe 
+  
+   for (long il=0;il<N;++il)
+    for (long jl=0;jl<M;++jl)
+     { 
+       long i = ii[il];
+       long j = jj[jl];
+       if( i>=0 && j >=0) {
+          if ( !(0 <= i && i < N && 0 <= j && j < M ) )
+            {
+              cerr << " Out of Bound  in A(I,J) : " << i << " " << j << " not in " << "[0,"<<N<<"[x[0," << M << "[ \n";
+              ExecError("Out of Bound Error");
+             }
+       
+          R aij=a(i,j);
+       //cout << i << " " << j << " :: " << ii[i] << " " << jj[j] << " = " << aij << endl;
+	  if (Fem2D::norm(aij)>1e-40) 
+           A[make_pair(il,jl)] += aij;
+       }
+     }
+      
+  return pA;
+}
+
+template<class R>
+AnyType Matrixfull2map (Stack , const AnyType & pp)
+{
+   const KNM<R> & a(*GetAny<KNM<R> *>(pp));
+   int N=a.N(),M=a.M();
+   int n = N;
+   int m= M;
+   map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+   map< pair<int,int>, R> & A(*pA);
+   A[make_pair(n-1,m-1)] = R(); // Hack to be sure that the last term existe 
+  
+   for (int i=0;i<N;++i)
+    for (int j=0;j<M;++j)
+     { R aij=a(i,j);
+       if (Fem2D::norm(aij)>1e-40) 
+      A[make_pair(i,j)] += aij;
+     }
+      
+  return pA;
+}
+
+
+template<class R>
+map< pair<int,int>, R> *Matrixoutp2mapIJ_inv (outProduct_KN_<R>   * const & pop,const Inv_KN_long & iii,const Inv_KN_long & jjj)
+{
+   const KN_<long> &ii(iii), &jj(jjj);
+   const outProduct_KN_<R> & op(*pop);
+   long  N=op.a.N(),M=op.b.N();
+   long  n = ii(SubArray(N)).max()+1;
+   long m= jj(SubArray(M)).max()+1;
+/*
+   long minn = ii(SubArray(N)).min()+1;
+   long minm= jj(SubArray(M)).min()+1;
+     if ( !(0 <= minn && 0 <=  minm) ) 
+        {
+            cerr << " Out of Bound  in A(I^-1,J^1) :  "<< minn << " " << minm <<" =>  negative value!! " << endl;
+            ExecError("Out of Bound Error");
+        }
+ */
+   map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+   map< pair<int,int>, R> & A(*pA);
+   A[make_pair(n-1,m-1)] = R(); // Hack to be sure that the last term existe 
+  
+   for (int i=0;i<N;++i)
+    for (int j=0;j<M;++j)
+     { 
+       R aij=op.a[i]*RNM::conj(op.b[j]);
+       if(ii[i]>=0 && jj[j]>=0 && Fem2D::norm(aij)>1e-40) 
+//       if (norm(aij)>1e-40 &) 
+          A[make_pair(ii[i],jj[j])] += aij;
+     }   
+  delete pop;
+    
+  return pA;
+}
+
+
+template<class R>
+map< pair<int,int>, R> *Matrixmapp2mapIJ1 (map< pair<int,int>, R> *const &  B,const Inv_KN_long & iii,const Inv_KN_long  & jjj)
+{
+    const KN_<long> &ii(iii), &jj(jjj);  
+    typedef typename map< pair<int,int>, R>::const_iterator It;
+    
+    map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+    map< pair<int,int>, R> & A(*pA);
+    int n=0,m=0;
+    // hack:  the last element must exist in the map  to set matrix size 
+/*    
+    It lastb= --B->end(); // le last element
+    
+    if( lastb != B->end() )	
+    { 
+	nb = last->first.first+1; 
+	mb=last->first.second+1;
+    } */
+    int N=ii.N(),M=jj.N();
+   // A[make_pair(n-1,m-1)] = R(); // Hack to be sure that the last term existe 
+    
+    for (It k=B->begin();k!=B->end();++k)
+    {
+	int il =  k->first.first;
+	int jl =  k->first.second;
+	if ( !( 0 <= il && il < N && 0 <= jl && jl < M )  )
+	{
+	    cerr << " Out of Bound  in (Map)(I,J) : " << il << " " << jl << " not in " << "[0,"<<N<<"[x[0," << M << "[ \n";
+	    ExecError("Out of Bound Error");
+	}
+	int i=ii(il);
+	int j=jj(jl);
+	n=max(i,n);
+	m=max(j,m);
+	R aij =k->second;
+	if(i >=0 && j>=0) 
+	  A[make_pair(i,j)] += aij;
+    }
+     A[make_pair(n,m)] += R(); // Hack to be sure that the last term existe 
+     delete B;
+    
+    return pA;
+}
+
+template<class R>
+map< pair<int,int>, R> *Matrixmapp2mapIJ (map< pair<int,int>, R> *const &  B,const KN_<long> & ii,const KN_<long>  & jj)
+{
+    
+    typedef typename map< pair<int,int>, R>::const_iterator It;
+    typedef typename multimap< int,int>::iterator  MI;
+    
+    map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+    map< pair<int,int>, R> & A(*pA);
+    multimap< int,int > I,J;
+    int N=ii.N(),M=jj.N();
+    for (int i=0;i<N;++i)
+	if(ii[i]>=0)
+	  I.insert(make_pair(ii[i],i));
+    for (int j=0;j<M;++j)
+	if(jj[j]>=0)
+	    J.insert(make_pair(jj[j],j));
+    int n=N-1,m=M-1;// change FH  sep 2009 to have the correct size..
+
+    for (It k=B->begin();k!=B->end();++k)
+    {
+	int il =  k->first.first;
+	int jl =  k->first.second;
+	R aij =k->second;
+	pair<MI,MI> PPi=I.equal_range(il);
+	pair<MI,MI> PPj=J.equal_range(jl);
+	for(MI pi=PPi.first ; pi !=  PPi.second; ++pi)
+	{
+	    int i=pi->second;
+	    for(MI pj=PPj.first ; pj !=  PPj.second; ++pj)
+	    { 
+		int j=pj->second;
+		n=max(i,n);
+	        m=max(j,m);	
+	       if(i >=0 && j>=0) 
+	         A[make_pair(i,j)] += aij;
+	    }
+	}   
+    }
+    A[make_pair(n,m)] += R(); // Hack to be sure that the last term existe 
+    delete B;
+    
+    return pA;
+}
+
+template<class R>
+map< pair<int,int>, R> *Matrixoutp2mapIJ (outProduct_KN_<R>   * const & pop,const KN_<long> & ii,const KN_<long>  & jj)
+{
+   const outProduct_KN_<R> & op(*pop);
+   long N=op.a.N(),M=op.b.N();
+   long n=ii.N(),m=jj.N();
+   
+   map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+   map< pair<int,int>, R> & A(*pA);
+   A[make_pair(n-1,m-1)] = R(); // Hack to be sure that the last term existe 
+   
+   for (long il=0;il<n;++il)
+    for (long jl=0;jl<m;++jl)
+     { 
+       long i = ii[il];
+       long j = jj[jl];
+       if(i>=0 && j >=0)
+        {
+               if ( !( 0 <= i && i < N && 0 <= j && j < M )  )
+                {
+                    cerr << " Out of Bound  in (a*b')(I,J) : " << i << " " << j << " not in " << "[0,"<<N<<"[x[0," << M << "[ \n";
+                    ExecError("Out of Bound Error");
+                }
+               R aij=op.a[i]*RNM::conj(op.b[j]);
+               if (Fem2D::norm(aij)>1e-40) 
+                  A[make_pair(il,jl)] += aij;
+               }
+     }   
+  delete pop;
+    
+  return pA;
+}
+
+
+template<class R>
+AnyType Matrixoutp2map (Stack , const AnyType & pp)
+{
+   const outProduct_KN_<R> & op(*GetAny<outProduct_KN_<R> *>(pp));
+   long N=op.a.N(),M=op.b.N();
+   long n = N;
+   long m= M;
+   map< pair<int,int>, R> *pA= new map< pair<int,int>, R>;
+   map< pair<int,int>, R> & A(*pA);
+   A[make_pair(n-1,m-1)] = R(); // Hack to be sure that the last term existe 
+  
+   for (long i=0;i<N;++i)
+    for (long j=0;j<M;++j)
+     { 
+      R aij=op.a[i]*RNM::conj(op.b[j]);
+      if (Fem2D::norm(aij)>1e-40) 
+        A[make_pair(i,j)] += aij;
+     } 
+  delete &op;        
+  return pA;
+}
+
+
+template<typename R>  BlockMatrix<R>::~BlockMatrix() 
+{  
+    if (e_Mij)
+    {  cout << " del Block matrix "<< this << " " << e_Mij <<" N = " << N << " M = " << M << endl;
+	for (int i=0;i<N;i++)
+	{ delete [] e_Mij[i];
+	    delete [] t_Mij[i];
+	}
+	delete [] e_Mij;
+	delete [] t_Mij;
+	N=0;
+	M=0;
+	e_Mij=0;
+	t_Mij=0; }
+}   
+
+template<typename R>  RawMatrix<R>::RawMatrix(const basicAC_F0 & args,int iinit)
+: init(iinit)
+{
+    args.SetNameParam();
+    emat = args[0];
+    
+    const E_Array & ee= *dynamic_cast<const E_Array*>((Expression) args[1]);
+    
+    int N=ee.size();
+    if (N==1)
+    {
+	C_F0 c0(ee[0]);
+	coef=to<KN_<R> >(ee[0]);
+	lig=0;
+	col=0;
+    }
+    
+    else if (N==3)
+    {
+	C_F0 c0(ee[0]),c1(ee[1]),c2(ee[2]);
+	coef=to<KN_<R> >(ee[2]);
+	lig=to<KN_<long> >(ee[0]);
+	col=to<KN_<long> >(ee[1]);
+	
+    }
+    
+    
+}
+template<typename R>  BlockMatrix<R>::BlockMatrix(const basicAC_F0 & args,int iinit)
+: init(iinit)
+{   
+    N=0;
+    M=0;
+    args.SetNameParam();
+    emat = args[0];
+    const E_Array & eMij= *dynamic_cast<const E_Array*>((Expression) args[1]);
+    N=eMij.size();
+    int err =0;
+    for (int i=0;i<N;i++)
+    {
+        const E_Array* emi= dynamic_cast<const E_Array*>((Expression)  eMij[i]);
+        if (!emi) err++;
+        else
+        { 
+	    if ( i==0) 
+		M = emi->size();
+	    else
+		if(M != emi->size()) err++;
+        }
+    }
+    if (err) {
+	CompileError(" Block matrix : [[ a, b, c], [ a,b,c ]] or Raw Matrix [a] or [ l, c, a ] ");
+    }
+    assert(N && M);
+    e_Mij = new Expression * [N];
+    t_Mij = new int * [N];
+    for (int i=0;i<N;i++)
+    {
+	const E_Array li= *dynamic_cast<const E_Array*>((Expression)  eMij[i]);
+	
+	e_Mij[i] =  new Expression [M];
+	t_Mij[i] = new int [M]; 
+	for (int j=0; j<M;j++)  
+	{
+	    C_F0 c_Mij(li[j]);
+	    Expression eij=c_Mij.LeftValue();
+	    aType rij = c_Mij.left();
+	    if ( rij == atype<long>() &&  eij->EvaluableWithOutStack() )
+	    {
+		long contm = GetAny<long>((*eij)(NullStack));
+		/*  prev  version
+		if(contm !=0) 
+		CompileError(" Block matrix , Just 0 matrix");
+		e_Mij[i][j]=0;
+		t_Mij[i][j]=0;*/
+		if(contm==0)
+		{
+		    e_Mij[i][j]=0;
+		    t_Mij[i][j]=0;
+		}
+		else if ( atype<R >()->CastingFrom(rij) )
+		{  		  // frev 2007 
+		    e_Mij[i][j]=to<R>(c_Mij);
+		    t_Mij[i][j]=7; //  just un scalaire 
+		}
+		else CompileError(" Block matrix , Just 0 matrix");
+	    }
+	    else if ( rij ==  atype<Matrice_Creuse<R> *>()) 
+	    {
+		e_Mij[i][j]=eij;
+		t_Mij[i][j]=1;
+	    } 
+	    else if ( rij ==  atype<Matrice_Creuse_Transpose<R> >()) 
+	    {
+		e_Mij[i][j]=eij;
+		t_Mij[i][j]=2;
+	    } 
+	    else if ( atype<KNM<R> *  >()->CastingFrom(rij) )
+	      {  //  before KN_ because KNM can be cast in KN_
+		  
+		  e_Mij[i][j]=to<KNM<R> * >(c_Mij);
+		  t_Mij[i][j]=5;
+	      }	    
+	    else if ( atype<KN_<R> >()->CastingFrom(rij) )
+	    {  
+		e_Mij[i][j]=to<KN_<R> >(c_Mij);
+		t_Mij[i][j]=3;
+		
+	    } 
+	    else if ( atype<Transpose<KN_<R> > >()->CastingFrom(rij) )
+	    {  
+		
+		e_Mij[i][j]=to<Transpose<KN_<R> > >(c_Mij);
+		t_Mij[i][j]=4;
+	    } 
+	    else if ( atype<Transpose< KNM<R> * > >()->CastingFrom(rij) )
+	    {  
+		
+		e_Mij[i][j]=to<Transpose<KNM<R> *> >(c_Mij);
+		t_Mij[i][j]=6;
+	    }
+	    else if ( atype<R >()->CastingFrom(rij) )
+	    {  		  // frev 2007 
+		e_Mij[i][j]=to<R>(c_Mij);
+		t_Mij[i][j]=7; //  just un scalaire 
+	    }
+	    
+	    else {  
+		
+		CompileError(" Block matrix ,  bad type in block matrix");
+	    }
+	    /*            else if   ( atype<map< pair<int,int>, R> * >()->CastingFrom(rij) ) 
+	    {
+		e_Mij[i][j]= to<map< pair<int,int>, R> *>(C_F0(eij,rij)).LeftValue();
+		t_Mij[i][j]=10;
+	    }*/
+	}
+	
+    }
+}
+
+template<typename RR>
+class  SetRawMatformMat : public OneOperator { 
+public:
+    typedef Matrice_Creuse<RR> *  A; // Warning  B type of  2 parameter 
+    typedef Matrice_Creuse<RR> *  R;
+    typedef E_Array B; //   A type of 1 parameter
+    
+    class CODE : public  E_F0 { public:
+	Expression Mat;
+	Expression lig;
+	Expression col;
+	Expression coef;
+	bool mi;    
+	    CODE(Expression a,const E_Array & tt)  
+		: Mat(a),
+		 mi(tt.MeshIndependent())
+	    {
+
+		    assert(&tt);
+		    if(tt.size()!=3) 
+			CompileError("Set raw matrix:  [ lg,col, a] = A (size !=3) ");
+		    if (    aatypeknlongp->CastingFrom(tt[0].left() ) //// for  compilation error with g++ 3.2.2 (4 times)
+			&&  aatypeknlongp->CastingFrom(tt[1].left() )
+			&&  atype<KN<RR>* >()->CastingFrom(tt[2].left() ) )
+			    {
+			      lig = aatypeknlongp->CastTo(tt[0]);
+			      col = aatypeknlongp->CastTo(tt[1]);
+			      coef = atype<KN<RR>* >()->CastTo(tt[2]);
+			    }      
+			    else 
+				CompileError(" we are waiting for [ lg,col,a] = A");
+    }
+	    
+	    AnyType operator()(Stack stack)  const 
+	    {
+		A  a=GetAny<A>((*Mat)(stack));
+		KN<long> *lg,*cl;
+		KN<RR> *cc;
+		lg = GetAny<KN<long>*>((*lig)(stack));
+		cl = GetAny<KN<long>*>((*col)(stack));
+		cc = GetAny<KN<RR>*>((*coef)(stack));
+		int n=a->N(),m=a->M();
+		map<pair<int,int>,RR> *M=new map<pair<int,int>,RR>;
+		if (n >0 && m>0 && a->A) 
+		{
+		    a->A->addMatTo(RR(1.),*M);
+		    // hack 
+		    (*M)[make_pair(n-1,m-1)]+=RR();
+		}
+		int kk = M->size();
+		lg->resize(kk);
+		cc->resize(kk);
+		cl->resize(kk);
+		int k=0;
+		typename map<pair<int,int>,RR>::const_iterator i;
+		//if (!a->sym)
+		 for (i=M->begin(); i != M->end();++i,++k)
+		  {  
+		    (*lg)[k]= i->first.first;
+		    (*cl)[k]= i->first.second;
+		    (*cc)[k]= i->second;
+		  }
+		    
+		delete M;
+		return SetAny<R>(a);
+	    } 
+	    bool MeshIndependent() const     {return  mi;} // 
+	    ~CODE() {}
+	    operator aType () const { return atype<R>();}    
+    }; // end sub class CODE
+    
+    
+public: // warning hack  A and B 
+	E_F0 * code(const basicAC_F0 & args) const 
+    { return  new CODE(t[1]->CastTo(args[1]),*dynamic_cast<const E_Array*>( t[0]->CastTo(args[0]).RightValue()));} 
+    SetRawMatformMat():   OneOperator(atype<R>(),atype<B>(),atype<A>())  {} // warning with A and B 
+    
+};
+
+
+R realC(Complex c) {return c.real();}
+R imagC(Complex c) {return c.imag();}
+template<int init>
+AnyType CopyMatC2R(Stack stack,Expression emat,Expression CR2eA)
+{
+    typedef Complex C; 
+    typedef double R; 
+    using namespace Fem2D;
+    Matrice_Creuse_C2R   CRMat =GetAny<Matrice_Creuse_C2R>((*CR2eA)(stack));
+    Matrice_Creuse<C> *Mat=CRMat; 
+    int cas = CRMat.cas; 
+    Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+    MatriceMorse<C> * mr=Mat->A->toMatriceMorse(false,false);
+    MatriceMorse<R> * mrr = 0;
+   // cout << " CopyMatC2R:  " << init << " " <<  sparse_mat <<endl;
+    if(cas==0) 
+        mrr = new MatriceMorse<R>(*mr,realC);
+    else if(cas==1) 
+        mrr = new MatriceMorse<R>(*mr,imagC);
+    else {
+         cout << " cas = " << cas <<endl;
+        ffassert(0); 
+    }
+    delete mr;
+    if(!init) sparse_mat->init() ; // ???? 
+    sparse_mat->A.master(mrr);
+    //ffassert(0);// a faire 
+    return sparse_mat;
+}
+
+template<typename R>  AnyType RawMatrix<R>::operator()(Stack stack) const
+{
+    MatriceMorse<R> * amorse =0; 
+    KN_<R> cc(GetAny< KN_<R>  >((*coef)(stack)));
+    int k= cc.N();
+    int n= k;
+    int m=n;
+    map< pair<int,int>, R> Aij;
+    bool sym=false;
+    if( lig && col)
+    {
+	KN_<long> lg(GetAny< KN_<long>  >((*lig)(stack)));
+	KN_<long> cl=(GetAny< KN_<long>  >((*col)(stack)));
+	n = lg.max()+1;
+	m = cl.max()+1;
+	ffassert( lg.N()==k && cl.N()==k && lg.min()>=0 && lg.max()>=0);
+	sym=false;
+	for(int i=0;i<k;++i)
+	    Aij[make_pair<int,int>(lg[i],cl[i])]+=cc[i];	
+    }
+    else
+    {
+	sym=true;
+	for(int i=0;i<n;++i)
+	    Aij[make_pair(i,i)]=cc[i];
+    }
+    //cout <<  " nxm  =" <<n<< "x" << m <<endl; 
+    amorse=  new MatriceMorse<R>(n,m,Aij,sym); 
+    if(verbosity)
+	cout << "  -- Raw Matrix    nxm  =" <<n<< "x" << m << " nb  none zero coef. " << amorse->nbcoef << endl;
+    
+    Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(stack));
+    if( !init) sparse_mat->init();
+    // sparse_mat->pUh=0;
+    // sparse_mat->pVh=0; 
+    sparse_mat->A.master(amorse);
+    sparse_mat->typemat=(amorse->n == amorse->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+    
+    if(verbosity>3) { cout << "  End Raw Matrix : " << endl;}
+    
+    return sparse_mat;   
+}
+template<typename R>  AnyType BlockMatrix<R>::operator()(Stack s) const
+{
+  typedef list<triplet<R,MatriceCreuse<R> *,bool> > * L;
+   KNM<L> Bij(N,M);
+   KNM<KNM_<R> * > Fij(N,M); 
+   KNM<bool> cnjij(N,M); 
+   KNM<R> Rij(N,M); //  to sto
+  
+   cnjij = false; 
+   KN<long> Oi(N+1), Oj(M+1);
+   if(verbosity>3) { cout << " Build Block Matrix : " << N << " x " << M << endl;}
+   Bij = (L) 0;
+   Oi = (long) 0;
+   Oj = (long)0;
+  for (int i=0;i<N;++i)
+   for (int j=0;j<M;++j)
+    {
+      Fij(i,j)=0;
+      Expression eij = e_Mij[i][j];
+      int tij=t_Mij[i][j];
+      if (eij) 
+      {
+        cnjij(i,j) = tij%2 == 0; 
+        AnyType e=(*eij)(s);
+        if (tij==1) Bij(i,j) = to( GetAny< Matrice_Creuse<R>* >( e)) ;
+        else if  (tij==2) Bij(i,j) = to( GetAny<Matrice_Creuse_Transpose<R> >(e));
+        else if (tij==3)  { KN_<R> x=GetAny< KN_<R>  >( e);  Fij(i,j) = new KNM_<R>(x,x.N(),1);}
+        else if (tij==4)  { KN_<R> x=GetAny< Transpose< KN_<R> >   >( e).t ;  Fij(i,j) = new KNM_<R>(x,1,x.N());}
+        else if (tij==5)  { KNM<R> * m= GetAny< KNM<R>*  >( e);  Fij(i,j) = new KNM_<R>(*m);}
+        else if (tij==6)  { KNM<R> * m= GetAny< Transpose< KNM<R>* >  >( e).t;  Fij(i,j) = new KNM_<R>(m->t()); }
+	else if (tij==7)   { Rij(i,j)=GetAny< R  >( e);  Fij(i,j) = new KNM_<R>(&(Rij(i,j)),1,1);}
+        
+   //     else if  (tij==3) {}
+        else {
+         cout << " Bug " << tij << endl;
+         ExecError(" Type sub matrix block unknown ");
+        }
+      }
+     }
+     //  compute size of matrix
+     int err=0;
+    for (int i=0;i<N;++i)
+     for (int j=0;j<M;++j) 
+       {
+        pair<long,long> nm(0,0);
+        
+       if (Bij(i,j)) 
+         nm = get_NM( *Bij(i,j));
+       else if(Fij(i,j)) 
+         nm = make_pair<long,long>(Fij(i,j)->N(), Fij(i,j)->M());
+          
+        if (( nm.first || nm.second)  && verbosity>3)
+          cout << " Block [ " << i << "," << j << " ]      =     " << nm.first << " x " << nm.second << " cnj = " << cnjij(i,j) << endl;
+        if (nm.first)
+          {
+          if ( Oi(i+1) ==0 )  Oi(i+1)=nm.first;
+          else  if(Oi(i+1) != nm.first)
+            { 
+                 err++;
+                 cerr <<"Error Block Matrix,  size sub matrix" << i << ","<< j << " n (old) "  << Oi(i+1) 
+                       << " n (new) " << nm.first << endl;
+
+            }
+          }
+          if(nm.second) 
+          {  
+          if   ( Oj(j+1) ==0) Oj(j+1)=nm.second;
+          else   if(Oj(j+1) != nm.second) 
+            { 
+              cerr <<"Error Block Matrix,  size sub matrix" << i << ","<< j << " m (old) "  << Oj(j+1) 
+                   << " m (new) " << nm.second << endl;
+              err++;}
+          }
+        }
+
+    if (err)    ExecError("Error Block Matrix,  size sub matrix");
+    //  gestion of zero block ????
+    
+    for (int j=0;j<M;++j)
+    {  if(verbosity>9) cout << j << " colum size" << Oj(j+1) << endl;
+        if   ( Oj(j+1) ==0) {
+            Oj(j+1)=1;
+            if( Oj(j+1) !=1)  err++;}
+    }
+    for (int i=0;i<N;++i)
+    {
+        if(verbosity>9) cout << i << " row size" << Oi(i+1) << endl;
+        if   ( Oi(i+1) ==0) {
+               Oi(i+1)=1;
+               if( Oi(i+1) !=1)  err++;}
+    }
+    if (err)    ExecError("Error Block Matrix with  0 line or  0 colomn..");
+   
+
+   
+    
+
+//  cout << "Oi = " <<  Oi << endl;
+//  cout << "Oj = " <<  Oj << endl;
+
+    for (int i=0;i<N;++i)
+      Oi(i+1) += Oi(i);
+    for (int j=0;j<M;++j) // correct 10/01/2007 FH 
+      Oj(j+1) += Oj(j);// correct 07/03/2010 FH
+  long n=Oi(N),m=Oj(M);
+  if(verbosity>3)
+   {
+     cout << "     Oi = " <<  Oi << endl;
+     cout << "     Oj = " <<  Oj << endl;
+  }
+  MatriceMorse<R> * amorse =0; 
+{
+   map< pair<int,int>, R> Aij;
+    for (int i=0;i<N;++i)
+     for (int j=0;j<M;++j) 
+       if (Bij(i,j)) 
+         {
+           if(verbosity>3)
+             cout << "  Add  Block S " << i << "," << j << " =  at " << Oi(i) << " x " << Oj(j) << " conj = " << cnjij(i,j) << endl;
+           BuildCombMat(Aij,*Bij(i,j),false,Oi(i),Oj(j),cnjij(i,j));
+         }
+       else if (Fij(i,j))
+        {
+           if(verbosity>3)
+             cout << "  Add  Block F " << i << "," << j << " =  at " << Oi(i) << " x " << Oj(j) << endl;
+           BuildCombMat(Aij,*Fij(i,j),Oi(i),Oj(j),R(1.),cnjij(i,j));// BuildCombMat
+        }
+        
+           
+  amorse=  new MatriceMorse<R>(n,m,Aij,false); 
+  }
+  if(verbosity)
+     cout << "  -- Block Matrix NxM = " << N << "x" << M << "    nxm  =" <<n<< "x" << m << " nb  none zero coef. " << amorse->nbcoef << endl;
+ 
+  Matrice_Creuse<R> * sparse_mat =GetAny<Matrice_Creuse<R>* >((*emat)(s));
+  if(!init) sparse_mat->init();
+  //sparse_mat->pUh=0;
+  // sparse_mat->pVh=0; 
+  sparse_mat->A.master(amorse);
+  sparse_mat->typemat=(amorse->n == amorse->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+                
+     
+  // cleanning    
+  for (int i=0;i<N;++i)
+   for (int j=0;j<M;++j)
+    if(Bij(i,j)) delete Bij(i,j);
+    else if(Fij(i,j))  delete Fij(i,j);  
+   if(verbosity>3) { cout << "  End Build Blok Matrix : " << endl;}
+   
+ return sparse_mat;  
+
+}
+
+template<class R>
+class minusMat { public:
+    list<triplet<R,MatriceCreuse<R> *,bool> >  *l;
+    minusMat(list<triplet<R,MatriceCreuse<R> *,bool> > *ll):
+	l(new list<triplet<R,MatriceCreuse<R> *,bool> >(*ll) )
+      {
+	    typedef typename list<triplet<R,MatriceCreuse<R> *,bool> >::iterator lci;
+	    for (lci i= l->begin();i !=l->end();++i)
+		i->first*= R(-1);
+      }
+};
+
+template<class R>
+AnyType mM2L3 (Stack , const AnyType & pp)
+{
+    minusMat<R> mpp(to(GetAny<Matrice_Creuse<R> *>(pp)));
+    return SetAny<minusMat<R> >(mpp);
+}
+/* template<class R>
+AnyType mmM2L3 (Stack , const AnyType & pp)
+{
+    minusMat<R> &  p(GetAny<minusMat<R> >(pp));
+    minusMat<R> mpp(p.l);
+    delete  p.l;
+    return mpp.l;
+}
+
+template<class R>
+AnyType mmM2L3c (Stack , const AnyType & pp)
+{
+    list<triplet<R,MatriceCreuse<R> *,bool> >  *  p(GetAny<minusMat<R> >(pp))
+    minusMat<R> mpp(p.l);
+    delete  p.l;
+    return mpp.l;
+}
+*/
+template <class R>
+void AddSparseMat()
+{
+// aType tkrp = atype<KN<R> *>(); 
+ SetMatrix_Op<R>::btype = Dcl_Type<const  SetMatrix_Op<R> * >();
+ Dcl_Type<TheDiagMat<R> >();
+ Dcl_Type<TheCoefMat<R> >(); // Add FH oct 2005
+ Dcl_Type< map< pair<int,int>, R> * >(); // Add FH mars 2005 
+ Dcl_Type<  minusMat<R>  >(); // Add FJH mars 2007
+ 
+ basicForEachType * t_MC=atype<  Matrice_Creuse<R>* >();
+// basicForEachType * t_MCt=atype<  Matrice_Creuse_Transpose<R> >();
+// basicForEachType * t_lM=atype< list<triplet<R,MatriceCreuse<R> *,bool> > * >();
+// basicForEachType * t_nM=atype<  minusMat<R> >();
+ 
+ basicForEachType * t_MM=atype<map< pair<int,int>, R> * >();
+ 
+TheOperators->Add("*", 
+        new OneBinaryOperator<Op2_mulvirtAv<typename VirtualMatrice<R>::plusAx,Matrice_Creuse<R>*,KN_<R> > >,
+        new OneBinaryOperator<Op2_mulvirtAv<typename VirtualMatrice<R>::plusAtx,Matrice_Creuse_Transpose<R>,KN_<R> > >,
+        new OneBinaryOperator<Op2_mulvirtAv<typename VirtualMatrice<R>::solveAxeqb,Matrice_Creuse_inv<R>,KN_<R> > >     
+        );
+
+/*if(0)
+TheOperators->Add("*", 
+        new OneBinaryOperator<Op2_mulvirtAv<typename VirtualMatrice<R>::plusAx,Matrice_Creuse<R>*,KN_<R> > >( 0  ,tkrp),
+        new OneBinaryOperator<Op2_mulvirtAv<typename VirtualMatrice<R>::plusAtx,Matrice_Creuse_Transpose<R>,KN_<R> > >( 0 ,tkrp),
+        new OneBinaryOperator<Op2_mulvirtAv<typename VirtualMatrice<R>::solveAxeqb,Matrice_Creuse_inv<R>,KN_<R> > >( 0 ,tkrp)     
+        );
+*/        
+TheOperators->Add("^", new OneBinaryOperatorA_inv<R>());
+  
+// matrix new code   FH (Houston 2004)        
+ TheOperators->Add("=",
+//       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const MatrixInterpolation::Op*,E_F_StackF0F0>(SetMatrixInterpolation),
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const Matrix_Prod<R,R>,E_F_StackF0F0>(ProdMat<R,R,R,1>),
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,KN<R> *,E_F_StackF0F0>(DiagMat<R,1>),
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,Matrice_Creuse_Transpose<R>,E_F_StackF0F0>(CopyTrans<R,R,1>), 
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,Matrice_Creuse<R>*,E_F_StackF0F0>(CopyMat<R,R,1>) ,
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,KNM<R>*,E_F_StackF0F0>(MatFull2Sparse<R,1>) ,
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,map< pair<int,int>, R> * ,E_F_StackF0F0>(MatMap2Sparse<R,1>) ,
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,list<triplet<R,MatriceCreuse<R> *,bool> > *,E_F_StackF0F0>(CombMat<R,1>) ,
+       new OneOperatorCode<BlockMatrix1<R> >()
+       
+       );
+       
+ TheOperators->Add("<-",
+       new OneOperatorCode<BlockMatrix<R> >(),
+//       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const MatrixInterpolation::Op*,E_F_StackF0F0>(SetMatrixInterpolation),
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const Matrix_Prod<R,R>,E_F_StackF0F0>(ProdMat<R,R,R,0>),
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,KN<R> *,E_F_StackF0F0>(DiagMat<R,0>)  ,
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,Matrice_Creuse_Transpose<R>,E_F_StackF0F0>(CopyTrans<R,R,0>), 
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,Matrice_Creuse<R>*,E_F_StackF0F0>(CopyMat<R,R,0>) ,
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,KNM<R>*,E_F_StackF0F0>(MatFull2Sparse<R,0>) ,
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,map< pair<int,int>, R> * ,E_F_StackF0F0>(MatMap2Sparse<R,0>) ,
+       new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,list<triplet<R,MatriceCreuse<R> *,bool> > *,E_F_StackF0F0>(CombMat<R,0>)
+      
+       
+       );
+TheOperators->Add("*", 
+        new OneBinaryOperator<Op2_pair<Matrix_Prod<R,R>,Matrice_Creuse<R>*,Matrice_Creuse<R>*> >,
+        new OneBinaryOperator<Op2_pair<Matrix_Prod<R,R>,Matrice_Creuse_Transpose<R>,Matrice_Creuse<R>* > >, 
+        new OneBinaryOperator<Op2_pair<Matrix_Prod<R,R>,Matrice_Creuse_Transpose<R>,Matrice_Creuse_Transpose<R> > >,
+        new OneBinaryOperator<Op2_pair<Matrix_Prod<R,R>,Matrice_Creuse<R>*,Matrice_Creuse_Transpose<R> > > ,
+        new OneBinaryOperator<Op2_ListCM<R> >  , 
+        new OneBinaryOperator<Op2_ListMC<R> >  ,
+	new OneBinaryOperator<Op2_ListCMt<R> >  , 
+        new OneBinaryOperator<Op2_ListMtC<R> >  
+		  
+        );
+TheOperators->Add("+", 
+        new OneBinaryOperator<Op2_ListCMCMadd<R> >,
+        new OneBinaryOperator<Op2_ListCMMadd<R> >,
+        new OneBinaryOperator<Op2_ListMCMadd<R> >,
+//	new OneBinaryOperator<Op2_ListCMCMadd<R> >(t_MCt,t_lM),
+//	new OneBinaryOperator<Op2_ListCMCMadd<R> >(t_MC,t_lM),
+        new OneBinaryOperator<Op2_ListMMadd<R> >
+       
+       ); 
+ TheOperators->Add("-",  
+	 new OneUnaryOperator<Op1_LCMd<R> >
+     );
+ Add<Matrice_Creuse<R> *>("n",".",new OneOperator1<long,Matrice_Creuse<R> *>(get_mat_n<R>) );
+ Add<Matrice_Creuse<R> *>("m",".",new OneOperator1<long,Matrice_Creuse<R> *>(get_mat_m<R>) );
+ Add<Matrice_Creuse<R> *>("nbcoef",".",new OneOperator1<long,Matrice_Creuse<R> *>(get_mat_nbcoef<R>) );
+ Add<Matrice_Creuse<R> *>("nnz",".",new OneOperator1<long,Matrice_Creuse<R> *>(get_mat_nbcoef<R>) );
+ Add<Matrice_Creuse<R> *>("size",".",new OneOperator1<long,Matrice_Creuse<R> *>(get_mat_nbcoef<R>) );
+    
+ 
+ Add<Matrice_Creuse<R> *>("diag",".",new OneOperator1<TheDiagMat<R> ,Matrice_Creuse<R> *>(thediag<R>) );
+ Add<Matrice_Creuse<R> *>("coef",".",new OneOperator1<TheCoefMat<R> ,Matrice_Creuse<R> *>(thecoef<R>) );
+
+// Add<Matrice_Creuse<R> *>("setdiag",".",new OneOperator2<long,Matrice_Creuse<R> *,KN<R> *>(set_diag<R>) );
+ TheOperators->Add("=", new OneOperator2<KN<R>*,KN<R>*,TheDiagMat<R> >(get_mat_daig<R>) );
+ TheOperators->Add("=", new OneOperator2<TheDiagMat<R>,TheDiagMat<R>,KN<R>*>(set_mat_daig<R>) );
+ 
+// TheOperators->Add("=", new OneOperator2<KN<R>*,KN<R>*,TheDiagMat<R> >(get_mat_daig<R>) );
+// TheOperators->Add("=", new OneOperator2<TheDiagMat<R>,TheDiagMat<R>,KN<R>*>(set_mat_daig<R>) );
+// ADD oct 2005
+ TheOperators->Add("=", new OneOperator2<KN<R>*,KN<R>*,TheCoefMat<R> >(get_mat_coef<R>) );
+ TheOperators->Add("=", new OneOperator2<TheCoefMat<R>,TheCoefMat<R>,KN<R>*>(set_mat_coef<R>) );
+ 
+// TheOperators->Add("=", new OneOperator2<KN<R>*,KN<R>*,TheCoefMat<R> >(get_mat_coef<R>) );
+// TheOperators->Add("=", new OneOperator2<TheCoefMat<R>,TheCoefMat<R>,KN<R>*>(set_mat_coef<R>) );
+ 
+ Global.Add("set","(",new SetMatrix<R>);
+ //Global.Add("psor","(",new  OneOperatorCode<Psor<R> > );
+ 
+ atype<Matrice_Creuse<R> * >()->Add("(","",new OneOperator3_<R*,Matrice_Creuse<R> *,long,long >(get_elementp2mc<R>));
+ 
+ atype<KNM<R>*>()->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,KNM<R>*,Inv_KN_long,Inv_KN_long >(Matrixfull2mapIJ_inv<R>));
+ atype<KNM<R>*>()->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,KNM<R>*,KN_<long>,KN_<long> >(Matrixfull2mapIJ<R>));
+ 
+ atype<outProduct_KN_<R>*>()->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,outProduct_KN_<R>*,Inv_KN_long,Inv_KN_long >(Matrixoutp2mapIJ_inv<R>));
+ atype<outProduct_KN_<R>*>()->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,outProduct_KN_<R>*,KN_<long>,KN_<long> >(Matrixoutp2mapIJ<R>));
+
+
+ TheOperators->Add("=", new SetRawMatformMat<R>);
+
+
+
+ t_MM->Add("(","",  new OneOperator3_<map< pair<int,int>, R> *,map< pair<int,int>, R> *,Inv_KN_long,Inv_KN_long >(Matrixmapp2mapIJ1<R>));
+ t_MM->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,map< pair<int,int>, R> *,KN_<long>,KN_<long> >(Matrixmapp2mapIJ<R>));
+
+ t_MC->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,map< pair<int,int>, R> *,Inv_KN_long,Inv_KN_long >(Matrixmapp2mapIJ1<R>,t_MC));
+ t_MC->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,map< pair<int,int>, R> *,KN_<long>,KN_<long> >(Matrixmapp2mapIJ<R>,t_MC));
+
+ //atype<outProduct_KN_<R>*>()->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,map< pair<int,int>, R> *,Inv_KN_long,Inv_KN_long >(Matrixmapp2mapIJ1<R>),t_lM);
+ //atype<outProduct_KN_<R>*>()->Add("(","",new OneOperator3_<map< pair<int,int>, R> *,map< pair<int,int>, R> *,KN_<long>,KN_<long> >(Matrixmapp2mapIJ<R>),t_lM);
+
+ 
+//map< pair<int,int>, R> * ttt=   (0);
+
+   //   ; 
+ map_type[typeid(map< pair<int,int>, R> *).name()]->AddCast(
+     new E_F1_funcT<map< pair<int,int>, R> *,KNM<R>* >(Matrixfull2map<R>),
+     new E_F1_funcT<map< pair<int,int>, R> *,outProduct_KN_<R>* >(Matrixoutp2map<R>),
+     new E_F1_funcT<map< pair<int,int>, R> *,Matrice_Creuse<R>* >(MatriceCreuse2map<R>)
+
+       ); 
+
+ map_type[typeid(list<triplet<R,MatriceCreuse<R> *,bool> > *).name()]->AddCast(
+     new E_F1_funcT<list<triplet<R,MatriceCreuse<R> *,bool> > *,Matrice_Creuse<R>* >(M2L3<R>),
+     new E_F1_funcT<list<triplet<R,MatriceCreuse<R> *,bool> > *,Matrice_Creuse_Transpose<R> >(tM2L3<R>),						    
+     new E_F1_funcT<list<triplet<R,MatriceCreuse<R> *,bool> > *,minusMat<R> >(mM2L3<R> )
+     );
+ /*
+ map_type[typeid(minusMat<R>).name()]->AddCast( 
+	new E_F1_funcT<minusMat<R>,list<triplet<R,MatriceCreuse<R> *,bool> > * >(mmM2L3<R> )
+	//new E_F1_funcT<minusMat<R>,Matrice_Creuse<R>*  > * >(mmM2L3c<R> ),
+	//new E_F1_funcT<minusMat<R>,Matrice_Creuse_Transpose<R> > * >(mmM2L3ct<R> )
+						
+      );
+*/
+
+
+
+      
+//  --- end  
+}
+
+
+//extern Map_type_of_map map_type_of_map ; //  to store te type 
+//extern Map_type_of_map map_pair_of_type ; //  to store te type 
+extern int lineno(); 
+class  PrintErrorCompile : public OneOperator {
+    public: 
+    const char * cmm;
+    E_F0 * code(const basicAC_F0 & ) const 
+     { ErrorCompile(cmm,lineno());
+      return 0;} 
+    PrintErrorCompile(const char * cc): OneOperator(map_type[typeid(R).name()]),cmm(cc){}
+
+};
+
+class PrintErrorCompileIM :  public E_F0info { public:  
+ typedef double  Result;
+ static E_F0 *   f(const basicAC_F0 & args)  
+    {   
+     lgerror("\n\n *** change interplotematrix in interpole.\n  *** Bad name in previous version,\n *** sorry FH.\n\n");
+     return 0;  }   
+    static ArrayOfaType  typeargs() {return  ArrayOfaType(true);}
+    operator aType () const { return atype<double>();} 
+
+};
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+DefSparseSolverSym<double>::SparseMatSolver SparseMatSolverSym_R ; ;
+DefSparseSolverSym<Complex>::SparseMatSolver SparseMatSolverSym_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    DefSparseSolverSym<double>::solver =SparseMatSolverSym_R;
+    DefSparseSolverSym<Complex>::solver =SparseMatSolverSym_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+    return  true;
+}
+
+
+bool SparseDefault()
+{
+    return TypeSolveMat::SparseSolver== TypeSolveMat::defaultvalue;
+}
+
+bool Have_UMFPACK_=false;
+bool Have_UMFPACK() { return Have_UMFPACK_;}
+//OneOperator0<bool> *TheSetDefaultSolver=0; // to change the SetDefaultSolver
+void  init_lgmat() 
+
+{
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  SparseMatSolverSym_R= DefSparseSolverSym<double>::solver;
+  SparseMatSolverSym_C= DefSparseSolverSym<Complex>::solver;
+
+  
+  Dcl_Type<const  MatrixInterpolation<pfes>::Op *>(); 
+  Dcl_Type<const  MatrixInterpolation<pfes3>::Op *>(); 
+
+  map_type_of_map[make_pair(atype<Matrice_Creuse<double>* >(),atype<double*>())]=atype<Matrice_Creuse<double> *>();
+  map_type_of_map[make_pair(atype<Matrice_Creuse<double>* >(),atype<Complex*>())]=atype<Matrice_Creuse<Complex> *>();
+  AddSparseMat<double>();
+  AddSparseMat<Complex>();
+  
+  Add<const MatrixInterpolation<pfes>::Op *>("<-","(", new MatrixInterpolation<pfes>);
+  Add<const MatrixInterpolation<pfes>::Op *>("<-","(", new MatrixInterpolation<pfes>(1));
+  Add<const MatrixInterpolation<pfes>::Op *>("<-","(", new MatrixInterpolation<pfes3>);
+  Add<const MatrixInterpolation<pfes>::Op *>("<-","(", new MatrixInterpolation<pfes3>(1,1));
+    
+    Dcl_Type<const  RestrictArray<pfes>::Op *>();
+    Dcl_Type<const  RestrictArray<pfes3>::Op *>();
+  //  Add<const RestrictArray<pfes>::Op *>("<-","(", new RestrictArray<pfes>);
+  //  Add<const RestrictArray<pfes3>::Op *>("<-","(", new RestrictArray<pfes3>);
+  
+  Global.Add("restrict","(",new RestrictArray<pfes>);// FH Jan 2014
+  Global.Add("restrict","(",new RestrictArray<pfes3>);// FH Jan 2014
+    
+  TheOperators->Add("=",
+                      new OneOperator2_<KN<long>*,KN<long>*,const RestrictArray<pfes>::Op*,E_F_StackF0F0>(SetRestrict<pfes,1>),
+                      new OneOperator2_<KN<long>*,KN<long>*,const RestrictArray<pfes3>::Op*,E_F_StackF0F0>(SetRestrict<pfes3,1>)
+                      );
+    TheOperators->Add("<-",
+                      new OneOperator2_<KN<long>*,KN<long>*,const RestrictArray<pfes>::Op*,E_F_StackF0F0>(SetRestrict<pfes,0>),
+                      new OneOperator2_<KN<long>*,KN<long>*,const RestrictArray<pfes3>::Op*,E_F_StackF0F0>(SetRestrict<pfes3,0>)
+                      );
+  
+
+  Global.Add("interpolate","(",new MatrixInterpolation<pfes>);
+  Global.Add("interpolate","(",new MatrixInterpolation<pfes>(1));
+  Global.Add("interpolate","(",new MatrixInterpolation<pfes3>);
+  Global.Add("interpolate","(",new MatrixInterpolation<pfes3>(1,1));
+  Global.Add("interplotematrix","(",new  OneOperatorCode<PrintErrorCompileIM>);
+  zzzfff->Add("mapmatrix",atype<map< pair<int,int>, double> *>());
+  zzzfff->Add("Cmapmatrix",atype<map< pair<int,int>, Complex> *>()); // a voir
+  
+  Global.Add("defaulttoGMRES","(",new OneOperator0<bool>(SetGMRES));
+  Global.Add("defaulttoCG","(",new OneOperator0<bool>(SetCG));
+  Global.New("havesparsesolver",CVariable<bool>(SparseDefault));
+  Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  
+  Dcl_Type< Resize<Matrice_Creuse<double> > > ();
+  
+  Add<Matrice_Creuse<double> *>("resize",".",new OneOperator1< Resize<Matrice_Creuse<double>  >,Matrice_Creuse<double> *>(to_Resize));
+  Add<Resize<Matrice_Creuse<double> > >("(","",new OneOperator3_<Matrice_Creuse<double>  *,Resize<Matrice_Creuse<double>  > , long, long  >(resize2)); 
+  // add missing in
+ Dcl_Type< Resize<Matrice_Creuse<Complex> > > ();
+ Add<Matrice_Creuse<Complex> *>("resize",".",new OneOperator1< Resize<Matrice_Creuse<Complex>  >,Matrice_Creuse<Complex> *>(to_Resize));
+ Add<Resize<Matrice_Creuse<Complex> > >("(","",new OneOperator3_<Matrice_Creuse<Complex>  *,Resize<Matrice_Creuse<Complex>  > , long, long  >(resize2));   
+ 
+ 
+ //Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefaultSolver));
+ 
+ // pour compatibiliter 
+ 
+ TheOperators->Add("=",
+		   new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const MatrixInterpolation<pfes>::Op*,E_F_StackF0F0>(SetMatrixInterpolation<1>),
+		   new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const MatrixInterpolation<pfes3>::Op*,E_F_StackF0F0>(SetMatrixInterpolation3<1>)
+		   );
+
+    
+ TheOperators->Add("<-",
+		   new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const MatrixInterpolation<pfes>::Op*,E_F_StackF0F0>(SetMatrixInterpolation<0>),
+		   new OneOperator2_<Matrice_Creuse<R>*,Matrice_Creuse<R>*,const MatrixInterpolation<pfes3>::Op*,E_F_StackF0F0>(SetMatrixInterpolation3<0>)
+		   );
+ // construction of complex matrix form a double matrix
+ TheOperators->Add("=", new OneOperator2_<Matrice_Creuse<Complex>*,Matrice_Creuse<Complex>*,Matrice_Creuse<double>*,E_F_StackF0F0>(CopyMat<R,Complex,1>)
+		   );
+ 
+ TheOperators->Add("<-", new OneOperator2_<Matrice_Creuse<Complex>*,Matrice_Creuse<Complex>*,Matrice_Creuse<double>*,E_F_StackF0F0>(CopyMat<R,Complex,0>)
+		   );
+ // Global.Add("imag","(",new OneOperator1_<double,Complex>(Imag));
+ //   Add<double>("<--","(",new OneOperator1_<double,Complex>(Real));
+    Dcl_Type<Matrice_Creuse_C2R>(); 
+    Add<Matrice_Creuse<Complex>*>("re",".",new OneOperator1<Matrice_Creuse_C2R ,Matrice_Creuse<Complex>* >(Build_Matrice_Creuse_C2R<0> ));
+    Add<Matrice_Creuse<Complex>*>("im",".",new OneOperator1<Matrice_Creuse_C2R ,Matrice_Creuse<Complex>* >(Build_Matrice_Creuse_C2R<1> ));
+    // construction of complex matrix form a double matrix
+    TheOperators->Add("=", new OneOperator2_<Matrice_Creuse<Complex>*,Matrice_Creuse<double>*,Matrice_Creuse_C2R,E_F_StackF0F0>(CopyMatC2R<1>));
+
+    TheOperators->Add("<-", new OneOperator2_<Matrice_Creuse<Complex>*,Matrice_Creuse<double>*,Matrice_Creuse_C2R,E_F_StackF0F0>(CopyMatC2R<0>));
+
+ extern  void init_UMFPack_solver();
+ init_UMFPack_solver();
+}
+
+int Data_Sparse_Solver_version() { return VDATASPARSESOLVER;}
diff --git a/src/fflib/lgmesh.cpp b/src/fflib/lgmesh.cpp
new file mode 100644
index 0000000..b4ce749
--- /dev/null
+++ b/src/fflib/lgmesh.cpp
@@ -0,0 +1,1937 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+/*
+#include  <iostream>
+#include  <cfloat>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "rgraph.hpp"
+
+#include "RNM.hpp"
+#include "fem.hpp"
+
+
+#include "FESpacen.hpp"
+#include "FESpace.hpp" 
+
+
+//#include "fem3.hpp"
+#include "MeshPoint.hpp"
+#include <complex>
+#include "Operator.hpp" 
+
+#include <set>
+#include <vector>
+#include <fstream>
+
+#include "lex.hpp"
+
+#include "Mesh2.h"
+
+#include "BamgFreeFem.hpp"
+#include "lgfem.hpp"
+*/
+
+#include "ff++.hpp"
+#include "AFunction_ext.hpp"
+
+
+#include "lgmesh.hpp"
+
+using Fem2D::Mesh;
+using Fem2D::MeshPoint;
+
+extern bool NoWait; 
+
+typedef Mesh * pmesh;
+
+
+
+
+class classBuildMesh :  public E_F0mps { public:  
+ 
+   typedef pmesh  Result;
+
+   static basicAC_F0::name_and_type name_param[] ;
+   static const int n_name_param =2;
+   
+    Expression nargs[n_name_param];
+   
+   Expression getborders;
+   
+   long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+   bool arg(int i,Stack stack,bool a) const{ return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+    
+    classBuildMesh(const basicAC_F0 & args) 
+    {   
+      args.SetNameParam(n_name_param,name_param,nargs);
+      getborders=to<const E_BorderN *>(args[0]); 
+     }   
+     
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<const E_BorderN *>());}
+    static  E_F0 * f(const basicAC_F0 & args){ return new classBuildMesh(args);} 
+    AnyType operator()(Stack s) const ;
+    operator aType () const { return atype<Result>();} 
+
+};
+
+class classBuildMeshArray :  public E_F0mps { public:  
+    
+    typedef pmesh  Result;
+    
+    //static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =0;
+    
+//Expression nargs[n_name_param];
+    
+    Expression env,ent,enbe;
+    Expression ev,et,ebe;
+    
+    
+  
+    
+     classBuildMeshArray(const basicAC_F0 & args) 
+    {   
+	args.SetNameParam(0,0,0);
+	env=to<long>(args[0]); 
+	ent=to<long>(args[1]); 
+	enbe=to<long>(args[2]); 
+	ev=to<KNM_<double> >(args[3]); 
+	et=to<KNM_<long> >(args[4]); 
+	ebe=to<KNM_<long> >(args[5]);
+	
+    }   
+    
+    static ArrayOfaType  typeargs() { 
+	
+	aType ffint =atype< long >();
+	aType ffMi =atype< KNM_<long> >();
+	aType ffMr =atype< KNM_<double> >();
+	return  ArrayOfaType(ffint,ffint,ffint,ffMr,ffMi,ffMi);}
+    
+    static  E_F0 * f(const basicAC_F0 & args){ return new classBuildMeshArray(args);} 
+    AnyType operator()(Stack s) const {
+	long nv = GetAny<long >((*env)(s));
+	long nt = GetAny<long >((*ent)(s));
+	long nbe = GetAny<long >((*enbe)(s));
+	KNM_<double> xyl( GetAny<KNM_<double> >((*ev)(s)));
+	KNM_<long> nut(	GetAny<KNM_<long> >((*et)(s)));	 
+	KNM_<long> nube( GetAny<KNM_<long> >((*ebe)(s)));	
+	using  Fem2D::Vertex;
+	using  Fem2D::R2;
+	using  Fem2D::BoundaryEdge;
+	using  Fem2D::Mesh;
+	using  Fem2D::MeshPointStack;
+
+	//   Mesh(int nbv,int nbt,int nbeb,Vertex *v,Triangle *t,BoundaryEdge  *b); 
+	cout << nv << " " << nt << " " << nbe << endl;
+	cout << xyl.N() << " "<< xyl.M() << endl;
+	cout << nut.N() << " "<< nut.M() << endl;
+	cout << nube.N() << " "<< nube.M() << endl;
+	ffassert(xyl.N() >=nv && xyl.M() >= 3);
+	ffassert(nut.N() >=nt && nut.M() >= 4);
+	ffassert(nube.N() >=nbe && nube.M() >= 3);
+	Vertex *v= new Vertex [nv];
+	Triangle *t= new Triangle[nt];
+	BoundaryEdge *b = new BoundaryEdge[nbe];
+	
+	for(int i=0;i<nv;++i)
+	  {
+	    v[i].x = xyl(i,0);
+	    v[i].y = xyl(i,1);
+	    v[i].lab = xyl(i,2);	    
+	  }
+	for(int i=0;i<nt;++i)
+	    t[i].set(v,nut(i,0),nut(i,1),nut(i,2),nut(i,3));
+	for(int i=0;i<nbe;++i)
+	    b[i].set(v,nube(i,0),nube(i,1),nube(i,2));
+	  
+	
+	Mesh * pth= new Mesh(nv,nt,nbe,v,t,b);
+	if(verbosity) cout << "  -- BuildMesh " << pth << " " << nv << " " << nt << " " << nbe << endl; 
+	R2 Pn,Px;
+	pth->BoundingBox(Pn,Px);
+	if(!pth->quadtree)
+	    pth->quadtree=new Fem2D::FQuadTree(pth,Pn,Px,pth->nv);
+	
+	
+	return Add2StackOfPtr2FreeRC(s,pth);//  07/2008 FH	
+	
+	
+    }
+    operator aType () const { return atype<Result>();} 
+    
+};
+
+
+basicAC_F0::name_and_type  classBuildMesh::name_param[]= {
+    {  "nbvx", &typeid(long)} ,
+    {"fixeborder", &typeid(bool)}  
+};
+// modif aout 2007
+class BuildMeshFile :  public E_F0mps { public:  
+    
+    typedef pmesh  Result;
+    
+    static basicAC_F0::name_and_type name_param[] ;
+    static const int n_name_param =1;
+    
+    Expression nargs[n_name_param];
+    
+    Expression getfilename;
+    
+    long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+    
+    BuildMeshFile(const basicAC_F0 & args) 
+    {   
+	args.SetNameParam(n_name_param,name_param,nargs);
+	getfilename=to<string* >(args[0]); 
+    }   
+    
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<string *>());}
+    static  E_F0 * f(const basicAC_F0 & args){ return new BuildMeshFile(args);} 
+    AnyType operator()(Stack s) const ;
+    operator aType () const { return atype<Result>();} 
+    
+};
+
+basicAC_F0::name_and_type  BuildMeshFile::name_param[]= {
+    {  "nbvx", &typeid(long) }
+};
+// fin modif 2007 
+
+class MoveMesh :  public E_F0mps { public:  
+ 
+   typedef pmesh  Result;
+   Expression getmesh;
+   Expression U,V;
+   int nbsol;    
+    vector<Expression> sol;
+   
+    MoveMesh(const basicAC_F0 & args) :nbsol(args.size()-2),sol(args.size()-2)
+    {   
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+      args.SetNameParam();
+      getmesh=to<pmesh>(args[0]); 
+      const E_Array * a = dynamic_cast<const E_Array *>(args[1].LeftValue());
+      
+      ffassert(a);
+      if (a->size() !=2) CompileError("movemesh(Th,[u,v],...) need 2 componate in array ",atype<pmesh>());
+      U=to<double>( (*a)[0]);
+      V=to<double>( (*a)[1]);
+      
+      for (int i=2;i<args.size();i++)
+        sol[i-2]=to<double>(args[i]);      
+    }   
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh>(),atype<E_Array>(),true);}
+    static  E_F0 * f(const basicAC_F0 & args){ return new MoveMesh(args);} 
+    AnyType operator()(Stack s) const ;
+      operator aType () const { return atype<Result>();} 
+
+};
+
+class SplitMesh :  public E_F0mps { public:  
+ 
+   typedef pmesh  Result;
+   Expression getmesh;
+   Expression U;
+   
+    SplitMesh(const basicAC_F0 & args) 
+    {   
+      args.SetNameParam();
+      getmesh=to<pmesh>(args[0]); 
+      U = to<long>(args[1]);      
+     }   
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh>(),atype<long>());}
+    static  E_F0 * f(const basicAC_F0 & args){ return new SplitMesh(args);} 
+    AnyType operator()(Stack s) const ;
+    operator aType () const { return atype<Result>();} 
+
+};
+
+class SaveMesh :  public E_F0 { public:  
+ 
+   typedef pmesh  Result;
+   Expression getmesh;
+   Expression filename; 
+   Expression xx,yy,zz;  
+   SaveMesh(const basicAC_F0 & args) 
+    {   
+      xx=0;
+      yy=0;
+      zz=0;
+      args.SetNameParam();
+      getmesh=to<pmesh>(args[0]); 
+      filename=to<string*>(args[1]); 
+      if (args.size() >2) 
+        {
+          const E_Array * a = dynamic_cast<const E_Array *>(args[2].LeftValue());
+          if (!a) CompileError("savemesh(Th,\"filename\",[u,v,w],...");
+          int k=a->size() ;
+         // cout << k << endl;
+          if ( k!=2 && k !=3) CompileError("savemesh(Th,\"filename\",[u,v,w]) need 2 or 3  componate in array ",atype<pmesh>());
+          xx=to<double>( (*a)[0]);
+          yy=to<double>( (*a)[1]);
+          if(k==3)
+           zz=to<double>( (*a)[2]);
+         }
+      
+   }   
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh>(),atype<string*>(),true);}
+    static  E_F0 * f(const basicAC_F0 & args){ return new SaveMesh(args);} 
+    AnyType operator()(Stack s) const ;
+  
+};
+
+
+class Adaptation :   public E_F0mps { public:
+  typedef pmesh  Result;
+  
+  static basicAC_F0::name_and_type name_param[] ;
+  static const int n_name_param =28;
+  
+  int nbsol;    
+  Expression nargs[n_name_param];
+  Expression getmesh;
+  Expression em11,em22,em12;
+  int  typesol[100];
+  vector<Expression> sol;
+  int nbcperiodic;
+  Expression *periodic;
+  
+  
+  double arg(int i,Stack stack,double a) const { return nargs[i] ? GetAny<double>( (*nargs[i])(stack) ): a;}
+  long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+  long* arg(int i,Stack stack,long* a) const{ return nargs[i] ? GetAny<long*>( (*nargs[i])(stack) ): a;}
+  bool arg(int i,Stack stack,bool a) const{ return nargs[i] ? GetAny<bool>( (*nargs[i])(stack) ): a;}
+  int arg(int i,Stack stack,int a) const{ return nargs[i] ? GetAny<int>( (*nargs[i])(stack) ): a;}
+  
+  Adaptation(const basicAC_F0 & args) :nbsol(args.size()-1),sol(args.size()-1)
+  {   
+      em11=0;
+      em22=0;
+      em12=0;
+      
+      args.SetNameParam(n_name_param,name_param,nargs);
+      getmesh=to<pmesh>(args[0]); 
+      int ksol=0; 
+      ffassert(nbsol<100);
+      for (int i=1;i<nbsol+1;i++)       
+         if (args[i].left()==atype<E_Array>())
+          {
+            const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+            ffassert(a);
+            ksol+=a->size(); 
+          }
+         else
+           ksol++;
+      sol.resize(ksol); 
+      ksol=0; 
+      for (int i=1;i<nbsol+1;i++)       
+         if (args[i].left()==atype<E_Array>())
+          {
+            const E_Array * a = dynamic_cast<const E_Array *>(args[i].LeftValue());
+            ffassert(a);
+             int N=a->size();
+            typesol[i-1]=N-1; // ok en 2D
+            if (N<=4) {
+             for (int j=0;j<N;j++)             
+              sol[ksol++]=to<double>((*a)[j]); }
+            else {
+             lgerror(" Adaptation vecteur a plus de 4 compossantes inconnue");
+            }
+              
+          }
+         else {
+          typesol[i-1]=0;
+          sol[ksol++]=to<double>(args[i]);
+          }
+    const E_Array * expmetrix = dynamic_cast<const E_Array *>(nargs[24]);
+  
+  if(expmetrix)
+   {
+      if(expmetrix->nbitem()!=3)
+        ExecError("\nSorry we wait an array with 3 componants in: metrix=[m11,m12,m22]");
+        
+      em11=(*expmetrix)[0];
+      em12=(*expmetrix)[1];
+      em22=(*expmetrix)[2];
+      
+      if(  (*expmetrix)[0].left()!= atype<KN<double> *>() )
+          CompileError("Sorry the fist  array componant in metrix=[m11,m12,m22] must be vector");
+      if( (*expmetrix)[1].left()!= atype<KN<double> *>() )
+          CompileError("Sorry the second  array componant in metrix=[m11,m12,m22] must be vector");
+      if( (*expmetrix)[2].left()!= atype<KN<double> *>() ) 
+          CompileError("Sorry the third  array componant in metrix=[m11,m12,m22] must be vector");
+          
+          
+     }
+     nbcperiodic=0;
+     periodic=0;
+     GetPeriodic(2,nargs[25],nbcperiodic,periodic);
+       
+   }  
+    
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh>(),true);}
+    static  E_F0 * f(const basicAC_F0 & args){ return new Adaptation(args);} 
+    AnyType operator()(Stack s) const ;    
+    operator aType () const { return atype<pmesh>();}         
+};
+
+
+ basicAC_F0::name_and_type Adaptation::name_param[Adaptation::n_name_param] = {
+       {   "hmin",             &typeid(double)},  // � 
+       {   "hmax",             &typeid(double)},
+       {   "err",              &typeid(double)}, 
+       {   "errg",             &typeid(double)}, 
+       {   "nbvx",             &typeid(long)},        // 4
+       {   "nbsmooth",         &typeid(long)},
+       {   "nbjacoby",         &typeid(long)},
+       {   "ratio",            &typeid(double)}, 
+       {   "omega",            &typeid(double)},        
+       {   "iso",              &typeid(bool)},         // 9
+       {   "abserror",         &typeid(bool)}, 
+       {   "cutoff",           &typeid(double)},  
+       {   "verbosity",        &typeid(long)},
+       {   "inquire",          &typeid(bool)},         
+       {   "splitpbedge",      &typeid(bool)}, // 14
+       {   "maxsubdiv",        &typeid(double)},
+       {   "anisomax",         &typeid(double)},
+       {   "rescaling",        &typeid(bool)},
+       {   "keepbackvertices", &typeid(bool)},
+       {   "IsMetric",         &typeid(bool)},    // 19
+       {   "power",            &typeid(double)},    // 20 
+       {   "thetamax",         &typeid(double)}, 
+       {   "splitin2",         &typeid(bool) },
+       {  "nomeshgeneration", &typeid(bool) },
+       {   "metric"          ,  &typeid(E_Array)},  // 24
+       {   "periodic"        ,  &typeid(E_Array) },// 25 
+       { "requirededges",    &typeid(KN_<long> ) }, // 26
+       { "warning",    &typeid(long *) } // 27
+     
+    };
+
+struct Op_trunc_mesh : public OneOperator {
+
+    class Op: public E_F0mps   { public:
+      static basicAC_F0::name_and_type name_param[] ;
+      static const int n_name_param =4;
+      Expression nargs[n_name_param];
+    
+      Expression getmesh,bbb;
+      long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+        
+       KN<long> *  arg(int i,Stack stack) const{ return nargs[i] ? GetAny<KN<long> *>( (*nargs[i])(stack) ): 0;}
+      Op(const basicAC_F0 &  args,Expression t,Expression b) : getmesh(t),bbb(b)
+        { args.SetNameParam(n_name_param,name_param,nargs); }
+      AnyType operator()(Stack s)  const ;
+     };
+    E_F0 * code(const basicAC_F0 & args) const 
+     { return new Op(args,to<pmesh>(args[0]),to<bool>(args[1])) ;}
+   Op_trunc_mesh() : 
+     OneOperator(atype<pmesh>(),atype<pmesh>(),atype<bool>()) {}     
+};
+
+basicAC_F0::name_and_type Op_trunc_mesh::Op::name_param[Op_trunc_mesh::Op::n_name_param] =
+ {
+   {  "split",             &typeid(long)},
+   {  "label",             &typeid(long)},
+   { "new2old", &typeid(KN<long>*)},  //  ajout FH pour P. Jovilet jan 2014
+   { "old2new", &typeid(KN<long>*)}   //  ajout FH pour P. Jovilet jan 2014
+ 
+ };
+
+
+//extern Fem2D::Mesh *  BuildMesh(Stack stack, E_BorderN const * const & b,bool justboundary,int nbvmax,) ;
+
+
+AnyType classBuildMesh::operator()(Stack stack)  const { 
+    const E_BorderN * borders = GetAny<const E_BorderN *>((*getborders)(stack));
+   long  nbvx         = arg(0,stack,0L); 
+   bool  requireborder=  arg(1,stack,false);
+   ffassert(   nbvx >= 0);
+   
+   return SetAny<pmesh>(Add2StackOfPtr2FreeRC(stack,BuildMesh(stack,borders,false,nbvx,requireborder)));
+
+}
+
+AnyType BuildMeshFile::operator()(Stack stack)  const { 
+     string*  filename = GetAny<string* >((*getfilename)(stack));
+    long  nbvx         = arg(0,stack,0); 
+    ffassert(   nbvx >= 0);
+    pmesh pmsh=buildmeshbamg( filename,nbvx);
+    Add2StackOfPtr2FreeRC(stack,pmsh);//  07/2008 FH     
+    return SetAny<pmesh>(pmsh);
+    
+}
+
+AnyType Op_trunc_mesh::Op::operator()(Stack stack)  const { 
+    using namespace    Fem2D;
+    Mesh & Th = *GetAny<pmesh>((*getmesh)(stack));
+    long kkksplit =arg(0,stack,1L);
+    long label =arg(1,stack,2L);
+    KN<long> * pn2o =  arg(2,stack);
+    KN<long> * po2n =  arg(3,stack);
+    KN<int> split(Th.nt);
+    split=kkksplit;
+    long ks=kkksplit*kkksplit;
+    MeshPoint *mp= MeshPointStack(stack),mps=*mp;
+    long kk=0;
+    for (int k=0;k<Th.nt;k++)
+     { 
+       Triangle & K(Th[k]);
+       R2 B(1./3.,1./3.);
+       mp->set(Th,K(B),B,K,0);
+       if (  GetAny<bool>((*bbb)(stack))  ) kk++;
+       else  split[k]=0  ;    
+     }
+    
+    if(pn2o)
+        {
+          pn2o->resize(kk*ks);
+          KN<long> &n2o(*pn2o);
+          int l=0;
+          for(int k=0; k< Th.nt; ++k)
+             if( split[k] )
+                 for(int i=0; i< ks; ++i)
+                     n2o[l++] = k;
+        }
+        if(po2n)
+        {
+            po2n->resize(Th.nt);
+            KN<long> &o2n(*po2n);
+            int l=0;
+            for(int k=0; k< Th.nt; ++k)
+                if( split[k] )
+                {
+                        o2n[k] = l;
+                       l+=ks;
+                }
+            else o2n[k]=-1;
+        }
+
+    
+     *mp=mps;
+     if (verbosity>1) 
+     cout << "  -- Trunc mesh: Nb of Triangle = " << kk << " label=" <<label <<endl;
+  pmesh pmsh = new Mesh(Th,split,false,label);
+  pmsh->renum();
+   /* deja fait  dans bamg2msh
+  Fem2D::R2 Pn,Px;
+  m->BoundingBox(Pn,Px);
+  m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);*/
+ // pmsh->decrement();  
+  Add2StackOfPtr2FreeRC(stack,pmsh);//  07/2008 FH 
+
+  return SetAny<pmesh>(pmsh); 
+ };
+ 
+
+AnyType SplitMesh::operator()(Stack stack) const 
+{
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+   MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+   Mesh * Thh = GetAny<pmesh>((*getmesh)(stack));
+   ffassert(Thh);
+   int label=1;
+   Mesh & Th(*Thh);
+   //   long nbv=Thh->nv;
+   long nbt=Thh->nt;
+   KN<int> split(nbt);
+   R2 B(1./3.,1./3.);
+   int smax=0;
+   int smin=100000;
+   for (int it=0;it<nbt;it++)
+    {
+      Triangle & K(Th[it]);      
+      mp->set(Th,K(B),B,K,K.lab);
+      split[it]=GetAny<long>((*U)(stack));
+      smin=min(smin,split[it]);
+      smax=max(smax,split[it]);
+    }
+   if(verbosity) cout << "  -- Splitmesh " << Thh << " split  min: " << smin << " max: " << smax << endl; 
+   Mesh * pth= new Mesh(*Thh,split,false,label);
+   R2 Pn,Px;
+   pth->BoundingBox(Pn,Px);
+   if(!pth->quadtree)
+   pth->quadtree=new Fem2D::FQuadTree(pth,Pn,Px,pth->nv);
+
+   *mp=mps;
+   // pth->decrement();   
+    Add2StackOfPtr2FreeRC(stack,pth);//  07/2008 FH
+
+    return SetAny<pmesh>(pth);
+}
+AnyType SaveMesh::operator()(Stack stack) const 
+{
+  using  Fem2D::MeshPointStack;
+   Fem2D::Mesh * Thh = GetAny<pmesh>((*getmesh)(stack));
+   string * fn =  GetAny<string*>((*filename)(stack));
+   if (!xx && !yy ) {
+     ::bamg::Triangles * bTh= msh2bamg(*Thh);   
+     (*bTh).Write(fn->c_str(),::bamg::Triangles::AutoMesh);
+     delete bTh;
+     }
+   else {
+    MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+     ofstream fp((*fn+".points").c_str());
+     ofstream ff((*fn+".faces").c_str());
+     fp.precision(12);
+     if (verbosity>1) 
+       cout << "  -- Opening files " << (*fn+".points") << " and " << (*fn+".faces") << endl;
+    const   Fem2D::Mesh & Th=*Thh;
+    long nbv=Thh->nv;
+    long nbt=Thh->nt;
+    ff << nbt << endl;
+    fp << nbv << endl;
+    KN<long> num(nbv);
+    num=-1;
+    int k=0;
+    for (int it=0;it<nbt;it++)
+      {
+        const Fem2D::Triangle & K(Th[it]); 
+        
+        num[Th(K[0])]=k++;
+        num[Th(K[1])]=k++;
+        num[Th(K[2])]=k++;
+        
+         ff << " 3 " << Th(K[0])+1 << ' ' << Th(K[1])+1 << ' ' << Th(K[2])+1 << ' ' 
+         	<< " 0 0 0 " << K.lab << '\n';
+      }
+    if( verbosity>5)
+     cout << "  - end writing faces  " << endl;
+    for (int iv=0;iv<nbv;iv++)
+      {
+ //       cout << iv << endl;
+        const Fem2D::Vertex  & v(Th(iv)); 
+        ffassert( iv == Th(num[iv]/3,num[iv]%3));
+        mp->setP(Thh,num[iv]/3,num[iv]%3);
+        
+        fp << GetAny<double>((*xx)(stack)) << ' ';
+        fp << GetAny<double>((*yy)(stack)) << ' ';
+        if (zz)
+         fp << GetAny<double>((*zz)(stack)) << ' ';
+        else 
+         fp << " 0 ";
+        fp << v.lab<< '\n';
+      }
+    if( verbosity>5)
+     cout << "  - end writing points  " << endl;
+
+   *mp= mps;   
+     
+   }
+  //  delete fn;   modif mars 2006 auto del ptr
+   return SetAny<pmesh>(Thh);
+}
+AnyType MoveMesh::operator()(Stack stack) const 
+{
+ 
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+   MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+   Mesh * Thh = GetAny<pmesh>((*getmesh)(stack));
+   ffassert(Thh);
+   long nbv=Thh->nv;
+   long nbt=Thh->nt;
+   KN<double> u(nbv),v(nbv);
+   double infini=DBL_MAX;
+   u=infini;
+   for (int it=0;it<nbt;it++)
+    for (int iv=0;iv<3;iv++)
+    {
+      int i=(*Thh)(it,iv);
+      if ( u[i]==infini) { // if nuset the set 
+        mp->setP(Thh,it,iv);
+        u[i]=GetAny<double>((*U)(stack));
+        v[i]=GetAny<double>((*V)(stack));
+      }
+    }
+    
+   Mesh * pth= MoveTheMesh(*Thh,u,v);
+   if (pth)
+     for (size_t i=0;i<sol.size();i++)
+       { //  ale 
+	 pair<FEbase<double,v_fes>,int> * s = GetAny<pair<FEbase<double,v_fes>,int>*>( (*sol[i])(stack));
+	 ffassert(s->first.Vh);
+	 ffassert( &s->first.Vh->Th == Thh); // same old mesh
+	 ffassert(0); // a faire ????
+       }
+   *mp=mps;
+    //pth->decrement();   
+    Add2StackOfPtr2FreeRC(stack,pth);// 07/2008 FH
+    return SetAny<pmesh>(pth);
+
+}
+
+
+AnyType Adaptation::operator()(Stack stack) const 
+{
+  using namespace bamg;
+  using bamg::Min;
+  using bamg::Max;
+  using bamg::Abs;
+  
+
+  Real8 err         = arg(2,stack,0.01);    // coef in the metric
+  Real8  errg       = Min(arg(3,stack,0.01),err);
+  long nbsx         = Max(100L,arg(4,stack,9000L));
+  long nbsmooth     =  arg(5,stack,3L);
+  long nbjacobi     =  arg(6,stack,0L) ;              // if increased will be more smooth
+  const Real8 raison = arg(7,stack,1.8);
+  const Real8 omega =  arg(8,stack,1.0) ; 
+  bool iso          =   arg(9,stack,false);
+  bool AbsError     =   arg(10,stack,true);
+  Real8 CutOff      =   arg(11,stack, 1.0e-6);
+  verbosity         =   arg(12,stack, (long) verbosity);   
+  bool inq          =   arg(13,stack,false);
+  bool SplitEdgeWith2Boundary =  arg(14,stack,true);
+  double maxsubdiv             = Max(Min( arg(15,stack,10.0),10.0),0.1);
+  double anisomax              =   Max((double) arg(16,stack,1.0e6),1.0);
+  bool rescaling               = arg(17,stack,true) ;
+  bool KeepBackVertices        =   arg(18,stack,true) ;
+  int givenmetric              =  arg(19,stack,false) ;
+  double powerM                = arg(20,stack,1.0) ;
+  double cutoffradian          = arg(21,stack,-1.0)* bamg::Pi/180. ;
+  bool split                    = arg(22,stack,false) ;
+  bool nomeshgeneration         = arg(23,stack,false) ;
+  long lwarning=0;
+
+  long * pwarning                = arg(27,stack,&lwarning) ;
+  long &warning=*pwarning; //  get get warning message ...
+    
+  //   the 24th param is metrix  and is store at compilation time
+  //  const E_Array * expmetrix = dynamic_cast<const E_Array *>(nargs[24]);
+  //   the 25th param is periodic and it store at compilation time
+  // in nbcperiodic,periodic  variable 
+    KN<long> reqedges0;
+    //  list of label of required edges , for no adapattion on this part of the boundary.     
+    KN<long> reqedges ( nargs[26] ? GetAny< KN_<long> >( (*nargs[26])(stack) ): (KN_<long>)reqedges0); 
+
+  if(reqedges.N() && verbosity)
+      cout << " reqedges labels "  << reqedges << endl;
+  KN<double> *mm11=0, *mm12=0,* mm22=0;
+
+  using Fem2D::MeshPoint;
+  using Fem2D::Mesh;
+   Mesh * Thh = GetAny<pmesh>((*getmesh)(stack));
+  ffassert(Thh);
+    Triangles * oTh =0;
+  if (nbcperiodic) {
+    KN<int> ndfv(Thh->nv);
+    KN<int> ndfe(Thh->neb);
+    int nbdfv=0,nbdfe=0;      
+    BuildPeriodic(nbcperiodic,periodic,*Thh,stack,nbdfv,ndfv,nbdfe,ndfe);
+     oTh = msh2bamg(*Thh,cutoffradian,nbdfv,ndfv,nbdfe,ndfe,reqedges,reqedges.N());
+     
+  //  cerr << " Sorry periodic mesh adaptation is not well implemented "<< endl;
+  //  ExecError("adaptmesh( ... )");
+  }
+  else
+   oTh = msh2bamg(*Thh,cutoffradian,reqedges,reqedges.N());
+  Triangles &Th(*oTh);
+  bool mtx=em11 && em22 && em12;
+  if( mtx )
+   {
+      mm11= GetAny<KN<double> *>( (*em11)(stack) );
+      mm22= GetAny<KN<double> *>( (*em22)(stack) );
+      mm12= GetAny<KN<double> *>( (*em12)(stack) );
+      if (mm11->N() != Th.nbv || mm22->N() != Th.nbv || mm12->N() != Th.nbv)
+        ExecError("The size of3  metrics array must be equal to nb of vertex");
+      
+   }
+   
+  KN<double> &m11=*mm11;
+  KN<double> &m12=*mm12;
+  KN<double> &m22=*mm22;
+ 
+  
+  Real8 hmax = 0.3*Th.MaximalHmax(); // final largest edge 
+  Real8 hmin = Th.MinimalHmin();        // final smallest edge
+  
+  Real8 coef =1;                // a priori don't touch
+  // gestion des arguments 
+  hmin              = Max(hmin, arg(0,stack,hmin));
+  hmax              = Min(hmax,arg(1,stack,hmax));
+  if (inq && initgraphique) 
+   if (!withrgraphique ) {initgraphique();withrgraphique=true;}
+  
+    if (iso)  anisomax=1;
+  if (verbosity>2) 
+    {
+      cout << endl  << endl; 
+      cout << " \t\t ## adapt : nbsol= " << nbsol << ", nbsx = " << nbsx << ", err = " << err ;
+      cout << ", hmin = " << hmin << ", hmax = " << hmax <<endl;
+      cout << " \t\t    ratio  = " << raison << ", nbsmooth = " << nbsmooth ;
+      cout << ", omega = " << omega <<  ", coef = " << coef << ", iso = " << iso << endl;
+      cout << " \t\t    AbsError =" << AbsError << ", CutOff = " << CutOff << ", nbjacobi = " << nbjacobi <<endl;
+      cout << " \t\t    maxsubdiv = " << maxsubdiv << " splitpbedge = " << SplitEdgeWith2Boundary  <<endl;
+      cout << " \t\t    anisomax = " << anisomax << ", rescaling = " << rescaling << ", power = " << powerM
+           << ", KeepBackvertices = " << KeepBackVertices << " IsMetric = " << givenmetric
+      << endl << endl ; 
+    }
+    
+ // 
+ Th.ReMakeTriangleContainingTheVertex();
+  MeshPoint* mp(Fem2D::MeshPointStack(stack));
+   
+  Int4 i,iv; 
+  int ksol =0;
+  for (i=0;i<nbsol;i++)
+    ksol += typesol[i]+1; //  marche en 2d 
+   
+  double * lessol = new double [Th.nbv*ksol];
+  double *ss = lessol;
+  // be careful because renum --
+  // the triangle was no renum 
+  for ( iv=0;iv<Th.nbv;iv++) 
+    Th[iv].color=1; // color 
+ for (Int4  it = 0; it < Thh->nt; it++)
+    for (Int4  jt = 0; jt < 3; jt++)
+      { 
+        bamg::Vertex & v= Th(it)[jt];
+	//   const Fem2D::Vertex & vf = (*Thh)[it][jt];
+        if (&v && v.color)
+          {
+            v.color =0; // uncolor
+            mp->setP(Thh ,it,jt);
+ 
+            ss = lessol + ksol* Th.Number(v);
+            for (int j =0; j < ksol; j++)
+              *ss++= GetAny<double>( (*sol[j])(stack) );
+           
+          }
+      }
+  mp->unset();
+  // computation of the metric --- 
+  // better thing -> create keyword in the language 
+  //    a faire F Hecht .
+    
+  Metric Mhmax(hmax);
+    double  ch2=2/(hmax*hmax);
+    double  cH2=2/(hmin*hmin);
+    
+  for ( iv=0;iv<Th.nbv;iv++) 
+    Th[iv].m = Mhmax;
+    int miss=0; 
+   if (mtx) 
+    for ( iv=0;iv<Th.nbv;iv++) 
+      //if ( (m11[iv]+m22[iv]) > ch2) // modif FH (Thank to J-F Remacle 07/2010), correct 03/2011 FH. 
+       Th[iv].m.IntersectWith(MetricAnIso(m11[iv],m12[iv],m22[iv]));// add inters ..
+      else miss++;
+  //if(miss && verbosity>1) cout << "   -- Warning: Missing metric on vertices (too large) " <<  miss << " " << ch2 << endl;
+  if ( givenmetric)
+    if (ksol == 1) 
+      {
+        for (Int4  iv = 0,k=0; iv < Th.nbv ; iv++)
+          Th[iv].m.IntersectWith(Metric(lessol[k++]));
+      }
+    else if (ksol == 3) 
+      {
+        for (Int4  iv = 0,k=0; iv < Th.nbv ; iv++, k += 3)
+          {
+	    Metric MM(lessol[k],lessol[k+1],lessol[k+2]);
+	    MatVVP2x2 vp(MM);
+	    vp.Abs();
+	    Th[iv].m.IntersectWith(vp);
+          }
+      }
+    else
+      lgerror("Adapt mesh: ksol is wrong, IsMetric  and ksol != 1 or 3");
+  else
+  Th.IntersectConsMetric(lessol,nbsol,typesol,hmin,hmax,sqrt(err)*coef,anisomax,AbsError?0.0:CutOff,nbjacobi,rescaling,powerM,0);
+#ifdef DRAWING1
+  if ( (inq!=0) && initgraphique ) {
+    if (!withrgraphique) {initgraphique();withrgraphique=true;}
+    reffecran();
+    Th.InitDraw();
+    Th.Draw();
+    if (!NoWait) Th.inquire();} 
+#endif     
+  delete [] lessol;
+  Th.IntersectGeomMetric(errg,iso);
+  Th.SmoothMetric(raison);
+  Th.MaxSubDivision(maxsubdiv);
+  Th.BoundAnisotropy(anisomax);
+  // end of metric's computation 
+   if (mtx) 
+    for ( iv=0;iv<Th.nbv;iv++) 
+      {
+       m11[iv] = Th[iv].m.a11  ;
+       m22[iv] = Th[iv].m.a22 ; 
+       m12[iv] = Th[iv].m.a21;
+      }
+  
+  Triangles* nTh = 0;
+  
+  if ( ! nomeshgeneration)
+  {
+  nTh= new Triangles(nbsx,Th,KeepBackVertices); // Adaption is here
+  if (split)
+	    nTh->SplitElement(1); // modif FH mai 2009 (thank J-M Mirebeau) : Th ->nTh
+ 
+  if(SplitEdgeWith2Boundary)
+    nTh->SplitInternalEdgeWithBorderVertices();
+  if(verbosity>3) 
+    nTh->ShowHistogram();
+  if (nbsmooth)
+    nTh->SmoothingVertex(nbsmooth,omega);
+  if(verbosity>2 && nbsmooth) 
+    nTh->ShowHistogram();
+  if(verbosity>0)  
+      nTh->ShowRegulaty()  ;
+   
+#ifdef DRAWING
+  if ((inq!=0) && initgraphique) {
+    if (!withrgraphique ) {initgraphique();withrgraphique=true;}
+    
+    reffecran();
+    nTh->InitDraw();
+    nTh->Draw();
+    if(!NoWait) nTh->inquire();}
+#else
+  inq=0;
+#endif  
+  Metric M(hmax);
+  for (iv=0;iv < Th.nbv;iv++)
+    Th[iv].m = M;
+  warning = nTh->warning;
+
+  Mesh * g=  bamg2msh(nTh,true);
+
+  delete nTh;
+  delete oTh;
+  //g->decrement();
+  Add2StackOfPtr2FreeRC(stack,g);// 07/2008  FH
+     
+  return SetAny<pmesh>(g);
+  }
+ else {
+    
+     if(verbosity>1)  
+     {  cout << " regularty Old mesh / New metrix ";
+	 oTh->ShowRegulaty()  ;}     
+   delete oTh;
+   return SetAny<pmesh>(Thh);
+ }
+}   
+
+ 
+
+
+Fem2D::Mesh  * EmptyTheMesh( Fem2D::Mesh *  const & pTh,long *ssd=0)
+{
+  using namespace Fem2D;
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+  const Mesh & Th=*pTh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+  int nbv=Th.nv;
+  int nbt=0;
+  int neb=Th.neb;
+  KN<int> renum(Th.nv);
+  renum=-1;
+  if(ssd)
+   {
+    nbt=-1; //  pour ne pas retire l'exterieur
+    int nebb=0;
+    for (int i=0;i<Th.nt;i++)
+     for (int e=0;e<3;e++)
+      { int ee=e,ii=Th.ElementAdj(i,ee);
+        if ( (ii>= 0 && ii != i) && (i<ii && ssd[ii] != ssd[i]) ) 
+          {
+           nebb++;
+           int i1= Th(i,VerticesOfTriangularEdge[e][0]);
+           int i2= Th(i,VerticesOfTriangularEdge[e][1]);
+           cout << i1 << " " << i2 << endl;
+           renum[i1]=1;
+           renum[i2]=1;
+         }
+      }
+      neb=nebb;
+   }
+   else 
+  for (int i=0;i<neb;i++)
+    {        
+     int i1=Th(Th.bedges[i][0]);
+     int i2=Th(Th.bedges[i][1]);
+     renum[i1]=1;
+     renum[i2]=1;
+     }
+  int nbvnew=0;
+  for(int i=0;i<nbv;i++)
+   if (renum[i]>=0)
+     renum[i]= nbvnew++;
+      
+  Vertex * v= new Vertex[nbvnew];
+  //  Triangle *t= 0;
+  BoundaryEdge *b= new BoundaryEdge[neb];
+  //Vertex *vv=v;
+  Vertex *vo=Th.vertices;
+  BoundaryEdge * bb=b;
+
+  if(ssd)
+   {
+    int nebb=0;
+    for (int i=0;i<Th.nt;i++)
+     for (int e=0;e<3;e++)
+      { int ee=e,ii=Th.ElementAdj(i,ee);
+        if ( (ii>= 0 && ii != i) && (i<ii && ssd[ii] != ssd[i]) ) 
+         {
+           nebb++;
+           int i1= renum[Th(i,VerticesOfTriangularEdge[e][0])];
+           int i2= renum[Th(i,VerticesOfTriangularEdge[e][1])];
+           int labM=0,labm=0;
+           labM=Th[i].lab;
+           if( ii >=0) labm=Th[ii].lab;
+           if( labM <labm) Exchange(labM,labm);
+           int lab= 100*labM+labm ;     
+           *bb++ = BoundaryEdge(v,i1,i2,lab);   
+         }
+      }
+   }
+   else   
+  for (int i=0;i<neb;i++)
+    {        
+     int i1=renum[Th(Th.bedges[i][0])];
+     int i2=renum[Th(Th.bedges[i][1])];
+     int lab=Th.bedges[i].lab;     
+     *bb++ = BoundaryEdge(v,i1,i2,lab);   
+    }
+  
+  for (int i=0;i<nbv;i++)
+   {
+     int j=renum[i];
+     if(j>=0) 
+      {
+        v[j].x=vo[i].x;
+        v[j].y=vo[i].y;
+        v[j].lab=vo[i].lab;
+      }   
+    }
+
+ {
+  Mesh * m = new Mesh(nbvnew,nbt,neb,v,0,b);
+  R2 Pn,Px;
+  m->BoundingBox(Pn,Px);
+  m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+//  m->decrement();  
+  return m;
+      
+}
+}
+Fem2D::Mesh  * EmptyTheMesh( Fem2D::Mesh *  const & pTh)
+{
+  return EmptyTheMesh(pTh,0);
+}
+Fem2D::Mesh  * EmptyTheMesh( Fem2D::Mesh *  const & pTh,  KN<long> * const &  k)
+{
+  return EmptyTheMesh(pTh,*k);
+}
+
+
+Mesh * MoveTheMesh(const Fem2D::Mesh &Th,const KN_<double> & U,const KN_<double> &V)
+{
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+  int nbv=Th.nv;
+  int nbt=Th.nt;
+  int neb=Th.neb;
+  Vertex * v= new Vertex[nbv];
+  Triangle *t= new Triangle[nbt];
+  BoundaryEdge *b= new BoundaryEdge[neb];
+  Vertex *vv=v;
+  for (int i=0;i<nbv;i++)
+   {
+     R2 P(U[i],V[i]);     
+     vv->x=P.x;
+     vv->y=P.y;
+     vv->lab = Th(i).lab;
+     vv++;      
+    }   
+  Triangle *tt= t; 
+  int nberr=0;
+  double atotal=0,atotal0=0;
+  double amax=-1e100,amin=1e100;
+  for (int i=0;i<nbt;i++)
+    {
+       atotal0 += Th[i].area;
+      int i0=Th(i,0), i1=Th(i,1),i2=Th(i,2);
+      double a= Area2(v[i0],v[i1],v[i2])/2;
+      atotal +=  a;
+      amax=max(a,amax);
+      amin=min(a,amin);
+    }  
+  double  eps = 1e-6 * max(abs(atotal),1e-100)/atotal0;
+  bool rev=(atotal<0);
+  if(verbosity>2 && rev) cout <<  "  -- movemesh negatif tranfomation => reverse all triangle (old area " << atotal0 << ") ( new area  " << atotal << ") "<< endl; 
+  for (int i=0;i<nbt;i++)
+    {
+      int i0=Th(i,0), i1=Th(i,1),i2=Th(i,2);
+      if(rev) swap(i1,i2);
+      R a= Area2(v[i0],v[i1],v[i2])/2;
+      if ( a < Th[i].area*eps) 
+       { nberr++;
+        if (verbosity>1) 
+         {
+          if (nberr==1) { cerr << "Erreur: MoveMesh "; }
+	  cerr << " T = " << Th[i] <<  endl;
+          }
+          if (nberr < verbosity*5) {
+            cerr << " " <<i;
+            if ( nberr % 5 )  cerr << "\n\t";}
+         }
+       else 
+        (*tt++).set(v,i0,i1,i2,Th[i].lab,a);
+    
+   }  
+    if (nberr)
+      { if (verbosity) 
+	  cerr << "Error movemesh: " << nberr << " triangles was reverse  (=> no move)" <<  endl;  
+	  cout << " u min " << U.min() << " max " << U.max() << endl;
+	  cout << " v min " << V.min() << " max " << V.max() << endl;
+	  
+	  delete []v;
+	  delete []t;
+	  delete []b;   
+	  throw(ErrorExec("Error move mesh triangles was reverse",1));      
+	  return 0;
+      }
+    
+  BoundaryEdge * bb=b;
+  for (int i=0;i<neb;i++)
+    {        
+     int i1=Th(Th.bedges[i][0]);
+     int i2=Th(Th.bedges[i][1]);
+     int lab=Th.bedges[i].lab;     
+     if(rev) swap(i1,i2);     
+     *bb++ = BoundaryEdge(v,i1,i2,lab);   
+    }
+ {
+  Mesh * m = new Mesh(nbv,nbt,neb,v,t,b);
+  R2 Pn,Px;
+  m->BoundingBox(Pn,Px);
+  m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+ //m->decrement();  //  delete done external
+  return m;
+      
+}
+}
+
+/// <<Carre>> Builds a square-shaped 2D mesh. An Expression [[file:AFunction.hpp::Expression]] is a pointer to an object
+/// of class E_F0 [[file:AFunction.hpp::E_F0]].
+
+Mesh * Carre(int nx,int ny,Expression fx,Expression fy,Stack stack,int flags,KN_<long> lab,long reg)
+{
+  if(verbosity>99)  cout << " region = " << reg << " labels " << lab <<endl;  
+  const int unionjack=1;
+  using  Fem2D::Vertex;
+  using  Fem2D::Triangle;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+  using  Fem2D::R;
+
+  using  Fem2D::MeshPointStack;
+  int nx1=nx+1,ny1=ny+1;
+  int nbv=(nx1)*(ny1);
+  int nbt=(nx)*ny*2;
+  int neb=(nx+ny)*2;
+  int l1=1,l2=2,l3=3,l4=4;
+  if(lab.N()>=1) l1=lab[0];
+  if(lab.N()>=2) l2=lab[1];
+  if(lab.N()>=3) l3=lab[2];
+  if(lab.N()>=4) l4=lab[3];
+    
+  Vertex * v= new Vertex[nbv];
+  Triangle *t= new Triangle[nbt];
+  BoundaryEdge *b= new BoundaryEdge[neb];
+  Vertex *vv=v;
+  for (int j=0;j<ny1;j++)
+   for (int i=0;i<nx1;i++)
+   {
+     R2 P((R) i/nx,(R) j/ny);
+     
+     vv->x=P.x;
+     vv->y=P.y;
+     vv->lab =  0;
+     vv++;
+   }
+  if (fx || fy)
+   {
+     MeshPoint *mp=MeshPointStack(stack);
+    vv=v;
+    for (int j=0;j<ny1;j++)
+     for (int i=0;i<nx1;i++)
+       {
+         mp->set(vv->x,vv->y);
+         if (fx)  vv->x= GetAny<R>((*fx)(stack));
+         if (fy)  vv->y= GetAny<R>((*fy)(stack));
+         vv++;
+       } 
+   }
+  Triangle *tt= t;   
+  // 
+  bool direct = det(v[0],v[1],v[nx1+1]) > 0; //  signe  triangle 0
+  
+    if(verbosity>1&& !direct) cout << "  -- square : all triangles are reversed" <<   endl;
+
+    int p[2]={1,0};
+    if(direct) {p[0]=0,p[1]=1;} 
+  for (int j=0;j<ny;j++)
+   for (int i=0;i<nx;i++)
+     { 
+       int i0 = i + j*nx1;
+       int i1= i0+1;
+       int i2=i1+nx1;
+       int i3=i2-1;
+       bool c00= (i==0) && (j==0);
+       bool c10= (i==nx-1) && (j==0);
+       bool c01= (i==0) && (j==ny-1);
+       bool c11= (i==nx-1) && (j==ny-1);
+  	 
+      bool cas = true;
+      switch (flags)
+       {
+       case unionjack:
+          cas =  (i+ j) %2 ; break;
+       case 2: // new  jan 2010 
+	     cas = false; break;
+       case 3:// never triangle with 3 vertex on boundary 
+	     cas = c01 || c10 ? false : true; break;
+       case 4:// never triangle with 3 vertex on boundary
+	     cas = c00 || c11 ? true : false; break;	     
+       default:
+          cas = true;
+       } ;
+	 
+	 if (cas) 
+	   {
+	       if(direct)
+		 {     // diag 1 
+		     (tt++)->set(v,i0,i1,i2,reg,0.0);
+		     (tt++)->set(v,i0,i2,i3,reg,0.0);	       
+		 }
+	       else
+		 {     // diag 1 
+		     (tt++)->set(v,i1,i0,i2,reg,0.0);
+		     (tt++)->set(v,i2,i0,i3,reg,0.0);	       
+		 }
+	   } 
+	 else 
+	   {
+	       if(direct)
+		 {    // diag 2  		     
+		     (tt++)->set(v,i0,i1,i3,reg,0.0);
+		     (tt++)->set(v,i3,i1,i2,reg,0.0);		     
+		 }
+	       else 
+		 {    // diag 2  		     
+		     (tt++)->set(v,i1,i0,i3,reg,0.0);
+		     (tt++)->set(v,i1,i3,i2,reg,0.0);
+		     
+		 }
+	   }
+	 
+     }  
+    BoundaryEdge * bb=b;
+  for (int i=0;i<nx;i++)
+    {  // bottom 
+      //      int j=0;
+      int i1=i,i2=i1+1;
+      *bb++ = BoundaryEdge(v,i1,i2,l1);
+      v[i1].lab=v[i2].lab=l1;
+    }     
+  for (int j=0;j<ny;j++)
+    { // right
+      int i=nx;
+      int i1= i + j*nx1 ,i2=i1+nx1;
+      *bb++ = BoundaryEdge(v,i1,i2,l2);
+      v[i1].lab=v[i2].lab=l2;
+    }     
+    
+  for (int i=0;i<nx;i++)
+    {  // up
+      int j=ny;
+      int i1=i + j*nx1,i2=i1+1;
+      *bb++ = BoundaryEdge(v,i1,i2,l3);
+      v[i1].lab=v[i2].lab=l3;
+
+    }     
+  for (int j=0;j<ny;j++)
+    { // left
+      int i=0;
+      int i1= i + j*nx1,i2=i1+nx1;
+      *bb++ = BoundaryEdge(v,i1,i2,l4);
+      v[i1].lab=v[i2].lab=l4;
+    }     
+    
+  {
+    if(verbosity) cout << "  -- Square mesh : nb vertices  =" << nbv 
+		       << " ,  nb triangles = " << nbt << " ,  nb boundary edges " << neb << endl;  
+    Mesh * m = new Mesh(nbv,nbt,neb,v,t,b);
+    R2 Pn,Px;
+    m->BoundingBox(Pn,Px);
+    m->quadtree=new Fem2D::FQuadTree(m,Pn,Px,m->nv);
+
+    Add2StackOfPtr2FreeRC(stack,m);// 07/2008 FH
+
+    return m;
+  }
+}
+
+/// <<MeshCarre2>> Creates a square mesh by calling the [[Carre]] function at script evaluation time. Uses class E_F0mps
+/// [[file:AFunction.hpp::E_F0mps]] to connect to the FF language.
+
+class MeshCarre2 :   public E_F0mps {
+public:
+  typedef pmesh  Result;
+  Expression nx,ny;
+  static basicAC_F0::name_and_type name_param[] ;
+  static const int n_name_param =1+2;
+  Expression nargs[n_name_param];
+   
+  long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+    
+     
+  MeshCarre2(const basicAC_F0 & args) 
+  {     
+    args.SetNameParam(n_name_param,name_param,nargs);
+    nx=to<long>(args[0]); 
+    ny=to<long>(args[1]); 
+  }
+    
+  static ArrayOfaType  typeargs() { 
+    return  ArrayOfaType(atype<long>(),atype<long>(),false);}
+
+  /// <<MeshCarre2_f>>
+
+  static  E_F0 * f(const basicAC_F0 & args){
+    return new MeshCarre2(args);} 
+        
+  AnyType operator()(Stack s) const { 
+    long flags=arg(0,s,0);
+    KN<long> zz;
+    KN<long> label=arg(1,s,zz);
+    long region=arg(2,s,0L);// correct aout 2010 FH ... 2-> 0 
+    
+    /// calls [[Carre]]
+    
+    return SetAny<pmesh>(Carre( GetAny<long>( (*nx)(s)) , GetAny<long>( (*ny)(s)),0,0,s,flags,label,region ));
+  }
+
+  operator aType () const { return atype<pmesh>();} 
+};
+
+/// <<MeshCarre2f>> Creates a square mesh by calling the [[Carre]] function at script evaluation time
+
+class MeshCarre2f :   public E_F0mps {
+public:
+  typedef pmesh  Result;
+  Expression nx,ny;
+  Expression fx,fy;
+  static basicAC_F0::name_and_type name_param[] ;
+  static const int n_name_param =1+2;
+  Expression nargs[n_name_param];
+   
+  long arg(int i,Stack stack,long a) const{ return nargs[i] ? GetAny<long>( (*nargs[i])(stack) ): a;}
+  KN_<long>  arg(int i,Stack stack,KN_<long> a ) const
+  { return nargs[i] ? GetAny<KN_<long> >( (*nargs[i])(stack) ): a;}
+     
+  MeshCarre2f(const basicAC_F0 & args) 
+  { 
+    args.SetNameParam(n_name_param,name_param,nargs);
+    nx=to<long>(args[0]); 
+    ny=to<long>(args[1]); 
+    const E_Array *  a= dynamic_cast<const E_Array*>(args[2].LeftValue());
+    ffassert(a);fx=0;fy=0;
+    if (a->size()>0) fx=to<double>( (*a)[0]);
+    if (a->size()>1) fy=to<double>( (*a)[1]);
+  }
+    
+  static ArrayOfaType  typeargs() { 
+    return  ArrayOfaType(atype<long>(),atype<long>(),atype<E_Array>(),false);}
+        
+  static  E_F0 * f(const basicAC_F0 & args){
+    return new MeshCarre2f(args);} 
+        
+  AnyType operator()(Stack s) const { 
+    long flags=arg(0,s,0);
+    KN<long> zz;
+    KN<long> label=arg(1,s,zz);
+    long region=arg(2,s,0L);
+	
+    return SetAny<pmesh>(Carre( GetAny<long>( (*nx)(s)) , GetAny<long>( (*ny)(s)), fx,fy,s , flags,label,region));}
+
+  operator aType () const { return atype<pmesh>();} 
+};
+
+basicAC_F0::name_and_type  MeshCarre2::name_param[]= {
+	{  "flags", &typeid(long) },	
+	{  "label", &typeid(KN_<long> ) },
+	{  "region", &typeid(long) }      
+    
+};
+basicAC_F0::name_and_type  MeshCarre2f::name_param[]= {
+	{  "flags", &typeid(long) },
+	{  "label", &typeid(KN_<long> )},
+	{  "region", &typeid(long)}
+    };
+    
+
+/*
+
+Grid * Etruncmesh::eval()
+{
+  Analvar save(*an);
+  throwassert(idgrid && idgrid->typesol ==Iden::maillage );
+  Grid* go = idgrid->fg;
+  throwassert(go);
+  int * flag= new int[go->nt];
+  int * bb  = new int[go->nt];
+  Real xl[]={ 1./3.,1./3.,1./3.};      
+  for (int i=0;i<go->nt;i++)
+    {
+      int oldlocal = an->local;
+      const bTriangle & T = go->t[i];
+      const bVertex & v0 = *T.v[0];
+      const bVertex & v1 = *T.v[1];
+      const bVertex & v2 = *T.v[2];
+      Real x = v0.x*xl[0] + v1.x*xl[1] + v2.x*xl[2];
+      Real y = v0.y*xl[0] + v1.y*xl[1] + v2.y*xl[2];                        
+      an->setAn(0,x, y, T.where, xl,-1,-1,i);
+      Real ee = e->eval();
+      flag[i] = (int) Max((Real)-32000.0,Min(e->eval(),(Real)32000.0));
+      if (b) 
+        bb[i]  = (int) Max((Real)-32000.0,Min(b->eval(),(Real)32000.0));
+      else 
+        bb[i] = 1;
+      //   cout << ee  << " " << flag[i] <<  " " << bb[i] << endl;
+
+      an->local  = oldlocal;
+    }
+  Grid* g = new Grid();
+  // for (int i=0;i<go->nt;i++)
+  //  cout << flag[i] << (i%10 == 9 ? '\n' : ' ');
+  cout << endl;
+  Triangles * Th = new Triangles(*go->Th,flag,bb);
+  delete [] flag;
+  delete [] bb;
+  if( ! Th) erreur("trunc triangulation");
+  double hmax = Th->MaximalHmax();
+  //  cout << " hmax = " << hmax << " ------- " << endl;
+  Metric M(hmax);
+  for (int iv=0;iv < Th->nbv;iv++)
+    (*Th)[iv].m = M;
+  
+#ifdef DRAWING1
+  reffecran();
+  Th->InitDraw();
+  Th->inquire();
+#endif 
+  
+  g->th2t(Th);
+  g->renum();
+  g->prepgrid(0);
+   
+  if(!toScilab)
+  g->draw(*an);
+  // an->activeMesh=g; // set the activegrid
+  *an=save;
+  return g; 
+}
+
+Grid * Emovemesh::eval()
+{
+   Analvar save(*an); 
+  int i;
+  Grid* go = idmoved->fg;
+  Grid* gn = new Grid(go);
+  throwassert(go);
+  
+  Grid& t =*gn;
+  an->gridxyng = go;
+  Real xl[3] = {0.,0.,0.};
+  for ( i = 0; i < go->nv; i++)
+    {
+      int oldlocal = an->local;
+      an->setAn(0, go->v[i].x, go->v[i].y, go->v[i].where,xl, i); 
+      t.v[i].x = ex->eval();
+      t.v[i].y = ey->eval();
+      an->local  = oldlocal;
+    }
+  an->gridxyng =0;
+  t.prepgrid(1);
+  //  for(i=0;i<t.nt;i++)
+  //  for(int iloc=0;iloc<3;iloc++)
+  //    t.t[i].e[iloc] = go->t[i].e[iloc];
+  if(!toScilab)
+  t.draw(*an);
+  Geometry * tGh = new Geometry(go->Th->Gh);
+  Triangles* tTh = new Triangles(*go->Th,tGh);// copy the Triangles
+  cout << "\t\t MoveMesh Grid * " << gn << " Gh = " <<  tGh << " Th = " << tTh  << endl;
+  //tTh->Write("movemesh.Th");
+  
+  Triangles & Th = *tTh;
+  Geometry & Gh = *tGh;
+  Geometry & GhO = go->Th->Gh;
+  int * renu = go->NumThinGrid;
+  
+  cout << "\t\t renu = " << renu << " " << (renu ? renu[0] : 0) << endl;
+  // move of the geometry 
+  for ( i = 0; i <GhO.nbv;i++)
+    {
+      int oldlocal = an->local;
+      an->setAn(0,GhO.vertices[i].r.x, GhO.vertices[i].r.y, GhO.vertices[i].ref(),xl);
+      Gh.vertices[i].r.x  = ex->eval();
+      Gh.vertices[i].r.y  = ey->eval();
+      an->local  = oldlocal;
+    }
+  // change the tangente 
+
+  for (i=0;i<Gh.nbe;i++) 
+    {
+      R2 AB = Gh.edges[i].v[1]->r - Gh.edges[i].v[0]->r;        
+      Real8 lAB = Norme2(AB); // length of current edge AB
+        
+      for (int jj=0;jj<2;jj++) 
+        if( ! Gh.edges[i].v[jj]->Corner() &&
+            (    (jj==0 && Gh.edges[i].TgA()) 
+                 || (jj==1 && Gh.edges[i].TgB()) ) )
+          {       
+                
+            // recompute the tangent
+            R2 tg =  Gh.edges[i].v[1-jj]->r 
+              - Gh.edges[i].Adj[jj]->v[1-Gh.edges[i].SensAdj[jj]]->r;
+            Real8 ltg =  Norme2(tg);
+            tg =  tg *(lAB/ltg);
+            if ( (tg,AB) < 0) 
+              tg = -tg;
+            Gh.edges[i].tg[jj] = tg;                 
+          }          
+    } // for (i=0;i<nbe;i++)
+if(!toScilab)
+{    
+#ifdef DRAWING
+  Gh.InitDraw();
+#endif
+#ifdef DRAWING2    
+  reffecran();
+  Gh.InitDraw();
+  Gh.Draw();
+#endif 
+}     
+  //  move of the bamg mesh 
+  Th.pmin =  R2(t.v[0].x,t.v[0].y);
+  Th.pmax =  Th.pmin;
+
+  for ( i = 0; i < Th.nbv; i++)
+    {   // Be carefull we do a renumbering 
+      int j = renu ? renu[i] : i;
+      Th.vertices[i].r =   R2(t.v[j].x,t.v[j].y);
+      Th.pmin.x = Min( Th.pmin.x, Th.vertices[i].r.x);
+      Th.pmin.y = Min( Th.pmin.y, Th.vertices[i].r.y);
+      Th.pmax.x = Max( Th.pmax.x, Th.vertices[i].r.x);
+      Th.pmax.y = Max( Th.pmax.y, Th.vertices[i].r.y);          
+    }
+  {R2 P10 = (Th.pmax-Th.pmin)*0.1;
+  Th.pmin = Th.pmin - P10;Th.pmax = Th.pmax + P10;}
+
+  Gh.pmin =  Gh.vertices[0].r;
+  Gh.pmax =  Gh.pmin;
+
+  for ( i = 0; i < Gh.nbv; i++)
+    {
+      Gh.pmin.x = Min( Gh.pmin.x, Gh.vertices[i].r.x);
+      Gh.pmin.y = Min( Gh.pmin.y, Gh.vertices[i].r.y);
+      Gh.pmax.x = Max( Gh.pmax.x, Gh.vertices[i].r.x);
+      Gh.pmax.y = Max( Gh.pmax.y, Gh.vertices[i].r.y);          
+    }
+  {R2 P10 = (Gh.pmax-Gh.pmin)*0.1;
+  Gh.pmin = Gh.pmin - P10;Gh.pmax = Gh.pmax + P10;}
+    
+  delete [] renu;
+  renu=0;
+  
+  Gh.coefIcoor = (MaxICoor)/(Max( Gh.pmax.x- Gh.pmin.x, Gh.pmax.y- Gh.pmin.y));
+  Th.coefIcoor = (MaxICoor)/(Max( Th.pmax.x- Th.pmin.x, Th.pmax.y- Th.pmin.y));
+
+  //  for ( i = 0; i < Gh.nbv; i++)
+  //    Gh.vertices[i].i = Gh.toI2(Gh.vertices[i].r);
+  
+  for ( i = 0; i < Th.nbv; i++)
+    Th.vertices[i].i = Th.toI2(Th.vertices[i].r);
+  // remove all the adj  and save the flag
+  for ( i= 0; i < Th.nbt; i++)
+    { 
+      Triangle & t = Th(i);
+      for ( int j = 0 ; j<3; j++) 
+        t.SetAdj2(j,0,t.GetAllflag(j));
+    }
+   
+
+  //  Th.quadtree=new QuadTree(&Th);
+  Th.nbt = Th.nbt - Th.NbOutT; // remove all the  the ouside triangles 
+  Th.SetIntCoor("In movemesh"); 
+  Th.FillHoleInMesh(); 
+  // delete Th.quadtree; // delete old 
+  if (!Th.quadtree)
+    Th.quadtree=new QuadTree(&Th);
+  Th.ReMakeTriangleContainingTheVertex();
+  
+
+#ifdef DRAWING2 
+  Th.inquire();
+#endif  
+  gn->Th = &Th;
+  gn->Gh = &Gh;
+  Gh.NbRef++;
+  gn->nbholes = go->nbholes;
+  *an=save;  
+  return gn;
+}
+
+*/   
+
+   void  MeshErrorIO(ios& )
+{
+   ExecError("Mesh IO Error ");
+}
+
+inline pmesh *  initMesh(pmesh * const & p, string * const & s) {
+  Mesh * m;
+  *p= m =new Mesh(*s); 
+  m->MakeQuadTree();
+ //  delete s;  modif mars 2006 auto del ptr 
+  return p;
+ }
+
+class CheckMoveMesh :  public E_F0mps { public:  
+ 
+   typedef double  Result;
+   Expression getmesh;
+   Expression U,V;
+   int nbsol;    
+    vector<Expression> sol;
+   
+    CheckMoveMesh(const basicAC_F0 & args) :nbsol(args.size()-2),sol(args.size()-2)
+    {   
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+      args.SetNameParam();
+      getmesh=to<pmesh>(args[0]); 
+      const E_Array * a = dynamic_cast<const E_Array *>(args[1].LeftValue());
+      
+      ffassert(a);
+      if (a->size() !=2) CompileError("CheckMoveMesh(Th,[u,v]) need 2 componate in array ",atype<pmesh>());
+      U=to<double>( (*a)[0]);
+      V=to<double>( (*a)[1]);
+      
+      for (int i=2;i<args.size();i++)
+        sol[i-2]=to<double>(args[i]);      
+    }   
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh>(),atype<E_Array>(),false);}
+    static  E_F0 * f(const basicAC_F0 & args){ return new CheckMoveMesh(args);} 
+    AnyType operator()(Stack s) const ;
+    operator aType () const { return atype<double>();}         
+  
+};
+AnyType CheckMoveMesh::operator()(Stack stack) const 
+{
+ 
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+   MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+   Mesh * Thh = GetAny<pmesh>((*getmesh)(stack));
+   Mesh & Th(*Thh);
+   ffassert(Thh);
+   long nbv=Thh->nv;
+   long nbt=Thh->nt;
+   KN<double> u(nbv),v(nbv);
+   double infini=DBL_MAX;
+   u=infini;
+   for (int it=0;it<nbt;it++)
+    for (int iv=0;iv<3;iv++)
+    {
+      int i=(*Thh)(it,iv);
+      if ( u[i]==infini) { // if nuset the set 
+        mp->setP(Thh,it,iv);
+        u[i]=GetAny<double>((*U)(stack));
+        v[i]=GetAny<double>((*V)(stack));
+      }
+    }
+     double minarea=DBL_MAX;
+    for (int t=0;t<Th.nt;t++)
+     {
+      int i0=Th(t,0),i1=Th(t,1),i2=Th(t,2);
+      minarea=Min(minarea,Area2(R2(u[i0],v[i0]), R2(u[i1],v[i1]),R2(u[i2],v[i2])));
+     }
+    *mp=mps;
+    return SetAny<double>(minarea/2.);
+
+}
+
+bool SameMesh(Mesh * const & pTh1,Mesh * const & pTh2)
+{
+    typedef Mesh::Element Element;
+    if( !pTh1) return 0;
+    if( !pTh2) return 0;
+    if( pTh1 == pTh2) return 1;
+    if( pTh1->nv != pTh2->nv) return 0;
+    if( pTh1->nt != pTh2->nt) return 0;
+    Mesh & Th1=*pTh1, & Th2 = *pTh2;
+    ffassert(0); // a faire..
+    
+    return 1;
+}
+
+bool AddLayers(Mesh * const & pTh, KN<double> * const & psupp, long const & nlayer,KN<double> * const & pphi)
+{
+    ffassert(pTh && psupp && pphi);
+    const int nve = Mesh::Element::NbV;
+    Mesh & Th= *pTh;
+    const int nt = Th.nt;
+    const int nv = Th.nv;
+    
+    KN<double> & supp(*psupp);
+    KN<double> u(nv), s(nt);
+    KN<double> & phi(*pphi);
+    ffassert(supp.N()==nt);//P0
+    ffassert(phi.N()==nv); // P1
+    s = supp;
+    phi=0.;
+    // supp = 0.;
+    // cout << " s  " << s << endl;
+    
+    for(int step=0; step < nlayer; ++ step)
+    {
+        
+        
+        u = 0.;
+        for(int k=0; k<nt; ++k)
+            for(int i=0; i<nve; ++i)
+                u[Th(k,i)] += s[k];
+        
+        for(int v=0; v < nv; ++v)
+            u[v] = u[v] >0.;
+        // cout << " u  " << u << endl;
+        
+        phi += u;
+        
+        s = 0.;
+        for(int k=0; k<nt; ++k)
+            for(int i=0; i<nve; ++i)
+                s[k] += u[Th(k,i)];
+        
+        for(int k=0; k < nt; ++k)
+            s[k] = s[k] > 0.;
+        supp += s;
+        // cout << " s  " << s << endl;
+    }
+    // cout << " phi  " << phi << endl;
+    phi *= (1./nlayer);
+    // supp =s;
+    return true;
+}
+
+
+double arealevelset(Mesh * const & pTh,KN<double>  * const & pphi,const double & phi0,KN<double>  * const & where)
+{
+    Mesh & Th=*pTh;
+    KN<double> & phi=*pphi;
+    ffassert( phi.N() == Th.nv); // P1
+    double arean=0., areap=0.;
+    for (int k=0;k<Th.nt;k++)
+    {
+        if( !where || (*where)[k] )
+        {
+            const Triangle & K(Th[k]);
+            const Vertex & A(K[0]), &B(K[1]),&C(K[2]);
+            int iK[3]={Th(k,0),Th(k,1),Th(k,2)};
+            R  fk[3]={phi[iK[0]]-phi0,phi[iK[1]]-phi0,phi[iK[2]]-phi0 };
+            int i0 = 0, i1 = 1, i2 =2;
+            if( fk[i0] > fk[i1] ) swap(i0,i1) ;
+            if( fk[i0] > fk[i2] ) swap(i0,i2) ;
+            if( fk[i1] > fk[i2] ) swap(i1,i2) ;
+            
+            if ( fk[i2] <=0.) arean+= K.area;
+            else  if ( fk[i0] >=0.) areap+= K.area;
+            else {
+                double c = (fk[i2]-fk[i1])/(fk[i2]-fk[i0]); // coef Up Traing
+                if( fk[i1] < 0 ) { double y=fk[i2]/(fk[i2]-fk[i1]); c *=y*y; }
+                else {double y=fk[i0]/(fk[i0]-fk[i1]) ; c = 1.- (1.-c)*y*y; };
+                assert( c > -1e-10 && c-1. < 1e-10);
+                areap += c*K.area;
+                arean += (1-c)*K.area;
+            }
+        }
+    }
+    // cout << phi0 << endl;
+    return arean; //  negative area ...
+}
+double arealevelset(Mesh * const & pTh,KN<double>  * const & pphi,const double & phi0)
+{
+    return arealevelset(pTh,pphi,phi0,0);
+}
+
+
+double volumelevelset(Mesh3 * const & pTh,KN<double> * const &pphi,const double & phi0,KN<double> * const & where)
+{
+    Mesh3 & Th = *pTh;
+    KN<double> & phi = *pphi;
+    ffassert(phi.N() == Th.nv); //assertion fails if the levelset function is not P1
+    double volumen=0.,volumep=0.;
+    for(int k=0;k<Th.nt;++k)
+    {
+        if(!where || (*where)[k])
+        {
+            const Tet & K(Th[k]);
+            int iK[4] =  {Th(k,0),Th(k,1),Th(k,2),Th(k,3)};
+            R  fk[4]={phi[iK[0]]-phi0,phi[iK[1]]-phi0,phi[iK[2]]-phi0,phi[iK[3]]-phi0};
+            int ij[4] = {0,1,2,3};
+            for(int i=0;i<4;++i) for(int j=i+1;j<4;++j) if(fk[ij[i]] > fk[ij[j]]) swap(ij[i],ij[j]);
+            if(fk[ij[3]]<=0.) volumen += K.mesure();
+            else if(fk[ij[0]]>=0.) volumep += K.mesure();
+            else
+            {
+                //cout << "ij = {" << ij[0] << ',' << ij[1] << ',' << ij[2] << ',' << ij[3] << '}' << endl;
+                const R3 A[4] = {K[ij[0]],K[ij[1]],K[ij[2]],K[ij[3]]};
+                const R f[4] = {fk[ij[0]],fk[ij[1]],fk[ij[2]],fk[ij[3]]};
+                if(f[0]<0. && f[1]>=0.) //the only negative dof is f0
+                {
+                    double c = (f[0]*f[0]*f[0])/((f[0]-f[1])*(f[0]-f[2])*(f[0]-f[3]));
+                    volumen += c*K.mesure();
+                    volumep += (1.-c)*K.mesure();
+                }
+                else if(f[1]<0. && f[2]>=0.) //two negative dof, this is the hard case...
+                {
+                    const R3  A03 = A[3] + f[3]/(f[3]-f[0]) * (A[0]-A[3]) , A13 = A[3] + f[3]/(f[3]-f[1]) * (A[1]-A[3]),
+                    A02 = A[2] + f[2]/(f[2]-f[0]) * (A[0]-A[2]) , A12 = A[2] + f[2]/(f[2]-f[1]) * (A[1]-A[2]);
+                    double V1 = f[3]*f[3]/((f[3]-f[1])*(f[3]-f[0])) * K.mesure();
+                    double V2 = 1./6.*abs(det(A13-A[2],A12-A[2],A02-A[2]));
+                    double V3 = 1./6.*abs(det(A13-A[2],A02-A[2],A03-A[2]));
+                    volumep += V1+V2+V3;
+                    volumen += (K.mesure() - V1-V2-V3);
+                }
+                else
+                {
+                    double c = (f[3]*f[3]*f[3])/((f[3]-f[0])*(f[3]-f[1])*(f[3]-f[2]));
+                    volumen += (1.-c)*K.mesure();
+                    volumep += c*K.mesure();
+                }
+            }
+        }
+    }
+    return volumen;
+}
+double volumelevelset(Mesh3 * const &pTh,KN<double> * const &pphi,const double & phi0) {return volumelevelset(pTh,pphi,phi0,0);}
+
+
+
+void init_lgmesh() {
+  if(verbosity&&(mpirank==0) )  cout <<"lg_mesh ";
+  bamg::MeshIstreamErrorHandler = MeshErrorIO;
+
+  Global.Add("buildmesh","(",new OneOperatorCode<classBuildMesh>);
+  Global.Add("buildmesh","(",new OneOperatorCode<classBuildMeshArray>);
+  Global.Add("buildmesh","(",new OneOperatorCode<BuildMeshFile>);
+   
+  Global.Add("buildmeshborder","(",new OneOperator1s_<pmesh,const E_BorderN *>(BuildMeshBorder));    
+  Global.Add("adaptmesh","(",new OneOperatorCode<Adaptation>);
+  Global.Add("movemesh","(",new OneOperatorCode<MoveMesh>);
+  Global.Add("splitmesh","(",new OneOperatorCode<SplitMesh>);
+  Global.Add("checkmovemesh","(",new OneOperatorCode<CheckMoveMesh>);
+
+  /// <<square_keyword>> see [[file:AFunction.hpp::OneOperatorCode]]
+  Global.Add("square","(",new OneOperatorCode<MeshCarre2>);
+  Global.Add("square","(",new OneOperatorCode<MeshCarre2f>);
+
+  Global.Add("savemesh","(",new OneOperatorCode<SaveMesh>);
+  Global.Add("trunc","(", new Op_trunc_mesh);
+  Global.Add("readmesh","(",new OneOperator1_<pmesh,string*, E_F_F0_Add2RC<pmesh,string*> >(ReadMeshbamg));
+  Global.Add("emptymesh","(",new OneOperator1_<pmesh,pmesh, E_F_F0_Add2RC<pmesh,pmesh> >(EmptyTheMesh));
+  Global.Add("emptymesh","(",new OneOperator2_<pmesh,pmesh,KN<long> *, E_F_F0F0_Add2RC<pmesh,pmesh,KN<long>*> >(EmptyTheMesh));
+  Global.Add("triangulate","(",new OneOperator1_<pmesh,string*, E_F_F0_Add2RC<pmesh,string*> >(ReadTriangulate));
+  Global.Add("triangulate","(",new OneOperator2_<pmesh,KN_<double>,KN_<double>,E_F_F0F0_Add2RC<pmesh,KN_<double>,KN_<double>,E_F0> >(Triangulate));
+  TheOperators->Add("<-",
+		    new OneOperator2_<pmesh*,pmesh*,string* >(&initMesh));
+    // Thg,suppi[],nnn,unssd[]
+  Global.Add("AddLayers","(",new OneOperator4_<bool, Mesh * , KN<double> * , long ,KN<double> * >(AddLayers));
+  Global.Add("AddLayers","(",new OneOperator2_<bool, Mesh * , Mesh * >(SameMesh));
+  // use for :   mesh Th = readmesh ( ...);
+    //  Add FH mars 2015 to compute mesure under levelset ...
+    Global.Add("arealevelset","(",new OneOperator3_<double,Mesh *, KN<double>*,double>(arealevelset));
+    Global.Add("arealevelset","(",new OneOperator4_<double,Mesh *, KN<double>*,double,KN<double>*>(arealevelset));
+    //Global.Add("convectlevelset","(", new OneOperatorCode<ConvectLevelSet0 >( ));
+    Global.Add("volumelevelset","(",new OneOperator3_<double,Mesh3 *,KN<double>*,double>(volumelevelset));
+    Global.Add("volumelevelset","(",new OneOperator4_<double,Mesh3*,KN<double>*,double,KN<double>*>(volumelevelset));
+
+  TheOperators->Add("<-",
+		    new OneOperator2_<pmesh*,pmesh*,pmesh >(&set_copy_incr));
+  extern void init_glumesh2D();
+  init_glumesh2D();
+}
diff --git a/src/fflib/lgmesh.hpp b/src/fflib/lgmesh.hpp
new file mode 100644
index 0000000..8c77185
--- /dev/null
+++ b/src/fflib/lgmesh.hpp
@@ -0,0 +1,40 @@
+/*!
+ * \file 
+ * 
+ * \brief Exposed functions from lgmesh.cpp
+ * 
+ * 
+ * \author Written by Antoine Le Hyaric
+ * \author http://www.ljll.math.upmc.fr/lehyaric
+ * \author Laboratoire Jacques-Louis Lions
+ * \author Université Pierre et Marie Curie-Paris6, UMR 7598, Paris, F-75005 France
+ * 
+ * \copyright This file is part of Freefem++
+ * 
+ * \copyright Freefem++ is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * \copyright Freefem++ is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ * 
+ * \copyright You should have received a copy of the GNU Lesser General Public
+ * License along with Freefem++; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * 
+ * headeralh brief="Exposed functions from lgmesh.cpp" cpp default=0 dox freefem start=21/10/2013 upmc written
+ */
+
+  // <<Carre>> [[file:lgmesh.cpp::Carre]]
+  Fem2D::Mesh* Carre(int nx,int ny,Expression fx,Expression fy,Stack stack,int flags,KN_<long> lab,long reg=0);
+
+/*!
+ * Local Variables:
+ * mode:c++
+ * ispell-local-dictionary:"british"
+ * coding:utf-8
+ * End:
+ */
diff --git a/src/fflib/lgmesh3.cpp b/src/fflib/lgmesh3.cpp
new file mode 100644
index 0000000..3cea1ce
--- /dev/null
+++ b/src/fflib/lgmesh3.cpp
@@ -0,0 +1,1634 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "ff++.hpp"
+#include "array_resize.hpp"
+using Fem2D::Mesh;
+using Fem2D::MeshPoint;
+
+extern bool NoWait; 
+
+typedef Mesh * pmesh;
+typedef Mesh3 * pmesh3;
+
+map<pair<int,int>,int>::iterator closeto(map<pair<int,int>,int> & m, pair<int,int> & k)
+{
+    map<pair<int,int>,int>::iterator it= m.end();
+    for (int i=-1;i<2;++i)
+	for (int j=-1;j<2;++j)
+	  {
+	      pair<int,int>  kk(k.first+i,k.second+j);// bug corrigie april 2011 FH. tanks . J. Morice
+	      it=  m.find(kk);
+	      if(it != m.end()) return it;
+	  }
+    return it;
+}
+
+ inline void Perm3_I2J(const int *I,const int*J,int *S)
+{
+    if(I[0]==J[0]) S[0]=0;
+    else if(I[0]==J[1]) S[0]=1;
+    else {S[0]=2; assert(I[0]==J[2]) ;}
+    if(I[1]==J[0]) S[1]=0;
+    else if(I[1]==J[1]) S[1]=1;
+    else {S[1]=2; assert(I[1]==J[2]) ; }
+    S[2]=3-S[0]-S[1];
+    assert(I[2]==J[3-S[0]-S[1]]);
+}
+
+bool BuildPeriodic( 
+		   int nbcperiodic ,
+		   Expression *periodic,
+		   const Mesh3 &Th,Stack stack,
+		   KN<int> & ndfe) 
+{ 
+    
+    /*
+     build numbering of vertex form 0 to nbdfv-1
+     and build numbering  of  edge form 0 to nbdfe-1
+     we removing common vextex or common edge    
+     --  we suppose one df by vertex 
+     nbdfv number of df on vertex 
+     ndfv[i]  given the numero of the df of the vertex 
+     -- we suppose 1 df
+     */ 
+    typedef Mesh3::BorderElement BE;
+    //typedef Smallvect<int,2> int2;    
+    if (nbcperiodic ) {
+	
+	//    KN<int> ndfv(Th.nv);
+	//   KN<int> ndfe(Th.nbe);
+	//ffassert(ndfv.N()==Th.nv);
+	//ffassert(ndfe.N()==Th.nbe);
+        
+	MeshPoint *mp=MeshPointStack(stack),smp=*mp;   
+	int n= nbcperiodic;
+	if (verbosity >2)
+	    cout << " Nb of pair of periodic conditions (3d) : = " << n <<  endl;
+	int * link1=0;
+	int * link2=0;
+	KN<int*> plk1(n),plk2(n);
+	KN<int> nlk1(n),nlk2(n);
+	KN<int> lab1(n),lab2(n);
+#ifndef  HUGE_VAL      
+	const double infty= numeric_limits<double>::infinity();
+#else
+	const double infty= HUGE_VAL;
+#endif       
+	int nblink1, nblink2;
+	int *plink1 , *plink2;
+        for (int step=0;step<2;step++)
+	  {
+	      nblink1=0,     nblink2=0;
+	      plink1=link1,  plink2=link2;
+	      for (int ip=0, k=0;ip<n;ip++,k+=6)
+		{
+		    int label1=GetAny<long>((*periodic[k+0])(stack));
+		    int label2=GetAny<long>((*periodic[k+3])(stack));
+		    lab1[ip]=label1;
+		    lab2[ip]=label2;
+		    
+		    int l1=nblink1;
+		    int l2=nblink2;
+		    plk1[ip]= plink1;
+		    plk2[ip]= plink2;
+		    for (int ke=0;ke<Th.nbe;ke++)
+		      {
+			  if (Th.be(ke).lab==label1)
+			    {
+				if (plink1) *plink1++=ke;
+				nblink1++;
+			    }
+			  else if (Th.be(ke).lab==label2)
+			    {
+				if (plink2) *plink2++=ke;
+				nblink2++;
+			    }
+		      }
+		    nlk1[ip]= nblink1-l1;
+		    nlk2[ip]= nblink2-l2;              
+		}
+	      if(step) break; // no reallocl 
+	      if (verbosity >3)
+		  cout << "  Periodic = " << nblink1 << " " << nblink2 << " step=" << step << endl;
+	      if(nblink1 != nblink2)
+		    ExecError("Periodic 3d:  the both number of face is not the same ");
+		
+	      
+	      ndfe.resize(nblink1*2);
+	      link1 = new int[nblink1];
+	      link2 = new int[nblink2];
+	  }
+        if ( nblink1 >0) 
+	  {
+	      int indfe=0;
+	      for (int ip=0, k=0;ip<n;ip++,k+=6)
+		{
+		    map<pair<int,int>,int> m;
+		    const int kkx1=1,kky1=2,kkx2=4,kky2=5;
+		    int label1=lab1[ip],label2=lab2[ip];
+		    int n1=nlk1[ip],n2=nlk2[ip];
+		    int *pke1=plk1[ip], *pke2=plk2[ip];
+		    //int oip=pke1-link1;
+		    typedef HashTable<SortArray<int,3>,int> HTable;
+		    typedef HTable::iterator HTiterator;
+		    HashTable<SortArray<int,3>,int> table1(n1,Th.nv); //  Table of face lab 1
+		    R2 P[3];
+		    R2 Pmin(infty,infty),Pmax(-infty,-infty);
+		    double hmn=infty;
+		    int iface[3];
+		    if (verbosity >1)
+			cout << "  --Update: periodic  couple label1= " << label1 
+			     << ", n faces= " << n1 << "; "
+			<< ", label2= " << label2<<  ", n faces= " << n2 <<endl; 
+		    if (n1 != n2) 
+		      ExecError("periodic 3D BC:  the number of set of faces is not the same ");
+		    //  compute the hmn size to find common point 
+		    for (int i1=0;i1<n1;i1++)
+		      {
+			  const BE & e =Th.be(pke1[i1]);
+			  
+			  assert(e.lab==label1) ;
+			  {   
+			      for(int ee=0;ee<3;++ee)
+				{
+				    iface[ee]=Th(e[ee]);
+				    mp->set(e[ee].x,e[ee].y,e[ee].z);
+				    P[ee].x=GetAny<double>((*periodic[k+kkx1])(stack));
+				    P[ee].y=GetAny<double>((*periodic[k+kky1])(stack));
+				}
+			      
+			      HTiterator hte=table1.add(SortArray<int,3>(iface),pke1[i1]);
+			      ffassert(hte-table1.begin() == i1);
+			      for(int ee=0,eo=2;ee<3;eo=ee++)
+				{
+				    double l = (P[ee]-P[eo]).norme2();
+				    Pmin=Minc(Pmin,P[ee]);
+				    Pmax=Maxc(Pmax,P[ee]);
+				    hmn=Min(hmn,l);
+				}
+			      
+			      
+			  }                                
+		      }
+		    hmn=sqrt(hmn);
+		    ffassert(hmn>1.0e-20);
+		    double coef = 8/hmn;
+		    double x0 = Pmin.x;
+		    double y0 = Pmin.y;
+		    if (verbosity > 2)
+			cout << "  --Update: periodic " << Pmin << " " << Pmax << " " << " h=" << hmn 
+			<< " ,  coef = "<< coef << " / " << (Pmax-Pmin).norme2()*coef*coef << endl;
+		    ffassert(coef>1e-10 && (Pmax-Pmin).norme2()*coef*coef < 1.e14 ); // correct  FH mars 2013 
+		    
+		    //  map construction ----
+		    for (int i1=0;i1<n1;i1++)
+		      {
+			  int ie=pke1[i1];
+			  const BE & e =Th.be(ie);
+			  assert (e.lab==label1);
+			  for (int ne=0;ne<3;ne++)
+			    {
+				int kv=Th(e[ne]);
+				
+				// cout << ne << " " << kv << " " << " " << e[ne] << " ";
+				mp->set(e[ne].x,e[ne].y,e[ne].z);
+				double xx=GetAny<double>((*periodic[k+kkx1])(stack));
+				double yy=GetAny<double>((*periodic[k+kky1])(stack));
+				pair<int,int> ij((int) ((xx-x0)*coef),(int) ((yy-y0)*coef));				    
+				map<pair<int,int>,int>::iterator im=closeto(m,ij);
+				if (im==m.end())
+				  {
+				      if (verbosity >50)
+					  cout << kv << " " << xx << " " << yy << " ->   " << ij << " :: " << ie << endl;
+				      im=m.insert(pair<pair<int,int>,int>(ij,kv)).first;
+				  }
+				else {
+				    if(im->second != kv)
+					cout << kv << " ==  " << im->second << " " << xx << " " << yy << " ->   " << ij << " == " << im->first << endl;
+				    ffassert( im->second == kv);
+				}
+				
+			    }                                
+		      }
+		    //  find ...  face of list 2 in list 1 .... 
+		    int err=0;
+		    for (int i2=0;i2<n2;i2++)
+		      {
+			  int ie2=pke2[i2];
+			  const BE & e =Th.be(ie2);
+			  assert (e.lab==label2);
+			{
+			    if (verbosity >50)
+				cout << ie2 << " : " <<Th(e[0]) << " " << Th(e[1]) << " " << Th(e[2]) << ":: ";
+			    R2 P[3];
+			    pair<int,int> I[3];
+			    map<pair<int,int>,int>::iterator im;
+			    int i2to1[3];
+			    
+			    for(int ee=0;ee<3;++ee)
+			      {
+				  mp->set(e[ee].x,e[ee].y,e[ee].z);
+				  
+				  P[ee].x=GetAny<double>((*periodic[k+kkx2])(stack));
+				  P[ee].y=GetAny<double>((*periodic[k+kky2])(stack));
+				  I[ee].first = int((P[ee].x-x0)*coef);
+				  I[ee].second= int((P[ee].y-y0)*coef);
+				  im=closeto(m,I[ee]);
+				  
+				  if(im == m.end() )
+				    {
+					cout << " vertex : " << Th(e[ee]) << " " <<e[ee]<< "  Abscisses: s = "<< P[ee]   << "  " <<  I[ee] << endl; 
+					ExecError("periodic: Sorry one vertex of face is losted "); 
+				    }
+				  i2to1[ee] = im->second;
+				  
+			      }
+			    
+			    //int ie1=-1;
+			    SortArray<int,3> sf(i2to1);
+			    HTiterator ht=table1.find(sf);
+			    if( ! ht ) {
+				err++;
+				cerr << " missing face " << ie2 << " " << sf <<  endl;
+			    }
+			    else
+			      {
+				
+				  int ie1 = ht->v; 
+				  assert(ie1>=0  );
+				  const BE & eo =Th.be(ie1);
+				  int fo[3]={Th(eo[0]),Th(eo[1]),Th(eo[2])};
+				  
+				  int np1= NumPerm1<3>(fo); //  number of 
+				  int np2= NumPerm1<3>(i2to1);
+				  ndfe[indfe++]=ie1*8+np1; 
+				  ndfe[indfe++]=ie2*8+np2; 
+				  int p1[3],p2[3];
+				  SetNumPerm<3>(np1,p1);
+				  SetNumPerm<3>(np2,p2);
+				  if(verbosity>50)
+				      cout <<"  " << ie1 << " ==  " << ie2  << ":  " <<  fo[p1[0]] << " " << fo[p1[1]] << " " << fo[p1[2]] << " == " 
+				       << i2to1[p2[0]] << " " << i2to1[p2[1]] << " " << i2to1[p2[2]]  << "  e ="
+				       << Th(e[p2[0]]) << " " << Th(e[p2[1]]) << " " << Th(e[p2[2]])  << " "
+ 				      
+				           << " nu= " << np1 << " , " << np2  << endl;
+				 
+			      }
+			    
+			}
+		      }
+		    if(err ) {
+			cerr << " 3d periodic FE: number of  missing periodic faces " << err << endl; 
+			ExecError(" 3d periodic condition missing common face ");
+		    }
+		    
+		    
+		}
+	      *mp = smp;
+	      ffassert(indfe==ndfe.size());
+
+	      /*  rm  FH :
+	      for (int i=0;i<Th.nbe;i++)
+		  ndfe[i]=i;// circular link
+	      for (int i=0;i<Th.nv;i++)
+		  ndfv[i]=i;// circular link
+	      for (int i=0;i<nblink1;i++)
+		{
+		    int ie1=-link1[i]/8;
+		    int ie2=link2[i];
+		    int np=-link1[i]%8;
+		    int p[3]={np%3,np/3,3-np%3-np/3};
+		    if (verbosity >50)
+			cout << " face " << ie1 << " <==> " << ie2 << endl;
+		    ffassert(ie1!=ie2);
+		    if(!InCircularList(ndfe,ie1,ie2))   // merge of two list 
+			Exchange(ndfe[ie1],ndfe[ie2]);
+		    int kv1[3],kv2[3];
+		    // kv1 == kv2 (p) 
+		    const BE & e1=Th.be(ie1), &e2=Th.be(ie2);
+		    for (int ee=0;ee<3;ee++)
+		      {
+			  kv1[ee] =Th(e1[ee]);
+			  kv2[ee] =Th(e2[ee]);		           
+		      }
+		    for (int ee=0;ee<3;ee++)
+		      {
+			  int iv1=kv1[ee];
+			  int iv2=kv2[p[ee]];
+			  //  l'orientation de la face 2 / face 1  est  dans p.
+			  
+			  if (!InCircularList(ndfv,iv1,iv2)) {  // merge of two list 
+			      Exchange(ndfv[iv2],ndfv[iv1]);
+			      
+			      if (verbosity >50)
+				{ 
+				    int ii=iv1,l=1;
+				    while ( (ii=ndfv[ii]) != iv1 && l++<10) (void) 0;
+				    if( (verbosity >50) || ( l > 2 && verbosity >40)) 
+				     cout << l << "  vertex " << iv1 <<  "<==> " << iv2 << " list : " << iv1 << " " << Th(iv1) << " <=> " << Th(iv2);
+				    int i=iv1,k=0;
+				    while ( (i=ndfv[i]) != iv1 && k++<10)
+					cout << ", "<< i ; 
+				    cout << endl;
+				    
+				}}                  
+		      }
+		    
+		} 
+	      // generation de numero de dlt
+	      
+	      nbdfv = numeroteclink(ndfv) ; 
+	      nbdfe = numeroteclink(ndfe) ; 
+	      if (verbosity>2) 
+		  cout << "  -- nb df on vertices " << nbdfv << endl;
+	      */
+	      delete [] link1;
+	      delete [] link2;
+	      return true; //new FESpace(**ppTh,*tef,nbdfv,ndfv,nbdfe,ndfe);
+	  }
+	
+    }
+    return false;   
+}
+
+
+bool  v_fes3::buildperiodic(Stack stack, KN<int> & ndfe) { 
+    return BuildPeriodic(nbcperiodic,periodic,**ppTh,stack,ndfe);
+    
+}
+
+template<class Mesh> 
+class GlgVertex {
+public:
+  typedef double R;
+  typedef typename Mesh::Rd Rd;
+  typedef typename Mesh::Vertex Vertex;
+  CountPointer<Mesh> pTh;
+  const Vertex *v;
+  void Check() const {   if (!v || !pTh) { ExecError("Too bad! Unset Vertex!"); } }
+  void init() { v=0;pTh.init();}
+  GlgVertex(Mesh * Th,long kk): pTh(Th),v( &(*pTh)(kk)) {}
+  GlgVertex(Mesh * Th,const Vertex * kk): pTh(Th),v(kk) {}
+  operator int() const { Check(); return (* pTh)(v);} 
+  operator Rd*(){ Check(); return v;} 
+  R x() const {Check() ; return v->X();}
+  R y() const {Check() ; return v->Y();}
+  R z() const {Check() ; return v->Z();}
+  long lab() const {Check() ; return v->lab;}
+  void destroy()  {pTh.destroy();}
+};
+
+template<class Mesh>
+class GlgElement { public:
+typedef typename Mesh::Element Element;
+
+    struct Adj {// 
+	Mesh *pTh;
+	const Element *k;
+	Adj(const GlgElement<Mesh> & pp) : pTh(pp.pTh),k(pp.k) {}
+	GlgElement<Mesh> adj(long & e) const  {
+	    int ee,ko;
+	    ffassert(pTh && k && e >=0 && e < Element::nv );
+	    long kk=pTh->ElementAdj(ko=(*pTh)(k),ee=e);
+	    if(ee>=0) e=ee;//  ok adj exist
+	    else  return  GlgElement<Mesh>(pTh,ko);// return same .. 
+	    
+	return  GlgElement<Mesh>(pTh,kk);}
+    }; 
+    
+    CountPointer<Mesh> pTh;
+  const Element *k;
+  
+  GlgElement():  k(0) {}
+  void  Check() const  {   if (!k || !pTh) { ExecError("Unset Triangle,Sorry!"); } }
+  void init() { k=0;pTh.init();}
+  void destroy() {pTh.destroy();}
+  GlgElement(Mesh * Th,long kk): pTh(Th),k( &(*pTh)[kk]) {}
+  GlgElement(Mesh * Th,Element * kk): pTh(Th),k(kk) {}
+  operator int() const { Check(); return (* pTh)(k);} 
+  GlgVertex<Mesh> operator [](const long & i) const { Check(); return GlgVertex<Mesh>(pTh,&(*k)[i]);}   
+  long lab() const {Check() ; return k ? k->lab : 0;}
+  double mes() const {Check() ; return k->mesure() ;}
+  long n() const { return k ? Element::nv: 0 ;}
+    
+  bool operator==(const GlgElement & l) const { return pTh==l.pTh && k == l.k;}
+  bool operator!=(const GlgElement & l) const { return pTh!=l.pTh || k != l.k;}
+  bool operator<(const GlgElement & l) const { return pTh==l.pTh && k <l.k;}
+  bool operator<=(const GlgElement & l) const { return pTh==l.pTh && k <=l.k;}
+    
+};
+
+template<class Mesh>
+class GlgBoundaryElement { public:
+    
+    typedef typename Mesh::Element Element;
+    typedef typename Mesh::BorderElement BorderElement;
+    
+    struct BE {
+	Mesh * p;
+	BE(Mesh *pp) : p(pp) {}
+	BE(Mesh **pp) : p(*pp) {}
+	operator Mesh * () const {return p;}
+    };
+    
+    CountPointer<Mesh> pTh;
+    BorderElement *k;
+    
+    GlgBoundaryElement():  k(0) {}
+    void  Check() const  {   if (!k || !pTh) { ExecError("Unset BoundaryEdge,Sorry!"); } }
+    void init() { k=0;pTh.init();}
+    void destroy() {pTh.destroy();}
+    GlgBoundaryElement(Mesh * Th,long kk): pTh(Th),k( &(*pTh).be(kk)) {}
+    GlgBoundaryElement(Mesh * Th,BoundaryEdge * kk): pTh(Th),k(kk) {}
+    GlgBoundaryElement(const BE & be,long kk): pTh(be.p),k( &(*pTh).be(kk)) {}
+    GlgBoundaryElement(const BE & be,BoundaryEdge * kk): pTh(be.p),k(kk) {}
+    operator int() const { Check(); return (* pTh)(k);} 
+    GlgVertex<Mesh> operator [](const long & i) const { Check(); return GlgVertex<Mesh>(pTh,&(*k)[i]);}   
+    long lab() const {Check() ; return k ? k->lab : 0;}
+    double length() const {Check() ; return k->length()  ;}
+    long n() const { return k ? BorderElement::nv : 0 ;}
+    GlgElement<Mesh> element() const {Check() ;int ee; return GlgElement<Mesh>(pTh,(*pTh).BoundaryElement((*pTh)(k),ee));}
+    long nuBoundaryElement() const {Check() ;int ee;  (*pTh).BoundaryElement((*pTh)(k),ee);return ee;}
+    
+};
+
+GlgBoundaryElement<Mesh3> get_element(GlgBoundaryElement<Mesh3>::BE const & a, long const & n){  return GlgBoundaryElement<Mesh3>(a,n);}
+GlgVertex<Mesh3> get_element(GlgBoundaryElement<Mesh3> const & a, long const & n){  return a[n];}
+
+GlgElement<Mesh3> get_adj(GlgElement<Mesh3>::Adj const & a, long  * const & n){return  a.adj(*n);}
+
+GlgElement<Mesh3> get_element(pmesh3 const & a, long const & n) {  return GlgElement<Mesh3>(a,n);}
+GlgElement<Mesh3> get_element(pmesh3 *const & a, long const & n) {  return GlgElement<Mesh3>(*a,n);}
+
+GlgVertex<Mesh3> get_vertex(pmesh3 const & a, long const & n){ return GlgVertex<Mesh3>(a,n);}
+GlgVertex<Mesh3> get_vertex(pmesh3 *const & a, long const & n){ return GlgVertex<Mesh3>(*a,n);}
+GlgVertex<Mesh3> get_element(GlgElement<Mesh3> const & a, long const & n) {  return a[n];}
+
+GlgElement<Mesh3> getElement(GlgBoundaryElement<Mesh3> const & a)
+{    return a.element();}
+
+long NuElement(GlgBoundaryElement<Mesh3> const & a)
+{    return a.nuBoundaryElement(); }
+
+R getx(GlgVertex<Mesh3> const & a){  return a.x();}
+R gety(GlgVertex<Mesh3> const & a){  return a.y();}
+R getz(GlgVertex<Mesh3> const & a){  return a.z();}
+long  getlab(GlgVertex<Mesh3> const & a){  return a.lab();}
+long getlab(GlgElement<Mesh3> const & a){  return a.lab();}
+long getlab(GlgBoundaryElement<Mesh3> const & a){  return a.lab();}
+R getmes(GlgElement<Mesh3> const & a){  return a.mes();}
+
+double pmesh_mes(pmesh3 * p) { ffassert(p && *p) ;  return (**p).mes ;}
+double pmesh_mesb(pmesh3 * p) { ffassert(p && *p) ;  return (**p).mesb;}
+long pmesh_nt(pmesh3 * p) { ffassert(p && *p) ;  return (**p).nt ;}
+long pmesh_nv(pmesh3 * p) { ffassert(p && *p) ;  return (**p).nv ;}
+long pmesh_nbe(pmesh3 * p) { ffassert(p && *p) ;  return (**p).nbe ;}
+
+pf3rbase* get_element(pf3rbasearray *const & a, long const & n)
+{
+    return (**a)[n];
+}
+
+pf3r get_element(pf3rarray const & a, long const & n)
+{  //cout << " ************ " << n << " " << a.second << endl;
+    return pf3r( *(*a.first)[n],a.second);
+}
+
+//  complex case 
+pf3cbase* get_element(pf3cbasearray *const & a, long const & n)
+{
+    return (**a)[n];
+}
+pf3c get_element(pf3carray const & a, long const & n)
+{
+    return pf3c( *(*a.first)[n],a.second);
+}
+//  end complex case 
+
+class MoveMesh3 :  public E_F0mps { public:  
+ 
+   typedef pmesh  Result;
+   Expression getmesh;
+   Expression U,V;
+   int nbsol;    
+    vector<Expression> sol;
+   
+    MoveMesh3(const basicAC_F0 & args) :nbsol(args.size()-2),sol(args.size()-2)
+    {   
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+      args.SetNameParam();
+      getmesh=to<pmesh>(args[0]); 
+      const E_Array * a = dynamic_cast<const E_Array *>(args[1].LeftValue());
+      
+      ffassert(a);
+      if (a->size() !=2) CompileError("movemesh(Th,[u,v],...) need 2 componate in array ",atype<pmesh>());
+      U=to<double>( (*a)[0]);
+      V=to<double>( (*a)[1]);
+      
+      for (int i=2;i<args.size();i++)
+        sol[i-2]=to<double>(args[i]);      
+    }   
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh>(),atype<E_Array>(),true);}
+    static  E_F0 * f(const basicAC_F0 & args){ return new MoveMesh3(args);} 
+    AnyType operator()(Stack s) const ;
+  operator aType () const { return atype<Result>();} 
+
+};
+
+
+
+
+class ReadMesh3 :  public E_F0 { public:  
+    
+  Expression filename; 
+  typedef pmesh3  Result;
+  ReadMesh3(const basicAC_F0 & args) 
+  {   
+    args.SetNameParam(); 
+    filename=to<string*>(args[0]);   
+  }   
+  static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<string*>());}
+  static  E_F0 * f(const basicAC_F0 & args){ return new ReadMesh3(args);} 
+  AnyType operator()(Stack stack) const;
+};
+
+
+AnyType ReadMesh3::operator()(Stack stack) const 
+{
+  using  Fem2D::MeshPointStack;
+ 
+  string * fn =  GetAny<string*>((*filename)(stack));
+  cout << "ReadMesh3 " << *fn << endl;
+  Mesh3 *Thh = new Mesh3(*fn);
+  Thh->BuildGTree();
+  Add2StackOfPtr2FreeRC(stack,Thh);
+  return SetAny<pmesh3>(Thh);;
+  
+}
+
+class SaveMesh3 :  public E_F0 { public:  
+ 
+   typedef pmesh3  Result;
+   Expression getmesh;
+   Expression filename; 
+   Expression xx,yy,zz;  
+   SaveMesh3(const basicAC_F0 & args) 
+    {   
+      xx=0;
+      yy=0;
+      zz=0;
+      args.SetNameParam();
+      getmesh=to<pmesh3>(args[0]); 
+      filename=to<string*>(args[1]); 
+      if (args.size() >2) 
+        {
+          const E_Array * a = dynamic_cast<const E_Array *>(args[2].LeftValue());
+          if (!a) CompileError("savemesh(Th,\"filename\",[u,v,w],...");
+          int k=a->size() ;
+         // cout << k << endl;
+          if ( k!=2 && k !=3) CompileError("savemesh(Th,\"filename\",[u,v,w]) need 2 or 3  componate in array ",atype<pmesh>());
+          xx=to<double>( (*a)[0]);
+          yy=to<double>( (*a)[1]);
+          if(k==3)
+           zz=to<double>( (*a)[2]);
+         }
+      
+   }   
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh3>(),atype<string*>(),true);}
+    static  E_F0 * f(const basicAC_F0 & args){ return new SaveMesh3(args);} 
+    AnyType operator()(Stack s) const ;
+  
+};
+
+
+AnyType SaveMesh3::operator()(Stack stack) const 
+{
+  using  Fem2D::MeshPointStack;
+  
+  
+   pmesh3 Thh = GetAny<pmesh3>((*getmesh)(stack));
+   string * fn =  GetAny<string*>((*filename)(stack));
+   cout << "SaveMesh3 " << *fn << " " << Thh << endl;
+   Thh->Save(*fn);
+   return SetAny<pmesh3>(Thh);
+
+}
+
+class SaveSurfaceMesh3 :  public E_F0 { public:  
+ 
+    typedef pmesh  Result;
+  Expression getmesh;
+  Expression filename; 
+  Expression filename1;  
+  int pointsfaces;
+  SaveSurfaceMesh3(const basicAC_F0 & args) 
+  {   
+    args.SetNameParam();
+    getmesh=to<pmesh3>(args[0]); 
+    filename=to<string*>(args[1]); 
+    pointsfaces=0;
+    if (args.size() >2) 
+      {
+	if(BCastTo<string *>(args[2])){ 
+	  pointsfaces=1;
+	  filename1=CastTo<string*>(args[2]);
+	}  
+	else{
+	  CompileError("savesurfmesh(Th,filename.points,filename.faces)");
+	}
+      }
+    
+  }   
+  static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh3>(),atype<string*>(),true);}
+  static  E_F0 * f(const basicAC_F0 & args){ return new SaveSurfaceMesh3(args);} 
+  AnyType operator()(Stack s) const ;
+  
+};
+
+
+AnyType SaveSurfaceMesh3::operator()(Stack stack) const 
+{
+  using  Fem2D::MeshPointStack;
+  
+  
+  pmesh3 Thh = GetAny<pmesh3>((*getmesh)(stack));
+  string * fn =  GetAny<string*>((*filename)(stack));
+  if( pointsfaces==0 ){
+    cout << "SaveSurfaceMesh3 " << *fn << " " << Thh << endl;
+    Thh->SaveSurface(*fn);
+  }
+  else{
+    string * fn1 =  GetAny<string*>((*filename1)(stack));
+    cout << "SaveSurfaceMesh3 " << *fn << " " << *fn1 << " " << Thh << endl;
+    Thh->SaveSurface(*fn,*fn1); 
+  }
+  return SetAny<pmesh3>(Thh);
+  
+}
+
+
+
+AnyType MoveMesh3::operator()(Stack stack) const 
+{
+  ffassert(0);
+    /*
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+   MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+   Mesh * Thh = GetAny<pmesh>((*getmesh)(stack));
+   ffassert(Thh);
+   long nbv=Thh->nv;
+   long nbt=Thh->nt;
+   KN<double> u(nbv),v(nbv);
+   double infini=DBL_MAX;
+   u=infini;
+   for (int it=0;it<nbt;it++)
+    for (int iv=0;iv<3;iv++)
+    {
+      int i=(*Thh)(it,iv);
+      if ( u[i]==infini) { // if nuset the set 
+        mp->setP(Thh,it,iv);
+        u[i]=GetAny<double>((*U)(stack));
+        v[i]=GetAny<double>((*V)(stack));
+      }
+    }
+    
+   Mesh * pth= MoveTheMesh(*Thh,u,v);
+   if (pth)
+     for (size_t i=0;i<sol.size();i++)
+       { //  ale 
+          pair<FEbase<double>,int> * s = GetAny<pair<FEbase<double>,int>*>( (*sol[i])(stack));
+          ffassert(s->first.Vh);
+          ffassert( &s->first.Vh->Th == Thh); // same old mesh
+          ffassert(0); // a faire ????
+       }
+   *mp=mps;
+    pth->decrement();   
+    return SetAny<pmesh>(pth);
+    */
+}
+
+
+inline pmesh3 *  initMesh(pmesh3 * const & p, string * const & s) {
+  Mesh3 * m;
+  cout << " initMesh " << *s << endl;
+  *p= m =new Mesh3(*s); 
+  m->BuildGTree();
+ //  delete s;  modif mars 2006 auto del ptr 
+  return p;
+ }
+/*
+class CheckMoveMesh :  public E_F0mps { public:  
+ 
+   typedef double  Result;
+   Expression getmesh;
+   Expression U,V;
+   int nbsol;    
+    vector<Expression> sol;
+   
+    CheckMoveMesh(const basicAC_F0 & args) :nbsol(args.size()-2),sol(args.size()-2)
+    {   
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+      args.SetNameParam();
+      getmesh=to<pmesh>(args[0]); 
+      const E_Array * a = dynamic_cast<const E_Array *>(args[1].LeftValue());
+      
+      ffassert(a);
+      if (a->size() !=2) CompileError("CheckMoveMesh(Th,[u,v]) need 2 componate in array ",atype<pmesh>());
+      U=to<double>( (*a)[0]);
+      V=to<double>( (*a)[1]);
+      
+      for (int i=2;i<args.size();i++)
+        sol[i-2]=to<double>(args[i]);      
+    }   
+    static ArrayOfaType  typeargs() { return  ArrayOfaType(atype<pmesh>(),atype<E_Array>(),false);}
+    static  E_F0 * f(const basicAC_F0 & args){ return new CheckMoveMesh(args);} 
+    AnyType operator()(Stack s) const ;
+    operator aType () const { return atype<double>();}         
+  
+};
+AnyType CheckMoveMesh::operator()(Stack stack) const 
+{
+ 
+  using  Fem2D::Triangle;
+  using  Fem2D::Vertex;
+  using  Fem2D::R2;
+  using  Fem2D::BoundaryEdge;
+  using  Fem2D::Mesh;
+ // using  Fem2D::R;
+  using  Fem2D::MeshPointStack;
+   MeshPoint *mp(MeshPointStack(stack)) , mps=*mp;
+   Mesh * Thh = GetAny<pmesh>((*getmesh)(stack));
+   Mesh & Th(*Thh);
+   ffassert(Thh);
+   long nbv=Thh->nv;
+   long nbt=Thh->nt;
+   KN<double> u(nbv),v(nbv);
+   double infini=DBL_MAX;
+   u=infini;
+   for (int it=0;it<nbt;it++)
+    for (int iv=0;iv<3;iv++)
+    {
+      int i=(*Thh)(it,iv);
+      if ( u[i]==infini) { // if nuset the set 
+        mp->setP(Thh,it,iv);
+        u[i]=GetAny<double>((*U)(stack));
+        v[i]=GetAny<double>((*V)(stack));
+      }
+    }
+     double minarea=DBL_MAX;
+    for (int t=0;t<Th.nt;t++)
+     {
+      int i0=Th(t,0),i1=Th(t,1),i2=Th(t,2);
+      minarea=Min(minarea,Area2(R2(u[i0],v[i0]), R2(u[i1],v[i1]),R2(u[i2],v[i2])));
+     }
+    *mp=mps;
+    return SetAny<double>(minarea/2.);
+
+}
+*/
+
+template<class R>
+AnyType set_fe3 (Stack s,Expression ppfe, Expression e)
+{ 
+  typedef v_fes3 v_fes;
+  typedef typename  v_fes::pfes pfes;
+  typedef typename  v_fes::FESpace FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::FElement FElement;
+  typedef typename  Mesh::Element Element;
+  typedef typename  Mesh::Vertex Vertex;  
+  typedef typename  Mesh::RdHat RdHat;  
+  typedef typename  Mesh::Rd Rd;  
+  long kkff = Mesh::kfind,  kkth = Mesh::kthrough;
+  StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
+  
+  
+  MeshPoint *mps=MeshPointStack(s),mp=*mps;  
+  pair<FEbase<R,v_fes> *,int>  pp=GetAny<pair<FEbase<R,v_fes> *,int> >((*ppfe)(s));
+  FEbase<R,v_fes> & fe(*pp.first);
+  const  FESpace & Vh(*fe.newVh());
+  KN<R> gg(Vh.MaximalNbOfDF()); 
+  const  Mesh & Th(Vh.Th);
+  //   R F[100]; // buffer 
+  TabFuncArg tabexp(s,Vh.N);
+  tabexp[0]=e;
+  
+  if(Vh.N!=1)
+    {  cerr << " Try to set a  vectorial  FE function  (nb  componant=" <<  Vh.N << ") with one scalar " << endl;
+       ExecError(" Error interploation (set)  FE function (vectorial) with a scalar");
+    }
+  KN<R> * y=new  KN<R>(Vh.NbOfDF);
+  KN<R> & yy(*y);
+  // interpoler
+  int npPh = Vh.maxNbPtforInterpolation;
+  KNM<R>   Vp(npPh,1);
+  KN<R>  Vdf(Vh.MaxNbDFPerElement);
+  const E_F0 & ff(* (const  E_F0 *) e ) ;
+ //   cout << "Vh.isFEMesh() :" <<Vh.isFEMesh() << endl;
+  if (Vh.isFEMesh() )
+    {
+      
+      ffassert(Vh.NbOfDF == Th.nv && Vh.N == 1 );
+      for (int iv=0;iv<Th.nv;iv++)
+	{
+	  const Vertex & v(Th(iv));
+	  int ik=Th.Contening(&v);
+	  const Element & K(Th[ik]);
+	  int il=-1;
+	  for(int k=0;k<Element::nv;++k)
+	    if  ( &K[k] == &v) il=k;
+	  assert(il>=0);
+	  mps->setP(&Th,ik,il);
+	  yy[iv] = GetAny<R>( ff(s) );
+	  sptr->clean(); // modif FH mars 2006  clean Ptr
+	}
+      
+    }
+  else     
+    {
+      InterpolationMatrix<RdHat> ipmat(Vh);    
+      for (int t=0;t<Th.nt;t++)
+	{
+	  FElement K(Vh[t]);
+	  int nbdf=K.NbDoF() ;	  
+	  ipmat.set(K);
+	  for (int p=0;p<ipmat.np;p++)
+	    { 
+	      const RdHat & PtHat(ipmat.P[p]);
+	      mps->set(K.T(PtHat),PtHat,K);
+	      Vp[p]=GetAny<R>( ff(s) );
+	    }
+	  K.Pi_h(Vp,Vdf,ipmat);
+	 //   cout << "Vp::: " << Vp << " " << Vdf << endl;
+	  for (int df=0;df<nbdf;df++)         
+	    (*y)[K(df)] =  Vdf[df] ;
+	  sptr->clean(); // modif FH mars 2006  clean Ptr	
+	}
+    }
+  *mps=mp;
+  fe=y;
+  kkff = Mesh::kfind - kkff;
+  kkth = Mesh::kthrough -kkth;
+  
+  if(verbosity>1)
+    ShowBound(*y,cout) 
+      << " " << kkth << "/" << kkff << " =  " << double(kkth)/Max<double>(1.,kkff) << endl;
+  return SetAny<FEbase<R,v_fes>*>(&fe); 
+}
+
+
+template<class K,class v_fes>
+E_set_fev3<K,v_fes>::E_set_fev3(const E_Array * a,Expression pp) 
+  :aa(*a),ppfe(pp),optimize(true),
+   where_in_stack_opt(),optiexp0(),optiexpK() 
+   { 
+     aa.map(to<K>) ;
+     bool kdump=false;
+     if(optimize)
+       { // new code Optimized  -------
+	 int n=aa.size();
+	 deque<pair<Expression,int> > ll;
+	 MapOfE_F0 m;
+	 where_in_stack_opt.resize(n);
+	 size_t top = currentblock->OffSet(0), topbb=top; // FH. bofbof ??? 
+	 for (int i=0; i<n; i++)
+	   {
+	     Expression ee= aa[i].LeftValue();
+	     if (kdump)
+	       cout << "Optimize OneOperatorMakePtrFE:  type exp: " << typeid(*ee).name() << " "<<endl;
+	     where_in_stack_opt[i]=ee->Optimize(ll, m, top);
+	     if (kdump)
+	       cout  << "\n\t\t"<< i  << ": " << where_in_stack_opt[i] << endl;
+	   }
+	 
+	 currentblock->OffSet(top-topbb);
+	 //  
+	 int k=ll.size(),k0=0,k1=0;
+	 for (int i=0;i<k;i++)
+	   if (ll[i].first->MeshIndependent()) k0++;
+	 deque<pair<Expression,int> > l0(k0),l1(k-k0);
+	 k0=0,k1=0;
+	 for (int i=0;i<k;i++)
+	   if (ll[i].first->MeshIndependent()) 
+	     {
+	       if (kdump)
+		 cout << " mi " << ll[i].second << " " << *(ll[i].first) << endl;
+	       l0[k0++]=ll[i];
+	     }
+	   else 
+	     {
+	       if (kdump)
+		 cout << " md " << ll[i].second << " " << *(ll[i].first) << endl;
+	       l1[k1++]=ll[i];
+	     }
+	 if (k0)      
+	   optiexp0 = new E_F0_Optimize(l0,m,0);  // constant part
+	 if (k1) 
+	   optiexpK = new E_F0_Optimize(l1,m,0);  // none constant part
+	 
+       }
+     
+     
+   }
+
+
+template<class K,class v_fes>   
+AnyType E_set_fev3<K,v_fes>::operator()(Stack s)  const
+{  
+  StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);     
+  MeshPoint *mps=MeshPointStack(s), mp=*mps;   
+  FEbase<K,v_fes> ** pp=GetAny< FEbase<K,v_fes> **>((*ppfe)(s));
+  FEbase<K,v_fes> & fe(**pp);
+  const  FESpace & Vh(*fe.newVh());
+ // KN<K> gg(Vh.MaximalNbOfDF()); 
+  
+  
+  const  Mesh & Th(Vh.Th);
+  const int dim=Vh.N;
+  K ** copt=0;
+  if (optimize)   copt= new K *[dim];
+  if(copt) {
+    assert((size_t) dim== where_in_stack_opt.size());
+    for (int i=0;i<dim;i++)
+      {
+        int offset=where_in_stack_opt[i];
+        assert(offset>10);
+        copt[i]= static_cast<K *>(static_cast<void *>((char*)s+offset));
+        *(copt[i])=0;
+      }
+    if (optiexp0) (*optiexp0)(s); // init 
+  }
+  
+  ffassert(dim<100);
+  //   R F[100]; // buffer 
+  
+  TabFuncArg tabexp(s,Vh.N);
+  //   const E_Array * aa = dynamic_cast<const E_Array *>(e);
+  ffassert( aa.size() == Vh.N);
+  for (int i=0;i<dim;i++)
+    tabexp[i]=aa[i]; 
+  
+  KN<K> * y=new  KN<K>(Vh.NbOfDF);
+  KN<K> & yy(*y);
+  int npPh = Vh.maxNbPtforInterpolation;
+  KNM<K>   Vp(npPh,dim);
+  KN<K>  Vdf(Vh.MaxNbDFPerElement);
+  
+  if (Vh.isFEMesh() )
+    {
+      // crrect bug 29/08/2011 (thanks to rychet at fzu.cz)
+      // remove wrong bulid of KHat (memory out of bound)
+      ffassert(Vh.NbOfDF == Th.nv && dim == 1 );
+      for (int iv=0;iv<Th.nv;iv++)
+	{
+	  const E_F0 & ff(* (const  E_F0 *) aa[0]  ) ;
+	  const Vertex & v(Th(iv));
+	  int ik=Th.Contening(&v);
+	  const Element & Kv(Th[ik]);
+          int il=-1;
+          for(int k=0;k<Element::nv;++k)
+            if  ( &Kv[k] == &v) il=k;
+          assert(il>=0);
+          mps->set(Th,v,RdHat::KHat[il],Kv,v.lab);
+	  if (copt) {
+	    if (optiexpK) (*optiexpK)(s); 
+	    yy[iv] =  *(copt[0]);
+	  }
+	  else 
+	    yy[iv] = GetAny<K>( ff(s) );
+	  sptr->clean(); // modif FH mars 2006  clean Ptr
+       }
+    }
+  else
+    {
+       InterpolationMatrix<RdHat> ipmat(Vh);    
+       
+       for (int t=0;t<Th.nt;t++)
+	 {
+	   FElement Kt(Vh[t]);
+	   int nbdf=Kt.NbDoF();
+	   
+	   //gg=K();
+	   
+	   for (int p=0;p<ipmat.np;p++)
+	     {
+	       const RdHat & PtHat(ipmat.P[p]);
+	       mps->set(Kt.T(PtHat),PtHat,Kt);
+	       
+	       if (copt) { // optimize  version 
+		 if (optiexpK) (*optiexpK)(s);
+		 for (int j=0;j<dim;j++)
+		   Vp(p,j) = *(copt[j]);}
+	       else  // old version 
+		 for (int j=0;j<dim;j++)
+		   if (tabexp[j]) 
+		     Vp(p,j)=GetAny<K>( (*tabexp[j])(s) );
+		   else Vp(p,j)=0;
+	       
+	     }
+	   Kt.Pi_h(Vp,Vdf,ipmat);  
+	   //  cout << "Vp --- "<< Vp  << "  Vdf;; " << Vdf[0] << endl;
+	   for (int df=0;df<nbdf;df++)         
+	     yy[Kt(df)] =  Vdf[df] ;
+	   
+	   sptr->clean(); // modif FH mars 2006  clean Ptr          
+	 } 
+    }
+  fe=y;
+  if (copt) delete [] copt;
+  *MeshPointStack(s) = mp;
+  if(verbosity>1)
+    ShowBound(*y,cout) << endl ;
+  return Nothing;
+}
+
+
+template<class K>
+inline FEbase<K,v_fes> * MakePtrFE3_(pfes3 * const &  a){ 
+  FEbase<K,v_fes3> * p=new FEbase<K,v_fes3>(a);
+  return p ;}
+  
+template<class K>
+inline FEbase<K,v_fes3> ** MakePtrFE3_2(FEbase<K,v_fes3> * * const &  p,pfes3 * const &  a){ 
+  *p=new FEbase<K,v_fes3>(a);
+  return p ;}
+
+template<class K>  
+inline FEbaseArray<K,v_fes3> ** MakePtrFE3_3(FEbaseArray<K,v_fes3> * * const &  p,pfes3 * const &  a,const long & N){ 
+  *p=new FEbaseArray<K,v_fes3>(a,N);
+  return p ;}
+
+template<class K,class v_fes>
+class  OneOperatorMakePtrFE3 : public OneOperator 
+{
+public:
+  typedef typename  v_fes::pfes pfes;
+  typedef typename  v_fes::FESpace FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::FElement FElement;
+  typedef typename  Mesh::Element Element;
+  typedef typename  Mesh::Vertex Vertex;  
+  typedef typename  Mesh::RdHat RdHat;  
+  typedef typename  Mesh::Rd Rd;  
+
+  // il faut Optimize 
+  // typedef double K;
+  typedef  FEbase<K,v_fes> ** R;
+  typedef pfes* B;
+  class CODE : public E_F0mps  
+  {
+  public:
+    Expression fer,fes;
+    E_set_fev3<K,v_fes> * e_set_fev3;
+    const E_Array * v;
+    CODE(const basicAC_F0 & args) 
+      : 
+      fer(to<R>(args[0])),
+      fes(to<B>(args[1])),
+      e_set_fev3(0) 
+    {
+      if (BCastTo<K>(args[2]) )
+	v = new E_Array(basicAC_F0_wa(to<K>(args[2]))); 
+      else 
+	v = dynamic_cast<const E_Array *>( args[2].LeftValue() );
+      if (!v) {
+	cout << "Error: type of arg :" << *args[2].left()  << " in " << typeid(K).name() << " case " << endl;
+	ErrorCompile(" We wait  a double/complex expression or a array expression",1);
+      }
+      e_set_fev3=  new   E_set_fev3<K,v_fes>(v,fer);
+      
+    }
+    
+    AnyType operator()(Stack stack)  const {
+      R  p = GetAny<R>( (*fer)(stack));
+      B  a = GetAny<B>( (*fes)(stack)); 
+      *p=new FEbase<K,v_fes>(a);
+      (*e_set_fev3)(stack); 
+      return SetAny<R>(p);
+    }
+    operator aType () const { return atype<R>();}         
+    
+    
+  };
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { return  new CODE(args);}
+  OneOperatorMakePtrFE3(aType tt):  // tt= aType<double>() or aType<E_Array>()  
+    OneOperator(map_type[typeid(R).name()],map_type[typeid(R).name()],map_type[typeid(B).name()],tt)
+  {}
+};
+
+
+/*
+template<class K,class v_fes>    
+KN<K> * pf3r2vect( pair<FEbase<K,v_fes> *,int> p)
+ {  
+    KN<K> * x=p.first->x();
+    if ( !x) {  // defined 
+      FESpace3 * Vh= p.first->newVh();     
+      throwassert( Vh);
+      *p.first = x = new KN<K>(Vh->NbOfDF);
+      *x=K(); 
+    }
+    return x;}
+*/
+template<class K>        
+long pf3r_nbdf(pair<FEbase<K,v_fes3> *,int> p)
+ {  
+   if (!p.first->Vh) p.first->Vh= p.first->newVh();
+   throwassert( !!p.first->Vh);
+   return p.first->Vh->NbOfDF;
+ }
+
+long pVh3_ndof(pfes3 * p)
+ { throwassert(p && *p);
+   FESpace3 *fes=**p; ;  return fes->NbOfDF ;}
+long pVh3_nt(pfes3 * p)
+ { throwassert(p && *p);
+   FESpace3 *fes=**p; ;  return fes->NbOfElements ;}
+long pVh3_ndofK(pfes3 * p)
+ { throwassert(p && *p);
+   FESpace3 *fes=**p;   return (*fes)[0].NbDoF() ;}
+
+template<class R,int dd,class v_fes>
+AnyType pf3r2R(Stack s,const AnyType &a)
+{
+  typedef typename  v_fes::pfes pfes;
+  typedef typename  v_fes::FESpace FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::FElement FElement;
+  typedef typename  Mesh::Element Element;
+  typedef typename  Mesh::Vertex Vertex;  
+  typedef typename  Mesh::RdHat RdHat;  
+  typedef typename  Mesh::Rd Rd;  
+
+  
+  pair< FEbase<R,v_fes> *  ,int> ppfe=GetAny<pair< FEbase<R,v_fes> *,int> >(a);
+  FEbase<R,v_fes> & fe( *ppfe.first);
+  int componante=ppfe.second;
+  //  cout << "+++++++++++ " << componante <<endl;
+  if ( !fe.x()) {
+    if ( !fe.x()){
+      // CompileError(" Sorry unset fem array ");
+      return   SetAny<R>(0.0);
+    }
+  }
+  
+  const FESpace & Vh(*fe.Vh);
+  const Mesh & Th(Vh.Th);
+  MeshPoint & mp = *MeshPointStack(s);
+  const Element *K;
+  RdHat PHat;
+  bool outside=false;
+  bool qnu=true;
+  if ( mp.Th3 && mp.Th3->elements == Th.elements && mp.T)
+   {
+     qnu=false;
+     K=mp.T3;
+     PHat=mp.PHat;
+   }
+  else if ( mp.other.Th3 
+            && (mp.other.Th3->elements ==  Th.elements)
+            && (mp.other.P.x == mp.P.x) && (mp.other.P.y == mp.P.y) && (mp.other.P.z == mp.P.z)   )
+    {
+      K=mp.other.T3;
+      PHat=mp.other.PHat;
+      outside = mp.other.outside;
+    } 
+  else {
+    if (mp.isUnset()) ExecError("Try to get unset x,y, ...");
+    K=Th.Find(mp.P,PHat,outside);
+    mp.other.set(Th,mp.P,PHat,*K,0,outside);
+  }
+  if(verbosity>100)
+    {
+    if(outside)
+	cout << "  ---  " << qnu << "  " << mp.P << " out=" << mp.outside <<  " out=" << outside << " K= " << K << " " << PHat << endl;
+    else 
+	cout << "  ---  " << qnu << " P=  " << mp.P << " out=" << mp.outside <<  " out=" << outside << " K(PHat) == P =  " <<  (*K)(PHat) << " PHat = " << PHat << endl;
+    }
+  const FElement KK(Vh[Th(K)]);
+  if (outside && KK.tfe->discontinue)
+  {   if(verbosity>=10000) cout << " outside f() = 0. " << KK.tfe->discontinue << "\n";
+    return   SetAny<R>(0.0);
+  }
+#ifndef NDEBUG
+  if (!outside) 
+    {
+      if ( Norme2_2( (*K)(PHat) - mp.P ) > 1e-12 )
+        cout << "bug ??  " << Norme2_2( (*K)(PHat) - mp.P ) << " " << mp.P << " " << (*K)(PHat) << endl;
+    } 
+#endif
+/*  int nbdf=KK.NbDoF();
+  
+  int N= KK.N;
+  KN_<R> U(*fe.x());
+  KNMK<R> fb(nbdf,N,3); //  the value for basic fonction
+  KN<R> fk(nbdf);
+  for (int i=0;i<nbdf;i++) // get the local value
+    fk[i] = U[KK(i)];
+    //  get value of basic function
+  KK.BF(PHat,fb);  
+  
+  R r = (fb('.',componante,dd),fk);  
+*/
+  
+ const R rr = KK(PHat,*fe.x(),componante,dd);
+//  cout << " " << rr << endl;
+//  R2 B(mp.P);
+/*   if ( r < 0.08001 &&  Norme2_2(mp.P) > 0.05  && Norme2_2(mp.P) < 0.4*0.4  ) 
+     {
+     int vv=verbosity;
+      cout << " f()  triangle  " << Th(K) << " " << mp.P << " " << PHat << " =  " << r << " " <<outside ;
+      if (outside) {  verbosity = 200;
+         K=Th.Find(mp.P,PHat,outside);
+          cout << Th(K) << " " << outside << endl;}
+       cout << endl; verbosity=vv;
+     } */
+//  if ( qnu )   
+ //  cout << " f()  triangle       " << Th(K) << " " << mp.P << " " << PHat << " =  " << r <<  endl;
+ if(verbosity>=10000)
+      cout << componante<< " "<< dd << " f()  Tet:  " << Th(K) << " " << mp.P << " " << PHat << " =  " << rr <<  endl; 
+  return SetAny<R>(rr);
+}
+
+
+template<class K,class v_fes>
+class Op4_pf32K : public quad_function<pair<FEbase<K,v_fes> *,int>,R,R,R,K> { public:
+    
+    
+    class Op : public E_F0mps { public:
+	Expression a,b,c,d;
+      Op(Expression aa,Expression bb,Expression cc,Expression dd) 
+	: a(aa),b(bb),c(cc),d(dd) {}       
+      AnyType operator()(Stack s)  const 
+      { 
+	
+	R xx(GetAny<R>((*b)(s)));
+	R yy(GetAny<R>((*c)(s)));
+	R zz(GetAny<R>((*d)(s)));
+	MeshPoint & mp = *MeshPointStack(s),mps=mp;
+	mp.set(xx,yy,zz);
+	AnyType ret = pf3r2R<K,0,v_fes>(s,(*a)(s));
+	mp=mps;
+	return  ret;}
+      
+    };
+};
+
+template<class K,class v_fes>    
+KN<K> * pf3r2vect( pair<FEbase<K,v_fes> *,int> p)
+{  
+  //  cout << "  pf3r2vect " << endl;
+  typedef typename  v_fes::FESpace FESpace;
+  KN<K> * x=p.first->x();
+  if ( !x) {  // defined 
+    FESpace * Vh= p.first->newVh();     
+    throwassert( Vh);
+    *p.first = x = new KN<K>(Vh->NbOfDF);
+    *x=K(); 
+  }
+  return x;}
+
+// add 19 jan 2009 FH
+
+class pVh3_ndf : public ternary_function<pfes3 *,long,long,long> { public:
+    
+    
+    class Op : public E_F0mps { public:
+	Expression a,b,c;
+	Op(Expression aa,Expression bb,Expression cc) : a(aa),b(bb),c(cc) {}       
+	AnyType operator()(Stack s)  const 
+        { 
+	    pfes3 * p(GetAny<pfes3 *>((*a)(s)));
+	    long  k(GetAny<long>((*b)(s)));
+	    long  i(GetAny<long>((*c)(s)));
+	    throwassert(p && *p);
+	    FESpace3 *fes=**p;
+	    throwassert(fes && k >=0 && k < fes->NbOfElements );
+	    FESpace3::FElement K=(*fes)[k];
+	    throwassert(i>=0 && i <K.NbDoF() );
+	    long ret(K(i));
+	    return  ret;
+	}
+	
+    };
+};
+
+
+/*  no trivial ....   FH jan 2009..  */
+class Op4_Mesh32mp : public quad_function<pmesh3*,R,R,R,MeshPoint *> { public:
+    class Op : public E_F0mps { public:
+	Expression a,b,c,d;
+	Op(Expression aa,Expression bb,Expression cc,Expression dd) : a(aa),b(bb),c(cc),d(dd) {}       
+	AnyType operator()(Stack s)  const 
+        { 
+	    R xx(GetAny<R>((*b)(s)));
+	    R yy(GetAny<R>((*c)(s)));
+	    R zz(GetAny<R>((*d)(s)));
+	    pmesh3 *ppTh(GetAny<pmesh3*>((*a)(s)));
+	    if( !ppTh || !*ppTh) ExecError("Op3_Mesh32mp unset mesh ??");
+	    pmesh3 pTh(*ppTh);
+	    MeshPoint * mp = new MeshPoint();
+	    mp->set(xx,yy,zz);
+	    R3 PHat;
+	    bool outside;
+	    const Tet * K=pTh->Find(mp->P,PHat,outside);
+	    int n=(*pTh)(K);
+	    if(verbosity>200)
+	    cout << " n Tet = " << n << " " << K << " " <<  mp->P <<  endl;
+	    mp->set(*pTh,mp->P,PHat,*K,0,outside);
+	return mp;}
+	
+    };
+};
+
+
+// FH
+
+// add Feb. 2010 FH 
+template<class A> inline AnyType DestroyKN(Stack,const AnyType &x){
+    KN<A> * a=GetAny<KN<A>*>(x);
+    for (int i=0;i<a->N(); i++)
+	(*a)[i]->destroy();
+    a->destroy(); 
+    return  Nothing;
+}
+template<class RR,class A,class B>  
+RR * get_elementp_(const A & a,const B & b){ 
+    if( b<0 || a->N() <= b) 
+      { cerr << " Out of bound  0 <=" << b << " < "  << a->N() << " array type = " << typeid(A).name() << endl;
+	  ExecError("Out of bound in operator []");}
+    return  &((*a)[b]);}
+
+template<class R>  R * set_initinit( R* const & a,const long & n){ 
+    SHOWVERB( cout << " set_init " << typeid(R).name() << " " << n << endl);
+    a->init(n);
+    for (int i=0;i<n;i++)
+	(*a)[i]=0;
+    return a;}
+
+void init_mesh3_array()
+{
+    Dcl_Type<KN<pmesh3> *>(0,::DestroyKN<pmesh3> );
+    atype<KN<pmesh3>* >()->Add("[","",new OneOperator2_<pmesh3*,KN<pmesh3>*,long >(get_elementp_<pmesh3,KN<pmesh3>*,long>));
+    TheOperators->Add("<-", 
+		      new OneOperator2_<KN<pmesh3> *,KN<pmesh3> *,long>(&set_initinit));
+    map_type_of_map[make_pair(atype<long>(),atype<pmesh3>())]=atype<KN<pmesh3>*>(); // vector
+    
+    Dcl_Type< Resize<KN<pmesh3> > > ();
+    Add<KN<pmesh3>*>("resize",".",new OneOperator1< Resize<KN<pmesh3> >,KN<pmesh3>*>(to_Resize));
+    Add<Resize<KN<pmesh3> > >("(","",new OneOperator2_<KN<pmesh3> *,Resize<KN<pmesh3> > , long   >(resizeandclean1));
+    
+    
+}
+
+
+void init_lgmesh3() {
+  if(verbosity&&(mpirank==0))  cout <<"lg_mesh3 ";
+
+    //   Global.Add("buildmesh","(",new OneOperatorCode<classBuildMesh3>);
+    // Global.Add("buildmesh","(",new OneOperatorCode<BuildMeshFile3>);
+
+ atype<pmesh3>()->AddCast( new E_F1_funcT<pmesh3,pmesh3*>(UnRef<pmesh3 >)); 
+ atype<pfes3 >()->AddCast(  new E_F1_funcT<pfes3,pfes3*>(UnRef<pfes3>));
+ 
+ atype<pf3rbase>()->AddCast(  new E_F1_funcT<pf3rbase,pf3rbase>(UnRef<pf3rbase>));
+ atype<pf3cbase>()->AddCast(  new E_F1_funcT<pf3cbase,pf3cbase>(UnRef<pf3cbase>));
+ 
+ Add<pf3r>("[]",".",new OneOperator1<KN<double> *,pf3r>(pf3r2vect<R,v_fes3>));
+ Add<pf3c>("[]",".",new OneOperator1<KN<Complex> *,pf3c>(pf3r2vect<Complex,v_fes3>));
+ Add<pf3r>("(","",new OneQuadOperator<Op4_pf32K<R,v_fes3>,Op4_pf32K<R,v_fes3>::Op> );
+ Add<pf3c>("(","",new OneQuadOperator<Op4_pf32K<Complex,v_fes3>,Op4_pf32K<Complex,v_fes3>::Op> );
+ Add<double>("(","",new OneQuadOperator<Op4_K2R<R>,Op4_K2R<R>::Op> );
+// Add<long>("(","",new OneTernaryOperator<Op3_K2R<long>,Op3_K2R<long>::Op> ); // FH stupide 
+ Add<Complex>("(","",new OneQuadOperator<Op4_K2R<Complex>,Op4_K2R<Complex>::Op> );
+ Add<pmesh3 *>("(","",new OneQuadOperator<Op4_Mesh32mp,Op4_Mesh32mp::Op> );
+
+ 
+ TheOperators->Add("<-",
+       new OneOperator2_<pmesh3*,pmesh3*,string* >(&initMesh));
+       
+// use for :   mesh Th = readmesh ( ...);       
+  TheOperators->Add("<-",
+       new OneOperator2_<pmesh3*,pmesh3*,pmesh3 >(&set_copy_incr));
+
+  TheOperators->Add("=",
+		    new OneOperator2<pmesh3*,pmesh3*,pmesh3 >(&set_eqdestroy_incr)
+		    );
+  
+ 
+  Global.Add("readmesh3","(",new OneOperatorCode<ReadMesh3>);
+  Global.Add("savemesh","(",new OneOperatorCode<SaveMesh3>);
+  Global.Add("savesurfacemesh","(",new OneOperatorCode<SaveSurfaceMesh3>);
+
+   Dcl_Type<GlgVertex<Mesh3> >(); 
+   Dcl_Type<GlgElement<Mesh3> >( ); 
+    Dcl_Type<GlgElement<Mesh3>::Adj>( ); 
+    
+    Dcl_Type<GlgBoundaryElement<Mesh3>::BE >( ); 
+    Dcl_Type<GlgBoundaryElement<Mesh3> >( ); 
+    
+   atype<long>()->AddCast( 
+			  new E_F1_funcT<long,GlgVertex<Mesh3> >(Cast<long,GlgVertex<Mesh3> >),
+			  new E_F1_funcT<long,GlgElement<Mesh3> >(Cast<long,GlgElement<Mesh3> >),
+			  new E_F1_funcT<long,GlgBoundaryElement<Mesh3> >(Cast<long,GlgBoundaryElement<Mesh3> >)
+
+			   );
+
+   Add<pmesh3>("[","",new OneOperator2_<GlgElement<Mesh3>,pmesh3,long>(get_element));
+   Add<pmesh3*>("[","",new OneOperator2_<GlgElement<Mesh3>,pmesh3*,long>(get_element));
+   Add<pmesh3>("(","",new OneOperator2_<GlgVertex<Mesh3>,pmesh3,long>(get_vertex));
+   Add<pmesh3*>("(","",new OneOperator2_<GlgVertex<Mesh3>,pmesh3*,long>(get_vertex));
+
+    Add<pmesh3*>("be",".",new OneOperator1_<GlgBoundaryElement<Mesh3>::BE,pmesh3*>(Build));
+    Add<GlgElement<Mesh3> >("adj",".",new OneOperator1_<GlgElement<Mesh3>::Adj,GlgElement<Mesh3> >(Build));
+    Add<GlgBoundaryElement<Mesh3>::BE>("(","",new OneOperator2_<GlgBoundaryElement<Mesh3>,GlgBoundaryElement<Mesh3>::BE,long>(get_element));
+    Add<GlgElement<Mesh3>::Adj>("(","",new OneOperator2_<GlgElement<Mesh3>,GlgElement<Mesh3>::Adj,long*>(get_adj));
+    TheOperators->Add("==", new OneBinaryOperator<Op2_eq<GlgElement<Mesh3>,GlgElement<Mesh3> > >);
+    TheOperators->Add("!=", new OneBinaryOperator<Op2_ne<GlgElement<Mesh3>,GlgElement<Mesh3> > >);
+    TheOperators->Add("<", new OneBinaryOperator<Op2_lt<GlgElement<Mesh3>,GlgElement<Mesh3> > >);
+    TheOperators->Add("<=", new OneBinaryOperator<Op2_le<GlgElement<Mesh3>,GlgElement<Mesh3> > >);
+
+    Add<GlgBoundaryElement<Mesh3> >("label",".",new OneOperator1_<long,GlgBoundaryElement<Mesh3> >(getlab));
+    Add<GlgBoundaryElement<Mesh3> >("Element",".",new OneOperator1_<GlgElement<Mesh3> ,GlgBoundaryElement<Mesh3> >(getElement));
+    Add<GlgBoundaryElement<Mesh3> >("whoinElement",".",new OneOperator1_<long,GlgBoundaryElement<Mesh3> >(NuElement));
+    
+
+   Add<GlgElement<Mesh3> >("[","",new OneOperator2_<GlgVertex<Mesh3> ,GlgElement<Mesh3> ,long>(get_element));
+   Add<GlgBoundaryElement<Mesh3> >("[","",new OneOperator2_<GlgVertex<Mesh3>,GlgBoundaryElement<Mesh3>,long>(get_element));
+ 
+   Add<GlgVertex<Mesh3> >("x",".",new OneOperator1_<R,GlgVertex<Mesh3> >(getx));
+   Add<GlgVertex<Mesh3> >("y",".",new OneOperator1_<R,GlgVertex<Mesh3> >(gety));
+   Add<GlgVertex<Mesh3> >("z",".",new OneOperator1_<R,GlgVertex<Mesh3> >(getz));
+   Add<GlgVertex<Mesh3> >("label",".",new OneOperator1_<long,GlgVertex<Mesh3> >(getlab));
+   Add<GlgElement<Mesh3> >("label",".",new OneOperator1_<long,GlgElement<Mesh3> >(getlab));
+   Add<GlgElement<Mesh3> >("region",".",new OneOperator1_<long,GlgElement<Mesh3> >(getlab));
+   Add<GlgElement<Mesh3> >("mesure",".",new OneOperator1_<double,GlgElement<Mesh3> >(getmes));
+   Add<pmesh3*>("mesure",".",new OneOperator1<double,pmesh3*>(pmesh_mes));
+   Add<pmesh3*>("bordermesure",".",new OneOperator1<double,pmesh3*>(pmesh_mesb));
+   Add<pmesh3*>("nt",".",new OneOperator1<long,pmesh3*>(pmesh_nt));
+   Add<pmesh3*>("nv",".",new OneOperator1<long,pmesh3*>(pmesh_nv));
+   Add<pmesh3*>("nbe",".",new OneOperator1<long,pmesh3*>(pmesh_nbe));
+
+ TheOperators->Add("<-",
+       new OneOperator2_<pf3rbase*,pf3rbase*,pfes3* >(MakePtrFE3_2),
+       new OneOperator3_<pf3rbasearray*,pf3rbasearray*,pfes3*,long >(MakePtrFE3_3),  
+
+
+       new OneOperator2_<pf3cbase*,pf3cbase*,pfes3* >(MakePtrFE3_2),
+       new OneOperator3_<pf3cbasearray*,pf3cbasearray*,pfes3*,long >(MakePtrFE3_3) //,
+     //  new OneOperator2_<pmesharray*,pmesharray*,long >(MakePtr)
+       
+       
+       );
+ TheOperators->Add("<-",
+		   new OneOperatorMakePtrFE3<double,v_fes3>(atype<double>()),  //  scalar case
+		   new OneOperatorMakePtrFE3<double,v_fes3>(atype<E_Array>()),  //  vect case
+		   new OneOperatorMakePtrFE3<Complex,v_fes3>(atype<Complex>()),  //  scalar complex  case
+		   new OneOperatorMakePtrFE3<Complex,v_fes3>(atype<E_Array>())  //  vect complex case
+       );
+ TheOperators->Add("<-",
+       new OneOperator2_<pfes3*,pfes3*,pfes3>(&set_copy_incr));
+
+ TheOperators->Add("=",
+		   new OneOperator2<pfes3*,pfes3*,pfes3>(&set_eqdestroy_incr)
+		   ); 
+
+
+ TheOperators->Add("=",
+       new OneOperator2_<pf3r,pf3r,double,E_F_StackF0F0opt2<double> >(set_fe3<double>) ,
+       new OneOperator2_<pf3c,pf3c,Complex,E_F_StackF0F0opt2<Complex> >(set_fe3<Complex>)        
+       ) ;     
+
+
+ map_type[typeid(double).name()]->AddCast(
+   new E_F1_funcT<double,pf3r>(pf3r2R<R,0,v_fes3>)
+   );
+   
+ map_type[typeid(Complex).name()]->AddCast(
+   new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,0,v_fes3>)
+   );
+
+ Global.Add("dz","(",new OneOperatorCode<CODE_Diff<Ftest,op_dz> >);
+ Global.Add("dxz","(",new OneOperatorCode<CODE_Diff<Ftest,op_dxz> >);
+ Global.Add("dyz","(",new OneOperatorCode<CODE_Diff<Ftest,op_dyz> >);
+ Global.Add("dzx","(",new OneOperatorCode<CODE_Diff<Ftest,op_dzx> >);
+ Global.Add("dzx","(",new OneOperatorCode<CODE_Diff<Ftest,op_dzy> >);
+ Global.Add("dzz","(",new OneOperatorCode<CODE_Diff<Ftest,op_dzz> >);
+
+
+ Global.Add("dz","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dz> >);
+ Global.Add("dxz","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dxz> >);
+ Global.Add("dyz","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dyz> >);
+ Global.Add("dzx","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dzx> >);
+ Global.Add("dzx","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dzy> >);
+ Global.Add("dzz","(",new OneOperatorCode<CODE_Diff<Finconnue,op_dzz> >);
+
+
+ 
+// bof  
+ Global.Add("dx","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dx,v_fes3>));
+ Global.Add("dy","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dy,v_fes3>));
+ Global.Add("dz","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dz,v_fes3>));
+ Global.Add("dxx","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dxx,v_fes3>));
+ Global.Add("dyy","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dyy,v_fes3>));
+ Global.Add("dxy","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dxy,v_fes3>));
+ Global.Add("dyx","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dyx,v_fes3>));
+ Global.Add("dzx","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dzx,v_fes3>));
+ Global.Add("dzy","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dzy,v_fes3>));
+ Global.Add("dzz","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dzz,v_fes3>));
+ Global.Add("dxz","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dxz,v_fes3>));
+ Global.Add("dyz","(",new E_F1_funcT<double,pf3r>(pf3r2R<R,op_dyz,v_fes3>));
+
+
+
+ Global.Add("dx","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dx,v_fes3>));
+ Global.Add("dy","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dy,v_fes3>));
+ Global.Add("dz","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dz,v_fes3>));
+ Global.Add("dxx","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dxx,v_fes3>));
+ Global.Add("dyy","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dyy,v_fes3>));
+ Global.Add("dxy","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dxy,v_fes3>));
+ Global.Add("dyx","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dyx,v_fes3>));
+ Global.Add("dzx","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dzx,v_fes3>));
+ Global.Add("dzy","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dzy,v_fes3>));
+ Global.Add("dzz","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dzz,v_fes3>));
+ Global.Add("dxz","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dxz,v_fes3>));
+ Global.Add("dyz","(",new E_F1_funcT<Complex,pf3c>(pf3r2R<Complex,op_dyz,v_fes3>));
+
+
+ Global.Add("int3d","(",new OneOperatorCode<CDomainOfIntegration3d>);
+ Global.Add("int2d","(",new OneOperatorCode<CDomainOfIntegrationBorder3d>);
+ Global.Add("intallfaces","(",new OneOperatorCode<CDomainOfIntegrationAllFaces>);
+
+
+ /*decommente par J. Morice 14/01/09*/ 
+ Add<pf3r>("n",".",new OneOperator1<long,pf3r>(pf3r_nbdf<R>));
+ Add<pf3c>("n",".",new OneOperator1<long,pf3c>(pf3r_nbdf<Complex>));
+ Add<pfes3*>("ndof",".",new OneOperator1<long,pfes3*>(pVh3_ndof));
+ Add<pfes3*>("nt",".",new OneOperator1<long,pfes3*>(pVh3_nt));
+ Add<pfes3*>("ndofK",".",new OneOperator1<long,pfes3*>(pVh3_ndofK));
+
+ //Add<pf3rbasearray*>("[","",new OneOperator2_<pf3rbase*,pf3rbasearray*,long>(get_element));
+ //Add<pf3rarray>("[","",new OneOperator2_<pf3r,pf3rarray,long>(get_element));
+ //Add<pf3carray>("[","",new OneOperator2_<pf3c,pf3carray,long>(get_element));
+ 
+    // 3d new code 
+    Add<pf3cbasearray*>("[","",new OneOperator2_<pf3cbase*,pf3cbasearray*,long>(get_element));  // use ???? FH sep. 2009 
+    Add<pf3rbasearray*>("[","",new OneOperator2_<pf3rbase*,pf3rbasearray*,long>(get_element));  //  use ???? FH sep. 2009 
+    Add<pf3rarray>("[","",new OneOperator2_FE_get_elmnt<double,v_fes3>());// new version FH sep 2009
+    Add<pf3carray>("[","",new OneOperator2_FE_get_elmnt<Complex,v_fes3>());
+    
+ 
+ Add<pfes3*>("(","", new OneTernaryOperator<pVh3_ndf,pVh3_ndf::Op>  );
+init_mesh3_array();   
+ 
+}
+//#include "InitFunct.hpp"
+//static addingInitFunct TheaddingInitFunct(-10,init_lgmesh3);
+template E_set_fev3<double,v_fes3>::E_set_fev3(const E_Array * a,Expression pp) ;
+template E_set_fev3<Complex,v_fes3>::E_set_fev3(const E_Array * a,Expression pp) ;
diff --git a/src/fflib/lgmesh3.hpp b/src/fflib/lgmesh3.hpp
new file mode 100644
index 0000000..9beb150
--- /dev/null
+++ b/src/fflib/lgmesh3.hpp
@@ -0,0 +1,40 @@
+#ifndef LGMESH3_HPP
+#define LGMESH3_HPP
+// 3d
+typedef FEbase<double,v_fes3> * pf3rbase ;
+typedef FEbaseArray<double,v_fes3> * pf3rbasearray ;
+typedef pair<pf3rbase,int> pf3r ;
+typedef pair<pf3rbasearray,int> pf3rarray ;
+
+typedef FEbase<Complex,v_fes3> * pf3cbase ;
+typedef FEbaseArray<Complex,v_fes3> * pf3cbasearray ;
+typedef pair<pf3cbase,int> pf3c ;
+typedef pair<pf3cbasearray,int> pf3carray ;
+// fin
+bool isSameMesh(const list<C_F0> & largs,const void * Thu,const void * Thv,Stack stack) ; // true => VF type of Matrix   
+  //bool isSameMesh(const list<C_F0> & largs,const Mesh * Thu,const Mesh * Thv,Stack stack)  ;
+
+
+inline C_F0 CCastToR(const C_F0 & f){ return C_F0(atype<double>()->CastTo(f),atype<double>());}
+inline bool BCastToR(const C_F0 & f){ return atype<double>()->CastingFrom(f.left());}
+
+
+
+inline C_F0 CCastToC(const C_F0 & f){ return C_F0(atype<Complex>()->CastTo(f),atype<Complex>());}
+inline bool BCastToC(const C_F0 & f){ return atype<Complex>()->CastingFrom(f.left());}
+
+template<class Result>
+inline Expression CastTo(const C_F0 & f) { return atype<Result>()->CastTo(f);}
+
+template<class Result>
+inline bool BCastTo(const C_F0 & f) { return atype<Result>()->CastingFrom(f.left());}
+
+inline void Check(bool  v,const char * mess)
+{
+  if (!v) { cerr << " Error " << mess ;
+  throw(ErrorExec(mess,1));
+  }
+}           
+
+ 
+#endif
diff --git a/src/fflib/lgsolver.hpp b/src/fflib/lgsolver.hpp
new file mode 100644
index 0000000..565c289
--- /dev/null
+++ b/src/fflib/lgsolver.hpp
@@ -0,0 +1,612 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "gmres.hpp"
+typedef void *    pcommworld;
+
+namespace  Fem2D {
+
+// hack ---  F. Hecht -----
+
+//  une fonction pour change un tableau de 
+
+// complex en tableau de real 
+
+//  Idee faire
+
+// Une class qui tranforme une matrice complex en matric real
+
+// et faire de transformateur de vecteur
+
+
+inline KN_<double> C2R(KN_<complex<double> > & vc)
+
+{ 
+
+  assert(vc.step==1); 
+
+  complex<double> * pc=vc; // pointeur du tableau
+
+  double *pr = static_cast<double*>(static_cast<void*>(pc));
+
+  return KN_<double>(pr,vc.N()*2);
+
+}
+
+
+inline const KN_<double> C2R(const KN_<complex<double> > & vc)
+
+{ 
+
+  assert(vc.step==1); 
+
+  complex<double> * pc=vc; // pointeur du tableau
+
+  double *pr = static_cast<double*>(static_cast<void*>(pc));
+
+  return KN_<double>(pr,vc.N()*2);
+
+}
+
+
+
+
+inline KN_<complex<double> > R2C(KN_<double>  & vr)
+
+{
+
+  assert(vr.step==1 && vr.N() %2 ==0);
+
+  double *pr =vr; // pointeur du tableau
+
+   complex<double> * pc  = static_cast<complex<double>* >(static_cast<void*>(pr));
+
+  return KN_<complex<double> >(pc,vr.N()/2);
+
+}
+
+
+
+inline const KN_<complex<double> > R2C(const KN_<double>  & vr)
+
+{
+
+  assert(vr.step==1 && vr.N() %2 ==0);
+
+  double *pr =vr; // pointeur du tableau
+
+   complex<double> * pc  = static_cast<complex<double>* >(static_cast<void*>(pr));
+
+  return KN_<complex<double> >(pc,vr.N()/2);
+
+}
+
+
+
+//  une classe pour transforme une Matrice complex en Matrice  real 
+
+// -----------------------------------------------------------------
+
+template <class MM>
+class MatC2R : public VirtualMatrice<double> { public:
+
+  typedef typename VirtualMatrice<double>::plusAx plusAx;
+
+  //  typedef  VirtualMatrice<complex<double> > M;
+
+  const MM &m;
+
+  MatC2R(const MM &mm):
+      VirtualMatrice<double>(mm.N*2,mm.M*2),m(mm) {}
+
+  void addMatMul(const  KN_<double>  & x, KN_<double> & Ax) const {
+
+    R2C(Ax) += m*R2C(x);
+
+  }
+
+  plusAx operator*(const KN<double> &  x) const {return plusAx(this,x);}
+  virtual bool ChecknbLine(int n) const { return !N ||n==N;}  
+  virtual bool ChecknbColumn(int m) const { return !M ||m==M;}
+
+
+};
+
+
+
+template<class R>
+class SolveGCPrecon :   public MatriceMorse<R>::VirtualSolver , public VirtualMatrice<R>{
+  int n;
+  int nbitermax;
+  double eps;
+  mutable double  epsr;
+  const E_F0 * precon;
+  KN<R> D1;   // pour le CL bloque (tgv)
+  mutable KN<R> xx; 
+  Expression xx_del, code_del; 
+  Stack stack;
+  typedef typename VirtualMatrice<R>::plusAx plusAx;
+ 
+  public:
+  SolveGCPrecon(const MatriceMorse<R> &A,const OneOperator * C,Stack stk,int itmax, double epsilon=1e-6) : 
+    VirtualMatrice<R>(A.n),
+    n(A.n),nbitermax(itmax?itmax: Max(100,n)),eps(epsilon),epsr(0),precon(0),
+    D1(n),xx(n),stack(stk)
+{
+      assert(C); 
+
+      WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+      throwassert(A.sym());
+      Type_Expr te_xx(CPValue(xx));
+      xx_del=te_xx.second;
+      C_F0 e_xx(te_xx); // 1 undelete pointer
+      code_del= C->code(basicAC_F0_wa(e_xx));
+      precon =  to<KN_<R> >(C_F0(code_del,*C));// 2 undelete pointer
+      
+      throwassert(precon);
+      R aii;
+      A.getdiag(D1);
+     for (int i=0;i<n;i++)
+       D1[i] = (Fem2D::norm(aii=D1[i]) < 1e-20 ? R(1.) : R(1.)/aii);
+      
+}
+   void Solver(const MatriceMorse<R> &a,KN_<R> &x,const KN_<R> &b) const  {
+     epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+     ConjuguedGradient<R,MatriceMorse<R>,SolveGCPrecon<R>,StopGC<R> >(a,*this,b,x,nbitermax,epsr);
+   }
+plusAx operator*(const KN_<R> &  x) const {return plusAx(this,x);} 
+
+
+ void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  { 
+    assert(x.N()==Ax.N());
+      
+    xx=x;
+   // cout << x[0] << "  ";
+    xx=GetAny<KN_<R> >((*precon)(stack));
+    WhereStackOfPtr2Free(stack)->clean(); 
+  //  cout << (xx)[0] << "  " << endl;
+    R dii;
+    for (int i=0;i<n;i++) 
+       Ax[i] += ((dii=D1[i])==1.0) ? (xx)[i] : x[i]*dii;
+  }
+
+    
+  ~SolveGCPrecon(){
+
+  WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005    
+  delete  xx_del;
+  delete  code_del;
+// cout << "~SolveGCPrecon " << endl;
+ }
+  virtual bool ChecknbLine(int n) const { return true;}  
+  virtual bool ChecknbColumn(int m) const { return true;} 
+
+};     
+
+template<class R>
+class SolveGMRESPrecon :   public MatriceMorse<R>::VirtualSolver , public VirtualMatrice<R>{
+  int n;
+  int nbitermax;
+  double eps;
+  mutable double  epsr;
+  const E_F0 * precon;
+  KN<R> D1;  
+  mutable KN<R> xx; 
+  Expression xx_del, code_del;    
+  Stack stack;
+  int dKrylov; 
+  typedef typename VirtualMatrice<R>::plusAx plusAx;
+  public:
+  SolveGMRESPrecon(const MatriceMorse<R> &A,const OneOperator * C,Stack stk,int dk=50,int itmax=0,double epsilon=1e-6) : 
+    VirtualMatrice<R>(A.n),
+    n(A.n),nbitermax(itmax?itmax: Max(100,n)),eps(epsilon),epsr(0),precon(0),
+    D1(n),xx(n),
+    stack(stk),dKrylov(dk)
+
+{
+      assert(C); 
+      WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+      // C_F0 e_xx(CPValue(xx));
+      //precon =  to<KN_<R> >(C_F0(C->code(basicAC_F0_wa(e_xx)),*C));
+      Type_Expr te_xx(CPValue(xx));
+      xx_del=te_xx.second;
+      C_F0 e_xx(te_xx); // 1 undelete pointer
+      code_del= C->code(basicAC_F0_wa(e_xx));
+      precon =  to<KN_<R> >(C_F0(code_del,*C));// 2 undelete pointer
+      
+      throwassert(precon);
+    
+      R aii;
+      A.getdiag(D1);
+      double tgv = D1.linfty(); 
+      if( tgv < 1e5) tgv = 1e100; // if no tgv remove .. 
+     // if(verbosity>10 ) cout << "        in Precon GMRES, find tgv = " << tgv << endl;
+      for (int i=0;i<n;i++)
+        D1[i] = (std::abs(D1[i]) <  tgv ) ? R(1.)  : R() ; // remove the tgv ...
+      
+}
+   void Solver(const MatriceMorse<R> &a,KN_<R> &x,const KN_<R> &b) const  {
+     epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+  //   ConjuguedGradient<R,MatriceMorse<R>,SolveGCPrecon<R> >(a,*this,b,x,nbitermax,epsr);
+      KNM<R> H(dKrylov+1,dKrylov+1);
+      int k=dKrylov,nn=nbitermax;
+
+      //int res=
+      GMRES(a,(KN<R> &)x, (const KN<R> &)b,*this,H,k,nn,epsr,verbosity);
+
+   }
+plusAx operator*(const KN_<R> &  x) const {return plusAx(this,x);} 
+
+
+ void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  { 
+    assert(x.N()==Ax.N());
+      
+    xx=x;
+   // cout << x[0] << "  ";
+    xx=GetAny<KN_<R> >((*precon)(stack)); // xx value of the preoco 
+    WhereStackOfPtr2Free(stack)->clean(); 
+
+//    cout << (xx)[0] << "  " << endl;
+ //   R dii;
+  //   for (int i=0;i<n;i++) // take on value 
+  //     Ax[i] += (D1[i]) ? xx[i] : x[i];//  remove dii ... mars 2011
+    Ax += xx; 
+  }
+
+    
+  ~SolveGMRESPrecon(){
+  delete  xx_del;
+  delete  code_del;
+   WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005    
+  // cout << "~SolveGMRESPrecon; " << endl;
+ }
+  virtual bool ChecknbLine(int n) const { return true;}  
+  virtual bool ChecknbColumn(int m) const { return true;} 
+ 
+};     
+
+template<class R>
+class SolveGMRESDiag :   public MatriceMorse<R>::VirtualSolver , public VirtualMatrice<R>{
+  int n;
+  int nbitermax;
+  double eps;
+  mutable double  epsr;
+  int dKrilov;
+  KN<R> D1;
+  public:
+  typedef typename VirtualMatrice<R>::plusAx plusAx;
+  SolveGMRESDiag(const MatriceMorse<R> &A,int nbk=50,int itmax=0,double epsilon=1e-6) : 
+     VirtualMatrice<R>(A.n),
+    n(A.n),nbitermax(itmax?itmax: Max(100,n)),eps(epsilon),epsr(0),
+    dKrilov(nbk) ,D1(n)
+  { 
+    R aii=0;
+    A.getdiag(D1);
+    for (int i=0;i<n;i++)
+      D1[i] = (norm(aii=D1[i]) < 1e-20 ? R(1.) : R(1.)/aii);}
+
+   void Solver(const MatriceMorse<R> &a,KN_<R> &x,const KN_<R> &b) const  {
+      epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+   //  ConjuguedGradient<R,MatriceMorse<R>,SolveGCDiag<R> >(a,*this,b,x,nbitermax,epsr);
+         KNM<R> H(dKrilov+1,dKrilov+1);
+      int k=dKrilov,nn=nbitermax;
+      //int res=
+      GMRES(a,(KN<R> &)x,(const KN<R> &)b,*this,H,k,nn,epsr,verbosity);
+
+ }
+
+plusAx  operator*(const KN_<R> &  x) const {return plusAx(this,x);} 
+
+
+ void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  { 
+     assert(x.N()==Ax.N());
+   for (int i=0;i<n;i++) 
+     Ax[i]+= D1[i]*x[i];}
+     
+  virtual bool ChecknbLine(int n) const { return true;}  
+  virtual bool ChecknbColumn(int m) const { return true;} 
+
+};   
+
+template<>
+class SolveGMRESDiag<Complex> :   public MatriceMorse<Complex>::VirtualSolver , public VirtualMatrice<Complex>{
+   int n;
+  int nbitermax;
+  KN<Complex> D1;
+  double eps;
+  mutable double  epsr;
+  int dKrilov;
+  public:
+  typedef  VirtualMatrice<Complex>::plusAx plusAx;
+  SolveGMRESDiag(const MatriceMorse<Complex> &A,int nbk=50,int itmax=0,double epsilon=1e-6) : 
+    VirtualMatrice<Complex>(A.n),
+    n(A.n),nbitermax(itmax?itmax: Max(100,n)),D1(n),eps(epsilon),epsr(0),
+    dKrilov(nbk) 
+  { 
+    Complex aii=0;
+    A.getdiag(D1);
+    for (int i=0;i<n;i++)
+      D1[i] = (Fem2D::norm(aii=D1[i]) < 1e-20 ? Complex(1.) : Complex(1.)/aii);}
+
+   void Solver(const MatriceMorse<Complex> &a,KN_<Complex> &x,const KN_<Complex> &b) const  {
+      epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+   //  ConjuguedGradient<Complex,MatriceMorse<Complex>,SolveGCDiag<Complex> >(a,*this,b,x,nbitermax,epsr);
+         KNM<double> H(dKrilov+1,dKrilov+1);
+      int k=dKrilov,nn=nbitermax;
+      KN_<double> rx=C2R(x);
+      const  KN_<double> rb=C2R(b);
+      typedef MatC2R<MatriceMorse<Complex> > VA;
+      typedef MatC2R<SolveGMRESDiag<Complex> > VC;
+      VA AR(a);
+      VC CR(*this);
+      //int res=
+      GMRES(AR,(KN<double> &)rx,(const KN<double> &)rb,CR,H,k,nn,epsr,verbosity);
+
+ }
+
+plusAx  operator*(const KN_<Complex> &  x) const {return plusAx(this,x);} 
+
+
+ void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  { 
+     assert(x.N()==Ax.N());
+   for (int i=0;i<n;i++) 
+     Ax[i]+= D1[i]*x[i];}
+     
+  virtual bool ChecknbLine(int n) const { return true;}  
+  virtual bool ChecknbColumn(int m) const { return true;} 
+
+};   
+
+template<>
+class SolveGMRESPrecon<Complex> :   public MatriceMorse<Complex>::VirtualSolver , public VirtualMatrice<Complex>{
+  public:
+  int n;
+  int nbitermax;
+  Expression xx_del, code_del; 
+  const E_F0 * precon;
+  Stack stack;
+  double eps;
+  mutable double  epsr;
+  int dKrylov; 
+  KN<Complex> D1;  
+  mutable KN<Complex> xx;  
+  typedef  VirtualMatrice<Complex>::plusAx plusAx;
+  public:
+  SolveGMRESPrecon(const MatriceMorse<Complex> &A,const OneOperator * C,Stack stk,int dk=50,int itmax=0,double epsilon=1e-6) : 
+    VirtualMatrice<Complex>(A.n),   
+    n(A.n),nbitermax(itmax?itmax: Max(100,n)),
+    xx_del(0),code_del(0),
+    precon(0),stack(stk),eps(epsilon),epsr(0),dKrylov(dk),
+    D1(n),xx(n)
+{
+      assert(C); 
+      WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH mars 2005   
+      Type_Expr te_xx(CPValue(xx));
+      xx_del=te_xx.second;
+      C_F0 e_xx(te_xx); // 1 undelete pointer
+      code_del= C->code(basicAC_F0_wa(e_xx));
+      precon =  to<KN_<R> >(C_F0(code_del,*C));// 2 undelete pointer
+      //C_F0 e_xx(CPValue(xx));
+      //precon =  to<KN_<Complex> >(C_F0(C->code(basicAC_F0_wa(e_xx)),*C));
+      
+      throwassert(precon);
+      Complex aii;
+      A.getdiag(D1);
+      for (int i=0;i<n;i++)
+	D1[i] = Fem2D::norm(aii=D1[i])<1e-20 ? Complex(1.0) : Complex(1.)/aii;
+      
+}
+   void Solver(const MatriceMorse<Complex> &a,KN_<Complex> &x,const KN_<Complex> &b) const  {
+     epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+    // cout << " epsr = " << epsr << endl;
+  //   ConjuguedGradient<Complex,MatriceMorse<Complex>,SolveGCPrecon<Complex> >(a,*this,b,x,nbitermax,epsr);
+      KNM<double> H(dKrylov+1,dKrylov+1);
+      int k=dKrylov,nn=nbitermax;
+
+      KN_<double> rx=C2R(x);
+      const  KN_<double> rb=C2R(b);
+      typedef MatC2R<MatriceMorse<Complex> > VA;
+      typedef MatC2R<SolveGMRESPrecon<Complex> > VC;
+      VA AR(a);
+      VC CR(*this);
+      //int res=
+	GMRES(AR,(KN<double> &)rx,(const KN<double> &)rb,CR,H,k,nn,epsr,verbosity);
+      
+      // assert(0); // a faire 
+      //int res=GMRES(a,(KN<double> &)x, (const KN<double> &)b,*this,H,k,nn,epsr);
+
+   }
+plusAx operator*(const KN_<Complex> &  x) const {return plusAx(this,x);} 
+
+
+ void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  { 
+    assert(x.N()==Ax.N());
+      
+    xx=x;
+   // cout << x[0] << "  ";
+    xx=GetAny<KN_<Complex> >((*precon)(stack));
+       WhereStackOfPtr2Free(stack)->clean(); 
+
+//    cout << (xx)[0] << "  " << endl;
+    Complex dii;
+    for (int i=0;i<n;i++) 
+       Ax[i] += ((dii=D1[i])==1.0) ? (xx)[i] : x[i]*dii;
+  }
+
+    
+  ~SolveGMRESPrecon(){
+    WhereStackOfPtr2Free(stack)->clean(); // FH mars 2005    
+    delete  xx_del;
+    delete  code_del;
+  
+  // cout << "~SolveGMRESPrecon; " << endl;
+ }
+   virtual bool ChecknbLine(int ) const { return true;}  
+  virtual bool ChecknbColumn(int ) const { return true;} 
+
+ 
+};     
+
+
+template<class R>
+typename MatriceMorse<R>::VirtualSolver *
+BuildSolverGMRES(DCL_ARG_SPARSE_SOLVER(R,A))
+{
+    typename MatriceMorse<R>::VirtualSolver * ret=0;
+    if (ds.precon)
+	ret=new SolveGMRESPrecon<R>(*A,(const OneOperator *)ds.precon,stack,ds.NbSpace,ds.itmax,ds.epsilon);
+    else 
+	ret=new SolveGMRESDiag<R>(*A,ds.NbSpace,ds.itmax,ds.epsilon);
+    
+    return ret;	
+}
+
+template<class R>
+typename MatriceMorse<R>::VirtualSolver *
+BuildSolverCG(DCL_ARG_SPARSE_SOLVER(R,A)  )
+{
+    typename MatriceMorse<R>::VirtualSolver * ret=0;
+    if (ds.precon)
+	ret=new SolveGCPrecon<R>(*A,(const OneOperator *)ds.precon,stack,ds.itmax,ds.epsilon);
+    else 
+	ret=new SolveGCDiag<R>(*A,ds.itmax,ds.epsilon);    
+    return ret;
+}
+
+
+#define LIST_NAME_PARM_MAT \
+    {  "init", &typeid(bool)}, \
+    {  "solver", &typeid(TypeSolveMat*)}, \
+    {  "eps", &typeid(double)  }, \
+    {  "precon",&typeid(Polymorphic*)}, \
+    {  "dimKrylov",&typeid(long)}, \
+    {  "tgv",&typeid(double )}, \
+    {  "factorize",&typeid(bool)}, \
+    {  "strategy",&typeid(long )}, \
+    {  "tolpivot",&typeid(double )}, \
+    {  "tolpivotsym",&typeid(double )}, \
+    {  "nbiter", &typeid(long)}, \
+    { "datafilename", &typeid(string*)} , \
+    { "lparams",&typeid(KN_<long>)} , \
+    { "dparams", &typeid(KN_<double>)},  \
+    { "smap", &typeid(map<string,string>*)}, \
+    { "permr", &typeid(KN_<long>)}, \
+    { "permc", &typeid(KN_<long>)}, \
+    { "scaler", &typeid(KN_<double>)}, \
+    { "scalec", &typeid(KN_<double>)}, \
+    { "sparams", &typeid(string*)}, \
+    { "commworld", &typeid(pcommworld)}, \
+    { "master", &typeid(long)} \
+
+
+
+const int NB_NAME_PARM_MAT =  22  ;
+    
+/*
+ {  "init", &typeid(bool)},
+ {  "solver", &typeid(TypeSolveMat*)},
+ {  "eps", &typeid(double)  },
+ {  "precon",&typeid(Polymorphic*)}, 
+ {  "dimKrylov",&typeid(long)},
+ {  "bmat",&typeid(Matrice_Creuse<R>* )},
+ {  "tgv",&typeid(double )},
+ {  "factorize",&typeid(bool)},
+ {  "strategy",&typeid(long )},
+ {  "tolpivot",&typeid(double )},
+ {  "tolpivotsym",&typeid(double )},
+ {  "nbiter", &typeid(long)}, // 11
+ //  avril 2009  FH
+ { "datafilename",& &typeid(string*)} 
+ { "lparams",& &typeid(KN_<long>)} 
+ { "dparams",& &typeid(KN_<double>)} 
+ { "smap", &typeid(map<string,string>*)} 
+ { "permr", &typeid(KN_<long>)} 
+ { "permc", &typeid(KN_<long>)} 
+ { "scaler", &typeid(KN_<double>)} 
+ { "scalec", &typeid(KN_<double>)} 
+ 
+*/  
+    
+template<class R>
+inline void SetEnd_Data_Sparse_Solver(Stack stack,Data_Sparse_Solver & ds,Expression const *nargs ,int n_name_param)
+    {
+	int kk = n_name_param-NB_NAME_PARM_MAT-1;
+	if (nargs[++kk]) ds.initmat= ! GetAny<bool>((*nargs[kk])(stack));	
+	if (nargs[++kk]) ds.typemat= GetAny<TypeSolveMat *>((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.epsilon= GetAny<double>((*nargs[kk])(stack));
+	if (nargs[++kk])
+	{// modif FH fev 2010 ...
+	  const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(nargs[kk]);
+	  if(op)
+	   ds.precon = op->Find("(",ArrayOfaType(atype<KN<R>* >(),false)); // strange bug in g++ is R become a double
+	}
+      
+	if (nargs[++kk]) ds.NbSpace= GetAny<long>((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.tgv= GetAny<double>((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.factorize= GetAny<bool>((*nargs[kk])(stack));	
+	if (nargs[++kk]) ds.strategy = GetAny<long>((*nargs[kk])(stack)); 
+	if (nargs[++kk]) ds.tol_pivot = GetAny<double>((*nargs[kk])(stack)); 
+	if (nargs[++kk]) ds.tol_pivot_sym = GetAny<double>((*nargs[kk])(stack)); 
+	if (nargs[++kk]) ds.itmax = GetAny<long>((*nargs[kk])(stack)); //  frev 2007 OK
+	if (nargs[++kk]) ds.data_filename = *GetAny<string*>((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.lparams = GetAny<KN_<long> >((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.dparams = GetAny<KN_<double> >((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.smap = GetAny<MyMap<String,String> *>((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.perm_r = GetAny<KN_<long> >((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.perm_c = GetAny<KN_<long> >((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.scale_r = GetAny<KN_<double> >((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.scale_c = GetAny<KN_<double> >((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.sparams = *GetAny<string*>((*nargs[kk])(stack));
+	if (nargs[++kk]) ds.commworld = GetAny<pcommworld>((*nargs[kk])(stack));
+#ifdef VDATASPARSESOLVER
+        if (nargs[++kk]) ds.master = GetAny<long>((*nargs[kk])(stack));
+#endif
+  /* de datafilename a scalec */
+/*	
+	if (nargs[++kk]) ds.param_int= GetAny< KN<int> >((*nargs[kk+12])(stack));  // Add J. Morice 02/09 
+	if (nargs[kk+13]) ds.param_double= GetAny< KN<double> >((*nargs[kk+13])(stack));
+	if (nargs[kk+14]) ds.param_char= GetAny< string * >((*nargs[kk+14])(stack));  //
+	if (nargs[kk+15]) ds.perm_r = GetAny< KN<int > >((*nargs[kk+15])(stack));
+	if (nargs[kk+16]) ds.perm_c = GetAny< KN<int> >((*nargs[kk+16])(stack));  //
+	if (nargs[kk+17]) ds.file_param_int= GetAny< string* >((*nargs[kk+17])(stack));  // Add J. Morice 02/09 
+	if (nargs[kk+18]) ds.file_param_double= GetAny< string* >((*nargs[kk+18])(stack));
+	if (nargs[kk+19]) ds.file_param_char= GetAny< string* >((*nargs[kk+19])(stack));  //
+	if (nargs[kk+20]) ds.file_param_perm_r = GetAny< string* >((*nargs[kk+20])(stack));
+	if (nargs[kk+21]) ds.file_param_perm_c = GetAny< string* >((*nargs[kk+21])(stack));  //
+*/	
+	assert(++kk == n_name_param);
+    }
+} // end of namespace Fem2D
diff --git a/src/fflib/load.cpp b/src/fflib/load.cpp
new file mode 100644
index 0000000..d6c5edf
--- /dev/null
+++ b/src/fflib/load.cpp
@@ -0,0 +1,168 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include "config-wrapper.h" // needed for HAVE_DLFCN_H
+
+#include  <iostream>
+#include  <map>
+#include  <set>
+#include "AFunction.hpp"
+#include "environment.hpp"
+#include "InitFunct.hpp"
+using namespace std;
+#include "lex.hpp"
+#define LOAD 1
+#if defined(__INTEL__) || defined(__MWERKS__) || !defined(HAVE_DLFCN_H)
+#undef LOAD
+#endif
+
+#ifdef LOAD
+#include <dlfcn.h>
+#elif WIN32
+#include <windows.h>
+#endif
+
+#include "ffapi.hpp"
+
+set<string> SetLoadFile;
+
+bool load(string ss)
+{
+  
+  // FFCS - do not allow potentially dangerous commands from remote anonymous clients
+  
+  if(ffapi::protectedservermode() && (ss=="pipe" || ss=="shell")){
+    cerr<<"library "<<ss<<" not allowed in server environment"<<endl;
+    CompileError("Error load");
+    return 0;
+  }
+
+  if(SetLoadFile.find(ss) != SetLoadFile.end())
+    { 
+      if( (mpirank==0)&& verbosity)
+	cout << " (already loaded : " <<  ss << " ) " ;
+    }
+  else
+    {
+      SetLoadFile.insert(ss);
+      bool ret=false;
+      void * handle = 0;
+      const int /*nbprefix=2,*/nbsuffix=2;
+      list<string> prefix(ffenvironment["loadpath"]);
+      if(prefix.empty())
+	{
+	  prefix.push_back("");
+	  prefix.push_back("./");
+	}
+      
+      string suffix[nbsuffix] ;
+	
+      suffix[0]="";
+      suffix[1]=".so";
+#ifdef  __APPLE__
+      suffix[1]=".dylib";
+#endif  
+#ifdef WIN32  
+      suffix[1]=".dll";
+#endif 
+      int j; 
+      for (list<string>::const_iterator i= prefix.begin();i !=prefix.end();++i)
+	for ( j= 0;j< nbsuffix;++j)
+	  {
+	    string s= *i+ss+suffix[j];
+	    
+#ifdef LOAD  
+	    handle = dlopen (s.c_str(), RTLD_LAZY ); 
+	    if (verbosity>9) cout << " test dlopen(" << s << ")= " << handle <<  endl;
+	    
+	    // FFCS - 20/9/11 - print explanation for load errors
+	    if(verbosity>9 && !handle){
+	      cout<<"load error was: "<<dlerror()<<endl;
+	    }
+	    
+	    ret= handle !=0;
+	    if (  ret ) 
+	      {
+		if(verbosity && (mpirank ==0))
+		  cout << " (load: dlopen " << s << " " << handle << ") ";
+		callInitsFunct() ;  
+		return handle;
+	      }
+	    
+#elif WIN32
+	    {
+	      HINSTANCE mod=  LoadLibrary(s.c_str());
+	      if (verbosity>9) cout << " test LoadLibrary(" << s << ")= " << mod <<  endl;
+	      if(mod==0) 
+		{
+		  DWORD merr = GetLastError();
+		  if(verbosity>19)
+		    cerr  <<   "\n try loadLibary : " <<s << "\n \t fail : " << merr << endl;
+		}
+	      else 
+		{
+		  if(verbosity&& (mpirank ==0))
+		    cout << "(load: loadLibary " <<  s <<  " = " << handle << ")";
+		  callInitsFunct() ; 
+		  return mod;
+		}
+	    }
+#else
+	    if(mpirank ==0)
+		{
+		  cout << "------------------------------------   \n" ;
+		  cout << "  load: sorry no dlopen on this system " << s << " \n" ;
+		  cout << "------------------------------------   \n" ;
+		}
+	    CompileError("Error load");
+	    return 0;
+#endif  
+	  }
+      if(mpirank ==0)
+	{
+	  cerr  <<   "\nload error : " << ss << "\n \t fail : "  << endl;
+	  char *error=0;
+#ifndef WIN32
+#ifdef LOAD
+	  error= dlerror();
+	  if ( error  != NULL) {
+	    cerr << " dlerror : " << error << endl;
+	  }
+#endif
+#endif
+	  cerr << "list  prefix: " ;
+	  for (list<string>::const_iterator i= prefix.begin();i !=prefix.end();++i)
+	    cerr <<"'"<<*i<<"' ";
+	  cerr << "list  suffix : '"<< suffix[0] << "' , '"  << suffix[1] << "' "; 
+	  
+	  cerr << endl;
+	}
+      CompileError("Error load");
+    }
+  return 0 ;
+}
+
diff --git a/src/fflib/mt19937ar.cpp b/src/fflib/mt19937ar.cpp
new file mode 100755
index 0000000..34e8d68
--- /dev/null
+++ b/src/fflib/mt19937ar.cpp
@@ -0,0 +1,191 @@
+/* 
+   A C-program for MT19937, with initialization improved 2002/1/26.
+   Coded by Takuji Nishimura and Makoto Matsumoto.
+
+   Before using, initialize the state by using init_genrand(seed)  
+   or init_by_array(init_key, key_length).
+
+   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+   All rights reserved.                          
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+
+     3. The names of its contributors may not be used to endorse or promote 
+        products derived from this software without specific prior written 
+        permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+   Any feedback is very welcome.
+   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
+   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
+*/
+
+#include <stdio.h>
+
+/* Period parameters */  
+#define N 624
+#define M 397
+#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
+#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
+#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
+
+static unsigned long mt[N]; /* the array for the state vector  */
+static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
+
+/* initializes mt[N] with a seed */
+void init_genrand(unsigned long s)
+{
+    mt[0]= s & 0xffffffffUL;
+    for (mti=1; mti<N; mti++) {
+        mt[mti] = 
+	    (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); 
+        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
+        /* In the previous versions, MSBs of the seed affect   */
+        /* only MSBs of the array mt[].                        */
+        /* 2002/01/09 modified by Makoto Matsumoto             */
+        mt[mti] &= 0xffffffffUL;
+        /* for >32 bit machines */
+    }
+}
+
+/* initialize by an array with array-length */
+/* init_key is the array for initializing keys */
+/* key_length is its length */
+/* slight change for C++, 2004/2/26 */
+void init_by_array(unsigned long init_key[], int key_length)
+{
+    int i, j, k;
+    init_genrand(19650218UL);
+    i=1; j=0;
+    k = (N>key_length ? N : key_length);
+    for (; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+          + init_key[j] + j; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++; j++;
+        if (i>=N) { mt[0] = mt[N-1]; i=1; }
+        if (j>=key_length) j=0;
+    }
+    for (k=N-1; k; k--) {
+        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
+          - i; /* non linear */
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        i++;
+        if (i>=N) { mt[0] = mt[N-1]; i=1; }
+    }
+
+    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
+}
+
+/* generates a random number on [0,0xffffffff]-interval */
+unsigned long genrand_int32(void)
+{
+    unsigned long y;
+    static unsigned long mag01[2]={0x0UL, MATRIX_A};
+    /* mag01[x] = x * MATRIX_A  for x=0,1 */
+
+    if (mti >= N) { /* generate N words at one time */
+        int kk;
+
+        if (mti == N+1)   /* if init_genrand() has not been called, */
+            init_genrand(5489UL); /* a default initial seed is used */
+
+        for (kk=0;kk<N-M;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
+        }
+        for (;kk<N-1;kk++) {
+            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
+            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
+        }
+        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
+        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
+
+        mti = 0;
+    }
+  
+    y = mt[mti++];
+
+    /* Tempering */
+    y ^= (y >> 11);
+    y ^= (y << 7) & 0x9d2c5680UL;
+    y ^= (y << 15) & 0xefc60000UL;
+    y ^= (y >> 18);
+
+    return y;
+}
+
+/* generates a random number on [0,0x7fffffff]-interval */
+long genrand_int31(void)
+{
+    return (long)(genrand_int32()>>1);
+}
+
+/* generates a random number on [0,1]-real-interval */
+double genrand_real1(void)
+{
+    return genrand_int32()*(1.0/4294967295.0); 
+    /* divided by 2^32-1 */ 
+}
+
+/* generates a random number on [0,1)-real-interval */
+double genrand_real2(void)
+{
+    return genrand_int32()*(1.0/4294967296.0); 
+    /* divided by 2^32 */
+}
+
+/* generates a random number on (0,1)-real-interval */
+double genrand_real3(void)
+{
+    return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); 
+    /* divided by 2^32 */
+}
+
+/* generates a random number on [0,1) with 53-bit resolution*/
+double genrand_res53(void) 
+{ 
+    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 
+    return(a*67108864.0+b)*(1.0/9007199254740992.0); 
+} 
+/* These real versions are due to Isaku Wada, 2002/01/09 added */
+/*
+int main(void)
+{
+    int i;
+    unsigned long init[4]={0x123, 0x234, 0x345, 0x456}, length=4;
+    init_by_array(init, length);
+    printf("1000 outputs of genrand_int32()\n");
+    for (i=0; i<1000; i++) {
+      printf("%10lu ", genrand_int32());
+      if (i%5==4) printf("\n");
+    }
+    printf("\n1000 outputs of genrand_real2()\n");
+    for (i=0; i<1000; i++) {
+      printf("%10.8f ", genrand_real2());
+      if (i%5==4) printf("\n");
+    }
+    return 0;
+}
+*/
diff --git a/src/fflib/problem.cpp b/src/fflib/problem.cpp
new file mode 100644
index 0000000..04bda8d
--- /dev/null
+++ b/src/fflib/problem.cpp
@@ -0,0 +1,6137 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "Mesh3dn.hpp"
+#include "MeshPoint.hpp"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+#include <set>
+
+
+
+basicAC_F0::name_and_type  CDomainOfIntegration::name_param[]= {
+    { "qft", &typeid(const Fem2D::QuadratureFormular *)},
+    { "qfe", &typeid(const Fem2D::QuadratureFormular1d *)},
+    { "qforder",&typeid(long)},
+    { "qfnbpT",&typeid(long)},
+    { "qfnbpE",&typeid(long)},
+    { "optimize",&typeid(bool)},
+    { "binside",&typeid(double)},
+    { "mortar",&typeid(bool)},
+    { "qfV", &typeid(const Fem2D::GQuadratureFormular<R3> *)},
+    { "levelset",&typeid(double)}
+
+};
+
+
+basicAC_F0::name_and_type  Problem::name_param[]= {
+{  "save",&typeid(string* )},
+{  "cadna",&typeid(KN<double>*)},
+{  "bmat",&typeid(Matrice_Creuse<R>* )},
+LIST_NAME_PARM_MAT
+/*
+  {  "init", &typeid(bool)},
+  {  "solver", &typeid(TypeSolveMat*)},
+  {  "eps", &typeid(double) },
+  {  "precon",&typeid(Polymorphic*)}, 
+  {  "dimKrylov",&typeid(long)},
+  {  "bmat",&typeid(Matrice_Creuse<R>* )},
+  {  "tgv",&typeid(double )},
+  {  "strategy",&typeid(long )},
+  {  "save",&typeid(string* )},
+  {  "cadna",&typeid(KN<double>*)},
+  {  "tolpivot", &typeid(double)},
+  {  "tolpivotsym", &typeid(double)},
+  {  "nbiter", &typeid(long)}, // 12 
+  {   "paramint",&typeid(KN_<long>)}, // Add J. Morice 02/09 
+  {   "paramdouble",&typeid(KN_<double>)},
+  {   "paramstring",&typeid(string *)},
+  {   "permrow",&typeid(KN_<long>)},
+  {   "permcol",&typeid(KN_<long>)},
+  {   "fileparamint",&typeid(string*)}, // Add J. Morice 02/09 
+  {   "fileparamdouble",&typeid(string*)},
+  {   "fileparamstring",&typeid(string* )},
+  {   "filepermrow",&typeid(string*)},
+  {   "filepermcol",&typeid(string*)} //22
+ */
+};
+
+struct pair_stack_double
+{
+    Stack first;
+    double *second;
+    pair_stack_double(Stack ss,double* bb) : first(ss),second(bb) {};
+
+};
+
+namespace Fem2D {
+
+    void  Expandsetoflab(Stack stack,const CDomainOfIntegration & di,set<int> & setoflab,bool &all);
+    void  Expandsetoflab(Stack stack,const BC_set & bc,set<long> & setoflab);
+
+void Check(const Opera &Op,int N,int  M)
+ {
+   int err=0;
+   for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++)
+     {  // attention la fonction test donne la ligne 
+       //  et la fonction test est en second      
+       BilinearOperator::K ll(*l);
+       pair<int,int> jj(ll.first.first),ii(ll.first.second);
+       if (ii.first <0 || ii.first >= M) err++;
+       if (jj.first <0 || jj.first >= N) err++;
+       
+     }
+   if (err) {
+     cout << "Check Bilinear Operator" << N << " " << M << endl;
+     for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++)
+       {  // attention la fonction test donne la ligne 
+         //  et la fonction test est en second      
+         BilinearOperator::K ll(*l);
+         pair<int,int> jj(ll.first.first),ii(ll.first.second);
+         cout << " +  " << jj.first << " " << jj.second << "*" << ii.first << " " << ii.second << endl;
+          }
+     ExecError("Check BilinearOperator N M");
+   }
+ }
+ void Check(const  BC_set * bc,int N)
+ {
+   int err=0;
+   int kk=bc->bc.size();
+   for (int k=0;k<kk;k++)
+     {
+       pair<int,Expression> xx=bc->bc[k];
+       if (xx.first >= N) { 
+         err++;
+         cerr << " Sorry : just " << N << " componant in FE space \n"
+              << "   and Boundary condition refere to " << xx.first << "+1 componant " << endl;
+       }
+     }
+   if (err) 
+     ExecError("Incompatibility beetwen  boundary condition  and FE space");
+ }
+ 
+  void Check(const  Ftest * fl,int N)
+ {
+   assert(fl);
+   int err=0;
+   Ftest::const_iterator kk= fl->v.end(),k;
+   int ii=0;
+   for (k=fl->v.begin();k<kk;k++)
+     { 
+       ii++;
+       int j=k->first.first;
+       if (  j >= N) { 
+         err++;
+         cerr << " Sorry : just " << N << " componant in FE space \n"
+              << " and linear var form  refere to " << j << "+1 componant (part " << ii << ")" << endl;
+       }
+     }
+   if (err) 
+     ExecError("Incompatibility beetwen linear varf  and FE space");
+ }
+ //---------------------------------------------------------------------------------------
+  template<class R>
+  void  Element_OpVF(MatriceElementairePleine<R,FESpace3> & mat,
+		     const FElement3 & Ku,const FElement3 & KKu,
+		     const FElement3 & Kv,const FElement3 & KKv,
+		     double * p,int ie,int iie, int label,void *bstack,R3 *B)
+  {
+    ffassert(0); 
+  }
+  
+  template<class R>
+  void  Element_OpVF(MatriceElementairePleine<R,FESpace> & mat,
+			const FElement & Ku,const FElement & KKu,
+			const FElement & Kv,const FElement & KKv,
+			double * p,int ie,int iie, int label,void *bstack,R2 *B)
+  {
+     ffassert(B==0);
+    pair_stack_double * bs=static_cast<pair_stack_double *>(bstack);   
+    Stack stack= bs->first;
+    double binside = *bs->second; // truc FH pour fluide de grad2 (decentrage bizard)
+    assert(mat.onFace); //   Finite Volume or discontinous Galerkine 
+    assert(ie>=0 && ie < 3); //  int on edge 
+    MeshPoint mp= *MeshPointStack(stack);
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    
+    bool same = &Ku == & Kv;
+    assert(same); 
+    const Triangle & T  = Ku.T;
+    int nTonEdge =  &Ku == &KKu ? 1 : 2; 
+    double cmean = 1./nTonEdge;
+    
+    throwassert(&T == &Kv.T);  
+  // const QuadratureFormular & FI = mat.FIT;
+    const QuadratureFormular1d & FIb = mat.FIE;
+    long npi;
+    R *a=mat.a;
+    R *pa=a;
+    long i,j;
+    long n= mat.n,m=mat.m,nx=n*m;
+    assert(nx<=mat.lga);
+    long N= Kv.N;
+    long M= Ku.N;
+    
+    long mu=Ku.NbDoF();
+    long mmu=KKu.NbDoF();
+    long nv=Kv.NbDoF();
+    long nnv=Kv.NbDoF();
+    assert(mu==mmu && nv == nnv) ; 
+    
+    
+    
+    const Opera &Op(*mat.bilinearform);
+    bool classoptm = copt && Op.optiexpK;
+    //  if (Ku.number<1 && verbosity/100 && verbosity % 10 == 2) 
+    if (Ku.number<1 && ( verbosity > 1 ) )
+      cout << "Element_OpVF P: copt = " << copt << " " << classoptm << " binside (For FH) =" << binside <<endl;
+  
+    
+    KN<bool> Dop(last_operatortype); //  sinon ca plate bizarre 
+    Op.DiffOp(Dop);  
+    int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+    //assert(lastop<=3);
+    int lffv = nv*N*last_operatortype;  
+    int lffu = mu*M*last_operatortype;
+    int loffset =  same ? 0 :  (nv+nnv)*N*last_operatortype;
+    
+    RNMK_ fv(p,nv,N,lastop); //  the value for basic fonction in K
+    RNMK_ ffv(p + lffv ,nnv,N,lastop); //  the value for basic fonction in KK
+    RNMK_ fu(  (double*) fv   + loffset  ,mu,M,lastop); //  the value for basic fonction
+    RNMK_ ffu( (double*) fu  + lffu  ,mmu,M,lastop); //  the value for basic fonction
+    
+    R2 E=T.Edge(ie);
+    double le = sqrt((E,E));
+    R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+      PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]),
+      PC(TriangleHat[OppositeVertex[ie]]);
+    // warning the to edge are in opposite sens         
+    R2 PP_A(TriangleHat[VerticesOfTriangularEdge[iie][1]]),
+      PP_B(TriangleHat[VerticesOfTriangularEdge[iie][0]]),
+      PP_C(TriangleHat[OppositeVertex[ie]]);
+    R2 Normal(E.perp()/-le); 
+    for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+      {
+        pa =a;
+        QuadratureFormular1dPoint pi( FIb[npi]);        
+        double coef = le*pi.a;
+        double sa=pi.x,sb=1-sa;
+        R2 Pt(PA*sa+PB*sb ); //
+        R2 PP_t(PP_A*sa+PP_B*sb ); //  
+        if (binside) {
+	  Pt   = (1-binside)*Pt + binside*PC; 
+	  PP_t  = (1-binside)*PP_t + binside*PP_C; }
+        Ku.BF(Dop,Pt,fu);
+        KKu.BF(Dop,PP_t,ffu);
+        if (!same) { Kv.BF(Dop,Pt,fv); KKv.BF(Dop,PP_t,ffv); }     
+        // int label=-999999; // a passer en argument 
+        MeshPointStack(stack)->set(T(Pt),Pt,Kv,label, Normal,ie);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+        
+        
+        for ( i=0;  i<n;   i++ )  
+            { 
+              int ik= mat.nik[i];
+              int ikk=mat.nikk[i]; 
+               
+              RNM_ wi(fv(Max(ik,0),'.','.'));   
+              RNM_ wwi(ffv(Max(ikk,0),'.','.'));   
+                  
+              for ( j=0;  j<m;   j++,pa++ ) 
+                { 
+                  int jk= mat.njk[j];
+                  int jkk=mat.njkk[j];
+                    
+                  RNM_ wj(fu(Max(jk,0),'.','.'));
+                  RNM_ wwj(ffu(Max(jkk,0),'.','.'));
+                  
+                  int il=0;
+                  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                      {       
+                        BilinearOperator::K ll(*l);
+                        pair<int,int> jj(ll.first.first),ii(ll.first.second);
+                        int iis = ii.second, jjs=jj.second;
+                        
+                        int iicase  = iis / last_operatortype;
+                        int jjcase  = jjs / last_operatortype;
+                        
+                         iis %= last_operatortype;
+                         jjs %= last_operatortype;
+                        double w_i=0,w_j=0,ww_i=0,ww_j=0;
+                        
+                        if(ik>=0) w_i =   wi(ii.first,iis ); 
+                        if(jk>=0) w_j =   wj(jj.first,jjs );
+                        
+                        if( iicase>0 && ikk>=0) ww_i =  wwi(ii.first,iis ); 
+                        if( jjcase>0 && jkk>=0) ww_j =  wwj(jj.first,jjs );
+                       
+                        
+                        if       (iicase==Code_Jump) w_i = ww_i-w_i; // jump
+                        else  if (iicase==Code_Mean) { 
+                            
+                            w_i = cmean*  (w_i + ww_i );} // average
+                        else  if (iicase==Code_OtherSide) w_i = ww_i;  // valeur de autre cote
+                        
+                        if      (jjcase==Code_Jump) w_j = ww_j-w_j; // jump
+                        else if (jjcase==Code_Mean) w_j = cmean*  (w_j +ww_j ); // average
+                        else if (jjcase==Code_OtherSide) w_j = ww_j;  //  valeur de l'autre cote    
+                        
+                       // R ccc = GetAny<R>(ll.second.eval(stack));
+                       
+                        R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+                       if ( copt && Kv.number <1)
+                        {
+                         R cc  =  GetAny<R>(ll.second.eval(stack));
+                         if ( ccc != cc) { 
+                          cerr << cc << " != " << ccc << " => ";
+                         cerr << "Sorry error in Optimization (b) add:  int2d(Th,optimize=0)(...)" << endl;
+                         ExecError("In Optimized version "); }
+                 }
+                         *pa += coef * ccc * w_i*w_j;
+                      }
+                }
+            } 
+         // else pa += m;
+      }
+  
+  
+     pa=a;
+     if ( (verbosity > 9999) ||( (verbosity > 55) && (Ku.number <=0 || KKu.number <=0 )))  {
+       cout <<endl  << " edge between " << Ku.number << " , " <<  KKu.number   << " =  "<<  T[0] << ", " << T[1] << ", " << T[2] << " " << nx << endl;
+       cout << " K u, uu =  " << Ku.number << " " << KKu.number << " " <<  " K v, vv =  " << Kv.number << " " << KKv.number << " " <<endl; 
+       for (int i=0;i<n;i++)
+	 {
+	   cout << setw(2) << i << setw(4) << mat.ni[i] <<  setw(4) << mat.nik[i] << setw(4) << mat.nikk[i]  <<  " :";
+	   for (int j=0;j<m;j++)
+	     cout << setw(5)  << (*pa++) << " ";
+	   cout << endl;
+	 } } 
+     
+     *MeshPointStack(stack) = mp;
+  }  
+
+ //--------------------------------------------------------------------------------------
+ 
+// --------- FH 120105
+ template<class R>
+ void AssembleBilinearForm(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+			   MatriceCreuse<R>  & A, const  FormBilinear * b  )
+   
+ {
+     /*FH:  case ..in 2D
+      in varf ...
+      standard case ..
+      */
+
+   StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+   bool sptrclean=true;
+   const CDomainOfIntegration & di= *b->di;
+   const Mesh * pThdi = GetAny<pmesh>( (* di.Th)(stack));
+   if ( pThdi != &Th || &Uh.Th !=&Th || &Vh.Th !=&Th) { 
+       cout << " --Use matrix formulation ---" << endl; 
+     ExecError("No way to compute bilinear form with integrale of on mesh \n"
+	       "  test  or unkown function  defined on an other mesh! sorry to hard.   ");
+   }
+   SHOWVERB(cout << " FormBilinear " << endl);
+    MatriceElementaireSymetrique<R,FESpace> *mates =0;
+    MatriceElementairePleine<R,FESpace> *matep =0;
+    const bool useopt=di.UseOpt(stack);    
+    double binside=di.binside(stack);
+    
+    //const vector<Expression>  & what(di.what);             
+    CDomainOfIntegration::typeofkind  kind = di.kind;
+    set<int> setoflab;
+    bool all=true;
+     
+    const Mesh & ThI = Th;//* GetAny<pmesh>( (* di.Th)(stack));
+    bool sameMesh = &ThI == &Vh.Th &&  &ThI == &Uh.Th;
+    
+//    const QuadratureFormular1d & FIE = di.FIE(stack);
+//    const QuadratureFormular & FIT = di.FIT(stack);
+     const QuadratureFormular1d & FIEo = di.FIE(stack);
+     const QuadratureFormular & FITo = di.FIT(stack);
+     // const GQuadratureFormular<R3> & FIVo = di.FIV(stack);
+     //  to change the quadrature on element ... may 2014 FH ..
+     QuadratureFormular1d  FIE(FIEo,3);
+     QuadratureFormular FIT(FITo,3);
+    // GQuadratureFormular<R3>  FIV(FIVo,3);
+
+    bool VF=b->VF();  // finite Volume or discontinous Galerkin
+    if (verbosity>2) cout << "  -- discontinous Galerkin  =" << VF << " size of Mat =" << A.size()<< " Bytes\n";
+    if (verbosity>3)
+    {
+      if (CDomainOfIntegration::int1d==kind) cout << "  -- boundary int border ( nQP: "<< FIE.n << ") ,"  ;
+      else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges ( nQP: "<< FIE.n << "),"  ;
+      else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIE.n << ")," ;
+      else cout << "  --  int    (nQP: "<< FIT.n << " ) in "  ;
+    }
+     //if(di.islevelset()) InternalError("So no levelset integration type on this case (6)");
+     if(di.islevelset() && ( (CDomainOfIntegration::int1d!=kind) && (CDomainOfIntegration::int2d!=kind) )  )
+         InternalError("So no levelset integration type on no int1d case (6)");
+     
+    Expandsetoflab(stack,di, setoflab,all);
+   /*
+    for (size_t i=0;i<what.size();i++)
+      {
+	long  lab  = GetAny<long>( (*what[i])(stack));
+	setoflab.insert(lab);
+	if ( verbosity>3) cout << lab << " ";
+	all=false;
+      }*/
+    if (verbosity>3) cout <<" Optimized = "<< useopt << ", ";
+    const E_F0 & optiexp0=*b->b->optiexp0;
+    
+    int n_where_in_stack_opt=b->b->where_in_stack_opt.size();
+    R** where_in_stack =0;
+    if (n_where_in_stack_opt && useopt)
+      where_in_stack = new R * [n_where_in_stack_opt];
+    if (where_in_stack)
+      {
+	assert(b->b->v.size()==(size_t) n_where_in_stack_opt);
+	for (int i=0;i<n_where_in_stack_opt;i++)
+	  {
+	    int offset=b->b->where_in_stack_opt[i];
+	    assert(offset>10);
+	    where_in_stack[i]= static_cast<R *>(static_cast<void *>((char*)stack+offset));
+	    *(where_in_stack[i])=0;
+	  }
+	
+	
+	if(&optiexp0) 
+	  optiexp0(stack); 
+	KN<bool> ok(b->b->v.size());
+	{  //   remove the zero coef in the liste 
+	  // R zero=R();  
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+	    ok[il] =  ! (b->b->mesh_indep_stack_opt[il] && ( Fem2D::norm(*(where_in_stack[il])) < 1e-100 ) );
+	}
+	BilinearOperator b_nozer(*b->b,ok); 
+	if (verbosity % 10 > 3 ) 
+	  cout << "   -- nb term in bilinear form  (!0) : " << b_nozer.v.size() 
+	       << "  total " << n_where_in_stack_opt << endl;
+	
+	if ( (verbosity/100) % 10 >= 2)   
+	  { 
+	    int il=0;
+	    
+	    for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+	      cout << il << " coef (" << l->first << ") = " << *(where_in_stack[il]) 
+		   << " offset=" << b->b->where_in_stack_opt[il] 
+		   << " dep mesh " << l->second.MeshIndependent() << b->b->mesh_indep_stack_opt[il] << endl;
+	  }
+      }
+    Stack_Ptr<R*>(stack,ElemMatPtrOffset) =where_in_stack;
+    void *paramate=stack;
+    pair_stack_double parammatElement_OpVF(stack,& binside);
+   // parammatElement_OpVF.first = stack;
+   // parammatElement_OpVF.second= & binside;
+    
+    if (verbosity >3)
+    {
+      if (all) cout << " all " << endl ;
+      else cout << endl;
+    }
+    if(VF) {
+      if(&Uh != &Vh || sym)
+	cout << ("To Day in bilinear form with discontinous Galerkin (2d):   \n"
+		  "  test or unkown function must be  defined on the same FEspace, \n"
+		  "  and the matrix is not symmetric. \n" 
+		  " To do other case in a future (F. Hecht) dec. 2003 ");
+        if(&Uh == &Vh)
+            matep= new MatriceElementairePleine<R,FESpace>(Uh,VF,FIT,FIE);
+        else
+            matep= new MatriceElementairePleine<R,FESpace>(Uh,Vh,VF,FIT,FIE);
+
+        
+     
+  //      matep= new MatriceElementairePleine<R,FESpace>(Uh,Vh,VF,FIT,FIE);
+      matep->faceelement = Element_OpVF;   
+      paramate= &parammatElement_OpVF;            
+    }
+    else if (sym) {
+      mates= new MatriceElementaireSymetrique<R,FESpace>(Uh,FIT,FIE);
+      mates->element = Element_Op<R>;
+    }
+    else {
+      matep= new MatriceElementairePleine<R,FESpace>(Uh,Vh,FIT,FIE);
+      matep->element = Element_Op<R>;               
+    }
+    MatriceElementaireFES<R,FESpace> & mate(*( sym? (MatriceElementaireFES<R,FESpace> *)mates : (MatriceElementaireFES<R,FESpace> *) matep));
+    
+    
+    mate.bilinearform=b->b;
+    
+    Check(*mate.bilinearform,mate.Uh.N,mate.Vh.N);
+    
+    if (di.kind == CDomainOfIntegration::int1d )
+      {
+          if(di.islevelset())
+          {
+              double uset = HUGE_VAL;
+              R2 Q[3];
+              KN<double> phi(Th.nv);phi=uset;
+              double f[3];
+              for(int t=0; t< Th.nt;++t)
+              {
+                if ( all || setoflab.find(Th[t].lab) != setoflab.end())
+                  {
+                  double umx=-HUGE_VAL,umn=HUGE_VAL;
+                  for(int i=0;i<3;++i)
+                  {
+                      int j= ThI(t,i);
+                      if( phi[j]==uset)
+                      {
+                          MeshPointStack(stack)->setP(&ThI,t,i);
+                          phi[j]= di.levelset(stack);//zzzz
+                      }
+                      f[i]=phi[j];
+                      umx = std::max(umx,phi[j]);
+                      umn = std::min(umn,phi[j]);
+                      
+                  }
+                  if( umn <=0 && umx >= 0)
+                  {
+                      
+                      int np= IsoLineK(f,Q,1e-10);
+                      if(np==2)
+                      {
+                         /* if ( sameMesh)
+                          {
+                           
+                              Element_rhs<R>(Vh[t],*l->l,buf,stack,*B,FIE,Q[0],Q[1]);
+                          }
+                          else*/ 
+                           //   InternalError(" No levelSet on Diff mesh :    to day  int1d of Matrix");
+                         A += mate(t,10,Th[t].lab,stack,Q);
+                      }
+                      if(sptrclean) sptrclean=sptr->clean();
+                  }
+              }
+              }
+          }
+        else for( int e=0;e<Th.neb;e++)
+          {
+            if (all || setoflab.find(Th.bedges[e].lab) != setoflab.end())   
+              {                  
+                int ie,i =Th.BoundaryElement(e,ie);
+                A += mate(i,ie,Th.bedges[e].lab,stack);  
+                if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+		
+              }
+          }
+      }
+    else if (di.kind == CDomainOfIntegration::intalledges)
+      {
+        for (int i=0;i< Th.nt; i++) 
+          {
+            if ( all || setoflab.find(Th[i].lab) != setoflab.end())
+	      for (int ie=0;ie<3;ie++)   
+              A += mate(i,ie,Th[i].lab,paramate); 
+	    if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	    
+          }
+	
+      }      
+    else if (di.kind == CDomainOfIntegration::intallVFedges)
+      {
+	cerr << " a faire intallVFedges " << endl;
+	ffassert(0);
+        for (int i=0;i< Th.nt; i++) 
+          {
+            if ( all || setoflab.find(Th[i].lab) != setoflab.end())
+             for (int ie=0;ie<3;ie++)   
+	       A += mate(i,ie,Th[i].lab,paramate);  
+	    if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	    
+          }
+	
+      }      
+    else if (di.kind == CDomainOfIntegration::int2d )
+      {
+          
+          if(di.islevelset())
+          {
+              double uset = HUGE_VAL;
+              R2 Q[2][3];
+              double vol6[2];
+              KN<double> phi(Th.nv);phi=uset;
+              double f[3];
+              for(int t=0; t< Th.nt;++t)
+              {
+                  if ( all || setoflab.find(Th[t].lab) != setoflab.end())
+                  {
+                      double umx=-HUGE_VAL,umn=HUGE_VAL;
+                      for(int i=0;i<3;++i)
+                      {
+                          int j= ThI(t,i);
+                          if( phi[j]==uset)
+                          {
+                              MeshPointStack(stack)->setP(&ThI,t,i);
+                              phi[j]= di.levelset(stack);//zzzz
+                          }
+                          f[i]=phi[j];
+                          umx = std::max(umx,phi[j]);
+                          umn = std::min(umn,phi[j]);
+                          
+                      }
+                      int nt= UnderIso(f,Q, vol6,1e-14);
+                      setQF<R2>(FIT,FITo,QuadratureFormular_T_1, Q,vol6,nt);
+                      if(FIT.n)
+                       A += mate(t,-1,Th[t].lab,stack);
+                      if(sptrclean) sptrclean=sptr->clean();
+                      }
+                  }
+                FIT =FITo;
+              }
+        else
+         
+          
+        for (int i=0;i< Th.nt; i++) 
+          {
+            if ( all || setoflab.find(Th[i].lab) != setoflab.end())  
+              A += mate(i,-1,Th[i].lab,stack);   
+            if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+
+            // AA += mate;
+          }
+      } 
+    else 
+      InternalError(" kind of CDomainOfIntegration unkown");
+    
+    if (where_in_stack) delete [] where_in_stack;
+    delete &mate;
+ }
+// --------- FH 120105
+// 3d
+ template<class R>
+ void AssembleBilinearForm(Stack stack,const FESpace3::Mesh & Th,const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+			   MatriceCreuse<R>  & A, const  FormBilinear * b  )
+   
+ {
+     
+     /*FH:  case ..in 3D
+      in varf ...
+      standard case ..
+      */
+     
+     
+   typedef FESpace3 FESpace;
+   typedef FESpace3::Mesh Mesh;
+   typedef Mesh *pmesh ;
+   StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+   bool sptrclean=true;
+   const CDomainOfIntegration & di= *b->di;
+   ffassert(di.d==3);
+   const Mesh * pThdi = GetAny<pmesh>( (* di.Th)(stack));
+   if ( pThdi != &Th || &Uh.Th !=&Th || &Vh.Th !=&Th) { 
+       cout << " Use matrix formulation .... " << endl;
+     ExecError("No way to compute bilinear form with integrale of on mesh \n"
+	       "  test  or unkown function  defined on an other mesh! sorry to hard.   ");
+   }
+   SHOWVERB(cout << " FormBilinear " << endl);
+    MatriceElementaireSymetrique<R,FESpace> *mates =0;
+    MatriceElementairePleine<R,FESpace> *matep =0;
+    const bool useopt=di.UseOpt(stack);    
+    double binside=di.binside(stack);
+    
+    //const vector<Expression>  & what(di.what);             
+    CDomainOfIntegration::typeofkind  kind = di.kind;
+    set<int> setoflab;
+    bool all=true; 
+    const QuadratureFormular1d & FIEo = di.FIE(stack);
+    const QuadratureFormular & FITo = di.FIT(stack);
+    const GQuadratureFormular<R3> & FIVo = di.FIV(stack);
+     //  to change the quadrature on element ... may 2014 FH ..
+     QuadratureFormular1d  FIE(FIEo,3);
+    QuadratureFormular FIT(FITo,3);
+    GQuadratureFormular<R3>  FIV(FIVo,3);
+     
+    bool VF=b->VF();  // finite Volume or discontinous Galerkin
+    if (verbosity>2) cout << "  -- discontinous Galerkin  =" << VF << " size of Mat =" << A.size()<< " Bytes\n";
+    if (verbosity>3)
+    {
+      if (CDomainOfIntegration::int2d==kind) cout << "  -- boundary int border ( nQP: "<< FIT.n << ") ,"  ;
+      else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges ( nQP: "<< FIT.n << "),"  ;
+      else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIE.n << ")," ;
+      else cout << "  --  int3d   (nQP: "<< FIV.n << " ) in "  ;
+      if(di.islevelset()) cout << " ( int on Levelset) " << endl;
+  
+    }
+      if(di.islevelset() && (CDomainOfIntegration::int2d!=kind) && (CDomainOfIntegration::int3d!=kind))
+          InternalError("Sorry no levelset integration type on no int[2|3]d case");
+     
+   Expandsetoflab(stack,di, setoflab,all);
+   /*
+    for (size_t i=0;i<what.size();i++)
+      {
+	long  lab  = GetAny<long>( (*what[i])(stack));
+	setoflab.insert(lab);
+	if ( verbosity>3) cout << lab << " ";
+	all=false;
+      }*/
+    if (verbosity>3) cout <<" Optimized = "<< useopt << ", ";
+    const E_F0 & optiexp0=*b->b->optiexp0;
+    
+    int n_where_in_stack_opt=b->b->where_in_stack_opt.size();
+    R** where_in_stack =0;
+    if (n_where_in_stack_opt && useopt)
+      where_in_stack = new R * [n_where_in_stack_opt];
+    if (where_in_stack)
+      {
+	assert(b->b->v.size()==(size_t) n_where_in_stack_opt);
+	for (int i=0;i<n_where_in_stack_opt;i++)
+	  {
+	    int offset=b->b->where_in_stack_opt[i];
+	    assert(offset>10);
+	    where_in_stack[i]= static_cast<R *>(static_cast<void *>((char*)stack+offset));
+	    *(where_in_stack[i])=0;
+	  }
+	
+	
+	if(&optiexp0) 
+	  optiexp0(stack); 
+	KN<bool> ok(b->b->v.size());
+	{  //   remove the zero coef in the liste 
+	  // R zero=R();  
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+	    ok[il] =  ! (b->b->mesh_indep_stack_opt[il] && ( Fem2D::norm(*(where_in_stack[il])) < 1e-100 ) );
+	}
+	BilinearOperator b_nozer(*b->b,ok); 
+	if (verbosity % 10 > 3 ) 
+	  cout << "   -- nb term in bilinear form  (!0) : " << b_nozer.v.size() 
+	       << "  total " << n_where_in_stack_opt << endl;
+	
+	if ( (verbosity/100) % 10 >= 2)   
+	  { 
+	    int il=0;
+	    
+	    for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+	      cout << il << " coef (" << l->first << ") = " << *(where_in_stack[il]) 
+		   << " offset=" << b->b->where_in_stack_opt[il] 
+		   << " dep mesh " << l->second.MeshIndependent() << b->b->mesh_indep_stack_opt[il] << endl;
+	  }
+      }
+    Stack_Ptr<R*>(stack,ElemMatPtrOffset) =where_in_stack;
+    void *paramate=stack;
+    pair_stack_double parammatElement_OpVF(stack, & binside);
+    parammatElement_OpVF.first = stack;
+    parammatElement_OpVF.second= & binside;
+    
+    if (verbosity >3)
+    {
+      if (all) cout << " all " << endl ;
+      else cout << endl;
+    }
+    if(VF) {
+      if(&Uh != &Vh || sym)
+	cout <<  ("To Day in bilinear form with discontinous Galerkin (3d):   \n"
+		  "  test or unkown function must be  defined on the same FEspace, \n"
+		  "  and the matrix is not symmetric. \n" 
+		  " To do other case in a future (F. Hecht) dec. 2014 ");
+      if(&Uh == &Vh)
+      matep= new MatriceElementairePleine<R,FESpace>(Uh,VF,FIV,FIT);
+      else
+      matep= new MatriceElementairePleine<R,FESpace>(Uh,Vh,VF,FIV,FIT);
+      matep->faceelement = Element_OpVF;   
+      paramate= &parammatElement_OpVF;            
+    }
+    else if (sym) {
+      mates= new MatriceElementaireSymetrique<R,FESpace>(Uh,FIV,FIT);
+      mates->element = Element_Op<R>;               
+    }
+    else {
+      matep= new MatriceElementairePleine<R,FESpace>(Uh,Vh,FIV,FIT);
+      matep->element = Element_Op<R>;               
+    }
+    MatriceElementaireFES<R,FESpace> & mate(*( sym? (MatriceElementaireFES<R,FESpace> *)mates : (MatriceElementaireFES<R,FESpace> *) matep));
+    
+    
+    mate.bilinearform=b->b;
+    
+    Check(*mate.bilinearform,mate.Uh.N,mate.Vh.N);
+    
+    if (di.kind == CDomainOfIntegration::int2d )
+    {
+        
+        if(di.islevelset())
+        {
+            if(verbosity>99) cout << " int2d on levelset in 3d " << endl;
+            double uset = HUGE_VAL;
+            R3 Q[4];
+            KN<double> phi(Th.nv);phi=uset;
+            double f[4];
+            for(int t=0; t< Th.nt;++t)
+            {
+                if ( all || setoflab.find(Th[t].lab) != setoflab.end())
+                {
+                double umx=-HUGE_VAL,umn=HUGE_VAL;
+                for(int i=0;i<4;++i)
+                {
+                    int j= Th(t,i);
+                    if( phi[j]==uset)
+                    {
+                        MeshPointStack(stack)->setP(&Th,t,i);
+                        phi[j]= di.levelset(stack);//zzzz
+                    }
+                    f[i]=phi[j];
+                    umx = std::max(umx,phi[j]);
+                    umn = std::min(umn,phi[j]);
+                    
+                }
+                if( umn <=0 && umx >= 0)
+                {
+                    int np= IsoLineK(f,Q,1e-10);// ca code ...
+                  //  cout <<umn << " " << umx << " " << np << endl;
+              
+                    if(np>2 )
+                    {
+                       if( verbosity > 999 ) cout << " -- int " << np << " on:  " << Q[0] << " " << Q[1] << " " << Q[2] << " " << Q[3] << endl;
+                       A += mate(t,10+np,Th[t].lab,stack,Q);
+                    }
+                    if(sptrclean) sptrclean=sptr->clean();
+                }
+                }}
+            
+        }
+        else
+            for( int e=0;e<Th.nbe;e++)
+            {
+                if (all || setoflab.find(Th.be(e).lab) != setoflab.end())
+                {
+                    int ie,i =Th.BoundaryElement(e,ie);
+                    A += mate(i,ie,Th.be(e).lab,stack);
+                    if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+                    
+                }
+            }
+    }
+    else if (di.kind == CDomainOfIntegration::intallfaces  )
+      {
+        for (int i=0;i< Th.nt; i++) 
+          {
+            if ( all || setoflab.find(Th[i].lab) != setoflab.end())
+	      for (int ie=0;ie<3;ie++)   
+              A += mate(i,ie,Th[i].lab,paramate); 
+	    if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	    
+          }
+	
+      }      
+    else if (di.kind == CDomainOfIntegration::intallVFedges)
+      {
+	cerr << " a faire intallVFedges " << endl;
+	ffassert(0);
+        for (int i=0;i< Th.nt; i++)
+          {
+            if ( all || setoflab.find(Th[i].lab) != setoflab.end())
+             for (int ie=0;ie<3;ie++)   
+	       A += mate(i,ie,Th[i].lab,paramate);  
+	    if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	    
+          }
+	
+      }      
+    else if (di.kind == CDomainOfIntegration::int3d )
+    {
+        if(di.islevelset())  //  may 2014 FH ...
+        {   // int3d levelset < 0
+            double llevelset = 0;
+            const double uset = std::numeric_limits<double>::max();
+            // cout << " uset ="<<uset << endl;
+            R3 Q[3][4];
+            double vol6[3];
+            KN<double> phi(Th.nv);
+            phi=uset;
+            double f[4];
+            
+            for (int t=0;t< Th.nt; t++)
+            {
+                
+                const Mesh3::Element & K(Th[t]);
+                if ( all || setoflab.find(Th[t].lab) != setoflab.end())
+                    
+                {
+                    double umx=std::numeric_limits<double>::min(),umn=std::numeric_limits<double>::max();
+                    for(int i=0;i<4;++i)
+                    {
+                        int j= Th(t,i);
+                        if( phi[j]==uset)
+                        {
+                            MeshPointStack(stack)->setP(&Th,t,i);
+                            phi[j]= di.levelset(stack);//zzzz
+                        }
+                        f[i]=phi[j];
+                    }
+                    int ntets= UnderIso(f,Q, vol6,1e-14);
+                    setQF<R3>(FIV,FIVo,QuadratureFormular_Tet_1, Q,vol6,ntets);
+                    if(FIV.n)
+                    {
+                        A += mate(t,-1,Th[t].lab,stack);
+                        if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+                        
+                    }
+                }
+            }
+            FIV=FIVo;
+        }
+        else
+            for (int i=0;i< Th.nt; i++)
+            {
+                if ( all || setoflab.find(Th[i].lab) != setoflab.end())
+                    A += mate(i,-1,Th[i].lab,stack);
+                if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+                
+                // AA += mate;
+            }
+        
+    }
+    else
+    {
+        cerr << " kind of CDomainOfIntegration unkown ?? " << di.kind << endl;
+      InternalError(" kind of CDomainOfIntegration unkown");
+    }
+    
+    if (where_in_stack) delete [] where_in_stack;
+    delete &mate;
+ }
+
+// end 3d
+
+// --------- FH 170605  
+
+    template<class R> 
+    void  AddMatElem(map<pair<int,int>, R > & A,const Mesh & Th,const BilinearOperator & Op,bool sym,int it,  int ie,int label,
+		     const FESpace & Uh,const FESpace & Vh,
+		     const QuadratureFormular & FI,
+		     const QuadratureFormular1d & FIb,
+		     double *p,   void *vstack, bool intmortar=false,R2 *Q=0)
+    {
+        //cout << "AddMatElem" << Q << " "  << ie << endl;
+        Stack stack=pvoid2Stack(vstack);
+	MeshPoint mp= *MeshPointStack(stack);
+	R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+	const Mesh & Thu(Uh.Th);
+	const Mesh & Thv(Vh.Th);
+	
+	bool same = &Uh == & Vh;
+	const Triangle & T  = Th[it];
+	long npi;
+	long i,j;
+	bool classoptm = copt && Op.optiexpK;
+	assert(Op.MaxOp() <last_operatortype);
+	//
+	
+	
+	KN<bool> Dop(last_operatortype);
+	Op.DiffOp(Dop);  
+	int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+	//assert(lastop<=3);
+	
+	if (ie<0)
+        {
+	    for (npi=0;npi<FI.n;npi++) // loop on the integration point
+	    {
+		QuadraturePoint pi(FI[npi]);
+		double coef = T.area*pi.a;
+		R2 Pt(pi),Ptu,Ptv;
+		R2 P(T(Pt));
+		bool outsideu,outsidev;
+		// ici trouve le T
+		int iut=0,ivt=0;
+		const Triangle * tu,*tv;
+		if(&Th == & Thu )
+		{
+		    tu =&T;
+		    Ptu=Pt;
+		}
+		else
+		{
+		    tu= Thu.Find(P,Ptu,outsideu);
+		    if( !tu ||  outsideu) { 
+			if(verbosity>100) cout << " On a pas trouver (u) " << P << " " << endl; 
+			continue;}}
+		if(same)
+		{
+		    tv=tu;
+		    outsidev=outsideu;
+		    Ptv=Ptu;
+		}
+		else
+		{
+		    if(&Th == & Thv )
+		    {
+			tv =&T;
+			Ptv=Pt;
+		    }
+		    else
+		    {
+			tv= Thv.Find(P,Ptv,outsidev);
+			if( !tv || outsidev) {
+			    if(verbosity>100) cout << " On a pas trouver (v) " << P << " " << endl;
+			    continue;
+			}}
+		} 
+		iut = Thu(tu);
+		ivt = Thv(tv);
+		if( verbosity>1000) cout << " T " << it  << "  iut " << iut << " ivt " << ivt  <<  endl ; 
+		FElement Ku(Uh[iut]);
+		FElement Kv(Vh[ivt]);
+		long n= Kv.NbDoF() ,m=Ku.NbDoF();
+		long N= Kv.N;
+		long M= Ku.N;
+		RNMK_ fv(p,n,N,lastop); //  the value for basic fonction
+		RNMK_ fu(p+ (same ?0:n*N*lastop) ,m,M,lastop); //  the value for basic fonction
+		
+		
+		Ku.BF(Dop,Ptu,fu);
+		MeshPointStack(stack)->set(Th,P,Pt,T,label);
+		if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+		if (!same) Kv.BF(Dop,Ptv,fv);      
+		for ( i=0;  i<n;   i++ )  
+		{ 
+		    
+		    // attention la fonction test donne la ligne 
+		    //  et la fonction test est en second      
+		    int ig = Kv(i);
+		    RNM_ wi(fv(i,'.','.'));         
+		    for ( j=0;  j<m;   j++ ) 
+		    { 
+			RNM_ wj(fu(j,'.','.'));
+			int il=0;
+			int jg(Ku(j));
+			if ( !sym ||  ig <= jg ) 
+			    for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+			    {  // attention la fonction test donne la ligne 
+			       //  et la fonction test est en second      
+				BilinearOperator::K ll(*l);
+				pair<int,int> jj(ll.first.first),ii(ll.first.second);
+				double w_i =  wi(ii.first,ii.second); 
+				double w_j =  wj(jj.first,jj.second);
+				R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack))   ;  
+				if( verbosity>1000) cout << ig << " " << jg << " "  <<  " " << ccc << " " <<  coef * ccc * w_i*w_j << " on T \n"   ;                                        
+				double wij =  w_i*w_j;
+				if (abs(wij)>= 1e-10)                                          
+				    A[make_pair(ig,jg)] += coef * ccc * wij;
+			    }
+		    }
+		}
+	    }
+        }
+      else // int on edge ie
+            {
+                R2 PA,PB,E;
+                if(Q)
+                {
+                    PA=Q[0];
+                    PB=Q[1];
+                    E=T(PB)-T(PA);
+                    // cout << " AddMAtElem " <<  PA <<  " " << PB << " "<< sqrt((E,E))<< endl;
+                }
+                else
+                {
+                  PA=TriangleHat[VerticesOfTriangularEdge[ie][0]];
+                  PB=TriangleHat[VerticesOfTriangularEdge[ie][1]];
+                  E=T.Edge(ie);
+                }
+                double le = sqrt((E,E));
+               
+              for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+		    {
+			QuadratureFormular1dPoint pi( FIb[npi]);
+                        double sa=pi.x,sb=1-sa;
+                        double coef = le*pi.a;
+
+			R2 Pt(PA*sa+PB*sb ); //
+			
+			R2 Ptu,Ptv;
+			R2 P(T(Pt));
+			bool outsideu,outsidev;
+			// ici trouve le T
+			int iut=0,ivt=0;
+			const Triangle * tu, *tv;
+			if(&Th == & Thu )
+			{
+			    tu =&T;
+			    Ptu=Pt;
+			}
+			else
+			{	
+			    tu= Thu.Find(P,Ptu,outsideu);
+			    if( !tu ||  (outsideu && !intmortar) )  { 
+				//R dd=-1;
+				//if(tu) { R2 PP((*tu)(Ptu)),PPP(P,PP) ; cout << PP << " " << sqrt( (PPP,PPP) ) <<"    "; } 
+				if(verbosity>100) cout << " On a pas trouver (u) " << P << " " <<Ptu << " " << tu <<   endl; 
+				continue;}}
+			iut = Thu(tu);
+			if(same)
+			{
+			    tv=tu;
+			    outsidev=outsideu;
+			    Ptv=Ptu;
+			    ivt=iut;
+			}
+			else
+			{
+			    if(&Th == & Thv )
+			    {
+				tv =&T;
+				Ptv=Pt;
+			    }
+			    else {
+				tv= Thv.Find(P,Ptv,outsidev);
+				if( !tv || (outsidev&& !intmortar))  { 
+				    if(verbosity>100) cout << " On a pas trouver (v) " << P << " " << endl; 
+				    continue;}} 
+			    ivt = Thv(tv);
+			} 
+			FElement Ku(Uh[iut]);
+			FElement Kv(Vh[ivt]);
+			long n= Kv.NbDoF() ,m=Ku.NbDoF();
+			long N= Kv.N;
+			long M= Ku.N;
+			//  cout << P << " " <<  Pt << " " <<  iut << " " << ivt  << "  Ptu : " << Ptu << " Ptv: " << Ptv << " n:" << n << " m:" << m << endl;
+			RNMK_ fv(p,n,N,lastop); //  the value for basic fonction
+			RNMK_ fu(p+ (same ?0:n*N*lastop) ,m,M,lastop); //  the value for basic fonction
+			
+			Ku.BF(Dop,Ptu,fu);
+			if( !same)
+			    Kv.BF(Dop,Ptv,fv);
+			
+			
+			// int label=-999999; // a passer en argument 
+			MeshPointStack(stack)->set(Th,P,Pt,T,label,R2(E.y,-E.x)/le,ie);
+			if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+			
+			
+			for ( i=0;  i<n;   i++ )  
+			    // if (onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // juste the df on edge bofbof generaly wrong FH dec 2003
+			{ 
+			    RNM_ wi(fv(i,'.','.'));       
+			    int ig=Kv(i);
+			    for ( j=0;  j<m;   j++ ) 
+			    { 
+				RNM_ wj(fu(j,'.','.'));
+				int il=0;
+				int jg=Ku(j);
+				if( ! sym || ig <= jg )
+				    for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+				    {       
+					BilinearOperator::K ll(*l);
+					pair<int,int> jj(ll.first.first),ii(ll.first.second);
+					double w_i =  wi(ii.first,ii.second); 
+					double w_j =  wj(jj.first,jj.second);
+					// R ccc = GetAny<R>(ll.second.eval(stack));
+					
+					R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+					double wij =  w_i*w_j;
+					if (abs(wij)>= 1e-10&& (verbosity>1000))  
+					    cout << " \t\t\t" << ig << " " << jg << " "  <<  ccc <<  " " <<  coef * ccc * w_i*w_j << " on edge \n" ;  
+					if (abs(wij)>= 1e-10)                                          
+					    A[make_pair(ig,jg)] += wij*coef*ccc ;
+				    }
+			    }
+			} 
+		    }
+            }
+			
+        *MeshPointStack(stack) = mp;
+    }  
+			
+    
+    template<class R> 
+    void  AddMatElem(map<pair<int,int>, R > & A,const Mesh3 & Th,const BilinearOperator & Op,bool sym,int it,  int ie,int label,
+                     const FESpace3 & Uh,const FESpace3 & Vh,
+                     const Fem2D::GQuadratureFormular<R3>  & FI,
+                     const  QuadratureFormular & FIb,
+                     double *p,   void *vstack, bool intmortar=false)
+    {
+         Stack stack=pvoid2Stack(vstack);
+        MeshPoint mp= *MeshPointStack(stack);
+        static int count =0; // non test FH .........................
+        if(count++ < 1) {
+            cout << " Warning : Assemble Matrix with incompatible 3d meshes in test (FH)  " << endl;
+            cout << " ------------------------------------------------------------- " << endl;
+        }
+        R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+        const Mesh3 & Thu(Uh.Th);
+        const Mesh3 & Thv(Vh.Th);
+        
+        bool same = &Uh == & Vh;
+        const Tet & T  = Th[it];
+        long npi;
+        long i,j;
+        bool classoptm = copt && Op.optiexpK;
+        assert(Op.MaxOp() <last_operatortype);
+        //
+        int lastop=0;
+        lastop = 0;
+        What_d Dop = Op.DiffOp(lastop);
+
+       
+        //assert(lastop<=3);
+        
+        if (ie<0)    
+            for (npi=0;npi<FI.n;npi++) // loop on the integration point
+            {
+                GQuadraturePoint<R3> pi(FI[npi]);
+                double coef = T.mesure()*pi.a;
+                R3 Pt(pi),Ptu,Ptv;
+                R3 P(T(Pt));
+                bool outsideu,outsidev;
+                // ici trouve le T
+                int iut=0,ivt=0;
+                const Tet * tu,*tv;
+                if(&Th == & Thu )
+                {
+                    tu =&T;
+                    Ptu=Pt;
+                }
+                else
+                {
+                    tu= Thu.Find(P,Ptu,outsideu);
+                    if( !tu ||  outsideu) { 
+                        if(verbosity>100) cout << " On a pas trouver (u) " << P << " " << endl; 
+                        continue;}}
+                if(same)
+                {
+                    tv=tu;
+                    outsidev=outsideu;
+                    Ptv=Ptu;
+                }
+                else
+                {
+                    if(&Th == & Thv )
+                    {
+                        tv =&T;
+                        Ptv=Pt;
+                    }
+                    else
+                    {
+                        tv= Thv.Find(P,Ptv,outsidev);
+                        if( !tv || outsidev) {
+                            if(verbosity>100) cout << " On a pas trouver (v) " << P << " " << endl;
+                            continue;
+                        }}
+                } 
+                iut = Thu(tu);
+                ivt = Thv(tv);
+                if( verbosity>1000) cout << " T " << it  << "  iut " << iut << " ivt " << ivt  <<  endl ; 
+                FElement3 Ku(Uh[iut]);
+                FElement3 Kv(Vh[ivt]);
+                long n= Kv.NbDoF() ,m=Ku.NbDoF();
+                long N= Kv.N;
+                long M= Ku.N;
+                RNMK_ fv(p,n,N,(long) lastop); //  the value for basic fonction
+                RNMK_ fu(p+ (same ?0:n*N*lastop) ,m,M,(long) lastop); //  the value for basic fonction
+                
+                
+                Ku.BF(Dop,Ptu,fu);
+                MeshPointStack(stack)->set(Th,P,Pt,T,label);
+                if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+                if (!same) Kv.BF(Dop,Ptv,fv);      
+                for ( i=0;  i<n;   i++ )  
+                { 
+                    
+                    // attention la fonction test donne la ligne 
+                    //  et la fonction test est en second      
+                    int ig = Kv(i);
+                    RNM_ wi(fv(i,'.','.'));         
+                    for ( j=0;  j<m;   j++ ) 
+                    { 
+                        RNM_ wj(fu(j,'.','.'));
+                        int il=0;
+                        int jg(Ku(j));
+                        if ( !sym ||  ig <= jg ) 
+                            for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                            {  // attention la fonction test donne la ligne 
+                                //  et la fonction test est en second      
+                                BilinearOperator::K ll(*l);
+                                pair<int,int> jj(ll.first.first),ii(ll.first.second);
+                                double w_i =  wi(ii.first,ii.second); 
+                                double w_j =  wj(jj.first,jj.second);
+                                R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack))   ;  
+                                if( verbosity>1000) cout << ig << " " << jg << " "  <<  " " << ccc << " " <<  coef * ccc * w_i*w_j << " on T \n"   ;                                        
+                                double wij =  w_i*w_j;
+                                if (abs(wij)>= 1e-10)                                          
+                                    A[make_pair(ig,jg)] += coef * ccc * wij;
+                            }
+                    }
+                }
+            }
+		else // int on edge ie 
+		    for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+		    {
+              
+                GQuadraturePoint<R2> pi( FIb[npi]);
+                R3 NN= T.N(ie);
+                double mes=NN.norme();
+                NN/=mes;
+                double coef = 0.5*mes*pi.a; // correction 0.5 050109 FH
+                R3 Pt(T.PBord(ie,pi));
+                //Ku.BF(Dop,Pt,fu);
+
+               
+                
+                R3 Ptu,Ptv;
+                R3 P(T(Pt));
+                bool outsideu,outsidev;
+                // ici trouve le T
+                int iut=0,ivt=0;
+                const Tet * tu, *tv;
+                if(&Th == & Thu )
+                {
+                    tu =&T;
+                    Ptu=Pt;
+                }
+                else
+                {	
+                    tu= Thu.Find(P,Ptu,outsideu);
+                    if( !tu ||  (outsideu && !intmortar) )  { 
+                        //R dd=-1;
+                        //if(tu) { R2 PP((*tu)(Ptu)),PPP(P,PP) ; cout << PP << " " << sqrt( (PPP,PPP) ) <<"    "; } 
+                        if(verbosity>100) cout << " On a pas trouver (u) " << P << " " <<Ptu << " " << tu <<   endl; 
+                        continue;}}
+                iut = Thu(tu);
+                if(same)
+                {
+                    tv=tu;
+                    outsidev=outsideu;
+                    Ptv=Ptu;
+                    ivt=iut;
+                }
+                else
+                {
+                    if(&Th == & Thv )
+                    {
+                        tv =&T;
+                        Ptv=Pt;
+                    }
+                    else {
+                        tv= Thv.Find(P,Ptv,outsidev);
+                        if( !tv || (outsidev&& !intmortar))  { 
+                            if(verbosity>100) cout << " On a pas trouver (v) " << P << " " << endl; 
+                            continue;}} 
+                    ivt = Thv(tv);
+                } 
+                FElement3 Ku(Uh[iut]);
+                FElement3 Kv(Vh[ivt]);
+                long n= Kv.NbDoF() ,m=Ku.NbDoF();
+                long N= Kv.N;
+                long M= Ku.N;
+                //  cout << P << " " <<  Pt << " " <<  iut << " " << ivt  << "  Ptu : " << Ptu << " Ptv: " << Ptv << " n:" << n << " m:" << m << endl;
+                RNMK_ fv(p,n,N,lastop); //  the value for basic fonction
+                RNMK_ fu(p+ (same ?0:n*N*lastop) ,m,M,lastop); //  the value for basic fonction
+                
+                Ku.BF(Dop,Ptu,fu);
+                if( !same)
+                    Kv.BF(Dop,Ptv,fv);
+                
+                
+                // int label=-999999; // a passer en argument 
+                MeshPointStack(stack)->set(Th,P,Pt,T,label,NN,ie);
+                if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+                
+                
+                for ( i=0;  i<n;   i++ )  
+                    // if (onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // juste the df on edge bofbof generaly wrong FH dec 2003
+                { 
+                    RNM_ wi(fv(i,'.','.'));       
+                    int ig=Kv(i);
+                    for ( j=0;  j<m;   j++ ) 
+                    { 
+                        RNM_ wj(fu(j,'.','.'));
+                        int il=0;
+                        int jg=Ku(j);
+                        if( ! sym || ig <= jg )
+                            for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                            {       
+                                BilinearOperator::K ll(*l);
+                                pair<int,int> jj(ll.first.first),ii(ll.first.second);
+                                double w_i =  wi(ii.first,ii.second); 
+                                double w_j =  wj(jj.first,jj.second);
+                                // R ccc = GetAny<R>(ll.second.eval(stack));
+                                
+                                R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+                                double wij =  w_i*w_j;
+                                if (abs(wij)>= 1e-10&& (verbosity>1000))  
+                                    cout << " \t\t\t" << ig << " " << jg << " "  <<  ccc <<  " " <<  coef * ccc * w_i*w_j << " on edge \n" ;  
+                                if (abs(wij)>= 1e-10)                                          
+                                    A[make_pair(ig,jg)] += wij*coef*ccc ;
+                            }
+                    }
+                } 
+		    }
+        
+        
+        *MeshPointStack(stack) = mp;
+    }  
+   
+ template<class R>
+  void AssembleBilinearForm(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                           map<pair<int,int>, R >  & A, const  FormBilinear * b  )
+    
+  {
+  /*FH:  case ..in 2D
+     in varf ...
+     all mesh can can be different ....
+   */
+      StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+     bool sptrclean=true;
+     //     sptr->clean(); // modif FH mars 2006  clean Ptr
+
+    const CDomainOfIntegration & di= *b->di;
+    const Mesh * pThdi = GetAny<pmesh>( (* di.Th)(stack));
+    SHOWVERB(cout << " FormBilinear () " << endl);
+    //MatriceElementaireSymetrique<R> *mates =0;
+    // MatriceElementairePleine<R> *matep =0;
+    const bool useopt=di.UseOpt(stack);    
+    //double binside=di.binside(stack);
+    const bool intmortar=di.intmortar(stack);
+    if ( verbosity >1)
+     {
+      cout << " Integral   on Th nv :  " << Th.nv << " nt : " << Th.nt << endl;
+      cout << "        Th/ u nv : " << Uh.Th.nv << "   nt : " << Uh.Th.nt << endl;
+      cout << "        Th/ v nv : " << Vh.Th.nv << "   nt : " << Vh.Th.nt << endl;
+      cout << "        suppose in mortar " << intmortar << "   levelset=  " << di.islevelset() << endl;
+     }
+    assert(pThdi == & Th);
+    //const vector<Expression>  & what(di.what);             
+    CDomainOfIntegration::typeofkind  kind = di.kind;
+    set<int> setoflab;
+    bool all=true; 
+    const QuadratureFormular1d & FIE = di.FIE(stack);
+    const QuadratureFormular & FITo = di.FIT(stack);
+    QuadratureFormular FIT(FITo,3);
+    bool VF=b->VF();  // finite Volume or discontinous Galerkin
+    if (verbosity>2) cout << "  -- discontinous Galerkin  =" << VF << " size of Mat =" << A.size()<< " Bytes\n";
+    if (verbosity>3)
+    {
+      if (CDomainOfIntegration::int1d==kind) cout << "  -- boundary int border ( nQP: "<< FIE.n << ") ,"  ;
+      else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges ( nQP: "<< FIE.n << "),"  ;
+      else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIE.n << ")," ;
+      else cout << "  --  int    (nQP: "<< FIT.n << " ) in "  ;
+    }
+     // if(di.islevelset()) InternalError("Sorry no levelset integration type on this case (1)");
+      if(di.islevelset() && (CDomainOfIntegration::int1d!=kind) &&  (CDomainOfIntegration::int2d!=kind) )
+          InternalError("Sorry no levelset integration type on no int1d case");
+      
+    /*
+    if (verbosity>3) 
+      if (CDomainOfIntegration::int1d==kind) cout << "  -- boundary int border  " ;
+      else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges, "   ;
+      else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges, "   ;
+      else cout << "  --  int  in  " ; */
+    Expandsetoflab(stack,di, setoflab,all);
+    /*
+    for (size_t i=0;i<what.size();i++)
+      {long  lab  = GetAny<long>( (*what[i])(stack));
+      setoflab.insert(lab);
+      if ( verbosity>3) cout << lab << " ";
+      all=false;
+      }*/
+     if (verbosity>3) cout <<" Optimized = "<< useopt << ", ";
+  const E_F0 & optiexp0=*b->b->optiexp0;
+  // const E_F0 & optiexpK=*b->b->optiexpK;
+  int n_where_in_stack_opt=b->b->where_in_stack_opt.size();
+  R** where_in_stack =0;
+  if (n_where_in_stack_opt && useopt)
+    where_in_stack = new R * [n_where_in_stack_opt];
+  if (where_in_stack)
+   {
+    assert(b->b->v.size()==(size_t) n_where_in_stack_opt);
+    for (int i=0;i<n_where_in_stack_opt;i++)
+    {
+      int offset=b->b->where_in_stack_opt[i];
+      assert(offset>10);
+      where_in_stack[i]= static_cast<R *>(static_cast<void *>((char*)stack+offset));
+      *(where_in_stack[i])=0;
+     }
+    
+    
+    if(&optiexp0) 
+      optiexp0(stack); 
+    KN<bool> ok(b->b->v.size());
+     {  //   remove the zero coef in the liste 
+       // R zero=R();  
+      int il=0;
+      for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+        ok[il] =  ! (b->b->mesh_indep_stack_opt[il] && ( Fem2D::norm(*(where_in_stack[il])) < 1e-100 ) );
+     }
+    BilinearOperator b_nozer(*b->b,ok); 
+    if (verbosity % 10 > 3 ) 
+      cout << "   -- nb term in bilinear form  (!0) : " << b_nozer.v.size() 
+           << "  total " << n_where_in_stack_opt << endl;
+    
+    if ( (verbosity/100) % 10 >= 2)   
+     { 
+      int il=0;
+      
+      for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+       cout << il << " coef (" << l->first << ") = " << *(where_in_stack[il]) 
+                  << " offset=" << b->b->where_in_stack_opt[il] 
+                  << " dep mesh " << l->second.MeshIndependent() << b->b->mesh_indep_stack_opt[il] << endl;
+    }
+    }
+    Stack_Ptr<R*>(stack,ElemMatPtrOffset) =where_in_stack;
+  
+   KN<double>  p(Vh.esize()+ Uh.esize() );
+
+    
+    if (verbosity >3)
+    {
+      if (all) cout << " all " << endl ;
+      else cout << endl;
+    }
+    
+      if (di.kind == CDomainOfIntegration::int1d )
+      {
+         
+          if(di.islevelset())
+          {
+              double uset = HUGE_VAL;
+              R2 Q[2];
+              double vol6[2];
+              KN<double> phi(Th.nv);phi=uset;
+              double f[3], ll=0;
+              for(int t=0; t< Th.nt;++t)
+              {
+                  if ( all || setoflab.find(Th[t].lab) != setoflab.end())
+                  {
+                      double umx=-HUGE_VAL,umn=HUGE_VAL;
+                      for(int i=0;i<3;++i)
+                      {
+                          int j= Th(t,i);
+                          if( phi[j]==uset)
+                          {
+                              MeshPointStack(stack)->setP(&Th,t,i);
+                              phi[j]= di.levelset(stack);//zzzz
+                          }
+                          f[i]=phi[j];
+                          umx = std::max(umx,phi[j]);
+                          umn = std::min(umn,phi[j]);
+                          
+                      }
+                      int ntp= IsoLineK(f,Q,1e-10);
+                      if(verbosity>999 && ntp==2)
+                      {
+                          const Triangle &T = Th[t];
+                          R2 E(T(Q[0]),T(Q[1]));
+                          double le=sqrt((E,E));
+                          ll += le;
+                        cout << "\t\t" << ntp <<" :  " << Q[0] << " " << Q[1] << " ;  "
+                             << f[0] << " " << f[1] << " " << f[2] << "  " << le << " / " << ll<<endl;
+                      }
+                      if( ntp==2)
+                      {
+                          AddMatElem(A,Th,*b->b,sym,t,10,Th[t].lab,Uh,Vh,FIT,FIE,p,stack,intmortar,Q);
+                          if(sptrclean) sptrclean=sptr->clean();
+                      }
+                  }
+              }
+              FIT =FITo;
+          }
+          
+          
+          else
+          {
+              for( int e=0;e<Th.neb;e++)
+              {
+                  if (all || setoflab.find(Th.bedges[e].lab) != setoflab.end())
+                  {
+                      int ie,i =Th.BoundaryElement(e,ie);
+                      AddMatElem(A,Th,*b->b,sym,i,ie,Th.bedges[e].lab,Uh,Vh,FIT,FIE,p,stack,intmortar);
+                      if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+                  }
+              }
+          }}
+    else if (di.kind == CDomainOfIntegration::intalledges)
+      {
+        cerr << " Sorry no implement to hard  "<< endl;
+        ExecError("FH: no intalledges on diff mesh ???");
+        ffassert(0); // a faire 
+        for (int i=0;i< Th.nt; i++) 
+          {
+            if ( all || setoflab.find(Th[i].lab) != setoflab.end())
+             for (int ie=0;ie<3;ie++)   
+                AddMatElem(A,Th,*b->b,sym,i,ie,Th[i].lab,Uh,Vh,FIT,FIE,p,stack,intmortar);  
+             if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr   
+                
+                
+          }
+         
+      }      
+    else if (di.kind == CDomainOfIntegration::intallVFedges)
+      {
+       
+       cerr << " a faire intallVFedges " << endl;
+       ffassert(0);
+         
+      }      
+    else if (di.kind == CDomainOfIntegration::int2d )
+      {
+       // cerr << " a faire CDomainOfIntegration::int2d  " << endl;
+          if(di.islevelset())
+          {
+              double uset = HUGE_VAL;
+              R2 Q[2][3];
+              double vol6[2];
+              KN<double> phi(Th.nv);phi=uset;
+              double f[3];
+              for(int t=0; t< Th.nt;++t)
+              {
+                  if ( all || setoflab.find(Th[t].lab) != setoflab.end())
+                  {
+                      double umx=-HUGE_VAL,umn=HUGE_VAL;
+                      for(int i=0;i<3;++i)
+                      {
+                          int j= Th(t,i);
+                          if( phi[j]==uset)
+                          {
+                              MeshPointStack(stack)->setP(&Th,t,i);
+                              phi[j]= di.levelset(stack);//zzzz
+                          }
+                          f[i]=phi[j];
+                          umx = std::max(umx,phi[j]);
+                          umn = std::min(umn,phi[j]);
+                          
+                      }
+                      int nt= UnderIso(f,Q, vol6,1e-14);
+                      setQF<R2>(FIT,FITo,QuadratureFormular_T_1, Q,vol6,nt);
+                      if(FIT.n)
+                        AddMatElem(A,Th,*b->b,sym,t,-1,Th[t].lab,Uh,Vh,FIT,FIE,p,stack);
+                      if(sptrclean) sptrclean=sptr->clean();
+                  }
+              }
+              FIT =FITo;
+          }
+          else
+  
+        {
+        for (int i=0;i< Th.nt; i++)
+          {
+            if ( all || setoflab.find(Th[i].lab) != setoflab.end())  
+               AddMatElem(A,Th,*b->b,sym,i,-1,Th[i].lab,Uh,Vh,FIT,FIE,p,stack); 
+            if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr    
+          }
+
+      }}
+    else 
+      InternalError(" kind of CDomainOfIntegration unkown");
+      
+    if (where_in_stack) delete [] where_in_stack;
+  }
+
+			
+ template<class R>
+  void AssembleBilinearForm(Stack stack,const Mesh3 & Th,const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+                           map<pair<int,int>, R >  & A, const  FormBilinear * b  )
+    
+  {
+      /*FH:  case ..in 3D
+       in varf ...
+       all mesh can can be different ....
+       */
+      
+      
+      StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+      bool sptrclean=true;
+      //     sptr->clean(); // modif FH mars 2006  clean Ptr
+      
+      const CDomainOfIntegration & di= *b->di;
+      const Mesh3 * pThdi = GetAny<pmesh3>( (* di.Th)(stack));
+      SHOWVERB(cout << " FormBilinear () " << endl);
+      //MatriceElementaireSymetrique<R> *mates =0;
+      // MatriceElementairePleine<R> *matep =0;
+      const bool useopt=di.UseOpt(stack);    
+      //double binside=di.binside(stack);
+      const bool intmortar=di.intmortar(stack);
+      if ( verbosity >1)
+      {
+          cout << " Integral   on Th nv :  " << Th.nv << " nt : " << Th.nt << endl;
+          cout << "        Th/ u nv : " << Uh.Th.nv << "   nt : " << Uh.Th.nt << endl;
+          cout << "        Th/ v nv : " << Vh.Th.nv << "   nt : " << Vh.Th.nt << endl;
+          cout << "        suppose in mortar " << intmortar << endl;
+      }
+      assert(pThdi == & Th);
+      //const vector<Expression>  & what(di.what);             
+      CDomainOfIntegration::typeofkind  kind = di.kind;
+      set<int> setoflab;
+      bool all=true;
+      // const QuadratureFormular1d & FIEo = di.FIE(stack);
+      const QuadratureFormular & FITo = di.FIT(stack);
+      const GQuadratureFormular<R3> & FIVo = di.FIV(stack);
+      //  to change the quadrature on element ... may 2014 FH ..
+      // QuadratureFormular1d  FIE(FIEo,3);
+      QuadratureFormular FIT(FITo,3);
+      GQuadratureFormular<R3>  FIV(FIVo,3);
+      
+      
+      
+  //    const QuadratureFormular & FIT = di.FIT(stack);
+  //    const Fem2D::GQuadratureFormular<R3> & FIV = di.FIV(stack);
+      bool VF=b->VF();  // finite Volume or discontinous Galerkin
+      if (verbosity>2) cout << "  -- discontinous Galerkin  =" << VF << " size of Mat =" << A.size()<< " Bytes\n";
+      if (verbosity>3)
+      {
+          if (CDomainOfIntegration::int2d==kind) cout << "  -- boundary int border ( nQP: "<< FIT.n << ") ,"  ;
+          else  if (CDomainOfIntegration::intallfaces==kind) cout << "  -- boundary int all edges ( nQP: "<< FIT.n << "),"  ;
+          //else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIT.n << ")," ;
+          else cout << "  --  int    (nQP: "<< FIV.n << " ) in "  ;
+      }
+      if(di.islevelset()) InternalError("Sorry no levelset integration type on this case (2)");
+      if(di.islevelset() && (CDomainOfIntegration::int2d!=kind) && (CDomainOfIntegration::int3d!=kind) ) InternalError("Sorry no levelset integration type on no int2d case");
+   
+      Expandsetoflab(stack,di, setoflab,all);
+      /*
+       for (size_t i=0;i<what.size();i++)
+       {long  lab  = GetAny<long>( (*what[i])(stack));
+       setoflab.insert(lab);
+       if ( verbosity>3) cout << lab << " ";
+       all=false;
+       }*/
+      if (verbosity>3) cout <<" Optimized = "<< useopt << ", ";
+      const E_F0 & optiexp0=*b->b->optiexp0;
+      // const E_F0 & optiexpK=*b->b->optiexpK;
+      int n_where_in_stack_opt=b->b->where_in_stack_opt.size();
+      R** where_in_stack =0;
+      if (n_where_in_stack_opt && useopt)
+          where_in_stack = new R * [n_where_in_stack_opt];
+      if (where_in_stack)
+      {
+          assert(b->b->v.size()==(size_t) n_where_in_stack_opt);
+          for (int i=0;i<n_where_in_stack_opt;i++)
+          {
+              int offset=b->b->where_in_stack_opt[i];
+              assert(offset>10);
+              where_in_stack[i]= static_cast<R *>(static_cast<void *>((char*)stack+offset));
+              *(where_in_stack[i])=0;
+          }
+          
+          
+          if(&optiexp0) 
+              optiexp0(stack); 
+          KN<bool> ok(b->b->v.size());
+          {  //   remove the zero coef in the liste 
+              // R zero=R();  
+              int il=0;
+              for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+                  ok[il] =  ! (b->b->mesh_indep_stack_opt[il] && ( Fem2D::norm(*(where_in_stack[il])) < 1e-100 ) );
+          }
+          BilinearOperator b_nozer(*b->b,ok); 
+          if (verbosity % 10 > 3 ) 
+              cout << "   -- nb term in bilinear form  (!0) : " << b_nozer.v.size() 
+              << "  total " << n_where_in_stack_opt << endl;
+          
+          if ( (verbosity/100) % 10 >= 2)   
+          { 
+              int il=0;
+              
+              for (BilinearOperator::const_iterator l=b->b->v.begin();l!=b->b->v.end();l++,il++)
+                  cout << il << " coef (" << l->first << ") = " << *(where_in_stack[il]) 
+                  << " offset=" << b->b->where_in_stack_opt[il] 
+                  << " dep mesh " << l->second.MeshIndependent() << b->b->mesh_indep_stack_opt[il] << endl;
+          }
+      }
+      Stack_Ptr<R*>(stack,ElemMatPtrOffset) =where_in_stack;
+      
+      KN<double>  p(Vh.esize()+ Uh.esize() );
+      
+      
+      if (verbosity >3) 
+	{
+	  if (all) cout << " all " << endl ;
+          else cout << endl;
+	}
+      
+      if (di.kind == CDomainOfIntegration::int2d )
+      { 
+          for( int e=0;e<Th.nbe;e++)
+          {
+              if (all || setoflab.find(Th.be(e).lab) != setoflab.end())   
+              {                  
+                  int ie,i =Th.BoundaryElement(e,ie);
+                  AddMatElem(A,Th,*b->b,sym,i,ie,Th.be(e).lab,Uh,Vh,FIV,FIT,p,stack,intmortar);  
+                  if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+              }
+          }
+      }
+      else if (di.kind == CDomainOfIntegration::intallfaces)
+      {
+          ffassert(0); // a faire 
+          
+          for (int i=0;i< Th.nt; i++) 
+          {
+              if ( all || setoflab.find(Th[i].lab) != setoflab.end())
+                  for (int ie=0;ie<3;ie++)   
+                      AddMatElem(A,Th,*b->b,sym,i,ie,Th[i].lab,Uh,Vh,FIV,FIT,p,stack,intmortar);  
+           
+              if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr   
+              
+              
+          } 
+          
+      }      
+     /* else if (di.kind == CDomainOfIntegration::intallVFedges)
+      {
+          
+          cerr << " a faire intallVFedges " << endl;
+          ffassert(0);
+          
+      }  */    
+      else if (di.kind == CDomainOfIntegration::int3d )
+      {
+          if(di.islevelset())  //  may 2014 FH ...
+          {   // int3d levelset < 0
+              double llevelset = 0;
+              const double uset = std::numeric_limits<double>::max();
+              // cout << " uset ="<<uset << endl;
+              R3 Q[3][4];
+              double vol6[3];
+              KN<double> phi(Th.nv);
+              phi=uset;
+              double f[4];
+              
+              for (int t=0;t< Th.nt; t++)
+              {
+                  
+                  const Mesh3::Element & K(Th[t]);
+                  if (all || setoflab.find(Th[t].lab) != setoflab.end())
+                      
+                  {
+                      double umx=std::numeric_limits<double>::min(),umn=std::numeric_limits<double>::max();
+                      for(int i=0;i<4;++i)
+                      {
+                          int j= Th(t,i);
+                          if( phi[j]==uset)
+                          {
+                              MeshPointStack(stack)->setP(&Th,t,i);
+                              phi[j]= di.levelset(stack);//zzzz
+                          }
+                          f[i]=phi[j];
+                      }
+                      int ntets= UnderIso(f,Q, vol6,1e-14);
+                      setQF<R3>(FIV,FIVo,QuadratureFormular_Tet_1, Q,vol6,ntets);
+                      if(FIV.n)
+                      {
+                          AddMatElem(A,Th,*b->b,sym,t,-1,Th[t].lab,Uh,Vh,FIV,FIT,p,stack);
+                          if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+                          
+                      }
+                      
+                  }
+              }
+              FIV = FIVo;
+              
+          }
+          else
+
+      {
+          // cerr << " a faire CDomainOfIntegration::int3d  " << endl;
+          for (int i=0;i< Th.nt; i++) 
+          {
+              if ( all || setoflab.find(Th[i].lab) != setoflab.end())  
+                  AddMatElem(A,Th,*b->b,sym,i,-1,Th[i].lab,Uh,Vh,FIV,FIT,p,stack); 
+              if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr    
+          }
+          
+      } }
+      else 
+          InternalError(" kind of CDomainOfIntegration unkown");
+      
+      if (where_in_stack) delete [] where_in_stack;      
+   
+  }
+// --------- FH 170605
+ 
+ 
+  template<class R> 
+  void  Element_Op(MatriceElementairePleine<R,FESpace3> & mat,const FElement3 & Ku,const FElement3 & Kv,double * p,int ie,int label,void *vstack,R3 *B)
+  {
+  //  ffassert(B==0);
+   Stack stack=pvoid2Stack(vstack);    
+    //    ffassert(0);
+    typedef  FElement3::Element Element;
+    MeshPoint mp= *MeshPointStack(stack);
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    
+    bool same = &Ku == & Kv;
+    const Element & T  = Ku.T;
+    throwassert(&T == &Kv.T);  
+    const GQuadratureFormular<R3> & FI = mat.FIT;
+    const GQuadratureFormular<R2> & FIb = mat.FIE;
+    long npi;
+    R *a=mat.a;
+    R *pa=a;
+    long i,j;
+    long n= mat.n,m=mat.m,nx=n*m;
+    long N= Kv.N;
+    long M= Ku.N;
+    
+  
+    
+    
+    
+    const Opera &Op(*mat.bilinearform);
+    bool classoptm = copt && Op.optiexpK;
+    bool oldopt=1;  // juin 2007 FH ???? a voir 
+    int  iloop=0;
+    KN<bool> unvarexp(classoptm ? Op.optiexpK->sizevar() : 1);
+    if (Ku.number<1 && verbosity/100 && verbosity % 10 == 2) 
+      cout << "Element_Op 3d P: copt = " << copt << " " << classoptm << endl;
+    assert(Op.MaxOp() <last_operatortype);
+    //
+    int lastop;
+    lastop = 0;
+    What_d Dop = Op.DiffOp(lastop);
+    //KN<bool> Dop(last_operatortype);
+    //p.DiffOp(Dop);  
+    //int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+    //assert(lastop<=3);
+    RNMK_ fv(p,n,N,lastop); //  the value for basic fonction
+    RNMK_ fu(p+ (same ?0:n*N*lastop) ,m,M,lastop); //  the value for basic fonction
+  
+    for (i=0;i< nx;i++) 
+      *pa++ = 0.; 
+    if (ie<0)    
+      for (npi=0;npi<FI.n;npi++) // loop on the integration point
+	{
+	  GQuadraturePoint<R3> pi(FI[npi]);
+	  R coef = T.mesure()*pi.a;
+	  R3 Pt(pi);
+	  pa =a;
+	  Ku.BF(Dop,Pt,fu);
+	  MeshPointStack(stack)->set(T(Pt),Pt,Kv);
+	  if (classoptm) {
+	    if( oldopt) (*Op.optiexpK)(stack); // call old optim version 
+	    else Op.optiexpK->eval(stack,iloop++,unvarexp); // new optim version 
+	  }
+	  if (!same) Kv.BF(Dop,Pt,fv);
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	    {  // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      BilinearOperator::K ll(*l);
+	      //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+	      long jcomp= ll.first.first.first,jop=ll.first.first.second;
+	      long icomp= ll.first.second.first,iop=ll.first.second.second;
+	      
+	      R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+	      if ( copt && Kv.number <1)
+		{
+		  R cc  =  GetAny<R>(ll.second.eval(stack));
+		  //cout << *(copt[il]) << " == " <<  cc << endl;
+		  if ( ccc != cc) { 
+		    cerr << cc << " != " << ccc << " => ";
+		    cerr << "Sorry error in Optimization (a) add:  int2d(Th,optimize=0)(...)" << endl;
+		    ExecError("In Optimized version "); }
+		}
+	      int fi=Kv.dfcbegin(icomp);
+	      int li=Kv.dfcend(icomp);
+	      int fj=Ku.dfcbegin(jcomp);
+	      int lj=Ku.dfcend(jcomp);
+	      ccc *= coef;
+	      
+	      // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      
+	      for ( i=fi;  i<li;   i++ )  
+		{ 
+		  for ( j=fj;  j<lj;   j++ ) 
+		    { 		      
+		      R w_i =  fv(i,icomp,iop); 
+		      R w_j =  fu(j,jcomp,jop);		      
+		      mat(i,j) += ccc * w_i*w_j;
+		    }
+		}
+	    }
+	}
+    else if(B)
+    {  // int on leveset
+        int np = ie-10; //= (B[0].x == B[3].x ) && (B[0].y == B[3].y ) && (B[0].z == B[3].z ) ? 3 : 4;
+        if(verbosity>999) cout << "    Ass mat pleine /"<< np << endl;
+        assert( np==3 || np==4);
+        // XXXXXXX
+        double epsmes3=T.mesure()*T.mesure()*1e-18;
+        R3 PP[4];
+        double l[3];
+        for(int i=0; i< np; ++i)
+            PP[i]= T(B[i]);
+        
+        for( int i =0; i+1 < np; i+=2)
+        { // 0,1,, a and 2,3,0.
+            int i0=i,i1=i+1,i2=(i+2)%np;
+            R3 NN= R3(PP[i0],PP[i1])^R3(PP[i0],PP[i2]);
+            double mes2 = (NN,NN);
+            double mes = sqrt(mes2);
+
+            if(mes2*mes <epsmes3) continue; //  too small
+            NN /= mes;
+            mes *= 0.5;
+            if(verbosity>999)
+                cout << " --int on leveset3d " << np << " " << mes << " " << i0<<i1<<i2 <<endl;
+            double asum=0;
+            for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+            {
+                GQuadraturePoint<R2>  pi( FIb[npi]);
+               // cout << " %% " << npi << " " << pi.a << " " << pi.x << " " << pi.y << endl;
+                asum+= pi.a;
+                pi.toBary(l);
+                R3 Pt( l[0]*B[i0]+l[1]*B[i1]+l[2]*B[i2]); //
+                double coef = mes*pi.a; // correction 0.5 050109 FH
+                Ku.BF(Dop,Pt,fu);
+                if (!same) Kv.BF(Dop,Pt,fv);
+                MeshPointStack(stack)->set(T(Pt),Pt,Ku,label,NN,ie);
+                if (classoptm) (*Op.optiexpK)(stack); // call optim version
+
+                pa=a;
+                for (int i=0;  i<n;   i++ )
+                {
+                    RNM_ wi(fv(i,'.','.'));
+                    for (int  j=0;  j<m;   j++,pa++ )
+                    {
+                        RNM_ wj(fu(j,'.','.'));
+                        int il=0;
+                        for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+			{
+			    BilinearOperator::K ll(*l);
+			    pair<int,int> jj(ll.first.first),ii(ll.first.second);
+			    
+			    double w_i =  wi(ii.first,ii.second);
+			    double w_j =  wj(jj.first,jj.second);
+			    
+			    R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+			    if ( copt && Kv.number <1)
+                            {
+                                R cc  =  GetAny<R>(ll.second.eval(stack));
+                                if ( ccc != cc) {
+                                    cerr << cc << " != " << ccc << " => ";
+                                    cerr << "Sorry error in Optimization (b) add:  int2d(Th,optimize=0)(...)" << endl;
+                                    ExecError("In Optimized version "); }
+                            }
+                            if(verbosity>999)
+                                cout << " -- int on leveset3d  aij = "<< pi.a* ccc * w_i*w_j <<" " << ccc << " " << w_i*w_j <<endl;
+			    *pa += coef * ccc * w_i*w_j;
+			}
+                    }
+                }
+               if(verbosity>999) cout << " ++\n";
+            }
+
+            if(verbosity>999) cout << " @@ "<< asum << endl;;
+
+        }
+        
+    }// end int level set ...
+    else // int on edge ie
+     for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+      {
+        pa =a;
+	GQuadraturePoint<R2> pi( FIb[npi]);
+	R3 NN= T.N(ie);
+	  double mes=NN.norme();
+	  NN/=mes;
+	  double coef = 0.5*mes*pi.a; // correction 0.5 050109 FH
+	  R3 Pt(T.PBord(ie,pi));
+	  Ku.BF(Dop,Pt,fu);
+	  if (!same) Kv.BF(Dop,Pt,fv);      
+          MeshPointStack(stack)->set(T(Pt),Pt,Ku,label,NN,ie);
+         if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+        
+        
+	  for ( i=0;  i<n;   i++ )  
+	    { 
+		RNM_ wi(fv(i,'.','.'));       
+		for ( j=0;  j<m;   j++,pa++ ) 
+		  { 
+		      RNM_ wj(fu(j,'.','.'));
+		      int il=0;
+		      for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+			{       
+			    BilinearOperator::K ll(*l);
+			    pair<int,int> jj(ll.first.first),ii(ll.first.second);
+			    
+			    double w_i =  wi(ii.first,ii.second); 
+			    double w_j =  wj(jj.first,jj.second);
+			    
+			    R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+			    if ( copt && Kv.number <1)
+			      {
+				  R cc  =  GetAny<R>(ll.second.eval(stack));
+				  if ( ccc != cc) { 
+				      cerr << cc << " != " << ccc << " => ";
+				      cerr << "Sorry error in Optimization (b) add:  int2d(Th,optimize=0)(...)" << endl;
+				  ExecError("In Optimized version "); }
+			      }
+			    *pa += coef * ccc * w_i*w_j;
+			}
+		  }
+	    } 
+      }
+   
+    
+    if (Ku.Vh.Th(T) <1 && verbosity>100) {
+      pa=mat.a;
+      cout <<endl  << " Tet " << Ku.Vh.Th(T) << " =  " << T  << " " << nx << endl;
+      for (int i=0;i<n;i++)
+	{
+	  cout << setw(2) << i << setw(4) << mat.ni[i] << " :";
+	  for (int j=0;j<m;j++)
+	    cout << setw(5)  << (*pa++) << " ";
+	  cout << endl;
+	} } 
+    
+
+  } 
+  // xxxxxxxxxxxxxxxxx  modif a faire 
+  template<class R> 
+  void  Element_Op(MatriceElementairePleine<R,FESpace> & mat,const FElement & Ku,const FElement & Kv,double * p,int ie,int label,void *vstack,R2 *B)
+  {
+      Stack stack=pvoid2Stack(vstack);
+    typedef  FElement::Element Element;
+    MeshPoint mp= *MeshPointStack(stack);
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+
+  bool same = &Ku == & Kv;
+  const Element & T  = Ku.T;
+  throwassert(&T == &Kv.T);  
+  const QuadratureFormular & FI = mat.FIT;
+  const QuadratureFormular1d & FIb = mat.FIE;
+  long npi;
+  R *a=mat.a;
+  R *pa=a;
+  long i,j;
+  long n= mat.n,m=mat.m,nx=n*m;
+  long N= Kv.N;
+  long M= Ku.N;
+  
+  
+  
+  
+  
+  const Opera &Op(*mat.bilinearform);
+  bool classoptm = copt && Op.optiexpK;
+  bool oldopt=1;  // juin 2007 FH ???? a voir 
+  int  iloop=0;
+  KN<bool> unvarexp(classoptm ? Op.optiexpK->sizevar() : 1);
+  if (Ku.number<1 && verbosity/100 && verbosity % 10 == 2) 
+     cout << "Element_Op P: copt = " << copt << " " << classoptm << endl;
+    assert(Op.MaxOp() <last_operatortype);
+  
+    
+  KN<bool> Dop(last_operatortype);
+  Op.DiffOp(Dop);  
+  int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+ //assert(lastop<=3);
+  RNMK_ fv(p,n,N,lastop); //  the value for basic fonction
+  RNMK_ fu(p+ (same ?0:n*N*lastop) ,m,M,lastop); //  the value for basic fonction
+
+  for (i=0;i< nx;i++) 
+    *pa++ = 0.; 
+  if (ie<0 )//&& B==0)
+    for (npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+        QuadraturePoint pi(FI[npi]);
+          R mes = B ? B->x : T.area;
+        R coef = mes *pi.a;
+        R2 Pt(pi);
+        pa =a;
+        Ku.BF(Dop,Pt,fu);
+	MeshPointStack(stack)->set(T(Pt),Pt,Kv);
+        if (classoptm) {
+	    if( oldopt) (*Op.optiexpK)(stack); // call old optim version 
+	    else Op.optiexpK->eval(stack,iloop++,unvarexp); // new optim version 
+	}
+        if (!same) Kv.BF(Dop,Pt,fv);      
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	    {  // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      BilinearOperator::K ll(*l);
+	      //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+	      long jcomp= ll.first.first.first,jop=ll.first.first.second;
+	      long icomp= ll.first.second.first,iop=ll.first.second.second;
+	      
+	      R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+	      if ( copt && Kv.number <1)
+		{
+		  R cc  =  GetAny<R>(ll.second.eval(stack));
+		  //cout << *(copt[il]) << " == " <<  cc << endl;
+		  if ( ccc != cc) { 
+		    cerr << cc << " != " << ccc << " => ";
+		    cerr << "Sorry error in Optimization (a) add:  int2d(Th,optimize=0)(...)" << endl;
+		    ExecError("In Optimized version "); }
+		}
+	      int fi=Kv.dfcbegin(icomp);
+	      int li=Kv.dfcend(icomp);
+	      int fj=Ku.dfcbegin(jcomp);
+	      int lj=Ku.dfcend(jcomp);
+	      fi=0,fj=0;
+	      li=n,lj=m;
+	      ccc *= coef;
+	      
+	      // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      for ( i=fi;  i<li;   i++ )  
+		{ 
+		  for ( j=fj;  j<lj;   j++ ) 
+		    { 		      
+		      R w_i =  fv(i,icomp,iop); 
+		      R w_j =  fu(j,jcomp,jop);		      
+		      mat(i,j) += ccc * w_i*w_j;
+		    }
+		}
+	    }
+      }
+  else if(B)
+  {  // int on isovalue ...
+      R2 PA(B[0]),PB(B[1]);
+      R2 A=T(PA),B=T(PB);
+      R2 E(A,B);
+      double le = sqrt((E,E));
+    //  cout << " xxxx "<< le << " "<< A << " " << B << endl;
+      if(le > 1e-15) // bofbof ????
+      for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+      {
+          pa =a;
+          QuadratureFormular1dPoint pi( FIb[npi]);
+          double coef = le*pi.a;
+          double sa=pi.x,sb=1-sa;
+          R2 Pt(PA*sa+PB*sb ); //
+          Ku.BF(Dop,Pt,fu);
+          if (!same) Kv.BF(Dop,Pt,fv);
+          // int label=-999999; // a passer en argument
+          MeshPointStack(stack)->set(T(Pt),Pt,Kv,-1,R2(E.y,-E.x)/le,-1);
+          if (classoptm) (*Op.optiexpK)(stack); // call optim version
+          int il=0;
+          for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	  {  // attention la fonction test donne la ligne
+              //  et la fonction test est en second
+              BilinearOperator::K ll(*l);
+              //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+              long jcomp= ll.first.first.first,jop=ll.first.first.second;
+              long icomp= ll.first.second.first,iop=ll.first.second.second;
+              
+              
+              R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+              if ( copt && Kv.number <1)
+	      {
+                  R cc  =  GetAny<R>(ll.second.eval(stack));
+                  //cout << *(copt[il]) << " == " <<  cc << endl;
+                  if ( ccc != cc) {
+                      cerr << cc << " != " << ccc << " => ";
+                      cerr << "Sorry error in Optimization (a) add:  int2d(Th,optimize=0)(...)" << endl;
+                      ExecError("In Optimized version "); }
+	      }
+              int fi=Kv.dfcbegin(icomp);
+              int li=Kv.dfcend(icomp);
+              int fj=Ku.dfcbegin(jcomp);
+              int lj=Ku.dfcend(jcomp);
+              ccc *= coef;
+              
+              // attention la fonction test donne la ligne
+              //  et la fonction test est en second      
+              
+              for ( i=fi;  i<li;   i++ )  
+	      { 
+		  for ( j=fj;  j<lj;   j++ ) 
+                  { 		      
+		      R w_i =  fv(i,icomp,iop); 
+		      R w_j =  fu(j,jcomp,jop);		      
+		      mat(i,j) += ccc * w_i*w_j;
+                  }
+	      }
+	  }
+      }
+  }
+  else // int on edge ie
+    for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+      {
+        pa =a;
+        QuadratureFormular1dPoint pi( FIb[npi]);
+        R2 E=T.Edge(ie);
+        double le = sqrt((E,E));
+        double coef = le*pi.a;
+        double sa=pi.x,sb=1-sa;
+        R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+          PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]);
+        R2 Pt(PA*sa+PB*sb ); //  
+        Ku.BF(Dop,Pt,fu);
+        if (!same) Kv.BF(Dop,Pt,fv);      
+        // int label=-999999; // a passer en argument 
+        MeshPointStack(stack)->set(T(Pt),Pt,Kv,label,R2(E.y,-E.x)/le,ie);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+	int il=0;
+	for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	  {  // attention la fonction test donne la ligne 
+	    //  et la fonction test est en second      
+	    BilinearOperator::K ll(*l);
+	    //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+	    long jcomp= ll.first.first.first,jop=ll.first.first.second;
+	    long icomp= ll.first.second.first,iop=ll.first.second.second;
+
+	    
+	    R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+	    if ( copt && Kv.number <1)
+	      {
+		R cc  =  GetAny<R>(ll.second.eval(stack));
+		//cout << *(copt[il]) << " == " <<  cc << endl;
+		if ( ccc != cc) { 
+		  cerr << cc << " != " << ccc << " => ";
+		  cerr << "Sorry error in Optimization (a) add:  int2d(Th,optimize=0)(...)" << endl;
+		  ExecError("In Optimized version "); }
+	      }
+	    int fi=Kv.dfcbegin(icomp);
+	    int li=Kv.dfcend(icomp);
+	    int fj=Ku.dfcbegin(jcomp);
+	    int lj=Ku.dfcend(jcomp);
+	    ccc *= coef;
+	    
+	    // attention la fonction test donne la ligne 
+	    //  et la fonction test est en second      
+	    
+	    for ( i=fi;  i<li;   i++ )  
+	      { 
+		  for ( j=fj;  j<lj;   j++ ) 
+		    { 		      
+		      R w_i =  fv(i,icomp,iop); 
+		      R w_j =  fu(j,jcomp,jop);		      
+		      mat(i,j) += ccc * w_i*w_j;
+		    }
+	      }
+	  }
+	  
+	/*        
+        for ( i=0;  i<n;   i++ )  
+         // if (onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // juste the df on edge bofbof generaly wrong FH dec 2003
+            { 
+              RNM_ wi(fv(i,'.','.'));       
+              for ( j=0;  j<m;   j++,pa++ ) 
+                { 
+                  RNM_ wj(fu(j,'.','.'));
+                  int il=0;
+                  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                   // if (onWhatIsEdge[ie][Kv.DFOnWhat(j)]) // juste the df on edge bofbof generaly wrong FH dec 2003
+                      {       
+                        BilinearOperator::K ll(*l);
+                        pair<int,int> jj(ll.first.first),ii(ll.first.second);
+                        
+                        double w_i =  wi(ii.first,ii.second); 
+                        double w_j =  wj(jj.first,jj.second);
+                       // R ccc = GetAny<R>(ll.second.eval(stack));
+                       
+                    R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+                if ( copt && Kv.number <1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( ccc != cc) { 
+                        cerr << cc << " != " << ccc << " => ";
+                       cerr << "Sorry error in Optimization (b) add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                         *pa += coef * ccc * w_i*w_j;
+                      }
+                }
+            } 
+         // else pa += m;  FH dec 2003
+	 */
+      }
+  
+  
+  /*  pa=a;
+      if (Ku.Vh.Th(T) >=0 ) {
+      cout <<endl  << " Triangle " << Ku.Vh.Th(T) << " =  "<<  T[0] << ", " << T[1] << ", " << T[2] << " " << nx << endl;
+      for (int i=0;i<n;i++)
+      {
+      cout << setw(2) << i << setw(4) << mat.ni[i] << " :";
+      for (int j=0;j<m;j++)
+      cout << setw(5)  << (*pa++) << " ";
+      cout << endl;
+      } } 
+  */ 
+  *MeshPointStack(stack) = mp;
+  }  
+  
+  
+  
+ template<class R>
+ void  Element_Op(MatriceElementaireSymetrique<R,FESpace3> & mat,const FElement3 & Ku,double * p,int ie,int label, void * vstack,R3 *B)
+  {
+  //    ffassert(B==0);
+      Stack stack=pvoid2Stack(vstack);
+   typedef FESpace3 FESpace;
+   typedef typename FESpace3::Mesh Mesh;
+   typedef Mesh *pmesh ;
+   typedef typename Mesh::Element Element;
+    MeshPoint mp= *MeshPointStack(stack);
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    const Element & T  = Ku.T;
+
+    const GQuadratureFormular<R3> & FI = mat.FIT;
+    const GQuadratureFormular<R2> & FIb = mat.FIE;
+
+    long npi;
+    R *a=mat.a;
+    R *pa=a;
+    long i,j;
+    long n= mat.n,m=mat.m,nx=n*(m+1)/2;
+    long N= Ku.N;
+    
+    assert(mat.bilinearform);
+    
+    const Opera &Op(*mat.bilinearform);
+    bool classoptm = copt && Op.optiexpK;
+    // assert(  (copt !=0) ||  (Op.where_in_stack_opt.size() !=0) );
+    int lastop;
+    What_d Dop = Op.DiffOp(lastop);
+
+    if (Ku.number<1  && verbosity/100 && verbosity % 10 == 2 ) 
+      cout << "Element_Op S 3d: copt = " << copt << " " << classoptm << " lastop = "<< lastop << " Dop " << Dop << endl;
+    assert(Op.MaxOp() <last_operatortype);
+    
+    RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+    
+    
+    pa =a;
+    for (i=0;i< nx;i++) 
+      *pa++ = 0.; 
+    
+    if (ie<0)   
+      for (npi=0;npi<FI.n;npi++) // loop on the integration point
+        {
+          GQuadraturePoint<R3> pi(FI[npi]);
+          double coef = T.mesure()*pi.a;
+	  //R3 Pt(pi);
+          pa =a;
+          Ku.BF(Dop,pi,fu);
+          MeshPointStack(stack)->set(T(pi),pi,Ku);
+          if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	    {  // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      BilinearOperator::K ll(*l);
+	      //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+	      long jcomp= ll.first.first.first,jop=ll.first.first.second;
+	      long icomp= ll.first.second.first,iop=ll.first.second.second;
+
+              
+	      R c = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+	      if ( copt && Ku.number <1)
+		{
+		  R cc  =  GetAny<R>(ll.second.eval(stack));
+		  // cout << *(copt[il]) << " == " <<  cc << endl;
+		  if ( c != cc) { 
+		    cerr << c << " != " << cc << " => ";
+			    cerr << "Sorry error in Optimization (c) add:  int2d(Th,optimize=0)(...)" << endl;
+			    ExecError("In Optimized version "); }
+		}
+	      c *= coef ;
+	      long fi=Ku.dfcbegin(icomp);
+	      long li=Ku.dfcend(icomp);
+	      long fj=Ku.dfcbegin(jcomp);
+	      long lj=Ku.dfcend(jcomp);
+
+	      for ( i=fi;  i<li;   i++ )  
+		for ( j=fj;  j<min(lj,i+1);  j++,pa++ ) // 
+		  {
+		    R w_i =  fu(i,icomp,iop); 
+		    R w_j =  fu(j,jcomp,jop);		      
+		    
+		    mat(i,j)  +=  c * w_i*w_j;
+
+		    /*
+		      if (Ku.Vh.Th(T) < 1 && npi < 1 && i < 1 && j < 1 ) 
+		      cout <<" + " << c << " (" <<coef << " " << w_i << " " << w_j << " " << jj.first << " " << jj.second << ") " ;
+		    */
+		  }
+              
+            }
+          
+        } 
+    else if(B)
+        {  // int on leveset
+            int np = ie-10; //= (B[0].x == B[3].x ) && (B[0].y == B[3].y ) && (B[0].z == B[3].z ) ? 3 : 4;
+            if(verbosity>999) cout << "    Ass mat pleine /"<< np << endl;
+            assert( np==3 || np==4);
+            // XXXXXXX
+            double epsmes3=T.mesure()*T.mesure()*1e-18;
+            R3 PP[4];
+            double l[3];
+            for(int i=0; i< np; ++i)
+                PP[i]= T(B[i]);
+            
+            for( int i =0; i+1 < np; i+=2)
+            { // 0,1,, a and 2,3,0.
+                int i0=i,i1=i+1,i2=(i+2)%np;
+                R3 NN= R3(PP[i0],PP[i1])^R3(PP[i0],PP[i2]);
+                double mes2 = (NN,NN);
+                double mes = sqrt(mes2);
+                
+                if(mes2*mes <epsmes3) continue; //  too small
+                NN /= mes;
+                mes *= 0.5;
+                if(verbosity>999)
+                    cout << " --int on leveset3d " << np << " " << mes << " " << i0<<i1<<i2 <<endl;
+                double asum=0;
+                for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+                {
+                    GQuadraturePoint<R2>  pi( FIb[npi]);
+                    // cout << " %% " << npi << " " << pi.a << " " << pi.x << " " << pi.y << endl;
+                    asum+= pi.a;
+                    pi.toBary(l);
+                    R3 Pt( l[0]*B[i0]+l[1]*B[i1]+l[2]*B[i2]); //
+                    double coef = mes*pi.a; // correction 0.5 050109 FH
+                    Ku.BF(Dop,Pt,fu);
+                     MeshPointStack(stack)->set(T(Pt),Pt,Ku,label,NN,ie);
+                    if (classoptm) (*Op.optiexpK)(stack); // call optim version
+                    
+                    pa=a;
+                    int il=0;
+                    for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                    {  // attention la fonction test donne la ligne
+                        //  et la fonction test est en second
+                        BilinearOperator::K ll(*l);
+                        //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+                        long jcomp= ll.first.first.first,jop=ll.first.first.second;
+                        long icomp= ll.first.second.first,iop=ll.first.second.second;
+                        
+                        R c = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+                        if ( copt && Ku.number <1)
+                        {
+                            R cc  =  GetAny<R>(ll.second.eval(stack));
+                            // cout << *(copt[il]) << " == " <<  cc << endl;
+                            if ( c != cc) {
+                                cerr << c << " != " << cc << " => ";
+                                cerr << "Sorry error in Optimization (c) add:  int2d(Th,optimize=0)(...)" << endl;
+                                ExecError("In Optimized version "); }
+                        }
+                        c *= coef ;
+                        long fi=Ku.dfcbegin(icomp);
+                        long li=Ku.dfcend(icomp);
+                        long  fj=Ku.dfcbegin(jcomp);
+                        long  lj=Ku.dfcend(jcomp);
+                        
+                        for (long i=fi;  i<li;   i++ )
+                            for (long j=fj;  j<min(lj,i+1);  j++,pa++ ) //
+                            {
+                                R w_i =  fu(i,icomp,iop); 
+                                R w_j =  fu(j,jcomp,jop);		      
+                                
+                                mat(i,j)  +=  c * w_i*w_j;
+                                
+                                /*
+                                 if (Ku.Vh.Th(T) < 1 && npi < 1 && i < 1 && j < 1 ) 
+                                 cout <<" + " << c << " (" <<coef << " " << w_i << " " << w_j << " " << jj.first << " " << jj.second << ") " ;
+                                 */
+                            }
+                        
+                    }
+                    
+                    
+                    
+                }
+                
+                
+            }
+            
+        }// end int level set ...
+      else
+        // int on edge ie
+      for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+        {
+          
+          pa =a;
+          GQuadraturePoint<R2> pi( FIb[npi]);
+	  R3 NN= T.N(ie);
+	  double mes=NN.norme();
+	  NN/=mes;
+	  mes *=0.5;	
+	  double coef = mes*pi.a; // correction 0.5 050109 FH
+	  R3 Pt(T.PBord(ie,pi));
+          Ku.BF(Dop,Pt,fu);
+          // int label=-999999; // a passer en argument 
+          MeshPointStack(stack)->set(T(Pt),Pt,Ku,label,NN,ie);
+          if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	    {  // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      BilinearOperator::K ll(*l);
+	      //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+	      long jcomp= ll.first.first.first,jop=ll.first.first.second;
+	      long icomp= ll.first.second.first,iop=ll.first.second.second;
+              
+	      R c = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+	      if ( copt && Ku.number <1)
+		{
+		  R cc  =  GetAny<R>(ll.second.eval(stack));
+		  // cout << *(copt[il]) << " == " <<  cc << endl;
+		  if ( c != cc) { 
+		    cerr << c << " != " << cc << " => ";
+			    cerr << "Sorry error in Optimization (c) add:  int2d(Th,optimize=0)(...)" << endl;
+			    ExecError("In Optimized version "); }
+		}
+	      c *= coef ;
+	      long fi=Ku.dfcbegin(icomp);
+	      long li=Ku.dfcend(icomp);
+	      long  fj=Ku.dfcbegin(jcomp);
+	      long  lj=Ku.dfcend(jcomp);
+
+	      for (long i=fi;  i<li;   i++ )
+		for (long j=fj;  j<min(lj,i+1);  j++,pa++ ) //
+		  {
+		    R w_i =  fu(i,icomp,iop); 
+		    R w_j =  fu(j,jcomp,jop);		      
+		    
+		    mat(i,j)  +=  c * w_i*w_j;
+		    
+		    /*
+		      if (Ku.Vh.Th(T) < 1 && npi < 1 && i < 1 && j < 1 ) 
+		      cout <<" + " << c << " (" <<coef << " " << w_i << " " << w_j << " " << jj.first << " " << jj.second << ") " ;
+		    */
+		  }
+              
+            }
+          
+          
+        }
+    
+    
+    pa=a;
+    if (Ku.Vh.Th(T) <0 & verbosity>100) {
+      cout <<endl  << " Tet " << Ku.Vh.Th(T) << " =  "<<  T << "  nx= " << nx << endl;
+      for (int i=0;i<n;i++)
+	{
+	  cout << setw(2) << i << setw(4) << mat.ni[i] << " :";
+	  for (int j=0;j<=i;j++)
+	    cout << setw(5)  << (*pa++) << " ";
+	  cout << endl;
+	} } 
+    /*
+    pa=a;
+    for (int i=0;i<n;i++)
+      cout << mat.ni[i] << " " ;
+    for (int i=0;i<n;i++)
+      for (int j=0;j<n;j++,pa++)
+	if ( mat.ni[i]==150 && mat.nj[j] == 150)
+	  cout << "a_150,150 = "<< *pa ;
+    cout << endl; 
+    */
+    
+    *MeshPointStack(stack) = mp;
+
+  }
+
+  // xxxxxxxxxxxxxxxxx  modif a faire   
+ template<class R>
+ void  Element_Op(MatriceElementaireSymetrique<R,FESpace> & mat,const FElement & Ku,double * p,int ie,int label, void * vstack,R2*B)
+  {
+    Stack stack=pvoid2Stack(vstack);
+    MeshPoint mp= *MeshPointStack(stack);
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    const Triangle & T  = Ku.T;
+    //  const QuadratureFormular & FI = QuadratureFormular_T_2;
+    //  const QuadratureFormular1d & FIb = QF_GaussLegendre2;
+    const QuadratureFormular & FI = mat.FIT;
+    const QuadratureFormular1d & FIb = mat.FIE;
+    long npi;
+    R *a=mat.a;
+    R *pa=a;
+    long i,j;
+    long n= mat.n,m=mat.m,nx=n*(m+1)/2;
+    long N= Ku.N;
+    //long M=N;
+    // bool show = Ku.Vh.Th(T)==0;
+    //    char * xxx[] ={" u"," v"," p"," q"," r"};
+    //char * xxxx[] ={" u'"," v'"," p'"," q'"," r'"};
+    //char * yyy[] ={" ","_x ","_y "};
+    
+    
+    throwassert(mat.bilinearform);
+    
+    const Opera &Op(*mat.bilinearform);
+    bool classoptm = copt && Op.optiexpK;
+   // assert(  (copt !=0) ||  (Op.where_in_stack_opt.size() !=0) );
+  if (Ku.number<1  && verbosity/100 && verbosity % 10 == 2 ) 
+     cout << "Element_Op S: copt = " << copt << " " << classoptm << endl;
+    assert(Op.MaxOp() <last_operatortype);
+
+
+    KN<bool> Dop(last_operatortype);
+    Op.DiffOp(Dop);  
+    int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+   // assert(lastop<=3);
+
+    RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+    
+    pa =a;
+    for (i=0;i< nx;i++) 
+      *pa++ = 0.; 
+    
+    if (ie<0)   
+      for (npi=0;npi<FI.n;npi++) // loop on the integration point
+        {
+          QuadraturePoint pi(FI[npi]);
+          double mes= B ? B->x :T.area;
+          double coef = mes*pi.a;
+          R2 Pt(pi);
+          pa =a;
+          Ku.BF(Dop,Pt,fu);
+          MeshPointStack(stack)->set(T(pi),pi,Ku);
+          if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	    {  // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      BilinearOperator::K ll(*l);
+	      //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+	      long jcomp= ll.first.first.first,jop=ll.first.first.second;
+	      long icomp= ll.first.second.first,iop=ll.first.second.second;
+              
+	      R c = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+	      if ( copt && Ku.number <1)
+		{
+		  R cc  =  GetAny<R>(ll.second.eval(stack));
+		  // cout << *(copt[il]) << " == " <<  cc << endl;
+		  if ( c != cc) { 
+		    cerr << c << " != " << cc << " => ";
+			    cerr << "Sorry error in Optimization (c) add:  int2d(Th,optimize=0)(...)" << endl;
+			    ExecError("In Optimized version "); }
+		}
+	      c *= coef ;
+	      long fi=Ku.dfcbegin(icomp);
+	      long li=Ku.dfcend(icomp);
+	      long fj=Ku.dfcbegin(jcomp);
+	      long lj=Ku.dfcend(jcomp);
+	      if (verbosity>10 && Ku.Vh.Th(T) < 1 && npi < 1)
+		cout << " ic "<< icomp << fi<< " "<< lj << " "<< " c "<< jcomp << " " <<fj << " "<< lj << endl; 
+	      for ( i=fi;  i<li;   i++ )  
+		for ( j=fj;  j<min(lj,i+1);  j++ ) // 
+		  {
+		    R w_i =  fu(i,icomp,iop); 
+		    R w_j =  fu(j,jcomp,jop);		      
+		    
+		    mat(i,j)  +=  c * w_i*w_j;
+
+		  }
+              
+            }
+          
+	  /*
+          for ( i=0;  i<n;   i++ )  
+            { 
+              RNM_ wi(fu(i,'.','.'));
+              //    if (Ku.Vh.Th(T) < 1) cout << i <<" " <<Pt<< "wi =" << wi ;
+              for ( j=0;  j<=i;  j++,pa++ ) // 
+                {
+                  
+                  RNM_ wj(fu(j,'.','.'));
+                  //   if (Ku.Vh.Th(T) < 1) cout << j <<" " <<Pt<< "wj =" << wj ;
+                  int il=0;
+                  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                    {       
+                      const  BilinearOperator::K & ll(*l);
+                      pair<int,int> ii(ll.first.first),jj(ll.first.second);
+                      double w_i =  wi(ii.first,ii.second);
+                      double w_j =  wj(jj.first,jj.second);
+		      
+                      R c = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+                if ( copt && Ku.number <1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                    // cout << *(copt[il]) << " == " <<  cc << endl;
+                     if ( c != cc) { 
+                       cerr << c << " != " << cc << " => ";
+                       cerr << "Sorry error in Optimization (c) add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                      
+                      *pa += coef * c * w_i*w_j;
+		      }
+		      }
+		      
+		      }*/
+          
+        } 
+    else if(B)
+    {
+        R2 PA(B[0]),PB(B[0]);
+        R2 A=T(PA),B=T(PB);
+        R2 E(A,B);
+        double le = sqrt((E,E));
+         if(le > 1e-15)
+        for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+        {
+            
+            pa =a;
+            QuadratureFormular1dPoint pi( FIb[npi]);
+           
+            double coef = le*pi.a;
+            double sa=pi.x,sb=1-sa;
+            R2 Pt(PA*sa+PB*sb ); //
+            Ku.BF(Dop,Pt,fu);
+            // int label=-999999; // a passer en argument
+            MeshPointStack(stack)->set(T(Pt),Pt,Ku,0,R2(E.y,-E.x)/le,0);
+            if (classoptm) (*Op.optiexpK)(stack); // call optim version
+            
+            int il=0;
+            for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	    {  // attention la fonction test donne la ligne
+                //  et la fonction test est en second
+                BilinearOperator::K ll(*l);
+                //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+                long jcomp= ll.first.first.first,jop=ll.first.first.second;
+                long icomp= ll.first.second.first,iop=ll.first.second.second;
+                
+                R c = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+                if ( copt && Ku.number <1)
+		{
+                    R cc  =  GetAny<R>(ll.second.eval(stack));
+                    // cout << *(copt[il]) << " == " <<  cc << endl;
+                    if ( c != cc) {
+                        cerr << c << " != " << cc << " => ";
+                        cerr << "Sorry error in Optimization (c) add:  int2d(Th,optimize=0)(...)" << endl;
+                        ExecError("In Optimized version "); }
+		}
+                c *= coef ;
+                long fi=Ku.dfcbegin(icomp);
+                long li=Ku.dfcend(icomp);
+                long fj=Ku.dfcbegin(jcomp);
+                long lj=Ku.dfcend(jcomp);
+                
+                for ( i=fi;  i<li;   i++ )
+                    for ( j=fj;  j<min(lj,i+1);  j++,pa++ ) //
+                    {
+                        R w_i =  fu(i,icomp,iop);
+                        R w_j =  fu(j,jcomp,jop);		      
+                        
+                        mat(i,j)  +=  c * w_i*w_j;
+                        /*
+                         if (Ku.Vh.Th(T) < 1 && npi < 1 && i < 1 && j < 1 ) 
+                         cout <<" + " << c << " (" <<coef << " " << w_i << " " << w_j << " " << jj.first << " " << jj.second << ") " ;
+                         */
+                    }
+                
+            }
+        }
+    }
+    else    // int on edge ie
+      for (npi=0;npi<FIb.n;npi++) // loop on the integration point
+        {
+          
+          pa =a;
+          QuadratureFormular1dPoint pi( FIb[npi]);
+          R2 E=T.Edge(ie);
+          double le = sqrt((E,E));
+          double coef = le*pi.a;
+          double sa=pi.x,sb=1-sa;
+          R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+            PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]);
+          R2 Pt(PA*sa+PB*sb ); //  
+          Ku.BF(Dop,Pt,fu);
+          // int label=-999999; // a passer en argument 
+          MeshPointStack(stack)->set(T(Pt),Pt,Ku,label,R2(E.y,-E.x)/le,ie);
+          if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+
+	  int il=0;
+	  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+	    {  // attention la fonction test donne la ligne 
+	      //  et la fonction test est en second      
+	      BilinearOperator::K ll(*l);
+	      //	      pair<int,int> jj(ll.first.first),ii(ll.first.second);
+	      long jcomp= ll.first.first.first,jop=ll.first.first.second;
+	      long icomp= ll.first.second.first,iop=ll.first.second.second;
+              
+	      R c = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+	      if ( copt && Ku.number <1)
+		{
+		  R cc  =  GetAny<R>(ll.second.eval(stack));
+		  // cout << *(copt[il]) << " == " <<  cc << endl;
+		  if ( c != cc) { 
+		    cerr << c << " != " << cc << " => ";
+			    cerr << "Sorry error in Optimization (c) add:  int2d(Th,optimize=0)(...)" << endl;
+			    ExecError("In Optimized version "); }
+		}
+	      c *= coef ;
+	      long fi=Ku.dfcbegin(icomp);
+	      long li=Ku.dfcend(icomp);
+	      long fj=Ku.dfcbegin(jcomp);
+	      long lj=Ku.dfcend(jcomp);
+
+	      for ( i=fi;  i<li;   i++ )  
+		for ( j=fj;  j<min(lj,i+1);  j++,pa++ ) // 
+		  {
+		    R w_i =  fu(i,icomp,iop); 
+		    R w_j =  fu(j,jcomp,jop);		      
+		    
+		    mat(i,j)  +=  c * w_i*w_j;
+		    /*
+		      if (Ku.Vh.Th(T) < 1 && npi < 1 && i < 1 && j < 1 ) 
+		      cout <<" + " << c << " (" <<coef << " " << w_i << " " << w_j << " " << jj.first << " " << jj.second << ") " ;
+		    */
+		  }
+              
+            }
+                    
+          /*
+          for ( i=0;  i<n;   i++ )  
+           // if ( onWhatIsEdge[ie][Ku.DFOnWhat(i)]) // generaly wrong FH dec 2003
+              { 
+                RNM_ wi(fu(i,'.','.'));     
+                for ( j=0;  j<=i;   j++,pa++ ) 
+                  { 
+                    RNM_ wj(fu(j,'.','.'));
+                    int il=0;
+                    for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                     // if (onWhatIsEdge[ie][Ku.DFOnWhat(j)]) // generaly wrong FH dec 2003
+                        {       
+                          BilinearOperator::K ll(*l);
+                          pair<int,int> ii(ll.first.first),jj(ll.first.second);
+                          double w_i =  wi(ii.first,ii.second); 
+                          double w_j =  wj(jj.first,jj.second);
+                         // R ccc = GetAny<R>(ll.second.eval(stack));
+                      R ccc = copt ? *(copt[il]): GetAny<R>(ll.second.eval(stack));
+                if ( copt && Ku.number <1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( ccc != cc) { 
+                       cerr << ccc << " != " << cc << ", xy = "<< T(Pt) << " => ";
+                       cerr << "Sorry error in Optimization (d)  add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                          
+                          *pa += coef * ccc * w_i*w_j;
+                        }
+                  }
+              } //else pa+= i+1;
+	  */
+        }
+    
+    /*  
+    pa=a;
+    if (Ku.Vh.Th(T) <=0 ) {
+      cout <<endl  << " Triangle " << Ku.Vh.Th(T) << " =  "<<  T[0] << ", " << T[1] << ", " << T[2] << " " << nx << endl;
+      for (int i=0;i<n;i++)
+	{
+	  cout << setw(2) << i << setw(4) << mat.ni[i] << " :";
+	  for (int j=0;j<=i;j++)
+	    cout << setw(5)  << (*pa++) << " ";
+	  cout << endl;
+	} } 
+    pa=a;
+        for (int i=0;i<n;i++)
+      cout << mat.ni[i] << " " ;
+    for (int i=0;i<n;i++)
+      for (int j=0;j<n;j++,pa++)
+         if ( mat.ni[i]==150 && mat.nj[j] == 150)
+         cout << "a_150,150 = "<< *pa ;
+         cout << endl; 
+    */
+    
+    *MeshPointStack(stack) = mp;
+    
+  }    
+  
+  
+  
+  // #pragma optimization_level 0
+ template<class R>
+  void  Element_rhs(const FElement & Kv,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                    const QuadratureFormular & FI = QuadratureFormular_T_2)
+  {
+    Stack stack=pvoid2Stack(vstack);
+    MeshPoint mp=*MeshPointStack(stack) ;
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    const Triangle & T  = Kv.T;
+    //  const QuadratureFormular & FI = QuadratureFormular_T_2;
+    //  const QuadratureFormular & FI = QuadratureFormular_T_2;
+    long npi;
+    long i,n=Kv.NbDoF(),N=Kv.N;
+    
+    //  bool show = Kv.Vh.Th(T)==0;
+  //  char * xxx[] ={" u"," v,"," p"," q"," r"};
+   // char * xxxx[] ={" u'"," v',"," p'"," q'"," r'"};
+   // char * yyy[] ={" ","_x ","_y "};
+    
+    bool classoptm = copt && Op.optiexpK;
+   // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+    if (Kv.number<1  && verbosity/100 && verbosity % 10 == 2) 
+     cout << "Element_rhs S0: copt = " << copt << " " << classoptm << endl;
+ 
+
+    KN<bool> Dop(last_operatortype);
+    Op.DiffOp(Dop);  
+    int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+    assert(Op.MaxOp() <last_operatortype);
+    
+  //  assert(lastop<=3);
+
+    
+    RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+    
+    for (npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+        QuadraturePoint pi(FI[npi]);
+        double coef = T.area*pi.a;
+        R2 Pt(pi);
+        Kv.BF(Dop,Pt,fu);
+        MeshPointStack(stack)->set(T(Pt),Pt,Kv);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+        for ( i=0;  i<n;   i++ )  
+          { 
+            RNM_ wi(fu(i,'.','.'));
+            int il=0;
+            for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+              {       
+                LOperaD::K ll(*l);
+                pair<int,int> ii(ll.first);
+                double w_i =  wi(ii.first,ii.second);
+                //copt=0;
+                R c = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack)); //GetAny<double>(ll.second.eval(stack));
+                if ( copt && Kv.number <1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( c != cc) { 
+                       cerr << c << " != " << cc << " => ";
+                       cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                //if (Kv.number<5) cout << il<< " " << i << "  c== " <<  c << endl;
+                R a = coef * c * w_i;
+                B[Kv(i)] += a;
+              }
+          }
+        
+        
+      }  
+    *MeshPointStack(stack) = mp;
+    
+    
+  }  
+
+  // 3D
+ template<class R>
+  void  Element_rhs(const FElement3 & Kv,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                    const GQuadratureFormular<R3> & FI = QuadratureFormular_Tet_2)
+  {
+    Stack stack=pvoid2Stack(vstack);
+    typedef  FElement3::Element Element;
+    MeshPoint mp=*MeshPointStack(stack) ;
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    const Element & T  = Kv.T;
+    //  const QuadratureFormular & FI = QuadratureFormular_T_2;
+    //  const QuadratureFormular & FI = QuadratureFormular_T_2;
+    long npi;
+    long i,n=Kv.NbDoF(),N=Kv.N;
+    
+     
+    bool classoptm = copt && Op.optiexpK;
+   // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+    if (Kv.number<1  && verbosity/100 && verbosity % 10 == 2) 
+     cout << "Element_rhs S0: copt = " << copt << " " << classoptm << endl;
+
+
+    int lastop;
+    What_d Dop = Op.DiffOp(lastop);
+    assert(Op.MaxOp() <last_operatortype);
+    
+  //  assert(lastop<=3);
+
+    
+    RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+    
+    for (npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+        GQuadraturePoint<R3> pi(FI[npi]);
+        double coef = T.mesure()*pi.a;
+        R3 Pt(pi);
+        Kv.BF(Dop,Pt,fu);
+        MeshPointStack(stack)->set(T(Pt),Pt,Kv);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+        for ( i=0;  i<n;   i++ )  
+          { 
+            RNM_ wi(fu(i,'.','.'));
+            int il=0;
+            for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+              {       
+                LOperaD::K ll(*l);
+                pair<int,int> ii(ll.first);
+                double w_i =  wi(ii.first,ii.second);
+                //copt=0;
+                R c = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack)); //GetAny<double>(ll.second.eval(stack));
+                if ( copt && Kv.number <1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( c != cc) { 
+                       cerr << c << " != " << cc << " => ";
+                       cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                //if (Kv.number<5) cout << il<< " " << i << "  c== " <<  c << endl;
+                R a = coef * c * w_i;
+                B[Kv(i)] += a;
+              }
+          }
+        
+        
+      }  
+    *MeshPointStack(stack) = mp;
+    
+    
+  }  
+  // fin 3d   
+  // #pragma optimization_level 0
+  // 3d
+ template<class R>
+ void  Element_rhs(const  Mesh3 & ThI,const Mesh3::Element & KI,
+                    const FESpace3 & Vh,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+		   const GQuadratureFormular<R3> & FI)
+ {
+     Stack stack=pvoid2Stack(vstack);
+   // AFAIRE("Element_rhs 3d diff meshes");
+     static int count=0;
+     if(count++<1)
+     {
+         cout << "Warning:  Element_rhs 3 3d diff meshes in test (FH) " << endl;
+         cout << "--------------------------------------------------- " << endl;
+     }
+     MeshPoint mp=*MeshPointStack(stack) ;
+     R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+     //    int maxd = Op.MaxOp();
+     //    assert(maxd<last_operatortype);
+     const Tet * Kp=0;
+     
+     bool classoptm = copt && Op.optiexpK;
+     // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+     if (ThI(KI)<1 && verbosity/100 && verbosity % 10 == 2)
+         
+         cout << "Element_rhs 3d  3: copt = " << copt << " " << classoptm << endl;
+     
+     assert(Op.MaxOp() <last_operatortype);
+     //
+     int lastop=0;
+     lastop = 0;
+     What_d Dop = Op.DiffOp(lastop);
+     assert(Op.MaxOp() <last_operatortype);
+     
+     // assert(lastop<=3);
+     
+     for (long npi=0;npi<FI.n;npi++) // loop on the integration point
+     {
+         GQuadraturePoint<R3> pi(FI[npi]);
+         R3 PI(KI(pi));      
+         double coef = KI.mesure()*pi.a;
+         MeshPointStack(stack)->set(ThI,PI,pi,KI,KI.lab);
+         if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+         bool outside;
+         R3 Pt;
+         const Tet & K  = *Vh.Th.Find(PI,Pt,outside,Kp);
+         if ( ! outside) 
+         {
+             const  FElement3  Kv= Vh[K];
+             long i,n=Kv.NbDoF(),N=Kv.N;
+             RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+             Kv.BF(Dop,Pt,fu);
+             
+             for ( i=0;  i<n;   i++ )  
+             { 
+                 RNM_ wi(fu(i,'.','.'));
+                 int il=0;
+                 for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                 {       
+                     LOperaD::K ll(*l);
+                     pair<int,int> ii(ll.first);
+                     
+                     double w_i =  wi(ii.first,ii.second);
+                     
+                     R c = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));;//GetAny<double>(ll.second.eval(stack));
+                     if ( copt && ThI(KI) <1)
+                     {
+                         R cc  =  GetAny<R>(ll.second.eval(stack));
+                         if ( c != cc) { 
+                             cerr << c << " != " << cc << " => ";
+                             cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                             ExecError("In Optimized version "); }
+                     }
+                     
+                     R a = coef * c * w_i;
+                     B[Kv(i)] += a;
+                 }
+             }
+         }
+         Kp = & K; 
+     }  
+     *MeshPointStack(stack) = mp;
+     
+    
+}
+  //
+ template<class R>
+  void  Element_rhs(const  Mesh & ThI,const Triangle & KI,
+                    const FESpace & Vh,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                    const QuadratureFormular & FI = QuadratureFormular_T_2)
+  {
+   Stack stack=pvoid2Stack(vstack);
+    MeshPoint mp=*MeshPointStack(stack) ;
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+//    int maxd = Op.MaxOp();
+//    assert(maxd<last_operatortype);
+    const Triangle * Kp=0;
+
+    bool classoptm = copt && Op.optiexpK;
+   // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+    if (ThI(KI)<1 && verbosity/100 && verbosity % 10 == 2)
+
+     cout << "Element_rhs 3: copt = " << copt << " " << classoptm << endl;
+
+    KN<bool> Dop(last_operatortype);
+    Op.DiffOp(Dop);  
+    int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+    assert(Op.MaxOp() <last_operatortype);
+
+   // assert(lastop<=3);
+      
+    for (long npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+        QuadraturePoint pi(FI[npi]);
+        R2 PI(KI(pi));      
+        double coef = KI.area*pi.a;
+        MeshPointStack(stack)->set(ThI,PI,pi,KI,KI.lab);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version 
+        bool outside;
+        R2 Pt;
+        const Triangle & K  = *Vh.Th.Find(PI,Pt,outside,Kp);
+        if ( ! outside) 
+          {
+            const  FElement  Kv= Vh[K];
+            long i,n=Kv.NbDoF(),N=Kv.N;
+            RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+            Kv.BF(Dop,Pt,fu);
+            
+            for ( i=0;  i<n;   i++ )  
+              { 
+                RNM_ wi(fu(i,'.','.'));
+                int il=0;
+                for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                  {       
+                    LOperaD::K ll(*l);
+                    pair<int,int> ii(ll.first);
+                    
+                    double w_i =  wi(ii.first,ii.second);
+                    
+                    R c = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));;//GetAny<double>(ll.second.eval(stack));
+                if ( copt && ThI(KI) <1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( c != cc) { 
+                       cerr << c << " != " << cc << " => ";
+                       cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                    
+                    R a = coef * c * w_i;
+                    B[Kv(i)] += a;
+                  }
+              }
+          }
+        Kp = & K; 
+      }  
+    *MeshPointStack(stack) = mp;
+    
+    
+  }  
+  // 3d 
+  template<class R>
+  void  Element_rhs(const FElement3 & Kv,int ie,int label,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                    const QuadratureFormular & FI ,bool alledges=false)
+  {
+    //   AFAIRE("Element_rhs on border");
+    Stack stack=pvoid2Stack(vstack);
+    typedef  FElement3::Element Element;
+    MeshPoint mp=*MeshPointStack(stack) ;
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    const Element & T  = Kv.T;
+    long npi;
+    long i,n=Kv.NbDoF(),N=Kv.N;
+    
+    bool classoptm = copt && Op.optiexpK;
+   // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+    if (Kv.number<1 && verbosity/100 && verbosity % 10 == 2) 
+     cout << "Element_rhs 3d S: copt = " << copt << " " << classoptm << endl;
+    int lastop;
+    What_d Dop = Op.DiffOp(lastop);
+
+    assert(Op.MaxOp() <last_operatortype);
+   // assert(lastop<=3);
+
+    RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+    
+    for (npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+         GQuadraturePoint<R2> pi( FI[npi]);
+	R3 NN=T.N(ie);
+	double le= NN.norme();
+	NN /= le;
+        double coef = le*pi.a*0.5;// correction 050109 FH
+        R3 Pt(T.PBord(ie,pi));
+      //  
+        Kv.BF(Dop,Pt,fu);
+        MeshPointStack(stack)->set(T(Pt),Pt,Kv,label,NN,ie);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version         
+        
+        for ( i=0;  i<n;   i++ )  
+         // if (alledges || onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // bofbof faux si il y a des derives ..
+            { 
+              RNM_ wi(fu(i,'.','.'));
+              int il=0;
+              for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                {       
+                  LOperaD::K ll(*l);
+                  pair<int,int> ii(ll.first);
+                  double w_i =  wi(ii.first,ii.second);
+                  R c =copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+		  // FFCS - removing what is probably a small glitch
+                if ( copt && Kv.number<1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( c != cc) { 
+			 cerr << c << " =! " << cc << endl;
+                       cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                  
+                  
+                  //= GetAny<double>(ll.second.eval(stack));
+                 
+                  B[Kv(i)] += coef * c * w_i;
+                }
+            }
+        
+        
+      }  
+    *MeshPointStack(stack) = mp;
+    
+  }
+    // 3d isoline ... levelset ...
+    template<class R>
+    void  Element_rhs(const FElement3 & Kv,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                      const QuadratureFormular & FI ,int np, R3 *Q)
+    {
+        //   AFAIRE("Element_rhs on border");
+        Stack stack=pvoid2Stack(vstack);
+        typedef  FElement3::Element Element;
+        
+        MeshPoint mp=*MeshPointStack(stack) ;
+        R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+        const Element & K  = Kv.T;
+        const Mesh3 & Th= Kv.Vh.Th;
+        double epsmes3=K.mesure()*K.mesure()*1e-18;
+        long npi;
+        long n=Kv.NbDoF(),N=Kv.N;
+        double l[3];
+        
+        bool classoptm = copt && Op.optiexpK;
+        // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+        if (Kv.number<1 && verbosity/100 && verbosity % 10 == 2)
+            cout << "Element_rhs 3d S(levelset): copt = " << copt << " " << classoptm << endl;
+        int lastop;
+        What_d Dop = Op.DiffOp(lastop);
+        
+        assert(Op.MaxOp() <last_operatortype);
+        // assert(lastop<=3);
+        
+        RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+        R3 PP[4];
+        for(int i=0; i< np; ++i)
+            PP[i]= K(Q[i]);
+
+        for( int iii =0; iii+1 < np; iii+=2)
+        { // 0,1,, a and 2,3,0.
+            int i0=iii,i1=iii+1,i2=(iii+2)%np;
+            R3 NN= R3(PP[i0],PP[i1])^R3(PP[i0],PP[i2]);
+            double mes2 = (NN,NN);
+            double mes = sqrt(mes2);
+            if(mes2*mes <epsmes3) continue; //  too small
+            NN /= mes;
+            mes *= 0.5;
+           // cout << " Element_rhs::mes " << mes << " " << iii << endl;
+
+        for (npi=0;npi<FI.n;npi++) // loop on the integration point
+        {
+            GQuadraturePoint<R2>  pi( FI[npi]);
+            pi.toBary(l);
+            R3 Pt( l[0]*Q[i0]+l[1]*Q[i1]+l[2]*Q[i2]); //
+            MeshPointStack(stack)->set(Th,K(Pt),Pt,K,-1,NN,-1);
+            //
+            Kv.BF(Dop,Pt,fu);
+    //        MeshPointStack(stack)->set(K(Pt),Pt,Kv,label,NN,ie);
+            if (classoptm) (*Op.optiexpK)(stack); // call optim version
+            double coef = mes*pi.a;
+            for (int  i=0;  i<n;   i++ )
+                // if (alledges || onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // bofbof faux si il y a des derives ..
+            {
+                RNM_ wi(fu(i,'.','.'));
+                int il=0;
+                for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                {
+                    LOperaD::K ll(*l);
+                    pair<int,int> ii(ll.first);
+                    double w_i =  wi(ii.first,ii.second);
+                    R c =copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+                    // FFCS - removing what is probably a small glitch
+                    if ( copt && Kv.number<1)
+                    {
+                        R cc  =  GetAny<R>(ll.second.eval(stack));
+                        if ( c != cc) {
+                            cerr << c << " =! " << cc << endl;
+                            cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                            ExecError("In Optimized version "); }
+                    }
+                    
+                    
+                    //= GetAny<double>(ll.second.eval(stack));
+                    
+                    B[Kv(i)] += coef * c * w_i;
+                }
+            }
+            
+            
+        }
+    }
+        *MeshPointStack(stack) = mp;
+        
+}
+    
+    
+    
+  // end 3d
+    
+    
+ template<class R>
+  void  Element_rhs(const FElement & Kv,int ie,int label,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                    const QuadratureFormular1d & FI = QF_GaussLegendre2,bool alledges=false)
+  {
+    Stack stack=pvoid2Stack(vstack);
+    MeshPoint mp=*MeshPointStack(stack) ;
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    const Triangle & T  = Kv.T;
+    // const QuadratureFormular1d & FI = QF_GaussLegendre2;
+    long npi;
+    long i,n=Kv.NbDoF(),N=Kv.N;
+    
+    //  bool show = Kv.Vh.Th(T)==0;
+    // char * xxx[] ={" u"," v,"," p"," q"," r"};
+    // char * xxxx[] ={" u'"," v',"," p'"," q'"," r'"};
+    // char * yyy[] ={" ","_x ","_y "};
+
+    bool classoptm = copt && Op.optiexpK;
+   // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+    if (Kv.number<1 && verbosity/100 && verbosity % 10 == 2) 
+     cout << "Element_rhs S: copt = " << copt << " " << classoptm << endl;
+    KN<bool> Dop(last_operatortype);
+    Op.DiffOp(Dop);  
+    int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+    assert(Op.MaxOp() <last_operatortype);
+   // assert(lastop<=3);
+
+    RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+    
+    for (npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+        QuadratureFormular1dPoint pi( FI[npi]);
+        R2 E=T.Edge(ie);
+        double le = sqrt((E,E));
+        double coef = le*pi.a;
+        double sa=pi.x,sb=1-sa;
+        R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+          PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]);
+        R2 Pt(PA*sa+PB*sb ); //  
+        Kv.BF(Dop,Pt,fu);
+        MeshPointStack(stack)->set(T(Pt),Pt,Kv,label,R2(E.y,-E.x)/le,ie);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version         
+        
+        for ( i=0;  i<n;   i++ )  
+         // if (alledges || onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // bofbof faux si il y a des derives ..
+            { 
+              RNM_ wi(fu(i,'.','.'));
+              int il=0;
+              for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                {       
+                  LOperaD::K ll(*l);
+                  pair<int,int> ii(ll.first);
+                  double w_i =  wi(ii.first,ii.second);
+                  R c =copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+		  // FFCS - removing what is probably a small glitch
+                if ( copt && Kv.number<1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( c != cc) { 
+			 cerr << c << " =! " << cc << endl;
+                       cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                  
+                  
+                  //= GetAny<double>(ll.second.eval(stack));
+                 
+                  B[Kv(i)] += coef * c * w_i;
+                }
+            }
+        
+        
+      }  
+    *MeshPointStack(stack) = mp;
+    
+  }
+    
+    template<class R>
+    void  Element_rhs(const FElement & Kv,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                      const QuadratureFormular1d & FI ,const R2 & PPA,const R2 &PPB)
+    {
+        Stack stack=pvoid2Stack(vstack);
+        MeshPoint mp=*MeshPointStack(stack) ;
+        R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+        const Triangle & T  = Kv.T;
+        R2 PA=T(PPA),PB=T(PPB);
+        // const QuadratureFormular1d & FI = QF_GaussLegendre2;
+        long npi;
+        long i,n=Kv.NbDoF(),N=Kv.N;
+        
+        //  bool show = Kv.Vh.Th(T)==0;
+        // char * xxx[] ={" u"," v,"," p"," q"," r"};
+        // char * xxxx[] ={" u'"," v',"," p'"," q'"," r'"};
+        // char * yyy[] ={" ","_x ","_y "};
+        
+        bool classoptm = copt && Op.optiexpK;
+        // assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+        if (Kv.number<1 && verbosity/100 && verbosity % 10 == 2)
+            cout << "Element_rhs(levelset) S: copt = " << copt << " " << classoptm << endl;
+        KN<bool> Dop(last_operatortype);
+        Op.DiffOp(Dop);
+        int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+        assert(Op.MaxOp() <last_operatortype);
+        // assert(lastop<=3);
+        
+        RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+        
+        for (npi=0;npi<FI.n;npi++) // loop on the integration point
+        {
+            QuadratureFormular1dPoint pi( FI[npi]);
+            R2 E(PA,PB);
+            double le = sqrt((E,E));
+            double coef = le*pi.a;
+            double sa=pi.x,sb=1-sa;
+           
+            R2 Pt(PA*sa+PB*sb ); //
+            Kv.BF(Dop,Pt,fu);
+            MeshPointStack(stack)->set(T(Pt),Pt,Kv,0,R2(E.y,-E.x)/le,0);
+            if (classoptm) (*Op.optiexpK)(stack); // call optim version
+            
+            for ( i=0;  i<n;   i++ )
+                // if (alledges || onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // bofbof faux si il y a des derives ..
+            {
+                RNM_ wi(fu(i,'.','.'));
+                int il=0;
+                for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                {
+                    LOperaD::K ll(*l);
+                    pair<int,int> ii(ll.first);
+                    double w_i =  wi(ii.first,ii.second);
+                    R c =copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+		  // FFCS - removing what is probably a small glitch
+                    if ( copt && Kv.number<1)
+                    {
+                        R cc  =  GetAny<R>(ll.second.eval(stack));
+                        if ( c != cc) {
+                            cerr << c << " =! " << cc << endl;
+                            cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+                            ExecError("In Optimized version "); }
+                    }
+                    
+                    
+                    //= GetAny<double>(ll.second.eval(stack));
+                    
+                    B[Kv(i)] += coef * c * w_i;
+                }
+            }
+            
+            
+        }  
+        *MeshPointStack(stack) = mp;
+        
+    } 
+   
+    
+ 
+    template<class R>
+    void  Element_rhsVF(const FElement & Kv,const FElement & KKv,int ie,int iie,int label,const LOperaD &Op,double * p,int *ip,void  * bstack,KN_<R> & B,
+		      const QuadratureFormular1d & FI = QF_GaussLegendre2)
+    // sier of ip
+    {
+	pair_stack_double * bs=static_cast<pair_stack_double *>(bstack);   
+	Stack stack= bs->first;
+	double binside = *bs->second; // truc FH pour fluide de grad2 (decentrage bizard)
+	
+	MeshPoint mp=*MeshPointStack(stack) ;
+	R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+	const Triangle & T  = Kv.T;
+	// const QuadratureFormular1d & FI = QF_GaussLegendre2;
+	long npi;
+	long i,nv=Kv.NbDoF(),N=Kv.N;
+	long nnv=KKv.NbDoF();
+	assert(nv==nnv);
+	//  bool show = Kv.Vh.Th(T)==0;
+	// char * xxx[] ={" u"," v,"," p"," q"," r"};
+	// char * xxxx[] ={" u'"," v',"," p'"," q'"," r'"};
+	// char * yyy[] ={" ","_x ","_y "};
+	
+	bool classoptm = copt && Op.optiexpK;
+	// assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+       	if (Kv.number<1 && verbosity/100 && verbosity % 10 == 2) 
+	    cout << "Element_rhs S: copt = " << copt << " " << classoptm << endl;
+	KN<bool> Dop(last_operatortype);
+	Op.DiffOp(Dop);  
+	int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+	//assert(Op.MaxOp() <last_operatortype);
+	// assert(lastop<=3);
+	int lffv = nv*N*last_operatortype; 
+	int lp =nv*2;
+	KN_<int> pp(ip,lp),pk(ip+lp,lp),pkk(ip+2*lp,lp);	
+	int n = BuildMEK_KK(lp,pp,pk,pkk,&Kv,&KKv); 
+	RNMK_ fu(p,nv,N,lastop); //  the value for basic fonction
+	RNMK_ ffu( (double*) p  + lffv  ,nv,N,lastop); //  the value for basic fonction
+	
+	R2 E=T.Edge(ie);
+	double le = sqrt((E,E));
+	R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+	PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]),
+	PC(TriangleHat[OppositeVertex[ie]]);
+	// warning the to edge are in opposite sens         
+	R2 PP_A(TriangleHat[VerticesOfTriangularEdge[iie][1]]),
+	PP_B(TriangleHat[VerticesOfTriangularEdge[iie][0]]),
+	PP_C(TriangleHat[OppositeVertex[ie]]);
+	R2 Normal(E.perp()/-le); 
+	bool onborder= &Kv.T == &KKv.T; 
+        double cmean = onborder ? 1. : 0.5;
+	for (npi=0;npi<FI.n;npi++) // loop on the integration point
+	  {
+	      QuadratureFormular1dPoint pi( FI[npi]);
+	      R2 E=T.Edge(ie);
+	      double le = sqrt((E,E));
+	      double coef = le*pi.a;
+	      double sa=pi.x,sb=1-sa;
+	      R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),
+	      PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]);
+	      R2 Pt(PA*sa+PB*sb ); //
+	      R2 PP_t(PP_A*sa+PP_B*sb ); //  
+	      if (binside) {
+		  Pt   = (1-binside)*Pt + binside*PC; 
+	      PP_t  = (1-binside)*PP_t + binside*PP_C; }
+	      Kv.BF(Dop,Pt,fu);
+	      if(onborder)
+		ffu=0;
+	      else 
+	        KKv.BF(Dop,PP_t,ffu);
+	      
+	      MeshPointStack(stack)->set(T(Pt),Pt,Kv,label,R2(E.y,-E.x)/le,ie);
+	      if (classoptm) (*Op.optiexpK)(stack); // call optim version         
+	      
+	      for ( i=0;  i<n;   i++ )  
+		  // if (alledges || onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // bofbof faux si il y a des derives ..
+		{ 
+		    int ik= pk[i];
+		    int ikk=pkk[i]; 
+		    RNM_ wi(fu(Max(ik,0),'.','.'));
+                    RNM_ wwi(ffu(Max(ikk,0),'.','.'));  		    
+		    int il=0;
+		    for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+		      {       
+			 
+			  
+			  LOperaD::K ll(*l);
+			  pair<int,int> ii(ll.first);
+			  int iis = ii.second;
+			  int iicase  = iis / last_operatortype;
+			  iis %= last_operatortype;
+			  double w_i=0,ww_i=0; 
+			  if(ik>=0) w_i =   wi(ii.first,iis ); 
+			  if( iicase>0 ) 
+			    {
+			    if( ikk>=0) ww_i =  wwi(ii.first,iis );  
+			    if       (iicase==Code_Jump)      w_i = ww_i-w_i; // jump
+			    else  if (iicase==Code_Mean)      w_i = cmean*  (w_i + ww_i ); // average
+			    else  if (iicase==Code_OtherSide) w_i = ww_i;  // valeur de autre cote
+			    }
+			  R c =copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+		  // FFCS - removing what is probably a small glitch
+			  if ( copt && Kv.number<1)
+			    {
+				R cc  =  GetAny<R>(ll.second.eval(stack));
+				if ( c != cc) { 
+				     cerr << c << " =! " << cc << endl;
+				    cerr << "Sorry error in Optimization add:  int2d(Th,optimize=0)(...)" << endl;
+				ExecError("In Optimized version "); }
+			    }
+			  
+			  
+			  //= GetAny<double>(ll.second.eval(stack));
+			  
+			  B[Kv(i)] += coef * c * w_i;
+		      }
+		}
+	      
+	      
+	  }  
+	*MeshPointStack(stack) = mp;
+	
+    } 
+    
+  // 3d  
+ template<class R>
+ void  Element_rhs(const  Mesh3 & ThI,const Mesh3::Element & KI, const FESpace3 & Vh,
+ int ie,int label,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                    const QuadratureFormular & FI,bool alledges=false)
+    {
+      Stack stack=pvoid2Stack(vstack);
+      int intmortar=0;
+  //  AFAIRE("Element_rhs 3d on surface  2 diff mesh ");
+      static int count =0;
+      if(count++<1) 
+      {
+          cout << " Element_rhs 3d on surface  2 diff mesh int test (FH)" << endl;
+          cout << " -----------------------------------------------------" << endl;
+      }
+      // integration 1d on 2 diff mesh 
+      
+      
+      MeshPoint mp=*MeshPointStack(stack) ;
+      R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+      
+      
+      bool classoptm = copt && Op.optiexpK;
+      //assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+      if (ThI(KI)<1 && verbosity/100 && verbosity % 10 == 2) 
+          cout << "Element_rhs S: copt = " << copt << " " << classoptm << endl;
+      assert(Op.MaxOp() <last_operatortype);
+      //
+      int lastop=0;
+      lastop = 0;
+      What_d Dop = Op.DiffOp(lastop);
+      // assert(lastop<=3);
+      const Tet & T  = KI;
+      long npi;
+      
+      const Tet * Kp=0;
+      
+      for (npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+          
+          GQuadraturePoint<R2> pi(FI[npi]);
+          R3 NN= T.N(ie);
+          double mes=NN.norme();
+          NN/=mes;
+          double coef = 0.5*mes*pi.a; // 
+          R3 Pt(T.PBord(ie,pi)),PI(T(Pt));
+          
+          
+          
+          MeshPointStack(stack)->set(ThI,PI,Pt,KI,label,NN,ie);
+          if (classoptm) (*Op.optiexpK)(stack); // call optim version         
+          bool outside;
+          R3 PIt;
+          const Tet & K  = *Vh.Th.Find(PI,PIt,outside,Kp);
+          if ( ! outside || intmortar) //  FH march 2009 ???
+          {
+              const  FElement3  Kv= Vh[K];
+              long i,n=Kv.NbDoF(),N=Kv.N;
+              RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+              Kv.BF(Dop,PIt,fu);
+              
+              for ( i=0;  i<n;   i++ )  
+             //   if (alledges || onWhatIsFace[ie][Kv.DFOnWhat(i)]) // bofbof faux si il y a des derives ..
+              { 
+                  RNM_ wi(fu(i,'.','.'));
+                  int il=0;
+                  for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                  {       
+                      LOperaD::K ll(*l);
+                      pair<int,int> ii(ll.first);
+                      double w_i =  wi(ii.first,ii.second);
+                      R c =copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+		  // FFCS - removing what is probably a small glitch
+                      if ( copt && Kv.number<1)
+                      {
+                          R cc  =  GetAny<R>(ll.second.eval(stack));
+                          if ( c != cc) { 
+                              cerr << c << " =! " << cc << endl;
+                              cerr << "Sorry error in Optimization add:  int1d(Th,optimize=0)(...)" << endl;
+                              ExecError("In Optimized version "); }
+                      }
+                      
+                      
+                      //= GetAny<double>(ll.second.eval(stack));
+                      
+                      B[Kv(i)] += coef * c * w_i;
+                  }
+              }
+              
+          }
+      }  
+      *MeshPointStack(stack) = mp;
+     
+      
+  } 
+  // 3d
+ template<class R>
+ void  Element_rhs(const  Mesh & ThI,const Triangle & KI, const FESpace & Vh,
+ int ie,int label,const LOperaD &Op,double * p,void * vstack,KN_<R> & B,
+                    const QuadratureFormular1d & FI = QF_GaussLegendre2,bool alledges=false,bool intmortar=false,
+                   R2 *Q=0)
+  {
+     // integration 1d on 2 diff mesh 
+    
+     Stack stack=pvoid2Stack(vstack);
+    MeshPoint mp=*MeshPointStack(stack) ;
+    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);
+    
+
+    bool classoptm = copt && Op.optiexpK;
+    //assert(  (copt !=0) ==  (Op.where_in_stack_opt.size() !=0) );
+    if (ThI.number(KI)<1 && verbosity/100 && verbosity % 10 == 2) 
+     cout << "Element_rhs S: copt = " << copt << " " << classoptm << endl;
+    KN<bool> Dop(last_operatortype);
+    Op.DiffOp(Dop);  
+    int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));
+    assert(Op.MaxOp() <last_operatortype);
+   // assert(lastop<=3);
+    const Triangle & T  = KI;
+    long npi;
+    
+    const Triangle * Kp=0;
+    R2 PA,PB,E;
+    if( Q==0)
+      {
+       PA=TriangleHat[VerticesOfTriangularEdge[ie][0]];
+       PB=TriangleHat[VerticesOfTriangularEdge[ie][1]];
+       E=T.Edge(ie);
+      }
+      else
+      {
+          PA=Q[0];
+          PB=Q[1];
+          E=T(PB)-T(PA);
+      }
+    double le = sqrt((E,E));
+   
+    for (npi=0;npi<FI.n;npi++) // loop on the integration point
+      {
+        QuadratureFormular1dPoint pi( FI[npi]);
+
+        
+        double coef = le*pi.a;
+        double sa=pi.x,sb=1-sa;
+        R2 Pt(PA*sa+PB*sb ); //
+        R2 PI(KI(Pt));  
+     //   Kv.BF(Dop,Pt,fu);
+        MeshPointStack(stack)->set(ThI,PI,Pt,KI,label,R2(E.y,-E.x)/le,ie);
+        if (classoptm) (*Op.optiexpK)(stack); // call optim version         
+        bool outside;
+        R2 PIt;
+        const Triangle & K  = *Vh.Th.Find(PI,PIt,outside,Kp);
+        if ( ! outside || intmortar) //  FH march 2009 ???
+          {
+            const  FElement  Kv= Vh[K];
+            long i,n=Kv.NbDoF(),N=Kv.N;
+            RNMK_ fu(p,n,N,lastop); //  the value for basic fonction
+            Kv.BF(Dop,PIt,fu);
+        
+        for ( i=0;  i<n;   i++ )  
+         // if (alledges || onWhatIsEdge[ie][Kv.DFOnWhat(i)]) // bofbof faux si il y a des derives ..
+            { 
+              RNM_ wi(fu(i,'.','.'));
+              int il=0;
+              for (LOperaD::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)
+                {       
+                  LOperaD::K ll(*l);
+                  pair<int,int> ii(ll.first);
+                  double w_i =  wi(ii.first,ii.second);
+                  R c =copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));
+		  // FFCS - removing what is probably a small glitch
+                if ( copt && Kv.number<1)
+                 {
+                     R cc  =  GetAny<R>(ll.second.eval(stack));
+                     if ( c != cc) { 
+			  cerr << c << " =! " << cc << endl;
+                       cerr << "Sorry error in Optimization add:  int1d(Th,optimize=0)(...)" << endl;
+                       ExecError("In Optimized version "); }
+                 }
+                  
+                  
+                  //= GetAny<double>(ll.second.eval(stack));
+                 
+                  B[Kv(i)] += coef * c * w_i;
+                }
+            }
+        
+        }
+      }  
+    *MeshPointStack(stack) = mp;
+    
+  } 
+  
+
+  template<class R,typename MC,class FESpace >
+  bool AssembleVarForm(Stack stack,const typename FESpace::Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                       MC  * A,KN_<R> * B,const list<C_F0> &largs)
+  { // return true if BC 
+    typedef typename FESpace::Mesh Mesh ;
+    typedef Mesh * pmesh;
+    bool ret=false; 
+    typedef DotStar_KN_<R> DotStar;
+    typedef DotSlash_KN_<R> DotSlash;
+    list<C_F0>::const_iterator ii,ib=largs.begin(),
+      ie=largs.end();
+     using namespace FreeFempp;  
+     TypeVarForm<R> *tvf=TypeVarForm<R>::Global;
+     assert( tvf);
+    for (ii=ib;ii != ie;ii++)
+      {
+        Expression e=ii->LeftValue();
+        aType r = ii->left();
+      //  if(A)        cout << "AssembleVarForm " <<  * r << " " <<  (*A)(0,3) << endl;
+        if (r==  tvf->tFB) 
+          { if (A)
+           { 
+            const  FormBilinear * bf =dynamic_cast<const  FormBilinear *>(e);
+            pmesh  Thbf = GetAny<pmesh>((*bf->di->Th)(stack));
+            if(Thbf)AssembleBilinearForm<R>( stack,*Thbf,Uh,Vh,sym,*A,bf);
+           }
+          }
+        else if (r==tvf->tMat)
+          {
+            if (A)
+              InternalError(" Add sparse matrice; to do, sorry");
+          }
+        else if (r==tvf->tFL)
+          {
+            if (B) {
+              const  FormLinear * bf =dynamic_cast<const  FormLinear *>(e);
+              pmesh  Thbf = GetAny<pmesh>((*bf->di->Th)(stack));            
+              if(Thbf) AssembleLinearForm<R>( stack,*Thbf, Vh, B,bf) ;
+	    }
+          }
+        else if (r==tvf->tTab)
+          {
+            if ( B) 
+              *B += *GetAny<KN<R> *>( (*e)(stack) );
+          }
+        else if (r==tvf->tDotStar)
+          {
+            if ( B) 
+              {
+                DotStar ab=GetAny<DotStar>( (*e)(stack) );
+                *B += ab;
+              }
+          }
+        else if (r==tvf->tMatX)
+          {
+            if ( B) 
+              { 
+                *B += GetAny<typename VirtualMatrice<R>::plusAx >( (*e)(stack) )  ;
+              }
+          }
+        else if (r==tvf->tMatTX)
+          {
+            if ( B) 
+              { 
+                *B += GetAny<typename VirtualMatrice<R>::plusAtx >( (*e)(stack) )  ;
+              }
+          }
+        else if (r== tvf->tBC) 
+          ret=true;
+        else 
+          { 
+            cerr << "AssembleVarForm  invalid type : " << * r <<  endl;
+            throw(ErrorExec("AssembleVarForm invalid type in varf",1));
+          }
+      }
+    return ret;
+  }                            
+  
+  template<class R,class FESpace>
+  void AssembleBC(Stack stack,const typename FESpace::Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                  MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X, const list<C_F0> &largs , double tgv  )
+  {
+    list<C_F0>::const_iterator ii,ib=largs.begin(),
+      ie=largs.end();
+    aType tBC( atype<const  BC_set  *>()) ;                    
+    for (ii=ib;ii != ie;ii++)
+      {
+        Expression e=ii->LeftValue();
+        aType r = ii->left();
+        if (r==tBC)
+          AssembleBC(stack,Th,Uh,Vh,sym,A,B,X, dynamic_cast<const  BC_set *>(e),tgv);
+      }
+    
+  }
+  
+
+ template<class R>
+  void AssembleBC(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                  MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X, const  BC_set * bc, double tgv  )
+    
+  {
+    MeshPoint *mps= MeshPointStack(stack),mp=*mps;
+     StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+     bool sptrclean=true;
+     //     sptr->clean(); // modif FH mars 2006  clean Ptr
+    
+    int ktbc=0, nbon =0;
+    bool Aii = A && A->n == A->m;
+    int Nbcomp=Vh.N;
+    Check(bc,Nbcomp);
+    ffassert(Vh.N == Uh.N);
+    TabFuncArg tabexp(stack,Vh.N);
+    KN<double> buf(Vh.MaximalNbOfDF()*last_operatortype*Vh.N);
+    KN<R> gg(buf);
+    if ( B && B->N() != Vh.NbOfDF) ExecError("AssembleBC size rhs and nb of DF of Vh");
+    if(verbosity>99) cout << " Problem : BC_set "<< typeid(R).name() << " " ;
+    nbon =bc->on.size();
+    set<long> on;
+    Expandsetoflab(stack,*bc, on);
+/*
+    for (int i=0;i<nbon;i++)
+      {
+        long  lab  = GetAny<long>( (*bc->on[i])(stack));
+        if(verbosity>99) cout << lab << " " ;
+        on.insert(lab);
+      }
+    if(verbosity>99) 
+      cout << endl;
+    */
+    int kk=bc->bc.size();
+    
+    const int dim=Vh.N;
+    FElement::aIPJ ipj(Vh[0].Pi_h_ipj()); 
+    FElement::aR2  PtHat(Vh[0].Pi_h_R2()); 
+    
+    KN<int> PtonB(PtHat.N());
+    
+    KN<double>   Aipj(ipj.N());
+    KNM<R>  Vp(dim,PtHat.N());
+    
+    double tgv1=tgv <0? 1: tgv; // change 21 dec 2010 FH (Hack of ILU)
+    for (int ib=0;ib<Th.neb;ib++)
+      {
+        int ie;
+        int it = Th.BoundaryElement(ib,ie);
+        int r =Th.bedges[ib].lab;
+        if (on.find(r) != on.end() ) 
+          {
+            const FElement K(Uh[it]);
+            R2 E=K.T.Edge(ie);
+            double le = sqrt((E,E));
+            
+            ktbc++;
+            if(verbosity>99)   cout << "BC " << it << " " << ie << " lab=" << r <<  ":\t"
+                                    << K.T[VerticesOfTriangularEdge[ie][0]] << "; " 
+                                    << K.T[VerticesOfTriangularEdge[ie][1]] << " E=" << K.T.Edge(ie) << endl;
+            
+            for (int k=0;k<kk;k++)
+              {
+                gg=R();
+                pair<int,Expression> xx=bc->bc[k];
+                tabexp=0; 
+                int comp = xx.first;
+                tabexp[comp]=xx.second;
+                // while  (comp+1 <Nbcomp && which_uh[comp+1] == which_uh[comp])   
+                while  (comp+1 <Nbcomp && Uh.dim_which_sub_fem[comp+1] == Uh.dim_which_sub_fem[comp])   
+                  {  // the right 
+                    k++; // NEXT COMP 
+                    comp++;
+                    if (k<kk && (comp == bc->bc[k].first) )
+                      tabexp[comp]=bc->bc[k].second;
+                    else
+                      CompileError("In Boundary condition the vector FESpace , we must have:"
+                                   " all componant, in the right order");
+                    
+                  }
+                 // cout << " k "<< k << " " << comp << " " << " Nbcomp=" << Nbcomp << " " << Uh.dim_which_sub_fem[comp] << " " << Uh.dim_which_sub_fem[comp+1] <<  endl; 
+#ifdef OLDPih                    
+                K.Pi_h(gg,F_Pi_h,buf,&tabexp);
+                
+#else
+         K.Pi_h(Aipj);
+         PtonB = 0;
+        for (int i=0;i<Aipj.N();i++)
+           PtonB[ipj[i].p] += onWhatIsEdge[ie][K.DFOnWhat(ipj[i].i)] ;
+         // cout << "   bc->complextype:  " << bc->complextype << endl;             
+         for (int p=0;p<PtHat.N();p++)
+          if (PtonB[p]) // in on boundary 
+          { 
+            mps->set(K.T(PtHat[p]),PtHat[p],K,r,R2(E.y,-E.x)/le,ie); // la normal bofbof ?
+            KN_<R> Vpp(Vp('.',p));
+	    Vpp=R();
+            for (int j=0;j<dim;j++)
+             if (tabexp[j]) 
+	       {  
+		  if(bc->complextype) // FH may 2007  MatriceCreuse
+                   Vpp[j]=GetAny<R>( (*tabexp[j])(stack) );
+		  else 
+		   Vpp[j]=GetAny<double>( (*tabexp[j])(stack) );
+	        }       
+              else Vpp[j]=0.;
+           }
+		//cout << " ..... Vp " << Vp << " " << bc->complextype << " " << bc << endl;  
+         for (int i=0;i<Aipj.N();i++)
+          { 
+           const FElement::IPJ &ipj_i(ipj[i]);
+           gg[ipj_i.i] += Aipj[i]*Vp(ipj_i.j,ipj_i.p);           
+          }
+#endif
+                int nbdf = K.NbDoF();
+                for (int df=0;df<nbdf;df++)
+                  // if (K.FromFE(df)==which_uh[xx.first] && onWhatIsEdge[ie][K.DFOnWhat(df)] ) 
+                  {
+                  //  cout << df << " from = " << K.FromFE(df) << "   dim .. " << Uh.dim_which_sub_fem[xx.first] << "  first " << xx.first << " " << onWhatIsEdge[ie][K.DFOnWhat(df)] << endl;
+                  if (K.FromASubFE(df)==Uh.dim_which_sub_fem[xx.first] && onWhatIsEdge[ie][K.DFOnWhat(df)] ) 
+                    {
+                      // cout << k << " df=" << df <<  " g= " << gg[df] <<" " << gg(FromTo(0,2)) << endl;
+                      int ddf=K(df);
+                      // AA(ddf,ddf) =tgv;
+                      if (Aii)  A->SetBC(ddf, tgv);// change 21 dec 2010 FH (Hack of ILU)
+                      if (B) (*B)[ddf]=  tgv1*gg[df]; 
+                      if (X) (*X)[ddf]=gg[df];
+                    }
+                   }
+              if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	      }
+          }
+      }
+    if (! ktbc  && nbon && verbosity ) 
+      {
+        cout << " Warning: -- Your set of boundary condition is incompatible with the mesh label." << endl;
+      }
+    *mps =mp;            
+  }
+ 
+
+template<class R>
+  void AssembleBC(Stack stack,const Mesh3 & Th,const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+                  MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X, const  BC_set * bc, double tgv  )
+    
+  {
+    typedef Mesh3 Mesh;
+    typedef typename FESpace3::FElement FElement;
+    typedef typename Mesh::BorderElement BorderElement;
+    typedef typename Mesh::Rd Rd;
+    typedef typename Mesh::Element Element;
+    typedef typename Mesh::RdHat RdHat;
+    
+    MeshPoint *mps= MeshPointStack(stack),mp=*mps;
+    StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+    bool sptrclean=true;
+    //     sptr->clean(); // modif FH mars 2006  clean Ptr
+    
+    int ktbc=0, nbon =0;
+    bool Aii = A && A->n == A->m;
+    int Nbcomp=Vh.N;
+    Check(bc,Nbcomp);
+    assert(Vh.N == Uh.N);
+    TabFuncArg tabexp(stack,Vh.N);
+    KN<double> buf(Vh.MaximalNbOfDF()*last_operatortype*Vh.N);
+    KN<R> gg(buf);
+    if ( B && B->N() != Vh.NbOfDF) ExecError("AssembleBC size rhs and nb of DF of Vh");
+    if(verbosity>99) cout << " Problem : BC_set "<< typeid(R).name() << " " ;
+    nbon =bc->on.size();
+    set<long> on;
+    Expandsetoflab(stack,*bc, on);
+/*
+    for (int i=0;i<nbon;i++)
+      {
+        long  lab  = GetAny<long>( (*bc->on[i])(stack));
+        if(verbosity>99) cout << lab << " " ;
+        on.insert(lab);
+      }
+    if(verbosity>99) 
+      cout << endl;*/
+    int kk=bc->bc.size();
+    
+    const int dim=Vh.N;
+    
+    InterpolationMatrix<RdHat> ipmat(Vh);    
+    int npPh = Vh.maxNbPtforInterpolation;
+    KN<int> PtonB(npPh);
+    KNM<R>   Vp(npPh,dim);
+    Vp=R();
+    KN<R>  Vdf(Vh.MaxNbDFPerElement);
+    double tgv1=tgv <0? 1: tgv; 
+    map<int,int> lll;
+    for (int ib=0;ib<Th.nbe;ib++)
+      {
+        int ie;
+        int it = Th.BoundaryElement(ib,ie);
+	
+	//const BorderElement &be=Th.be(ib);
+        int r =Th.be(ib).lab;
+	lll[r]++;
+        if (on.find(r) != on.end() ) 
+          {
+	     const FElement K(Uh[it]);
+	    ipmat.set(K);
+           
+            //R2 E=K.T.Edge(ie);
+            //double le = be.mesure(); 
+            
+            ktbc++;
+	    /*
+            if(verbosity>99)   cout << "BC " << it << " " << ie << " lab=" << r <<  ":\t"
+                                    << K.T[VerticesOfTriangularEdge[ie][0]] << "; " 
+                                    << K.T[VerticesOfTriangularEdge[ie][1]] << " E=" << K.T.Edge(ie) << endl;
+	    */
+            for (int k=0;k<kk;k++)
+              {
+                gg=R();
+                pair<int,Expression> xx=bc->bc[k];
+                tabexp=0; 
+                int comp = xx.first;
+                tabexp[comp]=xx.second;
+                // while  (comp+1 <Nbcomp && which_uh[comp+1] == which_uh[comp])   
+                while  (comp+1 <Nbcomp && Uh.dim_which_sub_fem[comp+1] == Uh.dim_which_sub_fem[comp])   
+                  {  // the right 
+                    k++; // NEXT COMP 
+                    comp++;
+                    if (k<kk && (comp == bc->bc[k].first) )
+                      tabexp[comp]=bc->bc[k].second;
+                    else
+                      CompileError("In Boundary condition the vector FESpace , we must have:"
+                                   " all componant, in the right order");
+                    
+                  }
+		int nbdf=K.NbDoF() ;	  
+		//ipmat.set(it);
+		PtonB = 0;
+		Rd NN=K.T.N(ie);
+		NN /= NN.norme();
+		for (int i=0;i<ipmat.ncoef;i++)
+		  PtonB[ipmat.p[i]] +=  Element::onWhatBorder[ie][K.DFOnWhat(ipmat.dofe[i])] ;
+		
+		
+		for (int p=0;p<ipmat.np;p++)
+		  if (PtonB[p]) // in on boundary 
+		    { 
+		      const RdHat & PtHat(ipmat.P[p]);
+		      mps->set(K.T(PtHat),PtHat,K,r,NN,ie); // la normal bofbof ?
+		      KN_<R> Vpp(Vp(p,'.'));
+		      for (int j=0;j<dim;j++)
+			if (tabexp[j]) 
+			  if(bc->complextype) // FH may 2007   
+			  Vpp[j]=GetAny<R>( (*tabexp[j])(stack) );
+			  else 
+			  Vpp[j]=GetAny<double>( (*tabexp[j])(stack) );
+    
+			else Vpp[j]=0.;
+		    }
+		// cout << " Vp:  " << Vp << endl;
+		K.Pi_h(Vp,Vdf,ipmat);  
+                for (int df=0;df<nbdf;df++)
+                  {
+		    if (K.FromASubFE(df)==Uh.dim_which_sub_fem[xx.first] && Element::onWhatBorder[ie][K.DFOnWhat(df)] ) 
+		      {
+			int ddf=K(df);
+			// cout << ddf << " " << df << " " << Vdf[df] << " " << it << " ib = " << ib  << " == " << Th(Th[it][df]) <<  endl;
+			if (Aii)  A->SetBC(ddf,tgv);// change 21 dec 2010 FH (Hack of ILU)
+			if (B) (*B)[ddf]=tgv1*Vdf[df]; 
+			if (X) (*X)[ddf]=Vdf[df];
+		      }
+		  }
+		if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	      }
+          }
+      }
+    if (! ktbc  && nbon && verbosity ) 
+      {
+        cout << " Warning: -- Your set of boundary condition is incompatible with the mesh label." << endl;
+	for (map<int,int>::const_iterator i=lll.begin();i!=lll.end();i++)
+	  cout << " lab " << i-> first << "  nb " << i->second  << endl;
+      }
+    *mps =mp;            
+  }
+void  Expandsetoflab(Stack stack,const BC_set & bc,set<long> & setoflab);
+void  Expandsetoflab(Stack stack,const CDomainOfIntegration & di,set<int> & setoflab,bool &all);
+    
+
+template<class R>
+ void AssembleLinearForm(Stack stack,const Mesh3 & Th,const FESpace3 & Vh,KN_<R> * B,const  FormLinear * l )
+{
+    typedef FESpace3 FESpace;
+   typedef FESpace3::Mesh Mesh;
+   typedef Mesh *pmesh ;
+
+      StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+     bool sptrclean=true;
+     //     sptr->clean(); // modif FH mars 2006  clean Ptr
+    Check(l->l,Vh.N);
+    if ( B && B->N() != Vh.NbOfDF) ExecError("AssembleLinearForm size rhs and nb of DF of Vh");
+   // if ( & Th != &Vh.Th ) ExecError("AssembleLinearForm on different meshes  ( not implemented FH).");
+    KN<double> buf(Vh.MaximalNbOfDF()*last_operatortype*Vh.N*2);
+    
+    //            const  FormLinear * l=dynamic_cast<const  FormLinear *>(e);
+    const CDomainOfIntegration & di= *l->di;
+    ffassert(di.d==3);
+   // const Mesh * pThdi = GetAny<pmesh>( (* di.Th)(stack));
+
+    const Mesh & ThI = Th;//* GetAny<pmesh>( (* di.Th)(stack));
+    bool sameMesh = &ThI == &Vh.Th;
+    
+    SHOWVERB(cout << " FormLinear " << endl);
+    //const vector<Expression>  & what(di.what);
+    
+    CDomainOfIntegration::typeofkind  kind = di.kind;
+    //const QuadratureFormular1d & FIE = di.FIE(stack);
+  //  const QuadratureFormular & FIT = di.FIT(stack);
+   // const GQuadratureFormular<R3> & FIV = di.FIV(stack);
+    
+   // const QuadratureFormular1d & FIEo = di.FIE(stack);
+    const QuadratureFormular & FITo = di.FIT(stack);
+    const GQuadratureFormular<R3> & FIVo = di.FIV(stack);
+    //  to change the quadrature on element ... may 2014 FH ..
+   // QuadratureFormular1d  FIE(FIEo,3);
+    QuadratureFormular FIT(FITo,3);
+    GQuadratureFormular<R3>  FIV(FIVo,3);
+    
+    const bool useopt=di.UseOpt(stack);    
+    double binside=di.binside(stack);  // truc FH pour fluide de grad2 (decentrage bizard)  
+  //  cout << "AssembleLinearForm " << l->l->v.size() << endl; 
+    set<int> setoflab;
+    bool all=true; 
+    bool VF=l->VF();  // finite Volume or discontinous Galerkin
+    if (verbosity>2) cout << "  -- AssembleLinearForm 1,  discontinous Galerkin  =" << VF << " binside = "<< binside <<"\n";
+
+    if (verbosity>3) 
+      {
+	if (CDomainOfIntegration::int2d==kind) cout << "  -- boundary int border ( nQP: "<< FIT.n << ") , samemesh: " << sameMesh << " "   ;
+	else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges ( nQP: "<< FIT.n << "),"  ;
+	else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIT.n << ")," ;
+	else cout << "  --  int    (nQP: "<< FIV.n << " ) in "  ;
+      }
+  //  if(di.islevelset()) InternalError("So no levelset integration type on this case (3)");
+    if(di.islevelset() && (CDomainOfIntegration::int2d!=kind) && (CDomainOfIntegration::int3d!=kind) )
+        InternalError("So no levelset intgeration type on no int2d/3d case");
+    /*
+    if ( verbosity>3) 
+      if (kind==CDomainOfIntegration::int1d) cout << "  -- boundary int border " ;
+      else if (kind==CDomainOfIntegration::intalledges) cout << "  -- boundary int all edges " ;
+      else if (kind==CDomainOfIntegration::intallVFedges) cout << "  -- boundary int all edges " ;
+      else cout << "  -- boundary int  " ;
+    */
+      
+    Expandsetoflab(stack,di, setoflab,all);
+    /*
+    for (size_t i=0;i<what.size();i++)
+      if(di.whatis[i] ==0)
+      {
+	long  lab  = GetAny<long>( (*what[i])(stack));
+        setoflab.insert(lab);
+        if ( verbosity>3) cout << lab << " ";
+        all=false;
+      }
+     else 
+        {
+	   KN<long>  labs( GetAny<KN_<long> >( (*what[i])(stack)));
+	  for (long j=0; j<labs.N(); ++j) {	      
+	      setoflab.insert(labs[j]);
+	      if ( verbosity>3) cout << labs[j] << " ";
+	  }	  
+	  all=false;	  
+     }*/
+
+    if (verbosity>3) cout << " Optimized = "<< useopt << ", ";
+    
+    const E_F0 & optiexp0=*l->l->optiexp0;
+    // const E_F0 & optiexpK=*l->l->optiexpK;
+    int n_where_in_stack_opt=l->l->where_in_stack_opt.size();
+    R** where_in_stack =   0;
+    if (n_where_in_stack_opt && useopt)
+      where_in_stack = new R * [n_where_in_stack_opt];
+    if (where_in_stack)
+      {
+	assert(l->l->v.size()==(size_t) n_where_in_stack_opt);
+	for (int i=0;i<n_where_in_stack_opt;i++)
+	  {
+	    int offset=l->l->where_in_stack_opt[i];
+	    assert(offset>10);
+	    where_in_stack[i]= static_cast<R *>(static_cast<void *>((char*)stack+offset));
+	    *(where_in_stack[i])=0;
+	  }
+	if(&optiexp0) optiexp0(stack);
+	
+	if( (verbosity/100) && verbosity % 10 == 2)
+	  {
+	    int il=0;
+
+	    for (LinearOperatorD::const_iterator ll=l->l->v.begin();ll!=l->l->v.end();ll++,il++)
+	      cout << il << " coef (" << ll->first << ") = " << *(where_in_stack[il]) << " offset=" << l->l->where_in_stack_opt[il] <<endl;
+	    
+	    for (int i=0;i<n_where_in_stack_opt;i++)
+	      cout << "const coef " << i << " = " << *(where_in_stack[i]) << endl;
+	  }
+      }
+    Stack_Ptr<R*>(stack,ElemMatPtrOffset) =where_in_stack;
+    
+      KN<int>   ip(Vh.MaxNbDFPerElement*6);
+    if (verbosity >3) 
+      {
+	if (all) cout << " all " << endl ;
+	else cout << endl;
+      }
+    if (kind==CDomainOfIntegration::int2d)
+      { //AFAIRE("3D Elment RHS CDomainOfIntegration::int2d");
+        double  ss =0;
+	if(VF) InternalError(" no jump or average in int1d of RHS");
+          if(di.islevelset()) // init on level set (of RHS)
+          {
+              double uset = HUGE_VAL;
+              R3 Q[4];
+              KN<double> phi(ThI.nv);phi=uset;
+              double f[4];
+              for(int t=0; t< ThI.nt;++t)
+              {
+                  
+                  double umx=-HUGE_VAL,umn=HUGE_VAL;
+                  for(int i=0;i<4;++i)
+                  {
+                      int j= ThI(t,i);
+                      if( phi[j]==uset)
+                      {
+                          MeshPointStack(stack)->setP(&ThI,t,i);
+                          phi[j]= di.levelset(stack);//zzzz
+                      }
+                      f[i]=phi[j];
+                      umx = std::max(umx,phi[j]);
+                      umn = std::min(umn,phi[j]);
+                      
+                  }
+                  if( umn <=0 && umx >= 0)
+                  {
+                      
+                      int np= IsoLineK(f,Q,1e-10);// ca code ...
+                      if(np==3 || np==4)
+                      {  //  if(np==3) Q[3]=Q[0]; // same 0 == 3 bofbof ??? FH
+                          //   cout << " Q[0]" << Q[0] << endl;
+                          if( verbosity> 99)
+                          {
+                          R3 PP[4];
+                          const Tet  &K(ThI[t]);
+                          for(int i=0; i< np; ++i)
+                              PP[i]= K(Q[i]);
+                          for( int i =0; i+1 < np; i+=2)
+                          {
+                              int i0=i,i1=i+1,i2=(i+2)%np;
+                              R3 NN= R3(PP[i0],PP[i1])^R3(PP[i0],PP[i2]);
+                              double mes2 = (NN,NN);
+                              double mes = sqrt(mes2)/2;
+                              ss+= mes;
+                              //cout << "mes " << mes << " " << i << " , ";
+                          }
+                          }
+
+                      if ( sameMesh)
+                          Element_rhs<R>(Vh[t],*l->l,buf,stack,*B,FIT,np,Q);
+                      else
+                      //    else
+                            InternalError(" No levelSet on Diff mesh3 :    to day  int2d of RHS");
+                      //    Element_rhs<R>(ThI,ThI[t],Vh,-1,lab,*l->l,buf,stack,*B,FIT,false);
+                      }
+                      if(sptrclean) sptrclean=sptr->clean();
+                  }
+              }
+              if( verbosity> 99)
+              cout << "          surf levelset = " << ss << endl;
+              
+          }
+        else
+        for( int e=0;e<ThI.nbe;e++)
+          {
+            if (all || setoflab.find(ThI.be(e).lab) != setoflab.end())   
+              {                  
+                int ie,i =ThI.BoundaryElement(e,ie);
+                if ( sameMesh) 
+                  Element_rhs<R>(Vh[i],ie,Th.be(e).lab,*l->l,buf,stack,*B,FIT,false); 
+                else 
+                  Element_rhs<R>(ThI,ThI[i],Vh,ie,Th.be(e).lab,*l->l,buf,stack,*B,FIT,false); 
+               if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr   
+              }
+	      } 
+      }
+    else if (kind==CDomainOfIntegration::intalledges)
+      {	 AFAIRE("3D Elment RHS CDomainOfIntegration::intalledges");
+       /*
+       if(VF)
+	 {
+	   pair_stack_double bstack; 
+	   
+	   bstack.first = stack;
+	   bstack.second= & binside;
+	   
+	   //InternalError(" Today no jump or average in intalledges of RHS ");
+	   for (int i=0;i< ThI.nt; i++) 
+	     if (all || setoflab.find(ThI[i].lab) != setoflab.end()) 
+	       {
+		 
+		 for (int ie=0;ie<3;ie++)
+		   if ( sameMesh) 
+		     {
+		       int iie=ie,ii=Th.ElementAdj(i,iie);	
+		       if(ii<0) ii=i;//  sur le bord	
+			      Element_rhsVF<R>(Vh[i],Vh[ii],ie,iie,Th[i].lab,*l->l,buf,ip,&bstack,*B,FIE); 
+		     }
+		   else 
+		     InternalError("To Do") ;
+		 if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+		  }
+	   
+	 }
+       else 
+	 for (int i=0;i< ThI.nt; i++) 
+	   if (all || setoflab.find(ThI[i].lab) != setoflab.end()) 
+	     {
+         for (int ie=0;ie<3;ie++)
+	   if ( sameMesh) 
+	     Element_rhs<R>(Vh[i],ie,Th[i].lab,*l->l,buf,stack,*B,FIE,true); 
+	   else 
+	     InternalError("To Do") ;
+	 if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	 }*/
+      }
+    else if (kind==CDomainOfIntegration::intallVFedges)
+      {
+	cerr << " intallVFedges a faire" << endl;
+	
+	InternalError(" intallVFedges a faire ");
+	
+	ffassert(0);/*
+      for (int i=0;i< ThI.nt; i++) 
+      {
+      if (all || setoflab.find(ThI[i].lab) != setoflab.end()) 
+         for (int ie=0;ie<3;ie++)
+	 if ( sameMesh) 
+	 Element_rhs<R>(Vh[i],ie,Th[i].lab,*l->l,buf,stack,*B,FIE,true); 
+	 else 
+                InternalError("To Do") ;
+		if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+		    
+		}*/
+      }
+    
+    else if(kind==CDomainOfIntegration::int3d) {
+        if(di.islevelset())  //  may 2014 FH ...
+        {   // int3d levelset < 0
+            double llevelset = 0;
+            const double uset = std::numeric_limits<double>::max();
+            // cout << " uset ="<<uset << endl;
+            R3 Q[3][4];
+            double vol6[3];
+            KN<double> phi(Th.nv);
+            phi=uset;
+            double f[4];
+            
+            for (int t=0;t< Th.nt; t++)
+            {
+                
+                const Mesh3::Element & K(ThI[t]);
+                if (all || setoflab.find(ThI[t].lab) != setoflab.end())
+
+                {
+                    double umx=std::numeric_limits<double>::min(),umn=std::numeric_limits<double>::max();
+                    for(int i=0;i<4;++i)
+                    {
+                        int j= ThI(t,i);
+                        if( phi[j]==uset)
+                        {
+                            MeshPointStack(stack)->setP(&ThI,t,i);
+                            phi[j]= di.levelset(stack);//zzzz
+                        }
+                        f[i]=phi[j];
+                    }
+                    int ntets= UnderIso(f,Q, vol6,1e-14);
+                    setQF<R3>(FIV,FIVo,QuadratureFormular_Tet_1, Q,vol6,ntets);
+                    if(FIV.n)
+                    {
+                    if ( sameMesh )
+                       Element_rhs<R>(Vh[t],*l->l,buf,stack,*B,FIV);
+                    else
+                        Element_rhs<R>(ThI,ThI[t],Vh,*l->l,buf,stack,*B,FIV);
+                    if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+                    
+                    }
+                 }
+            }
+          FIV=FIVo;
+        }
+        else
+        {
+      
+      for (int i=0;i< ThI.nt; i++) 
+        if (all || setoflab.find(ThI[i].lab) != setoflab.end()) 
+	  {
+	    if ( sameMesh ) 
+	      Element_rhs<R>(Vh[i],*l->l,buf,stack,*B,FIV); 
+	    else 
+	      Element_rhs<R>(ThI,ThI[i],Vh,*l->l,buf,stack,*B,FIV);
+            if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+	  }}
+    }  
+    else  if(kind==CDomainOfIntegration::intallfaces    ) {
+        
+	if(VF) InternalError(" no jump or average in intallfaces of RHS");
+        
+        for(int i=0;i<ThI.nt; i++)
+            for(int ie=0;ie<Mesh3::nea; ie++)
+        {
+            int lab=0;
+            // if face on bord get the lab ??? 
+                if ( sameMesh)
+                    Element_rhs<R>(Vh[i],ie,lab,*l->l,buf,stack,*B,FIT,false);
+                else
+                    Element_rhs<R>(ThI,ThI[i],Vh,ie,lab,*l->l,buf,stack,*B,FIT,false);
+                if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+            
+        }
+    }
+    else 
+    {
+      cout << " Strange (unknows) kind = " << kind << endl; 
+      ffassert(0);
+    }
+    if (n_where_in_stack_opt) delete [] where_in_stack;
+             
+  }
+
+
+template<class R>
+ void AssembleLinearForm(Stack stack,const Mesh & Th,const FESpace & Vh,KN_<R> * B,const  FormLinear * l )
+  {
+     StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);
+     bool sptrclean=true;
+     //     sptr->clean(); // modif FH mars 2006  clean Ptr
+    Check(l->l,Vh.N);
+    if ( B && B->N() != Vh.NbOfDF) ExecError("AssembleLinearForm size rhs and nb of DF of Vh");
+   // if ( & Th != &Vh.Th ) ExecError("AssembleLinearForm on different meshes  ( not implemented FH).");
+    KN<double> buf(Vh.MaximalNbOfDF()*last_operatortype*Vh.N*2);
+    
+    //            const  FormLinear * l=dynamic_cast<const  FormLinear *>(e);
+    const CDomainOfIntegration & di= *l->di;
+    const Mesh & ThI = Th;//* GetAny<pmesh>( (* di.Th)(stack));
+    bool sameMesh = &ThI == &Vh.Th;
+    const bool intmortar=di.intmortar(stack);
+    
+    SHOWVERB(cout << " FormLinear " << endl);
+   // const vector<Expression>  & what(di.what);
+    
+    CDomainOfIntegration::typeofkind  kind = di.kind;
+    const QuadratureFormular1d & FIE = di.FIE(stack);
+    const QuadratureFormular & FIT = di.FIT(stack);
+    const bool useopt=di.UseOpt(stack);    
+     double binside=di.binside(stack);  // truc FH pour fluide de grad2 (decentrage bizard)  
+  //  cout << "AssembleLinearForm " << l->l->v.size() << endl; 
+    set<int> setoflab;
+    bool all=true; 
+    bool VF=l->VF();  // finite Volume or discontinous Galerkin
+    if (verbosity>2) cout << "  -- AssembleLinearForm 2, discontinous Galerkin  =" << VF << " binside = "<< binside
+          << " levelset integration " <<di.islevelset()<<  "\n";
+
+    if (verbosity>3) 
+      {
+	if (CDomainOfIntegration::int1d==kind) cout << "  -- boundary int border ( nQP: "<< FIE.n << ") , samemesh :"<< sameMesh<< " int mortar: " << intmortar ;
+	else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges ( nQP: "<< FIE.n << "),"  ;
+	else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIE.n << ")," ;
+	else cout << "  --  int    (nQP: "<< FIT.n << " ) in "  ;
+      }
+    /*
+    if ( verbosity>3) 
+      if (kind==CDomainOfIntegration::int1d) cout << "  -- boundary int border " ;
+      else if (kind==CDomainOfIntegration::intalledges) cout << "  -- boundary int all edges " ;
+      else if (kind==CDomainOfIntegration::intallVFedges) cout << "  -- boundary int all edges " ;
+      else cout << "  -- boundary int  " ;
+    */
+      if(di.islevelset() && ( (CDomainOfIntegration::int1d!=kind) && (CDomainOfIntegration::int2d!=kind) )  )
+          InternalError("So no levelset integration type on no int1d/int2d case (4)");
+     Expandsetoflab(stack,di, setoflab,all);
+    /*
+    for (size_t i=0;i<what.size();i++)
+      {long  lab  = GetAny<long>( (*what[i])(stack));
+      setoflab.insert(lab);
+      if ( verbosity>3) cout << lab << " ";
+      all=false;
+      } */
+    if (verbosity>3) cout << " Optimized = "<< useopt << ", ";
+    
+    const E_F0 & optiexp0=*l->l->optiexp0;
+    // const E_F0 & optiexpK=*l->l->optiexpK;
+    int n_where_in_stack_opt=l->l->where_in_stack_opt.size();
+    R** where_in_stack =0;
+    if (n_where_in_stack_opt && useopt)
+      where_in_stack = new R * [n_where_in_stack_opt];
+    if (where_in_stack)
+      {
+	assert(l->l->v.size()==(size_t) n_where_in_stack_opt);
+	for (int i=0;i<n_where_in_stack_opt;i++)
+	  {
+	    int offset=l->l->where_in_stack_opt[i];
+	    assert(offset>10);
+	    where_in_stack[i]= static_cast<R *>(static_cast<void *>((char*)stack+offset));
+	    *(where_in_stack[i])=0;
+	  }
+	if(&optiexp0) optiexp0(stack);
+	
+	if( (verbosity/100) && verbosity % 10 == 2)
+	  {
+	    int il=0;
+
+	    for (LinearOperatorD::const_iterator ll=l->l->v.begin();ll!=l->l->v.end();ll++,il++)
+	      cout << il << " coef (" << ll->first << ") = " << *(where_in_stack[il]) << " offset=" << l->l->where_in_stack_opt[il] <<endl;
+	    
+	    for (int i=0;i<n_where_in_stack_opt;i++)
+	      cout << "const coef " << i << " = " << *(where_in_stack[i]) << endl;
+	  }
+      }
+    Stack_Ptr<R*>(stack,ElemMatPtrOffset) =where_in_stack;
+    
+      KN<int>   ip(Vh.MaxNbDFPerElement*6);
+    if (verbosity >3) 
+      {
+	if (all) cout << " all " << endl ;
+	else cout << endl;
+      }
+      if(di.islevelset() && (kind !=CDomainOfIntegration::int1d)&& (kind !=CDomainOfIntegration::int2d))
+       InternalError(" Sorry No levelSet integral for is case ..(5)");
+         
+
+    if (kind==CDomainOfIntegration::int1d)
+      {
+          
+          
+          if(VF) InternalError(" no jump or average in int1d of RHS");
+          if(di.islevelset())
+          {
+              double uset = HUGE_VAL;
+              R2 Q[3];
+              KN<double> phi(ThI.nv);phi=uset;
+              double f[3];
+              for(int t=0; t< ThI.nt;++t)
+              {
+                  double umx=-HUGE_VAL,umn=HUGE_VAL;
+                  for(int i=0;i<3;++i)
+                  {
+                      int j= ThI(t,i);
+                      if( phi[j]==uset)
+                      {
+                          MeshPointStack(stack)->setP(&ThI,t,i);
+                          phi[j]= di.levelset(stack);//zzzz
+                      }
+                      f[i]=phi[j];
+                      umx = std::max(umx,phi[j]);
+                      umn = std::min(umn,phi[j]);
+                      
+                  }
+                  if( umn <=0 && umx >= 0)
+                  {
+                      
+                      int np= IsoLineK(f,Q,1e-10);
+                      if(np==2)
+                      {
+                          if ( sameMesh)
+                          {/*
+                            void  Element_rhs(const FElement & Kv,const LOperaD &Op,double * p,void * stack,KN_<R> & B,
+                            const QuadratureFormular1d & FI ,const R2 & PA,const R2 &PB)
+                            
+                            */
+                              Element_rhs<R>(Vh[t],*l->l,buf,stack,*B,FIE,Q[0],Q[1]);
+                          }
+                          else
+                              Element_rhs<R>(ThI,ThI[t],Vh,0,ThI[t].lab,*l->l,buf,stack,*B,FIE,false,intmortar,Q);
+                              
+                              //InternalError(" No levelSet on Diff mesh :    to day  int1d of RHS");
+                      }
+                      if(sptrclean) sptrclean=sptr->clean();
+                  }
+              }
+              
+        }
+       else
+           for( int e=0;e<ThI.neb;e++)
+          {
+            if (all || setoflab.find(ThI.bedges[e].lab) != setoflab.end())
+              {                  
+                int ie,i =ThI.BoundaryElement(e,ie);
+                if ( sameMesh) 
+                  Element_rhs<R>(Vh[i],ie,Th.bedges[e].lab,*l->l,buf,stack,*B,FIE,false); 
+                else 
+                  Element_rhs<R>(ThI,ThI[i],Vh,ie,Th.bedges[e].lab,*l->l,buf,stack,*B,FIE,false,intmortar); 
+               if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr   
+              }
+          }
+      }
+    else if (kind==CDomainOfIntegration::intalledges)
+     {	
+      if(VF)
+        {
+	    pair_stack_double bstack(stack,& binside);
+	    
+	    //bstack.first = stack;
+	    //bstack.second= & binside;
+	    
+	    //InternalError(" Today no jump or average in intalledges of RHS ");
+	    for (int i=0;i< ThI.nt; i++) 
+		if (all || setoflab.find(ThI[i].lab) != setoflab.end()) 
+		  {
+		      
+		      for (int ie=0;ie<3;ie++)
+			  if ( sameMesh) 
+			    {
+			      int iie=ie,ii=Th.ElementAdj(i,iie);	
+			       if(ii<0) ii=i;//  sur le bord	
+			      Element_rhsVF<R>(Vh[i],Vh[ii],ie,iie,Th[i].lab,*l->l,buf,ip,&bstack,*B,FIE); 
+			    }
+			  else 
+			      InternalError("To Do") ;
+		      if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+		  }
+	    
+	}
+      else 
+      for (int i=0;i< ThI.nt; i++) 
+        if (all || setoflab.find(ThI[i].lab) != setoflab.end()) 
+         {
+         for (int ie=0;ie<3;ie++)
+            if ( sameMesh) 
+                Element_rhs<R>(Vh[i],ie,Th[i].lab,*l->l,buf,stack,*B,FIE,true); 
+             else 
+                InternalError("To Do") ;
+          if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+          }
+     }
+    else if (kind==CDomainOfIntegration::intallVFedges)
+     {
+      cerr << " intallVFedges a faire" << endl;
+
+      InternalError(" intallVFedges a faire ");
+	 
+      ffassert(0);
+      for (int i=0;i< ThI.nt; i++) 
+        {
+	  if (all || setoflab.find(ThI[i].lab) != setoflab.end()) 
+	    for (int ie=0;ie<3;ie++)
+	      { 
+		if ( sameMesh) 
+		  Element_rhs<R>(Vh[i],ie,Th[i].lab,*l->l,buf,stack,*B,FIE,true); 
+		else 
+		  InternalError("To Do") ;
+	      }
+	  if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+        }
+     }
+     
+    else if (kind==CDomainOfIntegration::int2d){
+        if(di.islevelset())
+        {
+            QuadratureFormular FITM(FIT);
+            double uset = HUGE_VAL;
+            R2 Q[4];
+            KN<double> phi(Th.nv);phi=uset;
+            double f[3];
+            for(int t=0; t< Th.nt;++t)
+            {
+                if ( all || setoflab.find(ThI[t].lab) != setoflab.end())
+                {
+                    double umx=-HUGE_VAL,umn=HUGE_VAL;
+                    for(int i=0;i<3;++i)
+                    {
+                        int j= ThI(t,i);
+                        if( phi[j]==uset)
+                        {
+                            MeshPointStack(stack)->setP(&ThI,t,i);
+                            phi[j]= di.levelset(stack);//zzzz
+                        }
+                        f[i]=phi[j];
+                        umx = std::max(umx,phi[j]);
+                        umn = std::min(umn,phi[j]);
+                        
+                    }
+                    if( umx <=0 )
+                        Element_rhs<R>(Vh[t],*l->l,buf,stack,*B,FIT);
+                    else if( umn <0 )
+                    { // coupe ..
+                        int i0 = 0, i1 = 1, i2 =2;
+                        
+                        if( f[i0] > f[i1] ) swap(i0,i1) ;
+                        if( f[i0] > f[i2] ) swap(i0,i2) ;
+                        if( f[i1] > f[i2] ) swap(i1,i2) ;
+                        
+                        double c = (f[i2]-f[i1])/(f[i2]-f[i0]); // coef Up Traing
+                        if( f[i1] < 0 ) {double y=f[i2]/(f[i2]-f[i1]); c *=y*y; }
+                        else {double y=f[i0]/(f[i0]-f[i1]) ; c = 1.- (1.-c)*y*y; };
+                        assert( c > 0 && c < 1);
+                        double arean = (1-c)*Th[t].area;
+                        FITM=FIT;
+                        FITM*=1-c;
+                        Element_rhs<R>(Vh[t],*l->l,buf,stack,*B,FITM);
+                    }
+                    if(sptrclean) sptrclean=sptr->clean();
+                }
+            }
+        }
+        else
+            for (int i=0;i< ThI.nt; i++)
+                if (all || setoflab.find(ThI[i].lab) != setoflab.end())
+                {
+                    if ( sameMesh )
+                        Element_rhs<R>(Vh[i],*l->l,buf,stack,*B,FIT);
+                    else
+                        Element_rhs<R>(ThI,ThI[i],Vh,*l->l,buf,stack,*B,FIT);
+                    if(sptrclean) sptrclean=sptr->clean(); // modif FH mars 2006  clean Ptr
+                }
+    }
+      
+      if (n_where_in_stack_opt) delete [] where_in_stack;
+      
+  }
+    
+  
+}// END of NameSpace Fem2D
+
+
+bool isVF(const list<C_F0> & largs)  // true => VF type of Matrix   
+{
+  list<C_F0>::const_iterator ii,ib=largs.begin(),
+    ie=largs.end();
+    
+  bool VVF =false;   
+  for (ii=ib;ii != ie;ii++)
+    {
+      Expression e=ii->LeftValue();
+      aType r = ii->left();
+      if (r==atype<const  FormBilinear *>()) 
+        {
+          const  FormBilinear * bb=dynamic_cast<const  FormBilinear *>(e);
+          bool vvf  = bb->VF();
+          if( vvf &&  (bb->di->kind != CDomainOfIntegration::intalledges && bb->di->kind != CDomainOfIntegration::intallVFedges  )
+             &&  (bb->di->kind != CDomainOfIntegration::intallfaces ))
+            CompileError("Sorry, no  jump or moy in bilinear form no of type intalledges or intallVFedges ");
+           VVF = vvf || VVF;
+          }
+    }
+  return VVF;
+} 
+
+
+bool isSameMesh(const list<C_F0> & largs,const void * Thu,const void * Thv,Stack stack)  // true => VF type of Matrix   
+{
+  if( Thv != Thu ) return false;
+  list<C_F0>::const_iterator ii,ib=largs.begin(),
+    ie=largs.end();
+    
+  // bool VVF =false;   
+  for (ii=ib;ii != ie;ii++)
+    {
+      Expression e=ii->LeftValue();
+      aType r = ii->left();
+      if (r==atype<const  FormBilinear *>()) 
+        {
+          const  FormBilinear * bb=dynamic_cast<const  FormBilinear *>(e);
+          const void *  Thbf = GetAny<const void *>((*bb->di->Th)(stack));
+          if (Thbf != Thu) return false;
+          }
+      else if (r==atype<const  FormLinear *>()) 
+        {
+          const  FormLinear * bb=dynamic_cast<const  FormLinear *>(e);
+          const void * Thbf = GetAny<const void *>((*bb->di->Th)(stack));
+          if (Thbf != Thu) return false;
+          }
+    }
+  return true;
+} 
+
+template<class R,class FESpace,class v_fes>
+void InitProblem( int Nb, const FESpace & Uh,
+                               const FESpace & Vh,
+		  KN<R> *&B,KN<R> *&X,vector<  pair< FEbase<R,v_fes> * ,int> > &u_hh,
+                 TypeSolveMat    *typemat ,
+		  vector<  FEbase<R,v_fes> *  > & u_h,const FESpace ** LL, bool initx )
+{
+    typedef typename  FESpace::Mesh Mesh;
+    typedef typename  FESpace::FElement FElement;
+    typedef typename  Mesh::Element Element;
+    typedef typename  Mesh::Vertex Vertex;  
+    typedef typename  Mesh::RdHat RdHat;  
+    typedef typename  Mesh::Rd Rd;  
+    
+  *B=R();
+  
+//  bool initx = typemat->t==TypeSolveMat::GC;
+  
+  const  Mesh & Th(Uh.Th);
+  
+  if (initx) 
+    {
+      if (!X || (X =B) )
+        X=new KN<R>(B->N());
+      const FEbase<R,v_fes> & u_h0 = *(u_h[0]);
+      const FESpace  * u_Vh = &*u_h0.Vh ;
+      
+      if ( u_Vh==0  || &(*(u_h[0])).Vh->Th != &Th )
+        {
+          *X=R();
+          if(verbosity>1)
+            cout << "   -- Change of Mesh " << (u_Vh ? & (*(u_h[0])).Vh->Th: 0 ) 
+                 << "  " << &Th <<  endl;
+        }
+      else
+        { //  copy the previous soluton to initialize CG, GMRES, etc ...
+          if (Nb==1) 
+	    {  // modif  FH 0701/2005 + april 2006 
+	    if(u_h[0]->x()->N() != X->N() )
+	      cout << " bug ???? " << endl;
+	    if (u_h[0]->x() && u_h[0]->x()->N() == X->N() )
+	      *X= * u_h[0]->x();
+	    else
+	      *X=R();
+	    }
+          else { // dispatch the solution  
+            const FElement ** sK= new const FElement * [Nb];  
+            KN<R> ** sol= new KN<R> * [Nb];
+            for (int i=0;i<Nb;i++) {
+              
+              sol[i] = (*(u_h[i])).x() ;
+            }
+            
+            for (int it=0;it<Th.nt;it++)
+              {
+                const FElement K(Uh[it]);
+                const int nbdf=K.NbDoF();
+                for (int i=0;i<Nb;i++)
+                  sK[i]= new FElement( (*LL[i])[it]) ;
+                for (int df=0;df< nbdf;df++)
+                  {  int kfe=K.FromFE(df);
+                  int kdf=K.FromDF(df);
+                  if (sol[kfe]) {
+                     const FElement & SK(*sK[kfe]);
+                     (*X)[K(df)]= (*sol[kfe])[SK(kdf)] ;
+                    }
+                   else (*X)[K(df)]= R();
+                  }
+                for (int i=0;i<Nb;i++)
+                  delete sK[i];        
+              }
+            delete [] sol;
+            delete [] sK; 
+          }}
+    }
+
+
+} 
+
+template<class R>
+void DefSolver(Stack stack, MatriceCreuse<R>  & A, Data_Sparse_Solver & ds )
+{
+    const OneOperator* pprecon= static_cast<const OneOperator*>(ds.precon);
+    if (ds.typemat->profile)
+      {
+        if(verbosity>5) cout << " Matrix skyline type:" << ds.typemat->t <<endl;
+        MatriceProfile<R> & AA(dynamic_cast<MatriceProfile<R> &>(A));
+        throwassert(&AA);
+        double tol_pivot1= (ds.tol_pivot>0.) ? ds.tol_pivot : EPSILON/8.;
+       // cout << " tol_pivot1 " <<tol_pivot1 <<  endl; auto_ptr
+        switch (ds.typemat->t) {
+        case TypeSolveMat::LU       : AA.LU(tol_pivot1); break;
+        case TypeSolveMat::CROUT    : AA.crout(tol_pivot1); break;
+        case TypeSolveMat::CHOLESKY : AA.cholesky(tol_pivot1); break;
+        default:
+          cerr << " type resolution " << ds.typemat->t << endl;
+          CompileError("type resolution profile inconnue"); break;       
+        }
+      }
+    else 
+      {
+        if(verbosity>5) cout << " Matrix morse type:" << ds.typemat->t <<endl;
+	MatriceMorse<R> & AA(dynamic_cast<MatriceMorse<R> &>(A));
+        throwassert(&A);
+        switch (ds.typemat->t) {
+        case    TypeSolveMat::GC:   
+          if (ds.precon)
+            AA.SetSolverMaster(new SolveGCPrecon<R>(AA,pprecon,stack,ds.itmax,ds.epsilon));
+          else 
+            AA.SetSolverMaster(new SolveGCDiag<R>(AA,ds.itmax,ds.epsilon));
+          break; 
+        case TypeSolveMat::GMRES :
+          if (ds.precon)
+            AA.SetSolverMaster(new SolveGMRESPrecon<R>(AA,pprecon,stack,ds.NbSpace,ds.itmax,ds.epsilon));
+          else 
+            AA.SetSolverMaster(new SolveGMRESDiag<R>(AA,ds.NbSpace,ds.itmax,ds.epsilon));
+         break;
+	 //#ifdef HAVE_LIBUMFPACK         
+        case TypeSolveMat::SparseSolver :
+	  AA.SetSolverMaster(DefSparseSolver<R>::Build(stack,&AA,ds));
+//           AA.SetSolverMaster(new SolveUMFPack<R>(AA,umfpackstrategy,tgv,eps,tol_pivot,tol_pivot_sym));
+         break;
+        case TypeSolveMat::SparseSolverSym :
+                AA.SetSolverMaster(DefSparseSolverSym<R>::Build(stack,&AA,ds));
+                //           AA.SetSolverMaster(new SolveUMFPack<R>(AA,umfpackstrategy,tgv,eps,tol_pivot,tol_pivot_sym));
+                break;
+          
+//#endif         
+        default:
+          cerr << " type resolution " << ds.typemat->t << endl;
+          CompileError("type resolution inconnue"); break;       
+        }
+        
+      }
+  }  
+
+bool SetGMRES()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse (morse) solver to GMRES" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverGMRES;
+    DefSparseSolver<Complex>::solver =BuildSolverGMRES; 
+    return true;
+}
+
+bool SetCG()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse (morse) solver to CG" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverCG;
+    DefSparseSolver<Complex>::solver =BuildSolverCG; 
+    return true;
+}
+
+#ifdef XXXXXXXXXXX
+#ifdef HAVE_LIBUMFPACK
+bool SetUMFPACK()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to UMFPack" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverUMFPack;
+    DefSparseSolver<Complex>::solver =BuildSolverUMFPack;  
+    return true;
+}
+
+template <>
+DefSparseSolver<double>::SparseMatSolver  DefSparseSolver<double>::solver =BuildSolverUMFPack;
+template <>
+DefSparseSolver<Complex>::SparseMatSolver  DefSparseSolver<Complex>::solver =BuildSolverUMFPack;
+
+#else
+template <>
+DefSparseSolver<double>::SparseMatSolver  DefSparseSolver<double>::solver =BuildSolverGMRES;
+template <>
+DefSparseSolver<Complex>::SparseMatSolver  DefSparseSolver<Complex>::solver =BuildSolverGMRES;
+
+bool SetUMFPACK()
+{
+    if(verbosity>1)
+	cout << " Sorry no UMFPack" << endl;
+    return false;
+}
+
+#endif
+#endif
+template <>
+DefSparseSolverSym<double>::SparseMatSolver  DefSparseSolverSym<double>::solver =BuildSolverGMRES;
+template <>
+DefSparseSolverSym<Complex>::SparseMatSolver  DefSparseSolverSym<Complex>::solver =BuildSolverGMRES;
+
+ 
+template<class R>
+ MatriceCreuse<typename CadnaType<R>::Scalaire> * DefSolverCadna(
+  Stack stack,
+  MatriceCreuse<R>  & A,
+  Data_Sparse_Solver & ds
+/*  long NbSpace , 
+  long itmax, 
+  double & eps,
+  bool initmat,
+  int strategy,
+  const OneOperator *precon,
+  double tgv,
+  double tol_pivot, double tol_pivot_sym
+*/
+)
+{
+   typedef typename CadnaType<R>::Scalaire R_st;
+ //  MatriceCreuse<R_st> *CadnaMat;
+    if (ds.typemat->profile)
+      {
+        if(verbosity>5) cout << " Matrix skyline type:" << ds.typemat->t <<endl;
+        MatriceProfile<R> & AAA(dynamic_cast<MatriceProfile<R> &>(A));
+        MatriceProfile<R_st> &AA(*new MatriceProfile<R_st>(AAA)); // 
+        
+        throwassert(&AA);
+        double tol_pivot1= (ds.tol_pivot>0) ? ds.tol_pivot : EPSILON/8.;
+       // cout << " tol_pivot1 " <<tol_pivot1 <<  endl;
+        switch (ds.typemat->t) {
+        case TypeSolveMat::LU       : AA.LU(tol_pivot1); break;
+        case TypeSolveMat::CROUT    : AA.crout(tol_pivot1); break;
+        case TypeSolveMat::CHOLESKY : AA.cholesky(tol_pivot1); break;
+        default:
+          cerr << " type resolution " << ds.typemat->t << endl;
+          CompileError("type resolution profile inconnue"); break;       
+        }
+        return &AA;
+      }
+    else 
+      {
+         ExecError("matrix morse & CADNA are incompatible today, sorry!");
+         return 0;
+      }
+   return 0;   
+  }      
+  
+template<class R,class FESpace,class v_fes>   
+void   DispatchSolution(const typename FESpace::Mesh & Th,int Nb, vector<  FEbase<R,v_fes> * > & u_h,KN<R> * X,KN<R> * B,const FESpace **  LL,const FESpace &  Uh)
+  {
+      typedef typename  FESpace::Mesh Mesh;
+      typedef typename  FESpace::FElement FElement;
+      typedef typename  Mesh::Element Element;
+      typedef typename  Mesh::Vertex Vertex;  
+      typedef typename  Mesh::RdHat RdHat;  
+      typedef typename  Mesh::Rd Rd;  
+      
+   // dispatch the solution 
+  if (Nb==1)  {
+    *(u_h[0])=X;
+    if (X != B ) delete B;  }
+  else {
+    const FElement ** sK= new const FElement * [Nb];
+    
+    KN<R> ** sol= new KN<R> * [Nb];
+    for (int i=0;i<Nb;i++) {
+      sol[i]= new KN<R>( LL[i]->NbOfDF) ;
+      *(u_h[i]) = sol[i];
+    }
+    
+    for (int it=0;it<Th.nt;it++)
+      {
+        const FElement K(Uh[it]);
+        const int nbdf=K.NbDoF();
+        for (int i=0;i<Nb;i++)
+          sK[i]= new FElement( (*LL[i])[it]) ;
+        for (int df=0;df< nbdf;df++)
+          {  int kfe=K.FromFE(df);
+          int kdf=K.FromDF(df);
+          const FElement & SK(*sK[kfe]);
+          (*sol[kfe])[SK(kdf)] = (*X)[K(df)];
+          }
+        for (int i=0;i<Nb;i++)
+          delete sK[i];
+        
+      }
+    
+     delete [] sK;
+     delete [] sol;
+     if (X != B && X ) delete X; 
+     delete B; 
+  }
+  }
+
+#ifdef HAVE_LIBUMFPACK   
+TypeSolveMat::TSolveMat  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+#else
+TypeSolveMat::TSolveMat  TypeSolveMat::defaultvalue=TypeSolveMat::LU;
+#endif
+
+
+template<class R,class FESpace,class v_fes>
+AnyType Problem::eval(Stack stack,Data<FESpace> * data,CountPointer<MatriceCreuse<R> > & dataA, 
+      MatriceCreuse< typename CadnaType<R>::Scalaire >   * & cadnamat ) const
+{  
+    typedef typename  FESpace::Mesh Mesh;
+    typedef typename  FESpace::FElement FElement;
+    typedef typename  Mesh::Element Element;
+    typedef typename  Mesh::Vertex Vertex;  
+    typedef typename  Mesh::RdHat RdHat;  
+    typedef typename  Mesh::Rd Rd;  
+    
+  using namespace Fem2D;
+  typedef typename CadnaType<R>::Scalaire R_st;
+  MeshPoint *mps= MeshPointStack(stack),mp=*mps;
+    Data_Sparse_Solver ds;
+ /* long NbSpace = 50; 
+  long itmax=0; 
+  double epsilon=1e-6;*/
+  string save;
+    
+//  bool VF=false;
+//  VF=isVF(op->largs);
+ // assert(!VF); 
+//  double tgv = 1e30;
+// type de matrice par default
+    TypeSolveMat tmat(TypeSolveMat::defaultvalue); 
+     
+   ds.typemat=&tmat;
+ // bool initmat=true;
+/*
+    int strategy=0;
+  double tol_pivot=-1.; // defaut UMFPACK value  Add FH 31 oct 2005 
+  double tol_pivot_sym=-1.; // defaut Add FH 31 oct 2005 
+  
+  KN<int> param_int;
+  KN<double> param_double; 
+  string *param_char = NULL;
+  KN<int> perm_r; 
+  KN<int> perm_c;
+  string *file_param_int;  // Add J. Morice 02/09 
+  string *file_param_double; 
+  string* file_param_char;
+  string* file_param_perm_r;
+  string* file_param_perm_c;  
+*/
+  KN<double>* cadna=0; 
+/*
+ {  "save",&typeid(string* )}, 0
+ {  "cadna",&typeid(KN<double>*)}, 1
+ {  "bmat",&typeid(Matrice_Creuse<R>* )}, 2
+ 
+ */
+ if (nargs[0]) save = *GetAny<string*>((*nargs[0])(stack));
+ if (nargs[1]) cadna= GetAny<KN<double>* >((*nargs[1])(stack));   
+  // bmat not used .... bizarre  
+/*    
+  if (nargs[0]) ds.initmat= ! GetAny<bool>((*nargs[0])(stack));
+  if (nargs[1]) ds.typemat= GetAny<TypeSolveMat *>((*nargs[1])(stack));
+  if (nargs[2]) ds.epsilon= GetAny<double>((*nargs[2])(stack));
+  // 3 precon 
+  if (nargs[4]) ds.NbSpace= GetAny<long>((*nargs[4])(stack));
+  if (nargs[6]) ds.tgv= GetAny<double>((*nargs[6])(stack));
+  if (nargs[7]) ds.strategy = GetAny<long>((*nargs[7])(stack));
+  if (nargs[8]) save = *GetAny<string*>((*nargs[8])(stack));
+  if (nargs[9]) cadna= GetAny<KN<double>* >((*nargs[9])(stack));
+*/
+/*
+  if (nargs[10]) ds.tol_pivot= GetAny<double>((*nargs[10])(stack));
+  if (nargs[11]) ds.tol_pivot_sym= GetAny<double>((*nargs[11])(stack));
+  if (nargs[12]) ds.itmax = GetAny<long>((*nargs[12])(stack)); //  fevr 2007
+
+  if (nargs[13]) ds.param_int= GetAny< KN<int> >((*nargs[13])(stack));  // Add J. Morice 02/09 
+  if (nargs[14]) ds.param_double= GetAny< KN<double> >((*nargs[14])(stack));
+  if (nargs[15]) ds.param_char= GetAny< string * >((*nargs[15])(stack));  //
+  if (nargs[16]) ds.perm_r = GetAny< KN<int > >((*nargs[16])(stack));
+  if (nargs[17]) ds.perm_c = GetAny< KN<int> >((*nargs[17])(stack));  //
+  if (nargs[18]) ds.file_param_int= GetAny< string* >((*nargs[18])(stack));  // Add J. Morice 02/09 
+  if (nargs[19]) ds.file_param_double= GetAny< string* > ((*nargs[19])(stack));
+  if (nargs[20]) ds.file_param_char= GetAny< string* >((*nargs[20])(stack));  //
+  if (nargs[21]) ds.file_param_perm_r = GetAny< string* >((*nargs[21])(stack));
+  if (nargs[22]) ds.file_param_perm_c = GetAny< string* >((*nargs[22])(stack));  //
+ */
+    SetEnd_Data_Sparse_Solver<R>(stack,ds,nargs,n_name_param);
+
+
+  //  for the gestion of the PTR. 
+  WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH aout 2007 
+
+  bool sym = ds.typemat->sym;
+  
+  list<C_F0>::const_iterator ii,ib=op->largs.begin(),
+    ie=op->largs.end();
+  int Nbcomp2=var.size(),Nbcomp=Nbcomp2/2; // nb de composante 
+  throwassert(Nbcomp2==2*Nbcomp);
+//  Data *data= dataptr(stack);
+  //   data->init();
+  KN<int>  which_comp(Nbcomp2),which_uh(Nbcomp2);
+  
+  TabFuncArg tabexp(stack,Nbcomp);
+  typedef pair< FEbase<R,v_fes> *,int> pfer;
+  vector< pair< FEbase<R,v_fes> *,int> > u_hh(Nbcomp2); 
+  for (size_t i=0;i<var.size();i++)
+    u_hh[i] = GetAny< pfer  >( (*(var[i]))(stack));
+  for (size_t i=0;i<var.size();i++)
+    u_hh[i].first->newVh(); 
+  //   compression pour les cas vectoriel
+  int kkk=0;
+  for (int i=0;i<Nbcomp2;i++)
+    {
+      if ( u_hh[i].second==0) 
+        kkk++;
+      else {          
+        throwassert(u_hh[i].second==(u_hh[i-1].second+1));}
+      which_uh[i]=kkk-1;  
+      which_comp[i]=u_hh[i].second;  
+    }
+  
+  vector<  FEbase<R,v_fes> * > u_h(kkk); 
+  kkk= 0;
+  for (int i=0;i<Nbcomp2;i++)
+    if ( u_hh[i].second==0) u_h[kkk++]=u_hh[i].first;
+  const int  Nb2 = kkk, Nb=Nb2/2; // nb of FESpace 
+  throwassert(Nb2==2*Nb);
+  
+  //const FESpace ** LL = new  const FESpace *[var.size()];
+  KN<const FESpace *> LL(var.size());
+  for (int i=0;i<Nb2;i++)
+    LL[i]= (*(u_h[i])).newVh();
+  SHOWVERB(cout << "Problem  " << Nb << endl);
+  
+  //   const de  
+  
+  //  const FESpace * Uhh , *Vhh;
+  const Mesh * pTh= &LL[0]->Th;
+  for (int i=0;i<Nb2;i++)
+    if ( &LL[i]->Th != pTh)
+      ExecError("all the finites elements spaces must be defined on the same mesh in solve");
+  if ( pTh != data->pTh ) 
+    {
+       ds.initmat = true;
+       data->pTh=pTh;
+       if (Nb==1) 
+         { //  cas scalaire
+           data->Uh=LL[0];
+           data->Vh=LL[1]; }
+       else 
+         { //  cas vectoriel 
+           bool same=true;
+           for (int i=0;i<Nb;i++)
+             if ( LL[i] != LL[Nb+i] )
+               {
+                 same = false;
+                 break;
+               }
+           if(!same)
+             InternalError("Methode de Galerkine (a faire)");
+           else
+             {
+               
+               bool unique=true;
+               for (int i=1;i<Nb;i++)
+                 if ( LL[0] != LL[i]) 
+                   {
+                     unique = false;
+                     break;
+                   }
+               if (unique) 
+                 data->Uh.master( new FESpace(*LL[0],Nb));
+               else 
+                 data->Uh.master(new FESpace(LL,Nb));
+               data->Vh=data->Uh;
+             }
+           
+         }
+    }          
+               
+  const FESpace & Uh(*data->Uh);    
+  const FESpace & Vh(*data->Vh);
+  throwassert(Nbcomp==Uh.N && Nbcomp==Vh.N); 
+  KN<R> *B=new KN<R>(Vh.NbOfDF);
+  KN<R> *X=B; //
+  const  Mesh & Th(Uh.Th);
+  bool initx = true; //typemat->t==TypeSolveMat::GC ; //  make x and b different in all case 
+  // more safe for the future ( 4 days lose with is optimization FH )
+
+  InitProblem<R,FESpace,v_fes>(  Nb,  Uh, Vh, B, X,u_hh,ds.typemat , u_h,  LL,  initx);
+
+  if(verbosity>2) cout << "   Problem(): initmat " << ds.initmat << " VF (discontinuous Galerkin) = " << VF << endl;
+  
+
+  
+  if (ds.initmat) 
+   {
+    if (ds.typemat->profile) 
+      {
+      dataA.master(new MatriceProfile<R>(Vh,VF));      
+      }
+    else 
+      {
+        if ( &Uh == & Vh )
+          dataA.master(new MatriceMorse<R>(Vh,sym,VF));
+        else 
+          dataA.master(new MatriceMorse<R>(Vh,Uh,VF));
+      }
+      MatriceCreuse<R>  & AA(dataA);
+     if(verbosity>1) cout <<  "   -- size of Matrix " << AA.size()<< " Bytes" << " skyline =" <<ds.typemat->profile << endl;
+    }
+  MatriceCreuse<R>  & A(dataA);
+  if  (AssembleVarForm( stack,Th,Uh,Vh,sym, ds.initmat ? &A:0 , B, op->largs)) 
+    { 
+      *B = - *B; 
+      // hach FH 
+      for (int i=0, n= B->N(); i< n; i++)
+        if( abs((*B)[i]) < 1.e-60 ) (*B)[i]=0;
+        
+      AssembleBC<R,FESpace>     ( stack,Th,Uh,Vh,sym, ds.initmat ? &A:0 , B, initx ? X:0,  op->largs, ds.tgv );
+    }
+  else 
+    *B = - *B;
+  MatriceCreuse<R_st>  * ACadna = 0;
+  
+  
+  try {  
+  
+  if (ds.initmat)
+    {
+      if(cadna)
+	ACadna = DefSolverCadna( stack,A, ds);
+      else
+	DefSolver(stack,  A, ds);
+    }
+
+
+      
+ // if(verbosity>3) cout << "   B  min " << B->min() << " ,  max = " << B->max() << endl;
+  if( save.length() )
+  {
+      string savem=save+".matrix";
+      string saveb=save+".b";
+    {
+     ofstream outmtx( savem.c_str());
+     outmtx << A << endl;
+    }  
+    {
+     ofstream outb(saveb.c_str());
+     outb<< *B << endl;
+    }  
+     
+  }
+  if (verbosity>99)
+   {
+    cout << " X= " << *X << endl;
+    cout << " B= " << *B << endl;
+    }
+    
+   if(ACadna)  
+    {
+     KN<R_st> XX(*X);
+     KN<R_st> BB(*B);
+     ACadna->Solve(XX,BB);
+     *X=XX;
+     *cadna =-1.;            
+
+#ifdef HAVE_CADNA     
+     R_st xxmin = XX.min();
+     R_st xxmax = XX.max();
+     cout  << "    cadna:      min " <<  xxmin << "/ nd " << cestac(xxmin) 
+	   << " ,   max " << xxmax << " / nd " << cestac(xxmax)   << endl ;
+     int nn= XX.N();
+     if ( cadna->N() == nn )
+       for (int i=0;i<nn;++i)
+         (*cadna)[i] = cestac(XX[i]);
+     else
+       cerr << "Warning: Sorry array is incorrect size to store cestac " 
+	    << nn << " != " << cadna->N() << endl;
+#endif
+    }
+  else
+    
+    A.Solve(*X,*B);
+   
+    if (verbosity>99)
+    {
+      cout << " X= " << *X << endl;
+     }
+    }
+   catch (...)
+   {
+     if(verbosity) cout << " catch an erreur in  solve  =>  set  sol = 0 !!!!!!! "   <<  endl;
+     *X=R(); // erreur set the sol of zero ???? 
+     DispatchSolution<R,FESpace,v_fes>(Th,Nb,u_h,X,B,LL,Uh);
+     throw ; 
+   }
+   DispatchSolution<R,FESpace,v_fes>(Th,Nb,u_h,X,B,LL,Uh);
+  
+ 
+  if (verbosity) 
+    {cout << "  -- Solve : \n" ; 
+    for (int i=0;i<Nb;i++) 
+      cout  << "          min " << (u_h[i])->x()->min() << "  max " << (u_h[i])->x()->max() << endl ;
+    }
+    
+ // delete [] LL;
+ // if (save) delete save; // clean memory
+  *mps=mp;
+  return SetAny<const Problem *>(this);
+}
+
+
+
+int dimProblem(const ListOfId &l)
+{
+    int dim=2;
+    int nb=l.size();//,nbarray=0;//,n=0,
+    //const UnId *p1;
+    if(nb>0) 
+      {
+	  if (l[0].array) 
+	    {
+		ListOfId * array=l[0].array;
+		if(array->size()>0)
+		  {
+		      const UnId & idi( (*array)[0]);
+		      if (idi.r == 0 && idi.re  == 0 && idi.array==0 ) 
+			{
+			    C_F0 c=::Find( idi.id);
+			    if(BCastTo<pf3c>(c) ) dim=3;
+			    if(BCastTo<pf3r>(c) ) dim=3;	
+			}
+		  }
+	    }
+	  else 
+	    {
+		C_F0 c=::Find(l[0].id);
+		if(BCastTo<pf3c>(c) ) dim=3;
+		if(BCastTo<pf3r>(c) ) dim=3;	  
+	    }
+	  
+      }
+    return dim;
+    
+}
+template<class pfer,class pfec>
+bool GetBilinearParam(const ListOfId &l,basicAC_F0::name_and_type *name_param,int n_name_param,
+                      Expression *nargs,int & N,int & M,  vector<Expression> & var )
+{
+  bool unset=true,complextype=false;
+  
+  for (int i=0;i<n_name_param;i++)
+    nargs[i]=0;
+  int nb=l.size(),n=0,nbarray=0;
+  ListOfId * array[2];
+  for (int i=0;i<nb;i++)
+    if (l[i].r == 0 && l[i].re  == 0 && l[i].array == 0) 
+      n++;
+       else if (l[i].array) array[Min(nbarray++,1)] = l[i].array;
+    else 
+      {  
+        bool ok=false;
+        for (int j=0;j<n_name_param;j++)
+          if (!strcmp(l[i].id,name_param[j].name))
+            {
+              ok = !nargs[j];
+              nargs[j]= map_type[name_param[j].type->name()]->CastTo(C_F0(l[i].e,l[i].re));
+              break;
+            }
+        if (!ok) 
+          {
+            cerr << " Error name argument " << l[i].id << " the kown arg : "; 
+            for (int k=0;k<n_name_param;k++)
+              cerr << name_param[k].name << " ";
+            cerr << endl;
+                 CompileError("Unkown name argument or two times same name argument ");
+          }
+      }
+  
+  if (nbarray)
+    { // new version ok
+      if(nbarray!=2) 
+        CompileError(" Must have 2 array, one for unknow functions, one for test functions");
+      N = array[0]->size();
+      M = array[1]->size();
+      var.resize(N+M);
+      for (size_t k=0,j=0;k<2;k++)
+        for  (size_t i=0;i<array[k]->size();i++)
+          { 
+            const UnId & idi((*array[k])[i]);
+            if (idi.r == 0 && idi.re  == 0 && idi.array==0 ) 
+              { C_F0 c=::Find( idi.id);
+              if (unset) 
+                complextype =  BCastTo<pfec>(c) , unset=false;
+
+              if(complextype) 
+              var[j++]=CastTo<pfec>(c);
+              else 
+              var[j++]=CastTo<pfer>(c);
+               }         
+            else 
+              CompileError(" Just Variable in array parameter ");   
+          }   
+    }
+  else
+    { // old version
+      assert(n%2==0);
+      N=n/2;
+      M=N; 
+      var.resize(N+M);
+      for  (size_t i=0,j=0;i<l.size();i++)
+        if (l[i].r == 0 && l[i].re  == 0 && l[i].array==0 ) 
+          {
+            C_F0 c=::Find(l[i].id);
+              if (unset) 
+                complextype =  BCastTo<pfec>(c) , unset=false;
+              if(complextype) 
+              var[j++]=CastTo<pfec>(c);
+              else 
+              var[j++]=CastTo<pfer>(c);
+         } 
+      
+    }
+  return complextype;
+}
+
+ 
+/*
+int DimForm( list<C_F0> & largs) 
+{
+  int dim=0;
+  list<C_F0>::iterator ii,ib=largs.begin(),
+    ie=largs.end();
+  for (ii=ib;ii != ie;ii++)
+    {
+      Expression e=ii->LeftValue();
+      aType r = ii->left();
+      if (r==atype<const  FormBilinear *>())
+        {
+          const  FormBilinear * bb=dynamic_cast<const  FormBilinear *>(e);
+	  if(dim) ffassert(bb->d==dim); 
+	  else 
+	    dim=bb->d;
+	}
+      else if (r==atype<const  FormLinear *>())
+        {
+          const  FormLinear * ll=dynamic_cast<const  FormLinear *>(e);
+	  if(dim) ffassert(bb->d==dim); 
+	  else 
+	    dim=bb->d;
+
+        }
+      else if (r == atype<const  BC_set *>())
+	{
+          const  BC_set * bc=dynamic_cast<const  BC_set *>(e);
+          if (bc->complextype)  complextype=true;
+
+	}
+    }
+
+    }*/
+bool FieldOfForm( list<C_F0> & largs ,bool complextype)  // true => complex problem 
+{
+  //  bool   iscomplextype=complextype;
+  list<C_F0>::iterator ii,ib=largs.begin(),
+    ie=largs.end();
+ // bool complextype =false;   
+  for (ii=ib;ii != ie;ii++)
+    {
+      Expression e=ii->LeftValue();
+      aType r = ii->left();
+      if (r==atype<const  FormBilinear *>()) 
+        {
+          const  FormBilinear * bb=dynamic_cast<const  FormBilinear *>(e);
+          if (! bb->b->mappable(BCastToR)) 
+            complextype=true;
+          }
+      else if (r==atype<const  FormLinear *>())
+        {
+          const  FormLinear * ll=dynamic_cast<const  FormLinear *>(e);
+          if (! ll->l->mappable(BCastToR)) 
+            complextype=true;
+        }
+      else if (r == atype<const  BC_set *>())
+       {
+          const  BC_set * bc=dynamic_cast<const  BC_set *>(e);
+          if (bc->complextype)  complextype=true;
+
+       }
+    }
+   
+  for (ii=ib;ii != ie;ii++)
+    {
+      Expression e=ii->LeftValue();
+      aType r = ii->left();
+      if (r==atype<const  FormBilinear *>()) 
+        {
+          FormBilinear * bb=new FormBilinear(*dynamic_cast<const FormBilinear *>(e));
+          Foperator * b=const_cast<  Foperator *>(bb->b);
+         // const Foperator * b=bb->b;
+          //cout << b <<  " bb->b " <<  bb->b << " " <<  bb->b <<  " " << bb->b->isoptimize <<endl;                 
+          assert(b->isoptimize==false);
+          if (complextype)  b->mapping(&CCastToC);
+          else b->mapping(&CCastToR) ;  
+          Foperator * bn = b->Optimize(currentblock);  
+          *bb->b = *bn;
+           *ii=C_F0(bb,r);           
+        }
+      else if (r==atype<const  FormLinear *>())
+        {
+	  FormLinear * ll=new FormLinear(*dynamic_cast<const  FormLinear *>(e));
+          Ftest * l= const_cast<Ftest *>(ll->l);
+          if (complextype)  l->mapping(&CCastToC) ;
+          else l->mapping(&CCastToR) ; 
+          Ftest * ln = l->Optimize(currentblock);  
+          *ll->l=*ln; 
+           *ii=C_F0(ll,r);    
+          //cout << l <<   " ll->l " <<  ll->l << " " << ll->l->isoptimize <<endl;                
+        }
+      else if (r==atype<const  BC_set *>())
+      {// modif FH  mai 2007  A FAIRE il y a un bug ici XXXXXXXXXXXXX
+    
+	BC_set * bc= new BC_set(*dynamic_cast<const  BC_set *>(e));
+	if (complextype && !bc->complextype) {
+	    bc->CastToK<Complex>() ;
+	    if(verbosity > 10) cout << " Bc to complex " << endl;
+	} 
+	//else bc->mapping(&CCastToR) ; 
+          //cout << l <<   " ll->l " <<  ll->l << " " << ll->l->isoptimize <<endl;    
+	 *ii=C_F0(bc,r);   
+      }
+      
+    } 
+  return complextype;
+}  
+
+
+Problem::Problem(const C_args * ca,const ListOfId &l,size_t & top) :
+  op(new C_args(*ca)),
+  var(l.size()),
+  VF(false), 
+  offset(align8(top)),
+  dim(dimProblem(l))
+{
+  // cout << "Problem : -----------------------------" << top << " dim = " << dim<< endl;
+  top = offset + max(sizeof(Data<FESpace>),sizeof(Data<FESpace>));
+    
+    bool iscomplex;
+    if(dim==2)
+	iscomplex=GetBilinearParam<pfer,pfec>(l,name_param,n_name_param,nargs, Nitem,Mitem,var);
+    else if (dim==3) 
+ 	iscomplex=GetBilinearParam<pf3r,pf3c>(l,name_param,n_name_param,nargs, Nitem,Mitem,var);
+    else ffassert(0); // bug 
+        
+  precon = 0; //  a changer 
+  if ( nargs[3+3])
+    {
+      const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(nargs[3+3]);
+      assert(op);
+      precon = op->Find("(",ArrayOfaType(atype<KN<R>* >(),false));
+   }
+
+  VF=isVF(op->largs);   
+ // cout << " Problem ) VF = " << VF << endl;
+  complextype =  FieldOfForm(op->largs,iscomplex)  ;  // Warning do the casting of all expression in double or complex
+ if( complextype && !iscomplex) 
+    CompileError("Error: Problem  a complex problem with no complex FE function ");
+ if( verbosity > 1)
+    cout << "  -- Problem type  ( complex : " << complextype << " )  "  <<endl;  
+}
+
+Expression IsFebaseArray(Expression f)
+{
+  assert(f);
+  size_t N=f->nbitem();
+   E_Array * vvi(dynamic_cast< E_Array *>(f));
+  if ( ! vvi) return 0;
+   E_Array & vi(*vvi);
+  Expression febase=0;
+  for (size_t i=0;i<N;i++)
+    { 
+      assert(vi[i].left() == atype<pfer>() );
+      const E_FEcomp<R,v_fes> * comp=dynamic_cast<const E_FEcomp<R,v_fes> *>( vi[i].LeftValue()) ;   
+      if (!(comp && comp->comp == (int) i  && comp->N == (int) N)) return 0; 
+      if (!febase) febase = comp->a0;
+      else if(comp->a0 != febase) return 0;        
+    }   
+  return febase;  
+}
+template<class VFES>
+Call_FormBilinear<VFES>::Call_FormBilinear(int dd,Expression * na,Expression  BB,Expression fi, Expression fj)
+  : d(dd),nargs(na),largs(),N(fi->nbitem()),M(fj->nbitem()), 
+     euh(fi), evh(fj)
+{
+  assert(nargs );
+  const C_args * LLL=dynamic_cast<const C_args *>(BB);
+  if (!LLL) 
+    CompileError("Sorry the variationnal form (varf)  is not a the variationnal form (type const C_args *)");
+  largs=LLL->largs;
+}
+template<class VFES>
+Call_FormLinear<VFES>::Call_FormLinear(int dd,Expression *na,Expression  LL, Expression ft)
+  : d(dd),largs(),nargs(na),N(ft->nbitem()),
+  ppfes(ft)//IsFebaseArray(ft)) 
+{
+  const C_args * LLL=dynamic_cast<const C_args *>(LL);
+  if ( !LLL) CompileError("The parameter of a LinearForm must be a array of all componate of FE function");
+  largs=LLL->largs;
+}
+bool C_args::IsLinearOperator() const {
+  //  int n=largs.size();
+  aType tRn =atype<KN<R>* >();
+  aType tCn =atype<KN<Complex>* >();
+  for (const_iterator i=largs.begin(); i != largs.end();i++) 
+    { 
+      C_F0  c= *i; 
+      // Expression e=c; 
+      aType r=c.left();
+      if (     ( r != atype<const  FormLinear *>() )
+	       &&  ( r != atype<const  BC_set *>() )
+	       &&  ( r != atype<VirtualMatrice<R>::plusAx >() )
+	       &&  ( r != atype<VirtualMatrice<R>::plusAtx >() )
+	       &&  ( r != atype<VirtualMatrice<Complex>::plusAx >() )
+	       &&  ( r != atype<VirtualMatrice<Complex>::plusAtx >() )
+	       &&  ( r != tRn) 
+	       &&  ( r != tCn) 
+	       ) return false;
+    }
+  return true;}
+
+bool C_args::IsBilinearOperator() const {
+  //int n=largs.size();
+  aType tRn =atype<Matrice_Creuse<R>* >();
+  aType tCn =atype<Matrice_Creuse<Complex>* >();
+  for (const_iterator i=largs.begin(); i != largs.end();i++) 
+    {  
+      C_F0  c= *i;
+      //Expression e=c;
+      aType r=c.left();
+      if (     ( r!= atype<const  FormBilinear *>() )
+	       &&  ( r != atype<const  BC_set *>() )
+	       &&  ( r != tRn) 
+	       &&  ( r != tCn)
+	       ) return false;
+    }
+  return true;}
+
+
+void SetArgsFormLinear(const ListOfId *lid,int ordre)
+{  
+  //  the local parameter are 
+  //  ordre ==2 => bilinear form  unknown (newU_) and test function (newV_)
+  //  ordre ==1 =>   linear form just  test function (newV_)
+  // ---------------------
+  throwassert(ordre >0 && ordre <=2 && (lid || lid->size()>0 ) );
+  const ListOfId & l(*lid);
+  int nb=l.size();
+  int n=0;
+  C_F0 type,init;
+  int nbarray=0;
+  ListOfId * array[2];
+  aType uh=atype<const finconnue*>(),vh=atype<const ftest*>();
+  
+  for (int i=0;i<nb;i++)        
+    if (l[i].r == 0 &&  l[i].re == 0 && l[i].id  ) n++; 
+         else if (l[i].array) 
+           array[Min(nbarray++,2)] = l[i].array;  
+  if (nbarray && n==0)
+    {  // 
+      
+      if(nbarray!=ordre) 
+        { cerr << " form " << ordre << " == " << nbarray << " Nb of Array "<<endl;
+        CompileError(" Must have 1 or 2 array, one for unknow functions, one for test functions");
+        }
+      for (int k=0;k<ordre;k++)
+        for  (int i=0,iend=array[k]->size();i<iend;i++)
+          { 
+            const UnId & idi((*array[k])[i].id);
+            if (idi.r == 0 && idi.re  == 0 && idi.array==0 ) 
+              {
+                if (k==ordre-2)  //  unknow function just in case of bilinear form  
+                  currentblock->NewID(uh,idi.id,C_F0(newU_(i),uh));
+                else   //  test function 
+                  currentblock->NewID(vh,idi.id,C_F0(newV_(i),vh));
+              }
+            else 
+              CompileError(" Just Variable in array parameter "); 
+          }  
+    }
+  else if (nbarray==0)
+    {    // a supprimer  to remove   in case of bilinear    
+      
+      SHOWVERB(cout << "SetArgs:: form  set parameter " << endl);
+      if( ! ( ordre==1 || n%2==0) )
+       CompileError(" Error in test or unkwon function (odd number of function) ");
+      ffassert( ordre==1 || n%2==0);
+      int nn=ordre==1 ? 0 : n/2; // ordre == 1 => no unknown function just test function
+      
+      for (int i=0,j=0;i<nb;i++)
+        if (l[i].r == 0 && l[i].re  == 0 && l[i].array==0) 
+          {          
+            SHOWVERB(cout <<"  " <<  l[i].id  << " " << (j<nn) << endl); 
+            if (j<nn)
+              currentblock->NewID(uh,l[i].id,C_F0(newU_(j%nn),uh));
+            else 
+              currentblock->NewID(vh,l[i].id,C_F0(newV_(j%nn),vh));
+            j++;
+          }
+    }
+  else
+    {
+       CompileError(" Sorry you mixte formulation with and without array "); 
+    }
+}
+
+const Fem2D::GQuadratureFormular<R3> & CDomainOfIntegration::FIV(Stack stack) const 
+{
+  using namespace Fem2D;
+  if (nargs[8]) return  *GetAny<const Fem2D::GQuadratureFormular<R3> *>((*nargs[8])(stack));
+  int exact = 5;
+  if (nargs[2]) exact=  GetAny<long>((*nargs[2])(stack))-1;
+  GQuadratureFormular<R3> *qf=QF_Simplex<R3>(exact);//QF_Tria_exact(exact);
+  if(verbosity>99 && qf ) cout << "   QF Tet  n:" << qf->n << " exact = " << exact <<  endl;
+  if(qf) return *qf;
+  /*
+  if( QuadratureFormular_T_1.exact >= exact ) return QuadratureFormular_T_1;
+  if( QuadratureFormular_T_2.exact >= exact ) return QuadratureFormular_T_2;
+  if( QuadratureFormular_T_5.exact >= exact ) return QuadratureFormular_T_5;
+  if( QuadratureFormular_T_7.exact >= exact ) return QuadratureFormular_T_7;
+  if( QuadratureFormular_T_9.exact >= exact ) return QuadratureFormular_T_9;
+  */
+  cerr << "Warning :  Order of the Quadrature Formular order " << exact+1 << " exact = " << exact << endl;
+  //  ExecError(" We find  no Quadrature Formular on Tet for this  order: too high");
+  return QuadratureFormular_Tet_5;
+}
+
+const Fem2D::QuadratureFormular & CDomainOfIntegration::FIT(Stack stack) const 
+{
+  using namespace Fem2D;
+  if (nargs[0]) return  *GetAny<const Fem2D::QuadratureFormular *>((*nargs[0])(stack));
+  int exact = 5;
+  if (nargs[2]) exact=  GetAny<long>((*nargs[2])(stack))-1;
+  QuadratureFormular *qf=QF_Simplex<R2>(exact);//QF_Tria_exact(exact);
+  if(verbosity>99 && qf ) cout << "   QF Tria  n:" << qf->n << " exact = " << exact <<  endl;
+  if(qf) return *qf;
+  /*
+  if( QuadratureFormular_T_1.exact >= exact ) return QuadratureFormular_T_1;
+  if( QuadratureFormular_T_2.exact >= exact ) return QuadratureFormular_T_2;
+  if( QuadratureFormular_T_5.exact >= exact ) return QuadratureFormular_T_5;
+  if( QuadratureFormular_T_7.exact >= exact ) return QuadratureFormular_T_7;
+  if( QuadratureFormular_T_9.exact >= exact ) return QuadratureFormular_T_9;
+  */
+  cerr << " Order of the Quadature Formular: order = " << exact+1 << " exact = " << exact << endl;
+  ExecError("Sorry,  we find  no Quadrature Formular on Triangle for this  order: too high.");
+  return QuadratureFormular_T_1;
+}       
+const Fem2D::QuadratureFormular1d & CDomainOfIntegration::FIE(Stack stack) const 
+{
+  using namespace Fem2D;
+  if (nargs[1]) return  *GetAny<const Fem2D::QuadratureFormular1d *>((*nargs[1])(stack));
+  int exact = 5;
+  if (nargs[2]) exact=  GetAny<long>((*nargs[2])(stack))-1;
+  QuadratureFormular1d *qf=QF_Simplex<R1>(exact);//QF_1d_exact(exact);
+  if(verbosity>99 && qf ) cout << "   QF 1d  n:" << qf->n << " exact = " << exact <<  endl;
+  if(qf) return *qf; 
+  /*
+  if( 1 >= exact ) return QF_GaussLegendre1;
+  if( 3 >= exact ) return QF_GaussLegendre2;
+  if( 5 >= exact ) return QF_GaussLegendre3;
+  if( 7 >= exact ) return QF_GaussLegendre4;
+  if( 9 >= exact ) return QF_GaussLegendre5;
+  */
+  cerr << " Ordre of the Integration Formular on Edge, order = " << exact+1 << " exact = " << exact << endl;
+  ExecError(" We find  no Quadrature Formular on Edge  for this  order:  too high.");
+  return QF_GaussLegendre1;
+}
+
+
+namespace Fem2D {
+
+
+// instantiation  des template en double
+  template  bool AssembleVarForm<double,MatriceCreuse<double>,FESpace >(Stack stack,const FESpace::Mesh & Th,
+									const FESpace & Uh,const FESpace & Vh,bool sym,
+									MatriceCreuse<double>  * A,KN_<double> * B,const list<C_F0> &largs );
+
+  template  bool AssembleVarForm<double,MatriceCreuse<double>,FESpace3 >(Stack stack,const  FESpace3::Mesh & Th,
+									const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+									MatriceCreuse<double>  * A,KN_<double> * B,const list<C_F0> &largs );
+
+  template  bool AssembleVarForm<double,map< pair<int,int>, double>,FESpace >(Stack stack,const  FESpace::Mesh & Th,
+									      const FESpace & Uh,const FESpace & Vh,bool sym,
+									      map< pair<int,int>, double>  * A,KN_<double> * B,const list<C_F0> &largs );
+  //3d ->
+  template  bool AssembleVarForm<double,map< pair<int,int>, double>,FESpace3 >(Stack stack,const  FESpace3::Mesh & Th,
+									      const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+									      map< pair<int,int>, double>  * A,KN_<double> * B,const list<C_F0> &largs );
+
+  
+  template  void AssembleLinearForm<double>(Stack stack,const Mesh & Th,const FESpace & Vh,KN_<double> * B,const  FormLinear * const l);
+  
+  template   void AssembleBilinearForm<double>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+					       MatriceCreuse<double>  & A, const  FormBilinear * b  );
+  template   void AssembleBilinearForm<double>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+					       map<pair<int,int>, double >  & A, const  FormBilinear * b  );
+
+  // instantiation  des template en Complex
+  
+  template  bool AssembleVarForm<Complex,MatriceCreuse<Complex>,FESpace >(Stack stack,const FESpace::Mesh & Th,
+									  const FESpace & Uh,const FESpace & Vh,bool sym,
+									  MatriceCreuse<Complex>  * A,KN_<Complex> * B,const list<C_F0> &largs );
+  
+  template  bool AssembleVarForm<Complex,map<pair<int,int>, Complex >,FESpace >(Stack stack,const FESpace::Mesh & Th,
+										const FESpace & Uh,const FESpace & Vh,bool sym,
+										map<pair<int,int>, Complex >  * A,KN_<Complex> * B,const list<C_F0> &largs );
+  // 3d
+  template  bool AssembleVarForm<Complex,MatriceCreuse<Complex>,FESpace3 >(Stack stack,const FESpace3::Mesh & Th,
+									  const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+									  MatriceCreuse<Complex>  * A,KN_<Complex> * B,const list<C_F0> &largs );
+  
+  template  bool AssembleVarForm<Complex,map<pair<int,int>, Complex >,FESpace3 >(Stack stack,const FESpace3::Mesh & Th,
+										const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+										map<pair<int,int>, Complex >  * A,KN_<Complex> * B,const list<C_F0> &largs );
+  //  3d fin
+//template  bool AssembleVarForm<double,map< pair<int,int>, Complex> >(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+//                       map< pair<int,int>, Complex>  * A,KN<double> * B,const list<C_F0> &largs );
+  
+template  void AssembleLinearForm<Complex>(Stack stack,const Mesh & Th,const FESpace & Vh,KN_<Complex> * B,const  FormLinear * const l);
+
+template   void AssembleBilinearForm<Complex>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                            MatriceCreuse<Complex>  & A, const  FormBilinear * b  );
+                            
+template   void AssembleBilinearForm<Complex>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                            map<pair<int,int>, Complex >  & A, const  FormBilinear * b  );
+                            
+                            
+  //template   void AssembleBC<Complex>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+  //              MatriceCreuse<Complex>  * A,KN_<Complex> * B,KN_<Complex> * X, const  BC_set * bc , double tgv   );
+  //  template   void AssembleBC<double,FESpace>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+  //               MatriceCreuse<double>  * A,KN_<double> * B,KN_<double> * X, const  BC_set * bc , double tgv   );
+
+  template   void AssembleBC<Complex,FESpace>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                  MatriceCreuse<Complex>  * A,KN_<Complex> * B,KN_<Complex> * X, const list<C_F0> &largs , double tgv  );
+
+  template   void AssembleBC<double,FESpace>(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+					     MatriceCreuse<double>  * A,KN_<double> * B,KN_<double> * X, const list<C_F0> &largs , double tgv  );
+
+  template   void AssembleBC<Complex,FESpace3>(Stack stack,const Mesh3 & Th,const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+                  MatriceCreuse<Complex>  * A,KN_<Complex> * B,KN_<Complex> * X, const list<C_F0> &largs , double tgv  );
+
+  template   void AssembleBC<double,FESpace3>(Stack stack,const Mesh3 & Th,const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+					     MatriceCreuse<double>  * A,KN_<double> * B,KN_<double> * X, const list<C_F0> &largs , double tgv  );
+}
+  template class Call_FormLinear<v_fes>;
+  template class Call_FormLinear<v_fes3>;
+  template class Call_FormBilinear<v_fes>;
+  template class Call_FormBilinear<v_fes3>;
+
diff --git a/src/fflib/problem.hpp b/src/fflib/problem.hpp
new file mode 100644
index 0000000..f098936
--- /dev/null
+++ b/src/fflib/problem.hpp
@@ -0,0 +1,1347 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef PROBLEM_HPP_
+#define PROBLEM_HPP_
+extern Block *currentblock;
+
+template<class K> class Matrice_Creuse;
+template<class K> class MatriceCreuse;
+namespace  Fem2D {
+  template<class K> class SolveGCPrecon;
+  template<class K> class SolveGMRESPrecon;
+  template<class K> class SolveGMRESDiag;
+//  int IsoLineK(double *f,R2 *Q,double eps);
+  
+}
+
+#include "P1IsoValue.hpp"
+
+
+template<class K> class SolveGCDiag; 
+class Plot;
+class v_fes;
+
+typedef FEbase<double,v_fes> * pferbase ;
+typedef FEbaseArray<double,v_fes> * pferbasearray ;
+typedef pair<pferbase,int> pfer ;
+typedef pair<pferbasearray,int> pferarray ;
+
+typedef FEbase<Complex,v_fes> * pfecbase ;
+typedef FEbaseArray<Complex,v_fes> * pfecbasearray ;
+typedef pair<pfecbase,int> pfec ;
+typedef pair<pfecbasearray,int> pfecarray ;
+
+
+//typedef pair<pmesh *,int> pmesharray ;
+
+typedef   LinearComb<MGauche,C_F0> Finconnue;
+typedef   LinearComb<MDroit,C_F0> Ftest;
+typedef   LinearComb<pair<MGauche,MDroit>,C_F0> Foperator;
+
+inline int intOp(const MGauche &i) {return i.second;}
+inline int intOp(const MDroit &i) {return i.second;}
+inline int intOp(pair<MGauche,MDroit> & p) {return Max(intOp(p.first),intOp(p.second));}
+
+inline void SetOp(KN_<bool> & d,const MGauche &i) 
+          { d[i.second% last_operatortype]=true;}
+inline void SetOp(KN_<bool> & d,const MDroit &i)
+          { d[(int) i.second % last_operatortype]=true;}
+inline void SetOp(KN_<bool> & d,const pair<MGauche,MDroit> & p) 
+          {SetOp(d,p.first);SetOp(d,p.second);}
+
+inline unsigned int GetDiffOp(const MGauche &i, int& lastop) 
+   {int op=(i.second% last_operatortype);
+     lastop=max(lastop,op) ;
+     return 1<<op;}
+inline unsigned int GetDiffOp(const MDroit &i, int& lastop)
+   {int op=(i.second% last_operatortype);
+     lastop=max(lastop,op) ;
+     return 1<<op;}
+inline unsigned int GetDiffOp(const  pair<MGauche,MDroit> &p, int& lastop) 
+{ return GetDiffOp(p.first,lastop)|GetDiffOp(p.second,lastop);}
+
+typedef  const Finconnue  finconnue;
+typedef  const Ftest ftest;
+typedef  const Foperator foperator;
+
+Expression IsFebaseArray(Expression f);
+
+void SetArgsFormLinear(const ListOfId *lid,int ordre);
+
+
+inline ostream & operator<<(ostream & f,const  TypeSolveMat & tm)
+{
+  switch(tm.t) {
+   case TypeSolveMat::NONESQUARE:  f << "No Square (Sparse Morse)"; break;
+   case TypeSolveMat::LU:  f << "LU (Skyline)"; break;
+   case TypeSolveMat::CROUT:  f << "CROUT (Skyline)"; break;
+   case TypeSolveMat::CHOLESKY:  f << "CHOLESKY (Skyline)"; break;
+   case TypeSolveMat::GC:  f << "CG (Sparse Morse)"; break;
+   case TypeSolveMat::GMRES:  f << "GMRES (Sparse Morse)"; break;
+   case TypeSolveMat::SparseSolver:  f << "SparseSolver (Sparse Morse)"; break;
+   default: f << "Unknown  bug???";
+   }
+  return f;
+}
+
+
+class C_args: public E_F0mps  {public:
+  typedef const C_args *  Result;
+  list<C_F0> largs;
+  typedef list<C_F0> ::const_iterator const_iterator ;
+  // il faut expendre 
+  C_args() :largs(){}
+  C_args(C_F0 c) : largs() { if(!c.Zero() )largs.push_back(c);}
+  C_args(  const basicAC_F0 & args) :largs(){ 
+    int n=args.size();
+    for (int i=0;i< n;i++)
+      {
+       if(args[i].Zero()) ; //  skip zero term ...
+       else  if (args[i].left() == atype<const C_args *>())
+          {
+            const C_args * a = dynamic_cast<const C_args *>(args[i].LeftValue());
+            for (list<C_F0>::const_iterator i=a->largs.begin();i!=a->largs.end();i++)
+              largs.push_back(*i);                   
+          } 
+        else 
+          largs.push_back(args[i]);
+      };}
+  static ArrayOfaType  typeargs() { return ArrayOfaType(true);}
+  AnyType operator()(Stack ) const  { return SetAny<const C_args *>(this);}
+  operator aType () const { return atype<const C_args *>();}         
+  
+  static  E_F0 * f(const basicAC_F0 & args) { return new C_args(args);}
+  bool Zero() { return !largs.empty();}
+  bool IsLinearOperator() const;
+  bool IsBilinearOperator() const;
+};
+
+class C_args_minus: public C_args  {public:
+  C_args_minus(  const basicAC_F0 & args) { 
+    int n=args.size();
+    ffassert(n==2);    
+    if (args[0].left() == atype<const C_args *>())
+      {
+        const C_args * a = dynamic_cast<const C_args *>(args[0].LeftValue());
+        ffassert(a);
+        for (list<C_F0>::const_iterator i=a->largs.begin();i!=a->largs.end();i++)
+          largs.push_back(*i);                   
+      }
+    else 
+      largs.push_back(args[0]);
+    
+    largs.push_back(C_F0(TheOperators,"-",args[1]));
+     }
+  
+  static ArrayOfaType  typeargs() { return ArrayOfaType(atype<const C_args *>(),true);}
+  static  E_F0 * f(const basicAC_F0 & args) { return new C_args_minus(args);}    
+};
+
+bool isVF(const list<C_F0> & largs); 
+
+template<typename F>
+class Minus_Form: public  E_F0mps    {public:
+  typedef const F * Result;
+  static ArrayOfaType  typeargs() { return ArrayOfaType(atype<const F *>());}
+  static  E_F0 * f(const basicAC_F0 & args) { 
+    int n=args.size();
+    ffassert(n==1);
+    aType tF=atype<Result>();
+    ffassert(args[0].left() == tF);
+    Result f = dynamic_cast<Result>(args[0].LeftValue());
+    ffassert(f);
+    // F mf = -*f;
+    F * rf=new F(-*f);
+    return  rf;
+  }
+    operator aType () const { return atype<Result>();} 
+    
+    
+};
+
+//template<class RR=double>
+class BC_set : public E_F0mps { public:
+   bool  complextype;
+  typedef const BC_set* Result;
+  vector<Expression> on;
+  vector<int> onis;
+    
+  vector<pair<int,Expression> > bc; //  n� de l'inconnue+ valeur
+  BC_set(  const basicAC_F0 & args) 
+    :on(args.size()),onis(args.size())
+    {
+    int n = args.size();      
+    ffassert(args.named_parameter);
+    AC_F0::const_iterator ii=args.named_parameter->begin();
+    AC_F0::const_iterator ie=args.named_parameter->end();
+    bc.resize(args.named_parameter->size());
+    complextype=false;
+    for (int kk=0;ii!=ie;kk++,ii++)
+     {
+      if( ! BCastTo<double>(ii->second)) 
+       complextype = true; 
+     } 
+    ii=args.named_parameter->begin();
+    for (int kk=0;ii!=ie;kk++,ii++)
+      { //
+        C_F0 x=Find(ii->first);
+        if (x.left() != atype<const finconnue *>())
+          CompileError("We expected an unkown  u=... of the problem");
+        const finconnue * uu = dynamic_cast<const finconnue *>(x.LeftValue());
+        ffassert(uu);
+        const MGauche *ui=uu->simple();
+        ffassert(ui && ui->second == op_id);
+        if(verbosity>9)
+         cout << " on : " << ii->first << " n " << ui->first <<   " = ? " << endl;
+        if (complextype)
+        bc[kk]= make_pair(ui->first,CastTo<Complex>(ii->second));
+        else
+        bc[kk]= make_pair(ui->first,CastTo<double>(ii->second));
+        //ii->second;
+      } 
+    //  sort bc / num de composante
+        
+        std::sort(bc.begin(),bc.end());
+        if(verbosity>9)
+        for (vector<pair<int,Expression> >::iterator i=bc.begin(); i !=bc.end();++i)
+            cout <<"  on " <<  i->first << " " << i->second << endl;
+        
+    for (int i=0;i<n;i++)
+      if( ! BCastTo<KN_<long> >(args[i]))
+         {
+	   on[i]=CastTo<long>(args[i]);
+	   onis[i]=0;
+         }
+	 else 
+	 {
+	   on[i]=CastTo<KN_<long> >(args[i]);
+	   onis[i]=1;	   
+	 }
+  }
+    template<class K> 
+     void CastToK()
+    {
+      aType rr =  complextype ? atype<Complex>() : atype<double>();
+      if (rr == atype<Complex>()) complextype= true; 
+      if(verbosity > 10) cout << " CastToK => " << complextype <<endl;
+     for ( vector<pair<int,Expression> >::iterator k=bc.begin();k!=bc.end();k++)
+	k->second=CastTo<K>(C_F0(k->second,rr)) ;
+    }
+/* De
+  // ajout modif FH  mai 2007 XXXXXXXXXXXXX....
+ void mappingC(C_F0 (*f)(const C_F0 &)) {
+      
+      for ( vector<pair<int,Expression> >::iterator k=bc.begin();k!=bc.end();k++)
+	  k->second=CastTo<Complex>(C_F0(k->second,rr)) ;}
+  // fin ajout
+*/    
+  static ArrayOfaType  typeargs() { return ArrayOfaType(/*atype<long>(),*/true);} //  change frev 2011 FH...
+  AnyType operator()(Stack ) const  { return SetAny<Result>(this);}
+  operator aType () const { return atype<Result>();}         
+  
+  static  E_F0 * f(const basicAC_F0 & args) { return new BC_set(args);}         
+  //    void init(Stack stack) const {}
+  
+};
+
+class CDomainOfIntegration: public E_F0mps { 
+public:
+  static const int n_name_param =10;
+  static basicAC_F0::name_and_type name_param[] ;
+  Expression nargs[n_name_param];
+  enum typeofkind  { int2d=0, int1d=1, intalledges=2,intallVFedges=3, int3d = 4, intallfaces= 5,intallVFfaces=6 } ; //3d
+  typeofkind  kind; //  0 
+  int d; // 3d
+   typedef const CDomainOfIntegration* Result;
+  Expression Th;
+  vector<Expression> what;
+  vector<int> whatis; // 0 -> long , 1 -> array ??? 
+  CDomainOfIntegration( const basicAC_F0 & args,typeofkind b=int2d,int ddim=2) // 3d
+    :kind(b),d(ddim), Th(0), what(args.size()-1),whatis(args.size()-1)
+     
+  {
+    args.SetNameParam(n_name_param,name_param,nargs);
+    if(d==2) // 3d
+      Th=CastTo<pmesh>(args[0]);
+    else if(d==3)
+      Th=CastTo<pmesh3>(args[0]);
+    else ffassert(0); // a faire 
+    int n=args.size();
+    
+    for (int i=1;i<n;i++)
+      if(!BCastTo<KN_<long> >(args[i]) )	 
+	 {
+	   whatis[i-1]=0;
+	   what[i-1]=CastTo<long>(args[i]); 
+	 }
+      else 
+	 {
+	   whatis[i-1]=1;
+	   what[i-1]=CastTo<KN_<long> >(args[i]); 	   
+	 }
+    // cout << " CDomainOfIntegration " << this << endl;       
+  }
+  static  ArrayOfaType  typeargs() {  return ArrayOfaType(atype<pmesh>(), true);} // all type
+  AnyType operator()(Stack ) const  { return SetAny<const CDomainOfIntegration *>(this);}
+  operator aType () const { return atype<const CDomainOfIntegration *>();}         
+  
+  static  E_F0 * f(const basicAC_F0 & args) { return new CDomainOfIntegration(args);} 
+  const Fem2D::QuadratureFormular & FIT(Stack) const ;   
+  const Fem2D::QuadratureFormular1d & FIE(Stack) const ;  
+  const Fem2D::GQuadratureFormular<R3> & FIV(Stack) const ;  // 3d
+  bool UseOpt(Stack s) const  {  return nargs[5] ? GetAny<bool>( (*(nargs[5]))(s) )  : 1;}
+  double  binside(Stack s) const { return nargs[6] ? GetAny<double>( (*(nargs[6]))(s) )  : 0;} // truc pour FH
+  bool intmortar(Stack s) const { return nargs[7] ? GetAny<bool>( (*(nargs[7])) (s) )  : 1;} // truc  pour 
+  double levelset(Stack s) const { return nargs[9] ? GetAny<double>( (*(nargs[9]))(s) )  : 0;}
+  bool  islevelset() const { return nargs[9] != 0; }
+    
+};  
+
+class CDomainOfIntegrationBorder: public CDomainOfIntegration { 
+public:
+  CDomainOfIntegrationBorder( const basicAC_F0 & args) :CDomainOfIntegration(args,int1d) {}
+  static  E_F0 * f(const basicAC_F0 & args) { return new CDomainOfIntegration(args,int1d);}    
+};
+
+class CDomainOfIntegrationAllEdges: public CDomainOfIntegration { 
+public:
+  CDomainOfIntegrationAllEdges( const basicAC_F0 & args) :CDomainOfIntegration(args,intalledges) {}
+  static  E_F0 * f(const basicAC_F0 & args) { return new CDomainOfIntegration(args,intalledges);}    
+};
+
+class CDomainOfIntegrationVFEdges: public CDomainOfIntegration { 
+public:
+  CDomainOfIntegrationVFEdges( const basicAC_F0 & args) :CDomainOfIntegration(args,intallVFedges) {}
+  static  E_F0 * f(const basicAC_F0 & args) { return new CDomainOfIntegration(args,intallVFedges);}    
+};
+// add for the 3d case .. // 3d 
+class CDomainOfIntegration3d: public CDomainOfIntegration { 
+public:
+  CDomainOfIntegration3d( const basicAC_F0 & args) :CDomainOfIntegration(args,int3d,3) {}
+  static  E_F0 * f(const basicAC_F0 & args) { return new CDomainOfIntegration(args,int3d,3);}
+  static  ArrayOfaType  typeargs() {  return ArrayOfaType(atype<pmesh3>(), true);} // all type    
+};
+
+class CDomainOfIntegrationBorder3d: public CDomainOfIntegration { 
+public:
+  CDomainOfIntegrationBorder3d( const basicAC_F0 & args) :CDomainOfIntegration(args,int2d,3) {}
+  static  E_F0 * f(const basicAC_F0 & args) { return new CDomainOfIntegration(args,int2d,3);}    
+  static  ArrayOfaType  typeargs() {  return ArrayOfaType(atype<pmesh3>(), true);} // all type
+};
+
+class CDomainOfIntegrationAllFaces: public CDomainOfIntegration { 
+public:
+  CDomainOfIntegrationAllFaces( const basicAC_F0 & args) :CDomainOfIntegration(args,intallfaces,3) {}
+  static  E_F0 * f(const basicAC_F0 & args) { return new CDomainOfIntegration(args,intallfaces,3);}    
+  static  ArrayOfaType  typeargs() {  return ArrayOfaType(atype<pmesh3>(), true);} // all type
+};
+
+// end add
+
+
+
+
+
+// hack build template 
+template<class T> struct CadnaType{
+   typedef T  Scalaire;
+ }; 
+#ifdef  HAVE_CADNA
+#include <cadnafree.h>
+// specialisation 
+template<> struct CadnaType<complex<double> >{
+   typedef complex<double_st> Scalaire;
+ };
+template<> struct CadnaType<double> {
+   typedef double_st Scalaire;
+ };
+inline double_st conj(const double_st &x){ return x;};
+inline complex<double_st> conj(const complex<double_st> &x){ return complex<double_st>(x.real(),-x.imag());}
+ 
+ inline double norm(complex<double_st> x){return x.real()*x.real()+x.imag()*x.imag();} 
+ inline double norm(double_st x){return x*x;} 
+inline int cestac(const complex<double_st> & z) 
+{return min(cestac(z.real()),cestac(z.imag()));}
+#endif
+
+class Problem  : public Polymorphic { 
+  //  typedef double R;
+  static basicAC_F0::name_and_type name_param[] ;
+  static const int n_name_param =3+NB_NAME_PARM_MAT; // modi FH oct 2005 add tol_pivot 02/ 2007 add nbiter   
+  int Nitem,Mitem;
+  const int dim; 
+public:
+ template<class FESpace>   
+  struct Data {
+    typedef typename FESpace::Mesh Mesh;
+    const Mesh * pTh; 
+    CountPointer<const FESpace> Uh;
+    CountPointer<const FESpace> Vh;
+    CountPointer<MatriceCreuse<double> > AR;   
+    CountPointer<MatriceCreuse<Complex> > AC; 
+    typedef  CadnaType<double>::Scalaire double_st;  
+    typedef  CadnaType<complex<double> >::Scalaire cmplx_st;  
+    MatriceCreuse<double_st>  * AcadnaR;
+    MatriceCreuse<cmplx_st>  * AcadnaC;
+
+    void init()  {pTh=0; AcadnaR=0;AcadnaC=0; Uh.init(),Vh.init();AR.init();AC.init();}
+    void destroy() { 
+      pTh=0;
+      Uh.destroy(); 
+      Vh.destroy();
+      AR.destroy();       
+      AC.destroy();
+      
+      if(AcadnaR) AcadnaR->destroy();
+      if(AcadnaC) AcadnaC->destroy();
+      }        
+  } ;
+  const OneOperator *precon;
+  
+  C_args *op; // the list of all operator 
+  mutable vector<Expression> var; // list des var pour les solutions et test 
+  bool complextype,VF;
+
+  //   Expression noinit,type,epsilon;
+  Expression nargs[n_name_param];
+  
+  const size_t  offset;         
+  Problem(const C_args * ca,const ListOfId &l,size_t & top) ;
+  static ArrayOfaType  typeargs() { return ArrayOfaType(true);}// all type
+  
+  Data<FESpace> * dataptr (Stack stack) const {return   (Data<FESpace> *) (void *) (((char *) stack)+offset);}
+  Data<FESpace3> * dataptr3 (Stack stack) const {return   (Data<FESpace3> *) (void *) (((char *) stack)+offset);}
+  void init(Stack stack) const  {
+    // cout << " init  " << (char *) dataptr(stack) - (char*) stack  << " " << offset <<  endl; 
+    if(dim==2)
+	dataptr(stack)->init();
+    else 
+	dataptr3(stack)->init();
+      }
+  void destroy(Stack stack)  const  {
+      if(dim==2) dataptr(stack)->destroy();
+      else dataptr3(stack)->destroy();
+  }
+
+  template<class R,class FESpace,class v_fes>
+  AnyType eval(Stack stack,Data<FESpace> * data,CountPointer<MatriceCreuse<R> > & dataA,
+  MatriceCreuse< typename CadnaType<R>::Scalaire >  * & dataCadna) const;
+
+  AnyType operator()(Stack stack) const
+  {
+   if(dim==2)
+      {
+     Data<FESpace> *data= dataptr(stack);
+    if (complextype) 
+	return eval<Complex,FESpace,v_fes>(stack,data,data->AC,data->AcadnaC);
+    else
+     return eval<double,FESpace,v_fes>(stack,data,data->AR,data->AcadnaR);
+      }
+    
+    else if(dim==3)
+      {
+	Data<FESpace3> *data= dataptr3(stack);
+      if (complextype) 
+	  return eval<Complex,FESpace3,v_fes3>(stack,data,data->AC,data->AcadnaC);
+      else
+	  return eval<double,FESpace3,v_fes3>(stack,data,data->AR,data->AcadnaR);
+      }
+    else ffassert(0);
+  }
+    
+  
+  
+  bool Empty() const {return false;}     
+  size_t nbitem() const { return Nitem;}     
+};
+
+
+class Solve : public Problem { public:
+  // just a problem with implicit solve 
+  Solve(const C_args * ca,const ListOfId &l,size_t & top) 
+    : Problem(new C_args(*ca),l,top) {} 
+};
+
+class FormBilinear : public E_F0mps { public:
+  typedef const FormBilinear* Result;
+  typedef const CDomainOfIntegration * A;
+  typedef const foperator  *  B;
+  A  di;
+  Foperator * b;    
+  FormBilinear(const basicAC_F0 & args) {
+   di= dynamic_cast<A>(CastTo<A>(args[0]));
+   B  bb= dynamic_cast<B>(CastTo<B>(args[1]));
+  // b = bb->Optimize(currentblock); // FH1004
+  b=new Foperator(*bb); // FH1004  no optimisation here because we don't the type of the bilinear form here.
+  //  the opimisation is done after in FieldOfForm routine 
+  // to find if the form is real or complex 
+  
+  // delete bb; il ne faut pas detruire .. car bb peut etre dans une variable 
+    ffassert(di && b); }
+  
+  static ArrayOfaType  typeargs() { return ArrayOfaType(atype<A>(),atype<B>());}// all type
+  AnyType operator()(Stack ) const { return SetAny<Result>(this);}
+   operator aType () const { return atype<Result>();}         
+
+  static  E_F0 * f(const basicAC_F0 & args) { return new FormBilinear(args);}  
+  FormBilinear(A a,Expression bb) : di(a),b(new Foperator(*dynamic_cast<B>(bb))/*->Optimize(currentblock) FH1004 */) 
+  {ffassert(b);}   
+  FormBilinear operator-() const { return  FormBilinear(di,C_F0(TheOperators,"-",C_F0(b,atype<B>())));}
+  bool VF() const { return MaxOp(b) >= last_operatortype;}
+  int dim() const {return di->d;}
+  FormBilinear(const FormBilinear & fb) : di(fb.di),b(new Foperator(*fb.b) ) {}
+  //  void init(Stack stack) const {}
+};
+
+
+//template<class v_fes>
+class FormLinear : public E_F0mps { public:
+  typedef const FormLinear* Result;
+  typedef const CDomainOfIntegration * A;
+  typedef const ftest  *  B;
+  A  di;
+  Ftest * l;
+   
+  FormLinear(const basicAC_F0 & args) {
+    di= dynamic_cast<A>(CastTo<A>(args[0]));
+    assert(di);
+    Expression a1=CastTo<B>(args[1]);
+    assert(a1);
+   // cout << "  ---FormLinear: "<< a1 << "  " << typeid(*a1).name() << *a1 <<endl;
+    B ll= dynamic_cast<B>(a1);
+    assert(ll);
+    l = new Ftest(*ll); // FH1004 ->Optimize(currentblock);  same as bilinear
+    // delete ll; // il ne faut pas detruire car ll peut etre dans une variable
+    assert(l);
+    ffassert(di && l); 
+  }
+  bool VF() const { return MaxOp(l) >= last_operatortype;}
+ 
+  static ArrayOfaType  typeargs() { return ArrayOfaType(atype<A>(),atype<B>());}// all type
+  AnyType operator()(Stack ) const  { return SetAny<Result>(this);}
+   operator aType () const { return atype<Result>();}         
+  int dim() const {return di->d;}
+  static  E_F0 * f(const basicAC_F0 & args) { return new FormLinear(args);}    
+  FormLinear(A a,Expression bb) : di(a),l(new Ftest(*dynamic_cast<B>(bb))/*->Optimize(currentblock) FH1004 */) {ffassert(l);}   
+  FormLinear operator-() const { return  FormLinear(di,C_F0(TheOperators,"-",C_F0(l,atype<B>())));}
+  //  void init(Stack stack) const {}
+  FormLinear(const FormLinear & fb) : di(fb.di),l(new Ftest(*fb.l) ) {}
+  
+};
+
+template<class VFES>
+class Call_FormLinear: public E_F0mps 
+{ 
+public:
+  const int d;
+  list<C_F0> largs;
+  Expression *nargs;
+  typedef list<C_F0>::const_iterator const_iterator;
+  const int N;
+  Expression ppfes; 
+  
+  Call_FormLinear(int dd,Expression * na,Expression  LL, Expression ft) ;
+  AnyType operator()(Stack stack) const 
+  { InternalError(" bug: no eval of Call_FormLinear ");} 
+   operator aType () const { return atype<void>();}         
+  
+};
+
+template<class VFES>
+class Call_FormBilinear: public E_F0mps 
+{
+public:
+  const int d;
+  Expression *nargs;
+  list<C_F0> largs;
+  typedef list<C_F0>::const_iterator const_iterator;
+  
+  const int N,M;
+  Expression euh,evh; 
+  Call_FormBilinear(int dd,Expression * na,Expression  LL, Expression fi,Expression fj) ;
+  AnyType operator()(Stack stack) const  
+  { InternalError(" bug: no eval of Call_FormBilinear ");} 
+   operator aType () const { return atype<void>();}         
+    
+};
+
+
+struct OpCall_FormLinear_np {
+  static basicAC_F0::name_and_type name_param[] ;
+  static const int n_name_param =1;
+  
+};
+
+struct OpCall_FormBilinear_np {
+  static basicAC_F0::name_and_type name_param[] ;
+  static const int n_name_param =1+NB_NAME_PARM_MAT; // 9-> 11 FH 31/10/2005  11->12 nbiter 02/2007  // 12->22 MUMPS+ Autre Solveur 02/08
+};
+
+template<class T,class v_fes>
+struct OpCall_FormLinear
+  : public OneOperator,
+    public OpCall_FormLinear_np
+{
+  typedef v_fes *pfes;
+  E_F0 * code(const basicAC_F0 & args) const 
+  { 
+    Expression * nargs = new Expression[n_name_param];
+    args.SetNameParam(n_name_param,name_param,nargs);
+    
+    return  new Call_FormLinear<v_fes>(v_fes::d,nargs,to<const C_args*>(args[0]),to<pfes*>(args[1]));} 
+  OpCall_FormLinear() : 
+    OneOperator(atype<const Call_FormLinear<v_fes>*>(),atype<const T*>(),atype<pfes*>()) {}
+};
+
+
+template<class T,class v_fes>
+struct OpCall_FormLinear2
+  : public OneOperator,
+    public OpCall_FormLinear_np
+{
+  static const int d=v_fes::d;
+  typedef v_fes *pfes;
+  E_F0 * code(const basicAC_F0 & args) const 
+  {    
+    Expression * nargs = new Expression[this->n_name_param];
+    args.SetNameParam(this->n_name_param,this->name_param,nargs);
+    
+    Expression p=args[1];
+    if ( ! p->EvaluableWithOutStack() ) 
+      { CompileError("  a(long,Vh) , The long  must be a constant, and  = 0, sorry");}
+    long pv = GetAny<long>((*p)(NullStack));
+    if ( pv ) 
+      { CompileError("  a(long,Vh) , The long  must be a constant == 0, sorry");}       
+    return  new Call_FormLinear<v_fes>(v_fes::d,nargs,to<const C_args*>(args[0]),to<pfes*>(args[2]));} 
+  OpCall_FormLinear2() : 
+    OneOperator(atype<const Call_FormLinear<v_fes>*>(),atype<const T*>(),atype<long>(),atype<pfes*>()) {}
+};
+
+template<class T,class v_fes>
+struct OpCall_FormBilinear
+  : public OneOperator ,
+  OpCall_FormBilinear_np
+{
+  typedef v_fes *pfes;
+  static const int d=v_fes::d;
+  
+  E_F0 * code(const basicAC_F0 & args) const 
+  { Expression * nargs = new Expression[n_name_param];
+    args.SetNameParam(n_name_param,name_param,nargs);
+    // cout << " OpCall_FormBilinear " << *args[0].left() << " " << args[0].LeftValue() << endl;
+    return  new Call_FormBilinear<v_fes>(v_fes::d,nargs,to<const C_args*>(args[0]),to<pfes*>(args[1]),to<pfes*>(args[2]));} 
+  OpCall_FormBilinear() : 
+    OneOperator(atype<const Call_FormBilinear<v_fes>*>(),atype<const T *>(),atype<pfes*>(),atype<pfes*>()) {}
+};
+
+
+
+
+
+bool FieldOfForm( list<C_F0> & largs ,bool complextype);
+template<class A>  struct IsComplexType { static const bool value=false;};
+template<>  struct IsComplexType<Complex> { static const bool value=true;};
+
+template<class R,class v_fes>  //  to make   x=linearform(x)
+struct OpArraytoLinearForm
+  : public OneOperator
+{
+  typedef typename Call_FormLinear<v_fes>::const_iterator const_iterator;
+  const bool isptr;
+  const bool init;
+  const bool zero;
+  class Op : public E_F0mps 
+  {
+  public:
+    Call_FormLinear<v_fes> *l;
+    Expression x;
+    const  bool isptr; 
+    const  bool init; 
+    const  bool zero;
+    AnyType operator()(Stack s)  const ;
+    Op(Expression xx,Expression  ll,bool isptrr,bool initt,bool zzero) 
+      : l(new Call_FormLinear<v_fes>(*dynamic_cast<const Call_FormLinear<v_fes> *>(ll))),
+        x(xx),
+        isptr(isptrr),init(initt),zero(zzero)
+        {assert(l);
+	    
+	bool iscmplx=FieldOfForm(l->largs,IsComplexType<R>::value);
+	//cout<< "FieldOfForm:iscmplx " << iscmplx << " " << IsComplexType<R>::value << " " <<( (iscmplx) == IsComplexType<R>::value) << endl; 
+	ffassert( (iscmplx) == IsComplexType<R>::value); 
+}
+     operator aType () const { return atype<KN<R> *>();} 
+      
+  };
+  E_F0 * code(const basicAC_F0 & args) const 
+  { if(isptr) return new Op(to<KN<R> *>(args[0]),args[1],isptr,init,zero);
+    else      return new Op(to<KN_<R> >(args[0]),args[1],isptr,init,zero);}
+   
+  
+  //  OpArraytoLinearForm(const basicForEachType * tt) : 
+  //    OneOperator(atype<KN_<R> >(),tt,atype<const Call_FormLinear*>()),init(false),isptr(false) {}
+  
+  OpArraytoLinearForm(const basicForEachType * tt,bool isptrr, bool initt,bool zzero=1) : 
+    OneOperator(atype<KN_<R> >(),tt,atype<const Call_FormLinear<v_fes>*>()),
+    isptr(isptrr), init(initt),zero(zzero) {}
+  
+};
+
+
+template<class R,class v_fes>  //  to make   A=linearform(x)
+struct OpMatrixtoBilinearForm
+  : public OneOperator
+{
+  typedef typename Call_FormBilinear<v_fes>::const_iterator const_iterator;
+  int init; 
+  class Op : public E_F0mps {
+  public:
+    Call_FormBilinear<v_fes> *b;
+    Expression a;
+    int init;
+    AnyType operator()(Stack s)  const ;    
+
+    Op(Expression aa,Expression  bb,int initt) 
+      : b(new Call_FormBilinear<v_fes>(* dynamic_cast<const Call_FormBilinear<v_fes> *>(bb))),a(aa),init(initt) 
+  { assert(b && b->nargs);
+    bool iscmplx=FieldOfForm(b->largs,IsComplexType<R>::value)  ;
+     // cout<< "FieldOfForm:iscmplx " << iscmplx << " " << IsComplexType<R>::value << " " << ((iscmplx) == IsComplexType<R>::value) << endl; 
+    ffassert( (iscmplx) == IsComplexType<R>::value);
+}
+  operator aType () const { return atype<Matrice_Creuse<R>  *>();} 
+    
+  };
+  E_F0 * code(const basicAC_F0 & args) const 
+  { return  new Op(to<Matrice_Creuse<R>*>(args[0]),args[1],init);} 
+  OpMatrixtoBilinearForm(int initt=0) : 
+    OneOperator(atype<Matrice_Creuse<R>*>(),atype<Matrice_Creuse<R>*>(),atype<const Call_FormBilinear<v_fes>*>()),
+    init(initt)
+ {}
+};
+
+template<class R>
+class IntFunction  : public E_F0mps { public:
+  typedef R Result;
+  typedef const CDomainOfIntegration * A;
+  typedef R  B;
+  A  di;
+  Expression fonc;    
+  IntFunction(const basicAC_F0 & args) {
+    di= dynamic_cast<A>(CastTo<A>(args[0]));
+    fonc= CastTo<B>(args[1]);
+    ffassert(di && fonc); }
+  
+  static ArrayOfaType  typeargs() { return ArrayOfaType(atype<A>(),atype<B>());}// all type
+  AnyType operator()(Stack ) const;
+  static  E_F0 * f(const basicAC_F0 & args) { return new IntFunction(args);}    
+  //  IntFunction(A a,Expression bb) : di(a),fonc(bb) {}   
+   operator aType () const { return atype<Result>();}         
+  
+};
+
+
+extern Block *currentblock;
+
+class TypeFormOperator: public ForEachType<const C_args*> {
+public:
+  TypeFormOperator() : ForEachType<const C_args*>(0,0) {}
+  void SetArgs(const ListOfId *lid) const {
+    SetArgsFormLinear(lid,2);    } 
+  
+  Type_Expr SetParam(const C_F0 & c,const ListOfId *l,size_t & top) const 
+  { return Type_Expr(this,CastTo(c));}
+  
+  inline  C_F0 Initialization(const Type_Expr & e) const {return C_F0();}
+  
+};
+
+class TypeFormBilinear: public ForEachType<const FormBilinear*> {
+public:
+  TypeFormBilinear() : ForEachType<const FormBilinear*>(0,0) {}
+  void SetArgs(const ListOfId *lid) const {
+    SetArgsFormLinear(lid,2);  
+  }
+  
+  Type_Expr SetParam(const C_F0 & c,const ListOfId *l,size_t & top) const 
+  { return Type_Expr(this,CastTo(c));}
+  
+  
+  C_F0 Initialization(const Type_Expr & e) const 
+  {  
+    // cout << "Initialization " << *e.first << endl;
+    return C_F0(); }  // nothing to initialize 
+  Type_Expr construct(const Type_Expr & e) const 
+  {  
+    //cout << "construct " << *e.first << endl;
+    return e; } 
+  
+};
+
+template<bool exec_init,class Problem>
+class TypeSolve : public ForEachType<const Problem*>   {
+public:
+  TypeSolve() : ForEachType<const Problem*>(0,0) {}
+  
+  void SetArgs(const ListOfId *lid) const {
+    SetArgsFormLinear(lid,2);  
+    
+    
+  }  
+  Type_Expr SetParam(const C_F0 & c,const ListOfId *l,size_t & top) const 
+  {   if (c.left() != atype<const C_args*>())
+    CompileError(" Problem  a(...) = invalid type ",c.left());
+  const C_args * ca = dynamic_cast<const C_args *>(c.LeftValue());
+  Problem * pb=new Problem(ca,*l,top);
+  SHOWVERB(cout << "solve:SetParam " << ca << " pb=" << pb << endl);
+  
+  return Type_Expr(this,pb);        
+  
+  } 
+  
+  class SolveInit: public  E_F0 { public:
+    const Problem * a;
+    AnyType operator()(Stack s)  const {
+      a->init(s);       
+      return exec_init ? (*a)(s) : Nothing ;
+    } 
+    SolveInit(const Type_Expr &  te) : a(dynamic_cast<const Problem *>(te.second))
+    {  SHOWVERB(cout << "SolveInit " << te.second << endl);
+    ffassert(a);}
+  };
+  
+  class SolveDel: public  E_F0 { public:
+    const Problem * a;
+    SolveDel(const C_F0 & c) : a(dynamic_cast<const Problem *>(c.LeftValue()))
+    {   
+      SHOWVERB(cout << "SolveDel " << c.left()  << endl);
+      ffassert(a);}
+    
+    AnyType operator()(Stack s)  const { 
+      a->destroy(s);
+      return Nothing;
+    }};
+  
+  Expression Destroy(const C_F0 & c) const  
+  { return new SolveDel(c);}
+  
+  bool ExistDestroy() const {return true;} 
+  
+  C_F0 Initialization(const Type_Expr & e) const 
+  {  return C_F0( new SolveInit(e) ,atype<void>()); }  
+};
+
+
+
+
+class TypeFormLinear: public ForEachType<const FormLinear*> {
+public:
+  TypeFormLinear() : ForEachType<const FormLinear*>(0,0) {}
+  
+  void SetArgs(const ListOfId *lid) const {
+    SetArgsFormLinear(lid,1);  } 
+  
+  Type_Expr SetParam(const C_F0 & c,const ListOfId *l,size_t & top) const 
+  { return Type_Expr(this,CastTo(c));}
+  //  {  return Type_Expr(c.left(),c.LeftValue());  } // 
+  
+  C_F0 Initialization(const Type_Expr & e) const 
+  {  return C_F0(); }  // nothing to initialize 
+  
+};
+
+
+
+template<class K> class Matrice_Creuse  {
+  //  CountPointer<FESpace> Uh,Vh;
+  //pfes  *pUh,*pVh; // pointeur sur la variable stockant FESpace;  
+public:
+  UniqueffId Uh,Vh; // pour la reconstruction 
+  //  const void * pUh,pVh; //  pointeur pour la reconstruction 
+  CountPointer<MatriceCreuse<K> > A;  
+  TypeSolveMat typemat;
+    size_t count;
+  void init() {
+      count=0;
+    A.init();Uh.init();Vh.init();
+    typemat=TypeSolveMat(TypeSolveMat::NONESQUARE);}
+  Matrice_Creuse() { init();}
+  void destroy() {// Correct Oct 2015 FH (avant test a 'envert) !!!!
+    if(count--==0)
+      A.destroy();
+//else count--;
+    //    Uh.destroy();
+    //Vh.destroy();
+  }   
+  Matrice_Creuse( MatriceCreuse<K> * aa)//,const pfes  *ppUh,const pfes  *ppVh)
+    :A(aa){}//,pUh(ppUh),pVh(ppVh),Uh(*ppUh),Vh(*ppVh) {}
+  Matrice_Creuse( MatriceCreuse<K> * aa,const UniqueffId *pUh,const UniqueffId *pVh)//,const pfes  *ppUh,const pfes  *ppVh)
+    :A(aa),Uh(*pUh),Vh(*pVh) {}//,pUh(ppUh),pVh(ppVh),Uh(*ppUh),Vh(*ppVh) {}
+  long N() const {return  A ? A->n : 0;}
+  long M() const { return A ? A->m : 0;}
+  void resize(int n,int m) { if(A) A->resize(n,m);}
+  void increment(){ count++;}
+};
+
+template<class K> class Matrice_Creuse_Transpose;
+
+ template<class KA,class KB>   class Matrix_Prod { public:  
+  Matrice_Creuse<KA> *A;
+  Matrice_Creuse<KB> *B;
+  bool ta,tb;
+  Matrix_Prod(Matrice_Creuse<KA> *AA,Matrice_Creuse<KB> *BB) : A(AA),B(BB),ta(false),tb(false) {assert(AA && BB);}
+  Matrix_Prod(Matrice_Creuse_Transpose<KA> AA,Matrice_Creuse<KB> *BB)           : A(AA),B(BB),ta(true),tb(false) {assert(AA && BB);}
+  Matrix_Prod(Matrice_Creuse<KA> *AA,Matrice_Creuse_Transpose<KB> BB)           : A(AA),B(BB),ta(false),tb(true) {assert(AA && BB);}
+  Matrix_Prod(Matrice_Creuse_Transpose<KA> AA,Matrice_Creuse_Transpose<KB> BB) : A(AA),B(BB),ta(true),tb(true) {assert(AA && BB);}
+ };
+ 
+template<class K>  ostream & operator << (ostream & f,const Matrice_Creuse<K> & A) 
+{ if ( !A.A) f << " unset sparse matrix " << endl;
+ else f << *A.A ;
+ return f;  }
+
+template<class K>  istream & operator >> (istream & f,Matrice_Creuse<K> & A) 
+{ 
+    if ( WhichMatrix(f)== 2   )
+    {
+      //	A.pUh=0;
+      //A.pVh=0; 
+	A.A.master(new MatriceMorse<K>(f));
+	A.typemat=(A.A->n == A.A->m) ? TypeSolveMat(TypeSolveMat::GMRES) : TypeSolveMat(TypeSolveMat::NONESQUARE); //  none square matrice (morse)
+	
+    }
+    else {  
+	cerr << " unkwon type of matrix " << endl;
+	ExecError("Erreur read matrix ");	
+	A.A =0; }
+    return f;  }
+
+template<class K> class Matrice_Creuse_Transpose  { public:
+  Matrice_Creuse<K> * A;
+  
+  Matrice_Creuse_Transpose(Matrice_Creuse<K> * AA) : A(AA) {assert(A);}
+  operator MatriceCreuse<K> & () const {return *A->A;}
+  operator Matrice_Creuse<K> * () const {return A;}
+};
+
+template<class K> class Matrice_Creuse_inv  { public:
+  Matrice_Creuse<K> * A;
+  Matrice_Creuse_inv(Matrice_Creuse<K> * AA) : A(AA) {assert(A);}
+  operator MatriceCreuse<K> & () const {return *A->A;}
+  operator Matrice_Creuse<K> * () const {return A;}
+};
+
+
+
+
+
+namespace Fem2D {
+  
+  inline void F_Pi_h(R* v, const R2 & P,const baseFElement & K,int i,const R2 & Phat,void * arg)
+  {
+    TabFuncArg &tabe(*(TabFuncArg*)arg);
+    //MeshPoint & mp = *MeshPointStack(tabe.s);
+    MeshPointStack(tabe.s)->set(P,Phat,K);
+    tabe.eval(v);
+    // if (Norme2_2(P-mp.P) > 1e-10) 
+    //  cout << " bug?? F_Pi_h " << endl; 
+    
+  }
+  
+  inline void FoX_1_Pi_h(R* v, const R2 & P,const baseFElement & K,int i,const R2 & Phat,void * arg)
+  {
+    TabFuncArg &tabe(*(TabFuncArg*)arg);
+    MeshPointStack(tabe.s)->set(P,Phat,K);
+    R2 X=tabe.eval_X();
+    MeshPointStack(tabe.s)->set(X.x,X.y);
+    tabe.eval_2(v);
+  }
+  
+  template<class R,typename MC,class FESpace >  bool AssembleVarForm(Stack stack,const typename FESpace::Mesh & Th,
+								     const FESpace & Uh,const FESpace & Vh,bool sym,
+								     MC  * A,KN_<R> * B,const list<C_F0> &largs );
+
+  template<class R,class FESpace>   void AssembleBC(Stack stack,const typename FESpace::Mesh & Th,
+						    const FESpace & Uh,const FESpace & Vh,bool sym,
+						    MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X,
+						    const list<C_F0> &largs , double tgv  );
+  
+  
+  template<class R>   void AssembleLinearForm(Stack stack,const Mesh & Th,const FESpace & Vh,KN_<R> * B,const  FormLinear * const l);
+  
+  //  template<class R>   void AssembleBC(Stack stack,const Mesh3 & Th,const FESpace3 & Uh,const FESpace3 & Vh,bool sym,
+  //			      MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X, const list<C_F0> &largs , double tgv  );
+  
+  
+  template<class R>   void AssembleLinearForm(Stack stack,const Mesh3 & Th,const FESpace3 & Vh,KN_<R> * B,const  FormLinear * const l);
+  template<class R>   void AssembleBC(Stack stack,const Mesh & Th3,const FESpace & Uh3,const FESpace & Vh3,bool sym,
+				      MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X, const  BC_set * bc , double tgv   );
+  
+  template<class R>   void  Element_rhs(const FElement3 & Kv,int ie,int label,const LOperaD &Op,double * p,void * stack,KN_<R> & B,bool all);
+  template<class R>   void  Element_rhs(const FElement3 & Kv,const LOperaD &Op,double * p,void * stack,KN_<R> & B);
+  template<class R>   void  Element_Op(MatriceElementairePleine<R,FESpace3> & mat,const FElement3 & Ku,const FElement3 & Kv,double * p,int ie,int label, void *stack,R3 *B);
+  template<class R>   void  Element_Op(MatriceElementaireSymetrique<R,FESpace3> & mat,const FElement3 & Ku,double * p,int ie,int label, void * stack,R3 *B);
+  
+  template<class R,class FESpace>
+  void AssembleBC(Stack stack,const typename FESpace::Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                  MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X, const list<C_F0> &largs , double tgv  );
+  
+  // fin 3d 
+  
+  template<class R>   void  Element_rhs(const FElement & Kv,int ie,int label,const LOperaD &Op,double * p,void * stack,KN_<R> & B,bool all);
+  template<class R>   void  Element_rhs(const FElement & Kv,const LOperaD &Op,double * p,void * stack,KN_<R> & B);
+  template<class R>   void  Element_Op(MatriceElementairePleine<R,FESpace> & mat,const FElement & Ku,const FElement & Kv,double * p,int ie,int label, void *stack,R2 *B);
+  template<class R>   void  Element_Op(MatriceElementaireSymetrique<R,FESpace> & mat,const FElement & Ku,double * p,int ie,int label, void * stack,R2 *B);
+  
+/*template<class R>   void AssembleBilinearForm(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+                            MatriceCreuse<R>  & A, const  FormBilinear * b  );
+*/ // --------- FH 120105                           
+
+  //template<class R>   void AssembleBC(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,
+  //                MatriceCreuse<R>  * A,KN_<R> * B,KN_<R> * X, const  BC_set * bc , double tgv   );
+  
+  
+  //------
+
+
+
+}
+
+
+template<class R,class v_fes>
+AnyType OpArraytoLinearForm<R,v_fes>::Op::operator()(Stack stack)  const 
+{
+  typedef v_fes *pfes;
+  typedef typename  v_fes::FESpace FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::FElement FElement;
+  typedef typename  Mesh::Element Element;
+  typedef typename  Mesh::Vertex Vertex;  
+  typedef typename  Mesh::RdHat RdHat;  
+  typedef typename  Mesh::Rd Rd;  
+
+  pfes  &  pp= *GetAny<pfes * >((*l->ppfes)(stack));
+  FESpace * pVh = *pp ;
+  FESpace & Vh = *pVh ;
+  double tgv= 1e30;
+  if (l->nargs[0]) tgv= GetAny<double>((*l->nargs[0])(stack));  
+  long NbOfDF =  &Vh ? Vh.NbOfDF: 0;
+  KN<R> *px=0;
+  if(isptr)
+    {
+     px = GetAny<KN<R> * >((*x)(stack) );
+     if(init ) 
+       px->init(NbOfDF); 
+     if(px->N() != NbOfDF) //add Dec 2009
+	 px->resize(NbOfDF);
+     ffassert(px->N() == NbOfDF);
+   }
+  KN_<R>  xx( px ? *(KN_<R> *) px : GetAny<KN_<R> >((*x)(stack) ));
+  if(zero && NbOfDF )
+   xx=R();
+    
+  if ( & Vh && AssembleVarForm<R,MatriceCreuse<R>,FESpace >(stack,Vh.Th,Vh,Vh,false,0,&xx,l->largs) )
+    AssembleBC<R,FESpace>(stack,Vh.Th,Vh,Vh,false,0,&xx,0,l->largs,tgv);
+  return SetAny<KN_<R> >(xx);
+}
+
+template<class R>
+void SetSolver(Stack stack,bool VF,MatriceCreuse<R> & A, Data_Sparse_Solver & ds) 
+	       /*Stack stack,MatriceCreuse<R> & A,const TypeSolveMat *typemat,bool VF,double eps,int NbSpace,int itmax,
+	       const OneOperator * const precon,int umfpackstrategy, double tgv,
+	       double tol_pivot,double tol_pivot_sym, 
+	       int *param_int, double *param_double, string *param_char, int *perm_r, 
+	       int *perm_c, string *file_param_int, string *file_param_double, string *file_param_char, 
+	       string *file_param_perm_r, string *file_param_perm_c)*/
+{ 
+  using namespace Fem2D;
+  const OneOperator* pprecon= static_cast<const OneOperator*>(ds.precon);
+  if (ds.typemat->profile)
+    {
+      MatriceProfile<R> & AA(dynamic_cast<MatriceProfile<R> &>(A));
+      ffassert(&AA);
+      switch (ds.typemat->t) {
+        
+      case TypeSolveMat::LU       : AA.typesolver=FactorizationLU; break;
+      case TypeSolveMat::CROUT    : AA.typesolver=FactorizationCrout; break;
+      case TypeSolveMat::CHOLESKY :  AA.typesolver=FactorizationCholeski; break;
+      default:
+        cerr << " type resolution " << ds.typemat->t <<" sym=" <<  ds.typemat->profile <<  endl;
+        CompileError("type resolution unknown"); break;       
+      }
+    }
+  else 
+    {
+      typedef typename MatriceMorse<R>::VirtualSolver VirtualSolver;
+      if(verbosity>5) cout << " Morse matrix GC Precond diag" << endl;
+      MatriceMorse<R> & AA(dynamic_cast<MatriceMorse<R> &>(A));
+      ffassert(&AA);
+      //     ffassert(typemat->t==TypeSolveMat::GC);
+     // using Fem2D;
+      switch (ds.typemat->t) {
+      case    TypeSolveMat::GC:   
+        if (pprecon)
+          AA.SetSolverMaster(static_cast<const VirtualSolver *>(
+                                                                new Fem2D::SolveGCPrecon<R>(AA,pprecon,stack,ds.itmax,ds.epsilon)));
+        else 
+          AA.SetSolverMaster(static_cast<const VirtualSolver *>(
+                                                                new SolveGCDiag<R>(AA,ds.itmax,ds.epsilon)));
+        break; 
+      case TypeSolveMat::GMRES :
+        //        InternalError("GMRES solveur to do");
+        if (pprecon)
+          AA.SetSolverMaster(new SolveGMRESPrecon<R>(AA,pprecon,stack,ds.NbSpace,ds.itmax,ds.epsilon));
+        else 
+          AA.SetSolverMaster(new SolveGMRESDiag<R>(AA,ds.NbSpace,ds.itmax,ds.epsilon));
+        break;
+//#ifdef HAVE_LIBUMFPACK         
+        case TypeSolveMat::SparseSolver :
+	  AA.SetSolverMaster(DefSparseSolver<R>::Build( stack,&AA,ds) ); 
+         //   AA.SetSolverMaster(new SolveUMFPack<R>(AA,umfpackstrategy,tgv,epsilon,tol_pivot,tol_pivot_sym));
+        break;
+           
+//#endif         
+        
+      
+      default:
+      
+        if (verbosity >5)
+          cout << "  SetSolver:: no  default solver " << endl;
+        // cerr << " type resolution " << ds.typemat->t << endl;
+        //  CompileError("type resolution inconnue"); break;       
+      }
+      
+    }
+}
+
+template<class R,class v_fes>
+AnyType OpMatrixtoBilinearForm<R,v_fes>::Op::operator()(Stack stack)  const 
+{
+  typedef typename  v_fes::pfes pfes;
+  typedef typename  v_fes::FESpace FESpace;
+  typedef typename  FESpace::Mesh Mesh;
+  typedef typename  FESpace::FElement FElement;
+  typedef typename  Mesh::Element Element;
+  typedef typename  Mesh::Vertex Vertex;  
+  typedef typename  Mesh::RdHat RdHat;  
+  typedef typename  Mesh::Rd Rd;  
+
+  assert(b && b->nargs);// *GetAny<pfes * >
+  pfes  * pUh= GetAny<pfes *>((*b->euh)(stack));
+  pfes  * pVh= GetAny<pfes *>((*b->evh)(stack));
+  const FESpace & Uh =  *(FESpace*) **pUh ;
+  const FESpace & Vh =  *(FESpace*) **pVh ;
+  bool A_is_square= & Uh == & Vh || Uh.NbOfDF == Vh.NbOfDF ;
+
+  // MatriceProfile<R> *pmatpf=0;
+  bool VF=isVF(b->largs);
+//  assert(!VF);
+ // bool factorize=false;
+  Data_Sparse_Solver ds;
+  ds.factorize=false;
+  /*
+    long NbSpace = 50; 
+  long itmax=0; 
+  double epsilon=1e-6;
+  double tgv = 1e30;
+  int strategy=0;
+  double tol_pivot=-1;
+  double tol_pivot_sym=-1;
+
+  KN<int> param_int;
+  KN<double> param_double; 
+  string *param_char = NULL;
+  KN<int> perm_r; 
+  KN<int> perm_c;
+  string *file_param_int;  // Add J. Morice 02/09 
+  string *file_param_double; 
+  string* file_param_char;
+  string* file_param_perm_r;
+  string* file_param_perm_c;  
+*/
+  TypeSolveMat tmat=  ( & Uh == & Vh  ? TypeSolveMat::GMRES : TypeSolveMat::NONESQUARE);
+  ds.typemat=&tmat;
+  ds.initmat=true;
+  SetEnd_Data_Sparse_Solver<R>(stack,ds, b->nargs,OpCall_FormBilinear_np::n_name_param);
+  /*  
+  if (b->nargs[0]) initmat= ! GetAny<bool>((*b->nargs[0])(stack));
+  if (b->nargs[1]) typemat= *GetAny<TypeSolveMat *>((*b->nargs[1])(stack));
+  if (b->nargs[2]) ds.epsilon= GetAny<double>((*b->nargs[2])(stack));
+  if (b->nargs[4]) ds.NbSpace= GetAny<long>((*b->nargs[4])(stack));
+  if (b->nargs[6]) ds.tgv= GetAny<double>((*b->nargs[6])(stack));
+  if (b->nargs[7]) factorize= GetAny<bool>((*b->nargs[7])(stack));
+  if (b->nargs[8]) ds.strategy= GetAny<long>((*b->nargs[8])(stack));
+  if (b->nargs[9]) ds.tol_pivot= GetAny<double>((*b->nargs[9])(stack));
+  if (b->nargs[10]) ds.tol_pivot_sym= GetAny<double>((*b->nargs[10])(stack));
+  if (b->nargs[11]) ds.itmax= GetAny<long>((*b->nargs[11])(stack));
+
+  if (b->nargs[12]) ds.param_int= GetAny< KN<int> >((*b->nargs[12])(stack));  // Add J. Morice 02/09 
+  if (b->nargs[13]) ds.param_double= GetAny< KN<double> >((*b->nargs[13])(stack));
+  if (b->nargs[14]) ds.param_char= GetAny< string * >((*b->nargs[14])(stack));  //
+  if (b->nargs[15]) ds.perm_r = GetAny< KN< int > >((*b->nargs[15])(stack));
+  if (b->nargs[16]) ds.perm_c = GetAny< KN< int > >((*b->nargs[16])(stack));  //
+  if (b->nargs[17]) ds.file_param_int= GetAny< string* >((*b->nargs[17])(stack));  // Add J. Morice 02/09 
+  if (b->nargs[18]) ds.file_param_double= GetAny< string* >((*b->nargs[18])(stack));
+  if (b->nargs[19]) ds.file_param_char= GetAny< string* >((*b->nargs[19])(stack));  //
+  if (b->nargs[20]) ds.file_param_perm_r = GetAny< string* >((*b->nargs[20])(stack));
+  if (b->nargs[21]) ds.file_param_perm_c = GetAny< string* >((*b->nargs[21])(stack));  //
+ */
+  if (! A_is_square && *ds.typemat != TypeSolveMat::NONESQUARE) 
+   {
+     cout << " -- Error the solver << "<< ds.typemat <<"  is set  on rectangular matrix  " << endl;
+     ExecError("A solver is set on a none square matrix!");
+    ds.typemat= &(tmat =TypeSolveMat::NONESQUARE);
+   }
+    /*
+  const OneOperator *precon = static_cast<const OneOperator *> (ds.precon); //  a changer 
+  if ( ds.precon)
+    {
+     // const  Polymorphic * op=  dynamic_cast<const  Polymorphic *>(precon);
+      //ffassert(op);
+      precon =  ds.precon op->Find("(",ArrayOfaType(atype<KN<double>* >(),false));
+    }
+     */ // change mars 2011
+  //  for the gestion of the PTR. 
+  WhereStackOfPtr2Free(stack)=new StackOfPtr2Free(stack);// FH aout 2007 
+  
+  Matrice_Creuse<R> & A( * GetAny<Matrice_Creuse<R>*>((*a)(stack)));
+  if(init) A.init(); //
+  if( !& Uh || !& Vh) return SetAny<Matrice_Creuse<R>  *>(&A);
+  /*  if  ( (pUh != A.pUh ) || (pVh != A.pVh  || A.typemat->t != typemat->t) )
+    { 
+      A.Uh.destroy();
+      A.Vh.destroy();
+      }*/
+  const Mesh & Th = Uh.Th;
+  bool same=isSameMesh(b->largs,&Uh.Th,&Vh.Th,stack);     
+  if ( same)
+   {
+     A.typemat = *ds.typemat;
+     if ( A.Uh != Uh  || A.Vh != Vh ) 
+       { // reconstruct all the matrix
+	 A.A=0; // to delete  old  matrix ADD FH 16112005 
+	 A.Uh=Uh;
+	 A.Vh=Vh;
+	 if (ds.typemat->profile)
+	   { A.A.master( new MatriceProfile<R>(Vh,VF) ); ffassert( &Uh == & Vh);}
+	 else if (ds.typemat->sym )
+	   {  A.A.master( new  MatriceMorse<R>(Vh,ds.typemat->sym,VF) ); 
+	     ffassert( &Uh == & Vh);}
+	 else 
+	   {
+	     A.A.master( new  MatriceMorse<R>(Vh,Uh,VF) ); // lines corresponding to test functions 
+	   }
+       }
+     *A.A=R(); // reset value of the matrix
+     
+     if ( AssembleVarForm<R,MatriceCreuse<R>,FESpace >( stack,Th,Uh,Vh,ds.typemat->sym,A.A,0,b->largs) )
+       AssembleBC<R,FESpace>( stack,Th,Uh,Vh,ds.typemat->sym,A.A,0,0,b->largs,ds.tgv);
+   }
+  else
+   { // add FH 17 06 2005  int on different meshes. 
+     map<pair<int,int>, R >   AAA;
+     bool bc=AssembleVarForm<R,map<pair<int,int>, R >,FESpace  >( stack,Th,Uh,Vh,ds.typemat->sym,&AAA,0,b->largs);
+     if (ds.typemat->profile)
+        { ExecError(" Sorry, construction of Skyline matrix with different meshes is not implemented! ");}
+      else 
+        { A.A.master( new  MatriceMorse<R>(Vh.NbOfDF,Uh.NbOfDF,AAA,ds.typemat->sym) ); }
+      if (bc)
+           AssembleBC<R>( stack,Th,Uh,Vh,ds.typemat->sym,A.A,0,0,b->largs,ds.tgv);
+    
+   }
+  if( A_is_square && ds.factorize ) {
+    MatriceProfile<R> * pf = dynamic_cast<MatriceProfile<R> *>((MatriceCreuse<R> *) A.A);
+    assert(pf);
+    switch (ds.typemat->t) {
+    case TypeSolveMat::LU: pf->LU(Abs(ds.epsilon));break;
+    case TypeSolveMat::CROUT: pf->crout(Abs(ds.epsilon));break;
+    case TypeSolveMat::CHOLESKY: pf->cholesky(Abs(ds.epsilon));break;
+    default: ExecError("Sorry no factorize for this type for matrix"); 
+    }
+    
+  }    
+  if (A_is_square) 
+    SetSolver(stack,VF,*A.A,ds);
+	      /*stack,*A.A,&typemat,VF,eps,NbSpace,itmax,precon,umfpackstrategy,tgv,tol_pivot,tol_pivot_sym, 
+	      param_int, param_double, param_char, perm_r, perm_c, file_param_int, file_param_double, file_param_char, 
+	      file_param_perm_r, file_param_perm_c );*/
+  
+  return SetAny<Matrice_Creuse<R>  *>(&A);
+  
+}
+
+
+
+bool SetGMRES();
+bool SetCG();
+#ifdef HAVE_LIBUMFPACK
+bool SetUMFPACK();
+#endif
+/*
+template<class R>
+AnyType ProdMat(Stack,Expression ,Expression);
+template<class R> AnyType DiagMat(Stack,Expression ,Expression);
+template<class R> AnyType CopyTrans(Stack stack,Expression emat,Expression eA);
+template<class R> AnyType CopyMat(Stack stack,Expression emat,Expression eA);
+template<class R> AnyType CombMat(Stack stack,Expression emat,Expression combMat);
+template<class R> AnyType MatFull2Sparse(Stack stack,Expression emat,Expression eA);
+*/
+namespace FreeFempp {
+
+template<class R>
+class TypeVarForm { public:
+    aType tFB;                       
+  //    aType tFB3;                       
+    aType tMat;                       
+    aType tMat3;                       
+    aType tFL;                       
+  //aType tFL3;                       
+    aType tTab;                       
+    aType tMatX;  
+    aType tMatTX;  
+    aType tDotStar;
+    aType tBC ;                    
+  // aType tBC3 ;                    
+TypeVarForm() :
+  tFB( atype<const  FormBilinear *>() ),                      
+  //tFB3( atype<const  FormBilinear<v_fes3> *>() ),                      
+  tMat( atype<Matrice_Creuse<R>*>() ),                       
+  //  tMat3( atype<Matrice_Creuse<R,v_fes3>*>() ),                       
+  tFL( atype<const  FormLinear *>() ),                       
+  //tFL3( atype<const  FormLinear<v_fes3> *>() ),                       
+  tTab( atype<KN<R> *>() ),                       
+  tMatX( atype<typename VirtualMatrice<R>::plusAx >() ),  
+  tMatTX( atype<typename VirtualMatrice<R>::plusAtx >() ),  
+  tDotStar(atype< DotStar_KN_<R> >() ),
+  tBC( atype<const  BC_set  *>())                     
+  {  }
+
+
+ static TypeVarForm *Global;
+}; 
+   
+}
+#endif
diff --git a/src/fflib/showverb.hpp b/src/fflib/showverb.hpp
new file mode 100644
index 0000000..c3724c2
--- /dev/null
+++ b/src/fflib/showverb.hpp
@@ -0,0 +1,34 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef SHOWVERB
+#ifdef VERBOSE
+#define SHOWVERB(i) i
+#else
+#define SHOWVERB(i) ( (void)0)
+#endif
+#endif
diff --git a/src/fflib/string_def.cpp b/src/fflib/string_def.cpp
new file mode 100644
index 0000000..f8180b7
--- /dev/null
+++ b/src/fflib/string_def.cpp
@@ -0,0 +1,172 @@
+//#pragma dont_inline on
+//#pragma inline_depth(1)
+
+#include "config-wrapper.h"
+
+#include <complex>
+#include "AFunction.hpp"
+#include <cstdarg>
+#include <cstring>
+#include "error.hpp"
+#include "lex.hpp"
+
+#include "RNM.hpp"
+
+#include "Operator.hpp"
+// for exec routine 
+#include "rgraph.hpp"
+#include "InitFunct.hpp"
+#include <queue>
+
+#include "array_init.hpp"
+
+class SubString {  public:
+  string * s;
+  long i,n;
+  SubString(string **ss,long ii,long jj) :s(*ss),i(ii),n(jj)
+     {}
+  SubString(string **ss,const SubArray & sb) :s(*ss),i(sb.start),n(sb.n)
+     {ffassert(sb.step==1);}
+};
+
+
+extern Map_type_of_map map_type_of_map ; //  to store te type 
+extern Map_type_of_map map_pair_of_type ; //  to store te type 
+
+extern basicForEachType *  typevarreal,  * typevarcomplex;  //  type of real and complex variable
+
+extern int TheCurrentLine; // unset: by default
+extern long mpisize,mpirank;
+
+
+long get_size(string * p)  { ffassert(p ) ;  return p->size() ;}
+long get_sizep(string ** p)  { ffassert(p && *p) ;  return (*p)->size() ;}
+
+
+
+string ** get_replace(string ** pp,long i,long j, string *rr) 
+    {
+     ffassert(pp && *pp ) ; 
+      string  s=**pp; // copy modif for windows pb free 
+      s.replace(i,j,*rr); 
+      delete *pp;
+      *pp = new string(s);
+      return pp;
+    } 
+// a( : ) = "sqsd";
+
+struct set_substring: public binary_function<SubString,string *,SubString> {
+
+  static SubString f(SubString const  & a, string  *const  & b)  
+  {  
+     string s=*a.s;
+     s.replace(a.i,a.n,*b);
+     * a.s = s; // bofbof pour windows
+     return a;}
+};
+
+
+
+SubString fSubString( string ** const & a,const SubArray & b)
+ { return SubString(a,b);}
+ 
+template<bool B>
+ struct String_find {
+   string *p;
+   String_find(string *pp) :p(pp){ffassert(p);}
+   String_find(string **pp) :p(*pp){ffassert(p);}
+   
+   long find(string *f) const 
+      { return p->find(*f);}
+   long find(string *f,long i) const 
+      { return p->find(*f,i);}
+   
+ }; 
+
+// spacialisation find -> rfind  (bofbof ??) 
+template<>
+ struct String_find<false> {
+   string *p;
+   String_find(string *pp) :p(pp){ffassert(p);}
+   String_find(string **pp) :p(*pp){ffassert(p);}
+   
+   long find(string *f) const 
+      { return p->rfind(*f);}
+   long find(string *f,long i) const 
+      { return p->rfind(*f,i);}
+   
+ }; 
+
+template<bool B>
+String_find<B> to_String_find(string * p)
+  { return String_find<B>(p);}
+
+template<bool B>
+String_find<B> to_String_findp(string ** p)
+  { return String_find<B>(*p);}
+
+template<bool B>
+ long string_find(String_find<B> sf,string *s)
+ {  return sf.find(s); }
+template<bool B>
+ long string_find( String_find<B> const & sf,string *const &s,long const &i)
+ {  return sf.find(s,i); }
+string *  TOString(SubString const  & a)
+{
+    return new string(a.s->substr(a.i,a.n));
+}
+istream* getlinep( istream* f, string ** s)
+ {
+   getline(*f,**s);
+   size_t l= (**s).length();
+   // clean begin end for win32 file 
+   if( l) { if((**s)[0] == '\r') { (**s).erase(0,1); l--;}}
+   if( l) { if((**s)[l-1] == '\r') { (**s).erase(l-1,1); l--;}}
+   return f;
+   }
+void     initStringOperator()
+{
+
+  Dcl_Type<SubString>();
+  // aType  tstringp =atype<string*>();
+  //aType  tstringpp =atype<string**>();
+  
+   Dcl_Type< String_find<true> > ();
+   Dcl_Type< String_find<false> > ();
+    map_type[typeid(string*).name()]->AddCast(
+    new E_F1_funcT<string*,SubString>(FCast<string*,SubString,TOString>));
+// ajoute pour les chaines
+ Add<string **>("size",".",new OneOperator1<long,string **>(get_sizep) );
+ Add<string **>("length",".",new OneOperator1<long,string **>(get_sizep) );
+ 
+ Add<string *>("size",".",new OneOperator1<long,string *>(get_size) );
+ Add<string *>("length",".",new OneOperator1<long,string *>(get_size) );
+ 
+  Add<string *>("find",".",new OneOperator1<String_find<true>,string * >(to_String_find<true> ));
+  Add<string *>("rfind",".",new OneOperator1<String_find<false>,string * >(to_String_find<false> ));
+  Add<string **>("find",".",new OneOperator1<String_find<true>,string ** >(to_String_findp<true> ));
+  Add<string **>("rfind",".",new OneOperator1<String_find<false>,string ** >(to_String_findp<false> ));
+  
+  
+ 
+  Add<String_find<true> >("(","",new OneOperator2<long,String_find<true>,string *>(string_find ) );
+  Add<String_find<false> >("(","",new OneOperator2<long,String_find<false>,string *>(string_find ) );
+
+  Add<String_find<true> >("(","",new OneOperator3_<long,String_find<true>,string *,long>(string_find ) );
+  Add<String_find<false> >("(","",new OneOperator3_<long,String_find<false>,string *,long>(string_find ) );
+
+
+ TheOperators->Add("=",
+         new OneBinaryOperator<set_substring > );
+
+ Add<string**>("(","",new OneOperator2_<SubString,string **,SubArray>(fSubString)); 
+
+ TheOperators->Add("getline",new OneOperator2<istream*,istream*,string**>(getlinep));
+  
+ 
+ 
+// Add<string**>("[","",new OneOperator2_<SubString,string **,SubArray>(fSubString)); 
+ 
+ //Add<string **>("rfind",".",new OneOperator4_<long,string **,long,long,string *>(get_replace) );
+ 
+}
diff --git a/src/fflib/strversionnumber.hpp b/src/fflib/strversionnumber.hpp
new file mode 100644
index 0000000..21de319
--- /dev/null
+++ b/src/fflib/strversionnumber.hpp
@@ -0,0 +1,37 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef STRVERSIONNUMBER_HPP
+#define STRVERSIONNUMBER_HPP
+
+#include <string>
+using namespace std;
+
+double VersionNumber();
+string StrVersionNumber();
+
+#endif//STRVERSIONNUMBER_HPP
diff --git a/src/fflib/strversionnumber.m4 b/src/fflib/strversionnumber.m4
new file mode 100644
index 0000000..bdfdfbb
--- /dev/null
+++ b/src/fflib/strversionnumber.m4
@@ -0,0 +1,23 @@
+#include "config-wrapper.h"
+#include "strversionnumber.hpp"
+#include <cstdlib>
+using namespace std;
+#define TOSTRING1(i) #i
+#define TOSTRING(i) TOSTRING1(i)
+
+//#include <sstream>
+#include <cstdio>
+using namespace std;
+
+double VersionNumber(){
+  return VersionFreeFempp;
+}
+
+string StrVersionNumber(){
+//  std::ostringstream buffer;
+//  buffer.precision(8);
+//  buffer<<VersionNumber();
+  static char buffer[100];
+  sprintf(buffer," %9f (date VersionFreeFemDate)",VersionNumber());
+  return buffer; //.str()+" (date VersionFreeFemDate)" ;
+}
diff --git a/src/fflib/throwassert.hpp b/src/fflib/throwassert.hpp
new file mode 100644
index 0000000..5e91ccd
--- /dev/null
+++ b/src/fflib/throwassert.hpp
@@ -0,0 +1,54 @@
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :      
+// USAGE    :        
+// ORG      : 
+// AUTHOR   : Frederic Hecht
+// E-MAIL   : hecht at ann.jussieu.fr
+//
+
+/*
+ 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef THROWASSERT
+#define THROWASSERT
+#include <iostream>
+
+//#ifdef __INTEL__
+#define cerr cout 
+//#endif
+
+#include "error.hpp"
+
+#ifdef NDEBUG
+#define throwassert(i)  ( (void) 0)
+#else
+#define throwassert(condition)  ((condition) ? ( (void) 0) : throw(ErrorAssert(#condition,__FILE__, __LINE__)))
+ 
+#undef assert
+#define assert(condition) throwassert(condition)
+#endif
+
+// <<ffassert>> an unremovable assert. According to FH, ffassert() is as a more reliable way to trap FF than assert().
+#undef ffassert
+#define ffassert(condition)  ((condition) ? ( (void) 0) : throw(ErrorAssert(#condition,__FILE__, __LINE__)))
+//#define AFAIRE(str) ( (cerr << " TO be Done " << str << endl), throw(ErrorAssert("AFAIRE)/TO DO  (FH????",__FILE__, __LINE__))) 
+#define AFAIRE(cmm) ( cerr << "FH: A Faire/ To Do  "<< cmm << " file " << __FILE__<< " line "<< __LINE__ << endl, InternalError(cmm))
+
+#define InternalError(message) throw(ErrorInternal(message,__LINE__,__FILE__))
+#endif
diff --git a/src/fflib/versionnumber.hpp b/src/fflib/versionnumber.hpp
new file mode 100644
index 0000000..294f24f
--- /dev/null
+++ b/src/fflib/versionnumber.hpp
@@ -0,0 +1 @@
+#include "config-wrapper.h"
diff --git a/src/lglib/._lg.ypp b/src/lglib/._lg.ypp
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/lglib/._lg.ypp differ
diff --git a/src/lglib/Makefile.am b/src/lglib/Makefile.am
new file mode 100644
index 0000000..db84354
--- /dev/null
+++ b/src/lglib/Makefile.am
@@ -0,0 +1,20 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+
+noinst_LIBRARIES=liblg.a
+liblg_a_SOURCES=lg.tab.hpp lg.tab.cpp  mymain.cpp
+AM_CPPFLAGS=-I$(srcdir)/../fflib -I$(srcdir)/../bamglib -I$(srcdir)/../Graphics -I$(srcdir)/../femlib
+
+BUILT_SOURCES=lg.tab.hpp lg.tab.cpp
+
+# <<lg.tab.?pp>> ALH - 10/9/13 - skip dependency on lg.ypp to make sure that lg.tab.?pp are not rebuilt on every new
+# machine (the danger is to generate unnecessary version conflicts) on these automatically generated files
+
+lg.tab.hpp lg.tab.cpp:
+	-rm lg.tab.hpp  lg.tab.cpp lg.tab.cpp.h
+	bison -dtv -p lg  lg.ypp  -o lg.tab.cpp
+	-mv lg.tab.cpp.h  lg.tab.hpp # pour un  pb entre des versions de bison 
+
+libfreefem++.dylib: lg.tab.o ../fflib/libff.a
+	g++ -bundle lg.tab.o  ../fflib/libff.a $(UMFPACKLIB) $(ARPACKLIB) $(BLASLIB) $(LIBS) -o libfreefem++.dylib
+EXTRA_DIST=lg.ypp
diff --git a/src/lglib/lg.ypp b/src/lglib/lg.ypp
new file mode 100644
index 0000000..807b4eb
--- /dev/null
+++ b/src/lglib/lg.ypp
@@ -0,0 +1,943 @@
+// \file
+
+%{ 
+    // -*- Mode : c++ -*-
+    //
+    // SUMMARY  :      
+    // USAGE    :        
+    // ORG      : 
+    // AUTHOR   : Frederic Hecht
+    // E-MAIL   : hecht at ann.jussieu.fr
+    //
+    
+    /*
+     
+     This file is part of Freefem++
+     
+     Freefem++ is free software; you can redistribute it and/or modify
+     it under the terms of the GNU Lesser General Public License as published by
+     the Free Software Foundation; either version 2.1 of the License, or
+     (at your option) any later version.
+     
+     Freefem++  is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+     GNU Lesser General Public License for more details.
+     
+     You should have received a copy of the GNU Lesser General Public License
+     along with Freefem++; if not, write to the Free Software
+     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+     */
+    
+#include "config-wrapper.h"
+#include <iostream>
+#include  <complex>
+#include <string>
+  // for reset cout,cin  in windows  dll
+#ifdef _WIN32
+#include <ext/stdio_filebuf.h>
+#include <iostream>
+#include <cstdio>
+#endif
+
+#include "error.hpp"
+class Iden;
+#include "strversionnumber.hpp"
+#include "InitFunct.hpp"
+#ifdef __MWERKS__
+#ifdef __INTEL__
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
+#endif
+#include "RNM.hpp"
+
+#include "AFunction.hpp"
+//  to reserve space to graphical pointer function
+#include "rgraph.hpp"
+#include "fem.hpp"
+#include "FESpacen.hpp" 
+#include "FESpace.hpp" 
+#include "MeshPoint.hpp"
+
+#include "lgfem.hpp" 
+#include "lex.hpp"
+#include "environment.hpp"
+extern long storageused();
+    extern FILE *ThePlotStream;
+    extern KN<String> *pkarg;
+
+class Routine;
+bool load(string s);
+
+ template <class R,int d> class FE;
+ template <class R,int d,int i> class FE_;
+
+extern mylex *zzzfff;
+// modif FH for window to have 1 dll  for mpi and none mpi ..
+extern  void (*initparallele)(int &, char **&);
+extern  void (*init_lgparallele)();
+// extern  void (*end_parallele)();
+// 
+#ifdef HAVE_LIBARPACK
+  void init_eigenvalue();
+#endif
+   
+  aType dcltype;
+const int nbembtype=10;
+aType rettype[nbembtype];
+Block * routineinblock[nbembtype]; // Add FH july 2005 pb clean on return 
+int kkembtype=-1;
+int inloopcount=0;
+
+/// <<currentblock>> Block class from [[file:../fflib/AFunction.hpp::Block]]
+
+Block *currentblock;
+
+// Add FH july 2005 
+//  problem clean variable after break,continue and return.
+const int sizeStackOfLoop=100; 
+Block * StackOfLoop[sizeStackOfLoop];
+// end ADD
+double CPUcompileInit =0;
+//class pfes;
+C_F0  fespacetype;
+bool fespacecomplex;
+int fespacedim;
+extern int UnShowAlloc;
+int ShowAlloc(const char *s,size_t &);
+// <<yylex>> Connection from grammar to lexer object zzzfff [[file:../fflib/lex.hpp::zzzfff]] of class mylex
+// [[file:../fflib/lex.hpp::class mylex]]. Method mylex::scan() is implemented at [[file:../fflib/lex.cpp::mylex_scan]]
+
+inline int yylex()  {return zzzfff->scan();}
+inline int lineno() {return zzzfff->lineno();}
+
+extern bool withrgraphique;
+
+/// <<fingraphique>>
+
+inline void fingraphique()
+ { if(withrgraphique) 
+   { withrgraphique=false;
+    rattente(1);
+    closegraphique();
+  }}
+
+void lgerror (const char* s) ;
+
+
+ // mpi ptr to function ... 
+void (*initparallele)(int &argc, char **& argv)=0 ;
+void (*init_lgparallele)()=0;
+//void (*end_parallele)()=0;
+%}
+
+
+/* <<YYSTYPE>> definition. <<yylval>> is renamed <<lglval>> by bison at [[file:lg.tab.cpp::lglval]]. It is allocated in
+ lg.tab.o */
+%union{
+ double dnum;
+ long lnum;
+ char * str;
+ char oper[8];
+ CC_F0 cexp;
+ Routine   *routine;
+ AC_F0 args;
+ aType type;
+ CListOfInst cinst;
+ Block * block; 
+ ListOfId *clist_id;
+/* ListCatch * clist_Catchs;*/
+}
+
+/* BISON Declarations */
+
+%type <cinst>   input
+%type <cinst>   instructions
+%type <cexp>   instruction
+%type  <cexp>  try
+%type  <cexp>  catchs
+/* %type  <cexp>  throw */
+%type <cexp>  declaration 
+%type <cexp>  declaration_for
+%type <cexp>  list_of_dcls
+%type <cexp>  fespace_def
+%type <cexp>  fespace_def_list
+%type <cexp>   Expr
+%type <cexp>   no_comma_expr
+%type <cexp>   sub_script_expr
+%type <cexp>   no_ternary_expr
+%type <cexp>   no_set_expr
+%type <cexp>   unary_expr
+%type <cexp>   pow_expr
+%type <cexp>   primary
+%type <oper>   unop
+%type <args>  parameters
+%type <args>  array 
+%type <args>  parameters_list
+%type  <cexp> begin
+%type  <cexp> end
+%type  <clist_id> list_of_id_args
+%type  <clist_id> list_of_id1
+%type <cexp>  spaceIDs
+%type <cexp>  spaceIDa
+%type <cexp>  spaceIDb
+%type <cexp> ID_space
+%type <cexp>  ID_array_space
+%type <args> bornes;
+%type <args>   border_expr;
+%type <type>   type_of_dcl;
+%type <str> id;
+%type <str> fespace123;
+
+/* Add precedence rules to solve dangling else s/r conflict */
+
+%nonassoc IF
+%nonassoc ELSE
+
+%left <oper> ','
+%right <oper> '=' SET
+%left  <oper> LTLT GTGT
+%left  <oper> OR '|' 
+%left  <oper> AND '&'  
+%left  <oper> EQ NE
+%left  <oper>  '<' '>' LE GE 
+%left  <oper>  '+' '-'
+%left  <oper> '*' '/'  '%' DOTSTAR DOTSLASH
+%right <oper> UNARY PLUSPLUS MOINSMOINS '!'
+%right <oper>  '^' '\''
+%right <oper>  '_' 
+%left  <oper>  '(' '[' '.'
+
+%token <oper> ')'  ']' 
+ 
+%token <lnum> LNUM
+%token <dnum> DNUM
+%token <dnum> CNUM
+%token <str> ID
+%token <str> FESPACEID
+%token <str> IDPARAM
+%token <str> STRING
+
+%token ENDOFFILE
+%token INCLUDE
+%token LOAD
+%token BIDON 
+
+%token FOR
+%token WHILE
+%token IF
+%token ELSE
+%token BREAK
+%token CONTINUE
+%token RETURN
+%token TRY
+%token CATCH
+%token THROW
+
+%token <type> TYPE
+%token <type> FUNCTION
+%token <str> FESPACE
+%token <str> FESPACE1
+%token <str> FESPACE3
+
+
+%token DOTSTAR
+%token DOTSLASH
+%token AND
+%token OR
+%token EQ
+%token NE
+%token LE
+%token GE
+%token PLUSPLUS
+%token MOINSMOINS
+%token SET
+%token LTLT
+%token PLUSEQ
+%token MOINSEQ
+%token MULEQ
+%token DIVEQ
+%token DOTMULEQ
+%token DOTDIVEQ
+%token GTGT
+%token ARROW
+%token BORDER
+%token CURVE
+%token SOLVE
+
+%% 
+
+start:   input ENDOFFILE {
+    // clean FH  mach 2014
+		        const char *  magicffglut="#!ffglutdata3.1\n";// for complex and vector 3d plot 
+			//FFCS: divert stream to FFCS
+                        if(ThePlotStream) ffapi::fwriteinit(magicffglut,strlen(magicffglut),1,ThePlotStream);	            
+                        size_t sizestack = currentblock->size()+1024 ; //  before close 
+                        $1+=currentblock->close(currentblock);
+                        if(verbosity>2 || mpirank==0) cout << " sizestack + 1024 =" << sizestack << "  ( " << sizestack-1024 <<" )\n" ;   
+                        size_t lg0,lg1;                       
+                        int NbPtr = ShowAlloc("init execution ",lg0); // number of un delele ptr
+                        debugstack= new queue<pair<const E_Routine*,int> >;
+                        size_t stu0=storageused(); // get Storage usage
+			UnShowAlloc =0;// add FH for parallee
+                        if(verbosity>2  || mpirank==0) cout << endl;  
+                        { Stack stack = newStack(sizestack);
+                        double CPUcompile= CPUtime();
+                        try {                  
+                          $1.eval(stack);}
+                        catch ( E_exception & e)  {
+                          cerr << e.what() << " ,  mpirank " << mpirank << endl;
+                          return 1; }
+                        catch( Error & err) {
+                          cerr << err.what() << endl;
+			  cerr << " err code " << err.errcode() << " ,  mpirank " << mpirank << endl;
+                          return err.errcode();
+                        }
+                         catch( ...) { cerr << "Strange catch exception ???\n"; 
+                          cerr << " at exec line  " << TheCurrentLine << " ,  mpirank " << mpirank << endl;
+                          return 1; 
+                         }
+
+                        if(verbosity)  cout << "times: compile "<< CPUcompile-CPUcompileInit <<"s, execution " 
+			    <<  CPUtime()-CPUcompile  <<"s,  mpirank:" << mpirank << endl;
+                        deleteStack(stack);
+                        //debugstack.clear() 
+                        } 
+                        fingraphique();
+			//FFCS: divert stream to FFCS
+			if(ThePlotStream) {ffapi::ff_pclose(ThePlotStream); ThePlotStream=0;}
+			UnShowAlloc =1;
+                        if(debugstack) delete debugstack;
+                        NbPtr = ShowAlloc("end execution -- ",lg1) - NbPtr;
+                        long stu1 =storageused()-stu0    ;
+                        
+                        
+			    if (NbPtr || (stu1>100000) ) { cout << " ######## We forget of deleting   " << NbPtr
+			                      << " Nb pointer,   " <<  lg1-lg0 << "Bytes " << " ,  mpirank " << mpirank << ", memory leak ="<< stu1 <<  endl;}
+  return 0;}
+;
+
+/*<<input>>*/
+
+input:   instructions /*[[instructions]]*/
+;
+         
+/*<<instructions>>*/
+
+instructions:  instruction /*[[instruction]]*/   {$$=$1;;;}
+        | instructions  instruction   { $$= ($1+=$2) }         
+        ;
+
+/* Function arguments list */
+
+list_of_id_args:   { $$=new ListOfId();}
+            | id                      { $$ = new ListOfId(); $$->push_back(UnId($1))}
+            | id '=' no_comma_expr    { $$ = new ListOfId(); $$->push_back(UnId($1,$3)) }
+            | FESPACE id              { $$ = new ListOfId(); $$->push_back(UnId($2,Find($1),atype<FE<double,2> **>()))}
+            | FESPACE '&' id              { $$ = new ListOfId(); $$->push_back(UnId($3,Find($1),atype<FE<double,2> **>(),true))}
+            | FESPACE3 id              { $$ = new ListOfId(); $$->push_back(UnId($2,Find($1),atype<FE<double,3> **>()))}
+            | FESPACE3 '&' id              { $$ = new ListOfId(); $$->push_back(UnId($3,Find($1),atype<FE<double,3> **>(),true))}
+            | type_of_dcl id          { $$ = new ListOfId(); $$->push_back(UnId($2,C_F0(),$1->right())) }
+            | type_of_dcl '&' id      { $$ = new ListOfId(); $$->push_back(UnId($3,C_F0(),$1,true)) }
+            | '[' list_of_id_args ']' { $$ = new ListOfId(); $$->push_back(UnId($2)) }
+            | list_of_id_args ',' id                     { $$ = $1; $$->push_back(UnId($3)) }
+            | list_of_id_args ',''[' list_of_id_args ']' { $$ = $1; $$->push_back(UnId($4)) }
+            | list_of_id_args ',' id '=' no_comma_expr   { $$ = $1; $$->push_back(UnId($3,$5)) }
+            | list_of_id_args ',' FESPACE id             { $$ = $1; $$->push_back(UnId($4,Find($3),atype<FE<double,2> **>())) }
+            | list_of_id_args ',' FESPACE '&' id             { $$ = $1; $$->push_back(UnId($5,Find($3),atype<FE<double,2> **>(),true)) }
+            | list_of_id_args ',' FESPACE3 id             { $$ = $1; $$->push_back(UnId($4,Find($3),atype<FE<double,3> **>())) }
+            | list_of_id_args ',' FESPACE3 '&' id             { $$ = $1; $$->push_back(UnId($5,Find($3),atype<FE<double,3> **>(),true)) }
+            | list_of_id_args ',' type_of_dcl id         { $$ = $1; $$->push_back(UnId($4,C_F0(),$3->right())) }
+            | list_of_id_args ',' type_of_dcl '&' id     { $$ = $1; $$->push_back(UnId($5,C_F0(),$3,true)) }
+;
+
+list_of_id1:  id                      { $$ = new ListOfId(); $$->push_back(UnId($1)); }
+            | list_of_id1 ',' id      { $$=$1  ; $$->push_back(UnId($3)); }
+;
+   
+/*<<id>>*/
+      
+id: ID | FESPACE|FESPACE3|FESPACE1; 
+
+/* <<list_of_dcls>> */
+
+list_of_dcls:    ID                         {$$=currentblock->NewVar<LocalVariable>($1,dcltype)}   
+              |  ID '='   no_comma_expr     {$$=currentblock->NewVar<LocalVariable>($1,dcltype,$3)}
+              |  ID  '(' parameters_list ')' {$$=currentblock->NewVar<LocalVariable>($1,dcltype,$3);
+                                              $3.destroy()}
+              |  list_of_dcls ',' list_of_dcls  {$$=C_F0($1,$3)}
+                           
+              
+;
+
+
+parameters_list:
+	   no_set_expr {$$=$1} 
+	|  FESPACE  ID  {$$=Find($1)} 
+	|  FESPACE1  ID  {$$=Find($1)} 
+	|  FESPACE3  ID  {$$=Find($1)} 
+	|  ID '=' no_set_expr { $$=make_pair<const char *,const C_F0>($1,$3)} 	
+	| parameters_list ',' no_set_expr { $$ = ($1 += $3) }
+	| parameters_list ',' id '=' no_set_expr { $$= ($1+= make_pair<const char *,const C_F0>($3,$5))}
+; 
+
+/* <<type_of_dcl>> */
+
+type_of_dcl:   TYPE 
+             | TYPE '[' TYPE ']' {$$=TypeArray($1,$3)}
+             | TYPE '[' TYPE ']' '[' TYPE ']' {$$=TypeArray(TypeArray($1,$3),$6)} // Add FH mars 2012 
+             | TYPE '[' TYPE ',' TYPE ']' {$$=TypeArray($1,$3,$5)}
+             | TYPE '[' TYPE ',' TYPE ']' '[' TYPE ']' {$$=TypeArray(TypeArray($1,$3,$5),$8)}
+             | TYPE '<' TYPE '>' {$$=TypeTemplate($1,$3)}
+	     | TYPE '<' TYPE '>' '[' TYPE ']' {$$=TypeArray(TypeTemplate($1,$3),$6)}
+	     | TYPE '<' TYPE '>' '[' TYPE ',' TYPE ']' {$$=TypeArray(TypeTemplate($1,$3),$6,$8)}
+			    
+             
+;
+
+/* <<ID_space>> */
+
+ID_space:
+ID                                  { $$ =  NewFEvariable($1,currentblock,fespacetype,fespacecomplex,fespacedim); }
+  |  ID '[' no_set_expr ']'              { $$ =  NewFEarray($1,currentblock,fespacetype,$3,fespacecomplex,fespacedim); }
+  |  ID '=' no_set_expr                  { $$ =  NewFEvariable($1,currentblock,fespacetype,$3,fespacecomplex,fespacedim) }
+  |  '[' list_of_id1 ']'                 { $$ =  NewFEvariable($2,currentblock,fespacetype,fespacecomplex,fespacedim) }
+  |  '[' list_of_id1 ']' '[' no_set_expr ']'  { $$ =  NewFEarray($2,currentblock,fespacetype,$5,fespacecomplex,fespacedim) }
+  |  '[' list_of_id1 ']' '=' no_set_expr { $$ =  NewFEvariable($2,currentblock,fespacetype,$5,fespacecomplex,fespacedim) }
+; 
+ID_array_space:
+ ID '(' no_set_expr ')'              { $$ =  NewFEarray($1,currentblock,fespacetype,$3,fespacecomplex,fespacedim); }
+  |  '[' list_of_id1 ']' '(' no_set_expr ')'  { $$ =  NewFEarray($2,currentblock,fespacetype,$5,fespacecomplex,fespacedim) }
+
+;
+
+/* <<fespace>> */
+
+fespace123: FESPACE { fespacedim=2} |FESPACE1 { fespacedim=1} | FESPACE3 { fespacedim=3};
+fespace:  fespace123 {fespacecomplex=false;  fespacetype = Find($1);}
+        | fespace123 '<' TYPE '>' {
+             if ($3 != typevarreal && $3 != typevarcomplex) lgerror (" type of finite element <real> or <complex>");
+             fespacecomplex=($3==typevarcomplex);
+             fespacetype = Find($1);}
+;        
+spaceIDa  :      ID_array_space {  $$ = $1  } 
+            |    spaceIDa ',' ID_array_space { $$=C_F0($1,$3);} ;
+            
+spaceIDb  :      ID_space {  $$ = $1  } 
+            |    spaceIDb ',' ID_space { $$=C_F0($1,$3);} ;
+
+spaceIDs :    fespace               spaceIDb    { $$=0;  $$ = $2} 
+           |  fespace '[' TYPE ']'  spaceIDa    { $$=0;  $$ = $5}
+;
+
+/* <<fespace_def>> */
+
+fespace_def:
+   ID '(' parameters_list ')'  {$$=currentblock->NewVar<LocalVariableFES,size_t>($1,typeFESpace($3),$3,dimFESpaceImage($3));
+     $3.destroy(); };
+     
+fespace_def_list:  fespace_def
+                 | fespace_def_list ',' fespace_def {$$=C_F0($1,$3)}
+;
+    
+/* <<declaration>> */
+
+declaration:   type_of_dcl {dcltype=$1} list_of_dcls ';' {$$=$3} /* see [[type_of_dcl]] [[list_of_dcls]] */
+             | FESPACEID  fespace_def_list    ';' {$$=$2}  
+             | spaceIDs ';'{ $$=$1} 
+             | FUNCTION ID '=' Expr ';' {$$=currentblock->NewID($1,$2,$4);} 
+             | FUNCTION type_of_dcl ID  '(' list_of_id_args ')' 
+                   {   /* use the stack to store the prev return type*/
+                      assert(kkembtype+1<nbembtype);
+                      rettype[++kkembtype] = $2->right();
+                      routineinblock[kkembtype] = currentblock;
+                      $<routine>5=new Routine($1,$2->right(),$3,$5,currentblock);
+		      // routineinblock[kkembtype]->Add($3,"(",$<routine>5); //pas recursif pour l'instanat test  FH 27 dec 2008
+                     // cout << " \n after new routine \n " << endl;                      
+                      }
+                    '{' instructions'}' 
+                     { currentblock=$<routine>5->Set($9);
+                       currentblock->Add($3,"(",$<routine>5); //pas recursif pour l'instant test  FH 27 dec 2008
+                       kkembtype--;
+                       $$=0;
+                    
+                        }
+             | FUNCTION ID '(' list_of_id_args ')' 
+                      {Block::open(currentblock); $1->SetArgs($4);}
+                   '='   no_comma_expr  ';' 
+                      {  $<cinst>$=currentblock->close(currentblock);
+                         $$=currentblock->NewID($1,$2,$8,*$4);
+                         delete $4; //  FH 23032005
+                         } 
+;              
+
+begin: '{'  {  Block::open(currentblock)};
+end:   '}'  {  $$=currentblock->close(currentblock)};
+
+for_loop:  FOR {ffassert(inloopcount<sizeStackOfLoop);  // modif FH july 2005
+                StackOfLoop[inloopcount++]=currentblock;};
+while_loop:  WHILE {ffassert(inloopcount<sizeStackOfLoop);
+                StackOfLoop[inloopcount++]=currentblock;}; // modif FH july 2005
+                
+
+declaration_for: 
+    type_of_dcl {dcltype=$1; Block::open(currentblock);  }
+               list_of_dcls {$$=$3};
+
+try: TRY { Block::open(currentblock) };
+
+/*<<instruction>>*/
+
+instruction:   ';' {$$=0;} 
+         | INCLUDE  STRING  {zzzfff->input($2);$$= 0; }
+         | LOAD  STRING  {load($2);$$= 0; }
+         |  try  '{' instructions '}' catchs {$$=Try($3,$5,currentblock->close(currentblock));}
+         |  Expr ';' {$$=$1} /*[[Expr]]*/
+         |  declaration  {$$=$1} /*[[declaration]]*/
+         |  for_loop  '(' Expr ';' Expr ';' Expr ')' instruction {inloopcount--; $$=For($3,$5,$7,$9)} 
+         |  for_loop  '(' declaration_for ';' Expr ';' Expr ')' instruction 
+                {inloopcount--; 
+                $$=C_F0(For($3,$5,$7,$9),currentblock->close(currentblock))}
+                 
+         |  while_loop '(' Expr ')' instruction {inloopcount--;$$=While($3,$5)}
+         |  IF '(' Expr ')'   instruction  {$$=FIf($3,$5)}
+         |  IF '(' Expr ')'   instruction  ELSE instruction {$$=FIf($3,$5,$7)}
+         |  begin  instructions end { 
+                      $$=C_F0(new E_block($2,$3),atype<void>()) }
+         |  BORDER  ID   border_expr { /* <<BORDER_ID>> */
+                      $$=0;currentblock->NewID(atype<const E_Border *>(),$2,C_F0(TheOperators,"[border]",$3))} 
+         |  BORDER  ID   '['  array ']' ';' {
+                      $$=0;currentblock->NewID(atype<const E_Border *>(),$2,C_F0(TheOperators,"[border]",$4))} 
+                               
+         |  BREAK ';' {
+                    if(inloopcount) 
+                      $$= C_F0(new E_throw(E_exception::e_break),atype<void>()); 
+                    else lgerror("break not in loop") }
+         |  CONTINUE ';' { 
+                    if(inloopcount)
+                        $$= C_F0(new E_throw(E_exception::e_continue),atype<void>()) ;
+                    else lgerror("continue not in loop")}
+         |  RETURN  Expr ';' { 
+                    if (kkembtype>=0)
+                      $$= C_F0(new E_throw(E_exception::e_return,(rettype[kkembtype]->CastTo($2)).OnReturn()) ,atype<void>());
+                     else lgerror(" return not in routine ") }
+
+;
+catchs:  
+  CATCH '(' '.' '.' '.'  ')' instruction {$$ =  $7; }
+;
+
+bornes: '(' ID '=' Expr ',' Expr ')' {
+   Block::open(currentblock);
+   $$ = currentblock->NewVar<LocalVariable>($2,atype<double*>());
+   $$+= $4;
+   $$+= $6;
+   $$+= currentblock->NewVar<LocalVariable>("IndexBorder",atype<long*>());}
+;
+bornes: '(' ID '=' Expr ',' Expr ';' ID ')' {
+    Block::open(currentblock);
+    $$ = currentblock->NewVar<LocalVariable>($2,atype<double*>());
+    $$+= $4;
+    $$+= $6;
+    $$+= currentblock->NewVar<LocalVariable>($8,atype<long*>());}
+;
+
+/* <<border_expr>> */
+
+border_expr:   bornes instruction {   
+   $$ = ($1 += $2);
+   currentblock->close(currentblock)} 
+ ;
+
+/*<<Expr>>*/
+
+Expr:	 
+         no_comma_expr /*[[no_comma_expr]]*/
+       | Expr ',' Expr {$$=C_F0(TheOperators,$2,$1,$3);}
+;
+
+/*<<unop>>*/
+	
+unop:
+	  '-' 
+	| '+' 
+	| '!' 
+	| PLUSPLUS 
+	| MOINSMOINS 
+;
+
+/*<<no_comma_expr>>*/
+
+no_comma_expr:
+      no_set_expr /*[[no_set_expr]]*/
+	| no_set_expr '=' no_comma_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_set_expr PLUSEQ no_comma_expr {$$=C_F0(TheOperators,"+=",$1,$3)}
+	| no_set_expr MOINSEQ no_comma_expr {$$=C_F0(TheOperators,"-=",$1,$3)}
+	| no_set_expr MULEQ no_comma_expr {$$=C_F0(TheOperators,"*=",$1,$3)}
+	| no_set_expr DIVEQ no_comma_expr {$$=C_F0(TheOperators,"/=",$1,$3)}
+	| no_set_expr DOTMULEQ no_comma_expr {$$=C_F0(TheOperators,".*=",$1,$3)}
+	| no_set_expr DOTDIVEQ no_comma_expr {$$=C_F0(TheOperators,"./=",$1,$3)}
+;
+
+/*<<no_set_expr>>*/
+
+no_set_expr:
+	no_ternary_expr /*[[no_ternary_expr]]*/
+	| no_ternary_expr '?' no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,"?:",$1,$3,$5)}
+        | no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,"::",$1,$3)}
+	| no_ternary_expr ':' no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,"::",$1,$3,$5)} 	
+;
+
+/*<<no_ternary_expr>>*/
+
+no_ternary_expr:
+	  unary_expr /*[[unary_expr]]*/
+	| no_ternary_expr '*' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr DOTSTAR no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr DOTSLASH no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '/' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '%' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '+' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '-' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr LTLT no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr GTGT no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '&' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr AND no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '|' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr OR no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '<' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr LE no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr '>' no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr GE no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr EQ no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	| no_ternary_expr NE no_ternary_expr {$$=C_F0(TheOperators,$2,$1,$3)}
+	
+;
+
+/*<<sub_script_expr>>*/
+
+sub_script_expr:  
+	    no_ternary_expr {$$=$1} 
+    |   ':' {$$=C_F0(TheOperators,":")}			    
+    |   no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,":",$1,$3)}
+    |   no_ternary_expr ':' no_ternary_expr ':' no_ternary_expr {$$=C_F0(TheOperators,":",$1,$3,$5)} 
+
+;
+  
+/*<<parameters>>*/
+
+parameters:  {$$=0} 
+	|   FESPACE {$$=Find($1)} /*[[file:../fflib/AFunction2.cpp::Find]]*/
+	|   FESPACE1 {$$=Find($1)} 
+	|   FESPACE3 {$$=Find($1)} 
+
+    /* cf [[id]] [[no_set_expr]] */
+	|  id '=' no_set_expr { $$=make_pair<const char *,const C_F0>($1,$3)}
+
+	|   sub_script_expr {$$=$1} /*[[sub_script_expr]]*/
+	| parameters ',' FESPACE { $$ = ($1 += Find($3)) }
+	| parameters ',' FESPACE1 { $$ = ($1 += Find($3)) }
+	| parameters ',' FESPACE3 { $$ = ($1 += Find($3)) }
+	| parameters ',' sub_script_expr { $$ = ($1 += $3) } /*[[sub_script_expr]]*/
+
+    /* cf [[id]] [[no_set_expr]] */
+	| parameters ',' id '=' no_set_expr { $$= ($1+= make_pair<const char *,const C_F0>($3,$5)) }
+; 
+
+array:   no_comma_expr {$$=$1} 
+       | array ',' no_comma_expr {$$ = ($1 += $3) };
+     
+/*<<unary_expr>>*/
+    
+unary_expr:
+    pow_expr /*[[pow_expr]]*/
+  | unop  pow_expr %prec UNARY {$$=C_F0(TheOperators,$1,$2)} /*[[unop]] [[pow_expr]]*/
+;   
+
+/*<<pow_expr>>*/
+
+pow_expr: primary /*[[primary]]*/
+  |      primary  '^' unary_expr   {$$=C_F0(TheOperators,$2,$1,$3)} 
+  |      primary  '_' unary_expr   {$$=C_F0(TheOperators,$2,$1,$3)} 
+  |      primary '\''              {$$=C_F0(TheOperators,$2,$1)} 
+;
+
+/*<<primary>>*/
+
+primary:  
+
+  /* <<primary_ID>> calls [[file:~/ff/draft/src/fflib/AFunction2.cpp::Find]]
+     returns [[file:~/ff/draft/src/fflib/AFunction.hpp::C_F0]] */
+
+           ID           {$$=Find($1);}
+
+  |        LNUM         {$$= CConstant($1)}
+  |        DNUM         {$$= CConstant($1)}
+  |        CNUM         {$$= CConstant(complex<double>(0,$1))}
+  |        STRING {$$= CConstant<const char *>($1)}
+
+  /* <<primary_brackets_parameters>> refers to [[parameters]] and creates an object of class
+     [[file:../fflib/AFunction.hpp::C_F0]] */
+
+  |        primary '('  parameters ')'  {$$=C_F0($1,$2,$3);}
+
+  |        primary '[' sub_script_expr ']'    {$$=C_F0($1,$2,$3)}
+  |        primary '[' sub_script_expr ',' sub_script_expr ']'  {$$=C_F0($1,$2,$3,$5)}
+  |        primary '['  ']'        {$$=C_F0($1,"[]")}
+  |        primary '.'  ID       { $$=C_F0($1,$3) ;}
+  |        FESPACE '.'  ID       { $$=C_F0(Find($1),$3) ;}
+  |        FESPACE '(' parameters ')'     { $$=C_F0(Find($1),$2,$3) ;}
+  |        FESPACE1 '.'  ID       { $$=C_F0(Find($1),$3) ;}
+  |        FESPACE1 '(' parameters ')'     { $$=C_F0(Find($1),$2,$3) ;}
+  |        FESPACE3 '.'  ID       { $$=C_F0(Find($1),$3) ;}
+  |        FESPACE3 '(' parameters ')'     { $$=C_F0(Find($1),$2,$3) ;}
+  |        primary PLUSPLUS      {$$=C_F0(TheRightOperators,$2,$1)} 
+  |        primary MOINSMOINS    {$$=C_F0(TheRightOperators,$2,$1)} 
+  |        TYPE '('  Expr ')' {
+             if ($1->right()->CastingFrom($3.left()) ) 
+                $$=$1->right()->CastTo($3)  ;
+             else { $$=$1->right()->Find("<--",basicAC_F0_wa($3));
+             if (!$$.left()) { cerr << " no wait to change " << $3.left()->right()->name() << " in " << 
+                                        $1->right()->name() << endl;
+                                CompileError(" Error in type(exp) "); }
+             }
+            }
+  |        '(' Expr ')' {$$=$2}
+  |        '[' array  ']' { $$=C_F0(TheOperators,"[]",$2)} 
+
+;
+
+
+%% 
+
+
+#include <fstream>
+using namespace std;
+// bool lgdebug;
+// bool lexdebug;
+void ForDebug();
+void ForDebug()
+{
+  int i=0;
+  i++;
+}
+//extern void ShowAlloc(const char *s, size_t lg);
+//extern void ShowNbAlloc(const char *s);
+void init_lgfem() ;
+void init_lgmesh() ;
+void init_lgmesh3() ;
+void init_algo();
+bool withrgraphique = false;
+
+/// <<Compile>> Called by mainff(). Activates the bison parser by calling yyparse()
+int Compile()
+{
+
+  // see [[YYSTYPE]] [[yylval]] [[lglval]]
+  extern   YYSTYPE *plglval;  // modif FH 
+
+  /// plglval is allocated at [[file:../fflib/global.cpp::plglval]]
+  plglval = &lglval;
+
+  int retvalue=0;
+
+  currentblock=0;
+  Block::open(currentblock);  
+  try {
+    UnShowAlloc =0;
+
+    retvalue=yyparse(); // grammar analysis starting from [[start_symbol]]
+   
+    if(retvalue==0){
+      if(currentblock) 
+        {retvalue=1; if(!mpirank) cerr <<  "Error:a block is not close" << endl; }  
+      else {
+        if( verbosity  ) {
+	      UnShowAlloc =1;
+	      cerr << " CodeAlloc : nb ptr  "<< CodeAlloc::nb << ",  size :"  <<  CodeAlloc::lg 
+              << " mpirank: " <<mpirank <<  endl    ;
+	      if(!mpirank) cerr <<  "Ok: Normal End" << endl;
+	    }
+	}
+    }
+  }
+
+  catch (Error & e) 
+    {
+      retvalue=e.errcode();
+      if(mpirank ==0)
+	cerr << "error " << e.what() 
+	     << "\n code = "<<  retvalue << " mpirank: " <<mpirank  << endl;
+    }
+  catch(std::ios_base::failure & e)
+    {
+      cerr << "std  catch io failure \n what : " << e.what() << endl;; 
+      cerr << " at exec line  " << TheCurrentLine << " mpirank: " <<mpirank  << endl; 
+    }
+  catch(std::exception & e)
+    {
+      cerr << "std  catch exception \n what : " << e.what() << endl;; 
+      cerr << " at exec line  " << TheCurrentLine << " mpirank: " <<mpirank  << endl; 
+      
+    }
+  catch(...)
+    {
+      cerr << "Strange catch exception ???\n"; 
+      cerr << " at exec line  " << TheCurrentLine << " mpirank: " <<mpirank << endl; 
+    }
+  return retvalue; 
+}
+static void SetcppIo()
+{
+
+#ifdef _WIN32XXXX
+  freopen("conin$", "r", stdin);
+  freopen("conout$", "w", stdout);
+  using namespace __gnu_cxx;
+  //  stdio_filebuf<char> * ccout = new stdio_filebuf<char>(stdout, std::ios_base::out);
+  static  stdio_filebuf<char> ccout(stdout, std::ios_base::out);
+  static  stdio_filebuf<char> ccin(stdin, std::ios_base::in);
+   //stdio_filebuf<char> *ccin= new stdio_filebuf<char>(stdin, std::ios_base::in);
+   
+   cout.rdbuf(&ccout);
+   cin.rdbuf(&ccin);
+   cerr.rdbuf(&ccout);
+   cout << " -- SetcppIo --" << endl; 
+#endif
+   ios::sync_with_stdio();
+}
+
+// pour l'environement.
+extern const char *  prognamearg;
+extern  bool echo_edp;
+
+/// Called by mymain() and calls Compile() to run the FF language parser
+int mainff (int  argc, char **argv)
+{
+    
+   ffapi::init(); 
+  if(argc)  
+    prognamearg=argv[0];
+
+    int vvold=verbosity; 
+    if(mpirank !=0) verbosity=0;
+
+  // ALH - 14/10/8 - This breaks FFCS output redirection
+#ifndef ENABLE_FFCS
+  SetcppIo();
+#endif
+
+  GetEnvironment();   
+    vvold=verbosity; 
+    if(mpirank !=0) verbosity=0; 
+  //  size_t lg000;
+ // ShowAlloc("begin main ",lg000);
+  int retvalue=0;
+   ff_atend(fingraphique);
+   if (initparallele)initparallele(argc,argv);
+
+  CPUcompileInit= CPUtime();
+  withrgraphique = false;
+   atexit(ForDebug);
+//  AllFunctions::maptype  xlocal;
+//  local=&xlocal;
+  lexdebug = false;
+  lgdebug = false;
+
+  char *  cc= new char [1024];
+  //  istream * ccin=0;
+  if ( ! (getprog(cc,argc,argv) >0)  ) 
+    {
+      cout << "-- FreeFem++ v" << StrVersionNumber() << " (error parameter!)\n"  ;
+      if(ThePlotStream) {ffapi::ff_pclose(ThePlotStream); ThePlotStream=0;}
+      return 1; 
+    }
+   
+  if(verbosity && (mpirank==0)) { 
+      cout << "-- FreeFem++ v" << StrVersionNumber() << endl;
+      if(verbosity>1) cout << "   file :" << cc << " " << " verbosity= " << verbosity << endl;
+  }
+    
+    KN<String> karg(argc);
+    for(int i=0;i< argc;++i)
+	karg[i]=argv[i];
+    pkarg= &karg;
+
+    /// <<zzzfff>>
+    zzzfff = Newlex(cout,echo_edp);
+    
+  
+/*  
+  ccin= new ifstream(cc);
+  if (argc >1 && (ccin!=0) )  
+     ccin= new ifstream(argv[1]),throwassert(ccin);
+  if (ccin!=0) 
+    zzzfff = new  mylex(*ccin,cout) ;
+  else 
+    zzzfff = new  mylex(cin,cout) ;
+*/    
+//  les motsclefs    
+   zzzfff->Add("include",INCLUDE);
+   zzzfff->Add("load",LOAD);
+   zzzfff->Add("while",WHILE);
+   zzzfff->Add("for",FOR);
+   zzzfff->Add("if",IF);
+   zzzfff->Add("else",ELSE);
+   zzzfff->Add("end",ENDOFFILE);
+   zzzfff->Add("break",BREAK);
+   zzzfff->Add("continue",CONTINUE);
+   zzzfff->Add("return",RETURN);
+   zzzfff->Add("border",BORDER);
+   zzzfff->Add("fespace",FESPACEID);
+   zzzfff->Add("try",TRY);
+   zzzfff->Add("catch",CATCH);
+   zzzfff->Add("throw",THROW);
+//   Init_map_type();
+   if(verbosity>2 || (mpirank==0 ) ) cout << " Load: ";
+   callInitsFunct() ; //  init for dynamique libs ...
+  // init_lgfem() ;
+   init_lgmesh() ;
+   init_lgmesh3() ;
+   init_algo();
+
+#ifdef HAVE_LIBARPACK
+   init_eigenvalue();
+#endif   
+
+   if(init_lgparallele)  init_lgparallele(); 
+  //  callInitsFunct() ; //  init for dynamique libs ...
+
+   if(verbosity>2 || mpirank==0)  cout << endl;
+  zzzfff->input(cc); // [[file:../fflib/lex.cpp::void mylex input]]
+  EnvironmentLoad(); // just before compile
+  verbosity=vvold; 
+    
+  retvalue= Compile(); // [[Compile]]
+   // cout << " xxxxx " <<  retvalue << " " << ThePlotStream << endl;
+  
+  //if(end_parallele) end_parallele();
+  ff_finalize(); 
+  //  currentblock->close(currentblock).eval(thestack);
+ // fingraphique();
+  // FFCS: divert stream to FFCS
+  if(ThePlotStream){
+    ffapi::ff_pclose(ThePlotStream);
+    ThePlotStream=0;
+  }
+  Destroylex( zzzfff);
+  delete [] cc;
+   // ClearMem();
+  return retvalue;
+}
+
+/* FFCS: emacs configuration for this file */
+ 
+/*!
+ * Local Variables:
+ * mode:antlr
+ * ispell-local-dictionary:"british"
+ * coding:utf-8
+ * End:
+ */
diff --git a/src/lglib/mymain.cpp b/src/lglib/mymain.cpp
new file mode 100755
index 0000000..f7c8a11
--- /dev/null
+++ b/src/lglib/mymain.cpp
@@ -0,0 +1,14 @@
+/// \file
+
+int mainff (int  argc, char **argv);
+
+
+extern void init_ptr_parallelepmi();
+
+/// called by platform-dependent main() in src/Graphics/sansrgraph.cpp and others.
+int mymain (int  argc, char **argv)
+{
+
+ init_ptr_parallelepmi();
+ return mainff(argc,argv);
+}
diff --git a/src/libMesh/Makefile.am b/src/libMesh/Makefile.am
new file mode 100644
index 0000000..7b21062
--- /dev/null
+++ b/src/libMesh/Makefile.am
@@ -0,0 +1,13 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+
+# This is not compiled as a separate library because its
+# interconnections with other libraries have not been solved.
+
+noinst_LIBRARIES=libMesh.a
+
+libMesh_a_SOURCES= \
+chrono.c eigenv.c libmesh3.c  libmesh5.c memory.c \
+chrono.h	eigenv.h	libmesh3.h	libmesh5.h	memory.h
+
diff --git a/src/libMesh/chrono.c b/src/libMesh/chrono.c
new file mode 100644
index 0000000..16f5cf0
--- /dev/null
+++ b/src/libMesh/chrono.c
@@ -0,0 +1,98 @@
+/* 
+ *  simulation of a chronograph
+ *  in : tim
+ *  out: tim.dtim = elapsed time in micro-secs
+ *       tim.ptim = elapsed time in secs
+ *       tim.call = number of calls
+ *
+ *  Written by Pascal J. Frey
+ *  email: Pascal.Frey at inria.fr, 1999
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+#include <time.h>
+#include "chrono.h"
+
+
+/* return elapsed time in secs. */
+static double diftim(time_t t2,time_t t1) {
+  struct  tm  *ptm;
+  double  tim;
+  int     hh1,mm1,ss1,hh2,mm2,ss2;
+
+  ptm = localtime(&t1);
+  hh1 = ptm->tm_hour;
+  mm1 = ptm->tm_min;
+  ss1 = ptm->tm_sec;
+
+  ptm = localtime(&t2);
+  hh2 = ptm->tm_hour;
+  mm2 = ptm->tm_min;
+  ss2 = ptm->tm_sec;
+  if ( hh2 < hh1 )  hh2 += 24;
+  
+  tim  = 3600.0*(hh2-hh1);
+  tim += 60.0*(mm2-mm1);
+  tim += ss2-ss1;
+
+  return(tim);
+}
+
+
+/* get system and user times in micro-seconds */
+void  chrono(int cmode,mytime *ptt) {
+  time_t tt;
+
+  if ( cmode == RESET ) {
+    ptt->dtim  = clock();
+    ptt->ctim  = 0.0f;
+    ptt->ptim  = 0;
+    ptt->call  = 0;
+  }
+  else {
+    ptt->dtim = difftime(clock(),ptt->dtim);  /* in secs */
+    if ( cmode == ON ) {
+      ptt->ptim = time(NULL);
+      ptt->call++;
+    }
+    else if ( cmode == OFF ) {
+      tt = time(NULL);
+      ptt->ctim += diftim(tt,ptt->ptim);
+      ptt->ptim  = 0;
+    }
+  }
+}
+
+
+/* return time (converted in secs */
+double gttime(mytime t) {
+
+  if ( t.ctim < MAXCLK )
+    return(t.dtim / (double)CLOCKS_PER_SEC);
+  else
+    return(t.ctim);
+}
+
+
+/* initialize time table */
+void  tminit(mytime *t,int maxtim) {
+  int     k;
+
+  for (k=0; k<maxtim; k++) {
+    t[k].dtim = clock();
+    t[k].ptim = 0;
+    t[k].ctim = 0.0;
+    t[k].call = 0;
+  }
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/libMesh/chrono.h b/src/libMesh/chrono.h
new file mode 100644
index 0000000..fac808a
--- /dev/null
+++ b/src/libMesh/chrono.h
@@ -0,0 +1,32 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+
+#ifndef  ON
+#define  RESET  0
+#define  ON     1
+#define  OFF    2
+#endif
+
+#define  TIMEMAX   16
+#define  MAXCLK    ( 1073741823. / (double)CLOCKS_PER_SEC )
+
+
+typedef struct mytime {
+  double    ctim,dtim;
+  time_t    ptim;
+  short     call;
+} mytime;
+
+
+/* prototypes */
+void   chrono(int cmode,mytime *ptt);
+double gttime(mytime t);
+void   tminit(mytime *t,int maxtim);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libMesh/eigenv.c b/src/libMesh/eigenv.c
new file mode 100644
index 0000000..a51adfb
--- /dev/null
+++ b/src/libMesh/eigenv.c
@@ -0,0 +1,620 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+/* seeking 1.e-05 accuracy */
+#define  EPSD           1.e-15
+#define  EPSD2          1.e-10
+#define  EPS6           5.e-06
+#define  EPS            1.e-06
+#define  EPSX2          2.e-06
+#define  MAXTOU         50
+
+/* check if numbers are equal */ 
+#define egal(x,y)   ( \
+  (  ((x) == 0.0f) ? (fabs(y) < EPS) : \
+   ( ((y) == 0.0f) ? (fabs(x) < EPS) : \
+     (fabs((x)-(y)) / (fabs(x) + fabs(y)) < EPSX2) )  ) )
+
+
+static double Id[3][3] = { 
+  {  1.0, 0.0, 0.0},
+  {  0.0, 1.0, 0.0},
+  {  0.0, 0.0, 1.0} };
+
+
+/* find root(s) of polynomial:  P(x)= x^3+bx^2+cx+d 
+   return 1: 3 roots,  2: 2 roots,  3: 1 root */
+static int newton3(double p[4],double x[3]) {
+  double     b,c,d,da,db,dc,epsd;
+  double     delta,fx,dfx,dxx;
+  double     fdx0,fdx1,dx0,dx1,x1,x2;
+  int        it,n;
+
+  /* coeffs polynomial, a=1 */
+  b = p[2];
+  c = p[1];
+  d = p[0];
+  n = 1;
+
+  /* 1st derivative of f */
+  da = 3.0;
+  db = 2.0*b;
+
+  /* solve 2nd order eqn */
+  delta = db*db - 4.0*da*c;
+  epsd  = db*db*EPSD2;
+
+  /* inflexion (f'(x)=0, x=-b/2a) */
+  x1 = -db / 6.0f;
+
+  n = 1;
+  if ( delta > epsd ) {
+    delta = sqrt(delta);
+    dx0   = (-db + delta) / 6.0;
+    dx1   = (-db - delta) / 6.0;
+    /* Horner */
+    fdx0 = d + dx0*(c+dx0*(b+dx0));
+    fdx1 = d + dx1*(c+dx1*(b+dx1));
+
+    if ( fabs(fdx0) < EPSD ) {
+      /* dx0: double root, compute single root */
+      n = 2;
+      x[0] = dx0;
+      x[1] = dx0;
+      x[2] = -b - 2.0*dx0;
+      /* check if P(x) = 0 */
+      fx = d + x[2]*(c+x[2]*(b+x[2]));
+      if ( fabs(fx) > EPSD2 ) {
+#ifdef DDEBUG
+        fprintf(stderr,"  ## ERR 9100, newton3: fx= %E\n",fx);
+#endif
+        return(0);
+      }
+      return(n);
+    }
+    else if ( fabs(fdx1) < EPSD ) {
+      /* dx1: double root, compute single root */
+      n = 2;
+      x[0] = dx1;
+      x[1] = dx1;
+      x[2] = -b - 2.0*dx1;
+      /* check if P(x) = 0 */
+      fx = d + x[2]*(c+x[2]*(b+x[2]));
+      if ( fabs(fx) > EPSD2 ) {
+#ifdef DDEBUG
+        fprintf(stderr,"  ## ERR 9100, newton3: fx= %E\n",fx);
+#endif
+        return(0);
+      }
+      return(n);
+    }
+  }
+
+  else if ( fabs(delta) < epsd ) {
+    /* triple root */
+    n = 3;
+    x[0] = x1;
+    x[1] = x1;
+    x[2] = x1;
+    /* check if P(x) = 0 */
+    fx = d + x[0]*(c+x[0]*(b+x[0]));
+    if ( fabs(fx) > EPSD2 ) {
+#ifdef DDEBUG
+      fprintf(stderr,"  ## ERR 9100, newton3: fx= %E\n",fx);
+#endif
+      return(0);
+    }
+    return(n);
+  }
+  
+  else {
+#ifdef DDEBUG
+    fprintf(stderr,"  ## ERR 9101, newton3: no real roots\n");
+#endif
+    return(0);
+  }
+
+  /* Newton method: find one root (middle)
+     starting point: P"(x)=0 */
+  x1  = -b / 3.0;
+  dfx =  c + b*x1;
+  fx  = d + x1*(c -2.0*x1*x1);
+  it  = 0;
+  do {
+    x2 = x1 - fx / dfx;
+    fx = d + x2*(c+x2*(b+x2));
+    if ( fabs(fx) < EPSD ) {
+      x[0] = x2;
+      break;
+    }
+    dfx = c + x2*(db + da*x2);
+
+    /* check for break-off condition */
+    dxx = fabs((x2-x1) / x2);
+    if ( dxx < 1.0e-10 ) {
+      x[0] = x2;
+      if ( fabs(fx) > EPSD2 ) {
+        fprintf(stderr,"  ## ERR 9102, newton3, no root found (fx %E).\n",fx);
+        return(0);
+      }
+      break;
+    }
+    else
+      x1 = x2;
+  }
+  while ( ++it < MAXTOU );
+
+  if ( it == MAXTOU ) {
+    x[0] = x1;
+    fx   = d + x1*(c+(x1*(b+x1)));
+    if ( fabs(fx) > EPSD2 ) {
+      fprintf(stderr,"  ## ERR 9102, newton3, no root found (fx %E).\n",fx);
+      return(0);
+    }
+  }
+
+  /* solve 2nd order equation
+     P(x) = (x-sol(1))* (x^2+bb*x+cc)  */
+  db    = b + x[0];
+  dc    = c + x[0]*db;
+  delta = db*db - 4.0*dc;
+  
+  if ( delta <= 0.0 ) {
+    fprintf(stderr,"  ## ERR 9103, newton3, det = 0.\n");
+    return(0);
+  }
+
+  delta = sqrt(delta);
+  x[1] = 0.5 * (-db+delta);
+  x[2] = 0.5 * (-db-delta);
+  
+#ifdef DDEBUG
+    /* check for root accuracy */
+    fx = d + x[1]*(c+x[1]*(b+x[1]));
+    if ( fabs(fx) > EPSD2 ) {
+      fprintf(stderr,"  ## ERR 9104, newton3: fx= %E  x= %E\n",fx,x[1]);
+      return(0);
+    }
+    fx = d + x[2]*(c+x[2]*(b+x[2]));
+    if ( fabs(fx) > EPSD2 ) {
+      fprintf(stderr,"  ## ERR 9104, newton3: fx= %E  x= %E\n",fx,x[2]);
+      return(0);
+    }
+#endif
+
+  return(n);
+}
+
+
+/* find eigenvalues and vectors of a 3x3 symmetric definite
+ * positive matrix 
+ * return order of eigenvalues (1,2,3) or 0 if failed */
+int eigenv(int symmat,double *mat,double lambda[3],double v[3][3]) {
+  double    a11,a12,a13,a21,a22,a23,a31,a32,a33;
+  double    aa,bb,cc,dd,ee,ii,vx1[3],vx2[3],vx3[3],dd1,dd2,dd3;
+  double    maxd,maxm,valm,p[4],w1[3],w2[3],w3[3];
+  int       k,n;
+
+  /* default */
+  memcpy(v,Id,9*sizeof(double));
+  if ( symmat ) {
+    lambda[0] = (double)mat[0];
+    lambda[1] = (double)mat[3];
+    lambda[2] = (double)mat[5];
+
+    maxm = fabs(mat[0]);
+    for (k=1; k<6; k++) {
+      valm = fabs(mat[k]);
+      if ( valm > maxm )  maxm = valm;
+    }
+    /* single float accuracy */
+    if ( maxm < EPS6 )  return(1);
+
+    /* normalize matrix */
+    dd  = 1.0 / maxm;
+    a11 = mat[0] * dd;
+    a12 = mat[1] * dd;
+    a13 = mat[2] * dd;
+    a22 = mat[3] * dd;
+    a23 = mat[4] * dd;
+    a33 = mat[5] * dd;
+
+    /* diagonal matrix */
+    maxd = fabs(a12);
+    valm = fabs(a13);
+    if ( valm > maxd )  maxd = valm;
+    valm = fabs(a23);
+    if ( valm > maxd )  maxd = valm;
+    if ( maxd < EPSD )  return(1);
+
+    a21  = a12;
+    a31  = a13;
+    a32  = a23;
+    
+    /* build characteristic polynomial
+       P(X) = X^3 - trace X^2 + (somme des mineurs)X - det = 0 */
+    aa = a11*a22;
+    bb = a23*a32;
+    cc = a12*a21;
+    dd = a13*a31;
+    p[0] =  a11*bb + a33*(cc-aa) + a22*dd -2.0*a12*a13*a23;
+    p[1] =  a11*(a22 + a33) + a22*a33 - bb - cc - dd;
+    p[2] = -a11 - a22 - a33;
+    p[3] =  1.0;
+  }
+  else {
+    lambda[0] = (double)mat[0];
+    lambda[1] = (double)mat[4];
+    lambda[2] = (double)mat[8];
+
+    maxm = fabs(mat[0]);
+    for (k=1; k<9; k++) {
+      valm = fabs(mat[k]);
+      if ( valm > maxm )  maxm = valm;
+    }
+    if ( maxm < EPS6 )  return(1);
+
+    /* normalize matrix */
+    dd  = 1.0 / maxm;
+    a11 = mat[0] * dd;
+    a12 = mat[1] * dd;
+    a13 = mat[2] * dd;
+    a21 = mat[3] * dd;
+    a22 = mat[4] * dd;
+    a23 = mat[5] * dd;
+    a31 = mat[6] * dd;
+    a32 = mat[7] * dd;
+    a33 = mat[8] * dd;
+
+    /* diagonal matrix */
+    maxd = fabs(a12);
+    valm = fabs(a13);
+    if ( valm > maxd )  maxd = valm;
+    valm = fabs(a23);
+    if ( valm > maxd )  maxd = valm;
+    valm = fabs(a21);
+    if ( valm > maxd )  maxd = valm;
+    valm = fabs(a31);
+    if ( valm > maxd )  maxd = valm;
+     valm = fabs(a32);
+    if ( valm > maxd )  maxd = valm;
+    if ( maxd < EPSD )  return(1);
+
+    /* build characteristic polynomial
+       P(X) = X^3 - trace X^2 + (somme des mineurs)X - det = 0 */
+    aa = a22*a33 - a23*a32;
+    bb = a23*a31 - a21*a33;
+    cc = a21*a32 - a31*a22;
+    ee = a11*a33 - a13*a31;
+    ii = a11*a22 - a12*a21;
+    
+    p[0] =  -a11*aa - a12*bb - a13*cc;
+    p[1] =  aa + ee + ii;
+    p[2] = -a11 - a22 - a33;
+    p[3] =  1.0;
+  }
+
+  /* solve polynomial (find roots using newton) */
+  n = newton3(p,lambda);
+  if ( n <= 0 )  return(0);
+
+  /* compute eigenvectors:
+     an eigenvalue belong to orthogonal of Im(A-lambda*Id) */
+  v[0][0] = 1.0; v[0][1] = v[0][2] = 0.0;
+  v[1][1] = 1.0; v[1][0] = v[1][2] = 0.0;
+  v[2][2] = 1.0; v[2][0] = v[2][1] = 0.0;
+
+  w1[1] = a12;  w1[2] = a13;
+  w2[0] = a21;  w2[2] = a23;
+  w3[0] = a31;  w3[1] = a32;
+
+  if ( n == 1 ) {
+    /* vk = crsprd(wi,wj) */
+    for (k=0; k<3; k++) {
+      w1[0] = a11 - lambda[k];
+      w2[1] = a22 - lambda[k];
+      w3[2] = a33 - lambda[k];
+
+      /* cross product vectors in (Im(A-lambda(i) Id) ortho */
+      vx1[0] = w1[1]*w3[2] - w1[2]*w3[1];
+      vx1[1] = w1[2]*w3[0] - w1[0]*w3[2];
+      vx1[2] = w1[0]*w3[1] - w1[1]*w3[0];
+      dd1    = vx1[0]*vx1[0] + vx1[1]*vx1[1] + vx1[2]*vx1[2];
+
+      vx2[0] = w1[1]*w2[2] - w1[2]*w2[1];
+      vx2[1] = w1[2]*w2[0] - w1[0]*w2[2];
+      vx2[2] = w1[0]*w2[1] - w1[1]*w2[0];
+      dd2    = vx2[0]*vx2[0] + vx2[1]*vx2[1] + vx2[2]*vx2[2];
+
+      vx3[0] = w2[1]*w3[2] - w2[2]*w3[1];
+      vx3[1] = w2[2]*w3[0] - w2[0]*w3[2];
+      vx3[2] = w2[0]*w3[1] - w2[1]*w3[0];
+      dd3    = vx3[0]*vx3[0] + vx3[1]*vx3[1] + vx3[2]*vx3[2];
+
+      /* find vector of max norm */
+      if ( dd1 > dd2 ) {
+        if ( dd1 > dd3 ) {
+          dd1 = 1.0 / sqrt(dd1);
+          v[k][0] = vx1[0] * dd1;
+          v[k][1] = vx1[1] * dd1;
+          v[k][2] = vx1[2] * dd1;
+        }
+	else {
+          dd3 = 1.0 / sqrt(dd3);
+          v[k][0] = vx3[0] * dd3;
+          v[k][1] = vx3[1] * dd3;
+          v[k][2] = vx3[2] * dd3;
+	}
+      }
+      else {
+        if ( dd2 > dd3 ) { 
+          dd2 = 1.0 / sqrt(dd2);
+          v[k][0] = vx2[0] * dd2;
+          v[k][1] = vx2[1] * dd2;
+          v[k][2] = vx2[2] * dd2;
+        }
+        else {
+          dd3 = 1.0 / sqrt(dd3);
+          v[k][0] = vx3[0] * dd3;
+          v[k][1] = vx3[1] * dd3;
+          v[k][2] = vx3[2] * dd3;
+        }  
+      }
+    }
+  }
+
+  /* (vp1,vp2) double,  vp3 simple root */
+  else if ( n == 2 ) {
+    w1[0] = a11 - lambda[2];
+    w2[1] = a22 - lambda[2];
+    w3[2] = a33 - lambda[2];
+
+    /* cross product */
+    vx1[0] = w1[1]*w3[2] - w1[2]*w3[1];
+    vx1[1] = w1[2]*w3[0] - w1[0]*w3[2];
+    vx1[2] = w1[0]*w3[1] - w1[1]*w3[0];
+    dd1 = vx1[0]*vx1[0] + vx1[1]*vx1[1] + vx1[2]*vx1[2];
+ 
+    vx2[0] = w1[1]*w2[2] - w1[2]*w2[1];
+    vx2[1] = w1[2]*w2[0] - w1[0]*w2[2];
+    vx2[2] = w1[0]*w2[1] - w1[1]*w2[0];
+    dd2 = vx2[0]*vx2[0] + vx2[1]*vx2[1] + vx2[2]*vx2[2];
+
+    vx3[0] = w2[1]*w3[2] - w2[2]*w3[1];
+    vx3[1] = w2[2]*w3[0] - w2[0]*w3[2];
+    vx3[2] = w2[0]*w3[1] - w2[1]*w3[0];
+    dd3 = vx3[0]*vx3[0] + vx3[1]*vx3[1] + vx3[2]*vx3[2];
+
+    /* find vector of max norm */
+    if ( dd1 > dd2 ) {
+      if ( dd1 > dd3 ) {
+        dd1 = 1.0 / sqrt(dd1);
+        v[2][0] = vx1[0] * dd1;
+        v[2][1] = vx1[1] * dd1;
+        v[2][2] = vx1[2] * dd1;
+      }
+      else {
+        dd3 = 1.0 / sqrt(dd3);
+        v[2][0] = vx3[0] * dd3;
+        v[2][1] = vx3[1] * dd3;
+        v[2][2] = vx3[2] * dd3;
+      }
+    }
+    else {
+      if ( dd2 > dd3 ) {
+        dd2 = 1.0 / sqrt(dd2);
+        v[2][0] = vx2[0] * dd2;
+        v[2][1] = vx2[1] * dd2;
+        v[2][2] = vx2[2] * dd2;
+      }
+      else {
+        dd3 = 1.0 / sqrt(dd3);
+        v[2][0] = vx3[0] * dd3;
+        v[2][1] = vx3[1] * dd3;
+        v[2][2] = vx3[2] * dd3;
+      }
+    }
+
+    /* compute v1 and v2 in Im(A-vp3*Id) */
+    dd1 = w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2];
+    dd2 = w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2];
+    if ( dd1 > dd2 ) {
+      dd1 = 1.0 / sqrt(dd1);
+      v[0][0] = w1[0]*dd1;
+      v[0][1] = w1[1]*dd1;
+      v[0][2] = w1[2]*dd1;
+    }
+    else {
+      dd2 = 1.0 / sqrt(dd2);
+      v[0][0] = w2[0]*dd2;
+      v[0][1] = w2[1]*dd2;
+      v[0][2] = w2[2]*dd2;
+    }
+
+    /* 3rd vector orthogonal */
+    v[1][0] = v[2][1]*v[0][2] - v[2][2]*v[0][1];
+    v[1][1] = v[2][2]*v[0][0] - v[2][0]*v[0][2];
+    v[1][2] = v[2][0]*v[0][1] - v[2][1]*v[0][0];
+    dd1 = v[1][0]*v[1][0] + v[1][1]*v[1][1] + v[1][2]*v[1][2];
+    dd1 = 1.0 / sqrt(dd1);
+    v[1][0] *= dd1;
+    v[1][1] *= dd1;
+    v[1][2] *= dd1;
+  }
+
+  lambda[0] *= maxm;
+  lambda[1] *= maxm;
+  lambda[2] *= maxm;
+
+  /* check accuracy */
+  /*-------------------------------------------------------------------
+  if ( ddebug && symmat ) {
+    double  err,tmpx,tmpy,tmpz;
+    float   m[6];
+    int     i,j;
+
+    k = 0;
+    for (i=0; i<3; i++)
+      for (j=i; j<3; j++)
+        m[k++] = lambda[0]*v[i][0]*v[j][0]
+               + lambda[1]*v[i][1]*v[j][1]
+               + lambda[2]*v[i][2]*v[j][2];
+    err = fabs(mat[0]-m[0]);
+    for (i=1; i<6; i++)
+      if ( fabs(m[i]-mat[i]) > err )  err = fabs(m[i]-mat[i]);
+
+    if ( err > 1.e03*maxm ) {
+      printf("\nProbleme eigenv3: err= %f\n",err*maxm);
+      printf("mat depart :\n");
+      printf("%13.6f  %13.6f  %13.6f\n",mat[0],mat[1],mat[2]);
+      printf("%13.6f  %13.6f  %13.6f\n",mat[1],mat[3],mat[4]);
+      printf("%13.6f  %13.6f  %13.6f\n",mat[2],mat[4],mat[5]);
+      printf("mat finale :\n");
+      printf("%13.6f  %13.6f  %13.6f\n",m[0],m[1],m[2]);
+      printf("%13.6f  %13.6f  %13.6f\n",m[1],m[3],m[4]);
+      printf("%13.6f  %13.6f  %13.6f\n",m[2],m[4],m[5]);
+      printf("lambda : %f %f %f\n",lambda[0],lambda[1],lambda[2]);
+      printf(" ordre %d\n",n);
+      printf("\nOrtho:\n");
+      printf("v1.v2 = %.14f\n",
+             v[0][0]*v[1][0]+v[0][1]*v[1][1]+ v[0][2]*v[1][2]);
+      printf("v1.v3 = %.14f\n",
+             v[0][0]*v[2][0]+v[0][1]*v[2][1]+ v[0][2]*v[2][2]);
+      printf("v2.v3 = %.14f\n",
+             v[1][0]*v[2][0]+v[1][1]*v[2][1]+ v[1][2]*v[2][2]);
+      
+      printf("Consistency\n");
+      for (i=0; i<3; i++) {
+        tmpx = v[0][i]*m[0] + v[1][i]*m[1]
+             + v[2][i]*m[2] - lambda[i]*v[0][i];
+        tmpy = v[0][i]*m[1] + v[1][i]*m[3]
+             + v[2][i]*m[4] - lambda[i]*v[1][i];
+        tmpz = v[0][i]*m[2] + v[1][i]*m[4]
+             + v[2][i]*m[5] - lambda[i]*v[2][i];
+        printf(" Av %d - lambda %d *v %d = %f %f %f\n",
+        i,i,i,tmpx,tmpy,tmpz);
+        
+        printf("w1 %f %f %f\n",w1[0],w1[1],w1[2]);
+        printf("w2 %f %f %f\n",w2[0],w2[1],w2[2]);
+        printf("w3 %f %f %f\n",w3[0],w3[1],w3[2]);
+      }
+      exit(1);
+    }
+  }
+  -------------------------------------------------------------------*/
+
+  return(n);
+}
+
+
+/* eigen value + vector extraction */
+int eigen2(double *mm,double *lambda,double vp[2][2]) {
+  double   m[3],dd,a1,xn,ddeltb,rr1,rr2,ux,uy;
+
+  /* init */
+  ux = 1.0;
+  uy = 0.0;
+
+  /* normalize */
+  memcpy(m,mm,3*sizeof(double));
+  xn = fabs(m[0]);
+  if ( fabs(m[1]) > xn )  xn = fabs(m[1]);
+  if ( fabs(m[2]) > xn )  xn = fabs(m[2]);
+  if ( xn < EPSD2 ) {
+    lambda[0] = lambda[1] = 0.0;
+    vp[0][0] = 1.0; 
+    vp[0][1] = 0.0;
+    vp[1][0] = 0.0;
+    vp[1][1] = 1.0;
+    return(1);
+  }
+  xn = 1.0 / xn;
+  m[0] *= xn;
+  m[1] *= xn;
+  m[2] *= xn;
+
+  if ( egal(m[1],0.0) ) {
+    rr1 = m[0];
+    rr2 = m[2];
+    goto vect;
+  }
+
+  /* eigenvalues of jacobian */
+  a1	 = -(m[0] + m[2]);
+  ddeltb = a1*a1 - 4.0 * (m[0]*m[2] - m[1]*m[1]);
+
+  if ( ddeltb < 0.0 ) {
+    fprintf(stderr,"  Delta: %f\n",ddeltb);
+    ddeltb = 0.0;
+  }
+  ddeltb = sqrt(ddeltb);
+
+  if ( fabs(a1) < EPS ) {
+    rr1 = 0.5 * sqrt(ddeltb);
+    rr2 = -rr1;
+  } 
+  else if ( a1 < 0.0 ) {
+    rr1 = 0.5 * (-a1 + ddeltb);
+    rr2 = (-m[1]*m[1] + m[0]*m[2]) / rr1;
+  }
+  else if ( a1 > 0.0 ) {
+    rr1 = 0.5 * (-a1 - ddeltb);
+    rr2 = (-m[1]*m[1] + m[0]*m[2]) / rr1;
+  }
+  else {
+    rr1 = 0.5 * ddeltb;
+    rr2 = -rr1;
+  }
+
+vect:
+  xn = 1.0 / xn;
+  lambda[0] = rr1 * xn;
+  lambda[1] = rr2 * xn;
+
+  /* eigenvectors */
+  a1 = m[0] - rr1;
+  if ( fabs(a1)+fabs(m[1]) < EPS ) {
+    if (fabs(lambda[1]) < fabs(lambda[0]) ) {
+      ux = 1.0;
+      uy = 0.0;    
+    }
+    else {
+      ux = 0.0;
+      uy = 1.0;
+    }
+  }
+  else if ( fabs(a1) < fabs(m[1]) ) {
+    ux = 1.0;
+    uy = -a1 / m[1];
+  }
+  else if ( fabs(a1) > fabs(m[1]) ) {
+    ux = -m[1] / a1;
+    uy = 1.0;
+  }
+  else if ( fabs(lambda[1]) > fabs(lambda[0]) ) {
+    ux = 0.0;
+    uy = 1.0;
+  }
+  else {
+    ux = 1.0;
+    uy = 0.0;
+  }
+
+  dd = sqrt(ux*ux + uy*uy);
+  dd = 1.0 / dd;
+  if ( fabs(lambda[0]) > fabs(lambda[1]) ) {
+    vp[0][0] =  ux * dd;
+    vp[0][1] =  uy * dd;
+  }
+  else {
+    vp[0][0] =  uy * dd;
+    vp[0][1] = -ux * dd;
+  }
+
+  /* orthogonal vector */
+  vp[1][0] = -vp[0][1];
+  vp[1][1] =  vp[0][0];
+
+  return(1);
+}
diff --git a/src/libMesh/eigenv.h b/src/libMesh/eigenv.h
new file mode 100644
index 0000000..8b1d266
--- /dev/null
+++ b/src/libMesh/eigenv.h
@@ -0,0 +1,10 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int eigenv(int symmat,double *mat,double lambda[3],double v[3][3]);
+int eigen2(double *mm,double *lambda,double vp[2][2]);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libMesh/libmesh3.c b/src/libMesh/libmesh3.c
new file mode 100644
index 0000000..b49d3f6
--- /dev/null
+++ b/src/libMesh/libmesh3.c
@@ -0,0 +1,937 @@
+
+
+/*----------------------------------------------------------*/
+/*															*/
+/*						LIBMESH V 3.0						*/
+/*															*/
+/*----------------------------------------------------------*/
+/*															*/
+/*	Description:		handle .meshb file format I/O		*/
+/*	Author:				Loic MARECHAL						*/
+/*	Creation date:		aug  2 2003							*/
+/*	Last modification:	jan 25 2006							*/
+/*															*/
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Includes													*/
+/*----------------------------------------------------------*/
+
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <ctype.h>
+#include "libmesh3.h"
+
+
+/*----------------------------------------------------------*/
+/* Global variables											*/
+/*----------------------------------------------------------*/
+
+char *LM_kw_table[ LM_NBKW + 1 ][3] = 
+{	{"Reserved", "", ""},
+	{"MeshVersionFormatted", "", "i"},
+	{"Reserved", "", ""},
+	{"Dimension", "", "i"},
+	{"Vertices", "i", "dri"},
+	{"Edges", "i", "iii"},
+	{"Triangles", "i", "iiii"},
+	{"Quadrilaterals", "i", "iiiii"},
+	{"Tetrahedra", "i", "iiiii"},
+	{"Pentahedra", "i", "iiiiiii"},
+	{"Hexahedra", "i", "iiiiiiiii"},
+	{"SubDomainFromGeom", "i", "iiii"},
+	{"SubDomainFromMesh", "i", "iiii"},
+	{"Corners", "i", "i"},
+	{"Ridges", "i", "i"},
+	{"RequiredVertices", "i", "i"},
+	{"RequiredEdges", "i", "i"},
+	{"RequiredTriangles", "i", "i"},
+	{"RequiredQuadrilaterals", "i", "i"},
+	{"TangentAtEdgeVertices", "i", "iii"},
+	{"NormalAtVertices", "i", "ii"},
+	{"NormalAtTriangleVertices", "i", "iii"},
+	{"NormalAtQuadrilateralVertices", "i", "iiii"},
+	{"AngleOfCornerBound", "", "r"},
+	{"Geometry", "", "c"},
+	{"VertexOnGeometricVertex", "i", "ii"},
+	{"VertexOnGeometricEdge", "i", "iir"},
+	{"VertexOnGeometricTriangle", "i", "iirr"},
+	{"VertexOnGeometricQuadrilateral", "i", "iirr"},
+	{"EdgeOnGeometricEdge", "i", "ii"},
+	{"TriangleOnGeometricTriangle", "i", "ii"},
+	{"TriangleOnGeometricQuadrilateral", "i", "ii"},
+	{"QuadrilateralOnGeometricTriangle", "i", "ii"},
+	{"QuadrilateralOnGeometricQuadrilateral", "i", "ii"},
+	{"MeshSupportOfVertices", "", "c"},
+	{"VertexOnSupportVertex", "i", "ii"},
+	{"VertexOnSupportEdge", "i", "iir"},
+	{"VertexOnSupportTriangle", "i", "iirr"},
+	{"VertexOnSupportQuadrilateral", "i", "iirr"},
+	{"VertexOnSupportTetrahedron", "i", "iirrr"},
+	{"VertexOnSupportPentahedron", "i", "iirrr"},
+	{"VertexOnSupportHexahedron", "i", "iirrr"},
+	{"CrackedEdges", "i", "ii"},
+	{"CrackedTriangles", "i", "ii"},
+	{"CrackedQuadrilaterals", "i", "ii"},
+	{"EquivalentEdges", "i", "ii"},
+	{"EquivalentTriangles", "i", "ii"},
+	{"EquivalentQuadrilaterals", "i", "ii"},
+	{"PhysicsReference", "i", "ic"},
+	{"IncludeFile", "", "c"},
+	{"BoundingBox", "", "drdr"},
+	{"Identifier", "", "c"},
+	{"IdentityOfGeometry", "", "c"},
+	{"IdentityOfMeshSupport", "", "c"},
+	{"End", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Tangents", "i", "dr"},
+	{"Normals", "i", "dr"},
+	{"TangentAtVertices", "i", "ii"},
+	{"SolAtVertices", "i", "sr"},
+	{"SolAtEdges", "i", "sr"},
+	{"SolAtTriangles", "i", "sr"},
+	{"SolAtQuadrilaterals", "i", "sr"},
+	{"SolAtTetrahedra", "i", "sr"},
+	{"SolAtPentahedra", "i", "sr"},
+	{"SolAtHexahedra", "i", "sr"},
+	{"DSolAtVertices", "i", "sr"},
+	{"ISolAtVertices", "i", "i"},
+	{"ISolAtEdges", "i", "ii"},
+	{"ISolAtTriangles", "i", "iii"},
+	{"ISolAtQuadrilaterals", "i", "iiii"},
+	{"ISolAtTetrahedra", "i", "iiii"},
+	{"ISolAtPentahedra", "i", "iiiiii"},
+	{"ISolAtHexahedra", "i", "iiiiiiii"},
+	{"Iterations","","i"},
+	{"Time","","r"},
+	{"VertexHack","","drdr"}
+ };
+
+
+/*----------------------------------------------------------*/
+/* Prototypes of local procedures							*/
+/*----------------------------------------------------------*/
+
+static void write_kw(LM_mesh_struct *, int);
+static int read_int(LM_mesh_struct *);
+static void write_int(LM_mesh_struct *, int);
+static void file2kw_tab(LM_mesh_struct *);
+static void kw_tab2file(LM_mesh_struct *);
+static int expand_format(LM_mesh_struct *, int, char *);
+static void swap_bytes(void *, void *, int);
+static void read_sol_headers(LM_mesh_struct *);
+
+
+/*----------------------------------------------------------*/
+/* Open a mesh file in read or write mode					*/
+/*----------------------------------------------------------*/
+
+int LM_open_mesh(const char *filename, int mode, LM_mesh_struct *mesh, ...)
+{
+	int i;
+	va_list pa;
+	
+
+	/*---------------------*/
+	/* MESH STRUCTURE INIT */
+	/*---------------------*/
+
+	/* Init the kw table */
+
+	for(i=0;i<=LM_NBKW;i++)
+	{
+		mesh->kw_counters[i] = 0;
+		mesh->kw_pos[i][0] = 0;
+		mesh->kw_pos[i][1] = 0;
+		mesh->kw_pos[i][2] = 0;
+		mesh->sol_headers[i] = NULL;
+	}
+
+	/* Allocate a string large enough to contain the full filename and path plus the ".meshb" extension. */
+
+	mesh->filename = (char *)calloc((strlen(filename) + 7), sizeof(char));
+	strcpy(mesh->filename, filename);
+
+	/* Store the opening mode (read or write) and guess the filetype (binary or ascii) depending on the extension */
+
+	mesh->mode = mode;
+	mesh->current_kw = mesh->type = 0;
+	mesh->endian = 1;
+
+	if(strstr(mesh->filename, ".meshb"))
+		mesh->type |= (LM_BINARY | LM_MESH);
+	else if(strstr(mesh->filename, ".mesh"))
+		mesh->type |= (LM_ASCII | LM_MESH);
+	else if(strstr(mesh->filename, ".solb"))
+		mesh->type |= (LM_BINARY | LM_SOL);
+	else if(strstr(mesh->filename, ".sol"))
+		mesh->type |= (LM_ASCII | LM_SOL);
+	else
+		return(0);
+
+	/* Open the file in the required mode and initialyse the mesh structure */
+
+	if(mesh->mode == LM_READ)
+	{
+
+		/*-----------------------*/
+		/* OPEN FILE FOR READING */
+		/*-----------------------*/
+
+		/* Create the name string and open the file */
+
+		if(!(mesh->handle = fopen(mesh->filename, "rb")))
+			return(0);
+
+		/* Read the endian tag and the mesh version in binary */
+
+		if(mesh->type & LM_BINARY)
+		{
+			mesh->endian = read_int(mesh);
+
+			if( (mesh->endian != 1) && (mesh->endian != 16777216) )
+				return(0);
+
+			mesh->version = read_int(mesh);
+		}
+
+
+		/*------------*/
+		/* KW READING */
+		/*------------*/
+
+		/* Read the list of kw present in the file */
+
+		file2kw_tab(mesh);
+
+		/* Check the mesh dimension */
+
+		if(!mesh->kw_counters[ LM_Dimension ])
+			return(0);
+
+		LM_read_field(mesh, LM_Dimension, 1, &mesh->dimension);
+
+		if( (mesh->dimension != 2) && (mesh->dimension != 3) )
+			return(0);
+
+		/* Read the meshversion in ascii case */
+
+		if(mesh->type & LM_ASCII)
+			LM_read_field(mesh, LM_MeshVersionFormatted, 1, &mesh->version);
+
+		/* And read the extended sol headers */
+
+		read_sol_headers(mesh);
+	}
+	else if(mesh->mode == LM_WRITE)
+	{
+
+		/*-----------------------*/
+		/* OPEN FILE FOR WRITING */
+		/*-----------------------*/
+
+		/* Check if the user provided a valid dimension */
+
+		va_start(pa, mesh);
+		mesh->dimension = va_arg(pa, int);
+		va_end(pa);
+
+		if( (mesh->dimension != 2) && (mesh->dimension != 3) )
+			return(0);
+
+		/* If no extension has been provided, create a binary file */
+
+		if(!(mesh->handle = fopen(mesh->filename, "wb")))
+			return(0);
+
+
+		/*------------*/
+		/* KW WRITING */
+		/*------------*/
+
+		/* Initialyse the required fields. The kw will be stored afterward. */
+
+		mesh->version = LM_MESH_VERSION;
+		mesh->endian = 1;
+
+		/* Write the mesh version */
+
+		if(mesh->type & LM_ASCII)
+			LM_write_field(mesh, LM_MeshVersionFormatted, 1, &mesh->version);
+		else
+		{
+			write_int(mesh, mesh->endian);
+			write_int(mesh, mesh->version);
+		}
+
+		/* Write the mesh dimension */
+
+		LM_write_field(mesh, LM_Dimension, 1, &mesh->dimension);
+	}
+	else
+		return(0);
+
+	return(1);
+}
+
+
+/*----------------------------------------------------------*/
+/* Close a meshfile in the right way						*/
+/*----------------------------------------------------------*/
+
+int LM_close_mesh(LM_mesh_struct *mesh)
+{
+	if(mesh->mode == LM_WRITE)
+	{
+		/* Test if the user wrote the "End" kw */
+
+		if(!mesh->kw_counters[ LM_End ])
+			LM_write_field(mesh, LM_End, 0, NULL);
+
+		/* Write down the number lines written in each field to the file */
+
+		kw_tab2file(mesh);
+	}
+
+	if(fclose(mesh->handle))
+		return(0);
+	else
+		return(1);
+}
+
+
+/*----------------------------------------------------------*/
+/* Bufferized read of a whole orpart of a field				*/
+/*----------------------------------------------------------*/
+
+int LM_read_field(LM_mesh_struct *mesh, int kw_code, int nbl, void *buffer)
+{
+	int i, j, swaped, size, *int_buffer = (int *)buffer, string_size;
+	float *flt_buffer = (float *)buffer;
+	char format[256], letter, str_buf[256];
+
+	/* Check if the kw code is valid */
+
+	if( (kw_code < 1) || (kw_code > LM_NBKW) )
+		return(0);
+
+	/* Check if this kw has a format */
+
+	if(!strlen(LM_kw_table[ kw_code ][2]))
+		return(0);
+
+	/* If this kw is only a header, the number of lines to be read is set to one */
+
+	if(!strlen(LM_kw_table[ kw_code ][1]))
+		nbl = 1;
+
+	/* Check if the user is not asking more lines than the remaining lines in the file */
+
+	if(nbl > mesh->kw_counters[ kw_code ] - mesh->kw_pos[ kw_code ][2])
+		nbl = mesh->kw_counters[ kw_code ] - mesh->kw_pos[ kw_code ][2];
+
+	if(!nbl)
+		return(0);
+
+	/* Set the curent position in file to the begining of this kw's data */
+
+	fseek(mesh->handle, mesh->kw_pos[ kw_code ][1], SEEK_SET);
+
+	/* Transform the internal format into a "c" format string for the scanf and compute the size of 
+		field's line in order to compute the right adresses in the buffer */
+
+	size = expand_format(mesh, kw_code, format);
+
+	if(mesh->type & LM_ASCII)
+	{
+		for(i=0;i<nbl;i++)
+			for(j=0;j<size;j++)
+				if(format[j] == 'i')
+					fscanf(mesh->handle, "%d", &int_buffer[ i * size + j ]);
+				else if(format[j] == 'r')
+					fscanf(mesh->handle, "%g", &flt_buffer[ i * size + j ]);
+				else if(format[j] == 'c')
+				{
+					string_size = 0;
+
+					do
+					{
+						fscanf(mesh->handle, "%c", &letter);
+					}while(letter != '"');
+
+					do
+					{
+						fscanf(mesh->handle, "%c", &letter);
+						str_buf[ string_size++ ] = letter;
+					}while( (letter != '"') && (string_size <= 256) );
+
+					str_buf[ string_size-1 ] = 0;
+
+					memset(&flt_buffer[ i * size + j ], 0, 256);
+					strcpy((char *)&flt_buffer[ i * size + j ], str_buf);
+				}
+	}
+	else
+	{
+		fread(buffer, nbl * size * 4, 1, mesh->handle);
+
+		/* Swap the bytes in the whole buffer in case of different endian */
+
+		if(mesh->endian != 1)
+			for(i=0;i<nbl*size;i++)
+			{
+				swap_bytes((void *)&int_buffer[i], (void *)&swaped, 4);
+				int_buffer[i] = swaped;
+			}
+	}
+
+	/* Then store the curent position and the total number of read lines in case we didn't read the whole data */
+
+	mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
+	mesh->kw_pos[ kw_code ][2] += nbl;
+
+	return(nbl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Bufferized write of a whole field or part of it			*/
+/*----------------------------------------------------------*/
+
+int LM_write_field(LM_mesh_struct *mesh, int kw_code, int nbl, void *buffer, ...)
+{
+	int i, j, size, *int_buffer = (int *)buffer, nbsol;
+	float *flt_buffer = (float *)buffer;
+	char format[256];
+	va_list pa;
+
+	/* Check if the kw code is valid */
+
+	if( (kw_code < 1) || (kw_code > LM_NBKW) )
+		return(0);
+
+	/* Read further arguments if this kw is solution field and the extra header was not provided by the user */
+
+	if(!mesh->sol_headers[ kw_code ] && !strcmp(LM_kw_table[ kw_code ][2], "sr"))
+	{
+		va_start(pa, buffer);
+
+		nbsol = va_arg(pa, int);
+
+		if(!(mesh->sol_headers[ kw_code ] = malloc((nbsol+2) * sizeof(int))))
+			return(0);
+
+		mesh->sol_headers[ kw_code ][0] = nbsol;
+		mesh->sol_headers[ kw_code ][1] = 0;
+
+		for(i=1;i<=nbsol;i++)
+		{
+			mesh->sol_headers[ kw_code ][i+1] = va_arg(pa, int);
+
+			switch(mesh->sol_headers[ kw_code ][i+1])
+			{
+				case 1 : mesh->sol_headers[ kw_code ][1] += 1; break;
+				case 2 : mesh->sol_headers[ kw_code ][1] += mesh->dimension; break;
+				case 3 : mesh->sol_headers[ kw_code ][1] += (mesh->dimension * (mesh->dimension+1)) / 2; break;
+				case 4 : mesh->sol_headers[ kw_code ][1] += mesh->dimension * mesh->dimension; break;
+			}
+		}
+
+		va_end(pa);
+	}
+
+	/* If this kw is only a header, the number of lines to be read is set to one */
+
+	if(!strlen(LM_kw_table[ kw_code ][1]))
+		nbl = 1;
+
+	if(!mesh->kw_counters[ kw_code ])
+		write_kw(mesh, kw_code);
+
+	mesh->kw_counters[ kw_code ] += nbl;
+
+	/* Check if this kw has a format */
+
+	if(!strlen(LM_kw_table[ kw_code ][2]))
+		return(0);
+
+	size = expand_format(mesh, kw_code, format);
+
+	if(mesh->type & LM_ASCII)
+	{
+		for(i=0;i<nbl;i++)
+		{
+			for(j=0;j<size;j++)
+				if(format[j] == 'i')
+					fprintf(mesh->handle, "%d ", int_buffer[ i * size + j ]);
+				else if(format[j] == 'r')
+					fprintf(mesh->handle, "%g ", flt_buffer[ i * size + j ]);
+				else if(format[j] == 'c')
+				{
+					fputc('"', mesh->handle);
+					fprintf(mesh->handle, "%s", (char *)&flt_buffer[ i * size + j ]);
+					fputc('"', mesh->handle);
+				}
+
+			fprintf(mesh->handle, "\n");
+		}
+	}
+	else
+		fwrite(buffer, nbl * size * 4, 1, mesh->handle);
+
+	mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
+
+	return(1);
+}
+
+
+/*----------------------------------------------------------*/
+/* Single line read											*/
+/*----------------------------------------------------------*/
+
+int LM_read_line(LM_mesh_struct *mesh, int kw_code, ...)
+{
+	float buffer[10], *ptr_flt;
+	int i, size;
+	char format[256];
+	va_list pa;
+
+	/* Check wether this kw is not a simple header */
+
+	if(!strlen(LM_kw_table[ kw_code ][2]))
+		return(0);
+
+	/* Get a one line buffer */
+
+	LM_read_field(mesh, kw_code, 1, buffer);
+
+	/* Start decoding the arguments */
+
+	va_start(pa, kw_code);
+	size = expand_format(mesh, kw_code, format);
+
+	for(i=0;i<size;i++)
+	{
+		ptr_flt = va_arg(pa, float *);
+		*ptr_flt = buffer[i];
+	}
+
+	va_end(pa);
+
+	/* return the number of arguments filled */
+
+	return(size);
+}
+
+
+/*----------------------------------------------------------*/
+/* Single line write										*/
+/*----------------------------------------------------------*/
+
+int LM_write_line(LM_mesh_struct *mesh, int kw_code, ...)
+{
+	float buffer[10], *ptr_flt;
+	int i, size;
+	char format[256];
+	va_list pa;
+
+	/* Check wether this kw is not a simple header */
+
+	if(!strlen(LM_kw_table[ kw_code ][2]))
+		return(0);
+
+	/* Start decoding the arguments */
+
+	va_start(pa, kw_code);
+	size = expand_format(mesh, kw_code, format);
+
+	for(i=0;i<size;i++)
+	{
+		ptr_flt = va_arg(pa, float *);
+		buffer[i] = *ptr_flt;
+	}
+
+	va_end(pa);
+
+	/* Write a one line buffer */
+
+	LM_write_field(mesh, kw_code, 1, buffer);
+
+	/* return the number of arguments filled */
+
+	return(size);
+}
+
+
+/*----------------------------------------------------------*/
+/* Find every kw present in a meshfile						*/
+/*----------------------------------------------------------*/
+
+static void file2kw_tab(LM_mesh_struct *mesh)
+{
+	int kw_code, next_pos;
+	char str[256];
+
+	if(mesh->type & LM_ASCII)
+	{
+		/* Scan each string of the file until the end */
+
+		while(fscanf(mesh->handle, "%s", str) != EOF)
+		{
+			/* Fast test in order to reject quickly the numeric values */
+
+			if(isalpha(str[0]))
+			{
+				/* Search which kw code this string is associated with */
+
+				for(kw_code=1; kw_code<= LM_NBKW; kw_code++)
+					if(!strcmp(str, LM_kw_table[ kw_code ][0]))
+					{
+						/* The base position (0) in the file is set right after the kw */
+
+						mesh->kw_pos[ kw_code ][0] = ftell(mesh->handle);
+
+						/* If this kw has a header, read the number of lines */
+
+						if(!strcmp(LM_kw_table[ kw_code ][1], "i"))
+							mesh->kw_counters[ kw_code ] = read_int(mesh);
+						else
+							mesh->kw_counters[ kw_code ] = 1;
+
+						/* The curent position (1) in the file is set right before the data */
+
+						mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
+						break;
+					}
+			}
+			else if(str[0] == '#')
+				while(fgetc(mesh->handle) != '\n');
+		}
+	}
+	else
+	{
+		/* Jump through kw positions in the file */
+
+		do
+		{
+			kw_code = read_int(mesh);
+
+			/* Check if this kw belongs to this mesh version */
+
+			if( (kw_code >= 1) && (kw_code <= LM_NBKW) )
+			{
+				/* The base position (0) in the file is set right after the kw */
+
+				mesh->kw_pos[ kw_code ][0] =  ftell(mesh->handle);
+
+				/* Read the next kw position */
+
+				next_pos =  read_int(mesh);
+
+				/* If this kw has a header, read the number of lines */
+
+				if(!strcmp(LM_kw_table[ kw_code ][1], "i"))
+					mesh->kw_counters[ kw_code ] = read_int(mesh);
+				else
+					mesh->kw_counters[ kw_code ] = 1;
+
+				/* The curent position (1) in the file is set right before the data */
+
+				mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
+			}
+			else
+			{
+				/* Otherwise, read the next kw position in order to skip these unknown kw */
+
+				next_pos =  read_int(mesh);
+			}
+
+			/* Go to the next kw */
+
+			if(next_pos)
+				fseek(mesh->handle, next_pos, SEEK_SET);
+		}while(next_pos);
+	}
+}
+
+
+/*----------------------------------------------------------*/
+/* Update the number of lines written for each kw			*/
+/*----------------------------------------------------------*/
+
+static void kw_tab2file(LM_mesh_struct *mesh)
+{
+	int i;
+
+	for(i=1;i<=LM_NBKW;i++)
+		if( mesh->kw_counters[i] && strlen(LM_kw_table[i][2]) )
+			write_kw(mesh, i);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write the string associated with the kw code				*/
+/*----------------------------------------------------------*/
+
+static void write_kw(LM_mesh_struct *mesh, int kw_code)
+{
+	int i;
+
+	if(mesh->type & LM_ASCII)
+	{
+		/* Test if it is the first time this kw is written */
+
+		if(!mesh->kw_counters[ kw_code ])
+		{
+			/* If so, write the string and reserve some place afterward in order to store the 
+				number of lines */
+
+			fprintf(mesh->handle, "\n%s\n", LM_kw_table[ kw_code ][0]);
+
+			mesh->kw_pos[ kw_code ][0] = ftell(mesh->handle);
+
+			if(!strcmp("i", LM_kw_table[ kw_code ][1]))
+				fprintf(mesh->handle, "          \n");
+
+			/* In case of solution field, write the extended header at once */
+
+			if(mesh->sol_headers[ kw_code ])
+			{
+				fprintf(mesh->handle, "%d ", mesh->sol_headers[ kw_code ][0]);
+
+				for(i=1;i<=mesh->sol_headers[ kw_code ][0];i++)
+					fprintf(mesh->handle, "%d ", mesh->sol_headers[ kw_code ][i+1]);
+
+				fprintf(mesh->handle, "\n\n");
+			}
+
+			/* Store the positions right after the kw in order to write the number of lines at closing time.
+				Store the position right before the data for the write_field process. */
+
+			mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
+		}
+		else
+		{
+			/* If this kw has already be written in the file and has a header, go to pos(0) and write
+				down the final value */
+
+			if(strcmp("i", LM_kw_table[ kw_code ][1]))
+				return;
+
+			fseek(mesh->handle, mesh->kw_pos[ kw_code][0], SEEK_SET);
+			fprintf(mesh->handle, "%d\n", mesh->kw_counters[ kw_code ]);
+		}
+	}
+	else
+	{
+		/* Test if it is the first time this kw is written */
+
+		if(!mesh->kw_counters[ kw_code ])
+		{
+			/* If so, write the code, store the position afterward, reserve an int for the next kw position
+				and write the number of lines */
+
+			write_int(mesh, kw_code);
+			mesh->kw_pos[ kw_code ][0] = ftell(mesh->handle);
+			write_int(mesh, 0);
+
+			/* Set the next kw pos in the previously written kw */
+
+			if(mesh->current_kw)
+			{
+				fseek(mesh->handle, mesh->kw_pos[ mesh->current_kw ][0], SEEK_SET);
+				write_int(mesh, mesh->kw_pos[ kw_code ][0] - 4);
+				fseek(mesh->handle, mesh->kw_pos[ kw_code ][0] + 4, SEEK_SET);
+			}
+
+			mesh->current_kw = kw_code;
+
+			if(!strcmp("i", LM_kw_table[ kw_code ][1]))
+				write_int(mesh, 0);
+
+			/* In case of solution field, write the extended header at once */
+
+			if(mesh->sol_headers[ kw_code ])
+			{
+				write_int(mesh, mesh->sol_headers[ kw_code ][0]);
+
+				for(i=1;i<=mesh->sol_headers[ kw_code ][0];i++)
+					write_int(mesh, mesh->sol_headers[ kw_code ][i+1]);
+			}
+
+			mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
+		}
+		else
+		{
+			/* Write the number of lines written at closing time */
+
+			if(strcmp("i", LM_kw_table[ kw_code ][1]))
+				return;
+
+			fseek(mesh->handle, mesh->kw_pos[ kw_code ][0] + 4, SEEK_SET);
+			write_int(mesh, mesh->kw_counters[ kw_code ]);
+		}
+	}
+}
+
+
+/*----------------------------------------------------------*/
+/* Read an integer in a mesh file							*/
+/*----------------------------------------------------------*/
+
+static int read_int(LM_mesh_struct *mesh)
+{
+	int swaped, integer = 0;
+
+	if(mesh->type & LM_ASCII)
+		fscanf(mesh->handle, "%d", &integer);
+	else
+	{
+		/* Read a 4 bytes block in the file */
+
+		fread(&integer, 4, 1, mesh->handle);
+
+		if(mesh->endian != 1)
+		{
+			swap_bytes((void *)&integer, (void *)&swaped, 4);
+			integer = swaped;
+		}
+	}
+
+	return(integer);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write an integer in a mesh file							*/
+/*----------------------------------------------------------*/
+
+static void write_int(LM_mesh_struct *mesh, int integer)
+{
+	if(mesh->type & LM_ASCII)
+		fprintf(mesh->handle, "%d ", integer);
+	else
+		fwrite(&integer, 4, 1, mesh->handle);
+}
+
+
+/*----------------------------------------------------------*/
+/* Convert little endian <-> big endian						*/
+/*----------------------------------------------------------*/
+
+static void swap_bytes(void *c1, void *c2, int nbytes)
+{
+  int   k;
+  char *c11, *c22;
+
+  c11 = (char*)c1;
+  c22 = (char*)c2;
+
+  for (k=0; k<nbytes; k++)
+    c22[k] = c11[ nbytes-k-1 ];
+}
+
+
+/*----------------------------------------------------------*/
+/* Expand the compacted format and compute the line size	*/
+/*----------------------------------------------------------*/
+
+static int expand_format(LM_mesh_struct *mesh, int kw_code, char *out_format)
+{
+	int i, j, duplicate_next = 0, size = 0;
+	char *in_format = LM_kw_table[ kw_code ][2];
+
+	out_format[0] = '\0';
+
+	/* Scan each character of the format string */
+
+	for(i=0;i<strlen(in_format);i++)
+	{
+		if( (in_format[i] == 'i') || (in_format[i] == 'r') )
+		{
+			if(!duplicate_next)
+				duplicate_next = 1;
+
+			for(j=1;j<=duplicate_next;j++)
+			{
+				strncat(out_format, &in_format[i], 1);
+				size++;
+			}
+
+			duplicate_next = 0;
+		}
+		else if(in_format[i] == 'c')
+		{
+			strncat(out_format, &in_format[i], 1);
+			size += 64;
+		}
+		else if(in_format[i] == 'd')
+		{
+			/* 'd' means duplicate the next character mesh->dimension times */
+
+			duplicate_next = mesh->dimension;
+		}
+		else if(in_format[i] == 's')
+		{
+			/* 's' means duplicate the next character mesh->solsize times */
+
+			duplicate_next = mesh->sol_headers[ kw_code ][1];
+		}
+	}
+
+	/* Return the sum of item to be read */
+
+	return(size);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read the extended sol headers							*/
+/*----------------------------------------------------------*/
+
+static void read_sol_headers(LM_mesh_struct *mesh)
+{
+	int i, j, nbsol, solsize;
+
+	for(i=1;i<=LM_NBKW;i++)
+	{
+		/* If the kw is a special Sol field, read the extended header */
+
+		if(!mesh->kw_counters[i] || strcmp(LM_kw_table[i][2], "sr"))
+			continue;
+
+		/* Set the curent position in file to the begining of this kw's data */
+
+		fseek(mesh->handle, mesh->kw_pos[i][1], SEEK_SET);
+
+		nbsol = read_int(mesh);
+
+		if( (mesh->sol_headers[i] = malloc((nbsol+2) * sizeof(int))))
+		{
+			mesh->sol_headers[i][0] = nbsol;
+			solsize = 0;
+
+			for(j=1;j<=nbsol;j++)
+			{
+				mesh->sol_headers[i][j+1] = read_int(mesh);
+
+				switch(mesh->sol_headers[i][j+1])
+				{
+					case LM_SCALAR     : solsize += 1; break;
+					case LM_VECTOR     : solsize += mesh->dimension; break;
+					case LM_SYM_MATRIX : solsize += (mesh->dimension * (mesh->dimension+1)) / 2; break;
+					case LM_MATRIX     : solsize += mesh->dimension * mesh->dimension; break;
+				}
+
+				mesh->sol_headers[i][1] = solsize;
+			}
+
+			mesh->kw_pos[i][1] = ftell(mesh->handle);
+		}
+	}
+}
diff --git a/src/libMesh/libmesh3.h b/src/libMesh/libmesh3.h
new file mode 100644
index 0000000..3a84dae
--- /dev/null
+++ b/src/libMesh/libmesh3.h
@@ -0,0 +1,168 @@
+
+
+/*----------------------------------------------------------*/
+/*															*/
+/*						LIBMESH V 3.0						*/
+/*															*/
+/*----------------------------------------------------------*/
+/*															*/
+/*	Description:		handle .meshb file format I/O		*/
+/*	Author:				Loic MARECHAL						*/
+/*	Creation date:		aug 02 2003							*/
+/*	Last modification:	jan 25 2006							*/
+/*															*/
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Includes													*/
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+
+/*----------------------------------------------------------*/
+/* Defines													*/
+/*----------------------------------------------------------*/
+
+#define LM_NBKW 79
+#define LM_MESH_VERSION 1
+#define LM_INT 1
+#define LM_REAL 2
+#define LM_READ 1
+#define LM_WRITE 2
+#define LM_ASCII  1
+#define LM_BINARY 2
+#define LM_MESH   4
+#define LM_SOL    8
+#define LM_SCALAR 1
+#define LM_VECTOR 2
+#define LM_SYM_MATRIX 3
+#define LM_MATRIX 4
+
+enum LM_kw_tags
+{
+	LM_Reserved1, \
+	LM_MeshVersionFormatted, \
+	LM_Reserved2, \
+	LM_Dimension, \
+	LM_Vertices, \
+	LM_Edges, \
+	LM_Triangles, \
+	LM_Quadrilaterals, \
+	LM_Tetrahedra, \
+	LM_Pentahedra, \
+	LM_Hexahedra, \
+	LM_SubDomainFromGeom, \
+	LM_SubDomainFromMesh, \
+	LM_Corners, \
+	LM_Ridges, \
+	LM_RequiredVertices, \
+	LM_RequiredEdges, \
+	LM_RequiredTriangles, \
+	LM_RequiredQuadrilaterals, \
+	LM_TangentAtEdgeVertices, \
+	LM_NormalAtVertices, \
+	LM_NormalAtTriangleVertices, \
+	LM_NormalAtQuadrilateralVertices, \
+	LM_AngleOfCornerBound, \
+	LM_Geometry, \
+	LM_VertexOnGeometricVertex, \
+	LM_VertexOnGeometricEdge, \
+	LM_VertexOnGeometricTriangle, \
+	LM_VertexOnGeometricQuadrilateral, \
+	LM_EdgeOnGeometricEdge, \
+	LM_TriangleOnGeometricTriangle, \
+	LM_TriangleOnGeometricQuadrilateral, \
+	LM_QuadrilateralOnGeometricTriangle, \
+	LM_QuadrilateralOnGeometricQuadrilateral, \
+	LM_MeshSupportOfVertices, \
+	LM_VertexOnSupportVertex, \
+	LM_VertexOnSupportEdge, \
+	LM_VertexOnSupportTriangle, \
+	LM_VertexOnSupportQuadrilateral, \
+	LM_VertexOnSupportTetrahedron, \
+	LM_VertexOnSupportPentahedron, \
+	LM_VertexOnSupportHexahedron, \
+	LM_CrackedEdges, \
+	LM_CrackedTriangles, \
+	LM_CrackedQuadrilaterals, \
+	LM_EquivalentEdges, \
+	LM_EquivalentTriangles, \
+	LM_EquivalentQuadrilaterals, \
+	LM_PhysicsReference, \
+	LM_IncludeFile, \
+	LM_BoundingBox, \
+	LM_Identifier, \
+	LM_IdentityOfGeometry, \
+	LM_IdentityOfMeshSupport, \
+	LM_End, \
+	LM_Reserved10, \
+	LM_Reserved11, \
+	LM_Reserved12, \
+	LM_Reserved13, \
+	LM_Tangents, \
+	LM_Normals, \
+	LM_TangentAtVertices, \
+	LM_SolAtVertices, \
+	LM_SolAtEdges, \
+	LM_SolAtTriangles, \
+	LM_SolAtQuadrilaterals, \
+	LM_SolAtTetrahedra, \
+	LM_SolAtPentahedra, \
+	LM_SolAtHexahedra, \
+	LM_DSolAtVertices, \
+	LM_ISolAtVertices, \
+	LM_ISolAtEdges, \
+	LM_ISolAtTriangles, \
+	LM_ISolAtQuadrilaterals, \
+	LM_ISolAtTetrahedra, \
+	LM_ISolAtPentahedra, \
+	LM_ISolAtHexahedra, \
+	LM_Iterations, \
+	LM_Time, \
+	LM_VertexHack
+};
+
+
+/*----------------------------------------------------------*/
+/* Structures												*/
+/*----------------------------------------------------------*/
+
+typedef struct
+{
+	/* Public */
+
+	int dimension;
+	int kw_counters[ LM_NBKW + 1 ];
+	int *sol_headers[ LM_NBKW + 1 ];
+
+	/* Private */
+
+	int version, mode, type, endian, current_kw;
+	FILE *handle;
+	char *filename;
+	size_t kw_pos[ LM_NBKW + 1 ][3];
+}LM_mesh_struct;
+
+
+/*----------------------------------------------------------*/
+/* External tables and procedures							*/
+/*----------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+extern int LM_open_mesh(const char *, int, LM_mesh_struct *, ...);
+extern int LM_read_field(LM_mesh_struct *, int, int, void *);
+extern int LM_write_field(LM_mesh_struct *, int, int, void *, ...);
+extern int LM_read_line(LM_mesh_struct *, int, ...);
+extern int LM_write_line(LM_mesh_struct *, int, ...);
+extern int LM_close_mesh(LM_mesh_struct *);
+extern char *LM_kw_table[][3];
+#ifdef __cplusplus
+}
+#endif
+    
diff --git a/src/libMesh/libmesh5.c b/src/libMesh/libmesh5.c
new file mode 100644
index 0000000..677020f
--- /dev/null
+++ b/src/libMesh/libmesh5.c
@@ -0,0 +1,1260 @@
+
+
+/*----------------------------------------------------------*/
+/*															*/
+/*						LIBMESH V 5.0						*/
+/*															*/
+/*----------------------------------------------------------*/
+/*															*/
+/*	Description:		handle .meshb file format I/O		*/
+/*	Author:				Loic MARECHAL						*/
+/*	Creation date:		feb 16 2007							*/
+/*	Last modification:	jul 12 2007							*/
+/*															*/
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Includes													*/
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <ctype.h>
+#include "libmesh5.h"
+
+
+/*----------------------------------------------------------*/
+/* Structures												*/
+/*----------------------------------------------------------*/
+
+typedef struct
+{
+	int pos, typ, SolSiz, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ];
+	char fmt[ GmfMaxTyp ];
+}KwdSct;
+
+typedef struct
+{
+	int dim, ver, iter, mod, typ, cod, NexKwdPos;
+	double angle, bbox[3][2], time;
+	KwdSct KwdTab[ GmfMaxKwd + 1 ];
+	FILE *hdl;
+	char FilNam[ GmfStrSiz ];
+}GmfMshSct;
+
+
+/*----------------------------------------------------------*/
+/* Defines													*/
+/*----------------------------------------------------------*/
+
+#define Asc 1
+#define Bin 2
+#define MshFil 4
+#define SolFil 8
+#define MaxMsh 100
+#define InfKwd 1
+#define RegKwd 2
+#define SolKwd 3
+#define WrdSiz 4
+
+
+/*----------------------------------------------------------*/
+/* Global variables											*/
+/*----------------------------------------------------------*/
+
+int IniFlg=0;
+GmfMshSct *MshTab[ MaxMsh + 1 ];
+char *KwdFmt[ GmfMaxKwd + 1 ][3] = 
+{	{"Reserved", "", ""},
+	{"MeshVersionFormatted", "", "i"},
+	{"Reserved", "", ""},
+	{"Dimension", "", "i"},
+	{"Vertices", "i", "dri"},
+	{"Edges", "i", "iii"},
+	{"Triangles", "i", "iiii"},
+	{"Quadrilaterals", "i", "iiiii"},
+	{"Tetrahedra", "i", "iiiii"},
+	{"Pentahedra", "i", "iiiiiii"},
+	{"Hexahedra", "i", "iiiiiiiii"},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Corners", "i", "i"},
+	{"Ridges", "i", "i"},
+	{"RequiredVertices", "i", "i"},
+	{"RequiredEdges", "i", "i"},
+	{"RequiredTriangles", "i", "i"},
+	{"RequiredQuadrilaterals", "i", "i"},
+	{"TangentAtEdgeVertices", "i", "iii"},
+	{"NormalAtVertices", "i", "ii"},
+	{"NormalAtTriangleVertices", "i", "iii"},
+	{"NormalAtQuadrilateralVertices", "i", "iiii"},
+	{"AngleOfCornerBound", "", "r"},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"BoundingBox", "", "drdr"},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"End", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Reserved", "", ""},
+	{"Tangents", "i", "dr"},
+	{"Normals", "i", "dr"},
+	{"TangentAtVertices", "i", "ii"},
+	{"SolAtVertices", "i", "sr"},
+	{"SolAtEdges", "i", "sr"},
+	{"SolAtTriangles", "i", "sr"},
+	{"SolAtQuadrilaterals", "i", "sr"},
+	{"SolAtTetrahedra", "i", "sr"},
+	{"SolAtPentahedra", "i", "sr"},
+	{"SolAtHexahedra", "i", "sr"},
+	{"DSolAtVertices", "i", "sr"},
+	{"ISolAtVertices", "i", "i"},
+	{"ISolAtEdges", "i", "ii"},
+	{"ISolAtTriangles", "i", "iii"},
+	{"ISolAtQuadrilaterals", "i", "iiii"},
+	{"ISolAtTetrahedra", "i", "iiii"},
+	{"ISolAtPentahedra", "i", "iiiiii"},
+	{"ISolAtHexahedra", "i", "iiiiiiii"},
+	{"Iterations","","i"},
+	{"Time","","r"},
+	{"Reserved","",""}
+ };
+
+
+/*----------------------------------------------------------*/
+/* Prototypes of local procedures							*/
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *, unsigned char *);
+static void ScaDblWrd(GmfMshSct *, unsigned char *);
+static void RecWrd(GmfMshSct *, unsigned char *);
+static void RecDblWrd(GmfMshSct *, unsigned char *);
+static int ScaKwdTab(GmfMshSct *);
+static void ExpFmt(GmfMshSct *, int);
+static void ScaKwdHdr(GmfMshSct *, int);
+
+
+/*----------------------------------------------------------*/
+/* Open a mesh file in read or write mod					*/
+/*----------------------------------------------------------*/
+
+int GmfOpenMesh(const char *FilNam, int mod, ...)
+{
+	int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0;
+	char str[ GmfStrSiz ];
+	va_list par;
+	GmfMshSct *msh;
+
+	if(!IniFlg)
+	{
+	  for(i=0;i<MaxMsh;i++)
+	    MshTab[i] = NULL;
+
+	  IniFlg = 1;
+	}
+
+	/*---------------------*/
+	/* MESH STRUCTURE INIT */
+	/*---------------------*/
+
+	for(i=1;i<MaxMsh;i++)
+	  if(!MshTab[i])
+	    {
+	      MshIdx = i;
+	      break;
+	    }
+	
+	if( !MshIdx || !(msh = (GmfMshSct *) calloc(1, sizeof(GmfMshSct))) )
+	  return(0);
+
+	/* Copy the FilNam into the structure */
+
+	if(strlen(FilNam) + 7 >= GmfStrSiz)
+	  return(0);
+
+	strcpy(msh->FilNam, FilNam);
+
+	/* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
+
+	msh->mod = mod;
+
+	if(strstr(msh->FilNam, ".meshb"))
+		msh->typ |= (Bin | MshFil);
+	else if(strstr(msh->FilNam, ".mesh"))
+		msh->typ |= (Asc | MshFil);
+	else if(strstr(msh->FilNam, ".solb"))
+		msh->typ |= (Bin | SolFil);
+	else if(strstr(msh->FilNam, ".sol"))
+		msh->typ |= (Asc | SolFil);
+	else
+		return(0);
+
+	/* Open the file in the required mod and initialyse the mesh structure */
+
+	if(msh->mod == GmfRead)
+	{
+
+		/*-----------------------*/
+		/* OPEN FILE FOR READING */
+		/*-----------------------*/
+
+		va_start(par, mod);
+		PtrVer = va_arg(par, int *);
+		PtrDim = va_arg(par, int *);
+		va_end(par);
+
+		/* Create the name string and open the file */
+
+		if(!(msh->hdl = fopen(msh->FilNam, "rb")))
+			return(0);
+
+		/* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
+
+		if(msh->typ & Bin)
+		{
+			fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl);
+
+			if( (msh->cod != 1) && (msh->cod != 16777216) )
+				return(0);
+
+			ScaWrd(msh, (unsigned char *)&msh->ver);
+			ScaWrd(msh, (unsigned char *)&KwdCod);
+
+			if(KwdCod != GmfDimension)
+				return(0);
+
+			ScaWrd(msh, (unsigned char *)&KwdCod);
+			ScaWrd(msh, (unsigned char *)&msh->dim);
+		}
+		else
+		{
+			do
+			{
+				res = fscanf(msh->hdl, "%s", str);
+			}while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
+
+			if(res == EOF)
+				return(0);
+
+			fscanf(msh->hdl, "%d", &msh->ver);
+
+			do
+			{
+				res = fscanf(msh->hdl, "%s", str);
+			}while( (res != EOF) && strcmp(str, "Dimension") );
+
+			if(res == EOF)
+				return(0);
+
+			fscanf(msh->hdl, "%d", &msh->dim);
+		}
+
+		if( (msh->dim != 2) && (msh->dim != 3) )
+			return(0);
+
+		(*PtrVer) = msh->ver;
+		(*PtrDim) = msh->dim;
+
+		/*------------*/
+		/* KW READING */
+		/*------------*/
+
+		/* Read the list of kw present in the file */
+
+		if(!ScaKwdTab(msh))
+			return(0);
+
+		MshTab[ MshIdx ] = msh;
+
+		return(MshIdx);
+	}
+	else if(msh->mod == GmfWrite)
+	{
+
+		/*-----------------------*/
+		/* OPEN FILE FOR WRITING */
+		/*-----------------------*/
+
+		msh->cod = 1;
+
+		/* Check if the user provided a valid version number and dimension */
+
+		va_start(par, mod);
+		msh->ver = va_arg(par, int);
+		msh->dim = va_arg(par, int);
+		va_end(par);
+
+		if( (msh->ver != 1) && (msh->ver != 2) )
+			return(0);
+		if( (msh->dim != 2) && (msh->dim != 3) )
+			return(0);
+
+		/* Create the mesh file */
+
+		if(!(msh->hdl = fopen(msh->FilNam, "wb")))
+			return(0);
+
+		MshTab[ MshIdx ] = msh;
+
+
+		/*------------*/
+		/* KW WRITING */
+		/*------------*/
+
+		/* Write the mesh version and dimension */
+
+		if(msh->typ & Asc)
+		{
+			fprintf(msh->hdl, "%s %d\n\n", KwdFmt[ GmfVersionFormatted ][0], msh->ver);
+			fprintf(msh->hdl, "%s %d\n", KwdFmt[ GmfDimension ][0], msh->dim);
+		}
+		else
+		{
+			RecWrd(msh, (unsigned char *)&msh->cod);
+			RecWrd(msh, (unsigned char *)&msh->ver);
+			GmfSetKwd(MshIdx, GmfDimension, 0);
+			RecWrd(msh, (unsigned char *)&msh->dim);
+		}
+
+		return(MshIdx);
+	}
+	else
+		return(0);
+}
+
+
+/*----------------------------------------------------------*/
+/* Close a meshfile in the right way						*/
+/*----------------------------------------------------------*/
+
+int GmfCloseMesh(int MshIdx)
+{
+	int res = 1;
+	GmfMshSct *msh;
+
+	if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+	  return(0);
+	
+	fflush(stdout);
+	msh = MshTab[ MshIdx ];
+
+	/* In write down the "End" kw in write mode */
+
+	if(msh->mod == GmfWrite)
+		if(msh->typ & Asc)
+			fprintf(msh->hdl, "\n%s\n", KwdFmt[ GmfEnd ][0]);
+		else
+			GmfSetKwd(MshIdx, GmfEnd, 0);
+
+	/* Close the file and free the mesh structure */
+
+	if(fclose(msh->hdl))
+		res = 0;
+
+	free(msh);
+	MshTab[ MshIdx ] = NULL;
+	return(res);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read the number of lines and set the position to this kwd*/
+/*----------------------------------------------------------*/
+
+int GmfStatKwd(int MshIdx, int KwdCod, ...)
+{
+	int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
+	GmfMshSct *msh;
+	KwdSct *kwd;
+	va_list par;
+
+	if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+		return(0);
+
+	msh = MshTab[ MshIdx ];
+
+	if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+		return(0);
+
+	kwd = &msh->KwdTab[ KwdCod ];
+
+	if(!kwd->NmbLin)
+		return(0);
+
+	/* Read further arguments if this kw is a sol */
+
+	if(kwd->typ == SolKwd)
+	{
+		va_start(par, KwdCod);
+
+		PtrNmbTyp = va_arg(par, int *);
+		*PtrNmbTyp = kwd->NmbTyp;
+
+		PtrSolSiz = va_arg(par, int *);
+		*PtrSolSiz = kwd->SolSiz;
+
+		TypTab = va_arg(par, int *);
+
+		for(i=0;i<kwd->NmbTyp;i++)
+			TypTab[i] = kwd->TypTab[i];
+
+		va_end(par);
+	}
+
+	return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Set the current file position to a given kwd				*/
+/*----------------------------------------------------------*/
+
+int GmfGotoKwd(int MshIdx, int KwdCod)
+{
+	GmfMshSct *msh;
+	KwdSct *kwd;
+
+	if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+		return(0);
+
+	msh = MshTab[ MshIdx ];
+
+	if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+		return(0);
+
+	kwd = &msh->KwdTab[ KwdCod ];
+
+	if(!kwd->NmbLin)
+		return(0);
+
+	return(fseek(msh->hdl, kwd->pos, SEEK_SET));
+}
+
+
+/*----------------------------------------------------------*/
+/* Write the kwd and set the number of lines				*/
+/*----------------------------------------------------------*/
+
+int GmfSetKwd(int MshIdx, int KwdCod, ...)
+{
+	int i, CurPos, NmbLin=0, NulPos=0, *TypTab;
+	va_list par;
+	GmfMshSct *msh;
+	KwdSct *kwd;
+
+	if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+		return(0);
+
+	msh = MshTab[ MshIdx ];
+
+	if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+		return(0);
+
+	kwd = &msh->KwdTab[ KwdCod ];
+
+	/* Read further arguments if this kw has a header */
+
+	if(strlen(KwdFmt[ KwdCod ][1]))
+	{
+		va_start(par, KwdCod);
+		NmbLin = va_arg(par, int);
+
+		if(!strcmp(KwdFmt[ KwdCod ][2], "sr"))
+		{
+			kwd->NmbTyp = va_arg(par, int);
+			TypTab = va_arg(par, int *);
+
+			for(i=0;i<kwd->NmbTyp;i++)
+				kwd->TypTab[i] = TypTab[i];
+		}
+
+		va_end(par);
+	}
+
+	/* Setup the kwd info */
+
+	ExpFmt(msh, KwdCod);
+
+	if(!kwd->typ)
+		return(0);
+	else if(kwd->typ == InfKwd)
+		kwd->NmbLin = 1;
+	else
+		kwd->NmbLin = NmbLin;
+
+	/* Store the next kwd position in binary file */
+
+	if( (msh->typ & Bin) && msh->NexKwdPos )
+	{
+		CurPos = ftell(msh->hdl);
+		fseek(msh->hdl, msh->NexKwdPos, SEEK_SET);
+		RecWrd(msh, (unsigned char *)&CurPos);
+		fseek(msh->hdl, CurPos, SEEK_SET);
+	}
+
+	/* Write the header */
+
+	if(msh->typ & Asc)
+	{
+		fprintf(msh->hdl, "\n%s\n", KwdFmt[ KwdCod ][0]);
+
+		if(kwd->typ != InfKwd)
+			fprintf(msh->hdl, "%d\n", kwd->NmbLin);
+
+		/* In case of solution field, write the extended header */
+
+		if(kwd->typ == SolKwd)
+		{
+			fprintf(msh->hdl, "%d ", kwd->NmbTyp);
+
+			for(i=0;i<kwd->NmbTyp;i++)
+				fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
+
+			fprintf(msh->hdl, "\n\n");
+		}
+	}
+	else
+	{
+		RecWrd(msh, (unsigned char *)&KwdCod);
+		msh->NexKwdPos = ftell(msh->hdl);
+		RecWrd(msh, (unsigned char *)&NulPos);
+
+		if(kwd->typ != InfKwd)
+			RecWrd(msh, (unsigned char *)&kwd->NmbLin);
+
+		/* In case of solution field, write the extended header at once */
+
+		if(kwd->typ == SolKwd)
+		{
+			RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+			for(i=0;i<kwd->NmbTyp;i++)
+				RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+		}
+	}
+
+	return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a full line from the current kwd					*/
+/*----------------------------------------------------------*/
+
+void GmfGetLin(int MshIdx, int KwdCod, ...)
+{
+	double *DblPtr, *DblSolTab;
+	float *FltPtr, *FltSolTab;
+	int i, j, *IntPtr;
+	va_list par;
+	GmfMshSct *msh = MshTab[ MshIdx ];
+	KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+	/* Start decoding the arguments */
+
+	va_start(par, KwdCod);
+
+	if(kwd->typ != SolKwd)
+	{
+		if(msh->ver == 1)
+		{
+			if(msh->typ & Asc)
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						FltPtr = va_arg(par, float *);
+						fscanf(msh->hdl, "%f", FltPtr);
+					}
+					else
+					{
+						IntPtr = va_arg(par, int *);
+						fscanf(msh->hdl, "%d", IntPtr);
+					}
+				}
+			}
+			else
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						FltPtr = va_arg(par, float *);
+						ScaWrd(msh, (unsigned char *)FltPtr);
+					}
+					else
+					{
+						IntPtr = va_arg(par, int *);
+						ScaWrd(msh, (unsigned char *)IntPtr);
+					}
+				}
+			}
+		}
+		else
+		{
+			if(msh->typ & Asc)
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						DblPtr = va_arg(par, double *);
+						fscanf(msh->hdl, "%lf", DblPtr);
+					}
+					else
+					{
+						IntPtr = va_arg(par, int *);
+						fscanf(msh->hdl, "%d", IntPtr);
+					}
+				}
+			}
+			else
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						DblPtr = va_arg(par, double *);
+						ScaDblWrd(msh, (unsigned char *)DblPtr);
+					}
+					else
+					{
+						IntPtr = va_arg(par, int *);
+						ScaWrd(msh, (unsigned char *)IntPtr);
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		if(msh->ver == 1)
+		{
+			FltSolTab = va_arg(par, float *);
+
+			if(msh->typ & Asc)
+				for(j=0;j<kwd->SolSiz;j++)
+					fscanf(msh->hdl, "%f", &FltSolTab[j]);
+			else
+				for(j=0;j<kwd->SolSiz;j++)
+					ScaWrd(msh, (unsigned char *)&FltSolTab[j]);
+		}
+		else if(msh->ver == 2)
+		{
+			DblSolTab = va_arg(par, double *);
+
+			if(msh->typ & Asc)
+				for(j=0;j<kwd->SolSiz;j++)
+					fscanf(msh->hdl, "%lf", &DblSolTab[j]);
+			else
+				for(j=0;j<kwd->SolSiz;j++)
+					ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
+		}
+	}
+
+	va_end(par);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a full line from the current kwd					*/
+/*----------------------------------------------------------*/
+
+void GmfSetLin(int MshIdx, int KwdCod, ...)
+{
+	double d, *DblSolTab;
+	float f, *FltSolTab;
+	int i, j;
+	va_list par;
+	GmfMshSct *msh = MshTab[ MshIdx ];
+	KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+	/* Start decoding the arguments */
+
+	va_start(par, KwdCod);
+
+	if(kwd->typ != SolKwd)
+	{
+		if(msh->ver == 1)
+		{
+			if(msh->typ & Asc)
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						d = va_arg(par, double);
+						fprintf(msh->hdl, "%g ", (float)d);
+					}
+					else
+					{
+						j = va_arg(par, int);
+						fprintf(msh->hdl, "%d ", j);
+					}
+				}
+			}
+			else
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						d = va_arg(par, double);
+						f = d;
+						RecWrd(msh, (unsigned char *)&f);
+					}
+					else
+					{
+						j = va_arg(par, int);
+						RecWrd(msh, (unsigned char *)&j);
+					}
+				}
+			}
+		}
+		else
+		{
+			if(msh->typ & Asc)
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						d = va_arg(par, double);
+						fprintf(msh->hdl, "%.15lg ", d);
+					}
+					else
+					{
+						j = va_arg(par, int);
+						fprintf(msh->hdl, "%d ", j);
+					}
+				}
+			}
+			else
+			{
+				for(i=0;i<kwd->SolSiz;i++)
+				{
+					if(kwd->fmt[i] == 'r')
+					{
+						d = va_arg(par, double);
+						RecDblWrd(msh, (unsigned char *)&d);
+					}
+					else
+					{
+						j = va_arg(par, int);
+						RecWrd(msh, (unsigned char *)&j);
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		if(msh->ver == 1)
+		{
+			FltSolTab = va_arg(par, float *);
+
+			if(msh->typ & Asc)
+				for(j=0;j<kwd->SolSiz;j++)
+					fprintf(msh->hdl, "%g ", FltSolTab[j]);
+			else
+				for(j=0;j<kwd->SolSiz;j++)
+					RecWrd(msh, (unsigned char *)&FltSolTab[j]);
+		}
+		else if(msh->ver == 2)
+		{
+			DblSolTab = va_arg(par, double *);
+
+			if(msh->typ & Asc)
+				for(j=0;j<kwd->SolSiz;j++)
+					fprintf(msh->hdl, "%.15lg ", DblSolTab[j]);
+			else
+				for(j=0;j<kwd->SolSiz;j++)
+					RecDblWrd(msh, (unsigned char *)&DblSolTab[j]);
+		}
+	}
+
+	va_end(par);
+
+	if(msh->typ & Asc)
+		fprintf(msh->hdl, "\n");
+}
+
+
+/*----------------------------------------------------------*/
+/* Private procedure for transmesh : copy a whole line		*/
+/*----------------------------------------------------------*/
+
+void GmfCpyLin(int InpIdx, int OutIdx, int KwdCod)
+{
+	double d;
+	float f;
+	int i, a;
+	GmfMshSct *InpMsh = MshTab[ InpIdx ], *OutMsh = MshTab[ OutIdx ];
+	KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
+
+	for(i=0;i<kwd->SolSiz;i++)
+	{
+		if(kwd->fmt[i] == 'r')
+		{
+			if(InpMsh->ver == 1)
+			{
+				if(InpMsh->typ & Asc)
+					fscanf(InpMsh->hdl, "%f", &f);
+				else
+					ScaWrd(InpMsh, (unsigned char *)&f);
+
+				d = f;
+			}
+			else
+			{
+				if(InpMsh->typ & Asc)
+					fscanf(InpMsh->hdl, "%lf", &d);
+				else
+					ScaDblWrd(InpMsh, (unsigned char *)&d);
+
+				f = (float)d;
+			}
+
+			if(OutMsh->ver == 1)
+				if(OutMsh->typ & Asc)
+					fprintf(OutMsh->hdl, "%g ", f);
+				else
+					RecWrd(OutMsh, (unsigned char *)&f);
+			else
+				if(OutMsh->typ & Asc)
+					fprintf(OutMsh->hdl, "%.15g ", d);
+				else
+					RecDblWrd(OutMsh, (unsigned char *)&d);
+		}
+		else
+		{
+			if(InpMsh->typ & Asc)
+				fscanf(InpMsh->hdl, "%d", &a);
+			else
+				ScaWrd(InpMsh, (unsigned char *)&a);
+
+			if(OutMsh->typ & Asc)
+				fprintf(OutMsh->hdl, "%d ", a);
+			else
+				RecWrd(OutMsh, (unsigned char *)&a);
+		}
+	}
+
+	if(OutMsh->typ & Asc)
+		fprintf(OutMsh->hdl, "\n");
+}
+
+
+/*----------------------------------------------------------*/
+/* Find every kw present in a meshfile						*/
+/*----------------------------------------------------------*/
+
+static int ScaKwdTab(GmfMshSct *msh)
+{
+	int KwdCod, NexPos, CurPos, EndPos;
+	char str[ GmfStrSiz ];
+
+	if(msh->typ & Asc)
+	{
+		/* Scan each string in the file until the end */
+
+		while(fscanf(msh->hdl, "%s", str) != EOF)
+		{
+			/* Fast test in order to reject quickly the numeric values */
+
+			if(isalpha(str[0]))
+			{
+				/* Search which kwd code this string is associated with, 
+					then get its header and save the curent position in file (just before the data) */
+
+				for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
+					if(!strcmp(str, KwdFmt[ KwdCod ][0]))
+					{
+						ScaKwdHdr(msh, KwdCod);
+						break;
+					}
+			}
+			else if(str[0] == '#')
+				while(fgetc(msh->hdl) != '\n');
+		}
+	}
+	else
+	{
+		/* Get file size */
+
+		CurPos = ftell(msh->hdl);
+		fseek(msh->hdl, 0, SEEK_END);
+		EndPos = ftell(msh->hdl);
+		fseek(msh->hdl, CurPos, SEEK_SET);
+
+		/* Jump through kwd positions in the file */
+
+		do
+		{
+			/* Get the kwd code and the next kwd position */
+
+			ScaWrd(msh, (unsigned char *)&KwdCod);
+			ScaWrd(msh, (unsigned char *)&NexPos);
+
+			if(NexPos > EndPos)
+				return(0);
+
+			/* Check if this kwd belongs to this mesh version */
+
+			if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
+				ScaKwdHdr(msh, KwdCod);
+
+			/* Go to the next kwd */
+
+			if(NexPos)
+				fseek(msh->hdl, NexPos, SEEK_SET);
+		}while(NexPos && (KwdCod != GmfEnd));
+	}
+
+	return(1);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read and setup the keyword's header						*/
+/*----------------------------------------------------------*/
+
+static void ScaKwdHdr(GmfMshSct *msh, int KwdCod)
+{
+	int i;
+	KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+	if(!strcmp("i", KwdFmt[ KwdCod ][1]))
+	{
+		if(msh->typ & Asc)
+			fscanf(msh->hdl, "%d", &kwd->NmbLin);
+		else
+			ScaWrd(msh, (unsigned char *)&kwd->NmbLin);
+	}
+	else
+		kwd->NmbLin = 1;
+
+	if(!strcmp("sr", KwdFmt[ KwdCod ][2]))
+	{
+		if(msh->typ & Asc)
+		{
+			fscanf(msh->hdl, "%d", &kwd->NmbTyp);
+
+			for(i=0;i<kwd->NmbTyp;i++)
+				fscanf(msh->hdl, "%d", &kwd->TypTab[i]);
+		}
+		else
+		{
+			ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+			for(i=0;i<kwd->NmbTyp;i++)
+				ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+		}
+	}
+
+	ExpFmt(msh, KwdCod);
+	kwd->pos = ftell(msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Expand the compacted format and compute the line size	*/
+/*----------------------------------------------------------*/
+
+static void ExpFmt(GmfMshSct *msh, int KwdCod)
+{
+	int i, j, TmpSiz=0;
+	char chr, *InpFmt = KwdFmt[ KwdCod ][2];
+	KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+	/* Set the kwd's type */
+
+	if(!strlen(KwdFmt[ KwdCod ][1]))
+		kwd->typ = InfKwd;
+	else if(!strcmp(InpFmt, "sr"))
+		kwd->typ = SolKwd;
+	else
+		kwd->typ = RegKwd;
+
+	/* Get the solution-field's size */
+
+	if(kwd->typ == SolKwd)
+		for(i=0;i<kwd->NmbTyp;i++)
+			switch(kwd->TypTab[i])
+			{
+				case GmfSca    : TmpSiz += 1; break;
+				case GmfVec    : TmpSiz += msh->dim; break;
+				case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break;
+				case GmfMat    : TmpSiz += msh->dim * msh->dim; break;
+			}
+
+	/* Scan each character from the format string */
+
+	i = 0;
+
+	while(i < (int) strlen(InpFmt))
+	{
+		chr = InpFmt[ i++ ];
+
+		if(chr == 'd')
+		{
+			chr = InpFmt[i++];
+
+			for(j=0;j<msh->dim;j++)
+				kwd->fmt[ kwd->SolSiz++ ] = chr;
+		}
+		else if(chr == 's')
+		{
+			chr = InpFmt[i++];
+
+			for(j=0;j<TmpSiz;j++)
+				kwd->fmt[ kwd->SolSiz++ ] = chr;
+		}
+		else
+			kwd->fmt[ kwd->SolSiz++ ] = chr;
+	}
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a four bytes word in a mesh file					*/
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+	unsigned char swp;
+
+	fread(wrd, WrdSiz, 1, msh->hdl);
+
+	if(msh->cod == 1)
+		return;
+
+	swp = wrd[3];
+	wrd[3] = wrd[0];
+	wrd[0] = swp;
+
+	swp = wrd[2];
+	wrd[2] = wrd[1];
+	wrd[1] = swp;
+}
+
+
+/*----------------------------------------------------------*/
+/* Read an eight bytes word in a mesh file					*/
+/*----------------------------------------------------------*/
+
+static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+	int i;
+	unsigned char swp;
+
+	fread(wrd, WrdSiz, 2, msh->hdl);
+
+	if(msh->cod == 1)
+		return;
+
+	for(i=0;i<4;i++)
+	{
+		swp = wrd[7-i];
+		wrd[7-i] = wrd[i];
+		wrd[i] = swp;
+	}
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a four bytes word in a mesh file					*/
+/*----------------------------------------------------------*/
+
+static void RecWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+	fwrite(wrd, WrdSiz, 1, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write an eight bytes word in a mesh file					*/
+/*----------------------------------------------------------*/
+
+static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+	fwrite(wrd, WrdSiz, 2, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Fortran 77 API											*/
+/*----------------------------------------------------------*/
+
+int call(gmfopenmeshf77)(char *FilNam, int *mod, int *ver, int *dim, int StrSiz)
+{
+	int i;
+	char TmpNam[ GmfStrSiz ];
+
+	for(i=0;i<StrSiz;i++)
+		TmpNam[i] = FilNam[i];
+
+	TmpNam[ StrSiz ] = 0;
+
+	if(*mod == GmfRead)
+		return(GmfOpenMesh(TmpNam, *mod, ver, dim));
+	else
+		return(GmfOpenMesh(TmpNam, *mod, *ver, *dim));
+}
+
+int call(gmfclosemeshf77)(int *idx)
+{
+	return(GmfCloseMesh(*idx));
+}
+
+int call(gmfstatkwdf77)(int *MshIdx, int *KwdIdx, int *NmbTyp, int *SolSiz, int *TypTab)
+{
+	if(!strcmp(KwdFmt[ *KwdIdx ][2], "sr"))
+		return(GmfStatKwd(*MshIdx, *KwdIdx, NmbTyp, SolSiz, TypTab));
+	else
+		return(GmfStatKwd(*MshIdx, *KwdIdx));
+}
+
+int call(gmfgotokwdf77)(int *MshIdx, int *KwdIdx)
+{
+	return(GmfGotoKwd(*MshIdx, *KwdIdx));
+}
+
+int call(gmfsetkwdf77)(int *MshIdx, int *KwdIdx, int *NmbLin, int *NmbTyp, int *TypTab)
+{
+	if(!strcmp(KwdFmt[ *KwdIdx ][2], "sr"))
+		return(GmfSetKwd(*MshIdx, *KwdIdx, *NmbLin, *NmbTyp, TypTab));
+	else if(strlen(KwdFmt[ *KwdIdx ][1]))
+		return(GmfSetKwd(*MshIdx, *KwdIdx, *NmbLin));
+	else
+		return(GmfSetKwd(*MshIdx, *KwdIdx));
+}
+
+int call(gmfgetvertex2df77)(int *MshIdx, float *x, float *y, int *ref)
+{
+	GmfGetLin(*MshIdx, GmfVertices, x, y, ref);
+	return(1);
+}
+
+int call(gmfgetvertex3df77)(int *MshIdx, float *x, float *y, float *z, int *ref)
+{
+	GmfGetLin(*MshIdx, GmfVertices, x, y, z, ref);
+	return(1);
+}
+
+int call(gmfsetvertex2df77)(int *MshIdx, float *x, float *y, int *ref)
+{
+	GmfSetLin(*MshIdx, GmfVertices, *x, *y, *ref);
+	return(1);
+}
+
+int call(gmfsetvertex3df77)(int *MshIdx, float *x, float *y, float *z, int *ref)
+{
+	GmfSetLin(*MshIdx, GmfVertices, *x, *y, *z, *ref);
+	return(1);
+}
+
+int call(gmfgettrianglef77)(int *MshIdx, int *p1, int *p2, int *p3, int *ref)
+{
+	GmfGetLin(*MshIdx, GmfTriangles, p1, p2, p3, ref);
+	return(1);
+}
+
+int call(gmfsettrianglef77)(int *MshIdx, int *p1, int *p2, int *p3, int *ref)
+{
+	GmfSetLin(*MshIdx, GmfTriangles, *p1, *p2, *p3, *ref);
+	return(1);
+}
+
+int call(gmfgettetrahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+	GmfGetLin(*MshIdx, GmfTetrahedra, p1, p2, p3, p4, ref);
+	return(1);
+}
+
+int call(gmfsettetrahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+	GmfSetLin(*MshIdx, GmfTetrahedra, *p1, *p2, *p3, *p4, *ref);
+	return(1);
+}
+
+int call(gmfgetedgef77)(int *MshIdx, int *p1, int *p2, int *ref)
+{
+	GmfGetLin(*MshIdx, GmfEdges, p1, p2, ref);
+	return(1);
+}
+
+int call(gmfsetedgef77)(int *MshIdx, int *p1, int *p2, int *ref)
+{
+	GmfSetLin(*MshIdx, GmfEdges, *p1, *p2, *ref);
+	return(1);
+}
+
+int call(gmfgetquadrilateralf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+	GmfGetLin(*MshIdx, GmfQuadrilaterals, p1, p2, p3, p4, ref);
+	return(1);
+}
+
+int call(gmfsetquadrilateralf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *ref)
+{
+	GmfSetLin(*MshIdx, GmfQuadrilaterals, *p1, *p2, *p3, *p4, *ref);
+	return(1);
+}
+
+int call(gmfgethexahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *p5, int *p6, int *p7, int *p8, int *ref)
+{
+	GmfGetLin(*MshIdx, GmfHexahedra, p1, p2, p3, p4, p5, p6, p7, p8, ref);
+	return(1);
+}
+
+int call(gmfsethexahedronf77)(int *MshIdx, int *p1, int *p2, int *p3, int *p4, int *p5, int *p6, int *p7, int *p8, int *ref)
+{
+	GmfSetLin(*MshIdx, GmfHexahedra, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *ref);
+	return(1);
+}
+
+int call(gmfsetsolf77)(int *MshIdx, int *kwd, int *SolTab)
+{
+	GmfSetLin(*MshIdx, *kwd, SolTab);
+	return(1);
+}
+
+int call(gmfgetsolf77)(int *MshIdx, int *kwd, int *SolTab)
+{
+	GmfGetLin(*MshIdx, *kwd, SolTab);
+	return(1);
+}
diff --git a/src/libMesh/libmesh5.h b/src/libMesh/libmesh5.h
new file mode 100644
index 0000000..48e94c7
--- /dev/null
+++ b/src/libMesh/libmesh5.h
@@ -0,0 +1,174 @@
+
+
+/*----------------------------------------------------------*/
+/*															*/
+/*						LIBMESH V 5.0						*/
+/*															*/
+/*----------------------------------------------------------*/
+/*															*/
+/*	Description:		handle .meshb file format I/O		*/
+/*	Author:				Loic MARECHAL						*/
+/*	Creation date:		feb 16 2007							*/
+/*	Last modification:	apr 10 2007							*/
+/*															*/
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Defines													*/
+/*----------------------------------------------------------*/
+
+#define GmfStrSiz 1024
+#define GmfMaxTyp 20
+#define GmfMaxKwd 79
+#define GmfMshVer 1
+#define GmfRead 1
+#define GmfWrite 2
+#define GmfSca 1
+#define GmfVec 2
+#define GmfSymMat 3
+#define GmfMat 4
+#define GmfFloat 1
+#define GmfDouble 2
+
+enum GmfKwdCod
+{
+	GmfReserved1, \
+	GmfVersionFormatted, \
+	GmfReserved2, \
+	GmfDimension, \
+	GmfVertices, \
+	GmfEdges, \
+	GmfTriangles, \
+	GmfQuadrilaterals, \
+	GmfTetrahedra, \
+	GmfPentahedra, \
+	GmfHexahedra, \
+	GmfReserved3, \
+	GmfReserved4, \
+	GmfCorners, \
+	GmfRidges, \
+	GmfRequiredVertices, \
+	GmfRequiredEdges, \
+	GmfRequiredTriangles, \
+	GmfRequiredQuadrilaterals, \
+	GmfTangentAtEdgeVertices, \
+	GmfNormalAtVertices, \
+	GmfNormalAtTriangleVertices, \
+	GmfNormalAtQuadrilateralVertices, \
+	GmfAngleOfCornerBound, \
+	GmfReserved5, \
+	GmfReserved6, \
+	GmfReserved7, \
+	GmfReserved8, \
+	GmfReserved9, \
+	GmfReserved10, \
+	GmfReserved11, \
+	GmfReserved12, \
+	GmfReserved13, \
+	GmfReserved14, \
+	GmfReserved15, \
+	GmfReserved16, \
+	GmfReserved17, \
+	GmfReserved18, \
+	GmfReserved19, \
+	GmfReserved20, \
+	GmfReserved21, \
+	GmfReserved22, \
+	GmfReserved23, \
+	GmfReserved24, \
+	GmfReserved25, \
+	GmfReserved26, \
+	GmfReserved27, \
+	GmfReserved28, \
+	GmfReserved29, \
+	GmfReserved30, \
+	GmfBoundingBox, \
+	GmfReserved31, \
+	GmfReserved32, \
+	GmfReserved33, \
+	GmfEnd, \
+	GmfReserved34, \
+	GmfReserved35, \
+	GmfReserved36, \
+	GmfReserved37, \
+	GmfTangents, \
+	GmfNormals, \
+	GmfTangentAtVertices, \
+	GmfSolAtVertices, \
+	GmfSolAtEdges, \
+	GmfSolAtTriangles, \
+	GmfSolAtQuadrilaterals, \
+	GmfSolAtTetrahedra, \
+	GmfSolAtPentahedra, \
+	GmfSolAtHexahedra, \
+	GmfDSolAtVertices, \
+	GmfISolAtVertices, \
+	GmfISolAtEdges, \
+	GmfISolAtTriangles, \
+	GmfISolAtQuadrilaterals, \
+	GmfISolAtTetrahedra, \
+	GmfISolAtPentahedra, \
+	GmfISolAtHexahedra, \
+	GmfIterations, \
+	GmfTime, \
+	GmfReserved38
+};
+
+
+/*----------------------------------------------------------*/
+/* External procedures										*/
+/*----------------------------------------------------------*/
+
+extern int GmfOpenMesh(const char *, int, ...);
+extern int GmfCloseMesh(int);
+extern int GmfStatKwd(int, int, ...);
+extern int GmfGotoKwd(int, int);
+extern int GmfSetKwd(int, int, ...);
+extern void GmfGetLin(int, int, ...);
+extern void GmfSetLin(int, int, ...);
+
+
+/*----------------------------------------------------------*/
+/* Fortran 77 API											*/
+/*----------------------------------------------------------*/
+
+#if defined(F77_NO_UNDER_SCORE)
+#define call(x) x
+#else
+#define call(x) x ## _
+#endif
+
+int call(gmfopenmeshf77)(char *, int *, int *, int *, int);
+int call(gmfclosemeshf77)(int *);
+int call(gmfstatkwdf77)(int *, int *, int *, int *, int *);
+int call(gmfgotokwdf77)(int *, int *);
+int call(gmfsetkwdf77)(int *, int *, int *, int *, int *);
+int call(gmfgetvertex2df77)(int *, float *, float *, int *);
+int call(gmfgetvertex3df77)(int *, float *, float *, float *, int *);
+int call(gmfsetvertex2df77)(int *, float *, float *, int *);
+int call(gmfsetvertex3df77)(int *, float *, float *, float *, int *);
+int call(gmfgettrianglef77)(int *, int *, int *, int *, int *);
+int call(gmfsettrianglef77)(int *, int *, int *, int *, int *);
+int call(gmfgettetrahedronf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfsettetrahedronf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfgetedgef77)(int *, int *, int *, int *);
+int call(gmfsetedgef77)(int *, int *, int *, int *);
+int call(gmfgetquadrilateralf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfsetquadrilateralf77)(int *, int *, int *, int *, int *, int *);
+int call(gmfgethexahedronf77)(int *, int *, int *, int *, int *, int *, int *, int *, int *, int *);
+int call(gmfsethexahedronf77)(int *, int *, int *, int *, int *, int *, int *, int *, int *, int *);
+int call(gmfsetsolf77)(int *, int *, int *);
+int call(gmfgetsolf77)(int *, int *, int *);
+
+
+/*----------------------------------------------------------*/
+/* Transmesh private API									*/
+/*----------------------------------------------------------*/
+
+#ifdef TRANSMESH
+
+extern char *KwdFmt[ GmfMaxKwd + 1 ][3];
+extern int GmfCpyLin(int, int, int);
+
+#endif
diff --git a/src/libMesh/memory.c b/src/libMesh/memory.c
new file mode 100644
index 0000000..3a2859e
--- /dev/null
+++ b/src/libMesh/memory.c
@@ -0,0 +1,239 @@
+/* file    : memory.c
+ *   C code for memory debugging, to be used in lieu
+ *   of standard memory functions
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "memory.h"
+
+
+typedef struct memstack {
+  size_t   size;
+  void    *ptr;
+  int      nxt;
+  char     call[30];
+} Memstack;
+
+typedef Memstack   * pMemstack;
+
+const int  MAXMEM = 300;
+pMemstack  mstack;
+int        stack,cur;
+
+
+int M_memLeak() {
+  int   i,c=0;
+
+  for (i=1; i<=MAXMEM; i++)
+    if (mstack[i].ptr)  c++;
+  return(c);
+}
+
+/* print out allocated pointers */
+void M_memDump() {
+  size_t  size;
+  int     i,c;
+  static long mega = 1024 * 1024;
+  static long kilo = 1024;
+
+  fprintf(stdout,"\n  -- MEMORY USAGE\n");
+  fprintf(stdout,"  Allocated pointers\n");
+  size = 0;
+  c    = 0;
+  for (i=1; i<=MAXMEM; i++)
+    if ( mstack[i].ptr ) {
+      fprintf(stdout,"   %3d  %3d Pointer %10p  size ",++c,i,mstack[i].ptr);
+      if (mstack[i].size > mega)
+        fprintf(stdout,"   %10d Mbytes  ",(int)(mstack[i].size/mega));
+      else if (mstack[i].size > kilo)
+        fprintf(stdout,"   %10d Kbytes  ",(int)(mstack[i].size/kilo));
+      else 
+        fprintf(stdout,"   %10d  bytes  ",(int)(mstack[i].size));
+      fprintf(stdout,"(%s)\n",mstack[i].call);
+      size += mstack[i].size;
+    }
+  fprintf(stdout,"  Memory leaks    ");
+  if ( size > mega )
+    fprintf(stdout,"  %10d Mbytes  %d pointers\n",(int)(size/mega),c);
+  else if ( size > kilo )
+    fprintf(stdout,"  %10d Kbytes  %d pointers\n",(int)(size/kilo),c);
+  else if ( size )
+    fprintf(stdout,"  %10d bytes   %d pointers\n",(int)size,c);
+}
+
+/* Returns allocated memory space in bytes */
+size_t M_memSize() {
+  size_t size;
+  int    i;
+
+  size = 0;
+  for (i=1; i<=MAXMEM; i++)
+    if ( mstack[i].ptr )
+      size += mstack[i].size;
+  return size;
+}
+
+/* Allocates space for a block of at least size bytes,
+   but does not initialize the space. */
+void *M_malloc(size_t size,char *call) {
+  int   i;
+
+  /* check if first call */
+  if ( !mstack ) {
+    mstack = (Memstack *)calloc((1+MAXMEM),sizeof(Memstack));
+    assert(mstack);
+    for (i=1; i<MAXMEM; i++)
+      mstack[i].nxt    = i+1;
+    cur   = 1;
+    stack = 0;
+  }
+
+  /* store pointer, size */
+  if ( stack < MAXMEM ) {
+    mstack[cur].ptr  = malloc(size);
+    assert(mstack[cur].ptr);
+    mstack[cur].size = size;
+    /* i.e. mstack[cur].call = strdup(call) */
+    /* mstack[cur].call = (char*)malloc((strlen(call)+1) * sizeof(char));
+    assert(mstack[cur].call); */
+    strncpy(mstack[cur].call,call,19);
+    i = cur;
+    cur = mstack[cur].nxt;
+    ++stack;
+#ifdef MEMDEBUG
+    fprintf(stdout,"M_malloc: allocate %p of size %10d         (%g,%d)\n",
+	    mstack[cur].ptr,size,stack,cur);
+#endif
+    return(mstack[i].ptr);
+  }
+  else {
+    fprintf(stderr,"M_malloc: unable to store %10Zd bytes pointer. table full\n",
+	    size);
+    return(0);
+  }
+}
+
+
+/* Allocates space for an array of nelem elements, each of size 
+   elsize bytes, and initializes the space to zeros.  
+   Actual amount of space allocated is >=  nelem * elsize bytes. */
+void *M_calloc(size_t nelem, size_t elsize,char *call) {
+  int    i;
+
+  /* check if first call */
+  if ( !mstack ) {
+    mstack = (Memstack *)calloc((1+MAXMEM),sizeof(Memstack));
+    assert(mstack);
+    for (i=1; i<MAXMEM; i++)
+      mstack[i].nxt    = i+1;
+    cur   = 1;
+    stack = 0;
+  }
+
+  /* store pointer, size */
+  if ( stack < MAXMEM ) {
+    mstack[cur].ptr  = calloc(nelem,elsize);
+    if ( !mstack[cur].ptr )  return(0);
+
+    /*assert(mstack[cur].ptr);*/
+    mstack[cur].size = nelem * elsize;
+    /* mstack[cur].call = (char*)malloc((strlen(call)+1) * sizeof(char));
+    assert(mstack[cur].call); */
+    strncpy(mstack[cur].call,call,19);
+    i   = cur;
+    cur = mstack[cur].nxt;
+    ++stack;
+#ifdef MEMDEBUG
+    fprintf(stdout,"M_calloc: allocate %p of size %d         (%d,%d)\n",
+	    mstack[cur].ptr,nelem*elsize,stack,cur);
+#endif
+    return(mstack[i].ptr);
+  }
+  else {
+    fprintf(stderr,"M_calloc: unable to allocate %10Zd bytes. table full\n",
+	    nelem*elsize);
+    return(0);
+  }
+}
+
+/* Changes the size of the block pointed to by ptr to size bytes 
+   and returns a pointer to the (possibly moved) block. Existing 
+   contents are unchanged up to the lesser of the new and old sizes. */
+void *M_realloc(void *ptr, size_t size,char *call) {
+  int    i;
+
+  if ( !ptr )
+    return 0;
+
+  for (i=1; i<=MAXMEM; i++) {
+    if (ptr == mstack[i].ptr) {
+      /* free(mstack[i].call);
+      mstack[cur].call = (char*)malloc((strlen(call)+1) * sizeof(char));
+      assert(mstack[cur].call); */
+      strncpy(mstack[i].call,call,19);
+      mstack[i].ptr = realloc(mstack[i].ptr,size);
+      if (size)
+	assert(mstack[i].ptr);
+      mstack[i].size = size;
+#ifdef MEMDEBUG
+      fprintf(stdout,"M_realloc: reallocate %p of size %d       (%d)\n",
+	      mstack[i].ptr,mstack[i].size,size);
+#endif
+      return(mstack[i].ptr);
+    }
+  }
+#ifdef MEMDEBUG
+  fprintf(stderr,"M_realloc: pointer %p not found\n",ptr);
+#endif
+  return(0);
+}
+
+/* Deallocates the space pointed to by ptr (a pointer to a block 
+   previously allocated by malloc() and makes the space available
+   for further allocation.  If ptr is NULL, no action occurs. */
+void M_free(void *ptr) {
+  int   i;
+  
+  assert(ptr);
+  for (i=1; i<=MAXMEM; i++) {
+    if (mstack[i].ptr && ptr == mstack[i].ptr) {
+      --stack;
+      free(mstack[i].ptr);
+      mstack[i].ptr  = 0;
+      mstack[i].size = 0;
+      mstack[i].nxt  = cur;
+      mstack[i].call[0]  = '\0';
+      cur = i;
+#ifdef MEMDEBUG
+      fprintf(stdout,"M_free: deallocate %p of size %d       (%d,%d)\n",
+	      ptr,mstack[i].size,stack,cur);
+#endif
+      return;
+    }
+  }
+#ifdef MEMDEBUG
+  fprintf(stderr,"M_free: pointer %p not found\n",ptr);
+#endif
+}
+
+
+/* dump memory requirements */
+void primem(int np) {
+  int memsize;
+
+  memsize = M_memSize();
+  if ( memsize ) {
+    fprintf(stdout,"\n  -- MEMORY REQUIREMENTS\n");
+    if (memsize > 1024*1024)
+      fprintf(stdout,"  Total size :  %10Zd Mbytes",
+	      (long int)(memsize/(1024.*1024.)));
+    else if (memsize > 1024)
+      fprintf(stdout,"  Total size :  %10Zd Kbytes",(long int)(memsize/1024.));
+    else
+      fprintf(stdout,"  Total size :  %10Zd bytes ",(long int)memsize);
+    fprintf(stdout,"    (i.e. %d bytes/point)\n",memsize / np);
+  }
+}
diff --git a/src/libMesh/memory.h b/src/libMesh/memory.h
new file mode 100644
index 0000000..f930880
--- /dev/null
+++ b/src/libMesh/memory.h
@@ -0,0 +1,22 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+/* prototype (re)definitions */
+void  *M_malloc(size_t size,char *call);
+void  *M_calloc(size_t nelem,size_t elsize,char *call);
+void  *M_realloc(void *ptr, size_t size,char *call);
+void   M_free(void *ptr);
+
+/* ptototypes : tools */
+int    M_memLeak();
+void   M_memDump();
+size_t M_memSize();
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/._keyboard.c b/src/medit/._keyboard.c
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/medit/._keyboard.c differ
diff --git a/src/medit/._mouse.c b/src/medit/._mouse.c
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/medit/._mouse.c differ
diff --git a/src/medit/._sproto.h b/src/medit/._sproto.h
new file mode 100644
index 0000000..14f037e
Binary files /dev/null and b/src/medit/._sproto.h differ
diff --git a/src/medit/Makefile.am b/src/medit/Makefile.am
new file mode 100644
index 0000000..039b8fd
--- /dev/null
+++ b/src/medit/Makefile.am
@@ -0,0 +1,38 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+
+CXXLD=$(STATICTOOL) $(CXX)
+
+bin_PROGRAMS=$(MEDITPROG)
+EXTRA_DIST=picking.c 
+EXTRA_PROGRAMS=ffmedit
+ffmedit_SOURCES= animat.c cube.c image.c listnum.c mouse.c persp.c stream.c zaldy2.c bbfile.c dlists.c inmsh2.c		\
+material.c normal.c tiles.c camera.c ellipse.c inout.c medit.c param.c psfile.c transform.c cenrad.c geometry.c		\
+inout_morice.c menus.c parsar.c scene.c util.c clip.c gisfil.c inout_popenbinaire.c mesh.c parsop.c scissor.c vector.c	\
+clipvol.c hash.c items.c mlists.c particle.c sftcpy.c view.c critip.c ilists.c keyboard.c morphing.c path.c status.c	\
+zaldy1.c chrono.h extern.h image.h mesh.h eigenv.h grafic.h medit.h sproto.h
+
+
+LDADD=picking.$(OBJEXT) ../libMesh/libMesh.a $(LIBSGLUT) -lm
+AM_CPPFLAGS=-I$(srcdir)/../libMesh
+BUILT_SOURCES=compil.date
+compil.date: $(ffmedit_SOURCES)
+	echo "#define COMPIL " '"' `date` '(with ff++ $(VERSION))''"' > compil.date
+#.PHONY: compil.date
+
+# ALH - during a parallel make, we should make sure that picking.o is not used before being made by a different
+# thread. If I understand things correctly, picking.c should not be compiled with the regular CFLAGS options.
+
+ffmedit_DEPENDENCIES=picking.$(OBJEXT)
+picking.$(OBJEXT):picking.c
+	${CC} -c $< $(CNOFLAGS) -o $@ 
+
+###pinking.no-optffmedit$(EXEEXT):picking.c
+###	rm picking.$(OBJEXT)
+###	$(MAKE) picking.o $(MEDITPROG) CFLAGS="$(CNOFLAGS)"
+###	touch pinking.no-optffmedit$(EXEEXT)
+###pinking.no-opt:picking.c
+###	touch pinking.no-opt
+###clean-local:
+###	-rm pinking.no-opt pinking.no-optffmedit$(EXEEXT)
+
diff --git a/src/medit/animat.c b/src/medit/animat.c
new file mode 100644
index 0000000..d4aa6df
--- /dev/null
+++ b/src/medit/animat.c
@@ -0,0 +1,247 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+extern void resetLists(pScene ,pMesh );
+
+
+static int getmesh(pMesh mesh,int range) {
+  int     k,ret;
+  char   *ptr,data[256];
+  static char base[256];
+
+  /* allocate mesh structure */
+  if ( ddebug ) fprintf(stdout,"getmesh: create mesh %d\n",range);
+
+  if ( mesh->tria )  M_free(mesh->tria);
+  if ( mesh->quad )  M_free(mesh->quad);
+  if ( mesh->edge )  M_free(mesh->edge);
+  if ( mesh->tetra ) M_free(mesh->tetra);
+  if ( mesh->hexa )  M_free(mesh->hexa);
+  if ( mesh->adja )  M_free(mesh->adja);
+  if ( mesh->voy  )  M_free(mesh->voy);
+  if ( mesh->point ) M_free(mesh->point);
+  if ( mesh->extra ) {
+    if ( mesh->extra->iv )  M_free(mesh->extra->nv);
+    if ( mesh->extra->it )  M_free(mesh->extra->nt);
+    if ( mesh->extra->iq )  M_free(mesh->extra->nq);
+    if ( mesh->extra->n )   M_free(mesh->extra->n);
+    M_free(mesh->extra);
+    mesh->extra = (void*)0;
+  }
+  if ( mesh->sol && mesh->nbb ) {
+    if ( (mesh->dim==2 && mesh->nfield==3) || (mesh->dim==3 && mesh->nfield==6) )
+      for (k=1; k<=mesh->nbb; k++)
+        free(mesh->sol[k].m);
+    M_free(mesh->sol);
+    mesh->sol = (void*)0;
+  }
+  mesh->point = (void*)0;
+  mesh->tria  = (void*)0;
+  mesh->quad  = (void*)0;
+  mesh->edge  = (void*)0;
+  mesh->tetra = (void*)0;
+  mesh->hexa  = (void*)0;
+  mesh->adja  = (void*)0;
+  mesh->voy   = (void*)0;
+  mesh->np = mesh->nt = mesh->nq = mesh->ne = 0;
+  mesh->ntet = mesh->nhex = mesh->nbb = 0;
+
+  if ( animdep == range ) {
+    sprintf(data,".%d",range);
+    ptr = (char *)strstr(mesh->name,data);
+    if ( ptr )  *ptr = '\0';
+    strcpy(base,mesh->name);
+  }
+
+  /* adjust file name */
+  sprintf(mesh->name,"%s.%d",base,range);
+  if ( ddebug )  fprintf(stdout,"load %s\n",mesh->name);
+
+  /* read mesh */
+  if ( quiet ) {  
+    fprintf(stdout,"  Loading %s     \r",mesh->name);
+    fflush(stdout);
+  }
+  mesh->typ = 0;
+  ret = loadMesh(mesh);
+  if ( ret < 1 ) {
+    mesh->typ = 1;
+    ret = inmsh2(mesh);
+    if ( !ret ) {
+      mesh->typ = 2;
+      ret = loadGIS(mesh);
+      if ( !ret )  return(0);
+    }
+  }
+  if ( (mesh->ntet && !mesh->nt) || (mesh->nhex && !mesh->nq) )  
+    meshSurf(mesh);
+  meshBox(mesh,animdep==range);
+  if ( !quiet )  meshInfo(mesh);
+
+  /* read metric */
+  if ( !loadSol(mesh,mesh->name,1) )
+    bbfile(mesh);
+  if ( !quiet && mesh->nbb )
+    fprintf(stdout,"    Solutions  %8d\n",mesh->nbb);
+
+  return(1);
+}
+
+
+int loadNextMesh(pMesh mesh,int k,int parse) {
+  pScene    sc;
+  int       is;
+
+  if ( !getmesh(mesh,k) )  return(0);
+  if ( ddebug ) printf("loadNextMesh: create %d window(s)\n",cv.nbs);
+
+  /* compute mesh box */
+  is = currentScene();
+  if ( !cv.scene[is] ) {
+    cv.scene[is] = (pScene)M_calloc(1,sizeof(Scene),"loadNextMesh.scene");
+    if ( !cv.scene[is] )  return(0);
+  }
+  sc = cv.scene[is];
+  if ( parse ) {
+    parsop(sc,mesh);
+  }
+  setupPalette(sc,mesh);
+  meshRef(sc,mesh);
+  matSort(sc);
+
+  return(1);
+}
+
+
+int playAnim(pScene sc,pMesh mesh,int deb,int fin) {
+  int     k;
+  char   *ptr,data[256],base[256];
+
+  /* get basename */
+  sprintf(data,".%d",deb);
+  ptr = (char *)strstr(mesh->name,data);
+  if ( ptr )  *ptr = '\0';
+  strcpy(base,mesh->name);
+
+  if ( saveimg ) {
+    glDrawBuffer(GL_BACK_LEFT);
+  }
+
+  /* start animation */
+  for (k=deb; k<=fin; k++) {
+    strcpy(mesh->name,base);
+
+    resetLists(sc,mesh);
+    if ( !loadNextMesh(mesh,k,0) )  return(0);
+    doLists(sc,mesh);
+    sc->glist = geomList(sc,mesh);
+    if ( sc->mode & S_MAP ) doMapLists(sc,mesh,1);
+    if ( sc->isotyp )       doIsoLists(sc,mesh,1);
+
+    if ( !saveimg ) {
+      sprintf(data,"Medit - [%s] #%d",mesh->name,sc->idwin);
+      glutSetWindowTitle(data);
+    }
+
+    glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
+    if ( sc->type & S_SCISSOR )
+      scissorScene();
+    else
+      redrawScene();
+  }
+  fprintf(stdout,"\n  Done.\n");
+  strcpy(mesh->name,base);
+
+  if ( saveimg ) {
+    glDrawBuffer(GL_FRONT | GL_BACK);
+    if ( saveimg ) {
+      sprintf(data,"Medit - [%s] #%d",mesh->name,sc->idwin);
+      glutSetWindowTitle(data);
+    }
+    glutPostRedisplay();
+    saveimg = 0;
+  }
+
+  return(1);
+}
+
+
+int animParticle(pScene sc,pMesh mesh) {
+  int     cur;
+  char   *ptr,data[256],base[256];
+
+  /* get basename */
+  strcpy(base,mesh->name);
+  ptr = (char *)strstr(base,".");
+  sscanf(ptr,".%d",&cur);
+  cur++;
+  if ( cur > animfin )  return(0);
+  if ( ptr )  ptr[0] = '\0';
+  sprintf(data,"%s.%.3d",base,cur);
+  strcpy(mesh->name,base);
+
+  resetLists(sc,mesh);
+  if ( !loadNextMesh(mesh,cur,1) )  return(0);
+
+  doLists(sc,mesh);
+  sc->glist = geomList(sc,mesh);
+  if ( sc->mode & S_MAP ) doMapLists(sc,mesh,1);
+  if ( sc->isotyp )       doIsoLists(sc,mesh,2);
+
+  if ( !advectParticle(sc,mesh) )  return(0);
+
+  return(1);
+}
+
+
+int animat() {
+  pMesh    mesh;
+  pScene   sc;
+  char     data[128],*name;
+
+  /* default */
+  if ( ddebug )  printf("animat: read file(s)\n");
+
+  /* enter basename */
+  if ( !cv.nbm ) {
+    fprintf(stdout,"  File name(s) missing. Please enter : ");
+    fflush(stdout); fflush(stdin);
+    fgets(data,120,stdin);
+    if ( !strlen(data) ) {
+      fprintf(stdout,"  ## Error\n");
+      return(0);
+    }
+    fprintf(stdout,"  Enter range [start,end] :");
+    fflush(stdout); fflush(stdin);
+    fscanf(stdin,"%d %d",&animdep,&animfin);
+
+    /* parse file name(s) */
+    name = strtok(data," \n");
+    while( name ) {
+      if ( !cv.mesh[cv.nbm] ) {
+        cv.mesh[cv.nbm] = (pMesh)M_calloc(1,sizeof(Mesh),"animat.mesh");
+        if ( !cv.mesh[cv.nbm] )  return(0);
+      }
+      /*(cv.mesh[cv.nbm])->name = calloc(strlen(name)+15,sizeof(char));*/
+      strcpy(cv.mesh[cv.nbm]->name,name);
+      break;
+    }
+    if ( !cv.nbm ) return(0);
+  }
+  cv.nbs = cv.nbm;
+
+  /* read initial mesh */
+  mesh = cv.mesh[0];
+  if ( !loadNextMesh(mesh,animdep,1) )  return(0);
+
+  /* create grafix */
+  sc = cv.scene[0];
+  if ( !createScene(sc,0) ) {
+    fprintf(stderr,"  ## Unable to create scene\n");
+    return(0);
+  }
+
+  quiet = 1;
+  return(1);
+}
diff --git a/src/medit/bbfile.c b/src/medit/bbfile.c
new file mode 100644
index 0000000..2841b87
--- /dev/null
+++ b/src/medit/bbfile.c
@@ -0,0 +1,253 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+int EatLine(FILE  *in) {
+  int    k,c;  
+  
+  k = 0;
+  while ( (c=fgetc(in)) != EOF ) {
+    k++;
+    if ( c==10 || c== 13)  return(1);
+  }
+  return(0);
+}
+
+
+int EatSpace(FILE  *in) {
+  int   k,c,ret=0;  
+  
+  k=0;
+  while (isspace(c=fgetc(in)) ) {
+    k++;
+    if ( c==10 || c== 13 ) ret=1;
+  }
+  if ( c==EOF) return -1;
+  
+  /*  fprintf(stdout,"EatSpace %d %d last char=%d\n",ret,k,c); */
+  ungetc(c,in);
+  
+  return ret;
+}
+
+
+int bbfile(pMesh mesh) {
+  FILE      *in;
+  pSolution  ps;
+  double     a,b,c,lambda[3],eigv[3][3],m[6],vp[2][2];
+  float      dummy;
+  int        j,k,l,dim,np,nfield,nf,i1,i2,i3,i4,err,iord;
+  char      *ptr,data[128],tmp[128];
+  ubyte      bigbb;
+
+  /* default */
+  strcpy(tmp,mesh->name);
+  ptr = (char *)strstr(tmp,".mesh");
+  if ( ptr ) *ptr = '\0';
+
+  sprintf(data,"%s.bb",tmp);
+  in = fopen(data,"r");
+  bigbb = 0;
+  if ( !in ) {
+    sprintf(data,"%s.pbb",tmp);
+    in = fopen(data,"r");
+  }  
+  if ( !in ) {
+    bigbb = 1;
+    sprintf(data,"%s.BB",tmp);
+    in = fopen(data,"r");  
+    if ( !in ) { /* hack FH pour le mac */
+      sprintf(data,"%s.gbb",tmp);
+      in = fopen(data,"r");
+    }
+    
+  }
+  if ( !in )    
+    return(0);
+  
+  /* if ( !quiet )  fprintf(stdout,"  Reading %s\n",data); */
+  i1=i2=i3=i4=-1;
+  /* read file format */
+  err=0;
+  fscanf(in,"%d",&dim);
+  if(EatSpace(in)) err++;
+  fscanf(in,"%d",&i1);
+  if(EatSpace(in)) err++;
+  fscanf(in,"%d",&i2);
+  if(EatSpace(in)) err++;
+  fscanf(in,"%d",&i3);
+  bigbb=  (EatSpace(in)==0); /* not nl after the 4 integer => BB */
+
+  if ( !quiet )
+    if(bigbb)  fprintf(stdout,"  Reading BB file %s\n",data);
+    else  fprintf(stdout,"  Reading bb file %s\n",data);
+
+  if ( dim < 2 || dim > 3 || err ) {
+    fprintf(stderr,"  %%%% Wrong file (dim=%d) (err=%d). Ignored\n",dim,err);
+    return(0);
+  }
+  /* read number of field(s) */
+  nf = 0;
+
+  if ( bigbb ) {
+    /* get only 1st field */
+    /* fscanf(in,"%d",&nfield);*/
+    nfield=i1;
+    /*fscanf(in,"%d",&mesh->nfield);*/
+    mesh->nfield = i2;
+    if (nfield>1) 
+      {
+	nf += i3;
+	for (k=1; k<nfield-1; k++) {
+	  fscanf(in,"%d",&np);
+	  nf += np;
+	}
+	fscanf(in,"%d",&np);
+      }
+    else 
+      np = i3;
+    /* read file type */
+    fscanf(in,"%d",&mesh->typage);
+    printf(" np= %d, type= %d\n",np,mesh->typage);
+  }
+  else {
+   /* fscanf(in,"%d",&mesh->nfield);
+      fscanf(in,"%d",&np);*/
+    /* read file type */
+    /* fscanf(in,"%d",&mesh->typage);*/
+    mesh->nfield=i1;
+    np=i2;
+    mesh->typage=i3;
+  }  
+  
+
+  if ( mesh->typage == 2 ) {
+    if ( np < mesh->np ) {
+      fprintf(stderr,"  %%%% Wrong solution number (%d , %d). Ignored\n",np,mesh->np);
+      fclose(in);
+      return(0);
+    }
+    mesh->nbb = mesh->np;
+  }
+  else if ( mesh->typage == 1 ) {
+    if ( np < mesh->ne ) {
+      fprintf(stderr,"  %%%% Wrong solution number (%d , %d). Ignored\n",np,mesh->ne);
+      fclose(in);
+      return(0);
+    }
+    mesh->nbb = mesh->ne;
+  }
+  else {
+    fprintf(stderr,"  %%%% Wrong typage (%d). Ignored\n",mesh->typage);
+    fclose(in);
+    return(0);
+  }
+
+  /* read solutions */
+  mesh->bbmin  =  1.e10;
+  mesh->bbmax  = -1.e10;
+
+  /* allocate memory */
+  if ( !zaldy2(mesh) ) {
+    mesh->nbb = 0;
+    fclose(in);
+    return(0);
+  }
+
+  /* scalar field */
+  if ( mesh->nfield == 1 ) {
+    if ( ddebug )  printf("   scalar (isotropic) field\n");
+    for (k=1; k<=mesh->nbb; k++) {
+      ps = &mesh->sol[k];
+      ps->bb = 0.0;
+      if ( fscanf(in,"%s",data) != 1 )  continue;
+      if ( ptr = strpbrk(data,"dD") ) *ptr = 'E';
+      sscanf(data,"%f",&ps->bb);
+      if ( ps->bb < mesh->bbmin )  mesh->bbmin = ps->bb;
+      if ( ps->bb > mesh->bbmax )  mesh->bbmax = ps->bb;
+      for (j=1; j<=nf; j++)  fscanf(in,"%f",&dummy);
+    }
+  }
+
+  /* vector field */
+  else if ( mesh->nfield == mesh->dim ) {
+    if ( ddebug )  fprintf(stdout,"   vector field \n");
+    for (k=1; k<=mesh->nbb; k++) {
+      ps = &mesh->sol[k];
+      ps->bb = 0.0;
+      for (l=0; l<mesh->dim; l++) {
+        if ( fscanf(in,"%s",data) != 1 )  continue;
+        if ( ptr = strpbrk(data,"dD") ) *ptr = 'E';
+        sscanf(data,"%f",&ps->m[l]);
+        ps->bb += ps->m[l]*ps->m[l];
+      }
+      ps->bb = sqrt(ps->bb);
+      if ( ps->bb < mesh->bbmin )  mesh->bbmin = ps->bb;
+      if ( ps->bb > mesh->bbmax )
+        mesh->bbmax = ps->bb;
+      for (j=1; j<nf; j++)  fscanf(in,"%f",&dummy);
+    }
+    fclose(in);
+    return(0);
+  }
+  else if ( dim == 2 && mesh->nfield == 3 ) {
+    if ( ddebug )  fprintf(stdout,"   2D metric field\n");
+    for (k=1; k<=mesh->np; k++) {
+      ps = &mesh->sol[k];
+      fscanf(in,"%lf %lf %lf",&a,&b,&c);
+      ps->m[0] = a;
+      ps->m[1] = b;
+      ps->m[2] = c;
+      m[0] = a;
+      m[1] = b;
+      m[2] = c;
+      eigen2(m,lambda,vp);
+      ps->bb = min(lambda[0],lambda[1]);
+      if ( ps->bb < mesh->bbmin )  mesh->bbmin = ps->bb;
+      if ( ps->bb > mesh->bbmax )  mesh->bbmax = ps->bb;
+      for (j=1; j<nf; j++)  fscanf(in,"%f",&dummy);
+    }
+  }
+  else if ( dim == 3 && mesh->nfield == 6 ) {
+    if ( ddebug )  fprintf(stdout,"   3D metric field\n");
+    for (k=1; k<=mesh->np; k++) {
+      ps = &mesh->sol[k];
+      ps->bb = 0.0f;
+      for (l=0; l<6; l++) {
+        if ( fscanf(in,"%s",data) != 1 )  continue;
+        if ( ptr = strpbrk(data,"dD") ) *ptr = 'E';
+        sscanf(data,"%f",&dummy);
+        m[l] = dummy;
+      }
+      ps->m[0] = m[0];
+      ps->m[1] = m[1];
+      ps->m[2] = m[3];
+      ps->m[3] = m[2];
+      ps->m[4] = m[4];
+      ps->m[5] = m[5];
+
+      m[2] = ps->m[2];
+      m[3] = ps->m[3];
+      iord = eigenv(1,m,lambda,eigv);
+      if ( iord ) {
+        ps->bb = lambda[0];
+        ps->bb = max(ps->bb,lambda[1]);
+        ps->bb = max(ps->bb,lambda[2]);
+        if ( ps->bb < mesh->bbmin )  mesh->bbmin = ps->bb;
+        if ( ps->bb > mesh->bbmax )  mesh->bbmax = ps->bb;
+      }
+      else {
+        fprintf(stdout,"  ## Eigenvalue problem.\n");
+      }
+      
+      for (j=1; j<nf; j++)  fscanf(in,"%f",&dummy);
+    }
+  }
+  else {
+    fprintf(stderr," %%%% Solution not suitable. Ignored\n");
+    mesh->nbb = 0;
+  }
+
+  fclose(in);
+  return(np);
+}
diff --git a/src/medit/camera.c b/src/medit/camera.c
new file mode 100644
index 0000000..fb78297
--- /dev/null
+++ b/src/medit/camera.c
@@ -0,0 +1,139 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+double Azimuth(pCamera c) {
+  double  dd,azim,cosazim,sinazim;
+
+  dd      = sqrt((double)c->speed[0]*c->speed[0]+(double)c->speed[2]*c->speed[2]);
+  cosazim = c->speed[2] / dd;
+  sinazim = c->speed[0] / dd;
+  azim = atan2(sinazim,cosazim) * RTOD;
+  return(azim);
+}
+
+double Elevation(pCamera c) {
+  double  elev;
+
+  elev  = sqrt((double)c->speed[0]*c->speed[0]+(double)c->speed[2]*c->speed[2]);
+  elev  = atan2(c->speed[1],elev) * RTOD;
+  return(elev);
+}
+
+/* compute new sun position */
+void updateSun(pScene sc,pCamera c) {
+  double    dd;
+  GLfloat   axe[3],sunf[4];
+  GLdouble  speed[3],sunp[4],matrix[16];
+
+  axe[0] = c->speed[2];
+  axe[1] = 0.0f;
+  axe[2] = -c->speed[0];
+  dd = sqrt(axe[0]*axe[0] + axe[2]*axe[2]);
+  if ( dd != 0.0f ) {
+    axe[0] /= dd;
+    axe[2] /= dd;
+  }
+  
+  speed[0] = c->speed[0];
+  speed[1] = c->speed[1];
+  speed[2] = c->speed[2];
+  
+  glPushMatrix();
+  glLoadIdentity();
+    glRotatef(-30.0f,axe[0],axe[1],axe[2]);
+    glGetDoublev(GL_MODELVIEW_MATRIX,matrix);
+  glPopMatrix();
+  transformPointd(sunp,speed,matrix);
+  sunf[0] = -sc->dmax*sunp[0];
+  sunf[1] = -sc->dmax*sunp[1];
+  sunf[2] = -sc->dmax*sunp[2];
+  sunf[3] = 0.0;
+
+  glLightfv(GL_LIGHT0,GL_POSITION,sunf);
+
+  if ( ddebug ) {
+    printf("    speed  %g %g %g\n",c->speed[0],c->speed[1],c->speed[2]);
+    printf("    axe    %g %g %g\n",axe[0],axe[1],axe[2]);
+    printf("    sunpos %g %g %g\n",sunp[0],sunp[1],sunp[2]);
+  }
+}
+
+
+void updateCamera(pScene sc,pCamera c,double azim,double elev) {
+  double     d,lazim,lelev;
+
+  /* compute speed vector */
+  if ( elev > 89.0f )       elev =  89.0;
+  else if ( elev < -89.0f ) elev = -89.0;
+  lazim = azim * DTOR;
+  lelev = elev * DTOR;
+  c->speed[0] = sin(lazim)*cos(lelev);
+  c->speed[1] = sin(lelev);
+  c->speed[2] = cos(lazim)*cos(lelev);
+
+  d = (double)c->speed[0]*sc->par.sunpos[0] + c->speed[1]*sc->par.sunpos[1] +
+              c->speed[2]*sc->par.sunpos[2];
+  d = d / sqrt((double)sc->par.sunpos[0]*sc->par.sunpos[0]+
+               sc->par.sunpos[1]*sc->par.sunpos[1]+
+               sc->par.sunpos[2]*sc->par.sunpos[2]);
+  d = acos(d);
+  if ( fabs(d) > 0.10*sc->persp->fovy*DTOR )
+    updateSun(sc,c);
+}
+
+
+pCamera initCamera(pScene sc,int up) {
+  pCamera  c;
+  pMesh    mesh;
+  double   dd;
+  double   look[3];
+
+  if ( ddebug ) printf("    initCamera dmax %g\n",sc->dmax);
+  if ( sc->camera ) c = sc->camera;
+  else {
+    c = (pCamera)M_calloc(1,sizeof(struct camera),"camera");
+    if ( !c ) {
+      printf("  ## unable to allocate memory / camera\n");
+      exit(1);
+    }
+  }
+
+  /* adjust coeffs */
+  mesh = cv.mesh[sc->idmesh];
+  c->eye[0] = c->eye[1] = 0.0;
+  c->eye[2] = sc->dmax;
+
+  c->vecup  = up;
+
+  c->speed[0] = 0.0;
+  c->speed[1] = 0.0;
+  c->speed[2] = c->eye[2];
+  dd = -1.0 / sqrt(c->speed[2]*c->speed[2]);
+  c->speed[2] *= dd;
+  c->spmod  = 0.01*sc->dmax;
+  c->altinc = 0.01*(mesh->ymax-mesh->ymin);
+
+  /* set sun position */
+  updateSun(sc,c);
+
+  if ( ddebug ) {
+    look[0] = c->eye[0] + sc->dmax*c->speed[0];
+    look[1] = c->eye[1] + sc->dmax*c->speed[1];
+    look[2] = c->eye[2] + sc->dmax*c->speed[2];
+    printf("    eye   %g %g %g\n",c->eye[0],c->eye[1],c->eye[2]);
+    printf("    speed %g %g %g\n",c->speed[0],c->speed[1],c->speed[2]);
+    printf("    look  %g %g %g\n",look[0],look[1],look[2]);
+  }
+
+  return(c);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/cenrad.c b/src/medit/cenrad.c
new file mode 100644
index 0000000..b49a65a
--- /dev/null
+++ b/src/medit/cenrad.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+/* compute circumradius and center */
+int cenrad(pMesh mesh,int iel,double *c,double *rad) {
+  pTetra      pt;
+  pPoint      p1,p2,p3,p4;
+  double      dd,ux,uy,uz,n1[3],n2[3],n3[3],c1,c2,c3,pl1,pl2,pl3;
+
+  pt = &mesh->tetra[iel];
+  if ( !pt->v[0] )  return(0);
+
+  p1 = &mesh->point[pt->v[0]];
+  p2 = &mesh->point[pt->v[1]];
+  p3 = &mesh->point[pt->v[2]];
+  p4 = &mesh->point[pt->v[3]];
+  
+  ux = p4->c[0] - p1->c[0];
+  uy = p4->c[1] - p1->c[1];
+  uz = p4->c[2] - p1->c[2];
+  dd = 1.0 / sqrt(ux*ux + uy*uy + uz*uz);
+  n1[0] = ux*dd;
+  n1[1] = uy*dd;
+  n1[2] = uz*dd;
+  /* plan: vecteur directeur passant par milieu(1,4) */
+  pl1 = n1[0]*(p4->c[0]+p1->c[0]) \
+      + n1[1]*(p4->c[1]+p1->c[1]) + n1[2]*(p4->c[2]+p1->c[2]);
+
+  ux = p4->c[0] - p2->c[0];
+  uy = p4->c[1] - p2->c[1];
+  uz = p4->c[2] - p2->c[2];
+  dd = 1.0 / sqrt(ux*ux + uy*uy + uz*uz);
+  n2[0] = ux*dd;
+  n2[1] = uy*dd;
+  n2[2] = uz*dd;
+  pl2 = n2[0]*(p4->c[0]+p2->c[0]) \
+      + n2[1]*(p4->c[1]+p2->c[1]) + n2[2]*(p4->c[2]+p2->c[2]);
+
+  ux = p4->c[0] - p3->c[0];
+  uy = p4->c[1] - p3->c[1];
+  uz = p4->c[2] - p3->c[2];
+  dd = 1.0 / sqrt(ux*ux + uy*uy + uz*uz);
+  n3[0] = ux*dd;
+  n3[1] = uy*dd;
+  n3[2] = uz*dd;
+  pl3 = n3[0]*(p4->c[0]+p3->c[0]) \
+      + n3[1]*(p4->c[1]+p3->c[1]) + n3[2]*(p4->c[2]+p3->c[2]);
+
+  /* center = intersection of 3 planes */
+  ux = n2[1]*n3[2] - n2[2]*n3[1];
+  uy = n1[2]*n3[1] - n1[1]*n3[2];
+  uz = n1[1]*n2[2] - n1[2]*n2[1];
+
+  dd = n1[0]*ux + n2[0]*uy + n3[0]*uz;
+  dd = 0.5 / dd;
+
+  c1 = ux*pl1 + uy*pl2 + uz*pl3;
+  c2 = pl1 * (n2[2]*n3[0] - n2[0]*n3[2]) \
+     + pl2 * (n1[0]*n3[2] - n3[0]*n1[2]) \
+     + pl3 * (n2[0]*n1[2] - n2[2]*n1[0]);
+  c3 = pl1 * (n2[0]*n3[1] - n2[1]*n3[0]) \
+     + pl2 * (n3[0]*n1[1] - n3[1]*n1[0]) \
+     + pl3 * (n1[0]*n2[1] - n2[0]*n1[1]);
+
+  c[0] = dd * c1;
+  c[1] = dd * c2;
+  c[2] = dd * c3;
+
+  /* radius (squared) */
+  *rad = (c[0] - p4->c[0]) * (c[0] - p4->c[0]) \
+       + (c[1] - p4->c[1]) * (c[1] - p4->c[1]) \
+       + (c[2] - p4->c[2]) * (c[2] - p4->c[2]);
+
+  return(1);
+}
diff --git a/src/medit/chrono.h b/src/medit/chrono.h
new file mode 100644
index 0000000..fac808a
--- /dev/null
+++ b/src/medit/chrono.h
@@ -0,0 +1,32 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <time.h>
+
+#ifndef  ON
+#define  RESET  0
+#define  ON     1
+#define  OFF    2
+#endif
+
+#define  TIMEMAX   16
+#define  MAXCLK    ( 1073741823. / (double)CLOCKS_PER_SEC )
+
+
+typedef struct mytime {
+  double    ctim,dtim;
+  time_t    ptim;
+  short     call;
+} mytime;
+
+
+/* prototypes */
+void   chrono(int cmode,mytime *ptt);
+double gttime(mytime t);
+void   tminit(mytime *t,int maxtim);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/clip.c b/src/medit/clip.c
new file mode 100644
index 0000000..feb586d
--- /dev/null
+++ b/src/medit/clip.c
@@ -0,0 +1,345 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+static pClip     cclip   = 0;
+static ubyte     curclip = 0;
+static GLfloat   plane[4]  = {-1.0, 0.0, 0.0, 0.0};
+
+
+static void drawCap(pScene sc,pClip clip,GLboolean docap) {
+
+  if ( !docap ) {  
+    if ( clip->active & C_EDIT )        glColor3f(1.0,0.0,1.0);
+    else if ( clip->active & C_FREEZE ) glColor3f(0.0,0.6,0.9);
+    else                                glColor3f(0.0,1.0,0.0);
+
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glLineWidth(3.);
+    glBegin(GL_QUADS);
+      glVertex3f(0.,-1.,-1.);
+      glVertex3f(0., 1.,-1.);
+      glVertex3f(0., 1.,1.);
+      glVertex3f(0.,-1.,1.);
+    glEnd();
+
+    glLineWidth(1.);
+    glColor3f(1.,0.7,0.);
+    glBegin(GL_LINES);
+      glVertex3f(0.,0.,-1.);
+      glVertex3f(0.,0.,1.);
+      glColor3f(1.,0.7,0.);
+      glVertex3f(0.,-1.,0.);
+      glVertex3f(0.,1.,0.);
+    glEnd();
+
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+  }
+  else {
+    glDisable(GL_LIGHTING);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);    
+    glColor4fv(sc->material[DEFAULT_MAT].dif);
+    glRecti(-100,-100,100,100);
+  }
+}
+
+
+/* display clipping plane */
+void updateClip(pClip clip,pMesh mesh) {
+  pScene      sc;
+  pTransform  cliptr,view;
+  GLfloat     dd,dmax,inv[16],axis[4],trans[4],matrix[16];
+  int         idw;
+
+  /* default */
+  if ( ddebug ) printf("updateClip\n");
+
+  /* retrieve context */
+  idw    = currentScene();
+  sc     = cv.scene[idw];
+  view   = sc->view;
+  cliptr = clip->cliptr;
+
+  /* compute clip transform */
+  if ( clip->active & C_EDIT ) {
+    invertMatrix(view->matrix,inv);
+    inv[3] = inv[7] = inv[11] = 0.0;  inv[15] = 1.0;
+    
+    /* rotation cumulative */
+    if ( cliptr->angle != 0.0 ) {
+      transformVector(trans,cliptr->axis,inv);
+      glPushMatrix();
+      glLoadIdentity();
+      glRotatef(cliptr->angle,trans[0],trans[1],trans[2]);
+      glMultMatrixf(cliptr->rot);
+      glGetFloatv(GL_MODELVIEW_MATRIX,cliptr->rot);
+      glPopMatrix();
+    }
+
+    /* translation cumulative */
+    axis[0] = cliptr->panx;
+    axis[1] = cliptr->pany;
+    axis[2] = 0.0;
+    axis[3] = 1.0;
+    if ( cliptr->manim == GL_FALSE )
+      cliptr->panx = cliptr->pany = 0.0;
+    transformVector(trans,axis,inv);
+
+    dd = trans[0]*clip->eqn[0]+trans[1]*clip->eqn[1]+trans[2]*clip->eqn[2];
+    trans[0] = dd*clip->eqn[0];
+    trans[1] = dd*clip->eqn[1];
+    trans[2] = dd*clip->eqn[2];
+
+    cliptr->tra[12] += trans[0];
+    cliptr->tra[13] += trans[1];
+    cliptr->tra[14] += trans[2];
+
+    /* truncation */
+    dmax = mesh->xmax - mesh->xmin;
+    dmax = max(dmax,mesh->ymax - mesh->ymin);
+    dmax = max(dmax,mesh->zmax - mesh->zmin) / 1.8;
+    if ( fabs(cliptr->tra[12]) > dmax || fabs(cliptr->tra[13]) > dmax ||
+         fabs(cliptr->tra[14]) > dmax ) {
+      if ( cliptr->manim == GL_TRUE ) {
+        cliptr->panx = -cliptr->panx;
+        cliptr->pany = -cliptr->pany;
+      }
+      else {
+        cliptr->tra[12] = max(-dmax,min(dmax,cliptr->tra[12]));
+        cliptr->tra[13] = max(-dmax,min(dmax,cliptr->tra[13]));
+        cliptr->tra[14] = max(-dmax,min(dmax,cliptr->tra[14]));
+      }
+    }
+
+    /* final transformation */
+    glPushMatrix();
+    glLoadIdentity();
+    glMultMatrixf(cliptr->tra);
+    glMultMatrixf(cliptr->rot);
+    glGetFloatv(GL_MODELVIEW_MATRIX,cliptr->matrix);
+    glPopMatrix();
+
+    /* compute plane equation */
+    invertMatrix(cliptr->matrix,inv);
+    transformPoint(clip->eqn,plane,inv);
+
+    if ( clip->active & C_REDO )
+      clipVertices(mesh,sc,clip);
+   /* clip->active |= C_REDO;*/
+  }
+
+  else if ( clip->active & C_FREEZE ) {
+    glPushMatrix();
+    glLoadMatrixf(view->matrix);
+    glTranslatef(sc->cx,sc->cy,sc->cz);
+    glGetFloatv(GL_MODELVIEW_MATRIX,matrix);
+    glPopMatrix();
+    invertMatrix(matrix,inv);
+    inv[3] = inv[7] = inv[11] = 0.0;  inv[15] = 1.0;
+
+    glPushMatrix();
+    glLoadMatrixf(inv);
+    glMultMatrixf(view->oldmat);
+    glTranslatef(sc->cx,sc->cy,sc->cz);
+    glMultMatrixf(cliptr->matrix);
+    glGetFloatv(GL_MODELVIEW_MATRIX,cliptr->matrix);
+    glPopMatrix();
+
+    /* compute plane equation */
+    invertMatrix(cliptr->matrix,inv);
+    transformPoint(clip->eqn,plane,inv);
+    clip->active |= C_REDO;
+  }
+  if ( !cliptr->manim ) {
+    cliptr->angle = 0.0;
+    clip->active ^= C_UPDATE;
+  }
+}
+
+
+void clipVertices(pMesh mesh,pScene sc,pClip clip) {
+  pTetra     pt;
+  pHexa      ph;
+  pPoint     p0;
+  double     dd1,zero;
+  int        k,l,nbpos,nbneg,nbnul;
+
+  /* check points in plane */
+  zero = sc->dmax*1.e-13;
+  for (k=1; k<=mesh->np; k++) {
+    p0 = &mesh->point[k];
+    if ( p0->tag & M_UNUSED )  continue;
+    dd1 = p0->c[0]*clip->eqn[0] + p0->c[1]*clip->eqn[1] \
+        + p0->c[2]*clip->eqn[2] + clip->eqn[3];
+    if ( dd1 > zero )      p0->clip = 2;
+    else if ( dd1 < zero ) p0->clip = 1;
+    else                   p0->clip = 0;
+  }
+
+  /* update tetrahedra */
+  for (k=1; k<=mesh->ntet; k++) {
+    pt = &mesh->tetra[k];
+    pt->clip = 0;
+    nbpos = nbneg = nbnul = 0;
+    for (l=0; l<4; l++) {
+      p0  = &mesh->point[pt->v[l]];
+      if ( p0->clip == 2 )       nbpos++;
+      else if ( p0->clip == 1 )  nbneg++;
+      else                       nbnul++;
+    }
+    if ( nbpos && nbpos+nbnul < 4 )  pt->clip = 1;
+  }
+
+  /* update hexahedra */
+  for (k=1; k<=mesh->nhex; k++) {
+    ph = &mesh->hexa[k];
+    ph->clip = 0;
+    nbpos = nbneg = nbnul = 0;
+    for (l=0; l<8; l++) {
+      p0  = &mesh->point[ph->v[l]];
+      if ( p0->clip == 2 )       nbpos++;
+      else if ( p0->clip == 1 )  nbneg++;
+      else                       nbnul++;
+    }
+    if ( nbpos && nbpos+nbnul < 8 )  ph->clip = 1;
+  }
+}
+
+
+void drawClip(pScene sc,pClip clip,pMesh mesh,GLboolean docap) {
+  pTransform  cliptr,view;
+  GLfloat     scale;
+
+  /* default */
+  if ( ddebug ) printf("drawClip\n");
+  view   = sc->view;
+  cliptr = clip->cliptr;
+
+  if ( clip->active & C_UPDATE )  updateClip(clip,mesh);
+  if ( clip->active & C_REDO ) {
+    if ( !animate )  glutSetCursor(GLUT_CURSOR_WAIT);
+    /* update clip plane */
+    clipVertices(mesh,sc,clip);
+
+    /* build display lists */
+    if ( clip->active & C_VOL ) {
+      if ( sc->clist[LTets] )  glDeleteLists(sc->clist[LTets],1);
+      if ( sc->clist[LHexa] )  glDeleteLists(sc->clist[LHexa],1);
+      if ( sc->cmlist[LTets] ) glDeleteLists(sc->cmlist[LTets],1);
+      if ( sc->cmlist[LHexa] ) glDeleteLists(sc->cmlist[LHexa],1);
+      sc->clist[LTets] = sc->cmlist[LTets] = (GLuint)0;
+      sc->clist[LHexa] = sc->cmlist[LHexa] = (GLuint)0;
+
+      if ( clip->active & C_CAP ) {
+        sc->clist[LTets]  = capTetra(mesh);
+        if ( sc->mode & S_MAP )
+          sc->cmlist[LTets] = capTetraMap(mesh);
+        else if ( sc->isotyp & S_ISOLINE )
+          sc->ilist[LTets] = capTetraIso(mesh);
+      }
+      else {
+        sc->clist[LTets] = listTetra(sc,mesh,1);
+        sc->clist[LHexa] = listHexa(sc,mesh,1);
+        if ( sc->mode & S_MAP ) {
+          sc->cmlist[LTets] = listTetraMap(sc,mesh,1);
+          sc->cmlist[LHexa] = listHexaMap(sc,mesh,1);
+        }
+      }
+      if ( !animate )  clip->active ^= C_REDO;
+    }
+    else clip->active ^= C_REDO;
+    
+    if ( sc->isotyp & S_VECTOR ) {
+      if ( sc->vlist[LTets] )  glDeleteLists(sc->vlist[LTets],1);
+        sc->vlist[LTets] = listClipTetraVector(mesh);
+      if ( sc->vlist[LHexa] )  glDeleteLists(sc->vlist[LHexa],1);
+        sc->vlist[LHexa] = listClipHexaVector(mesh);
+    }
+    if ( !animate )  glutSetCursor(GLUT_CURSOR_INHERIT);
+  }
+
+  /* display plane frame */
+  if ( clip->active & C_HIDE )  return;
+  glPushMatrix();
+  glMultMatrixf(cliptr->matrix);
+  scale = 0.3*(sc->dmax+sc->dmin);
+  glScalef(scale,scale,scale);
+
+  drawCap(sc,clip,docap);
+
+  glPopMatrix();
+}
+
+
+void copyClip(pClip clip) {
+  if ( !cclip ) {
+    cclip = (pClip)M_calloc(1,sizeof(struct clip),"clip");
+    if ( !clip )  exit(2);
+  }
+  cclip = (pClip)memcpy(cclip,clip,sizeof(struct clip));
+  if ( !cclip )  exit(2);
+  curclip = 1;
+}
+
+int pasteClip(pClip clip) {
+  if ( !curclip )  return(0);
+  clip = (pClip)memcpy(clip,cclip,sizeof(struct clip));
+  if ( !clip )  exit(2);
+  clip->active = 0;
+  curclip = 0;
+  return(1);
+}
+
+void tiltClip(pScene sc,pClip clip) { 
+  float    axis[4];
+  
+  axis[0] = clip->cliptr->axis[0];
+  axis[1] = clip->cliptr->axis[1];
+  axis[2] = clip->cliptr->axis[2];
+
+  transformVector(clip->cliptr->axis,axis,sc->view->matrix);
+  /*clip->cliptr->angle = 90.0;*/
+
+  clip->active |= C_REDO;
+}
+
+/* change clip orientation */
+void invertClip(pScene sc,pClip clip) {
+  clip->eqn[0] = -clip->eqn[0];
+  clip->eqn[1] = -clip->eqn[1];
+  clip->eqn[2] = -clip->eqn[2];
+  clip->eqn[3] = -clip->eqn[3];
+  plane[0]     = -plane[0];
+}
+
+void resetClip(pScene sc,pClip clip,pMesh mesh) {
+  double    dd;
+
+  resetTransform(clip->cliptr);
+  dd = sc->par.clip[0]*sc->par.clip[3] + sc->par.clip[1]*sc->par.clip[4] \
+     + sc->par.clip[2]*sc->par.clip[5];
+
+  clip->active |= C_REDO;
+  clip->eqn[0] = sc->par.clip[3];
+  clip->eqn[1] = sc->par.clip[4];
+  clip->eqn[2] = sc->par.clip[5];
+  clip->eqn[3] = -dd;
+  /*clip->active = C_ON + C_VOL;*/
+}
+
+
+/* create a clipping plane */
+pClip createClip(pScene sc,pMesh mesh) {
+  pClip    clip;
+
+  /* default */
+  clip = (pClip)M_calloc(1,sizeof(struct clip),"clip");
+  assert(clip);
+  clip->cliptr = (pTransform)M_calloc(1,sizeof(struct transform),"clip");
+  assert(clip->cliptr);
+
+  resetClip(sc,clip,mesh);
+  return(clip);
+}
+
+
diff --git a/src/medit/clipvol.c b/src/medit/clipvol.c
new file mode 100644
index 0000000..067dc86
--- /dev/null
+++ b/src/medit/clipvol.c
@@ -0,0 +1,513 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define NBCOL    9
+
+/* build list for capping */
+GLuint capTetra(pMesh mesh) {
+  pScene     sc;
+  pClip      clip;
+  GLuint     dlist = 0;
+  pTetra     pt;
+  pPoint     p0,p1;
+  pMaterial  pm;
+  double     dd1[6],d,ax,ay,az,bx,by,bz;
+  double     cx[4],cy[4],cz[4],cc;
+  float      n[3];
+  int        m,k,k1,k2,l,transp,pos[6],neg[6],nbpos,nbneg,nbnul;
+  static int tn[4] = {0,0,1,1};
+  static int tp[4] = {0,1,1,0};
+
+  /* default */
+  if (!mesh->ntet )  return(0);
+  if ( ddebug ) printf("create capping list / TETRA\n");
+ 
+  /* build display list */
+  sc   = cv.scene[currentScene()];
+  clip = sc->clip;
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTets];
+    if ( !k || pm->flag )  continue;
+
+    transp = 0;
+    if ( !(sc->mode & S_MATERIAL) )
+      pm = &sc->material[DEFAULT_MAT+1];
+
+    /* check transparency */
+    transp = pm->amb[3] < 0.999 || pm->dif[3] < 0.999 || pm->spe[3] < 0.999;
+    if ( transp ) {
+      glDepthMask(GL_FALSE);
+      glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+      glEnable(GL_BLEND);
+    }
+    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,pm->dif);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,pm->amb);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,pm->spe);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,pm->emi);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,&pm->shininess);
+ 
+    while ( k != 0 ) {
+      pt = &mesh->tetra[k];
+      if ( !pt->v[0] || !pt->clip ) {
+        k = pt->nxt;
+        continue;
+      }
+      nbpos = nbneg = nbnul = 0;
+      for (l=0; l<4; l++) {
+        p0 = &mesh->point[pt->v[l]];
+        if ( p0->clip == 2 )      pos[nbpos++] = l;
+        else if (p0->clip == 1 )  neg[nbneg++] = l;
+        else                      nbnul++;
+        dd1[l] = p0->c[0]*clip->eqn[0] + p0->c[1]*clip->eqn[1] \
+               + p0->c[2]*clip->eqn[2] + clip->eqn[3];
+      }
+
+      if ( nbneg == 2 && nbpos == 2 ) {
+        /* display quadrilateral */
+        for (l=0; l<4; l++) {
+          k1 = neg[tn[l]];
+          k2 = pos[tp[l]];
+          p0 = &mesh->point[pt->v[k1]];
+          p1 = &mesh->point[pt->v[k2]];
+          cc = 1.0f;
+          if ( dd1[k2]-dd1[k1] != 0.0f )
+            cc = fabs(dd1[k1] / (dd1[k2]-dd1[k1]));
+          cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+          cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+          cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+        }
+
+        /* compute face normal */
+        ax = cx[1]-cx[0]; ay = cy[1]-cy[0]; az = cz[1]-cz[0];
+        bx = cx[2]-cx[0]; by = cy[2]-cy[0]; bz = cz[2]-cz[0];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( d > 0.0f ) {
+          d = 1.0f / sqrt(d);
+          n[0] *= d;  
+          n[1] *= d;  
+          n[2] *= d;
+        }
+        glBegin(GL_QUADS);
+        glNormal3fv(n);
+        glVertex3f(cx[0],cy[0],cz[0]);
+        glVertex3f(cx[1],cy[1],cz[1]);
+        glVertex3f(cx[2],cy[2],cz[2]);
+        glVertex3f(cx[3],cy[3],cz[3]);
+        glEnd();
+      }
+      
+      else {
+        /* display triangle */
+        for (l=0; l<3; l++) {
+          k1 = nbneg == 3 ? neg[l] : pos[l];
+          k2 = nbneg == 3 ? pos[0] : neg[0];
+          p0 = &mesh->point[pt->v[k1]];
+          p1 = &mesh->point[pt->v[k2]];
+          cc = fabs(dd1[k1] / (dd1[k2]-dd1[k1]));
+          cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+          cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+          cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+        }
+        /* compute face normal */
+        ax = cx[1]-cx[0]; ay = cy[1]-cy[0]; az = cz[1]-cz[0];
+        bx = cx[2]-cx[0]; by = cy[2]-cy[0]; bz = cz[2]-cz[0];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( d > 0.0f ) {
+          d = 1.0f / sqrt(d);
+          n[0] *= d;
+          n[1] *= d;
+          n[2] *= d;
+        }
+        glBegin(GL_TRIANGLES);
+        glNormal3fv(n);
+          glVertex3f(cx[0],cy[0],cz[0]);
+          glVertex3f(cx[1],cy[1],cz[1]);
+          glVertex3f(cx[2],cy[2],cz[2]);
+        glEnd();
+      } 
+      k = pt->nxt;
+    }
+    if ( transp ) {
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+    }
+  }
+
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list for capping map */
+GLuint capTetraMap(pMesh mesh) {
+  pScene     sc;
+  pClip      clip;
+  GLuint     dlist = 0;
+  pTetra     pt;
+  pPoint     p0,p1;
+  pMaterial  pm;
+  pSolution  ps0,ps1;
+  double     dd1[6],d,ax,ay,az,bx,by,bz;
+  double     cx[4],cy[4],cz[4],cc;
+  float      n[3],sol[4];
+  int        m,k,k1,k2,l,pos[6],neg[6],nbpos,nbneg,nbnul;
+  static int tn[4] = {0,0,1,1};
+  static int tp[4] = {0,1,1,0};
+  triangle   t1,t2;
+
+  /* default */
+  if ( !mesh->ntet || !mesh->nbb )  return(0);
+  if ( ddebug ) printf("create capping map list / TETRA\n");
+  sc  = cv.scene[currentScene()];
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* build display list */
+  clip = sc->clip;
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  glBegin(GL_TRIANGLES);
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTets];
+    if ( !k || pm->flag )  continue;
+ 
+    while ( k != 0 ) {
+      pt = &mesh->tetra[k];
+      if ( !pt->v[0] || !pt->clip ) {
+        k = pt->nxt;
+        continue;
+      }
+      nbpos = nbneg = nbnul = 0;
+      for (l=0; l<4; l++) {
+        p0 = &mesh->point[pt->v[l]];
+        if ( p0->clip == 2 )      pos[nbpos++] = l;
+        else if (p0->clip == 1 )  neg[nbneg++] = l;
+        else                      nbnul++;
+        dd1[l] = p0->c[0]*clip->eqn[0] + p0->c[1]*clip->eqn[1] \
+               + p0->c[2]*clip->eqn[2] + clip->eqn[3];
+      }
+
+      if ( nbneg == 2 && nbpos == 2 ) {
+        /* display quadrilateral */
+        for (l=0; l<4; l++) {
+          k1 = neg[tn[l]];
+          k2 = pos[tp[l]];
+          p0 = &mesh->point[pt->v[k1]];
+          p1 = &mesh->point[pt->v[k2]];
+          cc = 1.0f;
+          if ( dd1[k2]-dd1[k1] != 0.0f )
+            cc = fabs(dd1[k1] / (dd1[k2]-dd1[k1]));
+          cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+          cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+          cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+          if ( mesh->typage == 2 ) {
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            sol[l] = ps0->bb+cc*(ps1->bb-ps0->bb);
+          }
+          else {
+            ps0 = &mesh->sol[k];
+            sol[l] = ps0->bb;
+          }
+        }
+        
+        /* compute face normal */
+        ax = cx[1]-cx[0]; ay = cy[1]-cy[0]; az = cz[1]-cz[0];
+        bx = cx[2]-cx[0]; by = cy[2]-cy[0]; bz = cz[2]-cz[0];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( d > 0.0f ) {
+          d = 1.0f / sqrt(d);
+          n[0] *= d;  
+          n[1] *= d;  
+          n[2] *= d;
+        }
+
+        /* store triangles */
+        t1.a[0] = t2.a[0] = cx[0];
+        t1.a[1] = t2.a[1] = cy[0];
+        t1.a[2] = t2.a[2] = cz[0];
+
+        t1.b[0] = cx[1];
+        t1.b[1] = cy[1];
+        t1.b[2] = cz[1];
+
+        t1.c[0] = t2.b[0] = cx[2]; 
+        t1.c[1] = t2.b[1] = cy[2]; 
+        t1.c[2] = t2.b[2] = cz[2]; 
+
+        t2.c[0] = cx[3]; 
+        t2.c[1] = cy[3]; 
+        t2.c[2] = cz[3]; 
+        
+        /* store normals */
+        memcpy(t1.na,n,3*sizeof(float));
+	memcpy(t1.nb,n,3*sizeof(float));
+	memcpy(t1.nc,n,3*sizeof(float));
+	memcpy(t2.na,n,3*sizeof(float));
+	memcpy(t2.nb,n,3*sizeof(float));
+	memcpy(t2.nc,n,3*sizeof(float));
+
+        /* store solutions */
+        t1.va = t2.va = sol[0];
+	t1.vb = sol[1];
+	t1.vc = t2.vb = sol[2];
+	t2.vc = sol[3];
+        /* color interpolation */
+        cutTriangle(sc,t1);
+        cutTriangle(sc,t2);
+      }
+
+      else {
+        /* display triangle */
+        for (l=0; l<3; l++) {
+          k1 = nbneg == 3 ? neg[l] : pos[l];
+          k2 = nbneg == 3 ? pos[0] : neg[0];
+          p0 = &mesh->point[pt->v[k1]];
+          p1 = &mesh->point[pt->v[k2]];
+          cc = fabs(dd1[k1] / (dd1[k2]-dd1[k1]));
+          cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+          cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+          cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+          if ( mesh->typage == 2 ) {
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            sol[l] = ps0->bb+cc*(ps1->bb-ps0->bb);
+          }
+          else {
+            ps0 = &mesh->sol[k];
+            sol[l] = ps0->bb;
+          }
+        }
+
+        /* compute face normal */
+        ax = cx[1]-cx[0]; ay = cy[1]-cy[0]; az = cz[1]-cz[0];
+        bx = cx[2]-cx[0]; by = cy[2]-cy[0]; bz = cz[2]-cz[0];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( d > 0.0f ) {
+          d = 1.0f / sqrt(d);
+          n[0] *= d;
+          n[1] *= d;
+          n[2] *= d;
+        }
+
+        /* store triangle */
+        t1.a[0] = cx[0];
+        t1.a[1] = cy[0];
+        t1.a[2] = cz[0];
+
+        t1.b[0] = cx[1];
+        t1.b[1] = cy[1];
+        t1.b[2] = cz[1];
+
+        t1.c[0] = cx[2];
+        t1.c[1] = cy[2]; 
+        t1.c[2] = cz[2]; 
+
+        /* store normal */
+        memcpy(t1.na,n,3*sizeof(float));
+        memcpy(t1.nb,n,3*sizeof(float));
+        memcpy(t1.nc,n,3*sizeof(float));
+ 
+        /* store solutions */
+        t1.va = sol[0];
+        t1.vb = sol[1];
+        t1.vc = sol[2];
+        
+        /* color interpolation */
+        cutTriangle(sc,t1);
+      }     
+      k = pt->nxt;
+    }
+  }
+  
+  glEnd();
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list for capping isolines */
+GLuint capTetraIso(pMesh mesh) {
+  pScene     sc;
+  pClip      clip;
+  GLuint     dlist = 0;
+  pTetra     pt;
+  pPoint     p0,p1;
+  pMaterial  pm;
+  pSolution  ps0,ps1;
+  double     dd1[6];
+  double     rgb[3],cx[4],cy[4],cz[4],ccx,ccy,ccz,cc;
+  float      iso,kc,sol[4];
+  int        i,m,k,k1,k2,l,l1,nc,pos[6],neg[6],nbpos,nbneg,nbnul,ncol;
+  static int tn[4] = {0,0,1,1};
+  static int tp[4] = {0,1,1,0};
+  static double hsv[3]   = { 0.0f, 1.0f, 0.20f };
+  static int idirt[5] = {0,1,2,0,1};
+  static int idirq[6] = {0,1,2,3,0,1};
+
+  /* default */
+  if ( !mesh->ntet || !mesh->nbb || mesh->typage == 1 )  return(0);
+  if ( ddebug ) printf("create capping iso list / TETRA\n");
+  sc = cv.scene[currentScene()];
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* build display list */
+  clip  = sc->clip;
+  if ( !(clip->active & C_ON) )  return(0);
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  glBegin(GL_LINES);
+  ncol = NBCOL;
+  for (i=0; i<=ncol*(MAXISO-1); i++) {
+    if ( i < ncol*(MAXISO-1) ) {
+      l   = i / ncol;
+      kc  = (i % ncol) / (float)ncol;
+      iso = sc->iso.val[l]*(1.0-kc)+sc->iso.val[l+1]*kc;
+      hsv[0] = sc->iso.col[l]*(1.0-kc)+sc->iso.col[l+1]*kc;
+    }
+    else {
+      iso    = sc->iso.val[MAXISO-1];
+      hsv[0] = sc->iso.col[MAXISO-1];
+    }
+    
+    hsvrgb(hsv,rgb);
+    glColor3dv(rgb);
+
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTets];
+      if ( !k || pm->flag )  continue;
+ 
+      while ( k != 0 ) {
+        pt = &mesh->tetra[k];
+        if ( !pt->v[0] || !pt->clip ) {
+          k = pt->nxt;
+          continue;
+        }
+        nbpos = nbneg = nbnul = 0;
+        for (l=0; l<4; l++) {
+          p0 = &mesh->point[pt->v[l]];
+          if ( p0->clip == 2 )      pos[nbpos++] = l;
+          else if (p0->clip == 1 )  neg[nbneg++] = l;
+          else                      nbnul++;
+          dd1[l] = p0->c[0]*clip->eqn[0] + p0->c[1]*clip->eqn[1] \
+                 + p0->c[2]*clip->eqn[2] + clip->eqn[3];
+        }
+
+        if ( nbneg == 2 && nbpos == 2 ) {
+          /* analyze quadrilateral */
+          for (l=0; l<4; l++) {
+            k1 = neg[tn[l]];
+            k2 = pos[tp[l]];
+            p0 = &mesh->point[pt->v[k1]];
+            p1 = &mesh->point[pt->v[k2]];
+            cc = 1.0f;
+            if ( dd1[k2]-dd1[k1] != 0.0f )
+              cc = fabs(dd1[k1] / (dd1[k2]-dd1[k1]));
+            cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            sol[l] = ps0->bb+cc*(ps1->bb-ps0->bb);
+          }
+          for (l=0; l<4; l++) {
+            l1  = idirq[l+1];
+            if ( (sol[l] > iso && sol[l1] <= iso) ||
+                 (sol[l] < iso && sol[l1] >= iso) ) {
+              cc = 0.0f;
+ 
+              if ( fabs(sol[l1]-sol[l]) > 0.0f )
+                cc = (iso-sol[l]) / (sol[l1]-sol[l]);
+              if ( cc == 0.0f || cc == 1.0f )  continue;
+              ccx = cx[l]+cc*(cx[l1]-cx[l]);
+              ccy = cy[l]+cc*(cy[l1]-cy[l]);
+              ccz = cz[l]+cc*(cz[l1]-cz[l]);
+              glVertex3f(ccx,ccy,ccz);
+              nc++;
+            }
+            else if ( sol[l] == iso && sol[l1] == iso ) {
+              nc = 2;
+              glVertex3f(cx[l],cy[l],cz[l]);
+              glVertex3f(cx[l1],cy[l1],cz[l1]);
+              break;
+            }
+          }
+        }
+        else {
+          /* analyze triangle */
+          for (l=0; l<3; l++) {
+            k1 = nbneg == 3 ? neg[l] : pos[l];
+            k2 = nbneg == 3 ? pos[0] : neg[0];
+            p0 = &mesh->point[pt->v[k1]];
+            p1 = &mesh->point[pt->v[k2]];
+            cc = fabs(dd1[k1] / (dd1[k2]-dd1[k1]));
+            cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            sol[l] = ps0->bb+cc*(ps1->bb-ps0->bb);
+          }
+          
+          nc = 0;
+          ccx = ccy = ccz = 0.0f;
+          for (l=0; l<3; l++) {
+            l1  = idirt[l+1];
+            if ( (sol[l] > iso && sol[l1] <= iso) ||
+                 (sol[l] < iso && sol[l1] >= iso) ) {
+              cc = 0.0f;
+ 
+              if ( fabs(sol[l1]-sol[l]) > 0.0f )
+                cc = (iso-sol[l]) / (sol[l1]-sol[l]);
+              if ( cc == 0.0f || cc == 1.0f )  continue;
+              ccx = cx[l]+cc*(cx[l1]-cx[l]);
+              ccy = cy[l]+cc*(cy[l1]-cy[l]);
+              ccz = cz[l]+cc*(cz[l1]-cz[l]);
+              glVertex3f(ccx,ccy,ccz);
+              nc++;
+            }
+            else if ( sol[l] == iso && sol[l1] == iso ) {
+              nc = 2;
+              glVertex3f(cx[l],cy[l],cz[l]);
+              glVertex3f(cx[l1],cy[l1],cz[l1]);
+              break;
+            }
+          }
+          if ( nc > 0 && nc != 2 )
+            glVertex3f(ccx,ccy,ccz);
+        }
+        k = pt->nxt;
+      }
+    }
+  }
+  
+  glEnd();
+  glEndList();
+  return(dlist);
+}
diff --git a/src/medit/critip.c b/src/medit/critip.c
new file mode 100644
index 0000000..2234caa
--- /dev/null
+++ b/src/medit/critip.c
@@ -0,0 +1,312 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+typedef struct saddle {
+  double r1,r2;
+  float  pt[3];
+  float  vp1[2],vp2[2];
+  int    k;
+} Saddle;
+
+
+#define EPSD  1.e-14
+#define EPS3  1.e-03
+#define MAXPS 100
+#define HSIZ  0.001
+
+static int idir[5] = {0,1,2,0,1};
+
+
+int closedBall(pMesh mesh,int depart,ubyte i) {
+  pTriangle  pt;
+  int        adj,iadr;
+  ubyte      voy;
+
+  pt   = &mesh->tria[depart];
+  voy  = idir[i+1];
+  iadr = 3*(depart-1)+1;
+  adj  = mesh->adja[iadr+voy];
+
+  /* search triangles in ball */
+  while ( adj && adj != depart ) {
+    voy  = mesh->voy[iadr+voy];
+    iadr = 3*(adj-1)+1;
+    voy  = idir[voy+2];
+    adj  = mesh->adja[iadr+voy];
+  }
+
+  return( adj == depart );
+}
+
+
+GLuint listCritPoint(pScene sc,pMesh mesh) {
+  pTriangle   pt;
+  pPoint      p0,p1,p2;
+  pSolution   s0,s1,s2;
+  pMaterial   pm;
+  Saddle      sad[MAXPS];
+  GLuint      dlist;
+  double      aire,ux,uy,vx,vy,dd,cb0[3],cb1[3],cb2[3],vv[3][2],bc[3];
+  double      rgb[3],a0,a1,delta,rr1,rr2,aa,dmin;
+  float       p[3];
+  int        *adj,iadr,i,i1,i2,k,m,ncp,ps,ifilt;
+  ubyte       typ,tag;
+  static double hsv[3] = {0.0f, 1.0f, 0.80f};
+  time_t      t;
+
+  if ( !mesh->nbb || mesh->nfield != mesh->dim ) return(0);
+  if ( mesh->nt && !hashTria(mesh) )  return(0);
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( ddebug )  printf("find critical points\n");
+
+  /* build list */
+  typ = 0;
+  ncp = 0;
+  ps  = 0;
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+  glPointSize(4.0);
+
+  dmin   = sc->dmax * EPS;
+  dmin  *= dmin;
+  ifilt  = 0;
+  hsv[0] = sc->iso.col[0];
+  hsvrgb(hsv,rgb);
+
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTria];
+    if ( !k || pm->flag )  continue;
+
+    while ( k != 0 ) {
+      pt = &mesh->tria[k];
+      if ( !pt->v[0] ) {
+        k = pt->nxt;
+        continue;
+      }
+
+      p0 = &mesh->point[pt->v[0]];
+      p1 = &mesh->point[pt->v[1]];
+      p2 = &mesh->point[pt->v[2]];
+      s0 = &mesh->sol[pt->v[0]];
+      s1 = &mesh->sol[pt->v[1]];
+      s2 = &mesh->sol[pt->v[2]];
+      
+      ux = p1->c[0] - p0->c[0];
+      uy = p1->c[1] - p0->c[1];
+      vx = p2->c[0] - p0->c[0];
+      vy = p2->c[1] - p0->c[1];
+      
+      aire = ux*vy - uy*vx;
+      if ( aire == 0.0 ) {
+        k = pt->nxt;
+        continue;
+      }
+      else if ( aire < 0.0 ) {
+        p1 = &mesh->point[pt->v[2]];
+        p2 = &mesh->point[pt->v[1]];
+        s1 = &mesh->sol[pt->v[2]];
+        s2 = &mesh->sol[pt->v[1]];
+        aire = -aire;
+      }
+
+      /* coef des barycentriques */
+      aire   = 1.0 / aire;
+      cb0[0] =   p1->c[1] - p2->c[1];
+      cb0[1] = -(p1->c[0] - p2->c[0]);
+      cb0[2] =   p1->c[0]*p2->c[1] - p1->c[1]*p2->c[0];
+
+      cb1[0] =   p2->c[1] - p0->c[1];
+      cb1[1] = -(p2->c[0] - p0->c[0]);
+      cb1[2] =   p2->c[0]*p0->c[1] - p2->c[1]*p0->c[0];
+
+      cb2[0] =   p0->c[1] - p1->c[1];
+      cb2[1] = -(p0->c[0] - p1->c[0]);
+      cb2[2] =   p0->c[0]*p1->c[1] - p0->c[1]*p1->c[0];
+      for (i=0; i<3; i++) {
+        vv[i][0] = aire * (cb0[i]*s0->m[0] + cb1[i]*s1->m[0] + cb2[i]*s2->m[0]);
+        vv[i][1] = aire * (cb0[i]*s0->m[1] + cb1[i]*s1->m[1] + cb2[i]*s2->m[1]);
+      }
+
+      dd = vv[0][0]*vv[1][1] - vv[0][1]*vv[1][0];
+      if ( fabs(dd) < EPSD ) {
+        k = pt->nxt;
+        continue;
+      }
+
+      dd   = 1.0 / dd;
+      p[0] = dd * (vv[1][0]*vv[2][1] - vv[2][0]*vv[1][1]);
+      p[1] = dd * (vv[0][1]*vv[2][0] - vv[0][0]*vv[2][1]);
+      p[2] = 0.0;
+  
+      if ( p[0] < mesh->xmin-mesh->xtra || p[0] > mesh->xmax-mesh->xtra
+        || p[1] < mesh->ymin-mesh->ytra || p[1] > mesh->ymax-mesh->ytra ) {
+        k = pt->nxt;
+        continue;
+      }
+      else if ( !inTria(mesh,k,p,bc) ) {
+        k = pt->nxt;
+        continue;
+      }
+
+      /* filtering boundary points */
+      tag  = 0;
+      for (i=0; i<3; i++)  tag |= (bc[i] < EPS3) << i;
+      if ( tag ) {
+        iadr = 3*(k-1)+1;
+        adj  = &mesh->adja[iadr];
+        ifilt ++;
+	switch (tag) {
+          case 1:
+	    if ( !adj[0] ) {
+	      k = pt->nxt;
+	      continue;
+	    }
+	    break;
+	  case 2:
+	    if ( !adj[1] ) {
+	      k = pt->nxt;
+	      continue;
+	    }
+	    break;
+	  case 4:
+	    if ( !adj[2] ) {
+	      k = pt->nxt;
+	      continue;
+	    }
+	    break;
+	  
+	  case 3:
+            if ( !closedBall(mesh,k,2) ) {
+	      k = pt->nxt;
+	      continue;
+	    }
+	    break;
+	  case 5:
+            if ( !closedBall(mesh,k,1) ) {
+	      k = pt->nxt;
+	      continue;
+	    }	  
+	    break;  
+	  case 6:
+            if ( !closedBall(mesh,k,0) ) {
+	      k = pt->nxt;
+	      continue;
+	    }
+	    break;
+	}
+      }
+
+      /* eigenvalues of jacobian */
+      a1 = -(vv[0][0] + vv[1][1]);
+      a0 = vv[0][0] *vv[1][1] - vv[0][1]*vv[1][0];
+      delta = a1*a1 - 4*a0;
+      i1 = i2 = 0;
+      if ( delta >= 0.0 ) {
+        delta = sqrt(delta);
+        rr1 = 0.5 * (-a1+delta);
+        rr2 = 0.5 * (-a1-delta);
+      }
+      else {
+        delta = sqrt(fabs(delta));
+        rr1 = rr2 = -0.5 * a1;
+        i1  = i2  =  0.5 * delta;
+      }
+
+      /* classification */
+      if ( i1 && i2 ) {
+        glColor3f(0.0,1.0,0.5);
+        if ( rr1 == 0.0f && rr2 == 0.0f )
+          output2(p[0],p[1],"Cp");   /* center */
+        else if ( rr1 > 0.0f && rr2 > 0.0f )
+          output2(p[0],p[1],"Rf");   /* repelling focus */
+        else if ( rr1 < 0.0f && rr2 < 0.0f )
+          output2(p[0],p[1],"Af");   /* attracting focus */
+      }
+      else if ( !i1 && !i2 ) {
+        glColor3f(1.0,0.5,0.0);
+        if ( rr1 > 0.0f && rr2 > 0.0f )
+          output2(p[0],p[1],"Rn");   /* repelling node */
+        else if ( rr1 < 0.0f && rr2 < 0.0f )
+          output2(p[0],p[1],"An");   /* attracting node */
+        else if ( rr1*rr2 < 0.0f ) {
+          output2(p[0],p[1],"Sp");   /* Saddle point */
+          if ( ddebug ) 
+            printf("  saddle point %f %f\n",p[0]+mesh->xtra,p[1]+mesh->ytra);
+          if ( ps < MAXPS-5 ) {
+            ++ps;
+            sad[ps].pt[0] = p[0];
+            sad[ps].pt[1] = p[1];
+            sad[ps].pt[2] = 0.0f;
+
+            /* eigenvalues */
+            sad[ps].r1 = rr1;
+            sad[ps].r2 = rr2;
+            
+            /* eigenvectors */
+            aa = vv[0][0]*vv[0][0];
+            dd = vv[1][1]*vv[1][1];
+            delta = sqrt(aa-2.0*vv[0][0]*vv[1][1]+dd+4.0*vv[0][1]*vv[1][0]);
+            sad[ps].vp1[0] = -0.5*(-vv[0][0]+vv[1][1]-delta);
+            sad[ps].vp1[1] = vv[0][1];
+
+            sad[ps].vp2[0] = -0.5*(-vv[0][0]+vv[1][1]+delta);
+            sad[ps].vp2[1] = vv[0][1];
+            
+            sad[ps].k = k;
+          }
+        }
+      }
+
+      /* point color */
+      glBegin(GL_POINTS);
+        glColor3dv(rgb);
+        glVertex2fv(p);
+      glEnd();
+      pt->cpt--;
+      ++ncp;
+
+      k = pt->nxt;
+    }
+  }
+  glPointSize(1.0);
+  glEndList();
+
+  if ( ncp )
+    fprintf(stdout,"   %d critical points identified (%d filtered)\n",ncp,ifilt);
+
+return(dlist);
+  
+  if ( ps ) {
+    fprintf(stdout," Building streamline(s)");
+    fflush(stdout);
+    t = clock();
+
+    if ( !sc->slist ) {
+      sc->stream = createStream(sc,mesh);
+      if ( !sc->stream )  return(dlist);
+    }
+    for (k=1; k<=ps; k++) {
+      if ( ddebug )  printf("  eigenv1 %f %f\n",sad[k].vp1[0],sad[k].vp1[1]);      
+      
+      listSaddleStream(sc,mesh,sad[k].k,sad[k].pt,sad[k].vp1,sad[k].r1);
+      sad[k].vp1[0] = -sad[k].vp1[0];
+      sad[k].vp1[1] = -sad[k].vp1[1];
+      listSaddleStream(sc,mesh,sad[k].k,sad[k].pt,sad[k].vp1,sad[k].r1);
+      
+      if ( ddebug )  printf("  eigenv2 %f %f\n",sad[k].vp2[0],sad[k].vp2[1]);
+      listSaddleStream(sc,mesh,sad[k].k,sad[k].pt,sad[k].vp2,sad[k].r2);
+      sad[k].vp2[0] = -sad[k].vp2[0];
+      sad[k].vp2[1] = -sad[k].vp2[1];
+      listSaddleStream(sc,mesh,sad[k].k,sad[k].pt,sad[k].vp2,sad[k].r2);
+    }
+    sc->isotyp |= S_STREAML;
+    fprintf(stdout,": %d lines",ps);
+    t = clock() - t;
+    fprintf(stdout," %6.2f sec.\n",t/(float)CLOCKS_PER_SEC);
+  }
+  
+  return(dlist);
+}
diff --git a/src/medit/cube.c b/src/medit/cube.c
new file mode 100644
index 0000000..ee0019a
--- /dev/null
+++ b/src/medit/cube.c
@@ -0,0 +1,128 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+/* display cube */
+void updateCube(pCube cube,pMesh mesh) {
+  pScene      sc;
+  pTransform  cubetr,view;
+  GLfloat     inv[16],axis[4],trans[4];
+  int         idw;
+
+  /* default */
+  if ( ddebug ) printf("updateCube\n");
+
+  /* retrieve context */
+  idw    = currentScene();
+  sc     = cv.scene[idw];
+  view   = sc->view;
+  cubetr = cube->cubetr;
+
+  /* compute cube transform */
+  if ( cube->active & C_EDIT ) {
+    invertMatrix(view->matrix,inv);
+    inv[3] = inv[7] = inv[11] = 0.0f;  inv[15] = 1.0;
+ 
+    /* rotation cumulative */
+    if ( cubetr->angle != 0.0 ) {
+      transformVector(trans,cubetr->axis,inv);
+      glPushMatrix();
+      glLoadIdentity();
+      glRotatef(cubetr->angle,trans[0],trans[1],trans[2]);
+      glMultMatrixf(cubetr->rot);
+      glGetFloatv(GL_MODELVIEW_MATRIX,cubetr->rot);
+      glPopMatrix();
+    }
+
+    /* translation cumulative */
+    axis[0] = cubetr->panx;
+    axis[1] = cubetr->pany;
+    axis[2] = 0.0;
+    axis[3] = 1.0;
+    transformVector(trans,axis,inv);
+
+    cubetr->tra[12] = trans[0];
+    cubetr->tra[13] = trans[1];
+    cubetr->tra[14] = trans[2];
+
+   /* final transformation */
+    glPushMatrix();
+    glLoadIdentity();
+    glMultMatrixf(cubetr->tra);
+    glMultMatrixf(cubetr->rot);
+    glGetFloatv(GL_MODELVIEW_MATRIX,cubetr->matrix);
+    glPopMatrix();
+  }
+  if ( !cubetr->manim ) {
+    cubetr->angle = 0.0;
+    cube->active ^= C_UPDATE;
+  }
+}
+
+
+void dumpCube(pScene sc,pMesh mesh,pCube cube) {
+  float  *tr,u[4];
+  double  v[4];
+  int     i;
+  FILE   *out;
+
+  tr = cube->cubetr->matrix;
+
+  out = fopen("tr.data","w");
+  for (i=0; i<4; i++)
+    fprintf(out,"%f %f %f %f\n",tr[i],tr[4+i],tr[8+i],tr[12+i]);
+  
+  u[0] = cube->cmi[0] - mesh->xtra;
+  u[1] = cube->cmi[1] - mesh->ytra;
+  u[2] = cube->cmi[2] - mesh->ztra;
+  u[3] = 1.0;
+  /*printf("avant %f %f %f %f\n",u[0],u[1],u[2],u[3]);*/
+  transformPoint2(v,u,tr);
+  fprintf(out,"\n%f %f %f   %f\n",
+          v[0]+mesh->xtra,v[1]+mesh->ytra,v[2]+mesh->ztra,v[3]);
+
+  u[0] = cube->cma[0] - mesh->xtra;
+  u[1] = cube->cma[1] - mesh->ytra;
+  u[2] = cube->cma[2] - mesh->ztra;
+  /*printf("avant %f %f %f %f\n",u[0],u[1],u[2],u[3]);*/
+  transformPoint2(v,u,tr);
+  fprintf(out,"%f %f %f   %f\n",
+          v[0]+mesh->xtra,v[1]+mesh->ytra,v[2]+mesh->ztra,v[3]);
+
+  fprintf(out,"\n%f %f %f\n",
+          cube->cubetr->tra[12],cube->cubetr->tra[13],cube->cubetr->tra[14]);
+
+  fprintf(out,"%f   %f %f %f\n",
+    cube->cubetr->angle,cube->cubetr->axis[0],cube->cubetr->axis[1],
+    cube->cubetr->axis[2]);
+  fclose(out);
+}
+
+
+void resetCube(pScene sc,pCube cube,pMesh mesh) {
+
+  resetTransform(cube->cubetr);
+
+  cube->active |= C_REDO;
+  cube->cmi[0]  = mesh->xmin;
+  cube->cmi[1]  = mesh->ymin;
+  cube->cmi[2]  = mesh->zmin;
+  cube->cma[0]  = mesh->xmax;
+  cube->cma[1]  = mesh->ymax;
+  cube->cma[2]  = mesh->zmax;
+}
+
+
+pCube createCube(pScene sc,pMesh mesh) {
+  pCube   cube;
+
+  cube = (pCube)M_calloc(1,sizeof(struct cube),"cube");
+  assert(cube);
+  
+  cube->cubetr = (pTransform)M_calloc(1,sizeof(struct transform),"cube");
+  if ( !cube->cubetr )  return(0);
+
+  resetCube(sc,cube,mesh);
+  return(cube);	
+}
diff --git a/src/medit/dlists.c b/src/medit/dlists.c
new file mode 100644
index 0000000..8fa7a0b
--- /dev/null
+++ b/src/medit/dlists.c
@@ -0,0 +1,658 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+/* list of element faces */
+static int ct[4][3] = { {0,1,2}, {0,3,1}, {1,3,2}, {0,2,3} };
+static int ch[6][4] = { {0,1,2,3}, {4,5,6,7}, {0,1,5,4}, 
+			{1,2,6,5}, {2,3,7,6}, {0,3,7,4} };
+
+static float redcol[4]   = {1.0, 0.0, 0.0, 1.0};
+static float greencol[4] = {0.0, 0.6, 0.0, 1.0}; 
+
+
+/* build list of triangles */
+GLuint listTria(pScene sc,pMesh mesh) {
+  pMaterial  pm;
+  pTriangle  pt;
+  pPoint     p0,p1,p2;
+  GLuint     dlist;
+  double     dd,ax,ay,az,bx,by,bz;
+  float      cx,cy,cz,n[3],pp0[3],pp1[3],pp2[3];
+  int        k,m,mm,is0,is1,is2,transp;
+
+  /* default */
+  if ( !mesh->nt ) return(0);
+  if ( ddebug ) printf("create display list / TRIA\n");
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  for (m=0; m<sc->par.nbmat; m++) {
+    mm = sc->matsort[m];
+    pm = &sc->material[mm];
+    k  = pm->depmat[LTria];
+    if ( !k || pm->flag )  continue;
+    transp = 0;
+
+    if ( !(sc->mode & S_MATERIAL) )
+      pm = &sc->material[DEFAULT_MAT];
+    transp = pm->amb[3] < 0.999 || pm->dif[3] < 0.999 || pm->spe[3] < 0.999;
+    if ( transp ) {
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+      glDepthMask(GL_FALSE);
+    }
+    glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,pm->amb);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,pm->spe);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,pm->emi);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,&pm->shininess);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,pm->dif);
+
+    glBegin(GL_TRIANGLES);
+    if ( sc->type & S_FLAT ) {
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+        p0 = &mesh->point[pt->v[0]];
+        p1 = &mesh->point[pt->v[1]];
+        p2 = &mesh->point[pt->v[2]];
+
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0 ) {
+          dd = 1.0 / sqrt(dd);
+          n[0] *= dd;
+          n[1] *= dd;
+          n[2] *= dd;
+        }
+
+        if ( sc->shrink < 1.0 ) {
+          cx = (p0->c[0] + p1->c[0] + p2->c[0]) / 3.0;
+          cy = (p0->c[1] + p1->c[1] + p2->c[1]) / 3.0;
+          cz = (p0->c[2] + p1->c[2] + p2->c[2]) / 3.0;
+          pp0[0] = sc->shrink*(p0->c[0]-cx)+cx;
+          pp0[1] = sc->shrink*(p0->c[1]-cy)+cy;
+          pp0[2] = sc->shrink*(p0->c[2]-cz)+cz;
+          pp1[0] = sc->shrink*(p1->c[0]-cx)+cx;
+          pp1[1] = sc->shrink*(p1->c[1]-cy)+cy;
+          pp1[2] = sc->shrink*(p1->c[2]-cz)+cz;
+          pp2[0] = sc->shrink*(p2->c[0]-cx)+cx;
+          pp2[1] = sc->shrink*(p2->c[1]-cy)+cy;
+          pp2[2] = sc->shrink*(p2->c[2]-cz)+cz;
+          glNormal3fv(n);  glVertex3fv(pp0);
+          glNormal3fv(n);  glVertex3fv(pp1);
+          glNormal3fv(n);  glVertex3fv(pp2);
+        }
+        else {
+          glNormal3fv(n);  glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+          glNormal3fv(n);  glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+          glNormal3fv(n);  glVertex3f(p2->c[0],p2->c[1],p2->c[2]);
+        }
+        k = pt->nxt;
+      }
+    }
+    else {
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+        p0 = &mesh->point[pt->v[0]];
+        p1 = &mesh->point[pt->v[1]];
+        p2 = &mesh->point[pt->v[2]];
+
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0 ) {
+          dd = 1.0 / sqrt(dd);
+          n[0] *= dd;
+          n[1] *= dd;
+          n[2] *= dd;
+        }
+
+        is0 = is1 = is2 = 0;
+        if ( mesh->extra->iv ) {
+          if ( pt->v[0] <= mesh->nvn )
+            is0 = mesh->extra->nv[pt->v[0]];
+          if ( pt->v[1] <= mesh->nvn )
+            is1 = mesh->extra->nv[pt->v[1]];
+          if ( pt->v[2] <= mesh->nvn )
+            is2 = mesh->extra->nv[pt->v[2]];
+        }
+        if ( !is0 && pt->v[0] <= mesh->extra->it )
+          is0 = mesh->extra->nt[3*(k-1)+1];
+        if ( !is1 && pt->v[1] <= mesh->extra->it )
+          is1 = mesh->extra->nt[3*(k-1)+2];
+        if ( !is2 && pt->v[2] <= mesh->extra->it )
+          is2 = mesh->extra->nt[3*(k-1)+3];
+
+        if ( sc->shrink < 1.0 ) {
+          cx = (p0->c[0] + p1->c[0] + p2->c[0]) / 3.;
+          cy = (p0->c[1] + p1->c[1] + p2->c[1]) / 3.;
+          cz = (p0->c[2] + p1->c[2] + p2->c[2]) / 3.;
+          pp0[0] = sc->shrink*(p0->c[0]-cx)+cx;
+          pp0[1] = sc->shrink*(p0->c[1]-cy)+cy;
+          pp0[2] = sc->shrink*(p0->c[2]-cz)+cz;
+          pp1[0] = sc->shrink*(p1->c[0]-cx)+cx;
+          pp1[1] = sc->shrink*(p1->c[1]-cy)+cy;
+          pp1[2] = sc->shrink*(p1->c[2]-cz)+cz;
+          pp2[0] = sc->shrink*(p2->c[0]-cx)+cx;
+          pp2[1] = sc->shrink*(p2->c[1]-cy)+cy;
+          pp2[2] = sc->shrink*(p2->c[2]-cz)+cz;
+          
+          if ( !is0 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is0-1)+1]);
+          glVertex3fv(pp0);
+          if ( !is1 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is1-1)+1]);
+          glVertex3fv(pp1);
+          if ( !is2 )
+            glNormal3fv(n);
+          else
+            glNormal3fv(&mesh->extra->n[3*(is2-1)+1]);
+          glVertex3fv(pp2);
+        }
+        else {
+          if ( !is0 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is0-1)+1]);
+          glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+          if ( !is1 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is1-1)+1]);
+          glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+          if ( !is2 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is2-1)+1]);
+          glVertex3f(p2->c[0],p2->c[1],p2->c[2]);
+        }
+        k = pt->nxt;
+      }
+    }
+    glEnd();
+    if ( transp ) {
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+    }
+  }
+
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list of quadrilaterals */
+GLuint listQuad(pScene sc,pMesh mesh) {
+  pMaterial  pm;
+  pQuad      pq;
+  pPoint     p0,p1,p2,p3;
+  GLuint     dlist = 0;
+  double     ax,ay,az,bx,by,bz,dd;
+  float      cx,cy,cz,n[3],pp0[3],pp1[3],pp2[3],pp3[3];
+  int        k,m,mm,is0,is1,is2,is3,transp;
+
+  /* default */
+  if ( !mesh->nq ) return(0);
+  if ( ddebug ) printf("create display list / QUADS\n");
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  for (m=0; m<sc->par.nbmat; m++) {
+    mm = sc->matsort[m];
+    pm = &sc->material[mm];
+    k  = pm->depmat[LQuad];
+    if ( !k || pm->flag )  continue;
+    transp = 0;
+
+    if ( !(sc->mode & S_MATERIAL) )
+      pm = &sc->material[DEFAULT_MAT];
+    transp = pm->amb[3] < 0.999 || pm->dif[3] < 0.999 || pm->spe[3] < 0.999;
+    if ( transp ) {
+      glEnable(GL_BLEND);
+      glDepthMask(GL_FALSE);
+      glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+    }
+    glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,pm->amb);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,pm->spe);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,pm->emi);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,&pm->shininess);      
+    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,pm->dif);
+
+    glBegin(GL_QUADS);
+    if ( sc->type & S_FLAT ) {
+      while ( k != 0 ) {
+        pq = &mesh->quad[k];
+        if ( pq->v[0] == 0 ) {
+          k = pq->nxt;
+          continue;
+        }
+        p0 = &mesh->point[pq->v[0]];
+        p1 = &mesh->point[pq->v[1]];
+        p2 = &mesh->point[pq->v[2]];
+        p3 = &mesh->point[pq->v[3]];
+
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0 ) {
+          dd = 1.0 / sqrt(dd);
+          n[0] *= dd;
+          n[1] *= dd;
+          n[2] *= dd;
+        }
+
+        if ( sc->shrink < 1.0 ) {
+          cx = (p0->c[0] + p1->c[0] + p2->c[0] + p3->c[0]) / 4.;
+          cy = (p0->c[1] + p1->c[1] + p2->c[1] + p3->c[1]) / 4.;
+          cz = (p0->c[2] + p1->c[2] + p2->c[2] + p3->c[2]) / 4.;
+          pp0[0] = sc->shrink*(p0->c[0]-cx)+cx;
+          pp0[1] = sc->shrink*(p0->c[1]-cy)+cy;
+          pp0[2] = sc->shrink*(p0->c[2]-cz)+cz;
+          pp1[0] = sc->shrink*(p1->c[0]-cx)+cx;
+          pp1[1] = sc->shrink*(p1->c[1]-cy)+cy;
+          pp1[2] = sc->shrink*(p1->c[2]-cz)+cz;
+          pp2[0] = sc->shrink*(p2->c[0]-cx)+cx;
+          pp2[1] = sc->shrink*(p2->c[1]-cy)+cy;
+          pp2[2] = sc->shrink*(p2->c[2]-cz)+cz;
+          pp3[0] = sc->shrink*(p3->c[0]-cx)+cx;
+          pp3[1] = sc->shrink*(p3->c[1]-cy)+cy;
+          pp3[2] = sc->shrink*(p3->c[2]-cz)+cz;
+          glNormal3fv(n);  glVertex3fv(pp0);
+          glNormal3fv(n);  glVertex3fv(pp1);
+          glNormal3fv(n);  glVertex3fv(pp2);
+          glNormal3fv(n);  glVertex3fv(pp3);
+        }
+        else {
+          glNormal3fv(n);  glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+          glNormal3fv(n);  glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+          glNormal3fv(n);  glVertex3f(p2->c[0],p2->c[1],p2->c[2]);
+          glNormal3fv(n);  glVertex3f(p3->c[0],p3->c[1],p3->c[2]);
+        }
+        k = pq->nxt;
+      }
+    }
+    else {
+      while ( k != 0 ) {
+        pq = &mesh->quad[k];
+        if ( !pq->v[0] ) {
+          k = pq->nxt;
+          continue;
+        }
+        p0 = &mesh->point[pq->v[0]];
+        p1 = &mesh->point[pq->v[1]];
+        p2 = &mesh->point[pq->v[2]];
+        p3 = &mesh->point[pq->v[3]];
+
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0 ) {
+          dd = 1.0 / sqrt(dd);
+          n[0] *= dd;
+          n[1] *= dd;
+          n[2] *= dd;
+        }
+        is0 = is1 = is2 = is3 = 0;
+        if ( mesh->extra->iv ) {
+          if ( pq->v[0] <= mesh->nvn )
+            is0 = mesh->extra->nv[pq->v[0]];
+          if ( pq->v[1] <= mesh->nvn )
+            is1 = mesh->extra->nv[pq->v[1]];
+          if ( pq->v[2] <= mesh->nvn )
+            is2 = mesh->extra->nv[pq->v[2]];
+          if ( pq->v[3] <= mesh->nvn )
+            is3 = mesh->extra->nv[pq->v[3]];
+        }
+        if ( !is0 && pq->v[0] <= mesh->extra->iq )
+          is0 = mesh->extra->nq[4*(k-1)+1];
+        if ( !is1 && pq->v[1] <= mesh->extra->iq )
+          is1 = mesh->extra->nq[4*(k-1)+2];
+        if ( !is2 && pq->v[2] <= mesh->extra->iq )
+          is2 = mesh->extra->nq[4*(k-1)+3];
+        if ( !is3 && pq->v[3] <= mesh->extra->iq )
+          is3 = mesh->extra->nq[4*(k-1)+4];
+
+        if ( sc->shrink < 1.0 ) {
+          cx = (p0->c[0] + p1->c[0] + p2->c[0] + p3->c[0]) / 4.;
+          cy = (p0->c[1] + p1->c[1] + p2->c[1] + p3->c[1]) / 4.;
+          cz = (p0->c[2] + p1->c[2] + p2->c[2] + p3->c[2]) / 4.;
+          pp0[0] = sc->shrink*(p0->c[0]-cx)+cx;
+          pp0[1] = sc->shrink*(p0->c[1]-cy)+cy;
+          pp0[2] = sc->shrink*(p0->c[2]-cz)+cz;
+          pp1[0] = sc->shrink*(p1->c[0]-cx)+cx;
+          pp1[1] = sc->shrink*(p1->c[1]-cy)+cy;
+          pp1[2] = sc->shrink*(p1->c[2]-cz)+cz;
+          pp2[0] = sc->shrink*(p2->c[0]-cx)+cx;
+          pp2[1] = sc->shrink*(p2->c[1]-cy)+cy;
+          pp2[2] = sc->shrink*(p2->c[2]-cz)+cz;
+          pp3[0] = sc->shrink*(p3->c[0]-cx)+cx;
+          pp3[1] = sc->shrink*(p3->c[1]-cy)+cy;
+          pp3[2] = sc->shrink*(p3->c[2]-cz)+cz;
+
+          if ( !is0 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is0-1)+1]);
+          glVertex3fv(pp0);
+          if ( !is1 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is1-1)+1]);
+          glVertex3fv(pp1);
+          if ( !is2 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is2-1)+1]);
+          glVertex3fv(pp2);
+          if ( !is3 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is3-1)+1]);
+          glVertex3fv(pp3);
+        }
+        else {
+
+          if ( !is0 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is0-1)+1]);
+          glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+          if ( !is1 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is1-1)+1]);
+          glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+          if ( !is2 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is2-1)+1]);
+          glVertex3f(p2->c[0],p2->c[1],p2->c[2]);
+          if ( !is3 )
+            glNormal3fv(n);  
+          else
+            glNormal3fv(&mesh->extra->n[3*(is3-1)+1]);
+          glVertex3f(p3->c[0],p3->c[1],p3->c[2]);
+        }
+        k = pq->nxt;
+      }
+    }
+    glEnd();
+    if ( transp ) {
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+    }
+  }
+
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list of tetrahedra */
+GLuint listTetra(pScene sc,pMesh mesh,ubyte clip) {
+  pMaterial  pm;
+  pTetra     pt;
+  pPoint     p0,p1,p2;
+  GLuint     dlist;
+  double     ax,ay,az,bx,by,bz,d;
+  float      n[3],shrink,cx,cy,cz;
+  int        k,l,m,mm;
+
+  if ( !mesh->ntet )  return(0);
+  if ( ddebug ) printf("create 3d display list w. materials\n");
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+  shrink = min(sc->shrink,0.995);
+
+  /* scan tetra */
+  for (m=0; m<sc->par.nbmat; m++) {
+    mm = sc->matsort[m];
+    pm = &sc->material[mm];
+    k  = pm->depmat[LTets];
+    if ( !k || pm->flag )  continue;
+
+    if ( sc->mode & S_MATERIAL ) {
+      if ( pm->dif[3] < 0.999 ) {
+        glDepthMask(GL_FALSE);
+        glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+        glEnable(GL_BLEND);
+      }
+      glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,pm->dif);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,pm->amb);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,pm->spe);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,pm->emi);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,&pm->shininess);
+    }
+    else
+      glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,redcol);
+    
+    /* display triangular faces */
+    glBegin(GL_TRIANGLES);
+    while ( k != 0 ) {
+      pt = &mesh->tetra[k];
+      if ( !pt->v[0] || (clip && !pt->clip) ) {
+        k = pt->nxt;
+        continue;
+      }
+      /* build 4 faces */
+      cx = cy = cz = 0.;
+      for (l=0; l<4; l++) {
+        p0  = &mesh->point[pt->v[l]];
+        cx += p0->c[0];
+        cy += p0->c[1];
+        cz += p0->c[2];
+      }
+      cx *= 0.25; 
+      cy *= 0.25;
+      cz *= 0.25;
+
+      for (l=0; l<4; l++) {
+	p0 = &mesh->point[pt->v[ct[l][0]]];
+	p1 = &mesh->point[pt->v[ct[l][1]]];
+	p2 = &mesh->point[pt->v[ct[l][2]]];
+
+	/* compute face normal */
+	ax = p1->c[0] - p0->c[0]; ay = p1->c[1] - p0->c[1]; az = p1->c[2] - p0->c[2];
+	bx = p2->c[0] - p0->c[0]; by = p2->c[1] - p0->c[1]; bz = p2->c[2] - p0->c[2];
+	n[0] = ay*bz - az*by;
+	n[1] = az*bx - ax*bz;
+	n[2] = ax*by - ay*bx;
+	d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+	if ( d > 0.0f ) {
+	  d = 1.0f / sqrt(d);
+	  n[0] *= d;  
+          n[1] *= d;  
+          n[2] *= d;
+	}
+	glNormal3fv(n);
+	glVertex3f(shrink*(p0->c[0]-cx)+cx,
+                   shrink*(p0->c[1]-cy)+cy,
+                   shrink*(p0->c[2]-cz)+cz);
+	glNormal3fv(n);
+	glVertex3f(shrink*(p1->c[0]-cx)+cx,
+                   shrink*(p1->c[1]-cy)+cy,
+                   shrink*(p1->c[2]-cz)+cz);
+	glNormal3fv(n);
+	glVertex3f(shrink*(p2->c[0]-cx)+cx,
+                   shrink*(p2->c[1]-cy)+cy,
+                   shrink*(p2->c[2]-cz)+cz);
+      }
+      k = pt->nxt;
+    }
+    glEnd();
+    if ( sc->mode & S_MATERIAL && pm->dif[3] < 0.999 ) {
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+    }
+  }
+
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list of hexahedra */
+GLuint listHexa(pScene sc,pMesh mesh,ubyte clip) {
+  pMaterial  pm;
+  pHexa      ph;
+  pPoint     p0,p1,p2,p3;
+  GLuint     dlist;
+  double     ax,ay,az,bx,by,bz,d;
+  float      n[3],cx,cy,cz,shrink;
+  int        k,l,m,mm;
+
+  if ( !mesh->nhex )  return(0);
+  if ( ddebug ) printf("create 3d display list w. materials\n");
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+  shrink = min(sc->shrink,0.995);
+
+  /* scan hexa */
+  for (m=0; m<sc->par.nbmat; m++) {
+    mm = sc->matsort[m];
+    pm = &sc->material[mm];
+    k  = pm->depmat[LHexa];
+    if ( !k || pm->flag )  continue;
+
+    if ( sc->mode & S_MATERIAL ) {
+      if ( pm->dif[3] < 0.999) {
+        glDepthMask(GL_FALSE);
+        glBlendFunc(GL_DST_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+        glEnable(GL_BLEND);
+      }
+      glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,pm->dif);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,pm->amb);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,pm->spe);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,pm->emi);
+      glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,&pm->shininess);
+    }
+    else
+      glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,greencol);
+
+    /* display quadrilateral faces */
+    glBegin(GL_QUADS);
+    while ( k != 0 ) {
+      ph = &mesh->hexa[k];
+      if ( !ph->v[0] || (clip && !ph->clip) ) {
+        k = ph->nxt;
+        continue;
+      }
+
+      /* build 6 faces */
+      cx = cy = cz = 0.;
+      for (l=0; l<8; l++) {
+        p0  = &mesh->point[ph->v[l]];
+        cx += p0->c[0];
+        cy += p0->c[1];
+        cz += p0->c[2];
+      }
+      cx /= 8.;
+      cy /= 8.;
+      cz /= 8.;
+      for (l=0; l<6; l++) {
+        p0 = &mesh->point[ph->v[ch[l][0]]];
+        p1 = &mesh->point[ph->v[ch[l][1]]];
+        p2 = &mesh->point[ph->v[ch[l][2]]];
+        p3 = &mesh->point[ph->v[ch[l][3]]];
+
+        /* compute face normal */
+        ax = p1->c[0] - p0->c[0]; ay = p1->c[1] - p0->c[1]; az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0]; by = p2->c[1] - p0->c[1]; bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( d > 0.0f ) {
+          d = 1.0f / sqrt(d);
+          n[0] *= d;
+          n[1] *= d;
+          n[2] *= d;
+        }
+        glNormal3fv(n);
+        glVertex3f(shrink*(p0->c[0]-cx)+cx,
+                   shrink*(p0->c[1]-cy)+cy,
+                   shrink*(p0->c[2]-cz)+cz);
+        glNormal3fv(n);
+        glVertex3f(shrink*(p1->c[0]-cx)+cx,
+                   shrink*(p1->c[1]-cy)+cy,
+                   shrink*(p1->c[2]-cz)+cz);
+        glNormal3fv(n);
+        glVertex3f(shrink*(p2->c[0]-cx)+cx,
+                   shrink*(p2->c[1]-cy)+cy,
+                   shrink*(p2->c[2]-cz)+cz);
+        glNormal3fv(n);
+        glVertex3f(shrink*(p3->c[0]-cx)+cx,
+                   shrink*(p3->c[1]-cy)+cy,
+                   shrink*(p3->c[2]-cz)+cz);
+      }
+      k = ph->nxt;
+    }
+    glEnd();
+    if ( sc->mode & S_MATERIAL && pm->dif[3] < 0.999 ) {
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+    }
+  }
+
+  glEndList();
+  return(dlist);
+}
diff --git a/src/medit/eigenv.h b/src/medit/eigenv.h
new file mode 100644
index 0000000..996cbe8
--- /dev/null
+++ b/src/medit/eigenv.h
@@ -0,0 +1,2 @@
+int eigenv(int symmat,double *mat,double lambda[3],double v[3][3]);
+int eigen2(double *mm,double *lambda,double vp[2][2]);
diff --git a/src/medit/ellipse.c b/src/medit/ellipse.c
new file mode 100644
index 0000000..20c8957
--- /dev/null
+++ b/src/medit/ellipse.c
@@ -0,0 +1,351 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+#include "eigenv.h"
+
+#ifndef M_PI2
+#define M_PI2  (2.0*M_PI)
+#endif
+
+extern int refmat;
+extern int eigen2(double m[3],double lambda[2],double vp[2][2]);
+
+static GLfloat IdMatrix[16] = {
+   1.0, 0.0, 0.0, 0.0,
+   0.0, 1.0, 0.0, 0.0,
+   0.0, 0.0, 1.0, 0.0,
+   0.0, 0.0, 0.0, 1.0
+};
+
+void drawEllipsoid(pScene sc,pMesh mesh,int typel,int k) {
+  pMaterial    pm;
+  pSolution    ps;
+  pTriangle    pt;
+  pTetra       pt1;
+  pPoint       p0;
+  GLfloat      mat[16],cx,cy,cz;
+  double       m[6],lambda[3],v[3][3];
+  int          i,j,l,iord;
+
+  /* compute average size */
+  if ( mesh->nfield != 6 || !mesh->nbb )  return;
+
+  /* draw average ellipse at element */
+  if ( typel == LPoint ) {
+    p0 = &mesh->point[k];
+    /*pm = &sc->material[refmat];*/
+    pm = &sc->material[p0->ref];
+    ps = &mesh->sol[k];
+    for (j=0; j<6; j++) m[j] = ps->m[j];
+
+    iord = eigenv(1,m,lambda,v);
+    if ( !iord )  return;
+
+    if ( mesh->ne ) {    
+      fprintf(stdout,"  Eigenvectors :\n   vp1 : %f  %f  %f\n",
+              v[0][0],v[0][1],v[0][2]);
+      fprintf(stdout,"   vp2 : %f  %f  %f\n",v[1][0],v[1][1],v[1][2]);
+      fprintf(stdout,"   vp3 : %f  %f  %f\n",v[2][0],v[2][1],v[2][2]);
+      fprintf(stdout,"  Eigenvalues  : %f  %f  %f    %d\n",
+              lambda[0],lambda[1],lambda[2],iord);
+      if ( lambda[0] <= 0.0 || lambda[1] <= 0.0 || lambda[2] <= 0.0)
+        return;
+      fprintf(stdout,"  Sizes        : %f  %f  %f\n",
+              1.0/sqrt(lambda[0]),1.0/sqrt(lambda[1]),1.0/sqrt(lambda[2]));
+    }
+    else if ( lambda[0] <= 0.0 || lambda[1] <= 0.0 || lambda[2] <= 0.0)
+      return;
+
+    lambda[0] = max(EPS,0.5/sqrt(lambda[0]));
+    lambda[1] = max(EPS,0.5/sqrt(lambda[1]));
+    lambda[2] = max(EPS,0.5/sqrt(lambda[2]));
+    memcpy(mat,IdMatrix,16*sizeof(GLfloat));
+    for (j=0; j<3; j++) 
+      for (l=0; l<3; l++)
+        mat[j*4+l] = v[j][l];
+
+    glDisable(GL_LIGHTING);
+    glPushMatrix();
+    glColor4fv(pm->dif);
+    glTranslatef(p0->c[0],p0->c[1],p0->c[2]);
+    glMultMatrixf(mat);
+    glScalef(lambda[0],lambda[1],lambda[2]);
+    glutWireSphere(1.,30,30);
+    glPopMatrix();
+    glEnable(GL_LIGHTING);
+  }
+
+  else if ( typel == LTria ) {
+    pt = &mesh->tria[k];
+    if ( mesh->nbb == mesh->np )
+      pm = &sc->material[refmat];
+    else if ( mesh->nbb == mesh->nt )
+	  pm = &sc->material[k];
+	else
+	  return;
+    glColor4fv(pm->dif);
+    for (j=0; j<6; j++) m[j] = 0.;
+    cx = cy = cz = 0.0;
+    for (i=0; i<3; i++) {
+      ps = &mesh->sol[pt->v[i]];
+      p0 = &mesh->point[pt->v[i]];
+      cx += p0->c[0];
+      cy += p0->c[1];
+      cz += p0->c[2];
+      for (j=0; j<6; j++)
+        m[j] += ps->m[j];
+    }
+    cx /= 3.;  cy /= 3.;  cz /= 3.;
+    for (j=0; j<6; j++)  m[j] /= 6.;
+
+    if ( !eigenv(1,m,lambda,v) )  return;
+    lambda[0] = max(EPS,0.5/sqrt(lambda[0]));
+    lambda[1] = max(EPS,0.5/sqrt(lambda[1]));
+    lambda[2] = max(EPS,0.5/sqrt(lambda[2]));
+
+    memcpy(mat,IdMatrix,16*sizeof(GLfloat));
+    for (j=0; j<3; j++) 
+      for (l=0; l<3; l++)
+        mat[j*4+l] = v[j][l];
+
+    glDisable(GL_LIGHTING);
+    glPushMatrix();
+    glColor4fv(pm->dif);
+    glTranslatef(cx,cy,cz);
+    glMultMatrixf(mat);
+    glScalef(lambda[0],lambda[1],lambda[2]);
+    glutWireSphere(1.,30,30);
+    glPopMatrix();
+    glEnable(GL_LIGHTING);
+  }
+
+  else if ( typel == LTets ) {
+    pt1 = &mesh->tetra[k];
+    pm = &sc->material[refmat];
+    glColor4fv(pm->dif);
+    for (j=0; j<6; j++)  m[j] = 0.;
+    cx = cy = cz = 0.0;
+    for (i=0; i<4; i++) {
+      if ( mesh->nbb == mesh->np )
+        ps = &mesh->sol[pt1->v[i]];
+	  else if ( mesh->nbb == mesh->ntet )
+        ps = &mesh->sol[k];
+      else
+		return;
+      p0 = &mesh->point[pt1->v[i]];
+      cx += p0->c[0];
+      cy += p0->c[1];
+      cz += p0->c[2];
+      for (j=0; j<6; j++)
+        m[j] += ps->m[j];
+    }
+    cx /= 4.;  cy /= 4.;  cz /= 4.;
+    for (j=0; j<6; j++)  m[j] /= 6.;
+
+    if ( !eigenv(1,m,lambda,v) )  return;
+    lambda[0] = max(EPS,0.5/sqrt(lambda[0]));
+    lambda[1] = max(EPS,0.5/sqrt(lambda[1]));
+    lambda[2] = max(EPS,0.5/sqrt(lambda[2]));
+
+    memcpy(mat,IdMatrix,16*sizeof(GLfloat));
+    for (j=0; j<3; j++) 
+      for (l=0; l<3; l++)
+        mat[j*4+l] = v[j][l];
+    glDisable(GL_LIGHTING);
+    glPushMatrix();
+    glColor4fv(pm->dif);
+    glTranslatef(cx,cy,cz);
+    glMultMatrixf(mat);
+    glScalef(lambda[0],lambda[1],lambda[2]);
+    glutWireSphere(1.,30,30);
+    glPopMatrix();
+    glEnable(GL_LIGHTING);
+	
+  }
+  else return;
+}
+
+
+void glCircle(float radius) {
+  float   ang,ux,uy;
+
+  ux = 0.0f;
+  uy = radius;
+
+  glBegin(GL_LINE_STRIP);
+  for (ang=0.0f; ang<=2*M_PI+0.2; ang+=0.2) {
+    ux = radius*(float)sin((double)ang);
+    uy = radius*(float)cos((double)ang);
+    glVertex2f(ux,uy);
+  }
+  glEnd();
+}
+
+
+void drawEllipse(pScene sc,pMesh mesh,int typel,int k) {
+  pMaterial    pm;
+  pSolution    ps;
+  pPoint       p0;
+  double       m[3],vp[2][2],lambda[2],dd1,dd2;
+  float        theta;
+
+  /* draw ellipse at vertex */
+  if ( typel == LPoint ) {
+    ps = &mesh->sol[k];
+    p0 = &mesh->point[k];
+    pm = &sc->material[refmat];
+
+    m[0] = ps->m[0];
+    m[1] = ps->m[1];
+    m[2] = ps->m[2];
+    if ( !eigen2(m,lambda,vp) ) return;
+
+    /* consider eigenvalues as sizes */
+    dd1 = 1.0 / sqrt(fabs(lambda[0]));
+    dd2 = 1.0 / sqrt(fabs(lambda[1]));
+
+    glDisable(GL_LIGHTING);
+    glPushMatrix();
+    glLineWidth(1.0);
+    glBegin(GL_LINES);
+      glColor3fv(pm->dif);
+      glVertex3f(p0->c[0],p0->c[1],0.0);
+      glColor3fv(pm->dif);
+      glVertex3f(p0->c[0]+dd1*vp[0][0],p0->c[1]+dd1*vp[0][1],0.0);
+
+      glColor3fv(pm->dif);
+      glVertex3f(p0->c[0],p0->c[1],0.0);
+      glColor3fv(pm->dif);
+      glVertex3f(p0->c[0]+dd2*vp[1][0],p0->c[1]+dd2*vp[1][1],0.0);
+    glEnd();
+
+    theta = atan2(vp[0][1],vp[0][0])*RTOD;
+    glTranslatef(p0->c[0],p0->c[1],0.0);
+    glRotatef(theta,0.0,0.0,1.0);
+    glScaled(dd1,dd2,0.0);
+
+    glColor3fv(pm->dif);
+    glCircle(1.0);
+    glLineWidth(1.0);
+    glPopMatrix();
+    glEnable(GL_LIGHTING);
+
+    /* print out info */
+    fprintf(stdout,"  Eigenvectors :\n");
+    fprintf(stdout,"   vp1 : %f  %f\n",vp[0][0],vp[0][1]);
+    fprintf(stdout,"   vp2 : %f  %f\n",vp[1][0],vp[1][1]);
+    fprintf(stdout,"  Eigenvalues  : %f  %f\n",lambda[0],lambda[1]);
+    fprintf(stdout,"  Sizes        : %f  %f\n",dd1,dd2);
+  }
+}
+
+
+GLuint drawAllEllipse(pScene sc,pMesh mesh) {
+  GLuint       dlist;
+  pSolution    ps;
+  pMaterial    pm;
+  pTriangle    pt;
+  pPoint       p0;
+  double       m[3],vp[2][2],lambda[2],dd1,dd2;
+  float        theta,cx,cy;
+  int          k,i,ref;
+
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* draw ellipse at vertex */
+  glDisable(GL_LIGHTING);
+  glLineWidth(1.0);
+  
+  if ( mesh->typage == 1 ) {
+    for (k=1; k<=mesh->ne; k++) {
+      ps = &mesh->sol[k];
+      pt = &mesh->tria[k];
+      if ( !pt->v[0] )  continue;
+
+      ref = matRef(sc,pt->ref);
+      pm  = &sc->material[ref];
+      if ( pm->flag )   continue;
+
+      cx = cy = 0.0;
+      for (i=0; i<3; i++) {
+        p0 = &mesh->point[pt->v[i]];
+        cx += p0->c[0];
+        cy += p0->c[1];
+      }
+      cx *= 1. / 3.;
+      cy *= 1. / 3.;
+
+      m[0] = ps->m[0];
+      m[1] = ps->m[1];
+      m[2] = ps->m[2];
+      if ( !eigen2(m,lambda,vp) ) return (0) ;
+
+      /* consider eigenvalues as sizes */
+      dd1 = 1.0 / sqrt(fabs(lambda[0]));
+      dd2 = 1.0 / sqrt(fabs(lambda[1]));
+
+      glPushMatrix();
+      theta = atan2(vp[0][1],vp[0][0])*RTOD;
+      glTranslatef(cx,cy,0.0);
+      glRotatef(theta,0.0,0.0,1.0);
+      glScaled(dd1,dd2,0.0);
+      glColor3fv(pm->dif);
+      glCircle(1.0);
+      glPopMatrix();
+    }
+  }
+  else {
+    for (k=1; k<=mesh->np; k++) {
+      ps = &mesh->sol[k];
+      p0 = &mesh->point[k];
+
+      ref = matRef(sc,p0->ref);
+      pm  = &sc->material[ref];
+      if ( pm->flag )   continue;
+
+      m[0] = ps->m[0];
+      m[1] = ps->m[1];
+      m[2] = ps->m[2];
+      if ( !eigen2(m,lambda,vp) ) return (0) ;
+
+      /* consider eigenvalues as sizes */
+      dd1 = 1.0 / sqrt(fabs(lambda[0]));
+      dd2 = 1.0 / sqrt(fabs(lambda[1]));
+
+      glPushMatrix();
+      theta = atan2(vp[0][1],vp[0][0])*RTOD;
+      glTranslatef(p0->c[0],p0->c[1],0.0);
+      glRotatef(theta,0.0,0.0,1.0);
+      glScaled(dd1,dd2,0.0);
+      glColor3fv(pm->dif);
+      glCircle(1.0);
+      glPopMatrix();
+    }
+  }
+  glEnable(GL_LIGHTING);
+
+  glEndList();
+  return(dlist);
+}
+
+
+void circumSphere(pScene sc,pMesh mesh,int typel,int k) {
+  pMaterial    pm;
+  double       c[3],rad;
+
+  cenrad(mesh,k,c,&rad);
+  rad = sqrt(rad);
+  pm = &sc->material[refmat];
+
+  glDisable(GL_LIGHTING);
+  glPushMatrix();
+  glColor4fv(pm->dif);
+  glTranslated(c[0],c[1],c[2]);
+  glScalef(rad,rad,rad);
+  glutWireSphere(1.,30,30);
+  glPopMatrix();
+  glEnable(GL_LIGHTING);
+}
+
diff --git a/src/medit/extern.h b/src/medit/extern.h
new file mode 100644
index 0000000..cc4793b
--- /dev/null
+++ b/src/medit/extern.h
@@ -0,0 +1,6 @@
+#ifndef __MEDIT
+  extern Canvas   cv;
+  extern ubyte    ddebug,quiet,imprim,option,morphing,animate,saveimg,imgtype;
+  extern int      animdep,animfin;
+  extern char    *imgtyp[];
+#endif
diff --git a/src/medit/geometry.c b/src/medit/geometry.c
new file mode 100644
index 0000000..b8a4d42
--- /dev/null
+++ b/src/medit/geometry.c
@@ -0,0 +1,115 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+GLuint geomList(pScene sc,pMesh mesh) {
+  GLuint     list = 0;
+  pMaterial  pm;
+  pEdge      pr;
+  pPoint     ppt,pp0,pp1;
+  double     dd;
+  float      n[3];
+  int        k,it = 0,nm;
+  static float green[4] = {0.0, 1.0, 0.0, 1.0};
+  static float rouge[4] = {1.0, 0.0, 0.0, 1.0};
+  static float jaune[4] = {1.0, 1.0, 0.0, 1.0};
+
+  /* default */
+  if ( mesh->na+mesh->nc+mesh->np == 0 )  return(0);
+
+  /* create display list */
+  list = glGenLists(1);
+  if ( !list )  return(0);
+  glNewList(list,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* draw corners, ridges and required items */
+  if ( ddebug ) printf("construct point list\n");
+  if ( mesh->ne ) {
+    /*glPointSize(3);*/
+    glPointSize(sc->par.pointsize);  /* pour Herve LeDret */
+    glBegin(GL_POINTS);
+    for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+      if ( ppt->tag & M_UNUSED && !ppt->ref )  continue;
+      if ( ppt->tag == M_CORNER )
+        glColor3fv(rouge);
+      else if ( ppt->tag == M_REQUIRED )
+        glColor3fv(green);
+      else continue;
+      it++;
+      if ( sc->par.linc == 1 )  glColor3fv(sc->par.edge);
+      glVertex3f(ppt->c[0],ppt->c[1],ppt->c[2]);
+    }
+    glEnd();
+    glPointSize(1);
+  }
+  else {
+    pm = &sc->material[DEFAULT_MAT];
+    glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,pm->dif);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,pm->amb);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,pm->spe);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,pm->emi);
+    glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,&pm->shininess);
+    glBegin(GL_POINTS);
+    for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+      n[0] = ppt->c[0] - sc->cx;
+      n[1] = ppt->c[1] - sc->cy;
+      n[2] = ppt->c[2] - sc->cz;
+      dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+      if ( dd > 0.0f ) {
+        dd = 1.0 / sqrt(dd);
+        n[0] *= dd;
+        n[1] *= dd;
+        n[2] *= dd;
+      }
+      glNormal3fv(n);
+      glVertex3f(ppt->c[0],ppt->c[1],ppt->c[2]);
+    }
+    glEnd(); 
+    it = mesh->np;
+  }
+
+  /* draw edges */
+  if ( ddebug )  printf("construct edge list\n");
+  glLineWidth(sc->par.linewidth);
+  glBegin(GL_LINES);
+  for (k=1; k<=mesh->na; k++) {
+    pr = &mesh->edge[k];
+    if ( pr->v[0] > mesh->np || pr->v[1] > mesh->np )
+      continue;
+
+    if ( pr->tag & M_RIDGE ) {
+      if ( pr->tag & M_TAG )
+	    glColor3fv(jaune);  /* ridge + ref en jaune */
+      else
+	    glColor3fv(rouge);  /* ridges en rouge */
+    }
+    else if ( !pr->ref ) {
+      glColor3fv(sc->par.edge);
+    }
+    else {
+      nm = matRef(sc,pr->ref);
+      pm = &sc->material[nm];
+      glColor3fv(pm->dif);
+    }
+    if ( sc->par.linc == 1 )  glColor3fv(sc->par.edge);
+    pp0 = &mesh->point[pr->v[0]];
+    pp1 = &mesh->point[pr->v[1]];
+    glVertex3f(pp0->c[0],pp0->c[1],pp0->c[2]);
+    glVertex3f(pp1->c[0],pp1->c[1],pp1->c[2]);
+    it++;
+  }
+  glEnd();
+  glLineWidth(1.0);
+  glEndList();
+
+  if ( it == 0 ) {
+    glDeleteLists(list,1);
+    return(0);
+  }
+  else
+    return(list);
+}
+
diff --git a/src/medit/gisfil.c b/src/medit/gisfil.c
new file mode 100644
index 0000000..f48de08
--- /dev/null
+++ b/src/medit/gisfil.c
@@ -0,0 +1,193 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define FLOAT_MAX  1.e20
+
+int loadGIS(pMesh mesh) {
+  pQuad      pq;
+  pPoint     ppt;
+  pSolution  ps;
+  FILE      *fp;
+  double     xxm,yym,ggx,ggy,hhz;
+  float     *te,cx,cy,cz,gu,hu,xmi,ymi;
+  int        i,j,k,sx,sy,ni,ret,bitsize,pos,ref;
+  char      *ptr,c,buf[256],data[256];
+  ubyte      ityp;
+  
+
+  /* default */
+  strcpy(data,mesh->name);
+  ptr = strstr(data,".gis");
+  if ( !ptr )  strcat(data,".gis");
+  fp = fopen(data,"rb");
+  if ( !fp )  return(0);
+  fprintf(stdout,"  Reading %s\n",data);
+
+  if ( !fgets(buf,sizeof(buf),fp) ) {
+    fprintf(stderr,"  ## Invalid header.\n");
+    return(0);
+  }
+
+  /* remove leading spaces */
+  pos = 0;
+  while ( (buf[0] == ' ') && (buf[0] != 0x0d) && (buf[0] != 0x0a) )
+    memmove(&buf[0],&buf[1],strlen(buf));
+
+  /* check header file */
+  if ( buf[0] != 'G' ) {
+    fprintf(stderr,"  ## Invalid format.\n");
+    return(0);
+  }
+  if ( buf[1] == '1' )       ityp = 1;
+  else if ( buf[1] == '2' )  ityp = 2;
+  else {
+    fprintf(stderr,"  ## Invalid format ('G?' expected).\n");
+    return(0);
+  }
+
+  /* check and strip comments */
+  do {
+    ret = fscanf(fp,"%s",buf);
+    if ( ret == EOF ) break;
+    if ( buf[0] == '#' )
+      do
+        c = getc(fp);
+      while ( c != '\n' );
+    else break;
+  }
+  while (1);
+
+  /* header */
+  ret  = sscanf(buf,"%d",&sx);
+  ret += fscanf(fp,"%d",&sy);
+  ret += fscanf(fp,"%f %f %f",&cx,&cy,&cz);
+  ret += fscanf(fp,"%f",&gu);
+  ret += fscanf(fp,"%f",&hu);
+  ret += fscanf(fp,"%f %f",&xmi,&ymi);
+  if ( ret != 9 ) {
+    fprintf(stderr,"  ## Error loading terrain.\n");
+    free(mesh);
+    return(0);
+  }
+
+  bitsize = mesh->np*sizeof(float);
+  if ( ddebug ) {
+    fprintf(stdout,"   header: sx  %7d   sy %7d\n",sx,sy);
+    fprintf(stdout,"           cx  %7.2f   cy %7.2f  cz %7.2f\n",cx,cy,cz);
+    fprintf(stdout,"        units: %7.2f  %7.2f\n",gu,hu);
+    fprintf(stdout,"          min: %7.3e  %7.3e\n",xmi,ymi);
+    fprintf(stdout,"   terrain size: %dx%d  %ld bytes\n",sx,sy,(long)bitsize);
+  }
+
+  mesh->np = sx*sy;
+  mesh->nt = 0;
+  mesh->nq = (sx-1)*(sy-1);
+  mesh->ne = mesh->nq;
+
+  /* memory allocation for mesh */
+  if ( !zaldy1(mesh) ) {
+    fclose(fp);
+    return(0);
+  }
+
+  /* read data */
+  if ( ityp == 1 ) {
+    xxm = xmi / cx;
+    yym = ymi / cy;
+    ggx = gu  * cx;
+    ggy = gu  * cy;
+    hhz = hu  * cz;
+    for (j=1; j<=sy; j++)
+      for (i=1; i<=sx; i++) {
+        k   = (j-1)*sx + i;
+        ppt = &mesh->point[k];
+        fscanf(fp,"%f",&ppt->c[2]);
+        ppt->c[0] = (float)(ggx*(xxm + i-1));
+        ppt->c[1] = (float)(ggy*(yym + j-1));
+        ppt->c[2] = (float)(hhz*ppt->c[2]);
+      }
+  }
+  else {
+    te = (float*)malloc(sx*sizeof(float));
+    if ( !te )  exit(1);
+    ni = 0;
+    xxm = xmi / cx;
+    yym = ymi / cy;
+    ggx = gu  / cx;
+    ggy = gu  / cy;
+    hhz = hu  / cz;
+    for (j=1; j<=sy; j++) {
+      ret = fread(te,sizeof(int),sx,fp);
+      if ( ret != sx ) {
+        fprintf(stderr,"  ## Error loading terrain.\n");
+        free(mesh->point);
+        free(mesh);
+        return(0);
+      }
+      for (i=1; i<=sx; i++) {
+        k   = (j-1)*sx + i;
+        ppt = &mesh->point[k];
+        ppt->c[2] = te[ni++];
+        ppt->c[0] = ggx*(xxm + i-1);
+        ppt->c[1] = ggy*(yym + j-1);
+        ppt->c[2] = hhz*ppt->c[2];
+      }
+    }
+    free(te);
+  }
+
+  /* construct topology */
+  mesh->dim = 3;
+  for (j=1; j<sy; j++)
+    for (i=1; i<sx; i++) {
+      k  = (j-1)*(sx-1) + i;
+      pq = &mesh->quad[k];
+      pq->v[0] = (j-1)*sx+i;
+      pq->v[1] = pq->v[0]+1;
+      pq->v[2] = j*sx+i+1;
+      pq->v[3] = pq->v[2]-1;
+      pq->ref  = 0;
+    }
+
+  /* read references, if any */
+  if ( ityp == 1 ) {
+    pos = ftell(fp);
+    ret = fscanf(fp,"%d",&i);
+    if ( ret != EOF ) {
+      fseek(fp,pos,SEEK_SET);
+      for (j=1; j<sy; j++)
+        for (i=1; i<sx; i++) {
+          k  = (j-1)*(sx-1) + i;
+          pq = &mesh->quad[k];
+          fscanf(fp,"%d",&ref);
+          pq->ref = ref;
+        }
+    }
+  }
+
+  /* solution = elevations */
+  mesh->nbb    = mesh->np;
+  mesh->bbmin  =  FLOAT_MAX;
+  mesh->bbmax  = -FLOAT_MAX;
+  mesh->typage = 2;
+  mesh->nfield = 1;
+
+  /* allocate memory */
+  if ( !zaldy2(mesh) ) {
+    mesh->nbb = 0;
+    fclose(fp);
+    return(1);
+  }
+  
+  for (j=1; j<=mesh->np; j++) {
+    ps  = &mesh->sol[j];
+    ppt = &mesh->point[j];
+    ps->bb = ppt->c[2];
+    if ( ps->bb < mesh->bbmin )  mesh->bbmin = ps->bb;
+    if ( ps->bb > mesh->bbmax )  mesh->bbmax = ps->bb;
+  }
+
+  fclose(fp);
+  return(1);  
+}
diff --git a/src/medit/grafic.h b/src/medit/grafic.h
new file mode 100644
index 0000000..5988e83
--- /dev/null
+++ b/src/medit/grafic.h
@@ -0,0 +1,225 @@
+#ifndef _GRAFIC_H
+#define _GRAFIC_H
+
+#define MAX_LIST  4
+#define MAXISO    5
+
+#define C_ON     (1 << 0)
+#define C_EDIT   (1 << 1)   
+#define C_VOL    (1 << 2)
+#define C_UPDATE (1 << 3)
+#define C_FREEZE (1 << 4)
+#define C_CAP    (1 << 5)
+#define C_REDO   (1 << 6)
+#define C_HIDE   (1 << 7)
+
+/* view modes */
+#define S_BDRY     (1<<0)
+#define S_FILL     (1<<1)
+#define S_COLOR    (1<<2)
+#define S_MAP      (1<<3)
+#define S_MATERIAL (1<<4)
+#define S_ALTITUDE (1<<5)
+#define S_DISPL    (1<<6)
+
+#define MONO     0
+#define LEFT     1
+#define RIGHT    2
+
+enum {WIRE   = S_BDRY,
+      HIDDEN = S_BDRY + S_FILL,
+      DEPTH  = S_BDRY + S_COLOR,
+      FILL   = S_FILL + S_COLOR,
+      SHADED = S_BDRY + S_FILL + S_COLOR,
+      SIZEMAP= S_BDRY + S_FILL + S_MAP
+     };
+enum {LTria, LQuad, LTets, LHexa, LEdges, LPoint};
+enum {PERSPECTIVE, CAMERA, ORTHO};
+enum {X_AXIS=0, Y_AXIS, Z_AXIS};
+enum {VECTOR,CONE};
+
+/* items */
+#define S_AXIS    (1<<0)
+#define S_BOX     (1<<1)
+#define S_GRID    (1<<2)
+#define S_GEOM    (1<<3)
+#define S_ISO     (1<<4)
+#define S_PALETTE (1<<5)
+#define S_NUMP    (1<<6)
+#define S_NUMF    (1<<7)
+
+/* type */
+#define S_FLAT     (1<<0)     /* render with facet normals  */
+#define S_SCISSOR  (1<<1)     /* scissoring mode            */
+#define S_FOLLOW   (1<<2)     /* picking mode               */
+#define S_NORMAL   (1<<3)
+#define S_OPPOS    (1<<4)
+#define S_DECO     (1<<5)
+#define S_PATH     (1<<6)
+#define S_RESET    (1<<7)
+
+/* iso-values */
+#define MAX_ISO    5
+#define S_ISOLINE  (1<<1)
+#define S_ISOSURF  (1<<2)
+#define S_STREAML  (1<<3)
+#define S_STREAMR  (1<<4)
+#define S_VECTOR   (1<<5)
+#define S_CRITP    (1<<6)
+#define S_PARTICLE (1<<7)
+
+    
+typedef struct sperspective {
+  float      fovy,depth;
+  float      matrix[16],alpha,gamma;
+  int        rubix,rubfx,rubiy,rubfy;
+  ubyte      pmode,rubber;
+} Persp;
+typedef Persp * pPersp;
+
+typedef struct triangle {
+  float a[3],b[3],c[3];
+  float va,vb,vc;
+  float na[3],nb[3],nc[3];
+} triangle;
+
+typedef struct material {
+  float   amb[4],emi[4],dif[4],spe[4],shininess;
+  float   ext[6];
+  GLint   list;
+  int     depmat[MAX_LIST];
+  int     ref,sort;
+  char    name[128];
+  ubyte   flag;
+} Material ;
+typedef Material * pMaterial;
+
+typedef struct _cell {
+  int   id;
+  int   x,y;
+  float min,max;
+  float value;
+  float step;
+  char* info;
+  char* format;
+} cell;
+
+typedef struct transform {
+  float    pos[3];                /* current mouse position */
+  float    angle,axis[3];         /* rotation angle + axis  */
+  float    panx,pany,opanx,opany; /* screen translation     */
+  float    matrix[16],oldmat[16]; /* transformation matrix  */
+  float    rot[16],tra[16];
+  int      mstate,mbutton,manim;
+} Transform;
+typedef Transform * pTransform;
+
+typedef struct cube {
+  pTransform   cubetr;
+  float        cmi[3],cma[3];
+  ubyte        active;
+} Cube;
+typedef Cube *pCube;
+
+typedef struct clip {
+  pTransform   cliptr;
+  double       eqn[4];
+  ubyte        active;
+} Clip;
+typedef Clip *pClip;
+
+
+typedef struct camera {
+  GLfloat  eye[3];                /* Position of the camera */
+  GLfloat  speed[3],spmod,altinc;
+  int      vecup;
+} Camera;
+typedef Camera * pCamera;
+
+/* scene parameters */
+typedef struct sparam {
+  float     back[4],line[4],edge[4],sunpos[4],clip[6];
+  float     cm,dpi,coeff,cumtim,cumpertime,maxtime,pertime,dt;
+  float     eyesep,linewidth,pointsize;
+  short     xi,yi,xs,ys;
+  int       nbmat;
+  char      pscolor[10];
+  ubyte     sunp,linc,advtim,nbpart;
+} Param;
+
+/* trajectoire */
+typedef struct straj {
+  int      np;
+  float   *pt;
+  float   *tg;
+  float    sec;
+  GLuint   tlist;
+} Trajet;
+
+/* streamlines */
+typedef struct sstream {
+  double   size,norm;
+  float    xmin,xmax,ymin,ymax,zmin,zmax;
+  float   *listp;
+  float    stpt[4][3],stcol[4];
+  int      stnp,stiso[4];
+  short    nbstl;
+  ubyte    typtrack;
+} Stream;
+typedef Stream * pStream;
+
+typedef struct strgrd {
+  pTransform   strtr;
+  GLuint       grid;
+  ubyte        active;
+} Strgrd;
+typedef Strgrd * pStrgrd;
+
+typedef struct siso {
+  float  val[MAXISO+2];
+  float  col[MAXISO+2];
+  ubyte  palette,ptyp;
+} Iso;
+
+typedef struct scene {
+  pTransform view;
+  pClip      clip;
+  pCube      cube;
+  pPersp     persp;
+  pCamera    camera;
+  pMaterial  material;
+  pStream    stream;
+  /*pStrgrd    stg;*/
+  Param      par;
+  Trajet     path;
+  Iso        iso;
+
+  float      dmin,dmax;       /* scene size    */
+  float      shrink;          /* shrink value  */
+  float      cx,cy,cz;        /* center of scene */
+  
+  GLuint     dlist[MAX_LIST];    /* display lists  */
+  GLuint     mlist[MAX_LIST];    /* metric lists   */
+  GLuint     ilist[MAX_LIST];    /* iso-surfaces   */
+  GLuint     clist[MAX_LIST];
+  GLuint     cmlist[MAX_LIST];   /* clipped elts   */
+  GLuint     vlist[MAX_LIST];    /* vector list    */
+  GLuint    *slist,cplist;       /* streamlines    */
+  GLuint     glist,nlist;        /* geometry lists */
+  GLuint     grid;
+  GLuint     picklist;
+
+  int       *matsort;
+  short      idwin,idmesh;    /* window, mesh id */
+  short      master,slave;
+
+  ubyte      item;            /* display items */
+  ubyte      mode;            /* render mode   */
+  ubyte      type;
+  ubyte      isotyp;
+  ubyte      picked;
+} Scene;
+typedef Scene * pScene;
+
+
+#endif
diff --git a/src/medit/hash.c b/src/medit/hash.c
new file mode 100644
index 0000000..56f62b8
--- /dev/null
+++ b/src/medit/hash.c
@@ -0,0 +1,376 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+#include <time.h>
+
+#define NC     32
+#define NC2    (NC*NC)
+#define NC3    (NC2*NC)
+
+#define KA     31
+#define KB     57
+#define KC     79
+
+static int ch[6][4] = { {0,1,2,3}, {4,5,6,7}, {0,1,5,4}, 
+                        {1,2,6,5}, {2,3,7,6}, {0,3,7,4} };
+static int idir[5]  = {0,1,2,0,1};
+static int idirt[7] = {0,1,2,3,0,1,2};
+
+
+/* very sioux! (09/2002) */
+int hashTetra(pMesh mesh) {
+  pTetra    pt,pt1;
+  int       k,kk,pp,l,ll,mins,mins1,maxs,maxs1,sum,sum1,iadr;
+  int      *hcode,*link,inival,hsize;
+  char     *hvoy;
+  ubyte     i,ii,i1,i2,i3;
+  unsigned  int  key;
+
+  /* avoid building */
+  if ( mesh->adja )  return(1);
+  if ( 4*sizeof(char) != sizeof(int) )  exit(1);
+
+  /* default */
+  if ( ddebug) {
+    fprintf(stdout,"  Setting topology.");
+    fflush(stdout);
+  }
+
+  /* memory alloc */
+  hcode = (int*)M_calloc(max(100,mesh->ntet+1),sizeof(int),"hash.tetra");
+  link  = (int*)M_calloc(4*max(100,mesh->ntet+1),sizeof(int),"hash.tetra");
+  hsize = max(100,mesh->ntet);
+  assert(hcode);
+  assert(link);
+
+  hvoy = (char*)hcode;
+
+  /* init */
+  inival = 2<<30;
+  for (k=0; k<=mesh->ntet; k++)
+    hcode[k] = -inival;
+
+  /* build hash table */
+  for (k=1; k<=mesh->ntet; k++) {
+    pt = &mesh->tetra[k];
+    if ( !pt->v[0] )  continue;
+    for (i=0; i<4; i++) {
+      i1 = idirt[i+1];
+      i2 = idirt[i+2];
+      i3 = idirt[i+3];
+      mins = min(pt->v[i1],pt->v[i2]);
+      mins = min(mins,pt->v[i3]);
+      maxs = max(pt->v[i1],pt->v[i2]);
+      maxs = max(maxs,pt->v[i3]);
+
+      /* compute key */
+      sum = pt->v[i1] + pt->v[i2] + pt->v[i3];
+      key = KA*mins + KB*maxs + KC*sum;
+      key = key % hsize + 1;
+
+      /* insert */
+      iadr = 4*(k-1) + i+1;
+      link[iadr] = hcode[key];
+      hcode[key] = -iadr;
+    }
+  }
+  if ( ddebug ) {
+    fprintf(stdout,".");
+    fflush(stdout);
+  }
+
+  /* set adjacency */
+  for (l=4*mesh->ntet; l>0; l--) {
+    if ( link[l] >= 0 )  continue;
+    k = (l-1) / 4 + 1;
+    i = (l-1) % 4;
+    i1 = idirt[i+1];
+    i2 = idirt[i+2];
+    i3 = idirt[i+3];
+    pt = &mesh->tetra[k];
+
+    sum  = pt->v[i1] + pt->v[i2] + pt->v[i3];
+    mins = min(pt->v[i1],pt->v[i2]);
+    mins = min(mins,pt->v[i3]);
+    maxs = max(pt->v[i1],pt->v[i2]);
+    maxs = max(maxs,pt->v[i3]);
+
+    /* accross link */
+    ll = -link[l];
+    pp = 0;
+    link[l] = 0;
+    hvoy[l] = 0;
+    while ( ll != inival ) {
+      kk = (ll-1) / 4 + 1;
+      ii = (ll-1) % 4;
+      i1 = idirt[ii+1];
+      i2 = idirt[ii+2];
+      i3 = idirt[ii+3];
+      pt1  = &mesh->tetra[kk];
+      sum1 = pt1->v[i1] + pt1->v[i2] + pt1->v[i3];
+      if ( sum1 == sum ) {
+        mins1 = min(pt1->v[i1],pt1->v[i2]);
+        mins1 = min(mins1,pt1->v[i3]);
+        if ( mins1 == mins ) {
+          maxs1 = max(pt1->v[i1],pt1->v[i2]);
+          maxs1 = max(maxs1,pt1->v[i3]);
+          if ( maxs1 == maxs ) {
+            /* adjacent found */
+            if ( pp != 0 )  link[pp] = link[ll];
+            link[l] = kk;
+            hvoy[l] = ii;
+            link[ll]= k;
+            hvoy[ll]= i;
+            break;
+          }
+        }
+      }
+      pp = ll;
+      ll = -link[ll];
+    }
+  }
+  mesh->adja = (int*)link;
+  mesh->voy  = (ubyte*)hcode;
+
+  if ( ddebug )
+    fprintf(stdout,"..\n");
+
+  return(1);
+}
+
+
+/* very sioux! (09/2002) */
+int hashHexa(pMesh mesh) {
+  pHexa     ph,ph1;
+  int       k,kk,iadr,pp,l,ll,v;
+  int       imin,mins,mins1,opps,opps1;
+  int      *hcode,*link,inival,hsize;
+  char     *hvoy;
+  ubyte     i,i1,ii;
+  unsigned  int  key;
+
+  /* avoid building again! */
+  if ( mesh->adja )  return(1);
+  if ( 4*sizeof(char) != sizeof(int) )  exit(1);
+
+  /* default */
+  if ( ddebug ) {
+    fprintf(stdout,"  Setting topology.");
+    fflush(stdout);
+  }
+
+  /* memory alloc */
+/* bug fixe: 17/04/2007
+  hcode = (int*)M_calloc(max(11,mesh->nhex+1),sizeof(int),"hash.hexa");
+  link  = (int*)M_calloc(6*max(11,mesh->nhex+1),sizeof(int),"hash.hexa");
+  hsize = max(10,mesh->nhex);
+  if ( !hcode || !link ) {
+    myerror.coderr = 1000;
+    return(0);
+  }
+  hvoy = (char*)hcode;
+*/
+  hcode = (int*)M_calloc(max(10,6*mesh->nhex/4+1),sizeof(int),"hash.hexa");
+  assert(hcode);
+  link  = (int*)M_calloc(max(10,6*mesh->nhex+1),sizeof(int),"hash.hexa");
+  assert(link);
+  hsize = max(2,mesh->nhex);
+  hvoy  = (char*)hcode;
+
+  /* init */
+  inival = 2 << 30;
+  for (k=0; k<=6*mesh->nhex/4; k++)
+    hcode[k] = -inival;
+
+  /* build hash table */
+  for (k=1; k<=mesh->nhex; k++) {
+    ph = &mesh->hexa[k];
+    if ( !ph->v[0] )  continue;
+    for (i=0; i<6; i++) {
+      mins = ph->v[ch[i][0]];
+      imin = 0;
+      for (v=1; v<4; v++)
+        if ( ph->v[ch[i][v]] < mins ) {
+          mins = ph->v[ch[i][v]];
+          imin = v;
+        }
+      i1   = (imin+2) % 4;
+      opps = ph->v[ch[i][i1]];
+
+      /* compute key */
+      key = KA*mins + KB*opps;
+      key = key % hsize + 1;
+
+      /* insert */
+      iadr = 6*(k-1) + i+1;
+      link[iadr] = hcode[key];
+      hcode[key] = -iadr;
+    }
+  }
+  if ( ddebug ) {
+    fprintf(stdout,".");
+    fflush(stdout);
+  }
+
+  /* set adjacency */
+  for (l=6*mesh->nhex; l>0; l--) {
+    if ( link[l] >= 0 )  continue;
+    k = (l-1) / 6 + 1;
+    i = (l-1) % 6;
+    ph   = &mesh->hexa[k];
+    mins = ph->v[ch[i][0]];
+    imin = 0;
+    for (v=1; v<4; v++)
+      if ( ph->v[ch[i][v]] < mins ) {
+        mins = ph->v[ch[i][v]];
+        imin = v;
+      }
+    i1   = (imin+2) % 4;
+    opps = ph->v[ch[i][i1]];
+
+    /* accross link */
+    ll = -link[l];
+    pp = 0;
+    link[l] = 0;
+    hvoy[l] = 0;
+    while ( ll != inival ) {
+      kk = (ll-1) / 6 +1;
+      ii = (ll-1) % 6;
+      ph1   = &mesh->hexa[kk];
+      mins1 = ph1->v[ch[ii][0]];
+      imin  = 0;
+      for (v=1; v<4; v++)
+        if ( ph1->v[ch[ii][v]] < mins1 ) {
+          mins1 = ph1->v[ch[ii][v]];
+          imin  = v;
+        }
+      i1    = (imin+2) % 4;
+      opps1 = ph1->v[ch[ii][i1]];
+
+      /* adjacent found */
+      if ( mins1 == mins && opps1 == opps ) {
+        if ( pp != 0 )  link[pp] = link[ll];
+        link[l] = kk;
+        hvoy[l] = ii;
+        link[ll]= k;
+        hvoy[ll]= i;
+        break;
+      }
+      pp = ll;
+      ll = -link[ll];
+    }
+  }
+  mesh->adja = (int*)link;
+  mesh->voy  = (ubyte*)hcode;
+
+  if ( ddebug )
+    fprintf(stdout,"..\n");
+
+  return(1);
+}
+
+
+/* very sioux! (09/2002) */
+int hashTria(pMesh mesh) {
+  pTriangle pt,pt1;
+  int       k,kk,l,ll,mins,maxs,mins1,maxs1,hsize;
+  int      *hcode,*link,inival,iadr,pp;
+  char     *hvoy;
+  ubyte     i,i1,i2,ii;
+  unsigned int key;
+
+  /* avoid building again! */
+  if ( mesh->adja )  return(1);
+  if ( 4*sizeof(char) != sizeof(int) )  exit(1);
+
+  /* default */
+  if ( ddebug) {
+    fprintf(stdout,"  Setting topology.");
+    fflush(stdout);
+  }
+
+  /* memory alloc */
+  hcode = (int*)M_calloc(max(1,3*mesh->nt/4)+1,sizeof(int),"hash.tria");
+  link  = (int*)M_calloc(3*mesh->nt+1,sizeof(int),"hash.tria");
+  hsize = max(2,3*mesh->nt/4-1);
+  assert(hcode);
+  assert(link);
+  hvoy = (char*)hcode;
+
+  /* init */
+  inival = 2 << 30;
+  for (k=0; k<=3*mesh->nt/4; k++)
+    hcode[k] = -inival;
+
+  /* build hash table */
+  for (k=1; k<=mesh->nt; k++) {
+    pt = &mesh->tria[k];
+    if ( !pt->v[0] )  continue;
+    for (i=0; i<3; i++) {
+      i1 = idir[i+1];
+      i2 = idir[i+2];
+      mins = min(pt->v[i1],pt->v[i2]);
+      maxs = max(pt->v[i1],pt->v[i2]);
+
+      /* compute key */
+      key = KA*mins + KB*maxs;
+      key = key % hsize + 1;
+
+      /* insert */
+      iadr = 3*(k-1) + i+1;
+      link[iadr] = hcode[key];
+      hcode[key] = -iadr;
+    }
+  }
+  if ( ddebug ) {
+    fprintf(stdout,".");
+    fflush(stdout);
+  }
+
+  /* set adjacency */
+  for (l=3*mesh->nt; l>0; l--) {
+    if ( link[l] >= 0 )  continue;
+    k = (l-1) / 3 + 1;
+    i = (l-1) % 3;
+    i1 = idir[i+1];
+    i2 = idir[i+2];
+    pt = &mesh->tria[k];
+
+    mins = min(pt->v[i1],pt->v[i2]);
+    maxs = max(pt->v[i1],pt->v[i2]);
+
+    /* accross link */
+    ll = -link[l];
+    pp = 0;
+    link[l] = 0;
+    hvoy[l] = 0;
+    while ( ll != inival ) {
+      kk = (ll-1) / 3 + 1;
+      ii = (ll-1) % 3;
+      i1 = idir[ii+1];
+      i2 = idir[ii+2];
+      pt1   = &mesh->tria[kk];
+      mins1 = min(pt1->v[i1],pt1->v[i2]);
+      maxs1 = max(pt1->v[i1],pt1->v[i2]);
+      
+      /* adjacent found */
+      if ( mins1 == mins && maxs1 == maxs ) {
+        if ( pp != 0 )  link[pp] = link[ll];
+        link[l] = kk;
+        hvoy[l] = ii;
+        link[ll]= k;
+        hvoy[ll]= i;
+        break;
+      }
+      pp = ll;
+      ll = -link[ll];
+    }
+  }
+  mesh->adja = (int*)link;
+  mesh->voy  = (ubyte*)hcode;
+
+  if ( ddebug )
+    fprintf(stdout,".\n");
+
+  return(1);
+}
diff --git a/src/medit/ilists.c b/src/medit/ilists.c
new file mode 100644
index 0000000..40a3201
--- /dev/null
+++ b/src/medit/ilists.c
@@ -0,0 +1,524 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define BASETR   0.2
+#define NBCOL    9
+
+
+/* build lists for iso-surfaces */
+GLuint listTriaIso(pScene sc,pMesh mesh) {
+  GLuint     dlist = 0;
+  pTriangle  pt;
+  pPoint     p0,p1;
+  pMaterial  pm;
+  pSolution  ps0,ps1;
+  double     rgb[3];
+  float      iso,cx,cy,cz,cc,kc;
+  int        m,k,i,l,l1,nc,ncol;
+  static double hsv[3]  = { 0.0, 1.0, 0.9 };
+  static int    idir[5] = {0,1,2,0,1};
+
+  /* default */
+  if ( !mesh->nt || !mesh->nbb || mesh->typage == 1 )  return(0);
+  if ( ddebug ) printf("create iso-values map list / TRIA\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* create display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  glBegin(GL_LINES);
+  ncol = NBCOL;
+  for (i=0; i<=ncol*(MAXISO-1); i++) {
+    if ( i < ncol*(MAXISO-1) ) {
+      l   = i / ncol;
+      kc  = (i % ncol) / (float)ncol;
+      iso = sc->iso.val[l]*(1.0-kc)+sc->iso.val[l+1]*kc;
+      hsv[0] = sc->iso.col[l]*(1.0-kc)+sc->iso.col[l+1]*kc;
+    }
+    else {
+      iso    = sc->iso.val[MAXISO-1];
+      hsv[0] = sc->iso.col[MAXISO-1];
+    }
+
+    hsvrgb(hsv,rgb);
+    glColor3dv(rgb);
+
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTria];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        /* analyze edges */
+        nc = 0;
+        cx = cy = cz = 0.0;
+        for (l=0; l<3; l++) {
+          l1  = idir[l+1];
+          p0  = &mesh->point[pt->v[l]];
+          p1  = &mesh->point[pt->v[l1]];
+          ps0 = &mesh->sol[pt->v[l]];
+          ps1 = &mesh->sol[pt->v[l1]];
+          if ( (ps0->bb > iso && ps1->bb <= iso) ||
+               (ps0->bb < iso && ps1->bb >= iso) ) {
+            cc = 0.0;
+            if ( fabs(ps1->bb-ps0->bb) > 0.0 )
+              cc = (iso-ps0->bb) / (ps1->bb-ps0->bb);
+            if ( cc == 0.0 || cc == 1.0 )  continue;
+            cx = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            nc++;
+            if ( mesh->dim == 2 )
+              glVertex2f(cx,cy);
+            else {
+              cz = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+              glVertex3f(cx,cy,cz);
+            }
+          }
+          else if ( ps0->bb == iso && ps1->bb == iso ) {
+            nc = 2;
+            if ( mesh->dim == 2 ) {
+              glVertex2f(p0->c[0],p0->c[1]);
+              glVertex2f(p1->c[0],p1->c[1]);
+              break;
+            }
+            else {
+              glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+              glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+              break;
+            }
+          }
+        }
+        if ( nc > 0 && nc != 2 ) {
+          if ( mesh->dim ==2 )  glVertex2f(cx,cy);
+          else                  glVertex3f(cx,cy,cz);
+        }
+        k = pt->nxt;
+      }
+    }
+  }
+  glEnd();
+  glEndList();
+  return(dlist);
+}
+
+/* build lists for iso-surfaces */
+GLuint listQuadIso(pScene sc,pMesh mesh) {
+  GLuint     dlist = 0;
+  pQuad      pq;
+  pPoint     p0,p1;
+  pMaterial  pm;
+  pSolution  ps0,ps1;
+  double     rgb[3];
+  float      iso,cx,cy,cz,cc,kc;
+  int        m,k,i,l,l1,ncol;
+  static double hsv[3]   = { 0.0f, 1.0f, 0.8f };
+  static int idir[6] = {0,1,2,3,0,1};
+
+  /* default */
+  if ( !mesh->nq || !mesh->nbb || mesh->typage == 1 )  return(0);
+  if ( ddebug ) printf("create iso-values map list / QUAD\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  glBegin(GL_LINES);
+  ncol = NBCOL;
+  for (i=0; i<=ncol*(MAXISO-1); i++) {
+    if ( i < ncol*(MAXISO-1) ) {
+      l   = i / ncol;
+      kc  = (i % ncol) / (float)ncol;
+      iso = sc->iso.val[l]*(1.0-kc)+sc->iso.val[l+1]*kc;
+      hsv[0] = sc->iso.col[l]*(1.0-kc)+sc->iso.col[l+1]*kc;
+    }
+    else {
+      iso    = sc->iso.val[MAXISO-1];
+      hsv[0] = sc->iso.col[MAXISO-1];
+    }
+    
+    hsvrgb(hsv,rgb);
+    glColor3dv(rgb);
+
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LQuad];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pq = &mesh->quad[k];
+        if ( !pq->v[0] ) {
+          k = pq->nxt;
+          continue;
+        }
+
+        /* analyze edges */
+        for (l=0; l<4; l++) {
+          p0  = &mesh->point[pq->v[l]];
+          ps0 = &mesh->sol[pq->v[l]];
+          l1  = idir[l+1];
+          p1  = &mesh->point[pq->v[l1]];
+          ps1 = &mesh->sol[pq->v[l1]];
+          if ( (ps0->bb > iso && ps1->bb <= iso) ||
+               (ps0->bb < iso && ps1->bb >= iso) ) {
+            cc = 0.0f;
+            if ( fabs(ps1->bb-ps0->bb) > 0.0f )
+              cc = (iso-ps0->bb) / (ps1->bb-ps0->bb);
+            if ( cc == 0.0f || cc == 1.0f )  continue;
+            cx = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            if ( mesh->dim == 2 )
+              glVertex2f(cx,cy);
+            else {
+              cz = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+              glVertex3f(cx,cy,cz);
+            }
+          }
+        }
+        k = pq->nxt;
+      }
+    }
+  }
+  glEnd();
+  glEndList();
+  return(dlist);
+}
+
+
+/* build lists for iso-surfaces */
+GLuint listTetraIso(pScene sc,pMesh mesh) {
+  FILE      *outv,*outf;
+  GLuint     dlist = 0;
+  pTetra     pt;
+  pPoint     p0,p1;
+  pMaterial  pm;
+  pSolution  ps0,ps1;
+  double     delta,rgb[4],d,ax,ay,az,bx,by,bz;
+  float      iso,n[3],cx[4],cy[4],cz[4],cc;
+  int        m,k,k1,k2,i,l,pos[4],neg[4],nbpos,nbneg,nbnul,nv,nf;
+  static double hsv[3]   = { 0.0f, 1.0f, 0.80f };
+  static int tn[4] = {0,0,1,1};
+  static int tp[4] = {0,1,1,0};
+
+  /* default */
+  if ( !mesh->ntet || !mesh->nbb || mesh->typage == 1 )  return(0);
+  if ( ddebug ) printf("create iso-values map list / TETRA\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  delta = sc->iso.val[MAXISO-1] - sc->iso.val[0];
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+  glDepthMask(GL_FALSE);
+
+  if (ddebug) {
+	outv = fopen("vertex.mesh","w");
+	fprintf(outv,"MeshVersionFormatted 1\n Dimension\n 3\n\nVertices\n \n");
+	outf = fopen("faces.mesh2","w");
+	fprintf(outv,"Triangles\n \n");
+  }
+  nv = nf = 0;
+
+  glBegin(GL_TRIANGLES);
+  for (i=MAXISO-1; i>=0; i--) {
+    iso = sc->iso.val[i];
+
+    /* base color */
+    /*hsv[0] = 240.0f*(1.0f - (iso-sc->iso.val[0])/delta);*/
+    hsv[0] = sc->iso.col[i];
+    hsvrgb(hsv,rgb);
+    rgb[0] = min(1.0,rgb[0]+BASETR);
+    rgb[1] = min(1.0,rgb[1]+BASETR);
+    rgb[2] = min(1.0,rgb[2]+BASETR);
+    rgb[3] = BASETR + (float)(i-1)/(float)MAXISO*(1.0-BASETR);
+    /*rgb[3] = 0.5; */  
+    glColor4dv(rgb);
+
+    if ( i == MAXISO-1 )  iso -= 0.001*fabs(iso)/delta;
+    else if ( i == 0 )    iso += 0.001*fabs(iso)/delta;
+
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTets];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tetra[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        /* analyze vertices */
+        nbpos = nbneg = nbnul = 0;
+        for (l=0; l<4; l++) {
+          p0  = &mesh->point[pt->v[l]];
+          ps0 = &mesh->sol[pt->v[l]];
+          /*if ( ps0->bb < sc->iso.val[0] )  ps0->bb = sc->iso.val[0];*/
+          
+          if ( ps0->bb > iso )      pos[nbpos++] = l;
+          else if ( ps0->bb < iso ) neg[nbneg++] = l;
+          else                      nbnul++;
+        }
+        if ( nbneg == 4 || nbpos == 4 ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        if ( nbneg == 2 && nbpos == 2 ) {
+          for (l=0; l<4; l++) {
+            k1  = neg[tn[l]];
+            k2  = pos[tp[l]];
+            p0  = &mesh->point[pt->v[k1]];
+            p1  = &mesh->point[pt->v[k2]];
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            cc = 0.0f;
+            if ( fabs(ps1->bb-ps0->bb) > 0.0f )
+              cc = (iso-ps0->bb) / (ps1->bb-ps0->bb);
+            cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+          }
+
+          /* compute face normal */
+          ax = cx[1]-cx[0]; ay = cy[1]-cy[0]; az = cz[1]-cz[0];
+          bx = cx[2]-cx[0]; by = cy[2]-cy[0]; bz = cz[2]-cz[0];
+          n[0] = ay*bz - az*by;
+          n[1] = az*bx - ax*bz;
+          n[2] = ax*by - ay*bx;
+          d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+          if ( d > 0.0f ) {
+            d = 1.0f / sqrt(d);
+            n[0] *= d;  
+            n[1] *= d;  
+            n[2] *= d;
+          }
+          glNormal3fv(n);
+          glVertex3f(cx[0],cy[0],cz[0]);
+          glVertex3f(cx[1],cy[1],cz[1]);
+          glVertex3f(cx[2],cy[2],cz[2]);
+          
+	      glNormal3fv(n);
+          glVertex3f(cx[0],cy[0],cz[0]);
+          glVertex3f(cx[2],cy[2],cz[2]);
+          glVertex3f(cx[3],cy[3],cz[3]);
+
+          if ( ddebug ) {
+            fprintf(outv,"%f %f %f 0\n",cx[0],cy[0],cz[0]);
+            fprintf(outv,"%f %f %f 0\n",cx[1],cy[1],cz[1]);
+            fprintf(outv,"%f %f %f 0\n",cx[2],cy[2],cz[2]);
+            fprintf(outv,"%f %f %f 0\n",cx[3],cy[3],cz[3]);
+
+            fprintf(outf,"%d %d %d 0\n",nv+1,nv+2,nv+3);
+            fprintf(outf,"%d %d %d 0\n",nv+1,nv+3,nv+4);
+          }
+          nv+= 4;
+          nf+= 2;
+        }
+        else if ( !nbnul ) {
+          for (l=0; l<3; l++) {
+            k1 = nbneg == 3 ? neg[l] : pos[l];
+            k2 = nbneg == 3 ? pos[0] : neg[0];
+            p0 = &mesh->point[pt->v[k1]];
+            p1 = &mesh->point[pt->v[k2]];
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            cc = 0.0f;
+            if ( fabs(ps1->bb-ps0->bb) > 0.0f ) 
+              cc = (iso-ps0->bb) / (ps1->bb-ps0->bb);
+            cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+          }
+          /* compute face normal */
+          ax = cx[1]-cx[0]; ay = cy[1]-cy[0]; az = cz[1]-cz[0];
+          bx = cx[2]-cx[0]; by = cy[2]-cy[0]; bz = cz[2]-cz[0];
+          n[0] = ay*bz - az*by;
+          n[1] = az*bx - ax*bz;
+          n[2] = ax*by - ay*bx;
+          d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+          if ( d > 0.0f ) {
+            d = 1.0f / sqrt(d);
+            n[0] *= d;
+            n[1] *= d;
+            n[2] *= d;
+          }
+          glNormal3fv(n);
+          glVertex3f(cx[0],cy[0],cz[0]);
+          glVertex3f(cx[1],cy[1],cz[1]);
+          glVertex3f(cx[2],cy[2],cz[2]);
+
+          if ( ddebug ) {
+            fprintf(outv,"%f %f %f 0\n",cx[0],cy[0],cz[0]);
+            fprintf(outv,"%f %f %f 0\n",cx[1],cy[1],cz[1]);
+            fprintf(outv,"%f %f %f 0\n",cx[2],cy[2],cz[2]);
+            fprintf(outf,"%d %d %d 0\n",nv+1,nv+2,nv+3);
+          }
+          nv += 3;
+          nf += 1;
+        }
+        k = pt->nxt;
+      }
+    }
+  }
+  glEnd();
+  glDepthMask(GL_TRUE);
+  glDisable(GL_BLEND);
+
+  if ( ddebug ) {
+    fclose(outv);
+    fclose(outf);
+  }
+  printf("  Vertices %d   Triangles %d\n",nv,nf);
+  glEndList();
+  return(dlist);
+}
+
+
+int tetraIsoPOVray(pScene sc,pMesh mesh) {
+  FILE      *isofil;
+  pTetra     pt;
+  pPoint     p0,p1;
+  pMaterial  pm;
+  pSolution  ps0,ps1;
+  double     delta;
+  float      iso,cx[4],cy[4],cz[4],cc;
+  int        m,k,k1,k2,i,l,pos[4],neg[4],nbpos,nbneg,nbnul;
+  char      *ptr,data[128];
+  static int tn[4] = {0,0,1,1};
+  static int tp[4] = {0,1,1,0};
+
+  /* default */
+  if ( !mesh->ntet || !mesh->nbb || mesh->typage == 1 )  return(0);
+  if ( ddebug ) printf("create isosurfaces POVray\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  delta = sc->iso.val[MAXISO-1] - sc->iso.val[0];
+
+  strcpy(data,mesh->name);
+  ptr = strstr(data,".mesh");
+  if ( ptr )  ptr = '\0';
+  strcat(data,".pov"); 
+  if ( ddebug )  fprintf(stdout,"  Writing POVRay file %s\n",data);
+  isofil = fopen(data,"w");
+  if ( !isofil )  return(0);
+
+  for (i=MAXISO-1; i>=0; i--) {
+    iso = sc->iso.val[i];
+
+    if ( i == MAXISO-1 )  iso -= 0.001*fabs(iso)/delta;
+    else if ( i == 0 )    iso += 0.001*fabs(iso)/delta;
+
+    fprintf(isofil,"\n#declare isosurf%d = mesh {\n",i);
+
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTets];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tetra[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        /* analyze vertices */
+        nbpos = nbneg = nbnul = 0;
+        for (l=0; l<4; l++) {
+          p0  = &mesh->point[pt->v[l]];
+          ps0 = &mesh->sol[pt->v[l]];
+          
+          if ( ps0->bb > iso )      pos[nbpos++] = l;
+          else if ( ps0->bb < iso ) neg[nbneg++] = l;
+          else                      nbnul++;
+        }
+        if ( nbneg == 4 || nbpos == 4 ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        if ( nbneg == 2 && nbpos == 2 ) {
+          for (l=0; l<4; l++) {
+            k1  = neg[tn[l]];
+            k2  = pos[tp[l]];
+            p0  = &mesh->point[pt->v[k1]];
+            p1  = &mesh->point[pt->v[k2]];
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            cc = 0.0f;
+            if ( fabs(ps1->bb-ps0->bb) > 0.0f )
+              cc = (iso-ps0->bb) / (ps1->bb-ps0->bb);
+            cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+          }
+
+	  fprintf(isofil,"triangle {\n");
+	  fprintf(isofil,"  <%f,%f,%f>,\n",
+	  cx[0]+mesh->xtra,cy[0]+mesh->ytra,cz[0]+mesh->ztra);
+ 	  fprintf(isofil,"  <%f,%f,%f>,\n",
+	  cx[1]+mesh->xtra,cy[1]+mesh->ytra,cz[1]+mesh->ztra);
+	  fprintf(isofil,"  <%f,%f,%f>\n" ,
+	  cx[2]+mesh->xtra,cy[2]+mesh->ytra,cz[2]+mesh->ztra);
+          fprintf(isofil,"}\n");
+
+	  fprintf(isofil,"triangle {\n");
+	  fprintf(isofil,"  <%f,%f,%f>,\n",
+	  cx[0]+mesh->xtra,cy[0]+mesh->ytra,cz[0]+mesh->ztra);
+ 	  fprintf(isofil,"  <%f,%f,%f>,\n",
+	  cx[2]+mesh->xtra,cy[2]+mesh->ytra,cz[2]+mesh->ztra);
+	  fprintf(isofil,"  <%f,%f,%f>\n" ,
+	  cx[3]+mesh->xtra,cy[3]+mesh->ytra,cz[3]+mesh->ztra);
+          fprintf(isofil,"}\n");
+        }
+        else if ( !nbnul ) {
+          for (l=0; l<3; l++) {
+            k1 = nbneg == 3 ? neg[l] : pos[l];
+            k2 = nbneg == 3 ? pos[0] : neg[0];
+            p0 = &mesh->point[pt->v[k1]];
+            p1 = &mesh->point[pt->v[k2]];
+            ps0 = &mesh->sol[pt->v[k1]];
+            ps1 = &mesh->sol[pt->v[k2]];
+            cc = 0.0f;
+            if ( fabs(ps1->bb-ps0->bb) > 0.0f ) 
+              cc = (iso-ps0->bb) / (ps1->bb-ps0->bb);
+            cx[l] = p0->c[0]+cc*(p1->c[0]-p0->c[0]);
+            cy[l] = p0->c[1]+cc*(p1->c[1]-p0->c[1]);
+            cz[l] = p0->c[2]+cc*(p1->c[2]-p0->c[2]);
+          }
+	  fprintf(isofil,"triangle {\n");
+	  fprintf(isofil,"  <%f,%f,%f>,\n",
+	  cx[0]+mesh->xtra,cy[0]+mesh->ytra,cz[0]+mesh->ztra);
+ 	  fprintf(isofil,"  <%f,%f,%f>,\n",
+	  cx[1]+mesh->xtra,cy[1]+mesh->ytra,cz[1]+mesh->ztra);
+	  fprintf(isofil,"  <%f,%f,%f>\n",
+	  cx[2]+mesh->xtra,cy[2]+mesh->ytra,cz[2]+mesh->ztra);
+          fprintf(isofil,"}\n");
+        }
+        k = pt->nxt;
+      }
+    }
+    fprintf(isofil,"}\n");
+  }
+
+  fclose(isofil);
+  return(1);
+}
diff --git a/src/medit/image.c b/src/medit/image.c
new file mode 100644
index 0000000..de6c654
--- /dev/null
+++ b/src/medit/image.c
@@ -0,0 +1,333 @@
+#include "medit.h"
+#include "sproto.h"
+#include "extern.h"
+
+
+PPMimage *loadPPM(const char *imgname,int *type) {
+  pPPMimage  result;
+  FILE      *fp;
+  int        i,k,typimg,ret,r,g,b,s,maxval,bitsize;
+  char      *ptr,c,buff[1024],data[256];
+
+  /* search for image */
+  ptr = strstr(imgname,".ppm");
+  if ( !ptr ) {
+    strcpy(data,imgname);
+    strcat(data,".ppm");
+    fp = fopen(data,"rb");
+  } 
+  else
+    fp = fopen(imgname,"rb");
+  if ( !fp ) {
+    fprintf(stderr,"  ## Unable to open file %s.\n",imgname);
+    return(0);
+  }
+
+  if ( !fgets(buff,sizeof(buff),fp) ) {
+    fprintf(stderr,"  ## Invalid file header.\n");
+    return(0);
+  }
+
+  /* check header file */
+  if ( buff[0] != 'P' ) {
+    fprintf(stderr,"  ## Invalid image format.\n");
+    return(0);
+  }
+  
+  switch(buff[1]) {
+  case '2': typimg = P2;  break;
+  case '3': typimg = P3;  break;
+  case '5': typimg = P5;  break;
+  case '6': typimg = P6;  break;
+  default:
+    fprintf(stderr,"  ## Invalid image format.\n");
+    return(0);
+  }
+  
+  /* allocate memory to store imagee */
+  result = malloc(sizeof(PPMimage));
+  if ( !result ) {
+    fprintf(stderr,"  ## Unable to load image.\n");
+    return(0);
+  }
+
+  do {
+    ret = fscanf(fp,"%s",buff);
+    if ( ret == EOF ) break;
+    /* check and strip comments */
+    if ( buff[0] == '#' )
+      do
+        c = getc(fp);
+      while ( c != '\n' );
+    else break;
+  }
+  while (1);
+
+  /* read columns + lines */
+  ret  = sscanf(buff,"%d",&s);
+  result->sizeX = (short)s;
+  ret += fscanf(fp,"%d",&s);
+  result->sizeY = (short)s;
+  if ( ret != 2 ) {
+    fprintf(stderr,"  ## Error loading image.\n");
+    free(result);
+    return(0);
+  }
+  if ( !quiet )
+    fprintf(stdout,"  image size:   %d x %d\n",result->sizeX,result->sizeY);
+
+  if ( fscanf(fp,"%d",&maxval) != 1 ) {
+    fprintf(stderr,"  ## Invalid image size.\n");
+    free(result);
+    return(0);
+  }
+
+  /* strip line */
+  while ( fgetc(fp) != '\n' ) ;
+
+  /* size based on type */
+  if ( typimg == P2 || typimg == P5 )
+    bitsize = result->sizeX*result->sizeY;
+  else
+    bitsize = 3*result->sizeX*result->sizeY;
+  result->data = (ubyte*)malloc(bitsize*sizeof(ubyte));
+  if ( !result ) {
+    fprintf(stderr,"  ## Unable to load image.\n");
+    free(result);
+    return(0);
+  }
+
+  /* read data file */
+  switch( typimg ) {
+  case P2:  /* ascii file (grey)  */
+  case P3:  /* ascii file (color) */
+    for (i=0; i<bitsize; i++) {
+      fscanf(fp,"%d",&r);
+      result->data[i] = (ubyte)r;
+    }
+    break;
+    
+  case P5:  /* binary file (grey) */
+  case P6:  /* binary file (color) */
+    ret = fread(result->data,sizeof(ubyte),bitsize,fp);
+    if ( ret != bitsize ) {
+      fprintf(stderr,"  ## Error loading image.\n");
+      free(result->data);
+      free(result);
+      return(0);
+    }
+    break;
+  }
+  fclose(fp);
+
+  if ( *type == DEFAULT )
+    switch( typimg ) {
+     case P2:
+     case P5:
+       *type = GREY;  break;
+     case P3:
+     case P6:
+       *type = RGB;  break;
+    }
+
+  /* convert to grey levels */
+  else if ( *type == GREY && (typimg == P3 || typimg == P6) ) {
+    fprintf(stdout,"  converting to grey levels\n");
+    for (i=0,k=0; i<bitsize; i+=3,k++) {
+      r = (int)result->data[i];
+      g = (int)result->data[i+1];
+      b = (int)result->data[i+2];
+      result->data[k] = (ubyte)(0.3*r+0.59*g+0.11*b);
+    }
+    result->data = (ubyte*)realloc(result->data,sizeof(ubyte)*bitsize/3);
+  }
+  
+  return(result);
+}
+
+
+int savePPM(const char *imgname,pPPMimage img,int typimg) {
+  FILE      *out;
+  int        i,c,bitsize;
+  char      *ptr,data[512];
+
+  strcpy(data,imgname);
+  ptr  = (char*)strstr(data,".ppm");
+  if ( !ptr ) strcat(data,".ppm");
+  out = fopen(data,"w");
+  if ( !out ) {
+    fprintf(stderr,"  ## Unable to open file %s.\n",data);
+    exit(1);
+  }
+
+  bitsize = img->sizeX*img->sizeY;
+  switch(typimg) {
+  case P2:
+    fprintf(out,"P2\n");
+    fprintf(out,"# Created using medit %s %s, (c) INRIA\n",ME_VER,ME_REL);
+    fprintf(out,"%d %d\n",img->sizeX,img->sizeY);
+    fprintf(out,"255\n");
+    c = 0;
+    for (i=0; i<img->sizeX*img->sizeY; i++) {
+      fprintf(out,"%3d ",(int)img->data[i]);
+      if ( ++c == 17 ) { 
+        c = 0; 
+        fprintf(out,"\n");
+      }
+    }
+    fprintf(out,"\n");
+    break;
+  case P5:
+    fprintf(out,"P5\n");
+    fprintf(out,"# Created using medit %s %s, (c) INRIA\n",ME_VER,ME_REL);
+    fprintf(out,"%d %d\n",img->sizeX,img->sizeY);
+    fprintf(out,"255\n");
+    fwrite(img->data,sizeof(ubyte),bitsize,out);
+    break;
+  case P6:
+    fprintf(out,"P6\n");
+    fprintf(out,"# Created using medit %s %s, (c) INRIA\n",ME_VER,ME_REL);
+    fprintf(out,"%d %d\n",img->sizeX,img->sizeY);
+    fprintf(out,"255\n");
+    bitsize = (img->sizeX*24+7)/8*img->sizeY;
+    if ( fwrite(img->data,sizeof(ubyte),bitsize,out) < bitsize )
+      fprintf(stderr,"  ## Data file corrupted.\n");
+    break;
+  }
+  fclose(out);
+
+  return(1);
+}
+
+
+int saveTGA(const char *imgname,GLubyte *img,int w,int h) {
+  TGAheader  tga;
+  int        i;
+  char      *ptr,data[256];
+  FILE      *out;
+  
+  strcpy(data,imgname);
+  ptr  = (char*)strstr(data,".tga");
+  if ( !ptr ) strcat(data,".tga");
+  out = fopen(data,"wb");
+  if ( !out ) {
+    fprintf(stderr,"  ## UNABLE TO OPEN FILE %s.\n",data);
+    exit(1);
+  }
+
+  tga.idfield_len = 0;
+  tga.cmap_type   = 0;
+  tga.image_type  = 2;
+  for (i=0; i<5; i++)
+    tga.cmap_spec[i] = 0;
+  for (i=0; i<2; i++) {
+    tga.x_orig[i] = 0;
+    tga.y_orig[i] = 0;
+  }
+  /* Lo bits */
+  tga.width[0] = w & 0xFF;
+  /* Hi bits */
+  tga.width[1] = (w >> 8) & 0xFF;
+  tga.height[0] = h & 0xFF;
+  tga.height[1] = (h >> 8) & 0xFF;
+  tga.pixel_size = 24;
+  tga.image_desc = 0;
+  /* Output header */
+  fwrite(&tga,sizeof(TGAheader),1,out);
+  
+  /* Output image */
+  fwrite(img, sizeof(unsigned char),w*h*3,out);
+  return(1);
+}
+
+void swapPixels(PPMimage *pixels) {
+  GLubyte   *row;
+  int        i,k,ck,bits;
+
+  bits = 3*pixels->sizeX;
+  row  = (GLubyte*)malloc(bits*sizeof(GLubyte));
+  if ( !row ) return;
+
+  /* exchange rows */
+  for (i=0; i<pixels->sizeY/2; i++) {
+    k  = 3*i*pixels->sizeX;
+    ck = 3*(pixels->sizeY-i-1)*pixels->sizeX;
+    memcpy(row,&pixels->data[k],bits);
+    memcpy(&pixels->data[k],&pixels->data[ck],bits);
+    memcpy(&pixels->data[ck],row,bits);
+  }
+  free(row);
+}
+
+
+int imgHard(pScene sc,char *data,char key) {
+  PPMimage  *pixels;
+  GLint      viewport[4];
+  pPersp     p;
+  int        xx0,yy0,ww,hh;
+
+  pixels = (PPMimage*)M_malloc(sizeof(PPMimage),"imgHard");
+  if ( !pixels ) {
+    fprintf(stderr,"  ## UNABLE TO ALLOCATE MEMORY FOR IMAGE.\n");
+    return(0);
+  }
+
+  p = sc->persp;
+  if ( abs(p->rubfx-p->rubix) > 0 ) {
+    ww  = abs(p->rubfx-p->rubix)-2;
+    hh  = abs(p->rubfy-p->rubiy)-2;
+    xx0 = min(p->rubix,p->rubfx)+1;
+    yy0 = min(p->rubiy,p->rubfy)+1;
+  }
+  else {
+    glGetIntegerv(GL_VIEWPORT,viewport);
+    ww  = viewport[2];
+    hh  = viewport[3];
+    xx0 = 0;
+    yy0 = 0;
+  }
+  
+  /* align to 8 bytes */
+  ww = ww & ~7;
+  hh = hh & ~7;
+
+  pixels->sizeX = (short)ww;
+  pixels->sizeY = (short)hh;
+  pixels->data = (ubyte*)M_calloc(3*ww*hh,sizeof(ubyte),"imgHard.data");
+  if ( !pixels->data ) {
+    fprintf(stderr,"  ## Not enough memory to save image.\n");
+    M_free(pixels);
+    return(0);
+  }
+
+  if ( ddebug ) fprintf(stdout,"size %d x %d\n",ww,hh);
+  
+  glFinish();
+  if ( saveimg )
+    glReadBuffer(GL_BACK_LEFT);
+  else
+    glReadBuffer(GL_FRONT);
+  glPixelStorei(GL_PACK_ALIGNMENT,4);
+  glPixelStorei(GL_PACK_ROW_LENGTH,0);
+  glPixelStorei(GL_PACK_SKIP_ROWS,0);
+  glPixelStorei(GL_PACK_SKIP_PIXELS,0);
+
+  glReadPixels(xx0,yy0,ww,hh,GL_RGB,GL_UNSIGNED_BYTE,pixels->data);
+  if ( glGetError() != GL_NO_ERROR ) {
+    fprintf(stderr,"  ## Unable to save image\n");
+    M_free(pixels->data);
+    M_free(pixels);
+    return(0);
+  }
+
+  if ( key == 'H' ) {
+    swapPixels(pixels);
+    savePPM(data,pixels,P6);
+  }
+  else if ( key == 'T' )
+    saveTGA(data,pixels->data,ww,hh);
+
+  M_free(pixels->data);
+  M_free(pixels);
+  return(1);
+}
diff --git a/src/medit/image.h b/src/medit/image.h
new file mode 100644
index 0000000..2bd47ee
--- /dev/null
+++ b/src/medit/image.h
@@ -0,0 +1,29 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum imgtyp {DEFAULT=0, P2,P3,P5,P6, PS,
+             GREY,RGB,RED,GREEN,BLUE,COLOR};
+
+typedef struct {
+  int        sizeX,sizeY;
+  GLubyte   *data;
+} PPMimage;
+typedef PPMimage *pPPMimage;
+
+typedef struct {
+  unsigned char idfield_len;
+  unsigned char cmap_type;
+  unsigned char image_type;
+  unsigned char cmap_spec[5];
+  unsigned char x_orig[2];
+  unsigned char y_orig[2];
+  unsigned char width[2];
+  unsigned char height[2];
+  unsigned char pixel_size;
+  unsigned char image_desc;
+} TGAheader;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/inmsh2.c b/src/medit/inmsh2.c
new file mode 100644
index 0000000..a270059
--- /dev/null
+++ b/src/medit/inmsh2.c
@@ -0,0 +1,193 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+int inmsh2(pMesh mesh) {
+  FILE      *inp,*inf;
+  pPoint     ppt,pp0,pp1,pp2,pp3;
+  pTriangle  pt1;
+  pQuad      pq1;
+  pEdge      pr;
+  int        k,disc,ret,degree,dum,ref,tag;
+  char      *ptr,data[256],sx[128],sy[128],sz[128];
+
+  /* check for .points */
+  strcpy(data,mesh->name);
+  strcat(data,".points");
+  inp = fopen(data,"r");
+  if ( !inp ) return(0);
+
+  /* check for .faces */
+  strcpy(data,mesh->name);
+  strcat(data,".faces");
+  inf = fopen(data,"r");
+  if ( !inf ) return(0);
+  if ( !quiet )  fprintf(stdout,"  Reading %s.{points,.faces}\n",mesh->name);
+
+  /* get number of elements */
+  /*fgets(data,255,inp);
+    sscanf(data,"%d",&mesh->np);*/
+  fscanf(inp,"%d",&mesh->np);
+  EatLine(inp);
+  
+  /*fgets(data,255,inf);
+  sscanf(data,"%d",&mesh->ne);*/
+  fscanf(inf,"%d",&mesh->ne);
+  EatLine(inf);
+  if ( !mesh->np ) { /*|| (mesh->dim == 3 && !mesh->ne) ) {*/
+	fprintf(stdout,"  ## No vertex.\n");
+    fclose(inp);
+    return(-1);
+  }
+  mesh->dim = 3;
+  mesh->nt = mesh->nq = mesh->ntet = mesh->nhex = mesh->nvn = 0;
+
+  /* first pass get number of faces */
+  for (k=1; k<=mesh->ne; k++) {
+    fscanf(inf,"%d",&degree);
+    if ( degree < 2 || degree > 4 ) {
+      fprintf(stdout,"  ## Wrong degree\n");
+      fclose(inp);
+      fclose(inf);
+      return(0);
+    }
+    else if ( degree == 2 )
+      mesh->na++;
+    else if ( degree == 3 )
+      mesh->nt++;
+    else if ( degree == 4 )
+      mesh->nq++;
+    /*fgets(data,80,inf);*/
+    EatLine(inf);
+  }
+  
+  /* check if vertices and elements found */
+  if ( !mesh->np ) { /*|| mesh->ne == 0 ) {*/
+    fclose(inp);
+    fclose(inf);
+    return(0);
+  }
+
+  /* memory allocation for mesh */
+  if ( zaldy1(mesh) != TRUE ) {
+    fclose(inp);
+    fclose(inf);
+    return(0);
+  }
+  
+  /* read mesh vertices */
+  for(k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+    /* parse coordinates into strings */
+    ret = fscanf(inp,"%s %s %s %d",sx,sy,sz,&ref);
+    if ( ret != 4 ) {
+      fclose(inp);
+      fclose(inf);
+      return(0);
+    }
+    if ( ptr = strpbrk(sx,"dD") )
+      *ptr = 'E';
+    if ( ptr = strpbrk(sy,"dD") )
+      *ptr = 'E';
+    if ( ptr = strpbrk(sz,"dD") )
+      *ptr = 'E';
+    /*
+    sscanf(sx,"%f",&ppt->c[0]);
+    sscanf(sy,"%f",&ppt->c[1]);
+    sscanf(sz,"%f",&ppt->c[2]);
+    */
+    ppt->c[0] = atof(sx);
+    ppt->c[1] = atof(sy);
+    ppt->c[2] = atof(sz);
+
+    ppt->ref = ref;
+    ppt->tag = M_UNUSED;
+  }
+  fclose(inp);
+
+  /* allocate memory for mesh edges */
+  if ( mesh->na > 0 ) {
+    mesh->edge = (pEdge)M_calloc(mesh->na+1,sizeof(Edge),"inmsh2.edge");
+    if ( !mesh->edge ) {
+      fprintf(stderr,"  ## WARN 0004, INMESH, %d\n",mesh->na);
+      fclose(inf);
+      return(1);
+    }
+  }
+
+  /* read mesh faces */
+  rewind(inf);
+  /*fgets(data,255,inf);
+  sscanf(data,"%d",&mesh->ne);*/
+  fscanf(inf,"%d",&mesh->ne);
+  EatLine(inf);
+  mesh->nt = 0;
+  mesh->nq = 0;
+  mesh->na = 0;
+  disc     = 0;
+  for (k=1; k<=mesh->ne; k++) {
+    fscanf(inf,"%d",&degree);
+    
+    if ( degree == 2 ) {
+      pr = &mesh->edge[++mesh->na];
+      fscanf(inf,"%d %d %d %d %d\n",&pr->v[0],&pr->v[1],&tag,&dum,&dum);
+      pr->tag = tag == 0 ? M_NOTAG : M_TAG; 
+      pp0 = &mesh->point[pr->v[0]];
+      pp1 = &mesh->point[pr->v[1]];
+      pp0->tag = M_NOTAG;
+      pp1->tag = M_NOTAG;
+    }
+    else if ( degree == 3 ) {
+      pt1 = &mesh->tria[++mesh->nt];
+      fscanf(inf,"%d %d %d %d %d %d %d\n",&pt1->v[0],&pt1->v[1],&pt1->v[2],
+	     &ref,&dum,&dum,&dum);
+      if ( pt1->v[0] <= 0 || pt1->v[0] > mesh->np ||
+           pt1->v[1] <= 0 || pt1->v[1] > mesh->np ||
+           pt1->v[2] <= 0 || pt1->v[2] > mesh->np ) {
+	    fprintf(stdout,"  ## Wrong index\n");
+	    disc++;
+	    pt1->v[0] = 0;
+	    continue;
+      }
+      pt1->ref = fabs(ref);
+      pp0 = &mesh->point[pt1->v[0]];
+      pp1 = &mesh->point[pt1->v[1]];
+      pp2 = &mesh->point[pt1->v[2]];
+      pp0->tag = M_NOTAG;
+      pp1->tag = M_NOTAG;
+      pp2->tag = M_NOTAG;
+    }
+    else if ( degree == 4 ) {
+      pq1 = &mesh->quad[++mesh->nq];
+      fscanf(inf,"%d %d %d %d",&pq1->v[0],&pq1->v[1],&pq1->v[2],&pq1->v[3]);
+      fscanf(inf,"%d %d %d %d %d",&ref,&dum,&dum,&dum,&dum);
+      if ( pq1->v[0] <= 0 || pq1->v[0] > mesh->np ||
+           pq1->v[1] <= 0 || pq1->v[1] > mesh->np ||
+           pq1->v[2] <= 0 || pq1->v[2] > mesh->np ||
+           pq1->v[3] <= 0 || pq1->v[3] > mesh->np ) {
+		fprintf(stdout,"  ## Wrong index\n");
+	    disc++;
+	    pq1->v[0] = 0;
+	    continue;
+      }
+
+      pq1->ref = fabs(ref);
+      pp0 = &mesh->point[ pq1->v[0] ];
+      pp1 = &mesh->point[ pq1->v[1] ];
+      pp2 = &mesh->point[ pq1->v[2] ];
+      pp3 = &mesh->point[ pq1->v[3] ];
+      pp0->tag = M_NOTAG;
+      pp1->tag = M_NOTAG;
+      pp2->tag = M_NOTAG;
+      pp3->tag = M_NOTAG;
+    }
+  }
+
+  fclose(inf);
+  if ( disc > 0 ) {
+    fprintf(stdout," ## %d entities discarded\n",disc);
+  }
+  
+  return(1);
+}
diff --git a/src/medit/inout.c b/src/medit/inout.c
new file mode 100755
index 0000000..f929a20
--- /dev/null
+++ b/src/medit/inout.c
@@ -0,0 +1,754 @@
+#include "medit.h"
+#include "libmesh5.h"
+#include "extern.h"
+
+
+int loadMesh(pMesh mesh) {
+  pPoint      ppt;
+  pEdge       pr;
+  pTriangle   pt;
+  pQuad       pq;
+  pTetra      ptet;
+  pHexa       ph;
+  double      d,dp1,dp2,dp3,dn[3];
+  float      *n,fp1,fp2,fp3;
+  int         i,ia,ib,inm,ref,is,k,disc,nn,nt,nq;
+  char       *ptr,data[256];
+
+  printf("use loadMesh\n");
+  /* default */
+  strcpy(data,mesh->name);
+  ptr = strstr(data,".mesh");
+  if ( !ptr ) {
+    strcat(data,".meshb");
+    if ( !(inm = GmfOpenMesh(data,GmfRead,&mesh->ver,&mesh->dim)) ) {
+      ptr = strstr(data,".mesh");
+      *ptr = '\0';
+      strcat(data,".mesh");
+      if ( !(inm = GmfOpenMesh(data,GmfRead,&mesh->ver,&mesh->dim)) ) {
+        fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
+        return(-1);
+      }
+    }
+  }
+  else if (!(inm = GmfOpenMesh(data,GmfRead,&mesh->ver,&mesh->dim)) ) {
+    fprintf(stderr,"  ** %s  NOT FOUND.\n",data);
+    return(-1);
+  }
+  if ( !quiet )  fprintf(stdout,"  Reading %s\n",data);
+
+  /* parse keywords */
+  mesh->np   = GmfStatKwd(inm,GmfVertices);
+  printf("mesh->np=%i\n",mesh->np);
+  mesh->nt   = GmfStatKwd(inm,GmfTriangles);
+  printf("mesh->np=%i\n",mesh->nt);
+  mesh->nq   = GmfStatKwd(inm,GmfQuadrilaterals);
+  mesh->ntet = GmfStatKwd(inm,GmfTetrahedra);
+  mesh->nhex = GmfStatKwd(inm,GmfHexahedra);
+  mesh->nc   = GmfStatKwd(inm,GmfCorners);
+  mesh->nr   = GmfStatKwd(inm,GmfRequiredVertices);
+  mesh->na   = GmfStatKwd(inm,GmfEdges);
+  mesh->nri  = GmfStatKwd(inm,GmfRidges);
+  mesh->nre  = GmfStatKwd(inm,GmfRequiredEdges);
+  mesh->nvn  = GmfStatKwd(inm,GmfNormals);
+  mesh->ntg  = GmfStatKwd(inm,GmfTangents);
+  mesh->ne = mesh->nt + mesh->nq + mesh->ntet + mesh->nhex;
+
+  /* check space dimension */
+  if ( mesh->dim < 2 || mesh->dim > 3 ) {
+	fprintf(stdout,"  ## Wrong dim\n");
+    GmfCloseMesh(inm);
+    return(-1);
+  }
+  /* check if vertices and elements found */
+  if ( !mesh->np ) {
+    fprintf(stdout,"  ## No vertex\n");
+    GmfCloseMesh(inm);
+    return(-1);
+  }
+
+  /* memory allocation for mesh */
+  if ( !zaldy1(mesh) ) {
+    GmfCloseMesh(inm);
+    return(-1);
+  }
+
+  /* read mesh vertices */
+  GmfGotoKwd(inm,GmfVertices);
+  for (k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+    if ( mesh->ver == GmfFloat ) {
+      if ( mesh->dim == 2 ) {
+        GmfGetLin(inm,GmfVertices,&fp1,&fp2,&ref);
+  	    ppt->c[0] = fp1;
+  	    ppt->c[1] = fp2;
+	    printf("vertices %f %f %i\n",fp1,fp2,ref);
+      }
+      else {
+        GmfGetLin(inm,GmfVertices,&fp1,&fp2,&fp3,&ref);
+  	    ppt->c[0] = fp1;
+  	    ppt->c[1] = fp2;
+	    ppt->c[2] = fp3;
+      }
+    }
+    else {
+      if ( mesh->dim == 2 ) {
+        GmfGetLin(inm,GmfVertices,&dp1,&dp2,&ref);
+        ppt->c[0] = dp1;
+        ppt->c[1] = dp2;
+      }
+      else {
+        GmfGetLin(inm,GmfVertices,&dp1,&dp2,&dp3,&ref);
+        ppt->c[0] = dp1;
+        ppt->c[1] = dp2;
+        ppt->c[2] = dp3;
+      }
+    }
+    ppt->ref = ref & 0x7fff;
+    ppt->tag = M_UNUSED;
+  }
+
+  /* read mesh triangles */
+  disc = 0 ;
+  GmfGotoKwd(inm,GmfTriangles);
+  for (k=1; k<=mesh->nt; k++) {
+    pt = &mesh->tria[k];
+    GmfGetLin(inm,GmfTriangles,&pt->v[0],&pt->v[1],&pt->v[2],&ref);
+    pt->ref  = ref & 0x7fff;
+    for (i=0; i<3; i++) {    
+      if ( pt->v[i] < 1 || pt->v[i] > mesh->np ) {
+        disc++;
+    pt->v[0] = 0;
+        break;
+      }
+      else {
+        ppt = &mesh->point[pt->v[i]];
+        ppt->tag &= ~M_UNUSED;
+      }
+    }
+  }
+
+  /* mesh quadrilaterals */
+  GmfGotoKwd(inm,GmfQuadrilaterals);
+  for (k=1; k<=mesh->nq; k++) {
+    pq = &mesh->quad[k];
+    GmfGetLin(inm,GmfQuadrilaterals,&pq->v[0],&pq->v[1],&pq->v[2],&pq->v[3],&ref);
+    pq->ref  = ref & 0x7fff;
+    for (i=0; i<4; i++) {    
+      if ( pq->v[i] < 1 || pq->v[i] > mesh->np ) {
+        disc++;
+        pq->v[0] = 0;
+        break;
+      }
+      else {
+        ppt = &mesh->point[pq->v[i]];
+        ppt->tag &= ~M_UNUSED;
+      }
+    }
+  }
+
+  /* mesh tetrahedra */
+  GmfGotoKwd(inm,GmfTetrahedra);
+  for (k=1; k<=mesh->ntet; k++) {
+    ptet = &mesh->tetra[k];
+    GmfGetLin(inm,GmfTetrahedra,&ptet->v[0],&ptet->v[1],&ptet->v[2],&ptet->v[3],&ref);
+    ptet->ref  = ref & 0x7fff;
+    for (i=0; i<4; i++) {    
+      if ( ptet->v[i] < 1 || ptet->v[i] > mesh->np ) {
+        disc++;
+        ptet->v[0] = 0;
+        break;
+      }
+      else {
+        ppt = &mesh->point[ptet->v[i]];
+        ppt->tag &= ~M_UNUSED;
+      }
+    }
+  }
+
+  /* mesh hexahedra */
+  GmfGotoKwd(inm,GmfHexahedra);
+  for (k=1; k<=mesh->nhex; k++) {
+    ph = &mesh->hexa[k];
+    GmfGetLin(inm,GmfHexahedra,&ph->v[0],&ph->v[1],&ph->v[2],&ph->v[3],
+              &ph->v[4],&ph->v[5],&ph->v[6],&ph->v[7],&ref);
+    ph->ref  = ref & 0x7fff;
+    for (i=0; i<8; i++) {    
+      if ( ph->v[i] < 1 || ph->v[i] > mesh->np ) {
+        disc++;
+        ph->v[0] = 0;
+        break;
+      }
+      else {
+        ppt = &mesh->point[ph->v[i]];
+        ppt->tag &= ~M_UNUSED;
+      }
+    }
+  }
+
+  /* mesh corners */
+  GmfGotoKwd(inm,GmfCorners);
+  for (k=1; k<=mesh->nc; k++) {
+    GmfGetLin(inm,GmfCorners,&is);
+    if ( is < 1 || is > mesh->np )
+      disc++;
+    else {
+      ppt = &mesh->point[is];
+      ppt->tag |= M_CORNER;
+      ppt->tag &= ~M_UNUSED;
+    }
+  }
+
+  /* required vertices */
+  GmfGotoKwd(inm,GmfRequiredVertices);
+  for (k=1; k<=mesh->nr; k++) {
+    GmfGetLin(inm,GmfRequiredVertices,&is);
+    if ( is < 1 || is > mesh->np )
+      disc++;
+    else {
+      ppt = &mesh->point[is];
+      ppt->tag |= M_REQUIRED;
+      ppt->tag &= ~M_UNUSED;
+    }
+  }
+
+  /*mesh edges */
+  GmfGotoKwd(inm,GmfEdges);
+  for (k=1; k<=mesh->na; k++) {
+    GmfGetLin(inm,GmfEdges,&ia,&ib,&ref);
+    if ( ia < 1 || ia > mesh->np || ib < 1 || ib > mesh->np )
+      disc++;
+    else {
+      pr = &mesh->edge[k];
+      pr->v[0] = ia;
+      pr->v[1] = ib;
+      pr->ref  = ref & 0x7fff;
+      pr->tag  = !pr->ref ? M_NOTAG : M_TAG;
+      ppt = &mesh->point[ia];
+      ppt->tag &= ~M_UNUSED;
+      ppt = &mesh->point[ib];
+      ppt->tag &= ~M_UNUSED;
+    }
+  }
+
+  /* mesh ridges */
+  GmfGotoKwd(inm,GmfRidges);
+  for (k=1; k<=mesh->nri; k++) {
+    GmfGetLin(inm,GmfRidges,&is);
+    if ( is < 1 || is > mesh->na )
+      disc++;
+    else {
+      pr = &mesh->edge[is];
+      pr->tag |= M_RIDGE;
+    }
+  }
+
+  /* required edges */
+  GmfGotoKwd(inm,GmfRequiredEdges);
+  for (k=1; k<=mesh->nre; k++) {
+    GmfGetLin(inm,GmfRequiredEdges,&is);
+    if ( is < 1 || is > mesh->na )
+      disc++;
+    else {
+      pr = &mesh->edge[is];
+      pr->tag |= M_REQUIRED;
+    }
+  }
+
+
+  /* mesh normals */
+  GmfGotoKwd(inm,GmfNormals);
+  for (k=1; k<=mesh->nvn; k++) {
+    n = &mesh->extra->n[3*(k-1)+1];
+    if ( mesh->ver == GmfFloat )
+      GmfGetLin(inm,GmfNormals,&n[0],&n[1],&n[2]);
+    else {
+      GmfGetLin(inm,GmfNormals,&dn[0],&dn[1],&dn[2]);
+      n[0] = dn[0];
+      n[1] = dn[1];
+      n[2] = dn[2];
+    }
+    d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+    if ( d > 0.0 ) {
+      d = 1.0 / sqrt(d);
+      n[0] *= d;
+      n[1] *= d;
+      n[2] *= d;
+    }
+  }
+
+  if ( mesh->nvn ) {
+    /* normals at vertices */
+    mesh->extra->iv = GmfStatKwd(inm,GmfNormalAtVertices);
+    mesh->extra->nv = (int*)M_calloc(mesh->np+1,sizeof(int),"inmesh");
+    assert(mesh->extra->nv);
+    GmfGotoKwd(inm,GmfNormalAtVertices);
+    for (k=1; k<=mesh->extra->iv; k++) {
+      GmfGetLin(inm,GmfNormalAtVertices,&nn,&is);
+      if ( nn < 1 || nn > mesh->np )
+        disc++;
+      else
+    mesh->extra->nv[nn] = is;
+    }
+
+    /* normals at triangle vertices */
+    mesh->extra->it = GmfStatKwd(inm,GmfNormalAtTriangleVertices);
+    mesh->extra->nt = (int*)M_calloc(3*mesh->nt+1,sizeof(int),"inmesh");
+    assert(mesh->extra->nt);
+    GmfGotoKwd(inm,GmfNormalAtTriangleVertices);
+    for (k=1; k<=mesh->extra->it; k++) {
+      GmfGetLin(inm,GmfNormalAtTriangleVertices,&nt,&is,&nn);
+      if ( nt < 1 || nt > mesh->nt || is < 1 || is > 3 || nn < 1 || nn > mesh->nvn )
+        disc++;
+      else
+    mesh->extra->nt[3*(nt-1)+is] = nn;
+    }
+
+    /*normals at quadrilateral vertices */
+    mesh->extra->iq = GmfStatKwd(inm,GmfNormalAtQuadrilateralVertices);
+    mesh->extra->nq = (int*)M_calloc(4*mesh->nq+1,sizeof(int),"inmesh");
+    assert(mesh->extra->nq);
+    GmfGotoKwd(inm,GmfNormalAtQuadrilateralVertices);
+    for (k=1; k<=mesh->extra->iq; k++) {
+      GmfGetLin(inm,GmfNormalAtQuadrilateralVertices,&nq,&is,&nn);
+      if ( nq < 1 || nq > mesh->nq || is < 1 || is > 4 || nn < 1 || nn > mesh->nvn )
+        disc++;
+      else
+    mesh->extra->nq[3*(nq-1)+is] = nn;
+    }
+  }
+
+  /*mesh tangents */
+  GmfGotoKwd(inm,GmfTangents);
+  for (k=1; k<=mesh->ntg; k++) {
+    n = &mesh->extra->t[3*(k-1)+1];
+    if ( mesh->ver == GmfFloat )
+      GmfGetLin(inm,GmfTangents,&n[0],&n[1],&n[2]);
+    else {
+      GmfGetLin(inm,GmfTangents,&dn[0],&dn[1],&dn[2]);
+      n[0] = dn[0];
+      n[1] = dn[1];
+      n[2] = dn[2];
+    }
+    d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+    if ( d > 0.0 ) {
+      d = 1.0 / sqrt(d);
+      n[0] *= d;
+      n[1] *= d;
+      n[2] *= d;
+    }
+  }
+
+  if (mesh->ntg ) {
+    /*tangents at vertices */
+    mesh->extra->jv = GmfStatKwd(inm,GmfTangentAtVertices);
+    mesh->extra->tv = (int*)M_calloc(mesh->np+1,sizeof(int),"inmesh");
+    assert(mesh->extra->tv);
+    GmfGotoKwd(inm,GmfTangentAtVertices);
+    for (k=1; k<=mesh->extra->jv; k++) {
+      GmfGetLin(inm,GmfTangentAtVertices,&nn,&is);
+      if ( nn < 1 || nn > mesh->np )
+        disc++;
+      else
+    mesh->extra->tv[nn] = is;
+    }
+    
+    /* tangent at edge vertices */
+    mesh->extra->je = GmfStatKwd(inm,GmfTangentAtEdgeVertices);
+    mesh->extra->te = (int*)M_calloc(2*mesh->na+1,sizeof(int),"inmesh");
+    assert(mesh->extra->te);
+    GmfGotoKwd(inm,GmfTangentAtEdgeVertices);
+    for (k=1; k<=mesh->extra->je; k++) {
+      GmfGetLin(inm,GmfTangentAtEdgeVertices,&nt,&is,&nn);
+      if ( nt < 1 || nt > mesh->np || is < 1 || is > 2 || nn < 1 || nn > mesh->ntg )
+        disc++;
+      else
+    mesh->extra->te[3*(nt-1)+is] = is;
+    }
+  }
+
+  GmfCloseMesh(inm);
+  if ( disc > 0 ) {
+    fprintf(stdout,"  ## %d entities discarded\n",disc);
+  }
+  return(1);
+}
+
+
+/*mark clipped elements */
+static int markPt(pMesh mesh) {
+  pTriangle  pt;
+  pQuad      pq;
+  pPoint     ppt;
+  int        i,k,pos,neg,nul;
+
+  for (k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+    if ( ppt->tag & M_UNUSED )  continue;
+    ppt->tmp = 0;
+  }
+
+  for (k=1; k<=mesh->nt; k++ ) {
+    pt = &mesh->tria[k];
+    if ( !pt->v[0] )  continue;
+    pos = neg = nul = 0;
+    for (i=0; i<3; i++) {
+      ppt = &mesh->point[pt->v[i]];
+      if ( ppt->clip == 2 )       pos++;
+      else if ( ppt->clip == 1 )  neg++;
+      else                        nul++;
+    }
+    if ( pos && pos+nul < 4 ) {
+      for (i=0; i<3; i++) {
+        ppt = &mesh->point[pt->v[i]];
+        ppt->tmp = 1;
+      }
+    }
+  }
+
+  for (k=1; k<=mesh->nq; k++ ) {
+    pq = &mesh->quad[k];
+    if ( !pq->v[0] )  continue;
+    pos = neg = nul = 0;
+    for (i=0; i<4; i++) {
+      ppt = &mesh->point[pq->v[i]];
+      if ( ppt->clip == 2 )       pos++;
+      else if ( ppt->clip == 1 )  neg++;
+      else                        nul++;
+    }
+    if ( pos && pos+nul < 5 ) {
+      for (i=0; i<4; i++) {
+        ppt = &mesh->point[pq->v[i]];
+        ppt->tmp = 1;
+      }
+    }
+  }
+
+  return(1);
+}
+
+
+/* save (part of) mesh to disk */
+int saveMesh(pScene sc,pMesh mesh,char *fileout,ubyte clipon) {
+  pPoint     ppt;
+  pTriangle  pt;
+  pQuad      pq;
+  pTetra     ptt;
+  pMaterial  pm;
+  float      fp1,fp2,fp3;
+  int        outm,i,k,m,ver,np,nt,nq,ref;
+
+  ver = GmfFloat;
+  if ( !(outm = GmfOpenMesh(fileout,GmfWrite,ver,mesh->dim)) ) {
+    fprintf(stderr,"  ** UNABLE TO OPEN %s.\n",fileout);
+    return(0);
+  }
+  fprintf(stdout,"  %%%% %s OPENED\n",fileout);
+
+  /*compact vertices */
+  if ( clipon )  
+    markPt(mesh);
+  np = 0;
+  for (k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+    if ( ppt->tag & M_UNUSED )  continue;
+    ppt->tmp = ++np;
+  }
+
+  GmfSetKwd(outm,GmfVertices,np);
+  for (k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+    if ( ppt->tag & M_UNUSED )  continue;
+    ref = ppt->ref;
+    if ( mesh->dim == 2 ) {
+      fp1 = ppt->c[0] + mesh->xtra;
+      fp2 = ppt->c[1] + mesh->ytra;
+      ref = ppt->ref;
+      GmfSetLin(outm,GmfVertices,fp1,fp2,ref);
+    }
+    else {
+      fp1 = ppt->c[0] + mesh->xtra;
+      fp2 = ppt->c[1] + mesh->ytra;
+      fp3 = ppt->c[2] + mesh->ztra;
+      ref = ppt->ref;
+      GmfSetLin(outm,GmfVertices,fp1,fp2,fp3,ref);
+    }
+  }
+
+  /* write triangles */
+  nt = 0;
+  for (k=1; k<=mesh->nt; k++) {
+    pt = &mesh->tria[k];
+    if ( !pt->v[0] )  continue;
+    m  = matRef(sc,pt->ref);
+    pm = &sc->material[m];
+    if ( pm->flag )  continue;
+    for (i=0; i<3; i++)
+      if ( !mesh->point[pt->v[i]].tmp )  break;
+    if ( i == 3 )  nt++;
+  }
+  GmfSetKwd(outm,GmfTriangles,nt);
+  for (k=1; k<=mesh->nt; k++) {
+    pt = &mesh->tria[k];
+    if ( !pt->v[0] )  continue;
+    m  = matRef(sc,pt->ref);
+    pm = &sc->material[m];
+    if ( pm->flag )  continue;
+    for (i=0; i<3; i++)
+      if ( !mesh->point[pt->v[i]].tmp )  break;
+    if ( i < 3 )  continue;
+    ref = pt->ref;
+    GmfSetLin(outm,GmfTriangles,mesh->point[pt->v[0]].tmp,mesh->point[pt->v[1]].tmp,
+              mesh->point[pt->v[2]].tmp,ref);
+  }
+
+  /* write quads */
+  nq = 0;
+  for (k=1; k<=mesh->nq; k++) {
+    pq = &mesh->quad[k];
+    if ( !pq->v[0] )  continue;
+    m  = matRef(sc,pq->ref);
+    pm = &sc->material[m];
+    if ( pm->flag )  continue;
+    for (i=0; i<4; i++)
+      if ( !mesh->point[pq->v[i]].tmp )  break;
+    if ( i == 4 )  nq++;
+  }
+  GmfSetKwd(outm,GmfQuadrilaterals,nq);
+  for (k=1; k<=mesh->nq; k++) {
+    pq = &mesh->quad[k];
+    if ( !pq->v[0] )  continue;
+    m  = matRef(sc,pq->ref);
+    pm = &sc->material[m];
+    if ( pm->flag )  continue;
+    for (i=0; i<4; i++)
+      if ( !mesh->point[pq->v[i]].tmp )  break;
+    if ( i < 4 )  continue;
+    ref = pq->ref;
+    GmfSetLin(outm,GmfQuadrilaterals,mesh->point[pq->v[0]].tmp,mesh->point[pq->v[1]].tmp,
+              mesh->point[pq->v[2]].tmp,mesh->point[pq->v[3]].tmp,ref);
+  }
+
+  /* write tetrahedra */
+  GmfSetKwd(outm,GmfTetrahedra,mesh->ntet);
+  for (k=1; k<=mesh->ntet; k++) {
+    ptt = &mesh->tetra[k];
+    if ( !ptt->v[0] )  continue;
+    m  = matRef(sc,ptt->ref);
+    pm = &sc->material[m];
+    if ( pm->flag )  continue;
+    for (i=0; i<4; i++)
+      if ( !mesh->point[ptt->v[i]].tmp )  break;
+    if ( i < 4 )  continue;
+    ref = ptt->ref;
+    GmfSetLin(outm,GmfTetrahedra,mesh->point[ptt->v[0]].tmp,mesh->point[ptt->v[1]].tmp,
+              mesh->point[ptt->v[2]].tmp,mesh->point[ptt->v[3]].tmp,ref);
+  }
+
+  /* write hexahedra */
+
+  if ( !quiet ) {
+    fprintf(stdout,"     TOTAL NUMBER OF VERTICES   %8d\n",np);
+    fprintf(stdout,"     TOTAL NUMBER OF TRIANGLES  %8d\n",nt);
+    fprintf(stdout,"     TOTAL NUMBER OF QUADS      %8d\n",nq);
+    fprintf(stdout,"     TOTAL NUMBER OF TETRA      %8d\n",mesh->ntet);
+  }
+
+  GmfCloseMesh(outm);
+  return(1);
+}
+
+
+/* load solution (metric) */
+int loadSol(pMesh mesh,char *filename,int numsol) {
+  pSolution    sol;
+  double       dbuf[ GmfMaxTyp ];
+  float        fbuf[ GmfMaxTyp ];
+  double       m[6],lambda[3],eigv[3][3],vp[2][2];
+  int          inm,k,i,key,nel,size,type,iord,off,typtab[GmfMaxTyp],ver,dim;
+  char        *ptr,data[128];
+
+  strcpy(data,filename);
+  ptr = strstr(data,".mesh");
+  if ( ptr )  *ptr = '\0';
+  strcat(data,".solb");
+  if (!(inm = GmfOpenMesh(data,GmfRead,&ver,&dim)) ) {
+    ptr  = strstr(data,".sol");
+    *ptr = '\0';
+    strcat(data,".sol");
+    if (!(inm = GmfOpenMesh(data,GmfRead,&ver,&dim)) )
+      return(0);
+  }
+  if ( !quiet )  fprintf(stdout,"  Reading %s\n",data);
+
+  if ( dim != mesh->dim ) {
+    fprintf(stderr,"  %%%% Wrong dimension %d.\n",dim);
+    GmfCloseMesh(inm);
+    return(0);
+  }
+
+  nel = GmfStatKwd(inm,GmfSolAtVertices,&type,&size,typtab);
+  if ( nel ) {
+    if ( nel > mesh->np ) {
+      fprintf(stderr,"  %%%% Wrong number: %d Solutions discarded\n",nel-mesh->np);
+    }
+    mesh->typage = 2;
+    key = GmfSolAtVertices;
+  }
+  else {
+    mesh->typage = 1;
+    if ( mesh->dim == 2 && mesh->nt ) {
+      //if( mesh->nt){
+      nel = GmfStatKwd(inm,GmfSolAtTriangles,&type,&size,typtab);
+      if ( nel && nel != mesh->nt ) {
+        fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+        GmfCloseMesh(inm);
+        return(0);
+      }
+      key = GmfSolAtTriangles;
+    }
+    else if ( mesh->dim == 2 && mesh->nq ) {
+      nel = GmfStatKwd(inm,GmfSolAtQuadrilaterals,&type,&size,typtab);
+      if ( nel && nel != mesh->nq ) {
+        fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+        GmfCloseMesh(inm);
+        return(0);
+      }
+      key = GmfSolAtQuadrilaterals;
+    }
+    else if ( mesh->ntet ) {
+      nel = GmfStatKwd(inm,GmfSolAtTetrahedra,&type,&size,typtab);
+      if ( nel && nel != mesh->ntet ) {
+        fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+        GmfCloseMesh(inm);
+        return(0);
+      }
+      key = GmfSolAtTetrahedra;
+    }
+    else if ( mesh->nhex ) {
+      nel = GmfStatKwd(inm,GmfSolAtHexahedra,&type,&size,typtab);
+      if ( nel && nel != mesh->nhex ) {
+        fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+        GmfCloseMesh(inm);
+        return(0);
+      }
+      key = GmfSolAtHexahedra;
+    }
+  }
+  if ( !nel )  return(1);
+  if(ddebug) printf("numsol=%i, type=%i, size=%i\n",numsol,type,size); 
+  if ( numsol > type )  numsol = 1;
+  numsol--;
+  mesh->nbb    = nel;
+  mesh->bbmin  =  1.0e20;
+  mesh->bbmax  = -1.0e20;
+  if ( !zaldy2(mesh) ) {
+    GmfCloseMesh(inm);
+    return(0);
+  }
+  sol = mesh->sol;
+  sol->dim = dim;
+  sol->ver = ver;
+
+  off = 0;
+  for (i=0; i<numsol; i++) {
+    if(ddebug) printf("typtab[%i]=%i",i,typtab[i]); 
+    switch(typtab[i]) {
+      case GmfSca:  
+        off++; break;
+      case GmfVec:
+        off += sol->dim; break;
+      case GmfSymMat:
+        off += sol->dim*(sol->dim+1)/2;  break;
+    }
+  }
+  if(ddebug) printf("typtab[%i]=%i, off%i",i,typtab[i],off); 
+
+  GmfGotoKwd(inm,key);
+  if(ddebug) printf("numsol=%i,typtab[i]=%i\n",numsol,typtab[i]); 
+  switch(typtab[numsol]) {
+    case GmfSca:
+      if ( ddebug )  printf("   scalar field\n");
+      mesh->nfield = 1;
+      for (k=1; k<=nel; k++) {
+        if ( sol->ver == GmfFloat )
+          GmfGetLin(inm,key,fbuf);
+        else {
+          GmfGetLin(inm,key,dbuf);
+          for (i=0; i<GmfMaxTyp; i++)
+            fbuf[i] = dbuf[off+i];
+        }
+        mesh->sol[k].bb = fbuf[off];
+	if(ddebug) printf("valeur donneer %i %f\n",k,fbuf[off]);
+	if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+        if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+      }
+      break;
+
+    case GmfVec:
+      if ( ddebug )  printf("   vector field\n");
+      mesh->nfield = sol->dim;
+      for (k=1; k<=nel; k++) {
+	mesh->sol[k].bb = 0.0;
+        if ( sol->ver == GmfFloat )
+          GmfGetLin(inm,key,fbuf);
+        else {
+          GmfGetLin(inm,key,dbuf);
+          for (i=0; i<GmfMaxTyp; i++)
+            fbuf[i] = dbuf[off+i];
+        }
+        for (i=0; i<sol->dim; i++) {
+          mesh->sol[k].m[i] = fbuf[off+i];
+	  if(ddebug) printf("valeur donner %i composante %i %f\n",k,i,fbuf[off+i]);
+          mesh->sol[k].bb  += fbuf[off+i]*fbuf[off+i];
+        }
+        mesh->sol[k].bb = sqrt(mesh->sol[k].bb);
+        if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+        if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+      }
+      break;
+
+    case GmfSymMat:
+      if ( ddebug )  printf("   metric field\n");
+      mesh->nfield = sol->dim*(sol->dim+1) / 2;
+      for (k=1; k<=nel; k++) {
+        if ( sol->ver == GmfFloat )
+          GmfGetLin(inm,key,fbuf);
+        else {
+          GmfGetLin(inm,key,dbuf);
+          for (i=0; i<GmfMaxTyp; i++)
+            fbuf[i] = dbuf[off+i];
+        }
+        
+        if ( sol->dim == 2 ) {
+          for (i=0; i<3; i++)  
+            mesh->sol[k].m[i] = m[i] = fbuf[off+i];
+          iord = eigen2(m,lambda,vp);
+          mesh->sol[k].bb = min(lambda[0],lambda[1]);
+          if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+          if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+        }
+        else {
+          for (i=0; i<6; i++)  
+            mesh->sol[k].m[i] = fbuf[off+i];
+          mesh->sol[k].m[2] = fbuf[off+3];
+          mesh->sol[k].m[3] = fbuf[off+2];
+          for (i=0; i<6; i++)  m[i] = mesh->sol[k].m[i];
+          iord = eigenv(1,m,lambda,eigv);
+          if ( iord ) {
+            mesh->sol[k].bb = lambda[0];
+            mesh->sol[k].bb = max(mesh->sol[k].bb,lambda[1]);
+            mesh->sol[k].bb = max(mesh->sol[k].bb,lambda[2]);
+            if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+            if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+          }
+        }
+    }
+    break;
+  }
+
+  GmfCloseMesh(inm);
+  return(1);  
+}
+
+
diff --git a/src/medit/inout_morice.c b/src/medit/inout_morice.c
new file mode 100755
index 0000000..2fdb823
--- /dev/null
+++ b/src/medit/inout_morice.c
@@ -0,0 +1,1478 @@
+#include "medit.h"
+#include "libmesh5.h"
+#include "extern.h"
+#include "string.h"
+static  int debug=0;
+void getline_number(char *nature, int *nb){
+  char    data[256];
+  char   *tictac;
+ 
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+  if(tictac == NULL){
+    printf("problem in reading the number of %s\n",nature);
+    exit(1);
+  }
+  else{
+    //printf("tictac=%s\n",tictac);
+    *nb = atoi(tictac);
+    if(debug) fprintf(stdout,"Number of %s %i \n",nature,*nb);
+  }
+
+}
+
+void getline_1int(char *nature, int *nbint){
+  char    data[256];
+  char   *tictac;
+ 
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+  if(tictac == NULL){
+    printf("problem in reading the %s",nature);
+    exit(1);
+  }
+  
+  *nbint = atoi(tictac);
+}
+
+
+void getline_1intfirst(char *nature, int *nbint){
+  char    data[256];
+  char   *tictac;
+ 
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+  if(tictac == NULL){
+    fgets(data,256,stdin);
+    tictac = strtok(data," \n");
+  }
+  if(tictac == NULL){
+    printf("problem in reading the first %s",nature);
+    exit(1);
+  }
+  
+  *nbint = atoi(tictac);
+}
+
+
+void getline_popen_vertex(int ddim, double *c, int *ref){
+  char    data[256];
+  char   *tictac;
+  int     i;
+  int     lench;
+  char    keyseE[]="eE"; 
+  char    keyse[]="e"; 
+  float   res;
+  
+  fgets(data,256,stdin);
+  c[0]= strtod(data,&tictac);
+  //printf("valeur strtod c[0] %f c%sc \n",c[0], tictac);
+  for(i=1; i<ddim; i++ ) {
+    c[i]= strtod(tictac,&tictac);
+    //printf("valeur strtod c[i] %f c%sc \n",c[i], tictac);
+  }
+ 
+  /*
+  tictac = strtok(data," \n");
+  if(tictac == NULL) 
+    printf("problem in reading the vertices");
+  
+  for(i=0; i<ddim; i++ ) {
+    lench=strlen(tictac);
+    if( lench == strcspn(tictac,keyseE) ){
+      c[i] = atof(tictac);
+      //sscanf(tictac,"%f",&res);
+      //c[i]=res;
+      if(debug) printf("valeur atof c[i] %f c%sc \n",c[i], tictac);
+    }
+    else if( lench == strcspn(tictac,keyse) ){ 
+      sscanf(tictac,"%E",&c[i]);
+    }
+    else{
+      sscanf(tictac,"%e",&c[i]);
+    }
+    tictac = strtok(NULL," \n");
+  }
+  */
+  *ref = atoi(tictac); 
+
+  //fprintf(stdout,"sortie vertex fonction:= %i \n", *ref);
+}
+
+void getline_popen_firstvertex(int ddim, double *c, int *ref){
+  char    data[256];
+  char*   tictac;
+  char*   tictac2;
+  int     i;
+
+  fgets(data,256,stdin);
+  /*
+  tictac2 = strtok(data," \n");
+  if(tictac2 == NULL){
+    fgets(data,256,stdin);   
+    tictac2 = strtok(data," \n");
+  }
+ 
+  if(tictac2==NULL) printf("problem in reading the first vertices");
+  */
+  //printf("data=%s",data);
+  c[0]= strtod(data,&tictac);
+  //printf("first strtod c[0] %f c%sc \n",c[0], tictac);
+  for(i=1; i<ddim; i++ ) {
+    c[i]= strtod(tictac,&tictac);
+    //printf("first strtod c[i] %f c%sc \n",c[i], tictac);
+  }
+
+  *ref = atoi(tictac);
+  //fprintf(stdout,"sortie vertex fonction:= %i \n", *ref);
+}
+
+void getline_popen_elem(int ddim, int *v, int *ref){
+  char    data[256];
+  char   *tictac;
+  int     i;
+  
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+  if(tictac == NULL) printf("problem: in reading element");
+  
+  for(i=0; i<ddim; i++){
+    v[i] = atoi(tictac);
+    tictac = strtok(NULL," \n");
+  }
+ 
+  *ref = atoi(tictac);
+}
+
+void getline_popen_firstelem(int ddim, int *v, int *ref){
+  char    data[256];
+  char   *tictac;
+  int     i;
+  
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+
+  if(tictac == NULL){
+     fgets(data,256,stdin);
+     tictac = strtok(data," \n");
+  }
+
+  if(tictac == NULL) printf("problem in reading the first element");
+  
+  for(i=0; i<ddim; i++){
+    v[i] = atoi(tictac);
+    tictac = strtok(NULL," \n");
+  }
+ 
+  *ref = atoi(tictac);
+}
+
+void getline_popen_edge(int *v0, int *v1, int *ref){
+  char    data[256];
+  char   *tictac;
+  
+  
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+  if(tictac == NULL) printf("problem: in reading edges");
+  
+  *v0 = atoi(tictac);
+  tictac = strtok(NULL," \n");
+  
+  *v1 = atoi(tictac);
+  tictac = strtok(NULL," \n");
+
+ 
+  *ref = atoi(tictac);
+  //fprintf(stdout,"data edge valeur %i %i %i \n", *v0, *v1, *ref);
+}
+
+void getline_popen_firstedge(int *v0, int *v1, int *ref){
+  char    data[256];
+  char   *tictac;
+  
+  
+  fgets(data,256,stdin);
+ if(debug) fprintf(stdout,"data edge %s\n", data);
+  tictac = strtok(data," \n");
+  if(tictac == NULL){
+     fgets(data,256,stdin);
+     tictac = strtok(data," \n");
+  }
+
+  if(tictac == NULL) printf("problem: in reading first edges\n");
+  
+  *v0 = atoi(tictac);
+  tictac = strtok(NULL," \n");
+  
+  *v1 = atoi(tictac);
+  tictac = strtok(NULL," \n");
+ 
+  *ref = atoi(tictac);
+  //fprintf(stdout,"data edge valeur %i %i %i \n", *v0, *v1, *ref);
+  
+}
+
+void getline_popen_elemnoref(char* nature, int ddim, int *v){
+  char    data[256];
+  char   *tictac;
+  int     i;
+  
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+  if(tictac == NULL) printf("problem: in reading %s\n",nature);
+  
+  for(i=0; i<ddim; i++){
+    v[i] = atoi(tictac);
+    tictac = strtok(NULL," \n");
+  }
+  if(tictac != NULL) printf("problem: in reading %s\n",nature);
+}
+
+void getline_popen_firstelemnoref(char* nature, int ddim, int *v){
+  char    data[256];
+  char   *tictac;
+  int     i;
+  
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+
+  if(tictac == NULL){
+     fgets(data,256,stdin);
+     tictac = strtok(data," \n");
+  }
+
+  if(tictac == NULL) printf("problem in reading the first %s\n",nature);
+ 
+  for(i=0; i<ddim; i++){
+    v[i] = atoi(tictac);
+    tictac = strtok(NULL," \n");
+  }
+  //if(tictac != NULL) printf("problem: in reading the first %s\n",nature);
+}
+
+void getline_popen_firstdouble(char* nature, int ddim, double *v){
+  char    data[256];
+  char   *tictac;
+  int     i;
+  char*   tictac2;
+  
+  fgets(data,256,stdin);
+  
+  tictac2 = strtok(data," \n");
+
+  if(tictac2 == NULL){
+     fgets(data,256,stdin);
+  }
+  v[0]= strtod(data,&tictac);
+
+  for(i=1; i<ddim; i++ ) {
+    v[i]= strtod(tictac,&tictac);
+
+  }
+}
+
+void getline_popen_double(char* nature, int ddim, double *v){
+  char    data[256];
+  char   *tictac;
+  int     i;
+  int     lench;
+  char    keyseE[]="eE"; 
+  char    keyse[]="e"; 
+
+  fgets(data,256,stdin);
+  v[0]= strtod(data,&tictac);
+  for(i=1; i<ddim; i++ ) {
+    v[i]= strtod(tictac,&tictac);
+    //printf("v[i]= %f %s\n",v[i],tictac);
+  }
+}
+
+/**********************************/
+/*   function for loadsol_popen   */
+
+void read_TypeSizeTyptab(char* nature,int *type,int *size,int *typtab){
+
+  char    data[256];
+  char   *tictac;
+  int     i;
+  int    tmptype;
+  int    tmpsize;
+
+  fgets(data,256,stdin);
+  tictac = strtok(data," \n");
+  if(tictac == NULL) printf("problem: in reading %s",nature);
+
+  tmptype = atoi(tictac);
+  assert( tmptype <=GmfMaxTyp );
+
+  tictac = strtok(NULL," \n");
+  tmpsize=0;
+  for(i=0; i<tmptype; i++){
+    typtab[i] = atoi(tictac);
+    if(debug) printf("typtab[%i]=%i\n",i,typtab[i]);
+    tmpsize += typtab[i];  
+    tictac = strtok(NULL," \n");
+  }
+  
+  *size = tmpsize;
+  *type = tmptype;
+}
+
+int loadMesh_popen(pMesh mesh) {
+  pPoint      ppt;
+  pEdge       pr;
+  pTriangle   pt;
+  pQuad       pq;
+  pTetra      ptet;
+  pHexa       ph;
+  double      d,dp1,dp2,dp3,dn[3];
+  float      *n,fp1,fp2,fp3;
+  int         i,ia,ib,inm,ref,is,k,disc,nn,nt,nq;
+  char       *ptr,data[256];
+  /* Rajout popen*/
+  char       *tictac;
+  char       *natureread;
+  int        loopdebug;
+  int        vatn[2];
+  int        tvatn[3];
+  
+  
+  /* parse keywords */
+  mesh->np   = 0;
+  mesh->nt   = 0;
+  mesh->nq   = 0;
+  mesh->ntet = 0;
+  mesh->nhex = 0;
+  mesh->nc   = 0;
+  mesh->nr   = 0;
+  mesh->na   = 0;
+  mesh->nri  = 0;
+  mesh->nre  = 0;
+  mesh->nvn  = 0;
+  mesh->ntg  = 0;
+  mesh->ne = mesh->nt + mesh->nq + mesh->ntet + mesh->nhex;
+
+  //int tablecture[5];
+  //tablecture =
+  loopdebug = -1;
+
+  while( !feof(stdin) ){
+    fgets(data,256,stdin);
+    tictac = strtok(data," \n");
+    
+    loopdebug=loopdebug+1;
+    //fprintf(stdout,"%i: data %s \n",loopdebug,data);
+    //fprintf(stdout,"%i: tictac %s \n",loopdebug,tictac);
+    //fprintf(stdout,"%i: capture vertex %i\n",loopdebug,strcmp(tictac,"Vertices"));
+    
+    //fprintf(stdout,"%s\n",tictac);
+    if(tictac == NULL) continue;
+    
+    if( !strncmp(tictac,"MeshVersionFormatted",20) ){
+      /* read mesh format */
+      natureread="MeshVersionFormatted";
+      getline_number( natureread, &(mesh->ver) );
+
+      /*
+	 fgets(data,256,stdin);
+	 tictac = strtok(data," \n");
+	 //fprintf(stdout,"tictac= %s\n",tictac);
+	 if(tictac == NULL){
+	 printf("problem in reading the %s\n",natureread);
+	 exit(1);
+	 }
+	 else{
+	 mesh->ver = atoi(tictac);
+	 }
+	 fprintf(stdout,"reading format %s %i \n",natureread,mesh->ver);
+      */
+    }
+    else if( !strncmp(tictac,"Dimension",9) ){
+      /* read mesh dimension */
+      natureread="Dimension";
+      getline_number( natureread, &(mesh->dim) );
+      /*
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+	//fprintf(stdout,"tictac= %s\n",tictac);
+	
+	if(tictac == NULL){
+	printf("problem in reading the %s\n",natureread);
+	exit(1);
+	}
+	else{
+	mesh->dim = atoi(tictac);
+	if(debug) printf("%s %i\n",natureread,mesh->dim);
+	}
+       */
+      /*control of the dimension*/
+      if( (mesh->dim != 2) && (mesh->dim != 3) ){
+	printf("the dimension is not correct");
+      }
+     
+    }
+    else if( !strncmp(tictac,"Vertices",8) ){
+      /* read mesh vetices */
+      natureread="Vertices";
+      getline_number( natureread, &(mesh->np) );
+      /*
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+	if(tictac == NULL){
+	printf("problem in reading the number of %s\n",natureread);
+	exit(1);
+	}
+	else{
+	mesh->np = atoi(tictac);
+	if(debug) fprintf(stdout,"Number of  %s %i\n",natureread,mesh->np);
+	}
+      */
+      /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+      /*  Allocation of array of vertices  */
+      if ( ddebug ) printf("allocate %d points\n",mesh->np);
+      mesh->point = (pPoint)M_calloc(mesh->np+1,sizeof(Point),"zaldy1.point");
+      assert(mesh->point);
+      
+      /* read the first vertex */
+
+      k=1;
+      ppt = &mesh->point[k];
+      getline_popen_firstvertex(mesh->dim, ppt->c, &ref);
+     
+      ppt->ref = ref & 0x7fff;
+      ppt->tag = M_UNUSED;
+      
+
+      /* read the other vertices */ 
+      for (k=2; k<=mesh->np; k++) {
+	ppt = &mesh->point[k];
+	
+	getline_popen_vertex(mesh->dim, ppt->c, &ref);
+	//fprintf(stdout,"sortie vertex:= %i %i \n", k, ref);
+	ppt->ref = ref & 0x7fff;
+	ppt->tag = M_UNUSED;
+      }
+   
+    }
+    else if( !strncmp(tictac,"Triangles",9) ){
+      natureread="Triangles";
+      getline_number( natureread, &(mesh->nt) );
+      /*
+	fgets(data,256,stdin);      
+	tictac = strtok(data," \n");
+	if(tictac == NULL){
+	printf("problem in reading the number of triangles");
+	exit(1);
+	}
+	else{
+	mesh->nt = atoi(tictac);
+	}
+      */
+
+      /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+      /*  Allocation of array of triangles  */
+      if ( ddebug ) printf("allocate %d tria\n",mesh->nt);
+      mesh->tria = (pTriangle)M_calloc(mesh->nt+1,sizeof(Triangle),"zaldy1.tria");
+      assert(mesh->tria);
+
+      /* read the first triangle */
+  
+      k=1;
+      disc = 0;
+      pt = &mesh->tria[k];
+      getline_popen_firstelem( 3, pt->v, &ref);
+      
+      pt->ref  = ref & 0x7fff;
+      for (i=0; i<3; i++) {    
+	if ( pt->v[i] < 1 || pt->v[i] > mesh->np ) {
+	  disc++;
+	  pt->v[0] = 0;
+	  break;
+	}
+	else {
+	  ppt = &mesh->point[pt->v[i]];
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+    
+      
+      /* read mesh triangles */
+  
+      for (k=2; k<=mesh->nt; k++) {
+	pt = &mesh->tria[k];
+	getline_popen_elem( 3, pt->v, &ref);
+	
+	pt->ref  = ref & 0x7fff;
+	for (i=0; i<3; i++) {    
+	  if ( pt->v[i] < 1 || pt->v[i] > mesh->np ) {
+	    disc++;
+	    pt->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[pt->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+    }
+    else if( !strncmp(tictac,"Quadrilaterals",14) ){
+      natureread="Quadrilaterals";
+      getline_number( natureread, &(mesh->nq) );
+      /*
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+	if(tictac == NULL){
+	printf("problem in reading the number of Quadrilaterals");
+	exit(1);
+	}
+	else{
+	mesh->nq = atoi(tictac);
+      }
+      */
+      /****************/
+      /*  allocation  */
+      if ( ddebug ) printf("allocate %d quad\n",mesh->nq);
+      if ( mesh->nq ) {
+	mesh->quad = (pQuad)M_calloc(mesh->nq+1,sizeof(Quad),"zaldy1.quad");
+	assert(mesh->quad);
+      }
+
+      k=1;
+      pq = &mesh->quad[k];
+      getline_popen_firstelem( 4, pq->v, &ref);
+      pq->ref  = ref & 0x7fff;
+      for (i=0; i<4; i++) {    
+	if ( pq->v[i] < 1 || pq->v[i] > mesh->np ) {
+	  disc++;
+	  pq->v[0] = 0;
+	  break;
+	}
+	else {
+	  ppt = &mesh->point[pq->v[i]];
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+
+      for (k=2; k<=mesh->nq; k++) {
+	pq = &mesh->quad[k];
+	getline_popen_elem( 4, pq->v, &ref);
+	pq->ref  = ref & 0x7fff;
+
+	for (i=0; i<4; i++) {    
+	  if ( pq->v[i] < 1 || pq->v[i] > mesh->np ) {
+	    disc++;
+	    pq->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[pq->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+      
+    }
+    
+    else if( !strncmp(tictac,"Tetrahedra",10) ){
+      natureread="Tetrahedra";
+      getline_number( natureread, &(mesh->ntet) );
+      /*
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+	if(tictac == NULL){
+	printf("problem in reading the number of Tetrahedrons");
+	exit(1);
+	}
+	else{
+	mesh->ntet = atoi(tictac);
+	}
+      */
+      /******************************/
+      /*  allocation de la memoire  */
+      if ( mesh->ntet ) {
+	if ( ddebug ) printf("allocate %d tetra\n",mesh->ntet);
+	mesh->tetra = (pTetra)M_calloc(mesh->ntet+1,sizeof(Tetra),"zaldy1.tetra");
+	assert(mesh->tetra);
+      }
+
+      k=1;
+      //printf("valeur de k%i",k);
+      ptet = &mesh->tetra[k];
+      getline_popen_elem( 4, ptet->v, &ref);
+      //printf("valeur de k%i",k);
+      ptet->ref  = ref & 0x7fff;
+      for (i=0; i<4; i++) {    
+	if ( ptet->v[i] < 1 || ptet->v[i] > mesh->np ) {
+	  disc++;
+	  ptet->v[0] = 0;
+	  break;
+	}
+	else {
+	  ppt = &mesh->point[ptet->v[i]];
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+      
+      for (k=2; k<=mesh->ntet; k++) {
+	//printf("valeur de k%i",k);
+	ptet = &mesh->tetra[k];
+	getline_popen_elem( 4, ptet->v, &ref);
+	//printf("valeur de k%i",k);
+	ptet->ref  = ref & 0x7fff;
+	for (i=0; i<4; i++) {    
+	  if ( ptet->v[i] < 1 || ptet->v[i] > mesh->np ) {
+	    disc++;
+	    ptet->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[ptet->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+    }
+    /* mesh hexahedra */
+    else if( !strncmp(tictac,"Hexahedra",9) ){
+      natureread="Hexahedra";
+      getline_number( natureread, &(mesh->nhex) );
+      /*
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+	if(tictac == NULL){
+	printf("problem in reading the number of Hexahedrons");
+	exit(1);
+	}
+	else{
+	mesh->nhex = atoi(tictac);
+	//fprintf(stdout,"mesh->nbex %i \n",mesh->nbex);
+	}
+      */
+
+      /******************************/
+      /* allocation de la memoire   */      
+      if ( ddebug ) printf("allocate %d hexa\n",mesh->nhex);
+      mesh->hexa = (pHexa)M_calloc(mesh->nhex+1,sizeof(Hexa),"zaldy1.hexa");
+      assert(mesh->hexa);
+      
+
+      k=1;
+      ph = &mesh->hexa[k];
+      getline_popen_firstelem( 8, ph->v, &ref);
+           
+      ph->ref  = ref & 0x7fff;
+      for (i=0; i<8; i++) {    
+	if ( ph->v[i] < 1 || ph->v[i] > mesh->np ) {
+	  disc++;
+	  ph->v[0] = 0;
+	  break;
+	}
+	else {
+	  ppt = &mesh->point[ph->v[i]];
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+      
+ 
+      for (k=2; k<=mesh->nhex; k++) {
+	ph = &mesh->hexa[k];
+	getline_popen_elem( 8, ph->v, &ref);
+	
+	ph->ref  = ref & 0x7fff;
+	for (i=0; i<8; i++) {    
+	  if ( ph->v[i] < 1 || ph->v[i] > mesh->np ) {
+	    disc++;
+	    ph->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[ph->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+
+    }
+    
+    /* mesh corners */
+    else if( !strncmp(tictac,"Corners",7) ){
+      natureread="Corners";
+      getline_number( natureread, &(mesh->nc) );
+      /*
+      fgets(data,256,stdin);
+      tictac = strtok(data," \n");
+      if(tictac == NULL){
+	printf("problem in reading the number of Corners");
+	exit(1);
+      }
+      else{
+	mesh->nc = atoi(tictac);
+	fprintf(stdout,"Number of corners %i \n",mesh->nc);
+      }
+      */
+
+      fgets(data,256,stdin); 
+      if(tictac == NULL){
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+      }
+      if(tictac == NULL) printf("problem in reading the first corner");
+      tictac = strtok(data," \n");  is = atoi(tictac);
+      
+      if ( is < 1 || is > mesh->np )
+	disc++;
+      else {
+	ppt = &mesh->point[is];
+	ppt->tag |= M_CORNER;
+	ppt->tag &= ~M_UNUSED;
+      }
+      
+      for (k=2; k<=mesh->nc; k++) {
+	fgets(data,256,stdin);  tictac = strtok(data," \n");  is = atoi(tictac);
+	if ( is < 1 || is > mesh->np )
+	  disc++;
+	else {
+	  ppt = &mesh->point[is];
+	  ppt->tag |= M_CORNER;
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+    }
+    /* required vertices */
+    else if( !strncmp(tictac,"RequiredVertices",12) ){
+      natureread="RequiredVertices";
+      getline_number( natureread, &(mesh->nr) );
+      /*
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+	if(tictac == NULL){
+	printf("problem in reading the number of RequiredVertices");
+	exit(1);
+	}
+	else{
+	mesh->nr = atoi(tictac);
+	fprintf(stdout,"Number of RequiredVertices %i \n",mesh->nr);
+	}
+      */
+      
+      fgets(data,256,stdin); 
+      if(tictac == NULL){
+	fgets(data,256,stdin);
+	tictac = strtok(data," \n");
+      }
+      if(tictac == NULL) printf("problem in reading the first RequiredVertex");
+      tictac = strtok(data," \n");  is = atoi(tictac);
+    
+      if ( is < 1 || is > mesh->np )
+	disc++;
+      else {
+	ppt = &mesh->point[is];
+	ppt->tag |= M_REQUIRED;
+	ppt->tag &= ~M_UNUSED;
+      }
+     
+      for (k=2; k<=mesh->nr; k++) {
+       	fgets(data,256,stdin);  tictac = strtok(data," \n");  is = atoi(tictac);
+	if ( is < 1 || is > mesh->np )
+	  disc++;
+	else {
+	  ppt = &mesh->point[is];
+	  ppt->tag |= M_REQUIRED;
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+    }
+    /* mesh edges */
+    else if( !strncmp(tictac,"Edges",5) ){
+      natureread = "Edges";
+      getline_number( natureread, &( mesh->na ));
+      fprintf(stdout,"Number of %s %i \n",natureread,mesh->na);
+      /************************/
+      /*  allocation memoire  */
+      
+      if ( ddebug ) printf("allocate %d edges\n",mesh->na);
+      mesh->edge = (pEdge)M_calloc(mesh->na+1,sizeof(Edge),"zaldy1.edge");
+      assert(mesh->edge);
+      
+      k=1;
+      getline_popen_firstedge( &ia, &ib, &ref);
+      if ( ia < 1 || ia > mesh->np || ib < 1 || ib > mesh->np )
+	disc++;
+      else {
+	pr = &mesh->edge[k];
+	pr->v[0] = ia;
+	pr->v[1] = ib;
+	pr->ref  = ref & 0x7fff;
+	pr->tag  = !pr->ref ? M_NOTAG : M_TAG;
+	ppt = &mesh->point[ia];
+	ppt->tag &= ~M_UNUSED;
+	ppt = &mesh->point[ib];
+	ppt->tag &= ~M_UNUSED;
+      }
+
+
+      for (k=2; k<=mesh->na; k++) {
+	getline_popen_edge( &ia, &ib, &ref);
+	if ( ia < 1 || ia > mesh->np || ib < 1 || ib > mesh->np )
+	  disc++;
+	else {
+	  pr = &mesh->edge[k];
+	  pr->v[0] = ia;
+	  pr->v[1] = ib;
+	  pr->ref  = ref & 0x7fff;
+	  pr->tag  = !pr->ref ? M_NOTAG : M_TAG;
+	  ppt = &mesh->point[ia];
+	  ppt->tag &= ~M_UNUSED;
+	  ppt = &mesh->point[ib];
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+    }
+    /* mesh ridges */
+    else if( !strcmp(tictac,"Ridges") ){
+      natureread = "Ridges";
+      getline_number( natureread, &(mesh->nri) );
+      
+      getline_1intfirst( natureread, &is);  
+      if ( is < 1 || is > mesh->na )
+	disc++;
+      else {
+	pr = &mesh->edge[is];
+	pr->tag |= M_RIDGE;
+      }
+
+      for (k=2; k<=mesh->nri; k++) {
+	getline_1int( natureread, &is);
+	if ( is < 1 || is > mesh->na )
+	  disc++;
+	else {
+	  pr = &mesh->edge[is];
+	  pr->tag |= M_RIDGE;
+	}
+      }
+    }
+
+    /* required edges */
+    else if( !strncmp(tictac,"RequiredEdges",13) ){
+
+      natureread = "RequiredEdges";
+      getline_number( natureread, &(mesh->nre) );
+
+      getline_1intfirst( natureread, &is);
+      if ( is < 1 || is > mesh->na )
+	disc++;
+      else {
+	pr = &mesh->edge[is];
+	pr->tag |= M_REQUIRED;
+      }
+      
+      for (k=2; k<=mesh->nre; k++) {
+	getline_1int( natureread, &is);
+	if ( is < 1 || is > mesh->na )
+	  disc++;
+	else {
+	  pr = &mesh->edge[is];
+	  pr->tag |= M_REQUIRED;
+	}
+      }
+    }
+    /* mesh normals */
+    else if(!strncmp(tictac,"Normals",7)){
+      
+      natureread = "Normals";
+      getline_number( natureread, &(mesh->nvn) );
+      
+      /*****************/
+      /*  allocation  */ 
+      if ( !mesh->ntg ) {
+	mesh->extra = (pExtra)M_calloc(1,sizeof(Extra),"zaldy1.extra");
+	assert(mesh->extra);
+      }
+      
+      mesh->extra->n = (float*)M_calloc(3*mesh->nvn+1,sizeof(float),"inmesh");
+      assert(mesh->extra->n);
+    
+      k=1;
+      n = &mesh->extra->n[3*(k-1)+1];
+      getline_popen_firstdouble(natureread, 3, dn);
+ 
+      n[0] = dn[0];
+      n[1] = dn[1];
+      n[2] = dn[2]; 
+      d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+      if ( d > 0.0 ) {
+	d = 1.0 / sqrt(d);
+	n[0] *= d;
+	n[1] *= d;
+	n[2] *= d;
+      }
+
+      for (k=2; k<=mesh->nvn; k++) {
+	n = &mesh->extra->n[3*(k-1)+1];	
+	getline_popen_double(natureread, 3, dn); // modif FH 
+	n[0] = dn[0];
+	n[1] = dn[1];
+	n[2] = dn[2];
+	
+	d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+	if ( d > 0.0 ) {
+	  d = 1.0 / sqrt(d);
+	  n[0] *= d;
+	  n[1] *= d;
+	  n[2] *= d;
+	}
+      }
+    }
+    else if( !strncmp(tictac,"NormalAtVertices",16) ){
+      natureread ="NormalAtVertices";
+      if( !mesh->nvn ){
+	printf("The field Normal need to be reading before %s",natureread);
+	exit(1);
+      }
+      /* normals at vertices */
+      getline_number( natureread, &(	mesh->extra->iv ) );
+      mesh->extra->nv = (int*)M_calloc(mesh->np+1,sizeof(int),"inmesh");	
+      assert(mesh->extra->nv);	
+
+      k=1;
+      getline_popen_firstelemnoref(natureread, 2, vatn);
+      nn=vatn[0];
+      is=vatn[1];
+      if ( nn < 1 || nn > mesh->np )
+	disc++;
+      else
+	mesh->extra->nv[nn] = is;
+
+      for (k=2; k<=mesh->extra->iv; k++) {
+	//GmfGetLin(inm,GmfNormalAtVertices,&nn,&is);
+	getline_popen_elemnoref(natureread, 2, vatn);
+	nn=vatn[0];
+	is=vatn[1];
+	if ( nn < 1 || nn > mesh->np )
+	  disc++;
+	else
+	  mesh->extra->nv[nn] = is;
+      }
+    }
+    else if( !strncmp(tictac,"NormalAtTriangleVertices",24) ){
+      natureread ="NormalAtTriangleVertices";
+      if( !mesh->nvn ){
+	printf("The field Normal need to be reading before %s",natureread);
+	exit(1);
+      }
+      /* normals at triangle vertices */
+      getline_number( natureread, &(	mesh->extra->it ) );
+      mesh->extra->nt = (int*)M_calloc(3*mesh->nt+1,sizeof(int),"inmesh");
+      assert(mesh->extra->nt);
+	
+      k=1;
+      getline_popen_elemnoref(natureread, 3, tvatn);
+      //GmfGetLin(inm,GmfNormalAtTriangleVertices,&nt,&is,&nn);
+      tvatn[0] = nt;
+      tvatn[1] = is;
+      tvatn[2] = nn;
+	
+      if ( nt < 1 || nt > mesh->nt || is < 1 || is > 3 || nn < 1 || nn > mesh->nvn )
+	disc++;
+      else
+	mesh->extra->nt[3*(nt-1)+is] = nn;
+       
+      for (k=2; k<=mesh->extra->it; k++) {
+	getline_popen_elemnoref(natureread, 3, tvatn);
+	//GmfGetLin(inm,GmfNormalAtTriangleVertices,&nt,&is,&nn);
+	tvatn[0] = nt;
+	tvatn[1] = is;
+	tvatn[2] = nn;
+
+	if ( nt < 1 || nt > mesh->nt || is < 1 || is > 3 || nn < 1 || nn > mesh->nvn )
+	  disc++;
+	else
+	  mesh->extra->nt[3*(nt-1)+is] = nn;
+      }
+    }
+      
+    /*normals at quadrilateral vertices */
+    else if( !strncmp(tictac,"NormalAtQuadrilateralVertices",19) ){
+      natureread ="NormalAtQuadrilateralVertices";
+      if( !mesh->nvn ){
+	printf("The field Normal need to be reading before %s",natureread);
+	exit(1);
+      }
+      getline_number( natureread, &(	mesh->extra->iq ) );
+    
+      mesh->extra->nq = (int*)M_calloc(4*mesh->nq+1,sizeof(int),"inmesh");
+      assert(mesh->extra->nq);
+     
+      k=1;
+      getline_popen_firstelemnoref(natureread, 3, tvatn);
+      tvatn[0] = nq;
+      tvatn[1] = is;
+      tvatn[2] = nn;
+	
+      if ( nq < 1 || nq > mesh->nq || is < 1 || is > 4 || nn < 1 || nn > mesh->nvn )
+	disc++;
+      else
+	mesh->extra->nq[3*(nq-1)+is] = nn;
+	
+      for (k=2; k<=mesh->extra->iq; k++) {
+	//GmfGetLin(inm,GmfNormalAtQuadrilateralVertices,&nq,&is,&nn);
+	getline_popen_elemnoref(natureread, 3, tvatn);
+	tvatn[0] = nq;
+	tvatn[1] = is;
+	tvatn[2] = nn;
+
+	if ( nq < 1 || nq > mesh->nq || is < 1 || is > 4 || nn < 1 || nn > mesh->nvn )
+	  disc++;
+	else
+	  mesh->extra->nq[3*(nq-1)+is] = nn;
+      }	
+    }
+    
+    /*mesh tangents */
+    else if( !strncmp(tictac,"Tangents",8) ){ 
+    
+      natureread = "Tangents";
+      getline_number( natureread, &(mesh->ntg) );
+      
+      /*****************/
+      /*  allocation  */ 
+      if ( !mesh->nvn ) {
+	mesh->extra = (pExtra)M_calloc(1,sizeof(Extra),"zaldy1.extra");
+	assert(mesh->extra);
+      }
+     
+      mesh->extra->t = (float*)M_calloc(3*mesh->ntg+1,sizeof(float),"inmesh");
+      assert(mesh->extra->t);
+
+      k=1;
+
+      for (k=1; k<=mesh->ntg; k++) {
+	n = &mesh->extra->t[3*(k-1)+1];
+	
+	getline_popen_double(natureread, 3, dn);// modif FH
+	n[0] = dn[0];
+	n[1] = dn[1];
+	n[2] = dn[2];
+    
+	d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+	if ( d > 0.0 ) {
+	  d = 1.0 / sqrt(d);
+	  n[0] *= d;
+	  n[1] *= d;
+	  n[2] *= d;
+	}
+      }
+    }
+    /* tangent at vertices */
+    else if( !strncmp(tictac,"TangentAtVertices",17) ){
+      natureread = "TangentAtVertices";
+      if( !mesh->ntg ){
+	printf("The field Tangent need to be reading before %s",natureread);
+	exit(1);
+      }
+      getline_number( natureread, &(	mesh->extra->jv ) );
+      //mesh->extra->jv = GmfStatKwd(inm,GmfTangentAtVertices);
+      mesh->extra->tv = (int*)M_calloc(mesh->np+1,sizeof(int),"inmesh");
+      assert(mesh->extra->tv);
+      
+      k=1;
+      getline_popen_firstelemnoref(natureread, 2, vatn);
+      nn=vatn[0];
+      is=vatn[1];
+      if ( nn < 1 || nn > mesh->np )
+	disc++;
+      else
+	mesh->extra->tv[nn] = is;
+      
+      for (k=2; k<=mesh->extra->jv; k++) {
+	getline_popen_elemnoref(natureread, 2, vatn);
+	nn=vatn[0];
+	is=vatn[1];
+	//GmfGetLin(inm,GmfTangentAtVertices,&nn,&is);
+	if ( nn < 1 || nn > mesh->np )
+	  disc++;
+	else
+	  mesh->extra->tv[nn] = is;
+      }
+      
+    }
+
+    /* tangent at edge vertices */
+    else if( !strncmp(tictac,"TangentAtEdgeVertices",21) ){
+      natureread = "TangentAtEdgeVertices";
+      if( !mesh->ntg ){
+	printf("The field Tangent need to be reading before %s",natureread);
+	exit(1);
+      }
+      getline_number( natureread, &(	mesh->extra->je ) );
+      
+      mesh->extra->te = (int*)M_calloc(2*mesh->na+1,sizeof(int),"inmesh");
+      assert(mesh->extra->te);
+
+      k=1;
+      getline_popen_firstelemnoref(natureread, 3, tvatn);
+      nt=tvatn[0];
+      is=tvatn[1];
+      nn=tvatn[2];
+      if ( nt < 1 || nt > mesh->np || is < 1 || is > 2 || nn < 1 || nn > mesh->ntg )
+	disc++;
+      else
+	mesh->extra->te[3*(nt-1)+is] = is;
+      
+      for (k=2; k<=mesh->extra->je; k++) {
+	getline_popen_elemnoref(natureread, 3, tvatn);
+	nt=tvatn[0];
+	is=tvatn[1];
+	nn=tvatn[2];
+	//GmfGetLin(inm,GmfTangentAtEdgeVertices,&nt,&is,&nn);
+	if ( nt < 1 || nt > mesh->np || is < 1 || is > 2 || nn < 1 || nn > mesh->ntg )
+	  disc++;
+	else
+	  mesh->extra->te[3*(nt-1)+is] = is;
+      }
+    }
+
+    else if( !strncmp(tictac,"End",3) ||  !strncmp(tictac,"END",3) ){
+      if( ddebug ) printf("Reading of mesh file is finished");
+      break;
+    }
+    
+    
+  }
+  
+  /* check if vertices and elements found */
+  if ( !mesh->np ) {
+    fprintf(stdout,"  ## No vertex\n");
+    return(-1);
+  }
+  mesh->ne = mesh->nt + mesh->nq + mesh->ntet + mesh->nhex;
+
+  if ( disc > 0 ) {
+    fprintf(stdout,"  ## %d entities discarded\n",disc);
+  }
+  return(1);
+}
+
+/* function of lecture */
+
+int loadScaVecTen(pMesh mesh, int numsol, int dim, int ver, int nel, int type, int size, int * typtab, int key, char* natureread) {
+  pSolution    sol;
+  double       dbuf[ GmfMaxTyp ];
+  float        fbuf[ GmfMaxTyp ];
+  double       m[6],lambda[3],eigv[3][3],vp[2][2];
+  int          inm,k,i,iord,off;
+  char        *ptr,data[128];
+  double         ScaSol[1],VecSol[3],TenSol[9];
+
+  if ( numsol > type )  numsol = 1;
+  numsol--;
+  mesh->nbb    = nel;
+  mesh->bbmin  =  1.0e20;
+  mesh->bbmax  = -1.0e20;
+  if ( !zaldy2(mesh) ) {
+    return(0);
+  }
+  sol = mesh->sol;
+  sol->dim = dim;
+  sol->ver = ver;
+
+  off = 0;
+  for (i=0; i<numsol; i++) {
+    switch(typtab[i]) {
+      case GmfSca:
+        off++; break;
+      case GmfVec:
+        off += sol->dim; break;
+      case GmfSymMat:
+        off += sol->dim*(sol->dim+1)/2;  break;
+    }
+  }
+  
+  //printf("min= %f, max= %f\n",mesh->bbmin,mesh->bbmax);
+ 
+  switch(typtab[numsol]) {
+  case GmfSca:
+    mesh->nfield = 1;
+    for (k=1; k<=nel; k++) {
+      /*
+        if ( sol->ver == GmfFloat )
+	GmfGetLin(inm,key,fbuf);
+        else {
+	GmfGetLin(inm,key,dbuf);
+	for (i=0; i<GmfMaxTyp; i++)
+	fbuf[i] = dbuf[off+i];
+        }
+      */
+      getline_popen_firstdouble(natureread, 1, ScaSol);
+      mesh->sol[k].bb = ScaSol[0];
+      
+      if ( mesh->sol[k].bb < mesh->bbmin ) mesh->bbmin = mesh->sol[k].bb;
+      if ( mesh->sol[k].bb > mesh->bbmax ) mesh->bbmax = mesh->sol[k].bb;
+    }
+    break;
+
+  case GmfVec:
+    if ( ddebug )  printf("   vector field\n");
+    mesh->nfield = sol->dim;
+    for (k=1; k<=nel; k++) {
+      mesh->sol[k].bb = 0.0;
+      /*
+	if ( sol->ver == GmfFloat )
+	GmfGetLin(inm,key,fbuf);
+        else {
+	GmfGetLin(inm,key,dbuf);
+	for (i=0; i<GmfMaxTyp; i++)
+	fbuf[i] = dbuf[off+i];
+        }
+      */
+      getline_popen_firstdouble(natureread, sol->dim, VecSol);
+    
+      for (i=0; i<sol->dim; i++) {
+	fbuf[off+i] = VecSol[i];
+	//printf("solution vectorielle %i composante %i %f\n",k,i,VecSol[i]);
+      }
+      for (i=0; i<sol->dim; i++) {
+	mesh->sol[k].m[i] = fbuf[off+i];
+	mesh->sol[k].bb  += fbuf[off+i]*fbuf[off+i];
+      }
+      mesh->sol[k].bb = sqrt(mesh->sol[k].bb);
+      if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+      if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+    }
+    //printf("max= %f, min= %f",mesh->bbmin,mesh->bbmax);
+    break;
+
+  case GmfSymMat:
+    if ( ddebug )  printf("   metric field\n");
+    mesh->nfield = sol->dim*(sol->dim+1) / 2;
+    for (k=1; k<=nel; k++) {
+      /*
+	if ( sol->ver == GmfFloat )
+	GmfGetLin(inm,key,fbuf);
+        else {
+	GmfGetLin(inm,key,dbuf);
+	for (i=0; i<GmfMaxTyp; i++)
+	fbuf[i] = dbuf[off+i];
+        }
+      */
+      getline_popen_firstdouble(natureread, sol->dim*(sol->dim+1)/2, TenSol);
+      for (i=0; i<sol->dim*(sol->dim+1)/2; i++) {
+	fbuf[off+i] = TenSol[i];
+      }
+
+      if ( sol->dim == 2 ) {
+	for (i=0; i<3; i++)
+	  mesh->sol[k].m[i] = m[i] = fbuf[off+i];
+	iord = eigen2(m,lambda,vp);
+	mesh->sol[k].bb = min(lambda[0],lambda[1]);
+	if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+	if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+      }
+      else {
+	for (i=0; i<6; i++)
+	  mesh->sol[k].m[i] = fbuf[off+i];
+	mesh->sol[k].m[2] = fbuf[off+3];
+	mesh->sol[k].m[3] = fbuf[off+2];
+	for (i=0; i<6; i++)  m[i] = mesh->sol[k].m[i];
+	iord = eigenv(1,m,lambda,eigv);
+	if ( iord ) {
+	  mesh->sol[k].bb = lambda[0];
+	  mesh->sol[k].bb = max(mesh->sol[k].bb,lambda[1]);
+	  mesh->sol[k].bb = max(mesh->sol[k].bb,lambda[2]);
+	  if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+	  if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+	}
+     }
+    }
+    break;
+  }
+  
+  return(1);
+}
+
+/*load solution (metric) */
+int loadSol_popen(pMesh mesh,char *filename,int numsol) {
+  pSolution    sol;
+  double       dbuf[ GmfMaxTyp ];
+  float        fbuf[ GmfMaxTyp ];
+  double       m[6],lambda[3],eigv[3][3],vp[2][2];
+  int          inm,k,i,key,nel,size,type,iord,off,typtab[GmfMaxTyp],ver,dim;
+  char        *ptr,data[128];
+
+  // rajout pour popen
+  int       NumberofSolAT;
+  char*     tictac;
+  char       *natureread;
+  NumberofSolAT=0;
+
+  while( !feof(stdin) ){
+    //fprintf(stdout,"data= %s\n",data);
+    fgets(data,256,stdin);
+    tictac = strtok(data," \n");
+    if(tictac == NULL) continue;
+    //fprintf(stdout,"data= %s, tictac= %s\n",data,tictac);
+    if( !strncmp(tictac,"MeshVersionFormatted",20) ){
+      /* read mesh format */
+      natureread="MeshVersionFormatted";
+
+      tictac = strtok(NULL," \n");
+      printf("data= %s\n",data);
+      if(tictac == NULL){
+	printf(".sol: problem in reading the %s\n",natureread);
+	exit(1);
+      }
+      else{
+	ver = atoi(tictac);
+      }
+      if(debug) fprintf(stdout,".sol: reading format %s %i \n",natureread,ver);
+    }
+
+    if( !strncmp(tictac,"Dimension",9) ){
+      /* read mesh dimension */
+      natureread="Dimension";
+      tictac = strtok(NULL," \n");
+      printf("data= %s\n",data);
+      
+      if(tictac == NULL){
+	printf("problem in reading the %s\n",natureread);
+	exit(1);
+      }
+      else{
+	dim = atoi(tictac);
+	//if(debug) printf(".sol: %s %i (mesh)%i (lecture)%s \n",natureread,dim,mesh->dim,tictac);
+      }
+      /*control of the dimension*/
+      if ( dim != mesh->dim ) {
+	fprintf(stderr,"  %%%% Wrong dimension %d.\n",dim);
+	GmfCloseMesh(inm);
+	return(0);
+      }      
+    }
+
+    if( !strncmp(tictac,"SolAtVertices",13) ){
+      NumberofSolAT=NumberofSolAT+10;
+      natureread = "SolAtVertices";
+      fprintf(stdout,"data= %s\n",data);
+      getline_number( natureread, &(nel) );
+      fprintf(stdout,"nel %d, mesh->np %d  \n",nel,mesh->np);
+      if ( nel != mesh->np ) {
+	fprintf(stderr,"  %%%% Wrong number: %d Solutions discarded\n",nel-mesh->np);
+	return(0);
+      }
+      mesh->typage = 2;
+      key = GmfSolAtVertices;
+
+      /*  type,size,typetab  */  
+      read_TypeSizeTyptab( natureread, &type, &size, typtab);
+      printf("sol: %s; type %i; size%i;\n",natureread, type, size); 
+
+      /* Reading solutions*/
+      loadScaVecTen( mesh, 1, dim, ver, nel, type, size, typtab, key, natureread);
+    }
+
+
+    if( mesh->dim == 2 && mesh->nt ){
+      if( !strncmp(tictac,"SolAtTriangles",14) ){
+	NumberofSolAT=NumberofSolAT+1;
+	natureread = "SolAtTriangles";
+	fprintf(stdout,"data= %s\n",data);
+	getline_number( natureread, &(nel) );
+
+	if ( nel && nel != mesh->nt ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+	  return(0);
+        }
+
+	mesh->typage = 1;
+	key = GmfSolAtTriangles;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab( natureread, &type, &size, typtab);
+	printf("sol: %s; type %i; size%i;\n",natureread, type, size); 
+
+	/* Reading solutions*/
+	loadScaVecTen( mesh, 1, dim, ver, nel, type, size, typtab, key, natureread);
+      }
+    }
+
+    if( mesh->dim == 2 && mesh->nq ){
+      if( !strncmp(tictac,"SolAtQuadrilaterals",19) ){
+	NumberofSolAT=NumberofSolAT+1;
+	natureread = "SolAtQuadrilaterals";
+	fprintf(stdout,"data= %s\n",data);
+	getline_number( natureread, &(nel) );
+      
+	if ( nel && nel != mesh->nq ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+	  return(0);
+	}
+	
+	mesh->typage = 1;
+	key = GmfSolAtQuadrilaterals;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab( natureread, &type, &size, typtab);
+
+	/* Reading solutions*/
+	loadScaVecTen( mesh, 1, dim, ver, nel, type, size, typtab, key, natureread);
+      }
+    }
+
+    if( mesh->dim == 3 && mesh->ntet ){
+      if( !strncmp(tictac,"SolAtTetrahedra",15) ){
+	fprintf(stdout,"data= %s\n",data);
+	NumberofSolAT=NumberofSolAT+1;
+	natureread = "SolAtTetrahedra";
+	getline_number( natureread, &(nel) );
+
+	if ( nel && nel != mesh->ntet ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel); 
+	  return(0);
+	}
+	mesh->typage = 1;
+	key = GmfSolAtTetrahedra;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab( natureread, &type, &size, typtab);
+
+	/* Reading solutions*/
+	loadScaVecTen( mesh, 1, dim, ver, nel, type, size, typtab, key, natureread);
+
+      }
+    }
+
+    if( mesh->dim == 3 && mesh->nhex ){
+      if( !strncmp(tictac,"SolAtHexahedra",14) ){
+	fprintf(stdout,"data= %s\n",data);
+	NumberofSolAT=NumberofSolAT+1;
+	natureread = "SolAtHexahedra";
+	getline_number( natureread, &(nel) );
+
+	if ( nel && nel != mesh->nhex ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+	  GmfCloseMesh(inm);
+	  return(0);
+	}
+	mesh->typage = 1;
+	key = GmfSolAtHexahedra;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab( natureread, &type, &size, typtab);
+
+	/* Reading solutions*/
+	loadScaVecTen( mesh, 1, dim, ver, nel, type, size, typtab, key, natureread);
+      }
+    }
+    if( !strncmp(tictac,"End",3) ||  !strncmp(tictac,"END",3) ){
+      if( ddebug ) printf("Reading of mesh file is finished");
+      break;
+    }
+    
+  }
+  printf("NumberofSolAT %i\n",NumberofSolAT);
+  return(1);
+}
+
+
diff --git a/src/medit/inout_popenbinaire.c b/src/medit/inout_popenbinaire.c
new file mode 100644
index 0000000..3520152
--- /dev/null
+++ b/src/medit/inout_popenbinaire.c
@@ -0,0 +1,985 @@
+#include "medit.h"
+#include "libmesh5.h"
+#include "extern.h"
+#include "string.h"
+#ifdef WIN32
+#include <fcntl.h>
+#endif
+
+#define WrdSiz 4
+
+static int debug =0;
+void getline_bin_float_vertex(int ddim, double *c, int *ref){
+  int     i;
+  float   ff;
+  for(i=0; i<ddim; i++ ){
+    fread( (unsigned char *)&(ff) ,WrdSiz, 1, stdin);
+    c[i] = ff;
+  }
+  fread( (unsigned char *)&(*ref) ,WrdSiz, 1, stdin);   
+  
+
+}
+
+void getline_bin_double_vertex(int ddim, double *c, int *ref){
+  int     i;
+  
+  for(i=0; i<ddim; i++ ) 
+    fread( (unsigned char *)&(c[i]) ,WrdSiz, 2, stdin);   
+
+  fread( (unsigned char *)&(*ref) ,WrdSiz, 1, stdin);   
+  
+}
+
+void getline_bin_elem(int ddim, int *v, int *ref){
+  int     i;
+  
+  for(i=0; i<ddim; i++){
+    fread( (unsigned char *)&(v[i]) ,WrdSiz, 1, stdin);
+  }
+  fread( (unsigned char *)&(*ref) ,WrdSiz, 1, stdin);
+}
+
+
+void getline_bin_edge(int *v0, int *v1, int *ref){
+  fread( (unsigned char *)&(*v0) ,WrdSiz, 1, stdin);
+  fread( (unsigned char *)&(*v1) ,WrdSiz, 1, stdin);
+  fread( (unsigned char *)&(*ref) ,WrdSiz, 1, stdin);
+}
+
+
+void getline_bin_int_noref(int ddim, int *v){
+  int     i;
+   for(i=0; i<ddim; i++){
+    fread( (unsigned char *)&(v[i]) ,WrdSiz, 1, stdin);
+  }
+}
+
+void getline_bin_float_noref(int ddim, double *v){
+  int     i;
+  float  ff;
+  for(i=0; i<ddim; i++){
+    fread( (unsigned char *)&(ff) ,WrdSiz, 1, stdin);
+    if(debug)  printf("value of ff %f\n",ff);
+    v[i] = ff;
+  }
+}
+
+void getline_bin_double_noref(int ddim, double *v){
+  int     i;
+  for(i=0; i<ddim; i++){
+    fread( (unsigned char *)&(v[i]) ,WrdSiz, 2, stdin);
+  }
+}
+
+
+/**********************************/
+/*   function for loadsol_popen   */
+
+void read_TypeSizeTyptab_bin(int *type,int *size,int *typtab){
+
+  char    data[256];
+  char   *tictac;
+  int     i;
+  int    tmptype;
+  int    tmpsize;
+
+  fread( (unsigned char *)&(tmptype) ,WrdSiz, 1, stdin);
+  assert( tmptype <=GmfMaxTyp );
+
+  tmpsize=0;
+  for(i=0; i<tmptype; i++){
+    fread( (unsigned char *)&(typtab[i]) ,WrdSiz, 1, stdin);
+    //printf("typtab[%i]=%i\n",i,typtab[i]);
+    tmpsize += typtab[i];  
+  }
+  
+  *size = tmpsize;
+  *type = tmptype;
+}
+
+int loadMesh_popen_bin(pMesh mesh) {
+  pPoint      ppt;
+  pEdge       pr;
+  pTriangle   pt;
+  pQuad       pq;
+  pTetra      ptet;
+  pHexa       ph;
+  double      d,dp1,dp2,dp3,dn[3];
+  float      *n,fp1,fp2,fp3;
+  int         i,ia,ib,inm,ref,is,k,disc,nn,nt,nq;
+  char       *ptr,data[256];
+  /* Rajout popen*/
+  char       *tictac;
+  char       *natureread;
+  int        loopdebug;
+  int        vatn[2];
+  int        tvatn[3];
+ 
+  /* variable rajouter pour popen */
+  int retcode=0;
+  int cod;
+  int KwdCod;
+  int NulPos;
+  int NextKwdPos;
+  /* rajout */
+  float ftab[3];
+#ifdef WIN32
+  _setmode(fileno(stdin),O_BINARY);     
+#endif 
+  
+  /* parse keywords */
+  mesh->np   = 0;
+  mesh->nt   = 0;
+  mesh->nq   = 0;
+  mesh->ntet = 0;
+  mesh->nhex = 0;
+  mesh->nc   = 0;
+  mesh->nr   = 0;
+  mesh->na   = 0;
+  mesh->nri  = 0;
+  mesh->nre  = 0;
+  mesh->nvn  = 0;
+  mesh->ntg  = 0;
+  mesh->ne = mesh->nt + mesh->nq + mesh->ntet + mesh->nhex;
+
+
+  loopdebug = -1;
+  
+  // read code
+  fread( (unsigned char *)&cod ,WrdSiz, 1, stdin);
+  if(cod != 1 ){
+    printf("error in reading the binary file .meshb with popen\n");
+    exit(1);
+  }
+  fread( (unsigned char *)&(mesh->ver) ,WrdSiz, 1, stdin);
+  fread( (unsigned char *)&KwdCod ,WrdSiz, 1, stdin);
+  if(KwdCod != GmfDimension ){
+    printf("error in reading the binary file .meshb with popen\n");
+    exit(1);
+  }
+  fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+  fread( (unsigned char *)&(mesh->dim) ,WrdSiz, 1, stdin);
+  /*control of the dimension*/
+  if( (mesh->dim != 2) && (mesh->dim != 3) ){
+    printf("the dimension is not correct");
+  }
+ if(debug) printf("reading dimension %i \n",mesh->dim); 
+  while( !feof(stdin) ){
+
+    loopdebug=loopdebug+1;
+   
+    fread( (unsigned char *)&KwdCod ,WrdSiz, 1, stdin);
+
+    /* determination of KwdCod */
+    if(debug) printf("reading KwdCod %i %i\n",KwdCod,loopdebug);
+
+    switch (KwdCod){
+    
+    case GmfVertices :
+      natureread="Vertices";
+     if(debug)  printf("reading %s",natureread);
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->np) ,WrdSiz, 1, stdin);
+     if(debug)  printf(": number of vertices %i\n",mesh->np);
+   
+      if ( !mesh->np ) {
+	if(debug) fprintf(stdout,"  ## No vertex\n");
+ 	retcode=-1;
+	goto Lret; 
+      }
+      if ( ddebug ) printf("allocate %d points\n",mesh->np);
+      mesh->point = (pPoint)M_calloc(mesh->np+1,sizeof(Point),"zaldy1.point");
+      assert(mesh->point);
+      
+      for (k=1; k<=mesh->np; k++) {
+	//if(0) printf("lecture point du maillage k=%i np=%i ver=%i \n",k,mesh->np,mesh->ver);
+	ppt = &mesh->point[k];
+	
+	if(mesh->ver==GmfFloat)
+	  getline_bin_float_vertex(mesh->dim, ppt->c, &ref);
+	else
+	  getline_bin_double_vertex(mesh->dim, ppt->c, &ref);
+
+	ppt->ref = ref & 0x7fff;
+	ppt->tag = M_UNUSED;
+	
+      }
+      ppt = &mesh->point[k];
+
+      break;
+    case GmfTriangles :
+      natureread = "Triangles";
+      if(debug) printf("reading %s",natureread);
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nt) ,WrdSiz, 1, stdin);
+      if(debug)  printf(": number of triangles %i\n",mesh->nt);
+      if ( ddebug ) printf("allocate %d tria\n",mesh->nt);
+      mesh->tria = (pTriangle)M_calloc(mesh->nt+1,sizeof(Triangle),"zaldy1.tria");
+      assert(mesh->tria);
+
+      disc = 0;
+      for (k=1; k<=mesh->nt; k++) {
+	pt = &mesh->tria[k];
+	getline_bin_elem( 3, pt->v, &ref);
+	
+	pt->ref  = ref & 0x7fff;
+	for (i=0; i<3; i++) {    
+	  if ( pt->v[i] < 1 || pt->v[i] > mesh->np ) {
+	    disc++;
+	    pt->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[pt->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+      break;
+    case GmfQuadrilaterals :
+      natureread = "Quadrilateral";
+      if(debug) printf("reading %s",natureread);
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nq) ,WrdSiz, 1, stdin);
+      if(debug) printf(": number of hexahedrons %i\n",mesh->nq);
+
+      if ( ddebug ) printf("allocate %d quad\n",mesh->nq);
+      if ( mesh->nq ) {
+	mesh->quad = (pQuad)M_calloc(mesh->nq+1,sizeof(Quad),"zaldy1.quad");
+	assert(mesh->quad);
+      }
+
+      for (k=1; k<=mesh->nq; k++) {
+	pq = &mesh->quad[k];
+	getline_bin_elem( 4, pq->v, &ref);
+	pq->ref  = ref & 0x7fff;
+
+	for (i=0; i<4; i++) {    
+	  if ( pq->v[i] < 1 || pq->v[i] > mesh->np ) {
+	    disc++;
+	    pq->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[pq->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+      
+      break;
+    case GmfTetrahedra :
+      natureread = "Tetrahedra";
+      if(debug)  printf("reading %s",natureread);
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->ntet) ,WrdSiz, 1, stdin);
+      if(debug)  printf(": number of tetrahedrons %i\n",mesh->ntet);
+      if ( mesh->ntet ) {
+	if ( ddebug ) printf("allocate %d tetra\n",mesh->ntet);
+	mesh->tetra = (pTetra)M_calloc(mesh->ntet+1,sizeof(Tetra),"zaldy1.tetra");
+	assert(mesh->tetra);
+      }
+
+       for (k=1; k<=mesh->ntet; k++) {
+	ptet = &mesh->tetra[k];
+	getline_bin_elem( 4, ptet->v, &ref);
+	ptet->ref  = ref & 0x7fff;
+	for (i=0; i<4; i++) {    
+	  if ( ptet->v[i] < 1 || ptet->v[i] > mesh->np ) {
+	    disc++;
+	    ptet->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[ptet->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+
+      break;
+    case GmfHexahedra :
+      natureread = "Hexahedra";
+      if(debug)  printf("reading %s",natureread);
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nhex) ,WrdSiz, 1, stdin);
+     if(debug)  printf(": number of hexahedrons %i\n",mesh->nhex);
+
+      if ( ddebug ) printf("allocate %d hexa\n",mesh->nhex);
+      mesh->hexa = (pHexa)M_calloc(mesh->nhex+1,sizeof(Hexa),"zaldy1.hexa");
+      assert(mesh->hexa);
+            
+      for (k=1; k<=mesh->nhex; k++) {
+	ph = &mesh->hexa[k];
+	getline_bin_elem( 8, ph->v, &ref);
+	
+	ph->ref  = ref & 0x7fff;
+	for (i=0; i<8; i++) {    
+	  if ( ph->v[i] < 1 || ph->v[i] > mesh->np ) {
+	    disc++;
+	    ph->v[0] = 0;
+	    break;
+	  }
+	  else {
+	    ppt = &mesh->point[ph->v[i]];
+	    ppt->tag &= ~M_UNUSED;
+	  }
+	}
+      }
+      break;
+    case GmfCorners :
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nc) ,WrdSiz, 1, stdin);
+       
+      for (k=1; k<=mesh->nc; k++) {
+	fread( (unsigned char *)&is ,WrdSiz, 1, stdin);
+	//fgets(data,256,stdin);  tictac = strtok(data," \n");  is = atoi(tictac);
+	if ( is < 1 || is > mesh->np )
+	  disc++;
+	else {
+	  ppt = &mesh->point[is];
+	  ppt->tag |= M_CORNER;
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+      break;
+    case GmfRequiredVertices :
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nr) ,WrdSiz, 1, stdin);
+      for (k=1; k<=mesh->nr; k++) {
+       	//fgets(data,256,stdin);  tictac = strtok(data," \n");  is = atoi(tictac);
+	fread( (unsigned char *)&is ,WrdSiz, 1, stdin);
+	if ( is < 1 || is > mesh->np )
+	  disc++;
+	else {
+	  ppt = &mesh->point[is];
+	  ppt->tag |= M_REQUIRED;
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+      break;
+    case GmfEdges :
+      natureread="Edges";
+      if(debug)  printf("reading %s",natureread);
+      fread( (unsigned char *)&NulPos, WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->na), WrdSiz, 1, stdin);
+      if(debug)  printf(": number of edges %i\n",mesh->na);
+      if ( ddebug ) printf("allocate %d edges\n",mesh->na);
+      mesh->edge = (pEdge)M_calloc(mesh->na+1,sizeof(Edge),"zaldy1.edge");
+      assert(mesh->edge);
+
+      for (k=1; k<=mesh->na; k++) {
+	getline_bin_edge( &ia, &ib, &ref);
+	if ( ia < 1 || ia > mesh->np || ib < 1 || ib > mesh->np )
+	  disc++;
+	else {
+	  pr = &mesh->edge[k];
+	  pr->v[0] = ia;
+	  pr->v[1] = ib;
+	  pr->ref  = ref & 0x7fff;
+	  pr->tag  = !pr->ref ? M_NOTAG : M_TAG;
+	  ppt = &mesh->point[ia];
+	  ppt->tag &= ~M_UNUSED;
+	  ppt = &mesh->point[ib];
+	  ppt->tag &= ~M_UNUSED;
+	}
+      }
+      break;
+    case GmfRidges :
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nri) ,WrdSiz, 1, stdin);
+      
+      for (k=1; k<=mesh->nri; k++) {
+	//getline_1int( natureread, &is);
+	fread( (unsigned char *)&is, WrdSiz, 1, stdin);
+	if ( is < 1 || is > mesh->na )
+	  disc++;
+	else {
+	  pr = &mesh->edge[is];
+	  pr->tag |= M_RIDGE;
+	}
+      }
+
+      break;
+    case GmfRequiredEdges :
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nre) ,WrdSiz, 1, stdin);
+
+      for (k=2; k<=mesh->nre; k++) {
+	//getline_1int( natureread, &is);
+	fread( (unsigned char *)&is, WrdSiz, 1, stdin);
+	if ( is < 1 || is > mesh->na )
+	  disc++;
+	else {
+	  pr = &mesh->edge[is];
+	  pr->tag |= M_REQUIRED;
+	}
+      }
+
+      break;
+    case GmfNormals :
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->nvn) ,WrdSiz, 1, stdin);
+
+       /*  allocation  */ 
+      if ( !mesh->ntg ) {
+	mesh->extra = (pExtra)M_calloc(1,sizeof(Extra),"zaldy1.extra");
+	assert(mesh->extra);
+      }
+      
+      mesh->extra->n = (float*)M_calloc(3*mesh->nvn+1,sizeof(float),"inmesh");
+      assert(mesh->extra->n);
+
+      for (k=1; k<=mesh->nvn; k++) {
+	n = &mesh->extra->n[3*(k-1)+1];	
+
+	if(mesh->ver == GmfFloat)
+	  getline_bin_float_noref( 3, dn);
+	else
+	  getline_bin_double_noref( 3, dn);
+
+	n[0] = dn[0];
+	n[1] = dn[1];
+	n[2] = dn[2];
+	
+	d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+	if ( d > 0.0 ) {
+	  d = 1.0 / sqrt(d);
+	  n[0] *= d;
+	  n[1] *= d;
+	  n[2] *= d;
+	}
+      }
+    
+      break;
+    case GmfNormalAtVertices :
+      if(!mesh->nvn){
+	printf("The field Normal need to be reading before %s",natureread);
+	exit(1);
+      }
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->extra->iv) ,WrdSiz, 1, stdin);
+      mesh->extra->nv = (int*)M_calloc(mesh->np+1,sizeof(int),"inmesh");
+      assert(mesh->extra->nv);
+      
+      for (k=1; k<=mesh->extra->iv; k++) {
+	//GmfGetLin(inm,GmfNormalAtVertices,&nn,&is);
+	getline_bin_int_noref( 2, vatn);
+	nn=vatn[0];
+	is=vatn[1];
+	if ( nn < 1 || nn > mesh->np )
+	  disc++;
+	else
+	mesh->extra->nv[nn] = is;
+      }
+      break;
+    case GmfNormalAtTriangleVertices :
+      if(!mesh->nvn){
+	printf("The field Normal need to be reading before %s",natureread);
+	exit(1);
+      }
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->extra->it) ,WrdSiz, 1, stdin);
+      mesh->extra->nt = (int*)M_calloc(3*mesh->nt+1,sizeof(int),"inmesh");
+      assert(mesh->extra->nt);
+      
+      for (k=1; k<=mesh->extra->it; k++) {
+	//GmfGetLin(inm,GmfNormalAtTriangleVertices,&nt,&is,&nn);
+	getline_bin_int_noref( 3, tvatn);
+	tvatn[0] = nt;
+	tvatn[1] = is;
+	tvatn[2] = nn;
+
+	if ( nt < 1 || nt > mesh->nt || is < 1 || is > 3 || nn < 1 || nn > mesh->nvn )
+	  disc++;
+	else
+	  mesh->extra->nt[3*(nt-1)+is] = nn;
+      }
+      break;
+    case GmfNormalAtQuadrilateralVertices :
+      if(!mesh->nvn){
+	printf("The field Normal need to be reading before %s",natureread);
+	exit(1);
+      }
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->extra->iq) ,WrdSiz, 1, stdin);
+      mesh->extra->nq = (int*)M_calloc(4*mesh->nq+1,sizeof(int),"inmesh");
+      assert(mesh->extra->nq);
+      
+      for (k=1; k<=mesh->extra->iq; k++) {
+	//GmfGetLin(inm,GmfNormalAtQuadrilateralVertices,&nq,&is,&nn);
+	getline_bin_int_noref( 3, tvatn);
+	tvatn[0] = nq;
+	tvatn[1] = is;
+	tvatn[2] = nn;
+	if ( nq < 1 || nq > mesh->nq || is < 1 || is > 4 || nn < 1 || nn > mesh->nvn )
+	  disc++;
+	else
+	  mesh->extra->nq[3*(nq-1)+is] = nn;
+      }
+      break;
+    case GmfTangents :
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->ntg) ,WrdSiz, 1, stdin);
+      
+      if ( !mesh->nvn ) {
+	mesh->extra = (pExtra)M_calloc(1,sizeof(Extra),"zaldy1.extra");
+	assert(mesh->extra);
+      }
+     
+      mesh->extra->t = (float*)M_calloc(3*mesh->ntg+1,sizeof(float),"inmesh");
+      assert(mesh->extra->t);
+
+      for (k=1; k<=mesh->ntg; k++) {
+	n = &mesh->extra->t[3*(k-1)+1];
+	
+	if(mesh->ver == GmfFloat)
+	  getline_bin_float_noref( 3, dn);
+	else
+	  getline_bin_double_noref( 3, dn);
+
+	n[0] = dn[0];
+	n[1] = dn[1];
+	n[2] = dn[2];
+    
+	d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+	if ( d > 0.0 ) {
+	  d = 1.0 / sqrt(d);
+	  n[0] *= d;
+	  n[1] *= d;
+	  n[2] *= d;
+	}
+      }
+      break;
+    case GmfTangentAtVertices :
+      if( !mesh->ntg ){
+	printf("The field Tangent need to be reading before %s",natureread);
+	exit(1);
+      }
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->extra->tv) ,WrdSiz, 1, stdin);
+
+      mesh->extra->tv = (int*)M_calloc(mesh->np+1,sizeof(int),"inmesh");
+      assert(mesh->extra->tv);
+
+      for (k=1; k<=mesh->extra->jv; k++) {
+	getline_bin_int_noref( 2, vatn);
+	nn=vatn[0];
+	is=vatn[1];
+     
+	if ( nn < 1 || nn > mesh->np )
+	  disc++;
+	else
+	  mesh->extra->tv[nn] = is;
+      }
+
+      break;
+    case GmfTangentAtEdgeVertices :
+      if( !mesh->ntg ){
+	printf("The field Tangent need to be reading before %s",natureread);
+	exit(1);
+      }
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&(mesh->extra->je) ,WrdSiz, 1, stdin);
+
+      mesh->extra->te = (int*)M_calloc(2*mesh->na+1,sizeof(int),"inmesh");
+      assert(mesh->extra->te);
+
+      for (k=1; k<=mesh->extra->je; k++) {
+	getline_bin_int_noref( 3, tvatn);
+	nt=tvatn[0];
+	is=tvatn[1];
+	nn=tvatn[2];
+	
+	if ( nt < 1 || nt > mesh->np || is < 1 || is > 2 || nn < 1 || nn > mesh->ntg )
+	  disc++;
+	else
+	  mesh->extra->te[3*(nt-1)+is] = is;
+      }
+
+      break;
+    case GmfEnd :
+     
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      printf("End of mesh\n");
+      break;
+    default :
+      printf("This data KwdCod it is not taken in this version\n");
+      exit(1);
+      break;
+    }
+    
+    if(KwdCod == GmfEnd){
+      break;
+    }
+    /*
+      if( KwdCod == GmfVertices ){
+      }
+      else if(KwdCod == GmfTriangles){
+      }
+      else if(KwdCod == GmfQuadrilaterals){
+      }
+      else if(KwdCod == GmfTetrahedra){
+      }
+      else if(KwdCod == GmfHexahedra){
+      }
+      else if(KwdCod == GmfCorners){
+      }
+      else if(KwdCod == GmfRequiredVertices){
+      }
+      else if(KwdCod == GmfEdges){
+      }
+      else if(KwdCod == GmfRidges){
+      }
+      else if(KwdCod == GmfRequiredEdges){
+      }
+      else if(KwdCod == GmfNormals){
+      }
+      else if(KwdCod == GmfTangents){
+      }
+      else if(KwdCod == GmfEnd){
+      }
+      else{
+      printf("This data KwdCod it is not taken in this version\n");
+      exit(1);
+      }
+    */
+  }
+  
+  /* check if vertices and elements found */
+  if ( !mesh->np ) {
+    fprintf(stdout,"  ## No vertex\n");
+    retcode=-1;
+    goto Lret; 
+  }
+  mesh->ne = mesh->nt + mesh->nq + mesh->ntet + mesh->nhex;
+
+  if ( disc > 0 ) {
+    fprintf(stdout,"  ## %d entities discarded\n",disc);
+  }
+  retcode=1;
+
+ Lret:
+#ifdef WIN32
+  _setmode(fileno(stdin),O_TEXT);     
+#endif 
+return retcode;
+}
+
+/* function of lecture */
+
+int loadScaVecTen_bin(pMesh mesh, int numsol, int dim, int ver, int nel, int type, int size, int * typtab, int key) {
+  pSolution    sol;
+  double       dbuf[ GmfMaxTyp ];
+  float        fbuf[ GmfMaxTyp ];
+  double       m[6],lambda[3],eigv[3][3],vp[2][2];
+  int          inm,k,i,iord,off;
+  char        *ptr,data[128];
+  double       ScaSol[1],VecSol[3],TenSol[9];
+  float        fScaSol[1],fVecSol[3],fTenSol[9];
+  int retcode=0;
+
+  if(ddebug) printf("numsol=%i, type=%i, size=%i\n",numsol,type,size); 
+  if ( numsol > type )  numsol = 1;
+  numsol--;
+  mesh->nbb    = nel;
+  mesh->bbmin  =  1.0e20;
+  mesh->bbmax  = -1.0e20;
+  if ( !zaldy2(mesh) ) {
+    retcode=0;
+  }
+  sol = mesh->sol;
+  sol->dim = dim;
+  sol->ver = ver;
+
+  off = 0;
+  for (i=0; i<numsol; i++) {
+    if(ddebug) printf("typtab[%i]=%i",i,typtab[i]); 
+    switch(typtab[i]) {
+      case GmfSca:
+        off++; break;
+      case GmfVec:
+        off += sol->dim; break;
+      case GmfSymMat:
+        off += sol->dim*(sol->dim+1)/2;  break;
+    }
+  }
+  if(ddebug) printf("typtab[%i]=%i, off%i",i,typtab[i],off); 
+  //printf("min= %f, max= %f\n",mesh->bbmin,mesh->bbmax);
+ 
+  if(ddebug) printf("numsol=%i,typtab[i]=%i\n",numsol,typtab[i]); 
+  fflush(stdout);
+  switch(typtab[numsol]) {
+  case GmfSca:
+    mesh->nfield = 1;
+    
+    for (k=1; k<=nel; k++) {
+      //   reading data must be a double !
+      getline_bin_double_noref(1, ScaSol);
+      mesh->sol[k].bb = ScaSol[0];
+      
+      if ( mesh->sol[k].bb < mesh->bbmin ) mesh->bbmin = mesh->sol[k].bb;
+      if ( mesh->sol[k].bb > mesh->bbmax ) mesh->bbmax = mesh->sol[k].bb;
+    }
+    break;
+
+  case GmfVec:
+    if ( ddebug )  printf("   vector field\n");
+    mesh->nfield = sol->dim;
+
+    for (k=1; k<=nel; k++) {
+      //   reading data must be a double ! 
+      mesh->sol[k].bb = 0.0;      
+      getline_bin_double_noref( sol->dim, VecSol);
+      
+      for (i=0; i<sol->dim; i++) {
+	fbuf[off+i] = VecSol[i];
+	//printf("solution vectorielle %i composante %i %f\n",k,i,VecSol[i]);
+      }
+      
+      for (i=0; i<sol->dim; i++) {
+	mesh->sol[k].m[i] = fbuf[off+i];
+	mesh->sol[k].bb  += fbuf[off+i]*fbuf[off+i];
+      }
+      mesh->sol[k].bb = sqrt(mesh->sol[k].bb);
+      if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+      if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+    }
+    
+    //printf("max= %f, min= %f",mesh->bbmin,mesh->bbmax);
+    break;
+
+  case GmfSymMat:
+    if ( ddebug )  printf("   metric field\n");
+    mesh->nfield = sol->dim*(sol->dim+1) / 2;
+    
+    
+    for (k=1; k<=nel; k++) {
+      // reading data must be double !!! 
+      getline_bin_double_noref(sol->dim*(sol->dim+1)/2, TenSol);
+     
+      for (i=0; i<sol->dim*(sol->dim+1)/2; i++) {
+	fbuf[off+i] = TenSol[i];
+      }
+      
+      if ( sol->dim == 2 ) {
+	for (i=0; i<3; i++)
+	  mesh->sol[k].m[i] = m[i] = fbuf[off+i];
+	iord = eigen2(m,lambda,vp);
+	mesh->sol[k].bb = min(lambda[0],lambda[1]);
+	if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+	if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+      }
+      else {
+	for (i=0; i<6; i++)
+	  mesh->sol[k].m[i] = fbuf[off+i];
+	mesh->sol[k].m[2] = fbuf[off+3];
+	mesh->sol[k].m[3] = fbuf[off+2];
+	for (i=0; i<6; i++)  m[i] = mesh->sol[k].m[i];
+	iord = eigenv(1,m,lambda,eigv);
+	if ( iord ) {
+	  mesh->sol[k].bb = lambda[0];
+	  mesh->sol[k].bb = max(mesh->sol[k].bb,lambda[1]);
+	  mesh->sol[k].bb = max(mesh->sol[k].bb,lambda[2]);
+	  if ( mesh->sol[k].bb < mesh->bbmin )  mesh->bbmin = mesh->sol[k].bb;
+	  if ( mesh->sol[k].bb > mesh->bbmax )  mesh->bbmax = mesh->sol[k].bb;
+	}
+      }
+    }
+    
+    break;
+  }
+  retcode=1;
+  
+  return retcode;
+}
+
+/*load solution (metric) */
+int loadSol_popen_bin(pMesh mesh,char *filename,int numsol) {
+  pSolution    sol;
+  double       dbuf[ GmfMaxTyp ];
+  float        fbuf[ GmfMaxTyp ];
+  double       m[6],lambda[3],eigv[3][3],vp[2][2];
+  int          inm,k,i,key,nel,size,type,iord,off,typtab[GmfMaxTyp],ver,dim;
+  char        *ptr,data[128];
+
+  // rajout pour popen
+  int       NumberofSolAT;
+  char       *natureread;
+  // rajout binaire
+  int       KwdCod;
+  int       cod;
+  int       NulPos;
+  int retcode=0;
+  NumberofSolAT=0;
+#ifdef WIN32
+  _setmode(fileno(stdin),O_BINARY);     
+#endif
+  // read code
+  fread( (unsigned char *)&cod ,WrdSiz, 1, stdin);
+  if(cod != 1 ){
+    printf("error in reading the binary file .meshb with popen\n");
+    exit(1);
+  }
+
+  fread( (unsigned char *)&ver ,WrdSiz, 1, stdin);
+  fread( (unsigned char *)&KwdCod ,WrdSiz, 1, stdin);
+  if(KwdCod != GmfDimension ){
+    printf("error in reading the binary file .meshb with popen\n");
+    exit(1);
+  }
+
+  fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+  fread( (unsigned char *)&dim ,WrdSiz, 1, stdin);
+  natureread="Dimension";
+  printf(".sol: %s %i (mesh)%i (lecture)%i \n",natureread,dim,mesh->dim,ver);
+  /*control of the dimension*/
+  if( dim != mesh->dim ){
+    fprintf(stderr,"  %%%% Wrong dimension %d.\n",dim);
+    retcode=0;
+    goto Lret; 
+    //    return(0);
+  }
+
+  while( !feof(stdin) ){
+   
+    fread( (unsigned char *)&KwdCod ,WrdSiz, 1, stdin);
+   
+    if(KwdCod == GmfSolAtVertices){   
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      fread( (unsigned char *)&nel ,WrdSiz, 1, stdin);
+      natureread = "SolAtVertices";
+      if(debug) fprintf(stdout,"SolAtVertices : nel %i, mesh->np %i \n",nel,mesh->np);
+      
+      if ( nel != mesh->np ) {
+	fprintf(stderr,"  %%%% Wrong number: %d Solutions discarded\n",nel-mesh->np);
+	retcode=0;
+	goto Lret; 
+	//	return(0);
+      }
+      mesh->typage = 2;
+      key = GmfSolAtVertices;
+
+      /*  type,size,typetab  */  
+      read_TypeSizeTyptab_bin( &type, &size, typtab);
+      if(debug) printf("sol: %s; type %i; size%i;\n",natureread, type, size); 
+      fflush(stdout);
+      /* Reading solutions*/
+      loadScaVecTen_bin( mesh, 1, dim, ver, nel, type, size, typtab, key);
+    }
+    
+    if( mesh->dim == 2 && mesh->nt ){
+      if(KwdCod == GmfSolAtTriangles){
+	natureread = "SolAtTriangles";
+	fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+	fread( (unsigned char *)&nel ,WrdSiz, 1, stdin);
+	if(debug) printf(stdout,"SolAtTriangles : nel %d, mesh->nt %d \n",nel,mesh->nt);
+	if ( nel && nel != mesh->nt ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+	  retcode=0;
+	  goto Lret; 
+	  // return(0);
+        }
+
+	mesh->typage = 1;
+	key = GmfSolAtTriangles;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab_bin( &type, &size, typtab);
+	printf("sol: %s; type %i; size%i;\n",natureread, type, size); 
+
+	/* Reading solutions*/
+	loadScaVecTen_bin( mesh, 1, dim, ver, nel, type, size, typtab, key);
+
+      }
+      
+    }
+
+    if( mesh->dim == 2 && mesh->nq ){
+      if( KwdCod == GmfSolAtQuadrilaterals ){	
+	natureread = "SolAtQuadrilaterals";
+	fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+	fread( (unsigned char *)&nel ,WrdSiz, 1, stdin);
+	if(debug)  fprintf(stdout,"SolAtQuadrilaterals : nel %i, mesh->nq %i \n",nel,mesh->nq);
+	if ( nel && nel != mesh->nq ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+	  retcode=0;
+	  goto Lret; 
+	  //return(0);
+	}
+	
+	mesh->typage = 1;
+	key = GmfSolAtQuadrilaterals;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab_bin( &type, &size, typtab);
+
+	/* Reading solutions*/
+	loadScaVecTen_bin( mesh, 1, dim, ver, nel, type, size, typtab, key);
+      }
+    }
+
+    if( mesh->dim == 3 && mesh->ntet ){
+      if( KwdCod == GmfSolAtTetrahedra ){
+	natureread = "SolAtTetrahedra";
+	fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+	fread( (unsigned char *)&nel ,WrdSiz, 1, stdin);
+	if(debug)  fprintf(stdout,"SolAtTetrahedra : nel %i, mesh->ntet %i \n",nel,mesh->ntet);
+	if ( nel && nel != mesh->ntet ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel); 
+	  retcode=0;
+	  goto Lret; 
+	  //return(0);
+	}
+	mesh->typage = 1;
+	key = GmfSolAtTetrahedra;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab_bin( &type, &size, typtab);
+
+	/* Reading solutions */
+	loadScaVecTen_bin( mesh, 1, dim, ver, nel, type, size, typtab, key);
+
+      }
+    }
+
+    if( mesh->dim == 3 && mesh->nhex ){
+      if(  KwdCod == GmfSolAtHexahedra ){
+	natureread = "SolAtHexahedra";
+	fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+	fread( (unsigned char *)&nel ,WrdSiz, 1, stdin);
+	if(debug)  fprintf(stdout,"SolAtHexahedra : nel %d, mesh->nhex %d \n",nel,mesh->nhex);
+	if ( nel && nel != mesh->nhex ) {
+	  fprintf(stderr,"  %%%% Wrong number %d.\n",nel);
+	  GmfCloseMesh(inm);
+	  retcode=0;
+	  goto Lret; 
+	  //return(0);
+	}
+	mesh->typage = 1;
+	key = GmfSolAtHexahedra;
+
+	/*  type,size,typetab  */  
+	read_TypeSizeTyptab_bin( &type, &size, typtab);
+
+	/* Reading solutions*/
+	loadScaVecTen_bin( mesh, 1, dim, ver, nel, type, size, typtab, key);
+      }
+    }
+    if( KwdCod == GmfEnd ){
+      fread( (unsigned char *)&NulPos ,WrdSiz, 1, stdin);
+      if(debug)  printf("End of solution\n");
+      if( ddebug ) printf("Reading of mesh file is finished");
+      break;
+    }    
+  }
+  retcode=1;
+ Lret:
+#ifdef WIN32
+  _setmode(fileno(stdin),O_BINARY);     
+#endif 
+  return(retcode);
+}
+
+
diff --git a/src/medit/items.c b/src/medit/items.c
new file mode 100644
index 0000000..63c2ae5
--- /dev/null
+++ b/src/medit/items.c
@@ -0,0 +1,478 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+void drawRulers(pScene sc) {
+  pMesh  mesh = cv.mesh[sc->idmesh];
+  
+  if ( ddebug ) printf("draw rulers\n");
+  
+  glPushMatrix();
+  glTranslatef(-mesh->xtra,-mesh->ytra,-mesh->ztra);
+  glColor3fv(sc->par.line);
+  glEnable(GL_LINE_STIPPLE);
+  glLineStipple(1,0x0444);
+  glLineWidth(2.);
+  glBegin(GL_LINES);
+    glVertex3f(mesh->xmin,mesh->ymin,mesh->zmin);
+    glVertex3f(mesh->xmax,mesh->ymin,mesh->zmin);
+    glVertex3f(mesh->xmin,mesh->ymax,mesh->zmin);
+    glVertex3f(mesh->xmax,mesh->ymax,mesh->zmin);
+    glVertex3f(mesh->xmin,mesh->ymin,mesh->zmin);
+    glVertex3f(mesh->xmin,mesh->ymax,mesh->zmin);
+    glVertex3f(mesh->xmax,mesh->ymin,mesh->zmin);
+    glVertex3f(mesh->xmax,mesh->ymax,mesh->zmin);
+
+    glVertex3f(mesh->xmin,mesh->ymin,mesh->zmax);
+    glVertex3f(mesh->xmax,mesh->ymin,mesh->zmax);
+    glVertex3f(mesh->xmin,mesh->ymax,mesh->zmax);
+    glVertex3f(mesh->xmax,mesh->ymax,mesh->zmax);
+    glVertex3f(mesh->xmin,mesh->ymin,mesh->zmax);
+    glVertex3f(mesh->xmin,mesh->ymax,mesh->zmax);
+    glVertex3f(mesh->xmax,mesh->ymin,mesh->zmax);
+    glVertex3f(mesh->xmax,mesh->ymax,mesh->zmax);
+
+    glVertex3f(mesh->xmin,mesh->ymin,mesh->zmin);
+    glVertex3f(mesh->xmin,mesh->ymin,mesh->zmax);
+    glVertex3f(mesh->xmin,mesh->ymax,mesh->zmin);
+    glVertex3f(mesh->xmin,mesh->ymax,mesh->zmax);
+    glVertex3f(mesh->xmax,mesh->ymin,mesh->zmin);
+    glVertex3f(mesh->xmax,mesh->ymin,mesh->zmax);
+    glVertex3f(mesh->xmax,mesh->ymax,mesh->zmin);
+    glVertex3f(mesh->xmax,mesh->ymax,mesh->zmax);
+  glEnd();
+  glLineWidth(1.);
+  glDisable(GL_LINE_STIPPLE);
+  glPopMatrix();
+
+}
+
+void drawAxis(pScene sc,int dim) {
+  pMesh  mesh;
+
+  /* default */
+  if ( ddebug ) printf("draw axis\n");
+  mesh = cv.mesh[sc->idmesh];
+
+  glPushMatrix();
+  glTranslatef(1.01*(mesh->xmin-mesh->xtra),
+               1.01*(mesh->ymin-mesh->ytra),
+               1.01*(mesh->zmin-mesh->ztra));
+  glScalef(0.6*sc->dmin,0.6*sc->dmin,0.6*sc->dmin);
+  glLineWidth(max(2,sc->par.linewidth));
+  glColor3f(1.0,0.,0.);
+  if ( mesh->dim == 2 ) {
+    glBegin(GL_LINE_STRIP);
+    glVertex2f(0.0, 0.0);
+    glVertex2f(1.0, 0.0);
+    glVertex2f(0.95, 0.01);
+    glVertex2f(0.95, -0.01);
+    glVertex2f(1.0, 0.0);
+    glEnd();
+    glBegin(GL_LINE_STRIP);
+    glVertex2f(0.0, 0.0);
+    glVertex2f(0.0, 1.0);
+    glVertex2f(-0.01, 0.95);
+    glVertex2f(0.01, 0.95);
+    glVertex2f(0.0, 1.0);
+    glEnd();
+  
+    /*glColor3f(0.0f,1.0f,0.0f);*/
+    glColor3f(1.-sc->par.back[0],1.0-sc->par.back[1],1.0-sc->par.back[2]);
+    glRasterPos3f(1.02, 0.0, 0.0);
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'x');
+    glRasterPos3f(0.0, 1.02, 0.0);
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'y');
+  }
+  else {
+    glBegin(GL_LINE_STRIP);
+    glVertex3f(0.0, 0.0, 0.0);
+    glVertex3f(1.0, 0.0, 0.0);
+    glVertex3f(0.95, 0.01, 0.0);
+    glVertex3f(0.95, -0.01, 0.0);
+    glVertex3f(1.0, 0.0, 0.0);
+    glVertex3f(0.95, 0.0, 0.01);
+    glVertex3f(0.95, 0.0, -0.01);
+    glVertex3f(1.0, 0.0, 0.0);
+    glEnd();
+    glBegin(GL_LINE_STRIP);
+    glVertex3f(0.0, 0.0, 0.0);
+    glVertex3f(0.0, 1.0, 0.0);
+    glVertex3f(0.0, 0.95, 0.01);
+    glVertex3f(0.0, 0.95, -0.01);
+    glVertex3f(0.0, 1.0, 0.0);
+    glVertex3f(0.01, 0.95, 0.0);
+    glVertex3f(-0.01, 0.95, 0.0);
+    glVertex3f(0.0, 1.0, 0.0);
+    glEnd();
+    glBegin(GL_LINE_STRIP);
+    glVertex3f(0.0, 0.0, 0.0);
+    glVertex3f(0.0, 0.0, 1.0);
+    glVertex3f(0.01, 0.0, 0.95);
+    glVertex3f(-0.01, 0.0, 0.95);
+    glVertex3f(0.0, 0.0, 1.0);
+    glVertex3f(0.0, 0.01, 0.95);
+    glVertex3f(0.0, -0.01, 0.95);
+    glVertex3f(0.0, 0.0, 1.0);
+    glEnd();
+    
+    /*glColor3f(0.0f,1.0f,0.0f);*/
+    glColor3f(1.-sc->par.back[0],1.0-sc->par.back[1],1.0-sc->par.back[2]);
+    glRasterPos3f(1.02, 0.0, 0.0);
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'x');
+    glRasterPos3f(0.0, 1.02, 0.0);
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'y');
+    glRasterPos3f(0.0, 0.0, 1.02);
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12,'z');
+  }
+  
+  glLineWidth(1.0);
+  glPopMatrix();
+}
+
+
+void drawBox(pScene sc,pMesh mesh,int mode) {
+  pMaterial  pm;
+  float      cx,cy,cz;
+  int        i,k,m;
+
+  glDisable(GL_LIGHTING);
+  glPushMatrix();
+  glScalef(1.01 * fabs(mesh->xmax-mesh->xmin),
+           1.01 * fabs(mesh->ymax-mesh->ymin),
+           1.01 * fabs(mesh->zmax-mesh->zmin));
+  glColor3f(1.0,0.0,0.5);
+  glutWireCube(1.0);
+  glPopMatrix();
+
+  /* one box per sub-domain */
+  if ( mode ) {
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      for (i=0; i<MAX_LIST; i++) {
+        k  = pm->depmat[i];
+        if ( !k || pm->flag )  continue;
+        cx = 0.5 * (pm->ext[3]+pm->ext[0]);
+        cy = 0.5 * (pm->ext[4]+pm->ext[1]);
+        cz = 0.5 * (pm->ext[5]+pm->ext[2]);
+        glPushMatrix();
+        glColor3fv(pm->dif);
+        glTranslatef(cx,cy,cz);
+        glScalef(pm->ext[3]-pm->ext[0],pm->ext[4]-pm->ext[1],
+                 pm->ext[5]-pm->ext[2]);
+        glutWireCube(1.0);
+        glPopMatrix();
+      }
+    }
+  }
+}
+
+
+void drawCube(pScene sc,pMesh mesh) {
+  pTransform  cubetr;
+  pCube       cube;
+  float       x1,y1,z1,x2,y2,z2,xd,yd,zd;
+
+  cube   = sc->cube;
+  cubetr = cube->cubetr;
+
+  if ( cube->active & C_UPDATE )  updateCube(cube,mesh);
+
+  glDisable(GL_LIGHTING);
+  glPushMatrix();
+  glMultMatrixf(cubetr->matrix);
+
+  glLineWidth(3.0);
+  if ( cube->active & C_EDIT )        glColor3f(1.0,0.0,1.0);
+  else if ( cube->active & C_FREEZE ) glColor3f(0.0,0.6,0.9);
+  else                                glColor3f(0.0,1.0,0.0);
+  x1 = cube->cmi[0] - mesh->xtra;
+  y1 = cube->cmi[1] - mesh->ytra;
+  z1 = cube->cmi[2] - mesh->ztra;
+  x2 = cube->cma[0] - mesh->xtra;
+  y2 = cube->cma[1] - mesh->ytra;
+  z2 = cube->cma[2] - mesh->ztra;
+  xd = cube->cma[0] - cube->cmi[0];
+  yd = cube->cma[1] - cube->cmi[1];
+  zd = cube->cma[2] - cube->cmi[2];
+  
+  glBegin(GL_QUADS);
+    glVertex3f(x1,y1,z1);
+    glVertex3f(x1+xd,y1,z1);
+    glVertex3f(x1+xd,y1+yd,z1);
+    glVertex3f(x1,y1+yd,z1);
+
+    glVertex3f(x1,y1,z2);
+    glVertex3f(x1+xd,y1,z2);
+    glVertex3f(x1+xd,y1+yd,z2);
+    glVertex3f(x1,y1+yd,z2);
+  glEnd();
+  glBegin(GL_LINES);
+    glVertex3f(x1,y1,z1);
+    glVertex3f(x1,y1,z2);
+
+    glVertex3f(x1+xd,y1,z1);
+    glVertex3f(x1+xd,y1,z2);
+
+    glVertex3f(x1+xd,y1+yd,z1);
+    glVertex3f(x1+xd,y1+yd,z2);
+
+    glVertex3f(x1,y1+yd,z1);
+    glVertex3f(x1,y1+yd,z2);
+  glEnd();
+
+  glLineWidth(1.0);
+
+  glPopMatrix();
+}
+
+
+void drawGrid(pScene sc,pMesh mesh) {
+  int k;
+
+  /* default */
+  if ( ddebug ) printf("draw grid + graduation\n");
+
+  if ( !sc->grid ) {
+    sc->grid = glGenLists(1);
+    glNewList(sc->grid,GL_COMPILE);
+    glBegin(GL_LINES);
+    for (k=0; k<5; k++) {
+      glVertex3f(k*0.25,0.,0.);  glVertex3f(k*0.25,1.,0.);
+      glVertex3f(0.,k*0.25,0.);  glVertex3f(1.,k*0.25,0.);
+      glVertex3f(0.,k*0.25,0.);  glVertex3f(0.,k*0.25,1.);
+      glVertex3f(0.,0.,k*0.25);  glVertex3f(0.,1.,k*0.25);
+      glVertex3f(k*0.25,0.,0.);  glVertex3f(k*0.25,0.,1.);
+      glVertex3f(0.,0.,k*0.25);  glVertex3f(1.,0.,k*0.25);
+     }
+    glEnd();
+    glEndList();
+  }
+
+  /* call display list */
+  glPushMatrix();
+  glTranslatef(-0.3*fabs(sc->dmax),0.,-4.7*sc->dmax);
+  glRotatef(-60.,1.,0.,0.);
+  glRotatef(-120.,0.,0.,1.);
+  glScalef(2.5*sc->dmax,2.5*sc->dmax,2.5*sc->dmax);
+  glDisable(GL_LIGHTING);
+
+  glColor3f(0.4,0.4,0.4);
+  glCallList(sc->grid);
+
+  glColor3fv(sc->par.line);
+  output3(0.0,0.0,0.0,"%.2f",mesh->xmin);
+  output3(1.1,0.0,0.0,"%.2f",mesh->xmax);
+  output3(0.0,1.01,0.0,"%.2f",mesh->ymax);
+  output3(0.0,0.0,1.01,"%.2f",mesh->zmax);
+  glEnable(GL_LIGHTING);
+  glPopMatrix();
+}
+
+
+void drawBase(pScene sc,pMesh mesh) {
+  int  k;
+
+  /* default */
+  if ( ddebug ) printf("draw base\n");
+
+  if ( !sc->grid ) {
+    sc->grid = glGenLists(1);
+    glNewList(sc->grid,GL_COMPILE);
+    if ( glGetError() )  return;
+    glColor3f(0.5,0.5,0.5);
+    glLineWidth(2.0);
+    glBegin(GL_LINES);
+    for (k=0; k<21; k+=5) {
+      glVertex3f(k*0.05,0.,0.);  glVertex3f(k*0.05,1.,0.);
+      glVertex3f(0.,k*0.05,0.);  glVertex3f(1.,k*0.05,0.);
+    }
+    glEnd();
+    glColor3f(0.6,0.6,0.6);
+    glLineWidth(1.0);
+    glBegin(GL_LINES);
+    for (k=0; k<21; k++) {
+      if ( k%5 == 0 ) continue;
+      glVertex3f(k*0.05,0.,0.);  glVertex3f(k*0.05,1.,0.);
+      glVertex3f(0.,k*0.05,0.);  glVertex3f(1.,k*0.05,0.);
+    }
+    glEnd();
+    glEndList();
+  }
+
+  glPushMatrix();
+  glTranslatef(-1.5*sc->dmax,-1.5*sc->dmax,-0.5*(mesh->zmax-mesh->zmin));
+  glScalef(3*sc->dmax,3*sc->dmax,3*sc->dmax);
+  glDisable(GL_LIGHTING);
+    glCallList(sc->grid);
+  glPopMatrix();
+}
+
+
+/* draw HUD system for flight */
+void drawHUD(pScene sc) {
+  pCamera  c;
+  pMesh    mesh;
+  GLfloat  xm,ym,x,y,dx,dy,alt;
+  double   azim,elev;
+  int      i,j;
+
+  if ( ddebug )  fprintf(stdout,"drawHUD\n");
+  glDisable(GL_DEPTH_TEST);
+  glDisable(GL_LIGHTING);
+
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  gluOrtho2D(-0.5,639.5,-0.5,479.5);
+
+  c  = sc->camera;
+  mesh = cv.mesh[sc->idmesh];
+  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+  glColor3f(0.0,0.5,0.0);
+  glLineWidth(1.0f);
+  xm = sc->par.xs / 2.0f;
+  ym = sc->par.ys / 2.0f;
+  glRecti(200,160,440,320);
+
+  /* altitude */
+  glColor3f(1.0,0.5,0.0);
+  output2(230,330,"speed: %6.1f",1000.0f*c->spmod/sc->dmax);
+
+  switch(c->vecup) {
+    case X_AXIS: alt = (c->eye[1]+mesh->xtra)/(mesh->xmax-mesh->xmin); break;
+    case Y_AXIS: alt = (c->eye[1]+mesh->ytra)/(mesh->ymax-mesh->ymin); break;
+    case Z_AXIS: alt = (c->eye[1]+mesh->ztra)/(mesh->zmax-mesh->zmin); break;
+    default: alt = 0.0;  break;
+  }
+  glColor3f(1.0,0.5,0.0);
+  output2(350,330,"alt: %9.1f",1000.0f*alt);
+
+  /* horiz rulers */
+  output2(310,139.0f,"azim");
+  glColor3f(0.0,1.0,0.0);
+  output2(197,150,"-180");
+  output2(257,150," -90");
+  output2(317,150,"0");
+  output2(377,150," 90");
+  output2(437,150,"180");
+  x = 200.0f;
+  glBegin(GL_LINES);
+  for (i=1; i<8; i++) {
+    x += 240.0 / 8.0;
+    glVertex2f(x,158.0);
+    glVertex2f(x,162.0);
+  }
+  glEnd();
+  
+  /* vert rulers */
+  glColor3f(0.0,1.0,0.0);
+  output2(185,160,"-90");
+  output2(185,200,"-45");
+  output2(185,240,"0");
+  output2(185,280,"45");
+  output2(185,320,"90");
+  y = 160.0f;
+  glBegin(GL_LINES);
+  for (i=1; i<8; i++) {
+    y += 160.0 / 8.0;
+    glVertex2f(198,y);
+    glVertex2f(202,y);
+  }
+  glEnd();
+
+  /* azimuth */
+  azim = Azimuth(c);
+  if ( azim > 0.0f )      azim =  180.0f - azim;
+  else if ( azim < 0.0f ) azim = -180.0f - azim;
+  x = 2.0/3.0*azim + 320.0f;
+  glColor3f(1.0,0.0,0.0);
+  glLineWidth(1.0);
+  output2(x,143.0,"%d",azim>0 ? (int)(azim+0.5) : (int)(azim-0.5));
+  glBegin(GL_LINES);
+    glVertex2f(x,166.0);
+    glVertex2f(x,318.0);
+  glEnd();
+  y  = 160.0f;
+  dy = 160.0 / 8.0;
+  glBegin(GL_LINES);
+  for (i=0; i<8; i++) {
+    glVertex2f(x-4,y);
+    glVertex2f(x+4,y);
+    for (j=0; j<5; j++) {
+      glVertex2f(x-2,y+j*dy/5.0);
+      glVertex2f(x+2,y+j*dy/5.0);
+    }
+    y += dy;
+  }
+  glEnd();
+  
+  /* elevation */
+  elev = Elevation(c);
+  if ( elev > 90.0f )       y = 320.0f;
+  else if ( elev < -90.0f ) y = 160.0f;
+  else y = 8.0/9.0 * elev + 240.0;
+  glColor3f(1.0,0.0,0.0);
+  output2(175.0,y,"%5.1f",elev);
+  glBegin(GL_LINES);
+    glVertex2f(206.0,y);
+    glVertex2f(438.0,y);
+  glEnd();
+  x  = 200.0f;
+  dx = 240.0f / 8.0f;
+    glBegin(GL_LINES);
+  for (i=1; i<=8; i++) {
+    glVertex2f(x,y-4);
+    glVertex2f(x,y+4);
+    for (j=0; j<5; j++) {
+      glVertex2f(x+j*dx/5.0,y-2);
+      glVertex2f(x+j*dx/5.0,y+2);
+    }
+    x += dx;
+  }
+  glEnd();
+
+  /* horizon */
+  glLineWidth(2.0f);
+  glColor3f(0.0,0.0,1.0);
+  glBegin(GL_LINES);
+    glVertex2f(200.0,240.0);
+    glVertex2f(440.0,240.0);
+  glEnd();
+  glLineWidth(1.0f);
+
+  /* HUD */
+  glColor3f(1.0,0.0,0.0);
+  glBegin(GL_LINES);
+    glVertex2f(310,230);
+    glVertex2f(330,230);
+    glVertex2f(310,250);
+    glVertex2f(330,250);
+    
+    glVertex2f(310,230);
+    glVertex2f(310,234);
+    glVertex2f(330,230);
+    glVertex2f(330,234);
+    
+    glVertex2f(310,246);
+    glVertex2f(310,250);
+    glVertex2f(330,246);
+    glVertex2f(330,250);
+  glEnd();
+  /*glRecti(318,238,322,242);*/
+  glColor3f(0.0,1.0,0.0);
+  glLineWidth(3.0f);
+  glBegin(GL_LINES);
+    glVertex2f(320.,235.);
+    glVertex2f(320.,245.);
+    glVertex2f(315.,240.);
+    glVertex2f(325.,240.);
+  glEnd();
+  glLineWidth(1.0f);
+  
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glEnable(GL_DEPTH_TEST);
+}
diff --git a/src/medit/keyboard.c b/src/medit/keyboard.c
new file mode 100644
index 0000000..b4ebf96
--- /dev/null
+++ b/src/medit/keyboard.c
@@ -0,0 +1,868 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+extern int refmat,reftype,refitem;
+int       *pilmat,ipilmat;
+int        refpick = -1;
+
+GLfloat  dazim = 1.0;
+GLfloat  delev = 1.0;
+
+extern void mouseCamera(int button,int state,int x,int y);
+extern void motionCamera(int x,int y);
+extern GLboolean picking ;
+
+static void usage() {
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-- Medit: OnLine Help --\n");
+
+  fprintf(stdout,"** Rendering options (toggle):\n");
+  fprintf(stdout,"f - facets        l - lines          g - const. entities\n");
+  fprintf(stdout,"c - obj. color    e - material       b - back color\n");
+  fprintf(stdout,"A - axis          B - box            G - grid\n");
+  fprintf(stdout,"C - capping       r(R) - hide (show) refs.\n");
+  fprintf(stdout,"n - smooth/flat shading\n");
+
+  fprintf(stdout,"\n** Controls options:\n");
+  fprintf(stdout,"i - reset view    a - animate        I - interactive\n");
+  fprintf(stdout,"h - online help   q - quit           X - close window\n");
+
+  fprintf(stdout,"\n** View controls (ALT + key):\n");
+  fprintf(stdout,"c - copy   d - duplicate p - paste  l - link   u - unlink\n");
+  fprintf(stdout,"J - toggle flight        y - change axis\n");
+  
+  fprintf(stdout,"\n** Misc. features\n");
+  fprintf(stdout,"L - load prefs    W - save prefs\n");
+  fprintf(stdout,"H - hardcopy PPM\n");
+  fprintf(stdout,"F - face nums     P - point nums     # - select entity\n");
+  fprintf(stdout,"N - normals       O - oppos. normals ! - select plane\n");
+  fprintf(stdout,"m - data          o - iso-lines      w - tensor/vector\n");
+  fprintf(stdout,"v - streamlines   k - toggle elev.   K - elev. coeff.\n");
+  fprintf(stdout,"j - toggle deco   p - palette        S - play animation\n");
+  
+  fprintf(stdout,"+/- scale object  z/Z scale view\n");
+  fprintf(stdout,"F1,F2,F3 - clipping: On/Off, Edit, Freeze\n");
+}
+
+/* special keys CAMERA mode */
+void specCamera(pScene sc,int key) {
+  pCamera     c;
+  double      dd,azim,elev;
+  GLfloat     axe[3];
+  int         keyact;
+  
+  c  = sc->camera;
+  keyact = glutGetModifiers();
+
+  axe[0] = c->speed[2];
+  axe[1] = 0.0;
+  axe[2] = -c->speed[0];
+  dd = sqrt(axe[0]*axe[0] + axe[2]*axe[2]);
+  if ( dd != 0.0f ) {
+    axe[0] /= dd;
+    axe[2] /= dd;
+  }
+
+  switch (key) {
+  case GLUT_KEY_LEFT:
+    if ( keyact & GLUT_ACTIVE_SHIFT ) {
+      c->eye[0] += axe[0]*c->altinc;
+      c->eye[2] += axe[2]*c->altinc;
+      reshapeScene(sc->par.xs,sc->par.ys);
+      glutPostRedisplay();
+      return;
+    }
+    else {
+      azim = Azimuth(c);
+      elev = Elevation(c);
+      azim += dazim;
+    }
+    break;
+  case GLUT_KEY_RIGHT:
+    if ( keyact & GLUT_ACTIVE_SHIFT ) {
+      c->eye[0] -= axe[0]*c->altinc;
+      c->eye[2] -= axe[2]*c->altinc;
+      reshapeScene(sc->par.xs,sc->par.ys);
+      glutPostRedisplay();
+      return;
+    }
+    else {
+      azim = Azimuth(c);
+      elev = Elevation(c);
+      azim -= dazim;
+    }
+    break;
+  case GLUT_KEY_UP:
+    if ( keyact & GLUT_ACTIVE_SHIFT ) {
+      c->eye[1] += c->altinc;
+      reshapeScene(sc->par.xs,sc->par.ys);
+      glutPostRedisplay();
+      return;
+    }
+    else {
+      azim = Azimuth(c);
+      elev = Elevation(c);
+      elev -= delev;
+    }
+    break;
+  case GLUT_KEY_DOWN:
+    if ( keyact & GLUT_ACTIVE_SHIFT ) {
+      c->eye[1] -= c->altinc;
+      reshapeScene(sc->par.xs,sc->par.ys);
+      glutPostRedisplay();
+      return;
+    }
+    else {
+      azim = Azimuth(c);
+      elev = Elevation(c);
+      elev += delev;
+    }
+    break;
+  default:
+    return;
+  }
+
+  updateCamera(sc,c,azim,elev);
+
+  /* refresh scene */
+  reshapeScene(sc->par.xs,sc->par.ys);
+  glutPostRedisplay();
+}
+
+
+/* change center of scene */
+static void changeCenter(pScene sc,pMesh mesh) {
+  pPoint     p0;
+  pTriangle  pt;
+  pQuad      pq;
+  pTetra     ptt;
+  pHexa      ph;
+  float      cx,cy,cz;
+  int        i;
+
+  if ( !refitem )  return;
+  cx = cy = cz = 0.0;
+  switch(reftype) {
+  case LPoint:
+    p0 = &mesh->point[refitem];
+    cx = p0->c[0];
+    cy = p0->c[1];
+    cz = p0->c[2];
+    break;
+  case LTria:
+    pt = &mesh->tria[refitem];
+    for (i=0; i<3; i++) {
+      p0 = &mesh->point[pt->v[i]];
+      cx += 0.33 * p0->c[0];
+      cy += 0.33 * p0->c[1];
+      cz += 0.33 * p0->c[2];
+    }
+    break;
+  case LQuad:
+    pq = &mesh->quad[refitem];
+    for (i=0; i<4; i++) {
+      p0 = &mesh->point[pq->v[i]];
+      cx += 0.25 * p0->c[0];
+      cy += 0.25 * p0->c[1];
+      cz += 0.25 * p0->c[2];
+    }
+    break;
+  case LTets:
+    ptt = &mesh->tetra[refitem];
+    for (i=0; i<4; i++) {
+      p0 = &mesh->point[ptt->v[i]];
+      cx += 0.25 * p0->c[0];
+      cy += 0.25 * p0->c[1];
+      cz += 0.25 * p0->c[2];
+    }
+    break;
+  case LHexa:
+    ph = &mesh->hexa[refitem];
+    for (i=0; i<8; i++) {
+      p0 = &mesh->point[ph->v[i]];
+      cx += 0.125 * p0->c[0];
+      cy += 0.125 * p0->c[1];
+      cz += 0.125 * p0->c[2];
+    }
+    break;
+  }
+
+  /* reset translation and move to center */
+  sc->view->panx = sc->view->pany = 0.0;
+  sc->cx = -cx;
+  sc->cy = -cy;
+  sc->cz = -cz;
+}
+
+
+/* special keys PERSPECTIVE mode */
+void special(int key,int x,int y) {
+  pTransform  view;
+  pScene      sc;
+  pMesh       mesh;
+  pClip       clip;
+  pCube       cube;
+  float       pancoeff = 0.1f;
+  int         keyact,idw = currentScene();
+  ubyte       post = TRUE;
+ 
+  /* default */
+  if ( ddebug ) printf("special key  %d\n",key);
+  sc   = cv.scene[idw];
+
+  /* special mode camera */
+  if ( sc->persp->pmode == CAMERA ) {
+    specCamera(sc,key);
+    return;
+  }
+  
+  view = sc->view;
+  mesh = cv.mesh[sc->idmesh];
+  clip = sc->clip;
+  cube = sc->cube;
+  keyact = glutGetModifiers();
+  if ( keyact & GLUT_ACTIVE_SHIFT )
+    pancoeff = 0.01;
+
+  switch(key) {
+  case GLUT_KEY_F1:  /* toggle clipping plane */
+    if ( mesh->dim == 3 ) {
+      if ( cube->active & C_ON)
+    keyCube('C',0,0);
+      else
+    keyClip('C',0,0);
+    }
+    post = FALSE;
+    break;
+  case GLUT_KEY_F2:  /* edit clipping plane */
+    if ( mesh->dim == 3 ) {
+      if ( cube->active & C_ON)
+        keyCube('E',0,0);     
+      else if ( clip->active & C_ON ) 
+    keyClip('E',0,0);
+    }
+    post = FALSE;
+    break;
+  case GLUT_KEY_F3:  /* freeze clipping plane */
+    if ( cube->active & C_ON )
+      keyCube('F',0,0);
+    else if ( clip->active & C_ON ) 
+      keyClip('F',0,0);
+    post = FALSE;
+    break;
+  case GLUT_KEY_F4:  /* toggle Vclip */
+    if ( mesh->dim == 3 )  keyClip('Z',0,0);
+    post = FALSE;
+    break;
+  case GLUT_KEY_F5:  /* Toggle Shrink */
+    if ( mesh->ntet+mesh->nhex > 0 )
+      keyFeature('V',0,0);
+    else
+      keyFeature('S',0,0);
+    break;
+  case GLUT_KEY_F6:  /* Increase Shrink */
+    keyFeature('I',0,0);
+    break;
+  case GLUT_KEY_F7:  /* Decrease Shrink */
+    keyFeature('i',0,0);
+    break;
+
+  case GLUT_KEY_LEFT:  /* translate eyes or object */
+    if ( clip->active & C_EDIT ) {
+      clip->cliptr->panx -= 0.02 * sc->dmax;
+      clip->cliptr->angle = 0.0;
+      clip->active |= C_UPDATE + C_REDO;
+    }
+    else if ( keyact & GLUT_ACTIVE_CTRL ) {
+      sc->par.eyesep *= 0.9;
+      printf("eyesep %f\n",sc->par.eyesep);
+    }
+    else
+      view->panx -= pancoeff * sc->dmax;
+    break;
+  case GLUT_KEY_RIGHT:
+    if ( clip->active & C_EDIT ) {
+      clip->cliptr->panx += 0.02 * sc->dmax;
+      clip->cliptr->angle = 0.0;
+      clip->active |= C_UPDATE + C_REDO;
+    }
+    else if ( keyact & GLUT_ACTIVE_CTRL ) {
+      sc->par.eyesep *= 1.1;
+      printf("eyesep %f\n",sc->par.eyesep);
+    }
+    else
+      view->panx += pancoeff * sc->dmax;
+    break;
+  case GLUT_KEY_UP:
+    if ( clip->active & C_EDIT ) {
+      clip->cliptr->pany += 0.02 * sc->dmax;
+      clip->cliptr->angle = 0.0;
+      clip->active |= C_UPDATE + C_REDO;
+    }
+    else
+      view->pany += pancoeff * sc->dmax;
+    break;
+  case GLUT_KEY_DOWN:
+    if ( clip->active & C_EDIT ) {
+      clip->cliptr->pany -= 0.02 * sc->dmax;
+      clip->cliptr->angle = 0.0;
+      clip->active |= C_UPDATE + C_REDO;
+    }
+    else
+      view->pany -= pancoeff * sc->dmax;
+    break;
+  default:
+    return;
+  }
+  if ( post )  glutPostRedisplay();
+}
+
+
+void keyScene(unsigned char key,int x,int y) {
+  pMaterial   pm;
+  pTetra      ptt;
+  pHexa       ph;
+  pTriangle   pt;
+  pQuad       pq;
+  pScene      sc,sc1;
+  pMesh       mesh;
+  pClip       clip;
+  pCube       cube;
+  pPersp      p;
+  pCamera     cam;
+  double      dd;
+  float       a,b,c,d;
+  int         k,keyact,numit,idw = currentScene();
+  ubyte       post = FALSE,dolist = FALSE;
+
+  if ( idw < 0 ) exit(0);
+
+  /* ESC = end medit */
+  if ( key == 'q' || key == 27 ) 
+    exit(0);
+  else if ( key == 'h' || key == '?' )
+    usage();
+
+  /* default */
+  sc   = cv.scene[idw];
+  mesh = cv.mesh[sc->idmesh];
+  clip = sc->clip;
+  cube = sc->cube;
+  p    = sc->persp;
+
+  keyact = glutGetModifiers();
+  if ( key == ' ' ) {
+    if ( option == MORPHING )
+      morphMesh(sc,mesh);
+    else if ( sc->isotyp & S_PARTICLE ) {
+      glutIdleFunc(0);
+    } 
+    else {      
+      cam = sc->camera;
+      cam->eye[0] += cam->spmod*cam->speed[0];
+      cam->eye[1] += cam->spmod*cam->speed[1];
+      cam->eye[2] += cam->spmod*cam->speed[2];
+      reshapeScene(sc->par.xs,sc->par.ys);
+    }
+    post = TRUE;
+  }
+
+  else if ( islower(key) ) {
+    switch(key) {
+    case 'a':  /* toggle animate */
+      keyAnim('A',0,0);
+      break;
+    case 'b':  /* backcolor */
+      keyColor('b',0,0);
+      break;
+    case 'c':
+      if ( keyact & GLUT_ACTIVE_ALT )
+    keyView('C',0,0);
+      else {
+    sc->mode ^= S_COLOR;
+    post = TRUE;
+      }
+      break;
+    case 'd':
+      if ( keyact & GLUT_ACTIVE_ALT ) keyView('D',0,0);
+      break;
+    case 'e': 
+      keyColor('e',0,0);
+      break;
+    case 'f':
+      sc->mode ^= S_FILL;
+      post=TRUE;
+      break;
+    case 'g': 
+      keyItem('g',0,0);
+      break;
+    case 'h':
+      usage();
+      break;
+    case 'i':
+      keyView('R',0,0);
+      if ( clip->active & C_ON )  resetClip(sc,clip,mesh);
+      if ( cube->active & C_ON )  resetCube(sc,cube,mesh);
+      sc1 = sc;
+      while ( sc1->slave > -1 ) {
+        sc1 = cv.scene[sc1->slave];
+        glutSetWindow(sc1->idwin);
+        keyScene('i',0,0);
+      }
+      glutSetWindow(sc->idwin);
+      break;
+    case 'j':
+      sc->type ^= S_DECO;
+      post = TRUE;
+      break;
+    case 'k':
+      keyMetric('k',0,0);
+      break;
+    case 'l':
+      if ( keyact & GLUT_ACTIVE_ALT ) 
+        keyView('L',0,0);
+      else
+        sc->mode ^= S_BDRY;  
+      post = TRUE;  
+      break;
+    case 'm':  /* toggle metric */
+      if ( mesh->nbb )  keyMetric('m',0,0);
+      keyMode('n',0,0);
+      break;
+    case 'o': /* iso-lines */
+      if ( mesh->nbb ) keyMetric('l',0,0);
+      break;
+    case 'p':
+      if ( keyact & GLUT_ACTIVE_ALT ) 
+        keyView('P',0,0);
+      else
+        keyMetric('p',0,0);
+      break;
+           
+    case 'r':
+      if ( refmat<0 || ipilmat == sc->par.nbmat ) return;
+      pilmat[++ipilmat] = refmat;
+      pm = &sc->material[refmat];
+      pm->flag = 1;
+      updatePoints(sc,mesh,refmat);
+      if ( sc->picklist ) glDeleteLists(sc->picklist,1);
+      sc->picklist = 0;
+      refmat = -1;
+      dolist = TRUE;
+      post   = TRUE;
+      break;
+    case 's':
+      if ( !refitem ) return;
+      switch(reftype) {
+      case LTria:
+        pt = &mesh->tria[refitem];
+        pt->v[0] = 0;
+        break;
+      case LQuad:
+        pq = &mesh->quad[refitem];
+        pq->v[0] = 0;
+        break;
+      case LTets:
+        ptt = &mesh->tetra[refitem];
+        ptt->v[0] = 0;
+        break;
+      case LHexa:
+        ph = &mesh->hexa[refitem];
+        ph->v[0] = 0;
+        break;
+      }
+      sc->picklist = 0;
+      dolist = TRUE;
+      post   = TRUE;
+      break;
+    case 't':  /* toggle texture */
+      /*keyColor('t',0,0);*/
+      break;
+    case 'u':
+      if ( keyact & GLUT_ACTIVE_ALT ) 
+    keyView('U',0,0);
+      break;
+    case 'v':
+      keyMetric('v',0,0);
+      break;
+    case 'w':
+      keyMetric('w',0,0);
+      break;
+    case 'x':
+      if ( cube->active & C_EDIT ) {
+        cube->cma[0] += 0.1*sc->dmax;
+        post = TRUE;
+        break;
+      }
+    case 'y':
+      if ( cube->active & C_EDIT ) {
+        cube->cma[1] += 0.1*sc->dmax;
+        post = TRUE;
+        break;
+      }
+      if ( p->pmode & CAMERA ) {
+        cam = sc->camera;
+        cam->vecup = (cam->vecup+1) % 3;
+        switch(cam->vecup) {
+          case X_AXIS: cam->altinc = (mesh->xmax-mesh->xmin); break;
+          case Y_AXIS: cam->altinc = (mesh->ymax-mesh->ymin); break;
+          case Z_AXIS: cam->altinc = (mesh->zmax-mesh->zmin); break;
+        }
+        cam->altinc *= 0.005f;
+        sc->type |= S_RESET;
+        reshapeScene(sc->par.xs,sc->par.ys);
+      }
+      /* tilt cut plane */
+      else if ( clip->active & C_EDIT )
+        tiltClip(sc,clip);
+      else return;
+      post = TRUE;
+      break;
+
+    case 'z':  /* zoom in */
+      if ( cube->active & C_EDIT ) {
+        cube->cma[2] += 0.1*sc->dmax;
+        post = TRUE;
+        break;
+      }
+      else {
+    if ( p->rubber == 2 )
+      setPersp(sc,p,1);
+        else 
+          p->fovy = max(0.9*p->fovy,1e-05);
+        farclip(1);
+      }
+      post = TRUE;
+
+      /* get linked view */
+      sc1 = sc;
+      while ( sc1->slave > -1 ) {
+        sc1 = cv.scene[sc1->slave];
+        memcpy(sc1->view,sc->view,sizeof(struct transform));
+        memcpy(sc1->persp,sc->persp,sizeof(struct sperspective));
+        glutSetWindow(sc1->idwin);
+        reshapeScene(sc1->par.xs,sc1->par.ys);
+      }
+      glutSetWindow(sc->idwin);
+      break;
+    }
+  }
+
+  else if ( isupper(key) ) {
+    switch(key) {
+    case 'A':  /* toggle axis */
+      keyItem('A',0,0);
+      break;
+    case 'B':  /* toggle box */
+      keyItem('B',0,0);
+      break;
+    case 'C':  /* toggle capping */
+      keyClip('K',0,0);
+      break;
+    case 'D':  /* selection cube */
+      if (mesh->dim == 3 )  keyItem('D',0,0);
+        break;
+    case 'E':
+      keyColor('E',0,0);
+      glutSetWindow(sc->idwin);
+      break;
+    case 'F': /* toggle face nums */
+      keyItem('F',0,0);
+      break;
+    case 'G':  /* toggle grid */
+      keyItem('G',0,0);
+      break;
+    case 'H': /* hardcopy PPM */
+      keyFile('H',0,0);
+      break;
+    case 'I':  /* follows mouse */
+      sc->type ^= S_FOLLOW;
+      sc1 = sc;
+      while ( sc1->slave > -1 ) {
+        sc1 = cv.scene[sc1->slave];
+        sc1->type = sc->type;
+      }
+      break;
+    case 'J':
+      if ( mesh->dim == 2 && !(sc->mode & S_ALTITUDE) )  break;
+      if ( p->pmode == PERSPECTIVE ) {
+        p->pmode = CAMERA;  
+        glutMouseFunc(mouseCamera);
+        glutMotionFunc(motionCamera);
+      }
+      else {
+        p->pmode = PERSPECTIVE;
+        glutMouseFunc(mouse);
+        glutMotionFunc(motion);
+      }
+      sc->type = S_RESET;
+      reshapeScene(sc->par.xs,sc->par.ys);
+      post = TRUE;
+      break;
+    case 'K':
+      keyMetric('K',0,0);
+      break;
+    case 'L':
+      keyFile('L',0,0);
+      break;
+    case 'M':
+      morphing = 1-morphing;
+      post = TRUE;
+      break;
+    case 'N':  /* draw normals */
+    case 'O':
+      if ( mesh->nvn )
+        keyItem(key,0,0);
+      break;
+    case 'P': /* toggle point nums */
+      keyItem('P',0,0);
+      break;
+    case 'Q':
+      /*keyMetric('q',0,0);*/
+      break;
+    case 'R':
+      if ( ipilmat < 1 ) return;
+      refmat = pilmat[ipilmat--];
+      pm = &sc->material[refmat];
+      pm->flag = 0;
+      updatePoints(sc,mesh,refmat);
+      dolist = TRUE;
+      post   = TRUE;
+      break;
+    case 'S':  /* softcopy */
+      /*keyFile('S',0,0);*/
+      keyAnim('S',0,0);
+      break;
+    case 'V':  /* change center of scene */
+      if ( !refitem )  return;
+      changeCenter(sc,mesh);
+      reshapeScene(sc->par.xs,sc->par.ys);
+      post = TRUE;
+      /* linked view */
+      sc1 = sc;
+      while ( sc1->slave > -1 ) {
+    sc1 = cv.scene[sc1->slave];
+        sc1->cx = sc->cx;
+        sc1->cy = sc->cy;
+        sc1->cz = sc->cz;
+        memcpy(sc1->view,sc->view,sizeof(struct transform));
+        memcpy(sc1->persp,sc->persp,sizeof(struct sperspective));
+    glutSetWindow(sc1->idwin);
+    reshapeScene(sc1->par.xs,sc1->par.ys);
+      }
+      glutSetWindow(sc->idwin);
+      break;
+    case 'W':
+      keyFile('W',0,0);
+      break;
+    case 'X':  /* close window */
+      if ( cube->active & C_EDIT ) {
+        cube->cma[0] -= 0.1*sc->dmax;
+        post = TRUE;
+        break;
+      }
+      if ( idw != cv.nbs ) {
+    deleteScene(sc);
+    for (k=idw+1; k<cv.nbs; k++)
+      cv.scene[k-1] = cv.scene[k];
+    cv.scene[cv.nbs-1] = 0;
+      }
+      glutHideWindow();
+      if ( --cv.nbs == 0 ) exit(0);
+      break;
+
+    case 'Y':  /* close window */
+      if ( cube->active & C_EDIT ) {
+        cube->cma[1] -= 0.1*sc->dmax;
+        post = TRUE;
+        break;
+      }
+    case 'Z':  /* zoom out */
+      if ( cube->active & C_EDIT ) {
+        cube->cma[2] -= 0.1*sc->dmax;
+        post = TRUE;
+        break;
+      }
+      else {
+        if ( p->rubber == 2 )
+          setPersp(sc,p,0);
+        else 
+          p->fovy = min(1.1*p->fovy,179.0);
+        farclip(1);
+      }
+      post = TRUE;
+
+      /* get linked view */
+      sc1 = sc;
+      while ( sc1->slave > -1 ) {
+        sc1 = cv.scene[sc1->slave];
+        memcpy(sc1->view,sc->view,sizeof(struct transform));
+        memcpy(sc1->persp,sc->persp,sizeof(struct sperspective));
+        glutSetWindow(sc1->idwin);
+        reshapeScene(sc1->par.xs,sc1->par.ys);
+      }
+      glutSetWindow(sc->idwin);
+      break;
+    }
+  }
+  
+  else {
+    switch (key) {
+    case '-':
+      if (keyact & GLUT_ACTIVE_ALT ) {
+        keyAnim('p',0,0);
+        break;
+      }
+      if ( cube->active & C_EDIT ) {
+        cube->cma[0] *= 0.95;
+        cube->cma[1] *= 0.95;
+        cube->cma[2] *= 0.95;
+        post = TRUE;
+        break;
+      }  
+      if ( sc->persp->pmode == CAMERA ) {
+        cam = sc->camera;
+        cam->spmod -= 1.e-04 * sc->dmax;
+        post = TRUE;
+        break;
+      }
+      if ( p->depth < -20.0*sc->dmax )  break;
+      p->depth -= 0.1*sc->dmax;
+      farclip(1);
+      post = TRUE;
+
+      /*
+      if ( p->rubber == 2 )
+        setPersp(sc,p,0);
+      else 
+        p->fovy = min(1.1*p->fovy,179.0);
+      farclip(1);
+      post = TRUE;
+      */
+      /* get linked view */
+      sc1 = sc;
+      while ( sc1->slave > -1 ) {
+        sc1 = cv.scene[sc1->slave];
+        memcpy(sc1->view,sc->view,sizeof(struct transform));
+        memcpy(sc1->persp,sc->persp,sizeof(struct sperspective));
+        glutSetWindow(sc1->idwin);
+        reshapeScene(sc1->par.xs,sc1->par.ys);
+      }
+      glutSetWindow(sc->idwin);
+      break;
+
+    case '+':
+      if (keyact & GLUT_ACTIVE_ALT ) {
+        keyAnim('n',0,0);
+        break;
+      }
+      if ( cube->active & C_EDIT ) {
+    cube->cma[0] *= 1.05;
+    cube->cma[1] *= 1.05;
+    cube->cma[2] *= 1.05;
+        post = TRUE;
+        break;
+      }  
+      if ( sc->persp->pmode == CAMERA ) {
+        cam = sc->camera;
+        cam->spmod += 1.e-04 * sc->dmax;
+        post = TRUE;
+        break;
+      }
+      if ( p->depth > 0.0 )  break;
+      p->depth += 0.1*sc->dmax;
+      farclip(1);
+      post = TRUE;
+
+/*
+      if ( p->rubber == 2 )
+    setPersp(sc,p,1);
+      else 
+      p->fovy = max(0.9*p->fovy,1e-05);
+      farclip(1);
+      post = TRUE;
+*/      
+      /* update linked view */
+      sc1 = sc;
+      while ( sc1->slave > -1 ) {
+    sc1 = cv.scene[sc1->slave];
+        memcpy(sc1->view,sc->view,sizeof(struct transform));
+        memcpy(sc1->camera,sc->camera,sizeof(struct camera));
+        memcpy(sc1->persp,sc->persp,sizeof(struct sperspective));
+    glutSetWindow(sc1->idwin);
+    reshapeScene(sc1->par.xs,sc1->par.ys);
+      }
+      glutSetWindow(sc->idwin);
+      break;
+
+    case '#':  /* select entity */
+      fprintf(stdout,"ENTITY NUMBER: "); fflush(stdout);
+      fflush(stdin);  fscanf(stdin,"%d",&numit);
+      if ( sc->picklist )  glDeleteLists(sc->picklist,1);
+      if ( numit > 0 )
+    sc->picklist = pickItem(mesh,sc,numit);
+      post = TRUE;
+      break;
+    case '=':
+             picking = GL_TRUE;
+            if ( sc->picklist ) glDeleteLists(sc->picklist,1);
+            sc->picklist = pickingScene(sc,x,y,0);
+            break;
+
+    case '!':  /* clip plane */
+    return;
+      if ( !(clip->active & C_ON) )  return;
+      dd = clip->eqn[3]-clip->eqn[0]*mesh->xtra \
+         - clip->eqn[1]*mesh->ytra-clip->eqn[2]*mesh->ztra;
+      fprintf(stdout,"\nCurrent plane: %gx %+gy %+gz %+g = 0\n",
+              clip->eqn[0],clip->eqn[1],clip->eqn[2],dd);
+      fprintf(stdout,"Plane coeffs : "); fflush(stdout);
+      fflush(stdin);  fscanf(stdin,"%f %f %f %f",&a,&b,&c,&d);
+      resetClip(sc,clip,mesh);
+      clip->eqn[0] = a;
+      clip->eqn[1] = b;
+      clip->eqn[2] = c;
+      clip->eqn[3] = d;
+
+      fprintf(stdout,"New plane eq.: ");
+      if ( clip->eqn[0] )
+        fprintf(stdout,"%+gx",clip->eqn[0]);
+      if ( clip->eqn[1] )
+        fprintf(stdout," %+gy",clip->eqn[1]);
+      if ( clip->eqn[2] )  
+        fprintf(stdout," %+gz",clip->eqn[2]);
+      if ( clip->eqn[3] ) 
+        fprintf(stdout," %+g",clip->eqn[3]);
+      fprintf(stdout," = 0\n");
+      clip->eqn[3] += (a*mesh->xtra+b*mesh->ytra+c*mesh->ztra);
+      post   = TRUE;
+      dolist = TRUE;
+      break;
+    
+    case '@': /* add trajectoire point */
+      if ( p->pmode == CAMERA )
+        pathAdd(sc,x,y);
+      break;
+    
+    case '%':
+      fprintf(stdout,"reference (%d): ",refpick); fflush(stdout);
+      fflush(stdin);
+      fscanf(stdin,"%d",&refpick);
+      break;
+    
+    case '&':
+      puts("ADJUST");
+      parEdit(sc);
+      break;
+    }
+  }
+  
+  if ( dolist ) {
+    doLists(sc,mesh);
+    doMapLists(sc,mesh,1);
+    doIsoLists(sc,mesh,1);
+  }
+  if ( post )   glutPostRedisplay();
+}
+
diff --git a/src/medit/listnum.c b/src/medit/listnum.c
new file mode 100644
index 0000000..968ad1d
--- /dev/null
+++ b/src/medit/listnum.c
@@ -0,0 +1,148 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+void updatePoints(pScene sc,pMesh mesh,int refmat) {
+  pPoint    ppt;
+  pTriangle pt;
+  pQuad     pq;
+  pTetra    ptet;
+  pHexa     ph;
+  pMaterial pm;
+  int       i,k,m;
+
+  /* mark all points */
+  for (k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+    ppt->tag = M_UNUSED;
+  }
+
+  /* unmark points */
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    if ( pm->flag )  continue;
+
+    /*triangles */
+    k = pm->depmat[LTria];
+    while ( k > 0 ) {
+      pt = &mesh->tria[k];
+      if ( pt->v[0] ) {
+        for (i=0; i<3; i++) {
+          ppt = &mesh->point[pt->v[i]];
+          ppt->tag &= ~M_UNUSED;
+        }
+      }
+      k = pt->nxt;
+    }
+    
+    /* quads */
+    k  = pm->depmat[LQuad];
+    while ( k > 0 ) {
+      pq = &mesh->quad[k];
+      if ( pq->v[0] ) {
+        for (i=0; i<4; i++) {
+          ppt = &mesh->point[pq->v[i]];
+          ppt->tag &= ~M_UNUSED;
+        }
+      }
+      k = pq->nxt;
+    }
+    
+    /* tetras */
+    k = pm->depmat[LTets];
+    while ( k > 0 ) {
+      ptet = &mesh->tetra[k];
+      if ( ptet->v[0] ) {
+        for (i=0; i<4; i++) {
+          ppt = &mesh->point[ptet->v[i]];
+          ppt->tag &= ~M_UNUSED;
+        }
+      }
+      k = ptet->nxt;
+    }
+    
+    /* hexas */
+    k = pm->depmat[LHexa];
+    while ( k > 0 ) {
+       ph = &mesh->hexa[k];
+       if ( ph->v[0] ) {
+         for ( i=0; i<8; i++) {
+           ppt = &mesh->point[ph->v[i]];
+           ppt->tag &= ~M_UNUSED;
+         }
+       }
+       k = ph->nxt;
+    }
+  }
+}
+
+void listNum(pScene sc,pMesh mesh) {
+  pMaterial  pm;
+  pPoint     ppt;
+  pTriangle  pt;
+  pQuad      pq;
+  double     cx,cy,cz;
+  int        k,i,m;
+
+  glDisable(GL_LIGHTING);
+  /* point numbers */
+  if ( sc->item & S_NUMP ) {
+
+    for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+      if ( ppt->tag == M_UNUSED ) continue;
+      if ( ppt->ref ) {
+        m  = matRef(sc,ppt->ref);
+        pm = &sc->material[m];
+        glColor3f(pm->dif[0],pm->dif[1],pm->dif[2]);
+      }
+      else
+        glColor3fv(sc->par.line);
+      output3(ppt->c[0],ppt->c[1],ppt->c[2],"%d",k);
+    }
+  }
+
+  /* facets numbers */
+  if ( sc->item & S_NUMF ) {
+    glColor4fv(sc->par.line);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      if ( pm->flag )  continue;
+    
+      /*triangles */
+      k = pm->depmat[LTria];
+      while ( k > 0 ) {
+        pt = &mesh->tria[k];
+        if ( pt->v[0] ) {
+          cx = cy = cz = 0.0f;
+          for (i=0; i<3; i++) {
+            ppt = &mesh->point[pt->v[i]];
+            cx += 0.333 * ppt->c[0];
+            cy += 0.333 * ppt->c[1];
+            cz += 0.333 * ppt->c[2];
+          }
+          output3(cx,cy,cz,"%d",k);
+        }
+        k = pt->nxt;
+      }
+      
+      /* quads */
+      k = pm->depmat[LQuad];
+      while ( k > 0 ) {
+        pq = &mesh->quad[k];
+        if ( pq->v[0] ) {
+          cx = cy = cz = 0.0f;
+          for (i=0; i<4; i++) {
+            ppt = &mesh->point[pq->v[i]];
+            cx += 0.25 * ppt->c[0];
+            cy += 0.25 * ppt->c[1];
+            cz += 0.25 * ppt->c[2];
+          }
+          output3(cx,cy,cz,"%d",k);
+        }
+        k = pq->nxt;
+      }
+    }
+  }
+}
diff --git a/src/medit/material.c b/src/medit/material.c
new file mode 100644
index 0000000..1294bc1
--- /dev/null
+++ b/src/medit/material.c
@@ -0,0 +1,541 @@
+#include <stdarg.h>
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define Width   630
+#define Height  250
+#define MAX_MAT  32
+
+extern int refmat,reftype;
+
+/* globals */
+pScene    main_scene;
+GLint     matwin=0,m_subwin;
+GLint     selection;
+
+static float colors[MAX_MAT+1][3] = {
+  {0.1, 0.4, 0.9},    /* blue */
+  {1.0, 0.0, 0.0},    /* red */
+  {0.0, 1.0, 0.0},    /* green */
+  {1.0, 1.0, 0.0},    /* yellow */
+  {0.0, 1.0, 1.0},    /* cyan */ 
+  {1.0, 0.5, 0.0},    /* orange */
+  {0.5, 0.0, 1.0},    /* violet */ 
+  {0.0, 0.0, 0.4},    /* dark blue */
+  {0.0, 0.4, 0.0},    /* dark green */
+  {0.4, 0.0, 0.0},    /* dark red */
+  {1.0, 1.0, 0.5},
+  {1.0, 0.5, 1.0},  
+  {1.0, 0.5, 0.5},  
+  {1.0, 0.5, 0.0},    /* orange */
+  {1.0, 0.0, 1.0},  
+  {1.0, 0.0, 0.5},  
+  {0.5, 1.0, 1.0},  
+  {0.5, 1.0, 0.5},  
+  {0.5, 1.0, 0.0},
+  {0.5, 0.5, 1.0},  
+  {0.5, 0.5, 0.5},  
+  {0.5, 0.5, 0.0},
+  {0.5, 0.0, 0.5},  
+  {0.5, 0.0, 0.0},
+  {0.0, 1.0, 0.5},  
+  {0.0, 0.5, 1.0},  
+  {0.0, 0.5, 0.5},  
+  {0.0, 0.5, 0.0},
+  {0.0, 0.0, 0.5},
+  {0.4, 0.4, 0.0},    /* dark yellow */
+  {0.0, 0.4, 0.4},    /* dark cyan */ 
+  {0.3, 0.7, 0.9},    /* default blue */
+  {0.3, 0.7, 0.9}     /* default blue */
+};
+
+cell ambient[4] = {
+    { 1, 120, 60, 0.0, 1.0, 0.0, 0.01,
+      "Specifies R coordinate of ambient vector.", "%.2f" },
+    { 2, 180, 60, 0.0, 1.0, 0.0, 0.01,
+      "Specifies G coordinate of ambient vector.", "%.2f" },
+    { 3, 240, 60, 0.0, 1.0, 0.0, 0.01,
+      "Specifies B coordinate of ambient vector.", "%.2f" },
+    { 4, 300, 60, 0.0, 1.0, 0.0, 0.01,
+      "Specifies A coordinate of ambient vector.", "%.2f" },
+};
+cell diffuse[4] = {
+    { 5, 120, 90, 0.0, 1.0, 0.0, 0.01,
+      "Specifies R coordinate of diffuse vector.", "%.2f" },
+    { 6, 180, 90, 0.0, 1.0, 0.0, 0.01,
+      "Specifies G coordinate of diffuse vector.", "%.2f" },
+    { 7, 240, 90, 0.0, 1.0, 0.0, 0.01,
+      "Specifies B coordinate of diffuse vector.", "%.2f" },
+    { 8, 300, 90, 0.0, 1.0, 0.0, 0.01,
+      "Specifies A coordinate of diffuse vector.", "%.2f" },
+};
+cell specular[4] = {
+    { 9, 120, 120, 0.0, 1.0, 0.0, 0.01,
+      "Specifies R coordinate of specular vector.", "%.2f" },
+    { 10, 180, 120, 0.0, 1.0, 0.0, 0.01,
+      "Specifies G coordinate of specular vector.", "%.2f" },
+    { 11, 240, 120, 0.0, 1.0, 0.0, 0.01,
+      "Specifies B coordinate of specular vector.", "%.2f" },
+    { 12, 300, 120, 0.0, 1.0, 0.0, 0.01,
+      "Specifies A coordinate of specular vector.", "%.2f" },
+};
+cell emission[4] = {
+    { 13, 120, 150, 0.0, 1.0, 0.0, 0.01,
+      "Specifies R coordinate of emission vector.", "%.2f" },
+    { 14, 180, 150, 0.0, 1.0, 0.0, 0.01,
+      "Specifies G coordinate of emission vector.", "%.2f" },
+    { 15, 240, 150, 0.0, 1.0, 0.0, 0.01,
+      "Specifies B coordinate of emission vector.", "%.2f" },
+    { 16, 300, 150, 0.0, 1.0, 0.0, 0.01,
+      "Specifies A coordinate of emission vector.", "%.2f" },
+};
+cell shininess[1] = {
+    { 17, 120, 180, 3.0, 128.0, 0.0, 0.5,
+      "Specifies value of shininess.", "%.2f" },
+};
+
+
+void matInit(pScene sc) {
+  pMaterial  pm;
+  int        m,mm;
+
+  /* default */
+  if ( !sc->material ) {
+    sc->material = (pMaterial)M_calloc(2+sc->par.nbmat,sizeof(Material),"matinit");
+	assert(sc->material);
+    sc->matsort = (int*)M_calloc(2+sc->par.nbmat,sizeof(int),"matinit");
+	assert(sc->matsort);
+  }
+
+  /* store color in table */
+  for (m=0; m<=sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    /* diffuse : primary color */
+    mm = m % MAX_MAT;
+    memcpy(pm->dif,colors[mm],3*sizeof(float));
+    pm->dif[3] = 1.0;
+    /* ambient : grey level */
+    pm->amb[0] = pm->amb[1] = pm->amb[2] = 0.2;  pm->amb[3] = 1.0;
+    /* emission: null (pas un neon!) */
+    pm->emi[0] = pm->emi[1] = pm->emi[2] = 0.0;  pm->emi[3] = 1.0;
+    /* specular: soleil blanc */
+    pm->spe[0] = pm->spe[1] = pm->spe[2] = 0.4;  pm->spe[3] = 1.0;
+    /* shininess: etalement des reflections spec. */
+    pm->shininess = 80.0;
+    if ( m != DEFAULT_MAT )
+      sprintf(pm->name,"%s%.2d","MAT",m);
+    else
+      strcpy(pm->name,"DEFAULT_MAT");
+    pm->flag = 0;
+    if ( !pm->ref )  pm->ref = m; 
+    pm->sort = m;
+  }
+}
+
+void matSort(pScene sc) {
+  pMaterial  pm,pm1;
+  int        m,mm,transp;
+
+  /* sort materials */
+  if ( !quiet ) fprintf(stdout,"   Sorting %d materials\n",sc->par.nbmat);
+  transp = 0;
+
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm  = &sc->material[m];
+    pm->sort       = m;
+    sc->matsort[m] = m;
+    if ( pm->dif[3] < 0.999 )  transp++;
+  }
+  if ( !transp )  return;
+
+  /* sorting */
+  if ( ddebug ) fprintf(stdout,"   %d translucent\n",transp);
+  mm = sc->par.nbmat - 1;
+  for (m=0; m<sc->par.nbmat-transp-1; m++) {
+    pm = &sc->material[m];
+    if ( pm->dif[3] < 0.995 ) {
+      pm1 = &sc->material[mm];
+      sc->matsort[mm] = m;
+      sc->matsort[m]  = mm;
+      pm->sort  = mm;
+      pm1->sort = m;
+      mm--;
+    }
+  }
+}
+
+int matRef(pScene sc,int ref) {
+  pMaterial  pm;
+  int        m;
+
+  if ( !ref )  return(ref);
+  for (m=1; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    if ( pm->ref == ref )  return(m);
+  }
+  if ( sc->par.nbmat < 2 ) return(0);
+  m = 1+(ref-1) % (sc->par.nbmat-1);
+  return(m);
+}
+
+/* reshape material window */
+void matReshape(int width,int height) {
+  glutSetWindow(matwin);
+  glViewport(0,0,Width,Height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluOrtho2D(0,Width,Height,0);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glutReshapeWindow(Width,Height);
+}
+
+static void cellInit(int mat) {
+  pMaterial pm;
+  int       i;
+
+  pm = &main_scene->material[mat];
+  for (i=0; i<4; i++) {
+    ambient[i].value  = pm->amb[i];
+    diffuse[i].value  = pm->dif[i];
+    specular[i].value = pm->spe[i];
+    emission[i].value = pm->emi[i];
+  }
+  shininess[0].value = pm->shininess;
+  glutPostRedisplay();
+}
+
+static int cellCopy(int mat) {
+  pMaterial pm;
+  int       i,dosort;
+
+  pm = &main_scene->material[mat];
+  dosort = pm->dif[3] != diffuse[3].value;
+
+  for (i=0; i<4; i++) {
+    pm->amb[i] = ambient[i].value;
+    pm->dif[i] = diffuse[i].value;
+    pm->spe[i] = specular[i].value;
+    pm->emi[i] = emission[i].value;
+  }
+  pm->shininess = shininess[0].value;
+  return(dosort);
+}
+
+static void cellDraw(cell* cel) {
+  if ( selection == cel->id ) {
+    glColor3ub(255,255,0);
+    drwstr(10, 240,cel->info);
+    glColor3ub(255,0,0);
+  }
+  else
+    glColor3ub(0,255,128);
+  drwstr(cel->x,cel->y,cel->format,cel->value);
+}
+
+static int cellHit(cell* cel,int x,int y) {
+  if ( x > cel->x    && x < cel->x + 60 &&
+       y > cel->y-30 && y < cel->y+10 )
+    return cel->id;
+  else
+    return 0;
+}
+
+static void cellUpdate(cell* cel,int update) {
+  if ( selection != cel->id )
+    return;
+
+  cel->value += update * cel->step;
+
+  if (cel->value < cel->min)
+    cel->value = cel->min;
+  else if (cel->value > cel->max) 
+    cel->value = cel->max;
+}
+
+
+void matsubReshape(int x,int y) {
+  GLfloat    sunpos[4] = {5.,2.,10.0,0.};
+
+  glutSetWindow(m_subwin);
+  glViewport(0,0,200,200);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluPerspective(50.0,1.0,0.01f,100.0f);
+
+  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE);
+  glLightfv(GL_LIGHT0,GL_POSITION,sunpos);  
+  glEnable(GL_LIGHT0);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glTranslatef(0.0,0.0,-5.0);
+  glutSetWindow(matwin);
+}
+
+void matsubDisplay() {
+  GLfloat    amb[4],dif[4],emi[4],spe[4];
+  int        i,transp;
+
+  glutSetWindow(m_subwin);
+  glDisable(GL_COLOR_MATERIAL);
+  glDisable(GL_LIGHTING);
+  glClearColor(0.0f,0.0f,0.0f,1.0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glBegin(GL_QUADS);
+    glColor3f(0.8,0.,0.);
+    glVertex3f(-2.0,-1.5,-2.0);
+    glVertex3f( 0.0,-1.5,-2.0);
+    glVertex3f( 0.0,-1.5,5.0);
+    glVertex3f(-2.0,-1.5,5.0);
+    
+    glColor3f(0.,0.8,0.);
+    glVertex3f( 0.0,-1.5,-2.0);
+    glVertex3f( 2.0,-1.5,-2.0);
+    glVertex3f( 2.0,-1.5,5.0);
+    glVertex3f( 0.0,-1.5,5.0);
+    
+    glColor3f(0.,0.,0.8);
+    glVertex3f( 0.0,-1.5,-5.0);
+    glVertex3f( 2.0,-1.5,-5.0);
+    glVertex3f( 2.0,-1.5,-2.0);
+    glVertex3f( 0.0,-1.5,-2.0);
+
+    glColor3f(0.4,0.4,0.4);
+    glVertex3f(-2.0,-1.5,-5.0);
+    glVertex3f( 0.0,-1.5,-5.0);
+    glVertex3f( 0.0,-1.5,-2.0);
+    glVertex3f(-2.0,-1.5,-2.0);
+  glEnd();  
+
+  glEnable(GL_LIGHTING);
+  transp = ambient[3].value < 0.999 || 
+           diffuse[3].value < 0.999 || specular[3].value < 0.999;
+  if ( transp ) {
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+    glDepthMask(GL_FALSE);
+  }
+  for (i=0; i<4; i++) {
+    amb[i] = ambient[i].value;
+    dif[i] = diffuse[i].value;
+    spe[i] = specular[i].value;
+    emi[i] = emission[i].value;
+  }
+  glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,dif);
+  glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,amb);
+  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,spe);
+  glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,emi);
+  glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,&shininess[0].value);
+
+  glutSolidSphere(1.5,20,10);
+  if ( transp ) {
+    glDepthMask(GL_TRUE);
+    glDisable(GL_BLEND);
+  }
+  glutSwapBuffers();
+  glutSetWindow(matwin);
+}
+
+/* display mat properties */
+void matDisplay() {
+  pMaterial  pm;
+
+  glutSetWindow(matwin);
+  glClearColor(0.1,0.1,0.1,1.0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  pm = &main_scene->material[refmat];
+
+  glColor3ub(255,255,0);
+  setFont("helvetica", 18);
+  drwstr(10,20,pm->name);
+
+  glColor3ub(255,255,255);
+  setFont("helvetica", 18);
+  drwstr(30,ambient[0].y,"Ambient(");
+  drwstr(170,ambient[0].y,",");
+  drwstr(230,ambient[1].y,","); 
+  drwstr(290,ambient[2].y,",");
+  drwstr(350,ambient[3].y,");");
+
+  cellDraw(&ambient[0]);
+  cellDraw(&ambient[1]);
+  cellDraw(&ambient[2]);
+  cellDraw(&ambient[3]);
+
+  glColor3ub(255,255,255);
+  drwstr(40,diffuse[0].y,"Diffuse(");
+  drwstr(170,diffuse[0].y,",");
+  drwstr(230,diffuse[1].y,","); 
+  drwstr(290,diffuse[2].y,",");
+  drwstr(350,diffuse[3].y,");");
+
+  cellDraw(&diffuse[0]);
+  cellDraw(&diffuse[1]);
+  cellDraw(&diffuse[2]);
+  cellDraw(&diffuse[3]);
+
+  glColor3ub(255,255,255);
+  drwstr(25,specular[0].y,"Specular(");
+  drwstr(170,specular[0].y,",");
+  drwstr(230,specular[1].y,","); 
+  drwstr(290,specular[2].y,",");
+  drwstr(350,specular[3].y,");");
+
+  cellDraw(&specular[0]);
+  cellDraw(&specular[1]);
+  cellDraw(&specular[2]);
+  cellDraw(&specular[3]);
+
+  glColor3ub(255,255,255);
+  drwstr(25,emission[0].y,"Emission(");
+  drwstr(170,emission[0].y,",");
+  drwstr(230,emission[1].y,","); 
+  drwstr(290,emission[2].y,",");
+  drwstr(350,emission[3].y,");");
+
+  cellDraw(&emission[0]);
+  cellDraw(&emission[1]);
+  cellDraw(&emission[2]);
+  cellDraw(&emission[3]);
+
+  glColor3ub(255,255,255);
+  drwstr(20,shininess[0].y,"Shininess(");
+  drwstr(350,shininess[0].y,");");
+  cellDraw(&shininess[0]);
+
+  if ( !selection ) {
+    glColor3ub(255,255,0);
+    setFont("helvetica",18);
+    drwstr(10,240,"Click and move the mouse to modify values ('A' to apply).");
+  }
+
+  glutSwapBuffers();
+}
+
+static int old_y = 0;
+
+void matMouse(int button,int state,int x,int y) {
+  glutSetWindow(matwin);
+  selection = 0;
+  if ( button != GLUT_LEFT_BUTTON ) return; 
+  if ( state == GLUT_DOWN ) {
+    /* mouse should only hit _one_ of the cells, so adding up all
+       the hits just propagates a single hit. */
+    selection += cellHit(&ambient[0],x,y);
+    selection += cellHit(&ambient[1],x,y);
+    selection += cellHit(&ambient[2],x,y);
+    selection += cellHit(&ambient[3],x,y);
+    selection += cellHit(&diffuse[0],x,y);
+    selection += cellHit(&diffuse[1],x,y);
+    selection += cellHit(&diffuse[2],x,y);
+    selection += cellHit(&diffuse[3],x,y);
+    selection += cellHit(&specular[0],x,y);
+    selection += cellHit(&specular[1],x,y);
+    selection += cellHit(&specular[2],x,y);
+    selection += cellHit(&specular[3],x,y);
+    selection += cellHit(&emission[0],x,y);
+    selection += cellHit(&emission[1],x,y);
+    selection += cellHit(&emission[2],x,y);
+    selection += cellHit(&emission[3],x,y);
+    selection += cellHit(&shininess[0],x,y);
+  }
+  else {
+    /* update material */
+    glutSetWindow(m_subwin);
+  }
+  old_y = y;
+  glutPostRedisplay();
+}
+
+static void matMotion(int x,int y) {
+  cellUpdate(&ambient[0],old_y-y);
+  cellUpdate(&ambient[1],old_y-y);
+  cellUpdate(&ambient[2],old_y-y);
+  cellUpdate(&ambient[3],old_y-y);
+
+  cellUpdate(&diffuse[0],old_y-y);
+  cellUpdate(&diffuse[1],old_y-y);
+  cellUpdate(&diffuse[2],old_y-y);
+  cellUpdate(&diffuse[3],old_y-y);
+
+  cellUpdate(&specular[0],old_y-y);
+  cellUpdate(&specular[1],old_y-y);
+  cellUpdate(&specular[2],old_y-y);
+  cellUpdate(&specular[3],old_y-y);
+
+  cellUpdate(&emission[0],old_y-y);
+  cellUpdate(&emission[1],old_y-y);
+  cellUpdate(&emission[2],old_y-y);
+  cellUpdate(&emission[3],old_y-y);
+
+  cellUpdate(&shininess[0],old_y-y);
+  old_y = y;
+  glutPostRedisplay();
+
+  glutSetWindow(m_subwin);
+  glutPostRedisplay();
+}
+
+void matKeyboard(unsigned char key,int x,int y) {
+
+  if ( isdigit(key) )  return;
+  glutSetWindow(matwin);
+
+  switch(key) {
+  case 'a':
+  case 'A':
+    if ( cellCopy(refmat) )
+      matSort(main_scene);
+    matwin = 0;
+    glutHideWindow();
+    /*glutPostRedisplay();*/
+    glutSetWindow(main_scene->idwin);
+    doLists(main_scene,cv.mesh[main_scene->idmesh]);
+    glutPostRedisplay();
+    break;
+  case 'q':
+  case 27:
+    matwin = 0;
+    glutHideWindow();
+    glutPostRedisplay();
+    break;
+  }
+}
+
+void matEdit(pScene sc) {
+  /* init window */
+  if ( matwin || refmat < 0 )  return;
+  matwin = m_subwin = 0;
+
+  /* create 2d window */
+  glutInitWindowSize(Width,Height);
+  matwin = glutCreateWindow("Material Properties");
+  if ( !matwin ) return;
+  main_scene = sc;
+
+  /* set callbacks */
+  glutSetIconTitle("MatProp");
+  glutReshapeFunc(matReshape);
+  glutDisplayFunc(matDisplay); 
+  glutKeyboardFunc(matKeyboard);
+  glutMouseFunc(matMouse);
+  glutMotionFunc(matMotion);
+
+  /* create 3d sub-window */
+  glutSetWindow(matwin);
+  m_subwin = glutCreateSubWindow(matwin,400,20,200,200);
+  if ( ddebug)   printf("window %d\n",(int)matwin);
+  glutDisplayFunc(matsubDisplay);
+  glutReshapeFunc(matsubReshape);
+
+  glutSetWindow(matwin);
+  cellInit(refmat);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/medit.c b/src/medit/medit.c
new file mode 100644
index 0000000..64a566d
--- /dev/null
+++ b/src/medit/medit.c
@@ -0,0 +1,439 @@
+/* medit.c      mesh visualization tool
+ *
+ * Written by Pascal Frey, LJLL
+ * Copyright (c) Inria, 1999-2007. All rights reserved. */
+
+#include "medit.h"
+#include "compil.date"
+#ifdef ppc
+#include <unistd.h>
+#endif
+
+
+/* global variables (see extern.h) */
+GLboolean hasStereo = 1;
+Canvas    cv;
+mytime    ctim[TIMEMAX]; 
+ubyte     ddebug,animate,saveimg,imgtype,infogl,fullscreen;
+ubyte     quiet,option,morphing,stereoMode;
+int       menu,amenu,fmenu,femenu,vmenu,mmenu,smenu;
+int       clmenu,cmenu,vwmenu,txmenu,trmenu;
+int       animdep,animfin;
+
+/**********************/
+/*  Rajout pour popen */
+ubyte     dpopen,dpopensol,dpopenbin;
+
+static void excfun(int sigid) {
+  fprintf(stdout,"\n Unexpected error:");  fflush(stdout);
+  switch(sigid) {
+    case SIGABRT:
+      fprintf(stdout,"  Abnormal stop\n");  break;
+    case SIGFPE:
+      fprintf(stdout,"  Floating-point exception\n"); break;
+    case SIGILL:
+      fprintf(stdout,"  Illegal instruction\n"); break;
+    case SIGSEGV:
+      fprintf(stdout,"  Segmentation fault\n");  break;
+    case SIGTERM:
+    case SIGINT:
+      fprintf(stdout,"  Program killed\n");  break;
+  }
+  exit(1);
+}
+
+
+static void endcod() {
+  chrono(OFF,&ctim[0]);
+  fprintf(stdout,"\n Total running seconds:  %.2f\n",gttime(ctim[0]));
+  fprintf(stdout," Thank you for using Medit.\n");
+}
+
+
+static void grInfo(void) {
+  GLboolean  b;
+  GLint      i,win;
+
+  win = glutCreateWindow("Info");
+  fprintf(stdout,"Graphic info:\n");
+  fprintf(stdout," GL Vendor:\t%s\n",glGetString(GL_VENDOR));
+  fprintf(stdout," GL Version:\t%s\n",glGetString(GL_VERSION));
+  fprintf(stdout," GL Renderer:\t%s\n\n",glGetString(GL_RENDERER));
+  glGetBooleanv(GL_RGBA_MODE,&b);
+  if ( b )  fprintf(stdout,"  RGBA Mode\n");
+  glGetBooleanv(GL_DOUBLEBUFFER,&b);
+  if ( b )  fprintf(stdout,"  Double Buffer\n");
+  glGetBooleanv(GL_STEREO,&b);
+  if ( b )  fprintf(stdout,"  Stereo\n");
+  glGetIntegerv(GL_AUX_BUFFERS,&i);
+  if ( i )  fprintf(stdout,"  Auxilary Buffers\t%2d\n",(int)i);
+  glGetIntegerv(GL_INDEX_BITS,&i);
+  if ( i )  fprintf(stdout,"  Index Bits\t\t%2d\n",(int)i);
+  glGetIntegerv(GL_RED_BITS,&i);
+  fprintf(stdout,"  RGBA Bits\t\t%2d",(int)i);
+  glGetIntegerv(GL_GREEN_BITS,&i);
+  fprintf(stdout,"\t%2d",(int)i);
+  glGetIntegerv(GL_BLUE_BITS,&i);
+  fprintf(stdout,"\t%2d",(int)i);
+  glGetIntegerv(GL_ALPHA_BITS,&i);
+  fprintf(stdout,"\t%2d\n",(int)i);
+  glGetIntegerv(GL_ACCUM_RED_BITS,&i);
+  fprintf(stdout,"  Accum RGBA Bits\t%2d",(int)i);
+  glGetIntegerv(GL_ACCUM_GREEN_BITS,&i);
+  fprintf(stdout,"\t%2d",(int)i);
+  glGetIntegerv(GL_ACCUM_BLUE_BITS,&i);
+  fprintf(stdout,"\t%2d",(int)i);
+  glGetIntegerv(GL_ACCUM_ALPHA_BITS,&i);
+  fprintf(stdout,"\t%2d\n",(int)i);
+  glGetIntegerv(GL_DEPTH_BITS,&i);
+  fprintf(stdout,"  Depth Bits\t\t%2d\n",(int)i);
+  glGetIntegerv(GL_STENCIL_BITS,&i);
+  fprintf(stdout,"  Stencil Bits\t\t%2d\n",(int)i);
+  
+  exit(1);
+}
+
+
+int medit0() {
+  pMesh    mesh;
+  char     data[128],*name;
+  int      k,l,ret;
+  clock_t  ct;
+
+  /* default */
+  //  fprintf(stdout," \n medit0() \n");
+  fprintf(stdout," Loading data file(s)\n");
+  ct = clock();
+
+  /* enter name */
+  if ( !cv.nbm ) {
+    fprintf(stdout,"  File name(s) missing. Please enter : ");
+    fflush(stdout); fflush(stdin);
+    fgets(data,120,stdin);
+    if ( !strlen(data) ) {
+      fprintf(stdout,"  ## No data\n");
+      return(0);
+    }
+
+    /* parse file name(s) */
+    name = strtok(data," \n");
+    while( name ) {
+      if ( !cv.mesh[cv.nbm] ) {
+        cv.mesh[cv.nbm] = (pMesh)M_calloc(1,sizeof(Mesh),"medit0.mesh");
+        if ( !cv.mesh[cv.nbm] )  return(0);
+      }
+      /*(cv.mesh[cv.nbm])->name = calloc(strlen(name)+1,sizeof(char));*/
+      strcpy(cv.mesh[cv.nbm]->name,name);
+      name = strtok(NULL," \n\0");
+      if ( ++cv.nbm == MAX_MESH )  break;
+    }
+    if ( !cv.nbm ) return(0);
+  }
+
+  if ( !cv.nbm ) { 
+    fprintf(stdout,"  Number of mesh missing:. Please enter : "); 
+    fflush(stdout); fflush(stdin);
+    fgets(data,120,stdin);
+    cv.nbm = atoi(data);
+  }
+
+  /* read mesh(es) */
+  k = 0;
+  do {
+    if ( !cv.mesh[k] ) {
+      cv.mesh[k] = M_calloc(1,sizeof(Mesh),"medit0.mesh");
+      if ( !cv.mesh[k] )  return(0);
+    }
+    mesh = cv.mesh[k];
+    mesh->typ = 0;
+    ret  = loadMesh(mesh);
+    if ( ret < 0 ) {
+      mesh->typ = 1;
+      ret = inmsh2(mesh);
+      if ( !ret ) {
+        mesh->typ = 2;
+        ret = loadGIS(mesh);
+      }
+    }
+    if ( ret <= 0 ) {
+      for (l=k+1; l<cv.nbm; l++)
+	    cv.mesh[l-1] = cv.mesh[l];
+      cv.nbm--;
+      k--;
+      continue;
+    }
+
+    /* compute mesh box */  
+    if ( (mesh->ntet && !mesh->nt) || (mesh->nhex && !mesh->nq) )  
+      meshSurf(mesh);
+    meshBox(mesh,1);
+    if ( !quiet )  meshInfo(mesh);
+
+    /* read metric  */   
+    if ( !loadSol(mesh,mesh->name,1) )
+      bbfile(mesh);
+    if ( !quiet && mesh->nbb )
+      fprintf(stdout,"    Solutions  %8d\n",mesh->nbb);
+  }
+  while ( ++k < cv.nbm );
+  cv.nbs = cv.nbm;
+
+  ct = difftime(clock(),ct);
+  fprintf(stdout,"  Input seconds:     %.2f\n",
+          (double)ct/(double)CLOCKS_PER_SEC);
+
+  return(cv.nbm);
+}
+
+
+int medit0_popen() {
+  pMesh    mesh;
+  char     data[128],*name;
+  int      k,l,ret;
+  clock_t  ct;
+
+  /* default */
+  /*fprintf(stdout," \n medit0() \n");*/
+  fprintf(stdout," Loading data file(s)\n");
+  ct = clock();
+
+
+  /* enter number of mesh */
+  if ( !cv.nbm ) { 
+    fprintf(stdout,"  Number of mesh missing:. Please enter : "); 
+    fflush(stdout); fflush(stdin);
+    fgets(data,128,stdin);
+    cv.nbm = atoi(data);
+  }
+
+  /* read mesh(es) */
+  k = 0;
+  do {
+    // printf("mesh number %i\n",k+1);
+    if ( !cv.mesh[k] ) {
+      cv.mesh[k] = M_calloc(1,sizeof(Mesh),"medit0.mesh");
+      if ( !cv.mesh[k] )  return(0);
+    }
+    mesh = cv.mesh[k];
+    mesh->typ = 0;
+
+    //fgets(data,128,stdin);
+    //name = data;
+    //printf("data=%s\n",data);
+    //name = "toto.dat";
+    //strcpy(cv.mesh[k]->name,name);
+
+    if(dpopenbin) 
+      ret  = loadMesh_popen_bin(mesh);
+    else
+      ret  = loadMesh_popen(mesh);
+
+    /* compute mesh box */  
+    if ( (mesh->ntet && !mesh->nt) || (mesh->nhex && !mesh->nq) )  
+      meshSurf(mesh);
+    meshBox(mesh,1);
+    if ( !quiet )  meshInfo(mesh);
+
+    /*  /\* read metric *\/     // a changer lecture .sol et .bb */
+    /*    if ( !loadSol_popen(mesh,mesh->name,1) ) */
+    /*       bbfile_popen(mesh); */
+    /*     if ( !quiet && mesh->nbb ) */
+    /*       fprintf(stdout,"    Solutions  %8d\n",mesh->nbb); */
+    if( dpopensol ){
+      if(dpopenbin) 
+	loadSol_popen_bin(mesh,mesh->name,1);
+      else
+	loadSol_popen(mesh,mesh->name,1);
+    }
+    if ( !quiet && mesh->nbb )
+      fprintf(stdout,"    Solutions  %8d\n",mesh->nbb);
+  }
+  while ( ++k < cv.nbm );
+  cv.nbs = cv.nbm;
+
+  ct = difftime(clock(),ct);
+  fprintf(stdout,"  Input seconds:     %.2f\n",
+          (double)ct/(double)CLOCKS_PER_SEC);
+
+  return(cv.nbm);
+}
+
+int medit1() {
+  pScene   scene;
+  pMesh    mesh;
+  int      k;
+  clock_t  ct;
+
+  /* create grafix */
+  fprintf(stdout,"\n medit1() \n");
+  fprintf(stdout,"\n Building scene(s)\n");
+  ct = clock();
+  for (k=0; k<cv.nbs; k++) {
+    if ( !cv.scene[k] ) {
+      cv.scene[k] = (pScene)M_calloc(1,sizeof(Scene),"medit1.scene");
+      if ( !cv.scene[k] )  return(0);
+    }
+    scene = cv.scene[k];
+    if ( !cv.mesh[k] ) {
+      cv.mesh[k] = (pMesh)M_calloc(1,sizeof(Mesh),"medit1.mesh");
+      if ( !cv.mesh[k] )  return(0);
+    }
+    mesh  = cv.mesh[k];
+
+    fprintf(stdout,"  Creating scene %d\n",k+1);
+    parsop(scene,mesh);
+    meshRef(scene,mesh);
+    matSort(scene);
+    
+    if ( option == ISOSURF ) {
+	  if ( !mesh->nbb ) return(0);
+      setupPalette(scene,mesh);
+	  tetraIsoPOVray(scene,mesh);
+	}
+    else if ( !createScene(scene,k) ) {
+      fprintf(stderr,"  ## Unable to create scene\n");
+      return(0);
+    }
+  }
+  ct = difftime(clock(),ct);
+  fprintf(stdout,"  Scene seconds:     %.2f\n",(double)ct/(double)CLOCKS_PER_SEC);
+
+  return(1);
+}
+
+
+int main(int argc,char *argv[]) {
+  int    type;
+  char   pwd[1024];
+
+#ifdef ppc
+  if ( !getwd(pwd) )  exit(2);
+#endif
+
+  fprintf(stdout,"  -- Medit,  Release %s (%s)\n",ME_VER,ME_REL);
+  fprintf(stdout,"     %s.\n",ME_CPY);
+  fprintf(stdout,"     compiled: %s.\n\n",COMPIL);
+
+  /* trap exceptions */
+  signal(SIGABRT,excfun);
+  signal(SIGFPE,excfun);
+  signal(SIGILL,excfun);
+  signal(SIGSEGV,excfun);
+  signal(SIGTERM,excfun);
+  signal(SIGINT,excfun);
+  atexit(endcod);
+
+  tminit(ctim,TIMEMAX);
+  chrono(ON,&ctim[0]);
+
+  /* default values */
+  option     = STANDARD;
+  saveimg    = GL_FALSE;
+  imgtype    = P6;
+  animate    = FALSE;
+  morphing   = FALSE;
+  fullscreen = FALSE;
+  animdep    = 0;
+  animfin    = 0;
+  ddebug     = FALSE;
+  quiet      = TRUE;//FALSE;
+  stereoMode = 0;
+  cv.nbm = cv.nbs = 0;
+
+  /* default value for popen */
+  dpopen = FALSE;
+  dpopenbin = FALSE;
+  dpopensol = FALSE;
+
+  /* init grafix */
+  parsar(argc,argv);
+  //printf("fin de parsar");
+
+  if ( option == ISOSURF ) {
+    fprintf(stdout,"ISOSURF");
+    if ( !medit0() )  exit(1);
+    if ( !medit1() )  exit(1);
+    return(0);
+  }
+
+  glutInit(&argc,argv);
+  //printf("fin de glutInit");
+#ifdef ppc
+  chdir(pwd);
+#endif
+
+  chrono(ON,&ctim[0]);
+  if ( stereoMode == MONO )
+    type = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH;
+  else
+    type = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STEREO;
+  glutInitDisplayMode(type);
+  if ( infogl )  grInfo();
+
+  /* call animate or normal mode */
+  if( dpopen == FALSE ){
+    
+    switch (option) {
+    case STANDARD:
+
+    case SCHNAUZER:
+      if ( !medit0() )  exit(1);
+      if ( !medit1() )  exit(1);
+      break;
+    case SEQUENCE:
+      if ( !animat() )  exit(1);
+      break;
+    case SEQUENCE+PARTICLE:
+      
+      if ( !animat() )  exit(1);
+      break;
+    case MORPHING:
+      
+      if ( !medit0() )  exit(1);
+      if ( !modeMorphing() )  exit(1);
+      morphing = GL_FALSE;
+      break;
+    default:
+      fprintf(stderr,"  ## Unrecognized option %d\n",option);
+      exit(1);
+      break;
+    }
+  }
+  else{
+   switch (option) {
+   case STANDARD:
+     
+   case SCHNAUZER:
+     
+     if ( !medit0_popen() )  exit(1);
+     if ( !medit1() )  exit(1);
+     break;
+  
+  case SEQUENCE:
+    
+    if ( !animat() )  exit(1);
+    break;
+  case SEQUENCE+PARTICLE:
+    
+    if ( !animat() )  exit(1);
+    break;
+  case MORPHING:
+    
+    if ( !medit0_popen() )  exit(1);
+    if ( !modeMorphing() )  exit(1);
+    morphing = GL_FALSE;
+    break;
+  default:
+    fprintf(stderr,"  ## Unrecognized option %d\n",option);
+    exit(1);
+    break;
+  }
+  }
+
+  /* main grafix loop */
+  fprintf(stdout,"\n Rendering scene(s)\n");
+  glGetBooleanv(GL_STEREO,&hasStereo);
+  glutMainLoop();
+
+  return(0);
+}
diff --git a/src/medit/medit.h b/src/medit/medit.h
new file mode 100644
index 0000000..8ff0049
--- /dev/null
+++ b/src/medit/medit.h
@@ -0,0 +1,91 @@
+#ifndef _MEDIT_H
+#define _MEDIT_H
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+#include <time.h>
+#include <string.h>
+#include <float.h>
+#include <signal.h>
+#include <ctype.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#ifdef __APPLE__
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#include <GLUT/glut.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glut.h>
+#endif
+
+#include "chrono.h"
+#include "memory.h"
+#include "mesh.h"
+#include "grafic.h"
+#include "image.h"
+#include "sproto.h"
+
+#define ME_VER   "3.0a"
+#define ME_REL   "Nov. 30, 2007"
+#define ME_CPY   "Copyright (c) LJLL, 1999-2007"
+#define ME_STR   "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
+#define DEFAULT_FILE    "DEFAULT.medit"
+
+#define MAX_MESH      32
+#define MAX_SCENE     32
+#define MAX_OBJ       32
+#define MAX_MATERIAL 128
+#define DEFAULT_MAT    0
+
+#define DTOR       0.0174532925
+#define RTOD      57.29577951308232
+#define EPS            1.e-06
+#define EPS2           2.e-10
+
+#ifndef  TRUE
+#define  TRUE   1
+#define  FALSE  0
+#endif
+#ifdef M_PI
+#undef M_PI
+#undef M_PI_2
+#endif
+#define M_PI            3.14159265358979323846   /* pi   */
+#define M_PI_2          1.57079632679489661923   /* pi/2 */
+
+#ifdef min
+#undef min
+#undef max
+#endif
+#define  min(a,b)       ( ((a) < (b)) ? (a) : (b) )
+#define  max(a,b)       ( ((b) > (a)) ? (b) : (a) )
+
+/* check if numbers are equal */ 
+#define egal(x,y)   ( \
+  (  ((x) == 0.0f) ? (fabs(y) < EPS) : \
+   ( ((y) == 0.0f) ? (fabs(x) < EPS) : \
+     (fabs((x)-(y)) / (fabs(x) + fabs(y)) < EPS2) )  ) )
+
+
+/* options */
+enum { STANDARD=1, SEQUENCE, VERYBIG, MORPHING, SCHNAUZER, ISOSURF, PARTICLE};
+
+
+/* structure canvas */
+typedef struct canvas {
+  pMesh      mesh[MAX_MESH];
+  pScene     scene[MAX_SCENE];
+  int        nbm,nbs;
+} Canvas;
+typedef Canvas * pCanvas;
+
+
+
+#endif
diff --git a/src/medit/menus.c b/src/medit/menus.c
new file mode 100644
index 0000000..1337024
--- /dev/null
+++ b/src/medit/menus.c
@@ -0,0 +1,1181 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+GLfloat    altcoef=0.0;
+static int nbimg;
+extern int refitem,refmat,reftype,imstep,imreverse;
+extern int *pilmat,ipilmat;
+
+#define MAX_LST   128
+
+
+/* rebuild display lists */
+void doLists(pScene sc,pMesh mesh) {
+  int     k;
+
+  /*default */
+  if ( ddebug ) printf("build display lists\n");
+
+  if ( !morphing )  glutSetCursor(GLUT_CURSOR_WAIT);
+  for (k=0; k<MAX_LIST; k++) {
+    if ( sc->dlist[k] )  glDeleteLists(sc->dlist[k],1);
+    if ( sc->clist[k] )  glDeleteLists(sc->clist[k],1);
+    sc->dlist[k] = sc->clist[k] = (GLuint)0;
+  }
+
+  /* poly lists */
+  sc->dlist[LTria] = listTria(sc,mesh);
+  sc->dlist[LQuad] = listQuad(sc,mesh);
+  if ( !mesh->nt && !mesh->nq ) {
+    sc->dlist[LTets] = listTetra(sc,mesh,0);
+    sc->dlist[LHexa] = listHexa(sc,mesh,0);
+  }
+  if ( sc->clip->active & C_VOL )  sc->clip->active |= C_REDO;
+  glutSetCursor(GLUT_CURSOR_INHERIT);
+  checkErrors();
+}
+
+
+/* build metric list */
+void doMapLists(pScene sc,pMesh mesh,int reset) {
+  int   k;
+
+  /*default */
+  if ( !mesh->sol )  return;
+  if ( ddebug ) printf("build map lists\n");
+  glutSetCursor(GLUT_CURSOR_WAIT);
+
+  /* delete old lists */
+  if ( reset ) {
+    for (k=0; k<MAX_LIST; k++) {
+      if ( sc->mlist[k] )  glDeleteLists(sc->mlist[k],1);
+      sc->mlist[k] = (GLuint)0;
+    }
+  }
+
+  /* create map list */
+  if ( sc->mode & S_ALTITUDE ) {
+    sc->mlist[LTria] = alt2dList(sc,mesh,LTria,sc->shrink,altcoef);
+    sc->mlist[LQuad] = alt2dList(sc,mesh,LQuad,sc->shrink,altcoef);
+  }
+  else if ( sc->mode & S_MAP ) {
+    if ( mesh->nt && !sc->mlist[LTria] )
+      sc->mlist[LTria] = listTriaMap(sc,mesh);
+    if ( mesh->nq && !sc->mlist[LQuad] )
+      sc->mlist[LQuad] = listQuadMap(sc,mesh);
+    if ( !mesh->nt && mesh->ntet && !sc->mlist[LTets] )
+      sc->mlist[LTets] = listTetraMap(sc,mesh,0);
+    if ( !mesh->nq && mesh->nhex && !sc->mlist[LHexa] )
+      sc->mlist[LHexa] = listHexaMap(sc,mesh,0);
+  }
+
+  glutSetCursor(GLUT_CURSOR_INHERIT);
+  checkErrors();
+}
+
+
+/* rebuild iso-values lists */
+void doIsoLists(pScene sc,pMesh mesh,int reset) {
+  pPoint  ppt;
+  int     k,kk,ret;
+  
+  /*default */
+  if ( ddebug ) printf("build iso lists\n");
+  glutSetCursor(GLUT_CURSOR_WAIT);
+
+  /* delete old lists */
+  if ( reset ) {
+    for (k=0; k<MAX_LIST; k++) {
+      if ( sc->ilist[k] )  glDeleteLists(sc->ilist[k],1);
+      if ( sc->vlist[k] )  glDeleteLists(sc->vlist[k],1);
+      if ( sc->cplist )    glDeleteLists(sc->cplist,1);
+      sc->ilist[k] = sc->vlist[k] = (GLuint)0;
+      sc->cplist   = (GLuint)0;
+    }
+    if ( sc->stream && sc->stream->nbstl ) {
+      for (kk=0; kk<sc->stream->nbstl; kk++) {
+        if ( sc->slist[kk] )  glDeleteLists(sc->slist[kk],1);
+        sc->slist[kk] = (GLuint)0;
+      }
+      sc->slist = (GLuint)0;
+      if ( reset < 2 )   sc->stream->nbstl = 0;
+      for (k=1; k<=mesh->np; k++) {
+        ppt = &mesh->point[k];
+        ppt->flag = 0;
+      }
+    }
+  }
+
+  /* iso-lines */
+  if ( sc->isotyp & S_ISOLINE ) {
+    if ( mesh->nt && !sc->ilist[LTria] )
+      sc->ilist[LTria] = listTriaIso(sc,mesh);
+    if ( mesh->nq && !sc->ilist[LQuad] )
+      sc->ilist[LQuad] = listQuadIso(sc,mesh);
+  }
+  /* iso-surfaces */
+  if ( sc->isotyp & S_ISOSURF ) {
+    if ( mesh->ntet && !sc->ilist[LTets] )
+      sc->ilist[LTets] = listTetraIso(sc,mesh);
+  }
+
+  /* vector */
+  if ( sc->isotyp & S_VECTOR ) {
+    if ( mesh->dim == 2 ) {
+      if ( mesh->nt && !sc->vlist[LTria] )
+        sc->vlist[LTria] = listTria2dVector(mesh);
+      if ( mesh->nq && !sc->vlist[LQuad] )
+        sc->vlist[LQuad] = listQuad2dVector(mesh);
+    }
+    else {
+      if ( mesh->ntet+mesh->nhex == 0 ) {
+        sc->vlist[LTria] = listTria3dVector(mesh);
+      }
+      else {
+        if ( mesh->ntet && !sc->vlist[LTets] )
+          sc->vlist[LTets] = listClipTetraVector(mesh);
+        else if ( mesh->nhex && !sc->vlist[LHexa] )
+          sc->vlist[LHexa] = listClipHexaVector(mesh);
+      }
+    }
+  }
+
+  /* streamlines */
+  if ( sc->isotyp & S_STREAML ) {
+    if ( !mesh->adja || !sc->slist ) {
+      sc->stream = createStream(sc,mesh);
+      if ( !sc->stream )
+        sc->isotyp &= ~S_STREAML;
+    }
+    if ( sc->stream ) {
+      if ( reftype == LPoint )
+        ret = streamRefPoint(sc,mesh);
+      else if ( mesh->dim == 3 ) {
+        if ( reftype == LTria )
+          ret = streamRefTria(sc,mesh);
+        else if ( reftype == LQuad )
+          ret = streamRefQuad(sc,mesh);
+        if ( sc->picklist )  glDeleteLists(sc->picklist,1);
+        sc->picklist = 0;
+      }
+    }
+  }
+
+  /* critical points */
+  if ( sc->isotyp & S_CRITP ) {
+    if ( mesh->dim == 2 )
+      if ( mesh->nt && !sc->cplist )
+        sc->cplist = listCritPoint(sc,mesh);
+  }
+  
+  glutSetCursor(GLUT_CURSOR_INHERIT);
+  checkErrors();
+}
+
+
+void resetLists(pScene sc,pMesh mesh) {
+  int    kk;
+
+  for (kk=0; kk<MAX_LIST; kk++) {
+    if ( sc->dlist[kk] )  glDeleteLists(sc->dlist[kk],1);
+    if ( sc->mlist[kk] )  glDeleteLists(sc->mlist[kk],1);
+    if ( sc->ilist[kk] )  glDeleteLists(sc->ilist[kk],1);
+    if ( sc->clist[kk] )  glDeleteLists(sc->clist[kk],1);
+    if ( sc->cmlist[kk] ) glDeleteLists(sc->cmlist[kk],1);
+    if ( sc->vlist[kk] )  glDeleteLists(sc->vlist[kk],1);
+    if ( sc->cplist )     glDeleteLists(sc->cplist,1);
+    sc->dlist[kk] = sc->clist[kk] = sc->mlist[kk] = (GLuint)0;
+    sc->ilist[kk] = sc->vlist[kk] = sc->cplist    = (GLuint)0;
+  }
+  if ( sc->glist )  glDeleteLists(sc->glist,1);
+  if ( sc->nlist )  glDeleteLists(sc->nlist,1);
+  sc->glist = sc->nlist = (GLuint)0;
+}
+
+
+void keyFile(unsigned char key,int x,int y) {
+  pScene       sc;
+  pMesh        mesh;
+  pTransform   view;
+  char        *ptr,data[128];
+  ubyte        post  = FALSE,clipon;
+  static int   nfree = 0;
+
+  /* default */
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  view = sc->view;
+
+  switch(key) {
+  case 'L':  /* load prefs */
+    if ( parsop(sc,mesh) ) {
+      refitem = reftype = 0;
+      setupPalette(sc,mesh);
+      initGrafix(sc,mesh);
+      doLists(sc,mesh);
+      if ( sc->mode & S_MAP )  doMapLists(sc,mesh,1);
+      if ( sc->isotyp )        doIsoLists(sc,mesh,1);
+      glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
+      post = GL_TRUE;
+    }
+    break;
+  case 'W':  /* save prefs */
+    saveMeditFile(mesh->name,sc);
+    break;
+
+  case 'R':  /* reload mesh */
+    refitem = reftype = 0;
+    if ( !meshUpdate(sc,mesh) ) exit(1);
+    meshRef(sc,mesh);
+    matSort(sc);
+    setupPalette(sc,mesh);
+    doLists(sc,mesh);
+    if ( sc->mode & S_MAP ) doMapLists(sc,mesh,1);
+    if ( sc->isotyp )       doIsoLists(sc,mesh,1);
+    glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
+    post = GL_TRUE;
+    break;
+  
+  case 'S':  /* save mesh */
+    strcpy(data,mesh->name);
+    ptr = (char*)strstr(data,".mesh");
+    if ( ptr ) *ptr = '\0';
+    sprintf(data,"%s.d.mesh",data);
+    clipon = sc->clip->active & C_ON;
+    if ( clipon )
+      clipVertices(mesh,sc,sc->clip);
+    saveMesh(sc,mesh,data,clipon);
+    break;
+    
+  case 'B':
+  case 'C':
+  case 'G':
+  case 'H':  /* hardcopy */
+  case 'T':
+    strcpy(data,mesh->name);
+    ptr = (char*)strstr(data,".mesh");
+    if ( ptr ) *ptr = '\0';
+    ptr = (char*)strstr(data,".gis");
+    if ( ptr ) *ptr = '\0';
+
+    if ( option != SEQUENCE ) {
+      if ( key == 'H' )
+        nfree = filnum(data,nfree,"ppm");
+      else
+        nfree = filnum(data,nfree,"ps");
+      if ( nfree == -1 )  break;
+      sprintf(data,"%s.%.3d",data,nfree);
+    }
+    else
+      sprintf(data,"%s.ppm",data);
+    if (!saveimg )  glutSetCursor(GLUT_CURSOR_WAIT);
+    if ( key == 'B' || key == 'C' || key == 'G' )
+      imgTiling(sc,data,key);
+    else
+      imgHard(sc,data,key);
+    if ( animate && !(sc->persp->pmode & CAMERA) && ++nbimg > 179 ) {
+      view->angle = 0.0;
+      nbimg       = 0;
+      keyAnim('A',0,0);
+    }
+    if (!saveimg ) glutSetCursor(GLUT_CURSOR_INHERIT);
+    break;
+  case 's':  /* softcopy */
+    sftcpy(sc,mesh);
+    post = FALSE;
+    break;
+  }
+  if ( post ) glutPostRedisplay();
+}
+
+void menuFile(int item) {
+  keyFile((unsigned char)item,0,0);
+}
+
+
+void keyItem(unsigned char key,int x,int y) {
+  pScene  sc;
+  pMesh   mesh;
+  pCube   cube;
+  ubyte   post = TRUE;
+
+  /* default */
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  cube = sc->cube;
+
+  switch(key) {
+  case 'A':  /* draw axis */
+    sc->item ^= S_AXIS;
+    break;
+  case 'B':  /* draw bounding box */
+    sc->item ^= S_BOX;
+    break;
+  case 'D':  /*draw selection cube */
+    if ( cube->active & C_ON ) {
+      cube->active &= ~(C_ON+C_EDIT);
+      dumpCube(sc,mesh,cube);
+    }
+    else {
+      cube->active |= C_ON;
+    }
+    break;
+  case 'G':  /* draw grid */
+    sc->item ^= S_GRID;
+    break;
+  case 'j':  /* toggle info */
+    sc->type ^= S_DECO;
+    break;
+  case 'P':  /* toggle point nums */
+    sc->item ^= S_NUMP;
+    break;
+  case 'F':  /* toggle face nums */
+    sc->item ^= S_NUMF;
+    break;
+  case 'g':  /* const. items */
+    if ( !sc->glist )  post = FALSE;
+    sc->item ^= S_GEOM;
+    break;
+  case 'N':
+    if ( mesh->nvn )
+      sc->type ^= S_NORMAL;
+    else
+      post = FALSE;
+    break;
+  case 'O':
+    if ( mesh->nvn ) {
+      sc->type ^= S_OPPOS;
+      if ( sc->nlist ) {
+	glDeleteLists(sc->nlist,1);
+	sc->nlist = 0;
+      }
+      else 
+	post = FALSE;
+    }
+    else
+      post = FALSE;
+    break;
+  }
+  if ( post )  glutPostRedisplay();
+}
+
+void menuItem(int item) {
+  keyItem((unsigned char)item,0,0);
+}
+
+
+void keyAnim(unsigned char key,int x,int y) {
+  pScene  sc;
+  pMesh   mesh;
+  pClip   clip;
+  ubyte   post = TRUE;
+  char   *ptr,base[256];
+  static int depart = -1;
+
+  /* default */
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  clip = sc->clip;
+  if ( depart == -1 )
+    depart = animdep;
+
+  switch(key) {
+  case 'A':  /* switch animation */
+    if ( animate ) {
+      sc->view->manim     = GL_FALSE;
+      clip->cliptr->manim = GL_FALSE;
+      sc->view->angle = 0.0f;
+      glutIdleFunc(NULL);
+    }
+    else {
+      sc->view->manim     = GL_TRUE;
+      clip->cliptr->manim = GL_TRUE;
+      if ( sc->persp->pmode == CAMERA )
+        glutIdleFunc(glutIdle);
+    }
+    animate = 1-animate;
+    post = FALSE;
+    break;
+  case 'I':  /* save image */
+    saveimg = 1 - saveimg;
+    nbimg   = 0;
+    post    = GL_FALSE;
+    break;
+
+  case 'M':  /* morphing */
+    if ( morphing )
+      glutIdleFunc(NULL);
+    else
+      glutIdleFunc(glutIdle);
+    morphing = 1-morphing;
+    post = FALSE;
+    break;
+  case 'R':  /* next morph */
+    imreverse = 1-imreverse;
+    break;
+
+  case 'S':  /* start animation */
+    if ( ddebug ) fprintf(stdout,"debut sequence %d a %d\n",animdep,animfin);
+    glutSetWindow(sc->idwin);
+    if ( option == SEQUENCE )
+      playAnim(sc,mesh,animdep,animfin);
+    if ( !saveimg )  post = FALSE;
+    break;
+
+  case 'f': /* first mesh */
+    /* get basename */
+    ptr = (char *)strrchr(mesh->name,'.');
+    if ( ptr )  *ptr = '\0';
+    strcpy(base,mesh->name);
+    resetLists(sc,mesh);
+    if ( !loadNextMesh(mesh,animdep,0) )  break;
+    doLists(sc,mesh);
+    if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
+    if ( sc->isotyp )       doIsoLists(sc,mesh,0);
+    strcpy(mesh->name,base);
+    break;
+
+  case 'l':
+    /* get basename */
+    ptr = (char *)strrchr(mesh->name,'.');
+    if ( ptr )  *ptr = '\0';
+    strcpy(base,mesh->name);
+    resetLists(sc,mesh);
+    if ( !loadNextMesh(mesh,animfin,0) )  break;
+    doLists(sc,mesh);
+    if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
+    if ( sc->isotyp )       doIsoLists(sc,mesh,0);
+    strcpy(mesh->name,base);
+    break;
+
+  case 'n':
+    /* get basename */
+    if ( ++depart > animfin )  depart = animdep;
+    ptr = (char *)strrchr(mesh->name,'.');
+    if ( ptr )  *ptr = '\0';
+    strcpy(base,mesh->name);
+    resetLists(sc,mesh);
+    if ( !loadNextMesh(mesh,depart,0) )  break;
+    doLists(sc,mesh);
+    if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
+    if ( sc->isotyp )       doIsoLists(sc,mesh,0);
+    strcpy(mesh->name,base);
+    break;
+
+  case 'p':
+    /* get basename */
+    if ( --depart < animdep )  depart = animfin;
+    ptr = (char *)strrchr(mesh->name,'.');
+    if ( ptr )  *ptr = '\0';
+    strcpy(base,mesh->name);
+    resetLists(sc,mesh);
+    if ( !loadNextMesh(mesh,depart,0) )  break;
+    doLists(sc,mesh);
+    if ( sc->mode & S_MAP ) doMapLists(sc,mesh,0);
+    if ( sc->isotyp )       doIsoLists(sc,mesh,0);
+    strcpy(mesh->name,base);
+    break;
+  }
+  
+  if ( post == TRUE )   glutPostRedisplay();
+}
+
+void menuAnim(int item) {
+  keyAnim((unsigned char)item,0,0);
+}
+
+void keyTrajet(unsigned char key,int x,int y) {
+  pScene   sc;
+  pMesh    mesh;
+
+  sc = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  switch(key) {
+  case 'C': /* add control point */
+    pathAdd(sc,x,y);
+    break;
+  case 'S': /* show all points */
+    sc->type ^= S_PATH;
+    /*if ( sc->path.tlist )  glDeleteLists(sc->path.tlist,1);*/
+    if ( sc->type & S_PATH && !sc->path.tlist )
+      sc->path.tlist = pathList(sc);
+    break;
+  case 'F': /* follow path */
+    break;
+  case 'L': /* load path */
+    pathLoad(mesh->name,sc);
+    break;
+  case 'W': /* save path */
+    pathSave(mesh->name,sc);
+    break;
+  }
+  glutPostRedisplay();
+}
+
+void menuTrajet(int item) {
+  keyTrajet((unsigned char)item,0,0);
+}
+
+void keyMode(unsigned char key,int x,int y) {
+  pScene  sc;
+  pMesh   mesh;
+  ubyte   post = TRUE,dolist = FALSE,material;
+
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  material = sc->mode & S_MATERIAL;
+
+  switch(key) {
+  case 'D':  /* depth lines */
+    if ( sc->mode == DEPTH ) break;
+    sc->mode = DEPTH;
+    break;
+  case 'S': /* toggle smooth shading */
+    if ( sc->mode == FILL )
+      break;
+    sc->mode = FILL;
+    if ( material ) sc->mode |= S_MATERIAL;
+    break;
+  case 'P': /* toggle smooth shaded polys */
+    if ( sc->mode == SHADED )
+      break;
+    sc->mode = SHADED;
+    if ( material ) sc->mode |= S_MATERIAL;
+    break;
+  case 'H': /* hidden lines */
+    if ( sc->mode == HIDDEN ) break;
+    sc->mode = HIDDEN;
+    if ( material ) sc->mode |= S_MATERIAL;
+    break;
+  case 'W':  /* wireframe */
+    if ( sc->mode == WIRE ) break;
+    sc->mode = WIRE;
+    if ( material ) sc->mode |= S_MATERIAL;
+    break;
+  case 'n': /* toggle normals */
+    if ( mesh->nvn == 0 ) {
+      post = FALSE;
+      break;
+    }
+    sc->type ^= S_FLAT;
+    dolist = TRUE;
+    break;
+  default:
+    post = FALSE;
+    break;
+  }
+  if ( dolist == TRUE ) doLists(sc,mesh);
+  if ( post == TRUE )   glutPostRedisplay();
+}
+
+void menuMode(int item) {
+  keyMode((unsigned char)item,0,0);
+}
+
+
+void menuScene(int item) {
+  keyScene((unsigned char)item,0,0);
+}
+
+void keyView(unsigned char key,int x,int y) {
+  pScene  sc,sc1;
+  pMesh   mesh;
+  float   dmax;
+  ubyte   post = FALSE;
+
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  /*glutSetMenu(vmenu);*/
+
+  switch(key) {
+  case 'R':
+    sc->type |= S_RESET;
+    dmax = mesh->xmax - mesh->xmin;
+    dmax = max(dmax,mesh->ymax - mesh->ymin);
+    dmax = max(dmax,mesh->zmax - mesh->zmin);
+    sc->cx = sc->cy = sc->cz = 0.0f;
+    sc->dmax = fabs(dmax);
+    if ( sc->persp->pmode == PERSPECTIVE ) {
+      resetTransform(sc->view);
+      initPersp(sc->persp,sc->dmax);
+    }
+    else if ( sc->persp->pmode == CAMERA ) {
+      initPersp(sc->persp,sc->dmax);
+      initCamera(sc,sc->camera->vecup); 
+      sc->persp->pmode = CAMERA;
+    }
+    reshapeScene(sc->par.xs,sc->par.ys);
+    post = TRUE;
+    break;
+  case 'C':
+    copyView(sc->view,sc->camera,sc->persp);
+    copyClip(sc->clip);
+    break;
+  case 'L':  /* link view */
+    if ( !linkView(sc) )  return;
+    reshapeScene(sc->par.xs,sc->par.ys);
+    post = TRUE;
+    break;
+  case 'P':
+    if ( pasteView(sc->view,sc->camera,sc->persp) && 
+         pasteClip(sc->clip) ) {
+      reshapeScene(sc->par.xs,sc->par.ys);
+      post = TRUE;
+    }
+    break;
+  case 'U':
+    unlinkView(sc);
+    break;
+
+  case 'D':  /* duplicate view */
+    if ( cv.nbs == MAX_SCENE )  break;
+    if ( !cv.scene[++cv.nbs] ) {
+      cv.scene[cv.nbs] = (pScene)M_calloc(1,sizeof(Scene),"menus.scene");
+      if ( !cv.scene[cv.nbs] )  break;
+      sc1 = cv.scene[cv.nbs];
+      sc1->material = (pMaterial)calloc(2+sc->par.nbmat,sizeof(Material));
+      assert(sc1->material);
+    }
+    sc1 = cv.scene[cv.nbs];
+    memcpy(sc1,sc,sizeof(Scene));
+    memcpy(sc1->material,sc->material,sc->par.nbmat*sizeof(Material));
+    memcpy(&sc1->par,&sc->par,sizeof(Param));
+    if ( !createScene(sc1,sc1->idmesh) ) {
+      fprintf(stdout,"  ## Unable to create\n");
+      return;
+    }
+    copyView(sc->view,sc->camera,sc->persp);
+    copyClip(sc->clip);
+    pasteView(sc1->view,sc1->camera,sc1->persp);
+    pasteClip(sc1->clip);
+    break;
+  }
+  if ( post )  glutPostRedisplay();
+}
+
+void menuView(int item) {
+  keyView((unsigned char)item,0,0);
+}
+
+void keyColor(unsigned char key,int x,int y) {
+  pScene     sc;
+  pMesh      mesh;
+  pMaterial  pm;
+  int        i,k;
+  ubyte      post = TRUE,dolist = FALSE;
+
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+
+  switch(key) {
+  case 'b':  /* reverse backcolor */
+    sc->par.back[0] = 1.0f - sc->par.back[0];
+    sc->par.back[1] = 1.0f - sc->par.back[1];
+    sc->par.back[2] = 1.0f - sc->par.back[2];
+    glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
+    if ( !sc->par.linc ) {
+      sc->par.line[0] = 1.0f - sc->par.line[0];
+      sc->par.line[1] = 1.0f - sc->par.line[1];
+      sc->par.line[2] = 1.0f - sc->par.line[2];
+    }
+    break;
+  case 'e':  /* toggle matcolors */
+    sc->mode ^= S_MATERIAL;
+    dolist = TRUE;
+    break;
+  case 'E':  /* edit matcolors */
+    post   = FALSE; 
+    matEdit(sc);
+    break;
+  case 'r':
+      if ( refmat<0 || ipilmat == sc->par.nbmat )  break;
+      pilmat[++ipilmat] = refmat;
+      pm = &sc->material[refmat];
+      pm->flag = 1;
+      updatePoints(sc,mesh,refmat);
+      if ( sc->picklist ) glDeleteLists(sc->picklist,1);
+      sc->picklist = 0;
+      refmat = -1;
+      dolist = TRUE;
+      post   = TRUE;
+    break;
+  case 'R':  /* reset materials */
+    for (k=0; k<sc->par.nbmat; k++) {
+      pm = &sc->material[k];
+      for (i=LTria; i<=LHexa; i++)
+        pm->depmat[i] = abs(pm->depmat[i]);
+    }
+    dolist = TRUE;
+    break;
+  default:
+    post = FALSE;
+  }
+  if ( dolist ) doLists(sc,mesh);
+  if ( post )   glutPostRedisplay();
+}
+
+void menuColor(int item) {
+  keyColor((unsigned char)item,0,0);
+}
+
+
+void keyClip(unsigned char key,int x,int y) {
+  pScene  sc;
+  pMesh   mesh;
+  pClip   clip;
+  ubyte   post = TRUE;
+
+  /* default */
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  clip = sc->clip;
+
+  switch(key) {
+  case 'C': /* toggle clipping */
+    if ( clip->active & C_ON )
+      clip->active &= ~(C_ON+C_EDIT);
+    else {
+      clip->active |= C_ON;
+      if ( mesh->ntet+mesh->nhex )  clip->active |= C_VOL;
+    }
+    break;
+  case 'E': /* edit clip plane */
+    if ( !(clip->active & C_ON) )  return;
+    if ( clip->active & C_FREEZE ) clip->active ^= C_FREEZE;
+    clip->active ^= C_EDIT;
+    break;
+  case 'F':  /* freeze clip */
+    if ( !(clip->active & C_ON) )  return;
+    if ( clip->active & C_EDIT )   clip->active ^= C_EDIT;
+    clip->active ^= C_FREEZE;
+    break;
+  case 'H':  /* toggle draw plane */
+    clip->active ^= C_HIDE;
+    break;
+  case 'I': /* inverse orientation */
+    invertClip(sc,clip);
+    clip->active |= C_REDO;
+    break;
+  case 'K':  /* toggle capping */
+    clip->active ^= C_CAP;
+    clip->active |= C_REDO;
+    break;
+  case 'R':  /* reset clip */
+    if ( !(clip->active & C_ON) ) break;
+    resetClip(sc,clip,mesh);
+    break;
+  case 'Z':  /* toggle volclip */
+    clip->active ^= C_VOL;
+    if ( clip->active & C_VOL )
+      clip->active |= C_REDO;
+    break;
+  }
+  if ( post ) glutPostRedisplay();
+}
+
+void menuClip(int item) {
+  keyClip((unsigned char)item,0,0);
+}
+
+
+void keyCube(unsigned char key,int x,int y) {
+  pScene  sc;
+  pMesh   mesh;
+  pCube   cube;
+  ubyte   post = TRUE;
+
+  /* default */
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  cube = sc->cube;
+
+  switch(key) {
+  case 'C': /* toggle clipping */
+    if ( cube->active & C_ON )
+      cube->active &= ~(C_ON+C_EDIT);
+    else
+      cube->active |= C_ON;
+    break;
+  case 'E': /* edit clip plane */
+    if ( !(cube->active & C_ON) )  return;
+    if ( cube->active & C_FREEZE ) cube->active ^= C_FREEZE;
+    cube->active ^= C_EDIT;
+    break;
+  case 'F':  /* freeze cube */
+    if ( !(cube->active & C_ON) )  return;
+    if ( cube->active & C_EDIT )   cube->active ^= C_EDIT;
+    cube->active ^= C_FREEZE;
+    break;
+  case 'R':  /* reset cube */
+    if ( !(cube->active & C_ON) ) break;
+    resetCube(sc,cube,mesh);
+    break;
+  }
+  if ( post ) glutPostRedisplay();
+}
+
+void keyFeature(unsigned char key,int x,int y) {
+  pScene  sc;
+  pMesh   mesh;
+  ubyte   post=TRUE,dolist=TRUE;
+
+  /* default */
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+
+  switch(key) {
+  case 'S':  /* shrink mode */
+  case 'V':  /* volumic shrink */
+    if ( sc->shrink < 0.99 )
+      sc->shrink = 1.0f;
+    else
+      sc->shrink = 0.95;
+    dolist = TRUE;
+    break;
+  case 'I':  /* increase shrink value */
+    if ( sc->shrink > 0.99 ) break;
+    sc->shrink -= .05;
+    if ( sc->shrink < 0.1 ) sc->shrink = 0.1;
+    dolist = TRUE;
+    break;
+  case 'i':  /* decrease shrink value */
+    if ( sc->shrink > 0.99 ) break;
+    sc->shrink += .05;
+    if ( sc->shrink > 0.95 ) sc->shrink = 0.95;
+    dolist = TRUE;
+    break;
+  case 's':  /* scissor mode */
+    if ( mesh->dim == 2 )  break;
+    sc->type ^= S_SCISSOR;
+    if ( sc->type & S_SCISSOR )
+      glutDisplayFunc(scissorScene);
+    else {
+      glutDisplayFunc(redrawScene);
+      reshapeScene(sc->par.xs,sc->par.ys);
+    }
+    break;
+  }
+  if ( dolist == TRUE ) {
+    doLists(sc,mesh);
+    if ( sc->mode & S_MAP )  doMapLists(sc,mesh,1);
+    /*if ( sc->isotyp )        doIsoLists(sc,mesh,1);*/
+  }
+  if ( post == TRUE )   glutPostRedisplay();
+}
+
+void menuFeature(int item) {
+  keyFeature((unsigned char)item,0,0);
+}
+
+
+void menuImage(int item) {
+  imgtype = item;
+}
+
+void keyMetric(unsigned char key,int x,int y) {
+  pScene  sc;
+  pMesh   mesh;
+  pPoint  ppt;
+  float   maxd;
+  int     k,kk;
+  ubyte   post=TRUE;
+
+  /* default */
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+
+  switch(key) {
+  case 'c': /* critical points */
+    if ( !mesh->nbb )  return;
+    sc->isotyp ^= S_CRITP;
+    doIsoLists(sc,mesh,0);
+    break;
+  case 'f':  /* flush streamlines */
+    if ( sc->stream->nbstl ) {
+      for (kk=0; kk<sc->stream->nbstl; kk++) {
+        if ( sc->slist[kk] )  glDeleteLists(sc->slist[kk],1);
+        sc->slist[kk] = (GLuint)0;
+      }
+      sc->stream->nbstl = 0;
+      for (k=1; k<=mesh->np; k++) {
+        ppt = &mesh->point[k];
+        ppt->flag = 0;
+      }
+    }
+    break;
+  case 'l': /* iso-lines */
+    if ( !mesh->nbb )  return;
+    sc->isotyp ^= S_ISOLINE;
+    doIsoLists(sc,mesh,0);
+    break;
+  case 's': /* iso-surfaces */
+    if ( !mesh->nbb ) return;
+    sc->isotyp ^= S_ISOSURF;
+    doIsoLists(sc,mesh,0);
+    break;
+  case 'u': /* field lines animation */
+    if ( !mesh->nbb || mesh->nfield != mesh->dim )  return;
+    if ( refitem ) {
+      sc->isotyp |= S_PARTICLE;
+      createParticle(sc,mesh);
+    }
+    glutIdleFunc(streamIdle);
+    break;
+  case 'd': /* displacement */
+    if ( !mesh->nbb || mesh->nfield != mesh->dim )  return;
+    sc->mode ^= S_DISPL;
+	meshCoord(mesh,(sc->mode & S_DISPL) ? 1 : 0);
+	meshBox(mesh,1);
+    doLists(sc,mesh);
+    if ( sc->mode & S_MAP ) doMapLists(sc,mesh,1);
+    if ( sc->isotyp )       doIsoLists(sc,mesh,1);
+    break;
+
+  case 'v': /* streamlines */
+    if ( !mesh->nbb || mesh->nfield != mesh->dim )  return;
+    if ( refitem ) {
+      sc->isotyp |= S_STREAML;
+      doIsoLists(sc,mesh,0);
+    }
+    else {
+      if ( !streamIsoPoint(sc,mesh) ) {
+        post = FALSE;
+        sc->isotyp &= ~S_STREAML;
+      }
+    }
+    break;
+  case 'w': /*vector/tensor */
+    if ( mesh->nfield != mesh->dim ) {
+      if ( mesh->dim==2 && mesh->nfield == 3 ) {
+        if ( sc->picklist ) {
+          glDeleteLists(sc->picklist,1);
+          sc->picklist = 0;
+          break;
+        }
+        else
+          sc->picklist = drawAllEllipse(sc,mesh);
+          break;
+      }
+      return;
+    }
+    sc->isotyp ^= S_VECTOR;
+    if ( mesh->dim == 3 )
+      if ( mesh->ntet+mesh->nhex && !(sc->clip->active & C_ON) ) 
+        return;
+    doIsoLists(sc,mesh,0);
+    break;
+
+  case 'k': /* toggle elevation */
+    if ( mesh->dim != 2 )  return;
+    sc->mode ^= S_ALTITUDE;
+    if ( altcoef == 0.0 ) {
+      maxd = max(mesh->xmax-mesh->xmin,mesh->ymax-mesh->ymin);
+      altcoef = 0.3*maxd / mesh->bbmax;
+    }
+    if ( !(sc->mode & S_ALTITUDE) ) 
+      sc->type |= S_RESET;
+    doMapLists(sc,mesh,1);
+    break;
+  case 'K': /* elevation coeff */
+    fprintf(stdout,"elevation coeff (%.2f): ",altcoef);
+    fflush(stdout);
+    fflush(stdin); fscanf(stdin,"%f",&altcoef);
+    if ( altcoef == 0.0 ) sc->mode |= ~S_ALTITUDE;
+    sc->type |= S_RESET;
+    doMapLists(sc,mesh,1);
+    doIsoLists(sc,mesh,1);
+    break;
+
+  case 'm': /* display metric */
+    if ( !mesh->nbb ) return;
+    sc->mode ^= S_MAP;
+    doMapLists(sc,mesh,1);
+    if ( sc->mode & S_MAP ) {
+      if ( sc->clip->active & C_ON ) sc->clip->active |= C_REDO;
+      if ( !(sc->item & S_PALETTE) )
+        sc->item ^= S_PALETTE;
+    }
+    else if ( sc->item & S_PALETTE )
+      sc->item ^= S_PALETTE;
+    break;
+  case 'p': /* toggle palette */
+    if ( !mesh->nbb ) return;
+    sc->item ^= S_PALETTE;
+    break;
+
+  default:
+    post = FALSE;
+    break;
+  }
+  if ( post )  glutPostRedisplay();
+}
+
+void menuMetric(int item) {
+  keyMetric((unsigned char)item,0,0);
+}
+
+
+int createMenus(pScene sc,pMesh mesh) {
+  int   menu,amenu,fmenu,femenu,vmenu,mmenu,smenu;
+  int   clmenu,cmenu,vwmenu,trmenu;
+
+  /* default */
+  if ( ddebug )  printf("create menus\n");
+  smenu = 0;
+
+  /* File management menu */
+  fmenu = glutCreateMenu(menuFile);
+  glutAddMenuEntry("[L] Load prefs",'L');
+  glutAddMenuEntry("[W] Save prefs",'W');
+  glutAddMenuEntry("    Update mesh",'R');
+  glutAddMenuEntry("    Save mesh",'S');
+  glutAddMenuEntry("[H] Hardcopy PPM",'H');
+  glutAddMenuEntry("    Hardcopy EPS (Color)",'C');
+  glutAddMenuEntry("    Hardcopy EPS (Grey)",'G');
+  glutAddMenuEntry("    Hardcopy EPS (B/W)",'B');
+  glutAddMenuEntry("    Softcopy EPS",'s');
+
+  /* rendering mode selector */
+  mmenu = glutCreateMenu(menuMode);
+  glutAddMenuEntry("Wireframe",'W');
+  glutAddMenuEntry("Depth  lines",'D');
+  glutAddMenuEntry("Hidden lines",'H');
+  glutAddMenuEntry("Shading",'S');
+  glutAddMenuEntry("Shading+lines",'P');
+  if ( mesh->nvn > 0 )
+    glutAddMenuEntry("[n] Toggle Normals",'n');
+
+  /* color & material menu */
+  cmenu = glutCreateMenu(menuColor);
+  glutAddMenuEntry("[b] Toggle backcolor",'b');
+  glutAddMenuEntry("[e] Toggle matcolors",'e');
+  glutAddMenuEntry("[E] Edit   matcolors",'E');
+  glutAddMenuEntry("[r] Hide   material",'r');
+  glutAddMenuEntry("[R] Reset  materials",'R');
+
+  /* metric */
+  if ( mesh->nbb > 0 ) {
+    smenu = glutCreateMenu(menuMetric);
+    glutAddMenuEntry("[m] Toggle metric",'m');
+    glutAddMenuEntry("[p] Toggle palette",'p');
+    if ( mesh->typage == 2 )
+      glutAddMenuEntry("[o] Toggle iso-lines",'l');
+    if ( mesh->ntet+mesh->nhex > 0 && mesh->nfield == 1 )
+      glutAddMenuEntry("    Toggle iso-surfaces",'s');
+    if ( mesh->nfield == mesh->dim ) {
+      glutAddMenuEntry("[w]  Toggle vector/tensor",'w');
+	  glutAddMenuEntry("     Toggle displacement",'d');
+      glutAddMenuEntry("[v]  Toggle streamlines",'v');
+      glutAddMenuEntry("     Flush streamlines",'f');
+      glutAddMenuEntry("     Particle advection",'u');
+      if ( mesh->dim == 2 )
+        glutAddMenuEntry("     Critical points",'c');
+    }
+    if ( mesh->dim == 2 ) {
+      glutAddMenuEntry("[k]  Toggle elevation",'k');
+      glutAddMenuEntry("[K]  Elevation coeff",'K');
+    }
+  }
+
+  /* Show misc. items */
+  vmenu = glutCreateMenu(menuItem);
+  glutAddMenuEntry("[A] Axis",'A');
+  glutAddMenuEntry("[B] Bounding box",'B');
+  glutAddMenuEntry("[G] Grid ",'G');
+  if ( sc->glist )
+    glutAddMenuEntry("[g] Geometric items",'g');
+  glutAddMenuEntry("[j] Toggle Info",'j');
+  glutAddMenuEntry("[P] Toggle Point num",'P');
+  glutAddMenuEntry("[F] Toggle Face num",'F');
+  if ( mesh->nvn ) {
+    glutAddMenuEntry("[N] Toggle normals",'N');
+    glutAddMenuEntry("[O] Revert normals",'O');
+  }
+
+  /* clipping menu */
+  clmenu = glutCreateMenu(menuClip);
+  glutAddMenuEntry("[F1] Toggle clip",'C');
+  glutAddMenuEntry("[F2] Edit clip",'E');
+  glutAddMenuEntry("[F3] Freeze clip",'F');
+  glutAddMenuEntry("     Inverse orient",'I');
+  if ( mesh->ntet+mesh->nhex > 0 )
+    glutAddMenuEntry("     Toggle capping",'K');
+  glutAddMenuEntry("     Toggle plane",'H');
+  glutAddMenuEntry(" --  Reset clip",'R');
+  if ( mesh->ntet+mesh->nhex > 0 ) {
+    sc->clip->active |= C_VOL;
+    glutAddMenuEntry("[F4] Toggle Vclip",'Z');
+  }
+
+  /* feature menu */
+  femenu = glutCreateMenu(menuFeature);
+  if ( mesh->ntet+mesh->nhex > 0 )
+    glutAddMenuEntry("[F5] Toggle Vshrink",'V');
+  else
+    glutAddMenuEntry("[F5] Toggle shrink",'S');
+  glutAddMenuEntry("[F6] Increase shrink",'I');
+  glutAddMenuEntry("[F7] Decrease shrink",'i');
+  if ( mesh->dim == 3 )
+    glutAddMenuEntry("Toggle splitview",'s');
+
+  /* view handler menu */
+  vwmenu = glutCreateMenu(menuView);
+  glutAddMenuEntry("[i] Reset",'R');
+  glutAddMenuEntry("[Alt-c] Copy",'C');
+  glutAddMenuEntry("[Alt-p] Paste",'P');
+  glutAddMenuEntry("[Alt+l] Link",'L');
+  glutAddMenuEntry("[Alt+u] Unlink",'U');
+  /*glutAddMenuEntry("[Alt+d] Duplicate",'D');*/
+
+  /* animation menu */
+  amenu = glutCreateMenu(menuAnim);
+  glutAddMenuEntry("[a] Toggle Anim",'A');
+  glutAddMenuEntry("Toggle ImgSave",'I');
+  if ( option == SEQUENCE || option == SEQUENCE + PARTICLE ) {
+    glutAddMenuEntry("Play  sequence",'S');
+    glutAddMenuEntry("First mesh",'f');
+    glutAddMenuEntry("Last  mesh",'l');
+    glutAddMenuEntry("Next mesh",'n');
+    glutAddMenuEntry("Prev mesh",'p');
+  }
+  else if ( option == MORPHING ) {
+    glutAddMenuEntry("Start/Stop morph.",'M');
+    glutAddMenuEntry("Toggle AutoReverse",'R');
+  }
+
+  /* trajectoire menu */
+  if ( mesh->dim == 3 || mesh->nbb ) {
+    trmenu = glutCreateMenu(menuTrajet);
+    glutAddMenuEntry("New Ctrl point",'C');
+    glutAddMenuEntry("Toggle path",'S');
+    glutAddMenuEntry("Follow path",'F');
+    glutAddMenuEntry("Load path",'L');
+    glutAddMenuEntry("Save path",'W');
+  }
+  else
+    trmenu = 0;
+
+  /* main scene menu */
+  menu = glutCreateMenu(menuScene);
+  glutAddSubMenu("File",fmenu);
+  glutAddSubMenu("Render mode",mmenu);
+  glutAddSubMenu("Colors, Materials",cmenu);
+  if ( mesh->nbb )
+    glutAddSubMenu("Data",smenu);
+  glutAddSubMenu("Items",vmenu);
+  if ( mesh->dim == 3 )
+    glutAddSubMenu("Clipping",clmenu);
+  glutAddSubMenu("Features",femenu);
+  glutAddSubMenu("View",vwmenu);
+  glutAddSubMenu("Animation",amenu);
+  /*if ( trmenu )
+    glutAddSubMenu("Trajectory",trmenu);
+  */
+  glutAddMenuEntry("",'\0');
+  glutAddMenuEntry("Close window",'X');
+  glutAddMenuEntry("Quit",'q');
+
+
+  return(1);
+}
diff --git a/src/medit/mesh.c b/src/medit/mesh.c
new file mode 100644
index 0000000..d20fdc1
--- /dev/null
+++ b/src/medit/mesh.c
@@ -0,0 +1,477 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define FLOAT_MAX  1.e20
+ubyte   dosurf;
+
+
+double volTet(double *c1,double *c2,double *c3,double *c4) {
+  double   ax,ay,az,bx,by,bz,vol;
+
+  ax = c3[0] - c1[0];
+  ay = c3[1] - c1[1];
+  az = c3[2] - c1[2];
+
+  bx = c4[0] - c1[0];
+  by = c4[1] - c1[1];
+  bz = c4[2] - c1[2];
+
+  vol = (c2[0]-c1[0]) * (ay*bz - az*by) \
+      + (c2[1]-c1[1]) * (az*bx - ax*bz) \
+      + (c2[2]-c1[2]) * (ax*by - ay*bx);
+
+  return(vol / 6.0);
+}
+
+
+/* dump mesh info */
+void meshInfo(pMesh mesh) {
+  fprintf(stdout,"    Vertices   %8d",mesh->np);
+  if ( mesh->nc ) fprintf(stdout,"  Corners  %d",mesh->nc);
+  if ( mesh->nr ) fprintf(stdout,"  Required %d",mesh->nr);
+  fprintf(stdout,"\n");
+  if ( mesh->nt )   fprintf(stdout,"    Triangles  %8d\n",mesh->nt);
+  if ( mesh->nq )   fprintf(stdout,"    Quads      %8d\n",mesh->nq);
+  if ( mesh->ntet ) fprintf(stdout,"    Tetrahedra %8d\n",mesh->ntet);
+  if ( mesh->nhex ) fprintf(stdout,"    Hexahedra  %8d\n",mesh->nhex);
+  if ( mesh->na ) {
+    fprintf(stdout,"    Edges      %8d",mesh->na);
+    if ( mesh->nri ) fprintf(stdout,"  Ridges   %d",mesh->nri);
+    if ( mesh->nre ) fprintf(stdout,"  Required %d",mesh->nre);
+    fprintf(stdout,"\n");
+  }
+  if ( mesh->nvn || mesh->ntg) {
+    fprintf(stdout,"    Normals    %8d",mesh->nvn);
+    fprintf(stdout,"  Tangents   %d\n",mesh->ntg);
+  }
+  fprintf(stdout,"    Bounding box:  x:[%g  %g]  y:[%g  %g]  z:[%g  %g]\n",
+          mesh->xmin,mesh->xmax,mesh->ymin,mesh->ymax,mesh->zmin,mesh->zmax);
+}
+
+
+void meshCoord(pMesh mesh,int displ) {
+  pTetra     pt1;
+  pPoint     ppt;
+  pSolution  ps;
+  double    *c1,*c2,*c3,*c4,mul,vold,volf;
+  int        k;
+
+  /* default */
+  if ( ddebug ) printf("change mesh coord\n");
+  mul = 2.0*displ - 1.;
+  if ( mesh->dim == 2 ) {   
+   for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+	  ps  = &mesh->sol[k];
+	  ppt->c[0] = ppt->c[0] + mul*ps->m[0];
+	  ppt->c[1] = ppt->c[1] + mul*ps->m[1];
+    }
+  }
+  else {
+	vold = 0.0;
+	for (k=1; k<=mesh->ntet; k++) {
+	  pt1 = &mesh->tetra[k];
+	  if ( !pt1->v[0] )  continue;
+	  c1 = &mesh->point[pt1->v[0]].c[0];
+	  c2 = &mesh->point[pt1->v[1]].c[0];
+	  c3 = &mesh->point[pt1->v[2]].c[0];
+	  c4 = &mesh->point[pt1->v[3]].c[0];
+	  vold += volTet(c1,c2,c3,c4);
+	}
+    for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+	  ps  = &mesh->sol[k];
+	  ppt->c[0] = mesh->xtra + ppt->c[0] + mul*ps->m[0];
+	  ppt->c[1] = mesh->ytra + ppt->c[1] + mul*ps->m[1];
+	  ppt->c[2] = mesh->ztra + ppt->c[2] + mul*ps->m[2];
+    }
+	volf = 0.0;
+	for (k=1; k<=mesh->ntet; k++) {
+	  pt1 = &mesh->tetra[k];
+	  if ( !pt1->v[0] )  continue;
+	  c1 = &mesh->point[pt1->v[0]].c[0];
+	  c2 = &mesh->point[pt1->v[1]].c[0];
+	  c3 = &mesh->point[pt1->v[2]].c[0];
+	  c4 = &mesh->point[pt1->v[3]].c[0];
+	  volf += volTet(c1,c2,c3,c4);
+	}
+	fprintf(stdout,"  Volume: initial %E    final %E\n",vold,volf);
+  }
+}
+
+
+void meshBox(pMesh mesh,int bb) {
+  pPoint     ppt;
+  int        k;
+
+  /* default */
+  if ( ddebug ) printf("compute mesh box\n");
+  if ( bb ) {
+    mesh->xmin = mesh->ymin = mesh->zmin =  FLOAT_MAX;
+    mesh->xmax = mesh->ymax = mesh->zmax = -FLOAT_MAX;
+
+    for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+      if ( ppt->tag == M_UNUSED && mesh->ne )  continue;
+      if ( ppt->c[0] < mesh->xmin ) mesh->xmin = ppt->c[0];
+      if ( ppt->c[0] > mesh->xmax ) mesh->xmax = ppt->c[0];
+      if ( ppt->c[1] < mesh->ymin ) mesh->ymin = ppt->c[1];
+      if ( ppt->c[1] > mesh->ymax ) mesh->ymax = ppt->c[1];
+      if ( ppt->c[2] < mesh->zmin ) mesh->zmin = ppt->c[2];
+      if ( ppt->c[2] > mesh->zmax ) mesh->zmax = ppt->c[2];
+    }
+  }
+
+  /* translate mesh at center */
+  mesh->xtra = 0.5 * (mesh->xmin+mesh->xmax);
+  mesh->ytra = 0.5 * (mesh->ymin+mesh->ymax);
+  mesh->ztra = 0.5 * (mesh->zmin+mesh->zmax);
+  for (k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+    /*if ( ppt->tag == M_UNUSED && mesh->ne )  continue;*/
+    ppt->c[0] -= mesh->xtra; 
+    ppt->c[1] -= mesh->ytra; 
+    ppt->c[2] -= mesh->ztra;
+  }
+}
+
+
+int meshSurf(pMesh mesh) {
+  pTetra     ptt,pt2;
+  pHexa      ph;
+  pTriangle  pt;
+  pQuad      pq;
+  int       *adj,i,k,iadr;
+  ubyte      i1,i2,i3;
+  static int idirt[7] = {0,1,2,3,0,1,2};
+  static int ch[6][4] = { {0,1,2,3}, {4,5,6,7}, {0,1,5,4}, 
+			  {1,2,6,5}, {2,3,7,6}, {0,3,7,4} };
+
+  if ( !dosurf )  return(1);
+
+  /* extract surface */
+  if ( mesh->ntet > 0 && !mesh->nt ) {
+    if ( !hashTetra(mesh) )  return(0);
+
+    for (k=1; k<=mesh->ntet; k++) {
+      ptt = &mesh->tetra[k];
+      if ( !ptt->v[0] )  continue;
+      iadr = 4*(k-1)+1;
+      adj  = &mesh->adja[iadr];
+      for (i=0; i<4; i++)
+        if ( !adj[i] ) ++mesh->nt;
+	else {
+	  pt2 = &mesh->tetra[adj[i]];
+	  if ( ptt->ref != pt2->ref && k < adj[i] ) ++mesh->nt;
+	}
+    }
+
+    /* memory alloc */
+    if ( ddebug ) printf("allocate %d tria\n",mesh->nt);
+    mesh->tria = (pTriangle)calloc(mesh->nt+1,sizeof(struct striangle));
+    if ( !mesh->tria ) {
+      fprintf(stdout,"  ## No triangle\n");
+      return(0);
+    }
+
+    /* find triangles */
+    mesh->nt = 0;
+    for (k=1; k<=mesh->ntet; k++) {
+      ptt = &mesh->tetra[k];
+      if ( !ptt->v[0] )  continue;
+      iadr = 4*(k-1)+1;
+      adj  = &mesh->adja[iadr];
+      for (i=0; i<4; i++) {
+        if ( !adj[i] ) {
+          pt = &mesh->tria[++mesh->nt];
+          i1 = idirt[i+1];
+          i2 = idirt[i+2];
+          i3 = idirt[i+3];
+          pt->v[0] = ptt->v[i1];
+          pt->v[1] = ptt->v[i2];
+          pt->v[2] = ptt->v[i3];
+	      pt->ref  = 0;
+        }
+	    else {
+	      pt2 = &mesh->tetra[adj[i]];
+	      if ( (ptt->ref != pt2->ref) && (k < adj[i]) ) {
+            pt = &mesh->tria[++mesh->nt];
+            i1 = idirt[i+1];
+            i2 = idirt[i+2];
+            i3 = idirt[i+3];
+            pt->v[0] = ptt->v[i1];
+            pt->v[1] = ptt->v[i2];
+            pt->v[2] = ptt->v[i3];
+	        pt->ref  = max(ptt->ref,pt2->ref);
+	  } 
+	}
+      }	
+    } 
+  }
+
+  if ( mesh->nhex > 0 && !mesh->nq ) {
+    if ( mesh->adja ) {
+      free(mesh->adja);
+      free(mesh->voy);
+      mesh->adja = 0;
+      mesh->voy  = 0;
+    }
+    if ( !hashHexa(mesh) )  return(0);
+
+    for (k=1; k<=mesh->nhex; k++) {
+      ph = &mesh->hexa[k];
+      if ( !ph->v[0] )  continue;
+      iadr = 6*(k-1)+1;
+      adj  = &mesh->adja[iadr];
+      for (i=0; i<6; i++)
+        if ( !adj[i] ) ++mesh->nq;
+    }
+
+    /* memory alloc */
+    if ( ddebug ) printf("allocate %d quads\n",mesh->nq);
+    mesh->quad = (pQuad)calloc(mesh->nq+1,sizeof(struct squad));
+    if ( !mesh->quad ) {
+      fprintf(stdout,"  ## No quad\n");
+      return(0);
+    }
+
+    /* find quadrilaterals */
+    mesh->nq = 0;
+    for (k=1; k<=mesh->nhex; k++) {
+      ph = &mesh->hexa[k];
+      if ( !ph->v[0] )  continue;
+      iadr = 6*(k-1)+1;
+      adj  = &mesh->adja[iadr];
+      for (i=0; i<6; i++)
+        if ( !adj[i] ) {
+          pq = &mesh->quad[++mesh->nq];
+          pq->v[0] = ph->v[ch[i][0]];
+          pq->v[1] = ph->v[ch[i][1]];
+          pq->v[2] = ph->v[ch[i][2]];
+          pq->v[3] = ph->v[ch[i][3]];
+        }
+    } 
+  }
+
+  return(1);
+}
+
+void meshRef(pScene sc,pMesh mesh) {
+  pMaterial  pm;
+  pTriangle  pt;
+  pQuad      pq;
+  pTetra     pte;
+  pHexa      ph;
+  pPoint     ppt;
+  int       *old,i,k,m,nmat;
+
+  /* default */
+  if ( ddebug ) printf("    assign %d references\n",sc->par.nbmat-1);
+
+  /* sort elements by references */
+  if ( !quiet ) fprintf(stdout,"   Identifying sub-domains\n");
+  old = (int*)calloc(sc->par.nbmat+1,sizeof(int));
+  if ( !old )  exit(2);
+
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    pm->ext[0] = mesh->xmax-mesh->xtra;
+    pm->ext[1] = mesh->ymax-mesh->ytra;
+    pm->ext[2] = mesh->zmax-mesh->ztra;
+    pm->ext[3] = mesh->xmin-mesh->xtra;
+    pm->ext[4] = mesh->ymin-mesh->ytra;
+    pm->ext[5] = mesh->zmin-mesh->ztra;
+  }
+
+  for (k=mesh->nt; k>0; k--) {
+    pt   = &mesh->tria[k];
+	if ( !pt->v[0] )  continue;
+    nmat = matRef(sc,pt->ref);
+    /*nmat = !pt->ref ? DEFAULT_MAT : 1+(pt->ref-1)%(sc->par.nbmat-1);*/
+    pt->nxt   = old[nmat];
+    old[nmat] = k;
+    pm = &sc->material[nmat];
+    for (i=0; i<3; i++) {
+      ppt = &mesh->point[pt->v[i]];
+      pm->ext[0] = min(pm->ext[0],ppt->c[0]);
+      pm->ext[1] = min(pm->ext[1],ppt->c[1]);
+      pm->ext[2] = min(pm->ext[2],ppt->c[2]);
+      pm->ext[3] = max(pm->ext[3],ppt->c[0]);
+      pm->ext[4] = max(pm->ext[4],ppt->c[1]);
+      pm->ext[5] = max(pm->ext[5],ppt->c[2]);
+    }
+  }
+
+  for (m=0;m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    pm->depmat[LTria] = old[m];
+    old[m] = 0;
+  }
+
+  for (k=mesh->nq; k>0; k--) {
+    pq   = &mesh->quad[k];
+	if ( !pq->v[0] )  continue;
+    nmat = matRef(sc,pq->ref);
+    /*nmat = !pq->ref ? DEFAULT_MAT : 1+(pq->ref-1)%(sc->par.nbmat-1);*/
+    pq->nxt   = old[nmat];
+    old[nmat] = k;
+    pm = &sc->material[nmat];
+    for (i=0; i<4; i++) {
+      ppt = &mesh->point[pq->v[i]];
+      pm->ext[0] = min(pm->ext[0],ppt->c[0]);
+      pm->ext[1] = min(pm->ext[1],ppt->c[1]);
+      pm->ext[2] = min(pm->ext[2],ppt->c[2]);
+      pm->ext[3] = max(pm->ext[3],ppt->c[0]);
+      pm->ext[4] = max(pm->ext[4],ppt->c[1]);
+      pm->ext[5] = max(pm->ext[5],ppt->c[2]);
+    }
+  }
+
+  for (m=0;m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    pm->depmat[LQuad] = old[m];
+    old[m] = 0;
+  }
+
+  for (k=mesh->ntet; k>0; k--) {
+    pte  = &mesh->tetra[k];
+	if ( !pte->v[0] )  continue;
+    nmat = matRef(sc,pte->ref);
+    /*nmat = !pte->ref ? DEFAULT_MAT : 1+(pte->ref-1)%(sc->par.nbmat-1);*/
+    pte->nxt  = old[nmat];
+    old[nmat] = k;
+    pm = &sc->material[nmat];
+    for (i=0; i<4; i++) {
+      ppt = &mesh->point[pte->v[i]];
+      pm->ext[0] = min(pm->ext[0],ppt->c[0]);
+      pm->ext[1] = min(pm->ext[1],ppt->c[1]);
+      pm->ext[2] = min(pm->ext[2],ppt->c[2]);
+      pm->ext[3] = max(pm->ext[3],ppt->c[0]);
+      pm->ext[4] = max(pm->ext[4],ppt->c[1]);
+      pm->ext[5] = max(pm->ext[5],ppt->c[2]);
+    }
+  }
+
+  for (m=0;m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    pm->depmat[LTets] = old[m];
+    old[m] = 0;
+  }
+
+  for (k=mesh->nhex; k>0; k--) {
+    ph   = &mesh->hexa[k];
+    nmat = matRef(sc,ph->ref);
+    /*nmat = !ph->ref ? DEFAULT_MAT : 1+(ph->ref-1)%(sc->par.nbmat-1);*/
+    ph->nxt   = old[nmat];
+    old[nmat] = k;
+    pm = &sc->material[nmat];
+    for (i=0; i<8; i++) {
+      ppt = &mesh->point[ph->v[i]];
+      pm->ext[0] = min(pm->ext[0],ppt->c[0]);
+      pm->ext[1] = min(pm->ext[1],ppt->c[1]);
+      pm->ext[2] = min(pm->ext[2],ppt->c[2]);
+      pm->ext[3] = max(pm->ext[3],ppt->c[0]);
+      pm->ext[4] = max(pm->ext[4],ppt->c[1]);
+      pm->ext[5] = max(pm->ext[5],ppt->c[2]);
+    }
+  }
+  for (m=0;m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    pm->depmat[LHexa] = old[m];
+    old[m] = 0;
+  }
+
+  free(old);
+
+  /* remove unused materials */
+/*
+  for (m=1; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    if ( !pm->depmat[LTria] && !pm->depmat[LQuad] &&
+         !pm->depmat[LTets] && !pm->depmat[LHexa] ) {
+      pm1 = &sc->material[sc->par.nbmat-1];
+      memcpy(pm,pm1,sizeof(struct material));
+      sc->par.nbmat--;
+      m--;
+    }
+  }
+*/
+  if ( ddebug )
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      if ( pm->depmat[LTria] || pm->depmat[LQuad] || pm->depmat[LTets] ||
+           pm->depmat[LHexa] )
+        fprintf(stdout,"    depart[%d], ref %d = %d %d %d %d\n",
+                m,pm->ref,pm->depmat[LTria],pm->depmat[LQuad],
+                pm->depmat[LTets],pm->depmat[LHexa]);
+    }
+}
+
+int meshUpdate(pScene sc,pMesh mesh) {
+  int     k,ret;
+  clock_t  ct;
+
+  /* release mesh structure */
+  if ( ddebug ) fprintf(stdout,"loadMesh: update mesh\n");
+  if ( mesh->tria )  { M_free(mesh->tria);  mesh->tria  = 0; }
+  if ( mesh->quad )  { M_free(mesh->quad);  mesh->quad  = 0; }
+  if ( mesh->edge )  { M_free(mesh->edge);  mesh->edge  = 0; }
+  if ( mesh->tetra ) { M_free(mesh->tetra); mesh->tetra = 0; }
+  if ( mesh->hexa )  { M_free(mesh->hexa);  mesh->hexa  = 0; }
+  if ( mesh->adja )  { M_free(mesh->adja);  mesh->adja  = 0; }
+  if ( mesh->voy  )  { M_free(mesh->voy);   mesh->voy   = 0; }
+  if ( mesh->point ) { M_free(mesh->point); mesh->point = 0; }
+  if ( mesh->extra ) {
+    if ( mesh->extra->iv )  M_free(mesh->extra->nv);
+    if ( mesh->extra->it )  M_free(mesh->extra->nt);
+    if ( mesh->extra->iq )  M_free(mesh->extra->nq);
+    if ( mesh->extra->n )   M_free(mesh->extra->n);
+    M_free(mesh->extra);
+    mesh->extra = 0;
+  }
+  if ( mesh->nbb && mesh->sol ) {
+    if ( (mesh->dim==2 && mesh->nfield==3) ||
+         (mesh->dim==3 && mesh->nfield==6) )
+      for (k=1; k<=mesh->nbb; k++)
+        free(mesh->sol[k].m);
+    M_free(mesh->sol);
+    mesh->sol = 0;
+  }
+
+  /* read mesh */
+  fprintf(stdout," Loading data file(s)\n");
+  ct = clock();
+  ret = 0;
+  switch ( mesh->typ ) {
+  case 0:
+    ret = loadMesh(mesh);
+    break;
+  case 1:
+    ret = inmsh2(mesh);
+    break;
+  case 2:
+    ret = loadGIS(mesh);
+    break;
+  }
+  if ( !ret )  return(0);
+
+  /* compute mesh box */
+  if ( (mesh->ntet && !mesh->nt) || (mesh->nhex && !mesh->nq) )  
+    meshSurf(mesh);
+  meshBox(mesh,1);
+  /*parsop(sc,mesh);*/
+  if ( !quiet )  meshInfo(mesh);
+
+  /* read metric */
+  if ( !loadSol(mesh,mesh->name,1) )
+    bbfile(mesh);
+  if ( !quiet && mesh->nbb )
+    fprintf(stdout,"    Solutions  %8d\n",mesh->nbb);
+
+  ct = difftime(clock(),ct);
+  fprintf(stdout,"  Input seconds:     %.2f\n",
+          (double)ct/(double)CLOCKS_PER_SEC);
+
+  return(1);
+}
diff --git a/src/medit/mesh.h b/src/medit/mesh.h
new file mode 100644
index 0000000..24945f1
--- /dev/null
+++ b/src/medit/mesh.h
@@ -0,0 +1,108 @@
+#ifndef _MESH_H
+#define _MESH_H
+
+#define M_NOTAG    0
+#define M_CORNER   (1 << 0)
+#define M_RIDGE    (1 << 1)
+#define M_REQUIRED (1 << 2)
+#define M_TAG      (1 << 3)
+#define M_UNUSED   (1 << 5)
+
+#ifndef ubyte
+typedef unsigned char  ubyte;
+#endif
+#ifndef ushort
+typedef unsigned short uShort;
+#endif
+
+
+typedef struct spoint {
+  double    c[3];
+  int       tmp;
+  short     ref;
+  uShort    mark;
+  char      tag,clip,flag;
+} Point;
+typedef Point     * pPoint;
+
+typedef struct striangle {
+  int     v[3],nxt;
+  short   ref;              /* reference               */
+  uShort  mark,cpt;
+  char    clip;
+} Triangle;
+typedef Triangle  * pTriangle;
+
+typedef struct squad {
+  int     v[4],nxt;
+  short   ref;
+  char    clip;
+} Quad;
+typedef Quad * pQuad;
+
+typedef struct edge {
+  int     v[2];
+  short   ref;
+  char    tag;
+} Edge;
+typedef Edge * pEdge;
+
+typedef struct stetra {
+  int     v[4],nxt,mark;
+  short   ref;
+  uShort  cpt;
+  char    clip;
+} Tetra;
+typedef Tetra * pTetra;
+
+typedef struct shexa {
+  int     v[8],nxt,mark;
+  short   ref;
+  uShort  cpt;
+  char    clip;
+} Hexa;
+typedef Hexa * pHexa;
+
+typedef struct extra {
+  float    *n,*t;
+  int      *nv,*nt,*nq,*tv,*te;
+  int       iv,it,iq,jv,je;
+} Extra;
+typedef Extra * pExtra;
+
+typedef struct solu {
+  float   bb;
+  float  *m;
+  int     ver,dim;
+} Solution;
+typedef Solution  * pSolution;
+
+/* Mesh: mesh data structure */
+typedef struct mesh {
+  double      xmin,ymin,zmin,xmax,ymax,zmax;
+  double      xtra,ytra,ztra;
+  float       bbmin,bbmax;
+  int         ne,nt,nq,ntet,nhex;
+  int         np,nc,nr,na,nre,nri;
+  int         nvn,ntg,dim,ver,nbb,typage,nfield;
+  uShort      mark;
+  char        name[256],typ;
+
+  pPoint      point;
+  pTriangle   tria;
+  pQuad       quad;
+  pEdge       edge;
+  pTetra      tetra;
+  pHexa       hexa;
+
+  int        *adja;
+  int        *grid;
+  ubyte      *voy;
+
+  pExtra      extra;
+  pSolution   sol;
+} Mesh;
+typedef Mesh  * pMesh;
+
+
+#endif
diff --git a/src/medit/mlists.c b/src/medit/mlists.c
new file mode 100644
index 0000000..23e5a33
--- /dev/null
+++ b/src/medit/mlists.c
@@ -0,0 +1,1309 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+static int ct[4][3] = { {0,1,2}, {0,3,1}, {1,3,2}, {0,2,3} };
+static int ch[6][4] = { {0,1,2,3}, {4,5,6,7}, {0,1,5,4}, 
+            {1,2,6,5}, {2,3,7,6}, {0,3,7,4} };
+
+
+/* recursively subdivide a triangle */
+void cutTriangle(pScene sc,triangle t) {
+  triangle      t1,t2;
+  double        kc,x,dd,rgb[4],maxe;
+  int           i,ia,ib,ic,iedge;
+  static double hsv[3] = { 0.0f, 1.0f, 0.80f };
+
+  /* analyze triangle edges */
+  if ( t.va < sc->iso.val[0] )  
+    t.va = sc->iso.val[0];
+  else if ( t.va > sc->iso.val[MAXISO-1] )
+    t.va = sc->iso.val[MAXISO-1];
+  if ( t.vb < sc->iso.val[0] )  
+    t.vb = sc->iso.val[0];
+  else if ( t.vb > sc->iso.val[MAXISO-1] )
+    t.vb = sc->iso.val[MAXISO-1];
+  if ( t.vc < sc->iso.val[0] )  
+    t.vc = sc->iso.val[0];
+  else if ( t.vc > sc->iso.val[MAXISO-1] )
+    t.vc = sc->iso.val[MAXISO-1];
+
+  for (ia=0; ia<MAXISO-1; ia++)
+    if ( t.va < sc->iso.val[ia] )  break;
+
+  for (ib=0; ib<MAXISO-1; ib++)
+    if ( t.vb < sc->iso.val[ib] )  break;
+
+  for (ic=0; ic<MAXISO-1; ic++)
+    if ( t.vc < sc->iso.val[ic] )  break;
+
+  /* search longest edge */
+  maxe  = fabs(t.va-t.vb);
+  iedge = 1;
+  if ( maxe < fabs(t.vb-t.vc) ) {
+    maxe  = fabs(t.vb-t.vc);
+    iedge = 2;
+  }
+  if ( maxe < fabs(t.va-t.vc) ) {
+    maxe = fabs(t.va-t.vc);
+    iedge = 3;
+  }
+
+  /* split longest edge */
+  if ( maxe > 0.0 ) {
+    switch( iedge ) {
+    case 1:  /* edge a-b */
+      x  = ia < ib ? sc->iso.val[ia] : sc->iso.val[ib];
+      dd = (x-t.va) / (t.vb-t.va);
+      if ( dd > 0.001 && dd < 0.999 ) {
+        memcpy(&t1,&t,sizeof(struct triangle));
+        memcpy(&t2,&t,sizeof(struct triangle));
+        for (i=0; i<3; i++) {
+          t1.b[i]  = t2.a[i]  = t.a[i]  + dd*(t.b[i] -t.a[i]);
+          t1.nb[i] = t2.na[i] = t.na[i] + dd*(t.nb[i]-t.na[i]);
+        }
+        t1.vb = t2.va = x;
+        cutTriangle(sc,t1);
+        cutTriangle(sc,t2);
+        return;
+      }
+      break;
+
+    case 2:  /* edge b-c */
+      x  = ib < ic ? sc->iso.val[ib] : sc->iso.val[ic];
+      dd = (x-t.vb) / (t.vc-t.vb);
+      if ( dd > 0.001f && dd < 0.999f ) {
+        memcpy(&t1,&t,sizeof(struct triangle));
+        memcpy(&t2,&t,sizeof(struct triangle));
+        for (i=0; i<3; i++) {
+          t1.c[i]  = t2.b[i]  = t.b[i]  + dd*(t.c[i] -t.b[i]);
+          t1.nc[i] = t2.nb[i] = t.nb[i] + dd*(t.nc[i]-t.nb[i]);
+        }
+        t1.vc = t2.vb = x;
+        cutTriangle(sc,t1);
+        cutTriangle(sc,t2);
+        return;
+      }
+      break;
+    case 3:  /* edge c-a */
+      x  = ia < ic ? sc->iso.val[ia] : sc->iso.val[ic];
+      dd = (x-t.va) / (t.vc-t.va);
+      if ( dd > 0.001f && dd < 0.999f ) {
+        memcpy(&t1,&t,sizeof(struct triangle));
+        memcpy(&t2,&t,sizeof(struct triangle));
+        for (i=0; i<3; i++) {
+          t1.c[i]  = t2.a[i]  = t.a[i]  + dd*(t.c[i] -t.a[i]);
+          t1.nc[i] = t2.na[i] = t.na[i] + dd*(t.nc[i]-t.na[i]);
+        }
+        t1.vc = t2.va = x;
+        cutTriangle(sc,t1);
+        cutTriangle(sc,t2);
+        return;
+      }
+      break;
+    }
+  }
+
+  /* draw triangle */
+  if ( t.va < sc->iso.val[0] ) 
+    t.va = sc->iso.val[0];  
+  else if ( t.va > sc->iso.val[MAXISO-1] )
+    t.va = sc->iso.val[MAXISO-1];
+  kc = (t.va-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+  hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+  hsvrgb(hsv,rgb);
+
+  glColor4dv(rgb);
+  glNormal3fv(t.na);
+  glVertex3fv(t.a);
+
+  if ( t.vb < sc->iso.val[0] ) 
+    t.vb = sc->iso.val[0];
+  else if ( t.vb > sc->iso.val[MAXISO-1] )
+    t.vb = sc->iso.val[MAXISO-1];
+  kc = (t.vb-sc->iso.val[ib-1]) / (sc->iso.val[ib] - sc->iso.val[ib-1]);
+  hsv[0] = sc->iso.col[ib-1]*(1.0-kc)+sc->iso.col[ib]*kc;
+  hsvrgb(hsv,rgb);
+
+  glColor4dv(rgb);
+  glNormal3fv(t.nb);
+  glVertex3fv(t.b);
+
+  if ( t.vc < sc->iso.val[0] ) 
+    t.vc = sc->iso.val[0];
+  else if ( t.vc > sc->iso.val[MAXISO-1] )
+    t.vc = sc->iso.val[MAXISO-1];
+  kc = (t.vc-sc->iso.val[ic-1]) / (sc->iso.val[ic] - sc->iso.val[ic-1]);
+  hsv[0] = sc->iso.col[ic-1]*(1.0-kc)+sc->iso.col[ic]*kc;
+  hsvrgb(hsv,rgb);
+
+  glColor4dv(rgb);
+  glNormal3fv(t.nc);
+  glVertex3fv(t.c);
+}
+
+
+/* metric map: use linear interpolation on values
+   rather than color interpolation ! */
+GLuint listTriaMap(pScene sc,pMesh mesh) {
+  pMaterial  pm;
+  pTriangle  pt;
+  pPoint     p0,p1,p2;
+  pSolution  ps0,ps1,ps2;
+  GLint      dlist;
+  double     ax,ay,az,bx,by,bz,dd;
+  float      cx,cy,cz,n[3];
+  int        k,m,is0,is1,is2;
+  triangle   t;
+
+  /* default */
+  if ( !mesh->nt )  return(0);
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( ddebug ) printf("create display list map / TRIA\n");
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTria];
+    if ( !k || pm->flag )  continue;
+
+    if ( sc->type & S_FLAT ) {
+      glBegin(GL_TRIANGLES);
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+        p0 = &mesh->point[pt->v[0]];
+        p1 = &mesh->point[pt->v[1]];
+        p2 = &mesh->point[pt->v[2]];
+  
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0f ) {
+          dd = 1.0f / sqrt(dd);
+          n[0] *= dd;
+          n[1] *= dd;
+          n[2] *= dd;
+        }
+        memcpy(t.na,n,3*sizeof(float));
+        memcpy(t.nb,n,3*sizeof(float));
+        memcpy(t.nc,n,3*sizeof(float));
+
+        if ( sc->shrink < 1.0 ) {
+          cx = (p0->c[0] + p1->c[0] + p2->c[0]) / 3.0;
+          cy = (p0->c[1] + p1->c[1] + p2->c[1]) / 3.0;
+          cz = (p0->c[2] + p1->c[2] + p2->c[2]) / 3.0;
+          t.a[0] = sc->shrink*(p0->c[0]-cx)+cx;
+          t.a[1] = sc->shrink*(p0->c[1]-cy)+cy;
+          t.a[2] = sc->shrink*(p0->c[2]-cz)+cz;
+          t.b[0] = sc->shrink*(p1->c[0]-cx)+cx;
+          t.b[1] = sc->shrink*(p1->c[1]-cy)+cy;
+          t.b[2] = sc->shrink*(p1->c[2]-cz)+cz;
+          t.c[0] = sc->shrink*(p2->c[0]-cx)+cx;
+          t.c[1] = sc->shrink*(p2->c[1]-cy)+cy;
+          t.c[2] = sc->shrink*(p2->c[2]-cz)+cz;
+        }
+        else {
+          t.a[0] = p0->c[0];
+          t.a[1] = p0->c[1];
+          t.a[2] = p0->c[2];
+          t.b[0] = p1->c[0];
+          t.b[1] = p1->c[1];
+          t.b[2] = p1->c[2];
+          t.c[0] = p2->c[0];
+          t.c[1] = p2->c[1];
+          t.c[2] = p2->c[2];
+        }
+        if ( mesh->typage == 2 ) {
+          ps0  = &mesh->sol[pt->v[0]];
+          ps1  = &mesh->sol[pt->v[1]];
+          ps2  = &mesh->sol[pt->v[2]];
+          t.va = ps0->bb;
+          t.vb = ps1->bb;
+          t.vc = ps2->bb;
+        }
+        else {
+          ps0 = &mesh->sol[k];
+          t.va = t.vb = t.vc = ps0->bb;
+        }
+        cutTriangle(sc,t);
+        k = pt->nxt;
+      }
+      glEnd();
+    }
+    else {
+      glBegin(GL_TRIANGLES);
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+        p0 = &mesh->point[pt->v[0]];
+        p1 = &mesh->point[pt->v[1]];
+        p2 = &mesh->point[pt->v[2]];
+
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0f ) {
+      dd = 1.0f / sqrt(dd);
+      n[0] *= dd;
+      n[1] *= dd;
+      n[2] *= dd;
+        }
+
+        is0 = is1 = is2 = 0;
+        if ( mesh->extra->iv ) {
+          if ( pt->v[0] <= mesh->nvn )
+            is0 = mesh->extra->nv[pt->v[0]];
+          if ( pt->v[1] <= mesh->nvn )
+            is1 = mesh->extra->nv[pt->v[1]];
+          if ( pt->v[2] <= mesh->nvn )
+            is2 = mesh->extra->nv[pt->v[2]];
+        }
+        if ( !is0 && pt->v[0] <= mesh->extra->it )
+          is0 = mesh->extra->nt[3*(k-1)+1];
+        if ( !is1 && pt->v[1] <= mesh->extra->it )  
+          is1 = mesh->extra->nt[3*(k-1)+2];
+        if ( !is2 && pt->v[2] <= mesh->extra->it )
+          is2 = mesh->extra->nt[3*(k-1)+3];
+
+        if ( sc->shrink < 1.0 ) {
+          cx = (p0->c[0] + p1->c[0] + p2->c[0]) / 3.;
+          cy = (p0->c[1] + p1->c[1] + p2->c[1]) / 3.;
+          cz = (p0->c[2] + p1->c[2] + p2->c[2]) / 3.;
+          t.a[0] = sc->shrink*(p0->c[0]-cx)+cx;
+          t.a[1] = sc->shrink*(p0->c[1]-cy)+cy;
+          t.a[2] = sc->shrink*(p0->c[2]-cz)+cz;
+          t.b[0] = sc->shrink*(p1->c[0]-cx)+cx;
+          t.b[1] = sc->shrink*(p1->c[1]-cy)+cy;
+          t.b[2] = sc->shrink*(p1->c[2]-cz)+cz;
+          t.c[0] = sc->shrink*(p2->c[0]-cx)+cx;
+          t.c[1] = sc->shrink*(p2->c[1]-cy)+cy;
+          t.c[2] = sc->shrink*(p2->c[2]-cz)+cz;
+        }
+        else {
+          t.a[0] = p0->c[0];
+          t.a[1] = p0->c[1];
+          t.a[2] = p0->c[2];
+          t.b[0] = p1->c[0];
+          t.b[1] = p1->c[1];
+          t.b[2] = p1->c[2];
+          t.c[0] = p2->c[0];
+          t.c[1] = p2->c[1];
+          t.c[2] = p2->c[2];
+        }
+        if ( !is0 )
+          memcpy(t.na,n,3*sizeof(float));
+        else {
+          t.na[0] = mesh->extra->n[3*(is0-1)+1];
+          t.na[1] = mesh->extra->n[3*(is0-1)+2];
+          t.na[2] = mesh->extra->n[3*(is0-1)+3];
+        }
+        if ( !is1 )
+          memcpy(t.nb,n,3*sizeof(float));
+        else {
+          t.nb[0] = mesh->extra->n[3*(is1-1)+1];
+          t.nb[1] = mesh->extra->n[3*(is1-1)+2];
+          t.nb[2] = mesh->extra->n[3*(is1-1)+3];
+        }
+        if ( !is2 )
+          memcpy(t.nc,n,3*sizeof(float));
+        else {
+          t.nc[0] = mesh->extra->n[3*(is2-1)+1];
+          t.nc[1] = mesh->extra->n[3*(is2-1)+2];
+          t.nc[2] = mesh->extra->n[3*(is2-1)+3];
+        }
+        if ( mesh->typage == 2 ) {
+      ps0  = &mesh->sol[pt->v[0]];
+      ps1  = &mesh->sol[pt->v[1]];
+      ps2  = &mesh->sol[pt->v[2]];
+      t.va = ps0->bb;
+      t.vb = ps1->bb;
+      t.vc = ps2->bb;
+        }
+        else {
+      ps0 = &mesh->sol[k];
+      t.va = t.vb = t.vc = ps0->bb;
+        }
+        cutTriangle(sc,t);
+        k = pt->nxt;
+      }
+      glEnd();
+    }
+  }
+
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list of quadrilaterals */
+GLuint listQuadMap(pScene sc,pMesh mesh) {
+  pMaterial  pm;
+  pQuad      pq;
+  pPoint     p0,p1,p2,p3;
+  pSolution  ps0,ps1,ps2,ps3;
+  GLint      dlist = 0;
+  double     ax,ay,az,bx,by,bz,dd;
+  float      cx,cy,cz,n[3];
+  int        k,m,is0,is1,is2,is3;
+  triangle   t1,t2;
+
+  /* default */
+  if ( !mesh->nq ) return(0);
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( ddebug ) printf("create display list map / QUADS\n");
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LQuad];
+    if ( !k || pm->flag )  continue;
+
+    glBegin(GL_TRIANGLES);
+    while ( k != 0 ) {
+      pq = &mesh->quad[k];
+      if ( pq->v[0] == 0 ) {
+        k = pq->nxt;
+        continue;
+      }
+      p0 = &mesh->point[pq->v[0]];
+      p1 = &mesh->point[pq->v[1]];
+      p2 = &mesh->point[pq->v[2]];
+      p3 = &mesh->point[pq->v[3]];
+      
+      /* compute normal */
+      ax = p1->c[0] - p0->c[0];
+      ay = p1->c[1] - p0->c[1];
+      az = p1->c[2] - p0->c[2];
+      bx = p2->c[0] - p0->c[0];
+      by = p2->c[1] - p0->c[1];
+      bz = p2->c[2] - p0->c[2];
+      n[0] = ay*bz - az*by;
+      n[1] = az*bx - ax*bz;
+      n[2] = ax*by - ay*bx;
+      dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+      if ( dd > 0.0f ) {
+        dd = 1.0f / sqrt(dd);
+        n[0] *= dd;
+        n[1] *= dd;
+        n[2] *= dd;
+      }
+
+      if ( sc->shrink < 1.0 ) {
+        cx = 0.25 * (p0->c[0] + p1->c[0] + p2->c[0] + p3->c[0]);
+        cy = 0.25 * (p0->c[1] + p1->c[1] + p2->c[1] + p3->c[1]);
+        cz = 0.25 * (p0->c[2] + p1->c[2] + p2->c[2] + p3->c[2]);
+        t1.a[0] = t2.a[0] = sc->shrink*(p0->c[0]-cx)+cx;
+        t1.a[1] = t2.a[1] = sc->shrink*(p0->c[1]-cy)+cy;
+        t1.a[2] = t2.a[2] = sc->shrink*(p0->c[2]-cz)+cz;
+
+        t1.b[0] = sc->shrink*(p1->c[0]-cx)+cx;
+        t1.b[1] = sc->shrink*(p1->c[1]-cy)+cy;
+        t1.b[2] = sc->shrink*(p1->c[2]-cz)+cz;
+
+        t1.c[0] = t2.b[0] = sc->shrink*(p2->c[0]-cx)+cx; 
+        t1.c[1] = t2.b[1] = sc->shrink*(p2->c[1]-cy)+cy; 
+        t1.c[2] = t2.b[2] = sc->shrink*(p2->c[2]-cz)+cz; 
+
+        t2.c[0] = sc->shrink*(p3->c[0]-cx)+cx; 
+        t2.c[1] = sc->shrink*(p3->c[1]-cy)+cy; 
+        t2.c[2] = sc->shrink*(p3->c[2]-cz)+cz; 
+      }
+      else {
+        t1.a[0] = t2.a[0] = p0->c[0];
+        t1.a[1] = t2.a[1] = p0->c[1];
+        t1.a[2] = t2.a[2] = p0->c[2];
+
+        t1.b[0] = p1->c[0];
+        t1.b[1] = p1->c[1];
+        t1.b[2] = p1->c[2];
+
+        t1.c[0] = t2.b[0] = p2->c[0]; 
+        t1.c[1] = t2.b[1] = p2->c[1]; 
+        t1.c[2] = t2.b[2] = p2->c[2]; 
+
+        t2.c[0] = p3->c[0]; 
+        t2.c[1] = p3->c[1]; 
+        t2.c[2] = p3->c[2]; 
+      }
+      if ( sc->type & S_FLAT ) {
+        memcpy(t1.na,n,3*sizeof(float));
+        memcpy(t1.nb,n,3*sizeof(float));
+        memcpy(t1.nc,n,3*sizeof(float));
+        memcpy(t2.na,n,3*sizeof(float));
+        memcpy(t2.nb,n,3*sizeof(float));
+        memcpy(t2.nc,n,3*sizeof(float));
+      }
+      else {
+        is0 = is1 = is2 = is3 = 0;
+        if ( mesh->extra->iv ) {
+          if ( pq->v[0] <= mesh->nvn )
+            is0 = mesh->extra->nv[pq->v[0]];
+          if ( pq->v[1] <= mesh->nvn )
+            is1 = mesh->extra->nv[pq->v[1]];
+          if ( pq->v[2] <= mesh->nvn )
+            is2 = mesh->extra->nv[pq->v[2]];
+          if ( pq->v[3] <= mesh->nvn )
+            is3 = mesh->extra->nv[pq->v[3]];
+        }
+        if ( !is0 && pq->v[0] <= mesh->extra->iq )
+          is0 = mesh->extra->nq[4*(k-1)+1];
+        if ( !is1 && pq->v[1] <= mesh->extra->iq )
+          is1 = mesh->extra->nq[4*(k-1)+2];
+        if ( !is2 && pq->v[2] <= mesh->extra->iq )
+          is2 = mesh->extra->nq[4*(k-1)+3];
+        if ( !is3 && pq->v[3] <= mesh->extra->iq )
+          is3 = mesh->extra->nq[4*(k-1)+4];
+        
+        if ( !is0 )
+          memcpy(t1.na,n,3*sizeof(float));
+        else {
+          t1.na[0] = t2.na[0] = mesh->extra->n[3*(is0-1)+1];
+          t1.na[1] = t2.na[1] = mesh->extra->n[3*(is0-1)+2];
+          t1.na[2] = t2.na[2] = mesh->extra->n[3*(is0-1)+3];
+        }
+        if ( !is1 )
+          memcpy(t1.nb,n,3*sizeof(float));
+        else {
+          t1.nb[0] = mesh->extra->n[3*(is1-1)+1];
+          t1.nb[1] = mesh->extra->n[3*(is1-1)+2];
+          t1.nb[2] = mesh->extra->n[3*(is1-1)+3];
+        }
+        if ( !is2 )
+          memcpy(t1.nc,n,3*sizeof(float));
+        else {
+          t1.nc[0] = t2.nb[0] = mesh->extra->n[3*(is2-1)+1];
+          t1.nc[1] = t2.nb[1] = mesh->extra->n[3*(is2-1)+2];
+          t1.nc[2] = t2.nb[2] = mesh->extra->n[3*(is2-1)+3];
+        }
+        if ( !is3 )
+          memcpy(t1.nc,n,3*sizeof(float));
+        else {
+          t2.nc[0] = mesh->extra->n[3*(is3-1)+1];
+          t2.nc[1] = mesh->extra->n[3*(is3-1)+2];
+          t2.nc[2] = mesh->extra->n[3*(is3-1)+3];
+        }
+      }
+
+      if ( mesh->typage == 2 ) {
+        /* solutions at vertices */
+        ps0 = &mesh->sol[pq->v[0]];
+        ps1 = &mesh->sol[pq->v[1]];
+        ps2 = &mesh->sol[pq->v[2]];
+        ps3 = &mesh->sol[pq->v[3]];
+        t1.va = t2.va = ps0->bb;
+        t1.vb = ps1->bb;
+        t1.vc = t2.vb = ps2->bb;
+        t2.vc = ps3->bb;
+      }
+      else {
+        /* solution at element */
+        ps0 = &mesh->sol[k];
+        t1.va = t1.vb = t1.vc = ps0->bb;
+        t2.va = t2.vb = t2.vc = ps0->bb;
+      }
+      /* color interpolation */
+      cutTriangle(sc,t1);
+      cutTriangle(sc,t2);
+      k = pq->nxt;
+    }
+    glEnd();
+  }
+
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list of tetrahedra */
+GLuint listTetraMap(pScene sc,pMesh mesh,ubyte clip) {
+  pMaterial  pm;
+  pTetra     pt;
+  pPoint     p0,p1,p2;
+  pSolution  ps0,ps1,ps2;
+  GLint      dlist = 0;
+  float      cx,cy,cz,ax,ay,az,bx,by,bz,d,n[3];
+  int        k,l,m;
+  triangle   t;
+
+  /* default */
+  if ( !mesh->ntet )  return(0);
+  if ( ddebug ) printf("create display list map / TETRA\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+  
+  /* build list */
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTets];
+    if ( !k || pm->flag )  continue;
+
+    glBegin(GL_TRIANGLES);
+    while ( k != 0 ) {
+      pt = &mesh->tetra[k];
+      if ( !pt->v[0] || (clip && !pt->clip) ) {
+        k = pt->nxt;
+        continue;
+      }
+      /* build 4 faces */
+      cx = cy = cz = 0.0f;
+      for (l=0; l<4; l++) {
+    p0  = &mesh->point[pt->v[l]];
+    cx += p0->c[0];
+        cy += p0->c[1];
+        cz += p0->c[2];
+      }
+      cx /= 4.;
+      cy /= 4.;
+      cz /= 4.;
+
+      for (l=0; l<4; l++) {
+    p0 = &mesh->point[pt->v[ct[l][0]]];
+    p1 = &mesh->point[pt->v[ct[l][1]]];
+    p2 = &mesh->point[pt->v[ct[l][2]]];
+
+        /* compute face normal */
+    ax = p1->c[0] - p0->c[0]; ay = p1->c[1] - p0->c[1]; az = p1->c[2] - p0->c[2];
+    bx = p2->c[0] - p0->c[0]; by = p2->c[1] - p0->c[1]; bz = p2->c[2] - p0->c[2];
+    n[0] = ay*bz - az*by;
+    n[1] = az*bx - ax*bz;
+    n[2] = ax*by - ay*bx;
+    d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+    if ( d > 0.0f ) {
+      d = 1.0f / sqrt(d);
+      n[0] *= d;  
+          n[1] *= d;  
+          n[2] *= d;
+    }
+
+        /* store triangle */
+        t.a[0] = sc->shrink*(p0->c[0]-cx)+cx;
+        t.a[1] = sc->shrink*(p0->c[1]-cy)+cy;
+        t.a[2] = sc->shrink*(p0->c[2]-cz)+cz;
+
+        t.b[0] = sc->shrink*(p1->c[0]-cx)+cx;
+        t.b[1] = sc->shrink*(p1->c[1]-cy)+cy;
+        t.b[2] = sc->shrink*(p1->c[2]-cz)+cz;
+
+        t.c[0] = sc->shrink*(p2->c[0]-cx)+cx;
+        t.c[1] = sc->shrink*(p2->c[1]-cy)+cy; 
+        t.c[2] = sc->shrink*(p2->c[2]-cz)+cz; 
+        
+        /* store normals */
+        memcpy(t.na,n,3*sizeof(float));
+        memcpy(t.nb,n,3*sizeof(float));
+        memcpy(t.nc,n,3*sizeof(float));
+
+        if ( mesh->typage == 2 ) {
+          /* solutions at vertices */
+      ps0 = &mesh->sol[pt->v[ct[l][0]]];
+      ps1 = &mesh->sol[pt->v[ct[l][1]]];
+      ps2 = &mesh->sol[pt->v[ct[l][2]]];
+          t.va = ps0->bb;
+      t.vb = ps1->bb;
+      t.vc = ps2->bb;
+        }
+        else {
+          /* solution at element */  
+          ps0 = &mesh->sol[k];
+      t.va = t.vb = t.vc = ps0->bb;
+        }
+        /* color interpolation */
+        cutTriangle(sc,t);
+      }
+      k = pt->nxt;
+    }
+    glEnd();
+  }
+
+  glEndList();
+  return(dlist);
+}
+
+
+/* build list of hexahedra */
+GLuint listHexaMap(pScene sc,pMesh mesh,ubyte clip) {
+  pMaterial  pm;
+  pHexa      ph;
+  pPoint     p0,p1,p2,p3;
+  pSolution  ps0,ps1,ps2,ps3;
+  GLint      dlist = 0;
+  double     ax,ay,az,bx,by,bz,d;
+  float      n[3],cx,cy,cz;
+  int        k,l,m;
+  triangle   t1,t2;
+
+  if ( !mesh->nhex )  return(0);
+  if ( ddebug ) printf("create display list map / HEXA\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LHexa];
+    if ( !k || pm->flag )  continue;
+
+    glBegin(GL_TRIANGLES);
+    while ( k != 0 ) {
+      ph = &mesh->hexa[k];
+      if ( !ph->v[0] || (clip && !ph->clip) ) {
+        k = ph->nxt;
+        continue;
+      }
+      cx = cy = cz = 0.0f;
+      for (l=0; l<8; l++) {
+    p0  = &mesh->point[ph->v[l]];
+    cx += p0->c[0];
+        cy += p0->c[1];
+        cz += p0->c[2];
+      }
+      cx /= 8.; 
+      cy /= 8.;
+      cz /= 8.;
+      
+      for (l=0; l<6; l++) {
+    p0 = &mesh->point[ph->v[ch[l][0]]];
+    p1 = &mesh->point[ph->v[ch[l][1]]];
+    p2 = &mesh->point[ph->v[ch[l][2]]];
+    p3 = &mesh->point[ph->v[ch[l][3]]];
+        
+    /* compute face normal */
+    ax = p1->c[0] - p0->c[0]; ay = p1->c[1] - p0->c[1]; az = p1->c[2] - p0->c[2];
+    bx = p2->c[0] - p0->c[0]; by = p2->c[1] - p0->c[1]; bz = p2->c[2] - p0->c[2];
+    n[0] = ay*bz - az*by;
+    n[1] = az*bx - ax*bz;
+    n[2] = ax*by - ay*bx;
+    d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+    if ( d > 0.0f ) {
+      d = 1.0f / sqrt(d);
+      n[0] *= d;  
+          n[1] *= d;  
+          n[2] *= d;
+    }
+
+        /* store triangles */
+        t1.a[0] = t2.a[0] = sc->shrink*(p0->c[0]-cx)+cx;
+        t1.a[1] = t2.a[1] = sc->shrink*(p0->c[1]-cy)+cy;
+        t1.a[2] = t2.a[2] = sc->shrink*(p0->c[2]-cz)+cz;
+
+        t1.b[0] = sc->shrink*(p1->c[0]-cx)+cx;
+        t1.b[1] = sc->shrink*(p1->c[1]-cy)+cy;
+        t1.b[2] = sc->shrink*(p1->c[2]-cz)+cz;
+
+        t1.c[0] = t2.b[0] = sc->shrink*(p2->c[0]-cx)+cx; 
+        t1.c[1] = t2.b[1] = sc->shrink*(p2->c[1]-cy)+cy; 
+        t1.c[2] = t2.b[2] = sc->shrink*(p2->c[2]-cz)+cz; 
+
+        t2.c[0] = sc->shrink*(p3->c[0]-cx)+cx; 
+        t2.c[1] = sc->shrink*(p3->c[1]-cy)+cy; 
+        t2.c[2] = sc->shrink*(p3->c[2]-cz)+cz; 
+
+        /* store normals */
+    memcpy(t1.na,n,3*sizeof(float));
+    memcpy(t1.nb,n,3*sizeof(float));
+    memcpy(t1.nc,n,3*sizeof(float));
+    memcpy(t2.na,n,3*sizeof(float));
+    memcpy(t2.nb,n,3*sizeof(float));
+    memcpy(t2.nc,n,3*sizeof(float));
+
+        if ( mesh->typage == 2 ) {
+          /* solutions at vertices */
+      ps0 = &mesh->sol[ph->v[ch[l][0]]];
+      ps1 = &mesh->sol[ph->v[ch[l][1]]];
+      ps2 = &mesh->sol[ph->v[ch[l][2]]];
+      ps3 = &mesh->sol[ph->v[ch[l][3]]];
+      t1.va = t2.va = ps0->bb;
+      t1.vb = ps1->bb;
+      t1.vc = t2.vb = ps2->bb;
+      t2.vc = ps3->bb;
+        }
+        else {
+          /* solution at element */
+      ps0 = &mesh->sol[k];
+      t1.va = t1.vb = t1.vc = ps0->bb;
+      t2.va = t2.vb = t2.vc = ps0->bb;
+        }
+        /* color interpolation */
+        cutTriangle(sc,t1);
+        cutTriangle(sc,t2);
+     }
+     k = ph->nxt;
+   }
+   glEnd();
+  }
+  
+  glEndList();
+  return(dlist);
+}
+
+
+GLuint alt2dList(pScene sc,pMesh mesh,int geomtype,float shrink,float altcoef) {
+  pTriangle  pt,pt1;
+  pMaterial  pm;
+  pQuad      pq;
+  pPoint     p0,p1,p2,p3;
+  pSolution  ps0,ps1,ps2,ps3;
+  GLuint     dlist;
+  double     ax,ay,az,bx,by,bz,dd,kc,rgb[4];
+  float      cx,cy,cz,n[3];
+  int       *adj,k,m,ia,iadr;
+  ubyte     *voy;
+  triangle   t,t1,t2;
+  static double hsv[3] = { 0.0, 1.0, 0.80 };
+  static float  nn[3] = {1.0, 0.0, 0.0 };
+
+  /* default */
+  if ( ddebug ) printf("create 2d elevation map list\n");
+
+  if ( geomtype == LTria && !mesh->nt )  return(0);
+  if ( geomtype == LQuad && !mesh->nq )  return(0);
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  mesh->zmin = altcoef*mesh->bbmin;
+  mesh->zmax = altcoef*mesh->bbmax;
+  if ( mesh->bbmin*mesh->bbmax < 0.0 ) {
+    mesh->ztra = mesh->zmin;
+  }
+  else {
+    mesh->ztra = 0.95 * mesh->zmin;
+  }
+
+  switch (geomtype) {
+  case LTria:
+    if ( ddebug ) printf("create triangle list %d\n",mesh->nt);
+    
+    if ( mesh->typage == 1 ) {
+      if ( mesh->nt && !hashTria(mesh) )    return(0);
+    }
+
+    glBegin(GL_TRIANGLES);
+
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTria];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        p0 = &mesh->point[pt->v[0]];
+        p1 = &mesh->point[pt->v[1]];
+        p2 = &mesh->point[pt->v[2]];
+      
+        if ( mesh->typage == 1 )
+          ps0 = ps1 = ps2 = &mesh->sol[k];
+        else {
+          ps0  = &mesh->sol[pt->v[0]];
+          ps1  = &mesh->sol[pt->v[1]];
+          ps2  = &mesh->sol[pt->v[2]];
+        }
+        cx = (p0->c[0] + p1->c[0] + p2->c[0]) / 3.0;
+        cy = (p0->c[1] + p1->c[1] + p2->c[1]) / 3.0;
+        cz = (ps0->bb + ps1->bb + ps2->bb) / 3.0;
+
+        t.a[0] = shrink*(p0->c[0]-cx) + cx;
+        t.a[1] = shrink*(p0->c[1]-cy) + cy;
+        t.a[2] = shrink*(altcoef*ps0->bb-cz) + cz - 0.25*mesh->ztra;
+
+        t.b[0] = shrink*(p1->c[0]-cx) + cx;
+        t.b[1] = shrink*(p1->c[1]-cy) + cy;
+        t.b[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+        
+        t.c[0] = shrink*(p2->c[0]-cx) + cx;
+        t.c[1] = shrink*(p2->c[1]-cy) + cy;
+        t.c[2] = shrink*(altcoef*ps2->bb-cz) + cz - 0.25*mesh->ztra;
+        
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0 ) {
+      dd = 1.0 / sqrt(dd);
+      n[0] *= dd;
+      n[1] *= dd;
+      n[2] *= dd;
+        }
+
+        memcpy(t.na,n,3*sizeof(float));
+        memcpy(t.nb,n,3*sizeof(float));
+        memcpy(t.nc,n,3*sizeof(float));
+
+        t.va = ps0->bb;
+        t.vb = ps1->bb;
+        t.vc = ps2->bb;
+
+        if ( mesh->typage == 2 ) 
+          cutTriangle(sc,t);
+
+        else {
+          if ( t.va < sc->iso.val[0] ) 
+            t.va = sc->iso.val[0];  
+          else if ( t.va > sc->iso.val[MAXISO-1] )
+            t.va = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( t.va < sc->iso.val[ia] )  break;
+          kc = (t.va-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+
+          glColor4dv(rgb);
+          glNormal3fv(t.na);
+          glVertex3fv(t.a);
+          glVertex3fv(t.b);
+          glVertex3fv(t.c);
+
+          /* add quads to sides (thanks to F. Lagoutiere) */
+          iadr = 3*(k-1)+1;
+          adj  = &mesh->adja[iadr];
+          voy  = &mesh->voy[iadr];
+
+          if ( adj[0] && adj[0] < k ) {
+            pt1 = &mesh->tria[ adj[0] ]; 
+            p3  = &mesh->point[ pt1->v[voy[0]] ];
+            ps1 = &mesh->sol[ adj[0] ];
+            
+            cx = (p1->c[0] + p2->c[0] + p3->c[0]) / 3.0;
+            cy = (p1->c[1] + p2->c[1] + p3->c[1]) / 3.0;
+            cz = ps1->bb;
+
+            memcpy(t1.a,t.b,3*sizeof(float));
+            memcpy(t1.b,t.c,3*sizeof(float));
+            memcpy(t1.c,t.b,3*sizeof(float));
+            t1.c[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.va = ps0->bb;
+            t1.vb = ps0->bb;
+            t1.vc = ps1->bb;
+            memcpy(t1.na,nn,3*sizeof(float));
+            memcpy(t1.nb,nn,3*sizeof(float));
+            memcpy(t1.nc,nn,3*sizeof(float));
+            cutTriangle(sc,t1);
+
+            memcpy(t1.a,t.c,3*sizeof(float));
+            memcpy(t1.b,t.c,3*sizeof(float));
+            memcpy(t1.c,t.b,3*sizeof(float));
+            t1.b[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.c[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.va = ps0->bb;
+            t1.vb = ps1->bb;
+            t1.vc = ps1->bb;
+            memcpy(t1.na,nn,3*sizeof(float));
+            memcpy(t1.nb,nn,3*sizeof(float));
+            memcpy(t1.nc,nn,3*sizeof(float));
+            cutTriangle(sc,t1);
+          }
+          if ( adj[1] && adj[1] < k ) {
+            pt1 = &mesh->tria[ adj[1] ]; 
+            p3  = &mesh->point[ pt1->v[voy[1]] ];
+            ps1 = &mesh->sol[ adj[1] ];
+            
+            cx = (p0->c[0] + p2->c[0] + p3->c[0]) / 3.0;
+            cy = (p0->c[1] + p2->c[1] + p3->c[1]) / 3.0;
+            cz = ps1->bb;
+
+            memcpy(t1.a,t.a,3*sizeof(float));
+            memcpy(t1.b,t.c,3*sizeof(float));
+            memcpy(t1.c,t.a,3*sizeof(float));
+            t1.c[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.va = ps0->bb;
+            t1.vb = ps0->bb;
+            t1.vc = ps1->bb;
+            memcpy(t1.na,nn,3*sizeof(float));
+            memcpy(t1.nb,nn,3*sizeof(float));
+            memcpy(t1.nc,nn,3*sizeof(float));
+            cutTriangle(sc,t1);
+
+            memcpy(t1.a,t.c,3*sizeof(float));
+            memcpy(t1.b,t.c,3*sizeof(float));
+            memcpy(t1.c,t.a,3*sizeof(float));
+            t1.b[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.c[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.va = ps0->bb;
+            t1.vb = ps1->bb;
+            t1.vc = ps1->bb;
+            memcpy(t1.na,nn,3*sizeof(float));
+            memcpy(t1.nb,nn,3*sizeof(float));
+            memcpy(t1.nc,nn,3*sizeof(float));
+            cutTriangle(sc,t1);
+          }
+          if ( adj[2] && adj[2] < k ) {
+            pt1 = &mesh->tria[ adj[2] ]; 
+            p3  = &mesh->point[ pt1->v[voy[2]] ];
+            ps1 = &mesh->sol[ adj[2] ];
+            
+            cx = (p0->c[0] + p1->c[0] + p3->c[0]) / 3.0;
+            cy = (p0->c[1] + p1->c[1] + p3->c[1]) / 3.0;
+            cz = ps1->bb;
+
+            memcpy(t1.a,t.a,3*sizeof(float));
+            memcpy(t1.b,t.b,3*sizeof(float));
+            memcpy(t1.c,t.a,3*sizeof(float));
+            t1.c[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.va = ps0->bb;
+            t1.vb = ps0->bb;
+            t1.vc = ps1->bb;
+            memcpy(t1.na,nn,3*sizeof(float));
+            memcpy(t1.nb,nn,3*sizeof(float));
+            memcpy(t1.nc,nn,3*sizeof(float));
+            cutTriangle(sc,t1);
+
+            memcpy(t1.a,t.b,3*sizeof(float));
+            memcpy(t1.b,t.b,3*sizeof(float));
+            memcpy(t1.c,t.a,3*sizeof(float));
+            t1.b[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.c[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+            t1.va = ps0->bb;
+            t1.vb = ps1->bb;
+            t1.vc = ps1->bb;
+            memcpy(t1.na,nn,3*sizeof(float));
+            memcpy(t1.nb,nn,3*sizeof(float));
+            memcpy(t1.nc,nn,3*sizeof(float));
+            cutTriangle(sc,t1);
+          }
+        }
+
+        k = pt->nxt;
+      }
+    }
+    glEnd();
+    break;
+    
+  case LQuad:
+    if ( ddebug ) printf("create quadrilateral list %d\n",mesh->nq);
+
+    glBegin(GL_TRIANGLES);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LQuad];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pq = &mesh->quad[k];
+        if ( !pq->v[0] ) {
+          k = pq->nxt;
+          continue;
+        }
+        
+        p0 = &mesh->point[pq->v[0]];
+        p1 = &mesh->point[pq->v[1]];
+        p2 = &mesh->point[pq->v[2]];
+        p3 = &mesh->point[pq->v[3]];
+      
+        if ( mesh->typage == 1 )
+          ps0 = ps1 = ps2 = ps3 = &mesh->sol[k];
+        else {
+      ps0 = &mesh->sol[pq->v[0]];
+      ps1 = &mesh->sol[pq->v[1]];
+      ps2 = &mesh->sol[pq->v[2]];
+      ps3 = &mesh->sol[pq->v[3]];
+    }
+        cx = 0.25 * (p0->c[0] + p1->c[0] + p2->c[0] + p3->c[0]);
+        cy = 0.25 * (p0->c[1] + p1->c[1] + p2->c[1] + p3->c[1]);
+        cz = 0.25 * (ps0->bb + ps1->bb + ps2->bb + ps3->bb);
+
+        t.a[0] = t2.a[0] = shrink*(p0->c[0]-cx) + cx;
+        t.a[1] = t2.a[1] = shrink*(p0->c[1]-cy) + cy;
+        t.a[2] = t2.a[2] = shrink*(altcoef*ps0->bb-cz) + cz - 0.25*mesh->ztra;
+
+        t.b[0] = shrink*(p1->c[0]-cx) + cx;
+        t.b[1] = shrink*(p1->c[1]-cy) + cy;
+        t.b[2] = shrink*(altcoef*ps1->bb-cz) + cz - 0.25*mesh->ztra;
+        
+        t.c[0] = t2.b[0] = shrink*(p2->c[0]-cx) + cx;
+        t.c[1] = t2.b[1] = shrink*(p2->c[1]-cy) + cy;
+        t.c[2] = t2.b[2] = shrink*(altcoef*ps2->bb-cz) + cz - 0.25*mesh->ztra;
+
+        t2.c[0] = shrink*(p3->c[0]-cx) + cx;
+        t2.c[1] = shrink*(p3->c[1]-cy) + cy;
+        t2.c[2] = shrink*(altcoef*ps3->bb-cz) + cz - 0.25*mesh->ztra;
+
+        /* compute normal */
+        ax = p1->c[0] - p0->c[0];
+        ay = p1->c[1] - p0->c[1];
+        az = p1->c[2] - p0->c[2];
+        bx = p2->c[0] - p0->c[0];
+        by = p2->c[1] - p0->c[1];
+        bz = p2->c[2] - p0->c[2];
+        n[0] = ay*bz - az*by;
+        n[1] = az*bx - ax*bz;
+        n[2] = ax*by - ay*bx;
+        dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+        if ( dd > 0.0f ) {
+      dd = 1.0f / sqrt(dd);
+      n[0] *= dd;
+      n[1] *= dd;
+      n[2] *= dd;
+        }
+        memcpy(t.na,n,3*sizeof(float));
+        memcpy(t.nb,n,3*sizeof(float));
+        memcpy(t.nc,n,3*sizeof(float));
+        memcpy(t2.na,n,3*sizeof(float));
+        memcpy(t2.nb,n,3*sizeof(float));
+        memcpy(t2.nc,n,3*sizeof(float));
+
+        t.va = t2.va = ps0->bb;
+        t.vb = ps1->bb;
+        t.vc = t2.vb = ps2->bb;
+        t2.vc = ps3->bb;
+
+        cutTriangle(sc,t);
+        cutTriangle(sc,t2);
+
+        k = pq->nxt;
+      }
+    }
+    glEnd();
+    break;
+  }
+  glEndList();
+
+  return(dlist);
+}
+
+
+/* setup color table */
+void setupPalette(pScene sc,pMesh mesh) {
+  double     delta;
+  int        i;
+
+  if ( ddebug ) printf("create palette %f %f\n",mesh->bbmin,mesh->bbmax);
+
+  if ( !sc->iso.palette ) {
+    delta = mesh->bbmax - mesh->bbmin;
+    for (i=0; i<MAXISO; i++) {
+      sc->iso.col[i] = 240.0 *(1.0 - (float)i/(MAXISO-1));
+      sc->iso.val[i] = mesh->bbmin + i * delta/(MAXISO-1);
+    }
+    sc->iso.palette = 1;
+  }
+  else {
+    for (i=0; i<MAXISO; i++)
+      sc->iso.col[i] = 240.0 *(1.0 - (float)i/(MAXISO-1));
+  }
+}
+
+
+/* build color palette */
+GLuint drawPalette(pScene sc) {
+  double     rgb[3];
+  float      xpos,ypos,inc,top,bottom,left,right;
+  int        i;
+  static double hsv[3] = {1.0, 1.0, 0.80};
+
+  if ( sc->iso.palette < 3 ) {
+    if ( sc->iso.palette <= 2 ) {
+      top     = sc->par.ys - 20;
+      bottom  = top - 10;
+      left    = sc->par.xs / 10;
+      right   = sc->par.xs - left;
+    }
+    else if ( sc->iso.palette == 2 ) {
+      top     = 40;
+      bottom  = top - 10;
+      left    = sc->par.xs / 10;
+      right   = sc->par.xs - left;
+    }
+
+    inc  = (sc->par.xs-2*left) / (MAXISO-1);
+    xpos = left;
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glBegin(GL_QUADS);
+    for (i=1; i<MAXISO; i++) {
+      hsv[0] = sc->iso.col[i-1];
+      hsvrgb(hsv,rgb);
+      glColor3dv(rgb);
+      glVertex2f(xpos,bottom);
+      glVertex2f(xpos,top);
+
+      hsv[0] = sc->iso.col[i];
+      hsvrgb(hsv,rgb);
+      glColor3dv(rgb);
+      glVertex2f(xpos+inc,top);
+      glVertex2f(xpos+inc,bottom);
+      xpos += inc;
+    }
+    glEnd();
+
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glLineWidth(1.0);
+    glColor3fv(sc->par.line);
+    glRectf(left,bottom,xpos,top);
+
+    /* graduate  */
+    xpos = left / 2;
+    bottom -= 10;
+    top    += 5;
+    output2(xpos,bottom,"%.4E",sc->iso.val[0]);
+    xpos = left;
+    for (i=1; i<MAXISO-1; i++) {
+      xpos += inc;
+      if ( (i % 2) == 0 ) {
+        output2(xpos-25.0,bottom,"%.4E",sc->iso.val[i]);
+        glBegin(GL_LINES);
+          glVertex2f(xpos,bottom+15);
+          glVertex2f(xpos,bottom+10);
+        glEnd();
+      }
+      else {
+        output2(xpos-25.0,top,"%.4E",sc->iso.val[i]);
+        glBegin(GL_LINES);
+          glVertex2f(xpos,top-10);
+          glVertex2f(xpos,top-5);
+        glEnd();
+      }
+    }
+    output2(right-left/2,bottom,"%.4E",sc->iso.val[MAXISO-1]);
+  }
+
+  else if ( sc->iso.palette == 3 ) {
+    bottom  = sc->par.ys / 10;
+    top     = sc->par.ys - bottom;
+    left    = 10;
+    right   = left + 15;
+
+    inc  = (sc->par.ys-2*bottom) / (MAXISO-1);
+    ypos = bottom;
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glBegin(GL_QUADS);
+    for (i=1; i<MAXISO; i++) {
+      hsv[0] = sc->iso.col[i-1];
+      hsvrgb(hsv,rgb);
+      glColor3dv(rgb);
+      glVertex2f(left,ypos);
+      glVertex2f(right,ypos);
+
+      hsv[0] = sc->iso.col[i];
+      hsvrgb(hsv,rgb);
+      glColor3dv(rgb);
+      glVertex2f(right,ypos+inc);
+      glVertex2f(left,ypos+inc);
+      ypos += inc;
+    }
+    glEnd();
+
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glLineWidth(1.0);
+    glColor3fv(sc->par.line);
+    glRectf(left,bottom,right,top);
+
+    /* graduate  */
+    ypos    = bottom;
+    right  += 5;
+    output2(right,bottom,"%.4E",sc->iso.val[0]);
+    for (i=1; i<MAXISO-1; i++) {
+      ypos += inc;
+      output2(right,ypos,"%.4E",sc->iso.val[i]);
+      glBegin(GL_LINES);
+        glVertex2f(right-5,ypos);
+        glVertex2f(right-13,ypos);
+      glEnd();
+    }
+    output2(right,top,"%.4E",sc->iso.val[MAXISO-1]);
+  }
+
+  else {
+    bottom  = sc->par.ys / 10;
+    top     = sc->par.ys - bottom;
+    right   = sc->par.xs - 10;
+    left    = right - 15;
+    inc  = (sc->par.ys-2*bottom) / (MAXISO-1);
+
+    ypos = bottom;
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glBegin(GL_QUADS);
+    for (i=1; i<MAXISO; i++) {
+      hsv[0] = sc->iso.col[i-1];
+      hsvrgb(hsv,rgb);
+      glColor3dv(rgb);
+      glVertex2f(left,ypos);
+      glVertex2f(right,ypos);
+
+      hsv[0] = sc->iso.col[i];
+      hsvrgb(hsv,rgb);
+      glColor3dv(rgb);
+      glVertex2f(right,ypos+inc);
+      glVertex2f(left,ypos+inc);
+      ypos += inc;
+    }
+    glEnd();
+
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glLineWidth(1.0);
+    glColor3fv(sc->par.line);
+    glRectf(left,bottom,right,top);
+
+    /* graduate  */
+    ypos  = bottom;
+    left -= 65;
+    output2(left,bottom,"%.4E",sc->iso.val[0]);
+    for (i=1; i<MAXISO-1; i++) {
+      ypos += inc;
+      output2(left,ypos,"%.4E",sc->iso.val[i]);
+      glBegin(GL_LINES);
+        glVertex2f(left+65,ypos);
+        glVertex2f(left+75,ypos);
+      glEnd();
+    }
+    output2(left,top,"%.4E",sc->iso.val[MAXISO-1]);
+  }
+
+  return(1);
+}
+
diff --git a/src/medit/morphing.c b/src/medit/morphing.c
new file mode 100644
index 0000000..1cf1d99
--- /dev/null
+++ b/src/medit/morphing.c
@@ -0,0 +1,92 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define MAX_MORPH   100
+
+int     imstep,imreverse;
+
+int modeMorphing() {
+  pScene   scene;
+  pMesh    mesh1,mesh2;
+  pPoint   ppt1,ppt2;
+  int      k;
+  clock_t  ct;
+
+  /* default */
+  cv.nbs    = 1;
+  imstep    = 1;
+  imreverse = 1;
+  if ( ddebug ) printf("morphing: create window\n");
+  fprintf(stdout,"\n Building scene\n");
+  ct = clock();
+
+  /* create grafix */
+  scene = cv.scene[0];
+  mesh1 = cv.mesh[0];
+  iniopt(scene,mesh1);
+  parsop(scene,mesh1);
+  meshRef(scene,mesh1);
+  matSort(scene);
+
+  mesh2 = cv.mesh[1];
+  parsop(scene,mesh2);
+  meshRef(scene,mesh2);
+  for (k=1; k<=mesh2->np; k++) {
+    ppt1 = &mesh1->point[k]; 
+    ppt2 = &mesh2->point[k];
+    ppt2->c[0] -= ppt1->c[0]; 
+    ppt2->c[1] -= ppt1->c[1];
+    ppt2->c[2] -= ppt1->c[2];
+  }
+
+  if ( !createScene(scene,0) ) {
+    fprintf(stderr,"  ## Unable to create scene\n");
+    return(0);
+  }
+  ct = difftime(clock(),ct);
+  fprintf(stdout,"  Scene seconds:      %.2f\n",
+          (double)ct/(double)CLOCKS_PER_SEC);
+  return(1);
+}
+
+
+int morphMesh(pScene sc,pMesh mesh1) {
+  pMesh       mesh2;
+  pPoint      ppt1,ppt2;
+  int         k;
+  static  float  dt = 1.0 / MAX_MORPH;
+
+  imstep++;
+  if ( imstep == 0 ) {
+    imstep = 2;
+    dt = -dt;
+    if ( !imreverse ) {
+      glutIdleFunc(NULL);
+      morphing = 0;
+      return(0);
+    }
+  }
+  else if ( imstep == MAX_MORPH+1 ) {
+    imstep = -MAX_MORPH+1;
+    dt = -dt;
+    if ( !imreverse ) {
+      glutIdleFunc(NULL);
+      morphing = 0;
+      return(0);
+    }
+  }
+
+  mesh2 = cv.mesh[1];
+
+  for (k=1; k<=mesh1->np; k++) {
+    ppt1 = &mesh1->point[k];
+    ppt2 = &mesh2->point[k];
+    ppt1->c[0] += dt*ppt2->c[0]; 
+    ppt1->c[1] += dt*ppt2->c[1]; 
+    ppt1->c[2] += dt*ppt2->c[2]; 
+  }
+
+  doLists(sc,mesh1);
+  return(1);
+}
diff --git a/src/medit/mouse.c b/src/medit/mouse.c
new file mode 100644
index 0000000..2fca6af
--- /dev/null
+++ b/src/medit/mouse.c
@@ -0,0 +1,438 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+	
+#ifndef  ON
+#define  ON     1
+#define  OFF    0
+#endif
+
+
+GLuint    lasttime;
+GLboolean tracking = GL_FALSE,ctracking = GL_FALSE;
+GLboolean picking = GL_FALSE;
+int       cbutton  = 0;
+int       startx,starty,curx,cury;
+int       rxi,ryi,rx1,rx2,ry1,ry2; 
+
+#define MinWH   0.1
+#define MaxWH   0.9
+
+#ifndef GLUT_BUTTON_3
+#define GLUT_BUTTON_3   2
+#define GLUT_BUTTON_4   3
+#endif
+
+/* project x,y, onto a hemi-sphere */
+static void point2Vect(int x,int y,int w,int h,float *v) {
+  double   d,a,areax,areay;
+
+  areax = (w-startx) / w;
+  areay = (h-starty) / h;
+  if ( areax > MinWH && areax < MaxWH && areay > MinWH && areay < MaxWH ) {
+    v[0] = (2.0 * x - w) / w;
+    v[1] = (h - 2.0 * y) / h;
+    v[2] = 1.0f;
+  }
+  else {
+    v[0] =  2.0f*(x-startx) / w;
+    v[1] = -2.0f*(y-starty) / h;
+    v[2] = 1.0f;
+  }
+  d = v[0]*v[0]+v[1]*v[1];
+  if ( d == 0.0f )  return;
+  d = sqrt(d);
+
+  v[2] = cos(M_PI_2 * ((d < 1.0) ? d : 1.0));
+  d    = v[0]*v[0]+v[1]*v[1]+v[2]*v[2];
+  a    = 1.0f / sqrt(d);
+  v[0] *= a;  
+  v[1] *= a;  
+  v[2] *= a;
+}
+
+
+void ortho2D(pScene sc,ubyte mode) {
+  if ( mode == ON ) {
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+    gluOrtho2D(0,sc->par.xs,0.,sc->par.ys);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_DEPTH_TEST);
+    glMatrixMode(GL_MODELVIEW);
+  }
+  else if ( mode == OFF ) {
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix();
+    glMatrixMode(GL_MODELVIEW);
+    glEnable(GL_DEPTH_TEST);
+    glLineWidth(1.);
+  }
+}
+
+static void drawRubberBand(int xa,int ya,int xb,int yb) {
+  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+  glLineWidth(2.0);
+  glColor3f(0.5,0.5,0.5);
+  glRecti(xa,ya,xb,yb);
+}
+
+static void rubberMotion(int x,int y) {
+  pScene      sc;
+  pPersp      p;
+
+  sc = cv.scene[currentScene()];
+  p  = sc->persp;
+
+  glEnable(GL_COLOR_LOGIC_OP);
+  glLogicOp(GL_XOR);
+
+  /* draw frame */
+  drawRubberBand(rxi,ryi,rx1,ry1);
+  rx2 = x;
+  ry2 = sc->par.ys-y;
+  drawRubberBand(rxi,ryi,rx2,ry2);
+  glFlush();
+
+  glLogicOp(GL_COPY);
+  glDisable(GL_COLOR_LOGIC_OP);
+
+  /* keep old coords */
+  rx1 = rx2;
+  ry1 = ry2;
+}
+
+
+void zoomMotion(int x,int y) {
+  pScene      sc;
+  pPersp      p;
+  int         dy;
+
+  sc = cv.scene[currentScene()];
+  p  = sc->persp;
+
+  dy = starty - y;
+  if ( dy > 0 )
+    if ( p->fovy < 1.0e-02 )  
+      return;
+    else 
+      p->fovy = max(0.95*p->fovy,1e-05);
+  else if ( p->fovy > 160.0 )  return;
+  else
+    p->fovy = min(1.1*p->fovy,179.0);
+
+  farclip(1);
+  starty = y;
+  glutPostRedisplay();
+}
+
+
+void mouse(int button,int state,int x,int y) {
+  pScene      sc;
+  pTransform  tr;
+  pPersp      p;
+  int         keyact,idw = currentScene();
+  static int  olds = -1;
+  
+  picking=GL_FALSE;
+
+  /* default */
+  if ( ddebug ) printf("control mouse %d\n",state);
+  sc = cv.scene[idw];
+  p  = sc->persp;
+  if ( sc->cube->active & C_EDIT )
+    tr = sc->cube->cubetr;
+  else if ( sc->clip->active & C_EDIT ) 
+    tr = sc->clip->cliptr;
+  else
+    tr = sc->view;
+  tr->mstate  = state;
+  tr->mbutton = button;
+
+  /* check if ctrl-shift-alt pressed */
+  keyact = glutGetModifiers();
+
+  if ( state == GLUT_DOWN ) {
+    tracking = GL_TRUE;
+    lasttime = glutGet(GLUT_ELAPSED_TIME);
+
+    if ( button == GLUT_LEFT_BUTTON ) {
+      if ( keyact == GLUT_ACTIVE_SHIFT ) {
+        /* entity designation */
+        picking = GL_TRUE;
+	if ( sc->picklist ) glDeleteLists(sc->picklist,1);
+	sc->picklist = pickingScene(sc,x,y,0);
+	return;
+      }
+
+      else if ( keyact == GLUT_ACTIVE_ALT ) {
+	    /* zoom */
+	    starty = y;
+	    glutMotionFunc(zoomMotion);
+	    return;
+      }
+
+      else if ( keyact == GLUT_ACTIVE_CTRL ) {
+        /* rubberband selection */
+        glutSetCursor(GLUT_CURSOR_CROSSHAIR);
+        p->rubix  = p->rubfx = x;
+        p->rubiy  = p->rubfy = sc->par.ys-y;
+        rxi = rx1 = x;
+        ryi = ry1 = sc->par.ys-y;
+        p->rubber = 1;
+        glDrawBuffer(GL_BACK_LEFT);
+        ortho2D(sc,ON);
+        glutMotionFunc(rubberMotion);
+        return;
+      }
+    }
+    
+    else if ( button == GLUT_MIDDLE_BUTTON && keyact & GLUT_ACTIVE_SHIFT ) {
+      picking = GL_TRUE;
+      if ( sc->picklist ) glDeleteLists(sc->picklist,1);
+      sc->picklist = pickingScene(sc,x,y,LPoint);
+      return;
+    }
+
+    /* transformation */
+    startx = x;
+    starty = y;
+    point2Vect(x,y,sc->par.xs,sc->par.ys,tr->pos);
+    glutSetCursor(GLUT_CURSOR_INFO);
+  }
+
+  else if ( state == GLUT_UP ) {
+
+    if ( button == GLUT_LEFT_BUTTON ) {
+      
+      if ( keyact == GLUT_ACTIVE_CTRL ) {
+        /* rubberband selection */
+        p->rubfx  = x;
+        p->rubfy  = sc->par.ys-y;
+        p->rubber = 2;
+        glDrawBuffer(GL_BACK_LEFT);
+        ortho2D(sc,OFF);
+        glutMotionFunc(motion);
+        return;
+      }
+      
+      else if ( keyact == GLUT_ACTIVE_ALT ) {
+        glutMotionFunc(motion);
+	    return;
+      }
+
+      else if ( picking == GL_TRUE ) {
+        picking = GL_FALSE;
+        reshapeScene(sc->par.xs,sc->par.ys);
+        glutPostRedisplay();
+      }
+    }
+    
+    glutMotionFunc(motion);
+    if ( sc->clip->active & C_EDIT )
+      sc->clip->active |= C_REDO;
+
+    /* transformation */
+    glutSetCursor(GLUT_CURSOR_INHERIT);
+    tracking = GL_FALSE;
+    if ( glutGet(GLUT_ELAPSED_TIME) >= lasttime ) { 
+      if ( tr->manim == GL_TRUE )  glutIdleFunc(glutIdle);
+      else  tr->angle = 0.0;
+      /*if ( abs(startx-x) + abs(starty-y) > 0 )*/
+        glutPostRedisplay();
+    }
+    else if ( tr->manim == GL_TRUE && olds == idw )  
+      glutIdleFunc(NULL);
+  }
+
+  olds = idw;
+}
+
+void motion(int x,int y) {
+  pScene      sc;
+  pTransform  tr;
+  pPersp      p;
+  GLuint      gtime;
+  double      deltax,deltay;
+  float       coeff,pos[3],dx,dy,dz;
+  int         idw = currentScene();
+
+  /* default */
+  if ( picking )  return;
+  if ( ddebug ) fprintf(stdout,"motion\n");
+
+  if ( tracking == GL_FALSE )  return;
+  sc = cv.scene[idw];
+  p  = sc->persp;
+  if ( p->rubber == 1 )  return;
+
+  /* what is transformed ? */
+  if ( sc->cube->active & C_EDIT ) 
+    tr = sc->cube->cubetr;
+  else if ( sc->clip->active & C_EDIT ) 
+    tr = sc->clip->cliptr;
+  else
+    tr = sc->view;
+
+  if ( tr->mstate != GLUT_DOWN )  return;
+  if ( picking )  tr->angle = 0.0f;
+
+  gtime = glutGet(GLUT_ELAPSED_TIME);
+  if ( (animate || sc->type & S_FOLLOW) && gtime < lasttime+40 )  return;
+
+  if ( tr->mbutton == GLUT_LEFT_BUTTON ) {
+    /* calculate axis of rotation: cross product */
+    point2Vect(x,y,sc->par.xs,sc->par.ys,pos);
+    tr->axis[0] = tr->pos[1]*pos[2] - tr->pos[2]*pos[1];
+    tr->axis[1] = tr->pos[2]*pos[0] - tr->pos[0]*pos[2];
+    tr->axis[2] = tr->pos[0]*pos[1] - tr->pos[1]*pos[0];
+ 
+    /* calculate angle to rotate by */
+    if ( animate && saveimg )
+      tr->angle = 2.0f;
+    else {
+      dx = pos[0] - tr->pos[0];
+      dy = pos[1] - tr->pos[1];
+      dz = pos[2] - tr->pos[2];
+      tr->angle = 180.0*sqrt(dx*dx+dy*dy+dz*dz);
+    }
+
+    /* reset for next time */
+    tr->pos[0] = pos[0];
+    tr->pos[1] = pos[1];
+    tr->pos[2] = pos[2];
+    lasttime   = gtime;
+
+    if ( sc->cube->active & C_ON && sc->cube->active & C_EDIT )
+      sc->cube->active |= C_UPDATE;
+    else if ( sc->clip->active & C_ON && 
+	         (sc->clip->active & C_EDIT || sc->clip->active & C_FREEZE) )
+      sc->clip->active |= C_UPDATE;
+
+    glutPostRedisplay();
+  }
+
+  else if ( tr->mbutton == GLUT_MIDDLE_BUTTON ) {
+    coeff  = tr->manim == GL_TRUE ? 0.2 : 2.0;
+    deltax = coeff * (x-startx) / (float)sc->par.xs;
+    deltay = coeff * (starty-y) / (float)sc->par.ys;
+
+    if ( deltax != 0.0 )
+      tr->panx += -deltax * p->depth * tan(p->fovy/360.*M_PI);
+    if ( deltay != 0.0 )
+      tr->pany += -deltay * p->depth * tan(p->fovy/360.*M_PI);
+    tr->angle = 0.0;
+    startx = x;
+    starty = y;
+
+    lasttime = gtime;
+    if ( sc->cube->active & C_ON && sc->cube->active & C_EDIT )
+      sc->cube->active |= C_UPDATE;
+    else if ( sc->clip->active & C_ON && 
+        (sc->clip->active & C_EDIT || sc->clip->active & C_FREEZE) )
+      sc->clip->active |= C_UPDATE;
+
+    glutPostRedisplay();
+  }
+}
+
+void mouseCamera(int button,int state,int x,int y) {
+  /* default */
+  if ( ddebug ) printf("control mouse camera %d button %d\n",state,button);
+
+  cbutton = button;
+  if ( state == GLUT_DOWN ) {
+    ctracking = GL_TRUE;
+    startx = x;
+    starty = y;
+    curx   = x;
+    cury   = y;
+  }
+  else {
+    startx = x;
+    starty = y;
+    ctracking = GL_FALSE;
+  }
+}
+
+void motionCamera(int x,int y) {
+  pScene   sc;
+  pCamera  c;
+  double   dazim,delev,azim,elev;
+  float    cfelev,cfazim;
+
+  /* keep current pos */
+  curx = x;
+  cury = y;
+
+  if ( animate ) return;
+  sc = cv.scene[currentScene()];
+  c  = sc->camera;
+  azim  = Azimuth(c);
+  elev  = Elevation(c);
+   switch (cbutton) {
+    case GLUT_LEFT_BUTTON:
+      cfelev = 50.0;
+      cfazim = 50.0;
+      delev  = cfelev * (y-starty)/(float)sc->par.ys;
+      dazim  = cfazim * (x-startx)/(float)sc->par.xs;
+      startx = x;
+      starty = y;
+      elev  += delev;
+      azim  -= dazim;
+      break;
+    case GLUT_MIDDLE_BUTTON:
+      break;
+    case GLUT_BUTTON_3:
+      puts("button3");
+      break;
+    case GLUT_BUTTON_4:
+      puts("button4");
+      break;
+  }
+  updateCamera(sc,c,azim,elev);
+  reshapeScene(sc->par.xs,sc->par.ys);
+  glutPostRedisplay();
+}
+
+
+void animateCamera() {
+  pScene   sc;
+  pCamera  c;
+  double   dazim,delev,azim,elev;
+  float    cfelev,cfazim;
+
+  if ( !animate || !ctracking )  return;
+  sc = cv.scene[currentScene()];
+  c  = sc->camera;
+  azim  = Azimuth(c);
+  elev  = Elevation(c);
+
+  switch (cbutton) {
+    case GLUT_LEFT_BUTTON:
+      cfelev = 3.0;
+      cfazim = 3.0;
+      delev  = 2.0*(cury-starty)/(float)sc->par.ys;
+      dazim  = 2.0*(curx-startx)/(float)sc->par.xs;
+      if ( delev >= 0.0 ) delev *= delev;
+      else                delev = -delev*delev;
+      if ( dazim >= 0.0 ) dazim *= dazim;
+      else                dazim  = -dazim*dazim;
+      elev += cfelev * delev;
+      azim -= cfazim * dazim;
+      break;
+    
+    case GLUT_MIDDLE_BUTTON:
+      break;
+    case GLUT_BUTTON_3:
+      puts("button3");
+      break;
+    case GLUT_BUTTON_4:
+      puts("button4");
+      break;
+  }
+  updateCamera(sc,c,azim,elev);
+  reshapeScene(sc->par.xs,sc->par.ys);
+  glutPostRedisplay();
+}
diff --git a/src/medit/normal.c b/src/medit/normal.c
new file mode 100644
index 0000000..d4edabd
--- /dev/null
+++ b/src/medit/normal.c
@@ -0,0 +1,150 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+GLuint drawNormals(pMesh mesh,pScene sc) {
+  pTriangle   pt;
+  pQuad       pq;
+  pEdge       pr;
+  pPoint      ppt;
+  GLuint      dlist = 0;
+  double      nn[3];
+  float      *n,p[3],scal;
+  int         i,k,kk,ki,iadr;
+
+  /* default */
+  if ( !mesh->nvn )  return(0);
+  if ( ddebug ) printf("display normals, tangents\n");
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+  if ( sc->type & S_OPPOS )
+    scal = -0.025;
+  else
+    scal =  0.025;
+  scal *= sc->dmax;
+
+  glColor3f(0.8,0.2,0.6);
+  glLineWidth(2.0);
+  glBegin(GL_LINES);
+
+  /* normals at vertices */
+  if ( mesh->extra->iv && mesh->extra->nv ) {
+    for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+      ki  = mesh->extra->nv[k];
+      if ( ki > 0 ) {
+	iadr  = 3*(ki-1)+1;
+        n     = &mesh->extra->n[ iadr ];
+        p[0]  = ppt->c[0];
+        p[1]  = ppt->c[1];
+        p[2]  = ppt->c[2];
+        nn[0] = n[0];
+        nn[1] = n[1];
+        nn[2] = n[2];
+        drawVector3D(p,nn,scal);
+      }
+    }
+  }
+
+  /* normal at triangle vertices */
+  if ( mesh->extra->it && mesh->extra->nt ) {
+    for (k=1; k<=mesh->nt; k++) {
+      pt = &mesh->tria[k];
+      if ( !pt->v[0] )  continue;
+      for ( i=0; i<3; i++) {
+        kk = 3*(k-1)+i+1;
+        ki = mesh->extra->nt[kk];
+	if ( ki > 0 ) {
+	  ppt   = &mesh->point[pt->v[i]];
+	  iadr  = 3*(ki-1)+1;
+          n     = &mesh->extra->n[ iadr ];
+          p[0]  = ppt->c[0];
+          p[1]  = ppt->c[1];
+          p[2]  = ppt->c[2];
+          nn[0] = n[0];
+          nn[1] = n[1];
+          nn[2] = n[2];
+          drawVector3D(p,nn,scal);
+	}
+      }
+    }
+  }
+
+  /* normal at quad vertices */
+  if ( mesh->extra->iq && mesh->extra->nq ) {
+    for (k=1; k<=mesh->nq; k++) {
+      pq = &mesh->quad[k];
+      if ( !pq->v[0] )  continue;
+      for ( i=0; i<4; i++) {
+   	kk = 4*(k-1)+i+1;
+        ki = mesh->extra->nq[kk];
+	if ( ki > 0 ) {
+	  ppt   = &mesh->point[pq->v[i]];
+          iadr  = 3*(ki-1)+1;
+	  n     = &mesh->extra->n[ iadr ];
+          p[0]  = ppt->c[0];
+          p[1]  = ppt->c[1];
+          p[2]  = ppt->c[2];
+          nn[0] = n[0];
+          nn[1] = n[1];
+          nn[2] = n[2];
+          drawVector3D(p,nn,scal);
+	}
+      }
+    }
+  }
+
+
+  /* tangents at vertices */
+  if ( mesh->extra->jv && mesh->extra->tv ) {
+    glColor3f(0.2,0.6,0.8);
+    for (k=1; k<=mesh->np; k++) {
+      ppt = &mesh->point[k];
+      ki  = mesh->extra->tv[k];
+      if ( ki > 0 ) {
+	iadr  = 3*(ki-1)+1;
+	n     = &mesh->extra->t[ iadr ];
+        p[0]  = ppt->c[0];
+        p[1]  = ppt->c[1];
+        p[2]  = ppt->c[2];
+        nn[0] = n[0];
+        nn[1] = n[1];
+        nn[2] = n[2];
+        drawVector3D(p,nn,scal);
+      }
+    }
+  }
+
+  /* tangent at edge vertices */
+  if ( mesh->extra->je && mesh->extra->te ) {
+    for (k=1; k<=mesh->na; k++) {
+      pr = &mesh->edge[k];
+      if ( !pr->v[0] )  continue;
+      for ( i=0; i<2; i++) {
+        kk = 2*(k-1)+i+1;
+        ki = mesh->extra->te[kk];
+        if ( ki > 0 ) {
+	       ppt   = &mesh->point[pr->v[i]];
+          iadr  = 3*(ki-1)+1;
+          n     = &mesh->extra->t[ iadr ];
+          p[0]  = ppt->c[0];
+          p[1]  = ppt->c[1];
+          p[2]  = ppt->c[2];
+          nn[0] = n[0];
+          nn[1] = n[1];
+          nn[2] = n[2];
+          drawVector3D(p,nn,scal);
+        }
+      }
+    }
+  }
+
+  glEnd();
+  glLineWidth(1.0);
+  glEndList();
+  return(dlist);
+}
diff --git a/src/medit/param.c b/src/medit/param.c
new file mode 100644
index 0000000..96fb330
--- /dev/null
+++ b/src/medit/param.c
@@ -0,0 +1,66 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#ifndef  ON
+#define  ON     1
+#define  OFF    0
+#endif
+
+extern void ortho2D(pScene ,ubyte );
+
+/* globals */
+typedef struct sparval {
+  int   arg;
+} Parval;
+typedef Parval * pParval;
+
+
+static void parMotion(int x,int y) {
+  pScene    sc;
+
+  sc = cv.scene[currentScene()];
+  glEnable(GL_COLOR_LOGIC_OP);
+  glLogicOp(GL_XOR);
+  
+  glColor3ub(255,255,0);
+  setFont("helvetica",10);
+  drwstr(10,sc->par.ys-120,"Vector length");
+  glColor3ub(0,255,128);
+  drwstr(150,sc->par.ys-120,"%g",10.1);
+  glFlush();
+  glDisable(GL_COLOR_LOGIC_OP);
+}
+
+static void parMouse(int button,int state,int x,int y) {
+  pScene   sc;
+  if ( button != GLUT_LEFT_BUTTON )  return;
+  sc = cv.scene[currentScene()];
+
+  if ( state == GLUT_DOWN ) {
+    glColor3ub(0,255,128);
+    glDrawBuffer(GL_FRONT);
+    ortho2D(sc,ON);
+    glutMotionFunc(parMotion);
+  }
+  else {
+    glDrawBuffer(GL_BACK);
+    ortho2D(sc,OFF);
+    glutMotionFunc(parMotion);
+  }
+}
+
+
+
+void parEdit(pScene sc) {
+  glutMouseFunc(parMouse);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/parsar.c b/src/medit/parsar.c
new file mode 100644
index 0000000..7e07312
--- /dev/null
+++ b/src/medit/parsar.c
@@ -0,0 +1,162 @@
+/*
+ *  parse arguments from command line
+ *
+ *  Written by Pascal J. Frey, 1998.
+ *  email: Pascal.Frey at inria.fr
+*/
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+short schw,schh;
+extern ubyte option,infogl,fullscreen,dosurf,stereoMode;
+
+/********************/
+/*  rajout popen    */
+extern ubyte dpopen;
+extern ubyte dpopenbin;
+extern ubyte dpopensol;
+
+void usage() {
+  fprintf(stdout,"Usage: medit [options] [f1 .. fn]\n");
+  fprintf(stdout,"\n** Generic options :\n");
+  fprintf(stdout,"-d \t Debug mode (lot of info)\n");
+  fprintf(stdout,"-fs\t Fullscreen mode\n"); 
+  fprintf(stdout,"-h \t Print this message\n");
+  fprintf(stdout,"-i \t Print info on OpenGL configuration\n");
+  fprintf(stdout,"-l \t Process very large files\n");
+  fprintf(stdout,"-s \t Do no build surface\n");
+  fprintf(stdout,"-v \t Turn off quiet mode\n");
+  fprintf(stdout,"f1..fn\t Input data file(s)\n");
+  fprintf(stdout,"\n** Graphic options\n");
+  fprintf(stdout,"-a start stop\t Animation sequence\n");
+  fprintf(stdout,"-m  Morphing\n");
+  fprintf(stdout,"-xv width height\t Visual Schnauzer\n");
+  fprintf(stdout,"-stereo\t Stereo mode\n");     
+  fprintf(stdout,"\n");
+  exit(1);
+}
+
+
+int parsar(int argc,char *argv[]) {
+  pMesh    mesh;
+  int      i;
+  int      k;
+  /* default*/
+  cv.nbm = cv.nbs = 0;
+  i = 1;
+  infogl = FALSE;
+  dosurf = 1;
+  stereoMode = MONO;
+  while (i < argc) {
+    if ( !strcmp(argv[i],"-h") || !strcmp(argv[i],"-help") )
+      usage();
+    else if ( !strcmp(argv[i],"-d") || !strcmp(argv[i],"-debug") )
+      ddebug = TRUE;
+    // Rajout de l option popen
+    else if ( !strcmp(argv[i],"-popen") )
+      {
+	//printf("valeur de i=%i \n",i);
+	dpopen = TRUE;
+	
+	if( !strcmp(argv[i+1],"-filebin") ){
+	  dpopenbin = TRUE;
+	  i=i+1;
+	}
+
+	if( !strcmp(argv[i+1],"-addsol") ){
+	  dpopensol = TRUE;
+	  i=i+1; 
+	}
+	
+	if(dpopensol == TRUE && dpopenbin==TRUE){
+	  printf("medit with binary version of popen : mesh(es) and solution(s) \n");
+	}
+	else if(dpopensol == FALSE && dpopenbin==TRUE){
+	  printf("medit with binary version of popen : mesh(es)  \n");
+	}
+	else if(dpopensol == TRUE && dpopenbin==FALSE){
+	  printf("medit with popen : mesh(es) and solution(s) \n");
+	}
+	else{
+	  printf("medit with popen : mesh(es) \n");
+	}
+
+	if(i+1 != argc)
+	  {
+	    //printf("valeur de i=%i \n",i);
+	    cv.nbm = atoi(argv[i+1]);
+	    //printf("number of mesh= %i\n",cv.nbm);
+	    i++;
+	    if( cv.nbm==0) return(0);
+	  }
+	for( k=0; k<cv.nbm; k++){
+	  //printf("valeur de i=%i \n",i);
+	  cv.mesh[k] = (pMesh)M_calloc(1,sizeof(Mesh),"parsar.mesh");
+	  if ( !cv.mesh[k] )  return(0);
+	  mesh = cv.mesh[k];
+	  strcpy(mesh->name,argv[i+1]);
+	  printf("mesh_name= %s\n",mesh->name);
+	  i++;
+	}
+	//assert(i==argc);
+      }
+
+    // Fin Rajout de popen
+    else if ( !strcmp(argv[i],"-i") )
+      infogl = TRUE;
+    else if ( !strcmp(argv[i],"-fs") )
+      fullscreen = TRUE;
+    else if ( !strcmp(argv[i],"-l") )
+      option = VERYBIG;
+    else if ( !strcmp(argv[i],"-m") )
+      option = MORPHING;
+    else if ( !strcmp(argv[i],"-iso") )
+      option = ISOSURF;
+    else if ( !strcmp(argv[i],"-stereo") )
+      stereoMode = LEFT+RIGHT;
+    else if ( !strcmp(argv[i],"-s") )
+      dosurf = 0;
+    else if ( !strcmp(argv[i],"-v") )
+      quiet = 0;
+    else if ( !strcmp(argv[i],"-xv") ) {
+      if ( ++i < argc && isdigit(argv[i][0]) )
+	schw = atoi(argv[i]);
+      else
+        usage();
+      if ( ++i < argc && isdigit(argv[i][0]) )
+	schh = atoi(argv[i]);
+      else
+        usage();
+      option = SCHNAUZER;
+    }
+    else if ( !strcmp(argv[i],"-a") ) {
+      option = SEQUENCE;
+      if ( ++i < argc && isdigit(argv[i][0]) )
+	    animdep = atoi(argv[i]);
+      if ( ++i < argc && isdigit(argv[i][0]) )
+	    animfin = atoi(argv[i]);
+    }
+    else if ( !strcmp(argv[i],"-p") ) {
+      option = SEQUENCE + PARTICLE;
+      if ( ++i < argc && isdigit(argv[i][0]) )
+	animdep = atoi(argv[i]);
+      if ( ++i < argc && isdigit(argv[i][0]) )
+	animfin = atoi(argv[i]);
+    }
+    else {
+      if ( !cv.mesh[cv.nbm] ) {
+        cv.mesh[cv.nbm] = (pMesh)M_calloc(1,sizeof(Mesh),"parsar.mesh");
+        if ( !cv.mesh[cv.nbm] )  return(0);
+      }
+      mesh = cv.mesh[cv.nbm];
+      /*mesh->name = argv[i];*/
+	  strcpy(mesh->name,argv[i]);
+      if ( ddebug )  printf("parsar: mesh[%d] %s\n",cv.nbm,mesh->name);
+      if ( ++cv.nbm == MAX_MESH )  return(1);
+    }
+    i++;
+  }
+  
+  return(1);
+}
diff --git a/src/medit/parsop.c b/src/medit/parsop.c
new file mode 100644
index 0000000..a3ed7d1
--- /dev/null
+++ b/src/medit/parsop.c
@@ -0,0 +1,358 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+extern ubyte      stereoMode;
+
+
+int saveMeditFile(char *file,pScene sc) {
+  FILE      *out;
+  pMaterial  pm;
+  time_t     timeptr;
+  int        i,k,m;
+  char      *ptr,data[128];
+
+  strcpy(data,file);
+  ptr = (char *)strstr(data,".mesh");
+  if ( ptr )  *ptr = '\0';
+  if ( !strstr(data,".medit") )
+    strcat(data,".medit");
+
+  fprintf(stdout,"  Writing %s\n",data);
+  out = fopen(data,"w");
+  if ( !out ) {
+    fprintf(stdout,"  ## Unnable to write file\n");
+    return(0);
+  }
+
+  /* create standard parameter file */
+  fprintf(out,"#  File created with Medit %s\n",ME_VER);
+  fprintf(out,"#  Release %s\n",ME_REL);
+  time(&timeptr);
+  fprintf(out,"# Created: %s",ctime(&timeptr));
+
+  fprintf(out,"\n#  Assign background color\n");
+  fprintf(out,"BackgroundColor\n%f %f %f\n",
+	  sc->par.back[0],sc->par.back[1],sc->par.back[2]);
+  if ( sc->par.linc ) 
+    fprintf(out,"LineColor\n%f %f %f\n",
+	    sc->par.line[0],sc->par.line[1],sc->par.line[2]);
+
+  if ( sc->mode == HIDDEN )
+    fprintf(out,"\nRenderMode\nhidden\n");
+  else if ( sc->mode == FILL )
+    fprintf(out,"\nRenderMode\nfill\n");
+  else if ( sc->mode == S_FILL+S_COLOR+S_MATERIAL )
+    fprintf(out,"\nRenderMode\ncolorshading\n");
+  else if ( sc->mode == SHADED )
+    fprintf(out,"\nRenderMode\nshading\n");
+  else if ( sc->mode == S_FILL+S_BDRY+S_COLOR+S_MATERIAL )
+    fprintf(out,"\nRenderMode\ncolorshadingline\n");
+
+  fprintf(out,"\n#  Window Size\n");
+  fprintf(out,"WindowSize\n%d %d\n",sc->par.xs,sc->par.ys);
+  if ( sc->par.sunp ) {
+    fprintf(out,"\n#  Source Light\n");
+    fprintf(out,"SunPosition\n%f %f %f\n",
+            sc->par.sunpos[0]/(2.0*sc->dmax),
+            sc->par.sunpos[1]/(2.0*sc->dmax),
+            sc->par.sunpos[2]/(2.0*sc->dmax));
+  }
+  if ( sc->iso.palette ) {
+    fprintf(out,"# Color palette\n"); 
+    fprintf(out,"Palette\n");
+    for (k=0; k<MAXISO; k++)
+      fprintf(out,"%f ",sc->iso.val[k]);
+    fprintf(out,"\n");
+  }
+  if ( sc->par.nbmat ) {
+    m = 0;
+    for (k=0; k<sc->par.nbmat; k++) {
+      pm = &sc->material[k];
+      for (i=LTria; i<=LHexa; i++)
+        if ( pm->depmat[i] && !pm->flag )  m++;
+    }
+    fprintf(out,"\n# Subdomains colors\n");
+    fprintf(out,"NbMaterials\n%d\n",m);
+    for (k=0; k<sc->par.nbmat; k++) {
+      pm = &sc->material[k];
+      m = 0;
+      for (i=LTria; i<=LHexa; i++)
+        if ( pm->depmat[i] && !pm->flag )  break;
+      if ( i > LHexa )  continue;
+      fprintf(out,"# Material %s %d\n",pm->name,pm->ref);
+      fprintf(out,"Material %s %d\n",pm->name,pm->ref);
+      fprintf(out,"%.2f %.2f %.2f %.2f\n",
+                  pm->amb[0],pm->amb[1],pm->amb[2],pm->amb[3]);
+      fprintf(out,"%.2f %.2f %.2f %.2f\n",
+                  pm->dif[0],pm->dif[1],pm->dif[2],pm->dif[3]);
+      fprintf(out,"%.2f %.2f %.2f %.2f\n",
+                  pm->spe[0],pm->spe[1],pm->spe[2],pm->spe[3]);
+      fprintf(out,"%.2f %.2f %.2f %.2f\n",
+                  pm->emi[0],pm->emi[1],pm->emi[2],pm->emi[3]);
+      fprintf(out,"%.2f\n",pm->shininess);
+    }
+  }
+
+  if ( stereoMode != MONO )
+    fprintf(out,"EyeSep\n%f",sc->par.eyesep);
+
+  fclose(out);
+  return(1);
+}
+
+/* setup default values */
+void iniopt(pScene sc,pMesh mesh) {
+  GLfloat  sunpos[4]   = { 0.0, 0.0, 1.0, 1.0};
+  int      k;
+
+  sc->par.back[0] = sc->par.back[1] = sc->par.back[2] = 0.0;
+  sc->par.back[3] = 1.0;
+  sc->par.line[0] = sc->par.line[1] = sc->par.line[2] = 1.0;
+  sc->par.line[3] = 1.0;
+  sc->par.edge[0] = 1.0;
+  sc->par.edge[1] = 0.7;
+  sc->par.edge[2] = 0.1;
+  sc->par.edge[3] = 1.0;
+
+  memcpy(sc->par.sunpos,sunpos,4*sizeof(GLfloat));
+  sc->par.nbmat = -1;
+  sc->par.sunp  =  0;
+  sc->par.linc  =  0;
+  sc->par.linewidth = mesh->dim==3 ? 3 : 2;
+  sc->par.pointsize = 3.0;
+
+  for (k=0; k<MAXISO; k++) {
+    sc->iso.val[k] = 0.0;
+    sc->iso.col[k] = 0.0;
+  }
+  sc->iso.palette = 0;
+
+  /* postscript */
+  sc->par.dpi = 300.;
+  sc->par.cm  = 10.;
+  sc->par.coeff = 0.0;
+  
+  /* streamlines */
+  sc->par.maxtime = FLT_MAX;
+  sc->par.dt      = FLT_MAX;
+  sc->par.nbpart  = 1;
+
+  /* clip plane */
+  sc->par.clip[0] = 0.0;
+  sc->par.clip[1] = 0.0;
+  sc->par.clip[2] = 0.0;
+
+  sc->par.clip[3] = -1.0;
+  sc->par.clip[4] =  0.0;
+  sc->par.clip[5] =  0.0;
+  
+  sc->par.eyesep  = -1.0;
+}
+
+
+/* parse the program options */
+int parsop(pScene sc,pMesh mesh) {
+  FILE      *in;
+  pMaterial  pm;
+  double     dd;
+  float      r,g,b,ca,cb,cc,na,nb,nc;
+  int        k,i,m,n,xs,ys,ret,ref,nbmat;
+  char      *ptr,ub,data[128],key[256],buf[256],pscol[32];
+  
+  /* check if user-specified parameters */
+  iniopt(sc,mesh);
+
+  strcpy(data,mesh->name);
+  ptr = (char *)strstr(data,".mesh");
+  if ( ptr )  *ptr = '\0';
+  in = 0;
+  if ( !strstr(data,".medit") ) {
+    strcat(data,".medit");
+    in = fopen(data,"r"); 
+  }
+  if ( !in ) {
+    sprintf(data,"%s",DEFAULT_FILE);
+    in = fopen(data,"r");
+    if ( !in ) {
+      fprintf(stdout,"   Loading default options\n");
+      sc->par.nbmat = MAX_MATERIAL;
+      matInit(sc);
+      return(1);
+    }
+  }
+  if ( !quiet )  fprintf(stdout,"   Reading %s\n",data);
+  
+  m = n = 0;
+  while ( !feof(in) ) {
+    fscanf(in,"%s",key);
+    if ( feof(in) )  break;
+    for (i=0; i<strlen(key); i++) key[i] = tolower(key[i]);
+
+    if ( key[0] == '#' ) {
+      fgets(key,255,in);
+    }
+    else if ( !strcmp(key,"backgroundcolor") ) {
+      fscanf(in,"%f %f %f",&r,&g,&b);
+      sc->par.back[0] = r;
+      sc->par.back[1] = g;
+      sc->par.back[2] = b;
+      sc->par.back[3] = 1.0f;
+    }
+    else if ( !strcmp(key,"boundingbox") ) {
+      fscanf(in,"%f %f %f %f %f %f",&ca,&cb,&cc,&na,&nb,&nc);
+      mesh->xmin = ca;
+      mesh->ymin = cb;
+      mesh->zmin = cc;
+      mesh->xmax = na;
+      mesh->ymax = nb;
+      mesh->zmax = nc;
+    }
+    else if ( !strcmp(key,"clipplane") ) {
+      fscanf(in,"%f %f %f %f %f %f",&ca,&cb,&cc,&na,&nb,&nc);
+      sc->par.clip[0] = ca - mesh->xtra;
+      sc->par.clip[1] = cb - mesh->ytra;
+      sc->par.clip[2] = cc - mesh->ztra;
+      dd = sqrt(na*na + nb*nb + nc*nc);
+      if ( dd > EPS ) {
+        sc->par.clip[3] = na / dd;
+        sc->par.clip[4] = nb / dd;
+        sc->par.clip[5] = nc / dd;
+      }
+    }
+    else if ( !strcmp(key,"linecolor") ) {
+      fscanf(in,"%f %f %f",&r,&g,&b);
+      sc->par.line[0] = r;
+      sc->par.line[1] = g;
+      sc->par.line[2] = b;
+      sc->par.linc = 1;
+    }
+    else if ( !strcmp(key,"linewidth") ) {
+      fscanf(in,"%f",&r);
+      sc->par.linewidth = max(1.0,min(10.0,r));
+      sc->par.linc = 1;
+    }
+    else if ( !strcmp(key,"pointsize") ) {
+      fscanf(in,"%f",&r);
+      sc->par.pointsize = max(1.0,min(10.0,r));
+      sc->par.linc = 1;
+    }
+    else if ( !strcmp(key,"edgecolor") ) {
+      fscanf(in,"%f %f %f",&r,&g,&b);
+      sc->par.edge[0] = r;  sc->par.edge[1] = g;  sc->par.edge[2] = b;
+      sc->par.linc = 1;
+    }
+    else if ( !strcmp(key,"sunposition") ) {
+      fscanf(in,"%f %f %f",&r,&g,&b);
+      sc->dmax = mesh->xmax - mesh->xmin;
+      sc->dmax = max(sc->dmax,mesh->ymax - mesh->ymin);
+      sc->dmax = max(sc->dmax,mesh->zmax - mesh->zmin);
+      sc->dmax = fabs(sc->dmax);
+      sc->par.sunpos[0] = 2.0*sc->dmax*r;  
+      sc->par.sunpos[1] = 2.0*sc->dmax*g;
+      sc->par.sunpos[2] = 2.0*sc->dmax*b;
+      sc->par.sunp = 1;
+    }
+    else if ( !strcmp(key,"windowsize") ) {
+      fscanf(in,"%d %d",&xs,&ys);
+      sc->par.xs = (short)xs;  sc->par.ys = (short)ys;
+    }
+    else if ( !strcmp(key,"rendermode") ) {
+      fscanf(in,"%s",buf);
+      for (i=0; i<strlen(buf); i++) buf[i] = tolower(buf[i]);
+      if ( strstr(buf,"hidden") )
+        sc->mode = HIDDEN;
+      else if ( strstr(buf,"fill") )
+        sc->mode = FILL;
+      else if ( strstr(buf,"colorshadingline") )
+        sc->mode = SHADED + S_MATERIAL;
+      else if ( strstr(buf,"colorshading") )
+        sc->mode = S_FILL + S_COLOR + S_MATERIAL;
+      else if ( strstr(buf,"shading") )
+        sc->mode = SHADED; 
+    }
+    else if ( strstr(key,"palette") ) {
+      sc->iso.palette = 1;
+      if ( !strcmp(key,"palettet") ) 
+        sc->iso.palette = 1;
+      else if ( !strcmp(key,"paletteb") )
+        sc->iso.palette = 2;
+      else if ( !strcmp(key,"palettel") )
+        sc->iso.palette = 3;
+      else if ( !strcmp(key,"paletter") )
+        sc->iso.palette = 4;
+
+      for (k=0; k<MAXISO; k++)
+        ret = fscanf(in,"%f",&sc->iso.val[k]);
+      if ( sc->iso.val[MAXISO-1] < sc->iso.val[0] ) sc->iso.palette = 0;
+    }
+    else if ( !strcmp(key,"postscript") ) {
+      fscanf(in,"%f %f %s %s",&sc->par.cm,&sc->par.dpi,
+                              buf,pscol);
+      strncpy(sc->par.pscolor,pscol,10);
+      sc->par.coeff = atof(buf);
+      if ( sc->par.coeff < 0.0f ) sc->par.coeff = 0.0f;
+      if ( sc->par.coeff > 1.0f ) sc->par.coeff = 1.0f;
+    }
+    else if ( !strcmp(key,"time") ) {
+      ret = fscanf(in,"%f %f %f",&sc->par.maxtime,&sc->par.pertime,&sc->par.dt);
+      if ( !EatSpace(in) ) {
+        fscanf(in,"%c",&ub);
+        sc->par.nbpart = max(atoi(&ub),1);
+      }
+    }
+    else if ( !strcmp(key,"nbmaterial") ) {
+      fscanf(in,"%d",&nbmat);
+      sc->par.nbmat = max(2,nbmat);
+      matInit(sc);
+    }
+    else if ( !strcmp(key,"material") ) {
+      if ( sc->par.nbmat == -1 ) {
+        sc->par.nbmat = MAX_MATERIAL;
+        matInit(sc);
+      }
+      fgets(buf,255,in);
+      if ( n > sc->par.nbmat ) continue;
+      ret = sscanf(buf,"%s %d",buf,&ref);
+      ptr = strstr(buf,"DEFAULT");
+      pm  = ptr ? &sc->material[DEFAULT_MAT] : &sc->material[++n];
+      strcpy(pm->name,buf);
+      if ( ret < 2 )  ref = 0;
+      pm->ref = ref ? ref : n;
+      fscanf(in,"%f %f %f %f",&pm->amb[0],&pm->amb[1],&pm->amb[2],&pm->amb[3]);
+      fscanf(in,"%f %f %f %f",&pm->dif[0],&pm->dif[1],&pm->dif[2],&pm->dif[3]);
+      fscanf(in,"%f %f %f %f",&pm->spe[0],&pm->spe[1],&pm->spe[2],&pm->spe[3]);
+      fscanf(in,"%f %f %f %f",&pm->emi[0],&pm->emi[1],&pm->emi[2],&pm->emi[3]);
+      fscanf(in,"%f",&pm->shininess);
+
+      if ( pm->amb[3] == 0.0 )  pm->amb[3] = 1.0;
+      if ( pm->dif[3] == 0.0 )  pm->dif[3] = 1.0;
+      if ( pm->spe[3] == 0.0 )  pm->spe[3] = 1.0;
+      if ( pm->emi[3] == 0.0 )  pm->emi[3] = 1.0;
+      pm->shininess = min(fabs(pm->shininess),128.0f);
+      pm->shininess = max(pm->shininess,3.0f);
+      ++m;
+    }
+    
+    /* stereo mode */
+    else if ( !strcmp(key,"eyesep") ) {
+      fscanf(in,"%f",&sc->par.eyesep);
+    }
+
+  }
+  fclose(in);
+
+  if ( sc->par.nbmat < 0 ) {
+   sc->par.nbmat = MAX_MATERIAL;
+   matInit(sc);
+  }
+  else if ( m == n )  sc->par.nbmat++;
+  if ( !sc->par.linc ) {
+    sc->par.line[0] = 1.0 - sc->par.back[0];
+    sc->par.line[1] = 1.0 - sc->par.back[1];
+    sc->par.line[2] = 1.0 - sc->par.back[2];
+  }
+
+  if ( ddebug ) fprintf(stdout,"    Materials %8d\n",sc->par.nbmat);
+  return(1);
+}
diff --git a/src/medit/particle.c b/src/medit/particle.c
new file mode 100644
index 0000000..9ac0252
--- /dev/null
+++ b/src/medit/particle.c
@@ -0,0 +1,382 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define MAX_PRT    10
+#define MAX_LST    1024
+#define MAX_CPT    5000
+#define HSIZ       0.03
+
+extern int     reftype,refitem;
+
+
+typedef struct spart {
+  double    cb[4];
+  float     pos[MAX_PRT+1][3],col[MAX_PRT+1][3],size,norm,ct,step;
+  int       nsdep,cur;
+  ubyte     flag;
+} Particle;
+typedef Particle *pParticle;
+
+Particle  *tp;
+
+
+void colorParticle(pScene sc,pParticle pp) {
+  double        rgb[3],norm,kc;
+  int           i;
+  static double hsv[3] = { 0.0, 1.0, 0.80 };
+
+  norm = pp->norm;
+  if ( norm < sc->iso.val[0] )
+    norm = sc->iso.val[0];  
+  else if ( norm > sc->iso.val[MAXISO-1] )
+    norm = sc->iso.val[MAXISO-1];
+  for (i=0; i<MAXISO-1; i++)
+    if ( norm < sc->iso.val[i] )  break;
+  kc = (norm-sc->iso.val[i-1]) / (sc->iso.val[i] - sc->iso.val[i-1]);
+  hsv[0] = sc->iso.col[i-1]*(1.0-kc)+sc->iso.col[i]*kc;
+
+  hsvrgb(hsv,rgb);
+  pp->col[pp->cur][0] = rgb[0];
+  pp->col[pp->cur][1] = rgb[1];
+  pp->col[pp->cur][2] = rgb[2];
+}
+
+
+void drawParticle(pScene sc,pParticle pp) {
+  float         radius;
+  int           i;
+
+  radius = 0.005*sc->dmax;
+
+  for (i=1; i<=sc->par.nbpart; i++) {
+    glPushMatrix();
+    glTranslatef(pp->pos[i][0],pp->pos[i][1],pp->pos[i][2]);
+    glColor3fv(pp->col[i]);
+    glutSolidSphere(radius,10,10);
+    glPopMatrix();
+  }
+}
+
+
+void computeTetraParticle(pScene sc,pMesh mesh,int k) {
+  pTetra       pt;
+  pStream      st;
+  pParticle    pp;
+  double       dd,cb[4],v[4];
+  float        ux,uy,uz,pos[3],ldt;
+  int          cur,nsfin,nsold,nbp;
+
+  st   = sc->stream;
+  pp   = &tp[k];
+  if ( pp->ct > sc->par.pertime )  return;
+
+  ldt   = 0.0;
+  nbp   = 0;
+  nsold = pp->nsdep;
+
+  pos[0] = pp->pos[pp->cur][0];
+  pos[1] = pp->pos[pp->cur][1];
+  pos[2] = pp->pos[pp->cur][2];
+
+  do {
+    ux = pos[0];
+    uy = pos[1];
+    uz = pos[2];
+    if ( st->typtrack == 1 || !nxtPoint3D(mesh,pp->nsdep,pos,pp->step,v) ) {
+      pos[0] += pp->step*v[0];
+      pos[1] += pp->step*v[1];
+      pos[2] += pp->step*v[2];
+    }
+    if ( pos[0]<st->xmin || pos[0]>st->xmax ||
+         pos[1]<st->ymin || pos[1]>st->ymax ||
+	     pos[2]<st->zmin || pos[2]>st->zmax ) {
+      pp->flag = 0;
+      break;
+    }
+    ux -= pos[0];
+    uy -= pos[1];
+    uz -= pos[2];
+
+    dd      = sqrt(ux*ux + uy*uy + uz*uz) / pp->norm;
+    ldt    += dd;
+    pp->ct += dd;
+
+    if ( pp->ct >= sc->par.pertime ) {
+      pp->flag = 0;
+      sc->par.cumpertime = sc->par.pertime+1.e-06;
+      break; /*return;*/
+    }
+    else if ( ldt >= sc->par.dt  ) {
+      pp->cur = 1 + (pp->cur % sc->par.nbpart);
+      pp->pos[pp->cur][0] = pos[0];
+      pp->pos[pp->cur][1] = pos[1];
+      pp->pos[pp->cur][2] = pos[2];
+      colorParticle(sc,pp);
+      break; /*return;*/
+    }
+ 
+    /* find tet containing p */
+    nsfin = locateTetra(mesh,pp->nsdep,++mesh->mark,pos,cb);
+    if ( !nsfin ) {
+      pp->flag = 0;
+      break; /*return;*/
+    }
+    pp->nsdep = nsfin;
+    pt = &mesh->tetra[pp->nsdep];
+    if ( pt->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( pp->nsdep != nsold ) {
+      pp->size = sizeTetra(mesh,pp->nsdep);
+      nsold    = pp->nsdep;
+    }
+
+    /* vector field interpolation */
+    pp->norm = field3DInterp(mesh,pp->nsdep,pp->cb,v);
+    pp->step = HSIZ*min(pp->size,pp->norm);
+    if ( sc->par.maxtime < FLT_MAX )
+      pp->step = min(0.05*sc->par.dt,pp->step);
+    if ( pp->step == 0.0 ) {
+      pp->flag = 0;
+      return;
+    }
+    nbp++;
+  }
+  while ( ldt <= sc->par.dt );
+
+  cur = (pp->cur % MAX_PRT) + 1;
+  pp->pos[cur][0] = pp->pos[pp->cur][0];
+  pp->pos[cur][1] = pp->pos[pp->cur][1];
+  pp->pos[cur][2] = pp->pos[pp->cur][2];
+  pp->cur = cur;
+  colorParticle(sc,pp);
+}
+
+
+int displayParticle(pScene sc,pMesh mesh) {
+  pParticle   pp;
+  pStream     st;
+  int         k;
+
+  st = sc->stream;
+  if ( sc->par.advtim )
+    for (k=1; k<=st->nbstl; k++)
+      computeTetraParticle(sc,mesh,k);
+
+  /* redraw particles */
+  for (k=1; k<=st->nbstl; k++) {
+    pp = &tp[k];
+    if ( pp->flag )
+      drawParticle(sc,pp);
+  }
+
+  return(1);
+}
+
+
+int createParticle(pScene sc,pMesh mesh) {
+  pParticle   pp;
+  pStream     st;
+  pMaterial   pm;
+  pTetra      pt1;
+  pTriangle   pt;
+  pPoint      ppt;
+  double      v[4],cx,cy,cz;
+  int         i,j,k,l,nmat,nbp,base;
+
+  if ( ddebug )  printf("create particles\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  if ( sc->stream ) { 
+    st = sc->stream;
+    if ( st->listp )  free(st->listp);
+    free(sc->stream);
+  }
+  sc->stream     = createStream(sc,mesh);
+  sc->par.cumtim = 0.0;
+  sc->par.advtim = 0;
+  assert(sc->stream);
+  st = sc->stream;
+
+  fprintf(stdout," Creating particles :");  fflush(stdout);
+  st->nbstl = 0;
+
+  base = ++mesh->mark;
+  pt   = &mesh->tria[refitem];
+  nmat = matRef(sc,pt->ref);
+  pm   = &sc->material[nmat];
+  k    = pm->depmat[LTria];
+  if ( !k || pm->flag )  return(0);
+
+  /* point positions */
+  for (i=1; i<=mesh->np; i++) {
+    ppt = &mesh->point[i];
+    ppt->mark = base;
+  }
+  if ( sc->par.nbpart >= MAX_PRT )
+    sc->par.nbpart = MAX_PRT;
+
+  ++base;
+  l   = 1;
+  nbp = 0;
+  while ( k != 0 && st->nbstl < MAX_LST-1 ) {
+    pt = &mesh->tria[k];
+    if ( pt->v[0] ) {
+      cx = cy = cz = 0.0;
+      for (i=0; i<3; i++) {
+        ppt = &mesh->point[pt->v[i]];
+        cx += 0.33 * ppt->c[0];
+        cy += 0.33 * ppt->c[1];
+        cz += 0.33 * ppt->c[2];
+        ppt->flag = 1;
+      }  
+      st->listp[l++] = cx;
+      st->listp[l++] = cy;
+      st->listp[l++] = cz;
+      ++st->nbstl;
+      if ( st->nbstl > MAX_LST-1 ) break;
+      k = pt->nxt;
+    }
+  }
+  fprintf(stdout,"%d\n",st->nbstl);
+  if ( !st->nbstl )  return(0);
+
+  /* init positions */
+  tp = calloc((st->nbstl+1),sizeof(Particle));
+  assert(tp);
+  for (k=1; k<=st->nbstl; k++)
+    tp[k].nsdep = mesh->ntet / 2;
+
+  for (k=1; k<=mesh->ntet; k++)
+    mesh->tetra[k].cpt = 0;
+
+  l = 1;
+  for (k=1; k<=st->nbstl; k++) {
+    pp = &tp[k];
+    pp->pos[1][0] = st->listp[l++];
+    pp->pos[1][1] = st->listp[l++];
+    pp->pos[1][2] = st->listp[l++];
+
+    tp[k].nsdep = locateTetra(mesh,pp->nsdep,++mesh->mark,pp->pos[1],pp->cb);
+
+    if ( !pp->nsdep ) {
+      for (j=1; j<=mesh->ntet; j++) {
+        pt1 = &mesh->tetra[j];
+        if ( pt1->mark != mesh->mark && inTetra(mesh,j,pp->pos[1],pp->cb) )
+          break;
+      }
+      if ( j > mesh->ntet )  return(0);
+      else
+        pp->nsdep = j;
+    }
+    pp->norm  = field3DInterp(mesh,tp[k].nsdep,tp[k].cb,v);
+    pp->size  = sizeTetra(mesh,tp[k].nsdep);
+    if ( pp->size == 0.0 )
+      pp->step = EPS*sc->dmax;
+    else
+      pp->step = HSIZ * min(pp->size,pp->norm);
+    pp->step = min(0.05*sc->par.dt,pp->step);
+    pp->flag =  1;
+    pp->cur  =  1;
+    colorParticle(sc,pp);
+
+    for (i=2; i<=sc->par.nbpart; i++) {
+      pp->pos[i][0] = pp->pos[1][0];
+      pp->pos[i][1] = pp->pos[1][1];
+      pp->pos[i][2] = pp->pos[1][2];
+    }
+  }
+
+  return(1);
+}
+
+
+int advectParticle(pScene sc,pMesh mesh) {
+  pParticle   pp;
+  pStream     st;
+  pTetra      pt1;
+  pPoint      ppt;
+  double      v[4];
+  int         i,j,k,l,base;
+
+  if ( ddebug )  printf("advect particles\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( !sc->stream )  return(0);
+  st = sc->stream;
+
+  if ( mesh->ntet && !hashTetra(mesh) ) return(0);
+
+  st->xmin = mesh->xmin - mesh->xtra;
+  st->ymin = mesh->ymin - mesh->ytra;
+  st->zmin = mesh->zmin - mesh->ztra;
+  st->xmax = mesh->xmax - mesh->xtra;
+  st->ymax = mesh->ymax - mesh->ytra;
+  st->zmax = mesh->zmax - mesh->ztra;
+
+  sc->par.cumpertime = 0.0;
+  sc->par.advtim     = 0;
+
+  /* init list */
+  sc->slist = (GLuint*)calloc(MAX_LST,sizeof(GLuint));
+  if ( !sc->slist )  return(0);
+
+  /* point positions */
+  base = ++mesh->mark;
+  for (i=1; i<=mesh->np; i++) {
+    ppt = &mesh->point[i];
+    ppt->mark = base;
+  }
+  for (k=1; k<=mesh->ntet; k++)
+    mesh->tetra[k].cpt = 0;
+
+  l = 1;
+  for (k=1; k<=st->nbstl; k++) {
+    pp = &tp[k];
+    pp->ct = 0.0;
+    st->listp[l++] = pp->pos[pp->cur][0];
+    st->listp[l++] = pp->pos[pp->cur][1];
+    st->listp[l++] = pp->pos[pp->cur][2];
+    pp->cur = 1;
+  }
+
+  ++base;
+  l = 1;
+  for (k=1; k<=st->nbstl; k++) {
+    pp = &tp[k];
+    pp->pos[1][0] = st->listp[l++];
+    pp->pos[1][1] = st->listp[l++];
+    pp->pos[1][2] = st->listp[l++];
+
+    tp[k].nsdep = locateTetra(mesh,pp->nsdep,++mesh->mark,pp->pos[1],pp->cb);
+    if ( !pp->nsdep ) {
+      for (j=1; j<=mesh->ntet; j++) {
+        pt1 = &mesh->tetra[j];
+        if ( pt1->mark != mesh->mark && inTetra(mesh,j,pp->pos[1],pp->cb) )
+          break;
+      }
+      if ( j > mesh->ntet )  continue;
+      else
+        pp->nsdep = j;
+    }
+    pp->norm  = field3DInterp(mesh,tp[k].nsdep,tp[k].cb,v);
+    pp->size  = sizeTetra(mesh,tp[k].nsdep);
+    if ( pp->size == 0.0 )
+      pp->step = EPS*sc->dmax;
+    else
+      pp->step = HSIZ * min(pp->size,pp->norm);
+    pp->step = min(0.05*sc->par.dt,pp->step);
+    pp->flag =  1;
+    pp->cur  =  1;
+    colorParticle(sc,pp);
+
+    for (i=2; i<=sc->par.nbpart; i++) {
+      pp->pos[i][0] = pp->pos[1][0];
+      pp->pos[i][1] = pp->pos[1][1];
+      pp->pos[i][2] = pp->pos[1][2];
+    }
+  }
+
+  return(1);
+}
+
diff --git a/src/medit/path.c b/src/medit/path.c
new file mode 100644
index 0000000..88e16b5
--- /dev/null
+++ b/src/medit/path.c
@@ -0,0 +1,188 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define MAX_PATH    1024
+#define IMG_PER_SEC   25
+
+/* add point to path */
+int pathAdd(pScene sc,int x,int y) {
+  GLdouble    modelmat[16],projmat[16];
+  GLdouble    ptx,pty,ptz;
+  GLint       viewport[4];
+  Trajet     *path;
+  pMesh       mesh;
+  pTransform  view;
+  float      *p,*p1,*a;
+  int         k;
+
+  if ( ddebug )  fprintf(stdout,"pathAdd");
+  path = &sc->path;
+  mesh = cv.mesh[sc->idmesh];
+  view = sc->view;
+  if ( path->np == MAX_PATH ) return(0); 
+
+  /* memory alloc */
+  if ( !path->np ) {
+    path->pt = (float*)calloc(mesh->dim*(MAX_PATH+1),sizeof(float));
+    if ( !path->pt ) {
+      fprintf(stderr,"   Not enough memory to store path.\n");
+      return(0);
+    }
+    path->tg = (float*)calloc(mesh->dim*(MAX_PATH+1),sizeof(float));
+    if ( !path->tg ) {
+      fprintf(stderr,"   Not enough memory to store tangents.\n");
+      return(0);
+    }
+  }
+  else if ( path->np > MAX_PATH-1 ) return(0);
+
+  /* get 3D point */
+  glGetDoublev(GL_PROJECTION_MATRIX,projmat);
+  glGetIntegerv(GL_VIEWPORT,viewport);
+  for (k=0; k<16; k++) modelmat[k] = view->matrix[k];
+  gluUnProject(x,y,-100,modelmat,projmat,viewport,&ptx,&pty,&ptz);
+
+  /* store point coords */
+  ++path->np;
+  p = &path->pt[mesh->dim*path->np];
+  p[0] = ptx;
+  p[1] = pty;
+  p[2] = ptz;
+
+  /* compute tangent at point-1 */
+  if ( path->np > 2 ) {
+    p1 = &path->pt[mesh->dim*(path->np-2)];
+    a  = &path->tg[mesh->dim*path->np];
+    a[0] = 0.5 * (p[0] - p1[0]);
+    a[1] = 0.5 * (p[1] - p1[1]);
+    a[2] = 0.5 * (p[2] - p1[2]);
+  }
+  
+  if ( ddebug ) printf(" Point %d: (%f %f %f) added\n",path->np,p[0],p[1],p[2]);
+  return(1);
+}
+
+/* build list of points */
+GLuint pathList(pScene sc) {
+  Trajet   path;
+  pMesh    mesh;
+  GLuint   dlist;
+  float   *p;
+  int      k;
+  static GLfloat green[3] = {0.2, 1.0, 0.2};
+  /*static GLfloat orang[3] = {1.0, 0.7, 0.1};*/
+
+  if ( ddebug )  fprintf(stdout,"pathList");
+  path = sc->path;
+  mesh = cv.mesh[sc->idmesh];
+
+  /* build display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* node positions */
+  glPointSize(5);
+  glColor3f(1.0,0.3,0.3);
+  glBegin(GL_POINTS);
+  for (k=1; k<=path.np; k++) {
+    p = &path.pt[mesh->dim*k];
+    glVertex3fv(p);
+  }
+  glEnd();
+
+  /* straight path */
+  glLineWidth(2.0);
+  glColor3fv(green);
+  glBegin(GL_LINE_STRIP);
+  for (k=1; k<=path.np; k++) {
+    p = &path.pt[mesh->dim*k];
+    glVertex3fv(p);
+  }
+  glEnd();
+  glLineWidth(1.0);
+
+  /* curvilinear path */
+  /*
+  glBegin(GL_LINE_STRIP);
+  glColor3fv(orang);
+  glEnd();
+  */
+
+  glEndList();
+  return(dlist);  
+}
+
+/* follow path */
+void pathFollow(pScene sc) {
+  Trajet  path;
+  int     nbp;
+
+  if ( !sc->path.np ) return;
+  if ( ddebug )  fprintf(stdout,"pathFollow %d\n",sc->path.np);
+  path = sc->path;
+  if ( sc->path.sec < 0 )
+    nbp = sc->path.np;
+  else
+    nbp = (sc->path.sec*IMG_PER_SEC);
+}
+
+int pathLoad(char *file,pScene sc) {
+  FILE      *in;
+  char      *ptr,data[256];
+
+  strcpy(data,file);
+  ptr = (char *)strstr(data,".mesh");
+  if ( ptr )  *ptr = '\0';
+  if ( !strstr(data,".path") )
+    strcat(data,".path");
+  in = fopen(data,"r");
+  if ( !in ) {
+    sscanf(data,"DEFAULT.path");
+    in = fopen(data,"r");
+    if ( !in )  return(0);
+  }
+  if ( !quiet )  fprintf(stdout,"  Loading %s\n",data);
+
+  return(1);
+}
+
+int pathSave(char *file,pScene sc) {
+  FILE      *out;
+  pMesh      mesh;
+  time_t     timeptr;
+  float     *p;
+  int        i,k;
+  char      *ptr,data[256];
+
+  strcpy(data,file);
+  ptr = (char *)strstr(data,".mesh");
+  if ( ptr )  *ptr = '\0';
+  if ( !strstr(data,".path") )
+    strcat(data,".path");
+
+  out = fopen(data,"w");
+  if ( !out ) {
+	fprintf(stdout,"  ## Unable to open file\n");;
+    return(0);
+  }
+  if ( !quiet )  fprintf(stdout,"  Writing %s\n",data);
+
+  /* create standard path file */
+  fprintf(out,"#  File created with Medit %s\n",ME_VER);
+  fprintf(out,"#  Release %s\n",ME_REL);
+  time(&timeptr);
+  fprintf(out,"# Created: %s",ctime(&timeptr));
+
+  mesh = cv.mesh[sc->idmesh];
+  fprintf(out,"NbPoints\n%d\n",sc->path.np);
+  for (k=1; k<=sc->path.np; k++) {
+    p = &sc->path.pt[mesh->dim*k];
+    for (i=0; i<mesh->dim; i++)
+      fprintf(out,"%f ",p[i]);
+    fprintf(out,"\n");
+  }
+  fclose(out); 
+  return(1);
+}
diff --git a/src/medit/persp.c b/src/medit/persp.c
new file mode 100644
index 0000000..1140c96
--- /dev/null
+++ b/src/medit/persp.c
@@ -0,0 +1,83 @@
+#include <math.h>
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+static float ident[16] = {
+  1.,0.,0.,0., 0.,1.,0.,0., 0.,0.,1.,0., 0.,0.,0.,1.};
+
+
+void setPersp(pScene sc,pPersp p,int pmode) {
+  float       tgalpha,deltax,deltay,alphax,alphay,alpha,beta;
+  float       rapx,rapy,Deltax,Deltay,yy;
+  
+  
+  /* defalut */  
+  Deltax = sc->par.xs;  
+  Deltay = sc->par.ys;
+  alphax = p->fovy / 2.0f;
+  alphay = p->fovy / 2.0f;
+
+  deltax = (p->rubix+p->rubfx-Deltax) / (float)Deltax;
+  deltay = (p->rubiy+p->rubfy-Deltay) / (float)Deltay;
+
+  alpha = atan(deltax * tan(alphax*DTOR));
+  beta  = atan(deltay * tan(alphay*DTOR));
+  yy  = cos(alpha)*cos(alpha)*sin(beta)*sin(beta);
+  yy /= yy + cos(beta)*cos(beta);
+  yy  = sqrt(yy);
+
+  p->gamma = asin(yy)*RTOD;
+  if ( deltay < 0. ) 
+    p->gamma = -p->gamma;
+  p->alpha = alpha*RTOD;
+
+  /* new fovy */
+  tgalpha = tan(p->fovy*DTOR);
+  rapx    = fabs(p->rubfx-p->rubix) / (float)sc->par.xs;
+  rapy    = fabs(p->rubfy-p->rubiy) / (float)sc->par.ys;
+  
+  if ( pmode == 1 )
+    p->fovy = atan(tgalpha * rapy)*RTOD;
+  else if ( pmode == 0 )
+    p->fovy = atan(tgalpha / rapy)*RTOD;
+    
+  p->rubix = p->rubfx = 0;
+  p->rubiy = p->rubfy = 0;
+}
+
+
+pPersp initPersp(pPersp p,float dmax) {
+  pPersp    pp;
+
+  if ( p ) {
+    p->fovy   = 35.0f;
+    p->rubber = 0;
+    p->rubix  = p->rubfx = 0;
+    p->rubiy  = p->rubfy = 0;
+    p->alpha  = p->gamma = 0.0f;
+    p->depth  = -2.0*dmax;
+    p->pmode  = PERSPECTIVE;
+    memcpy(p->matrix,ident,16*sizeof(float));
+    return(p);
+  }
+  else {
+    pp = (pPersp)M_calloc(1,sizeof(struct sperspective),"persp");
+	assert(pp);
+
+    pp->fovy   = 35.0f;
+    pp->rubber = 0;
+    pp->rubix  = pp->rubfx = 0;
+    pp->rubiy  = pp->rubfy = 0;
+    pp->alpha  = pp->gamma = 0.0f;
+    pp->depth  = -2.0*dmax;
+    pp->pmode  = PERSPECTIVE;
+    memcpy(pp->matrix,ident,16*sizeof(float));
+    return(pp);
+  }
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/picking.c b/src/medit/picking.c
new file mode 100644
index 0000000..c76e017
--- /dev/null
+++ b/src/medit/picking.c
@@ -0,0 +1,943 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+typedef struct color {
+  GLuint  rMask,gMask,bMask,aMask;
+  int     rShift,gShift,bShift;
+  int     rBits,gBits,bBits,aBits;
+} Color;
+
+
+int    refmat=-1,reftype=-1,refitem=0,numel=0,refval=0;
+
+static int ch[6][4] = { {0,1,2,3}, {4,5,6,7}, {0,1,5,4}, 
+			{1,2,6,5}, {2,3,7,6}, {0,3,7,4} };
+static int ct[4][3] = { {0,1,2}, {0,3,1}, {1,3,2}, {0,2,3} };
+extern int refpick;
+
+
+static void drawTria(pScene sc,pMesh mesh,int k) {
+  pMaterial    pm;
+  pTriangle    pt;
+  pPoint       p0,p1,p2;
+  double       ax,ay,az,bx,by,bz,dd;
+  float        shrink,cx,cy,cz,n[3];
+
+  /* default */
+  if ( ddebug ) printf("draw triangle %d\n",k);
+  if ( k < 1 || k > mesh->nt )  return;
+
+  pt = &mesh->tria[k];
+  if ( refpick > 0 )  pt->ref = refpick;
+  refmat = matRef(sc,pt->ref);
+  p0 = &mesh->point[pt->v[0]];
+  p1 = &mesh->point[pt->v[1]];
+  p2 = &mesh->point[pt->v[2]];
+  pm = &sc->material[refmat];
+  cx = (p0->c[0] + p1->c[0] + p2->c[0]) / 3.;
+  cy = (p0->c[1] + p1->c[1] + p2->c[1]) / 3.;
+  cz = (p0->c[2] + p1->c[2] + p2->c[2]) / 3.;
+  shrink = 0.95 * sc->shrink;
+
+  glBegin(GL_TRIANGLES);
+  glColor3f(1.0-pm->dif[0],1.0-pm->dif[1],1.0-pm->dif[2]);
+
+  /* compute normal */
+  ax = p1->c[0] - p0->c[0];
+  ay = p1->c[1] - p0->c[1];
+  az = p1->c[2] - p0->c[2];
+  bx = p2->c[0] - p0->c[0];
+  by = p2->c[1] - p0->c[1];
+  bz = p2->c[2] - p0->c[2];
+  n[0] = ay*bz - az*by;
+  n[1] = az*bx - ax*bz;
+  n[2] = ax*by - ay*bx;
+  dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+  if ( dd > 0.0f ) {
+    dd = 1.0f / sqrt(dd);
+    n[0] *= dd;
+    n[1] *= dd;
+    n[2] *= dd;
+  }
+  glNormal3fv(n);
+  glVertex3f(shrink*(p0->c[0]-cx)+cx,
+             shrink*(p0->c[1]-cy)+cy,
+             shrink*(p0->c[2]-cz)+cz);
+  glNormal3fv(n);
+  glVertex3f(shrink*(p1->c[0]-cx)+cx,
+             shrink*(p1->c[1]-cy)+cy,
+             shrink*(p1->c[2]-cz)+cz);
+  glNormal3fv(n);
+  glVertex3f(shrink*(p2->c[0]-cx)+cx,
+             shrink*(p2->c[1]-cy)+cy,
+             shrink*(p2->c[2]-cz)+cz);
+  glEnd();
+
+  glColor3f(1.0-sc->par.back[0],1.0-sc->par.back[1],1.0-sc->par.back[2]);
+  output3(p0->c[0],p0->c[1],p0->c[2],"%d",pt->v[0]);
+  output3(p1->c[0],p1->c[1],p1->c[2],"%d",pt->v[1]);
+  output3(p2->c[0],p2->c[1],p2->c[2],"%d",pt->v[2]);
+}
+
+static void drawQuad(pScene sc,pMesh mesh,int k) {
+  pMaterial  pm;
+  pQuad      pq;
+  pPoint     p0,p1,p2,p3;
+  double     ax,ay,az,bx,by,bz,dd;
+  float      shrink,cx,cy,cz,n[3];
+
+  /* default */
+  if ( ddebug ) printf("draw quad %d\n",k);
+  if ( k < 1 || k > mesh->nq )  return;
+  pq = &mesh->quad[k];
+  if ( refpick > 0 )  pq->ref = refpick;
+  refmat = matRef(sc,pq->ref);
+
+  p0 = &mesh->point[pq->v[0]];
+  p1 = &mesh->point[pq->v[1]];
+  p2 = &mesh->point[pq->v[2]];
+  p3 = &mesh->point[pq->v[3]];
+  pm = &sc->material[refmat];
+  cx = (p0->c[0] + p1->c[0] + p2->c[0] + p3->c[0]) / 4.;
+  cy = (p0->c[1] + p1->c[1] + p2->c[1] + p3->c[1]) / 4.;
+  cz = (p0->c[2] + p1->c[2] + p2->c[2] + p3->c[2]) / 4.;
+  shrink = 0.95 * sc->shrink;
+
+  glBegin(GL_QUADS);
+  glColor3f(1.0-pm->dif[0],1.0-pm->dif[1],1.0-pm->dif[2]);
+
+  /* compute normal */
+  ax = p1->c[0] - p0->c[0];
+  ay = p1->c[1] - p0->c[1];
+  az = p1->c[2] - p0->c[2];
+  bx = p2->c[0] - p0->c[0];
+  by = p2->c[1] - p0->c[1];
+  bz = p2->c[2] - p0->c[2];
+  n[0] = ay*bz - az*by;
+  n[1] = az*bx - ax*bz;
+  n[2] = ax*by - ay*bx;
+  dd = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+  if ( dd > 0.0f ) {
+    dd = 1.0f / sqrt(dd);
+    n[0] *= dd;
+    n[1] *= dd;
+    n[2] *= dd;
+  }
+  glNormal3fv(n);
+  glVertex3f(shrink*(p0->c[0]-cx)+cx,
+             shrink*(p0->c[1]-cy)+cy,
+             shrink*(p0->c[2]-cz)+cz);
+  glNormal3fv(n);
+  glVertex3f(shrink*(p1->c[0]-cx)+cx,
+             shrink*(p1->c[1]-cy)+cy,
+             shrink*(p1->c[2]-cz)+cz);
+  glNormal3fv(n);
+  glVertex3f(shrink*(p2->c[0]-cx)+cx,
+             shrink*(p2->c[1]-cy)+cy,
+             shrink*(p2->c[2]-cz)+cz);
+  glNormal3fv(n);
+  glVertex3f(shrink*(p3->c[0]-cx)+cx,
+             shrink*(p3->c[1]-cy)+cy,
+             shrink*(p3->c[2]-cz)+cz);
+  glEnd();
+
+  /* display vertex number */
+  glColor3f(1.0-sc->par.back[0],1.0-sc->par.back[1],1.0-sc->par.back[2]);
+  output3(p0->c[0],p0->c[1],p0->c[2],"%d",pq->v[0]);
+  output3(p1->c[0],p1->c[1],p1->c[2],"%d",pq->v[1]);
+  output3(p2->c[0],p2->c[1],p2->c[2],"%d",pq->v[2]);
+  output3(p3->c[0],p3->c[1],p3->c[2],"%d",pq->v[3]);
+}
+
+static void drawTets(pScene sc,pMesh mesh,int k) {
+  pMaterial  pm;
+  pTetra     pt;
+  pPoint     p0,p1,p2,p3;
+  float      ax,ay,az,bx,by,bz,d,n[3];
+  float      shrink,cx,cy,cz;
+  int        l;
+
+  /* default */
+  if ( ddebug ) printf("draw tetra %d\n",k);
+  if ( k < 1 || k > mesh->ntet )  return;
+  pt = &mesh->tetra[k];
+  if ( refpick > 0 )  pt->ref = refpick;
+  refmat = matRef(sc,pt->ref);
+
+  pm = &sc->material[refmat];
+  shrink = 0.95*sc->shrink;
+
+  glBegin(GL_TRIANGLES);
+  glColor3f(1.0-pm->dif[0],1.0-pm->dif[1],1.0-pm->dif[2]);
+  for (l=0; l<4; l++) {
+    p0 = &mesh->point[pt->v[ct[l][0]]];
+    p1 = &mesh->point[pt->v[ct[l][1]]];
+    p2 = &mesh->point[pt->v[ct[l][2]]];
+    cx = (p0->c[0] + p1->c[0] + p2->c[0]) / 3.;
+    cy = (p0->c[1] + p1->c[1] + p2->c[1]) / 3.;
+    cz = (p0->c[2] + p1->c[2] + p2->c[2]) / 3.;
+
+    /* compute face normal */
+    ax = p1->c[0] - p0->c[0]; ay = p1->c[1] - p0->c[1]; az = p1->c[2] - p0->c[2];
+    bx = p2->c[0] - p0->c[0]; by = p2->c[1] - p0->c[1]; bz = p2->c[2] - p0->c[2];
+    n[0] = ay*bz - az*by;
+    n[1] = az*bx - ax*bz;
+    n[2] = ax*by - ay*bx;
+    d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+    if ( d > 0.0f ) {
+      d = 1.0 / sqrt(d);
+      n[0] *= d;
+      n[1] *= d;
+      n[2] *= d;
+    }
+    glNormal3fv(n);
+    glVertex3f(shrink*(p0->c[0]-cx)+cx,
+               shrink*(p0->c[1]-cy)+cy,
+               shrink*(p0->c[2]-cz)+cz);
+    glNormal3fv(n);
+    glVertex3f(shrink*(p1->c[0]-cx)+cx,
+               shrink*(p1->c[1]-cy)+cy,
+               shrink*(p1->c[2]-cz)+cz);
+    glNormal3fv(n);
+    glVertex3f(shrink*(p2->c[0]-cx)+cx,
+               shrink*(p2->c[1]-cy)+cy,
+               shrink*(p2->c[2]-cz)+cz);
+  }
+  glEnd();
+
+  /* display vertex number */
+  p0 = &mesh->point[pt->v[0]];
+  p1 = &mesh->point[pt->v[1]];
+  p2 = &mesh->point[pt->v[2]];
+  p3 = &mesh->point[pt->v[3]];
+
+  glColor3f(1.0-sc->par.back[0],1.0-sc->par.back[1],1.0-sc->par.back[2]);
+  output3(p0->c[0],p0->c[1],p0->c[2],"%d",pt->v[0]);
+  output3(p1->c[0],p1->c[1],p1->c[2],"%d",pt->v[1]);
+  output3(p2->c[0],p2->c[1],p2->c[2],"%d",pt->v[2]);
+  output3(p3->c[0],p3->c[1],p3->c[2],"%d",pt->v[3]);
+
+  /*if ( mesh->nfield == 6 )  drawEllipse(sc,mesh,LTets,k);*/
+  if ( !mesh->nbb )
+    circumSphere(sc,mesh,LTets,k);
+}
+
+static void drawHexa(pScene sc,pMesh mesh,int k) {
+  pMaterial  pm;
+  pHexa      ph;
+  pPoint     p0,p1,p2,p3;
+  float      ax,ay,az,bx,by,bz,d,n[3];
+  float      shrink,cx,cy,cz;
+  int        l;
+
+  /* default */
+  if ( ddebug ) printf("draw hexa %d\n",k);
+  if ( k < 1 || k > mesh->nhex )  return;
+  ph = &mesh->hexa[k];
+  if ( refpick > 0 )  ph->ref = refpick;
+  refmat = matRef(sc,ph->ref);
+  pm = &sc->material[refmat];
+  shrink = 0.95*sc->shrink;
+  
+  glBegin(GL_QUADS);
+  glColor3f(1.0-pm->dif[0],1.0-pm->dif[1],1.0-pm->dif[2]);
+  for (l=0; l<6; l++) {
+    p0 = &mesh->point[ph->v[ch[l][0]]];
+    p1 = &mesh->point[ph->v[ch[l][1]]];
+    p2 = &mesh->point[ph->v[ch[l][2]]];
+    p3 = &mesh->point[ph->v[ch[l][3]]];
+    cx = (p0->c[0] + p1->c[0] + p2->c[0] + p3->c[0]) / 4.;
+    cy = (p0->c[1] + p1->c[1] + p2->c[1] + p3->c[1]) / 4.;
+    cz = (p0->c[2] + p1->c[2] + p2->c[2] + p3->c[2]) / 4.;
+
+    /* compute face normal */
+    ax = p1->c[0] - p0->c[0]; ay = p1->c[1] - p0->c[1]; az = p1->c[2] - p0->c[2];
+    bx = p2->c[0] - p0->c[0]; by = p2->c[1] - p0->c[1]; bz = p2->c[2] - p0->c[2];
+    n[0] = ay*bz - az*by;
+    n[1] = az*bx - ax*bz;
+    n[2] = ax*by - ay*bx;
+    d = n[0]*n[0] + n[1]*n[1] + n[2]*n[2];
+    if ( d > 0.0f ) {
+      d = 1.0 / sqrt(d);
+      n[0] *= d;  
+      n[1] *= d;  
+      n[2] *= d;
+    }
+    glNormal3fv(n);
+    glVertex3f(sc->shrink*(p0->c[0]-cx)+cx,
+               sc->shrink*(p0->c[1]-cy)+cy,
+               sc->shrink*(p0->c[2]-cz)+cz);
+    glNormal3fv(n);
+    glVertex3f(sc->shrink*(p1->c[0]-cx)+cx,
+               sc->shrink*(p1->c[1]-cy)+cy,
+               sc->shrink*(p1->c[2]-cz)+cz);
+    glNormal3fv(n);
+    glVertex3f(sc->shrink*(p2->c[0]-cx)+cx,
+               sc->shrink*(p2->c[1]-cy)+cy,
+               sc->shrink*(p2->c[2]-cz)+cz);
+    glNormal3fv(n);
+    glVertex3f(sc->shrink*(p3->c[0]-cx)+cx,
+               sc->shrink*(p3->c[1]-cy)+cy,
+               sc->shrink*(p3->c[2]-cz)+cz);
+  }
+  glEnd();
+
+  /* display vertex number */
+  glColor3f(1.0-sc->par.back[0],1.0-sc->par.back[1],1.0-sc->par.back[2]);
+  for (l=0; l<8; l++) {
+    p0 = &mesh->point[ph->v[l]];
+    output3(p0->c[0],p0->c[1],p0->c[2],"%d",ph->v[l]);
+  }
+}
+
+static void drawPoint(pScene sc,pMesh mesh,int k) {
+  pPoint      pt;
+
+  pt = &mesh->point[k];
+
+  /*glDisable(GL_DEPTH_TEST);*/
+  glDisable(GL_LIGHTING);
+  glPointSize(6.0);
+  glColor3f(1.0,0.,0.);
+  glBegin(GL_POINTS);
+    glVertex3f(pt->c[0],pt->c[1],pt->c[2]);
+  glEnd();
+  output3(pt->c[0],pt->c[1],pt->c[2],"%d",refitem);
+  glEnable(GL_LIGHTING);
+  /*glEnable(GL_DEPTH_TEST);*/
+}
+
+
+static void infoData(pScene sc,pMesh mesh,int k,int typel) {
+  pSolution  ps;
+
+  if ( !mesh->nbb )  return;
+  ps = &mesh->sol[k];
+  if ( mesh->nfield == 1 )
+    fprintf(stdout,"  Data (scalar): %f\n",ps->bb);
+  else if ( mesh->nfield == mesh->dim ) {
+    fprintf(stdout,"  Data (vector): %f %f",ps->m[0],ps->m[1]);
+    if (mesh->dim == 3 )  fprintf(stdout," %f",ps->m[2]); 
+    fprintf(stdout,"\n");
+  }
+  else if ( mesh->dim == 2 && mesh->nfield == 3 ) {
+    fprintf(stdout,"  Data (tensor): %f %f %f\n",
+            ps->m[0],ps->m[1],ps->m[2]);
+    drawEllipse(sc,mesh,typel,k);
+  }
+  else if ( mesh->dim == 3 && mesh->nfield == 6 ) {
+    if ( mesh->ne)
+      fprintf(stdout,"  Data (tensor): %f %f %f %f %f %f\n",
+              ps->m[0],ps->m[1],ps->m[2],ps->m[3],ps->m[4],ps->m[5]);
+    drawEllipsoid(sc,mesh,typel,k);
+  }
+  fflush(stdout); /* add J. Morice 12/2008 */
+}
+
+
+static void infoEntity(pScene sc,pMesh mesh,int k,int type) {
+  pMaterial  pm;
+  pTriangle  pt;
+  pTetra     ptt;
+  pHexa      ph;
+  pQuad      pq;
+  pPoint     p0;
+  int        i;
+
+  if ( mesh->ne)  fprintf(stdout,"\n Picking result :\n");
+  pm = &sc->material[refmat];
+  switch(type) {
+  case LPoint:
+    p0 = &mesh->point[k];
+    if ( mesh->ne)
+      fprintf(stdout,"  Vertex %5d : %f, %f, %f    ref : %d\n",
+	      k,p0->c[0]+mesh->xtra,p0->c[1]+mesh->ytra,p0->c[2]+mesh->ztra,p0->ref);
+    if ( mesh->nbb && mesh->typage == 2 )  infoData(sc,mesh,k,LPoint);
+    break;
+ 
+  case LTria:
+    pt = &mesh->tria[k];
+    fprintf(stdout,"  Triangle %5d : %d, %d, %d    ref : %d [%s]\n",
+	    k,pt->v[0],pt->v[1],pt->v[2],pt->ref,pm->name);
+    if ( mesh->nbb && mesh->typage == 1 )  infoData(sc,mesh,k,LTria);
+    for (i=0; i<3; i++) {
+      p0 = &mesh->point[pt->v[i]];
+      fprintf(stdout,"  vertex   %5d : %f %f %f   ref %d\n",
+	    pt->v[i],p0->c[0]+mesh->xtra,p0->c[1]+mesh->ytra,p0->c[2]+mesh->ztra,p0->ref);
+      if ( mesh->nbb && mesh->typage == 2 )  infoData(sc,mesh,pt->v[i],LPoint);
+    }
+    break;
+  
+  case LQuad:
+    pq = &mesh->quad[k];
+    fprintf(stdout,"  Quad  %5d : %d, %d, %d, %d    ref : %d [%s]\n",
+	    k,pq->v[0],pq->v[1],pq->v[2],pq->v[3],pq->ref,pm->name);
+    if ( mesh->nbb && mesh->typage == 1 )  infoData(sc,mesh,k,LQuad);
+    for (i=0; i<4; i++) {
+      p0 = &mesh->point[pq->v[i]];
+      fprintf(stdout,"  vertex   %5d : %f %f %f   ref %d\n",
+	    pq->v[i],p0->c[0]+mesh->xtra,p0->c[1]+mesh->ytra,p0->c[2]+mesh->ztra,p0->ref);
+      if ( mesh->nbb && mesh->typage == 2 )  infoData(sc,mesh,pq->v[i],LPoint);
+    }
+    break;
+  
+  case LTets:
+    ptt = &mesh->tetra[k];
+    fprintf(stdout,"  Tetra  %5d : %d, %d, %d, %d    ref : %d [%s]\n",
+	    k,ptt->v[0],ptt->v[1],ptt->v[2],ptt->v[3],ptt->ref,pm->name);
+    if ( mesh->nbb && mesh->typage == 1 )  infoData(sc,mesh,k,LTets);
+    for (i=0; i<4; i++) {
+      p0 = &mesh->point[ptt->v[i]];
+      fprintf(stdout,"  vertex   %5d : %f %f %f   ref %d\n",
+	      ptt->v[i],p0->c[0]+mesh->xtra,p0->c[1]+mesh->ytra,p0->c[2]+mesh->ztra,p0->ref);
+      if ( mesh->nbb && mesh->typage == 2 )  infoData(sc,mesh,ptt->v[i],LPoint);
+    }
+    break;  
+  
+  case LHexa:
+    ph = &mesh->hexa[k];
+    fprintf(stdout,"  Hexa   %5d : %d, %d, %d, %d, %d, %d, %d, %d    ref : %d [%s]\n",
+	    k,ph->v[0],ph->v[1],ph->v[2],ph->v[3],ph->v[4],ph->v[5],
+            ph->v[6],ph->v[7],ph->ref,pm->name);
+    if ( mesh->nbb && mesh->typage == 1 )  infoData(sc,mesh,k,LHexa);
+    for (i=0; i<8; i++) {
+      p0 = &mesh->point[ph->v[i]];
+      fprintf(stdout,"  vertex   %5d : %f %f %f   ref %d\n",
+	      ph->v[i],p0->c[0]+mesh->xtra,p0->c[1]+mesh->ytra,p0->c[2]+mesh->ztra,p0->ref);
+      if ( mesh->nbb && mesh->typage == 2 )  infoData(sc,mesh,ph->v[i],LPoint);
+    }
+    break;  
+  }
+  fflush(stdout); /* add J. Morice 12/2008 */
+}
+
+
+static int getColorRange(Color *c,pMesh mesh) {
+  GLubyte    mask;
+  GLint      rBits,gBits,bBits,aBits;
+  long       nbmax;
+  int        i,nbits;
+
+  glGetIntegerv(GL_RED_BITS, &rBits);
+  glGetIntegerv(GL_GREEN_BITS, &gBits);
+  glGetIntegerv(GL_BLUE_BITS, &bBits);
+  glGetIntegerv(GL_ALPHA_BITS, &aBits);
+  nbits = rBits+gBits+bBits+aBits;
+
+  if ( nbits < 32 ) {
+    nbmax = 2 << (nbits-1);
+    if ( nbmax < mesh->nt+mesh->nq+mesh->ntet+mesh->nhex ) {
+      fprintf(stderr,"  Sorry. Picking disabled. (%ld,%d)\n",nbmax,mesh->nt+mesh->nq);
+      return(0);
+    }
+    else if ( nbmax < 0.1*(mesh->ntet+mesh->nhex) ) {
+      fprintf(stderr,"  Sorry. Picking disabled. (%ld,%d)\n",nbmax,mesh->nt+mesh->nq);
+      return(0);
+    }
+  }
+
+  mask  = 0;
+  nbits = nbits - rBits;
+  for (i=0; i<rBits; i++)  mask |= 1 << i;
+  c->rMask   = mask << nbits;
+  c->rShift  = nbits;
+  c->rBits   = 8 - rBits;
+
+  mask  = 0;
+  nbits = nbits - gBits;
+  for (i=0; i<gBits; i++)  mask |= 1 << i;
+  c->gMask  = mask << nbits;
+  c->gShift = nbits;
+  c->gBits  = 8 - gBits;
+
+  mask  = 0;
+  nbits = nbits - bBits;
+  for (i=0; i<bBits; i++)  mask |= 1 << i;
+  c->bMask   = mask << aBits;
+  c->bShift  = nbits;
+  c->bBits   = 8 - bBits;
+
+  mask = 0;
+  for (i=0; i<aBits; i++)  mask |= 1 << i;
+  c->aMask  = mask;
+  c->aBits  = 8 - aBits;
+}
+
+
+static void displayPoint(pScene sc,pMesh mesh,Color *c) {
+  pPoint       ppt;
+  unsigned int k,kk;
+
+  glPointSize(5);
+  glBegin(GL_POINTS);
+  for (k=1; k<=mesh->np; k++) {
+    ppt = &mesh->point[k];
+
+    kk = 2*k+1;
+    glColor4ub((kk & c->rMask) >> c->rShift << c->rBits,
+               (kk & c->gMask) >> c->gShift << c->gBits,
+               (kk & c->bMask) >> c->bShift << c->bBits,
+               (kk & c->aMask)              << c->aBits);
+
+    if ( mesh->dim == 2 )
+      glVertex2dv(ppt->c);
+    else
+      glVertex3dv(ppt->c);
+  }
+  glEnd();
+  glPointSize(1);
+}
+
+
+static void displayTria(pScene sc,pMesh mesh,Color *c) {
+  pTriangle    pt;
+  pPoint       p0,p1,p2;
+  pMaterial    pm;
+  int          m;
+  unsigned int k,kk;
+
+  glBegin(GL_TRIANGLES);
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTria];
+    if ( !k || pm->flag )  continue;
+
+    while ( k != 0 ) {
+      pt = &mesh->tria[k];
+      if ( pt->v[0] ) {
+        p0 = &mesh->point[pt->v[0]];
+        p1 = &mesh->point[pt->v[1]];
+        p2 = &mesh->point[pt->v[2]];
+
+        kk = 2*k+1;
+	    glColor4ub((kk & c->rMask) >> c->rShift << c->rBits,
+ 	               (kk & c->gMask) >> c->gShift << c->gBits,
+	               (kk & c->bMask) >> c->bShift << c->bBits,
+		           (kk & c->aMask)              << c->aBits);
+
+	    glVertex3dv(p0->c);
+        glVertex3dv(p1->c);
+        glVertex3dv(p2->c);
+      }
+      k = pt->nxt;
+    }
+  }
+  glEnd();
+}
+
+static int displayQuad(pScene sc,pMesh mesh,Color *c) {
+  pQuad        pq;
+  pPoint       p0,p1,p2,p3;
+  pMaterial    pm;
+  int          k,m,base;
+  unsigned int kk;
+
+  base = mesh->nt;
+
+  glBegin(GL_QUADS);
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LQuad];
+    if ( !k || pm->flag )  continue;
+
+    while ( k != 0 ) {
+      pq = &mesh->quad[k];
+      if ( pq->v[0] ) {
+        p0 = &mesh->point[pq->v[0]];
+        p1 = &mesh->point[pq->v[1]];
+        p2 = &mesh->point[pq->v[2]];
+        p3 = &mesh->point[pq->v[3]];
+
+        kk = base + k;
+        kk = 2*kk + 1;
+	glColor4ub((kk & c->rMask) >> c->rShift << c->rBits,
+ 	           (kk & c->gMask) >> c->gShift << c->gBits,
+	           (kk & c->bMask) >> c->bShift << c->bBits,
+		   (kk & c->aMask)              << c->aBits);
+
+	glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+        glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+        glVertex3f(p2->c[0],p2->c[1],p2->c[2]);
+        glVertex3f(p3->c[0],p3->c[1],p3->c[2]);
+      }
+      k = pq->nxt;
+    }
+  }
+  glEnd();
+}
+
+static int displayTets(pScene sc,pMesh mesh,Color *c) {
+  pTetra       ptt;
+  pPoint       p0,p1,p2;
+  pMaterial    pm;
+  pClip        clip;
+  int          k,l,m,base;
+  unsigned int kk;
+
+  clip = sc->clip;
+  base = mesh->nt + mesh->nq;
+
+  glBegin(GL_TRIANGLES);
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTets];
+    if ( !k || pm->flag )  continue;
+
+    while ( k != 0 ) {
+      ptt = &mesh->tetra[k];
+      if ( ptt->v[0] ) {
+        if ( (clip->active & C_ON && ptt->clip) || !(clip->active & C_ON) ) {
+          kk = base + k;
+          kk = 2*kk + 1;
+  	  for (l=0; l<4; l++) {
+	    p0 = &mesh->point[ptt->v[ct[l][0]]];
+	    p1 = &mesh->point[ptt->v[ct[l][1]]];
+	    p2 = &mesh->point[ptt->v[ct[l][2]]];
+
+	    glColor4ub((kk & c->rMask) >> c->rShift << c->rBits,
+ 	               (kk & c->gMask) >> c->gShift << c->gBits,
+	               (kk & c->bMask) >> c->bShift << c->bBits,
+		       (kk & c->aMask)              << c->aBits);
+
+	    glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+            glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+            glVertex3f(p2->c[0],p2->c[1],p2->c[2]);
+	  }
+	}
+      }
+      k = ptt->nxt;
+    }
+  }
+  glEnd();
+}
+
+static int displayHexa(pScene sc,pMesh mesh,Color *c) {
+  pHexa        ph;
+  pPoint       p0,p1,p2,p3;
+  pMaterial    pm;
+  pClip        clip;
+  int          k,l,m,base;
+  unsigned int kk;
+
+  clip = sc->clip;
+  base = mesh->nt + mesh->nq + mesh->ntet;
+
+  glBegin(GL_QUADS);
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LHexa];
+    if ( !k || pm->flag )  continue;
+
+    while ( k != 0 ) {
+      ph = &mesh->hexa[k];
+      if ( ph->v[0] ) {
+        if ( (clip->active & C_ON && ph->clip) || !(clip->active & C_ON) ) {
+          kk = base + k;
+          kk = 2*kk + 1;
+  	  for (l=0; l<6; l++) {
+	    p0 = &mesh->point[ph->v[ch[l][0]]];
+	    p1 = &mesh->point[ph->v[ch[l][1]]];
+	    p2 = &mesh->point[ph->v[ch[l][2]]];
+	    p3 = &mesh->point[ph->v[ch[l][3]]];
+
+	    glColor4ub((kk & c->rMask) >> c->rShift << c->rBits,
+ 	               (kk & c->gMask) >> c->gShift << c->gBits,
+	               (kk & c->bMask) >> c->bShift << c->bBits,
+		       (kk & c->aMask)              << c->aBits);
+
+	    glVertex3f(p0->c[0],p0->c[1],p0->c[2]);
+            glVertex3f(p1->c[0],p1->c[1],p1->c[2]);
+            glVertex3f(p2->c[0],p2->c[1],p2->c[2]);
+            glVertex3f(p3->c[0],p3->c[1],p3->c[2]);
+	  }
+	}
+      }
+      k = ph->nxt;
+    }
+  }
+  glEnd();
+}
+
+
+void drawModelSimple(pScene sc,pMesh mesh,Color *c) {
+
+  glDisable(GL_BLEND);
+  glDisable(GL_LIGHTING);
+  glShadeModel(GL_FLAT);
+  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+
+  if ( sc->clip->active & C_ON ) {
+    glClipPlane(GL_CLIP_PLANE0,sc->clip->eqn);
+    glEnable(GL_CLIP_PLANE0);
+    if ( mesh->nt )    displayTria(sc,mesh,c);
+    if ( mesh->nq )    displayQuad(sc,mesh,c);
+    glDisable(GL_CLIP_PLANE0);
+    if ( sc->clip->active & C_VOL ) {
+      if ( mesh->ntet )  displayTets(sc,mesh,c);
+      if ( mesh->nhex )  displayHexa(sc,mesh,c);
+    }
+  }
+  else {
+    if ( mesh->nt )  displayTria(sc,mesh,c);
+    if ( mesh->nq )  displayQuad(sc,mesh,c);
+    if ( mesh->dim == 3 ) {
+      if ( !mesh->nt ) displayTets(sc,mesh,c);
+      if ( !mesh->nq ) displayHexa(sc,mesh,c);
+    }
+  }
+
+  if ( !mesh->ne )  displayPoint(sc,mesh,c);
+    
+  glEnable(GL_LIGHTING);
+  glShadeModel(GL_SMOOTH);
+  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+}
+
+
+static int closestPoint(pScene sc,pMesh mesh,int x,int y,int item,int type) {
+  pTriangle   pt;
+  pQuad       pq;
+  pTetra      pte;
+  pHexa       ph;
+  pPoint      ppt;
+  GLdouble    projmat[16],winx,winy,winz,matrix[16];
+  GLint       viewport[4];
+  double      dd,dmin;
+  int         i,id;
+
+  glGetDoublev(GL_PROJECTION_MATRIX,projmat);
+  glGetIntegerv(GL_VIEWPORT,viewport);
+  glGetDoublev(GL_MODELVIEW_MATRIX,matrix);
+  y = viewport[3] - y;
+
+  id   = -1;
+  dmin = 1.e20;
+  switch(type) {
+  case LTria:
+    pt   = &mesh->tria[item];
+    for (i=0; i<3; i++) {
+      ppt = &mesh->point[pt->v[i]];
+      gluProject(ppt->c[0],ppt->c[1],ppt->c[2],
+                 matrix,projmat,viewport,
+                 &winx,&winy,&winz);
+      dd = (winx - x)*(winx - x) + (winy - y)*(winy - y);
+      if ( dd < dmin ) {
+        dmin = dd;
+	id   = i;
+      }
+    }
+    return(pt->v[id]);
+  
+  case LQuad:
+    pq   = &mesh->quad[item];
+    for (i=0; i<4; i++) {
+      ppt = &mesh->point[pq->v[i]];
+      gluProject(ppt->c[0]-sc->cx,ppt->c[1]-sc->cy,ppt->c[2]-sc->cz,
+                 matrix,projmat,viewport,
+                 &winx,&winy,&winz);
+      dd = (winx - x)*(winx - x) + (winy - y)*(winy - y);
+      if ( dd < dmin ) {
+        dmin = dd;
+	id   = i;
+      }
+    }
+    return(pq->v[id]);
+  
+  case LTets:
+    pte  = &mesh->tetra[item];
+    for (i=0; i<4; i++) {
+      ppt = &mesh->point[pte->v[i]];
+      gluProject(ppt->c[0]-sc->cx,ppt->c[1]-sc->cy,ppt->c[2]-sc->cz,
+                 matrix,projmat,viewport,
+                 &winx,&winy,&winz);
+      dd = (winx - x)*(winx - x) + (winy - y)*(winy - y);
+      if ( dd < dmin ) {
+        dmin = dd;
+	id   = i;
+      }
+    }
+    return(pte->v[id]);
+
+  case LHexa:
+    ph   = &mesh->hexa[item];
+    for (i=0; i<8; i++) {
+      ppt = &mesh->point[ph->v[i]];
+      gluProject(ppt->c[0]-sc->cx,ppt->c[1]-sc->cy,ppt->c[2]-sc->cz,
+                 matrix,projmat,viewport,
+                 &winx,&winy,&winz);
+      dd = (winx - x)*(winx - x) + (winy - y)*(winy - y);
+      if ( dd < dmin ) {
+        dmin = dd;
+	id   = i;
+      }
+    }
+    return(ph->v[id]);
+  }
+
+  return(0);
+}
+
+
+GLuint pickingScene(pScene sc,int x,int y,int ident) {
+  pMesh         mesh;
+  pClip         clip;
+  GLint         viewport[4];
+  GLubyte       pixel[4];
+  GLuint        dlist;
+  Color         c;
+  int           k;
+  unsigned int  item;
+
+  dlist   = 0;  
+  refitem = 0;
+  refmat  = -1;
+  mesh    = cv.mesh[sc->idmesh];
+  clip    = sc->clip;
+
+  if ( !getColorRange(&c,mesh) )  return(dlist);
+
+  glGetIntegerv(GL_VIEWPORT,viewport);
+  glDrawBuffer(GL_BACK_LEFT);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt(0.,0.,-sc->persp->depth, 0.,0.,0., 0.0,1.0,0.0);
+
+  setupView(sc);
+  glMultMatrixf(sc->view->matrix);
+  glTranslatef(sc->cx,sc->cy,sc->cz);
+  drawModelSimple(sc,mesh,&c);
+  glFlush();
+
+  /* process color */
+  glReadBuffer(GL_BACK_LEFT);
+  glReadPixels(x,viewport[3]-y,1,1,
+               GL_RGBA,GL_UNSIGNED_BYTE,(void *)pixel);
+  glDrawBuffer(GL_BACK_LEFT);
+
+  if ( ddebug )  printf("pixel %d %d %d %d\n",pixel[0],pixel[1],pixel[2],pixel[3]);
+
+  item  = pixel[0] >> c.rBits << c.rShift & c.rMask;
+  item += pixel[1] >> c.gBits << c.gShift & c.gMask;
+  item += pixel[2] >> c.bBits << c.bShift & c.bMask;
+  item += pixel[3] >> c.aBits             & c.aMask;
+  item /= 2;
+  if ( !item )  return(dlist);
+
+  if ( ddebug )  printf("item %d\n",item);
+
+  if ( !mesh->ne ) {
+    if ( item <= mesh->np ) {
+      refitem = item;
+      reftype = LPoint;
+    }
+  }
+  else if ( item <= mesh->nt ) {
+    refitem = item;
+    reftype = LTria;
+  }
+  else if ( item <= mesh->nt+mesh->nq ) {
+    refitem = item - mesh->nt;
+    reftype = LQuad;
+  }
+  else if ( item <= mesh->nt+mesh->nq+mesh->ntet ) {
+    refitem = item - (mesh->nt+mesh->nq);
+    reftype = LTets;
+  }
+  else if ( item <= mesh->nt+mesh->nq+mesh->ntet+mesh->nhex ) {
+    refitem = item - (mesh->nt+mesh->nq+mesh->ntet);
+    reftype = LHexa;
+  }
+
+  /* peculiar case: vertex */
+  if ( refitem > 0 && ident == LPoint ) {
+    if ( mesh->ne ) {
+      refitem = closestPoint(sc,mesh,x,y,refitem,reftype);
+      reftype = LPoint;
+    }
+  }
+
+  if ( refitem > 0 ) {
+    dlist = glGenLists(1);
+    glNewList(dlist,GL_COMPILE);
+    if ( glGetError() )  return(0);
+
+    switch(reftype) {
+    case LPoint:
+      if ( refitem <= mesh->np && !mesh->ne ) {
+        for (k=1; k<=mesh->np; k++) {
+          /*drawPoint(sc,mesh,k);*/
+          infoEntity(sc,mesh,k,LPoint);
+        }
+      }
+      else {
+        drawPoint(sc,mesh,refitem);
+        infoEntity(sc,mesh,refitem,LPoint);
+      }
+      break;
+    case LTria:
+      drawTria(sc,mesh,refitem);
+      infoEntity(sc,mesh,refitem,LTria);
+      break;
+    case LQuad:
+      drawQuad(sc,mesh,refitem);
+      infoEntity(sc,mesh,refitem,LQuad);
+      break;
+    case LTets:
+      drawTets(sc,mesh,refitem);
+      infoEntity(sc,mesh,refitem,LTets);
+      break;
+    case LHexa:
+      drawHexa(sc,mesh,refitem);
+      infoEntity(sc,mesh,refitem,LHexa);
+      break;
+    }
+
+    glEndList();
+    return(dlist);
+  }
+  else
+    refmat = -1;
+
+  return(dlist); 
+}
+
+
+GLuint pickItem(pMesh mesh,pScene sc,int numit) {
+  pMaterial  pm;
+  pPoint     ppt;
+  GLuint     dlist;
+  int        nm;
+
+  /* default */
+  if ( ddebug ) printf("create pickitem list\n");
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  if ( numit <= mesh->np && mesh->ne ) {
+    ppt = &mesh->point[numit];
+    pm  = &sc->material[DEFAULT_MAT];
+    if ( ppt->tag != M_UNUSED ) {
+      if ( ppt->ref ) {
+        nm = matRef(sc,ppt->ref);
+        /*nm = 1+(ppt->ref-1) % (sc->par.nbmat-1);*/
+        pm = &sc->material[nm];
+      }
+      glPointSize(3.0);
+      glColor3f(pm->dif[0],pm->dif[1],pm->dif[2]);
+      output3(ppt->c[0],ppt->c[1],ppt->c[2],"%d",numit);
+    }
+  }
+
+  if ( numit <= mesh->nt )   drawTria(sc,mesh,numit);
+  if ( numit <= mesh->nq )   drawQuad(sc,mesh,numit);
+  if ( numit <= mesh->ntet ) drawTets(sc,mesh,numit);
+  if ( numit <= mesh->nhex ) drawHexa(sc,mesh,numit);
+
+  glEndList(); 
+  return(dlist);
+}
diff --git a/src/medit/psfile.c b/src/medit/psfile.c
new file mode 100644
index 0000000..ee25b52
--- /dev/null
+++ b/src/medit/psfile.c
@@ -0,0 +1,204 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef ubyte
+typedef unsigned char  ubyte;
+#endif
+
+#define CM2IN     0.3937
+
+
+void writeEPSheader(FILE *out,char *data,char key,int ww,int hh,float cm,float dpi) {
+  int wpad;
+  
+  fprintf(out,"%%!PS-Adobe-2.0 EPSF-2.0\n");
+  fprintf(out,"%%LanguageLevel: 1\n");
+  fprintf(out,"%%%%Title: %s\n",data);
+  fprintf(out,"%%%%Creator: medit -  (C) INRIA-Rocquencourt, 1999-2001\n");
+  fprintf(out,"%%%%BoundingBox: 50 50 %d %d\n",
+               (int)(ww*72./dpi+50.5),(int)(hh*72.0/dpi+50.5));
+  fprintf(out,"%%%%Pages: (atend)\n");
+  fprintf(out,"%%DocumentFonts:\n");
+  fprintf(out,"%%%%EndComments\n");
+  fprintf(out,"%%%%EndProlog\n");
+  fprintf(out,"\n%%%%Page: 1 1\n");
+  fprintf(out,"\n%% remember original state\n");
+  fprintf(out,"/origstate save def\n");
+  fprintf(out,"\n%% build a temporary dictionary\n");
+  fprintf(out,"20 dict begin\n");
+
+  fprintf(out,"\n%% define space for color conversions\n");
+  fprintf(out,"/grays %d string def  %% space for gray scale line\n",ww);
+  fprintf(out,"/npixls 0 def\n");
+  fprintf(out,"/rgbindx 0 def\n");
+  fprintf(out,"\n%% lower left corner\n");
+  fprintf(out,"50 50 translate\n");
+  
+  fprintf(out,"\n%% size of image (on paper, in 1/72inch coords)\n");
+  fprintf(out,"%g %g scale\n",72.0*CM2IN*cm,72.0*CM2IN*cm*(float)hh/ww);
+  fprintf(out,"\n%% define string to hold a scanline's worth of data\n");
+
+  /* write BW image */
+  if ( key == 'B') {
+    wpad = (ww+7) & ~7;
+    fprintf(out,"/pix %d string def\n",wpad/8);
+    fprintf(out,"\n%% dimensions of data\n");
+    fprintf(out,"%d %d 1\n",ww,hh);
+    fprintf(out,"\n%% mapping matrix\n");
+    fprintf(out,"[%d 0 0 %d 0 %d]\n",ww,-hh,hh);
+    fprintf(out,"\n{currentfile pix readhexstring pop}\n");
+    fprintf(out,"image\n");
+  }
+  /* write greyscale image */
+  else if ( key == 'G' ) {
+    fprintf(out,"/pix %d string def\n",ww);
+    fprintf(out,"\n%% dimensions of data\n");
+    fprintf(out,"%d %d 8\n",ww,hh);
+    fprintf(out,"\n%% mapping matrix\n");
+    fprintf(out,"[%d 0 0 %d 0 %d]\n",ww,-hh,hh);
+    fprintf(out,"\n{currentfile pix readhexstring pop}\n");
+    fprintf(out,"image\n");
+  }
+  /* color image */
+  else if ( key == 'C' ) {
+    fprintf(out,"/pix %d string def\n",3*ww);
+
+    fprintf(out,"\n%% dimensions of data\n");
+    fprintf(out,"%d %d 8\n",ww,hh);
+    fprintf(out,"\n%% mapping matrix\n");
+    fprintf(out,"[%d 0 0 %d 0 %d]\n",ww,-hh,hh);
+
+    fprintf(out,"\n%% define 'colorimage' if it isn't defined\n");
+    fprintf(out,"/colorimage where   %% do we know about 'colorimage'?\n");
+    fprintf(out,"  { pop }           %% yes: pop off the 'dict' returned\n");
+    fprintf(out,"  {                 %% no:  define one\n");
+    fprintf(out,"    /colortogray {  %% define an RGB->I function\n");
+    fprintf(out,"      /rgbdata exch store    %% call input 'rgbdata'\n");
+    fprintf(out,"      rgbdata length 3 idiv\n");
+    fprintf(out,"      /npixls exch store\n");
+    fprintf(out,"      /rgbindx 0 store\n");
+    fprintf(out,"      0 1 npixls 1 sub {\n");
+    fprintf(out,"        grays exch\n");
+    fprintf(out,"        rgbdata rgbindx       get 20 mul    %% Red\n");
+    fprintf(out,"        rgbdata rgbindx 1 add get 32 mul    %% Green\n");
+    fprintf(out,"        rgbdata rgbindx 2 add get 12 mul    %% Blue\n");
+    fprintf(out,"        add add 64 idiv     %% I = .5G + .31R + .18B\n");
+    fprintf(out,"        put\n");
+    fprintf(out,"       /rgbindx rgbindx 3 add store\n");
+    fprintf(out,"      } for\n");
+    fprintf(out,"      grays 0 npixls getinterval\n");
+    fprintf(out,"    } bind def\n");
+
+    fprintf(out,"\n    %% Utility procedure for colorimage operator.\n");
+    fprintf(out,"    %% This procedure takes two procedures off the\n");
+    fprintf(out,"    %% stack and merges them into a single procedure.\n");
+
+    fprintf(out,"\n    /mergeprocs { %% def\n");
+    fprintf(out,"      dup length\n");
+    fprintf(out,"      3 -1 roll\n");
+    fprintf(out,"      dup\n");
+    fprintf(out,"      length\n");
+    fprintf(out,"     dup\n");
+    fprintf(out,"      5 1 roll\n");
+    fprintf(out,"      3 -1 roll\n");
+    fprintf(out,"      add\n");
+    fprintf(out,"      array cvx\n");
+    fprintf(out,"      dup\n");
+    fprintf(out,"      3 -1 roll\n");
+    fprintf(out,"      0 exch\n");
+    fprintf(out,"      putinterval\n");
+    fprintf(out,"      dup\n");
+    fprintf(out,"      4 2 roll\n");
+    fprintf(out,"      putinterval\n");
+    fprintf(out,"    } bind def\n");
+
+    fprintf(out,"    /colorimage { %% def\n");
+    fprintf(out,"      pop pop     %% remove 'false 3' operands\n");
+    fprintf(out,"      {colortogray} mergeprocs\n");
+    fprintf(out,"      image\n");
+    fprintf(out,"    } bind def\n");
+    fprintf(out,"  } ifelse          %% end of 'false' case\n");
+    fprintf(out,"\n{currentfile pix readhexstring pop}\n");
+    fprintf(out,"false 3 colorimage\n\n");
+  }
+}
+
+void writeEPStrailer(FILE *out) {
+  fprintf(out,"\nshowpage\n");
+  fprintf(out,"\n%% stop using temporary dictionary\n");
+  fprintf(out,"end\n");
+  fprintf(out,"\n%% restore original state\n");
+  fprintf(out,"origstate restore\n");
+  fprintf(out,"\n%%%%Trailer\n");
+}
+
+void writeEPSRow(FILE *out,char key,ubyte *buffer,int size,ubyte bckbyt) {
+  int    c,k,l;
+  ubyte  byte,bbyte;
+
+  l = 0;
+  switch (key) {
+  case 'B':  /* black & white */
+    byte = 0x0;
+    c    = 0;
+    for (k=0; k<3*size; k+=3) {
+      bbyte = (ubyte)(0.30*buffer[k]   + 0.59*buffer[k+1] 
+                    + 0.11*buffer[k+2] + 0.5);
+      if ( bbyte == bckbyt )  byte |= (1 << (7-c));
+      /*
+      if ( bbyte > 253 )  byte |= (1 << (7-c));
+      
+      if ( bbyte && bbyte != 255 )  {
+        printf("buffer %d %d %d\n",buffer[k],buffer[k+1],buffer[k+2]);
+        printf("bbyte  %d  byte %d\n",bbyte,byte);
+        exit(1);
+      }
+      */
+      if ( ++c == 8 ) {
+        fprintf(out,"%.2x",byte);
+        if ( ++l == 36 ) {
+          fprintf(out,"\n");
+          l = 0;
+        }
+        byte = 0x0;
+        c = 0;
+      }
+    }
+    /* padding */
+    if ( c ) {
+      for (l=8; l>c; l--) byte |= (1 << l);
+      fprintf(out,"%.2x",byte);
+    }
+    break;
+  case 'G':  /* greyscale */
+    for (k=0; k<3*size; k+=3) {
+      byte = (ubyte)(0.30*buffer[k] + 0.59*buffer[k+1] + 0.11*buffer[k+2]);
+      fprintf(out,"%.2x",byte);
+      if ( ++l == 36 ) {
+        fprintf(out,"\n");
+        l = 0;
+      }
+    }
+    break;
+  case 'C':  /* color scale */
+    for (k=0; k<3*size; k++) {
+      fprintf(out,"%.2x",buffer[k]);
+      if ( ++l == 36 ) {
+        fprintf(out,"\n");
+        l = 0;
+      }
+    }
+    break;
+  }
+  fprintf(out,"\n");
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/scene.c b/src/medit/scene.c
new file mode 100644
index 0000000..67acb7f
--- /dev/null
+++ b/src/medit/scene.c
@@ -0,0 +1,930 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+extern GLboolean  hasStereo;
+extern int       *pilmat,ipilmat,refmat,reftype,refitem;
+extern short      schw,schh;
+extern ubyte      quiet,fullscreen,tiling,stereoMode;
+
+
+/* return current active scene */
+int currentScene() {
+  int  k,idw;
+
+  idw = glutGetWindow();
+  for (k=0; k<MAX_SCENE; k++) {
+    if ( cv.scene[k] && idw == cv.scene[k]->idwin )
+      return(k);
+  }
+  return(0);
+}
+
+/* check for OpenGL error */
+void checkErrors(void) {
+  GLenum error;
+
+  while ( (error = glGetError()) != GL_NO_ERROR ) {
+    fprintf(stderr,"  ## ERROR: %d: %s\n",
+            (int)error,(char*)gluErrorString(error));
+    exit(1);
+  }
+}
+
+void farclip(GLboolean b) {
+  pScene  sc;
+  pPersp  p;
+  pCamera c;
+  float   look[3],ratio,units;
+  int     idw = currentScene();
+  static  GLfloat up[3] = { 0.0, 1.0, 0.0};
+
+  /* default */
+  sc    = cv.scene[idw];
+  p     = sc->persp;
+  c     = sc->camera;
+  ratio = (GLfloat)sc->par.xs / sc->par.ys;
+
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+
+  switch (p->pmode) {
+  case ORTHO:
+    glOrtho(-1.,1.,-1.,0.1,0.01,0.01);
+    break;
+
+  case PERSPECTIVE:
+    if ( b )
+      gluPerspective(p->fovy,ratio,sc->dmax,4.0*sc->dmax);
+    else
+      gluPerspective(p->fovy,ratio,0.01,10000.0*sc->dmax);
+
+    units = 1.e-02;
+    glPolygonOffset(1.0, units);
+    break;
+
+  case CAMERA:
+    gluPerspective(p->fovy,ratio,0.001*sc->dmax,4.0*sc->dmax);
+    look[0] = c->eye[0] + 0.001*sc->dmax*c->speed[0];
+    look[1] = c->eye[1] + 0.001*sc->dmax*c->speed[1];
+    look[2] = c->eye[2] + 0.001*sc->dmax*c->speed[2];
+    gluLookAt(c->eye[0],c->eye[1],c->eye[2], 
+              look[0],look[1],look[2],
+              up[0],up[1],up[2]);
+    break;
+  }
+
+  /* zoom transformation */
+  if ( p->rubber == 2 ) {
+    glPushMatrix();
+    glLoadIdentity();
+    glRotatef(-p->gamma,1.,0.,0.);
+    glRotatef(p->alpha,0.,1.,0.);
+    glMultMatrixf(p->matrix);
+    glGetFloatv(GL_PROJECTION_MATRIX,p->matrix);
+    glPopMatrix();
+    p->rubber = 0;
+  }
+
+  /* apply transformation */
+  glMultMatrixf(p->matrix);
+
+  glMatrixMode(GL_MODELVIEW);
+}
+
+
+void reshapeScene(int width,int height) {
+  pScene   sc;
+
+  if ( ddebug ) printf("reshape scene\n");
+  sc = cv.scene[currentScene()];
+  sc->par.xs = width;
+  sc->par.ys = height;
+
+  glViewport(0,0,width,height);
+  farclip(GL_TRUE);
+}
+
+
+static void drawList(pScene sc,int clip,int map) {
+  pMesh   mesh = cv.mesh[sc->idmesh];
+  ubyte   elev = sc->mode & S_ALTITUDE;
+
+  if ( ddebug ) printf("drawList %p %d %d\n",sc,clip,map);
+  if ( mesh->dim == 2 && !elev ) glDisable(GL_DEPTH_TEST);
+
+  glLineWidth(1.0);
+  if ( clip ) {
+    if ( map ) {
+      if ( sc->cmlist[LTets] ) glCallList(sc->cmlist[LTets]);
+      if ( sc->cmlist[LHexa] ) glCallList(sc->cmlist[LHexa]);
+    }
+    else {
+      if ( sc->clist[LTets] ) glCallList(sc->clist[LTets]);
+      if ( sc->clist[LHexa] ) glCallList(sc->clist[LHexa]);
+    }
+  }
+  else if ( map ) {
+    if ( mesh->nt+mesh->nq ) {
+      if ( sc->mlist[LTria] ) glCallList(sc->mlist[LTria]);
+      if ( sc->mlist[LQuad] ) glCallList(sc->mlist[LQuad]);
+    }
+    else {
+      if ( sc->mlist[LTets] ) glCallList(sc->mlist[LTets]);
+      if ( sc->mlist[LHexa] ) glCallList(sc->mlist[LHexa]);
+    }
+  }
+  else {
+    if ( mesh->nt+mesh->nq ) {
+      if ( sc->dlist[LTria] ) glCallList(sc->dlist[LTria]);
+      if ( sc->dlist[LQuad] ) glCallList(sc->dlist[LQuad]);
+    }
+    else {
+      if ( sc->dlist[LTets] ) glCallList(sc->dlist[LTets]);
+      if ( sc->dlist[LHexa] ) glCallList(sc->dlist[LHexa]);
+    }
+  }
+  if ( mesh->dim == 2 && !elev ) glEnable(GL_DEPTH_TEST);
+}
+
+#ifdef ppc
+void bogusQuad(pScene sc) {
+  /* bogus polygon (nvidia) */
+  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glLineWidth(1.0);
+    glColor3fv(sc->par.back);
+    glBegin(GL_QUADS);
+      glVertex3f(0., 0.,-sc->persp->depth);
+      glVertex3f(0., 0.,-sc->persp->depth);
+      glVertex3f(0., 0.,-sc->persp->depth);
+      glVertex3f(0., 0.,-sc->persp->depth);
+    glEnd();
+  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+}
+#endif
+
+static void displayScene(pScene sc,int mode,int clip) {
+  int     map;
+  
+  map = mode & S_MAP;
+
+  switch(mode) {
+  case FILL:  /* solid fill */
+    if ( ddebug ) printf("solid fill\n");
+    glEnable(GL_LIGHTING);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+      drawList(sc,clip,0);
+    glDisable(GL_LIGHTING);
+    break;
+
+  case WIRE:  /* basic wireframe */
+  case WIRE+S_MATERIAL:
+    if ( ddebug ) printf("wireframe\n");
+#ifdef ppc
+    bogusQuad(sc);
+#endif
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glColor4fv(sc->par.line);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+      drawList(sc,clip,0);
+    break;
+
+  case DEPTH:  /* depth wireframe */
+  case DEPTH + S_MATERIAL:
+    if ( ddebug ) printf("depth wireframe\n");
+    glEnable(GL_LIGHTING);
+    glDisable(GL_COLOR_MATERIAL);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+      drawList(sc,clip,0);
+    glDisable(GL_LIGHTING);
+    break;
+
+  case HIDDEN: /* hidden lines removal */
+  case HIDDEN + S_MATERIAL:
+    if ( ddebug ) printf("hidden lines\n");
+    glDisable(GL_LIGHTING);
+    glDisable(GL_COLOR_MATERIAL);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glColor3fv(sc->par.back);
+      drawList(sc,clip,0);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+#ifdef ppc
+    bogusQuad(sc);
+#endif
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glColor4fv(sc->par.line);
+      drawList(sc,clip,0);
+    break;
+
+  case SHADED: /* shaded polygons */
+  case SHADED+S_MATERIAL:
+    if ( ddebug ) printf("shaded polygons\n");
+    glEnable(GL_LIGHTING);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+      drawList(sc,clip,0);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+#ifdef ppc
+    bogusQuad(sc);
+#endif
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glColor4fv(sc->par.line);
+      drawList(sc,clip,0);
+    break;
+
+  case SIZEMAP: /* display metric map */
+  case SIZEMAP+S_MATERIAL:
+    if ( ddebug ) printf("display sizemap\n");
+    glEnable(GL_LIGHTING);
+    glEnable(GL_COLOR_MATERIAL);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+      drawList(sc,clip,map);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_COLOR_MATERIAL);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+#ifdef ppc
+    bogusQuad(sc);
+#endif
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glColor4fv(sc->par.line);
+    glLineWidth(1.0);
+      drawList(sc,clip,0);
+    if ( sc->mode & S_ALTITUDE ) {
+      glColor4fv(sc->par.line);
+      if ( sc->mlist[LTets] ) glCallList(sc->mlist[LTets]);
+      if ( sc->mlist[LHexa] ) glCallList(sc->mlist[LHexa]);
+    }
+    break;
+
+  default: /* other modes */
+    if ( ddebug ) printf("rendering mode %d\n",sc->mode);
+    /* interior */
+    if ( sc->mode & S_FILL ) {
+      if ( sc->mode & S_COLOR )  glEnable(GL_LIGHTING);
+      glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+      glEnable(GL_POLYGON_OFFSET_FILL);
+      if ( sc->mode & S_MAP ) {
+        glEnable(GL_COLOR_MATERIAL);
+	drawList(sc,clip,map);
+        glDisable(GL_COLOR_MATERIAL);
+      }
+      else {
+ 	glColor4fv(sc->par.back);
+	drawList(sc,clip,0);
+      }
+    }
+
+    /* boundary */
+    glDisable(GL_LIGHTING);
+    glDisable(GL_COLOR_MATERIAL);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+#ifdef ppc
+    bogusQuad(sc);
+#endif
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    if ( !(sc->mode & S_BDRY) )  break;
+    if ( sc->mode & S_COLOR && !(sc->mode & S_FILL) ) {
+      glEnable(GL_COLOR_MATERIAL);
+      glEnable(GL_LIGHTING);
+    }
+    if ( sc->mode & S_MAP) {
+      if ( sc->mode & S_FILL ) {
+        glColor4fv(sc->par.line);
+        drawList(sc,clip,0);
+      }
+      else
+        drawList(sc,clip,map);
+    }
+    else if ( sc->mode & S_ALTITUDE ) {
+      glColor4fv(sc->par.line);
+      drawList(sc,clip,map);
+      if ( sc->mlist[LTets] ) glCallList(sc->mlist[LTets]);
+      if ( sc->mlist[LHexa] ) glCallList(sc->mlist[LHexa]);
+    }
+    else {
+      glColor4fv(sc->par.line);
+      drawList(sc,clip,0);
+    }
+  }
+}
+
+static void displayData(pScene sc,pMesh mesh) {
+  int  kk;
+  
+  glDisable(GL_LIGHTING);
+  glDisable(GL_COLOR_MATERIAL);
+
+  /* iso-lines */
+  if ( sc->isotyp & S_ISOLINE ) {
+    glLineWidth(1.0);
+    if ( sc->ilist[LTria] )  glCallList(sc->ilist[LTria]);
+    if ( sc->ilist[LQuad] )  glCallList(sc->ilist[LQuad]);
+    glDisable(GL_CLIP_PLANE0);
+    if ( sc->ilist[LTets] && sc->clip->active & C_ON )
+      glCallList(sc->ilist[LTets]);
+  }
+
+  /* vector field */
+  if ( sc->isotyp & S_VECTOR ) {
+    if ( mesh->dim == 2 ) {
+      if ( sc->vlist[LTria] )  glCallList(sc->vlist[LTria]);
+      if ( sc->vlist[LQuad] )  glCallList(sc->vlist[LQuad]);
+    }
+    else {
+      if ( sc->clip->active & C_ON ) {
+        glDisable(GL_CLIP_PLANE0);
+        if ( sc->vlist[LTets] )  glCallList(sc->vlist[LTets]);
+        if ( sc->vlist[LHexa] )  glCallList(sc->vlist[LHexa]);
+      }
+      else if (mesh->ntet+mesh->nhex == 0 )
+        if ( sc->vlist[LTria] )  glCallList(sc->vlist[LTria]);
+    }
+  }
+
+  /* streamlines */
+  if ( sc->isotyp & S_CRITP && sc->cplist )
+    glCallList(sc->cplist);
+  if ( sc->isotyp & S_STREAML ) {
+    for (kk=0; kk<sc->stream->nbstl; kk++)
+      glCallList(sc->slist[kk]);
+  }
+  else if ( sc->isotyp & S_PARTICLE ) {
+    glEnable(GL_LIGHTING);
+    glEnable(GL_COLOR_MATERIAL);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    displayParticle(sc,mesh);
+    glDisable(GL_COLOR_MATERIAL);
+  }
+
+  /* iso-surfaces */
+  if ( sc->isotyp & S_ISOSURF ) {
+    glEnable(GL_LIGHTING);
+    glEnable(GL_COLOR_MATERIAL);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    if ( sc->ilist[LTets] )  glCallList(sc->ilist[LTets]);
+    if ( sc->ilist[LHexa] )  glCallList(sc->ilist[LHexa]);
+    glDisable(GL_LIGHTING);
+    glDisable(GL_COLOR_MATERIAL);
+  }
+  
+}
+
+
+void setupView(pScene sc) {
+  pScene       slave;
+  pMesh        mesh;
+  pTransform   view;
+  pPersp       p;
+  pCamera      c;
+  int          clvol;
+
+  /* default */
+  if ( ddebug )  fprintf(stdout,"setupView\n");
+  mesh = cv.mesh[sc->idmesh];
+  view = sc->view;
+  p    = sc->persp;
+  c    = sc->camera;
+
+  /* init transformation matrix */
+  if ( sc->type & S_RESET ) {
+    glPushMatrix();
+    glLoadIdentity();
+    if ( p->pmode != CAMERA ) {
+      if ( mesh->dim == 3 || sc->mode & S_ALTITUDE ) {
+        glRotatef(-60.,1.,0.,0.);
+        glRotatef(-120.,0.,0.,1.);
+      }
+    }
+    else {
+      if ( c->vecup == X_AXIS )
+        glRotatef(90.0,0.0,0.0,1.0);
+      else if ( c->vecup == Z_AXIS )
+        glRotatef(-90.0,1.0,0.0,0.0);
+    }
+    glGetFloatv(GL_MODELVIEW_MATRIX,view->matrix);
+    glPopMatrix();
+    sc->type ^= S_RESET;
+  }
+
+  /* keep old transformation */
+  memcpy(view->oldmat,view->matrix,16*sizeof(float));
+
+  /* compute new transformation */
+  glPushMatrix();
+  glLoadIdentity();
+  if ( p->pmode != CAMERA ) {
+    glTranslatef(view->panx,view->pany,0.0);
+    if ( mesh->dim == 3 || sc->mode & S_ALTITUDE )
+      glRotatef(view->angle,view->axis[0],view->axis[1],view->axis[2]);
+    glTranslatef(-view->opanx,-view->opany,0.);
+    glMultMatrixf(view->matrix);
+    glGetFloatv(GL_MODELVIEW_MATRIX,view->matrix);
+  }
+  else if ( animate ) {
+    c->eye[0] += c->spmod*c->speed[0];
+    c->eye[1] += c->spmod*c->speed[1];
+    c->eye[2] += c->spmod*c->speed[2];
+    animateCamera();
+    reshapeScene(sc->par.xs,sc->par.ys);
+  }
+  glPopMatrix();
+
+  /* keep old translation */
+  view->opanx = view->panx;
+  view->opany = view->pany;
+
+  /* copy views */
+  if ( !animate && sc->slave > -1 ) {
+    slave = cv.scene[sc->slave];
+    memcpy(slave->view,sc->view,sizeof(struct transform));
+    memcpy(slave->camera,sc->camera,sizeof(struct camera));
+    slave->view->angle = 0.0f;
+    clvol = slave->clip->active & C_VOL;
+    memcpy(slave->clip,sc->clip,sizeof(struct clip));
+    if ( clvol )  slave->clip->active |= C_VOL;
+  }
+}
+
+
+void drawModel(pScene sc) {
+  pMesh        mesh;
+  pTransform   view;
+  pClip        clip;
+  ubyte        sstatic;
+
+  /* default */
+  mesh = cv.mesh[sc->idmesh];
+  view = sc->view;
+  clip = sc->clip;
+  if ( ddebug ) printf("\n-- redraw scene %d, mesh %d\n",sc->idwin,sc->idmesh);
+
+  glDisable(GL_LIGHTING);
+
+  /* draw clipping plane */
+  if ( clip->active & C_ON ) {
+    drawClip(sc,clip,mesh,0);
+    glClipPlane(GL_CLIP_PLANE0,clip->eqn);
+    glEnable(GL_CLIP_PLANE0);
+  }
+  else
+    glDisable(GL_CLIP_PLANE0);
+
+  /* draw object if static scene */
+  sstatic = view->mstate > 0 && clip->cliptr->mstate > 0;
+  if ( sstatic || sc->type & S_FOLLOW ) {
+    displayScene(sc,sc->mode,0);
+    if ( sc->item & S_NUMP || sc->item & S_NUMF )  listNum(sc,mesh);
+    /* draw normals */
+    if ( sc->type & S_NORMAL ) {
+      if ( !sc->nlist ) sc->nlist = drawNormals(mesh,sc);
+      glCallList(sc->nlist);
+    }
+    /* draw data */
+    if ( sstatic )  displayData(sc,mesh);
+  }
+  else if ( !(sc->item & S_BOX) )
+    drawBox(sc,mesh,0);
+
+  /* draw ridges, corners, etc. */
+  if ( (sc->item & S_GEOM) && sc->glist ) {
+    glDisable(GL_LIGHTING);
+    if ( !mesh->ne )
+      glPointSize(1);
+    else
+      glPointSize(5);
+    glDisable(GL_COLOR_MATERIAL);
+    glCallList(sc->glist);
+  }
+
+  glDisable(GL_CLIP_PLANE0);
+  if ( clip->active & C_EDIT || sc->item & S_BOX )
+    drawBox(sc,mesh,0);
+  if ( sc->item & S_AXIS )
+    drawAxis(sc,mesh->dim);
+  if ( (mesh->dim == 3 || sc->mode & S_ALTITUDE) && sc->item & S_GRID )
+    drawBase(sc,mesh);
+  if ( sc->cube->active & C_ON )
+    drawCube(sc,mesh);
+
+  sstatic |= tiling;
+  if ( sstatic && clip->active & C_ON && clip->active & C_VOL )
+    displayScene(sc,sc->mode,1);
+
+  if ( sc->picklist && !(sc->isotyp & S_PARTICLE) ) {
+    glEnable(GL_LIGHTING);
+    glEnable(GL_COLOR_MATERIAL);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glDisable(GL_POLYGON_OFFSET_FILL);
+      glCallList(sc->picklist);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    glDisable(GL_COLOR_MATERIAL);
+    glDisable(GL_LIGHTING);
+  }
+
+  /* show path, if any */
+  if ( sc->type & S_PATH && sc->path.tlist )
+    glCallList(sc->path.tlist);
+}
+
+
+void redrawMorphing(pScene sc) {
+  pMesh   mesh;
+  
+  if ( morphing ) {
+    mesh = cv.mesh[sc->idmesh];
+    if ( !morphMesh(sc,mesh) )  return;
+  }
+}
+
+
+/* animate */
+void glutIdle(void) {
+  static float timePassed = 0.0;
+  static float timeRedraw = 0.02;  /*1.0 / 50.0*/
+  float  clk,timeElaps;
+
+  clk = clock();
+  timeElaps  = (clk - timePassed) / (float)CLOCKS_PER_SEC;
+  if ( timeElaps >= timeRedraw ) {
+    timePassed = clk;
+    glutPostRedisplay();
+  }
+}
+
+
+void streamIdle(void) {
+  pScene         sc;
+  pMesh          mesh;
+  float          elp;
+  clock_t        tim;
+  static clock_t timbase= 0;
+  static float   maxtim = 0.;
+
+  sc  = cv.scene[currentScene()];
+  sc->par.cumtim += sc->par.dt;
+  sc->par.advtim  = 1;
+  if ( sc->par.cumtim > sc->par.maxtime ) {
+    sc->par.cumtim     = 0.0;
+    sc->par.cumpertime = 0.0;
+    saveimg = 0;
+    sc->isotyp &= ~S_PARTICLE;
+    glutIdleFunc(0);
+    printf("\nfin");
+  }
+  else if ( sc->par.cumpertime >= sc->par.pertime ) {
+    mesh = cv.mesh[sc->idmesh];
+    sc->par.cumpertime = 0.0;
+    if ( !animParticle(sc,mesh) ) {
+      sc->par.cumtim     = 0.0;
+      sc->par.cumpertime = 0.0;
+      saveimg = 0;
+      glutIdleFunc(0);
+      printf("\nfin");
+    }
+    else
+      glutPostRedisplay();
+  }
+  else
+    glutPostRedisplay();
+
+  return;
+
+  if ( timbase < 1 ) {
+    timbase = clock();
+    maxtim  = 0.0;
+    sc->par.advtim = 0;
+    glutPostRedisplay();
+  }
+  else {
+    tim = clock();
+    elp = (tim - timbase) / (float)CLOCKS_PER_SEC;
+    if ( elp > sc->par.dt ) {
+      timbase = tim;
+      maxtim += elp;  
+      sc->par.advtim  = 1;
+      if ( maxtim > sc->par.maxtime )
+        glutIdleFunc(0);
+    }
+    sc->par.cumtim += sc->par.dt;
+    glutPostRedisplay();
+  }
+}
+
+
+/* OpenGL callbacks */
+void redrawScene() {
+  pScene       sc,slave;
+  pTransform   view;
+  pPersp       p;
+  pCamera      c;
+  double       ndfl,ratio,top,bottom,left,right,nnear,ffar;
+
+  sc   = cv.scene[currentScene()];
+  view = sc->view;
+  p    = sc->persp;
+  c    = sc->camera;
+
+  if ( stereoMode == MONO || !hasStereo ) {
+    glDrawBuffer(GL_BACK_LEFT);
+    glClearColor(sc->par.back[0],sc->par.back[1],
+                 sc->par.back[2],sc->par.back[3]);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    gluLookAt(0.,0.,-p->depth, 0.,0.,0., 0.0,1.0,0.0);
+
+    setupView(sc);
+    glMultMatrixf(view->matrix);
+    glTranslatef(sc->cx,sc->cy,sc->cz);
+    drawModel(sc);
+    if ( sc->type & S_DECO )  redrawStatusBar(sc);
+  }
+
+  else {
+    nnear   = -p->depth - 0.5 * sc->dmax;
+    if ( nnear < 0.1 )  nnear = 0.1;
+    ffar    = -p->depth + 0.5 * sc->dmax;
+    ratio   = sc->par.xs / (double)sc->par.ys;
+    top     = nnear * tan(DTOR * 0.5 * p->fovy);
+    ndfl    = nnear / p->depth;
+    if ( sc->par.eyesep < 0.0 )
+      sc->par.eyesep = fabs(p->depth / 20.0);
+
+    /* left view */
+    glDrawBuffer(GL_BACK_LEFT);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    left  = -ratio * top + 0.5 * sc->par.eyesep * ndfl;
+    right =  ratio * top + 0.5 * sc->par.eyesep * ndfl;
+    bottom= -top;
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glFrustum(left,right,top,bottom,nnear,ffar);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    gluLookAt(-sc->par.eyesep,0.,-p->depth, 
+              sc->par.eyesep/3.0,0.,0., 
+              0.0,1.0,0.0);
+
+    setupView(sc);
+    glMultMatrixf(view->matrix);
+    glTranslatef(sc->cx,sc->cy,sc->cz);
+    drawModel(sc);
+    if ( sc->type & S_DECO )  redrawStatusBar(sc);
+
+    /* right view */
+    glDrawBuffer(GL_BACK_RIGHT);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+    left  = -ratio * top - 0.5 * sc->par.eyesep * ndfl;
+    right =  ratio * top - 0.5 * sc->par.eyesep * ndfl;
+
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    glFrustum(left,right,top,bottom,nnear,ffar);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    gluLookAt(sc->par.eyesep,0.,-p->depth, 
+              sc->par.eyesep/3.0,0.,0., 
+              0.0,1.0,0.0);
+
+    setupView(sc);
+    glMultMatrixf(view->matrix);
+    glTranslatef(sc->cx,sc->cy,sc->cz);
+    drawModel(sc);
+    if ( sc->type & S_DECO )  redrawStatusBar(sc);
+  }
+
+  /* refresh screen */
+  if ( saveimg && animate )
+    glFlush();
+  else
+    glutSwapBuffers();
+
+  if ( ddebug ) checkErrors();
+
+  if ( saveimg && !(sc->type & S_SCISSOR) )  keyFile('H',0,0);
+
+  /* redraw linked scene */
+  if ( !animate && sc->slave > -1 ) {
+    slave = cv.scene[sc->slave];
+    glutSetWindow(slave->idwin);
+    redrawScene();
+  }
+}
+
+
+/* OpenGL callbacks */
+void redrawSchnauzer() {
+  pScene  sc = cv.scene[currentScene()];
+  pMesh   mesh;
+  char   *ptr,data[256];
+
+  mesh = cv.mesh[sc->idmesh];
+  strcpy(data,mesh->name);
+  ptr = (char*)strstr(data,".mesh");
+  if ( ptr ) *ptr = '\0';
+  ptr = (char*)strstr(data,".gis");
+  if ( ptr ) *ptr = '\0';
+
+  strcat(data,".ppm");
+  redrawScene();
+  imgHard(sc,data,'H');
+
+  exit(0);
+}
+
+
+void deleteScene(pScene sc) {
+  /* default */
+  if ( ddebug) printf("deleteScene\n");
+
+  M_free(sc->view);
+  M_free(sc->clip);
+  M_free(sc->persp);
+  M_free(sc->camera);
+  M_free(sc->material);
+  M_free(sc->matsort);
+  M_free(sc);
+}
+
+
+void initGrafix(pScene sc,pMesh mesh) {
+  GLfloat  lightamb[4] = { 0.3, 0.3, 0.3, 1.0 };
+  GLfloat  lightdif[4] = { 1.0, 1.0, 1.0, 1.0 };
+  GLfloat  lightpos[4] = { 0.0, 0.0, 1.0, 0.0 };
+
+  if ( ddebug )  printf("initGrafix\n");
+  glEnable(GL_DEPTH_TEST);
+  glDepthFunc(GL_LEQUAL);
+  glPolygonOffset(1.0, 1.0 / (float)0x10000);
+  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+
+  glShadeModel(GL_SMOOTH);
+  glDisable(GL_NORMALIZE);
+  glDisable(GL_LINE_SMOOTH);
+  glDisable(GL_POINT_SMOOTH);
+  glDisable(GL_DITHER);
+  glDisable(GL_CULL_FACE);
+  if ( mesh->typ == 2 ) {
+    glEnable(GL_CULL_FACE);
+    glCullFace(GL_BACK);
+  }
+  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+
+  /* lighting */
+  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+  glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_FALSE);
+#if ( !defined(GL_VERSION_1_1) )
+  glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
+#endif
+
+  glLightfv(GL_LIGHT0,GL_DIFFUSE,lightdif);
+  glLightfv(GL_LIGHT0,GL_AMBIENT,lightamb);
+  glEnable(GL_LIGHTING);
+  if ( stereoMode != MONO ) {
+    lightpos[2] = -1.0;
+    if ( sc->par.sunpos )
+      sc->par.sunpos[2] = -fabs(sc->par.sunpos[2]);
+  }
+  if ( sc->par.sunp )
+    glLightfv(GL_LIGHT0,GL_POSITION,sc->par.sunpos);
+  else
+    glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
+  glEnable(GL_LIGHT0);
+}
+
+
+/* new scene */
+int createScene(pScene sc,int idmesh) {
+  pMesh     mesh;
+  char      data[128];
+
+  /* default */
+  mesh = cv.mesh[idmesh];
+  if ( !quiet ) fprintf(stdout,"   Computing 3D scene\n");
+
+  /* set default mode */
+  sc->idmesh = idmesh;
+  sc->par.xi = sc->par.yi = 10;
+  if ( option == SCHNAUZER ) {
+    sc->par.xs = schw;
+    sc->par.ys = schh;
+  }
+  else {
+    if ( sc->par.xs == 0 )  sc->par.xs = 600;
+    if ( sc->par.ys == 0 )  sc->par.ys = 600;
+  }
+  if ( !sc->mode )  sc->mode = HIDDEN;
+
+  sc->item   = 0;
+  sc->shrink = 1.0;
+  sc->slave  = sc->master = -1;
+  sc->picked = 0;
+  if ( mesh->nvn == 0 )  sc->type ^= S_FLAT;
+  if ( mesh->ne == 0 )   sc->item |= S_GEOM;
+
+  /* compute scene depth */
+  sc->dmax = sc->dmin= mesh->xmax - mesh->xmin;
+  sc->dmax = max(sc->dmax,mesh->ymax - mesh->ymin);
+  sc->dmin = min(sc->dmin,mesh->ymax - mesh->ymin);
+  if ( mesh->dim == 3 ) {
+    sc->dmax = max(sc->dmax,mesh->zmax - mesh->zmin);
+    sc->dmin = min(sc->dmin,mesh->zmax - mesh->zmin);
+  }
+  sc->dmax = fabs(sc->dmax);
+  sc->dmin = fabs(sc->dmin);
+  if ( !sc->par.sunp ) {
+    sc->par.sunpos[0] *= 2.0*sc->dmax;
+    sc->par.sunpos[1] *= 2.0*sc->dmax;
+    sc->par.sunpos[2] *= 2.0*sc->dmax;
+  }
+  sc->par.sunpos[3] = 1.0;
+
+  /* create window */
+  glutInitWindowSize(sc->par.xs,sc->par.ys);
+  sc->idwin = glutCreateWindow("");
+  assert(sc->idwin != 0);
+  if ( fullscreen ) {
+    glutFullScreen();
+    sc->par.xs = glutGet(GLUT_SCREEN_WIDTH);
+    sc->par.ys = glutGet(GLUT_SCREEN_HEIGHT);
+  }
+
+  /* set window name */
+  sprintf(data,"Medit - [%s] #%d",mesh->name,sc->idwin);
+  glutSetWindowTitle(data);
+  glutSetIconTitle(data);
+ 
+ /* required! to change background color */
+  glClearColor(sc->par.back[0],sc->par.back[1],
+               sc->par.back[2],sc->par.back[3]);
+
+  /* init perspective */
+  sc->persp  = initPersp(0,sc->dmax);
+  sc->camera = (pCamera)initCamera(sc,Y_AXIS);
+  if ( mesh->typ == 2 ) {
+    sc->persp->pmode = CAMERA;
+    sc->persp->depth *= 0.5;
+  }
+
+  /* create default view */
+  sc->view = (pTransform)createTransform();
+  if ( !sc->view )  return(0);
+  sc->type |= S_RESET + S_DECO;
+  sc->clip  = (pClip)createClip(sc,mesh);
+  if ( !sc->clip )  return(0);
+  sc->cube  = (pCube)createCube(sc,mesh);
+  if ( !sc->cube )  return(0);
+
+  /* create menus */
+  if ( !createMenus(sc,mesh) )  return(0);
+
+  /* assign callbacks */
+  if ( sc->type & S_SCISSOR)
+    glutDisplayFunc(scissorScene);
+  else if ( option == SCHNAUZER )
+    glutDisplayFunc(redrawSchnauzer);
+  else if ( sc->persp->pmode == CAMERA ) {
+    glutMouseFunc(mouseCamera);
+    glutMotionFunc(motionCamera);
+    glutDisplayFunc(redrawScene);
+  }
+  else {
+    glutMouseFunc(mouse);
+    glutMotionFunc(motion);
+    glutDisplayFunc(redrawScene);
+  }
+  glutReshapeFunc(reshapeScene);
+  glutKeyboardFunc(keyScene);
+  glutSpecialFunc(special);
+  glutAttachMenu(GLUT_RIGHT_BUTTON);
+
+  /* create display lists by geom type */
+  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+  doLists(sc,mesh);
+  sc->glist = geomList(sc,mesh);
+  sc->type |= S_FOLLOW;
+
+  /* local stack */
+  if ( !pilmat ) {
+    pilmat = (int*)calloc(sc->par.nbmat+2,sizeof(int));
+    if ( !pilmat ) return(0);
+  }
+
+  /* color list */
+  setupPalette(sc,mesh);
+  sc->stream = NULL;
+
+  initGrafix(sc,mesh);
+  return(1);
+}
diff --git a/src/medit/scissor.c b/src/medit/scissor.c
new file mode 100644
index 0000000..863be6d
--- /dev/null
+++ b/src/medit/scissor.c
@@ -0,0 +1,113 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+void scissorScene() {
+  pScene      sc;
+  pMesh       mesh;
+  pPersp      p;
+  pTransform  view;
+  int         width,height;
+
+  /* default */
+  if ( ddebug ) printf("enable scissoring\n");
+  sc   = cv.scene[currentScene()];
+  mesh = cv.mesh[sc->idmesh];
+  view = sc->view;
+  p    = sc->persp; 
+
+  /* subdivide main window */
+  glViewport(0,0,sc->par.xs,sc->par.ys);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluOrtho2D(0,sc->par.xs,0,sc->par.ys);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glClearColor(sc->par.back[0],sc->par.back[1],sc->par.back[2],sc->par.back[3]);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  /* split window */
+  glDisable(GL_LIGHTING);
+  glColor4fv(sc->par.line);
+  glBegin(GL_LINES);
+  glVertex2i(sc->par.xs/2,0);
+  glVertex2i(sc->par.xs/2,sc->par.ys);
+  glVertex2i(0,sc->par.ys/2);
+  glVertex2i(sc->par.xs,sc->par.ys/2);
+  glEnd();
+  glEnable(GL_LIGHTING);
+
+  width  = (sc->par.xs + 1)/2;
+  height = (sc->par.ys + 1)/2;
+
+  glDisable(GL_LIGHTING);
+  glColor4fv(sc->par.line);
+  output2(5,sc->par.ys/2+5,"Top");
+  output2(5,5,"Front");
+  output2(sc->par.xs/2+5,5,"Right");
+
+  glEnable(GL_SCISSOR_TEST);
+
+  /* draw top right : normal */
+  glViewport(width,height,width,height);
+  glScissor(width,height,width,height);
+  farclip(1);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt(0.,0.,-p->depth, 0.,0.,0., 0.0,1.0,0.0);
+  setupView(sc);
+  glMultMatrixf(view->matrix);
+  glTranslatef(sc->cx,sc->cy,sc->cz);
+  drawModel(sc);
+  if ( sc->type & S_DECO )  redrawStatusBar(sc);
+
+  /* draw top left : top view */
+  glViewport(0,height,width,height);
+  glScissor(0,height,width,height);
+  farclip(1);  
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt(0.,0.,-p->depth, 0.,0.,0., 0.0,1.0,0.0);
+  setupView(sc);
+  glTranslatef(sc->cx,sc->cy,sc->cz);
+  glRotatef(-90,0.0,0.0,1.0);
+  glTranslatef(view->opanx,0.,0.);
+  drawModel(sc);
+
+  /* draw bottom left : front */
+  glViewport(0,0,width,height);
+  glScissor(0,0,width,height);
+  farclip(1);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt(0.,0.,-p->depth, 0.,0.,0., 0.0,1.0,0.0);
+  setupView(sc);
+  glTranslatef(sc->cx,sc->cy,sc->cz);
+  glRotatef(-90.0,1.0,0.0,0.0);
+  glTranslatef(view->opanx,0.,0.);
+  drawModel(sc);
+
+  /* draw bottom right : right */
+  glViewport(width,0,width,height);
+  glScissor(width,0,width,height);
+  farclip(1);
+
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  gluLookAt(0.,0.,-p->depth, 0.,0.,0., 0.0,1.0,0.0);
+  setupView(sc);
+  glRotatef(-90.0,1.0,0.0,0.0);
+  glRotatef(-90.0,0.0,0.0,1.0);
+  glTranslatef(0.,view->opany,0.);
+  drawModel(sc);
+
+  glutSwapBuffers();
+  glDisable(GL_SCISSOR_TEST);
+  glViewport(0,0,sc->par.xs,sc->par.ys);
+ 
+  if ( saveimg ) keyFile('H',0,0);
+}
diff --git a/src/medit/sftcpy.c b/src/medit/sftcpy.c
new file mode 100644
index 0000000..fcfa3e3
--- /dev/null
+++ b/src/medit/sftcpy.c
@@ -0,0 +1,329 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+/* OpenGL's GL_3D_COLOR feedback vertex format */
+typedef struct Feedback3Dcolor {
+  GLfloat   x,y,z;
+  GLfloat   r,g,b,a;
+} Feedback3Dcolor;
+
+typedef struct Token {
+  GLfloat   depth;
+  GLfloat  *ptr;
+} Token;
+
+
+static int compare(const void *a, const void *b) {
+  Token   *p1 = (Token *)a;
+  Token   *p2 = (Token *)b;
+  GLfloat  diff = p2->depth - p1->depth;
+
+  if ( diff > 0.0f )
+    return 1;
+  else if ( diff < 0.0f )
+    return -1;
+  else
+    return 0;
+}
+
+
+void headps(FILE *file) {
+  GLfloat  color[4],viewport[4];
+  GLfloat  linewidth = 0.1;
+  GLfloat  pointsize;
+ 
+
+  glGetFloatv(GL_VIEWPORT,viewport);
+  glGetFloatv(GL_COLOR_CLEAR_VALUE,color);
+  glGetFloatv(GL_LINE_WIDTH,&linewidth);
+  glGetFloatv(GL_POINT_SIZE,&pointsize);
+
+  /* write EPS header */
+  fprintf(file,"%%!PS-Adobe-2.0 EPSF-2.0\n");
+  fprintf(file,"%%LanguageLevel: 1\n");
+  fprintf(file,"%%%%Creator: Medit (via OpenGL feedback)\n");
+  fprintf(file,"%%%%Pages: (atend)\n");
+  fprintf(file,"%%%%BoundingBox: %g %g %g %g\n",
+	  viewport[0],viewport[1],viewport[2],viewport[3]);
+  fprintf(file,"%%EndComments\n\n");
+
+  /* define macros */
+  /* fprintf(file,"100 dict begin\n"); */
+  fprintf(file,"%%%%BeginProlog\n");
+  fprintf(file,"/sgm  {moveto lineto  stroke } def\n");  
+  fprintf(file,"/stg {setgray} def\n");
+  fprintf(file,"/stc {setrgbcolor} def\n");
+  fprintf(file,"/mt  {moveto} def\n");
+  fprintf(file,"/lt  {lineto} def\n");
+  fprintf(file,"/dc {currentrgbcolor mark} def\n");
+  fprintf(file,"/fc {stc newpath moveto\n");
+  fprintf(file,"     counttomark 2 idiv {lineto} repeat\n");
+  fprintf(file,"     closepath fill cleartomark  stc} def\n");
+  fprintf(file,"%%%%EndProlog\n\n");
+
+  fprintf(file,"gsave\n\n");
+
+  /* set background color */
+  fprintf(file,"%g %g %g setrgbcolor\n",color[0],color[1],color[2]);
+  fprintf(file,"%g %g %g %g rectfill\n\n",
+	  viewport[0],viewport[1],viewport[2],viewport[3]);
+  fprintf(file, "%g setlinewidth\n\n",0.01*linewidth);
+}
+
+void tailps(FILE *file) {
+  /* write EPS tail */
+  fprintf(file,"\n");
+  fprintf(file,"%%%%Trailer\n");
+  fprintf(file,"%%%%Pages:        1\n");
+  fprintf(file,"grestore\n\n");
+  fprintf(file,"showpage\n\n");
+  fclose(file);
+}
+
+int coreps(FILE *file,GLsizei size,GLfloat *buffer) {
+  Token           *ttoken;
+  pScene           sc;
+  Feedback3Dcolor *v;
+  GLfloat         *ptr;
+  int              i,k,idw,token,nit,nbv,sorting=TRUE;
+
+  /* default */
+  if ( ddebug ) printf("dump EPS file\n");
+  idw = currentScene();
+  sc = cv.scene[idw];
+
+  /* Count tokens */
+  nit = 0;
+  ptr = buffer;
+  while ( *ptr && ptr < buffer+size ) {
+    token = (int)*ptr;
+    switch (token) {
+    case GL_LINE_TOKEN:
+    case GL_LINE_RESET_TOKEN:
+      nit++;
+      ptr += 14;
+      break;
+
+    case GL_POLYGON_TOKEN:
+      nit++;
+      ++ptr;
+      nbv = *ptr;
+      ptr += (7 * nbv);
+      break;
+
+    case GL_POINT_TOKEN:
+      ptr += 7;
+      break;
+
+    case GL_BITMAP_TOKEN:
+      puts("BITMAP");
+      nit++;
+      ++ptr;
+      nbv = *ptr;
+      printf("nbv = %d\n",nbv);
+      break;
+
+    default:
+      fprintf(stdout,"  Unrecognized token %d\n",token);
+      break;
+    }
+    ptr++;
+  }
+
+  if ( ddebug )
+    printf("size = %d  ptr = %p  buffer = %p  -> size = %d\n",
+	   size,ptr,buffer,ptr-buffer);
+
+  /* allocate mem to store tokens */
+  if ( ddebug ) printf("%d tokens found\n",nit);
+  ttoken = (Token *)malloc((1+nit)*sizeof(struct Token));
+  assert(ttoken);
+
+  /* store tokens */
+  nit = 0;
+  ptr = buffer;
+  while ( *ptr && ptr < buffer+size ) {
+    ttoken[++nit].ptr = ptr;
+    token = (int)*ptr;
+    ptr++;
+    switch (token) {
+    case GL_LINE_TOKEN:
+    case GL_LINE_RESET_TOKEN:
+      v = (Feedback3Dcolor *)ptr;
+      ttoken[nit].depth = 0.5*(v[0].z+v[1].z);
+      ptr += 14;
+      break;
+
+    case GL_POLYGON_TOKEN:
+      nbv = *ptr;
+      ptr++;
+      v = (Feedback3Dcolor *)ptr;
+      ttoken[nit].depth = v[0].z;
+      for (k=1; k<nbv; k++)
+	ttoken[nit].depth += v[k].z;
+      ttoken[nit].depth /= nbv;
+      ptr += (7 * nbv);
+      break;
+
+    case GL_POINT_TOKEN:
+      ptr += 7;
+      nit--;
+      break;
+
+    default:
+      ptr += 4;
+      break;
+    }
+  }
+
+  /* Sort the primitives according to depth */
+  if ( sc->mode == WIRE || sc->mode == WIRE+S_MATERIAL )
+    sorting = FALSE;
+  if ( ddebug ) printf("prim = %d  size = %d, %d\n",nit,ptr-buffer-1,size);
+
+  if ( sorting == TRUE ) {
+    if ( ddebug ) printf("start sorting %d tokens...\n",nit);
+    qsort(ttoken+1,nit,sizeof(struct Token),compare);
+    if ( ddebug ) printf("end sorting\n");
+  }
+
+  /* write tokens in EPS file */
+  for (k=1; k<=nit; k++) {
+    ptr = ttoken[k].ptr;
+    if ( *ptr == 0 )  continue;
+    token = *ptr;
+    ptr++;
+    switch(token) {
+    case GL_LINE_RESET_TOKEN:
+    case GL_LINE_TOKEN:
+      v = (Feedback3Dcolor *)ptr;
+      fprintf(file,"%g %g %g stc\n",v[0].r,v[0].g,v[0].b);
+      fprintf(file,"%g %g %g %g sgm\n",v[0].x,v[0].y,v[1].x,v[1].y);
+      ptr += 14;
+      break;
+
+    case GL_POLYGON_TOKEN:
+      nbv = *ptr;
+      ptr++;
+      v = (Feedback3Dcolor *)ptr;
+
+      /* draw filled polygon */
+      if ( sorting == TRUE ) {
+	/* fprintf(file,"1. stg\n"); */
+	fprintf(file, "dc ");
+	for (i=0; i<nbv; i++)
+	  fprintf(file," %g %g",v[i].x,v[i].y);
+	fprintf(file,"  %g %g %g fc\n",v[0].r,v[0].g,v[0].b);
+      }
+
+      /* draw polygon border */
+      if ( sc->mode & S_BDRY ) {
+	fprintf(file,"0. stg\n");
+	for (i=0; i<nbv-1; i++)
+	  fprintf(file,"%g %g %g %g sgm\n",v[i].x,v[i].y,v[i+1].x,v[i+1].y);
+	fprintf(file,"%g %g %g %g sgm\n\n",v[nbv-1].x,v[nbv-1].y,v[0].x,v[0].y);
+      }
+
+      ptr += (7*nbv);
+      break;
+
+    case GL_POINT_TOKEN:
+      v = (Feedback3Dcolor *)ptr;
+      ptr += 7;
+      break; 
+    default:
+      printf("problem: token %d\n",token);
+    }
+  }
+
+  return(1);
+}
+
+
+int sftcpy(pScene sc,pMesh mesh) {
+  FILE     *file;
+  GLfloat  *fbbuffer;
+  GLint     nvalues;
+  GLsizei   size;
+  char     *ptr,data[128];
+  static int nfree=0;
+
+  /* default */
+  if ( ddebug ) printf("soft copy\n");
+
+  /* get file name */
+  strcpy(data,mesh->name);
+  ptr = (char*)strstr(data,".mesh");
+  if ( ptr ) *ptr = '\0';
+  nfree = filnum(data,nfree,"ps");
+  if ( nfree == -1 )  return(0);
+
+  /* open PS file */
+  sprintf(data,"%s.%.3d.ps",data,nfree);
+  file = fopen(data,"w");
+  if ( !file ) {
+    fprintf(stdout,"  Unable to open %s\n",data);
+    return(0);
+  }
+
+  /* size for feedback buffer */
+  size    =  0;
+  nvalues = -1;
+  do {
+    size += 1024*1024;
+    fbbuffer = (GLfloat *)calloc(1+size,sizeof(GLfloat));
+    if ( !fbbuffer ) {
+      return(0);
+    }
+    if ( ddebug ) printf("feedback pointer = %p\n",fbbuffer);
+
+    /* draw scene in back buffer */
+    glFeedbackBuffer(size,GL_3D_COLOR,fbbuffer);
+    (void)glRenderMode(GL_FEEDBACK);
+/*
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    gluLookAt(0.,0.,-sc->persp->depth, 0.,0.,0., 0.0,1.0,0.0);
+
+    setupView(sc);
+    glMultMatrixf(sc->view->matrix);
+    glTranslatef(sc->cx,sc->cy,sc->cz);
+*/
+    drawModel(sc);
+    if ( sc->type & S_DECO )  redrawStatusBar(sc);
+
+    /*drawModel(sc);*/
+    nvalues = (GLint)glRenderMode(GL_RENDER);
+    if ( nvalues < 0 )
+      free(fbbuffer);
+  }
+  while ( nvalues < 0 );
+
+  if ( nvalues < 1 ) {
+    return(0);
+  }
+  else if ( ddebug )  printf("nvalues = %d  size = %d\n",nvalues,size);
+  
+  /* write EPS file */
+  glutSetCursor(GLUT_CURSOR_WAIT);
+
+  headps(file);
+  coreps(file,size,fbbuffer);
+  tailps(file);
+
+  if ( ddebug ) fprintf(stdout,"%s written\n",data);
+  glutSetCursor(GLUT_CURSOR_INHERIT);
+
+  return(1);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/sproto.h b/src/medit/sproto.h
new file mode 100644
index 0000000..920b25c
--- /dev/null
+++ b/src/medit/sproto.h
@@ -0,0 +1,300 @@
+/* animat.c */
+int    loadNextMesh(pMesh ,int ,int );
+int    animat();
+int    playAnim(pScene ,pMesh ,int ,int );
+void   glutIdle(void);
+
+/* camera.c */
+double  Azimuth(pCamera );
+double  Elevation(pCamera );
+void    updateSun(pScene ,pCamera );
+void    updateCamera(pScene ,pCamera ,double ,double );
+pCamera initCamera(pScene ,int );
+
+/* clip.c */
+void   updateClip(pClip ,pMesh );
+void   clipVertices(pMesh ,pScene ,pClip );
+void   invertClip(pScene sc,pClip );
+void   drawClip(pScene ,pClip ,pMesh ,GLboolean );
+void   copyClip(pClip );
+int    pasteClip(pClip );
+void   resetClip(pScene ,pClip ,pMesh );
+pClip  createClip(pScene ,pMesh );
+
+void   updateCube(pCube ,pMesh );
+pCube  createCube(pScene ,pMesh );
+
+/* clipvol.c */
+GLuint capTetra(pMesh );
+GLuint capTetraMap(pMesh );
+GLuint capTetraIso(pMesh );
+
+/* critip.c */
+GLuint listCritPoint(pScene ,pMesh );
+
+/* dlists.c */
+GLuint  listTria(pScene ,pMesh );
+GLuint  listQuad(pScene ,pMesh );
+GLuint  listTetra(pScene ,pMesh ,ubyte );
+GLuint  listHexa(pScene ,pMesh ,ubyte );
+
+/* eigenv.c */
+int    eigenv(int sym,double mat[6],double lambda[3],double v[3][3]);
+
+/* geometry.c */
+GLuint geomList(pScene ,pMesh );
+
+/* gisfil.c */
+int loadGIS(pMesh );
+
+/* hash.c */
+int hashTria(pMesh );
+int hashTetra(pMesh );
+
+/* image.c */
+PPMimage *loadPPM(const char *imgname,int *type);
+int  savePPM(const char *imgname,pPPMimage img,int typimg);
+void saveEPS(pScene sc,const char *imgname,pPPMimage pixels);
+int  imgHard(pScene sc,char *data,char key);
+
+/* input/output */
+int    EatLine(FILE  *in);
+int    inmsh2(pMesh mesh);
+int    bbfile(pMesh );
+int    loadMesh(pMesh );
+int    saveMesh(pScene ,pMesh ,char *,ubyte );
+int    loadSol(pMesh mesh,char *filename,int numsol);
+int    loadMesh_popen(pMesh); //pour popen
+
+/* ilists.c */
+GLuint listTriaIso(pScene ,pMesh );
+GLuint listQuadIso(pScene ,pMesh );
+GLuint listTetraIso(pScene ,pMesh );
+
+/* items.c */
+void   drawAxis(pScene ,int );
+void   drawBox(pScene ,pMesh ,int );
+void   drawCube(pScene ,pMesh );
+void   drawGrid(pScene ,pMesh );
+void   rubberBand(pPersp );
+void   drawBase(pScene ,pMesh );
+void   drawIso(pScene );
+
+/* keyboard.c */
+void   specCamera(pScene ,int );
+void   special(int ,int ,int );
+void   keyScene(unsigned char ,int ,int );
+
+/* listnum.c */
+void   updatePoints(pScene sc,pMesh mesh,int refmat);
+void   listNum(pScene sc,pMesh mesh);
+
+/* material.c */
+void   matInit(pScene );
+void   matSort(pScene );
+int    matRef(pScene ,int );
+void   matReshape(int ,int );
+void   matsubReshape(int ,int );
+void   matsubDisplay();
+void   matDisplay();
+void   matMouse(int ,int ,int ,int );
+void   matKeyboard(unsigned char ,int ,int );
+void   matEdit(pScene );
+
+/* medit.c */
+int    medit0();
+int    medit1();
+
+/* menus.c */
+void   doLists(pScene ,pMesh );
+void   doMapLists(pScene ,pMesh ,int );
+void   doIsoLists(pScene ,pMesh ,int );
+void   keyFile(unsigned char ,int ,int );
+void   menuFile(int );
+void   keyItem(unsigned char ,int ,int );
+void   menuItem(int );
+void   keyAnim(unsigned char ,int ,int );
+void   menuAnim(int );
+void   keyTrajet(unsigned char ,int ,int );
+void   menuTrajet(int );
+void   keyMode(unsigned char ,int ,int );
+void   menuMode(int );
+void   menuScene(int ); 
+void   keyView(unsigned char ,int ,int );
+void   menuView(int );
+void   keyColor(unsigned char ,int ,int );
+void   menuColor(int );
+void   keyClip(unsigned char ,int ,int );
+void   menuClip(int );
+void   keyFeature(unsigned char ,int ,int );
+void   menuFeature(int );
+void   menuImage(int );
+void   keyMetric(unsigned char key,int x,int y);
+int    createMenus(pScene ,pMesh );
+GLuint pickingScene(pScene sc,int x,int y,int ident);
+ 
+/* mesh.c */
+void   meshInfo(pMesh );
+int    meshSurf(pMesh );
+void   meshCoord(pMesh ,int );
+void   meshBox(pMesh mesh,int bb);
+void   meshRef(pScene sc,pMesh mesh);
+int    meshUpdate(pScene sc,pMesh mesh);
+
+/* mlists.c */
+GLuint  listTriaMap(pScene ,pMesh );
+GLuint  listQuadMap(pScene ,pMesh );
+GLuint  listTetraMap(pScene ,pMesh ,ubyte );
+GLuint  listHexaMap(pScene ,pMesh ,ubyte );
+void    cutTriangle(pScene ,triangle );
+GLuint  alt2dList(pScene ,pMesh ,int ,float ,float );
+void    setupPalette(pScene ,pMesh );
+GLuint  drawPalette(pScene );
+
+/* morphing */
+int    morphMesh(pScene sc,pMesh mesh1);
+int    modeMorphing();
+ 
+/* mouse.c */
+void   mouse(int button,int state,int x,int y);
+void   motion(int x,int y);
+void   redrawOverlay(int stretchX,int stretchY);
+void   motionCamera(int x,int y);
+void   mouseCamera(int button,int state,int x,int y);
+void   animateCamera();
+
+/* normal.c */
+GLuint drawNormals(pMesh mesh,pScene sc);
+
+/* outmsh.c */
+int    outmsh(pScene ,pMesh ,char *name,ubyte clipon);
+
+/* parsar.c */
+int    parsar(int argc,char *argv[]);
+
+/* parsop.c */
+int    saveMeditFile(char *,pScene ); 
+void   iniopt(pScene ,pMesh );
+int    parsop(pScene ,pMesh );
+
+/* particle.c */
+int createParticle(pScene ,pMesh );
+
+/* path.c */
+int    pathAdd(pScene ,int, int);
+GLuint pathList(pScene );
+int    pathLoad(char *data,pScene );
+int    pathSave(char *file,pScene );
+void   pathFollow(pScene );
+
+/* persp.c */
+void   setPersp(pScene ,pPersp ,int );
+pPersp initPersp(pPersp ,float );
+
+/* picking.c */
+GLuint pickingList(pScene ,int ,int );
+GLuint pickingPoint(pScene sc,int x,int y);
+GLuint pickItem(pMesh ,pScene ,int );
+ 
+/* prierr.c */
+void   prierr(int typerr,int indice);
+
+/* psfile.c */
+void writeEPSheader(FILE *,char *,char ,int ,int ,float ,float);
+void writeEPStrailer(FILE *);
+void writeEPSRow(FILE *,char ,ubyte *,int ,ubyte );
+
+/* scene.c */
+int    currentScene();
+void   checkErrors(void);
+void   oglerr(GLenum error);
+void   farclip(GLboolean );
+void   reshapeScene(int width,int height);
+void   setupView(pScene sc);
+void   drawBackTex(pScene sc);
+void   drawModel(pScene sc);  
+void   drawScene(pScene );
+void   redrawScene();
+void   deleteScene(pScene sc);
+void   initGrafix(pScene sc,pMesh mesh);
+int    createScene(pScene sc,int idmesh);
+void   streamIdle();
+
+/* scissor.c */
+void   scissorScene();
+
+/* status.c */
+void reshapeStatusBar(pScene sc,int width,int height);
+void redrawStatusBar(pScene sc);
+void mouseStatus(int button,int state,int x,int y);
+
+/* stream.c */
+double  sizeTetra(pMesh ,int );
+double  sizeHexa(pMesh ,int );
+double  sizeTria(pMesh ,int );
+int     locateTria(pMesh mesh,int nsdep,int base,float *p,double *cb);
+int     locateTetra(pMesh mesh,int nsdep,int base,float *p,double *cb);
+int     inTria(pMesh ,int ,float *,double *);
+int     listTetraStream(pScene ,pMesh ,float *,int );
+int     listHexaStream(pScene ,pMesh ,float *,int );
+int     listTriaStream(pScene ,pMesh ,float *);
+pStream createStream(pScene ,pMesh );
+int     streamRefTria(pScene sc,pMesh mesh);
+int     streamRefQuad(pScene sc,pMesh mesh);
+int     streamRefPoint(pScene sc,pMesh mesh);
+int     listSaddleStream(pScene sc,pMesh mesh,int depart,
+                         float *pp,float *vv,double lambda);
+int     nxtPoint3D(pMesh mesh,int nsdep,float *p,float step,double *v);
+int     nxtPoint2D(pMesh mesh,int nsdep,float *p,float step,double *v);
+double  field2DInterp(pMesh mesh,int iel,double *cb,double *v);
+double  vector3DInterp(pMesh mesh,pPoint pt[4],double *cb,double *v);
+double  field3DInterp(pMesh mesh,int iel,double *cb,double *v);
+double  sizeTria(pMesh mesh,int k);
+double  sizeQuad(pMesh mesh,int k);
+double  sizeTetra(pMesh mesh,int k);
+
+
+/* tensor.c */
+GLuint listPointVector(pMesh ,ubyte );
+
+/* texture.c */
+pPPMimage texDistortion(pPPMimage );
+
+/* tiles.c */
+int   imgTiling(pScene sc,char *data,char key);
+
+/* transform.c */
+void   resetTransform(pTransform );
+pTransform createTransform();
+
+/* util.c */
+void   setFont(char* name,int size);
+void   drwstr(GLuint x,GLuint y,char* format, ...);
+void   output2(GLfloat x,GLfloat y,char *format,...); 
+void   output3(GLfloat x,GLfloat y,GLfloat z,char *format,...);
+void   hsvrgb(double *hsv,double *rgb);
+void   transformPoint(double u[4],float v[4],float m[16]);
+void   transformPointd(double u[4],double v[4],double m[16]);
+void   transformVector(float u[4],float v[4],float m[16]); 
+void   multMatrix(GLfloat *p,GLfloat *a,GLfloat *b);
+void   rotateMatrix(GLfloat angle,GLfloat x,GLfloat y,GLfloat z,GLfloat rm[16]);
+int    invertMatrix(float src[16],float inverse[16]);
+int    filnum(char *data,int numdep,char *ext);
+
+/* vector.c */
+void   drawVector2D(float p[2],double u[2],double scal);
+void   drawVector3D(float p[3],double u[3],double scal);
+GLuint listTria2dVector(pMesh mesh);
+GLuint listTria3dVector(pMesh mesh);
+GLuint listClipTetraVector(pMesh mesh);
+GLuint listClipHexaVector(pMesh mesh);
+
+/* view.c */
+void   copyView(pTransform view,pCamera cam,pPersp persp);
+int    pasteView(pTransform view,pCamera cam,pPersp persp);
+int    linkView(pScene sc1);
+void   unlinkView(pScene sc1);
+
+/* zaldy.c */
+int    zaldy1(pMesh mesh);
+int    zaldy2(pMesh mesh);
diff --git a/src/medit/status.c b/src/medit/status.c
new file mode 100644
index 0000000..0eb4ed6
--- /dev/null
+++ b/src/medit/status.c
@@ -0,0 +1,182 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+extern void  drawHUD(pScene );
+extern int   refmat,imstep;
+
+
+void initTexture(void) {
+  PPMimage *imgtex;
+  int       typimg;
+  ubyte     iquiet;
+  GLuint    texname;
+
+  iquiet = quiet;
+  quiet  = 1;
+  imgtex = loadPPM("Lions.ppm",&typimg);
+  quiet  = iquiet;
+  if ( !imgtex )  return;
+
+  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
+  glGenTextures(1,&texname);
+  glBindTexture(GL_TEXTURE_2D,texname);
+
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+  glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,imgtex->sizeX,imgtex->sizeY,
+               0,GL_RGB,GL_UNSIGNED_BYTE,imgtex->data);
+  free(imgtex);
+}
+
+void backTexture(pScene sc) {
+  glEnable(GL_TEXTURE_2D);
+  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glPushAttrib(GL_ENABLE_BIT);
+  glEnable(GL_TEXTURE_2D);
+  glDisable(GL_LIGHTING);
+  glBegin(GL_QUADS);
+    glTexCoord2f(0.0f, 0.0f);
+    glVertex2f(0.0,0.0);
+    
+    glTexCoord2f(sc->par.xs,0.0);
+    glVertex2f(sc->par.xs,0.0);
+    
+    glTexCoord2f(sc->par.xs,sc->par.ys);
+    glVertex2f(sc->par.xs,sc->par.ys);
+    
+    glTexCoord2f(0.0,sc->par.ys);
+    glVertex2f(0.0,sc->par.ys);
+  glEnd();
+  glPopAttrib();
+
+  glDisable(GL_TEXTURE_2D);
+}
+
+
+void redrawStatusBar(pScene sc) {
+  pClip  clip = sc->clip;
+  pMesh  mesh = cv.mesh[sc->idmesh];
+  double dd;
+  char   buf[128];
+  float  frame,elpms;
+  static float fps=0.0,lastfr = 0.0;
+  static int   nfr = 0,pps = 0;
+  
+  if ( sc->par.xs < 100 )  return;
+  if ( ddebug )  fprintf(stdout,"redrawStatusBar\n");
+  glDisable(GL_DEPTH_TEST);
+  glDisable(GL_LIGHTING);
+
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  gluOrtho2D(1.,sc->par.xs,1.,sc->par.ys);
+
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+
+  /* other info */
+  glColor3f(1.0-sc->par.back[0],1.0-sc->par.back[1],1.0-sc->par.back[2]);
+  if ( animate && !(sc->isotyp & S_PARTICLE) ) {
+    nfr++;
+    frame = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
+    elpms = frame - lastfr;
+    if ( elpms > 0.999 ) {
+      fps = nfr / elpms;
+      if ( mesh->nt+mesh->nq )
+        pps  = fps * (mesh->nt+mesh->nq);
+      else if (mesh->ntet+mesh->nhex )
+        pps  = fps * (mesh->ntet+mesh->nhex);
+      else
+        pps  = fps * mesh->np;
+      nfr = 0;
+      lastfr = frame;
+    }
+    output2(15,8,"Fps: %6.2f Pps: %8d",fps,pps);
+  }
+  if ( option == MORPHING )
+    output2(15,28,"%d",abs(imstep));
+
+  if ( sc->isotyp & S_STREAML && sc->par.maxtime < FLT_MAX )
+    output2(15,8,"t= %8.3f",sc->par.cumtim);
+  else if ( sc->isotyp & S_PARTICLE )
+    output2(15,8,"t= %8.3f",sc->par.cumtim);
+  
+  /* clip eqn */
+  if ( clip->active & C_ON && !(clip->active & C_HIDE) ) {
+    sprintf(buf,"Eqn: ");
+    if ( fabs(clip->eqn[0]) > EPS )
+      sprintf(buf,"%s %+.2gx",buf,clip->eqn[0]);
+    if ( fabs(clip->eqn[1]) > EPS )
+      sprintf(buf,"%s %+.2gy",buf,clip->eqn[1]);
+    if ( fabs(clip->eqn[2]) > EPS )  
+      sprintf(buf,"%s %+.2gz",buf,clip->eqn[2]);
+    dd = clip->eqn[3]-clip->eqn[0]*mesh->xtra \
+       - clip->eqn[1]*mesh->ytra-clip->eqn[2]*mesh->ztra;
+    if ( dd ) sprintf(buf,"%s %+.2g",buf,dd);
+    if ( sc->par.xs > 180 )
+      output2(150,8,"%s = 0",buf);
+  }
+
+  if ( sc->picklist && sc->par.xs > 390 && !sc->isotyp & S_PARTICLE )
+    output2(350,8,"%15s",sc->material[refmat].name);
+
+  if ( sc->persp->pmode == PERSPECTIVE && sc->item & S_PALETTE )
+    drawPalette(sc);
+
+  if ( sc->persp->pmode == CAMERA )  drawHUD(sc);
+  glPopMatrix();
+
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glEnable(GL_LIGHTING);
+  glEnable(GL_DEPTH_TEST);
+}
+
+void mouseStatus(int button,int state,int x,int y) {
+  pScene      sc   = cv.scene[currentScene()];
+  pTransform  view = sc->view;
+  ubyte       axis = X_AXIS;
+
+  /* default */
+  if ( ddebug ) printf("control mouse %d\n",state);
+  
+  if ( button == GLUT_LEFT_BUTTON ) {
+    if ( x < 16 && x > 5 )        axis = X_AXIS;
+    else if ( x < 26 && x > 15 )  axis = Y_AXIS;
+    else if ( x < 36 && x > 25 )  axis = Z_AXIS;
+    switch (axis) {
+    case X_AXIS:
+      view->angle = 90.0;
+      break;
+    case Y_AXIS:
+      view->angle   = 90.0;
+      view->axis[0] = 1.0;
+      view->axis[1] = view->axis[2] = 0.0f;
+      break;
+    case Z_AXIS:
+      view->angle   = 90.0;
+      view->axis[1] = 0.0f;
+      view->axis[0] = view->axis[2] = 0.0f;
+      break;
+    }
+  }
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/stream.c b/src/medit/stream.c
new file mode 100644
index 0000000..64acb3f
--- /dev/null
+++ b/src/medit/stream.c
@@ -0,0 +1,1961 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define MAX_PTS   100000
+#define MAX_CPT   5000
+#define MAX_LST   1024
+
+#define COS175  -0.996194698
+#define COS178  -0.99939083
+#define HSIZ     0.03
+#define EPST    -1.e-14
+#define EPSR     1.e+14
+
+
+extern int       reftype,refitem;
+extern GLfloat   altcoef;
+int    nbar=0;
+enum   {Euler=1,RK4=2};
+
+
+/* find tetra containg p, starting nsdep */
+int locateTetra(pMesh mesh,int nsdep,int base,float *p,double *cb) {
+  pTetra   pt;
+  pPoint   p0,p1,p2,p3;
+  double   bx,by,bz,cx,cy,cz,dx,dy,dz,vx,vy,vz,apx,apy,apz;
+  double   epsra,vol1,vol2,vol3,vol4,dd; 
+  int     *adj,iadr,it,nsfin;
+
+  it    = 0;
+  nsfin = nsdep;
+  /*  printf("locateTetra: searching for %f %f %f\n",p[0],p[1],p[2]);*/
+  do {
+    if ( !nsfin )  return(0);
+    pt = &mesh->tetra[nsfin];
+    if ( !pt->v[0] )  return(0);
+    if ( pt->mark == base )  return(0);
+    pt->mark = base;
+    iadr = 4*(nsfin-1)+1;
+    adj  = &mesh->adja[iadr];
+    p0 = &mesh->point[pt->v[0]];
+    p1 = &mesh->point[pt->v[1]];
+    p2 = &mesh->point[pt->v[2]];
+    p3 = &mesh->point[pt->v[3]];
+
+    /* barycentric */
+    bx  = p1->c[0] - p0->c[0];
+    by  = p1->c[1] - p0->c[1];
+    bz  = p1->c[2] - p0->c[2];
+    cx  = p2->c[0] - p0->c[0];
+    cy  = p2->c[1] - p0->c[1];
+    cz  = p2->c[2] - p0->c[2];
+    dx  = p3->c[0] - p0->c[0];
+    dy  = p3->c[1] - p0->c[1];
+    dz  = p3->c[2] - p0->c[2];
+
+    /* test volume */
+    vx  = cy*dz - cz*dy;
+    vy  = cz*dx - cx*dz;
+    vz  = cx*dy - cy*dx;
+
+    epsra = EPST*(bx*vx + by*vy + bz*vz);
+    apx = p[0] - p0->c[0];
+    apy = p[1] - p0->c[1];
+    apz = p[2] - p0->c[2];
+
+    /* p in 2 */
+    vol2  = apx*vx + apy*vy + apz*vz;
+    if ( epsra > vol2 ) {
+      nsfin = adj[1];
+      continue;
+    }
+
+    /* p in 3 */
+    vx  = by*apz - bz*apy;
+    vy  = bz*apx - bx*apz;
+    vz  = bx*apy - by*apx;
+    vol3 = dx*vx + dy*vy + dz*vz;
+    if ( epsra > vol3 ) {
+      nsfin = adj[2];
+      continue;
+    }
+    
+    /* p in 4 */
+    vol4 = -cx*vx - cy*vy - cz*vz;
+    if ( epsra > vol4 ) {
+      nsfin = adj[3];
+      continue;
+    }
+    
+    /* p in 1 */
+    vol1 = -epsra * EPSR - vol2 - vol3 - vol4;
+    if ( epsra > vol1 ) {
+      nsfin = adj[0];
+      continue;
+    }
+
+    dd = vol1+vol2+vol3+vol4;
+    if ( dd != 0.0 )  dd = 1.0 / dd;
+    cb[0] = vol1 * dd;
+    cb[1] = vol2 * dd;
+    cb[2] = vol3 * dd;
+    cb[3] = vol4 * dd; 
+    
+    pt->cpt++;
+    return(nsfin);
+  }
+  while ( ++it <= mesh->ntet );
+
+  return(0);
+}
+
+
+/* return 1 if point in tetra, adjacent #, if not */
+int inSubTetra(pPoint pt[4],float *p,double *cb) {
+  double   bx,by,bz,cx,cy,cz,dx,dy,dz,vx,vy,vz,apx,apy,apz;
+  double   epsra,vol1,vol2,vol3,vol4,dd; 
+
+  /* barycentric */
+  bx  = pt[1]->c[0] - pt[0]->c[0];
+  by  = pt[1]->c[1] - pt[0]->c[1];
+  bz  = pt[1]->c[2] - pt[0]->c[2];
+  cx  = pt[2]->c[0] - pt[0]->c[0];
+  cy  = pt[2]->c[1] - pt[0]->c[1];
+  cz  = pt[2]->c[2] - pt[0]->c[2];
+  dx  = pt[3]->c[0] - pt[0]->c[0];
+  dy  = pt[3]->c[1] - pt[0]->c[1];
+  dz  = pt[3]->c[2] - pt[0]->c[2];
+
+  /* test volume */
+  vx  = cy*dz - cz*dy;
+  vy  = cz*dx - cx*dz;
+  vz  = cx*dy - cy*dx;
+
+  epsra = EPST*(bx*vx + by*vy + bz*vz);
+  apx = p[0] - pt[0]->c[0];
+  apy = p[1] - pt[0]->c[1];
+  apz = p[2] - pt[0]->c[2];
+
+  /* p in 2 */
+  vol2 = apx*vx + apy*vy + apz*vz;
+  if ( epsra > vol2 )  return(-1);
+
+  /* p in 3 */
+  vx  = by*apz - bz*apy;
+  vy  = bz*apx - bx*apz;
+  vz  = bx*apy - by*apx;
+  vol3 = dx*vx + dy*vy + dz*vz;
+  if ( epsra > vol3 )  return(-2);
+  
+  /* p in 4 */
+  vol4 = -cx*vx - cy*vy - cz*vz;
+  if ( epsra > vol4 )  return(-3);
+
+  /* p in 1 */
+  vol1 = -epsra * EPSR - vol2 - vol3 - vol4;
+  if ( epsra > vol1 )  return(0);
+
+  dd = vol1+vol2+vol3+vol4;
+  if ( dd != 0.0f )  dd = 1.0 / dd;
+  cb[0] = vol1 * dd;
+  cb[1] = vol2 * dd;
+  cb[2] = vol3 * dd;
+  cb[3] = vol4 * dd; 
+  
+  return(1);
+}
+
+int locateHexa(pMesh mesh,int nsdep,int base,float *p,double *cb,pPoint pt[4]) {
+  pHexa    ph;
+  double   bx,by,bz,cx,cy,cz,dx,dy,dz,vx,vy,vz,apx,apy,apz;
+  double   epsra,vol1,vol2,vol3,vol4,dd; 
+  int     *adj,iadr,it,nsfin,in;
+
+  it    = 0;
+  nsfin = nsdep;
+  /*printf("locateHexa: searching for %f %f %f\n",p[0],p[1],p[2]);*/
+  do {
+    if ( !nsfin )  return(0);
+    ph = &mesh->hexa[nsfin];
+/*printf("\nnsfin %d  base %d  mark %d\n",nsfin,base,ph->mark);*/
+    if ( !ph->v[0] || ph->mark == base )  return(0);
+    ph->mark = base;
+    iadr = 6*(nsfin-1)+1;
+    adj  = &mesh->adja[iadr];
+/*printf("adj %d %d %d %d %d %d\n",adj[0],adj[1],adj[2],adj[3],adj[4],adj[5]);*/
+
+    /* tetra1: 0,2,3,7 : 3 external faces */
+/*printf("tet1: %d %d %d %d\n",ph->v[0],ph->v[2],ph->v[3],ph->v[7]);*/
+    pt[0] = &mesh->point[ph->v[0]];
+    pt[1] = &mesh->point[ph->v[2]];
+    pt[2] = &mesh->point[ph->v[3]];
+    pt[3] = &mesh->point[ph->v[7]];
+    in = inSubTetra(pt,p,cb);
+printf("tet1 : on sort en %d\n",in);
+    if ( in > 0 ) {
+      ph->cpt++;
+      return(nsfin);
+    }
+    else if ( in == 0 ) {
+      nsfin = adj[4];
+      continue;
+    }
+    else if ( in == -1 ) {
+      nsfin = adj[5];
+      continue;
+    }
+    else if ( in == -3 ) {
+      nsfin = adj[0];
+      continue;
+    }
+
+    /* tetra2: 1,4,5,6 : 3 external faces */
+    pt[0] = &mesh->point[ph->v[1]];
+    pt[1] = &mesh->point[ph->v[4]];
+    pt[2] = &mesh->point[ph->v[5]];
+    pt[3] = &mesh->point[ph->v[6]];
+    in = inSubTetra(pt,p,cb);
+    if ( in > 0 ) {
+      ph->cpt++;
+      return(nsfin);
+    }
+    else if ( in == 0 ) {
+      nsfin = adj[1];
+      continue;
+    }
+    else if ( in == -1 ) {
+      nsfin = adj[3];
+      continue;
+    }
+    else if ( in == -3 ) {
+      nsfin = adj[2];
+      continue;
+    }
+
+    /* tetra3: 0,4,6,7 : 2 external faces */
+    pt[0] = &mesh->point[ph->v[0]];
+    pt[1] = &mesh->point[ph->v[4]];
+    pt[2] = &mesh->point[ph->v[6]];
+    pt[3] = &mesh->point[ph->v[7]];
+    in = inSubTetra(pt,p,cb);
+    if ( in > 0 ) {
+      ph->cpt++;
+      return(nsfin);
+    }
+    else if ( in == 0 ) {
+      nsfin = adj[1];
+      continue;
+    }
+    else if ( in == -2 ) {
+      nsfin = adj[5];
+      continue;
+    }
+
+    /* tetra4: 0,1,2,6 : 2 external faces */
+    pt[0] = &mesh->point[ph->v[0]];
+    pt[1] = &mesh->point[ph->v[1]];
+    pt[2] = &mesh->point[ph->v[2]];
+    pt[3] = &mesh->point[ph->v[6]];
+    in = inSubTetra(pt,p,cb);
+    if ( in > 0 ) {
+      ph->cpt++;
+      return(nsfin);
+    }
+    else if ( in == 0 ) {
+      nsfin = adj[3];
+      continue;
+    }
+    else if ( in == -3 ) {
+      nsfin = adj[0];
+      continue;
+    }
+    
+    /* tetra5: 0,6,2,7 : 1 external face */
+    pt[0] = &mesh->point[ph->v[0]];
+    pt[1] = &mesh->point[ph->v[6]];
+    pt[2] = &mesh->point[ph->v[2]];
+    pt[3] = &mesh->point[ph->v[7]];
+    in = inSubTetra(pt,p,cb);
+    if ( in > 0 ) {
+      ph->cpt++;
+      return(nsfin);
+    }
+    else if ( in == 0 ) {
+      nsfin = adj[4];
+      continue;
+    }
+
+    /* tetra6: 0,4,1,6 : 1 external face */
+    pt[0] = &mesh->point[ph->v[0]];
+    pt[1] = &mesh->point[ph->v[4]];
+    pt[2] = &mesh->point[ph->v[1]];
+    pt[3] = &mesh->point[ph->v[6]];
+    in = inSubTetra(pt,p,cb);
+    if ( in > 0 ) {
+      ph->cpt++;
+      return(nsfin);
+    }
+    else if ( in == -3 ) {
+      nsfin = adj[2];
+      continue;
+    }
+puts("PROBLEME");
+exit(1);
+  }
+  while ( ++it <= mesh->nhex );
+
+  return(0);
+}
+
+int locateTria(pMesh mesh,int nsdep,int base,float *p,double *cb) {
+  pTriangle pt;
+  pPoint    p0,p1,p2;
+  double    ax,ay,bx,by,cx,cy;
+  double    epsra,aire1,aire2,aire3,dd; 
+  int      *adj,iadr,it,isign,nsfin;
+
+  it    = 0;
+  nsfin = nsdep;
+  /*printf("locateTria: searching for %f %f\n",p[0],p[1]);*/
+  do {
+    pt = &mesh->tria[nsfin];
+    if ( !pt->v[0] )  return(0);
+    if ( pt->mark == base )  return(0);
+    pt->mark = base;
+    iadr = 3*(nsfin-1)+1;
+    adj  = &mesh->adja[iadr];
+
+    p0 = &mesh->point[pt->v[0]];
+    p1 = &mesh->point[pt->v[1]];
+    p2 = &mesh->point[pt->v[2]];
+
+    ax = p1->c[0] - p0->c[0];
+    ay = p1->c[1] - p0->c[1];
+    bx = p2->c[0] - p0->c[0];
+    by = p2->c[1] - p0->c[1];
+    dd = ax*by - ay*bx;
+    isign= dd > 0 ? 1 : -1;
+    epsra = isign > 0 ? EPST*dd : -(EPST*dd);
+    /* barycentric */
+    bx = p1->c[0] - p[0];
+    by = p1->c[1] - p[1];
+    cx = p2->c[0] - p[0];
+    cy = p2->c[1] - p[1];
+    /* p in 1 */
+    aire1 = isign*(bx*cy - by*cx);
+    if ( epsra > aire1 ) {
+      nsfin = adj[0];
+      continue;
+    }
+
+    ax = p0->c[0] - p[0];
+    ay = p0->c[1] - p[1];
+    aire2 = isign*(cx*ay - cy*ax);
+    if ( epsra > aire2 ) {
+      nsfin = adj[1];
+      continue;
+    }
+
+    aire3 = -epsra*EPSR - aire1 - aire2;
+    if ( epsra > aire3 ) {
+      nsfin = adj[2];
+      continue;
+    }
+
+    dd = aire1+aire2+aire3;
+    if ( dd != 0.0f )  dd = 1.0 / dd;
+    cb[0] = aire1 * dd;
+    cb[1] = aire2 * dd;
+    cb[2] = aire3 * dd;
+    
+    pt->cpt++;
+    return(nsfin);
+  }
+  while ( ++it <= mesh->nt );
+
+  return(0);
+}
+
+/* point in tetra */
+int inTetra(pMesh mesh,int nsdep,float *p,double *cb) {
+  pTetra   pt;
+  pPoint   p0,p1,p2,p3;
+  double   bx,by,bz,cx,cy,cz,dx,dy,dz,vx,vy,vz,apx,apy,apz;
+  double   epsra,vol1,vol2,vol3,vol4,dd; 
+
+  pt = &mesh->tetra[nsdep];
+  if ( !pt->v[0] )  return(0);
+
+  p0 = &mesh->point[pt->v[0]];
+  p1 = &mesh->point[pt->v[1]];
+  p2 = &mesh->point[pt->v[2]];
+  p3 = &mesh->point[pt->v[3]];
+
+  /* barycentric */
+  bx  = p1->c[0] - p0->c[0];
+  by  = p1->c[1] - p0->c[1];
+  bz  = p1->c[2] - p0->c[2];
+  cx  = p2->c[0] - p0->c[0];
+  cy  = p2->c[1] - p0->c[1];
+  cz  = p2->c[2] - p0->c[2];
+  dx  = p3->c[0] - p0->c[0];
+  dy  = p3->c[1] - p0->c[1];
+  dz  = p3->c[2] - p0->c[2];
+
+  /* test volume */
+  vx  = cy*dz - cz*dy;
+  vy  = cz*dx - cx*dz;
+  vz  = cx*dy - cy*dx;
+
+  epsra = EPST*(bx*vx + by*vy + bz*vz);
+  apx = p[0] - p0->c[0];
+  apy = p[1] - p0->c[1];
+  apz = p[2] - p0->c[2];
+
+  /* p in 2 */
+  vol2  = apx*vx + apy*vy + apz*vz;
+  if ( epsra > vol2 )  return(0);
+
+  /* p in 3 */
+  vx  = by*apz - bz*apy;
+  vy  = bz*apx - bx*apz;
+  vz  = bx*apy - by*apx;
+  vol3 = dx*vx + dy*vy + dz*vz;
+  if ( epsra > vol3 )  return(0);
+    
+  /* p in 4 */
+  vol4 = -cx*vx - cy*vy - cz*vz;
+  if ( epsra > vol4 )  return(0);
+  
+  /* p in 1 */
+  vol1 = -epsra * EPSR - vol2 - vol3 - vol4;
+  if ( epsra > vol1 )  return(0);
+
+  dd = vol1+vol2+vol3+vol4;
+  if ( dd != 0.0f )  dd = 1.0 / dd;
+  cb[0] = vol1 * dd;
+  cb[1] = vol2 * dd;
+  cb[2] = vol3 * dd;
+  cb[3] = vol4 * dd; 
+
+  pt->cpt++;
+  return(1);
+}
+
+int inHexa(pMesh mesh,int nsdep,float *p,double *cb,pPoint pt[4]) {
+  return(0);
+}
+
+int inTria(pMesh mesh,int nsdep,float *p,double *cb) {
+  pTriangle  pt;
+  pPoint     p0,p1,p2;
+  double     ax,ay,bx,by,cx,cy;
+  double     epsra,dd,aire1,aire2,aire3;
+  int        isign;
+
+  pt = &mesh->tria[nsdep];
+  if ( !pt->v[0] )  return(0);
+
+  p0 = &mesh->point[pt->v[0]];
+  p1 = &mesh->point[pt->v[1]];
+  p2 = &mesh->point[pt->v[2]];
+
+  ax = p1->c[0] - p0->c[0];
+  ay = p1->c[1] - p0->c[1];
+  bx = p2->c[0] - p0->c[0];
+  by = p2->c[1] - p0->c[1];
+  dd = ax*by - ay*bx;
+  isign= dd > 0 ? 1 : -1;
+  epsra = isign > 0 ? EPST*dd : -(EPST*dd);
+
+  /* barycentric */
+  bx = p[0] - p1->c[0];
+  by = p[1] - p1->c[1];
+  cx = p[0] - p2->c[0];
+  cy = p[1] - p2->c[1];
+  aire1 = isign*(bx*cy - by*cx);
+  if ( epsra > aire1 )  return(0);
+
+  ax = p[0] - p0->c[0];
+  ay = p[1] - p0->c[1];
+  aire2 = isign*(cx*ay - cy*ax);
+  if ( epsra > aire2 )  return(0);
+  
+  aire3 = -epsra*EPSR - aire1 - aire2;
+  if ( epsra > aire3 )  return(0);
+
+  dd = aire1+aire2+aire3;
+  if ( dd != 0.0f )  dd = 1.0 / dd;
+  cb[0] = aire1 * dd;
+  cb[1] = aire2 * dd;
+  cb[2] = aire3 * dd;
+
+  pt->cpt++;
+  return(1);
+}
+
+
+/* return size of tetra */
+double sizeTetra(pMesh mesh,int k) {
+  pTetra   pt;
+  pPoint   p[4];
+  double   ax,ay,az,dd;
+  double   hmin;
+  int      i;
+  static int  idire[6][2] = {{0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3}};
+
+  pt = &mesh->tetra[k];
+  for (i=0; i<4; i++)
+    p[i] = &mesh->point[pt->v[i]];
+  hmin = FLT_MAX;
+  for (i=1; i<6; i++) {
+    ax = p[idire[i][0]]->c[0] - p[idire[i][1]]->c[0];
+    ay = p[idire[i][0]]->c[1] - p[idire[i][1]]->c[1];
+    az = p[idire[i][0]]->c[2] - p[idire[i][1]]->c[2];
+    dd = ax*ax + ay*ay + az*az;
+    hmin = min(dd,hmin);
+  }
+  return(sqrt(hmin));
+}
+
+double sizeHexa(pMesh mesh,int k) {
+  pHexa    ph;
+  pPoint   p[8];
+  double   ax,ay,az,dd;
+  double   hmin;
+  int      i;
+  static int idire[12][2] = {{0,1}, {1,2}, {2,3}, {0,3}, {4,5}, {5,6},
+                             {6,7}, {4,7}, {0,4}, {1,5}, {2,6}, {3,7}};
+
+  ph = &mesh->hexa[k];
+  for (i=0; i<8; i++)
+    p[i] = &mesh->point[ph->v[i]];
+  hmin = FLT_MAX;
+  for (i=1; i<12; i++) {
+    ax = p[idire[i][0]]->c[0] - p[idire[i][1]]->c[0];
+    ay = p[idire[i][0]]->c[1] - p[idire[i][1]]->c[1];
+    az = p[idire[i][0]]->c[2] - p[idire[i][1]]->c[2];
+    dd = ax*ax + ay*ay + az*az;
+    hmin = min(dd,hmin);
+  }
+  return(sqrt(hmin));
+}
+
+double sizeTria(pMesh mesh,int k) {
+  pTriangle pt;
+  pPoint    p0,p1;
+  double    ax,ay,dd;
+  double    hmin;
+  int       i;
+  static int idir[5] = {0,1,2,0,1};
+
+  pt = &mesh->tria[k];
+  hmin = FLT_MAX;
+  for (i=0; i<3; i++) {
+    p0 = &mesh->point[pt->v[i]];
+    p1 = &mesh->point[pt->v[idir[i+1]]];
+    ax = p0->c[0] - p1->c[0];
+    ay = p0->c[1] - p1->c[1];
+    dd = ax*ax + ay*ay;
+    hmin = min(dd,hmin);
+  }
+  return(sqrt(hmin));
+}
+
+double sizeQuad(pMesh mesh,int k) {
+  pQuad     pq;
+  pPoint    p0,p1;
+  double    ax,ay,dd;
+  double    hmin;
+  int       i;
+  static int idir[7] = {0,1,2,3,0,1,2};
+
+  pq = &mesh->quad[k];
+  hmin = FLT_MAX;
+  for (i=0; i<4; i++) {
+    p0 = &mesh->point[pq->v[i]];
+    p1 = &mesh->point[pq->v[idir[i+1]]];
+    ax = p0->c[0] - p1->c[0];
+    ay = p0->c[1] - p1->c[1];
+    dd = ax*ax + ay*ay;
+    hmin = min(dd,hmin);
+  }
+  return(sqrt(hmin));
+}
+
+/* vector interpolation */
+double field3DInterp(pMesh mesh,int iel,double *cb,double *v) {
+  pTetra     pt;
+  pSolution  ps0,ps1,ps2,ps3;
+  double     dd;
+
+  pt  = &mesh->tetra[iel];
+  ps0 = &mesh->sol[pt->v[0]];
+  ps1 = &mesh->sol[pt->v[1]];
+  ps2 = &mesh->sol[pt->v[2]];
+  ps3 = &mesh->sol[pt->v[3]];
+
+  v[0] = cb[0]*ps0->m[0] + cb[1]*ps1->m[0] + \
+         cb[2]*ps2->m[0] + cb[3]*ps3->m[0];
+  v[1] = cb[0]*ps0->m[1] + cb[1]*ps1->m[1] + \
+         cb[2]*ps2->m[1] + cb[3]*ps3->m[1];
+  v[2] = cb[0]*ps0->m[2] + cb[1]*ps1->m[2] + \
+         cb[2]*ps2->m[2] + cb[3]*ps3->m[2];
+  dd = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+  if ( dd > 0.0f ) {
+    v[0] /= dd;
+    v[1] /= dd;
+    v[2] /= dd;
+  }
+  return(dd);
+}
+
+/* vector interpolation */
+double vector3DInterp(pMesh mesh,pPoint pt[4],double *cb,double *v) {
+  pSolution  ps0,ps1,ps2,ps3;
+  double     dd;
+
+  ps0 = &mesh->sol[pt[0]-&mesh->point[0]];
+  ps1 = &mesh->sol[pt[1]-&mesh->point[0]];
+  ps2 = &mesh->sol[pt[2]-&mesh->point[0]];
+  ps3 = &mesh->sol[pt[3]-&mesh->point[0]];
+
+  v[0] = cb[0]*ps0->m[0] + cb[1]*ps1->m[0] + \
+         cb[2]*ps2->m[0] + cb[3]*ps3->m[0];
+  v[1] = cb[0]*ps0->m[1] + cb[1]*ps1->m[1] + \
+         cb[2]*ps2->m[1] + cb[3]*ps3->m[1];
+  v[2] = cb[0]*ps0->m[2] + cb[1]*ps1->m[2] + \
+         cb[2]*ps2->m[2] + cb[3]*ps3->m[2];
+  dd = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+  if ( dd > 0.0f ) {
+    v[0] /= dd;
+    v[1] /= dd;
+    v[2] /= dd;
+  }
+  return(dd);
+}
+
+
+double field2DInterp(pMesh mesh,int iel,double *cb,double *v) {
+  pTriangle  pt;
+  pSolution  ps0,ps1,ps2;
+  double     dd;
+
+  pt  = &mesh->tria[iel];
+  ps0 = &mesh->sol[pt->v[0]];
+  ps1 = &mesh->sol[pt->v[1]];
+  ps2 = &mesh->sol[pt->v[2]];
+
+  v[0] = cb[0]*ps0->m[0] + cb[1]*ps1->m[0] + cb[2]*ps2->m[0];
+  v[1] = cb[0]*ps0->m[1] + cb[1]*ps1->m[1] + cb[2]*ps2->m[1];
+  v[2] = 0.0f;
+  dd = sqrt(v[0]*v[0] + v[1]*v[1]);
+  if ( dd > 0.0f ) {
+    v[0] /= dd;
+    v[1] /= dd;
+  }
+  return(dd);
+}
+
+
+/* add point to display list, if needed */
+int filterPoint(pScene sc,Stream *st,float *p,ubyte color) {
+  double  norm,rgb[3],kc,ux,uy,uz,vx,vy,vz,dd;
+  int     i;
+  static double hsv[3] = { 0.0f, 1.0f, 0.80f };
+
+  /* store point */
+  memcpy(st->stpt[++st->stnp],p,3*sizeof(float));
+  nbar++;
+
+  /* point color */
+  norm = st->norm;
+  if ( !color ) {
+    if ( norm < sc->iso.val[0] ) 
+      norm = sc->iso.val[0];  
+    else if ( norm > sc->iso.val[MAXISO-1] )
+      norm = sc->iso.val[MAXISO-1];
+    for (i=0; i<MAXISO-1; i++)
+      if ( norm < sc->iso.val[i] )  break;
+    kc = (norm-sc->iso.val[i-1]) / (sc->iso.val[i] - sc->iso.val[i-1]);
+    st->stcol[st->stnp] = sc->iso.col[i-1]*(1.0-kc)+sc->iso.col[i]*kc;
+    st->stiso[st->stnp] = i;
+  }
+  else {
+    st->stcol[st->stnp] = sc->iso.col[MAXISO-1];
+    st->stiso[st->stnp] = MAXISO-1;
+  }
+
+  if ( sc->mode & S_ALTITUDE )
+    st->stpt[st->stnp][2] = altcoef*norm;
+
+  if ( !color && (st->stiso[0] != st->stiso[st->stnp]) ) {
+    hsv[0] = st->stcol[st->stnp];
+    hsvrgb(hsv,rgb);
+    glColor3dv(rgb);
+    glVertex3fv(st->stpt[st->stnp]);
+
+    memcpy(st->stpt[0],st->stpt[st->stnp],3*sizeof(float));
+    st->stcol[0] = st->stcol[st->stnp];
+    st->stiso[0] = st->stiso[st->stnp];
+    st->stnp = 0;
+    return(1);
+  }
+
+  if ( st->stnp < 2 )  return(0);
+
+  /* filtering point */
+  ux = st->stpt[0][0] - st->stpt[1][0];
+  uy = st->stpt[0][1] - st->stpt[1][1];
+  uz = st->stpt[0][2] - st->stpt[1][2];
+  dd = ux*ux + uy*uy + uz*uz;
+  
+  if ( dd > 0.0 ) {  
+    dd = 1.0f / sqrt(dd);
+    ux *= dd;
+    uy *= dd;
+    uz *= dd;
+  }
+  else {
+    memcpy(st->stpt[0],st->stpt[1],2*3*sizeof(float));
+    st->stnp--;
+    return(0);
+  }
+
+  vx = st->stpt[2][0] - st->stpt[1][0];
+  vy = st->stpt[2][1] - st->stpt[1][1];
+  vz = st->stpt[2][2] - st->stpt[1][2];
+  dd = vx*vx + vy*vy + vz*vz;
+  if ( dd > 0.0 ) {
+    dd = 1.0f / sqrt(dd);
+    vx *= dd;
+    vy *= dd;
+    vz *= dd;
+  }
+  else {
+    memcpy(st->stpt[1],st->stpt[2],3*sizeof(float));
+    st->stnp--;
+    return(0);
+  }
+
+  dd = ux*vx + uy*vy + uz*vz;
+  if ( dd > COS178 ) {
+    hsv[0] = st->stcol[st->stnp];
+    hsvrgb(hsv,rgb);
+    glColor3dv(rgb);
+    glVertex3fv(st->stpt[st->stnp]);
+
+    memcpy(st->stpt[0],st->stpt[st->stnp],3*sizeof(float));
+    st->stcol[0] = st->stcol[st->stnp];
+    st->stiso[0] = st->stiso[st->stnp];
+    st->stnp = 0;
+    return(1);
+  }
+  else {
+    memcpy(st->stpt[st->stnp-1],st->stpt[st->stnp],3*sizeof(float));
+    st->stcol[st->stnp-1] = st->stcol[st->stnp];
+    st->stiso[st->stnp-1] = st->stiso[st->stnp];
+    st->stnp--;
+    return(0);
+  }
+}
+
+
+/* add vertex to display list */
+void addPoint(pScene sc,Stream *st,float *p,ubyte color) {
+  double  norm,rgb[3],kc;
+  int     i;
+  static double hsv[3] = { 0.0f, 1.0f, 0.80f };
+
+  /* point color */
+  norm = st->norm;
+  i = MAXISO-1;
+  if ( !color ) {
+    norm = st->norm;
+    if ( norm < sc->iso.val[0] )
+      norm = sc->iso.val[0];  
+    else if ( norm > sc->iso.val[MAXISO-1] )
+      norm = sc->iso.val[MAXISO-1];
+    for (i=0; i<MAXISO-1; i++)
+      if ( norm < sc->iso.val[i] )  break;
+    kc = (norm-sc->iso.val[i-1]) / (sc->iso.val[i] - sc->iso.val[i-1]);
+    hsv[0] = sc->iso.col[i-1]*(1.0-kc)+sc->iso.col[i]*kc;
+  }
+
+  if ( sc->mode & S_ALTITUDE )
+    p[2] = altcoef*norm;
+
+  hsvrgb(hsv,rgb);
+  glColor3dv(rgb);
+  glVertex3fv(p);
+  st->stnp = 0;
+  memcpy(st->stpt[st->stnp],p,3*sizeof(float));
+  st->stcol[st->stnp] = hsv[0];
+  st->stiso[st->stnp] = i;
+  st->stnp++;
+}
+
+
+int nxtPoint3D(pMesh mesh,int nsdep,float *p,float step,double *v) {
+  pTetra     pt;
+  double     norm,h6,cb[4],v1[3],v2[3],v3[3];
+  float      xp1[3],xp2[3],xp3[3];
+  int        k;
+
+  /* 4th order Runge-Kutta */
+  xp1[0] = p[0] + 0.5*step*v[0];
+  xp1[1] = p[1] + 0.5*step*v[1];
+  xp1[2] = p[2] + 0.5*step*v[2];
+
+  k = locateTetra(mesh,nsdep,++mesh->mark,xp1,cb);
+  if ( !k )  return(0);
+  norm = field3DInterp(mesh,k,cb,v1);
+  pt = &mesh->tetra[k];
+  pt->cpt--;
+
+  xp2[0] = p[0] + 0.5*step*v1[0];
+  xp2[1] = p[1] + 0.5*step*v1[1];
+  xp2[2] = p[2] + 0.5*step*v1[2];
+
+  k = locateTetra(mesh,k,++mesh->mark,xp2,cb);
+  if ( !k )  return(0);
+  norm = field3DInterp(mesh,k,cb,v2);
+  pt = &mesh->tetra[k];
+  pt->cpt--;
+
+  xp3[0] = p[0] + step*v2[0];
+  xp3[1] = p[1] + step*v2[1];
+  xp3[2] = p[2] + step*v2[2];
+
+  k = locateTetra(mesh,k,++mesh->mark,xp3,cb);
+  if ( !k )  return(0);
+  norm = field3DInterp(mesh,k,cb,v3);
+  pt = &mesh->tetra[k];
+  pt->cpt--;
+
+  h6    = step / 6.0;
+  p[0] += h6 * (v[0] + 2*(v1[0] + v2[0]) + v3[0]);
+  p[1] += h6 * (v[1] + 2*(v1[1] + v2[1]) + v3[1]);
+  p[2] += h6 * (v[2] + 2*(v1[2] + v2[2]) + v3[2]);
+
+  return(1);
+}
+
+int nxtPoint2D(pMesh mesh,int nsdep,float *p,float step,double *v) {
+  pTriangle  pt;
+  double     norm,h6,cb[3],v1[3],v2[3],v3[3];
+  float      xp1[3],xp2[3],xp3[3];
+  int        k;
+
+  /* 4th order Runge-Kutta */
+  xp1[0] = p[0] + 0.5*step*v[0];
+  xp1[1] = p[1] + 0.5*step*v[1];
+
+  k = locateTria(mesh,nsdep,++mesh->mark,xp1,cb);
+  if ( !k )  return(0);
+  norm = field2DInterp(mesh,k,cb,v1);
+  pt = &mesh->tria[k];
+  pt->cpt--;
+  
+  xp2[0] = p[0] + 0.5*step*v1[0];
+  xp2[1] = p[1] + 0.5*step*v1[1];
+
+  k = locateTria(mesh,k,++mesh->mark,xp2,cb);
+  if ( !k )  return(0);
+  norm = field2DInterp(mesh,k,cb,v2);
+  pt = &mesh->tria[k];
+  pt->cpt--;
+
+  xp3[0] = p[0] + step*v2[0];
+  xp3[1] = p[1] + step*v2[1];
+
+  k = locateTria(mesh,k,++mesh->mark,xp3,cb);
+  if ( !k )  return(0);
+  norm = field2DInterp(mesh,k,cb,v3);
+  pt = &mesh->tria[k];
+  pt->cpt--;
+
+  h6 = step / 6.0;
+  p[0] += h6 * (v[0] + 2*(v1[0] + v2[0]) + v3[0]);
+  p[1] += h6 * (v[1] + 2*(v1[1] + v2[1]) + v3[1]);
+
+  return(1);
+}
+
+
+/* read streamlines origins */
+int parseStream(pScene sc,pMesh mesh) {
+  FILE    *in;
+  pStream  st;
+  float    x,y,z;
+  int      i,k,nbp,ret;
+  char    *ptr,data[128],key[256],tmp[128];
+
+  /* input file */
+  strcpy(tmp,mesh->name);
+  ptr = (char*)strstr(tmp,".mesh");
+  if ( ptr )  *ptr = '\0';
+
+  sprintf(data,"%s.iso",tmp);
+  in = fopen(data,"r");
+  if ( !in ) {
+    sscanf(data,"DEFAULT.iso");
+    in = fopen(data,"r");
+    if ( !in )  return(0);
+  }
+  if ( !quiet )  fprintf(stdout,"  Reading %s\n",data);
+  sc->stream = createStream(sc,mesh); 
+  st = sc->stream;
+
+  while ( !feof(in) ) {
+    fscanf(in,"%s",key);
+    for (i=0; i<strlen(key); i++) key[i] = tolower(key[i]);
+
+    if ( !strcmp(key,"nblines") ) {
+      fscanf(in,"%d",&nbp);
+      st->nbstl = nbp;
+      if ( mesh->dim == 3 )
+        for (k=1; k<=3*st->nbstl; k+=3) {
+          ret = fscanf(in,"%f %f %f\n",&x,&y,&z);
+printf("x %f %f %f\n",x,y,z);
+          st->listp[k]   = x - mesh->xtra;
+          st->listp[k+1] = y - mesh->ytra;
+          st->listp[k+2] = z - mesh->ztra;
+printf("x %f %f %f\n",st->listp[k],st->listp[k+1],st->listp[k+2]);
+        }
+      else
+        for (k=1; k<=2*st->nbstl; k+=2) {
+          ret = fscanf(in,"%f %f\n",&x,&y);
+          st->listp[k]   = x - mesh->xtra;
+          st->listp[k+1] = y - mesh->ytra;
+        }
+    }
+    else if ( !strcmp(key,"euler") ) {
+      st->typtrack = Euler;
+    }
+    else if ( !strcmp(key,"box") ) {
+      ret = fscanf(in,"%f %f",&x,&y);
+      if ( ret != 2 )  break; 
+      st->xmin = x - mesh->xtra;
+      st->xmax = y - mesh->xtra;
+      ret = fscanf(in,"%f %f",&x,&y);
+      if ( ret != 2 )  break;
+      st->ymin = x - mesh->ytra;
+      st->ymax = y - mesh->ytra; 
+      if ( mesh->dim == 3 ) {
+        ret = fscanf(in,"%f %f",&x,&y);
+        if ( ret != 2 )  break;
+        st->zmin = x - mesh->ztra;
+        st->zmax = y - mesh->ztra;
+      }
+    }
+    else if ( key[0] == '#' ) {
+      fgets(key,255,in);
+    }
+  }
+  fclose(in);
+
+  if ( !st->nbstl ) {
+    fprintf(stderr,"   ## No data found.\n");
+    return(0);
+  }
+k = 1;
+printf("fin proc %f %f %f\n",sc->stream->listp[k],sc->stream->listp[k+1],sc->stream->listp[k+2]);
+
+  return(1);
+}
+
+
+/* build lists for streamlines */
+int listTetraStream(pScene sc,pMesh mesh,float *pp,int squiet) {
+  pTetra     pt;
+  pStream    st;
+  double     dd,cb[4],cbdep[4],v[4],vdep[4],sizedep,normdep;
+  float      step,p[3],ox,oy,oz,ldt;
+  int        i,k,exh,depart,nsdep,nsfin,nsold,nbp,maxpts;
+  clock_t    ct;
+  FILE      *out;
+
+  /* default */
+  if ( !mesh->ntet )  return(0);
+  else if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( ddebug ) printf("\n create streamlines list / TETRA\n");
+
+  if ( !squiet && !ddebug ) {
+    fprintf(stdout," Building streamline(s)");
+    fflush(stdout);
+  }
+  ct = clock();
+
+  /* build display list */
+  st = sc->stream;
+  if ( st->nbstl > MAX_LST-1 )  return(0);
+  sc->slist[st->nbstl] = glGenLists(1);
+  glNewList(sc->slist[st->nbstl],GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  k = st->nbstl*3 + 1;
+  st->listp[k+0] = pp[0];
+  st->listp[k+1] = pp[1];
+  st->listp[k+2] = pp[2];
+  st->nbstl++;
+printf("\n%d: pp = %f %f %f\n",st->nbstl,st->listp[k+0],st->listp[k+1],st->listp[k+2]);
+
+  maxpts = max(MAX_PTS,5*mesh->ntet);
+  glLineWidth(2.0);
+
+  /* compute streamline */
+  nbp   = 0;
+  exh   = 0;
+  nsdep = mesh->ntet / 2;
+  step  = 0.0;
+  nbar  = 0;
+  if ( ddebug ) 
+    printf("   start point %d: %f %f %f\n",
+           3*k/3,st->listp[k],st->listp[k+1],st->listp[k+2]);
+
+  for (i=1; i<mesh->ntet; i++) {
+    pt = &mesh->tetra[i];
+    pt->cpt = 0;
+  }
+
+  /* find enclosing tet */
+  memcpy(p,pp,3*sizeof(float));
+  depart = locateTetra(mesh,nsdep,++mesh->mark,p,cb);
+printf("depart = %d\n",depart);
+  if ( !depart ) {
+    for (depart=1; depart<=mesh->ntet; depart++) {
+      pt = &mesh->tetra[depart];
+      if ( pt->mark != mesh->mark && inTetra(mesh,depart,p,cb) )
+        break;
+    }
+    if ( depart > mesh->ntet ) {
+      glEndList();
+      return(0);
+    }
+  }
+
+  st->norm = field3DInterp(mesh,depart,cb,v);
+  memcpy(cbdep,cb,4*sizeof(double));
+  memcpy(vdep,v,4*sizeof(double));
+  st->size = sizeTetra(mesh,depart);
+  sizedep  = st->size;
+  normdep  = st->norm;
+  ldt      = 0.0;
+
+  if ( st->size == 0.0 )
+    step = EPS*sc->dmax;
+  else
+    step = HSIZ * min(st->size,st->norm);
+
+  /* build display list incrementally */
+  nsdep = nsold = depart;
+  glBegin(GL_LINE_STRIP);
+  addPoint(sc,st,p,0);
+  nbp++;
+
+  if ( sc->par.maxtime < FLT_MAX ) {
+    sc->par.cumtim = 0.0;
+    step = min(0.05*sc->par.dt,step);
+    out  = fopen("particules.dat","a+");
+    assert(out);
+    fprintf(out,"\n%8.2f  %f %f %f\n",
+            sc->par.cumtim,p[0]+mesh->xtra,p[1]+mesh->ytra,p[2]+mesh->ztra);
+  }
+
+  do {
+    ox = p[0];
+    oy = p[1];
+    oz = p[2];
+
+    /* move to next point */
+    if ( st->typtrack == Euler || !nxtPoint3D(mesh,nsdep,p,step,v) ) {
+      p[0] += step*v[0];
+      p[1] += step*v[1];
+      p[2] += step*v[2];
+    }
+    if ( p[0]<st->xmin || p[1]<st->ymin || p[2]<st->zmin ||
+         p[0]>st->xmax || p[1]>st->ymax || p[2]>st->zmax )
+      break;
+    else if ( sc->par.maxtime < FLT_MAX ) {
+      ox -= p[0];
+      oy -= p[1];
+      oz -= p[2];
+      dd  = sqrt(ox*ox + oy*oy + oz*oz) / st->norm;
+      ldt += dd;
+      sc->par.cumtim     += dd;
+      if ( sc->par.cumtim  > sc->par.maxtime )  break;
+      
+      if ( ldt > sc->par.dt  ) {
+        fprintf(out,"%8.2f  %f %f %f\n",
+	        sc->par.cumtim,p[0]+mesh->xtra,p[1]+mesh->ytra,p[2]+mesh->ztra);
+    	ldt = fabs(sc->par.dt - ldt);
+      }
+    }
+
+    /* find tet containing p */
+    nsfin = locateTetra(mesh,nsdep,++mesh->mark,p,cb);
+    if ( !nsfin )  break;
+    nsdep = nsfin;
+    pt = &mesh->tetra[nsdep];
+    if ( pt->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( nsdep != nsold ) {
+      st->size = sizeTetra(mesh,nsdep);
+      nsold = nsdep;
+    }
+
+    /* vector field interpolation */
+    st->norm = field3DInterp(mesh,nsdep,cb,v);
+    step     = HSIZ*min(st->size,st->norm);
+    if ( sc->par.maxtime < FLT_MAX )
+      step = min(0.05*sc->par.dt,step);
+    if ( step == 0.0 )  break;
+
+    nbp += filterPoint(sc,st,p,0);
+  }
+  while ( nbp < maxpts );
+  addPoint(sc,st,p,0);
+  glEnd();
+
+  if ( nbp >= maxpts || sc->par.maxtime < FLT_MAX ) {
+    glLineWidth(1.0);
+    glEndList();
+    if ( !squiet && !ddebug ) {
+      fprintf(stdout,": %d (%d, %.2f) / %d lines",
+              nbar,nbp,(float)nbp/nbar,k/3);
+      ct = difftime(clock(),ct);
+      fprintf(stdout," %6.2f sec.\n",ct);
+    }
+    if ( sc->par.maxtime < FLT_MAX ) {
+      fprintf(out,"%8.2f  %f %f %f\n",
+              sc->par.cumtim,p[0]+mesh->xtra,p[1]+mesh->ytra,p[2]+mesh->ztra);
+      fclose(out);
+    }
+    return(1);
+  }
+
+  /* reverse orientation */
+  memcpy(p,pp,3*sizeof(float));
+  memcpy(cb,cbdep,4*sizeof(double));
+  memcpy(v,vdep,4*sizeof(double));
+  st->norm = normdep;
+  st->size = sizedep;
+  if ( st->size == 0.0 )
+    step = EPS * sc->dmax;
+  else
+    step = HSIZ * min(st->size,st->norm);
+
+  /* build display list incrementally */
+  nsdep = nsold = depart;
+  glBegin(GL_LINE_STRIP);
+  addPoint(sc,st,p,0);
+  nbp++;
+
+  do {
+    /* move to next point */
+    if ( st->typtrack == Euler || !nxtPoint3D(mesh,nsdep,p,-step,v) ) {
+      p[0] -= step*v[0];
+      p[1] -= step*v[1];
+      p[2] -= step*v[2];
+    }
+    if ( p[0]<st->xmin || p[1]<st->ymin || p[2]<st->zmin ||
+         p[0]>st->xmax || p[1]>st->ymax || p[2]>st->zmax )
+      break;
+
+    /* find tet containing p */
+    nsfin = locateTetra(mesh,nsdep,++mesh->mark,p,cb);
+    if ( !nsfin )  break;
+    nsdep = nsfin;
+    pt = &mesh->tetra[nsdep];
+    if ( pt->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( nsdep != nsold ) {
+      st->size = sizeTetra(mesh,nsdep);
+      nsold = nsdep;
+    }
+
+    /* vector field interpolation */
+    st->norm = field3DInterp(mesh,nsdep,cb,v);
+    step = HSIZ * min(st->size,st->norm);
+    if ( step == 0.0 )  break;
+
+    nbp += filterPoint(sc,st,p,0);
+  }
+  while ( nbp < maxpts );
+  addPoint(sc,st,p,0);
+  glEnd();
+  glLineWidth(1.0);
+  glEndList();
+
+  if ( !nbp ) {
+    st->nbstl--;
+    if ( !squiet && !ddebug )  fprintf(stdout,"..empty\n");
+    return(0);
+  }
+
+  if ( !squiet && !ddebug ) {  
+    if ( nbar )
+      fprintf(stdout,": %d (%d, %.2f) / %d lines",nbar,nbp,(float)nbp/nbar,k/3);
+    ct = difftime(clock(),ct);
+    fprintf(stdout," %6.2f sec.\n",ct);
+  }
+
+  return(1);
+}
+
+
+int listHexaStream(pScene sc,pMesh mesh,float *pp,int squiet) {
+  pHexa      ph;
+  pPoint     pt[4];
+  pStream    st;
+  double     cbdep[4],cb[4],v[6],vdep[6],sizedep,normdep;
+  float      step,p[3];
+  int        i,k,exh,depart,nsdep,nsfin,nsold,nbp,maxpts;
+  mytime     tt;
+
+  /* default */
+  if ( !mesh->nhex )  return(0);
+  else if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( ddebug ) printf("create streamlines list / HEXA\n");
+
+  if ( !squiet && !ddebug ) {
+    fprintf(stdout," Building streamline(s)");
+    fflush(stdout);
+    chrono(ON,&tt);
+  }
+
+  /* build display list */
+  st = sc->stream;
+  if ( st->nbstl > MAX_LST-1 )  return(0);
+  sc->slist[st->nbstl] = glGenLists(1);
+  glNewList(sc->slist[st->nbstl],GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  st->nbstl++;
+  k = st->nbstl*3;
+  st->listp[k]   = pp[0];
+  st->listp[k+1] = pp[1];
+  st->listp[k+2] = pp[2];
+
+  maxpts = max(MAX_PTS,5*mesh->nhex);
+  glLineWidth(2.0);
+
+  /* compute streamline */
+  nbp   = 0;
+  exh   = 0;
+  nsdep = mesh->nhex / 2;
+  step  = 0.0f;
+  nbar  = 0;
+  if ( ddebug ) 
+    printf("   start point %d: %f %f %f\n",
+           3*k/3,st->listp[k],st->listp[k+1],st->listp[k+2]);
+
+  for (i=1; i<mesh->nhex; i++) {
+    ph = &mesh->hexa[i];
+    ph->cpt  = 0;
+  }
+
+  /* find enclosing tet */
+  memcpy(p,pp,3*sizeof(float));
+  depart = locateHexa(mesh,nsdep,++mesh->mark,p,cb,pt);
+printf("DEPART %d\n",depart);
+ph = &mesh->hexa[depart];
+printf("sommets %d %d %d %d %d %d %d %d\n",
+ph->v[0],ph->v[1],ph->v[2],ph->v[3],ph->v[4],ph->v[5],ph->v[6],ph->v[7]);
+  
+  if ( !depart ) {
+    for (depart=1; depart<=mesh->nhex; depart++) {
+      ph = &mesh->hexa[depart];
+      if ( ph->mark != mesh->mark && inHexa(mesh,depart,p,cb,pt) )
+        break;
+    }
+    if ( depart > mesh->nhex )  return(0);
+  }
+
+  st->norm = vector3DInterp(mesh,pt,cb,v);
+  memcpy(cbdep,cb,4*sizeof(double));
+  memcpy(vdep,v,4*sizeof(double));
+  st->size = sizeHexa(mesh,depart);
+  sizedep  = st->size;
+  normdep  = st->norm;
+  if ( st->size == 0.0f )
+    step = EPS*sc->dmax;
+  else
+    step = HSIZ * st->size;
+
+  /* build display list incrementally */
+  nsdep = nsold = depart;
+  glBegin(GL_LINE_STRIP);
+  addPoint(sc,st,p,0);
+  nbp++;
+
+  do {
+    /* move to next point */
+    if ( st->typtrack == Euler || !nxtPoint3D(mesh,nsdep,p,step,v)) {
+      p[0] += step*v[0];
+      p[1] += step*v[1];
+      p[2] += step*v[2];
+    }
+    if ( p[0]<st->xmin || p[1]<st->ymin || p[2]<st->zmin ||
+         p[0]>st->xmax || p[1]>st->ymax || p[2]>st->zmax )
+      break;
+
+    /* find tet containing p */
+    nsfin = locateHexa(mesh,nsdep,++mesh->mark,p,cb,pt);
+    if ( !nsfin )  break;
+    nsdep = nsfin;
+    ph = &mesh->hexa[nsdep];
+    if ( ph->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( nsdep != nsold ) {
+      st->size = sizeHexa(mesh,nsdep);
+      step  = HSIZ*st->size;
+      nsold = nsdep;
+    }
+
+    /* vector field interpolation */
+    st->norm = vector3DInterp(mesh,pt,cb,v);
+    if ( st->norm < EPS*step )  break;
+    step = min(step,st->norm);
+    if ( step == 0.0f )  break; /*step = 1.0e-06*sc->dmax;*/
+
+    nbp += filterPoint(sc,st,p,0);
+  }
+  while ( nbp < maxpts );
+  glEnd();
+
+  if ( nbp >= maxpts ) {
+    glLineWidth(1.0);
+    glEndList();
+    if ( !squiet && !ddebug ) {
+      fprintf(stdout,": %d (%d, %.2f) / %d lines",
+              nbar,nbp,(float)nbp/nbar,k/3);
+      chrono(OFF,&tt);
+      fprintf(stdout," %6.2f sec.\n",gttime(tt));
+    }
+    return(1);
+  }
+
+  /* reverse orientation */
+  memcpy(p,pp,3*sizeof(float));
+  memcpy(cb,cbdep,4*sizeof(double));
+  memcpy(v,vdep,4*sizeof(double));
+  st->norm = normdep;
+  st->size = sizedep;
+  if ( st->size == 0.0f )
+    step = EPS * sc->dmax;
+  else
+    step = HSIZ*st->size;
+
+  /* build display list incrementally */
+  nsdep = nsold = depart;
+  glBegin(GL_LINE_STRIP);
+  addPoint(sc,st,p,0);
+  nbp++;
+
+  do {
+    /* move to next point */
+    if ( st->typtrack == Euler || !nxtPoint3D(mesh,nsdep,p,-step,v) ) {
+      p[0] -= step*v[0];
+      p[1] -= step*v[1];
+      p[2] -= step*v[2];
+    }
+    if ( p[0]<st->xmin || p[1]<st->ymin || p[2]<st->zmin ||
+         p[0]>st->xmax || p[1]>st->ymax || p[2]>st->zmax )
+      break;
+
+    /* find tet containing p */
+    nsfin = locateHexa(mesh,nsdep,++mesh->mark,p,cb,pt);
+    if ( !nsfin )  break;
+    nsdep = nsfin;
+    ph = &mesh->hexa[nsdep];
+    if ( ph->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( nsdep != nsold ) {
+      st->size = sizeHexa(mesh,nsdep);
+      step  = HSIZ * st->size;
+      nsold = nsdep;
+    }
+
+    /* vector field interpolation */
+    st->norm = vector3DInterp(mesh,pt,cb,v);
+    if ( st->norm < EPS*step )   break;
+    step = min(step,st->norm);
+    if ( step == 0.0f )  break; /*step = 1.e-06 * sc->dmax;*/
+
+    nbp += filterPoint(sc,st,p,0);
+  }
+  while ( nbp < maxpts );
+  glEnd();
+  glLineWidth(1.0);
+  glEndList();
+
+  if ( nbp >= maxpts ) {
+    glLineWidth(1.0);
+    glEndList();
+    if ( !squiet && !ddebug ) {
+      fprintf(stdout,": %d (%d, %.2f) / %d lines",
+              nbar,nbp,(float)nbp/nbar,k/3);
+      chrono(OFF,&tt);
+      fprintf(stdout," %6.2f sec.\n",gttime(tt));
+    }
+    return(1);
+  }
+
+  if ( !nbp ) {
+    st->nbstl--;
+    if ( !squiet && !ddebug )  fprintf(stdout,"..empty\n");
+    return(0);
+  }
+
+  if ( !squiet && !ddebug ) {  
+    if ( nbar )
+      fprintf(stdout,": %d (%d, %.2f) / %d lines",nbar,nbp,(float)nbp/nbar,k/3);
+    chrono(OFF,&tt);
+    fprintf(stdout," %6.2f sec.\n",gttime(tt));
+  }
+
+  return(1);
+}
+
+
+int listTriaStream(pScene sc,pMesh mesh,float *pp) {
+  pTriangle  pt;
+  pStream    st;
+  double     dd,cb[3],cbdep[3],v[3],vdep[3],sizedep,normdep;
+  float      step,p[3],ox,oy,ldt;
+  int        i,k,exh,depart,nsdep,nsfin,nsold,nbp,maxpts;
+  clock_t    ct;
+  FILE      *out;
+
+  /* default */
+  if ( !mesh->nt )  return(0);
+  if ( ddebug ) printf("create streamlines / TRIA\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  fprintf(stdout," Building streamline(s)");
+  fflush(stdout);
+  ct = clock();
+
+  /* build display list */
+  st = sc->stream;
+  if ( st->nbstl > MAX_LST-1 )  return(0);
+  sc->slist[st->nbstl] = glGenLists(1);
+  glNewList(sc->slist[st->nbstl],GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  st->nbstl++;
+  k = st->nbstl*3;
+  st->listp[k]   = pp[0];
+  st->listp[k+1] = pp[1];
+  st->listp[k+2] = pp[2];
+
+  maxpts = max(MAX_PTS,5*mesh->nt);
+  glLineWidth(2.0);
+
+  /* compute streamlines */
+  nbp   = 0;
+  exh   = 0;
+  nsdep = mesh->nt / 2;
+  step  = 0.0;
+  nbar  = 0;
+  if ( ddebug )
+    printf("   start point %d: %f %f\n",3*k/3,st->listp[k],st->listp[k+1]);
+
+  for (i=1; i<=mesh->nt; i++) {
+    pt = &mesh->tria[i];
+    pt->cpt = 0;
+  }
+
+  /* find enclosing triangle */
+  memcpy(p,pp,3*sizeof(float));
+  depart = locateTria(mesh,nsdep,++mesh->mark,p,cb);
+  if ( !depart ) {
+    if ( ddebug )  printf("exhaustif search\n");
+    for (depart=1; depart<=mesh->nt; depart++) {
+      pt = &mesh->tria[depart];
+      if ( pt->mark != mesh->mark && inTria(mesh,depart,p,cb) )
+        break;
+    }
+    if ( depart > mesh->nt ) {
+      st->nbstl--;
+      glEndList();
+      glLineWidth(1.0);
+      fflush(stdout);
+      return(0);
+    }
+  }
+
+  st->norm = field2DInterp(mesh,depart,cb,v);
+  memcpy(cbdep,cb,3*sizeof(double));
+  memcpy(vdep,v,3*sizeof(double));
+  st->size   = sizeTria(mesh,depart);
+  sizedep    = st->size;
+  normdep    = st->norm;
+  ldt        = 0.0;
+
+  if ( st->size == 0.0 )
+    step = EPS * sc->dmax;
+  else 
+    step = HSIZ * min(st->size,st->norm);
+
+  /* build display list incrementally */
+  nsdep = nsold = depart;
+  glBegin(GL_LINE_STRIP);
+  addPoint(sc,st,p,0);
+  nbp++;
+
+  if ( sc->par.maxtime < FLT_MAX ) {
+    sc->par.cumtim = 0.0;
+    step = min(0.05*sc->par.dt,step);
+    out  = fopen("particules.dat","a+");
+    assert(out);
+    fprintf(out,"\n%8.2f  %f %f\n",
+            sc->par.cumtim,p[0]+mesh->xtra,p[1]+mesh->ytra);
+  }
+
+  do {
+    ox = p[0];
+    oy = p[1];
+
+    /* move to next point */
+    if ( st->typtrack == Euler || !nxtPoint2D(mesh,nsdep,p,step,v) ) {
+      p[0] += step*v[0];
+      p[1] += step*v[1];
+    }
+    if ( p[0]<st->xmin || p[1]<st->ymin ||
+         p[0]>st->xmax || p[1]>st->ymax )
+      break;
+    else if ( sc->par.maxtime < FLT_MAX ) {
+      ox -= p[0];
+      oy -= p[1];
+      dd  = sqrt(ox*ox + oy*oy) / st->norm;
+      ldt += dd;
+      sc->par.cumtim     += dd;
+      if ( sc->par.cumtim >= sc->par.maxtime )  break;
+      if ( ldt > sc->par.dt ) {
+        fprintf(out,"%8.2f  %f %f\n",
+                sc->par.cumtim,p[0]+mesh->xtra,p[1]+mesh->ytra);
+        ldt = fabs(sc->par.dt - ldt);
+      }
+    }
+
+    /* find tet containing p */
+    nsfin = locateTria(mesh,nsdep,++mesh->mark,p,cb);
+    if ( !nsfin )   break;
+    nsdep = nsfin;
+    pt = &mesh->tria[nsdep];
+    if ( pt->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( nsdep != nsold ) {
+      st->size = sizeTria(mesh,nsdep);
+      nsold    = nsdep;
+    }
+
+    /* vector field interpolation */
+    st->norm = field2DInterp(mesh,nsdep,cb,v);
+    step     = HSIZ * min(st->size,st->norm);
+    if ( sc->par.maxtime < FLT_MAX )
+      step = min(0.05*sc->par.dt,step);
+    if ( step == 0.0 )   break;
+
+    nbp += filterPoint(sc,st,p,0);
+  }
+  while ( nbp < maxpts );
+  addPoint(sc,st,p,0);
+  glEnd();
+
+  if (  nbp >= maxpts || sc->par.maxtime < FLT_MAX ) {
+    glLineWidth(1.0);
+    glEndList();
+    fprintf(stdout,": %d (%d, %.2f) / %d lines",nbar,nbp,(float)nbp/nbar,k/3);
+    ct = difftime(clock(),ct);
+    fprintf(stdout," %6.2f sec.\n",ct);
+    if ( sc->par.maxtime < FLT_MAX ) {
+      fprintf(out,"%8.2f  %f %f\n",
+              sc->par.cumtim,p[0]+mesh->xtra,p[1]+mesh->ytra);
+      fclose(out);
+    }
+    return(1);
+  }
+
+  /* reverse orientation */
+  memcpy(p,pp,3*sizeof(float));
+  memcpy(cb,cbdep,3*sizeof(double));
+  memcpy(v,vdep,3*sizeof(double));
+  st->norm = normdep;
+  st->size = sizedep;
+  if ( st->size == 0.0 )
+    step = EPS * sc->dmax;
+  else
+    step = HSIZ* st->size;
+
+  /* build display list incrementally */
+  nsdep = nsold = depart;
+  glBegin(GL_LINE_STRIP);
+  addPoint(sc,st,p,0);
+  nbp++;
+
+  do {
+    /* move to next point */
+    if ( st->typtrack == Euler || !nxtPoint2D(mesh,nsdep,p,-step,v) ) {
+      p[0] -= step*v[0];
+      p[1] -= step*v[1];
+    }
+    if ( p[0]<st->xmin || p[1]<st->ymin || p[0]>st->xmax || p[1]>st->ymax )
+      break;
+
+    /* find tet containing p */
+    nsfin = locateTria(mesh,nsdep,++mesh->mark,p,cb);
+    if ( !nsfin )  break;
+    nsdep = nsfin;
+    pt = &mesh->tria[nsdep];
+    if ( pt->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( nsdep != nsold ) {
+      st->size = sizeTria(mesh,nsdep);
+      nsold    = nsdep;
+    }
+
+    /* vector field interpolation */
+    st->norm = field2DInterp(mesh,nsdep,cb,v);
+    step = HSIZ * min(st->size,st->norm);
+    if ( step == 0.0 )  break;
+
+    nbp += filterPoint(sc,st,p,0);
+  }
+  while ( nbp < maxpts );
+  addPoint(sc,st,p,0);
+  glEnd();
+  glLineWidth(1.0);
+  glEndList();
+
+  if ( !nbp ) {
+    st->nbstl--;
+    fprintf(stdout,".. empty.\n");
+    return(0);
+  }
+
+  /*if ( ddebug ) */
+  if ( nbar )
+    fprintf(stdout,": %d (%d, %.2f) / %d lines",nbar,nbp,(float)nbp/nbar,k/3);
+  ct = difftime(clock(),ct);
+  fprintf(stdout," %6.2f sec.\n",ct);
+
+  return(1);
+}
+
+
+int listSaddleStream(pScene sc,pMesh mesh,int depart,
+                     float *pp,float *vv,double lambda) {
+  pTriangle  pt;
+  pStream    st;
+  double     cb[3],v[3];
+  float      sens,step,p[3];
+  int        i,k,nsdep,nsfin,nsold,nbp,maxpts;
+
+  /* default */
+  if ( !mesh->nt )  return(0);
+  if ( ddebug ) printf("create streamlines for saddle point\n");
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* build display list */
+  st = sc->stream;
+  if ( st->nbstl > MAX_LST-1 )  return(0);
+  sc->slist[st->nbstl] = glGenLists(1);
+  glNewList(sc->slist[st->nbstl],GL_COMPILE);
+  if ( glGetError() )  return(0);
+  maxpts = max(MAX_PTS,5*mesh->nt);
+  glLineWidth(2.0);
+
+  st->nbstl++;
+  k = st->nbstl*3;
+  st->listp[k]   = p[0] = pp[0];
+  st->listp[k+1] = p[1] = pp[1];
+  st->listp[k+2] = p[2] = 0.0f;
+  
+  for (i=1; i<=mesh->nt; i++) {
+    pt = &mesh->tria[i];
+    pt->cpt = 0;
+  }
+ 
+  /* compute streamlines */
+  nsold = nsdep = depart;
+  nbp   = nbar   = 0;
+  glBegin(GL_LINE_STRIP);
+  addPoint(sc,st,pp,1);
+
+  st->size = sizeTria(mesh,depart);
+  st->norm = sqrt(vv[0]*vv[0] + vv[1]*vv[1]);
+  if ( st->size == 0.0f )
+    step = EPS * sc->dmax;
+  else
+    step = HSIZ* st->size;
+  if ( st->norm > 0.0f ) {
+    v[0] = vv[0] / st->norm;
+    v[1] = vv[1] / st->norm;
+  }
+  sens = lambda < 0.0f ? -1. : 1.;
+
+  /* build display list incrementally */
+  do {
+    /* move to next point */
+    if ( st->typtrack == Euler || !nxtPoint2D(mesh,nsdep,p,step,v) ) {
+      p[0] += sens*step*v[0];
+      p[1] += sens*step*v[1];
+    }
+
+    if ( p[0]<st->xmin || p[1]<st->ymin ||
+         p[0]>st->xmax || p[1]>st->ymax )  break;
+
+    /* find tet containing p */
+    nsfin = locateTria(mesh,nsdep,++mesh->mark,p,cb);
+    if ( !nsfin )  break;
+    nsdep = nsfin;
+    pt = &mesh->tria[nsdep];
+    if ( pt->cpt > MAX_CPT )  break;
+
+    /* adjust local stepsize */
+    if ( nsdep != nsold ) {
+      st->size = sizeTria(mesh,nsdep);
+      step  = HSIZ * st->size;
+      nsold = nsdep;
+    }
+
+    /* vector field interpolation */
+    st->norm = field2DInterp(mesh,nsdep,cb,v);
+    if ( st->norm < EPS*step )  break;
+    step = min(step,st->norm);
+    if ( step == 0.0f )  break;
+
+    nbp += filterPoint(sc,st,p,1);
+  }
+  while ( nbp < maxpts );
+  glEnd();
+  glLineWidth(1.0);
+  glEndList();
+
+  if ( !nbp ) {
+    glDeleteLists(sc->slist[st->nbstl--],1);
+    return(0);
+  }
+
+  return(1);
+}
+
+
+pStream createStream(pScene sc,pMesh mesh) {
+  pStream    st;
+
+  /* hash simplices */
+  if ( mesh->dim == 2 ) {
+    if ( mesh->nt && !hashTria(mesh) )    return(0);
+  }
+  else {
+    if ( mesh->ntet && !hashTetra(mesh) ) return(0);
+    if ( mesh->nhex && !hashHexa(mesh) )  return(0);
+  }
+
+  st = (pStream)calloc(1,sizeof(struct sstream));
+  if ( !st )  return(0);
+
+  /*st->typtrack = Euler;*/
+  st->typtrack = RK4;
+  st->stnp     = 0;
+  st->nbstl    = 0;
+
+  /* bounding box */
+  st->xmin = mesh->xmin - mesh->xtra;
+  st->ymin = mesh->ymin - mesh->ytra;
+  st->zmin = mesh->zmin - mesh->ztra;
+  st->xmax = mesh->xmax - mesh->xtra;
+  st->ymax = mesh->ymax - mesh->ytra;
+  st->zmax = mesh->zmax - mesh->ztra;
+
+  /* init list */
+  st->listp = (float*)malloc((MAX_LST*3+1)*sizeof(float));
+  assert(st->listp);
+
+  sc->slist = (GLuint*)calloc(MAX_LST,sizeof(GLuint));
+  if ( !sc->slist )  return(0);
+
+  return(st);
+}
+
+/* create from point picking */
+int streamRefPoint(pScene sc,pMesh mesh) {
+  pPoint    ppt;
+  float     s[3];
+
+  ppt = &mesh->point[refitem];
+  if ( ppt->flag )  return(0);
+  s[0] = ppt->c[0];
+  s[1] = ppt->c[1];
+  s[2] = ppt->c[2];
+  if ( mesh->dim == 2 )
+    listTriaStream(sc,mesh,s);
+  else {
+    if ( mesh->ntet )      listTetraStream(sc,mesh,s,0);
+    else if ( mesh->nhex ) listHexaStream(sc,mesh,s,0);
+  }
+  ppt->flag = 1;
+
+  return(1);
+}
+
+
+/* read starting point in file.iso */
+int streamIsoPoint(pScene sc,pMesh mesh) {
+  pStream   st;
+  int       k,nbp,nbstl;
+  time_t    t;
+
+  if ( !parseStream(sc,mesh) )  return(0);
+  t = clock();
+  fprintf(stdout," Building streamline(s)");
+  fflush(stdout);
+
+  st    = sc->stream;
+  nbstl = st->nbstl;
+  nbp   = 0;
+  st->nbstl = 0;
+  if ( mesh->dim == 3 ) {
+    if ( !mesh->ntet )  return(0);
+    nbp = 0;
+    for (k=1; k<=3*nbstl; k+=3) {
+printf("\n ici: %f %f %f\n",st->listp[k],st->listp[k+1],st->listp[k+2]);
+      nbp += listTetraStream(sc,mesh,&st->listp[k],1);
+    }
+  }
+
+  if ( !nbp )    return(0);
+  if ( ddebug )  printf("stream start: %d points  ",nbp);
+  fprintf(stdout,": %d lines",nbp);
+  t = clock() - t;
+  fprintf(stdout," %6.2f sec.\n",t/(float)CLOCKS_PER_SEC);
+
+  return(1);
+}
+
+
+int streamRefTria(pScene sc,pMesh mesh) {
+  pMaterial   pm;
+  pTriangle   pt;
+  pPoint      ppt;
+  float       s[3];
+  int         i,k,nmat,nbp,base;
+  time_t      t;
+
+  /* build list */
+  base = ++mesh->mark;
+  nbp  = 0;
+  pt   = &mesh->tria[refitem];
+
+  nmat = matRef(sc,pt->ref);
+  /*nmat = !pt->ref ? DEFAULT_MAT : 1+(pt->ref-1)%(sc->par.nbmat-1);*/
+  pm = &sc->material[nmat];
+  k  = pm->depmat[LTria];
+  if ( !k || pm->flag )  return(0);
+
+  t = clock();
+  fprintf(stdout," Building streamline(s)");
+  fflush(stdout);
+
+  for (i=1; i<=mesh->np; i++) {
+    ppt = &mesh->point[i];
+    ppt->mark = base;
+  }
+  ++base;
+  while ( k != 0 ) {
+    pt = &mesh->tria[k];
+    if ( !pt->v[0] ) {
+      k = pt->nxt;
+      continue;
+    }
+    for (i=0; i<3; i++) {
+      ppt = &mesh->point[pt->v[i]];
+      if ( ppt->mark != base ) {
+        ppt->mark = base;
+        s[0] = ppt->c[0];
+        s[1] = ppt->c[1];
+        s[2] = ppt->c[2];
+        if ( ++nbp > MAX_LST-1 ) break;
+        listTetraStream(sc,mesh,s,1);
+        ppt->flag = 1;
+      }
+    }
+    k = pt->nxt;
+  }
+  if ( !nbp )  return(0);
+  if ( ddebug )  printf("stream start: %d points  ",nbp);
+  fprintf(stdout,": %d lines",nbp);
+  t = clock() - t;
+  fprintf(stdout," %6.2f sec.\n",t/(float)CLOCKS_PER_SEC);
+
+  return(1);
+}
+
+int streamRefQuad(pScene sc,pMesh mesh) {
+  pMaterial   pm;
+  pQuad       pq;
+  pPoint      ppt;
+  float       s[3];
+  int         i,k,nmat,nbp,base;
+  time_t      t;
+
+  /* build list */
+  base = ++mesh->mark;
+  nbp  = 0;
+  pq   = &mesh->quad[refitem];
+
+  nmat = matRef(sc,pq->ref);
+  /*nmat = !pt->ref ? DEFAULT_MAT : 1+(pt->ref-1)%(sc->par.nbmat-1);*/
+  pm = &sc->material[nmat];
+  k  = pm->depmat[LQuad];
+  if ( !k || pm->flag )  return(0);
+
+  t = clock();
+  fprintf(stdout," Building streamline(s)");
+  fflush(stdout);
+
+  for (i=1; i<=mesh->np; i++) {
+    ppt = &mesh->point[i];
+    ppt->mark = base;
+  }
+  ++base;
+  while ( k != 0 ) {
+    pq = &mesh->quad[k];
+    if ( !pq->v[0] ) {
+      k = pq->nxt;
+      continue;
+    }
+    for (i=0; i<4; i++) {
+      ppt = &mesh->point[pq->v[i]];
+      if ( ppt->mark != base ) {
+        ppt->mark = base;
+        s[0] = ppt->c[0];
+        s[1] = ppt->c[1];
+        s[2] = ppt->c[2];
+        if ( ++nbp > MAX_LST-1 ) break;
+        listHexaStream(sc,mesh,s,1);
+        ppt->flag = 1;
+      }
+    }
+    k = pq->nxt;
+  }
+  if ( !nbp )  return(0);
+  if ( ddebug )  printf("stream start: %d points  ",nbp);
+  fprintf(stdout,": %d lines",nbp);
+  t = clock() - t;
+  fprintf(stdout," %6.2f sec.\n",t/(float)CLOCKS_PER_SEC);
+
+  return(1);
+}
diff --git a/src/medit/tiles.c b/src/medit/tiles.c
new file mode 100644
index 0000000..d80817b
--- /dev/null
+++ b/src/medit/tiles.c
@@ -0,0 +1,236 @@
+#include "medit.h"
+#include "sproto.h"
+#include "extern.h"
+
+extern ubyte ddebug;
+ubyte  tiling;
+
+#define IN2CM        2.54
+#define CM2IN        0.3937
+
+
+void dumpTile(char *data,int width,int height,GLubyte *buffer) {
+  FILE *out2; 
+
+  out2 = fopen(data,"w");
+  fprintf(out2,"P6\n");
+  fprintf(out2,"# Created using medit %s %s, (c) INRIA\n",ME_VER,ME_REL);
+  fprintf(out2,"%d %d\n",width,height);
+  fprintf(out2,"255\n");
+  fwrite(buffer,sizeof(GLubyte),width*height*3,out2);
+  fclose(out2);
+}
+
+
+/* dump big image */
+int imgTiling(pScene sc,char *data,char key) {
+  FILE     *out;
+  pCamera   c = sc->camera;
+  GLubyte  *tile,*buffer,*rowPtr;
+  GLint     matmode,viewport[4];
+  double    xmin,xmax,ymin,ymax,left,right,top,bottom,ratio;
+  float     debhaut,finhaut,deblarg,finlarg,look[3];
+  int       i,tw,th,col,row,nbcol,nbrow;
+  int       imgWidth,imgHeight,tileWidth,tileHeight,tileWidthNB,tileHeightNB;
+  int       bitsTileRow,bitsImgOffset,bitsCurTileRow,border;
+  int       bitsTileOffset,bitsPixel,imgRowSize;
+  char     *ptr,name[256];
+  ubyte     bckbyte;
+  static GLfloat up[3] = { 0.0, 1.0, 0.0};
+
+  glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+  bckbyte = (ubyte)(255*(0.30*sc->par.back[0] + 
+                         0.59*sc->par.back[1] + 
+                         0.11*sc->par.back[2])+ 0.5);
+
+  /* compute image size */
+  ratio = (double)sc->par.xs/(double)sc->par.ys;
+  ymax  = 0.1f*sc->dmax * tan(sc->persp->fovy * M_PI/360.0);
+  ymin  = -ymax;
+  xmin  = ymin * ratio;
+  xmax  = ymax * ratio;
+
+  bitsPixel  = 3 * sizeof(GLubyte);
+  imgWidth   = (int)(sc->par.dpi*CM2IN*sc->par.cm+0.5);
+  imgHeight  = (int)((double)imgWidth / ratio +0.5);
+  imgRowSize = imgWidth * bitsPixel;
+
+  tileWidth    = sc->par.xs;
+  tileHeight   = sc->par.ys;
+  border       = sc->mode & S_BDRY ? 1 : 0;
+  tileWidthNB  = tileWidth  - 2*border;
+  tileHeightNB = tileHeight - 2*border;
+
+  if ( ddebug ) {
+    fprintf(stdout,"   Generating %d by %d image\n",imgWidth,imgHeight);
+    fprintf(stdout,"   tile %d x %d\n",tileWidth,tileHeight);
+    fprintf(stdout,"   image size %f x %f cm\n",
+            sc->par.cm,(double)imgHeight/sc->par.dpi/CM2IN);
+  }
+
+  /* buffer to store one tile */
+  tile = (GLubyte*)calloc(tileWidthNB*tileHeightNB,bitsPixel);
+  if ( !tile ) {
+    fprintf(stderr,"  ## Unable to store buffer!\n");
+    return(0);
+  }
+  
+  /* buffer for a row of tiles */
+  buffer = (GLubyte*)calloc(imgWidth*tileHeightNB,bitsPixel);
+  if ( !buffer ) {
+    free(tile);
+    fprintf(stderr,"  ## Unable to store a row of tiles!\n");
+    return(0);
+  }
+  
+  /* open EPS file */
+  strcpy(name,data);
+  ptr  = (char*)strstr(name,".ps");
+  if ( !ptr ) strcat(name,".ps");
+  out = fopen(name,"w");
+  if ( !out ) {
+    fprintf(stderr,"  ## Unable to open file %s.\n",name);
+    free(tile);
+    return(0);
+  }
+  writeEPSheader(out,name,key,imgWidth,imgHeight,sc->par.cm,sc->par.dpi);
+  
+  /* save current viewport */
+  glGetIntegerv(GL_VIEWPORT,viewport);
+  glDrawBuffer(GL_BACK_LEFT);
+  glReadBuffer(GL_BACK_LEFT);
+
+  /* dump tiles */
+  nbcol  = (int)((float)imgWidth / tileWidthNB)  + 1;
+  nbrow  = (int)((float)imgHeight/ tileHeightNB) + 1;
+  tiling = 1;  
+  th = tileHeightNB;
+  finhaut = sc->par.ys;
+
+  for (row=nbrow-1; row>=0; row--) {
+    if ( row < nbrow-1 )
+      th = tileHeightNB;
+    else
+      th = imgHeight - row*tileHeightNB;
+    debhaut = finhaut - sc->par.ys * th / imgHeight;
+    deblarg = 0;
+    
+    for (col=0; col<nbcol; col++) {
+      if ( col < nbcol-1 )
+        tw = tileWidthNB;
+      else
+        tw = imgWidth - col*tileWidthNB;
+      if ( th > tileHeightNB || tw > tileWidthNB ) {
+        fprintf(stderr,"  %%%% Wrong tile size (%d,%d).\n",th,tw);
+        free(buffer);
+        free(tile);
+        return(0); 
+      }
+      finlarg = deblarg + sc->par.xs * tw / imgWidth;
+
+      /* set viewport to tilesize (with border) */
+      glViewport(0,0,tw+2*border,th+2*border);
+
+      /* current matrix */
+      glGetIntegerv(GL_MATRIX_MODE,&matmode);
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glMultMatrixf(sc->persp->matrix);
+
+      /* compute projection parameters */
+      if ( sc->persp->pmode == PERSPECTIVE ) {
+        left   = xmin   + (xmax-xmin) * (col*tileWidthNB) / imgWidth;
+        right  = left   + (xmax-xmin) * tw / imgWidth;
+        bottom = ymin   + (ymax-ymin) * (row*tileHeightNB) / imgHeight;
+        top    = bottom + (ymax-ymin) * th / imgHeight;
+
+        glFrustum(left,right,bottom,top,0.1*sc->dmax,10.0f*sc->dmax);
+        glTranslatef(0.0f,0.0,sc->persp->depth);
+      }
+      else if ( sc->persp->pmode == CAMERA ) {
+        left   = xmin   + (xmax-xmin) * (col*tileWidthNB) / imgWidth;
+        right  = left   + (xmax-xmin) * tw / imgWidth;
+        bottom = ymin   + (ymax-ymin) * (row*tileHeightNB) / imgHeight;
+        top    = bottom + (ymax-ymin) * th / imgHeight;
+
+        glFrustum(left,right,bottom,top,0.1f*sc->dmax,10.0f*sc->dmax);
+
+        look[0] = c->eye[0] + 0.001*sc->dmax*c->speed[0];
+        look[1] = c->eye[1] + 0.001*sc->dmax*c->speed[1];
+        look[2] = c->eye[2] + 0.001*sc->dmax*c->speed[2];
+        gluLookAt(c->eye[0],c->eye[1],c->eye[2], 
+                  look[0],look[1],look[2],
+                  up[0],up[1],up[2]);
+        glTranslatef(0.0f,0.0f,0.5*sc->persp->depth);
+      }
+      else if ( sc->persp->pmode == ORTHO ) {
+        glOrtho(-1.,1.,-1.,0.1,0.01,0.01);
+        glTranslatef(0.0,0.0,sc->persp->depth);
+      }
+
+      /* redraw scene */
+      glDisable(GL_LIGHTING);
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+      /*gluLookAt(0.,0.,-sc->persp->depth, 0.,0.,0., 0.0,1.0,0.0);*/
+
+      glMultMatrixf(sc->view->matrix);
+      glTranslatef(sc->cx,sc->cy,sc->cz);
+      drawModel(sc);
+
+      /* read buffer */
+      glFlush();
+      glReadPixels(border,border,tileWidthNB,tileHeightNB,
+                   GL_RGB,GL_UNSIGNED_BYTE,tile);
+
+      /* store to row buffer */
+      bitsImgOffset  = col * tileWidthNB * bitsPixel;
+      bitsTileRow    = tileWidthNB * bitsPixel;
+      bitsCurTileRow = tw * bitsPixel;
+      bitsTileOffset = border*bitsPixel;
+      bitsTileOffset = 0;
+      for (i=0; i<th; i++) {
+        memcpy(buffer + i*imgRowSize  + bitsImgOffset,
+               tile   + i*bitsTileRow + bitsTileOffset,
+               bitsCurTileRow);
+      }
+      deblarg = finlarg+1;
+    }
+    finhaut = debhaut-1;
+
+    /* modify color */
+    if ( sc->par.coeff > 0.0f ) {
+      for (i=0; i<imgWidth*tileHeightNB*bitsPixel; i++)
+        if ( buffer[i] > 10 )
+          buffer[i] += (255-buffer[i]) * sc->par.coeff;
+        else
+          buffer[i] += buffer[i] * sc->par.coeff;
+    }
+
+    /* write row of tiles */
+    for (i=0; i<th; i++) {
+      /* reverse image */
+      rowPtr = buffer + (th-1-i) * imgRowSize;
+      writeEPSRow(out,key,rowPtr,imgWidth,bckbyte);
+    }
+  }
+
+  writeEPStrailer(out);
+  fclose(out);
+  free(tile);
+  free(buffer);
+  tiling = 0;
+  
+  /* restore viewport */
+  glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
+  glDrawBuffer(GL_FRONT | GL_BACK);
+
+  farclip(GL_TRUE);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  if ( ddebug ) fprintf(stdout,"   Tiling completed.\n");
+  return(1);
+}
diff --git a/src/medit/transform.c b/src/medit/transform.c
new file mode 100644
index 0000000..c3e7189
--- /dev/null
+++ b/src/medit/transform.c
@@ -0,0 +1,36 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+void resetTransform(pTransform tr) {
+  static float  itransf[16] = { 1., 0., 0., 0.,  0., 1., 0., 0.,
+				0., 0., 1., 0.,  0., 0., 0., 1.};
+
+  tr->pos[0] = tr->pos[1] = tr->pos[2] = 0.0f;
+  tr->angle  = 0.0f;
+  tr->panx   = tr->pany  = 0.0f;
+  tr->opanx  = tr->opany = 0.0f;
+  tr->mstate = 1;  
+  tr->manim  = GL_FALSE;
+
+  memcpy(tr->matrix,itransf,16*sizeof(float));
+  memcpy(tr->rot,itransf,16*sizeof(float));
+  memcpy(tr->tra,itransf,16*sizeof(float));
+}
+
+pTransform createTransform() {
+  pTransform   tr;
+
+  /* default */
+  if ( ddebug) printf("create transformation\n");
+
+  tr = (pTransform)M_calloc(1,sizeof(struct transform),"transform") ;
+  assert(tr);
+
+  /* set default values */
+  resetTransform(tr);
+  tr->mbutton = 0;
+
+  return(tr);
+}
diff --git a/src/medit/util.c b/src/medit/util.c
new file mode 100644
index 0000000..e22ff99
--- /dev/null
+++ b/src/medit/util.c
@@ -0,0 +1,278 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <math.h>
+#include <stdarg.h>
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+static GLfloat IdMatrix[16] = {
+   1.0, 0.0, 0.0, 0.0,
+   0.0, 1.0, 0.0, 0.0,
+   0.0, 0.0, 1.0, 0.0,
+   0.0, 0.0, 0.0, 1.0
+};
+
+/* set font style and size */
+void setFont(char* name,int size) {
+  GLvoid *font_style = GLUT_BITMAP_HELVETICA_10;
+
+  if ( !strcmp(name,"helvetica") ) {
+    if (size == 12)
+      font_style = GLUT_BITMAP_HELVETICA_12;
+    else if (size == 18)
+      font_style = GLUT_BITMAP_HELVETICA_18;
+  }
+  else if (strcmp(name, "times roman") == 0) {
+    font_style = GLUT_BITMAP_TIMES_ROMAN_10;
+    if (size == 24)
+      font_style = GLUT_BITMAP_TIMES_ROMAN_24;
+  }
+  /*
+  else if (strcmp(name, "8x13") == 0)
+    font_style = GLUT_BITMAP_8_BY_13;
+  */
+  else if (strcmp(name, "9x15") == 0)
+    font_style = GLUT_BITMAP_9_BY_15;
+}
+
+/* display string format at pos(x,y) */
+void drwstr(GLuint x,GLuint y,char* format, ...) {
+  va_list  args;
+  char    *s,buffer[255];
+
+  va_start(args,format);
+  vsprintf(buffer,format,args);
+  va_end(args);
+
+  glRasterPos2i(x,y);
+  for (s=buffer; *s; s++)
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,*s);
+}
+
+void output2(GLfloat x,GLfloat y,char *format,...) {
+  va_list  args;
+  char    *s,buffer[255];
+
+  /*strcpy(myerror.procname,"output2");*/
+  va_start(args,format);
+  vsprintf(buffer,format,args);
+  va_end(args);
+
+  glRasterPos2f(x,y);
+  for (s=buffer; *s; s++) {
+    /*glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,*s);*/
+    /*glutBitmapCharacter(font_style,*s);*/
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10,*s);
+  }
+}
+
+void output3(GLfloat x,GLfloat y,GLfloat z,char *format,...) {
+  va_list args;
+  char buffer[255], *s;
+
+  /*strcpy(myerror.procname,"output3");*/
+  va_start(args,format);
+  vsprintf(buffer,format,args);
+  va_end(args);
+  glRasterPos3f(x,y,z);
+  for (s=buffer; *s; s++)
+    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10,*s);
+}
+
+/* color converter */
+void hsvrgb(double *hsv,double *rgb) {
+  double f,p,q,t;
+  int    i;
+
+  hsv[0] = ((int)hsv[0] % 360) / 60.;
+  i = (int)floor((double)hsv[0]);    /* largest int <= h     */
+  f = hsv[0] - i;                    /* fractional part of h */
+  p = hsv[2] * (1.0 - hsv[1]);
+  q = hsv[2] * (1.0 - (hsv[1] * f));
+  t = hsv[2] * (1.0 - (hsv[1] * (1.0 - f)));
+
+  switch(i) {
+  case 0: rgb[0] = hsv[2]; rgb[1] = t;      rgb[2] = p; break;
+  case 1: rgb[0] = q;      rgb[1] = hsv[2]; rgb[2] = p; break;
+  case 2: rgb[0] = p;      rgb[1] = hsv[2]; rgb[2] = t; break;
+  case 3: rgb[0] = p;      rgb[1] = q;      rgb[2] = hsv[2]; break;
+  case 4: rgb[0] = t;      rgb[1] = p;      rgb[2] = hsv[2]; break;
+  case 5: rgb[0] = hsv[2]; rgb[1] = p;      rgb[2] = q; break;
+  }
+}
+
+/* transform: u = MxV */
+void transformPoint(double u[4],float v[4],float m[16]) {
+  u[0] = v[0] * m[0]  + v[1] * m[1]  + v[2] * m[2]  + v[3] * m[3];
+  u[1] = v[0] * m[4]  + v[1] * m[5]  + v[2] * m[6]  + v[3] * m[7];
+  u[2] = v[0] * m[8]  + v[1] * m[9]  + v[2] * m[10] + v[3] * m[11];
+  u[3] = v[0] * m[12] + v[1] * m[13] + v[2] * m[14] + v[3] * m[15];
+}
+
+void transformPoint2(double u[4],float v[4],float m[16]) {
+  u[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8]  + v[3] * m[12];
+  u[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9]  + v[3] * m[13];
+  u[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14];
+  u[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15];
+}
+
+void transformPointd(double u[3],double v[3],double m[16]) {
+  u[0] = v[0] * m[0]  + v[1] * m[1]  + v[2] * m[2];
+  u[1] = v[0] * m[4]  + v[1] * m[5]  + v[2] * m[6];
+  u[2] = v[0] * m[8]  + v[1] * m[9]  + v[2] * m[10];
+}
+
+void transformVector(float u[4],float v[4],float m[16]) {
+  u[0] = v[0] * m[0] + v[1] * m[4] + v[2] * m[8];
+  u[1] = v[0] * m[1] + v[1] * m[5] + v[2] * m[9];
+  u[2] = v[0] * m[2] + v[1] * m[6] + v[2] * m[10];
+  u[3] = v[0] * m[3] + v[1] * m[7] + v[2] * m[11];
+}
+
+
+/* p = axb */
+void multMatrix(GLfloat *p,GLfloat *a,GLfloat *b) {
+  GLint i,row;
+
+  for (i=0; i<4; i++) {
+    row = i*4;
+    p[row+0] = a[row] * b[0] + a[row+1] * b[4] + a[row+2] * b[8]  + a[row+3] * b[12];
+    p[row+1] = a[row] * b[1] + a[row+1] * b[5] + a[row+2] * b[9]  + a[row+3] * b[13];
+    p[row+2] = a[row] * b[2] + a[row+1] * b[6] + a[row+2] * b[10] + a[row+3] * b[14];
+    p[row+3] = a[row] * b[3] + a[row+1] * b[7] + a[row+2] * b[11] + a[row+3] * b[15];
+  }
+}
+
+void rotateMatrix(GLfloat angle,GLfloat x,GLfloat y,GLfloat z,GLfloat rm[16]) {
+   GLfloat mag,s,c;
+   GLfloat xx,yy,zz,xy,yz,zx,xs,ys,zs,one_c;
+
+   if ( angle == 0.0f ) {
+     memcpy(rm,IdMatrix,16*sizeof(GLfloat));
+     return;
+   }
+   mag = x*x + y*y + z*z;
+
+   if ( mag == 0.0f ) {
+     memcpy(rm,IdMatrix,16*sizeof(GLfloat));
+     return;
+   }
+   mag = 1.0f / sqrt(mag);
+   x *= mag;    
+   y *= mag;    
+   z *= mag;
+   s  = sin(angle * DTOR);
+   c  = cos(angle * DTOR);
+   xx = x*x;  yy = y*y;  zz = z*z;
+   xy = x*y;  yz = y*z;  zx = z*x;
+   xs = x*s;  ys = y*s;  zs = z*s;
+   one_c = 1.0f - c;
+
+   rm[0] = (one_c * xx) + c;
+   rm[1] = (one_c * xy) - zs;
+   rm[2] = (one_c * zx) + ys;
+   rm[3]  = 0.0f;
+
+   rm[4] = (one_c * xy) + zs;
+   rm[5] = (one_c * yy) + c;
+   rm[6] = (one_c * yz) - xs;
+   rm[7] = 0.0f;
+
+   rm[8] = (one_c * zx) - ys;
+   rm[9] = (one_c * yz) + xs;
+   rm[10] = (one_c * zz) + c;
+   rm[11] = 0.0f;
+
+   rm[12] = rm[13] = rm[14] = 0.0f;
+   rm[15] = 1.0f;
+}
+
+int invertMatrix(float src[16],float inverse[16]) {
+  double  t;
+  int     i, j, k, swap;
+  double  tmp[4][4];
+
+  memcpy(inverse,IdMatrix,16*sizeof(GLfloat));
+  for (i=0; i<4; i++)
+    for (j=0; j<4; j++)
+      tmp[i][j] = src[i*4+j];
+
+  for (i=0; i<4; i++) {
+    /* look for largest element in column. */
+    swap = i;
+    for (j=i+1; j<4; j++) {
+      if ( fabs(tmp[j][i]) > fabs(tmp[i][i]) )
+	swap = j;
+    }
+    if ( swap != i ) {
+      /* swap rows. */
+      for (k=0; k<4; k++) {
+	t            = tmp[i][k];
+	tmp[i][k]    = tmp[swap][k];
+	tmp[swap][k] = t;
+	t                 = inverse[i*4+k];
+	inverse[i*4+k]    = inverse[swap*4+k];
+	inverse[swap*4+k] = t;
+      }
+    }
+    /* The matrix is singular. */
+    if ( tmp[i][i] == 0 )
+      return(0);
+    
+    t = tmp[i][i];
+    for (k=0; k<4; k++) {
+      tmp[i][k]      /= t;
+      inverse[i*4+k] /= t;
+    }
+    for (j=0; j<4; j++) {
+      if ( j != i ) {
+	t = tmp[j][i];
+	for (k=0; k<4; k++) {
+	  tmp[j][k]      -= tmp[i][k]*t;
+	  inverse[j*4+k] -= inverse[i*4+k]*t;
+	}
+      }
+    }
+  }
+
+  return(1);
+}
+
+void print_matrix(const GLfloat m[16],const char *ligne) {
+  int i;
+
+  printf("---- %s ----\n",ligne);
+  for (i=0; i<4; i++)
+    printf("%f %f %f %f\n",m[i],m[4+i],m[8+i],m[12+i]);
+  printf("---------------------------------\n");
+}
+
+void print_matrixd(const GLdouble m[16],const char *ligne) {
+  int i;
+
+  printf("---- %s ----\n",ligne);
+  for (i=0; i<4; i++)
+    printf("%f %f %f %f\n",m[i],m[4+i],m[8+i],m[12+i]);
+  printf("---------------------------------\n");
+}
+int filnum(char *data,int numdep,char *ext) {
+  FILE  *in;
+  char   tmpstr[256];
+
+  do {
+    sprintf(tmpstr,"%s.%.3d.%s",data,numdep,ext);
+    in = fopen(tmpstr,"r");
+    if ( !in ) return(numdep);
+    fclose(in);
+  }
+  while ( ++numdep < 999 );
+  return(-1);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/medit/vector.c b/src/medit/vector.c
new file mode 100644
index 0000000..f4cf10f
--- /dev/null
+++ b/src/medit/vector.c
@@ -0,0 +1,780 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+#define SCALV      1.0e-04
+#define EPST       1.e-14
+#define COSPI15    .9781476007338057
+#define SINPI15    .2079116908177593
+
+
+/* draw a vector in 3D: u = unit vector */
+void drawVector3D(float p[3],double u[3],double scale) {
+  double   c[3],cc[3],m[9],dd,scal5;
+
+  /* local frame */
+  m[0] = u[0];  m[1] = u[1];  m[2] = u[2];
+
+  if ( fabs(u[0]) > EPS ) {
+    m[3] = -(u[1]+u[2]) / u[0];
+    m[4] = m[5] = 1.0f;
+  }
+  else if ( fabs(u[1]) > EPS ) {
+    m[4] = -(u[0]+u[2]) / u[1];
+    m[3] = m[5] = 1.0f;
+  }
+  else {
+    m[5] = -(u[0]+u[1]) / u[2];
+    m[3] = m[4] = 1.0;
+  }
+  dd = 1.0 / sqrt(m[3]*m[3] + m[4]*m[4] + m[5]*m[5]);
+  m[3] *= dd;
+  m[4] *= dd;
+  m[5] *= dd;
+  
+  m[6] = m[1]*m[5] - m[2]*m[4];
+  m[7] = m[2]*m[3] - m[0]*m[5];
+  m[8] = m[0]*m[4] - m[3]*m[1];
+
+  u[0] *= scale;
+  u[1] *= scale;
+  u[2] *= scale;
+  c[0] = p[0] + u[0];
+  c[1] = p[1] + u[1];
+  c[2] = p[2] + u[2];
+  glVertex3fv(p);
+  glVertex3dv(c);
+
+  /* draw 4 arrows */
+  scal5 = scale / 10.0;
+  cc[0] = -COSPI15*scal5;
+  cc[1] =  0.0;
+  cc[2] =  SINPI15*scal5;
+
+  /* M^-1 . X */
+  glVertex3dv(c);
+  glVertex3d(c[0]+(m[0]*cc[0]+m[6]*cc[2]),
+             c[1]+(m[1]*cc[0]+m[7]*cc[2]),
+             c[2]+(m[2]*cc[0]+m[8]*cc[2]));
+
+  cc[0] = -COSPI15*scal5;
+  cc[2] = -cc[2];
+  glVertex3dv(c);
+  glVertex3d(c[0]+(m[0]*cc[0]+m[6]*cc[2]),
+             c[1]+(m[1]*cc[0]+m[7]*cc[2]),
+             c[2]+(m[2]*cc[0]+m[8]*cc[2]));
+
+  cc[0] = -COSPI15*scal5;
+  cc[1] =  SINPI15*scal5;
+  cc[2] =  0.0;
+  glVertex3dv(c);
+  glVertex3d(c[0]+(m[0]*cc[0]+m[3]*cc[1]),
+             c[1]+(m[1]*cc[0]+m[4]*cc[1]),
+             c[2]+(m[2]*cc[0]+m[5]*cc[1]));
+
+  cc[1] = -cc[1];
+  glVertex3dv(c);
+  glVertex3d(c[0]+(m[0]*cc[0]+m[3]*cc[1]),
+             c[1]+(m[1]*cc[0]+m[4]*cc[1]),
+             c[2]+(m[2]*cc[0]+m[5]*cc[1]));
+}
+
+void drawVector2D(float p[2],double u[2],double scale) {
+  double   c[2],dx,dy;
+
+  u[0] *= scale;
+  u[1] *= scale;
+  c[0] = p[0] + u[0];
+  c[1] = p[1] + u[1];
+  glVertex2fv(p);
+  glVertex2dv(c);
+
+  dx = ( COSPI15*u[0] + SINPI15*u[1]) / 3.0;
+  dy = (-SINPI15*u[0] + COSPI15*u[1]) / 3.0;
+  glVertex2dv(c);
+  glVertex2d(c[0]-dx,c[1]-dy);
+
+  dx = ( COSPI15*u[0] - SINPI15*u[1]) / 3.0;
+  dy = ( SINPI15*u[0] + COSPI15*u[1]) / 3.0;
+  glVertex2dv(c);
+  glVertex2d(c[0]-dx,c[1]-dy);
+}
+
+
+GLuint listClipTetraVector(pMesh mesh) {
+  pMaterial   pm;
+  pTetra      pt;
+  pPoint      ppt;
+  pSolution   ps0;
+  pScene      sc;
+  pClip       clip;
+  double      rgb[3],u[3],epsra,iso,kc,dd,scal,scalemin,scalemax;
+  float       cp[3];
+  GLuint      dlist = 0;
+  int         ia,k,l,m;
+  static double hsv[3] = { 0.0f, 1.0f, 0.80f };
+
+  /* default */
+  if ( !mesh->ntet || !mesh->nbb )  return(0);
+  if ( ddebug ) printf("create vector list for clip\n");
+
+  sc   = cv.scene[currentScene()];
+  clip = sc->clip;
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* create display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  scalemin = sc->dmax * SCALV;
+  scalemax = 10.0*scalemin;
+  mesh->mark++;
+  glLineWidth(2.0);
+
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LTets];
+    if ( !k || pm->flag )  continue;
+ 
+    glBegin(GL_LINES);
+    while ( k != 0 ) {
+      pt = &mesh->tetra[k];
+      if ( !pt->v[0] || !pt->clip ) {
+        k = pt->nxt;
+        continue;
+      }
+ 
+      /* element size */
+      scal  = 0.5*sizeTetra(mesh,k);
+      epsra = EPST * scal;
+
+      /* linear interpol. */
+      if ( mesh->typage == 2 )
+        for (l=0; l<4; l++) {
+          ppt = &mesh->point[pt->v[l]];
+          if ( ppt->mark == mesh->mark )  continue;
+          ppt->mark = mesh->mark;
+
+          ps0 = &mesh->sol[pt->v[l]];
+          dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]\
+                         + ps0->m[2]*ps0->m[2]);
+          if ( dd < epsra )  continue;
+
+          /* color =  norm */
+          if ( iso < sc->iso.val[0] ) 
+            iso = sc->iso.val[0];  
+          else if ( iso > sc->iso.val[MAXISO-1] )
+            iso = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( iso < sc->iso.val[ia] )  break;
+          kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+          glColor3dv(rgb);
+
+          /* 3D vectors */
+          dd    = 1.0 / dd;
+          u[0]  = ps0->m[0] * dd;
+          u[1]  = ps0->m[1] * dd;
+          u[2]  = ps0->m[2] * dd;
+          cp[0] = ppt->c[0];
+          cp[1] = ppt->c[1];
+          cp[2] = ppt->c[2];
+          drawVector3D(cp,u,scal);
+        }
+      else {
+        cp[0] = cp[1] = cp[2] = 0.0;
+        for (l=0; l<4; l++) {
+          ppt = &mesh->point[pt->v[l]];
+          cp[0] += ppt->c[0];
+          cp[1] += ppt->c[1];
+          cp[2] += ppt->c[2];
+        }
+        cp[0] *= 0.25;
+        cp[1] *= 0.25;
+        cp[2] *= 0.25;
+        
+        /* color = norm */
+        ps0 = &mesh->sol[k];
+        dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]\
+                        +ps0->m[2]*ps0->m[2]);
+        if ( dd > epsra ) {
+          if ( iso < sc->iso.val[0] ) 
+            iso = sc->iso.val[0];  
+          else if ( iso > sc->iso.val[MAXISO-1] )
+            iso = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( iso < sc->iso.val[ia] )  break;
+          kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+          glColor3dv(rgb);
+
+          dd    = 1.0 / dd;
+          u[0]  = ps0->m[0] * dd;
+          u[1]  = ps0->m[1] * dd;
+          u[2]  = ps0->m[2] * dd;
+          drawVector3D(cp,u,scal);
+        }
+      }
+      k = pt->nxt;
+    }
+    glEnd();
+  }
+  glLineWidth(1.0);
+  glEndList();
+
+  return(dlist);
+}
+
+GLuint listClipHexaVector(pMesh mesh) {
+  pMaterial   pm;
+  pHexa       ph;
+  pPoint      ppt;
+  pSolution   ps0;
+  pScene      sc;
+  pClip       clip;
+  double      rgb[3],u[3],epsra,iso,kc,dd,scal,scalemin,scalemax;
+  float       cp[3];
+  GLuint      dlist = 0;
+  int         ia,k,l,m;
+  static double hsv[3] = { 0.0f, 1.0f, 0.80f };
+
+  /* default */
+  if ( !mesh->nhex || !mesh->nbb )  return(0);
+  if ( ddebug ) printf("create vector list for clip\n");
+
+  sc   = cv.scene[currentScene()];
+  clip = sc->clip;
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+
+  /* create display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  /* build list */
+  scalemin = sc->dmax * SCALV;
+  scalemax = 10.0*scalemin;
+  mesh->mark++;
+  glLineWidth(2.0);
+
+  for (m=0; m<sc->par.nbmat; m++) {
+    pm = &sc->material[m];
+    k  = pm->depmat[LHexa];
+    if ( !k || pm->flag )  continue;
+ 
+    glBegin(GL_LINES);
+    while ( k != 0 ) {
+      ph = &mesh->hexa[k];
+      if ( !ph->v[0] || !ph->clip ) {
+        k = ph->nxt;
+        continue;
+      }
+ 
+      /* element size */
+      scal  = 0.5*sizeHexa(mesh,k);
+      epsra = EPST * scal;
+
+      /* linear interpol. */
+      if ( mesh->typage == 2 )
+        for (l=0; l<8; l++) {
+          ppt = &mesh->point[ph->v[l]];
+          if ( ppt->mark == mesh->mark )  continue;
+          ppt->mark = mesh->mark;
+
+          ps0 = &mesh->sol[ph->v[l]];
+          dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]\
+                         + ps0->m[2]*ps0->m[2]);
+          if ( dd < epsra )  continue;
+
+          /* color =  norm */
+          if ( iso < sc->iso.val[0] ) 
+            iso = sc->iso.val[0];  
+          else if ( iso > sc->iso.val[MAXISO-1] )
+            iso = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( iso < sc->iso.val[ia] )  break;
+          kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+          glColor3dv(rgb);
+
+          /* 3D vectors */
+          dd    = 1.0 / dd;
+          u[0]  = ps0->m[0] * dd;
+          u[1]  = ps0->m[1] * dd;
+          u[2]  = ps0->m[2] * dd;
+          cp[0] = ppt->c[0];
+          cp[1] = ppt->c[1];
+          cp[2] = ppt->c[2];
+          drawVector3D(cp,u,scal);
+        }
+      else {
+        cp[0] = cp[1] = cp[2] = 0.0;
+        for (l=0; l<8; l++) {
+          ppt = &mesh->point[ph->v[l]];
+          cp[0] += ppt->c[0];
+          cp[1] += ppt->c[1];
+          cp[2] += ppt->c[2];
+        }
+        cp[0] *= 0.125;
+        cp[1] *= 0.125;
+        cp[2] *= 0.125;
+        
+        /* color = norm */
+        ps0 = &mesh->sol[k];
+        dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]\
+                        +ps0->m[2]*ps0->m[2]);
+        if ( dd > epsra ) {
+          if ( iso < sc->iso.val[0] ) 
+            iso = sc->iso.val[0];  
+          else if ( iso > sc->iso.val[MAXISO-1] )
+            iso = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( iso < sc->iso.val[ia] )  break;
+          kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+          glColor3dv(rgb);
+
+          dd    = 1.0 / dd;
+          u[0]  = ps0->m[0] * dd;
+          u[1]  = ps0->m[1] * dd;
+          u[2]  = ps0->m[2] * dd;
+          drawVector3D(cp,u,scal);
+        }
+      }
+      k = ph->nxt;
+    }
+    glEnd();
+  }
+  glLineWidth(1.0);
+  glEndList();
+
+  return(dlist);
+}
+
+
+GLuint listTria2dVector(pMesh mesh) {
+  pMaterial   pm;
+  pTriangle   pt;
+  pPoint      ppt;
+  pSolution   ps0;
+  pScene      sc;
+  double      rgb[3],u[2],epsra,iso,kc,dd,scalemin,scalemax,scal;
+  float       cp[2];
+  GLuint      dlist = 0;
+  int         ia,i,k,l,m;
+  static double hsv[3] = { 0.0f, 1.0f, 0.80f };
+
+  /* default */
+  if ( !mesh->nt || !mesh->nbb )  return(0);
+
+  sc    = cv.scene[currentScene()];
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( ddebug ) printf("create vector list\n");
+
+  /* create display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  scalemin = sc->dmax * SCALV;
+  scalemax = 15*scalemin;
+  mesh->mark++;
+  glLineWidth(3.0);
+
+  if ( mesh->typage == 2 ) {
+    glBegin(GL_LINES);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTria];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        scal  = 0.5*sizeTria(mesh,k);
+        epsra = EPST * scal;
+
+        for (i=0; i<3; i++) {
+          ppt = &mesh->point[pt->v[i]];
+          if ( ppt->mark == mesh->mark )  continue;
+          ppt->mark = mesh->mark;
+
+          ps0 = &mesh->sol[pt->v[i]];
+          dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]);
+          if ( dd < epsra )  continue;
+
+          /* color = norm */
+          if ( iso < sc->iso.val[0] ) 
+            iso = sc->iso.val[0];  
+          else if ( iso > sc->iso.val[MAXISO-1] )
+            iso = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( iso < sc->iso.val[ia] )  break;
+          kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+          glColor3dv(rgb);
+
+          dd    = 1.0 / dd;
+          u[0]  = ps0->m[0] * dd;
+          u[1]  = ps0->m[1] * dd;
+          cp[0] = ppt->c[0];
+          cp[1] = ppt->c[1];
+          drawVector2D(cp,u,scal);
+        }
+        k = pt->nxt; 
+      }
+    }
+    glEnd();
+  }
+  else {
+    glBegin(GL_LINES);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTria];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        scal  = 0.5*sizeTria(mesh,k);
+        epsra = EPST * scal;
+        cp[0] = cp[1] = 0.0;
+        for (l=0; l<3; l++) {
+          ppt = &mesh->point[pt->v[l]];
+          cp[0] += ppt->c[0];
+          cp[1] += ppt->c[1];
+        }
+        cp[0] /= 3.0;
+        cp[1] /= 3.0;
+
+        /* color = norm */
+        ps0 = &mesh->sol[k];
+        dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]);
+        if ( dd < epsra ) {
+          k = pt->nxt; 
+          continue;
+        }
+        if ( iso < sc->iso.val[0] ) 
+          iso = sc->iso.val[0];  
+        else if ( iso > sc->iso.val[MAXISO-1] )
+          iso = sc->iso.val[MAXISO-1];
+        for (ia=0; ia<MAXISO-1; ia++)
+          if ( iso < sc->iso.val[ia] )  break;
+        kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+        hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+        hsvrgb(hsv,rgb);
+        glColor3dv(rgb);
+        
+        dd   = 1.0 / dd;
+        u[0] = ps0->m[0] * dd;
+        u[1] = ps0->m[1] * dd;
+        drawVector2D(cp,u,scal);
+        k = pt->nxt;
+      }
+    }
+    glEnd();
+  }
+
+  glLineWidth(1.0);
+  glEndList();
+  return(dlist);
+}
+
+
+GLuint listQuad2dVector(pMesh mesh) {
+  pMaterial   pm;
+  pQuad       pq;
+  pPoint      ppt;
+  pSolution   ps0;
+  pScene      sc;
+  double      rgb[3],u[2],epsra,iso,kc,dd,scalemin,scalemax,scal;
+  float       cp[2];
+  GLuint      dlist = 0;
+  int         ia,i,k,l,m;
+  static double hsv[3] = { 0.0, 1.0, 0.80 };
+
+  /* default */
+  if ( !mesh->nq || !mesh->nbb )  return(0);
+
+  sc    = cv.scene[currentScene()];
+  if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);
+  if ( ddebug ) printf("create vector list\n");
+
+  /* create display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  scalemin = sc->dmax * SCALV;
+  scalemax = 15*scalemin;
+  mesh->mark++;
+  glLineWidth(3.0);
+
+  if ( mesh->typage == 2 ) {
+    glBegin(GL_LINES);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LQuad];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pq = &mesh->quad[k];
+        if ( !pq->v[0] ) {
+          k = pq->nxt;
+          continue;
+        }
+
+        scal  = 0.5*sizeQuad(mesh,k);
+        epsra = EPST * scal;
+
+        for (i=0; i<4; i++) {
+          ppt = &mesh->point[pq->v[i]];
+          if ( ppt->mark == mesh->mark )  continue;
+          ppt->mark = mesh->mark;
+
+          ps0 = &mesh->sol[pq->v[i]];
+          dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]);
+          if ( dd < epsra )  continue;
+
+          /* color = norm */
+          if ( iso < sc->iso.val[0] ) 
+            iso = sc->iso.val[0];  
+          else if ( iso > sc->iso.val[MAXISO-1] )
+            iso = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( iso < sc->iso.val[ia] )  break;
+          kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+          glColor3dv(rgb);
+
+          dd    = 1.0 / dd;
+          u[0]  = ps0->m[0] * dd;
+          u[1]  = ps0->m[1] * dd;
+          cp[0] = ppt->c[0];
+          cp[1] = ppt->c[1];
+          drawVector2D(cp,u,scal);
+        }
+        k = pq->nxt; 
+      }
+    }
+    glEnd();
+  }
+  else {
+    glBegin(GL_LINES);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LQuad];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pq = &mesh->quad[k];
+        if ( !pq->v[0] ) {
+          k = pq->nxt;
+          continue;
+        }
+
+        scal  = 0.5*sizeQuad(mesh,k);
+        epsra = EPST * scal;
+        cp[0] = cp[1] = 0.0;
+        for (l=0; l<4; l++) {
+          ppt = &mesh->point[pq->v[l]];
+          cp[0] += ppt->c[0];
+          cp[1] += ppt->c[1];
+        }
+        cp[0] *= 0.25;
+        cp[1] *= 0.25;
+
+        /* color = norm */
+        ps0 = &mesh->sol[k];
+        dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]);
+        if ( dd < epsra ) {
+          k = pq->nxt; 
+          continue;
+        }
+        if ( iso < sc->iso.val[0] ) 
+          iso = sc->iso.val[0];  
+        else if ( iso > sc->iso.val[MAXISO-1] )
+          iso = sc->iso.val[MAXISO-1];
+        for (ia=0; ia<MAXISO-1; ia++)
+          if ( iso < sc->iso.val[ia] )  break;
+        kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+        hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+        hsvrgb(hsv,rgb);
+        glColor3dv(rgb);
+        
+        dd   = 1.0 / dd;
+        u[0] = ps0->m[0] * dd;
+        u[1] = ps0->m[1] * dd;
+        drawVector2D(cp,u,scal);
+        k = pq->nxt;
+      }
+    }
+    glEnd();
+  }
+
+  glLineWidth(1.0);
+  glEndList();
+  return(dlist);
+}
+
+
+GLuint listTria3dVector(pMesh mesh) {
+  pMaterial   pm;
+  pTriangle   pt;
+  pPoint      ppt;
+  pSolution   ps0;
+  pScene      sc;
+  double      rgb[3],u[3],epsra,iso,kc,dd,scalemin,scalemax,scal;
+  float       cp[3];
+  GLuint      dlist = 0;
+  int         ia,i,k,l,m;
+  static double hsv[3] = { 0.0f, 1.0f, 0.80f };
+
+  /* default */
+  if ( !mesh->nbb )  return(0);
+
+  sc    = cv.scene[currentScene()];
+  /*if ( egal(sc->iso.val[0],sc->iso.val[MAXISO-1]) )  return(0);*/
+  if ( ddebug ) printf("create vector list\n");
+
+  /* create display list */
+  dlist = glGenLists(1);
+  glNewList(dlist,GL_COMPILE);
+  if ( glGetError() )  return(0);
+
+  scalemin = sc->dmax * SCALV;
+  scalemax = 15*scalemin;
+  mesh->mark++;
+  glLineWidth(2.0);
+
+  if ( mesh->typage == 2 ) {
+    glBegin(GL_LINES);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTria];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        scal  = sizeTria(mesh,k);
+        epsra = EPST * scal;
+
+        for (i=0; i<3; i++) {
+          ppt = &mesh->point[pt->v[i]];
+          if ( ppt->mark == mesh->mark )  continue;
+          ppt->mark = mesh->mark;
+
+          ps0 = &mesh->sol[pt->v[i]];
+          dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]\
+              + ps0->m[2]*ps0->m[2]);
+          if ( dd < epsra )  continue;
+
+          /* color = norm */
+          if ( iso < sc->iso.val[0] ) 
+            iso = sc->iso.val[0];  
+          else if ( iso > sc->iso.val[MAXISO-1] )
+            iso = sc->iso.val[MAXISO-1];
+          for (ia=0; ia<MAXISO-1; ia++)
+            if ( iso < sc->iso.val[ia] )  break;
+          kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+          hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+          hsvrgb(hsv,rgb);
+          glColor3dv(rgb);
+
+          dd    = 1.0 / dd;
+          u[0]  = ps0->m[0] * dd;
+          u[1]  = ps0->m[1] * dd;
+          u[2]  = ps0->m[2] * dd;
+          cp[0] = ppt->c[0];
+          cp[1] = ppt->c[1];
+          cp[2] = ppt->c[2];
+          drawVector3D(cp,u,scal);
+        }
+        k = pt->nxt; 
+      }
+    }
+    glEnd();
+  }
+
+  else {
+    glBegin(GL_LINES);
+    for (m=0; m<sc->par.nbmat; m++) {
+      pm = &sc->material[m];
+      k  = pm->depmat[LTria];
+      if ( !k || pm->flag )  continue;
+
+      while ( k != 0 ) {
+        pt = &mesh->tria[k];
+        if ( !pt->v[0] ) {
+          k = pt->nxt;
+          continue;
+        }
+
+        scal  = 0.5*sizeTria(mesh,k);
+        epsra = EPST * scal;
+        cp[0] = cp[1] = 0.0;
+        for (l=0; l<3; l++) {
+          ppt = &mesh->point[pt->v[l]];
+          cp[0] += ppt->c[0];
+          cp[1] += ppt->c[1];
+          cp[2] += ppt->c[2];
+        }
+        cp[0] /= 3.0;
+        cp[1] /= 3.0;
+        cp[2] /= 3.0;
+
+        /* color = norm */
+        ps0 = &mesh->sol[k];
+        dd  = iso = sqrt(ps0->m[0]*ps0->m[0] + ps0->m[1]*ps0->m[1]\
+            + ps0->m[2]*ps0->m[2]);
+        if ( dd < epsra ) {
+          k = pt->nxt; 
+          continue;
+        }
+        if ( iso < sc->iso.val[0] ) 
+          iso = sc->iso.val[0];  
+        else if ( iso > sc->iso.val[MAXISO-1] )
+          iso = sc->iso.val[MAXISO-1];
+        for (ia=0; ia<MAXISO-1; ia++)
+          if ( iso < sc->iso.val[ia] )  break;
+        kc = (iso-sc->iso.val[ia-1]) / (sc->iso.val[ia] - sc->iso.val[ia-1]);
+        hsv[0] = sc->iso.col[ia-1]*(1.0-kc)+sc->iso.col[ia]*kc;
+        hsvrgb(hsv,rgb);
+        glColor3dv(rgb);
+        
+        dd   = 1.0 / dd;
+        u[0] = ps0->m[0]/dd;
+        u[1] = ps0->m[1]/dd;
+        u[2] = ps0->m[2]/dd;
+        drawVector3D(cp,u,scal);
+        k = pt->nxt;
+      }
+    }
+    glEnd();
+  }
+
+  glLineWidth(1.0);
+  glEndList();
+  return(dlist);
+}
diff --git a/src/medit/view.c b/src/medit/view.c
new file mode 100644
index 0000000..043d337
--- /dev/null
+++ b/src/medit/view.c
@@ -0,0 +1,91 @@
+#include "medit.h"
+#include "sproto.h"
+#include "extern.h"
+
+static pTransform  cview   = 0;
+static pCamera     ccam    = 0;
+static pPersp      cpersp  = 0;
+static int         cscene  = 0;
+static ubyte       curview = 0;
+
+
+void copyView(pTransform view,pCamera cam,pPersp persp) {
+  cscene = currentScene();
+
+  if ( !cview ) {
+    cview = (pTransform)calloc(1,sizeof(struct transform));
+    if ( !cview )  exit(2);
+  }
+  cview = (pTransform)memcpy(cview,view,sizeof(struct transform));
+  if ( !cview )  exit(2);
+  
+  if ( !ccam ) {
+    ccam = (pCamera)calloc(1,sizeof(struct camera));
+    if ( !ccam )  exit(2);
+  }
+  ccam = (pCamera)memcpy(ccam,cam,sizeof(struct camera));
+  if ( !ccam )  exit(2);
+  
+  if ( !cpersp ) {
+    cpersp = (pPersp)calloc(1,sizeof(struct sperspective));
+    if ( !cpersp )  exit(2);
+  }
+  cpersp = (pPersp)memcpy(cpersp,persp,sizeof(struct sperspective));
+  if ( !cpersp )  exit(2);
+
+  curview = 1;
+}
+
+int pasteView(pTransform view,pCamera cam,pPersp persp) {
+  if ( !curview && !ccam && !persp )   return(0);
+ 
+  view  = (pTransform)memcpy(view,cview,sizeof(struct transform));
+  cam   = (pCamera)memcpy(cam,ccam,sizeof(struct camera));
+  persp = memcpy(persp,cpersp,sizeof(struct sperspective));
+  
+  if ( !view || !cam || !persp )  exit(2);
+  curview = 0;
+
+  return(1);
+}
+
+/* link scene 1 (slave) to scene 2 (master) */
+int linkView(pScene slave) {
+  pScene master;
+  int    idw = currentScene();
+
+  /* default */
+  if ( ddebug ) printf("link view\n");
+
+  if ( !curview || idw == cscene )   return(0);
+
+  /* link 2 scenes */
+  master         = cv.scene[cscene];
+  master->slave  = idw;
+  master->master = -1;
+  memcpy(slave->view,master->view,sizeof(struct transform));
+  memcpy(slave->camera,master->camera,sizeof(struct camera));
+  memcpy(slave->persp,master->persp,sizeof(struct sperspective));
+  memcpy(slave->clip->eqn,master->clip->eqn,4*sizeof(float));
+  memcpy(slave->clip->cliptr,master->clip->cliptr,sizeof(struct transform));
+  slave->slave  = -1;
+  slave->master = cscene;
+  curview       = 0;
+
+  return(1);
+}
+
+void unlinkView(pScene sc1) {
+  pScene  sc2;
+
+  if ( sc1->master == -1 )  return;
+
+  /* copy master view */
+  sc2 = cv.scene[sc1->master];
+  sc1->view = (pTransform)createTransform();
+  memcpy(sc1->view,sc2->view,sizeof(struct transform));
+
+  /* remove link */
+  sc1->master = -1;
+  sc2->slave  = -1;
+}
diff --git a/src/medit/zaldy1.c b/src/medit/zaldy1.c
new file mode 100644
index 0000000..d68a3db
--- /dev/null
+++ b/src/medit/zaldy1.c
@@ -0,0 +1,70 @@
+/*
+ *  memory allocation for data structures
+ *
+ *  Written by Pascal J. Frey, Inria-Rocquencourt
+ *  Copyright (c) Inria, 1999.  All rights reserved. 
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+int zaldy1(pMesh mesh) {
+
+  /* default */
+  if ( ddebug ) printf("allocate %d points\n",mesh->np);
+  mesh->point = (pPoint)M_calloc(mesh->np+1,sizeof(Point),"zaldy1.point");
+  assert(mesh->point);
+
+  if ( ddebug ) printf("allocate %d tria\n",mesh->nt);
+  mesh->tria = (pTriangle)M_calloc(mesh->nt+1,sizeof(Triangle),"zaldy1.tria");
+  assert(mesh->tria);
+
+  if ( ddebug ) printf("allocate %d quad\n",mesh->nq);
+  if ( mesh->nq ) {
+    mesh->quad = (pQuad)M_calloc(mesh->nq+1,sizeof(Quad),"zaldy1.quad");
+	assert(mesh->quad);
+  }
+
+  if ( mesh->ntet ) {
+    if ( ddebug ) printf("allocate %d tetra\n",mesh->ntet);
+    mesh->tetra = (pTetra)M_calloc(mesh->ntet+1,sizeof(Tetra),"zaldy1.tetra");
+	assert(mesh->tetra);
+  }
+
+  if ( mesh->nhex ) {
+    if ( ddebug ) printf("allocate %d hexa\n",mesh->nhex);
+    mesh->hexa = (pHexa)M_calloc(mesh->nhex+1,sizeof(Hexa),"zaldy1.hexa");
+	assert(mesh->hexa);
+  }
+
+  if ( mesh->na ) {
+    if ( ddebug ) printf("allocate %d edges\n",mesh->na);
+    mesh->edge = (pEdge)M_calloc(mesh->na+1,sizeof(Edge),"zaldy1.edge");
+	assert(mesh->edge);
+  }
+
+  if ( mesh->nvn || mesh->ntg ) {
+    mesh->extra = (pExtra)M_calloc(1,sizeof(Extra),"zaldy1.extra");
+	assert(mesh->extra);
+  
+	if ( mesh->nvn ) {
+  	  mesh->extra->n = (float*)M_calloc(3*mesh->nvn+1,sizeof(float),"inmesh");
+	  assert(mesh->extra->n);
+    }
+
+    if ( mesh->ntg ) {
+      mesh->extra->t = (float*)M_calloc(3*mesh->ntg+1,sizeof(float),"inmesh");
+	  assert(mesh->extra->n);
+    }
+  }
+
+  return(1);
+}
diff --git a/src/medit/zaldy2.c b/src/medit/zaldy2.c
new file mode 100644
index 0000000..03ab159
--- /dev/null
+++ b/src/medit/zaldy2.c
@@ -0,0 +1,26 @@
+#include "medit.h"
+#include "extern.h"
+#include "sproto.h"
+
+
+int zaldy2(pMesh mesh) {
+  pSolution  ps;
+  int        k,nbf;
+  
+  /* memory alloc. */
+  mesh->sol = (pSolution)M_calloc(mesh->nbb+1,sizeof(struct solu),"zaldy2");
+  assert(mesh->sol);
+
+  if ( mesh->nfield == 1 )  return(1);
+  if ( mesh->nfield == mesh->dim )
+    nbf = mesh->dim;      /* vector field */
+  else 
+    nbf = mesh->dim*(mesh->dim+1)/2;  /* d*d matrix */        
+
+  for (k=1; k<=mesh->nbb; k++) {
+    ps = &mesh->sol[k];
+    ps->m = (float*)malloc(nbf*sizeof(float));
+  }
+
+  return(1);
+}
diff --git a/src/mpi/._parallelempi.cpp b/src/mpi/._parallelempi.cpp
new file mode 100644
index 0000000..e9604e8
Binary files /dev/null and b/src/mpi/._parallelempi.cpp differ
diff --git a/src/mpi/Makefile.am b/src/mpi/Makefile.am
new file mode 100644
index 0000000..34d05b7
--- /dev/null
+++ b/src/mpi/Makefile.am
@@ -0,0 +1,31 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+# change FH mars 2010 for sgi mpiu .... 
+
+# FFCS - we need to call MPICXX directly because Windows options are too different to be detailed to the FF configuration script.
+
+CXX=@MPICXX@
+
+# To create statically linked executables (see configure.ac)
+CXXLD=$(STATICTOOL) $(CXX)
+
+# MPI may not be installed. Checked in configure.ac
+bin_PROGRAMS=$(MPIPROG)
+bin_SCRIPTS=$(MPISCRIPT)
+EXTRA_PROGRAMS=FreeFem++-mpi
+EXTRA_SCRIPTS=ff-mpirun
+EXTRA_DIST=ff-mpirun.in
+
+# FFCS: visualization stream redirection
+FreeFem___mpi_SOURCES=../Graphics/sansrgraph.cpp ../lglib/mymain.cpp parallelempi.cpp ../lglib/lg.tab.cpp	\
+	../fflib/ffapi.cpp
+FreeFem___mpi_DEPENDENCIES=../fflib/libff.a
+LDADD=../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLASLIBS@ @MPI_LIB@
+
+AM_CXXFLAGS=-DPARALLELE
+AM_CPPFLAGS=-I$(srcdir)/../fflib -I$(srcdir)/../Graphics -I$(srcdir)/../femlib @MPI_INCLUDE@
+ff-mpirun:ff-mpirun.in Makefile
+	../../config.status  --file=ff-mpirun:ff-mpirun.in
+	chmod a+x  ff-mpirun
+
diff --git a/src/mpi/ff-mpirun.in b/src/mpi/ff-mpirun.in
new file mode 100755
index 0000000..d907220
--- /dev/null
+++ b/src/mpi/ff-mpirun.in
@@ -0,0 +1,35 @@
+#!/bin/bash
+# 	./config.status  --file=ff-mpirun:ff-mpirun.in
+mpirun=mpirun
+dir=`dirname $0`
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+bindir="@bindir@"
+nw=1
+if [ -n "@MPIRUN@"  ] ;then mpirun="@MPIRUN@"  ; fi
+ffmpi=FreeFem++-mpi
+if [ -x "$0" -a -x "$dir/$ffmpi" ]; then  ffmpi="$dir/$ffmpi"; fi    
+if [ -d "$bindir" ]  ;then export PATH="@bindir@:$PATH"  ; fi
+a[0]="'$mpirun'"
+j=1;
+#echo $1 ---
+while test -n "$1" ; do
+((j=$j+1))
+#((j1=$j+1))
+#echo --- $1 --  $j1 $j
+
+case "$1" in
+"-nw") nw=1;;
+"-win") nw=0;;
+*.edp) a[$j]="${ffmpi}";
+if [ "$nw" -eq 1 ]; then ((j=$j+1));a[$j]="-nw"; fi
+((j=$j+1));a[$j]="$1";;
+#if[ ! -f "$1" ]; then echo error file no found "$1"; dry=2; fi;;
+-dry) dry=1;; 
+*)  a[$j]="$1";;
+esac
+shift
+done
+echo "${a[*]}"
+if [ -n "$dry" ]; then echo which $ffmpi : `which  "$ffmpi"`; fi
+if [ -z "$dry" ]; then eval  "${a[*]}"; fi
diff --git a/src/mpi/parallelempi-empty.cpp b/src/mpi/parallelempi-empty.cpp
new file mode 100644
index 0000000..d1c7633
--- /dev/null
+++ b/src/mpi/parallelempi-empty.cpp
@@ -0,0 +1,11 @@
+// empty parallele interface if no MPI to build dll
+// with or without mpi..
+//#include "parallelepmi.hpp" 
+extern  void (*initparallele)(int &argc, char **& argv) ;
+extern void (*init_lgparallele)();
+extern void (*end_parallele)();
+
+void init_ptr_parallelepmi();
+void init_ptr_parallelepmi(){};
+
+
diff --git a/src/mpi/parallelempi.cpp b/src/mpi/parallelempi.cpp
new file mode 100644
index 0000000..ad31baa
--- /dev/null
+++ b/src/mpi/parallelempi.cpp
@@ -0,0 +1,2636 @@
+#include <config.h>
+#include <fstream>
+#include <iostream>
+#include <cfloat>
+#include <cmath>
+#include <cstring>
+#include <complex>
+#include<stdlib.h>
+using namespace std;
+#include "error.hpp"
+#include "AFunction.hpp"
+// FH: I have move AFunction_ext.hpp  to fflib dir.
+#include "AFunction_ext.hpp" 
+// Add J. Morice for AFunction_ext.hpp 
+#include "ufunction.hpp"
+using namespace std;  
+#include "rgraph.hpp"
+#include "RNM.hpp"
+// after RNM   otherwise 
+// trouble with index in RNM (I do no understander FH)
+#include <set>
+#include <vector>
+#include <map>
+
+#include "fem.hpp"
+
+
+#include "FESpacen.hpp" 
+#include "FESpace.hpp" 
+
+#include "MatriceCreuse_tpl.hpp"
+#include "MeshPoint.hpp"
+#include "Mesh2dn.hpp"
+#include "Mesh3dn.hpp"
+#include "Operator.hpp" 
+#include "lex.hpp"
+#include "libmesh5.h"
+#include "lgfem.hpp"
+#include "lgmesh3.hpp"
+#include "lgsolver.hpp"
+#include "problem.hpp"
+
+//FFCS redirection
+#include "../fflib/ffapi.hpp"
+
+#undef MPICH_SKIP_MPICXX
+#define  MPICH_SKIP_MPICXX
+#undef MPICH_IGNORE_CXX_SEEK
+#define MPICH_IGNORE_CXX_SEEK
+#include <mpi.h>
+
+// Remark on mipich  MPI_Comm, MPI_Resquest, MPI_Group, MPI_Op are int 
+//  => encapsulation
+
+//static long verbosity=1000;
+template<class MPI_type,int DIFF>
+struct fMPI { 
+  MPI_type v; 
+  operator  MPI_type &() {return v;}
+  operator  MPI_type *() {return &v;}
+  operator  MPI_type () const  {return v;}
+  
+  // MPI_type * operator  &() {return &v;}
+  void operator=(const MPI_type vv) { v=vv;}
+  fMPI(const MPI_type vv=0) : v(vv){}
+  bool operator!=(MPI_type vv) const {return vv !=v;}
+  bool operator==(MPI_type vv) const {return vv ==v;}
+  
+};
+
+// the encapsulation for the for MPI type  (int on mpich )
+
+typedef fMPI<MPI_Comm,1> fMPI_Comm;
+typedef fMPI<MPI_Group,2> fMPI_Group;
+typedef fMPI<MPI_Request,3> fMPI_Request;
+typedef fMPI<MPI_Op,4> fMPI_Op;
+
+
+
+// end of encapsulation ..
+
+// to send a sparse matrix we send header, line array ,colmun array, value array.
+//  end afer the fist resquest we need to do allocation.
+// so in this cas the communacatio is done in
+// 2 step  
+//    1 the header, 
+//       alloc time 
+//    2 the  message 
+//  a couple request, pointer. 
+//    Not use of IPROBE because probelem of wait. 
+class MPIrank; 
+class DoOnWaitMPI_Request ; 
+
+map<MPI_Request*,DoOnWaitMPI_Request *> ToDoOnWaitMPI_Request;
+
+void GetPendingWait() ;
+
+
+template<class T> struct MPI_TYPE {static const MPI_Datatype  TYPE(){return MPI_BYTE;}};;
+template<> struct MPI_TYPE<long>      {static const MPI_Datatype  TYPE(){return MPI_LONG;}};
+template<> struct MPI_TYPE<int>      {static const MPI_Datatype TYPE(){return MPI_INT;}};
+template<> struct MPI_TYPE<double>    {static const MPI_Datatype TYPE(){return MPI_DOUBLE;}};
+template<> struct MPI_TYPE<char>    {static const MPI_Datatype TYPE(){return MPI_BYTE;}};
+
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+template<> struct MPI_TYPE<Complex>   {static const MPI_Datatype TYPE(){return MPI_DOUBLE_COMPLEX;}};
+#endif
+template<class T> struct MPI_WHAT {};
+template<> struct MPI_WHAT<long>      {static const int WHAT=101;};
+template<> struct MPI_WHAT<double>    {static const int WHAT=102;};
+template<> struct MPI_WHAT<Complex>   {static const int WHAT=103;};
+template<> struct MPI_WHAT<KN<long> *>   {static const int WHAT=104;};
+template<> struct MPI_WHAT<KN<double>* >   {static const int WHAT=105;};
+template<> struct MPI_WHAT<KN<Complex>* >   {static const int WHAT=106;};
+
+template<class T> struct MPI_TAG {};
+template<> struct MPI_TAG<long>   {static const int TAG=5;};
+template<> struct MPI_TAG<double>    {static const int TAG=4;};
+template<> struct MPI_TAG<Complex >   {static const int TAG=6;};
+template<> struct MPI_TAG<KN<long>* >   {static const int TAG=11;};
+template<> struct MPI_TAG<KN<double>* >   {static const int TAG=12;};
+template<> struct MPI_TAG<KN<Complex>* >   {static const int TAG=13;};
+template<> struct MPI_TAG<Mesh *>   {static const int TAG=1000;};
+template<> struct MPI_TAG<Mesh3 *>   {static const int TAG=1010;};
+template<> struct MPI_TAG<Matrice_Creuse<double> *>   {static const int TAG=1020;};
+template<> struct MPI_TAG<Matrice_Creuse<Complex> *>   {static const int TAG=1030;};
+
+void f_initparallele(int &, char **&);
+void f_init_lgparallele();  
+
+extern long mpirank ;
+extern long mpisize ;
+
+//  for syncro communication
+MPI_Request *  Syncro_block = reinterpret_cast<MPI_Request * > (1); 
+
+const size_t sizempibuf = 1024*320;
+
+template<class R> 
+long  WSend( R * v,int l,int who,int tag,MPI_Comm comm,MPI_Request *rq)
+{
+  long ret=0;
+  MPI_Request rq0,*request=&rq0;
+  if(verbosity>100)
+    cout << mpirank<< " send to " << who << " tag " << tag << " " << rq << " " <<  comm << " syncro "<<  (rq == Syncro_block) <<endl;
+  if(rq == Syncro_block) 
+    ret=MPI_Send((void *) v,l, MPI_TYPE<R>::TYPE() , who, tag,comm);
+  else
+    {
+      ret=MPI_Isend((void *) v,l, MPI_TYPE<R>::TYPE() , who, tag,comm,request);
+      if(rq) *rq=*request;
+      else MPI_Request_free(request); 
+    }
+    return ret;
+}
+
+template<class T>
+void CheckContigueKN(const KN_<T> &t)
+{
+    if( t.step != 1 && t.N()>1) {
+	cout<< " step= "<< t.step << " size " << t.N() << " " << & t[0] << " " << & t[1] << endl;
+	ExecError("Sorry the array is not contigue (step != 1) ");
+    }
+}
+template<> 
+long  WSend<Complex> ( Complex * v,int n,int who,int tag,MPI_Comm comm,MPI_Request *rq)
+{
+  long ret=0;
+  MPI_Request rq0,*request=&rq0;
+  if(verbosity>100)
+    cout << mpirank<< " send to " << who << " tag " << tag << " " << rq << " " <<  comm << " syncro "<<  (rq == Syncro_block) << endl;
+  if(rq == Syncro_block) 
+    {
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+      ret=MPI_Send(reinterpret_cast<void*> (v) , n, MPI_DOUBLE_COMPLEX, who, tag,comm);
+#else
+      n *=2;
+      ret=  MPI_Send(reinterpret_cast<void*> (v), n, MPI_DOUBLE, who, tag,comm);
+#endif	  
+    }
+  else
+    {
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+      ret=MPI_Isend(reinterpret_cast<void*> (v) , n, MPI_DOUBLE_COMPLEX, who, tag,comm,request);
+#else
+      n *=2;
+      ret=MPI_Isend(reinterpret_cast<void*> (v), n, MPI_DOUBLE, who, tag,comm,request);
+      n /= 2;
+#endif
+      if(rq) *rq=*request;
+      else MPI_Request_free(request);
+      } 
+  return ret;
+}
+
+template<class R> 
+long  WRecv(R * v,int n,int who,int tag,MPI_Comm comm,MPI_Request *rq)
+{
+  MPI_Status status;
+  if(rq && (rq != Syncro_block)) 
+    return MPI_Irecv(reinterpret_cast<void*> (v),n, MPI_TYPE<R>::TYPE() , who, tag,comm,rq);
+  else 
+    return MPI_Recv(reinterpret_cast<void*> (v),n, MPI_TYPE<R>::TYPE() , who, tag,comm,&status);
+}
+
+template<> 
+long  WRecv<Complex> (Complex * v,int n,int who,int tag,MPI_Comm comm,MPI_Request *rq)
+{
+  MPI_Status status;
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+  if(rq && (rq != Syncro_block)) 
+    return MPI_Irecv(reinterpret_cast<void*> (v), n, MPI_DOUBLE_COMPLEX, who, tag,comm,rq);
+  else 
+    return MPI_Recv(reinterpret_cast<void*> (v), n, MPI_DOUBLE_COMPLEX, who, tag,comm,&status);
+#else
+  n *=2;
+  if(rq && (rq != Syncro_block)) 
+    return  MPI_Irecv(reinterpret_cast<void*> (v), n, MPI_DOUBLE, who, tag,comm,rq);
+  else 
+       return MPI_Recv(reinterpret_cast<void*> (v), n, MPI_DOUBLE, who, tag,comm,&status);
+#endif
+}
+			 
+template<class R> 
+void  WBcast(R * v,int  n,int who,MPI_Comm comm)  
+{
+  assert(v && n>0);
+  MPI_Bcast(reinterpret_cast<void*> (v), n, MPI_TYPE<R>::TYPE(), who,comm);
+}
+
+template<> 
+void  WBcast<Complex>(Complex * v,int  n,int who,MPI_Comm comm)  
+{
+  assert(v && n>0);
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    MPI_Bcast(reinterpret_cast<void*> (v), n, MPI_DOUBLE_COMPLEX /*MPI_TYPE<R>::TYPE()*/, who,comm);
+#else
+  n *=2;
+  MPI_Bcast(reinterpret_cast<void*> (v), n, MPI_DOUBLE, who,comm);
+#endif
+}
+
+			 
+
+
+
+struct MPIrank {
+  
+  int who; 
+  MPI_Comm comm; 
+  MPI_Request *rq; 
+  // mutable bool block;  
+  
+  MPIrank(int i=0,MPI_Comm com=MPI_COMM_WORLD, MPI_Request *rqq=0) 
+    : who(i) , comm(com),rq(rqq) 
+  {
+	int n;
+	MPI_Comm_size(comm, &n);
+	// cout <<" who = " << who << " ******** " << n << " "<< ((-2 < who) && (who < n))  << endl;
+	// ffassert( (-2 < who) && (who < n) ); // plant sans raison ...
+  } 
+  
+  
+  
+  long Send(double a)const  {return WSend(&a, 1, who, MPI_TAG< double >::TAG,comm,rq); }
+  long Send(long a)const  {return WSend(&a, 1, who, MPI_TAG< long >::TAG,comm,rq); }
+  long Send(Complex a)const  {return WSend(&a, 1, who, MPI_TAG< Complex >::TAG,comm,rq); }
+  
+  long Recv(double & a) const { return  WRecv(&a, 1,  who, MPI_TAG< double >::TAG ,comm,rq);}
+  long Recv(long & a) const { return  WRecv(&a, 1,  who, MPI_TAG< long >::TAG ,comm,rq);}
+  long Recv(Complex & a) const { return  WRecv(&a, 1,  who, MPI_TAG< Complex >::TAG ,comm,rq);}
+  
+  const MPIrank & Bcast(double & a) const {WBcast(&a, 1, who,comm); return *this; }
+  const MPIrank & Bcast(long & a) const {WBcast(&a, 1, who,comm); return *this; }
+  const MPIrank & Bcast(Complex & a) const {WBcast(&a, 1, who,comm); return *this; }
+  
+  
+  
+  template<class R>
+  long Recv(KN<R> & a) const {
+    assert(&a);
+      CheckContigueKN(a);
+  
+    if(verbosity>99)
+      cout << " ---- " << who  << "  >> " << & a << " " << a.N() << " " << a.step << " " << MPI_TAG<KN<R>* >::TAG 
+	       <<" from " << mpirank << "  "<<  (R *) a << endl;
+    int n= a.N();
+    long ll=WRecv((R *) a, n, who, MPI_TAG<KN<R>* >::TAG ,comm,rq);
+    if(verbosity>99)
+      cout << " ++++ " << who  << "  >> " << & a << " " << a.N() << " " << MPI_TAG<KN<R>* >::TAG 
+	   <<" from  " << mpirank << "  "<<  (R *) a << endl;
+    ffassert(a.N()==n);
+    return ll;
+  }
+  
+  template<class R>
+  long Send(const KN<R> *aa)const  {
+    const KN<R> & a=*aa;
+    ffassert(&a); 
+    int n= a.N();
+    CheckContigueKN(*aa);
+    if(verbosity>99)
+	  cout << " .... " << who  << "  >> " << & a << " " << a.N() << " " << a.step<< " " << MPI_TAG<KN<R>* >::TAG 
+	       <<" from  " << mpirank << "  "<<  (R *) a << endl;
+    return WSend((R *) a,n,who,MPI_TAG<KN<R>* >::TAG,comm,rq);
+  }
+  
+  template<class R> 
+  const MPIrank & Bcast(const KN<R> &a) const  {
+    //const KN<R> & a=*aa;
+    assert(&a); 
+    int n= a.N();
+    CheckContigueKN(a);
+
+    WBcast((R *) a, n, who,comm);
+    ffassert(a.N()==n);
+    return *this;
+  }
+  
+  
+  const MPIrank & Bcast(Fem2D::Mesh *&  a) const {
+    if(verbosity>1) 
+      cout << " MPI Bcast  (mesh *) " << a << endl;
+    Serialize  *buf=0;
+    long nbsize=0;
+    if(  who == mpirank)  
+      {
+	buf =new Serialize((*a).serialize());
+	nbsize =  buf->size();
+      }
+    WBcast( &nbsize, 1,  who,comm);
+    if (who != mpirank)
+      buf= new Serialize(nbsize,Fem2D::Mesh::magicmesh);
+    assert(nbsize);
+    if(verbosity>2) 
+      cout << " size to bcast : " << nbsize << " mpirank : " << mpirank << endl;
+    
+    WBcast( (char *)(*buf),nbsize,  who,comm);     
+        
+    if(who != mpirank)
+      {
+	if (a) (*a).decrement();
+	a= new Fem2D::Mesh(*buf);
+	Fem2D::R2 Pn,Px;
+	a->BoundingBox(Pn,Px);
+	a->quadtree=new Fem2D::FQuadTree(a,Pn,Px,a->nv);
+      }   
+    delete buf;      
+    return *this;
+   }
+  
+  const MPIrank & Bcast(Fem2D::Mesh3 *&  a) const {
+    if(verbosity>1) 
+      cout << " MPI Bcast  (mesh3 *) " << a << endl;
+    Serialize  *buf=0;
+    long  nbsize=0;
+    if(  who == mpirank)  
+      {
+	buf =new Serialize((*a).serialize());
+	nbsize =  buf->size();
+      }
+    WBcast( &nbsize, 1,  who,comm);
+    if (who != mpirank)
+      buf= new Serialize(nbsize,Fem2D::GenericMesh_magicmesh);
+    assert(nbsize);
+    if(verbosity>2) 
+      cout << " size to bcast : " << nbsize << " mpirank : " << mpirank << endl;
+    
+    WBcast( (char *)(*buf),nbsize,  who,comm);     
+    
+	if(who != mpirank)
+	  {
+	    if (a) (*a).decrement();
+	    a= new Fem2D::Mesh3(*buf);
+	    a->BuildGTree();
+	  }   
+	delete buf;      
+	return *this;
+  }
+  
+  template<class R>
+  const MPIrank & Bcast(Matrice_Creuse<R> &  a) const
+    {
+      if(verbosity>1) 
+	cout << mpirank <<  ":  MPI Bcast " << who << "  (Matrice_Creuse &) " << &a << " " << a.A << endl;
+      MatriceMorse<R> *mA=0;
+      int ldata[4]={0,0,0,0};
+      if(  who == mpirank)  
+	{
+	  if(a.A)
+	    {
+	      mA= a.A->toMatriceMorse();
+	      ldata[0]=mA->n;
+	      ldata[1]=mA->m;
+	      ldata[2]=mA->nbcoef;
+	      ldata[3]=mA->symetrique;
+	      // cout << mpirank << " ldata " << ldata[0] << " " << ldata[1] <<" " << ldata[2] << " " <<ldata[3] << endl;
+	    }
+	}
+      int n4=4;
+      WBcast( ldata,n4, who,comm); 
+      //cout << mpirank << " after 4 " " ldata " << ldata[0] << " " << ldata[1] <<" " << ldata[2] << " " <<ldata[3] << endl;
+      int n1= ldata[0]+1;
+      if(  who != mpirank && ldata[0] )
+	mA= new MatriceMorse<R>(ldata[0],ldata[1],ldata[2],ldata[3]); 
+      if(ldata[0]) 
+	  {
+	    // cout << mpirank << " " << who << " lg  " << mA->lg << " " << n1 << endl;
+	    WBcast(  mA->lg,n1, who,comm);     
+	    //cout << mpirank << " " << who << " cl  " << mA->cl << " " <<  mA->nbcoef << endl;
+	    WBcast(  mA->cl,mA->nbcoef, who,comm);     
+	    //cout << mpirank << " " << who << " a  " << mA->a << " " <<  mA->nbcoef << endl;
+	    WBcast( mA->a,mA->nbcoef , who,comm);  
+	  }
+      if(  who != mpirank) 
+	a.A.master(mA);
+      else 
+	delete mA;      
+      return *this;
+    }
+  
+  // version asyncrone or syncrone  Now 2010 ...
+  template<class R>   long Send(Matrice_Creuse<R> * const &  a) const ;
+  template<class R>   long Recv(Matrice_Creuse<R>  &  a) const ;
+  long Send(Fem2D::Mesh *  a) const ;
+  long Send (Fem2D::Mesh3 *  a) const ;
+  long Recv(Fem2D::Mesh *& a)  const;  
+  long Recv(Fem2D::Mesh3 *& a) const; 
+
+  operator int () const { return who;}     
+};
+
+
+
+
+// for MPI_WAIT_resquets (complex MPI asyncrone MPI recv request ) ..
+class DoOnWaitMPI_Request :public   MPIrank
+{  
+    
+public:
+    bool sync;
+    DoOnWaitMPI_Request( MPIrank  mpr) : MPIrank(mpr),sync((rq==0 || rq == Syncro_block)) {}
+    virtual  bool Do(MPI_Request *rrq) =0; // false -> end 
+    bool  DoSR() { // do the  Send/Recv Op. 
+	bool ret=false;
+	if(verbosity>100)
+	  cout << mpirank << "   --- Do Send/Recv :  "  << " " << rq << " " << sync <<  endl;
+	if(sync) //  wait ...
+	  { bool c=1; 
+	    if(verbosity>100)
+	      cout << mpirank << "   --- Do way :  " << c << " " << rq << endl;
+	    while (c)
+	      {
+		c=Do(rq); 
+		if(verbosity>100)
+		  cout << mpirank << "   --- Do return :  " << c << " " << rq << endl;
+	      }
+	    
+	    ret=true;// clean 
+	  } 
+	else 
+	  ToDoOnWaitMPI_Request[rq]=this; // add request for WAIT ..
+	return ret;
+    }
+    virtual ~DoOnWaitMPI_Request(){}
+private:
+    DoOnWaitMPI_Request(const DoOnWaitMPI_Request & );
+     DoOnWaitMPI_Request & operator=( DoOnWaitMPI_Request & );
+};
+
+
+
+void DoOnWaitMPIRequest(MPI_Request *rq)
+{
+  if( rq  )
+    { 
+	map<MPI_Request*,DoOnWaitMPI_Request *>:: iterator drd = ToDoOnWaitMPI_Request.find(rq) ;
+	if(drd != ToDoOnWaitMPI_Request.end())
+	  {
+	    if(verbosity>100)
+	      cout << " Do on DoOnWaitMPIRequest " << rq  << " "  << endl; 
+	    if( !drd->second->Do(rq) )
+	      {
+		delete drd->second;
+		ToDoOnWaitMPI_Request.erase(drd); // finish ... 
+	      }
+
+	  }
+	
+    }
+
+}
+
+void DeSerialize(Serialize * sTh,Fem2D::Mesh ** ppTh)
+{
+      if ( *ppTh ) (**ppTh).decrement();
+   // cout << " ####"<< sTh << endl;
+      Fem2D::Mesh * pTh= new Fem2D::Mesh(*sTh);
+   // cout << " ####\n";
+      *ppTh=pTh;
+ 
+      Fem2D::R2 Pn,Px;
+      pTh->BoundingBox(Pn,Px);
+      pTh->quadtree=new Fem2D::FQuadTree(pTh,Pn,Px,pTh->nv);
+}
+
+void DeSerialize(Serialize * sTh,Fem2D::Mesh3 ** ppTh)
+{
+      if ( *ppTh )  (**ppTh).decrement();
+      Fem2D::Mesh3 * pTh= new Fem2D::Mesh3(*sTh);
+      pTh->BuildGTree();
+      *ppTh=pTh;
+}
+
+
+template<class R>
+class RevcWMatd : public DoOnWaitMPI_Request
+{
+public:  
+  typedef Matrice_Creuse<R> Mat;
+  Matrice_Creuse<R> * pmat;
+  MatriceMorse<R> *mA;
+  int state;
+  int ldata[4];
+  RevcWMatd(const MPIrank *mpirank,Mat * pm)
+    : DoOnWaitMPI_Request(*mpirank),
+      pmat(pm),mA(0),state(0)
+  {
+    int tag = MPI_TAG<Matrice_Creuse<R>* >::TAG;
+    int ll=WRecv( ldata,4, who, tag,comm,rq);
+    ffassert(ll == MPI_SUCCESS);
+
+  }
+  
+  bool  Do(MPI_Request *rrq)
+  {
+    state++;
+    int tag=MPI_TAG<Mat *>::TAG;
+    if(verbosity>100)
+      cout << mpirank << "  ---R: ldata " << ldata[0] << " " << ldata[1] <<" " << ldata[2] << " " <<ldata[3] << " " << state << endl;
+    
+    int ll=0;
+    switch (state)
+      {
+      case 1:
+	mA =  new MatriceMorse<R>(ldata[0],ldata[1],ldata[2],ldata[3]); 
+	ll=WRecv(  mA->lg,mA->n+1,   who, tag+1,comm,rq);
+	break;
+      case 2:
+	ll=WRecv(  mA->cl,mA->nbcoef,  who, tag+2,comm,rq);
+	break;
+      case 3:
+	ll=WRecv(  mA->a,mA->nbcoef,  who, tag+3,comm,rq);
+	break;
+      default:
+	pmat->A.master(mA);
+	mA=0;
+	return false;
+	break;
+      }
+    ffassert(ll == MPI_SUCCESS);
+    return true; // OK 
+  }
+  ~RevcWMatd() {
+    if(mA) delete mA; 
+  }	
+  
+};
+
+template<class R>
+class SendWMatd : public DoOnWaitMPI_Request
+{
+public:  
+  typedef Matrice_Creuse<R> Mat;
+  Matrice_Creuse<R> * pmat;
+  MatriceMorse<R> *mA;
+  int state;
+  int ldata[4];
+  SendWMatd(const MPIrank *mpirank,Mat * pm)
+    : DoOnWaitMPI_Request(*mpirank),
+      pmat(pm),mA(0),state(0)
+  {
+    mA=pmat->A->toMatriceMorse();
+    ldata[0]=mA->n;
+    ldata[1]=mA->m;
+    ldata[2]=mA->nbcoef;
+    ldata[3]=mA->symetrique;
+    int tag = MPI_TAG<Matrice_Creuse<R>* >::TAG;
+    int ll=WSend( ldata,4, who, tag,comm,rq);
+    ffassert(ll == MPI_SUCCESS) ;
+  }
+  bool  Do(MPI_Request *rrq)
+  {
+    state++;
+    int tag=MPI_TAG<Mat *>::TAG;
+    if(verbosity>100)
+      cout << mpirank << "  ---S  ldata " << ldata[0] << " " << ldata[1] <<" " << ldata[2] << " " <<ldata[3] << endl;
+    
+    int ll=0;
+    switch (state)
+      {
+      case 1:
+	ll=WSend(  mA->lg,mA->n+1,  who, tag+1,comm,rq);     
+	break;
+      case 2:
+	ll=WSend( mA->cl,mA->nbcoef,  who, tag+2,comm,rq);  
+	break;
+      case 3:
+	ll=WSend(  mA->a,mA->nbcoef,   who, tag+3,comm,rq);  
+	break;
+      default:
+	delete mA;
+	mA=0;
+	return false;
+	break;
+      }
+    ffassert(ll == MPI_SUCCESS);
+    return true; // OK 
+  }
+  ~SendWMatd() {
+    if(mA) delete mA; 
+  }	
+  
+};
+
+
+template<class Mesh>
+class RevcWMeshd : public DoOnWaitMPI_Request,Serialize  
+{
+public:  
+  Mesh ** ppTh;
+  int state;
+  RevcWMeshd(const MPIrank *mpirank,Mesh ** ppThh)
+    : DoOnWaitMPI_Request(*mpirank),Serialize(sizempibuf,Fem2D::Mesh::magicmesh),
+      ppTh(ppThh),state(0)
+  {
+    int tag=MPI_TAG<Mesh *>::TAG;
+    if(verbosity>100)
+      cout << " -- RevcWMeshd   " << rq << " " << comm << " " << p << endl; 
+    char * pp = p-sizeof(long);
+    int ll=WRecv(pp, sizempibuf,  who, tag,comm,rq); // wait first part ..
+    // cout << mpirank << " ++ ll= " << ll << " pp= " << pp << endl;
+  }
+  
+  bool  Do(MPI_Request *rrq)
+  {
+    int tag=MPI_TAG<Mesh *>::TAG;
+    ffassert(rq == rrq);
+    long l = * (long *) (void *) p ;
+    long l1 = l -( sizempibuf-sizeof(long));
+    if(verbosity>100)
+      cout << mpirank << " Do RevcWMeshd " <<  l  <<" " << state << "  cont  : " <<  (l1 >0)  << " " << rq << " " << comm << endl; 
+    
+    if(0==state++ &&  l1>0 ) // recv first part ..
+      {
+	if(verbosity>100)
+	  cout << mpirank << " + Do RevcWMeshd " <<  l  <<" " << state << "  cont  : " <<  ( l > sizempibuf) <<  " " << rq << " " << l-sizempibuf << " p = " << (void *) p <<  endl; 
+	resize(l);
+	int ll=WRecv(p-sizeof(long)+sizempibuf,l1,  who, tag+state,comm,rq);
+	return true;// continue .. 	
+      }
+    else resize(l);
+    // we have the all buffer => DeSerialize
+    DeSerialize(this,ppTh);      
+    count()=0; 
+    if(verbosity>100) 
+      cout << "    " << mpirank << " recived from " << who << " serialized " << what <<   ", l=" 
+	   << l << ", tag=" << tag << " rq = " << rq << " "  << *ppTh << endl;
+    
+    return false; // OK 
+  }
+  ~RevcWMeshd() {count()=0;}	
+  
+};
+
+template<class Mesh>
+class SendWMeshd : public DoOnWaitMPI_Request,Serialize  
+{
+public:  
+  Mesh ** ppTh;
+  int state;
+  SendWMeshd(const MPIrank *mpirank,Mesh ** ppThh)
+    : DoOnWaitMPI_Request(*mpirank),Serialize((**ppThh).serialize()),
+      ppTh(ppThh),state(0)
+  {
+    int tag=MPI_TAG<Mesh *>::TAG;
+    if(verbosity>100)
+      cout << " -- SendWMeshd   " << rq << " " << comm << " " << p << endl; 
+    char * pp = p-sizeof(long);
+    count()=lg; // store length in count 
+    size_t ls=lg+sizeof(long);
+    if (ls<=sizempibuf)
+      WSend(pp,ls, who, tag,comm,rq);
+    else 
+      WSend(pp,sizempibuf,who, tag,comm,rq);
+  }
+  
+  bool  Do(MPI_Request *rrq)
+  {
+    int tag=MPI_TAG<Mesh *>::TAG;
+    char * pp = p-sizeof(long);
+    long l1 = lg -(sizempibuf- sizeof(long));
+    if(verbosity>100)
+      cout << mpirank << " Do SendWMeshd " <<  lg  <<" " << state << "  cont  : " <<  (l1 >0)  << " " << rq << " " << comm << endl; 
+    
+    if(0==state++ &&  l1>0 ) // send the second part 
+      {
+	int ll=WSend(pp+sizempibuf,l1,  who, tag+state,comm,rq);
+	return true;// Fini
+      }
+    return false; // OK 
+  }
+
+  ~SendWMeshd() {count()=0;}
+  
+};
+
+
+template<class R>
+  long MPIrank::Send(Matrice_Creuse<R> * const &  a) const 
+  {
+    if(0)
+      {
+	if(verbosity>100) 
+	  cout << " MPI << (Matrice_Creuse *) " << a << endl;
+	ffassert(rq==0 || rq == Syncro_block) ; // 
+	int tag = MPI_TAG<Matrice_Creuse<R>* >::TAG;		       
+	MatriceMorse<R> *mA=a->A->toMatriceMorse();
+	int ldata[4];
+	ldata[0]=mA->n;
+	ldata[1]=mA->m;
+	ldata[2]=mA->nbcoef;
+	ldata[3]=mA->symetrique;
+	
+	if(verbosity>100)
+	  cout << " ldata " << ldata[0] << " " << ldata[1] <<" " << ldata[2] << " " <<ldata[3] << endl;
+	int ll=0;
+	ll=WSend( ldata,4, who, tag,comm,rq);
+	if(ll == MPI_SUCCESS) 
+	  ll=WSend(  mA->lg,mA->n+1,  who, tag+1,comm,rq);     
+	if(ll == MPI_SUCCESS) 
+	  ll=WSend( mA->cl,mA->nbcoef,  who, tag+2,comm,rq);  
+	if(ll == MPI_SUCCESS) 
+	  ll=WSend(  mA->a,mA->nbcoef,   who, tag+3,comm,rq);  
+	delete mA;
+	return ll;
+      }
+    else
+      {
+	SendWMatd<R> *rwm= new SendWMatd<R>(this,a);
+	if( rwm->DoSR() ) delete rwm;
+	return MPI_SUCCESS;
+      }
+  }
+
+  template<class R>
+  long MPIrank::Recv(Matrice_Creuse<R>  &  a) const 
+  {
+    if(0)
+      {
+	if(verbosity>100) 
+	  cout << " MPI << (Matrice_Creuse ) " << a << endl;
+	ffassert(rq==0 || rq == Syncro_block) ; // 
+	int tag =  MPI_TAG<Matrice_Creuse<R>* >::TAG;		       
+	int ldata[4];	
+	int ll=0;
+	ll=WRecv( ldata,4, who, tag,comm,rq);
+	MatriceMorse<R> *mA= new MatriceMorse<R>(ldata[0],ldata[1],ldata[2],ldata[3]); 
+	if(ll == MPI_SUCCESS) 
+	  ll=WRecv(  mA->lg,mA->n+1,   who, tag+1,comm,rq);     
+	if(ll == MPI_SUCCESS) 
+	  ll=WRecv(  mA->cl,mA->nbcoef,  who, tag+2,comm,rq);     
+	if(ll == MPI_SUCCESS) 
+	  ll=WRecv(  mA->a,mA->nbcoef,  who, tag+3,comm,rq);  
+	a.A.master(mA);
+	return ll;
+      }
+    else
+      {
+	RevcWMatd<R> *rwm= new RevcWMatd<R>(this,&a);
+        if( rwm->DoSR() ) delete rwm;
+        return MPI_SUCCESS;	
+      }
+  }
+
+
+long MPIrank::Send(Fem2D::Mesh *  a) const {
+    if(verbosity>100) 
+      cout << " MPI << (mesh *) " << a << endl;
+    ffassert(a);
+    SendWMeshd<Mesh> *rwm= new SendWMeshd<Mesh>(this,&a);
+    //cout << " ... "<< endl;
+    if( rwm->DoSR() ) delete rwm;
+    return MPI_SUCCESS;
+  }
+long MPIrank::Send (Fem2D::Mesh3 *  a) const {
+    if(verbosity>100) 
+      cout << " MPI << (mesh3 *) " << a << endl;
+    ffassert(a);
+    SendWMeshd<Mesh3> *rwm= new SendWMeshd<Mesh3>(this,&a);
+    if( rwm->DoSR() ) delete rwm;
+    return MPI_SUCCESS;
+  }
+
+/*
+long MPIrank::Send(Fem2D::Mesh *  a) const {
+    if(verbosity>100) 
+      cout << " MPI << (mesh *) " << a << endl;
+    ffassert(a);
+    Serialize  buf=(*a).serialize();       
+    buf.mpisend(*this,MPI_TAG<Mesh *>::TAG,static_cast<const void *>(this));
+    return MPI_SUCCESS;
+  }
+long MPIrank::Send (Fem2D::Mesh3 *  a) const {
+    if(verbosity>100) 
+      cout << " MPI << (mesh3 *) " << a << endl;
+    ffassert(a);
+    Serialize  buf=(*a).serialize();       
+    buf.mpisend(*this,MPI_TAG<Mesh3 *>::TAG,static_cast<const void *>(this));
+    return MPI_SUCCESS;
+  }
+*/
+
+// new version asyncrone ...  Now 2010 ... 
+long MPIrank::Recv(Fem2D::Mesh *& a) const  {
+    if(verbosity>100) 
+	cout << " MPI >> (mesh *) &" << a << " " << &a << endl;
+    RevcWMeshd<Mesh> *rwm= new RevcWMeshd<Mesh>(this,&a);
+    if( rwm->DoSR() ) delete rwm;
+    if((rq==0 || rq == Syncro_block))  
+      ffassert( a );
+    return MPI_SUCCESS;
+}
+
+long MPIrank::Recv(Fem2D::Mesh3 *& a) const  {
+    if(verbosity>100) 
+      cout << " MPI >> (mesh3 *) &" << a << " " << &a << endl;
+    RevcWMeshd<Mesh3> *rwm= new RevcWMeshd<Mesh3>(this,&a);
+    if( rwm->DoSR() ) delete rwm;
+    if((rq==0 || rq == Syncro_block))  
+      ffassert( a );
+    return MPI_SUCCESS;
+}
+
+
+void Serialize::mpisend(const MPIrank & rank,long tag,const void * vmpirank)
+{
+  const MPIrank * mpirank=static_cast<const MPIrank *> (vmpirank);
+  MPI_Comm comm=mpirank->comm;
+  MPI_Request *rq=mpirank->rq;
+  ffassert(rq==0 || rq == Syncro_block);
+  char * pp = p-sizeof(long);
+  long countsave=count(); // save count 
+  count()=lg; // store length in count 
+  int l=lg+sizeof(long);
+  if(verbosity>100) 
+    cout << " -- send from  " << mpirank << " to " << rank << " serialized " << what 
+	 <<   ", l=" << l << ", tag=" << tag << " " << (l < sizempibuf) << endl;
+  if (l <=sizempibuf)
+    WSend(pp,l, rank, tag,comm,rq);
+  else {
+    WSend(pp,sizempibuf,  rank, tag,comm,rq);
+    WSend(pp+sizempibuf,l-sizempibuf, rank, tag+1,comm,rq);
+  }
+  if(verbosity>100) 
+    cout << "    ok send is arrived " << endl;      
+  count()=countsave; // restore count 
+}
+
+
+Serialize::Serialize(const MPIrank & rank,const char * wht,long tag,const void * vmpirank)
+  :what(wht) 
+{
+  const MPIrank * mpirank=static_cast<const MPIrank *> (vmpirank);
+  MPI_Comm comm=mpirank->comm;
+  MPI_Request *rq=mpirank->rq;
+  
+  if(verbosity>100) 
+    cout << " -- waiting " << mpirank << " from  " << rank << " serialized " << what 
+	 << " tag = " << tag <<  endl;
+  if(!(rq==0 || rq == Syncro_block))
+    {
+      ExecError("Not async recv of complex  objet!  Sorry to hard to code (FH!).");
+      ffassert(rq==0 || rq == Syncro_block); 
+    }
+      
+ 
+  char * buf= new char [sizempibuf];
+  WRecv(buf, sizempibuf,  rank, tag,comm,rq);
+  lg = * (long *) (void *) buf;
+  int l=lg+sizeof(long);
+  char * pp= new char[l]  ;
+  if ( l <= sizempibuf) 
+    memcpy(pp,buf,l);
+  else 
+    {
+      memcpy(pp,buf,sizempibuf);
+      WRecv(pp+sizempibuf,l-sizempibuf,  rank, tag+1,comm,rq)  ;       
+    }
+  
+  if(verbosity>100) 
+    cout << "    " << mpirank << " recived from " << rank << " serialized " << what <<   ", l=" 
+	 << l << ", tag=" << tag << endl;
+  delete [] buf;
+  p=pp+sizeof(long);
+  count()=0;
+  
+}
+
+template<class A>
+struct Op_Readmpi : public binary_function<MPIrank,A*,MPIrank> {
+  static MPIrank  f(MPIrank const  & f,A *  const  & a)  
+  { 
+    f.Recv(*a);
+    return f;
+  }
+};
+
+template<class A>
+struct Op_Recvmpi : public binary_function<MPIrank,A*,long> {
+  static MPIrank  f(MPIrank const  & f,A *  const  & a)  
+  { 
+    ffassert(f.rq ==0 || f.rq == Syncro_block); // Block 
+    return f.Recv(*a);
+    
+  }
+};
+template<class A>
+struct Op_IRecvmpi : public binary_function<MPIrank,A*,long> {
+  static MPIrank  f(MPIrank const  & f,A *  const  & a)  
+  { 
+    ffassert(f.rq !=0 || f.rq != Syncro_block); // no Block 
+    return f.Recv(*a);
+    
+  }
+};
+
+
+template<class A>
+struct Op_Writempi : public binary_function<MPIrank,A,MPIrank> {
+  static MPIrank  f(MPIrank const  & f,A   const  &  a)  
+  { 
+    f.Send(a);
+    return f;
+  }
+};
+
+
+template<class A>
+struct Op_Bcastmpi : public binary_function<MPIrank,A*,MPIrank> {
+  static MPIrank  f(MPIrank const  & f,A *  const  & a)  
+  { 
+    f.Bcast(*a);
+    return f;
+   }
+};
+
+template<class A>
+struct Op_ISendmpi : public binary_function<MPIrank,A,long> {
+  static MPIrank  f(MPIrank const  & f,A   const  & a)  
+  { 
+    ffassert(f.rq != Syncro_block); 
+    return f.Send(a);
+  }
+};
+template<class A>
+struct Op_Sendmpi : public binary_function<MPIrank,A,long> {
+  static MPIrank  f(MPIrank const  & f,A  const  & a)  
+  { 
+	MPIrank ff(f.who,f.comm,Syncro_block); 
+	return ff.Send(a);
+  }
+};
+
+
+template<class R>
+struct Op_All2All : public binary_function<KN_<R>,KN_<R>,long> {
+  static long  f( KN_<R>  const  & s, KN_<R>  const  &r)  
+  { 
+      CheckContigueKN(s);
+      CheckContigueKN(r);
+
+    MPI_Comm comm=MPI_COMM_WORLD;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); /* local */ 
+    int chunk = s.N()/mpisizew;
+    ffassert(s.N()==mpisizew*chunk && r.N()==s.N());
+    
+    return MPI_Alltoall( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			 (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(), comm);	
+  }
+};
+
+
+template<class R>
+struct Op_Allgather1 : public binary_function<R*,KN_<R>,long> {
+  static long  f( R*  const  & s, KN_<R>  const  &r)  
+    { 
+      MPI_Comm comm=MPI_COMM_WORLD;
+      int mpisizew;
+	CheckContigueKN(r);
+
+      MPI_Comm_size(comm, &mpisizew); /* local */ 
+      int chunk = 1;
+      ffassert(r.N()==mpisizew);
+      
+      return MPI_Allgather( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			    (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(), comm);	
+    }
+};
+
+template<class R>
+struct Op_Allgather : public binary_function<KN_<R>,KN_<R>,long> {
+  static long  f( KN_<R>  const  & s, KN_<R>  const  &r)  
+    { 
+	CheckContigueKN(s);
+	CheckContigueKN(r);
+
+      MPI_Comm comm=MPI_COMM_WORLD;
+      int mpisizew;
+      MPI_Comm_size(comm, &mpisizew); /* local */ 
+      int chunk = r.N()/mpisizew;
+      ffassert(r.N()==mpisizew*chunk && chunk == s.N());
+      return MPI_Allgather( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			    (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(), comm);	
+    }
+};
+
+template<class R>
+struct Op_All2All3 : public ternary_function<KN_<R>,KN_<R>,fMPI_Comm,long> {
+  static long  f(Stack, KN_<R>  const  & s, KN_<R>  const  &r,fMPI_Comm const & cmm )  
+    { 
+	CheckContigueKN(s);
+	CheckContigueKN(r);
+
+      MPI_Comm comm=cmm;
+      int mpisizew;
+      MPI_Comm_size(comm, &mpisizew); /* local */ 
+      int chunk = s.N()/mpisizew;
+      ffassert(s.N()==mpisizew*chunk && r.N()==s.N());
+      
+      return MPI_Alltoall( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			   (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(), comm);	
+    }
+};
+
+template<class R>
+struct Op_Allgather3 : public ternary_function<KN_<R>,KN_<R>,fMPI_Comm,long> {
+  static long  f(Stack, KN_<R>  const  & s, KN_<R>  const  &r,fMPI_Comm const & cmm)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    MPI_Comm comm=cmm;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); /* local */ 
+    int chunk = r.N()/mpisizew;    // bug corrected by J. Morice
+    //ffassert(s.N()==mpisizew*chunk && r.N()==s.N());
+    ffassert(s.N()==chunk && r.N()==s.N()*mpisizew);
+	
+    return MPI_Allgather( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			  (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(), comm);	
+  }
+};
+
+
+template<class R>
+struct Op_Allgather13 : public ternary_function<R*,KN_<R>,fMPI_Comm,long> {
+  static long  f(Stack, R*  const  & s, KN_<R>  const  &r,fMPI_Comm const & cmm)  
+  { 
+      
+      CheckContigueKN(r);
+
+    MPI_Comm comm=cmm;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); /* local */ 
+    int chunk = 1;    // bug corrected by J. Morice
+    //ffassert(s.N()==mpisizew*chunk && r.N()==s.N());
+    ffassert( r.N()==mpisizew);
+	
+    return MPI_Allgather( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			  (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(), comm);	
+  }
+};
+// Add J. Morice
+
+template<class R>
+long  Op_All2Allv( KN_<R>  const  & s, KN_<R>  const  &r, KN_<long> const &sendcnts, KN_<long> const &sdispls, KN_<long> const &recvcnts, KN_<long> const &rdispls)  
+{ 
+    CheckContigueKN(s);
+    CheckContigueKN(r);
+
+  MPI_Comm comm=MPI_COMM_WORLD;
+  int mpirankv=MPI_UNDEFINED;
+  MPI_Comm_rank(comm, &mpirankv); 
+  
+  int mpisizew;
+  MPI_Comm_size(comm, &mpisizew); /* local */ 
+  ffassert( sendcnts.N() == sdispls.N() && sendcnts.N() == recvcnts.N() && sendcnts.N() == rdispls.N() && sendcnts.N() == mpisizew );
+  
+  KN<int> INTsendcnts(sendcnts.N());
+  KN<int> INTsdispls(sdispls.N());
+  KN<int> INTrecvcnts(recvcnts.N());
+  KN<int> INTrdispls(rdispls.N());
+  
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii] = sendcnts[ii];
+    INTsdispls[ii]  = sdispls[ii];
+    INTrecvcnts[ii]  = recvcnts[ii];
+    INTrdispls[ii]  = rdispls[ii];
+  }
+  
+  return MPI_Alltoallv( (void *) (R*) s, INTsendcnts, INTsdispls, MPI_TYPE<R>::TYPE(),
+			(void *) (R*) r, INTrecvcnts, INTrdispls, MPI_TYPE<R>::TYPE(), comm);	
+}
+
+
+
+template<class R>
+struct Op_Allgatherv : public quad_function<KN_<R>,KN_<R>,KN_<long>,KN_<long>,long> {
+  static long f( Stack ,KN_<R>  const  & s, KN_<R>  const  &r, KN_<long> const & recvcount, KN_<long> const & displs)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    MPI_Comm comm=MPI_COMM_WORLD;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); 
+    ffassert( recvcount.N() == displs.N() && recvcount.N() == mpisizew);
+    long sum=0;
+    for(int ii=0; ii< recvcount.N(); ii++)
+      sum+=recvcount[ii];
+    ffassert( sum == r.N() );
+    
+    KN<int> INTrecvcount(recvcount.N());
+    KN<int> INTdispls(displs.N());
+    for(int ii=0; ii< recvcount.N(); ii++){
+      INTrecvcount[ii]= recvcount[ii];
+      INTdispls[ii]= displs[ii];
+    }
+    return MPI_Allgatherv( (void *) (R*) s, s.N(), MPI_TYPE<R>::TYPE(),
+			   (void *) (R*) r, INTrecvcount, INTdispls,MPI_TYPE<R>::TYPE(), comm);	
+  }
+};
+
+template<class R>
+long  Op_All2All3v(KN_<R>  const  & s, KN_<R>  const  &r,fMPI_Comm const & cmm, KN_<long> const &sendcnts, KN_<long> const &sdispls, KN_<long> const &recvcnts, KN_<long> const &rdispls )  
+{ 
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  MPI_Comm comm=cmm;
+  int mpirankv=MPI_UNDEFINED;
+  MPI_Comm_rank(comm, &mpirankv); 
+      
+  int mpisizew;
+  MPI_Comm_size(comm, &mpisizew); /* local */ 
+  ffassert( sendcnts.N() == sdispls.N() && sendcnts.N() == recvcnts.N() && sendcnts.N() == rdispls.N() && sendcnts.N() == mpisizew );
+      
+  //ffassert(s.N()==sendcnts[mpirankv] && r.N()==recvbuf[mpirankv]);
+      
+  KN<int> INTsendcnts(sendcnts.N());
+  KN<int> INTsdispls(sdispls.N());
+  KN<int> INTrecvcnts(recvcnts.N());
+  KN<int> INTrdispls(rdispls.N());
+      
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii] = sendcnts[ii];
+    INTsdispls[ii]  = sdispls[ii];
+    INTrecvcnts[ii]  = recvcnts[ii];
+    INTrdispls[ii]  = rdispls[ii];
+  }
+
+  return MPI_Alltoallv( (void *) (R*) s, INTsendcnts, INTsdispls, MPI_TYPE<R>::TYPE(),
+			(void *) (R*) r, INTrecvcnts, INTrdispls, MPI_TYPE<R>::TYPE(), comm);	
+}
+
+
+template<class R>
+long Op_Allgatherv3(KN_<R>  const  & s, KN_<R>  const  &r,fMPI_Comm const & cmm, KN_<long> const & recvcount, KN_<long> const & displs)
+{ 
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  MPI_Comm comm=cmm;
+  int mpisizew;
+  MPI_Comm_size(comm, &mpisizew); 
+  ffassert( recvcount.N() == displs.N() && recvcount.N() == mpisizew);
+  long sum=0;
+  for(int ii=0; ii< recvcount.N(); ii++)
+    sum+=recvcount[ii];
+  ffassert( sum == r.N() );
+  KN<int> INTrecvcount(recvcount.N());
+  KN<int> INTdispls(displs.N());
+  for(int ii=0; ii< recvcount.N(); ii++){
+    INTrecvcount[ii]= recvcount[ii];
+    INTdispls[ii]= displs[ii];
+  }
+
+  return MPI_Allgatherv( (void *) (R*) s, s.N(), MPI_TYPE<R>::TYPE(),
+			 (void *) (R*) r, INTrecvcount, INTdispls,MPI_TYPE<R>::TYPE(), comm);	
+}
+
+
+template<class R>
+struct Op_Scatter1 : public   ternary_function<KN_<R>, R* ,MPIrank,long> {
+  static long  f(Stack, KN_<R>  const  & s, R*  const  &r,  MPIrank const & root)  
+  { 
+      CheckContigueKN(s);
+      
+
+    int mpisizew;
+    MPI_Comm_size(root.comm, &mpisizew); 
+    int chunk = 1;
+   // ffassert(s.N()==mpisizew*chunk);
+    
+    return MPI_Scatter( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			(void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(),root.who,root.comm);	
+  }
+};
+
+
+// Fin add J. Morice
+
+
+template<class R>
+struct Op_Scatter3 : public   ternary_function<KN_<R>,KN_<R>,MPIrank,long> {
+  static long  f(Stack, KN_<R>  const  & s, KN_<R>  const  &r,  MPIrank const & root)  
+  { 
+    
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    int mpisizew;
+    MPI_Comm_size(root.comm, &mpisizew); 
+    int chunk = r.N(); // FH  correct  jan 2012 ... 
+    // ffassert(s.N()==mpisizew*chunk && r.N()==chunk);
+    
+    return MPI_Scatter( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			(void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(),root.who,root.comm);	
+  }
+};
+
+// Add J. Morice
+template<class R>
+//struct Op_Scatterv3 : public   penta_function< KN_<R>, KN_<R>, MPIrank, KN_<long>, KN_<long>, long> {
+long Op_Scatterv3( KN_<R>  const  & s, KN_<R>  const  &r,  MPIrank const & root, KN_<long> const &sendcnts, KN_<long> const &displs)  
+{ 
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  int mpirankv=MPI_UNDEFINED;
+  if(root.comm != MPI_COMM_NULL)
+    MPI_Comm_rank(root.comm, &mpirankv); 
+  
+  int mpisizew;
+  MPI_Comm_size(root.comm, &mpisizew); /* local */ 
+  KN<int> INTsendcnts(mpirankv == root.who ? sendcnts.N() : 0);
+  KN<int> INTdispls(mpirankv == root.who ? sendcnts.N() : 0);
+  for(int ii=0; ii< INTsendcnts.N(); ii++){
+    INTsendcnts[ii]= sendcnts[ii];
+    INTdispls[ii]= displs[ii];
+  }
+  
+  return MPI_Scatterv( (void *) (R*) s, INTsendcnts, INTdispls, MPI_TYPE<R>::TYPE(),
+		       (void *) (R*) r, r.N(), MPI_TYPE<R>::TYPE(),root.who,root.comm);
+}
+
+// fin J. Morice
+
+template<class R>
+struct Op_ReduceMat  : public   quad_function<Matrice_Creuse<R>*,Matrice_Creuse<R> *,MPIrank,fMPI_Op,long> {
+    static long  f(Stack, Matrice_Creuse<R>*  const  & s,Matrice_Creuse<R>*  const  &r,  MPIrank const & root, fMPI_Op const &op)  
+    { 
+	ffassert( r && s);
+	MatriceCreuse<R> * sA=s->A;
+	MatriceCreuse<R> * rA=r->A;
+	ffassert( sA && rA); 
+	MatriceMorse<R> & sM = *dynamic_cast<MatriceMorse<R>* > (sA);
+	MatriceMorse<R> & rM = *dynamic_cast<MatriceMorse<R>* > (rA);
+	ffassert( &sM && &rM);
+	int chunk = sM.nbcoef;
+	ffassert(chunk==rM.nbcoef);
+	
+	return MPI_Reduce( (void *)  sM.a,(void *)  rM.a, chunk , MPI_TYPE<R>::TYPE(),op,root.who,root.comm);	
+    }
+};
+template<class R>
+struct Op_AllReduceMat  : public   quad_function<Matrice_Creuse<R>*,Matrice_Creuse<R> *,fMPI_Comm,fMPI_Op,long> {
+    static long  f(Stack, Matrice_Creuse<R>*  const  & s,Matrice_Creuse<R>*  const  &r,  fMPI_Comm const & comm, fMPI_Op const &op)  
+    { 
+	ffassert( r && s);
+	MatriceCreuse<R> * sA=s->A;
+	MatriceCreuse<R> * rA=r->A;
+	ffassert( &sA );
+
+	MatriceMorse<R> & sM = *dynamic_cast<MatriceMorse<R>* > (sA);
+        ffassert( &sM );
+	if( ! rA ) { // build a zero matric copy of sM
+	    MatriceMorse<R> *rm=new MatriceMorse<R>(sM.n,sM.m,sM.nbcoef,sM.symetrique,0,sM.lg,sM.cl);
+	    *rm=R(); // set the matrix to Zero ..
+	    r->A.master(rm);
+	    rA=r->A;
+	    
+	}
+	ffassert( sA && rA); 
+	
+	MatriceMorse<R> & rM = *dynamic_cast<MatriceMorse<R>* > (rA);
+	
+	ffassert( &sM && &rM);
+	int chunk = sM.nbcoef;
+	ffassert(chunk==rM.nbcoef);
+	
+	return MPI_Allreduce( (void *)  sM.a,(void *)  rM.a, chunk , MPI_TYPE<R>::TYPE(),op,comm);	
+    }
+};
+
+
+
+template<class R>
+struct Op_Reduce  : public   quad_function<KN_<R>,KN_<R>,MPIrank,fMPI_Op,long> {
+  static long  f(Stack, KN_<R>  const  & s, KN_<R>  const  &r,  MPIrank const & root, fMPI_Op const &op)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    int chunk = s.N();
+    ffassert(chunk==r.N());
+    
+    return MPI_Reduce( (void *) (R*) s,(void *) (R*) r, chunk , MPI_TYPE<R>::TYPE(),op,root.who,root.comm);	
+  }
+};
+
+template<class R>
+struct Op_AllReduce  : public   quad_function<KN_<R>,KN_<R>,fMPI_Comm,fMPI_Op,long> {
+  static long  f(Stack, KN_<R>  const  & s, KN_<R>  const  &r,  fMPI_Comm const & comm,fMPI_Op const &op)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    int chunk = s.N();
+    ffassert(chunk==r.N());
+    return MPI_Allreduce( (void *) (R*) s,(void *) (R*) r, chunk , MPI_TYPE<R>::TYPE(),op,comm);	
+  }
+};
+
+template<class R>
+struct Op_AllReduce1  : public   quad_function<R *,R *,fMPI_Comm,fMPI_Op,long> {
+    static long  f(Stack, R *  const  & s, R *  const  &r,  fMPI_Comm const & comm,fMPI_Op const &op)  
+    { 
+	int chunk = 1;
+	return MPI_Allreduce( (void *) (R*) s,(void *) (R*) r, 1 , MPI_TYPE<R>::TYPE(),op,comm);	
+    }
+};
+/*
+template<class R>
+struct Op_Reducescatter  : public   quad_function<KN_<R>,KN_<R>,fMPI_Comm,fMPI_Op,long> {
+    static long  f(Stack, KN_<R>  const  & s, KN_<R>  const  &r,  fMPI_Comm const & comm,fMPI_Op const &op)  
+    { 
+	int chunk = s.N();
+	ffassert(chunk==r.N());
+        //    chunk est un tableau ????
+	MPI_Op oop = reinterpret_cast<MPI_Op> (op);
+	return MPI_Reduce_scatter( (void *) (R*) s,(void *) (R*) r, chunk , MPI_TYPE<R>::TYPE(),op,comm);	
+    }
+};*/
+
+template<class R>
+struct Op_Reduce1  : public   quad_function<R*,R*,MPIrank,fMPI_Op,long> {
+  static long  f(Stack, R*  const  & s, R*  const  &r,  MPIrank const & root, fMPI_Op const &op)  
+  { 
+    int chunk = 1;
+    return MPI_Reduce( (void *) (R*) s,(void *) (R*) r, chunk , MPI_TYPE<R>::TYPE(),op,root.who,root.comm);	
+  }
+};
+
+// Add J. Morice
+template<class R>
+struct Op_Gather1 : public   ternary_function<R*,KN_<R>,MPIrank,long> {
+    static long  f(Stack, R* const  & s, KN_<R>  const  &r,  MPIrank const & root)  
+  { 
+    
+    int mpisizew,myrank;
+    MPI_Comm_size(root.comm, &mpisizew); 
+    MPI_Comm_rank( root.comm, &myrank)  ;
+    int chunk = 1;
+    // ffassert( (myrank != root.who) || (r.N()>=mpisizew*chunk) );
+    
+    return MPI_Gather( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			   (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(),root.who,root.comm);	
+  }
+};
+
+// Fin Add J. Morice
+
+
+template<class R>
+struct Op_Gather3 : public   ternary_function<KN_<R>,KN_<R>,MPIrank,long> {
+    static long  f(Stack, KN_<R>  const  & s, KN_<R>  const  &r,  MPIrank const & root)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+      int mpisizew,myrank;
+      MPI_Comm_size(root.comm, &mpisizew); 
+      MPI_Comm_rank(root.comm, &myrank)  ;
+
+    int chunk = s.N();
+    //  cout << myrank << " " << root.who << " " << r.N() << " "<< s.N() << " " << chunk << " " << mpisizew << endl;
+    //ffassert( (myrank != root.who) || (r.N()==mpisizew*chunk) );
+    
+    return MPI_Gather( (void *) (R*) s, chunk, MPI_TYPE<R>::TYPE(),
+			   (void *) (R*) r, chunk, MPI_TYPE<R>::TYPE(),root.who,root.comm);	
+  }
+};
+
+// Add by J. Morice
+
+template<class R>
+//struct Op_Gatherv3 : public penta_function<KN_<R>,KN_<R>, MPIrank, KN_<long>, KN_<long>, long> {
+long  Op_Gatherv3(KN_<R>  const  & s, KN_<R>  const  &r,  MPIrank const & root, KN_<long> const & recvcount, KN_<long> const & displs)  
+{ 
+    
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  int mpirankw;
+  MPI_Comm_rank(root.comm, &mpirankw); 
+  int mpisizew;
+  MPI_Comm_size(root.comm, &mpisizew); 
+  KN<int> INTrecvcount(mpirankw == root.who ? recvcount.N() : 0);
+  KN<int> INTdispls(mpirankw == root.who ? recvcount.N() : 0);
+  for(int ii=0; ii< INTrecvcount.N(); ii++){
+    INTrecvcount[ii]= recvcount[ii];
+    INTdispls[ii]= displs[ii];
+  }
+  
+  return MPI_Gatherv( (void *) (R*) s, s.N(), MPI_TYPE<R>::TYPE(),
+		      (void *) (R*) r, INTrecvcount, INTdispls,MPI_TYPE<R>::TYPE(),root.who,root.comm);	
+}
+
+// Fin Add J. Morice
+
+
+// Add J. Morice communications entre processeurs complex
+
+template<>
+struct Op_All2All<Complex> : public binary_function<KN_<Complex>,KN_<Complex>,long> {
+  static long  f( KN_<Complex>  const  & s, KN_<Complex>  const  &r)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    MPI_Comm comm=MPI_COMM_WORLD;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); /* local */ 
+    int chunk = s.N()/mpisizew;
+    ffassert(s.N()==mpisizew*chunk && r.N()==s.N());
+   
+#ifdef HAVE_MPI_DOUBLE_COMPLEX 
+    return MPI_Alltoall( (void *) (Complex*) s, chunk, MPI_DOUBLE_COMPLEX,
+			 (void *) (Complex*) r, chunk, MPI_DOUBLE_COMPLEX, comm);	
+#else
+    chunk*=2;
+    return MPI_Alltoall( reinterpret_cast<void*> ( (Complex*) s), chunk, MPI_DOUBLE,
+			 reinterpret_cast<void*> ( (Complex*) r), chunk, MPI_DOUBLE, comm);	
+#endif
+  }
+};
+
+template<>
+struct Op_Allgather1<Complex> : public binary_function<Complex *,KN_<Complex>,long> {
+  static long  f( Complex *  const  & s, KN_<Complex>  const  &r)  
+  { 
+      CheckContigueKN(r);
+      
+
+    MPI_Comm comm=MPI_COMM_WORLD;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); /* local */ 
+    int chunk = 1;    
+    ffassert( r.N()== mpisizew);
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    return MPI_Allgather( (void *) (Complex*) s, chunk, MPI_DOUBLE_COMPLEX,
+			  (void *) (Complex*) r, chunk, MPI_DOUBLE_COMPLEX, comm);
+#else
+    chunk*=2;
+    return MPI_Allgather( reinterpret_cast<void*> ( (Complex*) s), chunk, MPI_DOUBLE,
+			  reinterpret_cast<void*> ( (Complex*) r), chunk, MPI_DOUBLE, comm);
+#endif
+  }
+};
+
+
+template<>
+struct Op_Allgather<Complex> : public binary_function<KN_<Complex>,KN_<Complex>,long> {
+  static long  f( KN_<Complex>  const  & s, KN_<Complex>  const  &r)  
+    { 
+	CheckContigueKN(r);
+	CheckContigueKN(s);
+
+      MPI_Comm comm=MPI_COMM_WORLD;
+      int mpisizew;
+      MPI_Comm_size(comm, &mpisizew); /* local */ 
+      int chunk = r.N()/mpisizew;
+      ffassert( r.N()==chunk*mpisizew && chunk==s.N() );
+#ifdef HAVE_MPI_DOUBLE_COMPLEX 
+      return MPI_Allgather( (void *) (Complex*) s, chunk, MPI_DOUBLE_COMPLEX,
+			    (void *) (Complex*) r, chunk, MPI_DOUBLE_COMPLEX, comm);
+#else
+      chunk*=2;
+      return MPI_Allgather( reinterpret_cast<void*> (  (Complex*) s), chunk, MPI_DOUBLE,
+			    reinterpret_cast<void*> ( (Complex*) r), chunk, MPI_DOUBLE, comm);
+#endif
+    }
+};
+
+template<>
+struct Op_All2All3<Complex> : public ternary_function<KN_<Complex>,KN_<Complex>,fMPI_Comm,long> {
+  static long  f(Stack, KN_<Complex>  const  & s, KN_<Complex>  const  &r,fMPI_Comm const & cmm )  
+    { 
+	CheckContigueKN(r);
+	CheckContigueKN(s);
+
+      MPI_Comm comm=cmm;
+      int mpisizew;
+      MPI_Comm_size(comm, &mpisizew); /* local */ 
+      int chunk = s.N()/mpisizew;
+      ffassert(s.N()==mpisizew*chunk && r.N()==s.N());
+#ifdef HAVE_MPI_DOUBLE_COMPLEX       
+      return MPI_Alltoall( (void *) (Complex*) s, chunk, MPI_DOUBLE_COMPLEX,
+			   (void *) (Complex*) r, chunk, MPI_DOUBLE_COMPLEX, comm);
+#else
+      chunk*=2;
+      return MPI_Alltoall( (void *) (Complex*) s, chunk, MPI_DOUBLE,
+			   (void *) (Complex*)  (r), chunk, MPI_DOUBLE, comm);
+#endif	
+    }
+};
+
+template<>
+struct Op_Allgather3<Complex> : public ternary_function<KN_<Complex>,KN_<Complex>,fMPI_Comm,long> {
+  static long  f(Stack, KN_<Complex>  const  & s, KN_<Complex>  const  &r,fMPI_Comm const & cmm)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    MPI_Comm comm=cmm;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); /* local */ 
+    int chunk = r.N()/mpisizew;    // bug corrected by J. Morice
+    //ffassert(s.N()==mpisizew*chunk && r.N()==s.N());
+    ffassert(s.N()==chunk && r.N()==s.N()*mpisizew);
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    return MPI_Allgather( (void *) (Complex*) s, chunk, MPI_DOUBLE_COMPLEX,
+			  (void *) (Complex*) r, chunk, MPI_DOUBLE_COMPLEX, comm);
+#else
+    chunk*=2;
+    return MPI_Allgather( (void *) (Complex*) (s), chunk, MPI_DOUBLE,
+			 (void *) (Complex*) (r), chunk, MPI_DOUBLE, comm);
+#endif
+  }
+};
+
+template<>
+struct Op_Allgather13<Complex> : public ternary_function<Complex *,KN_<Complex>,fMPI_Comm,long> {
+  static long  f(Stack, Complex *  const  & s, KN_<Complex>  const  &r,fMPI_Comm const & cmm)  
+  { 
+      CheckContigueKN(r);
+     
+
+    MPI_Comm comm=cmm;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); /* local */ 
+    int chunk = 1;    
+    ffassert( r.N()==mpisizew);
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    return MPI_Allgather( (void *) (Complex*) s, chunk, MPI_DOUBLE_COMPLEX,
+			  (void *) (Complex*) r, chunk, MPI_DOUBLE_COMPLEX, comm);
+#else
+    chunk*=2;
+    return MPI_Allgather((void *) (Complex*)(s), chunk, MPI_DOUBLE,
+			   (void *) (Complex*) (r), chunk, MPI_DOUBLE, comm);
+#endif
+  }
+};
+
+
+template<>
+long  Op_All2Allv<Complex>( KN_<Complex>  const  & s, KN_<Complex>  const  &r, KN_<long> const &sendcnts, KN_<long> const &sdispls, KN_<long> const &recvcnts, KN_<long> const &rdispls)  
+{ 
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  MPI_Comm comm=MPI_COMM_WORLD;
+  int mpirankv=MPI_UNDEFINED;
+  MPI_Comm_rank(comm, &mpirankv); 
+  
+  int mpisizew;
+  MPI_Comm_size(comm, &mpisizew); /* local */ 
+  ffassert( sendcnts.N() == sdispls.N() && sendcnts.N() == recvcnts.N() && sendcnts.N() == rdispls.N() && sendcnts.N() == mpisizew );
+  
+  KN<int> INTsendcnts(sendcnts.N());
+  KN<int> INTsdispls(sdispls.N());
+  KN<int> INTrecvcnts(recvcnts.N());
+  KN<int> INTrdispls(rdispls.N());
+  
+  
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii] = sendcnts[ii];
+    INTsdispls[ii]  = sdispls[ii];
+    INTrecvcnts[ii]  = recvcnts[ii];
+    INTrdispls[ii]  = rdispls[ii];
+  }
+  return MPI_Alltoallv( (void *) (Complex*) s, INTsendcnts, INTsdispls, MPI_DOUBLE_COMPLEX,
+			(void *) (Complex*) r, INTrecvcnts, INTrdispls, MPI_DOUBLE_COMPLEX, comm);	
+#else
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii] = 2*sendcnts[ii];
+    INTsdispls[ii]  = 2*sdispls[ii];
+    INTrecvcnts[ii] = 2*recvcnts[ii];
+    INTrdispls[ii]  = 2*rdispls[ii];
+  }
+  return MPI_Alltoallv( reinterpret_cast<void*> ( (Complex*) s), INTsendcnts, INTsdispls, MPI_DOUBLE,
+			reinterpret_cast<void*> ( (Complex*) r), INTrecvcnts, INTrdispls, MPI_DOUBLE, comm);
+#endif
+}
+
+
+
+template<>
+struct Op_Allgatherv<Complex> : public quad_function<KN_<Complex>,KN_<Complex>,KN_<long>,KN_<long>,long> {
+  static long f( Stack ,KN_<Complex>  const  & s, KN_<Complex>  const  &r, KN_<long> const & recvcount, KN_<long> const & displs)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    MPI_Comm comm=MPI_COMM_WORLD;
+    int mpisizew;
+    MPI_Comm_size(comm, &mpisizew); 
+    ffassert( recvcount.N() == displs.N() && recvcount.N() == mpisizew);
+    long sum=0;
+    for(int ii=0; ii< recvcount.N(); ii++)
+      sum+=recvcount[ii];
+    ffassert( sum == r.N() );
+  
+  
+    KN<int> INTrecvcount(recvcount.N());
+    KN<int> INTdispls(displs.N());
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    for(int ii=0; ii< recvcount.N(); ii++){
+      INTrecvcount[ii]= recvcount[ii];
+      INTdispls[ii]= displs[ii];
+    }
+    return MPI_Allgatherv( (void *) (Complex*)s, s.N(), MPI_DOUBLE_COMPLEX,
+			   (void *) (Complex*)r, INTrecvcount, INTdispls,MPI_DOUBLE_COMPLEX, comm);
+#else
+    for(int ii=0; ii< recvcount.N(); ii++){
+      INTrecvcount[ii]= 2*recvcount[ii];
+      INTdispls[ii]= 2*displs[ii];
+    }
+    return MPI_Allgatherv( reinterpret_cast<void*> ( (Complex*) s), 2*s.N(), MPI_DOUBLE,
+			   reinterpret_cast<void*> ( (Complex*) r), INTrecvcount, INTdispls,MPI_DOUBLE, comm);
+#endif	
+  }
+};
+
+template<>
+long  Op_All2All3v<Complex>(KN_<Complex>  const  & s, KN_<Complex>  const  &r,fMPI_Comm const & cmm, KN_<long> const &sendcnts, KN_<long> const &sdispls, KN_<long> const &recvcnts, KN_<long> const &rdispls )  
+{ 
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  MPI_Comm comm=cmm;
+  int mpirankv=MPI_UNDEFINED;
+  MPI_Comm_rank(comm, &mpirankv); 
+      
+  int mpisizew;
+  MPI_Comm_size(comm, &mpisizew); /* local */ 
+  ffassert( sendcnts.N() == sdispls.N() && sendcnts.N() == recvcnts.N() && sendcnts.N() == rdispls.N() && sendcnts.N() == mpisizew );
+      
+  //ffassert(s.N()==sendcnts[mpirankv] && r.N()==recvbuf[mpirankv]);
+      
+  KN<int> INTsendcnts(sendcnts.N());
+  KN<int> INTsdispls(sdispls.N());
+  KN<int> INTrecvcnts(recvcnts.N());
+  KN<int> INTrdispls(rdispls.N());
+    
+#ifdef HAVE_MPI_DOUBLE_COMPLEX  
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii] = sendcnts[ii];
+    INTsdispls[ii]  = sdispls[ii];
+    INTrecvcnts[ii]  = recvcnts[ii];
+    INTrdispls[ii]  = rdispls[ii];
+  }
+
+  return MPI_Alltoallv( (void *) (Complex*)s, INTsendcnts, INTsdispls, MPI_DOUBLE_COMPLEX,
+			(void *) (Complex*)r, INTrecvcnts, INTrdispls, MPI_DOUBLE_COMPLEX, comm);	
+#else
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii] = 2*sendcnts[ii];
+    INTsdispls[ii]  = 2*sdispls[ii];
+    INTrecvcnts[ii]  = 2*recvcnts[ii];
+    INTrdispls[ii]  = 2*rdispls[ii];
+  }
+
+  return MPI_Alltoallv( reinterpret_cast<void*> ( (Complex*) s), INTsendcnts, INTsdispls, MPI_DOUBLE,
+			reinterpret_cast<void*> ( (Complex*) r), INTrecvcnts, INTrdispls, MPI_DOUBLE, comm);
+#endif
+}
+
+
+template<>
+long Op_Allgatherv3<Complex>(KN_<Complex>  const  & s, KN_<Complex>  const  &r,fMPI_Comm const & cmm, KN_<long> const & recvcount, KN_<long> const & displs)
+{ 
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  MPI_Comm comm=cmm;
+  int mpisizew;
+  MPI_Comm_size(comm, &mpisizew); 
+  ffassert( recvcount.N() == displs.N() && recvcount.N() == mpisizew);
+  long sum=0;
+  for(int ii=0; ii< recvcount.N(); ii++)
+    sum+=recvcount[ii];
+  ffassert( sum == r.N() );
+  KN<int> INTrecvcount(recvcount.N());
+  KN<int> INTdispls(displs.N());
+  
+#ifdef HAVE_MPI_DOUBLE_COMPLEX 
+  for(int ii=0; ii< recvcount.N(); ii++){
+    INTrecvcount[ii]= recvcount[ii];
+    INTdispls[ii]= displs[ii];
+  }
+
+  return MPI_Allgatherv( (void *) (Complex*)s, s.N(), MPI_DOUBLE_COMPLEX,
+			 (void *) (Complex*)r, INTrecvcount, INTdispls,MPI_DOUBLE_COMPLEX, comm);	
+
+#else
+  for(int ii=0; ii< recvcount.N(); ii++){
+    INTrecvcount[ii]= 2*recvcount[ii];
+    INTdispls[ii]= 2*displs[ii];
+  }
+
+  return MPI_Allgatherv( reinterpret_cast<void*> ( (Complex*) s), 2*s.N(), MPI_DOUBLE,
+			 reinterpret_cast<void*> ( (Complex*) r), INTrecvcount, INTdispls,MPI_DOUBLE, comm);
+#endif
+
+}
+
+template<>
+struct Op_Scatter1<Complex> : public   ternary_function<KN_<Complex>,Complex *,MPIrank,long> {
+  static long  f(Stack, KN_<Complex> const  & s, Complex *  const  &r,  MPIrank const & root)  
+  { 
+     
+      CheckContigueKN(s);
+
+    int mpisizew;
+    MPI_Comm_size(root.comm, &mpisizew); 
+    int chunk = 1;
+    // ffassert(s.N()==mpisizew*chunk ); fait dans mpi
+#ifdef HAVE_MPI_DOUBLE_COMPLEX      
+    return MPI_Scatter( (void *) (Complex*)s, chunk, MPI_DOUBLE_COMPLEX,
+			(void *) (Complex*)r, chunk, MPI_DOUBLE_COMPLEX,root.who,root.comm);	
+#else
+    chunk*=2;
+    return MPI_Scatter( reinterpret_cast<void*> ( (Complex*) s), chunk, MPI_DOUBLE,
+			reinterpret_cast<void*> ( (Complex*) r), chunk, MPI_DOUBLE,root.who,root.comm);
+#endif
+  }
+};
+
+
+template<>
+struct Op_Scatter3<Complex> : public   ternary_function<KN_<Complex>,KN_<Complex>,MPIrank,long> {
+  static long  f(Stack, KN_<Complex>  const  & s, KN_<Complex>  const  &r,  MPIrank const & root)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    int mpisizew;
+    MPI_Comm_size(root.comm, &mpisizew); 
+    int chunk = r.N();// correct 2012 FH
+   // ffassert(s.N()==mpisizew*chunk && r.N()==chunk);
+#ifdef HAVE_MPI_DOUBLE_COMPLEX      
+    return MPI_Scatter( (void *) (Complex*)s, chunk, MPI_DOUBLE_COMPLEX,
+			(void *) (Complex*)r, chunk, MPI_DOUBLE_COMPLEX,root.who,root.comm);	
+#else
+    chunk*=2;
+    return MPI_Scatter( reinterpret_cast<void*> ( (Complex*) s), chunk, MPI_DOUBLE,
+			reinterpret_cast<void*> ( (Complex*) r), chunk, MPI_DOUBLE,root.who,root.comm);
+#endif
+  }
+};
+
+template<>
+long Op_Scatterv3<Complex>( KN_<Complex>  const  & s, KN_<Complex>  const  &r,  MPIrank const & root, KN_<long> const &sendcnts, KN_<long> const &displs)  
+{ 
+  
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  int mpirankv=MPI_UNDEFINED;
+  if(root.comm != MPI_COMM_NULL)
+    MPI_Comm_rank(root.comm, &mpirankv); 
+  
+  int mpisizew;
+  MPI_Comm_size(root.comm, &mpisizew); /* local */ 
+  //  ffassert( sendcnts.N() == displs.N() && sendcnts.N() == mpisizew );
+  // size control 
+  // ffassert( r.N() == sendcnts[mpirankv] );
+  long sumsize=0;
+  for(int ii=0; ii<sendcnts.N(); ii++){
+    sumsize += sendcnts[ii];
+  }
+  //ffassert( s.N() == sumsize );
+  
+  KN<int> INTsendcnts(sendcnts.N());
+  KN<int> INTdispls(displs.N());
+#ifdef HAVE_MPI_DOUBLE_COMPLEX  
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii]= sendcnts[ii];
+    INTdispls[ii]= displs[ii];
+  }
+
+  return MPI_Scatterv( (void *) (Complex*)s, INTsendcnts, INTdispls, MPI_DOUBLE_COMPLEX,
+		       (void *) (Complex*)r, r.N(), MPI_DOUBLE_COMPLEX,root.who,root.comm);
+#else
+  for(int ii=0; ii< sendcnts.N(); ii++){
+    INTsendcnts[ii]= 2*sendcnts[ii];
+    INTdispls[ii]= 2*displs[ii];
+  }
+
+  return MPI_Scatterv( reinterpret_cast<void*> ( (Complex*) s), INTsendcnts, INTdispls, MPI_DOUBLE,
+		       reinterpret_cast<void*> ( (Complex*) r), 2*r.N(), MPI_DOUBLE,root.who,root.comm);
+#endif
+
+}
+
+
+template<>
+struct Op_Reduce<Complex>  : public   quad_function<KN_<Complex>,KN_<Complex>,MPIrank,fMPI_Op,long> {
+  static long  f(Stack, KN_<Complex>  const  & s, KN_<Complex>  const  &r,  MPIrank const & root, fMPI_Op const &op)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    int chunk = s.N();
+    ffassert(chunk==r.N());
+#ifdef HAVE_MPI_DOUBLE_COMPLEX     
+    return MPI_Reduce( (void *) (Complex*)s,(void *) (Complex*)r, chunk , MPI_DOUBLE_COMPLEX,op,root.who,root.comm);
+#else
+    chunk*=2;
+    return MPI_Reduce( reinterpret_cast<void*> ( (Complex*) s), reinterpret_cast<void*> ( (Complex*) r), chunk , MPI_DOUBLE,op,root.who,root.comm);
+#endif	
+  }
+};
+
+template<>
+struct Op_AllReduce<Complex>  : public   quad_function<KN_<Complex>,KN_<Complex>,fMPI_Comm,fMPI_Op,long> {
+  static long  f(Stack, KN_<Complex>  const  & s, KN_<Complex>  const  &r,  fMPI_Comm const & comm,fMPI_Op const &op)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+    int chunk = s.N();
+    ffassert(chunk==r.N());
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    return MPI_Allreduce( (void *) (Complex*)s,(void *) (Complex*)r, chunk , MPI_DOUBLE_COMPLEX,op,comm);
+#else
+    chunk *=2;
+    return MPI_Allreduce( reinterpret_cast<void*> ( (Complex*) s), reinterpret_cast<void*> ( (Complex*) r), chunk , MPI_DOUBLE,op,comm);
+#endif	
+  }
+};
+// /*
+// template<>
+// struct Op_Reducescatter  : public   quad_function<KN_<Complex>,KN_<Complex>,fMPI_Comm,fMPI_Op,long> {
+//     static long  f(Stack, KN_<Complex>  const  & s, KN_<Complex>  const  &r,  fMPI_Comm const & comm,fMPI_Op const &op)  
+//     { 
+// 	int chunk = s.N();
+// 	ffassert(chunk==r.N());
+//         //    chunk est un tableau ????
+// 	MPI_Op oop = reinterpret_cast<MPI_Op> (op);
+// 	return MPI_Reduce_scatter( (void *) (Complex*)s,(void *) (Complex*)r, chunk , MPI_DOUBLE_COMPLEX,op,comm);	
+//     }
+// };*/
+
+template<>
+struct Op_Reduce1<Complex>  : public   quad_function<Complex*,Complex*,MPIrank,fMPI_Op,long> {
+  static long  f(Stack, Complex*  const  & s, Complex*  const  &r,  MPIrank const & root, fMPI_Op const &op)  
+  { 
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    int chunk = 1;
+    return MPI_Reduce( (void *) s, (void *) r, chunk , MPI_DOUBLE_COMPLEX,op,root.who,root.comm);
+#else
+    int chunk = 2;
+    return MPI_Reduce( reinterpret_cast<void*> ( (Complex*) s), reinterpret_cast<void*> ( (Complex*) r), chunk , MPI_DOUBLE,op,root.who,root.comm);
+#endif
+  }
+};
+
+// Add J. Morice
+template<>
+struct Op_Gather1<Complex> : public   ternary_function<Complex* ,KN_<Complex>,MPIrank,long> {
+    static long  f(Stack, Complex * const  & s, KN_<Complex>  const  &r,  MPIrank const & root)  
+  { 
+    
+      CheckContigueKN(r);
+      
+
+      int mpisizew,myrank;
+      MPI_Comm_size(root.comm, &mpisizew); 
+      MPI_Comm_rank( root.comm, &myrank)  ;
+      
+    int chunk = 1;
+   // ffassert( (myrank != root.who) || (r.N()>=mpisizew*chunk) );
+#ifdef HAVE_MPI_DOUBLE_COMPLEX  
+       
+    return MPI_Gather( (void *) (Complex*) s, chunk, MPI_DOUBLE_COMPLEX,
+			   (void *) (Complex*) r, chunk, MPI_DOUBLE_COMPLEX, root.who, root.comm);
+#else
+    chunk = 2;
+    return MPI_Gather( reinterpret_cast<void*> ( (Complex*) s), chunk, MPI_DOUBLE,
+		       reinterpret_cast<void*> ( (Complex*) r), chunk, MPI_DOUBLE, root.who, root.comm);
+#endif	
+  }
+};
+
+// Fin Add J. Morice
+
+
+template<>
+struct Op_Gather3<Complex> : public   ternary_function<KN_<Complex>,KN_<Complex>,MPIrank,long> {
+    static long  f(Stack, KN_<Complex>  const  & s, KN_<Complex>  const  &r,  MPIrank const & root)  
+  { 
+      CheckContigueKN(r);
+      CheckContigueKN(s);
+
+      int mpisizew,myrank;
+      MPI_Comm_size(root.comm, &mpisizew); 
+      MPI_Comm_rank( root.comm, &myrank)  ;
+
+    int chunk = s.N();
+    // ffassert( (myrank != root.who) || (r.N()>=mpisizew*chunk) );
+#ifdef HAVE_MPI_DOUBLE_COMPLEX    
+       
+    return MPI_Gather( (void *) (Complex*)s, chunk, MPI_DOUBLE_COMPLEX,
+			   (void *) (Complex*)r, chunk, MPI_DOUBLE_COMPLEX,root.who,root.comm);	
+#else
+    chunk *= 2; 
+    return MPI_Gather( reinterpret_cast<void*> ( (Complex*) s), chunk, MPI_DOUBLE,
+		       reinterpret_cast<void*> ( (Complex*) r), chunk, MPI_DOUBLE,root.who,root.comm);
+#endif
+  }
+};
+
+
+template<>
+//struct Op_Gatherv3 : public penta_function<KN_<Complex>,KN_<Complex>, MPIrank, KN_<long>, KN_<long>, long> {
+long  Op_Gatherv3<Complex>(KN_<Complex>  const  & s, KN_<Complex>  const  &r,  MPIrank const & root, KN_<long> const & recvcount, KN_<long> const & displs)  
+{ 
+    CheckContigueKN(r);
+    CheckContigueKN(s);
+
+  int mpirankw;
+  MPI_Comm_rank(root.comm, &mpirankw); 
+  int mpisizew;
+  MPI_Comm_size(root.comm, &mpisizew); 
+  //ffassert((mpirankw != root.who) || ( recvcount.N() == displs.N() && recvcount.N() == mpisizew));
+  
+  if( mpirankw == root.who){
+    long sum=0;
+    for(int ii=0; ii< recvcount.N(); ii++)
+      sum+=recvcount[ii];
+    ffassert( sum == r.N() );
+  }
+  KN<int> INTrecvcount(recvcount.N());
+  KN<int> INTdispls(displs.N());
+#ifdef HAVE_MPI_DOUBLE_COMPLEX   
+  for(int ii=0; ii< recvcount.N(); ii++){
+    INTrecvcount[ii]= recvcount[ii];
+    INTdispls[ii]= displs[ii];
+  }
+  return MPI_Gatherv( (void *) (Complex*)s, s.N(), MPI_DOUBLE_COMPLEX,
+		      (void *) (Complex*)r, INTrecvcount, INTdispls,MPI_DOUBLE_COMPLEX,root.who,root.comm);
+#else
+  for(int ii=0; ii< recvcount.N(); ii++){
+    INTrecvcount[ii]= 2*recvcount[ii];
+    INTdispls[ii]= 2*displs[ii];
+  }
+  return MPI_Gatherv( reinterpret_cast<void*> ( (Complex*) s), 2*s.N(), MPI_DOUBLE,
+		      reinterpret_cast<void*> ( (Complex*) r), INTrecvcount, INTdispls,MPI_DOUBLE,root.who,root.comm);
+#endif
+}
+
+// Fin Add J. Morice communication entre complexe
+
+MPIrank mpiwho(long i) { return MPIrank(i);}
+MPIrank mpiwho(long i,fMPI_Comm comm) { return MPIrank(i,comm,Syncro_block);}
+MPIrank mpiwho(fMPI_Comm comm,long i) { return MPIrank(i,comm,Syncro_block);}
+MPIrank mpiwhob(long i) { return MPIrank(i);}
+MPIrank mpiwhob(long i,fMPI_Comm comm) { return MPIrank(i,comm,Syncro_block);}
+
+MPIrank mpiwho_(const long &i,const fMPI_Comm &comm,fMPI_Request * const &rq) { return MPIrank(i,comm,*rq);}
+MPIrank mpiwho_(const long &i,fMPI_Request * const &rq) { return MPIrank(i, MPI_COMM_WORLD ,*rq);}
+
+long mpiWait(fMPI_Request * frq) { 
+ MPI_Request * rq= *frq; 
+ MPI_Status status;
+ long res=MPI_SUCCESS;
+  while(rq && *rq!=MPI_REQUEST_NULL)
+    {
+      res = MPI_Wait(rq,&status); 
+      DoOnWaitMPIRequest(rq);
+    }
+    return res;  
+
+}
+
+long mpiBarrier(fMPI_Comm * comm) 
+{    
+  return MPI_Barrier(*comm);
+}
+
+
+
+long mpiWaitAny(KN<MPI_Request>* rq)
+{ 
+  MPI_Status status;
+  int index;
+  //cout << "mpiWaitAny " <<rq->N() << " in "  <<  endl ;
+  do {
+      MPI_Waitany(rq->N(),*rq,&index,&status);
+      DoOnWaitMPIRequest(&(*rq)[index]);
+  }  while( (MPI_UNDEFINED!= index) &&  ((*rq)[index]!=MPI_REQUEST_NULL));
+    
+  //cout << "mpiWaitAny " <<rq->N() << " out " << index <<  endl ;
+  return index;
+}
+
+MPIrank * set_copympi( MPIrank* const & a,const MPIrank & b){ *a=b;return a;}
+ 
+
+long mpiSize(fMPI_Comm  cmm) { 
+    int s=0;
+ //   fMPI_Comm_rank(MPI_COMM_WORLD, &s); /* local */ 
+    if(cmm !=  (MPI_Comm) MPI_COMM_NULL)
+    MPI_Comm_size(cmm, &s); /* local */ 
+    return s;
+}
+long mpiRank(fMPI_Comm  cmm) { 
+    int s=MPI_UNDEFINED;
+    if(cmm != (MPI_Comm)MPI_COMM_NULL)
+    MPI_Comm_rank(cmm, &s); /* local */ 
+ //   MPI_Comm_size(MPI_COMM_WORLD, &s); /* local */ 
+    return s;
+}
+
+AnyType InitializeGroup(Stack stack,const AnyType &x){
+    MPI_Group *g=*PGetAny<fMPI_Group>(x);
+    *g=MPI_GROUP_NULL;
+     MPI_Comm_group(MPI_COMM_WORLD, g);
+    return  g;
+}
+AnyType DeleteGroup(Stack stack,const AnyType &x){
+    MPI_Group *g=*PGetAny<fMPI_Group>(x);
+    if(g && (*g != MPI_GROUP_NULL))MPI_Group_free(g);
+    return  Nothing;
+}
+AnyType InitializeComm(Stack stack,const AnyType &x){
+    MPI_Comm *comm= *PGetAny<fMPI_Comm>(x);
+    *comm=MPI_COMM_NULL;
+    MPI_Comm_dup(MPI_COMM_WORLD, comm);
+    return  comm;
+}
+AnyType DeleteComm(Stack stack,const AnyType &x){
+    MPI_Comm *comm= *PGetAny<fMPI_Comm>(x);
+    if(comm && (*comm != MPI_COMM_NULL && *comm != MPI_COMM_WORLD))// add MPI_COMM_WORLD FH 11/2010 FH
+      MPI_Comm_free(comm);
+    return  Nothing;
+}
+AnyType InitializeRequest(Stack stack,const AnyType &x){
+    MPI_Request *comm=*PGetAny<fMPI_Request>(x);
+    *comm=MPI_REQUEST_NULL;
+    
+    return  comm;
+}
+AnyType DeleteRequest(Stack stack,const AnyType &x){
+    MPI_Request *comm=*PGetAny<fMPI_Request>(x);
+    if(comm && ( *comm!=MPI_REQUEST_NULL )) MPI_Request_free(comm);
+    return  Nothing;
+}
+//  Hack to Bypass a bug in freefem FH  ... 
+template<> 
+class ForEachType<MPI_Group>:  public basicForEachType{public:// correction july 2009..... FH  Hoooo....  (Il y a un bug DUR DUR FH  ...) 
+    ForEachType(Function1 iv=0,Function1 id=0,Function1 OOnReturn=0):basicForEachType(typeid(MPI_Group),sizeof(MPI_Group),0,0,iv,id,OOnReturn) { }
+};
+
+template<> 
+class ForEachType<fMPI_Comm>:  public basicForEachType{public:// coorection july 2009..... FH  Hoooo....  (Il y a un bug DUR DUR FH  ...) 
+    ForEachType(Function1 iv=0,Function1 id=0,Function1 OOnReturn=0):basicForEachType(typeid(fMPI_Comm),sizeof(fMPI_Comm),0,0,iv,id,OOnReturn) {}
+};
+
+template<> 
+class ForEachType<fMPI_Request>:  public basicForEachType{public:// correction july 2009..... FH  Hoooo....  (Il y a un bug DUR DUR FH  ...) 
+    ForEachType(Function1 iv=0,Function1 id=0,Function1 OOnReturn=0):basicForEachType(typeid(fMPI_Request),sizeof(fMPI_Request),0,0,iv,id,OOnReturn) {}
+};
+// end Hack  ... 
+
+
+fMPI_Group* def_group( fMPI_Group* const & a,fMPI_Comm * const &comm, KN_<long>  const & b)
+{
+  MPI_Group group;
+  MPI_Comm_group(*comm,& group); 
+  KN<int> ranks(b);
+  MPI_Group_incl(group, ranks.N(),(int *) ranks, *a);
+  MPI_Group_free(&group) ;
+  // ici def a .. 
+  //  ffassert(0); //   A AFAIRE  //  pour arete le programm 
+  return a;}
+
+fMPI_Group* def_group( fMPI_Group* const & a, KN_<long>  const & b)
+{
+    MPI_Group group;
+    MPI_Comm comm=MPI_COMM_WORLD;
+    MPI_Comm_group(comm,& group); 
+    KN<int> ranks(b);
+    MPI_Group_incl(group, ranks.N(),(int *) ranks, *a);
+    MPI_Group_free(&group) ;
+    // ici def a .. 
+    //  ffassert(0); //   A AFAIRE  //  pour arete le programm 
+return a;}
+
+fMPI_Group* def_group( fMPI_Group* const & a,fMPI_Comm * const &comm)
+{
+  MPI_Comm_group(*comm,*a); 
+  return a;}
+
+fMPI_Comm* def_comm( fMPI_Comm* const & a,fMPI_Group* const & g)
+{
+    int ok=MPI_Comm_create(MPI_COMM_WORLD,*g,*a); 
+    return a;
+}
+
+fMPI_Comm* def_comm( fMPI_Comm* const & a,fMPI_Comm* const & b,fMPI_Group* const & g)
+{
+    MPI_Comm_create(*b,*g,*a); 
+    return a;
+}
+
+fMPI_Group* def_group( fMPI_Group* const & a,fMPI_Group  * const & group,KN_<long>  const & b)
+{
+  
+  KN<int> ranks(b);
+  MPI_Group_incl(*group, ranks.N(), (int *) ranks, *a);
+  // ici def a .. 
+  //  ffassert(0); //   A AFAIRE  //  pour arete le programm 
+  return a;
+}
+
+struct Def_def_Commsplit  : public  quad_function<fMPI_Comm*,fMPI_Comm*,long,long, fMPI_Comm*> 
+{
+    static fMPI_Comm * f(Stack,fMPI_Comm* const & a,fMPI_Comm* const & comm,const long &color ,const long &key  )
+    {    
+	MPI_Comm_split(*comm,color, key, *a);
+	return a;
+    }
+};
+
+fMPI_Comm * mpiCommsplit(fMPI_Comm* const & a,const MPIrank &p1,const long &key  )
+{    
+    MPI_Comm_split(p1.comm, p1.who, key, *a);
+    return a;
+}
+
+
+
+
+struct Def_def_Intercommcreate  : public  quad_function<fMPI_Comm*,MPIrank,MPIrank,long, fMPI_Comm*> 
+{
+static fMPI_Comm * f(Stack,fMPI_Comm* const & a, MPIrank const & p1, MPIrank const & p2, long const & tag )
+{
+    int err;
+    err=MPI_Intercomm_create(p1.comm, p1.who, p2.comm,p2.who,tag, *a);     
+    return a;	
+}
+};
+
+fMPI_Comm * def_intercommmerge(fMPI_Comm* const & a,fMPI_Comm* const & b, const long & high)
+{
+    MPI_Intercomm_merge(*b, high, *a);
+    return a;
+}
+
+
+template<typename K,typename KK>
+AnyType ClearReturnpKK(Stack stack, const AnyType & a)
+{
+  // a ne faire que pour les variables local au return...
+  //  pour l'instant on copie pour fqire mqrche 
+  // a repense  FH  mqi 2009....
+    KK * m = GetAny<KK * >(a);
+    //   KN<K> *cm=new KN<K>(true, *m); bug quant KN est une variable global
+    // KN<K> *cm=new KN<K>( *m); // on duplique le tableau comme en C++  (dur dur ?????? FH)
+    m->increment();
+    Add2StackOfPtr2FreeRC(stack,m);
+    if(verbosity>400)
+	cout << "ClearReturnpKK:: increment + Add2StackOfPtr2FreeRC nb ref  " <<  -m->next  << endl;
+    return m;
+}
+
+template<typename K,typename KK,typename KK_>
+AnyType ClearReturnpKK_(Stack stack, const AnyType & a)
+{
+  // il faut faire un copie du tableau 
+  KK_ * m = GetAny<KK_ * >(a);
+  KK *cm=new KK(*m); 
+  
+  Add2StackOfPtr2Free(stack,cm);// detruire la copie 
+  if(verbosity>400)
+    cout << "ClearReturnpKK_:: copie  Add2StackOfPtr2Free "  << endl;
+  return (KK_ *) cm;
+}
+template<typename K,typename KK,typename KK_>
+AnyType ClearReturnKK_(Stack stack, const AnyType & a)
+{
+  // il faut faire un copie du tableau 
+  KK_  m = GetAny<KK_>(a);
+  KK *cm=new KK(m); 
+  
+  Add2StackOfPtr2Free(stack,cm);// detruire la copie 
+  if(verbosity>400)
+    cout << "ClearReturnKK_:: copie  Add2StackOfPtr2Free   "  << endl;
+    return SetAny<KK_>(*cm);
+}
+//template<class RR,class A,class B>  fMPI_Request*,KN<MPI_Request>*,long
+fMPI_Request * get_elementp_( KN<MPI_Request> * const & a,const long & b){ 
+  if( a==0 || b<0 || a->N() <= b) 
+    { cerr << " Out of bound  0 <=" << b << " < "  << a->N() << " KN<MPI_Request> * " << endl;
+      ExecError("Out of bound in operator []");}
+  return  reinterpret_cast<fMPI_Request *> (&((*a)[b]));}// bofBof ... 
+
+KN<MPI_Request> * set_init0( KN<MPI_Request> * const & a,const long & b)
+   { 
+     a->init(b);
+     for(int i=0;i<b;++i)
+       (*a)[i]=MPI_REQUEST_NULL;
+     return a;
+   }
+bool toBool(fMPI_Comm *comm)
+{
+  return (comm && (*comm != (MPI_Comm)MPI_COMM_NULL)); 
+}
+void * topVoid(fMPI_Comm *comm) {    return comm; }
+
+template<typename T>
+class Quad_Op : public E_F0 {
+  typedef typename T::result_type R;
+  typedef typename T::first_argument_type A;
+  typedef typename T::second_argument_type B;
+  typedef typename T::third_argument_type C;
+  typedef typename T::fourth_argument_type D;
+  
+  typedef  typename T::result_type Result;
+  Expression a,b,c,d;
+public:
+  AnyType operator()(Stack s)  const 
+  {return  SetAny<R>(static_cast<R>(T::f(s, GetAny<A>((*a)(s)) ,
+					 GetAny<B>((*b)(s)) ,
+					 GetAny<C>((*c)(s)),
+					   GetAny<D>((*d)(s))
+					 )));}
+  Quad_Op(Expression aa,Expression bb,Expression cc,Expression dd) : a(aa),b(bb),c(cc),d(dd) {} 
+  bool MeshIndependent() const {
+    return a->MeshIndependent() && b->MeshIndependent() && c->MeshIndependent()  && d->MeshIndependent();}
+};
+
+
+// Fin add J. Morice
+
+void f_end_parallele()
+{
+    /// FFCS: MPI_Finalize() needs to be called later than this (in
+    /// ffcs/src/server.cpp)
+    ffapi::mpi_finalize();
+    if(mpirank==0 || verbosity>2) cout << "FreeFem++-mpi finalize correctly .\n" << flush ;
+    else if(verbosity>5)  cout << '.' << endl ;
+}
+void f_initparallele(int &argc, char **& argv)
+{
+  /// FFCS: MPI_Init() needs to be called earlier (in ffcs/src/server.cpp)
+  ffapi::mpi_init(argc,argv);
+  
+  int mpirank1,mpisize1;
+  MPI_Comm_rank(MPI_COMM_WORLD, &mpirank1); /* local */ 
+  MPI_Comm_size(MPI_COMM_WORLD, &mpisize1); /* local */ 
+  
+  mpirank = mpirank1;//MPI::COMM_WORLD.Get_rank();
+  mpisize =mpisize1;// MPI::COMM_WORLD.Get_size();
+  if(verbosity> 2 || (mpirank ==0))
+  cout << "initparallele rank " <<  mpirank << " on " << mpisize << endl;
+  ff_atend(f_end_parallele); // set end MPI // 
+}
+
+double ffMPI_Wtime() {return MPI_Wtime();}
+double ffMPI_Wtick() {return MPI_Wtick();}
+
+void f_init_lgparallele()
+  {
+    if(verbosity && mpirank == 0) cout << "parallelempi ";
+    using namespace Fem2D;
+    Dcl_TypeandPtr<MPIrank>(0);
+    
+    Dcl_TypeandPtr<fMPI_Group>(0,0,InitializeGroup,DeleteGroup); 
+    Dcl_TypeandPtr<fMPI_Comm>(0,0,InitializeComm,DeleteComm);  
+    Dcl_Type<fMPI_Op>(); 
+    Dcl_TypeandPtr<fMPI_Request>(0,0,InitializeRequest,DeleteRequest); // bof bof ... 
+    Dcl_TypeandPtr_<KN_<MPI_Request> ,KN<MPI_Request>*  > 
+      (0,0,0,::Destroy<KN<MPI_Request> >,
+       ::ClearReturnKK_<MPI_Request,KN<MPI_Request>,KN_<MPI_Request> >,
+       ::ClearReturnpKK<MPI_Request,KN<MPI_Request> >);
+      
+    zzzfff->Add("mpiGroup",atype<fMPI_Group*>());
+    zzzfff->Add("mpiComm",atype<fMPI_Comm*>());
+    zzzfff->Add("mpiRequest",atype<fMPI_Request*>());
+    
+    map_type_of_map[make_pair(atype<long>(),atype<fMPI_Request>())]=atype<KN<MPI_Request>*>(); // vector
+    
+    
+    map_type[typeid(MPIrank).name()]->AddCast(new E_F1_funcT<MPIrank,MPIrank*>(UnRef<MPIrank>));
+    map_type[typeid(fMPI_Group).name()]->AddCast(new E_F1_funcT<fMPI_Group,fMPI_Group*>(UnRef<fMPI_Group>));
+    map_type[typeid(fMPI_Comm).name()]->AddCast(new E_F1_funcT<fMPI_Comm,fMPI_Comm*>(UnRef<fMPI_Comm>));
+    map_type[typeid(bool).name()]->AddCast(new OneOperator1<bool,fMPI_Comm*>(toBool));
+    map_type[typeid(void*).name()]->AddCast(new OneOperator1<void *,fMPI_Comm*>(topVoid));
+      
+      
+    TheOperators->Add("<-", 
+		      new OneOperator2_<MPIrank*,MPIrank*,MPIrank>(&set_copympi));
+    
+    // constructor example ... 
+    TheOperators->Add("<-", 
+		      new OneOperator2_<fMPI_Group*,fMPI_Group*,KN_<long> >(&def_group),
+		      new OneOperator3_<fMPI_Group*,fMPI_Group*,fMPI_Group*,KN_<long> >(&def_group),
+		      new OneOperator3_<fMPI_Group*,fMPI_Group*,fMPI_Comm*,KN_<long> >(&def_group),
+		      new OneOperator2_<fMPI_Group*,fMPI_Group*,fMPI_Comm*>(&def_group));
+      
+      
+       /*
+       fMPI_Comm * mpiCommsplit(fMPI_Comm* const & a,const MPIrank &p1,const long &rk  )
+       fMPI_Comm * def_intercommmerge(fMPI_Comm* const & a,fMPI_Comm* const & b, const long & high)
+	fMPI_Comm * def_Intercommcreate(fMPI_Comm* const & a, MPIrank const & p1, MPIrank const & p2, long const & tag )
+	 quad_function<fMPI_Comm*,MPIrank,MPIrank,long, fMPI_Comm* >
+       
+       */
+      TheOperators->Add("<-", 
+			new OneOperator2_<fMPI_Comm*,fMPI_Comm*,fMPI_Group* >(&def_comm),
+			new OneOperator3_<fMPI_Comm*,fMPI_Comm*,fMPI_Comm*,fMPI_Group* >(&def_comm),
+			new OneOperator3_<fMPI_Comm*,fMPI_Comm*,MPIrank,long >(&mpiCommsplit),
+			new OneOperator3_<fMPI_Comm*,fMPI_Comm*,fMPI_Comm*,long >(&def_intercommmerge),
+			new OneQuadOperator< Def_def_Intercommcreate, Quad_Op<Def_def_Intercommcreate>  >,
+			new OneQuadOperator< Def_def_Commsplit, Quad_Op<Def_def_Commsplit>  >
+			
+			); 
+      
+    /*  code edp
+	int[int] procs=[1,2,3];
+	mpiGroup toto(procs);
+	mpiComm comm(toto);
+	
+    */
+      
+    
+    Global.Add("processor","(",new OneOperator1<MPIrank,long>(mpiwho));
+    Global.Add("processor","(",new OneOperator2<MPIrank,long,fMPI_Comm>(mpiwho));
+      Global.Add("processor","(",new OneOperator2<MPIrank,fMPI_Comm,long>(mpiwho));
+   
+    Global.Add("processorblock","(",new OneOperator1<MPIrank,long>(mpiwhob));
+    Global.Add("processorblock","(",new OneOperator2<MPIrank,long,fMPI_Comm>(mpiwhob));
+    
+    TheOperators->Add(">>",
+		      new OneBinaryOperator<Op_Readmpi<double> >,
+		      new OneBinaryOperator<Op_Readmpi<Complex> >,
+		      new OneBinaryOperator<Op_Readmpi<long> > ,
+		      new OneBinaryOperator<Op_Readmpi<KN<double> > > ,
+		      new OneBinaryOperator<Op_Readmpi<KN<long> > > ,
+		       new OneBinaryOperator<Op_Readmpi<KN<Complex> > > ,
+		      new OneBinaryOperator<Op_Readmpi<Mesh *> > ,
+		      new OneBinaryOperator<Op_Readmpi<Mesh3 *> > ,
+		      new OneBinaryOperator<Op_Readmpi<Matrice_Creuse<R> > > ,
+		      new OneBinaryOperator<Op_Readmpi<Matrice_Creuse<Complex> > > 
+		      );
+    
+     TheOperators->Add("<<",
+		       new OneBinaryOperator<Op_Writempi<double> >,
+		       new OneBinaryOperator<Op_Writempi<Complex> >,
+		       new OneBinaryOperator<Op_Writempi<long> > ,
+		       new OneBinaryOperator<Op_Writempi<KN<double> * > > ,
+		       new OneBinaryOperator<Op_Writempi<KN<long> * > > ,
+		       new OneBinaryOperator<Op_Writempi<KN<Complex> * > > ,
+		       new OneBinaryOperator<Op_Writempi<Mesh *> > ,
+		       new OneBinaryOperator<Op_Writempi<Mesh3 *> > ,
+		       new OneBinaryOperator<Op_Writempi<Matrice_Creuse<R> * > > ,
+		       new OneBinaryOperator<Op_Writempi<Matrice_Creuse<Complex>* > > 
+		       
+		       );
+     
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<double> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<long> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<Complex> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<KN<double> *> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<KN<long> *> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<KN<Complex> *> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<Mesh *> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<Mesh3 *> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<Matrice_Creuse<R> *> >);
+     Global.Add("Send","(", new OneBinaryOperator<Op_Sendmpi<Matrice_Creuse<Complex> *> >);
+     
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<double> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<long> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<Complex> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<KN<double> *> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<KN<long> *> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<KN<Complex> *> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<Mesh *> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<Mesh3 *> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<Matrice_Creuse<R> *> >);
+     Global.Add("Isend","(", new OneBinaryOperator<Op_ISendmpi<Matrice_Creuse<Complex> *> >);
+     
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<double> >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<long> >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<Complex> >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<KN<double> > >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<KN<long> > >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<KN<Complex> > >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<Mesh *> >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<Mesh3 *> >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<Matrice_Creuse<R> > >);
+      Global.Add("Recv","(", new OneBinaryOperator<Op_Recvmpi<Matrice_Creuse<Complex> > >);
+      
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<double> >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<long> >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<Complex> >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<KN<double> > >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<KN<long> > >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<KN<Complex> > >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<Mesh *> >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<Mesh3 *> >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<Matrice_Creuse<R> > >);
+      Global.Add("Irecv","(", new OneBinaryOperator<Op_IRecvmpi<Matrice_Creuse<Complex> > >);
+      
+    
+      
+      
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<double> >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<Complex> >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<long> >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<KN<double> > >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<KN<long> > >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<KN<Complex> > >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<Mesh *> >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<Mesh3 *> >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<Matrice_Creuse<R> > >);
+      Global.Add("broadcast","(",new OneBinaryOperator<Op_Bcastmpi<Matrice_Creuse<Complex> > >);
+      
+      Global.Add("mpiAlltoall","(",new OneBinaryOperator<Op_All2All< long > >);
+      Global.Add("mpiAlltoall","(",new OneBinaryOperator<Op_All2All< double > >);
+      Global.Add("mpiAllgather","(",new OneBinaryOperator<Op_Allgather< long > >);
+      Global.Add("mpiAllgather","(",new OneBinaryOperator<Op_Allgather< double > >);
+      Global.Add("mpiAlltoall","(",new OneTernaryOperator3<Op_All2All3< long > >);
+      Global.Add("mpiAlltoall","(",new OneTernaryOperator3<Op_All2All3< double > >);
+      Global.Add("mpiAllgather","(",new OneTernaryOperator3<Op_Allgather3< long > >);
+      Global.Add("mpiAllgather","(",new OneTernaryOperator3<Op_Allgather3< double > >);
+      
+      Global.Add("mpiAllgather","(",new OneBinaryOperator<Op_Allgather1< long > >);   // Add J. Morice
+      Global.Add("mpiAllgather","(",new OneBinaryOperator<Op_Allgather1< double > >); // Add J. Morice
+
+      Global.Add("mpiAllgather","(",new OneTernaryOperator3<Op_Allgather13< long > >);  // Add J. Morice
+      Global.Add("mpiAllgather","(",new OneTernaryOperator3<Op_Allgather13< double > >);// Add J. Morice
+      
+      Global.Add("mpiScatter","(",new OneTernaryOperator3<Op_Scatter1< long > >);    // Add J. Morice
+      Global.Add("mpiScatter","(",new OneTernaryOperator3<Op_Scatter1< double > >);  // Add J. Morice
+      Global.Add("mpiScatter","(",new OneTernaryOperator3<Op_Scatter3< long > >);
+      Global.Add("mpiScatter","(",new OneTernaryOperator3<Op_Scatter3< double > >);
+
+      Global.Add("mpiGather","(",new OneTernaryOperator3<Op_Gather1< long > >);   // Add J. Morice
+      Global.Add("mpiGather","(",new OneTernaryOperator3<Op_Gather1< double > >); // Add J. Morice
+      Global.Add("mpiGather","(",new OneTernaryOperator3<Op_Gather3< long > >); // correction J. Morice Scatter --> Gather
+      Global.Add("mpiGather","(",new OneTernaryOperator3<Op_Gather3< double > >);
+      
+      // Add J. Morice communication with vector of different size    
+      Global.Add("mpiAlltoallv","(",new OneOperator6_<long, KN_<double>, KN_<double>, KN_<long>, KN_<long>, KN_<long>, KN_<long> >( Op_All2Allv<double> ) );
+      Global.Add("mpiAlltoallv","(",new OneOperator6_<long, KN_<long>, KN_<long>, KN_<long>, KN_<long>, KN_<long>, KN_<long> >( Op_All2Allv<long> ) );
+      
+      Global.Add("mpiAlltoallv","(",new OneOperator7_<long, KN_<long>, KN_<long>, fMPI_Comm, KN_<long>, KN_<long>, KN_<long>, KN_<long> >( Op_All2All3v<long> ) ); 
+      Global.Add("mpiAlltoallv","(",new OneOperator7_<long, KN_<double>, KN_<double>, fMPI_Comm, KN_<long>, KN_<long>, KN_<long>, KN_<long> >( Op_All2All3v<double> ) ); 
+
+      Global.Add("mpiAllgatherv","(",new OneQuadOperator<Op_Allgatherv< long >, Quad_Op<Op_Allgatherv< long > > > );
+      Global.Add("mpiAllgatherv","(",new OneQuadOperator<Op_Allgatherv< double >, Quad_Op<Op_Allgatherv< double > > >);
+      Global.Add("mpiAllgatherv","(",new OneOperator5_<long, KN_<long>, KN_<long>, fMPI_Comm, KN_<long>, KN_<long> >(Op_Allgatherv3< long >) );
+      Global.Add("mpiAllgatherv","(",new OneOperator5_<long, KN_<double>, KN_<double>, fMPI_Comm, KN_<long>, KN_<long> >(Op_Allgatherv3< double >) );
+
+      Global.Add("mpiScatterv","(",new OneOperator5_<long, KN_<long>, KN_<long>, MPIrank, KN_<long>, KN_<long> >(Op_Scatterv3< long >) );
+      Global.Add("mpiScatterv","(",new OneOperator5_<long, KN_<double>, KN_<double>, MPIrank, KN_<long>, KN_<long> >(Op_Scatterv3< double >) );
+
+      Global.Add("mpiGatherv","(",new OneOperator5_<long, KN_<long>, KN_<long>, MPIrank, KN_<long>, KN_<long> >( Op_Gatherv3< long > ) );
+      Global.Add("mpiGatherv","(",new OneOperator5_<long, KN_<double>, KN_<double>, MPIrank, KN_<long>, KN_<long> >( Op_Gatherv3< double > ) );
+      // Fin Add J. Morice
+
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_Reduce< double >, Quad_Op<Op_Reduce< double > > >);
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_Reduce1< double >, Quad_Op<Op_Reduce1< double > > >);
+      Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduce< double >, Quad_Op<Op_AllReduce< double > > >);
+      Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduce1< double >, Quad_Op<Op_AllReduce1< double > > >); // add FH jan 2011 
+      //    Global.Add("mpiReduceScatter","(",new OneQuadOperator<Op_Reducescatter< double >, Quad_Op<Op_Reducescatter< double > > >);
+
+      // Add J. Morice
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_Reduce< long >, Quad_Op<Op_Reduce< long > > >);
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_Reduce1< long >, Quad_Op<Op_Reduce1< long > > >);
+      Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduce< long >, Quad_Op<Op_AllReduce< long > > >);
+      Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduce1< long >, Quad_Op<Op_AllReduce1< long > > >); // add FH jan 2011 
+      //    Global.Add("mpiReduceScatter","(",new OneQuadOperator<Op_Reducescatter< long >, Quad_Op<Op_Reducescatter< long > > >);
+      // fin Add J. Morice
+
+      // Add J. Morice :: complex communication between processor 
+      Global.Add("mpiAlltoall","(",new OneBinaryOperator<Op_All2All< Complex > >);
+      Global.Add("mpiAllgather","(",new OneBinaryOperator<Op_Allgather< Complex > >);    
+      Global.Add("mpiAlltoall","(",new OneTernaryOperator3<Op_All2All3< Complex > >);     
+      Global.Add("mpiAllgather","(",new OneTernaryOperator3<Op_Allgather3< Complex > >);
+        
+      Global.Add("mpiAllgather","(",new OneBinaryOperator<Op_Allgather1< Complex > >);
+      Global.Add("mpiAllgather","(",new OneTernaryOperator3<Op_Allgather13< Complex > >);
+
+      Global.Add("mpiScatter","(",new OneTernaryOperator3<Op_Scatter3< Complex > >);
+      Global.Add("mpiGather","(",new OneTernaryOperator3<Op_Gather3< Complex > >);
+
+      Global.Add("mpiScatter","(",new OneTernaryOperator3<Op_Scatter1< Complex > >);
+      Global.Add("mpiGather","(",new OneTernaryOperator3<Op_Gather1< Complex > >);
+      
+      // Add J. Morice communication with vector of different size    
+      Global.Add("mpiAlltoallv","(",new OneOperator6_<long, KN_<Complex>, KN_<Complex>, KN_<long>, KN_<long>, KN_<long>, KN_<long> >( Op_All2Allv<Complex> ) );   
+      Global.Add("mpiAlltoallv","(",new OneOperator7_<long, KN_<Complex>, KN_<Complex>, fMPI_Comm, KN_<long>, KN_<long>, KN_<long>, KN_<long> >( Op_All2All3v<Complex> ) ); 
+      Global.Add("mpiAllgatherv","(",new OneQuadOperator<Op_Allgatherv< Complex>, Quad_Op<Op_Allgatherv< Complex > > >);
+   
+      Global.Add("mpiAllgatherv","(",new OneOperator5_<long, KN_<Complex>, KN_<Complex>, fMPI_Comm, KN_<long>, KN_<long> >(Op_Allgatherv3< Complex >) );
+      Global.Add("mpiScatterv","(",new OneOperator5_<long, KN_<Complex>, KN_<Complex>, MPIrank, KN_<long>, KN_<long> >(Op_Scatterv3< Complex >) );
+      Global.Add("mpiGatherv","(",new OneOperator5_<long, KN_<Complex>, KN_<Complex>, MPIrank, KN_<long>, KN_<long> >( Op_Gatherv3< Complex > ) );
+     
+   
+    
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_ReduceMat< Complex >, Quad_Op<Op_ReduceMat< Complex > > >);// add FH april 2011
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_ReduceMat< double >, Quad_Op<Op_ReduceMat< double > > >);// add FH april 2011
+      Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduceMat< Complex >, Quad_Op<Op_AllReduceMat< Complex > > >);// add FH april 2011
+      Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduceMat< double >, Quad_Op<Op_AllReduceMat< double > > >);// add FH april 2011
+    
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_Reduce< Complex >, Quad_Op<Op_Reduce< Complex > > >);
+      Global.Add("mpiReduce","(",new OneQuadOperator<Op_Reduce1< Complex >, Quad_Op<Op_Reduce1< Complex > > >);
+      Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduce< Complex >, Quad_Op<Op_AllReduce< Complex > > >);
+#ifdef HAVE_MPI_DOUBLE_COMPLEX
+    Global.Add("mpiAllReduce","(",new OneQuadOperator<Op_AllReduce1< Complex >, Quad_Op<Op_AllReduce1< Complex > > >);// add FH jan 2011 
+#endif
+      // Fin Add J. Morice :: complex communication between processor 
+      
+      Global.New("mpirank",CConstant<long>(mpirank));
+      Global.New("mpisize",CConstant<long>(mpisize));
+     static long mpiUndefined=MPI_UNDEFINED, mpiAnySource =  MPI_ANY_SOURCE,mpiAnyTag=MPI_ANY_TAG ;
+     static fMPI_Comm fmpiWorld=MPI_COMM_WORLD;
+     
+     Global.New("mpiUndefined",CConstant<long>(mpiUndefined));
+     Global.New("mpiAnySource",CConstant<long>(mpiAnySource));
+      Global.New("mpiAnyTag",CConstant<long>(mpiAnyTag));
+      
+      
+      
+      Global.New("mpiCommWorld",CConstant<fMPI_Comm*>(&fmpiWorld));   
+      // add FH 
+      
+      
+     Global.Add("mpiWtime","(",new OneOperator0<double>(ffMPI_Wtime));    
+     Global.Add("mpiWtick","(",new OneOperator0<double>(ffMPI_Wtick));    
+     Global.Add("processor","(",new OneOperator3_<MPIrank,long,fMPI_Comm,fMPI_Request*>(mpiwho_));
+     Global.Add("processor","(",new OneOperator2_<MPIrank,long,fMPI_Request*>(mpiwho_));
+     Global.Add("mpiWait","(",new OneOperator1<long,fMPI_Request*>(mpiWait));
+     Global.Add("mpiWaitAny","(",new OneOperator1<long,KN<MPI_Request>*>(mpiWaitAny));
+     Global.Add("mpiSize","(",new OneOperator1<long,fMPI_Comm>(mpiSize)); 
+     Global.Add("mpiRank","(",new OneOperator1<long,fMPI_Comm>(mpiRank)); 
+      Global.Add("mpiBarrier","(",new OneOperator1<long,fMPI_Comm*>(mpiBarrier)); 
+      
+      static   fMPI_Op op_max(MPI_MAX);
+      static   fMPI_Op op_min(MPI_MIN);
+      static   fMPI_Op op_sum(MPI_SUM);
+      static   fMPI_Op op_prod(MPI_PROD);
+      static   fMPI_Op op_land(MPI_LAND);
+      
+      static   fMPI_Op op_lor(MPI_LOR);
+      static   fMPI_Op op_lxor(MPI_LXOR);
+      static   fMPI_Op op_band(MPI_BAND);
+      static   fMPI_Op op_bor(MPI_BOR);
+      static   fMPI_Op op_bxor(MPI_BXOR);
+      static   fMPI_Op op_maxloc(MPI_MAXLOC);
+      static   fMPI_Op op_minloc(MPI_MINLOC);
+      
+      Global.New("mpiMAX",CConstant<fMPI_Op>(op_max));
+      Global.New("mpiMIN",CConstant<fMPI_Op>(op_min));
+      Global.New("mpiSUM",CConstant<fMPI_Op>(op_sum));
+      Global.New("mpiPROD",CConstant<fMPI_Op>(op_prod));
+      Global.New("mpiLAND",CConstant<fMPI_Op>(op_land));
+      
+      Global.New("mpiLOR",CConstant<fMPI_Op>(op_lor));
+      Global.New("mpiLXOR",CConstant<fMPI_Op>(op_lxor));
+      Global.New("mpiBAND",CConstant<fMPI_Op>(op_band));
+      Global.New("mpiBXOR",CConstant<fMPI_Op>(op_bxor));
+      //  sur des pair bof bof ...
+      Global.New("mpiMAXLOC",CConstant<fMPI_Op>(op_maxloc));
+      Global.New("mpiMINLOC",CConstant<fMPI_Op>(op_minloc));
+      
+      
+      TheOperators->Add("<-", 
+			new OneOperator2_<KN<MPI_Request> *,KN<MPI_Request> *,long>(&set_init0)
+			);
+      atype<KN<MPI_Request>* >()->Add("[","",new OneOperator2_<fMPI_Request*,KN<MPI_Request>*,long >(get_elementp_));    
+      
+  }
+
+
+// set the 3 ptr 
+extern void (*initparallele)(int &argc, char **& argv) ;
+extern void (*init_lgparallele)();
+//extern void (*end_parallele)();
+
+
+void init_ptr_parallelepmi();
+void init_ptr_parallelepmi(){
+initparallele=&f_initparallele ;
+init_lgparallele=&f_init_lgparallele;
+//end_parallele=&f_end_parallele;
+};
diff --git a/src/nw/Makefile.am b/src/nw/Makefile.am
new file mode 100644
index 0000000..b95021a
--- /dev/null
+++ b/src/nw/Makefile.am
@@ -0,0 +1,25 @@
+# Makefile using Automake + Autoconf
+# ----------------------------------
+# $Id$
+
+# To create statically linked executables (see configure.ac)
+CXXLD=$(STATICTOOL) $(CXX)
+bin_PROGRAMS=FreeFem++ FreeFem++-nw @FFGLUTPROG@
+EXTRA_PROGRAMS=ffglut
+
+# FFCS:visualization stream redirection
+ffglut_SOURCES=../Graphics/ffglut.cpp ../Graphics/gggg.cpp ../Graphics/ffthreads.cpp \
+../Graphics/ffthreads.hpp \
+../femlib/fem.cpp ../femlib/Mesh3dn.cpp ../femlib/Mesh2dn.cpp  ../femlib/Mesh1dn.cpp ../femlib/GQuadTree.cpp  ../femlib/FQuadTree.cpp \
+../femlib/Drawing.cpp ../femlib/mshptg.cpp ../fflib/ffapi.cpp
+
+ffglut_DEPENDENCIES= ../libMesh/libMesh.a
+ffglut_LDADD= ../libMesh/libMesh.a @LIBSGLUT@ @LIBSPTHREAD@ 
+FreeFem___nw_SOURCES=../Graphics/sansrgraph.cpp ../mpi/parallelempi-empty.cpp ../fflib/ffapi.cpp
+FreeFem___SOURCES=../Graphics/sansrgraph.cpp  ../mpi/parallelempi-empty.cpp ../fflib/ffapi.cpp
+
+FreeFem___nw_DEPENDENCIES=../fflib/libff.a ../lglib/liblg.a
+FreeFem___DEPENDENCIES=../fflib/libff.a ../lglib/liblg.a
+
+LDADD=../lglib/liblg.a ../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLASLIBS@
+AM_CPPFLAGS=-I$(srcdir)/../fflib -I$(srcdir)/../Graphics -I$(srcdir)/../.. -I$(srcdir)/../femlib 
diff --git a/src/solver/MUMPS_FreeFem.cpp b/src/solver/MUMPS_FreeFem.cpp
new file mode 100644
index 0000000..22c9b61
--- /dev/null
+++ b/src/solver/MUMPS_FreeFem.cpp
@@ -0,0 +1,2571 @@
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+//ff-c++-LIBRARY-dep: metis mumps  blas 
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mpi.h"
+#include "dmumps_c.h"
+#include "zmumps_c.h"
+
+// read options for MUMPS in freefem++
+int s_(char* str, const char* cmp[])
+{
+  int i = 0;
+  while( cmp[i] != 0){
+    if( strcmp(str, cmp[i]) == 0){
+      //cout << *str << " return" << i << endl;
+      return i+1 ;
+    }
+    i++;
+  }
+  //cout << *str << " return 0" << endl;
+  return 0;
+}
+
+void read_options_freefem(string *string_option, int *SYM, int *PAR){
+  
+  static const char* comp[] = {"SYM", "PAR", 0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  cout << "data=" << data << endl;
+  char * tictac;
+  tictac = strtok(data," =,\t\n");
+  cout << "tictac=" << data << endl;
+
+  while(tictac != NULL){
+    
+    int id_option = s_(tictac, comp);
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 1 : // SYM
+	*SYM = atoi(tictac);
+	// strtol ???
+	if(*SYM != 0 && *SYM !=1) 
+	  cout << "SYM must be equal to 1 or 0 for MUMPS" << endl;
+	
+	break;
+      case 2:  // PAR
+	*PAR = atoi(tictac);
+	if(*PAR != 0 && *PAR !=1) 
+	  cout << "PAR must be equal to 1 or 0" << endl;
+	//strtol ???
+	break;
+      case 0: // Equivalent of case default
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+  
+}
+
+class dSolveMUMPSmpi :   public MatriceMorse<double>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  mutable MPI_Comm comm;
+  double            *a;
+  int       *irn, *jcn;
+  int          n, m, nz; 
+ 
+  // parameter MUMPS
+  
+  KN_<long>        perm_r; /* row permutations from partial pivoting */
+  KN_<long>        perm_c;
+  KN_<double>     scale_r;
+  KN_<double>     scale_c;
+  string string_option;
+  string data_option;
+  int SYM;
+  int PAR;
+  int myid;
+
+  // distribuer
+  int nz_loc;
+  int *jcn_loc, *irn_loc;
+  double *a_loc;
+  
+
+
+  static const int JOB_INIT=-1;
+  static const int JOB_END=-2;
+  static const int USE_COMM_WORLD= -987654;
+
+  // variable reel
+  mutable DMUMPS_STRUC_C id;
+  
+#define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */
+#define CNTL(I) cntl[(I)-1] /* macro s.t. indices match documentation */
+#define RINFOG(I) rinfog[(I)-1] /* macro s.t. indices match documentation */
+#define INFOG(I) infog[(I)-1] /* macro s.t. indices match documentation */
+public:
+  dSolveMUMPSmpi(const MatriceMorse<double> &AA,int strategy,double ttgv, double epsilon,
+		 double pivot,double pivot_sym, string param_string, string datafile, KN<long> &param_int, 
+		 KN<double> &param_double, KN<long> &pperm_r, KN<long> &pperm_c, KN<double> &pscale_r,KN<double> &pscale_c, MPI_Comm  * mpicommw
+		) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv), string_option(param_string), data_option(datafile), perm_r(pperm_r), perm_c(pperm_c), 
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot), scale_r(pscale_r), scale_c(pscale_c)
+  { 
+    long int starttime,finishtime;
+    long int timeused;
+
+    if(verbosity) starttime = clock();
+    int dataint[40];
+    double datadouble[15];
+    int ierr;
+
+     if(mpicommw==0){
+	comm=MPI_COMM_WORLD;
+	}
+	else
+	comm= *mpicommw;
+
+
+    /* ------------------------------------------------------------
+       INITIALIZE THE MUMPS PROCESS GRID. 
+       ------------------------------------------------------------*/
+    ierr = MPI_Comm_rank(comm, &myid);
+    
+    if( myid ==0){
+      n    = AA.n;
+      m    = AA.m; 
+      nz   = AA.nbcoef;
+    
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+    else{
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+    
+    if( !(param_int==NULL) ) 
+      assert( param_int.N() == 42);
+    if( !(param_double==NULL) ) 
+      assert( param_double.N() == 15);
+    if(perm_r)
+      assert( perm_r.N() == n);
+    if(perm_c)
+      assert( perm_c.N() == m);
+    if(scale_r) 
+      assert( scale_r.N() == n);
+    if(scale_c) 
+      assert( scale_c.N() == m);
+
+    if( n != m )
+      cerr << "only square matrix are supported by MUMPS" << endl;
+   
+  
+    // initialisation par defaut
+    SYM=0; PAR=1;
+    
+    /*
+      if(!string_option.empty()) 
+      {
+      if(myid==0){
+      cout << "read string option" <<endl;
+      read_options_freefem(&string_option,&SYM,&PAR);
+      
+      MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+      }
+      else{
+      MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+      }
+      }
+    */
+    if( !(param_int==NULL) ){
+      SYM = param_int[0];
+      PAR = param_int[1];
+      cout << "param :: myid =" << myid << endl;
+    }
+    else if( !data_option.empty() )
+      {	
+	cout << "myid =" << myid << endl;
+	if(myid==0){
+	  
+	  char * retfile= new char[data_option.size()+1];
+	  strcpy(retfile, (&data_option)->c_str());
+	  printf("read data option file %s\n",retfile);
+	  FILE *pFile=fopen(retfile,"rt");
+	
+	  int     i_data=0;
+	  int     d_data=0;
+	  char    data[256];
+	  char   *tictac;
+	  
+	  fgets(data,256,pFile);
+	  tictac = strtok(data," /!#\t\n");
+	  SYM = atoi(tictac);
+	  
+	  fgets(data,256,pFile);
+	  tictac = strtok(data," /!#\t\n");
+	  PAR = atoi(tictac);
+	  
+	  while( !feof(pFile) && i_data < 40){
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    dataint[i_data] = (int)atol(tictac);
+	    i_data++;
+	  }  
+	  assert(i_data == 40);
+	  while( !feof(pFile) && d_data < 15){
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    datadouble[d_data] = (double)atof(tictac);
+	    d_data++;
+	  }  
+	  assert(d_data == 15);
+	  /*
+	    for(int ii=0; ii< 40; ii++){
+	    cout << "double int["<< ii <<"] ="<< dataint[ii] << endl;
+	    }  
+	    for(int ii=0; ii< 15; ii++){
+	    cout << "double data["<< ii <<"] ="<< datadouble[ii] << endl;
+	    }  
+	  */
+	  MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	  MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+
+	  cout << "myid =" << myid << " init parameter :: PAR & SYM " << PAR << " " << SYM << endl; 
+
+	  MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	  MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+
+
+	  fclose(pFile);
+	  delete [] retfile;
+	}
+	else{
+	  
+
+	  MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	  MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+	  
+	  cout << "myid =" << myid << "  init parameter :: PAR & SYM " << PAR << " " << SYM << endl; 
+
+
+	  MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	  MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+	}
+      }
+    
+  
+    /* Initialize a MUMPS instance. Use comm */
+    id.job=JOB_INIT; 
+    id.par=PAR; 
+    id.sym=SYM;
+    id.comm_fortran= (MUMPS_INT) MPI_Comm_c2f( comm );
+    //id.comm_fortran= (F_INT) comm;
+
+    if(verbosity) cout << "init parameter :: PAR & SYM " << PAR << " " << SYM << endl; 
+
+    dmumps_c(&id);
+
+    if(verbosity) cout << "fin init parameter" << endl; 
+
+    /* set parameter of mumps */
+    if( !(param_int == NULL) || !(param_double == NULL) ){
+      if(!data_option.empty()){ 
+	printf("MUMPS ERROR:  parameters are given on the file %s and in the array lparams and dparams => double definition of parameters.",data_option.c_str());
+	exit(1);
+      }
+      
+      if( !(param_int == NULL) ){
+	cout << "internal parameter" << endl;
+	for(int ii=0; ii<40; ii++)	  
+	  id.ICNTL(ii+1) = param_int[ii+2];
+      }
+      else{
+
+	// parameter by default
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+      }
+      if( !(param_double == NULL) ){
+	cout << "internal parameter" << endl;
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = param_double[ii];
+      }
+    }    
+    else 
+      if(!data_option.empty()){
+	for(int ii=0; ii<40; ii++)
+	  id.ICNTL(ii+1) = dataint[ii];
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = datadouble[ii];
+      }
+      else{
+	// parameter by default
+	cout << "default parameter" << endl;
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+    }
+
+    // uniquement donner au host 
+    if(myid==0){
+      if( !(perm_r==NULL) && id.ICNTL(7)==1){
+	for(int ii=0; ii<n; ii++) id.perm_in[ii] = pperm_r[ii];
+      }
+      // a decommenter
+      //if( !(perm_c==NULL) && id.ICNTL(6)==1){
+      //for(int ii=0; ii<m; ii++) id.perm_in[ii] = pperm_c[ii];
+      //}
+      if( !(scale_r==NULL) && !(scale_c==NULL) && id.ICNTL(8)==-1 ){
+	// param_double[0::n-1] :: row  
+	// param_double[n::n+m-1] :: column 
+	for(int ii=0; ii<n; ii++) id.rowsca[ii] = scale_r[ii]; 
+	for(int ii=0; ii<m; ii++) id.colsca[ii] = scale_c[ii];
+      }
+    }
+
+    irn = NULL;
+    jcn = NULL;
+
+    /* valeur par defaut mis dans le dur */      
+    //id.ICNTL(5)  = 0;  
+    //id.ICNTL(18) = 0;
+    
+    // Distribution depend de la valeur de ICNTL(18)
+    if( id.ICNTL(5) != 0 ){
+      printf("we consider only assembled format \n");
+      printf("forced assembled format ==> id.ICNTL(5)  = 0;  \n");
+      id.ICNTL(5)  = 0;  
+      exit(1);
+    }
+
+    if (myid == 0) {
+      id.n = n; id.nz =nz; 
+      //id.irn=irn; id.jcn=jcn;
+      //id.a = a; //id.rhs = rhs;
+    }
+
+    if( id.ICNTL(18) == 0)
+      {
+        
+	// CASE:: NON DISTRIBUTED MATRIX
+	if (myid == 0) { // nouveau
+
+	  a=AA.a;
+	  // ATTENTION 
+	  // AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	  // index of row and colummn by 1
+	  jcn = AA.cl;
+	  for(int ii=0; ii<nz; ii++)
+	    jcn[ii] = jcn[ii]+1;
+	  
+	  if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	    printf("problem allocation jcn ");
+	    exit(1);
+	  }
+	
+	  assert(AA.lg[n] == nz);
+	  for(int ii=0; ii< n; ii++)
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	      irn[ii1] = ii+1;  
+		
+	  // if (myid == 0) {   // ancien
+	  id.irn=irn; id.jcn=jcn;
+	  id.a = a; //id.rhs = rhs;
+	}
+
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation 
+	id.job=4;
+	dmumps_c(&id);
+	
+      }
+
+
+    if( id.ICNTL(18) == 1 || id.ICNTL(18) == 2 )
+      {
+
+	if(verbosity > 1) cout <<"id.ICNTL(18) = 1 || id.ICNTL(18) == 2 "<< endl;
+	// ATTENTION 
+	// AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	// index of row and column by 1
+	
+	if (myid == 0) { // new host process 
+	
+	  jcn = AA.cl;
+	  for(int ii=0; ii<nz; ii++)
+	    jcn[ii] = jcn[ii]+1;
+	  
+	  if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	    printf("problem allocation irn ");
+	    exit(1);
+	  }
+	  
+	  assert(AA.lg[n] == nz);
+	  for(int ii=0; ii< n; ii++)
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	      irn[ii1] = ii+1;  
+	  
+	  
+	  //if (myid == 0) {  // enlever new host
+	  id.irn=irn; id.jcn=jcn;
+	}
+	
+	/* Call the MUMPS package. */
+	// Analyse   
+	id.job=1;
+	dmumps_c(&id);
+
+	if(id.ICNTL(18) == 1 ){
+	  
+	   if( PAR == 0 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    double *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    cout << commSize << "commSize" << "nz =" << nz << endl;
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      assert(nz_loc_procs[0] == 0);
+	      nz_loc_procs[0] = 2;
+
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      jcn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      a_g   = (double*) malloc( sizeof(double)*(nz+2) );
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      irn_g[ 0 ] = 1;
+	      jcn_g[ 0 ] = 1;
+	      a_g  [ 0 ] = 1.;
+	      
+	      irn_g[ 1 ] = 1;
+	      jcn_g[ 1 ] = 1;
+	      a_g  [ 1 ] = 1.;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+		assert(jj2 > 1);
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		cout << "jj2= " << jj2 << endl;
+		assert( jj2 < nz+2);
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    cout << "myid=" << myid <<" nz_loc=" << nz_loc << endl;
+	    if( myid == 1){
+	      cout << "nz_loc=" << nz_loc << endl;
+	      for(int ii=0;ii<nz_loc; ii++){
+		cout << "a_loc[ii]" << a_loc[ii] << endl;
+	
+	      }
+	    }
+	    
+	    if( myid > 0){
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = a_loc;
+	    }
+	    
+	    if( myid == 0){
+	      //free( irn_loc );
+	      //free( jcn_loc );
+	      //free( a_loc );
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	   }
+	
+	  
+	  if( PAR == 1 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    double *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );
+	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc(sizeof(int)*nz);
+	      jcn_g = (int*) malloc(sizeof(int)*nz);
+	      a_g   = (double*) malloc(sizeof(double)*nz);
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = a_loc;
+	    
+	    
+	    if( myid == 0){
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	  }
+	  // version all procs
+// 	    if(myid==0){
+//	    
+// 	    MPI_Bcast( id.mapping, nz, MPI_INT,  0, comm );
+//    
+// 	    nz_loc=0;
+// 	    for(int ii=0;ii<nz; ii++){
+// 	      if( id.mapping[ii] == myid) nz_loc++;
+// 	    }
+//   
+// 	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    a_loc   = (double*) malloc(sizeof(double)*nz_loc);
+//
+// 	    int jj=0;
+// 	    for(int ii=0;ii<nz; ii++)
+// 	      if( id.mapping[ii] == myid){
+// 		irn_loc[jj] = irn[ ii ];
+// 		jcn_loc[jj] = jcn[ ii ];
+// 		a_loc[jj] = AA.a[ ii ];
+// 		jj++;
+// 	      }
+// 	    assert(jj==nz_loc);
+//	    
+// 	    if(PAR==1){
+// 	      id.nz_loc = nz_loc;
+// 	      id.irn_loc = irn_loc;
+// 	      id.jcn_loc = jcn_loc;
+// 	      id.a_loc = a_loc;
+// 	    }
+//	    
+// 	  }
+// 	  else{
+// 	    int *mapping;
+// 	    mapping = (int*) malloc(sizeof(int)*nz);
+// 	    MPI_Bcast( mapping, nz, MPI_INT,  0, comm );
+// 	    nz_loc=0;
+//
+// 	    for(int ii=0;ii<nz; ii++)
+// 	      if( mapping[ii] == myid) nz_loc++;
+//	    
+// 	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    a_loc    = (double*) malloc(sizeof(double)* nz_loc);
+//	    
+// 	    //==============================
+// 	    //    besoin de irn, jcn, AA.a
+// 	    //==============================
+//
+// 	    int jj=0.;
+// 	    for(int ii=0;ii<nz; ii++)
+// 	      if( mapping[ii] == myid){
+// 		irn_loc[jj] = irn[ ii ];  
+// 		jcn_loc[jj] = jcn[ ii ];
+// 		a_loc[jj] = AA.a[ ii ];
+// 		jj++;
+// 	      }
+// 	    assert(jj==nz_loc);
+//
+// 	    free(mapping);
+//
+// 	    id.nz_loc = nz_loc;
+// 	    id.irn_loc = irn_loc;
+// 	    id.jcn_loc = jcn_loc;
+// 	    id.a_loc = a_loc;
+// 	  }
+	 
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  dmumps_c(&id);	  
+	  
+	}
+      
+
+	if(id.ICNTL(18) == 2 ){
+	  printf("id.ICNTL(18)==2 not avaible yet \n");
+	  exit(1);
+
+
+	  if(PAR == 0){ 
+	    printf("id.ICNTL(18)==2 with PAR=0 not available yet \n");
+	    exit(1);
+	    if(myid !=0) {
+	      
+	      //==============================
+	      //    besoin de irn, jcn, AA.a
+	      //==============================
+	      
+	      int commSize;	    
+	      ierr=MPI_Comm_size(comm,&commSize);
+	      commSize=commSize-1;
+	      int myidpar=myid-1;
+	      int m_loc_fst = m/commSize;
+	      int m_loc;
+	      if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+		m_loc = m-m_loc_fst*( commSize-1 );
+	      else
+		m_loc = m_loc_fst;
+	      
+	      int fst_row= myidpar*m_loc_fst;
+	      nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	      
+	      // allocation des tableaux
+	      irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	      
+	      int fst_nnz = AA.lg[fst_row];
+	      for(int ii=0; ii < nz_loc; ii++){
+		a_loc[ii] = AA.a[fst_nnz+ii];
+		jcn_loc[ii] = AA.cl[fst_nnz+ii]; // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	      }
+	      
+	      for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+		for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		  irn_loc[ii1-fst_nnz] = ii+1;  
+	      }
+	      
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = a_loc;
+	    }
+	  }
+	  if(PAR == 1){
+
+	    //==============================
+	    //    besoin de irn, jcn, AA.a
+	    //==============================
+	      
+	    int commSize;	    
+	    ierr=MPI_Comm_size(comm,&commSize);
+	    int m_loc_fst = m/commSize;
+	    int m_loc;
+	    if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	      m_loc = m-m_loc_fst*( commSize-1 );
+	    else
+	      m_loc = m_loc_fst;
+	    
+	    int fst_row= myid*m_loc_fst;
+	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+	    // allocation des tableaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	    
+	    int fst_nnz = AA.lg[fst_row];
+	    for(int ii=0; ii < nz_loc; ii++){
+	      a_loc[ii] = AA.a[fst_nnz+ii];
+	      jcn_loc[ii] = AA.cl[fst_nnz+ii];  // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	    }
+	    
+	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+	      for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		irn_loc[ii1-fst_nnz] = ii+1;  
+	    }
+	  
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = a_loc;
+	    
+	  }
+
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  dmumps_c(&id);
+	}
+      }
+	
+    if( id.ICNTL(18) == 3 )
+      {	
+	// indices et colonnes de la matrice
+	
+// 	//  Cas Matrice parallele ::
+// 	//  ========================
+//	
+// 	// Cas stockage Morse parallele
+// 	m_loc = AA.m_loc;       // Nombre de lignes prise en compte
+// 	nz_loc = AA.nbcoef_loc;   // Nombre de coefficients non nulles 
+// 	// indice des colonnes
+// 	jcn_loc = AA.cl_loc;       // indices des colonnes dans la matrice locale
+//	
+// 	if( !(irn_loc = (int*) malloc(sizeof(int)*nz_loc)) ){
+// 	  printf("problem allocation jcn ");
+// 	  exit(1);
+// 	}
+// 	assert(AA.lg_loc[nrow_loc] == nz_loc);
+// 	for(int ii=0; ii< nrow_loc; ii++)
+// 	  for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 	    irn_loc[ii1] = ii+1;
+//
+// 	a_loc=AA.a_loc;
+//
+	// Pas de matrice parallele ==> utilisation astuce de SuperLU
+	// Matrice :: distribution bloc continue de lignes :: voir SuperLU 
+	// Attention :: performance ???
+	
+// 	    //==================
+// 	    // pour un proc :
+// 	    // a:     AA.a[fstow]   , ..., AA.a[fstrow+nz_loc-1] 
+// 	    // jcn:   AA.cl[fstrow] , ..., AA.cl[fstrow+nz_loc-1]
+// 	    // irn:   AA.lg[fstrow] , ..., AA.lg[fstrow+m_loc] 
+// 	    //==================
+// 	    // apres reception : 
+// 	    // irn_reel:  
+// 	    //  int jj=0, 
+// 	    //  do ii=0,m_loc-1
+// 	    //      do ii1=irn_donnee[ii],irn_donnee[ii+1]-1
+// 	    //         irn_reel[jj] = fst_row+ii+1;
+// 	    //         jj++
+// 	    //      end do
+// 	    //  end do
+// 	    //=================
+
+	cout <<"id.ICNTL(18) = 3,  PAR="<< PAR << endl;
+
+	if(PAR == 0){
+	  	  
+	    
+// 	  if(myid != 0) {
+// 	    int commSize;	    
+// 	    ierr=MPI_Comm_size(comm,&commSize);
+// 	    commSize=commSize-1;
+// 	    int myidpar=myid-1;
+// 	    int m_loc_fst;
+// 	    m_loc_fst= m/commSize;
+// 	    int m_loc;
+// 	    if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+// 	      m_loc = m-m_loc_fst*( commSize-1 );
+// 	    else
+// 	      m_loc = m_loc_fst;
+	    
+// 	    int fst_row;
+// 	    fst_row= myidpar*m_loc_fst;
+// 	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+// 	    // allocation des tableaux
+// 	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	    a_loc    = (double*) malloc(sizeof(double)* nz_loc);
+	    
+// 	    int fst_nnz;
+// 	    fst_nnz = AA.lg[fst_row];
+// 	    for(int ii=0; ii < nz_loc; ii++){
+// 	      a_loc[ii] = AA.a[fst_nnz+ii];
+// 	      jcn_loc[ii] = AA.cl[fst_nnz+ii]+1;
+// 	    }
+	    
+// 	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+// 	      for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 		irn_loc[ii1-fst_nnz] = ii+1;  
+// 	    }
+	 
+// 	    id.nz_loc = nz_loc;
+// 	    id.irn_loc = irn_loc;
+// 	    id.jcn_loc = jcn_loc;
+// 	    id.a_loc = a_loc;
+// 	  }
+
+
+	  // definition de variables
+	  int commSize;
+	  int m_loc_fst;	 
+	  int m_loc;
+	  int fst_row;
+	  
+
+	  int *nz_loc_procs;
+	  int *fst_nz_procs;
+	  int *m_loc_procs;
+	  int *fst_row_procs;
+	 
+
+	  double *tab_a;
+	  int *tab_cl;
+	  int *tab_lg;
+	  int *tab_lg_loc;
+
+	  MPI_Comm_size(comm,&commSize);
+	  
+	  if( myid !=0){
+	    int commSizemm;
+	    int myidpar=myid-1;
+
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+	  
+	    if( myidpar == commSizemm-1 && ( m_loc_fst*commSizemm != m ) )  
+	      m_loc = m-m_loc_fst*( commSizemm-1 );
+	    else
+	      m_loc = m_loc_fst;
+	  
+	    if(verbosity > 5){
+	      fst_row = myidpar*m_loc_fst;
+	      cout << "   myid = " << myid << endl;
+	      cout <<"   m_loc = " << m_loc << endl;
+	      cout <<" fst_row = " << fst_row << endl;
+	    }
+
+	  }
+	  if( myid ==0){
+
+	    int commSizemm;
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+
+	    fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	    m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	    fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	    nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+	    
+	    
+	    fst_row_procs [0] = 0;
+	    m_loc_procs   [0] = 0;
+
+	    for( int ii= 1; ii<commSize; ii++){
+	      fst_row_procs [ii] = (ii-1)*m_loc_fst;
+	      m_loc_procs [ii] = m_loc_fst;
+	    }
+	    
+	    if( m_loc_fst*(commSize-1) != m ) 
+	      m_loc_procs [commSize-1] = m-m_loc_fst*( (commSize-1)-1 );
+
+
+	    nz_loc_procs [0] = 0;
+	    fst_nz_procs [0] = 0;
+	    
+	    for( int ii= 1; ii<commSize; ii++){
+	      nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	      fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	    }
+
+	   
+	    /*
+	      tab_a= (int* ) malloc( nz*sizeof(double) );
+	      tab_cl = (int* ) malloc( nz*sizeof(int) );
+	      tab_lg = (int* ) malloc ( n*sizeof(int) );
+	    */
+	    tab_a  = AA.a;
+	    tab_cl = AA.cl;
+	    tab_lg = AA.lg;
+	  }
+
+	  MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( m_loc_procs,  1, MPI_INT, &m_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( fst_row_procs,  1, MPI_INT, &fst_row, 1, MPI_INT, 0, comm);
+
+	  if(verbosity > 5){
+	    cout << "after scatter " << myid << endl;
+	    cout << "   myid = " << myid << endl;
+	    cout <<"   m_loc = " << m_loc << endl;
+	    cout <<" fst_row = " << fst_row << endl;
+	  }
+	  // allocation des tableaux locaux
+	  irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	  tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	  
+	
+
+	  MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	  MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	  MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	  
+	
+	  int jj=0;
+	  for(int  ii=0; ii<m_loc-1; ii++)
+	    for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	      irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	    }
+	  
+	  for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	    irn_loc[jj] = fst_row+(m_loc-1)+1;
+	    jj++;
+	  }
+	  
+	  for(int ii=0; ii < nz_loc; ii++){	    
+	    jcn_loc[ii] = jcn_loc[ii]+1; 
+	  }
+
+	  assert( jj == nz_loc );
+	  
+	  free( tab_lg_loc );
+	  
+	  id.nz_loc = nz_loc;
+	  id.irn_loc = irn_loc;
+	  id.jcn_loc = jcn_loc;
+	  id.a_loc = a_loc;
+	 
+	  if( myid == 0 ){
+	    free( fst_row_procs );
+	    free( m_loc_procs );
+	    free( fst_nz_procs );
+	    free( nz_loc_procs );
+	  }
+
+	}
+	if(PAR ==1) {
+	  /*
+	    int commSize;
+	    ierr=MPI_Comm_size(comm,&commSize);
+	    int m_loc_fst;
+	    m_loc_fst= m/commSize;
+	    int m_loc;
+	    if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	    m_loc = m-m_loc_fst*( commSize-1 );
+	    else
+	    m_loc = m_loc_fst;	  
+	    
+	    int fst_row;
+	    fst_row = myid*m_loc_fst;
+	    
+	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+	    // allocation des tableaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (double*) malloc(sizeof(double)* nz_loc);
+	    
+	    int fst_nnz;
+	    fst_nnz= AA.lg[fst_row];
+	    for(int ii=0; ii < nz_loc; ii++){
+	    a_loc[ii] = AA.a[fst_nnz+ii];
+	    jcn_loc[ii] = AA.cl[fst_nnz+ii]+1; 
+	    }
+	  
+	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++)
+	    irn_loc[ii1-fst_nnz] = ii+1;  
+	    }
+	    
+	  */
+
+	  // definition de variables
+	  int commSize;
+	  int m_loc_fst;	 
+	  int m_loc;
+	  int fst_row;
+	  
+
+	  int *nz_loc_procs;
+	  int *fst_nz_procs;
+	  int *m_loc_procs;
+	  int *fst_row_procs;
+	 
+
+	  double *tab_a;
+	  int *tab_cl;
+	  int *tab_lg;
+	  int *tab_lg_loc;
+
+	  MPI_Comm_size(comm,&commSize);
+	  m_loc_fst= m/commSize;
+	  
+	  if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	    m_loc = m-m_loc_fst*( commSize-1 );
+	  else
+	    m_loc = m_loc_fst;	  
+	  
+	  fst_row = myid*m_loc_fst;
+	  
+	  if( myid ==0){
+	    fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	    m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	    fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	    nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+
+	    for( int ii= 0; ii<commSize; ii++){
+	      fst_row_procs [ii] = ii*m_loc_fst;
+	      m_loc_procs [ii] = m_loc_fst;
+	    }
+	    
+	    if( m_loc_fst*commSize != m ) 
+	      m_loc_procs [commSize-1] = m-m_loc_fst*( commSize-1 );
+	    
+	    for( int ii= 0; ii<commSize; ii++){
+	      nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	      fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	    }
+
+	   
+	    /*
+	      tab_a= (int* ) malloc( nz*sizeof(double) );
+	      tab_cl = (int* ) malloc( nz*sizeof(int) );
+	      tab_lg = (int* ) malloc ( n*sizeof(int) );
+	    */
+	    tab_a  = AA.a;
+	    tab_cl = AA.cl;
+	    tab_lg = AA.lg;
+	  }
+
+	  MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  cout << "nz_loc("<<myid<<")="<< nz_loc << endl;
+	  cout << "m_loc("<<myid<<")="<< m_loc << endl;
+	  // allocation des tableaux locaux
+	  irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  a_loc    = (double*) malloc(sizeof(double)*nz_loc);
+	  tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	
+	  MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE, a_loc, nz_loc, MPI_DOUBLE, 0, comm);
+	  MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	  MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	
+	  int jj=0;
+	  for(int  ii=0; ii<m_loc-1; ii++)
+	    for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	      irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	    }
+	  
+	  for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	    irn_loc[jj] = fst_row+(m_loc-1)+1;
+	    jj++;
+	  }
+	  
+	  for(int ii=0; ii < nz_loc; ii++){	    
+	    jcn_loc[ii] = jcn_loc[ii]+1; 
+	  }
+
+	  assert( jj == nz_loc );
+	  
+	  free( tab_lg_loc );
+	  
+	  id.nz_loc = nz_loc;
+	  id.irn_loc = irn_loc;
+	  id.jcn_loc = jcn_loc;
+	  id.a_loc = a_loc;
+	 
+	  if( myid == 0 ){
+	    free( fst_row_procs );
+	    free( m_loc_procs );
+	    free( fst_nz_procs );
+	    free( nz_loc_procs );
+	  }
+	}
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation
+	 
+	 id.job=1;
+	 dmumps_c(&id);
+
+	 id.job=2;
+	 dmumps_c(&id);
+      }
+    
+    
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if( jcn != NULL )
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+
+    if( irn != NULL && id.ICNTL(18) >0 ){
+      free(irn); 
+      irn=NULL;
+    }
+
+
+    
+    if( verbosity > 1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Factorisation ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+    
+    if( verbosity )
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << "MUMPS : time factorisation  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+
+  }
+  void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+    long int starttime,finishtime;
+    long int timeused;
+    /////////////////////////////
+    double *rhs;
+    int job;
+
+    if(verbosity) starttime = clock();
+    
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+  
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]+1;
+   
+
+    if ( !(rhs = (double*) malloc(sizeof(double)*m) ) ){
+      printf("Pb allocate rhs in MUMPS\n");
+      exit(1);
+    }
+   
+    for(int ii=0; ii<m; ++ii){
+      rhs[ii] = b[ii];
+    }
+
+    if( myid == 0 )
+      id.rhs=rhs;
+
+    /* solve linear problem */
+
+    id.job=3;
+    dmumps_c(&id);
+
+    if( myid==0 ){
+      x=id.rhs;
+      MPI_Bcast( x, n, MPI_DOUBLE, 0, comm );
+    }
+    else
+      MPI_Bcast( x, n, MPI_DOUBLE, 0, comm );
+    
+    // deallocation de rhs
+    free(rhs);
+
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+    
+    if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+
+    
+
+
+    if( verbosity >1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Solving       ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+
+    if( verbosity ){
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << "MUMPS : time solve step  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+    }
+  }
+
+  ~dSolveMUMPSmpi() { 
+    if(verbosity)
+      cout << "~SolveMUMPS S:" << endl;
+    
+     id.job=JOB_END; 
+     dmumps_c(&id); /* Terminate instance */
+
+     if( irn != NULL){
+      free(irn); 
+      irn=NULL;
+     }
+     /*
+       free(jcn_loc);
+       free(irn_loc);
+       free(a_loc);
+     */
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+static mumps_double_complex *mumps_dc(Complex *p)  { return (mumps_double_complex *) (void *) p;}
+static Complex *inv_mumps_dc(mumps_double_complex *p)  { return (Complex *) (void *) p;}
+
+class zSolveMUMPSmpi :   public MatriceMorse<Complex>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  mutable MPI_Comm comm;
+
+  Complex           *a;
+  int       *irn, *jcn;
+  int          n, m, nz; 
+   
+  // parameter MUMPS
+  KN<int>        perm_r; /* row permutations from partial pivoting */
+  KN<int>        perm_c;
+  KN<double>     scale_r;
+  KN<double>     scale_c;
+  string  string_option;
+  string data_option;
+  int SYM;
+  int PAR;
+  int myid;
+
+  // distribuer
+  int nz_loc;
+  int *jcn_loc, *irn_loc;
+  Complex *a_loc;
+
+
+  static const int JOB_INIT=-1;
+  static const int JOB_END=-2;
+  static const int USE_COMM_WORLD= -987654;
+
+  // variable complex 
+  mutable ZMUMPS_STRUC_C id;
+
+  /* variable d'informations */ 
+  
+#define ICNTL(I) icntl[(I)-1] /* macro s.t. indices match documentation */
+#define CNTL(I) cntl[(I)-1] /* macro s.t. indices match documentation */
+#define RINFOG(I) rinfog[(I)-1] /* macro s.t. indices match documentation */
+#define INFOG(I) infog[(I)-1] /* macro s.t. indices match documentation */
+public:
+  zSolveMUMPSmpi(const MatriceMorse<Complex> &AA,int strategy,double ttgv, double epsilon,
+		 double pivot,double pivot_sym, string param_string, string datafile, KN<long> &param_int, 
+		 KN<double> &param_double, KN<long> &pperm_r, KN_<long> &pperm_c, KN<double> &pscale_r,KN<double> &pscale_c, MPI_Comm  * mpicommw) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv), string_option(param_string), data_option(datafile), perm_r(pperm_r), perm_c(pperm_c), 
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot), scale_r(pscale_r), scale_c(pscale_c)
+  { 
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+    int dataint[40];
+    double datadouble[15];
+    int ierr;
+
+    if(mpicommw==0){
+      comm=MPI_COMM_WORLD;
+    }
+    else
+      comm= *mpicommw;
+    
+    /* ------------------------------------------------------------
+       INITIALIZE THE MUMPS PROCESS GRID. 
+       ------------------------------------------------------------*/
+    ierr = MPI_Comm_rank(comm, &myid);
+    if( myid ==0){
+      n    = AA.n;
+      m    = AA.m; 
+      nz   = AA.nbcoef;
+    
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+    else{
+      MPI_Bcast(  &n, 1, MPI_INT,  0, comm );
+      MPI_Bcast(  &m, 1, MPI_INT,  0, comm );
+      MPI_Bcast( &nz, 1, MPI_INT,  0, comm );
+    }
+   
+
+    if( !(param_int==NULL) ) 
+      assert( param_int.N() == 42);
+    if( !(param_double==NULL) ) 
+      assert( param_double.N() == 15);
+    if(pperm_r)
+      assert( perm_r.N() == n);
+    if(pscale_r) 
+      assert( scale_r.N() == n+m );
+    if(pscale_c) 
+       assert( scale_c.N() == n+m );
+    if( n != m )
+      cerr << "only square matrix are supported by MUMPS" << endl;
+   
+      /* ------------------------------------------------------------
+       INITIALIZE THE MUMPS PROCESS GRID. 
+       ------------------------------------------------------------*/
+   
+    // initialisation par defaut
+ 
+    SYM=0; PAR=1;
+    
+    //      if(!string_option.empty()) 
+    //       {	
+    // 	read_options_freefem(&string_option,&SYM,&PAR);
+    //       }
+    if( !(param_int==NULL) ){
+      SYM = param_int[0];
+      PAR = param_int[1];
+    }
+    else 
+      if(!data_option.empty())
+	{
+	  if(myid==0){
+	    char * retfile= new char[data_option.size()+1];
+	    strcpy(retfile, (&data_option)->c_str());
+	    printf("read data from file %s\n", retfile);
+	    FILE *pFile=fopen(retfile,"rt");
+	    
+	    int     i_data=0;
+	    int     d_data=0.;
+	    char    data[256];
+	    char   *tictac;
+	    
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    SYM = atoi(tictac);
+	    
+	    fgets(data,256,pFile);
+	    tictac = strtok(data," /!#\t\n");
+	    PAR = atoi(tictac);
+	    
+	    while( !feof(pFile) && i_data < 40){
+	      fgets(data,256,pFile);
+	      tictac = strtok(data," /!#\t\n");
+	      dataint[i_data] = (int)atol(tictac);
+	      i_data++;
+	    }  
+	    assert(i_data == 40);
+	    while( !feof(pFile) && d_data < 15){
+	      fgets(data,256,pFile);
+	      tictac = strtok(data," /!#\t\n");
+	      datadouble[d_data] = (double)atof(tictac);
+	      d_data++;
+	    }  
+	    assert(d_data == 15);
+	    fclose(pFile);
+	    delete [] retfile;
+	    
+	    MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	    MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+	    
+	    MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	    MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+	    
+	    fclose(pFile);
+	    delete [] retfile;
+	  }
+	  else{
+	    
+	    MPI_Bcast(  &SYM, 1, MPI_INT,  0, comm );
+	    MPI_Bcast(  &PAR, 1, MPI_INT,  0, comm );
+	    
+	    MPI_Bcast(  dataint, 40, MPI_INT,  0, comm );
+	    MPI_Bcast(  datadouble, 15, MPI_DOUBLE,  0, comm );
+	  }
+	}
+    
+    /* Initialize a MUMPS instance. Use comm */
+    id.job=JOB_INIT; 
+    id.par=PAR; 
+    id.sym=SYM;
+    id.comm_fortran=(MUMPS_INT) MPI_Comm_c2f(comm); 
+
+    zmumps_c(&id);
+
+     /* set parameter of mumps */
+    if( !(param_int==NULL) || !(param_double==NULL) ){
+      if(!data_option.empty()){ 
+	printf("read option before with the file %s\n",data_option.c_str());
+	exit(1);
+      }
+      
+      if( !(param_int==NULL) ){ 
+	for(int ii=0; ii<40; ii++)
+	  id.ICNTL(ii+1) = param_int[ii+2];
+      }
+      else
+	// parameter by default
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+
+      if( !(param_double==NULL) )
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = param_double[ii];
+      
+    }    
+    else 
+      if(!data_option.empty()){
+	for(int ii=0; ii<40; ii++)
+	  id.ICNTL(ii+1) = dataint[ii];
+	for(int ii=0; ii<15; ii++)
+	  id.CNTL(ii+1) = datadouble[ii];
+      }
+      else{
+	// parameter by default
+	id.ICNTL(1)=-1; id.ICNTL(2)=-1; id.ICNTL(3)=-1; id.ICNTL(4)=0;
+      }
+
+    // uniquement donner au host 
+    if(myid==0){
+      if( !(perm_r==NULL) && id.ICNTL(7)==1){
+	for(int ii=0; ii<n; ii++) id.perm_in[ii] = pperm_r[ii];
+      }
+      // a decommenter
+      //if( !(perm_c==NULL) && id.ICNTL(6)==1){
+      //for(int ii=0; ii<m; ii++) id.perm_in[ii] = pperm_c[ii];
+      //}
+      if( !(scale_r==NULL) && !(scale_c==NULL) && id.ICNTL(8)==-1 ){
+	for(int ii=0; ii<n; ii++) id.rowsca[ii] = scale_r[ii]; 
+	for(int ii=0; ii<m; ii++) id.colsca[ii] = scale_c[ii];
+      }
+    }
+
+    
+    /* valeur par defaut mis dans le dur */
+   
+    irn = NULL;
+    jcn = NULL;
+
+
+    if( id.ICNTL(5) != 0 ){
+      printf("we consider only assembled format \n");
+      exit(1);
+    }
+   
+    
+    /* Define the problem on the host */
+    if (myid == 0) {
+      id.n = n; id.nz =nz; 
+      //id.irn=irn; id.jcn=jcn;
+      //id.a = mumps_dc(a); //id.rhs = rhs;
+    }
+
+    if( id.ICNTL(18) == 0)
+      {
+	// CASE:: NON DISTRIBUTED MATRIX
+	a=AA.a;
+	// ATTENTION 
+	// AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	// index of row and colummn by 1
+	jcn = AA.cl;
+	for(int ii=0; ii<nz; ii++)
+	  jcn[ii] = jcn[ii]+1;
+	
+	if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	  printf("problem allocation jcn ");
+	  exit(1);
+	}
+	
+	assert(AA.lg[n] == nz);
+	for(int ii=0; ii< n; ii++)
+	  for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	    irn[ii1] = ii+1;  
+		
+	if (myid == 0) {
+	  id.irn=irn; id.jcn=jcn;
+	  id.a = mumps_dc(a); //id.rhs = rhs;
+	}
+
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation 
+	id.job=4;
+	zmumps_c(&id);
+	
+      }
+
+    
+    if( id.ICNTL(18) == 1 || id.ICNTL(18) == 2 )
+      {
+
+	cout <<"id.ICNTL(18) = 1 || id.ICNTL(18) == 2 "<< endl;;
+	// ATTENTION 
+	// AA.cl :: indice des colonnes (exacte) et AA.lg :: indice des lignes 
+	// index of row and column by 1
+
+	if(myid == 0) { // uniquement sur le proc 0
+	  jcn = AA.cl;
+	  for(int ii=0; ii<nz; ii++)
+	    jcn[ii] = jcn[ii]+1;
+	  
+	  if( !(irn = (int*) malloc(sizeof(int)*nz)) ){
+	    printf("problem allocation irn ");
+	    exit(1);
+	  }
+	
+	  assert(AA.lg[n] == nz);
+	  for(int ii=0; ii< n; ii++)
+	    for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+	      irn[ii1] = ii+1;  
+
+
+	  //if (myid == 0) { // changement uniquement sur le proc 0
+	  id.irn=irn; id.jcn=jcn;
+	}
+	
+	/* Call the MUMPS package. */
+	// Analyse   
+	id.job=1;
+	zmumps_c(&id);
+
+	if(id.ICNTL(18) == 1 ){
+
+	   if( PAR == 0 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    Complex *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    cout << commSize << "commSize" << "nz =" << nz << endl;
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      assert(nz_loc_procs[0] == 0);
+	      nz_loc_procs[0] = 2;
+
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      jcn_g = (int*) malloc( sizeof(int)*(nz+2) );
+	      a_g   = (Complex*) malloc( 2*sizeof(double)*(nz+2) );
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      irn_g[ 0 ] = 1;
+	      jcn_g[ 0 ] = 1;
+	      a_g  [ 0 ] = 1.;
+	      
+	      irn_g[ 1 ] = 1;
+	      jcn_g[ 1 ] = 1;
+	      a_g  [ 1 ] = 1.;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+		assert(jj2 > 1);
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		cout << "jj2= " << jj2 << endl;
+		assert( jj2 < nz+2);
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    	    
+	    if( myid > 0){
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = mumps_dc(a_loc);
+	    }
+	    
+	    if( myid == 0){
+	      //free( irn_loc );
+	      //free( jcn_loc );
+	      //free( a_loc );
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	   }
+	
+	  
+	  if( PAR == 1 ){ 
+	    int *nz_loc_procs;
+	    int *fst_nz_procs;
+	    int *irn_g;
+	    int *jcn_g;
+	    Complex *a_g;
+	    int commSize;
+	    
+	    MPI_Comm_size(comm,&commSize);
+	    
+	    if(myid==0){
+	      // allocation des differents tableaux
+	      nz_loc_procs = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++){
+		nz_loc_procs[ii]=0;
+	      }
+	      for(int ii=0; ii<nz; ii++){
+		nz_loc_procs[ id.mapping[ii] ]++;
+	      }
+	      
+	      fst_nz_procs = (int*) malloc ( commSize*sizeof(int) );
+	      
+	      fst_nz_procs[0] = 0;
+	      for(int ii=1; ii<commSize; ii++){
+		fst_nz_procs[ii] = fst_nz_procs[ii-1]+nz_loc_procs[ii-1];
+	      }
+	      
+	      irn_g = (int*) malloc(sizeof(int)*nz);
+	      jcn_g = (int*) malloc(sizeof(int)*nz);
+	      a_g   = (Complex*) malloc(2*sizeof(double)*nz);
+	      
+	      int *index_p;
+	      index_p = (int*) malloc ( commSize*sizeof(int) );
+	      for(int ii=0; ii<commSize; ii++)
+		index_p[ii] =0;
+	      
+	      for(int ii=0;ii<nz; ii++){	      
+		int jj1 = id.mapping[ii];
+		int jj2 = fst_nz_procs[jj1] + index_p[jj1];
+
+		irn_g[ jj2 ] =  irn[ ii ];
+		jcn_g[ jj2 ] =  jcn[ ii ];
+		a_g  [ jj2 ] = AA.a[ ii ];
+		index_p[jj1]++;
+	      }
+	      free(index_p);
+	      
+	    }
+	    
+	    MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	    
+	    // allocation des tableaux locaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc   = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	    
+	    MPI_Scatterv(   a_g, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	    MPI_Scatterv( jcn_g, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	    MPI_Scatterv( irn_g, nz_loc_procs, fst_nz_procs, MPI_INT, irn_loc, nz_loc, MPI_INT, 0, comm);
+	    
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = mumps_dc(a_loc);
+	    
+	    
+	    if( myid == 0){
+	      free( nz_loc_procs );
+	      free( fst_nz_procs );
+	      free( irn_g );
+	      free( jcn_g );
+	      free( a_g );
+	    }
+	  }
+
+
+
+
+	  //printf("id.ICNTL(18)==1 pas prevus a construire \n");
+	  //exit(1);
+
+	  /* // version matrice sur tous les processeurs
+	  if(myid==0){
+
+	    MPI_Bcast( id.mapping, nz, MPI_INT,  0, comm );
+
+	    nz_loc=0;
+	    for(int ii=0;ii<nz; ii++){
+	      if( id.mapping[ii] == myid) nz_loc++;
+	    }
+	   
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc   = (Complex*) malloc(sizeof(Complex)*nz_loc);
+
+	    int jj=0;
+	    for(int ii=0;ii<nz; ii++)
+	      if( id.mapping[ii] == myid){
+		irn_loc[jj] = irn[ ii ];
+		jcn_loc[jj] = jcn[ ii ];
+		a_loc[jj] = AA.a[ ii ];
+		jj++;
+	      }
+	    assert(jj==nz_loc);
+	    
+	    if(PAR==1){
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = mumps_dc(a_loc);
+	    }
+  
+	  }
+	  else{
+	    int *mapping;
+	    mapping = (int*) malloc(sizeof(int)*nz);
+	    MPI_Bcast( mapping, nz, MPI_INT,  0, comm );
+	    nz_loc=0;
+
+	    for(int ii=0;ii<nz; ii++)
+	      if( mapping[ii] == myid) nz_loc++;
+	    
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (Complex*) malloc(sizeof(Complex)* nz_loc);
+	    
+	    int jj=0.;
+	    for(int ii=0;ii<nz; ii++)
+	      if( mapping[ii] == myid){
+		irn_loc[jj] = irn[ ii ];
+		jcn_loc[jj] = jcn[ ii ];
+		a_loc[jj] = AA.a[ ii ];
+		jj++;
+	      }
+	    assert(jj==nz_loc);
+
+	    free(mapping);
+
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = mumps_dc(a_loc);
+
+
+
+	  }
+	  */
+
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  zmumps_c(&id);	  
+	  
+	}
+      
+
+	if(id.ICNTL(18) == 2 ){
+	   printf("id.ICNTL(18)==2 not yet available \n");
+	   exit(1);
+
+	  if(PAR == 0){ 
+	    printf("id.ICNTL(18)==2 pas prevus \n");
+	    exit(1);
+	    if(myid !=0) {
+	      int commSize;	    
+	      ierr=MPI_Comm_size(comm,&commSize);
+	      commSize=commSize-1;
+	      int myidpar=myid-1;
+	      int m_loc_fst = m/commSize;
+	      int m_loc;
+	      if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+		m_loc = m-m_loc_fst*( commSize-1 );
+	      else
+		m_loc = m_loc_fst;
+	      
+	      int fst_row= myidpar*m_loc_fst;
+	      nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	      
+	      // allocation des tableaux
+	      irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	      a_loc    = (Complex*) malloc(sizeof(Complex)*nz_loc);
+	      
+	      int fst_nnz = AA.lg[fst_row];
+	      for(int ii=0; ii < nz_loc; ii++){
+		a_loc[ii] = AA.a[fst_nnz+ii];
+		jcn_loc[ii] = AA.cl[fst_nnz+ii]; // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	      }
+	      
+	      for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+		for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		  irn_loc[ii1-fst_nnz] = ii+1;  
+	      }
+	      
+	      id.nz_loc = nz_loc;
+	      id.irn_loc = irn_loc;
+	      id.jcn_loc = jcn_loc;
+	      id.a_loc = mumps_dc(a_loc);
+	    }
+	  }
+	  if(PAR == 1){
+
+	    int commSize;	    
+	    ierr=MPI_Comm_size(comm,&commSize);
+	    int m_loc_fst = m/commSize;
+	    int m_loc;
+	    if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	      m_loc = m-m_loc_fst*( commSize-1 );
+	    else
+	      m_loc = m_loc_fst;
+	    
+	    int fst_row= myid*m_loc_fst;
+	    nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+	    
+	    // allocation des tableaux
+	    irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	    a_loc    = (Complex*) malloc(sizeof(Complex)*nz_loc);
+	    
+	    int fst_nnz = AA.lg[fst_row];
+	    for(int ii=0; ii < nz_loc; ii++){
+	      a_loc[ii] = AA.a[fst_nnz+ii];
+	      jcn_loc[ii] = AA.cl[fst_nnz+ii];  // jcn=AA.cl a ete augmenter de 1 avant => pas ajouter 1
+	    }
+	    
+	    for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+	      for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+		irn_loc[ii1-fst_nnz] = ii+1;  
+	    }
+	  
+	    id.nz_loc = nz_loc;
+	    id.irn_loc = irn_loc;
+	    id.jcn_loc = jcn_loc;
+	    id.a_loc = mumps_dc(a_loc);
+
+	  }
+
+	  /* Call the MUMPS package. */
+	  // Factorisation   
+	  id.job=2;
+	  zmumps_c(&id);
+	}
+      }
+	
+    if( id.ICNTL(18) == 3 )
+      {	
+	// indices et colonnes de la matrice
+	
+// 	//  Cas Matrice parallele ::
+// 	//  ========================
+//	
+// 	// Cas stockage Morse parallele
+// 	m_loc = AA.m_loc;       // Nombre de lignes prise en compte
+// 	nz_loc = AA.nbcoef_loc;   // Nombre de coefficients non nulles 
+// 	// indice des colonnes
+// 	jcn_loc = AA.cl_loc;       // indices des colonnes dans la matrice locale
+//	
+// 	if( !(irn_loc = (int*) malloc(sizeof(int)*nz_loc)) ){
+// 	  printf("problem allocation jcn ");
+// 	  exit(1);
+// 	}
+// 	assert(AA.lg_loc[nrow_loc] == nz_loc);
+// 	for(int ii=0; ii< nrow_loc; ii++)
+// 	  for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 	    irn_loc[ii1] = ii+1;
+//
+// 	a_loc=AA.a_loc;
+//
+	// Pas de matrice parallele ==> utilisation astuce de SuperLU
+	// Matrice :: distribution bloc continue de lignes :: voir SuperLU 
+	// Attention :: performance ???
+	
+
+	cout <<"id.ICNTL(18) = 3,  PAR="<< PAR << endl;
+
+	 if(PAR == 0){ 
+// 	    if(myid !=0) {
+// 	      int commSize;	    
+// 	      ierr=MPI_Comm_size(comm,&commSize);
+// 	      commSize=commSize-1;
+// 	      int myidpar=myid-1;
+// 	      int m_loc_fst;
+// 	      m_loc_fst= m/commSize;
+// 	      int m_loc;
+// 	      if( myidpar == commSize-1 && ( m_loc_fst*commSize != m ) )  
+// 		m_loc = m-m_loc_fst*( commSize-1 );
+// 	      else
+// 		m_loc = m_loc_fst;
+//	      
+// 	      int fst_row;
+// 	      fst_row= myidpar*m_loc_fst;
+// 	      nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+//	      
+// 	      // allocation des tableaux
+// 	      irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	      jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	      a_loc    = (Complex*) malloc(sizeof(Complex)* nz_loc);
+//	      
+// 	      int fst_nnz;
+// 	      fst_nnz = AA.lg[fst_row];
+// 	      for(int ii=0; ii < nz_loc; ii++){
+// 		a_loc[ii] = AA.a[fst_nnz+ii];
+// 		jcn_loc[ii] = AA.cl[fst_nnz+ii]+1;
+// 	      }	      
+// 	      for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+// 		for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 		  irn_loc[ii1-fst_nnz] = ii+1;  
+// 	      }	      
+// 	      id.nz_loc = nz_loc;
+// 	      id.irn_loc = irn_loc;
+// 	      id.jcn_loc = jcn_loc;
+// 	      id.a_loc = mumps_dc(a_loc);
+// 	    }
+
+	    // definition de variables
+	  int commSize;
+	  int m_loc_fst;	 
+	  int m_loc;
+	  int fst_row;
+	  
+
+	  int *nz_loc_procs;
+	  int *fst_nz_procs;
+	  int *m_loc_procs;
+	  int *fst_row_procs;
+	 
+
+	  Complex *tab_a;
+	  int *tab_cl;
+	  int *tab_lg;
+	  int *tab_lg_loc;
+
+	  MPI_Comm_size(comm,&commSize);
+	  
+	  if( myid !=0){
+	    int commSizemm;
+	    int myidpar=myid-1;
+
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+	  
+	    if( myidpar == commSizemm-1 && ( m_loc_fst*commSizemm != m ) )  
+	      m_loc = m-m_loc_fst*( commSizemm-1 );
+	    else
+	      m_loc = m_loc_fst;
+	  
+	    if(verbosity > 5){
+	      fst_row = myidpar*m_loc_fst;
+	      cout << "   myid = " << myid << endl;
+	      cout <<"   m_loc = " << m_loc << endl;
+	      cout <<" fst_row = " << fst_row << endl;
+	    }
+
+	  }
+	  if( myid ==0){
+
+	    int commSizemm;
+	    commSizemm = commSize-1;
+	    m_loc_fst= m/commSizemm;
+
+	    fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	    m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	    fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	    nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+	    
+	    
+	    fst_row_procs [0] = 0;
+	    m_loc_procs   [0] = 0;
+
+	    for( int ii= 1; ii<commSize; ii++){
+	      fst_row_procs [ii] = (ii-1)*m_loc_fst;
+	      m_loc_procs [ii] = m_loc_fst;
+	    }
+	    
+	    if( m_loc_fst*(commSize-1) != m ) 
+	      m_loc_procs [commSize-1] = m-m_loc_fst*( (commSize-1)-1 );
+
+
+	    nz_loc_procs [0] = 0;
+	    fst_nz_procs [0] = 0;
+	    
+	    for( int ii= 1; ii<commSize; ii++){
+	      nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	      fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	    }
+
+	   
+	    /*
+	      tab_a= (int* ) malloc( nz*sizeof(double) );
+	      tab_cl = (int* ) malloc( nz*sizeof(int) );
+	      tab_lg = (int* ) malloc ( n*sizeof(int) );
+	    */
+	    tab_a  = AA.a;
+	    tab_cl = AA.cl;
+	    tab_lg = AA.lg;
+	  }
+
+	  MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( m_loc_procs,  1, MPI_INT, &m_loc, 1, MPI_INT, 0, comm);
+	  MPI_Scatter( fst_row_procs,  1, MPI_INT, &fst_row, 1, MPI_INT, 0, comm);
+
+	  if(verbosity > 5){
+	    cout << "after scatter " << myid << endl;
+	    cout << "   myid = " << myid << endl;
+	    cout <<"   m_loc = " << m_loc << endl;
+	    cout <<" fst_row = " << fst_row << endl;
+	  }
+	  // allocation des tableaux locaux
+	  irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	  a_loc    = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	  tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	  
+	
+
+	  MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	  MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	  MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	  
+	
+	  int jj=0;
+	  for(int  ii=0; ii<m_loc-1; ii++)
+	    for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	      irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	    }
+	  
+	  for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	    irn_loc[jj] = fst_row+(m_loc-1)+1;
+	    jj++;
+	  }
+	  
+	  for(int ii=0; ii < nz_loc; ii++){	    
+	    jcn_loc[ii] = jcn_loc[ii]+1; 
+	  }
+
+	  assert( jj == nz_loc );
+	  
+	  free( tab_lg_loc );
+	  
+	  id.nz_loc = nz_loc;
+	  id.irn_loc = irn_loc;
+	  id.jcn_loc = jcn_loc;
+	  id.a_loc = mumps_dc(a_loc);
+	 
+	  if( myid == 0 ){
+	    free( fst_row_procs );
+	    free( m_loc_procs );
+	    free( fst_nz_procs );
+	    free( nz_loc_procs );
+	  }
+	   
+
+	 }
+	 if(PAR ==1) {
+	  
+	   
+// 	   int commSize;
+// 	   ierr=MPI_Comm_size(comm,&commSize);
+// 	   int m_loc_fst;
+// 	   m_loc_fst= m/commSize;
+// 	   int m_loc;
+// 	   if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+// 	     m_loc = m-m_loc_fst*( commSize-1 );
+// 	   else
+// 	     m_loc = m_loc_fst;
+//	   
+// 	   int fst_row;
+// 	   fst_row = myid*m_loc_fst;
+// 	   nz_loc = AA.lg[fst_row+m_loc]-AA.lg[fst_row];
+//	    
+// 	   allocation des tableaux
+// 	   irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	   jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+// 	   a_loc    = (Complex*) malloc(sizeof(Complex)*nz_loc);
+//	   
+// 	   int fst_nnz;
+// 	   fst_nnz= AA.lg[fst_row];
+// 	   for(int ii=0; ii < nz_loc; ii++){
+// 	     a_loc[ii] = AA.a[fst_nnz+ii];
+// 	     jcn_loc[ii] = AA.cl[fst_nnz+ii]+1; 
+// 	   }
+//   
+// 	   for(int ii=fst_row; ii< fst_row+m_loc; ii++){
+// 	     for(int ii1=AA.lg[ii]; ii1 < AA.lg[ii+1]; ii1++ )
+// 	       irn_loc[ii1-fst_nnz] = ii+1;  
+// 	   }
+//	   
+// 	   id.nz_loc = nz_loc;
+// 	   id.irn_loc = irn_loc;
+// 	   id.jcn_loc = jcn_loc;
+// 	   id.a_loc = mumps_dc(a_loc);
+
+	   // definition de variables
+	   int commSize;
+	   int m_loc_fst;	 
+	   int m_loc;
+	   int fst_row;
+	   
+
+	   int *nz_loc_procs;
+	   int *fst_nz_procs;
+	   int *m_loc_procs;
+	   int *fst_row_procs;
+	   
+	   
+	   Complex *tab_a;
+	   int *tab_cl;
+	   int *tab_lg;
+	   int *tab_lg_loc;
+	   
+	   MPI_Comm_size(comm,&commSize);
+	   m_loc_fst= m/commSize;
+	   
+	   if( myid == commSize-1 && ( m_loc_fst*commSize != m ) )  
+	     m_loc = m-m_loc_fst*( commSize-1 );
+	   else
+	     m_loc = m_loc_fst;	  
+	   
+	   fst_row = myid*m_loc_fst;
+	   
+	   if( myid ==0){
+	     fst_row_procs = (int* ) malloc( commSize*sizeof(int) );
+	     m_loc_procs = (int* ) malloc( commSize*sizeof(int) );
+	     fst_nz_procs = (int* ) malloc( commSize*sizeof(int) );
+	     nz_loc_procs = (int* ) malloc ( commSize*sizeof(int) );
+
+	     for( int ii= 0; ii<commSize; ii++){
+	       fst_row_procs [ii] = ii*m_loc_fst;
+	       m_loc_procs [ii] = m_loc_fst;
+	     }
+	     
+	     if( m_loc_fst*commSize != m ) 
+	       m_loc_procs [commSize-1] = m-m_loc_fst*( commSize-1 );
+	     
+	     for( int ii= 0; ii<commSize; ii++){
+	       nz_loc_procs [ii] = AA.lg[fst_row_procs[ii]+m_loc_procs[ii] ] - AA.lg[fst_row_procs[ii]];
+	       fst_nz_procs [ii] = AA.lg[fst_row_procs[ii]];
+	     }
+	     
+	     
+	     /*
+	       tab_a= (int* ) malloc( nz*sizeof(double) );
+	       tab_cl = (int* ) malloc( nz*sizeof(int) );
+	       tab_lg = (int* ) malloc ( n*sizeof(int) );
+	     */
+	     tab_a  = AA.a;
+	     tab_cl = AA.cl;
+	     tab_lg = AA.lg;
+	   }
+	   
+	   MPI_Scatter( nz_loc_procs, 1, MPI_INT, &nz_loc, 1, MPI_INT, 0, comm);
+	  
+	   // allocation des tableaux locaux
+	   irn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	   jcn_loc = (int*) malloc(sizeof(int)*nz_loc);
+	   a_loc    = (Complex*) malloc(2*sizeof(double)*nz_loc);
+	   tab_lg_loc = (int*) malloc(sizeof(int)*(m_loc) );
+	   
+	   MPI_Scatterv(  tab_a, nz_loc_procs, fst_nz_procs, MPI_DOUBLE_COMPLEX, a_loc, nz_loc, MPI_DOUBLE_COMPLEX, 0, comm);
+	   MPI_Scatterv( tab_cl, nz_loc_procs, fst_nz_procs, MPI_INT, jcn_loc, nz_loc, MPI_INT, 0, comm);
+	   MPI_Scatterv( tab_lg,  m_loc_procs, fst_row_procs, MPI_INT, tab_lg_loc, m_loc, MPI_INT, 0, comm);
+	
+	   int jj=0;
+	   for(int  ii=0; ii<m_loc-1; ii++)
+	     for(int ii1= tab_lg_loc[ii]; ii1 < tab_lg_loc[ii+1]; ii1++){
+	       irn_loc[jj] = fst_row+ii+1;
+	      jj++;
+	     }
+	   
+	   for(int ii1= tab_lg_loc[m_loc-1]; ii1 < tab_lg_loc[0]+nz_loc; ii1++){
+	     irn_loc[jj] = fst_row+(m_loc-1)+1;
+	     jj++;
+	   }
+	   
+	   for(int ii=0; ii < nz_loc; ii++){	    
+	     jcn_loc[ii] = jcn_loc[ii]+1; 
+	   }
+	   
+	   assert( jj == nz_loc );
+	   
+	   free( tab_lg_loc );
+	   
+	   id.nz_loc  = nz_loc;
+	   id.irn_loc = irn_loc;
+	   id.jcn_loc = jcn_loc;
+	   id.a_loc = mumps_dc(a_loc);
+	 
+	   if( myid == 0 ){
+	     free( fst_row_procs );
+	     free( m_loc_procs );
+	     free( fst_nz_procs );
+	     free( nz_loc_procs );
+	   }
+	   
+
+	 }
+	/* Call the MUMPS package. */
+	// Analyse + Factorisation
+	 
+	 id.job=1;
+	 zmumps_c(&id);
+
+	 id.job=2;
+	 zmumps_c(&id);
+      }
+    
+    
+    
+
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if( jcn != NULL )
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+
+    if( irn != NULL ) free(irn); 
+ 
+
+    if( verbosity >1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Factorisation ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+    if( verbosity){
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << "MUMPS : time factorisation :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+    }
+        
+  
+  }
+
+  void Solver(const MatriceMorse<Complex> &AA,KN_<Complex> &x,const KN_<Complex> &b) const  {
+    long int starttime,finishtime;
+    long int timeused;
+    //*******************************************************************//
+    //    depend pas de la forme de la matrice: distribuer ou assembler
+    Complex *rhs;
+    int job;
+    
+    if(verbosity) starttime = clock();
+
+    ffassert ( &x[0] != &b[0]);
+    epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+  
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]+1;
+    
+    if ( !(rhs = (Complex*) malloc(sizeof(Complex)*m) ) ){
+      printf("Pb allocate rhs in MUMPS\n");
+      exit(1);
+    }
+   
+    for(int ii=0; ii<m; ++ii){
+      rhs[ii] = b[ii];
+    }
+
+    if( myid == 0 )
+      id.rhs=mumps_dc(rhs);
+
+    /* solve linear problem */
+    id.job=3;
+    zmumps_c(&id);
+
+   
+    if( myid==0 ){
+      x=inv_mumps_dc(id.rhs); 
+      MPI_Bcast( x,  n, MPI_DOUBLE_COMPLEX,  0, comm );
+    }
+    else
+      MPI_Bcast( x,  n, MPI_DOUBLE_COMPLEX,  0, comm );
+    
+  
+    
+    // deallocation de rhs
+    free(rhs);
+
+    // indices des colonnes commence par 1 avec mumps 
+    //  et 0 dans freefem ==> renumerotation
+    if(jcn != NULL)
+      for(int ii=0; ii<nz; ii++)
+	jcn[ii] = jcn[ii]-1;
+
+
+    if( verbosity > 1){
+      /* information given by mumps*/
+      int Rinfo=20;
+      int Sinfo=40;
+      // in Freefem++ we give only global information
+      if(myid == 0){
+	printf("Global Output Information of MUMPS: RINFOG and INFOG \n");
+	printf("=============  After Solving       ==================\n");
+	for(int ii=0; ii< Rinfo; ii++) 
+	  printf( "RINFOG[%d]= %f \n", ii, id.RINFOG(ii+1) );
+	printf("=====================================================\n");
+	for(int ii=0; ii< Sinfo; ii++) 
+	  printf( "INFOG[%d]= %d \n", ii, id.INFOG(ii+1) );
+	printf("=====================================================\n");
+      }
+    }
+
+    if(verbosity)
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << " MUMPS : time solve  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+    
+  }
+
+  ~zSolveMUMPSmpi() { 
+    //*******************************************************************//
+    //    depend pas de la forme de la matrice: distribuer ou assembler
+    if(verbosity)
+      cout << "~SolveMUMPS Z:" << endl;
+    
+     id.job=JOB_END; 
+     zmumps_c(&id); /* Terminate instance */
+     
+  }
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+     
+}; 
+
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverMUMPSmpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+      cout << " BuildSolverMUMPS<double>" << endl;
+    return new dSolveMUMPSmpi(*A,ds.strategy, ds.tgv, ds.epsilon, ds.tol_pivot, ds.tol_pivot_sym, ds.sparams, ds.data_filename,
+			      ds.lparams, ds.dparams, ds.perm_r, ds.perm_c, ds.scale_r, ds.scale_c,(MPI_Comm *)ds.commworld);
+}
+
+
+
+
+MatriceMorse<Complex>::VirtualSolver *
+BuildSolverMUMPSmpi(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+    if(verbosity>9)
+      cout << " BuildSolverMUMPS<Complex>" << endl;
+    return new zSolveMUMPSmpi(*A,ds.strategy, ds.tgv, ds.epsilon, ds.tol_pivot, ds.tol_pivot_sym, ds.sparams, ds.data_filename,  
+			      ds.lparams, ds.dparams, ds.perm_r, ds.perm_c, ds.scale_r, ds.scale_c,(MPI_Comm *)ds.commworld);
+}
+
+
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; 
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+}
+
+bool SetMUMPSmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to MUMPSmpi" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverMUMPSmpi;
+    DefSparseSolver<Complex>::solver =BuildSolverMUMPSmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+}
+
+
+
+Init init;
+Init::Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: MUMPS ,  defaultsolver defaultsolverMUMPS " << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverMUMPSmpi;
+  DefSparseSolver<Complex>::solver =BuildSolverMUMPSmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoMUMPS","(",new OneOperator0<bool>(SetMUMPSmpi));
+}
+
diff --git a/src/solver/README_COMPILE b/src/solver/README_COMPILE
new file mode 100644
index 0000000..cb0440c
--- /dev/null
+++ b/src/solver/README_COMPILE
@@ -0,0 +1,170 @@
+#############################################
+# README_COMPILE:
+#
+# HELP TO COMPILE THE DIFFERENT SPARSE SOLVER
+#
+#############################################
+
+General pre-requirements :
+
+- C,  C++ and Fortran (f77, f90)  compilers 
+- MPI  library
+- BLAS library
+
+These different elements are defined in the configure step of the compilation FreeFem++. Therefore, it must be same for the following solver. For computation, it is important to have an optimized BLAS. 
+Among optimized BLAS can be cited ATLAS (Automatically Tuned Linear Algebra Software) http://math-atlas.sourceforge.net/ (BSD licence), GotoBLAS  http://www.tacc.utexas.edu/resources/software/ (UT TACC Research license). These library can be used free under their license limitation. For GotoBLAS, the software and documentation can be used without any charge for academic, research, experimental or personal use. For commercial use, it is required to purchase a license. For more details, pl [...]
+
+Remark: In Mac OSX, a problem occur in calling the Blas function CDOTC, CDOTU, ZDOTC, ZDOTU with veclib in Fortran (see http://developper.apple.com/hardwaredrivers/ve/errata.html). A patch for the library veclib is given in the directory PATCHVECLIB.
+
+A) Sparse Direct Solver
+
+We have interfaced freefem++ with the following parallel sparse direct solver: SuperLU_DIST, MUMPS and pastix. These solver used different ordering library: Metis, ParMetis and scotch and pt-scotch.
+
+
+1. SuperLU_DIST
+
+The interface of SuperLU_DIST with freefem++ was tested with the version 3.2 of SuperLU_DIST. This solver use the external ordering libraries: Metis and ParMetis. To used these ordering or parallel symbolic factorization (which depend on ParMetis) in SuperLU_DIST, we need to install them. In the section ordering library, a description of installation of Metis and ParMetis is given.  
+
+pre-requirement: 
+	- Metis and ParMetis ordering libraries 
+
+installation procedure:
+	-  install Metis and ParMetis (see section ordering library for more details)
+	-  donwload the SuperLU_DIST 3.2 package on the web site http://crd.lbl.gov/~xiaoye/SuperLU
+	-  untar and decompress the tar.gz file
+				tar xvfz superlu_dist_2.3.tar.gz
+	-  go to the directory SuperLU_DIST_3.2
+	-  edit the make.inc to yours system (see the README file in this directory for more details)  
+	-  compilation can be done by simply typing "make"  on this directory.
+	
+ compilation of freefem++ load file of SuperLU_DIST (interface):
+	- go to the directory /src/solver/ on the tree of the source code of Freefem++
+	- edit the makefile-sparsesolver.inc
+	- type in this directory "make rslu_dist"(resp."make cslu_dist") to obtain dynamic library of the interface for real (resp. complex) arithmetic.  
+
+	
+References on SuperLU_DIST:
+
+[1] SuperLU_DIST: A Scalable Distributed-Memory Sparse Direct Solver for Unsymmetric Linear Systems. Xiaoye S.  Li and James W. Demmel. ACM Trans. on Math. Software, Vol. 29, No. 2, pp.110-140, 2003. 
+
+[2] Parallel Symbolic Factorization for Sparse LU with Static Pivoting. L. Grigori, J. Demmel and X.S. Li. SIAM J. Sci. Comp, Vol. 29, Issue 3, pp 1289--1314,  2007.
+
+2.  MUMPS
+
+MUMPS is a package writing in fortran 90. So we need a fortran compiler. The interface of MUMPS with freefem++ was tested with the version 4.8.3 and 4.8.4 of MUMPS. This solver use the external libraries: BLAS, BLACS, LAPACK, ScaLAPACK,  Metis, ParMetis and Scotch. BLAS and LAPACK are installed in most of system now. Therefore, we only describe BLACS and ScaLAPACK installations. BLAS, BLACS and LAPACK are libraries need by ScaLAPACK. Hence, we need to compile BLACS before.  A ScaLAPACK i [...]
+
+Pre-requirement:
+	- Fortran 90 compiler
+	- BLACS  (http://www.netlib.org/blacs/)
+	- LAPACK  (http://www.netlib.org/lapack/)
+	- SCALAPACK  (http://www.netlib.org/scalapack/)
+	- Metis and Scotch ordering (optional). It is recommended by the MUMPS team to have full possibility to ordering automatically.
+	
+Installation procedure for BLACS and ScaLAPACK:
+	a) installation of BLACS
+		
+		- download on the website http://www.netlib.org/blacs/ :  mpiblacs.tgz, mpiblacs-patch03.tgz and blacstester.tgz
+		- decompress all these file
+				tar -xvzf mpiblacs.tgz
+				tar -xvzf mpiblacs-patch03.tgz
+				tar -xvzf blacstester.tgz
+		- go to the directory BLACS.
+		- edit the Bmake.inc for yours system (some example of Bmake.inc is given in the directory BMAKES). Please refer to blacs_install.ps on the web site of BLACS for more information about this file.
+		- the installation can be done by typing "make mpi" in this directory.
+
+	b) installation of ScaLAPACK 
+		
+		- download the file "scalapack.tgz" on the website http://www.netlib.org/scalapack/.
+		- decompress this file 
+				tar -xvzf scalapack.tgz
+		- go to the directory's created scalapack-1.8.0
+		- edit the SLmake.inc for your system (some example of SLmake.inc is given in the directory INSTALL). Please refer to scalapack_install.ps on the web site of ScaLAPACK for more information about this file.
+		- the installation can be done by typing "make" in this directory.
+
+Installation procedure for MUMPS:
+	- install BLACS, SCALAPACK, Metis ordering(optional) and Scotch ordering (optional). Please see section ordering library for Metis and Scotch.
+	- go to website http://mumps.enseeiht.fr/  to fill the download request submission.
+	- decompress the tar.gz file.
+				tar -xvfz MUMPS_4.8.4.tar.gz
+	- go to the directory MUMPS_4.8.4.
+	- edit the Makefile.inc to yours system (see README file in this directory and example of Makefile.inc in the directory Make.inc).
+	- compilation can be done by simply "make" in this directory.
+
+Compilation of freefem++ load file of MUMPS(interface)
+
+	- go to the directory /src/solver/ on the tree of the source code of Freefem++.
+	- edit the makefile-sparsesolver.inc.
+	- type in this directory "make mumps" to obtain dynamic library of the interface.  
+
+References on MUMPS:
+
+[1]  P. R. Amestoy, I. S. Duff and J.-Y. L'Excellent. Multifrontal parallel ditributed symmetric and unsymmetric solvers, in Comput. Methods in Appl. Mech. Eng., 184, pp 501-520, 2000. 
+
+[2]  P. R. Amestoy, I. S. Duff, J. Koster and J.-Y. L'Excellent. A fully asynchronous multifrontal solver using distributed dynamic scheduling, SIAM J. Math. Anal. and Appl., Vol. 23(1), pp 15-41, 2001.  
+
+[3] P. R. Amestoy, A. Guermouche, J.-Y.L'Excellent and S. Pralet. Hybrid scheduling for the parallel solution of linear systems. Parallel Computing, Vol. 32(2), pp 136-156, 2006.
+
+3.  Pastix
+
+The interface of pastix with freefem++ was tested with the package pastix_release_2200.tar.bz2. The distributed matrix version of pastix is under developpement and some bug are not fixed in this release. The interface with distributed matrix version of pastix in Freefem++ is not given yet for this reason.
+
+Pre-requirement :
+	- Fortran 90 compiler
+	- Scotch or Metis ordering
+
+Procedure installation:
+	- install Scotch or Metis ordering
+	- download on the website  http://gforge.inria.fr/frs/?group_id=248 the pastix package.
+	- decompress the package  pastix_releas_***.
+	- go to the pastix directory's created. For package  pastix_release_2200.tar.bz2, this directory is pastix_release_2200.
+	- go to the directory src. Installation instruction are given in the file INSTALL.txt. 
+	- select the config file corresponding to your machine (these files are located in the directory config) and copy this file in the main src directory of pastix. For Mac, just type 
+				cp config/Mac.in config.in
+	(if there is not a config file corresponding copy one of them). 
+	- adapt the config.in to yours system. For freefem++ interface, the double precision support must be selected.  
+	- compile the Pastix library
+				make expor
+	- install the Pastix library
+				make install
+
+The header file and Pastix library are located in the directory pastix_release_2200/install for the package pastix_release_2200.tar.bz2. We have constructed interface for real and complex support. The header file and Pastix library are compile for one of these arithmetics (see the file config.in). A simple method to obtain these two arithmetics is to compile and install pastix in two different directory. 
+
+Compilation of freefem++ load file of pastix(interface)
+	
+	- go to the directory src/solver/ on the tree of the source code of Freefem++.
+	- edit the makefile makefile-sparsesolver.inc.
+	- type in this directory 
+			make rpastix		(real dynamic library)      
+			make cpastix 		(complex dynamic library)
+
+References on Pastix:
+
+[1] P. H�non, P.Ramet and J. Roman. PaStiX: A High-Performance Parallel Direct Solver for Sparse Symmetric Definite Systems. Parallel Computing, Vol. 28(2), pp. 301-321, 2002.
+ 
+B) Sparse Iterative Solver
+
+under construction
+
+C) Ordering 
+
+1. Metis and ParMetis
+
+The Metis Library is include in ParMetis package. Hence, we only need to build ParMetis. To install ParMetis,  download on the web site http://glaros.dtc.umn.edu/gkhome/metis/parmetis/download the file ParMetis-3.1.1. After this, read installation instuction on this web page to obtain ParMetis's library. 
+
+References on Metis and ParMetis:
+
+[1] G. Karypis and V. Kumar. A fast and Highly Quality Multilevel Scheme for Partitioning Irregular Graphs. SIAM J. Sci. Comp., Vol. 20(1), pp. 359 - 392, 1999.
+
+[2] G. Karypis and V. Kumar. A Parallel Algorithm for Multilevel Graph Partitioning and Sparse Matrix Ordering. Journal of Parallel and Distributed Computing. Vol. 48, pp. 71-85, 1998.
+
+2. Scotch and Pt-Scotch
+
+Scotch and Pt-Scotch are include in the same package. This file can be download on http://www.labri.fr/perso/pelegrin/scotch/. We must take the version of Scotch with interface for mumps. This file is named scotch_*.*.*_esmumps.tar.gz where *.*.* is the number of version of scotch. After decompress this file  tar -xvfz scotch_*.*.*_esmumps.tar.gz. Go to the new directory named scotch_*.*_esmumps.  Go to the src directory and edit makefile.inc to your system.  The instruction for fill thi [...]
+
+References on Scotch and Pt-Scotch:
+
+[1]  C. Chevalier and F. Pellegrini,  PT-SCOTCH: a tool for efficient parallel graph ordering. Parallel Computing, 34(6-8), pp. 318-331, 2008.
+
+[2] F. Pellegrini and J. Roman, SCOTCH: a software package for static mapping by dual recursive bipartitioning of process and architecture graphs. In: Proc. HPCN'96, Brussels. 
+LNCS, Vol  1067, pp 493-498, 1996.
+
diff --git a/src/solver/complex_SuperLU_DIST_FreeFem.cpp b/src/solver/complex_SuperLU_DIST_FreeFem.cpp
new file mode 100644
index 0000000..314a509
--- /dev/null
+++ b/src/solver/complex_SuperLU_DIST_FreeFem.cpp
@@ -0,0 +1,825 @@
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep: superlu_dist parmetis metis  blas 
+//ff-c++-cpp-dep: 
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+/*
+  Interface freefem++ et SuperLU_DIST_2.3 
+
+  /bin/sh ff-mpic++ zSuperLU_DIST.cpp -I/Users/morice/librairie/SuperLU_DIST_2.3/SRC/ -L/Users/morice/librairie/openmpi/lib/ -lmpi -lopen-pal -lopen-rte -L/Users/morice/librairie/PATCHVECLIB/ -lwrapperdotblas -framework veclib -L/Users/morice/librairie/ParMetis-3.1/ -lparmetis -lmetis -L/Users/morice/librairie/SuperLU_DIST_2.3/lib/ -lsuperlu_dist_2.3
+
+*/
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "mpi.h"
+#include "superlu_zdefs.h"
+#include "ffsuperludistoption.hpp"
+
+
+template <class R> struct SuperLUmpiDISTDriver
+{
+    
+};
+template <> struct SuperLUmpiDISTDriver<Complex>
+{
+  /* Driver routines */
+   /* Driver routines */
+  static  Dtype_t R_SLU_T() { return SLU_Z;} 
+  static doublecomplex *dc(Complex *p)  { return (doublecomplex *) (void *) p;}
+  static doublecomplex **dc(Complex **p)  { return (doublecomplex **) (void *) p;}
+
+  // Remplacement doublecomplex par Complex
+  static void
+  pgssvx(superlu_options_t *p1, SuperMatrix *p2, 
+	  ScalePermstruct_t *p3,
+	  Complex *p4, int p5, int p6, gridinfo_t *p7,
+	  LUstruct_t *p8, SOLVEstruct_t *p9, double *p10,
+	  SuperLUStat_t *p11, int *p12)
+  {
+     pzgssvx( p1,p2,p3,
+	      dc(p4),p5,p6,p7,p8,p9,p10,p11,p12 );
+  }
+    
+  static void
+  pgssvx_ABglobal(superlu_options_t *p1, SuperMatrix *p2, 
+		  ScalePermstruct_t *p3, 
+		  Complex *p4, int p5, int p6, gridinfo_t *p7,
+		  LUstruct_t *p8, double *p9,
+		  SuperLUStat_t *p10, int *p11)
+   
+  {
+    pzgssvx_ABglobal( p1,p2,p3,
+		      dc(p4),p5,p6,p7,p8,p9,p10,p11 );
+  }
+
+
+  static void
+  Create_CompCol_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+			      Complex *p5, int_t *p6, int_t *p7,
+			      Stype_t p8, Dtype_t p9, Mtype_t p10)
+  {
+    zCreate_CompCol_Matrix_dist( p1,p2,p3,
+				 p4,dc(p5),p6,p7,p8,p9,p10 );
+  }
+
+  static  void
+  Create_CompRowLoc_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3,
+				 int_t p4, int_t p5, int_t p6,
+				 Complex *p7, int_t *p8, int_t *p9,
+				 Stype_t p10, Dtype_t p11, Mtype_t p12)
+  {
+    zCreate_CompRowLoc_Matrix_dist( p1,p2,p3,
+				    p4,p5,p6,dc(p7),p8,p9,p10,p11,p12 );
+  }
+
+  static  void
+  CompRow_to_CompCol_dist(int_t p1, int_t p2, int_t p3, 
+			   Complex *p4, int_t *p5, int_t *p6,
+			   Complex **p7, int_t **p8, int_t **p9)
+  {
+    zCompRow_to_CompCol_dist( p1,p2,p3,
+			      dc(p4),p5,p6,dc(p7),p8,p9 );
+  }
+
+
+  static void
+  Create_Dense_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, Complex *p4,
+			  int_t p5, Stype_t p6, Dtype_t p7,Mtype_t p8)
+  {
+     zCreate_Dense_Matrix_dist( p1,p2,p3,
+				dc(p4),p5,p6,p7,p8  );
+  }
+
+
+
+  static void
+  Create_SuperNode_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+			       Complex *p5, int_t *p6,
+			       int_t *p7, int_t *p8,
+			       int_t *p9, int_t *p10,
+			       Stype_t p11, Dtype_t p12, Mtype_t p13)
+  {
+    zCreate_SuperNode_Matrix_dist( p1,p2,p3,
+				   p4,dc(p5),p6,p7,p8,p9,p10,p11,p12,p13 );
+  }
+  
+  static void
+  Print_CompRowLoc_Matrix_dist(SuperMatrix *p1)
+  {
+    zPrint_CompRowLoc_Matrix_dist(p1);
+  }
+
+
+};
+
+template<class R>
+class ZSolveSuperLUmpi :   public MatriceMorse<R>::VirtualSolver, public SuperLUmpiDISTDriver<R>   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+   
+   
+  //mutable char           equed[1];
+  //yes_no_t       equil;
+  mutable SuperMatrix    A;
+  NCformat       *Astore;
+  //NCformat       *Ustore;
+  //SCformat       *Lstore;
+
+  mutable superlu_options_t options;
+  mutable mem_usage_t    mem_usage;
+  mutable ScalePermstruct_t ScalePermstruct;
+  mutable LUstruct_t        LUstruct;
+  mutable SOLVEstruct_t     SOLVEstruct;
+  mutable gridinfo_t        grid;
+
+  string string_option;
+  string data_option;
+  R             *a;
+  int           *asub, *xa;
+  int_t m, n, nnz;
+  // rajout pour //
+  int_t nprow,npcol;  /* process rows and process columns*/
+
+
+  int matrixdist; // type of distributed matrix
+  MPI_Comm commworld ;
+
+  static const int assembled =0;
+  static const int distributedglobal =1;
+  static const int distributed =2;
+
+public:
+  ZSolveSuperLUmpi(const MatriceMorse<R> &AA,int strategy,double ttgv, double epsilon,
+		  double pivot,double pivot_sym, string datafile,
+		   string param_char, KN<long> &pperm_r, KN<long> &pperm_c, void * ccommworld=0 ) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),string_option(param_char),data_option(datafile),
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+    commworld = ccommworld ? *static_cast<MPI_Comm*>( ccommworld) : MPI_COMM_WORLD;    
+    
+    R*      B;
+    //R*      X;
+    SuperLUStat_t stat;
+    int            info, ldb, nrhs=0;
+    int            i;
+    double*        berr;
+    
+    int iam;
+
+    // Add for distributed matrix
+    int_t         m_loc, m_loc_fst, fst_row, nnz_loc, fst_nnz;
+    R             *aloc;
+    int           *asubloc, *xaloc;
+    // End Add for distributed matrix
+    
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+
+    A.Store=0;  
+    /* Defaults */
+    nrhs  = 0;
+
+    /* lecture de nprow and npcol */
+    // Cas max deux procs
+    nprow = 1;
+    npcol = 1;
+    matrixdist=0;
+    /* set the default options */
+    set_default_options_dist(&options);
+    DiagScale_t optionDiagScale;
+    
+    //if(verbosity > 10) print_options_dist(&options);
+
+    if(!string_option.empty()) read_nprow_npcol_freefem( &string_option, &nprow, &npcol, &matrixdist);
+    if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+
+    if(!data_option.empty()) read_options_superlu_datafile(&data_option,&options,&nprow, &npcol, &matrixdist,&optionDiagScale);
+
+    //if(verbosity > 10) print_options_dist(&options);
+    
+     /* ------------------------------------------------------------
+	 INITIALIZE THE SUPERLU PROCESS GRID. 
+	 ------------------------------------------------------------*/
+    cout << "Complex superlu_gridinit " << commworld << " "<< ccommworld << " : "  << nprow << "X" <<  npcol <<endl;
+    superlu_gridinit(commworld , nprow, npcol, &grid);
+    cout << " --\n";
+    /* Bail out if I do not belong in the grid. */
+    iam = grid.iam;
+    if ( iam >= nprow * npcol ){
+      //superlu_gridexit(&grid);
+      printf("this process is not used in superlu %d \n",iam);
+    }
+    else
+      {
+	// matrix to procs and vectors
+	if( matrixdist == assembled ){
+	  
+	  if(!iam){
+	    cout <<  "iam=" << iam << endl;
+	    printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	    
+	    /* create the matrix for superlu_dist */
+	    n=AA.n;
+	    m=AA.m;
+	    nnz=AA.nbcoef;
+	  
+	    assert( AA.lg[n] == nnz );	   
+	    printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	    
+	    /* transform Row to Col */
+	    // cela coute cher comme fonction //
+	    // dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    // dCompRow_to_CompCol_dist(m,n,nnz,arow,asubrow,xarow,&a,&asub,&xa);
+	    
+	    CompRow_to_CompCol_dist(m,n,nnz,AA.a,AA.cl,AA.lg,&a,&asub,&xa);
+	  
+	    /* Broadcast matrix A to the other PEs. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+
+	    MPI_Bcast( a,    nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );	    
+	    
+	  }
+	  else{
+	    /*
+	      printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	      /* Receive matrix A from PE 0. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    
+	    /* Allocate storage for compressed column representation. */
+	    zallocateA_dist(n, nnz, dc(&a), &asub, &xa);
+	    
+	    MPI_Bcast( a, nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	  }
+	  
+	  Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	  
+	  cout << "Debut: Create_CompCol_Matrix_dist" <<endl;
+	  Create_CompCol_Matrix_dist(&A, m, n, nnz, a, asub, xa, SLU_NC, R_SLU, SLU_GE);      
+	  cout << "Fin: Create_CompCol_Matrix_dist" <<endl;
+	  /* creation of pseudo solution + second member */
+	  
+	  if ( !(B = new Complex[m] ) ){
+	    //if ( !(B = doublecomplexMalloc_dist(m )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+
+	 
+// 	  /* set the default options */
+// 	  set_default_options_dist(&options);
+// 	  DiagScale_t optionDiagScale;
+// 	  if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	  
+	  /* Initialize ScalePermstruct and LUstruct. */
+	  ScalePermstructInit(m, n, &ScalePermstruct);
+	  if(!(pperm_r==NULL)  || !(pperm_c==NULL) ) ScalePermstruct.DiagScale=optionDiagScale;
+	  if( !(pperm_r==NULL) ) 
+	    for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[ii];
+	  if( !(pperm_c==NULL) )
+	    for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii]= pperm_c[ii];
+	  
+	  if( ScalePermstruct.DiagScale != NOEQUIL ){
+	    printf("FreeFem++ doesn't support change of the original matrix"); 
+	    exit(1);
+	  }
+	  LUstructInit(m, n, &LUstruct);
+	  
+	  /* Initialize the statistics variables. */
+	  PStatInit(&stat);
+	  
+	  ldb = m;
+	  nrhs=1;
+	  if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  berr[0]=0.;
+    	
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	
+	  /* INIT LU struct*/
+	  
+	  /* ONLY PERFORM THE LU DECOMPOSITION */
+	  //B.ncol = 0;  /* Indicate not to solve the system */
+	  
+	  nrhs=0;
+	  SuperLUmpiDISTDriver<R>::pgssvx_ABglobal(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					       &LUstruct, berr, &stat, &info);
+	
+	  if(verbosity)
+	    printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	  
+	  if ( verbosity) PStatPrint(&options,&stat,&grid);
+	  PStatFree(&stat);
+	  	 
+	}
+	//##########################################################
+	//
+	//       matrix distributed with matrix global given
+	//
+	//##########################################################
+	else if( matrixdist == distributedglobal) {
+	   if(!iam){
+
+	     printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	
+	     /* create the matrix for superlu_dist */
+	     n=AA.n;
+	     m=AA.m;
+	     nnz=AA.nbcoef;
+	     a=AA.a;
+	     asub=AA.cl;
+	     xa=AA.lg;
+	     
+	     xa[n] = nnz;
+	     printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	     
+	     /* Broadcast matrix A to the other PEs. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     MPI_Bcast( AA.a,    nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	     MPI_Bcast( AA.cl, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( AA.lg,   n+1, mpi_int_t,  0, grid.comm );
+	     
+	     
+	   }
+	   else
+	     {
+	     
+	     printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	     /* Receive matrix A from PE 0. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     /* Allocate storage for compressed column representation. */
+	     zallocateA_dist(n, nnz, dc(&a), &asub, &xa);
+	     
+	     MPI_Bcast( a, nnz, SuperLU_MPI_DOUBLE_COMPLEX, 0, grid.comm );
+	     MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+
+	   }
+	   
+	   /* Compute the number of rows to be distributed to local process */
+	   m_loc = m / (grid.nprow * grid.npcol); 
+	   m_loc_fst = m_loc;
+	   /* When m / procs is not an integer */
+	   if ((m_loc * grid.nprow * grid.npcol) != m) {
+	     /*m_loc = m_loc+1;
+	       m_loc_fst = m_loc;*/
+	     if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	       m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	   }
+	   
+	   fst_row = iam * m_loc_fst;
+	   
+	   nnz_loc = xa[fst_row+m_loc]-xa[fst_row];
+	   zallocateA_dist(m_loc, nnz_loc, dc(&aloc), &asubloc, &xaloc);
+	   
+	   //xaloc = (int_t*) intMalloc_dist(m_loc+1);
+	   for(int ii=0; ii < m_loc; ii++){
+	     xaloc[ii] = xa[fst_row+ii]-xa[fst_row];	
+	   }
+	   
+	   xaloc[m_loc]=nnz_loc;
+	   
+	   fst_nnz = xa[fst_row];
+	   //aloc    = new R[nnz_loc];
+	   //aloc    = (Complex*) doubleMalloc_dist(nnz_loc);
+	   //asubloc = (int_t*)  intMalloc_dist(nnz_loc);
+	   
+	   for(int ii=0; ii < nnz_loc; ii++){
+	     aloc[ii] = a[fst_nnz+ii];
+	     asubloc[ii] = asub[fst_nnz+ii];
+	   }
+	   
+	   if( iam ){
+	     SUPERLU_FREE( a );
+	     SUPERLU_FREE( asub );
+	     SUPERLU_FREE( xa );
+	   }
+	   
+	   Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	   
+	   if(verbosity) cout << "Debut: Create_CompRowCol_Matrix_dist" <<endl;
+	   if(verbosity) Create_CompRowLoc_Matrix_dist(&A, m, n, nnz_loc, m_loc, fst_row, aloc, asubloc, xaloc, SLU_NR_loc, R_SLU, SLU_GE);
+	   
+	   cout << "Fin: Create_CompRowCol_Matrix_dist" <<endl;
+	   /* creation of pseudo solution + second member */
+	   
+	   
+	   if ( !(B = new Complex[m_loc]) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   
+	   for(int ii=0; ii < m_loc; ii++){
+	     B[ii] = 1.; //BB[fst_row+ii];
+	   }
+     
+	   if(verbosity)
+	     printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   
+	   /* set the default options */
+	   set_default_options_dist(&options);
+	   DiagScale_t optionDiagScale;
+	   if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	   	   
+	   m=A.nrow;
+	   n=A.ncol;
+	   printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   /* Initialize ScalePermstruct and LUstruct. */
+	   ScalePermstructInit(m, n, &ScalePermstruct);
+	   if(pperm_r  ||  pperm_c ) ScalePermstruct.DiagScale=optionDiagScale;
+	   if(pperm_r) 
+	     for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[fst_row+ii];
+	   if(pperm_c) 
+	     for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii] = pperm_c[ii];
+	   
+	   LUstructInit(m, n, &LUstruct);
+	   
+
+
+	   /* Initialize the statistics variables. */
+	   PStatInit(&stat);
+	   
+	   ldb = m_loc;
+	   //ldx = m_loc;
+	   
+	   nrhs=1;
+	   if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   berr[0]=0.;
+	   
+	   /* ONLY PERFORM THE LU DECOMPOSITION */
+    
+	   nrhs=0;
+	   SuperLUmpiDISTDriver<R>::pgssvx(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					   &LUstruct, &SOLVEstruct, berr, &stat, &info);
+	   
+	   if(verbosity)
+	     printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	   
+	   if ( verbosity) PStatPrint(&options,&stat,&grid);
+	   PStatFree(&stat);
+	}
+	else if( matrixdist == distributed) {
+	  printf("in construction\n");
+	  exit(1);
+	}
+	else{
+	  printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	  exit(1);
+	}
+	
+	delete [] B;
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	nrhs=1;
+	SUPERLU_FREE(berr);  	
+
+	if(iam==0){
+	  finishtime = clock();
+	  timeused= (finishtime-starttime)/(1000 );
+	  printf("=====================================================\n");
+	  cout << "SuperLU_DIST : time factorisation :: " << timeused << " ms" <<endl;
+	  printf("=====================================================\n");
+	}
+	 
+      }
+  }
+
+  void Solver(const MatriceMorse<R> &AA,KN_<R> &x,const KN_<R> &b) const  {
+    R*        B;
+    SuperLUStat_t  stat;
+    int            iam;
+    int            info=0, ldb=m, nrhs=1;
+    int            i;
+    double*        berr;
+    double         ferr; 
+    double         rpg, rcond;
+      
+    int_t    m_loc,m_loc_fst,fst_row;
+    
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+
+    iam = grid.iam;
+    if( iam < nprow*npcol){
+
+      if(verbosity) starttime = clock();
+
+      if(n != m) exit(1);
+      
+      ffassert ( &x[0] != &b[0]);
+      epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+      
+      Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+      nrhs= 1;
+      
+      
+      /* Initialize the statistics variables. */
+      PStatInit(&stat);
+      
+      /* cas matrix assembled */ 
+      if( matrixdist == assembled ){
+      
+      if( !(B = new R[m*nrhs] ) ){
+	printf("probleme d allocation\n");
+	exit(1);
+	}
+	
+	for(int ii=0; ii<n; ii++){
+	  B[ii]=b[ii];
+	}
+	
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */   
+	ldb = m;
+	//nrhs= 1;
+	SuperLUmpiDISTDriver<R>::pgssvx_ABglobal (&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+						  &LUstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if(verbosity) PStatPrint(&options, &stat, &grid);   
+	
+	for(int ii=0; ii<n; ii++){
+	  x[ii] = B[ii]; 
+	}
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+      }
+      else if( matrixdist == distributedglobal) {
+	R*    xtemp;
+	iam = grid.iam;
+	/* Compute the number of rows to be distributed to local process */
+	m_loc = m / (grid.nprow * grid.npcol); 
+	m_loc_fst = m_loc;
+	/* When m / procs is not an integer */
+	if ((m_loc * grid.nprow * grid.npcol) != m) {
+	  /*m_loc = m_loc+1;
+	    m_loc_fst = m_loc;*/
+	  if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	    m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	}
+	
+	fst_row = iam * m_loc_fst;
+	
+	if ( !(B = new R[m_loc] ) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	//printf("initilisation B:");
+	for(int ii=0; ii<m_loc; ++ii){
+	  B[ii] = b[ii+fst_row];
+	  //printf("  B[%d]= %f  ",ii,B[ii]);
+	}
+	//printf(" :: fin \n");
+	//fflush(stdout);
+	
+      
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	//options.Equil = YES;
+	//options.Trans = TRANS;
+	
+	
+	ldb = m;
+	SuperLUmpiDISTDriver<R>::pgssvx(&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+					&LUstruct, &SOLVEstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if ( !(xtemp = new R[AA.n]) ){
+	  printf("probleme d allocation de xtemp\n");
+	  exit(1);
+	}
+	
+      
+	int disp[nprow*npcol];
+	MPI_Allgather(&fst_row, 1, MPI_INT, disp, 1, MPI_INT, grid.comm);
+	
+	int recv[nprow*npcol];
+	MPI_Allgather(&m_loc, 1, MPI_INT, recv, 1, MPI_INT, grid.comm);
+	
+	MPI_Allgatherv(B, m_loc, SuperLU_MPI_DOUBLE_COMPLEX, xtemp, recv, disp, SuperLU_MPI_DOUBLE_COMPLEX, grid.comm);
+	
+	for(int ii= 0; ii< AA.n ; ii++)
+	  x[ii] = xtemp[ii];
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+	delete [] xtemp;
+      
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+      
+
+      delete [] B;
+      SUPERLU_FREE( berr );
+      
+      PStatFree(&stat);
+
+      if(iam==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << " SuperLU_DIST : time solve  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+    }
+  }
+    
+  ~ZSolveSuperLUmpi() { 
+    int iam;
+    iam = grid.iam;
+    if(iam < nprow*npcol){
+      if(verbosity)
+	cout << "~SolveSuperLUmpi Complex:" << endl;
+      
+      if( matrixdist == assembled) {
+	//if( A.Store)  Destroy_CompCol_Matrix_dist(&A);
+	//if( L.Store && U.Store )  {
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	//}
+	if ( options.SolveInitialized ) {
+	  zSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributedglobal) {
+	if( A.Store)  Destroy_CompRowLoc_Matrix_dist(&A);
+	
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	
+	if ( options.SolveInitialized ) {
+	  zSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+    }
+    printf("superlu_gridexit(&grid), %d\n",iam);
+    superlu_gridexit(&grid); 
+   
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+
+
+MatriceMorse<Complex>::VirtualSolver *
+BuildSolverSuperLUmpi(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+  if(verbosity>9)
+      cout << " BuildSolverSuperLUmpi<double>" << endl;
+  return new ZSolveSuperLUmpi<Complex>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym,
+				       ds.data_filename, ds.sparams, ds.perm_r, ds.perm_c);
+}
+
+
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+//DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    //DefSparseSolver<double>::solver =SparseMatSolver_R;
+    DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+}
+
+bool SetSuperLUmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to SuperLUmpi double" << endl;
+    //DefSparseSolver<double>::solver  =BuildSolverSuperLUmpi;
+    DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+}
+
+
+
+Init init;
+Init::Init()
+{ 
+  
+  //SparseMatSolver_R= DefSparseSolver<double>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: Complex SuperLU_DIST,  defaultsolver defaultsolverSuperLUdist" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  //DefSparseSolver<double>::solver =BuildSolverSuperLUmpi;
+  DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("complexdefaulttoSuperLUdist","(",new OneOperator0<bool>(SetSuperLUmpi));
+}
+
diff --git a/src/solver/complex_pastix_FreeFem.cpp b/src/solver/complex_pastix_FreeFem.cpp
new file mode 100644
index 0000000..dc18519
--- /dev/null
+++ b/src/solver/complex_pastix_FreeFem.cpp
@@ -0,0 +1,705 @@
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+/*
+  Interface entre freefem++ et pastix
+*/
+#include  <iostream>
+using namespace std;
+   
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+#include <mpi.h>
+
+// #include <ctype.h>
+// #include <stdio.h>
+// #include <stdlib.h>
+// #include <unistd.h>
+// //#include <pthread.h>
+// #include <string.h>
+// #include <time.h>
+// #include <sys/time.h>
+// #include "mpi.h"
+   
+// #include <assert.h>
+// #include "pastix.h"
+// #include "cscd_utils.h"
+// #include "read_matrix.h"
+
+#include <assert.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "pastix.h"
+#include "cscd_utils.h"
+#ifdef __cplusplus
+}
+#endif
+//#include "read_matrix.h"
+
+#undef memFree_null
+#define memFree_null(x) {if (x ==NULL) {fprintf(stdout,"%s:%d freeing NULL\n",__FILE__,__LINE__);} free(x); x=NULL;}
+
+#define STR_SIZE 256
+
+static pastix_int_t * pastixint(int * ii){ return (pastix_int_t*) (void *) ii;} 
+static pastix_float_t * pastixfloat(Complex * ii){ return (pastix_float_t*) (void *) ii;} 
+
+typedef struct pastix_param {
+  pastix_data_t          *pastix_data; /*Pointer used by PaStiX to keep information alive between calls */
+  MPI_Comm                comm;        /* Communicator used by PaStiX                                    */
+  pastix_int_t            Ncol;        /* Size of the Matrix                                             */
+  pastix_int_t           *ia;          /* Index of first element of each column in ja and avals          */  
+  pastix_int_t           *ja;          /* Rows of the unknows of the matrix                              */
+  pastix_float_t         *avals;       /* Values of the matrix                                           */
+  pastix_int_t           *perm;        /* Permutation used for re-numbering of the unknowns              */
+  pastix_int_t           *invp;        /* Inverse permutation                                            */
+  pastix_float_t         *rhs;         /* Right hand side                                                */
+  pastix_int_t           *iparm;       /* Integer parameters                                             */
+  double                 *dparm;       /* Floating parameters                                            */
+} pastix_param_t;
+
+
+
+void
+Morse_to_CSC(int m, int n, int nnz, 
+	     Complex *a, int *colind, int  *rowptr,
+	     pastix_float_t **at, pastix_int_t **rowind, 
+	     pastix_int_t **colptr)
+{
+    register int i, j, col, relpos;
+    pastix_int_t *marker;
+
+    /* Allocate storage for another copy of the matrix. */
+    *at     = (pastix_float_t *) malloc(sizeof(pastix_float_t)*nnz);
+    *rowind = (pastix_int_t *) malloc(sizeof(pastix_int_t)*nnz);
+    *colptr = (pastix_int_t *) malloc(sizeof(pastix_int_t)*(n+1));
+    marker  = (pastix_int_t *) malloc(sizeof(pastix_int_t)*n);
+    
+    for (i = 0; i < n; ++i)
+      marker[i] = 0;
+    /* Get counts of each column of A, and set up column pointers */
+    for (i = 0; i < m; ++i)
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) ++marker[colind[j]];
+    (*colptr)[0] = 0;
+    for (j = 0; j < n; ++j) {
+	(*colptr)[j+1] = (*colptr)[j] + marker[j];
+	marker[j] = (*colptr)[j];
+    }
+
+    /* Transfer the matrix into the compressed column storage. */
+    for (i = 0; i < m; ++i) {
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) {
+	    col = colind[j];
+	    relpos = marker[col];
+	    (*rowind)[relpos] = i;
+	    (*at)[relpos] = a[j];
+	    ++marker[col];
+	}
+    }
+
+    free(marker);
+}
+
+
+
+static const int MAX_CHAR_PER_LINE=256;
+//void read_datafile_pastixff(const string &datafile, pastix_int_t *iparmtab, double *dparmtab){
+void read_datafile_pastixff(const string &datafile, int &mpi_flag, pastix_int_t *iparmtab, double *dparmtab){
+  FILE*   m_File;
+  int     i = 0;
+  char    szbuff[MAX_CHAR_PER_LINE];
+  char*   token;
+
+  char filename[datafile.size()+1];  
+  strcpy( filename, datafile.c_str()); 
+
+  m_File = fopen(filename,"rt");
+
+  if(!m_File)
+    {
+      printf("error in reading filename %s\n",&filename);
+    }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  
+  if( !(strcmp(token,"matrix") == 0) ){
+    printf("freefem++: error in reading matrix parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading matrix parameter for pastix \n");    
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+  
+  if(strcmp(token,"assembled") == 0)
+    mpi_flag = 0;
+  else if(strcmp(token,"distributedglobal") == 0) 
+    mpi_flag = 1;
+  else if(strcmp(token,"distributed") == 0) 
+    mpi_flag = 2;
+  else{
+    printf("value of parameter matrix is not correct %s \n", token );
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  if( !(strcmp(token,"iparm") == 0) ){
+    printf("freefem++: error in reading iparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading iparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      iparmtab[i] = (pastix_int_t)atol(token);
+      i++;
+    }
+
+  i=0;
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");  
+  if( !(strcmp(token,"dparm") == 0) ){
+    printf("freefem++: error in reading dparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading dparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      dparmtab[i] = atof(token);
+      i++;
+    }
+ 
+  fclose(m_File);
+
+#ifdef OOC
+/*   if (iparmtab[IPARM_OOC_THREAD] > 1) */
+    iparmtab[IPARM_OOC_THREAD] = 1;
+#endif
+  /* On empeche le 2d avec NUMA_ALLOC */
+#ifdef NUMA_ALLOC
+  if (iparmtab[IPARM_DISTRIBUTION_LEVEL] != 0)
+    {
+      errorPrint("2D not available with NUMA allocation\n");
+      exit(-1);
+    }
+#endif
+}
+
+// ATTENTION :: pastix_float_t  
+//      peut �tre soit un complex ou un reel cela depend de la maniere dont on a compiler pastix
+
+// CAS COMPLEX SEULEMENT 
+
+
+class zSolvepastixmpi :   public MatriceMorse<Complex>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  
+
+  int paraoption;
+  int myid, mpi_size;
+  int Nrow;
+  int mpi_flag;
+  int init_raff;
+  int thrd_flag;
+  int SYM;
+  
+  string data_option;
+  
+  mutable pastix_int_t    iparm[64];
+  mutable double          dparm[64];
+  mutable pastix_int_t    Ncol;
+  mutable pastix_int_t   *ia;
+  mutable pastix_int_t   *ja;
+  mutable pastix_float_t *avals;
+  mutable pastix_int_t   *loc2glob;
+  //char           *Type    = NULL;
+  //char           *RhsType = NULL;
+  mutable pastix_float_t *rhs;
+  mutable pastix_int_t   *perm;
+  mutable pastix_int_t   *invp;
+  mutable pastix_data_t  *pastix_data;
+  
+
+public:
+
+  zSolvepastixmpi(const MatriceMorse<Complex> &AA,int strategy,double ttgv, double epsilon,
+		  double pivot,double pivot_sym, string datafile, KN<long> &param_int, KN<double> &param_double, 
+		  KN<long> &pperm_r, KN<long> &pperm_c) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),tol_pivot_sym(pivot_sym),tol_pivot(pivot),
+    data_option(datafile) 
+  { 
+    //KN_<long> param_int(pparam_int);
+    //KN_<double> param_double(pparam_double);
+
+    //int m;
+    //int ierr;
+    struct timeval  tv1, tv2;
+    int nnz;
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+
+    ia    = NULL;
+    ja    = NULL;
+    avals   = NULL;
+    loc2glob = NULL;
+    rhs     = NULL;
+    pastix_data = NULL;
+    
+    // matrix assembled on host
+    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
+    printf("- Rang MPI : %d\n", myid);
+    MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
+    // SYMETRIQUE
+    // MPI_flag need to unselect for non distributed matrix
+    mpi_flag  = 0;
+    thrd_flag = 0;
+
+    // ######################  
+    //pastix_int_t init_raff;
+    fprintf(stdout,"-- INIT PARAMETERS --\n");
+    
+    // reading iparm from array    
+    if(!data_option.empty()){
+      read_datafile_pastixff(data_option,mpi_flag,iparm,dparm);
+      if(mpi_flag != 0) 
+	cerr << "ERROR :: GLOBAT INPUT MATRIX FOR ALL PROCS  matrix=assembled" << endl;
+    }
+    else if( !(param_int==NULL) || !(param_double==NULL)){
+	if( ! (param_int==NULL) ) 
+      {
+	cout << "internal param_int" << endl;
+	assert(param_int.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  iparm[ii] = param_int[ii];
+	iparm[IPARM_MODIFY_PARAMETER] = API_YES;
+      }
+	if( !(param_double==NULL) ) 
+      {
+	cout << "internal param_double" << endl;
+	assert(param_double.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  dparm[ii] = param_double[ii];
+      }
+    }  
+    else{
+      iparm[IPARM_MODIFY_PARAMETER] = API_NO;
+      cout << "initialize default parameter" << endl;
+    }
+    
+    //################################
+    if(myid == 0){
+      Ncol = AA.m;
+      Nrow = AA.n;
+      nnz  = AA.nbcoef;
+      // Avant : on ecrit la transpos�e
+      
+      // AA.cl : indices des colonnes
+      // AA.lg : pointeurs des lignes
+      Morse_to_CSC( AA.n , AA.m, AA.nbcoef, AA.a, AA.cl, AA.lg, &avals, &ja, &ia);
+      // ia : pointeurs des colonnes
+      // ja : indices des lignes
+      
+      cout << "AA.n= "<< AA.n << " AA.m=" <<  AA.m << " AA.nbcoef=" << AA.nbcoef << endl;
+      
+      for(int ii=0; ii < Ncol+1; ii++){
+	ia[ii] = ia[ii]+1;
+      }
+      assert( ia[Ncol]-1 == AA.nbcoef );
+      for(int ii=0; ii < ia[Ncol]-1; ii++){
+	ja[ii] = ja[ii]+1; 
+      }
+      MPI_Bcast( &Ncol,   1,    MPI_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast( &Nrow,   1,    MPI_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast( &nnz,    1,    MPI_INT,   0, MPI_COMM_WORLD );
+
+      MPI_Bcast( avals, nnz,    MPI_PASTIX_FLOAT, 0, MPI_COMM_WORLD );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+    }
+    else{
+      MPI_Bcast( &Ncol, 1,        MPI_INT,  0, MPI_COMM_WORLD );
+      MPI_Bcast( &Nrow, 1,        MPI_INT,  0, MPI_COMM_WORLD );
+      MPI_Bcast( &nnz,  1,        MPI_INT,  0, MPI_COMM_WORLD );
+      
+      avals = (pastix_float_t *) malloc( nnz*sizeof(pastix_float_t) );
+      ia = (pastix_int_t *) malloc( (Ncol+1)*sizeof(pastix_int_t) );
+      ja = (pastix_int_t *) malloc( nnz*sizeof(pastix_int_t) );
+
+      MPI_Bcast( avals, nnz,  MPI_PASTIX_FLOAT,   0, MPI_COMM_WORLD );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+    }
+
+    perm = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    invp = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    
+    rhs = (pastix_float_t *) malloc(Ncol*sizeof(pastix_float_t));
+    
+    // reading permutation given by the user
+    if(pperm_r) 
+      for(int ii=0; ii < Ncol; ii++)
+	perm[ii] = pperm_r[ii];
+    if(pperm_c)  
+      for(int ii=0; ii < Ncol; ii++)
+	invp[ii] = pperm_c[ii];
+   
+  
+    iparm[IPARM_START_TASK] = API_TASK_INIT;
+    iparm[IPARM_END_TASK]   = API_TASK_INIT;
+    iparm[IPARM_SYM] = API_SYM_NO; // Matrix is considered nonsymetric    
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm); 
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    fprintf(stdout,"-- FIN INIT PARAMETERS --\n");
+    init_raff = iparm[IPARM_ITERMAX];
+    cout << "init_raff=" << init_raff << endl;
+    fflush(stdout);
+    /* Passage en mode verbose */
+    
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    if( (param_int==NULL) && data_option.empty() ){
+      iparm[IPARM_MATRIX_VERIFICATION] = API_YES;
+      iparm[IPARM_REFINEMENT] = API_RAF_GMRES;
+      iparm[IPARM_INCOMPLETE] = API_NO;
+    }
+
+    if( (param_double==NULL) && data_option.empty()){
+      dparm[DPARM_EPSILON_REFINEMENT] = 1e-12;
+      dparm[DPARM_EPSILON_MAGN_CTRL] = 1e-32;
+    }
+
+  
+ //    cscd_checksym(Ncol, ia, ja, loc2glob, MPI_COMM_WORLD);
+    
+//     if (iparm[IPARM_SYM]==API_SYM_YES)
+//       {
+// 	/* Symetric problem */
+// 	/* Build non oriented graph */
+// 	/* build non symmetric csc from symmetric csc */
+// 	/*maillage global*/
+// 	INT *tmpia;
+// 	INT *tmpja;
+// 	INT  tmpn;
+	
+// 	cscd_symgraph_int(*n2,   *col2,  *row2 , NULL,
+// 			  &tmpn, &tmpia, &tmpja, NULL,
+// 			  *loc2glob2, pastix_comm, API_YES);
+	
+// 	memFree_null(*col2);
+// 	*col2 = tmpia;
+// 	memFree_null(*row2);
+// 	*row2 = tmpja;
+// 	*n2   = tmpn;
+//       }
+    
+
+    SYM = AA.symetrique; 
+    cout << "SYM = "<< SYM << endl;
+    // SYMETRIQUE
+    if( SYM == 1 ){
+      iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    
+    /* Scotch */
+    fprintf(stdout,"-- Scotch --\n");
+    fflush(stdout);
+    iparm[IPARM_START_TASK] = API_TASK_ORDERING;
+    iparm[IPARM_END_TASK]   = API_TASK_ORDERING; 
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl;  
+    iparm[IPARM_SYM] = API_SYM_NO;
+    /* Fax */
+    fprintf(stdout,"-- Fax --\n");
+    iparm[IPARM_START_TASK] = API_TASK_SYMBFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_SYMBFACT;
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    /* Blend */
+    fprintf(stdout,"-- Blend --\n");
+    iparm[IPARM_START_TASK] = API_TASK_ANALYSE;
+    iparm[IPARM_END_TASK]   = API_TASK_ANALYSE;
+    if( SYM == 1 ){
+      iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+   
+    /* Factorisation */
+    iparm[IPARM_START_TASK] = API_TASK_NUMFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_NUMFACT;
+    gettimeofday(&tv1, NULL);
+    fprintf(stdout,"-- SOPALIN --\n");
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+       cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call factorization : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+    
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    
+    //for(int ii=0; ii < ia[Ncol]-1; ii++)
+    //  ja[ii] = ja[ii]-1;
+
+    if(myid==0){
+      finishtime = clock();
+      timeused= (finishtime-starttime)/(1000 );
+      printf("=====================================================\n");
+      cout << " pastix : time factorization  :: " << timeused << " ms" <<endl;
+      printf("=====================================================\n");
+    }
+
+    
+  }
+  void Solver(const MatriceMorse<Complex> &AA,KN_<Complex> &x,const KN_<Complex> &b) const  {
+  
+    struct timeval  tv1, tv2;
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+    
+    // index for pastix    
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]+1;
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]+1;
+    
+    
+    // give value of the second member
+    for(int ii=0; ii < Ncol; ii++){
+      rhs[ii] = b[ii];  
+    }
+    
+  
+
+
+    //fprintf(stdout,"SOLVE STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    
+    /* updo */
+    iparm[IPARM_START_TASK] = API_TASK_SOLVE;
+    iparm[IPARM_END_TASK]   = API_TASK_SOLVE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call updown : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));    
+    
+    if(verbosity > 1)
+      for(int jj=0; jj < Ncol; jj++)
+	cout << "rhs["<< jj << "]=" << rhs[jj] << endl;
+    
+    
+    //fprintf(stdout,"RAFF STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    /* raff */
+    
+    
+    iparm[IPARM_START_TASK] = API_TASK_REFINE;
+    iparm[IPARM_END_TASK]   = API_TASK_REFINE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    iparm[IPARM_ITERMAX]    = init_raff;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call refinement : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+
+    
+    for(int ii=0; ii < Ncol; ii++)
+      x[ii] = rhs[ii];
+       
+    // index for freefem
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    
+    //for(int ii=0; ii < ia[Ncol]-1; ii++)
+    //  ja[ii] = ja[ii]-1;
+
+    if(myid==0){
+      finishtime = clock();
+      timeused= (finishtime-starttime)/(1000 );
+      printf("=====================================================\n");
+      cout << " pastix : time solve  :: " << timeused << " ms" <<endl;
+      printf("=====================================================\n");
+    }
+    
+    
+  }
+
+  ~zSolvepastixmpi(){
+    /* mem free */
+    iparm[IPARM_START_TASK] = API_TASK_CLEAN;
+    iparm[IPARM_END_TASK]   = API_TASK_CLEAN;
+    
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+   
+    memFree_null(ia);
+    memFree_null(ja);
+    
+    /* Free mem no longer necessary */
+    memFree_null(perm);
+    memFree_null(rhs);
+    
+  }
+  
+  void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+
+};
+
+MatriceMorse<Complex>::VirtualSolver *
+BuildSolverpastix_complex_mpi(DCL_ARG_SPARSE_SOLVER(Complex,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverpastix_complex_mpi<complex>" << endl;
+    return new zSolvepastixmpi(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym, ds.data_filename, 
+			       ds.lparams, ds.dparams, ds.perm_r, ds.perm_c);
+}
+
+
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+//DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    //DefSparseSolver<double>::solver =SparseMatSolver_R;
+    DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+}
+
+bool Setpastixmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to pastixmpi" << endl;
+    //DefSparseSolver<double>::solver  =BuildSolverpastix_complex_mpi;
+    DefSparseSolver<Complex>::solver =BuildSolverpastix_complex_mpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+}
+
+
+
+Init init;
+Init::Init()
+{ 
+  
+  //SparseMatSolver_R= DefSparseSolver<d>::solver;
+  SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: pastix,  defaultsolver defaultsolverpastix" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  //DefSparseSolver<double>::solver =BuildSolverpastix_complex_mpi;
+  DefSparseSolver<Complex>::solver =BuildSolverpastix_complex_mpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("complexdefaulttopastix","(",new OneOperator0<bool>(Setpastixmpi));
+}
diff --git a/src/solver/ffsuperludistoption.hpp b/src/solver/ffsuperludistoption.hpp
new file mode 100644
index 0000000..7201c93
--- /dev/null
+++ b/src/solver/ffsuperludistoption.hpp
@@ -0,0 +1,544 @@
+// read options for superlu in freefem++
+int s_(char* str, const char* cmp[])
+{
+  int i = 0;
+  while( cmp[i] != 0){
+    if( strcmp(str, cmp[i]) == 0){
+      //cout << *str << " return" << i << endl;
+      return i+1 ;
+    }
+    i++;
+  }
+  //cout << *str << " return 0" << endl;
+  return 0;
+}
+
+void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol){
+  
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+  
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2 = tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 13: // nprow
+	*nprow = atoi(tictac);
+	break;
+      case 14: // npcol 
+	*npcol = atoi(tictac);
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+	    exit(1);
+	  }	  
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+}
+
+void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol, int *matrixdist){
+  
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol","matrix",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+  
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2 = tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+    printf("param %s = value %s , id_option %d\n",tictac2,tictac,id_option);
+    switch (id_option)
+      { 
+      case 13: // nprow
+	*nprow = atoi(tictac);
+	break;
+      case 14: // npcol 
+	*npcol = atoi(tictac);
+	break;
+      case 15: // matrix
+	printf("parameter matrix \n");
+	if(strcmp(tictac,"assembled") == 0)
+	  *matrixdist = 0;
+	else if(strcmp(tictac,"distributedglobal") == 0) 
+	  *matrixdist = 1;
+	else if(strcmp(tictac,"distributed") == 0) 
+	  *matrixdist = 2;
+	else{
+	  printf("value of parameter matrix is not correct %s \n", tictac );
+	}
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+	    exit(1);
+	  }	  
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+}
+
+
+void read_options_freefem(string *string_option, superlu_options_t *options, DiagScale_t *diag){
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[6] = {NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A,PARMETIS, MY_PERMC};
+  static const rowperm_t  enumrowperm_t[3] = {NOROWPERM, LargeDiag, MY_PERMR};
+  static const DiagScale_t enumDiagScale_t[4] = {NOEQUIL, ROW, COL, BOTH};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const IterRefine_t enumIterRefine_t[4] = {NOREFINE, SINGLE, DOUBLE, EXTRA};  
+  //static const MemType enumMemType_t[4] = {LUSUP, UCOL, LSUB, USUB};  
+  //static const stack_end_t enumstack_end_t[2] = {HEAD, TAIL};
+  //static const LU_space_t enumLU_space_t[2] = {SYSTEM, USER};
+
+ 
+  static const char* compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* comprowperm_t[] = {"NOROWPERM", "LargeDiag", "MY_PERMR",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_AT_PLUS_A", "MMD_ATA", "METIS_AT_PLUS_A", "PARMETIS", "MY_PERMC",0};
+  static const char* compDiagScale_t[] = {"NOEQUIL", "ROW", "COL", "BOTH",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  //static const char* compMemType_t[] = {"LUSUP", "UCOL", "LSUB", "USUB",0};  
+  //static const char* compstack_end_t[] = {"HEAD", "TAIL",0};
+  //static const char* compLU_space_t[] = {"SYSTEM", "USER",0};
+
+  static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+			       "DiagPivotThresh","IterRefine","Trans",
+			       "ReplaceTinyPivot","SolveInitialized",
+			       "RefineInitialized","PrintStat","nprow","npcol","DiagScale","matrix",0};
+
+  char data[string_option->size()+1];  
+  strcpy( data, string_option->c_str()); 
+  cout << "data=" << data << endl;
+  char *tictac;
+  char *tictac2;
+  tictac = strtok(data," =,\t\n");
+
+  while(tictac != NULL){
+    int id_option = s_(tictac, comp);
+    tictac2=tictac;
+    tictac = strtok(NULL," =,\t\n");
+    int val_options;
+
+    switch (id_option)
+      { 
+      case 1 : // Fact
+	//char* comp1[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+	val_options= s_(tictac,compfact_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+	  exit(1);
+	}
+	options->Fact = enumfact_t[val_options-1];
+	break;
+      case 2:  // Equil
+	//char* comp2[] = {"NO", "YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+	  exit(1);
+	}
+	options->Equil = enumyes_no_t[val_options-1];
+	break;
+      case 3:  // ParSymbFact
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ParSymbFact = enumyes_no_t[val_options-1];
+	break;
+      case 4:  // ColPerm
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compcolperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ColPerm = enumcolperm_t[val_options-1];
+	break;
+      case 5:  // RowPerm
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,comprowperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->RowPerm = enumrowperm_t[val_options-1];
+	break;
+      case 6:  // DiagPivotThresh
+	options->DiagPivotThresh= strtod(tictac,&tictac);
+	break;
+      case 7:  // IterRefine
+	val_options= s_(tictac,compIterRefine_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->IterRefine = enumIterRefine_t[val_options-1];
+	break;
+      case 8:  // Trans
+	//char* comp5[] = {"NOTRANS", "TRANS", "CONJ", 0};
+	val_options= s_(tictac, comptrans_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+	  exit(1);
+	}
+	options->Trans = enumtrans_t[val_options-1];
+	break;
+      case 9:  // ReplaceTinyPivot
+	//char* comp7[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+	  exit(1);
+	}
+	options->ReplaceTinyPivot= enumyes_no_t[val_options-1]; 
+	break;
+      case 10:  // SolveInitialized
+	//char* comp8[] = {"NO","YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+	  exit(1);
+	}
+	options->SolveInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 11:  // RefineInitialized
+	//char* comp9[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+	  exit(1);
+	}
+	options->RefineInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 12: // PrintStat
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+	options->PrintStat = enumyes_no_t[val_options-1];
+	break;
+	// case 13 nprow
+	// case 14 npcol
+      case 15: // DiagScale_t
+	val_options= s_(tictac, compDiagScale_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+        *diag = enumDiagScale_t[val_options-1];
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0)
+	  {
+	    printf("parameter is not valid for superlu_dist %s \n", tictac2);
+	    exit(1);
+	  }	 
+	break;
+      }  
+    tictac = strtok(NULL," =,\t\n");
+  }
+  
+}
+
+// void read_nprow_npcol_freefem(string *string_option, int *nprow, int *npcol, int *matrixdist){
+  
+//   static const char* comp[] = {"Fact","Equil","ParSymbFact","ColPerm","RowPerm",
+// 			       "DiagPivotThresh","IterRefine","Trans",
+// 			       "ReplaceTinyPivot","SolveInitialized",
+// 			       "RefineInitialized","PrintStat","nprow","npcol","matrix",0};
+
+//   char data[string_option->size()+1];  
+//   strcpy( data, string_option->c_str()); 
+//   char *tictac;
+//   char *tictac2;
+//   tictac = strtok(data," =,\t\n");
+  
+//   while(tictac != NULL){
+//     int id_option = s_(tictac, comp);
+//     tictac2 = tictac;
+//     tictac = strtok(NULL," =,\t\n");
+//     int val_options;
+//     printf("param %s = value %s , id_option %d\n",tictac2,tictac,id_option);
+//     switch (id_option)
+//       { 
+//       case 13: // nprow
+// 	*nprow = atoi(tictac);
+// 	break;
+//       case 14: // npcol 
+// 	*npcol = atoi(tictac);
+// 	break;
+//       case 15: // matrix
+// 	printf("parameter matrix \n");
+// 	if(strcmp(tictac,"assembled") == 0)
+// 	  *matrixdist = 0;
+// 	else if(strcmp(tictac,"distributedglobal") == 0) 
+// 	  *matrixdist = 1;
+// 	else if(strcmp(tictac,"distributed") == 0) 
+// 	  *matrixdist = 2;
+// 	else{
+// 	  printf("value of parameter matrix is not correct %s \n", tictac );
+// 	}
+// 	break;
+//       default: // Equivalent of case default
+// 	if(id_option == 0)
+// 	  {
+// 	    printf("parameter is not valid for superlu_dist %s \n", tictac2 );
+// 	    exit(1);
+// 	  }	  
+// 	break;
+//       }  
+//     tictac = strtok(NULL," =,\t\n");
+//   }
+// }
+
+void read_nprow_npcol_matrixdist_superlu_datafile(string *data_option, int_t *nprow, int_t *npcol, int *matrixdist){
+ 
+  char datafile[data_option->size()+1];  
+  strcpy( datafile, data_option->c_str()); 
+  
+  FILE* pfile= fopen( datafile,"rt");
+  char data[256];
+  char *tictac;
+  
+  fgets(data,256,pfile);
+  cout << "data=" << data << endl;
+  tictac = strtok(data," /!#\t\n");
+  *nprow = (int) atol(tictac);
+  if(verbosity) printf("nprow=%d\n",*nprow);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  *npcol = (int) atol(tictac);
+  if(verbosity) printf("npcol=%d\n",*npcol);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  if(strcmp(tictac,"assembled") == 0)
+    *matrixdist = 0;
+  else if(strcmp(tictac,"distributedglobal") == 0) 
+    *matrixdist = 1;
+  else if(strcmp(tictac,"distributed") == 0) 
+    *matrixdist = 2;
+  else{
+    printf("matrix input %s for superlu_dist is not correct\n", tictac );
+    exit(1);
+  }
+ 
+  fclose(pfile);
+}
+
+
+void read_options_superlu_datafile(string *data_option, superlu_options_t *options, int_t *nprow, int_t *npcol, int *matrixdist, DiagScale_t *diag){
+  static const yes_no_t  enumyes_no_t[2] = {NO, YES};
+  static const fact_t  enumfact_t[4] = {DOFACT, SamePattern, SamePattern_SameRowPerm, FACTORED};
+  static const colperm_t  enumcolperm_t[6] = {NATURAL, MMD_AT_PLUS_A, MMD_ATA, METIS_AT_PLUS_A,PARMETIS, MY_PERMC};
+  static const rowperm_t  enumrowperm_t[3] = {NOROWPERM, LargeDiag, MY_PERMR};
+  static const DiagScale_t enumDiagScale_t[4] = {NOEQUIL, ROW, COL, BOTH};
+  static const trans_t  enumtrans_t[3] = {NOTRANS, TRANS, CONJ};
+  static const IterRefine_t enumIterRefine_t[4] = {NOREFINE, SINGLE, DOUBLE, EXTRA};  
+  //static const MemType enumMemType_t[4] = {LUSUP, UCOL, LSUB, USUB};  
+  //static const stack_end_t enumstack_end_t[2] = {HEAD, TAIL};
+  //static const LU_space_t enumLU_space_t[2] = {SYSTEM, USER};
+
+ 
+  static const char* compyes_no_t[] = {"NO", "YES",0};
+  static const char* compfact_t[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+  static const char* comprowperm_t[] = {"NOROWPERM", "LargeDiag", "MY_PERMR",0};
+  static const char* compcolperm_t[] = {"NATURAL", "MMD_AT_PLUS_A", "MMD_ATA", "METIS_AT_PLUS_A", "PARMETIS", "MY_PERMC",0};
+  static const char* compDiagScale_t[] = {"NOEQUIL", "ROW", "COL", "BOTH",0};
+  static const char* comptrans_t[] = {"NOTRANS", "TRANS", "CONJ",0};
+  static const char* compIterRefine_t[] = {"NOREFINE", "SINGLE", "DOUBLE", "EXTRA",0};
+  
+  //int_t ffnprow,ffnpcol;
+  //int matrixdist;
+
+  char datafile[data_option->size()+1];  
+  strcpy( datafile, data_option->c_str()); 
+  
+  FILE* pfile= fopen( datafile,"rt");
+  char data[256];
+  char *tictac;
+  
+  fgets(data,256,pfile);
+  cout << "data=" << data << endl;
+  tictac = strtok(data," /!#\t\n");
+  *nprow = (int) atol(tictac);
+  if(verbosity) printf("nprow=%d\n",*nprow);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  *npcol = (int) atol(tictac);
+  if(verbosity) printf("npcol=%d\n",*npcol);
+
+  fgets(data,256,pfile);
+  tictac = strtok(data," /!#\t\n");
+  if(strcmp(tictac,"assembled") == 0)
+    *matrixdist = 0;
+  else if(strcmp(tictac,"distributedglobal") == 0) 
+    *matrixdist = 1;
+  else if(strcmp(tictac,"distributed") == 0) 
+    *matrixdist = 2;
+  else{
+    printf("matrix input %s for superlu_dist is not correct\n", tictac );
+    exit(1);
+  }
+
+  int id_option=0;
+  
+  while( !feof(pfile) && id_option<12){
+    fgets(data,256,pfile);
+    tictac = strtok(data," /!#\t\n");
+    id_option++;
+    int val_options;
+    switch (id_option)
+      { 
+	
+      case 1 : // Fact
+	//char* comp1[] = {"DOFACT", "SamePattern", "SamePattern_SameRowPerm", "FACTORED",0};
+	val_options= s_(tictac,compfact_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Fact");
+	  exit(1);
+	}
+	
+	options->Fact = enumfact_t[val_options-1];
+	break;
+      case 2:  // Equil
+	//char* comp2[] = {"NO", "YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Equil");
+	  exit(1);
+	}
+	options->Equil = enumyes_no_t[val_options-1];
+	break;
+      case 3:  // ParSymbFact
+	//char* comp3[] = {"NATURAL", "MMD_ATA", "MMD_AT_PLUS_A", "COLAMD", "MY_PERMC", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ParSymbFact = enumyes_no_t[val_options-1];
+	break;
+      case 4:  // ColPerm
+	val_options= s_(tictac,compcolperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->ColPerm = enumcolperm_t[val_options-1];
+	break;
+      case 5:  // RowPerm
+	val_options= s_(tictac,comprowperm_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->RowPerm = enumrowperm_t[val_options-1];
+	break;
+      case 6:  // DiagPivotThresh
+	options->DiagPivotThresh= strtod(tictac,&tictac);
+	break;
+      case 7:  // IterRefine
+	val_options= s_(tictac,compIterRefine_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ColPerm");
+	  exit(1);
+	}
+	options->IterRefine = enumIterRefine_t[val_options-1];
+	break;
+      case 8:  // Trans
+	//char* comp5[] = {"NOTRANS", "TRANS", "CONJ", 0};
+	val_options= s_(tictac, comptrans_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","Trans");
+	  exit(1);
+	}
+	options->Trans = enumtrans_t[val_options-1];
+	break;
+      case 9:  // ReplaceTinyPivot
+	//char* comp7[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","SymmetricMode");
+	  exit(1);
+	}
+	options->ReplaceTinyPivot= enumyes_no_t[val_options-1]; 
+	break;
+      case 10:  // SolveInitialized
+	//char* comp8[] = {"NO","YES", 0};
+	val_options= s_(tictac,compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PivotGrowth");
+	  exit(1);
+	}
+	options->SolveInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 11:  // RefineInitialized
+	//char* comp9[] = {"NO","YES", 0};
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","ConditionNumber");
+	  exit(1);
+	}
+	options->RefineInitialized = enumyes_no_t[val_options-1];
+	break;
+      case 12: // PrintStat
+	val_options= s_(tictac, compyes_no_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+	options->PrintStat = enumyes_no_t[val_options-1];
+	break;
+      case 13: // DiagScale_t
+	val_options= s_(tictac, compDiagScale_t);
+	if( val_options == 0){
+	  printf("value given for SuperLU for options %s is not correct\n","PrintStat");
+	  exit(1);
+	}
+        *diag = enumDiagScale_t[val_options-1];
+	break;
+      default: // Equivalent of case default
+	if(id_option == 0 && id_option > 13)
+	  {
+	    printf("Error in reading data file for superlu_dist %s\n",datafile);
+	    exit(1);
+	  }	 
+	break;
+      }  
+  }
+  fclose(pfile);
+}
diff --git a/src/solver/hips_FreeFem.cpp b/src/solver/hips_FreeFem.cpp
new file mode 100755
index 0000000..5f4865e
--- /dev/null
+++ b/src/solver/hips_FreeFem.cpp
@@ -0,0 +1,643 @@
+// ORIG-DATE: 04/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : INRIA FUTUR
+// AUTHOR   : Guy Atenekeng
+// E-MAIL   : Guy_Antoine_Atenekeng_Kahou at lri.fr
+//
+//ff-c++-LIBRARY-dep: metis hips  blas 
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "mpi.h"
+
+extern "C" {
+  #include "hips.h"  
+ // #include "io.h"
+  #include "metis.h"
+}
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BUFLEN 200
+#define MCW MPI_COMM_WORLD
+
+//roscal(&n,&job,&tmp,AAv,p,pr,scaletmpr,AAv,p,pr,&ierr);
+
+int roscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpr , int *ierr)
+{
+/*---------------------------------------------------------------------
+|
+| This routine scales each row of mata so that the norm is 1.
+|
+|----------------------------------------------------------------------
+| on entry:
+| mata  = the matrix (in SparRow form)
+| nrm   = type of norm
+|          0 (\infty),  1 or 2
+|
+| on return
+| diag  = diag[j] = 1/norm(row[j])
+|
+|     0 --> normal return
+|     j --> row j is a zero row
+|--------------------------------------------------------------------*/
+/*   local variables    */
+   int i, k;
+   double  scal;
+   
+   for (i=0; i<n; i++) {
+      scal = 0.0;
+    // kr = &(AAv[pr[i]]);
+      if (nrm == 0) {
+	 for (k=pr[i]; k<pr[i+1]; k++)
+	    if (fabs(AAv[k]) > scal) scal = fabs(AAv[k]);
+      }
+      else if (nrm == 1) {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scal += fabs(AAv[k]);
+      }
+      else {  /* nrm = 2 */
+         for (k=pr[i]; k<(pr[i+1]); k++)
+            scal += AAv[k]*AAv[k];
+      }
+      if (nrm == 2) scal = sqrt(scal);
+      if (scal == 0.0) {
+	*ierr=i;
+	 return i+1;
+      }
+      else 
+	 scal = 1.0 / scal;
+      scaletmpr[i] = scal;
+      for (k=pr[i]; k<(pr[i+1]); k++)
+	 AAv[k] = AAv[k] * scal;
+     
+   }
+   *ierr=0;
+   return 0;
+}
+/*---------------end of roscalC-----------------------------------------
+----------------------------------------------------------------------*/
+int coscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpc , int * ierr)
+{
+/*---------------------------------------------------------------------
+|
+| This routine scales each column of mata so that the norm is 1.
+|
+|----------------------------------------------------------------------
+| on entry:
+| mata  = the matrix (in SparRow form)
+| nrm   = type of norm
+|          0 (\infty),  1 or 2
+|
+| on return
+| diag  = diag[j] = 1/norm(row[j])
+|
+|     0 --> normal return
+|     j --> column j is a zero column
+|--------------------------------------------------------------------*/
+/*   local variables    */
+   int i, j, k;
+   double *kr;
+   int *ki;
+   for (i=0; i<n; i++)
+      scaletmpc[i] = 0.0;
+/*---------------------------------------
+|   compute the norm of each column
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+      kr = &(AAv[pr[i]]);
+      ki = &(pr[i]);
+      if (nrm == 0) {
+	 for (k=pr[i]; k<pr[i+1]; k++) {
+	    j = pr[i];
+	    if (fabs(AAv[k]) > scaletmpc[p[k]]) scaletmpc[p[k]] = fabs(AAv[k]);
+	 }
+      }
+      else if (nrm == 1) {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scaletmpc[p[k]] += fabs(AAv[k]);
+      }
+      else {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scaletmpc[p[k]] += fabs(AAv[k])*fabs(AAv[k]);
+      }
+   }
+   if (nrm == 2) {
+      for (i=0; i<n; i++)
+	 scaletmpc[i] = sqrt(scaletmpc[i]);
+   }
+/*---------------------------------------
+|   invert
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+      if (scaletmpc[i] == 0.0)
+	{
+	 *ierr=i+1;
+	 return i+1;
+	}
+      else 
+	 scaletmpc[i] = 1.0 / scaletmpc[i];
+   }
+/*---------------------------------------
+|   C = A * D
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+    
+      for (k=pr[i]; k<pr[i+1]; k++)
+	AAv[k]=AAv[k]*scaletmpc[p[k]];
+	
+   }
+   *ierr=0;
+   return 0;
+}
+/*---------------end of coscalC-----------------------------------------
+----------------------------------------------------------------------*/
+
+
+
+
+
+
+void parm_param(string datafile,KN<long> param_int,KN<double> param_double)
+	{
+	char buf[BUFLEN];
+	int num,in_val;
+	double val;
+	  FILE *fp;
+	  char * filename=new char[datafile.length()+1]; 
+          strcpy(filename,datafile.c_str()); 
+	  int i;
+	  for(i=0;i<16;i++) param_int[i]=-1; for(i=0;i<9;i++) param_double[i]=-1.0;
+ 	 /* read parameters for preconditioner and iteration from file  'filename' */
+  	/*  ---- start modification by MS   */
+ 	 if( (fp = fopen(filename, "r")) == NULL ){
+          fprintf(stderr, "Cannot open file inputs\n");
+    	  exit(1);
+    	}
+  	num = 0;
+
+  while(fgets(buf, BUFLEN, fp) != NULL) {
+	if(num<=15) {sscanf(buf, "%d", &in_val); param_int[num]=in_val;}
+	else 
+	{sscanf(buf, "%lf", &val); param_double[num]=val;}
+	num++;
+	}
+  fclose(fp);
+}
+
+
+
+
+class HipsSolver :   public MatriceMorse<double>::VirtualSolver   {
+	double eps;
+	mutable double  epsr;
+	double tgv;	
+	double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+	string data_option;
+	MPI_Comm  comm;
+	mutable INTS id, idnbr, i, j;
+	mutable INTS *unknownlist;
+	mutable double *x;
+	mutable INTS   ln;
+	mutable INTS ierr;
+	mutable INTS n,nnz;
+	mutable double * a;
+	mutable INTS *ia, *ja;
+	mutable int *pp;
+	int loc_size,pbegin, pend;
+	INTS domsize, nproc,proc_id;
+	mutable int sym_pattern, sym_matrix;
+	KN<long> param_int;
+	KN<double> param_double;
+	mutable double *scaletmpr, *scaletmpc;
+	
+	mutable int *mapptr,*maptmp,*iwork,*riord,*iwork1,scale;
+	mutable int *pr, *p;
+	mutable double * AAv;
+	
+ public:
+  HipsSolver(const MatriceMorse<double> &AA,string datafile, const KN<long> &param_int1, const KN<double> &param_double1,  MPI_Comm  * mpicommw  ) : data_option(datafile) 
+  { 
+	int argc,sym,symm;
+	argc=1; 
+
+	
+
+	param_int=param_int1;
+	param_double=param_double1;	
+  	
+	
+        if(mpicommw==0){
+	comm=MPI_COMM_WORLD;
+	}
+	else
+	comm= *mpicommw;
+
+	  
+      
+  	MPI_Comm_rank(comm, &proc_id);
+  	MPI_Comm_size(comm, &nproc);
+	
+	id = 0; /** id of the linear system **/
+	
+	 
+  /***************************************/
+  /* Initialize HIPS for one problem     */
+  /***************************************/
+	idnbr = 1; /* total */
+	ierr = HIPS_Initialize(idnbr);
+	HIPS_ExitOnError(ierr);
+	id = 0; /** id of the linear system **/
+
+	int ic;
+	
+	if((!data_option.empty())&&((param_int==NULL)||(param_double==NULL))) 
+		parm_param(datafile,param_int,param_double);
+	else{
+		if((param_double.N()>0)||(param_int.N()>0)){
+		if(proc_id==0)      cout << "    WE SET PARAMETER FROM VECTORS   " << endl;}
+		else if(proc_id==0) cout << "    WE SET DEFAULT PARAMETERS       " << endl;
+	}
+	
+	 if(param_int.N()>0) {
+	if((param_int[0]==HIPS_ITERATIVE)||(param_int[0]==HIPS_HYBRID)) // Using strategy. Input is ok
+	{ HIPS_SetDefaultOptions(id,param_int[0]); ic=param_int[0];}
+	else {	HIPS_SetDefaultOptions(id,HIPS_ITERATIVE );ic=HIPS_ITERATIVE; } // Strategy is not they existing one
+
+	}else {HIPS_SetDefaultOptions(id,HIPS_ITERATIVE);ic=HIPS_ITERATIVE;} //Default strategy is ITERATIVE
+	
+	if(param_double.N()>0) {if(param_double[0]>0) HIPS_SetOptionREAL(id,HIPS_PREC,param_double[0]);
+	else HIPS_SetOptionREAL(id,HIPS_PREC,1e-09);} else  HIPS_SetOptionREAL(id,HIPS_PREC,1e-09);	
+	
+	if((param_int.N()>1)&&(ic==HIPS_ITERATIVE)) {if((param_int[1]==1)||(param_int[1]==0)) HIPS_SetOptionINT(id,HIPS_KRYLOV_METHOD,param_int[1]); 
+	else HIPS_SetOptionINT(id,HIPS_KRYLOV_METHOD,0);}else {if(ic==HIPS_ITERATIVE) HIPS_SetOptionINT(id,HIPS_KRYLOV_METHOD,0);}
+	
+	if(param_int.N()>2) { if(param_int[2]>0) HIPS_SetOptionINT(id,HIPS_ITMAX,param_int[2]); else  HIPS_SetOptionINT(id,HIPS_ITMAX,1000);}
+	else  HIPS_SetOptionINT(id,HIPS_ITMAX,1000);
+
+	if(param_int.N()>3) { if(param_int[3]>0) HIPS_SetOptionINT(id,HIPS_KRYLOV_RESTART,param_int[3]); 
+	else  HIPS_SetOptionINT(id,HIPS_KRYLOV_RESTART,40);} else HIPS_SetOptionINT(id,HIPS_KRYLOV_RESTART,40);
+
+	if(param_int.N()>4) {if(param_int[4]>0) {HIPS_SetOptionINT(id,HIPS_SYMMETRIC,param_int[4]); symm=param_int[4];}}
+	else {HIPS_SetOptionINT(id,HIPS_SYMMETRIC,1);symm=1;}
+
+	if(param_int.N()>5) {if((param_int[5]==0)||(param_int[5]==1)) {HIPS_SetOptionINT(id,HIPS_GRAPH_SYM,param_int[5]);sym=param_int[5];}
+	else {HIPS_SetOptionINT(id,HIPS_GRAPH_SYM,1);sym=1;}} else  {HIPS_SetOptionINT(id,HIPS_GRAPH_SYM,1);sym=1;}	
+
+	if(param_int.N()>6) { if(param_int[6]>0) HIPS_SetOptionINT(id,HIPS_PARTITION_TYPE,param_int[6]); 
+	else  HIPS_SetOptionINT(id,HIPS_PARTITION_TYPE,0);}else  HIPS_SetOptionINT(id,HIPS_PARTITION_TYPE,0);			
+		
+	if(param_int.N()>7) {if(param_int[7]>0) HIPS_SetOptionINT(id,HIPS_LOCALLY,param_int[7]); 
+	else  HIPS_SetOptionINT(id,HIPS_LOCALLY,2);}else HIPS_SetOptionINT(id,HIPS_LOCALLY,2);
+
+	if(param_int.N()>8) {if(param_int[8]>0) HIPS_SetOptionINT(id,HIPS_FORTRAN_NUMBERING,param_int[8]);
+	else HIPS_SetOptionINT(id,HIPS_FORTRAN_NUMBERING,0);} else  HIPS_SetOptionINT(id,HIPS_FORTRAN_NUMBERING,0);	
+	
+	if(param_int.N()>9) {if(param_int[9]>0) HIPS_SetOptionINT(id,HIPS_SCALE,param_int[9]);
+	else { HIPS_SetOptionINT(id,HIPS_SCALE,1); scale=1;}} else  {HIPS_SetOptionINT(id,HIPS_SCALE,1); scale=1;}
+
+	if(param_int.N()>10) {if(param_int[10]>0) HIPS_SetOptionINT(id,HIPS_REORDER,param_int[10]);
+	else HIPS_SetOptionINT(id,HIPS_REORDER,1);} else  HIPS_SetOptionINT(id,HIPS_REORDER,1);	
+
+	if(param_int.N()>11) {if(param_int[11]>0) HIPS_SetOptionINT(id,HIPS_DOF,param_int[11]);
+	else HIPS_SetOptionINT(id,HIPS_DOF,1);} else  HIPS_SetOptionINT(id,HIPS_DOF,1);
+
+	if(param_int.N()>12) {if(param_int[12]>0) HIPS_SetOptionINT(id,HIPS_SCALENBR,param_int[12]);
+	else HIPS_SetOptionINT(id,HIPS_SCALENBR,2);} else  HIPS_SetOptionINT(id,HIPS_SCALENBR,2);
+		
+	if(param_int.N()>13) {if(param_int[13]>0) HIPS_SetOptionINT(id,HIPS_VERBOSE,param_int[13]);
+	else HIPS_SetOptionINT(id,HIPS_VERBOSE,5);} else  HIPS_SetOptionINT(id,HIPS_VERBOSE,5);		
+
+	if(param_int.N()>14) {if(param_int[14]>0) HIPS_SetOptionINT(id,HIPS_DOMSIZE,param_int[14]);
+	else HIPS_SetOptionINT(id,HIPS_DOMSIZE,2);} else  HIPS_SetOptionINT(id,HIPS_DOMSIZE,2);	
+
+	// if(param_int.N()>15) {if(param_int[15]>0) HIPS_SetOptionINT(id,HIPS_SCHUR_METHOD,param_int[15]);
+        //else HIPS_SetOptionINT(id,HIPS_SCHUR_METHOD,2);} else  HIPS_SetOptionINT(id,HIPS_SCHUR_METHOD,2);
+
+      //   if(param_int.N()>16) {if(param_int[16]>0) HIPS_SetOptionINT(id,HIPS_ITMAX_SCHUR,param_int[16]);
+       // else HIPS_SetOptionINT(id,HIPS_ITMAX_SCHUR,2);} else  HIPS_SetOptionINT(id,HIPS_ITMAX_SCHUR,2);
+
+
+			
+	
+	if(param_double.N()>1){if(param_double[1]>0.0) HIPS_SetOptionREAL(id,HIPS_DROPTOL0,param_double[1]);
+	else  HIPS_SetOptionREAL(id,HIPS_DROPTOL0,0.005);} else   HIPS_SetOptionREAL(id,HIPS_DROPTOL0,0.005);
+
+	if(param_double.N()>2) {if(param_double[2]>0.0) HIPS_SetOptionREAL(id,HIPS_DROPTOL1,param_double[2]);
+	else  HIPS_SetOptionREAL(id,HIPS_DROPTOL1,0.005);} else  HIPS_SetOptionREAL(id,HIPS_DROPTOL1,0.005);
+
+	if(param_double.N()>3){if(param_double[3]>0.0) HIPS_SetOptionREAL(id,HIPS_DROPTOLE,param_double[3]);
+	else  HIPS_SetOptionREAL(id,HIPS_DROPTOLE,0.005);} HIPS_SetOptionREAL(id,HIPS_DROPTOLE,0.005);
+
+	if(param_double.N()>4){if(param_double[4]>0.0) HIPS_SetOptionREAL(id,HIPS_AMALG,param_double[4]);
+	else  HIPS_SetOptionREAL(id,HIPS_AMALG,0.005);} HIPS_SetOptionREAL(id,HIPS_AMALG,0.005);
+	
+	/*if(param_double.N()>5){if(param_double[5]>0.0) HIPS_SetOptionREAL(id,HIPS_DROPTOLSCHUR ,param_double[5]);
+        else  HIPS_SetOptionREAL(id,HIPS_DROPTOLSCHUR ,0.005);} HIPS_SetOptionREAL(id,HIPS_DROPTOLSCHUR ,0.005);*/
+
+
+	
+
+    
+
+     
+
+        
+
+	
+		
+		
+	HIPS_SetCommunicator(id,comm);
+
+	n=AA.n; nnz=AA.nbcoef;
+
+	
+	
+	int ierr;
+	
+	pr= new int[n+1];
+	p=  new int[nnz];
+	AAv=new double[nnz];
+	
+
+	for(i=0;i<nnz;i++){
+	AAv[i]=AA.a[i];
+	p[i]=AA.cl[i];
+	if(i<=n) pr[i]=AA.lg[i];
+	}
+
+	
+	int job, tmp;
+	 if(scale) {
+	  	  job = 1;
+	   	  tmp = 2; /*-- compute 2-norm */
+		 scaletmpr=new double[n]; 		 scaletmpc=new double[n]; 
+	   
+	    roscal(n,job,tmp,AAv,p,pr,scaletmpr,&ierr);
+	    if (ierr) fprintf(stderr, "Error: in roscal, ierr = %d\n", ierr);
+	/*------- scale the RHS according to row scaling coefficients */
+		
+	    coscal(n,job,tmp,AAv,p,pr,scaletmpc,&ierr);
+	    if (ierr) fprintf(stderr, "Error: in coscal, ierr = %d\n", ierr);
+	  
+	  } /*--- end of branch on scaling */
+
+
+	int wgtflag=0, numflag=0, volume;
+	
+	riord=(int *)malloc(sizeof(int)*n);
+	if(riord==NULL) {if(nproc==0)printf("%s","Memory allocation failed in partition stage \n"); exit(1);}
+	int option[5];	option[0]=0;
+	if(nproc>1){
+		METIS_PartGraphKway(&n, AA.lg, AA.cl, NULL, NULL, &wgtflag, &numflag,&nproc, option, &volume, riord);
+	}
+	else if(nproc==1){
+		for (i=0; i<n; i++) riord[i]=0;
+	}
+	iwork=(int *)malloc(sizeof(int)*n);
+	maptmp=(int *)malloc(sizeof(int)*n);
+	mapptr=(int *)malloc(sizeof(int)*(nproc+1));
+	iwork1=(int *)malloc(sizeof(int)*(nproc+1));
+	
+       if(nproc==1){iwork[0]=0;iwork1[0]=0;}
+	
+	for(i=0; i<nproc; i++){
+		iwork[i]=0;iwork1[i]=0;
+	}
+
+	for(j=0; j<n; j++){
+		iwork[riord[j]]++;
+		iwork1[riord[j]]++;
+	}
+	numflag=0;
+	for(i=0; i<nproc; i++){
+		mapptr[i]=numflag;
+		numflag+=iwork[i];
+	}
+	
+	mapptr[nproc]=numflag;
+	
+	for (i=0; i<nproc; i++){
+		iwork[i]=mapptr[i];
+	}
+	if(nproc==0) iwork[0]=mapptr[0];
+	
+	for(i=0; i<n; i++){
+		maptmp[iwork[riord[i]]]=i;
+		iwork[riord[i]]++;
+	}
+	int nnzz;
+	nnzz=0;
+	for(i=0;i<n;i++) if(riord[i]==proc_id){ nnzz=(AA.lg[i+1]-AA.lg[i])+nnzz;}
+	ierr = HIPS_GraphBegin(id, n, nnzz);
+	HIPS_ExitOnError(ierr);
+	
+       
+
+	for(i=0;i<n;i++)
+	{
+		if(riord[i]==proc_id){
+		for(j=AA.lg[i];j<AA.lg[i+1];j++)
+		{
+			ierr = HIPS_GraphEdge(id, i, AA.cl[j]);
+			HIPS_ExitOnError(ierr);	
+		}
+		}
+		
+	}
+	
+	ierr = HIPS_GraphEnd(id);
+  	HIPS_ExitOnError(ierr);
+	if(proc_id==0)
+	{
+		ierr = HIPS_SetPartition(id, nproc, mapptr, maptmp);
+	        HIPS_ExitOnError(ierr);
+	}
+	 ierr = HIPS_AssemblyBegin(id, nnzz, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_FOOL,symm);
+ 	 HIPS_ExitOnError(ierr);
+ 
+	 for(i=0;i<n;i++)
+	{
+		if(riord[i]==proc_id){
+		for(j=AA.lg[i];j<AA.lg[i+1];j++)
+		{					
+			ierr = HIPS_AssemblySetValue(id, i, AA.cl[j], AAv[j]);
+			HIPS_ExitOnError(ierr);
+		}
+		}
+		
+	}
+    	ierr = HIPS_AssemblyEnd(id);
+  	HIPS_ExitOnError(ierr);
+	if(pr!=NULL)	free(pr); if(p!=NULL)	free(p); if(AAv!=NULL) free(AAv);
+  }
+	void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+	/***************************************************/
+  	/*                                                 */
+  	/*          ENTER THE RIGHT-HAND-SIDE              */
+  	/*                                                 */
+  	/***************************************************/
+	int i,nloc;
+	nloc=0; 
+	int nnsize;
+	MPI_Comm_size(comm,&nnsize);
+	
+
+ 	COEF * rhsloc = (COEF *)malloc(sizeof(COEF)*iwork1[proc_id]);
+ 	COEF * xx = (COEF *)malloc(sizeof(COEF)*iwork1[proc_id]);
+	int * unknownlist = (INTS *)malloc(sizeof(INTS)*iwork1[proc_id]);
+	COEF * xz = (COEF *)malloc(sizeof(COEF)*n);
+  	
+	nloc=0;
+	if(scale){
+	for(i=0;i<n;i++)
+	{
+		if(riord[i]==proc_id){
+		rhsloc[nloc]=b[i]*scaletmpr[i]; unknownlist[nloc]=i; nloc++; 
+		}
+	}
+	}
+	for(i=0;i<iwork1[proc_id];i++) xx[i]=0.0;
+	 ierr = HIPS_SetRHS(id, nloc, unknownlist, rhsloc, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_OVW, HIPS_ASSEMBLY_FOOL);
+  	HIPS_ExitOnError(ierr);
+	
+	 /****************************************************/
+  	/* Get the local solution                           */
+  	/****************************************************/ 
+	
+  	ierr = HIPS_GetSolution(id, nloc, unknownlist, xx, HIPS_ASSEMBLY_FOOL);
+	
+  	HIPS_ExitOnError(ierr);
+	
+	int *perm, *invp;
+	perm=(int *)malloc(sizeof(int)*n); invp=(int *)malloc(sizeof(int)*n);
+
+
+
+	MPI_Gatherv(xx,iwork1[proc_id], MPI_DOUBLE, xz,iwork1,mapptr,MPI_DOUBLE,0,comm);
+        MPI_Gatherv(unknownlist,iwork1[proc_id], MPI_INT, perm,iwork1,mapptr,MPI_INT,0,comm);
+        MPI_Bcast(xz,n,MPI_DOUBLE,0, comm); MPI_Bcast(perm,n,MPI_INT,0, comm);
+	
+	for(i=0;i<n;i++) invp[perm[i]]=i;
+	if(scale){for(i=0;i<n;i++) {x[i]=xz[invp[i]]; x[i]=x[i]*scaletmpc[i];}}
+
+
+	/**************************************************/
+	/* Free HIPS internal structure for problem "id"  */
+	/*************************************************/
+
+	
+             
+		free(xz); free(perm); free(invp);free(rhsloc); free(unknownlist);  free(xx);
+		
+		HIPS_SetOptionINT(id,HIPS_DISABLE_PRECOND,0);HIPS_ExitOnError(ierr);
+ 		ierr = HIPS_Clean(id);
+  		HIPS_ExitOnError(ierr);	
+	
+	}
+	~HipsSolver()
+	{
+		if(verbosity>3)
+       		cout << "~Hips_Solver S:" << endl;
+		free(iwork1); free(mapptr); 
+		free(iwork); free(maptmp);
+		
+		HIPS_SetOptionINT(id,HIPS_DISABLE_PRECOND,0);HIPS_ExitOnError(ierr);
+ 		ierr = HIPS_Clean(id);
+  		HIPS_ExitOnError(ierr);	
+		
+	}	
+   void addMatMul(const KN_<double> & x, KN_<double> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<double> &) (*this) * x; 
+  }
+};
+
+//BuildSolverIUMFPack(DCL_ARG_SPARSE_SOLVER(double,A))
+inline MatriceMorse<double>::VirtualSolver *
+BuildSolverHipsSolvermpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverSuperLU<double>" << endl;
+    return new HipsSolver(*A,ds.data_filename, ds.lparams, ds.dparams,(MPI_Comm *)ds.commworld);
+}
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+   //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+	return 1;
+}
+
+bool SetHipsSolver()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to Hips" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverHipsSolvermpi;
+    //DefSparseSolver<Complex>::solver =BuildSolverHipsSolvermpi;    
+    TypeSolveMat::defaultvalue =TypeSolveMatdefaultvalue;
+	return 1;
+}
+Init init;
+Init::Init()
+{   
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: Hips,  defaultsolver defaultsolverHips" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver  =BuildSolverHipsSolvermpi;
+//  DefSparseSolver<Complex>::solver =BuildSolverHipsSolver;
+  if(! Global.Find("defaultsolver").NotNull() )
+  Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoHips","(",new OneOperator0<bool>(SetHipsSolver));
+}
+
+
+
+
diff --git a/src/solver/hypre_FreeFem.cpp b/src/solver/hypre_FreeFem.cpp
new file mode 100755
index 0000000..921f141
--- /dev/null
+++ b/src/solver/hypre_FreeFem.cpp
@@ -0,0 +1,1758 @@
+
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : INRIA Saclay 
+// AUTHOR   : Guy Atenekeng
+// E-MAIL   : Guy_Antoine_Atenekeng_Kahou at lri.fr
+//
+//ff-c++-LIBRARY-dep: metis hypre  blas 
+//ff-c++-cpp-dep: 
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#ifdef __cplusplus
+ extern "C" {
+ #include "metis.h"
+ #endif
+ #ifdef __cplusplus
+ }
+ #endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mpi.h"
+
+#ifdef MPI_WTIME_IS_GLOBAL
+#undef MPI_WTIME_IS_GLOBAL
+#endif
+#define MPI_WTIME_IS_GLOBAL 1
+#define STATS
+
+#include "_hypre_utilities.h"
+#include "HYPRE.h"
+#include "HYPRE_krylov.h"
+#include "HYPRE_IJ_mv.h"
+#include "HYPRE_parcsr_ls.h"
+#include "_hypre_parcsr_mv.h"
+#include "fortran_matrix.h"
+#include "HYPRE_lobpcg.h"
+
+#include "interpreter.h"
+#include "multivector.h"
+#include "HYPRE_MatvecFunctions.h"
+
+#include "HYPRE_parcsr_int.h"
+
+
+
+
+#define CHECK_ZERO
+#define MCW MPI_COMM_WORLD
+#define BUFLEN 100
+#define SCALE 0
+
+
+#ifdef SUN 
+/*
+ * 	It uses the system call gethrtime(3C), which is accurate to 
+ *	nanoseconds. 
+*/
+#include <sys/time.h>
+ 
+double dwalltime() {
+			 return ( (double)gethrtime() / 1e9 );
+				 }
+
+#else
+
+#ifndef NO_TIMER
+#include <sys/types.h>
+#include <sys/times.h>
+#include <time.h>
+#include <sys/time.h>
+#endif
+
+#ifndef CLK_TCK
+#define CLK_TCK 60
+#endif
+
+				 double dwalltime()
+		 {
+#ifdef NO_TIMER
+			 /* no sys/times.h on WIN32 */
+			 double tmp;
+			 tmp = 0.0;
+#else
+			 struct tms use;
+			 double tmp;
+			 times(&use);
+			 tmp = use.tms_utime;
+			 tmp += use.tms_stime;
+#endif
+			 return (double)(tmp) / CLK_TCK;
+		 }
+
+#endif
+
+
+
+
+
+int roscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpr , int *ierr)
+{
+/*---------------------------------------------------------------------
+|
+| This routine scales each row of mata so that the norm is 1.
+|
+|----------------------------------------------------------------------
+| on entry:
+| mata  = the matrix (in SparRow form)
+| nrm   = type of norm
+|          0 (\infty),  1 or 2
+|
+| on return
+| diag  = diag[j] = 1/norm(row[j])
+|
+|     0 --> normal return
+|     j --> row j is a zero row
+|--------------------------------------------------------------------*/
+/*   local variables    */
+   int i, k;
+   double  scal;
+   
+   for (i=0; i<n; i++) {
+      scal = 0.0;
+    // kr = &(AAv[pr[i]]);
+      if (nrm == 0) {
+	 for (k=pr[i]; k<pr[i+1]; k++)
+	    if (fabs(AAv[k]) > scal) scal = fabs(AAv[k]);
+      }
+      else if (nrm == 1) {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scal += fabs(AAv[k]);
+      }
+      else {  /* nrm = 2 */
+         for (k=pr[i]; k<(pr[i+1]); k++)
+            scal += AAv[k]*AAv[k];
+      }
+      if (nrm == 2) scal = sqrt(scal);
+      if (scal == 0.0) {
+	*ierr=i;
+	 return i+1;
+      }
+      else 
+	 scal = 1.0 / scal;
+      scaletmpr[i] = scal;
+      for (k=pr[i]; k<(pr[i+1]); k++)
+	 AAv[k] = AAv[k] * scal;
+     
+   }
+   *ierr=0;
+   return 0;
+}
+/*---------------end of roscalC-----------------------------------------
+----------------------------------------------------------------------*/
+int coscal(int n, int job,int nrm, double *AAv, int *p, int *pr, double * scaletmpc , int * ierr)
+{
+/*---------------------------------------------------------------------
+|
+| This routine scales each column of mata so that the norm is 1.
+|
+|----------------------------------------------------------------------
+| on entry:
+| mata  = the matrix (in SparRow form)
+| nrm   = type of norm
+|          0 (\infty),  1 or 2
+|
+| on return
+| diag  = diag[j] = 1/norm(row[j])
+|
+|     0 --> normal return
+|     j --> column j is a zero column
+|--------------------------------------------------------------------*/
+/*   local variables    */
+   int i, j, k;
+   double *kr;
+   int *ki;
+   for (i=0; i<n; i++)
+      scaletmpc[i] = 0.0;
+/*---------------------------------------
+|   compute the norm of each column
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+      kr = &(AAv[pr[i]]);
+      ki = &(pr[i]);
+      if (nrm == 0) {
+	 for (k=pr[i]; k<pr[i+1]; k++) {
+	    j = pr[i];
+	    if (fabs(AAv[k]) > scaletmpc[p[k]]) scaletmpc[p[k]] = fabs(AAv[k]);
+	 }
+      }
+      else if (nrm == 1) {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scaletmpc[p[k]] += fabs(AAv[k]);
+      }
+      else {
+         for (k=pr[i]; k<pr[i+1]; k++)
+            scaletmpc[p[k]] += fabs(AAv[k])*fabs(AAv[k]);
+      }
+   }
+   if (nrm == 2) {
+      for (i=0; i<n; i++)
+	 scaletmpc[i] = sqrt(scaletmpc[i]);
+   }
+/*---------------------------------------
+|   invert
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+      if (scaletmpc[i] == 0.0)
+	{
+	 *ierr=i+1;
+	 return i+1;
+	}
+      else 
+	 scaletmpc[i] = 1.0 / scaletmpc[i];
+   }
+/*---------------------------------------
+|   C = A * D
+|--------------------------------------*/
+   for (i=0; i<n; i++) {
+    
+      for (k=pr[i]; k<pr[i+1]; k++)
+	AAv[k]=AAv[k]*scaletmpc[p[k]];
+	
+   }
+   *ierr=0;
+   return 0;
+}
+/*---------------end of coscalC-----------------------------------------
+----------------------------------------------------------------------*/
+
+
+typedef struct sparse_mat_loc
+{
+        int *ptr;  //index of the beginning of rows in id_cols and vals
+        int *rows; //index of non empty rows
+        int *id_cols;
+        double *vals;
+	int ilower; // lower index limit
+	int iupper; //upper index limit
+        int n_loc ; /*number of rows*/
+        int *ncols; /*number of columns in each row*/
+}sparse_mat_loc;
+
+
+/* 
+  **Function to distribute a sparse matrix as blocks rows on several processes**
+  
+  A: (input) sparse matrix.
+    (matrix A as input is available on each process
+  type :(input) 0=CSR format, any other value=CSC
+  size: (input) size of the communicator
+  rk: (input) rank of the process in the communicator
+  A_loc: (output) sparse matrix in CSR reduced on local process
+  */
+  
+int dist_matrix(int n, int *ptr, int* id_rows, double *vals, int type, int size, int rk,int * mapptr,int *maptmp, int *iwork1 ,sparse_mat_loc *A_loc)
+{
+  	int     i, j, ilower, iupper;
+	int     n_loc, nnz_loc, relpos;
+	int     *marker;
+	
+	/* Compute the number of rows to distribute to local process */
+    n_loc =n/size;
+    if(rk==size-1) n_loc=n_loc+n%size;
+
+   
+   int i1,i2,ncols;	
+    //save the lower index (ilower) and upper (iupper) for each process
+    (A_loc)->ilower=rk*(n/size);
+    ilower=(A_loc)->ilower;
+    (A_loc)->iupper=(rk+1)*(n/size)-1; 
+    if(rk==size-1) (A_loc)->iupper=(A_loc)->iupper+n%size;
+    iupper=(A_loc)->iupper;
+    (A_loc)->n_loc=n_loc;
+  
+    
+	
+        if( !((A_loc)->ptr=(int *)malloc((n_loc+1)*sizeof(int))) ) {printf("%s","Malloc fails for ptr \n"); exit(1);}
+	if( !((A_loc)->rows=(int *)malloc((n_loc)*sizeof(int))) ) {printf("%s","Malloc fails for rows \n");exit(1);}
+	if( !((A_loc)->ncols=(int *)malloc((n_loc)*sizeof(int))) ) {printf("%s","Malloc fails for ncols \n");exit(1);}
+	
+    //Change global Input matrix (A) to local (A_loc) on each process
+	if(type==0){  //Matrix A is in CSR format
+		
+		//Gets local nnz 
+		 i1=(A_loc)->ilower;
+	         i2=(A_loc)->iupper; 
+		 (A_loc)->ilower=i1; (A_loc)->iupper=i2; nnz_loc=0;
+		 for(i=i1;i<=i2;i++){
+			nnz_loc+=ptr[i+1]-ptr[i];
+		 }
+		//Allocate memory for local matrix
+		
+		
+		if( !((A_loc)->id_cols=(int *)malloc(nnz_loc*sizeof(int))) ) {printf("%s","Malloc fails for id_cols \n");exit(1);}
+		if( !((A_loc)->vals=(double *)malloc(nnz_loc*sizeof(double))) ) {printf("%s","Malloc fails for vals"); exit(1);}
+		
+		//Transfer the corresponding values from global to local
+		relpos=0; 
+		//int ncols; //count number of elements in each row
+		for(i=i1;i<=i2;i++){
+			(A_loc)->rows[i-i1]=i;
+			(A_loc)->ptr[i-i1]=relpos;
+			ncols=relpos;
+			for(j=ptr[i];j<ptr[i+1];j++){
+				(A_loc)->id_cols[relpos]=id_rows[j];
+				(A_loc)->vals[relpos]=vals[j];
+				relpos++;
+			}
+			(A_loc)->ncols[i-i1]=relpos-ncols;
+		}
+		//cout << "taille des sous domaines" << nnz_loc << endl;
+	}
+	else{ //matrix A is in CSC format
+		marker= (int *)calloc(n, sizeof(int)); //count number of elements in each row
+		for(i=0; i<n; i++)
+			for(j=ptr[i]; j<ptr[i+1]; j++)
+				marker[id_rows[j]]++;
+		
+		(A_loc)->ptr[0]=0; //set up the beginning of each row
+		for(i=0; i<n_loc; i++){
+			(A_loc)->ptr[i+1] = (A_loc)->ptr[i] + marker[i+ilower];
+				(A_loc)->id_cols[relpos]=id_rows[j];
+				(A_loc)->vals[relpos]=vals[j];
+				relpos++;
+			}
+			(A_loc)->ncols[i-ilower]=relpos-ncols;
+		}
+    return 0;
+}
+
+
+
+
+class hypreParam {
+ //Solveur and preconditionner
+  public: 
+  char  solver[BUFLEN];
+  char  precon[BUFLEN];
+ //BoomerAMG parameter
+  int                  amg_coarsentype ;    /* Falgout coarsening */
+  int                  amg_relaxtype;      /* hybrid Gauss-Seidel or SOR */ 
+  int			amg_interptype;		/* default*/
+  int 			amg_maxlevels;
+  int                  amg_numsweeps;        /*default*/
+  double               amg_strongthreshold;/*suitable for 3D Laplace Operator*/
+  double		amg_truncfactor; 
+  int                  amg_prntlevel;        /* print setup info */
+  double			amg_tol;			//BoomerAMG Tolerance
+  int			amg_maxiter;
+  int 			scale;
+  int 			gsmg_sample, measure_type,cycle_type;
+  int                  solv_stopcrit ;
+  double trunc_factor;
+   
+  //More complex smoothers (Schwarz methods, Pilut, Parasails, Euclid)
+  int					smooth_type;
+  int 					smooth_numlevels; 
+  int 					smooth_numsweeps;
+  double				pilut_droptol;
+  double 				pilut_maxnz;
+  int					schwarz_overlap;
+  int 					schwarz_variant;
+  int					schwarz_domaintype;
+  
+  //parasails parameter
+  int                  sai_max_levels ;
+  double               sai_threshold ;
+
+  double               sai_filter ;
+  int                  sai_sym ;
+  int                  sai_log ;
+  int                  VERBOSE;
+
+  /***************************HYPRE_BOOMERAMG***********************/
+  double strong_threshold;
+ 
+  int * num_grid_sweeps;  
+  int * grid_relax_type;  
+  int * grid_relax_points;
+  double * relax_weight;
+  double *  omega;   
+  //Solver parameter (used for GMRES , PCG or BiCGStab)
+  double               solv_tol ;
+  int                  solv_maxiter;
+  int                  solv_kdim;
+  int                  solv_log;
+  int                  solv_prntlevel;
+  int                     precond_id, solver_id,matrix_id,solver_type;
+  int smooth_num_levels,smooth_num_sweeps,max_levels,Two_Norm;
+  int domain_type, num_functions,variant,overlap,nonzeros_to_keep;
+  double max_row_sum,drop_tol;
+  int *dof_func; 
+  int                 pcg_max_its,rrow_size,Rel_change;
+  int                 dscg_max_its,coarsen_type,hybrid,k_dim,num_sweep; 
+  int 		      pmax_iter;
+  double              cf_tol,tol,pc_tol;
+  double schwarz_rlx_weight;
+ 
+  /*For timing*/
+  int timing;
+public : hypreParam(const KN<long> &param_int, const KN<double> &param_double)
+  {
+    amg_coarsentype =6;    /* Falgout coarsening */
+    amg_relaxtype =3;      /* hybrid Gauss-Seidel or SOR */ 
+    amg_interptype=0;		/* default*/
+    amg_maxlevels=25;
+    amg_numsweeps=1;        /*default*/
+    amg_strongthreshold = 0.25;/*suitable for 3D Laplace Operator*/
+    amg_truncfactor=0.3; 
+    amg_prntlevel =1;        /* print setup info */
+    amg_tol=0.0;			//BoomerAMG Tolerance
+    amg_maxiter=20;
+    gsmg_sample=1;
+   //More complex smoothers (Schwarz methods, Pilut, Parasails, Euclid)
+    smooth_type=6;
+    smooth_numlevels=3; 
+    smooth_numsweeps=1;
+    pilut_droptol=1.0e-4;
+    pilut_maxnz=100;
+    schwarz_overlap=10;
+    schwarz_variant=2;
+    schwarz_domaintype=2;
+   //parasails parameter
+    sai_max_levels = 1;
+    sai_threshold = 0.1;
+    sai_filter = 0.1;
+    sai_sym =0;
+    sai_log = 1;
+    int i;
+			
+   //Solver parameter (used for GMRES or BiCGStab)
+    solv_tol = 1.0e-11;
+    solv_maxiter = 1000;
+    solv_kdim =40;
+    
+    solv_log = 0;
+    solv_prntlevel = 2;
+    precond_id=0;//BOOMER AMG 	
+    solver_id=1; //GMRES as solver
+    VERBOSE=0;
+    scale=1;
+    pmax_iter=30;
+    rrow_size=1000;
+    solv_stopcrit=1;
+
+    amg_interptype =6;  gsmg_sample =5; amg_coarsentype =6; 
+
+    measure_type =1;amg_strongthreshold=0.25; trunc_factor=1e-2; 
+
+    amg_maxiter=20; cycle_type=1;  smooth_num_levels=3; 
+    smooth_num_sweeps=1; max_levels=25; hybrid=1;
+   k_dim = 5;  smooth_type = 6;  num_functions = 1;  smooth_num_levels = 3;
+   smooth_num_sweeps = 2; num_sweep = 1;      variant = 0;
+   overlap = 10;  domain_type = 2;     nonzeros_to_keep = 1000;
+   tol = 1.e-8;  pc_tol = 0.;
+   drop_tol = -1.;  max_row_sum = 0.9; schwarz_rlx_weight = 1.;  sai_threshold = 0.1;
+   sai_filter = 0.1;
+	
+
+    relax_weight      = hypre_CTAlloc(double, max_levels);
+    omega             = hypre_CTAlloc(double, max_levels);
+    for (i=0; i < max_levels; i++)
+      {
+	relax_weight[i] = 1.;
+	omega[i] = 1.;
+      }
+    max_row_sum=0.9;  schwarz_rlx_weight=1.; variant=0; 
+    num_functions=1; overlap=10; domain_type= 2;
+		  		 	 
+    if(param_int.N()>0) {if((param_int[0]>=0)&&(param_int[0]<=9)) solver_id=param_int[0]; 
+      else solver_id=1;} //GMRES as solver
+	       
+    if((solver_id!=4)&&(solver_id!=5)){      
+      if(param_int.N()>1) {if((param_int[1]>=0)&&(param_int[1]<=9)) 
+	  precond_id=param_int[1]; else precond_id=0;}//BOOMER AMG }
+      if(param_int.N()>2) {if(param_int[2]>0)  solv_maxiter = param_int[2];else solv_maxiter=1000;}
+      if(param_int.N()>3) {if(param_int[3]>0)  solv_kdim =param_int[3];else solv_kdim=40;}
+      if(param_int.N()>4) {if(param_int[4]>=0) solv_prntlevel = param_int[4];}
+      if(param_int.N()>5) {if(param_int[5]>=0) solv_log = param_int[5];}
+      if(param_int.N()>6) {if(param_int[6]>=0) solv_stopcrit = param_int[6];}
+		
+
+      if(param_double.N()>0) {if(param_double[0]>0) solv_tol = param_double[0];}
+      switch(precond_id)
+	{
+	case 0 : //Preconditionner AMG
+	  if(param_int.N()>7)  {if(param_int[7]>=0) amg_interptype =param_int[7];}
+	  if(param_int.N()>8)  {if(param_int[8]>=0) gsmg_sample =param_int[8];}
+	  if(param_int.N()>9)  {if(param_int[9]>=0) amg_coarsentype =param_int[9];}
+	  if(param_int.N()>10) {if(param_int[10]>=0) measure_type =param_int[10];}
+	  if(param_double.N()>1) {if(param_double[1]>0) amg_strongthreshold = param_double[1];}
+	  if(param_double.N()>2) {if(param_double[2]>0) trunc_factor = param_double[2];}
+	  //if(param_int.N()>11)  {if(param_int[11]>0) amg_maxiter=param_int[11];}
+	  if(param_int.N()>11)  {if(param_int[11]>0) cycle_type=param_int[11];}
+	  if(param_int.N()>12)  {if(param_int[12]>0)  smooth_type=param_int[12];}
+	  if(param_int.N()>13) {if(param_int[13]>0) smooth_num_levels=param_int[13];}
+	  if(param_int.N()>14) {if(param_int[14]>0) smooth_num_sweeps=param_int[14];}
+	  if(param_int.N()>15) {if(param_int[15]>0) max_levels = param_int[15];}
+	  relax_weight      = hypre_CTAlloc(double, max_levels);
+	  omega      = hypre_CTAlloc(double, max_levels);
+	  for (i=0; i < max_levels; i++)
+	    {
+	      relax_weight[i] = 1.;
+	      omega[i] = 1.;
+	    }
+	  if(param_double.N()>3) {if(param_double[3]>0) max_row_sum = param_double[3];else max_row_sum=0.9;} else max_row_sum=0.9;
+	  if(param_double.N()>4) {if(param_double[4]>0) schwarz_rlx_weight = param_double[4];else schwarz_rlx_weight=1.;} else schwarz_rlx_weight=1.;
+	  if(param_int.N()>16) {if(param_int[16]>0) variant = param_int[16];else variant=3;} else variant=3;
+	  if(param_int.N()>17) {if(param_int[17]>0) num_functions = param_int[17];else num_functions=1;} else num_functions=1;
+	  if(param_int.N()>18) {if(param_int[18]>0) overlap = param_int[18];else overlap=10;} else overlap=10;
+	  if(param_int.N()>19) {if(param_int[19]>0) domain_type = param_int[19]; else domain_type= 2;} else domain_type= 2;				
+	  break;
+	  
+	case 1: //Preconditionner PILUT
+	  
+	  if(param_double.N()>1) {if(param_double[1]>0) drop_tol = param_double[1]; else drop_tol=1e-5;} else drop_tol=1e-5;
+	  if(param_int.N()>7)    {if(param_int[7]>0) nonzeros_to_keep = param_int[7]; else nonzeros_to_keep=1000;} else nonzeros_to_keep=1000;
+	  if(param_int.N()>8)    {if(param_int[8]>0) pmax_iter = param_int[8];}
+	  if(param_int.N()>9)    {if(param_int[9]>0) rrow_size = param_int[9];} 
+	  
+	  break;
+
+	case 2://Preconditionner ParaSails
+	  if(param_double.N()>1) {if(param_double[1]>0) sai_filter = param_double[1];else sai_filter=0.1;} else sai_filter=0.1;
+	  if(param_double.N()>2) {if(param_double[2]>0) sai_threshold = param_double[2];else sai_threshold=0.1;} else sai_threshold=0.1;
+	  if(param_int.N()>7)    {if(param_int[7]>0) max_levels = param_int[7];else max_levels=1;} else max_levels=1;
+	  if(param_int.N()>8)    {if(param_int[8]>0) sai_sym =param_int[8];else sai_sym=0;} else sai_sym=0;
+	  break;
+
+	case 3: //Preconditionner Schwarz
+	  if(param_double.N()>1) {if(param_double[1]>0) schwarz_rlx_weight = param_double[1];schwarz_rlx_weight=1;} 
+	  else schwarz_rlx_weight=1.;
+	  if(param_int.N()>7)    {if(param_int[7]>0) variant = param_int[7];else variant=1;} else variant=1;
+	  if(param_int.N()>8)    {if(param_int[8]>0) overlap = param_int[8];else overlap=1;} else overlap=1;
+	  if(param_int.N()>9)    {if(param_int[9]>0) domain_type = param_int[9];else domain_type=3;} else domain_type=3;
+	  break;
+
+	default:
+	  break;
+	}
+    }
+
+
+	
+		if(solver_id==4) // Solver AMG_HYBRID
+		{
+		 
+		 if(param_double.N()>1)  {if(param_double[1]>=0) amg_tol =param_double[1];else amg_tol=1e-9;} else amg_tol=1e-9;
+		 if(param_double.N()>2)  {if(param_double[2]>=0) cf_tol =param_double[2];else cf_tol= 1e-3;}  else cf_tol= 1e-3;
+		 if(param_int.N()>1)  {if(param_int[1]>=0) solver_type =param_int[1];else solver_type=1;} else solver_type=1;
+		 if(param_int.N()>2)  {if(param_int[2]>0) dscg_max_its=param_int[2];else dscg_max_its=1000;}  else dscg_max_its=1000;
+		 if(param_int.N()>3)  {if(param_int[3]>0) pcg_max_its=param_int[3];else pcg_max_its=200;}   else pcg_max_its=200;
+		 if(param_int.N()>4)  {if(param_int[4]>0) coarsen_type=param_int[4]; else coarsen_type=6;}  else coarsen_type=6;
+		 if(param_double.N()>3) {if(param_double[3]>0) strong_threshold = param_double[3]; else strong_threshold=1e-3;} else strong_threshold=1e-3;
+		 if(param_double.N()>4) {if(param_double[4]>0) trunc_factor = param_double[4]; else trunc_factor=1e-2;} else trunc_factor=1e-2;
+		 if(param_int.N()>5) {if(param_int[5]>0) max_levels = param_int[5]; else max_levels=25;} else max_levels=25;
+        	 if(param_double.N()>5) {if(param_double[5]>0) max_row_sum = param_double[5];else max_row_sum=0.9;} else max_row_sum=0.9;
+
+		 relax_weight      = hypre_CTAlloc(double, max_levels);
+   		 omega      = hypre_CTAlloc(double, max_levels);
+		for (i=0; i < max_levels; i++)
+		   {
+			relax_weight[i] = 1.;
+			omega[i] = 1.;
+		   }
+		}
+		if(solver_id==3)
+		{
+			if(param_int.N()>7)  {if(param_int[7]>=0) Two_Norm =param_int[7];else Two_Norm=2;} else Two_Norm=2;
+			if(param_int.N()>8)  {if(param_int[8]>=0) Rel_change =param_int[8];else Rel_change=1;} else Rel_change=1;
+		}
+		if(solver_id==5) //Solver AMG
+		{
+		 if(param_int.N()>7)  {if(param_int[7]>=0) amg_interptype =param_int[7];}
+		 if(param_int.N()>8)  {if(param_int[8]>=0) gsmg_sample =param_int[8];}
+		 if(param_int.N()>9)  {if(param_int[9]>=0) amg_coarsentype =param_int[9];}
+		 if(param_int.N()>10) {if(param_int[10]>=0) measure_type =param_int[10];}
+   		 if(param_double.N()>2) {if(param_double[2]>0) amg_strongthreshold = param_double[2];}
+   		 if(param_double.N()>3) {if(param_double[3]>0) trunc_factor = param_double[3];}
+                 if(param_int.N()>11)  {if(param_int[11]>0) amg_maxiter=param_int[11];}
+		 if(param_int.N()>12)  {if(param_int[12]>0) cycle_type=param_int[12];}
+		 if(param_int.N()>13)  {if(param_int[13]>0)  smooth_type=param_int[13];}
+		 if(param_int.N()>14) {if(param_int[14]>0) smooth_num_levels=param_int[14];}
+  		 if(param_int.N()>15) {if(param_int[15]>0) smooth_num_sweeps=param_int[15];}
+		 if(param_int.N()>16) {if(param_int[16]>0) max_levels = param_int[16];}
+		 relax_weight      = hypre_CTAlloc(double, max_levels);
+   		 omega      = hypre_CTAlloc(double, max_levels);
+		for (i=0; i < max_levels; i++)
+		   {
+			relax_weight[i] = 1.;
+			omega[i] = 1.;
+		   }
+		 if(param_double.N()>4) {if(param_double[4]>0) max_row_sum = param_double[4];else max_row_sum=1e-1;} else max_row_sum=1e-1;
+		 if(param_double.N()>5) {if(param_double[5]>0) schwarz_rlx_weight = param_double[5];else schwarz_rlx_weight=1.;} else schwarz_rlx_weight=1.;
+		 if(param_int.N()>17) {if(param_int[17]>0) variant = param_int[17];else variant=1;} else variant=1;
+		 if(param_int.N()>19) {if(param_int[18]>0) num_functions = param_int[18];else num_functions=5;} else num_functions=5;
+		 if(param_int.N()>20) {if(param_int[19]>0) overlap = param_int[19];else overlap=1;} else overlap=1;
+		 if(param_int.N()>21) {if(param_int[20]>0) domain_type = param_int[20];else domain_type= 1;} else domain_type= 1;
+		}
+		if(param_int.N()>22) {if(param_int[22]>0) VERBOSE = param_int[22];}
+		if(param_int.N()>23) {if(param_int[23]>0) scale = param_int[23]; else scale=1;} else scale=1;
+		if(param_int.N()>24) {if(param_int[24]>0) timing = param_int[24]; else timing=1;} else timing=1; 
+             }
+
+  public : hypreParam()
+	{
+		int i;
+		amg_coarsentype =6;    /* Falgout coarsening */
+   		amg_relaxtype =3;      /* hybrid Gauss-Seidel or SOR */ 
+	 	amg_interptype=0;		/* default*/
+   		amg_maxlevels=25;
+   		amg_numsweeps=1;        /*default*/
+		amg_strongthreshold = 0.25;/*suitable for 3D Laplace Operator*/
+   		amg_truncfactor=0.3; 
+		amg_prntlevel =1;        /* print setup info */
+		amg_tol=1e-7;			//BoomerAMG Tolerance
+		amg_maxiter=1;
+		gsmg_sample=1;
+	
+   
+			
+   //Solver parameter (used for GMRES or BiCGStab)
+   		solv_tol = 1.0e-11;
+		solv_maxiter = 1000;
+		solv_kdim =40;
+
+		solv_log = 0;
+		solv_prntlevel = 2;
+		precond_id=0;//BOOMER AMG 	
+		solver_id=1; //GMRES as solver
+	        VERBOSE=0;
+		scale=1;
+                pmax_iter=30;
+		rrow_size=1000;
+
+
+		amg_interptype =0;  gsmg_sample =1; amg_coarsentype =6; measure_type =1;amg_strongthreshold=0.25;
+		trunc_factor=1e-2;  amg_maxiter=20; cycle_type=1; smooth_type=6; smooth_num_levels=0; smooth_num_sweeps=2; max_levels=25;
+
+		relax_weight      = hypre_CTAlloc(double, max_levels);
+   		omega             = hypre_CTAlloc(double, max_levels);
+		for (i=0; i < max_levels; i++)
+		   {
+			relax_weight[i] = 1.;
+			omega[i] = 1.;
+		   }
+		 max_row_sum=0.9;  schwarz_rlx_weight=1.; variant=0;  num_functions=1; overlap=10; domain_type= 0;
+		
+		 
+
+
+		
+	}
+  public : hypreParam(char * fileparameter, MPI_Comm comm)
+	{
+		FILE *f;
+        	char buf[BUFLEN];
+		int num;
+		int rk, size;
+		MPI_Comm_rank(comm,&rk);
+		MPI_Comm_size(comm, &size);
+
+		
+		amg_coarsentype =6;    /* Falgout coarsening */
+   		amg_relaxtype =3;      /* hybrid Gauss-Seidel or SOR */ 
+	 	amg_interptype=0;		/* default*/
+   		amg_maxlevels=25;
+   		amg_numsweeps=1;        /*default*/
+		amg_strongthreshold = 0.25;/*suitable for 3D Laplace Operator*/
+   		amg_truncfactor=0.3; 
+		amg_prntlevel =1;        /* print setup info */
+		amg_tol=0.0;			//BoomerAMG Tolerance
+		amg_maxiter=20;
+   //More complex smoothers (Schwarz methods, Pilut, Parasails, Euclid)
+		smooth_type=6;
+		smooth_numlevels=3; 
+		smooth_numsweeps=1;
+		pilut_droptol=1.0e-4;
+ 		pilut_maxnz=100;
+		schwarz_overlap=10;
+		schwarz_variant=2;
+		schwarz_domaintype=2;
+   //parasails parameter
+  		sai_max_levels = 1;
+		sai_threshold = 0.1;
+		sai_filter = 0.05;
+	        sai_sym =0;
+	        sai_log = 1;
+	
+   //Solver parameter (used for GMRES or BiCGStab)
+   		solv_tol = 1.0e-30;
+		solv_maxiter = 80;
+		solv_kdim =40;
+  //  int                  solv_stopcrit = 1; //only for BiCGSTAB
+		solv_log = 0;
+		solv_prntlevel = 0;
+		precond_id=0;//BOOMER AMG 	
+		solver_id=1; //GMRES as solver
+		VERBOSE=0;
+		scale=1;
+		
+
+
+
+		if(fileparameter==NULL)
+		{
+			if(rk==0) printf("%s","Set default parameter because you not precise the parameter file \n \n");
+			solver_id=1; //GMRES as solver
+			precond_id=0;//BOOMER AMG 
+		
+		}
+		else if( (f=fopen(fileparameter,"r") )==NULL)
+			{
+			if(rk==0)printf("%s","Set default parameter because your parameter file not exist \n \n");
+			solver_id=1; //GMRES as solver
+			precond_id=0;//BOOMER AMG 	
+			}	
+			else
+			{
+			 if(rk==0) printf("%s%s%s","Read parameter from file ", fileparameter, "\n \n");
+			 num =0;
+			 while(fgets(buf, BUFLEN, f) != NULL) 
+			 {
+				switch(num) {
+				case 0:
+				sscanf(buf, "%s", solver); 
+				break;
+				case 1:
+ 				sscanf(buf, "%d", &solver_id);
+			        break;
+				case 2:
+ 				sscanf(buf, "%lf", &solv_tol);
+			        break;
+				case 3:
+ 				sscanf(buf, "%d", &solv_maxiter);
+			        break;
+				case 4:
+ 				sscanf(buf, "%d", &solv_prntlevel);
+			        break;
+				case 5:
+ 				sscanf(buf, "%d", &solv_log);
+				if(solver_id!=1) {fgets(buf, BUFLEN, f);num++;}
+				break;				
+				case 6:
+				sscanf(buf, "%d", &solv_kdim);
+			        break;
+				case 7:
+				sscanf(buf, "%s", precon); 
+				break;
+				case 8:
+				sscanf(buf, "%d", &precond_id); 
+				 	
+				if(precond_id==2) //The parameter of preconditionner is inside file
+				{
+					fclose(f);
+					exit(1);
+				}
+				break;
+				case 9:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_coarsentype); 
+				if(precond_id==1)
+				sscanf(buf, "%lf", &sai_threshold); 
+				break;
+				case 10:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_prntlevel); 
+				if(precond_id==1)
+				sscanf(buf, "%d", &sai_max_levels); 
+				break;
+				case 11:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_interptype); 
+				if(precond_id==1)
+				sscanf(buf, "%lf", &sai_filter); 
+				break;
+				case 12:
+				if(precond_id==0)
+				sscanf(buf, "%d", &amg_maxlevels); 
+				if(precond_id==1)
+				case 17:
+				sscanf(buf, "%d", &amg_prntlevel); 
+				break;
+				case 18:
+				sscanf(buf, "%lf", &amg_tol); 
+				break;
+				case 19:
+				sscanf(buf, "%d", &amg_maxiter); 
+				break;	
+				case 20:
+				sscanf(buf, "%d", &scale); 
+				break;						
+				default:
+				break;
+				}	
+         		 num++;	
+			 }
+			 if(fclose(f)==EOF) printf("%s","Error while closing the file \n"); else printf("%s","File is well close \n");			
+			}
+	}
+	
+};
+
+class HypreSolver :   public MatriceMorse<double>::VirtualSolver   {
+  mutable HYPRE_IJMatrix       ij_A;
+  mutable HYPRE_IJVector       ij_B;
+  mutable HYPRE_IJVector       ij_X;
+  mutable HYPRE_ParCSRMatrix   par_A;
+  mutable HYPRE_ParVector      par_B;
+  mutable HYPRE_ParVector      par_X;
+  void               *object;
+  HYPRE_ParCSRMatrix  parcsr_A;
+
+  string data_option;
+  mutable int		       time_index,time_index1;
+  mutable HYPRE_Solver         solver;
+  mutable HYPRE_Solver         precond;
+  mutable hypreParam           *param;
+  mutable double *scaletmpr, *scaletmpc;
+  mutable int rk,size;
+  int                  jlower, jupper;
+  int                  ilower, iupper;
+  mutable    int num_iter;
+  mutable   double 		final_res_norm;
+  mutable   double 		tgv,eps,tol_pivot,tol_pivot_sym,epsr;
+  sparse_mat_loc	A_loc;
+  mutable int *iwork, *maptmp, *mapptr, *iwork1,*riord;
+  mutable int n_loc,n,VERBOSE;
+  mutable MPI_Comm comm;
+  mutable int pcg_num_its,dscg_num_its; 
+
+ 
+public:
+  HypreSolver(const MatriceMorse<double> &AA,string datafile,
+	      KN<long> &param_int,  KN<double> &param_double,  
+	      MPI_Comm  * mpicommw )	
+  { 
+    int i,j,ierrr;
+    if(mpicommw==NULL){
+     comm=MPI_COMM_WORLD; 
+    }
+    else
+      comm= *mpicommw;
+	
+    /*****INITIALIZE MPI ENVIRONMENT*****/
+
+    ierrr = MPI_Comm_rank(comm, &rk);
+    ierrr = MPI_Comm_size(comm, &size);
+
+    
+    if(((param_double!=NULL)||(param_int!=NULL))&&(datafile.empty()))
+      {
+	if(rk==0)
+	  cout << "#########PARAMETERS ARE SET INSIDE A VECTOR###"<< endl;
+	param=new hypreParam(param_int,param_double);
+      }
+    if((datafile.empty())&&((param_int==NULL)&&(param_double==NULL)))
+      {
+	if(rk==0)
+	cout << "###########DEFAULT PARAMETERS WILL BE SET#######"<< endl;
+	param= new hypreParam();
+      }
+    if((!datafile.empty())&&((param_int==NULL)&&(param_double==NULL)))
+      {
+	if(rk==0)
+	  cout << "#########PARAMETERS ARE INSIDE A FILE#########"<< endl;
+	char *p;
+	p=new char[datafile.length()+1]; strcpy(p,datafile.c_str()); 
+	param= new hypreParam(p,comm);
+      }
+	
+    /*###################################################
+                         USING HYPRE
+    ####################################################*/
+    int n,nnz, *pr, *p,ierr;
+    double * AAv;
+    n=AA.n; nnz=AA.nbcoef;
+    /*##################################################
+                      COPY ENTRY MATRIX
+     ##################################################*/   
+	if(param->timing){
+	time_index = hypre_InitializeTiming("MATRIX DISTRIBUTION");
+   	hypre_BeginTiming(time_index);
+	}
+   
+ 
+    pr= new int[n+1];p=  new int[nnz];	AAv=new double[nnz];
+    for(i=0;i<nnz;i++){
+      AAv[i]=AA.a[i]; p[i]=AA.cl[i];
+      if(i<=n) pr[i]=AA.lg[i];
+    }
+    int job, tmp;
+    if(param->scale) {
+      job = 1; /*-- compute  1-norm */
+      tmp = 2; /*-- compute 2-norm  */
+      scaletmpr=new double[n]; 	 scaletmpc=new double[n]; 
+      roscal(n,job,tmp,AAv,p,pr,scaletmpr,&ierr);
+      if (ierr) fprintf(stderr, "ERROR: IN ROSCAL, IERR = %d\n", ierr);
+      /*------- scale the RHS according to row scaling coefficients */
+      coscal(n,job,tmp,AAv,p,pr,scaletmpc,&ierr);
+      if (ierr) fprintf(stderr, "ERROR : IN COSCAL, IERR = %d\n", ierr);
+    } /*--- end of branch on scaling */
+
+	
+	/*************************************************************
+	Distribute input matrix into local structures
+	*************************************************************/
+    int type=0,wgtflag=0, numflag=0, volume; //0=CSR; 1=CSC
+    int option[5];  option[0]=0;
+    riord=(int *)malloc(sizeof(int)*n);
+    if(riord==NULL){if(rk==0) printf("%s","IN PARTITION , MEMORY ALLOCATION FAILED \n");exit(1);}
+    /************************USE METIS FOR DATA DISTRIBUTION**************************/
+    if(size>1)
+      METIS_PartGraphKway(&n, pr, p, NULL, NULL, &wgtflag, &numflag,&size, option, &volume, riord);
+    else if(size==1){
+      for (i=0; i<n; i++) riord[i]=0;}
+    iwork= new int[n]; maptmp = new int[n]; mapptr = new int[size+1]; iwork1= new int[size+1];
+    for(i=0; i<size; i++){
+      iwork[i]=0;iwork1[i]=0; }
+    for(j=0; j<n; j++){
+      iwork[riord[j]]++;
+      iwork1[riord[j]]++;
+    }
+    numflag=0;
+    for(i=0; i<size; i++){
+      mapptr[i]=numflag;
+      numflag+=iwork[i];
+    }
+    mapptr[size]=numflag;
+
+    for (i=0; i<size; i++){
+      iwork[i]=mapptr[i];
+    }
+    for(i=0; i<n; i++){
+      maptmp[iwork[riord[i]]]=i;
+      iwork[riord[i]]++;
+    }
+    
+    dist_matrix(AA.n,pr,p,AAv, type, size, rk,mapptr,maptmp,iwork1, &A_loc); 	
+    /***Distribute vector***/
+    n_loc=A_loc.n_loc;
+    /**** Preparing Matrix *****/
+    ierr=0;
+    ilower=A_loc.ilower; jlower=ilower;	iupper=A_loc.iupper; jupper=iupper;
+    ierr+=HYPRE_IJMatrixCreate(comm, ilower, iupper, jlower, jupper, &ij_A);
+    
+	if (ierr)
+   {
+     printf("Error in driver building IJMatrix from parcsr matrix. \n");
+     exit(-1);
+   }
+        
+
+    ierr+=HYPRE_IJMatrixSetObjectType(ij_A, HYPRE_PARCSR);
+    ierr+=HYPRE_IJMatrixInitialize(ij_A);
+    
+   int taille;
+
+    for(i=ilower;i<=iupper;i++){
+	   taille=pr[i+1]-pr[i];
+	  
+	   ierr+=HYPRE_IJMatrixSetValues(ij_A, 1, &taille, &i , &(p[pr[i]]), &(AAv[pr[i]]));
+	}
+   
+    ierr+=HYPRE_IJMatrixAssemble(ij_A);
+   /*Extract HYPRE Object data structures suitable for the solvers*/
+    ierr+=HYPRE_IJMatrixGetObject(ij_A, (void **) &par_A);	   
+
+
+   /*Free local matrix in A_loc, B and X*/
+    free(A_loc.rows); free(A_loc.id_cols); free(A_loc.vals); free(A_loc.ncols); 
+    if(param->timing){
+	     hypre_EndTiming(time_index);
+   	     hypre_PrintTiming("IJ Matrix Setup", comm);
+	     hypre_FinalizeTiming(time_index);
+   	     hypre_ClearTiming();
+	}
+   
+   
+   
+    /*************************************************************
+                Create preconditioner 
+   
+                  Setup and Use solver
+   **************************************************************/
+   
+
+  param->timing=1;
+
+  
+
+   switch(param->solver_id){
+       case 0 : //BiCGStab solver
+	 HYPRE_ParCSRBiCGSTABCreate(comm, &solver);           
+	 HYPRE_ParCSRBiCGSTABSetTol(solver, param->solv_tol);
+	 HYPRE_ParCSRBiCGSTABSetMaxIter(solver, param->solv_maxiter);
+	 //HYPRE_ParCSRBiCGSTABSetStopCrit(solver, solv_stopcrit);
+	 HYPRE_ParCSRBiCGSTABSetPrintLevel(solver, param->solv_prntlevel);
+	 HYPRE_ParCSRBiCGSTABSetLogging(solver, param->solv_log);
+	
+
+            //Set Preconditioner
+	 switch (param->precond_id){
+	 case 0 : //set BoomerAMG as preconditioner
+	   if(rk==0) printf("SOLVER: BOOMERAMG-BiCGSTAB\n");
+	   HYPRE_BoomerAMGCreate(&precond);
+	
+
+	HYPRE_BoomerAMGSetInterpType(precond, param->amg_interptype);
+    
+       HYPRE_BoomerAMGSetTol(precond, param->amg_tol);
+       HYPRE_BoomerAMGSetCoarsenType(precond, param->amg_coarsentype); 
+       HYPRE_BoomerAMGSetMeasureType(precond,param-> measure_type);
+       HYPRE_BoomerAMGSetStrongThreshold(precond, param->amg_strongthreshold);
+
+       HYPRE_BoomerAMGSetTruncFactor(precond,param->trunc_factor);
+
+       HYPRE_BoomerAMGSetMaxIter(precond, param->amg_maxiter);
+       HYPRE_BoomerAMGSetCycleType(precond,param->cycle_type);
+       
+       HYPRE_BoomerAMGSetSmoothType(precond,param->smooth_type);
+       HYPRE_BoomerAMGSetSmoothNumLevels(precond,param->smooth_num_levels);
+       HYPRE_BoomerAMGSetSmoothNumSweeps(precond,param->smooth_num_sweeps);
+       HYPRE_BoomerAMGSetMaxLevels(precond,param->max_levels);
+       HYPRE_BoomerAMGSetMaxRowSum(precond,param->max_row_sum);
+       
+       HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);
+       
+      
+       HYPRE_BiCGSTABSetPrecond(solver, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup, 
+			     precond);
+	   break;
+	 case 4:
+	   /*use diagonal scaling as preconditioner*/
+	   if(rk==0) printf("SOLVER: DS-BiCGSTAB\n");
+	   precond=NULL;
+	   HYPRE_ParCSRBiCGSTABSetPrecond(solver, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScale, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScaleSetup, 
+					  precond);
+	   break;
+	 case 1:
+	   /*Use PILUT as preconditioner*/
+	   if(rk==0) printf("SOLVER: PILUT-BiCGSTAB\n");
+	   ierr=HYPRE_ParCSRPilutCreate(comm,&precond);
+	   if(ierr) printf("ERROR: PILUT-BiCGSTAB\n");
+	  
+	   if(param->drop_tol>=0)
+	     HYPRE_ParCSRPilutSetDropTolerance(precond,param->drop_tol);
+	   if(param->nonzeros_to_keep>=0)
+	     HYPRE_ParCSRPilutSetFactorRowSize(precond,param->nonzeros_to_keep);
+
+	   HYPRE_ParCSRBiCGSTABSetPrecond(solver, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSolve, 
+					  (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSetup, 
+					  precond);
+	   break;
+	 case 2:
+	   if(rk==0) printf("SOLVER: ParaSails-BicGSTAB\n");
+	   ierr=HYPRE_ParaSailsCreate(comm,&precond);
+	   if(ierr) printf("ERROR: ParaSails-BicGSTAB\n");
+	   HYPRE_ParaSailsSetParams(precond,param->sai_threshold,param->max_levels);
+	   HYPRE_ParaSailsSetFilter(precond,param->sai_filter);	  
+	   HYPRE_ParaSailsSetSym(precond,param->sai_sym);
+
+	   HYPRE_ParCSRBiCGSTABSetPrecond(solver, 
+					   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSolve, 
+					   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSetup, 
+					   precond);
+	   break;
+	case 3:
+       if(rk==0) printf("SOLVER: Schwarz-PCG \n");
+       	 HYPRE_SchwarzCreate(&precond);
+         HYPRE_SchwarzSetVariant(precond,param->variant);
+         HYPRE_SchwarzSetOverlap(precond,param->overlap);
+         HYPRE_SchwarzSetDomainType(precond,param->domain_type);
+       //HYPRE_SchwarzSetRelaxWeight(precond,param->schwarz_rlx_weight);
+       /*HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);*/
+
+       HYPRE_BiCGSTABSetPrecond(solver, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSolve, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSetup, 
+			   precond);
+
+       break;
+
+	 
+	 default: break;
+	   
+	 }
+	  
+  	break;
+  
+   case 2:/*USE PCG AS SOLVER*/
+     HYPRE_ParCSRPCGCreate(comm, &solver);
+     HYPRE_ParCSRPCGSetTol(solver, param->solv_tol);
+     HYPRE_PCGSetMaxIter(solver, param->solv_maxiter);   
+     HYPRE_PCGSetPrintLevel(solver, param->solv_prntlevel);
+     
+
+     HYPRE_PCGSetTwoNorm(solver, param->Two_Norm);
+     HYPRE_PCGSetRelChange(solver,param->Rel_change);
+     HYPRE_PCGGetPrecond(solver,&precond);
+     switch (param->precond_id){
+     case 0 : //set BoomerAMG as preconditioner in PCG
+       if(rk==0) printf("SOLVER: AMG-PCG\n");
+	HYPRE_BoomerAMGCreate(&precond);
+     
+      HYPRE_BoomerAMGSetInterpType(precond, param->amg_interptype);
+    
+       HYPRE_BoomerAMGSetTol(precond, param->amg_tol);
+       HYPRE_BoomerAMGSetCoarsenType(precond, param->amg_coarsentype); 
+       HYPRE_BoomerAMGSetMeasureType(precond,param-> measure_type);
+       HYPRE_BoomerAMGSetStrongThreshold(precond, param->amg_strongthreshold);
+
+       HYPRE_BoomerAMGSetTruncFactor(precond,param->trunc_factor);
+
+       HYPRE_BoomerAMGSetMaxIter(precond, param->amg_maxiter);
+       HYPRE_BoomerAMGSetCycleType(precond,param->cycle_type);
+       
+       HYPRE_BoomerAMGSetSmoothType(precond,param->smooth_type);
+       HYPRE_BoomerAMGSetSmoothNumLevels(precond,param->smooth_num_levels);
+       HYPRE_BoomerAMGSetSmoothNumSweeps(precond,param->smooth_num_sweeps);
+       HYPRE_BoomerAMGSetMaxLevels(precond,param->max_levels);
+       HYPRE_BoomerAMGSetMaxRowSum(precond,param->max_row_sum);
+       
+       HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);
+       
+     
+ 
+       HYPRE_PCGSetPrecond(solver, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve, 
+			     (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup, 
+			     precond);
+
+       break;
+    
+     case 2:
+       if(rk==0) printf("SOLVER: ParaSails-PCG\n");
+         ierr=HYPRE_ParaSailsCreate(comm,&precond);
+       if(ierr) printf("ERROR: ParaSails-PCG\n");
+       HYPRE_ParaSailsSetParams(precond,param->sai_threshold,param->max_levels);
+       HYPRE_ParaSailsSetFilter(precond,param->sai_filter);
+       HYPRE_ParaSailsSetSym(precond,param->sai_sym);
+       HYPRE_PCGSetPrecond(solver, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSolve, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSetup, 
+			   precond);
+       break;
+     case 3:
+       if(rk==0) printf("SOLVER: Schwarz-PCG \n");
+       HYPRE_SchwarzCreate(&precond);
+       HYPRE_SchwarzSetVariant(precond,param->variant);
+       HYPRE_SchwarzSetOverlap(precond,param->overlap);
+       HYPRE_SchwarzSetDomainType(precond,param->domain_type);
+      //HYPRE_SchwarzSetRelaxWeight(precond,param->schwarz_rlx_weight);
+       /*HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);*/
+
+       HYPRE_PCGSetPrecond(solver, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSolve, 
+			   (HYPRE_PtrToSolverFcn) HYPRE_SchwarzSetup, 
+			   precond);
+
+       break;
+
+     default: break;
+	    }
+    
+     break;
+   case 5:
+     if(rk==0) printf("SOLVER: AMG \n");
+     
+     HYPRE_BoomerAMGCreate(&solver);
+     HYPRE_BoomerAMGSetInterpType(solver, param->amg_interptype);
+     HYPRE_BoomerAMGSetNumSamples(solver, param->gsmg_sample);
+     HYPRE_BoomerAMGSetTol(solver, param->amg_tol);
+     HYPRE_BoomerAMGSetCoarsenType(solver, param->amg_coarsentype); 
+     HYPRE_BoomerAMGSetMeasureType(solver,param-> measure_type);
+     HYPRE_BoomerAMGSetStrongThreshold(solver, param->amg_strongthreshold);
+     HYPRE_BoomerAMGSetTruncFactor(solver,param->trunc_factor);
+     HYPRE_BoomerAMGSetMaxIter(solver, param->amg_maxiter);
+     HYPRE_BoomerAMGSetCycleType(solver,param->cycle_type);
+     HYPRE_BoomerAMGSetRelaxWeight(solver,param->relax_weight);
+     HYPRE_BoomerAMGSetOmega(solver,param->omega);
+    
+     HYPRE_BoomerAMGSetSmoothType(solver,param->smooth_type);
+     HYPRE_BoomerAMGSetSmoothNumLevels(solver,param->smooth_num_levels);
+     HYPRE_BoomerAMGSetSmoothNumSweeps(solver,param->smooth_num_sweeps);
+     HYPRE_BoomerAMGSetMaxLevels(solver,param->max_levels);
+     HYPRE_BoomerAMGSetMaxRowSum(solver,param->max_row_sum);
+	
+     HYPRE_BoomerAMGSetVariant(solver, param->variant);
+    // HYPRE_BoomerAMGSetNumFunctions(solver, param->num_functions);
+     //HYPRE_BoomerAMGSetSchwarzRlxWeight(solver,param->schwarz_rlx_weight);
+     HYPRE_BoomerAMGSetOverlap(solver, param->overlap);
+     HYPRE_BoomerAMGSetVariant(solver, param->domain_type);
+     /* if(param->num_functions>1)
+       HYPRE_BoomerAMGSetDofFunc(solver,param->dof_func);*/
+    
+     break;    
+   case 4:
+     if(rk==0) printf("SOLVER: AMG_HYBRID \n");
+    
+     HYPRE_ParCSRHybridCreate(&solver);
+     HYPRE_ParCSRHybridSetTol(solver, param->amg_tol);
+      
+    HYPRE_ParCSRHybridSetCoarsenType(solver,param->coarsen_type);
+     HYPRE_ParCSRHybridSetStrongThreshold(solver, param->strong_threshold);
+     HYPRE_ParCSRHybridSetTruncFactor(solver,param->trunc_factor);
+     HYPRE_ParCSRHybridSetDSCGMaxIter(solver,param->dscg_max_its);
+     HYPRE_ParCSRHybridSetPCGMaxIter(solver,param->pcg_max_its);
+     HYPRE_ParCSRHybridSetConvergenceTol(solver, param->cf_tol);
+     HYPRE_ParCSRHybridSetSolverType(solver, param->solver_type); 
+  
+     HYPRE_ParCSRHybridSetRelaxWeight(solver,param->relax_weight);
+     HYPRE_ParCSRHybridSetOmega(solver,param->omega);
+     HYPRE_ParCSRHybridSetMaxLevels(solver,param->max_levels);
+     HYPRE_ParCSRHybridSetMaxRowSum(solver,param->max_row_sum);
+    
+     break;
+  
+   case 1:/*GMRES AS SOLVER*/
+     HYPRE_ParCSRFlexGMRESCreate (comm, &solver);
+   
+     HYPRE_ParCSRFlexGMRESSetPrintLevel(solver,VERBOSE);
+ 
+     HYPRE_ParCSRFlexGMRESSetKDim(solver,param->solv_kdim);
+     HYPRE_ParCSRFlexGMRESSetMaxIter(solver, param->solv_maxiter );
+     HYPRE_ParCSRFlexGMRESSetTol(solver,param->solv_tol );     
+     HYPRE_FlexGMRESSetLogging(solver, param->solv_log);
+     HYPRE_ParCSRGMRESSetPrintLevel(solver,param->solv_prntlevel);
+     
+ //Set Preconditioner
+     switch (param->precond_id){
+     case 0 : //set BoomerAMG as preconditioner
+       if(rk==0) printf("SOLVER: AMG-GMRES\n");
+       HYPRE_BoomerAMGCreate(&precond);
+       
+       HYPRE_BoomerAMGSetInterpType(precond, param->amg_interptype);
+    
+     //  HYPRE_BoomerAMGSetTol(precond, param->amg_tol);
+       HYPRE_BoomerAMGSetCoarsenType(precond, param->amg_coarsentype); 
+       HYPRE_BoomerAMGSetMeasureType(precond,param-> measure_type);
+       HYPRE_BoomerAMGSetStrongThreshold(precond, param->amg_strongthreshold);
+
+       HYPRE_BoomerAMGSetTruncFactor(precond,param->trunc_factor);
+
+       HYPRE_BoomerAMGSetMaxIter(precond, param->amg_maxiter);
+       HYPRE_BoomerAMGSetCycleType(precond,param->cycle_type);
+       
+       HYPRE_BoomerAMGSetSmoothType(precond,param->smooth_type);
+       HYPRE_BoomerAMGSetSmoothNumLevels(precond,param->smooth_num_levels);
+       HYPRE_BoomerAMGSetSmoothNumSweeps(precond,param->smooth_num_sweeps);
+       HYPRE_BoomerAMGSetMaxLevels(precond,param->max_levels);
+       HYPRE_BoomerAMGSetMaxRowSum(precond,param->max_row_sum);
+       
+       HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);
+      
+       
+
+ 
+       HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_BoomerAMGSolve, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_BoomerAMGSetup, 
+			     precond);
+	
+       break;
+     case 4:
+       /*use diagonal scaling as preconditioner*/
+       if(rk==0) printf("SOLVER: DS-GMRES\n");
+	precond = NULL;
+      HYPRE_ParCSRFlexGMRESSetPrecond (solver, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScale, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRDiagScaleSetup, 
+			     precond);
+	
+       break;
+     case 1:
+       /*Use PILUT as preconditioner*/
+       if(rk==0) printf("SOLVER: PILUT-GMRES\n");
+       ierr=HYPRE_ParCSRPilutCreate(comm,&precond);
+    
+       HYPRE_ParCSRPilutSetMaxIter(precond,param->pmax_iter);
+       if(param->drop_tol>=0)
+	 HYPRE_ParCSRPilutSetDropTolerance(precond,param->drop_tol);
+       if(param->nonzeros_to_keep>=0)
+	 HYPRE_ParCSRPilutSetFactorRowSize(precond,param->nonzeros_to_keep);
+       if(ierr) printf("ERROR: PILUT-GMRES \n");
+      HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSolve, 
+			     (HYPRE_PtrToParSolverFcn) HYPRE_ParCSRPilutSetup, 
+			     precond);
+       break;
+  
+    case 3:
+       if(rk==0) printf("SOLVER: Schwarz-GMRES \n");
+       HYPRE_SchwarzCreate(&precond);
+       HYPRE_SchwarzSetVariant(precond,param->variant);
+       HYPRE_SchwarzSetOverlap(precond,param->overlap);
+       HYPRE_SchwarzSetDomainType(precond,param->domain_type);
+       //HYPRE_SchwarzSetRelaxWeight(precond,param->schwarz_rlx_weight);
+       /*HYPRE_BoomerAMGSetOverlap(precond, param->overlap);
+       HYPRE_BoomerAMGSetVariant(precond, param->variant);
+       HYPRE_BoomerAMGSetDomainType(precond, param->domain_type);*/
+
+      HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_SchwarzSolve, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_SchwarzSetup, 
+			   precond);
+
+       break;    
+   case 2:
+       if(rk==0) printf("SOLVER: ParaSails-GMRES\n");
+       ierr=HYPRE_ParaSailsCreate(comm,&precond);
+	
+       if(ierr) printf("ERROR: ParaSails-GMRES\n");
+       HYPRE_ParaSailsSetParams(precond,param->sai_threshold,param->max_levels);
+       HYPRE_ParaSailsSetFilter(precond,param->sai_filter);
+       HYPRE_ParaSailsSetSym(precond,param->sai_sym);
+	
+       HYPRE_ParCSRFlexGMRESSetPrecond(solver, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSolve, 
+			   (HYPRE_PtrToParSolverFcn) HYPRE_ParaSailsSetup, 
+			   precond);
+	
+       break; 
+     }
+     
+   default:
+	
+     break;
+   }
+	
+
+}
+	
+	void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+	 ffassert ( &x[0] != &b[0]);
+	 epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+	 int i, i1,i2;
+	 int *row,*row1;
+	 double * b_loc,*X_loc,*rhs,*xx;
+	 n=AA.n;
+
+	 rhs= (double *)malloc(sizeof(double)*n);
+	 xx= (double *)malloc(sizeof(double)*n);
+	 x= (double *)malloc(sizeof(double)*n);
+	 i1=ilower;
+	 i2=iupper; 
+	double t2,t1;
+	
+	
+
+	
+	for(i=0;i<n;i++) rhs[i]=b[i];
+
+	if(param->scale)
+	      for(i = 0; i < n; i++) 
+		rhs[i] *= scaletmpr[i];
+   	
+	b_loc=(double *)malloc(n_loc*sizeof(double));
+	X_loc=(double *)malloc(n_loc*sizeof(double));
+	row=(int *)malloc(n_loc*sizeof(int));
+	row1=(int *)malloc(n_loc*sizeof(int));
+	
+	for(i=i1;i <=i2; i++){
+	// node = maptmp[i];
+	b_loc[i-i1]=rhs[i];
+	X_loc[i-i1]=0.0;  //Initial Guest
+	row[i-i1]=i;  //used to get results later
+	row1[i-i1]=i;
+	}
+       int ierr=0;
+	HYPRE_IJVectorCreate(comm, ilower, iupper, &ij_B);
+	HYPRE_IJVectorCreate(comm, ilower, iupper, &ij_X);
+	
+
+	 HYPRE_IJVectorSetObjectType(ij_B, HYPRE_PARCSR);
+	 HYPRE_IJVectorSetObjectType(ij_X, HYPRE_PARCSR);
+	  
+	
+	
+	 HYPRE_IJVectorInitialize(ij_B);
+	 HYPRE_IJVectorInitialize(ij_X);
+	 
+	 HYPRE_IJVectorSetValues(ij_B, n_loc, row, b_loc); 
+	
+   	 HYPRE_IJVectorSetValues(ij_X, n_loc, row, X_loc);
+	  
+	 HYPRE_IJVectorAssemble(ij_B);
+	 HYPRE_IJVectorAssemble(ij_X);
+       
+	 ierr=HYPRE_IJVectorGetObject(ij_B, (void **) &par_B); 
+        
+	 
+   	ierr=HYPRE_IJVectorGetObject(ij_X, (void **) &par_X);
+         
+ 	
+	
+	switch (param->solver_id){
+	case 0 : //BICGSTAB solver
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("BiCGSTAB SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	  HYPRE_ParCSRBiCGSTABSetup (solver, par_A, par_B, par_X);
+	 if(param->timing){
+	      hypre_EndTiming(time_index1);
+	      hypre_PrintTiming("BiCGSTAB SETUP TIME", comm);
+	      hypre_FinalizeTiming(time_index1);
+	      hypre_ClearTiming();}
+
+	   if(param->timing){
+	    time_index1 = hypre_InitializeTiming("ParCSR BICGSTAB Solver");
+	    hypre_BeginTiming(time_index1);}
+
+		  
+	   HYPRE_ParCSRBiCGSTABSolve (solver, par_A, par_B, par_X);
+	   
+	   if(param->timing){
+	      hypre_EndTiming(time_index1);
+	      hypre_PrintTiming("SOLVE PHASE TIMES", comm);
+	      hypre_FinalizeTiming(time_index1);
+	      hypre_ClearTiming();}
+
+
+
+	   HYPRE_ParCSRBiCGSTABGetNumIterations(solver, &num_iter);
+	   HYPRE_ParCSRBiCGSTABGetFinalRelativeResidualNorm(solver, &final_res_norm);
+		
+		  //HYPRE_ParCSRBiCGSTABDestroy(solver);
+                    break;
+	case 1 : //GMRES Solver
+            if(param->timing){
+	   time_index1 = hypre_InitializeTiming("GMRES SETUP");
+	   hypre_BeginTiming(time_index1);
+	   }
+
+	     HYPRE_FlexGMRESSetup(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X);
+	   if(param->timing){
+	   hypre_EndTiming(time_index);
+      	   hypre_PrintTiming("SETUP PHASE TIME", comm);
+           hypre_FinalizeTiming(time_index);
+       	   hypre_ClearTiming();
+	     }
+	  
+	 
+	    if(param->timing){
+	    time_index1 = hypre_InitializeTiming("ParCSR GMRES Solver");
+	    hypre_BeginTiming(time_index1);
+		
+		}
+
+	 HYPRE_FlexGMRESSolve(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X);
+	  if(param->timing){
+	    hypre_EndTiming(time_index1);
+	    hypre_PrintTiming("Solve phase times", comm);
+	    hypre_FinalizeTiming(time_index1);
+	    hypre_ClearTiming();}
+
+	 HYPRE_GMRESGetNumIterations(solver, &num_iter);
+	 HYPRE_GMRESGetFinalRelativeResidualNorm(solver, &final_res_norm);
+		
+		//HYPRE_ParCSRGMRESDestroy(solver);
+                    break;
+	case 2 : //PCG
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("PCG SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	
+	  HYPRE_PCGSetup(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X);
+	   if(param->timing){
+	       hypre_EndTiming(time_index);
+	       hypre_PrintTiming("SETUP PHASE TIME", comm);
+	       hypre_FinalizeTiming(time_index);
+	       hypre_ClearTiming();
+	     }
+	 
+	  if(param->timing){
+	    time_index1 = hypre_InitializeTiming("ParCSR PCG Solve");
+	    hypre_BeginTiming(time_index1);}
+
+	  HYPRE_PCGSolve(solver, (HYPRE_Matrix)par_A, (HYPRE_Vector)par_B, (HYPRE_Vector)par_X); 
+
+	  if(param->timing){
+	    hypre_EndTiming(time_index1);
+	    hypre_PrintTiming("Solve phase times", comm);
+	    hypre_FinalizeTiming(time_index1);
+	    hypre_ClearTiming();}
+
+ 	
+	  HYPRE_ParCSRPCGGetNumIterations(solver,&dscg_num_its);
+	  HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver,&final_res_norm);
+
+	  break;
+	case 4:
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("HYBRID SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	  HYPRE_ParCSRHybridSetup(solver,par_A,par_B,par_X);
+	   if(param->timing){
+      	  hypre_EndTiming(time_index);
+       	  hypre_PrintTiming("SETUP PHASE TIME", comm);
+     	  hypre_FinalizeTiming(time_index);
+      	  hypre_ClearTiming();
+  	   }
+
+	   if(param->timing){
+	  time_index1 = hypre_InitializeTiming("ParCSR Hybrid Solve");
+	  hypre_BeginTiming(time_index1);}
+
+	  HYPRE_ParCSRHybridSolve(solver,par_A,par_B,par_X);
+	  if(param->timing){
+	  hypre_EndTiming(time_index1);
+	  hypre_PrintTiming("Solve phase times", comm);
+	  hypre_FinalizeTiming(time_index1);
+	  hypre_ClearTiming();}
+
+	  HYPRE_ParCSRHybridGetNumIterations(solver,&num_iter);
+	  HYPRE_ParCSRHybridGetPCGNumIterations(solver,&pcg_num_its);
+	  HYPRE_ParCSRHybridGetDSCGNumIterations(solver,&dscg_num_its);
+	  HYPRE_ParCSRHybridGetFinalRelativeResidualNorm(solver,&final_res_norm);
+	   if(rk==0){
+		        printf("\n");
+         		printf("Iterations = %d\n", num_iter);
+        		printf("PCG_Iterations = %d\n", pcg_num_its);
+		        printf("DSCG_Iterations = %d\n", dscg_num_its);
+		        printf("Final Relative Residual Norm = %e\n", final_res_norm);
+		        printf("\n");
+		      }
+	  break;
+	case 5:
+	   if(param->timing){
+	   time_index1 = hypre_InitializeTiming("BoomerAMG  SETUP");
+	   hypre_BeginTiming(time_index1);
+	 }
+	  HYPRE_BoomerAMGSetup(solver,par_A, par_B,par_X);
+	  if(param->timing){
+	  time_index1 = hypre_InitializeTiming("BoomerAMG SETUP Solve");
+	  hypre_BeginTiming(time_index1);}
+	  HYPRE_BoomerAMGSolve(solver,par_A,par_B,par_X);
+	  if(param->timing){
+	    hypre_EndTiming(time_index1);
+	    hypre_PrintTiming("Solve phase times", comm);
+	    hypre_FinalizeTiming(time_index1);
+	    hypre_ClearTiming();}
+	  break;
+
+	  
+	default :
+	  break;
+	}
+	
+	   
+	   /*Reconstruction of vector*/
+	  delete [] iwork1; delete []mapptr;
+	  iwork1=new int[size+1]; mapptr=new int[size+1];
+	  int disp=0;
+          for(i=0;i<size;i++){
+          iwork1[i]=n/size; if(i==size-1) iwork1[i]=(n/size)+n%size;
+	   mapptr[i]=disp; disp+=iwork1[i];
+	  }
+	  mapptr[i]=disp;
+
+	    HYPRE_IJVectorGetValues(ij_X, n_loc, row1, X_loc);
+	    MPI_Gatherv(X_loc,n_loc, MPI_DOUBLE, xx,iwork1,mapptr,MPI_DOUBLE,0,comm);
+	    MPI_Bcast(xx,n,MPI_DOUBLE,0, comm);
+	     
+	    for(i=0;i<n;i++) {x[i]=xx[i]; if(param->scale) x[i]=x[i]*scaletmpc[i];}
+
+	    if(verbosity==0) {
+	     MPI_Barrier(comm);
+             t2 = dwalltime();
+	     t2=t2-t1;
+	     MPI_Reduce(&t2, &t1, 1, MPI_DOUBLE, MPI_MAX, 0,comm);
+	     MPI_Bcast(&t1, 1, MPI_DOUBLE,0,comm);
+             
+	     if(rk==0){printf("%s%18.6g%s","TIME FOR SOLVING ", fabs(t1) ,"\n \n");
+		       printf("%s%18.6g%s","RELATIVE RESIDU  ", final_res_norm ,"\n \n");	
+			printf("%s%d%s","NUMBER OF ITERATION ", num_iter ," \n \n");
+		      }
+         }
+
+	   
+
+	    if(X_loc!=NULL) free(X_loc);  if(rhs!=NULL) free(rhs); if(xx!=NULL) free(xx);
+	    if(b_loc!=NULL) free(b_loc);  if(row!=NULL) free(row); 
+	    if(iwork1!=NULL) delete [] iwork1; 
+	    if(mapptr!=NULL) delete [] mapptr;
+            }
+	  ~HypreSolver() { 
+	    	if(verbosity){
+	        cout << "~HypreSolver():" << endl;
+  		HYPRE_IJMatrixDestroy(ij_A);
+		HYPRE_IJVectorDestroy(ij_B);
+		HYPRE_IJVectorDestroy(ij_X);
+		switch (param->solver_id){
+                case 0 : //BICGSTAB solver
+          	  	 HYPRE_ParCSRBiCGSTABDestroy(solver);
+			switch(param->precond_id){
+			case 0:  HYPRE_BoomerAMGDestroy(precond); break;
+			case 5:  HYPRE_ParaSailsDestroy(precond); break;
+			case 6:  HYPRE_SchwarzDestroy(precond); break;
+			case 4:  HYPRE_ParCSRPilutDestroy(precond); break;
+			default:   break;
+			
+			}
+			break;
+
+                case 1 : //GMRES Solver
+			 HYPRE_ParCSRFlexGMRESDestroy(solver);
+			switch(param->precond_id){
+			case 0:  HYPRE_BoomerAMGDestroy(precond); break;
+			case 5:  HYPRE_ParaSailsDestroy(precond); break;
+			case 6:  HYPRE_SchwarzDestroy(precond); break;
+			case 4:  HYPRE_ParCSRPilutDestroy(precond); break;
+			default:  break;
+			
+			}
+			break;
+                   
+                case 3 : //PCG
+			 
+			 HYPRE_ParCSRPCGDestroy(solver);
+			switch(param->precond_id){
+			case 0:  HYPRE_BoomerAMGDestroy(precond); break;
+			case 5:  HYPRE_ParaSailsDestroy(precond); break;
+			case 6:  HYPRE_SchwarzDestroy(precond); break;
+			default:  break;
+			}
+			
+                  break;
+		case 4: //AMG-Hybrid
+			 HYPRE_ParCSRHybridDestroy(solver);  break;
+		case 5: //AMG
+			 HYPRE_BoomerAMGDestroy(solver);  break;
+		  default :  break;
+		}
+			}
+	}
+ void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+  }
+};
+
+inline MatriceMorse<double>::VirtualSolver *
+BuildHypreSolver(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+      cout << " BuildSolverHypre>" << endl;
+	
+    return new HypreSolver(*A,ds.data_filename, ds.lparams, ds.dparams,(MPI_Comm *)ds.commworld);
+}
+
+
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; 
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+   
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+        return 1;
+
+ 
+
+}
+
+bool SetHypreSolver()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to Hyprempi" << endl;
+    DefSparseSolver<double>::solver  =BuildHypreSolver;
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+    return 1;
+
+
+}
+Init init;
+Init::Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  if(verbosity>1)
+    cout << "\n Add: Hyprempi,  defaultsolver defaultsolverHyprempi" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildHypreSolver;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttoHyprempi","(",new OneOperator0<bool>(SetHypreSolver));
+}
+
+  
+
+
+
diff --git a/src/solver/makefile b/src/solver/makefile
new file mode 100644
index 0000000..44298bd
--- /dev/null
+++ b/src/solver/makefile
@@ -0,0 +1,43 @@
+include makefile-sparsesolver.inc
+
+#Creation of Hips dynamic librairy
+hips    : 
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_HIPS) $(FREEFEM_INCLUDE) $(HIPS_INCLUDE) $(METIS_INCLUDE) $(HIPS_OTHER_INCLUDE) hips_FreeFem.cpp 
+	$(MPIFC)$  $(FFLAGS) hips_FreeFem.o -o hips_FreeFem.$(SUF) $(HIPS_ALL_LIBS) $(BLAS_LIB) $(METIS_LIB) $(HIPS_OTHER_LIB)
+
+parms	:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_PARMS) $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(PARMS_INCLUDE) $(METIS_INCLUDE) $(PARMS_OTHER_INCLUDE) parms_FreeFem.cpp 
+	$(MPIFC)$  $(FFLAGS) parms_FreeFem.o -o parms_FreeFem.$(SUF) $(PARMS_LIB) $(BLAS_LIB) $(METIS_LIB) $(PARMS_OTHER_LIB)
+
+hypre	:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_HYPRE) $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(HYPRE_INCLUDE) $(METIS_INCLUDE) $(HYPRE_OTHER_INCLUDE) hypre_FreeFem.cpp 
+	$(MPIFC)$  $(FFLAGS) hypre_FreeFem.o -o hypre_FreeFem.$(SUF) $(HYPRE_LIB) $(BLAS_LIB) $(METIS_LIB) $(HYPRE_OTHER_LIB)
+
+mumps	:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_MUMPS) $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(MUMPS_OTHER_INCLUDE) $(MUMPS_INCLUDE) $(SCOTCH_INCLUDE)  MUMPS_FreeFem.cpp
+	$(MPIFC)  $(FFLAGS) $(MPI_INCLUDE) $(MUMPS_OTHER_INCLUDE) $(MUMPS_INCLUDE) MUMPS_FreeFem.o -o MUMPS_FreeFem.$(SUF) $(MPI_LIB) $(BLAS_LIB) $(BLACS_LIB) $(SCALAPACK_LIB) $(METIS_LIB) $(PORD_LIB) $(SCOTCH_LIB) $(MUMPS_LIB) $(MUMPS_OTHER_LIB)
+#
+rpastix_dist:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_PASTIX)  $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(PTSCOTCH_INCLUDE) $(REAL_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) real_dpastix_FreeFem.cpp
+	$(MPIFC) $(FFLAGS) $(PTSCOTCH_INCLUDE) $(REAL_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) real_dpastix_FreeFem.o -o real_dpastix_FreeFem.$(SUF) $(MPI_LIB) $(BLAS_LIB) $(PTSCOTCH_LIB) $(METIS_LIB) $(REAL_PASTIX_LIB) $(PASTIX_OTHER_LIB)
+
+rpastix:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_PASTIX) $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(SCOTCH_INCLUDE) $(REAL_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) real_pastix_FreeFem.cpp
+	$(MPIFC) $(FFLAGS) $(SCOTCH_INCLUDE) $(REAL_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) real_pastix_FreeFem.o -o real_pastix_FreeFem.$(SUF) $(MPI_LIB) $(BLAS_LIB) $(SCOTCH_LIB) $(METIS_LIB) $(REAL_PASTIX_LIB) $(PASTIX_OTHER_LIB)
+
+cpastix_dist:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_PASTIX) -Wno-deprecated $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(SCOTCH_INCLUDE) $(COMPLEX_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) complex_dpastix_FreeFem.cpp
+	$(MPIFC) $(FFLAGS) $(PTSCOTCH_INCLUDE) $(COMPLEX_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) complex_dpastix_FreeFem.o -o complex_dpastix_FreeFem.$(SUF) $(MPI_LIB) $(BLAS_LIB) $(PTSCOTCH_LIB) $(METIS_LIB) $(COMPLEX_PASTIX_LIB) $(PASTIX_OTHER_LIB)
+
+cpastix:
+	$(MPICXX) -c $(CFLAGS) $(CFLAGS_PASTIX) -Wno-deprecated $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(SCOTCH_INCLUDE) $(COMPLEX_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) complex_pastix_FreeFem.cpp
+	$(MPIFC) $(FFLAGS) $(SCOTCH_INCLUDE) $(COMPLEX_PASTIX_INCLUDE) $(PASTIX_OTHER_INCLUDE) complex_pastix_FreeFem.o -o complex_pastix_FreeFem.$(SUF) $(MPI_LIB) $(BLAS_LIB) $(SCOTCH_LIB) $(METIS_LIB) $(COMPLEX_PASTIX_LIB) $(PASTIX_OTHER_LIB)
+
+rsludist:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_SLUDIST) $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(SLUDIST_INCLUDE) $(SLUDIST_OTHER_INCLUDE) real_SuperLU_DIST_FreeFem.cpp
+	$(MPIFC) $(FFLAGS)  $(SLUDIST_INCLUDE) $(SLUDIST_OTHER_INCLUDE) real_SuperLU_DIST_FreeFem.o -o real_SuperLU_DIST_FreeFem.$(SUF) $(MPI_LIB) $(BLAS_LIB) $(PARMETIS_LIB) $(METIS_LIB) $(SLUDIST_LIB) $(SLUDIST_OTHER_LIB)
+
+csludist:
+	$(MPICC) -c $(CFLAGS) $(CFLAGS_SLUDIST) $(MPI_INCLUDE) $(FREEFEM_INCLUDE) $(SLUDIST_INCLUDE) $(SLUDIST_OTHER_INCLUDE) complex_SuperLU_DIST_FreeFem.cpp
+	$(MPIFC) $(FFLAGS)  $(SLUDIST_INCLUDE) $(SLUDIST_OTHER_INCLUDE) complex_SuperLU_DIST_FreeFem.o -o complex_SuperLU_DIST_FreeFem.$(SUF) $(MPI_LIB) $(BLAS_LIB) $(PARMETIS_LIB) $(METIS_LIB) $(SLUDIST_LIB) $(SLUDIST_OTHER_LIB)
+
diff --git a/src/solver/makefile-common.inc b/src/solver/makefile-common.inc
new file mode 100644
index 0000000..9158628
--- /dev/null
+++ b/src/solver/makefile-common.inc
@@ -0,0 +1,64 @@
+##########################################################
+#
+# common variable for the different parallel sparse solver
+#
+#########################################################
+
+# frefem++ variables
+
+FREEFEM_DIR     = /Volumes/Ike/cazeaux/ff++/
+
+FREEFEM_INCLUDE = -I$(FREEFEM_DIR)examples++-load/include/ 
+
+# directory of the different package
+
+SOFT_DIR =  $(FREEFEM_DIR)download/
+
+
+#==========
+#   BLAS
+#==========
+BLAS_INCLUDE = 
+BLAS_LIB     = -L$(SOFT_DIR)BLAS/blas_LINUX.a 
+
+#============
+#  BLACS : this library is need by MUMPS 
+#============
+BLACS_DIR     =  $(SOFT_DIR)/BLACS/
+BLACS_INCLUDE = 
+BLACS_LIB     =  -L$(BLACS_DIR)LIB/ -lblacsCinit_MPI-BROCHET-0 -lblacs_MPI-BROCHET-0 -lblacsF77init_MPI-BROCHET-0
+
+#=============
+#  SCALAPACK : this library is need by MUMPS
+#=============
+SCALAPACK_DIR     = $(SOFT_DIR)/scalapack-1.8.0/
+SCALAPACK_INCLUDE = -I$(SCALAPACK_DIR)SRC/ 
+SCALAPACK_LIB     = -L$(SCALAPACK_DIR) -lscalapack
+
+#==============================================
+#   ordering : metis, parmetis, scotch 
+#===============================================
+#  pord : this ordering is given in the mumps package 
+#         and it is only need by MUMPS
+#PORD_DIR     =  $(SOFT_DIR)MUMPS_4.8.3/PORD/
+#PORD_INCLUDE = -I$(PORD_DIR)include
+#PORD_LIB     = -L$(PORD_DIR)lib/ -lpord
+
+# scotch
+SCOTCH_DIR = $(SOFT_DIR)/scotch_5.1_esmumps/
+SCOTCH_INCLUDE = -I$(SCOTCH_DIR)include/
+SCOTCH_LIB     = -L$(SCOTCH_DIR)lib/  -lesmumps  -lscotch -lscotcherr -lscotcherrexit -lm
+
+# ptscotch 
+PTSCOTCH_INCLUDE = -I$(SCOTCH_DIR)include/
+PTSCOTCH_LIB     = -L$(SCOTCH_DIR)lib/ -lptscotch -lptscotcherrexit -lm
+
+# metis
+METIS_DIR      = $(SOFT_DIR)metis-4.0/
+METIS_INCLUDE  = -I$(METIS_DIR)Lib/
+METIS_LIB      = -L$(METIS_DIR) -lmetis
+
+# parmetis
+PARMETIS_DIR      = $(SOFT_DIR)ParMetis-3.1.1/
+PARMETIS_INCLUDE  = -I$(PARMETIS_DIR)
+PARMETIS_LIB      = -L$(PARMETIS_DIR) -lparmetis -lmetis
diff --git a/src/solver/makefile-sparsesolver.inc b/src/solver/makefile-sparsesolver.inc
new file mode 100644
index 0000000..8c2e9bd
--- /dev/null
+++ b/src/solver/makefile-sparsesolver.inc
@@ -0,0 +1,317 @@
+#// ORIG-DATE: 02/2009
+#// -*- Mode : c++ -*-
+#//
+#// SUMMARY  :  
+#// USAGE    : LGPL      
+#// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+#// AUTHOR   : Jacques Morice
+#// E-MAIL   : jacques.morice at ann.jussieu.fr
+#//
+#/* 
+# This file is part of Freefem++
+# 
+# Freefem++ is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+# 
+# Freefem++  is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public License
+# along with Freefem++; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+# Thank to the ARN ()  FF2A3 grant
+# ref:ANR-07-CIS7-002-01 
+# */
+#####################################################
+#    SECTION 1: 
+#    General variables to compile sparse solver  
+#####################################################
+# Note ::   A remplir automatique avec automake
+#           Regarder notation de FreeFem++
+###################
+#    Compiler 
+###################
+# C compiler
+CC    = gcc 
+MPICC = /usr/local/bin/mpicc
+
+# C++ compiler
+CXX    = g++
+MPICXX = /usr/local/bin/mpicxx 
+
+# Fortran compiler
+FC     = fort77
+MPIFC  = /usr/local/bin/mpif77 #mpifort77 #/Users/morice/librairie/openmpi/bin/mpif90 --prefix /Users/morice/librairie/openmpi/
+FC_LIB = -L/usr/local/lib -lmpi_f77
+
+# Linker
+MPILD = 
+
+# directory of include file for mpi
+MPI_INCLUDE = /I/usr/local/include #-I/Users/morice/librairie/openmpi/include/
+MPI_LIB     = -L/usr/local/lib -lmpi -lmpi_cxx -lmpi_f77 -lmpi_f90 -lopen-rte -lopen-pal
+
+###############
+#   FLAGS
+###############
+# 
+LDFLAGS_FREEFEM = -bundle -undefined dynamic_lookup -DNDEBUG -g -DDRAWING -DBAMG_LONG_LONG -DCHECK_KN -fno-inline -fexceptions -I/usr/X11/include/
+CFLAGS_FREEFEM  =  -DNDEBUG -g -DDRAWING -DBAMG_LONG_LONG -DCHECK_KN -fno-inline -fexceptions -I/usr/X11/include/
+#
+CFLAGS	   =  $(CFLAGS_FREEFEM) # Additional C compiler flags
+FFLAGS	   =  $(LDFLAGS_FREEFEM) # Additional Fortran compiler flags
+LDFLAGS    =  $(LDFLAGS_FREEFEM) # linker flags
+COPTFLAGS  =    -O3       # Optimization flags
+FOPTFLAGS  =    -O3       # 
+LDOPTFLAGS =    -O3       #
+
+# SUFFIX OF DYNAMIC LIBRARY
+# linux   SUF = so
+# windows SUF = dll
+# mac osx SUF = dylib
+SUF      =  dylib
+
+
+##########################################################
+# SECTION 2: 
+# common variable for the different parallel sparse solver
+#
+#########################################################
+
+# frefem++ variables
+FREEFEM_DIR     = /Volumes/Ike/cazeaux/ff++/
+FREEFEM_INCLUDE = -I$(FREEFEM_DIR)examples++-load/include/ 
+
+FREEFEM_INCLUDE = -I$(FREEFEM_DIR)examples++-load/include/ 
+
+# directory of the different package
+#SOFT_DIR =  /Users/morice/librairie/
+SOFT_DIR =  $(FREEFEM_DIR)/download/
+
+#==========
+#   BLAS
+#==========
+BLAS_INCLUDE = 
+BLAS_LIB     = -L$(FREEFEM_DIR)ff++/src/solver/PATCHVECLIB/libwrapperdostblas.a  -framework veclib
+
+#============
+#  BLACS : this library is need by MUMPS 
+#============
+BLACS_DIR     =  $(SOFT_DIR)
+BLACS_INCLUDE = 
+BLACS_LIB     =  -L$(BLACS_DIR)lib/ -lblacsCinit_MPI-FREEFEM-0 -lblacs_MPI-FREEFEM-0 -lblacsF77init_MPI-FREEFEM-0
+
+#=============
+#  SCALAPACK : this library is need by MUMPS
+#=============
+SCALAPACK_DIR     = $(SOFT_DIR)
+SCALAPACK_INCLUDE = -I$(SCALAPACK_DIR)include/ 
+SCALAPACK_LIB     = -L$(SCALAPACK_DIR)lib/ -lscalapack
+
+#==============================================
+#   ordering : metis, parmetis, scotch 
+#===============================================
+
+# scotch
+SCOTCH_DIR = $(SOFT_DIR)
+SCOTCH_INCLUDE = -I$(SCOTCH_DIR)include/
+SCOTCH_LIB     = -L$(SCOTCH_DIR)lib/  -lesmumps  -lscotch -lscotcherr -lscotcherrexit -lm
+
+# ptscotch 
+PTSCOTCH_INCLUDE = -I$(SCOTCH_DIR)include/
+PTSCOTCH_LIB     = -L$(SCOTCH_DIR)lib/ -lptscotch -lptscotcherrexit -lm
+
+# metis
+METIS_DIR      = $(SOFT_DIR)
+METIS_INCLUDE  = -I$(METIS_DIR)include/metis/
+METIS_LIB      = -L$(METIS_DIR)lib -lmetis
+
+# parmetis
+PARMETIS_DIR      = $(SOFT_DIR)
+PARMETIS_INCLUDE  = -I$(PARMETIS_DIR)include/
+PARMETIS_LIB      = -L$(PARMETIS_DIR)lib/ -lparmetis -lmetis
+
+###########################################
+#  SECTION 3: 
+#      ITERATIVE/PRECONDITIONNER SPARSE SOLVER
+#  
+###########################################
+#      HIPS
+###########################################
+#  To compile HIPS, we need the following librairies
+#     -- ordering Metis or Scotch
+#        comment lines corresponding to Metis or Scotch in SECTION 2
+#     -- BLAS
+#        comment lines corresponding to BLAS in SECTION 2
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#  Variables needs by HIPS
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#     directory of HIPS
+HIPS_DIR           = $(SOFT_DIR)
+#    include file of HIPS
+HIPS_INCLUDE       = -I$(HIPS_DIR)include/hips/
+#   library of package hips
+HIPS_ALL_LIBS      = -L$(HIPS_DIR)lib/hips -lio -lhipssequential -lhips #-lspkit 
+
+IO_LIB             = $(HIPS_DIR)lib/hips/libio.a
+HIPSSEQUENTIAL_LIB = $(HIPS_DIR)lib/hips/libhipssequential.a
+HIPS_LIB           = $(HIPS_DIR)lib/hips/libhips.a
+#SPKIT_LIB	   = $(HIPS_DIR)LIB/libspkit.a
+
+
+# other compiler option for HIPS (see value of CFLAGS in SECTION 1)
+CFLAGS_HIPS =
+#  other include file and library file for interfacing
+HIPS_OTHER_INCLUDE =
+HIPS_OTHER_LIB     = 
+
+###########################################
+#      HYPRE
+###########################################
+#  To compile HYPRE, we need the following librairies
+#     -- ordering Metis 
+#        comment lines corresponding to Metis in SECTION 2
+#     -- BLAS
+#        comment lines corresponding to BLAS in SECTION 2
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#    Variables needs by HYPRE
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# directory of HYPRE
+HYPRE_DIR     = $(SOFT_DIR)
+# include file of HYPRE
+HYPRE_INCLUDE = -I$(HYPRE_DIR)include/hypre
+# library of HYPRE
+HYPRE_LIB     = -L$(HYPRE_DIR)lib/hypre/ -lHYPRE
+
+# other compiler option for HYPRE (see value of CFLAGS in SECTION 1)
+CFLAGS_HYPRE        = -Wall -DHAVE_CONFIG_H -DHYPRE_TIMING -Wno-deprecated -DLINUX -DSPKIT_F  -DMPICH_SKIP_MPICXX
+#  other directory of header file and library file for interfacing
+HYPRE_OTHER_INCLUDE = 
+HYPRE_OTHER_LIB     = -lm -lstdc++
+
+###########################################
+#      pARMS
+###########################################
+#  To compile pARMS, we need the following librairies
+#     -- ordering Metis 
+#        comment lines corresponding to Metis in SECTION 2
+#     -- BLAS
+#        comment lines corresponding to BLAS in SECTION 2
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#   variable needs by pARMS
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# directory of pARMS
+PARMS_DIR    = $(SOFT_DIR)
+# include file of pARMS
+PARMS_INCLUDE =  -I$(PARMS_DIR)include/parms
+# library of HYPRE
+PARMS_LIB     =  -L$(PARMS_DIR)lib/ -lparms-O3
+
+# other compiler option for HIPS (see value of CFLAGS in )
+# PARMS NEED THE ARCHITECTURE (see generaldefs.h). For Mac Osx defined the architecture as -DLINUX
+CFLAGS_PARMS   = -DLINUX -DSPKIT_F 
+# other include file and library file for interfacing
+PARMS_OTHER_INCLUDE = 
+PARMS_OTHER_LIB     = 
+
+
+###########################################
+#  SECTION 4: 
+#      DIRECT SPARSE SOLVER
+#  
+###########################################
+#      MUMPS
+###########################################
+#  To compile MUMPS, we need the following librairies
+#     -- ordering metis, scotch 
+#        comment lines corresponding to Metis and Scotch in SECTION 2
+#     -- BLAS, BLACS, SCALAPACK
+#        comment lines corresponding to BLAS, BLACS and SCALAPACK in SECTION 2
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#    Variables needs by MUMPS
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+MUMPS_HOST  = BROCHET
+#  directory of MUMPS
+MUMPS_DIR     =  $(SOFT_DIR)mumps/MUMPS_4.9.2/
+# directory of Header File for MUMPS
+MUMPS_INCLUDE = -I$(MUMPS_DIR)include/
+# library of MUMPS
+MUMPS_LIB     = -L$(MUMPS_DIR)lib/ -lmumps_common_$(MUMPS_HOST) -ldmumps_$(MUMPS_HOST) -lzmumps_$(MUMPS_HOST) 
+
+#   pord : ordering include in MUMPS package 
+PORD_DIR     =  $(MUMPS_DIR)PORD/
+PORD_INCLUDE = -I$(PORD_DIR)include
+PORD_LIB     = -L$(MUMPS_DIR)lib/ -lpord_$(MUMPS_HOST) 
+
+# other compiler option for MUMPS (see value of CFLAGS in SECTION 1)
+CFLAGS_MUMPS  =
+#  other include file and library file for interfacing
+MUMPS_OTHER_INCLUDE = -I/usr/X11/include
+MUMPS_OTHER_LIB     = -L/usr/lib/gcc/i686-apple-darwin9/4.2.1/ -lgfortran
+
+###########################################
+#      SuperLU_DIST
+###########################################
+#  To compile SuperLU_DIST, we need the following librairies
+#     -- ordering Metis and ParMetis 
+#        comment lines corresponding to Metis and ParMetis in SECTION 2
+#     -- BLAS
+#        comment lines corresponding to BLAS in SECTION 2
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#    Variables needs by SuperLU_DIST
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# directory of superlu_dist
+SLUDIST_DIR = $(SOFT_DIR)
+
+# include file of superlu_dist
+SLUDIST_INCLUDE = -I$(SLUDIST_DIR)include 
+# librairie of superlu_dist
+SLUDIST_LIB = -L$(SLUDIST_DIR)lib/ -lsuperlu_dist_2.3
+
+# other compiler option for SuperLU (see value of CFLAGS in SECTION 1)
+SLUDIST_CFLAGS        = 
+#  other include file and library file for interfacing
+SLUDIST_OTHER_INCLUDE = 
+SLUDIST_OTHER_LIB     = 
+
+###########################################
+#      Pastix
+###########################################
+#  To compile pastix, we need the following librairies
+#     -- ordering scotch, ptscotch, metis 
+#        comment lines corresponding to metis, scotch and ptsccoth in SECTION 2
+#     -- BLAS 
+#        comment lines corresponding to BLAS in SECTION 2
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#    Variables needs by pastix
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+#  To obtain real and complex  arithmetics, we need to install for real and for complex separately. 
+#   Hence we need to have two differents pastix directory
+#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
+#  real pastix
+#  directory of pastix
+REAL_PASTIX_DIR     = $(SOFT_DIR)/
+# include directory of pastix
+REAL_PASTIX_INCLUDE = -I$(REAL_PASTIX_DIR)include/pastix/double/ 
+# library
+REAL_PASTIX_LIB     = -L$(REAL_PASTIX_DIR)lib/pastix/double -lpastix #-lmatrix_driver 
+
+# complex pastix
+#  directory of pstix
+COMPLEX_PASTIX_DIR     = $(SOFT_DIR)
+# include directory of pastix
+COMPLEX_PASTIX_INCLUDE = -I$(COMPLEX_PASTIX_DIR)include/pastix/complex/
+# library
+COMPLEX_PASTIX_LIB     = -L$(COMPLEX_PASTIX_DIR)lib/pastix/complex/ -lpastix #-lmatrix_driver 
+
+
+# other compiler option for PASTIX (see value of CFLAGS in SECTION 1)
+CFLAGS_FLAGS        =   -DFORCE_LONG -DNUMA_ALLOC -DX_ARCHi686_mac -DDOF_CONSTANT  -DCOMMON_DEBUG -DSYMBOL_DEBUG -DDOF_DEBUG -DSOLVER_DEBUG -DORDER_DEBUG -DFAX_DEBUG -DSCOTCH_DEBUG -DDEBUG_BLEND -DBUBBLE_DEBUG -DPASTIX_DEBUG -Wno-depreciated
+# other directory of header file and library file for interfacing
+PASTIX_OTHER_INCLUDE = 
+PASTIX_OTHER_LIB     = -lm -lsupc++ -lpthread
\ No newline at end of file
diff --git a/src/solver/parms_FreeFem.cpp b/src/solver/parms_FreeFem.cpp
new file mode 100755
index 0000000..32119a5
--- /dev/null
+++ b/src/solver/parms_FreeFem.cpp
@@ -0,0 +1,1043 @@
+// ORIG-DATE: 04/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : INRIA FUTUR
+// AUTHOR   : Guy Atenekeng
+// E-MAIL   : Guy_Antoine_Atenekeng_Kahou at lri.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+
+#include  <iostream>
+using namespace std;
+
+
+#define MCW MPI_COMM_WORLD
+
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "mpi.h"
+
+/* Explain here what foobar does */
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "psparslib.h"
+#include "generaldefs.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+extern "C" {
+  #include "metis.h"
+}
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define BUFLEN 100
+#define NORHS 0
+
+#define BUFLEN 100
+
+//This functions come from pARMS package and consist to scale matrix 
+
+
+
+
+
+
+
+class parm_param {
+public:
+	mutable PrePar prepar;
+	mutable IterPar ipar;
+	mutable int sol_type;
+	mutable int  iov,scale, unsymm,method;
+	mutable int solver;
+	mutable int VERBOSE;
+	
+
+	public: parm_param(){
+		PARMS_malloc(prepar,1,_PrePar);
+		PARMS_malloc(ipar,1,_IterPar);  
+		/*----------------------------------------------------------------------  *
+		 * This function  sets some default  parameters just to get  started with *
+		 * pARMS.  There are  two arrays  which define  the parameters  in pARMS. *
+		 * Because ther\ e are so many methods, the number of parameters may seem *
+		 * overwhelming.. However\ , not all  are used. For example when add_ilut *
+		 * is  used  only  two parameters  are  r\  equired  which are  the  drop *
+		 * tolerance and the  max fill per row.. This  function s\ ets everything *
+		 * so that all the methods can be safely tested. YS -                     *
+		 *                                                                        *
+		 *------------------------------------------------------------------------*/
+		  int i; 
+		/*------------------------------------------------------------------------*/
+		  for (i=1; i<18; i++)
+		    ipar->ipar[i] = 0;
+		/* parameters to be set for the solver -- not all of these are used --  
+		     depending on the method selected -                                   */
+		/* parameters associated with various accelerators (inner/outer)          */
+		  ipar->ipar[0] = 3;       /* nlev in arms when used                      */
+		  ipar->ipar[1] = 20;      /* block size in arms when used                */
+		  ipar->ipar[5] = 30;      /* Outer iteration Krylov subs. dimension      */
+		  ipar->ipar[6] = 200;     /* Max. outer iterations                       */
+		  ipar->ipar[3] = 3;       /* Inner iteration Krylov subs. dimension      */
+		  ipar->ipar[4] = 3;       /* Max. inner iterations  */
+		  
+		  ipar->pgfpar[0] = 0.01;  /* tolerance for inner iteration when used     */
+		  ipar->pgfpar[1] = 1.e-10;/* tolerance for outer iteration               */
+		/* preconditioning parameters                                             */
+		  prepar->tolind = 0.1;    /* tolerance used for diag dom. filtration alg.*/
+		  prepar->lfil[0] = 20;    /* lfil0 (ilut, iluk, and arms)                */
+		  prepar->lfil[4] = 20;    /* lfil for Schur complement const.            */ 
+		  prepar->lfil[5] = 20;    /* lfil for Schur complement const.            */ 
+		  prepar->droptol[0]=.001; /* droptol0 (ilut, iluk, and arms)             */
+		  prepar->droptol[4]=.001; /* droptol for Schur complement const.         */ 
+		  prepar->droptol[5]=.001; /* droptol for Schur complement const.         */ 
+		  prepar->mc = 1;          /* multicoloring or not in ILU when used       */
+		 //Integer parameter
+		 iov=0; scale=1; unsymm=1; method= 2; VERBOSE=0; /*no statistic infos has print*/
+		 /*VERBOSE=1 Only informations on convergence will be print*/
+		 /*VERBOSE=2 Only informations on time will be print*/
+		  solver=0;
+		 
+		  memcpy(prepar->ipar, ipar->ipar, sizeof(int)*18);
+
+		  for (i=1; i<4; i++) {
+		    prepar->droptol[i] = prepar->droptol[0]; 
+		    prepar->lfil[i] = prepar->lfil[0];
+		  }
+		  prepar->lfil[6] = prepar->lfil[5];
+		  ipar->in_iters = 0;
+		 
+		/*-------------------- done  */                       
+	}
+	public: parm_param(const KN<long> &param_int, const KN<double> &param_double)
+	{
+		 int i; 
+		PARMS_malloc(prepar,1,_PrePar);
+		PARMS_malloc(ipar,1,_IterPar);  
+		for (i=1; i<18; i++)
+		 ipar->ipar[i] = 0;
+		
+		if(param_int.N()>0){if((param_int[0]<0)||(param_int[0]>2)) 
+		{printf("%s","WRONG SOLVER INDEX WE SET DEFAULT ONE \n"); solver=0; } else solver=param_int[0];}else solver=0;
+
+		if(param_int.N()>1){if((param_int[1]<0)||(param_int[1]>13)) 
+		{printf("%s","WRONG INDEX FOR PRECONDITIONER, WE SET DEFAULT ONE \n"); method=2; } 
+		else if((param_int[1]>=0)||(param_int[1]<=13)) method=param_int[1];}else method=2;
+		
+		if(param_int.N()>2){if(param_int[2]>0) ipar->ipar[5]=param_int[2]; else ipar->ipar[5]=30;}
+		else ipar->ipar[5]=30; /* Outer iteration Krylov subs. dimension      */
+
+
+		if(param_int.N()>3){if(param_int[3]>0) ipar->ipar[6]=param_int[3]; else ipar->ipar[6]=1000;}
+		else ipar->ipar[6]=1000; /* Max. outer iterations    */
+
+
+		if((method==3)||(method==7)||(method==11)) {if(param_int.N()>4) {if(param_int[4]>0) ipar->ipar[0]=param_int[4]; 
+		else ipar->ipar[0]=3;}	else ipar->ipar[0]=3;  } /* nlev in arms when used                      */
+
+		if(param_int.N()>5){ if(param_int[5]>0) ipar->ipar[3]=param_int[5]; else ipar->ipar[3]=3;}
+		else ipar->ipar[3]=3; /* Inner iteration Krylov subs. dimension */
+
+		if(param_int.N()>6){if(param_int[6]>0) ipar->ipar[4]=param_int[6]; else ipar->ipar[4]=3;}
+		else ipar->ipar[4]=3;  /* Max. inner iterations  */
+
+		if(param_int.N()>7){if(param_int[7]>=0) unsymm=param_int[7]; else unsymm=0;} else unsymm=0;
+
+		if(param_int.N()>8) {if(param_int[8]>=0) iov=param_int[8]; else iov=0;} else iov=0;
+		if(param_int.N()>9) {if(param_int[9]>0) scale=param_int[9]; else scale=1;}else scale=1;
+
+		if(param_int.N()>10){if(param_int[10]>0) ipar->ipar[1]=param_int[10]; else ipar->ipar[1]=20; }else ipar->ipar[1]=20;
+		 
+			
+
+		if(param_int.N()>11){if(param_int[11]>0) prepar->lfil[0]=param_int[11]; else prepar->lfil[0]=20;}
+		else prepar->lfil[0]=20; /* lfil0(ilut, iluk, and arms)   */
+
+		if(param_int.N()>12){if(param_int[12]>0) prepar->lfil[4]=param_int[12]; else prepar->lfil[4]=20;}
+		else prepar->lfil[4]=20; /* lfil for Schur complement const.   */
+
+		if(param_int.N()>13){if(param_int[13]>0) prepar->lfil[5]=param_int[13]; else prepar->lfil[13]=20;}
+		else prepar->lfil[5]=20; /* lfil for Schur complement const.   */		
+
+		if(param_int.N()>14){if(param_int[14]>0) prepar->mc=param_int[14]; else prepar->mc=1; }
+		else prepar->mc=1; 
+
+		if(param_int.N()>15){if(param_int[15]>0) ipar->in_iters=param_int[15]; else ipar->in_iters=0; }
+		else ipar->in_iters=0;
+		
+		if(param_int.N()>16){if(param_int[16]>0) VERBOSE=param_int[16]; else VERBOSE=0; }else VERBOSE=0;
+
+
+			
+
+
+		if(param_double.N()>0){if(param_double[0]>0) ipar->pgfpar[1]=param_double[0]; else ipar->pgfpar[1]=1.e-08;}
+		ipar->pgfpar[1]=1.e-08; /* tolerance for outer iteration               */
+
+		if(param_double.N()>1){if(param_double[1]>0) ipar->pgfpar[0]=param_double[1]; else ipar->pgfpar[0]=0.01;}
+		else ipar->pgfpar[0]=0.01;  /* tolerance for inner iteration when used     */
+
+		if(param_double.N()>2) {if(param_double[2]>0) prepar->tolind = param_double[2]; else prepar->tolind=0.1;}
+		else prepar->tolind=0.1; /* tolerance used for diag dom. filtration alg.*/
+
+		if(param_double.N()>3){if(param_double[3]>0) prepar->droptol[0]=param_double[3]; else prepar->droptol[0]=.001;}
+		else prepar->droptol[0]=.001;	/* droptol0 (ilut, iluk, and arms) */
+		if(param_double.N()>4) {if(param_double[4]>0) prepar->droptol[4]=param_double[4]; else prepar->droptol[4]=.001;}
+		else prepar->droptol[4]=.001; /* droptol for Schur complement const.         */ 
+
+		if(param_double.N()>5){if(param_double[5]>0) prepar->droptol[5]=param_double[5]; else prepar->droptol[5]=.001;}
+		else prepar->droptol[5]=.001; /* droptol for Schur complement const.         */ 
+
+		
+
+		memcpy(prepar->ipar, ipar->ipar, sizeof(int)*18);
+		  for (i=1; i<4; i++) {
+		    prepar->droptol[i] = prepar->droptol[0]; 
+		    prepar->lfil[i] = prepar->lfil[0];
+		  }
+		  prepar->lfil[6] = prepar->lfil[5];
+		 
+		 
+	}
+
+  public: parm_param(string datafile,DistMatrix dm)
+	{
+	  FILE *fp;
+	  char buf[BUFLEN], meth_buf[BUFLEN];
+	  int num;
+	  PARMS_malloc(prepar,1,_PrePar);
+  	  PARMS_malloc(ipar,1,_IterPar);  
+
+          parm_param();
+
+	  char * filename=new char[datafile.length()+1]; 
+                strcpy(filename,datafile.c_str()); 
+ 	 /* read parameters for preconditioner and iteration from file  'filename' */
+  /*  ---- start modification by MS
+   */
+ 	 if( (fp = fopen(filename, "r")) == NULL ){
+          fprintf(stderr, "Cannot open file inputs\n");
+    	  PARMS_Final();exit(1);
+    	}
+	  for (num=0; num< 18; num++)
+	    ipar->ipar[num] = 0; 
+
+  	num = 1;
+
+  while(fgets(buf, BUFLEN, fp) != NULL) {
+    switch(num) {
+     case 1:                             /* solver */
+      sscanf(buf, "%d", &solver);
+	if((solver!=0)&&(solver!=1)&&(solver!=2))
+	{printf("%s","WRONG SOLVER INDEX, WE SET DEFAULT ONE \n"); solver=0;}
+      break;
+    case 2:                             /* preconditionner */
+      sscanf(buf,"%s",meth_buf); 
+      method = assignprecon(meth_buf, dm);
+	if((method<0)||(method>13)) 
+	{printf("%s","WRONG INDEX FOR PRECONDITIONER, WE SET DEFAULT ONE \n"); method=2; }		
+      break;
+    case 3:                             /* im (Outer Krylov subs dim) */
+      sscanf(buf,"%d",&ipar->ipar[5]);
+      break;	
+    case 4:                             /* im (Outer Krylov subs dim) */
+      sscanf(buf,"%d",&ipar->ipar[6]);
+      break;	
+    case 5:                             /* outer tol */
+      sscanf(buf,"%lf",&ipar->pgfpar[1]);
+      break;	
+    case 6:                             /* inner tol */
+      sscanf(buf,"%lf",&ipar->pgfpar[0]);
+      break;
+    case 7:                             /* unsym */
+      sscanf(buf, "%d", &unsymm);
+      break;
+    case 8:                             /* inim (inned Krylov subs dim) */
+      sscanf(buf, "%d", &ipar->ipar[3]);
+      break;
+    case 9:                             /* Max. inner iterations     */ 
+      sscanf(buf,"%d",&ipar->ipar[4]);
+      break;
+    case 10:                             /* nlev   */
+      sscanf(buf, "%d", &iov);
+      break;
+    case 11:                             /*  scale  */ 
+      sscanf(buf,"%d",&scale);
+      break;
+    case 12:                             /* For printing result */ 
+      sscanf(buf, "%d", &VERBOSE);
+      break;
+    case 13:                             /* lfil0 (ilut, iluk, and arms) */
+      sscanf(buf, "%d", &prepar->lfil[0]);
+      break;
+    case 14:                             /* lfil 4 (schur construction) */
+      sscanf(buf, "%d", &prepar->lfil[4]);
+      break;
+    case 15:                             /* lfil 5 (ILUT for Schur) */
+      sscanf(buf, "%d", &prepar->lfil[5]);
+      break;
+    case 16:                             /* bsize   */
+      sscanf(buf,"%d",&ipar->ipar[1]);
+      break;
+    case 17:                              /* tolerance used for diag dom. filtration alg.*/  
+      sscanf(buf,"%lf",&prepar->tolind);
+      break;
+    case 18:                             /*droptol (0) -- simliar to lfil0*/
+      sscanf(buf, "%lf", &prepar->droptol[0]);
+      break;
+    case 19:                             /*droptol (4) -- simliar to lfil4*/
+      sscanf(buf, "%lf", &prepar->droptol[4]);
+      break;
+    case 20:                             /*droptol (5) -- simliar to lfil5*/
+      sscanf(buf, "%lf", &prepar->droptol[5]);
+      break;
+    case 21:                             /* multicoloring or not */ 
+      sscanf(buf, "%d", &prepar->mc);
+      break;
+    
+    default:
+      break;
+    }
+    num++;
+  }
+  fclose(fp);
+  
+  memcpy(prepar->ipar, ipar->ipar, sizeof(int)*18);
+  
+  prepar->droptol[1] = prepar->droptol[2] = prepar->droptol[3] =
+    prepar->droptol[0]; 
+  prepar->droptol[6] = prepar->droptol[5];
+  
+  prepar->lfil[1] = prepar->lfil[2] = prepar->lfil[3] =
+    prepar->lfil[0];
+  prepar->lfil[6] = prepar->lfil[5];
+  ipar->in_iters = 0; free(filename);
+
+	}
+	~parm_param(){
+		free(prepar); free(ipar); 
+	
+	}
+};
+
+
+int assignprecon( char *precon_str, DistMatrix dm) 
+{
+/*------------------------------------------------------------------ 
+     create preconditioner handler  
+   * precon    --  preconditioning handler
+   * add_ilu0  --  additive schwarz preconditioner with ilu0 as local
+                   preconditioner
+   * add_ilut  --  additive schwarz preconditioner with ilut as local
+                   preconditioner
+   * add_iluk  --  additive schwarz preconditioner with iluk as local
+                   preconditioner
+   * add_arms  --  additive schwarz preconditioner with arms as local
+                   preconditioner
+   * lsch_ilu0 --  schur complement preconditioner with ilu0 as local
+                   preconditioner		  
+   * lsch_ilut --  schur complement preconditioner with ilut as local
+                   preconditioner		  
+   * lsch_iluk --  schur complement preconditioner with iluk as local
+                   preconditioner		  
+   * lsch_arms --  schur complement preconditioner with arms as local
+                   preconditioner
+   * sch_gilu0 --  parallel ilu0 preconditioner
+   * sch_sgs   --  Schur-Symmetric GS preconditioner
+   *------------------------------------------------------------------*/
+  /* set the method label for preconditioning and parameter for inner
+     iteration -- actual labels (int) are defined in SRC/ARMS/data.h */ 
+
+  int ierr, method;
+
+  ierr = 0; method=0;
+
+  if(!strcmp(precon_str, "add_ilu0")) method = add_ilu0;
+  else if(!strcmp(precon_str, "add_ilut")) method = add_ilut;
+  else if(!strcmp(precon_str, "add_iluk")) method = add_iluk;
+  else if(!strcmp(precon_str, "add_arms")) method = add_arms;
+  else if(!strcmp(precon_str, "lsch_ilu0")) method = lsch_ilu0;
+  else if(!strcmp(precon_str, "lsch_ilut")) method = lsch_ilut;
+  else if(!strcmp(precon_str, "lsch_iluk")) method = lsch_iluk;
+  else if(!strcmp(precon_str, "lsch_arms")) method = lsch_arms;
+  else if(!strcmp(precon_str, "rsch_ilu0")) method = rsch_ilu0;
+  else if(!strcmp(precon_str, "rsch_ilut")) method = rsch_ilut;
+  else if(!strcmp(precon_str, "rsch_iluk")) method = rsch_iluk;
+  else if(!strcmp(precon_str, "rsch_arms")) method = rsch_arms;
+  else if(!strcmp(precon_str, "sch_sgs")) method = sch_sgs;
+  else if(!strcmp(precon_str, "sch_gilu0")) method = sch_gilu0;
+  else ierr = 1; 
+  char pcrM[40];
+  strcpy(pcrM,"invalid choice for the preconditioner \n");
+ 
+  if (ErrHand(ierr, dm, pcrM)) 
+      exit(1) ; 
+  return method;cout << "Cette resolution semble prendre du temps" << endl;
+
+  }
+
+
+
+#define minint(a, b)       ( (a) < (b) ? (a) : (b) )
+#define maxint(a, b)       ( (a) > (b) ? (a) : (b) )
+#define max(a, b)       ( (a) > (b) ? (a) : (b) )
+#define min(a, b)   ( a < b ? (a) : (b) )
+#define fabsmin(a, b)   ( fabs(a) < fabs(b) ? (a) : (b) )
+#define fabsmax(a, b)   ( fabs(a) > fabs(b) ? (a) : (b) )
+
+
+
+class dSolvePARMS :   public MatriceMorse<double>::VirtualSolver   {
+
+	char 					mat_domain[BUFLEN];
+    	int *riord;
+	mutable int                     n, nnz, nloc;
+
+	int 					iov, scale, unsymm, method,solver,VERBOSE;
+	string data_option;
+	int                     rk, size;
+	mutable double 					*rhs1, res;
+	//double 					t1, t2, t3, t4;
+	double 					*u, *v;
+	int 					job,i1,i2;
+	mutable DistMatrix 				dm;  		//distributed matrix object
+	mutable PrePar 					prepar;  
+	mutable PreCon 					precon;  	//structure for preconditioner
+	mutable IterPar 				ipar;		//structure for iteration
+	mutable  int * maptmp1, *mapptr1;
+	double eps, tol_pivot_sym,tgv, tol_pivot,epsr;
+	mutable double t1,t2,t3,t4;
+	mutable char * meth[14];
+	mutable int *maptmp, *mapptr,*iwork1,*iwork;
+	mutable double *scaletmpr, *scaletmpc;
+	mutable MPI_Comm comm;
+	char *p;
+//Constructor construct the distribute matrix and also preconditionner
+public:
+  dSolvePARMS(const MatriceMorse<double> &AA,string datafile,  KN<long> &param_int,  KN<double> &param_double,  MPI_Comm  * mpicommw)
+	{
+	int n,i,job,nnz,ierr,tmp;
+	int *ptr2,*id_rows2;
+	double *vals2;
+	double *AAv;
+	int *p, *pr;	
+	
+
+	int 	 j,    node;
+	/* Initialize PARMSARSLIB environment */
+	 if(mpicommw==NULL){
+	comm=MPI_COMM_WORLD;
+	}
+	else
+	comm= *mpicommw;
+	// comm=MPI_COMM_WORLD;
+	 ierr = MPI_Comm_rank(comm, &rk);
+	 ierr = MPI_Comm_size(comm, &size);
+	 parm_param * pp;
+	/*Differents preconditionners use*/
+	 meth[0]=(char *)malloc(sizeof(char)*9); strcpy(meth[0],"add_ilu0"); meth[1]=(char *)malloc(sizeof(char)*9); strcpy(meth[1],"add_ilut"); 
+	 meth[2]=(char *)malloc(sizeof(char)*9); strcpy(meth[2],"add_iluk"); meth[3]=(char *)malloc(sizeof(char)*9); strcpy(meth[3],"add_arms");
+	 // FFCS - fixed "buffer overflow" warning by JHunt
+	 meth[4]=(char *)malloc(sizeof(char)*10); strcpy(meth[4],"lsch_ilu0"); meth[5]=(char *)malloc(sizeof(char)*10); strcpy(meth[5],"lsch_ilut");  
+	 meth[6]=(char *)malloc(sizeof(char)*10); strcpy(meth[6],"lsch_iluk"); meth[7]=(char *)malloc(sizeof(char)*10); strcpy(meth[7],"lsch_arms"); 	
+	 meth[8]=(char *)malloc(sizeof(char)*10); strcpy(meth[8],"rsch_ilu0"); meth[9]=(char *)malloc(sizeof(char)*10); strcpy(meth[9],"rsch_ilut");
+         meth[10]=(char *)malloc(sizeof(char)*10); strcpy(meth[10],"rsch_iluk"); meth[11]=(char *)malloc(sizeof(char)*10); strcpy(meth[11],"rsch_arms");
+	 meth[12]=(char *)malloc(sizeof(char)*10); strcpy(meth[12],"sch_gilu0"); meth[13]=(char *)malloc(sizeof(char)*8); strcpy(meth[13],"sch_sgs");
+	/*storage format of the matrix*/
+         char pcrM[4];
+	strcpy(pcrM,"csr");
+	
+	/*- Create Distributed Matrix dm in CSR format */
+		
+	CreateMat(&dm, pcrM);
+	
+	dm->comm->mpi_comm=comm;dm->comm->myproc=rk; dm->comm->npro=size; 
+
+	/*------ Create PrePar /iterPar pointer */
+	
+		
+	/*---- parameters for preconditioning and iteration*/
+	if((datafile.empty())&&(param_double==NULL)&&(param_int==NULL)){
+		if(dm->comm->myproc==0)
+		printf("%s","We are going to set default parameters because user did not specify any one  \n \n ");
+		
+		parm_param * pp= new parm_param(); 
+		 
+		iov=pp->iov; scale=pp->scale; unsymm=pp->unsymm; 
+		
+		method= assignprecon(meth[pp->method], dm);
+		
+		prepar=pp->prepar; ipar=pp->ipar; VERBOSE=pp->VERBOSE; solver=pp->solver;
+	
+	}
+	if(((param_double!=NULL)||(param_int!=NULL))&&(datafile.empty()))
+	{
+		if(dm->comm->myproc==0)
+  		  printf("%s","User have set parameter inside vector of parameter  \n");	
+
+	        parm_param * pp= new parm_param(param_int, param_double); 
+		iov=pp->iov; scale=pp->scale; unsymm=pp->unsymm; method= assignprecon(meth[pp->method], dm); 
+		prepar=pp->prepar; ipar=pp->ipar; VERBOSE=pp->VERBOSE; solver=pp->solver;
+              
+	}
+	if((!datafile.empty())&&((param_double==NULL)&&(param_int==NULL)))
+	{
+		if(dm->comm->myproc==0)
+		printf("%s","User have set parameter inside file of parameter  \n");
+		parm_param * pp= new parm_param(datafile, dm); 
+		iov=pp->iov; scale=pp->scale; unsymm=pp->unsymm; method=pp->method; 
+		prepar=pp->prepar; ipar=pp->ipar; VERBOSE=pp->VERBOSE; solver=pp->solver;
+	}
+	if(((solver==1)||(solver==2))&&((method!=0)||(method!=4))) 
+	{
+		if(dm->comm->myproc==0) 
+		printf("%s%s%s", "WE NOT GARANTI THE PRECONDITIONNER WILL WORK BECAUSE ACCELARATOR ", meth[method] ," NO NEED INNER ITERATION \n");
+		//MPI_Finalize();
+	}
+	if((dm->comm->myproc==0)&&(VERBOSE>=0)){
+		printf("###########################################\n");
+		printf("######### CALLING PARMS PACKAGE ###########\n");
+		if(solver==0)
+		printf("########### SOLVER : FGMRES #######\n");
+		if(solver==1)
+		printf("########### SOLVER : BiCGStab #######\n");
+		if(solver==2)
+		printf("########### SOLVER : DGMRES #######\n");
+		printf("%s%s%s","########### PRECONDITIONNER : ",  meth[method], "\n" );
+		printf("###########################################\n");
+	}
+
+	/*----from zero-based to 1-based before calling pARMS routine----*/
+	n=AA.n; nnz=AA.nbcoef;
+	PARMS_malloc(pr,n+1,int) ;
+	PARMS_malloc(p,nnz,int) ;
+	PARMS_malloc(AAv,nnz,double) ;
+
+	for(i=0;i<nnz;i++){
+	AAv[i]=AA.a[i];
+	p[i]=AA.cl[i];
+	if(i<=n) pr[i]=AA.lg[i];
+	}
+        
+	for(j=0; j<pr[n]; j++){
+		p[j]+=1;
+	}	
+	for(i=0; i<=n; i++){
+		pr[i]+=1;
+	}
+//	pr[0]=1;
+
+	double * vals1;
+	int * id_rows1, *ptr1;
+	/*-------- transpose the matrix to CSC format--*/
+	PARMS_malloc(vals1,nnz,double) ;
+	PARMS_malloc(id_rows1,nnz,int) ;
+	PARMS_malloc(ptr1,n+1,int) ;
+	job=1;
+	i=1;
+	
+	csrcsc(&n, &job, &i, AAv, p, pr, vals1, id_rows1, ptr1);
+	
+ /*----------- compute C=A+B where B=transpose(A) -------*/	
+	
+	 if(unsymm) {
+	
+	PARMS_malloc(iwork,n,int);
+	PARMS_malloc(vals2, 2*nnz, double);
+	PARMS_malloc(id_rows2, 2*nnz, int);
+	PARMS_malloc(ptr2, n+1, int);
+	
+	for(i=0; i<nnz; i++) AAv[i]=0.0;
+	job=1;
+	i1=2*nnz; 
+
+	aplb(&n, &n, &job, vals1, id_rows1, ptr1, AAv, p, pr, 
+		  vals2, id_rows2, ptr2, &i1, iwork, &ierr);
+
+	
+
+	if(ierr) printf("error: in aplb, ierr=%d\n",ierr);
+	nnz=ptr2[n]-1;
+	if (!rk)
+        printf("Matrix pattern has been symmetrized; added %d nonzeros.\n",
+           ptr2[n]-pr[n]);
+
+	memcpy(pr, ptr2, (n+1)*sizeof(int));
+	p=(int *)realloc(p, nnz*sizeof(int));
+	AAv=(double *)realloc(AAv, nnz*sizeof(double));
+	memcpy(p, id_rows2, nnz*sizeof(int));
+	memcpy(AAv, vals2, nnz*sizeof(double));
+	free(vals1); free(vals2); free(id_rows1); free(id_rows2); free(ptr1); free(ptr2);
+	
+	}
+
+	 else {
+/*-------- simply overwrite A with B (transposed matrix)  */
+          nnz = ptr1[n]-1;
+      memcpy(pr, ptr1, (n+1)*sizeof(int));
+      memcpy(p, id_rows1, nnz*sizeof(int));
+      memcpy(AAv,  vals1, nnz*sizeof(double));
+    }
+	
+
+	/*------ scale the matrix */
+	  if(scale) {
+	    job = 1;
+	    tmp = 2; /*-- compute 2-norm */
+	    PARMS_malloc(scaletmpr,n,double) ; PARMS_malloc(scaletmpc,n,double) ;
+	    roscal(&n,&job,&tmp,AAv,p,pr,scaletmpr,AAv,p,pr,&ierr);
+	    if (ierr) fprintf(stderr, "Error: in roscal, ierr = %d\n", ierr);
+	
+	    coscal(&n,&job,&tmp,AAv,p,pr,scaletmpc,AAv,p,pr,&ierr);
+	    if (ierr) fprintf(stderr, "Error: in coscal, ierr = %d\n", ierr);
+	  } /*--- end of branch on scaling */
+
+	/* -------Matrix partitioning : Use Metis ----------*/
+	
+	PARMS_malloc(riord, n, int);
+	int wgtflag=0, numflag=1, volume;
+	
+	int option[5];
+	option[0]=0;
+	if(size>1){
+		METIS_PartGraphVKway(&n, pr, p, NULL, NULL, &wgtflag, &numflag,&size, option, &volume, riord);
+	}
+	else if(size==1){
+		for (i=0; i<n; i++) riord[i]=1;
+	}
+	
+	PARMS_malloc(iwork, n, int);
+	PARMS_malloc(maptmp, n, int);
+	PARMS_malloc(mapptr, size+1, int);
+	PARMS_malloc(iwork1, size+1, int);	
+	for(i=0; i<size; i++){
+		iwork[i]=0;
+	}
+	for(j=0; j<n; j++){
+		iwork[riord[j]-1]++;
+		
+	}
+	numflag=1;
+	for(i=0; i<size; i++){
+		mapptr[i]=numflag;
+		numflag+=iwork[i];
+	}
+	mapptr[size]=numflag;
+	
+	for (i=0; i<size; i++){
+		iwork[i]=mapptr[i]-1;
+	}
+	for(i=0; i<n; i++){
+		maptmp[iwork[riord[i]-1]]=i+1;
+		iwork[riord[i]-1]++;
+	}
+  	
+	
+	if(iov == 0) {
+/*------ in non-overlapping case, simply copy the node-to-processor info */
+ 	   maptmp1= maptmp ;
+   	   mapptr1 = mapptr;
+  	}
+
+	if(iov != 0) {
+/*----- expand sub-domain if overlapping is desired */
+	int maxmp;
+   	 maxmp = 15*n;
+	
+    	 PARMS_malloc(maptmp1,maxmp,int) ;
+    	 PARMS_malloc(mapptr1,size+1,int) ;
+         expnddom(&n, &size, p, pr, maptmp, mapptr, maptmp1, &maxmp,mapptr1, iwork);   	
+	free(maptmp); free(mapptr);
+  }
+	
+	
+/*---map from global node lables to local ---*/
+	getmap(dm, maptmp1, mapptr1, &n);	
+/*---prepare for extraction of local submatrix  --*/
+	int tmp0=1;
+	tmp =1;
+	i1=mapptr1[rk];
+	i2=mapptr1[rk+1]-1;
+	nloc=i2-i1+1;
+	nnz=0;
+
+	for(i=i1; i <=i2; i++){
+		node=maptmp1[i-1];
+		nnz += pr[node]-pr[node-1];
+		
+	}
+	PARMS_malloc(vals1, nnz, double);
+	PARMS_malloc(id_rows1, nnz, int);
+	PARMS_malloc(ptr1, nloc+1, int);
+	/*---- extract the submatrix to be owned by rk */
+	
+
+	DPERM1(&i1,&i2,AAv,p,pr,vals1,id_rows1,ptr1,maptmp1,&tmp0,&tmp);
+	
+	
+	
+
+	 free(p); p=NULL; free(pr); pr=NULL; free(AAv); AAv=NULL;
+
+/* --- CSR to Distributed matrix structure ---*/
+	
+	 CopyCsrToDm(dm, vals1, id_rows1, ptr1);
+	 free(vals1); free(id_rows1); free(ptr1);
+	 vals1=NULL; id_rows1=NULL; ptr1=NULL;
+	
+/*--- create boundary information */
+ 	 bdry(dm);
+
+/*--- set up the local data strucutre for the sparse matrix */
+	 setup(dm);
+	
+	
+	
+/*check consistency of input parameters for 'rsch*' and 'lsch*' preconditioners.
+	 -- at least one iteration on inner iterative solver should be performed for
+	 -- them, e.g., inner convergence tolerance; inner number of iterations and
+	 -- the inner subspace size should be nonzero.
+*/
+	
+	
+	 if (!strncmp(meth[method], "lsch", 4) || !strncmp(meth[method], "rsch", 4) ){
+		 ierr = 0;
+		 if (ipar->pgfpar[0] == 0.0){
+			 if (rk == 0)
+				 fprintf(stderr, "Error: Tolerance for inner solver\n");
+			 ierr = 1;
+		 }
+		 if (ipar->ipar[3] == 0){
+			 if (rk == 0)
+				 fprintf(stderr, "Error: Krylov subspace size for inner solver\n");
+			 ierr = 1;
+		 }
+		 if (ipar->ipar[4] == 0){
+			 if (rk == 0)
+				 fprintf(stderr, "Error: Maximum number of inner iterations\n");
+			 ierr = 1;
+		 }
+		 if (ierr == 1){
+			 if (rk == 0)
+				 fprintf(stderr,"should be nonzero to invoke the Schur Complement iteration\n ");
+			 PARMS_Final();
+			 exit(1);
+		 }
+	 }
+	
+	
+	 /*----- create preconditioner */
+	if(VERBOSE==3){
+	
+	  MPI_Barrier(dm->comm->mpi_comm);
+	 t1 = dwalltime();}
+	
+	 ierr = CreatePrec(dm,&precon,method,prepar,ipar);
+	
+	 
+	 if(VERBOSE==3) {
+	  MPI_Barrier(dm->comm->mpi_comm);
+	 t2 = dwalltime();
+	 t2 = fabs(t2-t1);
+	 double tmax=0.0;
+          MPI_Reduce(&t2, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0,dm->comm->mpi_comm);
+   	  MPI_Bcast(&tmax, 1, MPI_INT,0,dm->comm->mpi_comm);
+	t2=tmax;
+	 }
+	 
+	 /*----- check for errors in preconditioning construction, quit if any */
+	 if (ierr != 0)
+	 fprintf(stderr, "Fatal Error (ierr = %d) in preconditioner construction on processor %d\nExiting...\n", ierr, rk);
+	 ierr = ierr*ierr;
+	 int tmp_ierr=0;
+
+	 MPI_Allreduce(&ierr, &tmp_ierr, 1, MPI_INT, MPI_SUM, dm->comm->mpi_comm);
+	 
+	 if ( tmp_ierr > 0 ){ 
+		 /* delete distributed local matrix */
+		 DeleteMat(&dm);
+		 /* delete distributed local vector */	 
+		 free(prepar);
+		 free(ipar);
+		 free(pp); 
+	         
+		 /* exit PARMS and MPI environment */
+		 PARMS_Final();
+		 exit(1);
+	 }	
+	
+}
+	void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+	/* Vec structure
+	 rhs -- right hand side,
+	 sol -- solution,   
+	 xsol -- exact solution */
+	
+         Vec 	sol, rhs;
+	 int i,comt,node;
+	 int * poloc;
+	 double res1;
+	 double 	dnnz_pre, dgprec_nnz;
+	 nnz=AA.nbcoef;	
+
+	 CreateVec(&rhs);
+	 CreateVec(&sol);
+	 n=AA.n;
+	  double * rhsb=(double *)malloc(sizeof(double)*n);
+	 for(i=0;i<n;i++) rhsb[i]=b[i];
+	 /* Copy communication structure to Vec */
+	 CopyComm(dm,rhs);
+	 CopyComm(dm,sol);
+	 
+	 PARMS_malloc(rhs->vec, nloc, double); PARMS_malloc(poloc, nloc, int);
+	comt=0;
+	 if(scale)
+	     { for(i = 0; i < n; i++) 
+		rhsb[i] *= scaletmpr[i];
+		
+	}
+	
+
+	for(i=i1;i<=i2;i++)
+	{
+		  node = maptmp1[i-1];poloc[comt]=node-1;
+		  rhs->vec[comt]=rhsb[node-1];comt++;
+		  
+	}
+/*----Iteration count-------------------------------------*/
+	ipar->in_iters=0;
+	ipar->iters=0;
+	
+/*--- Permute RHS according to result of setup routine ---*/
+	 setuprhs(rhs);
+	   
+/*------- populate the initial guess with values */
+	 VecSetVal(sol,0.0); 
+/*------- calculate the norm of the residual on input */
+	 res1 = ResiNorm2(dm, sol, rhs);
+	 
+
+	 if(VERBOSE==3){
+	MPI_Barrier(dm->comm->mpi_comm);
+	 t3 = dwalltime(); }
+	double dgnnz;
+	if(VERBOSE==3){
+	dnnz_pre = precon->nnz_pre;
+        dgnnz = (double)nnz;
+	dgprec_nnz=0;
+	 MPI_Reduce(&dgprec_nnz, &dnnz_pre, 1, MPI_DOUBLE, MPI_SUM, 0, dm->comm->mpi_comm); 
+         }
+
+
+	 if(rk == 0) 	{
+			printf("Total NNZ(PreCon) / (NNZ*npro) = %6.2f\n",dgprec_nnz/dgnnz);
+			
+			
+		}
+		
+
+	if(solver==0) fgmresd(dm,precon,ipar,rhs,sol);
+	if(solver==1) dgmresd(dm,precon,ipar,rhs,sol);
+	if(solver==2) bcgstabd(dm,precon,ipar,rhs,sol);
+	
+	
+	 res = ResiNorm2(dm, sol, rhs);
+	
+
+	
+
+	if(VERBOSE==3){	
+	MPI_Barrier(dm->comm->mpi_comm);
+	 t4 = dwalltime(); 
+	 t4 = fabs(t4-t3); 
+	  double tmax=0;
+         MPI_Reduce(&t4, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0,dm->comm->mpi_comm);
+   	 MPI_Bcast(&tmax, 1, MPI_DOUBLE,0,dm->comm->mpi_comm);
+	t4=tmax;
+	 }
+	 
+	 
+	 /*----find the norm of the solution error */
+	 i=1;
+	 t3 = -1.0;
+	 int j;
+	  for (i=0; i<nloc; i++){
+       		j=sol->node[i]-1; /* get the global node corresponding to node i*/
+		poloc[i]=j;
+    	 }
+	
+	 if (scale){
+/*--------- apply permutations to scaletmp */
+   	for (i=0; i<nloc; i++){
+       		j=sol->node[i]-1; /* get the global node corresponding to node i*/
+	        sol->vec[i] = sol->vec[i]*scaletmpc[j];
+	/*---- find the residual of the computed solution */  
+	}
+  }	
+	 /*-----  compute the relative error of computed solution */
+
+	 if((dm->comm->myproc == 0)&&(VERBOSE==3)) {
+		 fprintf(stdout,"################   SOLVER STATISTICS     ####################\n");
+		 fprintf(stdout, "OUTER ITERATIONS COUNT IS %d\n", ipar->iters);
+		 fprintf(stdout, "INNER ITERATION COUNT IS %d\n", ipar->in_iters);
+		 fprintf(stdout, "THE TOTAL TIME IS %16.8f\n", t2+t4);
+		 fprintf(stdout, "THE TIME FOR CREATING PRECONDITIONER IS %16.8f\n", t2);
+		 fprintf(stdout, "THE TIME FOR SOLVING PROCESS is %16.8f\n", t4);
+		 fprintf(stdout, "The 2-NORM OF THE RELATIVE RESIDUAL IS %16.8g\n", res/res1);
+	 }
+	 if((dm->comm->myproc == 0)&&(VERBOSE==2)) {
+		 fprintf(stdout, "THE TOTAL TIME IS %16.8f\n", t2+t4);
+		 fprintf(stdout, "THE TIME FOR CREATING PRECONDITIONER IS %16.8f\n", t2);
+		 fprintf(stdout, "THE TIME FOR SOLVING PROCESS is %16.8f\n", t4);
+	 }
+	 if((dm->comm->myproc == 0)&&(VERBOSE==1)) {
+		 fprintf(stdout, "OUTER ITERATIONS COUNT IS %d\n", ipar->iters);
+		 fprintf(stdout, "INNER ITERATION COUNT IS %d\n", ipar->in_iters);
+		 fprintf(stdout, "The 2-NORM OF THE RELATIVE RESIDUAL IS %16.8g\n", res/res1);
+		 
+		
+	 }
+
+  	  double *  xx= (double *)malloc(sizeof(double)*n);
+	 
+	 
+	   comt=0;
+	    
+	    
+	   for(i=0;i<dm->comm->npro;i++) mapptr[i]--;
+	   int *displs, *perm; 
+	   PARMS_malloc(displs, nloc, int);PARMS_malloc(perm, n, int);
+	 
+	
+	   MPI_Gatherv(&(sol->vec[0]), nloc, MPI_DOUBLE, &(xx[0]), iwork, mapptr ,  MPI_DOUBLE, 0,comm );
+	   MPI_Gatherv(&(poloc[0]), nloc, MPI_INT, &(perm[0]), iwork, mapptr ,  MPI_INT, 0,comm );
+	   MPI_Bcast(perm,AA.n,MPI_INT,0, comm);
+	   
+	   int *invp=(int *)malloc(sizeof(int)*n);
+	   for(i=0;i<n;i++) invp[perm[i]]=i;
+
+	   if(dm->comm->myproc==0){for(i=0;i<n;i++) x[i]=xx[invp[i]];  } 
+	   MPI_Bcast(x,AA.n,MPI_DOUBLE,0, comm);
+	   for(i=0;i<dm->comm->npro;i++) mapptr[i]++;
+	  /*Delete use vectors*/
+	   DeleteVec(&sol); DeleteVec(&rhs); free(xx);
+	   //This should be in Destructor
+	   free(perm); free(invp);
+	  	
+	
+	}
+	~dSolvePARMS()
+	{
+	 if(VERBOSE==3){
+	  cout << "~SolvePARMS:" << endl;
+	 free(mapptr);
+	 DeletePrec(precon); free(scaletmpc); free(scaletmpr);
+	 /*---- Delete distributed local matrix */
+	 DeleteMat(&dm);
+	 /*---- Delete distributed local vector */
+	free(prepar); free(ipar);
+	/*Delete matrix and right hand side*/
+	
+	}
+	 
+	  //PARMS_Final();
+
+         }
+     void addMatMul(const KN_<Complex> & x, KN_<Complex> & Ax) const 
+     {  
+      ffassert(x.N()==Ax.N());
+      Ax +=  (const MatriceMorse<Complex> &) (*this) * x; 
+     }
+};
+
+
+inline MatriceMorse<double>::VirtualSolver *
+BuilddSolvePARMS(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+	 if(verbosity>9)
+      cout << " BuildSolverMUMPSmpi<double>" << endl;
+
+	
+
+    return new dSolvePARMS(*A,ds.data_filename, ds.lparams, ds.dparams,(MPI_Comm *)ds.commworld);
+}
+
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; 
+
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity>1)
+    cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+    return TRUE;
+}
+
+bool SetdSolvePARMS()
+{
+    if(verbosity>1)
+	cout << " SetDefault sparse solver to PARMS" << endl;
+      DefSparseSolver<double>::solver  =BuilddSolvePARMS;
+     TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+     return TRUE;
+}
+Init init;
+Init::Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: pARMSmpi,  defaultsolver defaultsolverpARMSmpi" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuilddSolvePARMS;
+  //DefSparseSolver<Complex>::solver =BuildSolverMUMPSmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("defaulttopARMSmpi","(",new OneOperator0<bool>(SetdSolvePARMS));
+}
+
+
diff --git a/src/solver/real_SuperLU_DIST_FreeFem.cpp b/src/solver/real_SuperLU_DIST_FreeFem.cpp
new file mode 100644
index 0000000..0035b69
--- /dev/null
+++ b/src/solver/real_SuperLU_DIST_FreeFem.cpp
@@ -0,0 +1,791 @@
+//   for automatic  compilation with ff-c++
+//ff-c++-LIBRARY-dep: superlu_dist parmetis metis  blas 
+//ff-c++-cpp-dep: 
+//
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+#include  <iostream>
+using namespace std;
+
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+#include "mpi.h"
+#include "superlu_ddefs.h"
+#include "ffsuperludistoption.hpp"
+
+template <class R> struct SuperLUmpiDISTDriver
+{
+    
+};
+
+template <> struct SuperLUmpiDISTDriver<double>
+{
+  /* Driver routines */
+  static  Dtype_t R_SLU_T() { return SLU_D;} 
+  static void
+  
+  pgssvx(superlu_options_t *p1, SuperMatrix *p2, ScalePermstruct_t *p3,
+	  double *p4, int p5, int p6, gridinfo_t *p7,
+	  LUstruct_t *p8, SOLVEstruct_t *p9, double *p10,
+	  SuperLUStat_t *p11, int *p12)
+  { pdgssvx( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12 ); }
+  
+    
+  static void
+  pgssvx_ABglobal(superlu_options_t *p1, SuperMatrix *p2, 
+	 ScalePermstruct_t *p3,
+	 double *p4, int p5, int p6, gridinfo_t *p7,
+	 LUstruct_t *p8, double *p9,
+	 SuperLUStat_t *p10, int *p11)
+  { pdgssvx_ABglobal( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11); }
+        
+  static void
+  Print_CompRowLoc_Matrix_dist(SuperMatrix *p1)
+  {
+    dPrint_CompRowLoc_Matrix_dist(p1);
+  }
+
+  static void
+  Create_CompCol_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+			     double *p5, int_t *p6, int_t *p7,
+			    Stype_t p8, Dtype_t p9, Mtype_t p10)
+  {
+    dCreate_CompCol_Matrix_dist(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10);
+  }
+  
+  static void
+  Create_CompRowLoc_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3,
+				 int_t p4, int_t p5, int_t p6,
+				 double *p7, int_t *p8, int_t *p9,
+				 Stype_t p10, Dtype_t p11, Mtype_t p12)
+  {
+    dCreate_CompRowLoc_Matrix_dist( p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12);
+  }
+   
+  static void
+  CompRow_to_CompCol_dist(int_t p1, int_t p2, int_t p3, 
+                         double *p4, int_t *p5, int_t *p6,
+                         double **p7, int_t **p8, int_t **p9)
+  {
+    dCompRow_to_CompCol_dist( p1,p2,p3,p4,p5,p6,p7,p8,p9 );
+  }
+
+  static void
+  Create_Dense_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, double *p4,
+			    int_t p5, Stype_t p6, Dtype_t p7,
+			    Mtype_t p8)
+  {
+    dCreate_Dense_Matrix_dist( p1,p2,p3,p4,p5,p6,p7,p8 );  
+  }
+
+  static void
+  Create_SuperNode_Matrix_dist(SuperMatrix *p1, int_t p2, int_t p3, int_t p4, 
+				double *p5, int_t *p6,
+				int_t *p7, int_t *p8,
+				int_t *p9, int_t *p10,
+				Stype_t p11, Dtype_t p12, Mtype_t p13)
+  {
+    dCreate_SuperNode_Matrix_dist(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,  p11,p12,p13);
+  }
+
+};
+
+template<class R>
+class SolveSuperLUmpi :   public MatriceMorse<R>::VirtualSolver, public SuperLUmpiDISTDriver<R>   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+   
+   
+  //mutable char           equed[1];
+  //yes_no_t       equil;
+  mutable SuperMatrix    A;
+  NCformat       *Astore;
+  //NCformat       *Ustore;
+  //SCformat       *Lstore;
+
+  mutable superlu_options_t options;
+  mutable mem_usage_t    mem_usage;
+  mutable ScalePermstruct_t ScalePermstruct;
+  mutable LUstruct_t        LUstruct;
+  mutable SOLVEstruct_t     SOLVEstruct;
+  mutable gridinfo_t        grid;
+
+  string string_option;
+  string data_option;
+  R             *a;
+  int           *asub, *xa;
+  int_t m, n, nnz;
+  // rajout pour //
+  int_t nprow,npcol;  /* process rows and process columns*/
+
+
+  int matrixdist; // type of distributed matrix
+  MPI_Comm commworld ;
+  static const int assembled =0;
+  static const int distributedglobal =1;
+  static const int distributed =2;
+
+  int iam;
+
+public:
+  SolveSuperLUmpi(const MatriceMorse<R> &AA,int strategy,double ttgv, double epsilon,
+		  double pivot,double pivot_sym, string datafile,
+		  string param_char, KN<long> &pperm_r, KN<long> &pperm_c,void * ccommworld=0) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),string_option(param_char),data_option(datafile),
+    tol_pivot_sym(pivot_sym),tol_pivot(pivot)
+  { 
+    commworld = ccommworld ? *static_cast<MPI_Comm*>( ccommworld) : MPI_COMM_WORLD;    
+    R*      B;
+    //R*      X;
+    SuperLUStat_t stat;
+    int            info, ldb, nrhs=0;
+    int            i;
+    double*        berr;
+    
+    //int iam;
+    // Add for distributed matrix
+    int_t         m_loc, m_loc_fst, fst_row, nnz_loc, fst_nnz;
+    R             *aloc;
+    int           *asubloc, *xaloc;
+    // End Add for distributed matrix
+    A.Store=0;
+   
+    int status;
+    // time variables
+
+    long int starttime,finishtime;
+    long int timeused;
+
+    // rajout debug
+    int myid;
+    if(verbosity) starttime = clock();
+
+
+    /* Defaults */
+    nrhs  = 0;
+
+    /* lecture de nprow and npcol */
+    // Cas max deux procs
+    nprow = 1;
+    npcol = 1;
+    matrixdist=0;
+    
+    
+    if(!data_option.empty()) read_nprow_npcol_matrixdist_superlu_datafile(&data_option, &nprow, &npcol, &matrixdist);
+    if(!string_option.empty()) read_nprow_npcol_freefem( &string_option, &nprow, &npcol, &matrixdist);
+    
+     /* ------------------------------------------------------------
+	 INITIALIZE THE SUPERLU PROCESS GRID. 
+	 ------------------------------------------------------------*/
+
+    cout << "Real superlu_gridinit" << " " << commworld << " " << ccommworld <<endl;
+    superlu_gridinit(commworld, nprow, npcol, &grid);
+
+    /* Bail out if I do not belong in the grid. */
+    iam = grid.iam;
+    if ( iam >= nprow * npcol ){      
+      printf("this process is not used in superlu %d \n",iam);
+    }
+    else
+      {
+	/* set the default options */
+	set_default_options_dist(&options);
+	DiagScale_t optionDiagScale;
+
+	if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);	
+	if(!data_option.empty()) read_options_superlu_datafile(&data_option,&options,&nprow, &npcol, &matrixdist,&optionDiagScale);
+
+	// matrix to procs and vectors
+	if( matrixdist == assembled ){
+	  
+	  if(!iam){
+	    cout <<  "iam=" << iam << endl;
+	    printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	    
+	    /* create the matrix for superlu_dist */
+	    n=AA.n;
+	    m=AA.m;
+	    nnz=AA.nbcoef;
+	  
+	    assert( AA.lg[n] == nnz );	   
+	    printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	    
+	    /* transform Row to Col */
+	    // cela coute cher comme fonction //
+	    //dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    //dCompRow_to_CompCol_dist(m,n,nnz,arow,asubrow,xarow,&a,&asub,&xa);
+	    
+	    dCompRow_to_CompCol_dist(m,n,nnz,AA.a,AA.cl,AA.lg,&a,&asub,&xa);
+	    
+	    /* Broadcast matrix A to the other PEs. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    int infobcast=MPI_Bcast( a,    nnz, MPI_DOUBLE, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	    
+	  }
+	  else{
+	    /*
+	      printf("\tProcess grid\t%d X %d\n", grid.nprow, grid.npcol);
+	      /* Receive matrix A from PE 0. */
+	    MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	    
+	    /* Allocate storage for compressed column representation. */
+	    dallocateA_dist(n, nnz, &a, &asub, &xa);
+	    
+	    int infobcast=MPI_Bcast( a, nnz, MPI_DOUBLE, 0, grid.comm );
+	    MPI_Bcast( asub, nnz, mpi_int_t,  0, grid.comm );
+	    MPI_Bcast( xa,   n+1, mpi_int_t,  0, grid.comm );
+	    
+	  }
+	  
+	  Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	  
+	  cout << "Debut: Create_CompCol_Matrix_dist" <<endl;
+	  Create_CompCol_Matrix_dist(&A, m, n, nnz, a, asub, xa, SLU_NC, R_SLU, SLU_GE);      
+	  cout << "Fin: Create_CompCol_Matrix_dist" <<endl;
+	  /* creation of pseudo solution + second member */
+	  
+	  if ( !(B = doubleMalloc_dist(m )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+
+	  
+	  /* Initialize ScalePermstruct and LUstruct. */
+	  ScalePermstructInit(m, n, &ScalePermstruct);
+	  if( !(pperm_r==NULL)  ||  !(pperm_c==NULL) ) ScalePermstruct.DiagScale=optionDiagScale;
+	  if( !(pperm_r==NULL) ) 
+	    for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[ii];
+	  if( !(pperm_c==NULL) )
+	    for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii]= pperm_c[ii];
+	  
+	  if( ScalePermstruct.DiagScale != NOEQUIL ){
+	    printf("FreeFem++ doesn't support change of the original matrix"); 
+	    exit(1);
+	  }
+	  LUstructInit(m, n, &LUstruct);
+	  
+	  /* Initialize the statistics variables. */
+	  PStatInit(&stat);
+	  
+	  ldb = m;
+	  nrhs=1;
+	  if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	    printf("probleme d allocation\n");
+	    exit(1);
+	  }
+	  berr[0]=0.;
+    	
+	  if(verbosity)
+	    printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	
+	  /* INIT LU struct*/
+	  
+	  /* ONLY PERFORM THE LU DECOMPOSITION */
+	  //B.ncol = 0;  /* Indicate not to solve the system */
+	  
+	  nrhs=0;
+	  SuperLUmpiDISTDriver<R>::pgssvx_ABglobal(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					       &LUstruct, berr, &stat, &info);
+	
+	  if(verbosity)
+	    printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	  
+	  if ( verbosity) PStatPrint(&options,&stat,&grid);
+	  PStatFree(&stat);
+	  	 
+	}
+	//##########################################################
+	//
+	//       matrix distributed with matrix global given
+	//
+	//##########################################################
+	else if( matrixdist == distributedglobal) {
+	   if(!iam){
+
+	     printf("\tProcess grid\t%d X %d iam=%d \n", grid.nprow, grid.npcol,iam);
+	
+	     /* create the matrix for superlu_dist */
+	     n=AA.n;
+	     m=AA.m;
+	     nnz=AA.nbcoef;
+	     a=AA.a;
+	     asub=AA.cl;
+	     xa=AA.lg;
+	     
+	     xa[n] = nnz;
+	     printf("\tDimension\t%dx%d\t # nonzeros %d\n", m, n, nnz);
+	     
+	     /* Broadcast matrix A to the other PEs. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     MPI_Bcast( AA.a,    nnz, MPI_DOUBLE, 0, grid.comm );
+	     MPI_Bcast( AA.cl, nnz, mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( AA.lg,   n+1, mpi_int_t,  0, grid.comm );
+	     
+	     
+	   }
+	   else{
+	     
+	     printf("\tProcess grid\t%d X %d iam=%d \n", grid.nprow, grid.npcol,iam);
+	     /* Receive matrix A from PE 0. */
+	     MPI_Bcast( &m,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &n,   1,   mpi_int_t,  0, grid.comm );
+	     MPI_Bcast( &nnz, 1,   mpi_int_t,  0, grid.comm );
+	     
+	     /* Allocate storage for compressed column representation. */
+	     dallocateA_dist(n, nnz, &a, &asub, &xa);
+	     
+	     MPI_Bcast(    a,   nnz, MPI_DOUBLE,  0, grid.comm );
+	     MPI_Bcast( asub,   nnz,  mpi_int_t,  0, grid.comm );
+	     MPI_Bcast(   xa,   n+1,  mpi_int_t,  0, grid.comm );
+
+	   }
+	   
+	   /* Compute the number of rows to be distributed to local process */
+	   m_loc = m / (grid.nprow * grid.npcol); 
+	   m_loc_fst = m_loc;
+	   /* When m / procs is not an integer */
+	   if ((m_loc * grid.nprow * grid.npcol) != m) {
+	     /*m_loc = m_loc+1;
+	       m_loc_fst = m_loc;*/
+	     if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	       m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	   }
+	   
+	   fst_row = iam * m_loc_fst;
+	   
+	   nnz_loc = xa[fst_row+m_loc]-xa[fst_row];
+	   
+	   xaloc = (int_t*) intMalloc_dist(m_loc+1);
+	   for(int ii=0; ii < m_loc; ii++){
+	     xaloc[ii] = xa[fst_row+ii]-xa[fst_row];	
+	   }
+	   
+	   xaloc[m_loc]=nnz_loc;
+	   
+	   fst_nnz = xa[fst_row];
+	   aloc    = (double*) doubleMalloc_dist(nnz_loc);
+	   asubloc = (int_t*)  intMalloc_dist(nnz_loc);
+	   
+	   for(int ii=0; ii < nnz_loc; ii++){
+	     aloc[ii] = a[fst_nnz+ii];
+	     asubloc[ii] = asub[fst_nnz+ii];
+	   }
+
+	   if( iam ){
+	     SUPERLU_FREE( a );
+	     SUPERLU_FREE( asub );
+	     SUPERLU_FREE( xa );
+	   }
+	   Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+	   
+	   cout << "Debut: Create_CompRowCol_Matrix_dist" <<endl;
+	   dCreate_CompRowLoc_Matrix_dist(&A, m, n, nnz_loc, m_loc, fst_row, aloc, asubloc, xaloc, SLU_NR_loc, R_SLU, SLU_GE);
+	   
+	   cout << "Fin: Create_CompRowCol_Matrix_dist" <<endl;
+	   /* creation of pseudo solution + second member */
+	   
+	   
+	   if ( !(B = doubleMalloc_dist(m_loc)) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   
+	   for(int ii=0; ii < m_loc; ii++){
+	     B[ii] = 1.; //BB[fst_row+ii];
+	   }
+     
+	   if(verbosity)
+	     printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   
+	   /* set the default options */
+	   //set_default_options_dist(&options);
+	   //DiagScale_t optionDiagScale;
+	   //if(!string_option.empty()) read_options_freefem(&string_option,&options,&optionDiagScale);
+	   	   
+	   m=A.nrow;
+	   n=A.ncol;
+	   printf("Dimension %dx%d; # nonzeros %d\n", A.nrow, A.ncol, nnz);
+	   /* Initialize ScalePermstruct and LUstruct. */
+	   ScalePermstructInit(m, n, &ScalePermstruct);
+	   if(pperm_r  ||  pperm_c ) ScalePermstruct.DiagScale=optionDiagScale;
+	   if(pperm_r) 
+	     for(int ii=0; ii<m; ii++) ScalePermstruct.perm_r[ii] = pperm_r[fst_row+ii];
+	   if(pperm_c) 
+	     for(int ii=0; ii<n; ii++) ScalePermstruct.perm_c[ii] = pperm_c[ii];
+	   
+	   LUstructInit(m, n, &LUstruct);
+	   
+	   /* Initialize the statistics variables. */
+	   PStatInit(&stat);
+	   
+	   ldb = m_loc;
+	   //ldx = m_loc;
+	   
+	   nrhs=1;
+	   if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	     printf("probleme d allocation\n");
+	     exit(1);
+	   }
+	   berr[0]=0.;
+	   
+	   /* ONLY PERFORM THE LU DECOMPOSITION */
+    
+	   nrhs=0;
+	   SuperLUmpiDISTDriver<R>::pgssvx(&options, &A,  &ScalePermstruct, B, ldb, nrhs, &grid,
+					   &LUstruct, &SOLVEstruct, berr, &stat, &info);
+	   
+	   if(verbosity)
+	     printf("LU factorization: pdgssvx()/p returns info %d\n", info);
+	   
+	   if ( verbosity) PStatPrint(&options,&stat,&grid);
+	   PStatFree(&stat);
+	}
+	else if( matrixdist == distributed) {
+	  printf("in construction\n");
+	  exit(1);
+	}
+	else{
+	  printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	  exit(1);
+	}
+	
+	SUPERLU_FREE( B );
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	nrhs=1;
+	SUPERLU_FREE(berr);  	
+      
+	if(iam==0){
+	  finishtime = clock();
+	  timeused= (finishtime-starttime)/(1000 );
+	  printf("=====================================================\n");
+	  cout << "SuperLU_DIST : time factorisation :: " << timeused << " ms" <<endl;
+	  printf("=====================================================\n");
+	}
+      }
+  }
+
+  void Solver(const MatriceMorse<R> &AA,KN_<R> &x,const KN_<R> &b) const  {
+    R*        B;
+    SuperLUStat_t  stat;
+    //int            iam;
+    int            info=0, ldb=m, nrhs=1;
+    int            i;
+    double*        berr;
+    double         ferr; 
+    double         rpg, rcond;
+      
+    int_t    m_loc,m_loc_fst,fst_row;
+    // time variable
+    long int starttime,finishtime;
+    long int timeused;
+
+    if( iam < nprow*npcol){
+
+      if(verbosity) starttime = clock();
+      
+      if(n != m) exit(1);
+      
+      ffassert ( &x[0] != &b[0]);
+      epsr = (eps < 0) ? (epsr >0 ? -epsr : -eps ) : eps ;
+      
+      Dtype_t R_SLU = SuperLUmpiDISTDriver<R>::R_SLU_T(); 
+      nrhs= 1;
+      
+
+  
+      //iam = grid.iam;
+      //if( iam < nprow*npcol){
+      /* Initialize the statistics variables. */
+      PStatInit(&stat);
+      /* cas matrix assembled */ 
+      if( matrixdist == assembled ){
+	
+	if( !(B = doubleMalloc_dist(m*nrhs)) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	for(int ii=0; ii<n; ii++){
+	  B[ii]=b[ii];
+	}
+	
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */   
+	ldb = m;
+	//nrhs= 1;
+	SuperLUmpiDISTDriver<R>::pgssvx_ABglobal (&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+						  &LUstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if(verbosity) PStatPrint(&options, &stat, &grid);   
+	
+	for(int ii=0; ii<n; ii++){
+	  x[ii] = B[ii]; 
+	}
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+      }
+      else if( matrixdist == distributedglobal) {
+	double*    xtemp;
+	//iam = grid.iam;
+	/* Compute the number of rows to be distributed to local process */
+	m_loc = m / (grid.nprow * grid.npcol); 
+	m_loc_fst = m_loc;
+	/* When m / procs is not an integer */
+	if ((m_loc * grid.nprow * grid.npcol) != m) {
+	  /*m_loc = m_loc+1;
+	    m_loc_fst = m_loc;*/
+	  if (iam == (grid.nprow * grid.npcol - 1)) /* last proc. gets all*/
+	    m_loc = m - m_loc * (grid.nprow * grid.npcol - 1);
+	}
+	
+	fst_row = iam * m_loc_fst;
+	
+	if ( !(B = doubleMalloc_dist(m_loc )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	
+	//printf("initilisation B:");
+	for(int ii=0; ii<m_loc; ++ii){
+	  B[ii] = b[ii+fst_row];
+	  //printf("  B[%d]= %f  ",ii,B[ii]);
+	}
+	//printf(" :: fin \n");
+	//fflush(stdout);
+	
+      
+	if ( !(berr = doubleMalloc_dist(nrhs )) ){
+	  printf("probleme d allocation\n");
+	  exit(1);
+	}
+	berr[0]=0.;
+	
+	options.Fact = FACTORED; /* Indicate the factored form of A is supplied. */
+	//options.Equil = YES;
+	//options.Trans = TRANS;
+	
+	
+	ldb = m;
+	SuperLUmpiDISTDriver<R>::pgssvx(&options, &A, &ScalePermstruct, B, ldb, nrhs, &grid,
+					&LUstruct, &SOLVEstruct, berr, &stat, &info );
+	
+	if(verbosity)
+	  printf("Triangular solve: dgssvx() returns info %d\n", info);
+	
+	if ( !(xtemp = doubleMalloc_dist(AA.n)) ){
+	  printf("probleme d allocation de xtemp\n");
+	  exit(1);
+	}
+	
+      
+	int disp[nprow*npcol];
+	MPI_Allgather(&fst_row, 1, MPI_INT, disp, 1, MPI_INT, grid.comm);
+	
+	int recv[nprow*npcol];
+	MPI_Allgather(&m_loc, 1, MPI_INT, recv, 1, MPI_INT, grid.comm);
+	
+	MPI_Allgatherv(B, m_loc, MPI_DOUBLE, xtemp, recv, disp, MPI_DOUBLE, grid.comm);
+	
+	for(int ii= 0; ii< AA.n ; ii++)
+	  x[ii] = xtemp[ii];
+	
+	if(verbosity) cout << "   x min max " << x.min() << " " <<x.max() << endl;
+	
+	SUPERLU_FREE( xtemp );
+      
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+      
+
+      SUPERLU_FREE( B );
+      SUPERLU_FREE( berr );
+      
+      PStatFree(&stat);
+   
+      if(iam==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << "SuperLu_DIST: time solve step :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+    }
+    
+  }
+    
+  ~SolveSuperLUmpi() { 
+    //int iam;
+    //iam = grid.iam;
+    if(iam < nprow*npcol){
+      if(verbosity)
+	cout << "~SolveSuperLUmpi double:" << endl;
+      
+      if( matrixdist == assembled) {
+	//if( A.Store)  Destroy_CompCol_Matrix_dist(&A);
+	//if( L.Store && U.Store )  {
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	//}
+	if ( options.SolveInitialized ) {
+	  dSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributedglobal) {
+	Destroy_CompRowLoc_Matrix_dist(&A);
+	
+	Destroy_LU(n, &grid, &LUstruct);
+	ScalePermstructFree(&ScalePermstruct);
+	LUstructFree(&LUstruct);
+	
+	if ( options.SolveInitialized ) {
+	  dSolveFinalize(&options, &SOLVEstruct);
+	}
+      }
+      else if( matrixdist == distributed) {
+	printf("in construction\n");
+	exit(1);
+      }
+      else{
+	printf("matrix choice for SuperLU_DIST is assembled, distributedglobal and distributed \n");
+	exit(1);
+      }
+    }
+    printf("Real superlu_gridexit(&grid), %d\n",iam);
+    superlu_gridexit(&grid); 
+    
+  }
+  void addMatMul(const KN_<R> & x, KN_<R> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<R> &) (*this) * x; 
+  }
+     
+}; 
+
+
+
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverSuperLUmpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverSuperLUmpi<double>" << endl;
+    return new SolveSuperLUmpi<double>(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym,
+				       ds.data_filename, ds.sparams, ds.perm_r, ds.perm_c, ds.commworld);
+}
+
+
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+}
+
+bool SetSuperLUmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to SuperLUmpi double" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverSuperLUmpi;
+    //DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+}
+
+
+
+Init init;
+Init::Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: Real SuperLUdist,  defaultsolver defaultsolverSuperLUdist" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverSuperLUmpi;
+  //DefSparseSolver<Complex>::solver =BuildSolverSuperLUmpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("realdefaulttoSuperLUdist","(",new OneOperator0<bool>(SetSuperLUmpi));
+}
+
diff --git a/src/solver/real_pastix_FreeFem.cpp b/src/solver/real_pastix_FreeFem.cpp
new file mode 100644
index 0000000..dc03577
--- /dev/null
+++ b/src/solver/real_pastix_FreeFem.cpp
@@ -0,0 +1,711 @@
+// ORIG-DATE: 02/2009
+// -*- Mode : c++ -*-
+//
+// SUMMARY  :  
+// USAGE    : LGPL      
+// ORG      : LJLL Universite Pierre et Marie Curie, Paris,  FRANCE 
+// AUTHOR   : Jacques Morice
+// E-MAIL   : jacques.morice at ann.jussieu.fr
+//
+
+/* 
+ This file is part of Freefem++
+ 
+ Freefem++ is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+ 
+ Freefem++  is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public License
+ along with Freefem++; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Thank to the ARN ()  FF2A3 grant
+ ref:ANR-07-CIS7-002-01 
+ */
+
+/*
+  Interface entre freefem++ et pastix
+*/
+#include  <iostream>
+using namespace std;
+   
+#include "rgraph.hpp"
+#include "error.hpp"
+#include "AFunction.hpp"
+
+//#include "lex.hpp"
+#include "MatriceCreuse_tpl.hpp"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+#include <mpi.h>
+
+// #include <ctype.h>
+// #include <stdio.h>
+// #include <stdlib.h>
+// #include <unistd.h>
+// //#include <pthread.h>
+// #include <string.h>
+// #include <time.h>
+// #include <sys/time.h>
+// #include "mpi.h"
+   
+// #include <assert.h>
+// #include "pastix.h"
+// #include "cscd_utils.h"
+// #include "read_matrix.h"
+
+#include <assert.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "pastix.h"
+//#include "cscd_utils.h"
+#ifdef __cplusplus
+}
+#endif
+//#include "read_matrix.h"
+
+#undef memFree_null
+#define memFree_null(x) {if (x ==NULL) {fprintf(stdout,"%s:%d freeing NULL\n",__FILE__,__LINE__);} free(x); x=NULL;}
+
+#define STR_SIZE 256
+
+static pastix_int_t * pastixint(int * ii){ return (pastix_int_t*) (void *) ii;} 
+static pastix_float_t * pastixfloat(double * ii){ return (pastix_float_t*) (void *) ii;} 
+
+typedef struct pastix_param {
+  pastix_data_t          *pastix_data; /*Pointer used by PaStiX to keep information alive between calls */
+  MPI_Comm                comm;        /* Communicator used by PaStiX                                    */
+  pastix_int_t            Ncol;        /* Size of the Matrix                                             */
+  pastix_int_t           *ia;          /* Index of first element of each column in ja and avals          */  
+  pastix_int_t           *ja;          /* Rows of the unknows of the matrix                              */
+  pastix_float_t         *avals;       /* Values of the matrix                                           */
+  pastix_int_t           *perm;        /* Permutation used for re-numbering of the unknowns              */
+  pastix_int_t           *invp;        /* Inverse permutation                                            */
+  pastix_float_t         *rhs;         /* Right hand side                                                */
+  pastix_int_t           *iparm;       /* Integer parameters                                             */
+  double                 *dparm;       /* Floating parameters                                            */
+} pastix_param_t;
+
+
+
+void
+Morse_to_CSC(int m, int n, int nnz, 
+	     double *a, int *colind, int  *rowptr,
+	     pastix_float_t **at, pastix_int_t **rowind, 
+	     pastix_int_t **colptr)
+{
+    register int i, j, col, relpos;
+    pastix_int_t *marker;
+
+    /* Allocate storage for another copy of the matrix. */
+    *at     = (pastix_float_t *) malloc(sizeof(pastix_float_t)*nnz);
+    *rowind = (pastix_int_t *) malloc(sizeof(pastix_int_t)*nnz);
+    *colptr = (pastix_int_t *) malloc(sizeof(pastix_int_t)*(n+1));
+    marker  = (pastix_int_t *) malloc(sizeof(pastix_int_t)*n);
+    
+    for (i = 0; i < n; ++i)
+      marker[i] = 0;
+    /* Get counts of each column of A, and set up column pointers */
+    for (i = 0; i < m; ++i)
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) ++marker[colind[j]];
+    (*colptr)[0] = 0;
+    for (j = 0; j < n; ++j) {
+	(*colptr)[j+1] = (*colptr)[j] + marker[j];
+	marker[j] = (*colptr)[j];
+    }
+
+    /* Transfer the matrix into the compressed column storage. */
+    for (i = 0; i < m; ++i) {
+	for (j = rowptr[i]; j < rowptr[i+1]; ++j) {
+	    col = colind[j];
+	    relpos = marker[col];
+	    (*rowind)[relpos] = i;
+	    (*at)[relpos] = a[j];
+	    ++marker[col];
+	}
+    }
+
+    free(marker);
+}
+
+static const int MAX_CHAR_PER_LINE=256;
+//void read_datafile_pastixff(const string &datafile, pastix_int_t *iparmtab, double *dparmtab){
+void read_datafile_pastixff(const string &datafile, int &mpi_flag, pastix_int_t *iparmtab, double *dparmtab){
+  FILE*   m_File;
+  int     i = 0;
+  char    szbuff[MAX_CHAR_PER_LINE];
+  char*   token;
+  
+  char filename[datafile.size()+1];  
+  strcpy( filename, datafile.c_str()); 
+
+  m_File = fopen(filename,"rt");
+
+  if(!m_File)
+    {
+      printf("error in reading filename %s\n",&filename);
+    }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  
+  if( !(strcmp(token,"matrix") == 0) ){
+    printf("freefem++: error in reading matrix parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading matrix parameter for pastix \n");    
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+  
+  if(strcmp(token,"assembled") == 0)
+    mpi_flag = 0;
+  else if(strcmp(token,"distributedglobal") == 0) 
+    mpi_flag = 1;
+  else if(strcmp(token,"distributed") == 0) 
+    mpi_flag = 2;
+  else{
+    printf("value of parameter matrix is not correct %s \n", token );
+  }
+
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");
+
+  if( !(strcmp(token,"iparm") == 0) ){
+    printf("freefem++: error in reading iparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading iparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      iparmtab[i] = (pastix_int_t)atol(token);
+      i++;
+    }
+
+  i=0;
+  fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+  token = strtok(szbuff," /#!\t\n");  
+  if( !(strcmp(token,"dparm") == 0) ){
+    printf("freefem++: error in reading dparm parameter for pastix (see strcuture of ffpastix_iparm_dparm.txt) \n");
+    exit(1);
+  }
+  else{
+    printf("freefem++: reading dparm parameter for pastix \n");    
+  }
+  while(!feof(m_File) && i < 64)
+    {   
+      fgets(szbuff,MAX_CHAR_PER_LINE,m_File);
+      token = strtok(szbuff," /#!\t\n");
+      dparmtab[i] = atof(token);
+      i++;
+    }
+ 
+  fclose(m_File);
+
+#ifdef OOC
+/*   if (iparmtab[IPARM_OOC_THREAD] > 1) */
+    iparmtab[IPARM_OOC_THREAD] = 1;
+#endif
+  /* On empeche le 2d avec NUMA_ALLOC */
+#ifdef NUMA_ALLOC
+  if (iparmtab[IPARM_DISTRIBUTION_LEVEL] != 0)
+    {
+      errorPrint("2D not available with NUMA allocation\n");
+      exit(-1);
+    }
+#endif
+}
+
+// ATTENTION :: pastix_float_t  
+//      peut �tre soit un complex ou un reel cela depend de la maniere dont on a compiler pastix
+
+// CAS DOUBLE SEULEMENT 
+
+
+
+class dSolvepastixmpi :   public MatriceMorse<double>::VirtualSolver   {
+  
+  double eps;
+  mutable double  epsr;
+  double tgv;
+  double tol_pivot_sym,tol_pivot; //Add 31 oct 2005
+  
+
+  int paraoption;
+  int myid, mpi_size;
+  int Nrow;
+  int mpi_flag;
+  int init_raff;
+  int thrd_flag;
+  int SYM;
+  
+  string data_option;
+  
+  mutable pastix_int_t  iparm[64];
+  mutable double        dparm[64];
+  mutable pastix_int_t    Ncol;
+  mutable pastix_int_t   *ia;
+  mutable pastix_int_t   *ja;
+  mutable pastix_float_t *avals;
+  mutable pastix_int_t   *loc2glob;
+  //char           *Type    = NULL;
+  //char           *RhsType = NULL;
+  mutable pastix_float_t *rhs;
+  mutable pastix_int_t   *perm;
+  mutable pastix_int_t   *invp;
+  mutable pastix_data_t  *pastix_data;
+  
+
+public:
+
+  dSolvepastixmpi(const MatriceMorse<double> &AA, int strategy, double ttgv, double epsilon,
+		  double pivot, double pivot_sym, string datafile, KN<long> &pparam_int, KN<double> &pparam_double, 
+		  KN<long> &pperm_r, KN<long> &pperm_c) : 
+    eps(epsilon),epsr(0),
+    tgv(ttgv),tol_pivot_sym(pivot_sym),tol_pivot(pivot),
+    data_option(datafile) 
+  { 
+    KN_<long> param_int(pparam_int);
+    KN_<double> param_double(pparam_double);
+
+    //int m;
+    //int ierr;
+    struct timeval  tv1, tv2;
+    int nnz;
+   
+     // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+
+    ia    = NULL;
+    ja    = NULL;
+    avals   = NULL;
+    loc2glob = NULL;
+    rhs     = NULL;
+    pastix_data = NULL;
+    
+    // matrix assembled on host
+    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
+    printf("- Rang MPI : %d\n", myid);
+    MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
+    // SYMETRIQUE
+    // MPI_flag need to unselect for non distributed matrix
+    mpi_flag  = 0;
+    thrd_flag = 0;
+
+    // ######################  
+    //pastix_int_t init_raff;
+    fprintf(stdout,"-- INIT PARAMETERS --\n");
+    
+    // reading iparm from array    
+    if(!data_option.empty()){
+      read_datafile_pastixff(data_option,mpi_flag,iparm,dparm);
+      if(mpi_flag != 0) 
+	cerr << "ERROR :: GLOBAT INPUT MATRIX FOR ALL PROCS  matrix=assembled" << endl;
+    }
+    else if( !(param_int==NULL) || !(param_double==NULL) ){
+      if( !(param_int==NULL) ) 
+      {
+	cout << "read param_int" << endl;
+	assert(param_int.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  iparm[ii] = param_int[ii];
+	iparm[IPARM_MODIFY_PARAMETER] = API_YES;
+      }
+      if( !(param_double==NULL) ) 
+      {
+	cout << "read param_double" << endl;
+	assert(param_double.N() == 64);
+	for(int ii=0; ii<64; ii++) 
+	  dparm[ii] = param_double[ii];
+      }
+    }  
+    else{
+      iparm[IPARM_MODIFY_PARAMETER] = API_NO;
+      cout << "initialize parameter" << endl;
+    }
+    
+    //################################
+    if( myid==0 ){
+      Ncol = AA.m;
+      Nrow = AA.n;
+      nnz  = AA.nbcoef;
+
+      // Avant : on ecrit la transpos�e
+      
+      // AA.cl : indices des colonnes
+      // AA.lg : pointeurs des lignes
+      Morse_to_CSC( AA.n , AA.m, AA.nbcoef, AA.a, AA.cl, AA.lg, &avals, &ja, &ia);
+      // ia : pointeurs des colonnes
+      // ja : indices des lignes
+      
+      cout << "AA.n= "<< AA.n << " AA.m=" <<  AA.m << " AA.nbcoef=" << AA.nbcoef << endl;
+    
+     
+      for(int ii=0; ii < Ncol+1; ii++){
+	ia[ii] = ia[ii]+1;
+      }
+      assert( ia[Ncol]-1 == AA.nbcoef );
+      for(int ii=0; ii < ia[Ncol]-1; ii++){
+	ja[ii] = ja[ii]+1; 
+      }
+            
+      MPI_Bcast( &Ncol,   1,    MPI_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast( &Nrow,   1,    MPI_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast( &nnz,    1,    MPI_INT,   0, MPI_COMM_WORLD );
+
+      MPI_Bcast( avals, nnz,    MPI_PASTIX_FLOAT, 0, MPI_COMM_WORLD );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+    }
+    else{
+      MPI_Bcast( &Ncol, 1,        MPI_INT,  0, MPI_COMM_WORLD );
+      MPI_Bcast( &Nrow, 1,        MPI_INT,  0, MPI_COMM_WORLD );
+      MPI_Bcast( &nnz,  1,        MPI_INT,  0, MPI_COMM_WORLD );
+      
+      avals = (pastix_float_t *) malloc( nnz*sizeof(pastix_float_t) );
+      ia = (pastix_int_t *) malloc( (Ncol+1)*sizeof(pastix_int_t) );
+      ja = (pastix_int_t *) malloc( nnz*sizeof(pastix_int_t) );
+
+      MPI_Bcast( avals, nnz,  MPI_PASTIX_FLOAT,   0, MPI_COMM_WORLD );
+      MPI_Bcast(    ia, Ncol+1, MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+      MPI_Bcast(    ja, nnz,    MPI_PASTIX_INT,   0, MPI_COMM_WORLD );
+    }
+
+    perm = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    invp = (pastix_int_t *) malloc(Ncol*sizeof(pastix_int_t));
+    
+    rhs = (pastix_float_t *) malloc(Ncol*sizeof(pastix_float_t));
+    
+    // reading permutation given by the user
+    if(pperm_r) 
+      for(int ii=0; ii < Ncol; ii++)
+	perm[ii] = pperm_r[ii];
+    if(pperm_c)  
+      for(int ii=0; ii < Ncol; ii++)
+	invp[ii] = pperm_c[ii];
+
+      
+    iparm[IPARM_START_TASK] = API_TASK_INIT;
+    iparm[IPARM_END_TASK]   = API_TASK_INIT;
+    iparm[IPARM_SYM] = API_SYM_NO; // Matrix is considered nonsymetric    
+
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm); 
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    fprintf(stdout,"-- FIN INIT PARAMETERS --\n");
+    init_raff = iparm[IPARM_ITERMAX];
+    
+    fflush(stdout);
+    /* Passage en mode verbose */
+    
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    if( (param_int==NULL) && data_option.empty() ){
+      iparm[IPARM_MATRIX_VERIFICATION] = API_YES;
+      iparm[IPARM_REFINEMENT] = API_RAF_GMRES;
+      iparm[IPARM_INCOMPLETE] = API_NO;
+    }
+
+    if( (param_double==NULL) && data_option.empty()){
+      dparm[DPARM_EPSILON_REFINEMENT] = 1e-12;
+      dparm[DPARM_EPSILON_MAGN_CTRL] = 1e-32;
+    }
+
+//    cscd_checksym(Ncol, ia, ja, loc2glob, MPI_COMM_WORLD);
+    
+//     if (iparm[IPARM_SYM]==API_SYM_YES)
+//       {
+// 	/* Symetric problem */
+// 	/* Build non oriented graph */
+// 	/* build non symmetric csc from symmetric csc */
+// 	/*maillage global*/
+// 	INT *tmpia;
+// 	INT *tmpja;
+// 	INT  tmpn;
+	
+// 	cscd_symgraph_int(*n2,   *col2,  *row2 , NULL,
+// 			  &tmpn, &tmpia, &tmpja, NULL,
+// 			  *loc2glob2, pastix_comm, API_YES);
+	
+// 	memFree_null(*col2);
+// 	*col2 = tmpia;
+// 	memFree_null(*row2);
+// 	*row2 = tmpja;
+// 	*n2   = tmpn;
+//       }
+    
+
+    SYM = AA.symetrique; 
+    cout << "SYM = "<< SYM << endl;
+    // SYMETRIQUE
+    if( SYM == 1 ){
+      iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    
+    /* Scotch */
+    fprintf(stdout,"-- Scotch --\n");
+    fflush(stdout);
+    iparm[IPARM_START_TASK] = API_TASK_ORDERING;
+    iparm[IPARM_END_TASK]   = API_TASK_ORDERING; 
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl;  
+    iparm[IPARM_SYM] = API_SYM_NO;
+    /* Fax */
+    fprintf(stdout,"-- Fax --\n");
+    iparm[IPARM_START_TASK] = API_TASK_SYMBFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_SYMBFACT;
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    /* Blend */
+    fprintf(stdout,"-- Blend --\n");
+    iparm[IPARM_START_TASK] = API_TASK_ANALYSE;
+    iparm[IPARM_END_TASK]   = API_TASK_ANALYSE;
+    if( SYM == 1 ){
+      //iparm[IPARM_SYM] = API_SYM_YES;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LDLT;
+    }
+    if( SYM == 0 ){
+      //iparm[IPARM_SYM] = API_SYM_NO;
+      iparm[IPARM_FACTORIZATION] = API_FACT_LU;
+    }
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+   
+    /* Factorisation */
+    iparm[IPARM_START_TASK] = API_TASK_NUMFACT;
+    iparm[IPARM_END_TASK]   = API_TASK_NUMFACT;
+    gettimeofday(&tv1, NULL);
+    fprintf(stdout,"-- SOPALIN --\n");
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+       cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call factorization : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+    
+   
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+    
+    if(verbosity)
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000);
+	printf("=====================================================\n");
+	cout << " pastix : time factorization  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+  }
+  void Solver(const MatriceMorse<double> &AA,KN_<double> &x,const KN_<double> &b) const  {
+  
+    struct timeval  tv1, tv2;
+    // time variables
+    long int starttime,finishtime;
+    long int timeused;
+    if(verbosity) starttime = clock();
+    
+
+    // index for pastix    
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]+1;
+    assert( ia[Ncol]-1 == AA.nbcoef );
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]+1;
+    
+    
+    // give value of the second member
+    for(int ii=0; ii < Ncol; ii++){
+      rhs[ii] = b[ii];  
+    }
+    
+    
+
+    //fprintf(stdout,"SOLVE STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    
+    /* updo */
+    iparm[IPARM_START_TASK] = API_TASK_SOLVE;
+    iparm[IPARM_END_TASK]   = API_TASK_SOLVE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call updown : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));    
+    
+    //if(verbosity > 1)
+    //  for(int jj=0; jj < Ncol; jj++)
+    //cout << "rhs["<< jj << "]=" << rhs[jj] << endl;
+    
+    
+    //fprintf(stdout,"RAFF STEP %ld (in FACTORIZE STEP %ld)\n",(long)ii,(long)jj);
+    /* raff */
+    
+    
+    iparm[IPARM_START_TASK] = API_TASK_REFINE;
+    iparm[IPARM_END_TASK]   = API_TASK_REFINE;
+    iparm[IPARM_RHS_MAKING] = API_RHS_B;
+    iparm[IPARM_ITERMAX]    = init_raff;
+    gettimeofday(&tv1, NULL);
+    if(mpi_flag == 0)
+      pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+    else
+      cerr << "error :: mpi_flag = 0 for calling pastix" << endl; 
+    gettimeofday(&tv2, NULL);
+    fprintf(stdout,"Time to call refinement : %ld usec\n", 
+	    (long)((tv2.tv_sec  - tv1.tv_sec ) * 1000000 + 
+		   tv2.tv_usec - tv1.tv_usec));
+
+    
+    for(int ii=0; ii < Ncol; ii++)
+      x[ii] = rhs[ii];
+       
+    // index for freefem
+    assert( ia[Ncol]-1 == AA.nbcoef );
+    for(int ii=0; ii < ia[Ncol]-1; ii++)
+      ja[ii] = ja[ii]-1;
+    for(int ii=0; ii < Ncol+1; ii++)
+      ia[ii] = ia[ii]-1;
+
+    if(verbosity)
+      if(myid==0){
+	finishtime = clock();
+	timeused= (finishtime-starttime)/(1000 );
+	printf("=====================================================\n");
+	cout << " pastix : time solve  :: " << timeused << " ms" <<endl;
+	printf("=====================================================\n");
+      }
+
+  
+  }
+
+  ~dSolvepastixmpi(){
+    /* mem free */
+    iparm[IPARM_START_TASK] = API_TASK_CLEAN;
+    iparm[IPARM_END_TASK]   = API_TASK_CLEAN;
+    
+    pastix(&pastix_data, MPI_COMM_WORLD, Ncol,ia,ja,avals,perm,invp,rhs,1,iparm,dparm);
+      
+    //if( sizeof(pastix_int_t) != sizeof(int) )
+    //  {
+    memFree_null(ia);
+    memFree_null(ja);
+    //}
+    memFree_null(avals);
+    /* Free mem no longer necessary */
+    memFree_null(perm);
+    memFree_null(invp);
+    memFree_null(rhs);
+    
+  
+    
+  }
+  
+  void addMatMul(const KN_<double> & x, KN_<double> & Ax) const 
+  {  
+    ffassert(x.N()==Ax.N());
+    Ax +=  (const MatriceMorse<double> &) (*this) * x; 
+  }
+
+};
+
+MatriceMorse<double>::VirtualSolver *
+BuildSolverpastix_real_mpi(DCL_ARG_SPARSE_SOLVER(double,A))
+{
+    if(verbosity>9)
+    cout << " BuildSolverpastix_real_mpi<double>" << endl;
+    return new dSolvepastixmpi(*A,ds.strategy,ds.tgv,ds.epsilon,ds.tol_pivot,ds.tol_pivot_sym, ds.data_filename, 
+			       ds.lparams, ds.dparams, ds.perm_r, ds.perm_c);
+}
+
+
+class Init { public:
+    Init();
+};
+
+//  the 2 default sparse solver double and complex
+DefSparseSolver<double>::SparseMatSolver SparseMatSolver_R ; ;
+//DefSparseSolver<Complex>::SparseMatSolver SparseMatSolver_C;
+// the default probleme solver 
+TypeSolveMat::TSolveMat  TypeSolveMatdefaultvalue=TypeSolveMat::defaultvalue;
+
+bool SetDefault()
+{
+    if(verbosity)
+	cout << " SetDefault sparse to default" << endl;
+    DefSparseSolver<double>::solver =SparseMatSolver_R;
+    //DefSparseSolver<Complex>::solver =SparseMatSolver_C;
+    TypeSolveMat::defaultvalue =TypeSolveMat::SparseSolver;
+}
+
+bool Setpastixmpi()
+{
+    if(verbosity)
+	cout << " SetDefault sparse solver to pastixmpi" << endl;
+    DefSparseSolver<double>::solver  =BuildSolverpastix_real_mpi;
+    //DefSparseSolver<Complex>::solver =BuildSolverpastix_real_mpi;    
+    TypeSolveMat::defaultvalue  = TypeSolveMatdefaultvalue;
+}
+
+
+
+Init init;
+Init::Init()
+{ 
+  
+  SparseMatSolver_R= DefSparseSolver<double>::solver;
+  //SparseMatSolver_C= DefSparseSolver<Complex>::solver;
+  
+  if(verbosity>1)
+    cout << "\n Add: pastix,  defaultsolver defaultsolverpastix" << endl;
+  TypeSolveMat::defaultvalue=TypeSolveMat::SparseSolver;
+  DefSparseSolver<double>::solver =BuildSolverpastix_real_mpi;
+  //DefSparseSolver<Complex>::solver =BuildSolverpastix_real_mpi;
+  if(! Global.Find("defaultsolver").NotNull() )
+    Global.Add("defaultsolver","(",new OneOperator0<bool>(SetDefault));
+  Global.Add("realdefaulttopastix","(",new OneOperator0<bool>(Setpastixmpi));
+}
diff --git a/src/solver/wrapper_dotblas.c b/src/solver/wrapper_dotblas.c
new file mode 100644
index 0000000..3ed8aa2
--- /dev/null
+++ b/src/solver/wrapper_dotblas.c
@@ -0,0 +1,30 @@
+typedef void doublecomplex;
+typedef void complex;
+typedef int integer; 
+#include <vecLib/cblas.h> 
+
+/* Double Complex */ void zdotc_(doublecomplex * ret_val, integer *n, 
+	doublecomplex *zx, integer *incx, doublecomplex *zy, integer *incy)
+{
+    cblas_zdotc_sub(*n, zx, *incx, zy, *incx , ret_val);
+} 
+
+/* Double Complex */ void zdotu_(doublecomplex * ret_val, integer *n, 
+	doublecomplex *zx, integer *incx, doublecomplex *zy, integer *incy)
+{
+    cblas_zdotu_sub(*n, zx, *incx, zy, *incx , ret_val);
+    return ;
+} /* zdotu___ */
+
+/* Complex */ void cdotc_(complex * ret_val, integer *n, complex *cx, 
+	integer *incx, complex *cy, integer *incy)
+{
+    cblas_cdotc_sub (*n, cx, *incx, cy, *incx , ret_val);
+} /* cdotc___ */
+
+/* Complex */ void  cdotu_(complex * ret_val, integer *n, complex *cx, 
+	integer *incx, complex *cy, integer *incy)
+{
+  cblas_cdotu_sub(*n, cx, *incx, cy, *incx , ret_val);
+} /* cdotu___ */
+
diff --git a/src/solver/wrapper_dotblas.f b/src/solver/wrapper_dotblas.f
new file mode 100644
index 0000000..87ca4e3
--- /dev/null
+++ b/src/solver/wrapper_dotblas.f
@@ -0,0 +1,42 @@
+c  a compile sans underscore   -fno-underscoring 
+c  gfortran -fno-underscoring  -O3 -c wrapper_dotblas.f
+c -------        
+        double complex function zdotc_(n, zx, incx, zy, incy)
+        double complex zx(*), zy(*), z
+        integer n, incx, incy
+        
+        call cblas_zdotc_sub(%val(n), zx, %val(incx), zy, %val(incy), z)
+c        print*,'cblas_zdotc_sub' 
+        zdotc_ = z
+        return
+        end
+        
+        double complex function zdotu_(n, zx, incx, zy, incy)
+        double complex zx(*), zy(*), z
+        integer n, incx, incy
+        
+        call cblas_zdotu_sub(%val(n), zx, %val(incx), zy, %val(incy), z)
+c        print*,'cblas_zdotu_sub' 
+        zdotu_ = z
+        return
+        end
+        
+        complex function cdotc_(n, cx, incx, cy, incy)
+        complex cx(*), cy(*), c
+        integer n, incx, incy
+        
+        call cblas_cdotc_sub(%val(n), cx, %val(incx), cy, %val(incy), c)
+c        print*,'cblas_cdotc_sub' 
+        cdotc_ = c
+        return
+        end
+        
+        complex function cdotu_(n, cx, incx, cy, incy)
+        complex cx(*), cy(*), c
+        integer n, incx, incy
+        
+        call cblas_cdotu_sub(%val(n), cx, %val(incx), cy, %val(incy), c)
+c        print*,'cblas_cdotu_sub' 
+        cdotu_ = c
+        return
+        end
diff --git a/src/solver/wrapper_dotblas1.c b/src/solver/wrapper_dotblas1.c
new file mode 100644
index 0000000..6176645
--- /dev/null
+++ b/src/solver/wrapper_dotblas1.c
@@ -0,0 +1,117 @@
+/* wrapper_dotblas1.f -- translated by f2c (version 20061008).
+   You must link the resulting object file with libf2c:
+	on Microsoft Windows system, link with libf2c.lib;
+	on Linux or Unix systems, link with .../path/to/libf2c.a -lm
+	or, if you install libf2c.a in a standard place, with -lf2c -lm
+	-- in that order, at the end of the command line, as in
+		cc *.o -lf2c -lm
+	Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
+
+		http://www.netlib.org/f2c/libf2c.zip
+*/
+
+#include "f2c.h"
+
+/*  a compile sans underscore   -fno-underscoring */
+/*  gfortran -fno-underscoring  -O3 -c wrapper_dotblas.f */
+/* ------- */
+/* Double Complex */ VOID zdotc___(doublecomplex * ret_val, integer *n, 
+	doublecomplex *zx, integer *incx, doublecomplex *zy, integer *incy)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static doublecomplex z__;
+    extern /* Subroutine */ int cblas_zdotc_sub__(integer *, doublecomplex *, 
+	    integer *, doublecomplex *, integer *, doublecomplex *);
+
+    /* Parameter adjustments */
+    --zy;
+    --zx;
+
+    /* Function Body */
+    i__1 = *n;
+    i__2 = *incx;
+    i__3 = *incy;
+    cblas_zdotc_sub__(&i__1, &zx[1], &i__2, &zy[1], &i__3, &z__);
+/*        print*,'cblas_zdotc_sub' */
+     ret_val->r = z__.r,  ret_val->i = z__.i;
+    return ;
+} /* zdotc___ */
+
+/* Double Complex */ VOID zdotu___(doublecomplex * ret_val, integer *n, 
+	doublecomplex *zx, integer *incx, doublecomplex *zy, integer *incy)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static doublecomplex z__;
+    extern /* Subroutine */ int cblas_zdotu_sub__(integer *, doublecomplex *, 
+	    integer *, doublecomplex *, integer *, doublecomplex *);
+
+    /* Parameter adjustments */
+    --zy;
+    --zx;
+
+    /* Function Body */
+    i__1 = *n;
+    i__2 = *incx;
+    i__3 = *incy;
+    cblas_zdotu_sub__(&i__1, &zx[1], &i__2, &zy[1], &i__3, &z__);
+/*        print*,'cblas_zdotu_sub' */
+     ret_val->r = z__.r,  ret_val->i = z__.i;
+    return ;
+} /* zdotu___ */
+
+/* Complex */ VOID cdotc___(complex * ret_val, integer *n, complex *cx, 
+	integer *incx, complex *cy, integer *incy)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static complex c__;
+    extern /* Subroutine */ int cblas_cdotc_sub__(integer *, complex *, 
+	    integer *, complex *, integer *, complex *);
+
+    /* Parameter adjustments */
+    --cy;
+    --cx;
+
+    /* Function Body */
+    i__1 = *n;
+    i__2 = *incx;
+    i__3 = *incy;
+    cblas_cdotc_sub__(&i__1, &cx[1], &i__2, &cy[1], &i__3, &c__);
+/*        print*,'cblas_cdotc_sub' */
+     ret_val->r = c__.r,  ret_val->i = c__.i;
+    return ;
+} /* cdotc___ */
+
+/* Complex */ VOID cdotu___(complex * ret_val, integer *n, complex *cx, 
+	integer *incx, complex *cy, integer *incy)
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static complex c__;
+    extern /* Subroutine */ int cblas_cdotu_sub__(integer *, complex *, 
+	    integer *, complex *, integer *, complex *);
+
+    /* Parameter adjustments */
+    --cy;
+    --cx;
+
+    /* Function Body */
+    i__1 = *n;
+    i__2 = *incx;
+    i__3 = *incy;
+    cblas_cdotu_sub__(&i__1, &cx[1], &i__2, &cy[1], &i__3, &c__);
+/*        print*,'cblas_cdotu_sub' */
+     ret_val->r = c__.r,  ret_val->i = c__.i;
+    return ;
+} /* cdotu___ */
+
diff --git a/src/solver/wrapper_dotblas1.f b/src/solver/wrapper_dotblas1.f
new file mode 100644
index 0000000..5d47889
--- /dev/null
+++ b/src/solver/wrapper_dotblas1.f
@@ -0,0 +1,42 @@
+c  a compile sans underscore   -fno-underscoring 
+c  gfortran -fno-underscoring  -O3 -c wrapper_dotblas.f
+c -------        
+        double complex function zdotc_(n, zx, incx, zy, incy)
+        double complex zx(*), zy(*), z
+        integer n, incx, incy
+        
+        call cblas_zdotc_sub((n), zx, (incx), zy, (incy), z)
+c        print*,'cblas_zdotc_sub' 
+        zdotc_ = z
+        return
+        end
+        
+        double complex function zdotu_(n, zx, incx, zy, incy)
+        double complex zx(*), zy(*), z
+        integer n, incx, incy
+        
+        call cblas_zdotu_sub((n), zx, (incx), zy, (incy), z)
+c        print*,'cblas_zdotu_sub' 
+        zdotu_ = z
+        return
+        end
+        
+        complex function cdotc_(n, cx, incx, cy, incy)
+        complex cx(*), cy(*), c
+        integer n, incx, incy
+        
+        call cblas_cdotc_sub((n), cx, (incx), cy, (incy), c)
+c        print*,'cblas_cdotc_sub' 
+        cdotc_ = c
+        return
+        end
+        
+        complex function cdotu_(n, cx, incx, cy, incy)
+        complex cx(*), cy(*), c
+        integer n, incx, incy
+        
+        call cblas_cdotu_sub((n), cx, (incx), cy, (incy), c)
+c        print*,'cblas_cdotu_sub' 
+        cdotu_ = c
+        return
+        end
diff --git a/test-driver b/test-driver
new file mode 100755
index 0000000..d306056
--- /dev/null
+++ b/test-driver
@@ -0,0 +1,139 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2013-07-13.22; # UTC
+
+# Copyright (C) 2011-2013 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+              [--expect-failure={yes|no}] [--color-tests={yes|no}]
+              [--enable-hard-errors={yes|no}] [--]
+              TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+   *) break;;
+  esac
+  shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file"  = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file"  = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+  usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+  usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='' # Red.
+  grn='' # Green.
+  lgn='' # Light green.
+  blu='' # Blue.
+  mgn='' # Magenta.
+  std=''     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  estatus=1
+fi
+
+case $estatus:$expect_failure in
+  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/test-driver-ff b/test-driver-ff
new file mode 100755
index 0000000..e025a4d
--- /dev/null
+++ b/test-driver-ff
@@ -0,0 +1,135 @@
+#!/bin/sh
+# test-driver-ff from test-driver - basic testsuite driver script.
+# modif F. Hecht UPMC. 
+
+scriptversion=2013-06-27.18; # UTC
+
+# Copyright (C) 2011-2013 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver-ff --test-name=NAME --log-file=PATH --trs-file=PATH
+              [--expect-failure={yes|no}] [--color-tests={yes|no}]
+              [--enable-hard-errors={yes|no}] [--] TEST-SCRIPT
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+# TODO: better error handling in option parsing (in particular, ensure
+# TODO: $log_file, $trs_file and $test_name are defined).
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+  esac
+  shift
+done
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='' # Red.
+  grn='' # Green.
+  lgn='' # Light green.
+  blu='' # Blue.
+  mgn='' # Magenta.
+  std=''     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+if test "${SKIP:-no}" = yes; then
+echo SKIP ${TEST_FFPP} ${FLAGS_FFPP}  "$@" >$log_file 2>&1
+estatus=77
+else
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+${TEST_FFPP} ${FLAGS_FFPP}  "$@" >$log_file 2>&1
+
+estatus=$?
+fi
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  estatus=1
+fi
+
+case $estatus:$expect_failure in
+  0:yes) col=$grn res=PASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/uninstall-ff++ b/uninstall-ff++
new file mode 100755
index 0000000..94d24b8
--- /dev/null
+++ b/uninstall-ff++
@@ -0,0 +1,18 @@
+echo rm /usr/local/bin/FreeFem++		/usr/local/bin/bamg		/usr/local/bin/ff-mpirun
+echo rm /usr/local/bin/FreeFem++-CoCoa	/usr/local/bin/cvmsh2			/usr/local/bin/ff-pkg-download
+echo rm /usr/local/bin/FreeFem++-mpi	/usr/local/bin/ff-c++				/usr/local/bin/ffglut
+echo rm /usr/local/bin/FreeFem++-nw	/usr/local/bin/ff-get-dep			/usr/local/bin/ffmedit
+echo rm -rf /usr/local/share/freefem++
+echo rm -rf /usr/local/lib/ff++/
+if [ -d /Applications/FreeFem++.app ]; then
+echo rm -rf /Applications/FreeFem++.app
+fi
+rm /usr/local/bin/FreeFem++		/usr/local/bin/bamg		/usr/local/bin/ff-mpirun
+rm /usr/local/bin/FreeFem++-CoCoa	/usr/local/bin/cvmsh2			/usr/local/bin/ff-pkg-download
+rm /usr/local/bin/FreeFem++-mpi	/usr/local/bin/ff-c++				/usr/local/bin/ffglut
+rm /usr/local/bin/FreeFem++-nw	/usr/local/bin/ff-get-dep			/usr/local/bin/ffmedit
+rm -rf /usr/local/share/freefem++
+rm -rf /usr/local/lib/ff++/
+if [ -d /Applications/FreeFem++.app ]; then
+rm -rf /Applications/FreeFem++.app
+fi
diff --git a/ylwrap b/ylwrap
new file mode 100755
index 0000000..5ea68e4
--- /dev/null
+++ b/ylwrap
@@ -0,0 +1,143 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+# Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey at cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Usage:
+#     ylwrap INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+# * INPUT is the input file
+# * OUTPUT is file PROG generates
+# * DESIRED is file we actually want
+# * PROGRAM is program to run
+# * ARGS are passed to PROG
+# Any number of OUTPUT,DESIRED pairs may be used.
+
+# The input.
+input="$1"
+shift
+case "$input" in
+ [\\/]* | ?:[\\/]*)
+    # Absolute path; do nothing.
+    ;;
+ *)
+    # Relative path.  Make it absolute.
+    input="`pwd`/$input"
+    ;;
+esac
+
+# The directory holding the input.
+input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+# Quote $INPUT_DIR so we can use it in a regexp.
+# FIXME: really we should care about more than `.' and `\'.
+input_rx=`echo "$input_dir" | sed -e 's,\\\\,\\\\\\\\,g' -e 's,\\.,\\\\.,g'`
+
+echo "got $input_rx"
+
+pairlist=
+while test "$#" -ne 0; do
+   if test "$1" = "--"; then
+      shift
+      break
+   fi
+   pairlist="$pairlist $1"
+   shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+ [\\/]* | ?:[\\/]*) ;;
+ *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines.  But that might take us over the 14-char limit.
+dirname=ylwrap$$
+trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+$prog ${1+"$@"} "$input"
+status=$?
+
+if test $status -eq 0; then
+   set X $pairlist
+   shift
+   first=yes
+   # Since DOS filename conventions don't allow two dots,
+   # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+   # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+   y_tab_nodot="no"
+   if test -f y_tab.c || test -f y_tab.h; then
+      y_tab_nodot="yes"
+   fi
+
+   while test "$#" -ne 0; do
+      from="$1"
+      # Handle y_tab.c and y_tab.h output by DOS
+      if test $y_tab_nodot = "yes"; then
+	 if test $from = "y.tab.c"; then
+	    from="y_tab.c"
+	 else
+	    if test $from = "y.tab.h"; then
+	       from="y_tab.h"
+	    fi
+	 fi
+      fi
+      if test -f "$from"; then
+         # If $2 is an absolute path name, then just use that,
+         # otherwise prepend `../'.
+         case "$2" in
+	   [\\/]* | ?:[\\/]*) target="$2";;
+	   *) target="../$2";;
+	 esac
+
+	 # Edit out `#line' or `#' directives.  We don't want the
+	 # resulting debug information to point at an absolute srcdir;
+	 # it is better for it to just mention the .y file with no
+	 # path.
+	 sed -e "/^#/ s,$input_rx,," "$from" > "$target" || status=$?
+      else
+	 # A missing file is only an error for the first file.  This
+	 # is a blatant hack to let us support using "yacc -d".  If -d
+	 # is not specified, we don't want an error when the header
+	 # file is "missing".
+	 if test $first = yes; then
+	    status=1
+	 fi
+      fi
+      shift
+      shift
+      first=no
+   done
+else
+   status=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $status

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/freefempp.git



More information about the debian-science-commits mailing list